major refactoring of almost all files

This commit is contained in:
envoyr
2022-04-28 20:48:00 +02:00
parent a2e95b960f
commit 4f4c71d79b
285 changed files with 21716 additions and 18766 deletions

View File

@@ -1,27 +1,35 @@
<?php
namespace Froxlor\Cron;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Michael Kaufmann <mkaufmann@nutime.de>
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
* 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.
*
* @since 0.10.0
* 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;
use Froxlor\Database\Database;
use Froxlor\FileDir;
use Froxlor\Froxlor;
use Froxlor\Settings;
use PDO;
class CronConfig
{
@@ -33,7 +41,6 @@ class CronConfig
*/
public static function checkCrondConfigurationFile()
{
// check for task
Database::query("
SELECT * FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = '99'
@@ -42,9 +49,8 @@ class CronConfig
// is there a task for re-generating the cron.d-file?
if ($num_results > 0) {
// get all crons and their intervals
if (\Froxlor\FileDir::isFreeBSD()) {
if (FileDir::isFreeBSD()) {
// FreeBSD does not need a header as we are writing directly to the crontab
$cronfile = "\n";
} else {
@@ -67,9 +73,9 @@ class CronConfig
$hour_delay = 0;
$day_delay = 5;
$month_delay = 7;
while ($row_cronentry = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
while ($row_cronentry = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
// create cron.d-entry
$matches = array();
$matches = [];
if (preg_match("/(\d+) (MINUTE|HOUR|DAY|WEEK|MONTH)/", $row_cronentry['interval'], $matches)) {
if ($matches[1] == 1) {
$minvalue = "*";
@@ -104,17 +110,17 @@ class CronConfig
}
// create entry-line
$cronfile .= "root " . $binpath . " " . \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . "/scripts/froxlor_master_cronjob.php") . " --" . $row_cronentry['cronfile'] . " 1> /dev/null\n";
$cronfile .= "root " . $binpath . " " . FileDir::makeCorrectFile(Froxlor::getInstallDir() . "/scripts/froxlor_master_cronjob.php") . " --" . $row_cronentry['cronfile'] . " 1> /dev/null\n";
}
}
// php sessionclean if enabled
if ((int) Settings::Get('phpfpm.enabled') == 1) {
if ((int)Settings::Get('phpfpm.enabled') == 1) {
$cronfile .= "# Look for and purge old sessions every 30 minutes" . PHP_EOL;
$cronfile .= "09,39 * * * * root " . $binpath . " " . \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . "/bin/froxlor-cli") . " froxlor:php-sessionclean 1> /dev/null" . PHP_EOL;
$cronfile .= "09,39 * * * * root " . $binpath . " " . FileDir::makeCorrectFile(Froxlor::getInstallDir() . "/bin/froxlor-cli") . " froxlor:php-sessionclean 1> /dev/null" . PHP_EOL;
}
if (\Froxlor\FileDir::isFreeBSD()) {
if (FileDir::isFreeBSD()) {
// FreeBSD handles the cron-stuff in another way. We need to directly
// write to the crontab file as there is not cron.d/froxlor file
// (settings for system.cronconfig should be set correctly of course)
@@ -153,7 +159,7 @@ class CronConfig
Database::query("DELETE FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = '99'");
// run reload command
\Froxlor\FileDir::safe_exec(escapeshellcmd(Settings::Get('system.crondreload')));
FileDir::safe_exec(escapeshellcmd(Settings::Get('system.crondreload')));
}
return true;
}

View File

@@ -1,22 +1,38 @@
<?php
namespace Froxlor\Cron\Dns;
use Froxlor\Settings;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2016 the Froxlor Team (see authors).
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2016-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
* 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\Dns;
use Froxlor\Dns\Dns;
use Froxlor\FileDir;
use Froxlor\FroxlorLogger;
use Froxlor\Settings;
use Froxlor\Validate\Validate;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
class Bind extends DnsBase
{
@@ -25,21 +41,21 @@ class Bind extends DnsBase
public function writeConfigs()
{
// tell the world what we are doing
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Task4 started - Rebuilding froxlor_bind.conf');
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Task4 started - Rebuilding froxlor_bind.conf');
// clean up
$this->cleanZonefiles();
// check for subfolder in bind-config-directory
if (! file_exists(\Froxlor\FileDir::makeCorrectDir(Settings::Get('system.bindconf_directory') . '/domains/'))) {
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'mkdir ' . escapeshellarg(\Froxlor\FileDir::makeCorrectDir(Settings::Get('system.bindconf_directory') . '/domains/')));
\Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg(\Froxlor\FileDir::makeCorrectDir(Settings::Get('system.bindconf_directory') . '/domains/')));
if (!file_exists(FileDir::makeCorrectDir(Settings::Get('system.bindconf_directory') . '/domains/'))) {
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'mkdir ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('system.bindconf_directory') . '/domains/')));
FileDir::safe_exec('mkdir -p ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('system.bindconf_directory') . '/domains/')));
}
$domains = $this->getDomainList();
if (empty($domains)) {
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'No domains found for nameserver-config, skipping...');
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'No domains found for nameserver-config, skipping...');
return;
}
@@ -53,12 +69,33 @@ class Bind extends DnsBase
$this->walkDomainList($domain, $domains);
}
$bindconf_file_handler = fopen(\Froxlor\FileDir::makeCorrectFile(Settings::Get('system.bindconf_directory') . '/froxlor_bind.conf'), 'w');
$bindconf_file_handler = fopen(FileDir::makeCorrectFile(Settings::Get('system.bindconf_directory') . '/froxlor_bind.conf'), 'w');
fwrite($bindconf_file_handler, $this->bindconf_file);
fclose($bindconf_file_handler);
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'froxlor_bind.conf written');
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'froxlor_bind.conf written');
$this->reloadDaemon();
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Task4 finished');
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Task4 finished');
}
private function cleanZonefiles()
{
$config_dir = FileDir::makeCorrectFile(Settings::Get('system.bindconf_directory') . '/domains/');
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Cleaning dns zone files from ' . $config_dir);
// check directory
if (@is_dir($config_dir)) {
// create directory iterator
$its = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($config_dir));
// iterate through all subdirs, look for zone files and delete them
foreach ($its as $it) {
if ($it->isFile()) {
// remove file
FileDir::safe_exec('rm -f ' . escapeshellarg(FileDir::makeCorrectFile($its->getPathname())));
}
}
}
}
private function walkDomainList($domain, $domains)
@@ -78,31 +115,31 @@ class Bind extends DnsBase
}
if ($domain['ismainbutsubto'] == 0) {
$zoneContent = (string) \Froxlor\Dns\Dns::createDomainZone(($domain['id'] == 'none') ? $domain : $domain['id'], $isFroxlorHostname);
$zoneContent = (string)Dns::createDomainZone(($domain['id'] == 'none') ? $domain : $domain['id'], $isFroxlorHostname);
$domain['zonefile'] = 'domains/' . $domain['domain'] . '.zone';
$zonefile_name = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.bindconf_directory') . '/' . $domain['zonefile']);
$zonefile_name = FileDir::makeCorrectFile(Settings::Get('system.bindconf_directory') . '/' . $domain['zonefile']);
$zonefile_handler = fopen($zonefile_name, 'w');
fwrite($zonefile_handler, $zoneContent . $subzones);
fclose($zonefile_handler);
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, '`' . $zonefile_name . '` written');
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, '`' . $zonefile_name . '` written');
$this->bindconf_file .= $this->generateDomainConfig($domain);
} else {
return (string) \Froxlor\Dns\Dns::createDomainZone(($domain['id'] == 'none') ? $domain : $domain['id'], $isFroxlorHostname, true);
return (string)Dns::createDomainZone(($domain['id'] == 'none') ? $domain : $domain['id'], $isFroxlorHostname, true);
}
} else {
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Added zonefile ' . $domain['zonefile'] . ' for domain ' . $domain['domain'] . ' - Note that you will also have to handle ALL records for ALL subdomains.');
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Added zonefile ' . $domain['zonefile'] . ' for domain ' . $domain['domain'] . ' - Note that you will also have to handle ALL records for ALL subdomains.');
$this->bindconf_file .= $this->generateDomainConfig($domain);
}
}
private function generateDomainConfig($domain = array())
private function generateDomainConfig($domain = [])
{
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'Generating dns config for ' . $domain['domain']);
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'Generating dns config for ' . $domain['domain']);
$bindconf_file = '# Domain ID: ' . $domain['id'] . ' - CustomerID: ' . $domain['customerid'] . ' - CustomerLogin: ' . $domain['loginname'] . "\n";
$bindconf_file .= 'zone "' . $domain['domain'] . '" in {' . "\n";
$bindconf_file .= ' type master;' . "\n";
$bindconf_file .= ' file "' . \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.bindconf_directory') . '/' . $domain['zonefile']) . '";' . "\n";
$bindconf_file .= ' file "' . FileDir::makeCorrectFile(Settings::Get('system.bindconf_directory') . '/' . $domain['zonefile']) . '";' . "\n";
$bindconf_file .= ' allow-query { any; };' . "\n";
if (count($this->ns) > 0 || count($this->axfr) > 0) {
@@ -112,7 +149,7 @@ class Bind extends DnsBase
if (count($this->ns) > 0) {
foreach ($this->ns as $ns) {
foreach ($ns["ips"] as $ip) {
$ip = \Froxlor\Validate\Validate::validate_ip2($ip, true, 'invalidip', true, true, true);
$ip = Validate::validate_ip2($ip, true, 'invalidip', true, true, true);
if ($ip) {
$bindconf_file .= ' ' . $ip . ";\n";
}
@@ -134,26 +171,4 @@ class Bind extends DnsBase
return $bindconf_file;
}
private function cleanZonefiles()
{
$config_dir = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.bindconf_directory') . '/domains/');
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Cleaning dns zone files from ' . $config_dir);
// check directory
if (@is_dir($config_dir)) {
// create directory iterator
$its = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($config_dir));
// iterate through all subdirs, look for zone files and delete them
foreach ($its as $it) {
if ($it->isFile()) {
// remove file
\Froxlor\FileDir::safe_exec('rm -f ' . escapeshellarg(\Froxlor\FileDir::makeCorrectFile($its->getPathname())));
}
}
}
}
}

View File

@@ -1,24 +1,37 @@
<?php
namespace Froxlor\Cron\Dns;
use Froxlor\Database\Database;
use Froxlor\Settings;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2016 the Froxlor Team (see authors).
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2016-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
* 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\Dns;
use Froxlor\Database\Database;
use Froxlor\FileDir;
use Froxlor\FroxlorLogger;
use Froxlor\PhpHelper;
use Froxlor\Settings;
use PDO;
/**
* Class DnsBase
*
@@ -29,13 +42,11 @@ abstract class DnsBase
protected $logger = false;
protected $ns = array();
protected $ns = [];
protected $mx = array();
protected $mx = [];
protected $axfr = array();
abstract public function writeConfigs();
protected $axfr = [];
public function __construct($logger)
{
@@ -48,31 +59,31 @@ abstract class DnsBase
$nameserver = trim($nameserver);
// DNS servers might be multi homed; allow transfer from all ip
// addresses of the DNS server
$nameserver_ips = \Froxlor\PhpHelper::gethostbynamel6($nameserver);
$nameserver_ips = PhpHelper::gethostbynamel6($nameserver);
// append dot to hostname
if (substr($nameserver, - 1, 1) != '.') {
if (substr($nameserver, -1, 1) != '.') {
$nameserver .= '.';
}
// ignore invalid responses
if (! is_array($nameserver_ips)) {
if (!is_array($nameserver_ips)) {
// act like \Froxlor\PhpHelper::gethostbynamel6() and return unmodified hostname on error
$nameserver_ips = array(
$nameserver_ips = [
$nameserver
);
];
} else {
$known_ns_ips = array_merge($known_ns_ips, $nameserver_ips);
}
$this->ns[] = array(
$this->ns[] = [
'hostname' => $nameserver,
'ips' => $nameserver_ips
);
];
}
}
if (Settings::Get('system.mxservers') != '') {
$mxservers = explode(',', Settings::Get('system.mxservers'));
foreach ($mxservers as $mxserver) {
if (substr($mxserver, - 1, 1) != '.') {
if (substr($mxserver, -1, 1) != '.') {
$mxserver .= '.';
}
$this->mx[] = $mxserver;
@@ -90,6 +101,100 @@ abstract class DnsBase
}
}
abstract public function writeConfigs();
public function reloadDaemon()
{
// reload DNS daemon
$cmd = Settings::Get('system.bindreload_command');
$cmdStatus = 1;
FileDir::safe_exec(escapeshellcmd($cmd), $cmdStatus);
if ($cmdStatus === 0) {
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, Settings::Get('system.dns_server') . ' daemon reloaded');
} else {
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, 'Error while running `' . $cmd . '`: exit code (' . $cmdStatus . ') - please check your system logs');
}
}
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()
{
$result_domains_stmt = Database::query("
@@ -117,16 +222,16 @@ abstract class DnsBase
`d`.`domain` ASC
");
$domains = array();
$domains = [];
// don't use fetchall() to be able to set the first column to the domain id and use it later on to set the rows'
// array of direct children without having to search the outer array
while ($domain = $result_domains_stmt->fetch(\PDO::FETCH_ASSOC)) {
while ($domain = $result_domains_stmt->fetch(PDO::FETCH_ASSOC)) {
$domains[$domain["id"]] = $domain;
}
// frolxor-hostname (#1090)
if (Settings::get('system.dns_createhostnameentry') == 1) {
$hostname_arr = array(
$hostname_arr = [
'id' => 'none',
'domain' => Settings::Get('system.hostname'),
'isbinddomain' => '1',
@@ -139,7 +244,7 @@ abstract class DnsBase
'ismainbutsubto' => '0',
'zonefile' => '',
'froxlorhost' => '1'
);
];
$domains['none'] = $hostname_arr;
}
@@ -149,8 +254,8 @@ abstract class DnsBase
// collect domain IDs of direct child domains as arrays in ['children'] column
foreach (array_keys($domains) as $key) {
if (! isset($domains[$key]['children'])) {
$domains[$key]['children'] = array();
if (!isset($domains[$key]['children'])) {
$domains[$key]['children'] = [];
}
if ($domains[$key]['ismainbutsubto'] > 0) {
if (isset($domains[$domains[$key]['ismainbutsubto']])) {
@@ -161,105 +266,12 @@ abstract class DnsBase
}
}
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, str_pad('domId', 9, ' ') . str_pad('domain', 40, ' ') . 'ismainbutsubto ' . str_pad('parent domain', 40, ' ') . "list of child domain ids");
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, str_pad('domId', 9, ' ') . str_pad('domain', 40, ' ') . 'ismainbutsubto ' . str_pad('parent domain', 40, ' ') . "list of child domain ids");
foreach ($domains as $domain) {
$logLine = str_pad($domain['id'], 9, ' ') . str_pad($domain['domain'], 40, ' ') . str_pad($domain['ismainbutsubto'], 15, ' ') . str_pad(((isset($domains[$domain['ismainbutsubto']])) ? $domains[$domain['ismainbutsubto']]['domain'] : '-'), 40, ' ') . join(', ', $domain['children']);
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, $logLine);
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, $logLine);
}
return $domains;
}
public function reloadDaemon()
{
// reload DNS daemon
$cmd = Settings::Get('system.bindreload_command');
$cmdStatus = 1;
\Froxlor\FileDir::safe_exec(escapeshellcmd($cmd), $cmdStatus);
if ($cmdStatus === 0) {
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, Settings::Get('system.dns_server') . ' daemon reloaded');
} else {
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, 'Error while running `' . $cmd . '`: exit code (' . $cmdStatus . ') - please check your system logs');
}
}
public function writeDKIMconfigs()
{
if (Settings::Get('dkim.use_dkim') == '1') {
if (! file_exists(\Froxlor\FileDir::makeCorrectDir(Settings::Get('dkim.dkim_prefix')))) {
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'mkdir -p ' . escapeshellarg(\Froxlor\FileDir::makeCorrectDir(Settings::Get('dkim.dkim_prefix'))));
\Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg(\Froxlor\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 = \Froxlor\FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim' . $domain['dkim_id'] . Settings::Get('dkim.privkeysuffix'));
$pubkey_filename = \Froxlor\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 = \Froxlor\FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim' . $domain['dkim_id'] . Settings::Get('dkim.privkeysuffix'));
\Froxlor\FileDir::safe_exec('openssl genrsa -out ' . escapeshellarg($privkey_filename) . ' ' . Settings::Get('dkim.dkim_keylength'));
$domain['dkim_privkey'] = file_get_contents($privkey_filename);
\Froxlor\FileDir::safe_exec("chmod 0640 " . escapeshellarg($privkey_filename));
$pubkey_filename = \Froxlor\FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim' . $domain['dkim_id'] . '.public');
\Froxlor\FileDir::safe_exec('openssl rsa -in ' . escapeshellarg($privkey_filename) . ' -pubout -outform pem -out ' . escapeshellarg($pubkey_filename));
$domain['dkim_pubkey'] = file_get_contents($pubkey_filename);
\Froxlor\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 = array(
'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);
\Froxlor\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);
\Froxlor\FileDir::safe_exec("chmod 0644 " . escapeshellarg($pubkey_filename));
}
$dkimdomains .= $domain['domain'] . "\n";
$dkimkeys .= "*@" . $domain['domain'] . ":" . $domain['domain'] . ":" . $privkey_filename . "\n";
}
$dkimdomains_filename = \Froxlor\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 = \Froxlor\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);
\Froxlor\FileDir::safe_exec(escapeshellcmd(Settings::Get('dkim.dkimrestart_command')));
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Dkim-milter reloaded');
}
}
}

View File

@@ -1,29 +1,43 @@
<?php
namespace Froxlor\Cron\Dns;
use Froxlor\Settings;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2016 the Froxlor Team (see authors).
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2016-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
* 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\Dns;
use Froxlor\Dns\Dns;
use Froxlor\Dns\DnsZone;
use Froxlor\FroxlorLogger;
use Froxlor\Settings;
use PDO;
class PowerDNS extends DnsBase
{
public function writeConfigs()
{
// tell the world what we are doing
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Task4 started - Refreshing DNS database');
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Task4 started - Refreshing DNS database');
$domains = $this->getDomainList();
@@ -31,7 +45,7 @@ class PowerDNS extends DnsBase
$this->clearZoneTables($domains);
if (empty($domains)) {
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'No domains found for nameserver-config, skipping...');
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'No domains found for nameserver-config, skipping...');
return;
}
@@ -43,15 +57,45 @@ class PowerDNS extends DnsBase
$this->walkDomainList($domain, $domains);
}
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'PowerDNS database updated');
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'PowerDNS database updated');
$this->reloadDaemon();
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Task4 finished');
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Task4 finished');
}
private function clearZoneTables($domains = null)
{
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Cleaning dns zone entries from database');
$pdns_domains_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("SELECT `id`, `name` FROM `domains` WHERE `name` = :domain");
$del_rec_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("DELETE FROM `records` WHERE `domain_id` = :did");
$del_meta_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("DELETE FROM `domainmetadata` WHERE `domain_id` = :did");
$del_dom_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("DELETE FROM `domains` WHERE `id` = :did");
foreach ($domains as $domain) {
$pdns_domains_stmt->execute([
'domain' => $domain['domain']
]);
$pdns_domain = $pdns_domains_stmt->fetch(PDO::FETCH_ASSOC);
if ($pdns_domain && !empty($pdns_domain['id'])) {
$del_rec_stmt->execute([
'did' => $pdns_domain['id']
]);
$del_meta_stmt->execute([
'did' => $pdns_domain['id']
]);
$del_dom_stmt->execute([
'did' => $pdns_domain['id']
]);
}
}
}
private function walkDomainList($domain, $domains)
{
$zoneContent = '';
$subzones = array();
$subzones = [];
foreach ($domain['children'] as $child_domain_id) {
$subzones[] = $this->walkDomainList($domains[$child_domain_id], $domains);
@@ -65,7 +109,7 @@ class PowerDNS extends DnsBase
}
if ($domain['ismainbutsubto'] == 0) {
$zoneContent = \Froxlor\Dns\Dns::createDomainZone(($domain['id'] == 'none') ? $domain : $domain['id'], $isFroxlorHostname);
$zoneContent = Dns::createDomainZone(($domain['id'] == 'none') ? $domain : $domain['id'], $isFroxlorHostname);
if (count($subzones)) {
foreach ($subzones as $subzone) {
$zoneContent->records[] = $subzone;
@@ -74,42 +118,12 @@ class PowerDNS extends DnsBase
$pdnsDomId = $this->insertZone($zoneContent->origin, $zoneContent->serial);
$this->insertRecords($pdnsDomId, $zoneContent->records, $zoneContent->origin);
$this->insertAllowedTransfers($pdnsDomId);
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'DB entries stored for zone `' . $domain['domain'] . '`');
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'DB entries stored for zone `' . $domain['domain'] . '`');
} else {
return \Froxlor\Dns\Dns::createDomainZone(($domain['id'] == 'none') ? $domain : $domain['id'], $isFroxlorHostname, true);
return Dns::createDomainZone(($domain['id'] == 'none') ? $domain : $domain['id'], $isFroxlorHostname, true);
}
} else {
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, 'Custom zonefiles are NOT supported when PowerDNS is selected as DNS daemon (triggered by: ' . $domain['domain'] . ')');
}
}
private function clearZoneTables($domains = null)
{
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Cleaning dns zone entries from database');
$pdns_domains_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("SELECT `id`, `name` FROM `domains` WHERE `name` = :domain");
$del_rec_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("DELETE FROM `records` WHERE `domain_id` = :did");
$del_meta_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("DELETE FROM `domainmetadata` WHERE `domain_id` = :did");
$del_dom_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("DELETE FROM `domains` WHERE `id` = :did");
foreach ($domains as $domain) {
$pdns_domains_stmt->execute(array(
'domain' => $domain['domain']
));
$pdns_domain = $pdns_domains_stmt->fetch(\PDO::FETCH_ASSOC);
if ($pdns_domain && ! empty($pdns_domain['id'])) {
$del_rec_stmt->execute(array(
'did' => $pdns_domain['id']
));
$del_meta_stmt->execute(array(
'did' => $pdns_domain['id']
));
$del_dom_stmt->execute(array(
'did' => $pdns_domain['id']
));
}
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, 'Custom zonefiles are NOT supported when PowerDNS is selected as DNS daemon (triggered by: ' . $domain['domain'] . ')');
}
}
@@ -118,16 +132,16 @@ class PowerDNS extends DnsBase
$ins_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("
INSERT INTO domains set `name` = :domainname, `notified_serial` = :serial, `type` = :type
");
$ins_stmt->execute(array(
$ins_stmt->execute([
'domainname' => $domainname,
'serial' => $serial,
'type' => strtoupper(Settings::Get('system.powerdns_mode'))
));
]);
$lastid = \Froxlor\Dns\PowerDNS::getDB()->lastInsertId();
return $lastid;
}
private function insertRecords($domainid = 0, $records = array(), $origin = "")
private function insertRecords($domainid = 0, $records = [], $origin = "")
{
$ins_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("
INSERT INTO records set
@@ -141,7 +155,7 @@ class PowerDNS extends DnsBase
");
foreach ($records as $record) {
if ($record instanceof \Froxlor\Dns\DnsZone) {
if ($record instanceof DnsZone) {
$this->insertRecords($domainid, $record->records, $record->origin);
continue;
}
@@ -152,14 +166,14 @@ class PowerDNS extends DnsBase
$_record = $record->record . "." . $origin;
}
$ins_data = array(
$ins_data = [
'did' => $domainid,
'rec' => $_record,
'type' => $record->type,
'content' => $record->content,
'ttl' => $record->ttl,
'prio' => $record->priority
);
];
$ins_stmt->execute($ins_data);
}
}
@@ -170,9 +184,9 @@ class PowerDNS extends DnsBase
INSERT INTO domainmetadata set `domain_id` = :did, `kind` = 'ALLOW-AXFR-FROM', `content` = :value
");
$ins_data = array(
$ins_data = [
'did' => $domainid
);
];
if (count($this->ns) > 0 || count($this->axfr) > 0) {
// put nameservers in allow-transfer

View File

@@ -1,32 +1,38 @@
<?php
namespace Froxlor\Cron;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Michael Kaufmann <mkaufmann@nutime.de>
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
* @since 0.10.0
*
* 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;
abstract class FroxlorCron
{
abstract public static function run();
protected static $cronlog = null;
protected static $lockfile = null;
abstract public static function run();
public static function getLockfile()
{
return static::$lockfile;

File diff suppressed because it is too large Load Diff

View File

@@ -1,45 +1,124 @@
<?php
namespace Froxlor\Cron\Http;
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\Cron\Http\Php\PhpInterface;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2003-2009 the SysCP Team (see authors).
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Florian Lippert <flo@syscp.org> (2003-2009)
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
* 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\Http;
use Froxlor\Cron\Http\Php\PhpInterface;
use Froxlor\Customer\Customer;
use Froxlor\Database\Database;
use Froxlor\FileDir;
use Froxlor\Froxlor;
use Froxlor\Http\Directory;
use Froxlor\Settings;
/**
* @author Florian Lippert <flo@syscp.org> (2003-2009)
* @author Froxlor team <team@froxlor.org> (2010-)
*/
class ApacheFcgi extends Apache
{
public function createOwnVhostStarter()
{
if (Settings::Get('system.mod_fcgid_ownvhost') == '1' || (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.enabled_ownvhost') == '1')) {
$mypath = Froxlor::getInstallDir();
if (Settings::Get('system.mod_fcgid_ownvhost') == '1') {
$user = Settings::Get('system.mod_fcgid_httpuser');
$group = Settings::Get('system.mod_fcgid_httpgroup');
} elseif (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.enabled_ownvhost') == '1') {
$user = Settings::Get('phpfpm.vhost_httpuser');
$group = Settings::Get('phpfpm.vhost_httpgroup');
// get fpm config
$fpm_sel_stmt = Database::prepare("
SELECT f.id FROM `" . TABLE_PANEL_FPMDAEMONS . "` f
LEFT JOIN `" . TABLE_PANEL_PHPCONFIGS . "` p ON p.fpmsettingid = f.id
WHERE p.id = :phpconfigid
");
$fpm_config = Database::pexecute_first($fpm_sel_stmt, [
'phpconfigid' => Settings::Get('phpfpm.vhost_defaultini')
]);
}
$domain = [
'id' => 'none',
'domain' => Settings::Get('system.hostname'),
'adminid' => 1, /* first admin-user (superadmin) */
'mod_fcgid_starter' => -1,
'mod_fcgid_maxrequests' => -1,
'guid' => $user,
'openbasedir' => 0,
'email' => Settings::Get('panel.adminmail'),
'loginname' => 'froxlor.panel',
'documentroot' => $mypath,
'customerroot' => $mypath,
'fpm_config_id' => isset($fpm_config['id']) ? $fpm_config['id'] : 1
];
// all the files and folders have to belong to the local user
// now because we also use fcgid for our own vhost
FileDir::safe_exec('chown -R ' . $user . ':' . $group . ' ' . escapeshellarg($mypath));
// get php.ini for our own vhost
$php = new PhpInterface($domain);
// get php-config
if (Settings::Get('phpfpm.enabled') == '1') {
// fpm
$phpconfig = $php->getPhpConfig(Settings::Get('phpfpm.vhost_defaultini'));
} else {
// fcgid
$phpconfig = $php->getPhpConfig(Settings::Get('system.mod_fcgid_defaultini_ownvhost'));
}
// create starter-file | config-file
$php->getInterface()->createConfig($phpconfig);
// create php.ini (fpm does nothing here, as it
// defines ini-settings in its pool config)
$php->getInterface()->createIniFile($phpconfig);
}
}
protected function composePhpOptions(&$domain, $ssl_vhost = false)
{
$php_options_text = '';
if ($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1') {
$php = new PhpInterface($domain);
$phpconfig = $php->getPhpConfig((int) $domain['phpsettingid']);
$phpconfig = $php->getPhpConfig((int)$domain['phpsettingid']);
if ((int) Settings::Get('phpfpm.enabled') == 1) {
if ((int)Settings::Get('phpfpm.enabled') == 1) {
$srvName = 'fpm.external';
if ($domain['ssl'] == 1 && $ssl_vhost) {
$srvName = 'ssl-fpm.external';
}
// #1317 - perl is executed via apache and therefore, when using fpm, does not know the user
// which perl is supposed to run as, hence the need for Suexec need
if (\Froxlor\Customer\Customer::customerHasPerlEnabled($domain['customerid'])) {
if (Customer::customerHasPerlEnabled($domain['customerid'])) {
$php_options_text .= ' SuexecUserGroup "' . $domain['loginname'] . '" "' . $domain['loginname'] . '"' . "\n";
}
@@ -54,19 +133,19 @@ class ApacheFcgi extends Apache
$filesmatch .= substr($ext, 1) . '|';
}
// start block, cut off last pipe and close block
$filesmatch = '(' . str_replace(".", "\.", substr($filesmatch, 0, - 1)) . ')';
$filesmatch = '(' . str_replace(".", "\.", substr($filesmatch, 0, -1)) . ')';
$php_options_text .= ' <FilesMatch \.' . $filesmatch . '$>' . "\n";
$php_options_text .= ' <If "-f %{SCRIPT_FILENAME}">' . "\n";
$php_options_text .= ' SetHandler proxy:unix:' . $domain['fpm_socket'] . '|fcgi://localhost' . "\n";
$php_options_text .= ' </If>' . "\n";
$php_options_text .= ' </FilesMatch>' . "\n";
$mypath_dir = new \Froxlor\Http\Directory($domain['documentroot']);
$mypath_dir = new Directory($domain['documentroot']);
// only create the require all granted if there is not active directory-protection
// for this path, as this would be the first require and therefore grant all access
if ($mypath_dir->isUserProtected() == false) {
$php_options_text .= ' <Directory "' . \Froxlor\FileDir::makeCorrectDir($domain['documentroot']) . '">' . "\n";
$php_options_text .= ' <Directory "' . FileDir::makeCorrectDir($domain['documentroot']) . '">' . "\n";
if ($phpconfig['pass_authorizationheader'] == '1') {
$php_options_text .= ' CGIPassAuth On' . "\n";
}
@@ -75,7 +154,7 @@ class ApacheFcgi extends Apache
$php_options_text .= ' </Directory>' . "\n";
} elseif ($phpconfig['pass_authorizationheader'] == '1') {
// allow Pass of Authorization header
$php_options_text .= ' <Directory "' . \Froxlor\FileDir::makeCorrectDir($domain['documentroot']) . '">' . "\n";
$php_options_text .= ' <Directory "' . FileDir::makeCorrectDir($domain['documentroot']) . '">' . "\n";
$php_options_text .= ' CGIPassAuth On' . "\n";
$php_options_text .= ' </Directory>' . "\n";
}
@@ -85,7 +164,7 @@ class ApacheFcgi extends Apache
$addheader = " -pass-header Authorization";
}
$php_options_text .= ' FastCgiExternalServer ' . $php->getInterface()->getAliasConfigDir() . $srvName . ' -socket ' . $domain['fpm_socket'] . ' -idle-timeout ' . $phpconfig['fpm_settings']['idle_timeout'] . $addheader . "\n";
$php_options_text .= ' <Directory "' . \Froxlor\FileDir::makeCorrectDir($domain['documentroot']) . '">' . "\n";
$php_options_text .= ' <Directory "' . FileDir::makeCorrectDir($domain['documentroot']) . '">' . "\n";
$filesmatch = $phpconfig['fpm_settings']['limit_extensions'];
$extensions = explode(" ", $filesmatch);
$filesmatch = "";
@@ -93,7 +172,7 @@ class ApacheFcgi extends Apache
$filesmatch .= substr($ext, 1) . '|';
}
// start block, cut off last pipe and close block
$filesmatch = '(' . str_replace(".", "\.", substr($filesmatch, 0, - 1)) . ')';
$filesmatch = '(' . str_replace(".", "\.", substr($filesmatch, 0, -1)) . ')';
$php_options_text .= ' <FilesMatch \.' . $filesmatch . '$>' . "\n";
$php_options_text .= ' SetHandler php-fastcgi' . "\n";
$php_options_text .= ' Action php-fastcgi /fastcgiphp' . "\n";
@@ -101,7 +180,7 @@ class ApacheFcgi extends Apache
$php_options_text .= ' </FilesMatch>' . "\n";
// >=apache-2.4 enabled?
if (Settings::Get('system.apache24') == '1') {
$mypath_dir = new \Froxlor\Http\Directory($domain['documentroot']);
$mypath_dir = new Directory($domain['documentroot']);
// only create the require all granted if there is not active directory-protection
// for this path, as this would be the first require and therefore grant all access
if ($mypath_dir->isUserProtected() == false) {
@@ -117,12 +196,12 @@ class ApacheFcgi extends Apache
}
} else {
$php_options_text .= ' FcgidIdleTimeout ' . Settings::Get('system.mod_fcgid_idle_timeout') . "\n";
if ((int) Settings::Get('system.mod_fcgid_wrapper') == 0) {
if ((int)Settings::Get('system.mod_fcgid_wrapper') == 0) {
$php_options_text .= ' SuexecUserGroup "' . $domain['loginname'] . '" "' . $domain['loginname'] . '"' . "\n";
$php_options_text .= ' ScriptAlias /php/ ' . $php->getInterface()->getConfigDir() . "\n";
} else {
$php_options_text .= ' SuexecUserGroup "' . $domain['loginname'] . '" "' . $domain['loginname'] . '"' . "\n";
$php_options_text .= ' <Directory "' . \Froxlor\FileDir::makeCorrectDir($domain['documentroot']) . '">' . "\n";
$php_options_text .= ' <Directory "' . FileDir::makeCorrectDir($domain['documentroot']) . '">' . "\n";
$file_extensions = explode(' ', $phpconfig['file_extensions']);
$php_options_text .= ' <FilesMatch "\.(' . implode('|', $file_extensions) . ')$">' . "\n";
$php_options_text .= ' SetHandler fcgid-script' . "\n";
@@ -133,7 +212,7 @@ class ApacheFcgi extends Apache
$php_options_text .= ' </FilesMatch>' . "\n";
// >=apache-2.4 enabled?
if (Settings::Get('system.apache24') == '1') {
$mypath_dir = new \Froxlor\Http\Directory($domain['documentroot']);
$mypath_dir = new Directory($domain['documentroot']);
// only create the require all granted if there is not active directory-protection
// for this path, as this would be the first require and therefore grant all access
if ($mypath_dir->isUserProtected() == false) {
@@ -160,67 +239,4 @@ class ApacheFcgi extends Apache
return $php_options_text;
}
public function createOwnVhostStarter()
{
if (Settings::Get('system.mod_fcgid_ownvhost') == '1' || (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.enabled_ownvhost') == '1')) {
$mypath = \Froxlor\Froxlor::getInstallDir();
if (Settings::Get('system.mod_fcgid_ownvhost') == '1') {
$user = Settings::Get('system.mod_fcgid_httpuser');
$group = Settings::Get('system.mod_fcgid_httpgroup');
} elseif (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.enabled_ownvhost') == '1') {
$user = Settings::Get('phpfpm.vhost_httpuser');
$group = Settings::Get('phpfpm.vhost_httpgroup');
// get fpm config
$fpm_sel_stmt = Database::prepare("
SELECT f.id FROM `" . TABLE_PANEL_FPMDAEMONS . "` f
LEFT JOIN `" . TABLE_PANEL_PHPCONFIGS . "` p ON p.fpmsettingid = f.id
WHERE p.id = :phpconfigid
");
$fpm_config = Database::pexecute_first($fpm_sel_stmt, array(
'phpconfigid' => Settings::Get('phpfpm.vhost_defaultini')
));
}
$domain = array(
'id' => 'none',
'domain' => Settings::Get('system.hostname'),
'adminid' => 1, /* first admin-user (superadmin) */
'mod_fcgid_starter' => - 1,
'mod_fcgid_maxrequests' => - 1,
'guid' => $user,
'openbasedir' => 0,
'email' => Settings::Get('panel.adminmail'),
'loginname' => 'froxlor.panel',
'documentroot' => $mypath,
'customerroot' => $mypath,
'fpm_config_id' => isset($fpm_config['id']) ? $fpm_config['id'] : 1
);
// all the files and folders have to belong to the local user
// now because we also use fcgid for our own vhost
\Froxlor\FileDir::safe_exec('chown -R ' . $user . ':' . $group . ' ' . escapeshellarg($mypath));
// get php.ini for our own vhost
$php = new PhpInterface($domain);
// get php-config
if (Settings::Get('phpfpm.enabled') == '1') {
// fpm
$phpconfig = $php->getPhpConfig(Settings::Get('phpfpm.vhost_defaultini'));
} else {
// fcgid
$phpconfig = $php->getPhpConfig(Settings::Get('system.mod_fcgid_defaultini_ownvhost'));
}
// create starter-file | config-file
$php->getInterface()->createConfig($phpconfig);
// create php.ini (fpm does nothing here, as it
// defines ini-settings in its pool config)
$php->getInterface()->createIniFile($phpconfig);
}
}
}

View File

@@ -1,25 +1,38 @@
<?php
namespace Froxlor\Cron\Http;
use Froxlor\Settings;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Michael Kaufmann <mkaufmann@nutime.de>
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
* @since 0.9.29
*
* 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\Http;
use Froxlor\Database\Database;
use Froxlor\FileDir;
use Froxlor\Froxlor;
use Froxlor\Settings;
use PDO;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
class ConfigIO
{
@@ -32,7 +45,6 @@ class ConfigIO
*/
public function cleanUp()
{
// old error logs
$this->cleanErrLogs();
@@ -57,107 +69,12 @@ class ConfigIO
private function cleanErrLogs()
{
$err_dir = \Froxlor\FileDir::makeCorrectDir(\Froxlor\Froxlor::getInstallDir() . "/logs/");
$err_dir = FileDir::makeCorrectDir(Froxlor::getInstallDir() . "/logs/");
if (@is_dir($err_dir)) {
// now get rid of old stuff
// (but append /*.log so we don't delete the directory)
$err_dir .= '/*.log';
\Froxlor\FileDir::safe_exec('rm -f ' . \Froxlor\FileDir::makeCorrectFile($err_dir));
}
}
/**
* remove customer-specified auto-generated ssl-certificates
* (they are being regenerated)
*
* @return null
*/
private function cleanCustomerSslCerts()
{
/*
* only clean up if we're actually using SSL
*/
if (Settings::Get('system.use_ssl') == '1') {
// get correct directory
$configdir = $this->getFile('system', 'customer_ssl_path');
if ($configdir !== false) {
$configdir = \Froxlor\FileDir::makeCorrectDir($configdir);
if (@is_dir($configdir)) {
// now get rid of old stuff
// (but append /* so we don't delete the directory)
$configdir .= '/*';
\Froxlor\FileDir::safe_exec('rm -f ' . \Froxlor\FileDir::makeCorrectFile($configdir));
}
}
}
}
/**
* remove webserver related configuration files before regeneration
*
* @return null
*/
private function cleanWebserverConfigs()
{
// get directories
$configdirs = array();
$dir = $this->getFile('system', 'apacheconf_vhost');
if ($dir !== false)
$configdirs[] = \Froxlor\FileDir::makeCorrectDir($dir);
$dir = $this->getFile('system', 'apacheconf_diroptions');
if ($dir !== false)
$configdirs[] = \Froxlor\FileDir::makeCorrectDir($dir);
// file pattern
$pattern = "/^([0-9]){2}_(froxlor|syscp)_(.+)\.conf$/";
// check ALL the folders
foreach ($configdirs as $config_dir) {
// check directory
if (@is_dir($config_dir)) {
// create directory iterator
$its = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($config_dir));
// iterate through all subdirs,
// look for vhost/diroption files
// and delete them
foreach ($its as $it) {
if ($it->isFile() && preg_match($pattern, $it->getFilename())) {
// remove file
\Froxlor\FileDir::safe_exec('rm -f ' . escapeshellarg(\Froxlor\FileDir::makeCorrectFile($its->getPathname())));
}
}
}
}
}
/**
* remove htpasswd files before regeneration
*
* @return null
*/
private function cleanHtpasswdFiles()
{
// get correct directory
$configdir = $this->getFile('system', 'apacheconf_htpasswddir');
if ($configdir !== false) {
$configdir = \Froxlor\FileDir::makeCorrectDir($configdir);
if (@is_dir($configdir)) {
// now get rid of old stuff
// (but append /* so we don't delete the directory)
$configdir .= '/*';
\Froxlor\FileDir::safe_exec('rm -f ' . \Froxlor\FileDir::makeCorrectFile($configdir));
}
FileDir::safe_exec('rm -f ' . FileDir::makeCorrectFile($err_dir));
}
}
@@ -173,7 +90,7 @@ class ConfigIO
}
// dhr: cleanout froxlor-generated awstats configs prior to re-creation
$awstatsclean = array();
$awstatsclean = [];
$awstatsclean['header'] = "## GENERATED BY FROXLOR\n";
$awstatsclean['headerold'] = "## GENERATED BY SYSCP\n";
$awstatsclean['path'] = $this->getFile('system', 'awstats_conf');
@@ -187,7 +104,7 @@ class ConfigIO
if ($awstatsclean['path'] !== false && is_dir($awstatsclean['path'])) {
$awstatsclean['dir'] = dir($awstatsclean['path']);
while ($awstatsclean['entry'] = $awstatsclean['dir']->read()) {
$awstatsclean['fullentry'] = \Froxlor\FileDir::makeCorrectFile($awstatsclean['path'] . '/' . $awstatsclean['entry']);
$awstatsclean['fullentry'] = FileDir::makeCorrectFile($awstatsclean['path'] . '/' . $awstatsclean['entry']);
/**
* don't do anything if the file does not exist
*/
@@ -197,7 +114,7 @@ class ConfigIO
fclose($awstatsclean['fh']);
if ($awstatsclean['headerRead'] == $awstatsclean['header'] || $awstatsclean['headerRead'] == $awstatsclean['headerold']) {
$awstats_conf_file = \Froxlor\FileDir::makeCorrectFile($awstatsclean['fullentry']);
$awstats_conf_file = FileDir::makeCorrectFile($awstatsclean['fullentry']);
@unlink($awstats_conf_file);
}
}
@@ -207,6 +124,30 @@ class ConfigIO
// end dhr
}
/**
* returns a file/directory from the settings and checks whether it exists
*
* @param string $group
* settings-group
* @param string $varname
* var-name
* @param boolean $check_exists
* check if the file exists
*
* @return string|boolean complete path including filename if any or false on error
*/
private function getFile($group, $varname, $check_exists = true)
{
// read from settings
$file = Settings::Get($group . '.' . $varname);
// check whether it exists
if ($check_exists && @file_exists($file) == false) {
return false;
}
return $file;
}
/**
* remove fcgid related configuration files before regeneration
*
@@ -221,12 +162,11 @@ class ConfigIO
// get correct directory
$configdir = $this->getFile('system', 'mod_fcgid_configdir');
if ($configdir !== false) {
$configdir = \Froxlor\FileDir::makeCorrectDir($configdir);
$configdir = FileDir::makeCorrectDir($configdir);
if (@is_dir($configdir)) {
// create directory iterator
$its = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($configdir));
$its = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($configdir));
// iterate through all subdirs,
// look for php-fcgi-starter files
@@ -235,14 +175,14 @@ class ConfigIO
foreach ($its as $it) {
if ($it->isFile() && $it->getFilename() == 'php-fcgi-starter') {
// set chattr -i
\Froxlor\FileDir::removeImmutable($its->getPathname());
FileDir::removeImmutable($its->getPathname());
}
}
// now get rid of old stuff
// (but append /* so we don't delete the directory)
$configdir .= '/*';
\Froxlor\FileDir::safe_exec('rm -rf ' . \Froxlor\FileDir::makeCorrectFile($configdir));
FileDir::safe_exec('rm -rf ' . FileDir::makeCorrectFile($configdir));
}
}
}
@@ -259,55 +199,121 @@ class ConfigIO
}
// get all fpm config paths
$fpmconf_sel = \Froxlor\Database\Database::prepare("SELECT config_dir FROM `" . TABLE_PANEL_FPMDAEMONS . "`");
\Froxlor\Database\Database::pexecute($fpmconf_sel);
$fpmconf_paths = $fpmconf_sel->fetchAll(\PDO::FETCH_ASSOC);
$fpmconf_sel = Database::prepare("SELECT config_dir FROM `" . TABLE_PANEL_FPMDAEMONS . "`");
Database::pexecute($fpmconf_sel);
$fpmconf_paths = $fpmconf_sel->fetchAll(PDO::FETCH_ASSOC);
// clean all php-fpm config-dirs
foreach ($fpmconf_paths as $configdir) {
$configdir = \Froxlor\FileDir::makeCorrectDir($configdir['config_dir']);
$configdir = FileDir::makeCorrectDir($configdir['config_dir']);
if (@is_dir($configdir)) {
// now get rid of old stuff
// (but append /*.conf so we don't delete the directory)
$configdir .= '/*.conf';
\Froxlor\FileDir::safe_exec('rm -f ' . \Froxlor\FileDir::makeCorrectFile($configdir));
FileDir::safe_exec('rm -f ' . FileDir::makeCorrectFile($configdir));
} else {
\Froxlor\FileDir::safe_exec('mkdir -p ' . $configdir);
FileDir::safe_exec('mkdir -p ' . $configdir);
}
}
// also remove aliasconfigdir #1273
$aliasconfigdir = $this->getFile('phpfpm', 'aliasconfigdir');
if ($aliasconfigdir !== false) {
$aliasconfigdir = \Froxlor\FileDir::makeCorrectDir($aliasconfigdir);
$aliasconfigdir = FileDir::makeCorrectDir($aliasconfigdir);
if (@is_dir($aliasconfigdir)) {
$aliasconfigdir .= '/*';
\Froxlor\FileDir::safe_exec('rm -rf ' . \Froxlor\FileDir::makeCorrectFile($aliasconfigdir));
FileDir::safe_exec('rm -rf ' . FileDir::makeCorrectFile($aliasconfigdir));
}
}
}
/**
* returns a file/directory from the settings and checks whether it exists
* remove webserver related configuration files before regeneration
*
* @param string $group
* settings-group
* @param string $varname
* var-name
* @param boolean $check_exists
* check if the file exists
*
* @return string|boolean complete path including filename if any or false on error
* @return null
*/
private function getFile($group, $varname, $check_exists = true)
private function cleanWebserverConfigs()
{
// read from settings
$file = Settings::Get($group . '.' . $varname);
// check whether it exists
if ($check_exists && @file_exists($file) == false) {
return false;
// get directories
$configdirs = [];
$dir = $this->getFile('system', 'apacheconf_vhost');
if ($dir !== false) {
$configdirs[] = FileDir::makeCorrectDir($dir);
}
$dir = $this->getFile('system', 'apacheconf_diroptions');
if ($dir !== false) {
$configdirs[] = FileDir::makeCorrectDir($dir);
}
// file pattern
$pattern = "/^([0-9]){2}_(froxlor|syscp)_(.+)\.conf$/";
// check ALL the folders
foreach ($configdirs as $config_dir) {
// check directory
if (@is_dir($config_dir)) {
// create directory iterator
$its = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($config_dir));
// iterate through all subdirs,
// look for vhost/diroption files
// and delete them
foreach ($its as $it) {
if ($it->isFile() && preg_match($pattern, $it->getFilename())) {
// remove file
FileDir::safe_exec('rm -f ' . escapeshellarg(FileDir::makeCorrectFile($its->getPathname())));
}
}
}
}
}
/**
* remove htpasswd files before regeneration
*
* @return null
*/
private function cleanHtpasswdFiles()
{
// get correct directory
$configdir = $this->getFile('system', 'apacheconf_htpasswddir');
if ($configdir !== false) {
$configdir = FileDir::makeCorrectDir($configdir);
if (@is_dir($configdir)) {
// now get rid of old stuff
// (but append /* so we don't delete the directory)
$configdir .= '/*';
FileDir::safe_exec('rm -f ' . FileDir::makeCorrectFile($configdir));
}
}
}
/**
* remove customer-specified auto-generated ssl-certificates
* (they are being regenerated)
*
* @return null
*/
private function cleanCustomerSslCerts()
{
/*
* only clean up if we're actually using SSL
*/
if (Settings::Get('system.use_ssl') == '1') {
// get correct directory
$configdir = $this->getFile('system', 'customer_ssl_path');
if ($configdir !== false) {
$configdir = FileDir::makeCorrectDir($configdir);
if (@is_dir($configdir)) {
// now get rid of old stuff
// (but append /* so we don't delete the directory)
$configdir .= '/*';
FileDir::safe_exec('rm -f ' . FileDir::makeCorrectFile($configdir));
}
}
}
return $file;
}
}

View File

@@ -1,26 +1,35 @@
<?php
namespace Froxlor\Cron\Http;
use Froxlor\Database\Database;
use Froxlor\Settings;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Michael Kaufmann <mkaufmann@nutime.de>
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
* @since 0.9.29
*
* 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\Http;
use Froxlor\Database\Database;
use Froxlor\FileDir;
use Froxlor\FroxlorLogger;
use Froxlor\Settings;
class DomainSSL
{
@@ -31,8 +40,8 @@ class DomainSSL
* Hence the parameter as reference.
*
* @param array $domain
* domain-array as reference so we can set the corresponding array-indices
*
* domain-array as reference so we can set the corresponding array-indices
*
* @return null
*/
public function setDomainSSLFilesArray(array &$domain = null)
@@ -41,35 +50,35 @@ class DomainSSL
$dom_certs_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :domid
");
$dom_certs = Database::pexecute_first($dom_certs_stmt, array(
$dom_certs = Database::pexecute_first($dom_certs_stmt, [
'domid' => $domain['id']
));
]);
if (! is_array($dom_certs) || ! isset($dom_certs['ssl_cert_file']) || $dom_certs['ssl_cert_file'] == '') {
if (!is_array($dom_certs) || !isset($dom_certs['ssl_cert_file']) || $dom_certs['ssl_cert_file'] == '') {
// maybe its parent?
if (isset($domain['parentdomainid']) && $domain['parentdomainid'] != 0) {
$dom_certs = Database::pexecute_first($dom_certs_stmt, array(
$dom_certs = Database::pexecute_first($dom_certs_stmt, [
'domid' => $domain['parentdomainid']
));
]);
}
}
// check if it's an array and if the most important field is set
if (is_array($dom_certs) && isset($dom_certs['ssl_cert_file']) && $dom_certs['ssl_cert_file'] != '') {
// get destination path
$sslcertpath = \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.customer_ssl_path'));
$sslcertpath = FileDir::makeCorrectDir(Settings::Get('system.customer_ssl_path'));
// create path if it does not exist
if (! file_exists($sslcertpath)) {
\Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg($sslcertpath));
if (!file_exists($sslcertpath)) {
FileDir::safe_exec('mkdir -p ' . escapeshellarg($sslcertpath));
}
// make correct files for the certificates
$ssl_files = array(
'ssl_cert_file' => \Froxlor\FileDir::makeCorrectFile($sslcertpath . '/' . $domain['domain'] . '.crt'),
'ssl_key_file' => \Froxlor\FileDir::makeCorrectFile($sslcertpath . '/' . $domain['domain'] . '.key')
);
$ssl_files = [
'ssl_cert_file' => FileDir::makeCorrectFile($sslcertpath . '/' . $domain['domain'] . '.crt'),
'ssl_key_file' => FileDir::makeCorrectFile($sslcertpath . '/' . $domain['domain'] . '.key')
];
if (! $this->validateCertificate($dom_certs)) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, 'Given SSL private key for ' . $domain['domain'] . ' does not seem to match the certificate. Cannot create ssl-directives');
if (!$this->validateCertificate($dom_certs)) {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, 'Given SSL private key for ' . $domain['domain'] . ' does not seem to match the certificate. Cannot create ssl-directives');
return;
}
@@ -84,19 +93,19 @@ class DomainSSL
$ssl_files['ssl_cert_chainfile'] = '';
// set them if they are != empty
if ($dom_certs['ssl_ca_file'] != '') {
$ssl_files['ssl_ca_file'] = \Froxlor\FileDir::makeCorrectFile($sslcertpath . '/' . $domain['domain'] . '_CA.pem');
$ssl_files['ssl_ca_file'] = FileDir::makeCorrectFile($sslcertpath . '/' . $domain['domain'] . '_CA.pem');
}
if ($dom_certs['ssl_cert_chainfile'] != '') {
if (Settings::Get('system.webserver') == 'nginx') {
// put ca.crt in my.crt, as nginx does not support a separate chain file.
$dom_certs['ssl_cert_file'] = trim($dom_certs['ssl_cert_file']) . "\n" . trim($dom_certs['ssl_cert_chainfile']) . "\n";
} else {
$ssl_files['ssl_cert_chainfile'] = \Froxlor\FileDir::makeCorrectFile($sslcertpath . '/' . $domain['domain'] . '_chain.pem');
$ssl_files['ssl_cert_chainfile'] = FileDir::makeCorrectFile($sslcertpath . '/' . $domain['domain'] . '_chain.pem');
}
}
// will only be generated to be used externally, froxlor does not need this
if ($dom_certs['ssl_fullchain_file'] != '') {
$ssl_files['ssl_fullchain_file'] = \Froxlor\FileDir::makeCorrectFile($sslcertpath . '/' . $domain['domain'] . '_fullchain.pem');
$ssl_files['ssl_fullchain_file'] = FileDir::makeCorrectFile($sslcertpath . '/' . $domain['domain'] . '_fullchain.pem');
}
// create them on the filesystem
foreach ($ssl_files as $type => $filename) {
@@ -122,7 +131,7 @@ class DomainSSL
return;
}
private function validateCertificate($dom_certs = array())
private function validateCertificate($dom_certs = [])
{
return openssl_x509_check_private_key($dom_certs['ssl_cert_file'], $dom_certs['ssl_key_file']);
}

View File

@@ -1,25 +1,41 @@
<?php
namespace Froxlor\Cron\Http;
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\Cron\Http\Php\Fpm;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2016 the Froxlor Team (see authors).
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2016-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
* 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\Http;
use Froxlor\Cron\Http\LetsEncrypt\AcmeSh;
use Froxlor\Cron\Http\Php\Fpm;
use Froxlor\Database\Database;
use Froxlor\FileDir;
use Froxlor\Froxlor;
use Froxlor\FroxlorLogger;
use Froxlor\PhpHelper;
use Froxlor\Settings;
use Froxlor\System\Cronjob;
use PDO;
/**
* Class HttpConfigBase
*
@@ -32,44 +48,44 @@ class HttpConfigBase
{
// if Let's Encrypt is activated, run it before regeneration of webserver configfiles
if (Settings::Get('system.leenabled') == 1) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Running Let\'s Encrypt cronjob prior to regenerating webserver config files');
\Froxlor\Cron\Http\LetsEncrypt\AcmeSh::$no_inserttask = true;
\Froxlor\Cron\Http\LetsEncrypt\AcmeSh::run(true);
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Running Let\'s Encrypt cronjob prior to regenerating webserver config files');
AcmeSh::$no_inserttask = true;
AcmeSh::run(true);
// set last run timestamp of cronjob
\Froxlor\System\Cronjob::updateLastRunOfCron('letsencrypt');
Cronjob::updateLastRunOfCron('letsencrypt');
}
}
public function reload()
{
$called_class = get_called_class();
if ((int) Settings::Get('phpfpm.enabled') == 1) {
if ((int)Settings::Get('phpfpm.enabled') == 1) {
// get all start/stop commands
$startstop_sel = Database::prepare("SELECT reload_cmd, config_dir FROM `" . TABLE_PANEL_FPMDAEMONS . "`");
Database::pexecute($startstop_sel);
$restart_cmds = $startstop_sel->fetchAll(\PDO::FETCH_ASSOC);
$restart_cmds = $startstop_sel->fetchAll(PDO::FETCH_ASSOC);
// restart all php-fpm instances
foreach ($restart_cmds as $restart_cmd) {
// check whether the config dir is empty (no domains uses this daemon)
// so we need to create a dummy
$_conffiles = glob(\Froxlor\FileDir::makeCorrectFile($restart_cmd['config_dir'] . "/*.conf"));
$_conffiles = glob(FileDir::makeCorrectFile($restart_cmd['config_dir'] . "/*.conf"));
if ($_conffiles === false || empty($_conffiles)) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, $called_class . '::reload: fpm config directory "' . $restart_cmd['config_dir'] . '" is empty. Creating dummy.');
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, $called_class . '::reload: fpm config directory "' . $restart_cmd['config_dir'] . '" is empty. Creating dummy.');
Fpm::createDummyPool($restart_cmd['config_dir']);
}
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, $called_class . '::reload: running ' . $restart_cmd['reload_cmd']);
\Froxlor\FileDir::safe_exec(escapeshellcmd($restart_cmd['reload_cmd']));
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, $called_class . '::reload: running ' . $restart_cmd['reload_cmd']);
FileDir::safe_exec(escapeshellcmd($restart_cmd['reload_cmd']));
}
}
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, $called_class . '::reload: reloading ' . $called_class);
\Froxlor\FileDir::safe_exec(escapeshellcmd(Settings::Get('system.apachereload_command')));
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, $called_class . '::reload: reloading ' . $called_class);
FileDir::safe_exec(escapeshellcmd(Settings::Get('system.apachereload_command')));
/**
* nginx does not auto-spawn fcgi-processes
*/
if (Settings::Get('system.webserver') == "nginx" && Settings::Get('system.phpreload_command') != '' && (int) Settings::Get('phpfpm.enabled') == 0) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, $called_class . '::reload: restarting php processes');
\Froxlor\FileDir::safe_exec(Settings::Get('system.phpreload_command'));
if (Settings::Get('system.webserver') == "nginx" && Settings::Get('system.phpreload_command') != '' && (int)Settings::Get('phpfpm.enabled') == 0) {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, $called_class . '::reload: restarting php processes');
FileDir::safe_exec(Settings::Get('system.phpreload_command'));
}
}
@@ -87,12 +103,12 @@ class HttpConfigBase
* {DOCROOT} - document root for this domain
*
* @param
* $template
* $template
* @return string
*/
protected function processSpecialConfigTemplate($template, $domain, $ip, $port, $is_ssl_vhost)
{
$templateVars = array(
$templateVars = [
'DOMAIN' => $domain['domain'],
'CUSTOMER' => $domain['loginname'],
'IP' => $ip,
@@ -100,24 +116,24 @@ class HttpConfigBase
'SCHEME' => ($is_ssl_vhost) ? 'https' : 'http',
'DOCROOT' => $domain['documentroot'],
'FPMSOCKET' => ''
);
if ((int) Settings::Get('phpfpm.enabled') == 1 && isset($domain['fpm_socket']) && !empty($domain['fpm_socket'])) {
];
if ((int)Settings::Get('phpfpm.enabled') == 1 && isset($domain['fpm_socket']) && !empty($domain['fpm_socket'])) {
$templateVars['FPMSOCKET'] = $domain['fpm_socket'];
}
return \Froxlor\PhpHelper::replaceVariables($template, $templateVars);
return PhpHelper::replaceVariables($template, $templateVars);
}
protected function getMyPath($ip_port = null)
{
if (! empty($ip_port) && $ip_port['docroot'] == '') {
if (!empty($ip_port) && $ip_port['docroot'] == '') {
if (Settings::Get('system.froxlordirectlyviahostname')) {
$mypath = \Froxlor\FileDir::makeCorrectDir(\Froxlor\Froxlor::getInstallDir());
$mypath = FileDir::makeCorrectDir(Froxlor::getInstallDir());
} else {
$mypath = \Froxlor\FileDir::makeCorrectDir(dirname(\Froxlor\Froxlor::getInstallDir()));
$mypath = FileDir::makeCorrectDir(dirname(Froxlor::getInstallDir()));
}
} else {
// user-defined docroot, #417
$mypath = \Froxlor\FileDir::makeCorrectDir($ip_port['docroot']);
$mypath = FileDir::makeCorrectDir($ip_port['docroot']);
}
return $mypath;
}
@@ -152,7 +168,7 @@ class HttpConfigBase
SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = '0'
");
$froxlor_ssl = Database::pexecute_first($froxlor_ssl_settings_stmt);
if ($froxlor_ssl && ! empty($froxlor_ssl['ssl_cert_file'])) {
if ($froxlor_ssl && !empty($froxlor_ssl['ssl_cert_file'])) {
return true;
}
return false;
@@ -166,7 +182,7 @@ class HttpConfigBase
(`expirationdate` < DATE_ADD(NOW(), INTERVAL 30 DAY) OR `expirationdate` IS NULL)
");
$froxlor_ssl = Database::pexecute_first($froxlor_ssl_settings_stmt);
if ($froxlor_ssl && ! empty($froxlor_ssl['ssl_cert_file'])) {
if ($froxlor_ssl && !empty($froxlor_ssl['ssl_cert_file'])) {
return true;
}
return false;

View File

@@ -1,31 +1,44 @@
<?php
namespace Froxlor\Cron\Http\LetsEncrypt;
use Froxlor\FroxlorLogger;
use Froxlor\Settings;
use Froxlor\Database\Database;
use Froxlor\PhpHelper;
use Froxlor\Domain\Domain;
use Froxlor\FileDir;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2016 the Froxlor Team (see authors).
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Florian Aders <kontakt-froxlor@neteraser.de>
* @author Froxlor team <team@froxlor.org> (2016-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
* @since 0.9.35
*
* 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
*/
class AcmeSh extends \Froxlor\Cron\FroxlorCron
namespace Froxlor\Cron\Http\LetsEncrypt;
use Froxlor\Cron\FroxlorCron;
use Froxlor\Database\Database;
use Froxlor\Domain\Domain;
use Froxlor\FileDir;
use Froxlor\Froxlor;
use Froxlor\FroxlorLogger;
use Froxlor\PhpHelper;
use Froxlor\Settings;
use Froxlor\System\Cronjob;
use Froxlor\Validate\Validate;
use PDO;
use PDOStatement;
class AcmeSh extends FroxlorCron
{
const ACME_PROVIDER = [
@@ -35,25 +48,20 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
'buypass_test' => "https://api.test4.buypass.no/acme/directory",
'zerossl' => "https://acme.zerossl.com/v2/DV90"
];
public static $no_inserttask = false;
private static $apiserver = "";
private static $acmesh = "/root/.acme.sh/acme.sh";
/**
*
* @var \PDOStatement
* @var PDOStatement
*/
private static $updcert_stmt = null;
/**
*
* @var \PDOStatement
* @var PDOStatement
*/
private static $upddom_stmt = null;
public static $no_inserttask = false;
/**
* run the task
*
@@ -63,7 +71,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
public static function run($internal = false)
{
// usually, this is action is called from within the tasks-jobs
if (! defined('CRON_IS_FORCED') && ! defined('CRON_DEBUG_FLAG') && $internal == false) {
if (!defined('CRON_IS_FORCED') && !defined('CRON_DEBUG_FLAG') && $internal == false) {
// Let's Encrypt cronjob is combined with regeneration of webserver configuration files.
// For debugging purposes you can use the --debug switch and the --force switch to run the cron manually.
// check whether we MIGHT need to run although there is no task to regenerate config-files
@@ -71,9 +79,9 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
$issue_domains = self::issueDomains();
$renew_froxlor = self::renewFroxlorVhost();
$renew_domains = self::renewDomains(true);
if ($issue_froxlor || ! empty($issue_domains) || ! empty($renew_froxlor) || $renew_domains) {
if ($issue_froxlor || !empty($issue_domains) || !empty($renew_froxlor) || $renew_domains) {
// insert task to generate certificates and vhost-configs
\Froxlor\System\Cronjob::inserttask(1);
Cronjob::inserttask(1);
}
return 0;
}
@@ -82,8 +90,8 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
self::$apiserver = self::ACME_PROVIDER[Settings::Get('system.letsencryptca')];
// validate acme.sh installation
if (! self::checkInstall()) {
return - 1;
if (!self::checkInstall()) {
return -1;
}
self::checkUpgrade();
@@ -117,11 +125,11 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
// first - generate LE for system-vhost if enabled
if ($issue_froxlor) {
// build row
$certrow = array(
$certrow = [
'loginname' => 'froxlor.panel',
'domain' => Settings::Get('system.hostname'),
'domainid' => 0,
'documentroot' => \Froxlor\Froxlor::getInstallDir(),
'documentroot' => Froxlor::getInstallDir(),
'leprivatekey' => Settings::Get('system.leprivatekey'),
'lepublickey' => Settings::Get('system.lepublickey'),
'leregistered' => Settings::Get('system.leregistered'),
@@ -133,7 +141,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
'ssl_csr_file' => null,
'id' => null,
'wwwserveralias' => 0
);
];
// add to queue
$issue_domains[] = $certrow;
@@ -152,11 +160,11 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
if ($renew_froxlor) {
// build row
$certrow = array(
$certrow = [
'loginname' => 'froxlor.panel',
'domain' => Settings::Get('system.hostname'),
'domainid' => 0,
'documentroot' => \Froxlor\Froxlor::getInstallDir(),
'documentroot' => Froxlor::getInstallDir(),
'leprivatekey' => Settings::Get('system.leprivatekey'),
'lepublickey' => Settings::Get('system.lepublickey'),
'leregistered' => Settings::Get('system.leregistered'),
@@ -168,17 +176,17 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
'ssl_csr_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_csr_file'] : null,
'id' => is_array($renew_froxlor) ? $renew_froxlor['id'] : null,
'wwwserveralias' => 0
);
];
$renew_domains[] = $certrow;
}
foreach ($renew_domains as $domain) {
$cronlog = FroxlorLogger::getInstanceOf(array(
$cronlog = FroxlorLogger::getInstanceOf([
'loginname' => $domain['loginname'],
'adminsession' => 0
));
]);
if (defined('CRON_IS_FORCED') || self::checkFsFilesAreNewer($domain['domain'], $domain['expirationdate'])) {
self::certToDb($domain, $cronlog, array());
self::certToDb($domain, $cronlog, []);
$changedetected = 1;
}
}
@@ -187,7 +195,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
// This is easiest done by just creating a new task ;)
if ($changedetected) {
if (self::$no_inserttask == false) {
\Froxlor\System\Cronjob::inserttask(1);
Cronjob::inserttask(1);
}
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Let's Encrypt certificates have been updated");
} else {
@@ -195,189 +203,6 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
}
}
/**
* issue certificates for a list of domains
*/
private static function runIssueFor($certrows = array())
{
// prepare aliasdomain-check
$aliasdomains_stmt = Database::prepare("
SELECT
dom.`id` as domainid,
dom.`domain`,
dom.`wwwserveralias`
FROM `" . TABLE_PANEL_DOMAINS . "` AS dom
WHERE
dom.`aliasdomain` = :id
AND dom.`letsencrypt` = 1
AND dom.`iswildcarddomain` = 0
");
// iterate through all domains
foreach ($certrows as $certrow) {
// set logger to corresponding loginname for the log to appear in the users system-log
$cronlog = FroxlorLogger::getInstanceOf(array(
'loginname' => $certrow['loginname'],
'adminsession' => 0
));
// Only issue let's encrypt certificate if no broken ssl_redirect is enabled
if ($certrow['ssl_redirect'] != 2) {
$do_force = false;
if (! empty($certrow['ssl_cert_file']) && empty($certrow['expirationdate'])) {
// domain changed (SAN or similar)
$do_force = true;
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Re-creating certificate for " . $certrow['domain']);
} else {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Creating certificate for " . $certrow['domain']);
}
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding common-name: " . $certrow['domain']);
$domains = array(
strtolower($certrow['domain'])
);
// add www.<domain> to SAN list
if ($certrow['wwwserveralias'] == 1) {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: www." . $certrow['domain']);
$domains[] = strtolower('www.' . $certrow['domain']);
}
if ($certrow['domainid'] == 0) {
$froxlor_aliases = Settings::Get('system.froxloraliases');
if (! empty($froxlor_aliases)) {
$froxlor_aliases = explode(",", $froxlor_aliases);
foreach ($froxlor_aliases as $falias) {
if (\Froxlor\Validate\Validate::validateDomain(trim($falias))) {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: " . strtolower(trim($falias)));
$domains[] = strtolower(trim($falias));
}
}
}
} else {
// add alias domains (and possibly www.<aliasdomain>) to SAN list
Database::pexecute($aliasdomains_stmt, array(
'id' => $certrow['domainid']
));
$aliasdomains = $aliasdomains_stmt->fetchAll(\PDO::FETCH_ASSOC);
foreach ($aliasdomains as $aliasdomain) {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: " . $aliasdomain['domain']);
$domains[] = strtolower($aliasdomain['domain']);
if ($aliasdomain['wwwserveralias'] == 1) {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: www." . $aliasdomain['domain']);
$domains[] = strtolower('www.' . $aliasdomain['domain']);
}
}
}
self::validateDns($domains, $certrow['domainid'], $cronlog);
self::runAcmeSh($certrow, $domains, $cronlog, $do_force);
} else {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $certrow['domain'] . " due to an enabled ssl_redirect");
}
}
}
/**
* validate dns (A / AAAA record) of domain against known system ips
*
* @param array $domains
* @param int $domain_id
* @param FroxlorLogger $cronlog
*/
private static function validateDns(array &$domains, $domain_id, &$cronlog)
{
if (Settings::Get('system.le_domain_dnscheck') == '1' && ! empty($domains)) {
$loop_domains = $domains;
// ips according to our system
$our_ips = Domain::getIpsOfDomain($domain_id);
foreach ($loop_domains as $idx => $domain) {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Validating DNS of " . $domain);
// ips according to NS
$domain_ips = PhpHelper::gethostbynamel6($domain);
if ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) <= 0) {
// no common ips...
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $domain . " due to no system known IP address via DNS check");
unset($domains[$idx]);
// in order to avoid a cron-loop that tries to get a certificate every 5 minutes, we disable let's encrypt for this domain
$upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `letsencrypt` = '0' WHERE `id` = :did");
Database::pexecute($upd_stmt, [
'did' => $domain_id
]);
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Let's Encrypt deactivated for domain " . $domain);
}
}
}
}
private static function runAcmeSh(array $certrow, array $domains, &$cronlog = null, $force = false)
{
if (! empty($domains)) {
$acmesh_cmd = self::getAcmeSh() . " --server " . self::$apiserver . " --issue -d " . implode(" -d ", $domains);
// challenge path
$acmesh_cmd .= " -w " . Settings::Get('system.letsencryptchallengepath');
if (Settings::Get('system.leecc') > 0) {
// ecc certificate
$acmesh_cmd .= " --keylength ec-" . Settings::Get('system.leecc');
} else {
$acmesh_cmd .= " --keylength " . Settings::Get('system.letsencryptkeysize');
}
if (Settings::Get('system.letsencryptreuseold') != '1') {
$acmesh_cmd .= " --always-force-new-domain-key";
}
if (Settings::Get('system.letsencryptca') == 'letsencrypt_test') {
$acmesh_cmd .= " --staging";
}
if ($force) {
$acmesh_cmd .= " --force";
}
if (defined('CRON_DEBUG_FLAG')) {
$acmesh_cmd .= " --debug";
}
$acme_result = \Froxlor\FileDir::safe_exec($acmesh_cmd);
// debug output of acme.sh run
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, implode("\n", $acme_result));
self::certToDb($certrow, $cronlog, $acme_result);
}
}
private static function certToDb($certrow, &$cronlog, $acme_result)
{
$return = array();
self::readCertificateToVar(strtolower($certrow['domain']), $return, $cronlog);
if (! empty($return['crt'])) {
$newcert = openssl_x509_parse($return['crt']);
if ($newcert) {
// Store the new data
Database::pexecute(self::$updcert_stmt, array(
'id' => $certrow['id'],
'domainid' => $certrow['domainid'],
'crt' => $return['crt'],
'key' => $return['key'],
'ca' => $return['chain'],
'chain' => $return['chain'],
'csr' => $return['csr'],
'fullchain' => $return['fullchain'],
'expirationdate' => date('Y-m-d H:i:s', $newcert['validTo_time_t'])
));
if ($certrow['ssl_redirect'] == 3) {
Database::pexecute(self::$upddom_stmt, array(
'domainid' => $certrow['domainid']
));
}
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Updated Let's Encrypt certificate for " . $certrow['domain']);
} else {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Got non-successful Let's Encrypt response for " . $certrow['domain'] . ":\n" . implode("\n", $acme_result));
}
} else {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Could not get Let's Encrypt certificate for " . $certrow['domain'] . ":\n" . implode("\n", $acme_result));
}
}
/**
* check whether we need to issue a new certificate for froxlor itself
*
@@ -393,13 +218,100 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
");
$froxlor_ssl = Database::pexecute_first($froxlor_ssl_settings_stmt);
// also check for possible existing certificate
if (! $froxlor_ssl && ! self::checkFsFilesAreNewer(Settings::Get('system.hostname'), date('Y-m-d H:i:s'))) {
if (!$froxlor_ssl && !self::checkFsFilesAreNewer(Settings::Get('system.hostname'), date('Y-m-d H:i:s'))) {
return true;
}
}
return false;
}
private static function checkFsFilesAreNewer($domain, $cert_date = 0)
{
$certificate_folder = self::getWorkingDirFromEnv(strtolower($domain));
$ssl_file = FileDir::makeCorrectFile($certificate_folder . '/' . strtolower($domain) . '.cer');
if (is_dir($certificate_folder) && file_exists($ssl_file) && is_readable($ssl_file)) {
$cert_data = openssl_x509_parse(file_get_contents($ssl_file));
if ($cert_data && $cert_data['validTo_time_t'] > strtotime($cert_date)) {
return true;
}
}
return false;
}
public static function getWorkingDirFromEnv($domain = "", $forced_noecc = false)
{
if (Settings::Get('system.leecc') > 0 && !$forced_noecc) {
$domain .= "_ecc";
}
$env_file = FileDir::makeCorrectFile(dirname(self::getAcmeSh()) . '/acme.sh.env');
if (file_exists($env_file)) {
$output = [];
$cut = <<<EOC
cut -d'"' -f2
EOC;
exec('grep "LE_WORKING_DIR" ' . escapeshellarg($env_file) . ' | ' . $cut, $output);
if (is_array($output) && !empty($output) && isset($output[0]) && !empty($output[0])) {
return FileDir::makeCorrectDir($output[0] . "/" . $domain);
}
}
return FileDir::makeCorrectDir(dirname(self::getAcmeSh()) . "/" . $domain);
}
public static function getAcmeSh()
{
$from_settings = Settings::Get('system.acmeshpath');
if (file_exists($from_settings)) {
return $from_settings;
}
return self::$acmesh;
}
/**
* get a list of domains that require a new certificate (issue)
*/
private static function issueDomains()
{
$certificates_stmt = Database::query("
SELECT
domssl.`id`,
domssl.`domainid`,
domssl.`expirationdate`,
domssl.`ssl_cert_file`,
domssl.`ssl_key_file`,
domssl.`ssl_ca_file`,
domssl.`ssl_csr_file`,
dom.`domain`,
dom.`wwwserveralias`,
dom.`documentroot`,
dom.`id` AS 'domainid',
dom.`ssl_redirect`,
cust.`leprivatekey`,
cust.`lepublickey`,
cust.`leregistered`,
cust.`customerid`,
cust.`loginname`
FROM
`" . TABLE_PANEL_CUSTOMERS . "` AS cust,
`" . TABLE_PANEL_DOMAINS . "` AS dom
LEFT JOIN
`" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` AS domssl ON
dom.`id` = domssl.`domainid`
WHERE
dom.`customerid` = cust.`customerid`
AND cust.deactivated = 0
AND dom.`letsencrypt` = 1
AND dom.`aliasdomain` IS NULL
AND dom.`iswildcarddomain` = 0
AND domssl.`expirationdate` IS NULL
");
$customer_ssl = $certificates_stmt->fetchAll(PDO::FETCH_ASSOC);
if ($customer_ssl) {
return $customer_ssl;
}
return [];
}
/**
* check whether we need to renew-check the certificate for froxlor itself
*
@@ -451,7 +363,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
AND dom.`aliasdomain` IS NULL
AND dom.`iswildcarddomain` = 0
");
$renew_certs = $certificates_stmt->fetchAll(\PDO::FETCH_ASSOC);
$renew_certs = $certificates_stmt->fetchAll(PDO::FETCH_ASSOC);
if ($renew_certs) {
if ($check) {
foreach ($renew_certs as $cert) {
@@ -463,94 +375,230 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
}
return $renew_certs;
}
return array();
return [];
}
/**
* get a list of domains that require a new certificate (issue)
* install acme.sh if not found yet
*/
private static function issueDomains()
private static function checkInstall($tries = 0)
{
$certificates_stmt = Database::query("
if (!file_exists(self::getAcmeSh()) && $tries > 0) {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Download/installation of acme.sh seems to have failed. Re-run cronjob to try again or install manually to '" . self::getAcmeSh() . "'");
echo PHP_EOL . "Download/installation of acme.sh seems to have failed. Re-run cronjob to try again or install manually to '" . self::getAcmeSh() . "'" . PHP_EOL;
return false;
} else {
if (!file_exists(self::getAcmeSh())) {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Could not find acme.sh - installing it to /root/.acme.sh/");
$return = false;
FileDir::safe_exec("wget -O - https://get.acme.sh | sh -s email=" . Settings::Get('panel.adminmail'), $return, [
'|'
]);
$set_path = self::getAcmeSh();
// after this, regardless of what the user specified, the acme.sh installation will be in /root/.acme.sh
if ($set_path != '/root/.acme.sh/acme.sh') {
Settings::Set('system.acmeshpath', '/root/.acme.sh/acme.sh', true);
// let the user know
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Acme.sh could not be found in '" . $set_path . "' so froxlor installed it to the default location, which is '/root/.acme.sh/'");
echo PHP_EOL . "Acme.sh could not be found in '" . $set_path . "' so froxlor installed it to the default location, which is '/root/.acme.sh/'" . PHP_EOL;
}
// check whether the installation worked
return self::checkInstall(++$tries);
}
}
return true;
}
/**
* run upgrade
*/
private static function checkUpgrade()
{
$acmesh_result = FileDir::safe_exec(self::getAcmeSh() . " --upgrade --auto-upgrade 0");
// check for activated cron
$acmesh_result2 = FileDir::safe_exec(self::getAcmeSh() . " --install-cronjob");
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Checking for LetsEncrypt client upgrades before renewing certificates:\n" . implode("\n", $acmesh_result) . "\n" . implode("\n", $acmesh_result2));
}
/**
* issue certificates for a list of domains
*/
private static function runIssueFor($certrows = [])
{
// prepare aliasdomain-check
$aliasdomains_stmt = Database::prepare("
SELECT
domssl.`id`,
domssl.`domainid`,
domssl.`expirationdate`,
domssl.`ssl_cert_file`,
domssl.`ssl_key_file`,
domssl.`ssl_ca_file`,
domssl.`ssl_csr_file`,
dom.`id` as domainid,
dom.`domain`,
dom.`wwwserveralias`,
dom.`documentroot`,
dom.`id` AS 'domainid',
dom.`ssl_redirect`,
cust.`leprivatekey`,
cust.`lepublickey`,
cust.`leregistered`,
cust.`customerid`,
cust.`loginname`
FROM
`" . TABLE_PANEL_CUSTOMERS . "` AS cust,
`" . TABLE_PANEL_DOMAINS . "` AS dom
LEFT JOIN
`" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` AS domssl ON
dom.`id` = domssl.`domainid`
dom.`wwwserveralias`
FROM `" . TABLE_PANEL_DOMAINS . "` AS dom
WHERE
dom.`customerid` = cust.`customerid`
AND cust.deactivated = 0
dom.`aliasdomain` = :id
AND dom.`letsencrypt` = 1
AND dom.`aliasdomain` IS NULL
AND dom.`iswildcarddomain` = 0
AND domssl.`expirationdate` IS NULL
");
$customer_ssl = $certificates_stmt->fetchAll(\PDO::FETCH_ASSOC);
if ($customer_ssl) {
return $customer_ssl;
}
return array();
}
// iterate through all domains
foreach ($certrows as $certrow) {
// set logger to corresponding loginname for the log to appear in the users system-log
$cronlog = FroxlorLogger::getInstanceOf([
'loginname' => $certrow['loginname'],
'adminsession' => 0
]);
// Only issue let's encrypt certificate if no broken ssl_redirect is enabled
if ($certrow['ssl_redirect'] != 2) {
$do_force = false;
if (!empty($certrow['ssl_cert_file']) && empty($certrow['expirationdate'])) {
// domain changed (SAN or similar)
$do_force = true;
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Re-creating certificate for " . $certrow['domain']);
} else {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Creating certificate for " . $certrow['domain']);
}
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding common-name: " . $certrow['domain']);
$domains = [
strtolower($certrow['domain'])
];
// add www.<domain> to SAN list
if ($certrow['wwwserveralias'] == 1) {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: www." . $certrow['domain']);
$domains[] = strtolower('www.' . $certrow['domain']);
}
if ($certrow['domainid'] == 0) {
$froxlor_aliases = Settings::Get('system.froxloraliases');
if (!empty($froxlor_aliases)) {
$froxlor_aliases = explode(",", $froxlor_aliases);
foreach ($froxlor_aliases as $falias) {
if (Validate::validateDomain(trim($falias))) {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: " . strtolower(trim($falias)));
$domains[] = strtolower(trim($falias));
}
}
}
} else {
// add alias domains (and possibly www.<aliasdomain>) to SAN list
Database::pexecute($aliasdomains_stmt, [
'id' => $certrow['domainid']
]);
$aliasdomains = $aliasdomains_stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($aliasdomains as $aliasdomain) {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: " . $aliasdomain['domain']);
$domains[] = strtolower($aliasdomain['domain']);
if ($aliasdomain['wwwserveralias'] == 1) {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: www." . $aliasdomain['domain']);
$domains[] = strtolower('www.' . $aliasdomain['domain']);
}
}
}
private static function checkFsFilesAreNewer($domain, $cert_date = 0)
{
$certificate_folder = self::getWorkingDirFromEnv(strtolower($domain));
$ssl_file = \Froxlor\FileDir::makeCorrectFile($certificate_folder . '/' . strtolower($domain) . '.cer');
self::validateDns($domains, $certrow['domainid'], $cronlog);
if (is_dir($certificate_folder) && file_exists($ssl_file) && is_readable($ssl_file)) {
$cert_data = openssl_x509_parse(file_get_contents($ssl_file));
if ($cert_data && $cert_data['validTo_time_t'] > strtotime($cert_date)) {
return true;
self::runAcmeSh($certrow, $domains, $cronlog, $do_force);
} else {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $certrow['domain'] . " due to an enabled ssl_redirect");
}
}
return false;
}
public static function getWorkingDirFromEnv($domain = "", $forced_noecc = false)
/**
* validate dns (A / AAAA record) of domain against known system ips
*
* @param array $domains
* @param int $domain_id
* @param FroxlorLogger $cronlog
*/
private static function validateDns(array &$domains, $domain_id, &$cronlog)
{
if (Settings::Get('system.leecc') > 0 && ! $forced_noecc) {
$domain .= "_ecc";
}
$env_file = FileDir::makeCorrectFile(dirname(self::getAcmeSh()) . '/acme.sh.env');
if (file_exists($env_file)) {
$output = [];
$cut = <<<EOC
cut -d'"' -f2
EOC;
exec('grep "LE_WORKING_DIR" ' . escapeshellarg($env_file) . ' | ' . $cut, $output);
if (is_array($output) && ! empty($output) && isset($output[0]) && ! empty($output[0])) {
return FileDir::makeCorrectDir($output[0] . "/" . $domain);
if (Settings::Get('system.le_domain_dnscheck') == '1' && !empty($domains)) {
$loop_domains = $domains;
// ips according to our system
$our_ips = Domain::getIpsOfDomain($domain_id);
foreach ($loop_domains as $idx => $domain) {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Validating DNS of " . $domain);
// ips according to NS
$domain_ips = PhpHelper::gethostbynamel6($domain);
if ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) <= 0) {
// no common ips...
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $domain . " due to no system known IP address via DNS check");
unset($domains[$idx]);
// in order to avoid a cron-loop that tries to get a certificate every 5 minutes, we disable let's encrypt for this domain
$upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `letsencrypt` = '0' WHERE `id` = :did");
Database::pexecute($upd_stmt, [
'did' => $domain_id
]);
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Let's Encrypt deactivated for domain " . $domain);
}
}
}
return FileDir::makeCorrectDir(dirname(self::getAcmeSh()) . "/" . $domain);
}
public static function getAcmeSh()
private static function runAcmeSh(array $certrow, array $domains, &$cronlog = null, $force = false)
{
$from_settings = Settings::Get('system.acmeshpath');
if (file_exists($from_settings)) {
return $from_settings;
if (!empty($domains)) {
$acmesh_cmd = self::getAcmeSh() . " --server " . self::$apiserver . " --issue -d " . implode(" -d ", $domains);
// challenge path
$acmesh_cmd .= " -w " . Settings::Get('system.letsencryptchallengepath');
if (Settings::Get('system.leecc') > 0) {
// ecc certificate
$acmesh_cmd .= " --keylength ec-" . Settings::Get('system.leecc');
} else {
$acmesh_cmd .= " --keylength " . Settings::Get('system.letsencryptkeysize');
}
if (Settings::Get('system.letsencryptreuseold') != '1') {
$acmesh_cmd .= " --always-force-new-domain-key";
}
if (Settings::Get('system.letsencryptca') == 'letsencrypt_test') {
$acmesh_cmd .= " --staging";
}
if ($force) {
$acmesh_cmd .= " --force";
}
if (defined('CRON_DEBUG_FLAG')) {
$acmesh_cmd .= " --debug";
}
$acme_result = FileDir::safe_exec($acmesh_cmd);
// debug output of acme.sh run
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, implode("\n", $acme_result));
self::certToDb($certrow, $cronlog, $acme_result);
}
}
private static function certToDb($certrow, &$cronlog, $acme_result)
{
$return = [];
self::readCertificateToVar(strtolower($certrow['domain']), $return, $cronlog);
if (!empty($return['crt'])) {
$newcert = openssl_x509_parse($return['crt']);
if ($newcert) {
// Store the new data
Database::pexecute(self::$updcert_stmt, [
'id' => $certrow['id'],
'domainid' => $certrow['domainid'],
'crt' => $return['crt'],
'key' => $return['key'],
'ca' => $return['chain'],
'chain' => $return['chain'],
'csr' => $return['csr'],
'fullchain' => $return['fullchain'],
'expirationdate' => date('Y-m-d H:i:s', $newcert['validTo_time_t'])
]);
if ($certrow['ssl_redirect'] == 3) {
Database::pexecute(self::$upddom_stmt, [
'domainid' => $certrow['domainid']
]);
}
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Updated Let's Encrypt certificate for " . $certrow['domain']);
} else {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Got non-successful Let's Encrypt response for " . $certrow['domain'] . ":\n" . implode("\n", $acme_result));
}
} else {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Could not get Let's Encrypt certificate for " . $certrow['domain'] . ":\n" . implode("\n", $acme_result));
}
return self::$acmesh;
}
/**
@@ -567,22 +615,24 @@ EOC;
if (Settings::Get('system.leecc') > 0) {
$certificate_folder_noecc = self::getWorkingDirFromEnv($domain, true);
}
$certificate_folder = \Froxlor\FileDir::makeCorrectDir($certificate_folder);
$certificate_folder = FileDir::makeCorrectDir($certificate_folder);
if (is_dir($certificate_folder) || is_dir($certificate_folder_noecc)) {
foreach ([
'crt' => $domain . '.cer',
'key' => $domain . '.key',
'chain' => 'ca.cer',
'fullchain' => 'fullchain.cer',
'csr' => $domain . '.csr'
] as $index => $sslfile) {
$ssl_file = \Froxlor\FileDir::makeCorrectFile($certificate_folder . '/' . $sslfile);
foreach (
[
'crt' => $domain . '.cer',
'key' => $domain . '.key',
'chain' => 'ca.cer',
'fullchain' => 'fullchain.cer',
'csr' => $domain . '.csr'
] as $index => $sslfile
) {
$ssl_file = FileDir::makeCorrectFile($certificate_folder . '/' . $sslfile);
if (file_exists($ssl_file)) {
$return[$index] = file_get_contents($ssl_file);
} else {
if (! empty($certificate_folder_noecc)) {
$ssl_file_fb = \Froxlor\FileDir::makeCorrectFile($certificate_folder_noecc . '/' . $sslfile);
if (!empty($certificate_folder_noecc)) {
$ssl_file_fb = FileDir::makeCorrectFile($certificate_folder_noecc . '/' . $sslfile);
if (file_exists($ssl_file_fb)) {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "ECC certificates activated but found only non-ecc file");
$return[$index] = file_get_contents($ssl_file_fb);
@@ -597,44 +647,4 @@ EOC;
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Could not find certificate-folder '" . $certificate_folder . "'");
}
}
/**
* install acme.sh if not found yet
*/
private static function checkInstall($tries = 0)
{
if (! file_exists(self::getAcmeSh()) && $tries > 0) {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Download/installation of acme.sh seems to have failed. Re-run cronjob to try again or install manually to '" . self::getAcmeSh() . "'");
echo PHP_EOL . "Download/installation of acme.sh seems to have failed. Re-run cronjob to try again or install manually to '" . self::getAcmeSh() . "'" . PHP_EOL;
return false;
} else if (! file_exists(self::getAcmeSh())) {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Could not find acme.sh - installing it to /root/.acme.sh/");
$return = false;
\Froxlor\FileDir::safe_exec("wget -O - https://get.acme.sh | sh -s email=" . Settings::Get('panel.adminmail'), $return, array(
'|'
));
$set_path = self::getAcmeSh();
// after this, regardless of what the user specified, the acme.sh installation will be in /root/.acme.sh
if ($set_path != '/root/.acme.sh/acme.sh') {
Settings::Set('system.acmeshpath', '/root/.acme.sh/acme.sh', true);
// let the user know
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Acme.sh could not be found in '" . $set_path . "' so froxlor installed it to the default location, which is '/root/.acme.sh/'");
echo PHP_EOL . "Acme.sh could not be found in '" . $set_path . "' so froxlor installed it to the default location, which is '/root/.acme.sh/'" . PHP_EOL;
}
// check whether the installation worked
return self::checkInstall(++ $tries);
}
return true;
}
/**
* run upgrade
*/
private static function checkUpgrade()
{
$acmesh_result = \Froxlor\FileDir::safe_exec(self::getAcmeSh() . " --upgrade --auto-upgrade 0");
// check for activated cron
$acmesh_result2 = \Froxlor\FileDir::safe_exec(self::getAcmeSh() . " --install-cronjob");
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Checking for LetsEncrypt client upgrades before renewing certificates:\n" . implode("\n", $acmesh_result) . "\n" . implode("\n", $acmesh_result2));
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,37 +1,106 @@
<?php
namespace Froxlor\Cron\Http;
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\Cron\Http\Php\PhpInterface;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
* 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\Http;
use Froxlor\Cron\Http\Php\PhpInterface;
use Froxlor\Database\Database;
use Froxlor\FileDir;
use Froxlor\Settings;
class LighttpdFcgi extends Lighttpd
{
public function createOwnVhostStarter()
{
if (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.enabled_ownvhost') == '1') {
$mypath = FileDir::makeCorrectDir(dirname(__FILE__, 3)); // /var/www/froxlor, needed for chown
$user = Settings::Get('phpfpm.vhost_httpuser');
$group = Settings::Get('phpfpm.vhost_httpgroup');
// get fpm config
$fpm_sel_stmt = Database::prepare("
SELECT f.id FROM `" . TABLE_PANEL_FPMDAEMONS . "` f
LEFT JOIN `" . TABLE_PANEL_PHPCONFIGS . "` p ON p.fpmsettingid = f.id
WHERE p.id = :phpconfigid
");
$fpm_config = Database::pexecute_first($fpm_sel_stmt, [
'phpconfigid' => Settings::Get('phpfpm.vhost_defaultini')
]);
$domain = [
'id' => 'none',
'domain' => Settings::Get('system.hostname'),
'adminid' => 1, /* first admin-user (superadmin) */
'mod_fcgid_starter' => -1,
'mod_fcgid_maxrequests' => -1,
'guid' => $user,
'openbasedir' => 0,
'email' => Settings::Get('panel.adminmail'),
'loginname' => 'froxlor.panel',
'documentroot' => $mypath,
'customerroot' => $mypath,
'fpm_config_id' => isset($fpm_config['id']) ? $fpm_config['id'] : 1
];
// all the files and folders have to belong to the local user
// now because we also use fcgid for our own vhost
FileDir::safe_exec('chown -R ' . $user . ':' . $group . ' ' . escapeshellarg($mypath));
// get php.ini for our own vhost
$php = new PhpInterface($domain);
// get php-config
if (Settings::Get('phpfpm.enabled') == '1') {
// fpm
$phpconfig = $php->getPhpConfig(Settings::Get('phpfpm.vhost_defaultini'));
} else {
// fcgid
$phpconfig = $php->getPhpConfig(Settings::Get('system.mod_fcgid_defaultini_ownvhost'));
}
// create starter-file | config-file
$php->getInterface()->createConfig($phpconfig);
// create php.ini (fpm does nothing here, as it
// defines ini-settings in its pool config)
$php->getInterface()->createIniFile($phpconfig);
}
}
protected function composePhpOptions(&$domain)
{
$php_options_text = '';
if ($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1') {
$php = new PhpInterface($domain);
$phpconfig = $php->getPhpConfig((int) $domain['phpsettingid']);
$phpconfig = $php->getPhpConfig((int)$domain['phpsettingid']);
// vhost data for php-fpm
if ((int) Settings::Get('phpfpm.enabled') == 1) {
if ((int)Settings::Get('phpfpm.enabled') == 1) {
$domain['fpm_socket'] = $php->getInterface()->getSocketFile();
$php_options_text = ' fastcgi.server = ( ' . "\n";
$php_options_text .= "\t" . '".php" => (' . "\n";
@@ -42,7 +111,7 @@ class LighttpdFcgi extends Lighttpd
$php_options_text .= "\t" . ')' . "\n";
$php_options_text .= "\t" . ')' . "\n";
$php_options_text .= ' )' . "\n";
} elseif ((int) Settings::Get('system.mod_fcgid') == 1) {
} elseif ((int)Settings::Get('system.mod_fcgid') == 1) {
// vhost data for fcgid
$php_options_text = ' fastcgi.server = ( ' . "\n";
$file_extensions = explode(' ', $phpconfig['file_extensions']);
@@ -52,23 +121,23 @@ class LighttpdFcgi extends Lighttpd
$php_options_text .= "\t\t" . '"socket" => "/var/run/lighttpd/' . $domain['loginname'] . '-' . $domain['domain'] . '-php.socket",' . "\n";
$php_options_text .= "\t\t" . '"bin-path" => "' . $phpconfig['binary'] . ' -c ' . $php->getInterface()->getIniFile() . '",' . "\n";
$php_options_text .= "\t\t" . '"bin-environment" => (' . "\n";
if ((int) $domain['mod_fcgid_starter'] != - 1) {
$php_options_text .= "\t\t\t" . '"PHP_FCGI_CHILDREN" => "' . (int) $domain['mod_fcgid_starter'] . '",' . "\n";
if ((int)$domain['mod_fcgid_starter'] != -1) {
$php_options_text .= "\t\t\t" . '"PHP_FCGI_CHILDREN" => "' . (int)$domain['mod_fcgid_starter'] . '",' . "\n";
} else {
if ((int) $phpconfig['mod_fcgid_starter'] != - 1) {
$php_options_text .= "\t\t\t" . '"PHP_FCGI_CHILDREN" => "' . (int) $phpconfig['mod_fcgid_starter'] . '",' . "\n";
if ((int)$phpconfig['mod_fcgid_starter'] != -1) {
$php_options_text .= "\t\t\t" . '"PHP_FCGI_CHILDREN" => "' . (int)$phpconfig['mod_fcgid_starter'] . '",' . "\n";
} else {
$php_options_text .= "\t\t\t" . '"PHP_FCGI_CHILDREN" => "' . (int) Settings::Get('system.mod_fcgid_starter') . '",' . "\n";
$php_options_text .= "\t\t\t" . '"PHP_FCGI_CHILDREN" => "' . (int)Settings::Get('system.mod_fcgid_starter') . '",' . "\n";
}
}
if ((int) $domain['mod_fcgid_maxrequests'] != - 1) {
$php_options_text .= "\t\t\t" . '"PHP_FCGI_MAX_REQUESTS" => "' . (int) $domain['mod_fcgid_maxrequests'] . '"' . "\n";
if ((int)$domain['mod_fcgid_maxrequests'] != -1) {
$php_options_text .= "\t\t\t" . '"PHP_FCGI_MAX_REQUESTS" => "' . (int)$domain['mod_fcgid_maxrequests'] . '"' . "\n";
} else {
if ((int) $phpconfig['mod_fcgid_maxrequests'] != - 1) {
$php_options_text .= "\t\t\t" . '"PHP_FCGI_MAX_REQUESTS" => "' . (int) $phpconfig['mod_fcgid_maxrequests'] . '"' . "\n";
if ((int)$phpconfig['mod_fcgid_maxrequests'] != -1) {
$php_options_text .= "\t\t\t" . '"PHP_FCGI_MAX_REQUESTS" => "' . (int)$phpconfig['mod_fcgid_maxrequests'] . '"' . "\n";
} else {
$php_options_text .= "\t\t\t" . '"PHP_FCGI_MAX_REQUESTS" => "' . (int) Settings::Get('system.mod_fcgid_maxrequests') . '"' . "\n";
$php_options_text .= "\t\t\t" . '"PHP_FCGI_MAX_REQUESTS" => "' . (int)Settings::Get('system.mod_fcgid_maxrequests') . '"' . "\n";
}
}
@@ -91,62 +160,4 @@ class LighttpdFcgi extends Lighttpd
return $php_options_text;
}
public function createOwnVhostStarter()
{
if (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.enabled_ownvhost') == '1') {
$mypath = \Froxlor\FileDir::makeCorrectDir(dirname(__FILE__, 3)); // /var/www/froxlor, needed for chown
$user = Settings::Get('phpfpm.vhost_httpuser');
$group = Settings::Get('phpfpm.vhost_httpgroup');
// get fpm config
$fpm_sel_stmt = Database::prepare("
SELECT f.id FROM `" . TABLE_PANEL_FPMDAEMONS . "` f
LEFT JOIN `" . TABLE_PANEL_PHPCONFIGS . "` p ON p.fpmsettingid = f.id
WHERE p.id = :phpconfigid
");
$fpm_config = Database::pexecute_first($fpm_sel_stmt, array(
'phpconfigid' => Settings::Get('phpfpm.vhost_defaultini')
));
$domain = array(
'id' => 'none',
'domain' => Settings::Get('system.hostname'),
'adminid' => 1, /* first admin-user (superadmin) */
'mod_fcgid_starter' => - 1,
'mod_fcgid_maxrequests' => - 1,
'guid' => $user,
'openbasedir' => 0,
'email' => Settings::Get('panel.adminmail'),
'loginname' => 'froxlor.panel',
'documentroot' => $mypath,
'customerroot' => $mypath,
'fpm_config_id' => isset($fpm_config['id']) ? $fpm_config['id'] : 1
);
// all the files and folders have to belong to the local user
// now because we also use fcgid for our own vhost
\Froxlor\FileDir::safe_exec('chown -R ' . $user . ':' . $group . ' ' . escapeshellarg($mypath));
// get php.ini for our own vhost
$php = new PhpInterface($domain);
// get php-config
if (Settings::Get('phpfpm.enabled') == '1') {
// fpm
$phpconfig = $php->getPhpConfig(Settings::Get('phpfpm.vhost_defaultini'));
} else {
// fcgid
$phpconfig = $php->getPhpConfig(Settings::Get('system.mod_fcgid_defaultini_ownvhost'));
}
// create starter-file | config-file
$php->getInterface()->createConfig($phpconfig);
// create php.ini (fpm does nothing here, as it
// defines ini-settings in its pool config)
$php->getInterface()->createIniFile($phpconfig);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,34 +1,103 @@
<?php
namespace Froxlor\Cron\Http;
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\Cron\Http\Php\PhpInterface;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
* 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\Http;
use Froxlor\Cron\Http\Php\PhpInterface;
use Froxlor\Database\Database;
use Froxlor\FileDir;
use Froxlor\Settings;
class NginxFcgi extends Nginx
{
public function createOwnVhostStarter()
{
if (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.enabled_ownvhost') == '1') {
$mypath = FileDir::makeCorrectDir(dirname(__FILE__, 3)); // /var/www/froxlor, needed for chown
$user = Settings::Get('phpfpm.vhost_httpuser');
$group = Settings::Get('phpfpm.vhost_httpgroup');
// get fpm config
$fpm_sel_stmt = Database::prepare("
SELECT f.id FROM `" . TABLE_PANEL_FPMDAEMONS . "` f
LEFT JOIN `" . TABLE_PANEL_PHPCONFIGS . "` p ON p.fpmsettingid = f.id
WHERE p.id = :phpconfigid
");
$fpm_config = Database::pexecute_first($fpm_sel_stmt, [
'phpconfigid' => Settings::Get('phpfpm.vhost_defaultini')
]);
$domain = [
'id' => 'none',
'domain' => Settings::Get('system.hostname'),
'adminid' => 1, /* first admin-user (superadmin) */
'mod_fcgid_starter' => -1,
'mod_fcgid_maxrequests' => -1,
'guid' => $user,
'openbasedir' => 0,
'email' => Settings::Get('panel.adminmail'),
'loginname' => 'froxlor.panel',
'documentroot' => $mypath,
'customerroot' => $mypath,
'fpm_config_id' => isset($fpm_config['id']) ? $fpm_config['id'] : 1
];
// all the files and folders have to belong to the local user
// now because we also use fcgid for our own vhost
FileDir::safe_exec('chown -R ' . $user . ':' . $group . ' ' . escapeshellarg($mypath));
// get php.ini for our own vhost
$php = new PhpInterface($domain);
// get php-config
if (Settings::Get('phpfpm.enabled') == '1') {
// fpm
$phpconfig = $php->getPhpConfig(Settings::Get('phpfpm.vhost_defaultini'));
} else {
// fcgid
$phpconfig = $php->getPhpConfig(Settings::Get('system.mod_fcgid_defaultini_ownvhost'));
}
// create starter-file | config-file
$php->getInterface()->createConfig($phpconfig);
// create php.ini (fpm does nothing here, as it
// defines ini-settings in its pool config)
$php->getInterface()->createIniFile($phpconfig);
}
}
protected function composePhpOptions(&$domain, $ssl_vhost = false)
{
$php_options_text = '';
if ($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1') {
$php = new PhpInterface($domain);
$phpconfig = $php->getPhpConfig((int) $domain['phpsettingid']);
$phpconfig = $php->getPhpConfig((int)$domain['phpsettingid']);
$php_options_text = "\t" . 'location ~ ^(.+?\.php)(/.*)?$ {' . "\n";
$php_options_text .= "\t\t" . 'try_files ' . $domain['nonexistinguri'] . ' @php;' . "\n";
@@ -60,62 +129,4 @@ class NginxFcgi extends Nginx
return $php_options_text;
}
public function createOwnVhostStarter()
{
if (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.enabled_ownvhost') == '1') {
$mypath = \Froxlor\FileDir::makeCorrectDir(dirname(__FILE__, 3)); // /var/www/froxlor, needed for chown
$user = Settings::Get('phpfpm.vhost_httpuser');
$group = Settings::Get('phpfpm.vhost_httpgroup');
// get fpm config
$fpm_sel_stmt = Database::prepare("
SELECT f.id FROM `" . TABLE_PANEL_FPMDAEMONS . "` f
LEFT JOIN `" . TABLE_PANEL_PHPCONFIGS . "` p ON p.fpmsettingid = f.id
WHERE p.id = :phpconfigid
");
$fpm_config = Database::pexecute_first($fpm_sel_stmt, array(
'phpconfigid' => Settings::Get('phpfpm.vhost_defaultini')
));
$domain = array(
'id' => 'none',
'domain' => Settings::Get('system.hostname'),
'adminid' => 1, /* first admin-user (superadmin) */
'mod_fcgid_starter' => - 1,
'mod_fcgid_maxrequests' => - 1,
'guid' => $user,
'openbasedir' => 0,
'email' => Settings::Get('panel.adminmail'),
'loginname' => 'froxlor.panel',
'documentroot' => $mypath,
'customerroot' => $mypath,
'fpm_config_id' => isset($fpm_config['id']) ? $fpm_config['id'] : 1
);
// all the files and folders have to belong to the local user
// now because we also use fcgid for our own vhost
\Froxlor\FileDir::safe_exec('chown -R ' . $user . ':' . $group . ' ' . escapeshellarg($mypath));
// get php.ini for our own vhost
$php = new PhpInterface($domain);
// get php-config
if (Settings::Get('phpfpm.enabled') == '1') {
// fpm
$phpconfig = $php->getPhpConfig(Settings::Get('phpfpm.vhost_defaultini'));
} else {
// fcgid
$phpconfig = $php->getPhpConfig(Settings::Get('system.mod_fcgid_defaultini_ownvhost'));
}
// create starter-file | config-file
$php->getInterface()->createConfig($phpconfig);
// create php.ini (fpm does nothing here, as it
// defines ini-settings in its pool config)
$php->getInterface()->createIniFile($phpconfig);
}
}
}

View File

@@ -1,27 +1,36 @@
<?php
namespace Froxlor\Cron\Http\Php;
use Froxlor\Database\Database;
use Froxlor\Settings;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Michael Kaufmann <mkaufmann@nutime.de>
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
* @link http://www.nutime.de/
* @since 0.9.16
*
* 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\Http\Php;
use Froxlor\Database\Database;
use Froxlor\Domain\Domain;
use Froxlor\FileDir;
use Froxlor\PhpHelper;
use Froxlor\Settings;
class Fcgid
{
@@ -30,14 +39,14 @@ class Fcgid
*
* @var array
*/
private $domain = array();
private $domain = [];
/**
* Admin-Date cache array
*
* @var array
*/
private $admin_cache = array();
private $admin_cache = [];
/**
* main constructor
@@ -54,7 +63,6 @@ class Fcgid
*/
public function createConfig($phpconfig)
{
// create starter
$starter_file = "#!/bin/sh\n\n";
$starter_file .= "#\n";
@@ -66,26 +74,26 @@ class Fcgid
$starter_file .= "export PHPRC\n";
// set number of processes for one domain
if ((int) $this->domain['mod_fcgid_starter'] != - 1) {
$starter_file .= "PHP_FCGI_CHILDREN=" . (int) $this->domain['mod_fcgid_starter'] . "\n";
if ((int)$this->domain['mod_fcgid_starter'] != -1) {
$starter_file .= "PHP_FCGI_CHILDREN=" . (int)$this->domain['mod_fcgid_starter'] . "\n";
} else {
if ((int) $phpconfig['mod_fcgid_starter'] != - 1) {
$starter_file .= "PHP_FCGI_CHILDREN=" . (int) $phpconfig['mod_fcgid_starter'] . "\n";
if ((int)$phpconfig['mod_fcgid_starter'] != -1) {
$starter_file .= "PHP_FCGI_CHILDREN=" . (int)$phpconfig['mod_fcgid_starter'] . "\n";
} else {
$starter_file .= "PHP_FCGI_CHILDREN=" . (int) Settings::Get('system.mod_fcgid_starter') . "\n";
$starter_file .= "PHP_FCGI_CHILDREN=" . (int)Settings::Get('system.mod_fcgid_starter') . "\n";
}
}
$starter_file .= "export PHP_FCGI_CHILDREN\n";
// set number of maximum requests for one domain
if ((int) $this->domain['mod_fcgid_maxrequests'] != - 1) {
$starter_file .= "PHP_FCGI_MAX_REQUESTS=" . (int) $this->domain['mod_fcgid_maxrequests'] . "\n";
if ((int)$this->domain['mod_fcgid_maxrequests'] != -1) {
$starter_file .= "PHP_FCGI_MAX_REQUESTS=" . (int)$this->domain['mod_fcgid_maxrequests'] . "\n";
} else {
if ((int) $phpconfig['mod_fcgid_maxrequests'] != - 1) {
$starter_file .= "PHP_FCGI_MAX_REQUESTS=" . (int) $phpconfig['mod_fcgid_maxrequests'] . "\n";
if ((int)$phpconfig['mod_fcgid_maxrequests'] != -1) {
$starter_file .= "PHP_FCGI_MAX_REQUESTS=" . (int)$phpconfig['mod_fcgid_maxrequests'] . "\n";
} else {
$starter_file .= "PHP_FCGI_MAX_REQUESTS=" . (int) Settings::Get('system.mod_fcgid_maxrequests') . "\n";
$starter_file .= "PHP_FCGI_MAX_REQUESTS=" . (int)Settings::Get('system.mod_fcgid_maxrequests') . "\n";
}
}
@@ -96,15 +104,46 @@ class Fcgid
// remove +i attribute, so starter can be overwritten
if (file_exists($this->getStarterFile())) {
\Froxlor\FileDir::removeImmutable($this->getStarterFile());
FileDir::removeImmutable($this->getStarterFile());
}
$starter_file_handler = fopen($this->getStarterFile(), 'w');
fwrite($starter_file_handler, $starter_file);
fclose($starter_file_handler);
\Froxlor\FileDir::safe_exec('chmod 750 ' . escapeshellarg($this->getStarterFile()));
\Froxlor\FileDir::safe_exec('chown ' . $this->domain['guid'] . ':' . $this->domain['guid'] . ' ' . escapeshellarg($this->getStarterFile()));
\Froxlor\FileDir::setImmutable($this->getStarterFile());
FileDir::safe_exec('chmod 750 ' . escapeshellarg($this->getStarterFile()));
FileDir::safe_exec('chown ' . $this->domain['guid'] . ':' . $this->domain['guid'] . ' ' . escapeshellarg($this->getStarterFile()));
FileDir::setImmutable($this->getStarterFile());
}
/**
* fcgid-config directory
*
* @param boolean $createifnotexists
* create the directory if it does not exist
*
* @return string the directory
*/
public function getConfigDir($createifnotexists = true)
{
$configdir = FileDir::makeCorrectDir(Settings::Get('system.mod_fcgid_configdir') . '/' . $this->domain['loginname'] . '/' . $this->domain['domain'] . '/');
if (!is_dir($configdir) && $createifnotexists) {
FileDir::safe_exec('mkdir -p ' . escapeshellarg($configdir));
FileDir::safe_exec('chown ' . $this->domain['guid'] . ':' . $this->domain['guid'] . ' ' . escapeshellarg($configdir));
}
return $configdir;
}
/**
* return path of php-starter file
*
* @return string the directory
*/
public function getStarterFile()
{
$starter_filename = FileDir::makeCorrectFile($this->getConfigDir() . '/php-fcgi-starter');
return $starter_filename;
}
/**
@@ -118,27 +157,26 @@ class Fcgid
$openbasedirc = ';';
if ($this->domain['openbasedir'] == '1') {
$openbasedirc = '';
$_phpappendopenbasedir = '';
$_custom_openbasedir = explode(':', Settings::Get('system.mod_fcgid_peardir'));
foreach ($_custom_openbasedir as $cobd) {
$_phpappendopenbasedir .= \Froxlor\Domain\Domain::appendOpenBasedirPath($cobd);
$_phpappendopenbasedir .= Domain::appendOpenBasedirPath($cobd);
}
$_custom_openbasedir = explode(':', Settings::Get('system.phpappendopenbasedir'));
foreach ($_custom_openbasedir as $cobd) {
$_phpappendopenbasedir .= \Froxlor\Domain\Domain::appendOpenBasedirPath($cobd);
$_phpappendopenbasedir .= Domain::appendOpenBasedirPath($cobd);
}
if ($this->domain['openbasedir_path'] == '0' && strstr($this->domain['documentroot'], ":") === false) {
$openbasedir = \Froxlor\Domain\Domain::appendOpenBasedirPath($this->domain['documentroot'], true);
$openbasedir = Domain::appendOpenBasedirPath($this->domain['documentroot'], true);
} else {
$openbasedir = \Froxlor\Domain\Domain::appendOpenBasedirPath($this->domain['customerroot'], true);
$openbasedir = Domain::appendOpenBasedirPath($this->domain['customerroot'], true);
}
$openbasedir .= \Froxlor\Domain\Domain::appendOpenBasedirPath($this->getTempDir());
$openbasedir .= Domain::appendOpenBasedirPath($this->getTempDir());
$openbasedir .= $_phpappendopenbasedir;
} else {
$openbasedir = 'none';
@@ -146,7 +184,7 @@ class Fcgid
}
$admin = $this->getAdminData($this->domain['adminid']);
$php_ini_variables = array(
$php_ini_variables = [
'SAFE_MODE' => 'Off', // keep this for compatibility, just in case
'PEAR_DIR' => Settings::Get('system.mod_fcgid_peardir'),
'TMP_DIR' => $this->getTempDir(),
@@ -158,75 +196,66 @@ class Fcgid
'OPEN_BASEDIR' => $openbasedir,
'OPEN_BASEDIR_C' => $openbasedirc,
'OPEN_BASEDIR_GLOBAL' => Settings::Get('system.phpappendopenbasedir'),
'DOCUMENT_ROOT' => \Froxlor\FileDir::makeCorrectDir($this->domain['documentroot']),
'CUSTOMER_HOMEDIR' => \Froxlor\FileDir::makeCorrectDir($this->domain['customerroot'])
);
'DOCUMENT_ROOT' => FileDir::makeCorrectDir($this->domain['documentroot']),
'CUSTOMER_HOMEDIR' => FileDir::makeCorrectDir($this->domain['customerroot'])
];
// insert a small header for the file
$phpini_file = ";\n";
$phpini_file .= "; php.ini created/changed on " . date("Y.m.d H:i:s") . " for domain '" . $this->domain['domain'] . "' with id #" . $this->domain['id'] . " from php template '" . $phpconfig['description'] . "' with id #" . $phpconfig['id'] . "\n";
$phpini_file .= "; Do not change anything in this file, it will be overwritten by the Froxlor Cronjob!\n";
$phpini_file .= ";\n\n";
$phpini_file .= \Froxlor\PhpHelper::replaceVariables($phpconfig['phpsettings'], $php_ini_variables);
$phpini_file .= PhpHelper::replaceVariables($phpconfig['phpsettings'], $php_ini_variables);
$phpini_file = str_replace('"none"', 'none', $phpini_file);
// $phpini_file = preg_replace('/\"+/', '"', $phpini_file);
$phpini_file_handler = fopen($this->getIniFile(), 'w');
fwrite($phpini_file_handler, $phpini_file);
fclose($phpini_file_handler);
\Froxlor\FileDir::safe_exec('chown root:0 ' . escapeshellarg($this->getIniFile()));
\Froxlor\FileDir::safe_exec('chmod 0644 ' . escapeshellarg($this->getIniFile()));
}
/**
* fcgid-config directory
*
* @param boolean $createifnotexists
* create the directory if it does not exist
*
* @return string the directory
*/
public function getConfigDir($createifnotexists = true)
{
$configdir = \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.mod_fcgid_configdir') . '/' . $this->domain['loginname'] . '/' . $this->domain['domain'] . '/');
if (! is_dir($configdir) && $createifnotexists) {
\Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg($configdir));
\Froxlor\FileDir::safe_exec('chown ' . $this->domain['guid'] . ':' . $this->domain['guid'] . ' ' . escapeshellarg($configdir));
}
return $configdir;
FileDir::safe_exec('chown root:0 ' . escapeshellarg($this->getIniFile()));
FileDir::safe_exec('chmod 0644 ' . escapeshellarg($this->getIniFile()));
}
/**
* fcgid-temp directory
*
* @param boolean $createifnotexists
* create the directory if it does not exist
*
* create the directory if it does not exist
*
* @return string the directory
*/
public function getTempDir($createifnotexists = true)
{
$tmpdir = \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.mod_fcgid_tmpdir') . '/' . $this->domain['loginname'] . '/');
$tmpdir = FileDir::makeCorrectDir(Settings::Get('system.mod_fcgid_tmpdir') . '/' . $this->domain['loginname'] . '/');
if (! is_dir($tmpdir) && $createifnotexists) {
\Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg($tmpdir));
\Froxlor\FileDir::safe_exec('chown -R ' . $this->domain['guid'] . ':' . $this->domain['guid'] . ' ' . escapeshellarg($tmpdir));
\Froxlor\FileDir::safe_exec('chmod 0750 ' . escapeshellarg($tmpdir));
if (!is_dir($tmpdir) && $createifnotexists) {
FileDir::safe_exec('mkdir -p ' . escapeshellarg($tmpdir));
FileDir::safe_exec('chown -R ' . $this->domain['guid'] . ':' . $this->domain['guid'] . ' ' . escapeshellarg($tmpdir));
FileDir::safe_exec('chmod 0750 ' . escapeshellarg($tmpdir));
}
return $tmpdir;
}
/**
* return path of php-starter file
* return the admin-data of a specific admin
*
* @return string the directory
* @param int $adminid
* id of the admin-user
*
* @return array
*/
public function getStarterFile()
private function getAdminData($adminid)
{
$starter_filename = \Froxlor\FileDir::makeCorrectFile($this->getConfigDir() . '/php-fcgi-starter');
return $starter_filename;
$adminid = intval($adminid);
if (!isset($this->admin_cache[$adminid])) {
$stmt = Database::prepare("
SELECT `email`, `loginname` FROM `" . TABLE_PANEL_ADMINS . "` WHERE `adminid` = :id");
$this->admin_cache[$adminid] = Database::pexecute_first($stmt, [
'id' => $adminid
]);
}
return $this->admin_cache[$adminid];
}
/**
@@ -236,29 +265,7 @@ class Fcgid
*/
public function getIniFile()
{
$phpini_filename = \Froxlor\FileDir::makeCorrectFile($this->getConfigDir() . '/php.ini');
$phpini_filename = FileDir::makeCorrectFile($this->getConfigDir() . '/php.ini');
return $phpini_filename;
}
/**
* return the admin-data of a specific admin
*
* @param int $adminid
* id of the admin-user
*
* @return array
*/
private function getAdminData($adminid)
{
$adminid = intval($adminid);
if (! isset($this->admin_cache[$adminid])) {
$stmt = Database::prepare("
SELECT `email`, `loginname` FROM `" . TABLE_PANEL_ADMINS . "` WHERE `adminid` = :id");
$this->admin_cache[$adminid] = Database::pexecute_first($stmt, array(
'id' => $adminid
));
}
return $this->admin_cache[$adminid];
}
}

View File

@@ -1,27 +1,36 @@
<?php
namespace Froxlor\Cron\Http\Php;
use Froxlor\Database\Database;
use Froxlor\Settings;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Michael Kaufmann <mkaufmann@nutime.de>
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
* 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.
*
* @link http://www.nutime.de/
* @since 0.9.16
* 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\Http\Php;
use Froxlor\Database\Database;
use Froxlor\Domain\Domain;
use Froxlor\FileDir;
use Froxlor\PhpHelper;
use Froxlor\Settings;
class Fpm
{
@@ -30,21 +39,21 @@ class Fpm
*
* @var array
*/
private $domain = array();
private $domain = [];
/**
* fpm config
*
* @var array
*/
private $fpm_cfg = array();
private $fpm_cfg = [];
/**
* Admin-Date cache array
*
* @var array
*/
private $admin_cache = array();
private $admin_cache = [];
/**
* defines what can be used for pool-config from php.ini
@@ -52,14 +61,14 @@ class Fpm
*
* @var array
*/
private $ini = array();
private $ini = [];
/**
* main constructor
*/
public function __construct($domain)
{
if (! isset($domain['fpm_config_id']) || empty($domain['fpm_config_id'])) {
if (!isset($domain['fpm_config_id']) || empty($domain['fpm_config_id'])) {
$domain['fpm_config_id'] = 1;
}
$this->domain = $domain;
@@ -67,22 +76,43 @@ class Fpm
$this->buildIniMapping();
}
private function readFpmConfig($fpm_config_id)
{
$stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "` WHERE `id` = :id");
$this->fpm_cfg = Database::pexecute_first($stmt, [
'id' => $fpm_config_id
]);
}
private function buildIniMapping()
{
$this->ini = array(
$this->ini = [
'php_flag' => explode("\n", Settings::Get('phpfpm.ini_flags')),
'php_value' => explode("\n", Settings::Get('phpfpm.ini_values')),
'php_admin_flag' => explode("\n", Settings::Get('phpfpm.ini_admin_flags')),
'php_admin_value' => explode("\n", Settings::Get('phpfpm.ini_admin_values'))
);
];
}
private function readFpmConfig($fpm_config_id)
/**
* create a dummy fpm pool config with minimal configuration
* (this is used whenever a config directory is empty but needs at least one pool to startup/restart)
*
* @param string $configdir
*/
public static function createDummyPool($configdir)
{
$stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "` WHERE `id` = :id");
$this->fpm_cfg = Database::pexecute_first($stmt, array(
'id' => $fpm_config_id
));
if (!is_dir($configdir)) {
FileDir::safe_exec('mkdir -p ' . escapeshellarg($configdir));
}
$config = FileDir::makeCorrectFile($configdir . '/dummy.conf');
$dummy = "[dummy]
user = " . Settings::Get('system.httpuser') . "
listen = /run/" . md5($configdir) . "-fpm.sock
pm = static
pm.max_children = 1
";
file_put_contents($config, $dummy);
}
/**
@@ -95,7 +125,6 @@ class Fpm
$fh = @fopen($this->getConfigFile(), 'w');
if ($fh) {
if ($phpconfig['override_fpmconfig'] == 1) {
$this->fpm_cfg['pm'] = $phpconfig['pm'];
$this->fpm_cfg['max_children'] = $phpconfig['max_children'];
@@ -108,12 +137,12 @@ class Fpm
}
$fpm_pm = $this->fpm_cfg['pm'];
$fpm_children = (int) $this->fpm_cfg['max_children'];
$fpm_start_servers = (int) $this->fpm_cfg['start_servers'];
$fpm_min_spare_servers = (int) $this->fpm_cfg['min_spare_servers'];
$fpm_max_spare_servers = (int) $this->fpm_cfg['max_spare_servers'];
$fpm_requests = (int) $this->fpm_cfg['max_requests'];
$fpm_process_idle_timeout = (int) $this->fpm_cfg['idle_timeout'];
$fpm_children = (int)$this->fpm_cfg['max_children'];
$fpm_start_servers = (int)$this->fpm_cfg['start_servers'];
$fpm_min_spare_servers = (int)$this->fpm_cfg['min_spare_servers'];
$fpm_max_spare_servers = (int)$this->fpm_cfg['max_spare_servers'];
$fpm_requests = (int)$this->fpm_cfg['max_requests'];
$fpm_process_idle_timeout = (int)$this->fpm_cfg['idle_timeout'];
$fpm_limit_extensions = $this->fpm_cfg['limit_extensions'];
$fpm_custom_config = $this->fpm_cfg['custom_config'];
@@ -173,21 +202,21 @@ class Fpm
if ($phpconfig['fpm_slowlog'] == '1') {
$fpm_config .= 'request_terminate_timeout = ' . $phpconfig['fpm_reqterm'] . "\n";
$fpm_config .= 'request_slowlog_timeout = ' . $phpconfig['fpm_reqslow'] . "\n";
$slowlog = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.logfiles_directory') . '/' . $this->domain['loginname'] . '-php-slow.log');
$slowlog = FileDir::makeCorrectFile(Settings::Get('system.logfiles_directory') . '/' . $this->domain['loginname'] . '-php-slow.log');
$fpm_config .= 'slowlog = ' . $slowlog . "\n";
$fpm_config .= 'catch_workers_output = yes' . "\n";
}
$fpm_config .= ';chroot = ' . \Froxlor\FileDir::makeCorrectDir($this->domain['documentroot']) . "\n";
$fpm_config .= ';chroot = ' . FileDir::makeCorrectDir($this->domain['documentroot']) . "\n";
$fpm_config .= 'security.limit_extensions = ' . $fpm_limit_extensions . "\n";
$tmpdir = \Froxlor\FileDir::makeCorrectDir(Settings::Get('phpfpm.tmpdir') . '/' . $this->domain['loginname'] . '/');
if (! is_dir($tmpdir)) {
$tmpdir = FileDir::makeCorrectDir(Settings::Get('phpfpm.tmpdir') . '/' . $this->domain['loginname'] . '/');
if (!is_dir($tmpdir)) {
$this->getTempDir();
}
$env_path = Settings::Get('phpfpm.envpath');
if (! empty($env_path)) {
if (!empty($env_path)) {
$fpm_config .= 'env[PATH] = ' . $env_path . "\n";
}
$fpm_config .= 'env[TMP] = ' . $tmpdir . "\n";
@@ -200,29 +229,29 @@ class Fpm
$_phpappendopenbasedir = '';
$_custom_openbasedir = explode(':', Settings::Get('phpfpm.peardir'));
foreach ($_custom_openbasedir as $cobd) {
$_phpappendopenbasedir .= \Froxlor\Domain\Domain::appendOpenBasedirPath($cobd);
$_phpappendopenbasedir .= Domain::appendOpenBasedirPath($cobd);
}
$_custom_openbasedir = explode(':', Settings::Get('system.phpappendopenbasedir'));
foreach ($_custom_openbasedir as $cobd) {
$_phpappendopenbasedir .= \Froxlor\Domain\Domain::appendOpenBasedirPath($cobd);
$_phpappendopenbasedir .= Domain::appendOpenBasedirPath($cobd);
}
if ($this->domain['openbasedir_path'] == '0' && strstr($this->domain['documentroot'], ":") === false) {
$openbasedir = \Froxlor\Domain\Domain::appendOpenBasedirPath($this->domain['documentroot'], true);
$openbasedir = Domain::appendOpenBasedirPath($this->domain['documentroot'], true);
} else {
$openbasedir = \Froxlor\Domain\Domain::appendOpenBasedirPath($this->domain['customerroot'], true);
$openbasedir = Domain::appendOpenBasedirPath($this->domain['customerroot'], true);
}
$openbasedir .= \Froxlor\Domain\Domain::appendOpenBasedirPath($this->getTempDir());
$openbasedir .= Domain::appendOpenBasedirPath($this->getTempDir());
$openbasedir .= $_phpappendopenbasedir;
}
}
$fpm_config .= 'php_admin_value[upload_tmp_dir] = ' . \Froxlor\FileDir::makeCorrectDir(Settings::Get('phpfpm.tmpdir') . '/' . $this->domain['loginname'] . '/') . "\n";
$fpm_config .= 'php_admin_value[upload_tmp_dir] = ' . FileDir::makeCorrectDir(Settings::Get('phpfpm.tmpdir') . '/' . $this->domain['loginname'] . '/') . "\n";
$admin = $this->getAdminData($this->domain['adminid']);
$php_ini_variables = array(
$php_ini_variables = [
'SAFE_MODE' => 'Off', // keep this for compatibility, just in case
'PEAR_DIR' => Settings::Get('phpfpm.peardir'),
'TMP_DIR' => $this->getTempDir(),
@@ -234,11 +263,11 @@ class Fpm
'OPEN_BASEDIR' => $openbasedir,
'OPEN_BASEDIR_C' => '',
'OPEN_BASEDIR_GLOBAL' => Settings::Get('system.phpappendopenbasedir'),
'DOCUMENT_ROOT' => \Froxlor\FileDir::makeCorrectDir($this->domain['documentroot']),
'CUSTOMER_HOMEDIR' => \Froxlor\FileDir::makeCorrectDir($this->domain['customerroot'])
);
'DOCUMENT_ROOT' => FileDir::makeCorrectDir($this->domain['documentroot']),
'CUSTOMER_HOMEDIR' => FileDir::makeCorrectDir($this->domain['customerroot'])
];
$phpini = \Froxlor\PhpHelper::replaceVariables($phpconfig['phpsettings'], $php_ini_variables);
$phpini = PhpHelper::replaceVariables($phpconfig['phpsettings'], $php_ini_variables);
$phpini_array = explode("\n", $phpini);
$fpm_config .= "\n\n";
@@ -270,9 +299,9 @@ class Fpm
}
// append custom phpfpm configuration
if (! empty($fpm_custom_config)) {
if (!empty($fpm_custom_config)) {
$fpm_config .= "\n; Custom Configuration\n";
$fpm_config .= \Froxlor\PhpHelper::replaceVariables($fpm_custom_config, $php_ini_variables);
$fpm_config .= PhpHelper::replaceVariables($fpm_custom_config, $php_ini_variables);
}
fwrite($fh, $fpm_config, strlen($fpm_config));
@@ -280,6 +309,91 @@ class Fpm
}
}
/**
* fpm-config file
*
* @param boolean $createifnotexists
* create the directory if it does not exist
*
* @return string the full path to the file
*/
public function getConfigFile($createifnotexists = true)
{
$configdir = $this->fpm_cfg['config_dir'];
$config = FileDir::makeCorrectFile($configdir . '/' . $this->domain['domain'] . '.conf');
if (!is_dir($configdir) && $createifnotexists) {
FileDir::safe_exec('mkdir -p ' . escapeshellarg($configdir));
}
return $config;
}
/**
* return path of fpm-socket file
*
* @param boolean $createifnotexists
* create the directory if it does not exist
*
* @return string the full path to the socket
*/
public function getSocketFile($createifnotexists = true)
{
$socketdir = FileDir::makeCorrectDir(Settings::Get('phpfpm.fastcgi_ipcdir'));
// add fpm-config-id to filename so it's unique for the fpm-daemon and doesn't interfere with running configs when reuilding
$socket = strtolower(FileDir::makeCorrectFile($socketdir . '/' . $this->domain['fpm_config_id'] . '-' . $this->domain['loginname'] . '-' . $this->domain['domain'] . '-php-fpm.socket'));
if (!is_dir($socketdir) && $createifnotexists) {
FileDir::safe_exec('mkdir -p ' . escapeshellarg($socketdir));
FileDir::safe_exec('chown -R ' . Settings::Get('system.httpuser') . ':' . Settings::Get('system.httpgroup') . ' ' . escapeshellarg($socketdir));
}
return $socket;
}
/**
* fpm-temp directory
*
* @param boolean $createifnotexists
* create the directory if it does not exist
*
* @return string the directory
*/
public function getTempDir($createifnotexists = true)
{
$tmpdir = FileDir::makeCorrectDir(Settings::Get('phpfpm.tmpdir') . '/' . $this->domain['loginname'] . '/');
if (!is_dir($tmpdir) && $createifnotexists) {
FileDir::safe_exec('mkdir -p ' . escapeshellarg($tmpdir));
FileDir::safe_exec('chown -R ' . $this->domain['guid'] . ':' . $this->domain['guid'] . ' ' . escapeshellarg($tmpdir));
FileDir::safe_exec('chmod 0750 ' . escapeshellarg($tmpdir));
}
return $tmpdir;
}
/**
* return the admin-data of a specific admin
*
* @param int $adminid
* id of the admin-user
*
* @return array
*/
private function getAdminData($adminid)
{
$adminid = intval($adminid);
if (!isset($this->admin_cache[$adminid])) {
$stmt = Database::prepare("
SELECT `email`, `loginname` FROM `" . TABLE_PANEL_ADMINS . "` WHERE `adminid` = :id");
$this->admin_cache[$adminid] = Database::pexecute_first($stmt, [
'id' => $adminid
]);
}
return $this->admin_cache[$adminid];
}
/**
* this is done via createConfig as php-fpm defines
* the ini-values/flags in its pool-config
@@ -291,134 +405,27 @@ class Fpm
return;
}
/**
* fpm-config file
*
* @param boolean $createifnotexists
* create the directory if it does not exist
*
* @return string the full path to the file
*/
public function getConfigFile($createifnotexists = true)
{
$configdir = $this->fpm_cfg['config_dir'];
$config = \Froxlor\FileDir::makeCorrectFile($configdir . '/' . $this->domain['domain'] . '.conf');
if (! is_dir($configdir) && $createifnotexists) {
\Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg($configdir));
}
return $config;
}
/**
* return path of fpm-socket file
*
* @param boolean $createifnotexists
* create the directory if it does not exist
*
* @return string the full path to the socket
*/
public function getSocketFile($createifnotexists = true)
{
$socketdir = \Froxlor\FileDir::makeCorrectDir(Settings::Get('phpfpm.fastcgi_ipcdir'));
// add fpm-config-id to filename so it's unique for the fpm-daemon and doesn't interfere with running configs when reuilding
$socket = strtolower(\Froxlor\FileDir::makeCorrectFile($socketdir . '/' . $this->domain['fpm_config_id'] . '-' . $this->domain['loginname'] . '-' . $this->domain['domain'] . '-php-fpm.socket'));
if (! is_dir($socketdir) && $createifnotexists) {
\Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg($socketdir));
\Froxlor\FileDir::safe_exec('chown -R ' . Settings::Get('system.httpuser') . ':' . Settings::Get('system.httpgroup') . ' ' . escapeshellarg($socketdir));
}
return $socket;
}
/**
* fpm-temp directory
*
* @param boolean $createifnotexists
* create the directory if it does not exist
*
* @return string the directory
*/
public function getTempDir($createifnotexists = true)
{
$tmpdir = \Froxlor\FileDir::makeCorrectDir(Settings::Get('phpfpm.tmpdir') . '/' . $this->domain['loginname'] . '/');
if (! is_dir($tmpdir) && $createifnotexists) {
\Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg($tmpdir));
\Froxlor\FileDir::safe_exec('chown -R ' . $this->domain['guid'] . ':' . $this->domain['guid'] . ' ' . escapeshellarg($tmpdir));
\Froxlor\FileDir::safe_exec('chmod 0750 ' . escapeshellarg($tmpdir));
}
return $tmpdir;
}
/**
* fastcgi-fakedirectory directory
*
* @param boolean $createifnotexists
* create the directory if it does not exist
* create the directory if it does not exist
*
* @return string the directory
*/
public function getAliasConfigDir($createifnotexists = true)
{
// ensure default...
if (Settings::Get('phpfpm.aliasconfigdir') == null) {
Settings::Set('phpfpm.aliasconfigdir', '/var/www/php-fpm');
}
$configdir = \Froxlor\FileDir::makeCorrectDir(Settings::Get('phpfpm.aliasconfigdir') . '/' . $this->domain['loginname'] . '/' . $this->domain['domain'] . '/');
if (! is_dir($configdir) && $createifnotexists) {
\Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg($configdir));
\Froxlor\FileDir::safe_exec('chown ' . $this->domain['guid'] . ':' . $this->domain['guid'] . ' ' . escapeshellarg($configdir));
$configdir = FileDir::makeCorrectDir(Settings::Get('phpfpm.aliasconfigdir') . '/' . $this->domain['loginname'] . '/' . $this->domain['domain'] . '/');
if (!is_dir($configdir) && $createifnotexists) {
FileDir::safe_exec('mkdir -p ' . escapeshellarg($configdir));
FileDir::safe_exec('chown ' . $this->domain['guid'] . ':' . $this->domain['guid'] . ' ' . escapeshellarg($configdir));
}
return $configdir;
}
/**
* create a dummy fpm pool config with minimal configuration
* (this is used whenever a config directory is empty but needs at least one pool to startup/restart)
*
* @param string $configdir
*/
public static function createDummyPool($configdir)
{
if (! is_dir($configdir)) {
\Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg($configdir));
}
$config = \Froxlor\FileDir::makeCorrectFile($configdir . '/dummy.conf');
$dummy = "[dummy]
user = " . Settings::Get('system.httpuser') . "
listen = /run/" . md5($configdir) . "-fpm.sock
pm = static
pm.max_children = 1
";
file_put_contents($config, $dummy);
}
/**
* return the admin-data of a specific admin
*
* @param int $adminid
* id of the admin-user
*
* @return array
*/
private function getAdminData($adminid)
{
$adminid = intval($adminid);
if (! isset($this->admin_cache[$adminid])) {
$stmt = Database::prepare("
SELECT `email`, `loginname` FROM `" . TABLE_PANEL_ADMINS . "` WHERE `adminid` = :id");
$this->admin_cache[$adminid] = Database::pexecute_first($stmt, array(
'id' => $adminid
));
}
return $this->admin_cache[$adminid];
}
}

View File

@@ -1,27 +1,33 @@
<?php
namespace Froxlor\Cron\Http\Php;
use Froxlor\Database\Database;
use Froxlor\Settings;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Michael Kaufmann <mkaufmann@nutime.de>
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
* @link http://www.nutime.de/
* @since 0.9.16
*
* 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\Http\Php;
use Froxlor\Database\Database;
use Froxlor\Settings;
class PhpInterface
{
@@ -30,7 +36,7 @@ class PhpInterface
*
* @var array
*/
private $domain = array();
private $domain = [];
/**
* Interface object
@@ -44,7 +50,7 @@ class PhpInterface
*
* @var array
*/
private $admin_cache = array();
private $admin_cache = [];
/**
* main constructor
@@ -55,6 +61,21 @@ class PhpInterface
$this->setInterface();
}
/**
* set interface-object by type of
* php-interface: fcgid or php-fpm
* sets private $_interface variable
*/
private function setInterface()
{
// php-fpm
if ((int)Settings::Get('phpfpm.enabled') == 1) {
$this->interface = new Fpm($this->domain);
} elseif ((int)Settings::Get('system.mod_fcgid') == 1) {
$this->interface = new Fcgid($this->domain);
}
}
/**
* returns the interface-object
* from where we can control it
@@ -64,27 +85,12 @@ class PhpInterface
return $this->interface;
}
/**
* set interface-object by type of
* php-interface: fcgid or php-fpm
* sets private $_interface variable
*/
private function setInterface()
{
// php-fpm
if ((int) Settings::Get('phpfpm.enabled') == 1) {
$this->interface = new Fpm($this->domain);
} elseif ((int) Settings::Get('system.mod_fcgid') == 1) {
$this->interface = new Fcgid($this->domain);
}
}
/**
* return the php-configuration from the database
*
* @param int $php_config_id
* id of the php-configuration
*
* id of the php-configuration
*
* @return array
*/
public function getPhpConfig($php_config_id)
@@ -96,18 +102,18 @@ class PhpInterface
$php_config_id = 1;
}
if (! isset($this->php_configs_cache[$php_config_id])) {
if (!isset($this->php_configs_cache[$php_config_id])) {
$stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `id` = :id");
$this->_php_configs_cache[$php_config_id] = Database::pexecute_first($stmt, array(
$this->_php_configs_cache[$php_config_id] = Database::pexecute_first($stmt, [
'id' => $php_config_id
));
if ((int) Settings::Get('phpfpm.enabled') == 1) {
]);
if ((int)Settings::Get('phpfpm.enabled') == 1) {
$stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "` WHERE `id` = :id");
$this->_php_configs_cache[$php_config_id]['fpm_settings'] = Database::pexecute_first($stmt, array(
$this->_php_configs_cache[$php_config_id]['fpm_settings'] = Database::pexecute_first($stmt, [
'id' => $this->_php_configs_cache[$php_config_id]['fpmsettingid']
));
]);
// override fpm daemon settings if set in php-config
if ($this->_php_configs_cache[$php_config_id]['override_fpmconfig'] == 1) {
$this->_php_configs_cache[$php_config_id]['fpm_settings']['limit_extensions'] = $this->_php_configs_cache[$php_config_id]['limit_extensions'];

View File

@@ -1,26 +1,35 @@
<?php
namespace Froxlor\Cron\Http;
use Froxlor\Database\Database;
use Froxlor\Settings;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Michael Kaufmann <mkaufmann@nutime.de>
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
* @since 0.9.31
*
* 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\Http;
use Froxlor\Database\Database;
use Froxlor\Domain\Domain;
use Froxlor\Settings;
use PDO;
class WebserverBase
{
@@ -64,9 +73,8 @@ class WebserverBase
WHERE p.id = :phpconfigid
");
$domains = array();
while ($domain = $result_domains_stmt->fetch(\PDO::FETCH_ASSOC)) {
$domains = [];
while ($domain = $result_domains_stmt->fetch(PDO::FETCH_ASSOC)) {
// set whole domain
$domains[$domain['domain']] = $domain;
// set empty-defaults for non-ssl
@@ -78,11 +86,10 @@ class WebserverBase
// now, if the domain has an ssl ip/port assigned, get
// the corresponding information from the db
if (\Froxlor\Domain\Domain::domainHasSslIpPort($domain['id'])) {
$ssl_ip = Database::pexecute_first($ip_stmt, array(
if (Domain::domainHasSslIpPort($domain['id'])) {
$ssl_ip = Database::pexecute_first($ip_stmt, [
'domainid' => $domain['id']
));
]);
// set ssl info for domain
$domains[$domain['domain']]['ssl'] = '1';
@@ -93,11 +100,10 @@ class WebserverBase
}
// read fpm-config-id if using fpm
if ((int) Settings::Get('phpfpm.enabled') == 1) {
$fpm_config = Database::pexecute_first($fpm_sel_stmt, array(
if ((int)Settings::Get('phpfpm.enabled') == 1) {
$fpm_config = Database::pexecute_first($fpm_sel_stmt, [
'phpconfigid' => $domain['phpsettingid']
));
]);
if ($fpm_config) {
$domains[$domain['domain']]['fpm_config_id'] = $fpm_config['id'];
} else {

View File

@@ -1,23 +1,41 @@
<?php
namespace Froxlor\Cron;
use Froxlor\Database\Database;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
* 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
*/
class MasterCron extends \Froxlor\Cron\FroxlorCron
namespace Froxlor\Cron;
use Exception;
use Froxlor\Cron\System\Extrausers;
use Froxlor\Database\Database;
use Froxlor\FileDir;
use Froxlor\Froxlor;
use Froxlor\FroxlorLogger;
use Froxlor\Settings;
use Froxlor\System\Cronjob;
use PDO;
class MasterCron extends FroxlorCron
{
private static $argv = null;
@@ -40,7 +58,7 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
{
self::init();
$jobs_to_run = array();
$jobs_to_run = [];
$argv = self::$argv;
/**
@@ -64,20 +82,20 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
* --force to include cron_tasks even if it's not its turn
* --debug to output debug information
*/
for ($x = 1; $x < count($argv); $x ++) {
for ($x = 1; $x < count($argv); $x++) {
// check argument
if (isset($argv[$x])) {
// --force
if (strtolower($argv[$x]) == '--force') {
// really force re-generating of config-files by
// inserting task 1
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
Cronjob::inserttask(TaskId::REBUILD_VHOST);
// bind (if enabled, \Froxlor\System\Cronjob::inserttask() checks this)
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
Cronjob::inserttask(TaskId::REBUILD_DNS);
// set quotas (if enabled)
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_QUOTA);
Cronjob::inserttask(TaskId::CREATE_QUOTA);
// also regenerate cron.d-file
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_CRON);
Cronjob::inserttask(TaskId::REBUILD_CRON);
array_push($jobs_to_run, 'tasks');
define('CRON_IS_FORCED', 1);
} elseif (strtolower($argv[$x]) == '--debug') {
@@ -85,8 +103,8 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
} elseif (strtolower($argv[$x]) == '--no-fork') {
define('CRON_NOFORK_FLAG', 1);
} elseif (strtolower($argv[$x]) == '--run-task') {
if (isset($argv[$x+1]) && in_array($argv[$x+1], [1,4,10,99])) {
\Froxlor\System\Cronjob::inserttask($argv[$x+1]);
if (isset($argv[$x + 1]) && in_array($argv[$x + 1], [1, 4, 10, 99])) {
Cronjob::inserttask($argv[$x + 1]);
array_push($jobs_to_run, 'tasks');
} else {
echo "Invalid argument for --run-task\n";
@@ -106,14 +124,14 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
self::$cronlog->setCronDebugFlag(defined('CRON_DEBUG_FLAG'));
$tasks_cnt_stmt = \Froxlor\Database\Database::query("SELECT COUNT(*) as jobcnt FROM `panel_tasks`");
$tasks_cnt = $tasks_cnt_stmt->fetch(\PDO::FETCH_ASSOC);
$tasks_cnt_stmt = Database::query("SELECT COUNT(*) as jobcnt FROM `panel_tasks`");
$tasks_cnt = $tasks_cnt_stmt->fetch(PDO::FETCH_ASSOC);
// do we have anything to include?
if (count($jobs_to_run) > 0) {
// include all jobs we want to execute
foreach ($jobs_to_run as $cron) {
\Froxlor\System\Cronjob::updateLastRunOfCron($cron);
Cronjob::updateLastRunOfCron($cron);
$cronfile = self::getCronModule($cron);
if ($cronfile && class_exists($cronfile)) {
$cronfile::run();
@@ -127,33 +145,13 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
* in case the admin installed new software which added a new user
* so users in the database don't conflict with system users
*/
self::$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Checking system\'s last guid');
\Froxlor\System\Cronjob::checkLastGuid();
self::$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Checking system\'s last guid');
Cronjob::checkLastGuid();
// shutdown cron
self::shutdown();
}
private static function refreshUsers($jobcount = 0)
{
if ($jobcount > 0) {
if (\Froxlor\Settings::Get('system.nssextrausers') == 1) {
\Froxlor\Cron\System\Extrausers::generateFiles(self::$cronlog);
}
// clear NSCD cache if using fcgid or fpm, #1570 - not needed for nss-extrausers
if ((\Froxlor\Settings::Get('system.mod_fcgid') == 1 || (int) \Froxlor\Settings::Get('phpfpm.enabled') == 1) && \Froxlor\Settings::Get('system.nssextrausers') == 0) {
$false_val = false;
\Froxlor\FileDir::safe_exec('nscd -i passwd 1> /dev/null', $false_val, array(
'>'
));
\Froxlor\FileDir::safe_exec('nscd -i group 1> /dev/null', $false_val, array(
'>'
));
}
}
}
private static function init()
{
if (@php_sapi_name() != 'cli' && @php_sapi_name() != 'cgi' && @php_sapi_name() != 'cgi-fcgi') {
@@ -168,8 +166,8 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
$basename = basename($_SERVER['PHP_SELF'], '.php');
$crontype = "";
if (isset(self::$argv) && is_array(self::$argv) && count(self::$argv) > 1) {
for ($x = 1; $x < count(self::$argv); $x ++) {
if (substr(self::$argv[$x], 0, 2) == '--' && strlen(self::$argv[$x]) > 3 && !in_array(substr(strtolower(self::$argv[$x]), 2),self::$noncron_params)) {
for ($x = 1; $x < count(self::$argv); $x++) {
if (substr(self::$argv[$x], 0, 2) == '--' && strlen(self::$argv[$x]) > 3 && !in_array(substr(strtolower(self::$argv[$x]), 2), self::$noncron_params)) {
$crontype = substr(strtolower(self::$argv[$x]), 2);
$basename .= "-" . $crontype;
break;
@@ -185,41 +183,41 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
// create and open the lockfile!
self::$debugHandler = fopen($lockfile, 'w');
fwrite(self::$debugHandler, 'Setting Lockfile to ' . $lockfile . "\n");
fwrite(self::$debugHandler, 'Setting Froxlor installation path to ' . \Froxlor\Froxlor::getInstallDir() . "\n");
fwrite(self::$debugHandler, 'Setting Froxlor installation path to ' . Froxlor::getInstallDir() . "\n");
if (! file_exists(\Froxlor\Froxlor::getInstallDir() . '/lib/userdata.inc.php')) {
if (!file_exists(Froxlor::getInstallDir() . '/lib/userdata.inc.php')) {
die("Froxlor does not seem to be installed yet - skipping cronjob");
}
$sql = array();
$sql_root = array();
$sql = [];
$sql_root = [];
// Includes the Usersettings eg. MySQL-Username/Passwort etc.
require \Froxlor\Froxlor::getInstallDir() . '/lib/userdata.inc.php';
require Froxlor::getInstallDir() . '/lib/userdata.inc.php';
fwrite(self::$debugHandler, 'Userdatas included' . "\n");
// Legacy sql-root-information
if (isset($sql['root_user']) && isset($sql['root_password']) && (! isset($sql_root) || ! is_array($sql_root))) {
$sql_root = array(
0 => array(
if (isset($sql['root_user']) && isset($sql['root_password']) && (!isset($sql_root) || !is_array($sql_root))) {
$sql_root = [
0 => [
'caption' => 'Default',
'host' => $sql['host'],
'user' => $sql['root_user'],
'password' => $sql['root_password']
)
);
]
];
unset($sql['root_user']);
unset($sql['root_password']);
}
// Includes the MySQL-Tabledefinitions etc.
require \Froxlor\Froxlor::getInstallDir() . '/lib/tables.inc.php';
require Froxlor::getInstallDir() . '/lib/tables.inc.php';
fwrite(self::$debugHandler, 'Table definitions included' . "\n");
// try database connection, it will throw
// and exception itself if failed
try {
\Froxlor\Database\Database::query("SELECT 1");
} catch (\Exception $e) {
Database::query("SELECT 1");
} catch (Exception $e) {
// Do not proceed further if no database connection could be established
fclose(self::$debugHandler);
unlink($lockfile);
@@ -232,7 +230,6 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
$lockDirHandle = opendir($lockdir);
while ($fName = readdir($lockDirHandle)) {
if ($lockFilename == substr($fName, 0, strlen($lockFilename)) && $lockfName != $fName) {
// Check if last run jailed out with an exception
$croncontent = file($lockdir . $fName);
@@ -241,13 +238,13 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
if ($lastline == '=== Keep lockfile because of exception ===') {
fclose(self::$debugHandler);
unlink($lockfile);
\Froxlor\System\Cronjob::dieWithMail('Last cron jailed out with an exception. Exiting...' . "\n" . 'Take a look into the contents of ' . $lockdir . $fName . '* for more information!' . "\n");
Cronjob::dieWithMail('Last cron jailed out with an exception. Exiting...' . "\n" . 'Take a look into the contents of ' . $lockdir . $fName . '* for more information!' . "\n");
}
// Check if cron is running or has died.
$check_pid = substr(strrchr($fName, "-"), 1);
$check_pid_return = null;
system("kill -CHLD " . (int) $check_pid . " 1> /dev/null 2> /dev/null", $check_pid_return);
system("kill -CHLD " . (int)$check_pid . " 1> /dev/null 2> /dev/null", $check_pid_return);
if ($check_pid_return == 1) {
// Result: Existing lockfile/pid isn't running
@@ -268,7 +265,7 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
// ... and delete it
unlink($lockfile);
\Froxlor\System\Cronjob::dieWithMail('There is already a Cronjob for ' . $crontype . ' in progress. Exiting...' . "\n" . 'Take a look into the contents of ' . $lockdir . $lockFilename . '* for more information!' . "\n");
Cronjob::dieWithMail('There is already a Cronjob for ' . $crontype . ' in progress. Exiting...' . "\n" . 'Take a look into the contents of ' . $lockdir . $lockFilename . '* for more information!' . "\n");
}
}
}
@@ -278,34 +275,34 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
* whether the permission of the files are still correct
*/
fwrite(self::$debugHandler, 'Checking froxlor file permissions' . "\n");
$_mypath = \Froxlor\FileDir::makeCorrectDir(\Froxlor\Froxlor::getInstallDir());
$_mypath = FileDir::makeCorrectDir(Froxlor::getInstallDir());
if (((int) \Froxlor\Settings::Get('system.mod_fcgid') == 1 && (int) \Froxlor\Settings::Get('system.mod_fcgid_ownvhost') == 1) || ((int) \Froxlor\Settings::Get('phpfpm.enabled') == 1 && (int) \Froxlor\Settings::Get('phpfpm.enabled_ownvhost') == 1)) {
$user = \Froxlor\Settings::Get('system.mod_fcgid_httpuser');
$group = \Froxlor\Settings::Get('system.mod_fcgid_httpgroup');
if (((int)Settings::Get('system.mod_fcgid') == 1 && (int)Settings::Get('system.mod_fcgid_ownvhost') == 1) || ((int)Settings::Get('phpfpm.enabled') == 1 && (int)Settings::Get('phpfpm.enabled_ownvhost') == 1)) {
$user = Settings::Get('system.mod_fcgid_httpuser');
$group = Settings::Get('system.mod_fcgid_httpgroup');
if (\Froxlor\Settings::Get('phpfpm.enabled') == 1) {
$user = \Froxlor\Settings::Get('phpfpm.vhost_httpuser');
$group = \Froxlor\Settings::Get('phpfpm.vhost_httpgroup');
if (Settings::Get('phpfpm.enabled') == 1) {
$user = Settings::Get('phpfpm.vhost_httpuser');
$group = Settings::Get('phpfpm.vhost_httpgroup');
}
// all the files and folders have to belong to the local user
// now because we also use fcgid for our own vhost
\Froxlor\FileDir::safe_exec('chown -R ' . $user . ':' . $group . ' ' . escapeshellarg($_mypath));
FileDir::safe_exec('chown -R ' . $user . ':' . $group . ' ' . escapeshellarg($_mypath));
} else {
// back to webserver permission
$user = \Froxlor\Settings::Get('system.httpuser');
$group = \Froxlor\Settings::Get('system.httpgroup');
\Froxlor\FileDir::safe_exec('chown -R ' . $user . ':' . $group . ' ' . escapeshellarg($_mypath));
$user = Settings::Get('system.httpuser');
$group = Settings::Get('system.httpgroup');
FileDir::safe_exec('chown -R ' . $user . ':' . $group . ' ' . escapeshellarg($_mypath));
}
// Initialize logging
self::$cronlog = \Froxlor\FroxlorLogger::getInstanceOf(array(
self::$cronlog = FroxlorLogger::getInstanceOf([
'loginname' => 'cronjob'
));
]);
fwrite(self::$debugHandler, 'Logger has been included' . "\n");
if (\Froxlor\Froxlor::hasUpdates() || \Froxlor\Froxlor::hasDbUpdates()) {
if (\Froxlor\Settings::Get('system.cron_allowautoupdate') == null || \Froxlor\Settings::Get('system.cron_allowautoupdate') == 0) {
if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) {
if (Settings::Get('system.cron_allowautoupdate') == null || Settings::Get('system.cron_allowautoupdate') == 0) {
/**
* Do not proceed further if the Database version is not the same as the script version
*/
@@ -313,26 +310,26 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
unlink($lockfile);
$errormessage = "Version of file doesn't match version of database. Exiting...\n\n";
$errormessage .= "Possible reason: Froxlor update\n";
$errormessage .= "Information: Current version in database: " . \Froxlor\Settings::Get('panel.version') . (! empty(\Froxlor\Froxlor::BRANDING) ? "-" . \Froxlor\Froxlor::BRANDING : "") . " (DB: " . \Froxlor\Settings::Get('panel.db_version') . ") - version of Froxlor files: " . \Froxlor\Froxlor::getVersionString() . ")\n";
$errormessage .= "Information: Current version in database: " . Settings::Get('panel.version') . (!empty(Froxlor::BRANDING) ? "-" . Froxlor::BRANDING : "") . " (DB: " . Settings::Get('panel.db_version') . ") - version of Froxlor files: " . Froxlor::getVersionString() . ")\n";
$errormessage .= "Solution: Please visit your Foxlor admin interface for further information.\n";
\Froxlor\System\Cronjob::dieWithMail($errormessage);
Cronjob::dieWithMail($errormessage);
}
if (\Froxlor\Settings::Get('system.cron_allowautoupdate') == 1) {
if (Settings::Get('system.cron_allowautoupdate') == 1) {
/**
* let's walk the walk - do the dangerous shit
*/
self::$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_WARNING, 'Automatic update is activated and we are going to proceed without any notices');
self::$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_WARNING, 'all new settings etc. will be stored with the default value, that might not always be right for your system!');
self::$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_WARNING, "If you don't want this to happen in the future consider removing the --allow-autoupdate flag from the cronjob");
self::$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, 'Automatic update is activated and we are going to proceed without any notices');
self::$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, 'all new settings etc. will be stored with the default value, that might not always be right for your system!');
self::$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "If you don't want this to happen in the future consider removing the --allow-autoupdate flag from the cronjob");
fwrite(self::$debugHandler, '*** WARNING *** - Automatic update is activated and we are going to proceed without any notices' . "\n");
fwrite(self::$debugHandler, '*** WARNING *** - all new settings etc. will be stored with the default value, that might not always be right for your system!' . "\n");
fwrite(self::$debugHandler, "*** WARNING *** - If you don't want this to happen in the future consider removing the --allow-autoupdate flag from the cronjob\n");
// including update procedures
define('_CRON_UPDATE', 1);
include_once \Froxlor\Froxlor::getInstallDir() . '/install/updatesql.php';
include_once Froxlor::getInstallDir() . '/install/updatesql.php';
// pew - everything went better than expected
self::$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_WARNING, 'Automatic update done - you should check your settings to be sure everything is fine');
self::$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, 'Automatic update done - you should check your settings to be sure everything is fine');
fwrite(self::$debugHandler, '*** WARNING *** - Automatic update done - you should check your settings to be sure everything is fine' . "\n");
}
}
@@ -340,35 +337,55 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
fwrite(self::$debugHandler, 'Froxlor version and database version are correct' . "\n");
}
private static function shutdown()
{
// check for cron.d-generation task and create it if necessary
\Froxlor\Cron\CronConfig::checkCrondConfigurationFile();
if (\Froxlor\Settings::Get('logger.log_cron') == '1') {
\Froxlor\FroxlorLogger::getInstanceOf()->setCronLog(0);
fwrite(self::$debugHandler, 'Logging for cron has been shutdown' . "\n");
}
fclose(self::$debugHandler);
if (\Froxlor\Settings::Get('system.debug_cron') != '1') {
unlink(self::getLockfile());
}
}
private static function getCronModule($cronname)
{
$upd_stmt = Database::prepare("
SELECT `cronclass` FROM `" . TABLE_PANEL_CRONRUNS . "` WHERE `cronfile` = :cron;
");
$cron = Database::pexecute_first($upd_stmt, array(
$cron = Database::pexecute_first($upd_stmt, [
'cron' => $cronname
));
]);
if ($cron) {
return $cron['cronclass'];
}
self::$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, "Requested cronjob '" . $cronname . "' could not be found.");
self::$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Requested cronjob '" . $cronname . "' could not be found.");
return false;
}
private static function refreshUsers($jobcount = 0)
{
if ($jobcount > 0) {
if (Settings::Get('system.nssextrausers') == 1) {
Extrausers::generateFiles(self::$cronlog);
}
// clear NSCD cache if using fcgid or fpm, #1570 - not needed for nss-extrausers
if ((Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) && Settings::Get('system.nssextrausers') == 0) {
$false_val = false;
FileDir::safe_exec('nscd -i passwd 1> /dev/null', $false_val, [
'>'
]);
FileDir::safe_exec('nscd -i group 1> /dev/null', $false_val, [
'>'
]);
}
}
}
private static function shutdown()
{
// check for cron.d-generation task and create it if necessary
CronConfig::checkCrondConfigurationFile();
if (Settings::Get('logger.log_cron') == '1') {
FroxlorLogger::getInstanceOf()->setCronLog(0);
fwrite(self::$debugHandler, 'Logging for cron has been shutdown' . "\n");
}
fclose(self::$debugHandler);
if (Settings::Get('system.debug_cron') != '1') {
unlink(self::getLockfile());
}
}
}

View File

@@ -1,35 +1,44 @@
<?php
namespace Froxlor\Cron\System;
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\FroxlorLogger;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2016 the Froxlor Team (see authors).
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Michael Kaufmann <mkaufmann@nutime.de>
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
* 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.
*
* @since 0.9.35.1
* 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
*/
class BackupCron extends \Froxlor\Cron\FroxlorCron
namespace Froxlor\Cron\System;
use Froxlor\Cron\FroxlorCron;
use Froxlor\Database\Database;
use Froxlor\FileDir;
use Froxlor\FroxlorLogger;
use Froxlor\Settings;
class BackupCron extends FroxlorCron
{
public static function run()
{
// Check Traffic-Lock
if (function_exists('pcntl_fork')) {
$BackupLock = \Froxlor\FileDir::makeCorrectFile(dirname(self::getLockfile()) . "/froxlor_cron_backup.lock");
$BackupLock = FileDir::makeCorrectFile(dirname(self::getLockfile()) . "/froxlor_cron_backup.lock");
if (file_exists($BackupLock) && is_numeric($BackupPid = file_get_contents($BackupLock))) {
if (function_exists('posix_kill')) {
$BackupPidStatus = @posix_kill($BackupPid, 0);
@@ -38,7 +47,7 @@ class BackupCron extends \Froxlor\Cron\FroxlorCron
$BackupPidStatus = !$BackupPidStatus;
}
if ($BackupPidStatus) {
FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Backup run already in progress');
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Backup run already in progress');
return 1;
}
}
@@ -66,10 +75,10 @@ class BackupCron extends \Froxlor\Cron\FroxlorCron
} else {
$msg = "PHP compiled without pcntl.";
}
FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_WARNING, $msg . " Not forking backup-cron, this may take a long time!");
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, $msg . " Not forking backup-cron, this may take a long time!");
}
FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'BackupCron: started - creating customer backup');
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'BackupCron: started - creating customer backup');
$result_tasks_stmt = Database::query("
SELECT * FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = '20' ORDER BY `id` ASC
@@ -80,21 +89,19 @@ class BackupCron extends \Froxlor\Cron\FroxlorCron
$cronlog = FroxlorLogger::getInstanceOf();
$all_jobs = $result_tasks_stmt->fetchAll();
foreach ($all_jobs as $row) {
if ($row['data'] != '') {
$row['data'] = json_decode($row['data'], true);
}
if (is_array($row['data'])) {
if (isset($row['data']['customerid']) && isset($row['data']['loginname']) && isset($row['data']['destdir'])) {
$row['data']['destdir'] = \Froxlor\FileDir::makeCorrectDir($row['data']['destdir']);
$customerdocroot = \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.documentroot_prefix') . '/' . $row['data']['loginname'] . '/');
$row['data']['destdir'] = FileDir::makeCorrectDir($row['data']['destdir']);
$customerdocroot = FileDir::makeCorrectDir(Settings::Get('system.documentroot_prefix') . '/' . $row['data']['loginname'] . '/');
// create folder if not exists
if (! file_exists($row['data']['destdir']) && $row['data']['destdir'] != '/' && $row['data']['destdir'] != Settings::Get('system.documentroot_prefix') && $row['data']['destdir'] != $customerdocroot) {
FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Creating backup-destination path for customer: ' . escapeshellarg($row['data']['destdir']));
\Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg($row['data']['destdir']));
if (!file_exists($row['data']['destdir']) && $row['data']['destdir'] != '/' && $row['data']['destdir'] != Settings::Get('system.documentroot_prefix') && $row['data']['destdir'] != $customerdocroot) {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Creating backup-destination path for customer: ' . escapeshellarg($row['data']['destdir']));
FileDir::safe_exec('mkdir -p ' . escapeshellarg($row['data']['destdir']));
}
self::createCustomerBackup($row['data'], $customerdocroot, $cronlog);
@@ -102,9 +109,9 @@ class BackupCron extends \Froxlor\Cron\FroxlorCron
}
// remove entry
Database::pexecute($del_stmt, array(
Database::pexecute($del_stmt, [
'id' => $row['id']
));
]);
}
if (function_exists('pcntl_fork')) {
@@ -123,27 +130,26 @@ class BackupCron extends \Froxlor\Cron\FroxlorCron
*/
private static function createCustomerBackup($data = null, $customerdocroot = null, &$cronlog = null)
{
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Creating Backup for user "' . $data['loginname'] . '"');
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Creating Backup for user "' . $data['loginname'] . '"');
// create tmp folder
$tmpdir = \Froxlor\FileDir::makeCorrectDir($data['destdir'] . '/.tmp/');
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'Creating tmp-folder "' . $tmpdir . '"');
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> mkdir -p ' . escapeshellarg($tmpdir));
\Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg($tmpdir));
$tmpdir = FileDir::makeCorrectDir($data['destdir'] . '/.tmp/');
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'Creating tmp-folder "' . $tmpdir . '"');
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> mkdir -p ' . escapeshellarg($tmpdir));
FileDir::safe_exec('mkdir -p ' . escapeshellarg($tmpdir));
$create_backup_tar_data = "";
// MySQL databases
if ($data['backup_dbs'] == 1) {
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'Creating mysql-folder "' . \Froxlor\FileDir::makeCorrectDir($tmpdir . '/mysql') . '"');
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> mkdir -p ' . escapeshellarg(\Froxlor\FileDir::makeCorrectDir($tmpdir . '/mysql')));
\Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg(\Froxlor\FileDir::makeCorrectDir($tmpdir . '/mysql')));
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'Creating mysql-folder "' . FileDir::makeCorrectDir($tmpdir . '/mysql') . '"');
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> mkdir -p ' . escapeshellarg(FileDir::makeCorrectDir($tmpdir . '/mysql')));
FileDir::safe_exec('mkdir -p ' . escapeshellarg(FileDir::makeCorrectDir($tmpdir . '/mysql')));
// get all customer database-names
$sel_stmt = Database::prepare("SELECT `databasename` FROM `" . TABLE_PANEL_DATABASES . "` WHERE `customerid` = :cid");
Database::pexecute($sel_stmt, array(
Database::pexecute($sel_stmt, [
'cid' => $data['customerid']
));
]);
Database::needRoot(true);
Database::needSqlData();
@@ -152,11 +158,11 @@ class BackupCron extends \Froxlor\Cron\FroxlorCron
$has_dbs = false;
while ($row = $sel_stmt->fetch()) {
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> mysqldump -u ' . escapeshellarg($sql_root['user']) . ' -pXXXXX ' . $row['databasename'] . ' > ' . \Froxlor\FileDir::makeCorrectFile($tmpdir . '/mysql/' . $row['databasename'] . '_' . date('YmdHi', time()) . '.sql'));
$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;
\Froxlor\FileDir::safe_exec('mysqldump -u ' . escapeshellarg($sql_root['user']) . ' -p' . $sql_root['passwd'] . ' ' . $row['databasename'] . ' > ' . \Froxlor\FileDir::makeCorrectFile($tmpdir . '/mysql/' . $row['databasename'] . '_' . date('YmdHi', time()) . '.sql'), $bool_false, array(
FileDir::safe_exec('mysqldump -u ' . escapeshellarg($sql_root['user']) . ' -p' . $sql_root['passwd'] . ' ' . $row['databasename'] . ' > ' . FileDir::makeCorrectFile($tmpdir . '/mysql/' . $row['databasename'] . '_' . date('YmdHi', time()) . '.sql'), $bool_false, [
'>'
));
]);
$has_dbs = true;
}
@@ -169,15 +175,14 @@ class BackupCron extends \Froxlor\Cron\FroxlorCron
// E-mail data
if ($data['backup_mail'] == 1) {
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'Creating mail-folder "' . \Froxlor\FileDir::makeCorrectDir($tmpdir . '/mail') . '"');
\Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg(\Froxlor\FileDir::makeCorrectDir($tmpdir . '/mail')));
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'Creating mail-folder "' . FileDir::makeCorrectDir($tmpdir . '/mail') . '"');
FileDir::safe_exec('mkdir -p ' . escapeshellarg(FileDir::makeCorrectDir($tmpdir . '/mail')));
// get all customer mail-accounts
$sel_stmt = Database::prepare("SELECT `homedir`, `maildir` FROM `" . TABLE_MAIL_USERS . "` WHERE `customerid` = :cid");
Database::pexecute($sel_stmt, array(
Database::pexecute($sel_stmt, [
'cid' => $data['customerid']
));
]);
$tar_file_list = "";
$mail_homedir = "";
@@ -186,38 +191,37 @@ class BackupCron extends \Froxlor\Cron\FroxlorCron
$mail_homedir = $row['homedir'];
}
if (! empty($tar_file_list)) {
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> tar cfvz ' . escapeshellarg(\Froxlor\FileDir::makeCorrectFile($tmpdir . '/mail/' . $data['loginname'] . '-mail.tar.gz')) . ' -C ' . escapeshellarg($mail_homedir) . ' ' . trim($tar_file_list));
\Froxlor\FileDir::safe_exec('tar cfz ' . escapeshellarg(\Froxlor\FileDir::makeCorrectFile($tmpdir . '/mail/' . $data['loginname'] . '-mail.tar.gz')) . ' -C ' . escapeshellarg($mail_homedir) . ' ' . trim($tar_file_list));
if (!empty($tar_file_list)) {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> tar cfvz ' . escapeshellarg(FileDir::makeCorrectFile($tmpdir . '/mail/' . $data['loginname'] . '-mail.tar.gz')) . ' -C ' . escapeshellarg($mail_homedir) . ' ' . trim($tar_file_list));
FileDir::safe_exec('tar cfz ' . escapeshellarg(FileDir::makeCorrectFile($tmpdir . '/mail/' . $data['loginname'] . '-mail.tar.gz')) . ' -C ' . escapeshellarg($mail_homedir) . ' ' . trim($tar_file_list));
$create_backup_tar_data .= './mail ';
}
}
// Web data
if ($data['backup_web'] == 1) {
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'Creating web-folder "' . \Froxlor\FileDir::makeCorrectDir($tmpdir . '/web') . '"');
\Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg(\Froxlor\FileDir::makeCorrectDir($tmpdir . '/web')));
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> tar cfz ' . escapeshellarg(\Froxlor\FileDir::makeCorrectFile($tmpdir . '/web/' . $data['loginname'] . '-web.tar.gz')) . ' --exclude=' . escapeshellarg(str_replace($customerdocroot, "./", \Froxlor\FileDir::makeCorrectFile($tmpdir . '/*'))) . ' --exclude=' . escapeshellarg(str_replace($customerdocroot, "./", substr(\Froxlor\FileDir::makeCorrectDir($tmpdir), 0, - 1))) . ' -C ' . escapeshellarg($customerdocroot) . ' .');
\Froxlor\FileDir::safe_exec('tar cfz ' . escapeshellarg(\Froxlor\FileDir::makeCorrectFile($tmpdir . '/web/' . $data['loginname'] . '-web.tar.gz')) . ' --exclude=' . escapeshellarg(str_replace($customerdocroot, "./", \Froxlor\FileDir::makeCorrectFile($tmpdir . '/*'))) . ' --exclude=' . escapeshellarg(str_replace($customerdocroot, "./", substr(\Froxlor\FileDir::makeCorrectFile($tmpdir), 0, - 1))) . ' -C ' . escapeshellarg($customerdocroot) . ' .');
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'Creating web-folder "' . FileDir::makeCorrectDir($tmpdir . '/web') . '"');
FileDir::safe_exec('mkdir -p ' . escapeshellarg(FileDir::makeCorrectDir($tmpdir . '/web')));
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> tar cfz ' . escapeshellarg(FileDir::makeCorrectFile($tmpdir . '/web/' . $data['loginname'] . '-web.tar.gz')) . ' --exclude=' . escapeshellarg(str_replace($customerdocroot, "./", FileDir::makeCorrectFile($tmpdir . '/*'))) . ' --exclude=' . escapeshellarg(str_replace($customerdocroot, "./", substr(FileDir::makeCorrectDir($tmpdir), 0, -1))) . ' -C ' . escapeshellarg($customerdocroot) . ' .');
FileDir::safe_exec('tar cfz ' . escapeshellarg(FileDir::makeCorrectFile($tmpdir . '/web/' . $data['loginname'] . '-web.tar.gz')) . ' --exclude=' . escapeshellarg(str_replace($customerdocroot, "./", FileDir::makeCorrectFile($tmpdir . '/*'))) . ' --exclude=' . escapeshellarg(str_replace($customerdocroot, "./", substr(FileDir::makeCorrectFile($tmpdir), 0, -1))) . ' -C ' . escapeshellarg($customerdocroot) . ' .');
$create_backup_tar_data .= './web ';
}
if (! empty($create_backup_tar_data)) {
$backup_file = \Froxlor\FileDir::makeCorrectFile($tmpdir . '/' . $data['loginname'] . '-backup_' . date('YmdHi', time()) . '.tar.gz');
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Creating backup-file "' . $backup_file . '"');
if (!empty($create_backup_tar_data)) {
$backup_file = FileDir::makeCorrectFile($tmpdir . '/' . $data['loginname'] . '-backup_' . date('YmdHi', time()) . '.tar.gz');
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Creating backup-file "' . $backup_file . '"');
// pack all archives in tmp-dir to one
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> tar cfz ' . escapeshellarg($backup_file) . ' -C ' . escapeshellarg($tmpdir) . ' ' . trim($create_backup_tar_data));
\Froxlor\FileDir::safe_exec('tar cfz ' . escapeshellarg($backup_file) . ' -C ' . escapeshellarg($tmpdir) . ' ' . trim($create_backup_tar_data));
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> tar cfz ' . escapeshellarg($backup_file) . ' -C ' . escapeshellarg($tmpdir) . ' ' . trim($create_backup_tar_data));
FileDir::safe_exec('tar cfz ' . escapeshellarg($backup_file) . ' -C ' . escapeshellarg($tmpdir) . ' ' . trim($create_backup_tar_data));
// move to destination directory
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> mv ' . escapeshellarg($backup_file) . ' ' . escapeshellarg($data['destdir']));
\Froxlor\FileDir::safe_exec('mv ' . escapeshellarg($backup_file) . ' ' . escapeshellarg($data['destdir']));
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> mv ' . escapeshellarg($backup_file) . ' ' . escapeshellarg($data['destdir']));
FileDir::safe_exec('mv ' . escapeshellarg($backup_file) . ' ' . escapeshellarg($data['destdir']));
// remove tmp-files
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> rm -rf ' . escapeshellarg($tmpdir));
\Froxlor\FileDir::safe_exec('rm -rf ' . escapeshellarg($tmpdir));
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> rm -rf ' . escapeshellarg($tmpdir));
FileDir::safe_exec('rm -rf ' . escapeshellarg($tmpdir));
// set owner to customer
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> chown -R ' . (int) $data['uid'] . ':' . (int) $data['gid'] . ' ' . escapeshellarg($data['destdir']));
\Froxlor\FileDir::safe_exec('chown -R ' . (int) $data['uid'] . ':' . (int) $data['gid'] . ' ' . escapeshellarg($data['destdir']));
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> chown -R ' . (int)$data['uid'] . ':' . (int)$data['gid'] . ' ' . escapeshellarg($data['destdir']));
FileDir::safe_exec('chown -R ' . (int)$data['uid'] . ':' . (int)$data['gid'] . ' ' . escapeshellarg($data['destdir']));
}
}
}

View File

@@ -1,23 +1,37 @@
<?php
namespace Froxlor\Cron\System;
use Froxlor\Database\Database;
use Froxlor\Settings;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2017 the Froxlor Team (see authors).
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2017-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
* 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\System;
use Froxlor\Customer\Customer;
use Froxlor\Database\Database;
use Froxlor\FroxlorLogger;
use Froxlor\Settings;
use Froxlor\User;
use PDO;
class Extrausers
{
@@ -49,27 +63,27 @@ class Extrausers
private static function generateFile($file, $query, &$cronlog, &$result_list = null)
{
$type = basename($file);
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Creating ' . $type . ' file');
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Creating ' . $type . ' file');
if (! file_exists($file)) {
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, $type . ' file does not yet exist');
if (!file_exists($file)) {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, $type . ' file does not yet exist');
@mkdir(dirname($file), 0750, true);
touch($file);
}
$data_sel_stmt = Database::query($query);
$data_content = "";
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Writing ' . $data_sel_stmt->rowCount() . ' entries to ' . $type . ' file');
while ($u = $data_sel_stmt->fetch(\PDO::FETCH_ASSOC)) {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Writing ' . $data_sel_stmt->rowCount() . ' entries to ' . $type . ' file');
while ($u = $data_sel_stmt->fetch(PDO::FETCH_ASSOC)) {
switch ($type) {
case 'passwd':
// get user real name
$salutation_array = array(
'firstname' => \Froxlor\Customer\Customer::getCustomerDetail($u['customerid'], 'firstname'),
'name' => \Froxlor\Customer\Customer::getCustomerDetail($u['customerid'], 'name'),
'company' => \Froxlor\Customer\Customer::getCustomerDetail($u['customerid'], 'company')
);
$u['comment'] = self::cleanString(\Froxlor\User::getCorrectUserSalutation($salutation_array));
$salutation_array = [
'firstname' => Customer::getCustomerDetail($u['customerid'], 'firstname'),
'name' => Customer::getCustomerDetail($u['customerid'], 'name'),
'company' => Customer::getCustomerDetail($u['customerid'], 'company')
];
$u['comment'] = self::cleanString(User::getCorrectUserSalutation($salutation_array));
if ($u['login_enabled'] != 'Y') {
$u['password'] = '*';
$u['shell'] = '/bin/false';
@@ -103,9 +117,9 @@ class Extrausers
}
if (file_put_contents($file, $data_content) !== false) {
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Succesfully wrote ' . $type . ' file');
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Succesfully wrote ' . $type . ' file');
} else {
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Error when writing ' . $type . ' file entries');
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Error when writing ' . $type . ' file entries');
}
}

View File

@@ -1,48 +1,61 @@
<?php
namespace Froxlor\Cron\System;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Michael Kaufmann <mkaufmann@nutime.de>
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
* @since 0.9.29.1
*
* 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
*/
class MailboxsizeCron extends \Froxlor\Cron\FroxlorCron
namespace Froxlor\Cron\System;
use Froxlor\Cron\FroxlorCron;
use Froxlor\Database\Database;
use Froxlor\FileDir;
use Froxlor\FroxlorLogger;
use Froxlor\Settings;
use PDO;
class MailboxsizeCron extends FroxlorCron
{
public static function run()
{
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'calculating mailspace usage');
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'calculating mailspace usage');
$maildirs_stmt = \Froxlor\Database\Database::query("
$maildirs_stmt = Database::query("
SELECT `id`, CONCAT(`homedir`, `maildir`) AS `maildirpath` FROM `" . TABLE_MAIL_USERS . "` ORDER BY `id`
");
$upd_stmt = \Froxlor\Database\Database::prepare("
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_MAIL_USERS . "` SET `mboxsize` = :size WHERE `id` = :id
");
while ($maildir = $maildirs_stmt->fetch(\PDO::FETCH_ASSOC)) {
$_maildir = \Froxlor\FileDir::makeCorrectDir($maildir['maildirpath']);
while ($maildir = $maildirs_stmt->fetch(PDO::FETCH_ASSOC)) {
$_maildir = FileDir::makeCorrectDir($maildir['maildirpath']);
if (file_exists($_maildir) && is_dir($_maildir)) {
$maildirsize = \Froxlor\FileDir::makeCorrectFile($_maildir . '/maildirsize');
$maildirsize = FileDir::makeCorrectFile($_maildir . '/maildirsize');
// When quota is enabled and maildirsize file exists, use that to calculate size
if (\Froxlor\Settings::Get('system.mail_quota_enabled') == 1 && file_exists($maildirsize)) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'found maildirsize file in ' . $_maildir);
if (Settings::Get('system.mail_quota_enabled') == 1 && file_exists($maildirsize)) {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'found maildirsize file in ' . $_maildir);
$file = file($maildirsize, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
// Remove header
array_shift($file);
@@ -58,14 +71,14 @@ class MailboxsizeCron extends \Froxlor\Cron\FroxlorCron
// if quota is disabled or maildirsize file does not exist, compute with du
// mail-address allows many special characters, see http://en.wikipedia.org/wiki/Email_address#Local_part
$return = false;
$back = \Froxlor\FileDir::safe_exec('du -sk ' . escapeshellarg($_maildir), $return, array(
$back = FileDir::safe_exec('du -sk ' . escapeshellarg($_maildir), $return, [
'|',
'&',
'`',
'$',
'~',
'?'
));
]);
foreach ($back as $backrow) {
$emailusage = explode(' ', $backrow);
}
@@ -77,12 +90,12 @@ class MailboxsizeCron extends \Froxlor\Cron\FroxlorCron
unset($back);
}
\Froxlor\Database\Database::pexecute($upd_stmt, array(
Database::pexecute($upd_stmt, [
'size' => $emailusage,
'id' => $maildir['id']
));
]);
} else {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_WARNING, 'maildir ' . $_maildir . ' does not exist');
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, 'maildir ' . $_maildir . ' does not exist');
}
}
}

View File

@@ -1,28 +1,42 @@
<?php
namespace Froxlor\Cron\System;
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\Cron\TaskId;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2003-2009 the SysCP Team (see authors).
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Florian Lippert <flo@syscp.org> (2003-2009)
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
* 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
*/
class TasksCron extends \Froxlor\Cron\FroxlorCron
namespace Froxlor\Cron\System;
use Froxlor\Cron\FroxlorCron;
use Froxlor\Cron\Http\ConfigIO;
use Froxlor\Cron\TaskId;
use Froxlor\Database\Database;
use Froxlor\Dns\PowerDNS;
use Froxlor\Domain\Domain;
use Froxlor\FileDir;
use Froxlor\FroxlorLogger;
use Froxlor\Settings;
use PDO;
class TasksCron extends FroxlorCron
{
public static function run()
@@ -30,17 +44,16 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
/**
* LOOK INTO TASKS TABLE TO SEE IF THERE ARE ANY UNDONE JOBS
*/
self::$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "TasksCron: Searching for tasks to do");
self::$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "TasksCron: Searching for tasks to do");
// no type 99 (regenerate cron.d-file) and no type 20 (customer backup)
// order by type descending to re-create bind and then webserver at the end
$result_tasks_stmt = Database::query("
SELECT `id`, `type`, `data` FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` <> '99' AND `type` <> '20' ORDER BY `type` DESC, `id` ASC
");
$num_results = Database::num_rows();
$resultIDs = array();
while ($row = $result_tasks_stmt->fetch(\PDO::FETCH_ASSOC)) {
$resultIDs = [];
while ($row = $result_tasks_stmt->fetch(PDO::FETCH_ASSOC)) {
$resultIDs[] = $row['id'];
if ($row['data'] != '') {
@@ -57,7 +70,7 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
* TYPE=2 MEANS TO CREATE A NEW HOME AND CHOWN
*/
self::createNewHome($row);
} elseif ($row['type'] == TaskId::REBUILD_DNS && (int) Settings::Get('system.bind_enable') != 0) {
} elseif ($row['type'] == TaskId::REBUILD_DNS && (int)Settings::Get('system.bind_enable') != 0) {
/**
* TYPE=4 MEANS THAT SOMETHING IN THE BIND CONFIG HAS CHANGED.
* REBUILD froxlor_bind.conf IF BIND IS ENABLED
@@ -84,7 +97,7 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
* refs #293
*/
self::deleteFtpData($row);
} 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
*/
@@ -93,22 +106,22 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
/**
* TYPE=11 domain has been deleted, remove from pdns database if used
*/
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, "Removing PowerDNS entries for domain " . $row['data']['domain']);
\Froxlor\Dns\PowerDNS::cleanDomainZone($row['data']['domain']);
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, "Removing PowerDNS entries for domain " . $row['data']['domain']);
PowerDNS::cleanDomainZone($row['data']['domain']);
} elseif ($row['type'] == TaskId::DELETE_DOMAIN_SSL) {
/**
* TYPE=12 domain has been deleted, remove from acme.sh/let's encrypt directory if used
*/
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, "Removing Let's Encrypt entries for domain " . $row['data']['domain']);
\Froxlor\Domain\Domain::doLetsEncryptCleanUp($row['data']['domain']);
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, "Removing Let's Encrypt entries for domain " . $row['data']['domain']);
Domain::doLetsEncryptCleanUp($row['data']['domain']);
}
}
if ($num_results != 0) {
$where = array();
$where_data = array();
$where = [];
$where_data = [];
foreach ($resultIDs as $id) {
$where[] = "`id` = :id_" . (int) $id;
$where[] = "`id` = :id_" . (int)$id;
$where_data['id_' . $id] = $id;
}
$where = implode(' OR ', $where);
@@ -123,7 +136,6 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
private static function rebuildWebserverConfigs()
{
if (Settings::Get('system.webserver') == "apache2") {
$websrv = '\\Froxlor\\Cron\\Http\\Apache';
if (Settings::Get('system.mod_fcgid') == 1 || Settings::Get('phpfpm.enabled') == 1) {
@@ -142,7 +154,7 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
}
// get configuration-I/O object
$configio = new \Froxlor\Cron\Http\ConfigIO();
$configio = new ConfigIO();
// get webserver object
$webserver = new $websrv();
@@ -167,12 +179,12 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
// get group info about the local-user's group (e.g. froxlorlocal)
$groupinfo = posix_getgrnam(Settings::Get('phpfpm.vhost_httpgroup'));
// check group members
if (isset($groupinfo['members']) && ! in_array(Settings::Get('system.httpuser'), $groupinfo['members'])) {
if (isset($groupinfo['members']) && !in_array(Settings::Get('system.httpuser'), $groupinfo['members'])) {
// webserver has no access, add it
if (\Froxlor\FileDir::isFreeBSD()) {
\Froxlor\FileDir::safe_exec('pw usermod ' . escapeshellarg(Settings::Get('system.httpuser')) . ' -G ' . escapeshellarg(Settings::Get('phpfpm.vhost_httpgroup')));
if (FileDir::isFreeBSD()) {
FileDir::safe_exec('pw usermod ' . escapeshellarg(Settings::Get('system.httpuser')) . ' -G ' . escapeshellarg(Settings::Get('phpfpm.vhost_httpgroup')));
} else {
\Froxlor\FileDir::safe_exec('usermod -a -G ' . escapeshellarg(Settings::Get('phpfpm.vhost_httpgroup')) . ' ' . escapeshellarg(Settings::Get('system.httpuser')));
FileDir::safe_exec('usermod -a -G ' . escapeshellarg(Settings::Get('phpfpm.vhost_httpgroup')) . ' ' . escapeshellarg(Settings::Get('system.httpuser')));
}
}
}
@@ -184,73 +196,73 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
private static function createNewHome($row = null)
{
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'TasksCron: Task2 started - create new home');
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'TasksCron: Task2 started - create new home');
if (is_array($row['data'])) {
// define paths
$userhomedir = \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.documentroot_prefix') . '/' . $row['data']['loginname'] . '/');
$usermaildir = \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.vmail_homedir') . '/' . $row['data']['loginname'] . '/');
$userhomedir = FileDir::makeCorrectDir(Settings::Get('system.documentroot_prefix') . '/' . $row['data']['loginname'] . '/');
$usermaildir = FileDir::makeCorrectDir(Settings::Get('system.vmail_homedir') . '/' . $row['data']['loginname'] . '/');
// stats directory
if (Settings::Get('system.awstats_enabled') == '1') {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: mkdir -p ' . escapeshellarg($userhomedir . 'awstats'));
\Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg($userhomedir . 'awstats'));
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: mkdir -p ' . escapeshellarg($userhomedir . 'awstats'));
FileDir::safe_exec('mkdir -p ' . escapeshellarg($userhomedir . 'awstats'));
// in case we changed from the other stats -> remove old
// (yes i know, the stats are lost - that's why you should not change all the time!)
if (file_exists($userhomedir . 'webalizer')) {
\Froxlor\FileDir::safe_exec('rm -rf ' . escapeshellarg($userhomedir . 'webalizer'));
FileDir::safe_exec('rm -rf ' . escapeshellarg($userhomedir . 'webalizer'));
}
} else {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: mkdir -p ' . escapeshellarg($userhomedir . 'webalizer'));
\Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg($userhomedir . 'webalizer'));
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: mkdir -p ' . escapeshellarg($userhomedir . 'webalizer'));
FileDir::safe_exec('mkdir -p ' . escapeshellarg($userhomedir . 'webalizer'));
// in case we changed from the other stats -> remove old
// (yes i know, the stats are lost - that's why you should not change all the time!)
if (file_exists($userhomedir . 'awstats')) {
\Froxlor\FileDir::safe_exec('rm -rf ' . escapeshellarg($userhomedir . 'awstats'));
FileDir::safe_exec('rm -rf ' . escapeshellarg($userhomedir . 'awstats'));
}
}
// maildir
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: mkdir -p ' . escapeshellarg($usermaildir));
\Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg($usermaildir));
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: mkdir -p ' . escapeshellarg($usermaildir));
FileDir::safe_exec('mkdir -p ' . escapeshellarg($usermaildir));
// check if admin of customer has added template for new customer directories
if ((int) $row['data']['store_defaultindex'] == 1) {
\Froxlor\FileDir::storeDefaultIndex($row['data']['loginname'], $userhomedir, \Froxlor\FroxlorLogger::getInstanceOf(), true);
if ((int)$row['data']['store_defaultindex'] == 1) {
FileDir::storeDefaultIndex($row['data']['loginname'], $userhomedir, FroxlorLogger::getInstanceOf(), true);
}
// strip of last slash of paths to have correct chown results
$userhomedir = (substr($userhomedir, 0, - 1) == '/') ? substr($userhomedir, 0, - 1) : $userhomedir;
$usermaildir = (substr($usermaildir, 0, - 1) == '/') ? substr($usermaildir, 0, - 1) : $usermaildir;
$userhomedir = (substr($userhomedir, 0, -1) == '/') ? substr($userhomedir, 0, -1) : $userhomedir;
$usermaildir = (substr($usermaildir, 0, -1) == '/') ? substr($usermaildir, 0, -1) : $usermaildir;
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: chown -R ' . (int) $row['data']['uid'] . ':' . (int) $row['data']['gid'] . ' ' . escapeshellarg($userhomedir));
\Froxlor\FileDir::safe_exec('chown -R ' . (int) $row['data']['uid'] . ':' . (int) $row['data']['gid'] . ' ' . escapeshellarg($userhomedir));
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: chown -R ' . (int)$row['data']['uid'] . ':' . (int)$row['data']['gid'] . ' ' . escapeshellarg($userhomedir));
FileDir::safe_exec('chown -R ' . (int)$row['data']['uid'] . ':' . (int)$row['data']['gid'] . ' ' . escapeshellarg($userhomedir));
// don't allow others to access the directory (webserver will be the group via libnss-mysql)
if (Settings::Get('system.mod_fcgid') == 1 || Settings::Get('phpfpm.enabled') == 1) {
// fcgid or fpm
\Froxlor\FileDir::safe_exec('chmod 0750 ' . escapeshellarg($userhomedir));
FileDir::safe_exec('chmod 0750 ' . escapeshellarg($userhomedir));
} else {
// mod_php -> no libnss-mysql -> no webserver-user in group
\Froxlor\FileDir::safe_exec('chmod 0755 ' . escapeshellarg($userhomedir));
FileDir::safe_exec('chmod 0755 ' . escapeshellarg($userhomedir));
}
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: chown -R ' . (int) Settings::Get('system.vmail_uid') . ':' . (int) Settings::Get('system.vmail_gid') . ' ' . escapeshellarg($usermaildir));
\Froxlor\FileDir::safe_exec('chown -R ' . (int) Settings::Get('system.vmail_uid') . ':' . (int) Settings::Get('system.vmail_gid') . ' ' . escapeshellarg($usermaildir));
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: chown -R ' . (int)Settings::Get('system.vmail_uid') . ':' . (int)Settings::Get('system.vmail_gid') . ' ' . escapeshellarg($usermaildir));
FileDir::safe_exec('chown -R ' . (int)Settings::Get('system.vmail_uid') . ':' . (int)Settings::Get('system.vmail_gid') . ' ' . escapeshellarg($usermaildir));
if (Settings::Get('system.nssextrausers') == 1) {
// explicitly create files after user has been created to avoid unknown user issues for apache/php-fpm when task#1 runs after this
$extrausers_log = \Froxlor\FroxlorLogger::getInstanceOf();
$extrausers_log = FroxlorLogger::getInstanceOf();
Extrausers::generateFiles($extrausers_log);
}
// clear NSCD cache if using fcgid or fpm, #1570 - not needed for nss-extrausers
if ((Settings::Get('system.mod_fcgid') == 1 || (int) Settings::Get('phpfpm.enabled') == 1) && Settings::Get('system.nssextrausers') == 0) {
if ((Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) && Settings::Get('system.nssextrausers') == 0) {
$false_val = false;
\Froxlor\FileDir::safe_exec('nscd -i passwd 1> /dev/null', $false_val, array(
FileDir::safe_exec('nscd -i passwd 1> /dev/null', $false_val, [
'>'
));
\Froxlor\FileDir::safe_exec('nscd -i group 1> /dev/null', $false_val, array(
]);
FileDir::safe_exec('nscd -i group 1> /dev/null', $false_val, [
'>'
));
]);
}
}
}
@@ -259,7 +271,7 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
{
$dnssrv = '\\Froxlor\\Cron\\Dns\\' . Settings::Get('system.dns_server');
$nameserver = new $dnssrv(\Froxlor\FroxlorLogger::getInstanceOf());
$nameserver = new $dnssrv(FroxlorLogger::getInstanceOf());
if (Settings::Get('dkim.use_dkim') == '1') {
$nameserver->writeDKIMconfigs();
@@ -270,62 +282,62 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
private static function createNewFtpHome($row = null)
{
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Creating new FTP-home');
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Creating new FTP-home');
$result_directories_stmt = Database::query("
SELECT `f`.`homedir`, `f`.`uid`, `f`.`gid`, `c`.`documentroot` AS `customerroot`
FROM `" . TABLE_FTP_USERS . "` `f` LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING (`customerid`)
");
while ($directory = $result_directories_stmt->fetch(\PDO::FETCH_ASSOC)) {
\Froxlor\FileDir::mkDirWithCorrectOwnership($directory['customerroot'], $directory['homedir'], $directory['uid'], $directory['gid']);
while ($directory = $result_directories_stmt->fetch(PDO::FETCH_ASSOC)) {
FileDir::mkDirWithCorrectOwnership($directory['customerroot'], $directory['homedir'], $directory['uid'], $directory['gid']);
}
}
private static function deleteCustomerData($row = null)
{
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'TasksCron: Task6 started - deleting customer data');
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'TasksCron: Task6 started - deleting customer data');
if (is_array($row['data'])) {
if (isset($row['data']['loginname'])) {
// remove homedir
$homedir = \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.documentroot_prefix') . '/' . $row['data']['loginname']);
$homedir = FileDir::makeCorrectDir(Settings::Get('system.documentroot_prefix') . '/' . $row['data']['loginname']);
if (file_exists($homedir) && $homedir != '/' && $homedir != Settings::Get('system.documentroot_prefix') && substr($homedir, 0, strlen(Settings::Get('system.documentroot_prefix'))) == Settings::Get('system.documentroot_prefix')) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: rm -rf ' . escapeshellarg($homedir));
\Froxlor\FileDir::safe_exec('rm -rf ' . escapeshellarg($homedir));
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: rm -rf ' . escapeshellarg($homedir));
FileDir::safe_exec('rm -rf ' . escapeshellarg($homedir));
}
// remove maildir
$maildir = \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.vmail_homedir') . '/' . $row['data']['loginname']);
$maildir = FileDir::makeCorrectDir(Settings::Get('system.vmail_homedir') . '/' . $row['data']['loginname']);
if (file_exists($maildir) && $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')) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\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
$return = false;
\Froxlor\FileDir::safe_exec('rm -rf ' . escapeshellarg($maildir), $return, array(
FileDir::safe_exec('rm -rf ' . escapeshellarg($maildir), $return, [
'|',
'&',
'`',
'$',
'?'
));
]);
}
// remove tmpdir if it exists
$tmpdir = \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.mod_fcgid_tmpdir') . '/' . $row['data']['loginname'] . '/');
$tmpdir = FileDir::makeCorrectDir(Settings::Get('system.mod_fcgid_tmpdir') . '/' . $row['data']['loginname'] . '/');
if (file_exists($tmpdir) && is_dir($tmpdir) && $tmpdir != "/" && $tmpdir != Settings::Get('system.mod_fcgid_tmpdir') && substr($tmpdir, 0, strlen(Settings::Get('system.mod_fcgid_tmpdir'))) == Settings::Get('system.mod_fcgid_tmpdir')) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: rm -rf ' . escapeshellarg($tmpdir));
\Froxlor\FileDir::safe_exec('rm -rf ' . escapeshellarg($tmpdir));
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: rm -rf ' . escapeshellarg($tmpdir));
FileDir::safe_exec('rm -rf ' . escapeshellarg($tmpdir));
}
// webserver logs
$logsdir = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.logfiles_directory') . '/' . $row['data']['loginname']);
$logsdir = FileDir::makeCorrectFile(Settings::Get('system.logfiles_directory') . '/' . $row['data']['loginname']);
if (file_exists($logsdir) && $logsdir != '/' && $logsdir != \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.logfiles_directory')) && substr($logsdir, 0, strlen(Settings::Get('system.logfiles_directory'))) == Settings::Get('system.logfiles_directory')) {
if (file_exists($logsdir) && $logsdir != '/' && $logsdir != FileDir::makeCorrectDir(Settings::Get('system.logfiles_directory')) && substr($logsdir, 0, strlen(Settings::Get('system.logfiles_directory'))) == Settings::Get('system.logfiles_directory')) {
// build up wildcard for webX-{access,error}.log{*}
$logsdir .= '-*';
\Froxlor\FileDir::safe_exec('rm -f ' . escapeshellarg($logsdir));
FileDir::safe_exec('rm -f ' . escapeshellarg($logsdir));
}
}
}
@@ -333,55 +345,54 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
private static function deleteEmailData($row = null)
{
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\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 (isset($row['data']['loginname']) && isset($row['data']['email'])) {
// remove specific maildir
$email_full = $row['data']['email'];
if (empty($email_full)) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, 'FATAL: Task7 asks to delete a email account but email 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) != "/") {
if (!empty($maildirname) and substr($maildirname, -1) != "/") {
$maildirpath .= "/";
}
$maildir = \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.vmail_homedir') . '/' . $row['data']['loginname'] . '/' . $email_domain . '/' . $email_user);
$maildir = FileDir::makeCorrectDir(Settings::Get('system.vmail_homedir') . '/' . $row['data']['loginname'] . '/' . $email_domain . '/' . $email_user);
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(\Froxlor\FileDir::makeCorrectDir($maildir . '/' . $maildirpath)) && fileowner($maildir) == Settings::Get('system.vmail_uid') && filegroup($maildir) == Settings::Get('system.vmail_gid')) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: rm -rf ' . escapeshellarg($maildir));
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));
// mail-address allows many special characters, see http://en.wikipedia.org/wiki/Email_address#Local_part
$return = false;
\Froxlor\FileDir::safe_exec('rm -rf ' . escapeshellarg($maildir), $return, array(
FileDir::safe_exec('rm -rf ' . escapeshellarg($maildir), $return, [
'|',
'&',
'`',
'$',
'~',
'?'
));
]);
} else {
// backward-compatibility for old folder-structure
$maildir_old = \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.vmail_homedir') . '/' . $row['data']['loginname'] . '/' . $row['data']['email']);
$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')) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: rm -rf ' . escapeshellarg($maildir_old));
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;
\Froxlor\FileDir::safe_exec('rm -rf ' . escapeshellarg($maildir_old), $return, array(
FileDir::safe_exec('rm -rf ' . escapeshellarg($maildir_old), $return, [
'|',
'&',
'`',
'$',
'~',
'?'
));
]);
}
}
}
@@ -390,18 +401,17 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
private static function deleteFtpData($row = null)
{
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'TasksCron: Task8 started - deleting customer ftp homedir');
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'TasksCron: Task8 started - deleting customer ftp homedir');
if (is_array($row['data'])) {
if (isset($row['data']['loginname']) && isset($row['data']['homedir'])) {
// remove specific homedir
$ftphomedir = \Froxlor\FileDir::makeCorrectDir($row['data']['homedir']);
$customerdocroot = \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.documentroot_prefix') . '/' . $row['data']['loginname'] . '/');
$ftphomedir = FileDir::makeCorrectDir($row['data']['homedir']);
$customerdocroot = FileDir::makeCorrectDir(Settings::Get('system.documentroot_prefix') . '/' . $row['data']['loginname'] . '/');
if (file_exists($ftphomedir) && $ftphomedir != '/' && $ftphomedir != Settings::Get('system.documentroot_prefix') && $ftphomedir != $customerdocroot) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: rm -rf ' . escapeshellarg($ftphomedir));
\Froxlor\FileDir::safe_exec('rm -rf ' . escapeshellarg($ftphomedir));
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: rm -rf ' . escapeshellarg($ftphomedir));
FileDir::safe_exec('rm -rf ' . escapeshellarg($ftphomedir));
}
}
}
@@ -409,33 +419,33 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
private static function setFilesystemQuota()
{
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'TasksCron: Task10 started - setting filesystem quota');
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'TasksCron: Task10 started - setting filesystem quota');
$usedquota = \Froxlor\FileDir::getFilesystemQuota();
$usedquota = FileDir::getFilesystemQuota();
// Check whether we really have entries to check
if (is_array($usedquota) && count($usedquota) > 0) {
// Select all customers Froxlor knows about
$result_stmt = Database::query("SELECT `guid`, `loginname`, `diskspace` FROM `" . TABLE_PANEL_CUSTOMERS . "`;");
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
// We do not want to set a quota for root by accident
if ($row['guid'] != 0) {
$used_quota = isset($usedquota[$row['guid']]) ? $usedquota[$row['guid']]['block']['hard'] : 0;
// The user has no quota in Froxlor, but on the filesystem
if (($row['diskspace'] == 0 || $row['diskspace'] == - 1024) && $used_quota != 0) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, "Disabling quota for " . $row['loginname']);
if (\Froxlor\FileDir::isFreeBSD()) {
\Froxlor\FileDir::safe_exec(Settings::Get('system.diskquota_quotatool_path') . " -e " . escapeshellarg(Settings::Get('system.diskquota_customer_partition')) . ":0:0 " . $row['guid']);
if (($row['diskspace'] == 0 || $row['diskspace'] == -1024) && $used_quota != 0) {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, "Disabling quota for " . $row['loginname']);
if (FileDir::isFreeBSD()) {
FileDir::safe_exec(Settings::Get('system.diskquota_quotatool_path') . " -e " . escapeshellarg(Settings::Get('system.diskquota_customer_partition')) . ":0:0 " . $row['guid']);
} else {
\Froxlor\FileDir::safe_exec(Settings::Get('system.diskquota_quotatool_path') . " -u " . $row['guid'] . " -bl 0 -q 0 " . escapeshellarg(Settings::Get('system.diskquota_customer_partition')));
FileDir::safe_exec(Settings::Get('system.diskquota_quotatool_path') . " -u " . $row['guid'] . " -bl 0 -q 0 " . escapeshellarg(Settings::Get('system.diskquota_customer_partition')));
}
} elseif ($row['diskspace'] != $used_quota && $row['diskspace'] != - 1024) {
} elseif ($row['diskspace'] != $used_quota && $row['diskspace'] != -1024) {
// The user quota in Froxlor is different than on the filesystem
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, "Setting quota for " . $row['loginname'] . " from " . $used_quota . " to " . $row['diskspace']);
if (\Froxlor\FileDir::isFreeBSD()) {
\Froxlor\FileDir::safe_exec(Settings::Get('system.diskquota_quotatool_path') . " -e " . escapeshellarg(Settings::Get('system.diskquota_customer_partition')) . ":" . $row['diskspace'] . ":" . $row['diskspace'] . " " . $row['guid']);
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, "Setting quota for " . $row['loginname'] . " from " . $used_quota . " to " . $row['diskspace']);
if (FileDir::isFreeBSD()) {
FileDir::safe_exec(Settings::Get('system.diskquota_quotatool_path') . " -e " . escapeshellarg(Settings::Get('system.diskquota_customer_partition')) . ":" . $row['diskspace'] . ":" . $row['diskspace'] . " " . $row['guid']);
} else {
\Froxlor\FileDir::safe_exec(Settings::Get('system.diskquota_quotatool_path') . " -u " . $row['guid'] . " -bl " . $row['diskspace'] . " -q " . $row['diskspace'] . " " . escapeshellarg(Settings::Get('system.diskquota_customer_partition')));
FileDir::safe_exec(Settings::Get('system.diskquota_quotatool_path') . " -u " . $row['guid'] . " -bl " . $row['diskspace'] . " -q " . $row['diskspace'] . " " . escapeshellarg(Settings::Get('system.diskquota_customer_partition')));
}
}
}

View File

@@ -1,9 +1,34 @@
<?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;
use ReflectionClass;
class TaskId {
class TaskId
{
/**
* TYPE=1 MEANS TO REBUILD APACHE VHOSTS.CONF
*/
@@ -52,33 +77,35 @@ class TaskId {
const DELETE_DOMAIN_PDNS = 11;
/**
* TYPE=12 domain has been deleted, remove from acme.sh/let's encrypt directory if used
* TYPE=12 domain has been deleted, remove from acme.sh/let's encrypt directory if used
*/
const DELETE_DOMAIN_SSL = 12;
/**
* TYPE=20 COSTUMERBACKUP
* TYPE=20 COSTUMERBACKUP
*/
const CREATE_CUSTOMER_BACKUP = 20;
/**
* TYPE=99 REGENERATE CRON
* TYPE=99 REGENERATE CRON
*/
const REBUILD_CRON = 99;
/**
* Return if a cron task id is valid
*
* @param int|string $id cron task id (legacy string support)
* @return boolean
*/
public static function isValid($id) {
public static function isValid($id)
{
static $reflContants;
if (!is_numeric($id)) {
return false;
}
$numericid = (int)$id;
if (!is_array($reflContants)) {
$reflClass = new \ReflectionClass(get_called_class());
$reflClass = new ReflectionClass(get_called_class());
$reflContants = $reflClass->getConstants();
}
return in_array($numericid, $reflContants, true);
@@ -86,20 +113,21 @@ class TaskId {
/**
* Get constant name by id
*
* @param int|string $id cron task id (legacy string support)
* @return string|false constant name or false if not found
*/
public static function convertToConstant($id) {
public static function convertToConstant($id)
{
static $reflContants;
if (!is_numeric($id)) {
return false;
}
$numericid = (int)$id;
if (!is_array($reflContants)) {
$reflClass = new \ReflectionClass(get_called_class());
$reflClass = new ReflectionClass(get_called_class());
$reflContants = $reflClass->getConstants();
}
return array_search($numericid, $reflContants, true);
}
}

View File

@@ -1,39 +1,61 @@
<?php
namespace Froxlor\Cron\Traffic;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2003-2009 the SysCP Team (see authors).
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* 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.
*
* @copyright (c) the authors
* @author Florian Lippert <flo@syscp.org> (2003-2009)
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
* 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\Settings;
class ReportsCron extends \Froxlor\Cron\FroxlorCron
namespace Froxlor\Cron\Traffic;
/**
* @author Florian Lippert <flo@syscp.org> (2003-2009)
* @author Froxlor team <team@froxlor.org> (2010-)
*/
use Exception;
use Froxlor\Cron\FroxlorCron;
use Froxlor\Database\Database;
use Froxlor\FileDir;
use Froxlor\Froxlor;
use Froxlor\FroxlorLogger;
use Froxlor\PhpHelper;
use Froxlor\Settings;
use Froxlor\System\Mailer;
use Froxlor\User;
use PDO;
class ReportsCron extends FroxlorCron
{
public static function run()
{
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Web- and Traffic-usage reporting started...');
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Web- and Traffic-usage reporting started...');
$yesterday = time() - (60 * 60 * 24);
/**
* Initialize the mailingsystem
*/
$mail = new \Froxlor\System\Mailer(true);
$mail = new Mailer(true);
if ((int) Settings::Get('system.report_trafficmax') > 0) {
if ((int)Settings::Get('system.report_trafficmax') > 0) {
// Warn the customers at xx% traffic-usage
$result_stmt = Database::prepare("
SELECT `c`.`customerid`, `c`.`customernumber`, `c`.`adminid`, `c`.`name`, `c`.`firstname`,
@@ -48,54 +70,56 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
ON `a`.`adminid` = `c`.`adminid` WHERE `c`.`reportsent` <> '1'
");
$result_data = array(
$result_data = [
'year' => date("Y", $yesterday),
'month' => date("m", $yesterday)
);
];
Database::pexecute($result_stmt, $result_data);
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
if (isset($row['traffic']) && $row['traffic'] > 0 && $row['traffic_used'] != null && (($row['traffic_used'] * 100) / $row['traffic']) >= (int) Settings::Get('system.report_trafficmax')) {
$rep_userinfo = array(
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
if (isset($row['traffic']) && $row['traffic'] > 0 && $row['traffic_used'] != null && (($row['traffic_used'] * 100) / $row['traffic']) >= (int)Settings::Get('system.report_trafficmax')) {
$rep_userinfo = [
'name' => $row['name'],
'firstname' => $row['firstname'],
'company' => $row['company'],
'customernumber' => $row['customernumber']
);
$replace_arr = array(
'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($rep_userinfo),
];
$replace_arr = [
'SALUTATION' => User::getCorrectUserSalutation($rep_userinfo),
'NAME' => $rep_userinfo['name'],
'FIRSTNAME' => $rep_userinfo['firstname'],
'COMPANY' => $rep_userinfo['company'],
'CUSTOMER_NO' => $rep_userinfo['customernumber'],
'TRAFFIC' => round(($row['traffic'] / 1024), 2), /* traffic is stored in KB, template uses MB */
'TRAFFICUSED' => round(($row['traffic_used'] / 1024), 2), /* traffic is stored in KB, template uses MB */
'TRAFFIC' => round(($row['traffic'] / 1024), 2),
/* traffic is stored in KB, template uses MB */
'TRAFFICUSED' => round(($row['traffic_used'] / 1024), 2),
/* traffic is stored in KB, template uses MB */
'USAGE_PERCENT' => round(($row['traffic_used'] * 100) / $row['traffic'], 2),
'MAX_PERCENT' => Settings::Get('system.report_trafficmax')
);
];
$lngfile_stmt = Database::prepare("
SELECT `file` FROM `" . TABLE_PANEL_LANGUAGE . "`
WHERE `language` = :deflang
");
$lngfile = Database::pexecute_first($lngfile_stmt, array(
$lngfile = Database::pexecute_first($lngfile_stmt, [
'deflang' => $row['def_language']
));
]);
if ($lngfile !== null) {
$langfile = $lngfile['file'];
} else {
$lngfile = Database::pexecute_first($lngfile_stmt, array(
$lngfile = Database::pexecute_first($lngfile_stmt, [
'deflang' => Settings::Get('panel.standardlanguage')
));
]);
$langfile = $lngfile['file'];
}
// include english language file (fallback)
include \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/lng/english.lng.php');
include FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/lng/english.lng.php');
// include admin/customer language file
if ($lngfile != 'lng/english.lng.php') {
include \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/' . $langfile);
include FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/' . $langfile);
}
// Get mail templates from database; the ones from 'admin' are fetched for fallback
@@ -105,17 +129,17 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
AND `language` = :lang
AND `templategroup` = 'mails' AND `varname` = :varname
");
$result2_data = array(
$result2_data = [
'adminid' => $row['adminid'],
'lang' => $row['def_language'],
'varname' => 'trafficmaxpercent_subject'
);
];
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_subject = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['subject']), $replace_arr));
$mail_subject = html_entity_decode(PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['subject']), $replace_arr));
$result2_data['varname'] = 'trafficmaxpercent_mailbody';
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_body = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['mailbody']), $replace_arr));
$mail_body = html_entity_decode(PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['mailbody']), $replace_arr));
$_mailerror = false;
$mailerr_msg = "";
@@ -129,13 +153,13 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
} catch (\PHPMailer\PHPMailer\Exception $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (\Exception $e) {
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, 'Error sending mail: ' . $mailerr_msg);
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, 'Error sending mail: ' . $mailerr_msg);
echo 'Error sending mail: ' . $mailerr_msg . "\n";
}
@@ -144,9 +168,9 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `reportsent` = '1'
WHERE `customerid` = :customerid
");
Database::pexecute($upd_stmt, array(
Database::pexecute($upd_stmt, [
'customerid' => $row['customerid']
));
]);
unset($lng);
}
@@ -162,46 +186,46 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
FROM `" . TABLE_PANEL_ADMINS . "` `a` WHERE `a`.`reportsent` = '0'
");
$result_data = array(
$result_data = [
'year' => date("Y", $yesterday),
'month' => date("m", $yesterday)
);
];
Database::pexecute($result_stmt, $result_data);
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
if (isset($row['traffic']) && $row['traffic'] > 0 && (($row['traffic_used_total'] * 100) / $row['traffic']) >= (int) Settings::Get('system.report_trafficmax')) {
$replace_arr = array(
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
if (isset($row['traffic']) && $row['traffic'] > 0 && (($row['traffic_used_total'] * 100) / $row['traffic']) >= (int)Settings::Get('system.report_trafficmax')) {
$replace_arr = [
'NAME' => $row['name'],
'TRAFFIC' => round(($row['traffic'] / 1024), 2), /* traffic is stored in KB, template uses MB */
'TRAFFICUSED' => round(($row['traffic_used_total'] / 1024), 2), /* traffic is stored in KB, template uses MB */
'TRAFFIC' => round(($row['traffic'] / 1024), 2),
/* traffic is stored in KB, template uses MB */
'TRAFFICUSED' => round(($row['traffic_used_total'] / 1024), 2),
/* traffic is stored in KB, template uses MB */
'USAGE_PERCENT' => round(($row['traffic_used_total'] * 100) / $row['traffic'], 2),
'MAX_PERCENT' => Settings::Get('system.report_trafficmax')
);
];
$lngfile_stmt = Database::prepare("
SELECT `file` FROM `" . TABLE_PANEL_LANGUAGE . "`
WHERE `language` = :deflang
");
$lngfile = Database::pexecute_first($lngfile_stmt, array(
$lngfile = Database::pexecute_first($lngfile_stmt, [
'deflang' => $row['def_language']
));
]);
if ($lngfile !== null) {
$langfile = $lngfile['file'];
} else {
$lngfile = Database::pexecute_first($lngfile_stmt, array(
$lngfile = Database::pexecute_first($lngfile_stmt, [
'deflang' => Settings::Get('panel.standardlanguage')
));
]);
$langfile = $lngfile['file'];
}
// include english language file (fallback)
include \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/lng/english.lng.php');
include FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/lng/english.lng.php');
// include admin/customer language file
if ($lngfile != 'lng/english.lng.php') {
include \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/' . $langfile);
include FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/' . $langfile);
}
// Get mail templates from database; the ones from 'admin' are fetched for fallback
@@ -211,17 +235,17 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
AND `language` = :lang
AND `templategroup` = 'mails' AND `varname` = :varname
");
$result2_data = array(
$result2_data = [
'adminid' => $row['adminid'],
'lang' => $row['def_language'],
'varname' => 'trafficmaxpercent_subject'
);
];
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_subject = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['subject']), $replace_arr));
$mail_subject = html_entity_decode(PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['subject']), $replace_arr));
$result2_data['varname'] = 'trafficmaxpercent_mailbody';
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_body = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['mailbody']), $replace_arr));
$mail_body = html_entity_decode(PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['mailbody']), $replace_arr));
$_mailerror = false;
$mailerr_msg = "";
@@ -235,13 +259,13 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
} catch (\PHPMailer\PHPMailer\Exception $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (\Exception $e) {
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg);
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg);
echo "Error sending mail: " . $mailerr_msg . "\n";
}
@@ -250,14 +274,13 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
UPDATE `" . TABLE_PANEL_ADMINS . "` SET `reportsent` = '1'
WHERE `adminid` = :adminid
");
Database::pexecute($upd_stmt, array(
Database::pexecute($upd_stmt, [
'adminid' => $row['adminid']
));
]);
}
// Another month, let's build our report
if (date('d') == '01') {
$mail_subject = 'Trafficreport ' . date("m/y", $yesterday) . ' for ' . $row['name'];
$mail_body = 'Trafficreport ' . date("m/y", $yesterday) . ' for ' . $row['name'] . "\n";
$mail_body .= '---------------------------------------------------------------' . "\n";
@@ -270,14 +293,14 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
) as `traffic_used_total`
FROM `" . TABLE_PANEL_CUSTOMERS . "` `c` WHERE `c`.`adminid` = :adminid
");
$customers_data = array(
$customers_data = [
'year' => date("Y", $yesterday),
'month' => date("m", $yesterday),
'adminid' => $row['adminid']
);
];
Database::pexecute($customers_stmt, $customers_data);
while ($customer = $customers_stmt->fetch(\PDO::FETCH_ASSOC)) {
while ($customer = $customers_stmt->fetch(PDO::FETCH_ASSOC)) {
$t = $customer['traffic_used_total'] / 1048576;
if ($customer['traffic'] > 0) {
$p = (($customer['traffic_used_total'] * 100) / $customer['traffic']);
@@ -320,13 +343,13 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
} catch (\PHPMailer\PHPMailer\Exception $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (\Exception $e) {
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, 'Error sending mail: ' . $mailerr_msg);
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, 'Error sending mail: ' . $mailerr_msg);
echo 'Error sending mail: ' . $mailerr_msg . "\n";
}
@@ -349,7 +372,7 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
private static function usageDiskspace()
{
if ((int) Settings::Get('system.report_webmax') > 0) {
if ((int)Settings::Get('system.report_webmax') > 0) {
/**
* report about diskusage for customers
*/
@@ -363,52 +386,52 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
WHERE `c`.`diskspace` > '0' AND `c`.`reportsent` <> '2'
");
$mail = new \Froxlor\System\Mailer(true);
$mail = new Mailer(true);
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
if (isset($row['diskspace']) && $row['diskspace_used'] != null && $row['diskspace_used'] > 0 && (($row['diskspace_used'] * 100) / $row['diskspace']) >= (int) Settings::Get('system.report_webmax')) {
$rep_userinfo = array(
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
if (isset($row['diskspace']) && $row['diskspace_used'] != null && $row['diskspace_used'] > 0 && (($row['diskspace_used'] * 100) / $row['diskspace']) >= (int)Settings::Get('system.report_webmax')) {
$rep_userinfo = [
'name' => $row['name'],
'firstname' => $row['firstname'],
'company' => $row['company'],
'customernumber' => $row['customernumber']
);
$replace_arr = array(
'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($rep_userinfo),
];
$replace_arr = [
'SALUTATION' => User::getCorrectUserSalutation($rep_userinfo),
'NAME' => $rep_userinfo['name'],
'FIRSTNAME' => $rep_userinfo['firstname'],
'COMPANY' => $rep_userinfo['company'],
'CUSTOMER_NO' => $rep_userinfo['customernumber'],
'DISKAVAILABLE' => round(($row['diskspace'] / 1024), 2), /* traffic is stored in KB, template uses MB */
'DISKUSED' => round($row['diskspace_used'] / 1024, 2), /* traffic is stored in KB, template uses MB */
'DISKAVAILABLE' => round(($row['diskspace'] / 1024), 2),
/* traffic is stored in KB, template uses MB */
'DISKUSED' => round($row['diskspace_used'] / 1024, 2),
/* traffic is stored in KB, template uses MB */
'USAGE_PERCENT' => round(($row['diskspace_used'] * 100) / $row['diskspace'], 2),
'MAX_PERCENT' => Settings::Get('system.report_webmax')
);
];
$lngfile_stmt = Database::prepare("
SELECT `file` FROM `" . TABLE_PANEL_LANGUAGE . "`
WHERE `language` = :deflang
");
$lngfile = Database::pexecute_first($lngfile_stmt, array(
$lngfile = Database::pexecute_first($lngfile_stmt, [
'deflang' => $row['def_language']
));
]);
if ($lngfile !== null) {
$langfile = $lngfile['file'];
} else {
$lngfile = Database::pexecute_first($lngfile_stmt, array(
$lngfile = Database::pexecute_first($lngfile_stmt, [
'deflang' => Settings::Get('panel.standardlanguage')
));
]);
$langfile = $lngfile['file'] ?? 'lng/english.lng.php';
}
// include english language file (fallback)
include \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/lng/english.lng.php');
include FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/lng/english.lng.php');
// include admin/customer language file
if ($lngfile != 'lng/english.lng.php') {
include \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/' . $langfile);
include FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/' . $langfile);
}
// Get mail templates from database; the ones from 'admin' are fetched for fallback
@@ -418,17 +441,17 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
AND `language` = :lang
AND `templategroup` = 'mails' AND `varname` = :varname
");
$result2_data = array(
$result2_data = [
'adminid' => $row['adminid'],
'lang' => $row['def_language'],
'varname' => 'diskmaxpercent_subject'
);
];
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_subject = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['subject']), $replace_arr));
$mail_subject = html_entity_decode(PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['subject']), $replace_arr));
$result2_data['varname'] = 'diskmaxpercent_mailbody';
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_body = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['mailbody']), $replace_arr));
$mail_body = html_entity_decode(PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['mailbody']), $replace_arr));
$_mailerror = false;
$mailerr_msg = "";
@@ -442,13 +465,13 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
} catch (\PHPMailer\PHPMailer\Exception $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (\Exception $e) {
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg);
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg);
echo "Error sending mail: " . $mailerr_msg . "\n";
}
@@ -457,9 +480,9 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `reportsent` = '2'
WHERE `customerid` = :customerid
");
Database::pexecute($upd_stmt, array(
Database::pexecute($upd_stmt, [
'customerid' => $row['customerid']
));
]);
unset($lng);
}
@@ -472,40 +495,40 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
SELECT `a`.* FROM `" . TABLE_PANEL_ADMINS . "` `a` WHERE `a`.`reportsent` <> '2'
");
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
if (isset($row['diskspace']) && $row['diskspace_used'] != null && $row['diskspace_used'] > 0 && (($row['diskspace_used'] * 100) / $row['diskspace']) >= (int) Settings::Get('system.report_webmax')) {
$replace_arr = array(
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
if (isset($row['diskspace']) && $row['diskspace_used'] != null && $row['diskspace_used'] > 0 && (($row['diskspace_used'] * 100) / $row['diskspace']) >= (int)Settings::Get('system.report_webmax')) {
$replace_arr = [
'NAME' => $row['name'],
'DISKAVAILABLE' => ($row['diskspace'] / 1024), /* traffic is stored in KB, template uses MB */
'DISKUSED' => round($row['diskspace_used'] / 1024, 2), /* traffic is stored in KB, template uses MB */
'DISKAVAILABLE' => ($row['diskspace'] / 1024),
/* traffic is stored in KB, template uses MB */
'DISKUSED' => round($row['diskspace_used'] / 1024, 2),
/* traffic is stored in KB, template uses MB */
'USAGE_PERCENT' => ($row['diskspace_used'] * 100) / $row['diskspace'],
'MAX_PERCENT' => Settings::Get('system.report_webmax')
);
];
$lngfile_stmt = Database::prepare("
SELECT `file` FROM `" . TABLE_PANEL_LANGUAGE . "`
WHERE `language` = :deflang
");
$lngfile = Database::pexecute_first($lngfile_stmt, array(
$lngfile = Database::pexecute_first($lngfile_stmt, [
'deflang' => $row['def_language']
));
]);
if ($lngfile !== null) {
$langfile = $lngfile['file'];
} else {
$lngfile = Database::pexecute_first($lngfile_stmt, array(
$lngfile = Database::pexecute_first($lngfile_stmt, [
'deflang' => Settings::Get('panel.standardlanguage')
));
]);
$langfile = $lngfile['file'];
}
// include english language file (fallback)
include \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/lng/english.lng.php');
include FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/lng/english.lng.php');
// include admin/customer language file
if ($lngfile != 'lng/english.lng.php') {
include \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/' . $langfile);
include FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/' . $langfile);
}
// Get mail templates from database; the ones from 'admin' are fetched for fallback
@@ -515,17 +538,17 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
AND `language` = :lang
AND `templategroup` = 'mails' AND `varname` = :varname
");
$result2_data = array(
$result2_data = [
'adminid' => $row['adminid'],
'lang' => $row['def_language'],
'varname' => 'diskmaxpercent_subject'
);
];
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_subject = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['subject']), $replace_arr));
$mail_subject = html_entity_decode(PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['subject']), $replace_arr));
$result2_data['varname'] = 'diskmaxpercent_mailbody';
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_body = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['mailbody']), $replace_arr));
$mail_body = html_entity_decode(PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['mailbody']), $replace_arr));
$_mailerror = false;
$mailerr_msg = "";
@@ -539,13 +562,13 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
} catch (\PHPMailer\PHPMailer\Exception $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (\Exception $e) {
} catch (Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg);
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg);
echo "Error sending mail: " . $mailerr_msg . "\n";
}
@@ -554,9 +577,9 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
UPDATE `" . TABLE_PANEL_ADMINS . "` SET `reportsent` = '2'
WHERE `adminid` = :adminid
");
Database::pexecute($upd_stmt, array(
Database::pexecute($upd_stmt, [
'adminid' => $row['adminid']
));
]);
unset($lng);
}

File diff suppressed because it is too large Load Diff