diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 539d79c5..d5d5c831 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -9,12 +9,10 @@ features or refactoring, especially not the kind which requires changes to a lot of files. Please focus on our API based version 0.10.x (current master). - - - ## Checklist General rules for PRs are: + * Please save us all some trouble and unnecessary round-trips by _testing_ your changes. @@ -24,34 +22,24 @@ changes. the next changes it back, a third one changes it again, only a little differently... - Thanks! - - - ### Webserver changes If you make changes to the functionality of webserver configuration, please make sure your implementation covers all supported webservers. - - - ### l10n If you add new language strings, please make sure you add the english fallback strings in -* `lng/english.lng.php` -* `install/lng/english.lng.php` (if applicable) - - - +* `lng/en.lng.php` +* `install/lng/en.lng.php` (if applicable) ### New settings and database-layout changes + If you add new settings or layout changes, please make sure you add these to -* `install/froxlor.sql` +* `install/froxlor.sql.php` * and handle the update (see `install/updates/froxlor/0.10/update_0.10.inc.php`) * if you have any question on how update-process works, please contact us - diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 910e6594..90bf4402 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,24 +1,20 @@ # Bug report vs. support request + If you're unsure of whether your problem is a bug or a configuration error * contact us via IRC in #froxlor on irc.libera.chat * or post a thread in our forum at https://forum.froxlor.org As a rule of thumb: before reporting an issue + * see if it hasn't been [reported](https://github.com/Froxlor/froxlor/issues) (and possibly already been [fixed](https://github.com/Froxlor/froxlor/issues?utf8=✓&q=is:issue%20is:closed)) first * try with the git master - - - - # Summary Please provide a concise summary of the problem you're experiencing... - - - # System information + * Froxlor version: $version/$gitSHA1 * Web server: apache2/nginx/lighttpd * DNS server: Bind/PowerDNS (standalone)/PowerDNS (Bind-backend) @@ -27,37 +23,26 @@ Please provide a concise summary of the problem you're experiencing... * FTP server: proftpd/pureftpd * OS/Version: ... - - - # Steps to reproduce 1. 2. 3. - - - # Expected behavior 1. 2. 3. - - - # Actual behavior 1. 2. 3. - - - # Log files/log entries + syslog:
 example
diff --git a/.github/LICENSE_HEADER b/.github/LICENSE_HEADER
index ea2ee538..9982cafc 100644
--- a/.github/LICENSE_HEADER
+++ b/.github/LICENSE_HEADER
@@ -9,14 +9,14 @@
  *
  * 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
+ * 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
- * http://files.froxlor.org/misc/COPYING.txt
+ * https://files.froxlor.org/misc/COPYING.txt
  *
  * @copyright  the authors
  * @author     Froxlor team 
- * @license    http://files.froxlor.org/misc/COPYING.txt GPLv2
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 6b107ce3..8e700c76 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -35,4 +35,3 @@ Please describe the tests that you ran to verify your changes. Provide instructi
 - [ ] My changes generate no new warnings
 - [ ] I have added tests that prove my fix is effective or that my feature works
 - [ ] New and existing unit tests pass locally with my changes
-
diff --git a/2fa.php b/2fa.php
index 53779d64..859d216b 100644
--- a/2fa.php
+++ b/2fa.php
@@ -1,33 +1,44 @@
 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
+ */
+
 if (!defined('AREA')) {
 	header("Location: index.php");
 	exit();
 }
 
 use Froxlor\Database\Database;
+use Froxlor\FroxlorLogger;
+use Froxlor\FroxlorTwoFactorAuth;
 use Froxlor\Settings;
 use Froxlor\UI\Panel\UI;
+use Froxlor\UI\Response;
 
 if (Settings::Get('2fa.enabled') != '1') {
-	\Froxlor\UI\Response::dynamic_error("2FA not activated");
+	Response::dynamicError('2fa.2fa_not_activated');
 }
 
-/**
- * This file is part of the Froxlor project.
- * Copyright (c) 2018 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
- *
- * @copyright (c) the authors
- * @author Froxlor team  (2018-)
- * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package Panel
- * @since 0.10.0
- *
- */
-
 // This file is being included in admin_index and customer_index
 // and therefore does not need to require lib/init.php
 if (AREA == 'admin') {
@@ -39,16 +50,16 @@ if (AREA == 'admin') {
 }
 $success_message = "";
 
-$tfa = new \Froxlor\FroxlorTwoFactorAuth('Froxlor ' . Settings::Get('system.hostname'));
+$tfa = new FroxlorTwoFactorAuth('Froxlor ' . Settings::Get('system.hostname'));
 
 // do the delete and then just show a success-message
 if ($action == 'delete') {
-	Database::pexecute($upd_stmt, array(
+	Database::pexecute($upd_stmt, [
 		't2fa' => 0,
 		'd2fa' => "",
 		'id' => $uid
-	));
-	\Froxlor\UI\Response::standard_success($lng['2fa']['2fa_removed']);
+	]);
+	Response::standardSuccess('2fa.2fa_removed');
 } elseif ($action == 'add') {
 	$type = isset($_POST['type_2fa']) ? $_POST['type_2fa'] : '0';
 
@@ -59,26 +70,25 @@ if ($action == 'delete') {
 		// generate secret for TOTP
 		$data = $tfa->createSecret();
 	}
-	Database::pexecute($upd_stmt, array(
+	Database::pexecute($upd_stmt, [
 		't2fa' => $type,
 		'd2fa' => $data,
 		'id' => $uid
-	));
-	\Froxlor\UI\Response::standard_success(sprintf($lng['2fa']['2fa_added'], $filename));
+	]);
+	Response::standardSuccess('2fa.2fa_added', [$filename]);
 }
 
-$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed 2fa::overview");
+$log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed 2fa::overview");
 
 $type_select_values = [];
 $ga_qrcode = '';
 if ($userinfo['type_2fa'] == '0') {
-
 	// available types
-	$type_select_values = array(
+	$type_select_values = [
 		0 => '-',
 		1 => 'E-Mail',
 		2 => 'Authenticator'
-	);
+	];
 	asort($type_select_values);
 } elseif ($userinfo['type_2fa'] == '1') {
 	// email 2fa enabled
diff --git a/actions/admin/settings/100.panel.php b/actions/admin/settings/100.panel.php
index 8d2739af..81ce0050 100644
--- a/actions/admin/settings/100.panel.php
+++ b/actions/admin/settings/100.panel.php
@@ -2,121 +2,128 @@
 
 /**
  * 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  (2003-2009)
- * @author     Froxlor team  (2010-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    Language
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
-return array(
-	'groups' => array(
-		'panel' => array(
-			'title' => $lng['admin']['panelsettings'],
+
+return [
+	'groups' => [
+		'panel' => [
+			'title' => lng('admin.panelsettings'),
 			'icon' => 'fa-solid fa-chalkboard-user',
-			'fields' => array(
-				'panel_standardlanguage' => array(
-					'label' => array(
-						'title' => $lng['login']['language'],
-						'description' => $lng['serversettings']['language']['description']
-					),
+			'fields' => [
+				'panel_standardlanguage' => [
+					'label' => [
+						'title' => lng('login.language'),
+						'description' => lng('serversettings.language.description')
+					],
 					'settinggroup' => 'panel',
 					'varname' => 'standardlanguage',
 					'type' => 'select',
 					'default' => 'English',
-					'option_options_method' => array(
+					'option_options_method' => [
 						'\\Froxlor\\User',
 						'getLanguages'
-					),
+					],
 					'save_method' => 'storeSettingField'
-				),
-				'panel_default_theme' => array(
-					'label' => array(
-						'title' => $lng['panel']['theme'],
-						'description' => $lng['serversettings']['default_theme']
-					),
+				],
+				'panel_default_theme' => [
+					'label' => [
+						'title' => lng('panel.theme'),
+						'description' => lng('serversettings.default_theme')
+					],
 					'settinggroup' => 'panel',
 					'varname' => 'default_theme',
 					'type' => 'select',
 					'default' => 'Froxlor',
-					'option_options_method' => array(
+					'option_options_method' => [
 						'\\Froxlor\\UI\\Panel\\UI',
 						'getThemes'
-					),
+					],
 					'save_method' => 'storeSettingDefaultTheme'
-				),
-				'panel_allow_theme_change_customer' => array(
-					'label' => $lng['serversettings']['panel_allow_theme_change_customer'],
+				],
+				'panel_allow_theme_change_customer' => [
+					'label' => lng('serversettings.panel_allow_theme_change_customer'),
 					'settinggroup' => 'panel',
 					'varname' => 'allow_theme_change_customer',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField'
-				),
-				'panel_allow_theme_change_admin' => array(
-					'label' => $lng['serversettings']['panel_allow_theme_change_admin'],
+				],
+				'panel_allow_theme_change_admin' => [
+					'label' => lng('serversettings.panel_allow_theme_change_admin'),
 					'settinggroup' => 'panel',
 					'varname' => 'allow_theme_change_admin',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField'
-				),
-				'panel_natsorting' => array(
-					'label' => $lng['serversettings']['natsorting'],
+				],
+				'panel_natsorting' => [
+					'label' => lng('serversettings.natsorting'),
 					'settinggroup' => 'panel',
 					'varname' => 'natsorting',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'panel_paging' => array(
-					'label' => $lng['serversettings']['paging'],
+				],
+				'panel_paging' => [
+					'label' => lng('serversettings.paging'),
 					'settinggroup' => 'panel',
 					'varname' => 'paging',
 					'type' => 'number',
 					'min' => 0,
 					'default' => 0,
 					'save_method' => 'storeSettingField'
-				),
-				'panel_pathedit' => array(
-					'label' => $lng['serversettings']['pathedit'],
+				],
+				'panel_pathedit' => [
+					'label' => lng('serversettings.pathedit'),
 					'settinggroup' => 'panel',
 					'varname' => 'pathedit',
 					'type' => 'select',
 					'default' => 'Manual',
 					'select_var' => [
-						'Manual' => $lng['serversettings']['manual'],
-						'Dropdown' => $lng['serversettings']['dropdown']
+						'Manual' => lng('serversettings.manual'),
+						'Dropdown' => lng('serversettings.dropdown')
 					],
 					'save_method' => 'storeSettingField'
-				),
-				'panel_adminmail' => array(
-					'label' => $lng['serversettings']['adminmail'],
+				],
+				'panel_adminmail' => [
+					'label' => lng('serversettings.adminmail'),
 					'settinggroup' => 'panel',
 					'varname' => 'adminmail',
 					'type' => 'email',
 					'string_emptyallowed' => true,
 					'default' => '',
 					'save_method' => 'storeSettingField'
-				),
-				'panel_adminmail_defname' => array(
-					'label' => $lng['serversettings']['adminmail_defname'],
+				],
+				'panel_adminmail_defname' => [
+					'label' => lng('serversettings.adminmail_defname'),
 					'settinggroup' => 'panel',
 					'varname' => 'adminmail_defname',
 					'type' => 'text',
 					'default' => 'Froxlor Administrator',
 					'save_method' => 'storeSettingField'
-				),
-				'panel_adminmail_return' => array(
-					'label' => $lng['serversettings']['adminmail_return'],
+				],
+				'panel_adminmail_return' => [
+					'label' => lng('serversettings.adminmail_return'),
 					'settinggroup' => 'panel',
 					'varname' => 'adminmail_return',
 					'type' => 'email',
@@ -124,9 +131,9 @@ return array(
 					'default' => '',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'panel_decimal_places' => array(
-					'label' => $lng['serversettings']['decimal_places'],
+				],
+				'panel_decimal_places' => [
+					'label' => lng('serversettings.decimal_places'),
 					'settinggroup' => 'panel',
 					'varname' => 'decimal_places',
 					'type' => 'number',
@@ -135,105 +142,105 @@ return array(
 					'default' => 4,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'panel_phpmyadmin_url' => array(
-					'label' => $lng['serversettings']['phpmyadmin_url'],
+				],
+				'panel_phpmyadmin_url' => [
+					'label' => lng('serversettings.phpmyadmin_url'),
 					'settinggroup' => 'panel',
 					'varname' => 'phpmyadmin_url',
 					'type' => 'url',
 					'string_emptyallowed' => true,
 					'default' => '',
 					'save_method' => 'storeSettingField'
-				),
-				'panel_webmail_url' => array(
-					'label' => $lng['serversettings']['webmail_url'],
+				],
+				'panel_webmail_url' => [
+					'label' => lng('serversettings.webmail_url'),
 					'settinggroup' => 'panel',
 					'varname' => 'webmail_url',
 					'type' => 'url',
 					'string_emptyallowed' => true,
 					'default' => '',
 					'save_method' => 'storeSettingField'
-				),
-				'panel_webftp_url' => array(
-					'label' => $lng['serversettings']['webftp_url'],
+				],
+				'panel_webftp_url' => [
+					'label' => lng('serversettings.webftp_url'),
 					'settinggroup' => 'panel',
 					'varname' => 'webftp_url',
 					'type' => 'url',
 					'string_emptyallowed' => true,
 					'default' => '',
 					'save_method' => 'storeSettingField'
-				),
-				'admin_show_version_login' => array(
-					'label' => $lng['admin']['show_version_login'],
+				],
+				'admin_show_version_login' => [
+					'label' => lng('admin.show_version_login'),
 					'settinggroup' => 'admin',
 					'varname' => 'show_version_login',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'admin_show_version_footer' => array(
-					'label' => $lng['admin']['show_version_footer'],
+				],
+				'admin_show_version_footer' => [
+					'label' => lng('admin.show_version_footer'),
 					'settinggroup' => 'admin',
 					'varname' => 'show_version_footer',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'admin_show_news_feed' => array(
-					'label' => $lng['admin']['show_news_feed'],
+				],
+				'admin_show_news_feed' => [
+					'label' => lng('admin.show_news_feed'),
 					'settinggroup' => 'admin',
 					'varname' => 'show_news_feed',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'customer_show_news_feed' => array(
-					'label' => $lng['admin']['customer_show_news_feed'],
+				],
+				'customer_show_news_feed' => [
+					'label' => lng('admin.customer_show_news_feed'),
 					'settinggroup' => 'customer',
 					'varname' => 'show_news_feed',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'customer_news_feed_url' => array(
-					'label' => $lng['admin']['customer_news_feed_url'],
+				],
+				'customer_news_feed_url' => [
+					'label' => lng('admin.customer_news_feed_url'),
 					'settinggroup' => 'customer',
 					'varname' => 'news_feed_url',
 					'type' => 'url',
 					'string_emptyallowed' => true,
 					'default' => '',
 					'save_method' => 'storeSettingField'
-				),
-				'panel_allow_domain_change_admin' => array(
-					'label' => $lng['serversettings']['panel_allow_domain_change_admin'],
+				],
+				'panel_allow_domain_change_admin' => [
+					'label' => lng('serversettings.panel_allow_domain_change_admin'),
 					'settinggroup' => 'panel',
 					'varname' => 'allow_domain_change_admin',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'panel_allow_domain_change_customer' => array(
-					'label' => $lng['serversettings']['panel_allow_domain_change_customer'],
+				],
+				'panel_allow_domain_change_customer' => [
+					'label' => lng('serversettings.panel_allow_domain_change_customer'),
 					'settinggroup' => 'panel',
 					'varname' => 'allow_domain_change_customer',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'panel_phpconfigs_hidestdsubdomain' => array(
-					'label' => $lng['serversettings']['panel_phpconfigs_hidestdsubdomain'],
+				],
+				'panel_phpconfigs_hidestdsubdomain' => [
+					'label' => lng('serversettings.panel_phpconfigs_hidestdsubdomain'),
 					'settinggroup' => 'panel',
 					'varname' => 'phpconfigs_hidestdsubdomain',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'panel_customer_hide_options' => array(
-					'label' => $lng['serversettings']['panel_customer_hide_options'],
+				],
+				'panel_customer_hide_options' => [
+					'label' => lng('serversettings.panel_customer_hide_options'),
 					'settinggroup' => 'panel',
 					'varname' => 'customer_hide_options',
 					'type' => 'select',
@@ -241,85 +248,85 @@ return array(
 					'select_mode' => 'multiple',
 					'option_emptyallowed' => true,
 					'select_var' => [
-						'email' => $lng['menue']['email']['email'],
-						'mysql' => $lng['menue']['mysql']['mysql'],
-						'domains' => $lng['menue']['domains']['domains'],
-						'ftp' => $lng['menue']['ftp']['ftp'],
-						'extras' => $lng['menue']['extras']['extras'],
-						'extras.directoryprotection' => $lng['menue']['extras']['extras'] . " / " . $lng['menue']['extras']['directoryprotection'],
-						'extras.pathoptions' => $lng['menue']['extras']['extras'] . " / " . $lng['menue']['extras']['pathoptions'],
-						'extras.logger' => $lng['menue']['extras']['extras'] . " / " . $lng['admin']['loggersystem'],
-						'extras.backup' => $lng['menue']['extras']['extras'] . " / " . $lng['menue']['extras']['backup'],
-						'traffic' => $lng['menue']['traffic']['traffic'],
-						'traffic.http' => $lng['menue']['traffic']['traffic'] . " / HTTP",
-						'traffic.ftp' => $lng['menue']['traffic']['traffic'] . " / FTP",
-						'traffic.mail' => $lng['menue']['traffic']['traffic'] . " / Mail"
+						'email' => lng('menue.email.email'),
+						'mysql' => lng('menue.mysql.mysql'),
+						'domains' => lng('menue.domains.domains'),
+						'ftp' => lng('menue.ftp.ftp'),
+						'extras' => lng('menue.extras.extras'),
+						'extras.directoryprotection' => lng('menue.extras.extras') . " / " . lng('menue.extras.directoryprotection'),
+						'extras.pathoptions' => lng('menue.extras.extras') . " / " . lng('menue.extras.pathoptions'),
+						'extras.logger' => lng('menue.extras.extras') . " / " . lng('admin.loggersystem'),
+						'extras.backup' => lng('menue.extras.extras') . " / " . lng('menue.extras.backup'),
+						'traffic' => lng('menue.traffic.traffic'),
+						'traffic.http' => lng('menue.traffic.traffic') . " / HTTP",
+						'traffic.ftp' => lng('menue.traffic.traffic') . " / FTP",
+						'traffic.mail' => lng('menue.traffic.traffic') . " / Mail"
 					],
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'panel_imprint_url' => array(
-					'label' => $lng['serversettings']['imprint_url'],
+				],
+				'panel_imprint_url' => [
+					'label' => lng('serversettings.imprint_url'),
 					'settinggroup' => 'panel',
 					'varname' => 'imprint_url',
 					'type' => 'url',
 					'string_emptyallowed' => true,
 					'default' => '',
 					'save_method' => 'storeSettingField'
-				),
-				'panel_terms_url' => array(
-					'label' => $lng['serversettings']['terms_url'],
+				],
+				'panel_terms_url' => [
+					'label' => lng('serversettings.terms_url'),
 					'settinggroup' => 'panel',
 					'varname' => 'terms_url',
 					'type' => 'url',
 					'string_emptyallowed' => true,
 					'default' => '',
 					'save_method' => 'storeSettingField'
-				),
-				'panel_privacy_url' => array(
-					'label' => $lng['serversettings']['privacy_url'],
+				],
+				'panel_privacy_url' => [
+					'label' => lng('serversettings.privacy_url'),
 					'settinggroup' => 'panel',
 					'varname' => 'privacy_url',
 					'type' => 'url',
 					'string_emptyallowed' => true,
 					'default' => '',
 					'save_method' => 'storeSettingField'
-				),
-				'panel_logo_overridetheme' => array(
-					'label' => $lng['serversettings']['logo_overridetheme'],
+				],
+				'panel_logo_overridetheme' => [
+					'label' => lng('serversettings.logo_overridetheme'),
 					'settinggroup' => 'panel',
 					'varname' => 'logo_overridetheme',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'panel_logo_overridecustom' => array(
-					'label' => $lng['serversettings']['logo_overridecustom'],
+				],
+				'panel_logo_overridecustom' => [
+					'label' => lng('serversettings.logo_overridecustom'),
 					'settinggroup' => 'panel',
 					'varname' => 'logo_overridecustom',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'panel_logo_image_header' => array(
-					'label' => $lng['serversettings']['logo_image_header'],
+				],
+				'panel_logo_image_header' => [
+					'label' => lng('serversettings.logo_image_header'),
 					'settinggroup' => 'panel',
 					'varname' => 'logo_image_header',
 					'type' => 'image',
 					'image_name' => 'logo_header',
 					'default' => '',
 					'save_method' => 'storeSettingImage'
-				),
-				'panel_logo_image_login' => array(
-					'label' => $lng['serversettings']['logo_image_login'],
+				],
+				'panel_logo_image_login' => [
+					'label' => lng('serversettings.logo_image_login'),
 					'settinggroup' => 'panel',
 					'varname' => 'logo_image_login',
 					'type' => 'image',
 					'image_name' => 'logo_login',
 					'default' => '',
 					'save_method' => 'storeSettingImage'
-				)
-			)
-		)
-	)
-);
+				]
+			]
+		]
+	]
+];
diff --git a/actions/admin/settings/110.accounts.php b/actions/admin/settings/110.accounts.php
index e6d381e2..c3ebcca2 100644
--- a/actions/admin/settings/110.accounts.php
+++ b/actions/admin/settings/110.accounts.php
@@ -2,229 +2,236 @@
 
 /**
  * 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  (2003-2009)
- * @author     Froxlor team  (2010-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    Settings
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
-return array(
-	'groups' => array(
-		'accounts' => array(
-			'title' => $lng['admin']['accountsettings'],
+
+return [
+	'groups' => [
+		'accounts' => [
+			'title' => lng('admin.accountsettings'),
 			'icon' => 'fa-solid fa-users-gear',
-			'fields' => array(
-				'session_sessiontimeout' => array(
-					'label' => $lng['serversettings']['session_timeout'],
+			'fields' => [
+				'session_sessiontimeout' => [
+					'label' => lng('serversettings.session_timeout'),
 					'settinggroup' => 'session',
 					'varname' => 'sessiontimeout',
 					'type' => 'number',
 					'min' => 60,
 					'default' => 600,
 					'save_method' => 'storeSettingField'
-				),
-				'session_allow_multiple_login' => array(
-					'label' => $lng['serversettings']['session_allow_multiple_login'],
+				],
+				'session_allow_multiple_login' => [
+					'label' => lng('serversettings.session_allow_multiple_login'),
 					'settinggroup' => 'session',
 					'varname' => 'allow_multiple_login',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'login_domain_login' => array(
-					'label' => $lng['serversettings']['login_domain_login'],
+				],
+				'login_domain_login' => [
+					'label' => lng('serversettings.login_domain_login'),
 					'settinggroup' => 'login',
 					'varname' => 'domain_login',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'login_maxloginattempts' => array(
-					'label' => $lng['serversettings']['maxloginattempts'],
+				],
+				'login_maxloginattempts' => [
+					'label' => lng('serversettings.maxloginattempts'),
 					'settinggroup' => 'login',
 					'varname' => 'maxloginattempts',
 					'type' => 'number',
 					'min' => 1,
 					'default' => 3,
 					'save_method' => 'storeSettingField'
-				),
-				'login_deactivatetime' => array(
-					'label' => $lng['serversettings']['deactivatetime'],
+				],
+				'login_deactivatetime' => [
+					'label' => lng('serversettings.deactivatetime'),
 					'settinggroup' => 'login',
 					'varname' => 'deactivatetime',
 					'type' => 'number',
 					'min' => 0,
 					'default' => 900,
 					'save_method' => 'storeSettingField'
-				),
-				'2fa_enabled' => array(
-					'label' => $lng['2fa']['2fa_enabled'],
+				],
+				'2fa_enabled' => [
+					'label' => lng('2fa.2fa_enabled'),
 					'settinggroup' => '2fa',
 					'varname' => 'enabled',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField'
-				),
-				'panel_password_min_length' => array(
-					'label' => $lng['serversettings']['panel_password_min_length'],
+				],
+				'panel_password_min_length' => [
+					'label' => lng('serversettings.panel_password_min_length'),
 					'settinggroup' => 'panel',
 					'varname' => 'password_min_length',
 					'type' => 'number',
 					'min' => 0,
 					'default' => 0,
 					'save_method' => 'storeSettingField'
-				),
-				'panel_password_alpha_lower' => array(
-					'label' => $lng['serversettings']['panel_password_alpha_lower'],
+				],
+				'panel_password_alpha_lower' => [
+					'label' => lng('serversettings.panel_password_alpha_lower'),
 					'settinggroup' => 'panel',
 					'varname' => 'password_alpha_lower',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField'
-				),
-				'panel_password_alpha_upper' => array(
-					'label' => $lng['serversettings']['panel_password_alpha_upper'],
+				],
+				'panel_password_alpha_upper' => [
+					'label' => lng('serversettings.panel_password_alpha_upper'),
 					'settinggroup' => 'panel',
 					'varname' => 'password_alpha_upper',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField'
-				),
-				'panel_password_numeric' => array(
-					'label' => $lng['serversettings']['panel_password_numeric'],
+				],
+				'panel_password_numeric' => [
+					'label' => lng('serversettings.panel_password_numeric'),
 					'settinggroup' => 'panel',
 					'varname' => 'password_numeric',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'panel_password_special_char_required' => array(
-					'label' => $lng['serversettings']['panel_password_special_char_required'],
+				],
+				'panel_password_special_char_required' => [
+					'label' => lng('serversettings.panel_password_special_char_required'),
 					'settinggroup' => 'panel',
 					'varname' => 'password_special_char_required',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'panel_password_special_char' => array(
-					'label' => $lng['serversettings']['panel_password_special_char'],
+				],
+				'panel_password_special_char' => [
+					'label' => lng('serversettings.panel_password_special_char'),
 					'settinggroup' => 'panel',
 					'varname' => 'password_special_char',
 					'type' => 'text',
 					'default' => '!?<>§$%+#=@',
 					'save_method' => 'storeSettingField'
-				),
-				'panel_password_regex' => array(
-					'label' => $lng['serversettings']['panel_password_regex'],
+				],
+				'panel_password_regex' => [
+					'label' => lng('serversettings.panel_password_regex'),
 					'settinggroup' => 'panel',
 					'varname' => 'password_regex',
 					'type' => 'text',
 					'default' => '',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'customer_accountprefix' => array(
-					'label' => $lng['serversettings']['accountprefix'],
+				],
+				'customer_accountprefix' => [
+					'label' => lng('serversettings.accountprefix'),
 					'settinggroup' => 'customer',
 					'varname' => 'accountprefix',
 					'type' => 'text',
 					'default' => '',
-					'plausibility_check_method' => array(
+					'plausibility_check_method' => [
 						'\\Froxlor\\Validate\\Check',
 						'checkUsername'
-					),
+					],
 					'save_method' => 'storeSettingField'
-				),
-				'customer_mysqlprefix' => array(
-					'label' => $lng['serversettings']['mysqlprefix'],
+				],
+				'customer_mysqlprefix' => [
+					'label' => lng('serversettings.mysqlprefix'),
 					'settinggroup' => 'customer',
 					'varname' => 'mysqlprefix',
 					'type' => 'text',
 					'default' => '',
-					'plausibility_check_method' => array(
+					'plausibility_check_method' => [
 						'\\Froxlor\\Validate\\Check',
 						'checkUsername'
-					),
+					],
 					'save_method' => 'storeSettingField'
-				),
-				'customer_ftpprefix' => array(
-					'label' => $lng['serversettings']['ftpprefix'],
+				],
+				'customer_ftpprefix' => [
+					'label' => lng('serversettings.ftpprefix'),
 					'settinggroup' => 'customer',
 					'varname' => 'ftpprefix',
 					'type' => 'text',
 					'default' => '',
 					'save_method' => 'storeSettingField'
-				),
-				'customer_ftpatdomain' => array(
-					'label' => $lng['serversettings']['ftpdomain'],
+				],
+				'customer_ftpatdomain' => [
+					'label' => lng('serversettings.ftpdomain'),
 					'settinggroup' => 'customer',
 					'varname' => 'ftpatdomain',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'panel_allow_preset' => array(
-					'label' => $lng['serversettings']['allow_password_reset'],
+				],
+				'panel_allow_preset' => [
+					'label' => lng('serversettings.allow_password_reset'),
 					'settinggroup' => 'panel',
 					'varname' => 'allow_preset',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
-					'dependency' => array(
+					'dependency' => [
 						'fieldname' => 'panel_allow_preset_admin',
-						'fielddata' => array(
+						'fielddata' => [
 							'settinggroup' => 'panel',
 							'varname' => 'allow_preset_admin'
-						),
+						],
 						'onlyif' => 0
-					)
-				),
-				'panel_allow_preset_admin' => array(
-					'label' => $lng['serversettings']['allow_password_reset_admin'],
+					]
+				],
+				'panel_allow_preset_admin' => [
+					'label' => lng('serversettings.allow_password_reset_admin'),
 					'settinggroup' => 'panel',
 					'varname' => 'allow_preset_admin',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
-					'dependency' => array(
+					'dependency' => [
 						'fieldname' => 'panel_allow_preset',
-						'fielddata' => array(
+						'fielddata' => [
 							'settinggroup' => 'panel',
 							'varname' => 'allow_preset'
-						),
+						],
 						'onlyif' => 1
-					)
-				),
-				'system_backupenabled' => array(
-					'label' => $lng['serversettings']['backupenabled'],
+					]
+				],
+				'system_backupenabled' => [
+					'label' => lng('serversettings.backupenabled'),
 					'settinggroup' => 'system',
 					'varname' => 'backupenabled',
 					'type' => 'checkbox',
 					'default' => false,
 					'cronmodule' => 'froxlor/backup',
 					'save_method' => 'storeSettingField'
-				),
-				'system_createstdsubdom_default' => array(
-					'label' => $lng['serversettings']['createstdsubdom_default'],
+				],
+				'system_createstdsubdom_default' => [
+					'label' => lng('serversettings.createstdsubdom_default'),
 					'settinggroup' => 'system',
 					'varname' => 'createstdsubdom_default',
 					'type' => 'select',
 					'default' => '1',
-					'select_var' => array(
-						'0' => $lng['panel']['no'],
-						'1' => $lng['panel']['yes']
-					),
+					'select_var' => [
+						'0' => lng('panel.no'),
+						'1' => lng('panel.yes')
+					],
 					'save_method' => 'storeSettingField'
-				),
-			)
-		)
-	)
-);
+				],
+			]
+		]
+	]
+];
diff --git a/actions/admin/settings/120.system.php b/actions/admin/settings/120.system.php
index afc676dc..ba3dd152 100644
--- a/actions/admin/settings/120.system.php
+++ b/actions/admin/settings/120.system.php
@@ -2,143 +2,150 @@
 
 /**
  * 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  (2003-2009)
- * @author     Froxlor team  (2010-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    Settings
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
-return array(
-	'groups' => array(
-		'system' => array(
-			'title' => $lng['admin']['systemsettings'],
+
+return [
+	'groups' => [
+		'system' => [
+			'title' => lng('admin.systemsettings'),
 			'icon' => 'fa-solid fa-gears',
-			'fields' => array(
-				'system_documentroot_prefix' => array(
-					'label' => $lng['serversettings']['documentroot_prefix'],
+			'fields' => [
+				'system_documentroot_prefix' => [
+					'label' => lng('serversettings.documentroot_prefix'),
 					'settinggroup' => 'system',
 					'varname' => 'documentroot_prefix',
 					'type' => 'text',
 					'string_type' => 'dir',
 					'default' => '/var/customers/webs/',
 					'save_method' => 'storeSettingField',
-					'plausibility_check_method' => array(
+					'plausibility_check_method' => [
 						'\\Froxlor\\Validate\\Check',
 						'checkPathConflicts'
-					)
-				),
-				'system_documentroot_use_default_value' => array(
-					'label' => $lng['serversettings']['documentroot_use_default_value'],
+					]
+				],
+				'system_documentroot_use_default_value' => [
+					'label' => lng('serversettings.documentroot_use_default_value'),
 					'settinggroup' => 'system',
 					'varname' => 'documentroot_use_default_value',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'system_ipaddress' => array(
-					'label' => $lng['serversettings']['ipaddress'],
+				],
+				'system_ipaddress' => [
+					'label' => lng('serversettings.ipaddress'),
 					'settinggroup' => 'system',
 					'varname' => 'ipaddress',
 					'type' => 'select',
-					'option_options_method' => array(
+					'option_options_method' => [
 						'\\Froxlor\\Domain\\IpAddr',
 						'getIpAddresses'
-					),
+					],
 					'default' => '',
 					'save_method' => 'storeSettingIpAddress'
-				),
-				'system_defaultip' => array(
-					'label' => $lng['serversettings']['defaultip'],
+				],
+				'system_defaultip' => [
+					'label' => lng('serversettings.defaultip'),
 					'settinggroup' => 'system',
 					'varname' => 'defaultip',
 					'type' => 'select',
 					'select_mode' => 'multiple',
-					'option_options_method' => array(
+					'option_options_method' => [
 						'\\Froxlor\\Domain\\IpAddr',
 						'getIpPortCombinations'
-					),
+					],
 					'default' => '',
 					'save_method' => 'storeSettingDefaultIp'
-				),
-				'system_defaultsslip' => array(
-					'label' => $lng['serversettings']['defaultsslip'],
+				],
+				'system_defaultsslip' => [
+					'label' => lng('serversettings.defaultsslip'),
 					'settinggroup' => 'system',
 					'varname' => 'defaultsslip',
 					'type' => 'select',
 					'select_mode' => 'multiple',
-					'option_options_method' => array(
+					'option_options_method' => [
 						'\\Froxlor\\Domain\\IpAddr',
 						'getSslIpPortCombinations'
-					),
+					],
 					'default' => '',
 					'save_method' => 'storeSettingDefaultSslIp'
-				),
-				'system_hostname' => array(
-					'label' => $lng['serversettings']['hostname'],
+				],
+				'system_hostname' => [
+					'label' => lng('serversettings.hostname'),
 					'settinggroup' => 'system',
 					'varname' => 'hostname',
 					'type' => 'text',
 					'default' => '',
 					'save_method' => 'storeSettingHostname',
-					'plausibility_check_method' => array(
+					'plausibility_check_method' => [
 						'\\Froxlor\\Validate\\Check',
 						'checkHostname'
-					)
-				),
-				'api_enabled' => array(
-					'label' => $lng['serversettings']['enable_api'],
+					]
+				],
+				'api_enabled' => [
+					'label' => lng('serversettings.enable_api'),
 					'settinggroup' => 'api',
 					'varname' => 'enabled',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'system_validatedomain' => array(
-					'label' => $lng['serversettings']['validate_domain'],
+				],
+				'system_validatedomain' => [
+					'label' => lng('serversettings.validate_domain'),
 					'settinggroup' => 'system',
 					'varname' => 'validate_domain',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField'
-				),
-				'system_stdsubdomain' => array(
-					'label' => $lng['serversettings']['stdsubdomainhost'],
+				],
+				'system_stdsubdomain' => [
+					'label' => lng('serversettings.stdsubdomainhost'),
 					'settinggroup' => 'system',
 					'varname' => 'stdsubdomain',
 					'type' => 'text',
 					'default' => '',
 					'save_method' => 'storeSettingHostname'
-				),
-				'system_mysql_access_host' => array(
-					'label' => $lng['serversettings']['mysql_access_host'],
+				],
+				'system_mysql_access_host' => [
+					'label' => lng('serversettings.mysql_access_host'),
 					'settinggroup' => 'system',
 					'varname' => 'mysql_access_host',
 					'type' => 'text',
 					'default' => '127.0.0.1,localhost',
-					'plausibility_check_method' => array(
+					'plausibility_check_method' => [
 						'\\Froxlor\\Validate\\Check',
 						'checkMysqlAccessHost'
-					),
+					],
 					'save_method' => 'storeSettingMysqlAccessHost'
-				),
-				'system_nssextrausers' => array(
-					'label' => $lng['serversettings']['nssextrausers'],
+				],
+				'system_nssextrausers' => [
+					'label' => lng('serversettings.nssextrausers'),
 					'settinggroup' => 'system',
 					'varname' => 'nssextrausers',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'system_index_file_extension' => array(
-					'label' => $lng['serversettings']['index_file_extension'],
+				],
+				'system_index_file_extension' => [
+					'label' => lng('serversettings.index_file_extension'),
 					'settinggroup' => 'system',
 					'varname' => 'index_file_extension',
 					'type' => 'text',
@@ -146,38 +153,38 @@ return array(
 					'default' => 'html',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_store_index_file_subs' => array(
-					'label' => $lng['serversettings']['system_store_index_file_subs'],
+				],
+				'system_store_index_file_subs' => [
+					'label' => lng('serversettings.system_store_index_file_subs'),
 					'settinggroup' => 'system',
 					'varname' => 'store_index_file_subs',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField'
-				),
-				'system_httpuser' => array(
+				],
+				'system_httpuser' => [
 					'settinggroup' => 'system',
 					'varname' => 'httpuser',
 					'type' => 'hidden',
 					'default' => 'www-data'
-				),
-				'system_httpgroup' => array(
+				],
+				'system_httpgroup' => [
 					'settinggroup' => 'system',
 					'varname' => 'httpgroup',
 					'type' => 'hidden',
 					'default' => 'www-data'
-				),
-				'system_report_enable' => array(
-					'label' => $lng['serversettings']['report']['report'],
+				],
+				'system_report_enable' => [
+					'label' => lng('serversettings.report.report'),
 					'settinggroup' => 'system',
 					'varname' => 'report_enable',
 					'type' => 'checkbox',
 					'default' => true,
 					'cronmodule' => 'froxlor/reports',
 					'save_method' => 'storeSettingField'
-				),
-				'system_report_webmax' => array(
-					'label' => $lng['serversettings']['report']['webmax'],
+				],
+				'system_report_webmax' => [
+					'label' => lng('serversettings.report.webmax'),
 					'settinggroup' => 'system',
 					'varname' => 'report_webmax',
 					'type' => 'number',
@@ -185,9 +192,9 @@ return array(
 					'max' => 150,
 					'default' => 90,
 					'save_method' => 'storeSettingField'
-				),
-				'system_report_trafficmax' => array(
-					'label' => $lng['serversettings']['report']['trafficmax'],
+				],
+				'system_report_trafficmax' => [
+					'label' => lng('serversettings.report.trafficmax'),
 					'settinggroup' => 'system',
 					'varname' => 'report_trafficmax',
 					'type' => 'number',
@@ -195,25 +202,25 @@ return array(
 					'max' => 150,
 					'default' => 90,
 					'save_method' => 'storeSettingField'
-				),
-				'system_mail_use_smtp' => array(
-					'label' => $lng['serversettings']['mail_use_smtp'],
+				],
+				'system_mail_use_smtp' => [
+					'label' => lng('serversettings.mail_use_smtp'),
 					'settinggroup' => 'system',
 					'varname' => 'mail_use_smtp',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'system_mail_smtp_host' => array(
-					'label' => $lng['serversettings']['mail_smtp_host'],
+				],
+				'system_mail_smtp_host' => [
+					'label' => lng('serversettings.mail_smtp_host'),
 					'settinggroup' => 'system',
 					'varname' => 'mail_smtp_host',
 					'type' => 'text',
 					'default' => 'localhost',
 					'save_method' => 'storeSettingField'
-				),
-				'system_mail_smtp_port' => array(
-					'label' => $lng['serversettings']['mail_smtp_port'],
+				],
+				'system_mail_smtp_port' => [
+					'label' => lng('serversettings.mail_smtp_port'),
 					'settinggroup' => 'system',
 					'varname' => 'mail_smtp_port',
 					'type' => 'number',
@@ -221,81 +228,81 @@ return array(
 					'max' => 65535,
 					'default' => 25,
 					'save_method' => 'storeSettingField'
-				),
-				'system_mail_smtp_usetls' => array(
-					'label' => $lng['serversettings']['mail_smtp_usetls'],
+				],
+				'system_mail_smtp_usetls' => [
+					'label' => lng('serversettings.mail_smtp_usetls'),
 					'settinggroup' => 'system',
 					'varname' => 'mail_smtp_usetls',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField'
-				),
-				'system_mail_smtp_auth' => array(
-					'label' => $lng['serversettings']['mail_smtp_auth'],
+				],
+				'system_mail_smtp_auth' => [
+					'label' => lng('serversettings.mail_smtp_auth'),
 					'settinggroup' => 'system',
 					'varname' => 'mail_smtp_auth',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField'
-				),
-				'system_mail_smtp_user' => array(
-					'label' => $lng['serversettings']['mail_smtp_user'],
+				],
+				'system_mail_smtp_user' => [
+					'label' => lng('serversettings.mail_smtp_user'),
 					'settinggroup' => 'system',
 					'varname' => 'mail_smtp_user',
 					'type' => 'text',
 					'default' => '',
 					'save_method' => 'storeSettingField'
-				),
-				'system_mail_smtp_passwd' => array(
-					'label' => $lng['serversettings']['mail_smtp_passwd'],
+				],
+				'system_mail_smtp_passwd' => [
+					'label' => lng('serversettings.mail_smtp_passwd'),
 					'settinggroup' => 'system',
 					'varname' => 'mail_smtp_passwd',
 					'type' => 'password',
 					'default' => '',
 					'save_method' => 'storeSettingField'
-				),
-				'system_apply_specialsettings_default' => array(
-					'label' => $lng['serversettings']['apply_specialsettings_default'],
+				],
+				'system_apply_specialsettings_default' => [
+					'label' => lng('serversettings.apply_specialsettings_default'),
 					'settinggroup' => 'system',
 					'varname' => 'apply_specialsettings_default',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_apply_phpconfigs_default' => array(
-					'label' => $lng['serversettings']['apply_phpconfigs_default'],
+				],
+				'system_apply_phpconfigs_default' => [
+					'label' => lng('serversettings.apply_phpconfigs_default'),
 					'settinggroup' => 'system',
 					'varname' => 'apply_phpconfigs_default',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_domaindefaultalias' => array(
-					'label' => $lng['admin']['domaindefaultalias'],
+				],
+				'system_domaindefaultalias' => [
+					'label' => lng('admin.domaindefaultalias'),
 					'settinggroup' => 'system',
 					'varname' => 'domaindefaultalias',
 					'type' => 'select',
 					'default' => '0',
-					'select_var' => array(
-						'0' => $lng['domains']['serveraliasoption_wildcard'],
-						'1' => $lng['domains']['serveraliasoption_www'],
-						'2' => $lng['domains']['serveraliasoption_none']
-					),
+					'select_var' => [
+						'0' => lng('domains.serveraliasoption_wildcard'),
+						'1' => lng('domains.serveraliasoption_www'),
+						'2' => lng('domains.serveraliasoption_none')
+					],
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'hide_incompatible_settings' => array(
-					'label' => $lng['serversettings']['hide_incompatible_settings'],
+				],
+				'hide_incompatible_settings' => [
+					'label' => lng('serversettings.hide_incompatible_settings'),
 					'settinggroup' => 'system',
 					'varname' => 'hide_incompatible_settings',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-			)
-		)
-	)
-);
+				],
+			]
+		]
+	]
+];
diff --git a/actions/admin/settings/122.froxlorvhost.php b/actions/admin/settings/122.froxlorvhost.php
index be6f6d98..eb17552f 100644
--- a/actions/admin/settings/122.froxlorvhost.php
+++ b/actions/admin/settings/122.froxlorvhost.php
@@ -2,37 +2,51 @@
 
 /**
  * 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  (2016-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    \Froxlor\Settings
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
-return array(
-	'groups' => array(
-		'froxlorvhost' => array(
-			'title' => $lng['admin']['froxlorvhost'] . (call_user_func(array('\Froxlor\Settings\FroxlorVhostSettings', 'hasVhostContainerEnabled')) == false ? $lng['admin']['novhostcontainer'] : ''),
+
+use Froxlor\Settings;
+
+return [
+	'groups' => [
+		'froxlorvhost' => [
+			'title' => lng('admin.froxlorvhost') . (call_user_func([
+					'\Froxlor\Settings\FroxlorVhostSettings',
+					'hasVhostContainerEnabled'
+				]) == false ? lng('admin.novhostcontainer') : ''),
 			'icon' => 'fa-solid fa-wrench',
-			'fields' => array(
+			'fields' => [
 				/**
 				 * Webserver-Vhost
 				 */
-				'system_froxlordirectlyviahostname' => array(
-					'label' => $lng['serversettings']['froxlordirectlyviahostname'],
+				'system_froxlordirectlyviahostname' => [
+					'label' => lng('serversettings.froxlordirectlyviahostname'),
 					'settinggroup' => 'system',
 					'varname' => 'froxlordirectlyviahostname',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'system_froxloraliases' => array(
-					'label' => $lng['serversettings']['froxloraliases'],
+				],
+				'system_froxloraliases' => [
+					'label' => lng('serversettings.froxloraliases'),
 					'settinggroup' => 'system',
 					'varname' => 'froxloraliases',
 					'type' => 'text',
@@ -41,36 +55,36 @@ return array(
 					'default' => '',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
+				],
 				/**
 				 * SSL / Let's Encrypt
 				 */
-				'system_le_froxlor_enabled' => array(
-					'label' => $lng['serversettings']['le_froxlor_enabled'],
+				'system_le_froxlor_enabled' => [
+					'label' => lng('serversettings.le_froxlor_enabled'),
 					'settinggroup' => 'system',
 					'varname' => 'le_froxlor_enabled',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingClearCertificates',
-					'visible' => \Froxlor\Settings::Get('system.leenabled') && call_user_func(array(
-						'\Froxlor\Settings\FroxlorVhostSettings',
-						'hasVhostContainerEnabled'
-					), true)
-				),
-				'system_le_froxlor_redirect' => array(
-					'label' => $lng['serversettings']['le_froxlor_redirect'],
+					'visible' => Settings::Get('system.leenabled') && call_user_func([
+							'\Froxlor\Settings\FroxlorVhostSettings',
+							'hasVhostContainerEnabled'
+						], true)
+				],
+				'system_le_froxlor_redirect' => [
+					'label' => lng('serversettings.le_froxlor_redirect'),
 					'settinggroup' => 'system',
 					'varname' => 'le_froxlor_redirect',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
-					'visible' => \Froxlor\Settings::Get('system.use_ssl') && call_user_func(array(
-						'\Froxlor\Settings\FroxlorVhostSettings',
-						'hasVhostContainerEnabled'
-					), true)
-				),
-				'system_hsts_maxage' => array(
-					'label' => $lng['admin']['domain_hsts_maxage'],
+					'visible' => Settings::Get('system.use_ssl') && call_user_func([
+							'\Froxlor\Settings\FroxlorVhostSettings',
+							'hasVhostContainerEnabled'
+						], true)
+				],
+				'system_hsts_maxage' => [
+					'label' => lng('admin.domain_hsts_maxage'),
 					'settinggroup' => 'system',
 					'varname' => 'hsts_maxage',
 					'type' => 'number',
@@ -78,199 +92,199 @@ return array(
 					'max' => 94608000, // 3-years
 					'default' => 10368000,
 					'save_method' => 'storeSettingField',
-					'visible' => \Froxlor\Settings::Get('system.use_ssl') && call_user_func(array(
-						'\Froxlor\Settings\FroxlorVhostSettings',
-						'hasVhostContainerEnabled'
-					), true),
+					'visible' => Settings::Get('system.use_ssl') && call_user_func([
+							'\Froxlor\Settings\FroxlorVhostSettings',
+							'hasVhostContainerEnabled'
+						], true),
 					'advanced_mode' => true
-				),
-				'system_hsts_incsub' => array(
-					'label' => $lng['admin']['domain_hsts_incsub'],
+				],
+				'system_hsts_incsub' => [
+					'label' => lng('admin.domain_hsts_incsub'),
 					'settinggroup' => 'system',
 					'varname' => 'hsts_incsub',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
-					'visible' => \Froxlor\Settings::Get('system.use_ssl') && call_user_func(array(
-						'\Froxlor\Settings\FroxlorVhostSettings',
-						'hasVhostContainerEnabled'
-					), true),
+					'visible' => Settings::Get('system.use_ssl') && call_user_func([
+							'\Froxlor\Settings\FroxlorVhostSettings',
+							'hasVhostContainerEnabled'
+						], true),
 					'advanced_mode' => true
-				),
-				'system_hsts_preload' => array(
-					'label' => $lng['admin']['domain_hsts_preload'],
+				],
+				'system_hsts_preload' => [
+					'label' => lng('admin.domain_hsts_preload'),
 					'settinggroup' => 'system',
 					'varname' => 'hsts_preload',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
-					'visible' => \Froxlor\Settings::Get('system.use_ssl') && call_user_func(array(
-						'\Froxlor\Settings\FroxlorVhostSettings',
-						'hasVhostContainerEnabled'
-					), true),
+					'visible' => Settings::Get('system.use_ssl') && call_user_func([
+							'\Froxlor\Settings\FroxlorVhostSettings',
+							'hasVhostContainerEnabled'
+						], true),
 					'advanced_mode' => true
-				),
-				'system_honorcipherorder' => array(
-					'label' => $lng['admin']['domain_honorcipherorder'],
+				],
+				'system_honorcipherorder' => [
+					'label' => lng('admin.domain_honorcipherorder'),
 					'settinggroup' => 'system',
 					'varname' => 'honorcipherorder',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
-					'visible' => \Froxlor\Settings::Get('system.use_ssl') && call_user_func(array(
-						'\Froxlor\Settings\FroxlorVhostSettings',
-						'hasVhostContainerEnabled'
-					), true),
+					'visible' => Settings::Get('system.use_ssl') && call_user_func([
+							'\Froxlor\Settings\FroxlorVhostSettings',
+							'hasVhostContainerEnabled'
+						], true),
 					'advanced_mode' => true
-				),
-				'system_sessiontickets' => array(
-					'label' => $lng['admin']['domain_sessiontickets'],
+				],
+				'system_sessiontickets' => [
+					'label' => lng('admin.domain_sessiontickets'),
 					'settinggroup' => 'system',
 					'varname' => 'sessiontickets',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField',
-					'visible' => \Froxlor\Settings::Get('system.use_ssl') && call_user_func(array(
-						'\Froxlor\Settings\FroxlorVhostSettings',
-						'hasVhostContainerEnabled'
-					), true),
+					'visible' => Settings::Get('system.use_ssl') && call_user_func([
+							'\Froxlor\Settings\FroxlorVhostSettings',
+							'hasVhostContainerEnabled'
+						], true),
 					'advanced_mode' => true
-				),
+				],
 				/**
 				 * FCGID
 				 */
-				'system_mod_fcgid_enabled_ownvhost' => array(
-					'label' => $lng['serversettings']['mod_fcgid_ownvhost'],
+				'system_mod_fcgid_enabled_ownvhost' => [
+					'label' => lng('serversettings.mod_fcgid_ownvhost'),
 					'settinggroup' => 'system',
 					'varname' => 'mod_fcgid_ownvhost',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'apache2'
-					),
-					'visible' => \Froxlor\Settings::Get('system.mod_fcgid') && call_user_func(array(
-						'\Froxlor\Settings\FroxlorVhostSettings',
-						'hasVhostContainerEnabled'
-					))
-				),
-				'system_mod_fcgid_httpuser' => array(
-					'label' => $lng['admin']['mod_fcgid_user'],
+					],
+					'visible' => Settings::Get('system.mod_fcgid') && call_user_func([
+							'\Froxlor\Settings\FroxlorVhostSettings',
+							'hasVhostContainerEnabled'
+						])
+				],
+				'system_mod_fcgid_httpuser' => [
+					'label' => lng('admin.mod_fcgid_user'),
 					'settinggroup' => 'system',
 					'varname' => 'mod_fcgid_httpuser',
 					'type' => 'text',
 					'default' => 'froxlorlocal',
 					'save_method' => 'storeSettingWebserverFcgidFpmUser',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'apache2'
-					),
-					'visible' => \Froxlor\Settings::Get('system.mod_fcgid') && call_user_func(array(
-						'\Froxlor\Settings\FroxlorVhostSettings',
-						'hasVhostContainerEnabled'
-					))
-				),
-				'system_mod_fcgid_httpgroup' => array(
-					'label' => $lng['admin']['mod_fcgid_group'],
+					],
+					'visible' => Settings::Get('system.mod_fcgid') && call_user_func([
+							'\Froxlor\Settings\FroxlorVhostSettings',
+							'hasVhostContainerEnabled'
+						])
+				],
+				'system_mod_fcgid_httpgroup' => [
+					'label' => lng('admin.mod_fcgid_group'),
 					'settinggroup' => 'system',
 					'varname' => 'mod_fcgid_httpgroup',
 					'type' => 'text',
 					'default' => 'froxlorlocal',
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'apache2'
-					),
-					'visible' => \Froxlor\Settings::Get('system.mod_fcgid') && call_user_func(array(
-						'\Froxlor\Settings\FroxlorVhostSettings',
-						'hasVhostContainerEnabled'
-					))
-				),
-				'system_mod_fcgid_defaultini_ownvhost' => array(
-					'label' => $lng['serversettings']['mod_fcgid']['defaultini_ownvhost'],
+					],
+					'visible' => Settings::Get('system.mod_fcgid') && call_user_func([
+							'\Froxlor\Settings\FroxlorVhostSettings',
+							'hasVhostContainerEnabled'
+						])
+				],
+				'system_mod_fcgid_defaultini_ownvhost' => [
+					'label' => lng('serversettings.mod_fcgid.defaultini_ownvhost'),
 					'settinggroup' => 'system',
 					'varname' => 'mod_fcgid_defaultini_ownvhost',
 					'type' => 'select',
 					'default' => '2',
-					'option_options_method' => array(
+					'option_options_method' => [
 						'\\Froxlor\\Http\\PhpConfig',
 						'getPhpConfigs'
-					),
+					],
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'apache2'
-					),
-					'visible' => \Froxlor\Settings::Get('system.mod_fcgid') && call_user_func(array(
-						'\Froxlor\Settings\FroxlorVhostSettings',
-						'hasVhostContainerEnabled'
-					))
-				),
+					],
+					'visible' => Settings::Get('system.mod_fcgid') && call_user_func([
+							'\Froxlor\Settings\FroxlorVhostSettings',
+							'hasVhostContainerEnabled'
+						])
+				],
 				/**
 				 * php-fpm
 				 */
-				'system_phpfpm_enabled_ownvhost' => array(
-					'label' => $lng['phpfpm']['ownvhost'],
+				'system_phpfpm_enabled_ownvhost' => [
+					'label' => lng('phpfpm.ownvhost'),
 					'settinggroup' => 'phpfpm',
 					'varname' => 'enabled_ownvhost',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField',
-					'visible' => \Froxlor\Settings::Get('phpfpm.enabled') && call_user_func(array(
-						'\Froxlor\Settings\FroxlorVhostSettings',
-						'hasVhostContainerEnabled'
-					))
-				),
-				'system_phpfpm_httpuser' => array(
-					'label' => $lng['phpfpm']['vhost_httpuser'],
+					'visible' => Settings::Get('phpfpm.enabled') && call_user_func([
+							'\Froxlor\Settings\FroxlorVhostSettings',
+							'hasVhostContainerEnabled'
+						])
+				],
+				'system_phpfpm_httpuser' => [
+					'label' => lng('phpfpm.vhost_httpuser'),
 					'settinggroup' => 'phpfpm',
 					'varname' => 'vhost_httpuser',
 					'type' => 'text',
 					'default' => 'froxlorlocal',
 					'save_method' => 'storeSettingWebserverFcgidFpmUser',
-					'visible' => \Froxlor\Settings::Get('phpfpm.enabled') && call_user_func(array(
-						'\Froxlor\Settings\FroxlorVhostSettings',
-						'hasVhostContainerEnabled'
-					))
-				),
-				'system_phpfpm_httpgroup' => array(
-					'label' => $lng['phpfpm']['vhost_httpgroup'],
+					'visible' => Settings::Get('phpfpm.enabled') && call_user_func([
+							'\Froxlor\Settings\FroxlorVhostSettings',
+							'hasVhostContainerEnabled'
+						])
+				],
+				'system_phpfpm_httpgroup' => [
+					'label' => lng('phpfpm.vhost_httpgroup'),
 					'settinggroup' => 'phpfpm',
 					'varname' => 'vhost_httpgroup',
 					'type' => 'text',
 					'default' => 'froxlorlocal',
 					'save_method' => 'storeSettingField',
-					'visible' => \Froxlor\Settings::Get('phpfpm.enabled') && call_user_func(array(
-						'\Froxlor\Settings\FroxlorVhostSettings',
-						'hasVhostContainerEnabled'
-					))
-				),
-				'system_phpfpm_defaultini_ownvhost' => array(
-					'label' => $lng['serversettings']['mod_fcgid']['defaultini_ownvhost'],
+					'visible' => Settings::Get('phpfpm.enabled') && call_user_func([
+							'\Froxlor\Settings\FroxlorVhostSettings',
+							'hasVhostContainerEnabled'
+						])
+				],
+				'system_phpfpm_defaultini_ownvhost' => [
+					'label' => lng('serversettings.mod_fcgid.defaultini_ownvhost'),
 					'settinggroup' => 'phpfpm',
 					'varname' => 'vhost_defaultini',
 					'type' => 'select',
 					'default' => '2',
-					'option_options_method' => array(
+					'option_options_method' => [
 						'\\Froxlor\\Http\\PhpConfig',
 						'getPhpConfigs'
-					),
+					],
 					'save_method' => 'storeSettingField',
-					'visible' => \Froxlor\Settings::Get('phpfpm.enabled') && call_user_func(array(
-						'\Froxlor\Settings\FroxlorVhostSettings',
-						'hasVhostContainerEnabled'
-					))
-				),
+					'visible' => Settings::Get('phpfpm.enabled') && call_user_func([
+							'\Froxlor\Settings\FroxlorVhostSettings',
+							'hasVhostContainerEnabled'
+						])
+				],
 				/**
 				 * DNS
 				 */
-				'system_dns_createhostnameentry' => array(
-					'label' => $lng['serversettings']['dns_createhostnameentry'],
+				'system_dns_createhostnameentry' => [
+					'label' => lng('serversettings.dns_createhostnameentry'),
 					'settinggroup' => 'system',
 					'varname' => 'dns_createhostnameentry',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
-					'visible' => \Froxlor\Settings::Get('system.bind_enable')
-				)
-			)
-		)
-	)
-);
+					'visible' => Settings::Get('system.bind_enable')
+				]
+			]
+		]
+	]
+];
diff --git a/actions/admin/settings/125.cronjob.php b/actions/admin/settings/125.cronjob.php
index 9217f1c4..383c0d19 100644
--- a/actions/admin/settings/125.cronjob.php
+++ b/actions/admin/settings/125.cronjob.php
@@ -2,67 +2,76 @@
 
 /**
  * This file is part of the Froxlor project.
- * Copyright (c) 2014 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  (2010-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    Settings
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
-return array(
-	'groups' => array(
-		'crond' => array(
-			'title' => $lng['admin']['cronsettings'],
+
+return [
+	'groups' => [
+		'crond' => [
+			'title' => lng('admin.cronsettings'),
 			'icon' => 'fa-solid fa-clock-rotate-left',
 			'advanced_mode' => true,
-			'fields' => array(
-				'system_cronconfig' => array(
-					'label' => $lng['serversettings']['system_cronconfig'],
+			'fields' => [
+				'system_cronconfig' => [
+					'label' => lng('serversettings.system_cronconfig'),
 					'settinggroup' => 'system',
 					'varname' => 'cronconfig',
 					'type' => 'text',
 					'string_type' => 'file',
 					'default' => '/etc/cron.d/froxlor',
 					'save_method' => 'storeSettingField'
-				),
-				'system_croncmdline' => array(
-					'label' => $lng['serversettings']['system_croncmdline'],
+				],
+				'system_croncmdline' => [
+					'label' => lng('serversettings.system_croncmdline'),
 					'settinggroup' => 'system',
 					'varname' => 'croncmdline',
 					'type' => 'text',
 					'default' => '/usr/bin/nice -n 5 /usr/bin/php -q',
 					'save_method' => 'storeSettingField'
-				),
-				'system_crondreload' => array(
-					'label' => $lng['serversettings']['system_crondreload'],
+				],
+				'system_crondreload' => [
+					'label' => lng('serversettings.system_crondreload'),
 					'settinggroup' => 'system',
 					'varname' => 'crondreload',
 					'type' => 'text',
 					'default' => '/etc/init.d/cron reload',
 					'save_method' => 'storeSettingField'
-				),
-				'system_cron_allowautoupdate' => array(
-					'label' => $lng['serversettings']['system_cron_allowautoupdate'],
+				],
+				'system_cron_allowautoupdate' => [
+					'label' => lng('serversettings.system_cron_allowautoupdate'),
 					'settinggroup' => 'system',
 					'varname' => 'cron_allowautoupdate',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'system_debug_cron' => array(
-					'label' => $lng['serversettings']['cron']['debug'],
+				],
+				'system_debug_cron' => [
+					'label' => lng('serversettings.cron.debug'),
 					'settinggroup' => 'system',
 					'varname' => 'debug_cron',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				)
-			)
-		)
-	)
-);
+				]
+			]
+		]
+	]
+];
diff --git a/actions/admin/settings/130.webserver.php b/actions/admin/settings/130.webserver.php
index 265519b2..5ab57cc5 100644
--- a/actions/admin/settings/130.webserver.php
+++ b/actions/admin/settings/130.webserver.php
@@ -2,82 +2,91 @@
 
 /**
  * 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  (2003-2009)
- * @author     Froxlor team  (2010-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    \Froxlor\Settings
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
-return array(
-	'groups' => array(
-		'webserver' => array(
-			'title' => $lng['admin']['webserversettings'],
+
+use Froxlor\Settings;
+
+return [
+	'groups' => [
+		'webserver' => [
+			'title' => lng('admin.webserversettings'),
 			'icon' => 'fa-solid fa-server',
-			'fields' => array(
-				'system_webserver' => array(
-					'label' => $lng['admin']['webserver'],
+			'fields' => [
+				'system_webserver' => [
+					'label' => lng('admin.webserver'),
 					'settinggroup' => 'system',
 					'varname' => 'webserver',
 					'type' => 'select',
 					'default' => 'apache2',
-					'select_var' => array(
+					'select_var' => [
 						'apache2' => 'Apache 2',
 						'lighttpd' => 'ligHTTPd',
 						'nginx' => 'Nginx'
-					),
+					],
 					'save_method' => 'storeSettingField',
-					'plausibility_check_method' => array(
+					'plausibility_check_method' => [
 						'\\Froxlor\\Validate\\Check',
 						'checkPhpInterfaceSetting'
-					)
-				),
-				'system_apache_24' => array(
-					'label' => $lng['serversettings']['apache_24'],
+					]
+				],
+				'system_apache_24' => [
+					'label' => lng('serversettings.apache_24'),
 					'settinggroup' => 'system',
 					'varname' => 'apache24',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'apache2'
-					)
-				),
-				'system_apache_itksupport' => array(
-					'label' => $lng['serversettings']['apache_itksupport'],
+					]
+				],
+				'system_apache_itksupport' => [
+					'label' => lng('serversettings.apache_itksupport'),
 					'settinggroup' => 'system',
 					'varname' => 'apacheitksupport',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
-					'visible' => (\Froxlor\Settings::Get('system.mod_fcgid') == 0 && \Froxlor\Settings::Get('phpfpm.enabled') == 0),
-					'websrv_avail' => array(
+					'visible' => (Settings::Get('system.mod_fcgid') == 0 && Settings::Get('phpfpm.enabled') == 0),
+					'websrv_avail' => [
 						'apache2'
-					),
+					],
 					'advanced_mode' => true
-				),
-				'system_http2_support' => array(
-					'label' => $lng['serversettings']['http2_support'],
+				],
+				'system_http2_support' => [
+					'label' => lng('serversettings.http2_support'),
 					'settinggroup' => 'system',
 					'varname' => 'http2_support',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'apache2',
 						'nginx'
-					),
-					'visible' => \Froxlor\Settings::Get('system.use_ssl')
-				),
-				'system_dhparams_file' => array(
-					'label' => $lng['serversettings']['dhparams_file'],
+					],
+					'visible' => Settings::Get('system.use_ssl')
+				],
+				'system_dhparams_file' => [
+					'label' => lng('serversettings.dhparams_file'),
 					'settinggroup' => 'system',
 					'varname' => 'dhparams_file',
 					'type' => 'text',
@@ -85,122 +94,122 @@ return array(
 					'string_emptyallowed' => true,
 					'default' => '',
 					'save_method' => 'storeSettingField',
-					'visible' => \Froxlor\Settings::Get('system.use_ssl'),
+					'visible' => Settings::Get('system.use_ssl'),
 					'advanced_mode' => true
-				),
-				'system_httpuser' => array(
-					'label' => $lng['admin']['webserver_user'],
+				],
+				'system_httpuser' => [
+					'label' => lng('admin.webserver_user'),
 					'settinggroup' => 'system',
 					'varname' => 'httpuser',
 					'type' => 'text',
 					'default' => 'www-data',
 					'save_method' => 'storeSettingWebserverFcgidFpmUser'
-				),
-				'system_httpgroup' => array(
-					'label' => $lng['admin']['webserver_group'],
+				],
+				'system_httpgroup' => [
+					'label' => lng('admin.webserver_group'),
 					'settinggroup' => 'system',
 					'varname' => 'httpgroup',
 					'type' => 'text',
 					'default' => 'www-data',
 					'save_method' => 'storeSettingField'
-				),
-				'system_apacheconf_vhost' => array(
-					'label' => $lng['serversettings']['apacheconf_vhost'],
+				],
+				'system_apacheconf_vhost' => [
+					'label' => lng('serversettings.apacheconf_vhost'),
 					'settinggroup' => 'system',
 					'varname' => 'apacheconf_vhost',
 					'type' => 'text',
 					'string_type' => 'filedir',
 					'default' => '/etc/apache2/sites-enabled/',
 					'save_method' => 'storeSettingField'
-				),
-				'system_apacheconf_diroptions' => array(
-					'label' => $lng['serversettings']['apacheconf_diroptions'],
+				],
+				'system_apacheconf_diroptions' => [
+					'label' => lng('serversettings.apacheconf_diroptions'),
 					'settinggroup' => 'system',
 					'varname' => 'apacheconf_diroptions',
 					'type' => 'text',
 					'string_type' => 'filedir',
 					'default' => '/etc/apache2/sites-enabled/',
 					'save_method' => 'storeSettingField'
-				),
-				'system_apacheconf_htpasswddir' => array(
-					'label' => $lng['serversettings']['apacheconf_htpasswddir'],
+				],
+				'system_apacheconf_htpasswddir' => [
+					'label' => lng('serversettings.apacheconf_htpasswddir'),
 					'settinggroup' => 'system',
 					'varname' => 'apacheconf_htpasswddir',
 					'type' => 'text',
 					'string_type' => 'confdir',
 					'default' => '/etc/apache2/htpasswd/',
 					'save_method' => 'storeSettingField'
-				),
-				'system_logfiles_directory' => array(
-					'label' => $lng['serversettings']['logfiles_directory'],
+				],
+				'system_logfiles_directory' => [
+					'label' => lng('serversettings.logfiles_directory'),
 					'settinggroup' => 'system',
 					'varname' => 'logfiles_directory',
 					'type' => 'text',
 					'string_type' => 'dir',
 					'default' => '/var/customers/logs/',
 					'save_method' => 'storeSettingField'
-				),
-				'system_logfiles_script' => array(
-					'label' => $lng['serversettings']['logfiles_script'],
+				],
+				'system_logfiles_script' => [
+					'label' => lng('serversettings.logfiles_script'),
 					'settinggroup' => 'system',
 					'varname' => 'logfiles_script',
 					'type' => 'text',
 					'default' => '',
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'apache2'
-					),
+					],
 					'advanced_mode' => true
-				),
-				'system_logfiles_piped' => array(
-					'label' => $lng['serversettings']['logfiles_piped'],
+				],
+				'system_logfiles_piped' => [
+					'label' => lng('serversettings.logfiles_piped'),
 					'settinggroup' => 'system',
 					'varname' => 'logfiles_piped',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'apache2'
-					),
+					],
 					'advanced_mode' => true
-				),
-				'system_logfiles_format' => array(
-					'label' => $lng['serversettings']['logfiles_format'],
+				],
+				'system_logfiles_format' => [
+					'label' => lng('serversettings.logfiles_format'),
 					'settinggroup' => 'system',
 					'varname' => 'logfiles_format',
 					'type' => 'text',
 					'default' => '',
 					'string_emptyallowed' => true,
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'apache2',
 						'nginx'
-					),
-					'visible' => \Froxlor\Settings::Get('system.awstats_enabled') == 1,
+					],
+					'visible' => Settings::Get('system.awstats_enabled') == 1,
 					'advanced_mode' => true
-				),
-				'system_logfiles_type' => array(
-					'label' => $lng['serversettings']['logfiles_type'],
+				],
+				'system_logfiles_type' => [
+					'label' => lng('serversettings.logfiles_type'),
 					'settinggroup' => 'system',
 					'varname' => 'logfiles_type',
 					'type' => 'select',
 					'default' => '1',
-					'select_var' => array(
+					'select_var' => [
 						'1' => 'combined',
 						'2' => 'vhost_combined'
-					),
+					],
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'apache2'
-					)
-				),
-				'system_errorlog_level' => array(
-					'label' => $lng['serversettings']['errorlog_level'],
+					]
+				],
+				'system_errorlog_level' => [
+					'label' => lng('serversettings.errorlog_level'),
 					'settinggroup' => 'system',
 					'varname' => 'errorlog_level',
 					'type' => 'select',
-					'default' => (\Froxlor\Settings::Get('system.webserver') == 'nginx' ? 'error' : 'warn'),
-					'select_var' => array(
+					'default' => (Settings::Get('system.webserver') == 'nginx' ? 'error' : 'warn'),
+					'select_var' => [
 						'emerg' => 'emerg',
 						'alert' => 'alert',
 						'crit' => 'crit',
@@ -209,24 +218,24 @@ return array(
 						'notice' => 'notice',
 						'info' => 'info',
 						'debug' => 'debug'
-					),
+					],
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'apache2',
 						'nginx'
-					)
-				),
-				'system_customersslpath' => array(
-					'label' => $lng['serversettings']['customerssl_directory'],
+					]
+				],
+				'system_customersslpath' => [
+					'label' => lng('serversettings.customerssl_directory'),
 					'settinggroup' => 'system',
 					'varname' => 'customer_ssl_path',
 					'type' => 'text',
 					'string_type' => 'confdir',
 					'default' => '/etc/ssl/froxlor-custom/',
 					'save_method' => 'storeSettingField'
-				),
-				'system_phpappendopenbasedir' => array(
-					'label' => $lng['serversettings']['phpappendopenbasedir'],
+				],
+				'system_phpappendopenbasedir' => [
+					'label' => lng('serversettings.phpappendopenbasedir'),
 					'settinggroup' => 'system',
 					'varname' => 'phpappendopenbasedir',
 					'type' => 'text',
@@ -234,9 +243,9 @@ return array(
 					'default' => '',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_deactivateddocroot' => array(
-					'label' => $lng['serversettings']['deactivateddocroot'],
+				],
+				'system_deactivateddocroot' => [
+					'label' => lng('serversettings.deactivateddocroot'),
 					'settinggroup' => 'system',
 					'varname' => 'deactivateddocroot',
 					'type' => 'text',
@@ -244,165 +253,165 @@ return array(
 					'string_emptyallowed' => true,
 					'default' => '',
 					'save_method' => 'storeSettingField'
-				),
-				'system_default_vhostconf' => array(
-					'label' => $lng['serversettings']['default_vhostconf'],
+				],
+				'system_default_vhostconf' => [
+					'label' => lng('serversettings.default_vhostconf'),
 					'settinggroup' => 'system',
 					'varname' => 'default_vhostconf',
 					'type' => 'textarea',
 					'default' => '',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_default_sslvhostconf' => array(
-					'label' => $lng['serversettings']['default_sslvhostconf'],
+				],
+				'system_default_sslvhostconf' => [
+					'label' => lng('serversettings.default_sslvhostconf'),
 					'settinggroup' => 'system',
 					'varname' => 'default_sslvhostconf',
 					'type' => 'textarea',
 					'default' => '',
 					'save_method' => 'storeSettingField',
-					'visible' => \Froxlor\Settings::Get('system.use_ssl') == 1,
+					'visible' => Settings::Get('system.use_ssl') == 1,
 					'advanced_mode' => true
-				),
-				'system_include_default_vhostconf' => array(
-					'label' => $lng['serversettings']['includedefault_sslvhostconf'],
+				],
+				'system_include_default_vhostconf' => [
+					'label' => lng('serversettings.includedefault_sslvhostconf'),
 					'settinggroup' => 'system',
 					'varname' => 'include_default_vhostconf',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_apache_globaldiropt' => array(
-					'label' => $lng['serversettings']['apache_globaldiropt'],
+				],
+				'system_apache_globaldiropt' => [
+					'label' => lng('serversettings.apache_globaldiropt'),
 					'settinggroup' => 'system',
 					'varname' => 'apacheglobaldiropt',
 					'type' => 'textarea',
 					'default' => '',
 					'save_method' => 'storeSettingField',
-					'visible' => (\Froxlor\Settings::Get('system.mod_fcgid') == 0 && \Froxlor\Settings::Get('phpfpm.enabled') == 0),
-					'websrv_avail' => array(
+					'visible' => (Settings::Get('system.mod_fcgid') == 0 && Settings::Get('phpfpm.enabled') == 0),
+					'websrv_avail' => [
 						'apache2'
-					),
+					],
 					'advanced_mode' => true
-				),
-				'system_apachereload_command' => array(
-					'label' => $lng['serversettings']['apachereload_command'],
+				],
+				'system_apachereload_command' => [
+					'label' => lng('serversettings.apachereload_command'),
 					'settinggroup' => 'system',
 					'varname' => 'apachereload_command',
 					'type' => 'text',
 					'default' => '/etc/init.d/apache2 reload',
 					'save_method' => 'storeSettingField'
-				),
-				'system_phpreload_command' => array(
-					'label' => $lng['serversettings']['phpreload_command'],
+				],
+				'system_phpreload_command' => [
+					'label' => lng('serversettings.phpreload_command'),
 					'settinggroup' => 'system',
 					'varname' => 'phpreload_command',
 					'type' => 'text',
 					'default' => '',
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'nginx'
-					)
-				),
-				'system_nginx_php_backend' => array(
-					'label' => $lng['serversettings']['nginx_php_backend'],
+					]
+				],
+				'system_nginx_php_backend' => [
+					'label' => lng('serversettings.nginx_php_backend'),
 					'settinggroup' => 'system',
 					'varname' => 'nginx_php_backend',
 					'type' => 'text',
 					'default' => '127.0.0.1:8888',
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'nginx'
-					)
-				),
-				'nginx_fastcgiparams' => array(
-					'label' => $lng['serversettings']['nginx_fastcgiparams'],
+					]
+				],
+				'nginx_fastcgiparams' => [
+					'label' => lng('serversettings.nginx_fastcgiparams'),
 					'settinggroup' => 'nginx',
 					'varname' => 'fastcgiparams',
 					'type' => 'text',
 					'string_type' => 'file',
 					'default' => '/etc/nginx/fastcgi_params',
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'nginx'
-					)
-				),
-				'defaultwebsrverrhandler_enabled' => array(
-					'label' => $lng['serversettings']['defaultwebsrverrhandler_enabled'],
+					]
+				],
+				'defaultwebsrverrhandler_enabled' => [
+					'label' => lng('serversettings.defaultwebsrverrhandler_enabled'),
 					'settinggroup' => 'defaultwebsrverrhandler',
 					'varname' => 'enabled',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'defaultwebsrverrhandler_err401' => array(
-					'label' => $lng['serversettings']['defaultwebsrverrhandler_err401'],
+				],
+				'defaultwebsrverrhandler_err401' => [
+					'label' => lng('serversettings.defaultwebsrverrhandler_err401'),
 					'settinggroup' => 'defaultwebsrverrhandler',
 					'varname' => 'err401',
 					'type' => 'text',
 					'default' => '',
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'apache2',
 						'nginx'
-					),
+					],
 					'advanced_mode' => true
-				),
-				'defaultwebsrverrhandler_err403' => array(
-					'label' => $lng['serversettings']['defaultwebsrverrhandler_err403'],
+				],
+				'defaultwebsrverrhandler_err403' => [
+					'label' => lng('serversettings.defaultwebsrverrhandler_err403'),
 					'settinggroup' => 'defaultwebsrverrhandler',
 					'varname' => 'err403',
 					'type' => 'text',
 					'default' => '',
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'apache2',
 						'nginx'
-					),
+					],
 					'advanced_mode' => true
-				),
-				'defaultwebsrverrhandler_err404' => array(
-					'label' => $lng['serversettings']['defaultwebsrverrhandler_err404'],
+				],
+				'defaultwebsrverrhandler_err404' => [
+					'label' => lng('serversettings.defaultwebsrverrhandler_err404'),
 					'settinggroup' => 'defaultwebsrverrhandler',
 					'varname' => 'err404',
 					'type' => 'text',
 					'default' => '',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'defaultwebsrverrhandler_err500' => array(
-					'label' => $lng['serversettings']['defaultwebsrverrhandler_err500'],
+				],
+				'defaultwebsrverrhandler_err500' => [
+					'label' => lng('serversettings.defaultwebsrverrhandler_err500'),
 					'settinggroup' => 'defaultwebsrverrhandler',
 					'varname' => 'err500',
 					'type' => 'text',
 					'default' => '',
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'apache2',
 						'nginx'
-					),
+					],
 					'advanced_mode' => true
-				),
-				'customredirect_enabled' => array(
-					'label' => $lng['serversettings']['customredirect_enabled'],
+				],
+				'customredirect_enabled' => [
+					'label' => lng('serversettings.customredirect_enabled'),
 					'settinggroup' => 'customredirect',
 					'varname' => 'enabled',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'customredirect_default' => array(
-					'label' => $lng['serversettings']['customredirect_default'],
+				],
+				'customredirect_default' => [
+					'label' => lng('serversettings.customredirect_default'),
 					'settinggroup' => 'customredirect',
 					'varname' => 'default',
 					'type' => 'select',
 					'default' => '1',
-					'option_options_method' => array('\\Froxlor\\Domain\\Domain', 'getRedirectCodes'),
+					'option_options_method' => ['\\Froxlor\\Domain\\Domain', 'getRedirectCodes'],
 					'save_method' => 'storeSettingField'
-				)
-			)
-		)
-	)
-);
+				]
+			]
+		]
+	]
+];
diff --git a/actions/admin/settings/131.ssl.php b/actions/admin/settings/131.ssl.php
index f23defe4..4b1174e5 100644
--- a/actions/admin/settings/131.ssl.php
+++ b/actions/admin/settings/131.ssl.php
@@ -2,52 +2,62 @@
 
 /**
  * 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  (2003-2009)
- * @author     Froxlor team  (2010-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    \Froxlor\Settings
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
-return array(
-	'groups' => array(
-		'ssl' => array(
-			'title' => $lng['admin']['sslsettings'],
+
+use Froxlor\Froxlor;
+use Froxlor\Settings;
+
+return [
+	'groups' => [
+		'ssl' => [
+			'title' => lng('admin.sslsettings'),
 			'icon' => 'fa-solid fa-shield',
-			'fields' => array(
-				'system_ssl_enabled' => array(
-					'label' => $lng['serversettings']['ssl']['use_ssl'],
+			'fields' => [
+				'system_ssl_enabled' => [
+					'label' => lng('serversettings.ssl.use_ssl'),
 					'settinggroup' => 'system',
 					'varname' => 'use_ssl',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
 					'overview_option' => true
-				),
-				'system_ssl_protocols' => array(
-					'label' => $lng['serversettings']['ssl']['ssl_protocols'],
+				],
+				'system_ssl_protocols' => [
+					'label' => lng('serversettings.ssl.ssl_protocols'),
 					'settinggroup' => 'system',
 					'varname' => 'ssl_protocols',
 					'type' => 'select',
 					'default' => 'TLSv1.2',
 					'select_mode' => 'multiple',
-					'select_var' => array(
+					'select_var' => [
 						'TLSv1' => 'TLSv1',
 						'TLSv1.1' => 'TLSv1.1',
 						'TLSv1.2' => 'TLSv1.2',
 						'TLSv1.3' => 'TLSv1.3'
-					),
+					],
 					'save_method' => 'storeSettingField'
-				),
-				'system_ssl_cipher_list' => array(
-					'label' => $lng['serversettings']['ssl']['ssl_cipher_list'],
+				],
+				'system_ssl_cipher_list' => [
+					'label' => lng('serversettings.ssl.ssl_cipher_list'),
 					'settinggroup' => 'system',
 					'varname' => 'ssl_cipher_list',
 					'type' => 'text',
@@ -55,20 +65,20 @@ return array(
 					'default' => 'ECDH+AESGCM:ECDH+AES256:!aNULL:!MD5:!DSS:!DH:!AES128',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_tlsv13_cipher_list' => array(
-					'label' => $lng['serversettings']['ssl']['tlsv13_cipher_list'],
+				],
+				'system_tlsv13_cipher_list' => [
+					'label' => lng('serversettings.ssl.tlsv13_cipher_list'),
 					'settinggroup' => 'system',
 					'varname' => 'tlsv13_cipher_list',
 					'type' => 'text',
 					'string_emptyallowed' => true,
 					'default' => '',
-					'visible' => \Froxlor\Settings::Get('system.webserver') == "apache2" && \Froxlor\Settings::Get('system.apache24') == 1,
+					'visible' => Settings::Get('system.webserver') == "apache2" && Settings::Get('system.apache24') == 1,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_ssl_cert_file' => array(
-					'label' => $lng['serversettings']['ssl']['ssl_cert_file'],
+				],
+				'system_ssl_cert_file' => [
+					'label' => lng('serversettings.ssl.ssl_cert_file'),
 					'settinggroup' => 'system',
 					'varname' => 'ssl_cert_file',
 					'type' => 'text',
@@ -76,9 +86,9 @@ return array(
 					'string_emptyallowed' => true,
 					'default' => '/etc/apache2/apache2.pem',
 					'save_method' => 'storeSettingField'
-				),
-				'system_ssl_key_file' => array(
-					'label' => $lng['serversettings']['ssl']['ssl_key_file'],
+				],
+				'system_ssl_key_file' => [
+					'label' => lng('serversettings.ssl.ssl_key_file'),
 					'settinggroup' => 'system',
 					'varname' => 'ssl_key_file',
 					'type' => 'text',
@@ -86,9 +96,9 @@ return array(
 					'string_emptyallowed' => true,
 					'default' => '/etc/apache2/apache2.key',
 					'save_method' => 'storeSettingField'
-				),
-				'system_ssl_cert_chainfile' => array(
-					'label' => $lng['admin']['ipsandports']['ssl_cert_chainfile'],
+				],
+				'system_ssl_cert_chainfile' => [
+					'label' => lng('admin.ipsandports.ssl_cert_chainfile'),
 					'settinggroup' => 'system',
 					'varname' => 'ssl_cert_chainfile',
 					'type' => 'text',
@@ -96,9 +106,9 @@ return array(
 					'string_emptyallowed' => true,
 					'default' => '',
 					'save_method' => 'storeSettingField'
-				),
-				'system_ssl_ca_file' => array(
-					'label' => $lng['serversettings']['ssl']['ssl_ca_file'],
+				],
+				'system_ssl_ca_file' => [
+					'label' => lng('serversettings.ssl.ssl_ca_file'),
 					'settinggroup' => 'system',
 					'varname' => 'ssl_ca_file',
 					'type' => 'text',
@@ -106,39 +116,39 @@ return array(
 					'string_emptyallowed' => true,
 					'default' => '',
 					'save_method' => 'storeSettingField'
-				),
-				'system_apache24_ocsp_cache_path' => array(
-					'label' => $lng['serversettings']['ssl']['apache24_ocsp_cache_path'],
+				],
+				'system_apache24_ocsp_cache_path' => [
+					'label' => lng('serversettings.ssl.apache24_ocsp_cache_path'),
 					'settinggroup' => 'system',
 					'varname' => 'apache24_ocsp_cache_path',
 					'type' => 'text',
 					'string_emptyallowed' => false,
 					'default' => 'shmcb:/var/run/apache2/ocsp-stapling.cache(131072)',
-					'visible' => \Froxlor\Settings::Get('system.webserver') == "apache2" && \Froxlor\Settings::Get('system.apache24') == 1,
+					'visible' => Settings::Get('system.webserver') == "apache2" && Settings::Get('system.apache24') == 1,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_sessionticketsenabled' => array(
-					'label' => $lng['admin']['domain_sessionticketsenabled'],
+				],
+				'system_sessionticketsenabled' => [
+					'label' => lng('admin.domain_sessionticketsenabled'),
 					'settinggroup' => 'system',
 					'varname' => 'sessionticketsenabled',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField',
-					'visible' => \Froxlor\Settings::Get('system.use_ssl') && (\Froxlor\Settings::Get('system.webserver') == "nginx" || (\Froxlor\Settings::Get('system.webserver') == "apache2" && \Froxlor\Settings::Get('system.apache24') == 1)),
+					'visible' => Settings::Get('system.use_ssl') && (Settings::Get('system.webserver') == "nginx" || (Settings::Get('system.webserver') == "apache2" && Settings::Get('system.apache24') == 1)),
 					'advanced_mode' => true
-				),
-				'system_leenabled' => array(
-					'label' => $lng['serversettings']['leenabled'],
+				],
+				'system_leenabled' => [
+					'label' => lng('serversettings.leenabled'),
 					'settinggroup' => 'system',
 					'varname' => 'leenabled',
 					'type' => 'checkbox',
 					'default' => false,
 					'cronmodule' => 'froxlor/letsencrypt',
 					'save_method' => 'storeSettingField'
-				),
-				'system_acmeshpath' => array(
-					'label' => $lng['serversettings']['acmeshpath'],
+				],
+				'system_acmeshpath' => [
+					'label' => lng('serversettings.acmeshpath'),
 					'settinggroup' => 'system',
 					'varname' => 'acmeshpath',
 					'type' => 'text',
@@ -146,102 +156,102 @@ return array(
 					'default' => '/root/.acme.sh/acme.sh',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_letsencryptacmeconf' => array(
-					'label' => $lng['serversettings']['letsencryptacmeconf'],
+				],
+				'system_letsencryptacmeconf' => [
+					'label' => lng('serversettings.letsencryptacmeconf'),
 					'settinggroup' => 'system',
 					'varname' => 'letsencryptacmeconf',
 					'type' => 'text',
 					'string_type' => 'file',
 					'default' => '/etc/apache2/conf-enabled/acme.conf',
 					'save_method' => 'storeSettingField'
-				),
+				],
 				/**
 				 * currently the only option anyway
 				 *
-				'system_leapiversion' => array(
-					'label' => $lng['serversettings']['leapiversion'],
-					'settinggroup' => 'system',
-					'varname' => 'leapiversion',
-					'type' => 'select',
-					'default' => '2',
-					'select_var' => array(
-						'2' => 'ACME v2'
-					),
-					'save_method' => 'storeSettingField'
-				),
+				 * 'system_leapiversion' => array(
+				 * 'label' => lng('serversettings.leapiversion'),
+				 * 'settinggroup' => 'system',
+				 * 'varname' => 'leapiversion',
+				 * 'type' => 'select',
+				 * 'default' => '2',
+				 * 'select_var' => array(
+				 * '2' => 'ACME v2'
+				 * ),
+				 * 'save_method' => 'storeSettingField'
+				 * ),
 				 */
-				'system_letsencryptca' => array(
-					'label' => $lng['serversettings']['letsencryptca'],
+				'system_letsencryptca' => [
+					'label' => lng('serversettings.letsencryptca'),
 					'settinggroup' => 'system',
 					'varname' => 'letsencryptca',
 					'type' => 'select',
 					'default' => 'letsencrypt',
-					'select_var' => array(
+					'select_var' => [
 						'letsencrypt_test' => 'Let\'s Encrypt (Test / Staging)',
 						'letsencrypt' => 'Let\'s Encrypt (Live)',
 						'buypass_test' => 'Buypass (Test / Staging)',
 						'buypass' => 'Buypass (Live)',
 						'zerossl' => 'ZeroSSL (Live)'
-					),
+					],
 					'save_method' => 'storeSettingField'
-				),
-				'system_letsencryptchallengepath' => array(
-					'label' => $lng['serversettings']['letsencryptchallengepath'],
+				],
+				'system_letsencryptchallengepath' => [
+					'label' => lng('serversettings.letsencryptchallengepath'),
 					'settinggroup' => 'system',
 					'varname' => 'letsencryptchallengepath',
 					'type' => 'text',
 					'string_emptyallowed' => false,
-					'default' => \Froxlor\Froxlor::getInstallDir(),
+					'default' => Froxlor::getInstallDir(),
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_letsencryptkeysize' => array(
-					'label' => $lng['serversettings']['letsencryptkeysize'],
+				],
+				'system_letsencryptkeysize' => [
+					'label' => lng('serversettings.letsencryptkeysize'),
 					'settinggroup' => 'system',
 					'varname' => 'letsencryptkeysize',
 					'type' => 'select',
 					'default' => '2048',
-					'select_var' => array(
+					'select_var' => [
 						'2048' => '2048',
 						'3072' => '3072',
 						'4096' => '4096',
 						'8192' => '8192'
-					),
+					],
 					'save_method' => 'storeSettingField'
-				),
-				'system_leecc' => array(
-					'label' => $lng['serversettings']['letsencryptecc'],
+				],
+				'system_leecc' => [
+					'label' => lng('serversettings.letsencryptecc'),
 					'settinggroup' => 'system',
 					'varname' => 'leecc',
 					'type' => 'select',
 					'default' => '0',
-					'select_var' => array(
+					'select_var' => [
 						'0' => '-',
 						'256' => 'ec-256',
 						'384' => 'ec-384'
-					),
+					],
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_letsencryptreuseold' => array(
-					'label' => $lng['serversettings']['letsencryptreuseold'],
+				],
+				'system_letsencryptreuseold' => [
+					'label' => lng('serversettings.letsencryptreuseold'),
 					'settinggroup' => 'system',
 					'varname' => 'letsencryptreuseold',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_le_domain_dnscheck' => array(
-					'label' => $lng['serversettings']['le_domain_dnscheck'],
+				],
+				'system_le_domain_dnscheck' => [
+					'label' => lng('serversettings.le_domain_dnscheck'),
 					'settinggroup' => 'system',
 					'varname' => 'le_domain_dnscheck',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField'
-				)
-			)
-		)
-	)
-);
+				]
+			]
+		]
+	]
+];
diff --git a/actions/admin/settings/135.fcgid.php b/actions/admin/settings/135.fcgid.php
index fc4a9dd3..c8dd03c8 100644
--- a/actions/admin/settings/135.fcgid.php
+++ b/actions/admin/settings/135.fcgid.php
@@ -4,63 +4,72 @@
  * 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  (2010-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    Settings
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
-return array(
-	'groups' => array(
-		'fcgid' => array(
-			'title' => $lng['admin']['fcgid_settings'],
+
+return [
+	'groups' => [
+		'fcgid' => [
+			'title' => lng('admin.fcgid_settings'),
 			'icon' => 'fa-brands fa-php',
-			'websrv_avail' => array(
+			'websrv_avail' => [
 				'apache2',
 				'lighttpd'
-			),
-			'fields' => array(
-				'system_mod_fcgid_enabled' => array(
-					'label' => $lng['serversettings']['mod_fcgid'],
+			],
+			'fields' => [
+				'system_mod_fcgid_enabled' => [
+					'label' => lng('serversettings.mod_fcgid'),
 					'settinggroup' => 'system',
 					'varname' => 'mod_fcgid',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
-					'plausibility_check_method' => array(
+					'plausibility_check_method' => [
 						'\\Froxlor\\Validate\\Check',
 						'checkFcgidPhpFpm'
-					),
+					],
 					'overview_option' => true
-				),
-				'system_mod_fcgid_configdir' => array(
-					'label' => $lng['serversettings']['mod_fcgid']['configdir'],
+				],
+				'system_mod_fcgid_configdir' => [
+					'label' => lng('serversettings.mod_fcgid.configdir'),
 					'settinggroup' => 'system',
 					'varname' => 'mod_fcgid_configdir',
 					'type' => 'text',
 					'string_type' => 'confdir',
 					'default' => '/var/www/php-fcgi-scripts/',
-					'plausibility_check_method' => array(
+					'plausibility_check_method' => [
 						'\\Froxlor\\Validate\\Check',
 						'checkPathConflicts'
-					),
+					],
 					'save_method' => 'storeSettingField'
-				),
-				'system_mod_fcgid_tmpdir' => array(
-					'label' => $lng['serversettings']['mod_fcgid']['tmpdir'],
+				],
+				'system_mod_fcgid_tmpdir' => [
+					'label' => lng('serversettings.mod_fcgid.tmpdir'),
 					'settinggroup' => 'system',
 					'varname' => 'mod_fcgid_tmpdir',
 					'type' => 'text',
 					'string_type' => 'dir',
 					'default' => '/var/customers/tmp/',
 					'save_method' => 'storeSettingField'
-				),
-				'system_mod_fcgid_peardir' => array(
-					'label' => $lng['serversettings']['mod_fcgid']['peardir'],
+				],
+				'system_mod_fcgid_peardir' => [
+					'label' => lng('serversettings.mod_fcgid.peardir'),
 					'settinggroup' => 'system',
 					'varname' => 'mod_fcgid_peardir',
 					'type' => 'text',
@@ -70,25 +79,25 @@ return array(
 					'default' => '/usr/share/php/:/usr/share/php5/',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_mod_fcgid_wrapper' => array(
-					'label' => $lng['serversettings']['mod_fcgid']['wrapper'],
+				],
+				'system_mod_fcgid_wrapper' => [
+					'label' => lng('serversettings.mod_fcgid.wrapper'),
 					'settinggroup' => 'system',
 					'varname' => 'mod_fcgid_wrapper',
 					'type' => 'select',
-					'select_var' => array(
+					'select_var' => [
 						0 => 'ScriptAlias',
 						1 => 'FcgidWrapper'
-					),
+					],
 					'default' => 1,
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'apache2'
-					),
+					],
 					'advanced_mode' => true
-				),
-				'system_mod_fcgid_starter' => array(
-					'label' => $lng['serversettings']['mod_fcgid']['starter'],
+				],
+				'system_mod_fcgid_starter' => [
+					'label' => lng('serversettings.mod_fcgid.starter'),
 					'settinggroup' => 'system',
 					'varname' => 'mod_fcgid_starter',
 					'type' => 'number',
@@ -96,37 +105,38 @@ return array(
 					'default' => 0,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_mod_fcgid_maxrequests' => array(
-					'label' => $lng['serversettings']['mod_fcgid']['maxrequests'],
+				],
+				'system_mod_fcgid_maxrequests' => [
+					'label' => lng('serversettings.mod_fcgid.maxrequests'),
 					'settinggroup' => 'system',
 					'varname' => 'mod_fcgid_maxrequests',
 					'type' => 'number',
 					'default' => 250,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_mod_fcgid_defaultini' => array(
-					'label' => $lng['serversettings']['mod_fcgid']['defaultini'],
+				],
+				'system_mod_fcgid_defaultini' => [
+					'label' => lng('serversettings.mod_fcgid.defaultini'),
 					'settinggroup' => 'system',
 					'varname' => 'mod_fcgid_defaultini',
 					'type' => 'select',
 					'default' => '1',
-					'option_options_method' => array(
+					'option_options_method' => [
 						'\\Froxlor\\Http\\PhpConfig',
-						'getPhpConfigs'),
+						'getPhpConfigs'
+					],
 					'save_method' => 'storeSettingField'
-				),
-				'system_mod_fcgid_idle_timeout' => array(
-					'label' => $lng['serversettings']['mod_fcgid']['idle_timeout'],
+				],
+				'system_mod_fcgid_idle_timeout' => [
+					'label' => lng('serversettings.mod_fcgid.idle_timeout'),
 					'settinggroup' => 'system',
 					'varname' => 'mod_fcgid_idle_timeout',
 					'type' => 'number',
 					'default' => 30,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				)
-			)
-		)
-	)
-);
+				]
+			]
+		]
+	]
+];
diff --git a/actions/admin/settings/136.phpfpm.php b/actions/admin/settings/136.phpfpm.php
index a575ca53..68d6b3e0 100644
--- a/actions/admin/settings/136.phpfpm.php
+++ b/actions/admin/settings/136.phpfpm.php
@@ -4,49 +4,60 @@
  * 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  (2010-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    \Froxlor\Settings
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
-return array(
-	'groups' => array(
-		'phpfpm' => array(
-			'title' => $lng['admin']['phpfpm_settings'],
+
+use Froxlor\Settings;
+
+return [
+	'groups' => [
+		'phpfpm' => [
+			'title' => lng('admin.phpfpm_settings'),
 			'icon' => 'fa-brands fa-php',
-			'fields' => array(
-				'system_phpfpm_enabled' => array(
-					'label' => $lng['serversettings']['phpfpm'],
+			'fields' => [
+				'system_phpfpm_enabled' => [
+					'label' => lng('serversettings.phpfpm'),
 					'settinggroup' => 'phpfpm',
 					'varname' => 'enabled',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
-					'plausibility_check_method' => array(
+					'plausibility_check_method' => [
 						'\\Froxlor\\Validate\\Check',
 						'checkFcgidPhpFpm'
-					),
+					],
 					'overview_option' => true
-				),
-				'system_phpfpm_defaultini' => array(
-					'label' => $lng['serversettings']['mod_fcgid']['defaultini'],
+				],
+				'system_phpfpm_defaultini' => [
+					'label' => lng('serversettings.mod_fcgid.defaultini'),
 					'settinggroup' => 'phpfpm',
 					'varname' => 'defaultini',
 					'type' => 'select',
 					'default' => '1',
-					'option_options_method' => array(
+					'option_options_method' => [
 						'\\Froxlor\\Http\\PhpConfig',
 						'getPhpConfigs'
-					),
+					],
 					'save_method' => 'storeSettingField'
-				),
-				'system_phpfpm_aliasconfigdir' => array(
-					'label' => $lng['serversettings']['phpfpm_settings']['aliasconfigdir'],
+				],
+				'system_phpfpm_aliasconfigdir' => [
+					'label' => lng('serversettings.phpfpm_settings.aliasconfigdir'),
 					'settinggroup' => 'phpfpm',
 					'varname' => 'aliasconfigdir',
 					'type' => 'text',
@@ -54,18 +65,18 @@ return array(
 					'default' => '/var/www/php-fpm/',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_phpfpm_tmpdir' => array(
-					'label' => $lng['serversettings']['mod_fcgid']['tmpdir'],
+				],
+				'system_phpfpm_tmpdir' => [
+					'label' => lng('serversettings.mod_fcgid.tmpdir'),
 					'settinggroup' => 'phpfpm',
 					'varname' => 'tmpdir',
 					'type' => 'text',
 					'string_type' => 'dir',
 					'default' => '/var/customers/tmp/',
 					'save_method' => 'storeSettingField'
-				),
-				'system_phpfpm_peardir' => array(
-					'label' => $lng['serversettings']['mod_fcgid']['peardir'],
+				],
+				'system_phpfpm_peardir' => [
+					'label' => lng('serversettings.mod_fcgid.peardir'),
 					'settinggroup' => 'phpfpm',
 					'varname' => 'peardir',
 					'type' => 'text',
@@ -75,9 +86,9 @@ return array(
 					'default' => '/usr/share/php/:/usr/share/php5/',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_phpfpm_envpath' => array(
-					'label' => $lng['serversettings']['phpfpm_settings']['envpath'],
+				],
+				'system_phpfpm_envpath' => [
+					'label' => lng('serversettings.phpfpm_settings.envpath'),
 					'settinggroup' => 'phpfpm',
 					'varname' => 'envpath',
 					'type' => 'text',
@@ -87,9 +98,9 @@ return array(
 					'default' => '/usr/local/bin:/usr/bin:/bin',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_phpfpm_fastcgi_ipcdir' => array(
-					'label' => $lng['serversettings']['phpfpm_settings']['ipcdir'],
+				],
+				'system_phpfpm_fastcgi_ipcdir' => [
+					'label' => lng('serversettings.phpfpm_settings.ipcdir'),
 					'settinggroup' => 'phpfpm',
 					'varname' => 'fastcgi_ipcdir',
 					'type' => 'text',
@@ -97,53 +108,53 @@ return array(
 					'default' => '/var/lib/apache2/fastcgi/',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_phpfpm_use_mod_proxy' => array(
-					'label' => $lng['phpfpm']['use_mod_proxy'],
+				],
+				'system_phpfpm_use_mod_proxy' => [
+					'label' => lng('phpfpm.use_mod_proxy'),
 					'settinggroup' => 'phpfpm',
 					'varname' => 'use_mod_proxy',
 					'type' => 'checkbox',
 					'default' => true,
-					'visible' => \Froxlor\Settings::Get('system.apache24'),
+					'visible' => Settings::Get('system.apache24'),
 					'save_method' => 'storeSettingField'
-				),
-				'system_phpfpm_ini_flags' => array(
-					'label' => $lng['phpfpm']['ini_flags'],
+				],
+				'system_phpfpm_ini_flags' => [
+					'label' => lng('phpfpm.ini_flags'),
 					'settinggroup' => 'phpfpm',
 					'varname' => 'ini_flags',
 					'type' => 'textarea',
 					'default' => '',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_phpfpm_ini_values' => array(
-					'label' => $lng['phpfpm']['ini_values'],
+				],
+				'system_phpfpm_ini_values' => [
+					'label' => lng('phpfpm.ini_values'),
 					'settinggroup' => 'phpfpm',
 					'varname' => 'ini_values',
 					'type' => 'textarea',
 					'default' => '',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_phpfpm_ini_admin_flags' => array(
-					'label' => $lng['phpfpm']['ini_admin_flags'],
+				],
+				'system_phpfpm_ini_admin_flags' => [
+					'label' => lng('phpfpm.ini_admin_flags'),
 					'settinggroup' => 'phpfpm',
 					'varname' => 'ini_admin_flags',
 					'type' => 'textarea',
 					'default' => '',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_phpfpm_ini_admin_values' => array(
-					'label' => $lng['phpfpm']['ini_admin_values'],
+				],
+				'system_phpfpm_ini_admin_values' => [
+					'label' => lng('phpfpm.ini_admin_values'),
 					'settinggroup' => 'phpfpm',
 					'varname' => 'ini_admin_values',
 					'type' => 'textarea',
 					'default' => '',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				)
-			)
-		)
-	)
-);
+				]
+			]
+		]
+	]
+];
diff --git a/actions/admin/settings/137.perl.php b/actions/admin/settings/137.perl.php
index d8581dfe..644fdb67 100644
--- a/actions/admin/settings/137.perl.php
+++ b/actions/admin/settings/137.perl.php
@@ -4,68 +4,77 @@
  * 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  (2010-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    Settings
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
-return array(
-	'groups' => array(
-		'perl' => array(
-			'title' => $lng['admin']['perl_settings'],
+
+return [
+	'groups' => [
+		'perl' => [
+			'title' => lng('admin.perl_settings'),
 			'icon' => 'fa-solid fa-code',
-			'fields' => array(
-				'perl_path' => array(
-					'label' => $lng['serversettings']['perl_path'],
+			'fields' => [
+				'perl_path' => [
+					'label' => lng('serversettings.perl_path'),
 					'settinggroup' => 'system',
 					'varname' => 'perl_path',
 					'type' => 'text',
 					'default' => '/usr/bin/perl',
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'lighttpd'
-					)
-				),
-				'system_perl_suexecworkaround' => array(
-					'label' => $lng['serversettings']['perl']['suexecworkaround'],
+					]
+				],
+				'system_perl_suexecworkaround' => [
+					'label' => lng('serversettings.perl.suexecworkaround'),
 					'settinggroup' => 'perl',
 					'varname' => 'suexecworkaround',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'apache2'
-					)
-				),
-				'system_perl_suexeccgipath' => array(
-					'label' => $lng['serversettings']['perl']['suexeccgipath'],
+					]
+				],
+				'system_perl_suexeccgipath' => [
+					'label' => lng('serversettings.perl.suexeccgipath'),
 					'settinggroup' => 'perl',
 					'varname' => 'suexecpath',
 					'type' => 'text',
 					'string_type' => 'dir',
 					'default' => '/var/www/cgi-bin/',
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'apache2'
-					)
-				),
-				'perl_server' => array(
-					'label' => $lng['serversettings']['perl_server'],
+					]
+				],
+				'perl_server' => [
+					'label' => lng('serversettings.perl_server'),
 					'settinggroup' => 'serversettings',
 					'varname' => 'perl_server',
 					'type' => 'text',
 					'default' => 'unix:/var/run/nginx/cgiwrap-dispatch.sock',
 					'save_method' => 'storeSettingField',
-					'websrv_avail' => array(
+					'websrv_avail' => [
 						'nginx'
-					)
-				)
-			)
-		)
-	)
-);
+					]
+				]
+			]
+		]
+	]
+];
diff --git a/actions/admin/settings/140.statistics.php b/actions/admin/settings/140.statistics.php
index dc305362..d9bd5c58 100644
--- a/actions/admin/settings/140.statistics.php
+++ b/actions/admin/settings/140.statistics.php
@@ -2,99 +2,108 @@
 
 /**
  * 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  (2003-2009)
- * @author     Froxlor team  (2010-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    Settings
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
-return array(
-	'groups' => array(
-		'statistics' => array(
-			'title' => $lng['admin']['statisticsettings'],
+
+use Froxlor\Settings;
+
+return [
+	'groups' => [
+		'statistics' => [
+			'title' => lng('admin.statisticsettings'),
 			'icon' => 'fa-solid fa-chart-area',
-			'fields' => array(
-				'system_webalizer_quiet' => array(
-					'label' => $lng['serversettings']['webalizer_quiet'],
+			'fields' => [
+				'system_webalizer_quiet' => [
+					'label' => lng('serversettings.webalizer_quiet'),
 					'settinggroup' => 'system',
 					'varname' => 'webalizer_quiet',
 					'type' => 'select',
 					'default' => 2,
-					'select_var' => array(
-						0 => $lng['admin']['webalizer']['normal'],
-						1 => $lng['admin']['webalizer']['quiet'],
-						2 => $lng['admin']['webalizer']['veryquiet']
-					),
+					'select_var' => [
+						0 => lng('admin.webalizer.normal'),
+						1 => lng('admin.webalizer.quiet'),
+						2 => lng('admin.webalizer.veryquiet')
+					],
 					'save_method' => 'storeSettingField',
-					'visible' => \Froxlor\Settings::Get('system.awstats_enabled') == 0
-				),
-				'system_awstats_enabled' => array(
-					'label' => $lng['serversettings']['awstats_enabled'],
+					'visible' => Settings::Get('system.awstats_enabled') == 0
+				],
+				'system_awstats_enabled' => [
+					'label' => lng('serversettings.awstats_enabled'),
 					'settinggroup' => 'system',
 					'varname' => 'awstats_enabled',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'system_awstats_path' => array(
-					'label' => $lng['serversettings']['awstats_path'],
+				],
+				'system_awstats_path' => [
+					'label' => lng('serversettings.awstats_path'),
 					'settinggroup' => 'system',
 					'varname' => 'awstats_path',
 					'type' => 'text',
 					'string_type' => 'dir',
 					'default' => '/usr/bin/',
 					'save_method' => 'storeSettingField',
-					'visible' => \Froxlor\Settings::Get('system.awstats_enabled') == 1
-				),
-				'system_awstats_awstatspath' => array(
-					'label' => $lng['serversettings']['awstats_awstatspath'],
+					'visible' => Settings::Get('system.awstats_enabled') == 1
+				],
+				'system_awstats_awstatspath' => [
+					'label' => lng('serversettings.awstats_awstatspath'),
 					'settinggroup' => 'system',
 					'varname' => 'awstats_awstatspath',
 					'type' => 'text',
 					'string_type' => 'dir',
 					'default' => '/usr/bin/',
 					'save_method' => 'storeSettingField',
-					'visible' => \Froxlor\Settings::Get('system.awstats_enabled') == 1
-				),
-				'system_awstats_conf' => array(
-					'label' => $lng['serversettings']['awstats_conf'],
+					'visible' => Settings::Get('system.awstats_enabled') == 1
+				],
+				'system_awstats_conf' => [
+					'label' => lng('serversettings.awstats_conf'),
 					'settinggroup' => 'system',
 					'varname' => 'awstats_conf',
 					'type' => 'text',
 					'string_type' => 'dir',
 					'default' => '/etc/awstats/',
 					'save_method' => 'storeSettingField',
-					'visible' => \Froxlor\Settings::Get('system.awstats_enabled') == 1
-				),
-				'system_awstats_icons' => array(
-					'label' => $lng['serversettings']['awstats_icons'],
+					'visible' => Settings::Get('system.awstats_enabled') == 1
+				],
+				'system_awstats_icons' => [
+					'label' => lng('serversettings.awstats_icons'),
 					'settinggroup' => 'system',
 					'varname' => 'awstats_icons',
 					'type' => 'text',
 					'string_type' => 'dir',
 					'default' => '/usr/share/awstats/icon/',
 					'save_method' => 'storeSettingField',
-					'visible' => \Froxlor\Settings::Get('system.awstats_enabled') == 1
-				),
-				'system_awstats_logformat' => array(
-					'label' => $lng['serversettings']['awstats']['logformat'],
+					'visible' => Settings::Get('system.awstats_enabled') == 1
+				],
+				'system_awstats_logformat' => [
+					'label' => lng('serversettings.awstats.logformat'),
 					'settinggroup' => 'system',
 					'varname' => 'awstats_logformat',
 					'type' => 'text',
 					'default' => '1',
 					'save_method' => 'storeSettingField',
-					'visible' => \Froxlor\Settings::Get('system.awstats_enabled') == 1,
+					'visible' => Settings::Get('system.awstats_enabled') == 1,
 					'advanced_mode' => true
-				)
-			)
-		)
-	)
-);
+				]
+			]
+		]
+	]
+];
diff --git a/actions/admin/settings/150.mail.php b/actions/admin/settings/150.mail.php
index 2f13b111..be05588f 100644
--- a/actions/admin/settings/150.mail.php
+++ b/actions/admin/settings/150.mail.php
@@ -2,28 +2,35 @@
 
 /**
  * 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  (2003-2009)
- * @author     Froxlor team  (2010-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    Settings
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
-return array(
-	'groups' => array(
-		'mail' => array(
-			'title' => $lng['admin']['mailserversettings'],
+
+return [
+	'groups' => [
+		'mail' => [
+			'title' => lng('admin.mailserversettings'),
 			'icon' => 'fa-solid fa-envelope',
-			'fields' => array(
-				'system_vmail_uid' => array(
-					'label' => $lng['serversettings']['vmail_uid'],
+			'fields' => [
+				'system_vmail_uid' => [
+					'label' => lng('serversettings.vmail_uid'),
 					'settinggroup' => 'system',
 					'varname' => 'vmail_uid',
 					'type' => 'number',
@@ -32,9 +39,9 @@ return array(
 					'max' => 65535,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_vmail_gid' => array(
-					'label' => $lng['serversettings']['vmail_gid'],
+				],
+				'system_vmail_gid' => [
+					'label' => lng('serversettings.vmail_gid'),
 					'settinggroup' => 'system',
 					'varname' => 'vmail_gid',
 					'type' => 'number',
@@ -43,18 +50,18 @@ return array(
 					'max' => 65535,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_vmail_homedir' => array(
-					'label' => $lng['serversettings']['vmail_homedir'],
+				],
+				'system_vmail_homedir' => [
+					'label' => lng('serversettings.vmail_homedir'),
 					'settinggroup' => 'system',
 					'varname' => 'vmail_homedir',
 					'type' => 'text',
 					'string_type' => 'dir',
 					'default' => '/var/customers/mail/',
 					'save_method' => 'storeSettingField'
-				),
-				'system_vmail_maildirname' => array(
-					'label' => $lng['serversettings']['vmail_maildirname'],
+				],
+				'system_vmail_maildirname' => [
+					'label' => lng('serversettings.vmail_maildirname'),
 					'settinggroup' => 'system',
 					'varname' => 'vmail_maildirname',
 					'type' => 'text',
@@ -63,63 +70,63 @@ return array(
 					'string_emptyallowed' => true,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'panel_sendalternativemail' => array(
-					'label' => $lng['serversettings']['sendalternativemail'],
+				],
+				'panel_sendalternativemail' => [
+					'label' => lng('serversettings.sendalternativemail'),
 					'settinggroup' => 'panel',
 					'varname' => 'sendalternativemail',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'system_mail_quota_enabled' => array(
-					'label' => $lng['serversettings']['mail_quota_enabled'],
+				],
+				'system_mail_quota_enabled' => [
+					'label' => lng('serversettings.mail_quota_enabled'),
 					'settinggroup' => 'system',
 					'varname' => 'mail_quota_enabled',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'system_mail_quota' => array(
-					'label' => $lng['serversettings']['mail_quota'],
+				],
+				'system_mail_quota' => [
+					'label' => lng('serversettings.mail_quota'),
 					'settinggroup' => 'system',
 					'varname' => 'mail_quota',
 					'type' => 'number',
 					'default' => 100,
 					'save_method' => 'storeSettingField'
-				),
-				'system_catchall_enabled' => array(
-					'label' => $lng['serversettings']['catchall_enabled'],
+				],
+				'system_catchall_enabled' => [
+					'label' => lng('serversettings.catchall_enabled'),
 					'settinggroup' => 'catchall',
 					'varname' => 'catchall_enabled',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingResetCatchall'
-				),
-				'system_mailtraffic_enabled' => array(
-					'label' => $lng['serversettings']['mailtraffic_enabled'],
+				],
+				'system_mailtraffic_enabled' => [
+					'label' => lng('serversettings.mailtraffic_enabled'),
 					'settinggroup' => 'system',
 					'varname' => 'mailtraffic_enabled',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_mdaserver' => array(
-					'label' => $lng['serversettings']['mdaserver'],
+				],
+				'system_mdaserver' => [
+					'label' => lng('serversettings.mdaserver'),
 					'settinggroup' => 'system',
 					'varname' => 'mdaserver',
 					'type' => 'select',
 					'default' => 'dovecot',
-					'select_var' => array(
+					'select_var' => [
 						'courier' => 'Courier',
 						'dovecot' => 'Dovecot'
-					),
+					],
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_mdalog' => array(
-					'label' => $lng['serversettings']['mdalog'],
+				],
+				'system_mdalog' => [
+					'label' => lng('serversettings.mdalog'),
 					'settinggroup' => 'system',
 					'varname' => 'mdalog',
 					'type' => 'text',
@@ -128,22 +135,22 @@ return array(
 					'string_emptyallowed' => true,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_mtaserver' => array(
-					'label' => $lng['serversettings']['mtaserver'],
+				],
+				'system_mtaserver' => [
+					'label' => lng('serversettings.mtaserver'),
 					'settinggroup' => 'system',
 					'varname' => 'mtaserver',
 					'type' => 'select',
 					'default' => 'postfix',
-					'select_var' => array(
+					'select_var' => [
 						'exim4' => 'Exim4',
 						'postfix' => 'Postfix'
-					),
+					],
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_mtalog' => array(
-					'label' => $lng['serversettings']['mtalog'],
+				],
+				'system_mtalog' => [
+					'label' => lng('serversettings.mtalog'),
 					'settinggroup' => 'system',
 					'varname' => 'mtalog',
 					'type' => 'text',
@@ -152,8 +159,8 @@ return array(
 					'string_emptyallowed' => true,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				)
-			)
-		)
-	)
-);
+				]
+			]
+		]
+	]
+];
diff --git a/actions/admin/settings/155.ftpserver.php b/actions/admin/settings/155.ftpserver.php
index e3d8d492..13975e73 100644
--- a/actions/admin/settings/155.ftpserver.php
+++ b/actions/admin/settings/155.ftpserver.php
@@ -2,39 +2,46 @@
 
 /**
  * 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  (2003-2009)
- * @author     Froxlor team  (2010-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    Settings
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
-return array(
-	'groups' => array(
-		'ftpserver' => array(
-			'title' => $lng['admin']['ftpserversettings'],
+
+return [
+	'groups' => [
+		'ftpserver' => [
+			'title' => lng('admin.ftpserversettings'),
 			'icon' => 'fa-solid fa-arrow-right-arrow-left',
-			'fields' => array(
-				'ftpserver' => array(
-					'label' => $lng['admin']['ftpserver'],
+			'fields' => [
+				'ftpserver' => [
+					'label' => lng('admin.ftpserver'),
 					'settinggroup' => 'system',
 					'varname' => 'ftpserver',
 					'type' => 'select',
 					'default' => 'proftpd',
-					'select_var' => array(
+					'select_var' => [
 						'proftpd' => 'Proftpd',
 						'pureftpd' => 'Pureftpd'
-					),
+					],
 					'save_method' => 'storeSettingField'
-				)
-			)
-		)
-	)
-);
+				]
+			]
+		]
+	]
+];
diff --git a/actions/admin/settings/160.nameserver.php b/actions/admin/settings/160.nameserver.php
index bccbd278..21c72b7f 100644
--- a/actions/admin/settings/160.nameserver.php
+++ b/actions/admin/settings/160.nameserver.php
@@ -2,74 +2,81 @@
 
 /**
  * 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  (2003-2009)
- * @author     Froxlor team  (2010-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    Settings
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
-return array(
-	'groups' => array(
-		'nameserver' => array(
-			'title' => $lng['admin']['nameserversettings'],
+
+return [
+	'groups' => [
+		'nameserver' => [
+			'title' => lng('admin.nameserversettings'),
 			'icon' => 'fa-solid fa-globe',
-			'fields' => array(
-				'nameserver_enable' => array(
-					'label' => $lng['serversettings']['bindenable'],
+			'fields' => [
+				'nameserver_enable' => [
+					'label' => lng('serversettings.bindenable'),
 					'settinggroup' => 'system',
 					'varname' => 'bind_enable',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField',
 					'overview_option' => true
-				),
-				'system_dnsenabled' => array(
-					'label' => $lng['serversettings']['dnseditorenable'],
+				],
+				'system_dnsenabled' => [
+					'label' => lng('serversettings.dnseditorenable'),
 					'settinggroup' => 'system',
 					'varname' => 'dnsenabled',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'system_dns_server' => array(
-					'label' => $lng['serversettings']['dns_server'],
+				],
+				'system_dns_server' => [
+					'label' => lng('serversettings.dns_server'),
 					'settinggroup' => 'system',
 					'varname' => 'dns_server',
 					'type' => 'select',
 					'default' => 'Bind',
-					'select_var' => array(
+					'select_var' => [
 						'Bind' => 'Bind9',
 						'PowerDNS' => 'PowerDNS'
-					),
+					],
 					'save_method' => 'storeSettingField'
-				),
-				'system_bindconf_directory' => array(
-					'label' => $lng['serversettings']['bindconf_directory'],
+				],
+				'system_bindconf_directory' => [
+					'label' => lng('serversettings.bindconf_directory'),
 					'settinggroup' => 'system',
 					'varname' => 'bindconf_directory',
 					'type' => 'text',
 					'string_type' => 'dir',
 					'default' => '/etc/bind/',
 					'save_method' => 'storeSettingField'
-				),
-				'system_bindreload_command' => array(
-					'label' => $lng['serversettings']['bindreload_command'],
+				],
+				'system_bindreload_command' => [
+					'label' => lng('serversettings.bindreload_command'),
 					'settinggroup' => 'system',
 					'varname' => 'bindreload_command',
 					'type' => 'text',
 					'default' => '/etc/init.d/bind9 reload',
 					'save_method' => 'storeSettingField'
-				),
-				'system_nameservers' => array(
-					'label' => $lng['serversettings']['nameservers'],
+				],
+				'system_nameservers' => [
+					'label' => lng('serversettings.nameservers'),
 					'settinggroup' => 'system',
 					'varname' => 'nameservers',
 					'type' => 'text',
@@ -77,9 +84,9 @@ return array(
 					'string_emptyallowed' => true,
 					'default' => '',
 					'save_method' => 'storeSettingFieldInsertBindTask'
-				),
-				'system_mxservers' => array(
-					'label' => $lng['serversettings']['mxservers'],
+				],
+				'system_mxservers' => [
+					'label' => lng('serversettings.mxservers'),
 					'settinggroup' => 'system',
 					'varname' => 'mxservers',
 					'type' => 'text',
@@ -87,9 +94,9 @@ return array(
 					'string_emptyallowed' => true,
 					'default' => '',
 					'save_method' => 'storeSettingField'
-				),
-				'system_axfrservers' => array(
-					'label' => $lng['serversettings']['axfrservers'],
+				],
+				'system_axfrservers' => [
+					'label' => lng('serversettings.axfrservers'),
 					'settinggroup' => 'system',
 					'varname' => 'axfrservers',
 					'type' => 'text',
@@ -98,48 +105,48 @@ return array(
 					'string_emptyallowed' => true,
 					'default' => '',
 					'save_method' => 'storeSettingField'
-				),
-				'system_powerdns_mode' => array(
-					'label' => $lng['serversettings']['powerdns_mode'],
+				],
+				'system_powerdns_mode' => [
+					'label' => lng('serversettings.powerdns_mode'),
 					'settinggroup' => 'system',
 					'varname' => 'powerdns_mode',
 					'type' => 'select',
 					'default' => 'Native',
-					'select_var' => array(
+					'select_var' => [
 						'Native' => 'Native',
 						'Master' => 'Master'
-					),
+					],
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_dns_createmailentry' => array(
-					'label' => $lng['serversettings']['mail_also_with_mxservers'],
+				],
+				'system_dns_createmailentry' => [
+					'label' => lng('serversettings.mail_also_with_mxservers'),
 					'settinggroup' => 'system',
 					'varname' => 'dns_createmailentry',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'system_dns_createcaaentry' => array(
-					'label' => $lng['serversettings']['caa_entry'],
+				],
+				'system_dns_createcaaentry' => [
+					'label' => lng('serversettings.caa_entry'),
 					'settinggroup' => 'system',
 					'varname' => 'dns_createcaaentry',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'caa_caa_entry' => array(
-					'label' => $lng['serversettings']['caa_entry_custom'],
+				],
+				'caa_caa_entry' => [
+					'label' => lng('serversettings.caa_entry_custom'),
 					'settinggroup' => 'caa',
 					'varname' => 'caa_entry',
 					'type' => 'textarea',
 					'default' => '',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_defaultttl' => array(
-					'label' => $lng['serversettings']['defaultttl'],
+				],
+				'system_defaultttl' => [
+					'label' => lng('serversettings.defaultttl'),
 					'settinggroup' => 'system',
 					'varname' => 'defaultttl',
 					'type' => 'number',
@@ -147,17 +154,17 @@ return array(
 					'min' => 3600, /* 1 hour */
 					'max' => 2147483647, /* integer max */
 					'save_method' => 'storeSettingField'
-				),
-				'system_soaemail' => array(
-					'label' => $lng['serversettings']['soaemail'],
+				],
+				'system_soaemail' => [
+					'label' => lng('serversettings.soaemail'),
 					'settinggroup' => 'system',
 					'varname' => 'soaemail',
 					'type' => 'email',
 					'string_emptyallowed' => true,
 					'default' => '',
 					'save_method' => 'storeSettingField'
-				)
-			)
-		)
-	)
-);
+				]
+			]
+		]
+	]
+];
diff --git a/actions/admin/settings/170.logger.php b/actions/admin/settings/170.logger.php
index d38f87aa..346d613a 100644
--- a/actions/admin/settings/170.logger.php
+++ b/actions/admin/settings/170.logger.php
@@ -2,63 +2,70 @@
 
 /**
  * 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  (2003-2009)
- * @author     Froxlor team  (2010-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    Settings
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
-return array(
-	'groups' => array(
-		'logging' => array(
-			'title' => $lng['admin']['loggersettings'],
+
+return [
+	'groups' => [
+		'logging' => [
+			'title' => lng('admin.loggersettings'),
 			'icon' => 'fa-solid fa-file-lines',
-			'fields' => array(
-				'logger_enabled' => array(
-					'label' => $lng['serversettings']['logger']['enable'],
+			'fields' => [
+				'logger_enabled' => [
+					'label' => lng('serversettings.logger.enable'),
 					'settinggroup' => 'logger',
 					'varname' => 'enabled',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
 					'overview_option' => true
-				),
-				'logger_severity' => array(
-					'label' => $lng['serversettings']['logger']['severity'],
+				],
+				'logger_severity' => [
+					'label' => lng('serversettings.logger.severity'),
 					'settinggroup' => 'logger',
 					'varname' => 'severity',
 					'type' => 'select',
 					'default' => 1,
-					'select_var' => array(
-						1 => $lng['admin']['logger']['normal'],
-						2 => $lng['admin']['logger']['paranoid']
-					),
+					'select_var' => [
+						1 => lng('admin.logger.normal'),
+						2 => lng('admin.logger.paranoid')
+					],
 					'save_method' => 'storeSettingField'
-				),
-				'logger_logtypes' => array(
-					'label' => $lng['serversettings']['logger']['types'],
+				],
+				'logger_logtypes' => [
+					'label' => lng('serversettings.logger.types'),
 					'settinggroup' => 'logger',
 					'varname' => 'logtypes',
 					'type' => 'select',
 					'default' => 'syslog,mysql',
 					'select_mode' => 'multiple',
-					'select_var' => array(
+					'select_var' => [
 						'syslog' => 'syslog',
 						'file' => 'file',
 						'mysql' => 'mysql'
-					),
+					],
 					'save_method' => 'storeSettingField'
-				),
-				'logger_logfile' => array(
-					'label' => $lng['serversettings']['logger']['logfile'],
+				],
+				'logger_logfile' => [
+					'label' => lng('serversettings.logger.logfile'),
 					'settinggroup' => 'logger',
 					'varname' => 'logfile',
 					'type' => 'text',
@@ -66,21 +73,21 @@ return array(
 					'string_emptyallowed' => true,
 					'default' => '',
 					'save_method' => 'storeSettingField'
-				),
-				'logger_log_cron' => array(
-					'label' => $lng['serversettings']['logger']['logcron'],
+				],
+				'logger_log_cron' => [
+					'label' => lng('serversettings.logger.logcron'),
 					'settinggroup' => 'logger',
 					'varname' => 'log_cron',
 					'type' => 'select',
 					'default' => 0,
-					'select_var' => array(
-						0 => $lng['serversettings']['logger']['logcronoption']['never'],
-						1 => $lng['serversettings']['logger']['logcronoption']['once'],
-						2 => $lng['serversettings']['logger']['logcronoption']['always']
-					),
+					'select_var' => [
+						0 => lng('serversettings.logger.logcronoption.never'),
+						1 => lng('serversettings.logger.logcronoption.once'),
+						2 => lng('serversettings.logger.logcronoption.always')
+					],
 					'save_method' => 'storeSettingField'
-				)
-			)
-		)
-	)
-);
+				]
+			]
+		]
+	]
+];
diff --git a/actions/admin/settings/180.dkim.php b/actions/admin/settings/180.dkim.php
index 15ba6909..792ed8ff 100644
--- a/actions/admin/settings/180.dkim.php
+++ b/actions/admin/settings/180.dkim.php
@@ -2,46 +2,55 @@
 
 /**
  * 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  (2003-2009)
- * @author     Froxlor team  (2010-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    \Froxlor\Settings
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
-return array(
-	'groups' => array(
-		'dkim' => array(
-			'title' => $lng['admin']['dkimsettings'],
+
+use Froxlor\Settings;
+
+return [
+	'groups' => [
+		'dkim' => [
+			'title' => lng('admin.dkimsettings'),
 			'icon' => 'fa-solid fa-fingerprint',
-			'fields' => array(
-				'dkim_enabled' => array(
-					'label' => $lng['dkim']['use_dkim'],
+			'fields' => [
+				'dkim_enabled' => [
+					'label' => lng('dkim.use_dkim'),
 					'settinggroup' => 'dkim',
 					'varname' => 'use_dkim',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingFieldInsertBindTask',
 					'overview_option' => true
-				),
-				'dkim_prefix' => array(
-					'label' => $lng['dkim']['dkim_prefix'],
+				],
+				'dkim_prefix' => [
+					'label' => lng('dkim.dkim_prefix'),
 					'settinggroup' => 'dkim',
 					'varname' => 'dkim_prefix',
 					'type' => 'text',
 					'string_type' => 'dir',
 					'default' => '/etc/postfix/dkim/',
 					'save_method' => 'storeSettingField'
-				),
-				'dkim_privkeysuffix' => array(
-					'label' => $lng['dkim']['privkeysuffix'],
+				],
+				'dkim_privkeysuffix' => [
+					'label' => lng('dkim.privkeysuffix'),
 					'settinggroup' => 'dkim',
 					'varname' => 'privkeysuffix',
 					'type' => 'text',
@@ -49,70 +58,70 @@ return array(
 					'default' => '.priv',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'dkim_domains' => array(
-					'label' => $lng['dkim']['dkim_domains'],
+				],
+				'dkim_domains' => [
+					'label' => lng('dkim.dkim_domains'),
 					'settinggroup' => 'dkim',
 					'varname' => 'dkim_domains',
 					'type' => 'text',
 					'string_regexp' => '/^[a-z0-9\._]+$/i',
 					'default' => 'domains',
 					'save_method' => 'storeSettingField'
-				),
-				'dkim_dkimkeys' => array(
-					'label' => $lng['dkim']['dkim_dkimkeys'],
+				],
+				'dkim_dkimkeys' => [
+					'label' => lng('dkim.dkim_dkimkeys'),
 					'settinggroup' => 'dkim',
 					'varname' => 'dkim_dkimkeys',
 					'type' => 'text',
 					'string_regexp' => '/^[a-z0-9\._]+$/i',
 					'default' => 'dkim-keys.conf',
 					'save_method' => 'storeSettingField'
-				),
-				'dkim_algorithm' => array(
-					'label' => $lng['dkim']['dkim_algorithm'],
+				],
+				'dkim_algorithm' => [
+					'label' => lng('dkim.dkim_algorithm'),
 					'settinggroup' => 'dkim',
 					'varname' => 'dkim_algorithm',
 					'type' => 'select',
 					'default' => 'all',
 					'select_mode' => 'multiple',
-					'select_var' => array(
+					'select_var' => [
 						'all' => 'All',
 						'sha1' => 'SHA1',
 						'sha256' => 'SHA256'
-					),
+					],
 					'save_method' => 'storeSettingFieldInsertBindTask',
 					'advanced_mode' => true
-				),
-				'dkim_servicetype' => array(
-					'label' => $lng['dkim']['dkim_servicetype'],
+				],
+				'dkim_servicetype' => [
+					'label' => lng('dkim.dkim_servicetype'),
 					'settinggroup' => 'dkim',
 					'varname' => 'dkim_servicetype',
 					'type' => 'select',
 					'default' => '0',
-					'select_var' => array(
+					'select_var' => [
 						'0' => 'All',
 						'1' => 'E-Mail'
-					),
+					],
 					'save_method' => 'storeSettingFieldInsertBindTask',
 					'advanced_mode' => true
-				),
-				'dkim_keylength' => array(
-					'label' => array(
-						'title' => $lng['dkim']['dkim_keylength']['title'],
-						'description' => sprintf($lng['dkim']['dkim_keylength']['description'], \Froxlor\Settings::Get('dkim.dkim_prefix'))
-					),
+				],
+				'dkim_keylength' => [
+					'label' => [
+						'title' => lng('dkim.dkim_keylength.title'),
+						'description' => sprintf(lng('dkim.dkim_keylength.description'), Settings::Get('dkim.dkim_prefix'))
+					],
 					'settinggroup' => 'dkim',
 					'varname' => 'dkim_keylength',
 					'type' => 'select',
 					'default' => '1024',
-					'select_var' => array(
+					'select_var' => [
 						'1024' => '1024 Bit',
 						'2048' => '2048 Bit'
-					),
+					],
 					'save_method' => 'storeSettingFieldInsertBindTask'
-				),
-				'dkim_notes' => array(
-					'label' => $lng['dkim']['dkim_notes'],
+				],
+				'dkim_notes' => [
+					'label' => lng('dkim.dkim_notes'),
 					'settinggroup' => 'dkim',
 					'varname' => 'dkim_notes',
 					'type' => 'text',
@@ -120,16 +129,16 @@ return array(
 					'default' => '',
 					'save_method' => 'storeSettingFieldInsertBindTask',
 					'advanced_mode' => true
-				),
-				'dkimrestart_command' => array(
-					'label' => $lng['dkim']['dkimrestart_command'],
+				],
+				'dkimrestart_command' => [
+					'label' => lng('dkim.dkimrestart_command'),
 					'settinggroup' => 'dkim',
 					'varname' => 'dkimrestart_command',
 					'type' => 'text',
 					'default' => '/etc/init.d/dkim-filter restart',
 					'save_method' => 'storeSettingField'
-				)
-			)
-		)
-	)
-);
+				]
+			]
+		]
+	]
+];
diff --git a/actions/admin/settings/185.spf.php b/actions/admin/settings/185.spf.php
index 402d4de1..51d7b9a2 100644
--- a/actions/admin/settings/185.spf.php
+++ b/actions/admin/settings/185.spf.php
@@ -4,40 +4,49 @@
  * 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  (2010-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    Settings
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
-return array(
-	'groups' => array(
-		'spf' => array(
-			'title' => $lng['admin']['spfsettings'],
+
+return [
+	'groups' => [
+		'spf' => [
+			'title' => lng('admin.spfsettings'),
 			'icon' => 'fa-solid fa-clipboard-check',
-			'fields' => array(
-				'spf_enabled' => array(
-					'label' => $lng['spf']['use_spf'],
+			'fields' => [
+				'spf_enabled' => [
+					'label' => lng('spf.use_spf'),
 					'settinggroup' => 'spf',
 					'varname' => 'use_spf',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
 					'overview_option' => true
-				),
-				'spf_entry' => array(
-					'label' => $lng['spf']['spf_entry'],
+				],
+				'spf_entry' => [
+					'label' => lng('spf.spf_entry'),
 					'settinggroup' => 'spf',
 					'varname' => 'spf_entry',
 					'type' => 'text',
 					'default' => '"v=spf1 a mx -all"',
 					'save_method' => 'storeSettingField'
-				)
-			)
-		)
-	)
-);
+				]
+			]
+		]
+	]
+];
diff --git a/actions/admin/settings/210.security.php b/actions/admin/settings/210.security.php
index 051c5d69..704ae994 100644
--- a/actions/admin/settings/210.security.php
+++ b/actions/admin/settings/210.security.php
@@ -2,83 +2,92 @@
 
 /**
  * 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  (2003-2009)
- * @author     Froxlor team  (2010-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    Settings
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
-return array(
-	'groups' => array(
-		'security' => array(
-			'title' => $lng['admin']['security_settings'],
+
+use Froxlor\Settings;
+
+return [
+	'groups' => [
+		'security' => [
+			'title' => lng('admin.security_settings'),
 			'icon' => 'fa-solid fa-user-lock',
-			'fields' => array(
-				'panel_unix_names' => array(
-					'label' => $lng['serversettings']['unix_names'],
+			'fields' => [
+				'panel_unix_names' => [
+					'label' => lng('serversettings.unix_names'),
 					'settinggroup' => 'panel',
 					'varname' => 'unix_names',
 					'type' => 'checkbox',
 					'default' => true,
 					'save_method' => 'storeSettingField'
-				),
-				'system_mailpwcleartext' => array(
-					'label' => $lng['serversettings']['mailpwcleartext'],
+				],
+				'system_mailpwcleartext' => [
+					'label' => lng('serversettings.mailpwcleartext'),
 					'settinggroup' => 'system',
 					'varname' => 'mailpwcleartext',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_passwordcryptfunc' => array(
-					'label' => $lng['serversettings']['passwordcryptfunc'],
+				],
+				'system_passwordcryptfunc' => [
+					'label' => lng('serversettings.passwordcryptfunc'),
 					'settinggroup' => 'system',
 					'varname' => 'passwordcryptfunc',
 					'type' => 'select',
 					'default' => 0,
-					'option_options_method' => array(
+					'option_options_method' => [
 						'\\Froxlor\\System\\Crypt',
 						'getAvailablePasswordHashes'
-					),
+					],
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_allow_error_report_admin' => array(
-					'label' => $lng['serversettings']['allow_error_report_admin'],
+				],
+				'system_allow_error_report_admin' => [
+					'label' => lng('serversettings.allow_error_report_admin'),
 					'settinggroup' => 'system',
 					'varname' => 'allow_error_report_admin',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'system_allow_error_report_customer' => array(
-					'label' => $lng['serversettings']['allow_error_report_customer'],
+				],
+				'system_allow_error_report_customer' => [
+					'label' => lng('serversettings.allow_error_report_customer'),
 					'settinggroup' => 'system',
 					'varname' => 'allow_error_report_customer',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField'
-				),
-				'system_allow_customer_shell' => array(
-					'label' => $lng['serversettings']['allow_allow_customer_shell'],
+				],
+				'system_allow_customer_shell' => [
+					'label' => lng('serversettings.allow_allow_customer_shell'),
 					'settinggroup' => 'system',
 					'varname' => 'allow_customer_shell',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_available_shells' => array(
-					'label' => $lng['serversettings']['available_shells'],
+				],
+				'system_available_shells' => [
+					'label' => lng('serversettings.available_shells'),
 					'settinggroup' => 'system',
 					'varname' => 'available_shells',
 					'type' => 'text',
@@ -86,22 +95,22 @@ return array(
 					'default' => '',
 					'save_method' => 'storeSettingField',
 					'advanced_mode' => true
-				),
-				'system_froxlorusergroup' => array(
-					'label' => $lng['serversettings']['froxlorusergroup'],
+				],
+				'system_froxlorusergroup' => [
+					'label' => lng('serversettings.froxlorusergroup'),
 					'settinggroup' => 'system',
 					'varname' => 'froxlorusergroup',
 					'type' => 'text',
 					'default' => '',
 					'save_method' => 'storeSettingField',
-					'plausibility_check_method' => array(
+					'plausibility_check_method' => [
 						'\\Froxlor\\Validate\\Check',
 						'checkLocalGroup'
-					),
-					'visible' => \Froxlor\Settings::Get('system.nssextrausers'),
+					],
+					'visible' => Settings::Get('system.nssextrausers'),
 					'advanced_mode' => true
-				),
-			)
-		)
-	)
-);
+				],
+			]
+		]
+	]
+];
diff --git a/actions/admin/settings/220.quota.php b/actions/admin/settings/220.quota.php
index f03b324b..b73b2be4 100644
--- a/actions/admin/settings/220.quota.php
+++ b/actions/admin/settings/220.quota.php
@@ -1,59 +1,69 @@
  (2011-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    Settings
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
-return array(
-	'groups' => array(
-		'diskquota' => array(
-			'title' => $lng['diskquota'],
+
+return [
+	'groups' => [
+		'diskquota' => [
+			'title' => lng('diskquota'),
 			'icon' => 'fa-solid fa-sliders',
 			'advanced_mode' => true,
-			'fields' => array(
-				'diskquota_enabled' => array(
-					'label' => $lng['serversettings']['diskquota_enabled'],
+			'fields' => [
+				'diskquota_enabled' => [
+					'label' => lng('serversettings.diskquota_enabled'),
 					'settinggroup' => 'system',
 					'varname' => 'diskquota_enabled',
 					'type' => 'checkbox',
 					'default' => false,
 					'save_method' => 'storeSettingField',
 					'overview_option' => true
-				),
-				'diskquota_repquota_path' => array(
-					'label' => $lng['serversettings']['diskquota_repquota_path']['description'],
+				],
+				'diskquota_repquota_path' => [
+					'label' => lng('serversettings.diskquota_repquota_path.description'),
 					'settinggroup' => 'system',
 					'varname' => 'diskquota_repquota_path',
 					'type' => 'text',
 					'default' => '/usr/sbin/repquota',
 					'save_method' => 'storeSettingField'
-				),
-				'diskquota_quotatool_path' => array(
-					'label' => $lng['serversettings']['diskquota_quotatool_path']['description'],
+				],
+				'diskquota_quotatool_path' => [
+					'label' => lng('serversettings.diskquota_quotatool_path.description'),
 					'settinggroup' => 'system',
 					'varname' => 'diskquota_quotatool_path',
 					'type' => 'text',
 					'default' => '/usr/bin/quotatool',
 					'save_method' => 'storeSettingField'
-				),
-				'diskquota_customer_partition' => array(
-					'label' => $lng['serversettings']['diskquota_customer_partition']['description'],
+				],
+				'diskquota_customer_partition' => [
+					'label' => lng('serversettings.diskquota_customer_partition.description'),
 					'settinggroup' => 'system',
 					'varname' => 'diskquota_customer_partition',
 					'type' => 'text',
 					'default' => '/dev/root',
 					'save_method' => 'storeSettingField'
-				)
-			)
-		)
-	)
-);
+				]
+			]
+		]
+	]
+];
diff --git a/admin_admins.php b/admin_admins.php
index 87b37b8b..5fecaf3e 100644
--- a/admin_admins.php
+++ b/admin_admins.php
@@ -2,123 +2,137 @@
 
 /**
  * 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  (2003-2009)
- * @author     Froxlor team  (2010-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    Panel
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
 
 const AREA = 'admin';
-require __DIR__ .  '/lib/init.php';
+require __DIR__ . '/lib/init.php';
 
 use Froxlor\Api\Commands\Admins;
+use Froxlor\CurrentUser;
 use Froxlor\Database\Database;
+use Froxlor\FroxlorLogger;
+use Froxlor\PhpHelper;
 use Froxlor\Settings;
+use Froxlor\UI\Collection;
+use Froxlor\UI\HTML;
+use Froxlor\UI\Listing;
 use Froxlor\UI\Panel\UI;
 use Froxlor\UI\Request;
+use Froxlor\UI\Response;
 
-$id = (int) Request::get('id');
+$id = (int)Request::get('id');
 
 if ($page == 'admins' && $userinfo['change_serversettings'] == '1') {
-
 	if ($action == '') {
-		$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_admins");
+		$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_admins");
 
-        try {
-            $admin_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/admin/tablelisting.admins.php';
-            $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Admins::class, $userinfo))
-                ->withPagination($admin_list_data['admin_list']['columns']);
+		try {
+			$admin_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/admin/tablelisting.admins.php';
+			$collection = (new Collection(Admins::class, $userinfo))
+				->withPagination($admin_list_data['admin_list']['columns']);
 		} catch (Exception $e) {
-			\Froxlor\UI\Response::dynamic_error($e->getMessage());
+			Response::dynamicError($e->getMessage());
 		}
 
 		UI::view('user/table.html.twig', [
-			'listing' => \Froxlor\UI\Listing::format($collection, $admin_list_data, 'admin_list') ,
-			'actions_links' => [[
-				'href' => $linker->getLink(['section' => 'admins', 'page' => $page, 'action' => 'add']),
-				'label' => $lng['admin']['admin_add']
-			]]
+			'listing' => Listing::format($collection, $admin_list_data, 'admin_list'),
+			'actions_links' => [
+				[
+					'href' => $linker->getLink(['section' => 'admins', 'page' => $page, 'action' => 'add']),
+					'label' => lng('admin.admin_add')
+				]
+			]
 		]);
 	} elseif ($action == 'su') {
-
 		try {
-			$json_result = Admins::getLocal($userinfo, array(
+			$json_result = Admins::getLocal($userinfo, [
 				'id' => $id
-			))->get();
+			])->get();
 		} catch (Exception $e) {
-			\Froxlor\UI\Response::dynamic_error($e->getMessage());
+			Response::dynamicError($e->getMessage());
 		}
 		$result = json_decode($json_result, true)['data'];
 		$destination_admin = $result['loginname'];
 
 		if ($destination_admin != '' && $result['adminid'] != $userinfo['userid']) {
-
-			$result['switched_user'] = \Froxlor\CurrentUser::getData();
+			$result['switched_user'] = CurrentUser::getData();
 			$result['adminsession'] = 1;
 			$result['userid'] = $result['adminid'];
-			\Froxlor\CurrentUser::setData($result);
+			CurrentUser::setData($result);
 
-			$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "switched adminuser and is now '" . $destination_admin . "'");
-			\Froxlor\UI\Response::redirectTo('admin_index.php');
+			$log->logAction(
+                FroxlorLogger::ADM_ACTION,
+                LOG_INFO,
+                "switched adminuser and is now '" . $destination_admin . "'"
+            );
+			Response::redirectTo('admin_index.php');
 		} else {
-			\Froxlor\UI\Response::redirectTo('index.php', array(
+			Response::redirectTo('index.php', [
 				'action' => 'login'
-			));
+			]);
 		}
 	} elseif ($action == 'delete' && $id != 0) {
 		try {
-			$json_result = Admins::getLocal($userinfo, array(
+			$json_result = Admins::getLocal($userinfo, [
 				'id' => $id
-			))->get();
+			])->get();
 		} catch (Exception $e) {
-			\Froxlor\UI\Response::dynamic_error($e->getMessage());
+			Response::dynamicError($e->getMessage());
 		}
 		$result = json_decode($json_result, true)['data'];
 
 		if ($result['loginname'] != '') {
 			if ($result['adminid'] == $userinfo['userid']) {
-				\Froxlor\UI\Response::standard_error('youcantdeleteyourself');
+				Response::standardError('youcantdeleteyourself');
 			}
 
 			if (isset($_POST['send']) && $_POST['send'] == 'send') {
-				Admins::getLocal($userinfo, array(
+				Admins::getLocal($userinfo, [
 					'id' => $id
-				))->delete();
-				\Froxlor\UI\Response::redirectTo($filename, array(
+				])->delete();
+				Response::redirectTo($filename, [
 					'page' => $page
-				));
+				]);
 			} else {
-				\Froxlor\UI\HTML::askYesNo('admin_admin_reallydelete', $filename, array(
+				HTML::askYesNo('admin_admin_reallydelete', $filename, [
 					'id' => $id,
 					'page' => $page,
 					'action' => $action
-				), $result['loginname']);
+				], $result['loginname']);
 			}
 		}
 	} elseif ($action == 'add') {
-
 		if (isset($_POST['send']) && $_POST['send'] == 'send') {
 			try {
 				Admins::getLocal($userinfo, $_POST)->add();
 			} catch (Exception $e) {
-				\Froxlor\UI\Response::dynamic_error($e->getMessage());
+				Response::dynamicError($e->getMessage());
 			}
-			\Froxlor\UI\Response::redirectTo($filename, array(
+			Response::redirectTo($filename, [
 				'page' => $page
-			));
+			]);
 		} else {
-
 			$ipaddress = [];
-			$ipaddress[-1] = $lng['admin']['allips'];
+			$ipaddress[-1] = lng('admin.allips');
 			$ipsandports_stmt = Database::query("
 				SELECT `id`, `ip` FROM `" . TABLE_PANEL_IPSANDPORTS . "` GROUP BY `ip` ORDER BY `ip` ASC
 			");
@@ -129,40 +143,38 @@ if ($page == 'admins' && $userinfo['change_serversettings'] == '1') {
 			$admin_add_data = include_once dirname(__FILE__) . '/lib/formfields/admin/admin/formfield.admin_add.php';
 
 			UI::view('user/form.html.twig', [
-				'formaction' => $linker->getLink(array('section' => 'admins')),
+				'formaction' => $linker->getLink(['section' => 'admins']),
 				'formdata' => $admin_add_data['admin_add']
 			]);
 		}
 	} elseif ($action == 'edit' && $id != 0) {
 		try {
-			$json_result = Admins::getLocal($userinfo, array(
+			$json_result = Admins::getLocal($userinfo, [
 				'id' => $id
-			))->get();
+			])->get();
 		} catch (Exception $e) {
-			\Froxlor\UI\Response::dynamic_error($e->getMessage());
+			Response::dynamicError($e->getMessage());
 		}
 		$result = json_decode($json_result, true)['data'];
 
 		if ($result['loginname'] != '') {
-
 			if (isset($_POST['send']) && $_POST['send'] == 'send') {
 				try {
 					Admins::getLocal($userinfo, $_POST)->update();
 				} catch (Exception $e) {
-					\Froxlor\UI\Response::dynamic_error($e->getMessage());
+					Response::dynamicError($e->getMessage());
 				}
-				\Froxlor\UI\Response::redirectTo($filename, array(
+				Response::redirectTo($filename, [
 					'page' => $page
-				));
+				]);
 			} else {
-
 				$dec_places = Settings::Get('panel.decimal_places');
 				$result['traffic'] = round($result['traffic'] / (1024 * 1024), $dec_places);
 				$result['diskspace'] = round($result['diskspace'] / 1024, $dec_places);
 				$result['email'] = $idna_convert->decode($result['email']);
 
 				$ipaddress = [];
-				$ipaddress[-1] = $lng['admin']['allips'];
+				$ipaddress[-1] = lng('admin.allips');
 				$ipsandports_stmt = Database::query("
 					SELECT `id`, `ip` FROM `" . TABLE_PANEL_IPSANDPORTS . "` GROUP BY `ip` ORDER BY `ip` ASC
 				");
@@ -170,12 +182,12 @@ if ($page == 'admins' && $userinfo['change_serversettings'] == '1') {
 					$ipaddress[$row['id']] = $row['ip'];
 				}
 
-				$result = \Froxlor\PhpHelper::htmlentitiesArray($result);
+				$result = PhpHelper::htmlentitiesArray($result);
 
 				$admin_edit_data = include_once dirname(__FILE__) . '/lib/formfields/admin/admin/formfield.admin_edit.php';
 
 				UI::view('user/form.html.twig', [
-					'formaction' => $linker->getLink(array('section' => 'admins', 'id' => $id)),
+					'formaction' => $linker->getLink(['section' => 'admins', 'id' => $id]),
 					'formdata' => $admin_edit_data['admin_edit'],
 					'editid' => $id
 				]);
diff --git a/admin_apcuinfo.php b/admin_apcuinfo.php
index c3a4e7cc..6a36d755 100644
--- a/admin_apcuinfo.php
+++ b/admin_apcuinfo.php
@@ -11,12 +11,12 @@
  *
  * 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
+ * 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
- * http://files.froxlor.org/misc/COPYING.txt
+ * https://files.froxlor.org/misc/COPYING.txt
  *
  * @copyright  the authors
  * @author     Froxlor team 
@@ -24,14 +24,16 @@
  * @author     Ralf Becker 
  * @author     Rasmus Lerdorf 
  * @author     Ilia Alshanetsky 
- * @license    http://files.froxlor.org/misc/COPYING.txt GPLv2
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  *
  * Based on https://github.com/krakjoe/apcu/blob/master/apc.php, which is
  * licensed under the PHP licence (version 3.01), which can be viewed
  * online at https://www.php.net/license/3_01.txt
  */
 
+use Froxlor\FroxlorLogger;
 use Froxlor\UI\Panel\UI;
+use Froxlor\UI\Response;
 
 const AREA = 'admin';
 require __DIR__ . '/lib/init.php';
@@ -40,31 +42,31 @@ $horizontal_bar_size = 950; // 1280px window width
 
 if ($action == 'delete' && function_exists('apcu_clear_cache') && $userinfo['change_serversettings'] == '1') {
 	apcu_clear_cache();
-	$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "cleared APCu cache");
-	header('Location: ' . $linker->getLink(array(
+	$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "cleared APCu cache");
+	header('Location: ' . $linker->getLink([
 			'section' => 'apcuinfo',
 			'page' => 'showinfo'
-		)));
+		]));
 	exit();
 }
 
 if (!function_exists('apcu_cache_info') || !function_exists('apcu_sma_info')) {
-	\Froxlor\UI\Response::standard_error($lng['error']['no_apcuinfo']);
+	Response::standardError(lng('error.no_apcuinfo'));
 }
 
 if ($page == 'showinfo') {
 	$cache = apcu_cache_info();
 	$mem = apcu_sma_info();
 	$time = time();
-	$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_apcuinfo");
+	$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_apcuinfo");
 
 	// check for possible empty values that are used in the templates
 	if (!isset($cache['file_upload_progress'])) {
-		$cache['file_upload_progress'] = $lng['logger']['unknown'];
+		$cache['file_upload_progress'] = lng('logger.unknown');
 	}
 
 	if (!isset($cache['num_expunges'])) {
-		$cache['num_expunges'] = $lng['logger']['unknown'];
+		$cache['num_expunges'] = lng('logger.unknown');
 	}
 
 	$overview = [
diff --git a/admin_autoupdate.php b/admin_autoupdate.php
index e4593905..2be6074b 100644
--- a/admin_autoupdate.php
+++ b/admin_autoupdate.php
@@ -2,70 +2,78 @@
 
 /**
  * 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 
- * @author     Froxlor team  (2010-)
- * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
- * @package    Frontend
+ * 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
+ * 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 
+ * @license    https://files.froxlor.org/misc/COPYING.txt GPLv2
  */
 
 const AREA = 'admin';
 require __DIR__ . '/lib/init.php';
 
+use Froxlor\Froxlor;
+use Froxlor\FroxlorLogger;
 use Froxlor\Http\HttpClient;
+use Froxlor\Settings;
 use Froxlor\UI\Panel\UI;
+use Froxlor\UI\Response;
 
 // define update-uri
-define('UPDATE_URI', "https://version.froxlor.org/Froxlor/api/" . \Froxlor\Froxlor::VERSION);
+define('UPDATE_URI', "https://version.froxlor.org/Froxlor/api/" . Froxlor::VERSION);
 define('RELEASE_URI', "https://autoupdate.froxlor.org/froxlor-{version}.zip");
 define('CHECKSUM_URI', "https://autoupdate.froxlor.org/froxlor-{version}.zip.sha256");
 
 if ($page != 'error') {
 	// check for archive-stuff
 	if (!extension_loaded('zip')) {
-		\Froxlor\UI\Response::redirectTo($filename, array(
+		Response::redirectTo($filename, [
 			'page' => 'error',
 			'errno' => 2
-		));
+		]);
 	}
 
 	// 0.11.x requires 7.4 at least
 	if (version_compare("7.4.0", PHP_VERSION, ">=")) {
-		\Froxlor\UI\Response::redirectTo($filename, array(
+		Response::redirectTo($filename, [
 			'page' => 'error',
 			'errno' => 10
-		));
+		]);
 	}
 
 	// check for webupdate to be enabled
-	if (\Froxlor\Settings::Config('enable_webupdate') != true) {
-		\Froxlor\UI\Response::redirectTo($filename, array(
+	if (Settings::Config('enable_webupdate') != true) {
+		Response::redirectTo($filename, [
 			'page' => 'error',
 			'errno' => 11
-		));
+		]);
 	}
 }
 
 // display initial version check
 if ($page == 'overview') {
-
 	// log our actions
-	$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "checking auto-update");
+	$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "checking auto-update");
 
 	// check for new version
 	try {
 		$latestversion = HttpClient::urlGet(UPDATE_URI, true, 3);
-	} catch (\Exception $e) {
-		\Froxlor\UI\Response::dynamic_error("Version-check currently unavailable, please try again later");
+	} catch (Exception $e) {
+		Response::dynamicError("Version-check currently unavailable, please try again later");
 	}
 	$latestversion = explode('|', $latestversion);
 
@@ -76,7 +84,7 @@ if ($page == 'overview') {
 
 		// add the branding so debian guys are not gettings confused
 		// about their version-number
-		$version_label = $_version . \Froxlor\Froxlor::BRANDING;
+		$version_label = $_version . Froxlor::BRANDING;
 		$version_link = $_link;
 		$message_addinfo = $_message;
 
@@ -84,11 +92,11 @@ if ($page == 'overview') {
 		if (!preg_match('/^((\d+\\.)(\d+\\.)(\d+\\.)?(\d+)?(\-(svn|dev|rc)(\d+))?)$/', $_version)) {
 			// check for customized version to not output
 			// "There is a newer version of froxlor" besides the error-message
-			\Froxlor\UI\Response::redirectTo($filename, array(
+			Response::redirectTo($filename, [
 				'page' => 'error',
 				'errno' => 3
-			));
-		} elseif (\Froxlor\Froxlor::versionCompare2(\Froxlor\Froxlor::VERSION, $_version) == -1) {
+			]);
+		} elseif (Froxlor::versionCompare2(Froxlor::VERSION, $_version) == -1) {
 			// there is a newer version - yay
 			$isnewerversion = 1;
 		} else {
@@ -99,11 +107,11 @@ if ($page == 'overview') {
 		// anzeige über version-status mit ggfls. formular
 		// zum update schritt #1 -> download
 		if ($isnewerversion == 1) {
-			$text = 'There is a newer version available. Update to version ' . $_version . ' now?
(Your current version is: ' . \Froxlor\Froxlor::VERSION . ')'; + $text = 'There is a newer version available. Update to version ' . $_version . ' now?
(Your current version is: ' . Froxlor::VERSION . ')'; $upd_formfield = [ 'updates' => [ - 'title' => $lng['update']['update'], + 'title' => lng('update.update'), 'image' => 'fa-solid fa-download', 'sections' => [ 'section_autoupd' => [ @@ -115,18 +123,18 @@ if ($page == 'overview') { 'buttons' => [ [ 'class' => 'btn-outline-secondary', - 'label' => $lng['panel']['cancel'], + 'label' => lng('panel.cancel'), 'type' => 'reset' ], [ - 'label' => $lng['update']['proceed'] + 'label' => lng('update.proceed') ] ] ] ]; UI::view('user/form-note.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'autoupdate', 'page' => 'getdownload')), + 'formaction' => $linker->getLink(['section' => 'autoupdate', 'page' => 'getdownload']), 'formdata' => $upd_formfield['updates'], // alert 'type' => 'warning', @@ -134,33 +142,31 @@ if ($page == 'overview') { ]); } elseif ($isnewerversion == 0) { // all good - \Froxlor\UI\Response::standard_success('noupdatesavail'); + Response::standardSuccess('noupdatesavail'); } else { - \Froxlor\UI\Response::standard_error('customized_version'); + Response::standardError('customized_version'); } } } // download the new archive elseif ($page == 'getdownload') { - // retrieve the new version from the form $newversion = isset($_POST['newversion']) ? $_POST['newversion'] : null; // valid? if ($newversion !== null) { - // define files to get $toLoad = str_replace('{version}', $newversion, RELEASE_URI); $toCheck = str_replace('{version}', $newversion, CHECKSUM_URI); // check for local destination folder - if (!is_dir(\Froxlor\Froxlor::getInstallDir() . '/updates/')) { - mkdir(\Froxlor\Froxlor::getInstallDir() . '/updates/'); + if (!is_dir(Froxlor::getInstallDir() . '/updates/')) { + mkdir(Froxlor::getInstallDir() . '/updates/'); } // name archive - $localArchive = \Froxlor\Froxlor::getInstallDir() . '/updates/' . basename($toLoad); + $localArchive = Froxlor::getInstallDir() . '/updates/' . basename($toLoad); - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "Downloading " . $toLoad . " to " . $localArchive); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "Downloading " . $toLoad . " to " . $localArchive); // remove old archive if (file_exists($localArchive)) { @@ -171,10 +177,10 @@ elseif ($page == 'getdownload') { try { HttpClient::fileGet($toLoad, $localArchive); } catch (Exception $e) { - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => 'error', 'errno' => 4 - )); + ]); } // validate the integrity of the downloaded file @@ -188,34 +194,33 @@ elseif ($page == 'getdownload') { $filesum = hash_file('sha256', $localArchive); if ($filesum != $shouldsum) { - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => 'error', 'errno' => 9 - )); + ]); } // to the next step - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => 'extract', 'archive' => basename($localArchive) - )); + ]); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => 'error', 'errno' => 6 - )); + ]); } // extract and install new version elseif ($page == 'extract') { - if (isset($_POST['send']) && $_POST['send'] == 'send') { $toExtract = isset($_POST['archive']) ? $_POST['archive'] : null; - $localArchive = \Froxlor\Froxlor::getInstallDir() . '/updates/' . $toExtract; + $localArchive = Froxlor::getInstallDir() . '/updates/' . $toExtract; // decompress from zip $zip = new ZipArchive(); $res = $zip->open($localArchive); if ($res === true) { - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "Extracting " . $localArchive . " to " . \Froxlor\Froxlor::getInstallDir()); - $zip->extractTo(\Froxlor\Froxlor::getInstallDir()); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "Extracting " . $localArchive . " to " . Froxlor::getInstallDir()); + $zip->extractTo(Froxlor::getInstallDir()); $zip->close(); // success - remove unused archive @unlink($localArchive); @@ -223,31 +228,31 @@ elseif ($page == 'extract') { sleep(2); } else { // error - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => 'error', 'errno' => 8 - )); + ]); } // redirect to update-page? - \Froxlor\UI\Response::redirectTo('admin_updates.php'); + Response::redirectTo('admin_updates.php'); } else { $toExtract = isset($_GET['archive']) ? $_GET['archive'] : null; - $localArchive = \Froxlor\Froxlor::getInstallDir() . '/updates/' . $toExtract; + $localArchive = Froxlor::getInstallDir() . '/updates/' . $toExtract; } if (!file_exists($localArchive)) { - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => 'error', 'errno' => 7 - )); + ]); } $text = 'Extract downloaded archive "' . $toExtract . '"?'; $upd_formfield = [ 'updates' => [ - 'title' => $lng['update']['update'], + 'title' => lng('update.update'), 'image' => 'fa-solid fa-download', 'sections' => [ 'section_autoupd' => [ @@ -259,18 +264,18 @@ elseif ($page == 'extract') { 'buttons' => [ [ 'class' => 'btn-outline-secondary', - 'label' => $lng['panel']['cancel'], + 'label' => lng('panel.cancel'), 'type' => 'reset' ], [ - 'label' => $lng['update']['proceed'] + 'label' => lng('update.proceed') ] ] ] ]; UI::view('user/form-note.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'autoupdate', 'page' => 'extract')), + 'formaction' => $linker->getLink(['section' => 'autoupdate', 'page' => 'extract']), 'formdata' => $upd_formfield['updates'], // alert 'type' => 'warning', @@ -278,9 +283,8 @@ elseif ($page == 'extract') { ]); } // display error elseif ($page == 'error') { - // retrieve error-number via url-parameter - $errno = isset($_GET['errno']) ? (int) $_GET['errno'] : 0; + $errno = isset($_GET['errno']) ? (int)$_GET['errno'] : 0; // 2 = no Zlib // 3 = custom version detected @@ -292,5 +296,5 @@ elseif ($page == 'error') { // 9 = checksum mismatch // 10 = (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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.34 + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ const AREA = 'admin'; require __DIR__ . '/lib/init.php'; +use Froxlor\Config\ConfigParser; +use Froxlor\FileDir; +use Froxlor\Froxlor; use Froxlor\Settings; use Froxlor\UI\Panel\UI; use Froxlor\UI\Request; +use Froxlor\UI\Response; if ($userinfo['change_serversettings'] == '1') { - if ($action == 'setconfigured') { Settings::Set('panel.is_configured', '1', true); - \Froxlor\UI\Response::redirectTo('admin_configfiles.php'); + Response::redirectTo('admin_configfiles.php'); } // get distro from URL param @@ -36,15 +46,15 @@ if ($userinfo['change_serversettings'] == '1') { $distributions_select = []; $services = []; - $config_dir = \Froxlor\FileDir::makeCorrectDir(\Froxlor\Froxlor::getInstallDir() . '/lib/configfiles/'); + $config_dir = FileDir::makeCorrectDir(Froxlor::getInstallDir() . '/lib/configfiles/'); if (!empty($distribution)) { if (!file_exists($config_dir . '/' . $distribution . ".xml")) { - \Froxlor\UI\Response::dynamic_error("Unknown distribution"); + Response::dynamicError("Unknown distribution"); } // create configparser object - $configfiles = new \Froxlor\Config\ConfigParser($config_dir . '/' . $distribution . ".xml"); + $configfiles = new ConfigParser($config_dir . '/' . $distribution . ".xml"); // get distro-info $dist_display = $configfiles->getCompleteDistroName(); @@ -52,13 +62,12 @@ if ($userinfo['change_serversettings'] == '1') { // get all the services from the distro $services = $configfiles->getServices(); } else { - // show list of available distro's $distros = glob($config_dir . '*.xml'); // read in all the distros foreach ($distros as $_distribution) { // get configparser object - $dist = new \Froxlor\Config\ConfigParser($_distribution); + $dist = new ConfigParser($_distribution); // store in tmp array $distributions_select[str_replace(".xml", "", strtolower(basename($_distribution)))] = $dist->getCompleteDistroName(); } @@ -68,7 +77,6 @@ if ($userinfo['change_serversettings'] == '1') { } if ($distribution != "" && isset($_POST['finish'])) { - unset($_POST['finish']); $params = $_POST; $params['distro'] = $distribution; @@ -77,19 +85,18 @@ if ($userinfo['change_serversettings'] == '1') { $params['system'][] = $sysdaemon; } $params_content = json_encode($params); - $params_filename = \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . 'install/' . \Froxlor\Froxlor::genSessionId() . '.json'); + $params_filename = FileDir::makeCorrectFile(Froxlor::getInstallDir() . 'install/' . Froxlor::genSessionId() . '.json'); file_put_contents($params_filename, $params_content); UI::twigBuffer('settings/configuration-final.html.twig', [ 'distribution' => $distribution, // alert 'type' => 'info', - 'alert_msg' => $lng['admin']['configfiles']['finishnote'], - 'basedir' => \Froxlor\Froxlor::getInstallDir(), + 'alert_msg' => lng('admin.configfiles.finishnote'), + 'basedir' => Froxlor::getInstallDir(), 'params_filename' => $params_filename ]); } else { - if (!empty($distribution)) { // show available services to configure $fields = $services; @@ -104,46 +111,56 @@ if ($userinfo['change_serversettings'] == '1') { $cfg_formfield = [ 'config' => [ - 'title' => $lng['admin']['configfiles']['serverconfiguration'], + 'title' => lng('admin.configfiles.serverconfiguration'), 'image' => 'fa-solid fa-wrench', - 'description' => $lng['admin']['configfiles']['description'], + 'description' => lng('admin.configfiles.description'), 'sections' => [ 'section_config' => [ 'fields' => [ - 'distribution' => ['type' => 'select', 'select_var' => $distributions_select, 'label' => $lng['admin']['configfiles']['distribution']] + 'distribution' => [ + 'type' => 'select', + 'select_var' => $distributions_select, + 'label' => lng('admin.configfiles.distribution') + ] ] ] ], 'buttons' => [ [ 'class' => 'btn-outline-secondary', - 'label' => $lng['panel']['cancel'], + 'label' => lng('panel.cancel'), 'type' => 'reset' ], [ - 'label' => $lng['update']['proceed'] + 'label' => lng('update.proceed') ] ] ] ]; UI::twigBuffer('user/form-note.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'configfiles')), + 'formaction' => $linker->getLink(['section' => 'configfiles']), 'formdata' => $cfg_formfield['config'], - 'actions_links' => (int) Settings::Get('panel.is_configured') == 0 ? [[ - 'href' => $linker->getLink(['section' => 'configfiles', 'page' => 'overview', 'action' => 'setconfigured']), - 'label' => $lng['panel']['ihave_configured'], - 'class' => 'btn-outline-warning', - 'icon' => 'fa fa-circle-check' - ]] : [], + 'actions_links' => (int)Settings::Get('panel.is_configured') == 0 ? [ + [ + 'href' => $linker->getLink([ + 'section' => 'configfiles', + 'page' => 'overview', + 'action' => 'setconfigured' + ]), + 'label' => lng('panel.ihave_configured'), + 'class' => 'btn-outline-warning', + 'icon' => 'fa fa-circle-check' + ] + ] : [], // alert 'type' => 'warning', - 'alert_msg' => $lng['panel']['settings_before_configuration'] . ((int)Settings::Get('panel.is_configured') == 1 ? '

' . $lng['panel']['system_is_configured'] : '') + 'alert_msg' => lng('panel.settings_before_configuration') . ((int)Settings::Get('panel.is_configured') == 1 ? '

' . lng('panel.system_is_configured') : '') ]); } } UI::twigOutputBuffer(); } else { - \Froxlor\UI\Response::redirectTo('admin_index.php'); + Response::redirectTo('admin_index.php'); } diff --git a/admin_cronjobs.php b/admin_cronjobs.php index 2fa9aaa2..433a072a 100644 --- a/admin_cronjobs.php +++ b/admin_cronjobs.php @@ -4,43 +4,55 @@ * 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 (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ const AREA = 'admin'; require __DIR__ . '/lib/init.php'; use Froxlor\Api\Commands\Cronjobs; +use Froxlor\FroxlorLogger; +use Froxlor\UI\Collection; +use Froxlor\UI\Listing; use Froxlor\UI\Panel\UI; use Froxlor\UI\Request; +use Froxlor\UI\Response; -$id = (int) Request::get('id'); +$id = (int)Request::get('id'); if ($page == 'cronjobs' || $page == 'overview') { if ($action == '') { - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'viewed admin_cronjobs'); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'viewed admin_cronjobs'); try { $cron_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/admin/tablelisting.cronjobs.php'; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Cronjobs::class, $userinfo)) + $collection = (new Collection(Cronjobs::class, $userinfo)) ->withPagination($cron_list_data['cron_list']['columns']); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } UI::view('user/table-note.html.twig', [ - 'listing' => \Froxlor\UI\Listing::format($collection, $cron_list_data, 'cron_list') , + 'listing' => Listing::format($collection, $cron_list_data, 'cron_list'), // alert-box 'type' => 'warning', - 'alert_msg' => $lng['cron']['changewarning'] + 'alert_msg' => lng('cron.changewarning') ]); } elseif ($action == 'new') { /* @@ -48,11 +60,11 @@ if ($page == 'cronjobs' || $page == 'overview') { */ } elseif ($action == 'edit' && $id != 0) { try { - $json_result = Cronjobs::getLocal($userinfo, array( + $json_result = Cronjobs::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; if ($result['cronfile'] != '') { @@ -60,17 +72,16 @@ if ($page == 'cronjobs' || $page == 'overview') { try { Cronjobs::getLocal($userinfo, $_POST)->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - $cronjobs_edit_data = include_once dirname(__FILE__) . '/lib/formfields/admin/cronjobs/formfield.cronjobs_edit.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'cronjobs', 'id' => $id)), + 'formaction' => $linker->getLink(['section' => 'cronjobs', 'id' => $id]), 'formdata' => $cronjobs_edit_data['cronjobs_edit'], 'editid' => $id ]); diff --git a/admin_customers.php b/admin_customers.php index 7e3dae48..3a52c451 100644 --- a/admin_customers.php +++ b/admin_customers.php @@ -2,165 +2,179 @@ /** * 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 (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ const AREA = 'admin'; require __DIR__ . '/lib/init.php'; +use Froxlor\Api\Commands\Admins; use Froxlor\Api\Commands\Customers as Customers; +use Froxlor\CurrentUser; use Froxlor\Database\Database; +use Froxlor\Froxlor; +use Froxlor\FroxlorLogger; +use Froxlor\PhpHelper; use Froxlor\Settings; +use Froxlor\UI\Collection; +use Froxlor\UI\HTML; +use Froxlor\UI\Listing; use Froxlor\UI\Panel\UI; use Froxlor\UI\Request; +use Froxlor\UI\Response; -$id = (int) Request::get('id'); +$id = (int)Request::get('id'); if ($page == 'customers' && $userinfo['customers'] != '0') { if ($action == '') { - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_customers"); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_customers"); try { $customer_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/admin/tablelisting.customers.php'; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Customers::class, $userinfo, ['show_usages' => true])) + $collection = (new Collection(Customers::class, $userinfo, ['show_usages' => true])) ->withPagination($customer_list_data['customer_list']['columns']); if ($userinfo['change_serversettings']) { - $collection->has('admin', \Froxlor\Api\Commands\Admins::class, 'adminid', 'adminid'); + $collection->has('admin', Admins::class, 'adminid', 'adminid'); } } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $actions_links = false; if ($userinfo['customers_used'] < $userinfo['customers'] || $userinfo['customers'] == '-1') { - $actions_links = [[ - 'href' => $linker->getLink(['section' => 'customers', 'page' => $page, 'action' => 'add']), - 'label' => $lng['admin']['customer_add'] - ]]; + $actions_links = [ + [ + 'href' => $linker->getLink(['section' => 'customers', 'page' => $page, 'action' => 'add']), + 'label' => lng('admin.customer_add') + ] + ]; } UI::view('user/table.html.twig', [ - 'listing' => \Froxlor\UI\Listing::format($collection, $customer_list_data, 'customer_list') , + 'listing' => Listing::format($collection, $customer_list_data, 'customer_list'), 'actions_links' => $actions_links ]); } elseif ($action == 'su' && $id != 0) { try { - $json_result = Customers::getLocal($userinfo, array( + $json_result = Customers::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; $destination_user = $result['loginname']; if ($destination_user != '') { - if ($result['deactivated'] == '1') { - \Froxlor\UI\Response::standard_error("usercurrentlydeactivated", $destination_user); + Response::standardError("usercurrentlydeactivated", $destination_user); } - $result['switched_user'] = \Froxlor\CurrentUser::getData(); + $result['switched_user'] = CurrentUser::getData(); $result['adminsession'] = 0; $result['userid'] = $result['customerid']; - \Froxlor\CurrentUser::setData($result); + CurrentUser::setData($result); - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "switched user and is now '" . $destination_user . "'"); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "switched user and is now '" . $destination_user . "'"); $target = (isset($_GET['target']) ? $_GET['target'] : 'index'); $redirect = "customer_" . $target . ".php"; - if (!file_exists(\Froxlor\Froxlor::getInstallDir() . "/" . $redirect)) { + if (!file_exists(Froxlor::getInstallDir() . "/" . $redirect)) { $redirect = "customer_index.php"; } - \Froxlor\UI\Response::redirectTo($redirect, null, true); + Response::redirectTo($redirect, null, true); } else { - \Froxlor\UI\Response::redirectTo('index.php', array( + Response::redirectTo('index.php', [ 'action' => 'login' - )); + ]); } } elseif ($action == 'unlock' && $id != 0) { try { - $json_result = Customers::getLocal($userinfo, array( + $json_result = Customers::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; if (isset($_POST['send']) && $_POST['send'] == 'send') { try { - $json_result = Customers::getLocal($userinfo, array( + $json_result = Customers::getLocal($userinfo, [ 'id' => $id - ))->unlock(); + ])->unlock(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - \Froxlor\UI\HTML::askYesNo('customer_reallyunlock', $filename, array( + HTML::askYesNo('customer_reallyunlock', $filename, [ 'id' => $id, 'page' => $page, 'action' => $action - ), $result['loginname']); + ], $result['loginname']); } } elseif ($action == 'delete' && $id != 0) { try { - $json_result = Customers::getLocal($userinfo, array( + $json_result = Customers::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; if (isset($_POST['send']) && $_POST['send'] == 'send') { try { - $json_result = Customers::getLocal($userinfo, array( + $json_result = Customers::getLocal($userinfo, [ 'id' => $id, - 'delete_userfiles' => (isset($_POST['delete_userfiles']) ? (int) $_POST['delete_userfiles'] : 0) - ))->delete(); + 'delete_userfiles' => (isset($_POST['delete_userfiles']) ? (int)$_POST['delete_userfiles'] : 0) + ])->delete(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - \Froxlor\UI\HTML::askYesNoWithCheckbox('admin_customer_reallydelete', 'admin_customer_alsoremovefiles', $filename, array( + HTML::askYesNoWithCheckbox('admin_customer_reallydelete', 'admin_customer_alsoremovefiles', $filename, [ 'id' => $id, 'page' => $page, 'action' => $action - ), $result['loginname']); + ], $result['loginname']); } } elseif ($action == 'add') { - if (isset($_POST['send']) && $_POST['send'] == 'send') { try { Customers::getLocal($userinfo, $_POST)->add(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - $phpconfigs = []; $configs = Database::query(" SELECT c.*, fc.description as interpreter @@ -168,16 +182,16 @@ if ($page == 'customers' && $userinfo['customers'] != '0') { LEFT JOIN `" . TABLE_PANEL_FPMDAEMONS . "` fc ON fc.id = c.fpmsettingid "); while ($row = $configs->fetch(PDO::FETCH_ASSOC)) { - if ((int) Settings::Get('phpfpm.enabled') == 1) { - $phpconfigs[] = array( + if ((int)Settings::Get('phpfpm.enabled') == 1) { + $phpconfigs[] = [ 'label' => $row['description'] . " [" . $row['interpreter'] . "]", 'value' => $row['id'] - ); + ]; } else { - $phpconfigs[] = array( + $phpconfigs[] = [ 'label' => $row['description'], 'value' => $row['id'] - ); + ]; } } @@ -198,40 +212,37 @@ if ($page == 'customers' && $userinfo['customers'] != '0') { $customer_add_data = include_once dirname(__FILE__) . '/lib/formfields/admin/customer/formfield.customer_add.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'customers')), + 'formaction' => $linker->getLink(['section' => 'customers']), 'formdata' => $customer_add_data['customer_add'] ]); } } elseif ($action == 'edit' && $id != 0) { - try { - $json_result = Customers::getLocal($userinfo, array( + $json_result = Customers::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; if ($result['loginname'] != '') { - if (isset($_POST['send']) && $_POST['send'] == 'send') { try { Customers::getLocal($userinfo, $_POST)->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - $dec_places = Settings::Get('panel.decimal_places'); $result['traffic'] = round($result['traffic'] / (1024 * 1024), $dec_places); $result['diskspace'] = round($result['diskspace'] / 1024, $dec_places); $result['email'] = $idna_convert->decode($result['email']); - $result = \Froxlor\PhpHelper::htmlentitiesArray($result); + $result = PhpHelper::htmlentitiesArray($result); $phpconfigs = []; $configs = Database::query(" @@ -240,16 +251,16 @@ if ($page == 'customers' && $userinfo['customers'] != '0') { LEFT JOIN `" . TABLE_PANEL_FPMDAEMONS . "` fc ON fc.id = c.fpmsettingid "); while ($row = $configs->fetch(PDO::FETCH_ASSOC)) { - if ((int) Settings::Get('phpfpm.enabled') == 1) { - $phpconfigs[] = array( + if ((int)Settings::Get('phpfpm.enabled') == 1) { + $phpconfigs[] = [ 'label' => $row['description'] . " [" . $row['interpreter'] . "]", 'value' => $row['id'] - ); + ]; } else { - $phpconfigs[] = array( + $phpconfigs[] = [ 'label' => $row['description'], 'value' => $row['id'] - ); + ]; } } @@ -282,7 +293,7 @@ if ($page == 'customers' && $userinfo['customers'] != '0') { $customer_edit_data = include_once dirname(__FILE__) . '/lib/formfields/admin/customer/formfield.customer_edit.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'customers', 'id' => $id)), + 'formaction' => $linker->getLink(['section' => 'customers', 'id' => $id]), 'formdata' => $customer_edit_data['customer_edit'], 'editid' => $id ]); diff --git a/admin_domains.php b/admin_domains.php index b5e5cb47..9ff1633b 100644 --- a/admin_domains.php +++ b/admin_domains.php @@ -2,19 +2,25 @@ /** * 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 (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ const AREA = 'admin'; @@ -22,25 +28,38 @@ require __DIR__ . '/lib/init.php'; use Froxlor\Api\Commands\Customers as Customers; use Froxlor\Api\Commands\Domains as Domains; +use Froxlor\Bulk\DomainBulkAction; +use Froxlor\Cron\TaskId; +use Froxlor\Customer\Customer; use Froxlor\Database\Database; +use Froxlor\Domain\Domain; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; use Froxlor\Settings; +use Froxlor\System\Cronjob; +use Froxlor\UI\Collection; +use Froxlor\UI\HTML; +use Froxlor\UI\Listing; use Froxlor\UI\Panel\UI; use Froxlor\UI\Request; +use Froxlor\UI\Response; +use Froxlor\User; +use Froxlor\Validate\Validate; -$id = (int) Request::get('id'); +$id = (int)Request::get('id'); if ($page == 'domains' || $page == 'overview') { if ($action == '') { - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_domains"); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_domains"); try { $domain_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/admin/tablelisting.domains.php'; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Domains::class, $userinfo)) - ->has('customer', \Froxlor\Api\Commands\Customers::class, 'customerid', 'customerid') + $collection = (new Collection(Domains::class, $userinfo)) + ->has('customer', Customers::class, 'customerid', 'customerid') ->withPagination($domain_list_data['domain_list']['columns']); - $customerCollection = (new \Froxlor\UI\Collection(Customers::class, $userinfo)); + $customerCollection = (new Collection(Customers::class, $userinfo)); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $actions_links = false; @@ -48,105 +67,99 @@ if ($page == 'domains' || $page == 'overview') { $actions_links = []; $actions_links[] = [ 'href' => $linker->getLink(['section' => 'domains', 'page' => $page, 'action' => 'add']), - 'label' => $lng['admin']['domain_add'] + 'label' => lng('admin.domain_add') ]; $actions_links[] = [ 'href' => $linker->getLink(['section' => 'domains', 'page' => $page, 'action' => 'import']), - 'label' => $lng['domains']['domain_import'], + 'label' => lng('domains.domain_import'), 'icon' => 'fa-solid fa-file-import', 'class' => 'btn-secondary' ]; } UI::view('user/table.html.twig', [ - 'listing' => \Froxlor\UI\Listing::format($collection, $domain_list_data, 'domain_list') , + 'listing' => Listing::format($collection, $domain_list_data, 'domain_list'), 'actions_links' => $actions_links ]); } elseif ($action == 'delete' && $id != 0) { - try { - $json_result = Domains::getLocal($userinfo, array( + $json_result = Domains::getLocal($userinfo, [ 'id' => $id, 'no_std_subdomain' => true - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; $alias_check_stmt = Database::prepare(" SELECT COUNT(`id`) AS `count` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `aliasdomain`= :id"); - $alias_check = Database::pexecute_first($alias_check_stmt, array( + $alias_check = Database::pexecute_first($alias_check_stmt, [ 'id' => $id - )); + ]); if ($result['domain'] != '') { if (isset($_POST['send']) && $_POST['send'] == 'send' && $alias_check['count'] == 0) { - try { Domains::getLocal($userinfo, $_POST)->delete(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } elseif ($alias_check['count'] > 0) { - \Froxlor\UI\Response::standard_error('domains_cantdeletedomainwithaliases'); + Response::standardError('domains_cantdeletedomainwithaliases'); } else { - $showcheck = false; - if (\Froxlor\Domain\Domain::domainHasMainSubDomains($id)) { + if (Domain::domainHasMainSubDomains($id)) { $showcheck = true; } - \Froxlor\UI\HTML::askYesNoWithCheckbox('admin_domain_reallydelete', 'remove_subbutmain_domains', $filename, array( + HTML::askYesNoWithCheckbox('admin_domain_reallydelete', 'remove_subbutmain_domains', $filename, [ 'id' => $id, 'page' => $page, 'action' => $action - ), $idna_convert->decode($result['domain']), $showcheck); + ], $idna_convert->decode($result['domain']), $showcheck); } } } elseif ($action == 'add') { - if (isset($_POST['send']) && $_POST['send'] == 'send') { try { Domains::getLocal($userinfo, $_POST)->add(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - $customers = [ - 0 => $lng['panel']['please_choose'] + 0 => lng('panel.please_choose') ]; $result_customers_stmt = Database::prepare(" SELECT `customerid`, `loginname`, `name`, `firstname`, `company` - FROM `" . TABLE_PANEL_CUSTOMERS . "` " . ($userinfo['customers_see_all'] ? '' : " WHERE `adminid` = '" . (int) $userinfo['adminid'] . "' ") . " ORDER BY COALESCE(NULLIF(`name`,''), `company`) ASC"); - $params = array(); + FROM `" . TABLE_PANEL_CUSTOMERS . "` " . ($userinfo['customers_see_all'] ? '' : " WHERE `adminid` = '" . (int)$userinfo['adminid'] . "' ") . " ORDER BY COALESCE(NULLIF(`name`,''), `company`) ASC"); + $params = []; if ($userinfo['customers_see_all'] == '0') { $params['adminid'] = $userinfo['adminid']; } Database::pexecute($result_customers_stmt, $params); while ($row_customer = $result_customers_stmt->fetch(PDO::FETCH_ASSOC)) { - $customers[$row_customer['customerid']] = \Froxlor\User::getCorrectFullUserDetails($row_customer) . ' (' . $row_customer['loginname'] . ')'; + $customers[$row_customer['customerid']] = User::getCorrectFullUserDetails($row_customer) . ' (' . $row_customer['loginname'] . ')'; } $admins = []; if ($userinfo['customers_see_all'] == '1') { - $result_admins_stmt = Database::query(" SELECT `adminid`, `loginname`, `name` FROM `" . TABLE_PANEL_ADMINS . "` WHERE `domains_used` < `domains` OR `domains` = '-1' ORDER BY `name` ASC"); while ($row_admin = $result_admins_stmt->fetch(PDO::FETCH_ASSOC)) { - $admins[$row_admin['adminid']] = \Froxlor\User::getCorrectFullUserDetails($row_admin) . ' (' . $row_admin['loginname'] . ')'; + $admins[$row_admin['adminid']] = User::getCorrectFullUserDetails($row_admin) . ' (' . $row_admin['loginname'] . ')'; } } @@ -161,50 +174,48 @@ if ($page == 'domains' || $page == 'overview') { $admin_ip_stmt = Database::prepare(" SELECT `id`, `ip`, `port` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `id` = :ipid ORDER BY `ip`, `port` ASC "); - $admin_ip = Database::pexecute_first($admin_ip_stmt, array( + $admin_ip = Database::pexecute_first($admin_ip_stmt, [ 'ipid' => $userinfo['ip'] - )); + ]); $result_ipsandports_stmt = Database::prepare(" SELECT `id`, `ip`, `port` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `ssl`='0' AND `ip` = :ipid ORDER BY `ip`, `port` ASC "); - Database::pexecute($result_ipsandports_stmt, array( + Database::pexecute($result_ipsandports_stmt, [ 'ipid' => $admin_ip['ip'] - )); + ]); $result_ssl_ipsandports_stmt = Database::prepare(" SELECT `id`, `ip`, `port` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `ssl`='1' AND `ip` = :ipid ORDER BY `ip`, `port` ASC "); - Database::pexecute($result_ssl_ipsandports_stmt, array( + Database::pexecute($result_ssl_ipsandports_stmt, [ 'ipid' => $admin_ip['ip'] - )); + ]); } // Build array holding all IPs and Ports available to this admin $ipsandports = []; while ($row_ipandport = $result_ipsandports_stmt->fetch(PDO::FETCH_ASSOC)) { - if (filter_var($row_ipandport['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { $row_ipandport['ip'] = '[' . $row_ipandport['ip'] . ']'; } - $ipsandports[] = array( + $ipsandports[] = [ 'label' => $row_ipandport['ip'] . ':' . $row_ipandport['port'], 'value' => $row_ipandport['id'] - ); + ]; } $ssl_ipsandports = []; while ($row_ssl_ipandport = $result_ssl_ipsandports_stmt->fetch(PDO::FETCH_ASSOC)) { - if (filter_var($row_ssl_ipandport['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { $row_ssl_ipandport['ip'] = '[' . $row_ssl_ipandport['ip'] . ']'; } - $ssl_ipsandports[] = array( + $ssl_ipsandports[] = [ 'label' => $row_ssl_ipandport['ip'] . ':' . $row_ssl_ipandport['port'], 'value' => $row_ssl_ipandport['id'] - ); + ]; } $standardsubdomains = []; @@ -223,14 +234,14 @@ if ($page == 'domains' || $page == 'overview') { } $domains = [ - 0 => $lng['domains']['noaliasdomain'] + 0 => lng('domains.noaliasdomain') ]; $result_domains_stmt = Database::prepare(" SELECT `d`.`id`, `d`.`domain`, `c`.`loginname` FROM `" . TABLE_PANEL_DOMAINS . "` `d`, `" . TABLE_PANEL_CUSTOMERS . "` `c` WHERE `d`.`aliasdomain` IS NULL AND `d`.`parentdomainid` = 0" . $standardsubdomains . ($userinfo['customers_see_all'] ? '' : " AND `d`.`adminid` = :adminid") . " AND `d`.`customerid`=`c`.`customerid` ORDER BY `loginname`, `domain` ASC "); - $params = array(); + $params = []; if ($userinfo['customers_see_all'] == '0') { $params['adminid'] = $userinfo['adminid']; } @@ -241,7 +252,7 @@ if ($page == 'domains' || $page == 'overview') { } $subtodomains = [ - 0 => $lng['domains']['nosubtomaindomain'] + 0 => lng('domains.nosubtomaindomain') ]; $result_domains_stmt = Database::prepare(" SELECT `d`.`id`, `d`.`domain`, `c`.`loginname` FROM `" . TABLE_PANEL_DOMAINS . "` `d`, `" . TABLE_PANEL_CUSTOMERS . "` `c` @@ -263,7 +274,7 @@ if ($page == 'domains' || $page == 'overview') { "); while ($row = $configs->fetch(PDO::FETCH_ASSOC)) { - if ((int) Settings::Get('phpfpm.enabled') == 1) { + if ((int)Settings::Get('phpfpm.enabled') == 1) { $phpconfigs[$row['id']] = $row['description'] . " [" . $row['interpreter'] . "]"; } else { $phpconfigs[$row['id']] = $row['description']; @@ -272,74 +283,70 @@ if ($page == 'domains' || $page == 'overview') { // create serveralias options $serveraliasoptions = [ - 0 => $lng['domains']['serveraliasoption_wildcard'], - 1 => $lng['domains']['serveraliasoption_www'], - 2 => $lng['domains']['serveraliasoption_none'] + 0 => lng('domains.serveraliasoption_wildcard'), + 1 => lng('domains.serveraliasoption_www'), + 2 => lng('domains.serveraliasoption_none') ]; $subcanemaildomain = [ - 0 => $lng['admin']['subcanemaildomain']['never'], - 1 => $lng['admin']['subcanemaildomain']['choosableno'], - 2 => $lng['admin']['subcanemaildomain']['choosableyes'], - 3 => $lng['admin']['subcanemaildomain']['always'] + 0 => lng('admin.subcanemaildomain.never'), + 1 => lng('admin.subcanemaildomain.choosableno'), + 2 => lng('admin.subcanemaildomain.choosableyes'), + 3 => lng('admin.subcanemaildomain.always') ]; $domain_add_data = include_once dirname(__FILE__) . '/lib/formfields/admin/domains/formfield.domains_add.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'domains')), + 'formaction' => $linker->getLink(['section' => 'domains']), 'formdata' => $domain_add_data['domain_add'] ]); } } elseif ($action == 'edit' && $id != 0) { - try { - $json_result = Domains::getLocal($userinfo, array( + $json_result = Domains::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; if ($result['domain'] != '') { - $subdomains_stmt = Database::prepare(" SELECT COUNT(`id`) AS count FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `parentdomainid` = :resultid "); - $subdomains = Database::pexecute_first($subdomains_stmt, array( + $subdomains = Database::pexecute_first($subdomains_stmt, [ 'resultid' => $result['id'] - )); + ]); $subdomains = $subdomains['count']; $alias_check_stmt = Database::prepare(" SELECT COUNT(`id`) AS count FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `aliasdomain` = :resultid "); - $alias_check = Database::pexecute_first($alias_check_stmt, array( + $alias_check = Database::pexecute_first($alias_check_stmt, [ 'resultid' => $result['id'] - )); + ]); $alias_check = $alias_check['count']; $domain_emails_result_stmt = Database::prepare(" SELECT `email`, `email_full`, `destination`, `popaccountid` AS `number_email_forwarders` FROM `" . TABLE_MAIL_VIRTUAL . "` WHERE `customerid` = :customerid AND `domainid` = :id "); - Database::pexecute($domain_emails_result_stmt, array( + Database::pexecute($domain_emails_result_stmt, [ 'customerid' => $result['customerid'], 'id' => $result['id'] - )); + ]); $emails = Database::num_rows(); $email_forwarders = 0; $email_accounts = 0; while ($domain_emails_row = $domain_emails_result_stmt->fetch(PDO::FETCH_ASSOC)) { - if ($domain_emails_row['destination'] != '') { - - $domain_emails_row['destination'] = explode(' ', \Froxlor\FileDir::makeCorrectDestination($domain_emails_row['destination'])); + $domain_emails_row['destination'] = explode(' ', FileDir::makeCorrectDestination($domain_emails_row['destination'])); $email_forwarders += count($domain_emails_row['destination']); if (in_array($domain_emails_row['email_full'], $domain_emails_row['destination'])) { @@ -352,11 +359,11 @@ if ($page == 'domains' || $page == 'overview') { $ipsresult_stmt = Database::prepare(" SELECT `id_ipandports` FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :id "); - Database::pexecute($ipsresult_stmt, array( + Database::pexecute($ipsresult_stmt, [ 'id' => $result['id'] - )); + ]); - $usedips = array(); + $usedips = []; while ($ipsresultrow = $ipsresult_stmt->fetch(PDO::FETCH_ASSOC)) { $usedips[] = $ipsresultrow['id_ipandports']; } @@ -369,13 +376,12 @@ if ($page == 'domains' || $page == 'overview') { } Domains::getLocal($userinfo, $_POST)->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - if (Settings::Get('panel.allow_domain_change_customer') == '1') { $customers = []; $result_customers_stmt = Database::prepare(" @@ -386,60 +392,59 @@ if ($page == 'domains' || $page == 'overview') { AND (`email_accounts_used` + :accounts <= `email_accounts` OR `email_accounts` = '-1' ) " . ($userinfo['customers_see_all'] ? '' : " AND `adminid` = :adminid ") . ") OR `customerid` = :customerid ORDER BY `name` ASC "); - $params = array( + $params = [ 'subdomains' => $subdomains, 'emails' => $emails, 'forwarders' => $email_forwarders, 'accounts' => $email_accounts, 'customerid' => $result['customerid'] - ); + ]; if ($userinfo['customers_see_all'] == '0') { $params['adminid'] = $userinfo['adminid']; } Database::pexecute($result_customers_stmt, $params); while ($row_customer = $result_customers_stmt->fetch(PDO::FETCH_ASSOC)) { - $customers[$row_customer['customerid']] = \Froxlor\User::getCorrectFullUserDetails($row_customer) . ' (' . $row_customer['loginname'] . ')'; + $customers[$row_customer['customerid']] = User::getCorrectFullUserDetails($row_customer) . ' (' . $row_customer['loginname'] . ')'; } } else { $customer_stmt = Database::prepare(" SELECT `customerid`, `loginname`, `name`, `firstname`, `company` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `customerid` = :customerid "); - $customer = Database::pexecute_first($customer_stmt, array( + $customer = Database::pexecute_first($customer_stmt, [ 'customerid' => $result['customerid'] - )); - $result['customername'] = \Froxlor\User::getCorrectFullUserDetails($customer); + ]); + $result['customername'] = User::getCorrectFullUserDetails($customer); } if ($userinfo['customers_see_all'] == '1') { if (Settings::Get('panel.allow_domain_change_admin') == '1') { - $admins = []; $result_admins_stmt = Database::prepare(" SELECT `adminid`, `loginname`, `name` FROM `" . TABLE_PANEL_ADMINS . "` WHERE (`domains_used` < `domains` OR `domains` = '-1') OR `adminid` = :adminid ORDER BY `name` ASC "); - Database::pexecute($result_admins_stmt, array( + Database::pexecute($result_admins_stmt, [ 'adminid' => $result['adminid'] - )); + ]); while ($row_admin = $result_admins_stmt->fetch(PDO::FETCH_ASSOC)) { - $admins[$row_admin['adminid']] = \Froxlor\User::getCorrectFullUserDetails($row_admin) . ' (' . $row_admin['loginname'] . ')'; + $admins[$row_admin['adminid']] = User::getCorrectFullUserDetails($row_admin) . ' (' . $row_admin['loginname'] . ')'; } } else { $admin_stmt = Database::prepare(" SELECT `adminid`, `loginname`, `name` FROM `" . TABLE_PANEL_ADMINS . "` WHERE `adminid` = :adminid "); - $admin = Database::pexecute_first($admin_stmt, array( + $admin = Database::pexecute_first($admin_stmt, [ 'adminid' => $result['adminid'] - )); - $result['adminname'] = \Froxlor\User::getCorrectFullUserDetails($admin) . ' (' . $admin['loginname'] . ')'; + ]); + $result['adminname'] = User::getCorrectFullUserDetails($admin) . ' (' . $admin['loginname'] . ')'; } } $domains = [ - 0 => $lng['domains']['noaliasdomain'] + 0 => lng('domains.noaliasdomain') ]; $result_domains_stmt = Database::prepare(" @@ -448,17 +453,17 @@ if ($page == 'domains' || $page == 'overview') { AND `c`.`standardsubdomain`<>`d`.`id` AND `d`.`customerid` = :customerid AND `c`.`customerid`=`d`.`customerid` ORDER BY `d`.`domain` ASC "); - Database::pexecute($result_domains_stmt, array( + Database::pexecute($result_domains_stmt, [ 'id' => $result['id'], 'customerid' => $result['customerid'] - )); + ]); while ($row_domain = $result_domains_stmt->fetch(PDO::FETCH_ASSOC)) { $domains[$row_domain['id']] = $idna_convert->decode($row_domain['domain']); } $subtodomains = [ - 0 => $lng['domains']['nosubtomaindomain'] + 0 => lng('domains.nosubtomaindomain') ]; $result_domains_stmt = Database::prepare(" SELECT `d`.`id`, `d`.`domain` FROM `" . TABLE_PANEL_DOMAINS . "` `d`, `" . TABLE_PANEL_CUSTOMERS . "` `c` @@ -466,9 +471,9 @@ if ($page == 'domains' || $page == 'overview') { AND `c`.`standardsubdomain`<>`d`.`id` AND `c`.`customerid`=`d`.`customerid`" . ($userinfo['customers_see_all'] ? '' : " AND `d`.`adminid` = :adminid") . " ORDER BY `d`.`domain` ASC "); - $params = array( + $params = [ 'id' => $result['id'] - ); + ]; if ($userinfo['customers_see_all'] == '0') { $params['adminid'] = $userinfo['adminid']; } @@ -489,23 +494,23 @@ if ($page == 'domains' || $page == 'overview') { $admin_ip_stmt = Database::prepare(" SELECT `id`, `ip`, `port` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `id` = :ipid ORDER BY `ip`, `port` ASC "); - $admin_ip = Database::pexecute_first($admin_ip_stmt, array( + $admin_ip = Database::pexecute_first($admin_ip_stmt, [ 'ipid' => $userinfo['ip'] - )); + ]); $result_ipsandports_stmt = Database::prepare(" SELECT `id`, `ip`, `port` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `ssl`='0' AND `ip` = :ipid ORDER BY `ip`, `port` ASC "); - Database::pexecute($result_ipsandports_stmt, array( + Database::pexecute($result_ipsandports_stmt, [ 'ipid' => $admin_ip['ip'] - )); + ]); $result_ssl_ipsandports_stmt = Database::prepare(" SELECT `id`, `ip`, `port` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `ssl`='1' AND `ip` = :ipid ORDER BY `ip`, `port` ASC "); - Database::pexecute($result_ssl_ipsandports_stmt, array( + Database::pexecute($result_ssl_ipsandports_stmt, [ 'ipid' => $admin_ip['ip'] - )); + ]); } $ipsandports = []; @@ -513,10 +518,10 @@ if ($page == 'domains' || $page == 'overview') { if (filter_var($row_ipandport['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { $row_ipandport['ip'] = '[' . $row_ipandport['ip'] . ']'; } - $ipsandports[] = array( + $ipsandports[] = [ 'label' => $row_ipandport['ip'] . ':' . $row_ipandport['port'], 'value' => $row_ipandport['id'] - ); + ]; } $ssl_ipsandports = []; @@ -524,10 +529,10 @@ if ($page == 'domains' || $page == 'overview') { if (filter_var($row_ssl_ipandport['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { $row_ssl_ipandport['ip'] = '[' . $row_ssl_ipandport['ip'] . ']'; } - $ssl_ipsandports[] = array( + $ssl_ipsandports[] = [ 'label' => $row_ssl_ipandport['ip'] . ':' . $row_ssl_ipandport['port'], 'value' => $row_ssl_ipandport['id'] - ); + ]; } // check that letsencrypt is not activated for wildcard domain @@ -540,16 +545,16 @@ if ($page == 'domains' || $page == 'overview') { $result['ssl_redirect'] = ($result['ssl_redirect'] == 0 ? 0 : 1); $serveraliasoptions = [ - 0 => $lng['domains']['serveraliasoption_wildcard'], - 1 => $lng['domains']['serveraliasoption_www'], - 2 => $lng['domains']['serveraliasoption_none'] + 0 => lng('domains.serveraliasoption_wildcard'), + 1 => lng('domains.serveraliasoption_www'), + 2 => lng('domains.serveraliasoption_none') ]; $subcanemaildomain = [ - 0 => $lng['admin']['subcanemaildomain']['never'], - 1 => $lng['admin']['subcanemaildomain']['choosableno'], - 2 => $lng['admin']['subcanemaildomain']['choosableyes'], - 3 => $lng['admin']['subcanemaildomain']['always'] + 0 => lng('admin.subcanemaildomain.never'), + 1 => lng('admin.subcanemaildomain.choosableno'), + 2 => lng('admin.subcanemaildomain.choosableyes'), + 3 => lng('admin.subcanemaildomain.always') ]; $phpconfigs = []; @@ -558,17 +563,17 @@ if ($page == 'domains' || $page == 'overview') { FROM `" . TABLE_PANEL_PHPCONFIGS . "` c LEFT JOIN `" . TABLE_PANEL_FPMDAEMONS . "` fc ON fc.id = c.fpmsettingid "); - $c_allowed_configs = \Froxlor\Customer\Customer::getCustomerDetail($result['customerid'], 'allowed_phpconfigs'); + $c_allowed_configs = Customer::getCustomerDetail($result['customerid'], 'allowed_phpconfigs'); if (!empty($c_allowed_configs)) { $c_allowed_configs = json_decode($c_allowed_configs, true); } else { - $c_allowed_configs = array(); + $c_allowed_configs = []; } while ($phpconfigs_row = $phpconfigs_result_stmt->fetch(PDO::FETCH_ASSOC)) { $disabled = !empty($c_allowed_configs) && !in_array($phpconfigs_row['id'], $c_allowed_configs); if (!$disabled) { - if ((int) Settings::Get('phpfpm.enabled') == 1) { + if ((int)Settings::Get('phpfpm.enabled') == 1) { $phpconfigs[$phpconfigs_row['id']] = $phpconfigs_row['description'] . " [" . $phpconfigs_row['interpreter'] . "]"; } else { $phpconfigs[$phpconfigs_row['id']] = $phpconfigs_row['description']; @@ -577,100 +582,94 @@ if ($page == 'domains' || $page == 'overview') { } if (Settings::Get('panel.allow_domain_change_customer') != '1') { - $result['customername'] .= ' (' . $customer['loginname'] . ')'; + $result['customername'] .= ' (' . $customer['loginname'] . ')'; } $domain_edit_data = include_once dirname(__FILE__) . '/lib/formfields/admin/domains/formfield.domains_edit.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'domains', 'id' => $id)), + 'formaction' => $linker->getLink(['section' => 'domains', 'id' => $id]), 'formdata' => $domain_edit_data['domain_edit'], 'editid' => $id ]); } } } elseif ($action == 'jqGetCustomerPHPConfigs') { - $customerid = intval($_POST['customerid']); - $allowed_phpconfigs = \Froxlor\Customer\Customer::getCustomerDetail($customerid, 'allowed_phpconfigs'); + $allowed_phpconfigs = Customer::getCustomerDetail($customerid, 'allowed_phpconfigs'); echo !empty($allowed_phpconfigs) ? $allowed_phpconfigs : json_encode([]); exit(); } elseif ($action == 'jqSpeciallogfileNote') { $domainid = intval($_POST['id']); $newval = intval($_POST['newval']); try { - $json_result = Domains::getLocal($userinfo, array( + $json_result = Domains::getLocal($userinfo, [ 'id' => $domainid - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; if ($newval != $result['speciallogfile']) { - echo json_encode(['changed' => true, 'info' => $lng['admin']['speciallogwarning']]); + echo json_encode(['changed' => true, 'info' => lng('admin.speciallogwarning')]); exit(); } echo 0; exit(); } elseif ($action == 'import') { - if (isset($_POST['send']) && $_POST['send'] == 'send') { - - $separator = \Froxlor\Validate\Validate::validate($_POST['separator'], 'separator'); - $offset = (int) \Froxlor\Validate\Validate::validate($_POST['offset'], 'offset', "/[0-9]/i"); + $separator = Validate::validate($_POST['separator'], 'separator'); + $offset = (int)Validate::validate($_POST['offset'], 'offset', "/[0-9]/i"); $file_name = $_FILES['file']['tmp_name']; - $result = array(); + $result = []; try { - $bulk = new \Froxlor\Bulk\DomainBulkAction($file_name, $userinfo); + $bulk = new DomainBulkAction($file_name, $userinfo); $result = $bulk->doImport($separator, $offset); } catch (Exception $e) { - \Froxlor\UI\Response::standard_error('domain_import_error', $e->getMessage()); + Response::standardError('domain_import_error', $e->getMessage()); } if (!empty($bulk->getErrors())) { - \Froxlor\UI\Response::dynamic_error(implode("
", $bulk->getErrors())); + Response::dynamicError(implode("
", $bulk->getErrors())); } // update customer/admin counters - \Froxlor\User::updateCounters(false); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); + User::updateCounters(false); + Cronjob::inserttask(TaskId::REBUILD_VHOST); + Cronjob::inserttask(TaskId::REBUILD_DNS); $result_str = $result['imported'] . ' / ' . $result['all'] . (!empty($result['note']) ? ' (' . $result['note'] . ')' : ''); - \Froxlor\UI\Response::standard_success('domain_import_successfully', $result_str, array( + Response::standardSuccess('domain_import_successfully', $result_str, [ 'filename' => $filename, 'action' => '', 'page' => 'domains' - )); + ]); } else { - $domain_import_data = include_once dirname(__FILE__) . '/lib/formfields/admin/domains/formfield.domains_import.php'; UI::view('user/form-note.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'domains', 'page' => $page)), + 'formaction' => $linker->getLink(['section' => 'domains', 'page' => $page]), 'formdata' => $domain_import_data['domain_import'], // alert-box 'type' => 'info', - 'alert_msg' => $lng['domains']['import_description'] + 'alert_msg' => lng('domains.import_description') ]); } } } elseif ($page == 'domainssleditor') { - require_once __DIR__ . '/ssl_editor.php'; } elseif ($page == 'domaindnseditor' && Settings::Get('system.dnsenabled') == '1') { - require_once __DIR__ . '/dns_editor.php'; } elseif ($page == 'sslcertificates') { - require_once __DIR__ . '/ssl_certificates.php'; } elseif ($page == 'logfiles') { - require_once __DIR__ . '/logfiles_viewer.php'; } diff --git a/admin_index.php b/admin_index.php index a42eeb03..88faa7bc 100644 --- a/admin_index.php +++ b/admin_index.php @@ -2,19 +2,25 @@ /** * 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 (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ const AREA = 'admin'; @@ -22,40 +28,44 @@ require __DIR__ . '/lib/init.php'; use Froxlor\Api\Commands\Admins as Admins; use Froxlor\Api\Commands\Froxlor as Froxlor; +use Froxlor\CurrentUser; use Froxlor\Database\Database; +use Froxlor\FroxlorLogger; use Froxlor\Settings; +use Froxlor\System\Cronjob; +use Froxlor\System\Crypt; use Froxlor\UI\Panel\UI; use Froxlor\UI\Request; +use Froxlor\UI\Response; +use Froxlor\Validate\Validate; -$id = (int) Request::get('id'); +$id = (int)Request::get('id'); if ($action == 'logout') { - - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "logged out"); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "logged out"); unset($_SESSION['userinfo']); - \Froxlor\CurrentUser::setData(); + CurrentUser::setData(); session_destroy(); - \Froxlor\UI\Response::redirectTo('index.php'); + Response::redirectTo('index.php'); } elseif ($action == 'suback') { - if (is_array(\Froxlor\CurrentUser::getField('switched_user'))) { - $result = \Froxlor\CurrentUser::getData(); + if (is_array(CurrentUser::getField('switched_user'))) { + $result = CurrentUser::getData(); $result = $result['switched_user']; - \Froxlor\CurrentUser::setData($result); + CurrentUser::setData($result); $target = (isset($_GET['target']) ? $_GET['target'] : 'index'); $redirect = "admin_" . $target . ".php"; if (!file_exists(\Froxlor\Froxlor::getInstallDir() . "/" . $redirect)) { $redirect = "admin_index.php"; } - \Froxlor\UI\Response::redirectTo($redirect, null, true); + Response::redirectTo($redirect, null, true); } else { - \Froxlor\UI\Response::dynamic_error("Cannot change back - You've never switched to another user :-)"); + Response::dynamicError("Cannot change back - You've never switched to another user :-)"); } } if ($page == 'overview') { - - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_index"); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_index"); $params = []; if ($userinfo['customers_see_all'] == '0') { $params = [ @@ -103,7 +113,7 @@ if ($page == 'overview') { try { $json_result = Froxlor::getLocal($userinfo)->checkUpdate(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; @@ -113,15 +123,15 @@ if ($page == 'overview') { $lookfornewversion_addinfo = $result['additional_info']; $isnewerversion = $result['isnewerversion']; } else { - $lookfornewversion_lable = $lng['admin']['lookfornewversion']['clickhere']; + $lookfornewversion_lable = lng('admin.lookfornewversion.clickhere'); $lookfornewversion_link = htmlspecialchars($filename . '?page=' . urlencode($page) . '&lookfornewversion=yes'); $lookfornewversion_message = ''; $lookfornewversion_addinfo = ''; $isnewerversion = 0; } - $cron_last_runs = \Froxlor\System\Cronjob::getCronjobsLastRun(); - $outstanding_tasks = \Froxlor\System\Cronjob::getOutstandingTasks(); + $cron_last_runs = Cronjob::getCronjobsLastRun(); + $outstanding_tasks = Cronjob::getOutstandingTasks(); // additional sys-infos $meminfo = explode("\n", @file_get_contents("/proc/meminfo")); @@ -138,7 +148,7 @@ if ($page == 'overview') { } else { $load = @file_get_contents('/proc/loadavg'); if (!$load) { - $load = $lng['admin']['noloadavailable']; + $load = lng('admin.noloadavailable'); } } @@ -186,72 +196,69 @@ if ($page == 'overview') { 'cron_last_runs' => $cron_last_runs ]); } elseif ($page == 'change_password') { - if (isset($_POST['send']) && $_POST['send'] == 'send') { - $old_password = \Froxlor\Validate\Validate::validate($_POST['old_password'], 'old password'); + $old_password = Validate::validate($_POST['old_password'], 'old password'); - if (!\Froxlor\System\Crypt::validatePasswordLogin($userinfo, $old_password, TABLE_PANEL_ADMINS, 'adminid')) { - \Froxlor\UI\Response::standard_error('oldpasswordnotcorrect'); + if (!Crypt::validatePasswordLogin($userinfo, $old_password, TABLE_PANEL_ADMINS, 'adminid')) { + Response::standardError('oldpasswordnotcorrect'); } try { - $new_password = \Froxlor\System\Crypt::validatePassword($_POST['new_password'], 'new password'); - $new_password_confirm = \Froxlor\System\Crypt::validatePassword($_POST['new_password_confirm'], 'new password confirm'); + $new_password = Crypt::validatePassword($_POST['new_password'], 'new password'); + $new_password_confirm = Crypt::validatePassword($_POST['new_password_confirm'], 'new password confirm'); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } if ($old_password == '') { - \Froxlor\UI\Response::standard_error(array( + Response::standardError([ 'stringisempty', 'oldpassword' - )); + ]); } elseif ($new_password == '') { - \Froxlor\UI\Response::standard_error(array( + Response::standardError([ 'stringisempty', 'newpassword' - )); + ]); } elseif ($new_password_confirm == '') { - \Froxlor\UI\Response::standard_error(array( + Response::standardError([ 'stringisempty', 'newpasswordconfirm' - )); + ]); } elseif ($new_password != $new_password_confirm) { - \Froxlor\UI\Response::standard_error('newpasswordconfirmerror'); + Response::standardError('newpasswordconfirmerror'); } else { try { - Admins::getLocal($userinfo, array( + Admins::getLocal($userinfo, [ 'id' => $userinfo['adminid'], 'admin_password' => $new_password - ))->update(); + ])->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'changed password'); - \Froxlor\UI\Response::redirectTo($filename); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'changed password'); + Response::redirectTo($filename); } } else { UI::view('user/change_password.html.twig'); } } elseif ($page == 'change_language') { - if (isset($_POST['send']) && $_POST['send'] == 'send') { - $def_language = \Froxlor\Validate\Validate::validate($_POST['def_language'], 'default language'); + $def_language = Validate::validate($_POST['def_language'], 'default language'); if (isset($languages[$def_language])) { try { - Admins::getLocal($userinfo, array( + Admins::getLocal($userinfo, [ 'id' => $userinfo['adminid'], 'def_language' => $def_language - ))->update(); + ])->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } } - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "changed his/her default language to '" . $def_language . "'"); - \Froxlor\UI\Response::redirectTo($filename); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "changed his/her default language to '" . $def_language . "'"); + Response::redirectTo($filename); } else { - $default_lang = Settings::Get('panel.standardlanguage'); if ($userinfo['def_language'] != '') { $default_lang = $userinfo['def_language']; @@ -263,22 +270,20 @@ if ($page == 'overview') { ]); } } elseif ($page == 'change_theme') { - if (isset($_POST['send']) && $_POST['send'] == 'send') { - $theme = \Froxlor\Validate\Validate::validate($_POST['theme'], 'theme'); + $theme = Validate::validate($_POST['theme'], 'theme'); try { - Admins::getLocal($userinfo, array( + Admins::getLocal($userinfo, [ 'id' => $userinfo['adminid'], 'theme' => $theme - ))->update(); + ])->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "changed his/her theme to '" . $theme . "'"); - \Froxlor\UI\Response::redirectTo($filename); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "changed his/her theme to '" . $theme . "'"); + Response::redirectTo($filename); } else { - $default_theme = Settings::Get('panel.default_theme'); if ($userinfo['theme'] != '') { $default_theme = $userinfo['theme']; diff --git a/admin_ipsandports.php b/admin_ipsandports.php index 8ba5e0d5..5f06c444 100644 --- a/admin_ipsandports.php +++ b/admin_ipsandports.php @@ -2,79 +2,92 @@ /** * 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 (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ const AREA = 'admin'; require __DIR__ . '/lib/init.php'; use Froxlor\Api\Commands\IpsAndPorts; +use Froxlor\FroxlorLogger; +use Froxlor\PhpHelper; +use Froxlor\UI\Collection; +use Froxlor\UI\HTML; +use Froxlor\UI\Listing; use Froxlor\UI\Panel\UI; use Froxlor\UI\Request; +use Froxlor\UI\Response; -$id = (int) Request::get('id'); +$id = (int)Request::get('id'); if ($page == 'ipsandports' || $page == 'overview') { if ($action == '') { - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_ipsandports"); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_ipsandports"); try { $ipsandports_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/admin/tablelisting.ipsandports.php'; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\IpsAndPorts::class, $userinfo)) + $collection = (new Collection(IpsAndPorts::class, $userinfo)) ->withPagination($ipsandports_list_data['ipsandports_list']['columns']); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } UI::view('user/table.html.twig', [ - 'listing' => \Froxlor\UI\Listing::format($collection, $ipsandports_list_data, 'ipsandports_list') , - 'actions_links' => [[ - 'href' => $linker->getLink(['section' => 'ipsandports', 'page' => $page, 'action' => 'add']), - 'label' => $lng['admin']['ipsandports']['add'] - ]] + 'listing' => Listing::format($collection, $ipsandports_list_data, 'ipsandports_list'), + 'actions_links' => [ + [ + 'href' => $linker->getLink(['section' => 'ipsandports', 'page' => $page, 'action' => 'add']), + 'label' => lng('admin.ipsandports.add') + ] + ] ]); } elseif ($action == 'delete' && $id != 0) { try { - $json_result = IpsAndPorts::getLocal($userinfo, array( + $json_result = IpsAndPorts::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; if (isset($result['id']) && $result['id'] == $id) { if (isset($_POST['send']) && $_POST['send'] == 'send') { - try { - IpsAndPorts::getLocal($userinfo, array( + IpsAndPorts::getLocal($userinfo, [ 'id' => $id - ))->delete(); + ])->delete(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - \Froxlor\UI\HTML::askYesNo('admin_ip_reallydelete', $filename, array( + HTML::askYesNo('admin_ip_reallydelete', $filename, [ 'id' => $id, 'page' => $page, 'action' => $action - ), $result['ip'] . ':' . $result['port']); + ], $result['ip'] . ':' . $result['port']); } } } elseif ($action == 'add') { @@ -82,49 +95,46 @@ if ($page == 'ipsandports' || $page == 'overview') { try { IpsAndPorts::getLocal($userinfo, $_POST)->add(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - $ipsandports_add_data = include_once dirname(__FILE__) . '/lib/formfields/admin/ipsandports/formfield.ipsandports_add.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'ipsandports')), + 'formaction' => $linker->getLink(['section' => 'ipsandports']), 'formdata' => $ipsandports_add_data['ipsandports_add'] ]); } } elseif ($action == 'edit' && $id != 0) { try { - $json_result = IpsAndPorts::getLocal($userinfo, array( + $json_result = IpsAndPorts::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; if ($result['ip'] != '') { - if (isset($_POST['send']) && $_POST['send'] == 'send') { try { IpsAndPorts::getLocal($userinfo, $_POST)->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - - $result = \Froxlor\PhpHelper::htmlentitiesArray($result); + $result = PhpHelper::htmlentitiesArray($result); $ipsandports_edit_data = include_once dirname(__FILE__) . '/lib/formfields/admin/ipsandports/formfield.ipsandports_edit.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'ipsandports', 'id' => $id)), + 'formaction' => $linker->getLink(['section' => 'ipsandports', 'id' => $id]), 'formdata' => $ipsandports_edit_data['ipsandports_edit'], 'editid' => $id ]); @@ -134,7 +144,7 @@ if ($page == 'ipsandports' || $page == 'overview') { $ip = $_POST['ip'] ?? ""; if ((filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) || filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) && filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE) == false) { // returns notice if private network detected so we can display it - echo json_encode($lng['admin']['ipsandports']['ipnote']); + echo json_encode(lng('admin.ipsandports.ipnote')); } else { echo 0; } diff --git a/admin_logger.php b/admin_logger.php index e89af3b0..dce4bf88 100644 --- a/admin_logger.php +++ b/admin_logger.php @@ -2,65 +2,76 @@ /** * 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 (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ const AREA = 'admin'; require __DIR__ . '/lib/init.php'; use Froxlor\Api\Commands\SysLog; +use Froxlor\UI\Collection; +use Froxlor\UI\HTML; +use Froxlor\UI\Listing; use Froxlor\UI\Panel\UI; +use Froxlor\UI\Response; if ($page == 'log' && $userinfo['change_serversettings'] == '1') { if ($action == '') { try { $syslog_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/tablelisting.syslog.php'; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\SysLog::class, $userinfo)) + $collection = (new Collection(SysLog::class, $userinfo)) ->addParam(['sql_orderby' => ['date' => 'DESC']]) ->withPagination($syslog_list_data['syslog_list']['columns']); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } UI::view('user/table.html.twig', [ - 'listing' => \Froxlor\UI\Listing::format($collection, $syslog_list_data, 'syslog_list') , - 'actions_links' => [[ - 'href' => $linker->getLink(['section' => 'logger', 'page' => 'log', 'action' => 'truncate']), - 'label' => $lng['logger']['truncate'], - 'icon' => 'fa-solid fa-recycle', - 'class' => 'btn-warning' - ]] + 'listing' => Listing::format($collection, $syslog_list_data, 'syslog_list'), + 'actions_links' => [ + [ + 'href' => $linker->getLink(['section' => 'logger', 'page' => 'log', 'action' => 'truncate']), + 'label' => lng('logger.truncate'), + 'icon' => 'fa-solid fa-recycle', + 'class' => 'btn-warning' + ] + ] ]); } elseif ($action == 'truncate') { - if (isset($_POST['send']) && $_POST['send'] == 'send') { try { - SysLog::getLocal($userinfo, array( + SysLog::getLocal($userinfo, [ 'min_to_keep' => 10 - ))->delete(); + ])->delete(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - \Froxlor\UI\HTML::askYesNo('logger_reallytruncate', $filename, array( + HTML::askYesNo('logger_reallytruncate', $filename, [ 'page' => $page, 'action' => $action - ), TABLE_PANEL_LOG); + ], TABLE_PANEL_LOG); } } } diff --git a/admin_message.php b/admin_message.php index 9ecf8703..4c473df8 100644 --- a/admin_message.php +++ b/admin_message.php @@ -2,56 +2,65 @@ /** * 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 (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ const AREA = 'admin'; require __DIR__ . '/lib/init.php'; use Froxlor\Database\Database; -use Froxlor\UI\Request; +use Froxlor\FroxlorLogger; use Froxlor\UI\Panel\UI; +use Froxlor\UI\Request; +use Froxlor\UI\Response; +use Froxlor\User; -$id = (int) Request::get('id'); +$id = (int)Request::get('id'); $note_type = null; $note_msg = null; if ($page == 'message') { if ($action == '') { - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'viewed panel_message'); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'viewed panel_message'); if (isset($_POST['send']) && $_POST['send'] == 'send') { if ($_POST['recipient'] == 0 && $userinfo['customers_see_all'] == '1') { - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'sending messages to admins'); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'sending messages to admins'); $result = Database::query('SELECT `name`, `email` FROM `' . TABLE_PANEL_ADMINS . "`"); } elseif ($_POST['recipient'] == 1) { if ($userinfo['customers_see_all'] == '1') { - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'sending messages to ALL customers'); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'sending messages to ALL customers'); $result = Database::query('SELECT `firstname`, `name`, `company`, `email` FROM `' . TABLE_PANEL_CUSTOMERS . "`"); } else { - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'sending messages to customers'); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'sending messages to customers'); $result = Database::prepare(' SELECT `firstname`, `name`, `company`, `email` FROM `' . TABLE_PANEL_CUSTOMERS . "` WHERE `adminid` = :adminid"); - Database::pexecute($result, array( + Database::pexecute($result, [ 'adminid' => $userinfo['adminid'] - )); + ]); } } else { - \Froxlor\UI\Response::standard_error('norecipientsgiven'); + Response::standardError('norecipientsgiven'); } $subject = $_POST['subject']; @@ -63,14 +72,13 @@ if ($page == 'message') { $mail->Subject = $subject; while ($row = $result->fetch(PDO::FETCH_ASSOC)) { - $row['firstname'] = isset($row['firstname']) ? $row['firstname'] : ''; $row['company'] = isset($row['company']) ? $row['company'] : ''; - $mail->AddAddress($row['email'], \Froxlor\User::getCorrectUserSalutation(array( + $mail->AddAddress($row['email'], User::getCorrectUserSalutation([ 'firstname' => $row['firstname'], 'name' => $row['name'], 'company' => $row['company'] - ))); + ])); $mail->From = $userinfo['email']; $mail->FromName = (isset($userinfo['firstname']) ? $userinfo['firstname'] . ' ' : '') . $userinfo['name']; @@ -81,54 +89,60 @@ if ($page == 'message') { $mailerr_msg = $row['email']; } - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_ERR, 'Error sending mail: ' . $mailerr_msg); - \Froxlor\UI\Response::standard_error('errorsendingmail', $row['email']); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_ERR, 'Error sending mail: ' . $mailerr_msg); + Response::standardError('errorsendingmail', $row['email']); } $mailcounter++; $mail->ClearAddresses(); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page, 'action' => 'showsuccess', 'sentitems' => $mailcounter - )); + ]); } else { - \Froxlor\UI\Response::standard_error('nomessagetosend'); + Response::standardError('nomessagetosend'); } } } elseif ($action == 'showsuccess') { - - $sentitems = isset($_GET['sentitems']) ? (int) $_GET['sentitems'] : 0; + $sentitems = isset($_GET['sentitems']) ? (int)$_GET['sentitems'] : 0; if ($sentitems == 0) { $note_type = 'info'; - $note_msg = $lng['message']['norecipients']; + $note_msg = lng('message.norecipients'); } else { $note_type = 'success'; - $note_msg = str_replace('%s', $sentitems, $lng['message']['success']); + $note_msg = str_replace('%s', $sentitems, lng('message.success')); } } $recipients = []; if ($userinfo['customers_see_all'] == '1') { - $recipients[0] = $lng['panel']['reseller']; + $recipients[0] = lng('panel.reseller'); } - $recipients[1] = $lng['panel']['customer']; + $recipients[1] = lng('panel.customer'); $messages_add_data = include_once dirname(__FILE__) . '/lib/formfields/admin/messages/formfield.messages_add.php'; UI::view('user/form-note.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'message')), + 'formaction' => $linker->getLink(['section' => 'message']), 'formdata' => $messages_add_data['messages_add'], - 'actions_links' => [[ - 'href' => $linker->getLink(['section' => 'settings', 'page' => 'overview', 'part' => 'system', 'em' => 'system_mail_use_smtp']), - 'label' => $lng['admin']['smtpsettings'], - 'icon' => 'fa-solid fa-gears', - 'class' => 'btn-outline-secondary' - ]], + 'actions_links' => [ + [ + 'href' => $linker->getLink([ + 'section' => 'settings', + 'page' => 'overview', + 'part' => 'system', + 'em' => 'system_mail_use_smtp' + ]), + 'label' => lng('admin.smtpsettings'), + 'icon' => 'fa-solid fa-gears', + 'class' => 'btn-outline-secondary' + ] + ], // alert-box 'type' => $note_type, 'alert_msg' => $note_msg diff --git a/admin_opcacheinfo.php b/admin_opcacheinfo.php index 20c9d0df..f03d96d7 100644 --- a/admin_opcacheinfo.php +++ b/admin_opcacheinfo.php @@ -11,18 +11,18 @@ * * 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 + * 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 - * http://files.froxlor.org/misc/COPYING.txt + * https://files.froxlor.org/misc/COPYING.txt * * @copyright the authors * @author Froxlor team * @author Janos Muzsi * @author Andrew Collington - * @license http://files.froxlor.org/misc/COPYING.txt GPLv2 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 * * Based on https://github.com/amnuts/opcache-gui, which is * licensed under the MIT licence, which can be viewed @@ -32,26 +32,27 @@ const AREA = 'admin'; require __DIR__ . '/lib/init.php'; +use Froxlor\FroxlorLogger; use Froxlor\UI\Panel\UI; +use Froxlor\UI\Response; if ($action == 'reset' && function_exists('opcache_reset') && $userinfo['change_serversettings'] == '1') { opcache_reset(); - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "reset OPcache"); - header('Location: ' . $linker->getLink(array( - 'section' => 'opcacheinfo', - 'page' => 'showinfo' - ))); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "reset OPcache"); + header('Location: ' . $linker->getLink([ + 'section' => 'opcacheinfo', + 'page' => 'showinfo' + ])); exit(); } if (!function_exists('opcache_get_configuration')) { - \Froxlor\UI\Response::standard_error($lng['error']['no_opcacheinfo']); + Response::standardError(lng('error.no_opcacheinfo')); } if ($page == 'showinfo') { - $time = time(); - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed OPcache info"); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed OPcache info"); $optimizationLevels = [ 1 << 0 => 'CSE, STRING construction', @@ -149,13 +150,13 @@ if ($page == 'showinfo') { [ 'total_memory' => $config['directives']['opcache.memory_consumption'], 'used_memory_percentage' => round(100 * ( - ($status['memory_usage']['used_memory'] + $status['memory_usage']['wasted_memory']) - / $config['directives']['opcache.memory_consumption'] - )), + ($status['memory_usage']['used_memory'] + $status['memory_usage']['wasted_memory']) + / $config['directives']['opcache.memory_consumption'] + )), 'hit_rate_percentage' => round($status['opcache_statistics']['opcache_hit_rate']), 'used_key_percentage' => round(100 * ($status['opcache_statistics']['num_cached_keys'] - / $status['opcache_statistics']['max_cached_keys'] - )), + / $status['opcache_statistics']['max_cached_keys'] + )), 'wasted_percentage' => round($status['memory_usage']['current_wasted_percentage'], 2), 'readable' => [ 'total_memory' => bsize($config['directives']['opcache.memory_consumption']), @@ -175,8 +176,8 @@ if ($page == 'showinfo') { 'last_restart_time' => ($status['opcache_statistics']['last_restart_time'] == 0 ? 'never' : (new DateTimeImmutable("@{$status['opcache_statistics']['last_restart_time']}")) - ->setTimezone(new DateTimeZone(date_default_timezone_get())) - ->format('Y-m-d H:i:s') + ->setTimezone(new DateTimeZone(date_default_timezone_get())) + ->format('Y-m-d H:i:s') ) ] ] diff --git a/admin_phpsettings.php b/admin_phpsettings.php index a6f76744..67e88dc1 100644 --- a/admin_phpsettings.php +++ b/admin_phpsettings.php @@ -2,19 +2,25 @@ /** * 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 (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ const AREA = 'admin'; @@ -23,49 +29,51 @@ require __DIR__ . '/lib/init.php'; use Froxlor\Api\Commands\FpmDaemons; use Froxlor\Api\Commands\PhpSettings; use Froxlor\Database\Database; +use Froxlor\Froxlor; +use Froxlor\UI\Collection; +use Froxlor\UI\HTML; +use Froxlor\UI\Listing; use Froxlor\UI\Panel\UI; use Froxlor\UI\Request; +use Froxlor\UI\Response; -$id = (int) Request::get('id'); +$id = (int)Request::get('id'); if ($page == 'overview') { - if ($action == '') { - try { $phpconf_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/admin/tablelisting.phpconfigs.php'; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\PhpSettings::class, $userinfo, ['with_subdomains' => true])) + $collection = (new Collection(PhpSettings::class, $userinfo, ['with_subdomains' => true])) ->withPagination($phpconf_list_data['phpconf_list']['columns']); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } UI::view('user/table.html.twig', [ - 'listing' => \Froxlor\UI\Listing::format($collection, $phpconf_list_data, 'phpconf_list') , - 'actions_links' => (bool)$userinfo['change_serversettings'] ? [[ - 'href' => $linker->getLink(['section' => 'phpsettings', 'page' => $page, 'action' => 'add']), - 'label' => $lng['admin']['phpsettings']['addnew'] - ]] : [] + 'listing' => Listing::format($collection, $phpconf_list_data, 'phpconf_list'), + 'actions_links' => (bool)$userinfo['change_serversettings'] ? [ + [ + 'href' => $linker->getLink(['section' => 'phpsettings', 'page' => $page, 'action' => 'add']), + 'label' => lng('admin.phpsettings.addnew') + ] + ] : [] ]); } if ($action == 'add') { - - if ((int) $userinfo['change_serversettings'] == 1) { - + if ((int)$userinfo['change_serversettings'] == 1) { if (isset($_POST['send']) && $_POST['send'] == 'send') { try { PhpSettings::getLocal($userinfo, $_POST)->add(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - - if (file_exists(\Froxlor\Froxlor::getInstallDir() . '/templates/misc/php/default.ini.php')) { - include \Froxlor\Froxlor::getInstallDir() . '/templates/misc/php/default.ini.php'; + if (file_exists(Froxlor::getInstallDir() . '/templates/misc/php/default.ini.php')) { + include Froxlor::getInstallDir() . '/templates/misc/php/default.ini.php'; $result = [ 'phpsettings' => $phpini ]; @@ -78,82 +86,77 @@ if ($page == 'overview') { $fpmconfigs = []; $configs = Database::query("SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "` ORDER BY `description` ASC"); while ($row = $configs->fetch(PDO::FETCH_ASSOC)) { - $fpmconfigs[$row['id']] = $row['description'];; + $fpmconfigs[$row['id']] = $row['description']; } $phpconfig_add_data = include_once dirname(__FILE__) . '/lib/formfields/admin/phpconfig/formfield.phpconfig_add.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'phpsettings')), + 'formaction' => $linker->getLink(['section' => 'phpsettings']), 'formdata' => $phpconfig_add_data['phpconfig_add'] ]); } } else { - \Froxlor\UI\Response::standard_error('nopermissionsorinvalidid'); + Response::standardError('nopermissionsorinvalidid'); } } if ($action == 'delete') { - try { - $json_result = PhpSettings::getLocal($userinfo, array( + $json_result = PhpSettings::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; - if ($result['id'] != 0 && $result['id'] == $id && (int) $userinfo['change_serversettings'] == 1 && $id != 1) // cannot delete the default php.config + if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1 && $id != 1) // cannot delete the default php.config { - if (isset($_POST['send']) && $_POST['send'] == 'send') { try { - PhpSettings::getLocal($userinfo, array( + PhpSettings::getLocal($userinfo, [ 'id' => $id - ))->delete(); + ])->delete(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - \Froxlor\UI\HTML::askYesNo('phpsetting_reallydelete', $filename, array( + HTML::askYesNo('phpsetting_reallydelete', $filename, [ 'id' => $id, 'page' => $page, 'action' => $action - ), $result['description']); + ], $result['description']); } } else { - \Froxlor\UI\Response::standard_error('nopermissionsorinvalidid'); + Response::standardError('nopermissionsorinvalidid'); } } if ($action == 'edit') { - try { - $json_result = PhpSettings::getLocal($userinfo, array( + $json_result = PhpSettings::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; - if ($result['id'] != 0 && $result['id'] == $id && (int) $userinfo['change_serversettings'] == 1) { - + if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1) { if (isset($_POST['send']) && $_POST['send'] == 'send') { try { PhpSettings::getLocal($userinfo, $_POST)->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - $fpmconfigs = []; $configs = Database::query("SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "` ORDER BY `description` ASC"); while ($row = $configs->fetch(PDO::FETCH_ASSOC)) { @@ -163,135 +166,128 @@ if ($page == 'overview') { $phpconfig_edit_data = include_once dirname(__FILE__) . '/lib/formfields/admin/phpconfig/formfield.phpconfig_edit.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'phpsettings', 'id' => $id)), + 'formaction' => $linker->getLink(['section' => 'phpsettings', 'id' => $id]), 'formdata' => $phpconfig_edit_data['phpconfig_edit'], 'editid' => $id ]); } } else { - \Froxlor\UI\Response::standard_error('nopermissionsorinvalidid'); + Response::standardError('nopermissionsorinvalidid'); } } } elseif ($page == 'fpmdaemons') { - if ($action == '') { - try { $fpmconf_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/admin/tablelisting.fpmconfigs.php'; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\FpmDaemons::class, $userinfo)) + $collection = (new Collection(FpmDaemons::class, $userinfo)) ->withPagination($fpmconf_list_data['fpmconf_list']['columns']); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } UI::view('user/table.html.twig', [ - 'listing' => \Froxlor\UI\Listing::format($collection, $fpmconf_list_data, 'fpmconf_list') , - 'actions_links' => (bool)$userinfo['change_serversettings'] ? [[ - 'href' => $linker->getLink(['section' => 'phpsettings', 'page' => $page, 'action' => 'add']), - 'label' => $lng['admin']['fpmsettings']['addnew'] - ]] : [] + 'listing' => Listing::format($collection, $fpmconf_list_data, 'fpmconf_list'), + 'actions_links' => (bool)$userinfo['change_serversettings'] ? [ + [ + 'href' => $linker->getLink(['section' => 'phpsettings', 'page' => $page, 'action' => 'add']), + 'label' => lng('admin.fpmsettings.addnew') + ] + ] : [] ]); } if ($action == 'add') { - - if ((int) $userinfo['change_serversettings'] == 1) { - + if ((int)$userinfo['change_serversettings'] == 1) { if (isset($_POST['send']) && $_POST['send'] == 'send') { try { FpmDaemons::getLocal($userinfo, $_POST)->add(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - $fpmconfig_add_data = include_once dirname(__FILE__) . '/lib/formfields/admin/phpconfig/formfield.fpmconfig_add.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'phpsettings', 'page' => 'fpmdaemons')), + 'formaction' => $linker->getLink(['section' => 'phpsettings', 'page' => 'fpmdaemons']), 'formdata' => $fpmconfig_add_data['fpmconfig_add'] ]); } } else { - \Froxlor\UI\Response::standard_error('nopermissionsorinvalidid'); + Response::standardError('nopermissionsorinvalidid'); } } if ($action == 'delete') { - try { - $json_result = FpmDaemons::getLocal($userinfo, array( + $json_result = FpmDaemons::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; if ($id == 1) { - \Froxlor\UI\Response::standard_error('cannotdeletedefaultphpconfig'); + Response::standardError('cannotdeletedefaultphpconfig'); } - if ($result['id'] != 0 && $result['id'] == $id && (int) $userinfo['change_serversettings'] == 1 && $id != 1) // cannot delete the default php.config + if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1 && $id != 1) // cannot delete the default php.config { if (isset($_POST['send']) && $_POST['send'] == 'send') { try { FpmDaemons::getLocal($userinfo, $_POST)->delete(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - \Froxlor\UI\HTML::askYesNo('fpmsetting_reallydelete', $filename, array( + HTML::askYesNo('fpmsetting_reallydelete', $filename, [ 'id' => $id, 'page' => $page, 'action' => $action - ), $result['description']); + ], $result['description']); } } else { - \Froxlor\UI\Response::standard_error('nopermissionsorinvalidid'); + Response::standardError('nopermissionsorinvalidid'); } } if ($action == 'edit') { - try { - $json_result = FpmDaemons::getLocal($userinfo, array( + $json_result = FpmDaemons::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; - if ($result['id'] != 0 && $result['id'] == $id && (int) $userinfo['change_serversettings'] == 1) { - + if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1) { if (isset($_POST['send']) && $_POST['send'] == 'send') { try { FpmDaemons::getLocal($userinfo, $_POST)->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - $fpmconfig_edit_data = include_once dirname(__FILE__) . '/lib/formfields/admin/phpconfig/formfield.fpmconfig_edit.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'phpsettings', 'page' => 'fpmdaemons', 'id' => $id)), + 'formaction' => $linker->getLink(['section' => 'phpsettings', 'page' => 'fpmdaemons', 'id' => $id]), 'formdata' => $fpmconfig_edit_data['fpmconfig_edit'], 'editid' => $id ]); } } else { - \Froxlor\UI\Response::standard_error('nopermissionsorinvalidid'); + Response::standardError('nopermissionsorinvalidid'); } } } diff --git a/admin_plans.php b/admin_plans.php index f68fc84d..d308454c 100644 --- a/admin_plans.php +++ b/admin_plans.php @@ -4,15 +4,23 @@ * 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 (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ const AREA = 'admin'; @@ -20,81 +28,83 @@ require __DIR__ . '/lib/init.php'; use Froxlor\Api\Commands\HostingPlans; use Froxlor\Database\Database; +use Froxlor\FroxlorLogger; +use Froxlor\PhpHelper; use Froxlor\Settings; +use Froxlor\UI\Collection; +use Froxlor\UI\HTML; +use Froxlor\UI\Listing; use Froxlor\UI\Panel\UI; use Froxlor\UI\Request; +use Froxlor\UI\Response; -$id = (int) Request::get('id'); +$id = (int)Request::get('id'); if ($page == '' || $page == 'overview') { - if ($action == '') { - - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_plans"); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_plans"); try { - $plan_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/admin/tablelisting.plans.php'; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\HostingPlans::class, $userinfo)) - ->withPagination($plan_list_data['plan_list']['columns']); + $plan_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/admin/tablelisting.plans.php'; + $collection = (new Collection(HostingPlans::class, $userinfo)) + ->withPagination($plan_list_data['plan_list']['columns']); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } UI::view('user/table.html.twig', [ - 'listing' => \Froxlor\UI\Listing::format($collection, $plan_list_data, 'plan_list') , - 'actions_links' => [[ - 'href' => $linker->getLink(['section' => 'plans', 'page' => $page, 'action' => 'add']), - 'label' => $lng['admin']['plans']['add'] - ]] + 'listing' => Listing::format($collection, $plan_list_data, 'plan_list'), + 'actions_links' => [ + [ + 'href' => $linker->getLink(['section' => 'plans', 'page' => $page, 'action' => 'add']), + 'label' => lng('admin.plans.add') + ] + ] ]); } elseif ($action == 'delete' && $id != 0) { - try { - $json_result = HostingPlans::getLocal($userinfo, array( + $json_result = HostingPlans::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; - if ($result['id'] != 0 && $result['id'] == $id && (int) $userinfo['adminid'] == $result['adminid']) { + if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['adminid'] == $result['adminid']) { if (isset($_POST['send']) && $_POST['send'] == 'send') { - try { - HostingPlans::getLocal($userinfo, array( + HostingPlans::getLocal($userinfo, [ 'id' => $id - ))->delete(); + ])->delete(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - \Froxlor\UI\HTML::askYesNo('plan_reallydelete', $filename, array( + HTML::askYesNo('plan_reallydelete', $filename, [ 'id' => $id, 'page' => $page, 'action' => $action - ), $result['name']); + ], $result['name']); } } else { - \Froxlor\UI\Response::standard_error('nopermissionsorinvalidid'); + Response::standardError('nopermissionsorinvalidid'); } } elseif ($action == 'add') { - if (isset($_POST['send']) && $_POST['send'] == 'send') { try { HostingPlans::getLocal($userinfo, $_POST)->add(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - $phpconfigs = []; $configs = Database::query(" SELECT c.*, fc.description as interpreter @@ -102,16 +112,16 @@ if ($page == '' || $page == 'overview') { LEFT JOIN `" . TABLE_PANEL_FPMDAEMONS . "` fc ON fc.id = c.fpmsettingid "); while ($row = $configs->fetch(PDO::FETCH_ASSOC)) { - if ((int) Settings::Get('phpfpm.enabled') == 1) { - $phpconfigs[] = array( + if ((int)Settings::Get('phpfpm.enabled') == 1) { + $phpconfigs[] = [ 'label' => $row['description'] . " [" . $row['interpreter'] . "]", 'value' => $row['id'] - ); + ]; } else { - $phpconfigs[] = array( + $phpconfigs[] = [ 'label' => $row['description'], 'value' => $row['id'] - ); + ]; } } @@ -128,24 +138,23 @@ if ($page == '' || $page == 'overview') { $plans_add_data['plans_add']['sections'] = array_merge($plans_add_data['plans_add']['sections'], $cust_add_data['customer_add']['sections']); UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'plans')), + 'formaction' => $linker->getLink(['section' => 'plans']), 'formdata' => $plans_add_data['plans_add'] ]); } } elseif ($action == 'edit' && $id != 0) { try { - $json_result = HostingPlans::getLocal($userinfo, array( + $json_result = HostingPlans::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; if ($result['name'] != '') { - $result['value'] = json_decode($result['value'], true); - $result = \Froxlor\PhpHelper::htmlentitiesArray($result); + $result = PhpHelper::htmlentitiesArray($result); foreach ($result['value'] as $index => $value) { $result[$index] = $value; @@ -153,17 +162,15 @@ if ($page == '' || $page == 'overview') { $result['allowed_phpconfigs'] = json_encode($result['allowed_phpconfigs']); if (isset($_POST['send']) && $_POST['send'] == 'send') { - try { HostingPlans::getLocal($userinfo, $_POST)->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - $phpconfigs = []; $configs = Database::query(" SELECT c.*, fc.description as interpreter @@ -171,16 +178,16 @@ if ($page == '' || $page == 'overview') { LEFT JOIN `" . TABLE_PANEL_FPMDAEMONS . "` fc ON fc.id = c.fpmsettingid "); while ($row = $configs->fetch(PDO::FETCH_ASSOC)) { - if ((int) Settings::Get('phpfpm.enabled') == 1) { - $phpconfigs[] = array( + if ((int)Settings::Get('phpfpm.enabled') == 1) { + $phpconfigs[] = [ 'label' => $row['description'] . " [" . $row['interpreter'] . "]", 'value' => $row['id'] - ); + ]; } else { - $phpconfigs[] = array( + $phpconfigs[] = [ 'label' => $row['description'], 'value' => $row['id'] - ); + ]; } } @@ -220,20 +227,20 @@ if ($page == '' || $page == 'overview') { $plans_edit_data['plans_edit']['sections'] = array_merge($plans_edit_data['plans_edit']['sections'], $cust_edit_data['customer_edit']['sections']); UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'plans', 'id' => $id)), + 'formaction' => $linker->getLink(['section' => 'plans', 'id' => $id]), 'formdata' => $plans_edit_data['plans_edit'], 'editid' => $id ]); } } } elseif ($action == 'jqGetPlanValues') { - $planid = isset($_POST['planid']) ? (int) $_POST['planid'] : 0; + $planid = isset($_POST['planid']) ? (int)$_POST['planid'] : 0; try { - $json_result = HostingPlans::getLocal($userinfo, array( + $json_result = HostingPlans::getLocal($userinfo, [ 'id' => $planid - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; echo $result['value']; diff --git a/admin_settings.php b/admin_settings.php index 903cd81b..945458ce 100644 --- a/admin_settings.php +++ b/admin_settings.php @@ -2,26 +2,43 @@ /** * 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 (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -use Froxlor\Database\Database; -use Froxlor\Settings; use Froxlor\Api\Commands\Froxlor; +use Froxlor\Cron\TaskId; +use Froxlor\Database\Database; +use Froxlor\Database\IntegrityCheck; +use Froxlor\FroxlorLogger; +use Froxlor\PhpHelper; +use Froxlor\Settings; +use Froxlor\System\Cronjob; +use Froxlor\UI\Form; +use Froxlor\UI\HTML; +use Froxlor\UI\Listing; use Froxlor\UI\Panel\UI; use Froxlor\UI\Request; +use Froxlor\UI\Response; +use Froxlor\User; +use PHPMailer\PHPMailer\PHPMailer; const AREA = 'admin'; require __DIR__ . '/lib/init.php'; @@ -33,11 +50,10 @@ $sql_root = Database::getSqlData(); Database::needRoot(false); if ($page == 'overview' && $userinfo['change_serversettings'] == '1') { - $settings_data = \Froxlor\PhpHelper::loadConfigArrayDir('./actions/admin/settings/'); + $settings_data = PhpHelper::loadConfigArrayDir('./actions/admin/settings/'); Settings::loadSettingsInto($settings_data); if (isset($_POST['send']) && $_POST['send'] == 'send') { - $_part = isset($_GET['part']) ? $_GET['part'] : ''; if ($_part == '') { $_part = isset($_POST['part']) ? $_POST['part'] : ''; @@ -60,35 +76,34 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') { // check if the session timeout is too low #815 if (isset($_POST['session_sessiontimeout']) && $_POST['session_sessiontimeout'] < 60) { - \Froxlor\UI\Response::standard_error($lng['error']['session_timeout'], $lng['error']['session_timeout_desc']); + Response::standardError(lng('error.session_timeout'), lng('error.session_timeout_desc')); } - if (\Froxlor\UI\Form::processForm($settings_data, $_POST, array( + if (Form::processForm($settings_data, $_POST, [ 'filename' => $filename, 'action' => $action, 'page' => $page - ), $_part, $settings_all, $settings_part, $only_enabledisable)) { - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "rebuild configfiles due to changed setting"); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + ], $_part, $settings_all, $settings_part, $only_enabledisable)) { + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "rebuild configfiles due to changed setting"); + Cronjob::inserttask(TaskId::REBUILD_VHOST); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); + Cronjob::inserttask(TaskId::REBUILD_DNS); // cron.d file - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_CRON); + Cronjob::inserttask(TaskId::REBUILD_CRON); - \Froxlor\UI\Response::standard_success('settingssaved', '', array( + Response::standardSuccess('settingssaved', '', [ 'filename' => $filename, 'action' => $action, 'page' => $page - )); + ]); } } else { - $_part = isset($_GET['part']) ? $_GET['part'] : ''; if ($_part == '') { $_part = isset($_POST['part']) ? $_POST['part'] : ''; } - $fields = \Froxlor\UI\Form::buildForm($settings_data, $_part); + $fields = Form::buildForm($settings_data, $_part); if ($_part == '' || $_part == 'all') { UI::view('settings/index.html.twig', ['fields' => $fields]); @@ -100,26 +115,26 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') { } elseif ($page == 'phpinfo' && $userinfo['change_serversettings'] == '1') { ob_start(); phpinfo(); - $phpinfo = array( - 'phpinfo' => array() - ); + $phpinfo = [ + 'phpinfo' => [] + ]; if (preg_match_all('#(?:

(?:)?(.*?)(?:)?

)|(?:(.*?)\s*(?:(.*?)\s*(?:(.*?)\s*)?)?)#s', ob_get_clean(), $matches, PREG_SET_ORDER)) { foreach ($matches as $match) { $end = array_keys($phpinfo); $end = end($end); if (strlen($match[1])) { - $phpinfo[$match[1]] = array(); + $phpinfo[$match[1]] = []; } elseif (isset($match[3])) { - $phpinfo[$end][$match[2]] = isset($match[4]) ? array( + $phpinfo[$end][$match[2]] = isset($match[4]) ? [ $match[3], $match[4] - ) : $match[3]; + ] : $match[3]; } else { $phpinfo[$end][] = $match[2]; } } } else { - \Froxlor\UI\Response::standard_error($lng['error']['no_phpinfo']); + Response::standardError(lng('error.no_phpinfo')); } UI::view('settings/phpinfo.html.twig', [ 'phpversion' => PHP_VERSION, @@ -127,64 +142,57 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') { ]); } elseif ($page == 'rebuildconfigs' && $userinfo['change_serversettings'] == '1') { if (isset($_POST['send']) && $_POST['send'] == 'send') { - - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "rebuild configfiles"); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_QUOTA); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "rebuild configfiles"); + Cronjob::inserttask(TaskId::REBUILD_VHOST); + Cronjob::inserttask(TaskId::CREATE_QUOTA); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); + Cronjob::inserttask(TaskId::REBUILD_DNS); // cron.d file - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_CRON); + Cronjob::inserttask(TaskId::REBUILD_CRON); - \Froxlor\UI\Response::standard_success('rebuildingconfigs', '', array( + Response::standardSuccess('rebuildingconfigs', '', [ 'filename' => 'admin_index.php' - )); + ]); } else { - \Froxlor\UI\HTML::askYesNo('admin_configs_reallyrebuild', $filename, array( + HTML::askYesNo('admin_configs_reallyrebuild', $filename, [ 'page' => $page - )); + ]); } } elseif ($page == 'updatecounters' && $userinfo['change_serversettings'] == '1') { - if (isset($_POST['send']) && $_POST['send'] == 'send') { - - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "updated resource-counters"); - $updatecounters = \Froxlor\User::updateCounters(true); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "updated resource-counters"); + $updatecounters = User::updateCounters(true); UI::view('user/resource-counter.html.twig', [ 'counters' => $updatecounters ]); } else { - \Froxlor\UI\HTML::askYesNo('admin_counters_reallyupdate', $filename, array( + HTML::askYesNo('admin_counters_reallyupdate', $filename, [ 'page' => $page - )); + ]); } } elseif ($page == 'wipecleartextmailpws' && $userinfo['change_serversettings'] == '1') { - if (isset($_POST['send']) && $_POST['send'] == 'send') { - - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "wiped all cleartext mail passwords"); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "wiped all cleartext mail passwords"); Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password` = '';"); Database::query("UPDATE `" . TABLE_PANEL_SETTINGS . "` SET `value` = '0' WHERE `settinggroup` = 'system' AND `varname` = 'mailpwcleartext'"); - \Froxlor\UI\Response::redirectTo($filename); + Response::redirectTo($filename); } else { - \Froxlor\UI\HTML::askYesNo('admin_cleartextmailpws_reallywipe', $filename, array( + HTML::askYesNo('admin_cleartextmailpws_reallywipe', $filename, [ 'page' => $page - )); + ]); } } elseif ($page == 'wipequotas' && $userinfo['change_serversettings'] == '1') { - if (isset($_POST['send']) && $_POST['send'] == 'send') { - - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "wiped all mailquotas"); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "wiped all mailquotas"); // Set the quota to 0 which means unlimited Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `quota` = '0';"); Database::query("UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `email_quota_used` = '0'"); - \Froxlor\UI\Response::redirectTo($filename); + Response::redirectTo($filename); } else { - \Froxlor\UI\HTML::askYesNo('admin_quotas_reallywipe', $filename, array( + HTML::askYesNo('admin_quotas_reallywipe', $filename, [ 'page' => $page - )); + ]); } } elseif ($page == 'enforcequotas' && $userinfo['change_serversettings'] == '1') { if (isset($_POST['send']) && $_POST['send'] == 'send') { @@ -192,7 +200,6 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') { $result_stmt = Database::query("SELECT `quota`, `customerid` FROM `" . TABLE_MAIL_USERS . "`"); if (Database::num_rows() > 0) { - $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `email_quota_used` = `email_quota_used` + :diff @@ -201,10 +208,10 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') { while ($array = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $difference = Settings::Get('system.mail_quota') - $array['quota']; - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'diff' => $difference, 'customerid' => $customerid - )); + ]); } } @@ -212,27 +219,27 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') { $upd_stmt = Database::prepare(" UPDATE `" . TABLE_MAIL_USERS . "` SET `quota` = :quota "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'quota' => Settings::Get('system.mail_quota') - )); + ]); // Update the Customer, if the used quota is bigger than the allowed quota Database::query("UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `email_quota` = `email_quota_used` WHERE `email_quota` < `email_quota_used`"); - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, 'enforcing mailquota to all customers: ' . Settings::Get('system.mail_quota') . ' MB'); - \Froxlor\UI\Response::redirectTo($filename); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, 'enforcing mailquota to all customers: ' . Settings::Get('system.mail_quota') . ' MB'); + Response::redirectTo($filename); } else { - \Froxlor\UI\HTML::askYesNo('admin_quotas_reallyenforce', $filename, array( + HTML::askYesNo('admin_quotas_reallyenforce', $filename, [ 'page' => $page - )); + ]); } } elseif ($page == 'integritycheck' && $userinfo['change_serversettings'] == '1') { - $integrity = new \Froxlor\Database\IntegrityCheck(); + $integrity = new IntegrityCheck(); if (isset($_POST['send']) && $_POST['send'] == 'send') { $integrity->fixAll(); } elseif (isset($_GET['action']) && $_GET['action'] == "fix") { - \Froxlor\UI\HTML::askYesNo('admin_integritycheck_reallyfix', $filename, array( + HTML::askYesNo('admin_integritycheck_reallyfix', $filename, [ 'page' => $page - )); + ]); } $integritycheck = []; @@ -240,7 +247,7 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') { $integritycheck[] = [ 'displayid' => $id + 1, 'result' => $integrity->$check(), - 'checkdesc' => $lng['integrity_check'][$check] + 'checkdesc' => lng('integrity_check.' . $check) ]; } @@ -251,18 +258,20 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') { ]; UI::view('user/table.html.twig', [ - 'listing' => \Froxlor\UI\Listing::formatFromArray($collection, $integrity_list_data['integrity_list']), - 'actions_links' => [[ - 'href' => $linker->getLink(['section' => 'settings', 'page' => $page, 'action' => 'fix']), - 'label' => $lng['admin']['integrityfix'], - 'icon' => 'fa-solid fa-screwdriver-wrench', - 'class' => 'btn-warning' - ]] + 'listing' => Listing::formatFromArray($collection, $integrity_list_data['integrity_list']), + 'actions_links' => [ + [ + 'href' => $linker->getLink(['section' => 'settings', 'page' => $page, 'action' => 'fix']), + 'label' => lng('admin.integrityfix'), + 'icon' => 'fa-solid fa-screwdriver-wrench', + 'class' => 'btn-warning' + ] + ] ]); } elseif ($page == 'importexport' && $userinfo['change_serversettings'] == '1') { // check for json-stuff if (!extension_loaded('json')) { - \Froxlor\UI\Response::standard_error('jsonextensionnotfound'); + Response::standardError('jsonextensionnotfound'); } if (isset($_GET['action']) && $_GET['action'] == "export") { @@ -271,7 +280,7 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') { $json_result = Froxlor::getLocal($userinfo)->exportSettings(); $json_export = json_decode($json_result, true)['data']; } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } header('Content-disposition: attachment; filename=Froxlor_settings-' . \Froxlor\Froxlor::VERSION . '-' . \Froxlor\Froxlor::DBVERSION . '_' . date('d.m.Y') . '.json'); header('Content-type: application/json'); @@ -284,47 +293,49 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') { if (isset($_FILES["import_file"]["tmp_name"])) { $imp_content = file_get_contents($_FILES["import_file"]["tmp_name"]); try { - Froxlor::getLocal($userinfo, array( + Froxlor::getLocal($userinfo, [ 'json_str' => $imp_content - ))->importSettings(); + ])->importSettings(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::standard_success('settingsimported', '', array( + Response::standardSuccess('settingsimported', '', [ 'filename' => 'admin_settings.php' - )); + ]); } - \Froxlor\UI\Response::dynamic_error("Upload failed"); + Response::dynamicError("Upload failed"); } } else { $settings_data = include_once dirname(__FILE__) . '/lib/formfields/admin/settings/formfield.settings_import.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'settings', 'page' => $page, 'action' => 'import')), + 'formaction' => $linker->getLink(['section' => 'settings', 'page' => $page, 'action' => 'import']), 'formdata' => $settings_data['settings_import'], - 'actions_links' => [[ - 'class' => 'btn-outline-primary', - 'href' => $linker->getLink(['section' => 'settings', 'page' => 'overview']), - 'label' => $lng['admin']['configfiles']['overview'], - 'icon' => 'fa fa-grip' - ], [ - 'class' => 'btn-outline-secondary', - 'href' => $linker->getLink(['section' => 'settings', 'page' => $page, 'action' => 'export']), - 'label' => 'Download/export ' . $lng['admin']['serversettings'], - 'icon' => 'fa fa-file-import' - ]] + 'actions_links' => [ + [ + 'class' => 'btn-outline-primary', + 'href' => $linker->getLink(['section' => 'settings', 'page' => 'overview']), + 'label' => lng('admin.configfiles.overview'), + 'icon' => 'fa fa-grip' + ], + [ + 'class' => 'btn-outline-secondary', + 'href' => $linker->getLink(['section' => 'settings', 'page' => $page, 'action' => 'export']), + 'label' => 'Download/export ' . lng('admin.serversettings'), + 'icon' => 'fa fa-file-import' + ] + ] ]); } } elseif ($page == 'testmail') { - $note_type = 'info'; - $note_msg = $lng['admin']['smtptestnote']; + $note_msg = lng('admin.smtptestnote'); if (isset($_POST['send']) && $_POST['send'] == 'send') { $test_addr = isset($_POST['test_addr']) ? $_POST['test_addr'] : null; // Initialize the mailingsystem - $testmail = new \PHPMailer\PHPMailer\PHPMailer(true); + $testmail = new PHPMailer(true); $testmail->CharSet = "UTF-8"; if (Settings::Get('system.mail_use_smtp')) { @@ -342,7 +353,7 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') { } $_mailerror = false; - if (\PHPMailer\PHPMailer\PHPMailer::ValidateAddress(Settings::Get('panel.adminmail')) !== false) { + if (PHPMailer::ValidateAddress(Settings::Get('panel.adminmail')) !== false) { // set return-to address and custom sender-name, see #76 $testmail->SetFrom(Settings::Get('panel.adminmail'), Settings::Get('panel.adminmail_defname')); if (Settings::Get('panel.adminmail_return') != '') { @@ -369,10 +380,10 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') { if (!$_mailerror) { // success $mail->ClearAddresses(); - \Froxlor\UI\Response::standard_success('testmailsent', '', array( + Response::standardSuccess('testmailsent', '', [ 'filename' => 'admin_settings.php', 'page' => 'testmail' - )); + ]); } } else { // invalid sender e-mail @@ -384,14 +395,21 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') { $mailtest_add_data = include_once dirname(__FILE__) . '/lib/formfields/admin/settings/formfield.settings_mailtest.php'; UI::view('user/form-note.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'settings')), + 'formaction' => $linker->getLink(['section' => 'settings']), 'formdata' => $mailtest_add_data['mailtest'], - 'actions_links' => [[ - 'href' => $linker->getLink(['section' => 'settings', 'page' => 'overview', 'part' => 'system', 'em' => 'system_mail_use_smtp']), - 'label' => $lng['admin']['smtpsettings'], - 'icon' => 'fa-solid fa-gears', - 'class' => 'btn-outline-secondary' - ]], + 'actions_links' => [ + [ + 'href' => $linker->getLink([ + 'section' => 'settings', + 'page' => 'overview', + 'part' => 'system', + 'em' => 'system_mail_use_smtp' + ]), + 'label' => lng('admin.smtpsettings'), + 'icon' => 'fa-solid fa-gears', + 'class' => 'btn-outline-secondary' + ] + ], // alert-box 'type' => $note_type, 'alert_msg' => $note_msg @@ -401,5 +419,5 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') { $cmode = Settings::Get('panel.settings_mode'); Settings::Set('panel.settings_mode', (int)(!(bool)$cmode)); } - \Froxlor\UI\Response::redirectTo($filename); + Response::redirectTo($filename); } diff --git a/admin_templates.php b/admin_templates.php index 664da5db..96336964 100644 --- a/admin_templates.php +++ b/admin_templates.php @@ -2,69 +2,82 @@ /** * 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 (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ const AREA = 'admin'; require __DIR__ . '/lib/init.php'; use Froxlor\Database\Database; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; +use Froxlor\PhpHelper; use Froxlor\Settings; +use Froxlor\UI\HTML; +use Froxlor\UI\Listing; use Froxlor\UI\Panel\UI; use Froxlor\UI\Request; +use Froxlor\UI\Response; +use Froxlor\Validate\Validate; -$id = (int) Request::get('id'); +$id = (int)Request::get('id'); $subjectid = intval(Request::get('subjectid')); $mailbodyid = intval(Request::get('mailbodyid')); -$available_templates = array( +$available_templates = [ 'createcustomer', 'pop_success', 'new_database_by_customer', 'new_ftpaccount_by_customer', 'password_reset' -); +]; // only show templates of features that are enabled #1191 -if ((int) Settings::Get('system.report_enable') == 1) { +if ((int)Settings::Get('system.report_enable') == 1) { array_push($available_templates, 'trafficmaxpercent', 'diskmaxpercent'); } if (Settings::Get('panel.sendalternativemail') == 1) { array_push($available_templates, 'pop_success_alternative'); } -$file_templates = array( +$file_templates = [ 'index_html' -); +]; if ($action == '') { // email templates - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_templates"); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_templates"); - $templates_array = array(); + $templates_array = []; $result_stmt = Database::prepare(" SELECT `id`, `language`, `varname` FROM `" . TABLE_PANEL_TEMPLATES . "` WHERE `adminid` = :adminid AND `templategroup`='mails' ORDER BY `language`, `varname` "); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'adminid' => $userinfo['adminid'] - )); + ]); while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { - $parts = array(); + $parts = []; preg_match('/^([a-z]([a-z_]+[a-z])*)_(mailbody|subject)$/', $row['varname'], $parts); $templates_array[$row['language']][$parts[1]][$parts[3]] = $row['id']; } @@ -75,7 +88,7 @@ if ($action == '') { $templates[] = [ 'subjectid' => $email['subject'], 'mailbodyid' => $email['mailbody'], - 'template' => $lng['admin']['templates'][$action], + 'template' => lng('admin.templates.' . $action), 'language' => $language ]; } @@ -83,27 +96,28 @@ if ($action == '') { $mail_actions_links = false; foreach ($languages as $language_file => $language_name) { - - $templates_done = array(); + $templates_done = []; $result_stmt = Database::prepare(" SELECT `varname` FROM `" . TABLE_PANEL_TEMPLATES . "` WHERE `adminid` = :adminid AND `language`= :lang AND `templategroup` = 'mails' AND `varname` LIKE '%_subject' "); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'adminid' => $userinfo['adminid'], 'lang' => $language_name - )); + ]); while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $templates_done[] = str_replace('_subject', '', $row['varname']); } if (count(array_diff($available_templates, $templates_done)) > 0) { - $mail_actions_links = [[ - 'href' => $linker->getLink(['section' => 'templates', 'page' => $page, 'action' => 'add']), - 'label' => $lng['admin']['templates']['template_add'] - ]]; + $mail_actions_links = [ + [ + 'href' => $linker->getLink(['section' => 'templates', 'page' => $page, 'action' => 'add']), + 'label' => lng('admin.templates.template_add') + ] + ]; } } @@ -117,24 +131,31 @@ if ($action == '') { $result_stmt = Database::prepare(" SELECT `id`, `varname` FROM `" . TABLE_PANEL_TEMPLATES . "` WHERE `adminid` = :adminid AND `templategroup`='files'"); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'adminid' => $userinfo['adminid'] - )); + ]); $filetemplates = []; while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $filetemplates[] = [ 'id' => $row['id'], - 'template' => $lng['admin']['templates'][$row['varname']] + 'template' => lng('admin.templates.' . $row['varname']) ]; } $file_actions_links = false; if (Database::num_rows() != count($file_templates)) { - $file_actions_links = [[ - 'href' => $linker->getLink(['section' => 'templates', 'page' => $page, 'action' => 'add', 'files' => 'files']), - 'label' => $lng['admin']['templates']['template_fileadd'] - ]]; + $file_actions_links = [ + [ + 'href' => $linker->getLink([ + 'section' => 'templates', + 'page' => $page, + 'action' => 'add', + 'files' => 'files' + ]), + 'label' => lng('admin.templates.template_fileadd') + ] + ]; } $filetpl_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/admin/tablelisting.filetemplates.php'; @@ -144,8 +165,8 @@ if ($action == '') { ]; UI::view('user/table-tpl.html.twig', [ - 'maillisting' => \Froxlor\UI\Listing::formatFromArray($collection_mail, $mailtpl_list_data['mailtpl_list']), - 'filelisting' => \Froxlor\UI\Listing::formatFromArray($collection_file, $filetpl_list_data['filetpl_list']), + 'maillisting' => Listing::formatFromArray($collection_mail, $mailtpl_list_data['mailtpl_list']), + 'filelisting' => Listing::formatFromArray($collection_file, $filetpl_list_data['filetpl_list']), 'actions_links' => array_merge($mail_actions_links, $file_actions_links) ]); } elseif ($action == 'delete' && $subjectid != 0 && $mailbodyid != 0) { @@ -153,10 +174,10 @@ if ($action == '') { $result_stmt = Database::prepare(" SELECT `language`, `varname` FROM `" . TABLE_PANEL_TEMPLATES . "` WHERE `adminid` = :adminid AND `id` = :id"); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'adminid' => $userinfo['adminid'], 'id' => $subjectid - )); + ]); $result = $result_stmt->fetch(PDO::FETCH_ASSOC); if ($result['varname'] != '') { @@ -165,22 +186,22 @@ if ($action == '') { DELETE FROM `" . TABLE_PANEL_TEMPLATES . "` WHERE `adminid` = :adminid AND (`id` = :ida OR `id` = :idb)"); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'adminid' => $userinfo['adminid'], 'ida' => $subjectid, 'idb' => $mailbodyid - )); - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "deleted template '" . $result['language'] . ' - ' . $lng['admin']['templates'][str_replace('_subject', '', $result['varname'])] . "'"); - \Froxlor\UI\Response::redirectTo($filename, array( + ]); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "deleted template '" . $result['language'] . ' - ' . lng('admin.templates.' . str_replace('_subject', '', $result['varname'])) . "'"); + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - \Froxlor\UI\HTML::askYesNo('admin_template_reallydelete', $filename, array( + HTML::askYesNo('admin_template_reallydelete', $filename, [ 'subjectid' => $subjectid, 'mailbodyid' => $mailbodyid, 'page' => $page, 'action' => $action - ), $result['language'] . ' - ' . $lng['admin']['templates'][str_replace('_subject', '', $result['varname'])]); + ], $result['language'] . ' - ' . lng('admin.templates.' . str_replace('_subject', '', $result['varname']))); } } } elseif ($action == 'deletef' && $id != 0) { @@ -188,95 +209,93 @@ if ($action == '') { $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_TEMPLATES . "` WHERE `adminid` = :adminid AND `id` = :id"); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'adminid' => $userinfo['adminid'], 'id' => $id - )); + ]); if (Database::num_rows() > 0) { - $row = $result_stmt->fetch(PDO::FETCH_ASSOC); if (isset($_POST['send']) && $_POST['send'] == 'send') { $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_TEMPLATES . "` WHERE `adminid` = :adminid AND `id` = :id"); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'adminid' => $userinfo['adminid'], 'id' => $id - )); - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "deleted template '" . $lng['admin']['templates'][$row['varname']] . "'"); - \Froxlor\UI\Response::redirectTo($filename, array( + ]); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "deleted template '" . lng('admin.templates.' . $row['varname']) . "'"); + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - \Froxlor\UI\HTML::askYesNo('admin_template_reallydelete', $filename, array( + HTML::askYesNo('admin_template_reallydelete', $filename, [ 'id' => $id, 'page' => $page, 'action' => $action - ), $lng['admin']['templates'][$row['varname']]); + ], lng('admin.templates.' . $row['varname'])); } } else { - \Froxlor\UI\Response::standard_error('templatenotfound'); + Response::standardError('templatenotfound'); } } elseif ($action == 'add') { - if (isset($_POST['prepare']) && $_POST['prepare'] == 'prepare') { // email templates - $language = htmlentities(\Froxlor\Validate\Validate::validate($_POST['language'], 'language', '/^[^\r\n\0"\']+$/', 'nolanguageselect')); - $template = \Froxlor\Validate\Validate::validate($_POST['template'], 'template'); + $language = htmlentities(Validate::validate($_POST['language'], 'language', '/^[^\r\n\0"\']+$/', 'nolanguageselect')); + $template = Validate::validate($_POST['template'], 'template'); $result_stmt = Database::prepare(" SELECT COUNT(*) as def FROM `" . TABLE_PANEL_TEMPLATES . "` WHERE `adminid` = :adminid AND `language` = :lang AND `templategroup` = 'mails' AND `varname` LIKE :template "); - $result = Database::pexecute_first($result_stmt, array( + $result = Database::pexecute_first($result_stmt, [ 'adminid' => $userinfo['adminid'], 'lang' => $language, 'template' => $template . '%' - )); + ]); if ($result && $result['def'] > 0) { - \Froxlor\UI\Response::standard_error('templatelanguagecombodefined'); + Response::standardError('templatelanguagecombodefined'); } $lng_bak = $lng; foreach ($langs['English'] as $key => $value) { - include_once \Froxlor\FileDir::makeSecurePath($value['file']); + include_once FileDir::makeSecurePath($value['file']); } if ($language != 'English') { foreach ($langs[$language] as $key => $value) { - include \Froxlor\FileDir::makeSecurePath($value['file']); + include FileDir::makeSecurePath($value['file']); } } - $subject = $lng['mails'][$template]['subject']; - $body = str_replace('\n', "\n", $lng['mails'][$template]['mailbody']); + $subject = lng('mails.' . $template . '.subject'); + $body = str_replace('\n', "\n", lng('mails.' . $template . '.mailbody')); $lng = $lng_bak; $template_add_data = include_once dirname(__FILE__) . '/lib/formfields/admin/templates/formfield.template_add.php'; UI::view('user/form-replacers.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'templates')), + 'formaction' => $linker->getLink(['section' => 'templates']), 'formdata' => $template_add_data['template_add'], 'replacers' => $template_add_data['template_replacers'] ]); } elseif (isset($_POST['send']) && $_POST['send'] == 'send' && !isset($_POST['filesend'])) { // email templates - $language = htmlentities(\Froxlor\Validate\Validate::validate($_POST['language'], 'language', '/^[^\r\n\0"\']+$/', 'nolanguageselect')); - $template = \Froxlor\Validate\Validate::validate($_POST['template'], 'template'); - $subject = \Froxlor\Validate\Validate::validate($_POST['subject'], 'subject', '/^[^\r\n\0]+$/', 'nosubjectcreate'); - $mailbody = \Froxlor\Validate\Validate::validate($_POST['mailbody'], 'mailbody', '/^[^\0]+$/', 'nomailbodycreate'); - $templates = array(); + $language = htmlentities(Validate::validate($_POST['language'], 'language', '/^[^\r\n\0"\']+$/', 'nolanguageselect')); + $template = Validate::validate($_POST['template'], 'template'); + $subject = Validate::validate($_POST['subject'], 'subject', '/^[^\r\n\0]+$/', 'nosubjectcreate'); + $mailbody = Validate::validate($_POST['mailbody'], 'mailbody', '/^[^\0]+$/', 'nomailbodycreate'); + $templates = []; $result_stmt = Database::prepare(" SELECT `varname` FROM `" . TABLE_PANEL_TEMPLATES . "` WHERE `adminid` = :adminid AND `language` = :lang AND `templategroup` = 'mails' AND `varname` LIKE '%_subject'"); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'adminid' => $userinfo['adminid'], 'lang' => $language - )); + ]); while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $templates[] = str_replace('_subject', '', $row['varname']); @@ -284,7 +303,7 @@ if ($action == '') { $templates = array_diff($available_templates, $templates); if (!in_array($template, $templates)) { - \Froxlor\UI\Response::standard_error('templatenotfound'); + Response::standardError('templatenotfound'); } else { $ins_stmt = Database::prepare(" INSERT INTO `" . TABLE_PANEL_TEMPLATES . "` SET @@ -295,32 +314,32 @@ if ($action == '') { `value` = :value"); // mail-subject - $ins_data = array( + $ins_data = [ 'adminid' => $userinfo['adminid'], 'lang' => $language, 'var' => $template . '_subject', 'value' => $subject - ); + ]; Database::pexecute($ins_stmt, $ins_data); // mail-body - $ins_data = array( + $ins_data = [ 'adminid' => $userinfo['adminid'], 'lang' => $language, 'var' => $template . '_mailbody', 'value' => $mailbody - ); + ]; Database::pexecute($ins_stmt, $ins_data); - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "added template '" . $language . ' - ' . $template . "'"); - \Froxlor\UI\Response::redirectTo($filename, array( + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "added template '" . $language . ' - ' . $template . "'"); + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } } elseif (isset($_POST['filesend']) && $_POST['filesend'] == 'filesend') { // file templates - $template = \Froxlor\Validate\Validate::validate($_POST['template'], 'template'); - $filecontent = \Froxlor\Validate\Validate::validate($_POST['filecontent'], 'filecontent', '/^[^\0]+$/', 'filecontentnotset'); + $template = Validate::validate($_POST['template'], 'template'); + $filecontent = Validate::validate($_POST['filecontent'], 'filecontent', '/^[^\0]+$/', 'filecontentnotset'); $ins_stmt = Database::prepare(" INSERT INTO `" . TABLE_PANEL_TEMPLATES . "` SET @@ -330,34 +349,33 @@ if ($action == '') { `varname` = :var, `value` = :value"); - $ins_data = array( + $ins_data = [ 'adminid' => $userinfo['adminid'], 'var' => $template, 'value' => $filecontent - ); + ]; Database::pexecute($ins_stmt, $ins_data); - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "added template '" . $template . "'"); - \Froxlor\UI\Response::redirectTo($filename, array( + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "added template '" . $template . "'"); + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } elseif (!isset($_GET['files'])) { - // email templates $add = false; $language_options = []; $template_options = []; foreach ($languages as $language_file => $language_name) { - $templates = array(); + $templates = []; $result_stmt = Database::prepare(" SELECT `varname` FROM `" . TABLE_PANEL_TEMPLATES . "` WHERE `adminid` = :adminid AND `language` = :lang AND `templategroup` = 'mails' AND `varname` LIKE '%_subject'"); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'adminid' => $userinfo['adminid'], 'lang' => $language_name - )); + ]); while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $templates[] = str_replace('_subject', '', $row['varname']); @@ -370,29 +388,29 @@ if ($action == '') { $templates = array_diff($available_templates, $templates); foreach ($templates as $template) { - $template_options[$template] = $lng['admin']['templates'][$template]; + $template_options[$template] = lng('admin.templates.' . $template); } } } if ($add) { UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'templates')), + 'formaction' => $linker->getLink(['section' => 'templates']), 'formdata' => [ - 'title' => $lng['admin']['templates']['template_add'], + 'title' => lng('admin.templates.template_add'), 'image' => 'fa-solid fa-plus', 'sections' => [ 'section_a' => [ - 'title' => $lng['admin']['templates']['template_add'], + 'title' => lng('admin.templates.template_add'), 'fields' => [ 'language' => [ - 'label' => $lng['login']['language'], + 'label' => lng('login.language'), 'type' => 'select', 'select_var' => $language_options, 'selected' => $userinfo['language'] ], 'template' => [ - 'label' => $lng['admin']['templates']['action'], + 'label' => lng('admin.templates.action'), 'type' => 'select', 'select_var' => $template_options ], @@ -407,22 +425,21 @@ if ($action == '') { 'editid' => $id ]); } else { - \Froxlor\UI\Response::standard_error('alltemplatesdefined'); + Response::standardError('alltemplatesdefined'); } } else { // filetemplates $result_stmt = Database::prepare(" SELECT `id`, `varname` FROM `" . TABLE_PANEL_TEMPLATES . "` WHERE `adminid` = :adminid AND `templategroup`='files'"); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'adminid' => $userinfo['adminid'] - )); + ]); if (Database::num_rows() == count($file_templates)) { - \Froxlor\UI\Response::standard_error('alltemplatesdefined'); + Response::standardError('alltemplatesdefined'); } else { - - $templatesdefined = array(); + $templatesdefined = []; $free_templates = []; while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { @@ -430,13 +447,13 @@ if ($action == '') { } foreach (array_diff($file_templates, $templatesdefined) as $template) { - $free_templates[$template] = $lng['admin']['templates'][$template]; + $free_templates[$template] = lng('admin.templates.' . $template); } $filetemplate_add_data = include_once dirname(__FILE__) . '/lib/formfields/admin/templates/formfield.filetemplate_add.php'; UI::view('user/form-replacers.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'templates')), + 'formaction' => $linker->getLink(['section' => 'templates']), 'formdata' => $filetemplate_add_data['filetemplate_add'], 'replacers' => $filetemplate_add_data['filetemplate_replacers'] ]); @@ -447,64 +464,62 @@ if ($action == '') { $result_stmt = Database::prepare(" SELECT `language`, `varname`, `value` FROM `" . TABLE_PANEL_TEMPLATES . "` WHERE `adminid` = :adminid AND `id` = :subjectid"); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'adminid' => $userinfo['adminid'], 'subjectid' => $subjectid - )); + ]); $result = $result_stmt->fetch(PDO::FETCH_ASSOC); if ($result['varname'] != '') { - if (isset($_POST['send']) && $_POST['send'] == 'send') { - $subject = \Froxlor\Validate\Validate::validate($_POST['subject'], 'subject', '/^[^\r\n\0]+$/', 'nosubjectcreate'); - $mailbody = \Froxlor\Validate\Validate::validate($_POST['mailbody'], 'mailbody', '/^[^\0]+$/', 'nomailbodycreate'); + $subject = Validate::validate($_POST['subject'], 'subject', '/^[^\r\n\0]+$/', 'nosubjectcreate'); + $mailbody = Validate::validate($_POST['mailbody'], 'mailbody', '/^[^\0]+$/', 'nomailbodycreate'); $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_TEMPLATES . "` SET `value` = :value WHERE `adminid` = :adminid AND `id` = :id"); // subject - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'value' => $subject, 'adminid' => $userinfo['adminid'], 'id' => $subjectid - )); + ]); // same query but mailbody - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'value' => $mailbody, 'adminid' => $userinfo['adminid'], 'id' => $mailbodyid - )); + ]); - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "edited template '" . $result['varname'] . "'"); - \Froxlor\UI\Response::redirectTo($filename, array( + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "edited template '" . $result['varname'] . "'"); + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - - $result = \Froxlor\PhpHelper::htmlentitiesArray($result); - $template_name = $lng['admin']['templates'][str_replace('_subject', '', $result['varname'])]; + $result = PhpHelper::htmlentitiesArray($result); + $template_name = lng('admin.templates.' . str_replace('_subject', '', $result['varname'])); $subject = $result['value']; $result_stmt = Database::prepare(" SELECT `language`, `varname`, `value` FROM `" . TABLE_PANEL_TEMPLATES . "` WHERE `id` = :id"); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'id' => $mailbodyid - )); + ]); $result = $result_stmt->fetch(PDO::FETCH_ASSOC); $template = str_replace('_mailbody', '', $result['varname']); // don't escape the already escaped language-string so save up before htmlentities() $language = $result['language']; - $result = \Froxlor\PhpHelper::htmlentitiesArray($result); + $result = PhpHelper::htmlentitiesArray($result); $mailbody = $result['value']; $template_edit_data = include_once dirname(__FILE__) . '/lib/formfields/admin/templates/formfield.template_edit.php'; UI::view('user/form-replacers.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'templates')), + 'formaction' => $linker->getLink(['section' => 'templates']), 'formdata' => $template_edit_data['template_edit'], 'replacers' => $template_edit_data['template_replacers'] ]); @@ -515,45 +530,44 @@ if ($action == '') { $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_TEMPLATES . "` WHERE `adminid` = :adminid AND `id` = :id"); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'adminid' => $userinfo['adminid'], 'id' => $id - )); + ]); if (Database::num_rows() > 0) { - $row = $result_stmt->fetch(PDO::FETCH_ASSOC); // filetemplates if (isset($_POST['filesend']) && $_POST['filesend'] == 'filesend') { - $filecontent = \Froxlor\Validate\Validate::validate($_POST['filecontent'], 'filecontent', '/^[^\0]+$/', 'filecontentnotset'); + $filecontent = Validate::validate($_POST['filecontent'], 'filecontent', '/^[^\0]+$/', 'filecontentnotset'); $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_TEMPLATES . "` SET `value` = :value WHERE `adminid` = :adminid AND `id` = :id"); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'value' => $filecontent, 'adminid' => $userinfo['adminid'], 'id' => $id - )); + ]); - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "edited template '" . $row['varname'] . "'"); - \Froxlor\UI\Response::redirectTo($filename, array( + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "edited template '" . $row['varname'] . "'"); + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - $row = \Froxlor\PhpHelper::htmlentitiesArray($row); + $row = PhpHelper::htmlentitiesArray($row); $filetemplate_edit_data = include_once dirname(__FILE__) . '/lib/formfields/admin/templates/formfield.filetemplate_edit.php'; UI::view('user/form-replacers.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'templates')), + 'formaction' => $linker->getLink(['section' => 'templates']), 'formdata' => $filetemplate_edit_data['filetemplate_edit'], 'replacers' => $filetemplate_edit_data['filetemplate_replacers'], 'editid' => $id ]); } } else { - \Froxlor\UI\Response::standard_error('templatenotfound'); + Response::standardError('templatenotfound'); } } diff --git a/admin_traffic.php b/admin_traffic.php index da074a89..0077f63d 100644 --- a/admin_traffic.php +++ b/admin_traffic.php @@ -2,31 +2,39 @@ /** * 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 Morton Jonuschat - * @license GPLv2 http://files.syscp.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ const AREA = 'admin'; require __DIR__ . '/lib/init.php'; use Froxlor\Database\Database; +use Froxlor\PhpHelper; use Froxlor\Settings; use Froxlor\UI\Panel\UI; use Froxlor\UI\Request; -$id = (int) Request::get('id'); +$id = (int)Request::get('id'); -$months = array( +$months = [ '0' => 'empty', '1' => 'jan', '2' => 'feb', @@ -40,13 +48,13 @@ $months = array( '10' => 'oct', '11' => 'nov', '12' => 'dec' -); +]; if ($page == 'overview' || $page == 'customers') { $minyear_stmt = Database::query("SELECT `year` FROM `" . TABLE_PANEL_TRAFFIC . "` ORDER BY `year` ASC LIMIT 1"); $minyear = $minyear_stmt->fetch(PDO::FETCH_ASSOC); - if (! isset($minyear['year']) || $minyear['year'] == 0) { + if (!isset($minyear['year']) || $minyear['year'] == 0) { $maxyears = 0; } else { $maxyears = date("Y") - $minyear['year']; @@ -63,20 +71,18 @@ if ($page == 'overview' || $page == 'customers') { SELECT `customerid`,`company`,`name`,`firstname` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `deactivated`='0'" . ($userinfo['customers_see_all'] ? '' : ' AND `adminid` = :id') . " - ORDER BY name" - ); + ORDER BY name"); $traffic_list_stmt = Database::prepare(" SELECT month, SUM(http+ftp_up+ftp_down+mail)*1024 AS traffic FROM `" . TABLE_PANEL_TRAFFIC . "` WHERE year = :year AND `customerid` = :id - GROUP BY month ORDER BY month" - ); + GROUP BY month ORDER BY month"); $stats = []; - for ($years = 0; $years <= $maxyears; $years ++) { - $totals = array( + for ($years = 0; $years <= $maxyears; $years++) { + $totals = [ 'jan' => 0, 'feb' => 0, 'mar' => 0, @@ -89,13 +95,13 @@ if ($page == 'overview' || $page == 'customers') { 'oct' => 0, 'nov' => 0, 'dec' => 0 - ); + ]; Database::pexecute($customer_name_list_stmt, $params); $data = []; while ($customer_name = $customer_name_list_stmt->fetch(PDO::FETCH_ASSOC)) { - $virtual_host = array( + $virtual_host = [ 'name' => ($customer_name['company'] == '' ? $customer_name['name'] . ", " . $customer_name['firstname'] : $customer_name['company']), 'customerid' => $customer_name['customerid'], 'jan' => '-', @@ -110,23 +116,23 @@ if ($page == 'overview' || $page == 'customers') { 'oct' => '-', 'nov' => '-', 'dec' => '-' - ); + ]; - Database::pexecute($traffic_list_stmt, array( + Database::pexecute($traffic_list_stmt, [ 'year' => (date("Y") - $years), 'id' => $customer_name['customerid'] - )); + ]); while ($traffic_month = $traffic_list_stmt->fetch(PDO::FETCH_ASSOC)) { - $virtual_host[$months[(int) $traffic_month['month']]] = \Froxlor\PhpHelper::sizeReadable($traffic_month['traffic'], 'GiB', 'bi', '%01.' . (int) Settings::Get('panel.decimal_places') . 'f %s'); - $totals[$months[(int) $traffic_month['month']]] += $traffic_month['traffic']; + $virtual_host[$months[(int)$traffic_month['month']]] = PhpHelper::sizeReadable($traffic_month['traffic'], 'GiB', 'bi', '%01.' . (int)Settings::Get('panel.decimal_places') . 'f %s'); + $totals[$months[(int)$traffic_month['month']]] += $traffic_month['traffic']; } $data = $virtual_host; } $stats[] = [ 'year' => date("Y") - $years, - 'type' => $lng['traffic']['customer'], + 'type' => lng('traffic.customer'), 'data' => $data, ]; } diff --git a/admin_updates.php b/admin_updates.php index 9d3e66e1..4b79a87b 100644 --- a/admin_updates.php +++ b/admin_updates.php @@ -4,33 +4,47 @@ * 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 (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ const AREA = 'admin'; require __DIR__ . '/lib/init.php'; +use Froxlor\Cron\TaskId; use Froxlor\Database\Database; +use Froxlor\Froxlor; +use Froxlor\FroxlorLogger; use Froxlor\Settings; +use Froxlor\System\Cronjob; use Froxlor\UI\Panel\UI; +use Froxlor\UI\Response; +use Froxlor\User; if ($page == 'overview') { - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_updates"); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_updates"); /** * this is a dirty hack but syscp 1.4.2.1 does not * have any version/dbversion in the database (don't know why) * so we have to set them both to run a correct upgrade */ - if (!\Froxlor\Froxlor::isFroxlor()) { + if (!Froxlor::isFroxlor()) { if (Settings::Get('panel.version') == null || Settings::Get('panel.version') == '') { Settings::Set('panel.version', '1.4.2.1'); } @@ -46,25 +60,24 @@ if ($page == 'overview') { $result = $result_stmt->fetch(PDO::FETCH_ASSOC); if (isset($result['value'])) { - Settings::Set('system.dbversion', (int) $result['value'], false); + Settings::Set('system.dbversion', (int)$result['value'], false); } else { Settings::Set('system.dbversion', 0, false); } } } - if (\Froxlor\Froxlor::hasDbUpdates() || \Froxlor\Froxlor::hasUpdates()) { + if (Froxlor::hasDbUpdates() || Froxlor::hasUpdates()) { $successful_update = false; $message = ''; if (isset($_POST['send']) && $_POST['send'] == 'send') { if ((isset($_POST['update_preconfig']) && isset($_POST['update_changesagreed']) && intval($_POST['update_changesagreed']) != 0) || !isset($_POST['update_preconfig'])) { + include_once Froxlor::getInstallDir() . 'install/updatesql.php'; - include_once \Froxlor\Froxlor::getInstallDir() . 'install/updatesql.php'; - - \Froxlor\User::updateCounters(); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); - @chmod(\Froxlor\Froxlor::getInstallDir() . '/lib/userdata.inc.php', 0400); + User::updateCounters(); + Cronjob::inserttask(TaskId::REBUILD_VHOST); + @chmod(Froxlor::getInstallDir() . '/lib/userdata.inc.php', 0400); UI::view('install/update.html.twig', [ 'checks' => $update_tasks @@ -80,11 +93,11 @@ if ($page == 'overview') { if (empty($current_db_version)) { $current_db_version = "0"; } - $new_version = \Froxlor\Froxlor::VERSION; - $new_db_version = \Froxlor\Froxlor::DBVERSION; + $new_version = Froxlor::VERSION; + $new_db_version = Froxlor::DBVERSION; - $ui_text = $lng['update']['update_information']['part_a']; - if (\Froxlor\Froxlor::VERSION != $current_version) { + $ui_text = lng('update.update_information.part_a'); + if (Froxlor::VERSION != $current_version) { $ui_text = str_replace('%curversion', $current_version, $ui_text); $ui_text = str_replace('%newversion', $new_version, $ui_text); } else { @@ -92,36 +105,36 @@ if ($page == 'overview') { $ui_text = str_replace('%curversion', $current_db_version, $ui_text); $ui_text = str_replace('%newversion', $new_db_version, $ui_text); } - $ui_text .= $lng['update']['update_information']['part_b']; + $ui_text .= lng('update.update_information.part_b'); $upd_formfield = [ 'updates' => [ - 'title' => $lng['update']['update'], + 'title' => lng('update.update'), 'image' => 'fa-solid fa-download', - 'description' => $lng['update']['description'], + 'description' => lng('update.description'), 'sections' => [], 'buttons' => [ [ - 'label' => $lng['update']['proceed'] + 'label' => lng('update.proceed') ] ] ] ]; - include_once \Froxlor\Froxlor::getInstallDir() . '/install/updates/preconfig.php'; + include_once Froxlor::getInstallDir() . '/install/updates/preconfig.php'; $preconfig = getPreConfig($current_version, $current_db_version); if (!empty($preconfig)) { $upd_formfield['updates']['sections'] = $preconfig; } UI::view('user/form-note.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'updates')), + 'formaction' => $linker->getLink(['section' => 'updates']), 'formdata' => $upd_formfield['updates'], // alert 'type' => !empty($message) ? 'danger' : 'info', 'alert_msg' => $ui_text . $message ]); } else { - \Froxlor\UI\Response::standard_success('noupdatesavail'); + Response::standardSuccess('noupdatesavail'); } } diff --git a/api.php b/api.php index 1b2861c9..c4b02611 100644 --- a/api.php +++ b/api.php @@ -11,16 +11,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 + * 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 - * http://files.froxlor.org/misc/COPYING.txt + * https://files.froxlor.org/misc/COPYING.txt * * @copyright the authors * @author Froxlor team - * @license http://files.froxlor.org/misc/COPYING.txt GPLv2 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ use Froxlor\Api\Api; @@ -32,7 +32,7 @@ require __DIR__ . '/lib/tables.inc.php'; // Return response try { - echo (new Api)->formatMiddleware(@file_get_contents('php://input'))->handle(); + echo (new Api)->formatMiddleware(@file_get_contents('php://input'))->handle(); } catch (Exception $e) { - echo Response::jsonErrorResponse($e->getMessage(), $e->getCode()); + echo Response::jsonErrorResponse($e->getMessage(), $e->getCode()); } diff --git a/api_keys.php b/api_keys.php index 0c1e0835..fe9ed76e 100644 --- a/api_keys.php +++ b/api_keys.php @@ -1,26 +1,37 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + if (!defined('AREA')) { header("Location: index.php"); exit(); } -/** - * This file is part of the Froxlor project. - * Copyright (c) 2018 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 - * - * @copyright (c) the authors - * @author Froxlor team (2018-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel - * @since 0.10.0 - * - */ - use Froxlor\Database\Database; +use Froxlor\FroxlorLogger; +use Froxlor\UI\HTML; +use Froxlor\UI\Listing; use Froxlor\UI\Panel\UI; use Froxlor\UI\Request; @@ -29,15 +40,15 @@ use Froxlor\UI\Request; $del_stmt = Database::prepare("DELETE FROM `" . TABLE_API_KEYS . "` WHERE id = :id"); $success_message = ""; -$id = (int) Request::get('id'); +$id = (int)Request::get('id'); // do the delete and then just show a success-message and the apikeys list again if ($action == 'delete' && $id > 0) { - \Froxlor\UI\HTML::askYesNo('apikey_reallydelete', $filename, array( + HTML::askYesNo('apikey_reallydelete', $filename, [ 'id' => $id, 'page' => $page, 'action' => 'deletesure' - ), '', [ + ], '', [ 'section' => 'index', 'page' => $page ]); @@ -49,26 +60,26 @@ if ($action == 'delete' && $id > 0) { LEFT JOIN `" . TABLE_API_KEYS . "` ak ON ak.customerid = c.customerid WHERE ak.`id` = :id AND c.`customerid` = :cid "); - $chk = Database::pexecute_first($chk_stmt, array( + $chk = Database::pexecute_first($chk_stmt, [ 'id' => $id, 'cid' => $userinfo['customerid'] - )); + ]); } elseif (AREA == 'admin' && $userinfo['customers_see_all'] == '0') { $chk_stmt = Database::prepare(" SELECT a.adminid FROM `" . TABLE_PANEL_ADMINS . "` a LEFT JOIN `" . TABLE_API_KEYS . "` ak ON ak.adminid = a.adminid WHERE ak.`id` = :id AND a.`adminid` = :aid "); - $chk = Database::pexecute_first($chk_stmt, array( + $chk = Database::pexecute_first($chk_stmt, [ 'id' => $id, 'aid' => $userinfo['adminid'] - )); + ]); } if ($chk !== false) { - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'id' => $id - )); - $success_message = sprintf($lng['apikeys']['apikey_removed'], $id); + ]); + $success_message = lng('apikeys.apikey_removed', [$id]); } } elseif ($action == 'add') { $ins_stmt = Database::prepare(" @@ -83,16 +94,16 @@ if ($action == 'delete' && $id > 0) { } $key = hash('sha256', openssl_random_pseudo_bytes(64 * 64)); $secret = hash('sha512', openssl_random_pseudo_bytes(64 * 64 * 4)); - Database::pexecute($ins_stmt, array( + Database::pexecute($ins_stmt, [ 'key' => $key, 'secret' => $secret, 'aid' => $userinfo['adminid'], 'cid' => $cid - )); - $success_message = $lng['apikeys']['apikey_added']; + ]); + $success_message = lng('apikeys.apikey_added'); } -$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed api::api_keys"); +$log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed api::api_keys"); // select all my (accessible) api-keys $keys_stmt_query = "SELECT ak.*, c.loginname, a.loginname as adminname @@ -101,27 +112,27 @@ $keys_stmt_query = "SELECT ak.*, c.loginname, a.loginname as adminname LEFT JOIN `" . TABLE_PANEL_ADMINS . "` a ON `a`.`adminid` = `ak`.`adminid` WHERE "; -$qry_params = array(); +$qry_params = []; if (AREA == 'admin' && $userinfo['customers_see_all'] == '0') { // admin with only customer-specific permissions $keys_stmt_query .= "ak.adminid = :adminid "; $qry_params['adminid'] = $userinfo['adminid']; - $fields = array( - 'a.loginname' => $lng['login']['username'] - ); + $fields = [ + 'a.loginname' => lng('login.username') + ]; } elseif (AREA == 'customer') { // customer-area $keys_stmt_query .= "ak.customerid = :cid "; $qry_params['cid'] = $userinfo['customerid']; - $fields = array( - 'c.loginname' => $lng['login']['username'] - ); + $fields = [ + 'c.loginname' => lng('login.username') + ]; } else { // admin who can see all customers / reseller / admins $keys_stmt_query .= "1 "; - $fields = array( - 'a.loginname' => $lng['login']['username'] - ); + $fields = [ + 'a.loginname' => lng('login.username') + ]; } //$keys_stmt_query .= $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit(); @@ -142,11 +153,13 @@ if (!empty($success_message)) { } UI::view($tpl, [ - 'listing' => \Froxlor\UI\Listing::formatFromArray($collection, $apikeys_list_data['apikeys_list']), - 'actions_links' => (int)$userinfo['api_allowed'] == 1 ? [[ - 'href' => $linker->getLink(['section' => 'index', 'page' => $page, 'action' => 'add']), - 'label' => $lng['apikeys']['key_add'] - ]] : null, + 'listing' => Listing::formatFromArray($collection, $apikeys_list_data['apikeys_list']), + 'actions_links' => (int)$userinfo['api_allowed'] == 1 ? [ + [ + 'href' => $linker->getLink(['section' => 'index', 'page' => $page, 'action' => 'add']), + 'label' => lng('apikeys.key_add') + ] + ] : null, // alert-box 'type' => 'success', 'alert_msg' => $success_message diff --git a/bin/froxlor-cli b/bin/froxlor-cli index c2fba361..29753950 100755 --- a/bin/froxlor-cli +++ b/bin/froxlor-cli @@ -1,6 +1,29 @@ #!/usr/bin/env php + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + declare(strict_types=1); use Symfony\Component\Console\Application; diff --git a/customer_domains.php b/customer_domains.php index e6918a93..1bd5889d 100644 --- a/customer_domains.php +++ b/customer_domains.php @@ -2,99 +2,117 @@ /** * 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 (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + const AREA = 'customer'; require __DIR__ . '/lib/init.php'; use Froxlor\Api\Commands\SubDomains as SubDomains; use Froxlor\Database\Database; +use Froxlor\Domain\Domain; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; +use Froxlor\PhpHelper; use Froxlor\Settings; +use Froxlor\UI\Collection; +use Froxlor\UI\HTML; +use Froxlor\UI\Listing; use Froxlor\UI\Panel\UI; use Froxlor\UI\Request; +use Froxlor\UI\Response; +use Froxlor\Validate\Validate; // redirect if this customer page is hidden via settings if (Settings::IsInList('panel.customer_hide_options', 'domains')) { - \Froxlor\UI\Response::redirectTo('customer_index.php'); + Response::redirectTo('customer_index.php'); } -$id = (int) Request::get('id'); +$id = (int)Request::get('id'); if ($page == 'overview' || $page == 'domains') { if ($action == '') { - $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_domains::domains"); + $log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_domains::domains"); - $parentdomain_id = (int) Request::get('pid', '0'); + $parentdomain_id = (int)Request::get('pid', '0'); try { $domain_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.domains.php'; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\SubDomains::class, $userinfo)) + $collection = (new Collection(SubDomains::class, $userinfo)) //->addParam(['sql_search' => ['d.parentdomainid' => $parentdomain_id]]) ->withPagination($domain_list_data['domain_list']['columns']); - $parentDomainCollection = (new \Froxlor\UI\Collection(SubDomains::class, $userinfo, ['sql_search' => ['d.parentdomainid' => 0]])); + $parentDomainCollection = (new Collection(SubDomains::class, $userinfo, ['sql_search' => ['d.parentdomainid' => 0]])); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $actions_links = false; if (($userinfo['subdomains_used'] < $userinfo['subdomains'] || $userinfo['subdomains'] == '-1') && $parentDomainCollection->count() != 0) { - $actions_links = [[ - 'href' => $linker->getLink(['section' => 'domains', 'page' => 'domains', 'action' => 'add']), - 'label' => $lng['domains']['subdomain_add'] - ]]; + $actions_links = [ + [ + 'href' => $linker->getLink(['section' => 'domains', 'page' => 'domains', 'action' => 'add']), + 'label' => lng('domains.subdomain_add') + ] + ]; } UI::view('user/table.html.twig', [ - 'listing' => \Froxlor\UI\Listing::format($collection, $domain_list_data, 'domain_list') , + 'listing' => Listing::format($collection, $domain_list_data, 'domain_list'), 'actions_links' => $actions_links, - 'entity_info' => $lng['domains']['description'] + 'entity_info' => lng('domains.description') ]); } elseif ($action == 'delete' && $id != 0) { try { - $json_result = SubDomains::getLocal($userinfo, array( + $json_result = SubDomains::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; $alias_stmt = Database::prepare("SELECT COUNT(`id`) AS `count` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `aliasdomain` = :aliasdomain"); - $alias_check = Database::pexecute_first($alias_stmt, array( + $alias_check = Database::pexecute_first($alias_stmt, [ "aliasdomain" => $id - )); + ]); if (isset($result['parentdomainid']) && $result['parentdomainid'] != '0' && $alias_check['count'] == 0) { if (isset($_POST['send']) && $_POST['send'] == 'send') { try { SubDomains::getLocal($userinfo, $_POST)->delete(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - \Froxlor\UI\HTML::askYesNo('domains_reallydelete', $filename, array( + HTML::askYesNo('domains_reallydelete', $filename, [ 'id' => $id, 'page' => $page, 'action' => $action - ), $idna_convert->decode($result['domain'])); + ], $idna_convert->decode($result['domain'])); } } else { - \Froxlor\UI\Response::standard_error('domains_cantdeletemaindomain'); + Response::standardError('domains_cantdeletemaindomain'); } } elseif ($action == 'add') { if ($userinfo['subdomains_used'] < $userinfo['subdomains'] || $userinfo['subdomains'] == '-1') { @@ -102,11 +120,11 @@ if ($page == 'overview' || $page == 'domains') { try { SubDomains::getLocal($userinfo, $_POST)->add(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { $stmt = Database::prepare("SELECT `id`, `domain`, `documentroot`, `ssl_redirect`,`isemaildomain`,`letsencrypt` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :customerid @@ -114,15 +132,15 @@ if ($page == 'overview' || $page == 'domains') { AND `email_only` = '0' AND `caneditdomain` = '1' ORDER BY `domain` ASC"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "customerid" => $userinfo['customerid'] - )); + ]); $domains = []; while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { $domains[$row['domain']] = $idna_convert->decode($row['domain']); } - $aliasdomains[0] = $lng['domains']['noaliasdomain']; + $aliasdomains[0] = lng('domains.noaliasdomain'); $domains_stmt = Database::prepare("SELECT `d`.`id`, `d`.`domain` FROM `" . TABLE_PANEL_DOMAINS . "` `d`, `" . TABLE_PANEL_CUSTOMERS . "` `c` WHERE `d`.`aliasdomain` IS NULL AND `d`.`id` <> `c`.`standardsubdomain` @@ -131,9 +149,9 @@ if ($page == 'overview' || $page == 'domains') { AND `d`.`email_only`='0' AND `d`.`customerid`= :customerid ORDER BY `d`.`domain` ASC"); - Database::pexecute($domains_stmt, array( + Database::pexecute($domains_stmt, [ "customerid" => $userinfo['customerid'] - )); + ]); while ($row_domain = $domains_stmt->fetch(PDO::FETCH_ASSOC)) { $aliasdomains[$row_domain['id']] = $idna_convert->decode($row_domain['domain']); @@ -141,9 +159,9 @@ if ($page == 'overview' || $page == 'domains') { $redirectcode = []; if (Settings::Get('customredirect.enabled') == '1') { - $codes = \Froxlor\Domain\Domain::getRedirectCodesArray(); + $codes = Domain::getRedirectCodesArray(); foreach ($codes as $rc) { - $redirectcode[$rc['id']] = $rc['code'] . ' (' . $lng['redirect_desc'][$rc['desc']] . ')'; + $redirectcode[$rc['id']] = $rc['code'] . ' (' . lng('redirect_desc.' . $rc['desc']) . ')'; } } @@ -157,15 +175,15 @@ if ($page == 'overview' || $page == 'domains') { "); Database::pexecute($ssl_ip_stmt); $resultX = $ssl_ip_stmt->fetch(PDO::FETCH_ASSOC); - if (isset($resultX['countSSL']) && (int) $resultX['countSSL'] > 0) { + if (isset($resultX['countSSL']) && (int)$resultX['countSSL'] > 0) { $ssl_ipsandports = true; } $openbasedir = [ - 0 => $lng['domain']['docroot'], - 1 => $lng['domain']['homedir'] + 0 => lng('domain.docroot'), + 1 => lng('domain.homedir') ]; - $pathSelect = \Froxlor\FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']); + $pathSelect = FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']); $phpconfigs = []; if (isset($userinfo['allowed_phpconfigs']) && !empty($userinfo['allowed_phpconfigs'])) { @@ -177,7 +195,7 @@ if ($page == 'overview' || $page == 'domains') { WHERE c.id IN (" . implode(", ", $allowed_cfg) . ") "); while ($phpconfigs_row = $phpconfigs_result_stmt->fetch(PDO::FETCH_ASSOC)) { - if ((int) Settings::Get('phpfpm.enabled') == 1) { + if ((int)Settings::Get('phpfpm.enabled') == 1) { $phpconfigs[$phpconfigs_row['id']] = $phpconfigs_row['description'] . " [" . $phpconfigs_row['interpreter'] . "]"; } else { $phpconfigs[$phpconfigs_row['id']] = $phpconfigs_row['description']; @@ -188,19 +206,18 @@ if ($page == 'overview' || $page == 'domains') { $subdomain_add_data = include_once dirname(__FILE__) . '/lib/formfields/customer/domains/formfield.domains_add.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'domains')), + 'formaction' => $linker->getLink(['section' => 'domains']), 'formdata' => $subdomain_add_data['domain_add'] ]); } } } elseif ($action == 'edit' && $id != 0) { - try { - $json_result = SubDomains::getLocal($userinfo, array( + $json_result = SubDomains::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; @@ -209,15 +226,15 @@ if ($page == 'overview' || $page == 'domains') { try { SubDomains::getLocal($userinfo, $_POST)->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { $result['domain'] = $idna_convert->decode($result['domain']); - $domains[0] = $lng['domains']['noaliasdomain']; + $domains[0] = lng('domains.noaliasdomain'); // also check ip/port combination to be the same, #176 $domains_stmt = Database::prepare("SELECT `d`.`id`, `d`.`domain` FROM `" . TABLE_PANEL_DOMAINS . "` `d` , `" . TABLE_PANEL_CUSTOMERS . "` `c` , `" . TABLE_DOMAINTOIP . "` `dip` WHERE `d`.`aliasdomain` IS NULL @@ -232,34 +249,34 @@ if ($page == 'overview' || $page == 'domains') { WHERE `id_domain` = :id) GROUP BY `d`.`id`, `d`.`domain` ORDER BY `d`.`domain` ASC"); - Database::pexecute($domains_stmt, array( + Database::pexecute($domains_stmt, [ "id" => $result['id'], "customerid" => $userinfo['customerid'] - )); + ]); while ($row_domain = $domains_stmt->fetch(PDO::FETCH_ASSOC)) { $domains[$row_domain['id']] = $idna_convert->decode($row_domain['domain']); } - if (preg_match('/^https?\:\/\//', $result['documentroot']) && \Froxlor\Validate\Validate::validateUrl($result['documentroot'])) { + if (preg_match('/^https?\:\/\//', $result['documentroot']) && Validate::validateUrl($result['documentroot'])) { if (Settings::Get('panel.pathedit') == 'Dropdown') { $urlvalue = $result['documentroot']; - $pathSelect = \Froxlor\FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']); + $pathSelect = FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']); } else { $urlvalue = ''; - $pathSelect = \Froxlor\FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid'], $result['documentroot'], true); + $pathSelect = FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid'], $result['documentroot'], true); } } else { $urlvalue = ''; - $pathSelect = \Froxlor\FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid'], $result['documentroot']); + $pathSelect = FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid'], $result['documentroot']); } $redirectcode = []; if (Settings::Get('customredirect.enabled') == '1') { - $def_code = \Froxlor\Domain\Domain::getDomainRedirectId($id); - $codes = \Froxlor\Domain\Domain::getRedirectCodesArray(); + $def_code = Domain::getDomainRedirectId($id); + $codes = Domain::getRedirectCodesArray(); foreach ($codes as $rc) { - $redirectcode[$rc['id']] = $rc['code'] . ' (' . $lng['redirect_desc'][$rc['desc']] . ')'; + $redirectcode[$rc['id']] = $rc['code'] . ' (' . lng('redirect_desc.' . $rc['desc']) . ')'; } } @@ -271,11 +288,11 @@ if ($page == 'overview' || $page == 'domains') { LEFT JOIN `" . TABLE_DOMAINTOIP . "` dti ON dti.id_ipandports = pip.id WHERE `dti`.`id_domain` = :id_domain AND pip.`ssl`='1' "); - Database::pexecute($ssl_ip_stmt, array( + Database::pexecute($ssl_ip_stmt, [ "id_domain" => $result['id'] - )); + ]); $resultX = $ssl_ip_stmt->fetch(PDO::FETCH_ASSOC); - if (isset($resultX['countSSL']) && (int) $resultX['countSSL'] > 0) { + if (isset($resultX['countSSL']) && (int)$resultX['countSSL'] > 0) { $ssl_ipsandports = true; } @@ -284,8 +301,8 @@ if ($page == 'overview' || $page == 'domains') { $result['ssl_redirect'] = ($result['ssl_redirect'] == 0 ? 0 : 1); $openbasedir = [ - 0 => $lng['domain']['docroot'], - 1 => $lng['domain']['homedir'] + 0 => lng('domain.docroot'), + 1 => lng('domain.homedir') ]; // create serveralias options @@ -296,18 +313,18 @@ if ($page == 'overview' || $page == 'domains') { } elseif ($result['wwwserveralias'] == '1') { $serveraliasoptions_selected = '1'; } - $serveraliasoptions[0] = $lng['domains']['serveraliasoption_wildcard']; - $serveraliasoptions[1] = $lng['domains']['serveraliasoption_www']; - $serveraliasoptions[2] = $lng['domains']['serveraliasoption_none']; + $serveraliasoptions[0] = lng('domains.serveraliasoption_wildcard'); + $serveraliasoptions[1] = lng('domains.serveraliasoption_www'); + $serveraliasoptions[2] = lng('domains.serveraliasoption_none'); $ips_stmt = Database::prepare("SELECT `p`.`ip` AS `ip` FROM `" . TABLE_PANEL_IPSANDPORTS . "` `p` LEFT JOIN `" . TABLE_DOMAINTOIP . "` `dip` ON ( `dip`.`id_ipandports` = `p`.`id` ) WHERE `dip`.`id_domain` = :id_domain GROUP BY `p`.`ip`"); - Database::pexecute($ips_stmt, array( + Database::pexecute($ips_stmt, [ "id_domain" => $result['id'] - )); + ]); $domainips = []; while ($rowip = $ips_stmt->fetch(PDO::FETCH_ASSOC)) { $domainips[] = ['item' => $rowip['ip']]; @@ -323,7 +340,7 @@ if ($page == 'overview' || $page == 'domains') { WHERE c.id IN (" . implode(", ", $allowed_cfg) . ") "); while ($phpconfigs_row = $phpconfigs_result_stmt->fetch(PDO::FETCH_ASSOC)) { - if ((int) Settings::Get('phpfpm.enabled') == 1) { + if ((int)Settings::Get('phpfpm.enabled') == 1) { $phpconfigs[$phpconfigs_row['id']] = $phpconfigs_row['description'] . " [" . $phpconfigs_row['interpreter'] . "]"; } else { $phpconfigs[$phpconfigs_row['id']] = $phpconfigs_row['description']; @@ -332,35 +349,31 @@ if ($page == 'overview' || $page == 'domains') { } $alias_stmt = Database::prepare("SELECT COUNT(`id`) AS count FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `aliasdomain`= :aliasdomain"); - $alias_check = Database::pexecute_first($alias_stmt, array( + $alias_check = Database::pexecute_first($alias_stmt, [ "aliasdomain" => $result['id'] - )); + ]); $alias_check = $alias_check['count']; - $result = \Froxlor\PhpHelper::htmlentitiesArray($result); + $result = PhpHelper::htmlentitiesArray($result); $subdomain_edit_data = include_once dirname(__FILE__) . '/lib/formfields/customer/domains/formfield.domains_edit.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'domains', 'id' => $id)), + 'formaction' => $linker->getLink(['section' => 'domains', 'id' => $id]), 'formdata' => $subdomain_edit_data['domain_edit'], 'editid' => $id ]); } } else { - \Froxlor\UI\Response::standard_error('domains_canteditdomain'); + Response::standardError('domains_canteditdomain'); } } } elseif ($page == 'domainssleditor') { - require_once __DIR__ . '/ssl_editor.php'; } elseif ($page == 'domaindnseditor' && $userinfo['dnsenabled'] == '1' && Settings::Get('system.dnsenabled') == '1') { - require_once __DIR__ . '/dns_editor.php'; } elseif ($page == 'sslcertificates') { - require_once __DIR__ . '/ssl_certificates.php'; } elseif ($page == 'logfiles') { - require_once __DIR__ . '/logfiles_viewer.php'; } diff --git a/customer_email.php b/customer_email.php index 27778ab5..b01355d9 100644 --- a/customer_email.php +++ b/customer_email.php @@ -2,20 +2,27 @@ /** * 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 (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + const AREA = 'customer'; require __DIR__ . '/lib/init.php'; @@ -23,27 +30,34 @@ use Froxlor\Api\Commands\EmailAccounts as EmailAccounts; use Froxlor\Api\Commands\EmailForwarders as EmailForwarders; use Froxlor\Api\Commands\Emails as Emails; use Froxlor\Database\Database; +use Froxlor\FroxlorLogger; +use Froxlor\PhpHelper; use Froxlor\Settings; +use Froxlor\UI\Collection; +use Froxlor\UI\HTML; +use Froxlor\UI\Listing; use Froxlor\UI\Panel\UI; use Froxlor\UI\Request; +use Froxlor\UI\Response; +use Froxlor\Validate\Check; // redirect if this customer page is hidden via settings if (Settings::IsInList('panel.customer_hide_options', 'email')) { - \Froxlor\UI\Response::redirectTo('customer_index.php'); + Response::redirectTo('customer_index.php'); } -$id = (int) Request::get('id'); +$id = (int)Request::get('id'); if ($page == 'overview' || $page == 'emails') { if ($action == '') { - $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_email::emails"); + $log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_email::emails"); try { $email_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.emails.php'; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Emails::class, $userinfo)) + $collection = (new Collection(Emails::class, $userinfo)) ->withPagination($email_list_data['email_list']['columns']); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result_stmt = Database::prepare(" @@ -51,58 +65,60 @@ if ($page == 'overview' || $page == 'emails') { FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid`= :cid AND `isemaildomain` = '1' "); - $result2 = Database::pexecute_first($result_stmt, array( + $result2 = Database::pexecute_first($result_stmt, [ "cid" => $userinfo['customerid'] - )); + ]); $emaildomains_count = $result2['emaildomains']; $actions_links = false; if (($userinfo['emails_used'] < $userinfo['emails'] || $userinfo['emails'] == '-1') && $emaildomains_count != 0) { - $actions_links = [[ - 'href' => $linker->getLink(['section' => 'email', 'page' => $page, 'action' => 'add']), - 'label' => $lng['emails']['emails_add'] - ]]; + $actions_links = [ + [ + 'href' => $linker->getLink(['section' => 'email', 'page' => $page, 'action' => 'add']), + 'label' => lng('emails.emails_add') + ] + ]; } UI::view('user/table.html.twig', [ - 'listing' => \Froxlor\UI\Listing::format($collection, $email_list_data, 'email_list') , + 'listing' => Listing::format($collection, $email_list_data, 'email_list'), 'actions_links' => $actions_links, - 'entity_info' => $lng['emails']['description'] + 'entity_info' => lng('emails.description') ]); } elseif ($action == 'delete' && $id != 0) { try { - $json_result = Emails::getLocal($userinfo, array( + $json_result = Emails::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; if (isset($result['email']) && $result['email'] != '') { if (isset($_POST['send']) && $_POST['send'] == 'send') { try { - Emails::getLocal($userinfo, array( + Emails::getLocal($userinfo, [ 'id' => $id, 'delete_userfiles' => ($_POST['delete_userfiles'] ?? 0) - ))->delete(); + ])->delete(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { if ($result['popaccountid'] != '0') { $show_checkbox = true; } else { $show_checkbox = false; } - \Froxlor\UI\HTML::askYesNoWithCheckbox('email_reallydelete', 'admin_customer_alsoremovemail', $filename, array( + HTML::askYesNoWithCheckbox('email_reallydelete', 'admin_customer_alsoremovemail', $filename, [ 'id' => $id, 'page' => $page, 'action' => $action - ), $idna_convert->decode($result['email_full']), $show_checkbox); + ], $idna_convert->decode($result['email_full']), $show_checkbox); } } } elseif ($action == 'add') { @@ -111,22 +127,22 @@ if ($page == 'overview' || $page == 'emails') { try { $json_result = Emails::getLocal($userinfo, $_POST)->add(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page, 'action' => 'edit', 'id' => $result['id'] - )); + ]); } else { $result_stmt = Database::prepare("SELECT `id`, `domain`, `customerid` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid`= :cid AND `isemaildomain`='1' ORDER BY `domain_ace` ASC"); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ "cid" => $userinfo['customerid'] - )); + ]); $domains = []; while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $domains[$row['domain']] = $idna_convert->decode($row['domain']); @@ -139,23 +155,23 @@ if ($page == 'overview' || $page == 'emails') { unset($email_add_data['emails_add']['sections']['section_a']['fields']['iscatchall']); } UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'email')), + 'formaction' => $linker->getLink(['section' => 'email']), 'formdata' => $email_add_data['emails_add'] ]); } else { - \Froxlor\UI\Response::standard_error('noemaildomainaddedyet'); + Response::standardError('noemaildomainaddedyet'); } } } else { - \Froxlor\UI\Response::standard_error('allresourcesused'); + Response::standardError('allresourcesused'); } } elseif ($action == 'edit' && $id != 0) { try { - $json_result = Emails::getLocal($userinfo, array( + $json_result = Emails::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; @@ -172,8 +188,14 @@ if ($page == 'overview' || $page == 'emails') { if ($destination != $result['email_full'] && $destination != '') { $forwarders[] = [ 'item' => $destination, - 'href' => $linker->getLink(array('section' => 'email', 'page' => 'forwarders', 'action' => 'delete', 'id' => $id, 'forwarderid' => $dest_id)), - 'label' => $lng['panel']['delete'], + 'href' => $linker->getLink([ + 'section' => 'email', + 'page' => 'forwarders', + 'action' => 'delete', + 'id' => $id, + 'forwarderid' => $dest_id + ]), + 'label' => lng('panel.delete'), 'classes' => 'btn btn-sm btn-danger' ]; $forwarders_count++; @@ -182,7 +204,7 @@ if ($page == 'overview' || $page == 'emails') { } $destinations_count = count($result['destination']); - $result = \Froxlor\PhpHelper::htmlentitiesArray($result); + $result = PhpHelper::htmlentitiesArray($result); $email_edit_data = include_once dirname(__FILE__) . '/lib/formfields/customer/email/formfield.emails_edit.php'; @@ -191,44 +213,44 @@ if ($page == 'overview' || $page == 'emails') { } UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'email')), + 'formaction' => $linker->getLink(['section' => 'email']), 'formdata' => $email_edit_data['emails_edit'], 'editid' => $id ]); } } elseif ($action == 'togglecatchall' && $id != 0) { try { - $json_result = Emails::getLocal($userinfo, array( + $json_result = Emails::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; try { - Emails::getLocal($userinfo, array( + Emails::getLocal($userinfo, [ 'id' => $id, 'iscatchall' => ($result['iscatchall'] == '1' ? 0 : 1) - ))->update(); + ])->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page, 'action' => 'edit', 'id' => $id - )); + ]); } } elseif ($page == 'accounts') { if ($action == 'add' && $id != 0) { if ($userinfo['email_accounts'] == '-1' || ($userinfo['email_accounts_used'] < $userinfo['email_accounts'])) { try { - $json_result = Emails::getLocal($userinfo, array( + $json_result = Emails::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; @@ -236,45 +258,44 @@ if ($page == 'overview' || $page == 'emails') { try { EmailAccounts::getLocal($userinfo, $_POST)->add(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => 'emails', 'action' => 'edit', 'id' => $id - )); + ]); } else { - - if (\Froxlor\Validate\Check::checkMailAccDeletionState($result['email_full'])) { - \Froxlor\UI\Response::standard_error(array( + if (Check::checkMailAccDeletionState($result['email_full'])) { + Response::standardError([ 'mailaccistobedeleted' - ), $result['email_full']); + ], $result['email_full']); } $result['email_full'] = $idna_convert->decode($result['email_full']); - $result = \Froxlor\PhpHelper::htmlentitiesArray($result); + $result = PhpHelper::htmlentitiesArray($result); $quota = Settings::Get('system.mail_quota'); $account_add_data = include_once dirname(__FILE__) . '/lib/formfields/customer/email/formfield.emails_addaccount.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'email', 'id' => $id)), + 'formaction' => $linker->getLink(['section' => 'email', 'id' => $id]), 'formdata' => $account_add_data['emails_addaccount'] ]); } } else { - \Froxlor\UI\Response::standard_error(array( + Response::standardError([ 'allresourcesused', 'allocatetoomuchquota' - ), $quota); + ], $quota); } } elseif ($action == 'changepw' && $id != 0) { try { - $json_result = Emails::getLocal($userinfo, array( + $json_result = Emails::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; @@ -283,32 +304,32 @@ if ($page == 'overview' || $page == 'emails') { try { EmailAccounts::getLocal($userinfo, $_POST)->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => 'emails', 'action' => 'edit', 'id' => $id - )); + ]); } else { $result['email_full'] = $idna_convert->decode($result['email_full']); - $result = \Froxlor\PhpHelper::htmlentitiesArray($result); + $result = PhpHelper::htmlentitiesArray($result); $account_changepw_data = include_once dirname(__FILE__) . '/lib/formfields/customer/email/formfield.emails_accountchangepasswd.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'email', 'id' => $id)), + 'formaction' => $linker->getLink(['section' => 'email', 'id' => $id]), 'formdata' => $account_changepw_data['emails_accountchangepasswd'] ]); } } } elseif ($action == 'changequota' && Settings::Get('system.mail_quota_enabled') == '1' && $id != 0) { try { - $json_result = Emails::getLocal($userinfo, array( + $json_result = Emails::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; @@ -317,32 +338,32 @@ if ($page == 'overview' || $page == 'emails') { try { EmailAccounts::getLocal($userinfo, $_POST)->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => 'emails', 'action' => 'edit', 'id' => $id - )); + ]); } else { $result['email_full'] = $idna_convert->decode($result['email_full']); - $result = \Froxlor\PhpHelper::htmlentitiesArray($result); + $result = PhpHelper::htmlentitiesArray($result); $quota_edit_data = include_once dirname(__FILE__) . '/lib/formfields/customer/email/formfield.emails_accountchangequota.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'email', 'id' => $id)), + 'formaction' => $linker->getLink(['section' => 'email', 'id' => $id]), 'formdata' => $quota_edit_data['emails_accountchangequota'] ]); } } } elseif ($action == 'delete' && $id != 0) { try { - $json_result = Emails::getLocal($userinfo, array( + $json_result = Emails::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; @@ -351,19 +372,19 @@ if ($page == 'overview' || $page == 'emails') { try { EmailAccounts::getLocal($userinfo, $_POST)->delete(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => 'emails', 'action' => 'edit', 'id' => $id - )); + ]); } else { - \Froxlor\UI\HTML::askYesNoWithCheckbox('email_reallydelete_account', 'admin_customer_alsoremovemail', $filename, array( + HTML::askYesNoWithCheckbox('email_reallydelete_account', 'admin_customer_alsoremovemail', $filename, [ 'id' => $id, 'page' => $page, 'action' => $action - ), $idna_convert->decode($result['email_full'])); + ], $idna_convert->decode($result['email_full'])); } } } @@ -371,11 +392,11 @@ if ($page == 'overview' || $page == 'emails') { if ($action == 'add' && $id != 0) { if ($userinfo['email_forwarders_used'] < $userinfo['email_forwarders'] || $userinfo['email_forwarders'] == '-1') { try { - $json_result = Emails::getLocal($userinfo, array( + $json_result = Emails::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; @@ -384,35 +405,35 @@ if ($page == 'overview' || $page == 'emails') { try { EmailForwarders::getLocal($userinfo, $_POST)->add(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => 'emails', 'action' => 'edit', 'id' => $id - )); + ]); } else { $result['email_full'] = $idna_convert->decode($result['email_full']); - $result = \Froxlor\PhpHelper::htmlentitiesArray($result); + $result = PhpHelper::htmlentitiesArray($result); $forwarder_add_data = include_once dirname(__FILE__) . '/lib/formfields/customer/email/formfield.emails_addforwarder.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'email', 'id' => $id)), + 'formaction' => $linker->getLink(['section' => 'email', 'id' => $id]), 'formdata' => $forwarder_add_data['emails_addforwarder'] ]); } } } else { - \Froxlor\UI\Response::standard_error('allresourcesused'); + Response::standardError('allresourcesused'); } } elseif ($action == 'delete' && $id != 0) { try { - $json_result = Emails::getLocal($userinfo, array( + $json_result = Emails::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; @@ -434,20 +455,20 @@ if ($page == 'overview' || $page == 'emails') { try { EmailForwarders::getLocal($userinfo, $_POST)->delete(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => 'emails', 'action' => 'edit', 'id' => $id - )); + ]); } else { - \Froxlor\UI\HTML::askYesNo('email_reallydelete_forwarder', $filename, array( + HTML::askYesNo('email_reallydelete_forwarder', $filename, [ 'id' => $id, 'forwarderid' => $forwarderid, 'page' => $page, 'action' => $action - ), $idna_convert->decode($result['email_full']) . ' -> ' . $idna_convert->decode($forwarder)); + ], $idna_convert->decode($result['email_full']) . ' -> ' . $idna_convert->decode($forwarder)); } } } diff --git a/customer_extras.php b/customer_extras.php index eb502fe2..58fd2d71 100644 --- a/customer_extras.php +++ b/customer_extras.php @@ -2,73 +2,89 @@ /** * 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 (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + const AREA = 'customer'; require __DIR__ . '/lib/init.php'; use Froxlor\Api\Commands\CustomerBackups as CustomerBackups; use Froxlor\Api\Commands\DirOptions as DirOptions; use Froxlor\Api\Commands\DirProtections as DirProtections; +use Froxlor\Customer\Customer; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; +use Froxlor\PhpHelper; use Froxlor\Settings; +use Froxlor\UI\Collection; +use Froxlor\UI\HTML; +use Froxlor\UI\Listing; use Froxlor\UI\Panel\UI; use Froxlor\UI\Request; +use Froxlor\UI\Response; // redirect if this customer page is hidden via settings if (Settings::IsInList('panel.customer_hide_options', 'extras')) { - \Froxlor\UI\Response::redirectTo('customer_index.php'); + Response::redirectTo('customer_index.php'); } -$id = (int) Request::get('id'); +$id = (int)Request::get('id'); if ($page == 'overview' || $page == 'htpasswds') { - // redirect if this customer sub-page is hidden via settings if (Settings::IsInList('panel.customer_hide_options', 'extras.directoryprotection')) { - \Froxlor\UI\Response::redirectTo('customer_index.php'); + Response::redirectTo('customer_index.php'); } if ($action == '') { - $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_extras::htpasswds"); - $fields = array( - 'username' => $lng['login']['username'], - 'path' => $lng['panel']['path'] - ); + $log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_extras::htpasswds"); + $fields = [ + 'username' => lng('login.username'), + 'path' => lng('panel.path') + ]; try { $htpasswd_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.htpasswd.php'; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\DirProtections::class, $userinfo)) + $collection = (new Collection(DirProtections::class, $userinfo)) ->withPagination($htpasswd_list_data['htpasswd_list']['columns']); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } UI::view('user/table.html.twig', [ - 'listing' => \Froxlor\UI\Listing::format($collection, $htpasswd_list_data, 'htpasswd_list') , - 'actions_links' => [[ - 'href' => $linker->getLink(['section' => 'extras', 'page' => 'htpasswds', 'action' => 'add']), - 'label' => $lng['extras']['directoryprotection_add'] - ]], - 'entity_info' => $lng['extras']['description'] + 'listing' => Listing::format($collection, $htpasswd_list_data, 'htpasswd_list'), + 'actions_links' => [ + [ + 'href' => $linker->getLink(['section' => 'extras', 'page' => 'htpasswds', 'action' => 'add']), + 'label' => lng('extras.directoryprotection_add') + ] + ], + 'entity_info' => lng('extras.description') ]); } elseif ($action == 'delete' && $id != 0) { try { - $json_result = DirProtections::getLocal($userinfo, array( + $json_result = DirProtections::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; @@ -77,21 +93,21 @@ if ($page == 'overview' || $page == 'htpasswds') { try { DirProtections::getLocal($userinfo, $_POST)->delete(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { if (strpos($result['path'], $userinfo['documentroot']) === 0) { $result['path'] = str_replace($userinfo['documentroot'], "/", $result['path']); } - \Froxlor\UI\HTML::askYesNo('extras_reallydelete', $filename, array( + HTML::askYesNo('extras_reallydelete', $filename, [ 'id' => $id, 'page' => $page, 'action' => $action - ), $result['username'] . ' (' . $result['path'] . ')'); + ], $result['username'] . ' (' . $result['path'] . ')'); } } } elseif ($action == 'add') { @@ -99,28 +115,28 @@ if ($page == 'overview' || $page == 'htpasswds') { try { DirProtections::getLocal($userinfo, $_POST)->add(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - $pathSelect = \Froxlor\FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']); + $pathSelect = FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']); $htpasswd_add_data = include_once dirname(__FILE__) . '/lib/formfields/customer/extras/formfield.htpasswd_add.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'extras')), + 'formaction' => $linker->getLink(['section' => 'extras']), 'formdata' => $htpasswd_add_data['htpasswd_add'] ]); } } elseif ($action == 'edit' && $id != 0) { try { - $json_result = DirProtections::getLocal($userinfo, array( + $json_result = DirProtections::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; @@ -129,21 +145,21 @@ if ($page == 'overview' || $page == 'htpasswds') { try { DirProtections::getLocal($userinfo, $_POST)->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { if (strpos($result['path'], $userinfo['documentroot']) === 0) { $result['path'] = str_replace($userinfo['documentroot'], "/", $result['path']); } - $result = \Froxlor\PhpHelper::htmlentitiesArray($result); + $result = PhpHelper::htmlentitiesArray($result); $htpasswd_edit_data = include_once dirname(__FILE__) . '/lib/formfields/customer/extras/formfield.htpasswd_edit.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'extras', 'id' => $id)), + 'formaction' => $linker->getLink(['section' => 'extras', 'id' => $id]), 'formdata' => $htpasswd_edit_data['htpasswd_edit'], 'editid' => $id ]); @@ -151,40 +167,41 @@ if ($page == 'overview' || $page == 'htpasswds') { } } } elseif ($page == 'htaccess') { - // redirect if this customer sub-page is hidden via settings if (Settings::IsInList('panel.customer_hide_options', 'extras.pathoptions')) { - \Froxlor\UI\Response::redirectTo('customer_index.php'); + Response::redirectTo('customer_index.php'); } if ($action == '') { - $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_extras::htaccess"); + $log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_extras::htaccess"); - $cperlenabled = \Froxlor\Customer\Customer::customerHasPerlEnabled($userinfo['customerid']); + $cperlenabled = Customer::customerHasPerlEnabled($userinfo['customerid']); try { $htaccess_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.htaccess.php'; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\DirOptions::class, $userinfo)) + $collection = (new Collection(DirOptions::class, $userinfo)) ->withPagination($htaccess_list_data['htaccess_list']['columns']); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } UI::view('user/table.html.twig', [ - 'listing' => \Froxlor\UI\Listing::format($collection, $htaccess_list_data, 'htaccess_list'), - 'actions_links' => [[ - 'href' => $linker->getLink(['section' => 'extras', 'page' => 'htaccess', 'action' => 'add']), - 'label' => $lng['extras']['pathoptions_add'] - ]], - 'entity_info' => $lng['extras']['description'] + 'listing' => Listing::format($collection, $htaccess_list_data, 'htaccess_list'), + 'actions_links' => [ + [ + 'href' => $linker->getLink(['section' => 'extras', 'page' => 'htaccess', 'action' => 'add']), + 'label' => lng('extras.pathoptions_add') + ] + ], + 'entity_info' => lng('extras.description') ]); } elseif ($action == 'delete' && $id != 0) { try { - $json_result = DirOptions::getLocal($userinfo, array( + $json_result = DirOptions::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; @@ -193,17 +210,17 @@ if ($page == 'overview' || $page == 'htpasswds') { try { DirOptions::getLocal($userinfo, $_POST)->delete(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - \Froxlor\UI\HTML::askYesNo('extras_reallydelete_pathoptions', $filename, array( + HTML::askYesNo('extras_reallydelete_pathoptions', $filename, [ 'id' => $id, 'page' => $page, 'action' => $action - ), str_replace($userinfo['documentroot'], '/', $result['path'])); + ], str_replace($userinfo['documentroot'], '/', $result['path'])); } } } elseif ($action == 'add') { @@ -211,29 +228,29 @@ if ($page == 'overview' || $page == 'htpasswds') { try { DirOptions::getLocal($userinfo, $_POST)->add(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - $pathSelect = \Froxlor\FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']); - $cperlenabled = \Froxlor\Customer\Customer::customerHasPerlEnabled($userinfo['customerid']); + $pathSelect = FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']); + $cperlenabled = Customer::customerHasPerlEnabled($userinfo['customerid']); $htaccess_add_data = include_once dirname(__FILE__) . '/lib/formfields/customer/extras/formfield.htaccess_add.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'extras')), + 'formaction' => $linker->getLink(['section' => 'extras']), 'formdata' => $htaccess_add_data['htaccess_add'] ]); } } elseif (($action == 'edit') && ($id != 0)) { try { - $json_result = DirOptions::getLocal($userinfo, array( + $json_result = DirOptions::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; @@ -242,23 +259,23 @@ if ($page == 'overview' || $page == 'htpasswds') { try { DirOptions::getLocal($userinfo, $_POST)->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { if (strpos($result['path'], $userinfo['documentroot']) === 0) { $result['path'] = str_replace($userinfo['documentroot'], "/", $result['path']); } - $cperlenabled = \Froxlor\Customer\Customer::customerHasPerlEnabled($userinfo['customerid']); + $cperlenabled = Customer::customerHasPerlEnabled($userinfo['customerid']); - $result = \Froxlor\PhpHelper::htmlentitiesArray($result); + $result = PhpHelper::htmlentitiesArray($result); $htaccess_edit_data = include_once dirname(__FILE__) . '/lib/formfields/customer/extras/formfield.htaccess_edit.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'extras', 'id' => $id)), + 'formaction' => $linker->getLink(['section' => 'extras', 'id' => $id]), 'formdata' => $htaccess_edit_data['htaccess_edit'], 'editid' => $id ]); @@ -266,56 +283,55 @@ if ($page == 'overview' || $page == 'htpasswds') { } } } elseif ($page == 'backup') { - // redirect if this customer sub-page is hidden via settings if (Settings::IsInList('panel.customer_hide_options', 'extras.backup')) { - \Froxlor\UI\Response::redirectTo('customer_index.php'); + Response::redirectTo('customer_index.php'); } if (Settings::Get('system.backupenabled') == 1) { if ($action == 'abort' && isset($_POST['send']) && $_POST['send'] == 'send') { - $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "customer_extras::backup - aborted scheduled backupjob"); + $log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "customer_extras::backup - aborted scheduled backupjob"); try { CustomerBackups::getLocal($userinfo, $_POST)->delete(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::standard_success('backupaborted'); - \Froxlor\UI\Response::redirectTo($filename, array( + Response::standardSuccess('backupaborted'); + Response::redirectTo($filename, [ 'page' => $page, 'action' => '' - )); + ]); } if ($action == '') { - $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_extras::backup"); + $log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_extras::backup"); // check whether there is a backup-job for this customer try { $backup_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.backups.php'; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\CustomerBackups::class, $userinfo)); + $collection = (new Collection(CustomerBackups::class, $userinfo)); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } if (isset($_POST['send']) && $_POST['send'] == 'send') { try { CustomerBackups::getLocal($userinfo, $_POST)->add(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::standard_success('backupscheduled'); + Response::standardSuccess('backupscheduled'); } else { - $pathSelect = \Froxlor\FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']); + $pathSelect = FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']); $backup_data = include_once dirname(__FILE__) . '/lib/formfields/customer/extras/formfield.backup.php'; UI::view('user/form-datatable.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'extras')), + 'formaction' => $linker->getLink(['section' => 'extras']), 'formdata' => $backup_data['backup'], - 'tabledata' => \Froxlor\UI\Listing::format($collection, $backup_list_data, 'backup_list') , + 'tabledata' => Listing::format($collection, $backup_list_data, 'backup_list'), ]); } } } else { - \Froxlor\UI\Response::standard_error('backupfunctionnotenabled'); + Response::standardError('backupfunctionnotenabled'); } } diff --git a/customer_ftp.php b/customer_ftp.php index 740f2c52..aa81167f 100644 --- a/customer_ftp.php +++ b/customer_ftp.php @@ -2,67 +2,82 @@ /** * 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 (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + const AREA = 'customer'; require __DIR__ . '/lib/init.php'; use Froxlor\Api\Commands\Ftps as Ftps; use Froxlor\Database\Database; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; use Froxlor\Settings; +use Froxlor\UI\Collection; +use Froxlor\UI\HTML; +use Froxlor\UI\Listing; use Froxlor\UI\Panel\UI; use Froxlor\UI\Request; +use Froxlor\UI\Response; // redirect if this customer page is hidden via settings if (Settings::IsInList('panel.customer_hide_options', 'ftp')) { - \Froxlor\UI\Response::redirectTo('customer_index.php'); + Response::redirectTo('customer_index.php'); } -$id = (int) Request::get('id', 0); +$id = (int)Request::get('id', 0); if ($page == 'overview' || $page == 'accounts') { if ($action == '') { - $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_ftp::accounts"); + $log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_ftp::accounts"); try { $ftp_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.ftps.php'; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Ftps::class, $userinfo)) + $collection = (new Collection(Ftps::class, $userinfo)) ->withPagination($ftp_list_data['ftp_list']['columns']); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $actions_links = false; if ($userinfo['ftps_used'] < $userinfo['ftps'] || $userinfo['ftps'] == '-1') { - $actions_links = [[ - 'href' => $linker->getLink(['section' => 'ftp', 'page' => 'accounts', 'action' => 'add']), - 'label' => $lng['ftp']['account_add'] - ]]; + $actions_links = [ + [ + 'href' => $linker->getLink(['section' => 'ftp', 'page' => 'accounts', 'action' => 'add']), + 'label' => lng('ftp.account_add') + ] + ]; } UI::view('user/table.html.twig', [ - 'listing' => \Froxlor\UI\Listing::format($collection, $ftp_list_data, 'ftp_list') , + 'listing' => Listing::format($collection, $ftp_list_data, 'ftp_list'), 'actions_links' => $actions_links, - 'entity_info' => $lng['ftp']['description'] + 'entity_info' => lng('ftp.description') ]); } elseif ($action == 'delete' && $id != 0) { try { - $json_result = Ftps::getLocal($userinfo, array( + $json_result = Ftps::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; @@ -71,20 +86,20 @@ if ($page == 'overview' || $page == 'accounts') { try { Ftps::getLocal($userinfo, $_POST)->delete(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - \Froxlor\UI\HTML::askYesNoWithCheckbox('ftp_reallydelete', 'admin_customer_alsoremoveftphomedir', $filename, array( + HTML::askYesNoWithCheckbox('ftp_reallydelete', 'admin_customer_alsoremoveftphomedir', $filename, [ 'id' => $id, 'page' => $page, 'action' => $action - ), $result['username']); + ], $result['username']); } } else { - \Froxlor\UI\Response::standard_error('ftp_cantdeletemainaccount'); + Response::standardError('ftp_cantdeletemainaccount'); } } elseif ($action == 'add') { if ($userinfo['ftps_used'] < $userinfo['ftps'] || $userinfo['ftps'] == '-1') { @@ -92,21 +107,21 @@ if ($page == 'overview' || $page == 'accounts') { try { Ftps::getLocal($userinfo, $_POST)->add(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - $pathSelect = \Froxlor\FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid'], '/'); + $pathSelect = FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid'], '/'); if (Settings::Get('customer.ftpatdomain') == '1') { $domainlist = []; $result_domains_stmt = Database::prepare("SELECT `domain` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid`= :customerid"); - Database::pexecute($result_domains_stmt, array( + Database::pexecute($result_domains_stmt, [ "customerid" => $userinfo['customerid'] - )); + ]); while ($row_domain = $result_domains_stmt->fetch(PDO::FETCH_ASSOC)) { $domainlist[$row_domain['domain']] = $idna_convert->decode($row_domain['domain']); @@ -126,18 +141,18 @@ if ($page == 'overview' || $page == 'accounts') { $ftp_add_data = include_once dirname(__FILE__) . '/lib/formfields/customer/ftp/formfield.ftp_add.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'ftp')), + 'formaction' => $linker->getLink(['section' => 'ftp']), 'formdata' => $ftp_add_data['ftp_add'] ]); } } } elseif ($action == 'edit' && $id != 0) { try { - $json_result = Ftps::getLocal($userinfo, array( + $json_result = Ftps::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; @@ -146,20 +161,20 @@ if ($page == 'overview' || $page == 'accounts') { try { Ftps::getLocal($userinfo, $_POST)->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { if (strpos($result['homedir'], $userinfo['documentroot']) === 0) { $homedir = str_replace($userinfo['documentroot'], "/", $result['homedir']); } else { $homedir = $result['homedir']; } - $homedir = \Froxlor\FileDir::makeCorrectDir($homedir); + $homedir = FileDir::makeCorrectDir($homedir); - $pathSelect = \Froxlor\FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid'], $homedir); + $pathSelect = FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid'], $homedir); if (Settings::Get('system.allow_customer_shell') == '1') { $shells['/bin/false'] = "/bin/false"; @@ -173,7 +188,7 @@ if ($page == 'overview' || $page == 'accounts') { $ftp_edit_data = include_once dirname(__FILE__) . '/lib/formfields/customer/ftp/formfield.ftp_edit.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'ftp', 'id' => $id)), + 'formaction' => $linker->getLink(['section' => 'ftp', 'id' => $id]), 'formdata' => $ftp_edit_data['ftp_edit'], 'editid' => $id ]); diff --git a/customer_index.php b/customer_index.php index 815d5494..7c25968e 100644 --- a/customer_index.php +++ b/customer_index.php @@ -2,66 +2,79 @@ /** * 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 (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + const AREA = 'customer'; require __DIR__ . '/lib/init.php'; -use Froxlor\Database\Database; -use Froxlor\Settings; use Froxlor\Api\Commands\Customers as Customers; +use Froxlor\CurrentUser; +use Froxlor\Database\Database; +use Froxlor\Froxlor; +use Froxlor\FroxlorLogger; +use Froxlor\Settings; +use Froxlor\System\Crypt; use Froxlor\UI\Panel\UI; +use Froxlor\UI\Response; +use Froxlor\Validate\Validate; if ($action == 'logout') { - $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, 'logged out'); + $log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, 'logged out'); unset($_SESSION['userinfo']); - \Froxlor\CurrentUser::setData(); + CurrentUser::setData(); session_destroy(); - \Froxlor\UI\Response::redirectTo('index.php'); + Response::redirectTo('index.php'); } elseif ($action == 'suback') { - if (is_array(\Froxlor\CurrentUser::getField('switched_user'))) { - $result = \Froxlor\CurrentUser::getData(); + if (is_array(CurrentUser::getField('switched_user'))) { + $result = CurrentUser::getData(); $result = $result['switched_user']; - \Froxlor\CurrentUser::setData($result); + CurrentUser::setData($result); $target = (isset($_GET['target']) ? $_GET['target'] : 'index'); $redirect = "admin_" . $target . ".php"; - if (!file_exists(\Froxlor\Froxlor::getInstallDir() . "/" . $redirect)) { + if (!file_exists(Froxlor::getInstallDir() . "/" . $redirect)) { $redirect = "admin_index.php"; } - \Froxlor\UI\Response::redirectTo($redirect, null, true); + Response::redirectTo($redirect, null, true); } else { - \Froxlor\UI\Response::dynamic_error("Cannot change back - You've never switched to another user :-)"); + Response::dynamicError("Cannot change back - You've never switched to another user :-)"); } } if ($page == 'overview') { - $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_index"); + $log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_index"); $domain_stmt = Database::prepare("SELECT `domain` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :customerid AND `parentdomainid` = '0' AND `id` <> :standardsubdomain "); - Database::pexecute($domain_stmt, array( + Database::pexecute($domain_stmt, [ "customerid" => $userinfo['customerid'], "standardsubdomain" => $userinfo['standardsubdomain'] - )); + ]); - $domainArray = array(); + $domainArray = []; while ($row = $domain_stmt->fetch(PDO::FETCH_ASSOC)) { $domainArray[] = $idna_convert->decode($row['domain']); } @@ -75,10 +88,10 @@ if ($page == 'overview') { WHERE `customerid` = :customerid AND `id` = :standardsubdomain "); - $std_domain = Database::pexecute_first($std_domain_stmt, array( + $std_domain = Database::pexecute_first($std_domain_stmt, [ "customerid" => $userinfo['customerid'], "standardsubdomain" => $userinfo['standardsubdomain'] - )); + ]); $stdsubdomain = $std_domain['domain']; } @@ -88,9 +101,9 @@ if ($page == 'overview') { // get disk-space usages for web, mysql and mail $usages_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DISKSPACE . "` WHERE `customerid` = :cid ORDER BY `stamp` DESC LIMIT 1"); - $usages = Database::pexecute_first($usages_stmt, array( + $usages = Database::pexecute_first($usages_stmt, [ 'cid' => $userinfo['customerid'] - )); + ]); // get everything in bytes for the percentage calculation on the dashboard $userinfo['diskspace_bytes'] = ($userinfo['diskspace'] > -1) ? $userinfo['diskspace'] * 1024 : -1; @@ -111,102 +124,101 @@ if ($page == 'overview') { 'stdsubdomain' => $stdsubdomain ]); } elseif ($page == 'change_password') { - if (isset($_POST['send']) && $_POST['send'] == 'send') { - $old_password = \Froxlor\Validate\Validate::validate($_POST['old_password'], 'old password'); + $old_password = Validate::validate($_POST['old_password'], 'old password'); - if (!\Froxlor\System\Crypt::validatePasswordLogin($userinfo, $old_password, TABLE_PANEL_CUSTOMERS, 'customerid')) { - \Froxlor\UI\Response::standard_error('oldpasswordnotcorrect'); + if (!Crypt::validatePasswordLogin($userinfo, $old_password, TABLE_PANEL_CUSTOMERS, 'customerid')) { + Response::standardError('oldpasswordnotcorrect'); } try { - $new_password = \Froxlor\System\Crypt::validatePassword($_POST['new_password'], 'new password'); - $new_password_confirm = \Froxlor\System\Crypt::validatePassword($_POST['new_password_confirm'], 'new password confirm'); + $new_password = Crypt::validatePassword($_POST['new_password'], 'new password'); + $new_password_confirm = Crypt::validatePassword($_POST['new_password_confirm'], 'new password confirm'); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } if ($old_password == '') { - \Froxlor\UI\Response::standard_error(array( + Response::standardError([ 'stringisempty', 'oldpassword' - )); + ]); } elseif ($new_password == '') { - \Froxlor\UI\Response::standard_error(array( + Response::standardError([ 'stringisempty', 'newpassword' - )); + ]); } elseif ($new_password_confirm == '') { - \Froxlor\UI\Response::standard_error(array( + Response::standardError([ 'stringisempty', 'newpasswordconfirm' - )); + ]); } elseif ($new_password != $new_password_confirm) { - \Froxlor\UI\Response::standard_error('newpasswordconfirmerror'); + Response::standardError('newpasswordconfirmerror'); } else { // Update user password try { - Customers::getLocal($userinfo, array( + Customers::getLocal($userinfo, [ 'id' => $userinfo['customerid'], 'new_customer_password' => $new_password - ))->update(); + ])->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, 'changed password'); + $log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, 'changed password'); // Update ftp password if (isset($_POST['change_main_ftp']) && $_POST['change_main_ftp'] == 'true') { - $cryptPassword = \Froxlor\System\Crypt::makeCryptPassword($new_password); + $cryptPassword = Crypt::makeCryptPassword($new_password); $stmt = Database::prepare("UPDATE `" . TABLE_FTP_USERS . "` SET `password` = :password WHERE `customerid` = :customerid AND `username` = :username"); - $params = array( + $params = [ "password" => $cryptPassword, "customerid" => $userinfo['customerid'], "username" => $userinfo['loginname'] - ); + ]; Database::pexecute($stmt, $params); - $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, 'changed main ftp password'); + $log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, 'changed main ftp password'); } // Update statistics password if (isset($_POST['change_stats']) && $_POST['change_stats'] == 'true') { - $new_stats_password = \Froxlor\System\Crypt::makeCryptPassword($new_password, true); + $new_stats_password = Crypt::makeCryptPassword($new_password, true); $stmt = Database::prepare("UPDATE `" . TABLE_PANEL_HTPASSWDS . "` SET `password` = :password WHERE `customerid` = :customerid AND `username` = :username"); - $params = array( + $params = [ "password" => $new_stats_password, "customerid" => $userinfo['customerid'], "username" => $userinfo['loginname'] - ); + ]; Database::pexecute($stmt, $params); } - \Froxlor\UI\Response::redirectTo($filename); + Response::redirectTo($filename); } } else { UI::view('user/change_password.html.twig'); } } elseif ($page == 'change_language') { if (isset($_POST['send']) && $_POST['send'] == 'send') { - $def_language = \Froxlor\Validate\Validate::validate($_POST['def_language'], 'default language'); + $def_language = Validate::validate($_POST['def_language'], 'default language'); if (isset($languages[$def_language])) { try { - Customers::getLocal($userinfo, array( + Customers::getLocal($userinfo, [ 'id' => $userinfo['customerid'], 'def_language' => $def_language - ))->update(); + ])->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } } - $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "changed default language to '" . $def_language . "'"); - \Froxlor\UI\Response::redirectTo($filename); + $log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "changed default language to '" . $def_language . "'"); + Response::redirectTo($filename); } else { $default_lang = Settings::Get('panel.standardlanguage'); if ($userinfo['def_language'] != '') { @@ -220,20 +232,19 @@ if ($page == 'overview') { } } elseif ($page == 'change_theme') { if (isset($_POST['send']) && $_POST['send'] == 'send') { - $theme = \Froxlor\Validate\Validate::validate($_POST['theme'], 'theme'); + $theme = Validate::validate($_POST['theme'], 'theme'); try { - Customers::getLocal($userinfo, array( + Customers::getLocal($userinfo, [ 'id' => $userinfo['customerid'], 'theme' => $theme - ))->update(); + ])->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "changed default theme to '" . $theme . "'"); - \Froxlor\UI\Response::redirectTo($filename); + $log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "changed default theme to '" . $theme . "'"); + Response::redirectTo($filename); } else { - $default_theme = Settings::Get('panel.default_theme'); if ($userinfo['theme'] != '') { $default_theme = $userinfo['theme']; diff --git a/customer_logger.php b/customer_logger.php index 2d09efb8..70be98cb 100644 --- a/customer_logger.php +++ b/customer_logger.php @@ -2,43 +2,54 @@ /** * 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 (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + const AREA = 'customer'; require __DIR__ . '/lib/init.php'; +use Froxlor\Api\Commands\SysLog; use Froxlor\Settings; +use Froxlor\UI\Collection; +use Froxlor\UI\Listing; use Froxlor\UI\Panel\UI; +use Froxlor\UI\Response; // redirect if this customer page is hidden via settings if (Settings::IsInList('panel.customer_hide_options', 'extras.logger')) { - \Froxlor\UI\Response::redirectTo('customer_index.php'); + Response::redirectTo('customer_index.php'); } if ($page == 'log') { if ($action == '') { try { $syslog_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/tablelisting.syslog.php'; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\SysLog::class, $userinfo)) + $collection = (new Collection(SysLog::class, $userinfo)) ->addParam(['sql_orderby' => ['date' => 'DESC']]) ->withPagination($syslog_list_data['syslog_list']['columns']); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } UI::view('user/table.html.twig', [ - 'listing' => \Froxlor\UI\Listing::format($collection, $syslog_list_data, 'syslog_list') + 'listing' => Listing::format($collection, $syslog_list_data, 'syslog_list') ]); } } diff --git a/customer_mysql.php b/customer_mysql.php index a56e90c7..648f8a7d 100644 --- a/customer_mysql.php +++ b/customer_mysql.php @@ -2,32 +2,44 @@ /** * 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 (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + const AREA = 'customer'; require __DIR__ . '/lib/init.php'; use Froxlor\Api\Commands\Mysqls as Mysqls; use Froxlor\Database\Database; +use Froxlor\FroxlorLogger; use Froxlor\Settings; +use Froxlor\UI\Collection; +use Froxlor\UI\HTML; +use Froxlor\UI\Listing; use Froxlor\UI\Panel\UI; use Froxlor\UI\Request; +use Froxlor\UI\Response; // redirect if this customer page is hidden via settings if (Settings::IsInList('panel.customer_hide_options', 'mysql')) { - \Froxlor\UI\Response::redirectTo('customer_index.php'); + Response::redirectTo('customer_index.php'); } // get sql-root access data @@ -36,11 +48,11 @@ Database::needSqlData(); $sql_root = Database::getSqlData(); Database::needRoot(false); -$id = (int) Request::get('id'); +$id = (int)Request::get('id'); if ($page == 'overview' || $page == 'mysqls') { if ($action == '') { - $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_mysql::mysqls"); + $log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_mysql::mysqls"); $dbservers_stmt = Database::query("SELECT COUNT(DISTINCT `dbserver`) as numservers FROM `" . TABLE_PANEL_DATABASES . "`"); $dbserver = $dbservers_stmt->fetch(PDO::FETCH_ASSOC); @@ -48,42 +60,43 @@ if ($page == 'overview' || $page == 'mysqls') { try { $mysql_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.mysqls.php'; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Mysqls::class, $userinfo)) + $collection = (new Collection(Mysqls::class, $userinfo)) ->withPagination($mysql_list_data['mysql_list']['columns']); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } Database::needSqlData(); $sql = Database::getSqlData(); - $lng['mysql']['description'] = str_replace('', $sql['host'], $lng['mysql']['description']); + // FIXME: setting translation on the fly is currently not supported; do we want this; alternatives + // $lng['mysql']['description'] = str_replace('', $sql['host'], lng('mysql.description')); $actions_links = false; if ($userinfo['mysqls_used'] < $userinfo['mysqls'] || $userinfo['mysqls'] == '-1') { - $actions_links = [[ - 'href' => $linker->getLink(['section' => 'mysql', 'page' => 'mysqls', 'action' => 'add']), - 'label' => $lng['mysql']['database_create'] - ]]; + $actions_links = [ + [ + 'href' => $linker->getLink(['section' => 'mysql', 'page' => 'mysqls', 'action' => 'add']), + 'label' => lng('mysql.database_create') + ] + ]; } UI::view('user/table.html.twig', [ - 'listing' => \Froxlor\UI\Listing::format($collection, $mysql_list_data, 'mysql_list') , + 'listing' => Listing::format($collection, $mysql_list_data, 'mysql_list'), 'actions_links' => $actions_links, - 'entity_info' => $lng['mysql']['description'] + 'entity_info' => lng('mysql.description') ]); } elseif ($action == 'delete' && $id != 0) { - try { - $json_result = Mysqls::getLocal($userinfo, array( + $json_result = Mysqls::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; if (isset($result['databasename']) && $result['databasename'] != '') { - Database::needRoot(true, $result['dbserver']); Database::needSqlData(); $sql_root = Database::getSqlData(); @@ -97,21 +110,21 @@ if ($page == 'overview' || $page == 'mysqls') { try { Mysqls::getLocal($userinfo, $_POST)->delete(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { $dbnamedesc = $result['databasename']; if (isset($result['description']) && $result['description'] != '') { $dbnamedesc .= ' (' . $result['description'] . ')'; } - \Froxlor\UI\HTML::askYesNo('mysql_reallydelete', $filename, array( + HTML::askYesNo('mysql_reallydelete', $filename, [ 'id' => $id, 'page' => $page, 'action' => $action - ), $dbnamedesc); + ], $dbnamedesc); } } } elseif ($action == 'add') { @@ -120,13 +133,12 @@ if ($page == 'overview' || $page == 'mysqls') { try { Mysqls::getLocal($userinfo, $_POST)->add(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - $dbservers_stmt = Database::query("SELECT DISTINCT `dbserver` FROM `" . TABLE_PANEL_DATABASES . "`"); $mysql_servers = []; while ($dbserver = $dbservers_stmt->fetch(PDO::FETCH_ASSOC)) { @@ -140,18 +152,18 @@ if ($page == 'overview' || $page == 'mysqls') { $mysql_add_data = include_once dirname(__FILE__) . '/lib/formfields/customer/mysql/formfield.mysql_add.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'mysql')), + 'formaction' => $linker->getLink(['section' => 'mysql']), 'formdata' => $mysql_add_data['mysql_add'] ]); } } } elseif ($action == 'edit' && $id != 0) { try { - $json_result = Mysqls::getLocal($userinfo, array( + $json_result = Mysqls::getLocal($userinfo, [ 'id' => $id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; @@ -160,13 +172,12 @@ if ($page == 'overview' || $page == 'mysqls') { try { $json_result = Mysqls::getLocal($userinfo, $_POST)->update(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } - \Froxlor\UI\Response::redirectTo($filename, array( + Response::redirectTo($filename, [ 'page' => $page - )); + ]); } else { - $dbservers_stmt = Database::query("SELECT COUNT(DISTINCT `dbserver`) as numservers FROM `" . TABLE_PANEL_DATABASES . "`"); $dbserver = $dbservers_stmt->fetch(PDO::FETCH_ASSOC); $count_mysql_servers = $dbserver['numservers']; @@ -179,7 +190,7 @@ if ($page == 'overview' || $page == 'mysqls') { $mysql_edit_data = include_once dirname(__FILE__) . '/lib/formfields/customer/mysql/formfield.mysql_edit.php'; UI::view('user/form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'mysql', 'id' => $id)), + 'formaction' => $linker->getLink(['section' => 'mysql', 'id' => $id]), 'formdata' => $mysql_edit_data['mysql_edit'], 'editid' => $id ]); diff --git a/customer_traffic.php b/customer_traffic.php index 487e10d7..67f08ba7 100644 --- a/customer_traffic.php +++ b/customer_traffic.php @@ -2,19 +2,25 @@ /** * 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 (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ const AREA = 'customer'; @@ -60,11 +66,11 @@ if (!is_null($month) && !is_null($year)) { AND `year` = :year GROUP BY `day` ORDER BY `day` DESC"); - $params = array( + $params = [ "customerid" => $userinfo['customerid'], "month" => $month, "year" => $year - ); + ]; Database::pexecute($result_stmt, $params); $traf['byte'] = 0; $traffic_complete['http'] = 0; @@ -108,9 +114,9 @@ if (!is_null($month) && !is_null($year)) { ORDER BY `year` DESC, `month` DESC LIMIT 12 "); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ "customerid" => $userinfo['customerid'] - )); + ]); $traffic_complete['http'] = 0; $traffic_complete['ftp'] = 0; $traffic_complete['mail'] = 0; @@ -132,7 +138,7 @@ if (!is_null($month) && !is_null($year)) { $traffic_complete['mail'] += $mail; $traf['month'] = $row['month']; $traf['year'] = $row['year']; - $traf['monthname'] = $lng['traffic']['months'][intval($row['month'])] . " " . $row['year']; + $traf['monthname'] = lng('traffic.months.' . intval($row['month'])) . " " . $row['year']; $traf['byte'] = $http + $ftp_up + $ftp_down + $mail; $traf['byte_total'] = $traf['byte_total'] + $http + $ftp_up + $ftp_down + $mail; $traf['days'][] = $traf['monthname']; diff --git a/dns_editor.php b/dns_editor.php index 6b812053..8e891fa1 100644 --- a/dns_editor.php +++ b/dns_editor.php @@ -1,41 +1,54 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + if (!defined('AREA')) { header("Location: index.php"); exit(); } -/** - * This file is part of the Froxlor project. - * Copyright (c) 2016 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 - * - * @copyright (c) the authors - * @author Froxlor team (2016-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel - * - */ - use Froxlor\Api\Commands\DomainZones; -use Froxlor\UI\Request; +use Froxlor\Dns\Dns; +use Froxlor\UI\Collection; +use Froxlor\UI\Listing; use Froxlor\UI\Panel\UI; +use Froxlor\UI\Request; +use Froxlor\UI\Response; // This file is being included in admin_domains and customer_domains // and therefore does not need to require lib/init.php -$domain_id = (int) Request::get('domain_id'); +$domain_id = (int)Request::get('domain_id'); $record = isset($_POST['dns_record']) ? trim($_POST['dns_record']) : null; $type = isset($_POST['dns_type']) ? $_POST['dns_type'] : 'A'; -$prio = isset($_POST['dns_mxp']) ? (int) $_POST['dns_mxp'] : null; +$prio = isset($_POST['dns_mxp']) ? (int)$_POST['dns_mxp'] : null; $content = isset($_POST['dns_content']) ? trim($_POST['dns_content']) : null; -$ttl = isset($_POST['record']['ttl']) ? (int) $_POST['record']['ttl'] : 18000; +$ttl = isset($_POST['record']['ttl']) ? (int)$_POST['record']['ttl'] : 18000; // get domain-name -$domain = \Froxlor\Dns\Dns::getAllowedDomainEntry($domain_id, AREA, $userinfo); +$domain = Dns::getAllowedDomainEntry($domain_id, AREA, $userinfo); $errors = ""; $success_message = ""; @@ -43,30 +56,30 @@ $success_message = ""; // action for adding a new entry if ($action == 'add_record' && !empty($_POST)) { try { - DomainZones::getLocal($userinfo, array( + DomainZones::getLocal($userinfo, [ 'id' => $domain_id, 'record' => $record, 'type' => $type, 'prio' => $prio, 'content' => $content, 'ttl' => $ttl - ))->add(); - $success_message = $lng['success']['dns_record_added']; + ])->add(); + $success_message = lng('success.dns_record_added'); $record = $prio = $content = ""; } catch (Exception $e) { $errors = str_replace("\n", "
", $e->getMessage()); } } elseif ($action == 'delete') { // remove entry - $entry_id = isset($_GET['id']) ? (int) $_GET['id'] : 0; + $entry_id = isset($_GET['id']) ? (int)$_GET['id'] : 0; if ($entry_id > 0) { try { - DomainZones::getLocal($userinfo, array( + DomainZones::getLocal($userinfo, [ 'entry_id' => $entry_id, 'id' => $domain_id - ))->delete(); + ])->delete(); // success message (inline) - $success_message = $lng['success']['dns_record_deleted']; + $success_message = lng('success.dns_record_deleted'); } catch (Exception $e) { $errors = str_replace("\n", "
", $e->getMessage()); } @@ -76,18 +89,18 @@ if ($action == 'add_record' && !empty($_POST)) { // select all entries try { $dns_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/tablelisting.dns.php'; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\DomainZones::class, $userinfo, ['id' => $domain_id])) + $collection = (new Collection(DomainZones::class, $userinfo, ['id' => $domain_id])) ->withPagination($dns_list_data['dns_list']['columns']); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } try { - $json_result = DomainZones::getLocal($userinfo, array( + $json_result = DomainZones::getLocal($userinfo, [ 'id' => $domain_id - ))->get(); + ])->get(); } catch (Exception $e) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } $result = json_decode($json_result, true)['data']; $zonefile = implode("\n", $result); @@ -95,22 +108,30 @@ $zonefile = implode("\n", $result); $dns_add_data = include_once dirname(__FILE__) . '/lib/formfields/formfield.dns_add.php'; UI::view('user/dns-editor.html.twig', [ - 'listing' => \Froxlor\UI\Listing::format($collection, $dns_list_data, 'dns_list') , - 'actions_links' => [[ - 'class' => 'btn-secondary', - 'href' => $linker->getLink(['section' => 'domains', 'page' => 'domains', 'action' => 'edit', 'id' => $domain_id]), - 'label' => $lng['panel']['edit'], - 'icon' => 'fa fa-pen' - ], [ - 'class' => 'btn-secondary', - 'href' => $linker->getLink(['section' => 'domains', 'page' => 'domains']), - 'label' => $lng['menue']['domains']['domains'], - 'icon' => 'fa fa-globe' - ]], - 'formaction' => $linker->getLink(array('section' => 'domains', 'action' => 'add_record', 'domain_id' => $domain_id)), + 'listing' => Listing::format($collection, $dns_list_data, 'dns_list'), + 'actions_links' => [ + [ + 'class' => 'btn-secondary', + 'href' => $linker->getLink([ + 'section' => 'domains', + 'page' => 'domains', + 'action' => 'edit', + 'id' => $domain_id + ]), + 'label' => lng('panel.edit'), + 'icon' => 'fa fa-pen' + ], + [ + 'class' => 'btn-secondary', + 'href' => $linker->getLink(['section' => 'domains', 'page' => 'domains']), + 'label' => lng('menue.domains.domains'), + 'icon' => 'fa fa-globe' + ] + ], + 'formaction' => $linker->getLink(['section' => 'domains', 'action' => 'add_record', 'domain_id' => $domain_id]), 'formdata' => $dns_add_data['dns_add'], // alert-box 'type' => (!empty($errors) ? 'danger' : (!empty($success_message) ? 'success' : 'warning')), - 'alert_msg' => (!empty($errors) ? $errors : (!empty($success_message) ? $success_message : $lng['dns']['howitworks'])), + 'alert_msg' => (!empty($errors) ? $errors : (!empty($success_message) ? $success_message : lng('dns.howitworks'))), 'zonefile' => $zonefile ]); diff --git a/doc/example/FroxlorAPI.php b/doc/example/FroxlorAPI.php index e2f8ff9a..e35861c3 100644 --- a/doc/example/FroxlorAPI.php +++ b/doc/example/FroxlorAPI.php @@ -2,19 +2,27 @@ /** * This file is part of the Froxlor project. - * Copyright (c) 2018 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 (2018-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API-example - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + class FroxlorAPI { private string $url; diff --git a/error_report.php b/error_report.php index f11437b8..b85d87ed 100644 --- a/error_report.php +++ b/error_report.php @@ -1,26 +1,38 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + if (!defined('AREA')) { header("Location: index.php"); exit(); } -/** - * This file is part of the Froxlor project. - * Copyright (c) 2022 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 - * - * @copyright (c) the authors - * @author Froxlor team (2016-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel - * - */ - -use Froxlor\UI\Request; +use Froxlor\FileDir; +use Froxlor\Froxlor; use Froxlor\UI\Panel\UI; +use Froxlor\UI\Request; +use Froxlor\UI\Response; // This file is being included in admin_domains and customer_domains // and therefore does not need to require lib/init.php @@ -29,21 +41,20 @@ $errid = Request::get('errorid'); if (!empty($errid)) { // read error file - $err_dir = \Froxlor\FileDir::makeCorrectDir(\Froxlor\Froxlor::getInstallDir() . "/logs/"); - $err_file = \Froxlor\FileDir::makeCorrectFile($err_dir . "/" . $errid . "_sql-error.log"); + $err_dir = FileDir::makeCorrectDir(Froxlor::getInstallDir() . "/logs/"); + $err_file = FileDir::makeCorrectFile($err_dir . "/" . $errid . "_sql-error.log"); if (file_exists($err_file)) { - $error_content = file_get_contents($err_file); $error = explode("|", $error_content); - $_error = array( + $_error = [ 'code' => str_replace("\n", "", substr($error[1], 5)), 'message' => str_replace("\n", "", substr($error[2], 4)), - 'file' => str_replace("\n", "", substr($error[3], 5 + strlen(\Froxlor\Froxlor::getInstallDir()))), + 'file' => str_replace("\n", "", substr($error[3], 5 + strlen(Froxlor::getInstallDir()))), 'line' => str_replace("\n", "", substr($error[4], 5)), - 'trace' => str_replace(\Froxlor\Froxlor::getInstallDir(), "", substr($error[5], 6)) - ); + 'trace' => str_replace(Froxlor::getInstallDir(), "", substr($error[5], 6)) + ]; // build mail-content $mail_body = "Dear froxlor-team,\n\n"; @@ -54,8 +65,8 @@ if (!empty($errid)) { $mail_body .= "Trace:\n" . trim($_error['trace']) . "\n\n"; $mail_body .= "-------------------------------------------------------------\n\n"; $mail_body .= "User-Area: " . AREA . "\n"; - $mail_body .= "Froxlor-version: " . \Froxlor\Froxlor::VERSION . "\n"; - $mail_body .= "DB-version: " . \Froxlor\Froxlor::DBVERSION . "\n\n"; + $mail_body .= "Froxlor-version: " . Froxlor::VERSION . "\n"; + $mail_body .= "DB-version: " . Froxlor::DBVERSION . "\n\n"; $mail_body .= "End of report"; $mail_html = nl2br($mail_body); @@ -79,12 +90,12 @@ if (!empty($errid)) { if ($_mailerror) { // error when reporting an error...LOLFUQ - \Froxlor\UI\Response::standard_error('send_report_error', $mailerr_msg); + Response::standardError('send_report_error', $mailerr_msg); } // finally remove error from fs @unlink($err_file); - \Froxlor\UI\Response::redirectTo($filename); + Response::redirectTo($filename); } // show a nice summary of the error-report // before actually sending anything @@ -92,8 +103,8 @@ if (!empty($errid)) { 'mail_html' => $mail_body ]); } else { - \Froxlor\UI\Response::redirectTo($filename); + Response::redirectTo($filename); } } else { - \Froxlor\UI\Response::redirectTo($filename); + Response::redirectTo($filename); } diff --git a/index.php b/index.php index 2ebd36e4..15dead6e 100644 --- a/index.php +++ b/index.php @@ -2,27 +2,44 @@ /** * 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 (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Panel + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -define('AREA', 'login'); + +const AREA = 'login'; require __DIR__ . '/lib/init.php'; +use Froxlor\CurrentUser; +use Froxlor\Customer\Customer; use Froxlor\Database\Database; -use Froxlor\Settings; +use Froxlor\FileDir; +use Froxlor\Froxlor; use Froxlor\FroxlorLogger; +use Froxlor\FroxlorTwoFactorAuth; +use Froxlor\PhpHelper; +use Froxlor\Settings; +use Froxlor\System\Crypt; use Froxlor\UI\Panel\UI; +use Froxlor\UI\Response; +use Froxlor\User; +use Froxlor\Validate\Validate; if ($action == '') { $action = 'login'; @@ -32,23 +49,23 @@ if ($action == '2fa_entercode') { // page for entering the 2FA code after successful login if (!isset($_SESSION) || !isset($_SESSION['secret_2fa'])) { // no session - redirect to index - \Froxlor\UI\Response::redirectTo('index.php'); + Response::redirectTo('index.php'); exit(); } // show template to enter code UI::view('login/enter2fa.html.twig', [ - 'pagetitle' => $lng['login']['2fa'] + 'pagetitle' => lng('login.2fa') ]); } elseif ($action == '2fa_verify') { // verify code from 2fa code-enter form if (!isset($_SESSION) || !isset($_SESSION['secret_2fa'])) { // no session - redirect to index - \Froxlor\UI\Response::redirectTo('index.php'); + Response::redirectTo('index.php'); exit(); } $code = isset($_POST['2fa_code']) ? $_POST['2fa_code'] : null; // verify entered code - $tfa = new \Froxlor\FroxlorTwoFactorAuth('Froxlor'); + $tfa = new FroxlorTwoFactorAuth('Froxlor'); $result = ($_SESSION['secret_2fa'] == 'email' ? true : $tfa->verifyCode($_SESSION['secret_2fa'], $code, 3)); // either the code is valid when using authenticator-app, or we will select userdata by id and entered code // which is temporarily stored for the customer when using email-2fa @@ -58,9 +75,9 @@ if ($action == '2fa_entercode') { $field = $_SESSION['uidfield_2fa']; $uid = $_SESSION['uid_2fa']; $isadmin = $_SESSION['unfo_2fa']; - $sel_param = array( + $sel_param = [ 'uid' => $uid - ); + ]; if ($_SESSION['secret_2fa'] == 'email') { // verify code by selecting user by id and the temp. stored code, // so only if it's the correct code, we get the user-data @@ -73,9 +90,9 @@ if ($action == '2fa_entercode') { $userinfo = Database::pexecute_first($sel_stmt, $sel_param); // whoops, no (valid) user? Start again if (empty($userinfo)) { - \Froxlor\UI\Response::redirectTo('index.php', array( + Response::redirectTo('index.php', [ 'showmessage' => '2' - )); + ]); } // set fields in $userinfo required for finishLogin() $userinfo['adminsession'] = $isadmin; @@ -83,34 +100,34 @@ if ($action == '2fa_entercode') { // if not successful somehow - start again if (!finishLogin($userinfo)) { - \Froxlor\UI\Response::redirectTo('index.php', array( + Response::redirectTo('index.php', [ 'showmessage' => '2' - )); + ]); } // when using email-2fa, remove the one-time-code if ($userinfo['type_2fa'] == '1') { $del_stmt = Database::prepare("UPDATE $table SET `data_2fa` = '' WHERE `" . $field . "` = :uid"); - $userinfo = Database::pexecute_first($del_stmt, array( + $userinfo = Database::pexecute_first($del_stmt, [ 'uid' => $uid - )); + ]); } exit(); } - \Froxlor\UI\Response::redirectTo('index.php', array( + Response::redirectTo('index.php', [ 'showmessage' => '2' - )); + ]); exit(); } elseif ($action == 'login') { if (isset($_POST['send']) && $_POST['send'] == 'send') { - $loginname = \Froxlor\Validate\Validate::validate($_POST['loginname'], 'loginname'); - $password = \Froxlor\Validate\Validate::validate($_POST['password'], 'password'); + $loginname = Validate::validate($_POST['loginname'], 'loginname'); + $password = Validate::validate($_POST['password'], 'password'); $stmt = Database::prepare("SELECT `loginname` AS `customer` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `loginname`= :loginname"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "loginname" => $loginname - )); + ]); $row = $stmt->fetch(PDO::FETCH_ASSOC); if ($row && $row['customer'] == $loginname) { @@ -120,26 +137,26 @@ if ($action == '2fa_entercode') { $is_admin = false; } else { $is_admin = true; - if ((int) Settings::Get('login.domain_login') == 1) { - $domainname = $idna_convert->encode(preg_replace(array( + if ((int)Settings::Get('login.domain_login') == 1) { + $domainname = $idna_convert->encode(preg_replace([ '/\:(\d)+$/', '/^https?\:\/\//' - ), '', $loginname)); + ], '', $loginname)); $stmt = Database::prepare("SELECT `customerid` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `domain` = :domain"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "domain" => $domainname - )); + ]); $row2 = $stmt->fetch(PDO::FETCH_ASSOC); if (isset($row2['customerid']) && $row2['customerid'] > 0) { - $loginname = \Froxlor\Customer\Customer::getCustomerDetail($row2['customerid'], 'loginname'); + $loginname = Customer::getCustomerDetail($row2['customerid'], 'loginname'); if ($loginname !== false) { $stmt = Database::prepare("SELECT `loginname` AS `customer` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `loginname`= :loginname"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "loginname" => $loginname - )); + ]); $row3 = $stmt->fetch(PDO::FETCH_ASSOC); if ($row3 && $row3['customer'] == $loginname) { $table = "`" . TABLE_PANEL_CUSTOMERS . "`"; @@ -152,31 +169,31 @@ if ($action == '2fa_entercode') { } } - if ((\Froxlor\Froxlor::hasUpdates() || \Froxlor\Froxlor::hasDbUpdates()) && $is_admin == false) { - \Froxlor\UI\Response::redirectTo('index.php'); + if ((Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) && $is_admin == false) { + Response::redirectTo('index.php'); exit(); } if ($is_admin) { - if (\Froxlor\Froxlor::hasUpdates() || \Froxlor\Froxlor::hasDbUpdates()) { + if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) { $stmt = Database::prepare("SELECT `loginname` AS `admin` FROM `" . TABLE_PANEL_ADMINS . "` WHERE `loginname`= :loginname AND `change_serversettings` = '1'"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "loginname" => $loginname - )); + ]); $row = $stmt->fetch(PDO::FETCH_ASSOC); if (!isset($row['admin'])) { // not an admin who can see updates - \Froxlor\UI\Response::redirectTo('index.php'); + Response::redirectTo('index.php'); exit(); } } else { $stmt = Database::prepare("SELECT `loginname` AS `admin` FROM `" . TABLE_PANEL_ADMINS . "` WHERE `loginname`= :loginname"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "loginname" => $loginname - )); + ]); $row = $stmt->fetch(PDO::FETCH_ASSOC); } @@ -186,38 +203,38 @@ if ($action == '2fa_entercode') { $adminsession = '1'; } else { // Log failed login - $rstlog = FroxlorLogger::getInstanceOf(array( + $rstlog = FroxlorLogger::getInstanceOf([ 'loginname' => $_SERVER['REMOTE_ADDR'] - )); - $rstlog->logAction(\Froxlor\FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "Unknown user '" . $loginname . "' tried to login."); + ]); + $rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "Unknown user '" . $loginname . "' tried to login."); - \Froxlor\UI\Response::redirectTo('index.php', array( + Response::redirectTo('index.php', [ 'showmessage' => '2' - )); + ]); exit(); } } $userinfo_stmt = Database::prepare("SELECT * FROM $table WHERE `loginname`= :loginname"); - Database::pexecute($userinfo_stmt, array( + Database::pexecute($userinfo_stmt, [ "loginname" => $loginname - )); + ]); $userinfo = $userinfo_stmt->fetch(PDO::FETCH_ASSOC); if ($userinfo['loginfail_count'] >= Settings::Get('login.maxloginattempts') && $userinfo['lastlogin_fail'] > (time() - Settings::Get('login.deactivatetime'))) { - \Froxlor\UI\Response::redirectTo('index.php', array( + Response::redirectTo('index.php', [ 'showmessage' => '3' - )); + ]); exit(); - } elseif (\Froxlor\System\Crypt::validatePasswordLogin($userinfo, $password, $table, $uid)) { + } elseif (Crypt::validatePasswordLogin($userinfo, $password, $table, $uid)) { // only show "you're banned" if the login was successful // because we don't want to publish that the user does exist if ($userinfo['deactivated']) { unset($userinfo); - \Froxlor\UI\Response::redirectTo('index.php', array( + Response::redirectTo('index.php', [ 'showmessage' => '5' - )); + ]); exit(); } else { // login correct @@ -225,10 +242,10 @@ if ($action == '2fa_entercode') { $stmt = Database::prepare("UPDATE $table SET `lastlogin_succ`= :lastlogin_succ, `loginfail_count`='0' WHERE `$uid`= :uid"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "lastlogin_succ" => time(), "uid" => $userinfo[$uid] - )); + ]); $userinfo['userid'] = $userinfo[$uid]; $userinfo['adminsession'] = $adminsession; } @@ -237,21 +254,21 @@ if ($action == '2fa_entercode') { $stmt = Database::prepare("UPDATE $table SET `lastlogin_fail`= :lastlogin_fail, `loginfail_count`=`loginfail_count`+1 WHERE `$uid`= :uid"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "lastlogin_fail" => time(), "uid" => $userinfo[$uid] - )); + ]); // Log failed login - $rstlog = FroxlorLogger::getInstanceOf(array( + $rstlog = FroxlorLogger::getInstanceOf([ 'loginname' => $_SERVER['REMOTE_ADDR'] - )); - $rstlog->logAction(\Froxlor\FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "User '" . $loginname . "' tried to login with wrong password."); + ]); + $rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "User '" . $loginname . "' tried to login with wrong password."); unset($userinfo); - \Froxlor\UI\Response::redirectTo('index.php', array( + Response::redirectTo('index.php', [ 'showmessage' => '2' - )); + ]); exit(); } @@ -266,27 +283,27 @@ if ($action == '2fa_entercode') { // send mail if type_2fa = 1 (email) if ($userinfo['type_2fa'] == 1) { // generate code - $tfa = new \Froxlor\FroxlorTwoFactorAuth('Froxlor'); + $tfa = new FroxlorTwoFactorAuth('Froxlor'); $code = $tfa->getCode($tfa->createSecret()); // set code for user $stmt = Database::prepare("UPDATE $table SET `data_2fa` = :d2fa WHERE `$uid` = :uid"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "d2fa" => $code, "uid" => $userinfo[$uid] - )); + ]); // build up & send email $_mailerror = false; $mailerr_msg = ""; - $replace_arr = array( + $replace_arr = [ 'CODE' => $code - ); - $mail_body = html_entity_decode(\Froxlor\PhpHelper::replaceVariables($lng['mails']['2fa']['mailbody'], $replace_arr)); + ]; + $mail_body = html_entity_decode(PhpHelper::replaceVariables(lng('mails.2fa.mailbody'), $replace_arr)); try { - $mail->Subject = $lng['mails']['2fa']['subject']; + $mail->Subject = lng('mails.2fa.subject'); $mail->AltBody = $mail_body; $mail->MsgHTML(str_replace("\n", "
", $mail_body)); - $mail->AddAddress($userinfo['email'], \Froxlor\User::getCorrectUserSalutation($userinfo)); + $mail->AddAddress($userinfo['email'], User::getCorrectUserSalutation($userinfo)); $mail->Send(); } catch (\PHPMailer\PHPMailer\Exception $e) { $mailerr_msg = $e->errorMessage(); @@ -297,67 +314,66 @@ if ($action == '2fa_entercode') { } if ($_mailerror) { - $rstlog = FroxlorLogger::getInstanceOf(array( + $rstlog = FroxlorLogger::getInstanceOf([ 'loginname' => '2fa code-sending' - )); - $rstlog->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg); - \Froxlor\UI\Response::redirectTo('index.php', array( + ]); + $rstlog->logAction(FroxlorLogger::ADM_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg); + Response::redirectTo('index.php', [ 'showmessage' => '4', 'customermail' => $userinfo['email'] - )); + ]); exit(); } $mail->ClearAddresses(); } - \Froxlor\UI\Response::redirectTo('index.php', array( + Response::redirectTo('index.php', [ 'action' => '2fa_entercode' - )); + ]); exit(); } if (!finishLogin($userinfo)) { - \Froxlor\UI\Response::redirectTo('index.php', array( + Response::redirectTo('index.php', [ 'showmessage' => '2' - )); + ]); } exit(); } else { - - $smessage = isset($_GET['showmessage']) ? (int) $_GET['showmessage'] : 0; + $smessage = isset($_GET['showmessage']) ? (int)$_GET['showmessage'] : 0; $message = ''; $successmessage = ''; switch ($smessage) { case 1: - $successmessage = $lng['pwdreminder']['success']; + $successmessage = lng('pwdreminder.success'); break; case 2: - $message = $lng['error']['login']; + $message = lng('error.login'); break; case 3: - $message = sprintf($lng['error']['login_blocked'], Settings::Get('login.deactivatetime')); + $message = lng('error.login_blocked', [Settings::Get('login.deactivatetime')]); break; case 4: $cmail = isset($_GET['customermail']) ? $_GET['customermail'] : 'unknown'; - $message = str_replace('%s', $cmail, $lng['error']['errorsendingmail']); + $message = str_replace('%s', $cmail, lng('error.errorsendingmail')); break; case 5: - $message = $lng['error']['user_banned']; + $message = lng('error.user_banned'); break; case 6: - $successmessage = $lng['pwdreminder']['changed']; + $successmessage = lng('pwdreminder.changed'); break; case 7: - $message = $lng['pwdreminder']['wrongcode']; + $message = lng('pwdreminder.wrongcode'); break; case 8: - $message = $lng['pwdreminder']['notallowed']; + $message = lng('pwdreminder.notallowed'); break; } $update_in_progress = false; - if (\Froxlor\Froxlor::hasUpdates() || \Froxlor\Froxlor::hasDbUpdates()) { + if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) { $update_in_progress = true; } @@ -394,24 +410,24 @@ if ($action == 'forgotpwd') { $message = ''; if (isset($_POST['send']) && $_POST['send'] == 'send') { - $loginname = \Froxlor\Validate\Validate::validate($_POST['loginname'], 'loginname'); - $email = \Froxlor\Validate\Validate::validateEmail($_POST['loginemail'], 'email'); + $loginname = Validate::validate($_POST['loginname'], 'loginname'); + $email = Validate::validateEmail($_POST['loginemail'], 'email'); $result_stmt = Database::prepare("SELECT `adminid`, `customerid`, `customernumber`, `firstname`, `name`, `company`, `email`, `loginname`, `def_language`, `deactivated` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `loginname`= :loginname AND `email`= :email"); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ "loginname" => $loginname, "email" => $email - )); + ]); if (Database::num_rows() == 0) { $result_stmt = Database::prepare("SELECT `adminid`, `name`, `email`, `loginname`, `def_language`, `deactivated` FROM `" . TABLE_PANEL_ADMINS . "` WHERE `loginname`= :loginname AND `email`= :email"); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ "loginname" => $loginname, "email" => $email - )); + ]); if (Database::num_rows() > 0) { $adminchecked = true; @@ -425,9 +441,9 @@ if ($action == 'forgotpwd') { /* Check whether user is banned */ if ($user['deactivated']) { - \Froxlor\UI\Response::redirectTo('index.php', array( + Response::redirectTo('index.php', [ 'showmessage' => '8' - )); + ]); exit(); } @@ -435,36 +451,36 @@ if ($action == 'forgotpwd') { if ($user !== false) { // build a activation code $timestamp = time(); - $first = substr(md5($user['loginname'] . $timestamp . \Froxlor\PhpHelper::randomStr(16)), 0, 15); - $third = substr(md5($user['email'] . $timestamp . \Froxlor\PhpHelper::randomStr(16)), -15); + $first = substr(md5($user['loginname'] . $timestamp . PhpHelper::randomStr(16)), 0, 15); + $third = substr(md5($user['email'] . $timestamp . PhpHelper::randomStr(16)), -15); $activationcode = $first . $timestamp . $third . substr(md5($third . $timestamp), 0, 10); // Drop all existing activation codes for this user $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_ACTIVATION . "` WHERE `userid` = :userid AND `admin` = :admin"); - $params = array( + $params = [ "userid" => $adminchecked ? $user['adminid'] : $user['customerid'], "admin" => $adminchecked ? 1 : 0 - ); + ]; Database::pexecute($stmt, $params); // Add new activation code to database $stmt = Database::prepare("INSERT INTO `" . TABLE_PANEL_ACTIVATION . "` (userid, admin, creation, activationcode) VALUES (:userid, :admin, :creation, :activationcode)"); - $params = array( + $params = [ "userid" => $adminchecked ? $user['adminid'] : $user['customerid'], "admin" => $adminchecked ? 1 : 0, "creation" => $timestamp, "activationcode" => $activationcode - ); + ]; Database::pexecute($stmt, $params); - $rstlog = FroxlorLogger::getInstanceOf(array( + $rstlog = FroxlorLogger::getInstanceOf([ 'loginname' => 'password_reset' - )); - $rstlog->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "User '" . $user['loginname'] . "' requested a link for setting a new password."); + ]); + $rstlog->logAction(FroxlorLogger::USR_ACTION, LOG_WARNING, "User '" . $user['loginname'] . "' requested a link for setting a new password."); // Set together our activation link $protocol = empty($_SERVER['HTTPS']) ? 'http' : 'https'; @@ -478,19 +494,19 @@ if ($action == 'forgotpwd') { // there can be only one script to handle this so we can use a fixed value here $script = "/index.php"; // $_SERVER['SCRIPT_NAME']; if (Settings::Get('system.froxlordirectlyviahostname') == 0) { - $script = \Froxlor\FileDir::makeCorrectFile("/" . basename(__DIR__) . "/" . $script); + $script = FileDir::makeCorrectFile("/" . basename(__DIR__) . "/" . $script); } $activationlink = $protocol . '://' . $host . $port . $script . '?action=resetpwd&resetcode=' . $activationcode; - $replace_arr = array( - 'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($user), + $replace_arr = [ + 'SALUTATION' => User::getCorrectUserSalutation($user), 'NAME' => $user['name'], 'FIRSTNAME' => $user['firstname'] ?? "", 'COMPANY' => $user['company'] ?? "", 'CUSTOMER_NO' => $user['customernumber'] ?? 0, 'USERNAME' => $loginname, 'LINK' => $activationlink - ); + ]; $def_language = ($user['def_language'] != '') ? $user['def_language'] : Settings::Get('panel.standardlanguage'); $result_stmt = Database::prepare('SELECT `value` FROM `' . TABLE_PANEL_TEMPLATES . '` @@ -498,24 +514,24 @@ if ($action == 'forgotpwd') { AND `language`= :lang AND `templategroup`=\'mails\' AND `varname`=\'password_reset_subject\''); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ "adminid" => $user['adminid'], "lang" => $def_language - )); + ]); $result = $result_stmt->fetch(PDO::FETCH_ASSOC); - $mail_subject = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result['value'] != '') ? $result['value'] : $lng['mails']['password_reset']['subject']), $replace_arr)); + $mail_subject = html_entity_decode(PhpHelper::replaceVariables((($result['value'] != '') ? $result['value'] : lng('mails.password_reset.subject')), $replace_arr)); $result_stmt = Database::prepare('SELECT `value` FROM `' . TABLE_PANEL_TEMPLATES . '` WHERE `adminid`= :adminid AND `language`= :lang AND `templategroup`=\'mails\' AND `varname`=\'password_reset_mailbody\''); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ "adminid" => $user['adminid'], "lang" => $def_language - )); + ]); $result = $result_stmt->fetch(PDO::FETCH_ASSOC); - $mail_body = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result['value'] != '') ? $result['value'] : $lng['mails']['password_reset']['mailbody']), $replace_arr)); + $mail_body = html_entity_decode(PhpHelper::replaceVariables((($result['value'] != '') ? $result['value'] : lng('mails.password_reset.mailbody')), $replace_arr)); $_mailerror = false; $mailerr_msg = ""; @@ -523,7 +539,7 @@ if ($action == 'forgotpwd') { $mail->Subject = $mail_subject; $mail->AltBody = $mail_body; $mail->MsgHTML(str_replace("\n", "
", $mail_body)); - $mail->AddAddress($user['email'], \Froxlor\User::getCorrectUserSalutation($user)); + $mail->AddAddress($user['email'], User::getCorrectUserSalutation($user)); $mail->Send(); } catch (\PHPMailer\PHPMailer\Exception $e) { $mailerr_msg = $e->errorMessage(); @@ -534,50 +550,50 @@ if ($action == 'forgotpwd') { } if ($_mailerror) { - $rstlog = FroxlorLogger::getInstanceOf(array( + $rstlog = FroxlorLogger::getInstanceOf([ 'loginname' => 'password_reset' - )); - $rstlog->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg); - \Froxlor\UI\Response::redirectTo('index.php', array( + ]); + $rstlog->logAction(FroxlorLogger::ADM_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg); + Response::redirectTo('index.php', [ 'showmessage' => '4', 'customermail' => $user['email'] - )); + ]); exit(); } $mail->ClearAddresses(); - \Froxlor\UI\Response::redirectTo('index.php', array( + Response::redirectTo('index.php', [ 'showmessage' => '1' - )); + ]); exit(); } else { - $rstlog = FroxlorLogger::getInstanceOf(array( + $rstlog = FroxlorLogger::getInstanceOf([ 'loginname' => 'password_reset' - )); - $rstlog->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "User '" . $loginname . "' requested to set a new password, but was not found in database!"); - $message = $lng['login']['combination_not_found']; + ]); + $rstlog->logAction(FroxlorLogger::USR_ACTION, LOG_WARNING, "User '" . $loginname . "' requested to set a new password, but was not found in database!"); + $message = lng('login.combination_not_found'); } unset($user); } } else { - $message = $lng['login']['usernotfound']; + $message = lng('login.usernotfound'); } } if ($adminchecked) { if (Settings::Get('panel.allow_preset_admin') != '1') { - $message = $lng['pwdreminder']['notallowed']; + $message = lng('pwdreminder.notallowed'); unset($adminchecked); } } else { if (Settings::Get('panel.allow_preset') != '1') { - $message = $lng['pwdreminder']['notallowed']; + $message = lng('pwdreminder.notallowed'); } } UI::view('login/fpwd.html.twig', [ - 'pagetitle' => $lng['login']['presend'], + 'pagetitle' => lng('login.presend'), 'action' => $action, 'message' => $message, ]); @@ -589,9 +605,9 @@ if ($action == 'resetpwd') { // Remove old activation codes $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_ACTIVATION . "` WHERE creation < :oldest"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "oldest" => time() - 86400 - )); + ]); if (isset($_GET['resetcode']) && strlen($_GET['resetcode']) == 50) { // Check if activation code is valid @@ -604,20 +620,20 @@ if ($action == 'resetpwd') { if (isset($_POST['send']) && $_POST['send'] == 'send') { $stmt = Database::prepare("SELECT `userid`, `admin` FROM `" . TABLE_PANEL_ACTIVATION . "` WHERE `activationcode` = :activationcode"); - $result = Database::pexecute_first($stmt, array( + $result = Database::pexecute_first($stmt, [ "activationcode" => $activationcode - )); + ]); if ($result !== false) { try { - $new_password = \Froxlor\System\Crypt::validatePassword($_POST['new_password'], true); - $new_password_confirm = \Froxlor\System\Crypt::validatePassword($_POST['new_password_confirm'], true); + $new_password = Crypt::validatePassword($_POST['new_password'], true); + $new_password_confirm = Crypt::validatePassword($_POST['new_password_confirm'], true); } catch (Exception $e) { $message = $e->getMessage(); } if (empty($message) && (empty($new_password) || $new_password != $new_password_confirm)) { - $message = $lng['error']['newpasswordconfirmerror']; + $message = lng('error.newpasswordconfirmerror'); } if (empty($message)) { @@ -631,47 +647,47 @@ if ($action == 'resetpwd') { SET `password` = :newpassword WHERE `customerid` = :userid"); } - Database::pexecute($stmt, array( - "newpassword" => \Froxlor\System\Crypt::makeCryptPassword($new_password), + Database::pexecute($stmt, [ + "newpassword" => Crypt::makeCryptPassword($new_password), "userid" => $result['userid'] - )); + ]); - $rstlog = FroxlorLogger::getInstanceOf(array( + $rstlog = FroxlorLogger::getInstanceOf([ 'loginname' => 'password_reset' - )); - $rstlog->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "changed password using password reset."); + ]); + $rstlog->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "changed password using password reset."); // Remove activation code from DB $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_ACTIVATION . "` WHERE `activationcode` = :activationcode AND `userid` = :userid"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "activationcode" => $activationcode, "userid" => $result['userid'] - )); - \Froxlor\UI\Response::redirectTo('index.php', array( + ]); + Response::redirectTo('index.php', [ "showmessage" => '6' - )); + ]); } } else { - \Froxlor\UI\Response::redirectTo('index.php', array( + Response::redirectTo('index.php', [ "showmessage" => '7' - )); + ]); } } UI::view('login/rpwd.html.twig', [ - 'pagetitle' => $lng['pwdreminder']['choosenew'], + 'pagetitle' => lng('pwdreminder.choosenew'), 'formaction' => 'index.php?action=resetpwd&resetcode=' . $activationcode, 'message' => $message, ]); } else { - \Froxlor\UI\Response::redirectTo('index.php', array( + Response::redirectTo('index.php', [ "showmessage" => '7' - )); + ]); } } else { - \Froxlor\UI\Response::redirectTo('index.php'); + Response::redirectTo('index.php'); } } @@ -680,11 +696,10 @@ function finishLogin($userinfo) global $languages; if (isset($userinfo['userid']) && $userinfo['userid'] != '') { - - \Froxlor\CurrentUser::setData($userinfo); + CurrentUser::setData($userinfo); if (isset($_POST['language'])) { - $language = \Froxlor\Validate\Validate::validate($_POST['language'], 'language'); + $language = Validate::validate($_POST['language'], 'language'); if ($language == 'profile') { $language = $userinfo['def_language']; } elseif (!isset($languages[$language])) { @@ -693,41 +708,41 @@ function finishLogin($userinfo) } else { $language = Settings::Get('panel.standardlanguage'); } - \Froxlor\CurrentUser::setField('language', $language); + CurrentUser::setField('language', $language); if (isset($userinfo['theme']) && $userinfo['theme'] != '') { $theme = $userinfo['theme']; } else { $theme = Settings::Get('panel.default_theme'); - \Froxlor\CurrentUser::setField('theme', $theme); + CurrentUser::setField('theme', $theme); } - $qryparams = array(); + $qryparams = []; if (isset($_POST['qrystr']) && $_POST['qrystr'] != "") { parse_str(urldecode($_POST['qrystr']), $qryparams); } if ($userinfo['adminsession'] == '1') { - if (\Froxlor\Froxlor::hasUpdates() || \Froxlor\Froxlor::hasDbUpdates()) { - \Froxlor\UI\Response::redirectTo('admin_updates.php?page=overview'); + if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) { + Response::redirectTo('admin_updates.php?page=overview'); } else { if (isset($_POST['script']) && $_POST['script'] != "") { if (preg_match("/customer\_/", $_POST['script']) === 1) { - \Froxlor\UI\Response::redirectTo('admin_customers.php', array( + Response::redirectTo('admin_customers.php', [ "page" => "customers" - )); + ]); } else { - \Froxlor\UI\Response::redirectTo($_POST['script'], $qryparams); + Response::redirectTo($_POST['script'], $qryparams); } } else { - \Froxlor\UI\Response::redirectTo('admin_index.php', $qryparams); + Response::redirectTo('admin_index.php', $qryparams); } } } else { if (isset($_POST['script']) && $_POST['script'] != "") { - \Froxlor\UI\Response::redirectTo($_POST['script'], $qryparams); + Response::redirectTo($_POST['script'], $qryparams); } else { - \Froxlor\UI\Response::redirectTo('customer_index.php', $qryparams); + Response::redirectTo('customer_index.php', $qryparams); } } } diff --git a/install/froxlor.sql.php b/install/froxlor.sql.php index 07dfbca1..40654f03 100644 --- a/install/froxlor.sql.php +++ b/install/froxlor.sql.php @@ -11,16 +11,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 + * 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 - * http://files.froxlor.org/misc/COPYING.txt + * https://files.froxlor.org/misc/COPYING.txt * * @copyright the authors * @author Froxlor team - * @license http://files.froxlor.org/misc/COPYING.txt GPLv2 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ return << - * @license http://files.froxlor.org/misc/COPYING.txt GPLv2 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ use Froxlor\Install\Install; diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index c5d71c8d..526d30e2 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -4,17 +4,23 @@ * 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 (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes + * 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.29.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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ use Froxlor\Froxlor; @@ -29,7 +35,7 @@ use Froxlor\UI\Panel\UI; * * @copyright (c) the authors * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @license GPLv2 https://files.froxlor.org/misc/COPYING.txt * @package Install * */ diff --git a/install/lng/english.lng.php b/install/lng/english.lng.php index 031c6ff8..25475920 100644 --- a/install/lng/english.lng.php +++ b/install/lng/english.lng.php @@ -7,12 +7,12 @@ * * 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 + * COPYING file online at https://files.froxlor.org/misc/COPYING.txt * * @copyright (c) the authors * @author Florian Lippert (2003-2009) * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @license GPLv2 https://files.froxlor.org/misc/COPYING.txt * @package Language * */ diff --git a/install/lng/french.lng.php b/install/lng/french.lng.php index aa27427e..114d563a 100644 --- a/install/lng/french.lng.php +++ b/install/lng/french.lng.php @@ -7,12 +7,12 @@ * * 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 + * COPYING file online at https://files.froxlor.org/misc/COPYING.txt * * @copyright (c) the authors * @author Florian Lippert (2003-2009) * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @license GPLv2 https://files.froxlor.org/misc/COPYING.txt * @package Language * */ diff --git a/install/lng/german.lng.php b/install/lng/german.lng.php index 0a1226ed..5f4705d4 100644 --- a/install/lng/german.lng.php +++ b/install/lng/german.lng.php @@ -7,12 +7,12 @@ * * 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 + * COPYING file online at https://files.froxlor.org/misc/COPYING.txt * * @copyright (c) the authors * @author Florian Lippert (2003-2009) * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @license GPLv2 https://files.froxlor.org/misc/COPYING.txt * @package Language * */ diff --git a/install/updates/froxlor/0.11/update_0.11.inc.php b/install/updates/froxlor/0.11/update_0.11.inc.php index 80b7c141..9ba10e9b 100644 --- a/install/updates/froxlor/0.11/update_0.11.inc.php +++ b/install/updates/froxlor/0.11/update_0.11.inc.php @@ -11,16 +11,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 + * 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 - * http://files.froxlor.org/misc/COPYING.txt + * https://files.froxlor.org/misc/COPYING.txt * * @copyright the authors * @author Froxlor team - * @license http://files.froxlor.org/misc/COPYING.txt GPLv2 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ use Froxlor\Froxlor; diff --git a/install/updates/preconfig.php b/install/updates/preconfig.php index 50562089..e01c09fe 100644 --- a/install/updates/preconfig.php +++ b/install/updates/preconfig.php @@ -11,16 +11,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 + * 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 - * http://files.froxlor.org/misc/COPYING.txt + * https://files.froxlor.org/misc/COPYING.txt * * @copyright the authors * @author Froxlor team - * @license http://files.froxlor.org/misc/COPYING.txt GPLv2 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ use Froxlor\Froxlor; diff --git a/install/updates/preconfig/0.11/preconfig_0.11.inc.php b/install/updates/preconfig/0.11/preconfig_0.11.inc.php index 8266abee..c86d8bb2 100644 --- a/install/updates/preconfig/0.11/preconfig_0.11.inc.php +++ b/install/updates/preconfig/0.11/preconfig_0.11.inc.php @@ -6,11 +6,11 @@ * * 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 + * COPYING file online at https://files.froxlor.org/misc/COPYING.txt * * @copyright (c) the authors * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @license GPLv2 https://files.froxlor.org/misc/COPYING.txt * @package Updater * */ @@ -24,7 +24,7 @@ * pointer to output string * @param string $current_version * current froxlor version - * + * * @return void */ function parseAndOutputPreconfig011(&$has_preconfig, &$return, $current_version, $current_db_version) diff --git a/install/updatesql.php b/install/updatesql.php index e5b72f62..41acf326 100644 --- a/install/updatesql.php +++ b/install/updatesql.php @@ -11,16 +11,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 + * 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 - * http://files.froxlor.org/misc/COPYING.txt + * https://files.froxlor.org/misc/COPYING.txt * * @copyright the authors * @author Froxlor team - * @license http://files.froxlor.org/misc/COPYING.txt GPLv2 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ use Froxlor\Froxlor; @@ -46,7 +46,7 @@ $filelog = FroxlorLogger::getInstanceOf(array( try { $filelog->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, '-------------- START LOG --------------'); } catch (Exception $e) { - Response::standard_error('exception', $e->getMessage()); + Response::standardError('exception', $e->getMessage()); } if (Froxlor::isFroxlor()) { diff --git a/lib/Froxlor/Ajax/Ajax.php b/lib/Froxlor/Ajax/Ajax.php index e0d8cc3e..677ece83 100644 --- a/lib/Froxlor/Ajax/Ajax.php +++ b/lib/Froxlor/Ajax/Ajax.php @@ -1,35 +1,46 @@ (2010-) - * @author Maurice Preuß - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package AJAX + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\Ajax; + +use Exception; +use Froxlor\Config\ConfigDisplay; +use Froxlor\Config\ConfigParser; +use Froxlor\CurrentUser; +use Froxlor\Database\Database; +use Froxlor\FileDir; +use Froxlor\Froxlor; +use Froxlor\Http\HttpClient; +use Froxlor\Settings; +use Froxlor\UI\Listing; +use Froxlor\UI\Panel\UI; +use Froxlor\UI\Request; +use Froxlor\UI\Response; +use Froxlor\Validate\Validate; +use PDO; + class Ajax { protected string $action; @@ -49,55 +60,6 @@ class Ajax UI::sendSslHeaders(); } - /** - * initialize global $lng variable to have - * localized strings available for the ApiCommands - */ - private function initLang() - { - global $lng; - - // query the whole table - $result_stmt = Database::query("SELECT * FROM `" . TABLE_PANEL_LANGUAGE . "`"); - - $langs = array(); - // presort languages - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { - $langs[$row['language']][] = $row; - } - - // set default language before anything else to - // ensure that we can display messages - $language = \Froxlor\Settings::Get('panel.standardlanguage'); - - if (isset($this->userinfo['language']) && isset($langs[$this->userinfo['language']])) { - // default: use language from session, #277 - $language = $this->userinfo['language']; - } elseif (isset($this->userinfo['def_language'])) { - $language = $this->userinfo['def_language']; - } - - // include every english language file we can get - foreach ($langs['English'] as $value) { - include_once \Froxlor\FileDir::makeSecurePath(\Froxlor\Froxlor::getInstallDir() . '/' . $value['file']); - } - - // now include the selected language if its not english - if ($language != 'English') { - if (isset($langs[$language])) { - foreach ($langs[$language] as $value) { - include_once \Froxlor\FileDir::makeSecurePath(\Froxlor\Froxlor::getInstallDir() . '/' . $value['file']); - } - } - } - - // last but not least include language references file - include_once \Froxlor\FileDir::makeSecurePath(\Froxlor\Froxlor::getInstallDir() . '/lng/lng_references.php'); - - // set array - $this->lng = $lng; - } - /** * @throws Exception */ @@ -127,27 +89,64 @@ class Ajax } } - public function errorResponse($message, int $response_code = 500) - { - header("Content-Type: application/json"); - return \Froxlor\Api\Response::jsonErrorResponse($message, $response_code); - } - - public function jsonResponse($value, int $response_code = 200) - { - header("Content-Type: application/json"); - return \Froxlor\Api\Response::jsonResponse($value, $response_code); - } - /** * @throws Exception */ private function getValidatedSession(): array { - if (\Froxlor\CurrentUser::hasSession() == false) { + if (CurrentUser::hasSession() == false) { throw new Exception("No valid session"); } - return \Froxlor\CurrentUser::getData(); + return CurrentUser::getData(); + } + + /** + * initialize global $lng variable to have + * localized strings available for the ApiCommands + */ + private function initLang() + { + global $lng; + + // query the whole table + $result_stmt = Database::query("SELECT * FROM `" . TABLE_PANEL_LANGUAGE . "`"); + + $langs = []; + // presort languages + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + $langs[$row['language']][] = $row; + } + + // set default language before anything else to + // ensure that we can display messages + $language = Settings::Get('panel.standardlanguage'); + + if (isset($this->userinfo['language']) && isset($langs[$this->userinfo['language']])) { + // default: use language from session, #277 + $language = $this->userinfo['language']; + } elseif (isset($this->userinfo['def_language'])) { + $language = $this->userinfo['def_language']; + } + + // include every english language file we can get + foreach ($langs['English'] as $value) { + include_once FileDir::makeSecurePath(Froxlor::getInstallDir() . '/' . $value['file']); + } + + // now include the selected language if its not english + if ($language != 'English') { + if (isset($langs[$language])) { + foreach ($langs[$language] as $value) { + include_once FileDir::makeSecurePath(Froxlor::getInstallDir() . '/' . $value['file']); + } + } + } + + // last but not least include language references file + include_once FileDir::makeSecurePath(Froxlor::getInstallDir() . '/lng/lng_references.php'); + + // set array + $this->lng = $lng; } /** @@ -213,6 +212,18 @@ class Ajax } } + public function errorResponse($message, int $response_code = 500) + { + header("Content-Type: application/json"); + return \Froxlor\Api\Response::jsonErrorResponse($message, $response_code); + } + + public function jsonResponse($value, int $response_code = 200) + { + header("Content-Type: application/json"); + return \Froxlor\Api\Response::jsonResponse($value, $response_code); + } + private function getUpdateCheck() { UI::initTwig(); @@ -225,7 +236,7 @@ class Ajax } catch (Exception $e) { // don't display anything if just not allowed due to permissions if ($e->getCode() != 403) { - \Froxlor\UI\Response::dynamic_error($e->getMessage()); + Response::dynamicError($e->getMessage()); } } } @@ -271,9 +282,9 @@ class Ajax private function editApiKey() { - $keyid = isset($_POST['id']) ? (int) $_POST['id'] : 0; + $keyid = isset($_POST['id']) ? (int)$_POST['id'] : 0; $allowed_from = isset($_POST['allowed_from']) ? $_POST['allowed_from'] : ""; - $valid_until = isset($_POST['valid_until']) ? (int) $_POST['valid_until'] : -1; + $valid_until = isset($_POST['valid_until']) ? (int)$_POST['valid_until'] : -1; // validate allowed_from if (!empty($allowed_from)) { @@ -309,18 +320,18 @@ class Ajax `valid_until` = :vu, `allowed_from` = :af WHERE `id` = :keyid AND `adminid` = :aid AND `customerid` = :cid "); - if ((int) $this->userinfo['adminsession'] == 1) { + if ((int)$this->userinfo['adminsession'] == 1) { $cid = 0; } else { $cid = $this->userinfo['customerid']; } - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'keyid' => $keyid, 'af' => $allowed_from, 'vu' => $valid_until, 'aid' => $this->userinfo['adminid'], 'cid' => $cid - )); + ]); return $this->jsonResponse(['allowed_from' => $allowed_from, 'valid_until' => $valid_until]); } diff --git a/lib/Froxlor/Ajax/GlobalSearch.php b/lib/Froxlor/Ajax/GlobalSearch.php index 6e466a6d..1a79f46d 100644 --- a/lib/Froxlor/Ajax/GlobalSearch.php +++ b/lib/Froxlor/Ajax/GlobalSearch.php @@ -1,26 +1,46 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package AJAX + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\Ajax; + +use Froxlor\Api\Commands\Admins; +use Froxlor\Api\Commands\Customers; +use Froxlor\Api\Commands\Domains; +use Froxlor\Api\Commands\Emails; +use Froxlor\Api\Commands\FpmDaemons; +use Froxlor\Api\Commands\Ftps; +use Froxlor\Api\Commands\HostingPlans; +use Froxlor\Api\Commands\IpsAndPorts; +use Froxlor\Api\Commands\Mysqls; +use Froxlor\Api\Commands\PhpSettings; +use Froxlor\Api\Commands\SubDomains; +use Froxlor\Froxlor; +use Froxlor\PhpHelper; +use Froxlor\Settings; +use Froxlor\UI\Collection; + class GlobalSearch { protected array $userinfo; @@ -42,7 +62,7 @@ class GlobalSearch } } $settings_data = PhpHelper::loadConfigArrayDir(Froxlor::getInstallDir() . '/actions/admin/settings/'); - $results = array(); + $results = []; if (!isset($processed['settings'])) { $processed['settings'] = []; } @@ -51,13 +71,13 @@ class GlobalSearch $pk = explode(".", $pathkey); if (count($pk) > 4) { $settingkey = $pk[0] . '.' . $pk[1] . '.' . $pk[2] . '.' . $pk[3]; - if (isset($settings_data[$pk[0]][$pk[1]]['advanced_mode']) && $settings_data[$pk[0]][$pk[1]]['advanced_mode'] && (int) Settings::Get('panel.settings_mode') == 0) { + if (isset($settings_data[$pk[0]][$pk[1]]['advanced_mode']) && $settings_data[$pk[0]][$pk[1]]['advanced_mode'] && (int)Settings::Get('panel.settings_mode') == 0) { continue; } if (is_array($processed['settings']) && !array_key_exists($settingkey, $processed['settings'])) { $processed['settings'][$settingkey] = true; $sresult = $settings_data[$pk[0]][$pk[1]][$pk[2]][$pk[3]]; - if (isset($sresult['advanced_mode']) && $sresult['advanced_mode'] && (int) Settings::Get('panel.settings_mode') == 0) { + if (isset($sresult['advanced_mode']) && $sresult['advanced_mode'] && (int)Settings::Get('panel.settings_mode') == 0) { continue; } if ($sresult['type'] != 'hidden') { @@ -78,7 +98,7 @@ class GlobalSearch } /** - * + * */ public static function searchGlobal(string $searchtext, array $userinfo): array { @@ -90,7 +110,6 @@ class GlobalSearch $module = ""; foreach ($stparts as $searchtext) { - $searchtext = trim($searchtext); if (preg_match('/^([a-z]+):$/', $searchtext, $matches)) { @@ -104,11 +123,10 @@ class GlobalSearch // admin if (isset($userinfo['adminsession']) && $userinfo['adminsession'] == 1) { - $toSearch = [ // customers 'customer' => [ - 'class' => \Froxlor\Api\Commands\Customers::class, + 'class' => Customers::class, 'searchfields' => [ 'c.loginname', 'c.name', @@ -129,7 +147,7 @@ class GlobalSearch ], // domains 'domains' => [ - 'class' => \Froxlor\Api\Commands\Domains::class, + 'class' => Domains::class, 'searchfields' => [ 'd.domain', 'd.domain_ace', @@ -144,7 +162,7 @@ class GlobalSearch ], // ips and ports 'ipsandports' => [ - 'class' => \Froxlor\Api\Commands\IpsAndPorts::class, + 'class' => IpsAndPorts::class, 'searchfields' => [ 'ip', 'vhostcontainer', @@ -160,7 +178,7 @@ class GlobalSearch ], // hosting-plans 'hostingplans' => [ - 'class' => \Froxlor\Api\Commands\HostingPlans::class, + 'class' => HostingPlans::class, 'searchfields' => [ 'p.name', 'p.description' @@ -174,7 +192,7 @@ class GlobalSearch ], // PHP configs 'phpconfigs' => [ - 'class' => \Froxlor\Api\Commands\PhpSettings::class, + 'class' => PhpSettings::class, 'searchfields' => [ 'c.description', 'fd.description', @@ -189,7 +207,7 @@ class GlobalSearch ], // FPM daemons 'fpmconfigs' => [ - 'class' => \Froxlor\Api\Commands\FpmDaemons::class, + 'class' => FpmDaemons::class, 'searchfields' => [ 'description', 'reload_cmd' @@ -203,10 +221,10 @@ class GlobalSearch ] ]; - if ((bool) $userinfo['change_serversettings']) { + if ((bool)$userinfo['change_serversettings']) { // admins $toSearch['admins'] = [ - 'class' => \Froxlor\Api\Commands\Admins::class, + 'class' => Admins::class, 'searchfields' => [ 'loginname', 'name', @@ -225,7 +243,7 @@ class GlobalSearch $toSearch = [ // (sub)domains 'domains' => [ - 'class' => \Froxlor\Api\Commands\SubDomains::class, + 'class' => SubDomains::class, 'searchfields' => [ 'd.domain', 'd.domain_ace', @@ -240,7 +258,7 @@ class GlobalSearch ], // email addresses 'emails' => [ - 'class' => \Froxlor\Api\Commands\Emails::class, + 'class' => Emails::class, 'searchfields' => [ 'm.email', 'm.email_full' @@ -254,7 +272,7 @@ class GlobalSearch ], // databases 'databases' => [ - 'class' => \Froxlor\Api\Commands\Mysqls::class, + 'class' => Mysqls::class, 'searchfields' => [ 'databasename', 'description' @@ -268,7 +286,7 @@ class GlobalSearch ], // ftp user 'ftpuser' => [ - 'class' => \Froxlor\Api\Commands\Ftps::class, + 'class' => Ftps::class, 'searchfields' => [ 'username', 'description' @@ -290,11 +308,12 @@ class GlobalSearch } foreach ($toSearch as $entity => $edata) { - $collection = (new Collection($edata['class'], $userinfo)) - ->addParam(['sql_search' => [ - '_plainsql' => self::searchStringSql($edata['searchfields'], $searchtext) - ]]); + ->addParam([ + 'sql_search' => [ + '_plainsql' => self::searchStringSql($edata['searchfields'], $searchtext) + ] + ]); if ($collection->count() > 0) { if (!isset($processed[$entity])) { $processed[$entity] = []; @@ -320,7 +339,7 @@ class GlobalSearch return $result; } - private static function searchStringSql(array $searchfields, $searchtext) + private static function searchStringSql(array $searchfields, $searchtext) { $result = ['sql' => [], 'values' => []]; $result['sql'] = "("; diff --git a/lib/Froxlor/Api/Api.php b/lib/Froxlor/Api/Api.php index 8b470f94..e04affa1 100644 --- a/lib/Froxlor/Api/Api.php +++ b/lib/Froxlor/Api/Api.php @@ -1,25 +1,34 @@ (2010-) - * @author Maurice Preuß - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\Api; + +use Exception; +use Froxlor\Settings; +use voku\helper\AntiXSS; + class Api { protected array $headers; @@ -40,14 +49,14 @@ class Api header("Content-Type: application/json"); // check whether API interface is enabled after all - if (\Froxlor\Settings::Get('api.enabled') != 1) { + if (Settings::Get('api.enabled') != 1) { throw new Exception('API is not enabled. Please contact the administrator if you think this is wrong.', 400); } } /** * @param mixed $request - * + * * @return Api */ public function formatMiddleware($request): Api @@ -65,6 +74,7 @@ class Api } return $this; } + /** * Handle incoming api request to our backend. * @@ -74,7 +84,7 @@ class Api { $request = $this->request; // validate content - $request = \Froxlor\Api\FroxlorRPC::validateRequest($request); + $request = FroxlorRPC::validateRequest($request); $request = (new AntiXSS())->xss_clean( $this->stripcslashesDeep($request) ); diff --git a/lib/Froxlor/Api/ApiCommand.php b/lib/Froxlor/Api/ApiCommand.php index 4f1f47fa..5ee3f2c6 100644 --- a/lib/Froxlor/Api/ApiCommand.php +++ b/lib/Froxlor/Api/ApiCommand.php @@ -11,68 +11,80 @@ * * 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 + * 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 - * http://files.froxlor.org/misc/COPYING.txt + * https://files.froxlor.org/misc/COPYING.txt * * @copyright the authors * @author Froxlor team - * @license http://files.froxlor.org/misc/COPYING.txt GPLv2 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ namespace Froxlor\Api; use Exception; +use Froxlor\Database\Database; use Froxlor\Froxlor; use Froxlor\FroxlorLogger; use Froxlor\Language; -use Froxlor\System\Mailer; -use Froxlor\Settings; -use Froxlor\Api\Response; use Froxlor\PhpHelper; -use Froxlor\Database\Database; +use Froxlor\Settings; +use Froxlor\System\Mailer; abstract class ApiCommand extends ApiParameter { + /** + * froxlor version + * + * @var string + */ + protected $version = null; + /** + * froxlor dbversion + * + * @var int + */ + protected $dbversion = null; + /** + * froxlor version-branding + * + * @var string + */ + protected $branding = null; /** * debug flag * * @var boolean */ private $debug = false; - /** * is admin flag * * @var boolean */ private $is_admin = false; - /** * internal user data array * * @var array */ private $user_data = null; - /** * logger interface * - * @var \Froxlor\FroxlorLogger + * @var FroxlorLogger */ private $logger = null; - /** * mail interface * - * @var \Froxlor\System\Mailer + * @var Mailer */ private $mail = null; - /** * whether the call is an internal one or not * @@ -80,39 +92,18 @@ abstract class ApiCommand extends ApiParameter */ private $internal_call = false; - /** - * froxlor version - * - * @var string - */ - protected $version = null; - - /** - * froxlor dbversion - * - * @var int - */ - protected $dbversion = null; - - /** - * froxlor version-branding - * - * @var string - */ - protected $branding = null; - /** * * @param array $header - * optional, passed via API + * optional, passed via API * @param array $params - * optional, array of parameters (var=>value) for the command + * optional, array of parameters (var=>value) for the command * @param array $userinfo - * optional, passed via WebInterface (instead of $header) + * optional, passed via WebInterface (instead of $header) * @param boolean $internal - * optional whether called internally, default false - * - * @throws \Exception + * optional whether called internally, default false + * + * @throws Exception */ public function __construct($header = null, $params = null, $userinfo = null, $internal = false) { @@ -154,57 +145,45 @@ abstract class ApiCommand extends ApiParameter } /** - * initialize language to have localized strings available for the ApiCommands + * read user data from database by api-request-header fields + * + * @param array $header + * api-request header + * + * @return boolean + * @throws Exception */ - private function initLang() + private function readUserData($header = null) { - Language::setLanguage(Settings::Get('panel.standardlanguage')); - - if ($this->getUserDetail('language') !== null && isset(Language::getLanguages()[$this->getUserDetail('language')])) { - Language::setLanguage($this->getUserDetail('language')); - } elseif ($this->getUserDetail('def_language') !== null) { - Language::setLanguage($this->getUserDetail('def_language')); + $sel_stmt = Database::prepare("SELECT * FROM `api_keys` WHERE `apikey` = :ak AND `secret` = :as"); + $result = Database::pexecute_first($sel_stmt, [ + 'ak' => $header['apikey'], + 'as' => $header['secret'] + ], true, true); + if ($result) { + // admin or customer? + if ($result['customerid'] == 0 && $result['adminid'] > 0) { + $this->is_admin = true; + $table = 'panel_admins'; + $key = "adminid"; + } elseif ($result['customerid'] > 0 && $result['adminid'] > 0) { + $this->is_admin = false; + $table = 'panel_customers'; + $key = "customerid"; + } else { + // neither adminid is > 0 nor customerid is > 0 - sorry man, no way + throw new Exception("Invalid API credentials", 400); + } + $sel_stmt = Database::prepare("SELECT * FROM `" . $table . "` WHERE `" . $key . "` = :id"); + $this->user_data = Database::pexecute_first($sel_stmt, [ + 'id' => ($this->is_admin ? $result['adminid'] : $result['customerid']) + ], true, true); + if ($this->is_admin) { + $this->user_data['adminsession'] = 1; + } + return true; } - } - - /** - * returns an instance of the wanted ApiCommand (e.g. - * Customers, Domains, etc); - * this is used widely in the WebInterface - * - * @param array $userinfo - * array of user-data - * @param array $params - * array of parameters for the command - * @param boolean $internal - * optional whether called internally, default false - * - * @return ApiCommand - * @throws \Exception - */ - public static function getLocal($userinfo = null, $params = null, $internal = false) - { - return new static(null, $params, $userinfo, $internal); - } - - /** - * admin flag - * - * @return boolean - */ - protected function isAdmin() - { - return $this->is_admin; - } - - /** - * internal call flag - * - * @return boolean - */ - protected function isInternal() - { - return $this->internal_call; + throw new Exception("Invalid API credentials", 400); } /** @@ -220,30 +199,69 @@ abstract class ApiCommand extends ApiParameter } /** - * return user-data array + * return logger instance * - * @return array + * @return FroxlorLogger */ - protected function getUserData() + protected function logger() { - return $this->user_data; + return $this->logger; + } + + /** + * initialize language to have localized strings available for the ApiCommands + */ + private function initLang() + { + Language::setLanguage(Settings::Get('panel.standardlanguage')); + + if ($this->getUserDetail('language') !== null && isset(Language::getLanguages()[$this->getUserDetail('language')])) { + Language::setLanguage($this->getUserDetail('language')); + } elseif ($this->getUserDetail('def_language') !== null) { + Language::setLanguage($this->getUserDetail('def_language')); + } + } + + /** + * increase/decrease a resource field for customers/admins + * + * @param string $table + * @param string $keyfield + * @param int $key + * @param string $operator + * @param string $resource + * @param string $extra + * @param int $step + */ + protected static function updateResourceUsage($table = null, $keyfield = null, $key = null, $operator = '+', $resource = null, $extra = null, $step = 1) + { + $stmt = Database::prepare(" + UPDATE `" . $table . "` + SET `" . $resource . "` = `" . $resource . "` " . $operator . " " . (int)$step . " " . $extra . " + WHERE `" . $keyfield . "` = :key + "); + Database::pexecute($stmt, [ + 'key' => $key + ], true, true); } /** * return SQL when parameter $sql_search is given via API * * @param array $sql_search - * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue * @param array $query_fields - * optional array of placeholders mapped to the actual value which is used in the API commands when executing the statement [internal] + * optional array of placeholders mapped to the actual value which is used in the API commands when + * executing the statement [internal] * @param boolean $append - * optional append to WHERE clause rather then create new one, default false [internal] - * + * optional append to WHERE clause rather then create new one, default false [internal] + * * @return string */ - protected function getSearchWhere(&$query_fields = array(), $append = false) + protected function getSearchWhere(&$query_fields = [], $append = false) { - $search = $this->getParam('sql_search', true, array()); + $search = $this->getParam('sql_search', true, []); $condition = ''; if (!empty($search)) { if ($append == true) { @@ -251,11 +269,11 @@ abstract class ApiCommand extends ApiParameter } else { $condition = ' WHERE '; } - $ops = array( + $ops = [ '<', '>', '=' - ); + ]; $first = true; foreach ($search as $field => $valoper) { if ($field == '_plainsql') { @@ -330,10 +348,10 @@ abstract class ApiCommand extends ApiParameter * return LIMIT clause when at least $sql_limit parameter is given via API * * @param int $sql_limit - * optional, limit resultset, default 0 + * optional, limit resultset, default 0 * @param int $sql_offset - * optional, offset for limitation, default 0 - * + * optional, offset for limitation, default 0 + * * @return string */ protected function getLimit() @@ -359,15 +377,15 @@ abstract class ApiCommand extends ApiParameter * return ORDER BY clause if parameter $sql_orderby parameter is given via API * * @param array $sql_orderby - * optional array with index = fieldname and value = ASC|DESC + * optional array with index = fieldname and value = ASC|DESC * @param boolean $append - * optional append to ORDER BY clause rather then create new one, default false [internal] - * + * optional append to ORDER BY clause rather then create new one, default false [internal] + * * @return string */ protected function getOrderBy($append = false) { - $orderby = $this->getParam('sql_orderby', true, array()); + $orderby = $this->getParam('sql_orderby', true, []); $order = ""; if (!empty($orderby)) { if ($append) { @@ -425,46 +443,16 @@ abstract class ApiCommand extends ApiParameter return $order; } - /** - * return logger instance - * - * @return \Froxlor\FroxlorLogger - */ - protected function logger() - { - return $this->logger; - } - /** * return mailer instance * - * @return \Froxlor\System\Mailer + * @return Mailer */ protected function mailer() { return $this->mail; } - /** - * call an api-command internally - * - * @param string $command - * @param array|null $params - * @param boolean $internal - * optional whether called internally, default false - * - * - * @return array - */ - protected function apiCall($command = null, $params = null, $internal = false) - { - $_command = explode(".", $command); - $module = __NAMESPACE__ . "\Commands\\" . $_command[0]; - $function = $_command[1]; - $json_result = $module::getLocal($this->getUserData(), $params, $internal)->{$function}(); - return json_decode($json_result, true)['data']; - } - /** * return api-compatible response in JSON format and send corresponding http-header * @@ -481,14 +469,15 @@ abstract class ApiCommand extends ApiParameter * returns an array of customers the current user can access * * @param string $customer_hide_option - * optional, when called as customer, some options might be hidden due to the panel.customer_hide_options ettings - * - * @throws \Exception + * optional, when called as customer, some options might be hidden due to the + * panel.customer_hide_options ettings + * * @return array + * @throws Exception */ protected function getAllowedCustomerIds($customer_hide_option = '') { - $customer_ids = array(); + $customer_ids = []; if ($this->isAdmin()) { // if we're an admin, list all ftp-users of all the admins customers // or optionally for one specific customer identified by id or loginname @@ -496,13 +485,13 @@ abstract class ApiCommand extends ApiParameter $loginname = $this->getParam('loginname', true, ''); if (!empty($customerid) || !empty($loginname)) { - $_result = $this->apiCall('Customers.get', array( + $_result = $this->apiCall('Customers.get', [ 'id' => $customerid, 'loginname' => $loginname - )); - $custom_list_result = array( + ]); + $custom_list_result = [ $_result - ); + ]; } else { $_custom_list_result = $this->apiCall('Customers.listing'); $custom_list_result = $_custom_list_result['list']; @@ -514,9 +503,9 @@ abstract class ApiCommand extends ApiParameter if (!$this->isInternal() && !empty($customer_hide_option) && Settings::IsInList('panel.customer_hide_options', $customer_hide_option)) { throw new Exception("You cannot access this resource", 405); } - $customer_ids = array( + $customer_ids = [ $this->getUserDetail('customerid') - ); + ]; } if (empty($customer_ids)) { throw new Exception("Required resource unsatisfied.", 405); @@ -524,28 +513,98 @@ abstract class ApiCommand extends ApiParameter return $customer_ids; } + /** + * admin flag + * + * @return boolean + */ + protected function isAdmin() + { + return $this->is_admin; + } + + /** + * call an api-command internally + * + * @param string $command + * @param array|null $params + * @param boolean $internal + * optional whether called internally, default false + * + * + * @return array + */ + protected function apiCall($command = null, $params = null, $internal = false) + { + $_command = explode(".", $command); + $module = __NAMESPACE__ . "\Commands\\" . $_command[0]; + $function = $_command[1]; + $json_result = $module::getLocal($this->getUserData(), $params, $internal)->{$function}(); + return json_decode($json_result, true)['data']; + } + + /** + * returns an instance of the wanted ApiCommand (e.g. + * Customers, Domains, etc); + * this is used widely in the WebInterface + * + * @param array $userinfo + * array of user-data + * @param array $params + * array of parameters for the command + * @param boolean $internal + * optional whether called internally, default false + * + * @return ApiCommand + * @throws Exception + */ + public static function getLocal($userinfo = null, $params = null, $internal = false) + { + return new static(null, $params, $userinfo, $internal); + } + + /** + * return user-data array + * + * @return array + */ + protected function getUserData() + { + return $this->user_data; + } + + /** + * internal call flag + * + * @return boolean + */ + protected function isInternal() + { + return $this->internal_call; + } + /** * returns an array of customer data for customer, or by customer-id/loginname for admin/reseller * * @param int $customerid - * optional, required if loginname is empty + * optional, required if loginname is empty * @param string $loginname - * optional, required of customerid is empty + * optional, required of customerid is empty * @param string $customer_resource_check - * optional, when called as admin, check the resources of the target customer - * - * @throws \Exception + * optional, when called as admin, check the resources of the target customer + * * @return array + * @throws Exception */ protected function getCustomerData($customer_resource_check = '') { if ($this->isAdmin()) { $customerid = $this->getParam('customerid', true, 0); $loginname = $this->getParam('loginname', true, ''); - $customer = $this->apiCall('Customers.get', array( + $customer = $this->apiCall('Customers.get', [ 'id' => $customerid, 'loginname' => $loginname - )); + ]); // check whether the customer has enough resources if (!empty($customer_resource_check) && $customer[$customer_resource_check . '_used'] >= $customer[$customer_resource_check] && $customer[$customer_resource_check] != '-1') { throw new Exception("Customer has no more resources available", 406); @@ -556,29 +615,6 @@ abstract class ApiCommand extends ApiParameter return $customer; } - /** - * increase/decrease a resource field for customers/admins - * - * @param string $table - * @param string $keyfield - * @param int $key - * @param string $operator - * @param string $resource - * @param string $extra - * @param int $step - */ - protected static function updateResourceUsage($table = null, $keyfield = null, $key = null, $operator = '+', $resource = null, $extra = null, $step = 1) - { - $stmt = Database::prepare(" - UPDATE `" . $table . "` - SET `" . $resource . "` = `" . $resource . "` " . $operator . " " . (int) $step . " " . $extra . " - WHERE `" . $keyfield . "` = :key - "); - Database::pexecute($stmt, array( - 'key' => $key - ), true, true); - } - /** * return email template content from database or global language file if not found in DB * @@ -590,19 +626,19 @@ abstract class ApiCommand extends ApiParameter * * @return string */ - protected function getMailTemplate($customerdata = null, $group = null, $varname = null, $replace_arr = array(), $default = "") + protected function getMailTemplate($customerdata = null, $group = null, $varname = null, $replace_arr = [], $default = "") { // get template $stmt = Database::prepare(" SELECT `value` FROM `" . TABLE_PANEL_TEMPLATES . "` WHERE `adminid`= :adminid AND `language`= :lang AND `templategroup`= :group AND `varname`= :var "); - $result = Database::pexecute_first($stmt, array( + $result = Database::pexecute_first($stmt, [ "adminid" => $customerdata['adminid'], "lang" => $customerdata['def_language'], "group" => $group, "var" => $varname - ), true, true); + ], true, true); $content = $default; if ($result) { $content = $result['value'] ?? $default; @@ -611,46 +647,4 @@ abstract class ApiCommand extends ApiParameter $content = html_entity_decode(PhpHelper::replaceVariables($content, $replace_arr)); return $content; } - - /** - * read user data from database by api-request-header fields - * - * @param array $header - * api-request header - * - * @throws \Exception - * @return boolean - */ - private function readUserData($header = null) - { - $sel_stmt = Database::prepare("SELECT * FROM `api_keys` WHERE `apikey` = :ak AND `secret` = :as"); - $result = Database::pexecute_first($sel_stmt, array( - 'ak' => $header['apikey'], - 'as' => $header['secret'] - ), true, true); - if ($result) { - // admin or customer? - if ($result['customerid'] == 0 && $result['adminid'] > 0) { - $this->is_admin = true; - $table = 'panel_admins'; - $key = "adminid"; - } elseif ($result['customerid'] > 0 && $result['adminid'] > 0) { - $this->is_admin = false; - $table = 'panel_customers'; - $key = "customerid"; - } else { - // neither adminid is > 0 nor customerid is > 0 - sorry man, no way - throw new Exception("Invalid API credentials", 400); - } - $sel_stmt = Database::prepare("SELECT * FROM `" . $table . "` WHERE `" . $key . "` = :id"); - $this->user_data = Database::pexecute_first($sel_stmt, array( - 'id' => ($this->is_admin ? $result['adminid'] : $result['customerid']) - ), true, true); - if ($this->is_admin) { - $this->user_data['adminsession'] = 1; - } - return true; - } - throw new Exception("Invalid API credentials", 400); - } } diff --git a/lib/Froxlor/Api/ApiParameter.php b/lib/Froxlor/Api/ApiParameter.php index b3edfa76..72f035cd 100644 --- a/lib/Froxlor/Api/ApiParameter.php +++ b/lib/Froxlor/Api/ApiParameter.php @@ -11,16 +11,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 + * 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 - * http://files.froxlor.org/misc/COPYING.txt + * https://files.froxlor.org/misc/COPYING.txt * * @copyright the authors * @author Froxlor team - * @license http://files.froxlor.org/misc/COPYING.txt GPLv2 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ namespace Froxlor\Api; @@ -40,37 +40,80 @@ abstract class ApiParameter /** * * @param array $params - * optional, array of parameters (var=>value) for the command - * - * @throws \Exception + * optional, array of parameters (var=>value) for the command + * + * @throws Exception */ public function __construct($params = null) { - if (! is_null($params)) { + if (!is_null($params)) { $params = $this->trimArray($params); } $this->cmd_params = $params; } + /** + * run 'trim' function on an array recursively + * + * @param array $input + * + * @return array + */ + private function trimArray($input) + { + if (!is_array($input)) { + return trim($input); + } + return array_map([ + $this, + 'trimArray' + ], $input); + } + + /** + * get specific parameter which also has and unlimited-field + * + * @param string $param + * parameter to get out of the request-parameter list + * @param string $ul_field + * parameter to get out of the request-parameter list + * @param bool $optional + * default: false + * @param mixed $default + * value which is returned if optional=true and param is not set + * + * @return mixed + * @throws Exception + */ + protected function getUlParam($param = null, $ul_field = null, $optional = false, $default = 0) + { + $param_value = (int)$this->getParam($param, $optional, $default); + $ul_field_value = $this->getBoolParam($ul_field, true, 0); + if ($ul_field_value != '0') { + $param_value = -1; + } + return $param_value; + } + /** * get specific parameter from the parameterlist; * check for existence and != empty if needed. * Maybe more in the future * * @param string $param - * parameter to get out of the request-parameter list + * parameter to get out of the request-parameter list * @param bool $optional - * default: false + * default: false * @param mixed $default - * value which is returned if optional=true and param is not set - * - * @throws \Exception + * value which is returned if optional=true and param is not set + * * @return mixed + * @throws Exception */ protected function getParam($param = null, $optional = false, $default = '') { // does it exist? - if (! isset($this->cmd_params[$param])) { + if (!isset($this->cmd_params[$param])) { if ($optional === false) { // get module + function for better error-messages $inmod = $this->getModFunctionString(); @@ -91,73 +134,13 @@ abstract class ApiParameter return $this->cmd_params[$param]; } - /** - * getParam wrapper for boolean parameter - * - * @param string $param - * parameter to get out of the request-parameter list - * @param bool $optional - * default: false - * @param mixed $default - * value which is returned if optional=true and param is not set - * - * @return string - */ - protected function getBoolParam($param = null, $optional = false, $default = false) - { - $_default = '0'; - if ($default) { - $_default = '1'; - } - $param_value = $this->getParam($param, $optional, $_default); - if ($param_value && intval($param_value) != 0) { - return '1'; - } - return '0'; - } - - /** - * get specific parameter which also has and unlimited-field - * - * @param string $param - * parameter to get out of the request-parameter list - * @param string $ul_field - * parameter to get out of the request-parameter list - * @param bool $optional - * default: false - * @param mixed $default - * value which is returned if optional=true and param is not set - * - * @return mixed - * @throws \Exception - */ - protected function getUlParam($param = null, $ul_field = null, $optional = false, $default = 0) - { - $param_value = (int) $this->getParam($param, $optional, $default); - $ul_field_value = $this->getBoolParam($ul_field, true, 0); - if ($ul_field_value != '0') { - $param_value = - 1; - } - return $param_value; - } - - /** - * return list of all parameters - * - * @return array - */ - protected function getParamList() - { - return $this->cmd_params; - } - /** * returns "module::function()" for better error-messages (missing parameter etc.) * makes debugging a whole lot more comfortable * * @param int $level - * depth of backtrace, default 2 - * + * depth of backtrace, default 2 + * * @param int $max_level * @param array|null $trace * @@ -177,26 +160,43 @@ abstract class ApiParameter // is it the one we are looking for? if ($class != $_class && $level <= $max_level) { // check one level deeper - return $this->getModFunctionString(++ $level, $max_level, $trace); + return $this->getModFunctionString(++$level, $max_level, $trace); } return str_replace("Froxlor\\Api\\Commands\\", "", $class) . ':' . $func; } /** - * run 'trim' function on an array recursively + * getParam wrapper for boolean parameter * - * @param array $input + * @param string $param + * parameter to get out of the request-parameter list + * @param bool $optional + * default: false + * @param mixed $default + * value which is returned if optional=true and param is not set + * + * @return string + */ + protected function getBoolParam($param = null, $optional = false, $default = false) + { + $_default = '0'; + if ($default) { + $_default = '1'; + } + $param_value = $this->getParam($param, $optional, $_default); + if ($param_value && intval($param_value) != 0) { + return '1'; + } + return '0'; + } + + /** + * return list of all parameters * * @return array */ - private function trimArray($input) + protected function getParamList() { - if (! is_array($input)) { - return trim($input); - } - return array_map(array( - $this, - 'trimArray' - ), $input); + return $this->cmd_params; } } diff --git a/lib/Froxlor/Api/Commands/Admins.php b/lib/Froxlor/Api/Commands/Admins.php index d554a607..58c74f14 100644 --- a/lib/Froxlor/Api/Commands/Admins.php +++ b/lib/Froxlor/Api/Commands/Admins.php @@ -1,70 +1,124 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Database\Database; +use Froxlor\FroxlorLogger; +use Froxlor\Idna\IdnaWrapper; +use Froxlor\Settings; +use Froxlor\System\Crypt; +use Froxlor\UI\Response; +use Froxlor\User; +use Froxlor\Validate\Validate; +use PDO; + +/** + * @since 0.10.0 + */ +class Admins extends ApiCommand implements ResourceEntity { + /** + * increase resource-usage + * + * @param int $adminid + * @param string $resource + * @param string $extra + * optional, default empty + * @param int $increase_by + * optional, default 1 + */ + public static function increaseUsage($adminid = 0, $resource = null, $extra = '', $increase_by = 1) + { + self::updateResourceUsage(TABLE_PANEL_ADMINS, 'adminid', $adminid, '+', $resource, $extra, $increase_by); + } + + /** + * decrease resource-usage + * + * @param int $adminid + * @param string $resource + * @param string $extra + * optional, default empty + * @param int $decrease_by + * optional, default 1 + */ + public static function decreaseUsage($adminid = 0, $resource = null, $extra = '', $decrease_by = 1) + { + self::updateResourceUsage(TABLE_PANEL_ADMINS, 'adminid', $adminid, '-', $resource, $extra, $decrease_by); + } + /** * lists all admin entries * * @param array $sql_search - * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue * @param int $sql_limit - * optional specify number of results to be returned + * optional specify number of results to be returned * @param int $sql_offset - * optional specify offset for resultset + * optional specify offset for resultset * @param array $sql_orderby - * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more + * fields * * @access admin - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listing() { if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) { - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list admins"); - $query_fields = array(); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list admins"); + $query_fields = []; $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_ADMINS . "`" . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit()); Database::pexecute($result_stmt, $query_fields, true, true); - $result = array(); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + $result = []; + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $result[] = $row; } - return $this->response(array( + return $this->response([ 'count' => count($result), 'list' => $result - )); + ]); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * returns the total number of admins for the given admin * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function listingCount() { @@ -78,43 +132,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt return $this->response($result['num_admins']); } } - throw new \Exception("Not allowed to execute given command.", 403); - } - - /** - * return an admin entry by either id or loginname - * - * @param int $id - * optional, the admin-id - * @param string $loginname - * optional, the loginname - * - * @access admin - * @throws \Exception - * @return string json-encoded array - */ - public function get() - { - $id = $this->getParam('id', true, 0); - $ln_optional = $id > 0; - $loginname = $this->getParam('loginname', $ln_optional, ''); - - if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') == 1 || ($this->getUserDetail('adminid') == $id || $this->getUserDetail('loginname') == $loginname))) { - $result_stmt = Database::prepare(" - SELECT * FROM `" . TABLE_PANEL_ADMINS . "` - WHERE " . ($id > 0 ? "`adminid` = :idln" : "`loginname` = :idln")); - $params = array( - 'idln' => ($id <= 0 ? $loginname : $id) - ); - $result = Database::pexecute_first($result_stmt, $params, true, true); - if ($result) { - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get admin '" . $result['loginname'] . "'"); - return $this->response($result); - } - $key = ($id > 0 ? "id #" . $id : "loginname '" . $loginname . "'"); - throw new \Exception("Admin with " . $key . " could not be found", 404); - } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** @@ -124,78 +142,77 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt * @param string $email * @param string $new_loginname * @param string $admin_password - * optional, default auto-generated + * optional, default auto-generated * @param string $def_language - * optional, default is system-default language + * optional, default is system-default language * @param bool $api_allowed - * optional, default is true if system setting api.enabled is true, else false + * optional, default is true if system setting api.enabled is true, else false * @param string $custom_notes - * optional, default empty + * optional, default empty * @param bool $custom_notes_show - * optional, default false + * optional, default false * @param int $diskspace - * optional, default 0 + * optional, default 0 * @param bool $diskspace_ul - * optional, default false + * optional, default false * @param int $traffic - * optional, default 0 + * optional, default 0 * @param bool $traffic_ul - * optional, default false + * optional, default false * @param int $customers - * optional, default 0 + * optional, default 0 * @param bool $customers_ul - * optional, default false + * optional, default false * @param int $domains - * optional, default 0 + * optional, default 0 * @param bool $domains_ul - * optional, default false + * optional, default false * @param int $subdomains - * optional, default 0 + * optional, default 0 * @param bool $subdomains_ul - * optional, default false + * optional, default false * @param int $emails - * optional, default 0 + * optional, default 0 * @param bool $emails_ul - * optional, default false + * optional, default false * @param int $email_accounts - * optional, default 0 + * optional, default 0 * @param bool $email_accounts_ul - * optional, default false + * optional, default false * @param int $email_forwarders - * optional, default 0 + * optional, default 0 * @param bool $email_forwarders_ul - * optional, default false + * optional, default false * @param int $email_quota - * optional, default 0 + * optional, default 0 * @param bool $email_quota_ul - * optional, default false + * optional, default false * @param int $ftps - * optional, default 0 + * optional, default 0 * @param bool $ftps_ul - * optional, default false + * optional, default false * @param int $mysqls - * optional, default 0 + * optional, default 0 * @param bool $mysqls_ul - * optional, default false + * optional, default false * @param bool $customers_see_all - * optional, default false + * optional, default false * @param bool $domains_see_all - * optional, default false + * optional, default false * @param bool $caneditphpsettings - * optional, default false + * optional, default false * @param bool $change_serversettings - * optional, default false + * optional, default false * @param array $ipaddress - * optional, list of ip-address id's; default -1 (all IP's) + * optional, list of ip-address id's; default -1 (all IP's) * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function add() { if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) { - // required parameters $name = $this->getParam('name'); $email = $this->getParam('email'); @@ -224,24 +241,24 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $domains_see_all = $this->getBoolParam('domains_see_all', true, 0); $caneditphpsettings = $this->getBoolParam('caneditphpsettings', true, 0); $change_serversettings = $this->getBoolParam('change_serversettings', true, 0); - $ipaddress = $this->getParam('ipaddress', true, - 1); + $ipaddress = $this->getParam('ipaddress', true, -1); // validation - $name = \Froxlor\Validate\Validate::validate($name, 'name', '', '', array(), true); - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); - $email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true)); - $def_language = \Froxlor\Validate\Validate::validate($def_language, 'default language', '', '', array(), true); - $custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true); + $name = Validate::validate($name, 'name', '', '', [], true); + $idna_convert = new IdnaWrapper(); + $email = $idna_convert->encode(Validate::validate($email, 'email', '', '', [], true)); + $def_language = Validate::validate($def_language, 'default language', '', '', [], true); + $custom_notes = Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', Validate::REGEX_CONF_TEXT, '', [], true); if (Settings::Get('system.mail_quota_enabled') != '1') { - $email_quota = - 1; + $email_quota = -1; } - $password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true); + $password = Validate::validate($password, 'password', '', '', [], true); // only check if not empty, // cause empty == generate password automatically if ($password != '') { - $password = \Froxlor\System\Crypt::validatePassword($password, true); + $password = Crypt::validatePassword($password, true); } $diskspace = $diskspace * 1024; @@ -252,30 +269,29 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $loginname_check_stmt = Database::prepare(" SELECT `loginname` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `loginname` = :login "); - $loginname_check = Database::pexecute_first($loginname_check_stmt, array( + $loginname_check = Database::pexecute_first($loginname_check_stmt, [ 'login' => $loginname - ), true, true); + ], true, true); // Check if an admin with the loginname already exists // do not check via api as we skip any permission checks for this task $loginname_check_admin_stmt = Database::prepare(" SELECT `loginname` FROM `" . TABLE_PANEL_ADMINS . "` WHERE `loginname` = :login "); - $loginname_check_admin = Database::pexecute_first($loginname_check_admin_stmt, array( + $loginname_check_admin = Database::pexecute_first($loginname_check_admin_stmt, [ 'login' => $loginname - ), true, true); + ], true, true); if (($loginname_check && strtolower($loginname_check['loginname']) == strtolower($loginname)) || ($loginname_check_admin && strtolower($loginname_check_admin['loginname']) == strtolower($loginname))) { - \Froxlor\UI\Response::standard_error('loginnameexists', $loginname, true); + Response::standardError('loginnameexists', $loginname, true); } elseif (preg_match('/^' . preg_quote(Settings::Get('customer.accountprefix'), '/') . '([0-9]+)/', $loginname)) { // Accounts which match systemaccounts are not allowed, filtering them - \Froxlor\UI\Response::standard_error('loginnameissystemaccount', Settings::Get('customer.accountprefix'), true); - } elseif (! \Froxlor\Validate\Validate::validateUsername($loginname)) { - \Froxlor\UI\Response::standard_error('loginnameiswrong', $loginname, true); - } elseif (! \Froxlor\Validate\Validate::validateEmail($email)) { - \Froxlor\UI\Response::standard_error('emailiswrong', $email, true); + Response::standardError('loginnameissystemaccount', Settings::Get('customer.accountprefix'), true); + } elseif (!Validate::validateUsername($loginname)) { + Response::standardError('loginnameiswrong', $loginname, true); + } elseif (!Validate::validateEmail($email)) { + Response::standardError('emailiswrong', $email, true); } else { - if ($customers_see_all != '1') { $customers_see_all = '0'; } @@ -293,14 +309,14 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt } if ($password == '') { - $password = \Froxlor\System\Crypt::generatePassword(); + $password = Crypt::generatePassword(); } $_theme = Settings::Get('panel.default_theme'); - $ins_data = array( + $ins_data = [ 'loginname' => $loginname, - 'password' => \Froxlor\System\Crypt::makeCryptPassword($password), + 'password' => Crypt::makeCryptPassword($password), 'name' => $name, 'email' => $email, 'lang' => $def_language, @@ -320,11 +336,11 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt 'quota' => $email_quota, 'ftps' => $ftps, 'mysqls' => $mysqls, - 'ip' => empty($ipaddress) ? "" : (is_array($ipaddress) && $ipaddress > 0 ? json_encode($ipaddress) : - 1), + 'ip' => empty($ipaddress) ? "" : (is_array($ipaddress) && $ipaddress > 0 ? json_encode($ipaddress) : -1), 'theme' => $_theme, 'custom_notes' => $custom_notes, 'custom_notes_show' => $custom_notes_show - ); + ]; $ins_stmt = Database::prepare(" INSERT INTO `" . TABLE_PANEL_ADMINS . "` SET @@ -358,120 +374,155 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $adminid = Database::lastInsertId(); $ins_data['adminid'] = $adminid; - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added admin '" . $loginname . "'"); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added admin '" . $loginname . "'"); // get all admin-data for return-array - $result = $this->apiCall('Admins.get', array( + $result = $this->apiCall('Admins.get', [ 'id' => $adminid - )); + ]); return $this->response($result); } } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); + } + + /** + * return an admin entry by either id or loginname + * + * @param int $id + * optional, the admin-id + * @param string $loginname + * optional, the loginname + * + * @access admin + * @return string json-encoded array + * @throws Exception + */ + public function get() + { + $id = $this->getParam('id', true, 0); + $ln_optional = $id > 0; + $loginname = $this->getParam('loginname', $ln_optional, ''); + + if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') == 1 || ($this->getUserDetail('adminid') == $id || $this->getUserDetail('loginname') == $loginname))) { + $result_stmt = Database::prepare(" + SELECT * FROM `" . TABLE_PANEL_ADMINS . "` + WHERE " . ($id > 0 ? "`adminid` = :idln" : "`loginname` = :idln")); + $params = [ + 'idln' => ($id <= 0 ? $loginname : $id) + ]; + $result = Database::pexecute_first($result_stmt, $params, true, true); + if ($result) { + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get admin '" . $result['loginname'] . "'"); + return $this->response($result); + } + $key = ($id > 0 ? "id #" . $id : "loginname '" . $loginname . "'"); + throw new Exception("Admin with " . $key . " could not be found", 404); + } + throw new Exception("Not allowed to execute given command.", 403); } /** * update an admin user by given id or loginname * * @param int $id - * optional, the admin-id + * optional, the admin-id * @param string $loginname - * optional, the loginname + * optional, the loginname * @param string $name - * optional + * optional * @param string $email - * optional + * optional * @param string $admin_password - * optional, default auto-generated + * optional, default auto-generated * @param string $def_language - * optional, default is system-default language + * optional, default is system-default language * @param bool $api_allowed - * optional, default is true if system setting api.enabled is true, else false + * optional, default is true if system setting api.enabled is true, else false * @param string $custom_notes - * optional, default empty + * optional, default empty * @param string $theme - * optional + * optional * @param bool $deactivated - * optional, default false + * optional, default false * @param bool $custom_notes_show - * optional, default false + * optional, default false * @param int $diskspace - * optional, default 0 + * optional, default 0 * @param bool $diskspace_ul - * optional, default false + * optional, default false * @param int $traffic - * optional, default 0 + * optional, default 0 * @param bool $traffic_ul - * optional, default false + * optional, default false * @param int $customers - * optional, default 0 + * optional, default 0 * @param bool $customers_ul - * optional, default false + * optional, default false * @param int $domains - * optional, default 0 + * optional, default 0 * @param bool $domains_ul - * optional, default false + * optional, default false * @param int $subdomains - * optional, default 0 + * optional, default 0 * @param bool $subdomains_ul - * optional, default false + * optional, default false * @param int $emails - * optional, default 0 + * optional, default 0 * @param bool $emails_ul - * optional, default false + * optional, default false * @param int $email_accounts - * optional, default 0 + * optional, default 0 * @param bool $email_accounts_ul - * optional, default false + * optional, default false * @param int $email_forwarders - * optional, default 0 + * optional, default 0 * @param bool $email_forwarders_ul - * optional, default false + * optional, default false * @param int $email_quota - * optional, default 0 + * optional, default 0 * @param bool $email_quota_ul - * optional, default false + * optional, default false * @param int $ftps - * optional, default 0 + * optional, default 0 * @param bool $ftps_ul - * optional, default false + * optional, default false * @param int $mysqls - * optional, default 0 + * optional, default 0 * @param bool $mysqls_ul - * optional, default false + * optional, default false * @param bool $customers_see_all - * optional, default false + * optional, default false * @param bool $domains_see_all - * optional, default false + * optional, default false * @param bool $caneditphpsettings - * optional, default false + * optional, default false * @param bool $change_serversettings - * optional, default false + * optional, default false * @param array $ipaddress - * optional, list of ip-address id's; default -1 (all IP's) + * optional, list of ip-address id's; default -1 (all IP's) * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function update() { if ($this->isAdmin()) { - $id = $this->getParam('id', true, 0); $ln_optional = $id > 0; $loginname = $this->getParam('loginname', $ln_optional, ''); - $result = $this->apiCall('Admins.get', array( + $result = $this->apiCall('Admins.get', [ 'id' => $id, 'loginname' => $loginname - )); + ]); $id = $result['adminid']; if ($this->getUserDetail('change_serversettings') == 1 || $result['adminid'] == $this->getUserDetail('adminid')) { // parameters $name = $this->getParam('name', true, $result['name']); - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); + $idna_convert = new IdnaWrapper(); $email = $this->getParam('email', true, $idna_convert->decode($result['email'])); $password = $this->getParam('admin_password', true, ''); $def_language = $this->getParam('def_language', true, $result['def_language']); @@ -498,7 +549,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $change_serversettings = $result['change_serversettings']; $diskspace = $result['diskspace']; $traffic = $result['traffic']; - $ipaddress = ($result['ip'] != - 1 ? json_decode($result['ip'], true) : - 1); + $ipaddress = ($result['ip'] != -1 ? json_decode($result['ip'], true) : -1); } else { $api_allowed = $this->getBoolParam('api_allowed', true, $result['api_allowed']); $deactivated = $this->getBoolParam('deactivated', true, $result['deactivated']); @@ -520,33 +571,32 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $domains_see_all = $this->getBoolParam('domains_see_all', true, $result['domains_see_all']); $caneditphpsettings = $this->getBoolParam('caneditphpsettings', true, $result['caneditphpsettings']); $change_serversettings = $this->getBoolParam('change_serversettings', true, $result['change_serversettings']); - $ipaddress = $this->getParam('ipaddress', true, ($result['ip'] != - 1 ? json_decode($result['ip'], true) : - 1)); + $ipaddress = $this->getParam('ipaddress', true, ($result['ip'] != -1 ? json_decode($result['ip'], true) : -1)); $diskspace = $diskspace * 1024; $traffic = $traffic * 1024 * 1024; } // validation - $name = \Froxlor\Validate\Validate::validate($name, 'name', '', '', array(), true); - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); - $email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true)); - $def_language = \Froxlor\Validate\Validate::validate($def_language, 'default language', '', '', array(), true); - $custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true); - $theme = \Froxlor\Validate\Validate::validate($theme, 'theme', '', '', array(), true); - $password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true); + $name = Validate::validate($name, 'name', '', '', [], true); + $idna_convert = new IdnaWrapper(); + $email = $idna_convert->encode(Validate::validate($email, 'email', '', '', [], true)); + $def_language = Validate::validate($def_language, 'default language', '', '', [], true); + $custom_notes = Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', Validate::REGEX_CONF_TEXT, '', [], true); + $theme = Validate::validate($theme, 'theme', '', '', [], true); + $password = Validate::validate($password, 'password', '', '', [], true); if (Settings::Get('system.mail_quota_enabled') != '1') { - $email_quota = - 1; + $email_quota = -1; } if (empty($theme)) { $theme = Settings::Get('panel.default_theme'); } - if (! \Froxlor\Validate\Validate::validateEmail($email)) { - \Froxlor\UI\Response::standard_error('emailiswrong', $email, true); + if (!Validate::validateEmail($email)) { + Response::standardError('emailiswrong', $email, true); } else { - if ($deactivated != '1') { $deactivated = '0'; } @@ -568,8 +618,8 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt } if ($password != '') { - $password = \Froxlor\System\Crypt::validatePassword($password, true); - $password = \Froxlor\System\Crypt::makeCryptPassword($password); + $password = Crypt::validatePassword($password, true); + $password = Crypt::makeCryptPassword($password); } else { $password = $result['password']; } @@ -577,42 +627,42 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt // check if a resource was set to something lower // than actually used by the admin/reseller $res_warning = ""; - if ($customers != $result['customers'] && $customers != - 1 && $customers < $result['customers_used']) { + if ($customers != $result['customers'] && $customers != -1 && $customers < $result['customers_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['customers']); } - if ($domains != $result['domains'] && $domains != - 1 && $domains < $result['domains_used']) { + if ($domains != $result['domains'] && $domains != -1 && $domains < $result['domains_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['domains']); } - if ($diskspace != $result['diskspace'] && ($diskspace / 1024) != - 1 && $diskspace < $result['diskspace_used']) { + if ($diskspace != $result['diskspace'] && ($diskspace / 1024) != -1 && $diskspace < $result['diskspace_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['diskspace']); } - if ($traffic != $result['traffic'] && ($traffic / 1024 / 1024) != - 1 && $traffic < $result['traffic_used']) { + if ($traffic != $result['traffic'] && ($traffic / 1024 / 1024) != -1 && $traffic < $result['traffic_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['traffic']); } - if ($emails != $result['emails'] && $emails != - 1 && $emails < $result['emails_used']) { + if ($emails != $result['emails'] && $emails != -1 && $emails < $result['emails_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['emails']); } - if ($email_accounts != $result['email_accounts'] && $email_accounts != - 1 && $email_accounts < $result['email_accounts_used']) { + if ($email_accounts != $result['email_accounts'] && $email_accounts != -1 && $email_accounts < $result['email_accounts_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['email accounts']); } - if ($email_forwarders != $result['email_forwarders'] && $email_forwarders != - 1 && $email_forwarders < $result['email_forwarders_used']) { + if ($email_forwarders != $result['email_forwarders'] && $email_forwarders != -1 && $email_forwarders < $result['email_forwarders_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['email forwarders']); } - if ($email_quota != $result['email_quota'] && $email_quota != - 1 && $email_quota < $result['email_quota_used']) { + if ($email_quota != $result['email_quota'] && $email_quota != -1 && $email_quota < $result['email_quota_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['email quota']); } - if ($ftps != $result['ftps'] && $ftps != - 1 && $ftps < $result['ftps_used']) { + if ($ftps != $result['ftps'] && $ftps != -1 && $ftps < $result['ftps_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['ftps']); } - if ($mysqls != $result['mysqls'] && $mysqls != - 1 && $mysqls < $result['mysqls_used']) { + if ($mysqls != $result['mysqls'] && $mysqls != -1 && $mysqls < $result['mysqls_used']) { $res_warning .= lng('error.setlessthanalreadyused', ['mysqls']); } - if (! empty($res_warning)) { - throw new \Exception($res_warning, 406); + if (!empty($res_warning)) { + throw new Exception($res_warning, 406); } - $upd_data = array( + $upd_data = [ 'password' => $password, 'name' => $name, 'email' => $email, @@ -633,13 +683,13 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt 'quota' => $email_quota, 'ftps' => $ftps, 'mysqls' => $mysqls, - 'ip' => empty($ipaddress) ? "" : (is_array($ipaddress) && $ipaddress > 0 ? json_encode($ipaddress) : - 1), + 'ip' => empty($ipaddress) ? "" : (is_array($ipaddress) && $ipaddress > 0 ? json_encode($ipaddress) : -1), 'deactivated' => $deactivated, 'custom_notes' => $custom_notes, 'custom_notes_show' => $custom_notes_show, 'theme' => $theme, 'adminid' => $id - ); + ]; $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_ADMINS . "` SET @@ -671,30 +721,30 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt WHERE `adminid` = :adminid "); Database::pexecute($upd_stmt, $upd_data, true, true); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] edited admin '" . $result['loginname'] . "'"); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] edited admin '" . $result['loginname'] . "'"); // get all admin-data for return-array - $result = $this->apiCall('Admins.get', array( + $result = $this->apiCall('Admins.get', [ 'id' => $result['adminid'] - )); + ]); return $this->response($result); } } } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * delete a admin entry by either id or loginname * * @param int $id - * optional, the admin-id + * optional, the admin-id * @param string $loginname - * optional, the loginname + * optional, the loginname * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function delete() { @@ -703,94 +753,94 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $ln_optional = $id > 0; $loginname = $this->getParam('loginname', $ln_optional, ''); - $result = $this->apiCall('Admins.get', array( + $result = $this->apiCall('Admins.get', [ 'id' => $id, 'loginname' => $loginname - )); + ]); $id = $result['adminid']; // don't be stupid if ($id == $this->getUserDetail('adminid')) { - \Froxlor\UI\Response::standard_error('youcantdeleteyourself', '', true); + Response::standardError('youcantdeleteyourself', '', true); } // can't delete the first superadmin if ($id == 1) { - \Froxlor\UI\Response::standard_error('cannotdeletesuperadmin', '', true); + Response::standardError('cannotdeletesuperadmin', '', true); } // delete admin $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_ADMINS . "` WHERE `adminid` = :adminid "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'adminid' => $id - ), true, true); + ], true, true); // delete the traffic-usage $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_TRAFFIC_ADMINS . "` WHERE `adminid` = :adminid "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'adminid' => $id - ), true, true); + ], true, true); // set admin-id of the old admin's customer to current admins $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `adminid` = :userid WHERE `adminid` = :adminid "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'userid' => $this->getUserDetail('adminid'), 'adminid' => $id - ), true, true); + ], true, true); // set admin-id of the old admin's domains to current admins $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `adminid` = :userid WHERE `adminid` = :adminid "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'userid' => $this->getUserDetail('adminid'), 'adminid' => $id - ), true, true); + ], true, true); // delete old admin's api keys if exists (no customer keys) $upd_stmt = Database::prepare(" DELETE FROM `" . TABLE_API_KEYS . "` WHERE `adminid` = :adminid AND `customerid` = '0' "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'adminid' => $id - ), true, true); + ], true, true); // set admin-id of the old admin's api-keys to current admins $upd_stmt = Database::prepare(" UPDATE `" . TABLE_API_KEYS . "` SET `adminid` = :userid WHERE `adminid` = :adminid "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'userid' => $this->getUserDetail('adminid'), 'adminid' => $id - ), true, true); + ], true, true); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted admin '" . $result['loginname'] . "'"); - \Froxlor\User::updateCounters(); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted admin '" . $result['loginname'] . "'"); + User::updateCounters(); return $this->response($result); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * unlock a locked admin by either id or loginname * * @param int $id - * optional, the admin-id + * optional, the admin-id * @param string $loginname - * optional, the loginname + * optional, the loginname * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function unlock() { @@ -799,10 +849,10 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $ln_optional = $id > 0; $loginname = $this->getParam('loginname', $ln_optional, ''); - $result = $this->apiCall('Admins.get', array( + $result = $this->apiCall('Admins.get', [ 'id' => $id, 'loginname' => $loginname - )); + ]); $id = $result['adminid']; $result_stmt = Database::prepare(" @@ -810,45 +860,15 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt `loginfail_count` = '0' WHERE `adminid`= :id "); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'id' => $id - ), true, true); + ], true, true); // set the new value for result-array $result['loginfail_count'] = 0; - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] unlocked admin '" . $result['loginname'] . "'"); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] unlocked admin '" . $result['loginname'] . "'"); return $this->response($result); } - throw new \Exception("Not allowed to execute given command.", 403); - } - - /** - * increase resource-usage - * - * @param int $adminid - * @param string $resource - * @param string $extra - * optional, default empty - * @param int $increase_by - * optional, default 1 - */ - public static function increaseUsage($adminid = 0, $resource = null, $extra = '', $increase_by = 1) - { - self::updateResourceUsage(TABLE_PANEL_ADMINS, 'adminid', $adminid, '+', $resource, $extra, $increase_by); - } - - /** - * decrease resource-usage - * - * @param int $adminid - * @param string $resource - * @param string $extra - * optional, default empty - * @param int $decrease_by - * optional, default 1 - */ - public static function decreaseUsage($adminid = 0, $resource = null, $extra = '', $decrease_by = 1) - { - self::updateResourceUsage(TABLE_PANEL_ADMINS, 'adminid', $adminid, '-', $resource, $extra, $decrease_by); + throw new Exception("Not allowed to execute given command.", 403); } } diff --git a/lib/Froxlor/Api/Commands/ApiKeys.php b/lib/Froxlor/Api/Commands/ApiKeys.php index eb25045e..d5180e36 100644 --- a/lib/Froxlor/Api/Commands/ApiKeys.php +++ b/lib/Froxlor/Api/Commands/ApiKeys.php @@ -1,34 +1,45 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class ApiKeys extends \Froxlor\Api\ApiCommand + +namespace Froxlor\Api\Commands; + +use Froxlor\Api\ApiCommand; + +/** + * @since 0.10.0 + */ +class ApiKeys extends ApiCommand { public function listing() { - // - } + // + } public function listingCount() { - // - } -} \ No newline at end of file + // + } +} diff --git a/lib/Froxlor/Api/Commands/Certificates.php b/lib/Froxlor/Api/Commands/Certificates.php index 5e983faa..a4c600da 100644 --- a/lib/Froxlor/Api/Commands/Certificates.php +++ b/lib/Froxlor/Api/Commands/Certificates.php @@ -1,44 +1,64 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Cron\TaskId; +use Froxlor\Database\Database; +use Froxlor\FroxlorLogger; +use Froxlor\Settings; +use Froxlor\System\Cronjob; +use Froxlor\UI\Response; +use PDO; + +/** + * @since 0.10.0 + */ +class Certificates extends ApiCommand implements ResourceEntity { /** * add new ssl-certificate entry for given domain by either id or domainname * * @param int $id - * optional, the domain-id + * optional, the domain-id * @param string $domainname - * optional, the domainname + * optional, the domainname * @param string $ssl_cert_file * @param string $ssl_key_file * @param string $ssl_ca_file - * optional + * optional * @param string $ssl_cert_chainfile - * optional + * optional * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function add() { @@ -47,13 +67,13 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou $domainname = $this->getParam('domainname', $dn_optional, ''); if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'domains')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } - $domain = $this->apiCall('SubDomains.get', array( + $domain = $this->apiCall('SubDomains.get', [ 'id' => $domainid, 'domainname' => $domainname - )); + ]); $domainid = $domain['id']; // parameters @@ -65,293 +85,25 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou // validate whether the domain does not already have an entry $has_cert = true; try { - $this->apiCall('Certificates.get', array( + $this->apiCall('Certificates.get', [ 'id' => $domainid - )); - } catch (\Exception $e) { + ]); + } catch (Exception $e) { if ($e->getCode() == 412) { $has_cert = false; } else { throw $e; } } - if (! $has_cert) { + if (!$has_cert) { $this->addOrUpdateCertificate($domain['id'], $ssl_cert_file, $ssl_key_file, $ssl_ca_file, $ssl_cert_chainfile, true); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added ssl-certificate for '" . $domain['domain'] . "'"); - $result = $this->apiCall('Certificates.get', array( + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added ssl-certificate for '" . $domain['domain'] . "'"); + $result = $this->apiCall('Certificates.get', [ 'id' => $domain['id'] - )); + ]); return $this->response($result); } - throw new \Exception("Domain '" . $domain['domain'] . "' already has a certificate. Did you mean to call update?", 406); - } - - /** - * return ssl-certificate entry for given domain by either id or domainname - * - * @param int $id - * optional, the domain-id - * @param string $domainname - * optional, the domainname - * - * @access admin, customer - * @throws \Exception - * @return string json-encoded array - */ - public function get() - { - $id = $this->getParam('id', true, 0); - $dn_optional = $id > 0; - $domainname = $this->getParam('domainname', $dn_optional, ''); - - if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'domains')) { - throw new \Exception("You cannot access this resource", 405); - } - - $domain = $this->apiCall('SubDomains.get', array( - 'id' => $id, - 'domainname' => $domainname - )); - $domainid = $domain['id']; - - $stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid`= :domainid"); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] get ssl-certificate for '" . $domain['domain'] . "'"); - $result = Database::pexecute_first($stmt, array( - "domainid" => $domainid - )); - if (! $result) { - throw new \Exception("Domain '" . $domain['domain'] . "' does not have a certificate.", 412); - } - return $this->response($result); - } - - /** - * update ssl-certificate entry for given domain by either id or domainname - * - * @param int $id - * optional, the domain-id - * @param string $domainname - * optional, the domainname - * @param string $ssl_cert_file - * @param string $ssl_key_file - * @param string $ssl_ca_file - * optional - * @param string $ssl_cert_chainfile - * optional - * - * @access admin, customer - * @throws \Exception - * @return string json-encoded array - */ - public function update() - { - $id = $this->getParam('id', true, 0); - $dn_optional = $id > 0; - $domainname = $this->getParam('domainname', $dn_optional, ''); - - if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'domains')) { - throw new \Exception("You cannot access this resource", 405); - } - - $domain = $this->apiCall('SubDomains.get', array( - 'id' => $id, - 'domainname' => $domainname - )); - - // parameters - $ssl_cert_file = $this->getParam('ssl_cert_file'); - $ssl_key_file = $this->getParam('ssl_key_file'); - $ssl_ca_file = $this->getParam('ssl_ca_file', true, ''); - $ssl_cert_chainfile = $this->getParam('ssl_cert_chainfile', true, ''); - $this->addOrUpdateCertificate($domain['id'], $ssl_cert_file, $ssl_key_file, $ssl_ca_file, $ssl_cert_chainfile, false); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] updated ssl-certificate for '" . $domain['domain'] . "'"); - $result = $this->apiCall('Certificates.get', array( - 'id' => $domain['id'] - )); - return $this->response($result); - } - - /** - * lists all certificate entries - * - * @param array $sql_search - * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue - * @param int $sql_limit - * optional specify number of results to be returned - * @param int $sql_offset - * optional specify offset for resultset - * @param array $sql_orderby - * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields - * - * @access admin, customer - * @throws \Exception - * @return string json-encoded array count|list - */ - public function listing() - { - // select all my (accessible) certificates - $certs_stmt_query = "SELECT s.*, d.domain, d.letsencrypt, c.customerid, c.loginname - FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s - LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON `d`.`id` = `s`.`domainid` - LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` c ON `c`.`customerid` = `d`.`customerid` - WHERE "; - - $qry_params = array(); - $query_fields = array(); - if ($this->isAdmin() && $this->getUserDetail('customers_see_all') == '0') { - // admin with only customer-specific permissions - $certs_stmt_query .= "d.adminid = :adminid "; - $qry_params['adminid'] = $this->getUserDetail('adminid'); - } elseif ($this->isAdmin() == false) { - // customer-area - $certs_stmt_query .= "d.customerid = :cid "; - $qry_params['cid'] = $this->getUserDetail('customerid'); - } else { - $certs_stmt_query .= "1 "; - } - $certs_stmt = Database::prepare($certs_stmt_query . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); - $qry_params = array_merge($qry_params, $query_fields); - Database::pexecute($certs_stmt, $qry_params, true, true); - $result = array(); - while ($cert = $certs_stmt->fetch(\PDO::FETCH_ASSOC)) { - // respect froxlor-hostname - if ($cert['domainid'] == 0) { - $cert['domain'] = Settings::Get('system.hostname'); - $cert['letsencrypt'] = Settings::Get('system.le_froxlor_enabled'); - $cert['loginname'] = 'froxlor.panel'; - } - - // Set data from certificate - $cert_data = openssl_x509_parse($cert['ssl_cert_file']); - if ($cert_data) { - $cert['validfromdate'] = date('Y-m-d H:i:s', $cert_data['validFrom_time_t']); - $cert['validtodate'] = date('Y-m-d H:i:s', $cert_data['validTo_time_t']); - $cert['isvalid'] = (bool) $cert_data['validTo_time_t'] > time(); - $cert['issuer'] = $cert_data['issuer']['O'] ?? null; - } - - // Set subject alt names from certificate - $cert['san'] = null; - if (isset($cert_data['extensions']['subjectAltName']) && ! empty($cert_data['extensions']['subjectAltName'])) { - $SANs = explode(",", $cert_data['extensions']['subjectAltName']); - $SANs = array_map('trim', $SANs); - foreach ($SANs as $san) { - $san = str_replace("DNS:", "", $san); - if ($san != $cert_data['subject']['CN'] && strpos($san, "othername:") === false) { - $cert['san'][] = $san; - } - } - } - - $result[] = $cert; - } - return $this->response(array( - 'count' => count($result), - 'list' => $result - )); - } - - /** - * returns the total number of certificates for the given user - * - * @access admin, customer - * @throws \Exception - * @return string json-encoded array - */ - public function listingCount() - { - // select all my (accessible) certificates - $certs_stmt_query = "SELECT COUNT(*) as num_certs - FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s - LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON `d`.`id` = `s`.`domainid` - LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` c ON `c`.`customerid` = `d`.`customerid` - WHERE "; - $qry_params = array(); - if ($this->isAdmin() && $this->getUserDetail('customers_see_all') == '0') { - // admin with only customer-specific permissions - $certs_stmt_query .= "d.adminid = :adminid "; - $qry_params['adminid'] = $this->getUserDetail('adminid'); - } elseif ($this->isAdmin() == false) { - // customer-area - $certs_stmt_query .= "d.customerid = :cid "; - $qry_params['cid'] = $this->getUserDetail('customerid'); - } else { - $certs_stmt_query .= "1 "; - } - $certs_stmt = Database::prepare($certs_stmt_query); - $result = Database::pexecute_first($certs_stmt, $qry_params, true, true); - if ($result) { - return $this->response($result['num_certs']); - } - } - - /** - * delete certificates entry by id - * - * @param int $id - * - * @throws \Exception - * @return string json-encoded array - */ - public function delete() - { - $id = $this->getParam('id'); - - if ($this->isAdmin() == false) { - $chk_stmt = Database::prepare(" - SELECT d.domain, d.letsencrypt FROM `" . TABLE_PANEL_DOMAINS . "` d - LEFT JOIN `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s ON s.domainid = d.id - WHERE s.`id` = :id AND d.`customerid` = :cid - "); - $chk = Database::pexecute_first($chk_stmt, array( - 'id' => $id, - 'cid' => $this->getUserDetail('customerid') - )); - } elseif ($this->isAdmin()) { - $chk_stmt = Database::prepare(" - SELECT d.domain, d.letsencrypt FROM `" . TABLE_PANEL_DOMAINS . "` d - LEFT JOIN `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s ON s.domainid = d.id - WHERE s.`id` = :id" . ($this->getUserDetail('customers_see_all') == '0' ? " AND d.`adminid` = :aid" : "")); - $params = array( - 'id' => $id - ); - if ($this->getUserDetail('customers_see_all') == '0') { - $params['aid'] = $this->getUserDetail('adminid'); - } - $chk = Database::pexecute_first($chk_stmt, $params); - if ($chk == false && $this->getUserDetail('change_serversettings')) { - // check whether it might be the froxlor-vhost certificate - $chk_stmt = Database::prepare(" - SELECT \"" . Settings::Get('system.hostname') . "\" as domain, \"" . Settings::Get('system.le_froxlor_enabled') . "\" as letsencrypt FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` - WHERE `id` = :id AND `domainid` = '0'"); - $params = array( - 'id' => $id - ); - $chk = Database::pexecute_first($chk_stmt, $params); - $chk['isFroxlorVhost'] = true; - } - } - if ($chk !== false) { - // additional access check by trying to get the certificate - if (isset($chk['isFroxlorVhost']) && $chk['isFroxlorVhost'] == true) { - $result = $chk; - } else { - $result = $this->apiCall('Certificates.get', array( - 'domainname' => $chk['domain'] - )); - } - $del_stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE id = :id"); - Database::pexecute($del_stmt, array( - 'id' => $id - )); - // trigger removing of certificate from acme.sh if let's encrypt - if ($chk['letsencrypt'] == '1') { - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_SSL, $chk['domain']); - } - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] removed ssl-certificate for '" . $chk['domain'] . "'"); - return $this->response($result); - } - throw new \Exception("Unable to determine SSL certificate. Maybe no access?", 406); + throw new Exception("Domain '" . $domain['domain'] . "' already has a certificate. Did you mean to call update?", 406); } /** @@ -363,15 +115,15 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou * @param string $ssl_ca_file * @param string $ssl_cert_chainfile * @param boolean $do_insert - * optional default false + * optional default false * * @return boolean - * @throws \Exception + * @throws Exception */ private function addOrUpdateCertificate($domainid = 0, $ssl_cert_file = '', $ssl_key_file = '', $ssl_ca_file = '', $ssl_cert_chainfile = '', $do_insert = false) { if ($ssl_cert_file != '' && $ssl_key_file == '') { - \Froxlor\UI\Response::standard_error('sslcertificateismissingprivatekey', '', true); + Response::standardError('sslcertificateismissingprivatekey', '', true); } $do_verify = true; @@ -395,26 +147,26 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou // bool openssl_x509_check_private_key ( mixed $cert , mixed $key ) // Checks whether the given key is the private key that corresponds to cert. if (openssl_x509_check_private_key($ssl_cert_file, $ssl_key_file) === false) { - \Froxlor\UI\Response::standard_error('sslcertificateinvalidcertkeypair', '', true); + Response::standardError('sslcertificateinvalidcertkeypair', '', true); } // check optional stuff if ($ssl_ca_file != '') { $ca_content = openssl_x509_parse($ssl_ca_file); - if (! is_array($ca_content)) { + if (!is_array($ca_content)) { // invalid - \Froxlor\UI\Response::standard_error('sslcertificateinvalidca', '', true); + Response::standardError('sslcertificateinvalidca', '', true); } } if ($ssl_cert_chainfile != '') { $chain_content = openssl_x509_parse($ssl_cert_chainfile); - if (! is_array($chain_content)) { + if (!is_array($chain_content)) { // invalid - \Froxlor\UI\Response::standard_error('sslcertificateinvalidchain', '', true); + Response::standardError('sslcertificateinvalidchain', '', true); } } } else { - \Froxlor\UI\Response::standard_error('sslcertificateinvalidcert', '', true); + Response::standardError('sslcertificateinvalidcert', '', true); } $expirationdate = empty($cert_content['validTo_time_t']) ? null : date("Y-m-d H:i:s", $cert_content['validTo_time_t']); } @@ -434,17 +186,287 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou `expirationdate` = :expirationdate " . $qrywhere . " `domainid`= :domainid "); - $params = array( + $params = [ "ssl_cert_file" => $ssl_cert_file, "ssl_key_file" => $ssl_key_file, "ssl_ca_file" => $ssl_ca_file, "ssl_cert_chainfile" => $ssl_cert_chainfile, "expirationdate" => $expirationdate, "domainid" => $domainid - ); + ]; Database::pexecute($stmt, $params, true, true); // insert task to re-generate webserver-configs (#1260) - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + Cronjob::inserttask(TaskId::REBUILD_VHOST); return true; } + + /** + * update ssl-certificate entry for given domain by either id or domainname + * + * @param int $id + * optional, the domain-id + * @param string $domainname + * optional, the domainname + * @param string $ssl_cert_file + * @param string $ssl_key_file + * @param string $ssl_ca_file + * optional + * @param string $ssl_cert_chainfile + * optional + * + * @access admin, customer + * @return string json-encoded array + * @throws Exception + */ + public function update() + { + $id = $this->getParam('id', true, 0); + $dn_optional = $id > 0; + $domainname = $this->getParam('domainname', $dn_optional, ''); + + if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'domains')) { + throw new Exception("You cannot access this resource", 405); + } + + $domain = $this->apiCall('SubDomains.get', [ + 'id' => $id, + 'domainname' => $domainname + ]); + + // parameters + $ssl_cert_file = $this->getParam('ssl_cert_file'); + $ssl_key_file = $this->getParam('ssl_key_file'); + $ssl_ca_file = $this->getParam('ssl_ca_file', true, ''); + $ssl_cert_chainfile = $this->getParam('ssl_cert_chainfile', true, ''); + $this->addOrUpdateCertificate($domain['id'], $ssl_cert_file, $ssl_key_file, $ssl_ca_file, $ssl_cert_chainfile, false); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] updated ssl-certificate for '" . $domain['domain'] . "'"); + $result = $this->apiCall('Certificates.get', [ + 'id' => $domain['id'] + ]); + return $this->response($result); + } + + /** + * lists all certificate entries + * + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue + * @param int $sql_limit + * optional specify number of results to be returned + * @param int $sql_offset + * optional specify offset for resultset + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more + * fields + * + * @access admin, customer + * @return string json-encoded array count|list + * @throws Exception + */ + public function listing() + { + // select all my (accessible) certificates + $certs_stmt_query = "SELECT s.*, d.domain, d.letsencrypt, c.customerid, c.loginname + FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s + LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON `d`.`id` = `s`.`domainid` + LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` c ON `c`.`customerid` = `d`.`customerid` + WHERE "; + + $qry_params = []; + $query_fields = []; + if ($this->isAdmin() && $this->getUserDetail('customers_see_all') == '0') { + // admin with only customer-specific permissions + $certs_stmt_query .= "d.adminid = :adminid "; + $qry_params['adminid'] = $this->getUserDetail('adminid'); + } elseif ($this->isAdmin() == false) { + // customer-area + $certs_stmt_query .= "d.customerid = :cid "; + $qry_params['cid'] = $this->getUserDetail('customerid'); + } else { + $certs_stmt_query .= "1 "; + } + $certs_stmt = Database::prepare($certs_stmt_query . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); + $qry_params = array_merge($qry_params, $query_fields); + Database::pexecute($certs_stmt, $qry_params, true, true); + $result = []; + while ($cert = $certs_stmt->fetch(PDO::FETCH_ASSOC)) { + // respect froxlor-hostname + if ($cert['domainid'] == 0) { + $cert['domain'] = Settings::Get('system.hostname'); + $cert['letsencrypt'] = Settings::Get('system.le_froxlor_enabled'); + $cert['loginname'] = 'froxlor.panel'; + } + + // Set data from certificate + $cert_data = openssl_x509_parse($cert['ssl_cert_file']); + if ($cert_data) { + $cert['validfromdate'] = date('Y-m-d H:i:s', $cert_data['validFrom_time_t']); + $cert['validtodate'] = date('Y-m-d H:i:s', $cert_data['validTo_time_t']); + $cert['isvalid'] = (bool)$cert_data['validTo_time_t'] > time(); + $cert['issuer'] = $cert_data['issuer']['O'] ?? null; + } + + // Set subject alt names from certificate + $cert['san'] = null; + if (isset($cert_data['extensions']['subjectAltName']) && !empty($cert_data['extensions']['subjectAltName'])) { + $SANs = explode(",", $cert_data['extensions']['subjectAltName']); + $SANs = array_map('trim', $SANs); + foreach ($SANs as $san) { + $san = str_replace("DNS:", "", $san); + if ($san != $cert_data['subject']['CN'] && strpos($san, "othername:") === false) { + $cert['san'][] = $san; + } + } + } + + $result[] = $cert; + } + return $this->response([ + 'count' => count($result), + 'list' => $result + ]); + } + + /** + * return ssl-certificate entry for given domain by either id or domainname + * + * @param int $id + * optional, the domain-id + * @param string $domainname + * optional, the domainname + * + * @access admin, customer + * @return string json-encoded array + * @throws Exception + */ + public function get() + { + $id = $this->getParam('id', true, 0); + $dn_optional = $id > 0; + $domainname = $this->getParam('domainname', $dn_optional, ''); + + if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'domains')) { + throw new Exception("You cannot access this resource", 405); + } + + $domain = $this->apiCall('SubDomains.get', [ + 'id' => $id, + 'domainname' => $domainname + ]); + $domainid = $domain['id']; + + $stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid`= :domainid"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] get ssl-certificate for '" . $domain['domain'] . "'"); + $result = Database::pexecute_first($stmt, [ + "domainid" => $domainid + ]); + if (!$result) { + throw new Exception("Domain '" . $domain['domain'] . "' does not have a certificate.", 412); + } + return $this->response($result); + } + + /** + * returns the total number of certificates for the given user + * + * @access admin, customer + * @return string json-encoded array + * @throws Exception + */ + public function listingCount() + { + // select all my (accessible) certificates + $certs_stmt_query = "SELECT COUNT(*) as num_certs + FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s + LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON `d`.`id` = `s`.`domainid` + LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` c ON `c`.`customerid` = `d`.`customerid` + WHERE "; + $qry_params = []; + if ($this->isAdmin() && $this->getUserDetail('customers_see_all') == '0') { + // admin with only customer-specific permissions + $certs_stmt_query .= "d.adminid = :adminid "; + $qry_params['adminid'] = $this->getUserDetail('adminid'); + } elseif ($this->isAdmin() == false) { + // customer-area + $certs_stmt_query .= "d.customerid = :cid "; + $qry_params['cid'] = $this->getUserDetail('customerid'); + } else { + $certs_stmt_query .= "1 "; + } + $certs_stmt = Database::prepare($certs_stmt_query); + $result = Database::pexecute_first($certs_stmt, $qry_params, true, true); + if ($result) { + return $this->response($result['num_certs']); + } + } + + /** + * delete certificates entry by id + * + * @param int $id + * + * @return string json-encoded array + * @throws Exception + */ + public function delete() + { + $id = $this->getParam('id'); + + if ($this->isAdmin() == false) { + $chk_stmt = Database::prepare(" + SELECT d.domain, d.letsencrypt FROM `" . TABLE_PANEL_DOMAINS . "` d + LEFT JOIN `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s ON s.domainid = d.id + WHERE s.`id` = :id AND d.`customerid` = :cid + "); + $chk = Database::pexecute_first($chk_stmt, [ + 'id' => $id, + 'cid' => $this->getUserDetail('customerid') + ]); + } elseif ($this->isAdmin()) { + $chk_stmt = Database::prepare(" + SELECT d.domain, d.letsencrypt FROM `" . TABLE_PANEL_DOMAINS . "` d + LEFT JOIN `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s ON s.domainid = d.id + WHERE s.`id` = :id" . ($this->getUserDetail('customers_see_all') == '0' ? " AND d.`adminid` = :aid" : "")); + $params = [ + 'id' => $id + ]; + if ($this->getUserDetail('customers_see_all') == '0') { + $params['aid'] = $this->getUserDetail('adminid'); + } + $chk = Database::pexecute_first($chk_stmt, $params); + if ($chk == false && $this->getUserDetail('change_serversettings')) { + // check whether it might be the froxlor-vhost certificate + $chk_stmt = Database::prepare(" + SELECT \"" . Settings::Get('system.hostname') . "\" as domain, \"" . Settings::Get('system.le_froxlor_enabled') . "\" as letsencrypt FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` + WHERE `id` = :id AND `domainid` = '0'"); + $params = [ + 'id' => $id + ]; + $chk = Database::pexecute_first($chk_stmt, $params); + $chk['isFroxlorVhost'] = true; + } + } + if ($chk !== false) { + // additional access check by trying to get the certificate + if (isset($chk['isFroxlorVhost']) && $chk['isFroxlorVhost'] == true) { + $result = $chk; + } else { + $result = $this->apiCall('Certificates.get', [ + 'domainname' => $chk['domain'] + ]); + } + $del_stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE id = :id"); + Database::pexecute($del_stmt, [ + 'id' => $id + ]); + // trigger removing of certificate from acme.sh if let's encrypt + if ($chk['letsencrypt'] == '1') { + Cronjob::inserttask(TaskId::DELETE_DOMAIN_SSL, $chk['domain']); + } + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] removed ssl-certificate for '" . $chk['domain'] . "'"); + return $this->response($result); + } + throw new Exception("Unable to determine SSL certificate. Maybe no access?", 406); + } } diff --git a/lib/Froxlor/Api/Commands/Cronjobs.php b/lib/Froxlor/Api/Commands/Cronjobs.php index 0285483f..6fd3bed5 100644 --- a/lib/Froxlor/Api/Commands/Cronjobs.php +++ b/lib/Froxlor/Api/Commands/Cronjobs.php @@ -1,24 +1,44 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Cron\TaskId; +use Froxlor\Database\Database; +use Froxlor\FroxlorLogger; +use Froxlor\System\Cronjob; +use Froxlor\Validate\Validate; +use PDO; + +/** + * @since 0.10.0 + */ +class Cronjobs extends ApiCommand implements ResourceEntity { /** @@ -26,18 +46,18 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE */ public function add() { - throw new \Exception('You cannot add new cronjobs yet.', 303); + throw new Exception('You cannot add new cronjobs yet.', 303); } /** * return a cronjob entry by id * * @param int $id - * cronjob-id - * + * cronjob-id + * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function get() { @@ -47,15 +67,15 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_CRONRUNS . "` WHERE `id` = :id "); - $result = Database::pexecute_first($result_stmt, array( + $result = Database::pexecute_first($result_stmt, [ 'id' => $id - ), true, true); + ], true, true); if ($result) { return $this->response($result); } - throw new \Exception("cronjob with id #" . $id . " could not be found", 404); + throw new Exception("cronjob with id #" . $id . " could not be found", 404); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** @@ -63,26 +83,25 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE * * @param int $id * @param bool $isactive - * optional whether the cronjob is active or not + * optional whether the cronjob is active or not * @param int $interval_value - * optional number of seconds/minutes/hours/etc. for the interval + * optional number of seconds/minutes/hours/etc. for the interval * @param string $interval_interval - * optional interval for the cronjob (MINUTE, HOUR, DAY, WEEK or MONTH) - * + * optional interval for the cronjob (MINUTE, HOUR, DAY, WEEK or MONTH) + * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function update() { if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) { - // required parameter $id = $this->getParam('id'); - $result = $this->apiCall('Cronjobs.get', array( + $result = $this->apiCall('Cronjobs.get', [ 'id' => $id - )); + ]); // split interval $cur_int = explode(" ", $result['interval']); @@ -96,8 +115,8 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE if ($isactive != 1) { $isactive = 0; } - $interval_value = \Froxlor\Validate\Validate::validate($interval_value, 'interval_value', '/^([0-9]+)$/Di', 'stringisempty', array(), true); - $interval_interval = \Froxlor\Validate\Validate::validate($interval_interval, 'interval_interval', '', '', array(), true); + $interval_value = Validate::validate($interval_value, 'interval_value', '/^([0-9]+)$/Di', 'stringisempty', [], true); + $interval_interval = Validate::validate($interval_interval, 'interval_interval', '', '', [], true); // put together interval value $interval = $interval_value . ' ' . strtoupper($interval_interval); @@ -107,65 +126,67 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE SET `isactive` = :isactive, `interval` = :int WHERE `id` = :id "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'isactive' => $isactive, 'int' => $interval, 'id' => $id - ), true, true); + ], true, true); // insert task to re-generate the cron.d-file - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_CRON); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] cronjob with description '" . $result['module'] . '/' . $result['cronfile'] . "' has been updated by '" . $this->getUserDetail('loginname') . "'"); - $result = $this->apiCall('Cronjobs.get', array( + Cronjob::inserttask(TaskId::REBUILD_CRON); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] cronjob with description '" . $result['module'] . '/' . $result['cronfile'] . "' has been updated by '" . $this->getUserDetail('loginname') . "'"); + $result = $this->apiCall('Cronjobs.get', [ 'id' => $id - )); + ]); return $this->response($result); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * lists all cronjob entries * * @param array $sql_search - * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue * @param int $sql_limit - * optional specify number of results to be returned + * optional specify number of results to be returned * @param int $sql_offset - * optional specify offset for resultset + * optional specify offset for resultset * @param array $sql_orderby - * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more + * fields * * @access admin - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listing() { if ($this->isAdmin()) { - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list cronjobs"); - $query_fields = array(); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list cronjobs"); + $query_fields = []; $result_stmt = Database::prepare(" SELECT `c`.* FROM `" . TABLE_PANEL_CRONRUNS . "` `c` " . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit()); Database::pexecute($result_stmt, $query_fields, true, true); - $result = array(); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + $result = []; + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $result[] = $row; } - return $this->response(array( + return $this->response([ 'count' => count($result), 'list' => $result - )); + ]); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * returns the total number of cronjobs * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function listingCount() { @@ -178,7 +199,7 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE return $this->response($result['num_crons']); } } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** @@ -186,6 +207,6 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE */ public function delete() { - throw new \Exception('You cannot delete system cronjobs.', 303); + throw new Exception('You cannot delete system cronjobs.', 303); } } diff --git a/lib/Froxlor/Api/Commands/CustomerBackups.php b/lib/Froxlor/Api/Commands/CustomerBackups.php index a5675a3c..124532b0 100644 --- a/lib/Froxlor/Api/Commands/CustomerBackups.php +++ b/lib/Froxlor/Api/Commands/CustomerBackups.php @@ -1,64 +1,68 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity -{ - /** - * check whether backup is enabled systemwide and if accessible for customer (hide_options) - * - * @throws \Exception - */ - private function validateAccess() - { - if (Settings::Get('system.backupenabled') != 1) { - throw new \Exception("You cannot access this resource", 405); - } - if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) { - throw new \Exception("You cannot access this resource", 405); - } - if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras.backup')) { - throw new \Exception("You cannot access this resource", 405); - } - } +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Cron\TaskId; +use Froxlor\Database\Database; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; +use Froxlor\Settings; +use Froxlor\System\Cronjob; +use Froxlor\UI\Response; +use Froxlor\Validate\Validate; +use PDO; + +/** + * @since 0.10.0 + */ +class CustomerBackups extends ApiCommand implements ResourceEntity +{ /** * add a new customer backup job * * @param string $path - * path to store the backup to + * path to store the backup to * @param bool $backup_dbs - * optional whether to backup databases, default is 0 (false) + * optional whether to backup databases, default is 0 (false) * @param bool $backup_mail - * optional whether to backup mail-data, default is 0 (false) + * optional whether to backup mail-data, default is 0 (false) * @param bool $backup_web - * optional whether to backup web-data, default is 0 (false) + * optional whether to backup web-data, default is 0 (false) * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) - * + * optional, required when called as admin (if $customerid is not specified) + * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function add() { @@ -76,13 +80,13 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re $customer = $this->getCustomerData(); // validation - $path = \Froxlor\FileDir::makeCorrectDir(\Froxlor\Validate\Validate::validate($path, 'path', '', '', array(), true)); + $path = FileDir::makeCorrectDir(Validate::validate($path, 'path', '', '', [], true)); $userpath = $path; - $path = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path); + $path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path); // path cannot be the customers docroot - if ($path == \Froxlor\FileDir::makeCorrectDir($customer['documentroot'])) { - \Froxlor\UI\Response::standard_error('backupfoldercannotbedocroot', '', true); + if ($path == FileDir::makeCorrectDir($customer['documentroot'])) { + Response::standardError('backupfoldercannotbedocroot', '', true); } if ($backup_dbs != '1') { @@ -97,7 +101,7 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re $backup_web = '0'; } - $task_data = array( + $task_data = [ 'customerid' => $customer['customerid'], 'uid' => $customer['guid'], 'gid' => $customer['guid'], @@ -106,21 +110,39 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re 'backup_dbs' => $backup_dbs, 'backup_mail' => $backup_mail, 'backup_web' => $backup_web - ); + ]; // schedule backup job - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_CUSTOMER_BACKUP, $task_data); + Cronjob::inserttask(TaskId::CREATE_CUSTOMER_BACKUP, $task_data); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] added customer-backup job for '" . $customer['loginname'] . "'. Target directory: " . $userpath); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] added customer-backup job for '" . $customer['loginname'] . "'. Target directory: " . $userpath); return $this->response($task_data); } + /** + * check whether backup is enabled systemwide and if accessible for customer (hide_options) + * + * @throws Exception + */ + private function validateAccess() + { + if (Settings::Get('system.backupenabled') != 1) { + throw new Exception("You cannot access this resource", 405); + } + if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) { + throw new Exception("You cannot access this resource", 405); + } + if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras.backup')) { + throw new Exception("You cannot access this resource", 405); + } + } + /** * You cannot get a planned backup. * Try CustomerBackups.listing() */ public function get() { - throw new \Exception('You cannot get a planned backup. Try CustomerBackups.listing()', 303); + throw new Exception('You cannot get a planned backup. Try CustomerBackups.listing()', 303); } /** @@ -129,28 +151,31 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re */ public function update() { - throw new \Exception('You cannot update a planned backup. You need to delete it and re-add it.', 303); + throw new Exception('You cannot update a planned backup. You need to delete it and re-add it.', 303); } /** - * list all planned backup-jobs, if called from an admin, list all planned backup-jobs of all customers you are allowed to view, or specify id or loginname for one specific customer + * list all planned backup-jobs, if called from an admin, list all planned backup-jobs of all customers you are + * allowed to view, or specify id or loginname for one specific customer * * @param int $customerid - * optional, admin-only, select backup-jobs of a specific customer by id + * optional, admin-only, select backup-jobs of a specific customer by id * @param string $loginname - * optional, admin-only, select backup-jobs of a specific customer by loginname + * optional, admin-only, select backup-jobs of a specific customer by loginname * @param array $sql_search - * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue * @param int $sql_limit - * optional specify number of results to be returned + * optional specify number of results to be returned * @param int $sql_offset - * optional specify offset for resultset + * optional specify offset for resultset * @param array $sql_orderby - * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more + * fields * * @access admin, customer - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listing() { @@ -159,34 +184,34 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re $customer_ids = $this->getAllowedCustomerIds('extras.backup'); // check whether there is a backup-job for this customer - $query_fields = array(); + $query_fields = []; $sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = '20'" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); Database::pexecute($sel_stmt, $query_fields, true, true); - $result = array(); - while ($entry = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) { + $result = []; + while ($entry = $sel_stmt->fetch(PDO::FETCH_ASSOC)) { $entry['data'] = json_decode($entry['data'], true); if (in_array($entry['data']['customerid'], $customer_ids)) { $result[] = $entry; } } - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list customer-backups"); - return $this->response(array( + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list customer-backups"); + return $this->response([ 'count' => count($result), 'list' => $result - )); + ]); } /** * returns the total number of planned backups * * @param int $customerid - * optional, admin-only, select backup-jobs of a specific customer by id + * optional, admin-only, select backup-jobs of a specific customer by id * @param string $loginname - * optional, admin-only, select backup-jobs of a specific customer by loginname - * + * optional, admin-only, select backup-jobs of a specific customer by loginname + * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function listingCount() { @@ -198,10 +223,10 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re $result_count = 0; $sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = '20'"); Database::pexecute($sel_stmt, null, true, true); - while ($entry = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($entry = $sel_stmt->fetch(PDO::FETCH_ASSOC)) { $entry['data'] = json_decode($entry['data'], true); if (in_array($entry['data']['customerid'], $customer_ids)) { - $result_count ++; + $result_count++; } } return $this->response($result_count); @@ -211,15 +236,15 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re * delete a planned backup-jobs by id, if called from an admin you need to specify the customerid/loginname * * @param int $backup_job_entry - * id of backup job + * id of backup job * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) - * + * optional, required when called as admin (if $customerid is not specified) + * * @access admin, customer - * @throws \Exception * @return bool + * @throws Exception */ public function delete() { @@ -235,14 +260,14 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re // check for the correct job foreach ($result['list'] as $backupjob) { if ($backupjob['id'] == $entry && in_array($backupjob['data']['customerid'], $customer_ids)) { - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'tid' => $entry - ), true, true); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] deleted planned customer-backup #" . $entry); + ], true, true); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] deleted planned customer-backup #" . $entry); return $this->response(true); } } } - throw new \Exception('Backup job with id #' . $entry . ' could not be found', 404); + throw new Exception('Backup job with id #' . $entry . ' could not be found', 404); } } diff --git a/lib/Froxlor/Api/Commands/Customers.php b/lib/Froxlor/Api/Commands/Customers.php index 1348b348..7362154a 100644 --- a/lib/Froxlor/Api/Commands/Customers.php +++ b/lib/Froxlor/Api/Commands/Customers.php @@ -1,65 +1,93 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Cron\TaskId; +use Froxlor\Database\Database; +use Froxlor\Database\DbManager; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; +use Froxlor\Idna\IdnaWrapper; +use Froxlor\Settings; +use Froxlor\System\Cronjob; +use Froxlor\System\Crypt; +use Froxlor\UI\Response; +use Froxlor\User; +use Froxlor\Validate\Validate; +use PDO; + +/** + * @since 0.10.0 + */ +class Customers extends ApiCommand implements ResourceEntity { /** * lists all customer entries * * @param array $sql_search - * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue * @param int $sql_limit - * optional specify number of results to be returned + * optional specify number of results to be returned * @param int $sql_offset - * optional specify offset for resultset + * optional specify offset for resultset * @param array $sql_orderby - * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more + * fields * @param bool $show_usages - * optional, default false + * optional, default false * * @access admin - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listing() { if ($this->isAdmin()) { $show_usages = $this->getBoolParam('show_usages', true, false); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list customers"); - $query_fields = array(); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list customers"); + $query_fields = []; $result_stmt = Database::prepare(" SELECT `c`.*, `a`.`loginname` AS `adminname` FROM `" . TABLE_PANEL_CUSTOMERS . "` `c`, `" . TABLE_PANEL_ADMINS . "` `a` WHERE " . ($this->getUserDetail('customers_see_all') ? '' : " `c`.`adminid` = :adminid AND ") . " `c`.`adminid` = `a`.`adminid`" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); - $params = array(); + $params = []; if ($this->getUserDetail('customers_see_all') == '0') { - $params = array( + $params = [ 'adminid' => $this->getUserDetail('adminid') - ); + ]; } $params = array_merge($params, $query_fields); Database::pexecute($result_stmt, $params, true, true); - $result = array(); + $result = []; $domains_stmt = null; $usages_stmt = null; @@ -78,19 +106,19 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource "); } - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { if ($show_usages) { // get number of domains - Database::pexecute($domains_stmt, array( + Database::pexecute($domains_stmt, [ 'cid' => $row['customerid'], 'stdd' => $row['standardsubdomain'] - )); - $domains = $domains_stmt->fetch(\PDO::FETCH_ASSOC); + ]); + $domains = $domains_stmt->fetch(PDO::FETCH_ASSOC); $row['domains'] = intval($domains['domains']); // get disk-space usages for web, mysql and mail - $usages = Database::pexecute_first($usages_stmt, array( + $usages = Database::pexecute_first($usages_stmt, [ 'cid' => $row['customerid'] - )); + ]); if ($usages) { $row['webspace_used'] = $usages['webspace']; $row['mailspace_used'] = $usages['mail']; @@ -103,20 +131,20 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource } $result[] = $row; } - return $this->response(array( + return $this->response([ 'count' => count($result), 'list' => $result - )); + ]); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * returns the total number of customers for the given admin * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function listingCount() { @@ -125,108 +153,18 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource SELECT COUNT(*) as num_customers FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE " . ($this->getUserDetail('customers_see_all') ? "1" : " `adminid` = :adminid ")); - $params = array(); + $params = []; if ($this->getUserDetail('customers_see_all') == '0') { - $params = array( + $params = [ 'adminid' => $this->getUserDetail('adminid') - ); + ]; } $result = Database::pexecute_first($result_stmt, $params, true, true); if ($result) { return $this->response($result['num_customers']); } } - throw new \Exception("Not allowed to execute given command.", 403); - } - - /** - * return a customer entry by either id or loginname - * - * @param int $id - * optional, the customer-id - * @param string $loginname - * optional, the loginname - * @param bool $show_usages - * optional, default false - * - * @access admin, customer - * @throws \Exception - * @return string json-encoded array - */ - public function get() - { - $id = $this->getParam('id', true, 0); - $ln_optional = $id > 0; - $loginname = $this->getParam('loginname', $ln_optional, ''); - $show_usages = $this->getBoolParam('show_usages', true, false); - - if ($this->isAdmin()) { - $result_stmt = Database::prepare(" - SELECT `c`.*, `a`.`loginname` AS `adminname` - FROM `" . TABLE_PANEL_CUSTOMERS . "` `c`, `" . TABLE_PANEL_ADMINS . "` `a` - WHERE " . ($id > 0 ? "`c`.`customerid` = :idln" : "`c`.`loginname` = :idln") . ($this->getUserDetail('customers_see_all') ? '' : " AND `c`.`adminid` = :adminid") . " AND `c`.`adminid` = `a`.`adminid`"); - $params = array( - 'idln' => ($id <= 0 ? $loginname : $id) - ); - if ($this->getUserDetail('customers_see_all') == '0') { - $params['adminid'] = $this->getUserDetail('adminid'); - } - } else { - if (($id > 0 && $id != $this->getUserDetail('customerid')) || ! empty($loginname) && $loginname != $this->getUserDetail('loginname')) { - throw new \Exception("You cannot access data of other customers", 401); - } - $result_stmt = Database::prepare(" - SELECT * FROM `" . TABLE_PANEL_CUSTOMERS . "` - WHERE " . ($id > 0 ? "`customerid` = :idln" : "`loginname` = :idln")); - $params = array( - 'idln' => ($id <= 0 ? $loginname : $id) - ); - } - $result = Database::pexecute_first($result_stmt, $params, true, true); - if ($result) { - // check whether the admin does not want the customer to see the notes - if (! $this->isAdmin() && $result['custom_notes_show'] != 1) { - $result['custom_notes'] = ""; - } - if ($show_usages) { - // get number of domains - $domains_stmt = Database::prepare(" - SELECT COUNT(`id`) AS `domains` - FROM `" . TABLE_PANEL_DOMAINS . "` - WHERE `customerid` = :cid - AND `parentdomainid` = '0' - AND `id`<> :stdd - "); - Database::pexecute($domains_stmt, array( - 'cid' => $result['customerid'], - 'stdd' => $result['standardsubdomain'] - )); - $domains = $domains_stmt->fetch(\PDO::FETCH_ASSOC); - $result['domains'] = intval($domains['domains']); - // get disk-space usages for web, mysql and mail - $usages_stmt = Database::prepare(" - SELECT * FROM `" . TABLE_PANEL_DISKSPACE . "` - WHERE `customerid` = :cid - ORDER BY `stamp` DESC LIMIT 1 - "); - $usages = Database::pexecute_first($usages_stmt, array( - 'cid' => $result['customerid'] - )); - if ($usages) { - $result['webspace_used'] = $usages['webspace']; - $result['mailspace_used'] = $usages['mail']; - $result['dbspace_used'] = $usages['mysql']; - } else { - $result['webspace_used'] = 0; - $result['mailspace_used'] = 0; - $result['dbspace_used'] = 0; - } - } - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get customer '" . $result['loginname'] . "'"); - return $this->response($result); - } - $key = ($id > 0 ? "id #" . $id : "loginname '" . $loginname . "'"); - throw new \Exception("Customer with " . $key . " could not be found", 404); + throw new Exception("Not allowed to execute given command.", 403); } /** @@ -234,112 +172,120 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource * * @param string $email * @param string $name - * optional if company is set, else required + * optional if company is set, else required * @param string $firstname - * optional if company is set, else required + * optional if company is set, else required * @param string $company - * optional but required if name/firstname empty + * optional but required if name/firstname empty * @param string $street - * optional + * optional * @param string $zipcode - * optional + * optional * @param string $city - * optional + * optional * @param string $phone - * optional + * optional * @param string $fax - * optional + * optional * @param int $customernumber - * optional - * @param string $def_language, - * optional, default is system-default language + * optional + * @param string $def_language , + * optional, default is system-default language * @param bool $api_allowed - * optional, default is true if system setting api.enabled is true, else false + * optional, default is true if system setting api.enabled is true, else false * @param int $gender - * optional, 0 = no-gender, 1 = male, 2 = female + * optional, 0 = no-gender, 1 = male, 2 = female * @param string $custom_notes - * optional notes + * optional notes * @param bool $custom_notes_show - * optional, whether to show the content of custom_notes to the customer, default 0 (false) + * optional, whether to show the content of custom_notes to the customer, default 0 + * (false) * @param string $new_loginname - * optional, if empty generated automatically using customer-prefix and increasing number + * optional, if empty generated automatically using customer-prefix and increasing + * number * @param string $new_customer_password - * optional, if empty generated automatically and send to the customer's email if $sendpassword is 1 + * optional, if empty generated automatically and send to the customer's email if + * $sendpassword is 1 * @param bool $sendpassword - * optional, whether to send the password to the customer after creation, default 0 (false) + * optional, whether to send the password to the customer after creation, default 0 + * (false) * @param int $diskspace - * optional disk-space available for customer in MB, default 0 + * optional disk-space available for customer in MB, default 0 * @param bool $diskspace_ul - * optional, whether customer should have unlimited diskspace, default 0 (false) + * optional, whether customer should have unlimited diskspace, default 0 (false) * @param int $traffic - * optional traffic available for customer in GB, default 0 + * optional traffic available for customer in GB, default 0 * @param bool $traffic_ul - * optional, whether customer should have unlimited traffic, default 0 (false) + * optional, whether customer should have unlimited traffic, default 0 (false) * @param int $subdomains - * optional amount of subdomains available for customer, default 0 + * optional amount of subdomains available for customer, default 0 * @param bool $subdomains_ul - * optional, whether customer should have unlimited subdomains, default 0 (false) + * optional, whether customer should have unlimited subdomains, default 0 (false) * @param int $emails - * optional amount of emails available for customer, default 0 + * optional amount of emails available for customer, default 0 * @param bool $emails_ul - * optional, whether customer should have unlimited emails, default 0 (false) + * optional, whether customer should have unlimited emails, default 0 (false) * @param int $email_accounts - * optional amount of email-accounts available for customer, default 0 + * optional amount of email-accounts available for customer, default 0 * @param bool $email_accounts_ul - * optional, whether customer should have unlimited email-accounts, default 0 (false) + * optional, whether customer should have unlimited email-accounts, default 0 (false) * @param int $email_forwarders - * optional amount of email-forwarders available for customer, default 0 + * optional amount of email-forwarders available for customer, default 0 * @param bool $email_forwarders_ul - * optional, whether customer should have unlimited email-forwarders, default 0 (false) + * optional, whether customer should have unlimited email-forwarders, default 0 (false) * @param int $email_quota - * optional size of email-quota available for customer in MB, default is system-setting mail_quota + * optional size of email-quota available for customer in MB, default is system-setting + * mail_quota * @param bool $email_quota_ul - * optional, whether customer should have unlimited email-quota, default 0 (false) + * optional, whether customer should have unlimited email-quota, default 0 (false) * @param bool $email_imap - * optional, whether to allow IMAP access, default 0 (false) + * optional, whether to allow IMAP access, default 0 (false) * @param bool $email_pop3 - * optional, whether to allow POP3 access, default 0 (false) + * optional, whether to allow POP3 access, default 0 (false) * @param int $ftps - * optional amount of ftp-accounts available for customer, default 0 + * optional amount of ftp-accounts available for customer, default 0 * @param bool $ftps_ul - * optional, whether customer should have unlimited ftp-accounts, default 0 (false) + * optional, whether customer should have unlimited ftp-accounts, default 0 (false) * @param int $mysqls - * optional amount of mysql-databases available for customer, default 0 + * optional amount of mysql-databases available for customer, default 0 * @param bool $mysqls_ul - * optional, whether customer should have unlimited mysql-databases, default 0 (false) + * optional, whether customer should have unlimited mysql-databases, default 0 (false) * @param bool $createstdsubdomain - * optional, whether to create a standard-subdomain ([loginname].froxlor-hostname.tld), default [system.createstdsubdom_default] + * optional, whether to create a standard-subdomain ([loginname].froxlor-hostname.tld), + * default [system.createstdsubdom_default] * @param bool $phpenabled - * optional, whether to allow usage of PHP, default 0 (false) + * optional, whether to allow usage of PHP, default 0 (false) * @param array $allowed_phpconfigs - * optional, array of IDs of php-config that the customer is allowed to use, default empty (none) + * optional, array of IDs of php-config that the customer is allowed to use, default + * empty (none) * @param bool $perlenabled - * optional, whether to allow usage of Perl/CGI, default 0 (false) + * optional, whether to allow usage of Perl/CGI, default 0 (false) * @param bool $dnsenabled - * optional, whether to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false) + * optional, whether to allow usage of the DNS editor (requires activated nameserver in + * settings), default 0 (false) * @param bool $logviewenabled - * optional, whether to allow access to webserver access/error-logs, default 0 (false) + * optional, whether to allow access to webserver access/error-logs, default 0 (false) * @param bool $store_defaultindex - * optional, whether to store the default index file to customers homedir + * optional, whether to store the default index file to customers homedir * @param int $hosting_plan_id - * optional, specify a hosting-plan to set certain resource-values from the plan instead of specifying them + * optional, specify a hosting-plan to set certain resource-values from the plan + * instead of specifying them * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function add() { if ($this->isAdmin()) { if ($this->getUserDetail('customers_used') < $this->getUserDetail('customers') || $this->getUserDetail('customers') == '-1') { - // required parameters $email = $this->getParam('email'); // parameters $name = $this->getParam('name', true, ''); $firstname = $this->getParam('firstname', true, ''); - $company_required = (! empty($name) && empty($firstname)) || (empty($name) && ! empty($firstname)) || (empty($name) && empty($firstname)); + $company_required = (!empty($name) && empty($firstname)) || (empty($name) && !empty($firstname)) || (empty($name) && empty($firstname)); $company = $this->getParam('company', !$company_required, ''); $street = $this->getParam('street', true, ''); $zipcode = $this->getParam('zipcode', true, ''); @@ -349,7 +295,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $customernumber = $this->getParam('customernumber', true, ''); $def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage')); $api_allowed = $this->getBoolParam('api_allowed', true, Settings::Get('api.enabled')); - $gender = (int) $this->getParam('gender', true, 0); + $gender = (int)$this->getParam('gender', true, 0); $custom_notes = $this->getParam('custom_notes', true, ''); $custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0); $createstdsubdomain = $this->getBoolParam('createstdsubdomain', true, Settings::Get('system.createstdsubdom_default')); @@ -361,9 +307,9 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource // hosting-plan values $hosting_plan_id = $this->getParam('hosting_plan_id', true, 0); if ($hosting_plan_id > 0) { - $hp_result = $this->apiCall('HostingPlans.get', array( + $hp_result = $this->apiCall('HostingPlans.get', [ 'id' => $hosting_plan_id - )); + ]); $hp_result['value'] = json_decode($hp_result['value'], true); foreach ($hp_result['value'] as $index => $value) { $hp_result[$index] = $value; @@ -397,36 +343,36 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $ftps = $this->getUlParam('ftps', 'ftps_ul', true, 0); $mysqls = $this->getUlParam('mysqls', 'mysqls_ul', true, 0); $phpenabled = $this->getBoolParam('phpenabled', true, 0); - $p_allowed_phpconfigs = $this->getParam('allowed_phpconfigs', true, array()); + $p_allowed_phpconfigs = $this->getParam('allowed_phpconfigs', true, []); $perlenabled = $this->getBoolParam('perlenabled', true, 0); $dnsenabled = $this->getBoolParam('dnsenabled', true, 0); $logviewenabled = $this->getBoolParam('logviewenabled', true, 0); } // validation - $name = \Froxlor\Validate\Validate::validate($name, 'name', '', '', array(), true); - $firstname = \Froxlor\Validate\Validate::validate($firstname, 'first name', '', '', array(), true); - $company = \Froxlor\Validate\Validate::validate($company, 'company', '', '', array(), true); - $street = \Froxlor\Validate\Validate::validate($street, 'street', '', '', array(), true); - $zipcode = \Froxlor\Validate\Validate::validate($zipcode, 'zipcode', '/^[0-9 \-A-Z]*$/', '', array(), true); - $city = \Froxlor\Validate\Validate::validate($city, 'city', '', '', array(), true); - $phone = \Froxlor\Validate\Validate::validate($phone, 'phone', '/^[0-9\- \+\(\)\/]*$/', '', array(), true); - $fax = \Froxlor\Validate\Validate::validate($fax, 'fax', '/^[0-9\- \+\(\)\/]*$/', '', array(), true); - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); - $email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true)); - $customernumber = \Froxlor\Validate\Validate::validate($customernumber, 'customer number', '/^[A-Za-z0-9 \-]*$/Di', '', array(), true); - $def_language = \Froxlor\Validate\Validate::validate($def_language, 'default language', '', '', array(), true); - $custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true); + $name = Validate::validate($name, 'name', '', '', [], true); + $firstname = Validate::validate($firstname, 'first name', '', '', [], true); + $company = Validate::validate($company, 'company', '', '', [], true); + $street = Validate::validate($street, 'street', '', '', [], true); + $zipcode = Validate::validate($zipcode, 'zipcode', '/^[0-9 \-A-Z]*$/', '', [], true); + $city = Validate::validate($city, 'city', '', '', [], true); + $phone = Validate::validate($phone, 'phone', '/^[0-9\- \+\(\)\/]*$/', '', [], true); + $fax = Validate::validate($fax, 'fax', '/^[0-9\- \+\(\)\/]*$/', '', [], true); + $idna_convert = new IdnaWrapper(); + $email = $idna_convert->encode(Validate::validate($email, 'email', '', '', [], true)); + $customernumber = Validate::validate($customernumber, 'customer number', '/^[A-Za-z0-9 \-]*$/Di', '', [], true); + $def_language = Validate::validate($def_language, 'default language', '', '', [], true); + $custom_notes = Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', Validate::REGEX_CONF_TEXT, '', [], true); if (Settings::Get('system.mail_quota_enabled') != '1') { - $email_quota = - 1; + $email_quota = -1; } - $password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true); + $password = Validate::validate($password, 'password', '', '', [], true); // only check if not empty, // cause empty == generate password automatically if ($password != '') { - $password = \Froxlor\System\Crypt::validatePassword($password, true); + $password = Crypt::validatePassword($password, true); } // gender out of range? [0,2] @@ -434,8 +380,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $gender = 0; } - $allowed_phpconfigs = array(); - if (! empty($p_allowed_phpconfigs) && is_array($p_allowed_phpconfigs)) { + $allowed_phpconfigs = []; + if (!empty($p_allowed_phpconfigs) && is_array($p_allowed_phpconfigs)) { foreach ($p_allowed_phpconfigs as $allowed_phpconfig) { $allowed_phpconfig = intval($allowed_phpconfig); $allowed_phpconfigs[] = $allowed_phpconfig; @@ -447,25 +393,24 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $traffic = $traffic * 1024 * 1024; if (((($this->getUserDetail('diskspace_used') + $diskspace) > $this->getUserDetail('diskspace')) && ($this->getUserDetail('diskspace') / 1024) != '-1') || ((($this->getUserDetail('mysqls_used') + $mysqls) > $this->getUserDetail('mysqls')) && $this->getUserDetail('mysqls') != '-1') || ((($this->getUserDetail('emails_used') + $emails) > $this->getUserDetail('emails')) && $this->getUserDetail('emails') != '-1') || ((($this->getUserDetail('email_accounts_used') + $email_accounts) > $this->getUserDetail('email_accounts')) && $this->getUserDetail('email_accounts') != '-1') || ((($this->getUserDetail('email_forwarders_used') + $email_forwarders) > $this->getUserDetail('email_forwarders')) && $this->getUserDetail('email_forwarders') != '-1') || ((($this->getUserDetail('email_quota_used') + $email_quota) > $this->getUserDetail('email_quota')) && $this->getUserDetail('email_quota') != '-1' && Settings::Get('system.mail_quota_enabled') == '1') || ((($this->getUserDetail('ftps_used') + $ftps) > $this->getUserDetail('ftps')) && $this->getUserDetail('ftps') != '-1') || ((($this->getUserDetail('subdomains_used') + $subdomains) > $this->getUserDetail('subdomains')) && $this->getUserDetail('subdomains') != '-1') || (($diskspace / 1024) == '-1' && ($this->getUserDetail('diskspace') / 1024) != '-1') || ($mysqls == '-1' && $this->getUserDetail('mysqls') != '-1') || ($emails == '-1' && $this->getUserDetail('emails') != '-1') || ($email_accounts == '-1' && $this->getUserDetail('email_accounts') != '-1') || ($email_forwarders == '-1' && $this->getUserDetail('email_forwarders') != '-1') || ($email_quota == '-1' && $this->getUserDetail('email_quota') != '-1' && Settings::Get('system.mail_quota_enabled') == '1') || ($ftps == '-1' && $this->getUserDetail('ftps') != '-1') || ($subdomains == '-1' && $this->getUserDetail('subdomains') != '-1')) { - \Froxlor\UI\Response::standard_error('youcantallocatemorethanyouhave', '', true); + Response::standardError('youcantallocatemorethanyouhave', '', true); } - if (! \Froxlor\Validate\Validate::validateEmail($email)) { - \Froxlor\UI\Response::standard_error('emailiswrong', $email, true); + if (!Validate::validateEmail($email)) { + Response::standardError('emailiswrong', $email, true); } else { - if ($loginname != '') { $accountnumber = intval(Settings::Get('system.lastaccountnumber')); - $loginname = \Froxlor\Validate\Validate::validate($loginname, 'loginname', '/^[a-z][a-z0-9\-_]+$/i', '', array(), true); + $loginname = Validate::validate($loginname, 'loginname', '/^[a-z][a-z0-9\-_]+$/i', '', [], true); // Accounts which match systemaccounts are not allowed, filtering them if (preg_match('/^' . preg_quote(Settings::Get('customer.accountprefix'), '/') . '([0-9]+)/', $loginname)) { - \Froxlor\UI\Response::standard_error('loginnameissystemaccount', Settings::Get('customer.accountprefix'), true); + Response::standardError('loginnameissystemaccount', Settings::Get('customer.accountprefix'), true); } // Additional filtering for Bug #962 - if (function_exists('posix_getpwnam') && ! in_array("posix_getpwnam", explode(",", ini_get('disable_functions'))) && posix_getpwnam($loginname)) { - \Froxlor\UI\Response::standard_error('loginnameissystemaccount', Settings::Get('customer.accountprefix'), true); + if (function_exists('posix_getpwnam') && !in_array("posix_getpwnam", explode(",", ini_get('disable_functions'))) && posix_getpwnam($loginname)) { + Response::standardError('loginnameissystemaccount', Settings::Get('customer.accountprefix'), true); } } else { $accountnumber = intval(Settings::Get('system.lastaccountnumber')) + 1; @@ -477,47 +422,47 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $loginname_check_stmt = Database::prepare(" SELECT `loginname` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `loginname` = :login "); - $loginname_check = Database::pexecute_first($loginname_check_stmt, array( + $loginname_check = Database::pexecute_first($loginname_check_stmt, [ 'login' => $loginname - ), true, true); + ], true, true); // Check if an admin with the loginname already exists // do not check via api as we skip any permission checks for this task $loginname_check_admin_stmt = Database::prepare(" SELECT `loginname` FROM `" . TABLE_PANEL_ADMINS . "` WHERE `loginname` = :login "); - $loginname_check_admin = Database::pexecute_first($loginname_check_admin_stmt, array( + $loginname_check_admin = Database::pexecute_first($loginname_check_admin_stmt, [ 'login' => $loginname - ), true, true); + ], true, true); - $mysql_maxlen = \Froxlor\Database\Database::getSqlUsernameLength() - strlen(Settings::Get('customer.mysqlprefix')); + $mysql_maxlen = Database::getSqlUsernameLength() - strlen(Settings::Get('customer.mysqlprefix')); if (($loginname_check && strtolower($loginname_check['loginname']) == strtolower($loginname)) || ($loginname_check_admin && strtolower($loginname_check_admin['loginname']) == strtolower($loginname))) { - \Froxlor\UI\Response::standard_error('loginnameexists', $loginname, true); - } elseif (! \Froxlor\Validate\Validate::validateUsername($loginname, Settings::Get('panel.unix_names'), $mysql_maxlen)) { + Response::standardError('loginnameexists', $loginname, true); + } elseif (!Validate::validateUsername($loginname, Settings::Get('panel.unix_names'), $mysql_maxlen)) { if (strlen($loginname) > $mysql_maxlen) { - \Froxlor\UI\Response::standard_error('loginnameiswrong2', $mysql_maxlen, true); + Response::standardError('loginnameiswrong2', $mysql_maxlen, true); } else { - \Froxlor\UI\Response::standard_error('loginnameiswrong', $loginname, true); + Response::standardError('loginnameiswrong', $loginname, true); } } $guid = intval(Settings::Get('system.lastguid')) + 1; - $documentroot = \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.documentroot_prefix') . '/' . $loginname); + $documentroot = FileDir::makeCorrectDir(Settings::Get('system.documentroot_prefix') . '/' . $loginname); if (file_exists($documentroot)) { - \Froxlor\UI\Response::standard_error('documentrootexists', $documentroot, true); + Response::standardError('documentrootexists', $documentroot, true); } if ($password == '') { - $password = \Froxlor\System\Crypt::generatePassword(); + $password = Crypt::generatePassword(); } $_theme = Settings::Get('panel.default_theme'); - $ins_data = array( + $ins_data = [ 'adminid' => $this->getUserDetail('adminid'), 'loginname' => $loginname, - 'passwd' => \Froxlor\System\Crypt::makeCryptPassword($password), + 'passwd' => Crypt::makeCryptPassword($password), 'name' => $name, 'firstname' => $firstname, 'gender' => $gender, @@ -552,7 +497,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource 'theme' => $_theme, 'custom_notes' => $custom_notes, 'custom_notes_show' => $custom_notes_show - ); + ]; $ins_stmt = Database::prepare(" INSERT INTO `" . TABLE_PANEL_CUSTOMERS . "` SET @@ -602,35 +547,35 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource // update admin resource-usage if ($mysqls != '-1') { - Admins::increaseUsage($this->getUserDetail('adminid'), 'mysqls_used', '', (int) $mysqls); + Admins::increaseUsage($this->getUserDetail('adminid'), 'mysqls_used', '', (int)$mysqls); } if ($emails != '-1') { - Admins::increaseUsage($this->getUserDetail('adminid'), 'emails_used', '', (int) $emails); + Admins::increaseUsage($this->getUserDetail('adminid'), 'emails_used', '', (int)$emails); } if ($email_accounts != '-1') { - Admins::increaseUsage($this->getUserDetail('adminid'), 'email_accounts_used', '', (int) $email_accounts); + Admins::increaseUsage($this->getUserDetail('adminid'), 'email_accounts_used', '', (int)$email_accounts); } if ($email_forwarders != '-1') { - Admins::increaseUsage($this->getUserDetail('adminid'), 'email_forwarders_used', '', (int) $email_forwarders); + Admins::increaseUsage($this->getUserDetail('adminid'), 'email_forwarders_used', '', (int)$email_forwarders); } if ($email_quota != '-1') { - Admins::increaseUsage($this->getUserDetail('adminid'), 'email_quota_used', '', (int) $email_quota); + Admins::increaseUsage($this->getUserDetail('adminid'), 'email_quota_used', '', (int)$email_quota); } if ($subdomains != '-1') { - Admins::increaseUsage($this->getUserDetail('adminid'), 'subdomains_used', '', (int) $subdomains); + Admins::increaseUsage($this->getUserDetail('adminid'), 'subdomains_used', '', (int)$subdomains); } if ($ftps != '-1') { - Admins::increaseUsage($this->getUserDetail('adminid'), 'ftps_used', '', (int) $ftps); + Admins::increaseUsage($this->getUserDetail('adminid'), 'ftps_used', '', (int)$ftps); } if (($diskspace / 1024) != '-1') { - Admins::increaseUsage($this->getUserDetail('adminid'), 'diskspace_used', '', (int) $diskspace); + Admins::increaseUsage($this->getUserDetail('adminid'), 'diskspace_used', '', (int)$diskspace); } // update last guid @@ -641,17 +586,17 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource Settings::Set('system.lastaccountnumber', $accountnumber, true); } - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] added customer '" . $loginname . "'"); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] added customer '" . $loginname . "'"); unset($ins_data); // insert task to create homedir etc. - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_HOME, $loginname, $guid, $guid, $store_defaultindex); + Cronjob::inserttask(TaskId::CREATE_HOME, $loginname, $guid, $guid, $store_defaultindex); // Using filesystem - quota, insert a task which cleans the filesystem - quota - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_QUOTA); + Cronjob::inserttask(TaskId::CREATE_QUOTA); // Add htpasswd for the stats-pages - $htpasswdPassword = \Froxlor\System\Crypt::makeCryptPassword($password, true); + $htpasswdPassword = Crypt::makeCryptPassword($password, true); $ins_stmt = Database::prepare(" INSERT INTO `" . TABLE_PANEL_HTPASSWDS . "` SET @@ -660,31 +605,31 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource `password` = :passwd, `path` = :path "); - $ins_data = array( + $ins_data = [ 'customerid' => $customerid, 'username' => $loginname, 'passwd' => $htpasswdPassword - ); + ]; $stats_folder = 'webalizer'; if (Settings::Get('system.awstats_enabled') == '1') { $stats_folder = 'awstats'; } - $ins_data['path'] = \Froxlor\FileDir::makeCorrectDir($documentroot . '/' . $stats_folder . '/'); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] automatically added " . $stats_folder . " htpasswd for user '" . $loginname . "'"); + $ins_data['path'] = FileDir::makeCorrectDir($documentroot . '/' . $stats_folder . '/'); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] automatically added " . $stats_folder . " htpasswd for user '" . $loginname . "'"); Database::pexecute($ins_stmt, $ins_data, true, true); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + Cronjob::inserttask(TaskId::REBUILD_VHOST); // add default FTP-User // also, add froxlor-local user to ftp-group (if exists!) to // allow access to customer-directories from within the panel, which // is necessary when pathedit = Dropdown - $local_users = array( + $local_users = [ Settings::Get('system.httpuser') - ); - if ((int) Settings::Get('system.mod_fcgid_ownvhost') == 1 || (int) Settings::Get('phpfpm.enabled_ownvhost') == 1) { - if ((int) Settings::Get('system.mod_fcgid') == 1) { + ]; + if ((int)Settings::Get('system.mod_fcgid_ownvhost') == 1 || (int)Settings::Get('phpfpm.enabled_ownvhost') == 1) { + if ((int)Settings::Get('system.mod_fcgid') == 1) { $local_user = Settings::Get('system.mod_fcgid_httpuser'); } else { $local_user = Settings::Get('phpfpm.vhost_httpuser'); @@ -695,7 +640,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $local_users[] = $local_user; } } - $this->apiCall('Ftps.add', array( + $this->apiCall('Ftps.add', [ 'customerid' => $customerid, 'path' => '/', 'ftp_password' => $password, @@ -704,7 +649,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource 'ftp_username' => $loginname, 'additional_members' => $local_users, 'is_defaultuser' => 1 - )); + ]); $_stdsubdomain = ''; if ($createstdsubdomain == '1') { @@ -714,37 +659,36 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $_stdsubdomain = $loginname . '.' . Settings::Get('system.hostname'); } - $ins_data = array( + $ins_data = [ 'domain' => $_stdsubdomain, 'customerid' => $customerid, 'adminid' => $this->getUserDetail('adminid'), 'docroot' => $documentroot, 'phpenabled' => $phpenabled, 'openbasedir' => '1' - ); - $domainid = - 1; + ]; + $domainid = -1; try { $std_domain = $this->apiCall('Domains.add', $ins_data); $domainid = $std_domain['id']; - } catch (\Exception $e) { - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_ERR, "[API] Unable to add standard-subdomain: " . $e->getMessage()); + } catch (Exception $e) { + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_ERR, "[API] Unable to add standard-subdomain: " . $e->getMessage()); } if ($domainid > 0) { $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `standardsubdomain` = :domainid WHERE `customerid` = :customerid "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'domainid' => $domainid, 'customerid' => $customerid - ), true, true); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] automatically added standardsubdomain for user '" . $loginname . "'"); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + ], true, true); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] automatically added standardsubdomain for user '" . $loginname . "'"); + Cronjob::inserttask(TaskId::REBUILD_VHOST); } } if ($sendpassword == '1') { - $srv_hostname = Settings::Get('system.hostname'); if (Settings::Get('system.froxlordirectlyviahostname') == '0') { $srv_hostname .= '/' . basename(\Froxlor\Froxlor::getInstallDir()); @@ -756,19 +700,19 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource "); $default_ips = Settings::Get('system.defaultip'); $default_ips = explode(',', $default_ips); - $srv_ip = Database::pexecute_first($srv_ip_stmt, array( + $srv_ip = Database::pexecute_first($srv_ip_stmt, [ 'defaultip' => reset($default_ips) - ), true, true); + ], true, true); - $replace_arr = array( + $replace_arr = [ 'FIRSTNAME' => $firstname, 'NAME' => $name, 'COMPANY' => $company, - 'SALUTATION' => \Froxlor\User::getCorrectUserSalutation(array( + 'SALUTATION' => User::getCorrectUserSalutation([ 'firstname' => $firstname, 'name' => $name, 'company' => $company - )), + ]), 'CUSTOMER_NO' => $customernumber, 'USERNAME' => $loginname, 'PASSWORD' => $password, @@ -776,18 +720,18 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource 'SERVER_IP' => isset($srv_ip['ip']) ? $srv_ip['ip'] : '', 'SERVER_PORT' => isset($srv_ip['port']) ? $srv_ip['port'] : '', 'DOMAINNAME' => $_stdsubdomain - ); + ]; // get template for mail subject - $mail_subject = $this->getMailTemplate(array( + $mail_subject = $this->getMailTemplate([ 'adminid' => $this->getUserDetail('adminid'), 'def_language' => $def_language - ), 'mails', 'createcustomer_subject', $replace_arr, $this->lng['mails']['createcustomer']['subject']); + ], 'mails', 'createcustomer_subject', $replace_arr, $this->lng['mails']['createcustomer']['subject']); // get template for mail body - $mail_body = $this->getMailTemplate(array( + $mail_body = $this->getMailTemplate([ 'adminid' => $this->getUserDetail('adminid'), 'def_language' => $def_language - ), 'mails', 'createcustomer_mailbody', $replace_arr, $this->lng['mails']['createcustomer']['mailbody']); + ], 'mails', 'createcustomer_mailbody', $replace_arr, $this->lng['mails']['createcustomer']['mailbody']); $_mailerror = false; $mailerr_msg = ""; @@ -795,143 +739,255 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $this->mailer()->Subject = $mail_subject; $this->mailer()->AltBody = $mail_body; $this->mailer()->msgHTML(str_replace("\n", "
", $mail_body)); - $this->mailer()->addAddress($email, \Froxlor\User::getCorrectUserSalutation(array( + $this->mailer()->addAddress($email, User::getCorrectUserSalutation([ 'firstname' => $firstname, 'name' => $name, 'company' => $company - ))); + ])); $this->mailer()->send(); } 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) { - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg); - \Froxlor\UI\Response::standard_error('errorsendingmail', $email, true); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg); + Response::standardError('errorsendingmail', $email, true); } $this->mailer()->clearAddresses(); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] automatically sent password to user '" . $loginname . "'"); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] automatically sent password to user '" . $loginname . "'"); } } - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added customer '" . $loginname . "'"); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added customer '" . $loginname . "'"); - $result = $this->apiCall('Customers.get', array( + $result = $this->apiCall('Customers.get', [ 'loginname' => $loginname - )); + ]); return $this->response($result); } - throw new \Exception("No more resources available", 406); + throw new Exception("No more resources available", 406); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); + } + + /** + * return a customer entry by either id or loginname + * + * @param int $id + * optional, the customer-id + * @param string $loginname + * optional, the loginname + * @param bool $show_usages + * optional, default false + * + * @access admin, customer + * @return string json-encoded array + * @throws Exception + */ + public function get() + { + $id = $this->getParam('id', true, 0); + $ln_optional = $id > 0; + $loginname = $this->getParam('loginname', $ln_optional, ''); + $show_usages = $this->getBoolParam('show_usages', true, false); + + if ($this->isAdmin()) { + $result_stmt = Database::prepare(" + SELECT `c`.*, `a`.`loginname` AS `adminname` + FROM `" . TABLE_PANEL_CUSTOMERS . "` `c`, `" . TABLE_PANEL_ADMINS . "` `a` + WHERE " . ($id > 0 ? "`c`.`customerid` = :idln" : "`c`.`loginname` = :idln") . ($this->getUserDetail('customers_see_all') ? '' : " AND `c`.`adminid` = :adminid") . " AND `c`.`adminid` = `a`.`adminid`"); + $params = [ + 'idln' => ($id <= 0 ? $loginname : $id) + ]; + if ($this->getUserDetail('customers_see_all') == '0') { + $params['adminid'] = $this->getUserDetail('adminid'); + } + } else { + if (($id > 0 && $id != $this->getUserDetail('customerid')) || !empty($loginname) && $loginname != $this->getUserDetail('loginname')) { + throw new Exception("You cannot access data of other customers", 401); + } + $result_stmt = Database::prepare(" + SELECT * FROM `" . TABLE_PANEL_CUSTOMERS . "` + WHERE " . ($id > 0 ? "`customerid` = :idln" : "`loginname` = :idln")); + $params = [ + 'idln' => ($id <= 0 ? $loginname : $id) + ]; + } + $result = Database::pexecute_first($result_stmt, $params, true, true); + if ($result) { + // check whether the admin does not want the customer to see the notes + if (!$this->isAdmin() && $result['custom_notes_show'] != 1) { + $result['custom_notes'] = ""; + } + if ($show_usages) { + // get number of domains + $domains_stmt = Database::prepare(" + SELECT COUNT(`id`) AS `domains` + FROM `" . TABLE_PANEL_DOMAINS . "` + WHERE `customerid` = :cid + AND `parentdomainid` = '0' + AND `id`<> :stdd + "); + Database::pexecute($domains_stmt, [ + 'cid' => $result['customerid'], + 'stdd' => $result['standardsubdomain'] + ]); + $domains = $domains_stmt->fetch(PDO::FETCH_ASSOC); + $result['domains'] = intval($domains['domains']); + // get disk-space usages for web, mysql and mail + $usages_stmt = Database::prepare(" + SELECT * FROM `" . TABLE_PANEL_DISKSPACE . "` + WHERE `customerid` = :cid + ORDER BY `stamp` DESC LIMIT 1 + "); + $usages = Database::pexecute_first($usages_stmt, [ + 'cid' => $result['customerid'] + ]); + if ($usages) { + $result['webspace_used'] = $usages['webspace']; + $result['mailspace_used'] = $usages['mail']; + $result['dbspace_used'] = $usages['mysql']; + } else { + $result['webspace_used'] = 0; + $result['mailspace_used'] = 0; + $result['dbspace_used'] = 0; + } + } + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get customer '" . $result['loginname'] . "'"); + return $this->response($result); + } + $key = ($id > 0 ? "id #" . $id : "loginname '" . $loginname . "'"); + throw new Exception("Customer with " . $key . " could not be found", 404); + } + + /** + * increase resource-usage + * + * @param int $customerid + * @param string $resource + * @param string $extra + * optional, default empty + * @param int $increase_by + * optional, default 1 + */ + public static function increaseUsage($customerid = 0, $resource = null, $extra = '', $increase_by = 1) + { + self::updateResourceUsage(TABLE_PANEL_CUSTOMERS, 'customerid', $customerid, '+', $resource, $extra, $increase_by); } /** * update customer entry by either id or loginname, customer can only change language, password and theme * * @param int $id - * optional, the customer-id + * optional, the customer-id * @param string $loginname - * optional, the loginname + * optional, the loginname * @param string $email * @param string $name - * optional if company is set, else required + * optional if company is set, else required * @param string $firstname - * optional if company is set, else required + * optional if company is set, else required * @param string $company - * optional but required if name/firstname empty + * optional but required if name/firstname empty * @param string $street - * optional + * optional * @param string $zipcode - * optional + * optional * @param string $city - * optional + * optional * @param string $phone - * optional + * optional * @param string $fax - * optional + * optional * @param int $customernumber - * optional - * @param string $def_language, - * optional, default is system-default language + * optional + * @param string $def_language , + * optional, default is system-default language * @param bool $api_allowed - * optional, default is true if system setting api.enabled is true, else false + * optional, default is true if system setting api.enabled is true, else false * @param int $gender - * optional, 0 = no-gender, 1 = male, 2 = female + * optional, 0 = no-gender, 1 = male, 2 = female * @param string $custom_notes - * optional notes + * optional notes * @param bool $custom_notes_show - * optional, whether to show the content of custom_notes to the customer, default 0 (false) + * optional, whether to show the content of custom_notes to the customer, default 0 + * (false) * @param string $new_customer_password - * optional, iset new password + * optional, iset new password * @param bool $sendpassword - * optional, whether to send the password to the customer after creation, default 0 (false) + * optional, whether to send the password to the customer after creation, default 0 + * (false) * @param int $move_to_admin - * optional, if valid admin-id is given here, the customer's admin/reseller can be changed + * optional, if valid admin-id is given here, the customer's admin/reseller can be + * changed * @param bool $deactivated - * optional, if 1 (true) the customer can be deactivated/suspended + * optional, if 1 (true) the customer can be deactivated/suspended * @param int $diskspace - * optional disk-space available for customer in MB, default 0 + * optional disk-space available for customer in MB, default 0 * @param bool $diskspace_ul - * optional, whether customer should have unlimited diskspace, default 0 (false) + * optional, whether customer should have unlimited diskspace, default 0 (false) * @param int $traffic - * optional traffic available for customer in GB, default 0 + * optional traffic available for customer in GB, default 0 * @param bool $traffic_ul - * optional, whether customer should have unlimited traffic, default 0 (false) + * optional, whether customer should have unlimited traffic, default 0 (false) * @param int $subdomains - * optional amount of subdomains available for customer, default 0 + * optional amount of subdomains available for customer, default 0 * @param bool $subdomains_ul - * optional, whether customer should have unlimited subdomains, default 0 (false) + * optional, whether customer should have unlimited subdomains, default 0 (false) * @param int $emails - * optional amount of emails available for customer, default 0 + * optional amount of emails available for customer, default 0 * @param bool $emails_ul - * optional, whether customer should have unlimited emails, default 0 (false) + * optional, whether customer should have unlimited emails, default 0 (false) * @param int $email_accounts - * optional amount of email-accounts available for customer, default 0 + * optional amount of email-accounts available for customer, default 0 * @param bool $email_accounts_ul - * optional, whether customer should have unlimited email-accounts, default 0 (false) + * optional, whether customer should have unlimited email-accounts, default 0 (false) * @param int $email_forwarders - * optional amount of email-forwarders available for customer, default 0 + * optional amount of email-forwarders available for customer, default 0 * @param bool $email_forwarders_ul - * optional, whether customer should have unlimited email-forwarders, default 0 (false) + * optional, whether customer should have unlimited email-forwarders, default 0 (false) * @param int $email_quota - * optional size of email-quota available for customer in MB, default is system-setting mail_quota + * optional size of email-quota available for customer in MB, default is system-setting + * mail_quota * @param bool $email_quota_ul - * optional, whether customer should have unlimited email-quota, default 0 (false) + * optional, whether customer should have unlimited email-quota, default 0 (false) * @param bool $email_imap - * optional, whether to allow IMAP access, default 0 (false) + * optional, whether to allow IMAP access, default 0 (false) * @param bool $email_pop3 - * optional, whether to allow POP3 access, default 0 (false) + * optional, whether to allow POP3 access, default 0 (false) * @param int $ftps - * optional amount of ftp-accounts available for customer, default 0 + * optional amount of ftp-accounts available for customer, default 0 * @param bool $ftps_ul - * optional, whether customer should have unlimited ftp-accounts, default 0 (false) + * optional, whether customer should have unlimited ftp-accounts, default 0 (false) * @param int $mysqls - * optional amount of mysql-databases available for customer, default 0 + * optional amount of mysql-databases available for customer, default 0 * @param bool $mysqls_ul - * optional, whether customer should have unlimited mysql-databases, default 0 (false) + * optional, whether customer should have unlimited mysql-databases, default 0 (false) * @param bool $createstdsubdomain - * optional, whether to create a standard-subdomain ([loginname].froxlor-hostname.tld), default 1 (if customer has std-subdomain) else 0 (false) + * optional, whether to create a standard-subdomain ([loginname].froxlor-hostname.tld), + * default 1 (if customer has std-subdomain) else 0 (false) * @param bool $phpenabled - * optional, whether to allow usage of PHP, default 0 (false) + * optional, whether to allow usage of PHP, default 0 (false) * @param array $allowed_phpconfigs - * optional, array of IDs of php-config that the customer is allowed to use, default empty (none) + * optional, array of IDs of php-config that the customer is allowed to use, default + * empty (none) * @param bool $perlenabled - * optional, whether to allow usage of Perl/CGI, default 0 (false) + * optional, whether to allow usage of Perl/CGI, default 0 (false) * @param bool $dnsenabled - * optional, whether to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false) + * optional, whether to allow usage of the DNS editor (requires activated nameserver in + * settings), default 0 (false) * @param bool $logviewenabled - * optional, whether to allow access to webserver access/error-logs, default 0 (false) + * optional, whether to allow access to webserver access/error-logs, default 0 (false) * @param string $theme - * optional, change theme + * optional, change theme * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function update() { @@ -939,21 +995,21 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $ln_optional = $id > 0; $loginname = $this->getParam('loginname', $ln_optional, ''); - $result = $this->apiCall('Customers.get', array( + $result = $this->apiCall('Customers.get', [ 'id' => $id, 'loginname' => $loginname - )); + ]); $id = $result['customerid']; if ($this->isAdmin()) { // parameters - $move_to_admin = (int) ($this->getParam('move_to_admin', true, 0)); + $move_to_admin = (int)($this->getParam('move_to_admin', true, 0)); - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); + $idna_convert = new IdnaWrapper(); $email = $this->getParam('email', true, $idna_convert->decode($result['email'])); $name = $this->getParam('name', true, $result['name']); $firstname = $this->getParam('firstname', true, $result['firstname']); - $company_required = empty($result['company']) && ((! empty($name) && empty($firstname)) || (empty($name) && ! empty($firstname)) || (empty($name) && empty($firstname))); + $company_required = empty($result['company']) && ((!empty($name) && empty($firstname)) || (empty($name) && !empty($firstname)) || (empty($name) && empty($firstname))); $company = $this->getParam('company', !$company_required, $result['company']); $street = $this->getParam('street', true, $result['street']); $zipcode = $this->getParam('zipcode', true, $result['zipcode']); @@ -963,7 +1019,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $customernumber = $this->getParam('customernumber', true, $result['customernumber']); $def_language = $this->getParam('def_language', true, $result['def_language']); $api_allowed = $this->getBoolParam('api_allowed', true, $result['api_allowed']); - $gender = (int) $this->getParam('gender', true, $result['gender']); + $gender = (int)$this->getParam('gender', true, $result['gender']); $custom_notes = $this->getParam('custom_notes', true, $result['custom_notes']); $custom_notes_show = $this->getBoolParam('custom_notes_show', true, $result['custom_notes_show']); @@ -997,27 +1053,27 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource // validation if ($this->isAdmin()) { - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); - $name = \Froxlor\Validate\Validate::validate($name, 'name', '', '', array(), true); - $firstname = \Froxlor\Validate\Validate::validate($firstname, 'first name', '', '', array(), true); - $company = \Froxlor\Validate\Validate::validate($company, 'company', '', '', array(), true); - $street = \Froxlor\Validate\Validate::validate($street, 'street', '', '', array(), true); - $zipcode = \Froxlor\Validate\Validate::validate($zipcode, 'zipcode', '/^[0-9 \-A-Z]*$/', '', array(), true); - $city = \Froxlor\Validate\Validate::validate($city, 'city', '', '', array(), true); - $phone = \Froxlor\Validate\Validate::validate($phone, 'phone', '/^[0-9\- \+\(\)\/]*$/', '', array(), true); - $fax = \Froxlor\Validate\Validate::validate($fax, 'fax', '/^[0-9\- \+\(\)\/]*$/', '', array(), true); - $email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true)); - $customernumber = \Froxlor\Validate\Validate::validate($customernumber, 'customer number', '/^[A-Za-z0-9 \-]*$/Di', '', array(), true); - $custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true); - if (! empty($allowed_phpconfigs)) { + $idna_convert = new IdnaWrapper(); + $name = Validate::validate($name, 'name', '', '', [], true); + $firstname = Validate::validate($firstname, 'first name', '', '', [], true); + $company = Validate::validate($company, 'company', '', '', [], true); + $street = Validate::validate($street, 'street', '', '', [], true); + $zipcode = Validate::validate($zipcode, 'zipcode', '/^[0-9 \-A-Z]*$/', '', [], true); + $city = Validate::validate($city, 'city', '', '', [], true); + $phone = Validate::validate($phone, 'phone', '/^[0-9\- \+\(\)\/]*$/', '', [], true); + $fax = Validate::validate($fax, 'fax', '/^[0-9\- \+\(\)\/]*$/', '', [], true); + $email = $idna_convert->encode(Validate::validate($email, 'email', '', '', [], true)); + $customernumber = Validate::validate($customernumber, 'customer number', '/^[A-Za-z0-9 \-]*$/Di', '', [], true); + $custom_notes = Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', Validate::REGEX_CONF_TEXT, '', [], true); + if (!empty($allowed_phpconfigs)) { $allowed_phpconfigs = array_map('intval', $allowed_phpconfigs); } } - $def_language = \Froxlor\Validate\Validate::validate($def_language, 'default language', '', '', array(), true); - $theme = \Froxlor\Validate\Validate::validate($theme, 'theme', '', '', array(), true); + $def_language = Validate::validate($def_language, 'default language', '', '', [], true); + $theme = Validate::validate($theme, 'theme', '', '', [], true); if (Settings::Get('system.mail_quota_enabled') != '1') { - $email_quota = - 1; + $email_quota = -1; } if (empty($theme)) { @@ -1025,27 +1081,26 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource } if ($this->isAdmin()) { - $diskspace = $diskspace * 1024; $traffic = $traffic * 1024 * 1024; if (((($this->getUserDetail('diskspace_used') + $diskspace - $result['diskspace']) > $this->getUserDetail('diskspace')) && ($this->getUserDetail('diskspace') / 1024) != '-1') || ((($this->getUserDetail('mysqls_used') + $mysqls - $result['mysqls']) > $this->getUserDetail('mysqls')) && $this->getUserDetail('mysqls') != '-1') || ((($this->getUserDetail('emails_used') + $emails - $result['emails']) > $this->getUserDetail('emails')) && $this->getUserDetail('emails') != '-1') || ((($this->getUserDetail('email_accounts_used') + $email_accounts - $result['email_accounts']) > $this->getUserDetail('email_accounts')) && $this->getUserDetail('email_accounts') != '-1') || ((($this->getUserDetail('email_forwarders_used') + $email_forwarders - $result['email_forwarders']) > $this->getUserDetail('email_forwarders')) && $this->getUserDetail('email_forwarders') != '-1') || ((($this->getUserDetail('email_quota_used') + $email_quota - $result['email_quota']) > $this->getUserDetail('email_quota')) && $this->getUserDetail('email_quota') != '-1' && Settings::Get('system.mail_quota_enabled') == '1') || ((($this->getUserDetail('ftps_used') + $ftps - $result['ftps']) > $this->getUserDetail('ftps')) && $this->getUserDetail('ftps') != '-1') || ((($this->getUserDetail('subdomains_used') + $subdomains - $result['subdomains']) > $this->getUserDetail('subdomains')) && $this->getUserDetail('subdomains') != '-1') || (($diskspace / 1024) == '-1' && ($this->getUserDetail('diskspace') / 1024) != '-1') || ($mysqls == '-1' && $this->getUserDetail('mysqls') != '-1') || ($emails == '-1' && $this->getUserDetail('emails') != '-1') || ($email_accounts == '-1' && $this->getUserDetail('email_accounts') != '-1') || ($email_forwarders == '-1' && $this->getUserDetail('email_forwarders') != '-1') || ($email_quota == '-1' && $this->getUserDetail('email_quota') != '-1' && Settings::Get('system.mail_quota_enabled') == '1') || ($ftps == '-1' && $this->getUserDetail('ftps') != '-1') || ($subdomains == '-1' && $this->getUserDetail('subdomains') != '-1')) { - \Froxlor\UI\Response::standard_error('youcantallocatemorethanyouhave', '', true); + Response::standardError('youcantallocatemorethanyouhave', '', true); } if ($email == '') { - \Froxlor\UI\Response::standard_error(array( + Response::standardError([ 'stringisempty', 'emailadd' - ), '', true); - } elseif (! \Froxlor\Validate\Validate::validateEmail($email)) { - \Froxlor\UI\Response::standard_error('emailiswrong', $email, true); + ], '', true); + } elseif (!Validate::validateEmail($email)) { + Response::standardError('emailiswrong', $email, true); } } if ($password != '') { - $password = \Froxlor\System\Crypt::validatePassword($password, true); - $password = \Froxlor\System\Crypt::makeCryptPassword($password); + $password = Crypt::validatePassword($password, true); + $password = Crypt::makeCryptPassword($password); } else { $password = $result['password']; } @@ -1056,106 +1111,103 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource } if ($createstdsubdomain == '1' && $result['standardsubdomain'] == '0') { - if (Settings::Get('system.stdsubdomain') !== null && Settings::Get('system.stdsubdomain') != '') { $_stdsubdomain = $result['loginname'] . '.' . Settings::Get('system.stdsubdomain'); } else { $_stdsubdomain = $result['loginname'] . '.' . Settings::Get('system.hostname'); } - $ins_data = array( + $ins_data = [ 'domain' => $_stdsubdomain, 'customerid' => $result['customerid'], 'adminid' => $this->getUserDetail('adminid'), 'docroot' => $result['documentroot'], 'phpenabled' => $phpenabled, 'openbasedir' => '1' - ); - $domainid = - 1; + ]; + $domainid = -1; try { $std_domain = $this->apiCall('Domains.add', $ins_data); $domainid = $std_domain['id']; - } catch (\Exception $e) { - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_ERR, "[API] Unable to add standard-subdomain: " . $e->getMessage()); + } catch (Exception $e) { + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_ERR, "[API] Unable to add standard-subdomain: " . $e->getMessage()); } if ($domainid > 0) { $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `standardsubdomain` = :domainid WHERE `customerid` = :customerid "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'domainid' => $domainid, 'customerid' => $result['customerid'] - ), true, true); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] automatically added standardsubdomain for user '" . $result['loginname'] . "'"); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + ], true, true); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] automatically added standardsubdomain for user '" . $result['loginname'] . "'"); + Cronjob::inserttask(TaskId::REBUILD_VHOST); } } if ($createstdsubdomain == '0' && $result['standardsubdomain'] != '0') { try { - $std_domain = $this->apiCall('Domains.delete', array( + $std_domain = $this->apiCall('Domains.delete', [ 'id' => $result['standardsubdomain'], 'is_stdsubdomain' => 1 - )); - } catch (\Exception $e) { - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_ERR, "[API] Unable to delete standard-subdomain: " . $e->getMessage()); + ]); + } catch (Exception $e) { + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_ERR, "[API] Unable to delete standard-subdomain: " . $e->getMessage()); } - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] automatically deleted standardsubdomain for user '" . $result['loginname'] . "'"); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] automatically deleted standardsubdomain for user '" . $result['loginname'] . "'"); + Cronjob::inserttask(TaskId::REBUILD_VHOST); } if ($phpenabled != $result['phpenabled'] || $perlenabled != $result['perlenabled'] || $email != $result['email']) { - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + Cronjob::inserttask(TaskId::REBUILD_VHOST); } // activate/deactivate customer services if ($deactivated != $result['deactivated']) { - $yesno = ($deactivated ? 'N' : 'Y'); - $pop3 = ($deactivated ? '0' : (int) $result['pop3']); - $imap = ($deactivated ? '0' : (int) $result['imap']); + $pop3 = ($deactivated ? '0' : (int)$result['pop3']); + $imap = ($deactivated ? '0' : (int)$result['imap']); $upd_stmt = Database::prepare(" UPDATE `" . TABLE_MAIL_USERS . "` SET `postfix`= :yesno, `pop3` = :pop3, `imap` = :imap WHERE `customerid` = :customerid "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'yesno' => $yesno, 'pop3' => $pop3, 'imap' => $imap, 'customerid' => $id - )); + ]); $upd_stmt = Database::prepare(" UPDATE `" . TABLE_FTP_USERS . "` SET `login_enabled` = :yesno WHERE `customerid` = :customerid "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'yesno' => $yesno, 'customerid' => $id - )); + ]); $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `deactivated`= :deactivated WHERE `customerid` = :customerid"); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'deactivated' => $deactivated, 'customerid' => $id - )); + ]); // Retrieve customer's databases $databases_stmt = Database::prepare("SELECT * FROM " . TABLE_PANEL_DATABASES . " WHERE customerid = :customerid ORDER BY `dbserver`"); - Database::pexecute($databases_stmt, array( + Database::pexecute($databases_stmt, [ 'customerid' => $id - )); + ]); Database::needRoot(true); $last_dbserver = 0; - $dbm = new \Froxlor\Database\DbManager($this->logger()); + $dbm = new DbManager($this->logger()); // For each of them $priv_changed = false; - while ($row_database = $databases_stmt->fetch(\PDO::FETCH_ASSOC)) { - + while ($row_database = $databases_stmt->fetch(PDO::FETCH_ASSOC)) { if ($last_dbserver != $row_database['dbserver']) { $dbm->getManager()->flushPrivileges(); Database::needRoot(true, $row_database['dbserver']); @@ -1184,45 +1236,45 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource Database::needRoot(false); // reactivate/deactivate api-keys - $valid_until = $deactivated ? 0 : - 1; + $valid_until = $deactivated ? 0 : -1; $stmt = Database::prepare("UPDATE `" . TABLE_API_KEYS . "` SET `valid_until` = :vu WHERE `customerid` = :id"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ 'id' => $id, 'vu' => $valid_until - ), true, true); + ], true, true); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] " . ($deactivated ? 'deactivated' : 'reactivated') . " user '" . $result['loginname'] . "'"); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] " . ($deactivated ? 'deactivated' : 'reactivated') . " user '" . $result['loginname'] . "'"); + Cronjob::inserttask(TaskId::REBUILD_VHOST); } // Disable or enable POP3 Login for customers Mail Accounts if ($email_pop3 != $result['pop3']) { $upd_stmt = Database::prepare("UPDATE `" . TABLE_MAIL_USERS . "` SET `pop3` = :pop3 WHERE `customerid` = :customerid"); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'pop3' => $email_pop3, 'customerid' => $id - )); + ]); } // Disable or enable IMAP Login for customers Mail Accounts if ($email_imap != $result['imap']) { $upd_stmt = Database::prepare("UPDATE `" . TABLE_MAIL_USERS . "` SET `imap` = :imap WHERE `customerid` = :customerid"); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'imap' => $email_imap, 'customerid' => $id - )); + ]); } } - $upd_data = array( + $upd_data = [ 'customerid' => $id, 'passwd' => $password, 'lang' => $def_language, 'theme' => $theme - ); + ]; if ($this->isAdmin()) { - $admin_upd_data = array( + $admin_upd_data = [ 'name' => $name, 'firstname' => $firstname, 'gender' => $gender, @@ -1254,7 +1306,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource 'custom_notes' => $custom_notes, 'custom_notes_show' => $custom_notes_show, 'api_allowed' => $api_allowed - ); + ]; $upd_data = $upd_data + $admin_upd_data; } @@ -1304,7 +1356,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource if ($this->isAdmin()) { // Using filesystem - quota, insert a task which cleans the filesystem - quota - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_QUOTA); + Cronjob::inserttask(TaskId::CREATE_QUOTA); $admin_update_query = "UPDATE `" . TABLE_PANEL_ADMINS . "` SET `customers_used` = `customers_used` "; @@ -1312,10 +1364,10 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $admin_update_query .= ", `mysqls_used` = `mysqls_used` "; if ($mysqls != '-1') { - $admin_update_query .= " + 0" . (int) $mysqls . " "; + $admin_update_query .= " + 0" . (int)$mysqls . " "; } if ($result['mysqls'] != '-1') { - $admin_update_query .= " - 0" . (int) $result['mysqls'] . " "; + $admin_update_query .= " - 0" . (int)$result['mysqls'] . " "; } } @@ -1323,10 +1375,10 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $admin_update_query .= ", `emails_used` = `emails_used` "; if ($emails != '-1') { - $admin_update_query .= " + 0" . (int) $emails . " "; + $admin_update_query .= " + 0" . (int)$emails . " "; } if ($result['emails'] != '-1') { - $admin_update_query .= " - 0" . (int) $result['emails'] . " "; + $admin_update_query .= " - 0" . (int)$result['emails'] . " "; } } @@ -1334,10 +1386,10 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $admin_update_query .= ", `email_accounts_used` = `email_accounts_used` "; if ($email_accounts != '-1') { - $admin_update_query .= " + 0" . (int) $email_accounts . " "; + $admin_update_query .= " + 0" . (int)$email_accounts . " "; } if ($result['email_accounts'] != '-1') { - $admin_update_query .= " - 0" . (int) $result['email_accounts'] . " "; + $admin_update_query .= " - 0" . (int)$result['email_accounts'] . " "; } } @@ -1345,10 +1397,10 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $admin_update_query .= ", `email_forwarders_used` = `email_forwarders_used` "; if ($email_forwarders != '-1') { - $admin_update_query .= " + 0" . (int) $email_forwarders . " "; + $admin_update_query .= " + 0" . (int)$email_forwarders . " "; } if ($result['email_forwarders'] != '-1') { - $admin_update_query .= " - 0" . (int) $result['email_forwarders'] . " "; + $admin_update_query .= " - 0" . (int)$result['email_forwarders'] . " "; } } @@ -1356,10 +1408,10 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $admin_update_query .= ", `email_quota_used` = `email_quota_used` "; if ($email_quota != '-1') { - $admin_update_query .= " + 0" . (int) $email_quota . " "; + $admin_update_query .= " + 0" . (int)$email_quota . " "; } if ($result['email_quota'] != '-1') { - $admin_update_query .= " - 0" . (int) $result['email_quota'] . " "; + $admin_update_query .= " - 0" . (int)$result['email_quota'] . " "; } } @@ -1367,10 +1419,10 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $admin_update_query .= ", `subdomains_used` = `subdomains_used` "; if ($subdomains != '-1') { - $admin_update_query .= " + 0" . (int) $subdomains . " "; + $admin_update_query .= " + 0" . (int)$subdomains . " "; } if ($result['subdomains'] != '-1') { - $admin_update_query .= " - 0" . (int) $result['subdomains'] . " "; + $admin_update_query .= " - 0" . (int)$result['subdomains'] . " "; } } @@ -1378,10 +1430,10 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $admin_update_query .= ", `ftps_used` = `ftps_used` "; if ($ftps != '-1') { - $admin_update_query .= " + 0" . (int) $ftps . " "; + $admin_update_query .= " + 0" . (int)$ftps . " "; } if ($result['ftps'] != '-1') { - $admin_update_query .= " - 0" . (int) $result['ftps'] . " "; + $admin_update_query .= " - 0" . (int)$result['ftps'] . " "; } } @@ -1389,37 +1441,37 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $admin_update_query .= ", `diskspace_used` = `diskspace_used` "; if (($diskspace / 1024) != '-1') { - $admin_update_query .= " + 0" . (int) $diskspace . " "; + $admin_update_query .= " + 0" . (int)$diskspace . " "; } if (($result['diskspace'] / 1024) != '-1') { - $admin_update_query .= " - 0" . (int) $result['diskspace'] . " "; + $admin_update_query .= " - 0" . (int)$result['diskspace'] . " "; } } - $admin_update_query .= " WHERE `adminid` = '" . (int) $result['adminid'] . "'"; + $admin_update_query .= " WHERE `adminid` = '" . (int)$result['adminid'] . "'"; Database::query($admin_update_query); } - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] edited user '" . $result['loginname'] . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] edited user '" . $result['loginname'] . "'"); /* * move customer to another admin/reseller; #1166 */ if ($this->isAdmin()) { if ($move_to_admin > 0 && $move_to_admin != $result['adminid']) { - $move_result = $this->apiCall('Customers.move', array( + $move_result = $this->apiCall('Customers.move', [ 'id' => $result['customerid'], 'adminid' => $move_to_admin - )); + ]); if ($move_result != true) { - \Froxlor\UI\Response::standard_error('moveofcustomerfailed', $move_result, true); + Response::standardError('moveofcustomerfailed', $move_result, true); } } } - $result = $this->apiCall('Customers.get', array( + $result = $this->apiCall('Customers.get', [ 'id' => $result['customerid'] - )); + ]); return $this->response($result); } @@ -1427,15 +1479,15 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource * delete a customer entry by either id or loginname * * @param int $id - * optional, the customer-id + * optional, the customer-id * @param string $loginname - * optional, the loginname + * optional, the loginname * @param bool $delete_userfiles - * optional, default false + * optional, default false * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function delete() { @@ -1445,26 +1497,26 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $loginname = $this->getParam('loginname', $ln_optional, ''); $delete_userfiles = $this->getParam('delete_userfiles', true, 0); - $result = $this->apiCall('Customers.get', array( + $result = $this->apiCall('Customers.get', [ 'id' => $id, 'loginname' => $loginname - )); + ]); $id = $result['customerid']; $databases_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_DATABASES . "` WHERE `customerid` = :id ORDER BY `dbserver` "); - Database::pexecute($databases_stmt, array( + Database::pexecute($databases_stmt, [ 'id' => $id - )); + ]); Database::needRoot(true); $last_dbserver = 0; - $dbm = new \Froxlor\Database\DbManager($this->logger()); + $dbm = new DbManager($this->logger()); $priv_changed = false; - while ($row_database = $databases_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row_database = $databases_stmt->fetch(PDO::FETCH_ASSOC)) { if ($last_dbserver != $row_database['dbserver']) { Database::needRoot(true, $row_database['dbserver']); $dbm->getManager()->flushPrivileges(); @@ -1480,115 +1532,115 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource // delete customer itself $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `customerid` = :id"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ 'id' => $id - ), true, true); + ], true, true); // delete customer databases $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DATABASES . "` WHERE `customerid` = :id"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ 'id' => $id - ), true, true); + ], true, true); // first gather all domain-id's to clean up panel_domaintoip, dns-entries and certificates accordingly $did_stmt = Database::prepare("SELECT `id`, `domain` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :id"); - Database::pexecute($did_stmt, array( + Database::pexecute($did_stmt, [ 'id' => $id - ), true, true); - while ($row = $did_stmt->fetch(\PDO::FETCH_ASSOC)) { + ], true, true); + while ($row = $did_stmt->fetch(PDO::FETCH_ASSOC)) { // remove domain->ip connection $stmt = Database::prepare("DELETE FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :did"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ 'did' => $row['id'] - ), true, true); + ], true, true); // remove domain->dns entries $stmt = Database::prepare("DELETE FROM `" . TABLE_DOMAIN_DNS . "` WHERE `domain_id` = :did"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ 'did' => $row['id'] - ), true, true); + ], true, true); // remove domain->certificates entries $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :did"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ 'did' => $row['id'] - ), true, true); + ], true, true); // remove domains DNS from powerDNS if used, #581 - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_PDNS, $row['domain']); + Cronjob::inserttask(TaskId::DELETE_DOMAIN_PDNS, $row['domain']); // remove domain from acme.sh / lets encrypt if used - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_SSL, $row['domain']); + Cronjob::inserttask(TaskId::DELETE_DOMAIN_SSL, $row['domain']); } // remove customer domains $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :id"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ 'id' => $id - ), true, true); + ], true, true); $domains_deleted = $stmt->rowCount(); // delete htpasswds $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_HTPASSWDS . "` WHERE `customerid` = :id"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ 'id' => $id - ), true, true); + ], true, true); // delete htaccess options $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_HTACCESS . "` WHERE `customerid` = :id"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ 'id' => $id - ), true, true); + ], true, true); // delete traffic information $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_TRAFFIC . "` WHERE `customerid` = :id"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ 'id' => $id - ), true, true); + ], true, true); // remove diskspace analysis $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DISKSPACE . "` WHERE `customerid` = :id"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ 'id' => $id - ), true, true); + ], true, true); // delete mail-accounts $stmt = Database::prepare("DELETE FROM `" . TABLE_MAIL_USERS . "` WHERE `customerid` = :id"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ 'id' => $id - ), true, true); + ], true, true); // delete mail-addresses $stmt = Database::prepare("DELETE FROM `" . TABLE_MAIL_VIRTUAL . "` WHERE `customerid` = :id"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ 'id' => $id - ), true, true); + ], true, true); // gather ftp-user names $result2_stmt = Database::prepare("SELECT `username` FROM `" . TABLE_FTP_USERS . "` WHERE `customerid` = :id"); - Database::pexecute($result2_stmt, array( + Database::pexecute($result2_stmt, [ 'id' => $id - ), true, true); - while ($row = $result2_stmt->fetch(\PDO::FETCH_ASSOC)) { + ], true, true); + while ($row = $result2_stmt->fetch(PDO::FETCH_ASSOC)) { // delete ftp-quotatallies by username $stmt = Database::prepare("DELETE FROM `" . TABLE_FTP_QUOTATALLIES . "` WHERE `name` = :name"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ 'name' => $row['username'] - ), true, true); + ], true, true); } // remove ftp-group $stmt = Database::prepare("DELETE FROM `" . TABLE_FTP_GROUPS . "` WHERE `customerid` = :id"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ 'id' => $id - ), true, true); + ], true, true); // remove ftp-users $stmt = Database::prepare("DELETE FROM `" . TABLE_FTP_USERS . "` WHERE `customerid` = :id"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ 'id' => $id - ), true, true); + ], true, true); // remove api-keys $stmt = Database::prepare("DELETE FROM `" . TABLE_API_KEYS . "` WHERE `customerid` = :id"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ 'id' => $id - ), true, true); + ], true, true); // Delete all waiting "create user" -tasks for this user, #276 // Note: the WHERE selects part of a serialized array, but it should be safe this way @@ -1596,77 +1648,92 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource DELETE FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = '2' AND `data` LIKE :loginname "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'loginname' => "%:{$result['loginname']};%" - ), true, true); + ], true, true); // update admin-resource-usage Admins::decreaseUsage($this->getUserDetail('adminid'), 'customers_used'); - Admins::decreaseUsage($this->getUserDetail('adminid'), 'domains_used', '', (int) ($domains_deleted - $result['subdomains_used'])); + Admins::decreaseUsage($this->getUserDetail('adminid'), 'domains_used', '', (int)($domains_deleted - $result['subdomains_used'])); if ($result['mysqls'] != '-1') { - Admins::decreaseUsage($this->getUserDetail('adminid'), 'mysqls_used', '', (int) $result['mysqls']); + Admins::decreaseUsage($this->getUserDetail('adminid'), 'mysqls_used', '', (int)$result['mysqls']); } if ($result['emails'] != '-1') { - Admins::decreaseUsage($this->getUserDetail('adminid'), 'emails_used', '', (int) $result['emails']); + Admins::decreaseUsage($this->getUserDetail('adminid'), 'emails_used', '', (int)$result['emails']); } if ($result['email_accounts'] != '-1') { - Admins::decreaseUsage($this->getUserDetail('adminid'), 'email_accounts_used', '', (int) $result['email_accounts']); + Admins::decreaseUsage($this->getUserDetail('adminid'), 'email_accounts_used', '', (int)$result['email_accounts']); } if ($result['email_forwarders'] != '-1') { - Admins::decreaseUsage($this->getUserDetail('adminid'), 'email_forwarders_used', '', (int) $result['email_forwarders']); + Admins::decreaseUsage($this->getUserDetail('adminid'), 'email_forwarders_used', '', (int)$result['email_forwarders']); } if ($result['email_quota'] != '-1') { - Admins::decreaseUsage($this->getUserDetail('adminid'), 'email_quota_used', '', (int) $result['email_quota']); + Admins::decreaseUsage($this->getUserDetail('adminid'), 'email_quota_used', '', (int)$result['email_quota']); } if ($result['subdomains'] != '-1') { - Admins::decreaseUsage($this->getUserDetail('adminid'), 'subdomains_used', '', (int) $result['subdomains']); + Admins::decreaseUsage($this->getUserDetail('adminid'), 'subdomains_used', '', (int)$result['subdomains']); } if ($result['ftps'] != '-1') { - Admins::decreaseUsage($this->getUserDetail('adminid'), 'ftps_used', '', (int) $result['ftps']); + Admins::decreaseUsage($this->getUserDetail('adminid'), 'ftps_used', '', (int)$result['ftps']); } if (($result['diskspace'] / 1024) != '-1') { - Admins::decreaseUsage($this->getUserDetail('adminid'), 'diskspace_used', '', (int) $result['diskspace']); + Admins::decreaseUsage($this->getUserDetail('adminid'), 'diskspace_used', '', (int)$result['diskspace']); } // rebuild configs - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + Cronjob::inserttask(TaskId::REBUILD_VHOST); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); + Cronjob::inserttask(TaskId::REBUILD_DNS); if ($delete_userfiles == 1) { // insert task to remove the customers files from the filesystem - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_CUSTOMER_FILES, $result['loginname']); + Cronjob::inserttask(TaskId::DELETE_CUSTOMER_FILES, $result['loginname']); } // Using filesystem - quota, insert a task which cleans the filesystem - quota - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_QUOTA); + Cronjob::inserttask(TaskId::CREATE_QUOTA); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted customer '" . $result['loginname'] . "'"); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted customer '" . $result['loginname'] . "'"); return $this->response($result); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); + } + + /** + * decrease resource-usage + * + * @param int $customerid + * @param string $resource + * @param string $extra + * optional, default empty + * @param int $decrease_by + * optional, default 1 + */ + public static function decreaseUsage($customerid = 0, $resource = null, $extra = '', $decrease_by = 1) + { + self::updateResourceUsage(TABLE_PANEL_CUSTOMERS, 'customerid', $customerid, '-', $resource, $extra, $decrease_by); } /** * unlock a locked customer by either id or loginname * * @param int $id - * optional, the customer-id + * optional, the customer-id * @param string $loginname - * optional, the loginname + * optional, the loginname * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function unlock() { @@ -1675,10 +1742,10 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $ln_optional = $id > 0; $loginname = $this->getParam('loginname', $ln_optional, ''); - $result = $this->apiCall('Customers.get', array( + $result = $this->apiCall('Customers.get', [ 'id' => $id, 'loginname' => $loginname - )); + ]); $id = $result['customerid']; $result_stmt = Database::prepare(" @@ -1686,16 +1753,16 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource `loginfail_count` = '0' WHERE `customerid`= :id "); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'id' => $id - ), true, true); + ], true, true); // set the new value for result-array $result['loginfail_count'] = 0; - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] unlocked customer '" . $result['loginname'] . "'"); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] unlocked customer '" . $result['loginname'] . "'"); return $this->response($result); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** @@ -1703,15 +1770,15 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource * and update all its references accordingly * * @param int $id - * optional, the customer-id + * optional, the customer-id * @param string $loginname - * optional, the loginname + * optional, the loginname * @param int $adminid - * target-admin-id + * target-admin-id * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function move() { @@ -1721,80 +1788,50 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $ln_optional = $id > 0; $loginname = $this->getParam('loginname', $ln_optional, ''); - $c_result = $this->apiCall('Customers.get', array( + $c_result = $this->apiCall('Customers.get', [ 'id' => $id, 'loginname' => $loginname - )); + ]); $id = $c_result['customerid']; // check if target-admin is the current admin if ($adminid == $c_result['adminid']) { - throw new \Exception("Cannot move customer to the same admin/reseller as he currently is assigned to", 406); + throw new Exception("Cannot move customer to the same admin/reseller as he currently is assigned to", 406); } // get target admin - $a_result = $this->apiCall('Admins.get', array( + $a_result = $this->apiCall('Admins.get', [ 'id' => $adminid - )); + ]); // Update customer entry $updCustomer_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `adminid` = :adminid WHERE `customerid` = :cid "); - Database::pexecute($updCustomer_stmt, array( + Database::pexecute($updCustomer_stmt, [ 'adminid' => $adminid, 'cid' => $id - ), true, true); + ], true, true); // Update customer-domains $updDomains_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `adminid` = :adminid WHERE `customerid` = :cid "); - Database::pexecute($updDomains_stmt, array( + Database::pexecute($updDomains_stmt, [ 'adminid' => $adminid, 'cid' => $id - ), true, true); + ], true, true); // now, recalculate the resource-usage for the old and the new admin - \Froxlor\User::updateCounters(false); + User::updateCounters(false); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] moved user '" . $c_result['loginname'] . "' from admin/reseller '" . $c_result['adminname'] . " to admin/reseller '" . $a_result['loginname'] . "'"); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] moved user '" . $c_result['loginname'] . "' from admin/reseller '" . $c_result['adminname'] . " to admin/reseller '" . $a_result['loginname'] . "'"); - $result = $this->apiCall('Customers.get', array( + $result = $this->apiCall('Customers.get', [ 'id' => $c_result['customerid'] - )); + ]); return $this->response($result); } - throw new \Exception("Not allowed to execute given command.", 403); - } - - /** - * increase resource-usage - * - * @param int $customerid - * @param string $resource - * @param string $extra - * optional, default empty - * @param int $increase_by - * optional, default 1 - */ - public static function increaseUsage($customerid = 0, $resource = null, $extra = '', $increase_by = 1) - { - self::updateResourceUsage(TABLE_PANEL_CUSTOMERS, 'customerid', $customerid, '+', $resource, $extra, $increase_by); - } - - /** - * decrease resource-usage - * - * @param int $customerid - * @param string $resource - * @param string $extra - * optional, default empty - * @param int $decrease_by - * optional, default 1 - */ - public static function decreaseUsage($customerid = 0, $resource = null, $extra = '', $decrease_by = 1) - { - self::updateResourceUsage(TABLE_PANEL_CUSTOMERS, 'customerid', $customerid, '-', $resource, $extra, $decrease_by); + throw new Exception("Not allowed to execute given command.", 403); } } diff --git a/lib/Froxlor/Api/Commands/DirOptions.php b/lib/Froxlor/Api/Commands/DirOptions.php index 40aeec2d..c0a700ea 100644 --- a/lib/Froxlor/Api/Commands/DirOptions.php +++ b/lib/Froxlor/Api/Commands/DirOptions.php @@ -1,58 +1,80 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Cron\TaskId; +use Froxlor\Database\Database; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; +use Froxlor\Settings; +use Froxlor\System\Cronjob; +use Froxlor\UI\Response; +use Froxlor\Validate\Validate; +use PDO; + +/** + * @since 0.10.0 + */ +class DirOptions extends ApiCommand implements ResourceEntity { /** * add options for a given directory * * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * @param string $path - * path relative to the customer's home-Directory + * path relative to the customer's home-Directory * @param bool $options_indexes - * optional, activate directory-listing for this path, default 0 (false) + * optional, activate directory-listing for this path, default 0 (false) * @param bool $options_cgi - * optional, allow Perl/CGI execution, default 0 (false) + * optional, allow Perl/CGI execution, default 0 (false) * @param string $error404path - * optional, custom 404 error string/file + * optional, custom 404 error string/file * @param string $error403path - * optional, custom 403 error string/file + * optional, custom 403 error string/file * @param string $error500path - * optional, custom 500 error string/file - * + * optional, custom 500 error string/file + * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function add() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras.pathoptions')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } // get needed customer info to reduce the email-address-counter by one @@ -69,19 +91,19 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $error500path = $this->getParam('error500path', true, ''); // validation - $path = \Froxlor\FileDir::makeCorrectDir(\Froxlor\Validate\Validate::validate($path, 'path', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true)); + $path = FileDir::makeCorrectDir(Validate::validate($path, 'path', Validate::REGEX_DIR, '', [], true)); $userpath = $path; - $path = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path); + $path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path); - if (! empty($error404path)) { + if (!empty($error404path)) { $error404path = $this->correctErrorDocument($error404path, true); } - if (! empty($error403path)) { + if (!empty($error403path)) { $error403path = $this->correctErrorDocument($error403path, true); } - if (! empty($error500path)) { + if (!empty($error500path)) { $error500path = $this->correctErrorDocument($error500path, true); } @@ -90,14 +112,14 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc SELECT `id`, `path` FROM `" . TABLE_PANEL_HTACCESS . "` WHERE `path`= :path AND `customerid`= :customerid "); - $path_dupe_check = Database::pexecute_first($path_dupe_check_stmt, array( + $path_dupe_check = Database::pexecute_first($path_dupe_check_stmt, [ "path" => $path, "customerid" => $customer['customerid'] - ), true, true); + ], true, true); // duplicate check if ($path_dupe_check && $path_dupe_check['path'] == $path) { - \Froxlor\UI\Response::standard_error('errordocpathdupe', $userpath, true); + Response::standardError('errordocpathdupe', $userpath, true); } // insert the entry @@ -111,7 +133,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc `error500path` = :error500path, `options_cgi` = :options_cgi '); - $params = array( + $params = [ "customerid" => $customer['customerid'], "path" => $path, "options_indexes" => $options_indexes, @@ -119,44 +141,85 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc "error404path" => $error404path, "error500path" => $error500path, "options_cgi" => $options_cgi - ); + ]; Database::pexecute($stmt, $params, true, true); $id = Database::lastInsertId(); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added directory-option for '" . $userpath . "'"); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added directory-option for '" . $userpath . "'"); + Cronjob::inserttask(TaskId::REBUILD_VHOST); - $result = $this->apiCall('DirOptions.get', array( + $result = $this->apiCall('DirOptions.get', [ 'id' => $id - )); + ]); return $this->response($result); } + /** + * this functions validates a given value as ErrorDocument + * refs #267 + * + * @param + * string error-document-string + * @param bool $throw_exception + * + * @return string error-document-string + * + */ + private function correctErrorDocument($errdoc = null, $throw_exception = false) + { + if ($errdoc !== null && $errdoc != '') { + // not a URL + if ((strtoupper(substr($errdoc, 0, 5)) != 'HTTP:' && strtoupper(substr($errdoc, 0, 6)) != 'HTTPS:') || !Validate::validateUrl($errdoc)) { + // a file + if (substr($errdoc, 0, 1) != '"') { + $errdoc = FileDir::makeCorrectFile($errdoc); + // apache needs a starting-slash (starting at the domains-docroot) + if (!substr($errdoc, 0, 1) == '/') { + $errdoc = '/' . $errdoc; + } + } else { + // a string (check for ending ") + // string won't work for lighty + if (Settings::Get('system.webserver') == 'lighttpd') { + Response::standardError('stringerrordocumentnotvalidforlighty', '', $throw_exception); + } elseif (substr($errdoc, -1) != '"') { + $errdoc .= '"'; + } + } + } else { + if (Settings::Get('system.webserver') == 'lighttpd') { + Response::standardError('urlerrordocumentnotvalidforlighty', '', $throw_exception); + } + } + } + return $errdoc; + } + /** * return a directory-protection entry by id * * @param int $id - * id of dir-protection entry - * + * id of dir-protection entry + * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function get() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $id = $this->getParam('id', true, 0); - $params = array(); + $params = []; if ($this->isAdmin()) { if ($this->getUserDetail('customers_see_all') == false) { // if it's a reseller or an admin who cannot see all customers, we need to check // whether the database belongs to one of his customers $_custom_list_result = $this->apiCall('Customers.listing'); $custom_list_result = $_custom_list_result['list']; - $customer_ids = array(); + $customer_ids = []; foreach ($custom_list_result as $customer) { $customer_ids[] = $customer['customerid']; } @@ -173,7 +236,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc } } else { if (Settings::IsInList('panel.customer_hide_options', 'extras.pathoptions')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_HTACCESS . "` @@ -185,45 +248,45 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $params['id'] = $id; $result = Database::pexecute_first($result_stmt, $params, true, true); if ($result) { - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get directory options for '" . $result['path'] . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get directory options for '" . $result['path'] . "'"); return $this->response($result); } $key = "id #" . $id; - throw new \Exception("Directory option with " . $key . " could not be found", 404); + throw new Exception("Directory option with " . $key . " could not be found", 404); } /** * update options for a given directory by id * * @param int $id - * id of dir-protection entry + * id of dir-protection entry * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * @param bool $options_indexes - * optional, activate directory-listing for this path, default 0 (false) + * optional, activate directory-listing for this path, default 0 (false) * @param bool $options_cgi - * optional, allow Perl/CGI execution, default 0 (false) + * optional, allow Perl/CGI execution, default 0 (false) * @param string $error404path - * optional, custom 404 error string/file + * optional, custom 404 error string/file * @param string $error403path - * optional, custom 403 error string/file + * optional, custom 403 error string/file * @param string $error500path - * optional, custom 500 error string/file - * + * optional, custom 500 error string/file + * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function update() { $id = $this->getParam('id', true, 0); // validation - $result = $this->apiCall('DirOptions.get', array( + $result = $this->apiCall('DirOptions.get', [ 'id' => $id - )); + ]); // get needed customer info to reduce the email-address-counter by one $customer = $this->getCustomerData(); @@ -235,20 +298,20 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $error403path = $this->getParam('error403path', true, $result['error403path']); $error500path = $this->getParam('error500path', true, $result['error500path']); - if (! empty($error404path)) { + if (!empty($error404path)) { $error404path = $this->correctErrorDocument($error404path, true); } - if (! empty($error403path)) { + if (!empty($error403path)) { $error403path = $this->correctErrorDocument($error403path, true); } - if (! empty($error500path)) { + if (!empty($error500path)) { $error500path = $this->correctErrorDocument($error500path, true); } if (($options_indexes != $result['options_indexes']) || ($error404path != $result['error404path']) || ($error403path != $result['error403path']) || ($error500path != $result['error500path']) || ($options_cgi != $result['options_cgi'])) { - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + Cronjob::inserttask(TaskId::REBUILD_VHOST); $stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_HTACCESS . "` SET `options_indexes` = :options_indexes, @@ -259,7 +322,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc WHERE `customerid` = :customerid AND `id` = :id "); - $params = array( + $params = [ "customerid" => $customer['customerid'], "options_indexes" => $options_indexes, "error403path" => $error403path, @@ -267,80 +330,83 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc "error500path" => $error500path, "options_cgi" => $options_cgi, "id" => $id - ); + ]; Database::pexecute($stmt, $params, true, true); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] edited directory options for '" . str_replace($customer['documentroot'], '/', $result['path']) . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] edited directory options for '" . str_replace($customer['documentroot'], '/', $result['path']) . "'"); } - $result = $this->apiCall('DirOptions.get', array( + $result = $this->apiCall('DirOptions.get', [ 'id' => $id - )); + ]); return $this->response($result); } /** - * list all directory-options, if called from an admin, list all directory-options of all customers you are allowed to view, or specify id or loginname for one specific customer + * list all directory-options, if called from an admin, list all directory-options of all customers you are allowed + * to view, or specify id or loginname for one specific customer * * @param int $customerid - * optional, admin-only, select directory-protections of a specific customer by id + * optional, admin-only, select directory-protections of a specific customer by id * @param string $loginname - * optional, admin-only, select directory-protections of a specific customer by loginname + * optional, admin-only, select directory-protections of a specific customer by loginname * @param array $sql_search - * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue * @param int $sql_limit - * optional specify number of results to be returned + * optional specify number of results to be returned * @param int $sql_offset - * optional specify offset for resultset + * optional specify offset for resultset * @param array $sql_orderby - * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more + * fields * * @access admin, customer - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listing() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $customer_ids = $this->getAllowedCustomerIds('extras.pathoptions'); - $result = array(); - $query_fields = array(); + $result = []; + $query_fields = []; $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_HTACCESS . "` WHERE `customerid` IN (" . implode(', ', $customer_ids) . ")" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); Database::pexecute($result_stmt, $query_fields, true, true); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $result[] = $row; } - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list directory-options"); - return $this->response(array( + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list directory-options"); + return $this->response([ 'count' => count($result), 'list' => $result - )); + ]); } /** * returns the total number of accessible directory options * * @param int $customerid - * optional, admin-only, select directory-protections of a specific customer by id + * optional, admin-only, select directory-protections of a specific customer by id * @param string $loginname - * optional, admin-only, select directory-protections of a specific customer by loginname + * optional, admin-only, select directory-protections of a specific customer by loginname * * @access admin, customer - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listingCount() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $customer_ids = $this->getAllowedCustomerIds('extras.pathoptions'); - - $result = array(); + + $result = []; $result_stmt = Database::prepare(" SELECT COUNT(*) as num_htaccess FROM `" . TABLE_PANEL_HTACCESS . "` WHERE `customerid` IN (" . implode(', ', $customer_ids) . ") @@ -355,52 +421,52 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc * delete a directory-options by id * * @param int $id - * id of dir-protection entry - * + * id of dir-protection entry + * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function delete() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $id = $this->getParam('id'); if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras.pathoptions')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } // get directory-option - $result = $this->apiCall('DirOptions.get', array( + $result = $this->apiCall('DirOptions.get', [ 'id' => $id - )); + ]); if ($this->isAdmin()) { // get customer-data - $customer_data = $this->apiCall('Customers.get', array( + $customer_data = $this->apiCall('Customers.get', [ 'id' => $result['customerid'] - )); + ]); } else { $customer_data = $this->getUserData(); } // do we have to remove the symlink and folder in suexecpath? - if ((int) Settings::Get('perl.suexecworkaround') == 1) { + if ((int)Settings::Get('perl.suexecworkaround') == 1) { $loginname = $customer_data['loginname']; - $suexecpath = \Froxlor\FileDir::makeCorrectDir(Settings::Get('perl.suexecpath') . '/' . $loginname . '/' . md5($result['path']) . '/'); - $perlsymlink = \Froxlor\FileDir::makeCorrectFile($result['path'] . '/cgi-bin'); + $suexecpath = FileDir::makeCorrectDir(Settings::Get('perl.suexecpath') . '/' . $loginname . '/' . md5($result['path']) . '/'); + $perlsymlink = FileDir::makeCorrectFile($result['path'] . '/cgi-bin'); // remove symlink if (file_exists($perlsymlink)) { - \Froxlor\FileDir::safe_exec('rm -f ' . escapeshellarg($perlsymlink)); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_DEBUG, "[API] deleted suexecworkaround symlink '" . $perlsymlink . "'"); + FileDir::safe_exec('rm -f ' . escapeshellarg($perlsymlink)); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_DEBUG, "[API] deleted suexecworkaround symlink '" . $perlsymlink . "'"); } // remove folder in suexec-path if (file_exists($suexecpath)) { - \Froxlor\FileDir::safe_exec('rm -rf ' . escapeshellarg($suexecpath)); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_DEBUG, "[API] deleted suexecworkaround path '" . $suexecpath . "'"); + FileDir::safe_exec('rm -rf ' . escapeshellarg($suexecpath)); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_DEBUG, "[API] deleted suexecworkaround path '" . $suexecpath . "'"); } } $stmt = Database::prepare(" @@ -408,53 +474,12 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc WHERE `customerid`= :customerid AND `id`= :id "); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "customerid" => $customer_data['customerid'], "id" => $id - ), true, true); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted directory-option for '" . str_replace($customer_data['documentroot'], '/', $result['path']) . "'"); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + ], true, true); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted directory-option for '" . str_replace($customer_data['documentroot'], '/', $result['path']) . "'"); + Cronjob::inserttask(TaskId::REBUILD_VHOST); return $this->response($result); } - - /** - * this functions validates a given value as ErrorDocument - * refs #267 - * - * @param - * string error-document-string - * @param bool $throw_exception - * - * @return string error-document-string - * - */ - private function correctErrorDocument($errdoc = null, $throw_exception = false) - { - if ($errdoc !== null && $errdoc != '') { - // not a URL - if ((strtoupper(substr($errdoc, 0, 5)) != 'HTTP:' && strtoupper(substr($errdoc, 0, 6)) != 'HTTPS:') || ! \Froxlor\Validate\Validate::validateUrl($errdoc)) { - // a file - if (substr($errdoc, 0, 1) != '"') { - $errdoc = \Froxlor\FileDir::makeCorrectFile($errdoc); - // apache needs a starting-slash (starting at the domains-docroot) - if (! substr($errdoc, 0, 1) == '/') { - $errdoc = '/' . $errdoc; - } - } else { - // a string (check for ending ") - // string won't work for lighty - if (Settings::Get('system.webserver') == 'lighttpd') { - \Froxlor\UI\Response::standard_error('stringerrordocumentnotvalidforlighty', '', $throw_exception); - } elseif (substr($errdoc, - 1) != '"') { - $errdoc .= '"'; - } - } - } else { - if (Settings::Get('system.webserver') == 'lighttpd') { - \Froxlor\UI\Response::standard_error('urlerrordocumentnotvalidforlighty', '', $throw_exception); - } - } - } - return $errdoc; - } } diff --git a/lib/Froxlor/Api/Commands/DirProtections.php b/lib/Froxlor/Api/Commands/DirProtections.php index 466abaff..f4964993 100644 --- a/lib/Froxlor/Api/Commands/DirProtections.php +++ b/lib/Froxlor/Api/Commands/DirProtections.php @@ -1,51 +1,74 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Cron\TaskId; +use Froxlor\Database\Database; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; +use Froxlor\Settings; +use Froxlor\System\Cronjob; +use Froxlor\System\Crypt; +use Froxlor\UI\Response; +use Froxlor\Validate\Validate; +use PDO; + +/** + * @since 0.10.0 + */ +class DirProtections extends ApiCommand implements ResourceEntity { /** * add htaccess protection to a given directory * * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * @param string $path * @param string $username * @param string $directory_password * @param string $directory_authname - * optional name/description for the protection + * optional name/description for the protection * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function add() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras.directoryprotection')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } // get needed customer info to reduce the email-address-counter by one @@ -60,31 +83,31 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res $authname = $this->getParam('directory_authname', true, ''); // validation - $path = \Froxlor\FileDir::makeCorrectDir(\Froxlor\Validate\Validate::validate($path, 'path', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true)); - $path = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path); - $username = \Froxlor\Validate\Validate::validate($username, 'username', '/^[a-zA-Z0-9][a-zA-Z0-9\-_]+\$?$/', '', array(), true); - $authname = \Froxlor\Validate\Validate::validate($authname, 'directory_authname', '/^[a-zA-Z0-9][a-zA-Z0-9\-_ ]+\$?$/', '', array(), true); - \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true); + $path = FileDir::makeCorrectDir(Validate::validate($path, 'path', Validate::REGEX_DIR, '', [], true)); + $path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path); + $username = Validate::validate($username, 'username', '/^[a-zA-Z0-9][a-zA-Z0-9\-_]+\$?$/', '', [], true); + $authname = Validate::validate($authname, 'directory_authname', '/^[a-zA-Z0-9][a-zA-Z0-9\-_ ]+\$?$/', '', [], true); + Validate::validate($password, 'password', '', '', [], true); // check for duplicate usernames for the path $username_path_check_stmt = Database::prepare(" SELECT `id`, `username`, `path` FROM `" . TABLE_PANEL_HTPASSWDS . "` WHERE `username`= :username AND `path`= :path AND `customerid`= :customerid "); - $params = array( + $params = [ "username" => $username, "path" => $path, "customerid" => $customer['customerid'] - ); + ]; $username_path_check = Database::pexecute_first($username_path_check_stmt, $params, true, true); - $password_enc = \Froxlor\System\Crypt::makeCryptPassword($password, true); + $password_enc = Crypt::makeCryptPassword($password, true); // duplicate check if ($username_path_check && $username_path_check['username'] == $username && $username_path_check['path'] == $path) { - \Froxlor\UI\Response::standard_error('userpathcombinationdupe', '', true); + Response::standardError('userpathcombinationdupe', '', true); } elseif ($password == $username) { - \Froxlor\UI\Response::standard_error('passwordshouldnotbeusername', '', true); + Response::standardError('passwordshouldnotbeusername', '', true); } // insert the entry @@ -96,21 +119,21 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res `path` = :path, `authname` = :authname "); - $params = array( + $params = [ "customerid" => $customer['customerid'], "username" => $username, "password" => $password_enc, "path" => $path, "authname" => $authname - ); + ]; Database::pexecute($stmt, $params, true, true); $id = Database::lastInsertId(); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added directory-protection for '" . $username . " (" . $path . ")'"); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added directory-protection for '" . $username . " (" . $path . ")'"); + Cronjob::inserttask(TaskId::REBUILD_VHOST); - $result = $this->apiCall('DirProtections.get', array( + $result = $this->apiCall('DirProtections.get', [ 'id' => $id - )); + ]); return $this->response($result); } @@ -118,32 +141,32 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res * return a directory-protection entry by either id or username * * @param int $id - * optional, the directory-protection-id + * optional, the directory-protection-id * @param string $username - * optional, the username + * optional, the username * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function get() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $id = $this->getParam('id', true, 0); $un_optional = $id > 0; $username = $this->getParam('username', $un_optional, ''); - $params = array(); + $params = []; if ($this->isAdmin()) { if ($this->getUserDetail('customers_see_all') == false) { // if it's a reseller or an admin who cannot see all customers, we need to check // whether the database belongs to one of his customers $_custom_list_result = $this->apiCall('Customers.listing'); $custom_list_result = $_custom_list_result['list']; - $customer_ids = array(); + $customer_ids = []; foreach ($custom_list_result as $customer) { $customer_ids[] = $customer['customerid']; } @@ -160,7 +183,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res } } else { if (Settings::IsInList('panel.customer_hide_options', 'extras.directoryprotection')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_HTPASSWDS . "` @@ -172,32 +195,32 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res $params['idun'] = ($id <= 0 ? $username : $id); $result = Database::pexecute_first($result_stmt, $params, true, true); if ($result) { - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get directory protection for '" . $result['path'] . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get directory protection for '" . $result['path'] . "'"); return $this->response($result); } $key = ($id > 0 ? "id #" . $id : "username '" . $username . "'"); - throw new \Exception("Directory protection with " . $key . " could not be found", 404); + throw new Exception("Directory protection with " . $key . " could not be found", 404); } /** * update htaccess protection of a given directory * * @param int $id - * optional the directory-protection-id + * optional the directory-protection-id * @param string $username - * optional, the username + * optional, the username * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * @param string $directory_password - * optional, leave empty for no change + * optional, leave empty for no change * @param string $directory_authname - * optional name/description for the protection + * optional name/description for the protection * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function update() { @@ -206,10 +229,10 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res $username = $this->getParam('username', $un_optional, ''); // validation - $result = $this->apiCall('DirProtections.get', array( + $result = $this->apiCall('DirProtections.get', [ 'id' => $id, 'username' => $username - )); + ]); $id = $result['id']; // parameters @@ -220,25 +243,25 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res $customer = $this->getCustomerData(); // validation - $authname = \Froxlor\Validate\Validate::validate($authname, 'directory_authname', '/^[a-zA-Z0-9][a-zA-Z0-9\-_ ]+\$?$/', '', array(), true); - \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true); + $authname = Validate::validate($authname, 'directory_authname', '/^[a-zA-Z0-9][a-zA-Z0-9\-_ ]+\$?$/', '', [], true); + Validate::validate($password, 'password', '', '', [], true); $upd_query = ""; - $upd_params = array( + $upd_params = [ "id" => $result['id'], "cid" => $customer['customerid'] - ); - if (! empty($password)) { + ]; + if (!empty($password)) { if ($password == $result['username']) { - \Froxlor\UI\Response::standard_error('passwordshouldnotbeusername', '', true); + Response::standardError('passwordshouldnotbeusername', '', true); } - $password_enc = \Froxlor\System\Crypt::makeCryptPassword($password, true); + $password_enc = Crypt::makeCryptPassword($password, true); $upd_query .= "`password`= :password_enc"; $upd_params['password_enc'] = $password_enc; } if ($authname != $result['authname']) { - if (! empty($upd_query)) { + if (!empty($upd_query)) { $upd_query .= ", "; } $upd_query .= "`authname` = :authname"; @@ -246,84 +269,87 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res } // build update query - if (! empty($upd_query)) { + if (!empty($upd_query)) { $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_HTPASSWDS . "` SET " . $upd_query . " WHERE `id` = :id AND `customerid`= :cid "); Database::pexecute($upd_stmt, $upd_params, true, true); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + Cronjob::inserttask(TaskId::REBUILD_VHOST); } - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] updated directory-protection '" . $result['username'] . " (" . $result['path'] . ")'"); - $result = $this->apiCall('DirProtections.get', array( + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] updated directory-protection '" . $result['username'] . " (" . $result['path'] . ")'"); + $result = $this->apiCall('DirProtections.get', [ 'id' => $result['id'] - )); + ]); return $this->response($result); } /** - * list all directory-protections, if called from an admin, list all directory-protections of all customers you are allowed to view, or specify id or loginname for one specific customer + * list all directory-protections, if called from an admin, list all directory-protections of all customers you are + * allowed to view, or specify id or loginname for one specific customer * * @param int $customerid - * optional, admin-only, select directory-protections of a specific customer by id + * optional, admin-only, select directory-protections of a specific customer by id * @param string $loginname - * optional, admin-only, select directory-protections of a specific customer by loginname + * optional, admin-only, select directory-protections of a specific customer by loginname * @param array $sql_search - * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue * @param int $sql_limit - * optional specify number of results to be returned + * optional specify number of results to be returned * @param int $sql_offset - * optional specify offset for resultset + * optional specify offset for resultset * @param array $sql_orderby - * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more + * fields * * @access admin, customer - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listing() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $customer_ids = $this->getAllowedCustomerIds('extras.directoryprotection'); - $result = array(); - $query_fields = array(); + $result = []; + $query_fields = []; $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_HTPASSWDS . "` WHERE `customerid` IN (" . implode(', ', $customer_ids) . ")" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); Database::pexecute($result_stmt, $query_fields, true, true); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $result[] = $row; } - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list directory-protections"); - return $this->response(array( + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list directory-protections"); + return $this->response([ 'count' => count($result), 'list' => $result - )); + ]); } /** * returns the total number of accessible directory protections * * @param int $customerid - * optional, admin-only, select directory-protections of a specific customer by id + * optional, admin-only, select directory-protections of a specific customer by id * @param string $loginname - * optional, admin-only, select directory-protections of a specific customer by loginname + * optional, admin-only, select directory-protections of a specific customer by loginname * * @access admin, customer - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listingCount() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $customer_ids = $this->getAllowedCustomerIds('extras.directoryprotection'); - $result = array(); + $result = []; $result_stmt = Database::prepare(" SELECT COUNT(*) as num_htpasswd FROM `" . TABLE_PANEL_HTPASSWDS . "` WHERE `customerid` IN (" . implode(', ', $customer_ids) . ") @@ -338,18 +364,18 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res * delete a directory-protection by either id or username * * @param int $id - * optional, the directory-protection-id + * optional, the directory-protection-id * @param string $username - * optional, the username + * optional, the username * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function delete() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $id = $this->getParam('id', true, 0); @@ -357,21 +383,21 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res $username = $this->getParam('username', $un_optional, ''); if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras.directoryprotection')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } // get directory protection - $result = $this->apiCall('DirProtections.get', array( + $result = $this->apiCall('DirProtections.get', [ 'id' => $id, 'username' => $username - )); + ]); $id = $result['id']; if ($this->isAdmin()) { // get customer-data - $customer_data = $this->apiCall('Customers.get', array( + $customer_data = $this->apiCall('Customers.get', [ 'id' => $result['customerid'] - )); + ]); } else { $customer_data = $this->getUserData(); } @@ -379,13 +405,13 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res $stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_HTPASSWDS . "` WHERE `customerid`= :customerid AND `id`= :id "); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "customerid" => $customer_data['customerid'], "id" => $id - )); + ]); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted htpasswd for '" . $result['username'] . " (" . $result['path'] . ")'"); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted htpasswd for '" . $result['username'] . " (" . $result['path'] . ")'"); + Cronjob::inserttask(TaskId::REBUILD_VHOST); return $this->response($result); } } diff --git a/lib/Froxlor/Api/Commands/DomainZones.php b/lib/Froxlor/Api/Commands/DomainZones.php index 2da17b32..eafdd0d4 100644 --- a/lib/Froxlor/Api/Commands/DomainZones.php +++ b/lib/Froxlor/Api/Commands/DomainZones.php @@ -1,57 +1,80 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Cron\TaskId; +use Froxlor\Database\Database; +use Froxlor\Dns\Dns; +use Froxlor\FroxlorLogger; +use Froxlor\Idna\IdnaWrapper; +use Froxlor\Settings; +use Froxlor\System\Cronjob; +use Froxlor\UI\Response; +use Froxlor\Validate\Validate; +use PDO; + +/** + * @since 0.10.0 + */ +class DomainZones extends ApiCommand implements ResourceEntity { /** * add a new dns zone for a given domain by id or domainname * * @param int $id - * optional domain id + * optional domain id * @param string $domainname - * optional domain name + * optional domain name * @param string $record - * optional, default empty + * optional, default empty * @param string $type - * optional, zone-entry type (A, AAAA, TXT, etc.), default 'A' + * optional, zone-entry type (A, AAAA, TXT, etc.), default 'A' * @param int $prio - * optional, priority, default empty + * optional, priority, default empty * @param string $content - * optional, default empty + * optional, default empty * @param int $ttl - * optional, default 18000 + * optional, default 18000 * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function add() { if (Settings::Get('system.dnsenabled') != '1') { - throw new \Exception("DNS service not enabled on this system", 405); + throw new Exception("DNS service not enabled on this system", 405); } if ($this->isAdmin() == false && $this->getUserDetail('dnsenabled') != '1') { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $id = $this->getParam('id', true, 0); @@ -59,10 +82,10 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $domainname = $this->getParam('domainname', $dn_optional, ''); // get requested domain - $result = $this->apiCall('SubDomains.get', array( + $result = $this->apiCall('SubDomains.get', [ 'id' => $id, 'domainname' => $domainname - )); + ]); $id = $result['id']; // parameters @@ -73,25 +96,25 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $ttl = $this->getParam('ttl', true, 18000); if ($result['parentdomainid'] != '0') { - throw new \Exception("DNS zones can only be generated for the main domain, not for subdomains", 406); + throw new Exception("DNS zones can only be generated for the main domain, not for subdomains", 406); } if ($result['subisbinddomain'] != '1') { - \Froxlor\UI\Response::standard_error('dns_domain_nodns', '', true); + Response::standardError('dns_domain_nodns', '', true); } - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); + $idna_convert = new IdnaWrapper(); $domain = $idna_convert->encode($result['domain']); // select all entries $sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_DOMAIN_DNS . "` WHERE domain_id = :did"); - Database::pexecute($sel_stmt, array( + Database::pexecute($sel_stmt, [ 'did' => $id - ), true, true); - $dom_entries = $sel_stmt->fetchAll(\PDO::FETCH_ASSOC); + ], true, true); + $dom_entries = $sel_stmt->fetchAll(PDO::FETCH_ASSOC); // validation - $errors = array(); + $errors = []; if (empty($record)) { $record = "@"; } @@ -154,29 +177,29 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour break; } } - } elseif ($type == 'CAA' && ! empty($content)) { + } elseif ($type == 'CAA' && !empty($content)) { $re = '/(?\'critical\'\d)\h*(?\'type\'iodef|issue|issuewild)\h*(?\'value\'(?\'issuevalue\'"(?\'domain\'(?=.{3,128}$)(?>(?>[a-zA-Z0-9]+[a-zA-Z0-9-]*[a-zA-Z0-9]+|[a-zA-Z0-9]+)\.)*(?>[a-zA-Z]{2,}|[a-zA-Z0-9]{2,}\.[a-zA-Z]{2,}))[;\h]*(?\'parameters\'(?>[a-zA-Z0-9]{1,60}=[a-zA-Z0-9]{1,60}\h*)+)?")|(?\'iodefvalue\'"(?\'url\'(mailto:.*|http:\/\/.*|https:\/\/.*))"))/'; preg_match($re, $content, $matches); if (empty($matches)) { $errors[] = lng('error.dns_content_invalid'); - } elseif (($matches['type'] == 'issue' || $matches['type'] == 'issuewild') && ! \Froxlor\Validate\Validate::validateDomain($matches['domain'])) { + } elseif (($matches['type'] == 'issue' || $matches['type'] == 'issuewild') && !Validate::validateDomain($matches['domain'])) { $errors[] = lng('error.dns_content_invalid'); - } elseif ($matches['type'] == 'iodef' && ! \Froxlor\Validate\Validate::validateUrl($matches['url'])) { + } elseif ($matches['type'] == 'iodef' && !Validate::validateUrl($matches['url'])) { $errors[] = lng('error.dns_content_invalid'); } else { $content = $matches[0]; } } elseif ($type == 'CNAME' || $type == 'DNAME') { // check for trailing dot - if (substr($content, - 1) == '.') { + if (substr($content, -1) == '.') { // remove it for checks - $content = substr($content, 0, - 1); + $content = substr($content, 0, -1); } else { // add domain name $content .= '.' . $domain; } - if (! \Froxlor\Validate\Validate::validateDomain($content, true)) { + if (!Validate::validateDomain($content, true)) { $errors[] = lng('error.dns_cname_invaliddom'); } else { // check whether there are RR-records for the same resource @@ -193,18 +216,18 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour } // append trailing dot (again) $content .= '.'; - } elseif ($type == 'LOC' && ! empty($content)) { + } elseif ($type == 'LOC' && !empty($content)) { $content = $content; } elseif ($type == 'MX') { if ($prio === null || $prio < 0) { $errors[] = lng('error.dns_mx_prioempty'); } // check for trailing dot - if (substr($content, - 1) == '.') { + if (substr($content, -1) == '.') { // remove it for checks - $content = substr($content, 0, - 1); + $content = substr($content, 0, -1); } - if (! \Froxlor\Validate\Validate::validateDomain($content)) { + if (!Validate::validateDomain($content)) { $errors[] = lng('error.dns_mx_needdom'); } else { // check whether there is a CNAME-record for the same resource @@ -213,8 +236,7 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour if ($existing_entries['type'] == 'CNAME' && $fqdn == $content) { $errors[] = lng('error.dns_mx_noalias'); break; - } - elseif ($existing_entries['type'] == 'CNAME' && $existing_entries['record'] == $record) { + } elseif ($existing_entries['type'] == 'CNAME' && $existing_entries['record'] == $record) { $errors[] = lng('error.dns_other_nomorerr'); break; } @@ -224,11 +246,11 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $content .= '.'; } elseif ($type == 'NS') { // check for trailing dot - if (substr($content, - 1) == '.') { + if (substr($content, -1) == '.') { // remove it for checks - $content = substr($content, 0, - 1); + $content = substr($content, 0, -1); } - if (! \Froxlor\Validate\Validate::validateDomain($content)) { + if (!Validate::validateDomain($content)) { $errors[] = lng('error.dns_ns_invaliddom'); } else { // check whether there is a CNAME-record for the same resource @@ -241,7 +263,7 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour } // append trailing dot (again) $content .= '.'; - } elseif ($type == 'RP' && ! empty($content)) { + } elseif ($type == 'RP' && !empty($content)) { $content = $content; } elseif ($type == 'SRV') { if ($prio === null || $prio < 0) { @@ -257,12 +279,12 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $target = trim($_split_content[count($_split_content) - 1]); if ($target != '.') { // check for trailing dot - if (substr($target, - 1) == '.') { + if (substr($target, -1) == '.') { // remove it for checks - $target = substr($target, 0, - 1); + $target = substr($target, 0, -1); } } - if ($target != '.' && ! \Froxlor\Validate\Validate::validateDomain($target, true)) { + if ($target != '.' && !Validate::validateDomain($target, true)) { $errors[] = lng('error.dns_srv_needdom'); } else { // check whether there is a CNAME-record for the same resource @@ -275,24 +297,24 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour } } // append trailing dot if there's none - if (substr($content, - 1) != '.') { + if (substr($content, -1) != '.') { $content .= '.'; } - } elseif ($type == 'SSHFP' && ! empty($content)) { + } elseif ($type == 'SSHFP' && !empty($content)) { $content = $content; - } elseif ($type == 'TXT' && ! empty($content)) { + } elseif ($type == 'TXT' && !empty($content)) { // check that TXT content is enclosed in " " - $content = \Froxlor\Dns\Dns::encloseTXTContent($content); + $content = Dns::encloseTXTContent($content); } - $new_entry = array( + $new_entry = [ 'record' => $record, 'type' => $type, - 'prio' => (int) $prio, + 'prio' => (int)$prio, 'content' => $content, - 'ttl' => (int) $ttl, - 'domain_id' => (int) $id - ); + 'ttl' => (int)$ttl, + 'domain_id' => (int)$id + ]; ksort($new_entry); // check for duplicate @@ -304,9 +326,9 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour // sort by key ksort($check_entry); // format integer fields to real integer (as they are read as string from the DB) - $check_entry['prio'] = (int) $check_entry['prio']; - $check_entry['ttl'] = (int) $check_entry['ttl']; - $check_entry['domain_id'] = (int) $check_entry['domain_id']; + $check_entry['prio'] = (int)$check_entry['prio']; + $check_entry['ttl'] = (int)$check_entry['ttl']; + $check_entry['domain_id'] = (int)$check_entry['domain_id']; // encode both $check_entry = json_encode($check_entry); $new = json_encode($new_entry); @@ -336,37 +358,37 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $dom_entries[] = $new_entry; // re-generate bind configs - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); + Cronjob::inserttask(TaskId::REBUILD_DNS); - $result = $this->apiCall('DomainZones.get', array( + $result = $this->apiCall('DomainZones.get', [ 'id' => $id - )); + ]); return $this->response($result); } // return $errors - throw new \Exception(implode("\n", $errors), 406); + throw new Exception(implode("\n", $errors), 406); } /** * return a domain-dns entry by either id or domainname * * @param int $id - * optional, the domain id + * optional, the domain id * @param string $domainname - * optional, the domain name + * optional, the domain name * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function get() { if (Settings::Get('system.dnsenabled') != '1') { - throw new \Exception("DNS service not enabled on this system", 405); + throw new Exception("DNS service not enabled on this system", 405); } if ($this->isAdmin() == false && $this->getUserDetail('dnsenabled') != '1') { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $id = $this->getParam('id', true, 0); @@ -374,24 +396,24 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $domainname = $this->getParam('domainname', $dn_optional, ''); // get requested domain - $result = $this->apiCall('SubDomains.get', array( + $result = $this->apiCall('SubDomains.get', [ 'id' => $id, 'domainname' => $domainname - )); + ]); $id = $result['id']; if ($result['parentdomainid'] != '0') { - throw new \Exception("DNS zones can only be generated for the main domain, not for subdomains", 406); + throw new Exception("DNS zones can only be generated for the main domain, not for subdomains", 406); } if ($result['subisbinddomain'] != '1') { - \Froxlor\UI\Response::standard_error('dns_domain_nodns', '', true); + Response::standardError('dns_domain_nodns', '', true); } - $zone = \Froxlor\Dns\Dns::createDomainZone($id); - $zonefile = (string) $zone; + $zone = Dns::createDomainZone($id); + $zonefile = (string)$zone; - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get dns-zone for '" . $result['domain'] . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get dns-zone for '" . $result['domain'] . "'"); return $this->response(explode("\n", $zonefile)); } @@ -401,37 +423,39 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour */ public function update() { - throw new \Exception('You cannot update a dns zone entry. You need to delete it and re-add it.', 303); + throw new Exception('You cannot update a dns zone entry. You need to delete it and re-add it.', 303); } /** * List all entry records of a given domain by either id or domainname * * @param int $id - * optional, the domain id + * optional, the domain id * @param string $domainname - * optional, the domain name + * optional, the domain name * @param array $sql_search - * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue * @param int $sql_limit - * optional specify number of results to be returned + * optional specify number of results to be returned * @param int $sql_offset - * optional specify offset for resultset + * optional specify offset for resultset * @param array $sql_orderby - * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more + * fields * * @access admin, customer - * @throws \Exception * @return bool + * @throws Exception */ public function listing() { if (Settings::Get('system.dnsenabled') != '1') { - throw new \Exception("DNS service not enabled on this system", 405); + throw new Exception("DNS service not enabled on this system", 405); } if ($this->isAdmin() == false && $this->getUserDetail('dnsenabled') != '1') { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $id = $this->getParam('id', true, 0); @@ -439,45 +463,45 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $domainname = $this->getParam('domainname', $dn_optional, ''); // get requested domain - $result = $this->apiCall('SubDomains.get', array( + $result = $this->apiCall('SubDomains.get', [ 'id' => $id, 'domainname' => $domainname - )); + ]); $id = $result['id']; - $query_fields = array(); + $query_fields = []; $sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_DOMAIN_DNS . "` WHERE `domain_id` = :did" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); $query_fields['did'] = $id; Database::pexecute($sel_stmt, $query_fields, true, true); $result = []; - while ($row = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $sel_stmt->fetch(PDO::FETCH_ASSOC)) { $result[] = $row; } - return $this->response(array( + return $this->response([ 'count' => count($result), 'list' => $result - )); + ]); } /** * returns the total number of domainzone-entries for given domain * * @param int $id - * optional, the domain id + * optional, the domain id * @param string $domainname - * optional, the domain name + * optional, the domain name * * @access admin, customer - * @throws \Exception * @return bool + * @throws Exception */ public function listingCount() { if (Settings::Get('system.dnsenabled') != '1') { - throw new \Exception("DNS service not enabled on this system", 405); + throw new Exception("DNS service not enabled on this system", 405); } if ($this->isAdmin() == false && $this->getUserDetail('dnsenabled') != '1') { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $id = $this->getParam('id', true, 0); @@ -485,16 +509,16 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $domainname = $this->getParam('domainname', $dn_optional, ''); // get requested domain - $result = $this->apiCall('SubDomains.get', array( + $result = $this->apiCall('SubDomains.get', [ 'id' => $id, 'domainname' => $domainname - )); + ]); $id = $result['id']; $sel_stmt = Database::prepare("SELECT COUNT(*) as num_dns FROM `" . TABLE_DOMAIN_DNS . "` WHERE `domain_id` = :did"); - $result = Database::pexecute_first($sel_stmt, array( + $result = Database::pexecute_first($sel_stmt, [ 'did' => $id - ), true, true); + ], true, true); if ($result) { return $this->response($result['num_dns']); } @@ -505,22 +529,22 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour * * @param int $entry_id * @param int $id - * optional, the domain id + * optional, the domain id * @param string $domainname - * optional, the domain name + * optional, the domain name * * @access admin, customer - * @throws \Exception * @return bool + * @throws Exception */ public function delete() { if (Settings::Get('system.dnsenabled') != '1') { - throw new \Exception("DNS service not enabled on this system", 405); + throw new Exception("DNS service not enabled on this system", 405); } if ($this->isAdmin() == false && $this->getUserDetail('dnsenabled') != '1') { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $entry_id = $this->getParam('entry_id'); @@ -529,20 +553,20 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $domainname = $this->getParam('domainname', $dn_optional, ''); // get requested domain - $result = $this->apiCall('SubDomains.get', array( + $result = $this->apiCall('SubDomains.get', [ 'id' => $id, 'domainname' => $domainname - )); + ]); $id = $result['id']; $del_stmt = Database::prepare("DELETE FROM `" . TABLE_DOMAIN_DNS . "` WHERE `id` = :id AND `domain_id` = :did"); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'id' => $entry_id, 'did' => $id - ), true, true); + ], true, true); if ($del_stmt->rowCount() > 0) { // re-generate bind configs - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); + Cronjob::inserttask(TaskId::REBUILD_DNS); return $this->response(true); } return $this->response(true, 304); diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php index 8898d31e..4355de44 100644 --- a/lib/Froxlor/Api/Commands/Domains.php +++ b/lib/Froxlor/Api/Commands/Domains.php @@ -1,51 +1,79 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Cron\TaskId; +use Froxlor\Database\Database; +use Froxlor\Domain\Domain; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; +use Froxlor\Idna\IdnaWrapper; +use Froxlor\PhpHelper; +use Froxlor\Settings; +use Froxlor\System\Cronjob; +use Froxlor\UI\Response; +use Froxlor\User; +use Froxlor\Validate\Validate; +use PDO; + +/** + * @since 0.10.0 + */ +class Domains extends ApiCommand implements ResourceEntity { /** * lists all domain entries * * @param bool $with_ips - * optional, default true + * optional, default true * @param array $sql_search - * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue * @param int $sql_limit - * optional specify number of results to be returned + * optional specify number of results to be returned * @param int $sql_offset - * optional specify offset for resultset + * optional specify offset for resultset * @param array $sql_orderby - * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more + * fields * * @access admin - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listing() { if ($this->isAdmin()) { $with_ips = $this->getParam('with_ips', true, true); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list domains"); - $query_fields = array(); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list domains"); + $query_fields = []; $result_stmt = Database::prepare(" SELECT `d`.*, `c`.`loginname`, `c`.`deactivated`, `c`.`name`, `c`.`firstname`, `c`.`company`, `c`.`standardsubdomain`, @@ -54,114 +82,26 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`) LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id` WHERE `d`.`parentdomainid`='0' " . ($this->getUserDetail('customers_see_all') ? '' : " AND `d`.`adminid` = :adminid ") . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); - $params = array(); + $params = []; if ($this->getUserDetail('customers_see_all') == '0') { $params['adminid'] = $this->getUserDetail('adminid'); } $params = array_merge($params, $query_fields); Database::pexecute($result_stmt, $params, true, true); - $result = array(); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { - $row['ipsandports'] = array(); + $result = []; + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + $row['ipsandports'] = []; if ($with_ips) { $row['ipsandports'] = $this->getIpsForDomain($row['id']); } $result[] = $row; } - return $this->response(array( + return $this->response([ 'count' => count($result), 'list' => $result - )); + ]); } - throw new \Exception("Not allowed to execute given command.", 403); - } - - /** - * returns the total number of accessible domains - * - * @access admin - * @throws \Exception - * @return string json-encoded array count|list - */ - public function listingCount() - { - if ($this->isAdmin()) { - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list domains"); - $result_stmt = Database::prepare(" - SELECT - COUNT(*) as num_domains - FROM `" . TABLE_PANEL_DOMAINS . "` `d` - LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`) - LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id` - WHERE `d`.`parentdomainid`='0' " . ($this->getUserDetail('customers_see_all') ? '' : " AND `d`.`adminid` = :adminid ")); - $params = array(); - if ($this->getUserDetail('customers_see_all') == '0') { - $params['adminid'] = $this->getUserDetail('adminid'); - } - $result = Database::pexecute_first($result_stmt, $params, true, true); - if ($result) { - return $this->response($result['num_domains']); - } - } - throw new \Exception("Not allowed to execute given command.", 403); - } - - /** - * return a domain entry by either id or domainname - * - * @param int $id - * optional, the domain-id - * @param string $domainname - * optional, the domainname - * @param bool $with_ips - * optional, default true - * @param bool $no_std_subdomain - * optional, default false - * - * @access admin - * @throws \Exception - * @return string json-encoded array - */ - public function get() - { - if ($this->isAdmin()) { - $id = $this->getParam('id', true, 0); - $dn_optional = $id > 0; - $domainname = $this->getParam('domainname', $dn_optional, ''); - $with_ips = $this->getParam('with_ips', true, true); - $no_std_subdomain = $this->getParam('no_std_subdomain', true, false); - - // convert possible idn domain to punycode - if (substr($domainname, 0, 4) != 'xn--') { - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); - $domainname = $idna_convert->encode($domainname); - } - - $result_stmt = Database::prepare(" - SELECT `d`.*, `c`.`customerid` - FROM `" . TABLE_PANEL_DOMAINS . "` `d` - LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`) - WHERE `d`.`parentdomainid` = '0' - AND " . ($id > 0 ? "`d`.`id` = :iddn" : "`d`.`domain` = :iddn") . ($no_std_subdomain ? ' AND `d`.`id` <> `c`.`standardsubdomain`' : '') . ($this->getUserDetail('customers_see_all') ? '' : " AND `d`.`adminid` = :adminid")); - $params = array( - 'iddn' => ($id <= 0 ? $domainname : $id) - ); - if ($this->getUserDetail('customers_see_all') == '0') { - $params['adminid'] = $this->getUserDetail('adminid'); - } - $result = Database::pexecute_first($result_stmt, $params, true, true); - if ($result) { - $result['ipsandports'] = array(); - if ($with_ips) { - $result['ipsandports'] = $this->getIpsForDomain($result['id']); - } - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get domain '" . $result['domain'] . "'"); - return $this->response($result); - } - $key = ($id > 0 ? "id #" . $id : "domainname '" . $domainname . "'"); - throw new \Exception("Domain with " . $key . " could not be found", 404); - } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** @@ -169,7 +109,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn * * @param number $domain_id * @param bool $ssl_only - * optional, return only ssl enabled ip's, default false + * optional, return only ssl enabled ip's, default false * @return array */ private function getIpsForDomain($domain_id = 0, $ssl_only = false) @@ -178,12 +118,12 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn SELECT `ips`.* FROM `" . TABLE_DOMAINTOIP . "` AS `dti`, `" . TABLE_PANEL_IPSANDPORTS . "` AS `ips` WHERE `dti`.`id_ipandports` = `ips`.`id` AND `dti`.`id_domain` = :domainid " . ($ssl_only ? " AND `ips`.`ssl` = '1'" : "")); - Database::pexecute($resultips_stmt, array( + Database::pexecute($resultips_stmt, [ 'domainid' => $domain_id - )); + ]); - $ipandports = array(); - while ($rowip = $resultips_stmt->fetch(\PDO::FETCH_ASSOC)) { + $ipandports = []; + while ($rowip = $resultips_stmt->fetch(PDO::FETCH_ASSOC)) { if (filter_var($rowip['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { $rowip['is_ipv6'] = true; } @@ -194,133 +134,155 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn } /** - * get ips from array of id's + * returns the total number of accessible domains * - * @param array $ips - * @return array + * @access admin + * @return string json-encoded array count|list + * @throws Exception */ - private function getIpsFromIdArray(array $ids) + public function listingCount() { - $resultips_stmt = Database::prepare(" - SELECT `ip` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE id = :id - "); - $result = []; - foreach ($ids as $id) { - $entry = Database::pexecute_first($resultips_stmt, array( - 'id' => $id - )); - $result[] = $entry['ip']; + if ($this->isAdmin()) { + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list domains"); + $result_stmt = Database::prepare(" + SELECT + COUNT(*) as num_domains + FROM `" . TABLE_PANEL_DOMAINS . "` `d` + LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`) + LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id` + WHERE `d`.`parentdomainid`='0' " . ($this->getUserDetail('customers_see_all') ? '' : " AND `d`.`adminid` = :adminid ")); + $params = []; + if ($this->getUserDetail('customers_see_all') == '0') { + $params['adminid'] = $this->getUserDetail('adminid'); + } + $result = Database::pexecute_first($result_stmt, $params, true, true); + if ($result) { + return $this->response($result['num_domains']); + } } - return $result; + throw new Exception("Not allowed to execute given command.", 403); } /** * add new domain entry * * @param string $domain - * domain-name + * domain-name * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * @param int $adminid - * optional, default is the calling admin's ID + * optional, default is the calling admin's ID * @param array $ipandport - * optional list of ip/ports to assign to domain, default is system-default-ips + * optional list of ip/ports to assign to domain, default is system-default-ips * @param int $subcanemaildomain - * optional, allow subdomains of this domain as email domains, 1 = choosable (default no), 2 = choosable (default yes), 3 = always, default 0 (never) + * optional, allow subdomains of this domain as email domains, 1 = choosable (default no), 2 = choosable + * (default yes), 3 = always, default 0 (never) * @param bool $isemaildomain - * optional, allow email usage with this domain, default 0 (false) + * optional, allow email usage with this domain, default 0 (false) * @param bool $email_only - * optional, restrict domain to email usage, default 0 (false) + * optional, restrict domain to email usage, default 0 (false) * @param int $selectserveralias - * optional, 0 = wildcard, 1 = www-alias, 2 = none, default [system.domaindefaultalias] + * optional, 0 = wildcard, 1 = www-alias, 2 = none, default [system.domaindefaultalias] * @param bool $speciallogfile - * optional, whether to create an exclusive web-logfile for this domain, default 0 (false) + * optional, whether to create an exclusive web-logfile for this domain, default 0 (false) * @param int $alias - * optional, domain-id of a domain that the new domain should be an alias of, default 0 (none) + * optional, domain-id of a domain that the new domain should be an alias of, default 0 (none) * @param int $issubof - * optional, domain-id of a domain this domain is a subdomain of (required for webserver-cronjob to generate the correct order), default 0 (none) + * optional, domain-id of a domain this domain is a subdomain of (required for webserver-cronjob to + * generate the correct order), default 0 (none) * @param string $registration_date - * optional, date of domain registration in form of YYYY-MM-DD, default empty (none) + * optional, date of domain registration in form of YYYY-MM-DD, default empty (none) * @param string $termination_date - * optional, date of domain termination in form of YYYY-MM-DD, default empty (none) + * optional, date of domain termination in form of YYYY-MM-DD, default empty (none) * @param bool $caneditdomain - * optional, whether to allow the customer to edit domain settings, default 0 (false) + * optional, whether to allow the customer to edit domain settings, default 0 (false) * @param bool $isbinddomain - * optional, whether to generate a dns-zone or not (only of nameserver is activated), default 0 (false) + * optional, whether to generate a dns-zone or not (only of nameserver is activated), default 0 (false) * @param string $zonefile - * optional, custom dns zone filename (only of nameserver is activated), default empty (auto-generated) + * optional, custom dns zone filename (only of nameserver is activated), default empty (auto-generated) * @param bool $dkim - * optional, currently not in use, default 0 (false) + * optional, currently not in use, default 0 (false) * @param string $specialsettings - * optional, custom webserver vhost-content which is added to the generated vhost, default empty + * optional, custom webserver vhost-content which is added to the generated vhost, default empty * @param string $ssl_specialsettings - * optional, custom webserver vhost-content which is added to the generated ssl-vhost, default empty + * optional, custom webserver vhost-content which is added to the generated ssl-vhost, default empty * @param bool $include_specialsettings - * optional, whether or not to include non-ssl specialsettings in the generated ssl-vhost, default false + * optional, whether or not to include non-ssl specialsettings in the generated ssl-vhost, default false * @param bool $notryfiles - * optional, [nginx only] do not generate the default try-files directive, default 0 (false) + * optional, [nginx only] do not generate the default try-files directive, default 0 (false) * @param bool $writeaccesslog - * optional, Enable writing an access-log file for this domain, default 1 (true) + * optional, Enable writing an access-log file for this domain, default 1 (true) * @param bool $writeerrorlog - * optional, Enable writing an error-log file for this domain, default 1 (true) + * optional, Enable writing an error-log file for this domain, default 1 (true) * @param string $documentroot - * optional, specify homedir of domain by specifying a directory (relative to customer-docroot), be aware, if path starts with / it it considered a full path, not relative to customer-docroot. Also specifying a URL is possible here (redirect), default empty (autogenerated) + * optional, specify homedir of domain by specifying a directory (relative to customer-docroot), be + * aware, if path starts with / it it considered a full path, not relative to customer-docroot. Also + * specifying a URL is possible here (redirect), default empty (autogenerated) * @param bool $phpenabled - * optional, whether php is enabled for this domain, default 0 (false) + * optional, whether php is enabled for this domain, default 0 (false) * @param bool $openbasedir - * optional, whether to activate openbasedir restriction for this domain, default 0 (false) + * optional, whether to activate openbasedir restriction for this domain, default 0 (false) * @param int $phpsettingid - * optional, specify php-configuration that is being used by id, default 1 (system-default) + * optional, specify php-configuration that is being used by id, default 1 (system-default) * @param int $mod_fcgid_starter - * optional number of fcgid-starters if FCGID is used, default is -1 + * optional number of fcgid-starters if FCGID is used, default is -1 * @param int $mod_fcgid_maxrequests - * optional number of fcgid-maxrequests if FCGID is used, default is -1 + * optional number of fcgid-maxrequests if FCGID is used, default is -1 * @param bool $ssl_redirect - * optional, whether to generate a https-redirect or not, default false; requires SSL to be enabled + * optional, whether to generate a https-redirect or not, default false; requires SSL to be enabled * @param bool $letsencrypt - * optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires SSL to be enabled + * optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires + * SSL to be enabled * @param array $ssl_ipandport - * optional, list of ssl-enabled ip/port id's to assign to this domain, default empty + * optional, list of ssl-enabled ip/port id's to assign to this domain, default empty * @param bool $dont_use_default_ssl_ipandport_if_empty - * optional, do NOT set the systems default ssl ip addresses if none are given via $ssl_ipandport parameter + * optional, do NOT set the systems default ssl ip addresses if none are given via $ssl_ipandport + * parameter * @param bool $sslenabled - * optional, whether or not SSL is enabled for this domain, regardless of the assigned ssl-ips, default 1 (true) + * optional, whether or not SSL is enabled for this domain, regardless of the assigned ssl-ips, default + * 1 (true) * @param bool $http2 - * optional, whether to enable http/2 for this domain (requires to be enabled in the settings), default 0 (false) + * optional, whether to enable http/2 for this domain (requires to be enabled in the settings), default + * 0 (false) * @param int $hsts_maxage - * optional max-age value for HSTS header + * optional max-age value for HSTS header * @param bool $hsts_sub - * optional whether or not to add subdomains to the HSTS header + * optional whether or not to add subdomains to the HSTS header * @param bool $hsts_preload - * optional whether or not to preload HSTS header value + * optional whether or not to preload HSTS header value * @param bool $ocsp_stapling - * optional whether to enable ocsp-stapling for this domain. default 0 (false), requires SSL + * optional whether to enable ocsp-stapling for this domain. default 0 (false), requires SSL * @param bool $honorcipherorder - * optional whether to honor the (server) cipher order for this domain. default 0 (false), requires SSL + * optional whether to honor the (server) cipher order for this domain. default 0 (false), requires SSL * @param bool $sessiontickets - * optional whether to enable or disable TLS sessiontickets (RFC 5077) for this domain. default 1 (true), requires SSL + * optional whether to enable or disable TLS sessiontickets (RFC 5077) for this domain. default 1 + * (true), requires SSL * @param bool $override_tls - * optional whether or not to override system-tls settings like protocol, ssl-ciphers and if applicable tls-1.3 ciphers, requires change_serversettings flag for the admin, default false + * optional whether or not to override system-tls settings like protocol, ssl-ciphers and if applicable + * tls-1.3 ciphers, requires change_serversettings flag for the admin, default false * @param array $ssl_protocols - * optional list of allowed/used ssl/tls protocols, see system.ssl_protocols setting, only used/required if $override_tls is true, default empty or system.ssl_protocols setting if $override_tls is true + * optional list of allowed/used ssl/tls protocols, see system.ssl_protocols setting, only used/required + * if $override_tls is true, default empty or system.ssl_protocols setting if $override_tls is true * @param string $ssl_cipher_list - * optional list of allowed/used ssl/tls ciphers, see system.ssl_cipher_list setting, only used/required if $override_tls is true, default empty or system.ssl_cipher_list setting if $override_tls is true + * optional list of allowed/used ssl/tls ciphers, see system.ssl_cipher_list setting, only used/required + * if $override_tls is true, default empty or system.ssl_cipher_list setting if $override_tls is true * @param string $tlsv13_cipher_list - * optional list of allowed/used tls-1.3 specific ciphers, see system.tlsv13_cipher_list setting, only used/required if $override_tls is true, default empty or system.tlsv13_cipher_list setting if $override_tls is true + * optional list of allowed/used tls-1.3 specific ciphers, see system.tlsv13_cipher_list setting, only + * used/required if $override_tls is true, default empty or system.tlsv13_cipher_list setting if + * $override_tls is true * @param string $description - * optional custom description (currently not used/shown in the frontend), default empty + * optional custom description (currently not used/shown in the frontend), default empty * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function add() { if ($this->isAdmin()) { if ($this->getUserDetail('domains_used') < $this->getUserDetail('domains') || $this->getUserDetail('domains') == '-1') { - // parameters $p_domain = $this->getParam('domain'); @@ -350,12 +312,12 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $phpenabled = $this->getBoolParam('phpenabled', true, 0); $openbasedir = $this->getBoolParam('openbasedir', true, 0); $phpsettingid = $this->getParam('phpsettingid', true, 1); - $mod_fcgid_starter = $this->getParam('mod_fcgid_starter', true, - 1); - $mod_fcgid_maxrequests = $this->getParam('mod_fcgid_maxrequests', true, - 1); + $mod_fcgid_starter = $this->getParam('mod_fcgid_starter', true, -1); + $mod_fcgid_maxrequests = $this->getParam('mod_fcgid_maxrequests', true, -1); $ssl_redirect = $this->getBoolParam('ssl_redirect', true, 0); $letsencrypt = $this->getBoolParam('letsencrypt', true, 0); $dont_use_default_ssl_ipandport_if_empty = $this->getBoolParam('dont_use_default_ssl_ipandport_if_empty', true, 0); - $p_ssl_ipandports = $this->getParam('ssl_ipandport', true, $dont_use_default_ssl_ipandport_if_empty ? array() : explode(',', Settings::Get('system.defaultsslip'))); + $p_ssl_ipandports = $this->getParam('ssl_ipandport', true, $dont_use_default_ssl_ipandport_if_empty ? [] : explode(',', Settings::Get('system.defaultsslip'))); $sslenabled = $this->getBoolParam('sslenabled', true, 1); $http2 = $this->getBoolParam('http2', true, 0); $hsts_maxage = $this->getParam('hsts_maxage', true, 0); @@ -366,7 +328,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $sessiontickets = $this->getBoolParam('sessiontickets', true, 1); $override_tls = $this->getBoolParam('override_tls', true, 0); - $p_ssl_protocols = array(); + $p_ssl_protocols = []; $ssl_cipher_list = ""; $tlsv13_cipher_list = ""; @@ -382,25 +344,25 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn // validation $p_domain = strtolower($p_domain); if ($p_domain == strtolower(Settings::Get('system.hostname'))) { - \Froxlor\UI\Response::standard_error('admin_domain_emailsystemhostname', '', true); + Response::standardError('admin_domain_emailsystemhostname', '', true); } if (substr($p_domain, 0, 4) == 'xn--') { - \Froxlor\UI\Response::standard_error('domain_nopunycode', '', true); + Response::standardError('domain_nopunycode', '', true); } - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); - $domain = $idna_convert->encode(preg_replace(array( + $idna_convert = new IdnaWrapper(); + $domain = $idna_convert->encode(preg_replace([ '/\:(\d)+$/', '/^https?\:\/\//' - ), '', \Froxlor\Validate\Validate::validate($p_domain, 'domain'))); + ], '', Validate::validate($p_domain, 'domain'))); // Check whether domain validation is enabled and if, validate the domain - if (Settings::Get('system.validate_domain') && ! \Froxlor\Validate\Validate::validateDomain($domain)) { - \Froxlor\UI\Response::standard_error(array( + if (Settings::Get('system.validate_domain') && !Validate::validateDomain($domain)) { + Response::standardError([ 'stringiswrong', 'mydomain' - ), '', true); + ], '', true); } $customer = $this->getCustomerData(); @@ -410,11 +372,11 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $admin_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_ADMINS . "` WHERE `adminid` = :adminid AND (`domains_used` < `domains` OR `domains` = '-1')"); - $admin = Database::pexecute_first($admin_stmt, array( + $admin = Database::pexecute_first($admin_stmt, [ 'adminid' => $adminid - ), true, true); + ], true, true); if (empty($admin)) { - \Froxlor\UI\Response::dynamic_error("Selected admin cannot have any more domains or could not be found"); + Response::dynamicError("Selected admin cannot have any more domains or could not be found"); } unset($admin); } @@ -425,69 +387,69 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn if (Settings::Get('system.documentroot_use_default_value') == 1) { $path_suffix = '/' . $domain; } - $_documentroot = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . $path_suffix); + $_documentroot = FileDir::makeCorrectDir($customer['documentroot'] . $path_suffix); - $documentroot = \Froxlor\Validate\Validate::validate($documentroot, 'documentroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true); + $documentroot = Validate::validate($documentroot, 'documentroot', Validate::REGEX_DIR, '', [], true); // If path is empty and 'Use domain name as default value for DocumentRoot path' is enabled in settings, // set default path to subdomain or domain name - if (! empty($documentroot)) { - if (substr($documentroot, 0, 1) != '/' && ! preg_match('/^https?\:\/\//', $documentroot)) { + if (!empty($documentroot)) { + if (substr($documentroot, 0, 1) != '/' && !preg_match('/^https?\:\/\//', $documentroot)) { $documentroot = $_documentroot . '/' . $documentroot; } elseif (substr($documentroot, 0, 1) == '/' && $this->getUserDetail('change_serversettings') != '1') { - \Froxlor\UI\Response::standard_error('pathmustberelative', '', true); + Response::standardError('pathmustberelative', '', true); } } else { $documentroot = $_documentroot; } - $registration_date = \Froxlor\Validate\Validate::validate($registration_date, 'registration_date', '/^(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])$/', '', array( + $registration_date = Validate::validate($registration_date, 'registration_date', '/^(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])$/', '', [ '0000-00-00', '0', '' - ), true); + ], true); if ($registration_date == '0000-00-00' || empty($registration_date)) { $registration_date = null; } - $termination_date = \Froxlor\Validate\Validate::validate($termination_date, 'termination_date', '/^(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])$/', '', array( + $termination_date = Validate::validate($termination_date, 'termination_date', '/^(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])$/', '', [ '0000-00-00', '0', '' - ), true); + ], true); if ($termination_date == '0000-00-00' || empty($termination_date)) { $termination_date = null; } if ($this->getUserDetail('change_serversettings') == '1') { if (Settings::Get('system.bind_enable') == '1') { - $zonefile = \Froxlor\Validate\Validate::validate($zonefile, 'zonefile', '', '', array(), true); + $zonefile = Validate::validate($zonefile, 'zonefile', '', '', [], true); } else { $isbinddomain = 0; $zonefile = ''; } - $specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $specialsettings), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true); + $specialsettings = Validate::validate(str_replace("\r\n", "\n", $specialsettings), 'specialsettings', Validate::REGEX_CONF_TEXT, '', [], true); - $ssl_protocols = array(); - if (! empty($p_ssl_protocols) && is_numeric($p_ssl_protocols)) { - $p_ssl_protocols = array( + $ssl_protocols = []; + if (!empty($p_ssl_protocols) && is_numeric($p_ssl_protocols)) { + $p_ssl_protocols = [ $p_ssl_protocols - ); + ]; } - if (! empty($p_ssl_protocols) && ! is_array($p_ssl_protocols)) { + if (!empty($p_ssl_protocols) && !is_array($p_ssl_protocols)) { $p_ssl_protocols = json_decode($p_ssl_protocols, true); } - if (! empty($p_ssl_protocols) && is_array($p_ssl_protocols)) { - $protocols_available = array( + if (!empty($p_ssl_protocols) && is_array($p_ssl_protocols)) { + $protocols_available = [ 'TLSv1', 'TLSv1.1', 'TLSv1.2', 'TLSv1.3' - ); + ]; foreach ($p_ssl_protocols as $ssl_protocol) { - if (! in_array(trim($ssl_protocol), $protocols_available)) { - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_DEBUG, "[API] unknown SSL protocol '" . trim($ssl_protocol) . "'"); + if (!in_array(trim($ssl_protocol), $protocols_available)) { + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_DEBUG, "[API] unknown SSL protocol '" . trim($ssl_protocol) . "'"); continue; } $ssl_protocols[] = $ssl_protocol; @@ -511,39 +473,37 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $writeaccesslog = '1'; $writeerrorlog = '1'; $override_tls = '0'; - $ssl_protocols = array(); + $ssl_protocols = []; } if ($this->getUserDetail('caneditphpsettings') == '1' || $this->getUserDetail('change_serversettings') == '1') { - - if ((int) Settings::Get('system.mod_fcgid') == 1 || (int) Settings::Get('phpfpm.enabled') == 1) { + if ((int)Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) { $phpsettingid_check_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `id` = :phpsettingid"); - $phpsettingid_check = Database::pexecute_first($phpsettingid_check_stmt, array( + $phpsettingid_check = Database::pexecute_first($phpsettingid_check_stmt, [ 'phpsettingid' => $phpsettingid - ), true, true); + ], true, true); - if (! isset($phpsettingid_check['id']) || $phpsettingid_check['id'] == '0' || $phpsettingid_check['id'] != $phpsettingid) { - \Froxlor\UI\Response::standard_error('phpsettingidwrong', '', true); + if (!isset($phpsettingid_check['id']) || $phpsettingid_check['id'] == '0' || $phpsettingid_check['id'] != $phpsettingid) { + Response::standardError('phpsettingidwrong', '', true); } - if ((int) Settings::Get('system.mod_fcgid') == 1) { - $mod_fcgid_starter = \Froxlor\Validate\Validate::validate($mod_fcgid_starter, 'mod_fcgid_starter', '/^[0-9]*$/', '', array( + if ((int)Settings::Get('system.mod_fcgid') == 1) { + $mod_fcgid_starter = Validate::validate($mod_fcgid_starter, 'mod_fcgid_starter', '/^[0-9]*$/', '', [ '-1', '' - ), true); - $mod_fcgid_maxrequests = \Froxlor\Validate\Validate::validate($mod_fcgid_maxrequests, 'mod_fcgid_maxrequests', '/^[0-9]*$/', '', array( + ], true); + $mod_fcgid_maxrequests = Validate::validate($mod_fcgid_maxrequests, 'mod_fcgid_maxrequests', '/^[0-9]*$/', '', [ '-1', '' - ), true); + ], true); } else { $mod_fcgid_starter = '-1'; $mod_fcgid_maxrequests = '-1'; } } else { - - if ((int) Settings::Get('phpfpm.enabled') == 1) { + if ((int)Settings::Get('phpfpm.enabled') == 1) { $phpsettingid = Settings::Get('phpfpm.defaultini'); } else { $phpsettingid = Settings::Get('system.mod_fcgid_defaultini'); @@ -552,11 +512,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $mod_fcgid_maxrequests = '-1'; } } else { - $phpenabled = '1'; $openbasedir = '1'; - if ((int) Settings::Get('phpfpm.enabled') == 1) { + if ((int)Settings::Get('phpfpm.enabled') == 1) { $phpsettingid = Settings::Get('phpfpm.defaultini'); } else { $phpsettingid = Settings::Get('system.mod_fcgid_defaultini'); @@ -568,12 +527,12 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn // check non-ssl IP $ipandports = $this->validateIpAddresses($p_ipandports); // check ssl IP - $ssl_ipandports = array(); - if (Settings::Get('system.use_ssl') == "1" && ! empty($p_ssl_ipandports)) { + $ssl_ipandports = []; + if (Settings::Get('system.use_ssl') == "1" && !empty($p_ssl_ipandports)) { $ssl_ipandports = $this->validateIpAddresses($p_ssl_ipandports, true); if ($this->getUserDetail('change_serversettings') == '1') { - $ssl_specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $ssl_specialsettings), 'ssl_specialsettings', '/^[^\0]*$/', '', array(), true); + $ssl_specialsettings = Validate::validate(str_replace("\r\n", "\n", $ssl_specialsettings), 'ssl_specialsettings', '/^[^\0]*$/', '', [], true); } } if (Settings::Get('system.use_ssl') == "0" || empty($ssl_ipandports)) { @@ -582,7 +541,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $http2 = 0; // we need this for the json_encode // if ssl is disabled or no ssl-ip/port exists - $ssl_ipandports[] = - 1; + $ssl_ipandports[] = -1; // HSTS $hsts_maxage = 0; @@ -599,16 +558,16 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn // validate dns if lets encrypt is enabled to check whether we can use it at all if ($letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') { - $domain_ips = \Froxlor\PhpHelper::gethostbynamel6($domain); + $domain_ips = PhpHelper::gethostbynamel6($domain); $selected_ips = $this->getIpsFromIdArray($ssl_ipandports); if ($domain_ips == false || count(array_intersect($selected_ips, $domain_ips)) <= 0) { - \Froxlor\UI\Response::standard_error('invaliddnsforletsencrypt', '', true); + Response::standardError('invaliddnsforletsencrypt', '', true); } } // We can't enable let's encrypt for wildcard-domains if ($serveraliasoption == '0' && $letsencrypt == '1') { - \Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt', '', true); + Response::standardError('nowildcardwithletsencrypt', '', true); } // Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated @@ -616,39 +575,39 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $ssl_redirect = 2; } - if (! preg_match('/^https?\:\/\//', $documentroot)) { + if (!preg_match('/^https?\:\/\//', $documentroot)) { if (strstr($documentroot, ":") !== false) { - \Froxlor\UI\Response::standard_error('pathmaynotcontaincolon', '', true); + Response::standardError('pathmaynotcontaincolon', '', true); } else { - $documentroot = \Froxlor\FileDir::makeCorrectDir($documentroot); + $documentroot = FileDir::makeCorrectDir($documentroot); } } $domain_check_stmt = Database::prepare(" SELECT `id`, `domain` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `domain` = :domain"); - $domain_check = Database::pexecute_first($domain_check_stmt, array( + $domain_check = Database::pexecute_first($domain_check_stmt, [ 'domain' => strtolower($domain) - ), true, true); - $aliasdomain_check = array( + ], true, true); + $aliasdomain_check = [ 'id' => 0 - ); + ]; if ($aliasdomain != 0) { // Overwrite given ipandports with these of the "main" domain - $ipandports = array(); - $ssl_ipandports = array(); + $ipandports = []; + $ssl_ipandports = []; $origipresult_stmt = Database::prepare(" SELECT `id_ipandports` FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :id"); - Database::pexecute($origipresult_stmt, array( + Database::pexecute($origipresult_stmt, [ 'id' => $aliasdomain - ), true, true); + ], true, true); $ipdata_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `id` = :ipid"); - while ($origip = $origipresult_stmt->fetch(\PDO::FETCH_ASSOC)) { - $_origip_tmp = Database::pexecute_first($ipdata_stmt, array( + while ($origip = $origipresult_stmt->fetch(PDO::FETCH_ASSOC)) { + $_origip_tmp = Database::pexecute_first($ipdata_stmt, [ 'ipid' => $origip['id_ipandports'] - ), true, true); + ], true, true); if ($_origip_tmp['ssl'] == 0) { $ipandports[] = $origip['id_ipandports']; } else { @@ -659,7 +618,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn if (count($ssl_ipandports) == 0) { // we need this for the json_encode // if ssl is disabled or no ssl-ip/port exists - $ssl_ipandports[] = - 1; + $ssl_ipandports[] = -1; } $aliasdomain_check_stmt = Database::prepare(" @@ -668,15 +627,15 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn AND `d`.`aliasdomain` IS NULL AND `d`.`id` <> `c`.`standardsubdomain` AND `c`.`customerid` = :customerid AND `d`.`id` = :aliasdomainid"); - $alias_params = array( + $alias_params = [ 'customerid' => $customerid, 'aliasdomainid' => $aliasdomain - ); + ]; $aliasdomain_check = Database::pexecute_first($aliasdomain_check_stmt, $alias_params, true, true); } if (count($ipandports) == 0) { - \Froxlor\UI\Response::standard_error('noipportgiven', '', true); + Response::standardError('noipportgiven', '', true); } if ($email_only == '1') { @@ -697,28 +656,28 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $issubof = '0'; } - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); + $idna_convert = new IdnaWrapper(); if ($domain == '') { - \Froxlor\UI\Response::standard_error(array( + Response::standardError([ 'stringisempty', 'mydomain' - ), '', true); + ], '', true); } elseif ($documentroot == '') { - \Froxlor\UI\Response::standard_error(array( + Response::standardError([ 'stringisempty', 'mydocumentroot' - ), '', true); + ], '', true); } elseif ($customerid == 0) { - \Froxlor\UI\Response::standard_error('adduserfirst', '', true); + Response::standardError('adduserfirst', '', true); } elseif ($domain_check && strtolower($domain_check['domain']) == strtolower($domain)) { - \Froxlor\UI\Response::standard_error('domainalreadyexists', $idna_convert->decode($domain), true); + Response::standardError('domainalreadyexists', $idna_convert->decode($domain), true); } elseif ($aliasdomain_check && $aliasdomain_check['id'] != $aliasdomain) { - \Froxlor\UI\Response::standard_error('domainisaliasorothercustomer', '', true); + Response::standardError('domainisaliasorothercustomer', '', true); } else { $wwwserveralias = ($serveraliasoption == '1') ? '1' : '0'; $iswildcarddomain = ($serveraliasoption == '0') ? '1' : '0'; - $ins_data = array( + $ins_data = [ 'domain' => $domain, 'domain_ace' => $idna_convert->decode($domain), 'customerid' => $customerid, @@ -765,7 +724,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn 'honorcipherorder' => $honorcipherorder, 'sessiontickets' => $sessiontickets, 'description' => $description - ); + ]; $ins_stmt = Database::prepare(" INSERT INTO `" . TABLE_PANEL_DOMAINS . "` SET @@ -827,9 +786,9 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_ADMINS . "` SET `domains_used` = `domains_used` + 1 WHERE `adminid` = :adminid"); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'adminid' => $adminid - ), true, true); + ], true, true); $ins_stmt = Database::prepare(" INSERT INTO `" . TABLE_DOMAINTOIP . "` SET @@ -838,169 +797,341 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn "); foreach ($ipandports as $ipportid) { - $ins_data = array( + $ins_data = [ 'domainid' => $domainid, 'ipandportsid' => $ipportid - ); + ]; Database::pexecute($ins_stmt, $ins_data, true, true); } foreach ($ssl_ipandports as $ssl_ipportid) { if ($ssl_ipportid > 0) { - $ins_data = array( + $ins_data = [ 'domainid' => $domainid, 'ipandportsid' => $ssl_ipportid - ); + ]; Database::pexecute($ins_stmt, $ins_data, true, true); } } - \Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger()); + Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger()); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + Cronjob::inserttask(TaskId::REBUILD_VHOST); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); + Cronjob::inserttask(TaskId::REBUILD_DNS); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added domain '" . $domain . "'"); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added domain '" . $domain . "'"); - $result = $this->apiCall('Domains.get', array( + $result = $this->apiCall('Domains.get', [ 'domainname' => $domain - )); + ]); return $this->response($result); } } - throw new \Exception("No more resources available", 406); + throw new Exception("No more resources available", 406); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); + } + + /** + * return a domain entry by either id or domainname + * + * @param int $id + * optional, the domain-id + * @param string $domainname + * optional, the domainname + * @param bool $with_ips + * optional, default true + * @param bool $no_std_subdomain + * optional, default false + * + * @access admin + * @return string json-encoded array + * @throws Exception + */ + public function get() + { + if ($this->isAdmin()) { + $id = $this->getParam('id', true, 0); + $dn_optional = $id > 0; + $domainname = $this->getParam('domainname', $dn_optional, ''); + $with_ips = $this->getParam('with_ips', true, true); + $no_std_subdomain = $this->getParam('no_std_subdomain', true, false); + + // convert possible idn domain to punycode + if (substr($domainname, 0, 4) != 'xn--') { + $idna_convert = new IdnaWrapper(); + $domainname = $idna_convert->encode($domainname); + } + + $result_stmt = Database::prepare(" + SELECT `d`.*, `c`.`customerid` + FROM `" . TABLE_PANEL_DOMAINS . "` `d` + LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`) + WHERE `d`.`parentdomainid` = '0' + AND " . ($id > 0 ? "`d`.`id` = :iddn" : "`d`.`domain` = :iddn") . ($no_std_subdomain ? ' AND `d`.`id` <> `c`.`standardsubdomain`' : '') . ($this->getUserDetail('customers_see_all') ? '' : " AND `d`.`adminid` = :adminid")); + $params = [ + 'iddn' => ($id <= 0 ? $domainname : $id) + ]; + if ($this->getUserDetail('customers_see_all') == '0') { + $params['adminid'] = $this->getUserDetail('adminid'); + } + $result = Database::pexecute_first($result_stmt, $params, true, true); + if ($result) { + $result['ipsandports'] = []; + if ($with_ips) { + $result['ipsandports'] = $this->getIpsForDomain($result['id']); + } + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get domain '" . $result['domain'] . "'"); + return $this->response($result); + } + $key = ($id > 0 ? "id #" . $id : "domainname '" . $domainname . "'"); + throw new Exception("Domain with " . $key . " could not be found", 404); + } + throw new Exception("Not allowed to execute given command.", 403); + } + + /** + * validate given ips + * + * @param int|string|array $p_ipandports + * @param boolean $ssl + * default false + * @param int $edit_id + * default 0 + * + * @return array + * @throws Exception + */ + private function validateIpAddresses($p_ipandports = null, $ssl = false, $edit_id = 0) + { + // when adding a new domain and no ip is given, we try to use the + // system-default, check here if there is none + // this is not required for ssl-enabled ip's + if ($edit_id <= 0 && !$ssl && empty($p_ipandports)) { + throw new Exception("No IPs given, unable to add domain (no default IPs set?)", 406); + } + + // convert given value(s) correctly + $ipandports = []; + if (!empty($p_ipandports) && is_numeric($p_ipandports)) { + $p_ipandports = [ + $p_ipandports + ]; + } + if (!empty($p_ipandports) && !is_array($p_ipandports)) { + $p_ipandports = json_decode($p_ipandports, true); + } + + // check whether there are ip usage restrictions + $additional_ip_condition = ''; + $aip_param = []; + if ($this->getUserDetail('ip') != "-1") { + // handle multiple-ip-array + $additional_ip_condition = " AND `ip` IN (" . implode(",", json_decode($this->getUserDetail('ip'), true)) . ") "; + } + + if (!empty($p_ipandports) && is_array($p_ipandports)) { + $ipandport_check_stmt = Database::prepare(" + SELECT `id`, `ip`, `port` + FROM `" . TABLE_PANEL_IPSANDPORTS . "` + WHERE `id` = :ipandport " . ($ssl ? " AND `ssl` = '1'" : "") . $additional_ip_condition); + foreach ($p_ipandports as $ipandport) { + if (trim($ipandport) == "") { + continue; + } + // fix if no ip/port is checked + if (trim($ipandport) < 1) { + continue; + } + $ipandport = intval($ipandport); + $ip_params = array_merge([ + 'ipandport' => $ipandport + ], $aip_param); + $ipandport_check = Database::pexecute_first($ipandport_check_stmt, $ip_params, true, true); + if (!isset($ipandport_check['id']) || $ipandport_check['id'] == '0' || $ipandport_check['id'] != $ipandport) { + Response::standardError('ipportdoesntexist', '', true); + } else { + $ipandports[] = $ipandport; + } + } + } elseif ($edit_id > 0) { + // set currently used ip's + $ipsresult_stmt = Database::prepare(" + SELECT d2i.`id_ipandports` + FROM `" . TABLE_DOMAINTOIP . "` d2i + LEFT JOIN `" . TABLE_PANEL_IPSANDPORTS . "` i ON i.id = d2i.id_ipandports + WHERE d2i.`id_domain` = :id AND i.`ssl` = " . ($ssl ? "'1'" : "'0'")); + Database::pexecute($ipsresult_stmt, [ + 'id' => $edit_id + ], true, true); + while ($ipsresultrow = $ipsresult_stmt->fetch(PDO::FETCH_ASSOC)) { + $ipandports[] = $ipsresultrow['id_ipandports']; + } + } + return $ipandports; + } + + /** + * get ips from array of id's + * + * @param array $ips + * @return array + */ + private function getIpsFromIdArray(array $ids) + { + $resultips_stmt = Database::prepare(" + SELECT `ip` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE id = :id + "); + $result = []; + foreach ($ids as $id) { + $entry = Database::pexecute_first($resultips_stmt, [ + 'id' => $id + ]); + $result[] = $entry['ip']; + } + return $result; } /** * update domain entry by either id or domainname * * @param int $id - * optional, the domain-id + * optional, the domain-id * @param string $domainname - * optional, the domainname + * optional, the domainname * @param int $customerid - * required (if $loginname is not specified) + * required (if $loginname is not specified) * @param string $loginname - * required (if $customerid is not specified) + * required (if $customerid is not specified) * @param int $adminid - * optional, default is the calling admin's ID + * optional, default is the calling admin's ID * @param array $ipandport - * optional list of ip/ports to assign to domain, default is system-default-ips + * optional list of ip/ports to assign to domain, default is system-default-ips * @param int $subcanemaildomain - * optional, allow subdomains of this domain as email domains, 1 = choosable (default no), 2 = choosable (default yes), 3 = always, default 0 (never) + * optional, allow subdomains of this domain as email domains, 1 = choosable (default no), 2 = choosable + * (default yes), 3 = always, default 0 (never) * @param bool $isemaildomain - * optional, allow email usage with this domain, default 0 (false) + * optional, allow email usage with this domain, default 0 (false) * @param bool $email_only - * optional, restrict domain to email usage, default 0 (false) + * optional, restrict domain to email usage, default 0 (false) * @param int $selectserveralias - * optional, 0 = wildcard, 1 = www-alias, 2 = none, default 0 + * optional, 0 = wildcard, 1 = www-alias, 2 = none, default 0 * @param bool $speciallogfile - * optional, whether to create an exclusive web-logfile for this domain, default 0 (false) + * optional, whether to create an exclusive web-logfile for this domain, default 0 (false) * @param bool $speciallogverified - * optional, when setting $speciallogfile to false, this needs to be set to true to confirm the action, default 0 (false) + * optional, when setting $speciallogfile to false, this needs to be set to true to confirm the action, + * default 0 (false) * @param int $alias - * optional, domain-id of a domain that the new domain should be an alias of, default 0 (none) + * optional, domain-id of a domain that the new domain should be an alias of, default 0 (none) * @param int $issubof - * optional, domain-id of a domain this domain is a subdomain of (required for webserver-cronjob to generate the correct order), default 0 (none) + * optional, domain-id of a domain this domain is a subdomain of (required for webserver-cronjob to + * generate the correct order), default 0 (none) * @param string $registration_date - * optional, date of domain registration in form of YYYY-MM-DD, default empty (none) + * optional, date of domain registration in form of YYYY-MM-DD, default empty (none) * @param string $termination_date - * optional, date of domain termination in form of YYYY-MM-DD, default empty (none) + * optional, date of domain termination in form of YYYY-MM-DD, default empty (none) * @param bool $caneditdomain - * optional, whether to allow the customer to edit domain settings, default 0 (false) + * optional, whether to allow the customer to edit domain settings, default 0 (false) * @param bool $isbinddomain - * optional, whether to generate a dns-zone or not (only of nameserver is activated), default 0 (false) + * optional, whether to generate a dns-zone or not (only of nameserver is activated), default 0 (false) * @param string $zonefile - * optional, custom dns zone filename (only of nameserver is activated), default empty (auto-generated) + * optional, custom dns zone filename (only of nameserver is activated), default empty (auto-generated) * @param bool $dkim - * optional, currently not in use, default 0 (false) + * optional, currently not in use, default 0 (false) * @param string $specialsettings - * optional, custom webserver vhost-content which is added to the generated vhost, default empty + * optional, custom webserver vhost-content which is added to the generated vhost, default empty * @param string $ssl_specialsettings - * optional, custom webserver vhost-content which is added to the generated ssl-vhost, default empty + * optional, custom webserver vhost-content which is added to the generated ssl-vhost, default empty * @param bool $include_specialsettings - * optional, whether or not to include non-ssl specialsettings in the generated ssl-vhost, default false + * optional, whether or not to include non-ssl specialsettings in the generated ssl-vhost, default false * @param bool $specialsettingsforsubdomains - * optional, whether to apply specialsettings to all subdomains of this domain, default is read from setting system.apply_specialsettings_default + * optional, whether to apply specialsettings to all subdomains of this domain, default is read from + * setting system.apply_specialsettings_default * @param bool $notryfiles - * optional, [nginx only] do not generate the default try-files directive, default 0 (false) + * optional, [nginx only] do not generate the default try-files directive, default 0 (false) * @param bool $writeaccesslog - * optional, Enable writing an access-log file for this domain, default 1 (true) + * optional, Enable writing an access-log file for this domain, default 1 (true) * @param bool $writeerrorlog - * optional, Enable writing an error-log file for this domain, default 1 (true) + * optional, Enable writing an error-log file for this domain, default 1 (true) * @param string $documentroot - * optional, specify homedir of domain by specifying a directory (relative to customer-docroot), be aware, if path starts with / it it considered a full path, not relative to customer-docroot. Also specifying a URL is possible here (redirect), default empty (autogenerated) + * optional, specify homedir of domain by specifying a directory (relative to customer-docroot), be + * aware, if path starts with / it it considered a full path, not relative to customer-docroot. Also + * specifying a URL is possible here (redirect), default empty (autogenerated) * @param bool $phpenabled - * optional, whether php is enabled for this domain, default 0 (false) + * optional, whether php is enabled for this domain, default 0 (false) * @param bool $phpsettingsforsubdomains - * optional, whether to apply php-setting to apply to all subdomains of this domain, default is read from setting system.apply_phpconfigs_default + * optional, whether to apply php-setting to apply to all subdomains of this domain, default is read + * from setting system.apply_phpconfigs_default * @param bool $openbasedir - * optional, whether to activate openbasedir restriction for this domain, default 0 (false) + * optional, whether to activate openbasedir restriction for this domain, default 0 (false) * @param int $phpsettingid - * optional, specify php-configuration that is being used by id, default 1 (system-default) + * optional, specify php-configuration that is being used by id, default 1 (system-default) * @param int $mod_fcgid_starter - * optional number of fcgid-starters if FCGID is used, default is -1 + * optional number of fcgid-starters if FCGID is used, default is -1 * @param int $mod_fcgid_maxrequests - * optional number of fcgid-maxrequests if FCGID is used, default is -1 + * optional number of fcgid-maxrequests if FCGID is used, default is -1 * @param bool $ssl_redirect - * optional, whether to generate a https-redirect or not, default false; requires SSL to be enabled + * optional, whether to generate a https-redirect or not, default false; requires SSL to be enabled * @param bool $letsencrypt - * optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires SSL to be enabled + * optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires + * SSL to be enabled * @param array $ssl_ipandport - * optional, list of ssl-enabled ip/port id's to assign to this domain, if left empty, the current set value is being used, to remove all ssl ips use $remove_ssl_ipandport + * optional, list of ssl-enabled ip/port id's to assign to this domain, if left empty, the current set + * value is being used, to remove all ssl ips use $remove_ssl_ipandport * @param bool $remove_ssl_ipandport - * optional, if set to true and no $ssl_ipandport value is given, the ip's get removed, otherwise, the currently set value is used, default false + * optional, if set to true and no $ssl_ipandport value is given, the ip's get removed, otherwise, the + * currently set value is used, default false * @param bool $sslenabled - * optional, whether or not SSL is enabled for this domain, regardless of the assigned ssl-ips, default 1 (true) + * optional, whether or not SSL is enabled for this domain, regardless of the assigned ssl-ips, default + * 1 (true) * @param bool $http2 - * optional, whether to enable http/2 for this domain (requires to be enabled in the settings), default 0 (false) + * optional, whether to enable http/2 for this domain (requires to be enabled in the settings), default + * 0 (false) * @param int $hsts_maxage - * optional max-age value for HSTS header + * optional max-age value for HSTS header * @param bool $hsts_sub - * optional whether or not to add subdomains to the HSTS header + * optional whether or not to add subdomains to the HSTS header * @param bool $hsts_preload - * optional whether or not to preload HSTS header value + * optional whether or not to preload HSTS header value * @param bool $ocsp_stapling - * optional whether to enable ocsp-stapling for this domain. default 0 (false), requires SSL + * optional whether to enable ocsp-stapling for this domain. default 0 (false), requires SSL * @param bool $honorcipherorder - * optional whether to honor the (server) cipher order for this domain. default 0 (false), requires SSL + * optional whether to honor the (server) cipher order for this domain. default 0 (false), requires SSL * @param bool $sessiontickets - * optional whether to enable or disable TLS sessiontickets (RFC 5077) for this domain. default 1 (true), requires SSL + * optional whether to enable or disable TLS sessiontickets (RFC 5077) for this domain. default 1 + * (true), requires SSL * @param string $description - * optional custom description (currently not used/shown in the frontend), default empty + * optional custom description (currently not used/shown in the frontend), default empty * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function update() { if ($this->isAdmin()) { - // parameters $id = $this->getParam('id', true, 0); $dn_optional = $id > 0; $domainname = $this->getParam('domainname', $dn_optional, ''); // get requested domain - $result = $this->apiCall('Domains.get', array( + $result = $this->apiCall('Domains.get', [ 'id' => $id, 'domainname' => $domainname - )); + ]); $id = $result['id']; // optional parameters - $p_ipandports = $this->getParam('ipandport', true, array()); + $p_ipandports = $this->getParam('ipandport', true, []); $adminid = intval($this->getParam('adminid', true, $result['adminid'])); if ($this->getParam('customerid', true, 0) == 0 && $this->getParam('loginname', true, '') == '') { $customerid = $result['customerid']; - $customer = $this->apiCall('Customers.get', array( + $customer = $this->apiCall('Customers.get', [ 'id' => $customerid - )); + ]); } else { $customer = $this->getCustomerData(); $customerid = $customer['customerid']; @@ -1009,7 +1140,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $subcanemaildomain = $this->getParam('subcanemaildomain', true, $result['subcanemaildomain']); $isemaildomain = $this->getBoolParam('isemaildomain', true, $result['isemaildomain']); $email_only = $this->getBoolParam('email_only', true, $result['email_only']); - $p_serveraliasoption = $this->getParam('selectserveralias', true, - 1); + $p_serveraliasoption = $this->getParam('selectserveralias', true, -1); $speciallogfile = $this->getBoolParam('speciallogfile', true, $result['speciallogfile']); $speciallogverified = $this->getBoolParam('speciallogverified', true, 0); $aliasdomain = intval($this->getParam('alias', true, $result['aliasdomain'])); @@ -1023,13 +1154,13 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $specialsettings = $this->getParam('specialsettings', true, $result['specialsettings']); $ssl_specialsettings = $this->getParam('ssl_specialsettings', true, $result['ssl_specialsettings']); $include_specialsettings = $this->getBoolParam('include_specialsettings', true, $result['include_specialsettings']); - $ssfs = $this->getBoolParam('specialsettingsforsubdomains', true, \Froxlor\Settings::Get('system.apply_specialsettings_default')); + $ssfs = $this->getBoolParam('specialsettingsforsubdomains', true, Settings::Get('system.apply_specialsettings_default')); $notryfiles = $this->getBoolParam('notryfiles', true, $result['notryfiles']); $writeaccesslog = $this->getBoolParam('writeaccesslog', true, $result['writeaccesslog']); $writeerrorlog = $this->getBoolParam('writeerrorlog', true, $result['writeerrorlog']); $documentroot = $this->getParam('documentroot', true, $result['documentroot']); $phpenabled = $this->getBoolParam('phpenabled', true, $result['phpenabled']); - $phpfs = $this->getBoolParam('phpsettingsforsubdomains', true, \Froxlor\Settings::Get('system.apply_phpconfigs_default')); + $phpfs = $this->getBoolParam('phpsettingsforsubdomains', true, Settings::Get('system.apply_phpconfigs_default')); $openbasedir = $this->getBoolParam('openbasedir', true, $result['openbasedir']); $phpsettingid = $this->getParam('phpsettingid', true, $result['phpsettingid']); $mod_fcgid_starter = $this->getParam('mod_fcgid_starter', true, $result['mod_fcgid_starter']); @@ -1037,9 +1168,9 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $ssl_redirect = $this->getBoolParam('ssl_redirect', true, $result['ssl_redirect']); $letsencrypt = $this->getBoolParam('letsencrypt', true, $result['letsencrypt']); $remove_ssl_ipandport = $this->getBoolParam('remove_ssl_ipandport', true, 0); - $p_ssl_ipandports = $this->getParam('ssl_ipandport', true, $remove_ssl_ipandport ? array( - - 1 - ) : null); + $p_ssl_ipandports = $this->getParam('ssl_ipandport', true, $remove_ssl_ipandport ? [ + -1 + ] : null); $sslenabled = $this->getBoolParam('sslenabled', true, $result['ssl_enabled']); $http2 = $this->getBoolParam('http2', true, $result['http2']); $hsts_maxage = $this->getParam('hsts_maxage', true, $result['hsts']); @@ -1057,7 +1188,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $ssl_cipher_list = $this->getParam('ssl_cipher_list', true, $result['ssl_cipher_list']); $tlsv13_cipher_list = $this->getParam('tlsv13_cipher_list', true, $result['tlsv13_cipher_list']); } else { - $p_ssl_protocols = array(); + $p_ssl_protocols = []; $ssl_cipher_list = ""; $tlsv13_cipher_list = ""; } @@ -1073,9 +1204,9 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn SELECT COUNT(`id`) AS count FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `parentdomainid` = :resultid "); - $subdomains = Database::pexecute_first($subdomains_stmt, array( + $subdomains = Database::pexecute_first($subdomains_stmt, [ 'resultid' => $result['id'] - ), true, true); + ], true, true); $subdomains = $subdomains['count']; // count where this domain is alias domain @@ -1083,9 +1214,9 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn SELECT COUNT(`id`) AS count FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `aliasdomain` = :resultid "); - $alias_check = Database::pexecute_first($alias_check_stmt, array( + $alias_check = Database::pexecute_first($alias_check_stmt, [ 'resultid' => $result['id'] - ), true, true); + ], true, true); $alias_check = $alias_check['count']; // count where we are used in email-accounts @@ -1093,22 +1224,22 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn SELECT `email`, `email_full`, `destination`, `popaccountid` AS `number_email_forwarders` FROM `" . TABLE_MAIL_VIRTUAL . "` WHERE `customerid` = :customerid AND `domainid` = :id "); - Database::pexecute($domain_emails_result_stmt, array( + Database::pexecute($domain_emails_result_stmt, [ 'customerid' => $result['customerid'], 'id' => $result['id'] - ), true, true); + ], true, true); $emails = Database::num_rows(); $email_forwarders = 0; $email_accounts = 0; - while ($domain_emails_row = $domain_emails_result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($domain_emails_row = $domain_emails_result_stmt->fetch(PDO::FETCH_ASSOC)) { if ($domain_emails_row['destination'] != '') { - $domain_emails_row['destination'] = explode(' ', \Froxlor\FileDir::makeCorrectDestination($domain_emails_row['destination'])); + $domain_emails_row['destination'] = explode(' ', FileDir::makeCorrectDestination($domain_emails_row['destination'])); $email_forwarders += count($domain_emails_row['destination']); if (in_array($domain_emails_row['email_full'], $domain_emails_row['destination'])) { $email_forwarders -= 1; - $email_accounts ++; + $email_accounts++; } } } @@ -1123,37 +1254,35 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn AND (`emails_used` + :emails <= `emails` OR `emails` = '-1' ) AND (`email_forwarders_used` + :forwarders <= `email_forwarders` OR `email_forwarders` = '-1' ) AND (`email_accounts_used` + :accounts <= `email_accounts` OR `email_accounts` = '-1' ) " . ($this->getUserDetail('customers_see_all') ? '' : " AND `adminid` = :adminid")); - $params = array( + $params = [ 'customerid' => $customerid, 'subdomains' => $subdomains, 'emails' => $emails, 'forwarders' => $email_forwarders, 'accounts' => $email_accounts - ); + ]; if ($this->getUserDetail('customers_see_all') == '0') { $params['adminid'] = $this->getUserDetail('adminid'); } $customer = Database::pexecute_first($customer_stmt, $params, true, true); if (empty($customer) || $customer['customerid'] != $customerid) { - \Froxlor\UI\Response::standard_error('customerdoesntexist', '', true); + Response::standardError('customerdoesntexist', '', true); } } // handle change of admin (move domain from admin to admin) if ($this->getUserDetail('customers_see_all') == '1') { - if ($adminid > 0 && $adminid != $result['adminid'] && Settings::Get('panel.allow_domain_change_admin') == '1') { - $admin_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_ADMINS . "` WHERE `adminid` = :adminid AND ( `domains_used` < `domains` OR `domains` = '-1' ) "); - $admin = Database::pexecute_first($admin_stmt, array( + $admin = Database::pexecute_first($admin_stmt, [ 'adminid' => $adminid - ), true, true); + ], true, true); if (empty($admin) || $admin['adminid'] != $adminid) { - \Froxlor\UI\Response::standard_error('admindoesntexist', '', true); + Response::standardError('admindoesntexist', '', true); } } else { $adminid = $result['adminid']; @@ -1162,19 +1291,19 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $adminid = $result['adminid']; } - $registration_date = \Froxlor\Validate\Validate::validate($registration_date, 'registration_date', '/^(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])$/', '', array( + $registration_date = Validate::validate($registration_date, 'registration_date', '/^(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])$/', '', [ '0000-00-00', '0', '' - ), true); + ], true); if ($registration_date == '0000-00-00' || empty($registration_date)) { $registration_date = null; } - $termination_date = \Froxlor\Validate\Validate::validate($termination_date, 'termination_date', '/^(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])$/', '', array( + $termination_date = Validate::validate($termination_date, 'termination_date', '/^(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])$/', '', [ '0000-00-00', '0', '' - ), true); + ], true); if ($termination_date == '0000-00-00' || empty($termination_date)) { $termination_date = null; } @@ -1185,21 +1314,21 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn } elseif ($result['wwwserveralias'] == '1') { $serveraliasoption = '1'; } - if ($p_serveraliasoption > - 1) { + if ($p_serveraliasoption > -1) { $serveraliasoption = $p_serveraliasoption; } - $documentroot = \Froxlor\Validate\Validate::validate($documentroot, 'documentroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true); + $documentroot = Validate::validate($documentroot, 'documentroot', Validate::REGEX_DIR, '', [], true); - if (! empty($documentroot) && $documentroot != $result['documentroot'] && substr($documentroot, 0, 1) == '/' && substr($documentroot, 0, strlen($customer['documentroot'])) != $customer['documentroot'] && $this->getUserDetail('change_serversettings') != '1') { - \Froxlor\UI\Response::standard_error('pathmustberelative', '', true); + if (!empty($documentroot) && $documentroot != $result['documentroot'] && substr($documentroot, 0, 1) == '/' && substr($documentroot, 0, strlen($customer['documentroot'])) != $customer['documentroot'] && $this->getUserDetail('change_serversettings') != '1') { + Response::standardError('pathmustberelative', '', true); } // when moving customer and no path is specified, update would normally reuse the current document-root // which would point to the wrong customer, therefore we will re-create that directory - if (! empty($documentroot) && $customerid > 0 && $customerid != $result['customerid'] && Settings::Get('panel.allow_domain_change_customer') == '1') { + if (!empty($documentroot) && $customerid > 0 && $customerid != $result['customerid'] && Settings::Get('panel.allow_domain_change_customer') == '1') { if (Settings::Get('system.documentroot_use_default_value') == 1) { - $_documentroot = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $result['domain']); + $_documentroot = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $result['domain']); } else { $_documentroot = $customer['documentroot']; } @@ -1211,20 +1340,19 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn // If path is empty and 'Use domain name as default value for DocumentRoot path' is enabled in settings, // set default path to subdomain or domain name if (Settings::Get('system.documentroot_use_default_value') == 1) { - $documentroot = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $result['domain']); + $documentroot = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $result['domain']); } else { $documentroot = $customer['documentroot']; } } - if (! preg_match('/^https?\:\/\//', $documentroot) && strstr($documentroot, ":") !== false) { - \Froxlor\UI\Response::standard_error('pathmaynotcontaincolon', '', true); + if (!preg_match('/^https?\:\/\//', $documentroot) && strstr($documentroot, ":") !== false) { + Response::standardError('pathmaynotcontaincolon', '', true); } if ($this->getUserDetail('change_serversettings') == '1') { - if (Settings::Get('system.bind_enable') == '1') { - $zonefile = \Froxlor\Validate\Validate::validate($zonefile, 'zonefile', '', '', array(), true); + $zonefile = Validate::validate($zonefile, 'zonefile', '', '', [], true); } else { $isbinddomain = $result['isbinddomain']; $zonefile = $result['zonefile']; @@ -1234,27 +1362,27 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $dkim = $result['dkim']; } - $specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $specialsettings), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true); + $specialsettings = Validate::validate(str_replace("\r\n", "\n", $specialsettings), 'specialsettings', Validate::REGEX_CONF_TEXT, '', [], true); - $ssl_protocols = array(); - if (! empty($p_ssl_protocols) && is_numeric($p_ssl_protocols)) { - $p_ssl_protocols = array( + $ssl_protocols = []; + if (!empty($p_ssl_protocols) && is_numeric($p_ssl_protocols)) { + $p_ssl_protocols = [ $p_ssl_protocols - ); + ]; } - if (! empty($p_ssl_protocols) && ! is_array($p_ssl_protocols)) { + if (!empty($p_ssl_protocols) && !is_array($p_ssl_protocols)) { $p_ssl_protocols = json_decode($p_ssl_protocols, true); } - if (! empty($p_ssl_protocols) && is_array($p_ssl_protocols)) { - $protocols_available = array( + if (!empty($p_ssl_protocols) && is_array($p_ssl_protocols)) { + $protocols_available = [ 'TLSv1', 'TLSv1.1', 'TLSv1.2', 'TLSv1.3' - ); + ]; foreach ($p_ssl_protocols as $ssl_protocol) { - if (! in_array(trim($ssl_protocol), $protocols_available)) { - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_DEBUG, "[API] unknown SSL protocol '" . trim($ssl_protocol) . "'"); + if (!in_array(trim($ssl_protocol), $protocols_available)) { + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_DEBUG, "[API] unknown SSL protocol '" . trim($ssl_protocol) . "'"); continue; } $ssl_protocols[] = $ssl_protocol; @@ -1279,28 +1407,27 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn } if ($this->getUserDetail('caneditphpsettings') == '1' || $this->getUserDetail('change_serversettings') == '1') { - - if ((int) Settings::Get('system.mod_fcgid') == 1 || (int) Settings::Get('phpfpm.enabled') == 1) { + if ((int)Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) { $phpsettingid_check_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `id` = :phpid "); - $phpsettingid_check = Database::pexecute_first($phpsettingid_check_stmt, array( + $phpsettingid_check = Database::pexecute_first($phpsettingid_check_stmt, [ 'phpid' => $phpsettingid - ), true, true); + ], true, true); - if (! isset($phpsettingid_check['id']) || $phpsettingid_check['id'] == '0' || $phpsettingid_check['id'] != $phpsettingid) { - \Froxlor\UI\Response::standard_error('phpsettingidwrong', '', true); + if (!isset($phpsettingid_check['id']) || $phpsettingid_check['id'] == '0' || $phpsettingid_check['id'] != $phpsettingid) { + Response::standardError('phpsettingidwrong', '', true); } - if ((int) Settings::Get('system.mod_fcgid') == 1) { - $mod_fcgid_starter = \Froxlor\Validate\Validate::validate($mod_fcgid_starter, 'mod_fcgid_starter', '/^[0-9]*$/', '', array( + if ((int)Settings::Get('system.mod_fcgid') == 1) { + $mod_fcgid_starter = Validate::validate($mod_fcgid_starter, 'mod_fcgid_starter', '/^[0-9]*$/', '', [ '-1', '' - ), true); - $mod_fcgid_maxrequests = \Froxlor\Validate\Validate::validate($mod_fcgid_maxrequests, 'mod_fcgid_maxrequests', '/^[0-9]*$/', '', array( + ], true); + $mod_fcgid_maxrequests = Validate::validate($mod_fcgid_maxrequests, 'mod_fcgid_maxrequests', '/^[0-9]*$/', '', [ '-1', '' - ), true); + ], true); } else { $mod_fcgid_starter = $result['mod_fcgid_starter']; $mod_fcgid_maxrequests = $result['mod_fcgid_maxrequests']; @@ -1323,23 +1450,23 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn // check non-ssl IP $ipandports = $this->validateIpAddresses($p_ipandports, false, $result['id']); // check ssl IP - if (empty($p_ssl_ipandports) || (! is_array($p_ssl_ipandports) && is_null($p_ssl_ipandports))) { + if (empty($p_ssl_ipandports) || (!is_array($p_ssl_ipandports) && is_null($p_ssl_ipandports))) { foreach ($result['ipsandports'] as $ip) { if ($ip['ssl'] == 1) { $p_ssl_ipandports[] = $ip['id']; } } } - $ssl_ipandports = array(); - if (Settings::Get('system.use_ssl') == "1" && ! empty($p_ssl_ipandports) && $p_ssl_ipandports[0] != - 1) { + $ssl_ipandports = []; + if (Settings::Get('system.use_ssl') == "1" && !empty($p_ssl_ipandports) && $p_ssl_ipandports[0] != -1) { $ssl_ipandports = $this->validateIpAddresses($p_ssl_ipandports, true, $result['id']); if ($this->getUserDetail('change_serversettings') == '1') { - $ssl_specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $ssl_specialsettings), 'ssl_specialsettings', '/^[^\0]*$/', '', array(), true); + $ssl_specialsettings = Validate::validate(str_replace("\r\n", "\n", $ssl_specialsettings), 'ssl_specialsettings', '/^[^\0]*$/', '', [], true); } } - if ($remove_ssl_ipandport || (! empty($p_ssl_ipandports) && $p_ssl_ipandports[0] == - 1)) { - $ssl_ipandports = array(); + if ($remove_ssl_ipandport || (!empty($p_ssl_ipandports) && $p_ssl_ipandports[0] == -1)) { + $ssl_ipandports = []; } if (Settings::Get('system.use_ssl') == "0" || empty($ssl_ipandports)) { $ssl_redirect = 0; @@ -1347,7 +1474,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $http2 = 0; // we need this for the json_encode // if ssl is disabled or no ssl-ip/port exists - $ssl_ipandports[] = - 1; + $ssl_ipandports[] = -1; // HSTS $hsts_maxage = 0; @@ -1364,16 +1491,16 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn // validate dns if lets encrypt is enabled to check whether we can use it at all if ($letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') { - $domain_ips = \Froxlor\PhpHelper::gethostbynamel6($result['domain']); + $domain_ips = PhpHelper::gethostbynamel6($result['domain']); $selected_ips = $this->getIpsFromIdArray($ssl_ipandports); if ($domain_ips == false || count(array_intersect($selected_ips, $domain_ips)) <= 0) { - \Froxlor\UI\Response::standard_error('invaliddnsforletsencrypt', '', true); + Response::standardError('invaliddnsforletsencrypt', '', true); } } // We can't enable let's encrypt for wildcard-domains if ($serveraliasoption == '0' && $letsencrypt == '1') { - \Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt', '', true); + Response::standardError('nowildcardwithletsencrypt', '', true); } // Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated @@ -1381,12 +1508,12 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $ssl_redirect = 2; } - if (! preg_match('/^https?\:\/\//', $documentroot)) { + if (!preg_match('/^https?\:\/\//', $documentroot)) { if ($documentroot != $result['documentroot']) { if (substr($documentroot, 0, 1) != "/") { $documentroot = $customer['documentroot'] . '/' . $documentroot; } - $documentroot = \Froxlor\FileDir::makeCorrectDir($documentroot); + $documentroot = FileDir::makeCorrectDir($documentroot); } } @@ -1400,25 +1527,25 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $subcanemaildomain = '0'; } - $aliasdomain_check = array( + $aliasdomain_check = [ 'id' => 0 - ); + ]; if ($aliasdomain != 0) { // Overwrite given ipandports with these of the "main" domain - $ipandports = array(); - $ssl_ipandports = array(); + $ipandports = []; + $ssl_ipandports = []; $origipresult_stmt = Database::prepare(" SELECT `id_ipandports` FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :aliasdomain "); - Database::pexecute($origipresult_stmt, array( + Database::pexecute($origipresult_stmt, [ 'aliasdomain' => $aliasdomain - ), true, true); + ], true, true); $ipdata_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `id` = :ipid"); - while ($origip = $origipresult_stmt->fetch(\PDO::FETCH_ASSOC)) { - $_origip_tmp = Database::pexecute_first($ipdata_stmt, array( + while ($origip = $origipresult_stmt->fetch(PDO::FETCH_ASSOC)) { + $_origip_tmp = Database::pexecute_first($ipdata_stmt, [ 'ipid' => $origip['id_ipandports'] - ), true, true); + ], true, true); if ($_origip_tmp['ssl'] == 0) { $ipandports[] = $origip['id_ipandports']; } else { @@ -1429,7 +1556,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn if (count($ssl_ipandports) == 0) { // we need this for the json_encode // if ssl is disabled or no ssl-ip/port exists - $ssl_ipandports[] = - 1; + $ssl_ipandports[] = -1; } $aliasdomain_check_stmt = Database::prepare(" @@ -1439,18 +1566,18 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn AND `c`.`customerid` = :customerid AND `d`.`id` = :aliasdomain "); - $aliasdomain_check = Database::pexecute_first($aliasdomain_check_stmt, array( + $aliasdomain_check = Database::pexecute_first($aliasdomain_check_stmt, [ 'customerid' => $customerid, 'aliasdomain' => $aliasdomain - ), true, true); + ], true, true); } if (count($ipandports) == 0) { - \Froxlor\UI\Response::standard_error('noipportgiven', '', true); + Response::standardError('noipportgiven', '', true); } if ($aliasdomain_check['id'] != $aliasdomain) { - \Froxlor\UI\Response::standard_error('domainisaliasorothercustomer', '', true); + Response::standardError('domainisaliasorothercustomer', '', true); } if ($issubof <= 0) { @@ -1465,7 +1592,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $iswildcarddomain = ($serveraliasoption == '0') ? '1' : '0'; if ($documentroot != $result['documentroot'] || $ssl_redirect != $result['ssl_redirect'] || $wwwserveralias != $result['wwwserveralias'] || $iswildcarddomain != $result['iswildcarddomain'] || $phpenabled != $result['phpenabled'] || $openbasedir != $result['openbasedir'] || $phpsettingid != $result['phpsettingid'] || $mod_fcgid_starter != $result['mod_fcgid_starter'] || $mod_fcgid_maxrequests != $result['mod_fcgid_maxrequests'] || $specialsettings != $result['specialsettings'] || $ssl_specialsettings != $result['ssl_specialsettings'] || $notryfiles != $result['notryfiles'] || $writeaccesslog != $result['writeaccesslog'] || $writeerrorlog != $result['writeerrorlog'] || $aliasdomain != $result['aliasdomain'] || $issubof != $result['ismainbutsubto'] || $email_only != $result['email_only'] || ($speciallogfile != $result['speciallogfile'] && $speciallogverified == '1') || $letsencrypt != $result['letsencrypt'] || $http2 != $result['http2'] || $hsts_maxage != $result['hsts'] || $hsts_sub != $result['hsts_sub'] || $hsts_preload != $result['hsts_preload'] || $ocsp_stapling != $result['ocsp_stapling']) { - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + Cronjob::inserttask(TaskId::REBUILD_VHOST); } if ($speciallogfile != $result['speciallogfile'] && $speciallogverified != '1') { @@ -1473,28 +1600,28 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn } if ($isbinddomain != $result['isbinddomain'] || $zonefile != $result['zonefile'] || $dkim != $result['dkim'] || $isemaildomain != $result['isemaildomain']) { - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); + Cronjob::inserttask(TaskId::REBUILD_DNS); } // check whether nameserver has been disabled, #581 if ($isbinddomain != $result['isbinddomain'] && $isbinddomain == 0) { - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_PDNS, $result['domain']); + Cronjob::inserttask(TaskId::DELETE_DOMAIN_PDNS, $result['domain']); } if ($isemaildomain == '0' && $result['isemaildomain'] == '1') { $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_MAIL_USERS . "` WHERE `domainid` = :id "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'id' => $id - ), true, true); + ], true, true); $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_MAIL_VIRTUAL . "` WHERE `domainid` = :id "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'id' => $id - ), true, true); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] deleted domain #" . $id . " from mail-tables as is-email-domain was set to 0"); + ], true, true); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] deleted domain #" . $id . " from mail-tables as is-email-domain was set to 0"); } // check whether LE has been disabled, so we remove the certificate @@ -1502,11 +1629,11 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :id "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'id' => $id - ), true, true); + ], true, true); // remove domain from acme.sh / lets encrypt if used - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_SSL, $result['domain']); + Cronjob::inserttask(TaskId::DELETE_DOMAIN_SSL, $result['domain']); } $updatechildren = ''; @@ -1518,10 +1645,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn } if ($customerid != $result['customerid'] && Settings::Get('panel.allow_domain_change_customer') == '1') { - $upd_data = array( + $upd_data = [ 'customerid' => $customerid, 'domainid' => $result['id'] - ); + ]; $upd_stmt = Database::prepare(" UPDATE `" . TABLE_MAIL_USERS . "` SET `customerid` = :customerid WHERE `domainid` = :domainid "); @@ -1530,12 +1657,12 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn UPDATE `" . TABLE_MAIL_VIRTUAL . "` SET `customerid` = :customerid WHERE `domainid` = :domainid "); Database::pexecute($upd_stmt, $upd_data, true, true); - $upd_data = array( + $upd_data = [ 'subdomains' => $subdomains, 'emails' => $emails, 'forwarders' => $email_forwarders, 'accounts' => $email_accounts - ); + ]; $upd_data['customerid'] = $customerid; $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET @@ -1563,19 +1690,19 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_ADMINS . "` SET `domains_used` = `domains_used` + 1 WHERE `adminid` = :adminid "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'adminid' => $adminid - ), true, true); + ], true, true); $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_ADMINS . "` SET `domains_used` = `domains_used` - 1 WHERE `adminid` = :adminid "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'adminid' => $result['adminid'] - ), true, true); + ], true, true); } - $_update_data = array(); + $_update_data = []; if ($ssfs == 1) { $_update_data['specialsettings'] = $specialsettings; @@ -1590,16 +1717,16 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `specialsettings`='', `ssl_specialsettings`='', `include_specialsettings`='0' WHERE `parentdomainid` = :id "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'id' => $id - ), true, true); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] removed specialsettings on all subdomains of domain #" . $id); + ], true, true); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] removed specialsettings on all subdomains of domain #" . $id); } $wwwserveralias = ($serveraliasoption == '1') ? '1' : '0'; $iswildcarddomain = ($serveraliasoption == '0') ? '1' : '0'; - $update_data = array(); + $update_data = []; $update_data['customerid'] = $customerid; $update_data['adminid'] = $adminid; $update_data['documentroot'] = $documentroot; @@ -1721,7 +1848,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn // all its subdomains must have "ssl-redirect = 0" // and disable let's encrypt $update_sslredirect = ''; - if (count($ssl_ipandports) == 1 && $ssl_ipandports[0] == - 1) { + if (count($ssl_ipandports) == 1 && $ssl_ipandports[0] == -1) { $update_sslredirect = ", `ssl_redirect` = '0', `letsencrypt` = '0' "; } @@ -1751,26 +1878,26 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :id "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'id' => $id - ), true, true); + ], true, true); $ins_stmt = Database::prepare(" INSERT INTO `" . TABLE_DOMAINTOIP . "` SET `id_domain` = :domainid, `id_ipandports` = :ipportid "); foreach ($ipandports as $ipportid) { - Database::pexecute($ins_stmt, array( + Database::pexecute($ins_stmt, [ 'domainid' => $id, 'ipportid' => $ipportid - ), true, true); + ], true, true); } foreach ($ssl_ipandports as $ssl_ipportid) { if ($ssl_ipportid > 0) { - Database::pexecute($ins_stmt, array( + Database::pexecute($ins_stmt, [ 'domainid' => $id, 'ipportid' => $ssl_ipportid - ), true, true); + ], true, true); } } @@ -1778,18 +1905,17 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $domainidsresult_stmt = Database::prepare(" SELECT `id` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `parentdomainid` = :id "); - Database::pexecute($domainidsresult_stmt, array( + Database::pexecute($domainidsresult_stmt, [ 'id' => $id - ), true, true); - - while ($row = $domainidsresult_stmt->fetch(\PDO::FETCH_ASSOC)) { + ], true, true); + while ($row = $domainidsresult_stmt->fetch(PDO::FETCH_ASSOC)) { $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :rowid "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'rowid' => $row['id'] - ), true, true); + ], true, true); $ins_stmt = Database::prepare(" INSERT INTO `" . TABLE_DOMAINTOIP . "` SET @@ -1798,61 +1924,63 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn "); foreach ($ipandports as $ipportid) { - Database::pexecute($ins_stmt, array( + Database::pexecute($ins_stmt, [ 'rowid' => $row['id'], 'ipportid' => $ipportid - ), true, true); + ], true, true); } foreach ($ssl_ipandports as $ssl_ipportid) { if ($ssl_ipportid > 0) { - Database::pexecute($ins_stmt, array( + Database::pexecute($ins_stmt, [ 'rowid' => $row['id'], 'ipportid' => $ssl_ipportid - ), true, true); + ], true, true); } } } if ($result['aliasdomain'] != $aliasdomain && is_numeric($result['aliasdomain'])) { // trigger when domain id for alias destination has changed: both for old and new destination - \Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger()); - \Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger()); + Domain::triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger()); + Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger()); } if ($result['wwwserveralias'] != $wwwserveralias || $result['letsencrypt'] != $letsencrypt) { // or when wwwserveralias or letsencrypt was changed - \Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger()); - if ((int) $aliasdomain === 0) { + Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger()); + if ((int)$aliasdomain === 0) { // in case the wwwserveralias is set on a main domain, $aliasdomain is 0 // --> the call just above to triggerLetsEncryptCSRForAliasDestinationDomain // is a noop...let's repeat it with the domain id of the main domain - \Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($id, $this->logger()); + Domain::triggerLetsEncryptCSRForAliasDestinationDomain($id, $this->logger()); } } - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] updated domain '" . $idna_convert->decode($result['domain']) . "'"); - $result = $this->apiCall('Domains.get', array( + $idna_convert = new IdnaWrapper(); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] updated domain '" . $idna_convert->decode($result['domain']) . "'"); + $result = $this->apiCall('Domains.get', [ 'domainname' => $result['domain'] - )); + ]); return $this->response($result); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * delete a domain entry by either id or domainname * * @param int $id - * optional, the domain-id + * optional, the domain-id * @param string $domainname - * optional, the domainname + * optional, the domainname * @param bool $delete_mainsubdomains - * optional, remove also domains that are subdomains of this domain but added as main domains; default false + * optional, remove also domains that are subdomains of this domain but added as main domains; default + * false * @param bool $is_stdsubdomain - * optional, default false, specify whether it's a std-subdomain you are deleting as it does not count as subdomain-resource + * optional, default false, specify whether it's a std-subdomain you are deleting as it does not count + * as subdomain-resource * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function delete() { @@ -1863,10 +1991,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $is_stdsubdomain = $this->getParam('is_stdsubdomain', true, 0); $remove_subbutmain_domains = $this->getParam('delete_mainsubdomains', true, 0); - $result = $this->apiCall('Domains.get', array( + $result = $this->apiCall('Domains.get', [ 'id' => $id, 'domainname' => $domainname - )); + ]); $id = $result['id']; // check for deletion of main-domains which are logically subdomains, #329 @@ -1878,13 +2006,13 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $subresult_stmt = Database::prepare(" SELECT `id` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE (`id` = :id OR `parentdomainid` = :id " . $rsd_sql . ")"); - Database::pexecute($subresult_stmt, array( + Database::pexecute($subresult_stmt, [ 'id' => $id - ), true, true); - $idString = array(); - $paramString = array(); - while ($subRow = $subresult_stmt->fetch(\PDO::FETCH_ASSOC)) { - $idString[] = "`domainid` = :domain_" . (int) $subRow['id']; + ], true, true); + $idString = []; + $paramString = []; + while ($subRow = $subresult_stmt->fetch(PDO::FETCH_ASSOC)) { + $idString[] = "`domainid` = :domain_" . (int)$subRow['id']; $paramString['domain_' . $subRow['id']] = $subRow['id']; } $idString = implode(' OR ', $idString); @@ -1896,7 +2024,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_MAIL_VIRTUAL . "` WHERE " . $idString); Database::pexecute($del_stmt, $paramString, true, true); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] deleted domain/s from mail-tables"); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] deleted domain/s from mail-tables"); } // if mainbutsubto-domains are not to be deleted, re-assign the (ismainbutsubto value of the main @@ -1907,18 +2035,18 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn `ismainbutsubto` = :newIsMainButSubtoValue WHERE `ismainbutsubto` = :deletedMainDomainId "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'newIsMainButSubtoValue' => $result['ismainbutsubto'], 'deletedMainDomainId' => $id - ), true, true); + ], true, true); } $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `id` = :id OR `parentdomainid` = :id " . $rsd_sql); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'id' => $id - ), true, true); + ], true, true); $deleted_domains = $del_stmt->rowCount(); @@ -1927,156 +2055,75 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `subdomains_used` = `subdomains_used` - :domaincount WHERE `customerid` = :customerid"); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'domaincount' => ($deleted_domains - 1), 'customerid' => $result['customerid'] - ), true, true); + ], true, true); $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_ADMINS . "` SET `domains_used` = `domains_used` - 1 WHERE `adminid` = :adminid"); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'adminid' => $this->getUserDetail('adminid') - ), true, true); + ], true, true); } $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `standardsubdomain` = '0' WHERE `standardsubdomain` = :id AND `customerid` = :customerid"); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'id' => $result['id'], 'customerid' => $result['customerid'] - ), true, true); + ], true, true); $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :domainid"); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'domainid' => $id - ), true, true); + ], true, true); $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_DOMAINREDIRECTS . "` WHERE `did` = :domainid"); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'domainid' => $id - ), true, true); + ], true, true); // remove certificate from domain_ssl_settings, fixes #1596 $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :domainid"); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'domainid' => $id - ), true, true); + ], true, true); // remove possible existing DNS entries $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_DOMAIN_DNS . "` WHERE `domain_id` = :domainid "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'domainid' => $id - ), true, true); + ], true, true); - \Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger()); + Domain::triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger()); // remove domains DNS from powerDNS if used, #581 - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_PDNS, $result['domain']); + Cronjob::inserttask(TaskId::DELETE_DOMAIN_PDNS, $result['domain']); // remove domain from acme.sh / lets encrypt if used - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_SSL, $result['domain']); + Cronjob::inserttask(TaskId::DELETE_DOMAIN_SSL, $result['domain']); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] deleted domain/subdomains (#" . $result['id'] . ")"); - \Froxlor\User::updateCounters(); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] deleted domain/subdomains (#" . $result['id'] . ")"); + User::updateCounters(); + Cronjob::inserttask(TaskId::REBUILD_VHOST); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); + Cronjob::inserttask(TaskId::REBUILD_DNS); return $this->response($result); } - throw new \Exception("Not allowed to execute given command.", 403); - } - - /** - * validate given ips - * - * @param int|string|array $p_ipandports - * @param boolean $ssl - * default false - * @param int $edit_id - * default 0 - * - * @throws \Exception - * @return array - */ - private function validateIpAddresses($p_ipandports = null, $ssl = false, $edit_id = 0) - { - // when adding a new domain and no ip is given, we try to use the - // system-default, check here if there is none - // this is not required for ssl-enabled ip's - if ($edit_id <= 0 && ! $ssl && empty($p_ipandports)) { - throw new \Exception("No IPs given, unable to add domain (no default IPs set?)", 406); - } - - // convert given value(s) correctly - $ipandports = array(); - if (! empty($p_ipandports) && is_numeric($p_ipandports)) { - $p_ipandports = array( - $p_ipandports - ); - } - if (! empty($p_ipandports) && ! is_array($p_ipandports)) { - $p_ipandports = json_decode($p_ipandports, true); - } - - // check whether there are ip usage restrictions - $additional_ip_condition = ''; - $aip_param = array(); - if ($this->getUserDetail('ip') != "-1") { - // handle multiple-ip-array - $additional_ip_condition = " AND `ip` IN (" . implode(",", json_decode($this->getUserDetail('ip'), true)) . ") "; - } - - if (! empty($p_ipandports) && is_array($p_ipandports)) { - $ipandport_check_stmt = Database::prepare(" - SELECT `id`, `ip`, `port` - FROM `" . TABLE_PANEL_IPSANDPORTS . "` - WHERE `id` = :ipandport " . ($ssl ? " AND `ssl` = '1'" : "") . $additional_ip_condition); - foreach ($p_ipandports as $ipandport) { - if (trim($ipandport) == "") { - continue; - } - // fix if no ip/port is checked - if (trim($ipandport) < 1) { - continue; - } - $ipandport = intval($ipandport); - $ip_params = array_merge(array( - 'ipandport' => $ipandport - ), $aip_param); - $ipandport_check = Database::pexecute_first($ipandport_check_stmt, $ip_params, true, true); - if (! isset($ipandport_check['id']) || $ipandport_check['id'] == '0' || $ipandport_check['id'] != $ipandport) { - \Froxlor\UI\Response::standard_error('ipportdoesntexist', '', true); - } else { - $ipandports[] = $ipandport; - } - } - } elseif ($edit_id > 0) { - // set currently used ip's - $ipsresult_stmt = Database::prepare(" - SELECT d2i.`id_ipandports` - FROM `" . TABLE_DOMAINTOIP . "` d2i - LEFT JOIN `" . TABLE_PANEL_IPSANDPORTS . "` i ON i.id = d2i.id_ipandports - WHERE d2i.`id_domain` = :id AND i.`ssl` = " . ($ssl ? "'1'" : "'0'")); - Database::pexecute($ipsresult_stmt, array( - 'id' => $edit_id - ), true, true); - while ($ipsresultrow = $ipsresult_stmt->fetch(\PDO::FETCH_ASSOC)) { - $ipandports[] = $ipsresultrow['id_ipandports']; - } - } - return $ipandports; + throw new Exception("Not allowed to execute given command.", 403); } } diff --git a/lib/Froxlor/Api/Commands/EmailAccounts.php b/lib/Froxlor/Api/Commands/EmailAccounts.php index c2898735..094363bc 100644 --- a/lib/Froxlor/Api/Commands/EmailAccounts.php +++ b/lib/Froxlor/Api/Commands/EmailAccounts.php @@ -1,59 +1,84 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Cron\TaskId; +use Froxlor\Database\Database; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; +use Froxlor\Idna\IdnaWrapper; +use Froxlor\Settings; +use Froxlor\System\Cronjob; +use Froxlor\System\Crypt; +use Froxlor\UI\Response; +use Froxlor\User; +use Froxlor\Validate\Check; +use Froxlor\Validate\Validate; + +/** + * @since 0.10.0 + */ +class EmailAccounts extends ApiCommand implements ResourceEntity { /** * add a new email account for a given email-address either by id or emailaddr * * @param int $id - * optional email-address-id of email-address to add the account for + * optional email-address-id of email-address to add the account for * @param string $emailaddr - * optional email-address to add the account for + * optional email-address to add the account for * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * @param string $email_password - * password for the account + * password for the account * @param string $alternative_email - * optional email address to send account information to, default is the account that is being created + * optional email address to send account information to, default is the account that is being created * @param int $email_quota - * optional quota if enabled in MB, default 0 + * optional quota if enabled in MB, default 0 * @param bool $sendinfomail - * optional, sends the welcome message to the new account (needed for creation, without the user won't be able to login before any mail is received), default 1 (true) + * optional, sends the welcome message to the new account (needed for creation, without the user won't + * be able to login before any mail is received), default 1 (true) * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function add() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } if ($this->getUserDetail('email_accounts_used') < $this->getUserDetail('email_accounts') || $this->getUserDetail('email_accounts') == '-1') { - // parameter $id = $this->getParam('id', true, 0); $ea_optional = $id > 0; @@ -64,44 +89,44 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso $sendinfomail = $this->getBoolParam('sendinfomail', true, 1); // validation - $quota = \Froxlor\Validate\Validate::validate($quota, 'email_quota', '/^\d+$/', 'vmailquotawrong', array(), true); + $quota = Validate::validate($quota, 'email_quota', '/^\d+$/', 'vmailquotawrong', [], true); // get needed customer info to reduce the email-account-counter by one $customer = $this->getCustomerData('email_accounts'); // check for imap||pop3 == 1, see #1298 if ($customer['imap'] != '1' && $customer['pop3'] != '1') { - \Froxlor\UI\Response::standard_error('notallowedtouseaccounts', '', true); + Response::standardError('notallowedtouseaccounts', '', true); } // get email address - $result = $this->apiCall('Emails.get', array( + $result = $this->apiCall('Emails.get', [ 'id' => $id, 'emailaddr' => $emailaddr - )); + ]); $id = $result['id']; - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); + $idna_convert = new IdnaWrapper(); $email_full = $result['email_full']; $username = $email_full; - $password = \Froxlor\Validate\Validate::validate($email_password, 'password', '', '', array(), true); - $password = \Froxlor\System\Crypt::validatePassword($password, true); + $password = Validate::validate($email_password, 'password', '', '', [], true); + $password = Crypt::validatePassword($password, true); if ($result['popaccountid'] != 0) { - throw new \Exception("Email address '" . $email_full . "' has already an account assigned.", 406); + throw new Exception("Email address '" . $email_full . "' has already an account assigned.", 406); } - if (\Froxlor\Validate\Check::checkMailAccDeletionState($email_full)) { - \Froxlor\UI\Response::standard_error(array( + if (Check::checkMailAccDeletionState($email_full)) { + Response::standardError([ 'mailaccistobedeleted' - ), $email_full, true); + ], $email_full, true); } // alternative email address to send info to if (Settings::Get('panel.sendalternativemail') == 1) { - $alternative_email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($alternative_email, 'alternative_email', '', '', array(), true)); - if (! empty($alternative_email) && ! \Froxlor\Validate\Validate::validateEmail($alternative_email)) { - \Froxlor\UI\Response::standard_error('alternativeemailiswrong', $alternative_email, true); + $alternative_email = $idna_convert->encode(Validate::validate($alternative_email, 'alternative_email', '', '', [], true)); + if (!empty($alternative_email) && !Validate::validateEmail($alternative_email)) { + Response::standardError('alternativeemailiswrong', $alternative_email, true); } } else { $alternative_email = ''; @@ -110,7 +135,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso // validate quota if enabled if (Settings::Get('system.mail_quota_enabled') == 1) { if ($customer['email_quota'] != '-1' && ($quota == 0 || ($quota + $customer['email_quota_used']) > $customer['email_quota'])) { - \Froxlor\UI\Response::standard_error('allocatetoomuchquota', $quota, true); + Response::standardError('allocatetoomuchquota', $quota, true); } } else { // disable @@ -118,18 +143,18 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso } if ($password == $email_full) { - \Froxlor\UI\Response::standard_error('passwordshouldnotbeusername', '', true); + Response::standardError('passwordshouldnotbeusername', '', true); } // encrypt the password - $cryptPassword = \Froxlor\System\Crypt::makeCryptPassword($password); + $cryptPassword = Crypt::makeCryptPassword($password); $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) && substr($maildirname, - 1) != "/") { + if (!empty($maildirname) && substr($maildirname, -1) != "/") { $maildirpath .= "/"; } @@ -149,7 +174,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso `imap` = :imap, `pop3` = :pop3 "); - $params = array( + $params = [ "cid" => $customer['customerid'], "email" => $email_full, "username" => $username, @@ -162,7 +187,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso "quota" => $quota, "imap" => $customer['imap'], "pop3" => $customer['pop3'] - ); + ]; if (Settings::Get('system.mailpwcleartext') == '1') { $params["password"] = $password; } @@ -175,12 +200,12 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso UPDATE `" . TABLE_MAIL_VIRTUAL . "` SET `destination` = :destination, `popaccountid` = :popaccountid WHERE `customerid`= :cid AND `id`= :id "); - $params = array( - "destination" => \Froxlor\FileDir::makeCorrectDestination($result['destination']), + $params = [ + "destination" => FileDir::makeCorrectDestination($result['destination']), "popaccountid" => $popaccountid, "cid" => $customer['customerid'], "id" => $id - ); + ]; Database::pexecute($stmt, $params, true, true); // update customer usage @@ -189,22 +214,22 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso if ($sendinfomail) { // replacer array for mail to create account on server - $replace_arr = array( + $replace_arr = [ 'EMAIL' => $email_full, 'USERNAME' => $username, 'PASSWORD' => htmlentities(htmlentities($password)), - 'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($customer), + 'SALUTATION' => User::getCorrectUserSalutation($customer), 'NAME' => $customer['name'], 'FIRSTNAME' => $customer['firstname'], 'COMPANY' => $customer['company'], 'CUSTOMER_NO' => $customer['customernumber'] - ); + ]; // get the customers admin $stmt = Database::prepare("SELECT `name`, `email` FROM `" . TABLE_PANEL_ADMINS . "` WHERE `adminid`= :adminid"); - $admin = Database::pexecute_first($stmt, array( + $admin = Database::pexecute_first($stmt, [ "adminid" => $customer['adminid'] - )); + ]); // get template for mail subject $mail_subject = $this->getMailTemplate($customer, 'mails', 'pop_success_subject', $replace_arr, lng('mails.pop_success.subject')); @@ -214,7 +239,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso $_mailerror = false; $mailerr_msg = ""; try { - $this->mailer()->setFrom($admin['email'], \Froxlor\User::getCorrectUserSalutation($admin)); + $this->mailer()->setFrom($admin['email'], User::getCorrectUserSalutation($admin)); $this->mailer()->Subject = $mail_subject; $this->mailer()->AltBody = $mail_body; $this->mailer()->msgHTML(str_replace("\n", "
", $mail_body)); @@ -223,20 +248,20 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso } 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) { - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg); - \Froxlor\UI\Response::standard_error('errorsendingmail', $email_full, true); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg); + Response::standardError('errorsendingmail', $email_full, true); } $this->mailer()->clearAddresses(); // customer wants to send the e-mail to an alternative email address too - if (Settings::Get('panel.sendalternativemail') == 1 && ! empty($alternative_email)) { + if (Settings::Get('panel.sendalternativemail') == 1 && !empty($alternative_email)) { // get template for mail subject $mail_subject = $this->getMailTemplate($customer, 'mails', 'pop_success_alternative_subject', $replace_arr, lng('mails.pop_success_alternative.subject')); // get template for mail body @@ -244,38 +269,38 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso $_mailerror = false; try { - $this->mailer()->setFrom($admin['email'], \Froxlor\User::getCorrectUserSalutation($admin)); + $this->mailer()->setFrom($admin['email'], User::getCorrectUserSalutation($admin)); $this->mailer()->Subject = $mail_subject; $this->mailer()->AltBody = $mail_body; $this->mailer()->msgHTML(str_replace("\n", "
", $mail_body)); - $this->mailer()->addAddress($idna_convert->encode($alternative_email), \Froxlor\User::getCorrectUserSalutation($customer)); + $this->mailer()->addAddress($idna_convert->encode($alternative_email), User::getCorrectUserSalutation($customer)); $this->mailer()->send(); } 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) { - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg); - \Froxlor\UI\Response::standard_error(array( + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg); + Response::standardError([ 'errorsendingmail' - ), $alternative_email, true); + ], $alternative_email, true); } $this->mailer()->clearAddresses(); } } - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added email account for '" . $result['email_full'] . "'"); - $result = $this->apiCall('Emails.get', array( + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added email account for '" . $result['email_full'] . "'"); + $result = $this->apiCall('Emails.get', [ 'emailaddr' => $result['email_full'] - )); + ]); return $this->response($result); } - throw new \Exception("No more resources available", 406); + throw new Exception("No more resources available", 406); } /** @@ -284,35 +309,35 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso */ public function get() { - throw new \Exception('You cannot directly get an email account. You need to call Emails.get()', 303); + throw new Exception('You cannot directly get an email account. You need to call Emails.get()', 303); } /** * update email-account entry for given email-address by either id or email-address * * @param int $id - * optional, the email-address-id + * optional, the email-address-id * @param string $emailaddr - * optional, the email-address to update + * optional, the email-address to update * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * @param int $email_quota - * optional, update quota + * optional, update quota * @param string $email_password - * optional, update password + * optional, update password * @param bool $deactivated - * optional, admin-only + * optional, admin-only * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function update() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } // parameter @@ -321,14 +346,14 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso $emailaddr = $this->getParam('emailaddr', $ea_optional, ''); // validation - $result = $this->apiCall('Emails.get', array( + $result = $this->apiCall('Emails.get', [ 'id' => $id, 'emailaddr' => $emailaddr - )); + ]); $id = $result['id']; if (empty($result['popaccountid']) || $result['popaccountid'] == 0) { - throw new \Exception("Email address '" . $result['email_full'] . "' has no account assigned.", 406); + throw new Exception("Email address '" . $result['email_full'] . "' has no account assigned.", 406); } $password = $this->getParam('email_password', true, ''); @@ -339,19 +364,19 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso $customer = $this->getCustomerData(); // validation - $quota = \Froxlor\Validate\Validate::validate($quota, 'email_quota', '/^\d+$/', 'vmailquotawrong', array(), true); + $quota = Validate::validate($quota, 'email_quota', '/^\d+$/', 'vmailquotawrong', [], true); $upd_query = ""; - $upd_params = array( + $upd_params = [ "id" => $result['popaccountid'], "cid" => $customer['customerid'] - ); - if (! empty($password)) { + ]; + if (!empty($password)) { if ($password == $result['email_full']) { - \Froxlor\UI\Response::standard_error('passwordshouldnotbeusername', '', true); + Response::standardError('passwordshouldnotbeusername', '', true); } - $password = \Froxlor\System\Crypt::validatePassword($password, true); - $cryptPassword = \Froxlor\System\Crypt::makeCryptPassword($password); + $password = Crypt::validatePassword($password, true); + $cryptPassword = Crypt::makeCryptPassword($password); $upd_query .= (Settings::Get('system.mailpwcleartext') == '1' ? "`password` = :password, " : '') . "`password_enc`= :password_enc"; $upd_params['password_enc'] = $cryptPassword; if (Settings::Get('system.mailpwcleartext') == '1') { @@ -362,9 +387,9 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso if (Settings::Get('system.mail_quota_enabled') == 1) { if ($quota != $result['quota']) { if ($customer['email_quota'] != '-1' && ($quota == 0 || ($quota + $customer['email_quota_used'] - $result['quota']) > $customer['email_quota'])) { - \Froxlor\UI\Response::standard_error('allocatetoomuchquota', $quota, true); + Response::standardError('allocatetoomuchquota', $quota, true); } - if (! empty($upd_query)) { + if (!empty($upd_query)) { $upd_query .= ", "; } $upd_query .= "`quota` = :quota"; @@ -377,7 +402,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso if ($this->isAdmin()) { if (($deactivated == true && strtolower($result['postfix']) == 'y') || ($deactivated == false && strtolower($result['postfix']) == 'n')) { - if (! empty($upd_query)) { + if (!empty($upd_query)) { $upd_query .= ", "; } $upd_query .= "`postfix` = :postfix, `imap` = :imap, `pop3` = :pop3"; @@ -388,7 +413,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso } // build update query - if (! empty($upd_query)) { + if (!empty($upd_query)) { $upd_stmt = Database::prepare(" UPDATE `" . TABLE_MAIL_USERS . "` SET " . $upd_query . " WHERE `id` = :id AND `customerid`= :cid "); @@ -400,10 +425,10 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso Admins::increaseUsage($customer['adminid'], 'email_quota_used', '', ($quota - $result['quota'])); } - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] updated email account '" . $result['email_full'] . "'"); - $result = $this->apiCall('Emails.get', array( + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] updated email account '" . $result['email_full'] . "'"); + $result = $this->apiCall('Emails.get', [ 'emailaddr' => $result['email_full'] - )); + ]); return $this->response($result); } @@ -413,7 +438,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso */ public function listing() { - throw new \Exception('You cannot directly list email accounts. You need to call Emails.listing()', 303); + throw new Exception('You cannot directly list email accounts. You need to call Emails.listing()', 303); } /** @@ -422,31 +447,31 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso */ public function listingCount() { - throw new \Exception('You cannot directly count email accounts. You need to call Emails.listingCount()', 303); + throw new Exception('You cannot directly count email accounts. You need to call Emails.listingCount()', 303); } /** * delete email-account entry for given email-address by either id or email-address * * @param int $id - * optional, the email-address-id + * optional, the email-address-id * @param string $emailaddr - * optional, the email-address to delete the account for + * optional, the email-address to delete the account for * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * @param bool $delete_userfiles - * optional, default false + * optional, default false * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function delete() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } // parameter @@ -456,14 +481,14 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso $delete_userfiles = $this->getBoolParam('delete_userfiles', true, 0); // validation - $result = $this->apiCall('Emails.get', array( + $result = $this->apiCall('Emails.get', [ 'id' => $id, 'emailaddr' => $emailaddr - )); + ]); $id = $result['id']; if (empty($result['popaccountid']) || $result['popaccountid'] == 0) { - throw new \Exception("Email address '" . $result['email_full'] . "' has no account assigned.", 406); + throw new Exception("Email address '" . $result['email_full'] . "' has no account assigned.", 406); } // get needed customer info to reduce the email-account-counter by one @@ -473,10 +498,10 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso $stmt = Database::prepare(" DELETE FROM `" . TABLE_MAIL_USERS . "` WHERE `customerid`= :cid AND `id`= :id "); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "cid" => $customer['customerid'], "id" => $result['popaccountid'] - ), true, true); + ], true, true); // update mail-virtual entry $result['destination'] = str_replace($result['email_full'], '', $result['destination']); @@ -484,29 +509,29 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso $stmt = Database::prepare(" UPDATE `" . TABLE_MAIL_VIRTUAL . "` SET `destination` = :dest, `popaccountid` = '0' WHERE `customerid`= :cid AND `id`= :id "); - $params = array( - "dest" => \Froxlor\FileDir::makeCorrectDestination($result['destination']), + $params = [ + "dest" => FileDir::makeCorrectDestination($result['destination']), "cid" => $customer['customerid'], "id" => $id - ); + ]; Database::pexecute($stmt, $params, true, true); $result['popaccountid'] = 0; if (Settings::Get('system.mail_quota_enabled') == '1' && $customer['email_quota'] != '-1') { - $quota = (int) $result['quota']; + $quota = (int)$result['quota']; } else { $quota = 0; } if ($delete_userfiles) { - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_EMAIL_DATA, $customer['loginname'], $result['email_full']); + Cronjob::inserttask(TaskId::DELETE_EMAIL_DATA, $customer['loginname'], $result['email_full']); } // decrease usage for customer Customers::decreaseUsage($customer['customerid'], 'email_accounts_used'); Customers::decreaseUsage($customer['customerid'], 'email_quota_used', '', $quota); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted email account for '" . $result['email_full'] . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted email account for '" . $result['email_full'] . "'"); return $this->response($result); } } diff --git a/lib/Froxlor/Api/Commands/EmailForwarders.php b/lib/Froxlor/Api/Commands/EmailForwarders.php index 1239e89e..61222cad 100644 --- a/lib/Froxlor/Api/Commands/EmailForwarders.php +++ b/lib/Froxlor/Api/Commands/EmailForwarders.php @@ -1,53 +1,72 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Database\Database; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; +use Froxlor\Idna\IdnaWrapper; +use Froxlor\Settings; +use Froxlor\UI\Response; +use Froxlor\Validate\Validate; + +/** + * @since 0.10.0 + */ +class EmailForwarders extends ApiCommand implements ResourceEntity { /** * add new email-forwarder entry for given email-address by either id or email-address * * @param int $id - * optional, the email-address-id + * optional, the email-address-id * @param string $emailaddr - * optional, the email-address to add the forwarder for + * optional, the email-address to add the forwarder for * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * @param string $destination - * email-address to add as forwarder + * email-address to add as forwarder * * @access admin,customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function add() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } if ($this->getUserDetail('email_forwarders_used') < $this->getUserDetail('email_forwarders') || $this->getUserDetail('email_forwarders') == '-1') { - // parameter $id = $this->getParam('id', true, 0); $ea_optional = $id > 0; @@ -55,13 +74,13 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re $destination = $this->getParam('destination'); // validation - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); + $idna_convert = new IdnaWrapper(); $destination = $idna_convert->encode($destination); - $result = $this->apiCall('Emails.get', array( + $result = $this->apiCall('Emails.get', [ 'id' => $id, 'emailaddr' => $emailaddr - )); + ]); $id = $result['id']; // current destination array @@ -70,12 +89,12 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re // prepare destination $destination = trim($destination); - if (! \Froxlor\Validate\Validate::validateEmail($destination)) { - \Froxlor\UI\Response::standard_error('destinationiswrong', $destination, true); + if (!Validate::validateEmail($destination)) { + Response::standardError('destinationiswrong', $destination, true); } elseif ($destination == $result['email']) { - \Froxlor\UI\Response::standard_error('destinationalreadyexistasmail', $destination, true); + Response::standardError('destinationalreadyexistasmail', $destination, true); } elseif (in_array($destination, $result['destination_array'])) { - \Froxlor\UI\Response::standard_error('destinationalreadyexist', $destination, true); + Response::standardError('destinationalreadyexist', $destination, true); } // get needed customer info to reduce the email-forwarder-counter by one @@ -87,24 +106,24 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re UPDATE `" . TABLE_MAIL_VIRTUAL . "` SET `destination` = :dest WHERE `customerid`= :cid AND `id`= :id "); - $params = array( - "dest" => \Froxlor\FileDir::makeCorrectDestination($result['destination']), + $params = [ + "dest" => FileDir::makeCorrectDestination($result['destination']), "cid" => $customer['customerid'], "id" => $id - ); + ]; Database::pexecute($stmt, $params, true, true); // update customer usage Customers::increaseUsage($customer['customerid'], 'email_forwarders_used'); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added email forwarder for '" . $result['email_full'] . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added email forwarder for '" . $result['email_full'] . "'"); - $result = $this->apiCall('Emails.get', array( + $result = $this->apiCall('Emails.get', [ 'emailaddr' => $result['email_full'] - )); + ]); return $this->response($result); } - throw new \Exception("No more resources available", 406); + throw new Exception("No more resources available", 406); } /** @@ -113,7 +132,7 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re */ public function get() { - throw new \Exception('You cannot directly get an email forwarder. Try EmailForwarders.listing()', 303); + throw new Exception('You cannot directly get an email forwarder. Try EmailForwarders.listing()', 303); } /** @@ -122,29 +141,29 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re */ public function update() { - throw new \Exception('You cannot update an email forwarder. You need to delete the entry and create a new one.', 303); + throw new Exception('You cannot update an email forwarder. You need to delete the entry and create a new one.', 303); } /** * List email forwarders for a given email address * * @param int $id - * optional, the email-address-id + * optional, the email-address-id * @param string $emailaddr - * optional, the email-address to delete the forwarder from + * optional, the email-address to delete the forwarder from * @param int $customerid - * optional, admin-only, the customer-id + * optional, admin-only, the customer-id * @param string $loginname - * optional, admin-only, the loginname + * optional, admin-only, the loginname * * @access admin,customer - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listing() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } // parameter @@ -153,14 +172,14 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re $emailaddr = $this->getParam('emailaddr', $ea_optional, ''); // validation - $result = $this->apiCall('Emails.get', array( + $result = $this->apiCall('Emails.get', [ 'id' => $id, 'emailaddr' => $emailaddr - )); + ]); $id = $result['id']; $result['destination'] = explode(' ', $result['destination']); - $destination = array(); + $destination = []; foreach ($result['destination'] as $index => $address) { $destination[] = [ 'id' => $index, @@ -178,22 +197,22 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re * count email forwarders for a given email address * * @param int $id - * optional, the email-address-id + * optional, the email-address-id * @param string $emailaddr - * optional, the email-address to delete the forwarder from + * optional, the email-address to delete the forwarder from * @param int $customerid - * optional, admin-only, the customer-id + * optional, admin-only, the customer-id * @param string $loginname - * optional, admin-only, the loginname + * optional, admin-only, the loginname * * @access admin,customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function listingCount() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } // parameter @@ -202,10 +221,10 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re $emailaddr = $this->getParam('emailaddr', $ea_optional, ''); // validation - $result = $this->apiCall('Emails.get', array( + $result = $this->apiCall('Emails.get', [ 'id' => $id, 'emailaddr' => $emailaddr - )); + ]); $id = $result['id']; $result['destination'] = explode(' ', $result['destination']); @@ -217,24 +236,24 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re * delete email-forwarder entry for given email-address by either id or email-address and forwarder-id * * @param int $id - * optional, the email-address-id + * optional, the email-address-id * @param string $emailaddr - * optional, the email-address to delete the forwarder from + * optional, the email-address to delete the forwarder from * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * @param int $forwarderid - * id of the forwarder to delete + * id of the forwarder to delete * * @access admin,customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function delete() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } // parameter @@ -244,15 +263,14 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re $forwarderid = $this->getParam('forwarderid'); // validation - $result = $this->apiCall('Emails.get', array( + $result = $this->apiCall('Emails.get', [ 'id' => $id, 'emailaddr' => $emailaddr - )); + ]); $id = $result['id']; $result['destination'] = explode(' ', $result['destination']); if (isset($result['destination'][$forwarderid]) && $result['email'] != $result['destination'][$forwarderid]) { - // get needed customer info to reduce the email-forwarder-counter by one $customer = $this->getCustomerData(); @@ -265,23 +283,23 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re UPDATE `" . TABLE_MAIL_VIRTUAL . "` SET `destination` = :dest WHERE `customerid`= :cid AND `id`= :id "); - $params = array( - "dest" => \Froxlor\FileDir::makeCorrectDestination($result['destination']), + $params = [ + "dest" => FileDir::makeCorrectDestination($result['destination']), "cid" => $customer['customerid'], "id" => $id - ); + ]; Database::pexecute($stmt, $params, true, true); // update customer usage Customers::decreaseUsage($customer['customerid'], 'email_forwarders_used'); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted email forwarder for '" . $result['email_full'] . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted email forwarder for '" . $result['email_full'] . "'"); - $result = $this->apiCall('Emails.get', array( + $result = $this->apiCall('Emails.get', [ 'emailaddr' => $result['email_full'] - )); + ]); return $this->response($result); } - throw new \Exception("Unknown forwarder id", 404); + throw new Exception("Unknown forwarder id", 404); } } diff --git a/lib/Froxlor/Api/Commands/Emails.php b/lib/Froxlor/Api/Commands/Emails.php index d48a4610..5b083b16 100644 --- a/lib/Froxlor/Api/Commands/Emails.php +++ b/lib/Froxlor/Api/Commands/Emails.php @@ -1,55 +1,74 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Database\Database; +use Froxlor\FroxlorLogger; +use Froxlor\Idna\IdnaWrapper; +use Froxlor\Settings; +use Froxlor\UI\Response; +use Froxlor\Validate\Validate; +use PDO; + +/** + * @since 0.10.0 + */ +class Emails extends ApiCommand implements ResourceEntity { /** * add a new email address * * @param string $email_part - * name of the address before @ + * name of the address before @ * @param string $domain - * domain-name for the email-address + * domain-name for the email-address * @param boolean $iscatchall - * optional, make this address a catchall address, default: no + * optional, make this address a catchall address, default: no * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * @param string $description - * optional custom description (currently not used/shown in the frontend), default empty + * optional custom description (currently not used/shown in the frontend), default empty * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function add() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } if ($this->getUserDetail('emails_used') < $this->getUserDetail('emails') || $this->getUserDetail('emails') == '-1') { - // required parameters $email_part = $this->getParam('email_part'); $domain = $this->getParam('domain'); @@ -60,17 +79,17 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt // validation if (substr($domain, 0, 4) != 'xn--') { - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); - $domain = $idna_convert->encode(\Froxlor\Validate\Validate::validate($domain, 'domain', '', '', array(), true)); + $idna_convert = new IdnaWrapper(); + $domain = $idna_convert->encode(Validate::validate($domain, 'domain', '', '', [], true)); } // check domain and whether it's an email-enabled domain // use internal call because the customer might have 'domains' in customer_hide_options - $domain_check = $this->apiCall('SubDomains.get', array( + $domain_check = $this->apiCall('SubDomains.get', [ 'domainname' => $domain - ), true); + ], true); if ($domain_check['isemaildomain'] == 0) { - \Froxlor\UI\Response::standard_error('maindomainnonexist', $domain, true); + Response::standardError('maindomainnonexist', $domain, true); } if (Settings::Get('catchall.catchall_enabled') != '1') { @@ -90,8 +109,8 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $email_full = $email_part . '@' . $domain; // validate it - if (! \Froxlor\Validate\Validate::validateEmail($email_full)) { - \Froxlor\UI\Response::standard_error('emailiswrong', $email_full, true); + if (!Validate::validateEmail($email_full)) { + Response::standardError('emailiswrong', $email_full, true); } // get needed customer info to reduce the email-address-counter by one @@ -103,18 +122,18 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt WHERE (`email` = :email OR `email_full` = :emailfull ) AND `customerid`= :cid "); - $params = array( + $params = [ "email" => $email, "emailfull" => $email_full, "cid" => $customer['customerid'] - ); + ]; $email_check = Database::pexecute_first($stmt, $params, true, true); if ($email_check) { if (strtolower($email_check['email_full']) == strtolower($email_full)) { - \Froxlor\UI\Response::standard_error('emailexistalready', $email_full, true); + Response::standardError('emailexistalready', $email_full, true); } elseif ($email_check['email'] == $email) { - \Froxlor\UI\Response::standard_error('youhavealreadyacatchallforthisdomain', '', true); + Response::standardError('youhavealreadyacatchallforthisdomain', '', true); } } @@ -127,40 +146,40 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt `domainid` = :domainid, `description` = :description "); - $params = array( + $params = [ "cid" => $customer['customerid'], "email" => $email, "email_full" => $email_full, "iscatchall" => $iscatchall, "domainid" => $domain_check['id'], "description" => $description - ); + ]; Database::pexecute($stmt, $params, true, true); // update customer usage Customers::increaseUsage($customer['customerid'], 'emails_used'); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added email address '" . $email_full . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added email address '" . $email_full . "'"); - $result = $this->apiCall('Emails.get', array( + $result = $this->apiCall('Emails.get', [ 'emailaddr' => $email_full - )); + ]); return $this->response($result); } - throw new \Exception("No more resources available", 406); + throw new Exception("No more resources available", 406); } /** * return a email-address entry by either id or email-address * * @param int $id - * optional, the email-address-id + * optional, the email-address-id * @param string $emailaddr - * optional, the email-address + * optional, the email-address * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function get() { @@ -168,7 +187,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $ea_optional = $id > 0; $emailaddr = $this->getParam('emailaddr', $ea_optional, ''); - $params = array(); + $params = []; $customer_ids = $this->getAllowedCustomerIds('email'); $params['idea'] = ($id <= 0 ? $emailaddr : $id); @@ -180,56 +199,56 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt "); $result = Database::pexecute_first($result_stmt, $params, true, true); if ($result) { - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get email address '" . $result['email_full'] . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get email address '" . $result['email_full'] . "'"); return $this->response($result); } $key = ($id > 0 ? "id #" . $id : "emailaddr '" . $emailaddr . "'"); - throw new \Exception("Email address with " . $key . " could not be found", 404); + throw new Exception("Email address with " . $key . " could not be found", 404); } /** * toggle catchall flag of given email address either by id or email-address * * @param int $id - * optional, the email-address-id + * optional, the email-address-id * @param string $emailaddr - * optional, the email-address + * optional, the email-address * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * @param boolean $iscatchall - * optional + * optional * @param string $description - * optional custom description (currently not used/shown in the frontend), default empty + * optional custom description (currently not used/shown in the frontend), default empty * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function update() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } // if enabling catchall is not allowed by settings, we do not need // to run update() if (Settings::Get('catchall.catchall_enabled') != '1') { - \Froxlor\UI\Response::standard_error(array( + Response::standardError([ 'operationnotpermitted', 'featureisdisabled' - ), 'catchall', true); + ], 'catchall', true); } $id = $this->getParam('id', true, 0); $ea_optional = $id > 0; $emailaddr = $this->getParam('emailaddr', $ea_optional, ''); - $result = $this->apiCall('Emails.get', array( + $result = $this->apiCall('Emails.get', [ 'id' => $id, 'emailaddr' => $emailaddr - )); + ]); $id = $result['id']; // parameters @@ -249,13 +268,13 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt SELECT `email_full` FROM `" . TABLE_MAIL_VIRTUAL . "` WHERE `email` = :email AND `customerid` = :cid AND `iscatchall` = '1' "); - $params = array( + $params = [ "email" => $email, "cid" => $customer['customerid'] - ); + ]; $email_check = Database::pexecute_first($stmt, $params, true, true); if ($email_check) { - \Froxlor\UI\Response::standard_error('youhavealreadyacatchallforthisdomain', '', true); + Response::standardError('youhavealreadyacatchallforthisdomain', '', true); } } else { $iscatchall = '0'; @@ -267,47 +286,50 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt SET `email` = :email , `iscatchall` = :caflag, `description` = :description WHERE `customerid`= :cid AND `id`= :id "); - $params = array( + $params = [ "email" => $email, "caflag" => $iscatchall, "description" => $description, "cid" => $customer['customerid'], "id" => $id - ); + ]; Database::pexecute($stmt, $params, true, true); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] toggled catchall-flag for email address '" . $result['email_full'] . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] toggled catchall-flag for email address '" . $result['email_full'] . "'"); - $result = $this->apiCall('Emails.get', array( + $result = $this->apiCall('Emails.get', [ 'emailaddr' => $result['email_full'] - )); + ]); return $this->response($result); } /** - * list all email addresses, if called from an admin, list all email addresses of all customers you are allowed to view, or specify id or loginname for one specific customer + * list all email addresses, if called from an admin, list all email addresses of all customers you are allowed to + * view, or specify id or loginname for one specific customer * * @param int $customerid - * optional, admin-only, select email addresses of a specific customer by id + * optional, admin-only, select email addresses of a specific customer by id * @param string $loginname - * optional, admin-only, select email addresses of a specific customer by loginname + * optional, admin-only, select email addresses of a specific customer by loginname * @param array $sql_search - * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue * @param int $sql_limit - * optional specify number of results to be returned + * optional specify number of results to be returned * @param int $sql_offset - * optional specify offset for resultset + * optional specify offset for resultset * @param array $sql_orderby - * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more + * fields * * @access admin, customer - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listing() { $customer_ids = $this->getAllowedCustomerIds('email'); - $result = array(); - $query_fields = array(); + $result = []; + $query_fields = []; $result_stmt = Database::prepare(" SELECT m.`id`, m.`domainid`, m.`email`, m.`email_full`, m.`iscatchall`, m.`destination`, m.`popaccountid`, d.`domain`, u.`quota`, u.`imap`, u.`pop3`, u.`postfix`, u.`mboxsize` FROM `" . TABLE_MAIL_VIRTUAL . "` m @@ -315,27 +337,27 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON (m.`popaccountid` = u.`id`) WHERE m.`customerid` IN (" . implode(", ", $customer_ids) . ")" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); Database::pexecute($result_stmt, $query_fields, true, true); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $result[] = $row; } - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list email-addresses"); - return $this->response(array( + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list email-addresses"); + return $this->response([ 'count' => count($result), 'list' => $result - )); + ]); } /** * returns the total number of accessible email addresses * * @param int $customerid - * optional, admin-only, select email addresses of a specific customer by id + * optional, admin-only, select email addresses of a specific customer by id * @param string $loginname - * optional, admin-only, select email addresses of a specific customer by loginname + * optional, admin-only, select email addresses of a specific customer by loginname * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function listingCount() { @@ -357,34 +379,34 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt * delete an email address by either id or username * * @param int $id - * optional, the email-address-id + * optional, the email-address-id * @param string $emailaddr - * optional, the email-address + * optional, the email-address * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * @param boolean $delete_userfiles - * optional, delete email data from filesystem, default: 0 (false) + * optional, delete email data from filesystem, default: 0 (false) * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function delete() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $id = $this->getParam('id', true, 0); $ea_optional = $id > 0; $emailaddr = $this->getParam('emailaddr', $ea_optional, ''); - $result = $this->apiCall('Emails.get', array( + $result = $this->apiCall('Emails.get', [ 'id' => $id, 'emailaddr' => $emailaddr - )); + ]); $id = $result['id']; // parameters @@ -402,12 +424,12 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt // check whether this address is an account if ($result['popaccountid'] != 0) { // use EmailAccounts.delete - $this->apiCall('EmailAccounts.delete', array( + $this->apiCall('EmailAccounts.delete', [ 'id' => $result['id'], 'customerid' => $customer['customerid'], 'delete_userfiles' => $delete_userfiles - )); - $number_forwarders --; + ]); + $number_forwarders--; } // decrease forwarder counter @@ -416,13 +438,13 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt // delete address $stmt = Database::prepare("DELETE FROM `" . TABLE_MAIL_VIRTUAL . "` WHERE `customerid`= :customerid AND `id`= :id"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "customerid" => $customer['customerid'], "id" => $id - ), true, true); + ], true, true); Customers::decreaseUsage($customer['customerid'], 'emails_used'); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted email address '" . $result['email_full'] . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted email address '" . $result['email_full'] . "'"); return $this->response($result); } } diff --git a/lib/Froxlor/Api/Commands/FpmDaemons.php b/lib/Froxlor/Api/Commands/FpmDaemons.php index 9a2c6e56..85cd3145 100644 --- a/lib/Froxlor/Api/Commands/FpmDaemons.php +++ b/lib/Froxlor/Api/Commands/FpmDaemons.php @@ -1,63 +1,86 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Cron\TaskId; +use Froxlor\Database\Database; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; +use Froxlor\System\Cronjob; +use Froxlor\UI\Response; +use Froxlor\Validate\Validate; +use PDO; + +/** + * @since 0.10.0 + */ +class FpmDaemons extends ApiCommand implements ResourceEntity { /** * lists all fpm-daemon entries * * @param array $sql_search - * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue * @param int $sql_limit - * optional specify number of results to be returned + * optional specify number of results to be returned * @param int $sql_offset - * optional specify offset for resultset + * optional specify offset for resultset * @param array $sql_orderby - * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields - * + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more + * fields + * * @access admin - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listing() { if ($this->isAdmin()) { - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list fpm-daemons"); - $query_fields = array(); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list fpm-daemons"); + $query_fields = []; $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "`" . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit()); Database::pexecute($result_stmt, $query_fields, true, true); - $fpmdaemons = array(); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { - - $query_params = array( + $fpmdaemons = []; + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + $query_params = [ 'id' => $row['id'] - ); + ]; $configresult_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `fpmsettingid` = :id"); Database::pexecute($configresult_stmt, $query_params, true, true); - $configs = array(); + $configs = []; if (Database::num_rows() > 0) { - while ($row2 = $configresult_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row2 = $configresult_stmt->fetch(PDO::FETCH_ASSOC)) { $configs[] = $row2['description']; } } @@ -70,20 +93,20 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $fpmdaemons[] = $row; } - return $this->response(array( + return $this->response([ 'count' => count($fpmdaemons), 'list' => $fpmdaemons - )); + ]); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * returns the total number of accessible fpm daemons * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function listingCount() { @@ -96,18 +119,18 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc return $this->response($result['num_fpms']); } } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * return a fpm-daemon entry by id * * @param int $id - * fpm-daemon-id - * + * fpm-daemon-id + * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function get() { @@ -117,15 +140,15 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "` WHERE `id` = :id "); - $result = Database::pexecute_first($result_stmt, array( + $result = Database::pexecute_first($result_stmt, [ 'id' => $id - ), true, true); + ], true, true); if ($result) { return $this->response($result); } - throw new \Exception("fpm-daemon with id #" . $id . " could not be found", 404); + throw new Exception("fpm-daemon with id #" . $id . " could not be found", 404); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** @@ -135,32 +158,31 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc * @param string $reload_cmd * @param string $config_dir * @param string $pm - * optional, process-manager, one of 'static', 'dynamic' or 'ondemand', default 'dynamic' + * optional, process-manager, one of 'static', 'dynamic' or 'ondemand', default 'dynamic' * @param int $max_children - * optional, default 5 + * optional, default 5 * @param int $start_servers - * optional, default 2 + * optional, default 2 * @param int $min_spare_servers - * optional, default 1 + * optional, default 1 * @param int $max_spare_servers - * optional, default 3 + * optional, default 3 * @param int $max_requests - * optional, default 0 + * optional, default 0 * @param int $idle_timeout - * optional, default 10 + * optional, default 10 * @param string $limit_extensions - * optional, limit execution to the following extensions, default '.php' + * optional, limit execution to the following extensions, default '.php' * @param string $custom_config - * optional, custom settings appended to phpfpm pool configuration - * + * optional, custom settings appended to phpfpm pool configuration + * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function add() { if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) { - // required parameter $description = $this->getParam('description'); $reload_cmd = $this->getParam('reload_cmd'); @@ -178,23 +200,23 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $custom_config = $this->getParam('custom_config', true, ''); // validation - $description = \Froxlor\Validate\Validate::validate($description, 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true); - $reload_cmd = \Froxlor\Validate\Validate::validate($reload_cmd, 'reload_cmd', '', '', array(), true); - $config_dir = \Froxlor\Validate\Validate::validate($config_dir, 'config_dir', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true); - if (! in_array($pmanager, array( + $description = Validate::validate($description, 'description', Validate::REGEX_DESC_TEXT, '', [], true); + $reload_cmd = Validate::validate($reload_cmd, 'reload_cmd', '', '', [], true); + $config_dir = Validate::validate($config_dir, 'config_dir', Validate::REGEX_DIR, '', [], true); + if (!in_array($pmanager, [ 'static', 'dynamic', 'ondemand' - ))) { - throw new \Exception("Unknown process manager", 406); + ])) { + throw new Exception("Unknown process manager", 406); } if (empty($limit_extensions)) { $limit_extensions = '.php'; } - $limit_extensions = \Froxlor\Validate\Validate::validate($limit_extensions, 'limit_extensions', '/^(\.[a-z]([a-z0-9]+)\ ?)+$/', '', array(), true); + $limit_extensions = Validate::validate($limit_extensions, 'limit_extensions', '/^(\.[a-z]([a-z0-9]+)\ ?)+$/', '', [], true); if (strlen($description) == 0 || strlen($description) > 50) { - \Froxlor\UI\Response::standard_error('descriptioninvalid', '', true); + Response::standardError('descriptioninvalid', '', true); } $ins_stmt = Database::prepare(" @@ -212,10 +234,10 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc `limit_extensions` = :limit_extensions, `custom_config` = :custom_config "); - $ins_data = array( + $ins_data = [ 'desc' => $description, 'reload_cmd' => $reload_cmd, - 'config_dir' => \Froxlor\FileDir::makeCorrectDir($config_dir), + 'config_dir' => FileDir::makeCorrectDir($config_dir), 'pm' => $pmanager, 'max_children' => $max_children, 'start_servers' => $start_servers, @@ -225,64 +247,63 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc 'idle_timeout' => $idle_timeout, 'limit_extensions' => $limit_extensions, 'custom_config' => $custom_config - ); + ]; Database::pexecute($ins_stmt, $ins_data); $id = Database::lastInsertId(); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] fpm-daemon with description '" . $description . "' has been created by '" . $this->getUserDetail('loginname') . "'"); - $result = $this->apiCall('FpmDaemons.get', array( + Cronjob::inserttask(TaskId::REBUILD_VHOST); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] fpm-daemon with description '" . $description . "' has been created by '" . $this->getUserDetail('loginname') . "'"); + $result = $this->apiCall('FpmDaemons.get', [ 'id' => $id - )); + ]); return $this->response($result); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * update a fpm-daemon entry by given id * * @param int $id - * fpm-daemon id + * fpm-daemon id * @param string $description - * optional + * optional * @param string $reload_cmd - * optional + * optional * @param string $config_dir - * optional + * optional * @param string $pm - * optional, process-manager, one of 'static', 'dynamic' or 'ondemand', default 'dynamic' + * optional, process-manager, one of 'static', 'dynamic' or 'ondemand', default 'dynamic' * @param int $max_children - * optional, default 5 + * optional, default 5 * @param int $start_servers - * optional, default 2 + * optional, default 2 * @param int $min_spare_servers - * optional, default 1 + * optional, default 1 * @param int $max_spare_servers - * optional, default 3 + * optional, default 3 * @param int $max_requests - * optional, default 0 + * optional, default 0 * @param int $idle_timeout - * optional, default 10 + * optional, default 10 * @param string $limit_extensions - * optional, limit execution to the following extensions, default '.php' + * optional, limit execution to the following extensions, default '.php' * @param string $custom_config - * optional, custom settings appended to phpfpm pool configuration - * + * optional, custom settings appended to phpfpm pool configuration + * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function update() { if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) { - // required parameter $id = $this->getParam('id'); - $result = $this->apiCall('FpmDaemons.get', array( + $result = $this->apiCall('FpmDaemons.get', [ 'id' => $id - )); + ]); // parameters $description = $this->getParam('description', true, $result['description']); @@ -299,23 +320,23 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $custom_config = $this->getParam('custom_config', true, $result['custom_config']); // validation - $description = \Froxlor\Validate\Validate::validate($description, 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true); - $reload_cmd = \Froxlor\Validate\Validate::validate($reload_cmd, 'reload_cmd', '', '', array(), true); - $config_dir = \Froxlor\Validate\Validate::validate($config_dir, 'config_dir', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true); - if (! in_array($pmanager, array( + $description = Validate::validate($description, 'description', Validate::REGEX_DESC_TEXT, '', [], true); + $reload_cmd = Validate::validate($reload_cmd, 'reload_cmd', '', '', [], true); + $config_dir = Validate::validate($config_dir, 'config_dir', Validate::REGEX_DIR, '', [], true); + if (!in_array($pmanager, [ 'static', 'dynamic', 'ondemand' - ))) { - throw new \Exception("Unknown process manager", 406); + ])) { + throw new Exception("Unknown process manager", 406); } if (empty($limit_extensions)) { $limit_extensions = '.php'; } - $limit_extensions = \Froxlor\Validate\Validate::validate($limit_extensions, 'limit_extensions', '/^(\.[a-z]([a-z0-9]+)\ ?)+$/', '', array(), true); + $limit_extensions = Validate::validate($limit_extensions, 'limit_extensions', '/^(\.[a-z]([a-z0-9]+)\ ?)+$/', '', [], true); if (strlen($description) == 0 || strlen($description) > 50) { - \Froxlor\UI\Response::standard_error('descriptioninvalid', '', true); + Response::standardError('descriptioninvalid', '', true); } $upd_stmt = Database::prepare(" @@ -334,10 +355,10 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc `custom_config` = :custom_config WHERE `id` = :id "); - $upd_data = array( + $upd_data = [ 'desc' => $description, 'reload_cmd' => $reload_cmd, - 'config_dir' => \Froxlor\FileDir::makeCorrectDir($config_dir), + 'config_dir' => FileDir::makeCorrectDir($config_dir), 'pm' => $pmanager, 'max_children' => $max_children, 'start_servers' => $start_servers, @@ -348,28 +369,28 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc 'limit_extensions' => $limit_extensions, 'custom_config' => $custom_config, 'id' => $id - ); + ]; Database::pexecute($upd_stmt, $upd_data, true, true); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] fpm-daemon with description '" . $description . "' has been updated by '" . $this->getUserDetail('loginname') . "'"); - $result = $this->apiCall('FpmDaemons.get', array( + Cronjob::inserttask(TaskId::REBUILD_VHOST); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] fpm-daemon with description '" . $description . "' has been updated by '" . $this->getUserDetail('loginname') . "'"); + $result = $this->apiCall('FpmDaemons.get', [ 'id' => $id - )); + ]); return $this->response($result); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * delete a fpm-daemon entry by id * * @param int $id - * fpm-daemon-id - * + * fpm-daemon-id + * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function delete() { @@ -377,33 +398,33 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $id = $this->getParam('id'); if ($id == 1) { - \Froxlor\UI\Response::standard_error('cannotdeletedefaultphpconfig', '', true); + Response::standardError('cannotdeletedefaultphpconfig', '', true); } - $result = $this->apiCall('FpmDaemons.get', array( + $result = $this->apiCall('FpmDaemons.get', [ 'id' => $id - )); + ]); // set default fpm daemon config for all php-config that use this config that is to be deleted $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_PHPCONFIGS . "` SET `fpmsettingid` = '1' WHERE `fpmsettingid` = :id "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'id' => $id - ), true, true); + ], true, true); $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_FPMDAEMONS . "` WHERE `id` = :id "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'id' => $id - ), true, true); + ], true, true); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] fpm-daemon setting '" . $result['description'] . "' has been deleted by '" . $this->getUserDetail('loginname') . "'"); + Cronjob::inserttask(TaskId::REBUILD_VHOST); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] fpm-daemon setting '" . $result['description'] . "' has been deleted by '" . $this->getUserDetail('loginname') . "'"); return $this->response($result); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } } diff --git a/lib/Froxlor/Api/Commands/Froxlor.php b/lib/Froxlor/Api/Commands/Froxlor.php index 6d97fa3c..3cc0fb1e 100644 --- a/lib/Froxlor/Api/Commands/Froxlor.php +++ b/lib/Froxlor/Api/Commands/Froxlor.php @@ -1,33 +1,61 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class Froxlor extends \Froxlor\Api\ApiCommand + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Cron\TaskId; +use Froxlor\Database\Database; +use Froxlor\Database\IntegrityCheck; +use Froxlor\FroxlorLogger; +use Froxlor\Http\HttpClient; +use Froxlor\Settings; +use Froxlor\SImExporter; +use Froxlor\System\Cronjob; +use Froxlor\System\Crypt; +use Froxlor\UI\Response; +use PDO; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use ReflectionClass; +use ReflectionException; +use ReflectionMethod; + +/** + * @since 0.10.0 + */ +class Froxlor extends ApiCommand { /** * checks whether there is a newer version of froxlor available * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function checkUpdate() { @@ -36,12 +64,12 @@ class Froxlor extends \Froxlor\Api\ApiCommand if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) { if (function_exists('curl_version')) { // log our actions - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] checking for updates"); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] checking for updates"); // check for new version try { - $latestversion = \Froxlor\Http\HttpClient::urlGet(UPDATE_URI, true, 3); - } catch (\Exception $e) { + $latestversion = HttpClient::urlGet(UPDATE_URI, true, 3); + } catch (Exception $e) { $latestversion = \Froxlor\Froxlor::getVersion() . "|Version-check currently unavailable, please try again later"; } $latestversion = explode('|', $latestversion); @@ -58,11 +86,11 @@ class Froxlor extends \Froxlor\Api\ApiCommand $message_addinfo = $_message; // not numeric -> error-message - if (! preg_match('/^((\d+\\.)(\d+\\.)(\d+\\.)?(\d+)?(\-(svn|dev|rc)(\d+))?)$/', $_version)) { + if (!preg_match('/^((\d+\\.)(\d+\\.)(\d+\\.)?(\d+)?(\-(svn|dev|rc)(\d+))?)$/', $_version)) { // check for customized version to not output // "There is a newer version of froxlor" besides the error-message - $isnewerversion = - 1; - } elseif (\Froxlor\Froxlor::versionCompare2($this->version, $_version) == - 1) { + $isnewerversion = -1; + } elseif (\Froxlor\Froxlor::versionCompare2($this->version, $_version) == -1) { // there is a newer version - yay $isnewerversion = 1; } else { @@ -74,92 +102,92 @@ class Froxlor extends \Froxlor\Api\ApiCommand // zum update schritt #1 -> download if ($isnewerversion == 1) { $text = 'There is a newer version available: "' . $_version . '" (Your current version is: ' . $this->version . ')'; - return $this->response(array( + return $this->response([ 'isnewerversion' => $isnewerversion, 'version' => $_version, 'message' => $text, 'link' => $version_link, 'additional_info' => $message_addinfo - )); + ]); } elseif ($isnewerversion == 0) { // all good - return $this->response(array( + return $this->response([ 'isnewerversion' => $isnewerversion, 'version' => $version_label, 'message' => "", 'link' => $version_link, 'additional_info' => $message_addinfo - )); + ]); } else { - \Froxlor\UI\Response::standard_error('customized_version', '', true); + Response::standardError('customized_version', '', true); } } } - return $this->response(array( + return $this->response([ 'isnewerversion' => 0, 'version' => $this->version . $this->branding, 'message' => 'Version-check not available due to missing php-curl extension', 'link' => UPDATE_URI . '/pretty', 'additional_info' => "" - ), 502); + ], 502); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * import settings * * @param string $json_str - * content of exported froxlor-settings json file - * + * content of exported froxlor-settings json file + * * @access admin - * @throws \Exception * @return string json-encoded bool + * @throws Exception */ public function importSettings() { if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) { $json_str = $this->getParam('json_str'); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "User " . $this->getUserDetail('loginname') . " imported settings"); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "User " . $this->getUserDetail('loginname') . " imported settings"); try { - \Froxlor\SImExporter::import($json_str); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_QUOTA); + SImExporter::import($json_str); + Cronjob::inserttask(TaskId::REBUILD_VHOST); + Cronjob::inserttask(TaskId::CREATE_QUOTA); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); + Cronjob::inserttask(TaskId::REBUILD_DNS); // cron.d file - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_CRON); + Cronjob::inserttask(TaskId::REBUILD_CRON); return $this->response(true); - } catch (\Exception $e) { - throw new \Exception($e->getMessage(), 406); + } catch (Exception $e) { + throw new Exception($e->getMessage(), 406); } } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * export settings * * @access admin - * @throws \Exception * @return string json-string + * @throws Exception */ public function exportSettings() { if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) { - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "User " . $this->getUserDetail('loginname') . " exported settings"); - $json_export = \Froxlor\SImExporter::export(); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "User " . $this->getUserDetail('loginname') . " exported settings"); + $json_export = SImExporter::export(); return $this->response($json_export); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * return a list of all settings * * @access admin - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listSettings() { @@ -168,30 +196,30 @@ class Froxlor extends \Froxlor\Api\ApiCommand SELECT * FROM `" . TABLE_PANEL_SETTINGS . "` ORDER BY settinggroup ASC, varname ASC "); Database::pexecute($sel_stmt, null, true, true); - $result = array(); - while ($row = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) { - $result[] = array( + $result = []; + while ($row = $sel_stmt->fetch(PDO::FETCH_ASSOC)) { + $result[] = [ 'key' => $row['settinggroup'] . '.' . $row['varname'], 'value' => $row['value'] - ); + ]; } - return $this->response(array( + return $this->response([ 'count' => count($result), 'list' => $result - )); + ]); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * return a setting by settinggroup.varname couple * * @param string $key - * settinggroup.varname couple - * + * settinggroup.varname couple + * * @access admin - * @throws \Exception * @return string + * @throws Exception */ public function getSetting() { @@ -199,37 +227,37 @@ class Froxlor extends \Froxlor\Api\ApiCommand $setting = $this->getParam('key'); return $this->response(Settings::Get($setting)); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * updates a setting * * @param string $key - * settinggroup.varname couple + * settinggroup.varname couple * @param string $value - * optional the new value, default is '' - * + * optional the new value, default is '' + * * @access admin - * @throws \Exception * @return string + * @throws Exception */ public function updateSetting() { // currently not implemented as it requires validation too so no wrong settings are being stored via API - throw new \Exception("Not available yet.", 501); + throw new Exception("Not available yet.", 501); if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) { $setting = $this->getParam('key'); $value = $this->getParam('value', true, ''); $oldvalue = Settings::Get($setting); if (is_null($oldvalue)) { - throw new \Exception("Setting '" . $setting . "' could not be found"); + throw new Exception("Setting '" . $setting . "' could not be found"); } - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] Changing setting '" . $setting . "' from '" . $oldvalue . "' to '" . $value . "'"); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] Changing setting '" . $setting . "' from '" . $oldvalue . "' to '" . $value . "'"); return $this->response(Settings::Set($setting, $value, true)); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** @@ -240,56 +268,56 @@ class Froxlor extends \Froxlor\Api\ApiCommand */ public function generatePassword() { - return $this->response(\Froxlor\System\Crypt::generatePassword()); + return $this->response(Crypt::generatePassword()); } /** * can be used to remotely run the integritiy checks froxlor implements * * @access admin - * @throws \Exception * @return string + * @throws Exception */ public function integrityCheck() { if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) { - $integrity = new \Froxlor\Database\IntegrityCheck(); + $integrity = new IntegrityCheck(); $result = $integrity->checkAll(); if ($result) { return $this->response(null, 204); } - throw new \Exception("Some checks failed.", 406); + throw new Exception("Some checks failed.", 406); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * returns a list of all available api functions * * @param string $module - * optional, return list of functions for a specific module - * + * optional, return list of functions for a specific module + * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function listFunctions() { $module = $this->getParam('module', true, ''); - $functions = array(); + $functions = []; if ($module != null) { // check existence $this->requireModules($module); // now get all static functions - $reflection = new \ReflectionClass(__NAMESPACE__ . '\\' . $module); - $_functions = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC); + $reflection = new ReflectionClass(__NAMESPACE__ . '\\' . $module); + $_functions = $reflection->getMethods(ReflectionMethod::IS_PUBLIC); foreach ($_functions as $func) { if ($func->class == __NAMESPACE__ . '\\' . $module && $func->isPublic()) { - array_push($functions, array_merge(array( + array_push($functions, array_merge([ 'module' => $module, 'function' => $func->name - ), $this->getParamListFromDoc($module, $func->name))); + ], $this->getParamListFromDoc($module, $func->name))); } } } else { @@ -298,37 +326,37 @@ class Froxlor extends \Froxlor\Api\ApiCommand // valid directory? if (is_dir($path)) { // create RecursiveIteratorIterator - $its = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path)); + $its = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)); // check every file foreach ($its as $it) { // does it match the Filename pattern? - $matches = array(); + $matches = []; if (preg_match("/^(.+)\.php$/i", $it->getFilename(), $matches)) { // check for existence try { // set the module to be in our namespace $mod = $matches[1]; $this->requireModules($mod); - } catch (\Exception $e) { + } catch (Exception $e) { // @todo log? continue; } // now get all static functions - $reflection = new \ReflectionClass(__NAMESPACE__ . '\\' . $mod); - $_functions = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC); + $reflection = new ReflectionClass(__NAMESPACE__ . '\\' . $mod); + $_functions = $reflection->getMethods(ReflectionMethod::IS_PUBLIC); foreach ($_functions as $func) { - if ($func->class == __NAMESPACE__ . '\\' . $mod && $func->isPublic() && ! $func->isStatic()) { - array_push($functions, array_merge(array( + if ($func->class == __NAMESPACE__ . '\\' . $mod && $func->isPublic() && !$func->isStatic()) { + array_push($functions, array_merge([ 'module' => $matches[1], 'function' => $func->name - ), $this->getParamListFromDoc($matches[1], $func->name))); + ], $this->getParamListFromDoc($matches[1], $func->name))); } } } } } else { // yikes - no valid directory to check - throw new \Exception("Cannot search directory '" . $path . "'. No such directory.", 500); + throw new Exception("Cannot search directory '" . $path . "'. No such directory.", 500); } } @@ -336,6 +364,45 @@ class Froxlor extends \Froxlor\Api\ApiCommand return $this->response($functions); } + /** + * this functions is used to check the availability + * of a given list of modules. + * If either one of + * them are not found, throw an Exception + * + * @param string|array $modules + * + * @throws Exception + */ + private function requireModules($modules = null) + { + if ($modules != null) { + // no array -> create one + if (!is_array($modules)) { + $modules = [ + $modules + ]; + } + // check all the modules + foreach ($modules as $module) { + try { + $module = __NAMESPACE__ . '\\' . $module; + // can we use the class? + if (class_exists($module)) { + continue; + } else { + throw new Exception('The required class "' . $module . '" could not be found but the module-file exists', 404); + } + } catch (Exception $e) { + // The autoloader will throw an Exception + // that the required class could not be found + // but we want a nicer error-message for this here + throw new Exception('The required module "' . $module . '" could not be found', 404); + } + } + } + } + /** * generate an api-response to list all parameters and the return-value of * a given module.function-combination @@ -343,59 +410,59 @@ class Froxlor extends \Froxlor\Api\ApiCommand * @param string $module * @param string $function * - * @throws \Exception * @return array|bool + * @throws Exception */ private function getParamListFromDoc($module = null, $function = null) { try { // set the module - $cls = new \ReflectionMethod(__NAMESPACE__ . '\\' . $module, $function); + $cls = new ReflectionMethod(__NAMESPACE__ . '\\' . $module, $function); $comment = $cls->getDocComment(); if ($comment == false) { - return array( + return [ 'head' => 'There is no comment-block for "' . $module . '.' . $function . '"' - ); + ]; } $clines = explode("\n", $comment); - $result = array(); - $result['params'] = array(); + $result = []; + $result['params'] = []; $param_desc = false; - $r = array(); + $r = []; foreach ($clines as $c) { $c = trim($c); // check param-section if (strpos($c, '@param')) { preg_match('/^\*\s\@param\s(.+)\s(\$\w+)(\s.*)?/', $c, $r); // cut $ off the parameter-name as it is not wanted in the api-request - $result['params'][] = array( + $result['params'][] = [ 'parameter' => substr($r[2], 1), 'type' => $r[1], 'desc' => (isset($r[3]) ? trim($r['3']) : '') - ); + ]; $param_desc = true; } elseif (strpos($c, '@access')) { // check access-section preg_match('/^\*\s\@access\s(.*)/', $c, $r); - if (! isset($r[0]) || empty($r[0])) { + if (!isset($r[0]) || empty($r[0])) { $r[1] = 'This function has no restrictions'; } - $result['access'] = array( + $result['access'] = [ 'groups' => (isset($r[1]) ? trim($r[1]) : '') - ); + ]; } elseif (strpos($c, '@return')) { // check return-section preg_match('/^\*\s\@return\s(\w+)(\s.*)?/', $c, $r); - if (! isset($r[0]) || empty($r[0])) { + if (!isset($r[0]) || empty($r[0])) { $r[1] = 'null'; $r[2] = 'This function has no return value given'; } - $result['return'] = array( + $result['return'] = [ 'type' => $r[1], 'desc' => (isset($r[2]) ? trim($r[2]) : '') - ); - } elseif (! empty($c) && strpos($c, '@throws') === false) { + ]; + } elseif (!empty($c) && strpos($c, '@throws') === false) { // check throws-section if (substr($c, 0, 3) == "/**") { continue; @@ -411,7 +478,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand if ($param_desc) { $result['params'][count($result['params']) - 1]['desc'] .= $c; } else { - if (! isset($result['head']) || empty($result['head'])) { + if (!isset($result['head']) || empty($result['head'])) { $result['head'] = $c . " "; } else { $result['head'] .= $c . " "; @@ -422,47 +489,8 @@ class Froxlor extends \Froxlor\Api\ApiCommand } $result['head'] = trim($result['head']); return $result; - } catch (\ReflectionException $e) { - return array(); - } - } - - /** - * this functions is used to check the availability - * of a given list of modules. - * If either one of - * them are not found, throw an Exception - * - * @param string|array $modules - * - * @throws \Exception - */ - private function requireModules($modules = null) - { - if ($modules != null) { - // no array -> create one - if (! is_array($modules)) { - $modules = array( - $modules - ); - } - // check all the modules - foreach ($modules as $module) { - try { - $module = __NAMESPACE__ . '\\' . $module; - // can we use the class? - if (class_exists($module)) { - continue; - } else { - throw new \Exception('The required class "' . $module . '" could not be found but the module-file exists', 404); - } - } catch (\Exception $e) { - // The autoloader will throw an Exception - // that the required class could not be found - // but we want a nicer error-message for this here - throw new \Exception('The required module "' . $module . '" could not be found', 404); - } - } + } catch (ReflectionException $e) { + return []; } } } diff --git a/lib/Froxlor/Api/Commands/Ftps.php b/lib/Froxlor/Api/Commands/Ftps.php index 12c1467d..37a8dda0 100644 --- a/lib/Froxlor/Api/Commands/Ftps.php +++ b/lib/Froxlor/Api/Commands/Ftps.php @@ -1,67 +1,91 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Cron\TaskId; +use Froxlor\Database\Database; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; +use Froxlor\Idna\IdnaWrapper; +use Froxlor\Settings; +use Froxlor\System\Cronjob; +use Froxlor\System\Crypt; +use Froxlor\UI\Response; +use Froxlor\User; +use Froxlor\Validate\Validate; +use PDO; + +/** + * @since 0.10.0 + */ +class Ftps extends ApiCommand implements ResourceEntity { /** * add a new ftp-user * * @param string $ftp_password - * password for the created database and database-user + * password for the created database and database-user * @param string $path - * destination path relative to the customers-homedir + * destination path relative to the customers-homedir * @param string $ftp_description - * optional, description for ftp-user + * optional, description for ftp-user * @param bool $sendinfomail - * optional, send created resource-information to customer, default: false + * optional, send created resource-information to customer, default: false * @param string $shell - * optional, default /bin/false (not changeable when deactivated) + * optional, default /bin/false (not changeable when deactivated) * @param string $ftp_username - * optional if customer.ftpatdomain is allowed, specify an username + * optional if customer.ftpatdomain is allowed, specify an username * @param string $ftp_domain - * optional if customer.ftpatdomain is allowed, specify a domain (customer must be owner) + * optional if customer.ftpatdomain is allowed, specify a domain (customer must be owner) * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * @param array $additional_members - * optional whether to add additional usernames to the group + * optional whether to add additional usernames to the group * @param bool $is_defaultuser - * optional whether this is the standard default ftp user which is being added so no usage is decreased + * optional whether this is the standard default ftp user which is being added so no usage is decreased * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function add() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'ftp')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $is_defaultuser = $this->getBoolParam('is_defaultuser', true, 0); if (($this->getUserDetail('ftps_used') < $this->getUserDetail('ftps') || $this->getUserDetail('ftps') == '-1') || $this->isAdmin() && $is_defaultuser == 1) { - // required parameters $path = $this->getParam('path'); $password = $this->getParam('ftp_password'); @@ -74,28 +98,28 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit $ftpusername = $this->getParam('ftp_username', true, ''); $ftpdomain = $this->getParam('ftp_domain', true, ''); - $additional_members = $this->getParam('additional_members', true, array()); + $additional_members = $this->getParam('additional_members', true, []); // validation - $password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true); - $password = \Froxlor\System\Crypt::validatePassword($password, true); - $description = \Froxlor\Validate\Validate::validate(trim($description), 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true); + $password = Validate::validate($password, 'password', '', '', [], true); + $password = Crypt::validatePassword($password, true); + $description = Validate::validate(trim($description), 'description', Validate::REGEX_DESC_TEXT, '', [], true); if (Settings::Get('system.allow_customer_shell') == '1') { - $shell = \Froxlor\Validate\Validate::validate(trim($shell), 'shell', '', '', array(), true); + $shell = Validate::validate(trim($shell), 'shell', '', '', [], true); } else { $shell = "/bin/false"; } if (Settings::Get('customer.ftpatdomain') == '1') { - $ftpusername = \Froxlor\Validate\Validate::validate(trim($ftpusername), 'username', '/^[a-zA-Z0-9][a-zA-Z0-9\-_]+\$?$/', '', array(), true); + $ftpusername = Validate::validate(trim($ftpusername), 'username', '/^[a-zA-Z0-9][a-zA-Z0-9\-_]+\$?$/', '', [], true); if (substr($ftpdomain, 0, 4) != 'xn--') { - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); - $ftpdomain = $idna_convert->encode(\Froxlor\Validate\Validate::validate($ftpdomain, 'domain', '', '', array(), true)); + $idna_convert = new IdnaWrapper(); + $ftpdomain = $idna_convert->encode(Validate::validate($ftpdomain, 'domain', '', '', [], true)); } } - $params = array(); + $params = []; // get needed customer info to reduce the ftp-user-counter by one if ($is_defaultuser) { // no resource check for default user @@ -108,23 +132,23 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit $sendinfomail = 0; } - if (Settings::Get('customer.ftpatdomain') == '1' && ! $is_defaultuser) { + if (Settings::Get('customer.ftpatdomain') == '1' && !$is_defaultuser) { if ($ftpusername == '') { - \Froxlor\UI\Response::standard_error(array( + Response::standardError([ 'stringisempty', 'username' - ), '', true); + ], '', true); } $ftpdomain_check_stmt = Database::prepare("SELECT `id`, `domain`, `customerid` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `domain` = :domain AND `customerid` = :customerid"); - $ftpdomain_check = Database::pexecute_first($ftpdomain_check_stmt, array( + $ftpdomain_check = Database::pexecute_first($ftpdomain_check_stmt, [ "domain" => $ftpdomain, "customerid" => $customer['customerid'] - ), true, true); + ], true, true); if ($ftpdomain_check && $ftpdomain_check['domain'] != $ftpdomain) { - \Froxlor\UI\Response::standard_error('maindomainnonexist', $ftpdomain, true); + Response::standardError('maindomainnonexist', $ftpdomain, true); } $username = $ftpusername . "@" . $ftpdomain; } else { @@ -138,22 +162,22 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit $username_check_stmt = Database::prepare(" SELECT * FROM `" . TABLE_FTP_USERS . "` WHERE `username` = :username "); - $username_check = Database::pexecute_first($username_check_stmt, array( + $username_check = Database::pexecute_first($username_check_stmt, [ "username" => $username - ), true, true); + ], true, true); - if (! empty($username_check) && $username_check['username'] = $username) { - \Froxlor\UI\Response::standard_error('usernamealreadyexists', $username, true); + if (!empty($username_check) && $username_check['username'] = $username) { + Response::standardError('usernamealreadyexists', $username, true); } elseif ($username == $password) { - \Froxlor\UI\Response::standard_error('passwordshouldnotbeusername', '', true); + Response::standardError('passwordshouldnotbeusername', '', true); } else { - $path = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path); - $cryptPassword = \Froxlor\System\Crypt::makeCryptPassword($password); + $path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path); + $cryptPassword = Crypt::makeCryptPassword($password); $stmt = Database::prepare("INSERT INTO `" . TABLE_FTP_USERS . "` (`customerid`, `username`, `description`, `password`, `homedir`, `login_enabled`, `uid`, `gid`, `shell`) VALUES (:customerid, :username, :description, :password, :homedir, 'y', :guid, :guid, :shell)"); - $params = array( + $params = [ "customerid" => $customer['customerid'], "username" => $username, "description" => $description, @@ -161,25 +185,25 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit "homedir" => $path, "guid" => $customer['guid'], "shell" => $shell - ); + ]; Database::pexecute($stmt, $params, true, true); $result_stmt = Database::prepare(" SELECT `bytes_in_used` FROM `" . TABLE_FTP_QUOTATALLIES . "` WHERE `name` = :name "); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ "name" => $customer['loginname'] - ), true, true); + ], true, true); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $stmt = Database::prepare("INSERT INTO `" . TABLE_FTP_QUOTATALLIES . "` (`name`, `quota_type`, `bytes_in_used`, `bytes_out_used`, `bytes_xfer_used`, `files_in_used`, `files_out_used`, `files_xfer_used`) VALUES (:name, 'user', :bytes_in_used, '0', '0', '0', '0', '0') "); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "name" => $username, "bytes_in_used" => $row['bytes_in_used'] - ), true, true); + ], true, true); } // create quotatallies entry if it not exists, refs #885 @@ -188,9 +212,9 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit (`name`, `quota_type`, `bytes_in_used`, `bytes_out_used`, `bytes_xfer_used`, `files_in_used`, `files_out_used`, `files_xfer_used`) VALUES (:name, 'user', '0', '0', '0', '0', '0', '0') "); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "name" => $username - ), true, true); + ], true, true); } $group_upd_stmt = Database::prepare(" @@ -198,11 +222,11 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit SET `members` = CONCAT_WS(',',`members`, :username) WHERE `customerid`= :customerid AND `gid`= :guid "); - $params = array( + $params = [ "username" => $username, "customerid" => $customer['customerid'], "guid" => $customer['guid'] - ); + ]; if ($is_defaultuser) { // add the new group @@ -218,36 +242,37 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit if (count($additional_members) > 0) { foreach ($additional_members as $add_member) { - $params = array( + $params = [ "username" => $add_member, "customerid" => $customer['customerid'], "guid" => $customer['guid'] - ); + ]; Database::pexecute($group_upd_stmt, $params, true, true); } } - if (! $is_defaultuser) { + if (!$is_defaultuser) { // update customer usage Customers::increaseUsage($customer['customerid'], 'ftps_used'); Customers::increaseUsage($customer['customerid'], 'ftp_lastaccountnumber'); } - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added ftp-account '" . $username . " (" . $path . ")'"); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_FTP); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added ftp-account '" . $username . " (" . $path . ")'"); + Cronjob::inserttask(TaskId::CREATE_FTP); if ($sendinfomail == 1) { - $replace_arr = array( - 'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($customer), - 'CUST_NAME' => \Froxlor\User::getCorrectUserSalutation($customer), // < keep this for compatibility + $replace_arr = [ + 'SALUTATION' => User::getCorrectUserSalutation($customer), + 'CUST_NAME' => User::getCorrectUserSalutation($customer), + // < keep this for compatibility 'NAME' => $customer['name'], 'FIRSTNAME' => $customer['firstname'], 'COMPANY' => $customer['company'], 'CUSTOMER_NO' => $customer['customernumber'], 'USR_NAME' => $username, 'USR_PASS' => htmlentities(htmlentities($password)), - 'USR_PATH' => \Froxlor\FileDir::makeCorrectDir(str_replace($customer['documentroot'], "/", $path)) - ); + 'USR_PATH' => FileDir::makeCorrectDir(str_replace($customer['documentroot'], "/", $path)) + ]; // get template for mail subject $mail_subject = $this->getMailTemplate($customer, 'mails', 'new_ftpaccount_by_customer_subject', $replace_arr, lng('mails.new_ftpaccount_by_customer.subject')); // get template for mail body @@ -259,45 +284,45 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit $this->mailer()->Subject = $mail_subject; $this->mailer()->AltBody = $mail_body; $this->mailer()->msgHTML(str_replace("\n", "
", $mail_body)); - $this->mailer()->addAddress($customer['email'], \Froxlor\User::getCorrectUserSalutation($customer)); + $this->mailer()->addAddress($customer['email'], User::getCorrectUserSalutation($customer)); $this->mailer()->send(); } 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) { - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg); - \Froxlor\UI\Response::standard_error('errorsendingmail', $customer['email'], true); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg); + Response::standardError('errorsendingmail', $customer['email'], true); } $this->mailer()->clearAddresses(); } - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] added ftp-user '" . $username . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] added ftp-user '" . $username . "'"); - $result = $this->apiCall('Ftps.get', array( + $result = $this->apiCall('Ftps.get', [ 'username' => $username - )); + ]); return $this->response($result); } } - throw new \Exception("No more resources available", 406); + throw new Exception("No more resources available", 406); } /** * return a ftp-user entry by either id or username * * @param int $id - * optional, the customer-id + * optional, the customer-id * @param string $username - * optional, the username + * optional, the username * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function get() { @@ -305,14 +330,14 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit $un_optional = $id > 0; $username = $this->getParam('username', $un_optional, ''); - $params = array(); + $params = []; if ($this->isAdmin()) { if ($this->getUserDetail('customers_see_all') == false) { // if it's a reseller or an admin who cannot see all customers, we need to check // whether the database belongs to one of his customers $_custom_list_result = $this->apiCall('Customers.listing'); $custom_list_result = $_custom_list_result['list']; - $customer_ids = array(); + $customer_ids = []; foreach ($custom_list_result as $customer) { $customer_ids[] = $customer['customerid']; } @@ -329,7 +354,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit } } else { if (Settings::IsInList('panel.customer_hide_options', 'ftp')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_FTP_USERS . "` @@ -341,51 +366,51 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit $params['idun'] = ($id <= 0 ? $username : $id); $result = Database::pexecute_first($result_stmt, $params, true, true); if ($result) { - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get ftp-user '" . $result['username'] . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get ftp-user '" . $result['username'] . "'"); return $this->response($result); } $key = ($id > 0 ? "id #" . $id : "username '" . $username . "'"); - throw new \Exception("FTP user with " . $key . " could not be found", 404); + throw new Exception("FTP user with " . $key . " could not be found", 404); } /** * update a given ftp-user by id or username * * @param int $id - * optional, the ftp-user-id + * optional, the ftp-user-id * @param string $username - * optional, the username + * optional, the username * @param string $ftp_password - * optional, update password if specified + * optional, update password if specified * @param string $path - * destination path relative to the customers-homedir + * destination path relative to the customers-homedir * @param string $ftp_description - * optional, description for ftp-user + * optional, description for ftp-user * @param string $shell - * optional, default /bin/false (not changeable when deactivated) + * optional, default /bin/false (not changeable when deactivated) * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function update() { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'ftp')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $id = $this->getParam('id', true, 0); $un_optional = $id > 0; $username = $this->getParam('username', $un_optional, ''); - $result = $this->apiCall('Ftps.get', array( + $result = $this->apiCall('Ftps.get', [ 'id' => $id, 'username' => $username - )); + ]); $id = $result['id']; // parameters @@ -395,11 +420,11 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit $shell = $this->getParam('shell', true, $result['shell']); // validation - $password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true); - $description = \Froxlor\Validate\Validate::validate(trim($description), 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true); + $password = Validate::validate($password, 'password', '', '', [], true); + $description = Validate::validate(trim($description), 'description', Validate::REGEX_DESC_TEXT, '', [], true); if (Settings::Get('system.allow_customer_shell') == '1') { - $shell = \Froxlor\Validate\Validate::validate(trim($shell), 'shell', '', '', array(), true); + $shell = Validate::validate(trim($shell), 'shell', '', '', [], true); } else { $shell = "/bin/false"; } @@ -410,29 +435,29 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit // password update? if ($password != '') { // validate password - $password = \Froxlor\System\Crypt::validatePassword($password, true); + $password = Crypt::validatePassword($password, true); if ($password == $result['username']) { - \Froxlor\UI\Response::standard_error('passwordshouldnotbeusername', '', true); + Response::standardError('passwordshouldnotbeusername', '', true); } - $cryptPassword = \Froxlor\System\Crypt::makeCryptPassword($password); + $cryptPassword = Crypt::makeCryptPassword($password); $stmt = Database::prepare("UPDATE `" . TABLE_FTP_USERS . "` SET `password` = :password WHERE `customerid` = :customerid AND `id` = :id "); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "customerid" => $customer['customerid'], "id" => $id, "password" => $cryptPassword - ), true, true); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] updated ftp-account password for '" . $result['username'] . "'"); + ], true, true); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] updated ftp-account password for '" . $result['username'] . "'"); } // path update? if ($path != '') { - $path = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path); + $path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path); if ($path != $result['homedir']) { $stmt = Database::prepare("UPDATE `" . TABLE_FTP_USERS . "` @@ -440,17 +465,17 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit WHERE `customerid` = :customerid AND `id` = :id "); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "homedir" => $path, "customerid" => $customer['customerid'], "id" => $id - ), true, true); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] updated ftp-account homdir for '" . $result['username'] . "'"); + ], true, true); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] updated ftp-account homdir for '" . $result['username'] . "'"); } } // it's the task for "new ftp" but that will // create all directories and correct their permissions - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_FTP); + Cronjob::inserttask(TaskId::CREATE_FTP); $stmt = Database::prepare(" UPDATE `" . TABLE_FTP_USERS . "` @@ -458,75 +483,78 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit WHERE `customerid` = :customerid AND `id` = :id "); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "desc" => $description, "shell" => $shell, "customerid" => $customer['customerid'], "id" => $id - ), true, true); + ], true, true); - $result = $this->apiCall('Ftps.get', array( + $result = $this->apiCall('Ftps.get', [ 'username' => $result['username'] - )); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] updated ftp-user '" . $result['username'] . "'"); + ]); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] updated ftp-user '" . $result['username'] . "'"); return $this->response($result); } /** - * list all ftp-users, if called from an admin, list all ftp-users of all customers you are allowed to view, or specify id or loginname for one specific customer + * list all ftp-users, if called from an admin, list all ftp-users of all customers you are allowed to view, or + * specify id or loginname for one specific customer * * @param int $customerid - * optional, admin-only, select ftp-users of a specific customer by id + * optional, admin-only, select ftp-users of a specific customer by id * @param string $loginname - * optional, admin-only, select ftp-users of a specific customer by loginname + * optional, admin-only, select ftp-users of a specific customer by loginname * @param array $sql_search - * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue * @param int $sql_limit - * optional specify number of results to be returned + * optional specify number of results to be returned * @param int $sql_offset - * optional specify offset for resultset + * optional specify offset for resultset * @param array $sql_orderby - * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more + * fields * * @access admin, customer - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listing() { $customer_ids = $this->getAllowedCustomerIds('ftp'); - $result = array(); - $query_fields = array(); + $result = []; + $query_fields = []; $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_FTP_USERS . "` WHERE `customerid` IN (" . implode(", ", $customer_ids) . ")" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); Database::pexecute($result_stmt, $query_fields, true, true); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $result[] = $row; } - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list ftp-users"); - return $this->response(array( + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list ftp-users"); + return $this->response([ 'count' => count($result), 'list' => $result - )); + ]); } /** * returns the total number of accessible ftp accounts * * @param int $customerid - * optional, admin-only, select ftp-users of a specific customer by id + * optional, admin-only, select ftp-users of a specific customer by id * @param string $loginname - * optional, admin-only, select ftp-users of a specific customer by loginname + * optional, admin-only, select ftp-users of a specific customer by loginname * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function listingCount() { $customer_ids = $this->getAllowedCustomerIds('ftp'); - $result = array(); + $result = []; $result_stmt = Database::prepare(" SELECT COUNT(*) as num_ftps FROM `" . TABLE_FTP_USERS . "` WHERE `customerid` IN (" . implode(", ", $customer_ids) . ") @@ -541,15 +569,15 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit * delete a ftp-user by either id or username * * @param int $id - * optional, the ftp-user-id + * optional, the ftp-user-id * @param string $username - * optional, the username + * optional, the username * @param bool $delete_userfiles - * optional, default false + * optional, default false * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function delete() { @@ -559,21 +587,21 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit $delete_userfiles = $this->getBoolParam('delete_userfiles', true, 0); if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'ftp')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } // get ftp-user - $result = $this->apiCall('Ftps.get', array( + $result = $this->apiCall('Ftps.get', [ 'id' => $id, 'username' => $username - )); + ]); $id = $result['id']; if ($this->isAdmin()) { // get customer-data - $customer_data = $this->apiCall('Customers.get', array( + $customer_data = $this->apiCall('Customers.get', [ 'id' => $result['customerid'] - )); + ]); } else { $customer_data = $this->getUserData(); } @@ -587,33 +615,33 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit `down_bytes` = `down_bytes` + :down_bytes WHERE `username` = :username "); - $params = array( + $params = [ "up_count" => $result['up_count'], "up_bytes" => $result['up_bytes'], "down_count" => $result['down_count'], "down_bytes" => $result['down_bytes'], "username" => $customer_data['loginname'] - ); + ]; Database::pexecute($stmt, $params, true, true); } else { // do not allow removing default ftp-account - \Froxlor\UI\Response::standard_error('ftp_cantdeletemainaccount', '', true); + Response::standardError('ftp_cantdeletemainaccount', '', true); } // remove all quotatallies $stmt = Database::prepare("DELETE FROM `" . TABLE_FTP_QUOTATALLIES . "` WHERE `name` = :name"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "name" => $result['username'] - ), true, true); + ], true, true); // remove user itself $stmt = Database::prepare(" DELETE FROM `" . TABLE_FTP_USERS . "` WHERE `customerid` = :customerid AND `id` = :id "); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "customerid" => $customer_data['customerid'], "id" => $id - ), true, true); + ], true, true); // update ftp-groups $stmt = Database::prepare(" @@ -621,18 +649,18 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit `members` = REPLACE(`members`, :username,'') WHERE `customerid` = :customerid "); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "username" => "," . $result['username'], "customerid" => $customer_data['customerid'] - ), true, true); + ], true, true); // refs #293 if ($delete_userfiles == 1) { - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_FTP_DATA, $customer_data['loginname'], $result['homedir']); + Cronjob::inserttask(TaskId::DELETE_FTP_DATA, $customer_data['loginname'], $result['homedir']); } else { if (Settings::Get('system.nssextrausers') == 1) { // this is used so that the libnss-extrausers cron is fired - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_FTP); + Cronjob::inserttask(TaskId::CREATE_FTP); } } @@ -640,7 +668,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit $resetaccnumber = ($customer_data['ftps_used'] == '1') ? " , `ftp_lastaccountnumber`='0'" : ''; Customers::decreaseUsage($customer_data['customerid'], 'ftps_used', $resetaccnumber); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] deleted ftp-user '" . $result['username'] . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] deleted ftp-user '" . $result['username'] . "'"); return $this->response($result); } } diff --git a/lib/Froxlor/Api/Commands/HostingPlans.php b/lib/Froxlor/Api/Commands/HostingPlans.php index 75da64e9..0cd0c560 100644 --- a/lib/Froxlor/Api/Commands/HostingPlans.php +++ b/lib/Froxlor/Api/Commands/HostingPlans.php @@ -1,76 +1,96 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Database\Database; +use Froxlor\FroxlorLogger; +use Froxlor\Settings; +use Froxlor\Validate\Validate; +use PDO; + +/** + * @since 0.10.0 + */ +class HostingPlans extends ApiCommand implements ResourceEntity { /** * list all available hosting plans * * @param array $sql_search - * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue * @param int $sql_limit - * optional specify number of results to be returned + * optional specify number of results to be returned * @param int $sql_offset - * optional specify offset for resultset + * optional specify offset for resultset * @param array $sql_orderby - * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more + * fields * * @access admin - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listing() { if ($this->isAdmin()) { - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list hosting-plans"); - $query_fields = array(); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list hosting-plans"); + $query_fields = []; $result_stmt = Database::prepare(" SELECT p.*, a.loginname as adminname FROM `" . TABLE_PANEL_PLANS . "` p, `" . TABLE_PANEL_ADMINS . "` a WHERE `p`.`adminid` = `a`.`adminid`" . ($this->getUserDetail('customers_see_all') ? '' : " AND `p`.`adminid` = :adminid ") . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); - $params = array(); + $params = []; if ($this->getUserDetail('customers_see_all') == '0') { $params['adminid'] = $this->getUserDetail('adminid'); } $params = array_merge($params, $query_fields); Database::pexecute($result_stmt, $params, true, true); - $result = array(); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + $result = []; + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $result[] = $row; } - return $this->response(array( + return $this->response([ 'count' => count($result), 'list' => $result - )); + ]); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * returns the total number of accessible hosting plans * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function listingCount() { @@ -79,7 +99,7 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou SELECT COUNT(*) as num_plans FROM `" . TABLE_PANEL_PLANS . "` p, `" . TABLE_PANEL_ADMINS . "` a WHERE `p`.`adminid` = `a`.`adminid`" . ($this->getUserDetail('customers_see_all') ? '' : " AND `p`.`adminid` = :adminid ")); - $params = array(); + $params = []; if ($this->getUserDetail('customers_see_all') == '0') { $params['adminid'] = $this->getUserDetail('adminid'); } @@ -88,107 +108,71 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou return $this->response($result['num_plans']); } } - throw new \Exception("Not allowed to execute given command.", 403); - } - - /** - * return a hosting-plan entry by either id or plan-name - * - * @param int $id - * optional, the hosting-plan-id - * @param string $planname - * optional, the hosting-plan-name - * - * @access admin - * @throws \Exception - * @return string json-encoded array - */ - public function get() - { - if ($this->isAdmin()) { - $id = $this->getParam('id', true, 0); - $dn_optional = $id > 0; - $planname = $this->getParam('planname', $dn_optional, ''); - $result_stmt = Database::prepare(" - SELECT * FROM `" . TABLE_PANEL_PLANS . "` WHERE " . ($id > 0 ? "`id` = :iddn" : "`name` = :iddn") . ($this->getUserDetail('customers_see_all') ? '' : " AND `adminid` = :adminid")); - $params = array( - 'iddn' => ($id <= 0 ? $planname : $id) - ); - if ($this->getUserDetail('customers_see_all') == '0') { - $params['adminid'] = $this->getUserDetail('adminid'); - } - $result = Database::pexecute_first($result_stmt, $params, true, true); - if ($result) { - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get hosting-plan '" . $result['name'] . "'"); - return $this->response($result); - } - $key = ($id > 0 ? "id #" . $id : "planname '" . $planname . "'"); - throw new \Exception("Hosting-plan with " . $key . " could not be found", 404); - } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * add new hosting-plan * * @param string $name - * name of the plan + * name of the plan * @param string $description - * optional, description for hosting-plan + * optional, description for hosting-plan * @param int $diskspace - * optional disk-space available for customer in MB, default 0 + * optional disk-space available for customer in MB, default 0 * @param bool $diskspace_ul - * optional, whether customer should have unlimited diskspace, default 0 (false) + * optional, whether customer should have unlimited diskspace, default 0 (false) * @param int $traffic - * optional traffic available for customer in GB, default 0 + * optional traffic available for customer in GB, default 0 * @param bool $traffic_ul - * optional, whether customer should have unlimited traffic, default 0 (false) + * optional, whether customer should have unlimited traffic, default 0 (false) * @param int $subdomains - * optional amount of subdomains available for customer, default 0 + * optional amount of subdomains available for customer, default 0 * @param bool $subdomains_ul - * optional, whether customer should have unlimited subdomains, default 0 (false) + * optional, whether customer should have unlimited subdomains, default 0 (false) * @param int $emails - * optional amount of emails available for customer, default 0 + * optional amount of emails available for customer, default 0 * @param bool $emails_ul - * optional, whether customer should have unlimited emails, default 0 (false) + * optional, whether customer should have unlimited emails, default 0 (false) * @param int $email_accounts - * optional amount of email-accounts available for customer, default 0 + * optional amount of email-accounts available for customer, default 0 * @param bool $email_accounts_ul - * optional, whether customer should have unlimited email-accounts, default 0 (false) + * optional, whether customer should have unlimited email-accounts, default 0 (false) * @param int $email_forwarders - * optional amount of email-forwarders available for customer, default 0 + * optional amount of email-forwarders available for customer, default 0 * @param bool $email_forwarders_ul - * optional, whether customer should have unlimited email-forwarders, default 0 (false) + * optional, whether customer should have unlimited email-forwarders, default 0 (false) * @param int $email_quota - * optional size of email-quota available for customer in MB, default is system-setting mail_quota + * optional size of email-quota available for customer in MB, default is system-setting mail_quota * @param bool $email_quota_ul - * optional, whether customer should have unlimited email-quota, default 0 (false) + * optional, whether customer should have unlimited email-quota, default 0 (false) * @param bool $email_imap - * optional, whether to allow IMAP access, default 0 (false) + * optional, whether to allow IMAP access, default 0 (false) * @param bool $email_pop3 - * optional, whether to allow POP3 access, default 0 (false) + * optional, whether to allow POP3 access, default 0 (false) * @param int $ftps - * optional amount of ftp-accounts available for customer, default 0 + * optional amount of ftp-accounts available for customer, default 0 * @param bool $ftps_ul - * optional, whether customer should have unlimited ftp-accounts, default 0 (false) + * optional, whether customer should have unlimited ftp-accounts, default 0 (false) * @param int $mysqls - * optional amount of mysql-databases available for customer, default 0 + * optional amount of mysql-databases available for customer, default 0 * @param bool $mysqls_ul - * optional, whether customer should have unlimited mysql-databases, default 0 (false) + * optional, whether customer should have unlimited mysql-databases, default 0 (false) * @param bool $phpenabled - * optional, whether to allow usage of PHP, default 0 (false) + * optional, whether to allow usage of PHP, default 0 (false) * @param array $allowed_phpconfigs - * optional, array of IDs of php-config that the customer is allowed to use, default empty (none) + * optional, array of IDs of php-config that the customer is allowed to use, default empty (none) * @param bool $perlenabled - * optional, whether to allow usage of Perl/CGI, default 0 (false) + * optional, whether to allow usage of Perl/CGI, default 0 (false) * @param bool $dnsenabled - * optional, whether to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false) + * optional, whether to allow usage of the DNS editor (requires activated nameserver in settings), + * default 0 (false) * @param bool $logviewenabled - * optional, whether to allow access to webserver access/error-logs, default 0 (false) + * optional, whether to allow access to webserver access/error-logs, default 0 (false) * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function add() { @@ -196,7 +180,7 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou $name = $this->getParam('name'); $description = $this->getParam('description', true, ''); - $value_arr = array(); + $value_arr = []; $value_arr['diskspace'] = $this->getUlParam('diskspace', 'diskspace_ul', true, 0); $value_arr['traffic'] = $this->getUlParam('traffic', 'traffic_ul', true, 0); $value_arr['subdomains'] = $this->getUlParam('subdomains', 'subdomains_ul', true, 0); @@ -209,21 +193,21 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou $value_arr['ftps'] = $this->getUlParam('ftps', 'ftps_ul', true, 0); $value_arr['mysqls'] = $this->getUlParam('mysqls', 'mysqls_ul', true, 0); $value_arr['phpenabled'] = $this->getBoolParam('phpenabled', true, 0); - $p_allowed_phpconfigs = $this->getParam('allowed_phpconfigs', true, array()); + $p_allowed_phpconfigs = $this->getParam('allowed_phpconfigs', true, []); $value_arr['perlenabled'] = $this->getBoolParam('perlenabled', true, 0); $value_arr['dnsenabled'] = $this->getBoolParam('dnsenabled', true, 0); $value_arr['logviewenabled'] = $this->getBoolParam('logviewenabled', true, 0); // validation - $name = \Froxlor\Validate\Validate::validate(trim($name), 'name', '', '', array(), true); - $description = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $description), 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT); + $name = Validate::validate(trim($name), 'name', '', '', [], true); + $description = Validate::validate(str_replace("\r\n", "\n", $description), 'description', Validate::REGEX_DESC_TEXT); if (Settings::Get('system.mail_quota_enabled') != '1') { - $value_arr['email_quota'] = - 1; + $value_arr['email_quota'] = -1; } - $value_arr['allowed_phpconfigs'] = array(); - if (! empty($p_allowed_phpconfigs) && is_array($p_allowed_phpconfigs)) { + $value_arr['allowed_phpconfigs'] = []; + if (!empty($p_allowed_phpconfigs) && is_array($p_allowed_phpconfigs)) { foreach ($p_allowed_phpconfigs as $allowed_phpconfig) { $allowed_phpconfig = intval($allowed_phpconfig); $value_arr['allowed_phpconfigs'][] = $allowed_phpconfig; @@ -235,102 +219,139 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou INSERT INTO `" . TABLE_PANEL_PLANS . "` SET `adminid` = :adminid, `name` = :name, `description` = :desc, `value` = :valuearr, `ts` = UNIX_TIMESTAMP(); "); - $ins_data = array( + $ins_data = [ 'adminid' => $this->getUserDetail('adminid'), 'name' => $name, 'desc' => $description, 'valuearr' => json_encode($value_arr) - ); + ]; Database::pexecute($ins_stmt, $ins_data, true, true); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added hosting-plan '" . $name . "'"); - $result = $this->apiCall('HostingPlans.get', array( + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added hosting-plan '" . $name . "'"); + $result = $this->apiCall('HostingPlans.get', [ 'planname' => $name - )); + ]); return $this->response($result); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); + } + + /** + * return a hosting-plan entry by either id or plan-name + * + * @param int $id + * optional, the hosting-plan-id + * @param string $planname + * optional, the hosting-plan-name + * + * @access admin + * @return string json-encoded array + * @throws Exception + */ + public function get() + { + if ($this->isAdmin()) { + $id = $this->getParam('id', true, 0); + $dn_optional = $id > 0; + $planname = $this->getParam('planname', $dn_optional, ''); + $result_stmt = Database::prepare(" + SELECT * FROM `" . TABLE_PANEL_PLANS . "` WHERE " . ($id > 0 ? "`id` = :iddn" : "`name` = :iddn") . ($this->getUserDetail('customers_see_all') ? '' : " AND `adminid` = :adminid")); + $params = [ + 'iddn' => ($id <= 0 ? $planname : $id) + ]; + if ($this->getUserDetail('customers_see_all') == '0') { + $params['adminid'] = $this->getUserDetail('adminid'); + } + $result = Database::pexecute_first($result_stmt, $params, true, true); + if ($result) { + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get hosting-plan '" . $result['name'] . "'"); + return $this->response($result); + } + $key = ($id > 0 ? "id #" . $id : "planname '" . $planname . "'"); + throw new Exception("Hosting-plan with " . $key . " could not be found", 404); + } + throw new Exception("Not allowed to execute given command.", 403); } /** * update hosting-plan by either id or plan-name * * @param int $id - * optional the hosting-plan-id + * optional the hosting-plan-id * @param string $planname - * optional the hosting-plan-name + * optional the hosting-plan-name * @param string $name - * optional name of the plan + * optional name of the plan * @param string $description - * optional description for hosting-plan + * optional description for hosting-plan * @param int $diskspace - * optional disk-space available for customer in MB, default 0 + * optional disk-space available for customer in MB, default 0 * @param bool $diskspace_ul - * optional, whether customer should have unlimited diskspace, default 0 (false) + * optional, whether customer should have unlimited diskspace, default 0 (false) * @param int $traffic - * optional traffic available for customer in GB, default 0 + * optional traffic available for customer in GB, default 0 * @param bool $traffic_ul - * optional, whether customer should have unlimited traffic, default 0 (false) + * optional, whether customer should have unlimited traffic, default 0 (false) * @param int $subdomains - * optional amount of subdomains available for customer, default 0 + * optional amount of subdomains available for customer, default 0 * @param bool $subdomains_ul - * optional, whether customer should have unlimited subdomains, default 0 (false) + * optional, whether customer should have unlimited subdomains, default 0 (false) * @param int $emails - * optional amount of emails available for customer, default 0 + * optional amount of emails available for customer, default 0 * @param bool $emails_ul - * optional, whether customer should have unlimited emails, default 0 (false) + * optional, whether customer should have unlimited emails, default 0 (false) * @param int $email_accounts - * optional amount of email-accounts available for customer, default 0 + * optional amount of email-accounts available for customer, default 0 * @param bool $email_accounts_ul - * optional, whether customer should have unlimited email-accounts, default 0 (false) + * optional, whether customer should have unlimited email-accounts, default 0 (false) * @param int $email_forwarders - * optional amount of email-forwarders available for customer, default 0 + * optional amount of email-forwarders available for customer, default 0 * @param bool $email_forwarders_ul - * optional, whether customer should have unlimited email-forwarders, default 0 (false) + * optional, whether customer should have unlimited email-forwarders, default 0 (false) * @param int $email_quota - * optional size of email-quota available for customer in MB, default is system-setting mail_quota + * optional size of email-quota available for customer in MB, default is system-setting mail_quota * @param bool $email_quota_ul - * optional, whether customer should have unlimited email-quota, default 0 (false) + * optional, whether customer should have unlimited email-quota, default 0 (false) * @param bool $email_imap - * optional, whether to allow IMAP access, default 0 (false) + * optional, whether to allow IMAP access, default 0 (false) * @param bool $email_pop3 - * optional, whether to allow POP3 access, default 0 (false) + * optional, whether to allow POP3 access, default 0 (false) * @param int $ftps - * optional amount of ftp-accounts available for customer, default 0 + * optional amount of ftp-accounts available for customer, default 0 * @param bool $ftps_ul - * optional, whether customer should have unlimited ftp-accounts, default 0 (false) + * optional, whether customer should have unlimited ftp-accounts, default 0 (false) * @param int $mysqls - * optional amount of mysql-databases available for customer, default 0 + * optional amount of mysql-databases available for customer, default 0 * @param bool $mysqls_ul - * optional, whether customer should have unlimited mysql-databases, default 0 (false) + * optional, whether customer should have unlimited mysql-databases, default 0 (false) * @param bool $phpenabled - * optional, whether to allow usage of PHP, default 0 (false) + * optional, whether to allow usage of PHP, default 0 (false) * @param array $allowed_phpconfigs - * optional, array of IDs of php-config that the customer is allowed to use, default empty (none) + * optional, array of IDs of php-config that the customer is allowed to use, default empty (none) * @param bool $perlenabled - * optional, whether to allow usage of Perl/CGI, default 0 (false) + * optional, whether to allow usage of Perl/CGI, default 0 (false) * @param bool $dnsenabled - * optional, either to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false) + * optional, either to allow usage of the DNS editor (requires activated nameserver in settings), + * default 0 (false) * @param bool $logviewenabled - * optional, either to allow access to webserver access/error-logs, default 0 (false) + * optional, either to allow access to webserver access/error-logs, default 0 (false) * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function update() { if ($this->isAdmin()) { - // parameters $id = $this->getParam('id', true, 0); $dn_optional = $id > 0; $planname = $this->getParam('planname', $dn_optional, ''); // get requested hosting-plan - $result = $this->apiCall('HostingPlans.get', array( + $result = $this->apiCall('HostingPlans.get', [ 'id' => $id, 'planname' => $planname - )); + ]); $id = $result['id']; $result['value'] = json_decode($result['value'], true); @@ -341,7 +362,7 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou $name = $this->getParam('name', true, $result['name']); $description = $this->getParam('description', true, $result['description']); - $value_arr = array(); + $value_arr = []; $value_arr['diskspace'] = $this->getUlParam('diskspace', 'diskspace_ul', true, $result['diskspace']); $value_arr['traffic'] = $this->getUlParam('traffic', 'traffic_ul', true, $result['traffic']); $value_arr['subdomains'] = $this->getUlParam('subdomains', 'subdomains_ul', true, $result['subdomains']); @@ -360,19 +381,19 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou $value_arr['logviewenabled'] = $this->getBoolParam('logviewenabled', true, $result['logviewenabled']); // validation - $name = \Froxlor\Validate\Validate::validate(trim($name), 'name', '', '', array(), true); - $description = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $description), 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT); + $name = Validate::validate(trim($name), 'name', '', '', [], true); + $description = Validate::validate(str_replace("\r\n", "\n", $description), 'description', Validate::REGEX_DESC_TEXT); if (Settings::Get('system.mail_quota_enabled') != '1') { - $value_arr['email_quota'] = - 1; + $value_arr['email_quota'] = -1; } if (empty($name)) { $name = $result['name']; } - $value_arr['allowed_phpconfigs'] = array(); - if (! empty($p_allowed_phpconfigs) && is_array($p_allowed_phpconfigs)) { + $value_arr['allowed_phpconfigs'] = []; + if (!empty($p_allowed_phpconfigs) && is_array($p_allowed_phpconfigs)) { foreach ($p_allowed_phpconfigs as $allowed_phpconfig) { $allowed_phpconfig = intval($allowed_phpconfig); $value_arr['allowed_phpconfigs'][] = $allowed_phpconfig; @@ -385,30 +406,30 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou SET `name` = :name, `description` = :desc, `value` = :valuearr, `ts` = UNIX_TIMESTAMP() WHERE `id` = :id "); - $update_data = array( + $update_data = [ 'name' => $name, 'desc' => $description, 'valuearr' => json_encode($value_arr), 'id' => $id - ); + ]; Database::pexecute($upd_stmt, $update_data, true, true); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] updated hosting-plan '" . $result['name'] . "'"); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] updated hosting-plan '" . $result['name'] . "'"); return $this->response($update_data); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * delete hosting-plan by either id or plan-name * * @param int $id - * optional the hosting-plan-id + * optional the hosting-plan-id * @param string $planname - * optional the hosting-plan-name + * optional the hosting-plan-name * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function delete() { @@ -418,21 +439,21 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou $planname = $this->getParam('planname', $dn_optional, ''); // get requested hosting-plan - $result = $this->apiCall('HostingPlans.get', array( + $result = $this->apiCall('HostingPlans.get', [ 'id' => $id, 'planname' => $planname - )); + ]); $id = $result['id']; $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_PLANS . "` WHERE `id` = :id "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'id' => $id - ), true, true); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted hosting-plan '" . $result['name'] . "'"); + ], true, true); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted hosting-plan '" . $result['name'] . "'"); return $this->response($result); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } } diff --git a/lib/Froxlor/Api/Commands/IpsAndPorts.php b/lib/Froxlor/Api/Commands/IpsAndPorts.php index c49ebf85..212dec0e 100644 --- a/lib/Froxlor/Api/Commands/IpsAndPorts.php +++ b/lib/Froxlor/Api/Commands/IpsAndPorts.php @@ -1,81 +1,105 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Cron\TaskId; +use Froxlor\Database\Database; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; +use Froxlor\Settings; +use Froxlor\System\Cronjob; +use Froxlor\UI\Response; +use Froxlor\Validate\Validate; +use PDO; + +/** + * @since 0.10.0 + */ +class IpsAndPorts extends ApiCommand implements ResourceEntity { /** * lists all ip/port entries * * @param array $sql_search - * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue * @param int $sql_limit - * optional specify number of results to be returned + * optional specify number of results to be returned * @param int $sql_offset - * optional specify offset for resultset + * optional specify offset for resultset * @param array $sql_orderby - * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more + * fields * * @access admin - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listing() { - if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || ! empty($this->getUserDetail('ip')))) { - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list ips and ports"); + if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || !empty($this->getUserDetail('ip')))) { + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list ips and ports"); $ip_where = ""; $append_where = false; - if (! empty($this->getUserDetail('ip')) && $this->getUserDetail('ip') != - 1) { + if (!empty($this->getUserDetail('ip')) && $this->getUserDetail('ip') != -1) { $ip_where = "WHERE `id` IN (" . implode(", ", json_decode($this->getUserDetail('ip'), true)) . ")"; $append_where = true; } - $query_fields = array(); + $query_fields = []; $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` " . $ip_where . $this->getSearchWhere($query_fields, $append_where) . $this->getOrderBy() . $this->getLimit()); Database::pexecute($result_stmt, $query_fields, true, true); - $result = array(); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + $result = []; + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $result[] = $row; } - return $this->response(array( + return $this->response([ 'count' => count($result), 'list' => $result - )); + ]); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * returns the total number of accessible ip/port entries * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function listingCount() { - if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || ! empty($this->getUserDetail('ip')))) { + if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || !empty($this->getUserDetail('ip')))) { $ip_where = ""; - if (! empty($this->getUserDetail('ip')) && $this->getUserDetail('ip') != - 1) { + if (!empty($this->getUserDetail('ip')) && $this->getUserDetail('ip') != -1) { $ip_where = "WHERE `id` IN (" . implode(", ", json_decode($this->getUserDetail('ip'), true)) . ")"; } $result_stmt = Database::prepare(" @@ -85,42 +109,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour return $this->response($result['num_ips']); } } - throw new \Exception("Not allowed to execute given command.", 403); - } - - /** - * return an ip/port entry by id - * - * @param int $id - * ip-port-id - * - * @access admin - * @throws \Exception - * @return string json-encoded array - */ - public function get() - { - if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || ! empty($this->getUserDetail('ip')))) { - $id = $this->getParam('id'); - if (! empty($this->getUserDetail('ip')) && $this->getUserDetail('ip') != - 1) { - $allowed_ips = json_decode($this->getUserDetail('ip'), true); - if (! in_array($id, $allowed_ips)) { - throw new \Exception("You cannot access this resource", 405); - } - } - $result_stmt = Database::prepare(" - SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `id` = :id - "); - $result = Database::pexecute_first($result_stmt, array( - 'id' => $id - ), true, true); - if ($result) { - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get ip " . $result['ip'] . " " . $result['port']); - return $this->response($result); - } - throw new \Exception("IP/port with id #" . $id . " could not be found", 404); - } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** @@ -128,71 +117,70 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour * * @param string $ip * @param int $port - * optional, default 80 + * optional, default 80 * @param bool $listen_statement - * optional, default 0 (false) + * optional, default 0 (false) * @param bool $namevirtualhost_statement - * optional, default 0 (false) + * optional, default 0 (false) * @param bool $vhostcontainer - * optional, default 0 (false) + * optional, default 0 (false) * @param string $specialsettings - * optional, default empty + * optional, default empty * @param bool $vhostcontainer_servername_statement - * optional, default 0 (false) + * optional, default 0 (false) * @param string $default_vhostconf_domain - * optional, defatul empty + * optional, defatul empty * @param string $docroot - * optional, default empty (point to froxlor) + * optional, default empty (point to froxlor) * @param bool $ssl - * optional, default 0 (false) + * optional, default 0 (false) * @param string $ssl_cert_file - * optional, requires $ssl = 1, default empty + * optional, requires $ssl = 1, default empty * @param string $ssl_key_file - * optional, requires $ssl = 1, default empty + * optional, requires $ssl = 1, default empty * @param string $ssl_ca_file - * optional, requires $ssl = 1, default empty + * optional, requires $ssl = 1, default empty * @param string $ssl_cert_chainfile - * optional, requires $ssl = 1, default empty + * optional, requires $ssl = 1, default empty * @param string $ssl_specialsettings - * optional, requires $ssl = 1, default empty + * optional, requires $ssl = 1, default empty * @param bool $include_specialsettings - * optional, requires $ssl = 1, whether or not to include non-ssl specialsettings, default false + * optional, requires $ssl = 1, whether or not to include non-ssl specialsettings, default false * @param string $ssl_default_vhostconf_domain - * optional, requires $ssl = 1, defatul empty + * optional, requires $ssl = 1, defatul empty * @param bool $include_default_vhostconf_domain - * optional, requires $ssl = 1, whether or not to include non-ssl default_vhostconf_domain, default false - * + * optional, requires $ssl = 1, whether or not to include non-ssl default_vhostconf_domain, default false + * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function add() { if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) { - - $ip = \Froxlor\Validate\Validate::validate_ip2($this->getParam('ip'), false, 'invalidip', false, true, false, false, true); - $port = \Froxlor\Validate\Validate::validate($this->getParam('port', true, 80), 'port', \Froxlor\Validate\Validate::REGEX_PORT, array( + $ip = Validate::validate_ip2($this->getParam('ip'), false, 'invalidip', false, true, false, false, true); + $port = Validate::validate($this->getParam('port', true, 80), 'port', Validate::REGEX_PORT, [ 'stringisempty', 'myport' - ), array(), true); - $listen_statement = ! empty($this->getBoolParam('listen_statement', true, 0)) ? 1 : 0; - $namevirtualhost_statement = ! empty($this->getBoolParam('namevirtualhost_statement', true, 0)) ? 1 : 0; - $vhostcontainer = ! empty($this->getBoolParam('vhostcontainer', true, 0)) ? 1 : 0; - $specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, '')), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true); - $vhostcontainer_servername_statement = ! empty($this->getBoolParam('vhostcontainer_servername_statement', true, 1)) ? 1 : 0; - $default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, '')), 'default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true); - $docroot = \Froxlor\Validate\Validate::validate($this->getParam('docroot', true, ''), 'docroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true); + ], [], true); + $listen_statement = !empty($this->getBoolParam('listen_statement', true, 0)) ? 1 : 0; + $namevirtualhost_statement = !empty($this->getBoolParam('namevirtualhost_statement', true, 0)) ? 1 : 0; + $vhostcontainer = !empty($this->getBoolParam('vhostcontainer', true, 0)) ? 1 : 0; + $specialsettings = Validate::validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, '')), 'specialsettings', Validate::REGEX_CONF_TEXT, '', [], true); + $vhostcontainer_servername_statement = !empty($this->getBoolParam('vhostcontainer_servername_statement', true, 1)) ? 1 : 0; + $default_vhostconf_domain = Validate::validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, '')), 'default_vhostconf_domain', Validate::REGEX_CONF_TEXT, '', [], true); + $docroot = Validate::validate($this->getParam('docroot', true, ''), 'docroot', Validate::REGEX_DIR, '', [], true); - if ((int) Settings::Get('system.use_ssl') == 1) { - $ssl = ! empty($this->getBoolParam('ssl', true, 0)) ? intval($this->getBoolParam('ssl', true, 0)) : 0; - $ssl_cert_file = \Froxlor\Validate\Validate::validate($this->getParam('ssl_cert_file', $ssl, ''), 'ssl_cert_file', '', '', array(), true); - $ssl_key_file = \Froxlor\Validate\Validate::validate($this->getParam('ssl_key_file', $ssl, ''), 'ssl_key_file', '', '', array(), true); - $ssl_ca_file = \Froxlor\Validate\Validate::validate($this->getParam('ssl_ca_file', true, ''), 'ssl_ca_file', '', '', array(), true); - $ssl_cert_chainfile = \Froxlor\Validate\Validate::validate($this->getParam('ssl_cert_chainfile', true, ''), 'ssl_cert_chainfile', '', '', array(), true); - $ssl_specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_specialsettings', true, '')), 'ssl_specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true); - $include_specialsettings = ! empty($this->getBoolParam('include_specialsettings', true, 0)) ? 1 : 0; - $ssl_default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_default_vhostconf_domain', true, '')), 'ssl_default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true); - $include_default_vhostconf_domain = ! empty($this->getBoolParam('include_default_vhostconf_domain', true, 0)) ? 1 : 0; + if ((int)Settings::Get('system.use_ssl') == 1) { + $ssl = !empty($this->getBoolParam('ssl', true, 0)) ? intval($this->getBoolParam('ssl', true, 0)) : 0; + $ssl_cert_file = Validate::validate($this->getParam('ssl_cert_file', $ssl, ''), 'ssl_cert_file', '', '', [], true); + $ssl_key_file = Validate::validate($this->getParam('ssl_key_file', $ssl, ''), 'ssl_key_file', '', '', [], true); + $ssl_ca_file = Validate::validate($this->getParam('ssl_ca_file', true, ''), 'ssl_ca_file', '', '', [], true); + $ssl_cert_chainfile = Validate::validate($this->getParam('ssl_cert_chainfile', true, ''), 'ssl_cert_chainfile', '', '', [], true); + $ssl_specialsettings = Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_specialsettings', true, '')), 'ssl_specialsettings', Validate::REGEX_CONF_TEXT, '', [], true); + $include_specialsettings = !empty($this->getBoolParam('include_specialsettings', true, 0)) ? 1 : 0; + $ssl_default_vhostconf_domain = Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_default_vhostconf_domain', true, '')), 'ssl_default_vhostconf_domain', Validate::REGEX_CONF_TEXT, '', [], true); + $include_default_vhostconf_domain = !empty($this->getBoolParam('include_default_vhostconf_domain', true, 0)) ? 1 : 0; } else { $ssl = 0; $ssl_cert_file = ''; @@ -226,23 +214,23 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour } if ($ssl_cert_file != '') { - $ssl_cert_file = \Froxlor\FileDir::makeCorrectFile($ssl_cert_file); + $ssl_cert_file = FileDir::makeCorrectFile($ssl_cert_file); } if ($ssl_key_file != '') { - $ssl_key_file = \Froxlor\FileDir::makeCorrectFile($ssl_key_file); + $ssl_key_file = FileDir::makeCorrectFile($ssl_key_file); } if ($ssl_ca_file != '') { - $ssl_ca_file = \Froxlor\FileDir::makeCorrectFile($ssl_ca_file); + $ssl_ca_file = FileDir::makeCorrectFile($ssl_ca_file); } if ($ssl_cert_chainfile != '') { - $ssl_cert_chainfile = \Froxlor\FileDir::makeCorrectFile($ssl_cert_chainfile); + $ssl_cert_chainfile = FileDir::makeCorrectFile($ssl_cert_chainfile); } if (strlen(trim($docroot)) > 0) { - $docroot = \Froxlor\FileDir::makeCorrectDir($docroot); + $docroot = FileDir::makeCorrectDir($docroot); } else { $docroot = ''; } @@ -253,13 +241,13 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $result_checkfordouble_stmt = Database::prepare(" SELECT `id` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `ip` = :ip AND `port` = :port"); - $result_checkfordouble = Database::pexecute_first($result_checkfordouble_stmt, array( + $result_checkfordouble = Database::pexecute_first($result_checkfordouble_stmt, [ 'ip' => $ip, 'port' => $port - )); + ]); if ($result_checkfordouble && $result_checkfordouble['id'] != '') { - \Froxlor\UI\Response::standard_error('myipnotdouble', '', true); + Response::standardError('myipnotdouble', '', true); } $ins_stmt = Database::prepare(" @@ -275,7 +263,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour `ssl_specialsettings` = :ssl_ss, `include_specialsettings` = :incss, `ssl_default_vhostconf_domain` = :ssl_dvhd, `include_default_vhostconf_domain` = :incdvhd; "); - $ins_data = array( + $ins_data = [ 'ip' => $ip, 'port' => $port, 'ls' => $listen_statement, @@ -294,25 +282,60 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour 'incss' => $include_specialsettings, 'ssl_dvhd' => $ssl_default_vhostconf_domain, 'incdvhd' => $include_default_vhostconf_domain - ); + ]; Database::pexecute($ins_stmt, $ins_data); $ins_data['id'] = Database::lastInsertId(); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + Cronjob::inserttask(TaskId::REBUILD_VHOST); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); + Cronjob::inserttask(TaskId::REBUILD_DNS); if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { $ip = '[' . $ip . ']'; } - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added IP/port '" . $ip . ":" . $port . "'"); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added IP/port '" . $ip . ":" . $port . "'"); // get ip for return-array - $result = $this->apiCall('IpsAndPorts.get', array( + $result = $this->apiCall('IpsAndPorts.get', [ 'id' => $ins_data['id'] - )); + ]); return $this->response($result); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); + } + + /** + * return an ip/port entry by id + * + * @param int $id + * ip-port-id + * + * @access admin + * @return string json-encoded array + * @throws Exception + */ + public function get() + { + if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || !empty($this->getUserDetail('ip')))) { + $id = $this->getParam('id'); + if (!empty($this->getUserDetail('ip')) && $this->getUserDetail('ip') != -1) { + $allowed_ips = json_decode($this->getUserDetail('ip'), true); + if (!in_array($id, $allowed_ips)) { + throw new Exception("You cannot access this resource", 405); + } + } + $result_stmt = Database::prepare(" + SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `id` = :id + "); + $result = Database::pexecute_first($result_stmt, [ + 'id' => $id + ], true, true); + if ($result) { + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get ip " . $result['ip'] . " " . $result['port']); + return $this->response($result); + } + throw new Exception("IP/port with id #" . $id . " could not be found", 404); + } + throw new Exception("Not allowed to execute given command.", 403); } /** @@ -320,78 +343,78 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour * * @param int $id * @param string $ip - * optional + * optional * @param int $port - * optional, default 80 + * optional, default 80 * @param bool $listen_statement - * optional, default 0 (false) + * optional, default 0 (false) * @param bool $namevirtualhost_statement - * optional, default 0 (false) + * optional, default 0 (false) * @param bool $vhostcontainer - * optional, default 0 (false) + * optional, default 0 (false) * @param string $specialsettings - * optional, default empty + * optional, default empty * @param bool $vhostcontainer_servername_statement - * optional, default 0 (false) + * optional, default 0 (false) * @param string $default_vhostconf_domain - * optional, defatul empty + * optional, defatul empty * @param string $docroot - * optional, default empty (point to froxlor) + * optional, default empty (point to froxlor) * @param bool $ssl - * optional, default 0 (false) + * optional, default 0 (false) * @param string $ssl_cert_file - * optional, requires $ssl = 1, default empty + * optional, requires $ssl = 1, default empty * @param string $ssl_key_file - * optional, requires $ssl = 1, default empty + * optional, requires $ssl = 1, default empty * @param string $ssl_ca_file - * optional, requires $ssl = 1, default empty + * optional, requires $ssl = 1, default empty * @param string $ssl_cert_chainfile - * optional, requires $ssl = 1, default empty + * optional, requires $ssl = 1, default empty * @param string $ssl_specialsettings - * optional, requires $ssl = 1, default empty + * optional, requires $ssl = 1, default empty * @param bool $include_specialsettings - * optional, requires $ssl = 1, whether or not to include non-ssl specialsettings, default false + * optional, requires $ssl = 1, whether or not to include non-ssl specialsettings, default false * @param string $ssl_default_vhostconf_domain - * optional, requires $ssl = 1, defatul empty + * optional, requires $ssl = 1, defatul empty * @param bool $include_default_vhostconf_domain - * optional, requires $ssl = 1, whether or not to include non-ssl default_vhostconf_domain, default false - * - * + * optional, requires $ssl = 1, whether or not to include non-ssl default_vhostconf_domain, default false + * + * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function update() { - if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || ! empty($this->getUserDetail('ip')))) { + if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || !empty($this->getUserDetail('ip')))) { $id = $this->getParam('id'); - $result = $this->apiCall('IpsAndPorts.get', array( + $result = $this->apiCall('IpsAndPorts.get', [ 'id' => $id - )); + ]); - $ip = \Froxlor\Validate\Validate::validate_ip2($this->getParam('ip', true, $result['ip']), false, 'invalidip', false, true, false, false, true); - $port = \Froxlor\Validate\Validate::validate($this->getParam('port', true, $result['port']), 'port', \Froxlor\Validate\Validate::REGEX_PORT, array( + $ip = Validate::validate_ip2($this->getParam('ip', true, $result['ip']), false, 'invalidip', false, true, false, false, true); + $port = Validate::validate($this->getParam('port', true, $result['port']), 'port', Validate::REGEX_PORT, [ 'stringisempty', 'myport' - ), array(), true); + ], [], true); $listen_statement = $this->getBoolParam('listen_statement', true, $result['listen_statement']); $namevirtualhost_statement = $this->getBoolParam('namevirtualhost_statement', true, $result['namevirtualhost_statement']); $vhostcontainer = $this->getBoolParam('vhostcontainer', true, $result['vhostcontainer']); - $specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, $result['specialsettings'])), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true); + $specialsettings = Validate::validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, $result['specialsettings'])), 'specialsettings', Validate::REGEX_CONF_TEXT, '', [], true); $vhostcontainer_servername_statement = $this->getParam('vhostcontainer_servername_statement', true, $result['vhostcontainer_servername_statement']); - $default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, $result['default_vhostconf_domain'])), 'default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true); - $docroot = \Froxlor\Validate\Validate::validate($this->getParam('docroot', true, $result['docroot']), 'docroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true); + $default_vhostconf_domain = Validate::validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, $result['default_vhostconf_domain'])), 'default_vhostconf_domain', Validate::REGEX_CONF_TEXT, '', [], true); + $docroot = Validate::validate($this->getParam('docroot', true, $result['docroot']), 'docroot', Validate::REGEX_DIR, '', [], true); - if ((int) Settings::Get('system.use_ssl') == 1) { + if ((int)Settings::Get('system.use_ssl') == 1) { $ssl = $this->getBoolParam('ssl', true, $result['ssl']); - $ssl_cert_file = \Froxlor\Validate\Validate::validate($this->getParam('ssl_cert_file', $ssl, $result['ssl_cert_file']), 'ssl_cert_file', '', '', array(), true); - $ssl_key_file = \Froxlor\Validate\Validate::validate($this->getParam('ssl_key_file', $ssl, $result['ssl_key_file']), 'ssl_key_file', '', '', array(), true); - $ssl_ca_file = \Froxlor\Validate\Validate::validate($this->getParam('ssl_ca_file', true, $result['ssl_ca_file']), 'ssl_ca_file', '', '', array(), true); - $ssl_cert_chainfile = \Froxlor\Validate\Validate::validate($this->getParam('ssl_cert_chainfile', true, $result['ssl_cert_chainfile']), 'ssl_cert_chainfile', '', '', array(), true); - $ssl_specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_specialsettings', true, $result['ssl_specialsettings'])), 'ssl_specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true); + $ssl_cert_file = Validate::validate($this->getParam('ssl_cert_file', $ssl, $result['ssl_cert_file']), 'ssl_cert_file', '', '', [], true); + $ssl_key_file = Validate::validate($this->getParam('ssl_key_file', $ssl, $result['ssl_key_file']), 'ssl_key_file', '', '', [], true); + $ssl_ca_file = Validate::validate($this->getParam('ssl_ca_file', true, $result['ssl_ca_file']), 'ssl_ca_file', '', '', [], true); + $ssl_cert_chainfile = Validate::validate($this->getParam('ssl_cert_chainfile', true, $result['ssl_cert_chainfile']), 'ssl_cert_chainfile', '', '', [], true); + $ssl_specialsettings = Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_specialsettings', true, $result['ssl_specialsettings'])), 'ssl_specialsettings', Validate::REGEX_CONF_TEXT, '', [], true); $include_specialsettings = $this->getBoolParam('include_specialsettings', true, $result['include_specialsettings']); - $ssl_default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_default_vhostconf_domain', true, $result['ssl_default_vhostconf_domain'])), 'ssl_default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true); + $ssl_default_vhostconf_domain = Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_default_vhostconf_domain', true, $result['ssl_default_vhostconf_domain'])), 'ssl_default_vhostconf_domain', Validate::REGEX_CONF_TEXT, '', [], true); $include_default_vhostconf_domain = $this->getBoolParam('include_default_vhostconf_domain', true, $result['include_default_vhostconf_domain']); } else { $ssl = 0; @@ -409,19 +432,19 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour SELECT `id` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `ip` = :ip AND `port` = :port "); - $result_checkfordouble = Database::pexecute_first($result_checkfordouble_stmt, array( + $result_checkfordouble = Database::pexecute_first($result_checkfordouble_stmt, [ 'ip' => $ip, 'port' => $port - )); + ]); $result_sameipotherport_stmt = Database::prepare(" SELECT `id` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `ip` = :ip AND `id` <> :id "); - $result_sameipotherport = Database::pexecute_first($result_sameipotherport_stmt, array( + $result_sameipotherport = Database::pexecute_first($result_sameipotherport_stmt, [ 'ip' => $ip, 'id' => $id - ), true, true); + ], true, true); if ($listen_statement != '1') { $listen_statement = '0'; @@ -444,23 +467,23 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour } if ($ssl_cert_file != '') { - $ssl_cert_file = \Froxlor\FileDir::makeCorrectFile($ssl_cert_file); + $ssl_cert_file = FileDir::makeCorrectFile($ssl_cert_file); } if ($ssl_key_file != '') { - $ssl_key_file = \Froxlor\FileDir::makeCorrectFile($ssl_key_file); + $ssl_key_file = FileDir::makeCorrectFile($ssl_key_file); } if ($ssl_ca_file != '') { - $ssl_ca_file = \Froxlor\FileDir::makeCorrectFile($ssl_ca_file); + $ssl_ca_file = FileDir::makeCorrectFile($ssl_ca_file); } if ($ssl_cert_chainfile != '') { - $ssl_cert_chainfile = \Froxlor\FileDir::makeCorrectFile($ssl_cert_chainfile); + $ssl_cert_chainfile = FileDir::makeCorrectFile($ssl_cert_chainfile); } if (strlen(trim($docroot)) > 0) { - $docroot = \Froxlor\FileDir::makeCorrectDir($docroot); + $docroot = FileDir::makeCorrectDir($docroot); } else { $docroot = ''; } @@ -469,11 +492,10 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $ip = inet_ntop(inet_pton($ip)); if ($result['ip'] != $ip && $result['ip'] == Settings::Get('system.ipaddress') && $result_sameipotherport == false) { - \Froxlor\UI\Response::standard_error('cantchangesystemip', '', true); + Response::standardError('cantchangesystemip', '', true); } elseif ($result_checkfordouble && $result_checkfordouble['id'] != '' && $result_checkfordouble['id'] != $id) { - \Froxlor\UI\Response::standard_error('myipnotdouble', '', true); + Response::standardError('myipnotdouble', '', true); } else { - $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_IPSANDPORTS . "` SET @@ -488,7 +510,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour `ssl_default_vhostconf_domain` = :ssl_dvhd, `include_default_vhostconf_domain` = :incdvhd WHERE `id` = :id; "); - $upd_data = array( + $upd_data = [ 'ip' => $ip, 'port' => $port, 'ls' => $listen_statement, @@ -508,98 +530,96 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour 'ssl_dvhd' => $ssl_default_vhostconf_domain, 'incdvhd' => $include_default_vhostconf_domain, 'id' => $id - ); + ]; Database::pexecute($upd_stmt, $upd_data); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + Cronjob::inserttask(TaskId::REBUILD_VHOST); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); + Cronjob::inserttask(TaskId::REBUILD_DNS); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] changed IP/port from '" . $result['ip'] . ":" . $result['port'] . "' to '" . $ip . ":" . $port . "'"); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] changed IP/port from '" . $result['ip'] . ":" . $result['port'] . "' to '" . $ip . ":" . $port . "'"); - $result = $this->apiCall('IpsAndPorts.get', array( + $result = $this->apiCall('IpsAndPorts.get', [ 'id' => $result['id'] - )); + ]); return $this->response($result); } } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * delete an ip/port entry by id * * @param int $id - * ip-port-id - * + * ip-port-id + * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function delete() { if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) { $id = $this->getParam('id'); - $result = $this->apiCall('IpsAndPorts.get', array( + $result = $this->apiCall('IpsAndPorts.get', [ 'id' => $id - )); + ]); $result_checkdomain_stmt = Database::prepare(" SELECT `id_domain` FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_ipandports` = :id "); - $result_checkdomain = Database::pexecute_first($result_checkdomain_stmt, array( + $result_checkdomain = Database::pexecute_first($result_checkdomain_stmt, [ 'id' => $id - ), true, true); + ], true, true); if (empty($result_checkdomain)) { - if (! in_array($result['id'], explode(',', Settings::Get('system.defaultip'))) && ! in_array($result['id'], explode(',', Settings::Get('system.defaultsslip')))) { - + if (!in_array($result['id'], explode(',', Settings::Get('system.defaultip'))) && !in_array($result['id'], explode(',', Settings::Get('system.defaultsslip')))) { // check whether there is the same IP with a different port // in case this ip-address is the system.ipaddress and therefore // when there is one - we have an alternative $result_sameipotherport_stmt = Database::prepare(" SELECT `id` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `ip` = :ip AND `id` <> :id"); - $result_sameipotherport = Database::pexecute_first($result_sameipotherport_stmt, array( + $result_sameipotherport = Database::pexecute_first($result_sameipotherport_stmt, [ 'id' => $id, 'ip' => $result['ip'] - )); + ]); if (($result['ip'] != Settings::Get('system.ipaddress')) || ($result['ip'] == Settings::Get('system.ipaddress') && $result_sameipotherport != false)) { - $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `id` = :id "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'id' => $id - ), true, true); + ], true, true); // also, remove connections to domains (multi-stack) $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_ipandports` = :id "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'id' => $id - ), true, true); + ], true, true); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + Cronjob::inserttask(TaskId::REBUILD_VHOST); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); + Cronjob::inserttask(TaskId::REBUILD_DNS); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted IP/port '" . $result['ip'] . ":" . $result['port'] . "'"); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted IP/port '" . $result['ip'] . ":" . $result['port'] . "'"); return $this->response($result); } else { - \Froxlor\UI\Response::standard_error('cantdeletesystemip', '', true); + Response::standardError('cantdeletesystemip', '', true); } } else { - \Froxlor\UI\Response::standard_error('cantdeletedefaultip', '', true); + Response::standardError('cantdeletedefaultip', '', true); } } else { - \Froxlor\UI\Response::standard_error('ipstillhasdomains', '', true); + Response::standardError('ipstillhasdomains', '', true); } } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } } diff --git a/lib/Froxlor/Api/Commands/Mysqls.php b/lib/Froxlor/Api/Commands/Mysqls.php index 0772829a..1465ef95 100644 --- a/lib/Froxlor/Api/Commands/Mysqls.php +++ b/lib/Froxlor/Api/Commands/Mysqls.php @@ -1,49 +1,70 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Database\Database; +use Froxlor\Database\DbManager; +use Froxlor\FroxlorLogger; +use Froxlor\Settings; +use Froxlor\System\Crypt; +use Froxlor\UI\Response; +use Froxlor\User; +use Froxlor\Validate\Validate; +use PDO; + +/** + * @since 0.10.0 + */ +class Mysqls extends ApiCommand implements ResourceEntity { /** * add a new mysql-database * * @param string $mysql_password - * password for the created database and database-user + * password for the created database and database-user * @param int $mysql_server - * optional, default is 0 + * optional, default is 0 * @param string $description - * optional, description for database + * optional, description for database * @param string $custom_suffix - * optional, name for database + * optional, name for database * @param bool $sendinfomail - * optional, send created resource-information to customer, default: false + * optional, send created resource-information to customer, default: false * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function add() { @@ -60,33 +81,33 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $customer = $this->getCustomerData('mysqls'); // validation - $password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true); - $password = \Froxlor\System\Crypt::validatePassword($password, true); - $databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true); + $password = Validate::validate($password, 'password', '', '', [], true); + $password = Crypt::validatePassword($password, true); + $databasedescription = Validate::validate(trim($databasedescription), 'description', Validate::REGEX_DESC_TEXT, '', [], true); if (!empty($databasename)) { - $databasename = \Froxlor\Validate\Validate::validate(trim($databasename), 'database_name', '/^[A-Za-z0-9][A-Za-z0-9\-_]+$/i', '', array(), true); + $databasename = Validate::validate(trim($databasename), 'database_name', '/^[A-Za-z0-9][A-Za-z0-9\-_]+$/i', '', [], true); } // validate whether the dbserver exists - $dbserver = \Froxlor\Validate\Validate::validate($dbserver, html_entity_decode(lng('mysql.mysql_server')), '', '', 0, true); + $dbserver = Validate::validate($dbserver, html_entity_decode(lng('mysql.mysql_server')), '', '', 0, true); Database::needRoot(true, $dbserver); Database::needSqlData(); $sql_root = Database::getSqlData(); Database::needRoot(false); if (!isset($sql_root) || !is_array($sql_root)) { - throw new \Exception("Database server with index #" . $dbserver . " is unknown", 404); + throw new Exception("Database server with index #" . $dbserver . " is unknown", 404); } if ($sendinfomail != 1) { $sendinfomail = 0; } - $newdb_params = array( + $newdb_params = [ 'loginname' => ($this->isAdmin() ? $customer['loginname'] : $this->getUserDetail('loginname')), 'mysql_lastaccountnumber' => ($this->isAdmin() ? $customer['mysql_lastaccountnumber'] : $this->getUserDetail('mysql_lastaccountnumber')) - ); + ]; // create database, user, set permissions, etc.pp. - $dbm = new \Froxlor\Database\DbManager($this->logger()); + $dbm = new DbManager($this->logger()); if (strtoupper(Settings::Get('customer.mysqlprefix')) == 'DBNAME' && !empty($databasename)) { $username = $dbm->createDatabase($newdb_params['loginname'] . '_' . $databasename, $password); @@ -96,7 +117,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt // we've checked against the password in dbm->createDatabase if ($username == false) { - \Froxlor\UI\Response::standard_error('passwordshouldnotbeusername', '', true); + Response::standardError('passwordshouldnotbeusername', '', true); } // add database info to froxlor @@ -108,12 +129,12 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt `description` = :description, `dbserver` = :dbserver "); - $params = array( + $params = [ "customerid" => $customer['customerid'], "databasename" => $username, "description" => $databasedescription, "dbserver" => $dbserver - ); + ]; Database::pexecute($stmt, $params, true, true); $databaseid = Database::lastInsertId(); $params['id'] = $databaseid; @@ -135,9 +156,9 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt Database::needRoot(false); $userinfo = $customer; - $replace_arr = array( - 'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($userinfo), - 'CUST_NAME' => \Froxlor\User::getCorrectUserSalutation($userinfo), // < keep this for compatibility + $replace_arr = [ + 'SALUTATION' => User::getCorrectUserSalutation($userinfo), + 'CUST_NAME' => User::getCorrectUserSalutation($userinfo), // < keep this for compatibility 'NAME' => $userinfo['name'], 'FIRSTNAME' => $userinfo['firstname'], 'COMPANY' => $userinfo['company'], @@ -147,7 +168,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt 'DB_DESC' => $databasedescription, 'DB_SRV' => $sql_root['host'], 'PMA_URI' => $pma - ); + ]; // get template for mail subject $mail_subject = $this->getMailTemplate($userinfo, 'mails', 'new_database_by_customer_subject', $replace_arr, lng('mails.new_database_by_customer.subject')); @@ -160,46 +181,46 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $this->mailer()->Subject = $mail_subject; $this->mailer()->AltBody = $mail_body; $this->mailer()->msgHTML(str_replace("\n", "
", $mail_body)); - $this->mailer()->addAddress($userinfo['email'], \Froxlor\User::getCorrectUserSalutation($userinfo)); + $this->mailer()->addAddress($userinfo['email'], User::getCorrectUserSalutation($userinfo)); $this->mailer()->send(); } 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) { - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg); - \Froxlor\UI\Response::standard_error('errorsendingmail', $userinfo['email'], true); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg); + Response::standardError('errorsendingmail', $userinfo['email'], true); } $this->mailer()->clearAddresses(); } - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] added mysql-database '" . $username . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] added mysql-database '" . $username . "'"); - $result = $this->apiCall('Mysqls.get', array( + $result = $this->apiCall('Mysqls.get', [ 'dbname' => $username - )); + ]); return $this->response($result); } - throw new \Exception("No more resources available", 406); + throw new Exception("No more resources available", 406); } /** * return a mysql database entry by either id or dbname * * @param int $id - * optional, the database-id + * optional, the database-id * @param string $dbname - * optional, the databasename + * optional, the databasename * @param int $mysql_server - * optional, specify database-server, default is none + * optional, specify database-server, default is none * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function get() { @@ -214,7 +235,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt // whether the database belongs to one of his customers $_custom_list_result = $this->apiCall('Customers.listing'); $custom_list_result = $_custom_list_result['list']; - $customer_ids = array(); + $customer_ids = []; foreach ($custom_list_result as $customer) { $customer_ids[] = $customer['customerid']; } @@ -223,37 +244,37 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt SELECT * FROM `" . TABLE_PANEL_DATABASES . "` WHERE " . ($id > 0 ? "`id` = :iddn" : "`databasename` = :iddn") . ($dbserver >= 0 ? " AND `dbserver` = :dbserver" : "") . " AND `customerid` IN (" . implode(", ", $customer_ids) . ") "); - $params = array( + $params = [ 'iddn' => ($id <= 0 ? $dbname : $id) - ); + ]; if ($dbserver >= 0) { $params['dbserver'] = $dbserver; } } else { - throw new \Exception("You do not have any customers yet", 406); + throw new Exception("You do not have any customers yet", 406); } } else { $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_DATABASES . "` WHERE " . ($id > 0 ? "`id` = :iddn" : "`databasename` = :iddn") . ($dbserver >= 0 ? " AND `dbserver` = :dbserver" : "")); - $params = array( + $params = [ 'iddn' => ($id <= 0 ? $dbname : $id) - ); + ]; if ($dbserver >= 0) { $params['dbserver'] = $dbserver; } } } else { if (Settings::IsInList('panel.customer_hide_options', 'mysql')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_DATABASES . "` WHERE `customerid`= :customerid AND " . ($id > 0 ? "`id` = :iddn" : "`databasename` = :iddn") . ($dbserver >= 0 ? " AND `dbserver` = :dbserver" : "")); - $params = array( + $params = [ 'customerid' => $this->getUserDetail('customerid'), 'iddn' => ($id <= 0 ? $dbname : $id) - ); + ]; if ($dbserver >= 0) { $params['dbserver'] = $dbserver; } @@ -266,40 +287,40 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt WHERE table_schema = :table_schema GROUP BY table_schema "); - Database::pexecute($mbdata_stmt, array( + Database::pexecute($mbdata_stmt, [ "table_schema" => $result['databasename'] - ), true, true); - $mbdata = $mbdata_stmt->fetch(\PDO::FETCH_ASSOC); + ], true, true); + $mbdata = $mbdata_stmt->fetch(PDO::FETCH_ASSOC); Database::needRoot(false); $result['size'] = $mbdata['MB'] ?? 0; - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get database '" . $result['databasename'] . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get database '" . $result['databasename'] . "'"); return $this->response($result); } $key = ($id > 0 ? "id #" . $id : "dbname '" . $dbname . "'"); - throw new \Exception("MySQL database with " . $key . " could not be found", 404); + throw new Exception("MySQL database with " . $key . " could not be found", 404); } /** * update a mysql database entry by either id or dbname * * @param int $id - * optional, the database-id + * optional, the database-id * @param string $dbname - * optional, the databasename + * optional, the databasename * @param int $mysql_server - * optional, specify database-server, default is none + * optional, specify database-server, default is none * @param string $mysql_password - * optional, update password for the database + * optional, update password for the database * @param string $description - * optional, description for database + * optional, description for database * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function update() { @@ -310,14 +331,14 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $customer = $this->getCustomerData(); if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'mysql')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } - $result = $this->apiCall('Mysqls.get', array( + $result = $this->apiCall('Mysqls.get', [ 'id' => $id, 'dbname' => $dbname, 'mysql_server' => $dbserver - )); + ]); $id = $result['id']; // parameters @@ -325,20 +346,20 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $databasedescription = $this->getParam('description', true, $result['description']); // validation - $password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true); - $databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true); + $password = Validate::validate($password, 'password', '', '', [], true); + $databasedescription = Validate::validate(trim($databasedescription), 'description', Validate::REGEX_DESC_TEXT, '', [], true); if ($password != '') { // validate password - $password = \Froxlor\System\Crypt::validatePassword($password, true); + $password = Crypt::validatePassword($password, true); if ($password == $result['databasename']) { - \Froxlor\UI\Response::standard_error('passwordshouldnotbeusername', '', true); + Response::standardError('passwordshouldnotbeusername', '', true); } // Begin root-session Database::needRoot(true, $result['dbserver']); - $dbmgr = new \Froxlor\Database\DbManager($this->logger()); + $dbmgr = new DbManager($this->logger()); foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) { $dbmgr->getManager()->grantPrivilegesTo($result['databasename'], $password, $mysql_access_host, false, true); } @@ -354,105 +375,108 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt WHERE `customerid` = :customerid AND `id` = :id "); - $params = array( + $params = [ "desc" => $databasedescription, "customerid" => $customer['customerid'], "id" => $id - ); + ]; Database::pexecute($stmt, $params, true, true); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] updated mysql-database '" . $result['databasename'] . "'"); - $result = $this->apiCall('Mysqls.get', array( + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] updated mysql-database '" . $result['databasename'] . "'"); + $result = $this->apiCall('Mysqls.get', [ 'dbname' => $result['databasename'] - )); + ]); return $this->response($result); } /** - * list all databases, if called from an admin, list all databases of all customers you are allowed to view, or specify id or loginname for one specific customer + * list all databases, if called from an admin, list all databases of all customers you are allowed to view, or + * specify id or loginname for one specific customer * * @param int $mysql_server - * optional, specify dbserver to select from, else use all available + * optional, specify dbserver to select from, else use all available * @param int $customerid - * optional, admin-only, select dbs of a specific customer by id + * optional, admin-only, select dbs of a specific customer by id * @param string $loginname - * optional, admin-only, select dbs of a specific customer by loginname + * optional, admin-only, select dbs of a specific customer by loginname * @param array $sql_search - * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue * @param int $sql_limit - * optional specify number of results to be returned + * optional specify number of results to be returned * @param int $sql_offset - * optional specify offset for resultset + * optional specify offset for resultset * @param array $sql_orderby - * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more + * fields * * @access admin, customer - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listing() { - $result = array(); + $result = []; $dbserver = $this->getParam('mysql_server', true, -1); $customer_ids = $this->getAllowedCustomerIds('mysql'); - $query_fields = array(); + $query_fields = []; $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_DATABASES . "` WHERE `customerid`= :customerid AND `dbserver` = :dbserver" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); if ($dbserver < 0) { // use all dbservers $dbservers_stmt = Database::query("SELECT DISTINCT `dbserver` FROM `" . TABLE_PANEL_DATABASES . "`"); - $dbservers = $dbservers_stmt->fetchAll(\PDO::FETCH_ASSOC); + $dbservers = $dbservers_stmt->fetchAll(PDO::FETCH_ASSOC); } else { // use specific dbserver - $dbservers = array( - array( + $dbservers = [ + [ 'dbserver' => $dbserver - ) - ); + ] + ]; } foreach ($customer_ids as $customer_id) { foreach ($dbservers as $_dbserver) { - Database::pexecute($result_stmt, array_merge(array( + Database::pexecute($result_stmt, array_merge([ 'customerid' => $customer_id, 'dbserver' => $_dbserver['dbserver'] - ), $query_fields), true, true); + ], $query_fields), true, true); // Begin root-session Database::needRoot(true, $_dbserver['dbserver']); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $mbdata_stmt = Database::prepare(" SELECT SUM(data_length + index_length) as MB FROM information_schema.TABLES WHERE table_schema = :table_schema GROUP BY table_schema "); - Database::pexecute($mbdata_stmt, array( + Database::pexecute($mbdata_stmt, [ "table_schema" => $row['databasename'] - ), true, true); - $mbdata = $mbdata_stmt->fetch(\PDO::FETCH_ASSOC); + ], true, true); + $mbdata = $mbdata_stmt->fetch(PDO::FETCH_ASSOC); $row['size'] = $mbdata['MB'] ?? 0; $result[] = $row; } Database::needRoot(false); } } - return $this->response(array( + return $this->response([ 'count' => count($result), 'list' => $result - )); + ]); } /** * returns the total number of accessible databases * * @param int $customerid - * optional, admin-only, select dbs of a specific customer by id + * optional, admin-only, select dbs of a specific customer by id * @param string $loginname - * optional, admin-only, select dbs of a specific customer by loginname + * optional, admin-only, select dbs of a specific customer by loginname * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function listingCount() { @@ -471,19 +495,19 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt * delete a mysql database by either id or dbname * * @param int $id - * optional, the database-id + * optional, the database-id * @param string $dbname - * optional, the databasename + * optional, the databasename * @param int $mysql_server - * optional, specify database-server, default is none + * optional, specify database-server, default is none * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function delete() { @@ -494,28 +518,28 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $customer = $this->getCustomerData(); if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'mysql')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } - $result = $this->apiCall('Mysqls.get', array( + $result = $this->apiCall('Mysqls.get', [ 'id' => $id, 'dbname' => $dbname, 'mysql_server' => $dbserver - )); + ]); $id = $result['id']; // Begin root-session Database::needRoot(true, $result['dbserver']); - $dbm = new \Froxlor\Database\DbManager($this->logger()); + $dbm = new DbManager($this->logger()); $dbm->getManager()->deleteDatabase($result['databasename']); Database::needRoot(false); // End root-session // delete from table $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DATABASES . "` WHERE `id` = :id"); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "id" => $id - ), true, true); + ], true, true); // get needed customer info to reduce the mysql-usage-counter by one $mysql_used = $customer['mysqls_used']; @@ -524,7 +548,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $resetaccnumber = ($mysql_used == '1') ? " , `mysql_lastaccountnumber` = '0' " : ''; Customers::decreaseUsage($customer['customerid'], 'mysqls_used', $resetaccnumber); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] deleted database '" . $result['databasename'] . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] deleted database '" . $result['databasename'] . "'"); return $this->response($result); } } diff --git a/lib/Froxlor/Api/Commands/PhpSettings.php b/lib/Froxlor/Api/Commands/PhpSettings.php index 4a5df145..6d244daf 100644 --- a/lib/Froxlor/Api/Commands/PhpSettings.php +++ b/lib/Froxlor/Api/Commands/PhpSettings.php @@ -1,81 +1,105 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Cron\TaskId; +use Froxlor\Database\Database; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; +use Froxlor\Settings; +use Froxlor\System\Cronjob; +use Froxlor\UI\Response; +use Froxlor\Validate\Validate; +use PDO; + +/** + * @since 0.10.0 + */ +class PhpSettings extends ApiCommand implements ResourceEntity { /** * lists all php-setting entries * * @param bool $with_subdomains - * optional, also include subdomains to the list domains that use the config, default 0 (false) + * optional, also include subdomains to the list domains that use the config, default 0 (false) * @param array $sql_search - * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue * @param int $sql_limit - * optional specify number of results to be returned + * optional specify number of results to be returned * @param int $sql_offset - * optional specify offset for resultset + * optional specify offset for resultset * @param array $sql_orderby - * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more + * fields * * @access admin - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listing() { if ($this->isAdmin()) { - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list php-configs"); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list php-configs"); $with_subdomains = $this->getBoolParam('with_subdomains', true, false); - $query_fields = array(); + $query_fields = []; $result_stmt = Database::prepare(" SELECT c.*, fd.description as fpmdesc FROM `" . TABLE_PANEL_PHPCONFIGS . "` c LEFT JOIN `" . TABLE_PANEL_FPMDAEMONS . "` fd ON fd.id = c.fpmsettingid" . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit()); Database::pexecute($result_stmt, $query_fields, true, true); - $phpconfigs = array(); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { - $query_params = array( + $phpconfigs = []; + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + $query_params = [ 'id' => $row['id'] - ); + ]; $query = "SELECT * FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `phpsettingid` = :id AND `email_only` = '0' AND `phpenabled` = '1'"; - if (! $with_subdomains) { + if (!$with_subdomains) { $query .= " AND `parentdomainid` = '0'"; } - if ((int) $this->getUserDetail('domains_see_all') == 0) { + if ((int)$this->getUserDetail('domains_see_all') == 0) { $query .= " AND `adminid` = :adminid"; $query_params['adminid'] = $this->getUserDetail('adminid'); } - if ((int) Settings::Get('panel.phpconfigs_hidestdsubdomain') == 1) { + if ((int)Settings::Get('panel.phpconfigs_hidestdsubdomain') == 1) { $ssdids_res = Database::query(" SELECT DISTINCT `standardsubdomain` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `standardsubdomain` > 0 ORDER BY `standardsubdomain` ASC;"); - $ssdids = array(); - while ($ssd = $ssdids_res->fetch(\PDO::FETCH_ASSOC)) { + $ssdids = []; + while ($ssd = $ssdids_res->fetch(PDO::FETCH_ASSOC)) { $ssdids[] = $ssd['standardsubdomain']; } if (count($ssdids) > 0) { @@ -83,13 +107,13 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour } } - $domains = array(); - $subdomains = array(); + $domains = []; + $subdomains = []; $domainresult_stmt = Database::prepare($query); Database::pexecute($domainresult_stmt, $query_params, true, true); if (Database::num_rows() > 0) { - while ($row2 = $domainresult_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row2 = $domainresult_stmt->fetch(PDO::FETCH_ASSOC)) { if ($row2['parentdomainid'] != 0) { $subdomains[] = $row2['domain']; } else { @@ -113,20 +137,49 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $phpconfigs[] = $row; } - return $this->response(array( + return $this->response([ 'count' => count($phpconfigs), 'list' => $phpconfigs - )); + ]); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); + } + + /** + * return a php-setting entry by id + * + * @param int $id + * php-settings-id + * + * @access admin + * @return string json-encoded array + * @throws Exception + */ + public function get() + { + if ($this->isAdmin()) { + $id = $this->getParam('id'); + + $result_stmt = Database::prepare(" + SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `id` = :id + "); + $result = Database::pexecute_first($result_stmt, [ + 'id' => $id + ], true, true); + if ($result) { + return $this->response($result); + } + throw new Exception("php-config with id #" . $id . " could not be found", 404); + } + throw new Exception("Not allowed to execute given command.", 403); } /** * returns the total number of accessible php-setting entries * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function listingCount() { @@ -140,94 +193,67 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour return $this->response($result['num_phps']); } } - throw new \Exception("Not allowed to execute given command.", 403); - } - - /** - * return a php-setting entry by id - * - * @param int $id - * php-settings-id - * - * @access admin - * @throws \Exception - * @return string json-encoded array - */ - public function get() - { - if ($this->isAdmin()) { - $id = $this->getParam('id'); - - $result_stmt = Database::prepare(" - SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `id` = :id - "); - $result = Database::pexecute_first($result_stmt, array( - 'id' => $id - ), true, true); - if ($result) { - return $this->response($result); - } - throw new \Exception("php-config with id #" . $id . " could not be found", 404); - } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * add new php-settings entry * * @param string $description - * description of the php-config + * description of the php-config * @param string $phpsettings - * the actual ini-settings + * the actual ini-settings * @param string $binary - * optional the binary to php-cgi if FCGID is used + * optional the binary to php-cgi if FCGID is used * @param string $file_extensions - * optional allowed php-file-extensions if FCGID is used, default is 'php' + * optional allowed php-file-extensions if FCGID is used, default is 'php' * @param int $mod_fcgid_starter - * optional number of fcgid-starters if FCGID is used, default is -1 + * optional number of fcgid-starters if FCGID is used, default is -1 * @param int $mod_fcgid_maxrequests - * optional number of fcgid-maxrequests if FCGID is used, default is -1 + * optional number of fcgid-maxrequests if FCGID is used, default is -1 * @param string $mod_fcgid_umask - * optional umask if FCGID is used, default is '022' + * optional umask if FCGID is used, default is '022' * @param int $fpmconfig - * optional id of the fpm-daemon-config if FPM is used + * optional id of the fpm-daemon-config if FPM is used * @param bool $phpfpm_enable_slowlog - * optional whether to write a slowlog or not if FPM is used, default is 0 (false) + * optional whether to write a slowlog or not if FPM is used, default is 0 (false) * @param string $phpfpm_reqtermtimeout - * optional request terminate timeout if FPM is used, default is '60s' + * optional request terminate timeout if FPM is used, default is '60s' * @param string $phpfpm_reqslowtimeout - * optional request slowlog timeout if FPM is used, default is '5s' + * optional request slowlog timeout if FPM is used, default is '5s' * @param bool $phpfpm_pass_authorizationheader - * optional whether to pass authorization header to webserver if FPM is used, default is 0 (false) + * optional whether to pass authorization header to webserver if FPM is used, default is 0 (false) * @param bool $override_fpmconfig - * optional whether to override fpm-daemon-config value for the following settings if FPM is used, default is 0 (false) + * optional whether to override fpm-daemon-config value for the following settings if FPM is used, + * default is 0 (false) * @param string $pm - * optional process-manager to use if FPM is used (allowed values are 'static', 'dynamic' and 'ondemand'), default is fpm-daemon-value + * optional process-manager to use if FPM is used (allowed values are 'static', 'dynamic' and + * 'ondemand'), default is fpm-daemon-value * @param int $max_children - * optional number of max children if FPM is used, default is the fpm-daemon-value + * optional number of max children if FPM is used, default is the fpm-daemon-value * @param int $start_server - * optional number of servers to start if FPM is used, default is fpm-daemon-value + * optional number of servers to start if FPM is used, default is fpm-daemon-value * @param int $min_spare_servers - * optional number of minimum spare servers if FPM is used, default is fpm-daemon-value + * optional number of minimum spare servers if FPM is used, default is fpm-daemon-value * @param int $max_spare_servers - * optional number of maximum spare servers if FPM is used, default is fpm-daemon-value + * optional number of maximum spare servers if FPM is used, default is fpm-daemon-value * @param int $max_requests - * optional number of maximum requests if FPM is used, default is fpm-daemon-value + * optional number of maximum requests if FPM is used, default is fpm-daemon-value * @param int $idle_timeout - * optional number of seconds for idle-timeout if FPM is used, default is fpm-daemon-value + * optional number of seconds for idle-timeout if FPM is used, default is fpm-daemon-value * @param string $limit_extensions - * optional limitation of php-file-extensions if FPM is used, default is fpm-daemon-value + * optional limitation of php-file-extensions if FPM is used, default is fpm-daemon-value * @param bool $allow_all_customers - * optional add this configuration to the list of every existing customer's allowed-fpm-config list, default is false (no) + * optional add this configuration to the list of every existing customer's allowed-fpm-config list, + * default is false (no) * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function add() { if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) { - // required parameter $description = $this->getParam('description'); $phpsettings = $this->getParam('phpsettings'); @@ -243,8 +269,8 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour // parameters $file_extensions = $this->getParam('file_extensions', true, 'php'); - $mod_fcgid_starter = $this->getParam('mod_fcgid_starter', true, - 1); - $mod_fcgid_maxrequests = $this->getParam('mod_fcgid_maxrequests', true, - 1); + $mod_fcgid_starter = $this->getParam('mod_fcgid_starter', true, -1); + $mod_fcgid_maxrequests = $this->getParam('mod_fcgid_maxrequests', true, -1); $mod_fcgid_umask = $this->getParam('mod_fcgid_umask', true, "022"); $fpm_enableslowlog = $this->getBoolParam('phpfpm_enable_slowlog', true, 0); $fpm_reqtermtimeout = $this->getParam('phpfpm_reqtermtimeout', true, "60s"); @@ -252,9 +278,9 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $fpm_pass_authorizationheader = $this->getBoolParam('phpfpm_pass_authorizationheader', true, 0); $override_fpmconfig = $this->getBoolParam('override_fpmconfig', true, 0); - $def_fpmconfig = $this->apiCall('FpmDaemons.get', array( + $def_fpmconfig = $this->apiCall('FpmDaemons.get', [ 'id' => $fpm_config_id - )); + ]); $pmanager = $this->getParam('pm', true, $def_fpmconfig['pm']); $max_children = $this->getParam('max_children', true, $def_fpmconfig['max_children']); $start_servers = $this->getParam('start_servers', true, $def_fpmconfig['start_servers']); @@ -266,20 +292,20 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $allow_all_customers = $this->getBoolParam('allow_all_customers', true, 0); // validation - $description = \Froxlor\Validate\Validate::validate($description, 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true); - $phpsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $phpsettings), 'phpsettings', '/^[^\0]*$/', '', array(), true); + $description = Validate::validate($description, 'description', Validate::REGEX_DESC_TEXT, '', [], true); + $phpsettings = Validate::validate(str_replace("\r\n", "\n", $phpsettings), 'phpsettings', '/^[^\0]*$/', '', [], true); if (Settings::Get('system.mod_fcgid') == 1) { - $binary = \Froxlor\FileDir::makeCorrectFile(\Froxlor\Validate\Validate::validate($binary, 'binary', '', '', array(), true)); - $file_extensions = \Froxlor\Validate\Validate::validate($file_extensions, 'file_extensions', '/^[a-zA-Z0-9\s]*$/', '', array(), true); - $mod_fcgid_starter = \Froxlor\Validate\Validate::validate($mod_fcgid_starter, 'mod_fcgid_starter', '/^[0-9]*$/', '', array( + $binary = FileDir::makeCorrectFile(Validate::validate($binary, 'binary', '', '', [], true)); + $file_extensions = Validate::validate($file_extensions, 'file_extensions', '/^[a-zA-Z0-9\s]*$/', '', [], true); + $mod_fcgid_starter = Validate::validate($mod_fcgid_starter, 'mod_fcgid_starter', '/^[0-9]*$/', '', [ '-1', '' - ), true); - $mod_fcgid_maxrequests = \Froxlor\Validate\Validate::validate($mod_fcgid_maxrequests, 'mod_fcgid_maxrequests', '/^[0-9]*$/', '', array( + ], true); + $mod_fcgid_maxrequests = Validate::validate($mod_fcgid_maxrequests, 'mod_fcgid_maxrequests', '/^[0-9]*$/', '', [ '-1', '' - ), true); - $mod_fcgid_umask = \Froxlor\Validate\Validate::validate($mod_fcgid_umask, 'mod_fcgid_umask', '/^[0-9]*$/', '', array(), true); + ], true); + $mod_fcgid_umask = Validate::validate($mod_fcgid_umask, 'mod_fcgid_umask', '/^[0-9]*$/', '', [], true); // disable fpm stuff $fpm_config_id = 1; $fpm_enableslowlog = 0; @@ -288,19 +314,19 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $fpm_pass_authorizationheader = 0; $override_fpmconfig = 0; } elseif (Settings::Get('phpfpm.enabled') == 1) { - $fpm_reqtermtimeout = \Froxlor\Validate\Validate::validate($fpm_reqtermtimeout, 'phpfpm_reqtermtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', array(), true); - $fpm_reqslowtimeout = \Froxlor\Validate\Validate::validate($fpm_reqslowtimeout, 'phpfpm_reqslowtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', array(), true); - if (! in_array($pmanager, array( + $fpm_reqtermtimeout = Validate::validate($fpm_reqtermtimeout, 'phpfpm_reqtermtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', [], true); + $fpm_reqslowtimeout = Validate::validate($fpm_reqslowtimeout, 'phpfpm_reqslowtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', [], true); + if (!in_array($pmanager, [ 'static', 'dynamic', 'ondemand' - ))) { - throw new \Exception("Unknown process manager", 406); + ])) { + throw new Exception("Unknown process manager", 406); } if (empty($limit_extensions)) { $limit_extensions = '.php'; } - $limit_extensions = \Froxlor\Validate\Validate::validate($limit_extensions, 'limit_extensions', '/^(\.[a-z]([a-z0-9]+)\ ?)+$/', '', array(), true); + $limit_extensions = Validate::validate($limit_extensions, 'limit_extensions', '/^(\.[a-z]([a-z0-9]+)\ ?)+$/', '', [], true); // disable fcgid stuff $binary = '/usr/bin/php-cgi'; @@ -311,7 +337,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour } if (strlen($description) == 0 || strlen($description) > 50) { - \Froxlor\UI\Response::standard_error('descriptioninvalid', '', true); + Response::standardError('descriptioninvalid', '', true); } $ins_stmt = Database::prepare(" @@ -338,7 +364,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour `idle_timeout` = :idle_timeout, `limit_extensions` = :limit_extensions "); - $ins_data = array( + $ins_data = [ 'desc' => $description, 'binary' => $binary, 'fext' => $file_extensions, @@ -360,21 +386,55 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour 'max_requests' => $max_requests, 'idle_timeout' => $idle_timeout, 'limit_extensions' => $limit_extensions - ); + ]; Database::pexecute($ins_stmt, $ins_data, true, true); $ins_data['id'] = Database::lastInsertId(); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] php setting with description '" . $description . "' has been created by '" . $this->getUserDetail('loginname') . "'"); + Cronjob::inserttask(TaskId::REBUILD_VHOST); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] php setting with description '" . $description . "' has been created by '" . $this->getUserDetail('loginname') . "'"); - $result = $this->apiCall('PhpSettings.get', array( + $result = $this->apiCall('PhpSettings.get', [ 'id' => $ins_data['id'] - )); + ]); $this->addForAllCustomers($allow_all_customers, $ins_data['id']); return $this->response($result); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); + } + + /** + * add given php-config id to the list of allowed php-config to all currently existing customers + * if allow_all_customers parameter is true in PhpSettings::add() or PhpSettings::update() + * + * @param bool $allow_all_customers + * @param int $config_id + */ + private function addForAllCustomers(bool $allow_all_customers, int $config_id) + { + // should this config be added to the allowed list of all existing customers? + if ($allow_all_customers) { + $sel_stmt = Database::prepare("SELECT customerid, allowed_phpconfigs FROM `" . TABLE_PANEL_CUSTOMERS . "`"); + $upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET allowed_phpconfigs = :ap WHERE customerid = :cid"); + Database::pexecute($sel_stmt); + while ($cust = $sel_stmt->fetch(PDO::FETCH_ASSOC)) { + // get existing entries of customer + $ap = json_decode($cust['allowed_phpconfigs'], true); + // initialize array if it's empty + if (empty($ap)) { + $ap = []; + } + // add this config + $ap[] = $config_id; + // check for duplicates and force value-type to be int + $ap = array_map('intval', array_unique($ap)); + // update customer-entry + Database::pexecute($upd_stmt, [ + 'ap' => json_encode($ap), + 'cid' => $cust['customerid'] + ]); + } + } } /** @@ -382,64 +442,66 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour * * @param int $id * @param string $description - * description of the php-config + * description of the php-config * @param string $phpsettings - * the actual ini-settings + * the actual ini-settings * @param string $binary - * optional the binary to php-cgi if FCGID is used + * optional the binary to php-cgi if FCGID is used * @param string $file_extensions - * optional allowed php-file-extensions if FCGID is used, default is 'php' + * optional allowed php-file-extensions if FCGID is used, default is 'php' * @param int $mod_fcgid_starter - * optional number of fcgid-starters if FCGID is used, default is -1 + * optional number of fcgid-starters if FCGID is used, default is -1 * @param int $mod_fcgid_maxrequests - * optional number of fcgid-maxrequests if FCGID is used, default is -1 + * optional number of fcgid-maxrequests if FCGID is used, default is -1 * @param string $mod_fcgid_umask - * optional umask if FCGID is used, default is '022' + * optional umask if FCGID is used, default is '022' * @param int $fpmconfig - * optional id of the fpm-daemon-config if FPM is used + * optional id of the fpm-daemon-config if FPM is used * @param bool $phpfpm_enable_slowlog - * optional whether to write a slowlog or not if FPM is used, default is 0 (false) + * optional whether to write a slowlog or not if FPM is used, default is 0 (false) * @param string $phpfpm_reqtermtimeout - * optional request terminate timeout if FPM is used, default is '60s' + * optional request terminate timeout if FPM is used, default is '60s' * @param string $phpfpm_reqslowtimeout - * optional request slowlog timeout if FPM is used, default is '5s' + * optional request slowlog timeout if FPM is used, default is '5s' * @param bool $phpfpm_pass_authorizationheader - * optional whether to pass authorization header to webserver if FPM is used, default is 0 (false) + * optional whether to pass authorization header to webserver if FPM is used, default is 0 (false) * @param bool $override_fpmconfig - * optional whether to override fpm-daemon-config value for the following settings if FPM is used, default is 0 (false) + * optional whether to override fpm-daemon-config value for the following settings if FPM is used, + * default is 0 (false) * @param string $pm - * optional process-manager to use if FPM is used (allowed values are 'static', 'dynamic' and 'ondemand'), default is fpm-daemon-value + * optional process-manager to use if FPM is used (allowed values are 'static', 'dynamic' and + * 'ondemand'), default is fpm-daemon-value * @param int $max_children - * optional number of max children if FPM is used, default is the fpm-daemon-value + * optional number of max children if FPM is used, default is the fpm-daemon-value * @param int $start_server - * optional number of servers to start if FPM is used, default is fpm-daemon-value + * optional number of servers to start if FPM is used, default is fpm-daemon-value * @param int $min_spare_servers - * optional number of minimum spare servers if FPM is used, default is fpm-daemon-value + * optional number of minimum spare servers if FPM is used, default is fpm-daemon-value * @param int $max_spare_servers - * optional number of maximum spare servers if FPM is used, default is fpm-daemon-value + * optional number of maximum spare servers if FPM is used, default is fpm-daemon-value * @param int $max_requests - * optional number of maximum requests if FPM is used, default is fpm-daemon-value + * optional number of maximum requests if FPM is used, default is fpm-daemon-value * @param int $idle_timeout - * optional number of seconds for idle-timeout if FPM is used, default is fpm-daemon-value + * optional number of seconds for idle-timeout if FPM is used, default is fpm-daemon-value * @param string $limit_extensions - * optional limitation of php-file-extensions if FPM is used, default is fpm-daemon-value + * optional limitation of php-file-extensions if FPM is used, default is fpm-daemon-value * @param bool $allow_all_customers - * optional add this configuration to the list of every existing customer's allowed-fpm-config list, default is false (no) - * + * optional add this configuration to the list of every existing customer's allowed-fpm-config list, + * default is false (no) + * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function update() { if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) { - // required parameter $id = $this->getParam('id'); - $result = $this->apiCall('PhpSettings.get', array( + $result = $this->apiCall('PhpSettings.get', [ 'id' => $id - )); + ]); // parameters $description = $this->getParam('description', true, $result['description']); @@ -466,20 +528,20 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $allow_all_customers = $this->getBoolParam('allow_all_customers', true, 0); // validation - $description = \Froxlor\Validate\Validate::validate($description, 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true); - $phpsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $phpsettings), 'phpsettings', '/^[^\0]*$/', '', array(), true); + $description = Validate::validate($description, 'description', Validate::REGEX_DESC_TEXT, '', [], true); + $phpsettings = Validate::validate(str_replace("\r\n", "\n", $phpsettings), 'phpsettings', '/^[^\0]*$/', '', [], true); if (Settings::Get('system.mod_fcgid') == 1) { - $binary = \Froxlor\FileDir::makeCorrectFile(\Froxlor\Validate\Validate::validate($binary, 'binary', '', '', array(), true)); - $file_extensions = \Froxlor\Validate\Validate::validate($file_extensions, 'file_extensions', '/^[a-zA-Z0-9\s]*$/', '', array(), true); - $mod_fcgid_starter = \Froxlor\Validate\Validate::validate($mod_fcgid_starter, 'mod_fcgid_starter', '/^[0-9]*$/', '', array( + $binary = FileDir::makeCorrectFile(Validate::validate($binary, 'binary', '', '', [], true)); + $file_extensions = Validate::validate($file_extensions, 'file_extensions', '/^[a-zA-Z0-9\s]*$/', '', [], true); + $mod_fcgid_starter = Validate::validate($mod_fcgid_starter, 'mod_fcgid_starter', '/^[0-9]*$/', '', [ '-1', '' - ), true); - $mod_fcgid_maxrequests = \Froxlor\Validate\Validate::validate($mod_fcgid_maxrequests, 'mod_fcgid_maxrequests', '/^[0-9]*$/', '', array( + ], true); + $mod_fcgid_maxrequests = Validate::validate($mod_fcgid_maxrequests, 'mod_fcgid_maxrequests', '/^[0-9]*$/', '', [ '-1', '' - ), true); - $mod_fcgid_umask = \Froxlor\Validate\Validate::validate($mod_fcgid_umask, 'mod_fcgid_umask', '/^[0-9]*$/', '', array(), true); + ], true); + $mod_fcgid_umask = Validate::validate($mod_fcgid_umask, 'mod_fcgid_umask', '/^[0-9]*$/', '', [], true); // disable fpm stuff $fpm_config_id = 1; $fpm_enableslowlog = 0; @@ -488,19 +550,19 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $fpm_pass_authorizationheader = 0; $override_fpmconfig = 0; } elseif (Settings::Get('phpfpm.enabled') == 1) { - $fpm_reqtermtimeout = \Froxlor\Validate\Validate::validate($fpm_reqtermtimeout, 'phpfpm_reqtermtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', array(), true); - $fpm_reqslowtimeout = \Froxlor\Validate\Validate::validate($fpm_reqslowtimeout, 'phpfpm_reqslowtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', array(), true); - if (! in_array($pmanager, array( + $fpm_reqtermtimeout = Validate::validate($fpm_reqtermtimeout, 'phpfpm_reqtermtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', [], true); + $fpm_reqslowtimeout = Validate::validate($fpm_reqslowtimeout, 'phpfpm_reqslowtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', [], true); + if (!in_array($pmanager, [ 'static', 'dynamic', 'ondemand' - ))) { - throw new \Exception("Unknown process manager", 406); + ])) { + throw new Exception("Unknown process manager", 406); } if (empty($limit_extensions)) { $limit_extensions = '.php'; } - $limit_extensions = \Froxlor\Validate\Validate::validate($limit_extensions, 'limit_extensions', '/^(\.[a-z]([a-z0-9]+)\ ?)+$/', '', array(), true); + $limit_extensions = Validate::validate($limit_extensions, 'limit_extensions', '/^(\.[a-z]([a-z0-9]+)\ ?)+$/', '', [], true); // disable fcgid stuff $binary = '/usr/bin/php-cgi'; @@ -511,7 +573,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour } if (strlen($description) == 0 || strlen($description) > 50) { - \Froxlor\UI\Response::standard_error('descriptioninvalid', '', true); + Response::standardError('descriptioninvalid', '', true); } $upd_stmt = Database::prepare(" @@ -539,7 +601,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour `limit_extensions` = :limit_extensions WHERE `id` = :id "); - $upd_data = array( + $upd_data = [ 'desc' => $description, 'binary' => $binary, 'fext' => $file_extensions, @@ -562,47 +624,47 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour 'idle_timeout' => $idle_timeout, 'limit_extensions' => $limit_extensions, 'id' => $id - ); + ]; Database::pexecute($upd_stmt, $upd_data, true, true); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] php setting with description '" . $description . "' has been updated by '" . $this->getUserDetail('loginname') . "'"); + Cronjob::inserttask(TaskId::REBUILD_VHOST); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] php setting with description '" . $description . "' has been updated by '" . $this->getUserDetail('loginname') . "'"); - $result = $this->apiCall('PhpSettings.get', array( + $result = $this->apiCall('PhpSettings.get', [ 'id' => $id - )); + ]); $this->addForAllCustomers($allow_all_customers, $id); return $this->response($result); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } /** * delete a php-setting entry by id * * @param int $id - * php-settings-id - * + * php-settings-id + * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function delete() { if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) { $id = $this->getParam('id'); - $result = $this->apiCall('PhpSettings.get', array( + $result = $this->apiCall('PhpSettings.get', [ 'id' => $id - )); + ]); if ((Settings::Get('system.mod_fcgid') == '1' && Settings::Get('system.mod_fcgid_defaultini_ownvhost') == $id) || (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.vhost_defaultini') == $id)) { - \Froxlor\UI\Response::standard_error('cannotdeletehostnamephpconfig', '', true); + Response::standardError('cannotdeletehostnamephpconfig', '', true); } if ((Settings::Get('system.mod_fcgid') == '1' && Settings::Get('system.mod_fcgid_defaultini') == $id) || (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.defaultini') == $id)) { - \Froxlor\UI\Response::standard_error('cannotdeletedefaultphpconfig', '', true); + Response::standardError('cannotdeletedefaultphpconfig', '', true); } // set php-config to default for all domains using the @@ -611,55 +673,21 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `phpsettingid` = '1' WHERE `phpsettingid` = :id "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'id' => $id - ), true, true); + ], true, true); $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `id` = :id "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'id' => $id - ), true, true); + ], true, true); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); - $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] php setting '" . $result['description'] . "' has been deleted by '" . $this->getUserDetail('loginname') . "'"); + Cronjob::inserttask(TaskId::REBUILD_VHOST); + $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] php setting '" . $result['description'] . "' has been deleted by '" . $this->getUserDetail('loginname') . "'"); return $this->response($result); } - throw new \Exception("Not allowed to execute given command.", 403); - } - - /** - * add given php-config id to the list of allowed php-config to all currently existing customers - * if allow_all_customers parameter is true in PhpSettings::add() or PhpSettings::update() - * - * @param bool $allow_all_customers - * @param int $config_id - */ - private function addForAllCustomers(bool $allow_all_customers, int $config_id) - { - // should this config be added to the allowed list of all existing customers? - if ($allow_all_customers) { - $sel_stmt = Database::prepare("SELECT customerid, allowed_phpconfigs FROM `" . TABLE_PANEL_CUSTOMERS . "`"); - $upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET allowed_phpconfigs = :ap WHERE customerid = :cid"); - Database::pexecute($sel_stmt); - while ($cust = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) { - // get existing entries of customer - $ap = json_decode($cust['allowed_phpconfigs'], true); - // initialize array if it's empty - if (empty($ap)) { - $ap = []; - } - // add this config - $ap[] = $config_id; - // check for duplicates and force value-type to be int - $ap = array_map('intval', array_unique($ap)); - // update customer-entry - Database::pexecute($upd_stmt, [ - 'ap' => json_encode($ap), - 'cid' => $cust['customerid'] - ]); - } - } + throw new Exception("Not allowed to execute given command.", 403); } } diff --git a/lib/Froxlor/Api/Commands/SubDomains.php b/lib/Froxlor/Api/Commands/SubDomains.php index afd68573..0831f22b 100644 --- a/lib/Froxlor/Api/Commands/SubDomains.php +++ b/lib/Froxlor/Api/Commands/SubDomains.php @@ -1,69 +1,97 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Cron\TaskId; +use Froxlor\Database\Database; +use Froxlor\Domain\Domain; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; +use Froxlor\Idna\IdnaWrapper; +use Froxlor\PhpHelper; +use Froxlor\Settings; +use Froxlor\System\Cronjob; +use Froxlor\UI\Response; +use Froxlor\Validate\Validate; +use PDO; + +/** + * @since 0.10.0 + */ +class SubDomains extends ApiCommand implements ResourceEntity { /** * add a new subdomain * * @param string $subdomain - * part before domain.tld to create as subdomain + * part before domain.tld to create as subdomain * @param string $domain - * domainname of main-domain + * domainname of main-domain * @param int $alias - * optional, domain-id of a domain that the new domain should be an alias of + * optional, domain-id of a domain that the new domain should be an alias of * @param string $path - * optional, destination path relative to the customers-homedir, default is customers-homedir + * optional, destination path relative to the customers-homedir, default is customers-homedir * @param string $url - * optional, overwrites path value with an URL to generate a redirect, alternatively use the path parameter also for URLs + * optional, overwrites path value with an URL to generate a redirect, alternatively use the path + * parameter also for URLs * @param int $openbasedir_path - * optional, either 0 for domains-docroot or 1 for customers-homedir + * optional, either 0 for domains-docroot or 1 for customers-homedir * @param int $phpsettingid - * optional, php-settings-id, if empty the $domain value is used + * optional, php-settings-id, if empty the $domain value is used * @param int $redirectcode - * optional, redirect-code-id from TABLE_PANEL_REDIRECTCODES + * optional, redirect-code-id from TABLE_PANEL_REDIRECTCODES * @param bool $sslenabled - * optional, whether or not SSL is enabled for this domain, regardless of the assigned ssl-ips, default 1 (true) + * optional, whether or not SSL is enabled for this domain, regardless of the assigned ssl-ips, default + * 1 (true) * @param bool $ssl_redirect - * optional, whether to generate a https-redirect or not, default false; requires SSL to be enabled + * optional, whether to generate a https-redirect or not, default false; requires SSL to be enabled * @param bool $letsencrypt - * optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires SSL to be enabled + * optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires + * SSL to be enabled * @param bool $http2 - * optional, whether to enable http/2 for this subdomain (requires to be enabled in the settings), default 0 (false) + * optional, whether to enable http/2 for this subdomain (requires to be enabled in the settings), + * default 0 (false) * @param int $hsts_maxage - * optional max-age value for HSTS header, default 0 + * optional max-age value for HSTS header, default 0 * @param bool $hsts_sub - * optional whether or not to add subdomains to the HSTS header, default 0 + * optional whether or not to add subdomains to the HSTS header, default 0 * @param bool $hsts_preload - * optional whether or not to preload HSTS header value, default 0 + * optional whether or not to preload HSTS header value, default 0 * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function add() { @@ -104,26 +132,26 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc // validation $subdomain = strtolower($subdomain); if (substr($subdomain, 0, 4) == 'xn--') { - \Froxlor\UI\Response::standard_error('domain_nopunycode', '', true); + Response::standardError('domain_nopunycode', '', true); } - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); - $subdomain = $idna_convert->encode(preg_replace(array( + $idna_convert = new IdnaWrapper(); + $subdomain = $idna_convert->encode(preg_replace([ '/\:(\d)+$/', '/^https?\:\/\//' - ), '', \Froxlor\Validate\Validate::validate($subdomain, 'subdomain', '', 'subdomainiswrong', array(), true))); + ], '', Validate::validate($subdomain, 'subdomain', '', 'subdomainiswrong', [], true))); // merge the two parts together $completedomain = $subdomain . '.' . $domain; - if (Settings::Get('system.validate_domain') && ! \Froxlor\Validate\Validate::validateDomain($completedomain)) { - \Froxlor\UI\Response::standard_error(array( + if (Settings::Get('system.validate_domain') && !Validate::validateDomain($completedomain)) { + Response::standardError([ 'stringiswrong', 'mydomain' - ), '', true); + ], '', true); } if ($completedomain == strtolower(Settings::Get('system.hostname'))) { - \Froxlor\UI\Response::standard_error('admin_domain_emailsystemhostname', '', true); + Response::standardError('admin_domain_emailsystemhostname', '', true); } // check whether the domain already exists @@ -134,14 +162,14 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc AND `email_only` = '0' AND `caneditdomain` = '1' "); - $completedomain_check = Database::pexecute_first($completedomain_stmt, array( + $completedomain_check = Database::pexecute_first($completedomain_stmt, [ "domain" => $completedomain, "customerid" => $customer['customerid'] - ), true, true); + ], true, true); if ($completedomain_check) { // no exception so far - domain exists - \Froxlor\UI\Response::standard_error('domainexistalready', $completedomain, true); + Response::standardError('domainexistalready', $completedomain, true); } // alias domain checked? @@ -160,14 +188,14 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc GROUP BY `d`.`domain` ORDER BY `d`.`domain` ASC "); - $aliasdomain_check = Database::pexecute_first($aliasdomain_stmt, array( + $aliasdomain_check = Database::pexecute_first($aliasdomain_stmt, [ "id" => $aliasdomain, "customerid" => $customer['customerid'] - ), true, true); + ], true, true); if ($aliasdomain_check['id'] != $aliasdomain) { - \Froxlor\UI\Response::standard_error('domainisaliasorothercustomer', '', true); + Response::standardError('domainisaliasorothercustomer', '', true); } - \Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger()); + Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger()); } // validate / correct path/url of domain @@ -187,20 +215,20 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc AND `email_only` = '0' AND `caneditdomain` = '1' "); - $domain_check = Database::pexecute_first($domain_stmt, array( + $domain_check = Database::pexecute_first($domain_stmt, [ "domain" => $domain, "customerid" => $customer['customerid'] - ), true, true); + ], true, true); - if (! $domain_check) { + if (!$domain_check) { // the given main-domain - \Froxlor\UI\Response::standard_error('maindomainnonexist', $domain, true); + Response::standardError('maindomainnonexist', $domain, true); } elseif ($subdomain == 'www' && $domain_check['wwwserveralias'] == '1') { // you cannot add 'www' as subdomain when the maindomain generates a www-alias - \Froxlor\UI\Response::standard_error('wwwnotallowed', '', true); + Response::standardError('wwwnotallowed', '', true); } elseif ($completedomain_check && strtolower($completedomain_check['domain']) == strtolower($completedomain)) { // the domain does already exist as main-domain - \Froxlor\UI\Response::standard_error('domainexistalready', $completedomain, true); + Response::standardError('domainexistalready', $completedomain, true); } // if allowed, check for 'is email domain'-flag @@ -213,30 +241,30 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc if ($ssl_redirect != 0) { // a ssl-redirect only works if there actually is a // ssl ip/port assigned to the domain - if (\Froxlor\Domain\Domain::domainHasSslIpPort($domain_check['id']) == true) { + if (Domain::domainHasSslIpPort($domain_check['id']) == true) { $ssl_redirect = '1'; $_doredirect = true; } else { - \Froxlor\UI\Response::standard_error('sslredirectonlypossiblewithsslipport', '', true); + Response::standardError('sslredirectonlypossiblewithsslipport', '', true); } } if ($letsencrypt != 0) { // let's encrypt only works if there actually is a // ssl ip/port assigned to the domain - if (\Froxlor\Domain\Domain::domainHasSslIpPort($domain_check['id']) == true) { + if (Domain::domainHasSslIpPort($domain_check['id']) == true) { $letsencrypt = '1'; } else { - \Froxlor\UI\Response::standard_error('letsencryptonlypossiblewithsslipport', '', true); + Response::standardError('letsencryptonlypossiblewithsslipport', '', true); } } // validate dns if lets encrypt is enabled to check whether we can use it at all if ($letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') { $our_ips = Domain::getIpsOfDomain($domain_check['id']); - $domain_ips = \Froxlor\PhpHelper::gethostbynamel6($completedomain); + $domain_ips = PhpHelper::gethostbynamel6($completedomain); if ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) <= 0) { - \Froxlor\UI\Response::standard_error('invaliddnsforletsencrypt', '', true); + Response::standardError('invaliddnsforletsencrypt', '', true); } } @@ -249,11 +277,11 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $phpsid_stmt = Database::prepare(" SELECT `phpsettingid` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `id` = :id "); - $phpsid_result = Database::pexecute_first($phpsid_stmt, array( + $phpsid_result = Database::pexecute_first($phpsid_stmt, [ "id" => $domain_check['id'] - ), true, true); + ], true, true); - if (! isset($phpsid_result['phpsettingid']) || (int) $phpsid_result['phpsettingid'] <= 0) { + if (!isset($phpsid_result['phpsettingid']) || (int)$phpsid_result['phpsettingid'] <= 0) { // assign default config $phpsid_result['phpsettingid'] = 1; } @@ -263,15 +291,15 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc } $allowed_phpconfigs = $customer['allowed_phpconfigs']; - if (! empty($allowed_phpconfigs)) { + if (!empty($allowed_phpconfigs)) { $allowed_phpconfigs = json_decode($allowed_phpconfigs, true); } else { $allowed_phpconfigs = []; } // only with fcgid/fpm enabled will it be possible to select a php-setting - if ((int) Settings::Get('system.mod_fcgid') == 1 || (int) Settings::Get('phpfpm.enabled') == 1) { - if (! in_array($phpsid_result['phpsettingid'], $allowed_phpconfigs)) { - \Froxlor\UI\Response::standard_error('notallowedphpconfigused', '', true); + if ((int)Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) { + if (!in_array($phpsid_result['phpsettingid'], $allowed_phpconfigs)) { + Response::standardError('notallowedphpconfigused', '', true); } } @@ -309,7 +337,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc `tlsv13_cipher_list` = :tlsv13_cipher_list, `ssl_enabled` = :sslenabled "); - $params = array( + $params = [ "customerid" => $customer['customerid'], "adminid" => $customer['adminid'], "domain" => $completedomain, @@ -340,7 +368,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc "ssl_cipher_list" => $domain_check['ssl_cipher_list'], "tlsv13_cipher_list" => $domain_check['tlsv13_cipher_list'], "sslenabled" => $sslenabled - ); + ]; Database::pexecute($stmt, $params, true, true); $subdomain_id = Database::lastInsertId(); @@ -351,41 +379,41 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :id_domain "); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "id_domain" => $domain_check['id'] - )); + ]); if ($_doredirect) { - \Froxlor\Domain\Domain::addRedirectToDomain($subdomain_id, $redirectcode); + Domain::addRedirectToDomain($subdomain_id, $redirectcode); } - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + Cronjob::inserttask(TaskId::REBUILD_VHOST); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); + Cronjob::inserttask(TaskId::REBUILD_DNS); Customers::increaseUsage($customer['customerid'], 'subdomains_used'); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added subdomain '" . $completedomain . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added subdomain '" . $completedomain . "'"); - $result = $this->apiCall('SubDomains.get', array( + $result = $this->apiCall('SubDomains.get', [ 'id' => $subdomain_id - )); + ]); return $this->response($result); } - throw new \Exception("No more resources available", 406); + throw new Exception("No more resources available", 406); } /** * return a subdomain entry by either id or domainname * * @param int $id - * optional, the domain-id + * optional, the domain-id * @param string $domainname - * optional, the domainname + * optional, the domainname * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function get() { @@ -395,7 +423,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc // convert possible idn domain to punycode if (substr($domainname, 0, 4) != 'xn--') { - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); + $idna_convert = new IdnaWrapper(); $domainname = $idna_convert->encode($domainname); } @@ -405,7 +433,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc // whether the database belongs to one of his customers $_custom_list_result = $this->apiCall('Customers.listing'); $custom_list_result = $_custom_list_result['list']; - $customer_ids = array(); + $customer_ids = []; foreach ($custom_list_result as $customer) { $customer_ids[] = $customer['customerid']; } @@ -416,11 +444,11 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc WHERE " . ($id > 0 ? "d.`id` = :iddn" : "d.`domain` = :iddn") . " AND d.`customerid` IN (" . implode(", ", $customer_ids) . ") AND ((d.`parentdomainid`!='0' AND pd.`id` = d.`parentdomainid`) OR (d.`parentdomainid`='0' AND pd.`id` = d.`id`)) "); - $params = array( + $params = [ 'iddn' => ($id <= 0 ? $domainname : $id) - ); + ]; } else { - throw new \Exception("You do not have any customers yet", 406); + throw new Exception("You do not have any customers yet", 406); } } else { $result_stmt = Database::prepare(" @@ -429,13 +457,13 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc WHERE " . ($id > 0 ? "d.`id` = :iddn" : "d.`domain` = :iddn") . " AND ((d.`parentdomainid`!='0' AND pd.`id` = d.`parentdomainid`) OR (d.`parentdomainid`='0' AND pd.`id` = d.`id`)) "); - $params = array( + $params = [ 'iddn' => ($id <= 0 ? $domainname : $id) - ); + ]; } } else { - if (! $this->isInternal() && Settings::IsInList('panel.customer_hide_options', 'domains')) { - throw new \Exception("You cannot access this resource", 405); + if (!$this->isInternal() && Settings::IsInList('panel.customer_hide_options', 'domains')) { + throw new Exception("You cannot access this resource", 405); } $result_stmt = Database::prepare(" SELECT d.*, pd.`subcanemaildomain`, pd.`isbinddomain` as subisbinddomain @@ -443,65 +471,111 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc WHERE d.`customerid`= :customerid AND " . ($id > 0 ? "d.`id` = :iddn" : "d.`domain` = :iddn") . " AND ((d.`parentdomainid`!='0' AND pd.`id` = d.`parentdomainid`) OR (d.`parentdomainid`='0' AND pd.`id` = d.`id`)) "); - $params = array( + $params = [ 'customerid' => $this->getUserDetail('customerid'), 'iddn' => ($id <= 0 ? $domainname : $id) - ); + ]; } $result = Database::pexecute_first($result_stmt, $params, true, true); if ($result) { - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get subdomain '" . $result['domain'] . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get subdomain '" . $result['domain'] . "'"); return $this->response($result); } $key = ($id > 0 ? "id #" . $id : "domainname '" . $domainname . "'"); - throw new \Exception("Subdomain with " . $key . " could not be found", 404); + throw new Exception("Subdomain with " . $key . " could not be found", 404); + } + + /** + * validate given path and replace with url if given and valid + * + * @param string $path + * @param string $url + * @param array $customer + * @param string $completedomain + * @param boolean $_doredirect + * + * @return string validated path + * @throws Exception + */ + private function validateDomainDocumentRoot($path = null, $url = null, $customer = null, $completedomain = null, &$_doredirect = false) + { + // check whether an URL was specified + $_doredirect = false; + if (!empty($url) && Validate::validateUrl($url)) { + $path = $url; + $_doredirect = true; + } else { + $path = Validate::validate($path, 'path', '', '', [], true); + } + + // check whether path is a real path + if (!preg_match('/^https?\:\/\//', $path) || !Validate::validateUrl($path)) { + if (strstr($path, ":") !== false) { + Response::standardError('pathmaynotcontaincolon', '', true); + } + // If path is empty or '/' and 'Use domain name as default value for DocumentRoot path' is enabled in settings, + // set default path to subdomain or domain name + if ((($path == '') || ($path == '/')) && Settings::Get('system.documentroot_use_default_value') == 1) { + $path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $completedomain); + } else { + $path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path); + } + } else { + // no it's not, create a redirect + $_doredirect = true; + } + return $path; } /** * update subdomain entry by either id or domainname * * @param int $id - * optional, the domain-id + * optional, the domain-id * @param string $domainname - * optional, the domainname + * optional, the domainname * @param int $alias - * optional, domain-id of a domain that the new domain should be an alias of + * optional, domain-id of a domain that the new domain should be an alias of * @param string $path - * optional, destination path relative to the customers-homedir, default is customers-homedir + * optional, destination path relative to the customers-homedir, default is customers-homedir * @param string $url - * optional, overwrites path value with an URL to generate a redirect, alternatively use the path parameter also for URLs + * optional, overwrites path value with an URL to generate a redirect, alternatively use the path + * parameter also for URLs * @param int $selectserveralias - * optional, 0 = wildcard, 1 = www-alias, 2 = none + * optional, 0 = wildcard, 1 = www-alias, 2 = none * @param bool $isemaildomain - * optional + * optional * @param int $openbasedir_path - * optional, either 0 for domains-docroot or 1 for customers-homedir + * optional, either 0 for domains-docroot or 1 for customers-homedir * @param int $phpsettingid - * optional, php-settings-id, if empty the $domain value is used + * optional, php-settings-id, if empty the $domain value is used * @param int $redirectcode - * optional, redirect-code-id from TABLE_PANEL_REDIRECTCODES + * optional, redirect-code-id from TABLE_PANEL_REDIRECTCODES * @param bool $sslenabled - * optional, whether or not SSL is enabled for this domain, regardless of the assigned ssl-ips, default 1 (true) + * optional, whether or not SSL is enabled for this domain, regardless of the assigned ssl-ips, default + * 1 (true) * @param bool $ssl_redirect - * optional, whether to generate a https-redirect or not, default false; requires SSL to be enabled + * optional, whether to generate a https-redirect or not, default false; requires SSL to be enabled * @param bool $letsencrypt - * optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires SSL to be enabled + * optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires + * SSL to be enabled * @param bool $http2 - * optional, whether to enable http/2 for this domain (requires to be enabled in the settings), default 0 (false) + * optional, whether to enable http/2 for this domain (requires to be enabled in the settings), default + * 0 (false) * @param int $hsts_maxage - * optional max-age value for HSTS header + * optional max-age value for HSTS header * @param bool $hsts_sub - * optional whether or not to add subdomains to the HSTS header + * optional whether or not to add subdomains to the HSTS header * @param bool $hsts_preload - * optional whether or not to preload HSTS header value + * optional whether or not to preload HSTS header value * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function update() { @@ -510,13 +584,13 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $domainname = $this->getParam('domainname', $dn_optional, ''); if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'domains')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } - $result = $this->apiCall('SubDomains.get', array( + $result = $this->apiCall('SubDomains.get', [ 'id' => $id, 'domainname' => $domainname - )); + ]); $id = $result['id']; // parameters @@ -529,7 +603,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $isemaildomain = $this->getBoolParam('isemaildomain', true, $result['isemaildomain']); $openbasedir_path = $this->getParam('openbasedir_path', true, $result['openbasedir_path']); $phpsettingid = $this->getParam('phpsettingid', true, $result['phpsettingid']); - $redirectcode = $this->getParam('redirectcode', true, \Froxlor\Domain\Domain::getDomainRedirectId($id)); + $redirectcode = $this->getParam('redirectcode', true, Domain::getDomainRedirectId($id)); if (Settings::Get('system.use_ssl')) { $sslenabled = $this->getBoolParam('sslenabled', true, $result['ssl_enabled']); $ssl_redirect = $this->getBoolParam('ssl_redirect', true, $result['ssl_redirect']); @@ -552,9 +626,9 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $customer = $this->getCustomerData(); $alias_stmt = Database::prepare("SELECT COUNT(`id`) AS count FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `aliasdomain`= :aliasdomain"); - $alias_check = Database::pexecute_first($alias_stmt, array( + $alias_check = Database::pexecute_first($alias_stmt, [ "aliasdomain" => $result['id'] - )); + ]); $alias_check = $alias_check['count']; // alias domain checked? @@ -567,14 +641,14 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc AND `c`.`customerid`= :customerid AND `d`.`id`= :id "); - $aliasdomain_check = Database::pexecute_first($aliasdomain_stmt, array( + $aliasdomain_check = Database::pexecute_first($aliasdomain_stmt, [ "id" => $aliasdomain, "customerid" => $customer['customerid'] - ), true, true); + ], true, true); if ($aliasdomain_check['id'] != $aliasdomain) { - \Froxlor\UI\Response::standard_error('domainisaliasorothercustomer', '', true); + Response::standardError('domainisaliasorothercustomer', '', true); } - \Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger()); + Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger()); } // validate / correct path/url of domain @@ -600,36 +674,36 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc if ($ssl_redirect != 0) { // a ssl-redirect only works if there actually is a // ssl ip/port assigned to the domain - if (\Froxlor\Domain\Domain::domainHasSslIpPort($result['id']) == true) { + if (Domain::domainHasSslIpPort($result['id']) == true) { $ssl_redirect = '1'; $_doredirect = true; } else { - \Froxlor\UI\Response::standard_error('sslredirectonlypossiblewithsslipport', '', true); + Response::standardError('sslredirectonlypossiblewithsslipport', '', true); } } if ($letsencrypt != 0) { // let's encrypt only works if there actually is a // ssl ip/port assigned to the domain - if (\Froxlor\Domain\Domain::domainHasSslIpPort($result['id']) == true) { + if (Domain::domainHasSslIpPort($result['id']) == true) { $letsencrypt = '1'; } else { - \Froxlor\UI\Response::standard_error('letsencryptonlypossiblewithsslipport', '', true); + Response::standardError('letsencryptonlypossiblewithsslipport', '', true); } } // validate dns if lets encrypt is enabled to check whether we can use it at all if ($result['letsencrypt'] != $letsencrypt && $letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') { $our_ips = Domain::getIpsOfDomain($result['parentdomainid']); - $domain_ips = \Froxlor\PhpHelper::gethostbynamel6($result['domain']); + $domain_ips = PhpHelper::gethostbynamel6($result['domain']); if ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) <= 0) { - \Froxlor\UI\Response::standard_error('invaliddnsforletsencrypt', '', true); + Response::standardError('invaliddnsforletsencrypt', '', true); } } // We can't enable let's encrypt for wildcard-domains if ($iswildcarddomain == '1' && $letsencrypt == '1') { - \Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt', '', true); + Response::standardError('nowildcardwithletsencrypt', '', true); } // Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated @@ -639,34 +713,34 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc // is-email-domain flag changed - remove mail accounts and mail-addresses if (($result['isemaildomain'] == '1') && $isemaildomain == '0') { - $params = array( + $params = [ "customerid" => $customer['customerid'], "domainid" => $id - ); + ]; $stmt = Database::prepare("DELETE FROM `" . TABLE_MAIL_USERS . "` WHERE `customerid`= :customerid AND `domainid`= :domainid"); Database::pexecute($stmt, $params, true, true); $stmt = Database::prepare("DELETE FROM `" . TABLE_MAIL_VIRTUAL . "` WHERE `customerid`= :customerid AND `domainid`= :domainid"); Database::pexecute($stmt, $params, true, true); - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] automatically deleted mail-table entries for '" . $idna_convert->decode($result['domain']) . "'"); + $idna_convert = new IdnaWrapper(); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] automatically deleted mail-table entries for '" . $idna_convert->decode($result['domain']) . "'"); } $allowed_phpconfigs = $customer['allowed_phpconfigs']; - if (! empty($allowed_phpconfigs)) { + if (!empty($allowed_phpconfigs)) { $allowed_phpconfigs = json_decode($allowed_phpconfigs, true); } else { $allowed_phpconfigs = []; } // only with fcgid/fpm enabled will it be possible to select a php-setting - if ((int) Settings::Get('system.mod_fcgid') == 1 || (int) Settings::Get('phpfpm.enabled') == 1) { - if (! in_array($phpsettingid, $allowed_phpconfigs)) { - \Froxlor\UI\Response::standard_error('notallowedphpconfigused', '', true); + if ((int)Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) { + if (!in_array($phpsettingid, $allowed_phpconfigs)) { + Response::standardError('notallowedphpconfigused', '', true); } } // handle redirect if ($_doredirect) { - \Froxlor\Domain\Domain::updateRedirectOfDomain($id, $redirectcode); + Domain::updateRedirectOfDomain($id, $redirectcode); } if ($path != $result['documentroot'] || $isemaildomain != $result['isemaildomain'] || $wwwserveralias != $result['wwwserveralias'] || $iswildcarddomain != $result['iswildcarddomain'] || $aliasdomain != (int)$result['aliasdomain'] || $openbasedir_path != $result['openbasedir_path'] || $ssl_redirect != $result['ssl_redirect'] || $letsencrypt != $result['letsencrypt'] || $hsts_maxage != $result['hsts'] || $hsts_sub != $result['hsts_sub'] || $hsts_preload != $result['hsts_preload'] || $phpsettingid != $result['phpsettingid']) { @@ -688,7 +762,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc `phpsettingid` = :phpsettingid WHERE `customerid`= :customerid AND `id`= :id "); - $params = array( + $params = [ "documentroot" => $path, "isemaildomain" => $isemaildomain, "wwwserveralias" => $wwwserveralias, @@ -705,22 +779,22 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc "phpsettingid" => $phpsettingid, "customerid" => $customer['customerid'], "id" => $id - ); + ]; Database::pexecute($stmt, $params, true, true); if ($result['aliasdomain'] != $aliasdomain && is_numeric($result['aliasdomain'])) { // trigger when domain id for alias destination has changed: both for old and new destination - \Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger()); - \Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger()); + Domain::triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger()); + Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger()); } if ($result['wwwserveralias'] != $wwwserveralias || $result['letsencrypt'] != $letsencrypt) { // or when wwwserveralias or letsencrypt was changed - \Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger()); - if ((int) $aliasdomain === 0) { + Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger()); + if ((int)$aliasdomain === 0) { // in case the wwwserveralias is set on a main domain, $aliasdomain is 0 // --> the call just above to triggerLetsEncryptCSRForAliasDestinationDomain // is a noop...let's repeat it with the domain id of the main domain - \Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($id, $this->logger()); + Domain::triggerLetsEncryptCSRForAliasDestinationDomain($id, $this->logger()); } } @@ -729,21 +803,21 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :id "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'id' => $id - ), true, true); + ], true, true); // remove domain from acme.sh / lets encrypt if used - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_SSL, $result['domain']); + Cronjob::inserttask(TaskId::DELETE_DOMAIN_SSL, $result['domain']); } - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] edited domain '" . $idna_convert->decode($result['domain']) . "'"); + Cronjob::inserttask(TaskId::REBUILD_VHOST); + Cronjob::inserttask(TaskId::REBUILD_DNS); + $idna_convert = new IdnaWrapper(); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] edited domain '" . $idna_convert->decode($result['domain']) . "'"); } - $result = $this->apiCall('SubDomains.get', array( + $result = $this->apiCall('SubDomains.get', [ 'id' => $id - )); + ]); return $this->response($result); } @@ -751,21 +825,23 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc * lists all subdomain entries * * @param int $customerid - * optional, admin-only, select (sub)domains of a specific customer by id + * optional, admin-only, select (sub)domains of a specific customer by id * @param string $loginname - * optional, admin-only, select (sub)domains of a specific customer by loginname + * optional, admin-only, select (sub)domains of a specific customer by loginname * @param array $sql_search - * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue * @param int $sql_limit - * optional specify number of results to be returned + * optional specify number of results to be returned * @param int $sql_offset - * optional specify offset for resultset + * optional specify offset for resultset * @param array $sql_orderby - * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more + * fields * * @access admin, customer - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listing() { @@ -775,29 +851,29 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $customerid = $this->getParam('customerid', true, 0); $loginname = $this->getParam('loginname', true, ''); - if (! empty($customerid) || ! empty($loginname)) { - $result = $this->apiCall('Customers.get', array( + if (!empty($customerid) || !empty($loginname)) { + $result = $this->apiCall('Customers.get', [ 'id' => $customerid, 'loginname' => $loginname - )); - $custom_list_result = array( + ]); + $custom_list_result = [ $result - ); + ]; } else { $_custom_list_result = $this->apiCall('Customers.listing'); $custom_list_result = $_custom_list_result['list']; } - $customer_ids = array(); - $customer_stdsubs = array(); + $customer_ids = []; + $customer_stdsubs = []; foreach ($custom_list_result as $customer) { $customer_ids[] = $customer['customerid']; $customer_stdsubs[$customer['customerid']] = $customer['standardsubdomain']; } if (empty($customer_ids)) { - throw new \Exception("Required resource unsatisfied.", 405); + throw new Exception("Required resource unsatisfied.", 405); } if (empty($customer_stdsubs)) { - throw new \Exception("Required resource unsatisfied.", 405); + throw new Exception("Required resource unsatisfied.", 405); } $select_fields = [ @@ -805,14 +881,14 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc ]; } else { if (Settings::IsInList('panel.customer_hide_options', 'domains')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } - $customer_ids = array( + $customer_ids = [ $this->getUserDetail('customerid') - ); - $customer_stdsubs = array( + ]; + $customer_stdsubs = [ $this->getUserDetail('customerid') => $this->getUserDetail('standardsubdomain') - ); + ]; $select_fields = [ '`d`.`id`', @@ -830,7 +906,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc '`d`.`termination_date`' ]; } - $query_fields = array(); + $query_fields = []; // prepare select statement $domains_stmt = Database::prepare(" @@ -843,28 +919,28 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc AND `d`.`email_only` = '0' AND `d`.`id` NOT IN (" . implode(', ', $customer_stdsubs) . ")" . $this->getSearchWhere($query_fields, true) . " GROUP BY `d`.`id` ORDER BY `parentdomainname` " . $this->getOrderBy(true) . $this->getLimit()); - $result = array(); + $result = []; Database::pexecute($domains_stmt, $query_fields, true, true); - while ($row = $domains_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $domains_stmt->fetch(PDO::FETCH_ASSOC)) { $result[] = $row; } - return $this->response(array( + return $this->response([ 'count' => count($result), 'list' => $result - )); + ]); } /** * returns the total number of accessible subdomain entries * * @param int $customerid - * optional, admin-only, select (sub)domains of a specific customer by id + * optional, admin-only, select (sub)domains of a specific customer by id * @param string $loginname - * optional, admin-only, select (sub)domains of a specific customer by loginname + * optional, admin-only, select (sub)domains of a specific customer by loginname * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function listingCount() { @@ -874,34 +950,34 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $customerid = $this->getParam('customerid', true, 0); $loginname = $this->getParam('loginname', true, ''); - if (! empty($customerid) || ! empty($loginname)) { - $result = $this->apiCall('Customers.get', array( + if (!empty($customerid) || !empty($loginname)) { + $result = $this->apiCall('Customers.get', [ 'id' => $customerid, 'loginname' => $loginname - )); - $custom_list_result = array( + ]); + $custom_list_result = [ $result - ); + ]; } else { $_custom_list_result = $this->apiCall('Customers.listing'); $custom_list_result = $_custom_list_result['list']; } - $customer_ids = array(); - $customer_stdsubs = array(); + $customer_ids = []; + $customer_stdsubs = []; foreach ($custom_list_result as $customer) { $customer_ids[] = $customer['customerid']; $customer_stdsubs[$customer['customerid']] = $customer['standardsubdomain']; } } else { if (Settings::IsInList('panel.customer_hide_options', 'domains')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } - $customer_ids = array( + $customer_ids = [ $this->getUserDetail('customerid') - ); - $customer_stdsubs = array( + ]; + $customer_stdsubs = [ $this->getUserDetail('customerid') => $this->getUserDetail('standardsubdomain') - ); + ]; } // prepare select statement $domains_stmt = Database::prepare(" @@ -921,17 +997,17 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc * delete a subdomain by either id or domainname * * @param int $id - * optional, the domain-id + * optional, the domain-id * @param string $domainname - * optional, the domainname + * optional, the domainname * @param int $customerid - * optional, required when called as admin (if $loginname is not specified) + * optional, required when called as admin (if $loginname is not specified) * @param string $loginname - * optional, required when called as admin (if $customerid is not specified) + * optional, required when called as admin (if $customerid is not specified) * * @access admin, customer - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function delete() { @@ -940,20 +1016,20 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $domainname = $this->getParam('domainname', $dn_optional, ''); if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'domains')) { - throw new \Exception("You cannot access this resource", 405); + throw new Exception("You cannot access this resource", 405); } - $result = $this->apiCall('SubDomains.get', array( + $result = $this->apiCall('SubDomains.get', [ 'id' => $id, 'domainname' => $domainname - )); + ]); $id = $result['id']; // get needed customer info to reduce the subdomain-usage-counter by one $customer = $this->getCustomerData(); - if (! $this->isAdmin() && $result['caneditdomain'] == 0) { - throw new \Exception("You cannot edit this resource", 405); + if (!$this->isAdmin() && $result['caneditdomain'] == 0) { + throw new Exception("You cannot edit this resource", 405); } if ($result['isemaildomain'] == '1') { @@ -962,117 +1038,75 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc SELECT COUNT(`id`) AS `count` FROM `" . TABLE_MAIL_VIRTUAL . "` WHERE `customerid` = :customerid AND `domainid` = :domainid "); - $emails = Database::pexecute_first($emails_stmt, array( + $emails = Database::pexecute_first($emails_stmt, [ "customerid" => $customer['customerid'], "domainid" => $id - ), true, true); + ], true, true); if ($emails['count'] != '0') { - \Froxlor\UI\Response::standard_error('domains_cantdeletedomainwithemail', '', true); + Response::standardError('domains_cantdeletedomainwithemail', '', true); } } - \Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger()); + Domain::triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger()); // delete domain from table $stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :customerid AND `id` = :id "); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "customerid" => $customer['customerid'], "id" => $id - ), true, true); + ], true, true); // remove connections to ips and domainredirects $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :domainid "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'domainid' => $id - ), true, true); + ], true, true); // remove redirect-codes $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_DOMAINREDIRECTS . "` WHERE `did` = :domainid "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'domainid' => $id - ), true, true); + ], true, true); // remove certificate from domain_ssl_settings, fixes #1596 $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :domainid "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'domainid' => $id - ), true, true); + ], true, true); // remove possible existing DNS entries $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_DOMAIN_DNS . "` WHERE `domain_id` = :domainid "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'domainid' => $id - ), true, true); + ], true, true); - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + Cronjob::inserttask(TaskId::REBUILD_VHOST); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); + Cronjob::inserttask(TaskId::REBUILD_DNS); // remove domains DNS from powerDNS if used, #581 - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_PDNS, $result['domain']); + Cronjob::inserttask(TaskId::DELETE_DOMAIN_PDNS, $result['domain']); // remove domain from acme.sh / lets encrypt if used - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_SSL, $result['domain']); + Cronjob::inserttask(TaskId::DELETE_DOMAIN_SSL, $result['domain']); // reduce subdomain-usage-counter Customers::decreaseUsage($customer['customerid'], 'subdomains_used'); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] deleted subdomain '" . $result['domain'] . "'"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] deleted subdomain '" . $result['domain'] . "'"); return $this->response($result); } - - /** - * validate given path and replace with url if given and valid - * - * @param string $path - * @param string $url - * @param array $customer - * @param string $completedomain - * @param boolean $_doredirect - * - * @return string validated path - * @throws \Exception - */ - private function validateDomainDocumentRoot($path = null, $url = null, $customer = null, $completedomain = null, &$_doredirect = false) - { - // check whether an URL was specified - $_doredirect = false; - if (! empty($url) && \Froxlor\Validate\Validate::validateUrl($url)) { - $path = $url; - $_doredirect = true; - } else { - $path = \Froxlor\Validate\Validate::validate($path, 'path', '', '', array(), true); - } - - // check whether path is a real path - if (! preg_match('/^https?\:\/\//', $path) || ! \Froxlor\Validate\Validate::validateUrl($path)) { - if (strstr($path, ":") !== false) { - \Froxlor\UI\Response::standard_error('pathmaynotcontaincolon', '', true); - } - // If path is empty or '/' and 'Use domain name as default value for DocumentRoot path' is enabled in settings, - // set default path to subdomain or domain name - if ((($path == '') || ($path == '/')) && Settings::Get('system.documentroot_use_default_value') == 1) { - $path = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $completedomain); - } else { - $path = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path); - } - } else { - // no it's not, create a redirect - $_doredirect = true; - } - return $path; - } } diff --git a/lib/Froxlor/Api/Commands/SysLog.php b/lib/Froxlor/Api/Commands/SysLog.php index cebcffcb..1428793c 100644 --- a/lib/Froxlor/Api/Commands/SysLog.php +++ b/lib/Froxlor/Api/Commands/SysLog.php @@ -1,46 +1,65 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @since 0.10.6 - * + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class SysLog extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Database\Database; +use Froxlor\FroxlorLogger; +use PDO; + +/** + * @since 0.10.6 + */ +class SysLog extends ApiCommand implements ResourceEntity { /** * list all log-entries * * @param array $sql_search - * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue * @param int $sql_limit - * optional specify number of results to be returned + * optional specify number of results to be returned * @param int $sql_offset - * optional specify offset for resultset + * optional specify offset for resultset * @param array $sql_orderby - * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields - * + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more + * fields + * * @access admin, customer - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listing() { - $result = array(); - $query_fields = array(); + $result = []; + $query_fields = []; if ($this->isAdmin() && $this->getUserDetail('customers_see_all') == '1') { $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_LOG . "` " . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit()); @@ -48,7 +67,7 @@ class SysLog extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt // get all admin customers $_custom_list_result = $this->apiCall('Customers.listing'); $custom_list_result = $_custom_list_result['list']; - $customer_names = array(); + $customer_names = []; foreach ($custom_list_result as $customer) { $customer_names[] = $customer['loginname']; } @@ -70,22 +89,22 @@ class SysLog extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $query_fields['loginname'] = $this->getUserDetail('loginname'); } Database::pexecute($result_stmt, $query_fields, true, true); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $result[] = $row; } - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list log-entries"); - return $this->response(array( + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list log-entries"); + return $this->response([ 'count' => count($result), 'list' => $result - )); + ]); } /** * returns the total number of log-entries * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function listingCount() { @@ -98,7 +117,7 @@ class SysLog extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt // get all admin customers $_custom_list_result = $this->apiCall('Customers.listing'); $custom_list_result = $_custom_list_result['list']; - $customer_names = array(); + $customer_names = []; foreach ($custom_list_result as $customer) { $customer_names[] = $customer['loginname']; } @@ -138,7 +157,7 @@ class SysLog extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt */ public function get() { - throw new \Exception('You cannot get log entries', 303); + throw new Exception('You cannot get log entries', 303); } /** @@ -146,7 +165,7 @@ class SysLog extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt */ public function add() { - throw new \Exception('You cannot add log entries', 303); + throw new Exception('You cannot add log entries', 303); } /** @@ -154,18 +173,18 @@ class SysLog extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt */ public function update() { - throw new \Exception('You cannot update log entries', 303); + throw new Exception('You cannot update log entries', 303); } /** * delete log entries * * @param int $min_to_keep - * optional minutes to keep, default is 10 - * + * optional minutes to keep, default is 10 + * * @access admin - * @throws \Exception * @return string json-encoded array + * @throws Exception */ public function delete() { @@ -175,7 +194,7 @@ class SysLog extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $min_to_keep = 0; } $truncatedate = time() - (60 * $min_to_keep); - $params = array(); + $params = []; if ($this->getUserDetail('customers_see_all') == '1') { $result_stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_LOG . "` WHERE `date` < :trunc @@ -184,7 +203,7 @@ class SysLog extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt // get all admin customers $_custom_list_result = $this->apiCall('Customers.listing'); $custom_list_result = $_custom_list_result['list']; - $customer_names = array(); + $customer_names = []; foreach ($custom_list_result as $customer) { $customer_names[] = $customer['loginname']; } @@ -203,9 +222,9 @@ class SysLog extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt } $params['trunc'] = $truncatedate; Database::pexecute($result_stmt, $params, true, true); - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] truncated the froxlor syslog"); + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] truncated the froxlor syslog"); return $this->response(true); } - throw new \Exception("Not allowed to execute given command.", 403); + throw new Exception("Not allowed to execute given command.", 403); } } diff --git a/lib/Froxlor/Api/Commands/Traffic.php b/lib/Froxlor/Api/Commands/Traffic.php index 178ef379..7fbf9c64 100644 --- a/lib/Froxlor/Api/Commands/Traffic.php +++ b/lib/Froxlor/Api/Commands/Traffic.php @@ -1,91 +1,109 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class Traffic extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Database\Database; +use Froxlor\FroxlorLogger; +use PDO; + +/** + * @since 0.10.0 + */ +class Traffic extends ApiCommand implements ResourceEntity { /** * You cannot add traffic data * - * @throws \Exception + * @throws Exception */ public function add() { - throw new \Exception('You cannot add traffic data', 303); + throw new Exception('You cannot add traffic data', 303); } /** * to get specific traffic details use year, month and/or day parameter for Traffic.listing() * - * @throws \Exception + * @throws Exception */ public function get() { - throw new \Exception('To get specific traffic details use year, month and/or day parameter for Traffic.listing()', 303); + throw new Exception('To get specific traffic details use year, month and/or day parameter for Traffic.listing()', 303); } /** * You cannot update traffic data * - * @throws \Exception + * @throws Exception */ public function update() { - throw new \Exception('You cannot update traffic data', 303); + throw new Exception('You cannot update traffic data', 303); } /** * list traffic information * * @param int $year - * optional, default empty + * optional, default empty * @param int $month - * optional, default empty + * optional, default empty * @param int $day - * optional, default empty + * optional, default empty * @param int $date_from - * optional timestamp, default empty, if specified, $year, $month and $day will be ignored + * optional timestamp, default empty, if specified, $year, $month and $day will be ignored * @param int $date_until - * optional timestamp, default empty, if specified, $year, $month and $day will be ignored + * optional timestamp, default empty, if specified, $year, $month and $day will be ignored * @param bool $customer_traffic - * optional, admin-only, whether to output ones own traffic or all of ones customers, default is 0 (false) + * optional, admin-only, whether to output ones own traffic or all of ones customers, default is 0 + * (false) * @param int $customerid - * optional, admin-only, select traffic of a specific customer by id + * optional, admin-only, select traffic of a specific customer by id * @param string $loginname - * optional, admin-only, select traffic of a specific customer by loginname - * + * optional, admin-only, select traffic of a specific customer by loginname + * * @access admin, customer - * @throws \Exception * @return string json-encoded array count|list + * @throws Exception */ public function listing() { $year = $this->getParam('year', true, ""); $month = $this->getParam('month', true, ""); $day = $this->getParam('day', true, ""); - $date_from = $this->getParam('date_from', true, - 1); - $date_until = $this->getParam('date_until', true, - 1); + $date_from = $this->getParam('date_from', true, -1); + $date_until = $this->getParam('date_until', true, -1); $customer_traffic = $this->getBoolParam('customer_traffic', true, 0); $customer_ids = $this->getAllowedCustomerIds(); - $result = array(); - $params = array(); + $result = []; + $params = []; // validate parameters if ($date_from >= 0 || $date_until >= 0) { @@ -105,15 +123,15 @@ class Traffic extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn // check for year/month/day $where_str = ""; - if (! empty($year) && is_numeric($year)) { + if (!empty($year) && is_numeric($year)) { $where_str .= " AND `year` = :year"; $params['year'] = $year; } - if (! empty($month) && is_numeric($month)) { + if (!empty($month) && is_numeric($month)) { $where_str .= " AND `month` = :month"; $params['month'] = $month; } - if (! empty($day) && is_numeric($day)) { + if (!empty($day) && is_numeric($day)) { $where_str .= " AND `day` = :day"; $params['day'] = $day; } @@ -129,7 +147,7 @@ class Traffic extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $params['du'] = $date_until; } - if (! $this->isAdmin() || ($this->isAdmin() && $customer_traffic)) { + if (!$this->isAdmin() || ($this->isAdmin() && $customer_traffic)) { $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_TRAFFIC . "` WHERE `customerid` IN (" . implode(", ", $customer_ids) . ")" . $where_str); @@ -140,33 +158,33 @@ class Traffic extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn WHERE `adminid` = :adminid" . $where_str); } Database::pexecute($result_stmt, $params, true, true); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $result[] = $row; } - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list traffic"); - return $this->response(array( + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list traffic"); + return $this->response([ 'count' => count($result), 'list' => $result - )); + ]); } /** * You cannot count the traffic data list * - * @throws \Exception + * @throws Exception */ public function listingCount() { - throw new \Exception('You cannot count the traffic data list', 303); + throw new Exception('You cannot count the traffic data list', 303); } /** * You cannot delete traffic data * - * @throws \Exception + * @throws Exception */ public function delete() { - throw new \Exception('You cannot delete traffic data', 303); + throw new Exception('You cannot delete traffic data', 303); } } diff --git a/lib/Froxlor/Api/FroxlorRPC.php b/lib/Froxlor/Api/FroxlorRPC.php index d3faba45..4a85872b 100644 --- a/lib/Froxlor/Api/FroxlorRPC.php +++ b/lib/Froxlor/Api/FroxlorRPC.php @@ -1,27 +1,34 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\Api; use Exception; use Froxlor\Database\Database; use Froxlor\System\IPTools; -/** - * 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 - * - * @copyright (c) the authors - * @author Froxlor team (2010-) - * @author Maurice Preuß - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @since 0.10.0 - * - */ class FroxlorRPC { /** @@ -76,10 +83,10 @@ class FroxlorRPC WHERE `apikey` = :ak AND `secret` = :as " ); - $result = Database::pexecute_first($sel_stmt, array( + $result = Database::pexecute_first($sel_stmt, [ 'ak' => $key, 'as' => $secret - ), true, true); + ], true, true); if ($result) { if ($result['apikey'] == $key && $result['secret'] == $secret && ($result['valid_until'] == -1 || $result['valid_until'] >= time()) && (($result['customerid'] == 0 && $result['admin_api_allowed'] == 1) || ($result['customerid'] > 0 && $result['cust_api_allowed'] == 1 && $result['deactivated'] == 0))) { // get user to check whether api call is allowed @@ -149,12 +156,12 @@ class FroxlorRPC if (!class_exists($apiclass) || !@method_exists($apiclass, $command[1])) { throw new Exception("Unknown command", 400); } - return array( - 'command' => array( + return [ + 'command' => [ 'class' => $command[0], 'method' => $command[1] - ), + ], 'params' => $request['params'] ?? null - ); + ]; } } diff --git a/lib/Froxlor/Api/ResourceEntity.php b/lib/Froxlor/Api/ResourceEntity.php index fe3068da..13ed7ee7 100644 --- a/lib/Froxlor/Api/ResourceEntity.php +++ b/lib/Froxlor/Api/ResourceEntity.php @@ -1,20 +1,32 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + +namespace Froxlor\Api; + +/** * @since 0.10.0 - * */ interface ResourceEntity { diff --git a/lib/Froxlor/Api/Response.php b/lib/Froxlor/Api/Response.php index 1ebae861..920a4c79 100644 --- a/lib/Froxlor/Api/Response.php +++ b/lib/Froxlor/Api/Response.php @@ -1,24 +1,37 @@ (2010-) - * @author Maurice Preuß - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\Api; + class Response { + public static function jsonDataResponse($data = null, int $response_code = 200) + { + return self::jsonResponse(['data' => $data], $response_code); + } + public static function jsonResponse($data = null, int $response_code = 200) { http_response_code($response_code); @@ -26,11 +39,6 @@ class Response return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT); } - public static function jsonDataResponse($data = null, int $response_code = 200) - { - return self::jsonResponse(['data' => $data], $response_code); - } - public static function jsonErrorResponse($message = null, int $response_code = 400) { return self::jsonResponse(['message' => $message], $response_code); diff --git a/lib/Froxlor/Bulk/BulkAction.php b/lib/Froxlor/Bulk/BulkAction.php index 9f946b38..ecb2d627 100644 --- a/lib/Froxlor/Bulk/BulkAction.php +++ b/lib/Froxlor/Bulk/BulkAction.php @@ -1,67 +1,72 @@ - * @author Froxlor team (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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ +namespace Froxlor\Bulk; + +use Exception; +use Froxlor\FileDir; + /** * Abstract Class BulkAction to mass-import entities * * @author Michael Kaufmann (d00p) - * + * */ abstract class BulkAction { - /** - * complete path including filename of file to be imported - * - * @var string - */ - private $impFile = null; - - /** - * api-function to call for addingg entity - * - * @var string - */ - private $api_call = null; - - /** - * api-function parameter names, read from import-file (first line) - * - * @var array - */ - private $api_params = null; - - /** - * errors while importing - * - * @var array - */ - private $errors = array(); - /** * logged in user * * @var array */ - protected $userinfo = array(); + protected $userinfo = []; + /** + * complete path including filename of file to be imported + * + * @var string + */ + private $impFile = null; + /** + * api-function to call for addingg entity + * + * @var string + */ + private $api_call = null; + /** + * api-function parameter names, read from import-file (first line) + * + * @var array + */ + private $api_params = null; + /** + * errors while importing + * + * @var array + */ + private $errors = []; /** * class constructor, optionally sets file and customer-id @@ -71,10 +76,10 @@ abstract class BulkAction * * @return object BulkAction instance */ - protected function __construct($import_file = null, $userinfo = array()) + protected function __construct($import_file = null, $userinfo = []) { - if (! empty($import_file)) { - $this->impFile = \Froxlor\FileDir::makeCorrectFile($import_file); + if (!empty($import_file)) { + $this->impFile = FileDir::makeCorrectFile($import_file); } $this->userinfo = $userinfo; } @@ -99,7 +104,7 @@ abstract class BulkAction */ public function setImportFile($import_file = null) { - $this->impFile = \Froxlor\FileDir::makeCorrectFile($import_file); + $this->impFile = FileDir::makeCorrectFile($import_file); } /** @@ -126,12 +131,14 @@ abstract class BulkAction protected function importEntity($data_array = null) { - if (empty($data_array)) return null; + if (empty($data_array)) { + return null; + } $module = '\\Froxlor\\Api\\Commands\\' . substr($this->api_call, 0, strpos($this->api_call, ".")); $function = substr($this->api_call, strpos($this->api_call, ".") + 1); - $new_data = array(); + $new_data = []; foreach ($this->api_params as $idx => $param) { if (isset($data_array[$idx])) { $new_data[$param] = $data_array[$idx]; @@ -142,10 +149,10 @@ abstract class BulkAction try { $json_result = $module::getLocal($this->userinfo, $new_data)->$function(); $result = json_decode($json_result, true)['data']; - } catch (\Exception $e) { + } catch (Exception $e) { $this->errors[] = $e->getMessage(); } - return ! empty($result); + return !empty($result); } /** @@ -159,28 +166,28 @@ abstract class BulkAction protected function parseImportFile($separator = ";") { if (empty($this->impFile)) { - throw new \Exception("No file was given for import"); + throw new Exception("No file was given for import"); } - if (! file_exists($this->impFile)) { - throw new \Exception("The file '" . $this->impFile . "' could not be found"); + if (!file_exists($this->impFile)) { + throw new Exception("The file '" . $this->impFile . "' could not be found"); } - if (! is_readable($this->impFile)) { - throw new \Exception("Unable to read file '" . $this->impFile . "'"); + if (!is_readable($this->impFile)) { + throw new Exception("Unable to read file '" . $this->impFile . "'"); } if (empty($separator) || strlen($separator) != 1) { - throw new \Exception("Invalid separator specified: '" . $separator . "'"); + throw new Exception("Invalid separator specified: '" . $separator . "'"); } - $file_data = array(); + $file_data = []; $is_params_line = true; $fh = @fopen($this->impFile, "r"); if ($fh) { while (($line = fgets($fh)) !== false) { $tmp_arr = explode($separator, $line); - $data_arr = array(); + $data_arr = []; foreach ($tmp_arr as $idx => $data) { if ($is_params_line) { $this->api_params[$idx] = $data; @@ -196,7 +203,7 @@ abstract class BulkAction } $this->api_params = array_map("trim", $this->api_params); } else { - throw new \Exception("Unable to open file '" . $this->impFile . "'"); + throw new Exception("Unable to open file '" . $this->impFile . "'"); } fclose($fh); diff --git a/lib/Froxlor/Bulk/DomainBulkAction.php b/lib/Froxlor/Bulk/DomainBulkAction.php index 2c0cf280..155f3de4 100644 --- a/lib/Froxlor/Bulk/DomainBulkAction.php +++ b/lib/Froxlor/Bulk/DomainBulkAction.php @@ -1,29 +1,34 @@ - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Cron - * - * @since 0.9.33 - * + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ +namespace Froxlor\Bulk; + +use Exception; + /** * Class DomainBulkAction to mass-import domains for a given customer - * - * @author Michael Kaufmann (d00p) - * */ class DomainBulkAction extends BulkAction { @@ -55,21 +60,21 @@ class DomainBulkAction extends BulkAction $dom_unlimited = false; } - $domains_used = (int) $this->userinfo['domains_used']; - $domains_avail = (int) $this->userinfo['domains']; + $domains_used = (int)$this->userinfo['domains_used']; + $domains_avail = (int)$this->userinfo['domains']; - if (! is_int($offset) || $offset < 0) { - throw new \Exception("Invalid offset specified"); + if (!is_int($offset) || $offset < 0) { + throw new Exception("Invalid offset specified"); } try { $domain_array = $this->parseImportFile($separator); - } catch (\Exception $e) { + } catch (Exception $e) { throw $e; } if (count($domain_array) <= 0) { - throw new \Exception("No domains were read from the file."); + throw new Exception("No domains were read from the file."); } $global_counter = 0; @@ -77,25 +82,24 @@ class DomainBulkAction extends BulkAction $note = ''; foreach ($domain_array as $idx => $dom) { if ($idx >= $offset) { - if ($dom_unlimited || (! $dom_unlimited && $domains_used < $domains_avail)) { - + if ($dom_unlimited || (!$dom_unlimited && $domains_used < $domains_avail)) { $result = $this->importEntity($dom); if ($result) { - $import_counter ++; - $domains_used ++; + $import_counter++; + $domains_used++; } } else { $note .= 'You have reached your maximum allocation of domains (' . $domains_avail . ').'; break; } } - $global_counter ++; + $global_counter++; } - return array( + return [ 'all' => $global_counter, 'imported' => $import_counter, 'notice' => $note - ); + ]; } } diff --git a/lib/Froxlor/Cli/CliCommand.php b/lib/Froxlor/Cli/CliCommand.php index 344d3ce7..935c41e6 100644 --- a/lib/Froxlor/Cli/CliCommand.php +++ b/lib/Froxlor/Cli/CliCommand.php @@ -11,24 +11,24 @@ * * 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 + * 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 - * http://files.froxlor.org/misc/COPYING.txt + * https://files.froxlor.org/misc/COPYING.txt * * @copyright the authors * @author Froxlor team - * @license http://files.froxlor.org/misc/COPYING.txt GPLv2 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ namespace Froxlor\Cli; +use Froxlor\Froxlor; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Froxlor\Froxlor; class CliCommand extends Command { diff --git a/lib/Froxlor/Cli/ConfigServices.php b/lib/Froxlor/Cli/ConfigServices.php index 0feeefb7..4f27dc9f 100644 --- a/lib/Froxlor/Cli/ConfigServices.php +++ b/lib/Froxlor/Cli/ConfigServices.php @@ -11,31 +11,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 + * 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 - * http://files.froxlor.org/misc/COPYING.txt + * https://files.froxlor.org/misc/COPYING.txt * * @copyright the authors * @author Froxlor team - * @license http://files.froxlor.org/misc/COPYING.txt GPLv2 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ namespace Froxlor\Cli; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; +use Froxlor\Config\ConfigParser; +use Froxlor\Database\Database; use Froxlor\FileDir; use Froxlor\Froxlor; use Froxlor\PhpHelper; use Froxlor\Settings; use Froxlor\SImExporter; -use Froxlor\Database\Database; -use Froxlor\Config\ConfigParser; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; final class ConfigServices extends CliCommand { @@ -100,21 +100,68 @@ final class ConfigServices extends CliCommand return $result; } + private function importSettings(InputInterface $input, OutputInterface $output) + { + $importFile = $input->getOption('import-settings'); + + if (strtoupper(substr($importFile, 0, 4)) == 'HTTP') { + $output->writeln("Settings file seems to be an URL, trying to download"); + $target = "/tmp/froxlor-import-settings-" . time() . ".json"; + if (@file_exists($target)) { + @unlink($target); + } + $this->downloadFile($importFile, $target); + $importFile = $target; + } + if (!is_file($importFile)) { + $output->writeln('Given settings file is not a file'); + return self::INVALID; + } elseif (!file_exists($importFile)) { + $output->writeln('Given settings file cannot be found (' . $importFile . ')'); + return self::INVALID; + } elseif (!is_readable($importFile)) { + $output->writeln('Given settings file cannot be read (' . $importFile . ')'); + return self::INVALID; + } + $imp_content = file_get_contents($importFile); + SImExporter::import($imp_content); + $output->writeln("Successfully imported settings from '" . $input->getOption('import-settings') . "'"); + return self::SUCCESS; + } + + private function downloadFile($src, $dest) + { + set_time_limit(0); + // This is the file where we save the information + $fp = fopen($dest, 'w+'); + // Here is the file we are downloading, replace spaces with %20 + $ch = curl_init(str_replace(" ", "%20", $src)); + curl_setopt($ch, CURLOPT_TIMEOUT, 50); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + // write curl response to file + curl_setopt($ch, CURLOPT_FILE, $fp); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + // get curl response + curl_exec($ch); + curl_close($ch); + fclose($fp); + } + private function createConfig(InputInterface $input, OutputInterface $output, SymfonyStyle $io) { - $_daemons_config = array( + $_daemons_config = [ 'distro' => "" - ); + ]; $config_dir = Froxlor::getInstallDir() . '/lib/configfiles/'; // show list of available distro's $distros = glob($config_dir . '*.xml'); // tmp array - $distributions_select_data = array(); + $distributions_select_data = []; //set default os. - $os_dist = array('ID' => 'bullseye'); - $os_version = array('0' => '11'); + $os_dist = ['ID' => 'bullseye']; + $os_version = ['0' => '11']; $os_default = $os_dist['ID']; //read os-release @@ -190,7 +237,7 @@ final class ConfigServices extends CliCommand $daemons['x'] = 'x'; if ($si == 'system') { - $_daemons_config[$si] = array(); + $_daemons_config[$si] = []; // for the system/other services we need a multiple choice possibility $output->writeln("Select every service you need. Enter empty value when done"); $sysservice = ""; @@ -389,9 +436,9 @@ final class ConfigServices extends CliCommand // ignore invalid responses if (!is_array($nameserver_ips)) { // act like 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); } @@ -418,7 +465,7 @@ final class ConfigServices extends CliCommand Database::needSqlData(); $sql = Database::getSqlData(); - $replace_arr = array( + $replace_arr = [ '' => $sql['user'], '' => $sql['passwd'], '' => $sql['db'], @@ -439,54 +486,7 @@ final class ConfigServices extends CliCommand '' => FileDir::makeCorrectDir(Settings::Get('system.logfiles_directory')), '' => FileDir::makeCorrectDir(Settings::Get('phpfpm.fastcgi_ipcdir')), '' => Settings::Get('system.httpgroup') - ); + ]; return $replace_arr; } - - private function importSettings(InputInterface $input, OutputInterface $output) - { - $importFile = $input->getOption('import-settings'); - - if (strtoupper(substr($importFile, 0, 4)) == 'HTTP') { - $output->writeln("Settings file seems to be an URL, trying to download"); - $target = "/tmp/froxlor-import-settings-" . time() . ".json"; - if (@file_exists($target)) { - @unlink($target); - } - $this->downloadFile($importFile, $target); - $importFile = $target; - } - if (!is_file($importFile)) { - $output->writeln('Given settings file is not a file'); - return self::INVALID; - } elseif (!file_exists($importFile)) { - $output->writeln('Given settings file cannot be found (' . $importFile . ')'); - return self::INVALID; - } elseif (!is_readable($importFile)) { - $output->writeln('Given settings file cannot be read (' . $importFile . ')'); - return self::INVALID; - } - $imp_content = file_get_contents($importFile); - SImExporter::import($imp_content); - $output->writeln("Successfully imported settings from '" . $input->getOption('import-settings') . "'"); - return self::SUCCESS; - } - - private function downloadFile($src, $dest) - { - set_time_limit(0); - // This is the file where we save the information - $fp = fopen($dest, 'w+'); - // Here is the file we are downloading, replace spaces with %20 - $ch = curl_init(str_replace(" ", "%20", $src)); - curl_setopt($ch, CURLOPT_TIMEOUT, 50); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); - // write curl response to file - curl_setopt($ch, CURLOPT_FILE, $fp); - curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); - // get curl response - curl_exec($ch); - curl_close($ch); - fclose($fp); - } } diff --git a/lib/Froxlor/Cli/PhpSessionclean.php b/lib/Froxlor/Cli/PhpSessionclean.php index 5ba94ad5..9c8fbd33 100644 --- a/lib/Froxlor/Cli/PhpSessionclean.php +++ b/lib/Froxlor/Cli/PhpSessionclean.php @@ -11,27 +11,27 @@ * * 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 + * 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 - * http://files.froxlor.org/misc/COPYING.txt + * https://files.froxlor.org/misc/COPYING.txt * * @copyright the authors * @author Froxlor team - * @license http://files.froxlor.org/misc/COPYING.txt GPLv2 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ namespace Froxlor\Cli; +use Froxlor\Database\Database; +use Froxlor\FileDir; +use Froxlor\Settings; +use PDO; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Froxlor\Froxlor; -use Froxlor\FileDir; -use Froxlor\Settings; -use Froxlor\Database\Database; final class PhpSessionclean extends CliCommand { @@ -48,8 +48,8 @@ final class PhpSessionclean extends CliCommand $result = $this->validateRequirements($input, $output); if ($result == self::SUCCESS) { - if ((int) Settings::Get('phpfpm.enabled') == 1) { - if ($input->hasArgument('max-lifetime') && is_numeric($input->getArgument('max-lifetime')) && $input->getArgument('max-lifetime') > 0) { + if ((int)Settings::Get('phpfpm.enabled') == 1) { + if ($input->hasArgument('max-lifetime') && is_numeric($input->getArgument('max-lifetime')) && $input->getArgument('max-lifetime') > 0) { $this->cleanSessionfiles((int)$input->getArgument('max-lifetime')); } else { // use default max-lifetime value @@ -72,7 +72,7 @@ final class PhpSessionclean extends CliCommand // get all pool-config directories configured $sel_stmt = Database::prepare("SELECT DISTINCT `config_dir` FROM `" . TABLE_PANEL_FPMDAEMONS . "`"); Database::pexecute($sel_stmt); - while ($fpmd = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($fpmd = $sel_stmt->fetch(PDO::FETCH_ASSOC)) { $poolfiles = glob(FileDir::makeCorrectFile($fpmd['config_dir'] . '/*.conf')); foreach ($poolfiles as $cf) { $contents = file_get_contents($cf); diff --git a/lib/Froxlor/Cli/SwitchServerIp.php b/lib/Froxlor/Cli/SwitchServerIp.php index 0dd9db71..5e1100cf 100644 --- a/lib/Froxlor/Cli/SwitchServerIp.php +++ b/lib/Froxlor/Cli/SwitchServerIp.php @@ -11,25 +11,26 @@ * * 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 + * 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 - * http://files.froxlor.org/misc/COPYING.txt + * https://files.froxlor.org/misc/COPYING.txt * * @copyright the authors * @author Froxlor team - * @license http://files.froxlor.org/misc/COPYING.txt GPLv2 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ namespace Froxlor\Cli; -use Symfony\Component\Console\Input\InputOption; +use Froxlor\Database\Database; +use PDO; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -use Froxlor\Database\Database; final class SwitchServerIp extends CliCommand { @@ -56,10 +57,9 @@ final class SwitchServerIp extends CliCommand $io = new SymfonyStyle($input, $output); if ($result == self::SUCCESS && $input->getOption('list')) { - $sel_stmt = Database::prepare("SELECT * FROM panel_ipsandports ORDER BY ip ASC, port ASC"); Database::pexecute($sel_stmt); - $ips = $sel_stmt->fetchAll(\PDO::FETCH_ASSOC); + $ips = $sel_stmt->fetchAll(PDO::FETCH_ASSOC); $table_rows = []; foreach ($ips as $ipdata) { $table_rows[] = [$ipdata['id'], $ipdata['ip'], $ipdata['port']]; @@ -127,18 +127,18 @@ final class SwitchServerIp extends CliCommand foreach ($ips_to_switch as $ip_pair) { $output->writeln('Switching IP ' . $ip_pair[0] . ' to IP ' . $ip_pair[1] . ''); - $ip_check = Database::pexecute_first($check_stmt, array( + $ip_check = Database::pexecute_first($check_stmt, [ 'newip' => $ip_pair[1] - )); + ]); if ($ip_check) { $output->writeln('Note: ' . $ip_pair[0] . ' not updated to ' . $ip_pair[1] . ' - IP already exists in froxlor\'s database'); continue; } - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'newip' => $ip_pair[1], 'oldip' => $ip_pair[0] - )); + ]); $rows_updated = $upd_stmt->rowCount(); if ($rows_updated == 0) { @@ -149,9 +149,9 @@ final class SwitchServerIp extends CliCommand // check whether the system.ipaddress needs updating if ($check_sysip['value'] == $ip_pair[0]) { $upd2_stmt = Database::prepare("UPDATE `panel_settings` SET `value` = :newip WHERE `settinggroup` = 'system' and `varname` = 'ipaddress'"); - Database::pexecute($upd2_stmt, array( + Database::pexecute($upd2_stmt, [ 'newip' => $ip_pair[1] - )); + ]); $output->writeln('Updated system-ipaddress from ' . $ip_pair[0] . ' to ' . $ip_pair[1] . ''); } @@ -159,9 +159,9 @@ final class SwitchServerIp extends CliCommand if (strstr($check_mysqlip['value'], $ip_pair[0]) !== false) { $new_mysqlip = str_replace($ip_pair[0], $ip_pair[1], $check_mysqlip['value']); $upd2_stmt = Database::prepare("UPDATE `panel_settings` SET `value` = :newmysql WHERE `settinggroup` = 'system' and `varname` = 'mysql_access_host'"); - Database::pexecute($upd2_stmt, array( + Database::pexecute($upd2_stmt, [ 'newmysql' => $new_mysqlip - )); + ]); $output->writeln('Updated mysql_access_host from ' . $check_mysqlip['value'] . ' to ' . $new_mysqlip . ''); } @@ -169,9 +169,9 @@ final class SwitchServerIp extends CliCommand if (strstr($check_axfrip['value'], $ip_pair[0]) !== false) { $new_axfrip = str_replace($ip_pair[0], $ip_pair[1], $check_axfrip['value']); $upd2_stmt = Database::prepare("UPDATE `panel_settings` SET `value` = :newaxfr WHERE `settinggroup` = 'system' and `varname` = 'axfrservers'"); - Database::pexecute($upd2_stmt, array( + Database::pexecute($upd2_stmt, [ 'newaxfr' => $new_axfrip - )); + ]); $output->writeln('Updated axfr-servers from ' . $check_axfrip['value'] . ' to ' . $new_axfrip . ''); } } diff --git a/lib/Froxlor/Config/ConfigDaemon.php b/lib/Froxlor/Config/ConfigDaemon.php index 1172519e..e31479e6 100644 --- a/lib/Froxlor/Config/ConfigDaemon.php +++ b/lib/Froxlor/Config/ConfigDaemon.php @@ -1,91 +1,90 @@ - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes - * - * @since 0.9.34 + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ +namespace Froxlor\Config; + +use Exception; +use Froxlor\Froxlor; +use Froxlor\Settings; +use SimpleXMLElement; + /** * Class ConfigDaemon * * Parses a distributions XML - file and gives access to the configuration * Not to be used directly - * - * @copyright (c) the authors - * @author Florian Aders - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes */ class ConfigDaemon { - /** - * Holding the commands for this daemon - * - * @var array - */ - private $orders = array(); - - /** - * Store the parsed SimpleXMLElement for usage - * - * @var \SimpleXMLElement - */ - private $fullxml; - - /** - * Memorize if we already parsed the XML - * - * @var bool - */ - private $isparsed = false; - - /** - * Sub - area of the full - XML only holding the daemon - data we are interested in - * - * @var \SimpleXMLElement - */ - private $daemon; - - /** - * xpath leading to this daemon in the full XML - * - * @var string - */ - private $xpath; - - /** - * cache of sql-data if used - */ - private $sqldata_cache = null; - /** * Human - readable title of this service * * @var string */ public $title; - /** * Whether this is the default daemon of the service-category * * @var boolean */ public $default; + /** + * Holding the commands for this daemon + * + * @var array + */ + private $orders = []; + /** + * Store the parsed SimpleXMLElement for usage + * + * @var SimpleXMLElement + */ + private $fullxml; + /** + * Memorize if we already parsed the XML + * + * @var bool + */ + private $isparsed = false; + /** + * Sub - area of the full - XML only holding the daemon - data we are interested in + * + * @var SimpleXMLElement + */ + private $daemon; + /** + * xpath leading to this daemon in the full XML + * + * @var string + */ + private $xpath; + /** + * cache of sql-data if used + */ + private $sqldata_cache = null; public function __construct($xml, $xpath) { @@ -94,13 +93,76 @@ class ConfigDaemon $this->daemon = $this->fullxml->xpath($this->xpath); $attributes = $this->daemon[0]->attributes(); if ($attributes['title'] != '') { - $this->title = $this->parseContent((string) $attributes['title']); + $this->title = $this->parseContent((string)$attributes['title']); } if (isset($attributes['default'])) { $this->default = ($attributes['default'] == true); } } + /** + * Replace placeholders with content + * + * @param string $content + * @return string $content w/o placeholder + */ + private function parseContent($content) + { + $content = preg_replace_callback('/\{\{(.*)\}\}/Ui', function ($matches) { + $match = null; + if (preg_match('/^settings\.(.*)$/', $matches[1], $match)) { + return Settings::Get($match[1]); + } elseif (preg_match('/^lng\.(.*)(?:\.(.*)(?:\.(.*)))$/U', $matches[1], $match)) { + global $lng; + if (isset($match[1]) && $match[1] != '' && isset($match[2]) && $match[2] != '' && isset($match[3]) && $match[3] != '') { + return $lng[$match[1]][$match[2]][$match[3]]; + } elseif (isset($match[1]) && $match[1] != '' && isset($match[2]) && $match[2] != '') { + return $lng[$match[1]][$match[2]]; + } elseif (isset($match[1]) && $match[1] != '') { + return $lng[$match[1]]; + } + return ''; + } elseif (preg_match('/^const\.(.*)$/', $matches[1], $match)) { + return $this->returnDynamic($match[1]); + } elseif (preg_match('/^sql\.(.*)$/', $matches[1], $match)) { + if (is_null($this->sqldata_cache)) { + // read in sql-data (if exists) + if (file_exists(Froxlor::getInstallDir() . "/lib/userdata.inc.php")) { + require Froxlor::getInstallDir() . "/lib/userdata.inc.php"; + unset($sql_root); + $this->sqldata_cache = $sql; + } + } + return isset($this->sqldata_cache[$match[1]]) ? $this->sqldata_cache[$match[1]] : ''; + } + }, $content); + return $content; + } + + private function returnDynamic($key = null) + { + $dynamics = [ + 'install_dir' => Froxlor::getInstallDir() + ]; + return $dynamics[$key] ?? ''; + } + + /** + * Get config for this daemon + * + * The returned array will be an array of array, each sub-array looking like this: + * array('type' => 'install|file|command', 'content' => '') + * If the type is "file", an additional "name" - element will be added to the array + * To configure a daemon, the steps in the array must be followed in order + * + * @return array + */ + public function getConfig() + { + $this->parse(); + return $this->orders; + } + /** * Parse the XML and populate $this->orders * @@ -113,10 +175,10 @@ class ConfigDaemon return true; } - $preparsed = array(); + $preparsed = []; // First: let's push everything into an array and expand all includes foreach ($this->daemon[0]->children() as $order) { - switch ((string) $order->getName()) { + switch ((string)$order->getName()) { case "install": case "file": case "command": @@ -125,10 +187,10 @@ class ConfigDaemon break; case "include": // Includes, get the part we want via xpath - $includes = $this->fullxml->xpath((string) $order); + $includes = $this->fullxml->xpath((string)$order); foreach ($includes[0] as $include) { // The "include" is also a child, so just skip it, would make a mess later - if ((string) $include->getName() == 'include') { + if ((string)$include->getName() == 'include') { continue; } $preparsed[] = $include; @@ -141,7 +203,7 @@ class ConfigDaemon // Hold the results $visibility = 1; foreach ($order->children() as $child) { - switch ((string) $child->getName()) { + switch ((string)$child->getName()) { case "visibility": $visibility += $this->checkVisibility($child); break; @@ -154,10 +216,10 @@ class ConfigDaemon break; case "include": // Includes, get the part we want via xpath - $includes = $this->fullxml->xpath((string) $child); + $includes = $this->fullxml->xpath((string)$child); foreach ($includes[0] as $include) { // The "include" is also a child, so just skip it, would make a mess later - if ((string) $include->getName() == 'include') { + if ((string)$include->getName() == 'include') { continue; } $preparsed[] = $include; @@ -189,37 +251,108 @@ class ConfigDaemon } /** - * Get config for this daemon + * Check if visibility should be changed * - * The returned array will be an array of array, each sub-array looking like this: - * array('type' => 'install|file|command', 'content' => '') - * If the type is "file", an additional "name" - element will be added to the array - * To configure a daemon, the steps in the array must be followed in order - * - * @return array + * @param SimpleXMLElement $order + * @return int 0|-1 */ - public function getConfig() + private function checkVisibility($order) { - $this->parse(); - return $this->orders; + $attributes = []; + foreach ($order->attributes() as $key => $value) { + $attributes[(string)$key] = $this->parseContent(trim((string)$value)); + } + + $order = $this->parseContent(trim((string)$order)); + if (!array_key_exists('mode', $attributes)) { + throw new Exception('"' . $order . '" is missing mode'); + } + + $return = 0; + switch ($attributes['mode']) { + case "isfile": + if (!is_file($order)) { + $return = -1; + } + break; + case "notisfile": + if (is_file($order)) { + $return = -1; + } + break; + case "isdir": + if (!is_dir($order)) { + $return = -1; + } + break; + case "notisdir": + if (is_dir($order)) { + $return = -1; + } + break; + case "false": + if ($order == true) { + $return = -1; + } + break; + case "true": + if ($order == false) { + $return = -1; + } + break; + case "notempty": + if ($order == "") { + $return = -1; + } + break; + case "userexists": + if (posix_getpwuid($order) === false) { + $return = -1; + } + break; + case "groupexists": + if (posix_getgrgid($order) === false) { + $return = -1; + } + break; + case "usernotexists": + if (is_array(posix_getpwuid($order))) { + $return = -1; + } + break; + case "groupnotexists": + if (is_array(posix_getgrgid($order))) { + $return = -1; + } + break; + case "usernamenotexists": + if (is_array(posix_getpwnam($order))) { + $return = -1; + } + break; + case "equals": + $return = (isset($attributes['value']) && $attributes['value'] == $order ? 0 : -1); + break; + } + return $return; } /** * Parse a single order and return it in a format for easier usage * * @param - * SimpleXMLElement object holding a single order from the distribution - XML + * SimpleXMLElement object holding a single order from the distribution - XML * @return array|string */ private function parseOrder($order) { - $attributes = array(); + $attributes = []; foreach ($order->attributes() as $key => $value) { - $attributes[(string) $key] = (string) $value; + $attributes[(string)$key] = (string)$value; } $parsedorder = ''; - switch ((string) $order->getName()) { + switch ((string)$order->getName()) { case "file": $parsedorder = $this->parseFile($order, $attributes); break; @@ -230,99 +363,17 @@ class ConfigDaemon $parsedorder = $this->parseInstall($order, $attributes); break; default: - throw new \Exception('Invalid order: ' . (string) $order->getName()); + throw new Exception('Invalid order: ' . (string)$order->getName()); } return $parsedorder; } - /** - * Parse a install - order and return it in a format for easier usage - * - * @param - * SimpleXMLElement object holding a single install from the distribution - XML - * @return array|string - */ - private function parseInstall($order, $attributes) - { - // No sub - elements, so the content can be returned directly - if ($order->count() == 0) { - return array( - 'type' => 'install', - 'content' => $this->parseContent(trim((string) $order)) - ); - } - - // Hold the results - $visibility = 1; - $content = ''; - foreach ($order->children() as $child) { - switch ((string) $child->getName()) { - case "visibility": - $visibility += $this->checkVisibility($child); - break; - case "content": - $content = trim((string) $child); - break; - } - } - - if ($visibility > 0) { - return array( - 'type' => 'install', - 'content' => $this->parseContent($content) - ); - } else { - return ''; - } - } - - /** - * Parse a command - order and return it in a format for easier usage - * - * @param - * SimpleXMLElement object holding a single command from the distribution - XML - * @return array|string - */ - private function parseCommand($order, $attributes) - { - // No sub - elements, so the content can be returned directly - if ($order->count() == 0) { - return array( - 'type' => 'command', - 'content' => $this->parseContent(trim((string) $order)) - ); - } - - // Hold the results - $visibility = 1; - $content = ''; - foreach ($order->children() as $child) { - switch ((string) $child->getName()) { - case "visibility": - $visibility += $this->checkVisibility($child); - break; - case "content": - $content = trim((string) $child); - break; - } - } - - if ($visibility > 0) { - return array( - 'type' => 'command', - 'content' => $this->parseContent($content) - ); - } else { - return ''; - } - } - /** * Parse a file - order and return it in a format for easier usage * * @param - * SimpleXMLElement object holding a single file from the distribution - XML + * SimpleXMLElement object holding a single file from the distribution - XML * @return array|string */ private function parseFile($order, $attributes) @@ -330,22 +381,22 @@ class ConfigDaemon $visibility = 1; // No sub - elements, so the content can be returned directly if ($order->count() == 0) { - $content = (string) $order; + $content = (string)$order; } else { // Hold the results foreach ($order->children() as $child) { - switch ((string) $child->getName()) { + switch ((string)$child->getName()) { case "visibility": $visibility += $this->checkVisibility($child); break; case "content": - $content = (string) $child; + $content = (string)$child; break; } } } - $return = array(); + $return = []; // Check if the original file should be backupped // @TODO: Maybe have a backup - location somewhere central? // @TODO: Use IO - class @@ -355,54 +406,54 @@ class ConfigDaemon } else { $cmd = 'mv'; } - $return[] = array( + $return[] = [ 'type' => 'command', 'content' => $cmd . ' "' . $this->parseContent($attributes['name']) . '" "' . $this->parseContent($attributes['name']) . '.frx.bak"', 'execute' => "pre" - ); + ]; } // Now the content of the file can be written if (isset($attributes['mode'])) { - $return[] = array( + $return[] = [ 'type' => 'file', 'content' => $this->parseContent($content), 'name' => $this->parseContent($attributes['name']), 'mode' => $this->parseContent($attributes['mode']) - ); + ]; } else { - $return[] = array( + $return[] = [ 'type' => 'file', 'content' => $this->parseContent($content), 'name' => $this->parseContent($attributes['name']) - ); + ]; } // Let's check if the mode of the file should be changed if (array_key_exists('chmod', $attributes)) { - $return[] = array( + $return[] = [ 'type' => 'command', 'content' => 'chmod ' . $attributes['chmod'] . ' "' . $this->parseContent($attributes['name']) . '"', 'execute' => "post" - ); + ]; } // Let's check if the owner of the file should be changed if (array_key_exists('chown', $attributes)) { - $return[] = array( + $return[] = [ 'type' => 'command', 'content' => 'chown ' . $attributes['chown'] . ' "' . $this->parseContent($attributes['name']) . '"', 'execute' => "post" - ); + ]; } // If we have more than 1 element, we want to group this stuff for easier processing later if (count($return) > 1) { - $return = array( + $return = [ 'type' => 'file', 'subcommands' => $return, 'name' => $this->parseContent($attributes['name']) - ); + ]; } if ($visibility > 0) { @@ -413,148 +464,84 @@ class ConfigDaemon } /** - * Replace placeholders with content + * Parse a command - order and return it in a format for easier usage * - * @param string $content - * @return string $content w/o placeholder + * @param + * SimpleXMLElement object holding a single command from the distribution - XML + * @return array|string */ - private function parseContent($content) + private function parseCommand($order, $attributes) { - $content = preg_replace_callback('/\{\{(.*)\}\}/Ui', function ($matches) { - $match = null; - if (preg_match('/^settings\.(.*)$/', $matches[1], $match)) { - return \Froxlor\Settings::Get($match[1]); - } elseif (preg_match('/^lng\.(.*)(?:\.(.*)(?:\.(.*)))$/U', $matches[1], $match)) { - global $lng; - if (isset($match[1]) && $match[1] != '' && isset($match[2]) && $match[2] != '' && isset($match[3]) && $match[3] != '') { - return $lng[$match[1]][$match[2]][$match[3]]; - } elseif (isset($match[1]) && $match[1] != '' && isset($match[2]) && $match[2] != '') { - return $lng[$match[1]][$match[2]]; - } elseif (isset($match[1]) && $match[1] != '') { - return $lng[$match[1]]; - } - return ''; - } elseif (preg_match('/^const\.(.*)$/', $matches[1], $match)) { - return $this->returnDynamic($match[1]); - } elseif (preg_match('/^sql\.(.*)$/', $matches[1], $match)) { - if (is_null($this->sqldata_cache)) { - // read in sql-data (if exists) - if (file_exists(\Froxlor\Froxlor::getInstallDir() . "/lib/userdata.inc.php")) { - require \Froxlor\Froxlor::getInstallDir() . "/lib/userdata.inc.php"; - unset($sql_root); - $this->sqldata_cache = $sql; - } - } - return isset($this->sqldata_cache[$match[1]]) ? $this->sqldata_cache[$match[1]] : ''; - } - }, $content); - return $content; - } + // No sub - elements, so the content can be returned directly + if ($order->count() == 0) { + return [ + 'type' => 'command', + 'content' => $this->parseContent(trim((string)$order)) + ]; + } - private function returnDynamic($key = null) - { - $dynamics = [ - 'install_dir' => \Froxlor\Froxlor::getInstallDir() - ]; - return $dynamics[$key] ?? ''; + // Hold the results + $visibility = 1; + $content = ''; + foreach ($order->children() as $child) { + switch ((string)$child->getName()) { + case "visibility": + $visibility += $this->checkVisibility($child); + break; + case "content": + $content = trim((string)$child); + break; + } + } + + if ($visibility > 0) { + return [ + 'type' => 'command', + 'content' => $this->parseContent($content) + ]; + } else { + return ''; + } } /** - * Check if visibility should be changed + * Parse a install - order and return it in a format for easier usage * - * @param \SimpleXMLElement $order - * @return int 0|-1 + * @param + * SimpleXMLElement object holding a single install from the distribution - XML + * @return array|string */ - private function checkVisibility($order) + private function parseInstall($order, $attributes) { - $attributes = array(); - foreach ($order->attributes() as $key => $value) { - $attributes[(string) $key] = $this->parseContent(trim((string) $value)); + // No sub - elements, so the content can be returned directly + if ($order->count() == 0) { + return [ + 'type' => 'install', + 'content' => $this->parseContent(trim((string)$order)) + ]; } - $order = $this->parseContent(trim((string) $order)); - if (! array_key_exists('mode', $attributes)) { - throw new \Exception('"' . $order . '" is missing mode'); + // Hold the results + $visibility = 1; + $content = ''; + foreach ($order->children() as $child) { + switch ((string)$child->getName()) { + case "visibility": + $visibility += $this->checkVisibility($child); + break; + case "content": + $content = trim((string)$child); + break; + } } - $return = 0; - switch ($attributes['mode']) { - case "isfile": - if (! is_file($order)) { - $return = - 1; - } - ; - break; - case "notisfile": - if (is_file($order)) { - $return = - 1; - } - ; - break; - case "isdir": - if (! is_dir($order)) { - $return = - 1; - } - ; - break; - case "notisdir": - if (is_dir($order)) { - $return = - 1; - } - ; - break; - case "false": - if ($order == true) { - $return = - 1; - } - ; - break; - case "true": - if ($order == false) { - $return = - 1; - } - ; - break; - case "notempty": - if ($order == "") { - $return = - 1; - } - ; - break; - case "userexists": - if (posix_getpwuid($order) === false) { - $return = - 1; - } - ; - break; - case "groupexists": - if (posix_getgrgid($order) === false) { - $return = - 1; - } - ; - break; - case "usernotexists": - if (is_array(posix_getpwuid($order))) { - $return = - 1; - } - ; - break; - case "groupnotexists": - if (is_array(posix_getgrgid($order))) { - $return = - 1; - } - ; - break; - case "usernamenotexists": - if (is_array(posix_getpwnam($order))) { - $return = - 1; - } - ; - break; - case "equals": - $return = (isset($attributes['value']) && $attributes['value'] == $order ? 0 : - 1); - break; + if ($visibility > 0) { + return [ + 'type' => 'install', + 'content' => $this->parseContent($content) + ]; + } else { + return ''; } - return $return; } } diff --git a/lib/Froxlor/Config/ConfigDisplay.php b/lib/Froxlor/Config/ConfigDisplay.php index cb6dd1eb..2ca6862e 100644 --- a/lib/Froxlor/Config/ConfigDisplay.php +++ b/lib/Froxlor/Config/ConfigDisplay.php @@ -1,28 +1,37 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Config + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\Config; + +use Froxlor\Database\Database; +use Froxlor\FileDir; +use Froxlor\Froxlor; +use Froxlor\PhpHelper; +use Froxlor\Settings; +use Froxlor\UI\Panel\UI; + class ConfigDisplay { /** @@ -74,9 +83,9 @@ class ConfigDisplay // ignore invalid responses 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); } @@ -103,7 +112,7 @@ class ConfigDisplay Database::needSqlData(true); $sql = Database::getSqlData(); - self::$replace_arr = array( + self::$replace_arr = [ '' => $sql['user'], '' => 'FROXLOR_MYSQL_PASSWORD', '' => $sql['db'], @@ -124,7 +133,7 @@ class ConfigDisplay '' => FileDir::makeCorrectDir(Settings::Get('system.logfiles_directory')), '' => FileDir::makeCorrectDir(Settings::Get('phpfpm.fastcgi_ipcdir')), '' => Settings::Get('system.httpgroup') - ); + ]; $commands_pre = ""; $commands_file = ""; @@ -139,7 +148,10 @@ class ConfigDisplay if ($lasttype != '' && $lasttype != $_action['type']) { $commands = trim($commands); $numbrows = count(explode("\n", $commands)); - $configpage .= UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', ['commands' => $commands, 'numbrows' => $numbrows]); + $configpage .= UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', [ + 'commands' => $commands, + 'numbrows' => $numbrows + ]); $lasttype = ''; $commands = ''; } @@ -170,12 +182,18 @@ class ConfigDisplay $commands = trim($commands_pre); if ($commands != "") { $numbrows = count(explode("\n", $commands)); - $commands_pre = UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', ['commands' => $commands, 'numbrows' => $numbrows]); + $commands_pre = UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', [ + 'commands' => $commands, + 'numbrows' => $numbrows + ]); } $commands = trim($commands_post); if ($commands != "") { $numbrows = count(explode("\n", $commands)); - $commands_post = UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', ['commands' => $commands, 'numbrows' => $numbrows]); + $commands_post = UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', [ + 'commands' => $commands, + 'numbrows' => $numbrows + ]); } $configpage .= UI::twig()->render(self::$theme . '/settings/conf/fileblock.html.twig', [ 'realname' => $realname, @@ -192,7 +210,10 @@ class ConfigDisplay $commands = trim($commands); if ($commands != '') { $numbrows = count(explode("\n", $commands)); - $configpage .= UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', ['commands' => $commands, 'numbrows' => $numbrows]); + $configpage .= UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', [ + 'commands' => $commands, + 'numbrows' => $numbrows + ]); } return $configpage; } diff --git a/lib/Froxlor/Config/ConfigParser.php b/lib/Froxlor/Config/ConfigParser.php index 20f624cc..874b1053 100644 --- a/lib/Froxlor/Config/ConfigParser.php +++ b/lib/Froxlor/Config/ConfigParser.php @@ -1,59 +1,89 @@ - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes - * - * @since 0.9.34 + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ +namespace Froxlor\Config; + +use Exception; +use SimpleXMLElement; + /** * Class ConfigParser * * Parses a distributions XML - file and gives access to the configuration - * - * @copyright (c) the authors - * @author Florian Aders - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes */ class ConfigParser { + /** + * Name of the distribution this configuration is for + * + * @var string + */ + public $distributionName = ''; + /** + * Codename of the distribution this configuration is for + * + * @var string + */ + public $distributionCodename = ''; + /** + * Version of the distribution this configuration is for + * + * @var string + */ + public $distributionVersion = ''; + /** + * Recommended editor + * + * @var string + */ + public $distributionEditor = '/bin/nano'; + /** + * Show if this configuration is deprecated + * + * @var bool + */ + public $deprecated = false; /** * Holding the available services in the XML * * @var array */ - private $services = array(); - + private $services = []; /** * Holding the available defaults in the XML * * @var array */ - private $defaults = array(); - + private $defaults = []; /** * Store the parsed SimpleXMLElement for usage * - * @var \SimpleXMLElement + * @var SimpleXMLElement */ private $xml; - /** * Memorize if we already parsed the XML * @@ -61,54 +91,19 @@ class ConfigParser */ private $isparsed = false; - /** - * Name of the distribution this configuration is for - * - * @var string - */ - public $distributionName = ''; - - /** - * Codename of the distribution this configuration is for - * - * @var string - */ - public $distributionCodename = ''; - - /** - * Version of the distribution this configuration is for - * - * @var string - */ - public $distributionVersion = ''; - - /** - * Recommended editor - * - * @var string - */ - public $distributionEditor = '/bin/nano'; - - /** - * Show if this configuration is deprecated - * - * @var bool - */ - public $deprecated = false; - /** * Constructor * * Initialize the XML - ConfigParser * * @param string $filename - * filename of the froxlor - configurationfile + * filename of the froxlor - configurationfile * @return void */ public function __construct($filename) { if (!is_readable($filename)) { - throw new \Exception('File not readable'); + throw new Exception('File not readable'); } $this->xml = simplexml_load_file($filename); @@ -117,7 +112,7 @@ class ConfigParser foreach (libxml_get_errors() as $error) { $error .= "\t" . $error->message; } - throw new \Exception($error); + throw new Exception($error); } // Let's see if we can find a block in the XML @@ -125,31 +120,47 @@ class ConfigParser // No distribution found - can't use this file if (!is_array($distribution)) { - throw new \Exception('Invalid XML, no distribution found'); + throw new Exception('Invalid XML, no distribution found'); } // Search for attributes we understand foreach ($distribution[0]->attributes() as $key => $value) { - switch ((string) $key) { + switch ((string)$key) { case "name": - $this->distributionName = (string) $value; + $this->distributionName = (string)$value; break; case "version": - $this->distributionVersion = (string) $value; + $this->distributionVersion = (string)$value; break; case "codename": - $this->distributionCodename = (string) $value; + $this->distributionCodename = (string)$value; break; case "defaulteditor": - $this->distributionEditor = (string) $value; + $this->distributionEditor = (string)$value; break; case "deprecated": - (string) $value == 'true' ? $this->deprecated = true : $this->deprecated = false; + (string)$value == 'true' ? $this->deprecated = true : $this->deprecated = false; break; } } } + /** + * Return all services defined by the XML + * + * The array will hold ConfigService - Objects for further handling + * + * @return array + */ + public function getServices() + { + // Let's parse this shit(!) + $this->parseServices(); + + // Return our carefully searched for services + return $this->services; + } + /** * Parse the XML and populate $this->services * @@ -172,7 +183,7 @@ class ConfigParser // Search the attributes for "type" foreach ($service->attributes() as $key => $value) { if ($key == 'type') { - $this->services[(string) $value] = new ConfigService($this->xml, '//services/service[@type="' . (string) $value . '"]'); + $this->services[(string)$value] = new ConfigService($this->xml, '//services/service[@type="' . (string)$value . '"]'); } } } @@ -182,6 +193,22 @@ class ConfigParser return true; } + /** + * Return all defaults defined by the XML + * + * The array will hold ConfigDefaults - Objects for further handling + * + * @return array + */ + public function getDefaults() + { + // Let's parse this shit(!) + $this->parseDefaults(); + + // Return our carefully searched for defaults + return $this->defaults; + } + /** * Parse the XML and populate $this->services * @@ -205,38 +232,6 @@ class ConfigParser return true; } - /** - * Return all services defined by the XML - * - * The array will hold ConfigService - Objects for further handling - * - * @return array - */ - public function getServices() - { - // Let's parse this shit(!) - $this->parseServices(); - - // Return our carefully searched for services - return $this->services; - } - - /** - * Return all defaults defined by the XML - * - * The array will hold ConfigDefaults - Objects for further handling - * - * @return array - */ - public function getDefaults() - { - // Let's parse this shit(!) - $this->parseDefaults(); - - // Return our carefully searched for defaults - return $this->defaults; - } - /** * return complete distribution string "Name [codename] [ (version)] [deprecated] * diff --git a/lib/Froxlor/Config/ConfigService.php b/lib/Froxlor/Config/ConfigService.php index 9b44993d..157c4250 100644 --- a/lib/Froxlor/Config/ConfigService.php +++ b/lib/Froxlor/Config/ConfigService.php @@ -1,72 +1,73 @@ - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes - * - * @since 0.9.34 + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ +namespace Froxlor\Config; + +use Exception; +use Froxlor\Settings; +use SimpleXMLElement; + /** * Class ConfigService * * Parses a distributions XML - file and gives access to the services within * Not to be used directly - * - * @copyright (c) the authors - * @author Florian Aders - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes */ class ConfigService { - /** - * Holding the available daemons in this service - * - * @var array - */ - private $daemons = array(); - - /** - * Store the parsed SimpleXMLElement for usage - * - * @var \SimpleXMLElement - */ - private $fullxml; - - /** - * Memorize if we already parsed the XML - * - * @var bool - */ - private $isparsed = false; - - /** - * xpath leading to this service in the full XML - * - * @var string - */ - private $xpath; - /** * Human - readable title of this service * * @var string */ public $title; + /** + * Holding the available daemons in this service + * + * @var array + */ + private $daemons = []; + /** + * Store the parsed SimpleXMLElement for usage + * + * @var SimpleXMLElement + */ + private $fullxml; + /** + * Memorize if we already parsed the XML + * + * @var bool + */ + private $isparsed = false; + /** + * xpath leading to this service in the full XML + * + * @var string + */ + private $xpath; public function __construct($xml, $xpath) { @@ -75,10 +76,43 @@ class ConfigService $service = $this->fullxml->xpath($this->xpath); $attributes = $service[0]->attributes(); if ($attributes['title'] != '') { - $this->title = $this->parseContent((string) $attributes['title']); + $this->title = $this->parseContent((string)$attributes['title']); } } + /** + * Replace placeholders with content + * + * @param string $content + * @return string $content w/o placeholder + */ + private function parseContent($content) + { + $content = preg_replace_callback('/\{\{(.*)\}\}/Ui', function ($matches) { + $match = null; + if (preg_match('/^settings\.(.*)$/', $matches[1], $match)) { + return Settings::Get($match[1]); + } elseif (preg_match('/^lng\.(.*)(?:\.(.*)(?:\.(.*)))$/U', $matches[1], $match)) { + global $lng; + if (isset($match[1]) && $match[1] != '' && isset($match[2]) && $match[2] != '' && isset($match[3]) && $match[3] != '') { + return $lng[$match[1]][$match[2]][$match[3]]; + } elseif (isset($match[1]) && $match[1] != '' && isset($match[2]) && $match[2] != '') { + return $lng[$match[1]][$match[2]]; + } elseif (isset($match[1]) && $match[1] != '') { + return $lng[$match[1]]; + } + return ''; + } + }, $content); + return $content; + } + + public function getDaemons() + { + $this->parse(); + return $this->daemons; + } + /** * Parse the XML and populate $this->daemons * @@ -101,10 +135,10 @@ class ConfigService $versiontag = ''; foreach ($daemon->attributes() as $key => $value) { if ($key == 'name' && $name == '') { - $name = (string) $value; + $name = (string)$value; $nametag = "[@name='" . $value . "']"; } elseif ($key == 'name' && $name != '') { - $name = (string) $value . '_' . $name; + $name = (string)$value . '_' . $name; $nametag = "[@name='" . $value . "']"; } elseif ($key == 'version' && $name == '') { $name = str_replace('.', '', $value); @@ -115,7 +149,7 @@ class ConfigService } } if ($name == '') { - throw new \Exception('No name attribute for daemon'); + throw new Exception('No name attribute for daemon'); } $this->daemons[$name] = new ConfigDaemon($this->fullxml, $this->xpath . "/daemon" . $nametag . $versiontag); } @@ -124,37 +158,4 @@ class ConfigService $this->isparsed = true; return true; } - - /** - * Replace placeholders with content - * - * @param string $content - * @return string $content w/o placeholder - */ - private function parseContent($content) - { - $content = preg_replace_callback('/\{\{(.*)\}\}/Ui', function ($matches) { - $match = null; - if (preg_match('/^settings\.(.*)$/', $matches[1], $match)) { - return \Froxlor\Settings::Get($match[1]); - } elseif (preg_match('/^lng\.(.*)(?:\.(.*)(?:\.(.*)))$/U', $matches[1], $match)) { - global $lng; - if (isset($match[1]) && $match[1] != '' && isset($match[2]) && $match[2] != '' && isset($match[3]) && $match[3] != '') { - return $lng[$match[1]][$match[2]][$match[3]]; - } elseif (isset($match[1]) && $match[1] != '' && isset($match[2]) && $match[2] != '') { - return $lng[$match[1]][$match[2]]; - } elseif (isset($match[1]) && $match[1] != '') { - return $lng[$match[1]]; - } - return ''; - } - }, $content); - return $content; - } - - public function getDaemons() - { - $this->parse(); - return $this->daemons; - } } diff --git a/lib/Froxlor/Cron/CronConfig.php b/lib/Froxlor/Cron/CronConfig.php index 259c869e..1f7ff2d1 100644 --- a/lib/Froxlor/Cron/CronConfig.php +++ b/lib/Froxlor/Cron/CronConfig.php @@ -1,27 +1,35 @@ - * @author Froxlor team (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 + * @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; } diff --git a/lib/Froxlor/Cron/Dns/Bind.php b/lib/Froxlor/Cron/Dns/Bind.php index 2c2ae9f9..939796d7 100644 --- a/lib/Froxlor/Cron/Dns/Bind.php +++ b/lib/Froxlor/Cron/Dns/Bind.php @@ -1,22 +1,38 @@ (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 + * @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()))); - } - } - } - } } diff --git a/lib/Froxlor/Cron/Dns/DnsBase.php b/lib/Froxlor/Cron/Dns/DnsBase.php index e3b1c9f2..5c9eb018 100644 --- a/lib/Froxlor/Cron/Dns/DnsBase.php +++ b/lib/Froxlor/Cron/Dns/DnsBase.php @@ -1,24 +1,37 @@ (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 + * @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'); - } - } } diff --git a/lib/Froxlor/Cron/Dns/PowerDNS.php b/lib/Froxlor/Cron/Dns/PowerDNS.php index e992e721..c3d8f20b 100644 --- a/lib/Froxlor/Cron/Dns/PowerDNS.php +++ b/lib/Froxlor/Cron/Dns/PowerDNS.php @@ -1,29 +1,43 @@ (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 + * @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 diff --git a/lib/Froxlor/Cron/FroxlorCron.php b/lib/Froxlor/Cron/FroxlorCron.php index 3433d23e..3ac2ab0a 100644 --- a/lib/Froxlor/Cron/FroxlorCron.php +++ b/lib/Froxlor/Cron/FroxlorCron.php @@ -1,32 +1,38 @@ - * @author Froxlor team (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 + * @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; diff --git a/lib/Froxlor/Cron/Http/Apache.php b/lib/Froxlor/Cron/Http/Apache.php index d194c659..0777ee71 100644 --- a/lib/Froxlor/Cron/Http/Apache.php +++ b/lib/Froxlor/Cron/Http/Apache.php @@ -1,41 +1,62 @@ (2003-2009) - * @author Froxlor team (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 + * @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\Domain\Domain; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; +use Froxlor\Http\Directory; +use Froxlor\Http\Statistics; +use Froxlor\PhpHelper; +use Froxlor\Settings; +use Froxlor\Validate\Validate; +use PDO; + +/** + * @author Florian Lippert (2003-2009) + * @author Froxlor team (2010-) */ class Apache extends HttpConfigBase { // protected - protected $known_vhostfilenames = array(); + protected $known_vhostfilenames = []; - protected $known_diroptionsfilenames = array(); + protected $known_diroptionsfilenames = []; - protected $known_htpasswdsfilenames = array(); + protected $known_htpasswdsfilenames = []; - protected $virtualhosts_data = array(); + protected $virtualhosts_data = []; - protected $diroptions_data = array(); + protected $diroptions_data = []; - protected $htpasswds_data = array(); + protected $htpasswds_data = []; /** * indicator whether a customer is deactivated or not @@ -45,126 +66,40 @@ class Apache extends HttpConfigBase */ private $deactivated = false; - /** - * define a standard -statement, bug #32 - */ - private function createStandardDirectoryEntry() - { - $vhosts_folder = ''; - if (is_dir(Settings::Get('system.apacheconf_vhost'))) { - $vhosts_folder = \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')); - } else { - $vhosts_folder = \Froxlor\FileDir::makeCorrectDir(dirname(Settings::Get('system.apacheconf_vhost'))); - } - $vhosts_filename = \Froxlor\FileDir::makeCorrectFile($vhosts_folder . '/05_froxlor_dirfix_nofcgid.conf'); - - if (! isset($this->virtualhosts_data[$vhosts_filename])) { - $this->virtualhosts_data[$vhosts_filename] = ''; - } - - $this->virtualhosts_data[$vhosts_filename] .= ' ' . "\n"; - - // check for custom values, see #1638 - $custom_opts = Settings::Get('system.apacheglobaldiropt'); - if (! empty($custom_opts)) { - $this->virtualhosts_data[$vhosts_filename] .= $custom_opts . "\n"; - } else { - // >=apache-2.4 enabled? - if (Settings::Get('system.apache24') == '1') { - $this->virtualhosts_data[$vhosts_filename] .= ' Require all granted' . "\n"; - $this->virtualhosts_data[$vhosts_filename] .= ' AllowOverride All' . "\n"; - } else { - $this->virtualhosts_data[$vhosts_filename] .= ' Order allow,deny' . "\n"; - $this->virtualhosts_data[$vhosts_filename] .= ' allow from all' . "\n"; - } - } - $this->virtualhosts_data[$vhosts_filename] .= ' ' . "\n"; - - $ocsp_cache_filename = \Froxlor\FileDir::makeCorrectFile($vhosts_folder . '/03_froxlor_ocsp_cache.conf'); - if (Settings::Get('system.use_ssl') == '1' && Settings::Get('system.apache24') == 1) { - $this->virtualhosts_data[$ocsp_cache_filename] = 'SSLStaplingCache ' . Settings::Get('system.apache24_ocsp_cache_path') . "\n"; - } else { - if (file_exists($ocsp_cache_filename)) { - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'apache::_createStandardDirectoryEntry: unlinking ' . basename($ocsp_cache_filename)); - unlink(\Froxlor\FileDir::makeCorrectFile($ocsp_cache_filename)); - } - } - } - - /** - * define a default ErrorDocument-statement, bug #unknown-yet - */ - private function createStandardErrorHandler() - { - if (Settings::Get('defaultwebsrverrhandler.enabled') == '1' && (Settings::Get('defaultwebsrverrhandler.err401') != '' || Settings::Get('defaultwebsrverrhandler.err403') != '' || Settings::Get('defaultwebsrverrhandler.err404') != '' || Settings::Get('defaultwebsrverrhandler.err500') != '')) { - $vhosts_folder = ''; - if (is_dir(Settings::Get('system.apacheconf_vhost'))) { - $vhosts_folder = \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')); - } else { - $vhosts_folder = \Froxlor\FileDir::makeCorrectDir(dirname(Settings::Get('system.apacheconf_vhost'))); - } - - $vhosts_filename = \Froxlor\FileDir::makeCorrectFile($vhosts_folder . '/05_froxlor_default_errorhandler.conf'); - - if (! isset($this->virtualhosts_data[$vhosts_filename])) { - $this->virtualhosts_data[$vhosts_filename] = ''; - } - - $statusCodes = array( - '401', - '403', - '404', - '500' - ); - foreach ($statusCodes as $statusCode) { - if (Settings::Get('defaultwebsrverrhandler.err' . $statusCode) != '') { - $defhandler = Settings::Get('defaultwebsrverrhandler.err' . $statusCode); - if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) { - if (substr($defhandler, 0, 1) != '"' && substr($defhandler, - 1, 1) != '"') { - $defhandler = '"' . \Froxlor\FileDir::makeCorrectFile($defhandler) . '"'; - } - } - $this->virtualhosts_data[$vhosts_filename] .= 'ErrorDocument ' . $statusCode . ' ' . $defhandler . "\n"; - } - } - } - } - public function createIpPort() { $result_ipsandports_stmt = Database::query("SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` ORDER BY `ip` ASC, `port` ASC"); - while ($row_ipsandports = $result_ipsandports_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row_ipsandports = $result_ipsandports_stmt->fetch(PDO::FETCH_ASSOC)) { if (filter_var($row_ipsandports['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { $ipport = '[' . $row_ipsandports['ip'] . ']:' . $row_ipsandports['port']; } else { $ipport = $row_ipsandports['ip'] . ':' . $row_ipsandports['port']; } - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'apache::createIpPort: creating ip/port settings for ' . $ipport); - $vhosts_filename = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/10_froxlor_ipandport_' . trim(str_replace(':', '.', $row_ipsandports['ip']), '.') . '.' . $row_ipsandports['port'] . '.conf'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'apache::createIpPort: creating ip/port settings for ' . $ipport); + $vhosts_filename = FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/10_froxlor_ipandport_' . trim(str_replace(':', '.', $row_ipsandports['ip']), '.') . '.' . $row_ipsandports['port'] . '.conf'); - if (! isset($this->virtualhosts_data[$vhosts_filename])) { + if (!isset($this->virtualhosts_data[$vhosts_filename])) { $this->virtualhosts_data[$vhosts_filename] = ''; } if ($row_ipsandports['listen_statement'] == '1') { $this->virtualhosts_data[$vhosts_filename] .= 'Listen ' . $ipport . "\n"; - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, $ipport . ' :: inserted listen-statement'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, $ipport . ' :: inserted listen-statement'); } if ($row_ipsandports['namevirtualhost_statement'] == '1') { // >=apache-2.4 enabled? if (Settings::Get('system.apache24') == '1') { - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, $ipport . ' :: namevirtualhost-statement no longer needed for apache-2.4'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, $ipport . ' :: namevirtualhost-statement no longer needed for apache-2.4'); } else { $this->virtualhosts_data[$vhosts_filename] .= 'NameVirtualHost ' . $ipport . "\n"; - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, $ipport . ' :: inserted namevirtualhost-statement'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, $ipport . ' :: inserted namevirtualhost-statement'); } } if ($row_ipsandports['vhostcontainer'] == '1') { - $without_vhost = $this->virtualhosts_data[$vhosts_filename]; $close_vhost = true; @@ -178,16 +113,16 @@ class Apache extends HttpConfigBase $this->virtualhosts_data[$vhosts_filename] .= ' ServerName ' . Settings::Get('system.hostname') . "\n"; $froxlor_aliases = Settings::Get('system.froxloraliases'); - if (! empty($froxlor_aliases)) { + if (!empty($froxlor_aliases)) { $froxlor_aliases = explode(",", $froxlor_aliases); $aliases = ""; foreach ($froxlor_aliases as $falias) { - if (\Froxlor\Validate\Validate::validateDomain(trim($falias))) { + if (Validate::validateDomain(trim($falias))) { $aliases .= trim($falias) . " "; } } $aliases = trim($aliases); - if (! empty($aliases)) { + if (!empty($aliases)) { $this->virtualhosts_data[$vhosts_filename] .= ' ServerAlias ' . $aliases . "\n"; } } @@ -224,32 +159,32 @@ class Apache extends HttpConfigBase } } - if (! $is_redirect) { + if (!$is_redirect) { // create fcgid -Part (starter is created in apache_fcgid) if (Settings::Get('system.mod_fcgid_ownvhost') == '1' && Settings::Get('system.mod_fcgid') == '1') { - $configdir = \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.mod_fcgid_configdir') . '/froxlor.panel/' . Settings::Get('system.hostname')); + $configdir = FileDir::makeCorrectDir(Settings::Get('system.mod_fcgid_configdir') . '/froxlor.panel/' . Settings::Get('system.hostname')); $this->virtualhosts_data[$vhosts_filename] .= ' 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) { $this->virtualhosts_data[$vhosts_filename] .= ' SuexecUserGroup "' . Settings::Get('system.mod_fcgid_httpuser') . '" "' . Settings::Get('system.mod_fcgid_httpgroup') . '"' . "\n"; $this->virtualhosts_data[$vhosts_filename] .= ' ScriptAlias /php/ ' . $configdir . "\n"; } else { - $domain = array( + $domain = [ 'id' => 'none', 'domain' => Settings::Get('system.hostname'), 'adminid' => 1, /* first admin-user (superadmin) */ - 'mod_fcgid_starter' => - 1, - 'mod_fcgid_maxrequests' => - 1, + 'mod_fcgid_starter' => -1, + 'mod_fcgid_maxrequests' => -1, 'guid' => Settings::Get('system.mod_fcgid_httpuser'), 'openbasedir' => 0, 'email' => Settings::Get('panel.adminmail'), 'loginname' => 'froxlor.panel', 'documentroot' => $mypath, 'customerroot' => $mypath - ); + ]; $php = new PhpInterface($domain); $phpconfig = $php->getPhpConfig(Settings::Get('system.mod_fcgid_defaultini_ownvhost')); - $starter_filename = \Froxlor\FileDir::makeCorrectFile($configdir . '/php-fcgi-starter'); + $starter_filename = FileDir::makeCorrectFile($configdir . '/php-fcgi-starter'); $this->virtualhosts_data[$vhosts_filename] .= ' SuexecUserGroup "' . Settings::Get('system.mod_fcgid_httpuser') . '" "' . Settings::Get('system.mod_fcgid_httpgroup') . '"' . "\n"; $this->virtualhosts_data[$vhosts_filename] .= ' ' . "\n"; $file_extensions = explode(' ', $phpconfig['file_extensions']); @@ -262,7 +197,7 @@ class Apache extends HttpConfigBase $this->virtualhosts_data[$vhosts_filename] .= ' ' . "\n"; // >=apache-2.4 enabled? if (Settings::Get('system.apache24') == '1') { - $mypath_dir = new \Froxlor\Http\Directory($mypath); + $mypath_dir = new Directory($mypath); // 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) { @@ -275,23 +210,23 @@ class Apache extends HttpConfigBase } $this->virtualhosts_data[$vhosts_filename] .= ' ' . "\n"; } - } elseif (Settings::Get('phpfpm.enabled') == '1' && (int) Settings::Get('phpfpm.enabled_ownvhost') == 1) { + } elseif (Settings::Get('phpfpm.enabled') == '1' && (int)Settings::Get('phpfpm.enabled_ownvhost') == 1) { // 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( + $fpm_config = Database::pexecute_first($fpm_sel_stmt, [ 'phpconfigid' => Settings::Get('phpfpm.vhost_defaultini') - )); + ]); // create php-fpm -Part (config is created in apache_fcgid) - $domain = array( + $domain = [ 'id' => 'none', 'domain' => Settings::Get('system.hostname'), 'adminid' => 1, /* first admin-user (superadmin) */ - 'mod_fcgid_starter' => - 1, - 'mod_fcgid_maxrequests' => - 1, + 'mod_fcgid_starter' => -1, + 'mod_fcgid_maxrequests' => -1, 'guid' => Settings::Get('phpfpm.vhost_httpuser'), 'openbasedir' => 0, 'email' => Settings::Get('panel.adminmail'), @@ -299,7 +234,7 @@ class Apache extends HttpConfigBase 'documentroot' => $mypath, 'customerroot' => $mypath, 'fpm_config_id' => isset($fpm_config['id']) ? $fpm_config['id'] : 1 - ); + ]; $php = new phpinterface($domain); $phpconfig = $php->getPhpConfig(Settings::Get('phpfpm.vhost_defaultini')); @@ -317,7 +252,7 @@ class Apache extends HttpConfigBase $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)) . ')'; $this->virtualhosts_data[$vhosts_filename] .= ' ' . "\n"; $this->virtualhosts_data[$vhosts_filename] .= ' SetHandler proxy:unix:' . $php->getInterface()->getSocketFile() . '|fcgi://localhost' . "\n"; $this->virtualhosts_data[$vhosts_filename] .= ' ' . "\n"; @@ -340,7 +275,7 @@ class Apache extends HttpConfigBase $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)) . ')'; $this->virtualhosts_data[$vhosts_filename] .= ' ' . "\n"; $this->virtualhosts_data[$vhosts_filename] .= ' AddHandler php-fastcgi .php' . "\n"; $this->virtualhosts_data[$vhosts_filename] .= ' Action php-fastcgi /fastcgiphp' . "\n"; @@ -348,7 +283,7 @@ class Apache extends HttpConfigBase $this->virtualhosts_data[$vhosts_filename] .= ' ' . "\n"; // >=apache-2.4 enabled? if (Settings::Get('system.apache24') == '1') { - $mypath_dir = new \Froxlor\Http\Directory($mypath); + $mypath_dir = new Directory($mypath); // 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) { @@ -364,7 +299,7 @@ class Apache extends HttpConfigBase } } else { // mod_php - $domain = array( + $domain = [ 'id' => 'none', 'domain' => Settings::Get('system.hostname'), 'adminid' => 1, /* first admin-user (superadmin) */ @@ -374,17 +309,17 @@ class Apache extends HttpConfigBase 'loginname' => 'froxlor.panel', 'documentroot' => $mypath, 'customerroot' => $mypath - ); + ]; } // end of ssl-redirect check } else { // fallback of froxlor domain-data for processSpecialConfigTemplate() - $domain = array( + $domain = [ 'domain' => Settings::Get('system.hostname'), 'loginname' => 'froxlor.panel', 'documentroot' => $mypath, 'customerroot' => $mypath - ); + ]; } /** @@ -395,7 +330,7 @@ class Apache extends HttpConfigBase * $this->virtualhosts_data[$vhosts_filename] .= "\t\tAllow from all\n"; * $this->virtualhosts_data[$vhosts_filename] .= "\t\tOptions -Indexes\n"; * $this->virtualhosts_data[$vhosts_filename] .= "\t\n"; - * + * * $this->virtualhosts_data[$vhosts_filename] .= "\t\n"; * $this->virtualhosts_data[$vhosts_filename] .= "\t\tOrder Deny,Allow\n"; * $this->virtualhosts_data[$vhosts_filename] .= "\t\tDeny from All\n"; @@ -408,27 +343,26 @@ class Apache extends HttpConfigBase } if ($row_ipsandports['ssl'] == '1' && Settings::Get('system.use_ssl') == '1') { - if ($row_ipsandports['ssl_specialsettings'] != '') { $this->virtualhosts_data[$vhosts_filename] .= $this->processSpecialConfigTemplate($row_ipsandports['ssl_specialsettings'], $domain, $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n"; } // check for required fallback - if (($row_ipsandports['ssl_cert_file'] == '' || ! file_exists($row_ipsandports['ssl_cert_file'])) && (Settings::Get('system.le_froxlor_enabled') == '0' || $this->froxlorVhostHasLetsEncryptCert() == false)) { + if (($row_ipsandports['ssl_cert_file'] == '' || !file_exists($row_ipsandports['ssl_cert_file'])) && (Settings::Get('system.le_froxlor_enabled') == '0' || $this->froxlorVhostHasLetsEncryptCert() == false)) { $row_ipsandports['ssl_cert_file'] = Settings::Get('system.ssl_cert_file'); - if (! file_exists($row_ipsandports['ssl_cert_file'])) { + if (!file_exists($row_ipsandports['ssl_cert_file'])) { // explicitly disable ssl for this vhost $row_ipsandports['ssl_cert_file'] = ""; - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Disabling SSL-vhost for "' . Settings::Get('system.hostname') . '"'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Disabling SSL-vhost for "' . Settings::Get('system.hostname') . '"'); } } if ($row_ipsandports['ssl_key_file'] == '') { $row_ipsandports['ssl_key_file'] = Settings::Get('system.ssl_key_file'); - if (! file_exists($row_ipsandports['ssl_key_file'])) { + if (!file_exists($row_ipsandports['ssl_key_file'])) { // explicitly disable ssl for this vhost $row_ipsandports['ssl_cert_file'] = ""; - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate key-file "' . Settings::Get('system.ssl_key_file') . '" does not seem to exist. Disabling SSL-vhost for "' . Settings::Get('system.hostname') . '"'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate key-file "' . Settings::Get('system.ssl_key_file') . '" does not seem to exist. Disabling SSL-vhost for "' . Settings::Get('system.hostname') . '"'); } } @@ -441,7 +375,7 @@ class Apache extends HttpConfigBase $row_ipsandports['ssl_cert_chainfile'] = Settings::Get('system.ssl_cert_chainfile'); } - $domain = array( + $domain = [ 'id' => 0, 'domain' => Settings::Get('system.hostname'), 'adminid' => 1, /* first admin-user (superadmin) */ @@ -451,7 +385,7 @@ class Apache extends HttpConfigBase 'parentdomainid' => 0, 'ssl_honorcipherorder' => Settings::Get('system.honorcipherorder'), 'ssl_sessiontickets' => Settings::Get('system.sessiontickets') - ); + ]; // override corresponding array values $domain['ssl_cert_file'] = $row_ipsandports['ssl_cert_file']; @@ -466,72 +400,70 @@ class Apache extends HttpConfigBase $dssl->setDomainSSLFilesArray($domain); if ($domain['ssl_cert_file'] != '') { - // check for existence, #1485 - if (! file_exists($domain['ssl_cert_file'])) { - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, $ipport . ' :: certificate file "' . $domain['ssl_cert_file'] . '" does not exist! Cannot create ssl-directives'); + if (!file_exists($domain['ssl_cert_file'])) { + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, $ipport . ' :: certificate file "' . $domain['ssl_cert_file'] . '" does not exist! Cannot create ssl-directives'); } else { - $this->virtualhosts_data[$vhosts_filename] .= ' SSLEngine On' . "\n"; $this->virtualhosts_data[$vhosts_filename] .= ' SSLProtocol -ALL +' . str_replace(",", " +", Settings::Get('system.ssl_protocols')) . "\n"; if (Settings::Get('system.apache24') == '1') { if (Settings::Get('system.http2_support') == '1') { $this->virtualhosts_data[$vhosts_filename] .= ' Protocols h2 http/1.1' . "\n"; } - if (! empty(Settings::Get('system.dhparams_file'))) { - $dhparams = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.dhparams_file')); - if (! file_exists($dhparams)) { - \Froxlor\FileDir::safe_exec('openssl dhparam -out ' . escapeshellarg($dhparams) . ' 4096'); + if (!empty(Settings::Get('system.dhparams_file'))) { + $dhparams = FileDir::makeCorrectFile(Settings::Get('system.dhparams_file')); + if (!file_exists($dhparams)) { + FileDir::safe_exec('openssl dhparam -out ' . escapeshellarg($dhparams) . ' 4096'); } $this->virtualhosts_data[$vhosts_filename] .= ' SSLOpenSSLConfCmd DHParameters "' . $dhparams . '"' . "\n"; } $this->virtualhosts_data[$vhosts_filename] .= ' SSLCompression Off' . "\n"; if (Settings::Get('system.sessionticketsenabled') == '1') { - $this->virtualhosts_data[$vhosts_filename] .= ' SSLSessionTickets ' . ($domain['ssl_sessiontickets'] == '1' ? 'on' : 'off') . "\n"; + $this->virtualhosts_data[$vhosts_filename] .= ' SSLSessionTickets ' . ($domain['ssl_sessiontickets'] == '1' ? 'on' : 'off') . "\n"; } } - $this->virtualhosts_data[$vhosts_filename] .= ' SSLHonorCipherOrder ' . ($domain['ssl_honorcipherorder'] == '1' ? 'on' : 'off') . "\n"; + $this->virtualhosts_data[$vhosts_filename] .= ' SSLHonorCipherOrder ' . ($domain['ssl_honorcipherorder'] == '1' ? 'on' : 'off') . "\n"; $this->virtualhosts_data[$vhosts_filename] .= ' SSLCipherSuite ' . Settings::Get('system.ssl_cipher_list') . "\n"; $protocols = array_map('trim', explode(",", Settings::Get('system.ssl_protocols'))); - if (in_array("TLSv1.3", $protocols) && ! empty(Settings::Get('system.tlsv13_cipher_list')) && Settings::Get('system.apache24') == 1) { + if (in_array("TLSv1.3", $protocols) && !empty(Settings::Get('system.tlsv13_cipher_list')) && Settings::Get('system.apache24') == 1) { $this->virtualhosts_data[$vhosts_filename] .= ' SSLCipherSuite TLSv1.3 ' . Settings::Get('system.tlsv13_cipher_list') . "\n"; } $this->virtualhosts_data[$vhosts_filename] .= ' SSLVerifyDepth 10' . "\n"; - $this->virtualhosts_data[$vhosts_filename] .= ' SSLCertificateFile ' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_cert_file']) . "\n"; + $this->virtualhosts_data[$vhosts_filename] .= ' SSLCertificateFile ' . FileDir::makeCorrectFile($domain['ssl_cert_file']) . "\n"; if ($domain['ssl_key_file'] != '') { // check for existence, #1485 - if (! file_exists($domain['ssl_key_file'])) { - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, $ipport . ' :: certificate key file "' . $domain['ssl_key_file'] . '" does not exist! Cannot create ssl-directives'); + if (!file_exists($domain['ssl_key_file'])) { + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, $ipport . ' :: certificate key file "' . $domain['ssl_key_file'] . '" does not exist! Cannot create ssl-directives'); } else { - $this->virtualhosts_data[$vhosts_filename] .= ' SSLCertificateKeyFile ' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_key_file']) . "\n"; + $this->virtualhosts_data[$vhosts_filename] .= ' SSLCertificateKeyFile ' . FileDir::makeCorrectFile($domain['ssl_key_file']) . "\n"; } } if ($domain['ssl_ca_file'] != '') { // check for existence, #1485 - if (! file_exists($domain['ssl_ca_file'])) { - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, $ipport . ' :: certificate CA file "' . $domain['ssl_ca_file'] . '" does not exist! Cannot create ssl-directives'); + if (!file_exists($domain['ssl_ca_file'])) { + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, $ipport . ' :: certificate CA file "' . $domain['ssl_ca_file'] . '" does not exist! Cannot create ssl-directives'); } else { - $this->virtualhosts_data[$vhosts_filename] .= ' SSLCACertificateFile ' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_ca_file']) . "\n"; + $this->virtualhosts_data[$vhosts_filename] .= ' SSLCACertificateFile ' . FileDir::makeCorrectFile($domain['ssl_ca_file']) . "\n"; } } // #418 if ($domain['ssl_cert_chainfile'] != '') { // check for existence, #1485 - if (! file_exists($domain['ssl_cert_chainfile'])) { - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, $ipport . ' :: certificate chain file "' . $domain['ssl_cert_chainfile'] . '" does not exist! Cannot create ssl-directives'); + if (!file_exists($domain['ssl_cert_chainfile'])) { + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, $ipport . ' :: certificate chain file "' . $domain['ssl_cert_chainfile'] . '" does not exist! Cannot create ssl-directives'); } else { - $this->virtualhosts_data[$vhosts_filename] .= ' SSLCertificateChainFile ' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_cert_chainfile']) . "\n"; + $this->virtualhosts_data[$vhosts_filename] .= ' SSLCertificateChainFile ' . FileDir::makeCorrectFile($domain['ssl_cert_chainfile']) . "\n"; } } } } else { // if there is no cert-file specified but we are generating a ssl-vhost, // we should return an empty string because this vhost would suck dick, ref #1583 - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, $domain['domain'] . ' :: empty certificate file! Cannot create ssl-directives'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, $domain['domain'] . ' :: empty certificate file! Cannot create ssl-directives'); $this->virtualhosts_data[$vhosts_filename] = $without_vhost; $this->virtualhosts_data[$vhosts_filename] .= '# no ssl-certificate was specified for this domain, therefore no explicit vhost-container is being generated'; $close_vhost = false; @@ -541,7 +473,7 @@ class Apache extends HttpConfigBase if ($close_vhost) { $this->virtualhosts_data[$vhosts_filename] .= '' . "\n"; } - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, $ipport . ' :: inserted vhostcontainer'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, $ipport . ' :: inserted vhostcontainer'); } unset($vhosts_filename); } @@ -558,52 +490,88 @@ class Apache extends HttpConfigBase } /** - * We put together the needed php options in the virtualhost entries - * - * @param array $domain - * @param bool $ssl_vhost - * - * @return string + * define a standard -statement, bug #32 */ - protected function composePhpOptions(&$domain, $ssl_vhost = false) + private function createStandardDirectoryEntry() { - $php_options_text = ''; - - if ($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1') { - // This vHost has PHP enabled and we are using the regular mod_php - $cmail = \Froxlor\Customer\Customer::getCustomerDetail($domain['customerid'], 'email'); - $php_options_text .= ' php_admin_value sendmail_path "/usr/sbin/sendmail -t -f ' . $cmail . '"' . PHP_EOL; - - if ($domain['openbasedir'] == '1') { - if ($domain['openbasedir_path'] == '1' || strstr($domain['documentroot'], ":") !== false) { - $_phpappendopenbasedir = \Froxlor\Domain\Domain::appendOpenBasedirPath($domain['customerroot'], true); - } else { - $_phpappendopenbasedir = \Froxlor\Domain\Domain::appendOpenBasedirPath($domain['documentroot'], true); - } - - $_custom_openbasedir = explode(':', Settings::Get('system.phpappendopenbasedir')); - foreach ($_custom_openbasedir as $cobd) { - $_phpappendopenbasedir .= \Froxlor\Domain\Domain::appendOpenBasedirPath($cobd); - } - - $php_options_text .= ' php_admin_value open_basedir "' . $_phpappendopenbasedir . '"' . "\n"; - } + $vhosts_folder = ''; + if (is_dir(Settings::Get('system.apacheconf_vhost'))) { + $vhosts_folder = FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')); } else { - $php_options_text .= ' # PHP is disabled for this vHost' . "\n"; - $php_options_text .= ' php_flag engine off' . "\n"; + $vhosts_folder = FileDir::makeCorrectDir(dirname(Settings::Get('system.apacheconf_vhost'))); + } + $vhosts_filename = FileDir::makeCorrectFile($vhosts_folder . '/05_froxlor_dirfix_nofcgid.conf'); + + if (!isset($this->virtualhosts_data[$vhosts_filename])) { + $this->virtualhosts_data[$vhosts_filename] = ''; } - /** - * check for apache-itk-support, #1400 - * why is this here? Because it only works with mod_php - */ - if (Settings::get('system.apacheitksupport') == 1) { - $php_options_text .= ' ' . "\n"; - $php_options_text .= ' AssignUserID ' . $domain['loginname'] . ' ' . $domain['loginname'] . "\n"; - $php_options_text .= ' ' . "\n"; - } + $this->virtualhosts_data[$vhosts_filename] .= ' ' . "\n"; - return $php_options_text; + // check for custom values, see #1638 + $custom_opts = Settings::Get('system.apacheglobaldiropt'); + if (!empty($custom_opts)) { + $this->virtualhosts_data[$vhosts_filename] .= $custom_opts . "\n"; + } else { + // >=apache-2.4 enabled? + if (Settings::Get('system.apache24') == '1') { + $this->virtualhosts_data[$vhosts_filename] .= ' Require all granted' . "\n"; + $this->virtualhosts_data[$vhosts_filename] .= ' AllowOverride All' . "\n"; + } else { + $this->virtualhosts_data[$vhosts_filename] .= ' Order allow,deny' . "\n"; + $this->virtualhosts_data[$vhosts_filename] .= ' allow from all' . "\n"; + } + } + $this->virtualhosts_data[$vhosts_filename] .= ' ' . "\n"; + + $ocsp_cache_filename = FileDir::makeCorrectFile($vhosts_folder . '/03_froxlor_ocsp_cache.conf'); + if (Settings::Get('system.use_ssl') == '1' && Settings::Get('system.apache24') == 1) { + $this->virtualhosts_data[$ocsp_cache_filename] = 'SSLStaplingCache ' . Settings::Get('system.apache24_ocsp_cache_path') . "\n"; + } else { + if (file_exists($ocsp_cache_filename)) { + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'apache::_createStandardDirectoryEntry: unlinking ' . basename($ocsp_cache_filename)); + unlink(FileDir::makeCorrectFile($ocsp_cache_filename)); + } + } + } + + /** + * define a default ErrorDocument-statement, bug #unknown-yet + */ + private function createStandardErrorHandler() + { + if (Settings::Get('defaultwebsrverrhandler.enabled') == '1' && (Settings::Get('defaultwebsrverrhandler.err401') != '' || Settings::Get('defaultwebsrverrhandler.err403') != '' || Settings::Get('defaultwebsrverrhandler.err404') != '' || Settings::Get('defaultwebsrverrhandler.err500') != '')) { + $vhosts_folder = ''; + if (is_dir(Settings::Get('system.apacheconf_vhost'))) { + $vhosts_folder = FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')); + } else { + $vhosts_folder = FileDir::makeCorrectDir(dirname(Settings::Get('system.apacheconf_vhost'))); + } + + $vhosts_filename = FileDir::makeCorrectFile($vhosts_folder . '/05_froxlor_default_errorhandler.conf'); + + if (!isset($this->virtualhosts_data[$vhosts_filename])) { + $this->virtualhosts_data[$vhosts_filename] = ''; + } + + $statusCodes = [ + '401', + '403', + '404', + '500' + ]; + foreach ($statusCodes as $statusCode) { + if (Settings::Get('defaultwebsrverrhandler.err' . $statusCode) != '') { + $defhandler = Settings::Get('defaultwebsrverrhandler.err' . $statusCode); + if (!Validate::validateUrl($defhandler)) { + if (substr($defhandler, 0, 1) != '"' && substr($defhandler, -1, 1) != '"') { + $defhandler = '"' . FileDir::makeCorrectFile($defhandler) . '"'; + } + } + $this->virtualhosts_data[$vhosts_filename] .= 'ErrorDocument ' . $statusCode . ' ' . $defhandler . "\n"; + } + } + } } public function createOwnVhostStarter() @@ -612,234 +580,32 @@ class Apache extends HttpConfigBase } /** - * We collect all servernames and Aliases + * We compose the virtualhost entries for the domains */ - protected function getServerNames($domain) + public function createVirtualHosts() { - $servernames_text = ' ServerName ' . $domain['domain'] . "\n"; + $domains = WebserverBase::getVhostsToCreate(); + foreach ($domains as $domain) { + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'apache::createVirtualHosts: creating vhost container for domain ' . $domain['id'] . ', customer ' . $domain['loginname']); + $vhosts_filename = $this->getVhostFilename($domain); - $server_alias = ''; - if ($domain['iswildcarddomain'] == '1') { - $server_alias = '*.' . $domain['domain']; - } elseif ($domain['wwwserveralias'] == '1') { - $server_alias = 'www.' . $domain['domain']; - } + // Apply header + $this->virtualhosts_data[$vhosts_filename] = '# Domain ID: ' . $domain['id'] . ' - CustomerID: ' . $domain['customerid'] . ' - CustomerLogin: ' . $domain['loginname'] . "\n"; - if (trim($server_alias) != '') { - $servernames_text .= ' ServerAlias ' . $server_alias . "\n"; - } + if ($domain['deactivated'] != '1' || Settings::Get('system.deactivateddocroot') != '') { + // Create vhost without ssl + $this->virtualhosts_data[$vhosts_filename] .= $this->getVhostContent($domain, false); - $alias_domains_stmt = Database::prepare(" - SELECT `domain`, `iswildcarddomain`, `wwwserveralias` - FROM `" . TABLE_PANEL_DOMAINS . "` - WHERE `aliasdomain`= :domainid - "); - Database::pexecute($alias_domains_stmt, array( - 'domainid' => $domain['id'] - )); - - while (($alias_domain = $alias_domains_stmt->fetch(\PDO::FETCH_ASSOC)) !== false) { - $server_alias = ' ServerAlias ' . $alias_domain['domain']; - - if ($alias_domain['iswildcarddomain'] == '1') { - $server_alias .= ' *.' . $alias_domain['domain']; - } else { - if ($alias_domain['wwwserveralias'] == '1') { - $server_alias .= ' www.' . $alias_domain['domain']; + if ($domain['ssl_enabled'] == '1' && ($domain['ssl'] == '1' || $domain['ssl_redirect'] == '1')) { + // Adding ssl stuff if enabled + $vhosts_filename_ssl = $this->getVhostFilename($domain, true); + $this->virtualhosts_data[$vhosts_filename_ssl] = '# Domain ID: ' . $domain['id'] . ' (SSL) - CustomerID: ' . $domain['customerid'] . ' - CustomerLogin: ' . $domain['loginname'] . "\n"; + $this->virtualhosts_data[$vhosts_filename_ssl] .= $this->getVhostContent($domain, true); } - } - - $servernames_text .= $server_alias . "\n"; - } - - $servernames_text .= ' ServerAdmin ' . $domain['email'] . "\n"; - return $servernames_text; - } - - /** - * Let's get the webroot - */ - protected function getWebroot($domain) - { - $webroot_text = ''; - $domain['customerroot'] = \Froxlor\FileDir::makeCorrectDir($domain['customerroot']); - $domain['documentroot'] = \Froxlor\FileDir::makeCorrectDir($domain['documentroot']); - - if ($domain['deactivated'] == '1' && Settings::Get('system.deactivateddocroot') != '') { - $webroot_text .= ' # Using docroot for deactivated users...' . "\n"; - $webroot_text .= ' DocumentRoot "' . rtrim(\Froxlor\FileDir::makeCorrectDir(Settings::Get('system.deactivateddocroot')), "/") . "\"\n"; - $webroot_text .= ' ' . "\n"; - // >=apache-2.4 enabled? - if (Settings::Get('system.apache24') == '1') { - $webroot_text .= ' Require all granted' . "\n"; - $webroot_text .= ' AllowOverride All' . "\n"; } else { - $webroot_text .= ' Order allow,deny' . "\n"; - $webroot_text .= ' allow from all' . "\n"; - } - $webroot_text .= ' ' . "\n"; - $this->deactivated = true; - } else { - $webroot_text .= ' DocumentRoot "' . rtrim($domain['documentroot'], "/") . "\"\n"; - $this->deactivated = false; - } - - return $webroot_text; - } - - /** - * Lets set the text part for the stats software - */ - protected function getStats($domain) - { - $stats_text = ''; - - if ($domain['speciallogfile'] == '1') { - $statDomain = ($domain['parentdomainid'] == '0') ? $domain['domain'] : $domain['parentdomain']; - if (Settings::Get('system.awstats_enabled') == '1') { - $stats_text .= ' Alias /awstats "' . \Froxlor\FileDir::makeCorrectFile($domain['customerroot'] . '/awstats/' . $statDomain) . '"' . "\n"; - $stats_text .= ' Alias /awstats-icon "' . \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '"' . "\n"; - } else { - $stats_text .= ' Alias /webalizer "' . \Froxlor\FileDir::makeCorrectFile($domain['customerroot'] . '/webalizer/' . $statDomain) . '"' . "\n"; - } - } else { - if ($domain['customerroot'] != $domain['documentroot']) { - if (Settings::Get('system.awstats_enabled') == '1') { - $stats_text .= ' Alias /awstats "' . \Froxlor\FileDir::makeCorrectFile($domain['customerroot'] . '/awstats/' . $domain['domain']) . '"' . "\n"; - $stats_text .= ' Alias /awstats-icon "' . \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '"' . "\n"; - } else { - $stats_text .= ' Alias /webalizer "' . \Froxlor\FileDir::makeCorrectFile($domain['customerroot'] . '/webalizer') . '"' . "\n"; - } - } elseif (Settings::Get('system.awstats_enabled') == '1') { - // if the docroots are equal, we still have to set an alias for awstats - // because the stats are in /awstats/[domain], not just /awstats/ - // also, the awstats-icons are someplace else too! - // -> webalizer does not need this! - $stats_text .= ' Alias /awstats "' . \Froxlor\FileDir::makeCorrectFile($domain['documentroot'] . '/awstats/' . $domain['domain']) . '"' . "\n"; - $stats_text .= ' Alias /awstats-icon "' . \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '"' . "\n"; + $this->virtualhosts_data[$vhosts_filename] .= '# Customer deactivated and a docroot for deactivated users hasn\'t been set.' . "\n"; } } - - return $stats_text; - } - - /** - * Lets set the logfiles - */ - protected function getLogfiles($domain) - { - $logfiles_text = ''; - - if ($domain['speciallogfile'] == '1') { - if ($domain['parentdomainid'] == '0') { - $speciallogfile = '-' . $domain['domain']; - } else { - $speciallogfile = '-' . $domain['parentdomain']; - } - } else { - $speciallogfile = ''; - } - - if ($domain['writeerrorlog']) { - // The normal access/error - logging is enabled - $error_log = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-error.log'); - // Create the logfile if it does not exist (fixes #46) - touch($error_log); - chown($error_log, Settings::Get('system.httpuser')); - chgrp($error_log, Settings::Get('system.httpgroup')); - // set error log log-level - $logfiles_text .= ' LogLevel ' . \Froxlor\Settings::Get('system.errorlog_level') . "\n"; - } else { - $error_log = '/dev/null'; - } - - if ($domain['writeaccesslog']) { - $access_log = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-access.log'); - // Create the logfile if it does not exist (fixes #46) - touch($access_log); - chown($access_log, Settings::Get('system.httpuser')); - chgrp($access_log, Settings::Get('system.httpgroup')); - } else { - $access_log = '/dev/null'; - } - - $logtype = 'combined'; - if (Settings::Get('system.logfiles_format') != '') { - $logtype = 'frx_custom'; - $logfiles_text .= ' LogFormat ' . Settings::Get('system.logfiles_format') . ' ' . $logtype . "\n"; - } - if (Settings::Get('system.logfiles_type') == '2' && Settings::Get('system.logfiles_format') == '') { - $logtype = 'vhost_combined'; - } - - if (Settings::Get('system.logfiles_piped') == '1' && Settings::Get('system.logfiles_script') != '') { - if ($domain['writeerrorlog']) { - // replace for error_log - $command = \Froxlor\PhpHelper::replaceVariables(Settings::Get('system.logfiles_script'), array( - 'LOGFILE' => $error_log, - 'DOMAIN' => $domain['domain'], - 'CUSTOMER' => $domain['loginname'] - )); - $logfiles_text .= ' ErrorLog "|' . $command . "\"\n"; - } else { - $logfiles_text .= ' ErrorLog "' . $error_log . '"' . "\n"; - } - if ($domain['writeaccesslog']) { - // replace for access_log - $command = \Froxlor\PhpHelper::replaceVariables(Settings::Get('system.logfiles_script'), array( - 'LOGFILE' => $access_log, - 'DOMAIN' => $domain['domain'], - 'CUSTOMER' => $domain['loginname'] - )); - $logfiles_text .= ' CustomLog "|' . $command . '" ' . $logtype . "\n"; - } else { - $logfiles_text .= ' CustomLog "' . $access_log . '" ' . $logtype . "\n"; - } - } else { - $logfiles_text .= ' ErrorLog "' . $error_log . '"' . "\n"; - $logfiles_text .= ' CustomLog "' . $access_log . '" ' . $logtype . "\n"; - } - - if (Settings::Get('system.awstats_enabled') == '1') { - if ((int) $domain['parentdomainid'] == 0) { - // prepare the aliases and subdomains for stats config files - $server_alias = ''; - $alias_domains_stmt = Database::prepare(" - SELECT `domain`, `iswildcarddomain`, `wwwserveralias` - FROM `" . TABLE_PANEL_DOMAINS . "` - WHERE `aliasdomain` = :domainid OR `parentdomainid` = :domainid - "); - Database::pexecute($alias_domains_stmt, array( - 'domainid' => $domain['id'] - )); - - while (($alias_domain = $alias_domains_stmt->fetch(\PDO::FETCH_ASSOC)) !== false) { - - $server_alias .= ' ' . $alias_domain['domain'] . ' '; - - if ($alias_domain['iswildcarddomain'] == '1') { - $server_alias .= '*.' . $alias_domain['domain']; - } elseif ($alias_domain['wwwserveralias'] == '1') { - $server_alias .= 'www.' . $alias_domain['domain']; - } - } - - $alias = ''; - if ($domain['iswildcarddomain'] == '1') { - $alias = '*.' . $domain['domain']; - } elseif ($domain['wwwserveralias'] == '1') { - $alias = 'www.' . $domain['domain']; - } - - // After inserting the AWStats information, - // be sure to build the awstats conf file as well - // and chown it using $awstats_params, #258 - // Bug 960 + Bug 970 : Use full $domain instead of custom $awstats_params as following classes depend on the information - \Froxlor\Http\Statistics::createAWStatsConf(Settings::Get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-access.log', $domain['domain'], $alias . $server_alias, $domain['customerroot'], $domain); - } - } - - return $logfiles_text; } /** @@ -847,19 +613,19 @@ class Apache extends HttpConfigBase */ protected function getVhostFilename($domain, $ssl_vhost = false) { - if ((int) $domain['parentdomainid'] == 0 && \Froxlor\Domain\Domain::isCustomerStdSubdomain((int) $domain['id']) == false && ((int) $domain['ismainbutsubto'] == 0 || \Froxlor\Domain\Domain::domainMainToSubExists($domain['ismainbutsubto']) == false)) { + if ((int)$domain['parentdomainid'] == 0 && Domain::isCustomerStdSubdomain((int)$domain['id']) == false && ((int)$domain['ismainbutsubto'] == 0 || Domain::domainMainToSubExists($domain['ismainbutsubto']) == false)) { $vhost_no = '35'; - } elseif ((int) $domain['parentdomainid'] == 0 && \Froxlor\Domain\Domain::isCustomerStdSubdomain((int) $domain['id']) == false && (int) $domain['ismainbutsubto'] > 0) { + } elseif ((int)$domain['parentdomainid'] == 0 && Domain::isCustomerStdSubdomain((int)$domain['id']) == false && (int)$domain['ismainbutsubto'] > 0) { $vhost_no = '30'; } else { // number of dots in a domain specifies it's position (and depth of subdomain) starting at 29 going downwards on higher depth - $vhost_no = (string) (30 - substr_count($domain['domain'], ".") + 1); + $vhost_no = (string)(30 - substr_count($domain['domain'], ".") + 1); } if ($ssl_vhost === true) { - $vhost_filename = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/' . $vhost_no . '_froxlor_ssl_vhost_' . $domain['domain'] . '.conf'); + $vhost_filename = FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/' . $vhost_no . '_froxlor_ssl_vhost_' . $domain['domain'] . '.conf'); } else { - $vhost_filename = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/' . $vhost_no . '_froxlor_normal_vhost_' . $domain['domain'] . '.conf'); + $vhost_filename = FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/' . $vhost_no . '_froxlor_normal_vhost_' . $domain['domain'] . '.conf'); } return $vhost_filename; @@ -886,14 +652,13 @@ class Apache extends HttpConfigBase $vhost_content = ''; $result_stmt = Database::prepare($query); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'domainid' => $domain['id'] - )); + ]); $ipportlist = ''; $_vhost_content = ''; - while ($ipandport = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { - + while ($ipandport = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $ipport = ''; $domain['ip'] = $ipandport['ip']; $domain['port'] = $ipandport['port']; @@ -943,9 +708,9 @@ class Apache extends HttpConfigBase AND `ip`.`ssl` = '1' AND `ip`.`port` != 443 ORDER BY `ip`.`ssl_cert_file` DESC, `ip`.`port` LIMIT 1; "); - $ssldestport = Database::pexecute_first($ssldestport_stmt, array( + $ssldestport = Database::pexecute_first($ssldestport_stmt, [ 'domainid' => $domain['id'] - )); + ]); if ($ssldestport && $ssldestport['port'] != '') { $_sslport = ":" . $ssldestport['port']; @@ -956,21 +721,21 @@ class Apache extends HttpConfigBase } if ($ssl_vhost === true && $domain['ssl'] == '1' && Settings::Get('system.use_ssl') == '1') { - if ($domain['ssl_cert_file'] == '' || ! file_exists($domain['ssl_cert_file'])) { + if ($domain['ssl_cert_file'] == '' || !file_exists($domain['ssl_cert_file'])) { $domain['ssl_cert_file'] = Settings::Get('system.ssl_cert_file'); - if (! file_exists($domain['ssl_cert_file'])) { + if (!file_exists($domain['ssl_cert_file'])) { // explicitly disable ssl for this vhost $domain['ssl_cert_file'] = ""; - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Disabling SSL-vhost for "' . $domain['domain'] . '"'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Disabling SSL-vhost for "' . $domain['domain'] . '"'); } } - if ($domain['ssl_key_file'] == '' || ! file_exists($domain['ssl_key_file'])) { + if ($domain['ssl_key_file'] == '' || !file_exists($domain['ssl_key_file'])) { $domain['ssl_key_file'] = Settings::Get('system.ssl_key_file'); - if (! file_exists($domain['ssl_key_file'])) { + if (!file_exists($domain['ssl_key_file'])) { // explicitly disable ssl for this vhost $domain['ssl_cert_file'] = ""; - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate key-file "' . Settings::Get('system.ssl_key_file') . '" does not seem to exist. Disabling SSL-vhost for "' . $domain['domain'] . '"'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate key-file "' . Settings::Get('system.ssl_key_file') . '" does not seem to exist. Disabling SSL-vhost for "' . $domain['domain'] . '"'); } } @@ -983,10 +748,9 @@ class Apache extends HttpConfigBase } if ($domain['ssl_cert_file'] != '') { - - $ssl_protocols = ($domain['override_tls'] == '1' && ! empty($domain['ssl_protocols'])) ? $domain['ssl_protocols'] : Settings::Get('system.ssl_protocols'); - $ssl_cipher_list = ($domain['override_tls'] == '1' && ! empty($domain['ssl_cipher_list'])) ? $domain['ssl_cipher_list'] : Settings::Get('system.ssl_cipher_list'); - $tlsv13_cipher_list = ($domain['override_tls'] == '1' && ! empty($domain['tlsv13_cipher_list'])) ? $domain['tlsv13_cipher_list'] : Settings::Get('system.tlsv13_cipher_list'); + $ssl_protocols = ($domain['override_tls'] == '1' && !empty($domain['ssl_protocols'])) ? $domain['ssl_protocols'] : Settings::Get('system.ssl_protocols'); + $ssl_cipher_list = ($domain['override_tls'] == '1' && !empty($domain['ssl_cipher_list'])) ? $domain['ssl_cipher_list'] : Settings::Get('system.ssl_cipher_list'); + $tlsv13_cipher_list = ($domain['override_tls'] == '1' && !empty($domain['tlsv13_cipher_list'])) ? $domain['tlsv13_cipher_list'] : Settings::Get('system.tlsv13_cipher_list'); $vhost_content .= ' SSLEngine On' . "\n"; $vhost_content .= ' SSLProtocol -ALL +' . str_replace(",", " +", $ssl_protocols) . "\n"; @@ -994,37 +758,37 @@ class Apache extends HttpConfigBase if (isset($domain['http2']) && $domain['http2'] == '1' && Settings::Get('system.http2_support') == '1') { $vhost_content .= ' Protocols h2 http/1.1' . "\n"; } - if (! empty(Settings::Get('system.dhparams_file'))) { - $dhparams = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.dhparams_file')); - if (! file_exists($dhparams)) { - \Froxlor\FileDir::safe_exec('openssl dhparam -out ' . escapeshellarg($dhparams) . ' 4096'); + if (!empty(Settings::Get('system.dhparams_file'))) { + $dhparams = FileDir::makeCorrectFile(Settings::Get('system.dhparams_file')); + if (!file_exists($dhparams)) { + FileDir::safe_exec('openssl dhparam -out ' . escapeshellarg($dhparams) . ' 4096'); } $vhost_content .= ' SSLOpenSSLConfCmd DHParameters "' . $dhparams . '"' . "\n"; } $vhost_content .= ' SSLCompression Off' . "\n"; if (Settings::Get('system.sessionticketsenabled') == '1') { - $vhost_content .= ' SSLSessionTickets ' . ($domain['ssl_sessiontickets'] == '1' ? 'on' : 'off') . "\n"; + $vhost_content .= ' SSLSessionTickets ' . ($domain['ssl_sessiontickets'] == '1' ? 'on' : 'off') . "\n"; } } - $vhost_content .= ' SSLHonorCipherOrder ' . ($domain['ssl_honorcipherorder'] == '1' ? 'on' : 'off') . "\n"; + $vhost_content .= ' SSLHonorCipherOrder ' . ($domain['ssl_honorcipherorder'] == '1' ? 'on' : 'off') . "\n"; $vhost_content .= ' SSLCipherSuite ' . $ssl_cipher_list . "\n"; $protocols = array_map('trim', explode(",", $ssl_protocols)); - if (in_array("TLSv1.3", $protocols) && ! empty($tlsv13_cipher_list) && Settings::Get('system.apache24') == 1) { + if (in_array("TLSv1.3", $protocols) && !empty($tlsv13_cipher_list) && Settings::Get('system.apache24') == 1) { $vhost_content .= ' SSLCipherSuite TLSv1.3 ' . $tlsv13_cipher_list . "\n"; } $vhost_content .= ' SSLVerifyDepth 10' . "\n"; - $vhost_content .= ' SSLCertificateFile ' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_cert_file']) . "\n"; + $vhost_content .= ' SSLCertificateFile ' . FileDir::makeCorrectFile($domain['ssl_cert_file']) . "\n"; if ($domain['ssl_key_file'] != '') { - $vhost_content .= ' SSLCertificateKeyFile ' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_key_file']) . "\n"; + $vhost_content .= ' SSLCertificateKeyFile ' . FileDir::makeCorrectFile($domain['ssl_key_file']) . "\n"; } if ($domain['ssl_ca_file'] != '') { - $vhost_content .= ' SSLCACertificateFile ' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_ca_file']) . "\n"; + $vhost_content .= ' SSLCACertificateFile ' . FileDir::makeCorrectFile($domain['ssl_ca_file']) . "\n"; } if ($domain['ssl_cert_chainfile'] != '') { - $vhost_content .= ' SSLCertificateChainFile ' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_cert_chainfile']) . "\n"; + $vhost_content .= ' SSLCertificateChainFile ' . FileDir::makeCorrectFile($domain['ssl_cert_chainfile']) . "\n"; } if (Settings::Get('system.apache24') == '1' && isset($domain['ocsp_stapling']) && $domain['ocsp_stapling'] == '1') { @@ -1046,7 +810,7 @@ class Apache extends HttpConfigBase } else { // if there is no cert-file specified but we are generating a ssl-vhost, // we should return an empty string because this vhost would suck dick, ref #1583 - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, $domain['domain'] . ' :: empty certificate file! Cannot create ssl-directives'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, $domain['domain'] . ' :: empty certificate file! Cannot create ssl-directives'); return '# no ssl-certificate was specified for this domain, therefore no explicit vhost is being generated'; } } @@ -1058,7 +822,7 @@ class Apache extends HttpConfigBase $corrected_docroot = $domain['documentroot']; // Get domain's redirect code - $code = \Froxlor\Domain\Domain::getDomainRedirectCode($domain['id']); + $code = Domain::getDomainRedirectCode($domain['id']); $modrew_red = ''; if ($code != '') { $modrew_red = ' [R=' . $code . ';L,NE]'; @@ -1067,7 +831,7 @@ class Apache extends HttpConfigBase // redirect everything, not only root-directory, #541 $vhost_content .= ' ' . "\n"; $vhost_content .= ' RewriteEngine On' . "\n"; - if (! $ssl_vhost) { + if (!$ssl_vhost) { $vhost_content .= ' RewriteCond %{HTTPS} off' . "\n"; } if ($domain['letsencrypt'] == '1') { @@ -1079,8 +843,7 @@ class Apache extends HttpConfigBase $vhost_content .= ' Redirect ' . $code . ' / ' . $domain['documentroot_norewrite'] . "\n"; $vhost_content .= ' ' . "\n"; } else { - - \Froxlor\FileDir::mkDirWithCorrectOwnership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true, true); + FileDir::mkDirWithCorrectOwnership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true, true); $vhost_content .= $this->getWebroot($domain); if ($this->deactivated == false) { $vhost_content .= $this->composePhpOptions($domain, $ssl_vhost); @@ -1115,33 +878,282 @@ class Apache extends HttpConfigBase } /** - * We compose the virtualhost entries for the domains + * We collect all servernames and Aliases */ - public function createVirtualHosts() + protected function getServerNames($domain) { - $domains = WebserverBase::getVhostsToCreate(); - foreach ($domains as $domain) { + $servernames_text = ' ServerName ' . $domain['domain'] . "\n"; - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'apache::createVirtualHosts: creating vhost container for domain ' . $domain['id'] . ', customer ' . $domain['loginname']); - $vhosts_filename = $this->getVhostFilename($domain); + $server_alias = ''; + if ($domain['iswildcarddomain'] == '1') { + $server_alias = '*.' . $domain['domain']; + } elseif ($domain['wwwserveralias'] == '1') { + $server_alias = 'www.' . $domain['domain']; + } - // Apply header - $this->virtualhosts_data[$vhosts_filename] = '# Domain ID: ' . $domain['id'] . ' - CustomerID: ' . $domain['customerid'] . ' - CustomerLogin: ' . $domain['loginname'] . "\n"; + if (trim($server_alias) != '') { + $servernames_text .= ' ServerAlias ' . $server_alias . "\n"; + } - if ($domain['deactivated'] != '1' || Settings::Get('system.deactivateddocroot') != '') { - // Create vhost without ssl - $this->virtualhosts_data[$vhosts_filename] .= $this->getVhostContent($domain, false); + $alias_domains_stmt = Database::prepare(" + SELECT `domain`, `iswildcarddomain`, `wwwserveralias` + FROM `" . TABLE_PANEL_DOMAINS . "` + WHERE `aliasdomain`= :domainid + "); + Database::pexecute($alias_domains_stmt, [ + 'domainid' => $domain['id'] + ]); - if ($domain['ssl_enabled'] == '1' && ($domain['ssl'] == '1' || $domain['ssl_redirect'] == '1')) { - // Adding ssl stuff if enabled - $vhosts_filename_ssl = $this->getVhostFilename($domain, true); - $this->virtualhosts_data[$vhosts_filename_ssl] = '# Domain ID: ' . $domain['id'] . ' (SSL) - CustomerID: ' . $domain['customerid'] . ' - CustomerLogin: ' . $domain['loginname'] . "\n"; - $this->virtualhosts_data[$vhosts_filename_ssl] .= $this->getVhostContent($domain, true); - } + while (($alias_domain = $alias_domains_stmt->fetch(PDO::FETCH_ASSOC)) !== false) { + $server_alias = ' ServerAlias ' . $alias_domain['domain']; + + if ($alias_domain['iswildcarddomain'] == '1') { + $server_alias .= ' *.' . $alias_domain['domain']; } else { - $this->virtualhosts_data[$vhosts_filename] .= '# Customer deactivated and a docroot for deactivated users hasn\'t been set.' . "\n"; + if ($alias_domain['wwwserveralias'] == '1') { + $server_alias .= ' www.' . $alias_domain['domain']; + } + } + + $servernames_text .= $server_alias . "\n"; + } + + $servernames_text .= ' ServerAdmin ' . $domain['email'] . "\n"; + return $servernames_text; + } + + /** + * Let's get the webroot + */ + protected function getWebroot($domain) + { + $webroot_text = ''; + $domain['customerroot'] = FileDir::makeCorrectDir($domain['customerroot']); + $domain['documentroot'] = FileDir::makeCorrectDir($domain['documentroot']); + + if ($domain['deactivated'] == '1' && Settings::Get('system.deactivateddocroot') != '') { + $webroot_text .= ' # Using docroot for deactivated users...' . "\n"; + $webroot_text .= ' DocumentRoot "' . rtrim(FileDir::makeCorrectDir(Settings::Get('system.deactivateddocroot')), "/") . "\"\n"; + $webroot_text .= ' ' . "\n"; + // >=apache-2.4 enabled? + if (Settings::Get('system.apache24') == '1') { + $webroot_text .= ' Require all granted' . "\n"; + $webroot_text .= ' AllowOverride All' . "\n"; + } else { + $webroot_text .= ' Order allow,deny' . "\n"; + $webroot_text .= ' allow from all' . "\n"; + } + $webroot_text .= ' ' . "\n"; + $this->deactivated = true; + } else { + $webroot_text .= ' DocumentRoot "' . rtrim($domain['documentroot'], "/") . "\"\n"; + $this->deactivated = false; + } + + return $webroot_text; + } + + /** + * We put together the needed php options in the virtualhost entries + * + * @param array $domain + * @param bool $ssl_vhost + * + * @return string + */ + protected function composePhpOptions(&$domain, $ssl_vhost = false) + { + $php_options_text = ''; + + if ($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1') { + // This vHost has PHP enabled and we are using the regular mod_php + $cmail = Customer::getCustomerDetail($domain['customerid'], 'email'); + $php_options_text .= ' php_admin_value sendmail_path "/usr/sbin/sendmail -t -f ' . $cmail . '"' . PHP_EOL; + + if ($domain['openbasedir'] == '1') { + if ($domain['openbasedir_path'] == '1' || strstr($domain['documentroot'], ":") !== false) { + $_phpappendopenbasedir = Domain::appendOpenBasedirPath($domain['customerroot'], true); + } else { + $_phpappendopenbasedir = Domain::appendOpenBasedirPath($domain['documentroot'], true); + } + + $_custom_openbasedir = explode(':', Settings::Get('system.phpappendopenbasedir')); + foreach ($_custom_openbasedir as $cobd) { + $_phpappendopenbasedir .= Domain::appendOpenBasedirPath($cobd); + } + + $php_options_text .= ' php_admin_value open_basedir "' . $_phpappendopenbasedir . '"' . "\n"; + } + } else { + $php_options_text .= ' # PHP is disabled for this vHost' . "\n"; + $php_options_text .= ' php_flag engine off' . "\n"; + } + + /** + * check for apache-itk-support, #1400 + * why is this here? Because it only works with mod_php + */ + if (Settings::get('system.apacheitksupport') == 1) { + $php_options_text .= ' ' . "\n"; + $php_options_text .= ' AssignUserID ' . $domain['loginname'] . ' ' . $domain['loginname'] . "\n"; + $php_options_text .= ' ' . "\n"; + } + + return $php_options_text; + } + + /** + * Lets set the text part for the stats software + */ + protected function getStats($domain) + { + $stats_text = ''; + + if ($domain['speciallogfile'] == '1') { + $statDomain = ($domain['parentdomainid'] == '0') ? $domain['domain'] : $domain['parentdomain']; + if (Settings::Get('system.awstats_enabled') == '1') { + $stats_text .= ' Alias /awstats "' . FileDir::makeCorrectFile($domain['customerroot'] . '/awstats/' . $statDomain) . '"' . "\n"; + $stats_text .= ' Alias /awstats-icon "' . FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '"' . "\n"; + } else { + $stats_text .= ' Alias /webalizer "' . FileDir::makeCorrectFile($domain['customerroot'] . '/webalizer/' . $statDomain) . '"' . "\n"; + } + } else { + if ($domain['customerroot'] != $domain['documentroot']) { + if (Settings::Get('system.awstats_enabled') == '1') { + $stats_text .= ' Alias /awstats "' . FileDir::makeCorrectFile($domain['customerroot'] . '/awstats/' . $domain['domain']) . '"' . "\n"; + $stats_text .= ' Alias /awstats-icon "' . FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '"' . "\n"; + } else { + $stats_text .= ' Alias /webalizer "' . FileDir::makeCorrectFile($domain['customerroot'] . '/webalizer') . '"' . "\n"; + } + } elseif (Settings::Get('system.awstats_enabled') == '1') { + // if the docroots are equal, we still have to set an alias for awstats + // because the stats are in /awstats/[domain], not just /awstats/ + // also, the awstats-icons are someplace else too! + // -> webalizer does not need this! + $stats_text .= ' Alias /awstats "' . FileDir::makeCorrectFile($domain['documentroot'] . '/awstats/' . $domain['domain']) . '"' . "\n"; + $stats_text .= ' Alias /awstats-icon "' . FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '"' . "\n"; } } + + return $stats_text; + } + + /** + * Lets set the logfiles + */ + protected function getLogfiles($domain) + { + $logfiles_text = ''; + + if ($domain['speciallogfile'] == '1') { + if ($domain['parentdomainid'] == '0') { + $speciallogfile = '-' . $domain['domain']; + } else { + $speciallogfile = '-' . $domain['parentdomain']; + } + } else { + $speciallogfile = ''; + } + + if ($domain['writeerrorlog']) { + // The normal access/error - logging is enabled + $error_log = FileDir::makeCorrectFile(Settings::Get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-error.log'); + // Create the logfile if it does not exist (fixes #46) + touch($error_log); + chown($error_log, Settings::Get('system.httpuser')); + chgrp($error_log, Settings::Get('system.httpgroup')); + // set error log log-level + $logfiles_text .= ' LogLevel ' . Settings::Get('system.errorlog_level') . "\n"; + } else { + $error_log = '/dev/null'; + } + + if ($domain['writeaccesslog']) { + $access_log = FileDir::makeCorrectFile(Settings::Get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-access.log'); + // Create the logfile if it does not exist (fixes #46) + touch($access_log); + chown($access_log, Settings::Get('system.httpuser')); + chgrp($access_log, Settings::Get('system.httpgroup')); + } else { + $access_log = '/dev/null'; + } + + $logtype = 'combined'; + if (Settings::Get('system.logfiles_format') != '') { + $logtype = 'frx_custom'; + $logfiles_text .= ' LogFormat ' . Settings::Get('system.logfiles_format') . ' ' . $logtype . "\n"; + } + if (Settings::Get('system.logfiles_type') == '2' && Settings::Get('system.logfiles_format') == '') { + $logtype = 'vhost_combined'; + } + + if (Settings::Get('system.logfiles_piped') == '1' && Settings::Get('system.logfiles_script') != '') { + if ($domain['writeerrorlog']) { + // replace for error_log + $command = PhpHelper::replaceVariables(Settings::Get('system.logfiles_script'), [ + 'LOGFILE' => $error_log, + 'DOMAIN' => $domain['domain'], + 'CUSTOMER' => $domain['loginname'] + ]); + $logfiles_text .= ' ErrorLog "|' . $command . "\"\n"; + } else { + $logfiles_text .= ' ErrorLog "' . $error_log . '"' . "\n"; + } + if ($domain['writeaccesslog']) { + // replace for access_log + $command = PhpHelper::replaceVariables(Settings::Get('system.logfiles_script'), [ + 'LOGFILE' => $access_log, + 'DOMAIN' => $domain['domain'], + 'CUSTOMER' => $domain['loginname'] + ]); + $logfiles_text .= ' CustomLog "|' . $command . '" ' . $logtype . "\n"; + } else { + $logfiles_text .= ' CustomLog "' . $access_log . '" ' . $logtype . "\n"; + } + } else { + $logfiles_text .= ' ErrorLog "' . $error_log . '"' . "\n"; + $logfiles_text .= ' CustomLog "' . $access_log . '" ' . $logtype . "\n"; + } + + if (Settings::Get('system.awstats_enabled') == '1') { + if ((int)$domain['parentdomainid'] == 0) { + // prepare the aliases and subdomains for stats config files + $server_alias = ''; + $alias_domains_stmt = Database::prepare(" + SELECT `domain`, `iswildcarddomain`, `wwwserveralias` + FROM `" . TABLE_PANEL_DOMAINS . "` + WHERE `aliasdomain` = :domainid OR `parentdomainid` = :domainid + "); + Database::pexecute($alias_domains_stmt, [ + 'domainid' => $domain['id'] + ]); + + while (($alias_domain = $alias_domains_stmt->fetch(PDO::FETCH_ASSOC)) !== false) { + $server_alias .= ' ' . $alias_domain['domain'] . ' '; + + if ($alias_domain['iswildcarddomain'] == '1') { + $server_alias .= '*.' . $alias_domain['domain']; + } elseif ($alias_domain['wwwserveralias'] == '1') { + $server_alias .= 'www.' . $alias_domain['domain']; + } + } + + $alias = ''; + if ($domain['iswildcarddomain'] == '1') { + $alias = '*.' . $domain['domain']; + } elseif ($domain['wwwserveralias'] == '1') { + $alias = 'www.' . $domain['domain']; + } + + // After inserting the AWStats information, + // be sure to build the awstats conf file as well + // and chown it using $awstats_params, #258 + // Bug 960 + Bug 970 : Use full $domain instead of custom $awstats_params as following classes depend on the information + Statistics::createAWStatsConf(Settings::Get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-access.log', $domain['domain'], $alias . $server_alias, $domain['customerroot'], $domain); + } + } + + return $logfiles_text; } /** @@ -1155,12 +1167,12 @@ class Apache extends HttpConfigBase LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING (`customerid`) ORDER BY `htac`.`path` "); - $diroptions = array(); + $diroptions = []; - while ($row_diroptions = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row_diroptions = $result_stmt->fetch(PDO::FETCH_ASSOC)) { if ($row_diroptions['customerid'] != 0 && isset($row_diroptions['customerroot']) && $row_diroptions['customerroot'] != '') { $diroptions[$row_diroptions['path']] = $row_diroptions; - $diroptions[$row_diroptions['path']]['htpasswds'] = array(); + $diroptions[$row_diroptions['path']]['htpasswds'] = []; } } @@ -1171,10 +1183,10 @@ class Apache extends HttpConfigBase ORDER BY `htpw`.`path`, `htpw`.`username` "); - while ($row_htpasswds = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row_htpasswds = $result_stmt->fetch(PDO::FETCH_ASSOC)) { if ($row_htpasswds['customerid'] != 0 && isset($row_htpasswds['customerroot']) && $row_htpasswds['customerroot'] != '') { - if (! isset($diroptions[$row_htpasswds['path']]) || ! is_array($diroptions[$row_htpasswds['path']])) { - $diroptions[$row_htpasswds['path']] = array(); + if (!isset($diroptions[$row_htpasswds['path']]) || !is_array($diroptions[$row_htpasswds['path']])) { + $diroptions[$row_htpasswds['path']] = []; } $diroptions[$row_htpasswds['path']]['path'] = $row_htpasswds['path']; @@ -1186,16 +1198,16 @@ class Apache extends HttpConfigBase } foreach ($diroptions as $row_diroptions) { - $row_diroptions['path'] = \Froxlor\FileDir::makeCorrectDir($row_diroptions['path']); - \Froxlor\FileDir::mkDirWithCorrectOwnership($row_diroptions['customerroot'], $row_diroptions['path'], $row_diroptions['guid'], $row_diroptions['guid']); - $diroptions_filename = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_diroptions') . '/40_froxlor_diroption_' . md5($row_diroptions['path']) . '.conf'); + $row_diroptions['path'] = FileDir::makeCorrectDir($row_diroptions['path']); + FileDir::mkDirWithCorrectOwnership($row_diroptions['customerroot'], $row_diroptions['path'], $row_diroptions['guid'], $row_diroptions['guid']); + $diroptions_filename = FileDir::makeCorrectFile(Settings::Get('system.apacheconf_diroptions') . '/40_froxlor_diroption_' . md5($row_diroptions['path']) . '.conf'); - if (! isset($this->diroptions_data[$diroptions_filename])) { + if (!isset($this->diroptions_data[$diroptions_filename])) { $this->diroptions_data[$diroptions_filename] = ''; } if (is_dir($row_diroptions['path'])) { - $cperlenabled = \Froxlor\Customer\Customer::customerHasPerlEnabled($row_diroptions['customerid']); + $cperlenabled = Customer::customerHasPerlEnabled($row_diroptions['customerid']); $this->diroptions_data[$diroptions_filename] .= '' . "\n"; @@ -1208,7 +1220,7 @@ class Apache extends HttpConfigBase } else { $this->diroptions_data[$diroptions_filename] .= "\n"; } - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Setting Options +Indexes for ' . $row_diroptions['path']); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Setting Options +Indexes for ' . $row_diroptions['path']); } if (isset($row_diroptions['options_indexes']) && $row_diroptions['options_indexes'] == '0') { @@ -1220,20 +1232,20 @@ class Apache extends HttpConfigBase } else { $this->diroptions_data[$diroptions_filename] .= "\n"; } - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Setting Options -Indexes for ' . $row_diroptions['path']); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Setting Options -Indexes for ' . $row_diroptions['path']); } - $statusCodes = array( + $statusCodes = [ '404', '403', '500' - ); + ]; foreach ($statusCodes as $statusCode) { if (isset($row_diroptions['error' . $statusCode . 'path']) && $row_diroptions['error' . $statusCode . 'path'] != '') { $defhandler = $row_diroptions['error' . $statusCode . 'path']; - if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) { - if (substr($defhandler, 0, 1) != '"' && substr($defhandler, - 1, 1) != '"') { - $defhandler = '"' . \Froxlor\FileDir::makeCorrectFile($defhandler) . '"'; + if (!Validate::validateUrl($defhandler)) { + if (substr($defhandler, 0, 1) != '"' && substr($defhandler, -1, 1) != '"') { + $defhandler = '"' . FileDir::makeCorrectFile($defhandler) . '"'; } } $this->diroptions_data[$diroptions_filename] .= ' ErrorDocument ' . $statusCode . ' ' . $defhandler . "\n"; @@ -1245,7 +1257,7 @@ class Apache extends HttpConfigBase $this->diroptions_data[$diroptions_filename] .= ' AddHandler cgi-script .cgi .pl' . "\n"; // >=apache-2.4 enabled? if (Settings::Get('system.apache24') == '1') { - $mypath_dir = new \Froxlor\Http\Directory($row_diroptions['path']); + $mypath_dir = new Directory($row_diroptions['path']); // 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) { @@ -1256,50 +1268,50 @@ class Apache extends HttpConfigBase $this->diroptions_data[$diroptions_filename] .= ' Order allow,deny' . "\n"; $this->diroptions_data[$diroptions_filename] .= ' Allow from all' . "\n"; } - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Enabling perl execution for ' . $row_diroptions['path']); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Enabling perl execution for ' . $row_diroptions['path']); // check for suexec-workaround, #319 - if ((int) Settings::Get('perl.suexecworkaround') == 1) { + if ((int)Settings::Get('perl.suexecworkaround') == 1) { // symlink this directory to suexec-safe-path - $loginname = \Froxlor\Customer\Customer::getCustomerDetail($row_diroptions['customerid'], 'loginname'); - $suexecpath = \Froxlor\FileDir::makeCorrectDir(Settings::Get('perl.suexecpath') . '/' . $loginname . '/' . md5($row_diroptions['path']) . '/'); + $loginname = Customer::getCustomerDetail($row_diroptions['customerid'], 'loginname'); + $suexecpath = FileDir::makeCorrectDir(Settings::Get('perl.suexecpath') . '/' . $loginname . '/' . md5($row_diroptions['path']) . '/'); - if (! file_exists($suexecpath)) { - \Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg($suexecpath)); - \Froxlor\FileDir::safe_exec('chown -R ' . escapeshellarg($row_diroptions['guid']) . ':' . escapeshellarg($row_diroptions['guid']) . ' ' . escapeshellarg($suexecpath)); + if (!file_exists($suexecpath)) { + FileDir::safe_exec('mkdir -p ' . escapeshellarg($suexecpath)); + FileDir::safe_exec('chown -R ' . escapeshellarg($row_diroptions['guid']) . ':' . escapeshellarg($row_diroptions['guid']) . ' ' . escapeshellarg($suexecpath)); } // symlink to {$givenpath}/cgi-bin // NOTE: symlinks are FILES, so do not append a / here - $perlsymlink = \Froxlor\FileDir::makeCorrectFile($row_diroptions['path'] . '/cgi-bin'); - if (! file_exists($perlsymlink)) { - \Froxlor\FileDir::safe_exec('ln -s ' . escapeshellarg($suexecpath) . ' ' . escapeshellarg($perlsymlink)); + $perlsymlink = FileDir::makeCorrectFile($row_diroptions['path'] . '/cgi-bin'); + if (!file_exists($perlsymlink)) { + FileDir::safe_exec('ln -s ' . escapeshellarg($suexecpath) . ' ' . escapeshellarg($perlsymlink)); } - \Froxlor\FileDir::safe_exec('chown -h ' . escapeshellarg($row_diroptions['guid']) . ':' . escapeshellarg($row_diroptions['guid']) . ' ' . escapeshellarg($perlsymlink)); + FileDir::safe_exec('chown -h ' . escapeshellarg($row_diroptions['guid']) . ':' . escapeshellarg($row_diroptions['guid']) . ' ' . escapeshellarg($perlsymlink)); } } else { // if no perl-execution is enabled but the workaround is, // we have to remove the symlink and folder in suexecpath - if ((int) Settings::Get('perl.suexecworkaround') == 1) { - $loginname = \Froxlor\Customer\Customer::getCustomerDetail($row_diroptions['customerid'], 'loginname'); - $suexecpath = \Froxlor\FileDir::makeCorrectDir(Settings::Get('perl.suexecpath') . '/' . $loginname . '/' . md5($row_diroptions['path']) . '/'); - $perlsymlink = \Froxlor\FileDir::makeCorrectFile($row_diroptions['path'] . '/cgi-bin'); + if ((int)Settings::Get('perl.suexecworkaround') == 1) { + $loginname = Customer::getCustomerDetail($row_diroptions['customerid'], 'loginname'); + $suexecpath = FileDir::makeCorrectDir(Settings::Get('perl.suexecpath') . '/' . $loginname . '/' . md5($row_diroptions['path']) . '/'); + $perlsymlink = FileDir::makeCorrectFile($row_diroptions['path'] . '/cgi-bin'); // remove symlink if (file_exists($perlsymlink)) { - \Froxlor\FileDir::safe_exec('rm -f ' . escapeshellarg($perlsymlink)); + FileDir::safe_exec('rm -f ' . escapeshellarg($perlsymlink)); } // remove folder in suexec-path if (file_exists($suexecpath)) { - \Froxlor\FileDir::safe_exec('rm -rf ' . escapeshellarg($suexecpath)); + FileDir::safe_exec('rm -rf ' . escapeshellarg($suexecpath)); } } } if (count($row_diroptions['htpasswds']) > 0) { - $htpasswd_filename = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_htpasswddir') . '/' . $row_diroptions['customerid'] . '-' . md5($row_diroptions['path']) . '.htpasswd'); + $htpasswd_filename = FileDir::makeCorrectFile(Settings::Get('system.apacheconf_htpasswddir') . '/' . $row_diroptions['customerid'] . '-' . md5($row_diroptions['path']) . '.htpasswd'); - if (! isset($this->htpasswds_data[$htpasswd_filename])) { + if (!isset($this->htpasswds_data[$htpasswd_filename])) { $this->htpasswds_data[$htpasswd_filename] = ''; } @@ -1324,11 +1336,11 @@ class Apache extends HttpConfigBase public function writeConfigs() { // Write diroptions - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "apache::writeConfigs: rebuilding " . Settings::Get('system.apacheconf_diroptions')); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "apache::writeConfigs: rebuilding " . Settings::Get('system.apacheconf_diroptions')); if (count($this->diroptions_data) > 0) { - $optsDir = new \Froxlor\Http\Directory(Settings::Get('system.apacheconf_diroptions')); - if (! $optsDir->isConfigDir()) { + $optsDir = new Directory(Settings::Get('system.apacheconf_diroptions')); + if (!$optsDir->isConfigDir()) { // Save one big file $diroptions_file = ''; @@ -1344,9 +1356,9 @@ class Apache extends HttpConfigBase fwrite($diroptions_file_handler, $diroptions_file); fclose($diroptions_file_handler); } else { - if (! file_exists(Settings::Get('system.apacheconf_diroptions'))) { - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'apache::writeConfigs: mkdir ' . escapeshellarg(\Froxlor\FileDir::makeCorrectDir(Settings::Get('system.apacheconf_diroptions')))); - \Froxlor\FileDir::safe_exec('mkdir ' . escapeshellarg(\Froxlor\FileDir::makeCorrectDir(Settings::Get('system.apacheconf_diroptions')))); + if (!file_exists(Settings::Get('system.apacheconf_diroptions'))) { + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'apache::writeConfigs: mkdir ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('system.apacheconf_diroptions')))); + FileDir::safe_exec('mkdir ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('system.apacheconf_diroptions')))); } // Write a single file for every diroption @@ -1363,17 +1375,17 @@ class Apache extends HttpConfigBase } // Write htpasswds - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "apache::writeConfigs: rebuilding " . Settings::Get('system.apacheconf_htpasswddir')); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "apache::writeConfigs: rebuilding " . Settings::Get('system.apacheconf_htpasswddir')); if (count($this->htpasswds_data) > 0) { - if (! file_exists(Settings::Get('system.apacheconf_htpasswddir'))) { + if (!file_exists(Settings::Get('system.apacheconf_htpasswddir'))) { $umask = umask(); umask(0000); mkdir(Settings::Get('system.apacheconf_htpasswddir'), 0751); umask($umask); } - $htpasswdDir = new \Froxlor\Http\Directory(Settings::Get('system.apacheconf_htpasswddir')); + $htpasswdDir = new Directory(Settings::Get('system.apacheconf_htpasswddir')); if ($htpasswdDir->isConfigDir(true)) { foreach ($this->htpasswds_data as $htpasswd_filename => $htpasswd_file) { $this->known_htpasswdsfilenames[] = basename($htpasswd_filename); @@ -1382,16 +1394,16 @@ class Apache extends HttpConfigBase fclose($htpasswd_file_handler); } } else { - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_WARNING, 'WARNING!!! ' . Settings::Get('system.apacheconf_htpasswddir') . ' is not a directory. htpasswd directory protection is disabled!!!'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, 'WARNING!!! ' . Settings::Get('system.apacheconf_htpasswddir') . ' is not a directory. htpasswd directory protection is disabled!!!'); } } // Write virtualhosts - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "apache::writeConfigs: rebuilding " . Settings::Get('system.apacheconf_vhost')); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "apache::writeConfigs: rebuilding " . Settings::Get('system.apacheconf_vhost')); if (count($this->virtualhosts_data) > 0) { - $vhostDir = new \Froxlor\Http\Directory(Settings::Get('system.apacheconf_vhost')); - if (! $vhostDir->isConfigDir()) { + $vhostDir = new Directory(Settings::Get('system.apacheconf_vhost')); + if (!$vhostDir->isConfigDir()) { // Save one big file $vhosts_file = ''; @@ -1419,9 +1431,9 @@ class Apache extends HttpConfigBase fwrite($vhosts_file_handler, $vhosts_file); fclose($vhosts_file_handler); } else { - if (! file_exists(Settings::Get('system.apacheconf_vhost'))) { - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'apache::writeConfigs: mkdir ' . escapeshellarg(\Froxlor\FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); - \Froxlor\FileDir::safe_exec('mkdir ' . escapeshellarg(\Froxlor\FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); + if (!file_exists(Settings::Get('system.apacheconf_vhost'))) { + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'apache::writeConfigs: mkdir ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); + FileDir::safe_exec('mkdir ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); } // Write a single file for every vhost diff --git a/lib/Froxlor/Cron/Http/ApacheFcgi.php b/lib/Froxlor/Cron/Http/ApacheFcgi.php index bc92455d..0ef64d3e 100644 --- a/lib/Froxlor/Cron/Http/ApacheFcgi.php +++ b/lib/Froxlor/Cron/Http/ApacheFcgi.php @@ -1,45 +1,124 @@ (2003-2009) - * @author Froxlor team (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 + * @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 (2003-2009) + * @author Froxlor team (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 .= ' ' . "\n"; $php_options_text .= ' ' . "\n"; $php_options_text .= ' SetHandler proxy:unix:' . $domain['fpm_socket'] . '|fcgi://localhost' . "\n"; $php_options_text .= ' ' . "\n"; $php_options_text .= ' ' . "\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 .= ' ' . "\n"; + $php_options_text .= ' ' . "\n"; if ($phpconfig['pass_authorizationheader'] == '1') { $php_options_text .= ' CGIPassAuth On' . "\n"; } @@ -75,7 +154,7 @@ class ApacheFcgi extends Apache $php_options_text .= ' ' . "\n"; } elseif ($phpconfig['pass_authorizationheader'] == '1') { // allow Pass of Authorization header - $php_options_text .= ' ' . "\n"; + $php_options_text .= ' ' . "\n"; $php_options_text .= ' CGIPassAuth On' . "\n"; $php_options_text .= ' ' . "\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 .= ' ' . "\n"; + $php_options_text .= ' ' . "\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 .= ' ' . "\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 .= ' ' . "\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 .= ' ' . "\n"; + $php_options_text .= ' ' . "\n"; $file_extensions = explode(' ', $phpconfig['file_extensions']); $php_options_text .= ' ' . "\n"; $php_options_text .= ' SetHandler fcgid-script' . "\n"; @@ -133,7 +212,7 @@ class ApacheFcgi extends Apache $php_options_text .= ' ' . "\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); - } - } } diff --git a/lib/Froxlor/Cron/Http/ConfigIO.php b/lib/Froxlor/Cron/Http/ConfigIO.php index 2859b103..740514e4 100644 --- a/lib/Froxlor/Cron/Http/ConfigIO.php +++ b/lib/Froxlor/Cron/Http/ConfigIO.php @@ -1,25 +1,38 @@ - * @author Froxlor team (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 + * @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; } } diff --git a/lib/Froxlor/Cron/Http/DomainSSL.php b/lib/Froxlor/Cron/Http/DomainSSL.php index 82d7c56d..2e263d95 100644 --- a/lib/Froxlor/Cron/Http/DomainSSL.php +++ b/lib/Froxlor/Cron/Http/DomainSSL.php @@ -1,26 +1,35 @@ - * @author Froxlor team (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 + * @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']); } diff --git a/lib/Froxlor/Cron/Http/HttpConfigBase.php b/lib/Froxlor/Cron/Http/HttpConfigBase.php index 4a82f2b7..d23be3ec 100644 --- a/lib/Froxlor/Cron/Http/HttpConfigBase.php +++ b/lib/Froxlor/Cron/Http/HttpConfigBase.php @@ -1,25 +1,41 @@ (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 + * @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; diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index da0c796a..38401d98 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -1,31 +1,44 @@ - * @author Froxlor team (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 + * @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. 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.) 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 = <<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. 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.) 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 = << $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)); - } } diff --git a/lib/Froxlor/Cron/Http/Lighttpd.php b/lib/Froxlor/Cron/Http/Lighttpd.php index 04355999..9342630b 100644 --- a/lib/Froxlor/Cron/Http/Lighttpd.php +++ b/lib/Froxlor/Cron/Http/Lighttpd.php @@ -1,38 +1,59 @@ (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Cron - * - * @todo ssl-redirect to non-standard port + * 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 + * @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\Domain\Domain; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; +use Froxlor\Http\Directory; +use Froxlor\Http\Statistics; +use Froxlor\Settings; +use Froxlor\Validate\Validate; +use PDO; + +/** + * @author Florian Lippert (2003-2009) + * @author Froxlor team (2010-) + * + * @todo ssl-redirect to non-standard port */ class Lighttpd extends HttpConfigBase { // protected - protected $lighttpd_data = array(); + protected $lighttpd_data = []; - protected $needed_htpasswds = array(); + protected $needed_htpasswds = []; protected $auth_backend_loaded = false; - protected $htpasswd_files = array(); + protected $htpasswd_files = []; protected $mod_accesslog_loaded = "0"; @@ -48,7 +69,7 @@ class Lighttpd extends HttpConfigBase { $result_ipsandports_stmt = Database::query("SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` ORDER BY `ip` ASC, `port` ASC"); - while ($row_ipsandports = $result_ipsandports_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row_ipsandports = $result_ipsandports_stmt->fetch(PDO::FETCH_ASSOC)) { if (filter_var($row_ipsandports['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { $ip = '[' . $row_ipsandports['ip'] . ']'; $port = $row_ipsandports['port']; @@ -59,10 +80,10 @@ class Lighttpd extends HttpConfigBase $ipv6 = ''; } - $this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'lighttpd::createIpPort: creating ip/port settings for ' . $ip . ":" . $port); - $vhost_filename = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/10_froxlor_ipandport_' . trim(str_replace(':', '.', $row_ipsandports['ip']), '.') . '.' . $row_ipsandports['port'] . '.conf'); + $this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'lighttpd::createIpPort: creating ip/port settings for ' . $ip . ":" . $port); + $vhost_filename = FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/10_froxlor_ipandport_' . trim(str_replace(':', '.', $row_ipsandports['ip']), '.') . '.' . $row_ipsandports['port'] . '.conf'); - if (! isset($this->lighttpd_data[$vhost_filename])) { + if (!isset($this->lighttpd_data[$vhost_filename])) { $this->lighttpd_data[$vhost_filename] = ''; } @@ -102,12 +123,12 @@ class Lighttpd extends HttpConfigBase } } - if (! $is_redirect) { + if (!$is_redirect) { /** * dirprotection, see #72 * * @todo use better regex for this, deferred until 0.9.5 - * + * * $this->lighttpd_data[$vhost_filename].= ' $HTTP["url"] =~ "^/(.+)\/(.+)\.php" {' . "\n"; * $this->lighttpd_data[$vhost_filename].= ' url.access-deny = ("")' . "\n"; * $this->lighttpd_data[$vhost_filename].= ' }' . "\n"; @@ -116,22 +137,22 @@ class Lighttpd extends HttpConfigBase /** * own php-fpm vhost */ - if ((int) Settings::Get('phpfpm.enabled') == 1 && (int) Settings::Get('phpfpm.enabled_ownvhost') == 1) { + if ((int)Settings::Get('phpfpm.enabled') == 1 && (int)Settings::Get('phpfpm.enabled_ownvhost') == 1) { // 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( + $fpm_config = Database::pexecute_first($fpm_sel_stmt, [ 'phpconfigid' => Settings::Get('phpfpm.vhost_defaultini') - )); - $domain = array( + ]); + $domain = [ 'id' => 'none', 'domain' => Settings::Get('system.hostname'), 'adminid' => 1, /* first admin-user (superadmin) */ - 'mod_fcgid_starter' => - 1, - 'mod_fcgid_maxrequests' => - 1, + 'mod_fcgid_starter' => -1, + 'mod_fcgid_maxrequests' => -1, 'guid' => Settings::Get('phpfpm.vhost_httpuser'), 'openbasedir' => 0, 'email' => Settings::Get('panel.adminmail'), @@ -139,7 +160,7 @@ class Lighttpd extends HttpConfigBase 'documentroot' => $mypath, 'customerroot' => $mypath, 'fpm_config_id' => isset($fpm_config['id']) ? $fpm_config['id'] : 1 - ); + ]; $php = new PhpInterface($domain); @@ -153,7 +174,7 @@ class Lighttpd extends HttpConfigBase $this->lighttpd_data[$vhost_filename] .= "\t" . ')' . "\n"; $this->lighttpd_data[$vhost_filename] .= ' )' . "\n"; } else { - $domain = array( + $domain = [ 'id' => 'none', 'domain' => Settings::Get('system.hostname'), 'adminid' => 1, /* first admin-user (superadmin) */ @@ -163,16 +184,16 @@ class Lighttpd extends HttpConfigBase 'loginname' => 'froxlor.panel', 'documentroot' => $mypath, 'customerroot' => $mypath - ); + ]; } } else { // fallback of froxlor domain-data for processSpecialConfigTemplate() - $domain = array( + $domain = [ 'domain' => Settings::Get('system.hostname'), 'loginname' => 'froxlor.panel', 'documentroot' => $mypath, 'customerroot' => $mypath - ); + ]; } if ($row_ipsandports['specialsettings'] != '' && ($row_ipsandports['ssl'] == '0' || ($row_ipsandports['ssl'] == '1' && Settings::Get('system.use_ssl') == '1' && $row_ipsandports['include_specialsettings'] == '1'))) { @@ -183,18 +204,17 @@ class Lighttpd extends HttpConfigBase } if ($row_ipsandports['ssl'] == '1') { - if ($row_ipsandports['ssl_specialsettings'] != '') { $this->lighttpd_data[$vhost_filename] .= $this->processSpecialConfigTemplate($row_ipsandports['ssl_specialsettings'], $domain, $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n"; } // check for required fallback - if (($row_ipsandports['ssl_cert_file'] == '' || ! file_exists($row_ipsandports['ssl_cert_file'])) && (Settings::Get('system.le_froxlor_enabled') == '0' || $this->froxlorVhostHasLetsEncryptCert() == false)) { + if (($row_ipsandports['ssl_cert_file'] == '' || !file_exists($row_ipsandports['ssl_cert_file'])) && (Settings::Get('system.le_froxlor_enabled') == '0' || $this->froxlorVhostHasLetsEncryptCert() == false)) { $row_ipsandports['ssl_cert_file'] = Settings::Get('system.ssl_cert_file'); - if (! file_exists($row_ipsandports['ssl_cert_file'])) { + if (!file_exists($row_ipsandports['ssl_cert_file'])) { // explicitly disable ssl for this vhost $row_ipsandports['ssl_cert_file'] = ""; - $this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Disabling SSL-vhost for "' . Settings::Get('system.hostname') . '"'); + $this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Disabling SSL-vhost for "' . Settings::Get('system.hostname') . '"'); } } @@ -202,7 +222,7 @@ class Lighttpd extends HttpConfigBase $row_ipsandports['ssl_ca_file'] = Settings::Get('system.ssl_ca_file'); } - $domain = array( + $domain = [ 'id' => 0, 'domain' => Settings::Get('system.hostname'), 'adminid' => 1, /* first admin-user (superadmin) */ @@ -210,7 +230,7 @@ class Lighttpd extends HttpConfigBase 'documentroot' => $mypath, 'customerroot' => $mypath, 'parentdomainid' => 0 - ); + ]; // override corresponding array values $domain['ssl_cert_file'] = $row_ipsandports['ssl_cert_file']; @@ -225,18 +245,17 @@ class Lighttpd extends HttpConfigBase $dssl->setDomainSSLFilesArray($domain); if ($domain['ssl_cert_file'] != '') { - // check for existence, #1485 - if (! file_exists($domain['ssl_cert_file'])) { - $this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, $ip . ':' . $port . ' :: certificate file "' . $domain['ssl_cert_file'] . '" does not exist! Cannot create ssl-directives'); + if (!file_exists($domain['ssl_cert_file'])) { + $this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, $ip . ':' . $port . ' :: certificate file "' . $domain['ssl_cert_file'] . '" does not exist! Cannot create ssl-directives'); echo $ip . ':' . $port . ' :: certificate file "' . $domain['ssl_cert_file'] . '" does not exist! Cannot create SSL-directives' . "\n"; } else { $this->lighttpd_data[$vhost_filename] .= 'ssl.engine = "enable"' . "\n"; $this->lighttpd_data[$vhost_filename] .= 'ssl.use-compression = "disable"' . "\n"; - if (! empty(Settings::Get('system.dhparams_file'))) { - $dhparams = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.dhparams_file')); - if (! file_exists($dhparams)) { - \Froxlor\FileDir::safe_exec('openssl dhparam -out ' . escapeshellarg($dhparams) . ' 4096'); + if (!empty(Settings::Get('system.dhparams_file'))) { + $dhparams = FileDir::makeCorrectFile(Settings::Get('system.dhparams_file')); + if (!file_exists($dhparams)) { + FileDir::safe_exec('openssl dhparam -out ' . escapeshellarg($dhparams) . ' 4096'); } $this->lighttpd_data[$vhost_filename] .= 'ssl.dh-file = "' . $dhparams . '"' . "\n"; $this->lighttpd_data[$vhost_filename] .= 'ssl.ec-curve = "secp384r1"' . "\n"; @@ -245,15 +264,15 @@ class Lighttpd extends HttpConfigBase $this->lighttpd_data[$vhost_filename] .= 'ssl.use-sslv3 = "disable"' . "\n"; $this->lighttpd_data[$vhost_filename] .= 'ssl.cipher-list = "' . Settings::Get('system.ssl_cipher_list') . '"' . "\n"; $this->lighttpd_data[$vhost_filename] .= 'ssl.honor-cipher-order = "enable"' . "\n"; - $this->lighttpd_data[$vhost_filename] .= 'ssl.pemfile = "' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_cert_file']) . '"' . "\n"; + $this->lighttpd_data[$vhost_filename] .= 'ssl.pemfile = "' . FileDir::makeCorrectFile($domain['ssl_cert_file']) . '"' . "\n"; if ($domain['ssl_ca_file'] != '') { // check for existence, #1485 - if (! file_exists($domain['ssl_ca_file'])) { - $this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, $ip . ':' . $port . ' :: certificate CA file "' . $domain['ssl_ca_file'] . '" does not exist! Cannot create ssl-directives'); + if (!file_exists($domain['ssl_ca_file'])) { + $this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, $ip . ':' . $port . ' :: certificate CA file "' . $domain['ssl_ca_file'] . '" does not exist! Cannot create ssl-directives'); echo $ip . ':' . $port . ' :: certificate CA file "' . $domain['ssl_ca_file'] . '" does not exist! SSL-directives might not be working' . "\n"; } else { - $this->lighttpd_data[$vhost_filename] .= 'ssl.ca-file = "' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_ca_file']) . '"' . "\n"; + $this->lighttpd_data[$vhost_filename] .= 'ssl.ca-file = "' . FileDir::makeCorrectFile($domain['ssl_ca_file']) . '"' . "\n"; } } } @@ -284,137 +303,46 @@ class Lighttpd extends HttpConfigBase $this->createStandardErrorHandler(); } - /** - * define a default server.error-handler-404-statement, bug #unknown-yet - */ - private function createStandardErrorHandler() - { - if (Settings::Get('defaultwebsrverrhandler.enabled') == '1' && Settings::Get('defaultwebsrverrhandler.err404') != '') { - $vhost_filename = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/05_froxlor_default_errorhandler.conf'); - - if (! isset($this->lighttpd_data[$vhost_filename])) { - $this->lighttpd_data[$vhost_filename] = ''; - } - - $defhandler = Settings::Get('defaultwebsrverrhandler.err404'); - if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) { - $defhandler = \Froxlor\FileDir::makeCorrectFile($defhandler); - } - $this->lighttpd_data[$vhost_filename] = 'server.error-handler-404 = "' . $defhandler . '"'; - } - } - - protected function createHtaccess($domain) - { - $needed_htpasswds = array(); - $result_htpasswds_stmt = Database::prepare(" - SELECT * FROM " . TABLE_PANEL_HTPASSWDS . " - WHERE `path` LIKE :docroot - "); - Database::pexecute($result_htpasswds_stmt, array( - 'docroot' => $domain['documentroot'] . '%' - )); - - $htaccess_text = ''; - while ($row_htpasswds = $result_htpasswds_stmt->fetch(\PDO::FETCH_ASSOC)) { - $row_htpasswds['path'] = \Froxlor\FileDir::makeCorrectDir($row_htpasswds['path']); - \Froxlor\FileDir::mkDirWithCorrectOwnership($domain['documentroot'], $row_htpasswds['path'], $domain['guid'], $domain['guid']); - - $filename = $row_htpasswds['customerid'] . '-' . md5($row_htpasswds['path']) . '.htpasswd'; - - if (! in_array($row_htpasswds['path'], $needed_htpasswds)) { - if (! isset($this->needed_htpasswds[$filename])) { - $this->needed_htpasswds[$filename] = ''; - } - - if (! strstr($this->needed_htpasswds[$filename], $row_htpasswds['username'] . ':' . $row_htpasswds['password'])) { - $this->needed_htpasswds[$filename] .= $row_htpasswds['username'] . ':' . $row_htpasswds['password'] . "\n"; - } - - $htaccess_path = substr($row_htpasswds['path'], strlen($domain['documentroot']) - 1); - $htaccess_path = \Froxlor\FileDir::makeCorrectDir($htaccess_path); - - $htaccess_text .= ' $HTTP["url"] =~ "^' . $htaccess_path . '" {' . "\n"; - $htaccess_text .= ' auth.backend = "htpasswd"' . "\n"; - $htaccess_text .= ' auth.backend.htpasswd.userfile = "' . \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_htpasswddir') . '/' . $filename) . '"' . "\n"; - $htaccess_text .= ' auth.require = ( ' . "\n"; - $htaccess_text .= ' "' . $htaccess_path . '" =>' . "\n"; - $htaccess_text .= ' (' . "\n"; - $htaccess_text .= ' "method" => "basic",' . "\n"; - $htaccess_text .= ' "realm" => "' . $row_htpasswds['authname'] . '",' . "\n"; - $htaccess_text .= ' "require" => "valid-user"' . "\n"; - $htaccess_text .= ' )' . "\n"; - $htaccess_text .= ' )' . "\n"; - $htaccess_text .= ' }' . "\n"; - - $needed_htpasswds[] = $row_htpasswds['path']; - } - } - - return $htaccess_text; - } - - public function createVirtualHosts() - { - return; - } - - public function createFileDirOptions() - { - return; - } - - protected function composePhpOptions(&$domain) - { - return; - } - - public function createOwnVhostStarter() - { - return; - } - protected function createLighttpdHosts($ipid, $ssl, $vhost_filename) { $domains = WebserverBase::getVhostsToCreate(); - $included_vhosts = array(); + $included_vhosts = []; foreach ($domains as $domain) { - if (is_dir(Settings::Get('system.apacheconf_vhost'))) { - \Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg(\Froxlor\FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost') . '/vhosts/'))); + FileDir::safe_exec('mkdir -p ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost') . '/vhosts/'))); // determine correct include-path: // e.g. '/etc/lighttpd/conf-enabled/vhosts/ has to become' // 'conf-enabled/vhosts/' (damn debian, but luckily works too on other distros) - $_tmp_path = substr(\Froxlor\FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')), 0, - 1); + $_tmp_path = substr(FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')), 0, -1); $_pos = strrpos($_tmp_path, '/'); $_inc_path = substr($_tmp_path, $_pos + 1); // maindomain - if ((int) $domain['parentdomainid'] == 0 && \Froxlor\Domain\Domain::isCustomerStdSubdomain((int) $domain['id']) == false && ((int) $domain['ismainbutsubto'] == 0 || \Froxlor\Domain\Domain::domainMainToSubExists($domain['ismainbutsubto']) == false)) { + if ((int)$domain['parentdomainid'] == 0 && Domain::isCustomerStdSubdomain((int)$domain['id']) == false && ((int)$domain['ismainbutsubto'] == 0 || Domain::domainMainToSubExists($domain['ismainbutsubto']) == false)) { $vhost_no = '50'; - } elseif ((int) $domain['parentdomainid'] == 0 && \Froxlor\Domain\Domain::isCustomerStdSubdomain((int) $domain['id']) == false && (int) $domain['ismainbutsubto'] > 0) { + } elseif ((int)$domain['parentdomainid'] == 0 && Domain::isCustomerStdSubdomain((int)$domain['id']) == false && (int)$domain['ismainbutsubto'] > 0) { // sub-but-main-domain $vhost_no = '51'; } else { // subdomains // number of dots in a domain specifies it's position (and depth of subdomain) starting at 89 going downwards on higher depth - $vhost_no = (string) (90 - substr_count($domain['domain'], ".") + 1); + $vhost_no = (string)(90 - substr_count($domain['domain'], ".") + 1); } if ($ssl == '1') { - $vhost_no = (int) $vhost_no += 10; + $vhost_no = (int)$vhost_no += 10; } - $vhost_filename = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/vhosts/' . $vhost_no . '_' . $domain['domain'] . '.conf'); + $vhost_filename = FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/vhosts/' . $vhost_no . '_' . $domain['domain'] . '.conf'); $included_vhosts[] = $_inc_path . '/vhosts/' . $vhost_no . '_' . $domain['domain'] . '.conf'; } - if (! isset($this->lighttpd_data[$vhost_filename])) { + if (!isset($this->lighttpd_data[$vhost_filename])) { $this->lighttpd_data[$vhost_filename] = ''; } - if ((! empty($this->lighttpd_data[$vhost_filename]) && ! is_dir(Settings::Get('system.apacheconf_vhost'))) || is_dir(Settings::Get('system.apacheconf_vhost'))) { + if ((!empty($this->lighttpd_data[$vhost_filename]) && !is_dir(Settings::Get('system.apacheconf_vhost'))) || is_dir(Settings::Get('system.apacheconf_vhost'))) { if ($ssl == '1') { $ssl_vhost = true; } else { @@ -433,7 +361,7 @@ class Lighttpd extends HttpConfigBase protected function getVhostContent($domain, $ssl_vhost = false, $ipid = 0) { - if ($ssl_vhost === true && $domain['ssl'] != '1' && $domain['ssl_enabled'] != '1' && $domain['ssl_redirect'] != '1') { + if ($ssl_vhost === true && $domain['ssl'] != '1' && $domain['ssl_enabled'] != '1' && $domain['ssl_redirect'] != '1') { return ''; } @@ -453,9 +381,9 @@ class Lighttpd extends HttpConfigBase WHERE `dip`.`id_domain` = :domainid AND `ip`.`ssl` = '1' AND `ip`.`port` != 443 ORDER BY `ip`.`ssl_cert_file` DESC, `ip`.`port` LIMIT 1;"); - $ssldestport = Database::pexecute_first($ssldestport_stmt, array( + $ssldestport = Database::pexecute_first($ssldestport_stmt, [ 'domainid' => $domain['id'] - )); + ]); if ($ssldestport && $ssldestport['port'] != '') { $_sslport = ":" . $ssldestport['port']; @@ -471,15 +399,14 @@ class Lighttpd extends HttpConfigBase $uri = $domain['documentroot']; // Get domain's redirect code - $code = \Froxlor\Domain\Domain::getDomainRedirectCode($domain['id']); + $code = Domain::getDomainRedirectCode($domain['id']); $vhost_content .= ' url.redirect-code = ' . $code . "\n"; $vhost_content .= ' url.redirect = (' . "\n"; $vhost_content .= ' "^/(.*)$" => "' . $uri . '$1"' . "\n"; $vhost_content .= ' )' . "\n"; } else { - - \Froxlor\FileDir::mkDirWithCorrectOwnership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true, true); + FileDir::mkDirWithCorrectOwnership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true, true); $only_webroot = false; if ($ssl_vhost === false && $domain['ssl_redirect'] == '1') { @@ -487,7 +414,7 @@ class Lighttpd extends HttpConfigBase } $vhost_content .= $this->getWebroot($domain, $ssl_vhost); - if (! $only_webroot) { + if (!$only_webroot) { if ($this->deactivated == false) { $vhost_content .= $this->createHtaccess($domain); $vhost_content .= $this->createPathOptions($domain); @@ -498,9 +425,9 @@ class Lighttpd extends HttpConfigBase SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `id` = :id "); - $ipandport = Database::pexecute_first($ipandport_stmt, array( + $ipandport = Database::pexecute_first($ipandport_stmt, [ 'id' => $ipid - )); + ]); $domain['ip'] = $ipandport['ip']; $domain['port'] = $ipandport['port']; @@ -551,257 +478,9 @@ class Lighttpd extends HttpConfigBase return $vhost_content; } - protected function getSslSettings($domain, $ssl_vhost) - { - $ssl_settings = ''; - - if ($ssl_vhost === true && $domain['ssl'] == '1' && (int) Settings::Get('system.use_ssl') == 1) { - if ($domain['ssl_cert_file'] == '' || ! file_exists($domain['ssl_cert_file'])) { - $domain['ssl_cert_file'] = Settings::Get('system.ssl_cert_file'); - if (! file_exists($domain['ssl_cert_file'])) { - // explicitly disable ssl for this vhost - $domain['ssl_cert_file'] = ""; - $this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Disabling SSL-vhost for "' . $domain['domain'] . '"'); - } - } - - if ($domain['ssl_ca_file'] == '') { - $domain['ssl_ca_file'] = Settings::Get('system.ssl_ca_file'); - } - - if ($domain['ssl_cert_file'] != '') { - - $ssl_cipher_list = ($domain['override_tls'] == '1' && ! empty($domain['ssl_cipher_list'])) ? $domain['ssl_cipher_list'] : Settings::Get('system.ssl_cipher_list'); - - // ssl.engine only necessary once in the ip/port vhost (SERVER['socket'] condition) - // $ssl_settings .= 'ssl.engine = "enable"' . "\n"; - $ssl_settings .= 'ssl.use-compression = "disable"' . "\n"; - if (! empty(Settings::Get('system.dhparams_file'))) { - $dhparams = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.dhparams_file')); - if (! file_exists($dhparams)) { - \Froxlor\FileDir::safe_exec('openssl dhparam -out ' . escapeshellarg($dhparams) . ' 4096'); - } - $ssl_settings .= 'ssl.dh-file = "' . $dhparams . '"' . "\n"; - $ssl_settings .= 'ssl.ec-curve = "secp384r1"' . "\n"; - } - $ssl_settings .= 'ssl.use-sslv2 = "disable"' . "\n"; - $ssl_settings .= 'ssl.use-sslv3 = "disable"' . "\n"; - $ssl_settings .= 'ssl.cipher-list = "' . $ssl_cipher_list . '"' . "\n"; - $ssl_settings .= 'ssl.honor-cipher-order = ' . ($domain['ssl_honorcipherorder'] == '1' ? '"enable"' : '"disable"') . "\n"; - $ssl_settings .= 'ssl.pemfile = "' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_cert_file']) . '"' . "\n"; - - if ($domain['ssl_ca_file'] != '') { - $ssl_settings .= 'ssl.ca-file = "' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_ca_file']) . '"' . "\n"; - } - - if ($domain['hsts'] >= 0) { - - $ssl_settings .= '$HTTP["scheme"] == "https" { setenv.add-response-header = ( "Strict-Transport-Security" => "max-age=' . $domain['hsts']; - if ($domain['hsts_sub'] == 1) { - $ssl_settings .= '; includeSubDomains'; - } - if ($domain['hsts_preload'] == 1) { - $ssl_settings .= '; preload'; - } - $ssl_settings .= '") }' . "\n"; - } - } - } - return $ssl_settings; - } - - protected function getLogFiles($domain) - { - $logfiles_text = ''; - - $speciallogfile = ''; - if ($domain['speciallogfile'] == '1') { - if ($domain['parentdomainid'] == '0') { - $speciallogfile = '-' . $domain['domain']; - } else { - $speciallogfile = '-' . $domain['parentdomain']; - } - } - - // The normal access/error - logging is enabled - // error log cannot be set conditionally see - // https://redmine.lighttpd.net/issues/665 - if ($domain['writeaccesslog']) { - $access_log = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-access.log'); - // Create the logfile if it does not exist (fixes #46) - touch($access_log); - chown($access_log, Settings::Get('system.httpuser')); - chgrp($access_log, Settings::Get('system.httpgroup')); - - $logfiles_text .= ' accesslog.filename = "' . $access_log . '"' . "\n"; - } - - if (Settings::Get('system.awstats_enabled') == '1') { - - if ((int) $domain['parentdomainid'] == 0) { - // prepare the aliases and subdomains for stats config files - $server_alias = ''; - $alias_domains_stmt = Database::prepare(" - SELECT `domain`, `iswildcarddomain`, `wwwserveralias` - FROM `" . TABLE_PANEL_DOMAINS . "` - WHERE `aliasdomain` = :domainid OR `parentdomainid` = :domainid - "); - Database::pexecute($alias_domains_stmt, array( - 'domainid' => $domain['id'] - )); - - while (($alias_domain = $alias_domains_stmt->fetch(\PDO::FETCH_ASSOC)) !== false) { - - $server_alias .= ' ' . $alias_domain['domain'] . ' '; - - if ($alias_domain['iswildcarddomain'] == '1') { - $server_alias .= '*.' . $domain['domain']; - } else { - if ($alias_domain['wwwserveralias'] == '1') { - $server_alias .= 'www.' . $alias_domain['domain']; - } else { - $server_alias .= ''; - } - } - } - - if ($domain['iswildcarddomain'] == '1') { - $alias = '*.' . $domain['domain']; - } else { - if ($domain['wwwserveralias'] == '1') { - $alias = 'www.' . $domain['domain']; - } else { - $alias = ''; - } - } - - // After inserting the AWStats information, - // be sure to build the awstats conf file as well - // and chown it using $awstats_params, #258 - // Bug 960 + Bug 970 : Use full $domain instead of custom $awstats_params as following classes depend on the information - \Froxlor\Http\Statistics::createAWStatsConf(Settings::Get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-access.log', $domain['domain'], $alias . $server_alias, $domain['customerroot'], $domain); - } - } - - return $logfiles_text; - } - - protected function createPathOptions($domain) - { - $result_stmt = Database::prepare(" - SELECT * FROM " . TABLE_PANEL_HTACCESS . " - WHERE `path` LIKE :docroot - "); - Database::pexecute($result_stmt, array( - 'docroot' => $domain['documentroot'] . '%' - )); - - $path_options = ''; - $error_string = ''; - - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { - - if (! empty($row['error404path'])) { - $defhandler = $row['error404path']; - if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) { - $defhandler = \Froxlor\FileDir::makeCorrectFile($domain['documentroot'] . '/' . $defhandler); - } - $error_string .= ' server.error-handler-404 = "' . $defhandler . '"' . "\n\n"; - } - - if ($row['options_indexes'] != '0') { - if (! empty($error_string)) { - $path_options .= $error_string; - // reset $error_string here to prevent duplicate entries - $error_string = ''; - } - - $path = \Froxlor\FileDir::makeCorrectDir(substr($row['path'], strlen($domain['documentroot']) - 1)); - \Froxlor\FileDir::mkDirWithCorrectOwnership($domain['documentroot'], $row['path'], $domain['guid'], $domain['guid']); - - // We need to remove the last slash, otherwise the regex wouldn't work - if ($row['path'] != $domain['documentroot']) { - $path = substr($path, 0, - 1); - } - $path_options .= ' $HTTP["url"] =~ "^' . $path . '($|/)" {' . "\n"; - $path_options .= "\t" . 'dir-listing.activate = "enable"' . "\n"; - $path_options .= ' }' . "\n\n"; - } else { - $path_options = $error_string; - } - - if (\Froxlor\Customer\Customer::customerHasPerlEnabled($domain['customerid']) && $row['options_cgi'] != '0') { - $path = \Froxlor\FileDir::makeCorrectDir(substr($row['path'], strlen($domain['documentroot']) - 1)); - \Froxlor\FileDir::mkDirWithCorrectOwnership($domain['documentroot'], $row['path'], $domain['guid'], $domain['guid']); - - // We need to remove the last slash, otherwise the regex wouldn't work - if ($row['path'] != $domain['documentroot']) { - $path = substr($path, 0, - 1); - } - $path_options .= ' $HTTP["url"] =~ "^' . $path . '($|/)" {' . "\n"; - $path_options .= "\t" . 'cgi.assign = (' . "\n"; - $path_options .= "\t\t" . '".pl" => "' . \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.perl_path')) . '",' . "\n"; - $path_options .= "\t\t" . '".cgi" => "' . \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.perl_path')) . '"' . "\n"; - $path_options .= "\t" . ')' . "\n"; - $path_options .= ' }' . "\n\n"; - } - } - - return $path_options; - } - - protected function getDirOptions($domain) - { - $result_stmt = Database::prepare(" - SELECT * FROM " . TABLE_PANEL_HTPASSWDS . " - WHERE `customerid` = :customerid - "); - Database::pexecute($result_stmt, array( - 'customerid' => $domain['customerid'] - )); - - $diroption_text = ''; - while ($row_htpasswds = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { - if ($this->auth_backend_loaded[$domain['ipandport']] != 'yes' && $this->auth_backend_loaded[$domain['ssl_ipandport']] != 'yes') { - $filename = $domain['customerid'] . '.htpasswd'; - - if ($this->auth_backend_loaded[$domain['ipandport']] != 'yes') { - $this->auth_backend_loaded[$domain['ipandport']] = 'yes'; - $diroption_text .= 'auth.backend = "htpasswd"' . "\n"; - $diroption_text .= 'auth.backend.htpasswd.userfile = "' . \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_htpasswddir') . '/' . $filename) . '"' . "\n"; - $this->needed_htpasswds[$filename] = $row_htpasswds['username'] . ':' . $row_htpasswds['password'] . "\n"; - $diroption_text .= 'auth.require = ( ' . "\n"; - } elseif ($this->auth_backend_loaded[$domain['ssl_ipandport']] != 'yes') { - $this->auth_backend_loaded[$domain['ssl_ipandport']] = 'yes'; - $diroption_text .= 'auth.backend= "htpasswd"' . "\n"; - $diroption_text .= 'auth.backend.htpasswd.userfile = "' . \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_htpasswddir') . '/' . $filename) . '"' . "\n"; - $this->needed_htpasswds[$filename] = $row_htpasswds['username'] . ':' . $row_htpasswds['password'] . "\n"; - $diroption_text .= 'auth.require = ( ' . "\n"; - } - } - - $diroption_text .= '"' . \Froxlor\FileDir::makeCorrectDir($row_htpasswds['path']) . '" =>' . "\n"; - $diroption_text .= '(' . "\n"; - $diroption_text .= ' "method" => "basic",' . "\n"; - $diroption_text .= ' "realm" => "' . $row_htpasswds['authname'] . '",' . "\n"; - $diroption_text .= ' "require" => "valid-user"' . "\n"; - $diroption_text .= ')' . "\n"; - - if ($this->auth_backend_loaded[$domain['ssl_ipandport']] == 'yes') { - $this->needed_htpasswds[$domain['ssl_ipandport']] .= $diroption_text; - } - - if ($this->auth_backend_loaded[$domain['ipandport']] != 'yes') { - $this->needed_htpasswds[$domain['ipandport']] .= $diroption_text; - } - } - - return ' auth.backend.htpasswd.userfile = "' . \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_htpasswddir') . '/' . $filename) . '"' . "\n"; - } - protected function getServerNames($domain) { - $server_string = array(); + $server_string = []; $domain_name = str_replace('.', '\.', $domain['domain']); if ($domain['iswildcarddomain'] == '1') { @@ -819,11 +498,11 @@ class Lighttpd extends HttpConfigBase FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `aliasdomain` = :domainid "); - Database::pexecute($alias_domains_stmt, array( + Database::pexecute($alias_domains_stmt, [ 'domainid' => $domain['id'] - )); + ]); - while (($alias_domain = $alias_domains_stmt->fetch(\PDO::FETCH_ASSOC)) !== false) { + while (($alias_domain = $alias_domains_stmt->fetch(PDO::FETCH_ASSOC)) !== false) { $alias_domain_name = str_replace('.', '\.', $alias_domain['domain']); if ($alias_domain['iswildcarddomain'] == '1') { @@ -838,7 +517,7 @@ class Lighttpd extends HttpConfigBase } $servernames_text = ''; - for ($i = 0; $i < sizeof($server_string); $i ++) { + for ($i = 0; $i < sizeof($server_string); $i++) { $data = $server_string[$i]; if (sizeof($server_string) > 1) { @@ -871,7 +550,7 @@ class Lighttpd extends HttpConfigBase if ($domain['deactivated'] == '1' && Settings::Get('system.deactivateddocroot') != '') { $webroot_text .= ' # Using docroot for deactivated users...' . "\n"; - $webroot_text .= ' server.document-root = "' . \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.deactivateddocroot')) . "\"\n"; + $webroot_text .= ' server.document-root = "' . FileDir::makeCorrectDir(Settings::Get('system.deactivateddocroot')) . "\"\n"; $this->deactivated = true; } else { if ($ssl === false && $domain['ssl_redirect'] == '1') { @@ -889,7 +568,7 @@ class Lighttpd extends HttpConfigBase $webroot_text .= "\t" . '"/" => "' . $redirect_domain . '"' . "\n"; $webroot_text .= ' )' . "\n"; } else { - $webroot_text .= ' server.document-root = "' . \Froxlor\FileDir::makeCorrectDir($domain['documentroot']) . "\"\n"; + $webroot_text .= ' server.document-root = "' . FileDir::makeCorrectDir($domain['documentroot']) . "\"\n"; } $this->deactivated = false; } @@ -897,6 +576,124 @@ class Lighttpd extends HttpConfigBase return $webroot_text; } + protected function createHtaccess($domain) + { + $needed_htpasswds = []; + $result_htpasswds_stmt = Database::prepare(" + SELECT * FROM " . TABLE_PANEL_HTPASSWDS . " + WHERE `path` LIKE :docroot + "); + Database::pexecute($result_htpasswds_stmt, [ + 'docroot' => $domain['documentroot'] . '%' + ]); + + $htaccess_text = ''; + while ($row_htpasswds = $result_htpasswds_stmt->fetch(PDO::FETCH_ASSOC)) { + $row_htpasswds['path'] = FileDir::makeCorrectDir($row_htpasswds['path']); + FileDir::mkDirWithCorrectOwnership($domain['documentroot'], $row_htpasswds['path'], $domain['guid'], $domain['guid']); + + $filename = $row_htpasswds['customerid'] . '-' . md5($row_htpasswds['path']) . '.htpasswd'; + + if (!in_array($row_htpasswds['path'], $needed_htpasswds)) { + if (!isset($this->needed_htpasswds[$filename])) { + $this->needed_htpasswds[$filename] = ''; + } + + if (!strstr($this->needed_htpasswds[$filename], $row_htpasswds['username'] . ':' . $row_htpasswds['password'])) { + $this->needed_htpasswds[$filename] .= $row_htpasswds['username'] . ':' . $row_htpasswds['password'] . "\n"; + } + + $htaccess_path = substr($row_htpasswds['path'], strlen($domain['documentroot']) - 1); + $htaccess_path = FileDir::makeCorrectDir($htaccess_path); + + $htaccess_text .= ' $HTTP["url"] =~ "^' . $htaccess_path . '" {' . "\n"; + $htaccess_text .= ' auth.backend = "htpasswd"' . "\n"; + $htaccess_text .= ' auth.backend.htpasswd.userfile = "' . FileDir::makeCorrectFile(Settings::Get('system.apacheconf_htpasswddir') . '/' . $filename) . '"' . "\n"; + $htaccess_text .= ' auth.require = ( ' . "\n"; + $htaccess_text .= ' "' . $htaccess_path . '" =>' . "\n"; + $htaccess_text .= ' (' . "\n"; + $htaccess_text .= ' "method" => "basic",' . "\n"; + $htaccess_text .= ' "realm" => "' . $row_htpasswds['authname'] . '",' . "\n"; + $htaccess_text .= ' "require" => "valid-user"' . "\n"; + $htaccess_text .= ' )' . "\n"; + $htaccess_text .= ' )' . "\n"; + $htaccess_text .= ' }' . "\n"; + + $needed_htpasswds[] = $row_htpasswds['path']; + } + } + + return $htaccess_text; + } + + protected function createPathOptions($domain) + { + $result_stmt = Database::prepare(" + SELECT * FROM " . TABLE_PANEL_HTACCESS . " + WHERE `path` LIKE :docroot + "); + Database::pexecute($result_stmt, [ + 'docroot' => $domain['documentroot'] . '%' + ]); + + $path_options = ''; + $error_string = ''; + + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + if (!empty($row['error404path'])) { + $defhandler = $row['error404path']; + if (!Validate::validateUrl($defhandler)) { + $defhandler = FileDir::makeCorrectFile($domain['documentroot'] . '/' . $defhandler); + } + $error_string .= ' server.error-handler-404 = "' . $defhandler . '"' . "\n\n"; + } + + if ($row['options_indexes'] != '0') { + if (!empty($error_string)) { + $path_options .= $error_string; + // reset $error_string here to prevent duplicate entries + $error_string = ''; + } + + $path = FileDir::makeCorrectDir(substr($row['path'], strlen($domain['documentroot']) - 1)); + FileDir::mkDirWithCorrectOwnership($domain['documentroot'], $row['path'], $domain['guid'], $domain['guid']); + + // We need to remove the last slash, otherwise the regex wouldn't work + if ($row['path'] != $domain['documentroot']) { + $path = substr($path, 0, -1); + } + $path_options .= ' $HTTP["url"] =~ "^' . $path . '($|/)" {' . "\n"; + $path_options .= "\t" . 'dir-listing.activate = "enable"' . "\n"; + $path_options .= ' }' . "\n\n"; + } else { + $path_options = $error_string; + } + + if (Customer::customerHasPerlEnabled($domain['customerid']) && $row['options_cgi'] != '0') { + $path = FileDir::makeCorrectDir(substr($row['path'], strlen($domain['documentroot']) - 1)); + FileDir::mkDirWithCorrectOwnership($domain['documentroot'], $row['path'], $domain['guid'], $domain['guid']); + + // We need to remove the last slash, otherwise the regex wouldn't work + if ($row['path'] != $domain['documentroot']) { + $path = substr($path, 0, -1); + } + $path_options .= ' $HTTP["url"] =~ "^' . $path . '($|/)" {' . "\n"; + $path_options .= "\t" . 'cgi.assign = (' . "\n"; + $path_options .= "\t\t" . '".pl" => "' . FileDir::makeCorrectFile(Settings::Get('system.perl_path')) . '",' . "\n"; + $path_options .= "\t\t" . '".cgi" => "' . FileDir::makeCorrectFile(Settings::Get('system.perl_path')) . '"' . "\n"; + $path_options .= "\t" . ')' . "\n"; + $path_options .= ' }' . "\n\n"; + } + } + + return $path_options; + } + + protected function composePhpOptions(&$domain) + { + return; + } + /** * Lets set the text part for the stats software */ @@ -907,46 +704,212 @@ class Lighttpd extends HttpConfigBase if ($domain['speciallogfile'] == '1') { if ($domain['parentdomainid'] == '0') { if (Settings::Get('system.awstats_enabled') == '1') { - $stats_text .= ' alias.url = ( "/awstats/" => "' . \Froxlor\FileDir::makeCorrectFile($domain['customerroot'] . '/awstats/' . $domain['domain']) . '" )' . "\n"; - $stats_text .= ' alias.url += ( "/awstats-icon" => "' . \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '" )' . "\n"; + $stats_text .= ' alias.url = ( "/awstats/" => "' . FileDir::makeCorrectFile($domain['customerroot'] . '/awstats/' . $domain['domain']) . '" )' . "\n"; + $stats_text .= ' alias.url += ( "/awstats-icon" => "' . FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '" )' . "\n"; } else { - $stats_text .= ' alias.url = ( "/webalizer/" => "' . \Froxlor\FileDir::makeCorrectFile($domain['customerroot'] . '/webalizer/' . $domain['domain']) . '/" )' . "\n"; + $stats_text .= ' alias.url = ( "/webalizer/" => "' . FileDir::makeCorrectFile($domain['customerroot'] . '/webalizer/' . $domain['domain']) . '/" )' . "\n"; } } else { if (Settings::Get('system.awstats_enabled') == '1') { - $stats_text .= ' alias.url = ( "/awstats/" => "' . \Froxlor\FileDir::makeCorrectFile($domain['customerroot'] . '/awstats/' . $domain['parentdomain']) . '" )' . "\n"; - $stats_text .= ' alias.url += ( "/awstats-icon" => "' . \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '" )' . "\n"; + $stats_text .= ' alias.url = ( "/awstats/" => "' . FileDir::makeCorrectFile($domain['customerroot'] . '/awstats/' . $domain['parentdomain']) . '" )' . "\n"; + $stats_text .= ' alias.url += ( "/awstats-icon" => "' . FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '" )' . "\n"; } else { - $stats_text .= ' alias.url = ( "/webalizer/" => "' . \Froxlor\FileDir::makeCorrectFile($domain['customerroot'] . '/webalizer/' . $domain['parentdomain']) . '/" )' . "\n"; + $stats_text .= ' alias.url = ( "/webalizer/" => "' . FileDir::makeCorrectFile($domain['customerroot'] . '/webalizer/' . $domain['parentdomain']) . '/" )' . "\n"; } } } else { if ($domain['customerroot'] != $domain['documentroot']) { if (Settings::Get('system.awstats_enabled') == '1') { - $stats_text .= ' alias.url = ( "/awstats/" => "' . \Froxlor\FileDir::makeCorrectFile($domain['customerroot'] . '/awstats/' . $domain['domain']) . '" )' . "\n"; - $stats_text .= ' alias.url += ( "/awstats-icon" => "' . \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '" )' . "\n"; + $stats_text .= ' alias.url = ( "/awstats/" => "' . FileDir::makeCorrectFile($domain['customerroot'] . '/awstats/' . $domain['domain']) . '" )' . "\n"; + $stats_text .= ' alias.url += ( "/awstats-icon" => "' . FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '" )' . "\n"; } else { - $stats_text .= ' alias.url = ( "/webalizer/" => "' . \Froxlor\FileDir::makeCorrectFile($domain['customerroot'] . '/webalizer/') . '" )' . "\n"; + $stats_text .= ' alias.url = ( "/webalizer/" => "' . FileDir::makeCorrectFile($domain['customerroot'] . '/webalizer/') . '" )' . "\n"; } } elseif (Settings::Get('system.awstats_enabled') == '1') { // if the docroots are equal, we still have to set an alias for awstats // because the stats are in /awstats/[domain], not just /awstats/ // also, the awstats-icons are someplace else too! // -> webalizer does not need this! - $stats_text .= ' alias.url = ( "/awstats/" => "' . \Froxlor\FileDir::makeCorrectFile($domain['documentroot'] . '/awstats/' . $domain['domain']) . '" )' . "\n"; - $stats_text .= ' alias.url += ( "/awstats-icon" => "' . \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '" )' . "\n"; + $stats_text .= ' alias.url = ( "/awstats/" => "' . FileDir::makeCorrectFile($domain['documentroot'] . '/awstats/' . $domain['domain']) . '" )' . "\n"; + $stats_text .= ' alias.url += ( "/awstats-icon" => "' . FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '" )' . "\n"; } } return $stats_text; } + protected function getSslSettings($domain, $ssl_vhost) + { + $ssl_settings = ''; + + if ($ssl_vhost === true && $domain['ssl'] == '1' && (int)Settings::Get('system.use_ssl') == 1) { + if ($domain['ssl_cert_file'] == '' || !file_exists($domain['ssl_cert_file'])) { + $domain['ssl_cert_file'] = Settings::Get('system.ssl_cert_file'); + if (!file_exists($domain['ssl_cert_file'])) { + // explicitly disable ssl for this vhost + $domain['ssl_cert_file'] = ""; + $this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Disabling SSL-vhost for "' . $domain['domain'] . '"'); + } + } + + if ($domain['ssl_ca_file'] == '') { + $domain['ssl_ca_file'] = Settings::Get('system.ssl_ca_file'); + } + + if ($domain['ssl_cert_file'] != '') { + $ssl_cipher_list = ($domain['override_tls'] == '1' && !empty($domain['ssl_cipher_list'])) ? $domain['ssl_cipher_list'] : Settings::Get('system.ssl_cipher_list'); + + // ssl.engine only necessary once in the ip/port vhost (SERVER['socket'] condition) + // $ssl_settings .= 'ssl.engine = "enable"' . "\n"; + $ssl_settings .= 'ssl.use-compression = "disable"' . "\n"; + if (!empty(Settings::Get('system.dhparams_file'))) { + $dhparams = FileDir::makeCorrectFile(Settings::Get('system.dhparams_file')); + if (!file_exists($dhparams)) { + FileDir::safe_exec('openssl dhparam -out ' . escapeshellarg($dhparams) . ' 4096'); + } + $ssl_settings .= 'ssl.dh-file = "' . $dhparams . '"' . "\n"; + $ssl_settings .= 'ssl.ec-curve = "secp384r1"' . "\n"; + } + $ssl_settings .= 'ssl.use-sslv2 = "disable"' . "\n"; + $ssl_settings .= 'ssl.use-sslv3 = "disable"' . "\n"; + $ssl_settings .= 'ssl.cipher-list = "' . $ssl_cipher_list . '"' . "\n"; + $ssl_settings .= 'ssl.honor-cipher-order = ' . ($domain['ssl_honorcipherorder'] == '1' ? '"enable"' : '"disable"') . "\n"; + $ssl_settings .= 'ssl.pemfile = "' . FileDir::makeCorrectFile($domain['ssl_cert_file']) . '"' . "\n"; + + if ($domain['ssl_ca_file'] != '') { + $ssl_settings .= 'ssl.ca-file = "' . FileDir::makeCorrectFile($domain['ssl_ca_file']) . '"' . "\n"; + } + + if ($domain['hsts'] >= 0) { + $ssl_settings .= '$HTTP["scheme"] == "https" { setenv.add-response-header = ( "Strict-Transport-Security" => "max-age=' . $domain['hsts']; + if ($domain['hsts_sub'] == 1) { + $ssl_settings .= '; includeSubDomains'; + } + if ($domain['hsts_preload'] == 1) { + $ssl_settings .= '; preload'; + } + $ssl_settings .= '") }' . "\n"; + } + } + } + return $ssl_settings; + } + + protected function getLogFiles($domain) + { + $logfiles_text = ''; + + $speciallogfile = ''; + if ($domain['speciallogfile'] == '1') { + if ($domain['parentdomainid'] == '0') { + $speciallogfile = '-' . $domain['domain']; + } else { + $speciallogfile = '-' . $domain['parentdomain']; + } + } + + // The normal access/error - logging is enabled + // error log cannot be set conditionally see + // https://redmine.lighttpd.net/issues/665 + if ($domain['writeaccesslog']) { + $access_log = FileDir::makeCorrectFile(Settings::Get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-access.log'); + // Create the logfile if it does not exist (fixes #46) + touch($access_log); + chown($access_log, Settings::Get('system.httpuser')); + chgrp($access_log, Settings::Get('system.httpgroup')); + + $logfiles_text .= ' accesslog.filename = "' . $access_log . '"' . "\n"; + } + + if (Settings::Get('system.awstats_enabled') == '1') { + if ((int)$domain['parentdomainid'] == 0) { + // prepare the aliases and subdomains for stats config files + $server_alias = ''; + $alias_domains_stmt = Database::prepare(" + SELECT `domain`, `iswildcarddomain`, `wwwserveralias` + FROM `" . TABLE_PANEL_DOMAINS . "` + WHERE `aliasdomain` = :domainid OR `parentdomainid` = :domainid + "); + Database::pexecute($alias_domains_stmt, [ + 'domainid' => $domain['id'] + ]); + + while (($alias_domain = $alias_domains_stmt->fetch(PDO::FETCH_ASSOC)) !== false) { + $server_alias .= ' ' . $alias_domain['domain'] . ' '; + + if ($alias_domain['iswildcarddomain'] == '1') { + $server_alias .= '*.' . $domain['domain']; + } else { + if ($alias_domain['wwwserveralias'] == '1') { + $server_alias .= 'www.' . $alias_domain['domain']; + } else { + $server_alias .= ''; + } + } + } + + if ($domain['iswildcarddomain'] == '1') { + $alias = '*.' . $domain['domain']; + } else { + if ($domain['wwwserveralias'] == '1') { + $alias = 'www.' . $domain['domain']; + } else { + $alias = ''; + } + } + + // After inserting the AWStats information, + // be sure to build the awstats conf file as well + // and chown it using $awstats_params, #258 + // Bug 960 + Bug 970 : Use full $domain instead of custom $awstats_params as following classes depend on the information + Statistics::createAWStatsConf(Settings::Get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-access.log', $domain['domain'], $alias . $server_alias, $domain['customerroot'], $domain); + } + } + + return $logfiles_text; + } + + /** + * define a default server.error-handler-404-statement, bug #unknown-yet + */ + private function createStandardErrorHandler() + { + if (Settings::Get('defaultwebsrverrhandler.enabled') == '1' && Settings::Get('defaultwebsrverrhandler.err404') != '') { + $vhost_filename = FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/05_froxlor_default_errorhandler.conf'); + + if (!isset($this->lighttpd_data[$vhost_filename])) { + $this->lighttpd_data[$vhost_filename] = ''; + } + + $defhandler = Settings::Get('defaultwebsrverrhandler.err404'); + if (!Validate::validateUrl($defhandler)) { + $defhandler = FileDir::makeCorrectFile($defhandler); + } + $this->lighttpd_data[$vhost_filename] = 'server.error-handler-404 = "' . $defhandler . '"'; + } + } + + public function createVirtualHosts() + { + return; + } + + public function createFileDirOptions() + { + return; + } + + public function createOwnVhostStarter() + { + return; + } + public function writeConfigs() { - $this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "lighttpd::writeConfigs: rebuilding " . Settings::Get('system.apacheconf_vhost')); + $this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "lighttpd::writeConfigs: rebuilding " . Settings::Get('system.apacheconf_vhost')); - $vhostDir = new \Froxlor\Http\Directory(Settings::Get('system.apacheconf_vhost')); - if (! $vhostDir->isConfigDir()) { + $vhostDir = new Directory(Settings::Get('system.apacheconf_vhost')); + if (!$vhostDir->isConfigDir()) { // Save one big file $vhosts_file = ''; @@ -969,9 +932,9 @@ class Lighttpd extends HttpConfigBase fwrite($vhosts_file_handler, $vhosts_file); fclose($vhosts_file_handler); } else { - if (! file_exists(Settings::Get('system.apacheconf_vhost'))) { - $this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'lighttpd::writeConfigs: mkdir ' . escapeshellarg(\Froxlor\FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); - \Froxlor\FileDir::safe_exec('mkdir ' . escapeshellarg(\Froxlor\FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); + if (!file_exists(Settings::Get('system.apacheconf_vhost'))) { + $this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'lighttpd::writeConfigs: mkdir ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); + FileDir::safe_exec('mkdir ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); } // Write a single file for every vhost @@ -981,7 +944,7 @@ class Lighttpd extends HttpConfigBase // Apply header $vhosts_file = '# ' . basename($vhosts_filename) . "\n" . '# Created ' . date('d.m.Y H:i') . "\n" . '# Do NOT manually edit this file, all changes will be deleted after the next domain change at the panel.' . "\n" . "\n" . $vhosts_file; - if (! empty($vhosts_filename)) { + if (!empty($vhosts_filename)) { $vhosts_file_handler = fopen($vhosts_filename, 'w'); fwrite($vhosts_file_handler, $vhosts_file); fclose($vhosts_file_handler); @@ -990,18 +953,67 @@ class Lighttpd extends HttpConfigBase } // Write the diroptions - $htpasswdDir = new \Froxlor\Http\Directory(Settings::Get('system.apacheconf_htpasswddir')); + $htpasswdDir = new Directory(Settings::Get('system.apacheconf_htpasswddir')); if ($htpasswdDir->isConfigDir()) { foreach ($this->needed_htpasswds as $key => $data) { - if (! is_dir(Settings::Get('system.apacheconf_htpasswddir'))) { - mkdir(\Froxlor\FileDir::makeCorrectDir(Settings::Get('system.apacheconf_htpasswddir'))); + if (!is_dir(Settings::Get('system.apacheconf_htpasswddir'))) { + mkdir(FileDir::makeCorrectDir(Settings::Get('system.apacheconf_htpasswddir'))); } - $filename = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_htpasswddir') . '/' . $key); + $filename = FileDir::makeCorrectFile(Settings::Get('system.apacheconf_htpasswddir') . '/' . $key); $htpasswd_handler = fopen($filename, 'w'); fwrite($htpasswd_handler, $data); fclose($htpasswd_handler); } } } + + protected function getDirOptions($domain) + { + $result_stmt = Database::prepare(" + SELECT * FROM " . TABLE_PANEL_HTPASSWDS . " + WHERE `customerid` = :customerid + "); + Database::pexecute($result_stmt, [ + 'customerid' => $domain['customerid'] + ]); + + $diroption_text = ''; + while ($row_htpasswds = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + if ($this->auth_backend_loaded[$domain['ipandport']] != 'yes' && $this->auth_backend_loaded[$domain['ssl_ipandport']] != 'yes') { + $filename = $domain['customerid'] . '.htpasswd'; + + if ($this->auth_backend_loaded[$domain['ipandport']] != 'yes') { + $this->auth_backend_loaded[$domain['ipandport']] = 'yes'; + $diroption_text .= 'auth.backend = "htpasswd"' . "\n"; + $diroption_text .= 'auth.backend.htpasswd.userfile = "' . FileDir::makeCorrectFile(Settings::Get('system.apacheconf_htpasswddir') . '/' . $filename) . '"' . "\n"; + $this->needed_htpasswds[$filename] = $row_htpasswds['username'] . ':' . $row_htpasswds['password'] . "\n"; + $diroption_text .= 'auth.require = ( ' . "\n"; + } elseif ($this->auth_backend_loaded[$domain['ssl_ipandport']] != 'yes') { + $this->auth_backend_loaded[$domain['ssl_ipandport']] = 'yes'; + $diroption_text .= 'auth.backend= "htpasswd"' . "\n"; + $diroption_text .= 'auth.backend.htpasswd.userfile = "' . FileDir::makeCorrectFile(Settings::Get('system.apacheconf_htpasswddir') . '/' . $filename) . '"' . "\n"; + $this->needed_htpasswds[$filename] = $row_htpasswds['username'] . ':' . $row_htpasswds['password'] . "\n"; + $diroption_text .= 'auth.require = ( ' . "\n"; + } + } + + $diroption_text .= '"' . FileDir::makeCorrectDir($row_htpasswds['path']) . '" =>' . "\n"; + $diroption_text .= '(' . "\n"; + $diroption_text .= ' "method" => "basic",' . "\n"; + $diroption_text .= ' "realm" => "' . $row_htpasswds['authname'] . '",' . "\n"; + $diroption_text .= ' "require" => "valid-user"' . "\n"; + $diroption_text .= ')' . "\n"; + + if ($this->auth_backend_loaded[$domain['ssl_ipandport']] == 'yes') { + $this->needed_htpasswds[$domain['ssl_ipandport']] .= $diroption_text; + } + + if ($this->auth_backend_loaded[$domain['ipandport']] != 'yes') { + $this->needed_htpasswds[$domain['ipandport']] .= $diroption_text; + } + } + + return ' auth.backend.htpasswd.userfile = "' . FileDir::makeCorrectFile(Settings::Get('system.apacheconf_htpasswddir') . '/' . $filename) . '"' . "\n"; + } } diff --git a/lib/Froxlor/Cron/Http/LighttpdFcgi.php b/lib/Froxlor/Cron/Http/LighttpdFcgi.php index b792e345..1d18087a 100644 --- a/lib/Froxlor/Cron/Http/LighttpdFcgi.php +++ b/lib/Froxlor/Cron/Http/LighttpdFcgi.php @@ -1,37 +1,106 @@ (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 + * @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); - } - } } diff --git a/lib/Froxlor/Cron/Http/Nginx.php b/lib/Froxlor/Cron/Http/Nginx.php index e7fcc416..9a36379b 100644 --- a/lib/Froxlor/Cron/Http/Nginx.php +++ b/lib/Froxlor/Cron/Http/Nginx.php @@ -1,46 +1,56 @@ (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 + * @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\Domain\Domain; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; +use Froxlor\Http\Directory; +use Froxlor\Http\Statistics; +use Froxlor\Settings; +use Froxlor\Validate\Validate; +use PDO; + class Nginx extends HttpConfigBase { - private $nginx_server = array(); + protected $nginx_data = []; // protected - protected $nginx_data = array(); - - protected $needed_htpasswds = array(); - + protected $needed_htpasswds = []; protected $auth_backend_loaded = false; - - protected $htpasswds_data = array(); - - protected $known_htpasswdsfilenames = array(); - + protected $htpasswds_data = []; + protected $known_htpasswdsfilenames = []; protected $mod_accesslog_loaded = '0'; - protected $vhost_root_autoindex = false; - - protected $known_vhostfilenames = array(); - + protected $known_vhostfilenames = []; + private $nginx_server = []; /** * indicator whether a customer is deactivated or not * if yes, only the webroot will be generated @@ -49,69 +59,11 @@ class Nginx extends HttpConfigBase */ private $deactivated = false; - public function __construct($nginx_server = array()) + public function __construct($nginx_server = []) { $this->nginx_server = $nginx_server; } - private function createLogformatEntry() - { - if (Settings::Get('system.logfiles_format') != '') { - $vhosts_folder = ''; - if (is_dir(Settings::Get('system.apacheconf_vhost'))) { - $vhosts_folder = \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')); - } else { - $vhosts_folder = \Froxlor\FileDir::makeCorrectDir(dirname(Settings::Get('system.apacheconf_vhost'))); - } - - $vhosts_filename = \Froxlor\FileDir::makeCorrectFile($vhosts_folder . '/02_froxlor_logfiles_format.conf'); - - if (! isset($this->nginx_data[$vhosts_filename])) { - $this->nginx_data[$vhosts_filename] = ''; - } - - $logtype = 'frx_custom'; - $this->nginx_data[$vhosts_filename] = 'log_format ' . $logtype . ' ' . Settings::Get('system.logfiles_format') . ';' . "\n"; - } - } - - /** - * define a default ErrorDocument-statement, bug #unknown-yet - */ - private function createStandardErrorHandler() - { - if (Settings::Get('defaultwebsrverrhandler.enabled') == '1' && (Settings::Get('defaultwebsrverrhandler.err401') != '' || Settings::Get('defaultwebsrverrhandler.err403') != '' || Settings::Get('defaultwebsrverrhandler.err404') != '' || Settings::Get('defaultwebsrverrhandler.err500') != '')) { - $vhosts_folder = ''; - if (is_dir(Settings::Get('system.apacheconf_vhost'))) { - $vhosts_folder = \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')); - } else { - $vhosts_folder = \Froxlor\FileDir::makeCorrectDir(dirname(Settings::Get('system.apacheconf_vhost'))); - } - - $vhosts_filename = \Froxlor\FileDir::makeCorrectFile($vhosts_folder . '/05_froxlor_default_errorhandler.conf'); - - if (! isset($this->nginx_data[$vhosts_filename])) { - $this->nginx_data[$vhosts_filename] = ''; - } - - $statusCodes = array( - '401', - '403', - '404', - '500' - ); - foreach ($statusCodes as $statusCode) { - if (Settings::Get('defaultwebsrverrhandler.err' . $statusCode) != '') { - $defhandler = Settings::Get('defaultwebsrverrhandler.err' . $statusCode); - if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) { - $defhandler = \Froxlor\FileDir::makeCorrectFile($defhandler); - } - $this->nginx_data[$vhosts_filename] .= 'error_page ' . $statusCode . ' ' . $defhandler . ';' . "\n"; - } - } - } - } - public function createVirtualHosts() { return; @@ -130,7 +82,7 @@ class Nginx extends HttpConfigBase SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` ORDER BY `ip` ASC, `port` ASC "); - while ($row_ipsandports = $result_ipsandports_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row_ipsandports = $result_ipsandports_stmt->fetch(PDO::FETCH_ASSOC)) { if (filter_var($row_ipsandports['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { $ip = '[' . $row_ipsandports['ip'] . ']'; } else { @@ -138,15 +90,14 @@ class Nginx extends HttpConfigBase } $port = $row_ipsandports['port']; - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'nginx::createIpPort: creating ip/port settings for ' . $ip . ":" . $port); - $vhost_filename = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/10_froxlor_ipandport_' . trim(str_replace(':', '.', $row_ipsandports['ip']), '.') . '.' . $row_ipsandports['port'] . '.conf'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'nginx::createIpPort: creating ip/port settings for ' . $ip . ":" . $port); + $vhost_filename = FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/10_froxlor_ipandport_' . trim(str_replace(':', '.', $row_ipsandports['ip']), '.') . '.' . $row_ipsandports['port'] . '.conf'); - if (! isset($this->nginx_data[$vhost_filename])) { + if (!isset($this->nginx_data[$vhost_filename])) { $this->nginx_data[$vhost_filename] = ''; } if ($row_ipsandports['vhostcontainer'] == '1') { - $this->nginx_data[$vhost_filename] .= 'server { ' . "\n"; $mypath = $this->getMyPath($row_ipsandports); @@ -156,20 +107,20 @@ class Nginx extends HttpConfigBase $ssl_vhost = false; if ($row_ipsandports['ssl'] == '1') { // check for required fallback - if (($row_ipsandports['ssl_cert_file'] == '' || ! file_exists($row_ipsandports['ssl_cert_file'])) && (Settings::Get('system.le_froxlor_enabled') == '0' || $this->froxlorVhostHasLetsEncryptCert() == false)) { + if (($row_ipsandports['ssl_cert_file'] == '' || !file_exists($row_ipsandports['ssl_cert_file'])) && (Settings::Get('system.le_froxlor_enabled') == '0' || $this->froxlorVhostHasLetsEncryptCert() == false)) { $row_ipsandports['ssl_cert_file'] = Settings::Get('system.ssl_cert_file'); - if (! file_exists($row_ipsandports['ssl_cert_file'])) { + if (!file_exists($row_ipsandports['ssl_cert_file'])) { // explicitly disable ssl for this vhost $row_ipsandports['ssl_cert_file'] = ""; - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Disabling SSL-vhost for "' . Settings::Get('system.hostname') . '"'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Disabling SSL-vhost for "' . Settings::Get('system.hostname') . '"'); } } if ($row_ipsandports['ssl_key_file'] == '') { $row_ipsandports['ssl_key_file'] = Settings::Get('system.ssl_key_file'); - if (! file_exists($row_ipsandports['ssl_key_file'])) { + if (!file_exists($row_ipsandports['ssl_key_file'])) { // explicitly disable ssl for this vhost $row_ipsandports['ssl_cert_file'] = ""; - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate key-file "' . Settings::Get('system.ssl_key_file') . '" does not seem to exist. Disabling SSL-vhost for "' . Settings::Get('system.hostname') . '"'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate key-file "' . Settings::Get('system.ssl_key_file') . '" does not seem to exist. Disabling SSL-vhost for "' . Settings::Get('system.hostname') . '"'); } } if ($row_ipsandports['ssl_ca_file'] == '') { @@ -179,7 +130,7 @@ class Nginx extends HttpConfigBase $ssl_vhost = true; } - $domain = array( + $domain = [ 'id' => 0, 'domain' => Settings::Get('system.hostname'), 'adminid' => 1, /* first admin-user (superadmin) */ @@ -187,7 +138,7 @@ class Nginx extends HttpConfigBase 'documentroot' => $mypath, 'customerroot' => $mypath, 'parentdomainid' => 0 - ); + ]; // override corresponding array values $domain['ssl_cert_file'] = $row_ipsandports['ssl_cert_file']; @@ -222,10 +173,10 @@ class Nginx extends HttpConfigBase $aliases = ""; $froxlor_aliases = Settings::Get('system.froxloraliases'); - if (! empty($froxlor_aliases)) { + if (!empty($froxlor_aliases)) { $froxlor_aliases = explode(",", $froxlor_aliases); foreach ($froxlor_aliases as $falias) { - if (\Froxlor\Validate\Validate::validateDomain(trim($falias))) { + if (Validate::validateDomain(trim($falias))) { $aliases .= trim($falias) . " "; } } @@ -262,7 +213,7 @@ class Nginx extends HttpConfigBase } } - if (! $is_redirect) { + if (!$is_redirect) { $this->nginx_data[$vhost_filename] .= "\t" . 'root ' . $mypath . ';' . "\n"; $this->nginx_data[$vhost_filename] .= "\t" . 'index index.php index.html index.htm;' . "\n\n"; $this->nginx_data[$vhost_filename] .= "\t" . 'location / {' . "\n"; @@ -270,12 +221,12 @@ class Nginx extends HttpConfigBase } if ($row_ipsandports['specialsettings'] != '' && ($row_ipsandports['ssl'] == '0' || ($row_ipsandports['ssl'] == '1' && Settings::Get('system.use_ssl') == '1' && $row_ipsandports['include_specialsettings'] == '1'))) { - $this->nginx_data[$vhost_filename] .= $this->processSpecialConfigTemplate($row_ipsandports['specialsettings'], array( - 'domain' => Settings::Get('system.hostname'), - 'loginname' => Settings::Get('phpfpm.vhost_httpuser'), - 'documentroot' => $mypath, - 'customerroot' => $mypath - ), $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n"; + $this->nginx_data[$vhost_filename] .= $this->processSpecialConfigTemplate($row_ipsandports['specialsettings'], [ + 'domain' => Settings::Get('system.hostname'), + 'loginname' => Settings::Get('phpfpm.vhost_httpuser'), + 'documentroot' => $mypath, + 'customerroot' => $mypath + ], $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n"; } /** @@ -287,16 +238,16 @@ class Nginx extends HttpConfigBase $row_ipsandports['ssl_sessiontickets'] = Settings::Get('system.sessiontickets'); $this->nginx_data[$vhost_filename] .= $this->composeSslSettings($row_ipsandports); if ($row_ipsandports['ssl_specialsettings'] != '') { - $this->nginx_data[$vhost_filename] .= $this->processSpecialConfigTemplate($row_ipsandports['ssl_specialsettings'], array( - 'domain' => Settings::Get('system.hostname'), - 'loginname' => Settings::Get('phpfpm.vhost_httpuser'), - 'documentroot' => $mypath, - 'customerroot' => $mypath - ), $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n"; + $this->nginx_data[$vhost_filename] .= $this->processSpecialConfigTemplate($row_ipsandports['ssl_specialsettings'], [ + 'domain' => Settings::Get('system.hostname'), + 'loginname' => Settings::Get('phpfpm.vhost_httpuser'), + 'documentroot' => $mypath, + 'customerroot' => $mypath + ], $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n"; } } - if (! $is_redirect) { + if (!$is_redirect) { $this->nginx_data[$vhost_filename] .= "\tlocation ~ \.php {\n"; $this->nginx_data[$vhost_filename] .= "\t\tfastcgi_split_path_info ^(.+?\.php)(/.*)$;\n"; $this->nginx_data[$vhost_filename] .= "\t\tinclude " . Settings::Get('nginx.fastcgiparams') . ";\n"; @@ -308,22 +259,22 @@ class Nginx extends HttpConfigBase $this->nginx_data[$vhost_filename] .= "\t\tfastcgi_param HTTPS on;\n"; } - if ((int) Settings::Get('phpfpm.enabled') == 1 && (int) Settings::Get('phpfpm.enabled_ownvhost') == 1) { + if ((int)Settings::Get('phpfpm.enabled') == 1 && (int)Settings::Get('phpfpm.enabled_ownvhost') == 1) { // 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( + $fpm_config = Database::pexecute_first($fpm_sel_stmt, [ 'phpconfigid' => Settings::Get('phpfpm.vhost_defaultini') - )); - $domain = array( + ]); + $domain = [ 'id' => 'none', 'domain' => Settings::Get('system.hostname'), 'adminid' => 1, /* first admin-user (superadmin) */ - 'mod_fcgid_starter' => - 1, - 'mod_fcgid_maxrequests' => - 1, + 'mod_fcgid_starter' => -1, + 'mod_fcgid_maxrequests' => -1, 'guid' => Settings::Get('phpfpm.vhost_httpuser'), 'openbasedir' => 0, 'email' => Settings::Get('panel.adminmail'), @@ -331,7 +282,7 @@ class Nginx extends HttpConfigBase 'documentroot' => $mypath, 'customerroot' => $mypath, 'fpm_config_id' => isset($fpm_config['id']) ? $fpm_config['id'] : 1 - ); + ]; $php = new PhpInterface($domain); $this->nginx_data[$vhost_filename] .= "\t\tfastcgi_pass unix:" . $php->getInterface()->getSocketFile() . ";\n"; @@ -356,6 +307,122 @@ class Nginx extends HttpConfigBase $this->createStandardErrorHandler(); } + private function createLogformatEntry() + { + if (Settings::Get('system.logfiles_format') != '') { + $vhosts_folder = ''; + if (is_dir(Settings::Get('system.apacheconf_vhost'))) { + $vhosts_folder = FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')); + } else { + $vhosts_folder = FileDir::makeCorrectDir(dirname(Settings::Get('system.apacheconf_vhost'))); + } + + $vhosts_filename = FileDir::makeCorrectFile($vhosts_folder . '/02_froxlor_logfiles_format.conf'); + + if (!isset($this->nginx_data[$vhosts_filename])) { + $this->nginx_data[$vhosts_filename] = ''; + } + + $logtype = 'frx_custom'; + $this->nginx_data[$vhosts_filename] = 'log_format ' . $logtype . ' ' . Settings::Get('system.logfiles_format') . ';' . "\n"; + } + } + + protected function composeSslSettings($domain_or_ip) + { + $sslsettings = ''; + + if ($domain_or_ip['ssl_cert_file'] == '' || !file_exists($domain_or_ip['ssl_cert_file'])) { + $domain_or_ip['ssl_cert_file'] = Settings::Get('system.ssl_cert_file'); + if (!file_exists($domain_or_ip['ssl_cert_file'])) { + // explicitly disable ssl for this vhost + $domain_or_ip['ssl_cert_file'] = ""; + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Disabling SSL-vhost for "' . $domain_or_ip['domain'] . '"'); + } + } + + if ($domain_or_ip['ssl_key_file'] == '' || !file_exists($domain_or_ip['ssl_key_file'])) { + // use fallback + $domain_or_ip['ssl_key_file'] = Settings::Get('system.ssl_key_file'); + // check whether it exists + if (!file_exists($domain_or_ip['ssl_key_file'])) { + // explicitly disable ssl for this vhost + $domain_or_ip['ssl_cert_file'] = ""; + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate key-file "' . Settings::Get('system.ssl_key_file') . '" does not seem to exist. Disabling SSL-vhost for "' . $domain_or_ip['domain'] . '"'); + } + } + + if ($domain_or_ip['ssl_ca_file'] == '') { + $domain_or_ip['ssl_ca_file'] = Settings::Get('system.ssl_ca_file'); + } + + // #418 + if ($domain_or_ip['ssl_cert_chainfile'] == '') { + $domain_or_ip['ssl_cert_chainfile'] = Settings::Get('system.ssl_cert_chainfile'); + } + + if ($domain_or_ip['ssl_cert_file'] != '') { + // check for existence, #1485 + if (!file_exists($domain_or_ip['ssl_cert_file'])) { + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, $domain_or_ip['domain'] . ' :: certificate file "' . $domain_or_ip['ssl_cert_file'] . '" does not exist! Cannot create ssl-directives'); + } else { + $ssl_protocols = (isset($domain_or_ip['override_tls']) && $domain_or_ip['override_tls'] == '1' && !empty($domain_or_ip['ssl_protocols'])) ? $domain_or_ip['ssl_protocols'] : Settings::Get('system.ssl_protocols'); + $ssl_cipher_list = (isset($domain_or_ip['override_tls']) && $domain_or_ip['override_tls'] == '1' && !empty($domain_or_ip['ssl_cipher_list'])) ? $domain_or_ip['ssl_cipher_list'] : Settings::Get('system.ssl_cipher_list'); + + // obsolete: ssl on now belongs to the listen block as 'ssl' at the end + // $sslsettings .= "\t" . 'ssl on;' . "\n"; + $sslsettings .= "\t" . 'ssl_protocols ' . str_replace(",", " ", $ssl_protocols) . ';' . "\n"; + $sslsettings .= "\t" . 'ssl_ciphers ' . $ssl_cipher_list . ';' . "\n"; + if (!empty(Settings::Get('system.dhparams_file'))) { + $dhparams = FileDir::makeCorrectFile(Settings::Get('system.dhparams_file')); + if (!file_exists($dhparams)) { + FileDir::safe_exec('openssl dhparam -out ' . escapeshellarg($dhparams) . ' 4096'); + } + $sslsettings .= "\t" . 'ssl_dhparam ' . $dhparams . ';' . "\n"; + } + // When <1.11.0: Defaults to prime256v1, similar to first curve recommendation by Mozilla. + // (When specifyng just one, there's no fallback when specific curve is not supported by client.) + // When >1.11.0: Defaults to auto, using recommended curves provided by OpenSSL. + // see https://github.com/Froxlor/Froxlor/issues/652 + // $sslsettings .= "\t" . 'ssl_ecdh_curve secp384r1;' . "\n"; + $sslsettings .= "\t" . 'ssl_prefer_server_ciphers ' . (isset($domain_or_ip['ssl_honorcipherorder']) && $domain_or_ip['ssl_honorcipherorder'] == '1' ? 'on' : 'off') . ';' . "\n"; + if (Settings::Get('system.sessionticketsenabled') == '1') { + $sslsettings .= "\t" . 'ssl_session_tickets ' . (isset($domain_or_ip['ssl_sessiontickets']) && $domain_or_ip['ssl_sessiontickets'] == '1' ? 'on' : 'off') . ';' . "\n"; + } + $sslsettings .= "\t" . 'ssl_session_cache shared:SSL:10m;' . "\n"; + $sslsettings .= "\t" . 'ssl_certificate ' . FileDir::makeCorrectFile($domain_or_ip['ssl_cert_file']) . ';' . "\n"; + + if ($domain_or_ip['ssl_key_file'] != '') { + // check for existence, #1485 + if (!file_exists($domain_or_ip['ssl_key_file'])) { + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, $domain_or_ip['domain'] . ' :: certificate key file "' . $domain_or_ip['ssl_key_file'] . '" does not exist! Cannot create ssl-directives'); + } else { + $sslsettings .= "\t" . 'ssl_certificate_key ' . FileDir::makeCorrectFile($domain_or_ip['ssl_key_file']) . ';' . "\n"; + } + } + + if (isset($domain_or_ip['hsts']) && $domain_or_ip['hsts'] >= 0) { + $sslsettings .= 'add_header Strict-Transport-Security "max-age=' . $domain_or_ip['hsts']; + if ($domain_or_ip['hsts_sub'] == 1) { + $sslsettings .= '; includeSubDomains'; + } + if ($domain_or_ip['hsts_preload'] == 1) { + $sslsettings .= '; preload'; + } + $sslsettings .= '";' . "\n"; + } + + if ((isset($domain_or_ip['ocsp_stapling']) && $domain_or_ip['ocsp_stapling'] == "1") || (isset($domain_or_ip['letsencrypt']) && $domain_or_ip['letsencrypt'] == "1")) { + $sslsettings .= "\t" . 'ssl_stapling on;' . "\n"; + $sslsettings .= "\t" . 'ssl_stapling_verify on;' . "\n"; + $sslsettings .= "\t" . 'ssl_trusted_certificate ' . FileDir::makeCorrectFile($domain_or_ip['ssl_cert_file']) . ';' . "\n"; + } + } + } + + return $sslsettings; + } + /** * create vhosts */ @@ -363,25 +430,24 @@ class Nginx extends HttpConfigBase { $domains = WebserverBase::getVhostsToCreate(); foreach ($domains as $domain) { - if (is_dir(Settings::Get('system.apacheconf_vhost'))) { - \Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg(\Froxlor\FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); + FileDir::safe_exec('mkdir -p ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); } $vhost_filename = $this->getVhostFilename($domain); - if (! isset($this->nginx_data[$vhost_filename])) { + if (!isset($this->nginx_data[$vhost_filename])) { $this->nginx_data[$vhost_filename] = ''; } - if ((empty($this->nginx_data[$vhost_filename]) && ! is_dir(Settings::Get('system.apacheconf_vhost'))) || is_dir(Settings::Get('system.apacheconf_vhost'))) { + if ((empty($this->nginx_data[$vhost_filename]) && !is_dir(Settings::Get('system.apacheconf_vhost'))) || is_dir(Settings::Get('system.apacheconf_vhost'))) { $domain['nonexistinguri'] = '/' . md5(uniqid(microtime(), 1)) . '.htm'; // Create non-ssl host $this->nginx_data[$vhost_filename] .= $this->getVhostContent($domain, false); if ($domain['ssl'] == '1' || $domain['ssl_redirect'] == '1') { $vhost_filename_ssl = $this->getVhostFilename($domain, true); - if (! isset($this->nginx_data[$vhost_filename_ssl])) { + if (!isset($this->nginx_data[$vhost_filename_ssl])) { $this->nginx_data[$vhost_filename_ssl] = ''; } // Now enable ssl stuff @@ -393,19 +459,19 @@ class Nginx extends HttpConfigBase protected function getVhostFilename($domain, $ssl_vhost = false) { - if ((int) $domain['parentdomainid'] == 0 && \Froxlor\Domain\Domain::isCustomerStdSubdomain((int) $domain['id']) == false && ((int) $domain['ismainbutsubto'] == 0 || \Froxlor\Domain\Domain::domainMainToSubExists($domain['ismainbutsubto']) == false)) { + if ((int)$domain['parentdomainid'] == 0 && Domain::isCustomerStdSubdomain((int)$domain['id']) == false && ((int)$domain['ismainbutsubto'] == 0 || Domain::domainMainToSubExists($domain['ismainbutsubto']) == false)) { $vhost_no = '35'; - } elseif ((int) $domain['parentdomainid'] == 0 && \Froxlor\Domain\Domain::isCustomerStdSubdomain((int) $domain['id']) == false && (int) $domain['ismainbutsubto'] > 0) { + } elseif ((int)$domain['parentdomainid'] == 0 && Domain::isCustomerStdSubdomain((int)$domain['id']) == false && (int)$domain['ismainbutsubto'] > 0) { $vhost_no = '30'; } else { // number of dots in a domain specifies it's position (and depth of subdomain) starting at 29 going downwards on higher depth - $vhost_no = (string) (30 - substr_count($domain['domain'], ".") + 1); + $vhost_no = (string)(30 - substr_count($domain['domain'], ".") + 1); } if ($ssl_vhost === true) { - $vhost_filename = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/' . $vhost_no . '_froxlor_ssl_vhost_' . $domain['domain'] . '.conf'); + $vhost_filename = FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/' . $vhost_no . '_froxlor_ssl_vhost_' . $domain['domain'] . '.conf'); } else { - $vhost_filename = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/' . $vhost_no . '_froxlor_normal_vhost_' . $domain['domain'] . '.conf'); + $vhost_filename = FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/' . $vhost_no . '_froxlor_normal_vhost_' . $domain['domain'] . '.conf'); } return $vhost_filename; @@ -441,12 +507,11 @@ class Nginx extends HttpConfigBase $vhost_content .= 'server { ' . "\n"; $result_stmt = Database::prepare($query); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'domainid' => $domain['id'] - )); - - while ($ipandport = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + ]); + while ($ipandport = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $domain['ip'] = $ipandport['ip']; $domain['port'] = $ipandport['port']; if ($domain['ssl'] == '1') { @@ -495,9 +560,9 @@ class Nginx extends HttpConfigBase WHERE `dip`.`id_domain` = :domainid AND `ip`.`ssl` = '1' AND `ip`.`port` != 443 ORDER BY `ip`.`ssl_cert_file` DESC, `ip`.`port` LIMIT 1;"); - $ssldestport = Database::pexecute_first($ssldestport_stmt, array( + $ssldestport = Database::pexecute_first($ssldestport_stmt, [ 'domainid' => $domain['id'] - )); + ]); if ($ssldestport && $ssldestport['port'] != '') { $_sslport = ":" . $ssldestport['port']; @@ -522,24 +587,23 @@ class Nginx extends HttpConfigBase // if the documentroot is an URL we just redirect if (preg_match('/^https?\:\/\//', $domain['documentroot'])) { $uri = $domain['documentroot']; - if (substr($uri, - 1) == '/') { - $uri = substr($uri, 0, - 1); + if (substr($uri, -1) == '/') { + $uri = substr($uri, 0, -1); } // Get domain's redirect code - $code = \Froxlor\Domain\Domain::getDomainRedirectCode($domain['id']); + $code = Domain::getDomainRedirectCode($domain['id']); $vhost_content .= "\t" . 'location / {' . "\n"; $vhost_content .= "\t\t" . 'return ' . $code . ' ' . $uri . '$request_uri;' . "\n"; $vhost_content .= "\t" . '}' . "\n"; } else { - \Froxlor\FileDir::mkDirWithCorrectOwnership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true); + FileDir::mkDirWithCorrectOwnership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true); $vhost_content .= $this->getLogFiles($domain); $vhost_content .= $this->getWebroot($domain, $ssl_vhost); if ($this->deactivated == false) { - $vhost_content = $this->mergeVhostCustom($vhost_content, $this->createPathOptions($domain)) . "\n"; $vhost_content .= $this->composePhpOptions($domain, $ssl_vhost); @@ -571,6 +635,232 @@ class Nginx extends HttpConfigBase return $vhost_content; } + protected function getServerNames($domain) + { + $server_alias = ''; + + if ($domain['iswildcarddomain'] == '1') { + $server_alias = '*.' . $domain['domain']; + } elseif ($domain['wwwserveralias'] == '1') { + $server_alias = 'www.' . $domain['domain']; + } + + $alias_domains_stmt = Database::prepare(" + SELECT `domain`, `iswildcarddomain`, `wwwserveralias` + FROM `" . TABLE_PANEL_DOMAINS . "` + WHERE `aliasdomain` = :domainid + "); + Database::pexecute($alias_domains_stmt, [ + 'domainid' => $domain['id'] + ]); + + while (($alias_domain = $alias_domains_stmt->fetch(PDO::FETCH_ASSOC)) !== false) { + $server_alias .= ' ' . $alias_domain['domain']; + + if ($alias_domain['iswildcarddomain'] == '1') { + $server_alias .= ' *.' . $alias_domain['domain']; + } elseif ($alias_domain['wwwserveralias'] == '1') { + $server_alias .= ' www.' . $alias_domain['domain']; + } + } + + $servernames_text = "\t" . 'server_name ' . $domain['domain']; + if (trim($server_alias) != '') { + $servernames_text .= ' ' . $server_alias; + } + $servernames_text .= ';' . "\n"; + + return $servernames_text; + } + + protected function getLogFiles($domain) + { + $logfiles_text = ''; + + $speciallogfile = ''; + if ($domain['speciallogfile'] == '1') { + if ($domain['parentdomainid'] == '0') { + $speciallogfile = '-' . $domain['domain']; + } else { + $speciallogfile = '-' . $domain['parentdomain']; + } + } + + if ($domain['writeerrorlog']) { + // The normal access/error - logging is enabled + $error_log = FileDir::makeCorrectFile(Settings::Get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-error.log'); + // Create the logfile if it does not exist (fixes #46) + touch($error_log); + chown($error_log, Settings::Get('system.httpuser')); + chgrp($error_log, Settings::Get('system.httpgroup')); + } else { + $error_log = '/dev/null'; + } + + if ($domain['writeaccesslog']) { + $access_log = FileDir::makeCorrectFile(Settings::Get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-access.log'); + // Create the logfile if it does not exist (fixes #46) + touch($access_log); + chown($access_log, Settings::Get('system.httpuser')); + chgrp($access_log, Settings::Get('system.httpgroup')); + } else { + $access_log = '/dev/null'; + } + + $logtype = 'combined'; + if (Settings::Get('system.logfiles_format') != '') { + $logtype = 'frx_custom'; + } + + $logfiles_text .= "\t" . 'access_log ' . $access_log . ' ' . $logtype . ';' . "\n"; + $logfiles_text .= "\t" . 'error_log ' . $error_log . ' ' . Settings::Get('system.errorlog_level') . ';' . "\n"; + + if (Settings::Get('system.awstats_enabled') == '1') { + if ((int)$domain['parentdomainid'] == 0) { + // prepare the aliases and subdomains for stats config files + $server_alias = ''; + $alias_domains_stmt = Database::prepare(" + SELECT `domain`, `iswildcarddomain`, `wwwserveralias` + FROM `" . TABLE_PANEL_DOMAINS . "` + WHERE `aliasdomain` = :domainid OR `parentdomainid` = :domainid + "); + Database::pexecute($alias_domains_stmt, [ + 'domainid' => $domain['id'] + ]); + + while (($alias_domain = $alias_domains_stmt->fetch(PDO::FETCH_ASSOC)) !== false) { + $server_alias .= ' ' . $alias_domain['domain'] . ' '; + + if ($alias_domain['iswildcarddomain'] == '1') { + $server_alias .= '*.' . $domain['domain']; + } else { + if ($alias_domain['wwwserveralias'] == '1') { + $server_alias .= 'www.' . $alias_domain['domain']; + } else { + $server_alias .= ''; + } + } + } + + $alias = ''; + if ($domain['iswildcarddomain'] == '1') { + $alias = '*.' . $domain['domain']; + } elseif ($domain['wwwserveralias'] == '1') { + $alias = 'www.' . $domain['domain']; + } + + // After inserting the AWStats information, + // be sure to build the awstats conf file as well + // and chown it using $awstats_params, #258 + // Bug 960 + Bug 970 : Use full $domain instead of custom $awstats_params as following classes depend on the information + Statistics::createAWStatsConf(Settings::Get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-access.log', $domain['domain'], $alias . $server_alias, $domain['customerroot'], $domain); + } + } + + return $logfiles_text; + } + + protected function getWebroot($domain, $ssl) + { + $webroot_text = ''; + + if ($domain['deactivated'] == '1' && Settings::Get('system.deactivateddocroot') != '') { + $webroot_text .= "\t" . '# Using docroot for deactivated users...' . "\n"; + $webroot_text .= "\t" . 'root ' . FileDir::makeCorrectDir(Settings::Get('system.deactivateddocroot')) . ';' . "\n"; + $this->deactivated = true; + } else { + $webroot_text .= "\t" . 'root ' . FileDir::makeCorrectDir($domain['documentroot']) . ';' . "\n"; + $this->deactivated = false; + } + + $webroot_text .= "\n\t" . 'location / {' . "\n"; + + if ($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1') { + $webroot_text .= "\t" . 'index index.php index.html index.htm;' . "\n"; + if ($domain['notryfiles'] != 1) { + $webroot_text .= "\t\t" . 'try_files $uri $uri/ @rewrites;' . "\n"; + } + } else { + $webroot_text .= "\t" . 'index index.html index.htm;' . "\n"; + } + + if ($this->vhost_root_autoindex) { + $webroot_text .= "\t\t" . 'autoindex on;' . "\n"; + $this->vhost_root_autoindex = false; + } + + $webroot_text .= "\t" . '}' . "\n\n"; + if ($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1' && $domain['notryfiles'] != 1) { + $webroot_text .= "\tlocation @rewrites {\n"; + $webroot_text .= "\t\trewrite ^ /index.php last;\n"; + $webroot_text .= "\t}\n\n"; + } + + return $webroot_text; + } + + protected function mergeVhostCustom($vhost_frx, $vhost_usr) + { + // Clean froxlor defined settings + $vhost_frx = $this->cleanVhostStruct($vhost_frx); + // Clean user defined settings + $vhost_usr = $this->cleanVhostStruct($vhost_usr); + + // Cycle through the user defined settings + $currentBlock = []; + $blockLevel = 0; + foreach ($vhost_usr as $line) { + $line = trim($line); + $currentBlock[] = $line; + + if (strpos($line, "{") !== false) { + $blockLevel++; + } + if (strpos($line, "}") !== false && $blockLevel > 0) { + $blockLevel--; + } + + if ($line == "}" && $blockLevel == 0) { + if (in_array($currentBlock[0], $vhost_frx)) { + // Add to existing block + $pos = array_search($currentBlock[0], $vhost_frx); + do { + $pos++; + } while ($vhost_frx[$pos] != "}"); + + for ($i = 1; $i < count($currentBlock) - 1; $i++) { + array_splice($vhost_frx, $pos + $i - 1, 0, $currentBlock[$i]); + } + } else { + // Add to end + array_splice($vhost_frx, count($vhost_frx), 0, $currentBlock); + } + $currentBlock = []; + } elseif ($blockLevel == 0) { + array_splice($vhost_frx, count($vhost_frx), 0, $currentBlock); + $currentBlock = []; + } + } + + $nextLevel = 0; + for ($i = 0; $i < count($vhost_frx); $i++) { + if (substr_count($vhost_frx[$i], "}") != 0 && substr_count($vhost_frx[$i], "{") == 0) { + $nextLevel -= 1; + $vhost_frx[$i] .= "\n"; + } + if ($nextLevel > 0) { + for ($j = 0; $j < $nextLevel; $j++) { + $vhost_frx[$i] = " " . $vhost_frx[$i]; + } + } + if (substr_count($vhost_frx[$i], "{") != 0 && substr_count($vhost_frx[$i], "}") == 0) { + $nextLevel += 1; + } + } + + return implode("\n", $vhost_frx); + } + private function cleanVhostStruct($vhost = null) { // Remove windows linebreaks @@ -578,13 +868,13 @@ class Nginx extends HttpConfigBase // remove comments $vhost = implode("\n", preg_replace('/^(\s+)?#(.*)$/', '', explode("\n", $vhost))); // Break blocks into lines - $vhost = str_replace(array( + $vhost = str_replace([ "{", "}" - ), array( + ], [ " {\n", "\n}" - ), $vhost); + ], $vhost); // Break into array items $vhost = explode("\n", preg_replace('/[ \t]+/', ' ', trim(preg_replace('/\t+/', '', $vhost)))); // Remove empty lines @@ -599,208 +889,49 @@ class Nginx extends HttpConfigBase return $vhost; } - protected function mergeVhostCustom($vhost_frx, $vhost_usr) - { - // Clean froxlor defined settings - $vhost_frx = $this->cleanVhostStruct($vhost_frx); - // Clean user defined settings - $vhost_usr = $this->cleanVhostStruct($vhost_usr); - - // Cycle through the user defined settings - $currentBlock = array(); - $blockLevel = 0; - foreach ($vhost_usr as $line) { - $line = trim($line); - $currentBlock[] = $line; - - if (strpos($line, "{") !== false) { - $blockLevel ++; - } - if (strpos($line, "}") !== false && $blockLevel > 0) { - $blockLevel --; - } - - if ($line == "}" && $blockLevel == 0) { - if (in_array($currentBlock[0], $vhost_frx)) { - // Add to existing block - $pos = array_search($currentBlock[0], $vhost_frx); - do { - $pos ++; - } while ($vhost_frx[$pos] != "}"); - - for ($i = 1; $i < count($currentBlock) - 1; $i ++) { - array_splice($vhost_frx, $pos + $i - 1, 0, $currentBlock[$i]); - } - } else { - // Add to end - array_splice($vhost_frx, count($vhost_frx), 0, $currentBlock); - } - $currentBlock = array(); - } elseif ($blockLevel == 0) { - array_splice($vhost_frx, count($vhost_frx), 0, $currentBlock); - $currentBlock = array(); - } - } - - $nextLevel = 0; - for ($i = 0; $i < count($vhost_frx); $i ++) { - if (substr_count($vhost_frx[$i], "}") != 0 && substr_count($vhost_frx[$i], "{") == 0) { - $nextLevel -= 1; - $vhost_frx[$i] .= "\n"; - } - if ($nextLevel > 0) { - for ($j = 0; $j < $nextLevel; $j ++) { - $vhost_frx[$i] = " " . $vhost_frx[$i]; - } - } - if (substr_count($vhost_frx[$i], "{") != 0 && substr_count($vhost_frx[$i], "}") == 0) { - $nextLevel += 1; - } - } - - return implode("\n", $vhost_frx); - } - - protected function composeSslSettings($domain_or_ip) - { - $sslsettings = ''; - - if ($domain_or_ip['ssl_cert_file'] == '' || ! file_exists($domain_or_ip['ssl_cert_file'])) { - $domain_or_ip['ssl_cert_file'] = Settings::Get('system.ssl_cert_file'); - if (! file_exists($domain_or_ip['ssl_cert_file'])) { - // explicitly disable ssl for this vhost - $domain_or_ip['ssl_cert_file'] = ""; - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Disabling SSL-vhost for "' . $domain_or_ip['domain'] . '"'); - } - } - - if ($domain_or_ip['ssl_key_file'] == '' || ! file_exists($domain_or_ip['ssl_key_file'])) { - // use fallback - $domain_or_ip['ssl_key_file'] = Settings::Get('system.ssl_key_file'); - // check whether it exists - if (! file_exists($domain_or_ip['ssl_key_file'])) { - // explicitly disable ssl for this vhost - $domain_or_ip['ssl_cert_file'] = ""; - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate key-file "' . Settings::Get('system.ssl_key_file') . '" does not seem to exist. Disabling SSL-vhost for "' . $domain_or_ip['domain'] . '"'); - } - } - - if ($domain_or_ip['ssl_ca_file'] == '') { - $domain_or_ip['ssl_ca_file'] = Settings::Get('system.ssl_ca_file'); - } - - // #418 - if ($domain_or_ip['ssl_cert_chainfile'] == '') { - $domain_or_ip['ssl_cert_chainfile'] = Settings::Get('system.ssl_cert_chainfile'); - } - - if ($domain_or_ip['ssl_cert_file'] != '') { - - // check for existence, #1485 - if (! file_exists($domain_or_ip['ssl_cert_file'])) { - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, $domain_or_ip['domain'] . ' :: certificate file "' . $domain_or_ip['ssl_cert_file'] . '" does not exist! Cannot create ssl-directives'); - } else { - - $ssl_protocols = (isset($domain_or_ip['override_tls']) && $domain_or_ip['override_tls'] == '1' && ! empty($domain_or_ip['ssl_protocols'])) ? $domain_or_ip['ssl_protocols'] : Settings::Get('system.ssl_protocols'); - $ssl_cipher_list = (isset($domain_or_ip['override_tls']) && $domain_or_ip['override_tls'] == '1' && ! empty($domain_or_ip['ssl_cipher_list'])) ? $domain_or_ip['ssl_cipher_list'] : Settings::Get('system.ssl_cipher_list'); - - // obsolete: ssl on now belongs to the listen block as 'ssl' at the end - // $sslsettings .= "\t" . 'ssl on;' . "\n"; - $sslsettings .= "\t" . 'ssl_protocols ' . str_replace(",", " ", $ssl_protocols) . ';' . "\n"; - $sslsettings .= "\t" . 'ssl_ciphers ' . $ssl_cipher_list . ';' . "\n"; - if (! empty(Settings::Get('system.dhparams_file'))) { - $dhparams = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.dhparams_file')); - if (! file_exists($dhparams)) { - \Froxlor\FileDir::safe_exec('openssl dhparam -out ' . escapeshellarg($dhparams) . ' 4096'); - } - $sslsettings .= "\t" . 'ssl_dhparam ' . $dhparams . ';' . "\n"; - } - // When <1.11.0: Defaults to prime256v1, similar to first curve recommendation by Mozilla. - // (When specifyng just one, there's no fallback when specific curve is not supported by client.) - // When >1.11.0: Defaults to auto, using recommended curves provided by OpenSSL. - // see https://github.com/Froxlor/Froxlor/issues/652 - // $sslsettings .= "\t" . 'ssl_ecdh_curve secp384r1;' . "\n"; - $sslsettings .= "\t" . 'ssl_prefer_server_ciphers ' . (isset($domain_or_ip['ssl_honorcipherorder']) && $domain_or_ip['ssl_honorcipherorder'] == '1' ? 'on' : 'off') . ';' . "\n"; - if (Settings::Get('system.sessionticketsenabled') == '1') { - $sslsettings .= "\t" . 'ssl_session_tickets ' . (isset($domain_or_ip['ssl_sessiontickets']) && $domain_or_ip['ssl_sessiontickets'] == '1' ? 'on' : 'off') . ';' . "\n"; - } - $sslsettings .= "\t" . 'ssl_session_cache shared:SSL:10m;' . "\n"; - $sslsettings .= "\t" . 'ssl_certificate ' . \Froxlor\FileDir::makeCorrectFile($domain_or_ip['ssl_cert_file']) . ';' . "\n"; - - if ($domain_or_ip['ssl_key_file'] != '') { - // check for existence, #1485 - if (! file_exists($domain_or_ip['ssl_key_file'])) { - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, $domain_or_ip['domain'] . ' :: certificate key file "' . $domain_or_ip['ssl_key_file'] . '" does not exist! Cannot create ssl-directives'); - } else { - $sslsettings .= "\t" . 'ssl_certificate_key ' . \Froxlor\FileDir::makeCorrectFile($domain_or_ip['ssl_key_file']) . ';' . "\n"; - } - } - - if (isset($domain_or_ip['hsts']) && $domain_or_ip['hsts'] >= 0) { - $sslsettings .= 'add_header Strict-Transport-Security "max-age=' . $domain_or_ip['hsts']; - if ($domain_or_ip['hsts_sub'] == 1) { - $sslsettings .= '; includeSubDomains'; - } - if ($domain_or_ip['hsts_preload'] == 1) { - $sslsettings .= '; preload'; - } - $sslsettings .= '";' . "\n"; - } - - if ((isset($domain_or_ip['ocsp_stapling']) && $domain_or_ip['ocsp_stapling'] == "1") || (isset($domain_or_ip['letsencrypt']) && $domain_or_ip['letsencrypt'] == "1")) { - $sslsettings .= "\t" . 'ssl_stapling on;' . "\n"; - $sslsettings .= "\t" . 'ssl_stapling_verify on;' . "\n"; - $sslsettings .= "\t" . 'ssl_trusted_certificate ' . \Froxlor\FileDir::makeCorrectFile($domain_or_ip['ssl_cert_file']) . ';' . "\n"; - } - } - } - - return $sslsettings; - } - protected function createPathOptions($domain) { $result_stmt = Database::prepare(" SELECT * FROM " . TABLE_PANEL_HTACCESS . " WHERE `path` LIKE :docroot "); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'docroot' => $domain['documentroot'] . '%' - )); + ]); $path_options = ''; $htpasswds = $this->getHtpasswds($domain); // for each entry in the htaccess table - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { - if (! empty($row['error404path'])) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + if (!empty($row['error404path'])) { $defhandler = $row['error404path']; - if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) { - $defhandler = \Froxlor\FileDir::makeCorrectFile($defhandler); + if (!Validate::validateUrl($defhandler)) { + $defhandler = FileDir::makeCorrectFile($defhandler); } $path_options .= "\t" . 'error_page 404 ' . $defhandler . ';' . "\n"; } - if (! empty($row['error403path'])) { + if (!empty($row['error403path'])) { $defhandler = $row['error403path']; - if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) { - $defhandler = \Froxlor\FileDir::makeCorrectFile($defhandler); + if (!Validate::validateUrl($defhandler)) { + $defhandler = FileDir::makeCorrectFile($defhandler); } $path_options .= "\t" . 'error_page 403 ' . $defhandler . ';' . "\n"; } - if (! empty($row['error500path'])) { + if (!empty($row['error500path'])) { $defhandler = $row['error500path']; - if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) { - $defhandler = \Froxlor\FileDir::makeCorrectFile($defhandler); + if (!Validate::validateUrl($defhandler)) { + $defhandler = FileDir::makeCorrectFile($defhandler); } $path_options .= "\t" . 'error_page 500 502 503 504 ' . $defhandler . ';' . "\n"; } // if ($row['options_indexes'] != '0') { - $path = \Froxlor\FileDir::makeCorrectDir(substr($row['path'], strlen($domain['documentroot']) - 1)); + $path = FileDir::makeCorrectDir(substr($row['path'], strlen($domain['documentroot']) - 1)); - \Froxlor\FileDir::mkDirWithCorrectOwnership($domain['documentroot'], $row['path'], $domain['guid'], $domain['guid']); + FileDir::mkDirWithCorrectOwnership($domain['documentroot'], $row['path'], $domain['guid'], $domain['guid']); $path_options .= "\t" . '# ' . $path . "\n"; if ($path == '/') { @@ -826,7 +957,7 @@ class Nginx extends HttpConfigBase default: if ($single['path'] == '/') { $path_options .= "\t\t" . 'auth_basic "' . $single['authname'] . '";' . "\n"; - $path_options .= "\t\t" . 'auth_basic_user_file ' . \Froxlor\FileDir::makeCorrectFile($single['usrf']) . ';' . "\n"; + $path_options .= "\t\t" . 'auth_basic_user_file ' . FileDir::makeCorrectFile($single['usrf']) . ';' . "\n"; if ($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1') { $path_options .= "\t\t" . 'index index.php index.html index.htm;' . "\n"; } else { @@ -858,13 +989,13 @@ class Nginx extends HttpConfigBase * Perl support * required the fastCGI wrapper to be running to receive the CGI requests. */ - if (\Froxlor\Customer\Customer::customerHasPerlEnabled($domain['customerid']) && $row['options_cgi'] != '0') { - $path = \Froxlor\FileDir::makeCorrectDir(substr($row['path'], strlen($domain['documentroot']) - 1)); - \Froxlor\FileDir::mkDirWithCorrectOwnership($domain['documentroot'], $row['path'], $domain['guid'], $domain['guid']); + if (Customer::customerHasPerlEnabled($domain['customerid']) && $row['options_cgi'] != '0') { + $path = FileDir::makeCorrectDir(substr($row['path'], strlen($domain['documentroot']) - 1)); + FileDir::mkDirWithCorrectOwnership($domain['documentroot'], $row['path'], $domain['guid'], $domain['guid']); // We need to remove the last slash, otherwise the regex wouldn't work if ($row['path'] != $domain['documentroot']) { - $path = substr($path, 0, - 1); + $path = substr($path, 0, -1); } $path_options .= "\t" . 'location ~ \(.pl|.cgi)$ {' . "\n"; $path_options .= "\t\t" . 'gzip off; #gzip makes scripts feel slower since they have to complete before getting gzipped' . "\n"; @@ -886,9 +1017,9 @@ class Nginx extends HttpConfigBase unset($htpasswds[$idx]); break; default: - $path_options .= "\t" . 'location ' . \Froxlor\FileDir::makeCorrectDir($single['path']) . ' {' . "\n"; + $path_options .= "\t" . 'location ' . FileDir::makeCorrectDir($single['path']) . ' {' . "\n"; $path_options .= "\t\t" . 'auth_basic "' . $single['authname'] . '";' . "\n"; - $path_options .= "\t\t" . 'auth_basic_user_file ' . \Froxlor\FileDir::makeCorrectFile($single['usrf']) . ';' . "\n"; + $path_options .= "\t\t" . 'auth_basic_user_file ' . FileDir::makeCorrectFile($single['usrf']) . ';' . "\n"; if ($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1') { $path_options .= "\t\t" . 'index index.php index.html index.htm;' . "\n"; } else { @@ -915,19 +1046,19 @@ class Nginx extends HttpConfigBase JOIN `" . TABLE_PANEL_DOMAINS . "` AS b USING (`customerid`) WHERE b.customerid = :customerid AND b.domain = :domain "); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'customerid' => $domain['customerid'], 'domain' => $domain['domain'] - )); + ]); - $returnval = array(); + $returnval = []; $x = 0; - while ($row_htpasswds = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row_htpasswds = $result_stmt->fetch(PDO::FETCH_ASSOC)) { if (count($row_htpasswds) > 0) { - $htpasswd_filename = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_htpasswddir') . '/' . $row_htpasswds['customerid'] . '-' . md5($row_htpasswds['path']) . '.htpasswd'); + $htpasswd_filename = FileDir::makeCorrectFile(Settings::Get('system.apacheconf_htpasswddir') . '/' . $row_htpasswds['customerid'] . '-' . md5($row_htpasswds['path']) . '.htpasswd'); // ensure we can write to the array with index $htpasswd_filename - if (! isset($this->htpasswds_data[$htpasswd_filename])) { + if (!isset($this->htpasswds_data[$htpasswd_filename])) { $this->htpasswds_data[$htpasswd_filename] = ''; } @@ -937,21 +1068,21 @@ class Nginx extends HttpConfigBase // the nginx user, we have to evaluate the right path which is to protect if (stripos($row_htpasswds['path'], $domain['documentroot']) !== false) { // if the website contents is located in the user directory - $path = \Froxlor\FileDir::makeCorrectDir(substr($row_htpasswds['path'], strlen($domain['documentroot']) - 1)); + $path = FileDir::makeCorrectDir(substr($row_htpasswds['path'], strlen($domain['documentroot']) - 1)); } else { // if the website contents is located in a subdirectory of the user - $matches = array(); + $matches = []; preg_match('/^([\/[:print:]]*\/)([[:print:]\/]+){1}$/i', $row_htpasswds['path'], $matches); - $path = \Froxlor\FileDir::makeCorrectDir(substr($row_htpasswds['path'], strlen($matches[1]) - 1)); + $path = FileDir::makeCorrectDir(substr($row_htpasswds['path'], strlen($matches[1]) - 1)); } $returnval[$x]['path'] = $path; - $returnval[$x]['root'] = \Froxlor\FileDir::makeCorrectDir($domain['documentroot']); + $returnval[$x]['root'] = FileDir::makeCorrectDir($domain['documentroot']); // Ensure there is only one auth name per password block, otherwise // the directives are inserted multiple times -> invalid config $authname = $row_htpasswds['authname']; - for ($i = 0; $i < $x; $i ++) { + for ($i = 0; $i < $x; $i++) { if ($returnval[$i]['usrf'] == $htpasswd_filename) { $authname = $returnval[$i]['authname']; break; @@ -960,7 +1091,7 @@ class Nginx extends HttpConfigBase $returnval[$x]['authname'] = $authname; $returnval[$x]['usrf'] = $htpasswd_filename; - $x ++; + $x++; } } @@ -970,6 +1101,47 @@ class Nginx extends HttpConfigBase return $returnval; } + protected function getStats($domain, $single) + { + $stats_text = ''; + + // define basic path to the stats + if (Settings::Get('system.awstats_enabled') == '1') { + $alias_dir = FileDir::makeCorrectFile($domain['customerroot'] . '/awstats/'); + } else { + $alias_dir = FileDir::makeCorrectFile($domain['customerroot'] . '/webalizer/'); + } + + // if this is a parentdomain, we use this domain-name + if ($domain['parentdomainid'] == '0') { + $alias_dir = FileDir::makeCorrectDir($alias_dir . '/' . $domain['domain']); + } else { + $alias_dir = FileDir::makeCorrectDir($alias_dir . '/' . $domain['parentdomain']); + } + + if (Settings::Get('system.awstats_enabled') == '1') { + // awstats + $stats_text .= "\t" . 'location ^~ /awstats/ {' . "\n"; + } else { + // webalizer + $stats_text .= "\t" . 'location ^~ /webalizer {' . "\n"; + } + + $stats_text .= "\t\t" . 'alias ' . $alias_dir . ';' . "\n"; + $stats_text .= "\t\t" . 'auth_basic "' . $single['authname'] . '";' . "\n"; + $stats_text .= "\t\t" . 'auth_basic_user_file ' . FileDir::makeCorrectFile($single['usrf']) . ';' . "\n"; + $stats_text .= "\t" . '}' . "\n\n"; + + // awstats icons + if (Settings::Get('system.awstats_enabled') == '1') { + $stats_text .= "\t" . 'location ~ ^/awstats-icon/(.*)$ {' . "\n"; + $stats_text .= "\t\t" . 'alias ' . FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '$1;' . "\n"; + $stats_text .= "\t" . '}' . "\n\n"; + } + + return $stats_text; + } + protected function composePhpOptions(&$domain, $ssl_vhost = false) { $phpopts = ''; @@ -994,171 +1166,41 @@ class Nginx extends HttpConfigBase return $phpopts; } - protected function getWebroot($domain, $ssl) + /** + * define a default ErrorDocument-statement, bug #unknown-yet + */ + private function createStandardErrorHandler() { - $webroot_text = ''; - - if ($domain['deactivated'] == '1' && Settings::Get('system.deactivateddocroot') != '') { - $webroot_text .= "\t" . '# Using docroot for deactivated users...' . "\n"; - $webroot_text .= "\t" . 'root ' . \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.deactivateddocroot')) . ';' . "\n"; - $this->deactivated = true; - } else { - $webroot_text .= "\t" . 'root ' . \Froxlor\FileDir::makeCorrectDir($domain['documentroot']) . ';' . "\n"; - $this->deactivated = false; - } - - $webroot_text .= "\n\t" . 'location / {' . "\n"; - - if ($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1') { - $webroot_text .= "\t" . 'index index.php index.html index.htm;' . "\n"; - if ($domain['notryfiles'] != 1) { - $webroot_text .= "\t\t" . 'try_files $uri $uri/ @rewrites;' . "\n"; - } - } else { - $webroot_text .= "\t" . 'index index.html index.htm;' . "\n"; - } - - if ($this->vhost_root_autoindex) { - $webroot_text .= "\t\t" . 'autoindex on;' . "\n"; - $this->vhost_root_autoindex = false; - } - - $webroot_text .= "\t" . '}' . "\n\n"; - if ($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1' && $domain['notryfiles'] != 1) { - $webroot_text .= "\tlocation @rewrites {\n"; - $webroot_text .= "\t\trewrite ^ /index.php last;\n"; - $webroot_text .= "\t}\n\n"; - } - - return $webroot_text; - } - - protected function getStats($domain, $single) - { - $stats_text = ''; - - // define basic path to the stats - if (Settings::Get('system.awstats_enabled') == '1') { - $alias_dir = \Froxlor\FileDir::makeCorrectFile($domain['customerroot'] . '/awstats/'); - } else { - $alias_dir = \Froxlor\FileDir::makeCorrectFile($domain['customerroot'] . '/webalizer/'); - } - - // if this is a parentdomain, we use this domain-name - if ($domain['parentdomainid'] == '0') { - $alias_dir = \Froxlor\FileDir::makeCorrectDir($alias_dir . '/' . $domain['domain']); - } else { - $alias_dir = \Froxlor\FileDir::makeCorrectDir($alias_dir . '/' . $domain['parentdomain']); - } - - if (Settings::Get('system.awstats_enabled') == '1') { - // awstats - $stats_text .= "\t" . 'location ^~ /awstats/ {' . "\n"; - } else { - // webalizer - $stats_text .= "\t" . 'location ^~ /webalizer {' . "\n"; - } - - $stats_text .= "\t\t" . 'alias ' . $alias_dir . ';' . "\n"; - $stats_text .= "\t\t" . 'auth_basic "' . $single['authname'] . '";' . "\n"; - $stats_text .= "\t\t" . 'auth_basic_user_file ' . \Froxlor\FileDir::makeCorrectFile($single['usrf']) . ';' . "\n"; - $stats_text .= "\t" . '}' . "\n\n"; - - // awstats icons - if (Settings::Get('system.awstats_enabled') == '1') { - $stats_text .= "\t" . 'location ~ ^/awstats-icon/(.*)$ {' . "\n"; - $stats_text .= "\t\t" . 'alias ' . \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '$1;' . "\n"; - $stats_text .= "\t" . '}' . "\n\n"; - } - - return $stats_text; - } - - protected function getLogFiles($domain) - { - $logfiles_text = ''; - - $speciallogfile = ''; - if ($domain['speciallogfile'] == '1') { - if ($domain['parentdomainid'] == '0') { - $speciallogfile = '-' . $domain['domain']; + if (Settings::Get('defaultwebsrverrhandler.enabled') == '1' && (Settings::Get('defaultwebsrverrhandler.err401') != '' || Settings::Get('defaultwebsrverrhandler.err403') != '' || Settings::Get('defaultwebsrverrhandler.err404') != '' || Settings::Get('defaultwebsrverrhandler.err500') != '')) { + $vhosts_folder = ''; + if (is_dir(Settings::Get('system.apacheconf_vhost'))) { + $vhosts_folder = FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')); } else { - $speciallogfile = '-' . $domain['parentdomain']; + $vhosts_folder = FileDir::makeCorrectDir(dirname(Settings::Get('system.apacheconf_vhost'))); } - } - if ($domain['writeerrorlog']) { - // The normal access/error - logging is enabled - $error_log = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-error.log'); - // Create the logfile if it does not exist (fixes #46) - touch($error_log); - chown($error_log, Settings::Get('system.httpuser')); - chgrp($error_log, Settings::Get('system.httpgroup')); - } else { - $error_log = '/dev/null'; - } + $vhosts_filename = FileDir::makeCorrectFile($vhosts_folder . '/05_froxlor_default_errorhandler.conf'); - if ($domain['writeaccesslog']) { - $access_log = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-access.log'); - // Create the logfile if it does not exist (fixes #46) - touch($access_log); - chown($access_log, Settings::Get('system.httpuser')); - chgrp($access_log, Settings::Get('system.httpgroup')); - } else { - $access_log = '/dev/null'; - } + if (!isset($this->nginx_data[$vhosts_filename])) { + $this->nginx_data[$vhosts_filename] = ''; + } - $logtype = 'combined'; - if (Settings::Get('system.logfiles_format') != '') { - $logtype = 'frx_custom'; - } - - $logfiles_text .= "\t" . 'access_log ' . $access_log . ' ' . $logtype . ';' . "\n"; - $logfiles_text .= "\t" . 'error_log ' . $error_log . ' ' . \Froxlor\Settings::Get('system.errorlog_level') . ';' . "\n"; - - if (Settings::Get('system.awstats_enabled') == '1') { - if ((int) $domain['parentdomainid'] == 0) { - // prepare the aliases and subdomains for stats config files - $server_alias = ''; - $alias_domains_stmt = Database::prepare(" - SELECT `domain`, `iswildcarddomain`, `wwwserveralias` - FROM `" . TABLE_PANEL_DOMAINS . "` - WHERE `aliasdomain` = :domainid OR `parentdomainid` = :domainid - "); - Database::pexecute($alias_domains_stmt, array( - 'domainid' => $domain['id'] - )); - - while (($alias_domain = $alias_domains_stmt->fetch(\PDO::FETCH_ASSOC)) !== false) { - $server_alias .= ' ' . $alias_domain['domain'] . ' '; - - if ($alias_domain['iswildcarddomain'] == '1') { - $server_alias .= '*.' . $domain['domain']; - } else { - if ($alias_domain['wwwserveralias'] == '1') { - $server_alias .= 'www.' . $alias_domain['domain']; - } else { - $server_alias .= ''; - } + $statusCodes = [ + '401', + '403', + '404', + '500' + ]; + foreach ($statusCodes as $statusCode) { + if (Settings::Get('defaultwebsrverrhandler.err' . $statusCode) != '') { + $defhandler = Settings::Get('defaultwebsrverrhandler.err' . $statusCode); + if (!Validate::validateUrl($defhandler)) { + $defhandler = FileDir::makeCorrectFile($defhandler); } + $this->nginx_data[$vhosts_filename] .= 'error_page ' . $statusCode . ' ' . $defhandler . ';' . "\n"; } - - $alias = ''; - if ($domain['iswildcarddomain'] == '1') { - $alias = '*.' . $domain['domain']; - } elseif ($domain['wwwserveralias'] == '1') { - $alias = 'www.' . $domain['domain']; - } - - // After inserting the AWStats information, - // be sure to build the awstats conf file as well - // and chown it using $awstats_params, #258 - // Bug 960 + Bug 970 : Use full $domain instead of custom $awstats_params as following classes depend on the information - \Froxlor\Http\Statistics::createAWStatsConf(Settings::Get('system.logfiles_directory') . $domain['loginname'] . $speciallogfile . '-access.log', $domain['domain'], $alias . $server_alias, $domain['customerroot'], $domain); } } - - return $logfiles_text; } public function createOwnVhostStarter() @@ -1166,50 +1208,12 @@ class Nginx extends HttpConfigBase return; } - protected function getServerNames($domain) - { - $server_alias = ''; - - if ($domain['iswildcarddomain'] == '1') { - $server_alias = '*.' . $domain['domain']; - } elseif ($domain['wwwserveralias'] == '1') { - $server_alias = 'www.' . $domain['domain']; - } - - $alias_domains_stmt = Database::prepare(" - SELECT `domain`, `iswildcarddomain`, `wwwserveralias` - FROM `" . TABLE_PANEL_DOMAINS . "` - WHERE `aliasdomain` = :domainid - "); - Database::pexecute($alias_domains_stmt, array( - 'domainid' => $domain['id'] - )); - - while (($alias_domain = $alias_domains_stmt->fetch(\PDO::FETCH_ASSOC)) !== false) { - $server_alias .= ' ' . $alias_domain['domain']; - - if ($alias_domain['iswildcarddomain'] == '1') { - $server_alias .= ' *.' . $alias_domain['domain']; - } elseif ($alias_domain['wwwserveralias'] == '1') { - $server_alias .= ' www.' . $alias_domain['domain']; - } - } - - $servernames_text = "\t" . 'server_name ' . $domain['domain']; - if (trim($server_alias) != '') { - $servernames_text .= ' ' . $server_alias; - } - $servernames_text .= ';' . "\n"; - - return $servernames_text; - } - public function writeConfigs() { - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "nginx::writeConfigs: rebuilding " . Settings::Get('system.apacheconf_vhost')); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "nginx::writeConfigs: rebuilding " . Settings::Get('system.apacheconf_vhost')); - $vhostDir = new \Froxlor\Http\Directory(Settings::Get('system.apacheconf_vhost')); - if (! $vhostDir->isConfigDir()) { + $vhostDir = new Directory(Settings::Get('system.apacheconf_vhost')); + if (!$vhostDir->isConfigDir()) { // Save one big file $vhosts_file = ''; @@ -1231,9 +1235,9 @@ class Nginx extends HttpConfigBase fwrite($vhosts_file_handler, $vhosts_file); fclose($vhosts_file_handler); } else { - if (! file_exists(Settings::Get('system.apacheconf_vhost'))) { - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'nginx::writeConfigs: mkdir ' . escapeshellarg(\Froxlor\FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); - \Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg(\Froxlor\FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); + if (!file_exists(Settings::Get('system.apacheconf_vhost'))) { + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'nginx::writeConfigs: mkdir ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); + FileDir::safe_exec('mkdir -p ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); } // Write a single file for every vhost @@ -1243,7 +1247,7 @@ class Nginx extends HttpConfigBase // Apply header $vhosts_file = '# ' . basename($vhosts_filename) . "\n" . '# Created ' . date('d.m.Y H:i') . "\n" . '# Do NOT manually edit this file, all changes will be deleted after the next domain change at the panel.' . "\n" . "\n" . $vhosts_file; - if (! empty($vhosts_filename)) { + if (!empty($vhosts_filename)) { $vhosts_file_handler = fopen($vhosts_filename, 'w'); fwrite($vhosts_file_handler, $vhosts_file); fclose($vhosts_file_handler); @@ -1253,13 +1257,13 @@ class Nginx extends HttpConfigBase // htaccess stuff if (count($this->htpasswds_data) > 0) { - if (! file_exists(Settings::Get('system.apacheconf_htpasswddir'))) { + if (!file_exists(Settings::Get('system.apacheconf_htpasswddir'))) { $umask = umask(); umask(0000); mkdir(Settings::Get('system.apacheconf_htpasswddir'), 0751); umask($umask); - } elseif (! is_dir(Settings::Get('system.apacheconf_htpasswddir'))) { - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_WARNING, 'WARNING!!! ' . Settings::Get('system.apacheconf_htpasswddir') . ' is not a directory. htpasswd directory protection is disabled!!!'); + } elseif (!is_dir(Settings::Get('system.apacheconf_htpasswddir'))) { + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, 'WARNING!!! ' . Settings::Get('system.apacheconf_htpasswddir') . ' is not a directory. htpasswd directory protection is disabled!!!'); } if (is_dir(Settings::Get('system.apacheconf_htpasswddir'))) { diff --git a/lib/Froxlor/Cron/Http/NginxFcgi.php b/lib/Froxlor/Cron/Http/NginxFcgi.php index 9cdc1fe6..e655b0fa 100644 --- a/lib/Froxlor/Cron/Http/NginxFcgi.php +++ b/lib/Froxlor/Cron/Http/NginxFcgi.php @@ -1,34 +1,103 @@ (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 + * @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); - } - } } diff --git a/lib/Froxlor/Cron/Http/Php/Fcgid.php b/lib/Froxlor/Cron/Http/Php/Fcgid.php index 2cc74869..8add4866 100644 --- a/lib/Froxlor/Cron/Http/Php/Fcgid.php +++ b/lib/Froxlor/Cron/Http/Php/Fcgid.php @@ -1,27 +1,36 @@ - * @author Froxlor team (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 + * @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]; - } } diff --git a/lib/Froxlor/Cron/Http/Php/Fpm.php b/lib/Froxlor/Cron/Http/Php/Fpm.php index 5e826677..6ed3fb1c 100644 --- a/lib/Froxlor/Cron/Http/Php/Fpm.php +++ b/lib/Froxlor/Cron/Http/Php/Fpm.php @@ -1,27 +1,36 @@ - * @author Froxlor team (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 + * @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]; - } } diff --git a/lib/Froxlor/Cron/Http/Php/PhpInterface.php b/lib/Froxlor/Cron/Http/Php/PhpInterface.php index ae57f5f9..015fe978 100644 --- a/lib/Froxlor/Cron/Http/Php/PhpInterface.php +++ b/lib/Froxlor/Cron/Http/Php/PhpInterface.php @@ -1,27 +1,33 @@ - * @author Froxlor team (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 + * @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']; diff --git a/lib/Froxlor/Cron/Http/WebserverBase.php b/lib/Froxlor/Cron/Http/WebserverBase.php index fbca2677..86c30dea 100644 --- a/lib/Froxlor/Cron/Http/WebserverBase.php +++ b/lib/Froxlor/Cron/Http/WebserverBase.php @@ -1,26 +1,35 @@ - * @author Froxlor team (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 + * @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 { diff --git a/lib/Froxlor/Cron/MasterCron.php b/lib/Froxlor/Cron/MasterCron.php index c280b7c4..46178f91 100644 --- a/lib/Froxlor/Cron/MasterCron.php +++ b/lib/Froxlor/Cron/MasterCron.php @@ -1,23 +1,41 @@ (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 + * @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()); + } + } } diff --git a/lib/Froxlor/Cron/System/BackupCron.php b/lib/Froxlor/Cron/System/BackupCron.php index d6e4e68e..33a7fe11 100644 --- a/lib/Froxlor/Cron/System/BackupCron.php +++ b/lib/Froxlor/Cron/System/BackupCron.php @@ -1,35 +1,44 @@ - * @author Froxlor team (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 + * @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'])); } } } diff --git a/lib/Froxlor/Cron/System/Extrausers.php b/lib/Froxlor/Cron/System/Extrausers.php index 4cc79fbd..9947f946 100644 --- a/lib/Froxlor/Cron/System/Extrausers.php +++ b/lib/Froxlor/Cron/System/Extrausers.php @@ -1,23 +1,37 @@ (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 + * @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'); } } diff --git a/lib/Froxlor/Cron/System/MailboxsizeCron.php b/lib/Froxlor/Cron/System/MailboxsizeCron.php index d35df4ef..0e4c5750 100644 --- a/lib/Froxlor/Cron/System/MailboxsizeCron.php +++ b/lib/Froxlor/Cron/System/MailboxsizeCron.php @@ -1,48 +1,61 @@ - * @author Froxlor team (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 + * @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'); } } } diff --git a/lib/Froxlor/Cron/System/TasksCron.php b/lib/Froxlor/Cron/System/TasksCron.php index b2690c86..982a4b04 100644 --- a/lib/Froxlor/Cron/System/TasksCron.php +++ b/lib/Froxlor/Cron/System/TasksCron.php @@ -1,28 +1,42 @@ (2003-2009) - * @author Froxlor team (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 + * @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'))); } } } diff --git a/lib/Froxlor/Cron/TaskId.php b/lib/Froxlor/Cron/TaskId.php index f862e2fe..4d388ce2 100644 --- a/lib/Froxlor/Cron/TaskId.php +++ b/lib/Froxlor/Cron/TaskId.php @@ -1,9 +1,34 @@ + * @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); } } - diff --git a/lib/Froxlor/Cron/Traffic/ReportsCron.php b/lib/Froxlor/Cron/Traffic/ReportsCron.php index bd24d0ac..be549f09 100644 --- a/lib/Froxlor/Cron/Traffic/ReportsCron.php +++ b/lib/Froxlor/Cron/Traffic/ReportsCron.php @@ -1,39 +1,61 @@ (2003-2009) - * @author Froxlor team (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 + * @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 (2003-2009) + * @author Froxlor team (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); } diff --git a/lib/Froxlor/Cron/Traffic/TrafficCron.php b/lib/Froxlor/Cron/Traffic/TrafficCron.php index f3bcd385..9d8a872e 100644 --- a/lib/Froxlor/Cron/Traffic/TrafficCron.php +++ b/lib/Froxlor/Cron/Traffic/TrafficCron.php @@ -1,34 +1,53 @@ (2003-2009) - * @author Froxlor team (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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -use Froxlor\Database\Database; -use Froxlor\Settings; -class TrafficCron extends \Froxlor\Cron\FroxlorCron +namespace Froxlor\Cron\Traffic; + +/** + * @author Florian Lippert (2003-2009) + * @author Froxlor team (2010-) + */ + +use Froxlor\Cron\FroxlorCron; +use Froxlor\Database\Database; +use Froxlor\FileDir; +use Froxlor\Froxlor; +use Froxlor\FroxlorLogger; +use Froxlor\Http\Statistics; +use Froxlor\MailLogParser; +use Froxlor\Settings; +use PDO; + +class TrafficCron extends FroxlorCron { public static function run() { - // Check Traffic-Lock - if (function_exists('pcntl_fork') && ! defined('CRON_NOFORK_FLAG')) { - $TrafficLock = \Froxlor\FileDir::makeCorrectFile("/var/run/froxlor_cron_traffic.lock"); + if (function_exists('pcntl_fork') && !defined('CRON_NOFORK_FLAG')) { + $TrafficLock = FileDir::makeCorrectFile("/var/run/froxlor_cron_traffic.lock"); if (file_exists($TrafficLock) && is_numeric($TrafficPid = file_get_contents($TrafficLock))) { if (function_exists('posix_kill')) { $TrafficPidStatus = @posix_kill($TrafficPid, 0); @@ -37,7 +56,7 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron $TrafficPidStatus = !$TrafficPidStatus; } if ($TrafficPidStatus) { - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Traffic Run already in progress'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Traffic Run already in progress'); return 1; } } @@ -65,57 +84,55 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron } else { $msg = "PHP compiled without pcntl."; } - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, $msg . " Not forking traffic-cron, this may take a long time!"); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, $msg . " Not forking traffic-cron, this may take a long time!"); } /** * TRAFFIC AND DISKUSAGE MEASURE */ - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Traffic run started...'); - $admin_traffic = array(); - $domainlist = array(); - $speciallogfile_domainlist = array(); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Traffic run started...'); + $admin_traffic = []; + $domainlist = []; + $speciallogfile_domainlist = []; $result_domainlist_stmt = Database::query(" SELECT `id`, `domain`, `customerid`, `parentdomainid`, `speciallogfile` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `aliasdomain` IS NULL AND `email_only` <> '1'; "); - while ($row_domainlist = $result_domainlist_stmt->fetch(\PDO::FETCH_ASSOC)) { - - if (! isset($domainlist[$row_domainlist['customerid']])) { - $domainlist[$row_domainlist['customerid']] = array(); + while ($row_domainlist = $result_domainlist_stmt->fetch(PDO::FETCH_ASSOC)) { + if (!isset($domainlist[$row_domainlist['customerid']])) { + $domainlist[$row_domainlist['customerid']] = []; } $domainlist[$row_domainlist['customerid']][$row_domainlist['id']] = $row_domainlist['domain']; if ($row_domainlist['parentdomainid'] == '0' && $row_domainlist['speciallogfile'] == '1') { - if (! isset($speciallogfile_domainlist[$row_domainlist['customerid']])) { - $speciallogfile_domainlist[$row_domainlist['customerid']] = array(); + if (!isset($speciallogfile_domainlist[$row_domainlist['customerid']])) { + $speciallogfile_domainlist[$row_domainlist['customerid']] = []; } $speciallogfile_domainlist[$row_domainlist['customerid']][$row_domainlist['id']] = $row_domainlist['domain']; } } - $mysqlusage_all = array(); + $mysqlusage_all = []; $databases_stmt = Database::query("SELECT * FROM " . TABLE_PANEL_DATABASES . " ORDER BY `dbserver`"); $last_dbserver = 0; - $databases_list = array(); + $databases_list = []; Database::needRoot(true); $databases_list_result_stmt = Database::query("SHOW DATABASES"); - while ($databases_list_row = $databases_list_result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($databases_list_row = $databases_list_result_stmt->fetch(PDO::FETCH_ASSOC)) { $databases_list[] = strtolower($databases_list_row['Database']); } - while ($row_database = $databases_stmt->fetch(\PDO::FETCH_ASSOC)) { - + while ($row_database = $databases_stmt->fetch(PDO::FETCH_ASSOC)) { if ($last_dbserver != $row_database['dbserver']) { Database::needRoot(true, $row_database['dbserver']); $last_dbserver = $row_database['dbserver']; - $databases_list = array(); + $databases_list = []; $databases_list_result_stmt = Database::query("SHOW DATABASES"); - while ($databases_list_row = $databases_list_result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($databases_list_row = $databases_list_result_stmt->fetch(PDO::FETCH_ASSOC)) { $databases_list[] = strtolower($databases_list_row['Database']); } } @@ -129,21 +146,21 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron GROUP BY table_schema; "); // get the result - $mysql_usage_row = Database::pexecute_first($mysql_usage_result_stmt, array( + $mysql_usage_row = Database::pexecute_first($mysql_usage_result_stmt, [ 'database' => $row_database['databasename'] - )); + ]); // initialize counter for customer - if (! isset($mysqlusage_all[$row_database['customerid']])) { + if (!isset($mysqlusage_all[$row_database['customerid']])) { $mysqlusage_all[$row_database['customerid']] = 0; } // sum up result if ($mysql_usage_row) { $mysqlusage_all[$row_database['customerid']] += floatval($mysql_usage_row['customerusage']); } else { - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_WARNING, "Cannot get usage for database " . $row_database['databasename'] . "."); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Cannot get usage for database " . $row_database['databasename'] . "."); } } else { - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_WARNING, "Seems like the database " . $row_database['databasename'] . " had been removed manually."); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Seems like the database " . $row_database['databasename'] . " had been removed manually."); } } @@ -151,14 +168,14 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron // We are using the file-system quota, this will speed up the diskusage - collection if (Settings::Get('system.diskquota_enabled')) { - $usedquota = \Froxlor\FileDir::getFilesystemQuota(); + $usedquota = FileDir::getFilesystemQuota(); } /** * MAIL-Traffic */ if (Settings::Get("system.mailtraffic_enabled")) { - $mailTrafficCalc = new \Froxlor\MailLogParser(Settings::Get("system.last_traffic_run")); + $mailTrafficCalc = new MailLogParser(Settings::Get("system.last_traffic_run")); } $result_stmt = Database::query("SELECT * FROM `" . TABLE_PANEL_CUSTOMERS . "` ORDER BY `customerid` ASC"); @@ -170,11 +187,11 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron $current_month = date('m', $current_stamp); $current_day = date('d', $current_stamp); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { /** * HTTP-Traffic */ - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'http traffic for ' . $row['loginname'] . ' started...'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'http traffic for ' . $row['loginname'] . ' started...'); $httptraffic = 0; if (isset($domainlist[$row['customerid']]) && is_array($domainlist[$row['customerid']]) && count($domainlist[$row['customerid']]) != 0) { @@ -188,8 +205,7 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron // ... which results in non-usable links to files in the stats, so lets have a look if we find a domain which is not speciallogfiledomain foreach ($domainlist[$row['customerid']] as $domainid => $domain) { - - if (! isset($speciallogfile_domainlist[$row['customerid']]) || ! isset($speciallogfile_domainlist[$row['customerid']][$domainid])) { + if (!isset($speciallogfile_domainlist[$row['customerid']]) || !isset($speciallogfile_domainlist[$row['customerid']][$domainid])) { $caption = $domain; break; } @@ -221,56 +237,56 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron } // make the stuff readable for the customer, #258 - \Froxlor\Http\Statistics::makeChownWithNewStats($row); + Statistics::makeChownWithNewStats($row); } /** * FTP-Traffic */ - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'ftp traffic for ' . $row['loginname'] . ' started...'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'ftp traffic for ' . $row['loginname'] . ' started...'); $ftptraffic_stmt = Database::prepare(" SELECT SUM(`up_bytes`) AS `up_bytes_sum`, SUM(`down_bytes`) AS `down_bytes_sum` FROM `" . TABLE_FTP_USERS . "` WHERE `customerid` = :customerid "); - $ftptraffic = Database::pexecute_first($ftptraffic_stmt, array( + $ftptraffic = Database::pexecute_first($ftptraffic_stmt, [ 'customerid' => $row['customerid'] - )); + ]); - if (! is_array($ftptraffic)) { - $ftptraffic = array( + if (!is_array($ftptraffic)) { + $ftptraffic = [ 'up_bytes_sum' => 0, 'down_bytes_sum' => 0 - ); + ]; } $upd_stmt = Database::prepare(" UPDATE `" . TABLE_FTP_USERS . "` SET `up_bytes` = '0', `down_bytes` = '0' WHERE `customerid` = :customerid "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'customerid' => $row['customerid'] - )); + ]); /** * Mail-Traffic */ $mailtraffic = 0; if (Settings::Get("system.mailtraffic_enabled")) { - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'mail traffic usage for ' . $row['loginname'] . " started..."); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'mail traffic usage for ' . $row['loginname'] . " started..."); $domains_stmt = Database::prepare("SELECT domain FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :cid"); - Database::pexecute($domains_stmt, array( + Database::pexecute($domains_stmt, [ "cid" => $row['customerid'] - )); - while ($domainRow = $domains_stmt->fetch(\PDO::FETCH_ASSOC)) { + ]); + while ($domainRow = $domains_stmt->fetch(PDO::FETCH_ASSOC)) { $domainMailTraffic = $mailTrafficCalc->getDomainTraffic($domainRow["domain"]); - if (! is_array($domainMailTraffic)) { + if (!is_array($domainMailTraffic)) { continue; } foreach ($domainMailTraffic as $dateTraffic => $dayTraffic) { $dayTraffic = floatval($dayTraffic / 1024); - list ($year, $month, $day) = explode("-", $dateTraffic); + [$year, $month, $day] = explode("-", $dateTraffic); if ($dateTraffic == $currentDate) { $mailtraffic = $dayTraffic; } else { @@ -281,23 +297,23 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron AND `month` = :month AND `day` = :day "); - $params = array( + $params = [ "cid" => $row['customerid'], "year" => $year, "month" => $month, "day" => $day - ); + ]; Database::pexecute($stmt, $params); if ($stmt->rowCount() > 0) { - $updRow = $stmt->fetch(\PDO::FETCH_ASSOC); + $updRow = $stmt->fetch(PDO::FETCH_ASSOC); $upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_TRAFFIC . "` SET `mail` = :mail WHERE `id` = :id "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ "mail" => $updRow['mail'] + $dayTraffic, "id" => $updRow['id'] - )); + ]); } } } @@ -307,15 +323,15 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron /** * Total Traffic */ - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'total traffic for ' . $row['loginname'] . ' started'); - $current_traffic = array(); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'total traffic for ' . $row['loginname'] . ' started'); + $current_traffic = []; $current_traffic['http'] = floatval($httptraffic); $current_traffic['ftp_up'] = floatval(($ftptraffic['up_bytes_sum'] / 1024)); $current_traffic['ftp_down'] = floatval(($ftptraffic['down_bytes_sum'] / 1024)); $current_traffic['mail'] = floatval($mailtraffic); $current_traffic['all'] = $current_traffic['http'] + $current_traffic['ftp_up'] + $current_traffic['ftp_down'] + $current_traffic['mail']; - $ins_data = array( + $ins_data = [ 'customerid' => $row['customerid'], 'year' => $current_year, 'month' => $current_month, @@ -325,7 +341,7 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron 'ftp_up' => $current_traffic['ftp_up'], 'ftp_down' => $current_traffic['ftp_down'], 'mail' => $current_traffic['mail'] - ); + ]; $ins_stmt = Database::prepare(" INSERT INTO `" . TABLE_PANEL_TRAFFIC . "` SET `customerid` = :customerid, @@ -344,14 +360,14 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron SELECT SUM(`http`) AS `http`, SUM(`ftp_up`) AS `ftp_up`, SUM(`ftp_down`) AS `ftp_down`, SUM(`mail`) AS `mail` FROM `" . TABLE_PANEL_TRAFFIC . "` WHERE `year` = :year AND `month` = :month AND `customerid` = :customerid "); - $sum_month_traffic = Database::pexecute_first($sum_month_traffic_stmt, array( + $sum_month_traffic = Database::pexecute_first($sum_month_traffic_stmt, [ 'year' => $current_year, 'month' => $current_month, 'customerid' => $row['customerid'] - )); + ]); $sum_month_traffic['all'] = $sum_month_traffic['http'] + $sum_month_traffic['ftp_up'] + $sum_month_traffic['ftp_down'] + $sum_month_traffic['mail']; - if (! isset($admin_traffic[$row['adminid']]) || ! is_array($admin_traffic[$row['adminid']])) { + if (!isset($admin_traffic[$row['adminid']]) || !is_array($admin_traffic[$row['adminid']])) { $admin_traffic[$row['adminid']]['http'] = 0; $admin_traffic[$row['adminid']]['ftp_up'] = 0; $admin_traffic[$row['adminid']]['ftp_down'] = 0; @@ -370,7 +386,7 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron /** * WebSpace-Usage */ - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'calculating webspace usage for ' . $row['loginname']); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'calculating webspace usage for ' . $row['loginname']); $webspaceusage = 0; // Using repquota, it's faster using this tool than using du traversing the complete directory @@ -378,10 +394,9 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron // We may use the array we created earlier, the used diskspace is stored in [][block][used] $webspaceusage = floatval($usedquota[$row['guid']]['block']['used']); } else { - // Use the old fashioned way with "du" if (file_exists($row['documentroot']) && is_dir($row['documentroot'])) { - $back = \Froxlor\FileDir::safe_exec('du -sk ' . escapeshellarg($row['documentroot']) . ''); + $back = FileDir::safe_exec('du -sk ' . escapeshellarg($row['documentroot']) . ''); foreach ($back as $backrow) { $webspaceusage = explode(' ', $backrow); } @@ -389,19 +404,19 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron $webspaceusage = floatval($webspaceusage['0']); unset($back); } else { - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_WARNING, 'documentroot ' . $row['documentroot'] . ' does not exist'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, 'documentroot ' . $row['documentroot'] . ' does not exist'); } } /** * MailSpace-Usage */ - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'calculating mailspace usage for ' . $row['loginname']); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'calculating mailspace usage for ' . $row['loginname']); $emailusage = 0; - $maildir = \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.vmail_homedir') . $row['loginname']); + $maildir = FileDir::makeCorrectDir(Settings::Get('system.vmail_homedir') . $row['loginname']); if (file_exists($maildir) && is_dir($maildir)) { - $back = \Froxlor\FileDir::safe_exec('du -sk ' . escapeshellarg($maildir) . ''); + $back = FileDir::safe_exec('du -sk ' . escapeshellarg($maildir) . ''); foreach ($back as $backrow) { $emailusage = explode(' ', $backrow); } @@ -409,26 +424,26 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron $emailusage = floatval($emailusage['0']); unset($back); } 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'); } /** * MySQLSpace-Usage */ - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'calculating mysqlspace usage for ' . $row['loginname']); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'calculating mysqlspace usage for ' . $row['loginname']); $mysqlusage = 0; if (isset($mysqlusage_all[$row['customerid']])) { $mysqlusage = floatval($mysqlusage_all[$row['customerid']] / 1024); } - $current_diskspace = array(); + $current_diskspace = []; $current_diskspace['webspace'] = floatval($webspaceusage); $current_diskspace['mail'] = floatval($emailusage); $current_diskspace['mysql'] = floatval($mysqlusage); $current_diskspace['all'] = $current_diskspace['webspace'] + $current_diskspace['mail'] + $current_diskspace['mysql']; - $ins_data = array( + $ins_data = [ 'customerid' => $row['customerid'], 'year' => $current_year, 'month' => $current_month, @@ -437,7 +452,7 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron 'webspace' => $current_diskspace['webspace'], 'mail' => $current_diskspace['mail'], 'mysql' => $current_diskspace['mysql'] - ); + ]; $ins_stmt = Database::prepare(" INSERT INTO `" . TABLE_PANEL_DISKSPACE . "` SET `customerid` = :customerid, @@ -451,8 +466,8 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron "); Database::pexecute($ins_stmt, $ins_data); - if (! isset($admin_diskspace[$row['adminid']]) || ! is_array($admin_diskspace[$row['adminid']])) { - $admin_diskspace[$row['adminid']] = array(); + if (!isset($admin_diskspace[$row['adminid']]) || !is_array($admin_diskspace[$row['adminid']])) { + $admin_diskspace[$row['adminid']] = []; $admin_diskspace[$row['adminid']]['webspace'] = 0; $admin_diskspace[$row['adminid']]['mail'] = 0; $admin_diskspace[$row['adminid']]['mysql'] = 0; @@ -469,11 +484,11 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron */ $diskusage = floatval($webspaceusage + $emailusage + $mysqlusage); - $upd_data = array( + $upd_data = [ 'diskspace' => $current_diskspace['all'], 'traffic' => $sum_month_traffic['all'], 'customerid' => $row['customerid'] - ); + ]; $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `diskspace_used` = :diskspace, @@ -485,11 +500,11 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron /** * Proftpd Quota */ - $upd_data = array( + $upd_data = [ 'biu' => ($current_diskspace['all'] * 1024), 'loginname' => $row['loginname'], 'loginnamelike' => $row['loginname'] . Settings::Get('customer.ftpprefix') . "%" - ); + ]; $upd_stmt = Database::prepare(" UPDATE `" . TABLE_FTP_QUOTATALLIES . "` SET `bytes_in_used` = :biu WHERE `name` = :loginname OR `name` LIKE :loginnamelike @@ -500,13 +515,12 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron * Pureftpd Quota */ if (Settings::Get('system.ftpserver') == "pureftpd") { - $result_quota_stmt = Database::prepare(" SELECT homedir FROM `" . TABLE_FTP_USERS . "` WHERE customerid = :customerid "); - Database::pexecute($result_quota_stmt, array( + Database::pexecute($result_quota_stmt, [ 'customerid' => $row['customerid'] - )); + ]); // get correct user if ((Settings::Get('system.mod_fcgid') == 1 || Settings::Get('phpfpm.enabled') == 1) && $row['deactivated'] == '0') { @@ -517,13 +531,13 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron $group = $row['guid']; } - while ($row_quota = $result_quota_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row_quota = $result_quota_stmt->fetch(PDO::FETCH_ASSOC)) { $quotafile = "" . $row_quota['homedir'] . ".ftpquota"; $fh = fopen($quotafile, 'w'); $stringdata = "0 " . $current_diskspace['all'] * 1024 . ""; fwrite($fh, $stringdata); fclose($fh); - \Froxlor\FileDir::safe_exec('chown ' . $user . ':' . $group . ' ' . escapeshellarg($quotafile) . ''); + FileDir::safe_exec('chown ' . $user . ':' . $group . ' ' . escapeshellarg($quotafile) . ''); } } } @@ -533,11 +547,9 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron */ $result_stmt = Database::query("SELECT `adminid` FROM `" . TABLE_PANEL_ADMINS . "` ORDER BY `adminid` ASC"); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { - + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { if (isset($admin_traffic[$row['adminid']])) { - - $ins_data = array( + $ins_data = [ 'adminid' => $row['adminid'], 'year' => $current_year, 'month' => $current_month, @@ -547,7 +559,7 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron 'ftp_up' => $admin_traffic[$row['adminid']]['ftp_up'], 'ftp_down' => $admin_traffic[$row['adminid']]['ftp_down'], 'mail' => $admin_traffic[$row['adminid']]['mail'] - ); + ]; $ins_stmt = Database::prepare(" INSERT INTO `" . TABLE_PANEL_TRAFFIC_ADMINS . "` SET `adminid` = :adminid, @@ -562,10 +574,10 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron "); Database::pexecute($ins_stmt, $ins_data); - $upd_data = array( + $upd_data = [ 'traffic' => $admin_traffic[$row['adminid']]['sum_month'], 'adminid' => $row['adminid'] - ); + ]; $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_ADMINS . "` SET `traffic_used` = :traffic @@ -575,10 +587,10 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron } if (isset($admin_diskspace[$row['adminid']])) { - $upd_data = array( + $upd_data = [ 'diskspace' => $admin_diskspace[$row['adminid']]['all'], 'adminid' => $row['adminid'] - ); + ]; $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_ADMINS . "` SET `diskspace_used` = :diskspace @@ -590,54 +602,218 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron Database::query("UPDATE `" . TABLE_PANEL_SETTINGS . "` SET `value` = UNIX_TIMESTAMP() WHERE `settinggroup` = 'system' AND `varname` = 'last_traffic_run'"); - if (function_exists('pcntl_fork') && ! defined('CRON_NOFORK_FLAG')) { + if (function_exists('pcntl_fork') && !defined('CRON_NOFORK_FLAG')) { @unlink($TrafficLock); die(); } } + /** + * Function which make webalizer statistics and returns used traffic since last run + * + * @param + * string Name of logfile + * @param + * string Place where stats should be build + * @param + * string Caption for webalizer output + * @return int Used traffic + * @author Florian Lippert (2003-2009) + */ + private static function callWebalizerGetTraffic($logfile, $outputdir, $caption, $usersdomainlist) + { + $returnval = 0; + + $logfile = FileDir::makeCorrectFile(Settings::Get('system.logfiles_directory') . $logfile . '-access.log'); + if (file_exists($logfile)) { + $domainargs = ''; + foreach ($usersdomainlist as $domain) { + // hide referer + $domainargs .= ' -r ' . escapeshellarg($domain); + } + + $outputdir = FileDir::makeCorrectDir($outputdir); + if (!file_exists($outputdir)) { + FileDir::safe_exec('mkdir -p ' . escapeshellarg($outputdir)); + } + + if (file_exists($outputdir . 'webalizer.hist.1')) { + @unlink($outputdir . 'webalizer.hist.1'); + } + + if (file_exists($outputdir . 'webalizer.hist') && !file_exists($outputdir . 'webalizer.hist.1')) { + FileDir::safe_exec('cp ' . escapeshellarg($outputdir . 'webalizer.hist') . ' ' . escapeshellarg($outputdir . 'webalizer.hist.1')); + } + + $verbosity = ''; + if (Settings::Get('system.webalizer_quiet') == '1') { + $verbosity = '-q'; + } elseif (Settings::Get('system.webalizer_quiet') == '2') { + $verbosity = '-Q'; + } + + $we = '/usr/bin/webalizer'; + + // FreeBSD uses other paths, #140 + if (!file_exists($we)) { + $we = '/usr/local/bin/webalizer'; + } + + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Running webalizer for domain '" . $caption . "'"); + FileDir::safe_exec($we . ' ' . $verbosity . ' -p -o ' . escapeshellarg($outputdir) . ' -n ' . escapeshellarg($caption) . $domainargs . ' ' . escapeshellarg($logfile)); + + /** + * Format of webalizer.hist-files: + * Month: $webalizer_hist_row['0'] + * Year: $webalizer_hist_row['1'] + * KB: $webalizer_hist_row['5'] + */ + $httptraffic = []; + $webalizer_hist = @file_get_contents($outputdir . 'webalizer.hist'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Gathering traffic information from '" . $webalizer_hist . "'"); + + $webalizer_hist_rows = explode("\n", $webalizer_hist); + foreach ($webalizer_hist_rows as $webalizer_hist_row) { + if ($webalizer_hist_row != '') { + $webalizer_hist_row = explode(' ', $webalizer_hist_row); + + if (isset($webalizer_hist_row['0']) && isset($webalizer_hist_row['1']) && isset($webalizer_hist_row['5'])) { + $month = intval($webalizer_hist_row['0']); + $year = intval($webalizer_hist_row['1']); + $traffic = floatval($webalizer_hist_row['5']); + + if (!isset($httptraffic[$year])) { + $httptraffic[$year] = []; + } + + $httptraffic[$year][$month] = $traffic; + } + } + } + + reset($httptraffic); + $httptrafficlast = []; + $webalizer_lasthist = @file_get_contents($outputdir . 'webalizer.hist.1'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Gathering traffic information from '" . $webalizer_lasthist . "'"); + + $webalizer_lasthist_rows = explode("\n", $webalizer_lasthist); + foreach ($webalizer_lasthist_rows as $webalizer_lasthist_row) { + if ($webalizer_lasthist_row != '') { + $webalizer_lasthist_row = explode(' ', $webalizer_lasthist_row); + + if (isset($webalizer_lasthist_row['0']) && isset($webalizer_lasthist_row['1']) && isset($webalizer_lasthist_row['5'])) { + $month = intval($webalizer_lasthist_row['0']); + $year = intval($webalizer_lasthist_row['1']); + $traffic = floatval($webalizer_lasthist_row['5']); + + if (!isset($httptrafficlast[$year])) { + $httptrafficlast[$year] = []; + } + + $httptrafficlast[$year][$month] = $traffic; + } + } + } + + reset($httptrafficlast); + foreach ($httptraffic as $year => $months) { + foreach ($months as $month => $traffic) { + if (!isset($httptrafficlast[$year][$month])) { + $returnval += $traffic; + } elseif ($httptrafficlast[$year][$month] < $traffic) { + $returnval += ($traffic - $httptrafficlast[$year][$month]); + } + } + } + } + + return floatval($returnval); + } + + private static function callAwstatsGetTraffic($customerid, $outputdir, $usersdomainlist, $current_stamp) + { + $returnval = 0; + + foreach ($usersdomainlist as $singledomain) { + // as we check for the config-model awstats will only parse + // 'real' domains and no subdomains which are aliases in the + // model-config-file. + $returnval += self::awstatsDoSingleDomain($singledomain, $outputdir); + } + + /** + * as of #124, awstats traffic is saved in bytes instead + * of kilobytes (like webalizer does) + */ + $returnval = floatval($returnval / 1024); + + /** + * now, because this traffic is being saved daily, we have to + * subtract the values from all the month's values to return + * a sane value for our panel_traffic and to remain the whole stats + * (awstats overwrites the customers .html stats-files) + */ + if ($customerid !== false) { + $result_stmt = Database::prepare(" + SELECT SUM(`http`) as `trafficmonth` FROM `" . TABLE_PANEL_TRAFFIC . "` + WHERE `customerid` = :customerid + AND `year` = :year AND `month` = :month + "); + $result_data = [ + 'customerid' => $customerid, + 'year' => date('Y', $current_stamp), + 'month' => date('m', $current_stamp) + ]; + $result = Database::pexecute_first($result_stmt, $result_data); + + if (is_array($result) && isset($result['trafficmonth'])) { + $returnval = ($returnval - floatval($result['trafficmonth'])); + } + } + + return floatval($returnval); + } + private static function awstatsDoSingleDomain($domain, $outputdir) { $returnval = 0; - $domainconfig = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.awstats_conf') . '/awstats.' . $domain . '.conf'); + $domainconfig = FileDir::makeCorrectFile(Settings::Get('system.awstats_conf') . '/awstats.' . $domain . '.conf'); if (file_exists($domainconfig)) { + $outputdir = FileDir::makeCorrectDir($outputdir . '/' . $domain); + $staticOutputdir = FileDir::makeCorrectDir($outputdir . '/' . date('Y') . '-' . date('m')); - $outputdir = \Froxlor\FileDir::makeCorrectDir($outputdir . '/' . $domain); - $staticOutputdir = \Froxlor\FileDir::makeCorrectDir($outputdir . '/' . date('Y') . '-' . date('m')); - - if (! is_dir($staticOutputdir)) { - \Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg($staticOutputdir)); + if (!is_dir($staticOutputdir)) { + FileDir::safe_exec('mkdir -p ' . escapeshellarg($staticOutputdir)); } // check for correct path of awstats_buildstaticpages.pl - $awbsp = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.awstats_path') . '/awstats_buildstaticpages.pl'); - $awprog = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.awstats_awstatspath') . '/awstats.pl'); + $awbsp = FileDir::makeCorrectFile(Settings::Get('system.awstats_path') . '/awstats_buildstaticpages.pl'); + $awprog = FileDir::makeCorrectFile(Settings::Get('system.awstats_awstatspath') . '/awstats.pl'); - if (! file_exists($awbsp)) { + if (!file_exists($awbsp)) { echo "WANRING: Necessary awstats_buildstaticpages.pl script could not be found, no traffic is being calculated and no stats are generated. Please check your AWStats-Path setting"; - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_WARNING, "Necessary awstats_buildstaticpages.pl script could not be found, no traffic is being calculated and no stats are generated. Please check your AWStats-Path setting"); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Necessary awstats_buildstaticpages.pl script could not be found, no traffic is being calculated and no stats are generated. Please check your AWStats-Path setting"); exit(); } - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Running awstats_buildstaticpages.pl for domain '" . $domain . "' (Output: '" . $staticOutputdir . "')"); - \Froxlor\FileDir::safe_exec($awbsp . ' -awstatsprog=' . escapeshellarg($awprog) . ' -update -month=' . date('m') . ' -year=' . date('Y') . ' -config=' . $domain . ' -dir=' . escapeshellarg($staticOutputdir)); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Running awstats_buildstaticpages.pl for domain '" . $domain . "' (Output: '" . $staticOutputdir . "')"); + FileDir::safe_exec($awbsp . ' -awstatsprog=' . escapeshellarg($awprog) . ' -update -month=' . date('m') . ' -year=' . date('Y') . ' -config=' . $domain . ' -dir=' . escapeshellarg($staticOutputdir)); // update our awstats index files self::awstatsGenerateIndex($domain, $outputdir); // the default selection is 'current', // so link the latest dir to it - $new_current = \Froxlor\FileDir::makeCorrectFile($outputdir . '/current'); - \Froxlor\FileDir::safe_exec('ln -fTs ' . escapeshellarg($staticOutputdir) . ' ' . escapeshellarg($new_current)); + $new_current = FileDir::makeCorrectFile($outputdir . '/current'); + FileDir::safe_exec('ln -fTs ' . escapeshellarg($staticOutputdir) . ' ' . escapeshellarg($new_current)); // statistics file looks like: 'awstats[month][year].[domain].txt' - $file = \Froxlor\FileDir::makeCorrectFile($outputdir . '/awstats' . date('mY', time()) . '.' . $domain . '.txt'); - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Gathering traffic information from '" . $file . "'"); + $file = FileDir::makeCorrectFile($outputdir . '/awstats' . date('mY', time()) . '.' . $domain . '.txt'); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Gathering traffic information from '" . $file . "'"); if (file_exists($file)) { - $content = @file_get_contents($file); if ($content !== false) { $content_array = explode("\n", $content); @@ -672,40 +848,39 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron private static function awstatsGenerateIndex($domain, $outputdir) { - // Generation header $header = "\n"; // Looking for {year}-{month} directories - $entries = array(); + $entries = []; foreach (scandir($outputdir) as $a) { - if (is_dir(\Froxlor\FileDir::makeCorrectDir($outputdir . '/' . $a)) && preg_match('/^[0-9]{4}-[0-9]{2}$/', $a)) { + if (is_dir(FileDir::makeCorrectDir($outputdir . '/' . $a)) && preg_match('/^[0-9]{4}-[0-9]{2}$/', $a)) { array_push($entries, ''); } } // These are the variables we will replace - $regex = array( + $regex = [ '/\{SITE_DOMAIN\}/', '/\{SELECT_ENTRIES\}/' - ); + ]; - $replace = array( + $replace = [ $domain, implode($entries) - ); + ]; // File names - $index_file = \Froxlor\Froxlor::getInstallDir() . '/templates/misc/awstats/index.html'; - $index_file = \Froxlor\FileDir::makeCorrectFile($index_file); - $nav_file = \Froxlor\Froxlor::getInstallDir() . '/templates/misc/awstats/nav.html'; - $nav_file = \Froxlor\FileDir::makeCorrectFile($nav_file); + $index_file = Froxlor::getInstallDir() . '/templates/misc/awstats/index.html'; + $index_file = FileDir::makeCorrectFile($index_file); + $nav_file = Froxlor::getInstallDir() . '/templates/misc/awstats/nav.html'; + $nav_file = FileDir::makeCorrectFile($nav_file); // Write the index file // 'index.html' used to be a symlink (ignore errors in case this is the first run and no index.html exists yet) - @unlink(\Froxlor\FileDir::makeCorrectFile($outputdir . '/' . 'index.html')); + @unlink(FileDir::makeCorrectFile($outputdir . '/' . 'index.html')); - $awstats_index_file = fopen(\Froxlor\FileDir::makeCorrectFile($outputdir . '/' . 'index.html'), 'w'); + $awstats_index_file = fopen(FileDir::makeCorrectFile($outputdir . '/' . 'index.html'), 'w'); $awstats_index_tpl = fopen($index_file, 'r'); // Write the header @@ -713,7 +888,7 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron // Write the configuration file while (($line = fgets($awstats_index_tpl, 4096)) !== false) { - if (! preg_match('/^#/', $line) && trim($line) != '') { + if (!preg_match('/^#/', $line) && trim($line) != '') { fwrite($awstats_index_file, preg_replace($regex, $replace, $line)); } } @@ -721,7 +896,7 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron fclose($awstats_index_tpl); // Write the nav file - $awstats_nav_file = fopen(\Froxlor\FileDir::makeCorrectFile($outputdir . '/' . 'nav.html'), 'w'); + $awstats_nav_file = fopen(FileDir::makeCorrectFile($outputdir . '/' . 'nav.html'), 'w'); $awstats_nav_tpl = fopen($nav_file, 'r'); // Write the header @@ -729,7 +904,7 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron // Write the configuration file while (($line = fgets($awstats_nav_tpl, 4096)) !== false) { - if (! preg_match('/^#/', $line) && trim($line) != '') { + if (!preg_match('/^#/', $line) && trim($line) != '') { fwrite($awstats_nav_file, preg_replace($regex, $replace, $line)); } } @@ -738,173 +913,4 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron return; } - - private static function callAwstatsGetTraffic($customerid, $outputdir, $usersdomainlist, $current_stamp) - { - $returnval = 0; - - foreach ($usersdomainlist as $singledomain) { - // as we check for the config-model awstats will only parse - // 'real' domains and no subdomains which are aliases in the - // model-config-file. - $returnval += self::awstatsDoSingleDomain($singledomain, $outputdir); - } - - /** - * as of #124, awstats traffic is saved in bytes instead - * of kilobytes (like webalizer does) - */ - $returnval = floatval($returnval / 1024); - - /** - * now, because this traffic is being saved daily, we have to - * subtract the values from all the month's values to return - * a sane value for our panel_traffic and to remain the whole stats - * (awstats overwrites the customers .html stats-files) - */ - if ($customerid !== false) { - - $result_stmt = Database::prepare(" - SELECT SUM(`http`) as `trafficmonth` FROM `" . TABLE_PANEL_TRAFFIC . "` - WHERE `customerid` = :customerid - AND `year` = :year AND `month` = :month - "); - $result_data = array( - 'customerid' => $customerid, - 'year' => date('Y', $current_stamp), - 'month' => date('m', $current_stamp) - ); - $result = Database::pexecute_first($result_stmt, $result_data); - - if (is_array($result) && isset($result['trafficmonth'])) { - $returnval = ($returnval - floatval($result['trafficmonth'])); - } - } - - return floatval($returnval); - } - - /** - * Function which make webalizer statistics and returns used traffic since last run - * - * @param - * string Name of logfile - * @param - * string Place where stats should be build - * @param - * string Caption for webalizer output - * @return int Used traffic - * @author Florian Lippert - */ - private static function callWebalizerGetTraffic($logfile, $outputdir, $caption, $usersdomainlist) - { - $returnval = 0; - - $logfile = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.logfiles_directory') . $logfile . '-access.log'); - if (file_exists($logfile)) { - $domainargs = ''; - foreach ($usersdomainlist as $domain) { - // hide referer - $domainargs .= ' -r ' . escapeshellarg($domain); - } - - $outputdir = \Froxlor\FileDir::makeCorrectDir($outputdir); - if (! file_exists($outputdir)) { - \Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg($outputdir)); - } - - if (file_exists($outputdir . 'webalizer.hist.1')) { - @unlink($outputdir . 'webalizer.hist.1'); - } - - if (file_exists($outputdir . 'webalizer.hist') && ! file_exists($outputdir . 'webalizer.hist.1')) { - \Froxlor\FileDir::safe_exec('cp ' . escapeshellarg($outputdir . 'webalizer.hist') . ' ' . escapeshellarg($outputdir . 'webalizer.hist.1')); - } - - $verbosity = ''; - if (Settings::Get('system.webalizer_quiet') == '1') { - $verbosity = '-q'; - } elseif (Settings::Get('system.webalizer_quiet') == '2') { - $verbosity = '-Q'; - } - - $we = '/usr/bin/webalizer'; - - // FreeBSD uses other paths, #140 - if (! file_exists($we)) { - $we = '/usr/local/bin/webalizer'; - } - - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Running webalizer for domain '" . $caption . "'"); - \Froxlor\FileDir::safe_exec($we . ' ' . $verbosity . ' -p -o ' . escapeshellarg($outputdir) . ' -n ' . escapeshellarg($caption) . $domainargs . ' ' . escapeshellarg($logfile)); - - /** - * Format of webalizer.hist-files: - * Month: $webalizer_hist_row['0'] - * Year: $webalizer_hist_row['1'] - * KB: $webalizer_hist_row['5'] - */ - $httptraffic = array(); - $webalizer_hist = @file_get_contents($outputdir . 'webalizer.hist'); - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Gathering traffic information from '" . $webalizer_hist . "'"); - - $webalizer_hist_rows = explode("\n", $webalizer_hist); - foreach ($webalizer_hist_rows as $webalizer_hist_row) { - if ($webalizer_hist_row != '') { - - $webalizer_hist_row = explode(' ', $webalizer_hist_row); - - if (isset($webalizer_hist_row['0']) && isset($webalizer_hist_row['1']) && isset($webalizer_hist_row['5'])) { - $month = intval($webalizer_hist_row['0']); - $year = intval($webalizer_hist_row['1']); - $traffic = floatval($webalizer_hist_row['5']); - - if (! isset($httptraffic[$year])) { - $httptraffic[$year] = array(); - } - - $httptraffic[$year][$month] = $traffic; - } - } - } - - reset($httptraffic); - $httptrafficlast = array(); - $webalizer_lasthist = @file_get_contents($outputdir . 'webalizer.hist.1'); - \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Gathering traffic information from '" . $webalizer_lasthist . "'"); - - $webalizer_lasthist_rows = explode("\n", $webalizer_lasthist); - foreach ($webalizer_lasthist_rows as $webalizer_lasthist_row) { - if ($webalizer_lasthist_row != '') { - - $webalizer_lasthist_row = explode(' ', $webalizer_lasthist_row); - - if (isset($webalizer_lasthist_row['0']) && isset($webalizer_lasthist_row['1']) && isset($webalizer_lasthist_row['5'])) { - $month = intval($webalizer_lasthist_row['0']); - $year = intval($webalizer_lasthist_row['1']); - $traffic = floatval($webalizer_lasthist_row['5']); - - if (! isset($httptrafficlast[$year])) { - $httptrafficlast[$year] = array(); - } - - $httptrafficlast[$year][$month] = $traffic; - } - } - } - - reset($httptrafficlast); - foreach ($httptraffic as $year => $months) { - foreach ($months as $month => $traffic) { - if (! isset($httptrafficlast[$year][$month])) { - $returnval += $traffic; - } elseif ($httptrafficlast[$year][$month] < $traffic) { - $returnval += ($traffic - $httptrafficlast[$year][$month]); - } - } - } - } - - return floatval($returnval); - } } diff --git a/lib/Froxlor/CurrentUser.php b/lib/Froxlor/CurrentUser.php index 7b980d03..eda5b732 100644 --- a/lib/Froxlor/CurrentUser.php +++ b/lib/Froxlor/CurrentUser.php @@ -1,5 +1,28 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor; use Froxlor\Database\Database; @@ -10,19 +33,9 @@ use Froxlor\Database\Database; class CurrentUser { - /** - * set the userinfo data to the session - * - * @param array $data - */ - public static function setData(array $data = []): void - { - $_SESSION['userinfo'] = $data; - } - /** * returns whether there is an active session - * + * * @return bool */ public static function hasSession(): bool @@ -30,28 +43,6 @@ class CurrentUser return !empty($_SESSION) && isset($_SESSION['userinfo']) && !empty($_SESSION['userinfo']); } - /** - * returns whether user has an adminsession - * - * @return bool - */ - public static function isAdmin(): bool - { - return (self::getField('adminsession') == 1 && self::getField('adminid') > 0 && empty(self::getField('customerid'))); - } - - /** - * return content of a given field from userinfo-array - * - * @param string $index - * - * @return string|array - */ - public static function getField(string $index) - { - return isset($_SESSION['userinfo'][$index]) ? $_SESSION['userinfo'][$index] : ""; - } - /** * set userinfo field in session * @@ -66,16 +57,6 @@ class CurrentUser return true; } - /** - * Return userinfo array - * - * @return array - */ - public static function getData(): array - { - return $_SESSION['userinfo'] ?? []; - } - /** * re-read in the user data if a valid session exists * @@ -103,4 +84,46 @@ class CurrentUser self::setData([]); return false; } + + /** + * returns whether user has an adminsession + * + * @return bool + */ + public static function isAdmin(): bool + { + return (self::getField('adminsession') == 1 && self::getField('adminid') > 0 && empty(self::getField('customerid'))); + } + + /** + * return content of a given field from userinfo-array + * + * @param string $index + * + * @return string|array + */ + public static function getField(string $index) + { + return isset($_SESSION['userinfo'][$index]) ? $_SESSION['userinfo'][$index] : ""; + } + + /** + * Return userinfo array + * + * @return array + */ + public static function getData(): array + { + return $_SESSION['userinfo'] ?? []; + } + + /** + * set the userinfo data to the session + * + * @param array $data + */ + public static function setData(array $data = []): void + { + $_SESSION['userinfo'] = $data; + } } diff --git a/lib/Froxlor/Customer/Customer.php b/lib/Froxlor/Customer/Customer.php index 4f9fa078..7e81a348 100644 --- a/lib/Froxlor/Customer/Customer.php +++ b/lib/Froxlor/Customer/Customer.php @@ -1,7 +1,32 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\Customer; use Froxlor\Database\Database; +use PDO; class Customer { @@ -11,9 +36,9 @@ class Customer $customer_stmt = Database::prepare(" SELECT `" . $varname . "` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `customerid` = :customerid "); - $customer = Database::pexecute_first($customer_stmt, array( + $customer = Database::pexecute_first($customer_stmt, [ 'customerid' => $customerid - )); + ]); if (isset($customer[$varname])) { return $customer[$varname]; @@ -26,7 +51,7 @@ class Customer * returns the loginname of a customer by given uid * * @param int $uid - * uid of customer + * uid of customer * * @return string customers loginname */ @@ -35,9 +60,9 @@ class Customer $result_stmt = Database::prepare(" SELECT `loginname` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `guid` = :guid "); - $result = Database::pexecute_first($result_stmt, array( + $result = Database::pexecute_first($result_stmt, [ 'guid' => $uid - )); + ]); if (is_array($result) && isset($result['loginname'])) { return $result['loginname']; @@ -52,7 +77,7 @@ class Customer * enabled for the given customer * * @param - * int customer-id + * int customer-id * * @return boolean */ @@ -61,10 +86,10 @@ class Customer if ($cid > 0) { $result_stmt = Database::prepare(" SELECT `perlenabled` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `customerid` = :cid"); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'cid' => $cid - )); - $result = $result_stmt->fetch(\PDO::FETCH_ASSOC); + ]); + $result = $result_stmt->fetch(PDO::FETCH_ASSOC); if (is_array($result) && isset($result['perlenabled'])) { return $result['perlenabled'] == '1'; diff --git a/lib/Froxlor/Database/Database.php b/lib/Froxlor/Database/Database.php index 61455bdb..70fe03db 100644 --- a/lib/Froxlor/Database/Database.php +++ b/lib/Froxlor/Database/Database.php @@ -1,38 +1,48 @@ - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes + * 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.31 + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ +namespace Froxlor\Database; + +use Exception; +use Froxlor\FileDir; +use Froxlor\Froxlor; +use Froxlor\Settings; +use Froxlor\UI\Panel\UI; +use PDO; +use PDOException; +use PDOStatement; + /** * Class Database * * Wrapper-class for PHP-PDO * - * @copyright (c) the authors - * @author Michael Kaufmann - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes - * - * @method static \PDOStatement prepare($statement, array $driver_options = null) Prepares a statement for execution and returns a statement object - * @method static \PDOStatement query ($statement) Executes an SQL statement, returning a result set as a PDOStatement object + * @method static PDOStatement prepare($statement, array $driver_options = null) Prepares a statement for execution + * and returns a statement object + * @method static PDOStatement query ($statement) Executes an SQL statement, returning a result set as a PDOStatement + * object * @method static string lastInsertId ($name = null) Returns the ID of the last inserted row or sequence value * @method static string quote ($string, $parameter_type = null) Quotes a string for use in a query. */ @@ -68,42 +78,233 @@ class Database private static $sqldata = null; - /** - * Wrapper for PDOStatement::execute so we can catch the PDOException - * and display the error nicely on the panel - * - * @param \PDOStatement $stmt - * @param array $params - * (optional) - * @param bool $showerror - * suppress errordisplay (default true) - */ - public static function pexecute(&$stmt, $params = null, $showerror = true, $json_response = false) - { - try { - $stmt->execute($params); - } catch (\PDOException $e) { - self::showerror($e, $showerror, $json_response, $stmt); - } - } - /** * Wrapper for PDOStatement::execute so we can catch the PDOException * and display the error nicely on the panel - also fetches the * result from the statement and returns the resulting array * - * @param \PDOStatement $stmt + * @param PDOStatement $stmt * @param array $params - * (optional) + * (optional) * @param bool $showerror - * suppress errordisplay (default true) + * suppress errordisplay (default true) * * @return array */ public static function pexecute_first(&$stmt, $params = null, $showerror = true, $json_response = false) { self::pexecute($stmt, $params, $showerror, $json_response); - return $stmt->fetch(\PDO::FETCH_ASSOC); + return $stmt->fetch(PDO::FETCH_ASSOC); + } + + /** + * Wrapper for PDOStatement::execute so we can catch the PDOException + * and display the error nicely on the panel + * + * @param PDOStatement $stmt + * @param array $params + * (optional) + * @param bool $showerror + * suppress errordisplay (default true) + */ + public static function pexecute(&$stmt, $params = null, $showerror = true, $json_response = false) + { + try { + $stmt->execute($params); + } catch (PDOException $e) { + self::showerror($e, $showerror, $json_response, $stmt); + } + } + + /** + * display a nice error if it occurs and log everything + * + * @param PDOException $error + * @param bool $showerror + * if set to false, the error will be logged but we go on + */ + private static function showerror($error, $showerror = true, $json_response = false, PDOStatement $stmt = null) + { + global $userinfo, $theme, $linker; + + // include userdata.inc.php + require Froxlor::getInstallDir() . "/lib/userdata.inc.php"; + + // le format + if (isset($sql['root_user']) && isset($sql['root_password']) && (!isset($sql_root) || !is_array($sql_root))) { + $sql_root = [ + 0 => [ + 'caption' => 'Default', + 'host' => $sql['host'], + 'socket' => (isset($sql['socket']) ? $sql['socket'] : null), + 'user' => $sql['root_user'], + 'password' => $sql['root_password'] + ] + ]; + } + + $substitutions = [ + $sql['password'] => 'DB_UNPRIV_PWD', + $sql_root[0]['password'] => 'DB_ROOT_PWD' + ]; + + // hide username/password in messages + $error_message = $error->getMessage(); + $error_trace = $error->getTraceAsString(); + // error-message + $error_message = self::substitute($error_message, $substitutions); + // error-trace + $error_trace = self::substitute($error_trace, $substitutions); + + if ($error->getCode() == 2003) { + $error_message = "Unable to connect to database. Either the mysql-server is not running or your user/password is wrong."; + $error_trace = ""; + } + + /** + * log to a file, so we can actually ask people for the error + * (no one seems to find the stuff in the syslog) + */ + $sl_dir = FileDir::makeCorrectDir(Froxlor::getInstallDir() . "/logs/"); + if (!file_exists($sl_dir)) { + @mkdir($sl_dir, 0755); + } + openlog("froxlor", LOG_PID | LOG_PERROR, LOG_LOCAL0); + syslog(LOG_WARNING, str_replace("\n", " ", $error_message)); + syslog(LOG_WARNING, str_replace("\n", " ", "--- DEBUG: " . $error_trace)); + closelog(); + + /** + * log error for reporting + */ + $errid = self::genUniqueToken(); + $err_file = FileDir::makeCorrectFile($sl_dir . "/" . $errid . "_sql-error.log"); + $errlog = @fopen($err_file, 'w'); + @fwrite($errlog, "|CODE " . $error->getCode() . "\n"); + @fwrite($errlog, "|MSG " . $error_message . "\n"); + @fwrite($errlog, "|FILE " . $error->getFile() . "\n"); + @fwrite($errlog, "|LINE " . $error->getLine() . "\n"); + @fwrite($errlog, "|TRACE\n" . $error_trace . "\n"); + @fclose($errlog); + + if (empty($sql['debug'])) { + $error_trace = ''; + } elseif (!is_null($stmt)) { + $error_trace .= "\n\n" . $stmt->queryString; + } + + if ($showerror && $json_response) { + $exception_message = $error_message; + if (isset($sql['debug']) && $sql['debug'] == true) { + $exception_message .= "\n\n" . $error_trace; + } + throw new Exception($exception_message, 500); + } + + if ($showerror) { + // clean up sensitive data + unset($sql); + unset($sql_root); + + if ((isset($theme) && $theme != '') && !isset($_SERVER['SHELL']) || (isset($_SERVER['SHELL']) && $_SERVER['SHELL'] == '')) { + // if we're not on the shell, output a nice error + $err_report_link = ''; + if (is_array($userinfo) && (($userinfo['adminsession'] == '1' && Settings::Get('system.allow_error_report_admin') == '1') || ($userinfo['adminsession'] == '0' && Settings::Get('system.allow_error_report_customer') == '1'))) { + $err_report_link = $linker->getLink([ + 'section' => 'index', + 'page' => 'send_error_report', + 'errorid' => $errid + ]); + } + // show + UI::initTwig(true); + UI::twig()->addGlobal('install_mode', '1'); + UI::view('misc/dberrornice.html.twig', [ + 'page_title' => 'Database error', + 'message' => $error_message, + 'debug' => $error_trace, + 'report' => $err_report_link + ]); + die(); + } + die("We are sorry, but a MySQL - error occurred. The administrator may find more information in the syslog"); + } + } + + /** + * Substitutes patterns in content. + * + * @param string $content + * @param array $substitutions + * @param int $minLength + * @return string + */ + private static function substitute($content, array $substitutions, $minLength = 6) + { + $replacements = []; + + foreach ($substitutions as $search => $replace) { + $replacements = $replacements + self::createShiftedSubstitutions($search, $replace, $minLength); + } + + $content = str_replace(array_keys($replacements), array_values($replacements), $content); + + return $content; + } + + /** + * Creates substitutions, shifted by length, e.g. + * + * _createShiftedSubstitutions('abcdefgh', 'value', 4): + * array( + * 'abcdefgh' => 'value', + * 'abcdefg' => 'value', + * 'abcdef' => 'value', + * 'abcde' => 'value', + * 'abcd' => 'value', + * ) + * + * @param string $search + * @param string $replace + * @param int $minLength + * @return array + */ + private static function createShiftedSubstitutions($search, $replace, $minLength) + { + $substitutions = []; + $length = strlen($search); + + if ($length > $minLength) { + for ($shiftedLength = $length; $shiftedLength >= $minLength; $shiftedLength--) { + $substitutions[substr($search, 0, $shiftedLength)] = $replace; + } + } + + return $substitutions; + } + + /** + * generate safe unique token + * + * @param int $length + * @return string + */ + private static function genUniqueToken(int $length = 16) + { + if (!isset($length) || intval($length) <= 8) { + $length = 16; + } + if (function_exists('random_bytes')) { + return bin2hex(random_bytes($length)); + } + if (function_exists('mcrypt_create_iv')) { + return bin2hex(mcrypt_create_iv($length, MCRYPT_DEV_URANDOM)); + } + if (function_exists('openssl_random_pseudo_bytes')) { + return bin2hex(openssl_random_pseudo_bytes($length)); + } + // if everything else fails, use unsafe fallback + return substr(md5(uniqid(microtime(), 1)), 0, $length); } /** @@ -134,7 +335,7 @@ class Database * * @param bool $needroot * @param int $dbserver - * optional + * optional */ public static function needRoot($needroot = false, $dbserver = 0) { @@ -144,6 +345,17 @@ class Database self::$needroot = $needroot; } + /** + * set the database-server (relevant for root-connection) + * + * @param int $dbserver + */ + private static function setServer($dbserver = 0) + { + self::$dbserver = $dbserver; + self::$link = null; + } + /** * enable the temporary access to sql-access data * note: if you want root-sqldata you need to @@ -155,7 +367,7 @@ class Database public static function needSqlData() { self::$needsqldata = true; - self::$sqldata = array(); + self::$sqldata = []; self::$link = null; // we need a connection here because // if getSqlData() is called RIGHT after @@ -165,6 +377,140 @@ class Database self::getDB(); } + /** + * function that will be called on every static call + * which connects to the database if necessary + * + * @param bool $root + * + * @return object + */ + private static function getDB() + { + if (!extension_loaded('pdo') || in_array("mysql", PDO::getAvailableDrivers()) == false) { + self::showerror(new Exception("The php PDO extension or PDO-MySQL driver is not available")); + } + + // do we got a connection already? + if (self::$link) { + // return it + return self::$link; + } + + // include userdata.inc.php + require Froxlor::getInstallDir() . "/lib/userdata.inc.php"; + + // le format + if (self::$needroot == true && isset($sql['root_user']) && isset($sql['root_password']) && (!isset($sql_root) || !is_array($sql_root))) { + $sql_root = [ + 0 => [ + 'caption' => 'Default', + 'host' => $sql['host'], + 'socket' => (isset($sql['socket']) ? $sql['socket'] : null), + 'user' => $sql['root_user'], + 'password' => $sql['root_password'] + ] + ]; + unset($sql['root_user']); + unset($sql['root_password']); + } + + // either root or unprivileged user + if (self::$needroot) { + $caption = $sql_root[self::$dbserver]['caption']; + $user = $sql_root[self::$dbserver]['user']; + $password = $sql_root[self::$dbserver]['password']; + $host = $sql_root[self::$dbserver]['host']; + $socket = isset($sql_root[self::$dbserver]['socket']) ? $sql_root[self::$dbserver]['socket'] : null; + $port = isset($sql_root[self::$dbserver]['port']) ? $sql_root[self::$dbserver]['port'] : '3306'; + $sslCAFile = $sql_root[self::$dbserver]['ssl']['caFile'] ?? ""; + $sslVerifyServerCertificate = $sql_root[self::$dbserver]['ssl']['verifyServerCertificate'] ?? false; + } else { + $caption = 'localhost'; + $user = $sql["user"]; + $password = $sql["password"]; + $host = $sql["host"]; + $socket = isset($sql['socket']) ? $sql['socket'] : null; + $port = isset($sql['port']) ? $sql['port'] : '3306'; + $sslCAFile = $sql['ssl']['caFile'] ?? ""; + $sslVerifyServerCertificate = $sql['ssl']['verifyServerCertificate'] ?? false; + } + + // save sql-access-data if needed + if (self::$needsqldata) { + self::$sqldata = [ + 'user' => $user, + 'passwd' => $password, + 'host' => $host, + 'port' => $port, + 'socket' => $socket, + 'db' => $sql["db"], + 'caption' => $caption, + 'ssl_ca_file' => $sslCAFile, + 'ssl_verify_server_certificate' => $sslVerifyServerCertificate + ]; + } + + // build up connection string + $driver = 'mysql'; + $dsn = $driver . ":"; + $options = [ + 'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8' + ]; + $attributes = [ + 'ATTR_ERRMODE' => 'ERRMODE_EXCEPTION' + ]; + + $dbconf["dsn"] = [ + 'dbname' => $sql["db"], + 'charset' => 'utf8' + ]; + + if ($socket != null) { + $dbconf["dsn"]['unix_socket'] = FileDir::makeCorrectFile($socket); + } else { + $dbconf["dsn"]['host'] = $host; + $dbconf["dsn"]['port'] = $port; + + if (!empty(self::$sqldata['ssl_ca_file'])) { + $options[PDO::MYSQL_ATTR_SSL_CA] = self::$sqldata['ssl_ca_file']; + $options[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = (bool)self::$sqldata['ssl_verify_server_certificate']; + } + } + + self::$dbname = $sql["db"]; + + // add options to dsn-string + foreach ($dbconf["dsn"] as $k => $v) { + $dsn .= $k . "=" . $v . ";"; + } + + // clean up + unset($dbconf); + + // try to connect + try { + self::$link = new PDO($dsn, $user, $password, $options); + } catch (PDOException $e) { + self::showerror($e); + } + + // set attributes + foreach ($attributes as $k => $v) { + self::$link->setAttribute(constant("PDO::" . $k), constant("PDO::" . $v)); + } + + $version_server = self::$link->getAttribute(PDO::ATTR_SERVER_VERSION); + $sql_mode = 'NO_ENGINE_SUBSTITUTION'; + if (version_compare($version_server, '8.0.11', '<')) { + $sql_mode .= ',NO_AUTO_CREATE_USER'; + } + self::$link->exec('SET sql_mode = "' . $sql_mode . '"'); + + // return PDO instance + return self::$link; + } + /** * returns the sql-access data as array using indices * 'user', 'passwd' and 'host'. @@ -193,7 +539,7 @@ class Database { // MySQL user names can be up to 32 characters long (16 characters before MySQL 5.7.8). $mysql_max = 32; - if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.8', '<')) { + if (version_compare(Database::getAttribute(PDO::ATTR_SERVER_VERSION), '5.7.8', '<')) { $mysql_max = 16; } return $mysql_max; @@ -210,352 +556,16 @@ class Database */ public static function __callStatic($name, $args) { - $callback = array( + $callback = [ self::getDB(), $name - ); + ]; $result = null; try { $result = call_user_func_array($callback, $args); - } catch (\PDOException $e) { + } catch (PDOException $e) { self::showerror($e); } return $result; } - - /** - * set the database-server (relevant for root-connection) - * - * @param int $dbserver - */ - private static function setServer($dbserver = 0) - { - self::$dbserver = $dbserver; - self::$link = null; - } - - /** - * function that will be called on every static call - * which connects to the database if necessary - * - * @param bool $root - * - * @return object - */ - private static function getDB() - { - if (!extension_loaded('pdo') || in_array("mysql", \PDO::getAvailableDrivers()) == false) { - self::showerror(new \Exception("The php PDO extension or PDO-MySQL driver is not available")); - } - - // do we got a connection already? - if (self::$link) { - // return it - return self::$link; - } - - // include userdata.inc.php - require \Froxlor\Froxlor::getInstallDir() . "/lib/userdata.inc.php"; - - // le format - if (self::$needroot == true && isset($sql['root_user']) && isset($sql['root_password']) && (!isset($sql_root) || !is_array($sql_root))) { - $sql_root = array( - 0 => array( - 'caption' => 'Default', - 'host' => $sql['host'], - 'socket' => (isset($sql['socket']) ? $sql['socket'] : null), - 'user' => $sql['root_user'], - 'password' => $sql['root_password'] - ) - ); - unset($sql['root_user']); - unset($sql['root_password']); - } - - // either root or unprivileged user - if (self::$needroot) { - $caption = $sql_root[self::$dbserver]['caption']; - $user = $sql_root[self::$dbserver]['user']; - $password = $sql_root[self::$dbserver]['password']; - $host = $sql_root[self::$dbserver]['host']; - $socket = isset($sql_root[self::$dbserver]['socket']) ? $sql_root[self::$dbserver]['socket'] : null; - $port = isset($sql_root[self::$dbserver]['port']) ? $sql_root[self::$dbserver]['port'] : '3306'; - $sslCAFile = $sql_root[self::$dbserver]['ssl']['caFile'] ?? ""; - $sslVerifyServerCertificate = $sql_root[self::$dbserver]['ssl']['verifyServerCertificate'] ?? false; - } else { - $caption = 'localhost'; - $user = $sql["user"]; - $password = $sql["password"]; - $host = $sql["host"]; - $socket = isset($sql['socket']) ? $sql['socket'] : null; - $port = isset($sql['port']) ? $sql['port'] : '3306'; - $sslCAFile = $sql['ssl']['caFile'] ?? ""; - $sslVerifyServerCertificate = $sql['ssl']['verifyServerCertificate'] ?? false; - } - - // save sql-access-data if needed - if (self::$needsqldata) { - self::$sqldata = array( - 'user' => $user, - 'passwd' => $password, - 'host' => $host, - 'port' => $port, - 'socket' => $socket, - 'db' => $sql["db"], - 'caption' => $caption, - 'ssl_ca_file' => $sslCAFile, - 'ssl_verify_server_certificate' => $sslVerifyServerCertificate - ); - } - - // build up connection string - $driver = 'mysql'; - $dsn = $driver . ":"; - $options = array( - 'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8' - ); - $attributes = array( - 'ATTR_ERRMODE' => 'ERRMODE_EXCEPTION' - ); - - $dbconf["dsn"] = array( - 'dbname' => $sql["db"], - 'charset' => 'utf8' - ); - - if ($socket != null) { - $dbconf["dsn"]['unix_socket'] = \Froxlor\FileDir::makeCorrectFile($socket); - } else { - $dbconf["dsn"]['host'] = $host; - $dbconf["dsn"]['port'] = $port; - - if (!empty(self::$sqldata['ssl_ca_file'])) { - $options[\PDO::MYSQL_ATTR_SSL_CA] = self::$sqldata['ssl_ca_file']; - $options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = (bool) self::$sqldata['ssl_verify_server_certificate']; - } - } - - self::$dbname = $sql["db"]; - - // add options to dsn-string - foreach ($dbconf["dsn"] as $k => $v) { - $dsn .= $k . "=" . $v . ";"; - } - - // clean up - unset($dbconf); - - // try to connect - try { - self::$link = new \PDO($dsn, $user, $password, $options); - } catch (\PDOException $e) { - self::showerror($e); - } - - // set attributes - foreach ($attributes as $k => $v) { - self::$link->setAttribute(constant("PDO::" . $k), constant("PDO::" . $v)); - } - - $version_server = self::$link->getAttribute(\PDO::ATTR_SERVER_VERSION); - $sql_mode = 'NO_ENGINE_SUBSTITUTION'; - if (version_compare($version_server, '8.0.11', '<')) { - $sql_mode .= ',NO_AUTO_CREATE_USER'; - } - self::$link->exec('SET sql_mode = "' . $sql_mode . '"'); - - // return PDO instance - return self::$link; - } - - /** - * display a nice error if it occurs and log everything - * - * @param \PDOException $error - * @param bool $showerror - * if set to false, the error will be logged but we go on - */ - private static function showerror($error, $showerror = true, $json_response = false, \PDOStatement $stmt = null) - { - global $userinfo, $theme, $linker; - - // include userdata.inc.php - require \Froxlor\Froxlor::getInstallDir() . "/lib/userdata.inc.php"; - - // le format - if (isset($sql['root_user']) && isset($sql['root_password']) && (!isset($sql_root) || !is_array($sql_root))) { - $sql_root = array( - 0 => array( - 'caption' => 'Default', - 'host' => $sql['host'], - 'socket' => (isset($sql['socket']) ? $sql['socket'] : null), - 'user' => $sql['root_user'], - 'password' => $sql['root_password'] - ) - ); - } - - $substitutions = array( - $sql['password'] => 'DB_UNPRIV_PWD', - $sql_root[0]['password'] => 'DB_ROOT_PWD' - ); - - // hide username/password in messages - $error_message = $error->getMessage(); - $error_trace = $error->getTraceAsString(); - // error-message - $error_message = self::substitute($error_message, $substitutions); - // error-trace - $error_trace = self::substitute($error_trace, $substitutions); - - if ($error->getCode() == 2003) { - $error_message = "Unable to connect to database. Either the mysql-server is not running or your user/password is wrong."; - $error_trace = ""; - } - - /** - * log to a file, so we can actually ask people for the error - * (no one seems to find the stuff in the syslog) - */ - $sl_dir = \Froxlor\FileDir::makeCorrectDir(\Froxlor\Froxlor::getInstallDir() . "/logs/"); - if (!file_exists($sl_dir)) { - @mkdir($sl_dir, 0755); - } - openlog("froxlor", LOG_PID | LOG_PERROR, LOG_LOCAL0); - syslog(LOG_WARNING, str_replace("\n", " ", $error_message)); - syslog(LOG_WARNING, str_replace("\n", " ", "--- DEBUG: " . $error_trace)); - closelog(); - - /** - * log error for reporting - */ - $errid = self::genUniqueToken(); - $err_file = \Froxlor\FileDir::makeCorrectFile($sl_dir . "/" . $errid . "_sql-error.log"); - $errlog = @fopen($err_file, 'w'); - @fwrite($errlog, "|CODE " . $error->getCode() . "\n"); - @fwrite($errlog, "|MSG " . $error_message . "\n"); - @fwrite($errlog, "|FILE " . $error->getFile() . "\n"); - @fwrite($errlog, "|LINE " . $error->getLine() . "\n"); - @fwrite($errlog, "|TRACE\n" . $error_trace . "\n"); - @fclose($errlog); - - if (empty($sql['debug'])) { - $error_trace = ''; - } elseif (!is_null($stmt)) { - $error_trace .= "\n\n" . $stmt->queryString; - } - - if ($showerror && $json_response) { - $exception_message = $error_message; - if (isset($sql['debug']) && $sql['debug'] == true) { - $exception_message .= "\n\n" . $error_trace; - } - throw new \Exception($exception_message, 500); - } - - if ($showerror) { - // clean up sensitive data - unset($sql); - unset($sql_root); - - if ((isset($theme) && $theme != '') && !isset($_SERVER['SHELL']) || (isset($_SERVER['SHELL']) && $_SERVER['SHELL'] == '')) { - // if we're not on the shell, output a nice error - $err_report_link = ''; - if (is_array($userinfo) && (($userinfo['adminsession'] == '1' && \Froxlor\Settings::Get('system.allow_error_report_admin') == '1') || ($userinfo['adminsession'] == '0' && \Froxlor\Settings::Get('system.allow_error_report_customer') == '1'))) { - $err_report_link = $linker->getLink(array( - 'section' => 'index', - 'page' => 'send_error_report', - 'errorid' => $errid - )); - } - // show - \Froxlor\UI\Panel\UI::initTwig(true); - \Froxlor\UI\Panel\UI::twig()->addGlobal('install_mode', '1'); - \Froxlor\UI\Panel\UI::view('misc/dberrornice.html.twig', [ - 'page_title' => 'Database error', - 'message' => $error_message, - 'debug' => $error_trace, - 'report' => $err_report_link - ]); - die(); - } - die("We are sorry, but a MySQL - error occurred. The administrator may find more information in the syslog"); - } - } - - /** - * generate safe unique token - * - * @param int $length - * @return string - */ - private static function genUniqueToken(int $length = 16) - { - if (!isset($length) || intval($length) <= 8) { - $length = 16; - } - if (function_exists('random_bytes')) { - return bin2hex(random_bytes($length)); - } - if (function_exists('mcrypt_create_iv')) { - return bin2hex(mcrypt_create_iv($length, MCRYPT_DEV_URANDOM)); - } - if (function_exists('openssl_random_pseudo_bytes')) { - return bin2hex(openssl_random_pseudo_bytes($length)); - } - // if everything else fails, use unsafe fallback - return substr(md5(uniqid(microtime(), 1)), 0, $length); - } - - /** - * Substitutes patterns in content. - * - * @param string $content - * @param array $substitutions - * @param int $minLength - * @return string - */ - private static function substitute($content, array $substitutions, $minLength = 6) - { - $replacements = array(); - - foreach ($substitutions as $search => $replace) { - $replacements = $replacements + self::createShiftedSubstitutions($search, $replace, $minLength); - } - - $content = str_replace(array_keys($replacements), array_values($replacements), $content); - - return $content; - } - - /** - * Creates substitutions, shifted by length, e.g. - * - * _createShiftedSubstitutions('abcdefgh', 'value', 4): - * array( - * 'abcdefgh' => 'value', - * 'abcdefg' => 'value', - * 'abcdef' => 'value', - * 'abcde' => 'value', - * 'abcd' => 'value', - * ) - * - * @param string $search - * @param string $replace - * @param int $minLength - * @return array - */ - private static function createShiftedSubstitutions($search, $replace, $minLength) - { - $substitutions = array(); - $length = strlen($search); - - if ($length > $minLength) { - for ($shiftedLength = $length; $shiftedLength >= $minLength; $shiftedLength--) { - $substitutions[substr($search, 0, $shiftedLength)] = $replace; - } - } - - return $substitutions; - } } diff --git a/lib/Froxlor/Database/DbManager.php b/lib/Froxlor/Database/DbManager.php index dc0f3d1b..a80d3da1 100644 --- a/lib/Froxlor/Database/DbManager.php +++ b/lib/Froxlor/Database/DbManager.php @@ -1,37 +1,41 @@ - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes + * 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.31 + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ +namespace Froxlor\Database; + +use Froxlor\Database\Manager\DbManagerMySQL; +use Froxlor\Froxlor; +use Froxlor\FroxlorLogger; +use Froxlor\Settings; +use PDO; + /** * Class DbManager * * Wrapper-class for database-management like creating * and removing databases, users and permissions - * - * @copyright (c) the authors - * @author Michael Kaufmann - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes */ class DbManager { @@ -53,7 +57,7 @@ class DbManager /** * main constructor * - * @param \Froxlor\FroxlorLogger $log + * @param FroxlorLogger $log */ public function __construct($log = null) { @@ -61,6 +65,75 @@ class DbManager $this->setManager(); } + /** + * set manager-object by type of + * dbms: mysql only for now + * + * sets private $_manager variable + */ + private function setManager() + { + // TODO read different dbms from settings later + $this->manager = new DbManagerMySQL($this->log); + } + + public static function correctMysqlUsers($mysql_access_host_array) + { + // get sql-root access data + Database::needRoot(true); + Database::needSqlData(); + $sql_root = Database::getSqlData(); + Database::needRoot(false); + + $dbservers_stmt = Database::query("SELECT DISTINCT `dbserver` FROM `" . TABLE_PANEL_DATABASES . "`"); + while ($dbserver = $dbservers_stmt->fetch(PDO::FETCH_ASSOC)) { + Database::needRoot(true, $dbserver['dbserver']); + Database::needSqlData(); + $sql_root = Database::getSqlData(); + + $dbm = new DbManager(FroxlorLogger::getInstanceOf()); + $users = $dbm->getManager()->getAllSqlUsers(false); + + $databases = [ + $sql_root['db'] + ]; + $databases_result_stmt = Database::prepare(" + SELECT * FROM `" . TABLE_PANEL_DATABASES . "` + WHERE `dbserver` = :mysqlserver + "); + Database::pexecute($databases_result_stmt, [ + 'mysqlserver' => $dbserver['dbserver'] + ]); + + while ($databases_row = $databases_result_stmt->fetch(PDO::FETCH_ASSOC)) { + $databases[] = $databases_row['databasename']; + } + + foreach ($databases as $username) { + if (isset($users[$username]) && is_array($users[$username]) && isset($users[$username]['hosts']) && is_array($users[$username]['hosts'])) { + $password = $users[$username]['password']; + + foreach ($mysql_access_host_array as $mysql_access_host) { + $mysql_access_host = trim($mysql_access_host); + + if (!in_array($mysql_access_host, $users[$username]['hosts'])) { + $dbm->getManager()->grantPrivilegesTo($username, $password, $mysql_access_host, true); + } + } + + foreach ($users[$username]['hosts'] as $mysql_access_host) { + if (!in_array($mysql_access_host, $mysql_access_host_array)) { + $dbm->getManager()->deleteUser($username, $mysql_access_host); + } + } + } + } + + $dbm->getManager()->flushPrivileges(); + Database::needRoot(false); + } + } + /** * creates a new database and a user with the * same name with all privileges granted on the db. @@ -82,10 +155,10 @@ class DbManager // get all usernames from db-manager $allsqlusers = $this->getManager()->getAllSqlUsers(); // generate random username - $username = $loginname . '-' . substr(\Froxlor\Froxlor::genSessionId(), 20, 3); + $username = $loginname . '-' . substr(Froxlor::genSessionId(), 20, 3); // check whether it exists on the DBMS while (in_array($username, $allsqlusers)) { - $username = $loginname . '-' . substr(\Froxlor\Froxlor::genSessionId(), 20, 3); + $username = $loginname . '-' . substr(Froxlor::genSessionId(), 20, 3); } } elseif (strtoupper(Settings::Get('customer.mysqlprefix')) == 'DBNAME') { $username = $loginname; @@ -100,12 +173,12 @@ class DbManager // now create the database itself $this->getManager()->createDatabase($username); - $this->log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "created database '" . $username . "'"); + $this->log->logAction(FroxlorLogger::USR_ACTION, LOG_INFO, "created database '" . $username . "'"); // and give permission to the user on every access-host we have foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) { $this->getManager()->grantPrivilegesTo($username, $password, $mysql_access_host); - $this->log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "grant all privileges for '" . $username . "'@'" . $mysql_access_host . "'"); + $this->log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "grant all privileges for '" . $username . "'@'" . $mysql_access_host . "'"); } $this->getManager()->flushPrivileges(); @@ -123,78 +196,4 @@ class DbManager { return $this->manager; } - - /** - * set manager-object by type of - * dbms: mysql only for now - * - * sets private $_manager variable - */ - private function setManager() - { - // TODO read different dbms from settings later - $this->manager = new \Froxlor\Database\Manager\DbManagerMySQL($this->log); - } - - public static function correctMysqlUsers($mysql_access_host_array) - { - // get sql-root access data - Database::needRoot(true); - Database::needSqlData(); - $sql_root = Database::getSqlData(); - Database::needRoot(false); - - $dbservers_stmt = Database::query("SELECT DISTINCT `dbserver` FROM `" . TABLE_PANEL_DATABASES . "`"); - while ($dbserver = $dbservers_stmt->fetch(\PDO::FETCH_ASSOC)) { - - Database::needRoot(true, $dbserver['dbserver']); - Database::needSqlData(); - $sql_root = Database::getSqlData(); - - $dbm = new DbManager(\Froxlor\FroxlorLogger::getInstanceOf()); - $users = $dbm->getManager()->getAllSqlUsers(false); - - $databases = array( - $sql_root['db'] - ); - $databases_result_stmt = Database::prepare(" - SELECT * FROM `" . TABLE_PANEL_DATABASES . "` - WHERE `dbserver` = :mysqlserver - "); - Database::pexecute($databases_result_stmt, array( - 'mysqlserver' => $dbserver['dbserver'] - )); - - while ($databases_row = $databases_result_stmt->fetch(\PDO::FETCH_ASSOC)) { - $databases[] = $databases_row['databasename']; - } - - foreach ($databases as $username) { - - if (isset($users[$username]) && is_array($users[$username]) && isset($users[$username]['hosts']) && is_array($users[$username]['hosts'])) { - - $password = $users[$username]['password']; - - foreach ($mysql_access_host_array as $mysql_access_host) { - - $mysql_access_host = trim($mysql_access_host); - - if (! in_array($mysql_access_host, $users[$username]['hosts'])) { - $dbm->getManager()->grantPrivilegesTo($username, $password, $mysql_access_host, true); - } - } - - foreach ($users[$username]['hosts'] as $mysql_access_host) { - - if (! in_array($mysql_access_host, $mysql_access_host_array)) { - $dbm->getManager()->deleteUser($username, $mysql_access_host); - } - } - } - } - - $dbm->getManager()->flushPrivileges(); - Database::needRoot(false); - } - } } diff --git a/lib/Froxlor/Database/IntegrityCheck.php b/lib/Froxlor/Database/IntegrityCheck.php index 7d5334fd..7972f8f7 100644 --- a/lib/Froxlor/Database/IntegrityCheck.php +++ b/lib/Froxlor/Database/IntegrityCheck.php @@ -1,30 +1,39 @@ - * @author Froxlor team (2014-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Integrity - * - * IntegrityCheck - class + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\Database; + +use Froxlor\FroxlorLogger; +use Froxlor\Settings; +use PDO; + class IntegrityCheck { // Store all available checks - public $available = array(); + public $available = []; // logger object private $log = null; @@ -36,12 +45,12 @@ class IntegrityCheck public function __construct() { global $userinfo; - if (! isset($userinfo) || ! is_array($userinfo)) { - $userinfo = array( + if (!isset($userinfo) || !is_array($userinfo)) { + $userinfo = [ 'loginname' => 'integrity-check' - ); + ]; } - $this->log = \Froxlor\FroxlorLogger::getInstanceOf($userinfo); + $this->log = FroxlorLogger::getInstanceOf($userinfo); $this->available = get_class_methods($this); unset($this->available[array_search('__construct', $this->available)]); unset($this->available[array_search('checkAll', $this->available)]); @@ -77,31 +86,30 @@ class IntegrityCheck * check whether the froxlor database and its tables are in utf-8 character-set * * @param bool $fix - * fix db charset/collation if not utf8 - * + * fix db charset/collation if not utf8 + * * @return boolean */ public function databaseCharset($fix = false) { - // get characterset $cs_stmt = Database::prepare('SELECT default_character_set_name FROM information_schema.SCHEMATA WHERE schema_name = :dbname'); - $resp = Database::pexecute_first($cs_stmt, array( + $resp = Database::pexecute_first($cs_stmt, [ 'dbname' => Database::getDbName() - )); + ]); $charset = isset($resp['default_character_set_name']) ? $resp['default_character_set_name'] : null; - if (! empty($charset) && substr(strtolower($charset), 0, 4) != 'utf8') { - $this->log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "database charset seems to be different from UTF-8, integrity-check can fix that"); + if (!empty($charset) && substr(strtolower($charset), 0, 4) != 'utf8') { + $this->log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "database charset seems to be different from UTF-8, integrity-check can fix that"); if ($fix) { // fix database Database::query('ALTER DATABASE `' . Database::getDbName() . '` CHARACTER SET utf8 COLLATE utf8_general_ci'); // fix all tables $handle = Database::query('SHOW FULL TABLES WHERE Table_type != "VIEW"'); - while ($row = $handle->fetch(\PDO::FETCH_BOTH)) { + while ($row = $handle->fetch(PDO::FETCH_BOTH)) { $table = $row[0]; Database::query('ALTER TABLE `' . $table . '` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;'); } - $this->log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "database charset was different from UTF-8, integrity-check fixed that"); + $this->log->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "database charset was different from UTF-8, integrity-check fixed that"); } else { return false; } @@ -117,14 +125,14 @@ class IntegrityCheck * Check the integrity of the domain to ip/port - association * * @param bool $fix - * Fix everything found directly + * Fix everything found directly */ public function domainIpTable($fix = false) { - $ips = array(); - $domains = array(); - $ipstodomains = array(); - $admips = array(); + $ips = []; + $domains = []; + $ipstodomains = []; + $admips = []; if ($fix) { // Prepare insert / delete statement for the fixes @@ -140,14 +148,14 @@ class IntegrityCheck Database::pexecute($adm_stmt); $default_ips = explode(',', Settings::Get('system.defaultip')); $default_ssl_ips = explode(',', Settings::Get('system.defaultsslip')); - while ($row = $adm_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $adm_stmt->fetch(PDO::FETCH_ASSOC)) { if ($row['ip'] < 0 || is_null($row['ip']) || empty($row['ip'])) { // Admin uses default-IP $admips[$row['adminid']] = array_merge($default_ips, $default_ssl_ips); } else { - $admips[$row['adminid']] = array( + $admips[$row['adminid']] = [ $row['ip'] - ); + ]; } } } @@ -155,42 +163,42 @@ class IntegrityCheck // Cache all available ip/port - combinations $result_stmt = Database::prepare("SELECT `id`, `ip`, `port` FROM `" . TABLE_PANEL_IPSANDPORTS . "` ORDER BY `id` ASC"); Database::pexecute($result_stmt); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $ips[$row['id']] = $row['ip'] . ':' . $row['port']; } // Cache all configured domains $result_stmt = Database::prepare("SELECT `id`, `adminid` FROM `" . TABLE_PANEL_DOMAINS . "` ORDER BY `id` ASC"); Database::pexecute($result_stmt); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $domains[$row['id']] = $row['adminid']; } // Check if every domain to ip/port - association is valid in TABLE_DOMAINTOIP $result_stmt = Database::prepare("SELECT `id_domain`, `id_ipandports` FROM `" . TABLE_DOMAINTOIP . "`"); Database::pexecute($result_stmt); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { - if (! array_key_exists($row['id_ipandports'], $ips)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + if (!array_key_exists($row['id_ipandports'], $ips)) { if ($fix) { - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'domainid' => $row['id_domain'], 'ipandportid' => $row['id_ipandports'] - )); - $this->log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "found an ip/port-id in domain <> ip table which does not exist, integrity check fixed this"); + ]); + $this->log->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "found an ip/port-id in domain <> ip table which does not exist, integrity check fixed this"); } else { - $this->log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "found an ip/port-id in domain <> ip table which does not exist, integrity check can fix this"); + $this->log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "found an ip/port-id in domain <> ip table which does not exist, integrity check can fix this"); return false; } } - if (! array_key_exists($row['id_domain'], $domains)) { + if (!array_key_exists($row['id_domain'], $domains)) { if ($fix) { - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'domainid' => $row['id_domain'], 'ipandportid' => $row['id_ipandports'] - )); - $this->log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "found a domain-id in domain <> ip table which does not exist, integrity check fixed this"); + ]); + $this->log->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "found a domain-id in domain <> ip table which does not exist, integrity check fixed this"); } else { - $this->log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "found a domain-id in domain <> ip table which does not exist, integrity check can fix this"); + $this->log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "found a domain-id in domain <> ip table which does not exist, integrity check can fix this"); return false; } } @@ -200,17 +208,17 @@ class IntegrityCheck // Check that all domains have at least one IP/Port combination foreach ($domains as $domainid => $adminid) { - if (! array_key_exists($domainid, $ipstodomains)) { + if (!array_key_exists($domainid, $ipstodomains)) { if ($fix) { foreach ($admips[$adminid] as $defaultip) { - Database::pexecute($ins_stmt, array( + Database::pexecute($ins_stmt, [ 'domainid' => $domainid, 'ipandportid' => $defaultip - )); + ]); } - $this->log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "found a domain-id with no entry in domain <> ip table, integrity check fixed this"); + $this->log->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "found a domain-id with no entry in domain <> ip table, integrity check fixed this"); } else { - $this->log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "found a domain-id with no entry in domain <> ip table, integrity check can fix this"); + $this->log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "found a domain-id with no entry in domain <> ip table, integrity check can fix this"); return false; } } @@ -227,13 +235,13 @@ class IntegrityCheck * Check if all subdomains have ssl-redirect = 0 if domain has no ssl-port * * @param bool $fix - * Fix everything found directly + * Fix everything found directly */ public function subdomainSslRedirect($fix = false) { - $ips = array(); - $parentdomains = array(); - $subdomains = array(); + $ips = []; + $parentdomains = []; + $subdomains = []; if ($fix) { // Prepare update statement for the fixes @@ -245,7 +253,7 @@ class IntegrityCheck // Cache all ssl ip/port - combinations $result_stmt = Database::prepare("SELECT `id`, `ip`, `port` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `ssl` = 1 ORDER BY `id` ASC"); Database::pexecute($result_stmt); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $ips[$row['id']] = $row['ip'] . ':' . $row['port']; } @@ -253,14 +261,14 @@ class IntegrityCheck $result_stmt = Database::prepare("SELECT `id`, `parentdomainid`, `ssl_redirect` FROM `" . TABLE_PANEL_DOMAINS . "` ORDER BY `id` ASC"); $ip_stmt = Database::prepare("SELECT `id_domain`, `id_ipandports` FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :domainid"); Database::pexecute($result_stmt); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { if ($row['parentdomainid'] == 0) { // All parentdomains by default have no ssl - ip/port $parentdomains[$row['id']] = false; - Database::pexecute($ip_stmt, array( + Database::pexecute($ip_stmt, [ 'domainid' => $row['id'] - )); - while ($iprow = $ip_stmt->fetch(\PDO::FETCH_ASSOC)) { + ]); + while ($iprow = $ip_stmt->fetch(PDO::FETCH_ASSOC)) { // If the parentdomain has an ip/port assigned which we know is SSL enabled, set the parentdomain to "true" if (array_key_exists($iprow['id_ipandports'], $ips)) { $parentdomains[$row['id']] = true; @@ -268,8 +276,8 @@ class IntegrityCheck } } elseif ($row['ssl_redirect'] == 1) { // All subdomains with enabled ssl_redirect enabled are stored - if (! isset($subdomains[$row['parentdomainid']])) { - $subdomains[$row['parentdomainid']] = array(); + if (!isset($subdomains[$row['parentdomainid']])) { + $subdomains[$row['parentdomainid']] = []; } $subdomains[$row['parentdomainid']][] = $row['id']; } @@ -278,7 +286,7 @@ class IntegrityCheck // Check if every parentdomain with enabled ssl_redirect as SSL enabled foreach ($parentdomains as $id => $sslavailable) { // This parentdomain has no subdomains - if (! isset($subdomains[$id])) { + if (!isset($subdomains[$id])) { continue; } // This parentdomain has SSL enabled, doesn't matter what status the subdomains have @@ -289,13 +297,13 @@ class IntegrityCheck // At this point only parentdomains reside which have ssl_redirect enabled subdomains if ($fix) { // We make a blanket update to all subdomains of this parentdomain, doesn't matter which one is wrong, all have to be disabled - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'domainid' => $id - )); - $this->log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "found a subdomain with ssl_redirect=1 but parent-domain has ssl=0, integrity check fixed this"); + ]); + $this->log->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "found a subdomain with ssl_redirect=1 but parent-domain has ssl=0, integrity check fixed this"); } else { // It's just the check, let the function fail - $this->log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "found a subdomain with ssl_redirect=1 but parent-domain has ssl=0, integrity check can fix this"); + $this->log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "found a subdomain with ssl_redirect=1 but parent-domain has ssl=0, integrity check can fix this"); return false; } } @@ -311,13 +319,13 @@ class IntegrityCheck * Check if all subdomain have letsencrypt = 0 if domain has no ssl-port * * @param bool $fix - * Fix everything found directly + * Fix everything found directly */ public function subdomainLetsencrypt($fix = false) { - $ips = array(); - $parentdomains = array(); - $subdomains = array(); + $ips = []; + $parentdomains = []; + $subdomains = []; if ($fix) { // Prepare update statement for the fixes @@ -329,7 +337,7 @@ class IntegrityCheck // Cache all ssl ip/port - combinations $result_stmt = Database::prepare("SELECT `id`, `ip`, `port` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `ssl` = 1 ORDER BY `id` ASC"); Database::pexecute($result_stmt); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $ips[$row['id']] = $row['ip'] . ':' . $row['port']; } @@ -337,14 +345,14 @@ class IntegrityCheck $result_stmt = Database::prepare("SELECT `id`, `parentdomainid`, `letsencrypt` FROM `" . TABLE_PANEL_DOMAINS . "` ORDER BY `id` ASC"); $ip_stmt = Database::prepare("SELECT `id_domain`, `id_ipandports` FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :domainid"); Database::pexecute($result_stmt); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { if ($row['parentdomainid'] == 0) { // All parentdomains by default have no ssl - ip/port $parentdomains[$row['id']] = false; - Database::pexecute($ip_stmt, array( + Database::pexecute($ip_stmt, [ 'domainid' => $row['id'] - )); - while ($iprow = $ip_stmt->fetch(\PDO::FETCH_ASSOC)) { + ]); + while ($iprow = $ip_stmt->fetch(PDO::FETCH_ASSOC)) { // If the parentdomain has an ip/port assigned which we know is SSL enabled, set the parentdomain to "true" if (array_key_exists($iprow['id_ipandports'], $ips)) { $parentdomains[$row['id']] = true; @@ -352,8 +360,8 @@ class IntegrityCheck } } elseif ($row['letsencrypt'] == 1) { // All subdomains with enabled letsencrypt enabled are stored - if (! isset($subdomains[$row['parentdomainid']])) { - $subdomains[$row['parentdomainid']] = array(); + if (!isset($subdomains[$row['parentdomainid']])) { + $subdomains[$row['parentdomainid']] = []; } $subdomains[$row['parentdomainid']][] = $row['id']; } @@ -362,7 +370,7 @@ class IntegrityCheck // Check if every parentdomain with enabled letsencrypt as SSL enabled foreach ($parentdomains as $id => $sslavailable) { // This parentdomain has no subdomains - if (! isset($subdomains[$id])) { + if (!isset($subdomains[$id])) { continue; } // This parentdomain has SSL enabled, doesn't matter what status the subdomains have @@ -373,13 +381,13 @@ class IntegrityCheck // At this point only parentdomains reside which have letsencrypt enabled subdomains if ($fix) { // We make a blanket update to all subdomains of this parentdomain, doesn't matter which one is wrong, all have to be disabled - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'domainid' => $id - )); - $this->log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "found a subdomain with letsencrypt=1 but parent-domain has ssl=0, integrity check fixed this"); + ]); + $this->log->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "found a subdomain with letsencrypt=1 but parent-domain has ssl=0, integrity check fixed this"); } else { // It's just the check, let the function fail - $this->log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "found a subdomain with letsencrypt=1 but parent-domain has ssl=0, integrity check can fix this"); + $this->log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "found a subdomain with letsencrypt=1 but parent-domain has ssl=0, integrity check can fix this"); return false; } } @@ -396,8 +404,8 @@ class IntegrityCheck * the customers groups when fcgid / php-fpm is used * * @param bool $fix - * fix member/groups - * + * fix member/groups + * * @return boolean */ public function webserverGroupMemberForFcgidPhpFpm($fix = false) @@ -410,27 +418,27 @@ class IntegrityCheck $cwg_stmt = Database::prepare(" SELECT `id` FROM `" . TABLE_FTP_GROUPS . "` WHERE NOT FIND_IN_SET(:webserveruser, `members`) "); - Database::pexecute($cwg_stmt, array( + Database::pexecute($cwg_stmt, [ 'webserveruser' => Settings::Get('system.httpuser') - )); + ]); if ($cwg_stmt->rowCount() > 0) { - $this->log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "Customers are missing the webserver-user as group-member, integrity-check can fix that"); + $this->log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "Customers are missing the webserver-user as group-member, integrity-check can fix that"); if ($fix) { // prepare update statement $upd_stmt = Database::prepare(" UPDATE `" . TABLE_FTP_GROUPS . "` SET `members` = CONCAT(`members`, :additionaluser) WHERE `id` = :id "); - $upd_data = array( + $upd_data = [ 'additionaluser' => "," . Settings::Get('system.httpuser') - ); + ]; while ($cwg_row = $cwg_stmt->fetch()) { $upd_data['id'] = $cwg_row['id']; Database::pexecute($upd_stmt, $upd_data); } - $this->log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "Customers were missing the webserver-user as group-member, integrity-check fixed that"); + $this->log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "Customers were missing the webserver-user as group-member, integrity-check fixed that"); } else { return false; } @@ -448,8 +456,8 @@ class IntegrityCheck * fcgid/fpm in froxlor vhost is used * * @param bool $fix - * fix member/groups - * + * fix member/groups + * * @return boolean */ public function froxlorLocalGroupMemberForFcgidPhpFpm($fix = false) @@ -478,27 +486,27 @@ class IntegrityCheck $cwg_stmt = Database::prepare(" SELECT `id` FROM `" . TABLE_FTP_GROUPS . "` WHERE NOT FIND_IN_SET(:localuser, `members`) "); - Database::pexecute($cwg_stmt, array( + Database::pexecute($cwg_stmt, [ 'localuser' => $localuser - )); + ]); if ($cwg_stmt->rowCount() > 0) { - $this->log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "Customers are missing the local froxlor-user as group-member, integrity-check can fix that"); + $this->log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "Customers are missing the local froxlor-user as group-member, integrity-check can fix that"); if ($fix) { // prepare update statement $upd_stmt = Database::prepare(" UPDATE `" . TABLE_FTP_GROUPS . "` SET `members` = CONCAT(`members`, :additionaluser) WHERE `id` = :id "); - $upd_data = array( + $upd_data = [ 'additionaluser' => "," . $localuser - ); + ]; while ($cwg_row = $cwg_stmt->fetch()) { $upd_data['id'] = $cwg_row['id']; Database::pexecute($upd_stmt, $upd_data); } - $this->log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "Customers were missing the local froxlor-user as group-member, integrity-check fixed that"); + $this->log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "Customers were missing the local froxlor-user as group-member, integrity-check fixed that"); } else { return false; } diff --git a/lib/Froxlor/Database/Manager/DbManagerMySQL.php b/lib/Froxlor/Database/Manager/DbManagerMySQL.php index bf2f01ca..d7892792 100644 --- a/lib/Froxlor/Database/Manager/DbManagerMySQL.php +++ b/lib/Froxlor/Database/Manager/DbManagerMySQL.php @@ -1,37 +1,39 @@ - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes - * - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ +namespace Froxlor\Database\Manager; + +use Froxlor\Database\Database; +use Froxlor\FroxlorLogger; +use PDO; + /** * Class DbManagerMySQL * * Explicit class for database-management like creating * and removing databases, users and permissions for MySQL - * - * @copyright (c) the authors - * @author Michael Kaufmann - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes */ class DbManagerMySQL { @@ -46,7 +48,7 @@ class DbManagerMySQL /** * main constructor * - * @param \Froxlor\FroxlorLogger $log + * @param FroxlorLogger $log */ public function __construct(&$log = null) { @@ -71,16 +73,16 @@ class DbManagerMySQL * @param string $password * @param string $access_host * @param bool $p_encrypted - * optional, whether the password is encrypted or not, default false + * optional, whether the password is encrypted or not, default false * @param bool $update - * optional, whether to update the password only (not create user) + * optional, whether to update the password only (not create user) */ public function grantPrivilegesTo($username = null, $password = null, $access_host = null, $p_encrypted = false, $update = false) { - if (! $update) { + if (!$update) { // create user if ($p_encrypted) { - if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.0', '<')) { + if (version_compare(Database::getAttribute(PDO::ATTR_SERVER_VERSION), '5.7.0', '<')) { $stmt = Database::prepare(" CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED BY PASSWORD :password "); @@ -94,20 +96,20 @@ class DbManagerMySQL CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED BY :password "); } - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "password" => $password - )); + ]); // grant privileges $stmt = Database::prepare(" GRANT ALL ON `" . $username . "`.* TO :username@:host "); - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "username" => $username, "host" => $access_host - )); + ]); } else { // set password - if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.6', '<')) { + if (version_compare(Database::getAttribute(PDO::ATTR_SERVER_VERSION), '5.7.6', '<')) { if ($p_encrypted) { $stmt = Database::prepare("SET PASSWORD FOR :username@:host = :password"); } else { @@ -120,11 +122,11 @@ class DbManagerMySQL $stmt = Database::prepare("ALTER USER :username@:host IDENTIFIED BY :password"); } } - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "username" => $username, "host" => $access_host, "password" => $password - )); + ]); } } @@ -136,29 +138,29 @@ class DbManagerMySQL */ public function deleteDatabase($dbname = null) { - if (Database::getAttribute(\PDO::ATTR_SERVER_VERSION) < '5.0.2') { + if (Database::getAttribute(PDO::ATTR_SERVER_VERSION) < '5.0.2') { // failsafe if user has been deleted manually (requires MySQL 4.1.2+) $stmt = Database::prepare("REVOKE ALL PRIVILEGES, GRANT OPTION FROM `" . $dbname . "`"); - Database::pexecute($stmt, array(), false); + Database::pexecute($stmt, [], false); } $host_res_stmt = Database::prepare(" SELECT `Host` FROM `mysql`.`user` WHERE `User` = :dbname"); - Database::pexecute($host_res_stmt, array( + Database::pexecute($host_res_stmt, [ 'dbname' => $dbname - )); + ]); // as of MySQL 5.0.2 this also revokes privileges. (requires MySQL 4.1.2+) - if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.0', '<')) { + if (version_compare(Database::getAttribute(PDO::ATTR_SERVER_VERSION), '5.7.0', '<')) { $drop_stmt = Database::prepare("DROP USER :dbname@:host"); } else { $drop_stmt = Database::prepare("DROP USER IF EXISTS :dbname@:host"); } - while ($host = $host_res_stmt->fetch(\PDO::FETCH_ASSOC)) { - Database::pexecute($drop_stmt, array( + while ($host = $host_res_stmt->fetch(PDO::FETCH_ASSOC)) { + Database::pexecute($drop_stmt, [ 'dbname' => $dbname, 'host' => $host['Host'] - ), false); + ], false); } $drop_stmt = Database::prepare("DROP DATABASE IF EXISTS `" . $dbname . "`"); @@ -173,21 +175,21 @@ class DbManagerMySQL */ public function deleteUser($username = null, $host = null) { - if (Database::getAttribute(\PDO::ATTR_SERVER_VERSION) < '5.0.2') { + if (Database::getAttribute(PDO::ATTR_SERVER_VERSION) < '5.0.2') { // Revoke privileges (only required for MySQL 4.1.2 - 5.0.1) $stmt = Database::prepare("REVOKE ALL PRIVILEGES ON * . * FROM `" . $username . "`@`" . $host . "`"); Database::pexecute($stmt); } // as of MySQL 5.0.2 this also revokes privileges. (requires MySQL 4.1.2+) - if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.0', '<')) { + if (version_compare(Database::getAttribute(PDO::ATTR_SERVER_VERSION), '5.7.0', '<')) { $stmt = Database::prepare("DROP USER :username@:host"); } else { $stmt = Database::prepare("DROP USER IF EXISTS :username@:host"); } - Database::pexecute($stmt, array( + Database::pexecute($stmt, [ "username" => $username, "host" => $host - )); + ]); } /** @@ -195,12 +197,12 @@ class DbManagerMySQL * * @param string $username * @param string $host - * (unused in mysql) + * (unused in mysql) */ public function disableUser($username = null, $host = null) { $stmt = Database::prepare('REVOKE ALL PRIVILEGES, GRANT OPTION FROM `' . $username . '`@`' . $host . '`'); - Database::pexecute($stmt, array(), false); + Database::pexecute($stmt, [], false); } /** @@ -232,8 +234,8 @@ class DbManagerMySQL * return an array of all usernames used in that DBMS * * @param bool $user_only - * if false, * will be selected from mysql.user and slightly different array will be generated - * + * if false, * will be selected from mysql.user and slightly different array will be generated + * * @return array */ public function getAllSqlUsers($user_only = true) @@ -244,14 +246,14 @@ class DbManagerMySQL $result_stmt = Database::prepare('SELECT `User` FROM mysql.user'); } Database::pexecute($result_stmt); - $allsqlusers = array(); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + $allsqlusers = []; + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { if ($user_only == false) { - if (! isset($allsqlusers[$row['User']]) || ! is_array($allsqlusers[$row['User']])) { - $allsqlusers[$row['User']] = array( + if (!isset($allsqlusers[$row['User']]) || !is_array($allsqlusers[$row['User']])) { + $allsqlusers[$row['User']] = [ 'password' => $row['Password'] ?? $row['authentication_string'], - 'hosts' => array() - ); + 'hosts' => [] + ]; } $allsqlusers[$row['User']]['hosts'][] = $row['Host']; } else { diff --git a/lib/Froxlor/Dns/Dns.php b/lib/Froxlor/Dns/Dns.php index c870e3cc..553eda3c 100644 --- a/lib/Froxlor/Dns/Dns.php +++ b/lib/Froxlor/Dns/Dns.php @@ -1,17 +1,43 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\Dns; use Froxlor\Database\Database; +use Froxlor\Idna\IdnaWrapper; use Froxlor\Settings; +use Froxlor\UI\Response; +use PDO; class Dns { - - public static function getAllowedDomainEntry($domain_id, $area = 'customer', $userinfo = array()) + public static function getAllowedDomainEntry($domain_id, $area = 'customer', $userinfo = []) { - $dom_data = array( + $dom_data = [ 'did' => $domain_id - ); + ]; $where_clause = ''; if ($area == 'admin') { @@ -33,22 +59,22 @@ class Dns if ($domain) { if ($domain['isbinddomain'] != '1') { - \Froxlor\UI\Response::standard_error('dns_domain_nodns'); + Response::standardError('dns_domain_nodns'); } - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); + $idna_convert = new IdnaWrapper(); return $idna_convert->decode($domain['domain']); } - \Froxlor\UI\Response::standard_error('dns_notfoundorallowed'); + Response::standardError('dns_notfoundorallowed'); } public static function createDomainZone($domain_id, $froxlorhostname = false, $isMainButSubTo = false) { - if (! $froxlorhostname) { + if (!$froxlorhostname) { // get domain-name $dom_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAINS . "` WHERE id = :did"); - $domain = Database::pexecute_first($dom_stmt, array( + $domain = Database::pexecute_first($dom_stmt, [ 'did' => $domain_id - )); + ]); } else { $domain = $domain_id; } @@ -57,37 +83,41 @@ class Dns return; } - $dom_entries = array(); - if (! $froxlorhostname) { + $dom_entries = []; + if (!$froxlorhostname) { // select all entries $sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_DOMAIN_DNS . "` WHERE domain_id = :did ORDER BY id ASC"); - Database::pexecute($sel_stmt, array( + Database::pexecute($sel_stmt, [ 'did' => $domain_id - )); - $dom_entries = $sel_stmt->fetchAll(\PDO::FETCH_ASSOC); + ]); + $dom_entries = $sel_stmt->fetchAll(PDO::FETCH_ASSOC); } // check for required records - $required_entries = array(); + $required_entries = []; self::addRequiredEntry('@', 'A', $required_entries); self::addRequiredEntry('@', 'AAAA', $required_entries); - if (! $isMainButSubTo) { + if (!$isMainButSubTo) { self::addRequiredEntry('@', 'NS', $required_entries); } if ($domain['isemaildomain'] == '1') { self::addRequiredEntry('@', 'MX', $required_entries); if (Settings::Get('system.dns_createmailentry')) { - foreach (array( - 'imap', - 'pop3', - 'mail', - 'smtp' - ) as $record) { - foreach (array( - 'AAAA', - 'A' - ) as $type) { + foreach ( + [ + 'imap', + 'pop3', + 'mail', + 'smtp' + ] as $record + ) { + foreach ( + [ + 'AAAA', + 'A' + ] as $type + ) { self::addRequiredEntry($record, $type, $required_entries); } } @@ -103,17 +133,17 @@ class Dns self::addRequiredEntry('www', 'AAAA', $required_entries); } - if (! $froxlorhostname) { + if (!$froxlorhostname) { // additional required records for subdomains $subdomains_stmt = Database::prepare(" SELECT `domain`, `iswildcarddomain`, `wwwserveralias` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `parentdomainid` = :domainid "); - Database::pexecute($subdomains_stmt, array( + Database::pexecute($subdomains_stmt, [ 'domainid' => $domain_id - )); + ]); - while ($subdomain = $subdomains_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($subdomain = $subdomains_stmt->fetch(PDO::FETCH_ASSOC)) { // Listing domains is enough as there currently is no support for choosing // different ips for a subdomain => use same IPs as toplevel self::addRequiredEntry(str_replace('.' . $domain['domain'], '', $subdomain['domain']), 'A', $required_entries); @@ -138,16 +168,16 @@ class Dns LEFT JOIN " . TABLE_DOMAINTOIP . " dip ON dip.id_ipandports = i.id WHERE i.ssl = 1 AND dip.id_domain = :domainid "); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'domainid' => $domain['id'] - )); + ]); - $ssl_ipandports = array(); - while ($ssl_ipandport = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + $ssl_ipandports = []; + while ($ssl_ipandport = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $ssl_ipandports[] = $ssl_ipandport; } - if (! empty($ssl_ipandports)) { + if (!empty($ssl_ipandports)) { // check for CAA content later self::addRequiredEntry('@CAA@', 'CAA', $required_entries); } @@ -166,7 +196,7 @@ class Dns } $primary_ns = null; - $zonerecords = array(); + $zonerecords = []; // now generate all records and unset the required entries we have foreach ($dom_entries as $entry) { @@ -186,11 +216,13 @@ class Dns $primary_ns = $entry['content']; } // check for CNAME on @, www- or wildcard-Alias and remove A/AAAA record accordingly - foreach ([ - '@', - 'www', - '*' - ] as $crecord) { + foreach ( + [ + '@', + 'www', + '*' + ] as $crecord + ) { if ($entry['type'] == 'CNAME' && $entry['record'] == '@' && (array_key_exists(md5($crecord), $required_entries['A']) || array_key_exists(md5($crecord), $required_entries['AAAA']))) { unset($required_entries['A'][md5($crecord)]); unset($required_entries['AAAA'][md5($crecord)]); @@ -198,24 +230,25 @@ class Dns } // also allow overriding of auto-generated values (imap,pop3,mail,smtp) if enabled in the settings if (Settings::Get('system.dns_createmailentry')) { - foreach (array( - 'imap', - 'pop3', - 'mail', - 'smtp' - ) as $crecord) { - if ($entry['type'] == 'CNAME' && $entry['record'] == $crecord && (array_key_exists(md5($crecord), $required_entries['A']) || array_key_exists(md5($crecord), $required_entries['AAAA']))) { - unset($required_entries['A'][md5($crecord)]); - unset($required_entries['AAAA'][md5($crecord)]); - } - } + foreach ( + [ + 'imap', + 'pop3', + 'mail', + 'smtp' + ] as $crecord + ) { + if ($entry['type'] == 'CNAME' && $entry['record'] == $crecord && (array_key_exists(md5($crecord), $required_entries['A']) || array_key_exists(md5($crecord), $required_entries['AAAA']))) { + unset($required_entries['A'][md5($crecord)]); + unset($required_entries['AAAA'][md5($crecord)]); + } + } } $zonerecords[] = new DnsEntry($entry['record'], $entry['type'], $entry['content'], $entry['prio'], $entry['ttl']); } // add missing required entries - if (! empty($required_entries)) { - + if (!empty($required_entries)) { // A / AAAA records if (array_key_exists("A", $required_entries) || array_key_exists("AAAA", $required_entries)) { if ($froxlorhostname) { @@ -231,11 +264,11 @@ class Dns WHERE `di`.`id_domain` = :domainid AND `p`.`id` = `di`.`id_ipandports` GROUP BY `p`.`ip`; "); - Database::pexecute($result_ip_stmt, array( + Database::pexecute($result_ip_stmt, [ 'domainid' => $domain_id - )); + ]); } - $all_ips = $result_ip_stmt->fetchAll(\PDO::FETCH_ASSOC); + $all_ips = $result_ip_stmt->fetchAll(PDO::FETCH_ASSOC); foreach ($all_ips as $ip) { foreach ($required_entries as $type => $records) { @@ -259,7 +292,7 @@ class Dns foreach ($nameservers as $nameserver) { $nameserver = trim($nameserver); // append dot to hostname - if (substr($nameserver, - 1, 1) != '.') { + if (substr($nameserver, -1, 1) != '.') { $nameserver .= '.'; } foreach ($required_entries as $type => $records) { @@ -284,7 +317,7 @@ class Dns $mxservers = explode(',', Settings::Get('system.mxservers')); foreach ($mxservers as $mxserver) { $mxserver = trim($mxserver); - if (substr($mxserver, - 1, 1) != '.') { + if (substr($mxserver, -1, 1) != '.') { $mxserver .= '.'; } // split in prio and server @@ -307,7 +340,6 @@ class Dns // TXT (SPF and DKIM) if (array_key_exists("TXT", $required_entries)) { - if (Settings::Get('dkim.use_dkim') == '1') { $dkim_entries = self::generateDkimEntries($domain); } @@ -318,7 +350,7 @@ class Dns if ($record == '@SPF@') { $txt_content = Settings::Get('spf.spf_entry'); $zonerecords[] = new DnsEntry('@', 'TXT', self::encloseTXTContent($txt_content)); - } elseif ($record == 'dkim' . $domain['dkim_id'] . '._domainkey' && ! empty($dkim_entries)) { + } elseif ($record == 'dkim' . $domain['dkim_id'] . '._domainkey' && !empty($dkim_entries)) { // check for multiline entry $multiline = false; if (substr($dkim_entries[0], 0, 1) == '(') { @@ -361,7 +393,9 @@ class Dns } } foreach ($caa_entries as $entry) { - if (empty($entry)) continue; + if (empty($entry)) { + continue; + } $zonerecords[] = new DnsEntry('@', 'CAA', $entry); // additional required records by subdomain setting if ($domain['wwwserveralias'] == '1') { @@ -380,19 +414,19 @@ class Dns $primary_ns = Settings::Get('system.hostname'); } - if (! $isMainButSubTo) { + if (!$isMainButSubTo) { $date = date('Ymd'); $domain['bindserial'] = (preg_match('/^' . $date . '/', $domain['bindserial']) ? $domain['bindserial'] + 1 : $date . '00'); - if (! $froxlorhostname) { + if (!$froxlorhostname) { $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `bindserial` = :serial WHERE `id` = :id "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'serial' => $domain['bindserial'], 'id' => $domain['id'] - )); + ]); } // PowerDNS does not like multi-line-format @@ -409,52 +443,22 @@ class Dns array_unshift($zonerecords, $soa_record); } - $zone = new DnsZone((int) Settings::Get('system.defaultttl'), $domain['domain'], $domain['bindserial'], $zonerecords); + $zone = new DnsZone((int)Settings::Get('system.defaultttl'), $domain['domain'], $domain['bindserial'], $zonerecords); return $zone; } - private static function addRequiredEntry($record = '@', $type = 'A', &$required = array()) + private static function addRequiredEntry($record = '@', $type = 'A', &$required = []) { - if (! isset($required[$type])) { - $required[$type] = array(); + if (!isset($required[$type])) { + $required[$type] = []; } $required[$type][md5($record)] = $record; } - public static function encloseTXTContent($txt_content, $isMultiLine = false) - { - // check that TXT content is enclosed in " " - if ($isMultiLine == false && Settings::Get('system.dns_server') != 'PowerDNS') { - if (substr($txt_content, 0, 1) != '"') { - $txt_content = '"' . $txt_content; - } - if (substr($txt_content, - 1) != '"') { - $txt_content .= '"'; - } - } - if (Settings::Get('system.dns_server') == 'PowerDNS') { - // no quotation for PowerDNS - if (substr($txt_content, 0, 1) == '"') { - $txt_content = substr($txt_content, 1); - } - if (substr($txt_content, - 1) == '"') { - $txt_content = substr($txt_content, 0, - 1); - } - } - return $txt_content; - } - - private static function escapeSoaAdminMail($email) - { - $mail_parts = explode("@", $email); - $escpd_mail = str_replace(".", "\.", $mail_parts[0]) . "." . $mail_parts[1] . "."; - return $escpd_mail; - } - private static function generateDkimEntries($domain) { - $zone_dkim = array(); + $zone_dkim = []; if (Settings::Get('dkim.use_dkim') == '1' && $domain['dkim'] == '1' && $domain['dkim_pubkey'] != '') { // start @@ -472,7 +476,7 @@ class Dns } if ($alg != '') { - $alg = substr($alg, 0, - 1); + $alg = substr($alg, 0, -1); $dkim_txt .= 'h=' . $alg . ';'; } @@ -498,4 +502,34 @@ class Dns return $zone_dkim; } + + public static function encloseTXTContent($txt_content, $isMultiLine = false) + { + // check that TXT content is enclosed in " " + if ($isMultiLine == false && Settings::Get('system.dns_server') != 'PowerDNS') { + if (substr($txt_content, 0, 1) != '"') { + $txt_content = '"' . $txt_content; + } + if (substr($txt_content, -1) != '"') { + $txt_content .= '"'; + } + } + if (Settings::Get('system.dns_server') == 'PowerDNS') { + // no quotation for PowerDNS + if (substr($txt_content, 0, 1) == '"') { + $txt_content = substr($txt_content, 1); + } + if (substr($txt_content, -1) == '"') { + $txt_content = substr($txt_content, 0, -1); + } + } + return $txt_content; + } + + private static function escapeSoaAdminMail($email) + { + $mail_parts = explode("@", $email); + $escpd_mail = str_replace(".", "\.", $mail_parts[0]) . "." . $mail_parts[1] . "."; + return $escpd_mail; + } } diff --git a/lib/Froxlor/Dns/DnsEntry.php b/lib/Froxlor/Dns/DnsEntry.php index 6d388ac1..e2e8c8f3 100644 --- a/lib/Froxlor/Dns/DnsEntry.php +++ b/lib/Froxlor/Dns/DnsEntry.php @@ -1,35 +1,39 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\Dns; use Froxlor\Settings; -/** - * This file is part of the Froxlor project. - * Copyright (c) 2016 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 - * - * @copyright (c) the authors - * @author Froxlor team (2016-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes - * - */ class DnsEntry { - public $record; - public $ttl; - public $class = 'IN'; - public $type; - public $priority; - public $content; public function __construct($record = '', $type = 'A', $content = null, $prio = 0, $ttl = 0, $class = 'IN') @@ -58,8 +62,8 @@ class DnsEntry $_content = '("' . $_l . '"' . PHP_EOL; $_l = array_pop($_contentlines); // check for ending quote - if (substr($_l, - 1) == '"') { - $_l = substr($_l, 0, - 1); + if (substr($_l, -1) == '"') { + $_l = substr($_l, 0, -1); } foreach ($_contentlines as $_cl) { // lines in between diff --git a/lib/Froxlor/Dns/DnsZone.php b/lib/Froxlor/Dns/DnsZone.php index 863b56f2..5fb4d22b 100644 --- a/lib/Froxlor/Dns/DnsZone.php +++ b/lib/Froxlor/Dns/DnsZone.php @@ -1,31 +1,37 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\Dns; use Froxlor\Settings; -/** - * This file is part of the Froxlor project. - * Copyright (c) 2016 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 - * - * @copyright (c) the authors - * @author Froxlor team (2016-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes - * - */ class DnsZone { - public $ttl; - public $origin; - public $serial; - public $records; public function __construct($ttl = 0, $origin = '', $serial = '', $records = null) @@ -40,9 +46,9 @@ class DnsZone { $_zonefile = "\$TTL " . $this->ttl . PHP_EOL; $_zonefile .= "\$ORIGIN " . $this->origin . "." . PHP_EOL; - if (! empty($this->records)) { + if (!empty($this->records)) { foreach ($this->records as $record) { - $_zonefile .= (string) $record; + $_zonefile .= (string)$record; } } return $_zonefile; diff --git a/lib/Froxlor/Dns/PowerDNS.php b/lib/Froxlor/Dns/PowerDNS.php index 45262147..33c864eb 100644 --- a/lib/Froxlor/Dns/PowerDNS.php +++ b/lib/Froxlor/Dns/PowerDNS.php @@ -1,115 +1,39 @@ (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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\Dns; + +use Froxlor\FileDir; +use Froxlor\Settings; +use PDO; +use PDOException; + class PowerDNS { - private static $pdns_db = null; - private static function connectToPdnsDb() - { - // get froxlor pdns config - $cf = Settings::Get('system.bindconf_directory') . '/froxlor/pdns_froxlor.conf'; - $config = \Froxlor\FileDir::makeCorrectFile($cf); - - if (! file_exists($config)) { - die('PowerDNS configuration file (' . $config . ') not found. Did you go through the configuration templates?' . PHP_EOL); - } - $lines = file($config); - $mysql_data = array(); - foreach ($lines as $line) { - $line = trim($line); - if (strtolower(substr($line, 0, 6)) == 'gmysql') { - $namevalue = explode("=", $line); - $mysql_data[$namevalue[0]] = $namevalue[1]; - } - } - - // build up connection string - $driver = 'mysql'; - $dsn = $driver . ":"; - $options = array( - 'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8' - ); - $attributes = array( - 'ATTR_ERRMODE' => 'ERRMODE_EXCEPTION' - ); - $dbconf = array(); - - $dbconf["dsn"] = array( - 'dbname' => $mysql_data["gmysql-dbname"], - 'charset' => 'utf8' - ); - - if (isset($mysql_data['gmysql-socket']) && ! empty($mysql_data['gmysql-socket'])) { - $dbconf["dsn"]['unix_socket'] = \Froxlor\FileDir::makeCorrectFile($mysql_data['gmysql-socket']); - } else { - $dbconf["dsn"]['host'] = $mysql_data['gmysql-host']; - $dbconf["dsn"]['port'] = $mysql_data['gmysql-port']; - - if (!empty($mysql_data['gmysql-ssl-ca-file'])) { - $options[\PDO::MYSQL_ATTR_SSL_CA] = $mysql_data['gmysql-ssl-ca-file']; - $options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = (bool) $mysql_data['gmysql-ssl-verify-server-certificate']; - } - } - - // add options to dsn-string - foreach ($dbconf["dsn"] as $k => $v) { - $dsn .= $k . "=" . $v . ";"; - } - - // clean up - unset($dbconf); - - // try to connect - try { - self::$pdns_db = new \PDO($dsn, $mysql_data['gmysql-user'], $mysql_data['gmysql-password'], $options); - } catch (\PDOException $e) { - die($e->getMessage()); - } - - // set attributes - foreach ($attributes as $k => $v) { - self::$pdns_db->setAttribute(constant("PDO::" . $k), constant("PDO::" . $v)); - } - - $version_server = self::$pdns_db->getAttribute(\PDO::ATTR_SERVER_VERSION); - $sql_mode = 'NO_ENGINE_SUBSTITUTION'; - if (version_compare($version_server, '8.0.11', '<')) { - $sql_mode .= ',NO_AUTO_CREATE_USER'; - } - self::$pdns_db->exec('SET sql_mode = "' . $sql_mode . '"'); - } - - /** - * get pdo database connection to powerdns database - * - * @return \PDO - */ - public static function getDB() - { - if (! isset(self::$pdns_db) || (self::$pdns_db instanceof \PDO) == false) { - self::connectToPdnsDb(); - } - return self::$pdns_db; - } - /** * remove all records and entries of a given domain * @@ -123,20 +47,108 @@ class PowerDNS $del_meta_stmt = self::getDB()->prepare("DELETE FROM `domainmetadata` WHERE `domain_id` = :did"); $del_dom_stmt = self::getDB()->prepare("DELETE FROM `domains` WHERE `id` = :did"); - $pdns_domains_stmt->execute(array( + $pdns_domains_stmt->execute([ 'domain' => $domain['domain'] - )); - $pdns_domain = $pdns_domains_stmt->fetch(\PDO::FETCH_ASSOC); + ]); + $pdns_domain = $pdns_domains_stmt->fetch(PDO::FETCH_ASSOC); - $del_rec_stmt->execute(array( + $del_rec_stmt->execute([ 'did' => $pdns_domain['id'] - )); - $del_meta_stmt->execute(array( + ]); + $del_meta_stmt->execute([ 'did' => $pdns_domain['id'] - )); - $del_dom_stmt->execute(array( + ]); + $del_dom_stmt->execute([ 'did' => $pdns_domain['id'] - )); + ]); } } + + /** + * get pdo database connection to powerdns database + * + * @return PDO + */ + public static function getDB() + { + if (!isset(self::$pdns_db) || (self::$pdns_db instanceof PDO) == false) { + self::connectToPdnsDb(); + } + return self::$pdns_db; + } + + private static function connectToPdnsDb() + { + // get froxlor pdns config + $cf = Settings::Get('system.bindconf_directory') . '/froxlor/pdns_froxlor.conf'; + $config = FileDir::makeCorrectFile($cf); + + if (!file_exists($config)) { + die('PowerDNS configuration file (' . $config . ') not found. Did you go through the configuration templates?' . PHP_EOL); + } + $lines = file($config); + $mysql_data = []; + foreach ($lines as $line) { + $line = trim($line); + if (strtolower(substr($line, 0, 6)) == 'gmysql') { + $namevalue = explode("=", $line); + $mysql_data[$namevalue[0]] = $namevalue[1]; + } + } + + // build up connection string + $driver = 'mysql'; + $dsn = $driver . ":"; + $options = [ + 'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8' + ]; + $attributes = [ + 'ATTR_ERRMODE' => 'ERRMODE_EXCEPTION' + ]; + $dbconf = []; + + $dbconf["dsn"] = [ + 'dbname' => $mysql_data["gmysql-dbname"], + 'charset' => 'utf8' + ]; + + if (isset($mysql_data['gmysql-socket']) && !empty($mysql_data['gmysql-socket'])) { + $dbconf["dsn"]['unix_socket'] = FileDir::makeCorrectFile($mysql_data['gmysql-socket']); + } else { + $dbconf["dsn"]['host'] = $mysql_data['gmysql-host']; + $dbconf["dsn"]['port'] = $mysql_data['gmysql-port']; + + if (!empty($mysql_data['gmysql-ssl-ca-file'])) { + $options[PDO::MYSQL_ATTR_SSL_CA] = $mysql_data['gmysql-ssl-ca-file']; + $options[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = (bool)$mysql_data['gmysql-ssl-verify-server-certificate']; + } + } + + // add options to dsn-string + foreach ($dbconf["dsn"] as $k => $v) { + $dsn .= $k . "=" . $v . ";"; + } + + // clean up + unset($dbconf); + + // try to connect + try { + self::$pdns_db = new PDO($dsn, $mysql_data['gmysql-user'], $mysql_data['gmysql-password'], $options); + } catch (PDOException $e) { + die($e->getMessage()); + } + + // set attributes + foreach ($attributes as $k => $v) { + self::$pdns_db->setAttribute(constant("PDO::" . $k), constant("PDO::" . $v)); + } + + $version_server = self::$pdns_db->getAttribute(PDO::ATTR_SERVER_VERSION); + $sql_mode = 'NO_ENGINE_SUBSTITUTION'; + if (version_compare($version_server, '8.0.11', '<')) { + $sql_mode .= ',NO_AUTO_CREATE_USER'; + } + self::$pdns_db->exec('SET sql_mode = "' . $sql_mode . '"'); + } } diff --git a/lib/Froxlor/Domain/Domain.php b/lib/Froxlor/Domain/Domain.php index a63a5ba5..69aeb270 100644 --- a/lib/Froxlor/Domain/Domain.php +++ b/lib/Froxlor/Domain/Domain.php @@ -1,7 +1,36 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\Domain; +use Froxlor\Cron\Http\LetsEncrypt\AcmeSh; use Froxlor\Database\Database; +use Froxlor\FileDir; +use Froxlor\FroxlorLogger; +use Froxlor\Settings; +use PDO; class Domain { @@ -22,20 +51,20 @@ class Domain AND dip.id_domain = :domainid GROUP BY i.ip "); - $sel_param = array( + $sel_param = [ 'domainid' => $domain_id - ); + ]; } else { // assuming froxlor.vhost (id = 0) $sel_stmt = Database::prepare(" SELECT ip FROM `" . TABLE_PANEL_IPSANDPORTS . "` GROUP BY ip "); - $sel_param = array(); + $sel_param = []; } Database::pexecute($sel_stmt, $sel_param); - $result = array(); - while ($ip = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) { + $result = []; + while ($ip = $sel_stmt->fetch(PDO::FETCH_ASSOC)) { $result[] = $ip['ip']; } return $result; @@ -51,71 +80,42 @@ class Domain $sql = "SELECT * FROM `" . TABLE_PANEL_REDIRECTCODES . "` WHERE `enabled` = '1' ORDER BY `id` ASC"; $result_stmt = Database::query($sql); - $codes = array(); - while ($rc = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + $codes = []; + while ($rc = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $codes[] = $rc; } return $codes; } - /** - * return an array of all enabled redirect-codes - * for the settings form - * - * @param bool $add_desc - * optional, default true, add the code-description - * - * @return array array of enabled redirect-codes - */ - public static function getRedirectCodes($add_desc = true) - { - global $lng; - - $sql = "SELECT * FROM `" . TABLE_PANEL_REDIRECTCODES . "` WHERE `enabled` = '1' ORDER BY `id` ASC"; - $result_stmt = Database::query($sql); - - $codes = array(); - while ($rc = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { - $codes[$rc['id']] = $rc['code']; - if ($add_desc) { - $codes[$rc['id']] .= ' (' . $lng['redirect_desc'][$rc['desc']] . ')'; - } - } - - return $codes; - } - /** * returns the redirect-code for a given * domain-id * * @param integer $domainid - * id of the domain - * + * id of the domain + * * @return string redirect-code */ public static function getDomainRedirectCode($domainid = 0) { - // get system default $default = '301'; - if (\Froxlor\Settings::Get('customredirect.enabled') == '1') { + if (Settings::Get('customredirect.enabled') == '1') { $all_codes = self::getRedirectCodes(false); - $_default = $all_codes[\Froxlor\Settings::Get('customredirect.default')]; + $_default = $all_codes[Settings::Get('customredirect.default')]; $default = ($_default == '---') ? $default : $_default; } $code = $default; if ($domainid > 0) { - $result_stmt = Database::prepare(" SELECT `r`.`code` as `redirect` FROM `" . TABLE_PANEL_REDIRECTCODES . "` `r`, `" . TABLE_PANEL_DOMAINREDIRECTS . "` `rc` WHERE `r`.`id` = `rc`.`rid` and `rc`.`did` = :domainid "); - $result = Database::pexecute_first($result_stmt, array( + $result = Database::pexecute_first($result_stmt, [ 'domainid' => $domainid - )); + ]); if (is_array($result) && isset($result['redirect'])) { $code = ($result['redirect'] == '---') ? $default : $result['redirect']; @@ -124,13 +124,40 @@ class Domain return $code; } + /** + * return an array of all enabled redirect-codes + * for the settings form + * + * @param bool $add_desc + * optional, default true, add the code-description + * + * @return array array of enabled redirect-codes + */ + public static function getRedirectCodes($add_desc = true) + { + global $lng; + + $sql = "SELECT * FROM `" . TABLE_PANEL_REDIRECTCODES . "` WHERE `enabled` = '1' ORDER BY `id` ASC"; + $result_stmt = Database::query($sql); + + $codes = []; + while ($rc = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + $codes[$rc['id']] = $rc['code']; + if ($add_desc) { + $codes[$rc['id']] .= ' (' . $lng['redirect_desc'][$rc['desc']] . ')'; + } + } + + return $codes; + } + /** * returns the redirect-id for a given * domain-id * * @param integer $domainid - * id of the domain - * + * id of the domain + * * @return integer redirect-code-id */ public static function getDomainRedirectId($domainid = 0) @@ -142,12 +169,12 @@ class Domain FROM `" . TABLE_PANEL_REDIRECTCODES . "` `r`, `" . TABLE_PANEL_DOMAINREDIRECTS . "` `rc` WHERE `r`.`id` = `rc`.`rid` and `rc`.`did` = :domainid "); - $result = Database::pexecute_first($result_stmt, array( + $result = Database::pexecute_first($result_stmt, [ 'domainid' => $domainid - )); + ]); if (is_array($result) && isset($result['redirect'])) { - $code = (int) $result['redirect']; + $code = (int)$result['redirect']; } } return $code; @@ -157,10 +184,10 @@ class Domain * adds a redirectcode for a domain * * @param integer $domainid - * id of the domain to add the code for + * id of the domain to add the code for * @param integer $redirect - * selected redirect-id - * + * selected redirect-id + * * @return null */ public static function addRedirectToDomain($domainid = 0, $redirect = 1) @@ -169,10 +196,10 @@ class Domain $ins_stmt = Database::prepare(" INSERT INTO `" . TABLE_PANEL_DOMAINREDIRECTS . "` SET `rid` = :rid, `did` = :did "); - Database::pexecute($ins_stmt, array( + Database::pexecute($ins_stmt, [ 'rid' => $redirect, 'did' => $domainid - )); + ]); } } @@ -181,10 +208,10 @@ class Domain * if redirect-code is false, nothing happens * * @param integer $domainid - * id of the domain to update + * id of the domain to update * @param integer $redirect - * selected redirect-id or false - * + * selected redirect-id or false + * * @return null */ public static function updateRedirectOfDomain($domainid = 0, $redirect = false) @@ -197,17 +224,17 @@ class Domain $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_DOMAINREDIRECTS . "` WHERE `did` = :domainid "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'domainid' => $domainid - )); + ]); $ins_stmt = Database::prepare(" INSERT INTO `" . TABLE_PANEL_DOMAINREDIRECTS . "` SET `rid` = :rid, `did` = :did "); - Database::pexecute($ins_stmt, array( + Database::pexecute($ins_stmt, [ 'rid' => $redirect, 'did' => $domainid - )); + ]); } } @@ -216,8 +243,8 @@ class Domain * #329 * * @param int $id - * domain-id - * + * domain-id + * * @return boolean */ public static function domainHasMainSubDomains($id = 0) @@ -225,9 +252,9 @@ class Domain $result_stmt = Database::prepare(" SELECT COUNT(`id`) as `mainsubs` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `ismainbutsubto` = :id"); - $result = Database::pexecute_first($result_stmt, array( + $result = Database::pexecute_first($result_stmt, [ 'id' => $id - )); + ]); if (isset($result['mainsubs']) && $result['mainsubs'] > 0) { return true; @@ -240,18 +267,18 @@ class Domain * #329 * * @param int $id - * subof-domain-id - * + * subof-domain-id + * * @return boolean */ public static function domainMainToSubExists($id = 0) { $result_stmt = Database::prepare(" SELECT `id` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `id` = :id"); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'id' => $id - )); - $result = $result_stmt->fetch(\PDO::FETCH_ASSOC); + ]); + $result = $result_stmt->fetch(PDO::FETCH_ASSOC); if (isset($result['id']) && $result['id'] > 0) { return true; @@ -271,10 +298,10 @@ class Domain $result_stmt = Database::prepare(" SELECT `dt`.* FROM `" . TABLE_DOMAINTOIP . "` `dt`, `" . TABLE_PANEL_IPSANDPORTS . "` `iap` WHERE `dt`.`id_ipandports` = `iap`.`id` AND `iap`.`ssl` = '1' AND `dt`.`id_domain` = :domainid;"); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'domainid' => $domainid - )); - $result = $result_stmt->fetch(\PDO::FETCH_ASSOC); + ]); + $result = $result_stmt->fetch(PDO::FETCH_ASSOC); if (is_array($result) && isset($result['id_ipandports'])) { return true; @@ -287,8 +314,8 @@ class Domain * is the std-subdomain of a customer * * @param - * int domain-id - * + * int domain-id + * * @return boolean */ public static function isCustomerStdSubdomain($did = 0) @@ -298,9 +325,9 @@ class Domain SELECT `customerid` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `standardsubdomain` = :did "); - $result = Database::pexecute_first($result_stmt, array( + $result = Database::pexecute_first($result_stmt, [ 'did' => $did - )); + ]); if (is_array($result) && isset($result['customerid']) && $result['customerid'] > 0) { return true; @@ -312,7 +339,7 @@ class Domain public static function triggerLetsEncryptCSRForAliasDestinationDomain($aliasDestinationDomainID, $log) { if (isset($aliasDestinationDomainID) && $aliasDestinationDomainID > 0) { - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "LetsEncrypt CSR triggered for domain ID " . $aliasDestinationDomainID); + $log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "LetsEncrypt CSR triggered for domain ID " . $aliasDestinationDomainID); $upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` SET @@ -320,27 +347,27 @@ class Domain WHERE domainid = :domainid "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'domainid' => $aliasDestinationDomainID - )); + ]); } } public static function doLetsEncryptCleanUp($domainname = null) { // @ see \Froxlor\Cron\Http\LetsEncrypt\AcmeSh.php - $acmesh = \Froxlor\Cron\Http\LetsEncrypt\AcmeSh::getAcmeSh(); + $acmesh = AcmeSh::getAcmeSh(); if (file_exists($acmesh)) { - $certificate_folder = \Froxlor\Cron\Http\LetsEncrypt\AcmeSh::getWorkingDirFromEnv($domainname); + $certificate_folder = AcmeSh::getWorkingDirFromEnv($domainname); if (file_exists($certificate_folder)) { $params = " --remove -d " . $domainname; - if (\Froxlor\Settings::Get('system.leecc') > 0) { + if (Settings::Get('system.leecc') > 0) { $params .= " --ecc"; } // run remove command - \Froxlor\FileDir::safe_exec($acmesh . $params); + FileDir::safe_exec($acmesh . $params); // remove certificates directory - \Froxlor\FileDir::safe_exec('rm -rf ' . $certificate_folder); + FileDir::safe_exec('rm -rf ' . $certificate_folder); } } return true; @@ -352,20 +379,19 @@ class Domain * to a line for a open_basedir directive * * @param string $path - * the path to check and append + * the path to check and append * @param boolean $first - * if true, no ':' will be prefixed to the path - * + * if true, no ':' will be prefixed to the path + * * @return string */ public static function appendOpenBasedirPath($path = '', $first = false) { - if ($path != '' && $path != '/' && (! preg_match("#^/dev#i", $path) || preg_match("#^/dev/urandom#i", $path)) && ! preg_match("#^/proc#i", $path) && ! preg_match("#^/etc#i", $path) && ! preg_match("#^/sys#i", $path) && ! preg_match("#:#", $path)) { - + if ($path != '' && $path != '/' && (!preg_match("#^/dev#i", $path) || preg_match("#^/dev/urandom#i", $path)) && !preg_match("#^/proc#i", $path) && !preg_match("#^/etc#i", $path) && !preg_match("#^/sys#i", $path) && !preg_match("#:#", $path)) { if (preg_match("#^/dev/urandom#i", $path)) { - $path = \Froxlor\FileDir::makeCorrectFile($path); + $path = FileDir::makeCorrectFile($path); } else { - $path = \Froxlor\FileDir::makeCorrectDir($path); + $path = FileDir::makeCorrectDir($path); } // check for php-version that requires the trailing @@ -373,9 +399,9 @@ class Domain // of the subfolders within the given folder, fixes #797 if ((PHP_MINOR_VERSION == 2 && PHP_VERSION_ID >= 50216) || PHP_VERSION_ID >= 50304) { // check trailing slash - if (substr($path, - 1, 1) == '/') { + if (substr($path, -1, 1) == '/') { // remove it - $path = substr($path, 0, - 1); + $path = substr($path, 0, -1); } } diff --git a/lib/Froxlor/Domain/IpAddr.php b/lib/Froxlor/Domain/IpAddr.php index 62f9fea4..3ce52fad 100644 --- a/lib/Froxlor/Domain/IpAddr.php +++ b/lib/Froxlor/Domain/IpAddr.php @@ -1,7 +1,32 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\Domain; use Froxlor\Database\Database; +use PDO; class IpAddr { @@ -12,11 +37,10 @@ class IpAddr SELECT `id`, `ip`, `port` FROM `" . TABLE_PANEL_IPSANDPORTS . "` ORDER BY `ip` ASC, `port` ASC "); - $system_ipaddress_array = array(); + $system_ipaddress_array = []; - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { - - if (! isset($system_ipaddress_array[$row['ip']]) && ! in_array($row['ip'], $system_ipaddress_array)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + if (!isset($system_ipaddress_array[$row['ip']]) && !in_array($row['ip'], $system_ipaddress_array)) { if (filter_var($row['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { $row['ip'] = '[' . $row['ip'] . ']'; } @@ -27,21 +51,29 @@ class IpAddr return $system_ipaddress_array; } + public static function getSslIpPortCombinations() + { + global $lng; + return [ + '' => $lng['panel']['none_value'] + ] + self::getIpPortCombinations(true); + } + public static function getIpPortCombinations($ssl = false) { global $userinfo; - $additional_conditions_params = array(); - $additional_conditions_array = array(); + $additional_conditions_params = []; + $additional_conditions_array = []; if ($userinfo['ip'] != '-1') { $admin_ip_stmt = Database::prepare(" SELECT `id`, `ip`, `port` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `id` = IN (:ipid) "); $myips = implode(",", json_decode($userinfo['ip'], true)); - Database::pexecute($admin_ip_stmt, array( + Database::pexecute($admin_ip_stmt, [ 'ipid' => $myips - )); + ]); $additional_conditions_array[] = "`ip` IN (:adminips)"; $additional_conditions_params['adminips'] = $myips; } @@ -61,9 +93,9 @@ class IpAddr "); Database::pexecute($result_stmt, $additional_conditions_params); - $system_ipaddress_array = array(); + $system_ipaddress_array = []; - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { if (filter_var($row['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { $row['ip'] = '[' . $row['ip'] . ']'; } @@ -72,12 +104,4 @@ class IpAddr return $system_ipaddress_array; } - - public static function getSslIpPortCombinations() - { - global $lng; - return array( - '' => $lng['panel']['none_value'] - ) + self::getIpPortCombinations(true); - } } diff --git a/lib/Froxlor/FileDir.php b/lib/Froxlor/FileDir.php index 02bfb981..0d001d15 100644 --- a/lib/Froxlor/FileDir.php +++ b/lib/Froxlor/FileDir.php @@ -1,11 +1,190 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor; +use Exception; +use Froxlor\Customer\Customer; use Froxlor\Database\Database; +use PDO; +use RecursiveCallbackFilterIterator; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; class FileDir { + /** + * Creates a directory below a users homedir and sets all directories, + * which had to be created below with correct Owner/Group + * (Copied from cron_tasks.php:rev1189 as we'll need this more often in future) + * + * @param string $homeDir + * The homedir of the user + * @param string $dirToCreate + * The dir which should be created + * @param int $uid + * The uid of the user + * @param int $gid + * The gid of the user + * @param bool $placeindex + * Place standard-index.html into the new folder + * @param bool $allow_notwithinhomedir + * Allow creating a directory out of the customers docroot + * + * @return bool true if everything went okay, false if something went wrong + * @throws Exception + */ + public static function mkDirWithCorrectOwnership( + $homeDir, + $dirToCreate, + $uid, + $gid, + $placeindex = false, + $allow_notwithinhomedir = false + ) { + if ($homeDir != '' && $dirToCreate != '') { + $homeDir = self::makeCorrectDir($homeDir); + $dirToCreate = self::makeCorrectDir($dirToCreate); + + if (substr($dirToCreate, 0, strlen($homeDir)) == $homeDir) { + $subdir = substr($dirToCreate, strlen($homeDir) - 1); + $within_homedir = true; + } else { + $subdir = $dirToCreate; + $within_homedir = false; + } + + $subdir = self::makeCorrectDir($subdir); + $subdirs = []; + + if ($within_homedir || !$allow_notwithinhomedir) { + $subdirlen = strlen($subdir); + $offset = 0; + + while ($offset < $subdirlen) { + $offset = strpos($subdir, '/', $offset); + $subdirelem = substr($subdir, 0, $offset); + $offset++; + array_push($subdirs, self::makeCorrectDir($homeDir . $subdirelem)); + } + } else { + array_push($subdirs, $dirToCreate); + } + + $subdirs = array_unique($subdirs); + sort($subdirs); + foreach ($subdirs as $sdir) { + if (!is_dir($sdir)) { + $sdir = self::makeCorrectDir($sdir); + self::safe_exec('mkdir -p ' . escapeshellarg($sdir)); + // place index + if ($placeindex) { + $loginname = Customer::getLoginNameByUid($uid); + if ($loginname !== false) { + self::storeDefaultIndex($loginname, $sdir, null); + } + } + self::safe_exec('chown -R ' . (int)$uid . ':' . (int)$gid . ' ' . escapeshellarg($sdir)); + } + } + return true; + } + return false; + } + + /** + * Function which returns a correct dirname, means to add slashes at the beginning and at the end if there weren't + * some + * + * @param string $path + * the path to correct + * + * @return string the corrected path + * @throws Exception + */ + public static function makeCorrectDir($dir) + { + if (is_string($dir) && strlen($dir) > 0) { + $dir = trim($dir); + if (substr($dir, -1, 1) != '/') { + $dir .= '/'; + } + if (substr($dir, 0, 1) != '/') { + $dir = '/' . $dir; + } + return self::makeSecurePath($dir); + } + throw new Exception("Cannot validate directory in " . __FUNCTION__ . " which is very dangerous."); + } + + /** + * Function which returns a secure path, means to remove all multiple dots and slashes + * + * @param string $path + * the path to secure + * + * @return string the corrected path + */ + public static function makeSecurePath($path) + { + // check for bad characters, some are allowed with escaping + // but we generally don't want them in our directory-names, + // thx to aaronmueller for this snipped + $badchars = [ + ':', + ';', + '|', + '&', + '>', + '<', + '`', + '$', + '~', + '?', + "\0" + ]; + foreach ($badchars as $bc) { + $path = str_replace($bc, "", $path); + } + + $search = [ + '#/+#', + '#\.+#' + ]; + $replace = [ + '/', + '.' + ]; + $path = preg_replace($search, $replace, $path); + // don't just replace a space with an escaped space + // it might be escaped already + $path = str_replace("\ ", " ", $path); + $path = str_replace(" ", "\ ", $path); + + return $path; + } /** * Wrapper around the exec command. @@ -21,7 +200,7 @@ class FileDir */ public static function safe_exec($exec_string, &$return_value = false, $allowedChars = null) { - $disallowed = array( + $disallowed = [ ';', '|', '&', @@ -31,7 +210,7 @@ class FileDir '$', '~', '?' - ); + ]; $acheck = false; if ($allowedChars != null && is_array($allowedChars) && count($allowedChars) > 0) { @@ -61,129 +240,6 @@ class FileDir return $return; } - /** - * Creates a directory below a users homedir and sets all directories, - * which had to be created below with correct Owner/Group - * (Copied from cron_tasks.php:rev1189 as we'll need this more often in future) - * - * @param string $homeDir - * The homedir of the user - * @param string $dirToCreate - * The dir which should be created - * @param int $uid - * The uid of the user - * @param int $gid - * The gid of the user - * @param bool $placeindex - * Place standard-index.html into the new folder - * @param bool $allow_notwithinhomedir - * Allow creating a directory out of the customers docroot - * - * @return bool true if everything went okay, false if something went wrong - */ - public static function mkDirWithCorrectOwnership( - $homeDir, - $dirToCreate, - $uid, - $gid, - $placeindex = false, - $allow_notwithinhomedir = false - ) { - if ($homeDir != '' && $dirToCreate != '') { - $homeDir = self::makeCorrectDir($homeDir); - $dirToCreate = self::makeCorrectDir($dirToCreate); - - if (substr($dirToCreate, 0, strlen($homeDir)) == $homeDir) { - $subdir = substr($dirToCreate, strlen($homeDir) - 1); - $within_homedir = true; - } else { - $subdir = $dirToCreate; - $within_homedir = false; - } - - $subdir = self::makeCorrectDir($subdir); - $subdirs = array(); - - if ($within_homedir || !$allow_notwithinhomedir) { - $subdirlen = strlen($subdir); - $offset = 0; - - while ($offset < $subdirlen) { - $offset = strpos($subdir, '/', $offset); - $subdirelem = substr($subdir, 0, $offset); - $offset++; - array_push($subdirs, self::makeCorrectDir($homeDir . $subdirelem)); - } - } else { - array_push($subdirs, $dirToCreate); - } - - $subdirs = array_unique($subdirs); - sort($subdirs); - foreach ($subdirs as $sdir) { - if (!is_dir($sdir)) { - $sdir = self::makeCorrectDir($sdir); - self::safe_exec('mkdir -p ' . escapeshellarg($sdir)); - // place index - if ($placeindex) { - $loginname = \Froxlor\Customer\Customer::getLoginNameByUid($uid); - if ($loginname !== false) { - self::storeDefaultIndex($loginname, $sdir, null); - } - } - self::safe_exec('chown -R ' . (int)$uid . ':' . (int)$gid . ' ' . escapeshellarg($sdir)); - } - } - return true; - } - return false; - } - - /** - * checks a directory against disallowed paths which could - * lead to a damaged system if you use them - * - * @param string $fieldname - * @param array $fielddata - * @param mixed $newfieldvalue - * - * @return boolean|array - */ - public static function checkDisallowedPaths($path = null) - { - /* - * disallow base-directories and / - */ - $disallowed_values = array( - "/", - "/bin/", - "/boot/", - "/dev/", - "/etc/", - "/home/", - "/lib/", - "/lib32/", - "/lib64/", - "/opt/", - "/proc/", - "/root/", - "/run/", - "/sbin/", - "/sys/", - "/tmp/", - "/usr/", - "/var/" - ); - - $path = self::makeCorrectDir($path); - - // check if it's a disallowed path - if (in_array($path, $disallowed_values)) { - return false; - } - return true; - } - /** * store the default index-file in a given destination folder * @@ -208,20 +264,20 @@ class FileDir INNER JOIN `" . TABLE_PANEL_TEMPLATES . "` AS `t` ON `a`.`adminid` = `t`.`adminid` WHERE `varname` = 'index_html' AND `c`.`loginname` = :loginname"); - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, [ 'loginname' => $loginname - )); + ]); if (Database::num_rows() > 0) { - $template = $result_stmt->fetch(\PDO::FETCH_ASSOC); + $template = $result_stmt->fetch(PDO::FETCH_ASSOC); - $replace_arr = array( + $replace_arr = [ 'SERVERNAME' => Settings::Get('system.hostname'), 'CUSTOMER' => $template['customer_login'], 'ADMIN' => $template['admin_login'], 'CUSTOMER_EMAIL' => $template['customer_email'], 'ADMIN_EMAIL' => $template['admin_email'] - ); + ]; // replaceVariables $htmlcontent = PhpHelper::replaceVariables($template['value'], $replace_arr); @@ -230,16 +286,22 @@ class FileDir fwrite($index_html_handler, $htmlcontent); fclose($index_html_handler); if ($logger !== null) { - $logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, - 'Creating \'index.' . Settings::Get('system.index_file_extension') . '\' for Customer \'' . $template['customer_login'] . '\' based on template in directory ' . escapeshellarg($indexhtmlpath)); + $logger->logAction( + FroxlorLogger::CRON_ACTION, + LOG_NOTICE, + 'Creating \'index.' . Settings::Get('system.index_file_extension') . '\' for Customer \'' . $template['customer_login'] . '\' based on template in directory ' . escapeshellarg($indexhtmlpath) + ); } } else { $destination = self::makeCorrectDir($destination); if ($logger !== null) { - $logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, - 'Running: cp -a ' . \Froxlor\Froxlor::getInstallDir() . '/templates/misc/standardcustomer/* ' . escapeshellarg($destination)); + $logger->logAction( + FroxlorLogger::CRON_ACTION, + LOG_NOTICE, + 'Running: cp -a ' . Froxlor::getInstallDir() . '/templates/misc/standardcustomer/* ' . escapeshellarg($destination) + ); } - self::safe_exec('cp -a ' . \Froxlor\Froxlor::getInstallDir() . '/templates/misc/standardcustomer/* ' . escapeshellarg($destination)); + self::safe_exec('cp -a ' . Froxlor::getInstallDir() . '/templates/misc/standardcustomer/* ' . escapeshellarg($destination)); } } return; @@ -274,75 +336,48 @@ class FileDir } /** - * Function which returns a correct dirname, means to add slashes at the beginning and at the end if there weren't - * some + * checks a directory against disallowed paths which could + * lead to a damaged system if you use them * - * @param string $path - * the path to correct + * @param string $fieldname + * @param array $fielddata + * @param mixed $newfieldvalue * - * @return string the corrected path - * @throws \Exception + * @return boolean|array */ - public static function makeCorrectDir($dir) + public static function checkDisallowedPaths($path = null) { - if (is_string($dir) && strlen($dir) > 0) { - $dir = trim($dir); - if (substr($dir, -1, 1) != '/') { - $dir .= '/'; - } - if (substr($dir, 0, 1) != '/') { - $dir = '/' . $dir; - } - return self::makeSecurePath($dir); + /* + * disallow base-directories and / + */ + $disallowed_values = [ + "/", + "/bin/", + "/boot/", + "/dev/", + "/etc/", + "/home/", + "/lib/", + "/lib32/", + "/lib64/", + "/opt/", + "/proc/", + "/root/", + "/run/", + "/sbin/", + "/sys/", + "/tmp/", + "/usr/", + "/var/" + ]; + + $path = self::makeCorrectDir($path); + + // check if it's a disallowed path + if (in_array($path, $disallowed_values)) { + return false; } - throw new \Exception("Cannot validate directory in " . __FUNCTION__ . " which is very dangerous."); - } - - /** - * Function which returns a secure path, means to remove all multiple dots and slashes - * - * @param string $path - * the path to secure - * - * @return string the corrected path - */ - public static function makeSecurePath($path) - { - // check for bad characters, some are allowed with escaping - // but we generally don't want them in our directory-names, - // thx to aaronmueller for this snipped - $badchars = array( - ':', - ';', - '|', - '&', - '>', - '<', - '`', - '$', - '~', - '?', - "\0" - ); - foreach ($badchars as $bc) { - $path = str_replace($bc, "", $path); - } - - $search = array( - '#/+#', - '#\.+#' - ); - $replace = array( - '/', - '.' - ); - $path = preg_replace($search, $replace, $path); - // don't just replace a space with an escaped space - // it might be escaped already - $path = str_replace("\ ", " ", $path); - $path = str_replace(" ", "\ ", $path); - - return $path; + return true; } /** @@ -351,7 +386,7 @@ class FileDir * @param * string The destinations * @return string the corrected destinations - * @author Florian Lippert + * @author Florian Lippert (2003-2009) */ public static function makeCorrectDestination($destination) { @@ -392,7 +427,7 @@ class FileDir global $lng; $value = str_replace($path, '', $value); - $field = array(); + $field = []; // path is given without starting slash // but dirList holds the paths with starting slash @@ -402,13 +437,13 @@ class FileDir $value = '/' . $value; } - $fieldType = strtolower(\Froxlor\Settings::Get('panel.pathedit')); + $fieldType = strtolower(Settings::Get('panel.pathedit')); if ($fieldType == 'manual') { - $field = array( + $field = [ 'type' => 'text', 'value' => htmlspecialchars($value) - ); + ]; } elseif ($fieldType == 'dropdown') { $dirList = self::findDirs($path, $uid, $gid); natcasesort($dirList); @@ -427,30 +462,30 @@ class FileDir } $_field[$dir] = $dir; } - $field = array( + $field = [ 'type' => 'select', 'select_var' => $_field, 'selected' => $value - ); + ]; } else { // remove starting slash we added // for the Dropdown, #225 $value = substr($value, 1); // $field = $lng['panel']['toomanydirs']; - $field = array( + $field = [ 'type' => 'text', 'value' => htmlspecialchars($value), 'note' => $lng['panel']['toomanydirs'] - ); + ]; } } else { // $field = $lng['panel']['dirsmissing']; // $field = ''; - $field = array( + $field = [ 'type' => 'hidden', 'value' => '/', 'note' => $lng['panel']['dirsmissing'] - ); + ]; } } @@ -474,16 +509,16 @@ class FileDir */ private static function findDirs($path, $uid, $gid) { - $_fileList = array(); + $_fileList = []; $path = self::makeCorrectDir($path); // valid directory? if (is_dir($path)) { // Will exclude everything under these directories - $exclude = array( + $exclude = [ 'awstats', 'webalizer' - ); + ]; /** * @@ -500,8 +535,10 @@ class FileDir }; // create RecursiveIteratorIterator - $its = new \RecursiveIteratorIterator(new \RecursiveCallbackFilterIterator(new \RecursiveDirectoryIterator($path, - \RecursiveDirectoryIterator::SKIP_DOTS), $filter)); + $its = new RecursiveIteratorIterator(new RecursiveCallbackFilterIterator(new RecursiveDirectoryIterator( + $path, + RecursiveDirectoryIterator::SKIP_DOTS + ), $filter)); // we can limit the recursion-depth, but will it be helpful or // will people start asking "why do I only see 2 subdirectories, i want to use /a/b/c" // let's keep this in mind and see whether it will be useful @@ -520,24 +557,6 @@ class FileDir return array_unique($_fileList); } - /** - * check if the system is FreeBSD (if exact) - * or BSD-based (NetBSD, OpenBSD, etc. - * if exact = false [default]) - * - * @param boolean $exact - * whether to check explicitly for FreeBSD or *BSD - * - * @return boolean - */ - public static function isFreeBSD($exact = false) - { - if (($exact && PHP_OS == 'FreeBSD') || (!$exact && stristr(PHP_OS, 'BSD'))) { - return true; - } - return false; - } - /** * set the immutable flag for a file * @@ -548,20 +567,7 @@ class FileDir */ public static function setImmutable($filename = null) { - \Froxlor\FileDir::safe_exec(self::getImmutableFunction(false) . escapeshellarg($filename)); - } - - /** - * removes the immutable flag for a file - * - * @param string $filename - * the file to set the flag for - * - * @return boolean - */ - public static function removeImmutable($filename = null) - { - \Froxlor\FileDir::safe_exec(self::getImmutableFunction(true) . escapeshellarg($filename)); + FileDir::safe_exec(self::getImmutableFunction(false) . escapeshellarg($filename)); } /** @@ -584,6 +590,37 @@ class FileDir } } + /** + * check if the system is FreeBSD (if exact) + * or BSD-based (NetBSD, OpenBSD, etc. + * if exact = false [default]) + * + * @param boolean $exact + * whether to check explicitly for FreeBSD or *BSD + * + * @return boolean + */ + public static function isFreeBSD($exact = false) + { + if (($exact && PHP_OS == 'FreeBSD') || (!$exact && stristr(PHP_OS, 'BSD'))) { + return true; + } + return false; + } + + /** + * removes the immutable flag for a file + * + * @param string $filename + * the file to set the flag for + * + * @return boolean + */ + public static function removeImmutable($filename = null) + { + FileDir::safe_exec(self::getImmutableFunction(true) . escapeshellarg($filename)); + } + public static function getFilesystemQuota() { // enabled at all? @@ -600,30 +637,32 @@ class FileDir } // Fetch all quota in the desired partition - $repquota = array(); - exec(Settings::Get('system.diskquota_repquota_path') . " " . $repquota_params . " " . escapeshellarg(Settings::Get('system.diskquota_customer_partition')), - $repquota); + $repquota = []; + exec( + Settings::Get('system.diskquota_repquota_path') . " " . $repquota_params . " " . escapeshellarg(Settings::Get('system.diskquota_customer_partition')), + $repquota + ); - $usedquota = array(); + $usedquota = []; foreach ($repquota as $tmpquota) { $matches = null; // Let's see if the line matches a quota - line if (preg_match($quota_line_regex, $tmpquota, $matches)) { // It matches - put it into an array with userid as key (for easy lookup later) - $usedquota[$matches[1]] = array( - 'block' => array( + $usedquota[$matches[1]] = [ + 'block' => [ 'used' => $matches[2], 'soft' => $matches[3], 'hard' => $matches[4], 'grace' => (self::isFreeBSD() ? '0' : $matches[5]) - ), - 'file' => array( + ], + 'file' => [ 'used' => $matches[6], 'soft' => $matches[7], 'hard' => $matches[8], 'grace' => (self::isFreeBSD() ? '0' : $matches[9]) - ) - ); + ] + ]; } } diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index b6d7d2df..f85c6a4e 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -1,4 +1,28 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor; use Froxlor\Database\Database; @@ -36,16 +60,6 @@ final class Froxlor return self::VERSION; } - /** - * return version + branding - * - * @return string - */ - public static function getFullVersion() - { - return self::VERSION . self::BRANDING; - } - /** * return version + branding and database-version * @@ -56,13 +70,23 @@ final class Froxlor return self::getFullVersion() . ' (' . self::DBVERSION . ')'; } + /** + * return version + branding + * + * @return string + */ + public static function getFullVersion() + { + return self::VERSION . self::BRANDING; + } + /** * Function hasUpdates * * checks if a given version is not equal the current one * * @param string $to_check - * version to check, if empty current version is used + * version to check, if empty current version is used * * @return bool true if version to check does not match, else false */ @@ -83,7 +107,7 @@ final class Froxlor * checks if a given database-version is not equal the current one * * @param int $to_check - * version to check, if empty current dbversion is used + * version to check, if empty current dbversion is used * * @return bool true if version to check does not match, else false */ @@ -104,7 +128,7 @@ final class Froxlor * checks if a given database-version is the current one * * @param int $to_check - * version to check + * version to check * * @return bool true if version to check matches, else false */ @@ -123,7 +147,7 @@ final class Froxlor * to the given value (no checks here!) * * @param string $new_version - * new-version + * new-version * * @return bool true on success, else false */ @@ -133,9 +157,9 @@ final class Froxlor $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_SETTINGS . "` SET `value` = :newversion WHERE `settinggroup` = 'panel' AND `varname` = 'db_version'"); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'newversion' => $new_version - )); + ]); Settings::Set('panel.db_version', $new_version); return true; } @@ -149,7 +173,7 @@ final class Froxlor * to the given value (no checks here!) * * @param string $new_version - * new-version + * new-version * * @return bool true on success, else false */ @@ -159,9 +183,9 @@ final class Froxlor $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_SETTINGS . "` SET `value` = :newversion WHERE `settinggroup` = 'panel' AND `varname` = 'version'"); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'newversion' => $new_version - )); + ]); Settings::Set('panel.version', $new_version); return true; } @@ -190,7 +214,7 @@ final class Froxlor * current one (and panel is froxlor) * * @param string $to_check - * version to check + * version to check * * @return bool true if version to check matches, else false */ @@ -210,7 +234,7 @@ final class Froxlor */ public static function genSessionId(int $length = 16) { - if(!isset($length) || intval($length) <= 8 ){ + if (!isset($length) || intval($length) <= 8) { $length = 16; } if (function_exists('random_bytes')) { @@ -236,7 +260,6 @@ final class Froxlor */ public static function versionCompare2($a, $b) { - // split version into pieces and remove trailing .0 $a = explode(".", $a); $b = explode(".", $b); @@ -259,7 +282,7 @@ final class Froxlor if ($aVal > $b[$depth]) { return 1; // A > B } elseif ($aVal < $b[$depth]) { - return - 1; // B > A + return -1; // B > A } // an equal result is inconclusive at this point } else { @@ -269,7 +292,7 @@ final class Froxlor } // at this point, we know that to the depth that A and B extend to, they are equivalent. // either the loop ended because A is shorter than B, or both are equal. - return (count($a) < count($b)) ? - 1 : 0; + return (count($a) < count($b)) ? -1 : 0; } private static function parseVersionArray(&$arr = null) @@ -281,12 +304,12 @@ final class Froxlor if (stripos($x[1], 'rc') !== false) { $arr[] = '-1'; $arr[] = '2'; // rc > dev > svn - // number of rc + // number of rc $arr[] = substr($x[1], 2); } elseif (stripos($x[1], 'dev') !== false) { $arr[] = '-1'; $arr[] = '1'; // svn < dev < rc - // number of dev + // number of dev $arr[] = substr($x[1], 3); } elseif (stripos($x[1], 'svn') !== false) { // -svn version are deprecated diff --git a/lib/Froxlor/FroxlorLogger.php b/lib/Froxlor/FroxlorLogger.php index d64e8550..959fb7ca 100644 --- a/lib/Froxlor/FroxlorLogger.php +++ b/lib/Froxlor/FroxlorLogger.php @@ -1,10 +1,34 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor; -use Monolog\Logger; +use Froxlor\System\MysqlHandler; use Monolog\Handler\StreamHandler; use Monolog\Handler\SyslogHandler; -use Froxlor\System\MysqlHandler; +use Monolog\Logger; /** * Class FroxlorLogger @@ -12,34 +36,36 @@ use Froxlor\System\MysqlHandler; class FroxlorLogger { + const USR_ACTION = '10'; + const RES_ACTION = '20'; + const ADM_ACTION = '30'; + const CRON_ACTION = '40'; + const LOGIN_ACTION = '50'; + const LOG_ERROR = '99'; /** * current \Monolog\Logger object * - * @var \Monolog\Logger + * @var Logger */ private static $ml = null; - /** * LogTypes Array * * @var array */ private static $logtypes = null; - /** * whether to output log-messages to STDOUT (cron) * * @var bool */ private static $crondebug_flag = false; - /** * user info of logged in user * * @var array */ - private static $userinfo = array(); - + private static $userinfo = []; /** * whether the logger object has already been initialized * @@ -47,26 +73,14 @@ class FroxlorLogger */ private static $is_initialized = false; - const USR_ACTION = '10'; - - const RES_ACTION = '20'; - - const ADM_ACTION = '30'; - - const CRON_ACTION = '40'; - - const LOGIN_ACTION = '50'; - - const LOG_ERROR = '99'; - /** * Class constructor. */ - protected function __construct($userinfo = array()) + protected function __construct($userinfo = []) { $this->initMonolog(); self::$userinfo = $userinfo; - self::$logtypes = array(); + self::$logtypes = []; if ((Settings::Get('logger.logtypes') == null || Settings::Get('logger.logtypes') == '') && (Settings::Get('logger.enabled') !== null && Settings::Get('logger.enabled'))) { self::$logtypes[0] = 'syslog'; @@ -81,7 +95,6 @@ class FroxlorLogger if (self::$is_initialized == false) { foreach (self::$logtypes as $logger) { - switch ($logger) { case 'syslog': self::$ml->pushHandler(new SyslogHandler('froxlor', LOG_USER, Logger::DEBUG)); @@ -90,7 +103,7 @@ class FroxlorLogger $logger_logfile = Settings::Get('logger.logfile'); // is_writable needs an existing file to check if it's actually writable @touch($logger_logfile); - if (empty($logger_logfile) || ! is_writable($logger_logfile)) { + if (empty($logger_logfile) || !is_writable($logger_logfile)) { Settings::Set('logger.logfile', '/tmp/froxlor.log'); } self::$ml->pushHandler(new StreamHandler($logger_logfile, Logger::DEBUG)); @@ -104,27 +117,10 @@ class FroxlorLogger } } - /** - * return FroxlorLogger instance - * - * @param array $userinfo - * - * @return FroxlorLogger - */ - public static function getInstanceOf($userinfo = array()) - { - if (empty($userinfo)) { - $userinfo = array( - 'loginname' => 'system' - ); - } - return new FroxlorLogger($userinfo); - } - /** * initiate monolog object * - * @return \Monolog\Logger + * @return Logger */ private function initMonolog() { @@ -135,6 +131,23 @@ class FroxlorLogger return self::$ml; } + /** + * return FroxlorLogger instance + * + * @param array $userinfo + * + * @return FroxlorLogger + */ + public static function getInstanceOf($userinfo = []) + { + if (empty($userinfo)) { + $userinfo = [ + 'loginname' => 'system' + ]; + } + return new FroxlorLogger($userinfo); + } + /** * logs a given text to all enabled logger-facilities * @@ -142,10 +155,10 @@ class FroxlorLogger * @param int $type * @param string $text */ - public function logAction($action = \Froxlor\FroxlorLogger::USR_ACTION, $type = LOG_NOTICE, $text = null) + public function logAction($action = FroxlorLogger::USR_ACTION, $type = LOG_NOTICE, $text = null) { // not logging normal stuff if not set to "paranoid" logging - if (! self::$crondebug_flag && Settings::Get('logger.severity') == '1' && $type > LOG_NOTICE) { + if (!self::$crondebug_flag && Settings::Get('logger.severity') == '1' && $type > LOG_NOTICE) { return; } @@ -153,20 +166,20 @@ class FroxlorLogger $this->initMonolog(); } - if (self::$crondebug_flag || ($action == \Froxlor\FroxlorLogger::CRON_ACTION && $type <= LOG_WARNING)) { + if (self::$crondebug_flag || ($action == FroxlorLogger::CRON_ACTION && $type <= LOG_WARNING)) { echo "[" . $this->getLogLevelDesc($type) . "] " . $text . PHP_EOL; } // warnings, errors and critical messages WILL be logged - if (Settings::Get('logger.log_cron') == '0' && $action == \Froxlor\FroxlorLogger::CRON_ACTION && $type > LOG_WARNING) { + if (Settings::Get('logger.log_cron') == '0' && $action == FroxlorLogger::CRON_ACTION && $type > LOG_WARNING) { return; } - $logExtra = array( + $logExtra = [ 'source' => $this->getActionTypeDesc($action), 'action' => $action, 'user' => self::$userinfo['loginname'] - ); + ]; switch ($type) { case LOG_DEBUG: @@ -189,36 +202,6 @@ class FroxlorLogger } } - /** - * Set whether to log cron-runs - * - * @param bool $_cronlog - * - * @return boolean - */ - public function setCronLog($_cronlog = 0) - { - $_cronlog = (int) $_cronlog; - - if ($_cronlog < 0 || $_cronlog > 2) { - $_cronlog = 0; - } - Settings::Set('logger.log_cron', $_cronlog); - return $_cronlog; - } - - /** - * setter for crondebug-flag - * - * @param bool $_flag - * - * @return void - */ - public function setCronDebugFlag($_flag = false) - { - self::$crondebug_flag = (bool) $_flag; - } - public function getLogLevelDesc($type) { switch ($type) { @@ -250,19 +233,19 @@ class FroxlorLogger private function getActionTypeDesc($action) { switch ($action) { - case \Froxlor\FroxlorLogger::USR_ACTION: + case FroxlorLogger::USR_ACTION: $_action = 'user'; break; - case \Froxlor\FroxlorLogger::ADM_ACTION: + case FroxlorLogger::ADM_ACTION: $_action = 'admin'; break; - case \Froxlor\FroxlorLogger::RES_ACTION: + case FroxlorLogger::RES_ACTION: $_action = 'reseller'; break; - case \Froxlor\FroxlorLogger::CRON_ACTION: + case FroxlorLogger::CRON_ACTION: $_action = 'cron'; break; - case \Froxlor\FroxlorLogger::LOGIN_ACTION: + case FroxlorLogger::LOGIN_ACTION: $_action = 'login'; break; default: @@ -271,4 +254,34 @@ class FroxlorLogger } return $_action; } + + /** + * Set whether to log cron-runs + * + * @param bool $_cronlog + * + * @return boolean + */ + public function setCronLog($_cronlog = 0) + { + $_cronlog = (int)$_cronlog; + + if ($_cronlog < 0 || $_cronlog > 2) { + $_cronlog = 0; + } + Settings::Set('logger.log_cron', $_cronlog); + return $_cronlog; + } + + /** + * setter for crondebug-flag + * + * @param bool $_flag + * + * @return void + */ + public function setCronDebugFlag($_flag = false) + { + self::$crondebug_flag = (bool)$_flag; + } } diff --git a/lib/Froxlor/FroxlorTwoFactorAuth.php b/lib/Froxlor/FroxlorTwoFactorAuth.php index 7a0f5d01..ea85360b 100644 --- a/lib/Froxlor/FroxlorTwoFactorAuth.php +++ b/lib/Froxlor/FroxlorTwoFactorAuth.php @@ -1,21 +1,32 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ -class FroxlorTwoFactorAuth extends \RobThree\Auth\TwoFactorAuth + +namespace Froxlor; + +use RobThree\Auth\TwoFactorAuth; + +class FroxlorTwoFactorAuth extends TwoFactorAuth { } diff --git a/lib/Froxlor/Http/Directory.php b/lib/Froxlor/Http/Directory.php index a27d2854..1777eae3 100644 --- a/lib/Froxlor/Http/Directory.php +++ b/lib/Froxlor/Http/Directory.php @@ -1,32 +1,36 @@ - * @author Froxlor team (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.33 + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\Http; + use Froxlor\Database\Database; use Froxlor\FileDir; /** * Class frxDirectory handles directory actions and gives information * about a given directory in connections with its usage in froxlor - * - * @author Michael Kaufmann (d00p) - * */ class Directory { @@ -56,9 +60,9 @@ class Directory $uo_stmt = Database::prepare(" SELECT COUNT(`id`) as `usropts` FROM `" . TABLE_PANEL_HTACCESS . "` WHERE `path` = :dir "); - $uo_res = Database::pexecute_first($uo_stmt, array( + $uo_res = Database::pexecute_first($uo_stmt, [ 'dir' => FileDir::makeCorrectDir($this->dir) - )); + ]); if ($uo_res != false && isset($uo_res['usropts'])) { return $uo_res['usropts'] > 0; } @@ -73,9 +77,9 @@ class Directory $up_stmt = Database::prepare(" SELECT COUNT(`id`) as `usrprot` FROM `" . TABLE_PANEL_HTPASSWDS . "` WHERE `path` = :dir "); - $up_res = Database::pexecute_first($up_stmt, array( + $up_res = Database::pexecute_first($up_stmt, [ 'dir' => FileDir::makeCorrectDir($this->dir) - )); + ]); if ($up_res != false && isset($up_res['usrprot'])) { return $up_res['usrprot'] > 0; } @@ -87,7 +91,7 @@ class Directory * or should rather be used as a single file * * @param bool $ifexists - * also check whether file/dir exists + * also check whether file/dir exists * * @return bool true if usable as dir, false otherwise */ @@ -105,8 +109,8 @@ class Directory $returnval = false; } } else { - if (! $ifexists) { - if (substr($this->dir, - 1) == '/') { + if (!$ifexists) { + if (substr($this->dir, -1) == '/') { $returnval = true; } else { $returnval = false; diff --git a/lib/Froxlor/Http/HttpClient.php b/lib/Froxlor/Http/HttpClient.php index 59e935f2..f6a66c9d 100644 --- a/lib/Froxlor/Http/HttpClient.php +++ b/lib/Froxlor/Http/HttpClient.php @@ -1,21 +1,46 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\Http; use Exception; +use Froxlor\Froxlor; class HttpClient { - /** - * Executes simple GET request - * - * @return bool|string - * @throws Exception - */ + /** + * Executes simple GET request + * + * @return bool|string + * @throws Exception + */ public static function urlGet(string $url, bool $follow_location = true, int $timeout = 10) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_USERAGENT, 'Froxlor/' . \Froxlor\Froxlor::getVersion()); + curl_setopt($ch, CURLOPT_USERAGENT, 'Froxlor/' . Froxlor::getVersion()); if ($follow_location) { curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); } @@ -31,17 +56,17 @@ class HttpClient return $output; } - /** - * Downloads and stores a file from an url - * - * @throws Exception - */ + /** + * Downloads and stores a file from an url + * + * @throws Exception + */ public static function fileGet(string $url, string $target) - { + { $fh = fopen($target, 'w'); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_USERAGENT, 'Froxlor/' . \Froxlor\Froxlor::getVersion()); + curl_setopt($ch, CURLOPT_USERAGENT, 'Froxlor/' . Froxlor::getVersion()); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_TIMEOUT, 50); // give curl the file pointer so that it can write to it diff --git a/lib/Froxlor/Http/PhpConfig.php b/lib/Froxlor/Http/PhpConfig.php index ff7550ea..0ff5bb26 100644 --- a/lib/Froxlor/Http/PhpConfig.php +++ b/lib/Froxlor/Http/PhpConfig.php @@ -1,7 +1,32 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\Http; use Froxlor\Database\Database; +use PDO; class PhpConfig { @@ -14,18 +39,18 @@ class PhpConfig */ public static function getPhpConfigs() { - $configs_array = array(); + $configs_array = []; // check if table exists because this is used in a preconfig // where the tables possibly does not exist yet $results = Database::query("SHOW TABLES LIKE '" . TABLE_PANEL_PHPCONFIGS . "'"); - if (! $results) { + if (!$results) { $configs_array[1] = 'Default php.ini'; } else { // get all configs $result_stmt = Database::query("SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "`"); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { - if (! isset($configs_array[$row['id']]) && ! in_array($row['id'], $configs_array)) { + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + if (!isset($configs_array[$row['id']]) && !in_array($row['id'], $configs_array)) { $configs_array[$row['id']] = html_entity_decode($row['description']); } } diff --git a/lib/Froxlor/Http/Statistics.php b/lib/Froxlor/Http/Statistics.php index 85b63e19..48cf7e77 100644 --- a/lib/Froxlor/Http/Statistics.php +++ b/lib/Froxlor/Http/Statistics.php @@ -1,6 +1,32 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\Http; +use Froxlor\FileDir; +use Froxlor\Froxlor; use Froxlor\Settings; class Statistics @@ -11,34 +37,33 @@ class Statistics * Modified by Berend Dekens to allow custom configurations. * * @param - * logFile + * logFile * @param - * siteDomain + * siteDomain * @param - * hostAliases + * hostAliases * @return null */ - public static function createAWStatsConf($logFile, $siteDomain, $hostAliases, $customerDocroot, $awstats_params = array()) + public static function createAWStatsConf($logFile, $siteDomain, $hostAliases, $customerDocroot, $awstats_params = []) { - // Generation header $header = "## GENERATED BY FROXLOR\n"; $header2 = "## Do not remove the line above! This tells Froxlor to update this configuration\n## If you wish to manually change this configuration file, remove the first line to make sure Froxlor won't rebuild this file\n## Generated for domain {SITE_DOMAIN} on " . date('l dS \of F Y h:i:s A') . "\n"; - $awstats_dir = \Froxlor\FileDir::makeCorrectDir($customerDocroot . '/awstats/' . $siteDomain . '/'); - if (! is_dir($awstats_dir)) { - \Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg($awstats_dir)); + $awstats_dir = FileDir::makeCorrectDir($customerDocroot . '/awstats/' . $siteDomain . '/'); + if (!is_dir($awstats_dir)) { + FileDir::safe_exec('mkdir -p ' . escapeshellarg($awstats_dir)); } // chown created folder, #258 self::makeChownWithNewStats($awstats_params); // weird but could happen... - if (! is_dir(Settings::Get('system.awstats_conf'))) { - \Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg(Settings::Get('system.awstats_conf'))); + if (!is_dir(Settings::Get('system.awstats_conf'))) { + FileDir::safe_exec('mkdir -p ' . escapeshellarg(Settings::Get('system.awstats_conf'))); } $logformat = Settings::Get('system.awstats_logformat'); - if (! is_numeric($logformat)) { + if (!is_numeric($logformat)) { // if LogFormat is NOT numeric (e.g. 1,2,3,4), we quote it. // 1-4 are pre-defined formats by awstats which must not be quoted to work properly. So if // it is not a integer, it is something customized and we simply quote it. @@ -47,27 +72,27 @@ class Statistics } // These are the variables we will replace - $regex = array( + $regex = [ '/\{LOG_FILE\}/', '/\{SITE_DOMAIN\}/', '/\{HOST_ALIASES\}/', '/\{CUSTOMER_DOCROOT\}/', '/\{AWSTATS_CONF\}/', '/\{AWSTATS_LOGFORMAT\}/' - ); - $replace = array( - \Froxlor\FileDir::makeCorrectFile($logFile), + ]; + $replace = [ + FileDir::makeCorrectFile($logFile), $siteDomain, $hostAliases, $awstats_dir, - \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.awstats_conf')), + FileDir::makeCorrectDir(Settings::Get('system.awstats_conf')), $logformat - ); + ]; // File names - $domain_file = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.awstats_conf') . '/awstats.' . $siteDomain . '.conf'); - $model_file = \Froxlor\Froxlor::getInstallDir() . '/templates/misc/awstats/awstats.froxlor.model.conf'; - $model_file = \Froxlor\FileDir::makeCorrectFile($model_file); + $domain_file = FileDir::makeCorrectFile(Settings::Get('system.awstats_conf') . '/awstats.' . $siteDomain . '.conf'); + $model_file = Froxlor::getInstallDir() . '/templates/misc/awstats/awstats.froxlor.model.conf'; + $model_file = FileDir::makeCorrectFile($model_file); // Test if the file exists if (file_exists($domain_file)) { @@ -92,7 +117,7 @@ class Statistics // Write the configuration file while (($line = fgets($awstats_model_conf, 4096)) !== false) { - if (! preg_match('/^#/', $line) && trim($line) != '') { + if (!preg_match('/^#/', $line) && trim($line) != '') { fwrite($awstats_domain_conf, preg_replace($regex, $replace, $line)); } } @@ -107,13 +132,12 @@ class Statistics * is used - the customers name, #258 * * @param array $row - * array if panel_customers - * + * array if panel_customers + * * @return void */ public static function makeChownWithNewStats($row) { - // get correct user if ((Settings::Get('system.mod_fcgid') == '1' || Settings::Get('phpfpm.enabled') == '1') && isset($row['deactivated']) && $row['deactivated'] == '0') { $user = $row['loginname']; @@ -134,7 +158,7 @@ class Statistics // only run chown if directory exists if (file_exists($dir)) { // run chown - \Froxlor\FileDir::safe_exec('chown -R ' . escapeshellarg($user) . ':' . escapeshellarg($group) . ' ' . escapeshellarg(\Froxlor\FileDir::makeCorrectDir($dir))); + FileDir::safe_exec('chown -R ' . escapeshellarg($user) . ':' . escapeshellarg($group) . ' ' . escapeshellarg(FileDir::makeCorrectDir($dir))); } } } diff --git a/lib/Froxlor/Idna/IdnaWrapper.php b/lib/Froxlor/Idna/IdnaWrapper.php index 7d1830d3..fb192b08 100644 --- a/lib/Froxlor/Idna/IdnaWrapper.php +++ b/lib/Froxlor/Idna/IdnaWrapper.php @@ -1,27 +1,37 @@ (2003-2009) - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes - * + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ +namespace Froxlor\Idna; + +use Algo26\IdnaConvert\IdnaConvert; +use InvalidArgumentException; + /** * Class for wrapping a specific idna conversion class and offering a standard interface * - * @package Functions + * @author Michael Duergner (2003-2009) */ class IdnaWrapper { @@ -40,16 +50,16 @@ class IdnaWrapper public function __construct() { // Instantiate it - $this->idna_converter = new \Algo26\IdnaConvert\IdnaConvert(); + $this->idna_converter = new IdnaConvert(); } /** * Encode a domain name, a email address or a list of one of both. * * @param - * string May be either a single domain name, e single email address or a list of one - * separated either by ',', ';' or ' '. - * + * string May be either a single domain name, e single email address or a list of one + * separated either by ',', ';' or ' '. + * * @return string Returns either a single domain name, a single email address or a list of one of * both separated by the same string as the input. */ @@ -58,7 +68,7 @@ class IdnaWrapper $to_encode = $this->isUtf8($to_encode) ? $to_encode : utf8_encode($to_encode); try { return $this->idna_converter->encode($to_encode); - } catch (\InvalidArgumentException $iae) { + } catch (InvalidArgumentException $iae) { if ($iae->getCode() == 100) { return $to_encode; } @@ -66,21 +76,6 @@ class IdnaWrapper } } - /** - * Decode a domain name, a email address or a list of one of both. - * - * @param - * string May be either a single domain name, e single email address or a list of one - * separated either by ',', ';' or ' '. - * - * @return string Returns either a single domain name, a single email address or a list of one of - * both separated by the same string as the input. - */ - public function decode($to_decode) - { - return $this->idna_converter->decode($to_decode); - } - /** * check whether a string is utf-8 encoded or not * @@ -97,7 +92,7 @@ class IdnaWrapper return false; } $strlen = strlen($string); - for ($i = 0; $i < $strlen; $i ++) { + for ($i = 0; $i < $strlen; $i++) { $ord = ord($string[$i]); if ($ord < 0x80) { continue; // 0bbbbbbb @@ -112,8 +107,8 @@ class IdnaWrapper return false; } // $n Folgebytes? // 10bbbbbb - for ($c = 0; $c < $n; $c ++) { - if (++ $i === $strlen || (ord($string[$i]) & 0xC0) !== 0x80) { + for ($c = 0; $c < $n; $c++) { + if (++$i === $strlen || (ord($string[$i]) & 0xC0) !== 0x80) { // ungültiges UTF-8-Zeichen return false; } @@ -122,4 +117,19 @@ class IdnaWrapper // kein ungültiges UTF-8-Zeichen gefunden return true; } + + /** + * Decode a domain name, a email address or a list of one of both. + * + * @param + * string May be either a single domain name, e single email address or a list of one + * separated either by ',', ';' or ' '. + * + * @return string Returns either a single domain name, a single email address or a list of one of + * both separated by the same string as the input. + */ + public function decode($to_decode) + { + return $this->idna_converter->decode($to_decode); + } } diff --git a/lib/Froxlor/Install/Install.php b/lib/Froxlor/Install/Install.php index 3d769d0a..38f5afda 100644 --- a/lib/Froxlor/Install/Install.php +++ b/lib/Froxlor/Install/Install.php @@ -11,21 +11,22 @@ * * 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 + * 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 - * http://files.froxlor.org/misc/COPYING.txt + * https://files.froxlor.org/misc/COPYING.txt * * @copyright the authors * @author Froxlor team - * @license http://files.froxlor.org/misc/COPYING.txt GPLv2 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ namespace Froxlor\Install; use Froxlor\UI\Panel\UI; +use Froxlor\UI\Request; class Install { @@ -39,7 +40,7 @@ class Install public function __construct() { - $this->step = \Froxlor\UI\Request::get('step'); + $this->step = Request::get('step'); $this->phpVersion = phpversion(); $this->loadedExtensions = get_loaded_extensions(); @@ -51,29 +52,21 @@ class Install { // check for required extensions foreach ($this->requiredExtensions as $requiredExtension) { - if (in_array($requiredExtension, $this->loadedExtensions)) continue; + if (in_array($requiredExtension, $this->loadedExtensions)) { + continue; + } $this->criticals['missing_extensions'][] = $requiredExtension; } // check for suggested extensions foreach ($this->suggestedExtensions as $suggestedExtension) { - if (in_array($suggestedExtension, $this->loadedExtensions)) continue; + if (in_array($suggestedExtension, $this->loadedExtensions)) { + continue; + } $this->suggestions['missing_extensions'][] = $suggestedExtension; } } - public function getPreflightText(): string - { - if (version_compare($this->requiredVersion, PHP_VERSION, "<")) { - $text = 'Your system is running with PHP ' . $this->phpVersion; - } else { - $text = 'Your system is running a lower version than PHP ' . $this->requiredVersion; - $this->criticals[] = 'Update your current PHP Version from ' . $this->phpVersion . ' to ' . $this->requiredVersion . ' or higher'; - } - - return $text; - } - public function handle() { $formfield = require dirname(__DIR__, 3) . '/lib/formfields/install/formfield.install.php'; @@ -106,4 +99,16 @@ class Install // output view UI::twigOutputBuffer(); } + + public function getPreflightText(): string + { + if (version_compare($this->requiredVersion, PHP_VERSION, "<")) { + $text = 'Your system is running with PHP ' . $this->phpVersion; + } else { + $text = 'Your system is running a lower version than PHP ' . $this->requiredVersion; + $this->criticals[] = 'Update your current PHP Version from ' . $this->phpVersion . ' to ' . $this->requiredVersion . ' or higher'; + } + + return $text; + } } diff --git a/lib/Froxlor/Install/Update.php b/lib/Froxlor/Install/Update.php index 3a259835..19ad9fb7 100644 --- a/lib/Froxlor/Install/Update.php +++ b/lib/Froxlor/Install/Update.php @@ -11,16 +11,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 + * 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 - * http://files.froxlor.org/misc/COPYING.txt + * https://files.froxlor.org/misc/COPYING.txt * * @copyright the authors * @author Froxlor team - * @license http://files.froxlor.org/misc/COPYING.txt GPLv2 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ namespace Froxlor\Install; @@ -37,7 +37,7 @@ class Update * * @param string $task * @param bool $needs_status (if false, a linebreak will be added) - * + * * @return void */ public static function showUpdateStep($task = null, $needs_status = true) @@ -64,7 +64,7 @@ class Update * @param int $status (0 = success, 1 = warning, 2 = failure) * @param string $message * @param string $additional_info - * + * * @return string formatted output and log-entry */ public static function lastStepStatus(int $status = -1, string $message = '', string $additional_info = '') @@ -75,7 +75,6 @@ class Update $update_tasks[$task_counter]['result_desc'] = $additional_info ?? ''; switch ($status) { - case 0: break; case 1: diff --git a/lib/Froxlor/Language.php b/lib/Froxlor/Language.php index 62b0c8f7..794a8c2e 100644 --- a/lib/Froxlor/Language.php +++ b/lib/Froxlor/Language.php @@ -11,16 +11,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 + * 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 - * http://files.froxlor.org/misc/COPYING.txt + * https://files.froxlor.org/misc/COPYING.txt * * @copyright the authors * @author Froxlor team - * @license http://files.froxlor.org/misc/COPYING.txt GPLv2 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ namespace Froxlor; @@ -34,6 +34,46 @@ class Language protected static string $defaultLanguage = 'en'; protected static ?string $requestedLanguage = null; + /** + * @return array + * @fixme iso seems to be not used in froxlor? + */ + public static function getLanguages(): array + { + $languages = []; + $directory = dirname(__DIR__, 2) . '/lng'; + + foreach (array_diff(scandir($directory), ['..', '.', 'index.html']) as $language) { + $iso = explode('.', $language)[0]; + $languages[$iso] = self::getTranslation('languages.' . $iso); + } + + return $languages; + } + + public static function getTranslation(string $identifier, array $arguments = []) + { + // initialize + if (is_null(self::$lng)) { + // load fallback language + self::$lng = self::loadLanguage(self::$defaultLanguage); + + // load user requested language + if (self::$requestedLanguage) { + self::$lng = array_merge(self::$lng, self::loadLanguage(self::$requestedLanguage)); + } + + // load fallback from browser if nothing requested + $iso = trim(substr(strtok(strtok($_SERVER['HTTP_ACCEPT_LANGUAGE'], ','), ';'), 0, 5)); + if (!self::$requestedLanguage && strlen($iso) == 2 && $iso !== self::$defaultLanguage) { + self::$lng = array_merge(self::$lng, self::loadLanguage($iso)); + } + } + + // search by identifier + return vsprintf(self::$lng[$identifier] ?? $identifier, $arguments); + } + /** * @TODO: Possible iso: de, de-DE, de-AT (fallback to de) * @@ -65,46 +105,6 @@ class Language return $result; } - /** - * @return array - * @fixme iso seems to be not used in froxlor? - */ - public static function getLanguages(): array - { - $languages = []; - $directory = dirname(__DIR__, 2) . '/lng'; - - foreach (array_diff(scandir($directory), array('..', '.', 'index.html')) as $language) { - $iso = explode('.', $language)[0]; - $languages[$iso] = self::getTranslation('languages.' . $iso); - } - - return $languages; - } - - public static function getTranslation(string $identifier, array $arguments = []) - { - // initialize - if (is_null(self::$lng)) { - // load fallback language - self::$lng = self::loadLanguage(self::$defaultLanguage); - - // load user requested language - if (self::$requestedLanguage) { - self::$lng = array_merge(self::$lng, self::loadLanguage(self::$requestedLanguage)); - } - - // load fallback from browser if nothing requested - $iso = trim(substr(strtok(strtok($_SERVER['HTTP_ACCEPT_LANGUAGE'], ','), ';'), 0, 5)); - if (!self::$requestedLanguage && strlen($iso) == 2 && $iso !== self::$defaultLanguage) { - self::$lng = array_merge(self::$lng, self::loadLanguage($iso)); - } - } - - // search by identifier - return vsprintf(self::$lng[$identifier] ?? $identifier, $arguments); - } - public static function setDefaultLanguage(string $string) { self::$defaultLanguage = $string; diff --git a/lib/Froxlor/MailLogParser.php b/lib/Froxlor/MailLogParser.php index 4a9ef696..2df0d746 100644 --- a/lib/Froxlor/MailLogParser.php +++ b/lib/Froxlor/MailLogParser.php @@ -1,45 +1,50 @@ - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Cron - * - * @since 0.9.32 - * + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor; + +use Exception; +use Froxlor\Database\Database; +use PDO; + class MailLogParser { - private $startTime; - - private $domainTraffic = array(); - - private $myDomains = array(); - - private $mails = array(); + private $domainTraffic = []; + private $myDomains = []; + private $mails = []; /** * constructor * * @param - * string logFile + * string logFile * @param - * int startTime + * int startTime * @param - * string logFileExim + * string logFileExim */ public function __construct($startTime = 0) { @@ -47,8 +52,8 @@ class MailLogParser // Get all domains from Database $stmt = Database::prepare("SELECT domain FROM `" . TABLE_PANEL_DOMAINS . "`"); - Database::pexecute($stmt, array()); - while ($domain_row = $stmt->fetch(\PDO::FETCH_ASSOC)) { + Database::pexecute($stmt, []); + while ($domain_row = $stmt->fetch(PDO::FETCH_ASSOC)) { $this->myDomains[] = $domain_row["domain"]; } @@ -75,27 +80,27 @@ class MailLogParser * parses the traffic from a postfix logfile * * @param string $logFile - * logFile + * logFile */ private function parsePostfixLog($logFile) { // Check if file exists - if (! file_exists($logFile)) { + if (!file_exists($logFile)) { return false; } // Open the log file try { $file_handle = fopen($logFile, "r"); - if (! $file_handle) { - throw new \Exception("Could not open the file!"); + if (!$file_handle) { + throw new Exception("Could not open the file!"); } - } catch (\Exception $e) { + } catch (Exception $e) { echo "Error (File: " . $e->getFile() . ", line " . $e->getLine() . "): " . $e->getMessage(); return false; } - while (! feof($file_handle)) { + while (!feof($file_handle)) { unset($matches); $line = fgets($file_handle); @@ -103,10 +108,10 @@ class MailLogParser if ($this->startTime < $timestamp) { if (preg_match("/postfix\/qmgr.*(?::|\])\s([A-Z\d]+).*from=?, size=(\d+),/", $line, $matches)) { // Postfix from - $this->mails[$matches[1]] = array( + $this->mails[$matches[1]] = [ "domainFrom" => strtolower($matches[2]), "size" => $matches[3] - ); + ]; } elseif (preg_match("/postfix\/(?:pipe|smtp).*(?::|\])\s([A-Z\d]+).*to=?,/", $line, $matches)) { // Postfix to if (array_key_exists($matches[1], $this->mails)) { @@ -134,32 +139,78 @@ class MailLogParser return true; } + /** + * getLogTimestamp + * + * @param + * string line + * return int + */ + private function getLogTimestamp($line) + { + $matches = null; + if (preg_match("/((?:[A-Z]{3}\s{1,2}\d{1,2}|\d{4}-\d{2}-\d{2}) \d{2}:\d{2}:\d{2})/i", $line, $matches)) { + $timestamp = strtotime($matches[1]); + if ($timestamp > ($this->startTime + 60 * 60 * 24)) { + return strtotime($matches[1] . " -1 year"); + } else { + return strtotime($matches[1]); + } + } else { + return 0; + } + } + + /** + * _addDomainTraffic + * adds the traffic to the domain array if we own the domain + * + * @param + * string domain + * @param + * int traffic + */ + private function addDomainTraffic($domain, $traffic, $timestamp) + { + $date = date("Y-m-d", $timestamp); + if (in_array($domain, $this->myDomains)) { + if (array_key_exists($domain, $this->domainTraffic) && array_key_exists($date, $this->domainTraffic[$domain])) { + $this->domainTraffic[$domain][$date] += (int)$traffic; + } else { + if (!array_key_exists($domain, $this->domainTraffic)) { + $this->domainTraffic[$domain] = []; + } + $this->domainTraffic[$domain][$date] = (int)$traffic; + } + } + } + /** * parseExim4Log * parses the smtp traffic from a exim4 logfile * * @param string $logFile - * logFile + * logFile */ private function parseExim4Log($logFile) { // Check if file exists - if (! file_exists($logFile)) { + if (!file_exists($logFile)) { return false; } // Open the log file try { $file_handle = fopen($logFile, "r"); - if (! $file_handle) { - throw new \Exception("Could not open the file!"); + if (!$file_handle) { + throw new Exception("Could not open the file!"); } - } catch (\Exception $e) { + } catch (Exception $e) { echo "Error (File: " . $e->getFile() . ", line " . $e->getLine() . "): " . $e->getMessage(); return false; } - while (! feof($file_handle)) { + while (!feof($file_handle)) { unset($matches); $line = fgets($file_handle); @@ -183,27 +234,27 @@ class MailLogParser * parses the dovecot imap/pop3 traffic from logfile * * @param string $logFile - * logFile + * logFile */ private function parseDovecotLog($logFile) { // Check if file exists - if (! file_exists($logFile)) { + if (!file_exists($logFile)) { return false; } // Open the log file try { $file_handle = fopen($logFile, "r"); - if (! $file_handle) { - throw new \Exception("Could not open the file!"); + if (!$file_handle) { + throw new Exception("Could not open the file!"); } - } catch (\Exception $e) { + } catch (Exception $e) { echo "Error (File: " . $e->getFile() . ", line " . $e->getLine() . "): " . $e->getMessage(); return false; } - while (! feof($file_handle)) { + while (!feof($file_handle)) { unset($matches); $line = fgets($file_handle); @@ -211,10 +262,10 @@ class MailLogParser if ($this->startTime < $timestamp) { if (preg_match("/dovecot.*(?::|\]) imap\(.*@([a-z0-9\.\-]+)\)(<\d+><[a-z0-9+\/=]+>)?:.*(?:in=(\d+) out=(\d+)|bytes=(\d+)\/(\d+))/i", $line, $matches)) { // Dovecot IMAP - $this->addDomainTraffic($matches[1], (int) $matches[3] + (int) $matches[4], $timestamp); + $this->addDomainTraffic($matches[1], (int)$matches[3] + (int)$matches[4], $timestamp); } elseif (preg_match("/dovecot.*(?::|\]) pop3\(.*@([a-z0-9\.\-]+)\)(<\d+><[a-z0-9+\/=]+>)?:.*in=(\d+).*out=(\d+)/i", $line, $matches)) { // Dovecot POP3 - $this->addDomainTraffic($matches[1], (int) $matches[3] + (int) $matches[4], $timestamp); + $this->addDomainTraffic($matches[1], (int)$matches[3] + (int)$matches[4], $timestamp); } } } @@ -227,27 +278,27 @@ class MailLogParser * parses the dovecot imap/pop3 traffic from logfile * * @param string $logFile - * logFile + * logFile */ private function parseCourierLog($logFile) { // Check if file exists - if (! file_exists($logFile)) { + if (!file_exists($logFile)) { return false; } // Open the log file try { $file_handle = fopen($logFile, "r"); - if (! $file_handle) { - throw new \Exception("Could not open the file!"); + if (!$file_handle) { + throw new Exception("Could not open the file!"); } - } catch (\Exception $e) { + } catch (Exception $e) { echo "Error (File: " . $e->getFile() . ", line " . $e->getLine() . "): " . $e->getMessage(); return false; } - while (! feof($file_handle)) { + while (!feof($file_handle)) { unset($matches); $line = fgets($file_handle); @@ -255,7 +306,7 @@ class MailLogParser if ($this->startTime < $timestamp) { if (preg_match("/(?:imapd|pop3d)(?:-ssl)?.*(?::|\]).*user=.*@([a-z0-9\.\-]+),.*rcvd=(\d+), sent=(\d+),/i", $line, $matches)) { // Courier IMAP & POP3 - $this->addDomainTraffic($matches[1], (int) $matches[2] + (int) $matches[3], $timestamp); + $this->addDomainTraffic($matches[1], (int)$matches[2] + (int)$matches[3], $timestamp); } } } @@ -263,59 +314,13 @@ class MailLogParser return true; } - /** - * _addDomainTraffic - * adds the traffic to the domain array if we own the domain - * - * @param - * string domain - * @param - * int traffic - */ - private function addDomainTraffic($domain, $traffic, $timestamp) - { - $date = date("Y-m-d", $timestamp); - if (in_array($domain, $this->myDomains)) { - if (array_key_exists($domain, $this->domainTraffic) && array_key_exists($date, $this->domainTraffic[$domain])) { - $this->domainTraffic[$domain][$date] += (int) $traffic; - } else { - if (! array_key_exists($domain, $this->domainTraffic)) { - $this->domainTraffic[$domain] = array(); - } - $this->domainTraffic[$domain][$date] = (int) $traffic; - } - } - } - - /** - * getLogTimestamp - * - * @param - * string line - * return int - */ - private function getLogTimestamp($line) - { - $matches = null; - if (preg_match("/((?:[A-Z]{3}\s{1,2}\d{1,2}|\d{4}-\d{2}-\d{2}) \d{2}:\d{2}:\d{2})/i", $line, $matches)) { - $timestamp = strtotime($matches[1]); - if ($timestamp > ($this->startTime + 60 * 60 * 24)) { - return strtotime($matches[1] . " -1 year"); - } else { - return strtotime($matches[1]); - } - } else { - return 0; - } - } - /** * getDomainTraffic * returns the traffic of a given domain or 0 if the domain has no traffic * * @param - * string domain - * return array + * string domain + * return array */ public function getDomainTraffic($domain) { diff --git a/lib/Froxlor/PhpHelper.php b/lib/Froxlor/PhpHelper.php index 8ccd7c4c..7cce512d 100644 --- a/lib/Froxlor/PhpHelper.php +++ b/lib/Froxlor/PhpHelper.php @@ -1,12 +1,38 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor; +use Exception; +use Froxlor\UI\Panel\UI; +use Throwable; +use voku\helper\AntiXSS; + class PhpHelper { - private static $sort_key = 'id'; - private static $sort_type = SORT_STRING; /** @@ -21,18 +47,10 @@ class PhpHelper { self::$sort_type = Settings::Get('panel.natsorting') == 1 ? SORT_NATURAL : SORT_STRING; self::$sort_key = $key; - return usort($list, array( + return usort($list, [ 'self', 'sortListByGivenKey' - )); - } - - private static function sortListByGivenKey($a, $b) - { - if (self::$sort_type == SORT_NATURAL) { - return strnatcasecmp($a[self::$sort_key], $b[self::$sort_key]); - } - return strcasecmp($a[self::$sort_key], $b[self::$sort_key]); + ]); } /** @@ -40,16 +58,16 @@ class PhpHelper * can select which fields should be handled by htmlentities * * @param array|string $subject - * The subject array + * The subject array * @param string $fields - * The fields which should be checked for, separated by spaces + * The fields which should be checked for, separated by spaces * @param int $quote_style - * See php documentation about this + * See php documentation about this * @param string $charset - * See php documentation about this + * See php documentation about this * * @return array|string The string or an array with htmlentities converted strings - * @author Florian Lippert + * @author Florian Lippert (2003-2009) */ public static function htmlentitiesArray($subject, $fields = '', $quote_style = ENT_QUOTES, $charset = 'UTF-8') { @@ -71,20 +89,41 @@ class PhpHelper return $subject; } + /** + * Returns array with all empty-values removed + * + * @param array $source + * The array to trim + * @return array The trim'med array + */ + public static function arrayTrim($source) + { + $returnval = []; + if (is_array($source)) { + $source = array_map('trim', $source); + $returnval = array_filter($source, function ($value) { + return $value !== ''; + }); + } else { + $returnval = $source; + } + return $returnval; + } + /** * Replaces Strings in an array, with the advantage that you * can select which fields should be str_replace'd * - * @param string|array $search - * String or array of strings to search for + * @param string|array $search + * String or array of strings to search for * @param string|array $reaplce - * String or array to replace with + * String or array to replace with * @param string|array $subject - * String or array The subject array + * String or array The subject array * @param string $fields - * string The fields which should be checked for, separated by spaces + * string The fields which should be checked for, separated by spaces * @return string|array The str_replace'd array - * @author Florian Lippert + * @author Florian Lippert (2003-2009) */ public static function strReplaceArray($search, $replace, $subject, $fields = '') { @@ -121,7 +160,7 @@ class PhpHelper if (!isset($_SERVER['SHELL']) || (isset($_SERVER['SHELL']) && $_SERVER['SHELL'] == '')) { // prevent possible file-path-disclosure - $errfile = str_replace(\Froxlor\Froxlor::getInstallDir(), "", $errfile); + $errfile = str_replace(Froxlor::getInstallDir(), "", $errfile); // build alert $type = 'danger'; if ($errno == E_NOTICE || $errno == E_DEPRECATED || $errno == E_STRICT) { @@ -136,14 +175,14 @@ class PhpHelper $err_display .= '

';
 			$debug = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
 			foreach ($debug as $dline) {
-				$err_display .= $dline['function'] . '() called at [' . str_replace(\Froxlor\Froxlor::getInstallDir(), '', ($dline['file'] ?? 'unknown')) . ':' . ($dline['line'] ?? 0) . ']
'; + $err_display .= $dline['function'] . '() called at [' . str_replace(Froxlor::getInstallDir(), '', ($dline['file'] ?? 'unknown')) . ':' . ($dline['line'] ?? 0) . ']
'; } $err_display .= '

'; // end later $err_display .= ''; // check for more existing errors - $errors = isset(\Froxlor\UI\Panel\UI::twig()->getGlobals()['global_errors']) ? \Froxlor\UI\Panel\UI::twig()->getGlobals()['global_errors'] : ""; - \Froxlor\UI\Panel\UI::twig()->addGlobal('global_errors', $errors . $err_display); + $errors = isset(UI::twig()->getGlobals()['global_errors']) ? UI::twig()->getGlobals()['global_errors'] : ""; + UI::twig()->addGlobal('global_errors', $errors . $err_display); // return true to ignore php standard error-handler return true; } @@ -152,13 +191,13 @@ class PhpHelper return false; } - public static function phpExceptionHandler(\Throwable $exception) + public static function phpExceptionHandler(Throwable $exception) { if (!isset($_SERVER['SHELL']) || (isset($_SERVER['SHELL']) && $_SERVER['SHELL'] == '')) { // show - \Froxlor\UI\Panel\UI::initTwig(true); - \Froxlor\UI\Panel\UI::twig()->addGlobal('install_mode', '1'); - \Froxlor\UI\Panel\UI::view('misc/alert_nosession.html.twig', [ + UI::initTwig(true); + UI::twig()->addGlobal('install_mode', '1'); + UI::view('misc/alert_nosession.html.twig', [ 'page_title' => 'Uncaught exception', 'heading' => 'Uncaught exception', 'type' => 'danger', @@ -183,7 +222,7 @@ class PhpHelper // variable that holds all dirs that will // be parsed for inclusion - $configdirs = array(); + $configdirs = []; // if one of the parameters is an array // we assume that this is a list of // setting-groups to be selected @@ -197,8 +236,8 @@ class PhpHelper } } - $data = array(); - $data_files = array(); + $data = []; + $data_files = []; $has_data = false; foreach ($configdirs as $data_dirname) { @@ -223,9 +262,9 @@ class PhpHelper // if we have specific setting-groups // to select, we'll handle this here // (this is for multiserver-client settings) - $_data = array(); + $_data = []; if ($selection != null && is_array($selection) && isset($selection[0])) { - $_data['groups'] = array(); + $_data['groups'] = []; foreach ($data['groups'] as $group => $data) { if (in_array($group, $selection)) { $_data['groups'][$group] = $data; @@ -242,7 +281,7 @@ class PhpHelper * * @param string $host * @param boolean $try_a - * default true + * default true * @return boolean|array */ public static function gethostbynamel6($host, $try_a = true) @@ -262,7 +301,7 @@ class PhpHelper } else { $dns = $dns6; } - $ips = array(); + $ips = []; foreach ($dns as $record) { if ($record["type"] == "A") { // always use compressed ipv6 format @@ -282,63 +321,63 @@ class PhpHelper } } - /** - * Function randomStr - * - * generate a pseudo-random string of bytes - * - * @param int $length - * @return string - * @throws \Exception - */ + /** + * Function randomStr + * + * generate a pseudo-random string of bytes + * + * @param int $length + * @return string + * @throws Exception + */ public static function randomStr($length) { - if (function_exists('openssl_random_pseudo_bytes')) { - return openssl_random_pseudo_bytes($length); - } - return random_bytes($length); + if (function_exists('openssl_random_pseudo_bytes')) { + return openssl_random_pseudo_bytes($length); + } + return random_bytes($length); } /** * Return human readable sizes * * @param int $size - * size in bytes + * size in bytes * @param string $max - * maximum unit + * maximum unit * @param string $system - * 'si' for SI, 'bi' for binary prefixes + * 'si' for SI, 'bi' for binary prefixes * * @param string $retstring - * string + * string */ public static function sizeReadable($size, $max = null, $system = 'si', $retstring = '%01.2f %s') { // Pick units - $systems = array( - 'si' => array( - 'prefix' => array( + $systems = [ + 'si' => [ + 'prefix' => [ 'B', 'KB', 'MB', 'GB', 'TB', 'PB' - ), + ], 'size' => 1000 - ), - 'bi' => array( - 'prefix' => array( + ], + 'bi' => [ + 'prefix' => [ 'B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB' - ), + ], 'size' => 1024 - ) - ); + ] + ]; $sys = isset($systems[$system]) ? $systems[$system] : $systems['si']; // Max unit to display @@ -361,16 +400,16 @@ class PhpHelper * in the first argument with their values. * * @param string $text - * The string that should be searched for variables + * The string that should be searched for variables * @param array $vars - * The array containing the variables with their values + * The array containing the variables with their values * * @return string The submitted string with the variables replaced. */ public static function replaceVariables($text, $vars) { $pattern = "/\{([a-zA-Z0-9\-_]+)\}/"; - $matches = array(); + $matches = []; if (count($vars) > 0 && preg_match_all($pattern, $text, $matches)) { for ($i = 0; $i < count($matches[1]); $i++) { @@ -387,35 +426,16 @@ class PhpHelper return $text; } - /** - * Returns array with all empty-values removed - * - * @param array $source - * The array to trim - * @return array The trim'med array - */ - public static function arrayTrim($source) - { - $returnval = array(); - if (is_array($source)) { - $source = array_map('trim', $source); - $returnval = array_filter($source, function ($value) { - return $value !== ''; - }); - } else { - $returnval = $source; - } - return $returnval; - } - - public static function recursive_array_search($needle, $haystack, &$keys = array(), $currentKey = '') + public static function recursive_array_search($needle, $haystack, &$keys = [], $currentKey = '') { foreach ($haystack as $key => $value) { $pathkey = empty($currentKey) ? $key : $currentKey . '.' . $key; if (is_array($value)) { self::recursive_array_search($needle, $value, $keys, $pathkey); - } else if (stripos($value, $needle) !== false) { - $keys[] = $pathkey; + } else { + if (stripos($value, $needle) !== false) { + $keys[] = $pathkey; + } } } return true; @@ -426,7 +446,7 @@ class PhpHelper * so it gets automatically updated * * @param array $global - * @param \voku\helper\AntiXSS $antiXss + * @param AntiXSS $antiXss */ public static function cleanGlobal(&$global, &$antiXss) { @@ -449,4 +469,12 @@ class PhpHelper } } } + + private static function sortListByGivenKey($a, $b) + { + if (self::$sort_type == SORT_NATURAL) { + return strnatcasecmp($a[self::$sort_key], $b[self::$sort_key]); + } + return strcasecmp($a[self::$sort_key], $b[self::$sort_key]); + } } diff --git a/lib/Froxlor/SImExporter.php b/lib/Froxlor/SImExporter.php index 2f4929c8..3ee5b00c 100644 --- a/lib/Froxlor/SImExporter.php +++ b/lib/Froxlor/SImExporter.php @@ -1,40 +1,41 @@ - * @author Froxlor team (2018-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes + * 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.39 + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ +namespace Froxlor; + +use Exception; +use Froxlor\Database\Database; +use PDO; + /** * Class SImExporter * * Import/Export settings to JSON - * - * @copyright (c) the authors - * @author Michael Kaufmann - * @author Froxlor team (2018-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes */ class SImExporter { - /** * settings which are not being exported * @@ -60,40 +61,40 @@ class SImExporter public static function export() { - $settings_definitions = []; - foreach (\Froxlor\PhpHelper::loadConfigArrayDir('./actions/admin/settings/')['groups'] AS $group) { - foreach ($group['fields'] AS $field) { - $settings_definitions[$field['settinggroup']][$field['varname']] = $field; - } - } + $settings_definitions = []; + foreach (PhpHelper::loadConfigArrayDir('./actions/admin/settings/')['groups'] as $group) { + foreach ($group['fields'] as $field) { + $settings_definitions[$field['settinggroup']][$field['varname']] = $field; + } + } $result_stmt = Database::query(" SELECT * FROM `" . TABLE_PANEL_SETTINGS . "` ORDER BY `settingid` ASC "); - $_data = array(); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + $_data = []; + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $index = $row['settinggroup'] . "." . $row['varname']; - if (! in_array($index, self::$no_export)) { + if (!in_array($index, self::$no_export)) { $_data[$index] = $row['value']; } if (array_key_exists($row['settinggroup'], $settings_definitions) && array_key_exists($row['varname'], $settings_definitions[$row['settinggroup']])) { - // Export image file - if ($settings_definitions[$row['settinggroup']][$row['varname']]['type'] === "image") { - if ($row['value'] === "") { - continue; - } + // Export image file + if ($settings_definitions[$row['settinggroup']][$row['varname']]['type'] === "image") { + if ($row['value'] === "") { + continue; + } - $_data[$index.'.image_data'] = base64_encode(file_get_contents(explode('?', $row['value'], 2)[0])); - } - } + $_data[$index . '.image_data'] = base64_encode(file_get_contents(explode('?', $row['value'], 2)[0])); + } + } } // add checksum for validation $_data['_sha'] = sha1(var_export($_data, true)); $_export = json_encode($_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); - if (! $_export) { - throw new \Exception("Error exporting settings: " . json_last_error_msg()); + if (!$_export) { + throw new Exception("Error exporting settings: " . json_last_error_msg()); } return $_export; @@ -109,14 +110,14 @@ class SImExporter $_version = isset($_data['panel.version']) ? $_data['panel.version'] : false; $_dbversion = isset($_data['panel.db_version']) ? $_data['panel.db_version'] : false; // check if we have everything we need - if (! $_sha || ! $_version || ! $_dbversion) { - throw new \Exception("Invalid froxlor settings data. Unable to import."); + if (!$_sha || !$_version || !$_dbversion) { + throw new Exception("Invalid froxlor settings data. Unable to import."); } // validate import file unset($_data['_sha']); // compare if ($_sha != sha1(var_export($_data, true))) { - throw new \Exception("SHA check of import data failed. Unable to import."); + throw new Exception("SHA check of import data failed. Unable to import."); } // do not import version info - but we need that to possibly update settings // when there were changes in the variable-name or similar @@ -140,25 +141,25 @@ class SImExporter } // store new data foreach ($_data as $index => $value) { - $index_split = explode('.', $index, 3); + $index_split = explode('.', $index, 3); - // Catch image_data and save it - if (isset($index_split[2]) && $index_split[2] === 'image_data' && !empty($_data[$index_split[0].'.'.$index_split[1]])) { - $path = \Froxlor\Froxlor::getInstallDir().'/img/'; - if (!is_dir($path) && !mkdir($path, 0775)) { - throw new \Exception("img directory does not exist and cannot be created"); - } + // Catch image_data and save it + if (isset($index_split[2]) && $index_split[2] === 'image_data' && !empty($_data[$index_split[0] . '.' . $index_split[1]])) { + $path = Froxlor::getInstallDir() . '/img/'; + if (!is_dir($path) && !mkdir($path, 0775)) { + throw new Exception("img directory does not exist and cannot be created"); + } - // Make sure we can write to the upload directory - if (!is_writable($path)) { - if (!chmod($path, 0775)) { - throw new \Exception("Cannot write to img directory"); - } - } + // Make sure we can write to the upload directory + if (!is_writable($path)) { + if (!chmod($path, 0775)) { + throw new Exception("Cannot write to img directory"); + } + } - file_put_contents(\Froxlor\Froxlor::getInstallDir() . '/' . explode('?', $_data[$index_split[0].'.'.$index_split[1]], 2)[0], base64_decode($value)); - continue; - } + file_put_contents(Froxlor::getInstallDir() . '/' . explode('?', $_data[$index_split[0] . '.' . $index_split[1]], 2)[0], base64_decode($value)); + continue; + } Settings::Set($index, $value); } @@ -167,6 +168,6 @@ class SImExporter // all good return true; } - throw new \Exception("Invalid JSON data: " . json_last_error_msg()); + throw new Exception("Invalid JSON data: " . json_last_error_msg()); } } diff --git a/lib/Froxlor/Settings.php b/lib/Froxlor/Settings.php index 025a061f..2e2176bb 100644 --- a/lib/Froxlor/Settings.php +++ b/lib/Froxlor/Settings.php @@ -1,42 +1,41 @@ - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes - * - * @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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ +namespace Froxlor; + +use Froxlor\Database\Database; +use PDO; +use PDOStatement; + /** * Class Settings * * Interaction with settings from the db - * - * @copyright (c) the authors - * @author Michael Kaufmann - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Classes - * */ class Settings { - /** * settings data * @@ -62,10 +61,31 @@ class Settings * prepared statement for updating the * settings table * - * @var \PDOStatement + * @var PDOStatement */ private static $updstmt = null; + /** + * tests if a setting-value that i s a comma separated list contains an entry + * + * @param string $setting + * a group and a varname separated by a dot (group.varname) + * @param string $entry + * the entry that is expected to be in the list + * + * @return boolean true, if the list contains $entry + */ + public static function IsInList($setting = null, $entry = null) + { + self::init(); + $svalue = self::Get($setting); + if ($svalue == null) { + return false; + } + $slist = explode(",", $svalue); + return in_array($entry, $slist); + } + /** * private constructor, reads in all settings */ @@ -74,7 +94,7 @@ class Settings if (empty(self::$data)) { self::readSettings(); self::readConfig(); - self::$updatedata = array(); + self::$updatedata = []; // prepare statement self::$updstmt = Database::prepare(" @@ -94,8 +114,8 @@ class Settings SELECT `settingid`, `settinggroup`, `varname`, `value` FROM `" . TABLE_PANEL_SETTINGS . "` "); - self::$data = array(); - while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + self::$data = []; + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { self::$data[$row['settinggroup']][$row['varname']] = $row['value']; } return true; @@ -119,29 +139,12 @@ class Settings return true; } - /** - * update a value in the database - * - * @param string $group - * @param string $varname - * @param string $value - */ - private static function storeSetting($group = null, $varname = null, $value = null) - { - $upd_data = array( - 'group' => $group, - 'varname' => $varname, - 'value' => $value - ); - Database::pexecute(self::$updstmt, $upd_data); - } - /** * return a setting-value by its group and varname * * @param string $setting - * a group and a varname separated by a dot (group.varname) - * + * a group and a varname separated by a dot (group.varname) + * * @return mixed */ public static function Get($setting = null) @@ -159,32 +162,11 @@ class Settings return $result; } - /** - * tests if a setting-value that i s a comma separated list contains an entry - * - * @param string $setting - * a group and a varname separated by a dot (group.varname) - * @param string $entry - * the entry that is expected to be in the list - * - * @return boolean true, if the list contains $entry - */ - public static function IsInList($setting = null, $entry = null) - { - self::init(); - $svalue = self::Get($setting); - if ($svalue == null) { - return false; - } - $slist = explode(",", $svalue); - return in_array($entry, $slist); - } - /** * update a setting / set a new value * * @param string $setting - * a group and a varname separated by a dot (group.varname) + * a group and a varname separated by a dot (group.varname) * @param string $value * @param boolean $instant_save * @@ -207,12 +189,12 @@ class Settings } else { // set temporary data for usage if (!isset(self::$data[$sstr[0]]) || !is_array(self::$data[$sstr[0]])) { - self::$data[$sstr[0]] = array(); + self::$data[$sstr[0]] = []; } self::$data[$sstr[0]][$sstr[1]] = $value; // set update-data when invoking Flush() if (!isset(self::$updatedata[$sstr[0]]) || !is_array(self::$updatedata[$sstr[0]])) { - self::$updatedata[$sstr[0]] = array(); + self::$updatedata[$sstr[0]] = []; } self::$updatedata[$sstr[0]][$sstr[1]] = $value; } @@ -221,11 +203,28 @@ class Settings return false; } + /** + * update a value in the database + * + * @param string $group + * @param string $varname + * @param string $value + */ + private static function storeSetting($group = null, $varname = null, $value = null) + { + $upd_data = [ + 'group' => $group, + 'varname' => $varname, + 'value' => $value + ]; + Database::pexecute(self::$updstmt, $upd_data); + } + /** * add a new setting to the database (mainly used in updater) * * @param string $setting - * a group and a varname separated by a dot (group.varname) + * a group and a varname separated by a dot (group.varname) * @param string $value * * @return boolean @@ -247,11 +246,11 @@ class Settings `varname` = :varname, `value` = :value "); - $ins_data = array( + $ins_data = [ 'group' => $sstr[0], 'varname' => $sstr[1], 'value' => $value - ); + ]; Database::pexecute($ins_stmt, $ins_data); // also set new value to internal array and make it available self::$data[$sstr[0]][$sstr[1]] = $value; @@ -275,7 +274,7 @@ class Settings } } // now empty the array - self::$updatedata = array(); + self::$updatedata = []; // re-read in all settings return self::readSettings(); } @@ -289,7 +288,7 @@ class Settings { self::init(); // empty update array - self::$updatedata = array(); + self::$updatedata = []; // re-read in all settings return self::readSettings(); } @@ -297,7 +296,6 @@ class Settings public static function loadSettingsInto(&$settings_data) { if (is_array($settings_data) && isset($settings_data['groups']) && is_array($settings_data['groups'])) { - // prepare for use in for-loop $row_stmt = Database::prepare(" SELECT `settinggroup`, `varname`, `value` @@ -306,17 +304,14 @@ class Settings "); foreach ($settings_data['groups'] as $settings_part => $settings_part_details) { - if (is_array($settings_part_details) && isset($settings_part_details['fields']) && is_array($settings_part_details['fields'])) { - foreach ($settings_part_details['fields'] as $field_name => $field_details) { - if (isset($field_details['settinggroup']) && isset($field_details['varname']) && isset($field_details['default'])) { // execute prepared statement - $row = Database::pexecute_first($row_stmt, array( + $row = Database::pexecute_first($row_stmt, [ 'group' => $field_details['settinggroup'], 'varname' => $field_details['varname'] - )); + ]); if (!empty($row)) { $varvalue = $row['value']; @@ -344,7 +339,9 @@ class Settings $result = self::$conf; foreach ($sstr as $key) { $result = $result[$key] ?? null; - if (empty($result)) break; + if (empty($result)) { + break; + } } return $result; } diff --git a/lib/Froxlor/Settings/FroxlorVhostSettings.php b/lib/Froxlor/Settings/FroxlorVhostSettings.php index bb360c5f..10a7629f 100644 --- a/lib/Froxlor/Settings/FroxlorVhostSettings.php +++ b/lib/Froxlor/Settings/FroxlorVhostSettings.php @@ -1,4 +1,28 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\Settings; use Froxlor\Database\Database; diff --git a/lib/Froxlor/Settings/Store.php b/lib/Froxlor/Settings/Store.php index a7efe3d7..dc855220 100644 --- a/lib/Froxlor/Settings/Store.php +++ b/lib/Froxlor/Settings/Store.php @@ -1,9 +1,42 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\Settings; +use Exception; +use Froxlor\Cron\TaskId; use Froxlor\Database\Database; +use Froxlor\Database\DbManager; use Froxlor\FileDir; +use Froxlor\Froxlor; +use Froxlor\Idna\IdnaWrapper; +use Froxlor\PhpHelper; use Froxlor\Settings; +use Froxlor\System\Cronjob; +use Froxlor\System\IPTools; +use PDO; class Store { @@ -21,6 +54,37 @@ class Store return $returnvalue; } + public static function storeSettingField($fieldname, $fielddata, $newfieldvalue) + { + if (is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] != '' && isset($fielddata['varname']) && $fielddata['varname'] != '') { + if (Settings::Set($fielddata['settinggroup'] . '.' . $fielddata['varname'], $newfieldvalue) !== false) { + /* + * when fielddata[cronmodule] is set, this means enable/disable a cronjob + */ + if (isset($fielddata['cronmodule']) && $fielddata['cronmodule'] != '') { + Cronjob::toggleCronStatus($fielddata['cronmodule'], $newfieldvalue); + } + + /* + * satisfy dependencies + */ + if (isset($fielddata['dependency']) && is_array($fielddata['dependency'])) { + if ((int)$fielddata['dependency']['onlyif'] == (int)$newfieldvalue) { + self::storeSettingField($fielddata['dependency']['fieldname'], $fielddata['dependency']['fielddata'], $newfieldvalue); + } + } + + return [ + $fielddata['settinggroup'] . '.' . $fielddata['varname'] => $newfieldvalue + ]; + } else { + return false; + } + } else { + return false; + } + } + public static function storeSettingDefaultIp($fieldname, $fielddata, $newfieldvalue) { $defaultips_old = Settings::Get('system.defaultip'); @@ -34,19 +98,6 @@ class Store return $returnvalue; } - public static function storeSettingDefaultSslIp($fieldname, $fielddata, $newfieldvalue) - { - $defaultips_old = Settings::Get('system.defaultsslip'); - - $returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue); - - if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'system' && isset($fielddata['varname']) && $fielddata['varname'] == 'defaultsslip') { - self::updateStdSubdomainDefaultIp($newfieldvalue, $defaultips_old); - } - - return $returnvalue; - } - private static function updateStdSubdomainDefaultIp($newfieldvalue, $defaultips_old) { // update standard-subdomain of customer if exists @@ -55,17 +106,17 @@ class Store "); Database::pexecute($customerstddomains_result_stmt); - $ids = array(); - while ($customerstddomains_row = $customerstddomains_result_stmt->fetch(\PDO::FETCH_ASSOC)) { - $ids[] = (int) $customerstddomains_row['standardsubdomain']; + $ids = []; + while ($customerstddomains_row = $customerstddomains_result_stmt->fetch(PDO::FETCH_ASSOC)) { + $ids[] = (int)$customerstddomains_row['standardsubdomain']; } if (count($ids) > 0) { $defaultips_new = explode(',', $newfieldvalue); - if (! empty($defaultips_old) && ! empty($newfieldvalue)) { + if (!empty($defaultips_old) && !empty($newfieldvalue)) { $in_value = $defaultips_old . ", " . $newfieldvalue; - } elseif (! empty($defaultips_old) && empty($newfieldvalue)) { + } elseif (!empty($defaultips_old) && empty($newfieldvalue)) { $in_value = $defaultips_old; } else { $in_value = $newfieldvalue; @@ -88,16 +139,29 @@ class Store foreach ($ids as $id) { foreach ($defaultips_new as $defaultip_new) { - Database::pexecute($ins_stmt, array( + Database::pexecute($ins_stmt, [ 'domainid' => $id, 'ipandportid' => $defaultip_new - )); + ]); } } } } } + public static function storeSettingDefaultSslIp($fieldname, $fielddata, $newfieldvalue) + { + $defaultips_old = Settings::Get('system.defaultsslip'); + + $returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue); + + if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'system' && isset($fielddata['varname']) && $fielddata['varname'] == 'defaultsslip') { + self::updateStdSubdomainDefaultIp($newfieldvalue, $defaultips_old); + } + + return $returnvalue; + } + /** * updates the setting for the default panel-theme * and also the user themes (customers and admins) if @@ -121,61 +185,30 @@ class Store $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `theme` = :theme "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'theme' => $newfieldvalue - )); + ]); } if (Settings::Get('panel.allow_theme_change_admin') == '0') { $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_ADMINS . "` SET `theme` = :theme "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'theme' => $newfieldvalue - )); + ]); } } return $returnvalue; } - public static function storeSettingField($fieldname, $fielddata, $newfieldvalue) - { - if (is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] != '' && isset($fielddata['varname']) && $fielddata['varname'] != '') { - if (Settings::Set($fielddata['settinggroup'] . '.' . $fielddata['varname'], $newfieldvalue) !== false) { - /* - * when fielddata[cronmodule] is set, this means enable/disable a cronjob - */ - if (isset($fielddata['cronmodule']) && $fielddata['cronmodule'] != '') { - \Froxlor\System\Cronjob::toggleCronStatus($fielddata['cronmodule'], $newfieldvalue); - } - - /* - * satisfy dependencies - */ - if (isset($fielddata['dependency']) && is_array($fielddata['dependency'])) { - if ((int) $fielddata['dependency']['onlyif'] == (int) $newfieldvalue) { - self::storeSettingField($fielddata['dependency']['fieldname'], $fielddata['dependency']['fielddata'], $newfieldvalue); - } - } - - return array( - $fielddata['settinggroup'] . '.' . $fielddata['varname'] => $newfieldvalue - ); - } else { - return false; - } - } else { - return false; - } - } - public static function storeSettingFieldInsertBindTask($fieldname, $fielddata, $newfieldvalue) { // first save the setting itself $returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue); if ($returnvalue !== false) { - \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); + Cronjob::inserttask(TaskId::REBUILD_DNS); } return $returnvalue; } @@ -185,7 +218,7 @@ class Store $returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue); if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'system' && isset($fielddata['varname']) && ($fielddata['varname'] == 'hostname' || $fielddata['varname'] == 'stdsubdomain')) { - $idna_convert = new \Froxlor\Idna\IdnaWrapper(); + $idna_convert = new IdnaWrapper(); $newfieldvalue = $idna_convert->encode($newfieldvalue); if (($fielddata['varname'] == 'hostname' && Settings::Get('system.stdsubdomain') == '') || $fielddata['varname'] == 'stdsubdomain') { @@ -212,10 +245,10 @@ class Store "); Database::pexecute($customerstddomains_result_stmt); - $ids = array(); + $ids = []; - while ($customerstddomains_row = $customerstddomains_result_stmt->fetch(\PDO::FETCH_ASSOC)) { - $ids[] = (int) $customerstddomains_row['standardsubdomain']; + while ($customerstddomains_row = $customerstddomains_result_stmt->fetch(PDO::FETCH_ASSOC)) { + $ids[] = (int)$customerstddomains_row['standardsubdomain']; } if (count($ids) > 0) { @@ -224,10 +257,10 @@ class Store `domain` = REPLACE(`domain`, :host, :newval) WHERE `id` IN ('" . implode(', ', $ids) . "') "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'host' => $oldhost, 'newval' => $newhost - )); + ]); } } } @@ -242,8 +275,8 @@ class Store if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'system' && isset($fielddata['varname']) && $fielddata['varname'] == 'ipaddress') { $mysql_access_host_array = array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))); $mysql_access_host_array[] = $newfieldvalue; - $mysql_access_host_array = array_unique(\Froxlor\PhpHelper::arrayTrim($mysql_access_host_array)); - \Froxlor\Database\DbManager::correctMysqlUsers($mysql_access_host_array); + $mysql_access_host_array = array_unique(PhpHelper::arrayTrim($mysql_access_host_array)); + DbManager::correctMysqlUsers($mysql_access_host_array); $mysql_access_host = implode(',', $mysql_access_host_array); Settings::Set('system.mysql_access_host', $mysql_access_host); } @@ -266,7 +299,7 @@ class Store if (count($ip_cidr) === 2) { $ip = $ip_cidr[0]; if (strlen($ip_cidr[1]) <= 2) { - $ip_cidr[1] = \Froxlor\System\IPTools::cidr2NetmaskAddr($org_ip); + $ip_cidr[1] = IPTools::cidr2NetmaskAddr($org_ip); } $newfieldvalue[] = $ip . '/' . $ip_cidr[1]; } else { @@ -280,23 +313,23 @@ class Store if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'system' && isset($fielddata['varname']) && $fielddata['varname'] == 'mysql_access_host') { $mysql_access_host_array = array_map('trim', explode(',', $newfieldvalue)); - if (in_array('127.0.0.1', $mysql_access_host_array) && ! in_array('localhost', $mysql_access_host_array)) { + if (in_array('127.0.0.1', $mysql_access_host_array) && !in_array('localhost', $mysql_access_host_array)) { $mysql_access_host_array[] = 'localhost'; } - if (! in_array('127.0.0.1', $mysql_access_host_array) && in_array('localhost', $mysql_access_host_array)) { + if (!in_array('127.0.0.1', $mysql_access_host_array) && in_array('localhost', $mysql_access_host_array)) { $mysql_access_host_array[] = '127.0.0.1'; } // be aware that ipv6 addresses are enclosed in [ ] when passed here - $mysql_access_host_array = array_map(array( + $mysql_access_host_array = array_map([ '\\Froxlor\\Settings\\Store', 'cleanMySQLAccessHost' - ), $mysql_access_host_array); + ], $mysql_access_host_array); - $mysql_access_host_array = array_unique(\Froxlor\PhpHelper::arrayTrim($mysql_access_host_array)); + $mysql_access_host_array = array_unique(PhpHelper::arrayTrim($mysql_access_host_array)); $newfieldvalue = implode(',', $mysql_access_host_array); - \Froxlor\Database\DbManager::correctMysqlUsers($mysql_access_host_array); + DbManager::correctMysqlUsers($mysql_access_host_array); $mysql_access_host = implode(',', $mysql_access_host_array); Settings::Set('system.mysql_access_host', $mysql_access_host); } @@ -304,14 +337,6 @@ class Store return $returnvalue; } - private static function cleanMySQLAccessHost($value) - { - if (substr($value, 0, 1) == '[' && substr($value, - 1) == ']') { - return substr($value, 1, - 1); - } - return $value; - } - public static function storeSettingResetCatchall($fieldname, $fielddata, $newfieldvalue) { $returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue); @@ -332,7 +357,6 @@ class Store public static function storeSettingWebserverFcgidFpmUser($fieldname, $fielddata, $newfieldvalue) { if (is_array($fielddata) && isset($fielddata['settinggroup']) && isset($fielddata['varname'])) { - $update_user = null; // webserver @@ -358,10 +382,10 @@ class Store */ if ($update_user != null && $newfieldvalue != $update_user) { $upd_stmt = Database::prepare("UPDATE `" . TABLE_FTP_GROUPS . "` SET `members` = REPLACE(`members`, :olduser, :newuser)"); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'olduser' => $update_user, 'newuser' => $newfieldvalue - )); + ]); } } } @@ -370,66 +394,79 @@ class Store } public static function storeSettingImage($fieldname, $fielddata) - { - if (isset($fielddata['settinggroup'], $fielddata['varname']) && is_array($fielddata) && $fielddata['settinggroup'] !== '' && $fielddata['varname'] !== '') { - $save_to = null; - $path = \Froxlor\Froxlor::getInstallDir().'/img/'; - $path = \Froxlor\FileDir::makeCorrectDir($path); + { + if (isset($fielddata['settinggroup'], $fielddata['varname']) && is_array($fielddata) && $fielddata['settinggroup'] !== '' && $fielddata['varname'] !== '') { + $save_to = null; + $path = Froxlor::getInstallDir() . '/img/'; + $path = FileDir::makeCorrectDir($path); - // New file? - if (isset($_FILES[$fieldname]) && $_FILES[$fieldname]['tmp_name']) { - // Make sure upload directory exists - if (!is_dir($path) && !mkdir($path, 0775)) { - throw new \Exception("img directory does not exist and cannot be created"); - } + // New file? + if (isset($_FILES[$fieldname]) && $_FILES[$fieldname]['tmp_name']) { + // Make sure upload directory exists + if (!is_dir($path) && !mkdir($path, 0775)) { + throw new Exception("img directory does not exist and cannot be created"); + } - // Make sure we can write to the upload directory - if (!is_writable($path)) { - if (!chmod($path, 0775)) { - throw new \Exception("Cannot write to img directory"); - } - } + // Make sure we can write to the upload directory + if (!is_writable($path)) { + if (!chmod($path, 0775)) { + throw new Exception("Cannot write to img directory"); + } + } - // Make sure mime-type matches an image - if (!in_array(mime_content_type($_FILES[$fieldname]['tmp_name']), ['image/jpeg','image/jpg','image/png','image/gif'])) { - throw new \Exception("Uploaded file not a valid image"); - } + // Make sure mime-type matches an image + if (!in_array(mime_content_type($_FILES[$fieldname]['tmp_name']), [ + 'image/jpeg', + 'image/jpg', + 'image/png', + 'image/gif' + ])) { + throw new Exception("Uploaded file not a valid image"); + } - // Determine file extension - $spl = explode('.', $_FILES[$fieldname]['name']); - $file_extension = strtolower(array_pop($spl)); - unset($spl); + // Determine file extension + $spl = explode('.', $_FILES[$fieldname]['name']); + $file_extension = strtolower(array_pop($spl)); + unset($spl); - // Move file - if (!move_uploaded_file($_FILES[$fieldname]['tmp_name'], $path.$fielddata['image_name'].'.'.$file_extension)) { - throw new \Exception("Unable to save image to img folder"); - } + // Move file + if (!move_uploaded_file($_FILES[$fieldname]['tmp_name'], $path . $fielddata['image_name'] . '.' . $file_extension)) { + throw new Exception("Unable to save image to img folder"); + } - $save_to = 'img/'.$fielddata['image_name'].'.'.$file_extension.'?v='.time(); - } + $save_to = 'img/' . $fielddata['image_name'] . '.' . $file_extension . '?v=' . time(); + } - // Delete file? - if ($fielddata['value'] !== "" && array_key_exists($fieldname.'_delete', $_POST) && $_POST[$fieldname.'_delete']) { - @unlink(\Froxlor\Froxlor::getInstallDir() . '/' . explode('?', $fielddata['value'], 2)[0]); - $save_to = ''; - } + // Delete file? + if ($fielddata['value'] !== "" && array_key_exists($fieldname . '_delete', $_POST) && $_POST[$fieldname . '_delete']) { + @unlink(Froxlor::getInstallDir() . '/' . explode('?', $fielddata['value'], 2)[0]); + $save_to = ''; + } - // Nothing changed - if ($save_to === null) { - return array( - $fielddata['settinggroup'] . '.' . $fielddata['varname'] => $fielddata['value'] - ); - } + // Nothing changed + if ($save_to === null) { + return [ + $fielddata['settinggroup'] . '.' . $fielddata['varname'] => $fielddata['value'] + ]; + } - if (Settings::Set($fielddata['settinggroup'] . '.' . $fielddata['varname'], $save_to) === false) { - return false; - } + if (Settings::Set($fielddata['settinggroup'] . '.' . $fielddata['varname'], $save_to) === false) { + return false; + } - return array( - $fielddata['settinggroup'] . '.' . $fielddata['varname'] => $save_to - ); - } + return [ + $fielddata['settinggroup'] . '.' . $fielddata['varname'] => $save_to + ]; + } - return false; - } + return false; + } + + private static function cleanMySQLAccessHost($value) + { + if (substr($value, 0, 1) == '[' && substr($value, -1) == ']') { + return substr($value, 1, -1); + } + return $value; + } } diff --git a/lib/Froxlor/System/Cronjob.php b/lib/Froxlor/System/Cronjob.php index 29cae5ee..0f1dae13 100644 --- a/lib/Froxlor/System/Cronjob.php +++ b/lib/Froxlor/System/Cronjob.php @@ -1,10 +1,36 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\System; -use Froxlor\Settings; -use Froxlor\Database\Database; - +use Exception; use Froxlor\Cron\TaskId; +use Froxlor\Database\Database; +use Froxlor\FroxlorLogger; +use Froxlor\Settings; +use PDO; class Cronjob { @@ -20,15 +46,15 @@ class Cronjob */ public static function checkLastGuid() { - $mylog = \Froxlor\FroxlorLogger::getInstanceOf(); + $mylog = FroxlorLogger::getInstanceOf(); - $group_lines = array(); - $group_guids = array(); + $group_lines = []; + $group_guids = []; $update_to_guid = 0; $froxlor_guid = 0; $result_stmt = Database::query("SELECT MAX(`guid`) as `fguid` FROM `" . TABLE_PANEL_CUSTOMERS . "`"); - $result = $result_stmt->fetch(\PDO::FETCH_ASSOC); + $result = $result_stmt->fetch(PDO::FETCH_ASSOC); $froxlor_guid = $result['fguid']; // possibly no customers yet or f*cked up lastguid settings @@ -41,7 +67,6 @@ class Cronjob if (file_exists($g_file)) { if (is_readable($g_file)) { if (true == ($groups = file_get_contents($g_file))) { - $group_lines = explode("\n", $groups); foreach ($group_lines as $group) { @@ -57,7 +82,7 @@ class Cronjob continue; } - $guid = isset($group[2]) ? (int) $group[2] : 0; + $guid = isset($group[2]) ? (int)$group[2] : 0; if ($guid > $update_to_guid) { $update_to_guid = $guid; @@ -70,22 +95,22 @@ class Cronjob } elseif ($update_to_guid == $froxlor_guid) { // if it's equal, that means we already have a collision // to ensure it won't happen again, increase the guid by one - $update_to_guid = (int) $update_to_guid ++; + $update_to_guid = (int)$update_to_guid++; } // now check if it differs from our settings if ($update_to_guid != Settings::Get('system.lastguid')) { - $mylog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Updating froxlor last guid to ' . $update_to_guid); + $mylog->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Updating froxlor last guid to ' . $update_to_guid); Settings::Set('system.lastguid', $update_to_guid); } } else { - $mylog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'File /etc/group not readable; cannot check for latest guid'); + $mylog->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'File /etc/group not readable; cannot check for latest guid'); } } else { - $mylog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'File /etc/group not readable; cannot check for latest guid'); + $mylog->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'File /etc/group not readable; cannot check for latest guid'); } } else { - $mylog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'File /etc/group does not exist; cannot check for latest guid'); + $mylog->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'File /etc/group does not exist; cannot check for latest guid'); } } @@ -93,12 +118,12 @@ class Cronjob * Inserts a task into the PANEL_TASKS-Table * * @param - * int Type of task + * int Type of task * @param - * string Parameter (possible to pass multiple times) + * string Parameter (possible to pass multiple times) * - * @author Florian Lippert - * @author Froxlor team + * @author Florian Lippert (2003-2009) + * @author Froxlor team (2010-) */ public static function inserttask($type, ...$params) { @@ -121,81 +146,81 @@ class Cronjob $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = :type "); - Database::pexecute($del_stmt, array( + Database::pexecute($del_stmt, [ 'type' => $type - )); + ]); // insert the new task - Database::pexecute($ins_stmt, array( + Database::pexecute($ins_stmt, [ 'type' => $type, 'data' => '' - )); + ]); } elseif ($type == TaskId::CREATE_HOME && count($params) == 4 && $params[0] != '' && $params[1] != '' && $params[2] != '' && ($params[3] == 0 || $params[3] == 1)) { - $data = array(); + $data = []; $data['loginname'] = $params[0]; $data['uid'] = $params[1]; $data['gid'] = $params[2]; $data['store_defaultindex'] = $params[3]; $data = json_encode($data); - Database::pexecute($ins_stmt, array( + Database::pexecute($ins_stmt, [ 'type' => TaskId::CREATE_HOME, 'data' => $data - )); + ]); } elseif ($type == TaskId::DELETE_CUSTOMER_FILES && isset($params[0]) && $params[0] != '') { - $data = array(); + $data = []; $data['loginname'] = $params[0]; $data = json_encode($data); - Database::pexecute($ins_stmt, array( + Database::pexecute($ins_stmt, [ 'type' => TaskId::DELETE_CUSTOMER_FILES, 'data' => $data - )); + ]); } elseif ($type == TaskId::DELETE_EMAIL_DATA && count($params) == 2 && $params[0] != '' && $params[1] != '') { - $data = array(); + $data = []; $data['loginname'] = $params[0]; $data['email'] = $params[1]; $data = json_encode($data); - Database::pexecute($ins_stmt, array( + Database::pexecute($ins_stmt, [ 'type' => TaskId::DELETE_EMAIL_DATA, 'data' => $data - )); + ]); } elseif ($type == TaskId::DELETE_FTP_DATA && count($params) == 2 && $params[0] != '' && $params[1] != '') { - $data = array(); + $data = []; $data['loginname'] = $params[0]; $data['homedir'] = $params[1]; $data = json_encode($data); - Database::pexecute($ins_stmt, array( + Database::pexecute($ins_stmt, [ 'type' => TaskId::DELETE_FTP_DATA, 'data' => $data - )); + ]); } elseif ($type == TaskId::DELETE_DOMAIN_PDNS && isset($params[0]) && $params[0] != '' && Settings::Get('system.bind_enable') == '1' && Settings::Get('system.dns_server') == 'PowerDNS') { // -> if bind disabled or dns-server not PowerDNS -> no task - $data = array(); + $data = []; $data['domain'] = $params[0]; $data = json_encode($data); - Database::pexecute($ins_stmt, array( + Database::pexecute($ins_stmt, [ 'type' => TaskId::DELETE_DOMAIN_PDNS, 'data' => $data - )); + ]); } elseif ($type == TaskId::DELETE_DOMAIN_SSL && isset($params[0]) && $params[0] != '') { - $data = array(); + $data = []; $data['domain'] = $params[0]; $data = json_encode($data); - Database::pexecute($ins_stmt, array( + Database::pexecute($ins_stmt, [ 'type' => TaskId::DELETE_DOMAIN_SSL, 'data' => $data - )); + ]); } elseif ($type == TaskId::CREATE_CUSTOMER_BACKUP && isset($params[0]) && is_array($params[0])) { $data = json_encode($params[0]); - Database::pexecute($ins_stmt, array( + Database::pexecute($ins_stmt, [ 'type' => TaskId::CREATE_CUSTOMER_BACKUP, 'data' => $data - )); + ]); } } /** * returns an array of all cronjobs and when they last were executed - * + * * @return array */ public static function getCronjobsLastRun() @@ -206,7 +231,7 @@ class Cronjob $result = Database::query($query); $cronjobs_last_run = []; - while ($row = $result->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result->fetch(PDO::FETCH_ASSOC)) { $cronjobs_last_run[] = [ 'title' => $lng['crondesc'][$row['desc_lng_key']], 'lastrun' => $row['lastrun'] @@ -223,15 +248,15 @@ class Cronjob $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_CRONRUNS . "` SET `isactive` = :active WHERE `module` = :module"); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'active' => $isactive, 'module' => $module - )); + ]); } /** * returns an array of tasks that are queued to be run by the cronjob - * + * * @return array */ public static function getOutstandingTasks() @@ -242,15 +267,14 @@ class Cronjob $result = Database::query($query); $tasks = []; - while ($row = $result->fetch(\PDO::FETCH_ASSOC)) { - + while ($row = $result->fetch(PDO::FETCH_ASSOC)) { if ($row['data'] != '') { $row['data'] = json_decode($row['data'], true); } $task_id = $row['type']; - if (\Froxlor\Cron\TaskId::isValid($task_id)) { - $task_constname = \Froxlor\Cron\TaskId::convertToConstant($task_id); + if (TaskId::isValid($task_id)) { + $task_constname = TaskId::convertToConstant($task_id); $task = [ 'desc' => isset($lng['tasks'][$task_constname]) ? $lng['tasks'][$task_constname] : $task_constname ]; @@ -294,7 +318,6 @@ class Cronjob public static function dieWithMail($message, $subject = "[froxlor] Cronjob error") { if (Settings::Get('system.send_cron_errors') == '1') { - $_mail = new Mailer(true); $_mailerror = false; $mailerr_msg = ""; @@ -307,7 +330,7 @@ class Cronjob } catch (\PHPMailer\PHPMailer\Exception $e) { $mailerr_msg = $e->errorMessage(); $_mailerror = true; - } catch (\Exception $e) { + } catch (Exception $e) { $mailerr_msg = $e->getMessage(); $_mailerror = true; } @@ -327,8 +350,8 @@ class Cronjob $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_CRONRUNS . "` SET `lastrun` = UNIX_TIMESTAMP() WHERE `cronfile` = :cron; "); - Database::pexecute($upd_stmt, array( + Database::pexecute($upd_stmt, [ 'cron' => $cronname - )); + ]); } } diff --git a/lib/Froxlor/System/Crypt.php b/lib/Froxlor/System/Crypt.php index 8ad518cf..391a3782 100644 --- a/lib/Froxlor/System/Crypt.php +++ b/lib/Froxlor/System/Crypt.php @@ -1,8 +1,34 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\System; +use Froxlor\Database\Database; +use Froxlor\Froxlor; use Froxlor\Settings; +use Froxlor\Validate\Validate; class Crypt { @@ -48,7 +74,7 @@ class Crypt private static function specialShuffle($str = null) { $len = mb_strlen($str); - $sploded = array(); + $sploded = []; while ($len-- > 0) { $sploded[] = mb_substr($str, $len, 1); } @@ -56,35 +82,6 @@ class Crypt return join('', $sploded); } - /** - * Make encrypted password from clear text password - * - * @author Michal Wojcik - * @author Michael Kaufmann - * @author Froxlor team (2010-) - * - * 0 - default crypt (depends on system configuration) - * 1 - MD5 $1$ - * 2 - BLOWFISH $2y$07$ - * 3 - SHA-256 $5$ (default) - * 4 - SHA-512 $6$ - * - * @param string $password - * Password to be encrypted - * @param bool $htpasswd - * optional whether to generate a SHA1 password for directory protection - * - * @return string encrypted password - */ - public static function makeCryptPassword($password, $htpasswd = false) - { - if ($htpasswd) { - return '{SHA}' . base64_encode(sha1($password, true)); - } - $algo = Settings::Get('system.passwordcryptfunc') !== null ? Settings::Get('system.passwordcryptfunc') : PASSWORD_DEFAULT; - return password_hash($password, $algo); - } - /** * return an array of available hashes * @@ -95,9 +92,9 @@ class Crypt global $lng; // get available pwd-hases - $available_pwdhashes = array( + $available_pwdhashes = [ PASSWORD_DEFAULT => $lng['serversettings']['systemdefault'] - ); + ]; if (defined('PASSWORD_BCRYPT')) { $available_pwdhashes[PASSWORD_BCRYPT] = 'Bcrypt/Blowfish'; } @@ -119,30 +116,30 @@ class Crypt * an error message will be output and 'exit' is called * * @param string $password - * the password to validate + * the password to validate * * @return string either the password or an errormessage+exit */ public static function validatePassword($password = null, $json_response = false) { if (Settings::Get('panel.password_min_length') > 0) { - $password = \Froxlor\Validate\Validate::validate($password, Settings::Get('panel.password_min_length'), '/^.{' . (int) Settings::Get('panel.password_min_length') . ',}$/D', 'notrequiredpasswordlength', array(), $json_response); + $password = Validate::validate($password, Settings::Get('panel.password_min_length'), '/^.{' . (int)Settings::Get('panel.password_min_length') . ',}$/D', 'notrequiredpasswordlength', [], $json_response); } if (Settings::Get('panel.password_regex') != '') { - $password = \Froxlor\Validate\Validate::validate($password, Settings::Get('panel.password_regex'), Settings::Get('panel.password_regex'), 'notrequiredpasswordcomplexity', array(), $json_response); + $password = Validate::validate($password, Settings::Get('panel.password_regex'), Settings::Get('panel.password_regex'), 'notrequiredpasswordcomplexity', [], $json_response); } else { if (Settings::Get('panel.password_alpha_lower')) { - $password = \Froxlor\Validate\Validate::validate($password, '/.*[a-z]+.*/', '/.*[a-z]+.*/', 'notrequiredpasswordcomplexity', array(), $json_response); + $password = Validate::validate($password, '/.*[a-z]+.*/', '/.*[a-z]+.*/', 'notrequiredpasswordcomplexity', [], $json_response); } if (Settings::Get('panel.password_alpha_upper')) { - $password = \Froxlor\Validate\Validate::validate($password, '/.*[A-Z]+.*/', '/.*[A-Z]+.*/', 'notrequiredpasswordcomplexity', array(), $json_response); + $password = Validate::validate($password, '/.*[A-Z]+.*/', '/.*[A-Z]+.*/', 'notrequiredpasswordcomplexity', [], $json_response); } if (Settings::Get('panel.password_numeric')) { - $password = \Froxlor\Validate\Validate::validate($password, '/.*[0-9]+.*/', '/.*[0-9]+.*/', 'notrequiredpasswordcomplexity', array(), $json_response); + $password = Validate::validate($password, '/.*[0-9]+.*/', '/.*[0-9]+.*/', 'notrequiredpasswordcomplexity', [], $json_response); } if (Settings::Get('panel.password_special_char_required')) { - $password = \Froxlor\Validate\Validate::validate($password, '/.*[' . preg_quote(Settings::Get('panel.password_special_char'), '/') . ']+.*/', '/.*[' . preg_quote(Settings::Get('panel.password_special_char'), '/') . ']+.*/', 'notrequiredpasswordcomplexity', array(), $json_response); + $password = Validate::validate($password, '/.*[' . preg_quote(Settings::Get('panel.password_special_char'), '/') . ']+.*/', '/.*[' . preg_quote(Settings::Get('panel.password_special_char'), '/') . ']+.*/', 'notrequiredpasswordcomplexity', [], $json_response); } } @@ -158,13 +155,13 @@ class Crypt * or if the very old md5() sum is used * * @param array $userinfo - * user-data from table + * user-data from table * @param string $password - * the password to validate + * the password to validate * @param string $table - * either panel_customers or panel_admins + * either panel_customers or panel_admins * @param string $uid - * user-id-field in $table + * user-id-field in $table * * @return boolean */ @@ -187,21 +184,49 @@ class Crypt } if ($pwd_hash == $pwd_check || password_verify($password, $pwd_hash)) { - // check for update of hash (only if our database is ready to handle the bigger string) - $is_ready = \Froxlor\Froxlor::versionCompare2("0.9.33", \Froxlor\Froxlor::getVersion()) <= 0 ; + $is_ready = Froxlor::versionCompare2("0.9.33", Froxlor::getVersion()) <= 0; if ((password_needs_rehash($pwd_hash, $algo) || $update_hash) && $is_ready) { - $upd_stmt = \Froxlor\Database\Database::prepare(" + $upd_stmt = Database::prepare(" UPDATE " . $table . " SET `password` = :newpasswd WHERE `" . $uid . "` = :uid "); - $params = array( + $params = [ 'newpasswd' => self::makeCryptPassword($password), 'uid' => $userinfo[$uid] - ); - \Froxlor\Database\Database::pexecute($upd_stmt, $params); + ]; + Database::pexecute($upd_stmt, $params); } return true; } return false; } + + /** + * Make encrypted password from clear text password + * + * @param string $password + * Password to be encrypted + * @param bool $htpasswd + * optional whether to generate a SHA1 password for directory protection + * + * @return string encrypted password + * @author Michal Wojcik + * @author Michael Kaufmann + * @author Froxlor team (2010-) + * + * 0 - default crypt (depends on system configuration) + * 1 - MD5 $1$ + * 2 - BLOWFISH $2y$07$ + * 3 - SHA-256 $5$ (default) + * 4 - SHA-512 $6$ + * + */ + public static function makeCryptPassword($password, $htpasswd = false) + { + if ($htpasswd) { + return '{SHA}' . base64_encode(sha1($password, true)); + } + $algo = Settings::Get('system.passwordcryptfunc') !== null ? Settings::Get('system.passwordcryptfunc') : PASSWORD_DEFAULT; + return password_hash($password, $algo); + } } diff --git a/lib/Froxlor/System/IPTools.php b/lib/Froxlor/System/IPTools.php index 7ff2d81f..03d8a4d6 100644 --- a/lib/Froxlor/System/IPTools.php +++ b/lib/Froxlor/System/IPTools.php @@ -1,5 +1,28 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\System; class IPTools @@ -25,23 +48,11 @@ class IPTools return implode('.', $netmask); } - /** - * Checks if an $address (IP) is IPv6 - * - * @param string $address - * - * @return string|bool ip address on success, false on failure - */ - public static function is_ipv6($address) - { - return filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6); - } - /** * Checks whether the given $ip is in range of given ip/cidr range * * @param array $ip_cidr 0 => ip, 1 => netmask in decimal, e.g. [0 => '123.123.123.123', 1 => 24] - * @param string $ip ip-address to check + * @param string $ip ip-address to check * * @return bool */ @@ -59,11 +70,23 @@ class IPTools return (($ip_decimal & $netmask_decimal) == ($range_decimal & $netmask_decimal)); } + /** + * Checks if an $address (IP) is IPv6 + * + * @param string $address + * + * @return string|bool ip address on success, false on failure + */ + public static function is_ipv6($address) + { + return filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6); + } + /** * Checks whether the given ipv6 $ip is in range of given ip/cidr range * * @param array $ip_cidr 0 => ip, 1 => netmask in decimal, e.g. [0 => '123:123::1', 1 => 64] - * @param string $ip ip-address to check + * @param string $ip ip-address to check * * @return bool */ @@ -87,12 +110,16 @@ class IPTools $start_result = ''; for ($i = 0; $i < 8; $i++) { $start_result .= substr($start, $i * 4, 4); - if ($i != 7) $start_result .= ':'; + if ($i != 7) { + $start_result .= ':'; + } } $end_result = ''; for ($i = 0; $i < 8; $i++) { $end_result .= substr($end, $i * 4, 4); - if ($i != 7) $end_result .= ':'; + if ($i != 7) { + $end_result .= ':'; + } } $first = self::ip2long6($start_result); @@ -103,19 +130,6 @@ class IPTools return $in_range; } - private static function ip2long6($ip) - { - $ip_n = inet_pton($ip); - $bits = 15; // 16 x 8 bit = 128bit - $ipv6long = ''; - while ($bits >= 0) { - $bin = sprintf("%08b", (ord($ip_n[$bits]))); - $ipv6long = $bin . $ipv6long; - $bits--; - } - return gmp_strval(gmp_init($ipv6long, 2), 10); - } - private static function inet6_expand(string $addr) { // Check if there are segments missing, insert if necessary @@ -123,9 +137,10 @@ class IPTools $part = explode('::', $addr); $part[0] = explode(':', $part[0]); $part[1] = explode(':', $part[1]); - $missing = array(); - for ($i = 0; $i < (8 - (count($part[0]) + count($part[1]))); $i++) + $missing = []; + for ($i = 0; $i < (8 - (count($part[0]) + count($part[1]))); $i++) { array_push($missing, '0000'); + } $missing = array_merge($part[0], $missing); $part = array_merge($missing, $part[1]); } else { @@ -133,7 +148,9 @@ class IPTools } // Pad each segment until it has 4 digits foreach ($part as &$p) { - while (strlen($p) < 4) $p = '0' . $p; + while (strlen($p) < 4) { + $p = '0' . $p; + } } unset($p); // Join segments @@ -150,16 +167,37 @@ class IPTools { /* Make sure the prefix is a number between 1 and 127 (inclusive) */ $prefix = intval($prefix); - if ($prefix < 0 || $prefix > 128) return false; + if ($prefix < 0 || $prefix > 128) { + return false; + } $mask = '0b'; - for ($i = 0; $i < $prefix; $i++) $mask .= '1'; - for ($i = strlen($mask) - 2; $i < 128; $i++) $mask .= '0'; + for ($i = 0; $i < $prefix; $i++) { + $mask .= '1'; + } + for ($i = strlen($mask) - 2; $i < 128; $i++) { + $mask .= '0'; + } $mask = gmp_strval(gmp_init($mask), 16); $result = ''; for ($i = 0; $i < 8; $i++) { $result .= substr($mask, $i * 4, 4); - if ($i != 7) $result .= ':'; + if ($i != 7) { + $result .= ':'; + } } // for return inet_ntop(inet_pton($result)); } + + private static function ip2long6($ip) + { + $ip_n = inet_pton($ip); + $bits = 15; // 16 x 8 bit = 128bit + $ipv6long = ''; + while ($bits >= 0) { + $bin = sprintf("%08b", (ord($ip_n[$bits]))); + $ipv6long = $bin . $ipv6long; + $bits--; + } + return gmp_strval(gmp_init($ipv6long, 2), 10); + } } diff --git a/lib/Froxlor/System/Mailer.php b/lib/Froxlor/System/Mailer.php index 12594a98..d91cc5aa 100644 --- a/lib/Froxlor/System/Mailer.php +++ b/lib/Froxlor/System/Mailer.php @@ -1,16 +1,41 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\System; use Froxlor\Settings; +use PHPMailer\PHPMailer\PHPMailer; -class Mailer extends \PHPMailer\PHPMailer\PHPMailer +class Mailer extends PHPMailer { /** * class constructor * * @param string $exceptions - * whether to throw exceptions or not + * whether to throw exceptions or not * */ public function __construct($exceptions = false) diff --git a/lib/Froxlor/System/MysqlHandler.php b/lib/Froxlor/System/MysqlHandler.php index 1703d34a..c5067b4d 100644 --- a/lib/Froxlor/System/MysqlHandler.php +++ b/lib/Froxlor/System/MysqlHandler.php @@ -1,15 +1,38 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\System; +use Froxlor\Database\Database; use Monolog\Handler\AbstractProcessingHandler; use Monolog\Logger; class MysqlHandler extends AbstractProcessingHandler { - protected $pdoStatement = null; - - protected static $froxlorLevels = array( + protected static $froxlorLevels = [ Logger::DEBUG => LOG_DEBUG, Logger::INFO => LOG_INFO, Logger::NOTICE => LOG_NOTICE, @@ -18,13 +41,14 @@ class MysqlHandler extends AbstractProcessingHandler Logger::CRITICAL => LOG_ERR, Logger::ALERT => LOG_ERR, Logger::EMERGENCY => LOG_ERR - ); + ]; + protected $pdoStatement = null; /** * Constructor * * @param bool|int $level - * Debug level which this handler should store + * Debug level which this handler should store * @param bool $bubble */ public function __construct($level = Logger::DEBUG, $bubble = true) @@ -32,21 +56,6 @@ class MysqlHandler extends AbstractProcessingHandler parent::__construct($level, $bubble); } - /** - * Insert the data to the logger table - * - * @param array $data - * @return bool - */ - protected function insert(array $data) - { - if ($this->pdoStatement === null) { - $sql = "INSERT INTO `panel_syslog` SET `text` = :message, `user` = :contextUser, `action` = :contextAction, `type` = :level, `date` = :datetime"; - $this->pdoStatement = \Froxlor\Database\Database::prepare($sql); - } - return $this->pdoStatement->execute($data); - } - /** * Writes the record down to the log * @@ -63,4 +72,19 @@ class MysqlHandler extends AbstractProcessingHandler ':datetime' => $record['datetime']->format('U') ]); } + + /** + * Insert the data to the logger table + * + * @param array $data + * @return bool + */ + protected function insert(array $data) + { + if ($this->pdoStatement === null) { + $sql = "INSERT INTO `panel_syslog` SET `text` = :message, `user` = :contextUser, `action` = :contextAction, `type` = :level, `date` = :datetime"; + $this->pdoStatement = Database::prepare($sql); + } + return $this->pdoStatement->execute($data); + } } diff --git a/lib/Froxlor/UI/Callbacks/Admin.php b/lib/Froxlor/UI/Callbacks/Admin.php index c8d5e79e..26c22203 100644 --- a/lib/Froxlor/UI/Callbacks/Admin.php +++ b/lib/Froxlor/UI/Callbacks/Admin.php @@ -1,23 +1,32 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Froxlor\UI\Callbacks + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\UI\Callbacks; + +use Froxlor\UI\Panel\UI; + class Admin { public static function canChangeServerSettings(array $attributes) diff --git a/lib/Froxlor/UI/Callbacks/Customer.php b/lib/Froxlor/UI/Callbacks/Customer.php index 33d529bc..315abf97 100644 --- a/lib/Froxlor/UI/Callbacks/Customer.php +++ b/lib/Froxlor/UI/Callbacks/Customer.php @@ -1,23 +1,32 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Froxlor\UI\Callbacks + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\UI\Callbacks; + +use Froxlor\Settings; + class Customer { public static function isLocked(array $attributes) diff --git a/lib/Froxlor/UI/Callbacks/Dns.php b/lib/Froxlor/UI/Callbacks/Dns.php index 6ccb3a91..ea576b7b 100644 --- a/lib/Froxlor/UI/Callbacks/Dns.php +++ b/lib/Froxlor/UI/Callbacks/Dns.php @@ -1,21 +1,30 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Froxlor\UI\Callbacks + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\UI\Callbacks; + class Dns { public static function prio(array $attributes): string diff --git a/lib/Froxlor/UI/Callbacks/Domain.php b/lib/Froxlor/UI/Callbacks/Domain.php index 942d42b0..ad72856f 100644 --- a/lib/Froxlor/UI/Callbacks/Domain.php +++ b/lib/Froxlor/UI/Callbacks/Domain.php @@ -1,26 +1,35 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Froxlor\UI\Callbacks + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\UI\Callbacks; + +use Froxlor\Domain\Domain as DDomain; +use Froxlor\FileDir; +use Froxlor\Settings; +use Froxlor\UI\Panel\UI; + class Domain { public static function domainWithCustomerLink(array $attributes) @@ -28,12 +37,12 @@ class Domain $linker = UI::getLinker(); $result = '' . $attributes['data'] . ''; $result .= ' (' . $attributes['fields']['loginname'] . ')'; + 'section' => 'customers', + 'page' => 'customers', + 'action' => 'su', + 'sort' => $attributes['fields']['loginname'], + 'id' => $attributes['fields']['customerid'], + ]) . '">' . $attributes['fields']['loginname'] . ')'; return $result; } @@ -65,7 +74,7 @@ class Domain { $result = '' . $attributes['data'] . ''; // check for statistics if parentdomainid==0 to show stats-link for customers - if ((int) UI::getCurrentUser()['adminsession'] == 0 && $attributes['fields']['parentdomainid'] == 0) { + if ((int)UI::getCurrentUser()['adminsession'] == 0 && $attributes['fields']['parentdomainid'] == 0) { $statsapp = 'webalizer'; if (Settings::Get('system.awstats_enabled') == '1') { $statsapp = 'awstats'; @@ -89,9 +98,9 @@ class Domain public static function canViewLogs(array $attributes): bool { if ((int)$attributes['fields']['email_only'] == 0) { - if ((int) UI::getCurrentUser()['adminsession'] == 0 && (bool)UI::getCurrentUser()['logviewenabled']) { + if ((int)UI::getCurrentUser()['adminsession'] == 0 && (bool)UI::getCurrentUser()['logviewenabled']) { return true; - } elseif ((int) UI::getCurrentUser()['adminsession'] == 1) { + } elseif ((int)UI::getCurrentUser()['adminsession'] == 1) { return true; } } @@ -129,13 +138,12 @@ class Domain public static function hasLetsEncryptActivated(array $attributes): bool { - return ((bool) $attributes['fields']['letsencrypt'] && (int)$attributes['fields']['email_only'] == 0); + return ((bool)$attributes['fields']['letsencrypt'] && (int)$attributes['fields']['email_only'] == 0); } public static function canEditSSL(array $attributes): bool { - if ( - Settings::Get('system.use_ssl') == '1' + if (Settings::Get('system.use_ssl') == '1' && DDomain::domainHasSslIpPort($attributes['fields']['id']) && (int)$attributes['fields']['caneditdomain'] == 1 && (int)$attributes['fields']['letsencrypt'] == 0 diff --git a/lib/Froxlor/UI/Callbacks/Email.php b/lib/Froxlor/UI/Callbacks/Email.php index b22642ae..34449b46 100644 --- a/lib/Froxlor/UI/Callbacks/Email.php +++ b/lib/Froxlor/UI/Callbacks/Email.php @@ -1,24 +1,33 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\UI\Callbacks; use Froxlor\PhpHelper; 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 - * - * @copyright (c) the authors - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Froxlor\UI\Callbacks - * - */ class Email { public static function account(array $attributes) diff --git a/lib/Froxlor/UI/Callbacks/Ftp.php b/lib/Froxlor/UI/Callbacks/Ftp.php index 0f49da52..474550cc 100644 --- a/lib/Froxlor/UI/Callbacks/Ftp.php +++ b/lib/Froxlor/UI/Callbacks/Ftp.php @@ -1,24 +1,33 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\UI\Callbacks; use Froxlor\FileDir; use Froxlor\UI\Panel\UI; -/** - * 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 - * - * @copyright (c) the authors - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Froxlor\UI\Callbacks - * - */ class Ftp { public static function pathRelative(array $attributes): string diff --git a/lib/Froxlor/UI/Callbacks/Impersonate.php b/lib/Froxlor/UI/Callbacks/Impersonate.php index 74d4f557..f5624e08 100644 --- a/lib/Froxlor/UI/Callbacks/Impersonate.php +++ b/lib/Froxlor/UI/Callbacks/Impersonate.php @@ -1,26 +1,67 @@ (2010-) - * @author Maurice Preuß - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Froxlor\UI\Callbacks + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\UI\Callbacks; + +use Froxlor\UI\Panel\UI; + class Impersonate { + public static function apiAdminCustomerLink(array $attributes) + { + // my own key + $isMyKey = false; + if ($attributes['fields']['adminid'] == UI::getCurrentUser()['adminid'] + && ((AREA == 'admin' && $attributes['fields']['customerid'] == 0) + || (AREA == 'customer' && $attributes['fields']['customerid'] == UI::getCurrentUser()['customerid']) + ) + ) { + // this is mine + $isMyKey = true; + } + + $adminCustomerLink = ""; + if (AREA == 'admin') { + if ($isMyKey) { + $adminCustomerLink = $attributes['fields']['adminname']; + } else { + if (empty($attributes['fields']['customerid'])) { + $adminCustomerLink = self::admin($attributes); + } else { + $attributes['data'] = $attributes['fields']['loginname']; + $adminCustomerLink = self::customer($attributes); + } + } + } else { + // customer do not need links + $adminCustomerLink = $attributes['fields']['loginname']; + } + + return $adminCustomerLink; + } + public static function admin(array $attributes) { if (UI::getCurrentUser()['adminid'] != $attributes['fields']['adminid']) { @@ -58,38 +99,4 @@ class Impersonate ] ]; } - - public static function apiAdminCustomerLink(array $attributes) - { - // my own key - $isMyKey = false; - if ( - $attributes['fields']['adminid'] == UI::getCurrentUser()['adminid'] - && ((AREA == 'admin' && $attributes['fields']['customerid'] == 0) - || (AREA == 'customer' && $attributes['fields']['customerid'] == UI::getCurrentUser()['customerid']) - ) - ) { - // this is mine - $isMyKey = true; - } - - $adminCustomerLink = ""; - if (AREA == 'admin') { - if ($isMyKey) { - $adminCustomerLink = $attributes['fields']['adminname']; - } else { - if (empty($attributes['fields']['customerid'])) { - $adminCustomerLink = self::admin($attributes); - } else { - $attributes['data'] = $attributes['fields']['loginname']; - $adminCustomerLink = self::customer($attributes); - } - } - } else { - // customer do not need links - $adminCustomerLink = $attributes['fields']['loginname']; - } - - return $adminCustomerLink; - } } diff --git a/lib/Froxlor/UI/Callbacks/Mysql.php b/lib/Froxlor/UI/Callbacks/Mysql.php index cd58d436..3ab42b6e 100644 --- a/lib/Froxlor/UI/Callbacks/Mysql.php +++ b/lib/Froxlor/UI/Callbacks/Mysql.php @@ -1,23 +1,32 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Froxlor\UI\Callbacks + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\UI\Callbacks; + +use Froxlor\Database\Database; + class Mysql { public static function dbserver(array $attributes): string diff --git a/lib/Froxlor/UI/Callbacks/PHPConf.php b/lib/Froxlor/UI/Callbacks/PHPConf.php index 8b3cfc6d..28ac3d94 100644 --- a/lib/Froxlor/UI/Callbacks/PHPConf.php +++ b/lib/Froxlor/UI/Callbacks/PHPConf.php @@ -1,24 +1,33 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\UI\Callbacks; use Froxlor\Idna\IdnaWrapper; use Froxlor\UI\Panel\UI; -/** - * 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 - * - * @copyright (c) the authors - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Froxlor\UI\Callbacks - * - */ class PHPConf { public static function domainList(array $attributes): string diff --git a/lib/Froxlor/UI/Callbacks/ProgressBar.php b/lib/Froxlor/UI/Callbacks/ProgressBar.php index fc012176..64b24fcb 100644 --- a/lib/Froxlor/UI/Callbacks/ProgressBar.php +++ b/lib/Froxlor/UI/Callbacks/ProgressBar.php @@ -1,26 +1,34 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\UI\Callbacks; use Froxlor\PhpHelper; use Froxlor\Settings; use Froxlor\UI\Panel\UI; -/** - * 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 - * - * @copyright (c) the authors - * @author Froxlor team (2010-) - * @author Maurice Preuß - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Froxlor\UI\Callbacks - * - */ class ProgressBar { /** @@ -42,17 +50,6 @@ class ProgressBar return self::pbData('diskspace', $attributes['fields'], 1024, (int)Settings::Get('system.report_webmax'), $infotext); } - /** - * get progressbar data for traffic - * - * @param array $attributes['fields'] - * @return array - */ - public static function traffic(array $attributes): array - { - return self::pbData('traffic', $attributes['fields'], 1024, (int)Settings::Get('system.report_trafficmax')); - } - /** * do needed calculations */ @@ -84,4 +81,15 @@ class ProgressBar ] ]; } + + /** + * get progressbar data for traffic + * + * @param array $attributes ['fields'] + * @return array + */ + public static function traffic(array $attributes): array + { + return self::pbData('traffic', $attributes['fields'], 1024, (int)Settings::Get('system.report_trafficmax')); + } } diff --git a/lib/Froxlor/UI/Callbacks/SSLCertificate.php b/lib/Froxlor/UI/Callbacks/SSLCertificate.php index 31acc7fd..89a07b1b 100644 --- a/lib/Froxlor/UI/Callbacks/SSLCertificate.php +++ b/lib/Froxlor/UI/Callbacks/SSLCertificate.php @@ -1,22 +1,30 @@ (2010-) - * @author Maurice Preuß - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Froxlor\UI\Callbacks + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\UI\Callbacks; + class SSLCertificate { public static function domainWithSan(array $attributes): array diff --git a/lib/Froxlor/UI/Callbacks/Style.php b/lib/Froxlor/UI/Callbacks/Style.php index 6ff1ea9a..a7211e1d 100644 --- a/lib/Froxlor/UI/Callbacks/Style.php +++ b/lib/Froxlor/UI/Callbacks/Style.php @@ -1,27 +1,32 @@ (2010-) - * @author Maurice Preuß - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Froxlor\UI\Callbacks + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\UI\Callbacks; + +use Froxlor\Settings; + class Style { public static function deactivated(array $attributes): string @@ -66,11 +71,6 @@ class Style return self::getWarningStyle('diskspace', $attributes['fields'], (int)Settings::Get('system.report_webmax')); } - public static function trafficWarning(array $attributes): string - { - return self::getWarningStyle('traffic', $attributes['fields'], (int)Settings::Get('system.report_trafficmax')); - } - private static function getWarningStyle(string $field, array $attributes, int $report_max = 90): string { $style = ''; @@ -83,4 +83,9 @@ class Style } return $style; } + + public static function trafficWarning(array $attributes): string + { + return self::getWarningStyle('traffic', $attributes['fields'], (int)Settings::Get('system.report_trafficmax')); + } } diff --git a/lib/Froxlor/UI/Callbacks/SysLog.php b/lib/Froxlor/UI/Callbacks/SysLog.php index 52cc12b0..2b7c96d1 100644 --- a/lib/Froxlor/UI/Callbacks/SysLog.php +++ b/lib/Froxlor/UI/Callbacks/SysLog.php @@ -1,28 +1,37 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Froxlor\UI\Callbacks + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\UI\Callbacks; + +use Froxlor\FroxlorLogger; + class SysLog { public static function typeDescription(array $attributes): string { - return FroxlorLogger::getInstanceOf()->getLogLevelDesc($attributes['data']); + return FroxlorLogger::getInstanceOf()->getLogLevelDesc($attributes['data']); } } diff --git a/lib/Froxlor/UI/Callbacks/Text.php b/lib/Froxlor/UI/Callbacks/Text.php index 6f1c3156..ab2762b9 100644 --- a/lib/Froxlor/UI/Callbacks/Text.php +++ b/lib/Froxlor/UI/Callbacks/Text.php @@ -1,27 +1,35 @@ (2010-) - * @author Maurice Preuß - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Froxlor\UI\Callbacks + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\UI\Callbacks; + +use Froxlor\Froxlor; +use Froxlor\PhpHelper; +use Froxlor\UI\Panel\UI; +use Froxlor\User; + class Text { public static function boolean(array $attributes): array @@ -73,8 +81,8 @@ class Text $result = $attributes['fields']; $apikey_data = include Froxlor::getInstallDir() . '/lib/formfields/formfield.api_key.php'; - $body = UI::twig()->render(UI::getTheme().'/user/inline-form.html.twig', [ - 'formaction' => $linker->getLink(array('section' => 'index', 'page' => 'apikeys')), + $body = UI::twig()->render(UI::getTheme() . '/user/inline-form.html.twig', [ + 'formaction' => $linker->getLink(['section' => 'index', 'page' => 'apikeys']), 'formdata' => $apikey_data['apikey'], 'editid' => $attributes['fields']['id'] ]); diff --git a/lib/Froxlor/UI/Collection.php b/lib/Froxlor/UI/Collection.php index eeb18b7b..6d5ef9d9 100644 --- a/lib/Froxlor/UI/Collection.php +++ b/lib/Froxlor/UI/Collection.php @@ -1,24 +1,32 @@ (2010-) - * @author Maurice Preuß - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Collection + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\UI; + +use Froxlor\Settings; + class Collection { private string $class; @@ -34,14 +42,14 @@ class Collection $this->userinfo = $userInfo; } - private function getListing($class, $params): array + public function getList(): array { - return json_decode($class::getLocal($this->userinfo, $params)->listing(), true); + return $this->getData()['list']; } - public function count(): int + public function getData(): array { - return json_decode($this->class::getLocal($this->userinfo, $this->params)->listingCount(), true)['data']; + return $this->get()['data']; } public function get(): array @@ -71,14 +79,9 @@ class Collection return $result; } - public function getData(): array + private function getListing($class, $params): array { - return $this->get()['data']; - } - - public function getList(): array - { - return $this->getData()['list']; + return json_decode($class::getLocal($this->userinfo, $params)->listing(), true); } public function getJson(): string @@ -119,12 +122,17 @@ class Collection */ // Prepare pagination - $this->pagination = new Pagination($columns, $this->count(), (int) Settings::Get('panel.paging')); + $this->pagination = new Pagination($columns, $this->count(), (int)Settings::Get('panel.paging')); $this->params = array_merge($this->params, $this->pagination->getApiCommandParams()); return $this; } + public function count(): int + { + return json_decode($this->class::getLocal($this->userinfo, $this->params)->listingCount(), true)['data']; + } + public function getPagination(): ?Pagination { return $this->pagination; diff --git a/lib/Froxlor/UI/Data.php b/lib/Froxlor/UI/Data.php index 0fce9c67..185a988f 100644 --- a/lib/Froxlor/UI/Data.php +++ b/lib/Froxlor/UI/Data.php @@ -1,5 +1,28 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\UI; class Data @@ -10,11 +33,6 @@ class Data return self::getFormFieldDataText($fieldname, $fielddata, $input); } - public static function getFormFieldDataUrl($fieldname, $fielddata, $input) - { - return self::getFormFieldDataText($fieldname, $fielddata, $input); - } - public static function getFormFieldDataText($fieldname, $fielddata, $input) { if (isset($input[$fieldname])) { @@ -26,6 +44,11 @@ class Data return $newfieldvalue; } + public static function getFormFieldDataUrl($fieldname, $fielddata, $input) + { + return self::getFormFieldDataText($fieldname, $fielddata, $input); + } + public static function getFormFieldDataSelect($fieldname, $fielddata, $input) { if (isset($input[$fieldname])) { @@ -44,9 +67,9 @@ class Data public static function getFormFieldDataNumber($fieldname, $fielddata, $input) { if (isset($input[$fieldname])) { - $newfieldvalue = (int) $input[$fieldname]; + $newfieldvalue = (int)$input[$fieldname]; } else { - $newfieldvalue = (int) $fielddata['default']; + $newfieldvalue = (int)$fielddata['default']; } return $newfieldvalue; diff --git a/lib/Froxlor/UI/Form.php b/lib/Froxlor/UI/Form.php index d56ec2a7..63f1ad52 100644 --- a/lib/Froxlor/UI/Form.php +++ b/lib/Froxlor/UI/Form.php @@ -1,8 +1,32 @@ + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + namespace Froxlor\UI; use Froxlor\Settings; +use Froxlor\Validate\Check; class Form { @@ -13,7 +37,7 @@ class Form if (\Froxlor\Validate\Form::validateFormDefinition($form)) { foreach ($form['groups'] as $groupname => $groupdetails) { // check for advanced mode sections - if (isset($groupdetails['advanced_mode']) && $groupdetails['advanced_mode'] && (int) Settings::Get('panel.settings_mode') == 0) { + if (isset($groupdetails['advanced_mode']) && $groupdetails['advanced_mode'] && (int)Settings::Get('panel.settings_mode') == 0) { continue; } // show overview @@ -53,7 +77,7 @@ class Form // Collect form field output foreach ($groupdetails['fields'] as $fieldname => $fielddetails) { // check for advanced mode sections - if (isset($fielddetails['advanced_mode']) && $fielddetails['advanced_mode'] && (int) Settings::Get('panel.settings_mode') == 0) { + if (isset($fielddetails['advanced_mode']) && $fielddetails['advanced_mode'] && (int)Settings::Get('panel.settings_mode') == 0) { continue; } $fields[$fieldname] = self::getFormFieldOutput($fieldname, $fielddetails); @@ -67,148 +91,6 @@ class Form return $fields; } - public static function processForm(&$form, &$input, $url_params = array(), $part = null, $settings_all = array(), $settings_part = null, $only_enabledisable = false) - { - if (\Froxlor\Validate\Form::validateFormDefinition($form)) { - $submitted_fields = array(); - $changed_fields = array(); - $saved_fields = array(); - - foreach ($form['groups'] as $groupname => $groupdetails) { - if (($settings_part && $part == $groupname) || $settings_all || $only_enabledisable) { - if (\Froxlor\Validate\Form::validateFieldDefinition($groupdetails)) { - // Prefetch form fields - foreach ($groupdetails['fields'] as $fieldname => $fielddetails) { - if (!$only_enabledisable || ($only_enabledisable && isset($fielddetails['overview_option']))) { - $groupdetails['fields'][$fieldname] = self::arrayMergePrefix($fielddetails, $fielddetails['type'], self::prefetchFormFieldData($fieldname, $fielddetails)); - $form['groups'][$groupname]['fields'][$fieldname] = $groupdetails['fields'][$fieldname]; - } - } - } - } - } - - foreach ($form['groups'] as $groupname => $groupdetails) { - if (($settings_part && $part == $groupname) || $settings_all || $only_enabledisable) { - if (\Froxlor\Validate\Form::validateFieldDefinition($groupdetails)) { - // Validate fields - foreach ($groupdetails['fields'] as $fieldname => $fielddetails) { - if (!$only_enabledisable || ($only_enabledisable && isset($fielddetails['overview_option']))) { - $newfieldvalue = self::getFormFieldData($fieldname, $fielddetails, $input); - if ($newfieldvalue != $fielddetails['value']) { - if (($error = \Froxlor\Validate\Form::validateFormField($fieldname, $fielddetails, $newfieldvalue)) != true) { - \Froxlor\UI\Response::standard_error($error, $fieldname); - } else { - $changed_fields[$fieldname] = $newfieldvalue; - } - } - - $submitted_fields[$fieldname] = $newfieldvalue; - } - } - } - } - } - - foreach ($form['groups'] as $groupname => $groupdetails) { - if (($settings_part && $part == $groupname) || $settings_all || $only_enabledisable) { - if (\Froxlor\Validate\Form::validateFieldDefinition($groupdetails)) { - // Check fields for plausibility - foreach ($groupdetails['fields'] as $fieldname => $fielddetails) { - if (!$only_enabledisable || ($only_enabledisable && isset($fielddetails['overview_option']))) { - if (($plausibility_check = self::checkPlausibilityFormField($fieldname, $fielddetails, $submitted_fields[$fieldname], $submitted_fields)) !== false) { - if (is_array($plausibility_check) && isset($plausibility_check[0])) { - if ($plausibility_check[0] == \Froxlor\Validate\Check::FORMFIELDS_PLAUSIBILITY_CHECK_OK) { - // Nothing to do here, everything's okay - } elseif ($plausibility_check[0] == \Froxlor\Validate\Check::FORMFIELDS_PLAUSIBILITY_CHECK_ERROR) { - unset($plausibility_check[0]); - $error = $plausibility_check[1]; - unset($plausibility_check[1]); - $targetname = implode(' ', $plausibility_check); - \Froxlor\UI\Response::standard_error($error, $targetname); - } elseif ($plausibility_check[0] == \Froxlor\Validate\Check::FORMFIELDS_PLAUSIBILITY_CHECK_QUESTION) { - unset($plausibility_check[0]); - $question = $plausibility_check[1]; - unset($plausibility_check[1]); - $targetname = implode(' ', $plausibility_check); - if (!isset($input[$question])) { - if (is_array($url_params) && isset($url_params['filename'])) { - $filename = $url_params['filename']; - unset($url_params['filename']); - } else { - $filename = ''; - } - \Froxlor\UI\HTML::askYesNo($question, $filename, array_merge($url_params, $submitted_fields, array( - $question => $question - )), $targetname); - } - } else { - \Froxlor\UI\Response::standard_error('plausibilitychecknotunderstood'); - } - } - } - } - } - } - } - } - - foreach ($form['groups'] as $groupname => $groupdetails) { - if (($settings_part && $part == $groupname) || $settings_all || $only_enabledisable) { - if (\Froxlor\Validate\Form::validateFieldDefinition($groupdetails)) { - // Save fields - foreach ($groupdetails['fields'] as $fieldname => $fielddetails) { - if (!$only_enabledisable || ($only_enabledisable && isset($fielddetails['overview_option']))) { - if (isset($changed_fields[$fieldname])) { - if (($saved_field = self::saveFormField($fieldname, $fielddetails, self::manipulateFormFieldData($fieldname, $fielddetails, $changed_fields[$fieldname]))) !== false) { - $saved_fields = array_merge($saved_fields, $saved_field); - } else { - \Froxlor\UI\Response::standard_error('errorwhensaving', $fieldname); - } - } - } - } - } - } - } - - // Save form - return self::saveForm($form, $saved_fields); - } - } - - public static function saveForm($fielddata, $newfieldvalue) - { - $returnvalue = ''; - if (is_array($fielddata) && isset($fielddata['save_method']) && $fielddata['save_method'] != '') { - $returnvalue = call_user_func(array( - '\\Froxlor\\Settings\\Store', - $fielddata['save_method'] - ), $fielddata, $newfieldvalue); - } elseif (is_array($fielddata) && !isset($fielddata['save_method'])) { - $returnvalue = true; - } else { - $returnvalue = false; - } - return $returnvalue; - } - - public static function saveFormField($fieldname, $fielddata, $newfieldvalue) - { - $returnvalue = ''; - if (is_array($fielddata) && isset($fielddata['save_method']) && $fielddata['save_method'] != '') { - $returnvalue = call_user_func(array( - '\\Froxlor\\Settings\\Store', - $fielddata['save_method'] - ), $fieldname, $fielddata, $newfieldvalue); - } elseif (is_array($fielddata) && !isset($fielddata['save_method'])) { - $returnvalue = array(); - } else { - $returnvalue = false; - } - return $returnvalue; - } - public static function getFormOverviewGroupOutput($groupname, $groupdetails) { global $lng; @@ -220,9 +102,9 @@ class Form if ($fielddetails['type'] != 'checkbox') { // throw exception here as this is most likely an internal issue // if we messed up the arrays - \Froxlor\UI\Response::standard_error('overviewsettingoptionisnotavalidfield', '', true); + Response::standardError('overviewsettingoptionisnotavalidfield', '', true); } - $activated = (int) Settings::Get($fielddetails['settinggroup'] . '.' . $fielddetails['varname']); + $activated = (int)Settings::Get($fielddetails['settinggroup'] . '.' . $fielddetails['varname']); break; } } @@ -257,7 +139,6 @@ class Form $returnvalue = []; if (is_array($fielddata) && isset($fielddata['type']) && $fielddata['type'] != '') { - if (!isset($fielddata['value'])) { if (isset($fielddata['default'])) { $fielddata['value'] = $fielddata['default']; @@ -273,7 +154,7 @@ class Form unset($fielddata['value']); break; case 'checkbox': - $fielddata['checked'] = (bool) $fielddata['value']; + $fielddata['checked'] = (bool)$fielddata['value']; $fielddata['value'] = 1; break; } @@ -314,9 +195,8 @@ class Form public static function prefetchFormFieldData($fieldname, $fielddata) { - $returnvalue = array(); + $returnvalue = []; if (is_array($fielddata) && isset($fielddata['type']) && $fielddata['type'] == 'select') { - if ((!isset($fielddata['select_var']) || !is_array($fielddata['select_var']) || empty($fielddata['select_var'])) && (isset($fielddata['option_options_method']))) { $returnvalue['select_var'] = call_user_func($fielddata['option_options_method']); } @@ -324,47 +204,114 @@ class Form return $returnvalue; } - public static function getFormFieldData($fieldname, $fielddata, &$input) + public static function processForm(&$form, &$input, $url_params = [], $part = null, $settings_all = [], $settings_part = null, $only_enabledisable = false) { - if (is_array($fielddata) && isset($fielddata['type']) && $fielddata['type'] != '' && method_exists('\\Froxlor\\UI\\Data', 'getFormFieldData' . ucfirst($fielddata['type']))) { - $newfieldvalue = call_user_func(array( - '\\Froxlor\\UI\\Data', - 'getFormFieldData' . ucfirst($fielddata['type']) - ), $fieldname, $fielddata, $input); - } else { - if (isset($input[$fieldname])) { - $newfieldvalue = $input[$fieldname]; - } elseif (isset($fielddata['default'])) { - $newfieldvalue = $fielddata['default']; - } else { - $newfieldvalue = false; + if (\Froxlor\Validate\Form::validateFormDefinition($form)) { + $submitted_fields = []; + $changed_fields = []; + $saved_fields = []; + + foreach ($form['groups'] as $groupname => $groupdetails) { + if (($settings_part && $part == $groupname) || $settings_all || $only_enabledisable) { + if (\Froxlor\Validate\Form::validateFieldDefinition($groupdetails)) { + // Prefetch form fields + foreach ($groupdetails['fields'] as $fieldname => $fielddetails) { + if (!$only_enabledisable || ($only_enabledisable && isset($fielddetails['overview_option']))) { + $groupdetails['fields'][$fieldname] = self::arrayMergePrefix($fielddetails, $fielddetails['type'], self::prefetchFormFieldData($fieldname, $fielddetails)); + $form['groups'][$groupname]['fields'][$fieldname] = $groupdetails['fields'][$fieldname]; + } + } + } + } } + + foreach ($form['groups'] as $groupname => $groupdetails) { + if (($settings_part && $part == $groupname) || $settings_all || $only_enabledisable) { + if (\Froxlor\Validate\Form::validateFieldDefinition($groupdetails)) { + // Validate fields + foreach ($groupdetails['fields'] as $fieldname => $fielddetails) { + if (!$only_enabledisable || ($only_enabledisable && isset($fielddetails['overview_option']))) { + $newfieldvalue = self::getFormFieldData($fieldname, $fielddetails, $input); + if ($newfieldvalue != $fielddetails['value']) { + if (($error = \Froxlor\Validate\Form::validateFormField($fieldname, $fielddetails, $newfieldvalue)) != true) { + Response::standardError($error, $fieldname); + } else { + $changed_fields[$fieldname] = $newfieldvalue; + } + } + + $submitted_fields[$fieldname] = $newfieldvalue; + } + } + } + } + } + + foreach ($form['groups'] as $groupname => $groupdetails) { + if (($settings_part && $part == $groupname) || $settings_all || $only_enabledisable) { + if (\Froxlor\Validate\Form::validateFieldDefinition($groupdetails)) { + // Check fields for plausibility + foreach ($groupdetails['fields'] as $fieldname => $fielddetails) { + if (!$only_enabledisable || ($only_enabledisable && isset($fielddetails['overview_option']))) { + if (($plausibility_check = self::checkPlausibilityFormField($fieldname, $fielddetails, $submitted_fields[$fieldname], $submitted_fields)) !== false) { + if (is_array($plausibility_check) && isset($plausibility_check[0])) { + if ($plausibility_check[0] == Check::FORMFIELDS_PLAUSIBILITY_CHECK_OK) { + // Nothing to do here, everything's okay + } elseif ($plausibility_check[0] == Check::FORMFIELDS_PLAUSIBILITY_CHECK_ERROR) { + unset($plausibility_check[0]); + $error = $plausibility_check[1]; + unset($plausibility_check[1]); + $targetname = implode(' ', $plausibility_check); + Response::standardError($error, $targetname); + } elseif ($plausibility_check[0] == Check::FORMFIELDS_PLAUSIBILITY_CHECK_QUESTION) { + unset($plausibility_check[0]); + $question = $plausibility_check[1]; + unset($plausibility_check[1]); + $targetname = implode(' ', $plausibility_check); + if (!isset($input[$question])) { + if (is_array($url_params) && isset($url_params['filename'])) { + $filename = $url_params['filename']; + unset($url_params['filename']); + } else { + $filename = ''; + } + HTML::askYesNo($question, $filename, array_merge($url_params, $submitted_fields, [ + $question => $question + ]), $targetname); + } + } else { + Response::standardError('plausibilitychecknotunderstood'); + } + } + } + } + } + } + } + } + + foreach ($form['groups'] as $groupname => $groupdetails) { + if (($settings_part && $part == $groupname) || $settings_all || $only_enabledisable) { + if (\Froxlor\Validate\Form::validateFieldDefinition($groupdetails)) { + // Save fields + foreach ($groupdetails['fields'] as $fieldname => $fielddetails) { + if (!$only_enabledisable || ($only_enabledisable && isset($fielddetails['overview_option']))) { + if (isset($changed_fields[$fieldname])) { + if (($saved_field = self::saveFormField($fieldname, $fielddetails, self::manipulateFormFieldData($fieldname, $fielddetails, $changed_fields[$fieldname]))) !== false) { + $saved_fields = array_merge($saved_fields, $saved_field); + } else { + Response::standardError('errorwhensaving', $fieldname); + } + } + } + } + } + } + } + + // Save form + return self::saveForm($form, $saved_fields); } - - return trim($newfieldvalue); - } - - public static function manipulateFormFieldData($fieldname, $fielddata, $newfieldvalue) - { - if (is_array($fielddata) && isset($fielddata['type']) && $fielddata['type'] != '' && method_exists('\\Froxlor\\UI\\Data', 'manipulateFormFieldData' . ucfirst($fielddata['type']))) { - $newfieldvalue = call_user_func(array( - '\\Froxlor\\UI\\Data', - 'manipulateFormFieldData' . ucfirst($fielddata['type']) - ), $fieldname, $fielddata, $newfieldvalue); - } - - return $newfieldvalue; - } - - public static function checkPlausibilityFormField($fieldname, $fielddata, $newfieldvalue, $allnewfieldvalues) - { - $returnvalue = ''; - if (is_array($fielddata) && isset($fielddata['plausibility_check_method']) && $fielddata['plausibility_check_method'] != '' && method_exists($fielddata['plausibility_check_method'][0], $fielddata['plausibility_check_method'][1])) { - $returnvalue = call_user_func($fielddata['plausibility_check_method'], $fieldname, $fielddata, $newfieldvalue, $allnewfieldvalues); - } else { - $returnvalue = false; - } - return $returnvalue; } private static function arrayMergePrefix($array1, $key_prefix, $array2) @@ -384,4 +331,79 @@ class Form return $array1; } } + + public static function getFormFieldData($fieldname, $fielddata, &$input) + { + if (is_array($fielddata) && isset($fielddata['type']) && $fielddata['type'] != '' && method_exists('\\Froxlor\\UI\\Data', 'getFormFieldData' . ucfirst($fielddata['type']))) { + $newfieldvalue = call_user_func([ + '\\Froxlor\\UI\\Data', + 'getFormFieldData' . ucfirst($fielddata['type']) + ], $fieldname, $fielddata, $input); + } else { + if (isset($input[$fieldname])) { + $newfieldvalue = $input[$fieldname]; + } elseif (isset($fielddata['default'])) { + $newfieldvalue = $fielddata['default']; + } else { + $newfieldvalue = false; + } + } + + return trim($newfieldvalue); + } + + public static function checkPlausibilityFormField($fieldname, $fielddata, $newfieldvalue, $allnewfieldvalues) + { + $returnvalue = ''; + if (is_array($fielddata) && isset($fielddata['plausibility_check_method']) && $fielddata['plausibility_check_method'] != '' && method_exists($fielddata['plausibility_check_method'][0], $fielddata['plausibility_check_method'][1])) { + $returnvalue = call_user_func($fielddata['plausibility_check_method'], $fieldname, $fielddata, $newfieldvalue, $allnewfieldvalues); + } else { + $returnvalue = false; + } + return $returnvalue; + } + + public static function saveFormField($fieldname, $fielddata, $newfieldvalue) + { + $returnvalue = ''; + if (is_array($fielddata) && isset($fielddata['save_method']) && $fielddata['save_method'] != '') { + $returnvalue = call_user_func([ + '\\Froxlor\\Settings\\Store', + $fielddata['save_method'] + ], $fieldname, $fielddata, $newfieldvalue); + } elseif (is_array($fielddata) && !isset($fielddata['save_method'])) { + $returnvalue = []; + } else { + $returnvalue = false; + } + return $returnvalue; + } + + public static function manipulateFormFieldData($fieldname, $fielddata, $newfieldvalue) + { + if (is_array($fielddata) && isset($fielddata['type']) && $fielddata['type'] != '' && method_exists('\\Froxlor\\UI\\Data', 'manipulateFormFieldData' . ucfirst($fielddata['type']))) { + $newfieldvalue = call_user_func([ + '\\Froxlor\\UI\\Data', + 'manipulateFormFieldData' . ucfirst($fielddata['type']) + ], $fieldname, $fielddata, $newfieldvalue); + } + + return $newfieldvalue; + } + + public static function saveForm($fielddata, $newfieldvalue) + { + $returnvalue = ''; + if (is_array($fielddata) && isset($fielddata['save_method']) && $fielddata['save_method'] != '') { + $returnvalue = call_user_func([ + '\\Froxlor\\Settings\\Store', + $fielddata['save_method'] + ], $fielddata, $newfieldvalue); + } elseif (is_array($fielddata) && !isset($fielddata['save_method'])) { + $returnvalue = true; + } else { + $returnvalue = false; + } + return $returnvalue; + } } diff --git a/lib/Froxlor/UI/HTML.php b/lib/Froxlor/UI/HTML.php index 5f6af921..6fece703 100644 --- a/lib/Froxlor/UI/HTML.php +++ b/lib/Froxlor/UI/HTML.php @@ -1,20 +1,30 @@ (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package UI + * 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 + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 */ + +namespace Froxlor\UI; + class HTML { @@ -22,9 +32,9 @@ class HTML * Build Navigation Sidebar * * @param - * array navigation data + * array navigation data * @param - * array userinfo the userinfo of the user + * array userinfo the userinfo of the user * @return array the content of the navigation bar according to user-permissions */ public static function buildNavigation(array $navigation, array $userinfo) @@ -33,23 +43,22 @@ class HTML // sanitize user-given input (url-manipulation) if (isset($_GET['page']) && is_array($_GET['page'])) { - $_GET['page'] = (string) $_GET['page'][0]; + $_GET['page'] = (string)$_GET['page'][0]; } if (isset($_GET['action']) && is_array($_GET['action'])) { - $_GET['action'] = (string) $_GET['action'][0]; + $_GET['action'] = (string)$_GET['action'][0]; } foreach ($navigation as $box) { - if ((!isset($box['show_element']) || $box['show_element'] === true) && (!isset($box['required_resources']) || $box['required_resources'] == '' || (isset($userinfo[$box['required_resources']]) && ((int) $userinfo[$box['required_resources']] > 0 || $userinfo[$box['required_resources']] == '-1')))) { + if ((!isset($box['show_element']) || $box['show_element'] === true) && (!isset($box['required_resources']) || $box['required_resources'] == '' || (isset($userinfo[$box['required_resources']]) && ((int)$userinfo[$box['required_resources']] > 0 || $userinfo[$box['required_resources']] == '-1')))) { $navigation_links = []; $box_active = false; foreach ($box['elements'] as $element) { - if ((!isset($element['show_element']) || $element['show_element'] === true) && (!isset($element['required_resources']) || $element['required_resources'] == '' || (isset($userinfo[$element['required_resources']]) && ((int) $userinfo[$element['required_resources']] > 0 || $userinfo[$element['required_resources']] == '-1')))) { + if ((!isset($element['show_element']) || $element['show_element'] === true) && (!isset($element['required_resources']) || $element['required_resources'] == '' || (isset($userinfo[$element['required_resources']]) && ((int)$userinfo[$element['required_resources']] > 0 || $userinfo[$element['required_resources']] == '-1')))) { $target = ''; $active = false; $navurl = '#'; if (isset($element['url']) && trim($element['url']) != '') { - if (isset($element['new_window']) && $element['new_window'] == true) { $target = ' target="_blank"'; } @@ -80,7 +89,6 @@ class HTML if (!empty($navigation_links)) { $target = ''; if (isset($box['url']) && trim($box['url']) != '') { - if (isset($box['new_window']) && $box['new_window'] == true) { $target = ' target="_blank"'; } @@ -113,15 +121,15 @@ class HTML * Return HTML Code for an option within a