From 829498558861eb92774c713a9169a891237aec09 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sat, 8 Feb 2020 10:03:41 +0100 Subject: [PATCH 001/319] require set password complexity for admins too when resetting password; display correct error message if password complexity is not satisfied Signed-off-by: Michael Kaufmann --- index.php | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/index.php b/index.php index bfc6282a..fc929e02 100644 --- a/index.php +++ b/index.php @@ -598,21 +598,18 @@ if ($action == 'resetpwd') { )); if ($result !== false) { - if ($result['admin'] == 1) { - $new_password = \Froxlor\Validate\Validate::validate($_POST['new_password'], 'new password'); - $new_password_confirm = \Froxlor\Validate\Validate::validate($_POST['new_password_confirm'], 'new password confirm'); - } else { - $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'); + try { + $new_password = \Froxlor\System\Crypt::validatePassword($_POST['new_password'], true); + $new_password_confirm = \Froxlor\System\Crypt::validatePassword($_POST['new_password_confirm'], true); + } catch (Exception $e) { + $message = $e->getMessage(); } - if ($new_password == '') { - $message = $new_password; - } elseif ($new_password_confirm == '') { - $message = $new_password_confirm; - } elseif ($new_password != $new_password_confirm) { - $message = $new_password . " != " . $new_password_confirm; - } else { + if (empty($message) && (empty($new_password) || $new_password != $new_password_confirm)) { + $message = $lng['error']['newpasswordconfirmerror']; + } + + if (empty($message)) { // Update user password if ($result['admin'] == 1) { $stmt = Database::prepare("UPDATE `" . TABLE_PANEL_ADMINS . "` From 7f999302fa89e493a58b272947b4ae1082ddc6cb Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 14 Feb 2020 19:26:06 +0100 Subject: [PATCH 002/319] do not require enabled vhost-container for froxlor-vhost to change sslsessiontickets-setting Signed-off-by: Michael Kaufmann --- actions/admin/settings/131.ssl.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/actions/admin/settings/131.ssl.php b/actions/admin/settings/131.ssl.php index 609b0879..9cc89308 100644 --- a/actions/admin/settings/131.ssl.php +++ b/actions/admin/settings/131.ssl.php @@ -122,10 +122,7 @@ return array( 'type' => 'bool', '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)) && call_user_func(array( - '\Froxlor\Settings\FroxlorVhostSettings', - 'hasVhostContainerEnabled' - ), true) + '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)) ), 'system_leenabled' => array( 'label' => $lng['serversettings']['leenabled'], From f39aab6f328c16e29735f898d2bd5541c695f86d Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sat, 15 Feb 2020 07:11:28 +0100 Subject: [PATCH 003/319] disable sslsessiontickets-option in domain-add/edit if globally disabled in the settings Signed-off-by: Michael Kaufmann --- lib/formfields/admin/domains/formfield.domains_add.php | 2 +- lib/formfields/admin/domains/formfield.domains_edit.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/formfields/admin/domains/formfield.domains_add.php b/lib/formfields/admin/domains/formfield.domains_add.php index f5e99020..9ebfb3b6 100644 --- a/lib/formfields/admin/domains/formfield.domains_add.php +++ b/lib/formfields/admin/domains/formfield.domains_add.php @@ -384,7 +384,7 @@ return array( 'value' => array() ), 'sessiontickets' => array( - 'visible' => ($ssl_ipsandports != '' ? true : false) && \Froxlor\Settings::Get('system.webserver') != 'lighttpd', + 'visible' => ($ssl_ipsandports != '' ? true : false) && \Froxlor\Settings::Get('system.webserver') != 'lighttpd' && \Froxlor\Settings::Get('system.sessionticketsenabled' != '1'), 'label' => $lng['admin']['domain_sessiontickets'], 'type' => 'checkbox', 'values' => array( diff --git a/lib/formfields/admin/domains/formfield.domains_edit.php b/lib/formfields/admin/domains/formfield.domains_edit.php index 96f17caf..c53466cf 100644 --- a/lib/formfields/admin/domains/formfield.domains_edit.php +++ b/lib/formfields/admin/domains/formfield.domains_edit.php @@ -431,7 +431,7 @@ return array( ) ), 'sessiontickets' => array( - 'visible' => ($ssl_ipsandports != '' ? true : false) && \Froxlor\Settings::Get('system.webserver') != 'lighttpd', + 'visible' => ($ssl_ipsandports != '' ? true : false) && \Froxlor\Settings::Get('system.webserver') != 'lighttpd' && \Froxlor\Settings::Get('system.sessionticketsenabled' != '1'), 'label' => $lng['admin']['domain_sessiontickets'], 'type' => 'checkbox', 'values' => array( From 03450dcfa2e433008955955bde272fcadeb6c21f Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sat, 15 Feb 2020 07:25:23 +0100 Subject: [PATCH 004/319] fix listing of customer email addresses if 'domain' section is hidden via settings, fixes #803 Signed-off-by: Michael Kaufmann --- customer_email.php | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/customer_email.php b/customer_email.php index 7c143301..c776c707 100644 --- a/customer_email.php +++ b/customer_email.php @@ -129,16 +129,15 @@ if ($page == 'overview') { } } - $json_result = SubDomains::getLocal($userinfo, [ - 'sql_search' => [ - 'd.isemaildomain' => [ - 'value' => 1, - 'op' => '=' - ] - ] - ])->listing(); - $result = json_decode($json_result, true)['data']; - $emaildomains_count = $result['count']; + $result_stmt = Database::prepare(" + SELECT COUNT(`id`) as emaildomains + FROM `" . TABLE_PANEL_DOMAINS . "` + WHERE `customerid`= :cid AND `isemaildomain` = '1' + "); + $result = Database::pexecute_first($result_stmt, array( + "cid" => $userinfo['customerid'] + )); + $emaildomains_count = $result['emaildomains']; eval("echo \"" . \Froxlor\UI\Template::getTemplate("email/emails") . "\";"); } elseif ($action == 'delete' && $id != 0) { From d6c8b92523050d42926c66f721a85d8d1cf97906 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sat, 15 Feb 2020 07:30:56 +0100 Subject: [PATCH 005/319] add Froxlor.integrityCheck() API call to externally run integrity/consistency check, fixes #801 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Froxlor.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/lib/Froxlor/Api/Commands/Froxlor.php b/lib/Froxlor/Api/Commands/Froxlor.php index 709cffe2..080676d6 100644 --- a/lib/Froxlor/Api/Commands/Froxlor.php +++ b/lib/Froxlor/Api/Commands/Froxlor.php @@ -243,6 +243,26 @@ class Froxlor extends \Froxlor\Api\ApiCommand return $this->response(200, "successfull", \Froxlor\System\Crypt::generatePassword()); } + /** + * can be used to remotely run the integritiy checks froxlor implements + * + * @access admin + * @throws \Exception + * @return string + */ + public function integrityCheck() + { + if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) { + $integrity = new \Froxlor\Database\IntegrityCheck(); + $result = $integrity->checkAll(); + if ($result) { + return $this->response(200, "successfull", "OK"); + } + throw new \Exception("Some checks failed.", 406); + } + throw new \Exception("Not allowed to execute given command.", 403); + } + /** * returns a list of all available api functions * From 26e43077c263ae0b7dfa600cd4e9ad081abe06d1 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sat, 29 Feb 2020 08:16:55 +0100 Subject: [PATCH 006/319] make customer firstname,name,company and customer-no available for all templates; fixes #808 Signed-off-by: Michael Kaufmann --- index.php | 6 ++- lib/Froxlor/Api/Commands/Customers.php | 1 + lib/Froxlor/Api/Commands/EmailAccounts.php | 7 ++- lib/Froxlor/Api/Commands/Ftps.php | 4 ++ lib/Froxlor/Api/Commands/Mysqls.php | 4 ++ lib/Froxlor/Cron/Traffic/ReportsCron.php | 24 ++++++--- lng/english.lng.php | 1 + lng/german.lng.php | 1 + .../admin/templates/templates_add_2.tpl | 48 ++++++++---------- .../admin/templates/templates_edit.tpl | 49 ++++++++----------- 10 files changed, 78 insertions(+), 67 deletions(-) diff --git a/index.php b/index.php index fc929e02..8f5b4c8b 100644 --- a/index.php +++ b/index.php @@ -393,7 +393,7 @@ if ($action == 'forgotpwd') { if (isset($_POST['send']) && $_POST['send'] == 'send') { $loginname = \Froxlor\Validate\Validate::validate($_POST['loginname'], 'loginname'); $email = \Froxlor\Validate\Validate::validateEmail($_POST['loginemail'], 'email'); - $result_stmt = Database::prepare("SELECT `adminid`, `customerid`, `firstname`, `name`, `company`, `email`, `loginname`, `def_language`, `deactivated` FROM `" . TABLE_PANEL_CUSTOMERS . "` + $result_stmt = Database::prepare("SELECT `adminid`, `customerid`, `customernumber`, `firstname`, `name`, `company`, `email`, `loginname`, `def_language`, `deactivated` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `loginname`= :loginname AND `email`= :email"); Database::pexecute($result_stmt, array( @@ -481,6 +481,10 @@ if ($action == 'forgotpwd') { $replace_arr = array( 'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($user), + 'NAME' => $user['name'], + 'FIRSTNAME' => $user['firstname'] ?? "", + 'COMPANY' => $user['company'] ?? "", + 'CUSTOMER_NO' => $user['customernumber'] ?? 0, 'USERNAME' => $loginname, 'LINK' => $activationlink ); diff --git a/lib/Froxlor/Api/Commands/Customers.php b/lib/Froxlor/Api/Commands/Customers.php index cb815c92..8bb2616c 100644 --- a/lib/Froxlor/Api/Commands/Customers.php +++ b/lib/Froxlor/Api/Commands/Customers.php @@ -689,6 +689,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource 'name' => $name, 'company' => $company )), + 'CUSTOMER_NO' => $customernumber, 'USERNAME' => $loginname, 'PASSWORD' => $password, 'SERVER_HOSTNAME' => $srv_hostname, diff --git a/lib/Froxlor/Api/Commands/EmailAccounts.php b/lib/Froxlor/Api/Commands/EmailAccounts.php index 853bc8d2..0a06f524 100644 --- a/lib/Froxlor/Api/Commands/EmailAccounts.php +++ b/lib/Froxlor/Api/Commands/EmailAccounts.php @@ -192,7 +192,12 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso $replace_arr = array( 'EMAIL' => $email_full, 'USERNAME' => $username, - 'PASSWORD' => $password + 'PASSWORD' => $password, + 'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($customer), + 'NAME' => $customer['name'], + 'FIRSTNAME' => $customer['firstname'], + 'COMPANY' => $customer['company'], + 'CUSTOMER_NO' => $customer['customernumber'] ); // get the customers admin diff --git a/lib/Froxlor/Api/Commands/Ftps.php b/lib/Froxlor/Api/Commands/Ftps.php index 59b7906e..978b03b4 100644 --- a/lib/Froxlor/Api/Commands/Ftps.php +++ b/lib/Froxlor/Api/Commands/Ftps.php @@ -227,6 +227,10 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit $replace_arr = array( 'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($customer), 'CUST_NAME' => \Froxlor\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' => $password, 'USR_PATH' => \Froxlor\FileDir::makeCorrectDir(str_replace($customer['documentroot'], "/", $path)) diff --git a/lib/Froxlor/Api/Commands/Mysqls.php b/lib/Froxlor/Api/Commands/Mysqls.php index f9fd1b41..417e13ed 100644 --- a/lib/Froxlor/Api/Commands/Mysqls.php +++ b/lib/Froxlor/Api/Commands/Mysqls.php @@ -125,6 +125,10 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $replace_arr = array( 'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($userinfo), 'CUST_NAME' => \Froxlor\User::getCorrectUserSalutation($userinfo), // < keep this for compatibility + 'NAME' => $userinfo['name'], + 'FIRSTNAME' => $userinfo['firstname'], + 'COMPANY' => $userinfo['company'], + 'CUSTOMER_NO' => $userinfo['customernumber'], 'DB_NAME' => $username, 'DB_PASS' => $password, 'DB_DESC' => $databasedescription, diff --git a/lib/Froxlor/Cron/Traffic/ReportsCron.php b/lib/Froxlor/Cron/Traffic/ReportsCron.php index f97df232..7afdd7b0 100644 --- a/lib/Froxlor/Cron/Traffic/ReportsCron.php +++ b/lib/Froxlor/Cron/Traffic/ReportsCron.php @@ -36,7 +36,7 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron if ((int) Settings::Get('system.report_trafficmax') > 0) { // Warn the customers at xx% traffic-usage $result_stmt = Database::prepare(" - SELECT `c`.`customerid`, `c`.`adminid`, `c`.`name`, `c`.`firstname`, + SELECT `c`.`customerid`, `c`.`customernumber`, `c`.`adminid`, `c`.`name`, `c`.`firstname`, `c`.`company`, `c`.`traffic`, `c`.`email`, `c`.`def_language`, `a`.`name` AS `adminname`, `a`.`email` AS `adminmail`, (SELECT SUM(`t`.`http` + `t`.`ftp_up` + `t`.`ftp_down` + `t`.`mail`) @@ -60,11 +60,15 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron $rep_userinfo = array( 'name' => $row['name'], 'firstname' => $row['firstname'], - 'company' => $row['company'] + 'company' => $row['company'], + 'customernumber' => $row['customernumber'] ); $replace_arr = array( 'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($rep_userinfo), - 'NAME' => $row['name'], // < keep this for compatibility + '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 */ 'USAGE_PERCENT' => round(($row['traffic_used'] * 100) / $row['traffic'], 2), @@ -168,8 +172,8 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron $replace_arr = array( '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 */ - 'USAGE_PERCENT' => round(($row['traffic_used_total'] * 100) / $row['traffic'], 2), + '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') ); @@ -343,7 +347,7 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron * report about diskusage for customers */ $result_stmt = Database::query(" - SELECT `c`.`customerid`, `c`.`adminid`, `c`.`name`, `c`.`firstname`, + SELECT `c`.`customerid`, `c`.`customernumber`,, `c`.`adminid`, `c`.`name`, `c`.`firstname`, `c`.`company`, `c`.`diskspace`, `c`.`diskspace_used`, `c`.`email`, `c`.`def_language`, `a`.`name` AS `adminname`, `a`.`email` AS `adminmail` FROM `" . TABLE_PANEL_CUSTOMERS . "` AS `c` @@ -361,11 +365,15 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron $rep_userinfo = array( 'name' => $row['name'], 'firstname' => $row['firstname'], - 'company' => $row['company'] + 'company' => $row['company'], + 'customernumber' => $row['customernumber'] ); $replace_arr = array( 'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($rep_userinfo), - 'NAME' => $row['name'], // < keep this for compatibility + '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 */ 'USAGE_PERCENT' => round(($row['diskspace_used'] * 100) / $row['diskspace'], 2), diff --git a/lng/english.lng.php b/lng/english.lng.php index 1101ce30..5a1868a9 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -317,6 +317,7 @@ $lng['admin']['templates']['COMPANY'] = 'Replaces with the customer\'s company n $lng['admin']['templates']['USERNAME'] = 'Replaced with the customer\'s account username.'; $lng['admin']['templates']['PASSWORD'] = 'Replaced with the customer\'s account password.'; $lng['admin']['templates']['EMAIL'] = 'Replaced with the address of the POP3/IMAP account.'; +$lng['admin']['templates']['CUSTOMER_NO'] = 'Replaces with the customer number'; $lng['admin']['webserver'] = 'Webserver'; $lng['admin']['bindzonewarning'] = $lng['panel']['emptyfordefault'] . '
ATTENTION: If you use a zonefile you will have to manage all required records for all sub-zones manually as well.'; diff --git a/lng/german.lng.php b/lng/german.lng.php index ada5e836..9208d0e4 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -314,6 +314,7 @@ $lng['admin']['templates']['COMPANY'] = 'Wird mit dem Firmennamen des Kunden ers $lng['admin']['templates']['USERNAME'] = 'Wird mit dem Benutzernamen des neuen Kundenkontos ersetzt.'; $lng['admin']['templates']['PASSWORD'] = 'Wird mit dem Passwort des neuen Kundenkontos ersetzt.'; $lng['admin']['templates']['EMAIL'] = 'Wird mit der Adresse des neuen E-Mail-Kontos ersetzt.'; +$lng['admin']['templates']['CUSTOMER_NO'] = 'Wir mit der Kunden-Nummer ersetzt'; $lng['admin']['bindzonewarning'] = $lng['panel']['emptyfordefault'] . '
WARNUNG: Bei der Verwendung einer Zonendatei müssen alle benötigten Records aller Subdomains ebenfalls manuell verwaltet werden.'; /** diff --git a/templates/Sparkle/admin/templates/templates_add_2.tpl b/templates/Sparkle/admin/templates/templates_add_2.tpl index 6f197624..7077f924 100644 --- a/templates/Sparkle/admin/templates/templates_add_2.tpl +++ b/templates/Sparkle/admin/templates/templates_add_2.tpl @@ -40,23 +40,27 @@ $header + + {SALUTATION} + {$lng['admin']['templates']['SALUTATION']} + + + {FIRSTNAME} + {$lng['admin']['templates']['FIRSTNAME']} + + + {NAME} + {$lng['admin']['templates']['NAME']} + + + {COMPANY} + {$lng['admin']['templates']['COMPANY']} + + + {CUSTOMER_NO} + {$lng['admin']['templates']['CUSTOMER_NO']} + - - {SALUTATION} - {$lng['admin']['templates']['SALUTATION']} - - - {FIRSTNAME} - {$lng['admin']['templates']['FIRSTNAME']} - - - {NAME} - {$lng['admin']['templates']['NAME']} - - - {COMPANY} - {$lng['admin']['templates']['COMPANY']} - {USERNAME} {$lng['admin']['templates']['USERNAME']} @@ -88,10 +92,6 @@ $header - - {SALUTATION} - {$lng['admin']['templates']['SALUTATION']} - {USERNAME} {$lng['admin']['templates']['USERNAME']} @@ -138,10 +138,6 @@ $header - - {SALUTATION} - {$lng['admin']['templates']['SALUTATION']} - {DB_NAME} {$lng['admin']['templates']['DB_NAME']} @@ -164,10 +160,6 @@ $header - - {SALUTATION} - {$lng['admin']['templates']['SALUTATION']} - {USR_NAME} {$lng['admin']['templates']['USR_NAME']} diff --git a/templates/Sparkle/admin/templates/templates_edit.tpl b/templates/Sparkle/admin/templates/templates_edit.tpl index d9a12501..875ef050 100644 --- a/templates/Sparkle/admin/templates/templates_edit.tpl +++ b/templates/Sparkle/admin/templates/templates_edit.tpl @@ -42,23 +42,27 @@ $header + + {SALUTATION} + {$lng['admin']['templates']['SALUTATION']} + + + {FIRSTNAME} + {$lng['admin']['templates']['FIRSTNAME']} + + + {NAME} + {$lng['admin']['templates']['NAME']} + + + {COMPANY} + {$lng['admin']['templates']['COMPANY']} + + + {CUSTOMER_NO} + {$lng['admin']['templates']['CUSTOMER_NO']} + - - {SALUTATION} - {$lng['admin']['templates']['SALUTATION']} - - - {FIRSTNAME} - {$lng['admin']['templates']['FIRSTNAME']} - - - {NAME} - {$lng['admin']['templates']['NAME']} - - - {COMPANY} - {$lng['admin']['templates']['COMPANY']} - {USERNAME} {$lng['admin']['templates']['USERNAME']} @@ -90,10 +94,6 @@ $header - - {SALUTATION} - {$lng['admin']['templates']['SALUTATION']} - {USERNAME} {$lng['admin']['templates']['USERNAME']} @@ -140,10 +140,6 @@ $header - - {SALUTATION} - {$lng['admin']['templates']['SALUTATION']} - {DB_NAME} {$lng['admin']['templates']['DB_NAME']} @@ -166,10 +162,6 @@ $header - - {SALUTATION} - {$lng['admin']['templates']['SALUTATION']} - {USR_NAME} {$lng['admin']['templates']['USR_NAME']} @@ -190,4 +182,3 @@ $header $footer - From f11ceacf896b5de2fa82363c4021d9340f2216cb Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sat, 29 Feb 2020 09:50:29 +0100 Subject: [PATCH 007/319] store ace-string of domain besides idn-converted string to have correct sorting in the frontend; fixes #809 Signed-off-by: Michael Kaufmann --- admin_domains.php | 2 +- customer_domains.php | 2 +- customer_email.php | 6 ++--- install/froxlor.sql | 3 ++- .../updates/froxlor/0.10/update_0.10.inc.php | 23 ++++++++++++++++++- lib/Froxlor/Api/Commands/Domains.php | 2 ++ lib/Froxlor/Api/Commands/SubDomains.php | 5 +++- lib/Froxlor/Froxlor.php | 2 +- templates/Sparkle/admin/domains/domains.tpl | 2 +- .../Sparkle/customer/domains/domainlist.tpl | 2 +- tests/Certificates/CertificatesTest.php | 4 ++-- tests/Domains/DomainsTest.php | 23 +++++++++++++++++++ 12 files changed, 63 insertions(+), 13 deletions(-) diff --git a/admin_domains.php b/admin_domains.php index fa9686a7..b4f62e61 100644 --- a/admin_domains.php +++ b/admin_domains.php @@ -39,7 +39,7 @@ if ($page == 'domains' || $page == 'overview') { $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_domains"); $fields = array( - 'd.domain' => $lng['domains']['domainname'], + 'd.domain_ace' => $lng['domains']['domainname'], 'c.name' => $lng['customer']['name'], 'c.firstname' => $lng['customer']['firstname'], 'c.company' => $lng['customer']['company'], diff --git a/customer_domains.php b/customer_domains.php index ba285c95..26fe3833 100644 --- a/customer_domains.php +++ b/customer_domains.php @@ -42,7 +42,7 @@ if ($page == 'overview') { if ($action == '') { $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_domains::domains"); $fields = array( - 'd.domain' => $lng['domains']['domainname'], + 'd.domain_ace' => $lng['domains']['domainname'], 'd.aliasdomain' => $lng['domains']['aliasdomain'] ); try { diff --git a/customer_email.php b/customer_email.php index c776c707..3e8bd67e 100644 --- a/customer_email.php +++ b/customer_email.php @@ -44,7 +44,7 @@ if ($page == 'overview') { if ($action == '') { $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_email::emails"); $fields = array( - 'd.domain' => $lng['domains']['domainname'], + 'd.domain_ace' => $lng['domains']['domainname'], 'm.email_full' => $lng['emails']['emailaddress'], 'm.destination' => $lng['emails']['forwarders'] ); @@ -76,7 +76,7 @@ if ($page == 'overview') { $emails[$row['domain']][$row['email_full']] = $row; } - if ($paging->sortfield == 'd.domain' && $paging->sortorder == 'desc') { + if ($paging->sortfield == 'd.domain_ace' && $paging->sortorder == 'desc') { krsort($emails); } else { ksort($emails); @@ -195,7 +195,7 @@ if ($page == 'overview') { $result_stmt = Database::prepare("SELECT `id`, `domain`, `customerid` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid`= :cid AND `isemaildomain`='1' - ORDER BY `domain` ASC"); + ORDER BY `domain_ace` ASC"); Database::pexecute($result_stmt, array( "cid" => $userinfo['customerid'] )); diff --git a/install/froxlor.sql b/install/froxlor.sql index a0ff604e..3034a104 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -224,6 +224,7 @@ DROP TABLE IF EXISTS `panel_domains`; CREATE TABLE `panel_domains` ( `id` int(11) unsigned NOT NULL auto_increment, `domain` varchar(255) NOT NULL default '', + `domain_ace` varchar(255) NOT NULL default '', `adminid` int(11) unsigned NOT NULL default '0', `customerid` int(11) unsigned NOT NULL default '0', `aliasdomain` int(11) unsigned NULL, @@ -704,7 +705,7 @@ opcache.interned_strings_buffer'), ('panel', 'customer_hide_options', ''), ('panel', 'is_configured', '0'), ('panel', 'version', '0.10.13'), - ('panel', 'db_version', '201912313'); + ('panel', 'db_version', '202002290'); DROP TABLE IF EXISTS `panel_tasks`; diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index 3da2dea7..fa421aeb 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -546,7 +546,7 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.10')) { if (\Froxlor\Froxlor::isDatabaseVersion('201912311')) { showUpdateStep("Migrate logfiles_format setting"); $current_format = Settings::Set('system.logfiles_format'); - if (!empty($current_format)) { + if (! empty($current_format)) { Settings::Set('system.logfiles_format', '"' . Settings::Get('system.logfiles_format') . '"'); lastStepStatus(0); } else { @@ -571,3 +571,24 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.12')) { showUpdateStep("Updating from 0.10.12 to 0.10.13", false); \Froxlor\Froxlor::updateToVersion('0.10.13'); } + +if (\Froxlor\Froxlor::isDatabaseVersion('201912313')) { + showUpdateStep("Adding new field to domains table"); + Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `domain_ace` varchar(255) NOT NULL default '' AFTER `domain`;"); + lastStepStatus(0); + + showUpdateStep("Updating domain entries"); + $upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `domain_ace` = :ace WHERE `id` = :domainid"); + $sel_stmt = Database::prepare("SELECT id, domain FROM `" . TABLE_PANEL_DOMAINS . "` ORDER BY id ASC"); + Database::pexecute($sel_stmt); + $idna_convert = new \Froxlor\Idna\IdnaWrapper(); + while ($domain = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) { + Database::pexecute($upd_stmt, [ + 'ace' => $idna_convert->decode($domain['domain']), + 'domainid' => $domain['id'] + ]); + } + lastStepStatus(0); + + \Froxlor\Froxlor::updateToDbVersion('202002290'); +} diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php index c9e6dfda..bc572b3c 100644 --- a/lib/Froxlor/Api/Commands/Domains.php +++ b/lib/Froxlor/Api/Commands/Domains.php @@ -684,6 +684,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $ins_data = array( 'domain' => $domain, + 'domain_ace' => $idna_convert->decode($domain), 'customerid' => $customerid, 'adminid' => $adminid, 'documentroot' => $documentroot, @@ -732,6 +733,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $ins_stmt = Database::prepare(" INSERT INTO `" . TABLE_PANEL_DOMAINS . "` SET `domain` = :domain, + `domain_ace` = :domain_ace, `customerid` = :customerid, `adminid` = :adminid, `documentroot` = :documentroot, diff --git a/lib/Froxlor/Api/Commands/SubDomains.php b/lib/Froxlor/Api/Commands/SubDomains.php index 91addb6d..18d332a3 100644 --- a/lib/Froxlor/Api/Commands/SubDomains.php +++ b/lib/Froxlor/Api/Commands/SubDomains.php @@ -256,6 +256,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc `customerid` = :customerid, `adminid` = :adminid, `domain` = :domain, + `domain_ace` = :domain_ace, `documentroot` = :documentroot, `aliasdomain` = :aliasdomain, `parentdomainid` = :parentdomainid, @@ -287,6 +288,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc "customerid" => $customer['customerid'], "adminid" => $customer['adminid'], "domain" => $completedomain, + "domain_ace" => $idna_convert->decode($completedomain), "documentroot" => $path, "aliasdomain" => $aliasdomain != 0 ? $aliasdomain : null, "parentdomainid" => $domain_check['id'], @@ -765,6 +767,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc '`d`.`id`', '`d`.`customerid`', '`d`.`domain`', + '`d`.`domain_ace`', '`d`.`documentroot`', '`d`.`isbinddomain`', '`d`.`isemaildomain`', @@ -780,7 +783,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc // prepare select statement $domains_stmt = Database::prepare(" - SELECT " . implode(",", $select_fields) . ", IF(`d`.`parentdomainid` > 0, `pd`.`domain`, `d`.`domain`) AS `parentdomainname`, `ad`.`id` AS `aliasdomainid`, `ad`.`domain` AS `aliasdomain`, `da`.`id` AS `domainaliasid`, `da`.`domain` AS `domainalias` + SELECT " . implode(",", $select_fields) . ", IF(`d`.`parentdomainid` > 0, `pd`.`domain_ace`, `d`.`domain_ace`) AS `parentdomainname`, `ad`.`id` AS `aliasdomainid`, `ad`.`domain` AS `aliasdomain`, `da`.`id` AS `domainaliasid`, `da`.`domain` AS `domainalias` FROM `" . TABLE_PANEL_DOMAINS . "` `d` LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id` LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `da` ON `da`.`aliasdomain`=`d`.`id` diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index 3131a078..3ea62d39 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -10,7 +10,7 @@ final class Froxlor const VERSION = '0.10.13'; // Database version (YYYYMMDDC where C is a daily counter) - const DBVERSION = '201912313'; + const DBVERSION = '202002290'; // Distribution branding-tag (used for Debian etc.) const BRANDING = ''; diff --git a/templates/Sparkle/admin/domains/domains.tpl b/templates/Sparkle/admin/domains/domains.tpl index 952f94f5..0f90814d 100644 --- a/templates/Sparkle/admin/domains/domains.tpl +++ b/templates/Sparkle/admin/domains/domains.tpl @@ -30,7 +30,7 @@ - + diff --git a/templates/Sparkle/customer/domains/domainlist.tpl b/templates/Sparkle/customer/domains/domainlist.tpl index 5325ee92..ecce85a3 100644 --- a/templates/Sparkle/customer/domains/domainlist.tpl +++ b/templates/Sparkle/customer/domains/domainlist.tpl @@ -27,7 +27,7 @@
{$lng['domains']['domainname']} {$arrowcode['d.domain']}{$lng['domains']['domainname']} {$arrowcode['d.domain_ace']} {$lng['admin']['ipsandports']['ip']} {$lng['admin']['customer']} {$arrowcode['c.loginname']} {$lng['panel']['options']}
- + diff --git a/tests/Certificates/CertificatesTest.php b/tests/Certificates/CertificatesTest.php index cf33fbce..b1430bbc 100644 --- a/tests/Certificates/CertificatesTest.php +++ b/tests/Certificates/CertificatesTest.php @@ -64,7 +64,7 @@ class CertificatesTest extends TestCase 'ssl_key_file' => $certdata['key'] ))->add(); $result = json_decode($json_result, true)['data']; - $this->assertEquals(5, $result['domainid']); + $this->assertEquals(6, $result['domainid']); } public function testAdminCertificatesList() @@ -148,7 +148,7 @@ class CertificatesTest extends TestCase 'ssl_key_file' => $certdata['key'] ))->update(); $result = json_decode($json_result, true)['data']; - $this->assertEquals(5, $result['domainid']); + $this->assertEquals(6, $result['domainid']); $this->assertEquals(str_replace("\n", "", $certdata['cert']), str_replace("\n", "", $result['ssl_cert_file'])); } diff --git a/tests/Domains/DomainsTest.php b/tests/Domains/DomainsTest.php index f3aa40dc..ee186835 100644 --- a/tests/Domains/DomainsTest.php +++ b/tests/Domains/DomainsTest.php @@ -347,4 +347,27 @@ class DomainsTest extends TestCase $this->expectExceptionMessage("Not allowed to execute given command."); $json_result = Domains::getLocal($customer_userdata)->listingCount(); } + + public function testAdminIdnDomainsAdd() + { + global $admin_userdata; + // get customer + $json_result = Customers::getLocal($admin_userdata, array( + 'loginname' => 'test1' + ))->get(); + $customer_userdata = json_decode($json_result, true)['data']; + $data = [ + 'domain' => 'täst.local', + 'customerid' => $customer_userdata['customerid'] + ]; + $json_result = Domains::getLocal($admin_userdata, $data)->add(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals($customer_userdata['documentroot'] . 'xn--tst-qla.local/', $result['documentroot']); + $this->assertEquals('xn--tst-qla.local', $result['domain']); + $this->assertEquals('täst.local', $result['domain_ace']); + + Domains::getLocal($admin_userdata, [ + 'domainname' => 'täst.local' + ])->delete(); + } } From 5f3f2085344bf053bc1450a919d6c196c00da606 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 1 Mar 2020 09:16:47 +0100 Subject: [PATCH 008/319] remove superfluous comma in sql query which causes invalid sql Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/Traffic/ReportsCron.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Froxlor/Cron/Traffic/ReportsCron.php b/lib/Froxlor/Cron/Traffic/ReportsCron.php index 7afdd7b0..d2fd7829 100644 --- a/lib/Froxlor/Cron/Traffic/ReportsCron.php +++ b/lib/Froxlor/Cron/Traffic/ReportsCron.php @@ -347,7 +347,7 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron * report about diskusage for customers */ $result_stmt = Database::query(" - SELECT `c`.`customerid`, `c`.`customernumber`,, `c`.`adminid`, `c`.`name`, `c`.`firstname`, + SELECT `c`.`customerid`, `c`.`customernumber`, `c`.`adminid`, `c`.`name`, `c`.`firstname`, `c`.`company`, `c`.`diskspace`, `c`.`diskspace_used`, `c`.`email`, `c`.`def_language`, `a`.`name` AS `adminname`, `a`.`email` AS `adminmail` FROM `" . TABLE_PANEL_CUSTOMERS . "` AS `c` From 8807ae7dad7910e484983cae203b6ec274b64775 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Mon, 2 Mar 2020 09:51:44 +0100 Subject: [PATCH 009/319] allow private ip ranges in ips-and-ports as some configurations require that; fixes #802 Signed-off-by: Michael Kaufmann --- admin_ipsandports.php | 9 ++++ lib/Froxlor/Api/Commands/IpsAndPorts.php | 4 +- lng/english.lng.php | 1 + lng/german.lng.php | 1 + .../admin/ipsandports/ipsandports_add.tpl | 1 + .../admin/ipsandports/ipsandports_edit.tpl | 1 + templates/Sparkle/assets/js/ipsandports.js | 46 +++++++++++++++++++ 7 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 templates/Sparkle/assets/js/ipsandports.js diff --git a/admin_ipsandports.php b/admin_ipsandports.php index 6b64ae8f..84006fb0 100644 --- a/admin_ipsandports.php +++ b/admin_ipsandports.php @@ -160,5 +160,14 @@ if ($page == 'ipsandports' || $page == 'overview') { eval("echo \"" . \Froxlor\UI\Template::getTemplate("ipsandports/ipsandports_edit") . "\";"); } } + } elseif ($action == 'jqCheckIP') { + $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']); + } else { + echo 0; + } + exit(); } } diff --git a/lib/Froxlor/Api/Commands/IpsAndPorts.php b/lib/Froxlor/Api/Commands/IpsAndPorts.php index 2e690833..9b349080 100644 --- a/lib/Froxlor/Api/Commands/IpsAndPorts.php +++ b/lib/Froxlor/Api/Commands/IpsAndPorts.php @@ -170,7 +170,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour { if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) { - $ip = \Froxlor\Validate\Validate::validate_ip2($this->getParam('ip'), false, 'invalidip', false, false, false, false, true); + $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', '/^(([1-9])|([1-9][0-9])|([1-9][0-9][0-9])|([1-9][0-9][0-9][0-9])|([1-5][0-9][0-9][0-9][0-9])|(6[0-4][0-9][0-9][0-9])|(65[0-4][0-9][0-9])|(655[0-2][0-9])|(6553[0-5]))$/Di', array( 'stringisempty', 'myport' @@ -367,7 +367,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour 'id' => $id )); - $ip = \Froxlor\Validate\Validate::validate_ip2($this->getParam('ip', true, $result['ip']), false, 'invalidip', false, false, false, false, true); + $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', '/^(([1-9])|([1-9][0-9])|([1-9][0-9][0-9])|([1-9][0-9][0-9][0-9])|([1-5][0-9][0-9][0-9][0-9])|(6[0-4][0-9][0-9][0-9])|(65[0-4][0-9][0-9])|(655[0-2][0-9])|(6553[0-5]))$/Di', array( 'stringisempty', 'myport' diff --git a/lng/english.lng.php b/lng/english.lng.php index 5a1868a9..db12fe4d 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -409,6 +409,7 @@ $lng['admin']['ipsandports']['add'] = 'Add IP/Port'; $lng['admin']['ipsandports']['edit'] = 'Edit IP/Port'; $lng['admin']['ipsandports']['ipandport'] = 'IP/Port'; $lng['admin']['ipsandports']['ip'] = 'IP'; +$lng['admin']['ipsandports']['ipnote'] = '
Note: Although private ip addresses are allowed, some features like DNS might not behave correctly.
Only use private ip addresses if you are sure.
'; $lng['admin']['ipsandports']['port'] = 'Port'; // ADDED IN 1.2.13-rc3 diff --git a/lng/german.lng.php b/lng/german.lng.php index 9208d0e4..74dc5acb 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -404,6 +404,7 @@ $lng['admin']['ipsandports']['add'] = 'IP-Adresse/Port hinzufügen'; $lng['admin']['ipsandports']['edit'] = 'IP-Adresse/Port bearbeiten'; $lng['admin']['ipsandports']['ipandport'] = 'IP-Adresse/Port'; $lng['admin']['ipsandports']['ip'] = 'IP-Adresse'; +$lng['admin']['ipsandports']['ipnote'] = '
Hinweis: Obwohl private IP Adressen erlaubt sind, kann es bei manchen Features wie DNS zu ungewolltem Verhalten kommen.
Verwende private Adressen nur wenn du sicher bist.
'; $lng['admin']['ipsandports']['port'] = 'Port'; // ADDED IN 1.2.13-rc3 diff --git a/templates/Sparkle/admin/ipsandports/ipsandports_add.tpl b/templates/Sparkle/admin/ipsandports/ipsandports_add.tpl index 806617ee..20326cd3 100644 --- a/templates/Sparkle/admin/ipsandports/ipsandports_add.tpl +++ b/templates/Sparkle/admin/ipsandports/ipsandports_add.tpl @@ -6,6 +6,7 @@ $header {$title} +
diff --git a/templates/Sparkle/admin/ipsandports/ipsandports_edit.tpl b/templates/Sparkle/admin/ipsandports/ipsandports_edit.tpl index 4d12e2ac..4f61b938 100644 --- a/templates/Sparkle/admin/ipsandports/ipsandports_edit.tpl +++ b/templates/Sparkle/admin/ipsandports/ipsandports_edit.tpl @@ -6,6 +6,7 @@ $header {$title} +
diff --git a/templates/Sparkle/assets/js/ipsandports.js b/templates/Sparkle/assets/js/ipsandports.js new file mode 100644 index 00000000..87091afa --- /dev/null +++ b/templates/Sparkle/assets/js/ipsandports.js @@ -0,0 +1,46 @@ +$(document).ready(function() { + + var getUrlParameter = function getUrlParameter(sParam) { + var sPageURL = decodeURIComponent(window.location.search.substring(1)), + sURLVariables = sPageURL.split('&'), + sParameterName, + i; + + for (i = 0; i < sURLVariables.length; i++) { + sParameterName = sURLVariables[i].split('='); + + if (sParameterName[0] === sParam) { + return sParameterName[1] === undefined ? true : sParameterName[1]; + } + } + }; + + /** + * check for internal ip and output a notice if private-range ip is given + */ + $('#ip').change(function() { + var ipval = $(this).val(); + if (ipval.length > 0) { + var sid = getUrlParameter('s'); + $.ajax({ + url: "admin_ipsandports.php?s="+sid+"&page=overview&action=jqCheckIP", + type: "POST", + data: { + ip: ipval + }, + dataType: "json", + success: function(json) { + if (json != 0) { + $('#ip').parent().append(json); + } else { + $('#ipnote').remove(); + } + }, + error: function(a, b) { + console.log(a, b); + } + }); + } + }); + +}); From 6b09720ef8a1cc008751dd0ca0140a0597fedce5 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Wed, 4 Mar 2020 19:34:18 +0100 Subject: [PATCH 010/319] use unpredictable tmpfile-name in installation if lib/userdata.inc.php cannot be written due to permission Signed-off-by: Michael Kaufmann --- install/lib/class.FroxlorInstall.php | 21 +++++++++++++-------- install/lng/english.lng.php | 2 +- install/lng/french.lng.php | 2 +- install/lng/german.lng.php | 2 +- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index ddc3166a..11a16bfb 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -338,15 +338,20 @@ class FroxlorInstall @fclose($fp); $content .= $this->_status_message('green', 'OK'); chmod($userdata_file, 0440); - } elseif ($fp = @fopen('/tmp/userdata.inc.php', 'w')) { - $result = @fputs($fp, $userdata, strlen($userdata)); - @fclose($fp); - $content .= $this->_status_message('orange', $this->_lng['install']['creating_configfile_temp']); - chmod('/tmp/userdata.inc.php', 0440); } else { - $content .= $this->_status_message('red', $this->_lng['install']['creating_configfile_failed']); - $escpduserdata = nl2br(htmlspecialchars($userdata)); - eval("\$content .= \"" . $this->_getTemplate("textarea") . "\";"); + // try creating it in a temporary file + $temp_file = tempnam(sys_get_temp_dir(), 'fx'); + if (touch($temp_file)) { + chmod($temp_file, 0400); + $fp = @fopen($temp_file, 'w'); + $result = @fputs($fp, $userdata, strlen($userdata)); + @fclose($fp); + $content .= $this->_status_message('orange', sprintf($this->_lng['install']['creating_configfile_temp'], $temp_file)); + } else { + $content .= $this->_status_message('red', $this->_lng['install']['creating_configfile_failed']); + $escpduserdata = nl2br(htmlspecialchars($userdata)); + eval("\$content .= \"" . $this->_getTemplate("textarea") . "\";"); + } } return $content; diff --git a/install/lng/english.lng.php b/install/lng/english.lng.php index b7dd5ef8..e5e6b9cb 100644 --- a/install/lng/english.lng.php +++ b/install/lng/english.lng.php @@ -86,7 +86,7 @@ $lng['install']['changing_data'] = 'Adjusting settings...'; $lng['install']['creating_entries'] = 'Inserting new values...'; $lng['install']['adding_admin_user'] = 'Creating admin-account...'; $lng['install']['creating_configfile'] = 'Creating configfile...'; -$lng['install']['creating_configfile_temp'] = 'File was saved in /tmp/userdata.inc.php, please move to ' . dirname(dirname(__DIR__)) . '/lib/.'; +$lng['install']['creating_configfile_temp'] = 'File was saved in %s, please move to ' . dirname(dirname(__DIR__)) . '/lib/userdata.inc.php'; $lng['install']['creating_configfile_failed'] = 'Could not create ' . dirname(dirname(__DIR__)) . '/lib/userdata.inc.php, please create it manually with the following content:'; $lng['install']['froxlor_succ_installed'] = 'Froxlor was installed successfully.'; diff --git a/install/lng/french.lng.php b/install/lng/french.lng.php index fdb733ce..42ab1d7b 100644 --- a/install/lng/french.lng.php +++ b/install/lng/french.lng.php @@ -76,7 +76,7 @@ $lng['install']['changing_data'] = 'Ajustement des paramètres...'; $lng['install']['creating_entries'] = 'Insertion des nouvelles valeurs...'; $lng['install']['adding_admin_user'] = 'Création du compte administrateur...'; $lng['install']['creating_configfile'] = 'Création du fichier de configuration...'; -$lng['install']['creating_configfile_temp'] = 'Le fichier a été enregistré dans /tmp/userdata.inc.php, merci de le déplacer dans ' . dirname(dirname(__DIR__)) . '/lib/.'; +$lng['install']['creating_configfile_temp'] = 'Le fichier a été enregistré dans %s, merci de le déplacer dans ' . dirname(dirname(__DIR__)) . '/lib/userdata.inc.php'; $lng['install']['creating_configfile_failed'] = 'Impossible de créer ' . dirname(dirname(__DIR__)) . '/lib/userdata.inc.php, merci de le créer manuellement avec le contenu suivant:'; $lng['install']['froxlor_succ_installed'] = 'Froxlor a été installé avec succès.'; diff --git a/install/lng/german.lng.php b/install/lng/german.lng.php index 1f95decc..64b462b4 100644 --- a/install/lng/german.lng.php +++ b/install/lng/german.lng.php @@ -86,7 +86,7 @@ $lng['install']['changing_data'] = 'Einstellungen anpassen...'; $lng['install']['creating_entries'] = 'Trage neue Werte ein...'; $lng['install']['adding_admin_user'] = 'Erstelle Admin-Benutzer...'; $lng['install']['creating_configfile'] = 'Erstelle Konfigurationsdatei...'; -$lng['install']['creating_configfile_temp'] = 'Datei wurde in /tmp/userdata.inc.php gespeichert, bitte nach ' . dirname(dirname(__DIR__)) . '/lib/ verschieben.'; +$lng['install']['creating_configfile_temp'] = 'Datei wurde in %s gespeichert, bitte nach ' . dirname(dirname(__DIR__)) . '/lib/userdata.inc.php verschieben.'; $lng['install']['creating_configfile_failed'] = 'Konnte ' . dirname(dirname(__DIR__)) . '/lib/userdata.inc.php nicht erstellen, bitte manuell mit folgendem Inhalt anlegen:'; $lng['install']['froxlor_succ_installed'] = 'Froxlor wurde erfolgreich installiert.'; From 62ce21c9ec393f9962515c88f0c489ace42bf656 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Wed, 4 Mar 2020 19:35:57 +0100 Subject: [PATCH 011/319] secure shell-execution of mysqldump on installation if given database-name exists Signed-off-by: Michael Kaufmann --- install/lib/class.FroxlorInstall.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index 11a16bfb..dc67120f 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -735,7 +735,7 @@ class FroxlorInstall } if ($do_backup) { - $command = $mysql_dump . " " . $this->_data['mysql_database'] . " -u " . $this->_data['mysql_root_user'] . " --password='" . $this->_data['mysql_root_pass'] . "' --result-file=" . $filename; + $command = $mysql_dump . " " . escapeshellarg($this->_data['mysql_database']) . " -u " . escapeshellarg($this->_data['mysql_root_user']) . " --password='" . $this->_data['mysql_root_pass'] . "' --result-file=" . $filename; $output = exec($command); if (stristr($output, "error")) { $content .= $this->_status_message('red', $this->_lng['install']['backup_failed']); From 7e361274c5bf687b6a42dd1871f6d75506c5d207 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 6 Mar 2020 20:44:17 +0100 Subject: [PATCH 012/319] forgot one escapeshellarg() and enhanced security on userdata.inc.php creation when installing Signed-off-by: Michael Kaufmann --- install/lib/class.FroxlorInstall.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index dc67120f..4884a87e 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -333,18 +333,18 @@ class FroxlorInstall // test if we can store the userdata.inc.php in ../lib $userdata_file = dirname(dirname(dirname(__FILE__))) . '/lib/userdata.inc.php'; - if ($fp = @fopen($userdata_file, 'w')) { - $result = @fputs($fp, $userdata, strlen($userdata)); + if (@touch($userdata_file) && @chmod($userdata_file, 0400) && @is_writable($userdata_file)) { + $fp = @fopen($userdata_file, 'w'); + @fputs($fp, $userdata, strlen($userdata)); @fclose($fp); $content .= $this->_status_message('green', 'OK'); - chmod($userdata_file, 0440); } else { // try creating it in a temporary file - $temp_file = tempnam(sys_get_temp_dir(), 'fx'); - if (touch($temp_file)) { + $temp_file = @tempnam(sys_get_temp_dir(), 'fx'); + if ($temp_file) { chmod($temp_file, 0400); $fp = @fopen($temp_file, 'w'); - $result = @fputs($fp, $userdata, strlen($userdata)); + @fputs($fp, $userdata, strlen($userdata)); @fclose($fp); $content .= $this->_status_message('orange', sprintf($this->_lng['install']['creating_configfile_temp'], $temp_file)); } else { @@ -568,7 +568,7 @@ class FroxlorInstall for ($i = 0; $i < sizeof($sql_query); $i ++) { if (trim($sql_query[$i]) != '') { try { - $result = $db->query($sql_query[$i]); + $db->query($sql_query[$i]); } catch (\PDOException $e) { $content .= $this->_status_message('red', $e->getMessage()); $fatal_fail = true; @@ -735,7 +735,7 @@ class FroxlorInstall } if ($do_backup) { - $command = $mysql_dump . " " . escapeshellarg($this->_data['mysql_database']) . " -u " . escapeshellarg($this->_data['mysql_root_user']) . " --password='" . $this->_data['mysql_root_pass'] . "' --result-file=" . $filename; + $command = $mysql_dump . " " . escapeshellarg($this->_data['mysql_database']) . " -u " . escapeshellarg($this->_data['mysql_root_user']) . " --password='" . escapeshellarg($this->_data['mysql_root_pass']) . "' --result-file=" . $filename; $output = exec($command); if (stristr($output, "error")) { $content .= $this->_status_message('red', $this->_lng['install']['backup_failed']); From 32b62855890345af1f78a4c82eb78e5b461f2fcf Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 6 Mar 2020 20:47:20 +0100 Subject: [PATCH 013/319] set version to 0.10.14 for upcoming release Signed-off-by: Michael Kaufmann --- install/froxlor.sql | 4 ++-- install/updates/froxlor/0.10/update_0.10.inc.php | 5 +++++ lib/Froxlor/Froxlor.php | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index 3034a104..ae08d5dc 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -84,7 +84,7 @@ CREATE TABLE `panel_activation` ( `creation` int(11) unsigned NOT NULL default '0', `activationcode` varchar(50) default NULL, PRIMARY KEY (id) -) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci; +) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci; DROP TABLE IF EXISTS `panel_admins`; @@ -704,7 +704,7 @@ opcache.interned_strings_buffer'), ('panel', 'password_special_char', '!?<>§$%+#=@'), ('panel', 'customer_hide_options', ''), ('panel', 'is_configured', '0'), - ('panel', 'version', '0.10.13'), + ('panel', 'version', '0.10.14'), ('panel', 'db_version', '202002290'); diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index fa421aeb..61faadfd 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -592,3 +592,8 @@ if (\Froxlor\Froxlor::isDatabaseVersion('201912313')) { \Froxlor\Froxlor::updateToDbVersion('202002290'); } + +if (\Froxlor\Froxlor::isFroxlorVersion('0.10.13')) { + showUpdateStep("Updating from 0.10.13 to 0.10.14", false); + \Froxlor\Froxlor::updateToVersion('0.10.14'); +} diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index 3ea62d39..9dd03ade 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -7,7 +7,7 @@ final class Froxlor { // Main version variable - const VERSION = '0.10.13'; + const VERSION = '0.10.14'; // Database version (YYYYMMDDC where C is a daily counter) const DBVERSION = '202002290'; From cf2c7fa31c3ca0c8bd6f182570203ce520294b42 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 6 Mar 2020 22:03:41 +0100 Subject: [PATCH 014/319] deny api access to deactivated users with valid api-key Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/FroxlorRPC.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Froxlor/Api/FroxlorRPC.php b/lib/Froxlor/Api/FroxlorRPC.php index f4dce617..f5af0cf2 100644 --- a/lib/Froxlor/Api/FroxlorRPC.php +++ b/lib/Froxlor/Api/FroxlorRPC.php @@ -60,7 +60,7 @@ class FroxlorRPC FROM `api_keys` ak LEFT JOIN `panel_admins` a ON a.adminid = ak.adminid LEFT JOIN `panel_customers` c ON c.customerid = ak.customerid - WHERE `apikey` = :ak AND `secret` = :as + WHERE `apikey` = :ak AND `secret` = :as AND c.deactivated = 0 "); $result = \Froxlor\Database\Database::pexecute_first($sel_stmt, array( 'ak' => $key, From d7550ae58a434562bde13d3f98155d498653e817 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 6 Mar 2020 22:10:01 +0100 Subject: [PATCH 015/319] fix deactivated check in api Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/FroxlorRPC.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Froxlor/Api/FroxlorRPC.php b/lib/Froxlor/Api/FroxlorRPC.php index f5af0cf2..3a21f330 100644 --- a/lib/Froxlor/Api/FroxlorRPC.php +++ b/lib/Froxlor/Api/FroxlorRPC.php @@ -56,18 +56,18 @@ class FroxlorRPC private static function validateAuth($key, $secret) { $sel_stmt = \Froxlor\Database\Database::prepare(" - SELECT ak.*, a.api_allowed as admin_api_allowed, c.api_allowed as cust_api_allowed + SELECT ak.*, a.api_allowed as admin_api_allowed, c.api_allowed as cust_api_allowed, c.deactivated FROM `api_keys` ak LEFT JOIN `panel_admins` a ON a.adminid = ak.adminid LEFT JOIN `panel_customers` c ON c.customerid = ak.customerid - WHERE `apikey` = :ak AND `secret` = :as AND c.deactivated = 0 + WHERE `apikey` = :ak AND `secret` = :as "); $result = \Froxlor\Database\Database::pexecute_first($sel_stmt, array( 'ak' => $key, 'as' => $secret ), 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))) { + 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 if (! empty($result['allowed_from'])) { // @todo allow specification and validating of whole subnets later From 02c5f808546f4350c6754e7b61bf735688082435 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 8 Mar 2020 07:35:19 +0100 Subject: [PATCH 016/319] correct chmod value for userdata.inc.php file to be written on installation; fixes #815 Signed-off-by: Michael Kaufmann --- customer_email.php | 1 - install/lib/class.FroxlorInstall.php | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/customer_email.php b/customer_email.php index 3e8bd67e..8a9902de 100644 --- a/customer_email.php +++ b/customer_email.php @@ -19,7 +19,6 @@ define('AREA', 'customer'); require './lib/init.php'; -use Froxlor\Api\Commands\SubDomains; use Froxlor\Database\Database; use Froxlor\Settings; use Froxlor\Api\Commands\Emails as Emails; diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index 4884a87e..c00ebe85 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -333,16 +333,17 @@ class FroxlorInstall // test if we can store the userdata.inc.php in ../lib $userdata_file = dirname(dirname(dirname(__FILE__))) . '/lib/userdata.inc.php'; - if (@touch($userdata_file) && @chmod($userdata_file, 0400) && @is_writable($userdata_file)) { + if (@touch($userdata_file) && @chmod($userdata_file, 0600) && @is_writable($userdata_file)) { $fp = @fopen($userdata_file, 'w'); @fputs($fp, $userdata, strlen($userdata)); @fclose($fp); $content .= $this->_status_message('green', 'OK'); } else { + @unlink($userdata_file); // try creating it in a temporary file $temp_file = @tempnam(sys_get_temp_dir(), 'fx'); if ($temp_file) { - chmod($temp_file, 0400); + chmod($temp_file, 0600); $fp = @fopen($temp_file, 'w'); @fputs($fp, $userdata, strlen($userdata)); @fclose($fp); From 13767df562c229872e829c952014a01c5c909814 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 8 Mar 2020 07:39:39 +0100 Subject: [PATCH 017/319] set version to 0.10.15 for bugfix release Signed-off-by: Michael Kaufmann --- install/froxlor.sql | 2 +- install/updates/froxlor/0.10/update_0.10.inc.php | 5 +++++ lib/Froxlor/Froxlor.php | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index ae08d5dc..ff23c704 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -704,7 +704,7 @@ opcache.interned_strings_buffer'), ('panel', 'password_special_char', '!?<>§$%+#=@'), ('panel', 'customer_hide_options', ''), ('panel', 'is_configured', '0'), - ('panel', 'version', '0.10.14'), + ('panel', 'version', '0.10.15'), ('panel', 'db_version', '202002290'); diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index 61faadfd..b0bc4ad9 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -597,3 +597,8 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.13')) { showUpdateStep("Updating from 0.10.13 to 0.10.14", false); \Froxlor\Froxlor::updateToVersion('0.10.14'); } + +if (\Froxlor\Froxlor::isFroxlorVersion('0.10.14')) { + showUpdateStep("Updating from 0.10.14 to 0.10.15", false); + \Froxlor\Froxlor::updateToVersion('0.10.15'); +} diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index 9dd03ade..ac95a448 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -7,7 +7,7 @@ final class Froxlor { // Main version variable - const VERSION = '0.10.14'; + const VERSION = '0.10.15'; // Database version (YYYYMMDDC where C is a daily counter) const DBVERSION = '202002290'; From 1fe9f1e9d6151f464ca3746e279159a2c0961ef0 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 8 Mar 2020 10:30:33 +0100 Subject: [PATCH 018/319] fix language strings for cron cmdline setting and fallback to php binary if no setting is found Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/CronConfig.php | 2 +- lng/english.lng.php | 2 +- lng/german.lng.php | 2 +- lng/italian.lng.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Froxlor/Cron/CronConfig.php b/lib/Froxlor/Cron/CronConfig.php index 5c8e5cfc..774c5f51 100644 --- a/lib/Froxlor/Cron/CronConfig.php +++ b/lib/Froxlor/Cron/CronConfig.php @@ -99,7 +99,7 @@ class CronConfig $binpath = Settings::Get("system.croncmdline"); // fallback as it is important if ($binpath === null) { - $binpath = "/usr/bin/nice -n 5 /usr/bin/php5 -q"; + $binpath = "/usr/bin/nice -n 5 /usr/bin/php -q"; } $cronfile .= "root " . $binpath . " " . \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . "/scripts/froxlor_master_cronjob.php") . " --" . $row_cronentry['cronfile'] . " 1> /dev/null\n"; diff --git a/lng/english.lng.php b/lng/english.lng.php index db12fe4d..b33e0983 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -1697,7 +1697,7 @@ $lng['admin']['integrityresult'] = 'Result'; $lng['admin']['integrityfix'] = 'Fix problems automatically'; $lng['question']['admin_integritycheck_reallyfix'] = 'Do you really want to try fixing all database integrity problems automatically?'; $lng['serversettings']['system_croncmdline']['title'] = 'Cron execution command (php-binary)'; -$lng['serversettings']['system_croncmdline']['description'] = 'Command to execute our cronjobs. Change this only if you know what you are doing (default: "/usr/bin/nice -n 5 /usr/bin/php5 -q")!'; +$lng['serversettings']['system_croncmdline']['description'] = 'Command to execute our cronjobs. Change this only if you know what you are doing (default: "/usr/bin/nice -n 5 /usr/bin/php -q")!'; $lng['error']['cannotdeletehostnamephpconfig'] = 'This PHP-configuration is used by the Froxlor-vhost and cannot be deleted.'; $lng['error']['cannotdeletedefaultphpconfig'] = 'This PHP-configuration is set as default and cannot be deleted.'; $lng['serversettings']['system_cron_allowautoupdate']['title'] = 'Allow automatic database updates'; diff --git a/lng/german.lng.php b/lng/german.lng.php index 74dc5acb..d8f9d76c 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -1421,7 +1421,7 @@ $lng['admin']['integrityresult'] = 'Ergebnis'; $lng['admin']['integrityfix'] = 'Probleme automatisch beheben'; $lng['question']['admin_integritycheck_reallyfix'] = 'Möchten Sie wirklich versuchen sämtliche Datenbank-Integritätsprobleme automatisch zu beheben?'; $lng['serversettings']['system_croncmdline']['title'] = 'Cron Startbefehl (php Programm)'; -$lng['serversettings']['system_croncmdline']['description'] = 'Befehl zum Ausführen des Cronjobs. Ändern dieser Einstellung nur wenn nötig (Standard: "/usr/bin/nice -n 5 /usr/bin/php5 -q")!'; +$lng['serversettings']['system_croncmdline']['description'] = 'Befehl zum Ausführen des Cronjobs. Ändern dieser Einstellung nur wenn nötig (Standard: "/usr/bin/nice -n 5 /usr/bin/php -q")!'; $lng['error']['cannotdeletehostnamephpconfig'] = 'Diese PHP-Konfiguration ist dem Froxlor-Vhost zugewiesen und kann daher nicht gelöscht werden.'; $lng['error']['cannotdeletedefaultphpconfig'] = 'Diese PHP-Konfiguration ist als Standard hinterlegt und kann daher nicht gelöscht werden.'; $lng['serversettings']['system_cron_allowautoupdate']['title'] = 'Erlaube automatische Datenbank-Aktualisierungen'; diff --git a/lng/italian.lng.php b/lng/italian.lng.php index fd6e21e6..6489824f 100644 --- a/lng/italian.lng.php +++ b/lng/italian.lng.php @@ -1635,7 +1635,7 @@ $lng['admin']['integrityresult'] = 'Risultato'; $lng['admin']['integrityfix'] = 'Risolvi problemi automaticamente'; $lng['question']['admin_integritycheck_reallyfix'] = 'Vuoi veramente provare a risolvere i problemi di integrità del database automaticamente?'; $lng['serversettings']['system_croncmdline']['title'] = 'Commando di esecuzione Cron (binario php)'; -$lng['serversettings']['system_croncmdline']['description'] = 'Commando per eseguire i nostri cronjob. Modificalo soltanto se sai cosa stai facendo (predefinito: "/usr/bin/nice -n 5 /usr/bin/php5 -q")!'; +$lng['serversettings']['system_croncmdline']['description'] = 'Commando per eseguire i nostri cronjob. Modificalo soltanto se sai cosa stai facendo (predefinito: "/usr/bin/nice -n 5 /usr/bin/php -q")!'; $lng['error']['cannotdeletehostnamephpconfig'] = 'Questa configurazione PHP è utilizzata dal vhost Froxlor e non può essere eliminata.'; $lng['error']['cannotdeletedefaultphpconfig'] = 'Questa configurazione PHP è impostata come predefinita e non può essere eliminata.'; $lng['serversettings']['system_cron_allowautoupdate']['title'] = 'Permetti aggiornamenti automatici del database'; From a4431e25d3bde52f2d8f2deb1b95a359bf3c1475 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Tue, 10 Mar 2020 07:36:22 +0100 Subject: [PATCH 019/319] remove ssl-certificates connected to domains that are being deleted when deleting a customer; fixes #818 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Customers.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/Froxlor/Api/Commands/Customers.php b/lib/Froxlor/Api/Commands/Customers.php index 8bb2616c..47e309f4 100644 --- a/lib/Froxlor/Api/Commands/Customers.php +++ b/lib/Froxlor/Api/Commands/Customers.php @@ -1410,7 +1410,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource 'id' => $id ), true, true); - // first gather all domain-id's to clean up panel_domaintoip and dns-entries accordingly + // first gather all domain-id's to clean up panel_domaintoip, dns-entries and certificates accordingly $did_stmt = Database::prepare("SELECT `id` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :id"); Database::pexecute($did_stmt, array( 'id' => $id @@ -1426,6 +1426,11 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource Database::pexecute($stmt, array( 'did' => $row['id'] ), true, true); + // remove domain->certificates entries + $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :did"); + Database::pexecute($stmt, array( + 'did' => $row['id'] + ), true, true); } // remove customer domains $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :id"); From a46e7a3bc4cf89e7fdbbcaf03c8c1f8a75c7a573 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Tue, 10 Mar 2020 07:48:35 +0100 Subject: [PATCH 020/319] set correct umask to create user config in installation Signed-off-by: Michael Kaufmann --- install/lib/class.FroxlorInstall.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index c00ebe85..33dc8434 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -332,8 +332,9 @@ class FroxlorInstall $userdata .= "?>"; // test if we can store the userdata.inc.php in ../lib + $umask = @umask(077); $userdata_file = dirname(dirname(dirname(__FILE__))) . '/lib/userdata.inc.php'; - if (@touch($userdata_file) && @chmod($userdata_file, 0600) && @is_writable($userdata_file)) { + if (@touch($userdata_file) && @is_writable($userdata_file)) { $fp = @fopen($userdata_file, 'w'); @fputs($fp, $userdata, strlen($userdata)); @fclose($fp); @@ -343,7 +344,6 @@ class FroxlorInstall // try creating it in a temporary file $temp_file = @tempnam(sys_get_temp_dir(), 'fx'); if ($temp_file) { - chmod($temp_file, 0600); $fp = @fopen($temp_file, 'w'); @fputs($fp, $userdata, strlen($userdata)); @fclose($fp); @@ -354,6 +354,7 @@ class FroxlorInstall eval("\$content .= \"" . $this->_getTemplate("textarea") . "\";"); } } + @umask($umask); return $content; } From 489ccbe07ab04050a80efa777b471648be798d2d Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Thu, 12 Mar 2020 07:01:26 +0100 Subject: [PATCH 021/319] fix removing ip address if ip is set as system-ipaddress but there are other entries of that ip with a different port Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/IpsAndPorts.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Froxlor/Api/Commands/IpsAndPorts.php b/lib/Froxlor/Api/Commands/IpsAndPorts.php index 9b349080..e9492132 100644 --- a/lib/Froxlor/Api/Commands/IpsAndPorts.php +++ b/lib/Froxlor/Api/Commands/IpsAndPorts.php @@ -560,7 +560,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour 'ip' => $result['ip'] )); - if (($result['ip'] != Settings::Get('system.ipaddress')) || ($result['ip'] == Settings::Get('system.ipaddress') && $result_sameipotherport == false)) { + 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 . "` From 474558172012219b6bcf03df70df96077999dc69 Mon Sep 17 00:00:00 2001 From: HBerni Date: Sat, 21 Mar 2020 16:39:01 +0100 Subject: [PATCH 022/319] fixed parsing due to changes in dovecots default mail_log_prefix regex supports old and new default format now (see https://wiki2.dovecot.org/Upgrading/2.3) --- lib/Froxlor/MailLogParser.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Froxlor/MailLogParser.php b/lib/Froxlor/MailLogParser.php index f8800e89..4a9ef696 100644 --- a/lib/Froxlor/MailLogParser.php +++ b/lib/Froxlor/MailLogParser.php @@ -209,12 +209,12 @@ class MailLogParser $timestamp = $this->getLogTimestamp($line); if ($this->startTime < $timestamp) { - if (preg_match("/dovecot.*(?::|\]) imap\(.*@([a-z0-9\.\-]+)\):.*(?:in=(\d+) out=(\d+)|bytes=(\d+)\/(\d+))/i", $line, $matches)) { + 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[2] + (int) $matches[3], $timestamp); - } elseif (preg_match("/dovecot.*(?::|\]) pop3\(.*@([a-z0-9\.\-]+)\):.*in=(\d+).*out=(\d+)/i", $line, $matches)) { + $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[2] + (int) $matches[3], $timestamp); + $this->addDomainTraffic($matches[1], (int) $matches[3] + (int) $matches[4], $timestamp); } } } From 048e6c13aeab4d31c3eaefd8d0dd6f2a2ba14269 Mon Sep 17 00:00:00 2001 From: Christian Schneider Date: Sun, 29 Mar 2020 22:36:26 +0200 Subject: [PATCH 023/319] Fix renewal of ECC/ECDSA certificates. The ACME v2 implementation uses separate directoies for ECC and on-ECC certificates. The renew command for a domain checks if an ECC directory exists (having a "_ecc" suffix) and refuses the command unless the "--ecc" flag was specified. Confusingly, this flag is only required to *renew* an ECC certificate, but not to issue it. This fixes https://github.com/Froxlor/Froxlor/issues/820. --- lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index 2515783a..7b8cbcae 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -327,6 +327,9 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron } if (Settings::Get('system.leecc') > 0) { $acmesh_cmd .= " --keylength ec-" . Settings::Get('system.leecc'); + if ($cert_mode != 'issue') { + $acmesh_cmd .= " --ecc"; + } } else { $acmesh_cmd .= " --keylength " . Settings::Get('system.letsencryptkeysize'); } From 0d35f5cb29e6b609d6eb64ed12d23bd8c504a469 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sat, 4 Apr 2020 18:04:39 +0200 Subject: [PATCH 024/319] restructure acmesh implementation and let acme.sh take care of renewing the certificates itself; fixes #792, fixes #816 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 684 ++++++++++--------- 1 file changed, 374 insertions(+), 310 deletions(-) diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index 7b8cbcae..2a9fa2ed 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -45,7 +45,328 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron public static $no_inserttask = false; - private static function needRenew() + /** + * run the task + * + * @param boolean $internal + * @return number + */ + 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) { + // 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 + $needRenew = self::issueDomains(); + if ($needRenew || self::issueFroxlorVhost()) { + // insert task to generate certificates and vhost-configs + \Froxlor\System\Cronjob::inserttask(1); + } + return 0; + } + + // set server according to settings + self::$apiserver = 'https://acme-' . (Settings::Get('system.letsencryptca') == 'testing' ? 'staging-' : '') . 'v0' . \Froxlor\Settings::Get('system.leapiversion') . '.api.letsencrypt.org/directory'; + + // validate acme.sh installation + self::checkInstall(); + + // flag for re-generation of vhost files + $changedetected = 0; + + // prepare update sql + self::$updcert_stmt = Database::prepare(" + REPLACE INTO + `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` + SET + `id` = :id, + `domainid` = :domainid, + `ssl_cert_file` = :crt, + `ssl_key_file` = :key, + `ssl_ca_file` = :ca, + `ssl_cert_chainfile` = :chain, + `ssl_csr_file` = :csr, + `ssl_fullchain_file` = :fullchain, + `expirationdate` = :expirationdate + "); + + // prepare domain update sql + self::$upddom_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `ssl_redirect` = '1' WHERE `id` = :domainid"); + + // check whether there are certificates to issue + $issue_froxlor = self::issueFroxlorVhost(); + $issue_domains = self::issueDomains(); + + // first - generate LE for system-vhost if enabled + if ($issue_froxlor) { + // build row + $certrow = array( + 'loginname' => 'froxlor.panel', + 'domain' => Settings::Get('system.hostname'), + 'domainid' => 0, + 'documentroot' => \Froxlor\Froxlor::getInstallDir(), + 'leprivatekey' => Settings::Get('system.leprivatekey'), + 'lepublickey' => Settings::Get('system.lepublickey'), + 'leregistered' => Settings::Get('system.leregistered'), + 'ssl_redirect' => Settings::Get('system.le_froxlor_redirect'), + 'expirationdate' => null, + 'ssl_cert_file' => null, + 'ssl_key_file' => null, + 'ssl_ca_file' => null, + 'ssl_csr_file' => null, + 'id' => null + ); + + // add to queue + $issue_domains[] = $certrow; + } + + if (count($issue_domains)) { + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Requesting " . count($issue_domains) . " new Let's Encrypt certificates"); + self::runIssueFor($issue_domains); + $changedetected = 1; + } + + // compare file-system certificates with the ones in our database + // and update if needed + $renew_domains = self::renewDomains(); + foreach ($renew_domains as $domain) { + $cronlog = FroxlorLogger::getInstanceOf(array( + 'loginname' => $domain['loginname'], + 'adminsession' => 0 + )); + if (defined('CRON_IS_FORCED') || self::checkFsFilesAreNewer($domain['domain'], $domain['expirationdate'])) { + self::certToDb($domain, $cronlog, array()); + $changedetected = 1; + } + } + + // If we have a change in a certificate, we need to update the webserver - configs + // This is easiest done by just creating a new task ;) + if ($changedetected) { + if (self::$no_inserttask == false) { + \Froxlor\System\Cronjob::inserttask(1); + } + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Let's Encrypt certificates have been updated"); + } else { + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "No new certificates or certificate updates found"); + } + } + + /** + * 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::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"); + } + } + } + + private static function runAcmeSh($certrow = array(), $domains = array(), &$cronlog = null, $force = false) + { + if (! empty($domains)) { + + if (self::$do_update) { + self::checkUpgrade(); + self::$do_update = false; + } + + $acmesh_cmd = self::$acmesh . " --auto-upgrade 0 --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') == 'testing') { + $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($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 certificat for froxlor itself + * + * @return boolean + */ + private static function issueFroxlorVhost() + { + if (Settings::Get('system.le_froxlor_enabled') == '1') { + $froxlor_ssl_settings_stmt = Database::prepare(" + SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` + WHERE `domainid` = '0' AND `expirationdate` IS NULL + "); + $froxlor_ssl = Database::pexecute_first($froxlor_ssl_settings_stmt); + if ($froxlor_ssl) { + return true; + } + } + return false; + } + + /** + * get a list of domains that have a lets encrypt certificate (possible renew) + */ + private static function renewDomains() + { + $certificates_stmt = Database::query(" + SELECT + domssl.`id`, + domssl.`domainid`, + domssl.`expirationdate`, + domssl.`ssl_cert_file`, + domssl.`ssl_key_file`, + dom.`domain`, + dom.`id` AS 'domainid', + dom.`ssl_redirect`, + cust.`loginname` + FROM + `" . TABLE_PANEL_CUSTOMERS . "` AS cust, + `" . TABLE_PANEL_DOMAINS . "` AS dom + LEFT JOIN + `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` AS domssl ON + dom.`id` = domssl.`domainid` + WHERE + dom.`customerid` = cust.`customerid` + AND cust.deactivated = 0 + AND dom.`letsencrypt` = 1 + AND dom.`aliasdomain` IS NULL + AND dom.`iswildcarddomain` = 0 + "); + $renew_certs = $certificates_stmt->fetchAll(\PDO::FETCH_ASSOC); + if ($renew_certs) { + return $renew_certs; + } + return array(); + } + + /** + * get a list of domains that require a new certificate (issue) + */ + private static function issueDomains() { $certificates_stmt = Database::query(" SELECT @@ -78,325 +399,51 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron AND dom.`letsencrypt` = 1 AND dom.`aliasdomain` IS NULL AND dom.`iswildcarddomain` = 0 - AND ( - domssl.`expirationdate` < DATE_ADD(NOW(), INTERVAL 30 DAY) - OR domssl.`expirationdate` IS NULL - ) + AND domssl.`expirationdate` IS NULL "); $customer_ssl = $certificates_stmt->fetchAll(\PDO::FETCH_ASSOC); - if (! $customer_ssl) { - $customer_ssl = array(); + if ($customer_ssl) { + return $customer_ssl; } - - $froxlor_ssl = array(); - if (Settings::Get('system.le_froxlor_enabled') == '1') { - $froxlor_ssl_settings_stmt = Database::prepare(" - SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` - WHERE `domainid` = '0' AND - (`expirationdate` < DATE_ADD(NOW(), INTERVAL 30 DAY) OR `expirationdate` IS NULL) - "); - $froxlor_ssl = Database::pexecute_first($froxlor_ssl_settings_stmt); - if (! $froxlor_ssl) { - $froxlor_ssl = array(); - } - } - - if (count($customer_ssl) > 0 || count($froxlor_ssl) > 0) { - return array( - 'customer_ssl' => $customer_ssl, - 'froxlor_ssl' => $froxlor_ssl - ); - } - return false; + return array(); } - public static function run($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 - $needRenew = self::needRenew(); - if ($needRenew) { - // insert task to generate certificates and vhost-configs - \Froxlor\System\Cronjob::inserttask(1); - } - return 0; - } - - self::checkInstall(); - - self::$apiserver = 'https://acme-'.(Settings::Get('system.letsencryptca') == 'testing' ? 'staging-' : '').'v0' . \Froxlor\Settings::Get('system.leapiversion') . '.api.letsencrypt.org/directory'; - - FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Requesting/renewing Let's Encrypt certificates"); - - $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 - "); - - self::$updcert_stmt = Database::prepare(" - REPLACE INTO - `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` - SET - `id` = :id, - `domainid` = :domainid, - `ssl_cert_file` = :crt, - `ssl_key_file` = :key, - `ssl_ca_file` = :ca, - `ssl_cert_chainfile` = :chain, - `ssl_csr_file` = :csr, - `ssl_fullchain_file` = :fullchain, - `expirationdate` = :expirationdate - "); - - self::$upddom_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `ssl_redirect` = '1' WHERE `id` = :domainid"); - - // flag for re-generation of vhost files - $changedetected = 0; - - $needRenew = self::needRenew(); - - // first - generate LE for system-vhost if enabled - if (Settings::Get('system.le_froxlor_enabled') == '1') { - - $certrow = array( - 'loginname' => 'froxlor.panel', - 'domain' => Settings::Get('system.hostname'), - 'domainid' => 0, - 'documentroot' => \Froxlor\Froxlor::getInstallDir(), - 'leprivatekey' => Settings::Get('system.leprivatekey'), - 'lepublickey' => Settings::Get('system.lepublickey'), - 'leregistered' => Settings::Get('system.leregistered'), - 'ssl_redirect' => Settings::Get('system.le_froxlor_redirect'), - 'expirationdate' => null, - 'ssl_cert_file' => null, - 'ssl_key_file' => null, - 'ssl_ca_file' => null, - 'ssl_csr_file' => null, - 'id' => null - ); - - $froxlor_ssl = $needRenew ? $needRenew['froxlor_ssl'] : array(); - - $cert_mode = 'issue'; - if (count($froxlor_ssl) > 0) { - $cert_mode = 'renew'; - $certrow['id'] = $froxlor_ssl['id']; - $certrow['expirationdate'] = $froxlor_ssl['expirationdate']; - $certrow['ssl_cert_file'] = $froxlor_ssl['ssl_cert_file']; - $certrow['ssl_key_file'] = $froxlor_ssl['ssl_key_file']; - $certrow['ssl_ca_file'] = $froxlor_ssl['ssl_ca_file']; - $certrow['ssl_csr_file'] = $froxlor_ssl['ssl_csr_file']; - } else { - // check whether we have an entry with valid certificates which just does not need - // updating yet, so we need to skip this here - $froxlor_ssl_settings_stmt = Database::prepare(" - 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'])) { - $cert_mode = false; - } - } - - if ($cert_mode) { - $domains = array( - strtolower($certrow['domain']) - ); - - $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))) { - $domains[] = strtolower(trim($falias)); - } - } - } - - // Only renew let's encrypt certificate if no broken ssl_redirect is enabled - // - this temp. deactivation of the ssl-redirect is handled by the webserver-cronjob - $do_force = false; - if ($cert_mode == 'renew') { - FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Updating certificate for " . $certrow['domain']); - } else { - $do_force = true; - FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Creating certificate for " . $certrow['domain']); - } - - $cronlog = FroxlorLogger::getInstanceOf(array( - 'loginname' => $certrow['loginname'], - 'adminsession' => 0 - )); - - self::runAcmeSh($certrow, $domains, $cert_mode, $cronlog, $changedetected, $do_force); - } - } - - // customer domains - $certrows = $needRenew ? $needRenew['customer_ssl'] : array(); - foreach ($certrows as $certrow) { - - // initialize mode to 'issue' - $cert_mode = 'issue'; - - // 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 renew 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'])) { - $cert_mode = 'renew'; - $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Updating certificate for " . $certrow['domain']); - } else 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 SAN entry: " . $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']); - } - - // 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::runAcmeSh($certrow, $domains, $cert_mode, $cronlog, $changedetected, $do_force); - } else { - $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $certrow['domain'] . " due to an enabled ssl_redirect"); - } - } - - // If we have a change in a certificate, we need to update the webserver - configs - // This is easiest done by just creating a new task ;) - if ($changedetected) { - if (self::$no_inserttask == false) { - \Froxlor\System\Cronjob::inserttask(1); - } - FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Let's Encrypt certificates have been updated"); - } else { - FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "No new certificates or certificates due for renewal found"); - } - } - - private static function runAcmeSh($certrow = array(), $domains = array(), $cert_mode = 'issue', &$cronlog = null, &$changedetected = 0, $force = false) - { - if (! empty($domains)) { - - if (self::$do_update) { - self::checkUpgrade(); - self::$do_update = false; - } - - $acmesh_cmd = self::$acmesh . " --auto-upgrade 0 --server " . self::$apiserver . " --" . $cert_mode . " -d " . implode(" -d ", $domains); - - if ($cert_mode == 'issue') { - $acmesh_cmd .= " -w " . Settings::Get('system.letsencryptchallengepath'); - } - if (Settings::Get('system.leecc') > 0) { - $acmesh_cmd .= " --keylength ec-" . Settings::Get('system.leecc'); - if ($cert_mode != 'issue') { - $acmesh_cmd .= " --ecc"; - } - } 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') == 'testing') { - $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)); - - $return = array(); - self::readCertificateToVar($certrow['domain'], $return); - - 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']); - $changedetected = 1; - } 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)); - } - } - } - - private static function readCertificateToVar($domain, &$return) + private static function checkFsFilesAreNewer($domain, $cert_date = 0) { $certificate_folder = dirname(self::$acmesh) . "/" . $domain; if (Settings::Get('system.leecc') > 0) { $certificate_folder .= "_ecc"; } $certificate_folder = \Froxlor\FileDir::makeCorrectDir($certificate_folder); + $ssl_file = \Froxlor\FileDir::makeCorrectFile($certificate_folder . '/' . $domain . '.cer'); - if (is_dir($certificate_folder)) { + if (is_dir($certificate_folder) && file_exists($ssl_file) && is_readable($ssl_file)) { + $cert_data = openssl_x509_parse(file_get_contents($ssl_file)); + if (strtotime($cert_data['validTo_time_t']) > strtotime($cert_date)) { + return true; + } + } + return false; + } + + /** + * get certificate files from filesystem and store in $return array + * + * @param string $domain + * @param array $return + * @param object $cronlog + */ + private static function readCertificateToVar($domain, &$return, &$cronlog) + { + $certificate_folder = dirname(self::$acmesh) . "/" . $domain; + $certificate_folder_noecc = null; + if (Settings::Get('system.leecc') > 0) { + $certificate_folder_noecc = \Froxlor\FileDir::makeCorrectDir($certificate_folder); + $certificate_folder .= "_ecc"; + } + $certificate_folder = \Froxlor\FileDir::makeCorrectDir($certificate_folder); + + if (is_dir($certificate_folder) || is_dir($certificate_folder_noecc)) { foreach ([ 'crt' => $domain . '.cer', 'key' => $domain . '.key', @@ -408,12 +455,26 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron 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 (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); + continue; + } + } + $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Could not find file '" . $sslfile . "' in '" . $certificate_folder . "'"); $return[$index] = null; } } + } else { + $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() { if (! file_exists(self::$acmesh)) { @@ -425,11 +486,14 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron } } + /** + * run upgrade + */ private static function checkUpgrade() { $acmesh_result = \Froxlor\FileDir::safe_exec(self::$acmesh . " --upgrade"); - // check for activated cron (which is installed automatically) but we don't need it - $acmesh_result2 = \Froxlor\FileDir::safe_exec(self::$acmesh . " --uninstall-cronjob"); + // check for activated cron + $acmesh_result2 = \Froxlor\FileDir::safe_exec(self::$acmesh . " --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)); } } From 8bdd843bd95314d7b0fbe02ead379fe5eda03496 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Wed, 8 Apr 2020 09:07:48 +0200 Subject: [PATCH 025/319] fix renew of froxlors own letsencrypt certificate; fix only variables should be passed by reference in BackupCron; fix possible notice or double inclusion of language file in ReportsCron Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 58 ++++++++++++++++++-- lib/Froxlor/Cron/System/BackupCron.php | 3 +- lib/Froxlor/Cron/Traffic/ReportsCron.php | 6 +- 3 files changed, 60 insertions(+), 7 deletions(-) diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index 2a9fa2ed..716f06c0 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -130,7 +130,30 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron // compare file-system certificates with the ones in our database // and update if needed + $renew_froxlor = self::renewFroxlorVhost(); $renew_domains = self::renewDomains(); + + if ($renew_froxlor) { + // build row + $certrow = array( + 'loginname' => 'froxlor.panel', + 'domain' => Settings::Get('system.hostname'), + 'domainid' => 0, + 'documentroot' => \Froxlor\Froxlor::getInstallDir(), + 'leprivatekey' => Settings::Get('system.leprivatekey'), + 'lepublickey' => Settings::Get('system.lepublickey'), + 'leregistered' => Settings::Get('system.leregistered'), + 'ssl_redirect' => Settings::Get('system.le_froxlor_redirect'), + 'expirationdate' => is_array($renew_froxlor) ? $renew_froxlor['expirationdate'] : date('Y-m-d H:i:s', 0), + 'ssl_cert_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_cert_file'] : null, + 'ssl_key_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_key_file'] : null, + 'ssl_ca_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_ca_file'] : null, + 'ssl_csr_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_csr_file'] : null, + 'id' => is_array($renew_froxlor) ? $renew_froxlor['id'] : null + ); + $renew_domains[] = $certrow; + } + foreach ($renew_domains as $domain) { $cronlog = FroxlorLogger::getInstanceOf(array( 'loginname' => $domain['loginname'], @@ -308,25 +331,49 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron } /** - * check whether we need to issue a new certificat for froxlor itself + * check whether we need to issue a new certificate for froxlor itself * * @return boolean */ private static function issueFroxlorVhost() { if (Settings::Get('system.le_froxlor_enabled') == '1') { + // let's encrypt is enabled, now check whether we have a certificate $froxlor_ssl_settings_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` - WHERE `domainid` = '0' AND `expirationdate` IS NULL + WHERE `domainid` = '0' "); $froxlor_ssl = Database::pexecute_first($froxlor_ssl_settings_stmt); - if ($froxlor_ssl) { + // also check for possible existing certificate + if (! $froxlor_ssl && ! self::checkFsFilesAreNewer(Settings::Get('system.hostname'), date('Y-m-d H:i:s'))) { return true; } } return false; } + /** + * check whether we need to renew-check the certificate for froxlor itself + * + * @return boolean + */ + private static function renewFroxlorVhost() + { + if (Settings::Get('system.le_froxlor_enabled') == '1') { + // let's encrypt is enabled, now check whether we have a certificate + $froxlor_ssl_settings_stmt = Database::prepare(" + SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` + WHERE `domainid` = '0' + "); + $froxlor_ssl = Database::pexecute_first($froxlor_ssl_settings_stmt); + // also check for possible existing certificate + if ($froxlor_ssl || (! $froxlor_ssl && ! self::checkFsFilesAreNewer(Settings::Get('system.hostname'), date('Y-m-d H:i:s', 0)))) { + return ($froxlor_ssl ? $froxlor_ssl : true); + } + } + return false; + } + /** * get a list of domains that have a lets encrypt certificate (possible renew) */ @@ -357,6 +404,9 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron AND dom.`iswildcarddomain` = 0 "); $renew_certs = $certificates_stmt->fetchAll(\PDO::FETCH_ASSOC); + if (self::renewFroxlorVhost()) { + // add froxlor to the list of renews + } if ($renew_certs) { return $renew_certs; } @@ -455,7 +505,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron if (file_exists($ssl_file)) { $return[$index] = file_get_contents($ssl_file); } else { - if (!empty($certificate_folder_noecc)) { + if (! empty($certificate_folder_noecc)) { $ssl_file_fb = \Froxlor\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"); diff --git a/lib/Froxlor/Cron/System/BackupCron.php b/lib/Froxlor/Cron/System/BackupCron.php index 0b817d31..899e7717 100644 --- a/lib/Froxlor/Cron/System/BackupCron.php +++ b/lib/Froxlor/Cron/System/BackupCron.php @@ -77,6 +77,7 @@ class BackupCron extends \Froxlor\Cron\FroxlorCron $del_stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_TASKS . "` WHERE `id` = :id"); + $cronlog = FroxlorLogger::getInstanceOf(); $all_jobs = $result_tasks_stmt->fetchAll(); foreach ($all_jobs as $row) { @@ -96,7 +97,7 @@ class BackupCron extends \Froxlor\Cron\FroxlorCron \Froxlor\FileDir::safe_exec('mkdir -p ' . escapeshellarg($row['data']['destdir'])); } - self::createCustomerBackup($row['data'], $customerdocroot, FroxlorLogger::getInstanceOf()); + self::createCustomerBackup($row['data'], $customerdocroot, $cronlog); } } diff --git a/lib/Froxlor/Cron/Traffic/ReportsCron.php b/lib/Froxlor/Cron/Traffic/ReportsCron.php index d2fd7829..aaa2403c 100644 --- a/lib/Froxlor/Cron/Traffic/ReportsCron.php +++ b/lib/Froxlor/Cron/Traffic/ReportsCron.php @@ -394,13 +394,15 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron $lngfile = Database::pexecute_first($lngfile_stmt, array( 'deflang' => Settings::Get('panel.standardlanguage') )); - $langfile = $lngfile['file']; + $langfile = $lngfile['file'] ?? 'lng/english.lng.php'; } // include english language file (fallback) include_once \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/lng/english.lng.php'); // include admin/customer language file - include_once \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/' . $langfile); + if ($lngfile != 'lng/english.lng.php') { + include_once \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/' . $langfile); + } // Get mail templates from database; the ones from 'admin' are fetched for fallback $result2_stmt = Database::prepare(" From 9018404faa332461ecbc9e28f822888a6907b77b Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Tue, 14 Apr 2020 08:10:36 +0200 Subject: [PATCH 026/319] Double check whether installation of acme.sh worked when not installed yet and do not continue if not; fixes #823 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index 716f06c0..f20e6be6 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -70,7 +70,9 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron self::$apiserver = 'https://acme-' . (Settings::Get('system.letsencryptca') == 'testing' ? 'staging-' : '') . 'v0' . \Froxlor\Settings::Get('system.leapiversion') . '.api.letsencrypt.org/directory'; // validate acme.sh installation - self::checkInstall(); + if (! self::checkInstall()) { + return - 1; + } // flag for re-generation of vhost files $changedetected = 0; @@ -525,15 +527,22 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron /** * install acme.sh if not found yet */ - private static function checkInstall() + private static function checkInstall($tries = 0) { - if (! file_exists(self::$acmesh)) { + if (! file_exists(self::$acmesh) && $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::$acmesh . "'"); + echo PHP_EOL . "Download/installation of acme.sh seems to have failed. Re-run cronjob to try again or install manually to '" . self::$acmesh . "'" . PHP_EOL; + return false; + } else if (! file_exists(self::$acmesh)) { 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", $return, array( '|' )); + // check whether the installation worked + return self::checkInstall(++ $tries); } + return true; } /** From 78fc4f84b2fbaa47d531dcb9b956edcbd00cedd2 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Tue, 14 Apr 2020 10:28:33 +0200 Subject: [PATCH 027/319] add optional dns validation for let's encrypt activated domains; fixes #817 Signed-off-by: Michael Kaufmann --- actions/admin/settings/131.ssl.php | 6 +-- install/froxlor.sql | 4 +- .../updates/froxlor/0.10/update_0.10.inc.php | 10 +++++ install/updates/preconfig.php | 3 ++ .../preconfig/0.10/preconfig_0.10.inc.php | 42 +++++++++++++++++++ lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 31 ++++++++++++++ lib/Froxlor/Domain/Domain.php | 35 ++++++++++++++++ lib/Froxlor/Froxlor.php | 2 +- lng/english.lng.php | 4 +- lng/german.lng.php | 4 +- 10 files changed, 131 insertions(+), 10 deletions(-) create mode 100644 install/updates/preconfig/0.10/preconfig_0.10.inc.php diff --git a/actions/admin/settings/131.ssl.php b/actions/admin/settings/131.ssl.php index 9cc89308..fe37a1dc 100644 --- a/actions/admin/settings/131.ssl.php +++ b/actions/admin/settings/131.ssl.php @@ -214,11 +214,11 @@ return array( 'save_method' => 'storeSettingField' ), 'system_disable_le_selfcheck' => array( - 'label' => $lng['serversettings']['disable_le_selfcheck'], + 'label' => $lng['serversettings']['le_domain_dnscheck'], 'settinggroup' => 'system', - 'varname' => 'disable_le_selfcheck', + 'varname' => 'le_domain_dnscheck', 'type' => 'bool', - 'default' => false, + 'default' => true, 'save_method' => 'storeSettingField' ) ) diff --git a/install/froxlor.sql b/install/froxlor.sql index ff23c704..544edc1d 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -654,7 +654,7 @@ opcache.interned_strings_buffer'), ('system', 'leregistered', '0'), ('system', 'leaccount', ''), ('system', 'nssextrausers', '0'), - ('system', 'disable_le_selfcheck', '0'), + ('system', 'le_domain_dnscheck', '1'), ('system', 'ssl_protocols', 'TLSv1,TLSv1.2'), ('system', 'tlsv13_cipher_list', ''), ('system', 'honorcipherorder', '0'), @@ -705,7 +705,7 @@ opcache.interned_strings_buffer'), ('panel', 'customer_hide_options', ''), ('panel', 'is_configured', '0'), ('panel', 'version', '0.10.15'), - ('panel', 'db_version', '202002290'); + ('panel', 'db_version', '202004140'); DROP TABLE IF EXISTS `panel_tasks`; diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index b0bc4ad9..b554ea9d 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -602,3 +602,13 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.14')) { showUpdateStep("Updating from 0.10.14 to 0.10.15", false); \Froxlor\Froxlor::updateToVersion('0.10.15'); } + +if (\Froxlor\Froxlor::isDatabaseVersion('202002290')) { + showUpdateStep("Adding new setting to validate DNS when using Let's Encrypt"); + Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'system' AND `varname` = 'disable_le_selfcheck'"); + $le_domain_dnscheck = isset($_POST['system_le_domain_dnscheck']) ? (int) $_POST['system_le_domain_dnscheck'] : '1'; + Settings::AddNew("system.le_domain_dnscheck", $le_domain_dnscheck); + lastStepStatus(0); + + \Froxlor\Froxlor::updateToDbVersion('202004140'); +} diff --git a/install/updates/preconfig.php b/install/updates/preconfig.php index c2fd9dcf..e0f601c5 100644 --- a/install/updates/preconfig.php +++ b/install/updates/preconfig.php @@ -34,6 +34,9 @@ function getPreConfig($current_version, $current_db_version) include_once \Froxlor\FileDir::makeCorrectFile(dirname(__FILE__) . '/preconfig/0.9/preconfig_0.9.inc.php'); parseAndOutputPreconfig($has_preconfig, $return, $current_version, $current_db_version); + include_once \Froxlor\FileDir::makeCorrectFile(dirname(__FILE__) . '/preconfig/0.10/preconfig_0.10.inc.php'); + parseAndOutputPreconfig2($has_preconfig, $return, $current_version, $current_db_version); + $return .= '

' . \Froxlor\UI\HTML::makecheckbox('update_changesagreed', 'I have read the update notifications above and I am aware of the changes made to my system.', '1', true, '0', true); $return .= ''; $return .= ''; diff --git a/install/updates/preconfig/0.10/preconfig_0.10.inc.php b/install/updates/preconfig/0.10/preconfig_0.10.inc.php new file mode 100644 index 00000000..91c9e140 --- /dev/null +++ b/install/updates/preconfig/0.10/preconfig_0.10.inc.php @@ -0,0 +1,42 @@ + (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Updater + * + */ + +/** + * checks if the new-version has some updating to do + * + * @param boolean $has_preconfig + * pointer to check if any preconfig has to be output + * @param string $return + * pointer to output string + * @param string $current_version + * current froxlor version + * + * @return null + */ +function parseAndOutputPreconfig2(&$has_preconfig, &$return, $current_version, $current_db_version) +{ + global $lng; + + if (versionInUpdate($current_db_version, '202004140')) { + $has_preconfig = true; + $description = 'Froxlor can now optionally validate the dns entries of domains that request Lets Encrypt certificates to reduce dns-related problems (e.g. freshly registered domain or updated a-record).
'; + $question = 'Validate DNS of domains when using Lets Encrypt '; + $question .= \Froxlor\UI\HTML::makeyesno('system_le_domain_dnscheck', '1', '0', '1'); + + eval("\$return.=\"" . \Froxlor\UI\Template::getTemplate("update/preconfigitem") . "\";"); + } +} diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index f20e6be6..436c018e 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -4,6 +4,8 @@ namespace Froxlor\Cron\Http\LetsEncrypt; use Froxlor\FroxlorLogger; use Froxlor\Settings; use Froxlor\Database\Database; +use Froxlor\PhpHelper; +use Froxlor\Domain\Domain; /** * This file is part of the Froxlor project. @@ -248,6 +250,9 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron } } } + + 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"); @@ -255,6 +260,32 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron } } + /** + * 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(&$domains = array(), $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 accordint to NS + $domain_ips = PhpHelper::gethostbynamel6($domain); + if (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]); + } + } + } + } + private static function runAcmeSh($certrow = array(), $domains = array(), &$cronlog = null, $force = false) { if (! empty($domains)) { diff --git a/lib/Froxlor/Domain/Domain.php b/lib/Froxlor/Domain/Domain.php index bb0d2d7f..8072019b 100644 --- a/lib/Froxlor/Domain/Domain.php +++ b/lib/Froxlor/Domain/Domain.php @@ -6,6 +6,41 @@ use Froxlor\Database\Database; class Domain { + /** + * return all ip addresses associated with given domain, + * returns all ips if domain-id = 0 (froxlor.vhost) + * + * @param int $domain_id + * @return array + */ + public static function getIpsOfDomain($domain_id) + { + if ($domain_id > 0) { + $sel_stmt = Database::prepare(" + SELECT i.ip FROM `" . TABLE_PANEL_IPSANDPORTS . "` `i` + LEFT JOIN `" . TABLE_DOMAINTOIP . "` `dip` ON dip.id_ipandports = i.id + AND dip.id_domain = :domainid + GROUP BY i.ip + "); + $sel_param = array( + '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(); + } + Database::pexecute($sel_stmt, $sel_param); + $result = array(); + while ($ip = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) { + $result[] = $ip['ip']; + } + return $result; + } + /** * return an array of all enabled redirect-codes * diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index ac95a448..c7e2eefd 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -10,7 +10,7 @@ final class Froxlor const VERSION = '0.10.15'; // Database version (YYYYMMDDC where C is a daily counter) - const DBVERSION = '202002290'; + const DBVERSION = '202004140'; // Distribution branding-tag (used for Debian etc.) const BRANDING = ''; diff --git a/lng/english.lng.php b/lng/english.lng.php index b33e0983..30e71497 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -1982,8 +1982,8 @@ $lng['admin']['domain_http2']['title'] = 'HTTP2 support'; $lng['admin']['domain_http2']['description'] = 'See Wikipedia for a detailed explanation of HTTP2'; $lng['admin']['testmail'] = 'SMTP test'; $lng['success']['testmailsent'] = 'Test mail sent successfully'; -$lng['serversettings']['disable_le_selfcheck']['title'] = "Disable Let's Encrypt local self-check"; -$lng['serversettings']['disable_le_selfcheck']['description'] = "If activated, froxlor will not perform its self-check for token accessibility. Needed for NATed IP's or similar."; +$lng['serversettings']['le_domain_dnscheck']['title'] = "Validate DNS of domains when using Let's Encrypt"; +$lng['serversettings']['le_domain_dnscheck']['description'] = "If activated, froxlor will validate whether the domain which requests a Let's Encrypt certificate resolves to at least one of the system ip addresses."; $lng['menue']['phpsettings']['fpmdaemons'] = 'PHP-FPM versions'; $lng['admin']['phpsettings']['activephpconfigs'] = 'In use for php-config(s)'; $lng['admin']['phpsettingsforsubdomains'] = 'Apply php-config to all subdomains:'; diff --git a/lng/german.lng.php b/lng/german.lng.php index d8f9d76c..df3f5d2f 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -1632,8 +1632,8 @@ $lng['admin']['domain_http2']['title'] = 'HTTP2 Unterstützung'; $lng['admin']['domain_http2']['description'] = 'Siehe Wikipedia für eine ausführliche Beschreibung von HTTP2'; $lng['admin']['testmail'] = 'SMTP Test'; $lng['success']['testmailsent'] = 'Test E-Mail erfolgreich gesendet'; -$lng['serversettings']['disable_le_selfcheck']['title'] = "Deaktiviere Let's Encrypt lokale Selbstprüfung"; -$lng['serversettings']['disable_le_selfcheck']['description'] = "Wenn aktiviert wird Froxlor keine Erreichbarkeitsprüfung des Tokens vornehmen. Nötig bei ge-NAT-eten IP-Adressen oder Ähnlichem"; +$lng['serversettings']['le_domain_dnscheck']['title'] = "Validiere DNS der Domains wenn Let's Encrypt genutzt wird"; +$lng['serversettings']['le_domain_dnscheck']['description'] = "Wenn aktiviert wird froxlor überprüfen ob die DNS Einträge der Domains, welche ein Let's Encrypt Zertifikat beantragt, mindestens auf eine der System IP Adressen auflöst."; $lng['menue']['phpsettings']['fpmdaemons'] = 'PHP-FPM Versionen'; $lng['admin']['phpsettings']['activephpconfigs'] = 'In Verwendung für PHP-Konfiguration(en)'; $lng['admin']['phpsettingsforsubdomains'] = 'PHP-Config für alle Subdomains übernehmen:'; From 8dace6eca5474ab838799947d08d4eca88087df9 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Tue, 28 Apr 2020 07:56:38 +0200 Subject: [PATCH 028/319] remove special characters from name when generating extrausers file add froxlor hostname to 2fa-qrcode; refs #814 Signed-off-by: Michael Kaufmann --- 2fa.php | 2 +- lib/Froxlor/Cron/System/Extrausers.php | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/2fa.php b/2fa.php index dd73110b..9bd5f2cd 100644 --- a/2fa.php +++ b/2fa.php @@ -38,7 +38,7 @@ if (AREA == 'admin') { } $success_message = ""; -$tfa = new \Froxlor\FroxlorTwoFactorAuth('Froxlor'); +$tfa = new \Froxlor\FroxlorTwoFactorAuth('Froxlor ' . Settings::Get('system.hostname')); // do the delete and then just show a success-message if ($action == 'delete') { diff --git a/lib/Froxlor/Cron/System/Extrausers.php b/lib/Froxlor/Cron/System/Extrausers.php index e837c683..74f1aea5 100644 --- a/lib/Froxlor/Cron/System/Extrausers.php +++ b/lib/Froxlor/Cron/System/Extrausers.php @@ -67,7 +67,7 @@ class Extrausers 'name' => \Froxlor\Customer\Customer::getCustomerDetail($u['customerid'], 'name'), 'company' => \Froxlor\Customer\Customer::getCustomerDetail($u['customerid'], 'company') ); - $u['comment'] = \Froxlor\User::getCorrectUserSalutation($salutation_array); + $u['comment'] = self::cleanString(\Froxlor\User::getCorrectUserSalutation($salutation_array)); if ($u['login_enabled'] != 'Y') { $u['password'] = '*'; $u['shell'] = '/bin/false'; @@ -90,4 +90,10 @@ class Extrausers $cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Error when writing ' . $type . ' file entries'); } } + + private static function cleanString($string = null) + { + $allowed = "/[^a-z0-9\\.\\-\\_\\ ]/i"; + return preg_replace($allowed, "", $string); + } } From 98c636c282b35ed1797f976a85fa8090319f8d14 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Thu, 30 Apr 2020 13:03:19 +0200 Subject: [PATCH 029/319] let send-to-alternative-email be optional if no address is given instead of displaying error that the email address is invalid; fixes #829 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/EmailAccounts.php | 6 +++--- lng/english.lng.php | 1 + lng/german.lng.php | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/Froxlor/Api/Commands/EmailAccounts.php b/lib/Froxlor/Api/Commands/EmailAccounts.php index 0a06f524..d9396ee2 100644 --- a/lib/Froxlor/Api/Commands/EmailAccounts.php +++ b/lib/Froxlor/Api/Commands/EmailAccounts.php @@ -100,8 +100,8 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso // 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 (! \Froxlor\Validate\Validate::validateEmail($alternative_email)) { - \Froxlor\UI\Response::standard_error('emailiswrong', $alternative_email, true); + if (!empty($alternative_email) && ! \Froxlor\Validate\Validate::validateEmail($alternative_email)) { + \Froxlor\UI\Response::standard_error('alternativeemailiswrong', $alternative_email, true); } } else { $alternative_email = ''; @@ -236,7 +236,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso $this->mailer()->clearAddresses(); // customer wants to send the e-mail to an alternative email address too - if (Settings::Get('panel.sendalternativemail') == 1) { + 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, $this->lng['mails']['pop_success_alternative']['subject']); // get template for mail body diff --git a/lng/english.lng.php b/lng/english.lng.php index 30e71497..f6ccd8dd 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -204,6 +204,7 @@ $lng['error']['mydomain'] = '\'Domain\''; $lng['error']['mydocumentroot'] = '\'Documentroot\''; $lng['error']['loginnameexists'] = 'Loginname %s already exists'; $lng['error']['emailiswrong'] = 'Email-address %s contains invalid characters or is incomplete'; +$lng['error']['alternativeemailiswrong'] = 'The given alternative email address %s to send the credentials to seems to be invalid'; $lng['error']['loginnameiswrong'] = 'Loginname "%s" contains illegal characters.'; $lng['error']['loginnameiswrong2'] = 'Loginname contains too many characters. Only %s characters are allowed.'; $lng['error']['userpathcombinationdupe'] = 'Combination of username and path already exists'; diff --git a/lng/german.lng.php b/lng/german.lng.php index df3f5d2f..2e55bbb1 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -202,6 +202,7 @@ $lng['error']['mydomain'] = '\'Domain\''; $lng['error']['mydocumentroot'] = '\'Documentroot\''; $lng['error']['loginnameexists'] = 'Der Login-Name "%s" existiert bereits.'; $lng['error']['emailiswrong'] = 'Die E-Mail-Adresse "%s" enthält ungültige Zeichen oder ist nicht vollständig.'; +$lng['error']['alternativeemailiswrong'] = 'Die angegebene alternative E-Mail Adresse "%s", an welche die Zugangsdaten geschickt werden soll, scheint ungültig zu sein.'; $lng['error']['loginnameiswrong'] = 'Der Login-Name "%s" enthält ungültige Zeichen.'; $lng['error']['loginnameiswrong2'] = 'Der Login-Name enthält zu viele Zeichen, es sind maximal %s Zeichen erlaubt.'; $lng['error']['userpathcombinationdupe'] = 'Die Kombination aus Benutzername und Pfad existiert bereits.'; From 43070e4808728fa7f6f94f905654ea1d00956ddb Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Thu, 30 Apr 2020 19:49:20 +0200 Subject: [PATCH 030/319] remove possible trailing slash of apache DocumentRoot diretives as sugggested by the httpd-docs, thx to jonbert Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/Http/Apache.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Froxlor/Cron/Http/Apache.php b/lib/Froxlor/Cron/Http/Apache.php index 80fc8cc9..921faf3d 100644 --- a/lib/Froxlor/Cron/Http/Apache.php +++ b/lib/Froxlor/Cron/Http/Apache.php @@ -172,7 +172,7 @@ class Apache extends HttpConfigBase $mypath = $this->getMyPath($row_ipsandports); - $this->virtualhosts_data[$vhosts_filename] .= 'DocumentRoot "' . $mypath . '"' . "\n"; + $this->virtualhosts_data[$vhosts_filename] .= 'DocumentRoot "' . rtrim($mypath, "/") . '"' . "\n"; if ($row_ipsandports['vhostcontainer_servername_statement'] == '1') { $this->virtualhosts_data[$vhosts_filename] .= ' ServerName ' . Settings::Get('system.hostname') . "\n"; @@ -661,7 +661,7 @@ class Apache extends HttpConfigBase if ($domain['deactivated'] == '1' && Settings::Get('system.deactivateddocroot') != '') { $webroot_text .= ' # Using docroot for deactivated users...' . "\n"; - $webroot_text .= ' DocumentRoot "' . \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.deactivateddocroot')) . "\"\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') { @@ -674,7 +674,7 @@ class Apache extends HttpConfigBase $webroot_text .= ' ' . "\n"; $this->deactivated = true; } else { - $webroot_text .= ' DocumentRoot "' . $domain['documentroot'] . "\"\n"; + $webroot_text .= ' DocumentRoot "' . rtrim($domain['documentroot'], "/") . "\"\n"; $this->deactivated = false; } From a02a081c6b5705027884f7a4dbd33ef49558975f Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Thu, 30 Apr 2020 20:03:54 +0200 Subject: [PATCH 031/319] try to fix travis irc notifications Signed-off-by: Michael Kaufmann --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4148f43a..4448cde3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,7 +58,7 @@ after_success: - bash <(curl -s https://codecov.io/bash) -f "build/logs/clover.xml" notifications: - irc: "irc.freenode.org#froxlor" + irc: "chat.freenode.org#froxlor" webhooks: urls: - https://webhooks.gitter.im/e/bdf91d1c3f745e51f796 From 14413a3e8d3d4c23ac9ab090d1400bf249a2e847 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Thu, 30 Apr 2020 20:10:52 +0200 Subject: [PATCH 032/319] try to fix travis irc notifications again Signed-off-by: Michael Kaufmann --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4448cde3..e058cf32 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,7 +58,7 @@ after_success: - bash <(curl -s https://codecov.io/bash) -f "build/logs/clover.xml" notifications: - irc: "chat.freenode.org#froxlor" + irc: "chat.freenode.net#froxlor" webhooks: urls: - https://webhooks.gitter.im/e/bdf91d1c3f745e51f796 From b3db4dd8877379db83dcfa67c5fd24f02ce9a787 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 1 May 2020 16:27:23 +0200 Subject: [PATCH 033/319] set version to 0.10.16 for upcoming release Signed-off-by: Michael Kaufmann --- install/froxlor.sql | 2 +- install/updates/froxlor/0.10/update_0.10.inc.php | 5 +++++ lib/Froxlor/Froxlor.php | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index 544edc1d..e6214ef6 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -704,7 +704,7 @@ opcache.interned_strings_buffer'), ('panel', 'password_special_char', '!?<>§$%+#=@'), ('panel', 'customer_hide_options', ''), ('panel', 'is_configured', '0'), - ('panel', 'version', '0.10.15'), + ('panel', 'version', '0.10.16'), ('panel', 'db_version', '202004140'); diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index b554ea9d..8541feb4 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -612,3 +612,8 @@ if (\Froxlor\Froxlor::isDatabaseVersion('202002290')) { \Froxlor\Froxlor::updateToDbVersion('202004140'); } + +if (\Froxlor\Froxlor::isFroxlorVersion('0.10.15')) { + showUpdateStep("Updating from 0.10.15 to 0.10.16", false); + \Froxlor\Froxlor::updateToVersion('0.10.16'); +} diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index c7e2eefd..b333b3c6 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -7,7 +7,7 @@ final class Froxlor { // Main version variable - const VERSION = '0.10.15'; + const VERSION = '0.10.16'; // Database version (YYYYMMDDC where C is a daily counter) const DBVERSION = '202004140'; From c0dd432916f846ac66e473a9f0382a4002bb3e00 Mon Sep 17 00:00:00 2001 From: Andreas Grundler Date: Mon, 4 May 2020 12:08:20 +0200 Subject: [PATCH 034/319] Certificate file cannot be read to database if the domain contains capital letters. --- lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index 436c018e..59f5f653 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -20,9 +20,9 @@ use Froxlor\Domain\Domain; * @author Froxlor team (2016-) * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt * @package Cron - * + * * @since 0.9.35 - * + * */ class AcmeSh extends \Froxlor\Cron\FroxlorCron { @@ -328,7 +328,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron private static function certToDb($certrow, &$cronlog, $acme_result) { $return = array(); - self::readCertificateToVar($certrow['domain'], $return, $cronlog); + self::readCertificateToVar(strtolower($certrow['domain']), $return, $cronlog); if (! empty($return['crt'])) { From edc702dafa67029f772ce71996753592f4a3686a Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 8 May 2020 09:58:45 +0200 Subject: [PATCH 035/319] check for required min version of php every time (frontend and cron), fixes #833 Signed-off-by: Michael Kaufmann --- lib/init.php | 11 +++++ scripts/froxlor_master_cronjob.php | 6 +++ .../Sparkle/misc/phprequirementfailed.tpl | 43 +++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 templates/Sparkle/misc/phprequirementfailed.tpl diff --git a/lib/init.php b/lib/init.php index acc2375c..75d6e4f6 100644 --- a/lib/init.php +++ b/lib/init.php @@ -20,6 +20,17 @@ // define default theme for configurehint, etc. $_deftheme = 'Sparkle'; +// validate correct php version +if (version_compare("7.0.0", PHP_VERSION, ">=")) { + // get hint-template + $vendor_hint = file_get_contents(dirname(__DIR__) . '/templates/' . $_deftheme . '/misc/phprequirementfailed.tpl'); + // replace values + $vendor_hint = str_replace("", "7.0.0", $vendor_hint); + $vendor_hint = str_replace("", PHP_VERSION, $vendor_hint); + $vendor_hint = str_replace("", date('Y', time()), $vendor_hint); + die($vendor_hint); +} + if (! file_exists(dirname(__DIR__) . '/vendor/autoload.php')) { // get hint-template $vendor_hint = file_get_contents(dirname(__DIR__) . '/templates/' . $_deftheme . '/misc/vendormissinghint.tpl'); diff --git a/scripts/froxlor_master_cronjob.php b/scripts/froxlor_master_cronjob.php index 900929fc..d30fe4e8 100644 --- a/scripts/froxlor_master_cronjob.php +++ b/scripts/froxlor_master_cronjob.php @@ -14,6 +14,12 @@ * @package Cron * */ + +// validate correct php version +if (version_compare("7.0.0", PHP_VERSION, ">=")) { + die('Froxlor requires at least php-7.0. Please validate that your php-cli version and the cron execution command are correct.'); +} + require dirname(__DIR__) . '/vendor/autoload.php'; \Froxlor\Cron\MasterCron::setArguments($argv); diff --git a/templates/Sparkle/misc/phprequirementfailed.tpl b/templates/Sparkle/misc/phprequirementfailed.tpl new file mode 100644 index 00000000..40639184 --- /dev/null +++ b/templates/Sparkle/misc/phprequirementfailed.tpl @@ -0,0 +1,43 @@ + + + + + + + + + + Froxlor Server Management Panel - Requirements not met + + +
+ +
+
+ Froxlor Server Management Panel +
+ +
+
+
Whoops!
+
+

It seems you are using an older version of PHP

+

 

+

Froxlor requires at least PHP version
The installed version is:

+
+
+ +
+ +
+ +
+ + + From bddf9b496cf4ae946ecc9ec5249318747e79a6b9 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 15 May 2020 09:35:20 +0200 Subject: [PATCH 036/319] enable internal api-call to bypass customer_hide_options check in certain situations where it is needed, fixes #803 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/ApiCommand.php | 47 +++++++++++++++----- lib/Froxlor/Api/Commands/Emails.php | 3 +- lib/Froxlor/Api/Commands/SubDomains.php | 2 +- lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 3 -- tests/Emails/EmailsTest.php | 6 +++ 5 files changed, 46 insertions(+), 15 deletions(-) diff --git a/lib/Froxlor/Api/ApiCommand.php b/lib/Froxlor/Api/ApiCommand.php index 065a9090..77fc415e 100644 --- a/lib/Froxlor/Api/ApiCommand.php +++ b/lib/Froxlor/Api/ApiCommand.php @@ -54,6 +54,13 @@ abstract class ApiCommand extends ApiParameter */ private $mail = null; + /** + * whether the call is an internal one or not + * + * @var boolean + */ + private $internal_call = false; + /** * language strings array * @@ -90,10 +97,12 @@ abstract class ApiCommand extends ApiParameter * optional, array of parameters (var=>value) for the command * @param array $userinfo * optional, passed via WebInterface (instead of $header) + * @param boolean $internal + * optional whether called internally, default false * * @throws \Exception */ - public function __construct($header = null, $params = null, $userinfo = null) + public function __construct($header = null, $params = null, $userinfo = null, $internal = false) { parent::__construct($params); @@ -127,6 +136,9 @@ abstract class ApiCommand extends ApiParameter if ($this->debug) { $this->logger()->logAction(\Froxlor\FroxlorLogger::LOG_ERROR, LOG_DEBUG, "[API] " . get_called_class() . ": " . json_encode($params, JSON_UNESCAPED_SLASHES)); } + + // set internal call flag + $this->internal_call = $internal; } /** @@ -191,13 +203,15 @@ abstract class ApiCommand extends ApiParameter * 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) + public static function getLocal($userinfo = null, $params = null, $internal = false) { - return new static(null, $params, $userinfo); + return new static(null, $params, $userinfo, $internal); } /** @@ -210,6 +224,16 @@ abstract class ApiCommand extends ApiParameter return $this->is_admin; } + /** + * internal call flag + * + * @return boolean + */ + protected function isInternal() + { + return $this->internal_call; + } + /** * return field from user-table * @@ -241,7 +265,7 @@ abstract class ApiCommand extends ApiParameter * 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] - * + * * @return string */ protected function getSearchWhere(&$query_fields = array(), $append = false) @@ -304,7 +328,7 @@ abstract class ApiCommand extends ApiParameter * optional, limit resultset, default 0 * @param int $sql_offset * optional, offset for limitation, default 0 - * + * * @return string */ protected function getLimit() @@ -333,7 +357,7 @@ abstract class ApiCommand extends ApiParameter * 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] - * + * * @return string */ protected function getOrderBy($append = false) @@ -417,15 +441,18 @@ abstract class ApiCommand extends ApiParameter * * @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) + 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)->{$function}(); + $json_result = $module::getLocal($this->getUserData(), $params, $internal)->{$function}(); return json_decode($json_result, true)['data']; } @@ -491,7 +518,7 @@ abstract class ApiCommand extends ApiParameter $customer_ids[] = $customer['customerid']; } } else { - if (! empty($customer_hide_option) && \Froxlor\Settings::IsInList('panel.customer_hide_options', $customer_hide_option)) { + if (!$this->isInternal() && ! empty($customer_hide_option) && \Froxlor\Settings::IsInList('panel.customer_hide_options', $customer_hide_option)) { throw new \Exception("You cannot access this resource", 405); } $customer_ids = array( diff --git a/lib/Froxlor/Api/Commands/Emails.php b/lib/Froxlor/Api/Commands/Emails.php index af1cd0a2..c22989c8 100644 --- a/lib/Froxlor/Api/Commands/Emails.php +++ b/lib/Froxlor/Api/Commands/Emails.php @@ -62,9 +62,10 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt } // 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( 'domainname' => $domain - )); + ), true); if ($domain_check['isemaildomain'] == 0) { \Froxlor\UI\Response::standard_error('maindomainnonexist', $domain, true); } diff --git a/lib/Froxlor/Api/Commands/SubDomains.php b/lib/Froxlor/Api/Commands/SubDomains.php index 18d332a3..3b7fbfb7 100644 --- a/lib/Froxlor/Api/Commands/SubDomains.php +++ b/lib/Froxlor/Api/Commands/SubDomains.php @@ -409,7 +409,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc ); } } else { - if (Settings::IsInList('panel.customer_hide_options', 'domains')) { + if (! $this->isInternal() && Settings::IsInList('panel.customer_hide_options', 'domains')) { throw new \Exception("You cannot access this resource", 405); } $result_stmt = Database::prepare(" diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index 59f5f653..4767732d 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -437,9 +437,6 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron AND dom.`iswildcarddomain` = 0 "); $renew_certs = $certificates_stmt->fetchAll(\PDO::FETCH_ASSOC); - if (self::renewFroxlorVhost()) { - // add froxlor to the list of renews - } if ($renew_certs) { return $renew_certs; } diff --git a/tests/Emails/EmailsTest.php b/tests/Emails/EmailsTest.php index c8879414..9e5df92a 100644 --- a/tests/Emails/EmailsTest.php +++ b/tests/Emails/EmailsTest.php @@ -25,6 +25,9 @@ class MailsTest extends TestCase { global $admin_userdata; + // set domains as hidden to test whether the internal flag works + Settings::Set('panel.customer_hide_options', 'domains', true); + // get customer $json_result = Customers::getLocal($admin_userdata, array( 'loginname' => 'test1' @@ -39,6 +42,9 @@ class MailsTest extends TestCase $result = json_decode($json_result, true)['data']; $this->assertEquals("info@test2.local", $result['email_full']); $this->assertEquals(0, $result['iscatchall']); + + // reset setting + Settings::Set('panel.customer_hide_options', '', true); } public function testAdminEmailsAdd() From eb3590dc340bf4336e9cf9677906d569a344ccfa Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 15 May 2020 09:49:53 +0200 Subject: [PATCH 037/319] add unique-key domainid to domain_ssl_settings table Signed-off-by: Michael Kaufmann --- install/froxlor.sql | 5 +++-- .../updates/froxlor/0.10/update_0.10.inc.php | 17 +++++++++++++++++ lib/Froxlor/Froxlor.php | 2 +- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index e6214ef6..b62423cc 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -705,7 +705,7 @@ opcache.interned_strings_buffer'), ('panel', 'customer_hide_options', ''), ('panel', 'is_configured', '0'), ('panel', 'version', '0.10.16'), - ('panel', 'db_version', '202004140'); + ('panel', 'db_version', '202005150'); DROP TABLE IF EXISTS `panel_tasks`; @@ -997,7 +997,8 @@ CREATE TABLE IF NOT EXISTS `domain_ssl_settings` ( `ssl_csr_file` mediumtext, `ssl_fullchain_file` mediumtext, `expirationdate` datetime DEFAULT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + UNIQUE KEY (`domainid`) ) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci; diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index 8541feb4..e7d26e6e 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -617,3 +617,20 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.15')) { showUpdateStep("Updating from 0.10.15 to 0.10.16", false); \Froxlor\Froxlor::updateToVersion('0.10.16'); } + +if (\Froxlor\Froxlor::isDatabaseVersion('202004140')) { + + showUpdateStep("Adding unique key on domainid field in domain ssl table"); + // check for duplicate entries prior to set a unique key to avoid errors on update + Database::query(" + DELETE a.* FROM domain_ssl_settings AS a + LEFT JOIN domain_ssl_settings AS b ON UNIX_TIMESTAMP(b.`expirationdate`) > UNIX_TIMESTAMP(a.`expirationdate`) + AND (b.`domainid`=a.`domainid` OR (UNIX_TIMESTAMP(b.`expirationdate`) = UNIX_TIMESTAMP(a.`expirationdate`) AND b.`id`>a.`id`)) + WHERE b.`id` IS NOT NULL + GROUP BY a.`id` + "); + Database::query("ALTER TABLE `domain_ssl_settings` ADD UNIQUE(`domainid`)"); + lastStepStatus(0); + + \Froxlor\Froxlor::updateToDbVersion('202005150'); +} diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index b333b3c6..034c9374 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -10,7 +10,7 @@ final class Froxlor const VERSION = '0.10.16'; // Database version (YYYYMMDDC where C is a daily counter) - const DBVERSION = '202004140'; + const DBVERSION = '202005150'; // Distribution branding-tag (used for Debian etc.) const BRANDING = ''; From 6d90b5ba8035ca81c5cfff57a079dc4bcd071099 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 15 May 2020 09:56:24 +0200 Subject: [PATCH 038/319] remove leftover GROUP BY from testing Signed-off-by: Michael Kaufmann --- install/updates/froxlor/0.10/update_0.10.inc.php | 1 - 1 file changed, 1 deletion(-) diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index e7d26e6e..059e2fbd 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -627,7 +627,6 @@ if (\Froxlor\Froxlor::isDatabaseVersion('202004140')) { LEFT JOIN domain_ssl_settings AS b ON UNIX_TIMESTAMP(b.`expirationdate`) > UNIX_TIMESTAMP(a.`expirationdate`) AND (b.`domainid`=a.`domainid` OR (UNIX_TIMESTAMP(b.`expirationdate`) = UNIX_TIMESTAMP(a.`expirationdate`) AND b.`id`>a.`id`)) WHERE b.`id` IS NOT NULL - GROUP BY a.`id` "); Database::query("ALTER TABLE `domain_ssl_settings` ADD UNIQUE(`domainid`)"); lastStepStatus(0); From ecb9470b65f592cb980e289681b573671575ff91 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 15 May 2020 15:16:24 +0200 Subject: [PATCH 039/319] fix including of language-strings in reports-cron, fixes #836 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/Traffic/ReportsCron.php | 31 +++++++++++++++++------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/lib/Froxlor/Cron/Traffic/ReportsCron.php b/lib/Froxlor/Cron/Traffic/ReportsCron.php index aaa2403c..5019e519 100644 --- a/lib/Froxlor/Cron/Traffic/ReportsCron.php +++ b/lib/Froxlor/Cron/Traffic/ReportsCron.php @@ -55,7 +55,6 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron 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( 'name' => $row['name'], @@ -93,9 +92,11 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron } // include english language file (fallback) - include_once \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/lng/english.lng.php'); + include \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/lng/english.lng.php'); // include admin/customer language file - include_once \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/' . $langfile); + if ($lngfile != 'lng/english.lng.php') { + include \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/' . $langfile); + } // Get mail templates from database; the ones from 'admin' are fetched for fallback $result2_stmt = Database::prepare(" @@ -146,6 +147,8 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron Database::pexecute($upd_stmt, array( 'customerid' => $row['customerid'] )); + + unset($lng); } } @@ -195,9 +198,11 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron } // include english language file (fallback) - include_once \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/lng/english.lng.php'); + include \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/lng/english.lng.php'); // include admin/customer language file - include_once \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/' . $langfile); + if ($lngfile != 'lng/english.lng.php') { + include \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/' . $langfile); + } // Get mail templates from database; the ones from 'admin' are fetched for fallback $result2_stmt = Database::prepare(" @@ -326,6 +331,8 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron } $mail->ClearAddresses(); + + unset($lng); } } } // trafficmax > 0 @@ -398,10 +405,10 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron } // include english language file (fallback) - include_once \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/lng/english.lng.php'); + include \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/lng/english.lng.php'); // include admin/customer language file if ($lngfile != 'lng/english.lng.php') { - include_once \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/' . $langfile); + include \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/' . $langfile); } // Get mail templates from database; the ones from 'admin' are fetched for fallback @@ -453,6 +460,8 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron Database::pexecute($upd_stmt, array( 'customerid' => $row['customerid'] )); + + unset($lng); } } @@ -493,9 +502,11 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron } // include english language file (fallback) - include_once \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/lng/english.lng.php'); + include \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/lng/english.lng.php'); // include admin/customer language file - include_once \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/' . $langfile); + if ($lngfile != 'lng/english.lng.php') { + include \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . '/' . $langfile); + } // Get mail templates from database; the ones from 'admin' are fetched for fallback $result2_stmt = Database::prepare(" @@ -546,6 +557,8 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron Database::pexecute($upd_stmt, array( 'adminid' => $row['adminid'] )); + + unset($lng); } } } // webmax > 0 From 50f2047da375d05baf25a092b256ccd47381c5f5 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 15 May 2020 20:35:25 +0200 Subject: [PATCH 040/319] set version to 0.10.17 for upcoming maintenance release Signed-off-by: Michael Kaufmann --- install/froxlor.sql | 2 +- install/updates/froxlor/0.10/update_0.10.inc.php | 5 +++++ lib/Froxlor/Froxlor.php | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index b62423cc..f3e289f3 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -704,7 +704,7 @@ opcache.interned_strings_buffer'), ('panel', 'password_special_char', '!?<>§$%+#=@'), ('panel', 'customer_hide_options', ''), ('panel', 'is_configured', '0'), - ('panel', 'version', '0.10.16'), + ('panel', 'version', '0.10.17'), ('panel', 'db_version', '202005150'); diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index 059e2fbd..0c966205 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -633,3 +633,8 @@ if (\Froxlor\Froxlor::isDatabaseVersion('202004140')) { \Froxlor\Froxlor::updateToDbVersion('202005150'); } + +if (\Froxlor\Froxlor::isFroxlorVersion('0.10.16')) { + showUpdateStep("Updating from 0.10.16 to 0.10.17", false); + \Froxlor\Froxlor::updateToVersion('0.10.17'); +} diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index 034c9374..c436f2c4 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -7,7 +7,7 @@ final class Froxlor { // Main version variable - const VERSION = '0.10.16'; + const VERSION = '0.10.17'; // Database version (YYYYMMDDC where C is a daily counter) const DBVERSION = '202005150'; From c2e57dfd60e5b7858f2a78b206c09eb589cc03c3 Mon Sep 17 00:00:00 2001 From: Grigory Morozov Date: Mon, 18 May 2020 05:18:42 +0700 Subject: [PATCH 041/319] TLSv1 is deprecated --- lib/formfields/admin/domains/formfield.domains_add.php | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/formfields/admin/domains/formfield.domains_add.php b/lib/formfields/admin/domains/formfield.domains_add.php index 9ebfb3b6..b0c9ac5b 100644 --- a/lib/formfields/admin/domains/formfield.domains_add.php +++ b/lib/formfields/admin/domains/formfield.domains_add.php @@ -265,7 +265,6 @@ return array( 'desc' => $lng['serversettings']['ssl']['ssl_protocols']['description'], 'type' => 'checkbox', 'value' => array( - 'TLSv1', 'TLSv1.2' ), 'values' => array( From bc73ed0c75afd1d03797acdf84b6df413df39ba9 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Mon, 18 May 2020 20:48:04 +0200 Subject: [PATCH 042/319] adjust tls default value to tlsv1.2; refs #839 Signed-off-by: Michael Kaufmann --- actions/admin/settings/131.ssl.php | 2 +- install/froxlor.sql | 2 +- lng/english.lng.php | 2 +- lng/german.lng.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/actions/admin/settings/131.ssl.php b/actions/admin/settings/131.ssl.php index fe37a1dc..973dbf2b 100644 --- a/actions/admin/settings/131.ssl.php +++ b/actions/admin/settings/131.ssl.php @@ -35,7 +35,7 @@ return array( 'settinggroup' => 'system', 'varname' => 'ssl_protocols', 'type' => 'option', - 'default' => 'TLSv1,TLSv1.2', + 'default' => 'TLSv1.2', 'option_mode' => 'multiple', 'option_options' => array( 'TLSv1' => 'TLSv1', diff --git a/install/froxlor.sql b/install/froxlor.sql index f3e289f3..05fe3410 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -655,7 +655,7 @@ opcache.interned_strings_buffer'), ('system', 'leaccount', ''), ('system', 'nssextrausers', '0'), ('system', 'le_domain_dnscheck', '1'), - ('system', 'ssl_protocols', 'TLSv1,TLSv1.2'), + ('system', 'ssl_protocols', 'TLSv1.2'), ('system', 'tlsv13_cipher_list', ''), ('system', 'honorcipherorder', '0'), ('system', 'sessiontickets', '1'), diff --git a/lng/english.lng.php b/lng/english.lng.php index f6ccd8dd..4629a53b 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -1993,7 +1993,7 @@ $lng['serversettings']['leapiversion']['title'] = "Choose Let's Encrypt ACME imp $lng['serversettings']['leapiversion']['description'] = "Currently only ACME v2 implementation for Let's Encrypt is supported."; $lng['admin']['phpsettings']['pass_authorizationheader'] = 'Add "-pass-header Authorization" / "CGIPassAuth On" to vhosts'; $lng['serversettings']['ssl']['ssl_protocols']['title'] = 'Configure the TLS protocol version'; -$lng['serversettings']['ssl']['ssl_protocols']['description'] = 'This is a list of ssl protocols that you want (or don\'t want) to use when using SSL. Notice: Some older browsers may not support the newest protcol versions.

Default value is:
TLSv1, TLSv1.2
'; +$lng['serversettings']['ssl']['ssl_protocols']['description'] = 'This is a list of ssl protocols that you want (or don\'t want) to use when using SSL. Notice: Some older browsers may not support the newest protcol versions.

Default value is:
TLSv1.2
'; $lng['serversettings']['phpfpm_settings']['limit_extensions']['title'] = 'Allowed extensions'; $lng['serversettings']['phpfpm_settings']['limit_extensions']['description'] = 'Limits the extensions of the main script FPM will allow to parse. This can prevent configuration mistakes on the web server side. You should only limit FPM to .php extensions to prevent malicious users to use other extensions to execute php code. Default value: .php'; $lng['phpfpm']['ini_flags'] = 'Enter possible php_flags for php.ini. One entry per line'; diff --git a/lng/german.lng.php b/lng/german.lng.php index 2e55bbb1..c7287d0e 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -1643,7 +1643,7 @@ $lng['serversettings']['leapiversion']['title'] = "Wählen Sie die Let's Encrypt $lng['serversettings']['leapiversion']['description'] = "Aktuell unterstützt froxlor lediglich die ACME v2 Implementierung von Let's Encrypt."; $lng['admin']['phpsettings']['pass_authorizationheader'] = 'Füge "-pass-header Authorization" / "CGIPassAuth On" in Vhosts ein'; $lng['serversettings']['ssl']['ssl_protocols']['title'] = 'SSL Protokollversion festlegen'; -$lng['serversettings']['ssl']['ssl_protocols']['description'] = 'Dies ist eine Liste von SSL/TLS Protokollversionen die genutzt werden sollen (oder auch nicht genutzt werden sollen), wenn SSL verwendet wird. Hinweis: Ältere Browser sind möglicherweise nicht vollständig zum neusten Protokoll kompatibel.

Standard-Wert ist:
TLSv1, TLSv1.2
'; +$lng['serversettings']['ssl']['ssl_protocols']['description'] = 'Dies ist eine Liste von SSL/TLS Protokollversionen die genutzt werden sollen (oder auch nicht genutzt werden sollen), wenn SSL verwendet wird. Hinweis: Ältere Browser sind möglicherweise nicht vollständig zum neusten Protokoll kompatibel.

Standard-Wert ist:
TLSv1.2
'; $lng['serversettings']['phpfpm_settings']['limit_extensions']['title'] = 'Erlaubte Dateiendungen'; $lng['serversettings']['phpfpm_settings']['limit_extensions']['description'] = 'Beschränkt die Dateierweiterungen des Haupt-Skripts, das FPM zu parsen erlaubt. Dies kann Konfigurationsfehler auf der Webserverseite verhindern. Sie sollten FPM nur auf .php Erweiterungen beschränken, um zu verhindern, dass bösartige Nutzter andere Erweiterungen verwenden, um PHP Code auszuführen. Standardwert: .php'; $lng['phpfpm']['ini_flags'] = 'Mögliche php_flags für die php.ini. Pro Zeile eine Direktive'; From ffa9205f9547dffa4a86d3fdbabd9122e4b081e6 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Mon, 18 May 2020 20:48:48 +0200 Subject: [PATCH 043/319] fix sql query to remove duplicates before setting unique key in updater, fixes #840 Signed-off-by: Michael Kaufmann --- install/updates/froxlor/0.10/update_0.10.inc.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index 0c966205..7cdafb40 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -624,8 +624,9 @@ if (\Froxlor\Froxlor::isDatabaseVersion('202004140')) { // check for duplicate entries prior to set a unique key to avoid errors on update Database::query(" DELETE a.* FROM domain_ssl_settings AS a - LEFT JOIN domain_ssl_settings AS b ON UNIX_TIMESTAMP(b.`expirationdate`) > UNIX_TIMESTAMP(a.`expirationdate`) - AND (b.`domainid`=a.`domainid` OR (UNIX_TIMESTAMP(b.`expirationdate`) = UNIX_TIMESTAMP(a.`expirationdate`) AND b.`id`>a.`id`)) + LEFT JOIN domain_ssl_settings AS b ON + ((b.`domainid`=a.`domainid` AND UNIX_TIMESTAMP(b.`expirationdate`) > UNIX_TIMESTAMP(a.`expirationdate`)) + OR (UNIX_TIMESTAMP(b.`expirationdate`) = UNIX_TIMESTAMP(a.`expirationdate`) AND b.`id`>a.`id`)) WHERE b.`id` IS NOT NULL "); Database::query("ALTER TABLE `domain_ssl_settings` ADD UNIQUE(`domainid`)"); From 3b1ff03b33e77bfbf1b1f03e03ada6b2e53fa817 Mon Sep 17 00:00:00 2001 From: Ruben Barkow-Kuder Date: Sat, 23 May 2020 20:12:27 +0200 Subject: [PATCH 044/319] Don't suggest php5 during update as default --- install/updates/preconfig/0.9/preconfig_0.9.inc.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install/updates/preconfig/0.9/preconfig_0.9.inc.php b/install/updates/preconfig/0.9/preconfig_0.9.inc.php index 41af997f..122114c1 100644 --- a/install/updates/preconfig/0.9/preconfig_0.9.inc.php +++ b/install/updates/preconfig/0.9/preconfig_0.9.inc.php @@ -600,8 +600,8 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c if (versionInUpdate($current_version, '0.9.32-rc2')) { $has_preconfig = true; $description = 'To customize the command which executes the cronjob (php - basically) change the path below according to your system.

'; - $question = 'Please specify the command to execute cronscripts (default: "/usr/bin/nice -n 5 /usr/bin/php5 -q")
'; - $question .= '
'; + $question = 'Please specify the command to execute cronscripts (default: "/usr/bin/nice -n 5 /usr/bin/php -q")
'; + $question .= '
'; eval("\$return.=\"" . \Froxlor\UI\Template::getTemplate("update/preconfigitem") . "\";"); } From 65b2e4efa7dca9308b6d86a2353e733494d5525a Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sat, 23 May 2020 21:17:43 +0200 Subject: [PATCH 045/319] do not check for mariadb.sys user on mariadb-10.4 when testing with travis Signed-off-by: Michael Kaufmann --- tests/Mysqls/MysqlsTest.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Mysqls/MysqlsTest.php b/tests/Mysqls/MysqlsTest.php index 8d521452..d216c08b 100644 --- a/tests/Mysqls/MysqlsTest.php +++ b/tests/Mysqls/MysqlsTest.php @@ -210,6 +210,11 @@ class MysqlsTest extends TestCase $dbm = new \Froxlor\Database\DbManager(\Froxlor\FroxlorLogger::getInstanceOf()); $users = $dbm->getManager()->getAllSqlUsers(false); foreach ($users as $user => $data) { + if (TRAVIS_CI == 1 && strtolower($user) == 'mariadb.sys') { + // travis seems to have a user for mariadb on version 10.4 + // we do not want to test that one + continue; + } $this->assertNotEmpty($data['password'], 'No password for user "' . $user . '"'); } From 6ca79201473638332934fab50fe485ea197c31c9 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 24 May 2020 11:54:37 +0200 Subject: [PATCH 046/319] fix missing language files in config-services cli script; set ubuntu xenial deprecated, remove Ubuntu trusty; fix a2dismod command in buster config-template as php7.3 is default Signed-off-by: Michael Kaufmann --- .../Cli/Action/ConfigServicesAction.php | 5 + lib/configfiles/buster.xml | 2 +- lib/configfiles/trusty.xml | 1784 ----------------- lib/configfiles/xenial.xml | 2 +- 4 files changed, 7 insertions(+), 1786 deletions(-) delete mode 100644 lib/configfiles/trusty.xml diff --git a/lib/Froxlor/Cli/Action/ConfigServicesAction.php b/lib/Froxlor/Cli/Action/ConfigServicesAction.php index fccddc5f..73192a91 100644 --- a/lib/Froxlor/Cli/Action/ConfigServicesAction.php +++ b/lib/Froxlor/Cli/Action/ConfigServicesAction.php @@ -26,11 +26,16 @@ class ConfigServicesAction extends \Froxlor\Cli\Action */ private function validate() { + global $lng; + $this->checkConfigParam(true); $this->parseConfig(); require FROXLOR_INSTALL_DIR . '/lib/tables.inc.php'; + include_once FROXLOR_INSTALL_DIR . '/lng/english.lng.php'; + include_once FROXLOR_INSTALL_DIR . '/lng/lng_references.php'; + if (array_key_exists("import-settings", $this->_args)) { $this->importSettings(); } diff --git a/lib/configfiles/buster.xml b/lib/configfiles/buster.xml index 47107c6f..e3922dcf 100644 --- a/lib/configfiles/buster.xml +++ b/lib/configfiles/buster.xml @@ -4860,7 +4860,7 @@ aliases: files {{settings.phpfpm.enabled_ownvhost}} - + {{settings.system.webserver}} diff --git a/lib/configfiles/trusty.xml b/lib/configfiles/trusty.xml deleted file mode 100644 index 08262f33..00000000 --- a/lib/configfiles/trusty.xml +++ /dev/null @@ -1,1784 +0,0 @@ - - - - - - - - - - - {{settings.system.apacheconf_vhost}} - - - - - {{settings.system.apacheconf_vhost}} - - - - - - - {{settings.system.apacheconf_diroptions}} - - - - - {{settings.system.apacheconf_diroptions}} - - - - - - - - - - - {{settings.system.deactivateddocroot}} - - - - - - - - - //service[@type='http']/general/commands - - - - {{settings.system.use_ssl}} - - - - - {{settings.phpfpm.enabled}} - - - FastCgiIpcDir - - - Order Deny,Allow - Deny from All - # Prevent accessing this path directly - Allow from env=REDIRECT_STATUS - - -]]> - - - - {{settings.system.leenabled}} - - - Order allow,deny - Allow from all - -]]> - - - - - - - //service[@type='http']/general/commands - - - - {{settings.system.use_ssl}} - - - - - {{settings.phpfpm.enabled}} - - - FastCgiIpcDir - - - Require all granted - Require env REDIRECT_STATUS - - -]]> - - - - {{settings.system.leenabled}} - - - Require all granted - -]]> - - - - - - - - - " -server.port = 80 -server.bind = "" -url.access-deny = ("~", ".inc") - -fastcgi.server = ( -".php" => ( - "localhost" => ( - "socket" => "/tmp/lighttpd-fcgi-sock-lighttpd", - "broken-scriptfilename" => "enable", - "bin-path" => "/usr/bin/php5-cgi", - "min-procs" => 1, - "max-procs" => 1, - "max-load-per-proc" => 4, - "idle-timeout" => 60, - "bin-environment" => ( - "UID" => "www-data", - "GID" => "www-data", - "PHP_FCGI_CHILDREN" => "0", - "PHP_FCGI_MAX_REQUESTS" => "10000" - ), - "bin-copy-environment" => ( "" ) - ) - ) -) - -alias.url += ("/.well-known/acme-challenge/" => "{{settings.system.letsencryptchallengepath}}/.well-known/acme-challenge/") - -#### external configuration files -## mimetype mapping -include_shell "/usr/share/lighttpd/create-mime.assign.pl" -]]> - - - //service[@type='http']/general/commands - - {{settings.system.apacheconf_vhost}} - - > /etc/lighttpd/lighttpd.conf]]> - - - {{settings.system.apacheconf_vhost}} - - > /etc/lighttpd/lighttpd.conf]]> - - - {{settings.system.apacheconf_diroptions}} - - > /etc/lighttpd/lighttpd.conf]]> - - - {{settings.system.apacheconf_diroptions}} - - > /etc/lighttpd/lighttpd.conf]]> - - - - - - - - - - {{settings.phpfpm.enabled}} - - {{settings.system.mod_fcgid}} - - - - - - - - - - - - - - {{settings.system.leenabled}} - - - - - - {{settings.phpfpm.enabled}} - - {{settings.system.mod_fcgid}} - - - - - //service[@type='http']/general/commands - - {{settings.phpfpm.enabled}} - - {{settings.system.mod_fcgid}} - - - - - - - - - - - - > /etc/bind/named.conf]]> - - - - - - - - - -# add these entries to the list if any speficied: -allow-recursion=127.0.0.1 -config-dir=/etc/powerdns -daemon=yes -guardian=yes -lazy-recursion=yes -local-port=53 -master=yes -module-dir=/usr/lib/powerdns -setgid=pdns -setuid=pdns -socket-dir=/var/run -version-string=powerdns -include-dir=/etc/powerdns/froxlor/ -]]> - - - - - - - - - - - - - -# add these entries to the list if any speficied: -allow-recursion=127.0.0.1 -config-dir=/etc/powerdns -daemon=yes -guardian=yes -launch=bind -lazy-recursion=yes -local-port=53 -master=yes -module-dir=/usr/lib/powerdns -setgid=pdns -setuid=pdns -socket-dir=/var/run -version-string=powerdns -bind-config=named.conf -bind-check-interval=300 -include-dir=/etc/powerdns/froxlor/ -]]> - - - - - -# add these entries to the list if any speficied: -#local-ipv6=YOUR_IPv6_(if_any) -bind-config=named.conf -bind-check-interval=180 -log-dns-details=yes -local-address=,127.0.0.1 -]]> - - - - - - - - - - - - {{settings.system.vmail_gid}} - - - - - {{settings.system.vmail_uid}} - - - - - - - - - - - - - - - - - -password = -dbname = -hosts = -query = SELECT destination FROM mail_virtual AS v, panel_customers AS c WHERE c.customerid = v.customerid AND c.deactivated = 0 AND v.email = '%s' AND trim(v.destination) <> '' -]]> - - - - -password = -dbname = -hosts = -query = SELECT domain FROM panel_domains WHERE domain = '%s' AND isemaildomain = '1' -]]> - - - - -password = -dbname = -expansion_limit = 1 -hosts = -query = SELECT CONCAT(homedir,maildir) FROM mail_users WHERE email = '%s' -]]> - - - - -password = -dbname = -hosts = -query = SELECT DISTINCT username FROM mail_users WHERE email in ((SELECT mail_virtual.email_full FROM mail_virtual WHERE mail_virtual.email = '%s' UNION SELECT mail_virtual.destination FROM mail_virtual WHERE mail_virtual.email = '%s')); -]]> - - - - -password = -dbname = -expansion_limit = 1 -hosts = -query = SELECT uid FROM mail_users WHERE email = '%s' -]]> - - - - -password = -dbname = -expansion_limit = 1 -hosts = -query = SELECT gid FROM mail_users WHERE email = '%s' -]]> - - - - -]]> - - - - - - - - - - - //service[@type='smtp']/general/commands[@index=1] - - //service[@type='smtp']/general/installs[@index=1] - - //service[@type='smtp']/general/commands[@index=2] - - - - -# set myhostname to $mydomain because Froxlor alrady uses a FQDN -myhostname = $mydomain - -mydestination = $myhostname, - $mydomain, - localhost.$myhostname, - localhost.$mydomain, - localhost -mynetworks = 127.0.0.0/8 -inet_interfaces = all -append_dot_mydomain = no -biff = no - -# Postfix performance settings -default_destination_concurrency_limit = 20 -local_destination_concurrency_limit = 2 - -# SMTPD Settings -smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) -smtpd_helo_required = yes -smtpd_recipient_restrictions = permit_mynetworks, - permit_sasl_authenticated, - reject_unauth_destination, - reject_unauth_pipelining, - reject_non_fqdn_recipient -smtpd_sender_restrictions = permit_mynetworks, - reject_sender_login_mismatch, - permit_sasl_authenticated, - reject_unknown_helo_hostname, - reject_unknown_recipient_domain, - reject_unknown_sender_domain -smtpd_client_restrictions = permit_mynetworks, - permit_sasl_authenticated, - reject_unknown_client_hostname - -# Postfix 2.10 requires this option. Postfix < 2.10 ignores this. -# The option is intentionally left empty. -smtpd_relay_restrictions = - -# Maximum size of Message in bytes (50MB) -message_size_limit = 52428800 - -## SASL Auth Settings -smtpd_sasl_auth_enable = yes -smtpd_sasl_local_domain = $myhostname -broken_sasl_auth_clients = yes -## Dovecot Settings for deliver, SASL Auth and virtual transport -smtpd_sasl_type = dovecot -virtual_transport = dovecot -dovecot_destination_recipient_limit = 1 -smtpd_sasl_path = private/dovecot-auth - -# Virtual delivery settings -virtual_mailbox_base = / -virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual_mailbox_maps.cf -virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual_mailbox_domains.cf -virtual_alias_maps = mysql:/etc/postfix/mysql-virtual_alias_maps.cf -smtpd_sender_login_maps = mysql:/etc/postfix/mysql-virtual_sender_permissions.cf -virtual_uid_maps = static: -virtual_gid_maps = static: - -# Local delivery settings -local_transport = local -alias_maps = $alias_database - -# Default Mailbox size, is set to 0 which means unlimited! -mailbox_size_limit = 0 -virtual_mailbox_limit = 0 - -### TLS settings -### -## TLS for outgoing mails from the server to another server -#smtp_tls_security_level = may -#smtp_tls_note_starttls_offer = yes -## TLS for incoming connections (clients or other mail servers) -#smtpd_tls_security_level = may -#smtpd_tls_cert_file = /etc/ssl/server/.pem -#smtpd_tls_key_file = $smtpd_tls_cert_file -#smtpd_tls_CAfile = /etc/ssl/certs/ca-certificates.crt -#smtpd_tls_loglevel = 1 -#smtpd_tls_received_header = yes - -debugger_command = - PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin - ddd $daemon_directory/$process_name $process_id & sleep 5 -]]> - - - //service[@type='smtp']/general/files[@index=0] - - - - - //service[@type='smtp']/general/commands[@index=3] - - - - - //service[@type='smtp']/general/commands[@index=1] - - //service[@type='smtp']/general/installs[@index=1] - - - //service[@type='smtp']/general/commands[@index=2] - - - - -# should be different from $mydomain eg. "mail.$mydomain" -myhostname = mail.$mydomain - -mydestination = $myhostname, - $mydomain, - localhost.$myhostname, - localhost.$mydomain, - localhost -mynetworks = 127.0.0.0/8 -inet_interfaces = all -append_dot_mydomain = no -biff = no - -# Postfix performance settings -default_destination_concurrency_limit = 20 -local_destination_concurrency_limit = 2 - -# SMTPD Settings -smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) -smtpd_helo_required = yes -smtpd_recipient_restrictions = permit_mynetworks, - permit_sasl_authenticated, - reject_unauth_destination, - reject_unauth_pipelining, - reject_non_fqdn_recipient -smtpd_sender_restrictions = permit_mynetworks, - reject_sender_login_mismatch, - permit_sasl_authenticated, - reject_unknown_helo_hostname, - reject_unknown_recipient_domain, - reject_unknown_sender_domain -smtpd_client_restrictions = permit_mynetworks, - permit_sasl_authenticated, - reject_unknown_client_hostname - -# Postfix 2.10 requires this option. Postfix < 2.10 ignores this. -# The option is intentionally left empty. -smtpd_relay_restrictions = - -# Maximum size of Message in bytes (50MB) -message_size_limit = 52428800 - -## SASL Auth Settings -smtpd_sasl_auth_enable = yes -smtpd_sasl_local_domain = $myhostname -broken_sasl_auth_clients = yes - -# Virtual delivery settings -virtual_mailbox_base = / -virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual_mailbox_maps.cf -virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual_mailbox_domains.cf -virtual_alias_maps = mysql:/etc/postfix/mysql-virtual_alias_maps.cf -smtpd_sender_login_maps = mysql:/etc/postfix/mysql-virtual_sender_permissions.cf -virtual_uid_maps = static: -virtual_gid_maps = static: - -# Local delivery settings -local_transport = local -alias_maps = $alias_database - -# Default Mailbox size, is set to 0 which means unlimited! -mailbox_size_limit = 0 -virtual_mailbox_limit = 0 - -### TLS settings -### -## TLS for outgoing mails from the server to another server -#smtp_tls_security_level = may -#smtp_tls_note_starttls_offer = yes -## TLS for email client -#smtpd_tls_security_level = may -#smtpd_tls_cert_file = /etc/ssl/server/.pem -#smtpd_tls_key_file = $smtpd_tls_cert_file -#smtpd_tls_CAfile = /etc/ssl/certs/ca-certificates.crt -#smtpd_tls_loglevel = 1 -#smtpd_tls_received_header = yes - -debugger_command = - PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin - ddd $daemon_directory/$process_name $process_id & sleep 5 -]]> - - - //service[@type='smtp']/general/files[@index=0] - - -sql_user: -sql_passwd: -sql_database: -sql_select: SELECT password FROM mail_users WHERE username='%u@%r' OR email='%u@%r' -]]> - - - //service[@type='smtp']/general/commands[@index=3] - - - - - - - - - - - mail_plugins = sieve quota - quota_full_tempfail = yes - deliver_log_format = msgid=%m: %$ - rejection_reason = Your message to <%t> was automatically rejected:%n%r -} - -# Plugins configuration -plugin { - sieve=~/.dovecot.sieve - sieve_dir=~/sieve - quota = maildir -} - -# Authentication configuration -auth_mechanisms = plain login - -service auth { - # Postfix smtp-auth - unix_listener /var/spool/postfix/private/dovecot-auth { - mode = 0660 - user = postfix - group = postfix - } -} -]]> - - - - to characters. For example "#@/@" means -# that '#' and '/' characters are translated to '@'. -#auth_username_translation = - -# Username formatting before it's looked up from databases. You can use -# the standard variables here, eg. %Lu would lowercase the username, %n would -# drop away the domain if it was given, or "%n-AT-%d" would change the '@' into -# "-AT-". This translation is done after auth_username_translation changes. -#auth_username_format = - -# If you want to allow master users to log in by specifying the master -# username within the normal username string (ie. not using SASL mechanism's -# support for it), you can specify the separator character here. The format -# is then . UW-IMAP uses "*" as the -# separator, so that could be a good choice. -#auth_master_user_separator = - -# Username to use for users logging in with ANONYMOUS SASL mechanism -#auth_anonymous_username = anonymous - -# Maximum number of dovecot-auth worker processes. They're used to execute -# blocking passdb and userdb queries (eg. MySQL and PAM). They're -# automatically created and destroyed as needed. -#auth_worker_max_count = 30 - -# Host name to use in GSSAPI principal names. The default is to use the -# name returned by gethostname(). Use "$ALL" (with quotes) to allow all keytab -# entries. -#auth_gssapi_hostname = - -# Kerberos keytab to use for the GSSAPI mechanism. Will use the system -# default (usually /etc/krb5.keytab) if not specified. You may need to change -# the auth service to run as root to be able to read this file. -#auth_krb5_keytab = - -# Do NTLM and GSS-SPNEGO authentication using Samba's winbind daemon and -# ntlm_auth helper. -#auth_use_winbind = no - -# Path for Samba's ntlm_auth helper binary. -#auth_winbind_helper_path = /usr/bin/ntlm_auth - -# Time to delay before replying to failed authentications. -#auth_failure_delay = 2 secs - -# Require a valid SSL client certificate or the authentication fails. -#auth_ssl_require_client_cert = no - -# Take the username from client's SSL certificate, using -# X509_NAME_get_text_by_NID() which returns the subject's DN's -# CommonName. -#auth_ssl_username_from_cert = no - -# Space separated list of wanted authentication mechanisms: -# plain login digest-md5 cram-md5 ntlm rpa apop anonymous gssapi otp skey -# gss-spnego -# NOTE: See also disable_plaintext_auth setting. -auth_mechanisms = plain login - -## -## Password and user databases -## - -# -# Password database is used to verify user's password (and nothing more). -# You can have multiple passdbs and userdbs. This is useful if you want to -# allow both system users (/etc/passwd) and virtual users to login without -# duplicating the system users into virtual database. -# -# -# -# User database specifies where mails are located and what user/group IDs -# own them. For single-UID configuration use "static" userdb. -# -# - -#!include auth-deny.conf.ext -#!include auth-master.conf.ext - -#!include auth-system.conf.ext -!include auth-sql.conf.ext -#!include auth-ldap.conf.ext -#!include auth-passwdfile.conf.ext -#!include auth-checkpassword.conf.ext -#!include auth-vpopmail.conf.ext -#!include auth-static.conf.ext -]]> - - - - dbname= user= password= -default_pass_scheme = CRYPT -password_query = SELECT username AS user, password_enc AS password, CONCAT(homedir, maildir) AS userdb_home, uid AS userdb_uid, gid AS userdb_gid, CONCAT('maildir:', homedir, maildir) AS userdb_mail, CONCAT('*:storage=', quota, 'M') as userdb_quota_rule FROM mail_users WHERE (username = '%u' OR email = '%u') AND ((imap = 1 AND '%Ls' = 'imap') OR (pop3 = 1 AND '%Ls' = 'pop3') OR ((postfix = 'Y' AND '%Ls' = 'smtp') OR (postfix = 'Y' AND '%Ls' = 'sieve'))) -user_query = SELECT CONCAT(homedir, maildir) AS home, CONCAT('maildir:', homedir, maildir) AS mail, uid, gid, CONCAT('*:storage=', quota, 'M') as quota_rule FROM mail_users WHERE (username = '%u' OR email = '%u') -iterate_query = SELECT username AS user FROM mail_users WHERE (imap = 1 OR pop3 = 1) -]]> - - - - - - - - - - - - - -MYSQL_USERNAME -MYSQL_PASSWORD -MYSQL_PORT 3306 -MYSQL_DATABASE -MYSQL_USER_TABLE mail_users -MYSQL_CRYPT_PWFIELD password_enc -MYSQL_UID_FIELD uid -MYSQL_GID_FIELD gid -MYSQL_LOGIN_FIELD username -MYSQL_HOME_FIELD homedir -MYSQL_MAILDIR_FIELD maildir -MYSQL_QUOTA_FIELD (quota*1024*1024) -MYSQL_AUXOPTIONS_FIELD CONCAT("allowimap=",imap,",allowpop3=",pop3) -]]> - - - - - - - - - - - - - " -[ -f /etc/ssl/certs/proftpd_ec.crt ] || openssl req -new -x509 -nodes -newkey ec:<(openssl ecparam -name secp521r1) -keyout /etc/ssl/private/proftpd_ec.key -out /etc/ssl/certs/proftpd_ec.crt -days 3650 -subj "/C=US/ST=Some-State/O=Internet Widgits Pty Ltd/CN=" -chmod 0600 /etc/ssl/private/proftpd.key /etc/ssl/private/proftpd_ec.key -]]> - - - - - - - - FTP Server" -ServerType standalone -DeferWelcome off - -MultilineRFC2228 on -DefaultServer on -ShowSymlinks on - -TimeoutNoTransfer 600 -TimeoutStalled 600 -TimeoutIdle 1200 - -DisplayLogin welcome.msg -DisplayChdir .message true -ListOptions "-l" - -DenyFilter \*.*/ - -# Use this to jail all users in their homes -# DefaultRoot ~ - -# Users require a valid shell listed in /etc/shells to login. -# Use this directive to release that constrain. -# RequireValidShell off - -# Port 21 is the standard FTP port. -Port 21 - -# In some cases you have to specify passive ports range to by-pass -# firewall limitations. Ephemeral ports can be used for that, but -# feel free to use a more narrow range. -# PassivePorts 49152 65534 - -# If your host was NATted, this option is useful in order to -# allow passive tranfers to work. You have to use your public -# address and opening the passive ports used on your firewall as well. -# MasqueradeAddress 1.2.3.4 - -# This is useful for masquerading address with dynamic IPs: -# refresh any configured MasqueradeAddress directives every 8 hours - -# DynMasqRefresh 28800 - - -# To prevent DoS attacks, set the maximum number of child processes -# to 30. If you need to allow more than 30 concurrent connections -# at once, simply increase this value. Note that this ONLY works -# in standalone mode, in inetd mode you should use an inetd server -# that allows you to limit maximum number of processes per service -# (such as xinetd) -MaxInstances 30 - -# Set the user and group that the server normally runs at. -User proftpd -Group nogroup - -# Umask 022 is a good standard umask to prevent new files and dirs -# (second parm) from being group and world writable. -Umask 022 022 -# Normally, we want files to be overwriteable. -AllowOverwrite on - -# Uncomment this if you are using NIS or LDAP via NSS to retrieve passwords: -# PersistentPasswd off - -# This is required to use both PAM-based authentication and local passwords -# AuthOrder mod_auth_pam.c* mod_auth_unix.c - -# Be warned: use of this directive impacts CPU average load! -# Uncomment this if you like to see progress and transfer rate with ftpwho -# in downloads. That is not needed for uploads rates. -# -# UseSendFile off - -TransferLog /var/log/proftpd/xferlog -SystemLog /var/log/proftpd/proftpd.log - -# Allow up- and downloads to be continued -AllowRetrieveRestart On -AllowStoreRestart On - - -QuotaEngine on - - - -Ratios off - - - -# Delay engine reduces impact of the so-called Timing Attack described in -# http://security.lss.hr/index.php?page=details&ID=LSS-2004-10-02 -# It is on by default. - -DelayEngine off - - - -ControlsEngine off -ControlsMaxClients 2 -ControlsLog /var/log/proftpd/controls.log -ControlsInterval 5 -ControlsSocket /var/run/proftpd/proftpd.sock - - - -AdminControlsEngine off - - -# -# Alternative authentication frameworks -# -#Include /etc/proftpd/ldap.conf -Include /etc/proftpd/sql.conf - -# -# This is used for FTPS connections -# -Include /etc/proftpd/tls.conf -]]> - - - - - - - - -DefaultRoot ~ -RequireValidShell off -AuthOrder mod_sql.c - -SQLBackend mysql -SQLEngine on -SQLAuthenticate on - -SQLAuthTypes Crypt -SQLAuthenticate users* groups* -SQLConnectInfo @ -SQLUserInfo ftp_users username password uid gid homedir shell -SQLGroupInfo ftp_groups groupname gid members -SQLUserWhereClause "login_enabled = 'y'" - -SQLLog PASS login -SQLNamedQuery login UPDATE "last_login=now(), login_count=login_count+1 WHERE username='%u'" ftp_users - -SQLLog RETR download -SQLNamedQuery download UPDATE "down_count=down_count+1, down_bytes=down_bytes+%b WHERE username='%u'" ftp_users - -SQLLog STOR upload -SQLNamedQuery upload UPDATE "up_count=up_count+1, up_bytes=up_bytes+%b WHERE username='%u'" ftp_users - -QuotaEngine on -QuotaShowQuotas on -QuotaDisplayUnits Mb -QuotaLock /var/lock/ftpd.quotatab.lock -QuotaLimitTable sql:/get-quota-limit -QuotaTallyTable sql:/get-quota-tally/update-quota-tally/insert-quota-tally -SQLNamedQuery get-quota-limit SELECT "ftp_users.username AS name, ftp_quotalimits.quota_type, ftp_quotalimits.per_session, ftp_quotalimits.limit_type, panel_customers.diskspace*1024 AS bytes_in_avail, ftp_quotalimits.bytes_out_avail, ftp_quotalimits.bytes_xfer_avail, ftp_quotalimits.files_in_avail, ftp_quotalimits.files_out_avail, ftp_quotalimits.files_xfer_avail FROM ftp_users, ftp_quotalimits, panel_customers WHERE ftp_users.username = '%{0}' AND panel_customers.loginname = SUBSTRING_INDEX('%{0}', 'ftp', 1) AND quota_type ='%{1}'" -SQLNamedQuery get-quota-tally SELECT "name, quota_type, bytes_in_used,bytes_out_used, bytes_xfer_used, files_in_used, files_out_used,files_xfer_used FROM ftp_quotatallies WHERE name = '%{0}' AND quota_type = '%{1}'" -SQLNamedQuery update-quota-tally UPDATE "bytes_in_used = bytes_in_used + %{0}, bytes_out_used = bytes_out_used + %{1}, bytes_xfer_used = bytes_xfer_used + %{2}, files_in_used = files_in_used + %{3}, files_out_used= files_out_used + %{4}, files_xfer_used = files_xfer_used + %{5} WHERE name= '%{6}' AND quota_type = '%{7}'" ftp_quotatallies -SQLNamedQuery insert-quota-tally INSERT "%{0}, %{1}, %{2}, %{3}, %{4},%{5}, %{6}, %{7}" ftp_quotatallies - - -]]> - - - - -TLSEngine on -TLSLog /var/log/proftpd/tls.log -TLSProtocol TLSv1 TLSv1.1 TLSv1.2 -TLSRSACertificateFile /etc/ssl/certs/proftpd.crt -TLSRSACertificateKeyFile /etc/ssl/private/proftpd.key -#TLSECCertificateFile /etc/ssl/certs/proftpd_ec.crt -#TLSECCertificateKeyFile /etc/ssl/private/proftpd_ec.key -TLSOptions NoCertRequest NoSessionReuseRequired -TLSVerifyClient off - -# Are clients required to use FTP over TLS when talking to this server? -#TLSRequired on - -# Allow SSL/TLS renegotiations when the client requests them, but -# do not force the renegotations. Some clients do not support -# SSL/TLS renegotiations; when mod_tls forces a renegotiation, these -# clients will close the data connection, or there will be a timeout -# on an idle data connection. -# -#TLSRenegotiate required off - -]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -MYSQLUser -MYSQLPassword -MYSQLDatabase -MYSQLCrypt any - -MYSQLGetPW SELECT password FROM ftp_users WHERE username="\L" AND login_enabled="y" -MYSQLGetUID SELECT uid FROM ftp_users WHERE username="\L" AND login_enabled="y" -MYSQLGetGID SELECT gid FROM ftp_users WHERE username="\L" AND login_enabled="y" -MYSQLGetDir SELECT homedir FROM ftp_users WHERE username="\L" AND login_enabled="y" -MySQLGetQTASZ SELECT panel_customers.diskspace/1024 AS QuotaSize FROM panel_customers, ftp_users WHERE username = "\L" AND panel_customers.loginname = SUBSTRING_INDEX('\L', 'ftp', 1) -]]> - - - - - - - - - - - - - - - - - - - - - - scripts/froxlor_master_cronjob.php --run-task 99]]> - - - - - - - - - - - - - - - - -database -username -password -socket /var/run/mysqld/mysqld.sock -]]> - - - - - {{sql.socket}} - - - - -password -]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *.log { - missingok - daily - rotate 7 - compress - delaycompress - notifempty - create - sharedscripts - postrotate - > /dev/null 2>&1 || true - endscript -} -]]> - - - - - - - - - {{settings.system.mod_fcgid_ownvhost}} - - - - - - - - - - - - - - {{settings.system.webserver}} - - - - - - {{settings.system.webserver}} - - - - - - {{settings.system.webserver}} - - - - - {{settings.phpfpm.enabled_ownvhost}} - - {{settings.phpfpm.vhost_httpuser}} - - - - - - {{settings.system.webserver}} - - {{settings.phpfpm.enabled_ownvhost}} - - - - - {{settings.system.webserver}} - - - - - - - - - - diff --git a/lib/configfiles/xenial.xml b/lib/configfiles/xenial.xml index 9de365f1..19a36c33 100644 --- a/lib/configfiles/xenial.xml +++ b/lib/configfiles/xenial.xml @@ -1,7 +1,7 @@ + version="16.04" defaulteditor="/bin/nano" deprecated="true"> From 0524c70d2b0d0a409171c318cde16ba8220ae842 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 24 May 2020 12:16:17 +0200 Subject: [PATCH 047/319] add config-templates for ubuntu focal (partly tested only for now) Signed-off-by: Michael Kaufmann --- lib/configfiles/focal.xml | 4100 +++++++++++++++++++++++++++++++++++++ 1 file changed, 4100 insertions(+) create mode 100644 lib/configfiles/focal.xml diff --git a/lib/configfiles/focal.xml b/lib/configfiles/focal.xml new file mode 100644 index 00000000..588f0e4d --- /dev/null +++ b/lib/configfiles/focal.xml @@ -0,0 +1,4100 @@ + + + + + + + + + + + {{settings.system.apacheconf_vhost}} + + + + + {{settings.system.apacheconf_vhost}} + + + + + + + {{settings.system.apacheconf_diroptions}} + + + + + {{settings.system.apacheconf_diroptions}} + + + + + + + + + + + {{settings.system.deactivateddocroot}} + + + + + + + + + //service[@type='http']/general/commands + + + + {{settings.system.use_ssl}} + + + + + {{settings.phpfpm.enabled}} + + + + + {{settings.system.leenabled}} + + + Require all granted + +]]> + + + + + + + + + "{{settings.system.letsencryptchallengepath}}/.well-known/acme-challenge/") + +# default listening port for IPv6 falls back to the IPv4 port +include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port +include_shell "/usr/share/lighttpd/create-mime.assign.pl" +include_shell "/usr/share/lighttpd/include-conf-enabled.pl" +]]> + + + //service[@type='http']/general/commands + + {{settings.system.apacheconf_vhost}} + + > /etc/lighttpd/lighttpd.conf]]> + + + {{settings.system.apacheconf_vhost}} + + > /etc/lighttpd/lighttpd.conf]]> + + + {{settings.system.apacheconf_diroptions}} + + > /etc/lighttpd/lighttpd.conf]]> + + + {{settings.system.apacheconf_diroptions}} + + > /etc/lighttpd/lighttpd.conf]]> + + + + + + + + + + {{settings.phpfpm.enabled}} + + {{settings.system.mod_fcgid}} + + + + + + + + + + + + + {{settings.system.leenabled}} + + + + + + {{settings.phpfpm.enabled}} + + {{settings.system.mod_fcgid}} + + + + + //service[@type='http']/general/commands + + {{settings.phpfpm.enabled}} + + {{settings.system.mod_fcgid}} + + + + + + + + + + + + > /etc/bind/named.conf.local]]> + + + + + + + + + +# add these entries to the list if any speficied: + +################################# +# allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. +# +# allow-dnsupdate-from=127.0.0.0/8,::1 + +################################# +# allow-recursion List of subnets that are allowed to recurse +# +allow-recursion=127.0.0.1 + +################################# +# also-notify When notifying a domain, also notify these nameservers +# +# also-notify= + +################################# +# any-to-tcp Answer ANY queries with tc=1, shunting to TCP +# +# any-to-tcp=no + +################################# +# cache-ttl Seconds to store packets in the PacketCache +# +# cache-ttl=20 + +################################# +# carbon-interval Number of seconds between carbon (graphite) updates +# +# carbon-interval=30 + +################################# +# carbon-ourname If set, overrides our reported hostname for carbon stats +# +# carbon-ourname= + +################################# +# carbon-server If set, send metrics in carbon (graphite) format to this server +# +# carbon-server= + +################################# +# chroot If set, chroot to this directory for more security +# +# chroot= + +################################# +# config-dir Location of configuration directory (pdns.conf) +# +config-dir=/etc/powerdns + +################################# +# config-name Name of this virtual configuration - will rename the binary image +# +# config-name= + +################################# +# control-console Debugging switch - don't use +# +# control-console=no + +################################# +# daemon Operate as a daemon +# +daemon=yes + +################################# +# default-ksk-algorithms Default KSK algorithms +# +# default-ksk-algorithms=rsasha256 + +################################# +# default-ksk-size Default KSK size (0 means default) +# +# default-ksk-size=0 + +################################# +# default-soa-mail mail address to insert in the SOA record if none set in the backend +# +# default-soa-mail= + +################################# +# default-soa-name name to insert in the SOA record if none set in the backend +# +# default-soa-name=a.misconfigured.powerdns.server + +################################# +# default-ttl Seconds a result is valid if not set otherwise +# +# default-ttl=3600 + +################################# +# default-zsk-algorithms Default ZSK algorithms +# +# default-zsk-algorithms=rsasha256 + +################################# +# default-zsk-size Default ZSK size (0 means default) +# +# default-zsk-size=0 + +################################# +# direct-dnskey Fetch DNSKEY RRs from backend during DNSKEY synthesis +# +# direct-dnskey=no + +################################# +# disable-axfr Disable zonetransfers but do allow TCP queries +# +# disable-axfr=no + +################################# +# disable-axfr-rectify Disable the rectify step during an outgoing AXFR. Only required for regression testing. +# +# disable-axfr-rectify=no + +################################# +# disable-tcp Do not listen to TCP queries +# +# disable-tcp=no + +################################# +# distributor-threads Default number of Distributor (backend) threads to start +# +# distributor-threads=3 + +################################# +# do-ipv6-additional-processing Do AAAA additional processing +# +# do-ipv6-additional-processing=yes + +################################# +# edns-subnet-processing If we should act on EDNS Subnet options +# +# edns-subnet-processing=no + +################################# +# entropy-source If set, read entropy from this file +# +# entropy-source=/dev/urandom + +################################# +# experimental-api-key REST API Static authentication key (required for API use) +# +# experimental-api-key= + +################################# +# experimental-api-readonly If the JSON API should disallow data modification +# +# experimental-api-readonly=no + +################################# +# experimental-dname-processing If we should support DNAME records +# +# experimental-dname-processing=no + +################################# +# experimental-dnsupdate Enable/Disable DNS update (RFC2136) support. Default is no. +# +# experimental-dnsupdate=no + +################################# +# experimental-json-interface If the webserver should serve JSON data +# +# experimental-json-interface=no + +################################# +# experimental-logfile Filename of the log file for JSON parser +# +# experimental-logfile=/var/log/pdns.log + +################################# +# forward-dnsupdate A global setting to allow DNS update packages that are for a Slave domain, to be forwarded to the master. +# +# forward-dnsupdate=yes + +################################# +# guardian Run within a guardian process +# +guardian=yes + +################################# +# include-dir Include *.conf files from this directory +# +# include-dir= + +################################# +# launch Which backends to launch and order to query them in +# +# launch= + +################################# +# load-modules Load this module - supply absolute or relative path +# +# load-modules= + +################################# +# local-address Local IP addresses to which we bind +# +local-address=,127.0.0.1 + +################################# +# local-address-nonexist-fail Fail to start if one or more of the local-address's do not exist on this server +# +# local-address-nonexist-fail=yes + +################################# +# local-ipv6 Local IP address to which we bind +# +# local-ipv6= + +################################# +# local-ipv6-nonexist-fail Fail to start if one or more of the local-ipv6 addresses do not exist on this server +# +# local-ipv6-nonexist-fail=yes + +################################# +# local-port The port on which we listen +# +# local-port=53 + +################################# +# log-dns-details If PDNS should log DNS non-erroneous details +# +# log-dns-details=no + +################################# +# log-dns-queries If PDNS should log all incoming DNS queries +# +# log-dns-queries=no + +################################# +# logging-facility Log under a specific facility +# +# logging-facility= + +################################# +# loglevel Amount of logging. Higher is more. Do not set below 3 +# +# loglevel=4 + +################################# +# lua-prequery-script Lua script with prequery handler +# +# lua-prequery-script= + +################################# +# master Act as a master +# +master=yes + +################################# +# max-cache-entries Maximum number of cache entries +# +# max-cache-entries=1000000 + +################################# +# max-ent-entries Maximum number of empty non-terminals in a zone +# +# max-ent-entries=100000 + +################################# +# max-nsec3-iterations Limit the number of NSEC3 hash iterations +# +# max-nsec3-iterations=500 + +################################# +# max-queue-length Maximum queuelength before considering situation lost +# +# max-queue-length=5000 + +################################# +# max-signature-cache-entries Maximum number of signatures cache entries +# +# max-signature-cache-entries= + +################################# +# max-tcp-connections Maximum number of TCP connections +# +# max-tcp-connections=10 + +################################# +# module-dir Default directory for modules +# +# module-dir=/usr/lib/TRIPLET/pdns + +################################# +# negquery-cache-ttl Seconds to store negative query results in the QueryCache +# +# negquery-cache-ttl=60 + +################################# +# no-shuffle Set this to prevent random shuffling of answers - for regression testing +# +# no-shuffle=off + +################################# +# only-notify Only send AXFR NOTIFY to these IP addresses or netmasks +# +# only-notify=0.0.0.0/0,::/0 + +################################# +# out-of-zone-additional-processing Do out of zone additional processing +# +# out-of-zone-additional-processing=yes + +################################# +# overload-queue-length Maximum queuelength moving to packetcache only +# +# overload-queue-length=0 + +################################# +# pipebackend-abi-version Version of the pipe backend ABI +# +# pipebackend-abi-version=1 + +################################# +# prevent-self-notification Don't send notifications to what we think is ourself +# +# prevent-self-notification=yes + +################################# +# query-cache-ttl Seconds to store query results in the QueryCache +# +# query-cache-ttl=20 + +################################# +# query-local-address Source IP address for sending queries +# +# query-local-address=0.0.0.0 + +################################# +# query-local-address6 Source IPv6 address for sending queries +# +# query-local-address6=:: + +################################# +# query-logging Hint backends that queries should be logged +# +# query-logging=no + +################################# +# queue-limit Maximum number of milliseconds to queue a query +# +# queue-limit=1500 + +################################# +# receiver-threads Default number of receiver threads to start +# +# receiver-threads=1 + +################################# +# recursive-cache-ttl Seconds to store packets for recursive queries in the PacketCache +# +# recursive-cache-ttl=10 + +################################# +# recursor If recursion is desired, IP address of a recursing nameserver +# +# recursor=no + +################################# +# retrieval-threads Number of AXFR-retrieval threads for slave operation +# +# retrieval-threads=2 + +################################# +# reuseport Enable higher performance on compliant kernels by using SO_REUSEPORT allowing each receiver thread to open its own socket +# +# reuseport=no + +################################# +# security-poll-suffix Domain name from which to query security update notifications +# +# security-poll-suffix=secpoll.powerdns.com. + +################################# +# send-root-referral Send out old-fashioned root-referral instead of ServFail in case of no authority +# +# send-root-referral=no + +################################# +# server-id Returned when queried for 'server.id' TXT or NSID, defaults to hostname - disabled or custom +# +# server-id= + +################################# +# setgid If set, change group id to this gid for more security +# +setgid=pdns + +################################# +# setuid If set, change user id to this uid for more security +# +setuid=pdns + +################################# +# signing-threads Default number of signer threads to start +# +# signing-threads=3 + +################################# +# slave Act as a slave +# +# slave=no + +################################# +# slave-cycle-interval Reschedule failed SOA serial checks once every .. seconds +# +# slave-cycle-interval=60 + +################################# +# slave-renotify If we should send out notifications for slaved updates +# +# slave-renotify=no + +################################# +# soa-expire-default Default SOA expire +# +# soa-expire-default=604800 + +################################# +# soa-minimum-ttl Default SOA minimum ttl +# +# soa-minimum-ttl=3600 + +################################# +# soa-refresh-default Default SOA refresh +# +# soa-refresh-default=10800 + +################################# +# soa-retry-default Default SOA retry +# +# soa-retry-default=3600 + +################################# +# socket-dir Where the controlsocket will live +# +# socket-dir=/var/run + +################################# +# tcp-control-address If set, PowerDNS can be controlled over TCP on this address +# +# tcp-control-address= + +################################# +# tcp-control-port If set, PowerDNS can be controlled over TCP on this address +# +# tcp-control-port=53000 + +################################# +# tcp-control-range If set, remote control of PowerDNS is possible over these networks only +# +# tcp-control-range=127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fe80::/10 + +################################# +# tcp-control-secret If set, PowerDNS can be controlled over TCP after passing this secret +# +# tcp-control-secret= + +################################# +# traceback-handler Enable the traceback handler (Linux only) +# +# traceback-handler=yes + +################################# +# trusted-notification-proxy IP address of incoming notification proxy +# +# trusted-notification-proxy= + +################################# +# udp-truncation-threshold Maximum UDP response size before we truncate +# +# udp-truncation-threshold=1680 + +################################# +# version-string PowerDNS version in packets - full, anonymous, powerdns or custom +# + +version-string=powerdns +################################# +# webserver Start a webserver for monitoring +# +# webserver=no + +################################# +# webserver-address IP Address of webserver to listen on +# +# webserver-address=127.0.0.1 + +################################# +# webserver-allow-from Webserver access is only allowed from these subnets +# +# webserver-allow-from=0.0.0.0/0,::/0 + +################################# +# webserver-password Password required for accessing the webserver +# +# webserver-password= + +################################# +# webserver-port Port of webserver to listen on +# +# webserver-port=8081 + +################################# +# webserver-print-arguments If the webserver should print arguments +# +# webserver-print-arguments=no + +# include froxlor-bind-specific config +include-dir=/etc/powerdns/froxlor/ +]]> + + + + + + + + + + + + + +# add these entries to the list if any speficied: + +################################# +# allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. +# +# allow-dnsupdate-from=127.0.0.0/8,::1 + +################################# +# allow-recursion List of subnets that are allowed to recurse +# +allow-recursion=127.0.0.1 + +################################# +# also-notify When notifying a domain, also notify these nameservers +# +# also-notify= + +################################# +# any-to-tcp Answer ANY queries with tc=1, shunting to TCP +# +# any-to-tcp=no + +################################# +# cache-ttl Seconds to store packets in the PacketCache +# +# cache-ttl=20 + +################################# +# carbon-interval Number of seconds between carbon (graphite) updates +# +# carbon-interval=30 + +################################# +# carbon-ourname If set, overrides our reported hostname for carbon stats +# +# carbon-ourname= + +################################# +# carbon-server If set, send metrics in carbon (graphite) format to this server +# +# carbon-server= + +################################# +# chroot If set, chroot to this directory for more security +# +# chroot= + +################################# +# config-dir Location of configuration directory (pdns.conf) +# +config-dir=/etc/powerdns + +################################# +# config-name Name of this virtual configuration - will rename the binary image +# +# config-name= + +################################# +# control-console Debugging switch - don't use +# +# control-console=no + +################################# +# daemon Operate as a daemon +# +daemon=yes + +################################# +# default-ksk-algorithms Default KSK algorithms +# +# default-ksk-algorithms=rsasha256 + +################################# +# default-ksk-size Default KSK size (0 means default) +# +# default-ksk-size=0 + +################################# +# default-soa-mail mail address to insert in the SOA record if none set in the backend +# +# default-soa-mail= + +################################# +# default-soa-name name to insert in the SOA record if none set in the backend +# +# default-soa-name=a.misconfigured.powerdns.server + +################################# +# default-ttl Seconds a result is valid if not set otherwise +# +# default-ttl=3600 + +################################# +# default-zsk-algorithms Default ZSK algorithms +# +# default-zsk-algorithms=rsasha256 + +################################# +# default-zsk-size Default ZSK size (0 means default) +# +# default-zsk-size=0 + +################################# +# direct-dnskey Fetch DNSKEY RRs from backend during DNSKEY synthesis +# +# direct-dnskey=no + +################################# +# disable-axfr Disable zonetransfers but do allow TCP queries +# +# disable-axfr=no + +################################# +# disable-axfr-rectify Disable the rectify step during an outgoing AXFR. Only required for regression testing. +# +# disable-axfr-rectify=no + +################################# +# disable-tcp Do not listen to TCP queries +# +# disable-tcp=no + +################################# +# distributor-threads Default number of Distributor (backend) threads to start +# +# distributor-threads=3 + +################################# +# do-ipv6-additional-processing Do AAAA additional processing +# +# do-ipv6-additional-processing=yes + +################################# +# edns-subnet-processing If we should act on EDNS Subnet options +# +# edns-subnet-processing=no + +################################# +# entropy-source If set, read entropy from this file +# +# entropy-source=/dev/urandom + +################################# +# experimental-api-key REST API Static authentication key (required for API use) +# +# experimental-api-key= + +################################# +# experimental-api-readonly If the JSON API should disallow data modification +# +# experimental-api-readonly=no + +################################# +# experimental-dname-processing If we should support DNAME records +# +# experimental-dname-processing=no + +################################# +# experimental-dnsupdate Enable/Disable DNS update (RFC2136) support. Default is no. +# +# experimental-dnsupdate=no + +################################# +# experimental-json-interface If the webserver should serve JSON data +# +# experimental-json-interface=no + +################################# +# experimental-logfile Filename of the log file for JSON parser +# +# experimental-logfile=/var/log/pdns.log + +################################# +# forward-dnsupdate A global setting to allow DNS update packages that are for a Slave domain, to be forwarded to the master. +# +# forward-dnsupdate=yes + +################################# +# guardian Run within a guardian process +# +guardian=yes + +################################# +# include-dir Include *.conf files from this directory +# +# include-dir= + +################################# +# launch Which backends to launch and order to query them in +# +# launch= +launch=bind + +################################# +# load-modules Load this module - supply absolute or relative path +# +# load-modules= + +################################# +# local-address Local IP addresses to which we bind +# +local-address=,127.0.0.1 + +################################# +# local-address-nonexist-fail Fail to start if one or more of the local-address's do not exist on this server +# +# local-address-nonexist-fail=yes + +################################# +# local-ipv6 Local IP address to which we bind +# +# local-ipv6= + +################################# +# local-ipv6-nonexist-fail Fail to start if one or more of the local-ipv6 addresses do not exist on this server +# +# local-ipv6-nonexist-fail=yes + +################################# +# local-port The port on which we listen +# +# local-port=53 + +################################# +# log-dns-details If PDNS should log DNS non-erroneous details +# +# log-dns-details=no + +################################# +# log-dns-queries If PDNS should log all incoming DNS queries +# +# log-dns-queries=no + +################################# +# logging-facility Log under a specific facility +# +# logging-facility= + +################################# +# loglevel Amount of logging. Higher is more. Do not set below 3 +# +# loglevel=4 + +################################# +# lua-prequery-script Lua script with prequery handler +# +# lua-prequery-script= + +################################# +# master Act as a master +# +master=yes + +################################# +# max-cache-entries Maximum number of cache entries +# +# max-cache-entries=1000000 + +################################# +# max-ent-entries Maximum number of empty non-terminals in a zone +# +# max-ent-entries=100000 + +################################# +# max-nsec3-iterations Limit the number of NSEC3 hash iterations +# +# max-nsec3-iterations=500 + +################################# +# max-queue-length Maximum queuelength before considering situation lost +# +# max-queue-length=5000 + +################################# +# max-signature-cache-entries Maximum number of signatures cache entries +# +# max-signature-cache-entries= + +################################# +# max-tcp-connections Maximum number of TCP connections +# +# max-tcp-connections=10 + +################################# +# module-dir Default directory for modules +# +# module-dir=/usr/lib/TRIPLET/pdns + +################################# +# negquery-cache-ttl Seconds to store negative query results in the QueryCache +# +# negquery-cache-ttl=60 + +################################# +# no-shuffle Set this to prevent random shuffling of answers - for regression testing +# +# no-shuffle=off + +################################# +# only-notify Only send AXFR NOTIFY to these IP addresses or netmasks +# +# only-notify=0.0.0.0/0,::/0 + +################################# +# out-of-zone-additional-processing Do out of zone additional processing +# +# out-of-zone-additional-processing=yes + +################################# +# overload-queue-length Maximum queuelength moving to packetcache only +# +# overload-queue-length=0 + +################################# +# pipebackend-abi-version Version of the pipe backend ABI +# +# pipebackend-abi-version=1 + +################################# +# prevent-self-notification Don't send notifications to what we think is ourself +# +# prevent-self-notification=yes + +################################# +# query-cache-ttl Seconds to store query results in the QueryCache +# +# query-cache-ttl=20 + +################################# +# query-local-address Source IP address for sending queries +# +# query-local-address=0.0.0.0 + +################################# +# query-local-address6 Source IPv6 address for sending queries +# +# query-local-address6=:: + +################################# +# query-logging Hint backends that queries should be logged +# +# query-logging=no + +################################# +# queue-limit Maximum number of milliseconds to queue a query +# +# queue-limit=1500 + +################################# +# receiver-threads Default number of receiver threads to start +# +# receiver-threads=1 + +################################# +# recursive-cache-ttl Seconds to store packets for recursive queries in the PacketCache +# +# recursive-cache-ttl=10 + +################################# +# recursor If recursion is desired, IP address of a recursing nameserver +# +# recursor=no + +################################# +# retrieval-threads Number of AXFR-retrieval threads for slave operation +# +# retrieval-threads=2 + +################################# +# reuseport Enable higher performance on compliant kernels by using SO_REUSEPORT allowing each receiver thread to open its own socket +# +# reuseport=no + +################################# +# security-poll-suffix Domain name from which to query security update notifications +# +# security-poll-suffix=secpoll.powerdns.com. + +################################# +# send-root-referral Send out old-fashioned root-referral instead of ServFail in case of no authority +# +# send-root-referral=no + +################################# +# server-id Returned when queried for 'server.id' TXT or NSID, defaults to hostname - disabled or custom +# +# server-id= + +################################# +# setgid If set, change group id to this gid for more security +# +setgid=pdns + +################################# +# setuid If set, change user id to this uid for more security +# +setuid=pdns + +################################# +# signing-threads Default number of signer threads to start +# +# signing-threads=3 + +################################# +# slave Act as a slave +# +# slave=no + +################################# +# slave-cycle-interval Reschedule failed SOA serial checks once every .. seconds +# +# slave-cycle-interval=60 + +################################# +# slave-renotify If we should send out notifications for slaved updates +# +# slave-renotify=no + +################################# +# soa-expire-default Default SOA expire +# +# soa-expire-default=604800 + +################################# +# soa-minimum-ttl Default SOA minimum ttl +# +# soa-minimum-ttl=3600 + +################################# +# soa-refresh-default Default SOA refresh +# +# soa-refresh-default=10800 + +################################# +# soa-retry-default Default SOA retry +# +# soa-retry-default=3600 + +################################# +# socket-dir Where the controlsocket will live +# +# socket-dir=/var/run + +################################# +# tcp-control-address If set, PowerDNS can be controlled over TCP on this address +# +# tcp-control-address= + +################################# +# tcp-control-port If set, PowerDNS can be controlled over TCP on this address +# +# tcp-control-port=53000 + +################################# +# tcp-control-range If set, remote control of PowerDNS is possible over these networks only +# +# tcp-control-range=127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fe80::/10 + +################################# +# tcp-control-secret If set, PowerDNS can be controlled over TCP after passing this secret +# +# tcp-control-secret= + +################################# +# traceback-handler Enable the traceback handler (Linux only) +# +# traceback-handler=yes + +################################# +# trusted-notification-proxy IP address of incoming notification proxy +# +# trusted-notification-proxy= + +################################# +# udp-truncation-threshold Maximum UDP response size before we truncate +# +# udp-truncation-threshold=1680 + +################################# +# version-string PowerDNS version in packets - full, anonymous, powerdns or custom +# + +version-string=powerdns +################################# +# webserver Start a webserver for monitoring +# +# webserver=no + +################################# +# webserver-address IP Address of webserver to listen on +# +# webserver-address=127.0.0.1 + +################################# +# webserver-allow-from Webserver access is only allowed from these subnets +# +# webserver-allow-from=0.0.0.0/0,::/0 + +################################# +# webserver-password Password required for accessing the webserver +# +# webserver-password= + +################################# +# webserver-port Port of webserver to listen on +# +# webserver-port=8081 + +################################# +# webserver-print-arguments If the webserver should print arguments +# +# webserver-print-arguments=no + +# include froxlor-bind-specific config +include-dir=/etc/powerdns/froxlor/ +]]> + + + + + named.conf + +# How often to check for zone changes. See 'Operation' section. +bind-check-interval=180 + +# Uncomment to enable Huffman compression on zone data. +# Currently saves around 20% of memory actually used, but slows down operation. +# bind-enable-huffman +]]> + + + + + + + + + + + + {{settings.system.vmail_gid}} + + + + + {{settings.system.vmail_uid}} + + + + + + + + + + + + + + + + + +password = +dbname = +hosts = +query = SELECT destination FROM mail_virtual AS v, panel_customers AS c WHERE c.customerid = v.customerid AND c.deactivated = 0 AND v.email = '%s' AND trim(v.destination) <> '' +]]> + + + + +password = +dbname = +hosts = +query = SELECT domain FROM panel_domains WHERE domain = '%s' AND isemaildomain = '1' +]]> + + + + +password = +dbname = +expansion_limit = 1 +hosts = +query = SELECT CONCAT(homedir,maildir) FROM mail_users WHERE email = '%s' +]]> + + + + +password = +dbname = +hosts = +query = SELECT DISTINCT username FROM mail_users WHERE email in ((SELECT mail_virtual.email_full FROM mail_virtual WHERE mail_virtual.email = '%s' UNION SELECT mail_virtual.destination FROM mail_virtual WHERE mail_virtual.email = '%s')); +]]> + + + + +password = +dbname = +expansion_limit = 1 +hosts = +query = SELECT uid FROM mail_users WHERE email = '%s' +]]> + + + + +password = +dbname = +expansion_limit = 1 +hosts = +query = SELECT gid FROM mail_users WHERE email = '%s' +]]> + + + + +]]> + + + + + + + + + + + //service[@type='smtp']/general/commands[@index=1] + + //service[@type='smtp']/general/installs[@index=1] + + //service[@type='smtp']/general/commands[@index=2] + + + + +#mydestination = $myhostname, localhost.$mydomain, localhost +mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain +#mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain, +# mail.$mydomain, www.$mydomain, ftp.$mydomain + +# The default setting is 550 (reject mail) but it is safer to start +# with 450 (try again later) until you are certain that your +# local_recipient_maps settings are OK. +# +unknown_local_recipient_reject_code = 550 + +# The mailbox_command parameter specifies the optional external +# command to use instead of mailbox delivery. The command is run as +# the recipient with proper HOME, SHELL and LOGNAME environment settings. +# Exception: delivery for root is done as $default_user. +# +# Other environment variables of interest: USER (recipient username), +# EXTENSION (address extension), DOMAIN (domain part of address), +# and LOCAL (the address localpart). +# +# Unlike other Postfix configuration parameters, the mailbox_command +# parameter is not subjected to $parameter substitutions. This is to +# make it easier to specify shell syntax (see example below). +# +# Avoid shell meta characters because they will force Postfix to run +# an expensive shell process. Procmail alone is expensive enough. +# +# IF YOU USE THIS TO DELIVER MAIL SYSTEM-WIDE, YOU MUST SET UP AN +# ALIAS THAT FORWARDS MAIL FOR ROOT TO A REAL USER. +# +mailbox_command = /usr/lib/dovecot/deliver +#mailbox_command = /usr/bin/procmail -a "$EXTENSION" + +# The debugger_command specifies the external command that is executed +# when a Postfix daemon program is run with the -D option. +# +# Use "command .. & sleep 5" so that the debugger can attach before +# the process marches on. If you use an X-based debugger, be sure to +# set up your XAUTHORITY environment variable before starting Postfix. +# +debugger_command = + PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin + ddd $daemon_directory/$process_name $process_id & sleep 5 + +inet_protocols = ipv4 + +smtpd_helo_required = yes +smtpd_recipient_restrictions = permit_mynetworks, + permit_sasl_authenticated, + reject_unauth_destination, + reject_unauth_pipelining, + reject_non_fqdn_recipient +smtpd_sender_restrictions = permit_mynetworks, + reject_sender_login_mismatch, + permit_sasl_authenticated, + reject_unknown_helo_hostname, + reject_unknown_recipient_domain, + reject_unknown_sender_domain +smtpd_client_restrictions = permit_mynetworks, + permit_sasl_authenticated, + reject_unknown_client_hostname + +# Postfix 2.10 requires this option. Postfix < 2.10 ignores this. +# The option is intentionally left empty. +smtpd_relay_restrictions = + +# Maximum size of Message in bytes (50MB) +message_size_limit = 52428800 + +## SASL Auth Settings +smtpd_sasl_auth_enable = yes +smtpd_sasl_local_domain = $myhostname +broken_sasl_auth_clients = yes +## Dovecot Settings for deliver, SASL Auth and virtual transport +smtpd_sasl_type = dovecot +virtual_transport = dovecot +dovecot_destination_recipient_limit = 1 +smtpd_sasl_path = private/auth + +# Virtual delivery settings +virtual_mailbox_base = / +virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual_mailbox_maps.cf +virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual_mailbox_domains.cf +virtual_alias_maps = mysql:/etc/postfix/mysql-virtual_alias_maps.cf +smtpd_sender_login_maps = mysql:/etc/postfix/mysql-virtual_sender_permissions.cf +virtual_uid_maps = static: +virtual_gid_maps = static: + +# Local delivery settings +local_transport = local +alias_maps = $alias_database + +# Default Mailbox size, is set to 0 which means unlimited! +mailbox_size_limit = 0 +virtual_mailbox_limit = 0 + +### TLS settings +### +## TLS for outgoing mails from the server to another server +#smtp_tls_security_level = may +#smtp_tls_note_starttls_offer = yes +## TLS for incoming connections (clients or other mail servers) +#smtpd_tls_security_level = may +#smtpd_tls_cert_file = /etc/ssl/server/.pem +#smtpd_tls_key_file = $smtpd_tls_cert_file +#smtpd_tls_CAfile = /etc/ssl/certs/ca-certificates.crt +#smtpd_tls_loglevel = 1 +#smtpd_tls_received_header = yes +]]> + + + //service[@type='smtp']/general/files[@index=0] + + + + + //service[@type='smtp']/general/commands[@index=3] + + + + + + + + + + + + + to select which instance is used (an alternative +# to -c ). The instance name is also added to Dovecot processes +# in ps output. +#instance_name = dovecot + +# Greeting message for clients. +#login_greeting = Dovecot ready. + +# Space separated list of trusted network ranges. Connections from these +# IPs are allowed to override their IP addresses and ports (for logging and +# for authentication checks). disable_plaintext_auth is also ignored for +# these networks. Typically you'd specify your IMAP proxy servers here. +#login_trusted_networks = + +# Space separated list of login access check sockets (e.g. tcpwrap) +#login_access_sockets = + +# With proxy_maybe=yes if proxy destination matches any of these IPs, don't do +# proxying. This isn't necessary normally, but may be useful if the destination +# IP is e.g. a load balancer's IP. +#auth_proxy_self = + +# Show more verbose process titles (in ps). Currently shows user name and +# IP address. Useful for seeing who are actually using the IMAP processes +# (eg. shared mailboxes or if same uid is used for multiple accounts). +#verbose_proctitle = no + +# Should all processes be killed when Dovecot master process shuts down. +# Setting this to "no" means that Dovecot can be upgraded without +# forcing existing client connections to close (although that could also be +# a problem if the upgrade is e.g. because of a security fix). +#shutdown_clients = yes + +# If non-zero, run mail commands via this many connections to doveadm server, +# instead of running them directly in the same process. +#doveadm_worker_count = 0 +# UNIX socket or host:port used for connecting to doveadm server +#doveadm_socket_path = doveadm-server + +# Space separated list of environment variables that are preserved on Dovecot +# startup and passed down to all of its child processes. You can also give +# key=value pairs to always set specific settings. +#import_environment = TZ + +## +## Dictionary server settings +## + +# Dictionary can be used to store key=value lists. This is used by several +# plugins. The dictionary can be accessed either directly or though a +# dictionary server. The following dict block maps dictionary names to URIs +# when the server is used. These can then be referenced using URIs in format +# "proxy::". + +dict { + #quota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext + #expire = sqlite:/etc/dovecot/dovecot-dict-sql.conf.ext +} + +# Most of the actual configuration gets included below. The filenames are +# first sorted by their ASCII value and parsed in that order. The 00-prefixes +# in filenames are intended to make it easier to understand the ordering. +!include conf.d/*.conf + +# A config file can also tried to be included without giving an error if +# it's not found: +!include_try local.conf +]]> + + + + dbname= user= password= + +# Default password scheme. +# +# List of supported schemes is in +# http://wiki2.dovecot.org/Authentication/PasswordSchemes +# +default_pass_scheme = CRYPT + +# passdb query to retrieve the password. It can return fields: +# password - The user's password. This field must be returned. +# user - user@domain from the database. Needed with case-insensitive lookups. +# username and domain - An alternative way to represent the "user" field. +# +# The "user" field is often necessary with case-insensitive lookups to avoid +# e.g. "name" and "nAme" logins creating two different mail directories. If +# your user and domain names are in separate fields, you can return "username" +# and "domain" fields instead of "user". +# +# The query can also return other fields which have a special meaning, see +# http://wiki2.dovecot.org/PasswordDatabase/ExtraFields +# +# Commonly used available substitutions (see http://wiki2.dovecot.org/Variables +# for full list): +# %u = entire user@domain +# %n = user part of user@domain +# %d = domain part of user@domain +# +# Note that these can be used only as input to SQL query. If the query outputs +# any of these substitutions, they're not touched. Otherwise it would be +# difficult to have eg. usernames containing '%' characters. +# +# Example: +# password_query = SELECT userid AS user, pw AS password \ +# FROM users WHERE userid = '%u' AND active = 'Y' +# +#password_query = \ +# SELECT username, domain, password \ +# FROM users WHERE username = '%n' AND domain = '%d' + +# userdb query to retrieve the user information. It can return fields: +# uid - System UID (overrides mail_uid setting) +# gid - System GID (overrides mail_gid setting) +# home - Home directory +# mail - Mail location (overrides mail_location setting) +# +# None of these are strictly required. If you use a single UID and GID, and +# home or mail directory fits to a template string, you could use userdb static +# instead. For a list of all fields that can be returned, see +# http://wiki2.dovecot.org/UserDatabase/ExtraFields +# +# Examples: +# user_query = SELECT home, uid, gid FROM users WHERE userid = '%u' +# user_query = SELECT dir AS home, user AS uid, group AS gid FROM users where userid = '%u' +# user_query = SELECT home, 501 AS uid, 501 AS gid FROM users WHERE userid = '%u' +# +#user_query = \ +# SELECT home, uid, gid \ +# FROM users WHERE username = '%n' AND domain = '%d' +user_query = SELECT CONCAT(homedir, maildir) AS home, CONCAT('maildir:', homedir, maildir) AS mail, uid, gid, CONCAT('*:storage=', quota, 'M') as quota_rule FROM mail_users WHERE (username = '%u' OR email = '%u') + +# If you wish to avoid two SQL lookups (passdb + userdb), you can use +# userdb prefetch instead of userdb sql in dovecot.conf. In that case you'll +# also have to return userdb fields in password_query prefixed with "userdb_" +# string. For example: +#password_query = \ +# SELECT userid AS user, password, \ +# home AS userdb_home, uid AS userdb_uid, gid AS userdb_gid \ +# FROM users WHERE userid = '%u' +password_query = SELECT username AS user, password_enc AS password, CONCAT(homedir, maildir) AS userdb_home, uid AS userdb_uid, gid AS userdb_gid, CONCAT('maildir:', homedir, maildir) AS userdb_mail, CONCAT('*:storage=', quota, 'M') as userdb_quota_rule FROM mail_users WHERE (username = '%u' OR email = '%u') AND ((imap = 1 AND '%Ls' = 'imap') OR (pop3 = 1 AND '%Ls' = 'pop3') OR ((postfix = 'Y' AND '%Ls' = 'smtp') OR (postfix = 'Y' AND '%Ls' = 'sieve'))) + +# Query to get a list of all usernames. +#iterate_query = SELECT username AS user FROM users +]]> + + + + to characters. For example "#@/@" means +# that '#' and '/' characters are translated to '@'. +#auth_username_translation = + +# Username formatting before it's looked up from databases. You can use +# the standard variables here, eg. %Lu would lowercase the username, %n would +# drop away the domain if it was given, or "%n-AT-%d" would change the '@' into +# "-AT-". This translation is done after auth_username_translation changes. +#auth_username_format = %Lu + +# If you want to allow master users to log in by specifying the master +# username within the normal username string (ie. not using SASL mechanism's +# support for it), you can specify the separator character here. The format +# is then . UW-IMAP uses "*" as the +# separator, so that could be a good choice. +#auth_master_user_separator = + +# Username to use for users logging in with ANONYMOUS SASL mechanism +#auth_anonymous_username = anonymous + +# Maximum number of dovecot-auth worker processes. They're used to execute +# blocking passdb and userdb queries (eg. MySQL and PAM). They're +# automatically created and destroyed as needed. +#auth_worker_max_count = 30 + +# Host name to use in GSSAPI principal names. The default is to use the +# name returned by gethostname(). Use "$ALL" (with quotes) to allow all keytab +# entries. +#auth_gssapi_hostname = + +# Kerberos keytab to use for the GSSAPI mechanism. Will use the system +# default (usually /etc/krb5.keytab) if not specified. You may need to change +# the auth service to run as root to be able to read this file. +#auth_krb5_keytab = + +# Do NTLM and GSS-SPNEGO authentication using Samba's winbind daemon and +# ntlm_auth helper. +#auth_use_winbind = no + +# Path for Samba's ntlm_auth helper binary. +#auth_winbind_helper_path = /usr/bin/ntlm_auth + +# Time to delay before replying to failed authentications. +#auth_failure_delay = 2 secs + +# Require a valid SSL client certificate or the authentication fails. +#auth_ssl_require_client_cert = no + +# Take the username from client's SSL certificate, using +# X509_NAME_get_text_by_NID() which returns the subject's DN's +# CommonName. +#auth_ssl_username_from_cert = no + +# Space separated list of wanted authentication mechanisms: +# plain login digest-md5 cram-md5 ntlm rpa apop anonymous gssapi otp skey +# gss-spnego +# NOTE: See also disable_plaintext_auth setting. +auth_mechanisms = plain login + +## +## Password and user databases +## + +# +# Password database is used to verify user's password (and nothing more). +# You can have multiple passdbs and userdbs. This is useful if you want to +# allow both system users (/etc/passwd) and virtual users to login without +# duplicating the system users into virtual database. +# +# +# +# User database specifies where mails are located and what user/group IDs +# own them. For single-UID configuration use "static" userdb. +# +# + +#!include auth-deny.conf.ext +#!include auth-master.conf.ext + +#!include auth-system.conf.ext +!include auth-sql.conf.ext +#!include auth-ldap.conf.ext +#!include auth-passwdfile.conf.ext +#!include auth-checkpassword.conf.ext +#!include auth-vpopmail.conf.ext +#!include auth-static.conf.ext +]]> + + + + +# +mail_location = mbox:~/mail:INBOX=/var/mail/%u + +# If you need to set multiple mailbox locations or want to change default +# namespace settings, you can do it by defining namespace sections. +# +# You can have private, shared and public namespaces. Private namespaces +# are for user's personal mails. Shared namespaces are for accessing other +# users' mailboxes that have been shared. Public namespaces are for shared +# mailboxes that are managed by sysadmin. If you create any shared or public +# namespaces you'll typically want to enable ACL plugin also, otherwise all +# users can access all the shared mailboxes, assuming they have permissions +# on filesystem level to do so. +namespace inbox { + # Namespace type: private, shared or public + #type = private + + # Hierarchy separator to use. You should use the same separator for all + # namespaces or some clients get confused. '/' is usually a good one. + # The default however depends on the underlying mail storage format. + #separator = + + # Prefix required to access this namespace. This needs to be different for + # all namespaces. For example "Public/". + #prefix = + + # Physical location of the mailbox. This is in same format as + # mail_location, which is also the default for it. + #location = + + # There can be only one INBOX, and this setting defines which namespace + # has it. + inbox = yes + + # If namespace is hidden, it's not advertised to clients via NAMESPACE + # extension. You'll most likely also want to set list=no. This is mostly + # useful when converting from another server with different namespaces which + # you want to deprecate but still keep working. For example you can create + # hidden namespaces with prefixes "~/mail/", "~%u/mail/" and "mail/". + #hidden = no + + # Show the mailboxes under this namespace with LIST command. This makes the + # namespace visible for clients that don't support NAMESPACE extension. + # "children" value lists child mailboxes, but hides the namespace prefix. + #list = yes + + # Namespace handles its own subscriptions. If set to "no", the parent + # namespace handles them (empty prefix should always have this as "yes") + #subscriptions = yes +} + +# Example shared namespace configuration +#namespace { + #type = shared + #separator = / + + # Mailboxes are visible under "shared/user@domain/" + # %%n, %%d and %%u are expanded to the destination user. + #prefix = shared/%%u/ + + # Mail location for other users' mailboxes. Note that %variables and ~/ + # expands to the logged in user's data. %%n, %%d, %%u and %%h expand to the + # destination user's data. + #location = maildir:%%h/Maildir:INDEX=~/Maildir/shared/%%u + + # Use the default namespace for saving subscriptions. + #subscriptions = no + + # List the shared/ namespace only if there are visible shared mailboxes. + #list = children +#} +# Should shared INBOX be visible as "shared/user" or "shared/user/INBOX"? +#mail_shared_explicit_inbox = no + +# System user and group used to access mails. If you use multiple, userdb +# can override these by returning uid or gid fields. You can use either numbers +# or names. +#mail_uid = +#mail_gid = + +# Group to enable temporarily for privileged operations. Currently this is +# used only with INBOX when either its initial creation or dotlocking fails. +# Typically this is set to "mail" to give access to /var/mail. +#mail_privileged_group = + +# Grant access to these supplementary groups for mail processes. Typically +# these are used to set up access to shared mailboxes. Note that it may be +# dangerous to set these if users can create symlinks (e.g. if "mail" group is +# set here, ln -s /var/mail ~/mail/var could allow a user to delete others' +# mailboxes, or ln -s /secret/shared/box ~/mail/mybox would allow reading it). +mail_access_groups = vmail + +# Allow full filesystem access to clients. There's no access checks other than +# what the operating system does for the active UID/GID. It works with both +# maildir and mboxes, allowing you to prefix mailboxes names with eg. /path/ +# or ~user/. +#mail_full_filesystem_access = no + +# Dictionary for key=value mailbox attributes. Currently used by URLAUTH, but +# soon intended to be used by METADATA as well. +#mail_attribute_dict = + +## +## Mail processes +## + +# Don't use mmap() at all. This is required if you store indexes to shared +# filesystems (NFS or clustered filesystem). +#mmap_disable = no + +# Rely on O_EXCL to work when creating dotlock files. NFS supports O_EXCL +# since version 3, so this should be safe to use nowadays by default. +#dotlock_use_excl = yes + +# When to use fsync() or fdatasync() calls: +# optimized (default): Whenever necessary to avoid losing important data +# always: Useful with e.g. NFS when write()s are delayed +# never: Never use it (best performance, but crashes can lose data) +#mail_fsync = optimized + +# Locking method for index files. Alternatives are fcntl, flock and dotlock. +# Dotlocking uses some tricks which may create more disk I/O than other locking +# methods. NFS users: flock doesn't work, remember to change mmap_disable. +#lock_method = fcntl + +# Directory in which LDA/LMTP temporarily stores incoming mails >128 kB. +#mail_temp_dir = /tmp + +# Valid UID range for users, defaults to 500 and above. This is mostly +# to make sure that users can't log in as daemons or other system users. +# Note that denying root logins is hardcoded to dovecot binary and can't +# be done even if first_valid_uid is set to 0. +#first_valid_uid = 500 +#last_valid_uid = 0 + +# Valid GID range for users, defaults to non-root/wheel. Users having +# non-valid GID as primary group ID aren't allowed to log in. If user +# belongs to supplementary groups with non-valid GIDs, those groups are +# not set. +#first_valid_gid = 1 +#last_valid_gid = 0 + +# Maximum allowed length for mail keyword name. It's only forced when trying +# to create new keywords. +#mail_max_keyword_length = 50 + +# ':' separated list of directories under which chrooting is allowed for mail +# processes (ie. /var/mail will allow chrooting to /var/mail/foo/bar too). +# This setting doesn't affect login_chroot, mail_chroot or auth chroot +# settings. If this setting is empty, "/./" in home dirs are ignored. +# WARNING: Never add directories here which local users can modify, that +# may lead to root exploit. Usually this should be done only if you don't +# allow shell access for users. +#valid_chroot_dirs = + +# Default chroot directory for mail processes. This can be overridden for +# specific users in user database by giving /./ in user's home directory +# (eg. /home/./user chroots into /home). Note that usually there is no real +# need to do chrooting, Dovecot doesn't allow users to access files outside +# their mail directory anyway. If your home directories are prefixed with +# the chroot directory, append "/." to mail_chroot. +#mail_chroot = + +# UNIX socket path to master authentication server to find users. +# This is used by imap (for shared users) and lda. +#auth_socket_path = /var/run/dovecot/auth-userdb + +# Directory where to look up mail plugins. +#mail_plugin_dir = /usr/lib/dovecot/modules + +# Space separated list of plugins to load for all services. Plugins specific to +# IMAP, LDA, etc. are added to this list in their own .conf files. +#mail_plugins = + +## +## Mailbox handling optimizations +## + +# Mailbox list indexes can be used to optimize IMAP STATUS commands. They are +# also required for IMAP NOTIFY extension to be enabled. +#mailbox_list_index = no + +# The minimum number of mails in a mailbox before updates are done to cache +# file. This allows optimizing Dovecot's behavior to do less disk writes at +# the cost of more disk reads. +#mail_cache_min_mail_count = 0 + +# When IDLE command is running, mailbox is checked once in a while to see if +# there are any new mails or other changes. This setting defines the minimum +# time to wait between those checks. Dovecot can also use dnotify, inotify and +# kqueue to find out immediately when changes occur. +#mailbox_idle_check_interval = 30 secs + +# Save mails with CR+LF instead of plain LF. This makes sending those mails +# take less CPU, especially with sendfile() syscall with Linux and FreeBSD. +# But it also creates a bit more disk I/O which may just make it slower. +# Also note that if other software reads the mboxes/maildirs, they may handle +# the extra CRs wrong and cause problems. +#mail_save_crlf = no + +# Max number of mails to keep open and prefetch to memory. This only works with +# some mailbox formats and/or operating systems. +#mail_prefetch_count = 0 + +# How often to scan for stale temporary files and delete them (0 = never). +# These should exist only after Dovecot dies in the middle of saving mails. +#mail_temp_scan_interval = 1w + +## +## Maildir-specific settings +## + +# By default LIST command returns all entries in maildir beginning with a dot. +# Enabling this option makes Dovecot return only entries which are directories. +# This is done by stat()ing each entry, so it causes more disk I/O. +# (For systems setting struct dirent->d_type, this check is free and it's +# done always regardless of this setting) +#maildir_stat_dirs = no + +# When copying a message, do it with hard links whenever possible. This makes +# the performance much better, and it's unlikely to have any side effects. +#maildir_copy_with_hardlinks = yes + +# Assume Dovecot is the only MUA accessing Maildir: Scan cur/ directory only +# when its mtime changes unexpectedly or when we can't find the mail otherwise. +#maildir_very_dirty_syncs = no + +# If enabled, Dovecot doesn't use the S= in the Maildir filenames for +# getting the mail's physical size, except when recalculating Maildir++ quota. +# This can be useful in systems where a lot of the Maildir filenames have a +# broken size. The performance hit for enabling this is very small. +#maildir_broken_filename_sizes = no + +# Always move mails from new/ directory to cur/, even when the \Recent flags +# aren't being reset. +#maildir_empty_new = no + +## +## mbox-specific settings +## + +# Which locking methods to use for locking mbox. There are four available: +# dotlock: Create .lock file. This is the oldest and most NFS-safe +# solution. If you want to use /var/mail/ like directory, the users +# will need write access to that directory. +# dotlock_try: Same as dotlock, but if it fails because of permissions or +# because there isn't enough disk space, just skip it. +# fcntl : Use this if possible. Works with NFS too if lockd is used. +# flock : May not exist in all systems. Doesn't work with NFS. +# lockf : May not exist in all systems. Doesn't work with NFS. +# +# You can use multiple locking methods; if you do the order they're declared +# in is important to avoid deadlocks if other MTAs/MUAs are using multiple +# locking methods as well. Some operating systems don't allow using some of +# them simultaneously. +# +# The Debian value for mbox_write_locks differs from upstream Dovecot. It is +# changed to be compliant with Debian Policy (section 11.6) for NFS safety. +# Dovecot: mbox_write_locks = dotlock fcntl +# Debian: mbox_write_locks = fcntl dotlock +# +#mbox_read_locks = fcntl +#mbox_write_locks = fcntl dotlock + +# Maximum time to wait for lock (all of them) before aborting. +#mbox_lock_timeout = 5 mins + +# If dotlock exists but the mailbox isn't modified in any way, override the +# lock file after this much time. +#mbox_dotlock_change_timeout = 2 mins + +# When mbox changes unexpectedly we have to fully read it to find out what +# changed. If the mbox is large this can take a long time. Since the change +# is usually just a newly appended mail, it'd be faster to simply read the +# new mails. If this setting is enabled, Dovecot does this but still safely +# fallbacks to re-reading the whole mbox file whenever something in mbox isn't +# how it's expected to be. The only real downside to this setting is that if +# some other MUA changes message flags, Dovecot doesn't notice it immediately. +# Note that a full sync is done with SELECT, EXAMINE, EXPUNGE and CHECK +# commands. +#mbox_dirty_syncs = yes + +# Like mbox_dirty_syncs, but don't do full syncs even with SELECT, EXAMINE, +# EXPUNGE or CHECK commands. If this is set, mbox_dirty_syncs is ignored. +#mbox_very_dirty_syncs = no + +# Delay writing mbox headers until doing a full write sync (EXPUNGE and CHECK +# commands and when closing the mailbox). This is especially useful for POP3 +# where clients often delete all mails. The downside is that our changes +# aren't immediately visible to other MUAs. +#mbox_lazy_writes = yes + +# If mbox size is smaller than this (e.g. 100k), don't write index files. +# If an index file already exists it's still read, just not updated. +#mbox_min_index_size = 0 + +# Mail header selection algorithm to use for MD5 POP3 UIDLs when +# pop3_uidl_format=%m. For backwards compatibility we use apop3d inspired +# algorithm, but it fails if the first Received: header isn't unique in all +# mails. An alternative algorithm is "all" that selects all headers. +#mbox_md5 = apop3d + +## +## mdbox-specific settings +## + +# Maximum dbox file size until it's rotated. +#mdbox_rotate_size = 2M + +# Maximum dbox file age until it's rotated. Typically in days. Day begins +# from midnight, so 1d = today, 2d = yesterday, etc. 0 = check disabled. +#mdbox_rotate_interval = 0 + +# When creating new mdbox files, immediately preallocate their size to +# mdbox_rotate_size. This setting currently works only in Linux with some +# filesystems (ext4, xfs). +#mdbox_preallocate_space = no + +## +## Mail attachments +## + +# sdbox and mdbox support saving mail attachments to external files, which +# also allows single instance storage for them. Other backends don't support +# this for now. + +# Directory root where to store mail attachments. Disabled, if empty. +#mail_attachment_dir = + +# Attachments smaller than this aren't saved externally. It's also possible to +# write a plugin to disable saving specific attachments externally. +#mail_attachment_min_size = 128k + +# Filesystem backend to use for saving attachments: +# posix : No SiS done by Dovecot (but this might help FS's own deduplication) +# sis posix : SiS with immediate byte-by-byte comparison during saving +# sis-queue posix : SiS with delayed comparison and deduplication +#mail_attachment_fs = sis posix + +# Hash format to use in attachment filenames. You can add any text and +# variables: %{md4}, %{md5}, %{sha1}, %{sha256}, %{sha512}, %{size}. +# Variables can be truncated, e.g. %{sha256:80} returns only first 80 bits +#mail_attachment_hash = %{sha1} +]]> + + + + + #service_count = 1 + + # Number of processes to always keep waiting for more connections. + #process_min_avail = 0 + + # If you set service_count=0, you probably need to grow this. + #vsz_limit = $default_vsz_limit +} + +service pop3-login { + inet_listener pop3 { + #port = 110 + } + inet_listener pop3s { + #port = 995 + #ssl = yes + } +} + +service lmtp { + unix_listener lmtp { + #mode = 0666 + } + + # Create inet listener only if you can't use the above UNIX socket + #inet_listener lmtp { + # Avoid making LMTP visible for the entire internet + #address = + #port = + #} +} + +service imap { + # Most of the memory goes to mmap()ing files. You may need to increase this + # limit if you have huge mailboxes. + #vsz_limit = $default_vsz_limit + + # Max. number of IMAP processes (connections) + #process_limit = 1024 +} + +service pop3 { + # Max. number of POP3 processes (connections) + #process_limit = 1024 +} + +service auth { + # auth_socket_path points to this userdb socket by default. It's typically + # used by dovecot-lda, doveadm, possibly imap process, etc. Users that have + # full permissions to this socket are able to get a list of all usernames and + # get the results of everyone's userdb lookups. + # + # The default 0666 mode allows anyone to connect to the socket, but the + # userdb lookups will succeed only if the userdb returns an "uid" field that + # matches the caller process's UID. Also if caller's uid or gid matches the + # socket's uid or gid the lookup succeeds. Anything else causes a failure. + # + # To give the caller full permissions to lookup all users, set the mode to + # something else than 0666 and Dovecot lets the kernel enforce the + # permissions (e.g. 0777 allows everyone full permissions). + unix_listener auth-userdb { + #mode = 0666 + #user = + #group = + } + + # Postfix smtp-auth + unix_listener /var/spool/postfix/private/auth { + mode = 0660 + user = postfix + group = postfix + } + + # Exim4 smtp-auth + unix_listener auth-client { + mode = 0660 + user = mail + # group = Debian-exim + } + + # Auth process is run as this user. + #user = $default_internal_user +} + +service auth-worker { + # Auth worker process is run as root by default, so that it can access + # /etc/shadow. If this isn't necessary, the user should be changed to + # $default_internal_user. + #user = root +} + +service dict { + # If dict proxy is used, mail processes should have access to its socket. + # For example: mode=0660, group=vmail and global mail_access_groups=vmail + unix_listener dict { + #mode = 0600 + #user = + #group = + } +} +]]> + + + + +ssl = no + +# PEM encoded X.509 SSL/TLS certificate and private key. They're opened before +# dropping root privileges, so keep the key file unreadable by anyone but +# root. Included doc/mkcert.sh can be used to easily generate self-signed +# certificate, just make sure to update the domains in dovecot-openssl.cnf +#ssl_cert = + + + + . %d expands to recipient domain. +postmaster_address = postmaster@ + +# Hostname to use in various parts of sent mails (e.g. in Message-Id) and +# in LMTP replies. Default is the system's real hostname@domain. +#hostname = + +# If user is over quota, return with temporary failure instead of +# bouncing the mail. +#quota_full_tempfail = no + +# Binary to use for sending mails. +#sendmail_path = /usr/sbin/sendmail + +# If non-empty, send mails via this SMTP host[:port] instead of sendmail. +#submission_host = + +# Subject: header to use for rejection mails. You can use the same variables +# as for rejection_reason below. +#rejection_subject = Rejected: %s + +# Human readable error message for rejection mails. You can use variables: +# %n = CRLF, %r = reason, %s = original subject, %t = recipient +#rejection_reason = Your message to <%t> was automatically rejected:%n%r + +# Delimiter character between local-part and detail in email address. +#recipient_delimiter = + + +# Header where the original recipient address (SMTP's RCPT TO: address) is taken +# from if not available elsewhere. With dovecot-lda -a parameter overrides this. +# A commonly used header for this is X-Original-To. +#lda_original_recipient_header = + +# Should saving a mail to a nonexistent mailbox automatically create it? +#lda_mailbox_autocreate = no + +# Should automatically created mailboxes be also automatically subscribed? +#lda_mailbox_autosubscribe = no + +protocol lda { + # Space separated list of plugins to load (default is global mail_plugins). + mail_plugins = $mail_plugins quota sieve +} +]]> + + + + + + + + + #service_count = 1 + + # Number of processes to always keep waiting for more connections. + #process_min_avail = 0 + + # If you set service_count=0, you probably need to grow this. + #vsz_limit = 64M +#} + +#service managesieve { + # Max. number of ManageSieve processes (connections) + #process_limit = 1024 +#} + +# Service configuration + +protocol sieve { + # Maximum ManageSieve command line length in bytes. ManageSieve usually does + # not involve overly long command lines, so this setting will not normally + # need adjustment + #managesieve_max_line_length = 65536 + + # Maximum number of ManageSieve connections allowed for a user from each IP + # address. + # NOTE: The username is compared case-sensitively. + #mail_max_userip_connections = 10 + + # Space separated list of plugins to load (none known to be useful so far). + # Do NOT try to load IMAP plugins here. + #mail_plugins = + + # MANAGESIEVE logout format string: + # %i - total number of bytes read from client + # %o - total number of bytes sent to client + #managesieve_logout_format = bytes=%i/%o + + # To fool ManageSieve clients that are focused on CMU's timesieved you can + # specify the IMPLEMENTATION capability that Dovecot reports to clients. + # For example: 'Cyrus timsieved v2.2.13' + #managesieve_implementation_string = Dovecot Pigeonhole + + # Explicitly specify the SIEVE and NOTIFY capability reported by the server + # before login. If left unassigned these will be reported dynamically + # according to what the Sieve interpreter supports by default (after login + # this may differ depending on the user). + #managesieve_sieve_capability = + #managesieve_notify_capability = + + # The maximum number of compile errors that are returned to the client upon + # script upload or script verification. + #managesieve_max_compile_errors = 5 + + # Refer to 90-sieve.conf for script quota configuration and configuration of + # Sieve execution limits. +} +]]> + + + + = 2.1.4) : %v.%u +# Dovecot v0.99.x : %v.%u +# tpop3d : %Mf +# +# Note that Outlook 2003 seems to have problems with %v.%u format which was +# Dovecot's default, so if you're building a new server it would be a good +# idea to change this. %08Xu%08Xv should be pretty fail-safe. +# +#pop3_uidl_format = %08Xu%08Xv + +# Permanently save UIDLs sent to POP3 clients, so pop3_uidl_format changes +# won't change those UIDLs. Currently this works only with Maildir. +#pop3_save_uidl = no + +# What to do about duplicate UIDLs if they exist? +# allow: Show duplicates to clients. +# rename: Append a temporary -2, -3, etc. counter after the UIDL. +#pop3_uidl_duplicates = allow + +# This option changes POP3 behavior so that it's not possible to actually +# delete mails via POP3, only hide them from future POP3 sessions. The mails +# will still be counted towards user's quota until actually deleted via IMAP. +# Use e.g. "$POP3Deleted" as the value (it will be visible as IMAP keyword). +# Make sure you can legally archive mails before enabling this setting. +#pop3_deleted_flag = + +# POP3 logout format string: +# %i - total number of bytes read from client +# %o - total number of bytes sent to client +# %t - number of TOP commands +# %p - number of bytes sent to client as a result of TOP command +# %r - number of RETR commands +# %b - number of bytes sent to client as a result of RETR command +# %d - number of deleted messages +# %m - number of messages (before deletion) +# %s - mailbox size in bytes (before deletion) +# %u - old/new UIDL hash. may help finding out if UIDLs changed unexpectedly +pop3_logout_format = in=%i out=%o top=%t/%p, retr=%r/%b, del=%d/%m, size=%s + +# Workarounds for various client bugs: +# outlook-no-nuls: +# Outlook and Outlook Express hang if mails contain NUL characters. +# This setting replaces them with 0x80 character. +# oe-ns-eoh: +# Outlook Express and Netscape Mail breaks if end of headers-line is +# missing. This option simply sends it if it's missing. +# The list is space-separated. +#pop3_client_workarounds = + +protocol pop3 { + # Space separated list of plugins to load (default is global mail_plugins). + #mail_plugins = $mail_plugins + + # Maximum number of POP3 connections allowed for a user from each IP address. + # NOTE: The username is compared case-sensitively. + #mail_max_userip_connections = 10 +} +]]> + + + + See sieve_before fore executing scripts before the user's personal + # script. + #sieve_default = /var/lib/dovecot/sieve/default.sieve + + # Directory for :personal include scripts for the include extension. This + # is also where the ManageSieve service stores the user's scripts. + sieve_dir = ~/sieve + + # Directory for :global include scripts for the include extension. + #sieve_global_dir = + + # Path to a script file or a directory containing script files that need to be + # executed before the user's script. If the path points to a directory, all + # the Sieve scripts contained therein (with the proper .sieve extension) are + # executed. The order of execution within a directory is determined by the + # file names, using a normal 8bit per-character comparison. Multiple script + # file or directory paths can be specified by appending an increasing number. + #sieve_before = + #sieve_before2 = + #sieve_before3 = (etc...) + + # Identical to sieve_before, only the specified scripts are executed after the + # user's script (only when keep is still in effect!). Multiple script file or + # directory paths can be specified by appending an increasing number. + #sieve_after = + #sieve_after2 = + #sieve_after2 = (etc...) + + # Which Sieve language extensions are available to users. By default, all + # supported extensions are available, except for deprecated extensions or + # those that are still under development. Some system administrators may want + # to disable certain Sieve extensions or enable those that are not available + # by default. This setting can use '+' and '-' to specify differences relative + # to the default. For example `sieve_extensions = +imapflags' will enable the + # deprecated imapflags extension in addition to all extensions were already + # enabled by default. + #sieve_extensions = +notify +imapflags + + # Which Sieve language extensions are ONLY available in global scripts. This + # can be used to restrict the use of certain Sieve extensions to administrator + # control, for instance when these extensions can cause security concerns. + # This setting has higher precedence than the `sieve_extensions' setting + # (above), meaning that the extensions enabled with this setting are never + # available to the user's personal script no matter what is specified for the + # `sieve_extensions' setting. The syntax of this setting is similar to the + # `sieve_extensions' setting, with the difference that extensions are + # enabled or disabled for exclusive use in global scripts. Currently, no + # extensions are marked as such by default. + #sieve_global_extensions = + + # The Pigeonhole Sieve interpreter can have plugins of its own. Using this + # setting, the used plugins can be specified. Check the Dovecot wiki + # (wiki2.dovecot.org) or the pigeonhole website + # (http://pigeonhole.dovecot.org) for available plugins. + # The sieve_extprograms plugin is included in this release. + #sieve_plugins = + + # The separator that is expected between the :user and :detail + # address parts introduced by the subaddress extension. This may + # also be a sequence of characters (e.g. '--'). The current + # implementation looks for the separator from the left of the + # localpart and uses the first one encountered. The :user part is + # left of the separator and the :detail part is right. This setting + # is also used by Dovecot's LMTP service. + #recipient_delimiter = + + + # The maximum size of a Sieve script. The compiler will refuse to compile any + # script larger than this limit. If set to 0, no limit on the script size is + # enforced. + #sieve_max_script_size = 1M + + # The maximum number of actions that can be performed during a single script + # execution. If set to 0, no limit on the total number of actions is enforced. + #sieve_max_actions = 32 + + # The maximum number of redirect actions that can be performed during a single + # script execution. If set to 0, no redirect actions are allowed. + #sieve_max_redirects = 4 + + # The maximum number of personal Sieve scripts a single user can have. If set + # to 0, no limit on the number of scripts is enforced. + # (Currently only relevant for ManageSieve) + #sieve_quota_max_scripts = 0 + + # The maximum amount of disk storage a single user's scripts may occupy. If + # set to 0, no limit on the used amount of disk storage is enforced. + # (Currently only relevant for ManageSieve) + #sieve_quota_max_storage = 0 +} +]]> + + + + + + + + + + //service[@type='mail']/general/installs[@index=1] + + //service[@type='mail']/general/files[@index=1] + + //service[@type='mail']/general/commands[@index=1] + + + + + + + + + + " +[ -f /etc/ssl/certs/proftpd_ec.crt ] || openssl req -new -x509 -nodes -newkey ec:<(openssl ecparam -name secp521r1) -keyout /etc/ssl/private/proftpd_ec.key -out /etc/ssl/certs/proftpd_ec.crt -days 3650 -subj "/C=US/ST=Some-State/O=Internet Widgits Pty Ltd/CN=" +chmod 0600 /etc/ssl/private/proftpd.key /etc/ssl/private/proftpd_ec.key +]]> + + + + + + + + FTP Server" +ServerType standalone +DeferWelcome off + +MultilineRFC2228 on +DefaultServer on +ShowSymlinks on + +TimeoutNoTransfer 600 +TimeoutStalled 600 +TimeoutIdle 1200 + +DisplayLogin welcome.msg +DisplayChdir .message true +ListOptions "-l" + +DenyFilter \*.*/ + +# Use this to jail all users in their homes +# DefaultRoot ~ + +# Users require a valid shell listed in /etc/shells to login. +# Use this directive to release that constrain. +# RequireValidShell off + +# Port 21 is the standard FTP port. +Port 21 + +# In some cases you have to specify passive ports range to by-pass +# firewall limitations. Ephemeral ports can be used for that, but +# feel free to use a more narrow range. +# PassivePorts 49152 65534 + +# If your host was NATted, this option is useful in order to +# allow passive tranfers to work. You have to use your public +# address and opening the passive ports used on your firewall as well. +# MasqueradeAddress 1.2.3.4 + +# This is useful for masquerading address with dynamic IPs: +# refresh any configured MasqueradeAddress directives every 8 hours + +# DynMasqRefresh 28800 + + +# To prevent DoS attacks, set the maximum number of child processes +# to 30. If you need to allow more than 30 concurrent connections +# at once, simply increase this value. Note that this ONLY works +# in standalone mode, in inetd mode you should use an inetd server +# that allows you to limit maximum number of processes per service +# (such as xinetd) +MaxInstances 30 + +# Set the user and group that the server normally runs at. +User proftpd +Group nogroup + +# Umask 022 is a good standard umask to prevent new files and dirs +# (second parm) from being group and world writable. +Umask 022 022 +# Normally, we want files to be overwriteable. +AllowOverwrite on + +# Uncomment this if you are using NIS or LDAP via NSS to retrieve passwords: +# PersistentPasswd off + +# This is required to use both PAM-based authentication and local passwords +# AuthOrder mod_auth_pam.c* mod_auth_unix.c + +# Be warned: use of this directive impacts CPU average load! +# Uncomment this if you like to see progress and transfer rate with ftpwho +# in downloads. That is not needed for uploads rates. +# +# UseSendFile off + +TransferLog /var/log/proftpd/xferlog +SystemLog /var/log/proftpd/proftpd.log + +# Logging onto /var/log/lastlog is enabled but set to off by default +#UseLastlog on + +# In order to keep log file dates consistent after chroot, use timezone info +# from /etc/localtime. If this is not set, and proftpd is configured to +# chroot (e.g. DefaultRoot or ), it will use the non-daylight +# savings timezone regardless of whether DST is in effect. +#SetEnv TZ :/etc/localtime + + +QuotaEngine on + + + +Ratios off + + + +# Delay engine reduces impact of the so-called Timing Attack described in +# http://www.securityfocus.com/bid/11430/discuss +# It is on by default. + +DelayEngine on + + + +ControlsEngine off +ControlsMaxClients 2 +ControlsLog /var/log/proftpd/controls.log +ControlsInterval 5 +ControlsSocket /var/run/proftpd/proftpd.sock + + + +AdminControlsEngine off + + +# +# Alternative authentication frameworks +# +#Include /etc/proftpd/ldap.conf +Include /etc/proftpd/sql.conf + +# +# This is used for FTPS connections +# +Include /etc/proftpd/tls.conf + +# +# Useful to keep VirtualHost/VirtualRoot directives separated +# +#Include /etc/proftpd/virtuals.conf + +# A basic anonymous configuration, no upload directories. + +# +# User ftp +# Group nogroup +# # We want clients to be able to login with "anonymous" as well as "ftp" +# UserAlias anonymous ftp +# # Cosmetic changes, all files belongs to ftp user +# DirFakeUser on ftp +# DirFakeGroup on ftp +# +# RequireValidShell off +# +# # Limit the maximum number of anonymous logins +# MaxClients 10 +# +# # We want 'welcome.msg' displayed at login, and '.message' displayed +# # in each newly chdired directory. +# DisplayLogin welcome.msg +# DisplayChdir .message +# +# # Limit WRITE everywhere in the anonymous chroot +# +# +# DenyAll +# +# +# +# # Uncomment this if you're brave. +# # +# # # Umask 022 is a good standard umask to prevent new files and dirs +# # # (second parm) from being group and world writable. +# # Umask 022 022 +# # +# # DenyAll +# # +# # +# # AllowAll +# # +# # +# +# + +# Include other custom configuration files +Include /etc/proftpd/conf.d/ +]]> + + + + + + + + + +DefaultRoot ~ +RequireValidShell off +AuthOrder mod_sql.c + +# +# Choose a SQL backend among MySQL or PostgreSQL. +# Both modules are loaded in default configuration, so you have to specify the backend +# or comment out the unused module in /etc/proftpd/modules.conf. +# Use 'mysql' or 'postgres' as possible values. +# +SQLBackend mysql +# +SQLEngine on +SQLAuthenticate on +# +# Use both a crypted or plaintext password +SQLAuthTypes Crypt + +SQLAuthenticate users* groups* + +# +# Connection +SQLConnectInfo @ +# +# Describes both users/groups tables +# +SQLUserInfo ftp_users username password uid gid homedir shell +SQLGroupInfo ftp_groups groupname gid members +# +SQLUserWhereClause "login_enabled = 'y'" + +SQLLog PASS login +SQLNamedQuery login UPDATE "last_login=now(), login_count=login_count+1 WHERE username='%u'" ftp_users + +SQLLog RETR download +SQLNamedQuery download UPDATE "down_count=down_count+1, down_bytes=down_bytes+%b WHERE username='%u'" ftp_users + +SQLLog STOR upload +SQLNamedQuery upload UPDATE "up_count=up_count+1, up_bytes=up_bytes+%b WHERE username='%u'" ftp_users + +QuotaEngine on +QuotaShowQuotas on +QuotaDisplayUnits Mb +QuotaLock /var/lock/ftpd.quotatab.lock +QuotaLimitTable sql:/get-quota-limit +QuotaTallyTable sql:/get-quota-tally/update-quota-tally/insert-quota-tally +SQLNamedQuery get-quota-limit SELECT "ftp_users.username AS name, ftp_quotalimits.quota_type, ftp_quotalimits.per_session, ftp_quotalimits.limit_type, panel_customers.diskspace*1024 AS bytes_in_avail, ftp_quotalimits.bytes_out_avail, ftp_quotalimits.bytes_xfer_avail, ftp_quotalimits.files_in_avail, ftp_quotalimits.files_out_avail, ftp_quotalimits.files_xfer_avail FROM ftp_users, ftp_quotalimits, panel_customers WHERE ftp_users.username = '%{0}' AND panel_customers.loginname = SUBSTRING_INDEX('%{0}', 'ftp', 1) AND quota_type ='%{1}'" +SQLNamedQuery get-quota-tally SELECT "name, quota_type, bytes_in_used,bytes_out_used, bytes_xfer_used, files_in_used, files_out_used,files_xfer_used FROM ftp_quotatallies WHERE name = '%{0}' AND quota_type = '%{1}'" +SQLNamedQuery update-quota-tally UPDATE "bytes_in_used = bytes_in_used + %{0}, bytes_out_used = bytes_out_used + %{1}, bytes_xfer_used = bytes_xfer_used + %{2}, files_in_used = files_in_used + %{3}, files_out_used= files_out_used + %{4}, files_xfer_used = files_xfer_used + %{5} WHERE name= '%{6}' AND quota_type = '%{7}'" ftp_quotatallies +SQLNamedQuery insert-quota-tally INSERT "%{0}, %{1}, %{2}, %{3}, %{4},%{5}, %{6}, %{7}" ftp_quotatallies + + +]]> + + + + +TLSEngine on +TLSLog /var/log/proftpd/tls.log +TLSProtocol TLSv1 TLSv1.1 TLSv1.2 +TLSRSACertificateFile /etc/ssl/certs/proftpd.crt +TLSRSACertificateKeyFile /etc/ssl/private/proftpd.key +TLSECCertificateFile /etc/ssl/certs/proftpd_ec.crt +TLSECCertificateKeyFile /etc/ssl/private/proftpd_ec.key +TLSOptions NoCertRequest NoSessionReuseRequired +TLSVerifyClient off + +# Are clients required to use FTP over TLS when talking to this server? +#TLSRequired on + +# Allow SSL/TLS renegotiations when the client requests them, but +# do not force the renegotations. Some clients do not support +# SSL/TLS renegotiations; when mod_tls forces a renegotiation, these +# clients will close the data connection, or there will be a timeout +# on an idle data connection. +# +#TLSRenegotiate required off + +]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# Mandatory : user password. You must have a password. + +MYSQLPassword + + +# Mandatory : database to open. + +MYSQLDatabase + + +# Mandatory : how passwords are stored +# Valid values are : "cleartext", "crypt", "sha1", "md5" and "password" +# ("password" = MySQL password() function) +# You can also use "any" to try "crypt", "sha1", "md5" *and* "password" + +MYSQLCrypt any + + +# In the following directives, parts of the strings are replaced at +# run-time before performing queries : +# +# \L is replaced by the login of the user trying to authenticate. +# \I is replaced by the IP address the user connected to. +# \P is replaced by the port number the user connected to. +# \R is replaced by the IP address the user connected from. +# \D is replaced by the remote IP address, as a long decimal number. +# +# Very complex queries can be performed using these substitution strings, +# especially for virtual hosting. + + +# Query to execute in order to fetch the password + +MYSQLGetPW SELECT password FROM ftp_users WHERE username="\L" AND login_enabled="y" + + +# Query to execute in order to fetch the system user name or uid + +MYSQLGetUID SELECT uid FROM ftp_users WHERE username="\L" AND login_enabled="y" + + +# Optional : default UID - if set this overrides MYSQLGetUID + +#MYSQLDefaultUID 1000 + + +# Query to execute in order to fetch the system user group or gid + +MYSQLGetGID SELECT gid FROM ftp_users WHERE username="\L" AND login_enabled="y" + + +# Optional : default GID - if set this overrides MYSQLGetGID + +#MYSQLDefaultGID 1000 + + +# Query to execute in order to fetch the home directory + +MYSQLGetDir SELECT homedir FROM ftp_users WHERE username="\L" AND login_enabled="y" + + +# Optional : query to get the maximal number of files +# Pure-FTPd must have been compiled with virtual quotas support. + +# MySQLGetQTAFS SELECT QuotaFiles FROM users WHERE User='\L' + + +# Optional : query to get the maximal disk usage (virtual quotas) +# The number should be in Megabytes. +# Pure-FTPd must have been compiled with virtual quotas support. + +MySQLGetQTASZ SELECT panel_customers.diskspace/1024 AS QuotaSize FROM panel_customers, ftp_users WHERE username = "\L" AND panel_customers.loginname = SUBSTRING_INDEX('\L', 'ftp', 1) + + +# Optional : ratios. The server has to be compiled with ratio support. + +# MySQLGetRatioUL SELECT ULRatio FROM users WHERE User='\L' +# MySQLGetRatioDL SELECT DLRatio FROM users WHERE User='\L' + + +# Optional : bandwidth throttling. +# The server has to be compiled with throttling support. +# Values are in KB/s . + +# MySQLGetBandwidthUL SELECT ULBandwidth FROM users WHERE User='\L' +# MySQLGetBandwidthDL SELECT DLBandwidth FROM users WHERE User='\L' + +# Enable ~ expansion. NEVER ENABLE THIS BLINDLY UNLESS : +# 1) You know what you are doing. +# 2) Real and virtual users match. + +# MySQLForceTildeExpansion 1 + + +# If you're using a transactionnal storage engine, you can enable SQL +# transactions to avoid races. Leave this commented if you are using the +# traditional MyIsam engine. + +# MySQLTransactions On +]]> + + + + + + + + + + + + + + + + + + + + + + scripts/froxlor_master_cronjob.php --run-task 99]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + //service[@type='smtp']/general/commands[@index=3] + + + + + + + *.log { + missingok + daily + rotate 7 + compress + delaycompress + notifempty + create + sharedscripts + postrotate + > /dev/null 2>&1 || true + endscript +} +]]> + + + + + + + + + {{settings.system.mod_fcgid_ownvhost}} + + + + + + + + + + + + + + {{settings.system.webserver}} + + + + + + {{settings.system.webserver}} + + + + + {{settings.phpfpm.enabled_ownvhost}} + + {{settings.phpfpm.vhost_httpuser}} + + + + + + {{settings.system.webserver}} + + {{settings.phpfpm.enabled_ownvhost}} + + + + + {{settings.system.webserver}} + + + + + + + + + + From 9ea32b69cbad737ede8dedc04dcd1e389ef67e23 Mon Sep 17 00:00:00 2001 From: Ruben Barkow-Kuder Date: Mon, 25 May 2020 03:14:38 +0200 Subject: [PATCH 048/319] show disk-usage also on unlimited accounts Signed-off-by: Ruben Barkow-Kuder --- templates/Sparkle/admin/admins/admins_admin.tpl | 4 ++-- templates/Sparkle/admin/customers/customers_customer.tpl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/Sparkle/admin/admins/admins_admin.tpl b/templates/Sparkle/admin/admins/admins_admin.tpl index c009ff30..3c67b759 100644 --- a/templates/Sparkle/admin/admins/admins_admin.tpl +++ b/templates/Sparkle/admin/admins/admins_admin.tpl @@ -34,7 +34,7 @@ -
∞ +
@@ -58,7 +58,7 @@ -
∞ +
diff --git a/templates/Sparkle/admin/customers/customers_customer.tpl b/templates/Sparkle/admin/customers/customers_customer.tpl index 6a939ca3..38c71a53 100644 --- a/templates/Sparkle/admin/customers/customers_customer.tpl +++ b/templates/Sparkle/admin/customers/customers_customer.tpl @@ -41,7 +41,7 @@ -
∞ +
@@ -65,7 +65,7 @@ -
∞ +
From 8898c7c165249fcfd51c08f6715fbf9e8fdedd73 Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Mon, 25 May 2020 21:38:58 +0200 Subject: [PATCH 049/319] add named dns config --- lib/configfiles/{rhel_centos.xml => rhel7.xml} | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) rename lib/configfiles/{rhel_centos.xml => rhel7.xml} (98%) diff --git a/lib/configfiles/rhel_centos.xml b/lib/configfiles/rhel7.xml similarity index 98% rename from lib/configfiles/rhel_centos.xml rename to lib/configfiles/rhel7.xml index 3f6ab36a..29c92104 100644 --- a/lib/configfiles/rhel_centos.xml +++ b/lib/configfiles/rhel7.xml @@ -1,6 +1,6 @@ - @@ -61,6 +61,20 @@ Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath} + + + + + + + > /etc/named.conf]]> + > /etc/named.conf.local]]> + + + + + + From c6ac73f74fa746c5cf0fc8785875297ee13c095d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 May 2020 17:01:04 +0000 Subject: [PATCH 050/319] Bump phpmailer/phpmailer from 6.1.4 to 6.1.6 Bumps [phpmailer/phpmailer](https://github.com/PHPMailer/PHPMailer) from 6.1.4 to 6.1.6. - [Release notes](https://github.com/PHPMailer/PHPMailer/releases) - [Changelog](https://github.com/PHPMailer/PHPMailer/blob/master/changelog.md) - [Commits](https://github.com/PHPMailer/PHPMailer/compare/v6.1.4...v6.1.6) Signed-off-by: dependabot[bot] --- composer.lock | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/composer.lock b/composer.lock index 12069d86..cd4d0f9a 100644 --- a/composer.lock +++ b/composer.lock @@ -139,16 +139,16 @@ }, { "name": "phpmailer/phpmailer", - "version": "v6.1.4", + "version": "v6.1.6", "source": { "type": "git", "url": "https://github.com/PHPMailer/PHPMailer.git", - "reference": "c5e61d0729507049cec9673aa1a679f9adefd683" + "reference": "c2796cb1cb99d7717290b48c4e6f32cb6c60b7b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/c5e61d0729507049cec9673aa1a679f9adefd683", - "reference": "c5e61d0729507049cec9673aa1a679f9adefd683", + "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/c2796cb1cb99d7717290b48c4e6f32cb6c60b7b3", + "reference": "c2796cb1cb99d7717290b48c4e6f32cb6c60b7b3", "shasum": "" }, "require": { @@ -197,7 +197,7 @@ } ], "description": "PHPMailer is a full-featured email creation and transfer class for PHP", - "time": "2019-12-10T11:17:38+00:00" + "time": "2020-05-27T12:24:03+00:00" }, { "name": "psr/log", @@ -2849,6 +2849,7 @@ } ], "description": "An XSL wrapper / extension to the PHP 5.x XSLTProcessor with Exception and extended Callback support", + "abandoned": true, "time": "2014-11-27T20:08:52+00:00" }, { From d73d8da2fddd8c25922d8f31b7f5e36c585e0b5c Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Thu, 28 May 2020 20:08:49 +0200 Subject: [PATCH 051/319] read certificate data folder from acme.sh.env file, fixes #846 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 26 ++++++++++++++++++-- lib/Froxlor/Domain/Domain.php | 4 +-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index 4767732d..677d1cbe 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -6,6 +6,7 @@ use Froxlor\Settings; use Froxlor\Database\Database; use Froxlor\PhpHelper; use Froxlor\Domain\Domain; +use Froxlor\FileDir; /** * This file is part of the Froxlor project. @@ -490,7 +491,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron private static function checkFsFilesAreNewer($domain, $cert_date = 0) { - $certificate_folder = dirname(self::$acmesh) . "/" . $domain; + $certificate_folder = self::getWorkingDirFromEnv($domain); if (Settings::Get('system.leecc') > 0) { $certificate_folder .= "_ecc"; } @@ -506,6 +507,27 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron return false; } + public static function getWorkingDirFromEnv($domain = "") + { + $env_file = FileDir::makeCorrectFile(dirname(self::$acmesh) . '/acme.sh.env'); + if (file_exists($env_file)) { + $output = []; + $cut = << 0) { $certificate_folder_noecc = \Froxlor\FileDir::makeCorrectDir($certificate_folder); diff --git a/lib/Froxlor/Domain/Domain.php b/lib/Froxlor/Domain/Domain.php index 8072019b..675b897f 100644 --- a/lib/Froxlor/Domain/Domain.php +++ b/lib/Froxlor/Domain/Domain.php @@ -329,9 +329,9 @@ class Domain public static function doLetsEncryptCleanUp($domainname = null) { // @ see \Froxlor\Cron\Http\LetsEncrypt\AcmeSh.php - $acmesh = "/root/.acme.sh/acme.sh"; + $acmesh = \Froxlor\Cron\Http\LetsEncrypt\AcmeSh::getAcmeSh(); if (file_exists($acmesh)) { - $certificate_folder = dirname($acmesh) . "/" . $domainname; + $certificate_folder = \Froxlor\Cron\Http\LetsEncrypt\AcmeSh::getWorkingDirFromEnv($domainname); if (\Froxlor\Settings::Get('system.leecc') > 0) { $certificate_folder .= "_ecc"; } From 67d74406bdf7348a9fb2c4e0b1b8907ef536cb15 Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Fri, 29 May 2020 13:36:31 +0200 Subject: [PATCH 052/319] add os distribution detection --- install/lib/class.FroxlorInstall.php | 70 +++++++++++++++++++++++++--- install/lng/english.lng.php | 9 ++++ install/lng/french.lng.php | 9 ++++ install/lng/german.lng.php | 9 ++++ install/templates/dataitemchk.tpl | 4 +- 5 files changed, 93 insertions(+), 8 deletions(-) diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index 33dc8434..27854ad3 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -159,6 +159,7 @@ class FroxlorInstall $this->_guessServerName(); $this->_guessServerIP(); $this->_guessWebserver(); + $this->_guessDistribution(); $this->_getPostField('mysql_host', '127.0.0.1'); $this->_getPostField('mysql_database', 'froxlor'); @@ -840,6 +841,20 @@ class FroxlorInstall */ $section = $this->_lng['install']['serversettings']; eval("\$formdata .= \"" . $this->_getTemplate("datasection") . "\";"); + // distribution + if (! empty($_POST['installstep']) && $this->_data['distribution'] == '') { + $diststyle = 'color:red;'; + } else { + $diststyle = ''; + } + $formdata .= $this->_GETsectionItemCheckbox('distribution', 'jessie', ($this->_data['distribution'] == 'jessie'), $diststyle); + $formdata .= $this->_getSectionItemCheckbox('distribution', 'stretch', ($this->_data['distribution'] == 'stretch'), $diststyle); + $formdata .= $this->_getSectionItemCheckbox('distribution', 'buster', ($this->_data['distribution'] == 'buster'), $diststyle); + $formdata .= $this->_getSectionItemCheckbox('distribution', 'xenial', ($this->_data['distribution'] == 'xenial'), $diststyle); + $formdata .= $this->_getSectionItemCheckbox('distribution', 'bionic', ($this->_data['distribution'] == 'bionic'), $diststyle); + $formdata .= $this->_getSectionItemCheckbox('distribution', 'focal', ($this->_data['distribution'] == 'focal'), $diststyle); + $formdata .= $this->_getSectionItemCheckbox('distribution', 'rhel7', ($this->_data['distribution'] == 'rhel7'), $diststyle); + $formdata .= $this->_getSectionItemCheckbox('distribution', 'rhel8', ($this->_data['distribution'] == 'rhel8'), $diststyle); // servername if (! empty($_POST['installstep']) && $this->_data['servername'] == '') { $style = 'color:red;'; @@ -861,12 +876,12 @@ class FroxlorInstall $websrvstyle = ''; } // apache - $formdata .= $this->_getSectionItemCheckbox('apache2', ($this->_data['webserver'] == 'apache2'), $websrvstyle); - $formdata .= $this->_getSectionItemCheckbox('apache24', ($this->_data['webserver'] == 'apache24'), $websrvstyle); + $formdata .= $this->_getSectionItemCheckbox('webserver', 'apache2', ($this->_data['webserver'] == 'apache2'), $websrvstyle); + $formdata .= $this->_getSectionItemCheckbox('webserver', 'apache24', ($this->_data['webserver'] == 'apache24'), $websrvstyle); // lighttpd - $formdata .= $this->_getSectionItemCheckbox('lighttpd', ($this->_data['webserver'] == 'lighttpd'), $websrvstyle); + $formdata .= $this->_getSectionItemCheckbox('webserver', 'lighttpd', ($this->_data['webserver'] == 'lighttpd'), $websrvstyle); // nginx - $formdata .= $this->_getSectionItemCheckbox('nginx', ($this->_data['webserver'] == 'nginx'), $websrvstyle); + $formdata .= $this->_getSectionItemCheckbox('webserver', 'NGINx', ($this->_data['webserver'] == 'nginx'), $websrvstyle); // webserver-user if (! empty($_POST['installstep']) && $this->_data['httpuser'] == '') { $style = 'color:red;'; @@ -918,7 +933,7 @@ class FroxlorInstall } /** - * generate form radio field for webserver-selection + * generate form radio field * * @param string $fieldname * @param boolean $checked @@ -926,8 +941,9 @@ class FroxlorInstall * * @return string */ - private function _getSectionItemCheckbox($fieldname = null, $checked = false, $style = "") + private function _getSectionItemCheckbox($groupname = null, $fieldname = null, $checked = false, $style = "") { + $groupname = $this->_lng['install'][$groupname]; $fieldlabel = $this->_lng['install'][$fieldname]; if ($checked) { $checked = 'checked="checked"'; @@ -1273,6 +1289,48 @@ class FroxlorInstall } } + + /** + * get/guess linux distribution + */ + private function _guessDistribution() + { + // post + if (! empty($_POST['distribution'])) { + $this->_data['distribution'] = $_POST['distribution']; + } else { + $os_version = parse_ini_file('/etc/os-release', false); + if ($os_version['ID'] == 'debian') { + + } elseif ($os_version['ID'] == 'debian') { + if(explode('.',$os_version['VERSION_ID'])[0] == '8') { + $this->_data['distribution'] = 'jessie'; + } elseif(explode('.',$os_version['VERSION_ID'])[0] == '9') { + $this->_data['distribution'] = 'stretch'; + } elseif(explode('.',$os_version['VERSION_ID'])[0] == '10') { + $this->_data['distribution'] = 'buster'; + } + } elseif ($os_version['ID'] == 'ubuntu') { + if(explode('.',$os_version['VERSION_ID'])[0] == '16') { + $this->_data['distribution'] = 'xenial'; + } elseif(explode('.',$os_version['VERSION_ID'])[0] == '18') { + $this->_data['distribution'] = 'bionic'; + } elseif(explode('.',$os_version['VERSION_ID'])[0] == '20') { + $this->_data['distribution'] = 'focal'; + } + } elseif($os_version['ID'] == 'rhel' || $os_version['ID'] == 'centos' || $os_version['ID'] == 'fedora') { + if(explode('.',$os_version['VERSION_ID'])[0] == '7') { + $this->_data['distribution'] = 'rhel7'; + } elseif(explode('.',$os_version['VERSION_ID'])[0] == '8') { + $this->_data['distribution'] = 'rhel8'; + } + } else { + // we don't need to bail out, since unknown does not affect any critical installation routines + $this->_data['distribution'] = 'unknown'; + } + } + } + /** * check if POST field is set and get value for the * internal data array, if not set use either '' or $default if != null diff --git a/install/lng/english.lng.php b/install/lng/english.lng.php index e5e6b9cb..0b04e3c1 100644 --- a/install/lng/english.lng.php +++ b/install/lng/english.lng.php @@ -63,6 +63,15 @@ $lng['install']['admin_pass1'] = 'Administrator Password'; $lng['install']['admin_pass2'] = 'Administrator-Password (confirm)'; $lng['install']['activate_newsfeed'] = 'Enable the official newsfeed
(https://inside.froxlor.org/news/)'; $lng['install']['serversettings'] = 'Server settings'; +$lng['install']['distribution'] = 'Distribution'; +$lng['install']['jessie'] = 'Debian Jessie'; +$lng['install']['stretch'] = 'Debian Stretch'; +$lng['install']['buster'] = 'Debian Buster'; +$lng['install']['xenial'] = 'Ubuntu Xenial'; +$lng['install']['bionic'] = 'Ubuntu Bionic'; +$lng['install']['focal'] = 'Ubuntu Focal'; +$lng['install']['rhel7'] = 'RHEL 7'; +$lng['install']['rhel8'] = 'RHEL 8'; $lng['install']['servername'] = 'Server name (FQDN, no ip-address)'; $lng['install']['serverip'] = 'Server IP'; $lng['install']['webserver'] = 'Webserver'; diff --git a/install/lng/french.lng.php b/install/lng/french.lng.php index 42ab1d7b..2eb6cb96 100644 --- a/install/lng/french.lng.php +++ b/install/lng/french.lng.php @@ -53,6 +53,15 @@ $lng['install']['admin_user'] = 'Nom d\'utilisateur administrateur'; $lng['install']['admin_pass1'] = 'Mot de passe administrateur'; $lng['install']['admin_pass2'] = 'Mot de passe administrateur (confirmez)'; $lng['install']['serversettings'] = 'Réglages serveur'; +$lng['install']['distribution'] = 'Distribution'; +$lng['install']['jessie'] = 'Debian Jessie'; +$lng['install']['stretch'] = 'Debian Stretch'; +$lng['install']['buster'] = 'Debian Buster'; +$lng['install']['xenial'] = 'Ubuntu Xenial'; +$lng['install']['bionic'] = 'Ubuntu Bionic'; +$lng['install']['focal'] = 'Ubuntu Focal'; +$lng['install']['rhel7'] = 'RHEL 7'; +$lng['install']['rhel8'] = 'RHEL 8'; $lng['install']['servername'] = 'Nom du serveur (FQDN, pas d\'adresse IP)'; $lng['install']['serverip'] = 'Adresse IP du serveur'; $lng['install']['webserver'] = 'Serveur Web'; diff --git a/install/lng/german.lng.php b/install/lng/german.lng.php index 64b462b4..24554712 100644 --- a/install/lng/german.lng.php +++ b/install/lng/german.lng.php @@ -63,6 +63,15 @@ $lng['install']['admin_pass1'] = 'Administrator-Passwort'; $lng['install']['admin_pass2'] = 'Administrator-Passwort (Bestätigung)'; $lng['install']['activate_newsfeed'] = 'Aktiviere das offizielle Newsfeed
(https://inside.froxlor.org/news/)'; $lng['install']['serversettings'] = 'Servereinstellungen'; +$lng['install']['distribution'] = 'Verteilung'; +$lng['install']['jessie'] = 'Debian Jessie'; +$lng['install']['stretch'] = 'Debian Stretch'; +$lng['install']['buster'] = 'Debian Buster'; +$lng['install']['xenial'] = 'Ubuntu Xenial'; +$lng['install']['bionic'] = 'Ubuntu Bionic'; +$lng['install']['focal'] = 'Ubuntu Focal'; +$lng['install']['rhel7'] = 'RHEL 7'; +$lng['install']['rhel8'] = 'RHEL 8'; $lng['install']['servername'] = 'Servername (FQDN, keine IP-Adresse)'; $lng['install']['serverip'] = 'Server-IP'; $lng['install']['webserver'] = 'Webserver'; diff --git a/install/templates/dataitemchk.tpl b/install/templates/dataitemchk.tpl index 30279bfa..46c90d1c 100644 --- a/install/templates/dataitemchk.tpl +++ b/install/templates/dataitemchk.tpl @@ -1,4 +1,4 @@

- - {$fieldlabel} + + {$fieldlabel}

From 0bb48a3cdff529a54ae3a1829bb36d1a990b4203 Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Fri, 29 May 2020 13:45:46 +0200 Subject: [PATCH 053/319] fix nginx capitalisation. --- install/lib/class.FroxlorInstall.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index 27854ad3..cf583d31 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -881,7 +881,7 @@ class FroxlorInstall // lighttpd $formdata .= $this->_getSectionItemCheckbox('webserver', 'lighttpd', ($this->_data['webserver'] == 'lighttpd'), $websrvstyle); // nginx - $formdata .= $this->_getSectionItemCheckbox('webserver', 'NGINx', ($this->_data['webserver'] == 'nginx'), $websrvstyle); + $formdata .= $this->_getSectionItemCheckbox('webserver', 'nginx', ($this->_data['webserver'] == 'nginx'), $websrvstyle); // webserver-user if (! empty($_POST['installstep']) && $this->_data['httpuser'] == '') { $style = 'color:red;'; From 022ed1a9a8c3ab2ba70c72a126948cc45c927deb Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Fri, 29 May 2020 14:59:40 +0200 Subject: [PATCH 054/319] add setting defaults per distribution when given --- install/lib/class.FroxlorInstall.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index cf583d31..f0ed0e53 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -505,6 +505,15 @@ class FroxlorInstall $this->_updateSetting($upd_stmt, 'error', 'system', 'errorlog_level'); } + if (file_exists(dirname(__DIR__).'/../lib/configfiles/'.$this->_data['distribution'].'.xml')) { + $xml = simplexml_load_file(dirname(__DIR__).'/../lib/configfiles/'.$this->_data['distribution'].'.xml'); + foreach($xml->distribution->defaults->propery as $property) { + $this->_updateSetting($upd_stmt, $property->value[0], $property->group[0], $property->name[0]); + } + } else { + exit('Failed to open distribution XML file.'); + } + $this->_updateSetting($upd_stmt, $this->_data['activate_newsfeed'], 'admin', 'show_news_feed'); $this->_updateSetting($upd_stmt, dirname(dirname(dirname(__FILE__))), 'system', 'letsencryptchallengepath'); From 498ff15e988aeebfd26160f254efd936e704e798 Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Fri, 29 May 2020 14:59:48 +0200 Subject: [PATCH 055/319] add redhat defaults --- lib/configfiles/rhel7.xml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/lib/configfiles/rhel7.xml b/lib/configfiles/rhel7.xml index 29c92104..c95388f1 100644 --- a/lib/configfiles/rhel7.xml +++ b/lib/configfiles/rhel7.xml @@ -2,6 +2,38 @@ + + + apacheconf_vhost + system + /etc/httpd/conf.d/ + + + apacheconf_diroptions + system + /etc/httpd/conf.d/ + + + apacheconf_htpasswddir + system + /etc/httpd/froxlor-htpasswd/ + + + apachereload_command + system + systemctl reload-or-restart httpd.service + + + bindreload_command + system + systemctl reload-or-restart named.service + + + crondreload + system + systemctl reload-or-restart crond.service + + From a572ac3914ce17090f1adc5a352c468d65dd3e2b Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Fri, 29 May 2020 15:10:06 +0200 Subject: [PATCH 056/319] add rhel8 config file --- lib/configfiles/rhel8.xml | 2480 +++++++++++++++++++++++++++++++++++++ 1 file changed, 2480 insertions(+) create mode 100644 lib/configfiles/rhel8.xml diff --git a/lib/configfiles/rhel8.xml b/lib/configfiles/rhel8.xml new file mode 100644 index 00000000..42fc34c0 --- /dev/null +++ b/lib/configfiles/rhel8.xml @@ -0,0 +1,2480 @@ + + + + + + apacheconf_vhost + system + /etc/httpd/conf.d/ + + + apacheconf_diroptions + system + /etc/httpd/conf.d/ + + + apacheconf_htpasswddir + system + /etc/httpd/froxlor-htpasswd/ + + + apachereload_command + system + systemctl reload-or-restart httpd.service + + + bindreload_command + system + systemctl reload-or-restart named.service + + + crondreload + system + systemctl reload-or-restart crond.service + + + + + + + + + + {{settings.system.apacheconf_vhost}} + + + + + {{settings.system.apacheconf_vhost}} + + + + + + + {{settings.system.apacheconf_diroptions}} + + + + + {{settings.system.apacheconf_diroptions}} + + + + + + + + + + + {{settings.system.deactivateddocroot}} + + + + + + + + //service[@type='http']/general/commands + + {{settings.system.leenabled}} + + + Require all granted + +]]> + + + + + + + + + + + + > /etc/named.conf]]> + > /etc/named.conf.local]]> + + + + + + + + + + + + + {{settings.system.vmail_gid}} + + + + + {{settings.system.vmail_uid}} + + + + + + + + + + + + + + + + + +password = +dbname = +hosts = +query = SELECT destination FROM mail_virtual AS v, panel_customers AS c WHERE c.customerid = v.customerid AND c.deactivated = 0 AND v.email = '%s' AND trim(v.destination) <> '' +]]> + + + + +password = +dbname = +hosts = +query = SELECT domain FROM panel_domains WHERE domain = '%s' AND isemaildomain = '1' +]]> + + + + +password = +dbname = +expansion_limit = 1 +hosts = +query = SELECT CONCAT(homedir,maildir) FROM mail_users WHERE email = '%s' +]]> + + + + +password = +dbname = +hosts = +query = SELECT DISTINCT username FROM mail_users WHERE email in ((SELECT mail_virtual.email_full FROM mail_virtual WHERE mail_virtual.email = '%s' UNION SELECT mail_virtual.destination FROM mail_virtual WHERE mail_virtual.email = '%s')); +]]> + + + + +password = +dbname = +expansion_limit = 1 +hosts = +query = SELECT uid FROM mail_users WHERE email = '%s' +]]> + + + + +password = +dbname = +expansion_limit = 1 +hosts = +query = SELECT gid FROM mail_users WHERE email = '%s' +]]> + + + + + + + + + + + + //service[@type='smtp']/general/commands[@index=1] + + //service[@type='smtp']/general/installs[@index=1] + + //service[@type='smtp']/general/commands[@index=2] + + + + +# set myhostname to $mydomain because Froxlor alrady uses a FQDN +myhostname = $mydomain + +mydestination = $myhostname, + $mydomain, + localhost.$myhostname, + localhost.$mydomain, + localhost +mynetworks = 127.0.0.0/8 +inet_interfaces = all +append_dot_mydomain = no +biff = no + +# Postfix performance settings +default_destination_concurrency_limit = 20 +local_destination_concurrency_limit = 2 + +# SMTPD Settings +smtpd_banner = $myhostname ESMTP $mail_name +smtpd_helo_required = yes +smtpd_recipient_restrictions = permit_mynetworks, + permit_sasl_authenticated, + reject_unauth_destination, + reject_unauth_pipelining, + reject_non_fqdn_recipient +smtpd_sender_restrictions = permit_mynetworks, + reject_sender_login_mismatch, + permit_sasl_authenticated, + reject_unknown_helo_hostname, + reject_unknown_recipient_domain, + reject_unknown_sender_domain +smtpd_client_restrictions = permit_mynetworks, + permit_sasl_authenticated, + reject_unknown_client_hostname + +# Postfix 2.10 requires this option. Postfix < 2.10 ignores this. +# The option is intentionally left empty. +smtpd_relay_restrictions = + +# Maximum size of Message in bytes (50MB) +message_size_limit = 52428800 +mailbox_size_limit = 0 + +## SASL Auth Settings +smtpd_sasl_auth_enable = yes +smtpd_sasl_local_domain = $myhostname +broken_sasl_auth_clients = yes +## Dovecot Settings for deliver, SASL Auth and virtual transport +smtpd_sasl_type = dovecot +mailbox_command = /usr/lib/dovecot/deliver +virtual_transport = dovecot +dovecot_destination_recipient_limit = 1 +smtpd_sasl_path = private/auth + +# Virtual delivery settings +virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual_mailbox_maps.cf +virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual_mailbox_domains.cf +virtual_alias_maps = mysql:/etc/postfix/mysql-virtual_alias_maps.cf +smtpd_sender_login_maps = mysql:/etc/postfix/mysql-virtual_sender_permissions.cf + +# Local delivery settings +local_transport = local +alias_maps = $alias_database + +### TLS settings +### +## TLS for outgoing mails from the server to another server +#smtp_tls_security_level = may +#smtp_tls_note_starttls_offer = yes +## TLS for incoming connections (clients or other mail servers) +#smtpd_tls_security_level = may +#smtpd_tls_cert_file = /etc/ssl/server/.pem +#smtpd_tls_CAfile = /etc/ssl/certs/ca-certificates.crt +#smtpd_tls_loglevel = 1 +#smtpd_tls_received_header = yes + +debugger_command = + PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin + ddd $daemon_directory/$process_name $process_id & sleep 5 +]]> + + + //service[@type='smtp']/general/files[@index=0] + + + + + //service[@type='smtp']/general/commands[@index=3] + + + + + + + + + + +#protocols = imap pop3 lmtp +#protocols = imap pop3 lmtp sieve + +# A comma separated list of IPs or hosts where to listen in for connections. +# "*" listens in all IPv4 interfaces, "::" listens in all IPv6 interfaces. +# If you want to specify non-default ports or anything more complex, +# edit conf.d/master.conf. +listen = *, :: + +# Base directory where to store runtime data. +base_dir = /var/run/dovecot/ + +# Greeting message for clients. +login_greeting = Dovecot ready. + +# Space separated list of trusted network ranges. Connections from these +# IPs are allowed to override their IP addresses and ports (for logging and +# for authentication checks). disable_plaintext_auth is also ignored for +# these networks. Typically you'd specify your IMAP proxy servers here. +#login_trusted_networks = + +# Sepace separated list of login access check sockets (e.g. tcpwrap) +#login_access_sockets = + +# Show more verbose process titles (in ps). Currently shows user name and +# IP address. Useful for seeing who are actually using the IMAP processes +# (eg. shared mailboxes or if same uid is used for multiple accounts). +#verbose_proctitle = no + +# Should all processes be killed when Dovecot master process shuts down. +# Setting this to "no" means that Dovecot can be upgraded without +# forcing existing client connections to close (although that could also be +# a problem if the upgrade is e.g. because of a security fix). +shutdown_clients = yes + +# If non-zero, run mail commands via this many connections to doveadm server, +# instead of running them directly in the same process. +#doveadm_worker_count = 0 +# UNIX socket or host:port used for connecting to doveadm server +#doveadm_socket_path = doveadm-server + +## +## Dictionary server settings +## + +# Dictionary can be used to store key=value lists. This is used by several +# plugins. The dictionary can be accessed either directly or though a +# dictionary server. The following dict block maps dictionary names to URIs +# when the server is used. These can then be referenced using URIs in format +# "proxy::". + +dict { + #quota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext + #expire = sqlite:/etc/dovecot/dovecot-dict-sql.conf.ext +} + +# Most of the actual configuration gets included below. The filenames are +# first sorted by their ASCII value and parsed in that order. The 00-prefixes +# in filenames are intended to make it easier to understand the ordering. +!include conf.d/*.conf + +# A config file can also tried to be included without giving an error if +# it's not found: +#!include_try /etc/dovecot/local.conf +]]> + + + + to characters. For example "#@/@" means +# that '#' and '/' characters are translated to '@'. +#auth_username_translation = + +# Username formatting before it's looked up from databases. You can use +# the standard variables here, eg. %Lu would lowercase the username, %n would +# drop away the domain if it was given, or "%n-AT-%d" would change the '@' into +# "-AT-". This translation is done after auth_username_translation changes. +#auth_username_format = %Lu + +# If you want to allow master users to log in by specifying the master +# username within the normal username string (ie. not using SASL mechanism's +# support for it), you can specify the separator character here. The format +# is then . UW-IMAP uses "*" as the +# separator, so that could be a good choice. +#auth_master_user_separator = + +# Username to use for users logging in with ANONYMOUS SASL mechanism +#auth_anonymous_username = anonymous + +# Maximum number of dovecot-auth worker processes. They're used to execute +# blocking passdb and userdb queries (eg. MySQL and PAM). They're +# automatically created and destroyed as needed. +#auth_worker_max_count = 30 + +# Host name to use in GSSAPI principal names. The default is to use the +# name returned by gethostname(). Use "$ALL" (with quotes) to allow all keytab +# entries. +#auth_gssapi_hostname = + +# Kerberos keytab to use for the GSSAPI mechanism. Will use the system +# default (usually /etc/krb5.keytab) if not specified. You may need to change +# the auth service to run as root to be able to read this file. +#auth_krb5_keytab = + +# Do NTLM and GSS-SPNEGO authentication using Samba's winbind daemon and +# ntlm_auth helper. +#auth_use_winbind = no + +# Path for Samba's ntlm_auth helper binary. +#auth_winbind_helper_path = /usr/bin/ntlm_auth + +# Time to delay before replying to failed authentications. +#auth_failure_delay = 2 secs + +# Require a valid SSL client certificate or the authentication fails. +#auth_ssl_require_client_cert = no + +# Take the username from client's SSL certificate, using +# X509_NAME_get_text_by_NID() which returns the subject's DN's +# CommonName. +#auth_ssl_username_from_cert = no + +# Space separated list of wanted authentication mechanisms: +# plain login digest-md5 cram-md5 ntlm rpa apop anonymous gssapi otp skey +# gss-spnego +# NOTE: See also disable_plaintext_auth setting. +auth_mechanisms = plain + +## +## Password and user databases +## + +# +# Password database is used to verify user's password (and nothing more). +# You can have multiple passdbs and userdbs. This is useful if you want to +# allow both system users (/etc/passwd) and virtual users to login without +# duplicating the system users into virtual database. +# +# +# +# User database specifies where mails are located and what user/group IDs +# own them. For single-UID configuration use "static" userdb. +# +# + +#!include auth-deny.conf.ext +#!include auth-master.conf.ext + +#!include auth-system.conf.ext +!include auth-sql.conf.ext +#!include auth-ldap.conf.ext +#!include auth-passwdfile.conf.ext +#!include auth-checkpassword.conf.ext +#!include auth-vpopmail.conf.ext +#!include auth-static.conf.ext +]]> + + + + method=%m rip=%r lip=%l mpid=%e %c + +# Login log format. %s contains login_log_format_elements string, %$ contains +# the data we want to log. +#login_log_format = %$: %s + +# Log prefix for mail processes. See doc/wiki/Variables.txt for list of +# possible variables you can use. +#mail_log_prefix = "%s(%u): " + +# Format to use for logging mail deliveries. You can use variables: +# %$ - Delivery status message (e.g. "saved to INBOX") +# %m - Message-ID +# %s - Subject +# %f - From address +# %p - Physical size +# %w - Virtual size +#deliver_log_format = msgid=%m: %$ +]]> + + + + +# +mail_location = maildir:/var/vmail/%d/%u +# ########################## TODO + +# If you need to set multiple mailbox locations or want to change default +# namespace settings, you can do it by defining namespace sections. +# +# You can have private, shared and public namespaces. Private namespaces +# are for user's personal mails. Shared namespaces are for accessing other +# users' mailboxes that have been shared. Public namespaces are for shared +# mailboxes that are managed by sysadmin. If you create any shared or public +# namespaces you'll typically want to enable ACL plugin also, otherwise all +# users can access all the shared mailboxes, assuming they have permissions +# on filesystem level to do so. +namespace inbox { + # Namespace type: private, shared or public + #type = private + + # Hierarchy separator to use. You should use the same separator for all + # namespaces or some clients get confused. '/' is usually a good one. + # The default however depends on the underlying mail storage format. + #separator = + + # Prefix required to access this namespace. This needs to be different for + # all namespaces. For example "Public/". + #prefix = + + # Physical location of the mailbox. This is in same format as + # mail_location, which is also the default for it. + #location = + + # There can be only one INBOX, and this setting defines which namespace + # has it. + inbox = yes + + # If namespace is hidden, it's not advertised to clients via NAMESPACE + # extension. You'll most likely also want to set list=no. This is mostly + # useful when converting from another server with different namespaces which + # you want to deprecate but still keep working. For example you can create + # hidden namespaces with prefixes "~/mail/", "~%u/mail/" and "mail/". + #hidden = no + + # Show the mailboxes under this namespace with LIST command. This makes the + # namespace visible for clients that don't support NAMESPACE extension. + # "children" value lists child mailboxes, but hides the namespace prefix. + #list = yes + + # Namespace handles its own subscriptions. If set to "no", the parent + # namespace handles them (empty prefix should always have this as "yes") + #subscriptions = yes +} + +# Example shared namespace configuration +#namespace { + #type = shared + #separator = / + + # Mailboxes are visible under "shared/user@domain/" + # %%n, %%d and %%u are expanded to the destination user. + #prefix = shared/%%u/ + + # Mail location for other users' mailboxes. Note that %variables and ~/ + # expands to the logged in user's data. %%n, %%d, %%u and %%h expand to the + # destination user's data. + #location = maildir:%%h/Maildir:INDEX=~/Maildir/shared/%%u + + # Use the default namespace for saving subscriptions. + #subscriptions = no + + # List the shared/ namespace only if there are visible shared mailboxes. + #list = children +#} +# Should shared INBOX be visible as "shared/user" or "shared/user/INBOX"? +#mail_shared_explicit_inbox = no + +# System user and group used to access mails. If you use multiple, userdb +# can override these by returning uid or gid fields. You can use either numbers +# or names. +#mail_uid = +#mail_gid = + +# Group to enable temporarily for privileged operations. Currently this is +# used only with INBOX when either its initial creation or dotlocking fails. +# Typically this is set to "mail" to give access to /var/mail. +#mail_privileged_group = + +# Grant access to these supplementary groups for mail processes. Typically +# these are used to set up access to shared mailboxes. Note that it may be +# dangerous to set these if users can create symlinks (e.g. if "mail" group is +# set here, ln -s /var/mail ~/mail/var could allow a user to delete others' +# mailboxes, or ln -s /secret/shared/box ~/mail/mybox would allow reading it). +#mail_access_groups = vmail + +# Allow full filesystem access to clients. There's no access checks other than +# what the operating system does for the active UID/GID. It works with both +# maildir and mboxes, allowing you to prefix mailboxes names with eg. /path/ +# or ~user/. +#mail_full_filesystem_access = no + +# Dictionary for key=value mailbox attributes. Currently used by URLAUTH, but +# soon intended to be used by METADATA as well. +#mail_attribute_dict = + +## +## Mail processes +## + +# Don't use mmap() at all. This is required if you store indexes to shared +# filesystems (NFS or clustered filesystem). +#mmap_disable = no + +# Rely on O_EXCL to work when creating dotlock files. NFS supports O_EXCL +# since version 3, so this should be safe to use nowadays by default. +#dotlock_use_excl = yes + +# When to use fsync() or fdatasync() calls: +# optimized (default): Whenever necessary to avoid losing important data +# always: Useful with e.g. NFS when write()s are delayed +# never: Never use it (best performance, but crashes can lose data) +#mail_fsync = optimized + +# Mail storage exists in NFS. Set this to yes to make Dovecot flush NFS caches +# whenever needed. If you're using only a single mail server this isn't needed. +#mail_nfs_storage = no +# Mail index files also exist in NFS. Setting this to yes requires +# mmap_disable=yes and fsync_disable=no. +#mail_nfs_index = no + +# Locking method for index files. Alternatives are fcntl, flock and dotlock. +# Dotlocking uses some tricks which may create more disk I/O than other locking +# methods. NFS users: flock doesn't work, remember to change mmap_disable. +#lock_method = fcntl + +# Directory in which LDA/LMTP temporarily stores incoming mails >128 kB. +#mail_temp_dir = /tmp + +# Valid UID range for users, defaults to 500 and above. This is mostly +# to make sure that users can't log in as daemons or other system users. +# Note that denying root logins is hardcoded to dovecot binary and can't +# be done even if first_valid_uid is set to 0. +first_valid_uid = 150 +last_valid_uid = 150 + +# Valid GID range for users, defaults to non-root/wheel. Users having +# non-valid GID as primary group ID aren't allowed to log in. If user +# belongs to supplementary groups with non-valid GIDs, those groups are +# not set. +first_valid_gid = 12 +last_valid_gid = 12 + +# Maximum allowed length for mail keyword name. It's only forced when trying +# to create new keywords. +#mail_max_keyword_length = 50 + +# ':' separated list of directories under which chrooting is allowed for mail +# processes (ie. /var/mail will allow chrooting to /var/mail/foo/bar too). +# This setting doesn't affect login_chroot, mail_chroot or auth chroot +# settings. If this setting is empty, "/./" in home dirs are ignored. +# WARNING: Never add directories here which local users can modify, that +# may lead to root exploit. Usually this should be done only if you don't +# allow shell access for users. +#valid_chroot_dirs = + +# Default chroot directory for mail processes. This can be overridden for +# specific users in user database by giving /./ in user's home directory +# (eg. /home/./user chroots into /home). Note that usually there is no real +# need to do chrooting, Dovecot doesn't allow users to access files outside +# their mail directory anyway. If your home directories are prefixed with +# the chroot directory, append "/." to mail_chroot. +#mail_chroot = + +# UNIX socket path to master authentication server to find users. +# This is used by imap (for shared users) and lda. +#auth_socket_path = /var/run/dovecot/auth-userdb + +# Directory where to look up mail plugins. +#mail_plugin_dir = /usr/lib/dovecot + +# Space separated list of plugins to load for all services. Plugins specific to +# IMAP, LDA, etc. are added to this list in their own .conf files. +#mail_plugins = + +## +## Mailbox handling optimizations +## + +# Mailbox list indexes can be used to optimize IMAP STATUS commands. They are +# also required for IMAP NOTIFY extension to be enabled. +#mailbox_list_index = no + +# The minimum number of mails in a mailbox before updates are done to cache +# file. This allows optimizing Dovecot's behavior to do less disk writes at +# the cost of more disk reads. +#mail_cache_min_mail_count = 0 + +# When IDLE command is running, mailbox is checked once in a while to see if +# there are any new mails or other changes. This setting defines the minimum +# time to wait between those checks. Dovecot can also use dnotify, inotify and +# kqueue to find out immediately when changes occur. +#mailbox_idle_check_interval = 30 secs + +# Save mails with CR+LF instead of plain LF. This makes sending those mails +# take less CPU, especially with sendfile() syscall with Linux and FreeBSD. +# But it also creates a bit more disk I/O which may just make it slower. +# Also note that if other software reads the mboxes/maildirs, they may handle +# the extra CRs wrong and cause problems. +#mail_save_crlf = no + +# Max number of mails to keep open and prefetch to memory. This only works with +# some mailbox formats and/or operating systems. +#mail_prefetch_count = 0 + +# How often to scan for stale temporary files and delete them (0 = never). +# These should exist only after Dovecot dies in the middle of saving mails. +#mail_temp_scan_interval = 1w + +## +## Maildir-specific settings +## + +# By default LIST command returns all entries in maildir beginning with a dot. +# Enabling this option makes Dovecot return only entries which are directories. +# This is done by stat()ing each entry, so it causes more disk I/O. +# (For systems setting struct dirent->d_type, this check is free and it's +# done always regardless of this setting) +#maildir_stat_dirs = no + +# When copying a message, do it with hard links whenever possible. This makes +# the performance much better, and it's unlikely to have any side effects. +#maildir_copy_with_hardlinks = yes + +# Assume Dovecot is the only MUA accessing Maildir: Scan cur/ directory only +# when its mtime changes unexpectedly or when we can't find the mail otherwise. +#maildir_very_dirty_syncs = no + +# If enabled, Dovecot doesn't use the S= in the Maildir filenames for +# getting the mail's physical size, except when recalculating Maildir++ quota. +# This can be useful in systems where a lot of the Maildir filenames have a +# broken size. The performance hit for enabling this is very small. +#maildir_broken_filename_sizes = no + +## +## mbox-specific settings +## + +# Which locking methods to use for locking mbox. There are four available: +# dotlock: Create .lock file. This is the oldest and most NFS-safe +# solution. If you want to use /var/mail/ like directory, the users +# will need write access to that directory. +# dotlock_try: Same as dotlock, but if it fails because of permissions or +# because there isn't enough disk space, just skip it. +# fcntl : Use this if possible. Works with NFS too if lockd is used. +# flock : May not exist in all systems. Doesn't work with NFS. +# lockf : May not exist in all systems. Doesn't work with NFS. +# +# You can use multiple locking methods; if you do the order they're declared +# in is important to avoid deadlocks if other MTAs/MUAs are using multiple +# locking methods as well. Some operating systems don't allow using some of +# them simultaneously. +#mbox_read_locks = fcntl +#mbox_write_locks = dotlock fcntl +mbox_write_locks = fcntl + +# Maximum time to wait for lock (all of them) before aborting. +#mbox_lock_timeout = 5 mins + +# If dotlock exists but the mailbox isn't modified in any way, override the +# lock file after this much time. +#mbox_dotlock_change_timeout = 2 mins + +# When mbox changes unexpectedly we have to fully read it to find out what +# changed. If the mbox is large this can take a long time. Since the change +# is usually just a newly appended mail, it'd be faster to simply read the +# new mails. If this setting is enabled, Dovecot does this but still safely +# fallbacks to re-reading the whole mbox file whenever something in mbox isn't +# how it's expected to be. The only real downside to this setting is that if +# some other MUA changes message flags, Dovecot doesn't notice it immediately. +# Note that a full sync is done with SELECT, EXAMINE, EXPUNGE and CHECK +# commands. +#mbox_dirty_syncs = yes + +# Like mbox_dirty_syncs, but don't do full syncs even with SELECT, EXAMINE, +# EXPUNGE or CHECK commands. If this is set, mbox_dirty_syncs is ignored. +#mbox_very_dirty_syncs = no + +# Delay writing mbox headers until doing a full write sync (EXPUNGE and CHECK +# commands and when closing the mailbox). This is especially useful for POP3 +# where clients often delete all mails. The downside is that our changes +# aren't immediately visible to other MUAs. +#mbox_lazy_writes = yes + +# If mbox size is smaller than this (e.g. 100k), don't write index files. +# If an index file already exists it's still read, just not updated. +#mbox_min_index_size = 0 + +# Mail header selection algorithm to use for MD5 POP3 UIDLs when +# pop3_uidl_format=%m. For backwards compatibility we use apop3d inspired +# algorithm, but it fails if the first Received: header isn't unique in all +# mails. An alternative algorithm is "all" that selects all headers. +#mbox_md5 = apop3d + +## +## mdbox-specific settings +## + +# Maximum dbox file size until it's rotated. +#mdbox_rotate_size = 2M + +# Maximum dbox file age until it's rotated. Typically in days. Day begins +# from midnight, so 1d = today, 2d = yesterday, etc. 0 = check disabled. +#mdbox_rotate_interval = 0 + +# When creating new mdbox files, immediately preallocate their size to +# mdbox_rotate_size. This setting currently works only in Linux with some +# filesystems (ext4, xfs). +#mdbox_preallocate_space = no + +## +## Mail attachments +## + +# sdbox and mdbox support saving mail attachments to external files, which +# also allows single instance storage for them. Other backends don't support +# this for now. + +# Directory root where to store mail attachments. Disabled, if empty. +#mail_attachment_dir = + +# Attachments smaller than this aren't saved externally. It's also possible to +# write a plugin to disable saving specific attachments externally. +#mail_attachment_min_size = 128k + +# Filesystem backend to use for saving attachments: +# posix : No SiS done by Dovecot (but this might help FS's own deduplication) +# sis posix : SiS with immediate byte-by-byte comparison during saving +# sis-queue posix : SiS with delayed comparison and deduplication +#mail_attachment_fs = sis posix + +# Hash format to use in attachment filenames. You can add any text and +# variables: %{md4}, %{md5}, %{sha1}, %{sha256}, %{sha512}, %{size}. +# Variables can be truncated, e.g. %{sha256:80} returns only first 80 bits +#mail_attachment_hash = %{sha1} +]]> + + + + + #service_count = 1 + + # Number of processes to always keep waiting for more connections. + #process_min_avail = 0 + + # If you set service_count=0, you probably need to grow this. + #vsz_limit = $default_vsz_limit +} + +service pop3-login { + inet_listener pop3 { + #port = 110 + } + inet_listener pop3s { + #port = 995 + #ssl = yes + } +} + +service lmtp { + unix_listener lmtp { + #mode = 0666 + } + + # Create inet listener only if you can't use the above UNIX socket + #inet_listener lmtp { + # Avoid making LMTP visible for the entire internet + #address = + #port = + #} +} + +service imap { + # Most of the memory goes to mmap()ing files. You may need to increase this + # limit if you have huge mailboxes. + #vsz_limit = $default_vsz_limit + + # Max. number of IMAP processes (connections) + #process_limit = 1024 +} + +service pop3 { + # Max. number of POP3 processes (connections) + #process_limit = 1024 +} + +service auth { + # auth_socket_path points to this userdb socket by default. It's typically + # used by dovecot-lda, doveadm, possibly imap process, etc. Users that have + # full permissions to this socket are able to get a list of all usernames and + # get the results of everyone's userdb lookups. + # + # The default 0666 mode allows anyone to connect to the socket, but the + # userdb lookups will succeed only if the userdb returns an "uid" field that + # matches the caller process's UID. Also if caller's uid or gid matches the + # socket's uid or gid the lookup succeeds. Anything else causes a failure. + # + # To give the caller full permissions to lookup all users, set the mode to + # something else than 0666 and Dovecot lets the kernel enforce the + # permissions (e.g. 0777 allows everyone full permissions). + unix_listener auth-userdb { + #mode = 0666 + #user = + #group = + } + + # Postfix smtp-auth + unix_listener /var/spool/postfix/private/auth { + mode = 0666 + } + + # Auth process is run as this user. + #user = $default_internal_user +} + +service auth-worker { + # Auth worker process is run as root by default, so that it can access + # /etc/shadow. If this isn't necessary, the user should be changed to + # $default_internal_user. + #user = root +} + +service dict { + # If dict proxy is used, mail processes should have access to its socket. + # For example: mode=0660, group=vmail and global mail_access_groups=vmail + unix_listener dict { + #mode = 0600 + #user = + #group = + } +} +]]> + + + + +# disable plain pop3 and imap, allowed are only pop3+TLS, pop3s, imap+TLS and imaps +# plain imap and pop3 are still allowed for local connections +ssl = no + +# PEM encoded X.509 SSL/TLS certificate and private key. They're opened before +# dropping root privileges, so keep the key file unreadable by anyone but +# root. Included doc/mkcert.sh can be used to easily generate self-signed +# certificate, just make sure to update the domains in dovecot-openssl.cnf +#ssl_cert = + + + + . %d expands to recipient domain. +postmaster_address = postmaster@ + +# Hostname to use in various parts of sent mails (e.g. in Message-Id) and +# in LMTP replies. Default is the system's real hostname@domain. +#hostname = + +# If user is over quota, return with temporary failure instead of +# bouncing the mail. +#quota_full_tempfail = no + +# Binary to use for sending mails. +#sendmail_path = /usr/sbin/sendmail + +# If non-empty, send mails via this SMTP host[:port] instead of sendmail. +#submission_host = + +# Subject: header to use for rejection mails. You can use the same variables +# as for rejection_reason below. +#rejection_subject = Rejected: %s + +# Human readable error message for rejection mails. You can use variables: +# %n = CRLF, %r = reason, %s = original subject, %t = recipient +#rejection_reason = Your message to <%t> was automatically rejected:%n%r + +# Delimiter character between local-part and detail in email address. +#recipient_delimiter = + + +# Header where the original recipient address (SMTP's RCPT TO: address) is taken +# from if not available elsewhere. With dovecot-lda -a parameter overrides this. +# A commonly used header for this is X-Original-To. +#lda_original_recipient_header = + +# Should saving a mail to a nonexistent mailbox automatically create it? +#lda_mailbox_autocreate = no + +# Should automatically created mailboxes be also automatically subscribed? +#lda_mailbox_autosubscribe = no + +protocol lda { + # Space separated list of plugins to load (default is global mail_plugins). + mail_plugins = $mail_plugins quota sieve +} +]]> + + + + + + + + + + + + + + + + + #service_count = 1 + + # Number of processes to always keep waiting for more connections. + #process_min_avail = 0 + + # If you set service_count=0, you probably need to grow this. + #vsz_limit = 64M +#} + +#service managesieve { + # Max. number of ManageSieve processes (connections) + #process_limit = 1024 +#} + +# Service configuration + +protocol sieve { + # Maximum ManageSieve command line length in bytes. ManageSieve usually does + # not involve overly long command lines, so this setting will not normally + # need adjustment + #managesieve_max_line_length = 65536 + + # Maximum number of ManageSieve connections allowed for a user from each IP + # address. + # NOTE: The username is compared case-sensitively. + #mail_max_userip_connections = 10 + + # Space separated list of plugins to load (none known to be useful so far). + # Do NOT try to load IMAP plugins here. + #mail_plugins = + + # MANAGESIEVE logout format string: + # %i - total number of bytes read from client + # %o - total number of bytes sent to client + #managesieve_logout_format = bytes=%i/%o + + # To fool ManageSieve clients that are focused on CMU's timesieved you can + # specify the IMPLEMENTATION capability that Dovecot reports to clients. + # For example: 'Cyrus timsieved v2.2.13' + #managesieve_implementation_string = Dovecot Pigeonhole + + # Explicitly specify the SIEVE and NOTIFY capability reported by the server + # before login. If left unassigned these will be reported dynamically + # according to what the Sieve interpreter supports by default (after login + # this may differ depending on the user). + #managesieve_sieve_capability = + #managesieve_notify_capability = + + # The maximum number of compile errors that are returned to the client upon + # script upload or script verification. + #managesieve_max_compile_errors = 5 + + # Refer to 90-sieve.conf for script quota configuration and configuration of + # Sieve execution limits. +} +]]> + + + + = 2.1.4) : %v.%u +# Dovecot v0.99.x : %v.%u +# tpop3d : %Mf +# +# Note that Outlook 2003 seems to have problems with %v.%u format which was +# Dovecot's default, so if you're building a new server it would be a good +# idea to change this. %08Xu%08Xv should be pretty fail-safe. +# +#pop3_uidl_format = %08Xu%08Xv + +# Permanently save UIDLs sent to POP3 clients, so pop3_uidl_format changes +# won't change those UIDLs. Currently this works only with Maildir. +#pop3_save_uidl = no + +# What to do about duplicate UIDLs if they exist? +# allow: Show duplicates to clients. +# rename: Append a temporary -2, -3, etc. counter after the UIDL. +#pop3_uidl_duplicates = allow + +# This option changes POP3 behavior so that it's not possible to actually +# delete mails via POP3, only hide them from future POP3 sessions. The mails +# will still be counted towards user's quota until actually deleted via IMAP. +# Use e.g. "$POP3Deleted" as the value (it will be visible as IMAP keyword). +# Make sure you can legally archive mails before enabling this setting. +#pop3_deleted_flag = + +# POP3 logout format string: +# %i - total number of bytes read from client +# %o - total number of bytes sent to client +# %t - number of TOP commands +# %p - number of bytes sent to client as a result of TOP command +# %r - number of RETR commands +# %b - number of bytes sent to client as a result of RETR command +# %d - number of deleted messages +# %m - number of messages (before deletion) +# %s - mailbox size in bytes (before deletion) +# %u - old/new UIDL hash. may help finding out if UIDLs changed unexpectedly +pop3_logout_format = in=%i out=%o top=%t/%p, retr=%r/%b, del=%d/%m, size=%s + +# Workarounds for various client bugs: +# outlook-no-nuls: +# Outlook and Outlook Express hang if mails contain NUL characters. +# This setting replaces them with 0x80 character. +# oe-ns-eoh: +# Outlook Express and Netscape Mail breaks if end of headers-line is +# missing. This option simply sends it if it's missing. +# The list is space-separated. +#pop3_client_workarounds = + +protocol pop3 { + # Space separated list of plugins to load (default is global mail_plugins). + mail_plugins = $mail_plugins quota + + # Maximum number of POP3 connections allowed for a user from each IP address. + # NOTE: The username is compared case-sensitively. + #mail_max_userip_connections = 10 +} +]]> + + + + See sieve_before fore executing scripts before the user's personal + # script. + #sieve_default = /var/lib/dovecot/sieve/default.sieve + sieve_global_path = /var/lib/dovecot/sieve/default.sieve + + # Directory for :personal include scripts for the include extension. This + # is also where the ManageSieve service stores the user's scripts. + #sieve_dir = ~/sieve + sieve_dir = /var/sieve-userscripts/%u + + # Directory for :global include scripts for the include extension. + #sieve_global_dir = + sieve_global_dir = /var/lib/dovecot/sieve/global + + # Path to a script file or a directory containing script files that need to be + # executed before the user's script. If the path points to a directory, all + # the Sieve scripts contained therein (with the proper .sieve extension) are + # executed. The order of execution within a directory is determined by the + # file names, using a normal 8bit per-character comparison. Multiple script + # file or directory paths can be specified by appending an increasing number. + #sieve_before = + #sieve_before2 = + #sieve_before3 = (etc...) + sieve_before = /var/lib/dovecot/sieve/before/ + + # Identical to sieve_before, only the specified scripts are executed after the + # user's script (only when keep is still in effect!). Multiple script file or + # directory paths can be specified by appending an increasing number. + #sieve_after = + #sieve_after2 = + #sieve_after2 = (etc...) + + # Which Sieve language extensions are available to users. By default, all + # supported extensions are available, except for deprecated extensions or + # those that are still under development. Some system administrators may want + # to disable certain Sieve extensions or enable those that are not available + # by default. This setting can use '+' and '-' to specify differences relative + # to the default. For example `sieve_extensions = +imapflags' will enable the + # deprecated imapflags extension in addition to all extensions were already + # enabled by default. + #sieve_extensions = +notify +imapflags + sieve_extensions = +spamtest +spamtestplus +relational +comparator-i;ascii-numeric +notify +imapflags + + # Which Sieve language extensions are ONLY available in global scripts. This + # can be used to restrict the use of certain Sieve extensions to administrator + # control, for instance when these extensions can cause security concerns. + # This setting has higher precedence than the `sieve_extensions' setting + # (above), meaning that the extensions enabled with this setting are never + # available to the user's personal script no matter what is specified for the + # `sieve_extensions' setting. The syntax of this setting is similar to the + # `sieve_extensions' setting, with the difference that extensions are + # enabled or disabled for exclusive use in global scripts. Currently, no + # extensions are marked as such by default. + #sieve_global_extensions = + + # The Pigeonhole Sieve interpreter can have plugins of its own. Using this + # setting, the used plugins can be specified. Check the Dovecot wiki + # (wiki2.dovecot.org) or the pigeonhole website + # (http://pigeonhole.dovecot.org) for available plugins. + # The sieve_extprograms plugin is included in this release. + #sieve_plugins = + + # The separator that is expected between the :user and :detail + # address parts introduced by the subaddress extension. This may + # also be a sequence of characters (e.g. '--'). The current + # implementation looks for the separator from the left of the + # localpart and uses the first one encountered. The :user part is + # left of the separator and the :detail part is right. This setting + # is also used by Dovecot's LMTP service. + #recipient_delimiter = + + + # The maximum size of a Sieve script. The compiler will refuse to compile any + # script larger than this limit. If set to 0, no limit on the script size is + # enforced. + #sieve_max_script_size = 1M + + # The maximum number of actions that can be performed during a single script + # execution. If set to 0, no limit on the total number of actions is enforced. + #sieve_max_actions = 32 + + # The maximum number of redirect actions that can be performed during a single + # script execution. If set to 0, no redirect actions are allowed. + #sieve_max_redirects = 4 + + # The maximum number of personal Sieve scripts a single user can have. If set + # to 0, no limit on the number of scripts is enforced. + # (Currently only relevant for ManageSieve) + #sieve_quota_max_scripts = 0 + + # The maximum amount of disk storage a single user's scripts may occupy. If + # set to 0, no limit on the used amount of disk storage is enforced. + # (Currently only relevant for ManageSieve) + #sieve_quota_max_storage = 0 +} +]]> + + + + dbname= user= password= + +# Default password scheme. +# +# List of supported schemes is in +# http://wiki.dovecot.org/Authentication/PasswordSchemes +# +default_pass_scheme = CRYPT + +# passdb query to retrieve the password. It can return fields: +# password - The user's password. This field must be returned. +# user - user@domain from the database. Needed with case-insensitive lookups. +# username and domain - An alternative way to represent the "user" field. +# +# The "user" field is often necessary with case-insensitive lookups to avoid +# e.g. "name" and "nAme" logins creating two different mail directories. If +# your user and domain names are in separate fields, you can return "username" +# and "domain" fields instead of "user". +# +# The query can also return other fields which have a special meaning, see +# http://wiki.dovecot.org/PasswordDatabase/ExtraFields +# +# Commonly used available substitutions (see http://wiki.dovecot.org/Variables +# for full list): +# %u = entire user@domain +# %n = user part of user@domain +# %d = domain part of user@domain +# +# Note that these can be used only as input to SQL query. If the query outputs +# any of these substitutions, they're not touched. Otherwise it would be +# difficult to have eg. usernames containing '%' characters. +# +# Example: +# password_query = SELECT userid AS user, pw AS password \ +# FROM users WHERE userid = '%u' AND active = 'Y' +# +#password_query = \ +# SELECT username, domain, password \ +# FROM users WHERE username = '%n' AND domain = '%d' +password_query = SELECT username AS user, password_enc AS password, CONCAT(homedir, maildir) AS userdb_home, uid AS userdb_uid, gid AS userdb_gid, CONCAT('maildir:', homedir, maildir) AS userdb_mail, CONCAT('*:storage=', quota, 'M') as userdb_quota_rule FROM mail_users WHERE (username = '%u' OR email = '%u') AND ((imap = 1 AND '%Ls' = 'imap') OR (pop3 = 1 AND '%Ls' = 'pop3') OR ((postfix = 'Y' AND '%Ls' = 'smtp') OR (postfix = 'Y' AND '%Ls' = 'sieve'))) +#password_query = SELECT username as user, password, '/var/vmail/%d/%n' as userdb_home, 'maildir:/var/vmail/%d/%n' as userdb_mail, 150 as userdb_uid, 12 as userdb_gid FROM mailbox WHERE username = '%u' AND active = '1' + +# userdb query to retrieve the user information. It can return fields: +# uid - System UID (overrides mail_uid setting) +# gid - System GID (overrides mail_gid setting) +# home - Home directory +# mail - Mail location (overrides mail_location setting) +# +# None of these are strictly required. If you use a single UID and GID, and +# home or mail directory fits to a template string, you could use userdb static +# instead. For a list of all fields that can be returned, see +# http://wiki.dovecot.org/UserDatabase/ExtraFields +# +# Examples: +# user_query = SELECT home, uid, gid FROM users WHERE userid = '%u' +# user_query = SELECT dir AS home, user AS uid, group AS gid FROM users where userid = '%u' +# user_query = SELECT home, 501 AS uid, 501 AS gid FROM users WHERE userid = '%u' +# +#user_query = \ +# SELECT home, uid, gid \ +# FROM users WHERE username = '%n' AND domain = '%d' +user_query = SELECT CONCAT(homedir, maildir) AS home, CONCAT('maildir:', homedir, maildir) AS mail, uid, gid, CONCAT('*:storage=', quota, 'M') as quota_rule FROM mail_users WHERE (username = '%u' OR email = '%u') +#user_query = SELECT '/var/vmail/%d/%n' as home, 'maildir:/var/vmail/%d/%n' as mail, 150 AS uid, 12 AS gid FROM mailbox WHERE username = '%u' AND active = '1' + +# If you wish to avoid two SQL lookups (passdb + userdb), you can use +# userdb prefetch instead of userdb sql in dovecot.conf. In that case you'll +# also have to return userdb fields in password_query prefixed with "userdb_" +# string. For example: +#password_query = \ +# SELECT userid AS user, password, \ +# home AS userdb_home, uid AS userdb_uid, gid AS userdb_gid \ +# FROM users WHERE userid = '%u' + +# Query to get a list of all usernames. +#iterate_query = SELECT username AS user FROM users +iterate_query = SELECT username AS user FROM mail_users +]]> + + + + + + + + + + + + + or context +# See: http://www.proftpd.org/docs/howto/Vhost.html + +# Trace logging, disabled by default for performance reasons +# (http://www.proftpd.org/docs/howto/Tracing.html) +#TraceLog /var/log/proftpd/trace.log +#Trace DEFAULT:0 + +ServerName " FTP server" +ServerIdent on "FTP Server ready." +ServerAdmin root@ +DefaultServer on + +# The DebugLevel directive configures the debugging level the server will use when logging. +# The level parameter must be between 0 and 9. +# This configuration directive will take precedence over any command-line debugging options used. +#DebugLevel 9 + +# Cause every FTP user except adm to be chrooted into their home directory +DefaultRoot ~ !adm + +# Use pam to authenticate (default) and be authoritative +AuthPAMConfig proftpd +AuthOrder mod_sql.c +#AuthOrder mod_auth_pam.c* mod_auth_unix.c +# If you use NIS/YP/LDAP you may need to disable PersistentPasswd +#PersistentPasswd off + +# Don't do reverse DNS lookups (hangs on DNS problems) +UseReverseDNS off + +# Set the user and group that the server runs as +User nobody +Group nobody + +# To prevent DoS attacks, set the maximum number of child processes +# to 20. If you need to allow more than 20 concurrent connections +# at once, simply increase this value. Note that this ONLY works +# in standalone mode; in inetd mode you should use an inetd server +# that allows you to limit maximum number of processes per service +# (such as xinetd) +MaxInstances 20 + +# Disable sendfile by default since it breaks displaying the download speeds in +# ftptop and ftpwho +UseSendfile off + +# Define the log formats +LogFormat default "%h %l %u %t \"%r\" %s %b" +LogFormat auth "%v [%P] %h %t \"%r\" %s" + +# Dynamic Shared Object (DSO) loading +# See README.DSO and howto/DSO.html for more details +# +# General database support (http://www.proftpd.org/docs/contrib/mod_sql.html) + LoadModule mod_sql.c +# +# Support for base-64 or hex encoded MD5 and SHA1 passwords from SQL tables +# (contrib/mod_sql_passwd.html) +# LoadModule mod_sql_passwd.c +# +# Mysql support (requires proftpd-mysql package) +# (http://www.proftpd.org/docs/contrib/mod_sql.html) + LoadModule mod_sql_mysql.c +# +# Postgresql support (requires proftpd-postgresql package) +# (http://www.proftpd.org/docs/contrib/mod_sql.html) +# LoadModule mod_sql_postgres.c +# +# Quota support (http://www.proftpd.org/docs/contrib/mod_quotatab.html) + LoadModule mod_quotatab.c +# +# File-specific "driver" for storing quota table information in files +# (http://www.proftpd.org/docs/contrib/mod_quotatab_file.html) +# LoadModule mod_quotatab_file.c +# +# SQL database "driver" for storing quota table information in SQL tables +# (http://www.proftpd.org/docs/contrib/mod_quotatab_sql.html) + LoadModule mod_quotatab_sql.c +# +# LDAP support (requires proftpd-ldap package) +# (http://www.proftpd.org/docs/directives/linked/config_ref_mod_ldap.html) +# LoadModule mod_ldap.c +# +# LDAP quota support (requires proftpd-ldap package) +# (http://www.proftpd.org/docs/contrib/mod_quotatab_ldap.html) +# LoadModule mod_quotatab_ldap.c +# +# Support for authenticating users using the RADIUS protocol +# (http://www.proftpd.org/docs/contrib/mod_radius.html) +# LoadModule mod_radius.c +# +# Retrieve quota limit table information from a RADIUS server +# (http://www.proftpd.org/docs/contrib/mod_quotatab_radius.html) +# LoadModule mod_quotatab_radius.c +# +# SITE CPFR and SITE CPTO commands (analogous to RNFR and RNTO), which can be +# used to copy files/directories from one place to another on the server +# without having to transfer the data to the client and back +# (http://www.castaglia.org/proftpd/modules/mod_copy.html) +# LoadModule mod_copy.c +# +# Administrative control actions for the ftpdctl program +# (http://www.proftpd.org/docs/contrib/mod_ctrls_admin.html) +LoadModule mod_ctrls_admin.c +# +# Support for MODE Z commands, which allows FTP clients and servers to +# compress data for transfer +# (http://www.castaglia.org/proftpd/modules/mod_deflate.html) +# LoadModule mod_deflate.c +# +# Execute external programs or scripts at various points in the process +# of handling FTP commands +# (http://www.castaglia.org/proftpd/modules/mod_exec.html) +# LoadModule mod_exec.c +# +# Support for POSIX ACLs +# (http://www.proftpd.org/docs/modules/mod_facl.html) +# LoadModule mod_facl.c +# +# Support for using the GeoIP library to look up geographical information on +# the connecting client and using that to set access controls for the server +# (http://www.castaglia.org/proftpd/modules/mod_geoip.html) +# LoadModule mod_geoip.c +# +# Allow for version-specific configuration sections of the proftpd config file, +# useful for using the same proftpd config across multiple servers where +# different proftpd versions may be in use +# (http://www.castaglia.org/proftpd/modules/mod_ifversion.html) +# LoadModule mod_ifversion.c +# +# Configure server availability based on system load +# (http://www.proftpd.org/docs/contrib/mod_load.html) +# LoadModule mod_load.c +# +# Limit downloads to a multiple of upload volume (see README.ratio) +# LoadModule mod_ratio.c +# +# Rewrite FTP commands sent by clients on-the-fly, +# using regular expression matching and substitution +# (http://www.proftpd.org/docs/contrib/mod_rewrite.html) +# LoadModule mod_rewrite.c +# +# Support for the SSH2, SFTP, and SCP protocols, for secure file transfer over +# an SSH2 connection (http://www.castaglia.org/proftpd/modules/mod_sftp.html) +# LoadModule mod_sftp.c +# +# Use PAM to provide a 'keyboard-interactive' SSH2 authentication method for +# mod_sftp (http://www.castaglia.org/proftpd/modules/mod_sftp_pam.html) +# LoadModule mod_sftp_pam.c +# +# Use SQL (via mod_sql) for looking up authorized SSH2 public keys for user +# and host based authentication +# (http://www.castaglia.org/proftpd/modules/mod_sftp_sql.html) +# LoadModule mod_sftp_sql.c +# +# Provide data transfer rate "shaping" across the entire server +# (http://www.castaglia.org/proftpd/modules/mod_shaper.html) +# LoadModule mod_shaper.c +# +# Support for miscellaneous SITE commands such as SITE MKDIR, SITE SYMLINK, +# and SITE UTIME (http://www.proftpd.org/docs/contrib/mod_site_misc.html) +# LoadModule mod_site_misc.c +# +# Provide an external SSL session cache using shared memory +# (contrib/mod_tls_shmcache.html) +# LoadModule mod_tls_shmcache.c +# +# Provide a memcached-based implementation of an external SSL session cache +# (contrib/mod_tls_memcache.html) +# LoadModule mod_tls_memcache.c +# +# Use the /etc/hosts.allow and /etc/hosts.deny files, or other allow/deny +# files, for IP-based access control +# (http://www.proftpd.org/docs/contrib/mod_wrap.html) +# LoadModule mod_wrap.c +# +# Use the /etc/hosts.allow and /etc/hosts.deny files, or other allow/deny +# files, as well as SQL-based access rules, for IP-based access control +# (http://www.proftpd.org/docs/contrib/mod_wrap2.html) +# LoadModule mod_wrap2.c +# +# Support module for mod_wrap2 that handles access rules stored in specially +# formatted files on disk +# (http://www.proftpd.org/docs/contrib/mod_wrap2_file.html) +# LoadModule mod_wrap2_file.c +# +# Support module for mod_wrap2 that handles access rules stored in SQL +# database tables (http://www.proftpd.org/docs/contrib/mod_wrap2_sql.html) +# LoadModule mod_wrap2_sql.c +# +# Implement a virtual chroot capability that does not require root privileges +# (http://www.castaglia.org/proftpd/modules/mod_vroot.html) +# Using this module rather than the kernel's chroot() system call works +# around issues with PAM and chroot (http://bugzilla.redhat.com/506735) +# LoadModule mod_vroot.c +# +# Provide a flexible way of specifying that certain configuration directives +# only apply to certain sessions, based on credentials such as connection +# class, user, or group membership +# (http://www.proftpd.org/docs/contrib/mod_ifsession.html) +# LoadModule mod_ifsession.c + +# Allow only user root to load and unload modules, but allow everyone +# to see which modules have been loaded +# (http://www.proftpd.org/docs/modules/mod_dso.html#ModuleControlsACLs) +ModuleControlsACLs insmod,rmmod allow user root +ModuleControlsACLs lsmod allow user * + +# Enable basic controls via ftpdctl +# (http://www.proftpd.org/docs/modules/mod_ctrls.html) +ControlsEngine on +ControlsACLs all allow user root +ControlsSocketACL allow user * +ControlsLog /var/log/proftpd/controls.log + +# Enable admin controls via ftpdctl +# (http://www.proftpd.org/docs/contrib/mod_ctrls_admin.html) + + AdminControlsEngine on + AdminControlsACLs all allow user root + + +# Enable mod_vroot by default for better compatibility with PAM +# (http://bugzilla.redhat.com/506735) + + VRootEngine on + + +# TLS (http://www.castaglia.org/proftpd/modules/mod_tls.html) + + TLSEngine on + TLSRequired on + TLSRSACertificateFile /etc/pki/tls/certs/proftpd.pem + TLSRSACertificateKeyFile /etc/pki/tls/certs/proftpd.pem + TLSCipherSuite ALL:!ADH:!DES + TLSOptions NoCertRequest NoSessionReuseRequired + TLSVerifyClient off + #TLSRenegotiate ctrl 3600 data 512000 required off timeout 300 + TLSLog /var/log/proftpd/tls.log + + TLSSessionCache shm:/file=/var/run/proftpd/sesscache + + + +# Dynamic ban lists (http://www.proftpd.org/docs/contrib/mod_ban.html) +# Enable this with PROFTPD_OPTIONS=-DDYNAMIC_BAN_LISTS in /etc/sysconfig/proftpd + + LoadModule mod_ban.c + BanEngine on + BanLog /var/log/proftpd/ban.log + BanTable /var/run/proftpd/ban.tab + + # If the same client reaches the MaxLoginAttempts limit 2 times + # within 10 minutes, automatically add a ban for that client that + # will expire after one hour. + BanOnEvent MaxLoginAttempts 2/00:10:00 01:00:00 + + # Inform the user that it's not worth persisting + BanMessage "Host %a has been banned" + + # Allow the FTP admin to manually add/remove bans + BanControlsACLs all allow user ftpadm + + +# Set networking-specific "Quality of Service" (QoS) bits on the packets used +# by the server (contrib/mod_qos.html) + + LoadModule mod_qos.c + # RFC791 TOS parameter compatibility + QoSOptions dataqos throughput ctrlqos lowdelay + # For a DSCP environment (may require tweaking) + #QoSOptions dataqos CS2 ctrlqos AF41 + + +# Global Config - config common to Server Config and all virtual hosts +# See: http://www.proftpd.org/docs/howto/Vhost.html + + + # Umask 022 is a good standard umask to prevent new dirs and files + # from being group and world writable + Umask 077 + + # Allow users to overwrite files and change permissions + AllowOverwrite yes + + AllowAll + + +# CH-Root all users + DefaultRoot ~ +# Reject rootlogin (just for security) + RootLogin off +# Noo need to require valid shell, because user is virtual + RequireValidShell off + + +# A basic anonymous configuration, with an upload directory +# Enable this with PROFTPD_OPTIONS=-DANONYMOUS_FTP in /etc/sysconfig/proftpd + + # + #User ftp + #Group ftp + #AccessGrantMsg "Anonymous login ok, restrictions apply." + + ## We want clients to be able to login with "anonymous" as well as "ftp" + #UserAlias anonymous ftp + + ## Limit the maximum number of anonymous logins + #MaxClients 10 "Sorry, max %m users -- try again later" + + ## Put the user into /pub right after login + ##DefaultChdir /pub + + ## We want 'welcome.msg' displayed at login, '.message' displayed in + ## each newly chdired directory and tell users to read README* files. + #DisplayLogin /welcome.msg + #DisplayChdir .message + #DisplayReadme README* + + ## Cosmetic option to make all files appear to be owned by user "ftp" + #DirFakeUser on ftp + #DirFakeGroup on ftp + + ## Limit WRITE everywhere in the anonymous chroot + # + #DenyAll + # + + ## An upload directory that allows storing files but not retrieving + ## or creating directories. + # + #AllowOverwrite no + # + #DenyAll + # + + # + #AllowAll + # + # + + ## Don't write anonymous accesses to the system wtmp file (good idea!) + #WtmpLog off + + ## Logging for the anonymous transfers + #ExtendedLog /var/log/proftpd/access.log WRITE,READ default + #ExtendedLog /var/log/proftpd/auth.log AUTH auth + + # + + + + SQLLogFile /var/log/proftpd/sql.log + SQLAuthTypes Crypt + SQLAuthenticate users* groups* + SQLConnectInfo @ + SQLUserInfo ftp_users username password uid gid homedir shell + SQLGroupInfo ftp_groups groupname gid members + SQLUserWhereClause "login_enabled = 'y'" + + SQLLog PASS login + #SQLNamedQuery login UPDATE "last_login=now(), login_count=login_count+1 WHERE username='%u'" ftp_users + + SQLLog RETR download + #SQLNamedQuery download UPDATE "down_count=down_count+1, down_bytes=down_bytes+%b WHERE username='%u'" ftp_users + + SQLLog STOR upload + #SQLNamedQuery upload UPDATE "up_count=up_count+1, up_bytes=up_bytes+%b WHERE username='%u'" ftp_users + #QuotaEngine on + #QuotaShowQuotas on + #QuotaDisplayUnits Mb + #QuotaLock /var/lock/ftpd.quotatab.lock + #QuotaLimitTable sql:/get-quota-limit + #QuotaTallyTable sql:/get-quota-tally/update-quota-tally/insert-quota-tally + #SQLNamedQuery get-quota-limit SELECT "ftp_users.username AS name, ftp_quotalimits.quota_type, ftp_quotalimits.per_session, ftp_quotalimits.limit_type, panel_customers.diskspace*1024 AS bytes_in_avail, ftp_quotalimits.bytes_out_avail, ftp_quotalimits.bytes_xfer_avail, ftp_quotalimits.files_in_avail, ftp_quotalimits.files_out_avail, ftp_quotalimits.files_xfer_avail FROM ftp_users, ftp_quotalimits, panel_customers WHERE ftp_users.username = '%{0}' AND panel_customers.loginname = SUBSTRING_INDEX('%{0}', 'ftp', 1) AND quota_type ='%{1}'" + #SQLNamedQuery get-quota-tally SELECT "name, quota_type, bytes_in_used,bytes_out_used, bytes_xfer_used, files_in_used, files_out_used,files_xfer_used FROM ftp_quotatallies WHERE name = '%{0}' AND quota_type = '%{1}'" + #SQLNamedQuery update-quota-tally UPDATE "bytes_in_used = bytes_in_used + %{0}, bytes_out_used = bytes_out_used + %{1}, bytes_xfer_used = bytes_xfer_used + %{2}, files_in_used = files_in_used + %{3}, files_out_used= files_out_used + %{4}, files_xfer_used = files_xfer_used + %{5} WHERE name= '%{6}' AND quota_type = '%{7}'" ftp_quotatallies + #SQLNamedQuery insert-quota-tally INSERT "%{0}, %{1}, %{2}, %{3}, %{4},%{5}, %{6}, %{7}" ftp_quotatallies + +]]> + + + + + + + + + + + scripts/froxlor_master_cronjob.php --run-task 99]]> + + + + + + + + + + + + + + +database +username +password +#socket /var/lib/mysql/mysql.sock +#port 3306 +]]> + + + + + {{sql.socket}} + + + + + +password +]]> + + + + + + + + + + + + + + + *.log { + missingok + daily + rotate 7 + compress + delaycompress + notifempty + create + sharedscripts + postrotate + > /dev/null 2>&1 || true + endscript +} +]]> + + + + + + + From cb1df3a7e04779a3d83593f34e8cb58021c2c94a Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Fri, 29 May 2020 15:29:53 +0200 Subject: [PATCH 057/319] show failue as nice red message --- install/lib/class.FroxlorInstall.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index f0ed0e53..25b2f814 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -511,7 +511,8 @@ class FroxlorInstall $this->_updateSetting($upd_stmt, $property->value[0], $property->group[0], $property->name[0]); } } else { - exit('Failed to open distribution XML file.'); + $content .= $this->_status_message('red', 'Failed setting distribution defaults.'); + return $content; } $this->_updateSetting($upd_stmt, $this->_data['activate_newsfeed'], 'admin', 'show_news_feed'); From 27f0c4eb5302c36c398e3971bcb8fc34ff09f19f Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Fri, 29 May 2020 15:42:38 +0200 Subject: [PATCH 058/319] remove distribution names from language files --- install/lng/english.lng.php | 8 -------- install/lng/french.lng.php | 8 -------- install/lng/german.lng.php | 8 -------- 3 files changed, 24 deletions(-) diff --git a/install/lng/english.lng.php b/install/lng/english.lng.php index 0b04e3c1..69c06ced 100644 --- a/install/lng/english.lng.php +++ b/install/lng/english.lng.php @@ -64,14 +64,6 @@ $lng['install']['admin_pass2'] = 'Administrator-Password (confirm)'; $lng['install']['activate_newsfeed'] = 'Enable the official newsfeed
(https://inside.froxlor.org/news/)'; $lng['install']['serversettings'] = 'Server settings'; $lng['install']['distribution'] = 'Distribution'; -$lng['install']['jessie'] = 'Debian Jessie'; -$lng['install']['stretch'] = 'Debian Stretch'; -$lng['install']['buster'] = 'Debian Buster'; -$lng['install']['xenial'] = 'Ubuntu Xenial'; -$lng['install']['bionic'] = 'Ubuntu Bionic'; -$lng['install']['focal'] = 'Ubuntu Focal'; -$lng['install']['rhel7'] = 'RHEL 7'; -$lng['install']['rhel8'] = 'RHEL 8'; $lng['install']['servername'] = 'Server name (FQDN, no ip-address)'; $lng['install']['serverip'] = 'Server IP'; $lng['install']['webserver'] = 'Webserver'; diff --git a/install/lng/french.lng.php b/install/lng/french.lng.php index 2eb6cb96..a3aacc6a 100644 --- a/install/lng/french.lng.php +++ b/install/lng/french.lng.php @@ -54,14 +54,6 @@ $lng['install']['admin_pass1'] = 'Mot de passe administrateur'; $lng['install']['admin_pass2'] = 'Mot de passe administrateur (confirmez)'; $lng['install']['serversettings'] = 'Réglages serveur'; $lng['install']['distribution'] = 'Distribution'; -$lng['install']['jessie'] = 'Debian Jessie'; -$lng['install']['stretch'] = 'Debian Stretch'; -$lng['install']['buster'] = 'Debian Buster'; -$lng['install']['xenial'] = 'Ubuntu Xenial'; -$lng['install']['bionic'] = 'Ubuntu Bionic'; -$lng['install']['focal'] = 'Ubuntu Focal'; -$lng['install']['rhel7'] = 'RHEL 7'; -$lng['install']['rhel8'] = 'RHEL 8'; $lng['install']['servername'] = 'Nom du serveur (FQDN, pas d\'adresse IP)'; $lng['install']['serverip'] = 'Adresse IP du serveur'; $lng['install']['webserver'] = 'Serveur Web'; diff --git a/install/lng/german.lng.php b/install/lng/german.lng.php index 24554712..bc31c4e2 100644 --- a/install/lng/german.lng.php +++ b/install/lng/german.lng.php @@ -64,14 +64,6 @@ $lng['install']['admin_pass2'] = 'Administrator-Passwort (Bestätigung)'; $lng['install']['activate_newsfeed'] = 'Aktiviere das offizielle Newsfeed
(https://inside.froxlor.org/news/)'; $lng['install']['serversettings'] = 'Servereinstellungen'; $lng['install']['distribution'] = 'Verteilung'; -$lng['install']['jessie'] = 'Debian Jessie'; -$lng['install']['stretch'] = 'Debian Stretch'; -$lng['install']['buster'] = 'Debian Buster'; -$lng['install']['xenial'] = 'Ubuntu Xenial'; -$lng['install']['bionic'] = 'Ubuntu Bionic'; -$lng['install']['focal'] = 'Ubuntu Focal'; -$lng['install']['rhel7'] = 'RHEL 7'; -$lng['install']['rhel8'] = 'RHEL 8'; $lng['install']['servername'] = 'Servername (FQDN, keine IP-Adresse)'; $lng['install']['serverip'] = 'Server-IP'; $lng['install']['webserver'] = 'Webserver'; From f4d4490d0877d0033164c58fcbf3a732e4215874 Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Fri, 29 May 2020 15:45:04 +0200 Subject: [PATCH 059/319] change property tagnames --- lib/configfiles/rhel7.xml | 48 +++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/lib/configfiles/rhel7.xml b/lib/configfiles/rhel7.xml index c95388f1..f472fba8 100644 --- a/lib/configfiles/rhel7.xml +++ b/lib/configfiles/rhel7.xml @@ -3,36 +3,36 @@ - - apacheconf_vhost - system + + apacheconf_vhost + system /etc/httpd/conf.d/ - - - apacheconf_diroptions - system + + + apacheconf_diroptions + system /etc/httpd/conf.d/ - - - apacheconf_htpasswddir - system + + + apacheconf_htpasswddir + system /etc/httpd/froxlor-htpasswd/ - - - apachereload_command - system + + + apachereload_command + system systemctl reload-or-restart httpd.service - - - bindreload_command - system + + + bindreload_command + system systemctl reload-or-restart named.service - - - crondreload - system + + + crondreload + system systemctl reload-or-restart crond.service - + From 6128954231d175bbeafd5d5a6f2260fc232a47ac Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Fri, 29 May 2020 15:54:37 +0200 Subject: [PATCH 060/319] rename propery to property --- install/lib/class.FroxlorInstall.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index 25b2f814..c270462b 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -507,7 +507,7 @@ class FroxlorInstall if (file_exists(dirname(__DIR__).'/../lib/configfiles/'.$this->_data['distribution'].'.xml')) { $xml = simplexml_load_file(dirname(__DIR__).'/../lib/configfiles/'.$this->_data['distribution'].'.xml'); - foreach($xml->distribution->defaults->propery as $property) { + foreach($xml->distribution->defaults->property as $property) { $this->_updateSetting($upd_stmt, $property->value[0], $property->group[0], $property->name[0]); } } else { @@ -1308,7 +1308,7 @@ class FroxlorInstall // post if (! empty($_POST['distribution'])) { $this->_data['distribution'] = $_POST['distribution']; - } else { + } else { $os_version = parse_ini_file('/etc/os-release', false); if ($os_version['ID'] == 'debian') { From fb35fb9a3a5de362c836028ecb702240b60b554b Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Fri, 29 May 2020 17:33:48 +0200 Subject: [PATCH 061/319] read distribution from xml and selection via selectbox --- install/lib/class.FroxlorInstall.php | 81 ++++++++++++++++------------ install/templates/dataitemselect.tpl | 6 +++ 2 files changed, 53 insertions(+), 34 deletions(-) create mode 100644 install/templates/dataitemselect.tpl diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index c270462b..ce632f14 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -857,14 +857,26 @@ class FroxlorInstall } else { $diststyle = ''; } - $formdata .= $this->_GETsectionItemCheckbox('distribution', 'jessie', ($this->_data['distribution'] == 'jessie'), $diststyle); - $formdata .= $this->_getSectionItemCheckbox('distribution', 'stretch', ($this->_data['distribution'] == 'stretch'), $diststyle); - $formdata .= $this->_getSectionItemCheckbox('distribution', 'buster', ($this->_data['distribution'] == 'buster'), $diststyle); - $formdata .= $this->_getSectionItemCheckbox('distribution', 'xenial', ($this->_data['distribution'] == 'xenial'), $diststyle); - $formdata .= $this->_getSectionItemCheckbox('distribution', 'bionic', ($this->_data['distribution'] == 'bionic'), $diststyle); - $formdata .= $this->_getSectionItemCheckbox('distribution', 'focal', ($this->_data['distribution'] == 'focal'), $diststyle); - $formdata .= $this->_getSectionItemCheckbox('distribution', 'rhel7', ($this->_data['distribution'] == 'rhel7'), $diststyle); - $formdata .= $this->_getSectionItemCheckbox('distribution', 'rhel8', ($this->_data['distribution'] == 'rhel8'), $diststyle); + + // show list of available distro's + $distros = glob(\Froxlor\FileDir::makeCorrectDir(\Froxlor\Froxlor::getInstallDir() . '/lib/configfiles/') . '*.xml'); + foreach ($distros as $_distribution) { + $dist = new \Froxlor\Config\ConfigParser($_distribution); + $dist_display = $dist->distributionName." ".$dist->distributionCodename." (" . $dist->distributionVersion . ")"; + $distributions_select_data[$dist_display] .= str_replace(".xml", "", strtolower(basename($_distribution))); + } + + // sort by distribution name + ksort($distributions_select_data); + + foreach ($distributions_select_data as $dist_display => $dist_index) { + // create select-box-option + $distributions_select .= \Froxlor\UI\HTML::makeoption($dist_display, $dist_index, $this->_data['distribution']); + //$this->_data['distribution'] + } + + $formdata .= $this->_getSectionItemSelectbox('distribution', $distributions_select, $diststyle); + // servername if (! empty($_POST['installstep']) && $this->_data['servername'] == '') { $style = 'color:red;'; @@ -963,6 +975,25 @@ class FroxlorInstall return $sectionitem; } + /** + * generate form selectbox + * + * @param string $fieldname + * @param boolean $options + * @param string $style + * + * @return string + */ + private function _getSectionItemSelectbox($fieldname = null, $options = null, $style = "") + { + $groupname = $this->_lng['install'][$groupname]; + $fieldlabel = $this->_lng['install'][$fieldname]; + + $sectionitem = ""; + eval("\$sectionitem .= \"" . $this->_getTemplate("dataitemselect") . "\";"); + return $sectionitem; + } + /** * generate form checkbox field * @@ -1309,34 +1340,16 @@ class FroxlorInstall if (! empty($_POST['distribution'])) { $this->_data['distribution'] = $_POST['distribution']; } else { - $os_version = parse_ini_file('/etc/os-release', false); - if ($os_version['ID'] == 'debian') { + $os_dist = parse_ini_file('/etc/os-release', false); + $os_version = explode('.',$os_version['VERSION_ID'])[0]; - } elseif ($os_version['ID'] == 'debian') { - if(explode('.',$os_version['VERSION_ID'])[0] == '8') { - $this->_data['distribution'] = 'jessie'; - } elseif(explode('.',$os_version['VERSION_ID'])[0] == '9') { - $this->_data['distribution'] = 'stretch'; - } elseif(explode('.',$os_version['VERSION_ID'])[0] == '10') { - $this->_data['distribution'] = 'buster'; - } - } elseif ($os_version['ID'] == 'ubuntu') { - if(explode('.',$os_version['VERSION_ID'])[0] == '16') { - $this->_data['distribution'] = 'xenial'; - } elseif(explode('.',$os_version['VERSION_ID'])[0] == '18') { - $this->_data['distribution'] = 'bionic'; - } elseif(explode('.',$os_version['VERSION_ID'])[0] == '20') { - $this->_data['distribution'] = 'focal'; - } - } elseif($os_version['ID'] == 'rhel' || $os_version['ID'] == 'centos' || $os_version['ID'] == 'fedora') { - if(explode('.',$os_version['VERSION_ID'])[0] == '7') { - $this->_data['distribution'] = 'rhel7'; - } elseif(explode('.',$os_version['VERSION_ID'])[0] == '8') { - $this->_data['distribution'] = 'rhel8'; + $distros = glob(\Froxlor\FileDir::makeCorrectDir(\Froxlor\Froxlor::getInstallDir() . '/lib/configfiles/') . '*.xml'); + foreach ($distros as $_distribution) { + $dist = new \Froxlor\Config\ConfigParser($_distribution); + $ver = explode('.', $dist->distributionVersion)[0]; + if (strtolower($os_dist['ID']) == strtolower($dist->distributionName) && $os_version = $ver) { // && && $os_version == explode('.', $dist->distributionVersion)[0]) + $this->_data['distribution'] = str_replace(".xml", "", strtolower(basename($_distribution))); } - } else { - // we don't need to bail out, since unknown does not affect any critical installation routines - $this->_data['distribution'] = 'unknown'; } } } diff --git a/install/templates/dataitemselect.tpl b/install/templates/dataitemselect.tpl new file mode 100644 index 00000000..91701bc6 --- /dev/null +++ b/install/templates/dataitemselect.tpl @@ -0,0 +1,6 @@ +

+ + +

From 7fcacb46378fdb2aa23bd99da17e070b2852194e Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Fri, 29 May 2020 17:45:37 +0200 Subject: [PATCH 062/319] rename to centos because its most likey to be used --- lib/configfiles/{rhel8.xml => centos8.xml} | 50 +++++++++++----------- 1 file changed, 25 insertions(+), 25 deletions(-) rename lib/configfiles/{rhel8.xml => centos8.xml} (99%) diff --git a/lib/configfiles/rhel8.xml b/lib/configfiles/centos8.xml similarity index 99% rename from lib/configfiles/rhel8.xml rename to lib/configfiles/centos8.xml index 42fc34c0..0d33a5b9 100644 --- a/lib/configfiles/rhel8.xml +++ b/lib/configfiles/centos8.xml @@ -1,38 +1,38 @@ - - - apacheconf_vhost - system + + apacheconf_vhost + system /etc/httpd/conf.d/ - - - apacheconf_diroptions - system + + + apacheconf_diroptions + system /etc/httpd/conf.d/ - - - apacheconf_htpasswddir - system + + + apacheconf_htpasswddir + system /etc/httpd/froxlor-htpasswd/ - - - apachereload_command - system + + + apachereload_command + system systemctl reload-or-restart httpd.service - - - bindreload_command - system + + + bindreload_command + system systemctl reload-or-restart named.service - - - crondreload - system + + + crondreload + system systemctl reload-or-restart crond.service - + From 60578a5d31184fe37631d7ebd571c10e06ad8c90 Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Fri, 29 May 2020 17:46:38 +0200 Subject: [PATCH 063/319] rename to CentOS because its most likely to be used --- lib/configfiles/rhel7.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/configfiles/rhel7.xml b/lib/configfiles/rhel7.xml index f472fba8..833ab185 100644 --- a/lib/configfiles/rhel7.xml +++ b/lib/configfiles/rhel7.xml @@ -1,6 +1,6 @@ - From 86155f7a9c39aeb20ff5c4f69ec024e9648d79e2 Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Sat, 30 May 2020 09:11:43 +0200 Subject: [PATCH 064/319] use Distribution in german language --- install/lng/german.lng.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/lng/german.lng.php b/install/lng/german.lng.php index bc31c4e2..4c0aaf68 100644 --- a/install/lng/german.lng.php +++ b/install/lng/german.lng.php @@ -63,7 +63,7 @@ $lng['install']['admin_pass1'] = 'Administrator-Passwort'; $lng['install']['admin_pass2'] = 'Administrator-Passwort (Bestätigung)'; $lng['install']['activate_newsfeed'] = 'Aktiviere das offizielle Newsfeed
(https://inside.froxlor.org/news/)'; $lng['install']['serversettings'] = 'Servereinstellungen'; -$lng['install']['distribution'] = 'Verteilung'; +$lng['install']['distribution'] = 'Distribution'; $lng['install']['servername'] = 'Servername (FQDN, keine IP-Adresse)'; $lng['install']['serverip'] = 'Server-IP'; $lng['install']['webserver'] = 'Webserver'; From 0fde1ce7e9e805921c37fbf3e94d5d02d008f06b Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Sat, 30 May 2020 09:15:15 +0200 Subject: [PATCH 065/319] remove dev comment --- install/lib/class.FroxlorInstall.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index ce632f14..0e4bb52b 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -1347,7 +1347,7 @@ class FroxlorInstall foreach ($distros as $_distribution) { $dist = new \Froxlor\Config\ConfigParser($_distribution); $ver = explode('.', $dist->distributionVersion)[0]; - if (strtolower($os_dist['ID']) == strtolower($dist->distributionName) && $os_version = $ver) { // && && $os_version == explode('.', $dist->distributionVersion)[0]) + if (strtolower($os_dist['ID']) == strtolower($dist->distributionName) && $os_version = $ver) { $this->_data['distribution'] = str_replace(".xml", "", strtolower(basename($_distribution))); } } From 1454d8d40fe71fee247f423d36951ae8f42d961d Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Sat, 30 May 2020 10:08:05 +0200 Subject: [PATCH 066/319] get defaults from configparser --- install/lib/class.FroxlorInstall.php | 11 ++++++ lib/Froxlor/Config/ConfigParser.php | 50 ++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index 0e4bb52b..0ca253ce 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -505,6 +505,17 @@ class FroxlorInstall $this->_updateSetting($upd_stmt, 'error', 'system', 'errorlog_level'); } + $distros = glob(\Froxlor\FileDir::makeCorrectDir(\Froxlor\Froxlor::getInstallDir() . '/lib/configfiles/') . '*.xml'); + foreach ($distros as $_distribution) { + if($this->_data['distribution'] == str_replace(".xml", "", strtolower(basename($_distribution)))) { + $dist = new \Froxlor\Config\ConfigParser($_distribution); + $defaults = $dist->getDefaults(); + foreach ($defaults->property as $property) { + $this->_updateSetting($upd_stmt, $property->value, $property->settinggroup, $property->varname); + } + } + } + if (file_exists(dirname(__DIR__).'/../lib/configfiles/'.$this->_data['distribution'].'.xml')) { $xml = simplexml_load_file(dirname(__DIR__).'/../lib/configfiles/'.$this->_data['distribution'].'.xml'); foreach($xml->distribution->defaults->property as $property) { diff --git a/lib/Froxlor/Config/ConfigParser.php b/lib/Froxlor/Config/ConfigParser.php index ca995d7c..c881bcdd 100644 --- a/lib/Froxlor/Config/ConfigParser.php +++ b/lib/Froxlor/Config/ConfigParser.php @@ -39,6 +39,13 @@ class ConfigParser */ private $services = array(); + /** + * Holding the available defaults in the XML + * + * @var array + */ + private $defaults = array(); + /** * Store the parsed SimpleXMLElement for usage * @@ -147,7 +154,7 @@ class ConfigParser * * @return bool */ - private function parse() + private function parseServices() { // We only want to parse the stuff one time if ($this->isparsed == true) { @@ -174,6 +181,29 @@ class ConfigParser return true; } + /** + * Parse the XML and populate $this->services + * + * @return bool + */ + private function parseDefaults() + { + // We only want to parse the stuff one time + if ($this->isparsed == true) { + return true; + } + + // Get all defaults + $defaults = $this->xml->xpath('//defaults'); + foreach ($defaults as $default) { + $this->defaults = $default; + } + + // Switch flag to indicate we parsed our data + $this->isparsed = true; + return true; + } + /** * Return all services defined by the XML * @@ -184,9 +214,25 @@ class ConfigParser public function getServices() { // Let's parse this shit(!) - $this->parse(); + $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; + } } From 6ccfb7efbb013386a79c7d37ff95e83ebc2738b1 Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Sat, 30 May 2020 10:10:57 +0200 Subject: [PATCH 067/319] remove old code --- install/lib/class.FroxlorInstall.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index 0ca253ce..b9ab4dc0 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -516,16 +516,6 @@ class FroxlorInstall } } - if (file_exists(dirname(__DIR__).'/../lib/configfiles/'.$this->_data['distribution'].'.xml')) { - $xml = simplexml_load_file(dirname(__DIR__).'/../lib/configfiles/'.$this->_data['distribution'].'.xml'); - foreach($xml->distribution->defaults->property as $property) { - $this->_updateSetting($upd_stmt, $property->value[0], $property->group[0], $property->name[0]); - } - } else { - $content .= $this->_status_message('red', 'Failed setting distribution defaults.'); - return $content; - } - $this->_updateSetting($upd_stmt, $this->_data['activate_newsfeed'], 'admin', 'show_news_feed'); $this->_updateSetting($upd_stmt, dirname(dirname(dirname(__FILE__))), 'system', 'letsencryptchallengepath'); From 394ec4cd4a39c20d0f755a5d7c16c0c8589fd737 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 31 May 2020 09:13:22 +0200 Subject: [PATCH 068/319] fix ecc certificate paths Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index 677d1cbe..959dd2aa 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -492,10 +492,6 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron private static function checkFsFilesAreNewer($domain, $cert_date = 0) { $certificate_folder = self::getWorkingDirFromEnv($domain); - if (Settings::Get('system.leecc') > 0) { - $certificate_folder .= "_ecc"; - } - $certificate_folder = \Froxlor\FileDir::makeCorrectDir($certificate_folder); $ssl_file = \Froxlor\FileDir::makeCorrectFile($certificate_folder . '/' . $domain . '.cer'); if (is_dir($certificate_folder) && file_exists($ssl_file) && is_readable($ssl_file)) { @@ -509,6 +505,9 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron public static function getWorkingDirFromEnv($domain = "") { + if (Settings::Get('system.leecc') > 0) { + $domain .= "_ecc"; + } $env_file = FileDir::makeCorrectFile(dirname(self::$acmesh) . '/acme.sh.env'); if (file_exists($env_file)) { $output = []; From a7934bcb7bae7fde26d0e6b5f6cf04db2df51381 Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Sun, 31 May 2020 11:17:43 +0200 Subject: [PATCH 069/319] rename rhel7 to centos7 for consistancy --- lib/configfiles/{rhel7.xml => centos7.xml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lib/configfiles/{rhel7.xml => centos7.xml} (100%) diff --git a/lib/configfiles/rhel7.xml b/lib/configfiles/centos7.xml similarity index 100% rename from lib/configfiles/rhel7.xml rename to lib/configfiles/centos7.xml From de061e7e367f18398852021ab2e5553b0d6ee264 Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Sun, 31 May 2020 12:46:33 +0200 Subject: [PATCH 070/319] add missing apacheconf_htpasswddir dir --- lib/configfiles/centos8.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/configfiles/centos8.xml b/lib/configfiles/centos8.xml index 0d33a5b9..ad4098e0 100644 --- a/lib/configfiles/centos8.xml +++ b/lib/configfiles/centos8.xml @@ -64,6 +64,7 @@ + From 252449188393aa7b38656f08ec575b7650597173 Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Sun, 31 May 2020 12:47:28 +0200 Subject: [PATCH 071/319] centos8 uses 'dandified yum' --- lib/configfiles/centos8.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/configfiles/centos8.xml b/lib/configfiles/centos8.xml index ad4098e0..ee568f7e 100644 --- a/lib/configfiles/centos8.xml +++ b/lib/configfiles/centos8.xml @@ -98,7 +98,7 @@ Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath} - + > /etc/named.conf]]> > /etc/named.conf.local]]> @@ -125,7 +125,7 @@ Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath} - + @@ -327,7 +327,7 @@ dovecot unix - n n - - pipe flags=DRhu user=vmail:vmail argv=/usr/libexec/dove - + - + - - + + - + Date: Sun, 31 May 2020 12:52:31 +0200 Subject: [PATCH 072/319] proftpd requires epel --- lib/configfiles/centos8.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/configfiles/centos8.xml b/lib/configfiles/centos8.xml index ee568f7e..4d78ca8f 100644 --- a/lib/configfiles/centos8.xml +++ b/lib/configfiles/centos8.xml @@ -1872,6 +1872,7 @@ iterate_query = SELECT username AS user FROM mail_users + From b672c722b9170e75158521513dbeb47eabcd50b3 Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Sun, 31 May 2020 13:05:52 +0200 Subject: [PATCH 073/319] no user interaction on package installation --- lib/configfiles/centos8.xml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/configfiles/centos8.xml b/lib/configfiles/centos8.xml index 4d78ca8f..3b81b3ba 100644 --- a/lib/configfiles/centos8.xml +++ b/lib/configfiles/centos8.xml @@ -98,7 +98,7 @@ Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath} - + > /etc/named.conf]]> > /etc/named.conf.local]]> @@ -125,7 +125,7 @@ Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath} - + @@ -327,7 +327,7 @@ dovecot unix - n n - - pipe flags=DRhu user=vmail:vmail argv=/usr/libexec/dove - + - - + + - - + + - + Date: Sun, 31 May 2020 13:11:58 +0200 Subject: [PATCH 074/319] install awstats and requirements --- lib/configfiles/centos8.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/configfiles/centos8.xml b/lib/configfiles/centos8.xml index 3b81b3ba..30ce1efb 100644 --- a/lib/configfiles/centos8.xml +++ b/lib/configfiles/centos8.xml @@ -2343,6 +2343,8 @@ ControlsLog /var/log/proftpd/controls.log + + From 4e9df61fefd0f79de9e31feb6925c640e47752fb Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Sun, 31 May 2020 13:15:55 +0200 Subject: [PATCH 075/319] awstats cron is moved to cron.hourly --- lib/configfiles/centos8.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/configfiles/centos8.xml b/lib/configfiles/centos8.xml index 30ce1efb..3e0b5c18 100644 --- a/lib/configfiles/centos8.xml +++ b/lib/configfiles/centos8.xml @@ -2347,7 +2347,7 @@ ControlsLog /var/log/proftpd/controls.log - + Date: Sun, 31 May 2020 14:28:37 +0200 Subject: [PATCH 076/319] undo dnf -y --- lib/configfiles/centos8.xml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/configfiles/centos8.xml b/lib/configfiles/centos8.xml index 3e0b5c18..207f9785 100644 --- a/lib/configfiles/centos8.xml +++ b/lib/configfiles/centos8.xml @@ -98,7 +98,7 @@ Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath} - + > /etc/named.conf]]> > /etc/named.conf.local]]> @@ -125,7 +125,7 @@ Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath} - + @@ -327,7 +327,7 @@ dovecot unix - n n - - pipe flags=DRhu user=vmail:vmail argv=/usr/libexec/dove - + - - + + - + @@ -2352,8 +2352,8 @@ ControlsLog /var/log/proftpd/controls.log - - + + - + Date: Sun, 31 May 2020 14:57:07 +0200 Subject: [PATCH 077/319] proftp requires epel, awstats needs install and awstats cron moved --- lib/configfiles/centos7.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/configfiles/centos7.xml b/lib/configfiles/centos7.xml index 833ab185..98307ba3 100644 --- a/lib/configfiles/centos7.xml +++ b/lib/configfiles/centos7.xml @@ -1871,6 +1871,7 @@ iterate_query = SELECT username AS user FROM mail_users + @@ -2341,9 +2342,10 @@ ControlsLog /var/log/proftpd/controls.log + - + Date: Sun, 31 May 2020 16:00:50 +0200 Subject: [PATCH 078/319] fix bugs is dist detection --- install/lib/class.FroxlorInstall.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index b9ab4dc0..cb833d90 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -1342,13 +1342,13 @@ class FroxlorInstall $this->_data['distribution'] = $_POST['distribution']; } else { $os_dist = parse_ini_file('/etc/os-release', false); - $os_version = explode('.',$os_version['VERSION_ID'])[0]; + $os_version = explode('.',$os_dist['VERSION_ID'])[0]; $distros = glob(\Froxlor\FileDir::makeCorrectDir(\Froxlor\Froxlor::getInstallDir() . '/lib/configfiles/') . '*.xml'); foreach ($distros as $_distribution) { $dist = new \Froxlor\Config\ConfigParser($_distribution); $ver = explode('.', $dist->distributionVersion)[0]; - if (strtolower($os_dist['ID']) == strtolower($dist->distributionName) && $os_version = $ver) { + if (strtolower($os_dist['ID']) == strtolower($dist->distributionName) && $os_version == $ver) { $this->_data['distribution'] = str_replace(".xml", "", strtolower(basename($_distribution))); } } From fe0fb8dd5faba4777c62a69fed082b130fcadd9c Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 31 May 2020 16:38:53 +0200 Subject: [PATCH 079/319] fix non-static method called statically in \Froxlor\FileDir Signed-off-by: Michael Kaufmann --- lib/Froxlor/Customer/Customer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Froxlor/Customer/Customer.php b/lib/Froxlor/Customer/Customer.php index 26531196..2b04d6dd 100644 --- a/lib/Froxlor/Customer/Customer.php +++ b/lib/Froxlor/Customer/Customer.php @@ -30,7 +30,7 @@ class Customer * * @return string customers loginname */ - public function getLoginNameByUid($uid = null) + public static function getLoginNameByUid($uid = null) { $result_stmt = Database::prepare(" SELECT `loginname` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `guid` = :guid From 1f48ca47116137f13e127ea660fcfe01a2276af5 Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Sun, 31 May 2020 20:10:07 +0200 Subject: [PATCH 080/319] autodeterct distribution in CLI --- lib/Froxlor/Cli/Action/ConfigServicesAction.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/Froxlor/Cli/Action/ConfigServicesAction.php b/lib/Froxlor/Cli/Action/ConfigServicesAction.php index 73192a91..f4a941f1 100644 --- a/lib/Froxlor/Cli/Action/ConfigServicesAction.php +++ b/lib/Froxlor/Cli/Action/ConfigServicesAction.php @@ -83,6 +83,12 @@ class ConfigServicesAction extends \Froxlor\Cli\Action $distros = glob($config_dir . '*.xml'); // tmp array $distributions_select_data = array(); + + //read os-release + $os_dist = parse_ini_file('/etc/os-release', false); + $os_version = explode('.',$os_dist['VERSION_ID'])[0]; + $os_default = ""; + // read in all the distros foreach ($distros as $_distribution) { // get configparser object @@ -91,6 +97,11 @@ class ConfigServicesAction extends \Froxlor\Cli\Action $dist_display = $this->getCompleteDistroName($dist); // store in tmp array $distributions_select_data[$dist_display] = str_replace(".xml", "", strtolower(basename($_distribution))); + + $ver = explode('.', $dist->distributionVersion)[0]; + if (strtolower($os_dist['ID']) == strtolower($dist->distributionName) && $os_version == $ver) { + $os_default = str_replace(".xml", "", strtolower(basename($_distribution))); + } } // sort by distribution name @@ -108,7 +119,7 @@ class ConfigServicesAction extends \Froxlor\Cli\Action echo PHP_EOL; while (! in_array($_daemons_config['distro'], $distributions_select_data)) { - $_daemons_config['distro'] = ConfigServicesCmd::getInput("choose distribution", "buster"); + $_daemons_config['distro'] = ConfigServicesCmd::getInput("choose distribution", $os_default); } // go through all services and let user check whether to include it or not From e7cfceb65dc6bce4d568f64d3245d1ff04d4b7ef Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Sun, 31 May 2020 20:18:37 +0200 Subject: [PATCH 081/319] add comment --- lib/Froxlor/Cli/Action/ConfigServicesAction.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Froxlor/Cli/Action/ConfigServicesAction.php b/lib/Froxlor/Cli/Action/ConfigServicesAction.php index f4a941f1..cbe9e89a 100644 --- a/lib/Froxlor/Cli/Action/ConfigServicesAction.php +++ b/lib/Froxlor/Cli/Action/ConfigServicesAction.php @@ -98,6 +98,7 @@ class ConfigServicesAction extends \Froxlor\Cli\Action // store in tmp array $distributions_select_data[$dist_display] = str_replace(".xml", "", strtolower(basename($_distribution))); + //guess if this is the current distro. $ver = explode('.', $dist->distributionVersion)[0]; if (strtolower($os_dist['ID']) == strtolower($dist->distributionName) && $os_version == $ver) { $os_default = str_replace(".xml", "", strtolower(basename($_distribution))); From da1d94149a1f10676eaa7e74e6dad99d9b97f069 Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Sun, 31 May 2020 20:34:47 +0200 Subject: [PATCH 082/319] saet defaults and do some checks --- lib/Froxlor/Cli/Action/ConfigServicesAction.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/Froxlor/Cli/Action/ConfigServicesAction.php b/lib/Froxlor/Cli/Action/ConfigServicesAction.php index cbe9e89a..b9168f74 100644 --- a/lib/Froxlor/Cli/Action/ConfigServicesAction.php +++ b/lib/Froxlor/Cli/Action/ConfigServicesAction.php @@ -84,10 +84,17 @@ class ConfigServicesAction extends \Froxlor\Cli\Action // tmp array $distributions_select_data = array(); + //set default os. + $os_dist = array('ID' => 'buster'); + $os_version = array('0' => '10'); + $os_default = $os_dist['ID']; + //read os-release - $os_dist = parse_ini_file('/etc/os-release', false); - $os_version = explode('.',$os_dist['VERSION_ID'])[0]; - $os_default = ""; + if(file_exists('/etc/os-release')) { + $os_dist = parse_ini_file('/etc/os-release', false); + if(is_array($os_dist) && array_key_exists('ID', $os_dist) && array_key_exists('VERSION_ID', $os_dist)) + $os_version = explode('.',$os_dist['VERSION_ID'])[0]; + } // read in all the distros foreach ($distros as $_distribution) { From 1a6082ca915effeb0f1a931010661d573af09669 Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Sun, 31 May 2020 20:36:52 +0200 Subject: [PATCH 083/319] complete if statement --- lib/Froxlor/Cli/Action/ConfigServicesAction.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Froxlor/Cli/Action/ConfigServicesAction.php b/lib/Froxlor/Cli/Action/ConfigServicesAction.php index b9168f74..464e54df 100644 --- a/lib/Froxlor/Cli/Action/ConfigServicesAction.php +++ b/lib/Froxlor/Cli/Action/ConfigServicesAction.php @@ -92,8 +92,9 @@ class ConfigServicesAction extends \Froxlor\Cli\Action //read os-release if(file_exists('/etc/os-release')) { $os_dist = parse_ini_file('/etc/os-release', false); - if(is_array($os_dist) && array_key_exists('ID', $os_dist) && array_key_exists('VERSION_ID', $os_dist)) - $os_version = explode('.',$os_dist['VERSION_ID'])[0]; + if(is_array($os_dist) && array_key_exists('ID', $os_dist) && array_key_exists('VERSION_ID', $os_dist)) { + $os_version = explode('.',$os_dist['VERSION_ID'])[0]; + } } // read in all the distros From ed4dbba27809f9272c7dcbc235730db96ac9fc7a Mon Sep 17 00:00:00 2001 From: Ante de Baas Date: Sun, 31 May 2020 20:46:27 +0200 Subject: [PATCH 084/319] also perform checks in Install class --- install/lib/class.FroxlorInstall.php | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index cb833d90..2f4c8f95 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -1340,9 +1340,18 @@ class FroxlorInstall // post if (! empty($_POST['distribution'])) { $this->_data['distribution'] = $_POST['distribution']; - } else { - $os_dist = parse_ini_file('/etc/os-release', false); - $os_version = explode('.',$os_dist['VERSION_ID'])[0]; + } else { + //set default os. + $os_dist = array('ID' => 'buster'); + $os_version = array('0' => '10'); + + //read os-release + if(file_exists('/etc/os-release')) { + $os_dist = parse_ini_file('/etc/os-release', false); + if(is_array($os_dist) && array_key_exists('ID', $os_dist) && array_key_exists('VERSION_ID', $os_dist)) { + $os_version = explode('.',$os_dist['VERSION_ID'])[0]; + } + } $distros = glob(\Froxlor\FileDir::makeCorrectDir(\Froxlor\Froxlor::getInstallDir() . '/lib/configfiles/') . '*.xml'); foreach ($distros as $_distribution) { From 2c98fc4c2d2522ab3e8006b5e968bc8a39f0ff56 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Thu, 4 Jun 2020 07:42:13 +0200 Subject: [PATCH 085/319] fix wrong certificate folder for fallback ceck (ecc/non-ecc) Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index 959dd2aa..a5cb15b2 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -503,9 +503,9 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron return false; } - public static function getWorkingDirFromEnv($domain = "") + public static function getWorkingDirFromEnv($domain = "", $forced_noecc = false) { - if (Settings::Get('system.leecc') > 0) { + if (Settings::Get('system.leecc') > 0 && !$forced_noecc) { $domain .= "_ecc"; } $env_file = FileDir::makeCorrectFile(dirname(self::$acmesh) . '/acme.sh.env'); @@ -539,8 +539,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron $certificate_folder = self::getWorkingDirFromEnv($domain); $certificate_folder_noecc = null; if (Settings::Get('system.leecc') > 0) { - $certificate_folder_noecc = \Froxlor\FileDir::makeCorrectDir($certificate_folder); - $certificate_folder .= "_ecc"; + $certificate_folder_noecc = self::getWorkingDirFromEnv($domain, true); } $certificate_folder = \Froxlor\FileDir::makeCorrectDir($certificate_folder); From d4716b23769ced70f83cddd7a06893fd8ee8c892 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 5 Jun 2020 15:33:49 +0200 Subject: [PATCH 086/319] correct documentation for Customers.add(), fixes #856 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Customers.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Froxlor/Api/Commands/Customers.php b/lib/Froxlor/Api/Commands/Customers.php index 47e309f4..97c31225 100644 --- a/lib/Froxlor/Api/Commands/Customers.php +++ b/lib/Froxlor/Api/Commands/Customers.php @@ -183,7 +183,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource * 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 - * @param string $password + * @param string $new_customer_password * 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) From 8e60c6b20112acab4a969e2e2d67d33ce74ca573 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 5 Jun 2020 16:23:41 +0200 Subject: [PATCH 087/319] update api documentation for Ftps.update(), fixes #857 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Ftps.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Froxlor/Api/Commands/Ftps.php b/lib/Froxlor/Api/Commands/Ftps.php index 978b03b4..6123796a 100644 --- a/lib/Froxlor/Api/Commands/Ftps.php +++ b/lib/Froxlor/Api/Commands/Ftps.php @@ -339,7 +339,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit * update a given ftp-user by id or username * * @param int $id - * optional, the customer-id + * optional, the ftp-user-id * @param string $username * optional, the username * @param string $ftp_password From 2748f1b6337f477af93bd62cee13546c2b3c4827 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sat, 6 Jun 2020 15:37:06 +0200 Subject: [PATCH 088/319] also display error when domain does not resolv to any A or AAAA record in lets-encrypt-dns-validation Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index a5cb15b2..cd2f2913 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -278,7 +278,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Validating DNS of " . $domain); // ips accordint to NS $domain_ips = PhpHelper::gethostbynamel6($domain); - if (count(array_intersect($our_ips, $domain_ips)) <= 0) { + 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]); From 490704f8e12c174d012a78cf213e100659e1b26d Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sat, 6 Jun 2020 20:57:24 +0200 Subject: [PATCH 089/319] Heredoc/nowdoc with an indented closing marker is not supported in PHP 7.2 or earlier. Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index cd2f2913..e29dbbc2 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -505,15 +505,15 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron public static function getWorkingDirFromEnv($domain = "", $forced_noecc = false) { - if (Settings::Get('system.leecc') > 0 && !$forced_noecc) { + if (Settings::Get('system.leecc') > 0 && ! $forced_noecc) { $domain .= "_ecc"; } $env_file = FileDir::makeCorrectFile(dirname(self::$acmesh) . '/acme.sh.env'); if (file_exists($env_file)) { $output = []; $cut = << Date: Mon, 8 Jun 2020 11:42:44 +0200 Subject: [PATCH 090/319] fix typo in response status message, fixes #858 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Admins.php | 14 ++++----- lib/Froxlor/Api/Commands/ApiKeys.php | 30 ++++++++++++++++++++ lib/Froxlor/Api/Commands/Certificates.php | 12 ++++---- lib/Froxlor/Api/Commands/Cronjobs.php | 8 +++--- lib/Froxlor/Api/Commands/CustomerBackups.php | 8 +++--- lib/Froxlor/Api/Commands/Customers.php | 16 +++++------ lib/Froxlor/Api/Commands/DirOptions.php | 12 ++++---- lib/Froxlor/Api/Commands/DirProtections.php | 12 ++++---- lib/Froxlor/Api/Commands/DomainZones.php | 12 ++++---- lib/Froxlor/Api/Commands/Domains.php | 12 ++++---- lib/Froxlor/Api/Commands/EmailAccounts.php | 6 ++-- lib/Froxlor/Api/Commands/EmailForwarders.php | 8 +++--- lib/Froxlor/Api/Commands/Emails.php | 12 ++++---- lib/Froxlor/Api/Commands/FpmDaemons.php | 12 ++++---- lib/Froxlor/Api/Commands/Froxlor.php | 22 +++++++------- lib/Froxlor/Api/Commands/Ftps.php | 12 ++++---- lib/Froxlor/Api/Commands/HostingPlans.php | 12 ++++---- lib/Froxlor/Api/Commands/IpsAndPorts.php | 12 ++++---- lib/Froxlor/Api/Commands/Mysqls.php | 12 ++++---- lib/Froxlor/Api/Commands/PhpSettings.php | 12 ++++---- lib/Froxlor/Api/Commands/SubDomains.php | 12 ++++---- lib/Froxlor/Api/Commands/SysLog.php | 6 ++-- lib/Froxlor/Api/Commands/Traffic.php | 2 +- 23 files changed, 153 insertions(+), 123 deletions(-) create mode 100644 lib/Froxlor/Api/Commands/ApiKeys.php diff --git a/lib/Froxlor/Api/Commands/Admins.php b/lib/Froxlor/Api/Commands/Admins.php index dec4d09f..b833290c 100644 --- a/lib/Froxlor/Api/Commands/Admins.php +++ b/lib/Froxlor/Api/Commands/Admins.php @@ -51,7 +51,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { $result[] = $row; } - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($result), 'list' => $result )); @@ -75,7 +75,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt "); $result = Database::pexecute_first($result_stmt, null, true, true); if ($result) { - return $this->response(200, "successfull", $result['num_admins']); + return $this->response(200, "successful", $result['num_admins']); } } throw new \Exception("Not allowed to execute given command.", 403); @@ -109,7 +109,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $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(200, "successfull", $result); + return $this->response(200, "successful", $result); } $key = ($id > 0 ? "id #" . $id : "loginname '" . $loginname . "'"); throw new \Exception("Admin with " . $key . " could not be found", 404); @@ -364,7 +364,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $result = $this->apiCall('Admins.get', array( 'id' => $adminid )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } } throw new \Exception("Not allowed to execute given command.", 403); @@ -677,7 +677,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $result = $this->apiCall('Admins.get', array( 'id' => $result['adminid'] )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } } } @@ -779,7 +779,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted admin '" . $result['loginname'] . "'"); \Froxlor\User::updateCounters(); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("Not allowed to execute given command.", 403); } @@ -821,7 +821,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $result['loginfail_count'] = 0; $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] unlocked admin '" . $result['loginname'] . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } 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 new file mode 100644 index 00000000..971d92d3 --- /dev/null +++ b/lib/Froxlor/Api/Commands/ApiKeys.php @@ -0,0 +1,30 @@ + (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package API + * @since 0.10.0 + * + */ +class ApiKeys extends \Froxlor\Api\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 cf216186..ee79ab74 100644 --- a/lib/Froxlor/Api/Commands/Certificates.php +++ b/lib/Froxlor/Api/Commands/Certificates.php @@ -81,7 +81,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou $result = $this->apiCall('Certificates.get', array( 'id' => $domain['id'] )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("Domain '" . $domain['domain'] . "' already has a certificate. Did you mean to call update?", 406); } @@ -122,7 +122,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou if (! $result) { throw new \Exception("Domain '" . $domain['domain'] . "' does not have a certificate.", 412); } - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } /** @@ -168,7 +168,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou $result = $this->apiCall('Certificates.get', array( 'id' => $domain['id'] )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } /** @@ -222,7 +222,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou } $result[] = $cert; } - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($result), 'list' => $result )); @@ -258,7 +258,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou $certs_stmt = Database::prepare($certs_stmt_query); $result = Database::pexecute_first($certs_stmt, $qry_params, true, true); if ($result) { - return $this->response(200, "successfull", $result['num_certs']); + return $this->response(200, "successful", $result['num_certs']); } } @@ -326,7 +326,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou \Froxlor\System\Cronjob::inserttask('12', $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(200, "successfull", $result); + return $this->response(200, "successful", $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 99674501..d6bd7889 100644 --- a/lib/Froxlor/Api/Commands/Cronjobs.php +++ b/lib/Froxlor/Api/Commands/Cronjobs.php @@ -51,7 +51,7 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE 'id' => $id ), true, true); if ($result) { - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("cronjob with id #" . $id . " could not be found", 404); } @@ -119,7 +119,7 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE $result = $this->apiCall('Cronjobs.get', array( 'id' => $id )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("Not allowed to execute given command.", 403); } @@ -152,7 +152,7 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { $result[] = $row; } - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($result), 'list' => $result )); @@ -175,7 +175,7 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE "); $result = Database::pexecute_first($result_stmt, null, true, true); if ($result) { - return $this->response(200, "successfull", $result['num_crons']); + return $this->response(200, "successful", $result['num_crons']); } } throw new \Exception("Not allowed to execute given command.", 403); diff --git a/lib/Froxlor/Api/Commands/CustomerBackups.php b/lib/Froxlor/Api/Commands/CustomerBackups.php index 19f7b4ac..b5ebf5cf 100644 --- a/lib/Froxlor/Api/Commands/CustomerBackups.php +++ b/lib/Froxlor/Api/Commands/CustomerBackups.php @@ -109,7 +109,7 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re \Froxlor\System\Cronjob::inserttask('20', $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); - return $this->response(200, "successfull", $task_data); + return $this->response(200, "successful", $task_data); } /** @@ -168,7 +168,7 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re } } $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list customer-backups"); - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($result), 'list' => $result )); @@ -202,7 +202,7 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re $result_count ++; } } - return $this->response(200, "successfull", $result_count); + return $this->response(200, "successful", $result_count); } /** @@ -237,7 +237,7 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re '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); - return $this->response(200, "successfull", true); + return $this->response(200, "successful", true); } } } diff --git a/lib/Froxlor/Api/Commands/Customers.php b/lib/Froxlor/Api/Commands/Customers.php index 97c31225..ee747ef6 100644 --- a/lib/Froxlor/Api/Commands/Customers.php +++ b/lib/Froxlor/Api/Commands/Customers.php @@ -60,7 +60,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { $result[] = $row; } - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($result), 'list' => $result )); @@ -90,7 +90,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource } $result = Database::pexecute_first($result_stmt, $params, true, true); if ($result) { - return $this->response(200, "successfull", $result['num_customers']); + return $this->response(200, "successful", $result['num_customers']); } } throw new \Exception("Not allowed to execute given command.", 403); @@ -143,7 +143,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $result['custom_notes'] = ""; } $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get customer '" . $result['loginname'] . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } $key = ($id > 0 ? "id #" . $id : "loginname '" . $loginname . "'"); throw new \Exception("Customer with " . $key . " could not be found", 404); @@ -743,7 +743,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $result = $this->apiCall('Customers.get', array( 'loginname' => $loginname )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("No more resources available", 406); } @@ -1340,7 +1340,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $result = $this->apiCall('Customers.get', array( 'id' => $result['customerid'] )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } /** @@ -1573,7 +1573,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource \Froxlor\System\Cronjob::inserttask('10'); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted customer '" . $result['loginname'] . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("Not allowed to execute given command.", 403); } @@ -1615,7 +1615,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $result['loginfail_count'] = 0; $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] unlocked customer '" . $result['loginname'] . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("Not allowed to execute given command.", 403); } @@ -1685,7 +1685,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $result = $this->apiCall('Customers.get', array( 'id' => $c_result['customerid'] )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } 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 6da29a4c..b7ddeb90 100644 --- a/lib/Froxlor/Api/Commands/DirOptions.php +++ b/lib/Froxlor/Api/Commands/DirOptions.php @@ -128,7 +128,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $result = $this->apiCall('DirOptions.get', array( 'id' => $id )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } /** @@ -186,7 +186,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $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'] . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } $key = "id #" . $id; throw new \Exception("Directory option with " . $key . " could not be found", 404); @@ -275,7 +275,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $result = $this->apiCall('DirOptions.get', array( 'id' => $id )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } /** @@ -315,7 +315,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $result[] = $row; } $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list directory-options"); - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($result), 'list' => $result )); @@ -347,7 +347,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc "); $result = Database::pexecute_first($result_stmt, null, true, true); if ($result) { - return $this->response(200, "successfull", $result['num_htaccess']); + return $this->response(200, "successful", $result['num_htaccess']); } } @@ -414,7 +414,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc ), 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('1'); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } /** diff --git a/lib/Froxlor/Api/Commands/DirProtections.php b/lib/Froxlor/Api/Commands/DirProtections.php index 04b48e69..93959d59 100644 --- a/lib/Froxlor/Api/Commands/DirProtections.php +++ b/lib/Froxlor/Api/Commands/DirProtections.php @@ -111,7 +111,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res $result = $this->apiCall('DirProtections.get', array( 'id' => $id )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } /** @@ -173,7 +173,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res $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'] . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } $key = ($id > 0 ? "id #" . $id : "username '" . $username . "'"); throw new \Exception("Directory protection with " . $key . " could not be found", 404); @@ -258,7 +258,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res $result = $this->apiCall('DirProtections.get', array( 'id' => $result['id'] )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } /** @@ -298,7 +298,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res $result[] = $row; } $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list directory-protections"); - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($result), 'list' => $result )); @@ -330,7 +330,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res "); $result = Database::pexecute_first($result_stmt, null, true, true); if ($result) { - return $this->response(200, "successfull", $result['num_htpasswd']); + return $this->response(200, "successful", $result['num_htpasswd']); } } @@ -386,6 +386,6 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res $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('1'); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } } diff --git a/lib/Froxlor/Api/Commands/DomainZones.php b/lib/Froxlor/Api/Commands/DomainZones.php index 303be716..f643306a 100644 --- a/lib/Froxlor/Api/Commands/DomainZones.php +++ b/lib/Froxlor/Api/Commands/DomainZones.php @@ -309,7 +309,7 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $result = $this->apiCall('DomainZones.get', array( 'id' => $id )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } // return $errors throw new \Exception(implode("\n", $errors)); @@ -360,7 +360,7 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $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'] . "'"); - return $this->response(200, "successfull", explode("\n", $zonefile)); + return $this->response(200, "successful", explode("\n", $zonefile)); } /** @@ -420,7 +420,7 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour while ($row = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) { $result[] = $row; } - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($result), 'list' => $result )); @@ -464,7 +464,7 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour 'did' => $id ), true, true); if ($result) { - return $this->response(200, "successfull", $result['num_dns']); + return $this->response(200, "successful", $result['num_dns']); } } @@ -511,8 +511,8 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour if ($del_stmt->rowCount() > 0) { // re-generate bind configs \Froxlor\System\Cronjob::inserttask('4'); - return $this->response(200, "successfull", true); + return $this->response(200, "successful", true); } - return $this->response(304, "successfull", true); + return $this->response(304, "successful", true); } } diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php index bc572b3c..b87c10d5 100644 --- a/lib/Froxlor/Api/Commands/Domains.php +++ b/lib/Froxlor/Api/Commands/Domains.php @@ -68,7 +68,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn } $result[] = $row; } - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($result), 'list' => $result )); @@ -100,7 +100,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn } $result = Database::pexecute_first($result_stmt, $params, true, true); if ($result) { - return $this->response(200, "successfull", $result['num_domains']); + return $this->response(200, "successful", $result['num_domains']); } } throw new \Exception("Not allowed to execute given command.", 403); @@ -156,7 +156,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $result['ipsandports'] = $this->getIpsForDomain($result['id']); } $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get domain '" . $result['domain'] . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } $key = ($id > 0 ? "id #" . $id : "domainname '" . $domainname . "'"); throw new \Exception("Domain with " . $key . " could not be found", 404); @@ -828,7 +828,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $result = $this->apiCall('Domains.get', array( 'domainname' => $domain )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } } throw new \Exception("No more resources available", 406); @@ -1766,7 +1766,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $idna_convert = new \Froxlor\Idna\IdnaWrapper(); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] updated domain '" . $idna_convert->decode($result['domain']) . "'"); - return $this->response(200, "successfull", $update_data); + return $this->response(200, "successful", $update_data); } throw new \Exception("Not allowed to execute given command.", 403); } @@ -1927,7 +1927,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn \Froxlor\System\Cronjob::inserttask('1'); // Using nameserver, insert a task which rebuilds the server config \Froxlor\System\Cronjob::inserttask('4'); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } 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 d9396ee2..4a7b75b4 100644 --- a/lib/Froxlor/Api/Commands/EmailAccounts.php +++ b/lib/Froxlor/Api/Commands/EmailAccounts.php @@ -273,7 +273,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso $result = $this->apiCall('Emails.get', array( 'emailaddr' => $result['email_full'] )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("No more resources available", 406); } @@ -389,7 +389,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso $result = $this->apiCall('Emails.get', array( 'emailaddr' => $result['email_full'] )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } /** @@ -492,6 +492,6 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso 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'] . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } } diff --git a/lib/Froxlor/Api/Commands/EmailForwarders.php b/lib/Froxlor/Api/Commands/EmailForwarders.php index af344a67..d01094d8 100644 --- a/lib/Froxlor/Api/Commands/EmailForwarders.php +++ b/lib/Froxlor/Api/Commands/EmailForwarders.php @@ -102,7 +102,7 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re $result = $this->apiCall('Emails.get', array( 'emailaddr' => $result['email_full'] )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("No more resources available", 406); } @@ -168,7 +168,7 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re ]; } - return $this->response(200, "successfull", [ + return $this->response(200, "successful", [ 'count' => count($destination), 'list' => $destination ]); @@ -210,7 +210,7 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re $result['destination'] = explode(' ', $result['destination']); - return $this->response(200, "successfull", count($result['destination'])); + return $this->response(200, "successful", count($result['destination'])); } /** @@ -280,7 +280,7 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re $result = $this->apiCall('Emails.get', array( 'emailaddr' => $result['email_full'] )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("Unknown forwarder id", 404); } diff --git a/lib/Froxlor/Api/Commands/Emails.php b/lib/Froxlor/Api/Commands/Emails.php index c22989c8..c3120fe7 100644 --- a/lib/Froxlor/Api/Commands/Emails.php +++ b/lib/Froxlor/Api/Commands/Emails.php @@ -140,7 +140,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $result = $this->apiCall('Emails.get', array( 'emailaddr' => $email_full )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("No more resources available", 406); } @@ -176,7 +176,7 @@ 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'] . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } $key = ($id > 0 ? "id #" . $id : "emailaddr '" . $emailaddr . "'"); throw new \Exception("Email address with " . $key . " could not be found", 404); @@ -271,7 +271,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $result = $this->apiCall('Emails.get', array( 'emailaddr' => $result['email_full'] )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } /** @@ -310,7 +310,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $result[] = $row; } $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list email-addresses"); - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($result), 'list' => $result )); @@ -340,7 +340,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt "); $result = Database::pexecute_first($result_stmt, null, true, true); if ($result) { - return $this->response(200, "successfull", $result['num_emails']); + return $this->response(200, "successful", $result['num_emails']); } } @@ -418,6 +418,6 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt 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'] . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } } diff --git a/lib/Froxlor/Api/Commands/FpmDaemons.php b/lib/Froxlor/Api/Commands/FpmDaemons.php index 09ef8091..ba757dc0 100644 --- a/lib/Froxlor/Api/Commands/FpmDaemons.php +++ b/lib/Froxlor/Api/Commands/FpmDaemons.php @@ -70,7 +70,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $fpmdaemons[] = $row; } - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($fpmdaemons), 'list' => $fpmdaemons )); @@ -93,7 +93,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc "); $result = Database::pexecute_first($result_stmt, null, true, true); if ($result) { - return $this->response(200, "successfull", $result['num_fpms']); + return $this->response(200, "successful", $result['num_fpms']); } } throw new \Exception("Not allowed to execute given command.", 403); @@ -121,7 +121,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc 'id' => $id ), true, true); if ($result) { - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("fpm-daemon with id #" . $id . " could not be found", 404); } @@ -234,7 +234,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $result = $this->apiCall('FpmDaemons.get', array( 'id' => $id )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("Not allowed to execute given command.", 403); } @@ -356,7 +356,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $result = $this->apiCall('FpmDaemons.get', array( 'id' => $id )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("Not allowed to execute given command.", 403); } @@ -402,7 +402,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc \Froxlor\System\Cronjob::inserttask('1'); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] fpm-daemon setting '" . $result['description'] . "' has been deleted by '" . $this->getUserDetail('loginname') . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } 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 080676d6..78c772c9 100644 --- a/lib/Froxlor/Api/Commands/Froxlor.php +++ b/lib/Froxlor/Api/Commands/Froxlor.php @@ -74,7 +74,7 @@ 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(200, "successfull", array( + return $this->response(200, "successful", array( 'isnewerversion' => $isnewerversion, 'version' => $_version, 'message' => $text, @@ -83,7 +83,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand )); } elseif ($isnewerversion == 0) { // all good - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'isnewerversion' => $isnewerversion, 'version' => $version_label, 'message' => "", @@ -95,7 +95,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand } } } - return $this->response(300, "successfull", array( + return $this->response(300, "successful", array( 'isnewerversion' => 0, 'version' => $this->version . $this->branding, 'message' => 'Version-check not available due to missing php-curl extension', @@ -129,7 +129,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand \Froxlor\System\Cronjob::inserttask('4'); // cron.d file \Froxlor\System\Cronjob::inserttask('99'); - return $this->response(200, "successfull", true); + return $this->response(200, "successful", true); } catch (\Exception $e) { throw new \Exception($e->getMessage(), 406); } @@ -149,7 +149,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand 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(); - return $this->response(200, "successfull", $json_export); + return $this->response(200, "successful", $json_export); } throw new \Exception("Not allowed to execute given command.", 403); } @@ -175,7 +175,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand 'value' => $row['value'] ); } - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($result), 'list' => $result )); @@ -197,7 +197,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand { if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) { $setting = $this->getParam('key'); - return $this->response(200, "successfull", Settings::Get($setting)); + return $this->response(200, "successful", Settings::Get($setting)); } throw new \Exception("Not allowed to execute given command.", 403); } @@ -227,7 +227,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand 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 . "'"); - return $this->response(200, "successfull", Settings::Set($setting, $value, true)); + return $this->response(200, "successful", Settings::Set($setting, $value, true)); } throw new \Exception("Not allowed to execute given command.", 403); } @@ -240,7 +240,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand */ public function generatePassword() { - return $this->response(200, "successfull", \Froxlor\System\Crypt::generatePassword()); + return $this->response(200, "successful", \Froxlor\System\Crypt::generatePassword()); } /** @@ -256,7 +256,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand $integrity = new \Froxlor\Database\IntegrityCheck(); $result = $integrity->checkAll(); if ($result) { - return $this->response(200, "successfull", "OK"); + return $this->response(200, "successful", "OK"); } throw new \Exception("Some checks failed.", 406); } @@ -333,7 +333,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand } // return the list - return $this->response(200, "successfull", $functions); + return $this->response(200, "successful", $functions); } /** diff --git a/lib/Froxlor/Api/Commands/Ftps.php b/lib/Froxlor/Api/Commands/Ftps.php index 6123796a..056c43bf 100644 --- a/lib/Froxlor/Api/Commands/Ftps.php +++ b/lib/Froxlor/Api/Commands/Ftps.php @@ -268,7 +268,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit $result = $this->apiCall('Ftps.get', array( 'username' => $username )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } } throw new \Exception("No more resources available", 406); @@ -329,7 +329,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit $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'] . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } $key = ($id > 0 ? "id #" . $id : "username '" . $username . "'"); throw new \Exception("FTP user with " . $key . " could not be found", 404); @@ -454,7 +454,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit 'username' => $result['username'] )); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] updated ftp-user '" . $result['username'] . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } /** @@ -490,7 +490,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit $result[] = $row; } $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list ftp-users"); - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($result), 'list' => $result )); @@ -518,7 +518,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit "); $result = Database::pexecute_first($result_stmt, null, true, true); if ($result) { - return $this->response(200, "successfull", $result['num_ftps']); + return $this->response(200, "successful", $result['num_ftps']); } } @@ -626,6 +626,6 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit 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'] . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } } diff --git a/lib/Froxlor/Api/Commands/HostingPlans.php b/lib/Froxlor/Api/Commands/HostingPlans.php index a8070198..ca3a76bc 100644 --- a/lib/Froxlor/Api/Commands/HostingPlans.php +++ b/lib/Froxlor/Api/Commands/HostingPlans.php @@ -57,7 +57,7 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { $result[] = $row; } - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($result), 'list' => $result )); @@ -85,7 +85,7 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou } $result = Database::pexecute_first($result_stmt, $params, true, true); if ($result) { - return $this->response(200, "successfull", $result['num_plans']); + return $this->response(200, "successful", $result['num_plans']); } } throw new \Exception("Not allowed to execute given command.", 403); @@ -120,7 +120,7 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou $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(200, "successfull", $result); + return $this->response(200, "successful", $result); } $key = ($id > 0 ? "id #" . $id : "planname '" . $planname . "'"); throw new \Exception("Hosting-plan with " . $key . " could not be found", 404); @@ -246,7 +246,7 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou $result = $this->apiCall('HostingPlans.get', array( 'planname' => $name )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("Not allowed to execute given command.", 403); } @@ -393,7 +393,7 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou ); Database::pexecute($upd_stmt, $update_data, true, true); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] updated hosting-plan '" . $result['name'] . "'"); - return $this->response(200, "successfull", $update_data); + return $this->response(200, "successful", $update_data); } throw new \Exception("Not allowed to execute given command.", 403); } @@ -431,7 +431,7 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou 'id' => $id ), true, true); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted hosting-plan '" . $result['name'] . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } 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 e9492132..adfe2965 100644 --- a/lib/Froxlor/Api/Commands/IpsAndPorts.php +++ b/lib/Froxlor/Api/Commands/IpsAndPorts.php @@ -56,7 +56,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { $result[] = $row; } - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($result), 'list' => $result )); @@ -82,7 +82,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour SELECT COUNT(*) as num_ips FROM `" . TABLE_PANEL_IPSANDPORTS . "` " . $ip_where); $result = Database::pexecute_first($result_stmt, null, true, true); if ($result) { - return $this->response(200, "successfull", $result['num_ips']); + return $this->response(200, "successful", $result['num_ips']); } } throw new \Exception("Not allowed to execute given command.", 403); @@ -116,7 +116,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour ), true, true); if ($result) { $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get ip " . $result['ip'] . " " . $result['port']); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("IP/port with id #" . $id . " could not be found", 404); } @@ -307,7 +307,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $result = $this->apiCall('IpsAndPorts.get', array( 'id' => $ins_data['id'] )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("Not allowed to execute given command.", 403); } @@ -514,7 +514,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $result = $this->apiCall('IpsAndPorts.get', array( 'id' => $result['id'] )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } } throw new \Exception("Not allowed to execute given command.", 403); @@ -583,7 +583,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour \Froxlor\System\Cronjob::inserttask('4'); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted IP/port '" . $result['ip'] . ":" . $result['port'] . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } else { \Froxlor\UI\Response::standard_error('cantdeletesystemip', '', true); } diff --git a/lib/Froxlor/Api/Commands/Mysqls.php b/lib/Froxlor/Api/Commands/Mysqls.php index 417e13ed..6ad4e1f8 100644 --- a/lib/Froxlor/Api/Commands/Mysqls.php +++ b/lib/Froxlor/Api/Commands/Mysqls.php @@ -169,7 +169,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $result = $this->apiCall('Mysqls.get', array( 'dbname' => $username )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } /** @@ -258,7 +258,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt 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'] . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } $key = ($id > 0 ? "id #" . $id : "dbname '" . $dbname . "'"); throw new \Exception("MySQL database with " . $key . " could not be found", 404); @@ -350,7 +350,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $result = $this->apiCall('Mysqls.get', array( 'dbname' => $result['databasename'] )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } /** @@ -421,7 +421,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt Database::needRoot(false); } } - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($result), 'list' => $result )); @@ -448,7 +448,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt "); $result = Database::pexecute_first($result_stmt, null, true, true); if ($result) { - return $this->response(200, "successfull", $result['num_dbs']); + return $this->response(200, "successful", $result['num_dbs']); } } @@ -510,6 +510,6 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt 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'] . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } } diff --git a/lib/Froxlor/Api/Commands/PhpSettings.php b/lib/Froxlor/Api/Commands/PhpSettings.php index a77d8e02..002ebbca 100644 --- a/lib/Froxlor/Api/Commands/PhpSettings.php +++ b/lib/Froxlor/Api/Commands/PhpSettings.php @@ -113,7 +113,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $phpconfigs[] = $row; } - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($phpconfigs), 'list' => $phpconfigs )); @@ -137,7 +137,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour "); $result = Database::pexecute_first($result_stmt, null, true, true); if ($result) { - return $this->response(200, "successfull", $result['num_phps']); + return $this->response(200, "successful", $result['num_phps']); } } throw new \Exception("Not allowed to execute given command.", 403); @@ -165,7 +165,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour 'id' => $id ), true, true); if ($result) { - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("php-config with id #" . $id . " could not be found", 404); } @@ -367,7 +367,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $result = $this->apiCall('PhpSettings.get', array( 'id' => $ins_data['id'] )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("Not allowed to execute given command.", 403); } @@ -563,7 +563,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $result = $this->apiCall('PhpSettings.get', array( 'id' => $id )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("Not allowed to execute given command.", 403); } @@ -614,7 +614,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour \Froxlor\System\Cronjob::inserttask('1'); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] php setting '" . $result['description'] . "' has been deleted by '" . $this->getUserDetail('loginname') . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } 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 3b7fbfb7..e4bee37f 100644 --- a/lib/Froxlor/Api/Commands/SubDomains.php +++ b/lib/Froxlor/Api/Commands/SubDomains.php @@ -345,7 +345,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $result = $this->apiCall('SubDomains.get', array( 'id' => $subdomain_id )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } throw new \Exception("No more resources available", 406); } @@ -426,7 +426,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $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'] . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } $key = ($id > 0 ? "id #" . $id : "domainname '" . $domainname . "'"); throw new \Exception("Subdomain with " . $key . " could not be found", 404); @@ -693,7 +693,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $result = $this->apiCall('SubDomains.get', array( 'id' => $id )); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } /** @@ -797,7 +797,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc while ($row = $domains_stmt->fetch(\PDO::FETCH_ASSOC)) { $result[] = $row; } - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($result), 'list' => $result )); @@ -862,7 +862,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc "); $result = Database::pexecute_first($domains_stmt, null, true, true); if ($result) { - return $this->response(200, "successfull", $result['num_subdom']); + return $this->response(200, "successful", $result['num_subdom']); } } @@ -976,7 +976,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc 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'] . "'"); - return $this->response(200, "successfull", $result); + return $this->response(200, "successful", $result); } /** diff --git a/lib/Froxlor/Api/Commands/SysLog.php b/lib/Froxlor/Api/Commands/SysLog.php index c19d6e75..9e744827 100644 --- a/lib/Froxlor/Api/Commands/SysLog.php +++ b/lib/Froxlor/Api/Commands/SysLog.php @@ -74,7 +74,7 @@ class SysLog extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $result[] = $row; } $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list log-entries"); - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($result), 'list' => $result )); @@ -129,7 +129,7 @@ class SysLog extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $result = Database::pexecute_first($result_stmt, $params, true, true); if ($result) { - return $this->response(200, "successfull", $result['num_logs']); + return $this->response(200, "successful", $result['num_logs']); } } @@ -204,7 +204,7 @@ 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"); - return $this->response(200, "successfull", true); + return $this->response(200, "successful", true); } 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 368c81e2..7212e3c1 100644 --- a/lib/Froxlor/Api/Commands/Traffic.php +++ b/lib/Froxlor/Api/Commands/Traffic.php @@ -110,7 +110,7 @@ class Traffic extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $result[] = $row; } $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list traffic"); - return $this->response(200, "successfull", array( + return $this->response(200, "successful", array( 'count' => count($result), 'list' => $result )); From 0398f4cdba4c4e2acc184bac4d17c432861698a7 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 12 Jun 2020 15:17:09 +0200 Subject: [PATCH 091/319] set version to 0.10.18 for upcoming release Signed-off-by: Michael Kaufmann --- .codecov.yml | 4 ---- .travis.yml | 5 +---- install/froxlor.sql | 2 +- install/updates/froxlor/0.10/update_0.10.inc.php | 5 +++++ lib/Froxlor/Froxlor.php | 2 +- 5 files changed, 8 insertions(+), 10 deletions(-) delete mode 100644 .codecov.yml diff --git a/.codecov.yml b/.codecov.yml deleted file mode 100644 index 26cec6c2..00000000 --- a/.codecov.yml +++ /dev/null @@ -1,4 +0,0 @@ -codecov: - notify: - require_ci_to_pass: no - diff --git a/.travis.yml b/.travis.yml index e058cf32..eed5b7c8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,10 +52,7 @@ install: - mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI froxlor010 < install/froxlor.sql script: - - ant phpunit - -after_success: - - bash <(curl -s https://codecov.io/bash) -f "build/logs/clover.xml" + - ant phpunit-no-coverage notifications: irc: "chat.freenode.net#froxlor" diff --git a/install/froxlor.sql b/install/froxlor.sql index 05fe3410..96a33798 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -704,7 +704,7 @@ opcache.interned_strings_buffer'), ('panel', 'password_special_char', '!?<>§$%+#=@'), ('panel', 'customer_hide_options', ''), ('panel', 'is_configured', '0'), - ('panel', 'version', '0.10.17'), + ('panel', 'version', '0.10.18'), ('panel', 'db_version', '202005150'); diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index 7cdafb40..d994c0cb 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -639,3 +639,8 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.16')) { showUpdateStep("Updating from 0.10.16 to 0.10.17", false); \Froxlor\Froxlor::updateToVersion('0.10.17'); } + +if (\Froxlor\Froxlor::isFroxlorVersion('0.10.17')) { + showUpdateStep("Updating from 0.10.17 to 0.10.18", false); + \Froxlor\Froxlor::updateToVersion('0.10.18'); +} diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index c436f2c4..1cafd44f 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -7,7 +7,7 @@ final class Froxlor { // Main version variable - const VERSION = '0.10.17'; + const VERSION = '0.10.18'; // Database version (YYYYMMDDC where C is a daily counter) const DBVERSION = '202005150'; From daa223ed4203d0829a0b6a8aad7707928316dcc2 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Wed, 17 Jun 2020 09:29:02 +0200 Subject: [PATCH 092/319] return full domain object on Domains.update() call, fixes #861 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Domains.php | 5 ++++- tests/Domains/DomainsTest.php | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php index b87c10d5..d68c0ebe 100644 --- a/lib/Froxlor/Api/Commands/Domains.php +++ b/lib/Froxlor/Api/Commands/Domains.php @@ -1766,7 +1766,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $idna_convert = new \Froxlor\Idna\IdnaWrapper(); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] updated domain '" . $idna_convert->decode($result['domain']) . "'"); - return $this->response(200, "successful", $update_data); + $result = $this->apiCall('Domains.get', array( + 'domainname' => $result['domain'] + )); + return $this->response(200, "successful", $result); } throw new \Exception("Not allowed to execute given command.", 403); } diff --git a/tests/Domains/DomainsTest.php b/tests/Domains/DomainsTest.php index ee186835..85e0855b 100644 --- a/tests/Domains/DomainsTest.php +++ b/tests/Domains/DomainsTest.php @@ -155,6 +155,7 @@ class DomainsTest extends TestCase $json_result = Domains::getLocal($reseller_userdata, $data)->update(); $result = json_decode($json_result, true)['data']; $this->assertEmpty($result['ssl_protocols']); + $this->assertEquals('test2.local', $result['domain']); } public function testAdminDomainsAddSysHostname() @@ -206,6 +207,7 @@ class DomainsTest extends TestCase $result = json_decode($json_result, true)['data']; $this->assertEquals(1, $result['email_only']); $this->assertFalse(in_array('TLSv1.3', explode(",", $result['ssl_protocols']))); + $this->assertEquals('test.local', $result['domain']); } /** From 70677fced2316dee533a0fe2f0c54a069f1c0163 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Wed, 17 Jun 2020 12:08:54 +0200 Subject: [PATCH 093/319] fix double-adding of _ecc to certificate folder when deleting let's encrypt certificate Signed-off-by: Michael Kaufmann --- lib/Froxlor/Domain/Domain.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/Froxlor/Domain/Domain.php b/lib/Froxlor/Domain/Domain.php index 675b897f..c70c6cac 100644 --- a/lib/Froxlor/Domain/Domain.php +++ b/lib/Froxlor/Domain/Domain.php @@ -332,10 +332,6 @@ class Domain $acmesh = \Froxlor\Cron\Http\LetsEncrypt\AcmeSh::getAcmeSh(); if (file_exists($acmesh)) { $certificate_folder = \Froxlor\Cron\Http\LetsEncrypt\AcmeSh::getWorkingDirFromEnv($domainname); - if (\Froxlor\Settings::Get('system.leecc') > 0) { - $certificate_folder .= "_ecc"; - } - $certificate_folder = \Froxlor\FileDir::makeCorrectDir($certificate_folder); if (file_exists($certificate_folder)) { $params = " --remove -d " . $domainname; if (\Froxlor\Settings::Get('system.leecc') > 0) { From e733701459bc4e84322dade41becfff88b20ce6f Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Wed, 17 Jun 2020 14:09:26 +0200 Subject: [PATCH 094/319] trigger removal cronjob of lets encrypt certificate via acme.sh also when domain update removes letsencrypt flag from domain Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Domains.php | 2 ++ lib/Froxlor/Api/Commands/SubDomains.php | 2 ++ lib/Froxlor/Froxlor.php | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php index d68c0ebe..6ef2ef2d 100644 --- a/lib/Froxlor/Api/Commands/Domains.php +++ b/lib/Froxlor/Api/Commands/Domains.php @@ -1442,6 +1442,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn Database::pexecute($del_stmt, array( 'id' => $id ), true, true); + // remove domain from acme.sh / lets encrypt if used + \Froxlor\System\Cronjob::inserttask('12', $result['domain']); } $updatechildren = ''; diff --git a/lib/Froxlor/Api/Commands/SubDomains.php b/lib/Froxlor/Api/Commands/SubDomains.php index e4bee37f..b07cada7 100644 --- a/lib/Froxlor/Api/Commands/SubDomains.php +++ b/lib/Froxlor/Api/Commands/SubDomains.php @@ -683,6 +683,8 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc Database::pexecute($del_stmt, array( 'id' => $id ), true, true); + // remove domain from acme.sh / lets encrypt if used + \Froxlor\System\Cronjob::inserttask('12', $result['domain']); } \Froxlor\System\Cronjob::inserttask('1'); diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index 1cafd44f..e7b5834f 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -17,7 +17,7 @@ final class Froxlor /** * return path to where froxlor is installed, e.g. - * /var/www/froxlor + * /var/www/froxlor/ * * @return string */ From 35a69fbfe0930bb33f0f52fa2f327b1274a50644 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Thu, 18 Jun 2020 13:05:17 +0200 Subject: [PATCH 095/319] add missing parmeter customerid for SubDomains.delete() which is required when called as admin; fixes #862 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/SubDomains.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Froxlor/Api/Commands/SubDomains.php b/lib/Froxlor/Api/Commands/SubDomains.php index b07cada7..968e286b 100644 --- a/lib/Froxlor/Api/Commands/SubDomains.php +++ b/lib/Froxlor/Api/Commands/SubDomains.php @@ -875,7 +875,9 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc * optional, the domain-id * @param string $domainname * optional, the domainname - * + * @param int $customerid + * required when called as admin, not needed when called as customer + * * @access admin, customer * @throws \Exception * @return string json-encoded array From d653f6842f747921c432d341dfafe551a187123c Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 21 Jun 2020 19:50:46 +0200 Subject: [PATCH 096/319] check for acme.sh upgrade on every run; fix not running --install-cronjob without having an issue command Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index e29dbbc2..357c893d 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -44,8 +44,6 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron */ private static $upddom_stmt = null; - private static $do_update = true; - public static $no_inserttask = false; /** @@ -77,6 +75,8 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron return - 1; } + self::checkUpgrade(); + // flag for re-generation of vhost files $changedetected = 0; @@ -291,12 +291,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron { if (! empty($domains)) { - if (self::$do_update) { - self::checkUpgrade(); - self::$do_update = false; - } - - $acmesh_cmd = self::$acmesh . " --auto-upgrade 0 --server " . self::$apiserver . " --issue -d " . implode(" -d ", $domains); + $acmesh_cmd = self::$acmesh . " --server " . self::$apiserver . " --issue -d " . implode(" -d ", $domains); // challenge path $acmesh_cmd .= " -w " . Settings::Get('system.letsencryptchallengepath'); if (Settings::Get('system.leecc') > 0) { @@ -598,7 +593,7 @@ EOC; */ private static function checkUpgrade() { - $acmesh_result = \Froxlor\FileDir::safe_exec(self::$acmesh . " --upgrade"); + $acmesh_result = \Froxlor\FileDir::safe_exec(self::$acmesh . " --upgrade --auto-upgrade 0"); // check for activated cron $acmesh_result2 = \Froxlor\FileDir::safe_exec(self::$acmesh . " --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)); From 7c3ff95d221ea699541a2918b4748fc53fae4d62 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Tue, 23 Jun 2020 09:39:00 +0200 Subject: [PATCH 097/319] check for possible CNAME overrides of A/AAAA record in dns-editor, fixes #864 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Dns/Dns.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/Froxlor/Dns/Dns.php b/lib/Froxlor/Dns/Dns.php index ba8518a9..8d0b329c 100644 --- a/lib/Froxlor/Dns/Dns.php +++ b/lib/Froxlor/Dns/Dns.php @@ -168,6 +168,13 @@ class Dns // use the first NS entry as primary ns $primary_ns = $entry['content']; } + // check for CNAME on @, www- or wildcard-Alias and remove A/AAAA record accordingly + foreach (['@', 'www', '*'] as $crceord) { + if ($entry['type'] == 'CNAME' && $entry['record'] == '@' && (array_key_exists(md5($crceord), $required_entries['A']) || array_key_exists(md5($crceord), $required_entries['AAAA']))) { + unset($required_entries['A'][md5($crceord)]); + unset($required_entries['AAAA'][md5($crceord)]); + } + } $zonerecords[] = new DnsEntry($entry['record'], $entry['type'], $entry['content'], $entry['prio'], $entry['ttl']); } From a141c83ad48191a5460c14a6098b5f18ae49b473 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Tue, 23 Jun 2020 20:35:50 +0200 Subject: [PATCH 098/319] do not call strtotime on the validTo_time_t key of cert_data as it already is an UNIX-timestamp, refs #865 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index 357c893d..aeeb3a32 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -491,7 +491,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron if (is_dir($certificate_folder) && file_exists($ssl_file) && is_readable($ssl_file)) { $cert_data = openssl_x509_parse(file_get_contents($ssl_file)); - if (strtotime($cert_data['validTo_time_t']) > strtotime($cert_date)) { + if ($cert_data['validTo_time_t'] > strtotime($cert_date)) { return true; } } From 37176c94a132b7f84dc33433ae7bf3265295b247 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 3 Jul 2020 14:12:48 +0200 Subject: [PATCH 099/319] set version to 0.10.19 for upcoming release Signed-off-by: Michael Kaufmann --- install/froxlor.sql | 2 +- install/updates/froxlor/0.10/update_0.10.inc.php | 5 +++++ lib/Froxlor/Froxlor.php | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index 96a33798..6fc93163 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -704,7 +704,7 @@ opcache.interned_strings_buffer'), ('panel', 'password_special_char', '!?<>§$%+#=@'), ('panel', 'customer_hide_options', ''), ('panel', 'is_configured', '0'), - ('panel', 'version', '0.10.18'), + ('panel', 'version', '0.10.19'), ('panel', 'db_version', '202005150'); diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index d994c0cb..d17f4bdb 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -644,3 +644,8 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.17')) { showUpdateStep("Updating from 0.10.17 to 0.10.18", false); \Froxlor\Froxlor::updateToVersion('0.10.18'); } + +if (\Froxlor\Froxlor::isFroxlorVersion('0.10.18')) { + showUpdateStep("Updating from 0.10.18 to 0.10.19", false); + \Froxlor\Froxlor::updateToVersion('0.10.19'); +} diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index e7b5834f..4a636eb3 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -7,7 +7,7 @@ final class Froxlor { // Main version variable - const VERSION = '0.10.18'; + const VERSION = '0.10.19'; // Database version (YYYYMMDDC where C is a daily counter) const DBVERSION = '202005150'; From 03bc94e69cf1a98dffc4e1001ae5ea0f04eb651e Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Tue, 7 Jul 2020 12:10:40 +0200 Subject: [PATCH 100/319] insert task to sync certificates for all cases (issue and renew) Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index aeeb3a32..e0e152c9 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -59,8 +59,11 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron // 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 - $needRenew = self::issueDomains(); - if ($needRenew || self::issueFroxlorVhost()) { + $issue_froxlor = self::issueFroxlorVhost(); + $issue_domains = self::issueDomains(); + $renew_froxlor = self::renewFroxlorVhost(); + $renew_domains = self::renewDomains(); + if ($issue_froxlor || $issue_domains || $renew_froxlor || $renew_domains) { // insert task to generate certificates and vhost-configs \Froxlor\System\Cronjob::inserttask(1); } From a5e6ef674f7d5829595c24171024c979fc406583 Mon Sep 17 00:00:00 2001 From: tczaude Date: Fri, 24 Jul 2020 14:35:55 +0200 Subject: [PATCH 101/319] issue 868 : Add new performerce indexes --- install/froxlor.sql | 2 +- .../updates/froxlor/0.10/update_0.10.inc.php | 17 +++++++++++++++++ lib/Froxlor/Froxlor.php | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index 6fc93163..0de23c7c 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -705,7 +705,7 @@ opcache.interned_strings_buffer'), ('panel', 'customer_hide_options', ''), ('panel', 'is_configured', '0'), ('panel', 'version', '0.10.19'), - ('panel', 'db_version', '202005150'); + ('panel', 'db_version', '202007240'); DROP TABLE IF EXISTS `panel_tasks`; diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index d17f4bdb..8980b928 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -649,3 +649,20 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.18')) { showUpdateStep("Updating from 0.10.18 to 0.10.19", false); \Froxlor\Froxlor::updateToVersion('0.10.19'); } + +if (\Froxlor\Froxlor::isDatabaseVersion('202005150')) { + showUpdateStep("Add new performerce indexes", false); + + Database::query("ALTER TABLE panel_customers ADD INDEX guid (guid);"); + Database::query("ALTER TABLE panel_tasks ADD INDEX type (type);"); + Database::query("ALTER TABLE mail_users ADD INDEX username (username);"); + Database::query("ALTER TABLE mail_users ADD INDEX imap (imap);"); + Database::query("ALTER TABLE mail_users ADD INDEX pop3 (pop3);"); + Database::query("ALTER TABLE ftp_groups ADD INDEX gid (gid);"); + Database::query("ALTER TABLE ftp_groups ADD INDEX members (members);"); + + + lastStepStatus(0); + \Froxlor\Froxlor::updateToDbVersion('202007240'); +} + diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index 4a636eb3..47593629 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -10,7 +10,7 @@ final class Froxlor const VERSION = '0.10.19'; // Database version (YYYYMMDDC where C is a daily counter) - const DBVERSION = '202005150'; + const DBVERSION = '202007240'; // Distribution branding-tag (used for Debian etc.) const BRANDING = ''; From ac5bc78e121122c496901455176c544a36d34dba Mon Sep 17 00:00:00 2001 From: tczaude Date: Fri, 24 Jul 2020 19:32:04 +0200 Subject: [PATCH 102/319] fix showUpdateStep --- install/updates/froxlor/0.10/update_0.10.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index 8980b928..fd89ba61 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -651,7 +651,7 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.18')) { } if (\Froxlor\Froxlor::isDatabaseVersion('202005150')) { - showUpdateStep("Add new performerce indexes", false); + showUpdateStep("Add new performance indexes", true); Database::query("ALTER TABLE panel_customers ADD INDEX guid (guid);"); Database::query("ALTER TABLE panel_tasks ADD INDEX type (type);"); From 665c87cca759af897eafc00097661153c2f55d26 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sat, 25 Jul 2020 17:21:13 +0200 Subject: [PATCH 103/319] fix index on longtext field which is not working due to unknown length; fixes #868 Signed-off-by: Michael Kaufmann --- install/updates/froxlor/0.10/update_0.10.inc.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index fd89ba61..1dabf720 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -651,18 +651,16 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.18')) { } if (\Froxlor\Froxlor::isDatabaseVersion('202005150')) { + showUpdateStep("Add new performance indexes", true); - Database::query("ALTER TABLE panel_customers ADD INDEX guid (guid);"); Database::query("ALTER TABLE panel_tasks ADD INDEX type (type);"); Database::query("ALTER TABLE mail_users ADD INDEX username (username);"); Database::query("ALTER TABLE mail_users ADD INDEX imap (imap);"); Database::query("ALTER TABLE mail_users ADD INDEX pop3 (pop3);"); Database::query("ALTER TABLE ftp_groups ADD INDEX gid (gid);"); - Database::query("ALTER TABLE ftp_groups ADD INDEX members (members);"); - - lastStepStatus(0); + \Froxlor\Froxlor::updateToDbVersion('202007240'); } From 0af655f10650777c31ed1cd40d059d08cf79b466 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sat, 25 Jul 2020 17:21:52 +0200 Subject: [PATCH 104/319] fix permanent rebuilding of vhost configs due to always-true renew check of let's encrypt certificates Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index e0e152c9..209e51b4 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -62,7 +62,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron $issue_froxlor = self::issueFroxlorVhost(); $issue_domains = self::issueDomains(); $renew_froxlor = self::renewFroxlorVhost(); - $renew_domains = self::renewDomains(); + $renew_domains = self::renewDomains(true); if ($issue_froxlor || $issue_domains || $renew_froxlor || $renew_domains) { // insert task to generate certificates and vhost-configs \Froxlor\System\Cronjob::inserttask(1); @@ -409,7 +409,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron /** * get a list of domains that have a lets encrypt certificate (possible renew) */ - private static function renewDomains() + private static function renewDomains($check = false) { $certificates_stmt = Database::query(" SELECT @@ -437,6 +437,13 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron "); $renew_certs = $certificates_stmt->fetchAll(\PDO::FETCH_ASSOC); if ($renew_certs) { + if ($check) { + foreach ($renew_certs as $cert) { + if (self::checkFsFilesAreNewer($cert['domain'], $cert['expirationdate'])) { + return true; + } + } + } return $renew_certs; } return array(); From 10b52486b57f88ff78db924f01fd86876f8970ad Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sat, 25 Jul 2020 17:28:46 +0200 Subject: [PATCH 105/319] ups, forgot to save the file so it's missing a critical return :P Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index 209e51b4..4b70d6ce 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -443,6 +443,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron return true; } } + return false; } return $renew_certs; } From aa1448799574f9926d6b129891d18579755ccc6c Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Tue, 28 Jul 2020 13:28:47 +0200 Subject: [PATCH 106/319] update jquery library, fixes #872 Signed-off-by: Michael Kaufmann --- js/html5shiv.min.js | 4 ++-- js/jquery.min.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/js/html5shiv.min.js b/js/html5shiv.min.js index d4c731ad..355afd10 100644 --- a/js/html5shiv.min.js +++ b/js/html5shiv.min.js @@ -1,4 +1,4 @@ /** -* @preserve HTML5 Shiv 3.7.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed +* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed */ -!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.2",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b)}(this,document); \ No newline at end of file +!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document); \ No newline at end of file diff --git a/js/jquery.min.js b/js/jquery.min.js index 4d9b3a25..d467083b 100644 --- a/js/jquery.min.js +++ b/js/jquery.min.js @@ -1,2 +1,2 @@ -/*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){"use strict";var n=[],r=e.document,i=Object.getPrototypeOf,o=n.slice,a=n.concat,s=n.push,u=n.indexOf,l={},c=l.toString,f=l.hasOwnProperty,p=f.toString,d=p.call(Object),h={},g=function e(t){return"function"==typeof t&&"number"!=typeof t.nodeType},y=function e(t){return null!=t&&t===t.window},v={type:!0,src:!0,noModule:!0};function m(e,t,n){var i,o=(t=t||r).createElement("script");if(o.text=e,n)for(i in v)n[i]&&(o[i]=n[i]);t.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[c.call(e)]||"object":typeof e}var b="3.3.1",w=function(e,t){return new w.fn.init(e,t)},T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;w.fn=w.prototype={jquery:"3.3.1",constructor:w,length:0,toArray:function(){return o.call(this)},get:function(e){return null==e?o.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=w.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return w.each(this,e)},map:function(e){return this.pushStack(w.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(o.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n0&&t-1 in e)}var E=function(e){var t,n,r,i,o,a,s,u,l,c,f,p,d,h,g,y,v,m,x,b="sizzle"+1*new Date,w=e.document,T=0,C=0,E=ae(),k=ae(),S=ae(),D=function(e,t){return e===t&&(f=!0),0},N={}.hasOwnProperty,A=[],j=A.pop,q=A.push,L=A.push,H=A.slice,O=function(e,t){for(var n=0,r=e.length;n+~]|"+M+")"+M+"*"),z=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),X=new RegExp(W),U=new RegExp("^"+R+"$"),V={ID:new RegExp("^#("+R+")"),CLASS:new RegExp("^\\.("+R+")"),TAG:new RegExp("^("+R+"|[*])"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+W),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+P+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},G=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Q=/^[^{]+\{\s*\[native \w/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,K=/[+~]/,Z=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ee=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},te=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ne=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},re=function(){p()},ie=me(function(e){return!0===e.disabled&&("form"in e||"label"in e)},{dir:"parentNode",next:"legend"});try{L.apply(A=H.call(w.childNodes),w.childNodes),A[w.childNodes.length].nodeType}catch(e){L={apply:A.length?function(e,t){q.apply(e,H.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function oe(e,t,r,i){var o,s,l,c,f,h,v,m=t&&t.ownerDocument,T=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==T&&9!==T&&11!==T)return r;if(!i&&((t?t.ownerDocument||t:w)!==d&&p(t),t=t||d,g)){if(11!==T&&(f=J.exec(e)))if(o=f[1]){if(9===T){if(!(l=t.getElementById(o)))return r;if(l.id===o)return r.push(l),r}else if(m&&(l=m.getElementById(o))&&x(t,l)&&l.id===o)return r.push(l),r}else{if(f[2])return L.apply(r,t.getElementsByTagName(e)),r;if((o=f[3])&&n.getElementsByClassName&&t.getElementsByClassName)return L.apply(r,t.getElementsByClassName(o)),r}if(n.qsa&&!S[e+" "]&&(!y||!y.test(e))){if(1!==T)m=t,v=e;else if("object"!==t.nodeName.toLowerCase()){(c=t.getAttribute("id"))?c=c.replace(te,ne):t.setAttribute("id",c=b),s=(h=a(e)).length;while(s--)h[s]="#"+c+" "+ve(h[s]);v=h.join(","),m=K.test(e)&&ge(t.parentNode)||t}if(v)try{return L.apply(r,m.querySelectorAll(v)),r}catch(e){}finally{c===b&&t.removeAttribute("id")}}}return u(e.replace(B,"$1"),t,r,i)}function ae(){var e=[];function t(n,i){return e.push(n+" ")>r.cacheLength&&delete t[e.shift()],t[n+" "]=i}return t}function se(e){return e[b]=!0,e}function ue(e){var t=d.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function le(e,t){var n=e.split("|"),i=n.length;while(i--)r.attrHandle[n[i]]=t}function ce(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function fe(e){return function(t){return"input"===t.nodeName.toLowerCase()&&t.type===e}}function pe(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function de(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&ie(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function he(e){return se(function(t){return t=+t,se(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function ge(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}n=oe.support={},o=oe.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},p=oe.setDocument=function(e){var t,i,a=e?e.ownerDocument||e:w;return a!==d&&9===a.nodeType&&a.documentElement?(d=a,h=d.documentElement,g=!o(d),w!==d&&(i=d.defaultView)&&i.top!==i&&(i.addEventListener?i.addEventListener("unload",re,!1):i.attachEvent&&i.attachEvent("onunload",re)),n.attributes=ue(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ue(function(e){return e.appendChild(d.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=Q.test(d.getElementsByClassName),n.getById=ue(function(e){return h.appendChild(e).id=b,!d.getElementsByName||!d.getElementsByName(b).length}),n.getById?(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){return e.getAttribute("id")===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n=t.getElementById(e);return n?[n]:[]}}):(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),r.find.TAG=n.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):n.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=n.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&g)return t.getElementsByClassName(e)},v=[],y=[],(n.qsa=Q.test(d.querySelectorAll))&&(ue(function(e){h.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+P+")"),e.querySelectorAll("[id~="+b+"-]").length||y.push("~="),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+b+"+*").length||y.push(".#.+[+~]")}),ue(function(e){e.innerHTML="";var t=d.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),h.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(n.matchesSelector=Q.test(m=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ue(function(e){n.disconnectedMatch=m.call(e,"*"),m.call(e,"[s!='']:x"),v.push("!=",W)}),y=y.length&&new RegExp(y.join("|")),v=v.length&&new RegExp(v.join("|")),t=Q.test(h.compareDocumentPosition),x=t||Q.test(h.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return f=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r||(1&(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!n.sortDetached&&t.compareDocumentPosition(e)===r?e===d||e.ownerDocument===w&&x(w,e)?-1:t===d||t.ownerDocument===w&&x(w,t)?1:c?O(c,e)-O(c,t):0:4&r?-1:1)}:function(e,t){if(e===t)return f=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===d?-1:t===d?1:i?-1:o?1:c?O(c,e)-O(c,t):0;if(i===o)return ce(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?ce(a[r],s[r]):a[r]===w?-1:s[r]===w?1:0},d):d},oe.matches=function(e,t){return oe(e,null,null,t)},oe.matchesSelector=function(e,t){if((e.ownerDocument||e)!==d&&p(e),t=t.replace(z,"='$1']"),n.matchesSelector&&g&&!S[t+" "]&&(!v||!v.test(t))&&(!y||!y.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){}return oe(t,d,null,[e]).length>0},oe.contains=function(e,t){return(e.ownerDocument||e)!==d&&p(e),x(e,t)},oe.attr=function(e,t){(e.ownerDocument||e)!==d&&p(e);var i=r.attrHandle[t.toLowerCase()],o=i&&N.call(r.attrHandle,t.toLowerCase())?i(e,t,!g):void 0;return void 0!==o?o:n.attributes||!g?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null},oe.escape=function(e){return(e+"").replace(te,ne)},oe.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},oe.uniqueSort=function(e){var t,r=[],i=0,o=0;if(f=!n.detectDuplicates,c=!n.sortStable&&e.slice(0),e.sort(D),f){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return c=null,e},i=oe.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else while(t=e[r++])n+=i(t);return n},(r=oe.selectors={cacheLength:50,createPseudo:se,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(Z,ee),e[3]=(e[3]||e[4]||e[5]||"").replace(Z,ee),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||oe.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&oe.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return V.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=a(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(Z,ee).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=E[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&E(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=oe.attr(r,e);return null==i?"!="===t:!t||(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i.replace($," ")+" ").indexOf(n)>-1:"|="===t&&(i===n||i.slice(0,n.length+1)===n+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h,g=o!==a?"nextSibling":"previousSibling",y=t.parentNode,v=s&&t.nodeName.toLowerCase(),m=!u&&!s,x=!1;if(y){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===v:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?y.firstChild:y.lastChild],a&&m){x=(d=(l=(c=(f=(p=y)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1])&&l[2],p=d&&y.childNodes[d];while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if(1===p.nodeType&&++x&&p===t){c[e]=[T,d,x];break}}else if(m&&(x=d=(l=(c=(f=(p=t)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1]),!1===x)while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===v:1===p.nodeType)&&++x&&(m&&((c=(f=p[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]=[T,x]),p===t))break;return(x-=i)===r||x%r==0&&x/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||oe.error("unsupported pseudo: "+e);return i[b]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?se(function(e,n){var r,o=i(e,t),a=o.length;while(a--)e[r=O(e,o[a])]=!(n[r]=o[a])}):function(e){return i(e,0,n)}):i}},pseudos:{not:se(function(e){var t=[],n=[],r=s(e.replace(B,"$1"));return r[b]?se(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),t[0]=null,!n.pop()}}),has:se(function(e){return function(t){return oe(e,t).length>0}}),contains:se(function(e){return e=e.replace(Z,ee),function(t){return(t.textContent||t.innerText||i(t)).indexOf(e)>-1}}),lang:se(function(e){return U.test(e||"")||oe.error("unsupported lang: "+e),e=e.replace(Z,ee).toLowerCase(),function(t){var n;do{if(n=g?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===h},focus:function(e){return e===d.activeElement&&(!d.hasFocus||d.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:de(!1),disabled:de(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return Y.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:he(function(){return[0]}),last:he(function(e,t){return[t-1]}),eq:he(function(e,t,n){return[n<0?n+t:n]}),even:he(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:he(function(e,t,n){for(var r=n<0?n+t:n;++r1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function be(e,t,n){for(var r=0,i=t.length;r-1&&(o[l]=!(a[l]=f))}}else v=we(v===a?v.splice(h,v.length):v),i?i(null,a,v,u):L.apply(a,v)})}function Ce(e){for(var t,n,i,o=e.length,a=r.relative[e[0].type],s=a||r.relative[" "],u=a?1:0,c=me(function(e){return e===t},s,!0),f=me(function(e){return O(t,e)>-1},s,!0),p=[function(e,n,r){var i=!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):f(e,n,r));return t=null,i}];u1&&xe(p),u>1&&ve(e.slice(0,u-1).concat({value:" "===e[u-2].type?"*":""})).replace(B,"$1"),n,u0,i=e.length>0,o=function(o,a,s,u,c){var f,h,y,v=0,m="0",x=o&&[],b=[],w=l,C=o||i&&r.find.TAG("*",c),E=T+=null==w?1:Math.random()||.1,k=C.length;for(c&&(l=a===d||a||c);m!==k&&null!=(f=C[m]);m++){if(i&&f){h=0,a||f.ownerDocument===d||(p(f),s=!g);while(y=e[h++])if(y(f,a||d,s)){u.push(f);break}c&&(T=E)}n&&((f=!y&&f)&&v--,o&&x.push(f))}if(v+=m,n&&m!==v){h=0;while(y=t[h++])y(x,b,a,s);if(o){if(v>0)while(m--)x[m]||b[m]||(b[m]=j.call(u));b=we(b)}L.apply(u,b),c&&!o&&b.length>0&&v+t.length>1&&oe.uniqueSort(u)}return c&&(T=E,l=w),x};return n?se(o):o}return s=oe.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=a(e)),n=t.length;while(n--)(o=Ce(t[n]))[b]?r.push(o):i.push(o);(o=S(e,Ee(i,r))).selector=e}return o},u=oe.select=function(e,t,n,i){var o,u,l,c,f,p="function"==typeof e&&e,d=!i&&a(e=p.selector||e);if(n=n||[],1===d.length){if((u=d[0]=d[0].slice(0)).length>2&&"ID"===(l=u[0]).type&&9===t.nodeType&&g&&r.relative[u[1].type]){if(!(t=(r.find.ID(l.matches[0].replace(Z,ee),t)||[])[0]))return n;p&&(t=t.parentNode),e=e.slice(u.shift().value.length)}o=V.needsContext.test(e)?0:u.length;while(o--){if(l=u[o],r.relative[c=l.type])break;if((f=r.find[c])&&(i=f(l.matches[0].replace(Z,ee),K.test(u[0].type)&&ge(t.parentNode)||t))){if(u.splice(o,1),!(e=i.length&&ve(u)))return L.apply(n,i),n;break}}}return(p||s(e,d))(i,t,!g,n,!t||K.test(e)&&ge(t.parentNode)||t),n},n.sortStable=b.split("").sort(D).join("")===b,n.detectDuplicates=!!f,p(),n.sortDetached=ue(function(e){return 1&e.compareDocumentPosition(d.createElement("fieldset"))}),ue(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||le("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ue(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||le("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ue(function(e){return null==e.getAttribute("disabled")})||le(P,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),oe}(e);w.find=E,w.expr=E.selectors,w.expr[":"]=w.expr.pseudos,w.uniqueSort=w.unique=E.uniqueSort,w.text=E.getText,w.isXMLDoc=E.isXML,w.contains=E.contains,w.escapeSelector=E.escape;var k=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&w(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},D=w.expr.match.needsContext;function N(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var A=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,t,n){return g(t)?w.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?w.grep(e,function(e){return e===t!==n}):"string"!=typeof t?w.grep(e,function(e){return u.call(t,e)>-1!==n}):w.filter(t,e,n)}w.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?w.find.matchesSelector(r,e)?[r]:[]:w.find.matches(e,w.grep(t,function(e){return 1===e.nodeType}))},w.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(w(e).filter(function(){for(t=0;t1?w.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&D.test(e)?w(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(w.fn.init=function(e,t,n){var i,o;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(i="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:L.exec(e))||!i[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(i[1]){if(t=t instanceof w?t[0]:t,w.merge(this,w.parseHTML(i[1],t&&t.nodeType?t.ownerDocument||t:r,!0)),A.test(i[1])&&w.isPlainObject(t))for(i in t)g(this[i])?this[i](t[i]):this.attr(i,t[i]);return this}return(o=r.getElementById(i[2]))&&(this[0]=o,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):g(e)?void 0!==n.ready?n.ready(e):e(w):w.makeArray(e,this)}).prototype=w.fn,q=w(r);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};w.fn.extend({has:function(e){var t=w(e,this),n=t.length;return this.filter(function(){for(var e=0;e-1:1===n.nodeType&&w.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?w.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?u.call(w(e),this[0]):u.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(w.uniqueSort(w.merge(this.get(),w(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}w.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return k(e,"parentNode")},parentsUntil:function(e,t,n){return k(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return k(e,"nextSibling")},prevAll:function(e){return k(e,"previousSibling")},nextUntil:function(e,t,n){return k(e,"nextSibling",n)},prevUntil:function(e,t,n){return k(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return N(e,"iframe")?e.contentDocument:(N(e,"template")&&(e=e.content||e),w.merge([],e.childNodes))}},function(e,t){w.fn[e]=function(n,r){var i=w.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=w.filter(r,i)),this.length>1&&(O[e]||w.uniqueSort(i),H.test(e)&&i.reverse()),this.pushStack(i)}});var M=/[^\x20\t\r\n\f]+/g;function R(e){var t={};return w.each(e.match(M)||[],function(e,n){t[n]=!0}),t}w.Callbacks=function(e){e="string"==typeof e?R(e):w.extend({},e);var t,n,r,i,o=[],a=[],s=-1,u=function(){for(i=i||e.once,r=t=!0;a.length;s=-1){n=a.shift();while(++s-1)o.splice(n,1),n<=s&&s--}),this},has:function(e){return e?w.inArray(e,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=a=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=a=[],n||t||(o=n=""),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=[e,(n=n||[]).slice?n.slice():n],a.push(n),t||u()),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!r}};return l};function I(e){return e}function W(e){throw e}function $(e,t,n,r){var i;try{e&&g(i=e.promise)?i.call(e).done(t).fail(n):e&&g(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}w.extend({Deferred:function(t){var n=[["notify","progress",w.Callbacks("memory"),w.Callbacks("memory"),2],["resolve","done",w.Callbacks("once memory"),w.Callbacks("once memory"),0,"resolved"],["reject","fail",w.Callbacks("once memory"),w.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},"catch":function(e){return i.then(null,e)},pipe:function(){var e=arguments;return w.Deferred(function(t){w.each(n,function(n,r){var i=g(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&g(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(t,r,i){var o=0;function a(t,n,r,i){return function(){var s=this,u=arguments,l=function(){var e,l;if(!(t=o&&(r!==W&&(s=void 0,u=[e]),n.rejectWith(s,u))}};t?c():(w.Deferred.getStackHook&&(c.stackTrace=w.Deferred.getStackHook()),e.setTimeout(c))}}return w.Deferred(function(e){n[0][3].add(a(0,e,g(i)?i:I,e.notifyWith)),n[1][3].add(a(0,e,g(t)?t:I)),n[2][3].add(a(0,e,g(r)?r:W))}).promise()},promise:function(e){return null!=e?w.extend(e,i):i}},o={};return w.each(n,function(e,t){var a=t[2],s=t[5];i[t[1]]=a.add,s&&a.add(function(){r=s},n[3-e][2].disable,n[3-e][3].disable,n[0][2].lock,n[0][3].lock),a.add(t[3].fire),o[t[0]]=function(){return o[t[0]+"With"](this===o?void 0:this,arguments),this},o[t[0]+"With"]=a.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=o.call(arguments),a=w.Deferred(),s=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?o.call(arguments):n,--t||a.resolveWith(r,i)}};if(t<=1&&($(e,a.done(s(n)).resolve,a.reject,!t),"pending"===a.state()||g(i[n]&&i[n].then)))return a.then();while(n--)$(i[n],s(n),a.reject);return a.promise()}});var B=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;w.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&B.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},w.readyException=function(t){e.setTimeout(function(){throw t})};var F=w.Deferred();w.fn.ready=function(e){return F.then(e)["catch"](function(e){w.readyException(e)}),this},w.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--w.readyWait:w.isReady)||(w.isReady=!0,!0!==e&&--w.readyWait>0||F.resolveWith(r,[w]))}}),w.ready.then=F.then;function _(){r.removeEventListener("DOMContentLoaded",_),e.removeEventListener("load",_),w.ready()}"complete"===r.readyState||"loading"!==r.readyState&&!r.documentElement.doScroll?e.setTimeout(w.ready):(r.addEventListener("DOMContentLoaded",_),e.addEventListener("load",_));var z=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===x(n)){i=!0;for(s in n)z(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,g(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(w(e),n)})),t))for(;s1,null,!0)},removeData:function(e){return this.each(function(){K.remove(this,e)})}}),w.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=J.get(e,t),n&&(!r||Array.isArray(n)?r=J.access(e,t,w.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=w.queue(e,t),r=n.length,i=n.shift(),o=w._queueHooks(e,t),a=function(){w.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return J.get(e,n)||J.access(e,n,{empty:w.Callbacks("once memory").add(function(){J.remove(e,[t+"queue",n])})})}}),w.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length\x20\t\r\n\f]+)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"
{$lng['domains']['domainname']} {$arrowcode['d.domain']}{$lng['domains']['domainname']} {$arrowcode['d.domain_ace']} {$lng['panel']['path']} {$lng['panel']['options']}
","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&N(e,t)?w.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n-1)i&&i.push(o);else if(l=w.contains(o.ownerDocument,o),a=ye(f.appendChild(o),"script"),l&&ve(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}!function(){var e=r.createDocumentFragment().appendChild(r.createElement("div")),t=r.createElement("input");t.setAttribute("type","radio"),t.setAttribute("checked","checked"),t.setAttribute("name","t"),e.appendChild(t),h.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,e.innerHTML="",h.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue}();var be=r.documentElement,we=/^key/,Te=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ce=/^([^.]*)(?:\.(.+)|)/;function Ee(){return!0}function ke(){return!1}function Se(){try{return r.activeElement}catch(e){}}function De(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)De(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=ke;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return w().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=w.guid++)),e.each(function(){w.event.add(this,t,i,r,n)})}w.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.get(e);if(y){n.handler&&(n=(o=n).handler,i=o.selector),i&&w.find.matchesSelector(be,i),n.guid||(n.guid=w.guid++),(u=y.events)||(u=y.events={}),(a=y.handle)||(a=y.handle=function(t){return"undefined"!=typeof w&&w.event.triggered!==t.type?w.event.dispatch.apply(e,arguments):void 0}),l=(t=(t||"").match(M)||[""]).length;while(l--)d=g=(s=Ce.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=w.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=w.event.special[d]||{},c=w.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&w.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(e,r,h,a)||e.addEventListener&&e.addEventListener(d,a)),f.add&&(f.add.call(e,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),w.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.hasData(e)&&J.get(e);if(y&&(u=y.events)){l=(t=(t||"").match(M)||[""]).length;while(l--)if(s=Ce.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){f=w.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,y.handle)||w.removeEvent(e,d,y.handle),delete u[d])}else for(d in u)w.event.remove(e,d+t[l],n,r,!0);w.isEmptyObject(u)&&J.remove(e,"handle events")}},dispatch:function(e){var t=w.event.fix(e),n,r,i,o,a,s,u=new Array(arguments.length),l=(J.get(this,"events")||{})[t.type]||[],c=w.event.special[t.type]||{};for(u[0]=t,n=1;n=1))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n-1:w.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u\x20\t\r\n\f]*)[^>]*)\/>/gi,Ae=/\s*$/g;function Le(e,t){return N(e,"table")&&N(11!==t.nodeType?t:t.firstChild,"tr")?w(e).children("tbody")[0]||e:e}function He(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Oe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Pe(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(J.hasData(e)&&(o=J.access(e),a=J.set(t,o),l=o.events)){delete a.handle,a.events={};for(i in l)for(n=0,r=l[i].length;n1&&"string"==typeof y&&!h.checkClone&&je.test(y))return e.each(function(i){var o=e.eq(i);v&&(t[0]=y.call(this,i,o.html())),Re(o,t,n,r)});if(p&&(i=xe(t,e[0].ownerDocument,!1,e,r),o=i.firstChild,1===i.childNodes.length&&(i=o),o||r)){for(u=(s=w.map(ye(i,"script"),He)).length;f")},clone:function(e,t,n){var r,i,o,a,s=e.cloneNode(!0),u=w.contains(e.ownerDocument,e);if(!(h.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||w.isXMLDoc(e)))for(a=ye(s),r=0,i=(o=ye(e)).length;r0&&ve(a,!u&&ye(e,"script")),s},cleanData:function(e){for(var t,n,r,i=w.event.special,o=0;void 0!==(n=e[o]);o++)if(Y(n)){if(t=n[J.expando]){if(t.events)for(r in t.events)i[r]?w.event.remove(n,r):w.removeEvent(n,r,t.handle);n[J.expando]=void 0}n[K.expando]&&(n[K.expando]=void 0)}}}),w.fn.extend({detach:function(e){return Ie(this,e,!0)},remove:function(e){return Ie(this,e)},text:function(e){return z(this,function(e){return void 0===e?w.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Re(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Le(this,e).appendChild(e)})},prepend:function(){return Re(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Le(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(w.cleanData(ye(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return w.clone(this,e,t)})},html:function(e){return z(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Ae.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=w.htmlPrefilter(e);try{for(;n=0&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))),u}function et(e,t,n){var r=$e(e),i=Fe(e,t,r),o="border-box"===w.css(e,"boxSizing",!1,r),a=o;if(We.test(i)){if(!n)return i;i="auto"}return a=a&&(h.boxSizingReliable()||i===e.style[t]),("auto"===i||!parseFloat(i)&&"inline"===w.css(e,"display",!1,r))&&(i=e["offset"+t[0].toUpperCase()+t.slice(1)],a=!0),(i=parseFloat(i)||0)+Ze(e,t,n||(o?"border":"content"),a,r,i)+"px"}w.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Fe(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=G(t),u=Xe.test(t),l=e.style;if(u||(t=Je(s)),a=w.cssHooks[t]||w.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"==(o=typeof n)&&(i=ie.exec(n))&&i[1]&&(n=ue(e,t,i),o="number"),null!=n&&n===n&&("number"===o&&(n+=i&&i[3]||(w.cssNumber[s]?"":"px")),h.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=G(t);return Xe.test(t)||(t=Je(s)),(a=w.cssHooks[t]||w.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Fe(e,t,r)),"normal"===i&&t in Ve&&(i=Ve[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),w.each(["height","width"],function(e,t){w.cssHooks[t]={get:function(e,n,r){if(n)return!ze.test(w.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?et(e,t,r):se(e,Ue,function(){return et(e,t,r)})},set:function(e,n,r){var i,o=$e(e),a="border-box"===w.css(e,"boxSizing",!1,o),s=r&&Ze(e,t,r,a,o);return a&&h.scrollboxSize()===o.position&&(s-=Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-parseFloat(o[t])-Ze(e,t,"border",!1,o)-.5)),s&&(i=ie.exec(n))&&"px"!==(i[3]||"px")&&(e.style[t]=n,n=w.css(e,t)),Ke(e,n,s)}}}),w.cssHooks.marginLeft=_e(h.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Fe(e,"marginLeft"))||e.getBoundingClientRect().left-se(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),w.each({margin:"",padding:"",border:"Width"},function(e,t){w.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+oe[r]+t]=o[r]||o[r-2]||o[0];return i}},"margin"!==e&&(w.cssHooks[e+t].set=Ke)}),w.fn.extend({css:function(e,t){return z(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=$e(e),i=t.length;a1)}});function tt(e,t,n,r,i){return new tt.prototype.init(e,t,n,r,i)}w.Tween=tt,tt.prototype={constructor:tt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||w.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(w.cssNumber[n]?"":"px")},cur:function(){var e=tt.propHooks[this.prop];return e&&e.get?e.get(this):tt.propHooks._default.get(this)},run:function(e){var t,n=tt.propHooks[this.prop];return this.options.duration?this.pos=t=w.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):tt.propHooks._default.set(this),this}},tt.prototype.init.prototype=tt.prototype,tt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=w.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){w.fx.step[e.prop]?w.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[w.cssProps[e.prop]]&&!w.cssHooks[e.prop]?e.elem[e.prop]=e.now:w.style(e.elem,e.prop,e.now+e.unit)}}},tt.propHooks.scrollTop=tt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},w.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},w.fx=tt.prototype.init,w.fx.step={};var nt,rt,it=/^(?:toggle|show|hide)$/,ot=/queueHooks$/;function at(){rt&&(!1===r.hidden&&e.requestAnimationFrame?e.requestAnimationFrame(at):e.setTimeout(at,w.fx.interval),w.fx.tick())}function st(){return e.setTimeout(function(){nt=void 0}),nt=Date.now()}function ut(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=oe[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function lt(e,t,n){for(var r,i=(pt.tweeners[t]||[]).concat(pt.tweeners["*"]),o=0,a=i.length;o1)},removeAttr:function(e){return this.each(function(){w.removeAttr(this,e)})}}),w.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?w.prop(e,t,n):(1===o&&w.isXMLDoc(e)||(i=w.attrHooks[t.toLowerCase()]||(w.expr.match.bool.test(t)?dt:void 0)),void 0!==n?null===n?void w.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=w.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!h.radioValue&&"radio"===t&&N(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(M);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),dt={set:function(e,t,n){return!1===t?w.removeAttr(e,n):e.setAttribute(n,n),n}},w.each(w.expr.match.bool.source.match(/\w+/g),function(e,t){var n=ht[t]||w.find.attr;ht[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=ht[a],ht[a]=i,i=null!=n(e,t,r)?a:null,ht[a]=o),i}});var gt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;w.fn.extend({prop:function(e,t){return z(this,w.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[w.propFix[e]||e]})}}),w.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&w.isXMLDoc(e)||(t=w.propFix[t]||t,i=w.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=w.find.attr(e,"tabindex");return t?parseInt(t,10):gt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),h.optSelected||(w.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),w.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){w.propFix[this.toLowerCase()]=this});function vt(e){return(e.match(M)||[]).join(" ")}function mt(e){return e.getAttribute&&e.getAttribute("class")||""}function xt(e){return Array.isArray(e)?e:"string"==typeof e?e.match(M)||[]:[]}w.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).addClass(e.call(this,t,mt(this)))});if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).removeClass(e.call(this,t,mt(this)))});if(!arguments.length)return this.attr("class","");if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])while(r.indexOf(" "+o+" ")>-1)r=r.replace(" "+o+" "," ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(e,t){var n=typeof e,r="string"===n||Array.isArray(e);return"boolean"==typeof t&&r?t?this.addClass(e):this.removeClass(e):g(e)?this.each(function(n){w(this).toggleClass(e.call(this,n,mt(this),t),t)}):this.each(function(){var t,i,o,a;if(r){i=0,o=w(this),a=xt(e);while(t=a[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else void 0!==e&&"boolean"!==n||((t=mt(this))&&J.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":J.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&(" "+vt(mt(n))+" ").indexOf(t)>-1)return!0;return!1}});var bt=/\r/g;w.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=g(e),this.each(function(n){var i;1===this.nodeType&&(null==(i=r?e.call(this,n,w(this).val()):e)?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=w.map(i,function(e){return null==e?"":e+""})),(t=w.valHooks[this.type]||w.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return(t=w.valHooks[i.type]||w.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:"string"==typeof(n=i.value)?n.replace(bt,""):null==n?"":n}}}),w.extend({valHooks:{option:{get:function(e){var t=w.find.attr(e,"value");return null!=t?t:vt(w.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),w.each(["radio","checkbox"],function(){w.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=w.inArray(w(e).val(),t)>-1}},h.checkOn||(w.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),h.focusin="onfocusin"in e;var wt=/^(?:focusinfocus|focusoutblur)$/,Tt=function(e){e.stopPropagation()};w.extend(w.event,{trigger:function(t,n,i,o){var a,s,u,l,c,p,d,h,v=[i||r],m=f.call(t,"type")?t.type:t,x=f.call(t,"namespace")?t.namespace.split("."):[];if(s=h=u=i=i||r,3!==i.nodeType&&8!==i.nodeType&&!wt.test(m+w.event.triggered)&&(m.indexOf(".")>-1&&(m=(x=m.split(".")).shift(),x.sort()),c=m.indexOf(":")<0&&"on"+m,t=t[w.expando]?t:new w.Event(m,"object"==typeof t&&t),t.isTrigger=o?2:3,t.namespace=x.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+x.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=i),n=null==n?[t]:w.makeArray(n,[t]),d=w.event.special[m]||{},o||!d.trigger||!1!==d.trigger.apply(i,n))){if(!o&&!d.noBubble&&!y(i)){for(l=d.delegateType||m,wt.test(l+m)||(s=s.parentNode);s;s=s.parentNode)v.push(s),u=s;u===(i.ownerDocument||r)&&v.push(u.defaultView||u.parentWindow||e)}a=0;while((s=v[a++])&&!t.isPropagationStopped())h=s,t.type=a>1?l:d.bindType||m,(p=(J.get(s,"events")||{})[t.type]&&J.get(s,"handle"))&&p.apply(s,n),(p=c&&s[c])&&p.apply&&Y(s)&&(t.result=p.apply(s,n),!1===t.result&&t.preventDefault());return t.type=m,o||t.isDefaultPrevented()||d._default&&!1!==d._default.apply(v.pop(),n)||!Y(i)||c&&g(i[m])&&!y(i)&&((u=i[c])&&(i[c]=null),w.event.triggered=m,t.isPropagationStopped()&&h.addEventListener(m,Tt),i[m](),t.isPropagationStopped()&&h.removeEventListener(m,Tt),w.event.triggered=void 0,u&&(i[c]=u)),t.result}},simulate:function(e,t,n){var r=w.extend(new w.Event,n,{type:e,isSimulated:!0});w.event.trigger(r,null,t)}}),w.fn.extend({trigger:function(e,t){return this.each(function(){w.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return w.event.trigger(e,t,n,!0)}}),h.focusin||w.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){w.event.simulate(t,e.target,w.event.fix(e))};w.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=J.access(r,t);i||r.addEventListener(e,n,!0),J.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=J.access(r,t)-1;i?J.access(r,t,i):(r.removeEventListener(e,n,!0),J.remove(r,t))}}});var Ct=e.location,Et=Date.now(),kt=/\?/;w.parseXML=function(t){var n;if(!t||"string"!=typeof t)return null;try{n=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){n=void 0}return n&&!n.getElementsByTagName("parsererror").length||w.error("Invalid XML: "+t),n};var St=/\[\]$/,Dt=/\r?\n/g,Nt=/^(?:submit|button|image|reset|file)$/i,At=/^(?:input|select|textarea|keygen)/i;function jt(e,t,n,r){var i;if(Array.isArray(t))w.each(t,function(t,i){n||St.test(e)?r(e,i):jt(e+"["+("object"==typeof i&&null!=i?t:"")+"]",i,n,r)});else if(n||"object"!==x(t))r(e,t);else for(i in t)jt(e+"["+i+"]",t[i],n,r)}w.param=function(e,t){var n,r=[],i=function(e,t){var n=g(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(e)||e.jquery&&!w.isPlainObject(e))w.each(e,function(){i(this.name,this.value)});else for(n in e)jt(n,e[n],t,i);return r.join("&")},w.fn.extend({serialize:function(){return w.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=w.prop(this,"elements");return e?w.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!w(this).is(":disabled")&&At.test(this.nodeName)&&!Nt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=w(this).val();return null==n?null:Array.isArray(n)?w.map(n,function(e){return{name:t.name,value:e.replace(Dt,"\r\n")}}):{name:t.name,value:n.replace(Dt,"\r\n")}}).get()}});var qt=/%20/g,Lt=/#.*$/,Ht=/([?&])_=[^&]*/,Ot=/^(.*?):[ \t]*([^\r\n]*)$/gm,Pt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Mt=/^(?:GET|HEAD)$/,Rt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Bt=r.createElement("a");Bt.href=Ct.href;function Ft(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(M)||[];if(g(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function _t(e,t,n,r){var i={},o=e===Wt;function a(s){var u;return i[s]=!0,w.each(e[s]||[],function(e,s){var l=s(t,n,r);return"string"!=typeof l||o||i[l]?o?!(u=l):void 0:(t.dataTypes.unshift(l),a(l),!1)}),u}return a(t.dataTypes[0])||!i["*"]&&a("*")}function zt(e,t){var n,r,i=w.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&w.extend(!0,e,r),e}function Xt(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}function Ut(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}w.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ct.href,type:"GET",isLocal:Pt.test(Ct.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":w.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,w.ajaxSettings),t):zt(w.ajaxSettings,e)},ajaxPrefilter:Ft(It),ajaxTransport:Ft(Wt),ajax:function(t,n){"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,p,d,h=w.ajaxSetup({},n),g=h.context||h,y=h.context&&(g.nodeType||g.jquery)?w(g):w.event,v=w.Deferred(),m=w.Callbacks("once memory"),x=h.statusCode||{},b={},T={},C="canceled",E={readyState:0,getResponseHeader:function(e){var t;if(c){if(!s){s={};while(t=Ot.exec(a))s[t[1].toLowerCase()]=t[2]}t=s[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return c?a:null},setRequestHeader:function(e,t){return null==c&&(e=T[e.toLowerCase()]=T[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==c&&(h.mimeType=e),this},statusCode:function(e){var t;if(e)if(c)E.always(e[E.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||C;return i&&i.abort(t),k(0,t),this}};if(v.promise(E),h.url=((t||h.url||Ct.href)+"").replace(Rt,Ct.protocol+"//"),h.type=n.method||n.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(M)||[""],null==h.crossDomain){l=r.createElement("a");try{l.href=h.url,l.href=l.href,h.crossDomain=Bt.protocol+"//"+Bt.host!=l.protocol+"//"+l.host}catch(e){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=w.param(h.data,h.traditional)),_t(It,h,n,E),c)return E;(f=w.event&&h.global)&&0==w.active++&&w.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!Mt.test(h.type),o=h.url.replace(Lt,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(qt,"+")):(d=h.url.slice(o.length),h.data&&(h.processData||"string"==typeof h.data)&&(o+=(kt.test(o)?"&":"?")+h.data,delete h.data),!1===h.cache&&(o=o.replace(Ht,"$1"),d=(kt.test(o)?"&":"?")+"_="+Et+++d),h.url=o+d),h.ifModified&&(w.lastModified[o]&&E.setRequestHeader("If-Modified-Since",w.lastModified[o]),w.etag[o]&&E.setRequestHeader("If-None-Match",w.etag[o])),(h.data&&h.hasContent&&!1!==h.contentType||n.contentType)&&E.setRequestHeader("Content-Type",h.contentType),E.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+$t+"; q=0.01":""):h.accepts["*"]);for(p in h.headers)E.setRequestHeader(p,h.headers[p]);if(h.beforeSend&&(!1===h.beforeSend.call(g,E,h)||c))return E.abort();if(C="abort",m.add(h.complete),E.done(h.success),E.fail(h.error),i=_t(Wt,h,n,E)){if(E.readyState=1,f&&y.trigger("ajaxSend",[E,h]),c)return E;h.async&&h.timeout>0&&(u=e.setTimeout(function(){E.abort("timeout")},h.timeout));try{c=!1,i.send(b,k)}catch(e){if(c)throw e;k(-1,e)}}else k(-1,"No Transport");function k(t,n,r,s){var l,p,d,b,T,C=n;c||(c=!0,u&&e.clearTimeout(u),i=void 0,a=s||"",E.readyState=t>0?4:0,l=t>=200&&t<300||304===t,r&&(b=Xt(h,E,r)),b=Ut(h,b,E,l),l?(h.ifModified&&((T=E.getResponseHeader("Last-Modified"))&&(w.lastModified[o]=T),(T=E.getResponseHeader("etag"))&&(w.etag[o]=T)),204===t||"HEAD"===h.type?C="nocontent":304===t?C="notmodified":(C=b.state,p=b.data,l=!(d=b.error))):(d=C,!t&&C||(C="error",t<0&&(t=0))),E.status=t,E.statusText=(n||C)+"",l?v.resolveWith(g,[p,C,E]):v.rejectWith(g,[E,C,d]),E.statusCode(x),x=void 0,f&&y.trigger(l?"ajaxSuccess":"ajaxError",[E,h,l?p:d]),m.fireWith(g,[E,C]),f&&(y.trigger("ajaxComplete",[E,h]),--w.active||w.event.trigger("ajaxStop")))}return E},getJSON:function(e,t,n){return w.get(e,t,n,"json")},getScript:function(e,t){return w.get(e,void 0,t,"script")}}),w.each(["get","post"],function(e,t){w[t]=function(e,n,r,i){return g(n)&&(i=i||r,r=n,n=void 0),w.ajax(w.extend({url:e,type:t,dataType:i,data:n,success:r},w.isPlainObject(e)&&e))}}),w._evalUrl=function(e){return w.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},w.fn.extend({wrapAll:function(e){var t;return this[0]&&(g(e)&&(e=e.call(this[0])),t=w(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return g(e)?this.each(function(t){w(this).wrapInner(e.call(this,t))}):this.each(function(){var t=w(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=g(e);return this.each(function(n){w(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){w(this).replaceWith(this.childNodes)}),this}}),w.expr.pseudos.hidden=function(e){return!w.expr.pseudos.visible(e)},w.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},w.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var Vt={0:200,1223:204},Gt=w.ajaxSettings.xhr();h.cors=!!Gt&&"withCredentials"in Gt,h.ajax=Gt=!!Gt,w.ajaxTransport(function(t){var n,r;if(h.cors||Gt&&!t.crossDomain)return{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(a in t.xhrFields)s[a]=t.xhrFields[a];t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");for(a in i)s.setRequestHeader(a,i[a]);n=function(e){return function(){n&&(n=r=s.onload=s.onerror=s.onabort=s.ontimeout=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(Vt[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=n(),r=s.onerror=s.ontimeout=n("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&e.setTimeout(function(){n&&r()})},n=n("abort");try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}},abort:function(){n&&n()}}}),w.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),w.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return w.globalEval(e),e}}}),w.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),w.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(i,o){t=w(" From 09038ac7aa59b657c09107831a7aa7b812e66e25 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 31 Jul 2021 09:51:54 +0200 Subject: [PATCH 251/319] Fix some typos (found by codespell) (#969) Signed-off-by: Stefan Weil --- admin_apcuinfo.php | 2 +- admin_opcacheinfo.php | 2 +- api_keys.php | 2 +- install/lib/class.FroxlorInstall.php | 4 ++-- install/lng/english.lng.php | 4 ++-- .../updates/froxlor/0.9/update_0.9.inc.php | 6 +++--- install/updates/preconfig.php | 2 +- .../preconfig/0.9/preconfig_0.9.inc.php | 2 +- lib/Froxlor/Api/Commands/Certificates.php | 4 ++-- lib/Froxlor/Api/Commands/CustomerBackups.php | 2 +- lib/Froxlor/Api/Commands/Customers.php | 8 ++++---- lib/Froxlor/Api/Commands/DirOptions.php | 2 +- lib/Froxlor/Api/Commands/DirProtections.php | 2 +- lib/Froxlor/Api/Commands/Domains.php | 2 +- lib/Froxlor/Api/Commands/Emails.php | 2 +- lib/Froxlor/Api/Commands/FpmDaemons.php | 2 +- lib/Froxlor/Api/Commands/Ftps.php | 4 ++-- lib/Froxlor/Api/Commands/HostingPlans.php | 10 +++++----- lib/Froxlor/Api/Commands/IpsAndPorts.php | 2 +- lib/Froxlor/Api/Commands/Mysqls.php | 6 +++--- lib/Froxlor/Api/Commands/PhpSettings.php | 2 +- lib/Froxlor/Api/Commands/SubDomains.php | 2 +- lib/Froxlor/Bulk/BulkAction.php | 2 +- .../Cli/Action/ConfigServicesAction.php | 2 +- .../Cli/Action/SwitchServerIpAction.php | 4 ++-- lib/Froxlor/Config/ConfigDaemon.php | 2 +- lib/Froxlor/Cron/Http/Apache.php | 2 +- lib/Froxlor/Cron/Http/ConfigIO.php | 2 +- lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 2 +- lib/Froxlor/Cron/Http/Lighttpd.php | 2 +- lib/Froxlor/Cron/Http/Nginx.php | 2 +- lib/Froxlor/Cron/Http/Php/Fcgid.php | 2 +- lib/Froxlor/Cron/Traffic/TrafficCron.php | 2 +- lib/Froxlor/Database/Database.php | 2 +- lib/Froxlor/FileDir.php | 4 ++-- lib/Froxlor/FroxlorLogger.php | 2 +- lib/Froxlor/SImExporter.php | 2 +- lib/Froxlor/System/Crypt.php | 6 +++--- lib/Froxlor/System/Mailer.php | 2 +- lib/Froxlor/User.php | 4 ++-- lib/configfiles/bionic.xml | 20 +++++++++---------- lib/configfiles/bullseye.xml | 16 +++++++-------- lib/configfiles/buster.xml | 16 +++++++-------- lib/configfiles/centos7.xml | 12 +++++------ lib/configfiles/centos8.xml | 12 +++++------ lib/configfiles/focal.xml | 18 ++++++++--------- lib/configfiles/gentoo.xml | 10 +++++----- lib/configfiles/stretch.xml | 20 +++++++++---------- lib/configfiles/xenial.xml | 20 +++++++++---------- lib/init.php | 4 ++-- lng/czech.lng.php | 12 +++++------ lng/english.lng.php | 10 +++++----- templates/Sparkle/assets/js/circular.js | 6 +++--- 53 files changed, 148 insertions(+), 148 deletions(-) diff --git a/admin_apcuinfo.php b/admin_apcuinfo.php index a0b0f937..d7854d65 100644 --- a/admin_apcuinfo.php +++ b/admin_apcuinfo.php @@ -87,7 +87,7 @@ if ($page == 'showinfo') { $hits = $cache['num_hits'] . @sprintf(" (%.1f%%)", $cache['num_hits'] * 100 / ($cache['num_hits'] + $cache['num_misses'])); $misses = $cache['num_misses'] . @sprintf(" (%.1f%%)", $cache['num_misses'] * 100 / ($cache['num_hits'] + $cache['num_misses'])); - // Fragementation: (freeseg - 1) / total_seg + // Fragmentation: (freeseg - 1) / total_seg $nseg = $freeseg = $fragsize = $freetotal = 0; for ($i = 0; $i < $mem['num_seg']; $i ++) { $ptr = 0; diff --git a/admin_opcacheinfo.php b/admin_opcacheinfo.php index b6afbb51..85b8a8f3 100644 --- a/admin_opcacheinfo.php +++ b/admin_opcacheinfo.php @@ -22,7 +22,7 @@ require './lib/init.php'; if ($action == 'reset' && function_exists('opcache_reset') && $userinfo['change_serversettings'] == '1') { opcache_reset(); - $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "reseted OPcache"); + $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "reset OPcache"); header('Location: ' . $linker->getLink(array( 'section' => 'opcacheinfo', 'page' => 'showinfo' diff --git a/api_keys.php b/api_keys.php index 0c3126e5..1a110ce4 100644 --- a/api_keys.php +++ b/api_keys.php @@ -127,7 +127,7 @@ if ($action == 'delete') { $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed api::api_keys"); -// select all my (accessable) certificates +// select all my (accessible) certificates $keys_stmt_query = "SELECT ak.*, c.loginname, a.loginname as adminname FROM `" . TABLE_API_KEYS . "` ak LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` c ON `c`.`customerid` = `ak`.`customerid` diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index 350e4277..b8eb2dcc 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -123,7 +123,7 @@ class FroxlorInstall if ((isset($_POST['installstep']) && $_POST['installstep'] == '1') || (isset($_GET['check']) && $_GET['check'] == '1')) { $pagetitle = $this->_lng['install']['title']; if ($this->_checkPostData()) { - // ceck data and create userdata etc.etc.etc. + // check data and create userdata etc.etc.etc. $result = $this->_doInstall(); } elseif (isset($_GET['check']) && $_GET['check'] == '1') { // gather data @@ -739,7 +739,7 @@ class FroxlorInstall } if ($tables_exist) { - // tell whats going on + // tell what's going on $content .= $this->_status_message('begin', $this->_lng['install']['backup_old_db']); // create temporary backup-filename diff --git a/install/lng/english.lng.php b/install/lng/english.lng.php index 69c06ced..e6e126c5 100644 --- a/install/lng/english.lng.php +++ b/install/lng/english.lng.php @@ -23,7 +23,7 @@ $lng['requirements']['notfound'] = 'not found'; $lng['requirements']['notinstalled'] = 'not installed'; $lng['requirements']['activated'] = 'enabled'; $lng['requirements']['phpversion'] = 'PHP version >= 7.0'; -$lng['requirements']['newerphpprefered'] = 'Good, but php-7.1 is prefered.'; +$lng['requirements']['newerphpprefered'] = 'Good, but php-7.1 is preferred.'; $lng['requirements']['phppdo'] = 'PHP PDO extension and PDO-MySQL driver...'; $lng['requirements']['phpsession'] = 'PHP session-extension...'; $lng['requirements']['phpctype'] = 'PHP ctype-extension...'; @@ -39,7 +39,7 @@ $lng['requirements']['phpjson'] = 'PHP json-extension...'; $lng['requirements']['bcmathdescription'] = 'Traffic-calculation related functions will not work correctly!'; $lng['requirements']['zipdescription'] = 'The auto-update feature requires the zip extension.'; $lng['requirements']['openbasedir'] = 'open_basedir...'; -$lng['requirements']['openbasedirenabled'] = 'Froxlor will not work properly with open_basedir enabled. Please disable open_basedir for Froxlor in the coresponding php.ini'; +$lng['requirements']['openbasedirenabled'] = 'Froxlor will not work properly with open_basedir enabled. Please disable open_basedir for Froxlor in the corresponding php.ini'; $lng['requirements']['mysqldump'] = 'MySQL dump tool'; $lng['requirements']['mysqldumpmissing'] = 'Automatic backup of possible existing database is not possible. Please install mysql-client tools'; $lng['requirements']['diedbecauseofrequirements'] = 'Cannot install Froxlor without these requirements! Try to fix them and retry.'; diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index 4a1ed614..156541f3 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -2505,7 +2505,7 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.9.30')) { showUpdateStep("Updating from 0.9.30 to 0.9.31-dev1", true); lastStepStatus(0); - showUpdateStep("Removing unsused tables"); + showUpdateStep("Removing unused tables"); Database::query("DROP TABLE IF EXISTS `ipsandports_docrootsettings`;"); Database::query("DROP TABLE IF EXISTS `domain_docrootsettings`;"); lastStepStatus(0); @@ -2856,7 +2856,7 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.9.32-rc1')) { Settings::AddNew("system.croncmdline", $croncmdline); // add task to generate cron.d-file \Froxlor\System\Cronjob::inserttask('99'); - // silenty add the auto-update setting - we do not want everybody to know and use this + // silently add the auto-update setting - we do not want everybody to know and use this // as it is a very dangerous setting Settings::AddNew("system.cron_allowautoupdate", 0); lastStepStatus(0); @@ -3872,7 +3872,7 @@ opcache.interned_strings_buffer'); if (\Froxlor\Froxlor::isDatabaseVersion('201801110')) { - showUpdateStep("Adding php-fpm php PATH setting for envrironment"); + showUpdateStep("Adding php-fpm php PATH setting for environment"); Settings::AddNew("phpfpm.envpath", '/usr/local/bin:/usr/bin:/bin'); lastStepStatus(0); diff --git a/install/updates/preconfig.php b/install/updates/preconfig.php index e0f601c5..66c29416 100644 --- a/install/updates/preconfig.php +++ b/install/updates/preconfig.php @@ -19,7 +19,7 @@ * Function getPreConfig * * outputs various content before the update process - * can be continued (askes for agreement whatever is being asked) + * can be continued (asks for agreement whatever is being asked) * * @param string $current_version * @param int $current_db_version diff --git a/install/updates/preconfig/0.9/preconfig_0.9.inc.php b/install/updates/preconfig/0.9/preconfig_0.9.inc.php index 122114c1..848f032d 100644 --- a/install/updates/preconfig/0.9/preconfig_0.9.inc.php +++ b/install/updates/preconfig/0.9/preconfig_0.9.inc.php @@ -414,7 +414,7 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c if (Settings::Get('system.webserver') == 'apache2') { $has_preconfig = true; - $description = 'Froxlor now supports the new Apache 2.4. Please be aware that you need to load additional apache-modules in ordner to use it.
'; + $description = 'Froxlor now supports the new Apache 2.4. Please be aware that you need to load additional apache-modules in order to use it.
'; $description .= '
LoadModule authz_core_module modules/mod_authz_core.so
 					LoadModule authz_host_module modules/mod_authz_host.so

'; $question = 'Do you want to enable the Apache-2.4 modification?: '; diff --git a/lib/Froxlor/Api/Commands/Certificates.php b/lib/Froxlor/Api/Commands/Certificates.php index ee79ab74..69ffc718 100644 --- a/lib/Froxlor/Api/Commands/Certificates.php +++ b/lib/Froxlor/Api/Commands/Certificates.php @@ -189,7 +189,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou */ public function listing() { - // select all my (accessable) certificates + // 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` @@ -237,7 +237,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou */ public function listingCount() { - // select all my (accessable) certificates + // 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` diff --git a/lib/Froxlor/Api/Commands/CustomerBackups.php b/lib/Froxlor/Api/Commands/CustomerBackups.php index bd74dac3..84941cec 100644 --- a/lib/Froxlor/Api/Commands/CustomerBackups.php +++ b/lib/Froxlor/Api/Commands/CustomerBackups.php @@ -23,7 +23,7 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re { /** - * check whether backup is enabled systemwide and if accessable for customer (hide_options) + * check whether backup is enabled systemwide and if accessible for customer (hide_options) * * @throws \Exception */ diff --git a/lib/Froxlor/Api/Commands/Customers.php b/lib/Froxlor/Api/Commands/Customers.php index f9bbedf0..05749ca1 100644 --- a/lib/Froxlor/Api/Commands/Customers.php +++ b/lib/Froxlor/Api/Commands/Customers.php @@ -316,9 +316,9 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource * @param bool $perlenabled * optional, whether to allow usage of Perl/CGI, default 0 (false) * @param bool $dnsenabled - * optional, wether 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, wether to allow acccess 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 * @param int $hosting_plan_id @@ -923,9 +923,9 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource * @param bool $perlenabled * optional, whether to allow usage of Perl/CGI, default 0 (false) * @param bool $dnsenabled - * optional, ether 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, ether to allow acccess 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 * diff --git a/lib/Froxlor/Api/Commands/DirOptions.php b/lib/Froxlor/Api/Commands/DirOptions.php index 8fb44e9a..fc54f0cb 100644 --- a/lib/Froxlor/Api/Commands/DirOptions.php +++ b/lib/Froxlor/Api/Commands/DirOptions.php @@ -322,7 +322,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc } /** - * returns the total number of accessable directory options + * returns the total number of accessible directory options * * @param int $customerid * optional, admin-only, select directory-protections of a specific customer by id diff --git a/lib/Froxlor/Api/Commands/DirProtections.php b/lib/Froxlor/Api/Commands/DirProtections.php index b79785ef..241592d2 100644 --- a/lib/Froxlor/Api/Commands/DirProtections.php +++ b/lib/Froxlor/Api/Commands/DirProtections.php @@ -305,7 +305,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res } /** - * returns the total number of accessable directory protections + * returns the total number of accessible directory protections * * @param int $customerid * optional, admin-only, select directory-protections of a specific customer by id diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php index 45366c97..72dc7c09 100644 --- a/lib/Froxlor/Api/Commands/Domains.php +++ b/lib/Froxlor/Api/Commands/Domains.php @@ -77,7 +77,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn } /** - * returns the total number of accessable domains + * returns the total number of accessible domains * * @access admin * @throws \Exception diff --git a/lib/Froxlor/Api/Commands/Emails.php b/lib/Froxlor/Api/Commands/Emails.php index 924fe90e..699533c7 100644 --- a/lib/Froxlor/Api/Commands/Emails.php +++ b/lib/Froxlor/Api/Commands/Emails.php @@ -326,7 +326,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt } /** - * returns the total number of accessable email addresses + * returns the total number of accessible email addresses * * @param int $customerid * optional, admin-only, select email addresses of a specific customer by id diff --git a/lib/Froxlor/Api/Commands/FpmDaemons.php b/lib/Froxlor/Api/Commands/FpmDaemons.php index ba757dc0..52192591 100644 --- a/lib/Froxlor/Api/Commands/FpmDaemons.php +++ b/lib/Froxlor/Api/Commands/FpmDaemons.php @@ -79,7 +79,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc } /** - * returns the total number of accessable fpm daemons + * returns the total number of accessible fpm daemons * * @access admin * @throws \Exception diff --git a/lib/Froxlor/Api/Commands/Ftps.php b/lib/Froxlor/Api/Commands/Ftps.php index 486a1854..1e30bd4c 100644 --- a/lib/Froxlor/Api/Commands/Ftps.php +++ b/lib/Froxlor/Api/Commands/Ftps.php @@ -62,7 +62,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit if (($this->getUserDetail('ftps_used') < $this->getUserDetail('ftps') || $this->getUserDetail('ftps') == '-1') || $this->isAdmin() && $is_defaultuser == 1) { - // required paramters + // required parameters $path = $this->getParam('path'); $password = $this->getParam('ftp_password'); @@ -512,7 +512,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit } /** - * returns the total number of accessable ftp accounts + * returns the total number of accessible ftp accounts * * @param int $customerid * optional, admin-only, select ftp-users of a specific customer by id diff --git a/lib/Froxlor/Api/Commands/HostingPlans.php b/lib/Froxlor/Api/Commands/HostingPlans.php index ca3a76bc..68373d52 100644 --- a/lib/Froxlor/Api/Commands/HostingPlans.php +++ b/lib/Froxlor/Api/Commands/HostingPlans.php @@ -66,7 +66,7 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou } /** - * returns the total number of accessable hosting plans + * returns the total number of accessible hosting plans * * @access admin * @throws \Exception @@ -182,9 +182,9 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou * @param bool $perlenabled * optional, whether to allow usage of Perl/CGI, default 0 (false) * @param bool $dnsenabled - * optional, ether 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, ether to allow acccess 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 @@ -309,9 +309,9 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou * @param bool $perlenabled * optional, whether to allow usage of Perl/CGI, default 0 (false) * @param bool $dnsenabled - * optional, ether 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, ether to allow acccess 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 diff --git a/lib/Froxlor/Api/Commands/IpsAndPorts.php b/lib/Froxlor/Api/Commands/IpsAndPorts.php index 40531c0f..4f8fd1e4 100644 --- a/lib/Froxlor/Api/Commands/IpsAndPorts.php +++ b/lib/Froxlor/Api/Commands/IpsAndPorts.php @@ -65,7 +65,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour } /** - * returns the total number of accessable ip/port entries + * returns the total number of accessible ip/port entries * * @access admin * @throws \Exception diff --git a/lib/Froxlor/Api/Commands/Mysqls.php b/lib/Froxlor/Api/Commands/Mysqls.php index e4f61d47..19d95d6f 100644 --- a/lib/Froxlor/Api/Commands/Mysqls.php +++ b/lib/Froxlor/Api/Commands/Mysqls.php @@ -46,7 +46,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt */ public function add() { - // required paramters + // required parameters $password = $this->getParam('mysql_password'); // parameters @@ -314,7 +314,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt )); $id = $result['id']; - // paramters + // parameters $password = $this->getParam('mysql_password', true, ''); $databasedescription = $this->getParam('description', true, $result['description']); @@ -437,7 +437,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt } /** - * returns the total number of accessable databases + * returns the total number of accessible databases * * @param int $customerid * optional, admin-only, select dbs of a specific customer by id diff --git a/lib/Froxlor/Api/Commands/PhpSettings.php b/lib/Froxlor/Api/Commands/PhpSettings.php index 9d3ca362..5f0be1ee 100644 --- a/lib/Froxlor/Api/Commands/PhpSettings.php +++ b/lib/Froxlor/Api/Commands/PhpSettings.php @@ -122,7 +122,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour } /** - * returns the total number of accessable php-setting entries + * returns the total number of accessible php-setting entries * * @access admin * @throws \Exception diff --git a/lib/Froxlor/Api/Commands/SubDomains.php b/lib/Froxlor/Api/Commands/SubDomains.php index 3c09c6f8..cb861f9f 100644 --- a/lib/Froxlor/Api/Commands/SubDomains.php +++ b/lib/Froxlor/Api/Commands/SubDomains.php @@ -810,7 +810,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc } /** - * returns the total number of accessable subdomain entries + * returns the total number of accessible subdomain entries * * @param int $customerid * optional, admin-only, select (sub)domains of a specific customer by id diff --git a/lib/Froxlor/Bulk/BulkAction.php b/lib/Froxlor/Bulk/BulkAction.php index 457ef46b..fdfca799 100644 --- a/lib/Froxlor/Bulk/BulkAction.php +++ b/lib/Froxlor/Bulk/BulkAction.php @@ -150,7 +150,7 @@ abstract class BulkAction /** * reads in the csv import file and returns an array with - * all the entites to be imported + * all the entities to be imported * * @param string $separator * diff --git a/lib/Froxlor/Cli/Action/ConfigServicesAction.php b/lib/Froxlor/Cli/Action/ConfigServicesAction.php index 464e54df..a425ac3d 100644 --- a/lib/Froxlor/Cli/Action/ConfigServicesAction.php +++ b/lib/Froxlor/Cli/Action/ConfigServicesAction.php @@ -402,7 +402,7 @@ class ConfigServicesAction extends \Froxlor\Cli\Action } elseif (! file_exists($this->_args["froxlor-dir"])) { throw new \Exception("Given froxlor directory cannot be found ('" . $this->_args["froxlor-dir"] . "')"); } elseif (! is_readable($this->_args["froxlor-dir"])) { - throw new \Exception("Given froxlor direcotry cannot be read ('" . $this->_args["froxlor-dir"] . "')"); + throw new \Exception("Given froxlor directory cannot be read ('" . $this->_args["froxlor-dir"] . "')"); } } } diff --git a/lib/Froxlor/Cli/Action/SwitchServerIpAction.php b/lib/Froxlor/Cli/Action/SwitchServerIpAction.php index d4213eb4..fe6719a5 100644 --- a/lib/Froxlor/Cli/Action/SwitchServerIpAction.php +++ b/lib/Froxlor/Cli/Action/SwitchServerIpAction.php @@ -62,7 +62,7 @@ class SwitchServerIpAction extends \Froxlor\Cli\Action $ip_list = $this->_args['switch']; if (empty($ip_list) || is_bool($ip_list)) { - throw new \Exception("No paramters given for --switch action."); + throw new \Exception("No parameters given for --switch action."); } $ips_to_switch = array(); @@ -179,7 +179,7 @@ class SwitchServerIpAction extends \Froxlor\Cli\Action } elseif (! file_exists($this->_args["froxlor-dir"])) { throw new \Exception("Given froxlor directory cannot be found ('" . $this->_args["froxlor-dir"] . "')"); } elseif (! is_readable($this->_args["froxlor-dir"])) { - throw new \Exception("Given froxlor direcotry cannot be read ('" . $this->_args["froxlor-dir"] . "')"); + throw new \Exception("Given froxlor directory cannot be read ('" . $this->_args["froxlor-dir"] . "')"); } } } diff --git a/lib/Froxlor/Config/ConfigDaemon.php b/lib/Froxlor/Config/ConfigDaemon.php index f1de8b0e..1172519e 100644 --- a/lib/Froxlor/Config/ConfigDaemon.php +++ b/lib/Froxlor/Config/ConfigDaemon.php @@ -55,7 +55,7 @@ class ConfigDaemon private $isparsed = false; /** - * Sub - area of the full - XML only holding the daemon - data we are interessted in + * Sub - area of the full - XML only holding the daemon - data we are interested in * * @var \SimpleXMLElement */ diff --git a/lib/Froxlor/Cron/Http/Apache.php b/lib/Froxlor/Cron/Http/Apache.php index 9d3bb71c..9a1efe9f 100644 --- a/lib/Froxlor/Cron/Http/Apache.php +++ b/lib/Froxlor/Cron/Http/Apache.php @@ -826,7 +826,7 @@ class Apache extends HttpConfigBase // 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 informations + // 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); } } diff --git a/lib/Froxlor/Cron/Http/ConfigIO.php b/lib/Froxlor/Cron/Http/ConfigIO.php index 55002285..2859b103 100644 --- a/lib/Froxlor/Cron/Http/ConfigIO.php +++ b/lib/Froxlor/Cron/Http/ConfigIO.php @@ -287,7 +287,7 @@ class ConfigIO } /** - * returns a file/direcotry from the settings and checks whether it exists + * returns a file/directory from the settings and checks whether it exists * * @param string $group * settings-group diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index 858b3f29..dc83ff19 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -287,7 +287,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron $our_ips = Domain::getIpsOfDomain($domain_id); foreach ($loop_domains as $idx => $domain) { $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Validating DNS of " . $domain); - // ips accordint to NS + // ips according to NS $domain_ips = PhpHelper::gethostbynamel6($domain); if ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) <= 0) { // no common ips... diff --git a/lib/Froxlor/Cron/Http/Lighttpd.php b/lib/Froxlor/Cron/Http/Lighttpd.php index 5d9f6b5e..d6a08d6e 100644 --- a/lib/Froxlor/Cron/Http/Lighttpd.php +++ b/lib/Froxlor/Cron/Http/Lighttpd.php @@ -678,7 +678,7 @@ class Lighttpd extends HttpConfigBase // 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 informations + // 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); } } diff --git a/lib/Froxlor/Cron/Http/Nginx.php b/lib/Froxlor/Cron/Http/Nginx.php index 8d51c0b6..e7fcc416 100644 --- a/lib/Froxlor/Cron/Http/Nginx.php +++ b/lib/Froxlor/Cron/Http/Nginx.php @@ -1153,7 +1153,7 @@ class Nginx extends HttpConfigBase // 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 informations + // 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); } } diff --git a/lib/Froxlor/Cron/Http/Php/Fcgid.php b/lib/Froxlor/Cron/Http/Php/Fcgid.php index 410261e3..2cc74869 100644 --- a/lib/Froxlor/Cron/Http/Php/Fcgid.php +++ b/lib/Froxlor/Cron/Http/Php/Fcgid.php @@ -94,7 +94,7 @@ class Fcgid // Set Binary $starter_file .= "exec " . $phpconfig['binary'] . " -c " . escapeshellarg($this->getConfigDir()) . "\n"; - // remove +i attibute, so starter can be overwritten + // remove +i attribute, so starter can be overwritten if (file_exists($this->getStarterFile())) { \Froxlor\FileDir::removeImmutable($this->getStarterFile()); } diff --git a/lib/Froxlor/Cron/Traffic/TrafficCron.php b/lib/Froxlor/Cron/Traffic/TrafficCron.php index e11b2d08..4d291caa 100644 --- a/lib/Froxlor/Cron/Traffic/TrafficCron.php +++ b/lib/Froxlor/Cron/Traffic/TrafficCron.php @@ -69,7 +69,7 @@ class TrafficCron extends \Froxlor\Cron\FroxlorCron } /** - * TRAFFIC AND DISKUSAGE MESSURE + * TRAFFIC AND DISKUSAGE MEASURE */ \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Traffic run started...'); $admin_traffic = array(); diff --git a/lib/Froxlor/Database/Database.php b/lib/Froxlor/Database/Database.php index d0791148..fd498dee 100644 --- a/lib/Froxlor/Database/Database.php +++ b/lib/Froxlor/Database/Database.php @@ -165,7 +165,7 @@ class Database } /** - * returns the sql-access data as array using indeces + * returns the sql-access data as array using indices * 'user', 'passwd' and 'host'. * Returns false if not enabled * diff --git a/lib/Froxlor/FileDir.php b/lib/Froxlor/FileDir.php index d7a5e55c..60251b0d 100644 --- a/lib/Froxlor/FileDir.php +++ b/lib/Froxlor/FileDir.php @@ -370,7 +370,7 @@ class FileDir * @param * integer uid The uid which must match the found directories * @param - * integer gid The gid which must match the found direcotries + * integer gid The gid which must match the found directories * @param * string value the value for the input-field * @@ -461,7 +461,7 @@ class FileDir * @param int $uid * the uid which must match the found directories * @param int $gid - * the gid which must match the found direcotries + * the gid which must match the found directories * * @return array Array of found valid paths */ diff --git a/lib/Froxlor/FroxlorLogger.php b/lib/Froxlor/FroxlorLogger.php index f44e4e15..d64e8550 100644 --- a/lib/Froxlor/FroxlorLogger.php +++ b/lib/Froxlor/FroxlorLogger.php @@ -157,7 +157,7 @@ class FroxlorLogger echo "[" . $this->getLogLevelDesc($type) . "] " . $text . PHP_EOL; } - // warnings, errors and critical mesages WILL be logged + // warnings, errors and critical messages WILL be logged if (Settings::Get('logger.log_cron') == '0' && $action == \Froxlor\FroxlorLogger::CRON_ACTION && $type > LOG_WARNING) { return; } diff --git a/lib/Froxlor/SImExporter.php b/lib/Froxlor/SImExporter.php index 5a549f97..91ba149f 100644 --- a/lib/Froxlor/SImExporter.php +++ b/lib/Froxlor/SImExporter.php @@ -118,7 +118,7 @@ class SImExporter if ($_sha != sha1(var_export($_data, true))) { throw new \Exception("SHA check of import data failed. Unable to import."); } - // do not import version info - but we need that to possibily update settings + // do not import version info - but we need that to possibly update settings // when there were changes in the variable-name or similar unset($_data['panel.version']); unset($_data['panel.db_version']); diff --git a/lib/Froxlor/System/Crypt.php b/lib/Froxlor/System/Crypt.php index 7f2a9e17..34b5a771 100644 --- a/lib/Froxlor/System/Crypt.php +++ b/lib/Froxlor/System/Crypt.php @@ -59,20 +59,20 @@ class Crypt } /** - * Make crypted password from clear text password + * Make encrypted password from clear text password * * @author Michal Wojcik * @author Michael Kaufmann * @author Froxlor team (2010-) * - * 0 - default crypt (depenend on system configuration) + * 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 crypted + * Password to be encrypted * @param bool $htpasswd * optional whether to generate a SHA1 password for directory protection * diff --git a/lib/Froxlor/System/Mailer.php b/lib/Froxlor/System/Mailer.php index 0ced5466..e9d08c6c 100644 --- a/lib/Froxlor/System/Mailer.php +++ b/lib/Froxlor/System/Mailer.php @@ -7,7 +7,7 @@ class Mailer extends \PHPMailer\PHPMailer\PHPMailer { /** - * class construtor + * class constructor * * @param string $exceptions * whether to throw exceptions or not diff --git a/lib/Froxlor/User.php b/lib/Froxlor/User.php index e8e8eac3..717579e9 100644 --- a/lib/Froxlor/User.php +++ b/lib/Froxlor/User.php @@ -77,7 +77,7 @@ class User } /** - * Function which updates all counters of used ressources in panel_admins and panel_customers + * Function which updates all counters of used resources in panel_admins and panel_customers * * @param bool $returndebuginfo * Set to true to get an array with debug information @@ -237,7 +237,7 @@ class User $admin_domains = Database::pexecute_first($admin_domains_stmt, array( "aid" => $admin['adminid'] )); - // substract the amount of domains that are std-subdomains later when we iterated through all customers and know for sure + // subtract the amount of domains that are std-subdomains later when we iterated through all customers and know for sure $admin['domains_used_new'] = $admin_domains['number_domains']; // set current admin $cur_adm = $admin['adminid']; diff --git a/lib/configfiles/bionic.xml b/lib/configfiles/bionic.xml index 9d66426d..0522b429 100644 --- a/lib/configfiles/bionic.xml +++ b/lib/configfiles/bionic.xml @@ -388,7 +388,7 @@ exit "$RETVAL" # allow-axfr-ips Allow zonetransfers only to these subnets # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any speficied: +# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -931,7 +931,7 @@ gmysql-password= # allow-axfr-ips Allow zonetransfers only to these subnets # # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any speficied: +# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -2228,7 +2228,7 @@ debugger_command = # >$config_directory/$process_name.$process_id.log & sleep 5 # # Another possibility is to run gdb under a detached screen session. -# To attach to the screen sesssion, su root and run "screen -r +# To attach to the screen session, su root and run "screen -r # " where uniquely matches one of the detached # sessions (from "screen -list"). # @@ -2642,7 +2642,7 @@ driver = mysql # settings, like: host=sql1.host.org host=sql2.host.org # # pgsql: -# For available options, see the PostgreSQL documention for the +# For available options, see the PostgreSQL documentation for the # PQconnectdb function of libpq. # Use maxconns=n (default 5) to change how many connections Dovecot can # create to pgsql. @@ -3707,7 +3707,7 @@ protocol sieve { # # If you want UIDL compatibility with other POP3 servers, use: # UW's ipop3d : %08Xv%08Xu -# Courier : %f or %v-%u (both might be used simultaneosly) +# Courier : %f or %v-%u (both might be used simultaneously) # Cyrus (<= 2.1.3) : %u # Cyrus (>= 2.1.4) : %v.%u # Dovecot v0.99.x : %v.%u @@ -3965,7 +3965,7 @@ Port 21 # PassivePorts 49152 65534 # If your host was NATted, this option is useful in order to -# allow passive tranfers to work. You have to use your public +# allow passive transfers to work. You have to use your public # address and opening the passive ports used on your firewall as well. # MasqueradeAddress 1.2.3.4 @@ -3990,7 +3990,7 @@ Group nogroup # Umask 022 is a good standard umask to prevent new files and dirs # (second parm) from being group and world writable. Umask 022 022 -# Normally, we want files to be overwriteable. +# Normally, we want files to be overwritable. AllowOverwrite on # Uncomment this if you are using NIS or LDAP via NSS to retrieve passwords: @@ -4237,7 +4237,7 @@ SQLBackend mysql SQLEngine on SQLAuthenticate on # -# Use both a crypted or plaintext password +# Use both an encrypted or plaintext password SQLAuthTypes Crypt SQLAuthenticate users* groups* @@ -4295,7 +4295,7 @@ TLSVerifyClient off #TLSRequired on # Allow SSL/TLS renegotiations when the client requests them, but -# do not force the renegotations. Some clients do not support +# do not force the renegotiations. Some clients do not support # SSL/TLS renegotiations; when mod_tls forces a renegotiation, these # clients will close the data connection, or there will be a timeout # on an idle data connection. @@ -4595,7 +4595,7 @@ aliases: files chmod="0644"> *.log { missingok diff --git a/lib/configfiles/bullseye.xml b/lib/configfiles/bullseye.xml index 7fee323d..26de3086 100644 --- a/lib/configfiles/bullseye.xml +++ b/lib/configfiles/bullseye.xml @@ -377,7 +377,7 @@ exit "$RETVAL" # allow-axfr-ips Allow zonetransfers only to these subnets # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any speficied: +# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -905,7 +905,7 @@ gmysql-password= # allow-axfr-ips Allow zonetransfers only to these subnets # # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any speficied: +# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -2187,7 +2187,7 @@ debugger_command = # >$config_directory/$process_name.$process_id.log & sleep 5 # # Another possibility is to run gdb under a detached screen session. -# To attach to the screen sesssion, su root and run "screen -r +# To attach to the screen session, su root and run "screen -r # " where uniquely matches one of the detached # sessions (from "screen -list"). # @@ -4174,7 +4174,7 @@ Port 21 # PassivePorts 49152 65534 # If your host was NATted, this option is useful in order to -# allow passive tranfers to work. You have to use your public +# allow passive transfers to work. You have to use your public # address and opening the passive ports used on your firewall as well. # MasqueradeAddress 1.2.3.4 @@ -4199,7 +4199,7 @@ Group nogroup # Umask 022 is a good standard umask to prevent new files and dirs # (second parm) from being group and world writable. Umask 022 022 -# Normally, we want files to be overwriteable. +# Normally, we want files to be overwritable. AllowOverwrite on # Uncomment this if you are using NIS or LDAP via NSS to retrieve passwords: @@ -4448,7 +4448,7 @@ SQLBackend mysql SQLEngine on SQLAuthenticate on # -# Use both a crypted or plaintext password +# Use both an encrypted or plaintext password SQLAuthTypes Crypt SQLAuthenticate users* groups* @@ -4506,7 +4506,7 @@ TLSVerifyClient off #TLSRequired on # Allow SSL/TLS renegotiations when the client requests them, but -# do not force the renegotations. Some clients do not support +# do not force the renegotiations. Some clients do not support # SSL/TLS renegotiations; when mod_tls forces a renegotiation, these # clients will close the data connection, or there will be a timeout # on an idle data connection. @@ -4806,7 +4806,7 @@ aliases: files chmod="0644"> *.log { missingok diff --git a/lib/configfiles/buster.xml b/lib/configfiles/buster.xml index e3922dcf..b7b484bf 100644 --- a/lib/configfiles/buster.xml +++ b/lib/configfiles/buster.xml @@ -377,7 +377,7 @@ exit "$RETVAL" # allow-axfr-ips Allow zonetransfers only to these subnets # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any speficied: +# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -905,7 +905,7 @@ gmysql-password= # allow-axfr-ips Allow zonetransfers only to these subnets # # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any speficied: +# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -2187,7 +2187,7 @@ debugger_command = # >$config_directory/$process_name.$process_id.log & sleep 5 # # Another possibility is to run gdb under a detached screen session. -# To attach to the screen sesssion, su root and run "screen -r +# To attach to the screen session, su root and run "screen -r # " where uniquely matches one of the detached # sessions (from "screen -list"). # @@ -4167,7 +4167,7 @@ Port 21 # PassivePorts 49152 65534 # If your host was NATted, this option is useful in order to -# allow passive tranfers to work. You have to use your public +# allow passive transfers to work. You have to use your public # address and opening the passive ports used on your firewall as well. # MasqueradeAddress 1.2.3.4 @@ -4192,7 +4192,7 @@ Group nogroup # Umask 022 is a good standard umask to prevent new files and dirs # (second parm) from being group and world writable. Umask 022 022 -# Normally, we want files to be overwriteable. +# Normally, we want files to be overwritable. AllowOverwrite on # Uncomment this if you are using NIS or LDAP via NSS to retrieve passwords: @@ -4439,7 +4439,7 @@ SQLBackend mysql SQLEngine on SQLAuthenticate on # -# Use both a crypted or plaintext password +# Use both an encrypted or plaintext password SQLAuthTypes Crypt SQLAuthenticate users* groups* @@ -4497,7 +4497,7 @@ TLSVerifyClient off #TLSRequired on # Allow SSL/TLS renegotiations when the client requests them, but -# do not force the renegotations. Some clients do not support +# do not force the renegotiations. Some clients do not support # SSL/TLS renegotiations; when mod_tls forces a renegotiation, these # clients will close the data connection, or there will be a timeout # on an idle data connection. @@ -4797,7 +4797,7 @@ aliases: files chmod="0644"> *.log { missingok diff --git a/lib/configfiles/centos7.xml b/lib/configfiles/centos7.xml index 98307ba3..6ec83c48 100644 --- a/lib/configfiles/centos7.xml +++ b/lib/configfiles/centos7.xml @@ -226,7 +226,7 @@ query = SELECT gid FROM mail_users WHERE email = '%s' # FQDN from Froxlor mydomain = -# set myhostname to $mydomain because Froxlor alrady uses a FQDN +# set myhostname to $mydomain because Froxlor already uses a FQDN myhostname = $mydomain mydestination = $myhostname, @@ -1536,7 +1536,7 @@ protocol sieve { # # If you want UIDL compatibility with other POP3 servers, use: # UW's ipop3d : %08Xv%08Xu -# Courier : %f or %v-%u (both might be used simultaneosly) +# Courier : %f or %v-%u (both might be used simultaneously) # Cyrus (<= 2.1.3) : %u # Cyrus (>= 2.1.4) : %v.%u # Dovecot v0.99.x : %v.%u @@ -1754,7 +1754,7 @@ driver = mysql # settings, like: host=sql1.host.org host=sql2.host.org # # pgsql: -# For available options, see the PostgreSQL documention for the +# For available options, see the PostgreSQL documentation for the # PQconnectdb function of libpq. # Use maxconns=n (default 5) to change how many connections Dovecot can # create to pgsql. @@ -2237,7 +2237,7 @@ ControlsLog /var/log/proftpd/controls.log DefaultRoot ~ # Reject rootlogin (just for security) RootLogin off -# Noo need to require valid shell, because user is virtual +# No need to require valid shell, because user is virtual RequireValidShell off @@ -2447,7 +2447,7 @@ aliases: files nisplus - + @@ -2457,7 +2457,7 @@ aliases: files nisplus chmod="0644"> *.log { missingok diff --git a/lib/configfiles/centos8.xml b/lib/configfiles/centos8.xml index 207f9785..db55f89a 100644 --- a/lib/configfiles/centos8.xml +++ b/lib/configfiles/centos8.xml @@ -227,7 +227,7 @@ query = SELECT gid FROM mail_users WHERE email = '%s' # FQDN from Froxlor mydomain = -# set myhostname to $mydomain because Froxlor alrady uses a FQDN +# set myhostname to $mydomain because Froxlor already uses a FQDN myhostname = $mydomain mydestination = $myhostname, @@ -1537,7 +1537,7 @@ protocol sieve { # # If you want UIDL compatibility with other POP3 servers, use: # UW's ipop3d : %08Xv%08Xu -# Courier : %f or %v-%u (both might be used simultaneosly) +# Courier : %f or %v-%u (both might be used simultaneously) # Cyrus (<= 2.1.3) : %u # Cyrus (>= 2.1.4) : %v.%u # Dovecot v0.99.x : %v.%u @@ -1755,7 +1755,7 @@ driver = mysql # settings, like: host=sql1.host.org host=sql2.host.org # # pgsql: -# For available options, see the PostgreSQL documention for the +# For available options, see the PostgreSQL documentation for the # PQconnectdb function of libpq. # Use maxconns=n (default 5) to change how many connections Dovecot can # create to pgsql. @@ -2238,7 +2238,7 @@ ControlsLog /var/log/proftpd/controls.log DefaultRoot ~ # Reject rootlogin (just for security) RootLogin off -# Noo need to require valid shell, because user is virtual +# No need to require valid shell, because user is virtual RequireValidShell off @@ -2449,7 +2449,7 @@ aliases: files nisplus - + @@ -2459,7 +2459,7 @@ aliases: files nisplus chmod="0644"> *.log { missingok diff --git a/lib/configfiles/focal.xml b/lib/configfiles/focal.xml index 0a060b63..f0e4c462 100644 --- a/lib/configfiles/focal.xml +++ b/lib/configfiles/focal.xml @@ -375,7 +375,7 @@ exit "$RETVAL" # allow-axfr-ips Allow zonetransfers only to these subnets # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any speficied: +# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -918,7 +918,7 @@ gmysql-password= # allow-axfr-ips Allow zonetransfers only to these subnets # # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any speficied: +# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -2058,7 +2058,7 @@ driver = mysql # settings, like: host=sql1.host.org host=sql2.host.org # # pgsql: -# For available options, see the PostgreSQL documention for the +# For available options, see the PostgreSQL documentation for the # PQconnectdb function of libpq. # Use maxconns=n (default 5) to change how many connections Dovecot can # create to pgsql. @@ -3123,7 +3123,7 @@ protocol sieve { # # If you want UIDL compatibility with other POP3 servers, use: # UW's ipop3d : %08Xv%08Xu -# Courier : %f or %v-%u (both might be used simultaneosly) +# Courier : %f or %v-%u (both might be used simultaneously) # Cyrus (<= 2.1.3) : %u # Cyrus (>= 2.1.4) : %v.%u # Dovecot v0.99.x : %v.%u @@ -3381,7 +3381,7 @@ Port 21 # PassivePorts 49152 65534 # If your host was NATted, this option is useful in order to -# allow passive tranfers to work. You have to use your public +# allow passive transfers to work. You have to use your public # address and opening the passive ports used on your firewall as well. # MasqueradeAddress 1.2.3.4 @@ -3406,7 +3406,7 @@ Group nogroup # Umask 022 is a good standard umask to prevent new files and dirs # (second parm) from being group and world writable. Umask 022 022 -# Normally, we want files to be overwriteable. +# Normally, we want files to be overwritable. AllowOverwrite on # Uncomment this if you are using NIS or LDAP via NSS to retrieve passwords: @@ -3653,7 +3653,7 @@ SQLBackend mysql SQLEngine on SQLAuthenticate on # -# Use both a crypted or plaintext password +# Use both an encrypted or plaintext password SQLAuthTypes Crypt SQLAuthenticate users* groups* @@ -3711,7 +3711,7 @@ TLSVerifyClient off #TLSRequired on # Allow SSL/TLS renegotiations when the client requests them, but -# do not force the renegotations. Some clients do not support +# do not force the renegotiations. Some clients do not support # SSL/TLS renegotiations; when mod_tls forces a renegotiation, these # clients will close the data connection, or there will be a timeout # on an idle data connection. @@ -4019,7 +4019,7 @@ aliases: files chmod="0644"> *.log { missingok diff --git a/lib/configfiles/gentoo.xml b/lib/configfiles/gentoo.xml index 321eb26e..afa5e295 100644 --- a/lib/configfiles/gentoo.xml +++ b/lib/configfiles/gentoo.xml @@ -398,7 +398,7 @@ mail IN A # allow-axfr-ips Allow zonetransfers only to these subnets # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any speficied: +# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -927,7 +927,7 @@ gmysql-password= # allow-axfr-ips Allow zonetransfers only to these subnets # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any speficied: +# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -1587,7 +1587,7 @@ sendmail_path = /usr/sbin/sendmail # FQDN from Froxlor mydomain = -# set myhostname to $mydomain because Froxlor alrady uses a FQDN +# set myhostname to $mydomain because Froxlor already uses a FQDN myhostname = $mydomain mydestination = $myhostname, @@ -3762,7 +3762,7 @@ aliases: files - + @@ -3772,7 +3772,7 @@ aliases: files chmod="0644"> *.log { missingok diff --git a/lib/configfiles/stretch.xml b/lib/configfiles/stretch.xml index 2b1bb25e..67cdce50 100644 --- a/lib/configfiles/stretch.xml +++ b/lib/configfiles/stretch.xml @@ -377,7 +377,7 @@ exit "$RETVAL" # allow-axfr-ips Allow zonetransfers only to these subnets # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any speficied: +# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -920,7 +920,7 @@ gmysql-password= # allow-axfr-ips Allow zonetransfers only to these subnets # # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any speficied: +# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -2217,7 +2217,7 @@ debugger_command = # >$config_directory/$process_name.$process_id.log & sleep 5 # # Another possibility is to run gdb under a detached screen session. -# To attach to the screen sesssion, su root and run "screen -r +# To attach to the screen session, su root and run "screen -r # " where uniquely matches one of the detached # sessions (from "screen -list"). # @@ -2631,7 +2631,7 @@ driver = mysql # settings, like: host=sql1.host.org host=sql2.host.org # # pgsql: -# For available options, see the PostgreSQL documention for the +# For available options, see the PostgreSQL documentation for the # PQconnectdb function of libpq. # Use maxconns=n (default 5) to change how many connections Dovecot can # create to pgsql. @@ -3696,7 +3696,7 @@ protocol sieve { # # If you want UIDL compatibility with other POP3 servers, use: # UW's ipop3d : %08Xv%08Xu -# Courier : %f or %v-%u (both might be used simultaneosly) +# Courier : %f or %v-%u (both might be used simultaneously) # Cyrus (<= 2.1.3) : %u # Cyrus (>= 2.1.4) : %v.%u # Dovecot v0.99.x : %v.%u @@ -3954,7 +3954,7 @@ Port 21 # PassivePorts 49152 65534 # If your host was NATted, this option is useful in order to -# allow passive tranfers to work. You have to use your public +# allow passive transfers to work. You have to use your public # address and opening the passive ports used on your firewall as well. # MasqueradeAddress 1.2.3.4 @@ -3979,7 +3979,7 @@ Group nogroup # Umask 022 is a good standard umask to prevent new files and dirs # (second parm) from being group and world writable. Umask 022 022 -# Normally, we want files to be overwriteable. +# Normally, we want files to be overwritable. AllowOverwrite on # Uncomment this if you are using NIS or LDAP via NSS to retrieve passwords: @@ -4226,7 +4226,7 @@ SQLBackend mysql SQLEngine on SQLAuthenticate on # -# Use both a crypted or plaintext password +# Use both an encrypted or plaintext password SQLAuthTypes Crypt SQLAuthenticate users* groups* @@ -4284,7 +4284,7 @@ TLSVerifyClient off #TLSRequired on # Allow SSL/TLS renegotiations when the client requests them, but -# do not force the renegotations. Some clients do not support +# do not force the renegotiations. Some clients do not support # SSL/TLS renegotiations; when mod_tls forces a renegotiation, these # clients will close the data connection, or there will be a timeout # on an idle data connection. @@ -4584,7 +4584,7 @@ aliases: files chmod="0644"> *.log { missingok diff --git a/lib/configfiles/xenial.xml b/lib/configfiles/xenial.xml index 19a36c33..356c469b 100644 --- a/lib/configfiles/xenial.xml +++ b/lib/configfiles/xenial.xml @@ -388,7 +388,7 @@ exit "$RETVAL" # allow-axfr-ips Allow zonetransfers only to these subnets # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any speficied: +# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -931,7 +931,7 @@ gmysql-password= # allow-axfr-ips Allow zonetransfers only to these subnets # # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any speficied: +# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -2228,7 +2228,7 @@ debugger_command = # >$config_directory/$process_name.$process_id.log & sleep 5 # # Another possibility is to run gdb under a detached screen session. -# To attach to the screen sesssion, su root and run "screen -r +# To attach to the screen session, su root and run "screen -r # " where uniquely matches one of the detached # sessions (from "screen -list"). # @@ -2642,7 +2642,7 @@ driver = mysql # settings, like: host=sql1.host.org host=sql2.host.org # # pgsql: -# For available options, see the PostgreSQL documention for the +# For available options, see the PostgreSQL documentation for the # PQconnectdb function of libpq. # Use maxconns=n (default 5) to change how many connections Dovecot can # create to pgsql. @@ -3707,7 +3707,7 @@ protocol sieve { # # If you want UIDL compatibility with other POP3 servers, use: # UW's ipop3d : %08Xv%08Xu -# Courier : %f or %v-%u (both might be used simultaneosly) +# Courier : %f or %v-%u (both might be used simultaneously) # Cyrus (<= 2.1.3) : %u # Cyrus (>= 2.1.4) : %v.%u # Dovecot v0.99.x : %v.%u @@ -3965,7 +3965,7 @@ Port 21 # PassivePorts 49152 65534 # If your host was NATted, this option is useful in order to -# allow passive tranfers to work. You have to use your public +# allow passive transfers to work. You have to use your public # address and opening the passive ports used on your firewall as well. # MasqueradeAddress 1.2.3.4 @@ -3990,7 +3990,7 @@ Group nogroup # Umask 022 is a good standard umask to prevent new files and dirs # (second parm) from being group and world writable. Umask 022 022 -# Normally, we want files to be overwriteable. +# Normally, we want files to be overwritable. AllowOverwrite on # Uncomment this if you are using NIS or LDAP via NSS to retrieve passwords: @@ -4237,7 +4237,7 @@ SQLBackend mysql SQLEngine on SQLAuthenticate on # -# Use both a crypted or plaintext password +# Use both an encrypted or plaintext password SQLAuthTypes Crypt SQLAuthenticate users* groups* @@ -4295,7 +4295,7 @@ TLSVerifyClient off #TLSRequired on # Allow SSL/TLS renegotiations when the client requests them, but -# do not force the renegotations. Some clients do not support +# do not force the renegotiations. Some clients do not support # SSL/TLS renegotiations; when mod_tls forces a renegotiation, these # clients will close the data connection, or there will be a timeout # on an idle data connection. @@ -4595,7 +4595,7 @@ aliases: files chmod="0644"> *.log { missingok diff --git a/lib/init.php b/lib/init.php index 7a6d8b44..84c6e627 100644 --- a/lib/init.php +++ b/lib/init.php @@ -265,7 +265,7 @@ if (isset($s) && $s != "" && $nosession != 1) { } /** - * Language Managament + * Language Management */ $langs = array(); $languages = array(); @@ -279,7 +279,7 @@ while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { $langs[$row['language']][] = $row; // check for row[iso] cause older froxlor // versions didn't have that and it will - // lead to a lot of undfined variables + // lead to a lot of undefined variables // before the admin can even update if (isset($row['iso'])) { $iso[$row['iso']] = $row['language']; diff --git a/lng/czech.lng.php b/lng/czech.lng.php index 0b429793..0d19b467 100644 --- a/lng/czech.lng.php +++ b/lng/czech.lng.php @@ -923,7 +923,7 @@ $lng['admin']['ipsandports']['default_vhostconf_domain'] = 'Default vHost-settin $lng['serversettings']['ssl']['ssl_key_file']['title'] = 'Path to the SSL Keyfile'; $lng['serversettings']['ssl']['ssl_key_file']['description'] = 'Specify the path including the filename for the private-key file (.key mostly)'; $lng['serversettings']['ssl']['ssl_ca_file']['title'] = 'Path to the SSL CA certificate (optional)'; -$lng['serversettings']['ssl']['ssl_ca_file']['description'] = 'Client authentification, set this only if you know what it is.'; +$lng['serversettings']['ssl']['ssl_ca_file']['description'] = 'Client authentication, set this only if you know what it is.'; $lng['error']['usernamealreadyexists'] = 'The username %s already exists.'; @@ -1598,7 +1598,7 @@ $lng['admin']['ipsandports']['ssl_paste_description'] = 'Paste your complete cer $lng['admin']['ipsandports']['ssl_cert_file_content'] = 'Content of the ssl certificate'; $lng['admin']['ipsandports']['ssl_key_file_content'] = 'Content of the ssl (private-) key file'; $lng['admin']['ipsandports']['ssl_ca_file_content'] = 'Content of the ssl CA file (optional)'; -$lng['admin']['ipsandports']['ssl_ca_file_content_desc'] = '

Client authentification, set this only if you know what it is.'; +$lng['admin']['ipsandports']['ssl_ca_file_content_desc'] = '

Client authentication, set this only if you know what it is.'; $lng['admin']['ipsandports']['ssl_cert_chainfile_content'] = 'Content of the certificate chain file (optional)'; $lng['admin']['ipsandports']['ssl_cert_chainfile_content_desc'] = '

Mostly CA_Bundle, or similar, you probably want to set this if you bought a SSL certificate.'; $lng['error']['sslcertificateismissingprivatekey'] = 'You need to specify a private key for your certificate'; @@ -1608,7 +1608,7 @@ $lng['error']['sslcertificateinvalidcertkeypair'] = 'The given private-key does $lng['error']['sslcertificateinvalidca'] = 'The given CA certificate data does not seem to be a valid certificate'; $lng['error']['sslcertificateinvalidchain'] = 'The given certificate chain data does not seem to be a valid certificate'; $lng['serversettings']['customerssl_directory']['title'] = 'Webserver customer-ssl certificates-directory'; -$lng['serversettings']['customerssl_directory']['description'] = 'Where should customer-specified ssl-certificates be created?

NOTE: This folder\'s content gets deleted regulary so avoid storing data in there manually.
'; +$lng['serversettings']['customerssl_directory']['description'] = 'Where should customer-specified ssl-certificates be created?

NOTE: This folder\'s content gets deleted regularly so avoid storing data in there manually.
'; $lng['admin']['phpfpm.ininote'] = 'Not all values you may want to define can be used in the php-fpm pool configuration'; // Added in Froxlor 0.9.30 @@ -1914,7 +1914,7 @@ $lng['dnseditor']['records'] = 'záznamy'; $lng['error']['dns_notfoundorallowed'] = 'Domain not found or no permission'; $lng['serversettings']['dnseditorenable']['title'] = 'Enable DNS editor'; $lng['serversettings']['dnseditorenable']['description'] = 'Allows admins and customer to manage domain dns entries'; -$lng['dns']['howitworks'] = 'Here you can manage DNS entries for your domain. Note that froxlor will automatically generate NS/MX/A/AAAA records for you. The custom entries are prefered, only missing entries will be automatically generated.'; +$lng['dns']['howitworks'] = 'Here you can manage DNS entries for your domain. Note that froxlor will automatically generate NS/MX/A/AAAA records for you. The custom entries are preferred, only missing entries will be automatically generated.'; $lng['serversettings']['dns_server']['title'] = 'DNS server daemon'; $lng['serversettings']['dns_server']['description'] = 'Remember that daemons have to be configured using froxlors configuration templates'; @@ -1928,7 +1928,7 @@ $lng['serversettings']['panel_customer_hide_options']['description'] = 'Select i // Added in froxlor 0.9.38-rc1 $lng['serversettings']['allow_allow_customer_shell']['title'] = 'Allow customers to enable shell access for ftp-users'; -$lng['serversettings']['allow_allow_customer_shell']['description'] = 'Please note: Shell access allows the user to execute various binaries on your system. Use with extrem caution. Please only activate this if you REALLY know what you are doing!!!'; +$lng['serversettings']['allow_allow_customer_shell']['description'] = 'Please note: Shell access allows the user to execute various binaries on your system. Use with extreme caution. Please only activate this if you REALLY know what you are doing!!!'; $lng['serversettings']['available_shells']['title'] = 'List of available shells'; $lng['serversettings']['available_shells']['description'] = 'Comma separated list of shells that are available for the customer to chose from for their ftp-users.

Note that the default shell /bin/false will always be a choice (if enabled), even if this setting is empty. It is the default value for ftp-users in any case'; $lng['panel']['shell'] = 'Shell'; @@ -1989,7 +1989,7 @@ $lng['serversettings']['leapiversion']['title'] = "Choose Let's Encrypt ACME imp $lng['serversettings']['leapiversion']['description'] = "Currently only ACME v2 implementation for Let's Encrypt is supported."; $lng['admin']['phpsettings']['pass_authorizationheader'] = 'Add "-pass-header Authorization" / "CGIPassAuth On" to vhosts'; $lng['serversettings']['ssl']['ssl_protocols']['title'] = 'Configure the TLS protocol version'; -$lng['serversettings']['ssl']['ssl_protocols']['description'] = 'This is a list of ssl protocols that you want (or don\'t want) to use when using SSL. Notice: Some older browsers may not support the newest protcol versions.

Default value is:
TLSv1.2
'; +$lng['serversettings']['ssl']['ssl_protocols']['description'] = 'This is a list of ssl protocols that you want (or don\'t want) to use when using SSL. Notice: Some older browsers may not support the newest protocol versions.

Default value is:
TLSv1.2
'; $lng['serversettings']['phpfpm_settings']['limit_extensions']['title'] = 'Allowed extensions'; $lng['serversettings']['phpfpm_settings']['limit_extensions']['description'] = 'Limits the extensions of the main script FPM will allow to parse. This can prevent configuration mistakes on the web server side. You should only limit FPM to .php extensions to prevent malicious users to use other extensions to execute php code. Default value: .php'; $lng['phpfpm']['ini_flags'] = 'Enter possible php_flags for php.ini. One entry per line'; diff --git a/lng/english.lng.php b/lng/english.lng.php index e7fb8413..20379bdf 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -926,7 +926,7 @@ $lng['admin']['ipsandports']['default_vhostconf_domain'] = 'Default vHost-settin $lng['serversettings']['ssl']['ssl_key_file']['title'] = 'Path to the SSL Keyfile'; $lng['serversettings']['ssl']['ssl_key_file']['description'] = 'Specify the path including the filename for the private-key file (.key mostly)'; $lng['serversettings']['ssl']['ssl_ca_file']['title'] = 'Path to the SSL CA certificate (optional)'; -$lng['serversettings']['ssl']['ssl_ca_file']['description'] = 'Client authentification, set this only if you know what it is.'; +$lng['serversettings']['ssl']['ssl_ca_file']['description'] = 'Client authentication, set this only if you know what it is.'; $lng['error']['usernamealreadyexists'] = 'The username %s already exists.'; @@ -1601,7 +1601,7 @@ $lng['admin']['ipsandports']['ssl_paste_description'] = 'Paste your complete cer $lng['admin']['ipsandports']['ssl_cert_file_content'] = 'Content of the ssl certificate'; $lng['admin']['ipsandports']['ssl_key_file_content'] = 'Content of the ssl (private-) key file'; $lng['admin']['ipsandports']['ssl_ca_file_content'] = 'Content of the ssl CA file (optional)'; -$lng['admin']['ipsandports']['ssl_ca_file_content_desc'] = '

Client authentification, set this only if you know what it is.'; +$lng['admin']['ipsandports']['ssl_ca_file_content_desc'] = '

Client authentication, set this only if you know what it is.'; $lng['admin']['ipsandports']['ssl_cert_chainfile_content'] = 'Content of the certificate chain file (optional)'; $lng['admin']['ipsandports']['ssl_cert_chainfile_content_desc'] = '

Mostly CA_Bundle, or similar, you probably want to set this if you bought a SSL certificate.'; $lng['error']['sslcertificateismissingprivatekey'] = 'You need to specify a private key for your certificate'; @@ -1611,7 +1611,7 @@ $lng['error']['sslcertificateinvalidcertkeypair'] = 'The given private-key does $lng['error']['sslcertificateinvalidca'] = 'The given CA certificate data does not seem to be a valid certificate'; $lng['error']['sslcertificateinvalidchain'] = 'The given certificate chain data does not seem to be a valid certificate'; $lng['serversettings']['customerssl_directory']['title'] = 'Webserver customer-ssl certificates-directory'; -$lng['serversettings']['customerssl_directory']['description'] = 'Where should customer-specified ssl-certificates be created?

NOTE: This folder\'s content gets deleted regulary so avoid storing data in there manually.
'; +$lng['serversettings']['customerssl_directory']['description'] = 'Where should customer-specified ssl-certificates be created?

NOTE: This folder\'s content gets deleted regularly so avoid storing data in there manually.
'; $lng['admin']['phpfpm.ininote'] = 'Not all values you may want to define can be used in the php-fpm pool configuration'; // Added in Froxlor 0.9.30 @@ -1918,7 +1918,7 @@ $lng['dnseditor']['records'] = 'records'; $lng['error']['dns_notfoundorallowed'] = 'Domain not found or no permission'; $lng['serversettings']['dnseditorenable']['title'] = 'Enable DNS editor'; $lng['serversettings']['dnseditorenable']['description'] = 'Allows admins and customer to manage domain dns entries'; -$lng['dns']['howitworks'] = 'Here you can manage DNS entries for your domain. Note that froxlor will automatically generate NS/MX/A/AAAA records for you. The custom entries are prefered, only missing entries will be automatically generated.'; +$lng['dns']['howitworks'] = 'Here you can manage DNS entries for your domain. Note that froxlor will automatically generate NS/MX/A/AAAA records for you. The custom entries are preferred, only missing entries will be automatically generated.'; $lng['serversettings']['dns_server']['title'] = 'DNS server daemon'; $lng['serversettings']['dns_server']['description'] = 'Remember that daemons have to be configured using froxlors configuration templates'; @@ -1993,7 +1993,7 @@ $lng['serversettings']['leapiversion']['title'] = "Choose Let's Encrypt ACME imp $lng['serversettings']['leapiversion']['description'] = "Currently only ACME v2 implementation for Let's Encrypt is supported."; $lng['admin']['phpsettings']['pass_authorizationheader'] = 'Add "-pass-header Authorization" / "CGIPassAuth On" to vhosts'; $lng['serversettings']['ssl']['ssl_protocols']['title'] = 'Configure the TLS protocol version'; -$lng['serversettings']['ssl']['ssl_protocols']['description'] = 'This is a list of ssl protocols that you want (or don\'t want) to use when using SSL. Notice: Some older browsers may not support the newest protcol versions.

Default value is:
TLSv1.2
'; +$lng['serversettings']['ssl']['ssl_protocols']['description'] = 'This is a list of ssl protocols that you want (or don\'t want) to use when using SSL. Notice: Some older browsers may not support the newest protocol versions.

Default value is:
TLSv1.2
'; $lng['serversettings']['phpfpm_settings']['limit_extensions']['title'] = 'Allowed extensions'; $lng['serversettings']['phpfpm_settings']['limit_extensions']['description'] = 'Limits the extensions of the main script FPM will allow to parse. This can prevent configuration mistakes on the web server side. You should only limit FPM to .php extensions to prevent malicious users to use other extensions to execute php code. Default value: .php'; $lng['phpfpm']['ini_flags'] = 'Enter possible php_flags for php.ini. One entry per line'; diff --git a/templates/Sparkle/assets/js/circular.js b/templates/Sparkle/assets/js/circular.js index 085743bf..f755c7e6 100644 --- a/templates/Sparkle/assets/js/circular.js +++ b/templates/Sparkle/assets/js/circular.js @@ -56,7 +56,7 @@ $(document).ready(function() { // Draw percentages if (!isNaN(assigned) && available == "∞") { - // Unlimited ressource and assigned + // Unlimited resource and assigned if (assigned > used) { // Draw assigned as full circle circularCircle(canvas, 38, 0, 270, 4, assiColor); @@ -77,7 +77,7 @@ $(document).ready(function() { } circularText(canvas, 60, 42, 26, "∞"); } else if (!isNaN(assigned)) { - // Limited ressources but assigned + // Limited resources but assigned available = parseFloat(available); assignedP = Math.round(100 / available * assigned); @@ -92,7 +92,7 @@ $(document).ready(function() { circularCircle(canvas, 40, 0, 270, 8, unliColor); circularText(canvas, 60, 42, 26, "∞"); } else { - // Limited ressources + // Limited resources available = parseFloat(available); usedP = 100 / available * used; if (usedP < 1 && usedP > 0) { From f8e2bc7bffded78f8bf950805cf9019e0421a42d Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sun, 1 Aug 2021 19:00:33 +0200 Subject: [PATCH 252/319] Fix some typos in code (found by codespell) (#970) Signed-off-by: Stefan Weil --- admin_message.php | 14 +++++++------- lng/czech.lng.php | 6 +++--- lng/dutch.lng.php | 6 +++--- lng/english.lng.php | 6 +++--- lng/french.lng.php | 6 +++--- lng/german.lng.php | 6 +++--- lng/italian.lng.php | 6 +++--- lng/portugues.lng.php | 6 +++--- templates/Sparkle/admin/message/message.tpl | 4 ++-- 9 files changed, 30 insertions(+), 30 deletions(-) diff --git a/admin_message.php b/admin_message.php index 6f06156b..ce84da88 100644 --- a/admin_message.php +++ b/admin_message.php @@ -32,10 +32,10 @@ if ($page == 'message') { $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'viewed panel_message'); if (isset($_POST['send']) && $_POST['send'] == 'send') { - if ($_POST['receipient'] == 0 && $userinfo['customers_see_all'] == '1') { + if ($_POST['recipient'] == 0 && $userinfo['customers_see_all'] == '1') { $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'sending messages to admins'); $result = Database::query('SELECT `name`, `email` FROM `' . TABLE_PANEL_ADMINS . "`"); - } elseif ($_POST['receipient'] == 1) { + } elseif ($_POST['recipient'] == 1) { if ($userinfo['customers_see_all'] == '1') { $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'sending messages to ALL customers'); $result = Database::query('SELECT `firstname`, `name`, `company`, `email` FROM `' . TABLE_PANEL_CUSTOMERS . "`"); @@ -49,7 +49,7 @@ if ($page == 'message') { )); } } else { - \Froxlor\UI\Response::standard_error('noreceipientsgiven'); + \Froxlor\UI\Response::standard_error('norecipientsgiven'); } $subject = $_POST['subject']; @@ -105,7 +105,7 @@ if ($page == 'message') { $sentitems = isset($_GET['sentitems']) ? (int) $_GET['sentitems'] : 0; if ($sentitems == 0) { - $successmessage = $lng['message']['noreceipients']; + $successmessage = $lng['message']['norecipients']; } else { $successmessage = str_replace('%s', $sentitems, $lng['message']['success']); } @@ -116,12 +116,12 @@ if ($page == 'message') { } $action = ''; - $receipients = ''; + $recipients = ''; if ($userinfo['customers_see_all'] == '1') { - $receipients .= \Froxlor\UI\HTML::makeoption($lng['panel']['reseller'], 0); + $recipients .= \Froxlor\UI\HTML::makeoption($lng['panel']['reseller'], 0); } - $receipients .= \Froxlor\UI\HTML::makeoption($lng['panel']['customer'], 1); + $recipients .= \Froxlor\UI\HTML::makeoption($lng['panel']['customer'], 1); eval("echo \"" . \Froxlor\UI\Template::getTemplate('message/message') . "\";"); } diff --git a/lng/czech.lng.php b/lng/czech.lng.php index 0d19b467..d5cfcbcf 100644 --- a/lng/czech.lng.php +++ b/lng/czech.lng.php @@ -659,7 +659,7 @@ $lng['panel']['reseller'] = 'prodejce'; $lng['panel']['admin'] = 'admin'; $lng['panel']['customer'] = 'zákazník/ci'; $lng['error']['nomessagetosend'] = 'Nezadal/a jsi zprávu.'; -$lng['error']['noreceipientsgiven'] = 'Nespecifikoval/a jsi žádného příjemce'; +$lng['error']['norecipientsgiven'] = 'Nespecifikoval/a jsi žádného příjemce'; $lng['admin']['emaildomain'] = 'Emailová doména'; $lng['admin']['email_only'] = 'Jen email?'; $lng['admin']['wwwserveralias'] = 'Přidat "www." ServerAlias'; @@ -667,14 +667,14 @@ $lng['admin']['ipsandports']['enable_ssl'] = 'Je tohle SSL port?'; $lng['admin']['ipsandports']['ssl_cert_file'] = 'Cesta k SSL certifikátu'; $lng['panel']['send'] = 'odeslat'; $lng['admin']['subject'] = 'Předmět'; -$lng['admin']['receipient'] = 'Příjemce'; +$lng['admin']['recipient'] = 'Příjemce'; $lng['admin']['message'] = 'Napsat zprávu'; $lng['admin']['text'] = 'Zpráva'; $lng['menu']['message'] = 'Zprávy'; $lng['error']['errorsendingmail'] = 'Zpráva uživateli "%s" selhala'; $lng['error']['cannotreaddir'] = 'Nelze přečíst adresář "%s"'; $lng['message']['success'] = 'Zpráva úspěšně odeslána %s příjemcům,'; -$lng['message']['noreceipients'] = 'Email nebyl odeslán, protože databáze neobsahuje žádné příjemce'; +$lng['message']['norecipients'] = 'Email nebyl odeslán, protože databáze neobsahuje žádné příjemce'; $lng['admin']['sslsettings'] = 'SSL nastavení'; $lng['cronjobs']['notyetrun'] = 'Ještě nespuštěno'; $lng['serversettings']['default_vhostconf']['title'] = 'Výchozí vHost-nastavení'; diff --git a/lng/dutch.lng.php b/lng/dutch.lng.php index e1c3bf7d..6198b37a 100644 --- a/lng/dutch.lng.php +++ b/lng/dutch.lng.php @@ -587,7 +587,7 @@ $lng['panel']['reseller'] = 'wederverkoper'; $lng['panel']['admin'] = 'beheerder'; $lng['panel']['customer'] = 'klant(en)'; $lng['error']['nomessagetosend'] = 'U hebt geen bericht opgegeven.'; -$lng['error']['noreceipientsgiven'] = 'U hebt geen ontvanger opgegeven'; +$lng['error']['norecipientsgiven'] = 'U hebt geen ontvanger opgegeven'; $lng['admin']['emaildomain'] = 'Emaildomein'; $lng['admin']['email_only'] = 'Alleen email?'; $lng['admin']['wwwserveralias'] = 'Voeg een "www." ServerAlias toe'; @@ -595,14 +595,14 @@ $lng['admin']['ipsandports']['enable_ssl'] = 'Is dit een SSL-poort?'; $lng['admin']['ipsandports']['ssl_cert_file'] = 'Pad naar SSL-certificaat'; $lng['panel']['send'] = 'verzenden'; $lng['admin']['subject'] = 'Onderwerp'; -$lng['admin']['receipient'] = 'Ontvanger'; +$lng['admin']['recipient'] = 'Ontvanger'; $lng['admin']['message'] = 'Bericht schrijven'; $lng['admin']['text'] = 'Bericht'; $lng['menu']['message'] = 'Berichten'; $lng['error']['errorsendingmail'] = 'Het versturen van het bericht naar "%s" is mislukt'; $lng['error']['cannotreaddir'] = 'De map "%s" kan niet gelezen worden'; $lng['message']['success'] = 'Bericht verzonden naar ontvangers %s'; -$lng['message']['noreceipients'] = 'Er is geen email verstuurd omdat er geen ontvangers in de database zijn'; +$lng['message']['norecipients'] = 'Er is geen email verstuurd omdat er geen ontvangers in de database zijn'; $lng['admin']['sslsettings'] = 'Instellingen voor SSL'; $lng['cronjobs']['notyetrun'] = 'Nog niet uitgevoerd'; $lng['serversettings']['default_vhostconf']['title'] = 'Standaard vhost-instellingen'; diff --git a/lng/english.lng.php b/lng/english.lng.php index 20379bdf..576b2673 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -660,7 +660,7 @@ $lng['panel']['reseller'] = 'reseller'; $lng['panel']['admin'] = 'admin'; $lng['panel']['customer'] = 'customer/s'; $lng['error']['nomessagetosend'] = 'You did not enter a message.'; -$lng['error']['noreceipientsgiven'] = 'You did not specify any recipient'; +$lng['error']['norecipientsgiven'] = 'You did not specify any recipient'; $lng['admin']['emaildomain'] = 'Emaildomain'; $lng['admin']['email_only'] = 'Only email?'; $lng['admin']['wwwserveralias'] = 'Add a "www." ServerAlias'; @@ -668,14 +668,14 @@ $lng['admin']['ipsandports']['enable_ssl'] = 'Is this an SSL Port?'; $lng['admin']['ipsandports']['ssl_cert_file'] = 'Path to the SSL Certificate'; $lng['panel']['send'] = 'send'; $lng['admin']['subject'] = 'Subject'; -$lng['admin']['receipient'] = 'Recipient'; +$lng['admin']['recipient'] = 'Recipient'; $lng['admin']['message'] = 'Write a Message'; $lng['admin']['text'] = 'Message'; $lng['menu']['message'] = 'Messages'; $lng['error']['errorsendingmail'] = 'The message to "%s" failed'; $lng['error']['cannotreaddir'] = 'Unable to read directory "%s"'; $lng['message']['success'] = 'Successfully sent message to %s recipients'; -$lng['message']['noreceipients'] = 'No e-mail has been sent because there are no recipients in the database'; +$lng['message']['norecipients'] = 'No e-mail has been sent because there are no recipients in the database'; $lng['admin']['sslsettings'] = 'SSL settings'; $lng['cronjobs']['notyetrun'] = 'Not yet run'; $lng['serversettings']['default_vhostconf']['title'] = 'Default vHost-settings'; diff --git a/lng/french.lng.php b/lng/french.lng.php index 9920fa95..ab22cbfc 100644 --- a/lng/french.lng.php +++ b/lng/french.lng.php @@ -627,7 +627,7 @@ $lng['panel']['reseller'] = 'revendeur'; $lng['panel']['admin'] = 'administrateur'; $lng['panel']['customer'] = 'client(s)'; $lng['error']['nomessagetosend'] = 'Vous n\'avez pas entré de message.'; -$lng['error']['noreceipientsgiven'] = 'Vous n\'avez pas spécifier de destinataire'; +$lng['error']['norecipientsgiven'] = 'Vous n\'avez pas spécifier de destinataire'; $lng['admin']['emaildomain'] = 'Domaine e-mail'; $lng['admin']['email_only'] = 'Seulement des e-mails ?'; $lng['admin']['wwwserveralias'] = 'Ajouter un "www." à l\'alias du serveur "ServerAlias"'; @@ -635,14 +635,14 @@ $lng['admin']['ipsandports']['enable_ssl'] = 'Est-ce un port SSL ?'; $lng['admin']['ipsandports']['ssl_cert_file'] = 'Emplacement du certificat SSL'; $lng['panel']['send'] = 'envoyé'; $lng['admin']['subject'] = 'Sujet'; -$lng['admin']['receipient'] = 'Destinataire'; +$lng['admin']['recipient'] = 'Destinataire'; $lng['admin']['message'] = 'Ecrire un message'; $lng['admin']['text'] = 'Message'; $lng['menu']['message'] = 'Messages'; $lng['error']['errorsendingmail'] = 'Echec d\'envoi du message à "%s"'; $lng['error']['cannotreaddir'] = 'Impossible de lire dossier "%s"'; $lng['message']['success'] = 'Le message a été envoyé aux destinataires "%s"'; -$lng['message']['noreceipients'] = 'Aucun e-mail n\'a été envoyé car il n\'existe aucun destinataire dans la base de données'; +$lng['message']['norecipients'] = 'Aucun e-mail n\'a été envoyé car il n\'existe aucun destinataire dans la base de données'; $lng['admin']['sslsettings'] = 'Paramètres SSL'; $lng['cronjobs']['notyetrun'] = 'Pas encore lancé'; $lng['serversettings']['default_vhostconf']['title'] = 'Paramètres par défaut pour les vHosts'; diff --git a/lng/german.lng.php b/lng/german.lng.php index a13bf8e0..cec305f0 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -653,7 +653,7 @@ $lng['panel']['reseller'] = 'Reseller'; $lng['panel']['admin'] = 'Administrator'; $lng['panel']['customer'] = 'Kunde/n'; $lng['error']['nomessagetosend'] = 'Keine Nachricht angegeben'; -$lng['error']['noreceipientsgiven'] = 'Keine Empfänger angegeben'; +$lng['error']['norecipientsgiven'] = 'Keine Empfänger angegeben'; $lng['admin']['emaildomain'] = 'E-Mail-Domain'; $lng['admin']['email_only'] = 'Nur als E-Mail-Domain verwenden?'; $lng['admin']['wwwserveralias'] = 'Einen "www." ServerAlias hinzufügen'; @@ -661,14 +661,14 @@ $lng['admin']['ipsandports']['enable_ssl'] = 'Ist dies ein SSL-Port?'; $lng['admin']['ipsandports']['ssl_cert_file'] = 'Pfad zum Zertifikat'; $lng['panel']['send'] = 'Versenden'; $lng['admin']['subject'] = 'Betreff'; -$lng['admin']['receipient'] = 'Empfänger'; +$lng['admin']['recipient'] = 'Empfänger'; $lng['admin']['message'] = 'Rundmail senden'; $lng['admin']['text'] = 'Nachricht'; $lng['menu']['message'] = 'Nachrichten'; $lng['error']['errorsendingmail'] = 'Das Versenden der Nachricht an "%s" schlug fehl.'; $lng['error']['cannotreaddir'] = 'Der Ordner "%s" kann nicht gelesen werden'; $lng['message']['success'] = 'Nachricht erfolgreich an "%s" Empfänger gesendet'; -$lng['message']['noreceipients'] = 'Es wurde keine E-Mail versendet, da sich keine Empfänger in der Datenbank befinden'; +$lng['message']['norecipients'] = 'Es wurde keine E-Mail versendet, da sich keine Empfänger in der Datenbank befinden'; $lng['admin']['sslsettings'] = 'SSL-Einstellungen'; $lng['cronjobs']['notyetrun'] = 'Bisher nicht gestartet'; $lng['serversettings']['default_vhostconf']['title'] = 'Standard vHost-Einstellungen'; diff --git a/lng/italian.lng.php b/lng/italian.lng.php index d56ec21c..0807cd92 100644 --- a/lng/italian.lng.php +++ b/lng/italian.lng.php @@ -610,7 +610,7 @@ $lng['panel']['reseller'] = 'rivenditore'; $lng['panel']['admin'] = 'amministratore'; $lng['panel']['customer'] = 'cliente/i'; $lng['error']['nomessagetosend'] = 'Non hai inserito un messaggio.'; -$lng['error']['noreceipientsgiven'] = 'Non hai specificato alcun destinatario'; +$lng['error']['norecipientsgiven'] = 'Non hai specificato alcun destinatario'; $lng['admin']['emaildomain'] = 'Email dominio'; $lng['admin']['email_only'] = 'Solo email?'; $lng['admin']['wwwserveralias'] = 'Aggiungi a "www." ServerAlias'; @@ -618,14 +618,14 @@ $lng['admin']['ipsandports']['enable_ssl'] = 'Questa è una porta SSL?'; $lng['admin']['ipsandports']['ssl_cert_file'] = 'Percorso del certificato SSL (SSL certificate)'; $lng['panel']['send'] = 'invia'; $lng['admin']['subject'] = 'Oggetto'; -$lng['admin']['receipient'] = 'Destinatario'; +$lng['admin']['recipient'] = 'Destinatario'; $lng['admin']['message'] = 'Scrivi un messaggio'; $lng['admin']['text'] = 'Messaggio'; $lng['menu']['message'] = 'Messaggi'; $lng['error']['errorsendingmail'] = 'Il messaggio a "%s" fallito'; $lng['error']['cannotreaddir'] = 'Impossibile leggere la cartella "%s"'; $lng['message']['success'] = 'Inviato correttamente il messaggio a %s recipients'; -$lng['message']['noreceipients'] = 'Nessuna e-mail è stata inviata perch¸ non ci sono i destinatari nel database'; +$lng['message']['norecipients'] = 'Nessuna e-mail è stata inviata perch¸ non ci sono i destinatari nel database'; $lng['admin']['sslsettings'] = 'Impostazioni SSL'; $lng['cronjobs']['notyetrun'] = 'Non ancora avviato'; $lng['serversettings']['default_vhostconf']['title'] = 'Impostazioni default vhost'; diff --git a/lng/portugues.lng.php b/lng/portugues.lng.php index e97c3e95..98e3a1a5 100644 --- a/lng/portugues.lng.php +++ b/lng/portugues.lng.php @@ -554,7 +554,7 @@ $lng['panel']['reseller'] = 'Revenda'; $lng['panel']['admin'] = 'Administrador'; $lng['panel']['customer'] = 'Cliente(s)'; $lng['error']['nomessagetosend'] = 'Você não entrou com uma mensagem'; -$lng['error']['noreceipientsgiven'] = 'Você não especificou um destinatário'; +$lng['error']['norecipientsgiven'] = 'Você não especificou um destinatário'; $lng['admin']['emaildomain'] = 'Domínio de Email'; $lng['admin']['email_only'] = 'Somente Email?'; $lng['admin']['wwwserveralias'] = 'Adicionar um "www." ServerAlias'; @@ -562,14 +562,14 @@ $lng['admin']['ipsandports']['enable_ssl'] = 'Esta é uma porta SSL?'; $lng['admin']['ipsandports']['ssl_cert_file'] = 'Caminho para o certificado SSL'; $lng['panel']['send'] = 'Enviar'; $lng['admin']['subject'] = 'Assunto'; -$lng['admin']['receipient'] = 'Destinatário'; +$lng['admin']['recipient'] = 'Destinatário'; $lng['admin']['message'] = 'Escrever uma mensagem'; $lng['admin']['text'] = 'Mensagem'; $lng['menu']['message'] = 'Mensagens'; $lng['error']['errorsendingmail'] = 'A mensagem para "%s" falhou'; $lng['error']['cannotreaddir'] = 'Não é possível ler o diretório "%s"'; $lng['message']['success'] = 'Mensagens enviadas para %s destinatários com sucesso'; -$lng['message']['noreceipients'] = 'Email não enviado porque não tem destinatário no banco de dados'; +$lng['message']['norecipients'] = 'Email não enviado porque não tem destinatário no banco de dados'; $lng['admin']['sslsettings'] = 'Configuração de SSL'; $lng['cronjobs']['notyetrun'] = 'Ainda não está rodando'; $lng['serversettings']['default_vhostconf']['title'] = 'Configuração de Vhost padrão'; diff --git a/templates/Sparkle/admin/message/message.tpl b/templates/Sparkle/admin/message/message.tpl index eaacf581..f047150a 100644 --- a/templates/Sparkle/admin/message/message.tpl +++ b/templates/Sparkle/admin/message/message.tpl @@ -23,8 +23,8 @@ $header - - + + From bef5cedcd01f63a3d022bb697f6fb18edda9faaa Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Mon, 2 Aug 2021 16:58:34 +0200 Subject: [PATCH 253/319] only add link to customername when editing domain when panel.allow_domain_change_customer is false Signed-off-by: Michael Kaufmann --- admin_domains.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/admin_domains.php b/admin_domains.php index 67fbc77b..e4170e8b 100644 --- a/admin_domains.php +++ b/admin_domains.php @@ -594,8 +594,10 @@ if ($page == 'domains' || $page == 'overview') { } $result = \Froxlor\PhpHelper::htmlentitiesArray($result); - $result['customername'] .= ' (' . $customer['loginname'] . ')'; + if (Settings::Get('panel.allow_domain_change_customer') != '1') { + $result['customername'] .= ' (' . $customer['loginname'] . ')'; + } $domain_edit_data = include_once dirname(__FILE__) . '/lib/formfields/admin/domains/formfield.domains_edit.php'; $domain_edit_form = \Froxlor\UI\HtmlForm::genHTMLForm($domain_edit_data); From 0a1a3e023f6b2685179418363a414f691748a293 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Wed, 4 Aug 2021 13:44:13 +0200 Subject: [PATCH 254/319] check dns for lets encrypt when adding/editing domains and via cron; fixes #971 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Domains.php | 16 ++++++++++++++ lib/Froxlor/Api/Commands/SubDomains.php | 19 +++++++++++++++++ lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 6 ++++++ lng/english.lng.php | 1 + lng/german.lng.php | 1 + tests/Domains/DomainsTest.php | 22 ++++++++++++++++++++ tests/SubDomains/SubDomainsTest.php | 20 ++++++++++++++++++ 7 files changed, 85 insertions(+) diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php index 72dc7c09..8adbbff5 100644 --- a/lib/Froxlor/Api/Commands/Domains.php +++ b/lib/Froxlor/Api/Commands/Domains.php @@ -574,6 +574,14 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $include_specialsettings = 0; } + // 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); + if ($domain_ips == false || count(array_intersect($ssl_ipandports, $domain_ips)) <= 0) { + \Froxlor\UI\Response::standard_error('invaliddnsforletsencrypt', '', true); + } + } + // We can't enable let's encrypt for wildcard-domains if ($serveraliasoption == '0' && $letsencrypt == '1') { \Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt', '', true); @@ -1326,6 +1334,14 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $include_specialsettings = 0; } + // 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']); + if ($domain_ips == false || count(array_intersect($ssl_ipandports, $domain_ips)) <= 0) { + \Froxlor\UI\Response::standard_error('invaliddnsforletsencrypt', '', true); + } + } + // We can't enable let's encrypt for wildcard-domains if ($serveraliasoption == '0' && $letsencrypt == '1') { \Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt', '', true); diff --git a/lib/Froxlor/Api/Commands/SubDomains.php b/lib/Froxlor/Api/Commands/SubDomains.php index cb861f9f..21e68e63 100644 --- a/lib/Froxlor/Api/Commands/SubDomains.php +++ b/lib/Froxlor/Api/Commands/SubDomains.php @@ -2,6 +2,7 @@ namespace Froxlor\Api\Commands; use Froxlor\Database\Database; +use Froxlor\Domain\Domain; use Froxlor\Settings; /** @@ -230,6 +231,15 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc } } + // 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); + if ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) <= 0) { + \Froxlor\UI\Response::standard_error('invaliddnsforletsencrypt', '', true); + } + } + // Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated if ($ssl_redirect > 0 && $letsencrypt == 1) { $ssl_redirect = 2; @@ -595,6 +605,15 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc } } + // 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']); + if ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) <= 0) { + \Froxlor\UI\Response::standard_error('invaliddnsforletsencrypt', '', true); + } + } + // We can't enable let's encrypt for wildcard-domains if ($iswildcarddomain == '1' && $letsencrypt == '1') { \Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt'); diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index dc83ff19..686d4420 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -293,6 +293,12 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron // 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); } } } diff --git a/lng/english.lng.php b/lng/english.lng.php index 576b2673..1ebee0e6 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -2128,3 +2128,4 @@ $lng['serversettings']['froxlorusergroup']['title'] = 'Custom system group for a $lng['serversettings']['froxlorusergroup']['description'] = 'Usage of libnss-extrausers (system-settings) is required for this to take effect. An empty value skips creation or removes existing group.'; $lng['error']['local_group_exists'] = 'The given group already exists on the system.'; $lng['error']['local_group_invalid'] = 'The given group name is invalid'; +$lng['error']['invaliddnsforletsencrypt'] = 'The domains DNS does not include any of the chosen IP addresses. Let\'s Encrypt certificate generation not possible.'; diff --git a/lng/german.lng.php b/lng/german.lng.php index cec305f0..f0f2a6da 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -1774,3 +1774,4 @@ $lng['serversettings']['froxlorusergroup']['title'] = 'Benutzerdefinierte Gruppe $lng['serversettings']['froxlorusergroup']['description'] = 'Voraussetzung hierfür ist die Nutzung von libnss-extrausers (System-Einstellungen). Ein leerer Wert bedeutet, es wird keine Gruppe erstellt, bzw. vorhandene Gruppe wird entfernt.'; $lng['error']['local_group_exists'] = 'Die angegebene Gruppe existiert bereits auf dem System'; $lng['error']['local_group_invalid'] = 'Der angegebene Gruppen-Name ist nicht gültig'; +$lng['error']['invaliddnsforletsencrypt'] = 'Die DNS-Einträge der Domain enhalten keine der gewählten IP Adressen. Let\'s Encrypt Zertifikats-Erstellung ist nicht möglich.'; diff --git a/tests/Domains/DomainsTest.php b/tests/Domains/DomainsTest.php index 6d65c8bc..274bc0d3 100644 --- a/tests/Domains/DomainsTest.php +++ b/tests/Domains/DomainsTest.php @@ -24,6 +24,7 @@ class DomainsTest extends TestCase $json_result = Customers::getLocal($admin_userdata, array( 'loginname' => 'test1' ))->get(); + $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domain' => 'TEST.local', @@ -425,4 +426,25 @@ class DomainsTest extends TestCase 'domainname' => 'उदाहरण.भारत' ])->delete(); } + + public function testAdminDomainsAddDnsLetsEncryptFail() + { + global $admin_userdata; + // get customer + $json_result = Customers::getLocal($admin_userdata, array( + 'loginname' => 'test1' + ))->get(); + Settings::Set('system.le_domain_dnscheck', 1); + $customer_userdata = json_decode($json_result, true)['data']; + $data = [ + 'domain' => 'no-dns.local', + 'customerid' => $customer_userdata['customerid'], + 'letsencrypt' => 1, + 'description' => 'no dns domain' + ]; + + $this->expectExceptionCode(400); + $this->expectExceptionMessage('The domains DNS does not include any of the chosen IP addresses. Let\'s Encrypt certificate generation not possible.'); + Domains::getLocal($admin_userdata, $data)->add(); + } } diff --git a/tests/SubDomains/SubDomainsTest.php b/tests/SubDomains/SubDomainsTest.php index e6952555..91afbace 100644 --- a/tests/SubDomains/SubDomainsTest.php +++ b/tests/SubDomains/SubDomainsTest.php @@ -260,4 +260,24 @@ class SubDomainsTest extends TestCase $this->assertEquals('mysub.test2.local', $result['domain']); $this->assertEquals($customer_userdata['customerid'], $result['customerid']); } + + public function testCustomerSubDomainsAddDnsLetsEncryptFail() + { + global $admin_userdata; + // get customer + $json_result = Customers::getLocal($admin_userdata, array( + 'loginname' => 'test1' + ))->get(); + \Froxlor\Settings::Set('system.le_domain_dnscheck', 1); + $customer_userdata = json_decode($json_result, true)['data']; + $data = [ + 'subdomain' => 'nodns', + 'domain' => 'test2.local', + 'letsencrypt' => 1 + ]; + + $this->expectExceptionCode(400); + $this->expectExceptionMessage('The domains DNS does not include any of the chosen IP addresses. Let\'s Encrypt certificate generation not possible.'); + SubDomains::getLocal($customer_userdata, $data)->add(); + } } From eb49331b2116ec35e5bddf1dbc1f534d000a9664 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Wed, 4 Aug 2021 14:06:32 +0200 Subject: [PATCH 255/319] remove superfluous inserttask when editing domain as it will be called when there are actually changes to the domain earlier Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Domains.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php index 8adbbff5..7e6ae891 100644 --- a/lib/Froxlor/Api/Commands/Domains.php +++ b/lib/Froxlor/Api/Commands/Domains.php @@ -1718,9 +1718,6 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn "); Database::pexecute($_update_stmt, $_update_data, true, true); - // insert a rebuild-task - \Froxlor\System\Cronjob::inserttask('1'); - // Cleanup domain <-> ip mapping $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :id From 73e364d4ba866196f2c7841c89cbaee0200be107 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Wed, 4 Aug 2021 14:55:22 +0200 Subject: [PATCH 256/319] fix compare of old/new value of aliasdomain when editing a domain as customer to avoid unnecessary regeneration of configfiles Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/SubDomains.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Froxlor/Api/Commands/SubDomains.php b/lib/Froxlor/Api/Commands/SubDomains.php index 21e68e63..97b583a8 100644 --- a/lib/Froxlor/Api/Commands/SubDomains.php +++ b/lib/Froxlor/Api/Commands/SubDomains.php @@ -643,7 +643,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc \Froxlor\Domain\Domain::updateRedirectOfDomain($id, $redirectcode); } - if ($path != $result['documentroot'] || $isemaildomain != $result['isemaildomain'] || $wwwserveralias != $result['wwwserveralias'] || $iswildcarddomain != $result['iswildcarddomain'] || $aliasdomain != $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']) { + 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']) { $stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `documentroot` = :documentroot, From c967e585b5597dcb2abf9e6a971c4cef07d506ad Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 6 Aug 2021 08:11:06 +0200 Subject: [PATCH 257/319] avoid duplicate entries in mysql-access-host setting Signed-off-by: Michael Kaufmann --- lib/Froxlor/Validate/Check.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Froxlor/Validate/Check.php b/lib/Froxlor/Validate/Check.php index d5c1400f..01d627c4 100644 --- a/lib/Froxlor/Validate/Check.php +++ b/lib/Froxlor/Validate/Check.php @@ -74,7 +74,7 @@ class Check public static function checkMysqlAccessHost($fieldname, $fielddata, $newfieldvalue, $allnewfieldvalues) { - $mysql_access_host_array = array_map('trim', explode(',', $newfieldvalue)); + $mysql_access_host_array = array_unique(array_map('trim', explode(',', $newfieldvalue))); foreach ($mysql_access_host_array as $host_entry) { if (Validate::validate_ip2($host_entry, true, 'invalidip', true, true, true, true, false) == false && Validate::validateDomain($host_entry) == false && Validate::validateLocalHostname($host_entry) == false && $host_entry != '%') { From afd2d7b5e934738925a9d78fd47fd987a17cf643 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 8 Aug 2021 11:14:57 +0200 Subject: [PATCH 258/319] fix dns-validation in Domains.add() and Domains.update() when using Let's Encrypt DNS-check Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Domains.php | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php index 7e6ae891..9d8df59a 100644 --- a/lib/Froxlor/Api/Commands/Domains.php +++ b/lib/Froxlor/Api/Commands/Domains.php @@ -193,6 +193,27 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn 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, array( + 'id' => $id + )); + $result[] = $entry['ip']; + } + return $result; + } + /** * add new domain entry * @@ -577,7 +598,8 @@ 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); - if ($domain_ips == false || count(array_intersect($ssl_ipandports, $domain_ips)) <= 0) { + $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); } } @@ -1337,7 +1359,8 @@ 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']); - if ($domain_ips == false || count(array_intersect($ssl_ipandports, $domain_ips)) <= 0) { + $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); } } From f1887aaaf28428818e7d612ba1433cefe43995e9 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 13 Aug 2021 09:28:10 +0200 Subject: [PATCH 259/319] enable iterate_query in dovecot by default Signed-off-by: Michael Kaufmann --- lib/configfiles/bionic.xml | 2 +- lib/configfiles/bullseye.xml | 2 +- lib/configfiles/buster.xml | 2 +- lib/configfiles/centos7.xml | 3 +-- lib/configfiles/centos8.xml | 2 +- lib/configfiles/focal.xml | 2 +- lib/configfiles/stretch.xml | 2 +- lib/configfiles/xenial.xml | 2 +- 8 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/configfiles/bionic.xml b/lib/configfiles/bionic.xml index 0522b429..10e10ae1 100644 --- a/lib/configfiles/bionic.xml +++ b/lib/configfiles/bionic.xml @@ -2745,7 +2745,7 @@ user_query = SELECT CONCAT(homedir, maildir) AS home, CONCAT('maildir:', homedir password_query = SELECT username AS user, password_enc AS password, CONCAT(homedir, maildir) AS userdb_home, uid AS userdb_uid, gid AS userdb_gid, CONCAT('maildir:', homedir, maildir) AS userdb_mail, CONCAT('*:storage=', quota, 'M') as userdb_quota_rule FROM mail_users WHERE (username = '%u' OR email = '%u') AND ((imap = 1 AND '%Ls' = 'imap') OR (pop3 = 1 AND '%Ls' = 'pop3') OR ((postfix = 'Y' AND '%Ls' = 'smtp') OR (postfix = 'Y' AND '%Ls' = 'sieve'))) # Query to get a list of all usernames. -#iterate_query = SELECT username AS user FROM users +iterate_query = "SELECT username AS user FROM mail_users WHERE (imap = 1 OR pop3 = 1)" ]]> diff --git a/lib/configfiles/bullseye.xml b/lib/configfiles/bullseye.xml index 26de3086..5d8a7754 100644 --- a/lib/configfiles/bullseye.xml +++ b/lib/configfiles/bullseye.xml @@ -2707,7 +2707,7 @@ user_query = SELECT CONCAT(homedir, maildir) AS home, CONCAT('maildir:', homedir password_query = SELECT username AS user, password_enc AS password, CONCAT(homedir, maildir) AS userdb_home, uid AS userdb_uid, gid AS userdb_gid, CONCAT('maildir:', homedir, maildir) AS userdb_mail, CONCAT('*:storage=', quota, 'M') as userdb_quota_rule FROM mail_users WHERE (username = '%u' OR email = '%u') AND ((imap = 1 AND '%Ls' = 'imap') OR (pop3 = 1 AND '%Ls' = 'pop3') OR ((postfix = 'Y' AND '%Ls' = 'smtp') OR (postfix = 'Y' AND '%Ls' = 'sieve'))) # Query to get a list of all usernames. -#iterate_query = SELECT username AS user FROM mail_users +iterate_query = "SELECT username AS user FROM mail_users WHERE (imap = 1 OR pop3 = 1)" ]]> diff --git a/lib/configfiles/buster.xml b/lib/configfiles/buster.xml index b7b484bf..aec4da46 100644 --- a/lib/configfiles/buster.xml +++ b/lib/configfiles/buster.xml @@ -2707,7 +2707,7 @@ user_query = SELECT CONCAT(homedir, maildir) AS home, CONCAT('maildir:', homedir password_query = SELECT username AS user, password_enc AS password, CONCAT(homedir, maildir) AS userdb_home, uid AS userdb_uid, gid AS userdb_gid, CONCAT('maildir:', homedir, maildir) AS userdb_mail, CONCAT('*:storage=', quota, 'M') as userdb_quota_rule FROM mail_users WHERE (username = '%u' OR email = '%u') AND ((imap = 1 AND '%Ls' = 'imap') OR (pop3 = 1 AND '%Ls' = 'pop3') OR ((postfix = 'Y' AND '%Ls' = 'smtp') OR (postfix = 'Y' AND '%Ls' = 'sieve'))) # Query to get a list of all usernames. -#iterate_query = SELECT username AS user FROM mail_users +iterate_query = "SELECT username AS user FROM mail_users WHERE (imap = 1 OR pop3 = 1)" ]]> diff --git a/lib/configfiles/centos7.xml b/lib/configfiles/centos7.xml index 6ec83c48..df2c6fd9 100644 --- a/lib/configfiles/centos7.xml +++ b/lib/configfiles/centos7.xml @@ -1857,8 +1857,7 @@ user_query = SELECT CONCAT(homedir, maildir) AS home, CONCAT('maildir:', homedir # FROM users WHERE userid = '%u' # Query to get a list of all usernames. -#iterate_query = SELECT username AS user FROM users -iterate_query = SELECT username AS user FROM mail_users +iterate_query = "SELECT username AS user FROM mail_users WHERE (imap = 1 OR pop3 = 1)" ]]> diff --git a/lib/configfiles/centos8.xml b/lib/configfiles/centos8.xml index db55f89a..7fde8162 100644 --- a/lib/configfiles/centos8.xml +++ b/lib/configfiles/centos8.xml @@ -1859,7 +1859,7 @@ user_query = SELECT CONCAT(homedir, maildir) AS home, CONCAT('maildir:', homedir # Query to get a list of all usernames. #iterate_query = SELECT username AS user FROM users -iterate_query = SELECT username AS user FROM mail_users +iterate_query = "SELECT username AS user FROM mail_users WHERE (imap = 1 OR pop3 = 1)" ]]> diff --git a/lib/configfiles/focal.xml b/lib/configfiles/focal.xml index f0e4c462..111c4d1a 100644 --- a/lib/configfiles/focal.xml +++ b/lib/configfiles/focal.xml @@ -2161,7 +2161,7 @@ user_query = SELECT CONCAT(homedir, maildir) AS home, CONCAT('maildir:', homedir password_query = SELECT username AS user, password_enc AS password, CONCAT(homedir, maildir) AS userdb_home, uid AS userdb_uid, gid AS userdb_gid, CONCAT('maildir:', homedir, maildir) AS userdb_mail, CONCAT('*:storage=', quota, 'M') as userdb_quota_rule FROM mail_users WHERE (username = '%u' OR email = '%u') AND ((imap = 1 AND '%Ls' = 'imap') OR (pop3 = 1 AND '%Ls' = 'pop3') OR ((postfix = 'Y' AND '%Ls' = 'smtp') OR (postfix = 'Y' AND '%Ls' = 'sieve'))) # Query to get a list of all usernames. -#iterate_query = SELECT username AS user FROM users +iterate_query = "SELECT username AS user FROM mail_users WHERE (imap = 1 OR pop3 = 1)" ]]> diff --git a/lib/configfiles/stretch.xml b/lib/configfiles/stretch.xml index 67cdce50..9ccba11c 100644 --- a/lib/configfiles/stretch.xml +++ b/lib/configfiles/stretch.xml @@ -2734,7 +2734,7 @@ user_query = SELECT CONCAT(homedir, maildir) AS home, CONCAT('maildir:', homedir password_query = SELECT username AS user, password_enc AS password, CONCAT(homedir, maildir) AS userdb_home, uid AS userdb_uid, gid AS userdb_gid, CONCAT('maildir:', homedir, maildir) AS userdb_mail, CONCAT('*:storage=', quota, 'M') as userdb_quota_rule FROM mail_users WHERE (username = '%u' OR email = '%u') AND ((imap = 1 AND '%Ls' = 'imap') OR (pop3 = 1 AND '%Ls' = 'pop3') OR ((postfix = 'Y' AND '%Ls' = 'smtp') OR (postfix = 'Y' AND '%Ls' = 'sieve'))) # Query to get a list of all usernames. -#iterate_query = SELECT username AS user FROM users +iterate_query = "SELECT username AS user FROM mail_users WHERE (imap = 1 OR pop3 = 1)" ]]> diff --git a/lib/configfiles/xenial.xml b/lib/configfiles/xenial.xml index 356c469b..2ed4b59a 100644 --- a/lib/configfiles/xenial.xml +++ b/lib/configfiles/xenial.xml @@ -2745,7 +2745,7 @@ user_query = SELECT CONCAT(homedir, maildir) AS home, CONCAT('maildir:', homedir password_query = SELECT username AS user, password_enc AS password, CONCAT(homedir, maildir) AS userdb_home, uid AS userdb_uid, gid AS userdb_gid, CONCAT('maildir:', homedir, maildir) AS userdb_mail, CONCAT('*:storage=', quota, 'M') as userdb_quota_rule FROM mail_users WHERE (username = '%u' OR email = '%u') AND ((imap = 1 AND '%Ls' = 'imap') OR (pop3 = 1 AND '%Ls' = 'pop3') OR ((postfix = 'Y' AND '%Ls' = 'smtp') OR (postfix = 'Y' AND '%Ls' = 'sieve'))) # Query to get a list of all usernames. -#iterate_query = SELECT username AS user FROM users +iterate_query = "SELECT username AS user FROM mail_users WHERE (imap = 1 OR pop3 = 1)" ]]> From 67351ec3c2f2c62b7fa4bb83c8bb96e85791ea50 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 19 Aug 2021 12:00:09 +0200 Subject: [PATCH 260/319] Adding support for PowerDNS-Replication (#974) Adding support for powerdns-replication --- actions/admin/settings/160.nameserver.php | 13 ++++++++++++ install/froxlor.sql | 3 ++- .../updates/froxlor/0.10/update_0.10.inc.php | 7 +++++++ lib/Froxlor/Cron/Dns/PowerDNS.php | 21 +++++++++++-------- lib/Froxlor/Froxlor.php | 2 +- lng/english.lng.php | 2 ++ lng/german.lng.php | 2 ++ 7 files changed, 39 insertions(+), 11 deletions(-) diff --git a/actions/admin/settings/160.nameserver.php b/actions/admin/settings/160.nameserver.php index 463f413a..625089b7 100644 --- a/actions/admin/settings/160.nameserver.php +++ b/actions/admin/settings/160.nameserver.php @@ -99,6 +99,19 @@ return array( 'default' => '', 'save_method' => 'storeSettingField' ), + 'system_powerdns_mode' => array( + 'label' => $lng['serversettings']['powerdns_mode'], + 'settinggroup' => 'system', + 'varname' => 'powerdns_mode', + 'type' => 'option', + 'default' => 'Native', + 'option_mode' => 'one', + 'option_options' => array( + 'Native' => 'Native', + 'Master' => 'Master' + ), + 'save_method' => 'storeSettingField' + ), 'system_dns_createmailentry' => array( 'label' => $lng['serversettings']['mail_also_with_mxservers'], 'settinggroup' => 'system', diff --git a/install/froxlor.sql b/install/froxlor.sql index 3f793925..487f1208 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -611,6 +611,7 @@ opcache.interned_strings_buffer'), ('system', 'documentroot_use_default_value', '0'), ('system', 'passwordcryptfunc', '3'), ('system', 'axfrservers', ''), + ('system', 'powerdns_mode', 'Native'), ('system', 'customer_ssl_path', '/etc/ssl/froxlor-custom/'), ('system', 'allow_error_report_admin', '1'), ('system', 'allow_error_report_customer', '0'), @@ -722,7 +723,7 @@ opcache.interned_strings_buffer'), ('panel', 'logo_overridetheme', '0'), ('panel', 'logo_overridecustom', '0'), ('panel', 'version', '0.10.27'), - ('panel', 'db_version', '202107300'); + ('panel', 'db_version', '202108180'); DROP TABLE IF EXISTS `panel_tasks`; diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index 0eb6d0e2..572b309d 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -914,3 +914,10 @@ if (\Froxlor\Froxlor::isDatabaseVersion('202107260')) { lastStepStatus(0); \Froxlor\Froxlor::updateToDbVersion('202107300'); } + +if (\Froxlor\Froxlor::isDatabaseVersion('202107300')) { + showUpdateStep("Adds the possibility to select the PowerDNS Operation Mode", true); + Settings::AddNew("system.powerdns_mode", 'Native'); + lastStepStatus(0); + \Froxlor\Froxlor::updateToDbVersion('202108180'); +} diff --git a/lib/Froxlor/Cron/Dns/PowerDNS.php b/lib/Froxlor/Cron/Dns/PowerDNS.php index fa0e8d69..39556b2e 100644 --- a/lib/Froxlor/Cron/Dns/PowerDNS.php +++ b/lib/Froxlor/Cron/Dns/PowerDNS.php @@ -1,6 +1,8 @@ (2016-) * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt * @package Cron - * + * */ class PowerDNS extends DnsBase { @@ -111,15 +113,16 @@ class PowerDNS extends DnsBase private function insertZone($domainname, $serial = 0) { - $ins_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare(" - INSERT INTO domains set `name` = :domainname, `notified_serial` = :serial, `type` = 'NATIVE' + $ins_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare(" + INSERT INTO domains set `name` = :domainname, `notified_serial` = :serial, `type` = :type "); - $ins_stmt->execute(array( - 'domainname' => $domainname, - 'serial' => $serial - )); - $lastid = \Froxlor\Dns\PowerDNS::getDB()->lastInsertId(); - return $lastid; + $ins_stmt->execute(array( + '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 = "") diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index 6e5a7952..b121605b 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -10,7 +10,7 @@ final class Froxlor const VERSION = '0.10.27'; // Database version (YYYYMMDDC where C is a daily counter) - const DBVERSION = '202107300'; + const DBVERSION = '202108180'; // Distribution branding-tag (used for Debian etc.) const BRANDING = ''; diff --git a/lng/english.lng.php b/lng/english.lng.php index 1ebee0e6..51073260 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -1596,6 +1596,8 @@ $lng['serversettings']['panel_allow_theme_change_admin'] = 'Allow admins to chan $lng['serversettings']['panel_allow_theme_change_customer'] = 'Allow customers to change the theme'; $lng['serversettings']['axfrservers']['title'] = 'AXFR servers'; $lng['serversettings']['axfrservers']['description'] = 'A comma separated list of IP addresses allowed to transfer (AXFR) dns zones.'; +$lng['serversettings']['powerdns_mode']['title'] = 'PowerDNS Operation Mode'; +$lng['serversettings']['powerdns_mode']['description'] = 'Select the PoweDNS mode: Native for no replication (Default) / Master if DNS replication is needed.'; $lng['panel']['ssleditor'] = 'SSL settings for this domain'; $lng['admin']['ipsandports']['ssl_paste_description'] = 'Paste your complete certificate content in the textbox'; $lng['admin']['ipsandports']['ssl_cert_file_content'] = 'Content of the ssl certificate'; diff --git a/lng/german.lng.php b/lng/german.lng.php index f0f2a6da..cb6d976d 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -1320,6 +1320,8 @@ $lng['serversettings']['panel_allow_theme_change_admin'] = 'Erlaube Admins das T $lng['serversettings']['panel_allow_theme_change_customer'] = 'Erlaube Kunden das Theme zu wechseln'; $lng['serversettings']['axfrservers']['title'] = 'AXFR Server'; $lng['serversettings']['axfrservers']['description'] = 'Eine durch Kommas getrennte Liste von IP Adressen, die DNS-Zonen transferieren dürfen (AXFR).'; +$lng['serversettings']['powerdns_mode']['title'] = 'PowerDNS Operation Mode'; +$lng['serversettings']['powerdns_mode']['description'] = 'Wählen Sie den PowerDNS-Modus: Native für keine DNS-Replikation (Standard) / Master wenn eine DNS-Replikation benötigt wird.'; $lng['panel']['ssleditor'] = 'SSL-Einstellungen für diese Domain'; $lng['admin']['ipsandports']['ssl_paste_description'] = 'Bitte den Inhalt der Zertifikatsdatei in das Textfeld kopieren.'; $lng['admin']['ipsandports']['ssl_cert_file_content'] = 'Inhalt des SSL-Zertifikats (Certificate)'; From ec1c37aa064b491790c1caa9a78d0caf7fe15f28 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 20 Aug 2021 09:23:23 +0200 Subject: [PATCH 261/319] set version to 0.10.28 for upcoming release Signed-off-by: Michael Kaufmann --- install/froxlor.sql | 2 +- install/updates/froxlor/0.10/update_0.10.inc.php | 5 +++++ lib/Froxlor/Froxlor.php | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index 487f1208..ce4ac969 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -722,7 +722,7 @@ opcache.interned_strings_buffer'), ('panel', 'logo_image_login', ''), ('panel', 'logo_overridetheme', '0'), ('panel', 'logo_overridecustom', '0'), - ('panel', 'version', '0.10.27'), + ('panel', 'version', '0.10.28'), ('panel', 'db_version', '202108180'); diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index 572b309d..6eb090c0 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -921,3 +921,8 @@ if (\Froxlor\Froxlor::isDatabaseVersion('202107300')) { lastStepStatus(0); \Froxlor\Froxlor::updateToDbVersion('202108180'); } + +if (\Froxlor\Froxlor::isFroxlorVersion('0.10.27')) { + showUpdateStep("Updating from 0.10.27 to 0.10.28", false); + \Froxlor\Froxlor::updateToVersion('0.10.28'); +} diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index b121605b..22127e45 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -7,7 +7,7 @@ final class Froxlor { // Main version variable - const VERSION = '0.10.27'; + const VERSION = '0.10.28'; // Database version (YYYYMMDDC where C is a daily counter) const DBVERSION = '202108180'; From 4b22470872811fdd17da2c524db93a301724e3e0 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Wed, 25 Aug 2021 16:21:33 +0200 Subject: [PATCH 262/319] set php session security related settings (correctly in every case) Signed-off-by: Michael Kaufmann --- index.php | 6 ++++++ lib/init.php | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/index.php b/index.php index a8c33ea3..ee1031d0 100644 --- a/index.php +++ b/index.php @@ -28,6 +28,12 @@ if ($action == '') { } if (session_status() == PHP_SESSION_NONE) { + ini_set("session.name", "s"); + ini_set("url_rewriter.tags", ""); + ini_set("session.use_cookies", false); + ini_set("session.cookie_httponly", true); + ini_set("session.cookie_secure", $is_ssl); + session_id($s); session_start(); } diff --git a/lib/init.php b/lib/init.php index 84c6e627..11d48d10 100644 --- a/lib/init.php +++ b/lib/init.php @@ -161,7 +161,9 @@ $idna_convert = new \Froxlor\Idna\IdnaWrapper(); /** * If Froxlor was called via HTTPS -> enforce it for the next time by settings HSTS header according to settings */ +$is_ssl = false; if (isset($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off')) { + $is_ssl = true; $maxage = Settings::Get('system.hsts_maxage'); if (empty($maxage)) { $maxage = 0; @@ -217,6 +219,8 @@ if (isset($s) && $s != "" && $nosession != 1) { ini_set("session.name", "s"); ini_set("url_rewriter.tags", ""); ini_set("session.use_cookies", false); + ini_set("session.cookie_httponly", true); + ini_set("session.cookie_secure", $is_ssl); session_id($s); session_start(); $query = "SELECT `s`.*, `u`.* FROM `" . TABLE_PANEL_SESSIONS . "` `s` LEFT JOIN `"; From 5d375b784d3bbef634cdb714fab2340615385b79 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Wed, 25 Aug 2021 16:30:56 +0200 Subject: [PATCH 263/319] login action always goes to index.php Signed-off-by: Michael Kaufmann --- templates/Sparkle/login/fpwd.tpl | 2 +- templates/Sparkle/login/login.tpl | 2 +- templates/Sparkle/login/login_ftp.tpl | 41 --------------------------- templates/Sparkle/login/rpwd.tpl | 2 +- 4 files changed, 3 insertions(+), 44 deletions(-) delete mode 100644 templates/Sparkle/login/login_ftp.tpl diff --git a/templates/Sparkle/login/fpwd.tpl b/templates/Sparkle/login/fpwd.tpl index fa8c7d2e..50eaa305 100644 --- a/templates/Sparkle/login/fpwd.tpl +++ b/templates/Sparkle/login/fpwd.tpl @@ -10,7 +10,7 @@ $header
-
+
Froxlor - {$lng['login']['presend']}

diff --git a/templates/Sparkle/login/login.tpl b/templates/Sparkle/login/login.tpl index 670a4002..8944398f 100644 --- a/templates/Sparkle/login/login.tpl +++ b/templates/Sparkle/login/login.tpl @@ -25,7 +25,7 @@ $header

- +
diff --git a/templates/Sparkle/login/login_ftp.tpl b/templates/Sparkle/login/login_ftp.tpl deleted file mode 100644 index dd8ed686..00000000 --- a/templates/Sparkle/login/login_ftp.tpl +++ /dev/null @@ -1,41 +0,0 @@ - diff --git a/templates/Sparkle/login/rpwd.tpl b/templates/Sparkle/login/rpwd.tpl index 57f5cb14..6a25dba0 100644 --- a/templates/Sparkle/login/rpwd.tpl +++ b/templates/Sparkle/login/rpwd.tpl @@ -11,7 +11,7 @@ $header

{$lng['pwdreminder']['choosenew']}

-
+
Froxlor - {$lng['login']['presend']}

From 21983f27b6d4d85d8e0daea11171a4da2eb4adcd Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Wed, 25 Aug 2021 16:36:09 +0200 Subject: [PATCH 264/319] secure commonly used filename-variable against url manipulation Signed-off-by: Michael Kaufmann --- lib/init.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/init.php b/lib/init.php index 11d48d10..0448a244 100644 --- a/lib/init.php +++ b/lib/init.php @@ -103,7 +103,7 @@ unset($_); unset($value); unset($key); -$filename = htmlentities(basename($_SERVER['PHP_SELF'])); +$filename = htmlentities(basename($_SERVER['SCRIPT_NAME'])); // check whether the userdata file exists if (! file_exists(\Froxlor\Froxlor::getInstallDir() . '/lib/userdata.inc.php')) { From 319eec6124bbdec94846d994300aef0c13866c6f Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 27 Aug 2021 13:17:05 +0200 Subject: [PATCH 265/319] fix session for 2fa enabled logins Signed-off-by: Michael Kaufmann --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index ee1031d0..e59c1f5f 100644 --- a/index.php +++ b/index.php @@ -33,7 +33,7 @@ if (session_status() == PHP_SESSION_NONE) { ini_set("session.use_cookies", false); ini_set("session.cookie_httponly", true); ini_set("session.cookie_secure", $is_ssl); - session_id($s); + session_id('login'); session_start(); } From a47b790e19634cdd52bf322aa8791eb705b91466 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sat, 4 Sep 2021 09:30:44 +0200 Subject: [PATCH 266/319] actually integrate the new czech language file; refs #976 Signed-off-by: Michael Kaufmann --- install/froxlor.sql | 5 +++-- install/updates/froxlor/0.10/update_0.10.inc.php | 7 +++++++ lib/Froxlor/Froxlor.php | 2 +- lng/czech.lng.php | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index ce4ac969..5213d125 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -723,7 +723,7 @@ opcache.interned_strings_buffer'), ('panel', 'logo_overridetheme', '0'), ('panel', 'logo_overridecustom', '0'), ('panel', 'version', '0.10.28'), - ('panel', 'db_version', '202108180'); + ('panel', 'db_version', '202109040'); DROP TABLE IF EXISTS `panel_tasks`; @@ -822,7 +822,8 @@ INSERT INTO `panel_languages` (`id`, `language`, `iso`, `file`) VALUES (4, 'Português', 'pt', 'lng/portugues.lng.php'), (5, 'Italiano', 'it', 'lng/italian.lng.php'), (6, 'Nederlands', 'nl', 'lng/dutch.lng.php'), - (7, 'Svenska', 'sv', 'lng/swedish.lng.php'); + (7, 'Svenska', 'sv', 'lng/swedish.lng.php'), + (8, 'Česká republika', 'cs', 'lng/czech.lng.php'); DROP TABLE IF EXISTS `panel_syslog`; diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index 6eb090c0..47f5982b 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -926,3 +926,10 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.27')) { showUpdateStep("Updating from 0.10.27 to 0.10.28", false); \Froxlor\Froxlor::updateToVersion('0.10.28'); } + +if (\Froxlor\Froxlor::isDatabaseVersion('202108180')) { + showUpdateStep("Adding czech language file", true); + Database::query("INSERT INTO `" . TABLE_PANEL_LANGUAGE . "` SET `language` = 'Česká republika', `iso` = 'cs', `file` = 'lng/czech.lng.php'"); + lastStepStatus(0); + \Froxlor\Froxlor::updateToDbVersion('202109040'); +} diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index 22127e45..3f19e385 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -10,7 +10,7 @@ final class Froxlor const VERSION = '0.10.28'; // Database version (YYYYMMDDC where C is a daily counter) - const DBVERSION = '202108180'; + const DBVERSION = '202109040'; // Distribution branding-tag (used for Debian etc.) const BRANDING = ''; diff --git a/lng/czech.lng.php b/lng/czech.lng.php index d5cfcbcf..57340117 100644 --- a/lng/czech.lng.php +++ b/lng/czech.lng.php @@ -382,7 +382,7 @@ $lng['serversettings']['pathedit']['description'] = 'Měla by cesta být na výb $lng['serversettings']['nameservers']['title'] = 'Názvy serverů'; $lng['serversettings']['nameservers']['description'] = 'Seznam oddělený čárkami obsahující názvy hostitelů všech jmenných serverů. První bude primární.'; $lng['serversettings']['mxservers']['title'] = 'MX servery'; -$lng['serversettings']['mxservers']['description'] = 'Seznam oddělený čárkami obsahující dvojici čísla a jméno hostitele oddělené mezerou (např. \ '10 mx.example.com \ ') obsahující servery mx.'; +$lng['serversettings']['mxservers']['description'] = 'Seznam oddělený čárkami obsahující dvojici čísla a jméno hostitele oddělené mezerou (např. \'10 mx.example.com\') obsahující servery mx.'; /** * CHANGED BETWEEN 1.2.12 and 1.2.13 From e73523531ab2bd1047efc126a21acc4ba1fe97d5 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 24 Sep 2021 10:49:57 +0200 Subject: [PATCH 267/319] let user decide whether an existing database should be backup'ed and removed when installing froxlor; dont rely on parse_ini_file for OS check; enhance mysqldump so there is no issues with complex passwords and bash-escaping Signed-off-by: Michael Kaufmann --- install/lib/class.FroxlorInstall.php | 46 ++++++++++++++++++++++------ install/lng/english.lng.php | 3 ++ install/lng/german.lng.php | 3 ++ 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index b8eb2dcc..4bb2d7ca 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -163,6 +163,7 @@ class FroxlorInstall $this->_getPostField('mysql_host', '127.0.0.1'); $this->_getPostField('mysql_database', 'froxlor'); + $this->_getPostField('mysql_forcecreate', '0'); $this->_getPostField('mysql_unpriv_user', 'froxlor'); $this->_getPostField('mysql_unpriv_pass'); $this->_getPostField('mysql_root_user', 'root'); @@ -246,10 +247,12 @@ class FroxlorInstall $content .= $this->_status_message('green', "OK"); // check for existing db and create backup if so $content .= $this->_backupExistingDatabase($db_root); - // create unprivileged user and the database itself - $content .= $this->_createDatabaseAndUser($db_root); - // importing data to new database - $content .= $this->_importDatabaseData(); + if (!$this->_abort) { + // create unprivileged user and the database itself + $content .= $this->_createDatabaseAndUser($db_root); + // importing data to new database + $content .= $this->_importDatabaseData(); + } if (! $this->_abort) { // create DB object for new database $options = array( @@ -733,12 +736,16 @@ class FroxlorInstall )); $rows = $db_root->query("SELECT FOUND_ROWS()")->fetchColumn(); + $content .= $this->_status_message('begin', $this->_lng['install']['check_db_exists']); + // check result if ($result_stmt !== false && $rows > 0) { $tables_exist = true; } - if ($tables_exist) { + if ($tables_exist && (int)$this->_data['mysql_forcecreate'] > 0) { + // set status + $content .= $this->_status_message('orange', 'exists (' . $this->_data['mysql_database'] . ')'); // tell what's going on $content .= $this->_status_message('begin', $this->_lng['install']['backup_old_db']); @@ -755,17 +762,29 @@ class FroxlorInstall $mysql_dump = '/usr/local/bin/mysqldump'; } + // create temporary .cnf file + $cnffilename = "/tmp/froxlor_dump.cnf"; + $dumpcnf = "[mysqldump]".PHP_EOL."password=\"".$this->_data['mysql_root_pass']."\"".PHP_EOL; + file_put_contents($cnffilename, $dumpcnf); + if ($do_backup) { - $command = $mysql_dump . " " . escapeshellarg($this->_data['mysql_database']) . " -u " . escapeshellarg($this->_data['mysql_root_user']) . " --password='" . escapeshellarg($this->_data['mysql_root_pass']) . "' --result-file=" . $filename; - $output = exec($command); - if (stristr($output, "error")) { + $command = $mysql_dump . " --defaults-extra-file=" . $cnffilename . " " . escapeshellarg($this->_data['mysql_database']) . " -u " . escapeshellarg($this->_data['mysql_root_user']) . " --result-file=" . $filename; + $output = []; + exec($command, $output); + @unlink($cnffilename); + if (stristr(implode(" ", $output), "error") || !file_exists($filename)) { $content .= $this->_status_message('red', $this->_lng['install']['backup_failed']); + $this->_abort = true; } else { $content .= $this->_status_message('green', 'OK (' . $filename . ')'); } } else { $content .= $this->_status_message('red', $this->_lng['install']['backup_binary_missing']); + $this->_abort = true; } + } else { + $content .= $this->_status_message('red', $this->_lng['install']['db_exists']); + $this->_abort = true; } return $content; @@ -801,6 +820,8 @@ class FroxlorInstall $formdata .= $this->_getSectionItemString('mysql_host', true); // database $formdata .= $this->_getSectionItemString('mysql_database', true); + // database overwrite if exists? + $formdata .= $this->_getSectionItemYesNo('mysql_forcecreate', false); // unpriv-user has to be different from root if ($this->_data['mysql_unpriv_user'] == $this->_data['mysql_root_user']) { $style = 'blue'; @@ -1363,7 +1384,14 @@ class FroxlorInstall // read os-release if (file_exists('/etc/os-release')) { - $os_dist = parse_ini_file('/etc/os-release', false); + $os_dist_content = file_get_contents('/etc/os-release'); + $os_dist_arr = explode("\n", $os_dist_content); + $os_dist = []; + foreach ($os_dist_arr as $os_dist_line) { + if (empty(trim($os_dist_line))) continue; + $tmp = explode("=", $os_dist_line); + $os_dist[$tmp[0]] = str_replace('"', "", trim($tmp[1])); + } if (is_array($os_dist) && array_key_exists('ID', $os_dist) && array_key_exists('VERSION_ID', $os_dist)) { $os_version = explode('.', $os_dist['VERSION_ID'])[0]; } diff --git a/install/lng/english.lng.php b/install/lng/english.lng.php index e6e126c5..98967ca6 100644 --- a/install/lng/english.lng.php +++ b/install/lng/english.lng.php @@ -53,6 +53,7 @@ $lng['install']['welcometext'] = 'Thank you for choosing Froxlor. Please fill ou $lng['install']['database'] = 'Database connection'; $lng['install']['mysql_host'] = 'MySQL-Hostname'; $lng['install']['mysql_database'] = 'Database name'; +$lng['install']['mysql_forcecreate'] = 'Backup and overwrite database if exists?'; $lng['install']['mysql_unpriv_user'] = 'Username for the unprivileged MySQL-account'; $lng['install']['mysql_unpriv_pass'] = 'Password for the unprivileged MySQL-account'; $lng['install']['mysql_root_user'] = 'Username for the MySQL-root-account'; @@ -79,6 +80,8 @@ $lng['install']['testing_mysql_fail'] = 'There seems to be a problem with the da $lng['install']['backup_old_db'] = 'Creating backup of old database...'; $lng['install']['backup_binary_missing'] = 'Could not find mysqldump'; $lng['install']['backup_failed'] = 'Could not backup database'; +$lng['install']['check_db_exists'] = 'Checking database...'; +$lng['install']['db_exists'] = 'Unable to create database. A database with the same name exists and should not be overwritten'; $lng['install']['prepare_db'] = 'Preparing database...'; $lng['install']['create_mysqluser_and_db'] = 'Creating database and username...'; $lng['install']['testing_new_db'] = 'Testing if database and user have been created correctly...'; diff --git a/install/lng/german.lng.php b/install/lng/german.lng.php index 4c0aaf68..62493acb 100644 --- a/install/lng/german.lng.php +++ b/install/lng/german.lng.php @@ -53,6 +53,7 @@ $lng['install']['welcometext'] = 'Vielen Dank dass Sie sich für Froxlor entschi $lng['install']['database'] = 'Datenbankverbindung'; $lng['install']['mysql_host'] = 'MySQL-Hostname'; $lng['install']['mysql_database'] = 'Datenbank Name'; +$lng['install']['mysql_forcecreate'] = 'Datenbank sichern und überschreiben wenn vorhanden?'; $lng['install']['mysql_unpriv_user'] = 'Benutzername für den unprivilegierten MySQL-Account'; $lng['install']['mysql_unpriv_pass'] = 'Passwort für den unprivilegierten MySQL-Account'; $lng['install']['mysql_root_user'] = 'Benutzername für den MySQL-Root-Account'; @@ -79,6 +80,8 @@ $lng['install']['testing_mysql_fail'] = 'Bei der Verwendung der Datenbank gibt e $lng['install']['backup_old_db'] = 'Sicherung vorheriger Datenbank...'; $lng['install']['backup_binary_missing'] = 'Konnte mysqldump nicht finden'; $lng['install']['backup_failed'] = 'Sicherung fehlgeschlagen'; +$lng['install']['check_db_exists'] = 'Databenbank wird geprüft...'; +$lng['install']['db_exists'] = 'Datenbank kann nicht erstellt werden. Eine Datenbank mit dem selben Namen existiert bereits und soll nicht überschrieben werden.'; $lng['install']['prepare_db'] = 'Datenbank wird vorbereitet...'; $lng['install']['create_mysqluser_and_db'] = 'Erstelle Datenbank und Benutzer...'; $lng['install']['testing_new_db'] = 'Teste, ob Datenbank und Benutzer korrekt angelegt wurden...'; From 7feddf0aecd660ffe3802c303d83fdd9fc0247bb Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sat, 2 Oct 2021 12:38:17 +0200 Subject: [PATCH 268/319] generate unpredictable unique session ids Signed-off-by: Michael Kaufmann --- admin_admins.php | 2 +- admin_customers.php | 2 +- index.php | 2 +- install/lib/class.FroxlorInstall.php | 28 ++++++++++++++++++++++++++-- lib/Froxlor/Database/DbManager.php | 4 ++-- lib/Froxlor/Domain/Domain.php | 2 +- lib/Froxlor/Froxlor.php | 24 ++++++++++++++++++++++++ 7 files changed, 56 insertions(+), 8 deletions(-) diff --git a/admin_admins.php b/admin_admins.php index b404cf8c..3c8031d8 100644 --- a/admin_admins.php +++ b/admin_admins.php @@ -129,7 +129,7 @@ if ($page == 'admins' && $userinfo['change_serversettings'] == '1') { 'userid' => $userinfo['userid'] )); - $s = md5(uniqid(microtime(), 1)); + $s = \Froxlor\Froxlor::genSessionId(); $ins_stmt = Database::prepare(" INSERT INTO `" . TABLE_PANEL_SESSIONS . "` SET `hash` = :hash, `userid` = :userid, `ipaddress` = :ip, diff --git a/admin_customers.php b/admin_customers.php index af08c8d1..ac393f73 100644 --- a/admin_customers.php +++ b/admin_customers.php @@ -178,7 +178,7 @@ if ($page == 'customers' && $userinfo['customers'] != '0') { 'hash' => $s )); - $s = md5(uniqid(microtime(), 1)); + $s = \Froxlor\Froxlor::genSessionId(); $insert = Database::prepare(" INSERT INTO `" . TABLE_PANEL_SESSIONS . "` SET `hash` = :hash, diff --git a/index.php b/index.php index e59c1f5f..83ab7a4b 100644 --- a/index.php +++ b/index.php @@ -675,7 +675,7 @@ function finishLogin($userinfo) global $version, $dbversion, $remote_addr, $http_user_agent, $languages; if (isset($userinfo['userid']) && $userinfo['userid'] != '') { - $s = md5(uniqid(microtime(), 1)); + $s = \Froxlor\Froxlor::genSessionId(); if (isset($_POST['language'])) { $language = \Froxlor\Validate\Validate::validate($_POST['language'], 'language'); diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index 4bb2d7ca..62c6a66a 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -363,6 +363,30 @@ class FroxlorInstall return $content; } + /** + * generate safe unique token + * + * @param int $length + * @return string + */ + private 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 md5(uniqid(microtime(), 1)); + } + /** * create corresponding entries in froxlor database * @@ -406,8 +430,8 @@ class FroxlorInstall $content .= $this->_status_message('begin', $this->_lng['install']['adding_admin_user']); $ins_data = array( 'loginname' => $this->_data['admin_user'], - /* use SHA256 default crypt */ - 'password' => crypt($this->_data['admin_pass1'], '$5$' . md5(uniqid(microtime(), 1)) . md5(uniqid(microtime(), 1))), + /* use SHA256 default crypt */ + 'password' => crypt($this->_data['admin_pass1'], '$5$' . $this->genUniqueToken() . $this->genUniqueToken()), 'email' => 'admin@' . $this->_data['servername'], 'deflang' => $this->_languages[$this->_activelng] ); diff --git a/lib/Froxlor/Database/DbManager.php b/lib/Froxlor/Database/DbManager.php index d3b9296d..dc0f3d1b 100644 --- a/lib/Froxlor/Database/DbManager.php +++ b/lib/Froxlor/Database/DbManager.php @@ -82,10 +82,10 @@ class DbManager // get all usernames from db-manager $allsqlusers = $this->getManager()->getAllSqlUsers(); // generate random username - $username = $loginname . '-' . substr(md5(uniqid(microtime(), 1)), 20, 3); + $username = $loginname . '-' . substr(\Froxlor\Froxlor::genSessionId(), 20, 3); // check whether it exists on the DBMS while (in_array($username, $allsqlusers)) { - $username = $loginname . '-' . substr(md5(uniqid(microtime(), 1)), 20, 3); + $username = $loginname . '-' . substr(\Froxlor\Froxlor::genSessionId(), 20, 3); } } elseif (strtoupper(Settings::Get('customer.mysqlprefix')) == 'DBNAME') { $username = $loginname; diff --git a/lib/Froxlor/Domain/Domain.php b/lib/Froxlor/Domain/Domain.php index c70c6cac..a63a5ba5 100644 --- a/lib/Froxlor/Domain/Domain.php +++ b/lib/Froxlor/Domain/Domain.php @@ -340,7 +340,7 @@ class Domain // run remove command \Froxlor\FileDir::safe_exec($acmesh . $params); // remove certificates directory - @unlink($certificate_folder); + \Froxlor\FileDir::safe_exec('rm -rf ' . $certificate_folder); } } return true; diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index 3f19e385..58e73509 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -202,6 +202,30 @@ final class Froxlor return false; } + /** + * generate safe unique session id + * + * @param int $length + * @return string + */ + public static function genSessionId(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 md5(uniqid(microtime(), 1)); + } + /** * compare of froxlor versions * From 7ccbb37c4e1f5b879921f1a8df0f2da0a5688c4f Mon Sep 17 00:00:00 2001 From: Nick Ufer Date: Fri, 8 Oct 2021 08:28:32 +0200 Subject: [PATCH 269/319] feat: adds mysql tls support (#979) --- install/lib/class.FroxlorInstall.php | 27 +++++++++++++++++++++++++++ install/lng/english.lng.php | 2 ++ install/lng/german.lng.php | 2 ++ lib/Froxlor/Database/Database.php | 13 ++++++++++++- lib/Froxlor/Dns/PowerDNS.php | 5 +++++ 5 files changed, 48 insertions(+), 1 deletion(-) diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index 62c6a66a..7669381b 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -168,6 +168,8 @@ class FroxlorInstall $this->_getPostField('mysql_unpriv_pass'); $this->_getPostField('mysql_root_user', 'root'); $this->_getPostField('mysql_root_pass'); + $this->_getPostField('mysql_ssl_ca_file'); + $this->_getPostField('mysql_ssl_verify_server_certificate', 0); $this->_getPostField('admin_user', 'admin'); $this->_getPostField('admin_pass1'); $this->_getPostField('admin_pass2'); @@ -213,6 +215,12 @@ class FroxlorInstall $options = array( 'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8' ); + + if (!empty($this->_data['mysql_ssl_ca_file'])) { + $options[\PDO::MYSQL_ATTR_SSL_CA] = $this->_data['mysql_ssl_ca_file']; + $options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = (bool) $this->_data['mysql_ssl_verify_server_certificate']; + } + $dsn = "mysql:host=" . $this->_data['mysql_host'] . ";"; $fatal_fail = false; try { @@ -258,6 +266,12 @@ class FroxlorInstall $options = array( 'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8' ); + + if (!empty($this->_data['mysql_ssl_ca_file'])) { + $options[\PDO::MYSQL_ATTR_SSL_CA] = $this->_data['mysql_ssl_ca_file']; + $options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = (bool) $this->_data['mysql_ssl_verify_server_certificate']; + } + $dsn = "mysql:host=" . $this->_data['mysql_host'] . ";dbname=" . $this->_data['mysql_database'] . ";"; $another_fail = false; try { @@ -327,10 +341,14 @@ class FroxlorInstall $userdata .= "\$sql['user']='" . addcslashes($this->_data['mysql_unpriv_user'], "'\\") . "';\n"; $userdata .= "\$sql['password']='" . addcslashes($this->_data['mysql_unpriv_pass'], "'\\") . "';\n"; $userdata .= "\$sql['db']='" . addcslashes($this->_data['mysql_database'], "'\\") . "';\n"; + $userdata .= "\$sql['ssl']['caFile']='" . addcslashes($this->_data['mysql_ssl_ca_file'], "'\\") . "';\n"; + $userdata .= "\$sql['ssl']['verifyServerCertificate']='" . addcslashes($this->_data['mysql_ssl_verify_server_certificate'], "'\\") . "';\n"; $userdata .= "\$sql_root[0]['caption']='Default';\n"; $userdata .= "\$sql_root[0]['host']='" . addcslashes($this->_data['mysql_host'], "'\\") . "';\n"; $userdata .= "\$sql_root[0]['user']='" . addcslashes($this->_data['mysql_root_user'], "'\\") . "';\n"; $userdata .= "\$sql_root[0]['password']='" . addcslashes($this->_data['mysql_root_pass'], "'\\") . "';\n"; + $userdata .= "\$sql_root[0]['ssl']['caFile']='" . addcslashes($this->_data['mysql_ssl_ca_file'], "'\\") . "';\n"; + $userdata .= "\$sql_root[0]['ssl']['verifyServerCertificate']='" . addcslashes($this->_data['mysql_ssl_verify_server_certificate'], "'\\") . "';\n"; $userdata .= "// enable debugging to browser in case of SQL errors\n"; $userdata .= "\$sql['debug'] = false;\n"; $userdata .= "?>"; @@ -582,6 +600,12 @@ class FroxlorInstall $options = array( 'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8' ); + + if (!empty($this->_data['mysql_ssl_ca_file'])) { + $options[\PDO::MYSQL_ATTR_SSL_CA] = $this->_data['mysql_ssl_ca_file']; + $options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = (bool) $this->_data['mysql_ssl_verify_server_certificate']; + } + $dsn = "mysql:host=" . $this->_data['mysql_host'] . ";dbname=" . $this->_data['mysql_database'] . ";"; $fatal_fail = false; try { @@ -875,6 +899,9 @@ class FroxlorInstall } $formdata .= $this->_getSectionItemString('mysql_root_pass', true, $style, 'password'); + $formdata .= $this->_getSectionItemString('mysql_ssl_ca_file', false, $style); + $formdata .= $this->_getSectionItemYesNo('mysql_ssl_verify_server_certificate', false, $style); + /** * admin data */ diff --git a/install/lng/english.lng.php b/install/lng/english.lng.php index 98967ca6..8701a494 100644 --- a/install/lng/english.lng.php +++ b/install/lng/english.lng.php @@ -58,6 +58,8 @@ $lng['install']['mysql_unpriv_user'] = 'Username for the unprivileged MySQL-acco $lng['install']['mysql_unpriv_pass'] = 'Password for the unprivileged MySQL-account'; $lng['install']['mysql_root_user'] = 'Username for the MySQL-root-account'; $lng['install']['mysql_root_pass'] = 'Password for the MySQL-root-account'; +$lng['install']['mysql_ssl_ca_file'] = 'MySQL server certificate file path'; +$lng['install']['mysql_ssl_verify_server_certificate'] = 'Verify MySQL TLS certificate'; $lng['install']['admin_account'] = 'Administrator Account'; $lng['install']['admin_user'] = 'Administrator Username'; $lng['install']['admin_pass1'] = 'Administrator Password'; diff --git a/install/lng/german.lng.php b/install/lng/german.lng.php index 62493acb..8cde4390 100644 --- a/install/lng/german.lng.php +++ b/install/lng/german.lng.php @@ -58,6 +58,8 @@ $lng['install']['mysql_unpriv_user'] = 'Benutzername für den unprivilegierten M $lng['install']['mysql_unpriv_pass'] = 'Passwort für den unprivilegierten MySQL-Account'; $lng['install']['mysql_root_user'] = 'Benutzername für den MySQL-Root-Account'; $lng['install']['mysql_root_pass'] = 'Passwort für den MySQL-Root-Account'; +$lng['install']['mysql_ssl_ca_file'] = 'MySQL-Server Zertifikatspfad'; +$lng['install']['mysql_ssl_verify_server_certificate'] = 'Validieren des MySQL-Server Zertifikats'; $lng['install']['admin_account'] = 'Admin-Zugang'; $lng['install']['admin_user'] = 'Administrator-Benutzername'; $lng['install']['admin_pass1'] = 'Administrator-Passwort'; diff --git a/lib/Froxlor/Database/Database.php b/lib/Froxlor/Database/Database.php index fd498dee..5235cf11 100644 --- a/lib/Froxlor/Database/Database.php +++ b/lib/Froxlor/Database/Database.php @@ -279,6 +279,8 @@ class Database $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"]; @@ -286,6 +288,8 @@ class Database $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 @@ -297,7 +301,9 @@ class Database 'port' => $port, 'socket' => $socket, 'db' => $sql["db"], - 'caption' => $caption + 'caption' => $caption, + 'ssl_ca_file' => $sslCAFile, + 'ssl_verify_server_certificate' => $sslVerifyServerCertificate ); } @@ -321,6 +327,11 @@ class Database } 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"]; diff --git a/lib/Froxlor/Dns/PowerDNS.php b/lib/Froxlor/Dns/PowerDNS.php index b8ba6692..45262147 100644 --- a/lib/Froxlor/Dns/PowerDNS.php +++ b/lib/Froxlor/Dns/PowerDNS.php @@ -62,6 +62,11 @@ class PowerDNS } 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 From 7f13bd09daee8b0dd0088383ba6ea2900eb722f3 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 8 Oct 2021 08:39:22 +0200 Subject: [PATCH 270/319] add optional ssl parameters to powerdns-config-template Signed-off-by: Michael Kaufmann --- lib/configfiles/bionic.xml | 2 ++ lib/configfiles/bullseye.xml | 2 ++ lib/configfiles/buster.xml | 2 ++ lib/configfiles/focal.xml | 2 ++ lib/configfiles/gentoo.xml | 2 ++ lib/configfiles/stretch.xml | 2 ++ lib/configfiles/xenial.xml | 2 ++ 7 files changed, 14 insertions(+) diff --git a/lib/configfiles/bionic.xml b/lib/configfiles/bionic.xml index 10e10ae1..b9a2c01d 100644 --- a/lib/configfiles/bionic.xml +++ b/lib/configfiles/bionic.xml @@ -917,6 +917,8 @@ gmysql-dbname=pdns gmysql-user=powerdns gmysql-group=client gmysql-password= +#gmysql-ssl-ca-file= +#gmysql-ssl-verify-server-certificate=0 ]]> diff --git a/lib/configfiles/bullseye.xml b/lib/configfiles/bullseye.xml index 5d8a7754..48ad1ecf 100644 --- a/lib/configfiles/bullseye.xml +++ b/lib/configfiles/bullseye.xml @@ -891,6 +891,8 @@ gmysql-dbname=pdns gmysql-user=powerdns gmysql-group=client gmysql-password= +#gmysql-ssl-ca-file= +#gmysql-ssl-verify-server-certificate=0 ]]> diff --git a/lib/configfiles/buster.xml b/lib/configfiles/buster.xml index aec4da46..cb67bca9 100644 --- a/lib/configfiles/buster.xml +++ b/lib/configfiles/buster.xml @@ -891,6 +891,8 @@ gmysql-dbname=pdns gmysql-user=powerdns gmysql-group=client gmysql-password= +#gmysql-ssl-ca-file= +#gmysql-ssl-verify-server-certificate=0 ]]> diff --git a/lib/configfiles/focal.xml b/lib/configfiles/focal.xml index 111c4d1a..5a733992 100644 --- a/lib/configfiles/focal.xml +++ b/lib/configfiles/focal.xml @@ -904,6 +904,8 @@ gmysql-dbname=pdns gmysql-user=powerdns gmysql-group=client gmysql-password= +#gmysql-ssl-ca-file= +#gmysql-ssl-verify-server-certificate=0 ]]> diff --git a/lib/configfiles/gentoo.xml b/lib/configfiles/gentoo.xml index afa5e295..efeaf30b 100644 --- a/lib/configfiles/gentoo.xml +++ b/lib/configfiles/gentoo.xml @@ -912,6 +912,8 @@ gmysql-dbname=pdns gmysql-user=powerdns gmysql-group=client gmysql-password= +#gmysql-ssl-ca-file= +#gmysql-ssl-verify-server-certificate=0 ]]> diff --git a/lib/configfiles/stretch.xml b/lib/configfiles/stretch.xml index 9ccba11c..ce379257 100644 --- a/lib/configfiles/stretch.xml +++ b/lib/configfiles/stretch.xml @@ -906,6 +906,8 @@ gmysql-dbname=pdns gmysql-user=powerdns gmysql-group=client gmysql-password= +#gmysql-ssl-ca-file= +#gmysql-ssl-verify-server-certificate=0 ]]> diff --git a/lib/configfiles/xenial.xml b/lib/configfiles/xenial.xml index 2ed4b59a..a353294e 100644 --- a/lib/configfiles/xenial.xml +++ b/lib/configfiles/xenial.xml @@ -917,6 +917,8 @@ gmysql-dbname=pdns gmysql-user=powerdns gmysql-group=client gmysql-password= +#gmysql-ssl-ca-file= +#gmysql-ssl-verify-server-certificate=0 ]]> From 52135a1d3ac4c3ad37dab4fc7c483b3955bd655e Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 8 Oct 2021 08:46:58 +0200 Subject: [PATCH 271/319] set version to 0.10.29 for upcoming release Signed-off-by: Michael Kaufmann --- install/froxlor.sql | 2 +- install/updates/froxlor/0.10/update_0.10.inc.php | 5 +++++ lib/Froxlor/Froxlor.php | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index 5213d125..6fce25eb 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -722,7 +722,7 @@ opcache.interned_strings_buffer'), ('panel', 'logo_image_login', ''), ('panel', 'logo_overridetheme', '0'), ('panel', 'logo_overridecustom', '0'), - ('panel', 'version', '0.10.28'), + ('panel', 'version', '0.10.29'), ('panel', 'db_version', '202109040'); diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index 47f5982b..33020950 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -933,3 +933,8 @@ if (\Froxlor\Froxlor::isDatabaseVersion('202108180')) { lastStepStatus(0); \Froxlor\Froxlor::updateToDbVersion('202109040'); } + +if (\Froxlor\Froxlor::isFroxlorVersion('0.10.28')) { + showUpdateStep("Updating from 0.10.28 to 0.10.29", false); + \Froxlor\Froxlor::updateToVersion('0.10.29'); +} diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index 58e73509..053f0664 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -7,7 +7,7 @@ final class Froxlor { // Main version variable - const VERSION = '0.10.28'; + const VERSION = '0.10.29'; // Database version (YYYYMMDDC where C is a daily counter) const DBVERSION = '202109040'; From db1df84ef1f26403cfa78356fb33cc3d7be9fd22 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 10 Oct 2021 14:32:02 +0200 Subject: [PATCH 272/319] correct db-exists check in installation-process Signed-off-by: Michael Kaufmann --- install/lib/class.FroxlorInstall.php | 68 ++++++++++++++-------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index 7669381b..2bf61b5b 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -791,48 +791,50 @@ class FroxlorInstall $tables_exist = true; } - if ($tables_exist && (int)$this->_data['mysql_forcecreate'] > 0) { - // set status - $content .= $this->_status_message('orange', 'exists (' . $this->_data['mysql_database'] . ')'); - // tell what's going on - $content .= $this->_status_message('begin', $this->_lng['install']['backup_old_db']); + if ($tables_exist) { + if ((int)$this->_data['mysql_forcecreate'] > 0) { + // set status + $content .= $this->_status_message('orange', 'exists (' . $this->_data['mysql_database'] . ')'); + // tell what's going on + $content .= $this->_status_message('begin', $this->_lng['install']['backup_old_db']); - // create temporary backup-filename - $filename = "/tmp/froxlor_backup_" . date('YmdHi') . ".sql"; + // create temporary backup-filename + $filename = "/tmp/froxlor_backup_" . date('YmdHi') . ".sql"; - // look for mysqldump - $do_backup = false; - if (file_exists("/usr/bin/mysqldump")) { - $do_backup = true; - $mysql_dump = '/usr/bin/mysqldump'; - } elseif (file_exists("/usr/local/bin/mysqldump")) { - $do_backup = true; - $mysql_dump = '/usr/local/bin/mysqldump'; - } + // look for mysqldump + $do_backup = false; + if (file_exists("/usr/bin/mysqldump")) { + $do_backup = true; + $mysql_dump = '/usr/bin/mysqldump'; + } elseif (file_exists("/usr/local/bin/mysqldump")) { + $do_backup = true; + $mysql_dump = '/usr/local/bin/mysqldump'; + } - // create temporary .cnf file - $cnffilename = "/tmp/froxlor_dump.cnf"; - $dumpcnf = "[mysqldump]".PHP_EOL."password=\"".$this->_data['mysql_root_pass']."\"".PHP_EOL; - file_put_contents($cnffilename, $dumpcnf); + // create temporary .cnf file + $cnffilename = "/tmp/froxlor_dump.cnf"; + $dumpcnf = "[mysqldump]" . PHP_EOL . "password=\"" . $this->_data['mysql_root_pass'] . "\"" . PHP_EOL; + file_put_contents($cnffilename, $dumpcnf); - if ($do_backup) { - $command = $mysql_dump . " --defaults-extra-file=" . $cnffilename . " " . escapeshellarg($this->_data['mysql_database']) . " -u " . escapeshellarg($this->_data['mysql_root_user']) . " --result-file=" . $filename; - $output = []; - exec($command, $output); - @unlink($cnffilename); - if (stristr(implode(" ", $output), "error") || !file_exists($filename)) { - $content .= $this->_status_message('red', $this->_lng['install']['backup_failed']); - $this->_abort = true; + if ($do_backup) { + $command = $mysql_dump . " --defaults-extra-file=" . $cnffilename . " " . escapeshellarg($this->_data['mysql_database']) . " -u " . escapeshellarg($this->_data['mysql_root_user']) . " --result-file=" . $filename; + $output = []; + exec($command, $output); + @unlink($cnffilename); + if (stristr(implode(" ", $output), "error") || ! file_exists($filename)) { + $content .= $this->_status_message('red', $this->_lng['install']['backup_failed']); + $this->_abort = true; + } else { + $content .= $this->_status_message('green', 'OK (' . $filename . ')'); + } } else { - $content .= $this->_status_message('green', 'OK (' . $filename . ')'); + $content .= $this->_status_message('red', $this->_lng['install']['backup_binary_missing']); + $this->_abort = true; } } else { - $content .= $this->_status_message('red', $this->_lng['install']['backup_binary_missing']); + $content .= $this->_status_message('red', $this->_lng['install']['db_exists']); $this->_abort = true; } - } else { - $content .= $this->_status_message('red', $this->_lng['install']['db_exists']); - $this->_abort = true; } return $content; From c6f556c8d98e8aa1bacfea85881165b6c3931f8f Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 10 Oct 2021 14:45:17 +0200 Subject: [PATCH 273/319] set version to 0.10.29.1 for bugfix release Signed-off-by: Michael Kaufmann --- install/froxlor.sql | 2 +- install/updates/froxlor/0.10/update_0.10.inc.php | 5 +++++ lib/Froxlor/Froxlor.php | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index 6fce25eb..a05ba81f 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -722,7 +722,7 @@ opcache.interned_strings_buffer'), ('panel', 'logo_image_login', ''), ('panel', 'logo_overridetheme', '0'), ('panel', 'logo_overridecustom', '0'), - ('panel', 'version', '0.10.29'), + ('panel', 'version', '0.10.29.1'), ('panel', 'db_version', '202109040'); diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index 33020950..e7541083 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -938,3 +938,8 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.28')) { showUpdateStep("Updating from 0.10.28 to 0.10.29", false); \Froxlor\Froxlor::updateToVersion('0.10.29'); } + +if (\Froxlor\Froxlor::isFroxlorVersion('0.10.29')) { + showUpdateStep("Updating from 0.10.29 to 0.10.29.1", false); + \Froxlor\Froxlor::updateToVersion('0.10.29.1'); +} diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index 053f0664..f0af2086 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -7,7 +7,7 @@ final class Froxlor { // Main version variable - const VERSION = '0.10.29'; + const VERSION = '0.10.29.1'; // Database version (YYYYMMDDC where C is a daily counter) const DBVERSION = '202109040'; From eb592340b022298f62a0a3e8450dbfbe29585782 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Mon, 11 Oct 2021 18:33:48 +0200 Subject: [PATCH 274/319] use prepared statement for creating databases to avoid sql injections in custom db-names Signed-off-by: Michael Kaufmann --- lib/Froxlor/Database/Manager/DbManagerMySQL.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/Froxlor/Database/Manager/DbManagerMySQL.php b/lib/Froxlor/Database/Manager/DbManagerMySQL.php index bf2f01ca..70b6eee4 100644 --- a/lib/Froxlor/Database/Manager/DbManagerMySQL.php +++ b/lib/Froxlor/Database/Manager/DbManagerMySQL.php @@ -60,7 +60,10 @@ class DbManagerMySQL */ public function createDatabase($dbname = null) { - Database::query("CREATE DATABASE `" . $dbname . "`"); + $stmt = Database::prepare("CREATE DATABASE :dbname"); + Database::pexecute($stmt, [ + 'dbname' => $dbname + ]); } /** From 5009c625d8d9e672aa65acc81a65c2eccccaecad Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Mon, 11 Oct 2021 18:55:15 +0200 Subject: [PATCH 275/319] prep.statement cannot be used for create database query; regex-validate database_name Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Mysqls.php | 2 +- lib/Froxlor/Database/Manager/DbManagerMySQL.php | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/Froxlor/Api/Commands/Mysqls.php b/lib/Froxlor/Api/Commands/Mysqls.php index 19d95d6f..ec1d6dfb 100644 --- a/lib/Froxlor/Api/Commands/Mysqls.php +++ b/lib/Froxlor/Api/Commands/Mysqls.php @@ -61,7 +61,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true); $password = \Froxlor\System\Crypt::validatePassword($password, true); $databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', '', '', array(), true); - $databasename = \Froxlor\Validate\Validate::validate(trim($databasename), 'database_name', '', '', array(), true); + $databasename = \Froxlor\Validate\Validate::validate(trim($databasename), 'database_name', '/^[A-Za-z0-9][A-Za-z0-9\-_]+$/i', '', array(), true); // validate whether the dbserver exists $dbserver = \Froxlor\Validate\Validate::validate($dbserver, html_entity_decode($this->lng['mysql']['mysql_server']), '', '', 0, true); diff --git a/lib/Froxlor/Database/Manager/DbManagerMySQL.php b/lib/Froxlor/Database/Manager/DbManagerMySQL.php index 70b6eee4..3bb9040d 100644 --- a/lib/Froxlor/Database/Manager/DbManagerMySQL.php +++ b/lib/Froxlor/Database/Manager/DbManagerMySQL.php @@ -60,10 +60,7 @@ class DbManagerMySQL */ public function createDatabase($dbname = null) { - $stmt = Database::prepare("CREATE DATABASE :dbname"); - Database::pexecute($stmt, [ - 'dbname' => $dbname - ]); + Database::query("CREATE DATABASE `" . Database::quote($dbname) . "`"); } /** From 5d2f44ecd845e178df77b34017285af5c2c292f9 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Mon, 11 Oct 2021 18:59:26 +0200 Subject: [PATCH 276/319] only validate custom database name if used at all Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Mysqls.php | 4 +++- lib/Froxlor/Api/Commands/SubDomains.php | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/Froxlor/Api/Commands/Mysqls.php b/lib/Froxlor/Api/Commands/Mysqls.php index ec1d6dfb..5083efd5 100644 --- a/lib/Froxlor/Api/Commands/Mysqls.php +++ b/lib/Froxlor/Api/Commands/Mysqls.php @@ -61,7 +61,9 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true); $password = \Froxlor\System\Crypt::validatePassword($password, true); $databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', '', '', array(), true); - $databasename = \Froxlor\Validate\Validate::validate(trim($databasename), 'database_name', '/^[A-Za-z0-9][A-Za-z0-9\-_]+$/i', '', array(), true); + if (!empty($databasename)) { + $databasename = \Froxlor\Validate\Validate::validate(trim($databasename), 'database_name', '/^[A-Za-z0-9][A-Za-z0-9\-_]+$/i', '', array(), true); + } // validate whether the dbserver exists $dbserver = \Froxlor\Validate\Validate::validate($dbserver, html_entity_decode($this->lng['mysql']['mysql_server']), '', '', 0, true); diff --git a/lib/Froxlor/Api/Commands/SubDomains.php b/lib/Froxlor/Api/Commands/SubDomains.php index 97b583a8..e5503f9d 100644 --- a/lib/Froxlor/Api/Commands/SubDomains.php +++ b/lib/Froxlor/Api/Commands/SubDomains.php @@ -262,6 +262,16 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $phpsid_result['phpsettingid'] = intval($phpsettingid); } + $allowed_phpconfigs = $this->getUserDetail('allowed_phpconfigs'); + if (! empty($allowed_phpconfigs)) { + $allowed_phpconfigs = json_decode($allowed_phpconfigs, true); + } else { + $allowed_phpconfigs = []; + } + if (! in_array($phpsid_result['phpsettingid'], $allowed_phpconfigs)) { + \Froxlor\UI\Response::dynamic_error('Trying to use php-config which is not assigned to customer'); + } + // actually insert domain $stmt = Database::prepare(" INSERT INTO `" . TABLE_PANEL_DOMAINS . "` SET @@ -638,6 +648,16 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $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']) . "'"); } + $allowed_phpconfigs = $customer['allowed_phpconfigs']; + if (! empty($allowed_phpconfigs)) { + $allowed_phpconfigs = json_decode($allowed_phpconfigs, true); + } else { + $allowed_phpconfigs = []; + } + if (! in_array($phpsettingid, $allowed_phpconfigs)) { + \Froxlor\UI\Response::dynamic_error('Trying to use php-config which is not assigned to customer'); + } + // handle redirect if ($_doredirect) { \Froxlor\Domain\Domain::updateRedirectOfDomain($id, $redirectcode); From 5e281cf486842ff1eb6071e7c4f265b518f0c29b Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Mon, 11 Oct 2021 19:26:13 +0200 Subject: [PATCH 277/319] fix allowed-phpconfigs check in SubDomains.add() and SubDomains.update() Signed-off-by: Michael Kaufmann --- install/lib/class.FroxlorInstall.php | 2 ++ lib/Froxlor/Api/Commands/SubDomains.php | 8 ++++---- lib/Froxlor/Database/Manager/DbManagerMySQL.php | 2 +- lng/english.lng.php | 1 + lng/german.lng.php | 1 + tests/bootstrap.php | 17 ++++++++++++++--- 6 files changed, 23 insertions(+), 8 deletions(-) diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index 2bf61b5b..30855bfa 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -835,6 +835,8 @@ class FroxlorInstall $content .= $this->_status_message('red', $this->_lng['install']['db_exists']); $this->_abort = true; } + } else { + $content .= $content .= $this->_status_message('green', 'OK'); } return $content; diff --git a/lib/Froxlor/Api/Commands/SubDomains.php b/lib/Froxlor/Api/Commands/SubDomains.php index e5503f9d..3bc1efb5 100644 --- a/lib/Froxlor/Api/Commands/SubDomains.php +++ b/lib/Froxlor/Api/Commands/SubDomains.php @@ -262,14 +262,14 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $phpsid_result['phpsettingid'] = intval($phpsettingid); } - $allowed_phpconfigs = $this->getUserDetail('allowed_phpconfigs'); + $allowed_phpconfigs = $customer['allowed_phpconfigs']; if (! empty($allowed_phpconfigs)) { $allowed_phpconfigs = json_decode($allowed_phpconfigs, true); } else { $allowed_phpconfigs = []; } if (! in_array($phpsid_result['phpsettingid'], $allowed_phpconfigs)) { - \Froxlor\UI\Response::dynamic_error('Trying to use php-config which is not assigned to customer'); + \Froxlor\UI\Response::standard_error('notallowedphpconfigused', '', true); } // actually insert domain @@ -626,7 +626,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc // We can't enable let's encrypt for wildcard-domains if ($iswildcarddomain == '1' && $letsencrypt == '1') { - \Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt'); + \Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt', '', true); } // Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated @@ -655,7 +655,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $allowed_phpconfigs = []; } if (! in_array($phpsettingid, $allowed_phpconfigs)) { - \Froxlor\UI\Response::dynamic_error('Trying to use php-config which is not assigned to customer'); + \Froxlor\UI\Response::standard_error('notallowedphpconfigused', '', true); } // handle redirect diff --git a/lib/Froxlor/Database/Manager/DbManagerMySQL.php b/lib/Froxlor/Database/Manager/DbManagerMySQL.php index 3bb9040d..bf2f01ca 100644 --- a/lib/Froxlor/Database/Manager/DbManagerMySQL.php +++ b/lib/Froxlor/Database/Manager/DbManagerMySQL.php @@ -60,7 +60,7 @@ class DbManagerMySQL */ public function createDatabase($dbname = null) { - Database::query("CREATE DATABASE `" . Database::quote($dbname) . "`"); + Database::query("CREATE DATABASE `" . $dbname . "`"); } /** diff --git a/lng/english.lng.php b/lng/english.lng.php index 51073260..20389f17 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -2131,3 +2131,4 @@ $lng['serversettings']['froxlorusergroup']['description'] = 'Usage of libnss-ext $lng['error']['local_group_exists'] = 'The given group already exists on the system.'; $lng['error']['local_group_invalid'] = 'The given group name is invalid'; $lng['error']['invaliddnsforletsencrypt'] = 'The domains DNS does not include any of the chosen IP addresses. Let\'s Encrypt certificate generation not possible.'; +$lng['error']['notallowedphpconfigused'] = 'Trying to use php-config which is not assigned to customer'; diff --git a/lng/german.lng.php b/lng/german.lng.php index cb6d976d..b00dd44b 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -1777,3 +1777,4 @@ $lng['serversettings']['froxlorusergroup']['description'] = 'Voraussetzung hierf $lng['error']['local_group_exists'] = 'Die angegebene Gruppe existiert bereits auf dem System'; $lng['error']['local_group_invalid'] = 'Der angegebene Gruppen-Name ist nicht gültig'; $lng['error']['invaliddnsforletsencrypt'] = 'Die DNS-Einträge der Domain enhalten keine der gewählten IP Adressen. Let\'s Encrypt Zertifikats-Erstellung ist nicht möglich.'; +$lng['error']['notallowedphpconfigused'] = 'Nutzung einer PHP-Konfiguration welche nicht dem Kunden zugeordnet ist'; diff --git a/tests/bootstrap.php b/tests/bootstrap.php index e2d5aeac..0b13022f 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -43,14 +43,25 @@ require dirname(__DIR__) . '/lib/tables.inc.php'; use Froxlor\Database\Database; use Froxlor\Settings; -Database::needRoot(true); if (TRAVIS_CI == 0) { + Database::needRoot(true); Database::query("DROP DATABASE IF EXISTS `froxlor010`;"); Database::query("CREATE DATABASE `froxlor010`;"); exec("mysql -u root -p" . $rpwd . " froxlor010 < " . dirname(__DIR__) . "/install/froxlor.sql"); + Database::query("DROP USER IF EXISTS 'test1sql1'@'localhost';"); + Database::query("DROP USER IF EXISTS 'test1sql1'@'127.0.0.1';"); + Database::query("DROP USER IF EXISTS 'test1sql1'@'172.17.0.1';"); + Database::query("DROP USER IF EXISTS 'test1sql1'@'82.149.225.46';"); + Database::query("DROP USER IF EXISTS 'test1sql1'@'2a01:440:1:12:82:149:225:46';"); + Database::query("DROP USER IF EXISTS 'test1_abc123'@'localhost';"); + Database::query("DROP USER IF EXISTS 'test1_abc123'@'127.0.0.1';"); + Database::query("DROP USER IF EXISTS 'test1_abc123'@'172.17.0.1';"); + Database::query("DROP USER IF EXISTS 'test1_abc123'@'82.149.225.46';"); + Database::query("DROP USER IF EXISTS 'test1_abc123'@'2a01:440:1:12:82:149:225:46';"); + Database::query("DROP DATABASE IF EXISTS `test1sql1`;"); + Database::query("DROP DATABASE IF EXISTS `test1_abc123`;"); + Database::needRoot(false); } -Database::query("DROP DATABASE IF EXISTS `test1sql1`;"); -Database::needRoot(false); // clear all tables Database::query("TRUNCATE TABLE `" . TABLE_PANEL_CUSTOMERS . "`;"); From 8e166cb8423cb9a7b9710c384f7fc039eb930d59 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Tue, 12 Oct 2021 14:25:42 +0200 Subject: [PATCH 278/319] adjust debian 11 config templates, fixes #982 Signed-off-by: Michael Kaufmann --- lib/configfiles/bullseye.xml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/configfiles/bullseye.xml b/lib/configfiles/bullseye.xml index 48ad1ecf..73eefcd7 100644 --- a/lib/configfiles/bullseye.xml +++ b/lib/configfiles/bullseye.xml @@ -75,7 +75,7 @@ Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath} ]]> - + @@ -139,7 +139,7 @@ include_shell "/usr/share/lighttpd/include-conf-enabled.pl" - + @@ -355,7 +355,7 @@ exit "$RETVAL" - + @@ -367,7 +367,7 @@ exit "$RETVAL" - + @@ -896,7 +896,7 @@ gmysql-password= ]]> - + @@ -1428,7 +1428,7 @@ bind-check-interval=180 ]]> - + @@ -1551,7 +1551,7 @@ root: root@ - + @@ -4091,7 +4091,7 @@ plugin { - + @@ -4518,7 +4518,7 @@ TLSVerifyClient off ]]> - + @@ -4744,7 +4744,7 @@ UPLOADGID= ]]> - + @@ -4838,7 +4838,7 @@ aliases: files - + @@ -4871,12 +4871,12 @@ aliases: files {{settings.phpfpm.enabled_ownvhost}} - + {{settings.system.webserver}} - + From 724a5e172a8d1bd1a6f7911c042ef69de8f854f3 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Tue, 12 Oct 2021 16:29:04 +0200 Subject: [PATCH 279/319] don't remove 0-value parameter values from bulk-actions Signed-off-by: Michael Kaufmann --- lib/Froxlor/Bulk/BulkAction.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Froxlor/Bulk/BulkAction.php b/lib/Froxlor/Bulk/BulkAction.php index fdfca799..9f946b38 100644 --- a/lib/Froxlor/Bulk/BulkAction.php +++ b/lib/Froxlor/Bulk/BulkAction.php @@ -133,7 +133,7 @@ abstract class BulkAction $new_data = array(); foreach ($this->api_params as $idx => $param) { - if (isset($data_array[$idx]) && ! empty($data_array[$idx])) { + if (isset($data_array[$idx])) { $new_data[$param] = $data_array[$idx]; } } From 9870db2560196e5ebe787a34b0ee545ed9155511 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Thu, 14 Oct 2021 17:09:29 +0200 Subject: [PATCH 280/319] add possibility to assign new/edited php-config to all customer accounts; fixes #980 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/PhpSettings.php | 46 ++++++++++++++++++- .../phpconfig/formfield.phpconfig_add.php | 11 +++++ .../phpconfig/formfield.phpconfig_edit.php | 11 +++++ lng/english.lng.php | 3 ++ lng/german.lng.php | 3 ++ tests/PhpAndFpm/PhpSettingsTest.php | 30 ++++++++++++ 6 files changed, 103 insertions(+), 1 deletion(-) diff --git a/lib/Froxlor/Api/Commands/PhpSettings.php b/lib/Froxlor/Api/Commands/PhpSettings.php index 5f0be1ee..26ef83eb 100644 --- a/lib/Froxlor/Api/Commands/PhpSettings.php +++ b/lib/Froxlor/Api/Commands/PhpSettings.php @@ -217,7 +217,9 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour * 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 - * + * @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) + * * @access admin * @throws \Exception * @return string json-encoded array @@ -261,6 +263,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $max_requests = $this->getParam('max_requests', true, $def_fpmconfig['max_requests']); $idle_timeout = $this->getParam('idle_timeout', true, $def_fpmconfig['idle_timeout']); $limit_extensions = $this->getParam('limit_extensions', true, $def_fpmconfig['limit_extensions']); + $allow_all_customers = $this->getBoolParam('allow_all_customers', true, 0); // validation $description = \Froxlor\Validate\Validate::validate($description, 'description', '', '', array(), true); @@ -367,6 +370,8 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $result = $this->apiCall('PhpSettings.get', array( 'id' => $ins_data['id'] )); + + $this->addForAllCustomers($allow_all_customers, $ins_data['id']); return $this->response(200, "successful", $result); } throw new \Exception("Not allowed to execute given command.", 403); @@ -418,6 +423,8 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour * 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 + * @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) * * @access admin * @throws \Exception @@ -456,6 +463,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $max_requests = $this->getParam('max_requests', true, $result['max_requests']); $idle_timeout = $this->getParam('idle_timeout', true, $result['idle_timeout']); $limit_extensions = $this->getParam('limit_extensions', true, $result['limit_extensions']); + $allow_all_customers = $this->getBoolParam('allow_all_customers', true, 0); // validation $description = \Froxlor\Validate\Validate::validate($description, 'description', '', '', array(), true); @@ -563,6 +571,8 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $result = $this->apiCall('PhpSettings.get', array( 'id' => $id )); + + $this->addForAllCustomers($allow_all_customers, $id); return $this->response(200, "successful", $result); } throw new \Exception("Not allowed to execute given command.", 403); @@ -618,4 +628,38 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour } 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'] + ]); + } + } + } } diff --git a/lib/formfields/admin/phpconfig/formfield.phpconfig_add.php b/lib/formfields/admin/phpconfig/formfield.phpconfig_add.php index 41506df2..d3aa3e84 100644 --- a/lib/formfields/admin/phpconfig/formfield.phpconfig_add.php +++ b/lib/formfields/admin/phpconfig/formfield.phpconfig_add.php @@ -179,6 +179,17 @@ return array( 'cols' => 80, 'rows' => 20, 'value' => $result['phpsettings'] + ), + 'allow_all_customers' => array( + 'label' => $lng['serversettings']['phpfpm_settings']['allow_all_customers'], + 'type' => 'checkbox', + 'values' => array( + array( + 'label' => $lng['panel']['yes'], + 'value' => '1' + ) + ), + 'value' => array() ) ) ) diff --git a/lib/formfields/admin/phpconfig/formfield.phpconfig_edit.php b/lib/formfields/admin/phpconfig/formfield.phpconfig_edit.php index ef6acff5..c4d45c92 100644 --- a/lib/formfields/admin/phpconfig/formfield.phpconfig_edit.php +++ b/lib/formfields/admin/phpconfig/formfield.phpconfig_edit.php @@ -187,6 +187,17 @@ return array( 'cols' => 80, 'rows' => 20, 'value' => $result['phpsettings'] + ), + 'allow_all_customers' => array( + 'label' => $lng['serversettings']['phpfpm_settings']['allow_all_customers'], + 'type' => 'checkbox', + 'values' => array( + array( + 'label' => $lng['panel']['yes'], + 'value' => '1' + ) + ), + 'value' => array() ) ) ) diff --git a/lng/english.lng.php b/lng/english.lng.php index 20389f17..9472e51f 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -2132,3 +2132,6 @@ $lng['error']['local_group_exists'] = 'The given group already exists on the sys $lng['error']['local_group_invalid'] = 'The given group name is invalid'; $lng['error']['invaliddnsforletsencrypt'] = 'The domains DNS does not include any of the chosen IP addresses. Let\'s Encrypt certificate generation not possible.'; $lng['error']['notallowedphpconfigused'] = 'Trying to use php-config which is not assigned to customer'; + +$lng['serversettings']['phpfpm_settings']['allow_all_customers']['title'] = 'Assign this configuration to all currently existing customers'; +$lng['serversettings']['phpfpm_settings']['allow_all_customers']['description'] = 'Set this to "true" if you want to assign this configuration to all currently existing customers so it can be used by them. This setting is not permanent but can be run multiple times.'; diff --git a/lng/german.lng.php b/lng/german.lng.php index b00dd44b..7d85d144 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -1778,3 +1778,6 @@ $lng['error']['local_group_exists'] = 'Die angegebene Gruppe existiert bereits a $lng['error']['local_group_invalid'] = 'Der angegebene Gruppen-Name ist nicht gültig'; $lng['error']['invaliddnsforletsencrypt'] = 'Die DNS-Einträge der Domain enhalten keine der gewählten IP Adressen. Let\'s Encrypt Zertifikats-Erstellung ist nicht möglich.'; $lng['error']['notallowedphpconfigused'] = 'Nutzung einer PHP-Konfiguration welche nicht dem Kunden zugeordnet ist'; + +$lng['serversettings']['phpfpm_settings']['allow_all_customers']['title'] = 'Für aktuelle Kunden automatisch hinzufügen'; +$lng['serversettings']['phpfpm_settings']['allow_all_customers']['description'] = 'Ist diese Einstellung aktiv, wird die Konfiguration automatisch allen aktuell existierenden Kunden-Accounts zugewiesen. Diese Einstellung ist nicht permanent, kann aber mehrfach / nach Bedarf ausgeführt werden.'; diff --git a/tests/PhpAndFpm/PhpSettingsTest.php b/tests/PhpAndFpm/PhpSettingsTest.php index 29b61fe0..7365a90a 100644 --- a/tests/PhpAndFpm/PhpSettingsTest.php +++ b/tests/PhpAndFpm/PhpSettingsTest.php @@ -97,4 +97,34 @@ class PhpSettingsText extends TestCase 'id' => 1 ))->get(); } + + /** + * @depends testAdminPhpSettingsAdd + */ + public function testAdminPhpSettingsAddForAll() + { + global $admin_userdata; + $data = [ + 'description' => 'test php #2', + 'phpsettings' => 'error_reporting=E_ALL', + 'fpmconfig' => Settings::Get('phpfpm.defaultini'), + 'allow_all_customers' => true + ]; + $json_result = PhpSettings::getLocal($admin_userdata, $data)->add(); + $result = json_decode($json_result, true)['data']; + $required_id = $result['id']; + + $json_result = Customers::getLocal($admin_userdata)->listing(); + $result = json_decode($json_result, true)['data']; + + $allowed_cnt = 0; + foreach ($result['list'] as $customer) { + $cust_phpconfigsallowed = json_decode($customer['allowed_phpconfigs'], true); + if (!in_array($required_id, $cust_phpconfigsallowed)) { + $this->fail("Customer does not have php-config assigned which was added for all customers"); + } + $allowed_cnt++; + } + $this->assertTrue($allowed_cnt == $result['count']); + } } From 37ae69f07afa4b596b0514ca3e07d98786e9ab7e Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Thu, 14 Oct 2021 17:13:55 +0200 Subject: [PATCH 281/319] correct language strings in phpconfig formfield for new setting; refs #980 Signed-off-by: Michael Kaufmann --- lib/formfields/admin/phpconfig/formfield.phpconfig_add.php | 3 ++- lib/formfields/admin/phpconfig/formfield.phpconfig_edit.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/formfields/admin/phpconfig/formfield.phpconfig_add.php b/lib/formfields/admin/phpconfig/formfield.phpconfig_add.php index d3aa3e84..20d97b2f 100644 --- a/lib/formfields/admin/phpconfig/formfield.phpconfig_add.php +++ b/lib/formfields/admin/phpconfig/formfield.phpconfig_add.php @@ -181,7 +181,8 @@ return array( 'value' => $result['phpsettings'] ), 'allow_all_customers' => array( - 'label' => $lng['serversettings']['phpfpm_settings']['allow_all_customers'], + 'label' => $lng['serversettings']['phpfpm_settings']['allow_all_customers']['title'], + 'desc' => $lng['serversettings']['phpfpm_settings']['allow_all_customers']['description'], 'type' => 'checkbox', 'values' => array( array( diff --git a/lib/formfields/admin/phpconfig/formfield.phpconfig_edit.php b/lib/formfields/admin/phpconfig/formfield.phpconfig_edit.php index c4d45c92..e8b54f92 100644 --- a/lib/formfields/admin/phpconfig/formfield.phpconfig_edit.php +++ b/lib/formfields/admin/phpconfig/formfield.phpconfig_edit.php @@ -189,7 +189,8 @@ return array( 'value' => $result['phpsettings'] ), 'allow_all_customers' => array( - 'label' => $lng['serversettings']['phpfpm_settings']['allow_all_customers'], + 'label' => $lng['serversettings']['phpfpm_settings']['allow_all_customers']['title'], + 'desc' => $lng['serversettings']['phpfpm_settings']['allow_all_customers']['description'], 'type' => 'checkbox', 'values' => array( array( From 4ad2a1da1c78ebff547b835cd9967a2469703982 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Thu, 14 Oct 2021 19:07:05 +0200 Subject: [PATCH 282/319] add complete list of nameserver-ips and given axfr-servers to allow-axfr-ips list for PowerDNS; fixes #985 Signed-off-by: Michael Kaufmann --- admin_configfiles.php | 35 +++++++++++++++++-- .../Cli/Action/ConfigServicesAction.php | 35 +++++++++++++++++-- lib/configfiles/bionic.xml | 2 -- lib/configfiles/bullseye.xml | 2 -- lib/configfiles/buster.xml | 2 -- lib/configfiles/focal.xml | 2 -- lib/configfiles/gentoo.xml | 2 -- lib/configfiles/stretch.xml | 2 -- lib/configfiles/xenial.xml | 2 -- 9 files changed, 64 insertions(+), 20 deletions(-) diff --git a/admin_configfiles.php b/admin_configfiles.php index 1e14ddcf..594b7d2c 100644 --- a/admin_configfiles.php +++ b/admin_configfiles.php @@ -38,13 +38,43 @@ if ($userinfo['change_serversettings'] == '1') { // try to convert namserver hosts to ip's $ns_ips = ""; + $known_ns_ips = []; if (Settings::Get('system.nameservers') != '') { $nameservers = explode(',', Settings::Get('system.nameservers')); foreach ($nameservers as $nameserver) { $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); - if (is_array($nameserver_ips) && count($nameserver_ips) > 0) { - $ns_ips .= implode(",", $nameserver_ips); + // append dot to hostname + if (substr($nameserver, - 1, 1) != '.') { + $nameserver .= '.'; + } + // ignore invalid responses + if (! is_array($nameserver_ips)) { + // act like \Froxlor\PhpHelper::gethostbynamel6() and return unmodified hostname on error + $nameserver_ips = array( + $nameserver + ); + } else { + $known_ns_ips = array_merge($known_ns_ips, $nameserver_ips); + } + if (!empty($ns_ips)) { + $ns_ips .= ','; + } + $ns_ips .= implode(",", $nameserver_ips); + } + } + + // AXFR server + if (Settings::Get('system.axfrservers') != '') { + $axfrservers = explode(',', Settings::Get('system.axfrservers')); + foreach ($axfrservers as $axfrserver) { + if (!in_array(trim($axfrserver), $known_ns_ips)) { + if (!empty($ns_ips)) { + $ns_ips .= ','; + } + $ns_ips .= trim($axfrserver); } } } @@ -59,7 +89,6 @@ if ($userinfo['change_serversettings'] == '1') { '' => Settings::Get('system.ipaddress'), '' => Settings::Get('system.nameservers'), '' => $ns_ips, - '' => Settings::Get('system.axfrservers'), '' => Settings::Get('system.vmail_homedir'), '' => Settings::Get('system.vmail_uid'), '' => Settings::Get('system.vmail_gid'), diff --git a/lib/Froxlor/Cli/Action/ConfigServicesAction.php b/lib/Froxlor/Cli/Action/ConfigServicesAction.php index a425ac3d..8d6c5d68 100644 --- a/lib/Froxlor/Cli/Action/ConfigServicesAction.php +++ b/lib/Froxlor/Cli/Action/ConfigServicesAction.php @@ -341,13 +341,43 @@ class ConfigServicesAction extends \Froxlor\Cli\Action // try to convert namserver hosts to ip's $ns_ips = ""; + $known_ns_ips = []; if (Settings::Get('system.nameservers') != '') { $nameservers = explode(',', Settings::Get('system.nameservers')); foreach ($nameservers as $nameserver) { $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); - if (is_array($nameserver_ips) && count($nameserver_ips) > 0) { - $ns_ips .= implode(",", $nameserver_ips); + // append dot to hostname + if (substr($nameserver, - 1, 1) != '.') { + $nameserver .= '.'; + } + // ignore invalid responses + if (! is_array($nameserver_ips)) { + // act like \Froxlor\PhpHelper::gethostbynamel6() and return unmodified hostname on error + $nameserver_ips = array( + $nameserver + ); + } else { + $known_ns_ips = array_merge($known_ns_ips, $nameserver_ips); + } + if (!empty($ns_ips)) { + $ns_ips .= ','; + } + $ns_ips .= implode(",", $nameserver_ips); + } + } + + // AXFR server + if (Settings::Get('system.axfrservers') != '') { + $axfrservers = explode(',', Settings::Get('system.axfrservers')); + foreach ($axfrservers as $axfrserver) { + if (!in_array(trim($axfrserver), $known_ns_ips)) { + if (!empty($ns_ips)) { + $ns_ips .= ','; + } + $ns_ips .= trim($axfrserver); } } } @@ -365,7 +395,6 @@ class ConfigServicesAction extends \Froxlor\Cli\Action '' => Settings::Get('system.ipaddress'), '' => Settings::Get('system.nameservers'), '' => $ns_ips, - '' => Settings::Get('system.axfrservers'), '' => Settings::Get('system.vmail_homedir'), '' => Settings::Get('system.vmail_uid'), '' => Settings::Get('system.vmail_gid'), diff --git a/lib/configfiles/bionic.xml b/lib/configfiles/bionic.xml index b9a2c01d..fd7b22fd 100644 --- a/lib/configfiles/bionic.xml +++ b/lib/configfiles/bionic.xml @@ -388,7 +388,6 @@ exit "$RETVAL" # allow-axfr-ips Allow zonetransfers only to these subnets # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -933,7 +932,6 @@ gmysql-password= # allow-axfr-ips Allow zonetransfers only to these subnets # # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. diff --git a/lib/configfiles/bullseye.xml b/lib/configfiles/bullseye.xml index 73eefcd7..ff13ea85 100644 --- a/lib/configfiles/bullseye.xml +++ b/lib/configfiles/bullseye.xml @@ -377,7 +377,6 @@ exit "$RETVAL" # allow-axfr-ips Allow zonetransfers only to these subnets # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -907,7 +906,6 @@ gmysql-password= # allow-axfr-ips Allow zonetransfers only to these subnets # # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. diff --git a/lib/configfiles/buster.xml b/lib/configfiles/buster.xml index cb67bca9..f4fddd06 100644 --- a/lib/configfiles/buster.xml +++ b/lib/configfiles/buster.xml @@ -377,7 +377,6 @@ exit "$RETVAL" # allow-axfr-ips Allow zonetransfers only to these subnets # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -907,7 +906,6 @@ gmysql-password= # allow-axfr-ips Allow zonetransfers only to these subnets # # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. diff --git a/lib/configfiles/focal.xml b/lib/configfiles/focal.xml index 5a733992..f19bf6c4 100644 --- a/lib/configfiles/focal.xml +++ b/lib/configfiles/focal.xml @@ -375,7 +375,6 @@ exit "$RETVAL" # allow-axfr-ips Allow zonetransfers only to these subnets # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -920,7 +919,6 @@ gmysql-password= # allow-axfr-ips Allow zonetransfers only to these subnets # # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. diff --git a/lib/configfiles/gentoo.xml b/lib/configfiles/gentoo.xml index efeaf30b..8e9230f7 100644 --- a/lib/configfiles/gentoo.xml +++ b/lib/configfiles/gentoo.xml @@ -398,7 +398,6 @@ mail IN A # allow-axfr-ips Allow zonetransfers only to these subnets # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -929,7 +928,6 @@ gmysql-password= # allow-axfr-ips Allow zonetransfers only to these subnets # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. diff --git a/lib/configfiles/stretch.xml b/lib/configfiles/stretch.xml index ce379257..3bb9eb23 100644 --- a/lib/configfiles/stretch.xml +++ b/lib/configfiles/stretch.xml @@ -377,7 +377,6 @@ exit "$RETVAL" # allow-axfr-ips Allow zonetransfers only to these subnets # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -922,7 +921,6 @@ gmysql-password= # allow-axfr-ips Allow zonetransfers only to these subnets # # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. diff --git a/lib/configfiles/xenial.xml b/lib/configfiles/xenial.xml index a353294e..2285b441 100644 --- a/lib/configfiles/xenial.xml +++ b/lib/configfiles/xenial.xml @@ -388,7 +388,6 @@ exit "$RETVAL" # allow-axfr-ips Allow zonetransfers only to these subnets # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. @@ -933,7 +932,6 @@ gmysql-password= # allow-axfr-ips Allow zonetransfers only to these subnets # # allow-axfr-ips=127.0.0.0/8,::1, -# add these entries to the list if any specified: ################################# # allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. From a552ea878e415864b9450bd17b7c1f22b277ad6f Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 17 Oct 2021 11:48:40 +0200 Subject: [PATCH 283/319] avoid undefined index of 'wwwserveralias' field if issueing/renewing lets encrypt certificate for froxlor-hostname Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index 686d4420..9b3938d6 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -131,7 +131,8 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron 'ssl_key_file' => null, 'ssl_ca_file' => null, 'ssl_csr_file' => null, - 'id' => null + 'id' => null, + 'wwwserveralias' => 0 ); // add to queue @@ -165,7 +166,8 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron 'ssl_key_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_key_file'] : null, 'ssl_ca_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_ca_file'] : null, 'ssl_csr_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_csr_file'] : null, - 'id' => is_array($renew_froxlor) ? $renew_froxlor['id'] : null + 'id' => is_array($renew_froxlor) ? $renew_froxlor['id'] : null, + 'wwwserveralias' => 0 ); $renew_domains[] = $certrow; } From b961eba3828b33a03ab770943527f30ed05982f8 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Wed, 20 Oct 2021 16:51:16 +0200 Subject: [PATCH 284/319] fix api documentation for Domains.add() and Domains.update(); fixes #987 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Domains.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php index 9d8df59a..dca7dd98 100644 --- a/lib/Froxlor/Api/Commands/Domains.php +++ b/lib/Froxlor/Api/Commands/Domains.php @@ -239,7 +239,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn * 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) - * @param bool $issubof + * @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) * @param string $registration_date * optional, date of domain registration in form of YYYY-MM-DD, default empty (none) @@ -901,7 +901,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn * 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) - * @param bool $issubof + * @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) * @param string $registration_date * optional, date of domain registration in form of YYYY-MM-DD, default empty (none) From bd8327afbeed9a65a0d959a6b2f62bbc987aeec0 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Thu, 21 Oct 2021 11:56:34 +0200 Subject: [PATCH 285/319] soften/correct permissions on pdns configs; fixes #991 Signed-off-by: Michael Kaufmann --- lib/configfiles/bionic.xml | 8 ++++---- lib/configfiles/bullseye.xml | 8 ++++---- lib/configfiles/buster.xml | 8 ++++---- lib/configfiles/focal.xml | 8 ++++---- lib/configfiles/gentoo.xml | 8 ++++---- lib/configfiles/stretch.xml | 8 ++++---- lib/configfiles/xenial.xml | 8 ++++---- 7 files changed, 28 insertions(+), 28 deletions(-) diff --git a/lib/configfiles/bionic.xml b/lib/configfiles/bionic.xml index fd7b22fd..8c4de7c2 100644 --- a/lib/configfiles/bionic.xml +++ b/lib/configfiles/bionic.xml @@ -382,7 +382,7 @@ exit "$RETVAL" - + + chown="root:pdns" chmod="640"> - + + chown="root:pdns" chmod="640"> - + + chown="root:pdns" chmod="640"> - + + chown="root:pdns" chmod="640"> - + + chown="root:pdns" chmod="640"> - + + chown="root:pdns" chmod="640"> - + + chown="root:pdns" chmod="640"> - + + chown="root:pdns" chmod="640"> - + + chown="root:pdns" chmod="640"> - + + chown="root:pdns" chmod="640"> named.conf diff --git a/lib/configfiles/stretch.xml b/lib/configfiles/stretch.xml index 3bb9eb23..a04213d4 100644 --- a/lib/configfiles/stretch.xml +++ b/lib/configfiles/stretch.xml @@ -371,7 +371,7 @@ exit "$RETVAL" - + + chown="root:pdns" chmod="640"> - + + chown="root:pdns" chmod="640"> - + + chown="root:pdns" chmod="640"> - + + chown="root:pdns" chmod="640"> Date: Thu, 21 Oct 2021 12:00:36 +0200 Subject: [PATCH 286/319] check whether the domain to clean from pdns actually still exists there; fixes #992 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/Dns/PowerDNS.php | 38 ++++++++++++++++--------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/lib/Froxlor/Cron/Dns/PowerDNS.php b/lib/Froxlor/Cron/Dns/PowerDNS.php index 39556b2e..e992e721 100644 --- a/lib/Froxlor/Cron/Dns/PowerDNS.php +++ b/lib/Froxlor/Cron/Dns/PowerDNS.php @@ -15,7 +15,7 @@ use Froxlor\Settings; * @author Froxlor team (2016-) * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt * @package Cron - * + * */ class PowerDNS extends DnsBase { @@ -99,30 +99,32 @@ class PowerDNS extends DnsBase )); $pdns_domain = $pdns_domains_stmt->fetch(\PDO::FETCH_ASSOC); - $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'] - )); + 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'] + )); + } } } private function insertZone($domainname, $serial = 0) { - $ins_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare(" + $ins_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare(" INSERT INTO domains set `name` = :domainname, `notified_serial` = :serial, `type` = :type "); - $ins_stmt->execute(array( - 'domainname' => $domainname, - 'serial' => $serial, - 'type' => strtoupper(Settings::Get('system.powerdns_mode')) - )); - $lastid = \Froxlor\Dns\PowerDNS::getDB()->lastInsertId(); - return $lastid;; + $ins_stmt->execute(array( + '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 = "") From e5838f00cfaa057f3ce622c4d46b928aca5b1908 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Wed, 3 Nov 2021 14:08:57 +0100 Subject: [PATCH 287/319] add quota-plugin parameters to dovecot-config-templates; update standardcustomer index.html; set nameserver disabled by default Signed-off-by: Michael Kaufmann --- install/froxlor.sql | 2 +- lib/configfiles/bionic.xml | 9 +++++++++ lib/configfiles/bullseye.xml | 9 +++++++++ lib/configfiles/buster.xml | 9 +++++++++ lib/configfiles/centos7.xml | 9 +++++++++ lib/configfiles/centos8.xml | 9 +++++++++ lib/configfiles/focal.xml | 9 +++++++++ lib/configfiles/gentoo.xml | 9 +++++++++ lib/configfiles/stretch.xml | 9 +++++++++ lib/configfiles/xenial.xml | 9 +++++++++ templates/misc/standardcustomer/index.html | 2 +- 11 files changed, 83 insertions(+), 2 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index a05ba81f..0989e7b0 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -532,7 +532,7 @@ opcache.interned_strings_buffer'), ('system', 'vmail_gid', '2000'), ('system', 'vmail_homedir', '/var/customers/mail/'), ('system', 'vmail_maildirname', 'Maildir'), - ('system', 'bind_enable', '1'), + ('system', 'bind_enable', '0'), ('system', 'bindconf_directory', '/etc/bind/'), ('system', 'bindreload_command', '/etc/init.d/bind9 reload'), ('system', 'hostname', 'SERVERNAME'), diff --git a/lib/configfiles/bionic.xml b/lib/configfiles/bionic.xml index 8c4de7c2..4b7ae0b5 100644 --- a/lib/configfiles/bionic.xml +++ b/lib/configfiles/bionic.xml @@ -3877,6 +3877,15 @@ plugin { # (Currently only relevant for ManageSieve) #sieve_quota_max_storage = 0 } +]]> + + + + diff --git a/lib/configfiles/bullseye.xml b/lib/configfiles/bullseye.xml index 14b042c5..0ed6c24d 100644 --- a/lib/configfiles/bullseye.xml +++ b/lib/configfiles/bullseye.xml @@ -4084,6 +4084,15 @@ plugin { # the source line numbers. #sieve_trace_addresses = no } +]]> + + + + diff --git a/lib/configfiles/buster.xml b/lib/configfiles/buster.xml index 16a1350c..057fd7aa 100644 --- a/lib/configfiles/buster.xml +++ b/lib/configfiles/buster.xml @@ -4079,6 +4079,15 @@ plugin { # the source line numbers. #sieve_trace_addresses = no } +]]> + + + + diff --git a/lib/configfiles/centos7.xml b/lib/configfiles/centos7.xml index df2c6fd9..5e6c3294 100644 --- a/lib/configfiles/centos7.xml +++ b/lib/configfiles/centos7.xml @@ -1712,6 +1712,15 @@ plugin { # (Currently only relevant for ManageSieve) #sieve_quota_max_storage = 0 } +]]> + + + + diff --git a/lib/configfiles/centos8.xml b/lib/configfiles/centos8.xml index 7fde8162..2e5999c9 100644 --- a/lib/configfiles/centos8.xml +++ b/lib/configfiles/centos8.xml @@ -1713,6 +1713,15 @@ plugin { # (Currently only relevant for ManageSieve) #sieve_quota_max_storage = 0 } +]]> + + + + diff --git a/lib/configfiles/focal.xml b/lib/configfiles/focal.xml index fd8a3b6d..dbdbebfc 100644 --- a/lib/configfiles/focal.xml +++ b/lib/configfiles/focal.xml @@ -3293,6 +3293,15 @@ plugin { # (Currently only relevant for ManageSieve) #sieve_quota_max_storage = 0 } +]]> + + + + diff --git a/lib/configfiles/gentoo.xml b/lib/configfiles/gentoo.xml index ebe3f971..eb28ef51 100644 --- a/lib/configfiles/gentoo.xml +++ b/lib/configfiles/gentoo.xml @@ -2345,6 +2345,15 @@ plugin { ]]> + + + + diff --git a/lib/configfiles/stretch.xml b/lib/configfiles/stretch.xml index a04213d4..7f2f0294 100644 --- a/lib/configfiles/stretch.xml +++ b/lib/configfiles/stretch.xml @@ -3866,6 +3866,15 @@ plugin { # (Currently only relevant for ManageSieve) #sieve_quota_max_storage = 0 } +]]> + + + + diff --git a/lib/configfiles/xenial.xml b/lib/configfiles/xenial.xml index 48f3941d..bbae02e3 100644 --- a/lib/configfiles/xenial.xml +++ b/lib/configfiles/xenial.xml @@ -3877,6 +3877,15 @@ plugin { # (Currently only relevant for ManageSieve) #sieve_quota_max_storage = 0 } +]]> + + + + diff --git a/templates/misc/standardcustomer/index.html b/templates/misc/standardcustomer/index.html index 4521d6b3..e1ae6495 100644 --- a/templates/misc/standardcustomer/index.html +++ b/templates/misc/standardcustomer/index.html @@ -67,7 +67,7 @@ a:hover { - © 2009-2018 by the Froxlor + © 2009-2021 by the Froxlor Team From c4a2db03be84a91191d44274a15500efa6c72b14 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Wed, 3 Nov 2021 14:16:21 +0100 Subject: [PATCH 288/319] enable bind for testing-scenarios explicitly Signed-off-by: Michael Kaufmann --- tests/bootstrap.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 0b13022f..0d835c37 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -173,6 +173,7 @@ Settings::Set('system.mysql_access_host', 'localhost,127.0.0.1,172.17.0.1,2a01:4 Settings::Set('system.use_ssl', '1', true); Settings::Set('system.froxlordirectlyviahostname', '1', true); Settings::Set('system.dns_createhostnameentry', '1', true); +Settings::Set('system.bind_enable', '1', true); Settings::Set('system.dnsenabled', '1', true); Settings::Set('system.dns_server', 'PowerDNS', true); Settings::Set('phpfpm.enabled', '1', true); From eb841da0072e36adacc8654c4e3521b68e089f6f Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Thu, 4 Nov 2021 07:44:03 +0100 Subject: [PATCH 289/319] avoid possible DivisionByZeroError in APCu info page, fixes #995 Signed-off-by: Michael Kaufmann --- admin_apcuinfo.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/admin_apcuinfo.php b/admin_apcuinfo.php index d7854d65..b616b0a5 100644 --- a/admin_apcuinfo.php +++ b/admin_apcuinfo.php @@ -67,6 +67,9 @@ if ($page == 'showinfo') { $uptime_duration = duration($cache['start_time']); $size_vars = bsize($cache['mem_size']); + $num_hits_and_misses = $cache['num_hits'] + $cache['num_misses']; + $num_hits_and_misses = 0 >= $num_hits_and_misses ? 1 : $num_hits_and_misses; + // check for possible empty values that are used in the templates if (! isset($cache['file_upload_progress'])) { $cache['file_upload_progress'] = $lng['logger']['unknown']; @@ -84,8 +87,8 @@ if ($page == 'showinfo') { $freemem = bsize($mem_avail) . sprintf(" (%.1f%%)", $mem_avail * 100 / $mem_size); $usedmem = bsize($mem_used) . sprintf(" (%.1f%%)", $mem_used * 100 / $mem_size); - $hits = $cache['num_hits'] . @sprintf(" (%.1f%%)", $cache['num_hits'] * 100 / ($cache['num_hits'] + $cache['num_misses'])); - $misses = $cache['num_misses'] . @sprintf(" (%.1f%%)", $cache['num_misses'] * 100 / ($cache['num_hits'] + $cache['num_misses'])); + $hits = $cache['num_hits'] . @sprintf(" (%.1f%%)", $cache['num_hits'] * 100 / $num_hits_and_misses); + $misses = $cache['num_misses'] . @sprintf(" (%.1f%%)", $cache['num_misses'] * 100 / $num_hits_and_misses); // Fragmentation: (freeseg - 1) / total_seg $nseg = $freeseg = $fragsize = $freetotal = 0; From 46df429909dec540dfb84e2dc2b9ea21702318d7 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 5 Nov 2021 09:27:58 +0100 Subject: [PATCH 290/319] set version to 0.10.30 for upcoming release Signed-off-by: Michael Kaufmann --- install/froxlor.sql | 2 +- install/updates/froxlor/0.10/update_0.10.inc.php | 5 +++++ lib/Froxlor/Froxlor.php | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index 0989e7b0..9efd3337 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -722,7 +722,7 @@ opcache.interned_strings_buffer'), ('panel', 'logo_image_login', ''), ('panel', 'logo_overridetheme', '0'), ('panel', 'logo_overridecustom', '0'), - ('panel', 'version', '0.10.29.1'), + ('panel', 'version', '0.10.30'), ('panel', 'db_version', '202109040'); diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index e7541083..c2fe1167 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -943,3 +943,8 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.29')) { showUpdateStep("Updating from 0.10.29 to 0.10.29.1", false); \Froxlor\Froxlor::updateToVersion('0.10.29.1'); } + +if (\Froxlor\Froxlor::isFroxlorVersion('0.10.29.1')) { + showUpdateStep("Updating from 0.10.29.1 to 0.10.30", false); + \Froxlor\Froxlor::updateToVersion('0.10.30'); +} diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index f0af2086..8478d16c 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -7,7 +7,7 @@ final class Froxlor { // Main version variable - const VERSION = '0.10.29.1'; + const VERSION = '0.10.30'; // Database version (YYYYMMDDC where C is a daily counter) const DBVERSION = '202109040'; From 00771381e807a0f728d4faeb8c768b2c74084efe Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sat, 13 Nov 2021 20:20:05 +0100 Subject: [PATCH 291/319] set correct php-version numbers for installation dependencies-check; fixes #997 Signed-off-by: Michael Kaufmann --- install/lng/english.lng.php | 4 ++-- install/lng/french.lng.php | 2 +- install/lng/german.lng.php | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/install/lng/english.lng.php b/install/lng/english.lng.php index 8701a494..081de41b 100644 --- a/install/lng/english.lng.php +++ b/install/lng/english.lng.php @@ -22,8 +22,8 @@ $lng['requirements']['not_true'] = 'no'; $lng['requirements']['notfound'] = 'not found'; $lng['requirements']['notinstalled'] = 'not installed'; $lng['requirements']['activated'] = 'enabled'; -$lng['requirements']['phpversion'] = 'PHP version >= 7.0'; -$lng['requirements']['newerphpprefered'] = 'Good, but php-7.1 is preferred.'; +$lng['requirements']['phpversion'] = 'PHP version >= 7.1'; +$lng['requirements']['newerphpprefered'] = 'Good, but php-7.4 is preferred.'; $lng['requirements']['phppdo'] = 'PHP PDO extension and PDO-MySQL driver...'; $lng['requirements']['phpsession'] = 'PHP session-extension...'; $lng['requirements']['phpctype'] = 'PHP ctype-extension...'; diff --git a/install/lng/french.lng.php b/install/lng/french.lng.php index a3aacc6a..36a013a4 100644 --- a/install/lng/french.lng.php +++ b/install/lng/french.lng.php @@ -22,7 +22,7 @@ $lng['requirements']['not_true'] = 'non'; $lng['requirements']['notfound'] = 'introuvable'; $lng['requirements']['notinstalled'] = 'non installé'; $lng['requirements']['activated'] = 'activé'; -$lng['requirements']['phpversion'] = 'PHP version >= 7.0'; +$lng['requirements']['phpversion'] = 'PHP version >= 7.1'; $lng['requirements']['phppdo'] = 'extension PHP PDO et pilote PDO-MySQL ...'; $lng['requirements']['phpxml'] = 'extension PHP XML...'; $lng['requirements']['phpfilter'] = 'extension PHP filter ...'; diff --git a/install/lng/german.lng.php b/install/lng/german.lng.php index 8cde4390..86c97d3c 100644 --- a/install/lng/german.lng.php +++ b/install/lng/german.lng.php @@ -22,8 +22,8 @@ $lng['requirements']['not_true'] = 'nein'; $lng['requirements']['notfound'] = 'nicht gefunden'; $lng['requirements']['notinstalled'] = 'nicht installiert'; $lng['requirements']['activated'] = 'ist aktiviert.'; -$lng['requirements']['phpversion'] = 'PHP Version >= 7.0'; -$lng['requirements']['newerphpprefered'] = 'Passt, aber php-7.1 wird bevorzugt.'; +$lng['requirements']['phpversion'] = 'PHP Version >= 7.1'; +$lng['requirements']['newerphpprefered'] = 'Passt, aber php-7.4 wird bevorzugt.'; $lng['requirements']['phppdo'] = 'PHP PDO Erweiterung und PDO-MySQL Treiber...'; $lng['requirements']['phpsession'] = 'PHP session-Erweiterung...'; $lng['requirements']['phpctype'] = 'PHP ctype-Erweiterung...'; From 389d83f5a3ea4cc24dbba4e5b650d582a0d761a4 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Mon, 15 Nov 2021 20:04:01 +0100 Subject: [PATCH 292/319] fix behaviour in Customers.update() in case 'createstdsubdomain' is not set when called via API (wrong default); fixes #998 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Customers.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Froxlor/Api/Commands/Customers.php b/lib/Froxlor/Api/Commands/Customers.php index 05749ca1..90bc4dfd 100644 --- a/lib/Froxlor/Api/Commands/Customers.php +++ b/lib/Froxlor/Api/Commands/Customers.php @@ -915,7 +915,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource * @param bool $mysqls_ul * 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 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) * @param array $allowed_phpconfigs @@ -979,7 +979,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $email_pop3 = $this->getParam('email_pop3', true, $result['pop3']); $ftps = $this->getUlParam('ftps', 'ftps_ul', true, $result['ftps']); $mysqls = $this->getUlParam('mysqls', 'mysqls_ul', true, $result['mysqls']); - $createstdsubdomain = $this->getBoolParam('createstdsubdomain', true, 0); + $createstdsubdomain = $this->getBoolParam('createstdsubdomain', true, ($result['standardsubdomain'] != 0 ? 1 : 0)); $password = $this->getParam('new_customer_password', true, ''); $phpenabled = $this->getBoolParam('phpenabled', true, $result['phpenabled']); $allowed_phpconfigs = $this->getParam('allowed_phpconfigs', true, json_decode($result['allowed_phpconfigs'], true)); From b54c0125795799e33591c973687858f26576171d Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Mon, 15 Nov 2021 20:24:55 +0100 Subject: [PATCH 293/319] respect deactivated flag when createstdsubdomain's default falls back to 'true' if the customer has one (prior to deactivating); refs #998 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Customers.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Froxlor/Api/Commands/Customers.php b/lib/Froxlor/Api/Commands/Customers.php index 90bc4dfd..e89031c3 100644 --- a/lib/Froxlor/Api/Commands/Customers.php +++ b/lib/Froxlor/Api/Commands/Customers.php @@ -1051,7 +1051,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource } if ($this->isAdmin()) { - if ($createstdsubdomain != '1') { + if ($createstdsubdomain != '1' || $deactivated) { $createstdsubdomain = '0'; } From cb0b537f6c4bceda895b921190415ce25bb9d86c Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sat, 27 Nov 2021 18:04:36 +0100 Subject: [PATCH 294/319] allow settings/updating documentroot (only relative to customer homedirectory) when change_serversettings permission is not granted; fixes #1000 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Domains.php | 85 +++++++++++++++------------- lng/english.lng.php | 3 +- lng/german.lng.php | 3 +- tests/Domains/DomainsTest.php | 40 +++++++++++++ 4 files changed, 90 insertions(+), 41 deletions(-) diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php index dca7dd98..ff3ac065 100644 --- a/lib/Froxlor/Api/Commands/Domains.php +++ b/lib/Froxlor/Api/Commands/Domains.php @@ -427,6 +427,20 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn } $_documentroot = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . $path_suffix); + $documentroot = \Froxlor\Validate\Validate::validate($documentroot, 'documentroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), 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)) { + $documentroot = $_documentroot . '/' . $documentroot; + } elseif (substr($documentroot, 0, 1) == '/' && $this->getUserDetail('change_serversettings') != '1') { + \Froxlor\UI\Response::standard_error('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( '0000-00-00', '0', @@ -454,17 +468,6 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn } $specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $specialsettings), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true); - \Froxlor\Validate\Validate::validate($documentroot, 'documentroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), 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)) { - $documentroot = $_documentroot . '/' . $documentroot; - } - } else { - $documentroot = $_documentroot; - } $ssl_protocols = array(); if (! empty($p_ssl_protocols) && is_numeric($p_ssl_protocols)) { @@ -507,7 +510,6 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $notryfiles = '0'; $writeaccesslog = '1'; $writeerrorlog = '1'; - $documentroot = $_documentroot; $override_tls = '0'; $ssl_protocols = array(); } @@ -1187,6 +1189,38 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $serveraliasoption = $p_serveraliasoption; } + $documentroot = \Froxlor\Validate\Validate::validate($documentroot, 'documentroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), 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); + } + + // 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 (Settings::Get('system.documentroot_use_default_value') == 1) { + $_documentroot = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $result['domain']); + } else { + $_documentroot = $customer['documentroot']; + } + // set the customers default docroot + $documentroot = $_documentroot; + } + + if ($documentroot == '') { + // 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']); + } else { + $documentroot = $customer['documentroot']; + } + } + + if (! preg_match('/^https?\:\/\//', $documentroot) && strstr($documentroot, ":") !== false) { + \Froxlor\UI\Response::standard_error('pathmaynotcontaincolon', '', true); + } + if ($this->getUserDetail('change_serversettings') == '1') { if (Settings::Get('system.bind_enable') == '1') { @@ -1201,33 +1235,6 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn } $specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $specialsettings), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true); - $documentroot = \Froxlor\Validate\Validate::validate($documentroot, 'documentroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), 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 (Settings::Get('system.documentroot_use_default_value') == 1) { - $_documentroot = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $result['domain']); - } else { - $_documentroot = $customer['documentroot']; - } - // set the customers default docroot - $documentroot = $_documentroot; - } - - if ($documentroot == '') { - // 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']); - } else { - $documentroot = $customer['documentroot']; - } - } - - if (! preg_match('/^https?\:\/\//', $documentroot) && strstr($documentroot, ":") !== false) { - \Froxlor\UI\Response::standard_error('pathmaynotcontaincolon', '', true); - } $ssl_protocols = array(); if (! empty($p_ssl_protocols) && is_numeric($p_ssl_protocols)) { diff --git a/lng/english.lng.php b/lng/english.lng.php index 9472e51f..64d33b3c 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -1722,7 +1722,7 @@ $lng['serversettings']['panel_password_special_char_required']['description'] = $lng['serversettings']['panel_password_special_char']['title'] = 'Special characters list'; $lng['serversettings']['panel_password_special_char']['description'] = 'One of these characters is required if the above option is set.'; $lng['phpfpm']['use_mod_proxy']['title'] = 'Use mod_proxy / mod_proxy_fcgi'; -$lng['phpfpm']['use_mod_proxy']['description'] = 'Must be enabled when using Debian 9.x (Stretch). Activate to use php-fpm via mod_proxy_fcgi. Requires at least apache-2.4.9'; +$lng['phpfpm']['use_mod_proxy']['description'] = 'Must be enabled when using Debian 9.x (Stretch) or newer. Activate to use php-fpm via mod_proxy_fcgi. Requires at least apache-2.4.9'; $lng['error']['no_phpinfo'] = 'Sorry, unable to read phpinfo()'; $lng['admin']['movetoadmin'] = 'Move customer'; @@ -2135,3 +2135,4 @@ $lng['error']['notallowedphpconfigused'] = 'Trying to use php-config which is no $lng['serversettings']['phpfpm_settings']['allow_all_customers']['title'] = 'Assign this configuration to all currently existing customers'; $lng['serversettings']['phpfpm_settings']['allow_all_customers']['description'] = 'Set this to "true" if you want to assign this configuration to all currently existing customers so it can be used by them. This setting is not permanent but can be run multiple times.'; +$lng['error']['pathmustberelative'] = 'The user does not have the permission to specify directories outside the customers home-directory. Please specify a relative path (no leading /).'; diff --git a/lng/german.lng.php b/lng/german.lng.php index 7d85d144..c5b7bcc6 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -1445,7 +1445,7 @@ $lng['serversettings']['panel_password_special_char_required']['description'] = $lng['serversettings']['panel_password_special_char']['title'] = 'Sonderzeichen-Liste'; $lng['serversettings']['panel_password_special_char']['description'] = 'Mindestens eines dieser Sonderzeichen muss in dem Passwort vorkommen, sofern die Sonderzeichen-Option aktiviert ist.'; $lng['phpfpm']['use_mod_proxy']['title'] = 'Verwende mod_proxy / mod_proxy_fcgi'; -$lng['phpfpm']['use_mod_proxy']['description'] = 'Muss gesetzt sein bei Debian 9.x (Stretch). Diese Option kann aktiviert werden, um php-fpm via mod_proxy_fcgi einzubinden. Dies setzt mindestens apache-2.4.9 voraus'; +$lng['phpfpm']['use_mod_proxy']['description'] = 'Muss gesetzt sein bei Debian 9.x (Stretch) oder neuer. Diese Option kann aktiviert werden, um php-fpm via mod_proxy_fcgi einzubinden. Dies setzt mindestens apache-2.4.9 voraus'; $lng['error']['no_phpinfo'] = 'Entschuldigung, es ist nicht möglich die phpinfo() auszulesen.'; $lng['admin']['movetoadmin'] = 'Kunde verschieben'; @@ -1781,3 +1781,4 @@ $lng['error']['notallowedphpconfigused'] = 'Nutzung einer PHP-Konfiguration welc $lng['serversettings']['phpfpm_settings']['allow_all_customers']['title'] = 'Für aktuelle Kunden automatisch hinzufügen'; $lng['serversettings']['phpfpm_settings']['allow_all_customers']['description'] = 'Ist diese Einstellung aktiv, wird die Konfiguration automatisch allen aktuell existierenden Kunden-Accounts zugewiesen. Diese Einstellung ist nicht permanent, kann aber mehrfach / nach Bedarf ausgeführt werden.'; +$lng['error']['pathmustberelative'] = 'Der Benutzer hat nicht die benötigten Berechtigungen, um Pfade außerhalb des Kunden-Heimatverzeichnisses anzugeben. Bitte einen relativen Pfad angeben (kein führendes /).'; diff --git a/tests/Domains/DomainsTest.php b/tests/Domains/DomainsTest.php index 274bc0d3..a7081d34 100644 --- a/tests/Domains/DomainsTest.php +++ b/tests/Domains/DomainsTest.php @@ -138,6 +138,25 @@ class DomainsTest extends TestCase $this->assertEquals(2, $result['subcanemaildomain']); } + public function testResellerDomainsAddWithAbsolutePathNoChangeServerSettings() + { + global $admin_userdata; + // get reseller + $json_result = Admins::getLocal($admin_userdata, array( + 'loginname' => 'reseller' + ))->get(); + $reseller_userdata = json_decode($json_result, true)['data']; + $reseller_userdata['adminsession'] = 1; + $data = [ + 'domain' => 'test3.local', + 'customerid' => 1, + 'documentroot' => '/some/absolute/directory/the_reseller/cannot/set/', + 'ipandport' => 4 + ]; + $this->expectExceptionMessage("The user does not have the permission to specify directories outside the customers home-directory. Please specify a relative path (no leading /)."); + $json_result = Domains::getLocal($reseller_userdata, $data)->add(); + } + /** * * @depends testAdminDomainsAdd @@ -161,6 +180,27 @@ class DomainsTest extends TestCase $this->assertEquals('test2.local', $result['domain']); } + /** + * + * @depends testResellerDomainsUpdate + */ + public function testResellerDomainsUpdateAboslutePathNotAllowed() + { + global $admin_userdata; + // get reseller + $json_result = Admins::getLocal($admin_userdata, array( + 'loginname' => 'reseller' + ))->get(); + $reseller_userdata = json_decode($json_result, true)['data']; + $reseller_userdata['adminsession'] = 1; + $data = [ + 'domainname' => 'test2.local', + 'documentroot' => '/some/other/dir' + ]; + $this->expectExceptionMessage("The user does not have the permission to specify directories outside the customers home-directory. Please specify a relative path (no leading /)."); + $json_result = Domains::getLocal($reseller_userdata, $data)->update(); + } + public function testAdminDomainsAddSysHostname() { global $admin_userdata; From 149c0935fa0b32c1c484f328a1a7700a6f7c59fe Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sat, 27 Nov 2021 22:06:29 +0100 Subject: [PATCH 295/319] fix Domains.update() with correct path and change_serversettings=0; refs #1001 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Domains.php | 1 - tests/Domains/DomainsTest.php | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php index ff3ac065..340ac88e 100644 --- a/lib/Froxlor/Api/Commands/Domains.php +++ b/lib/Froxlor/Api/Commands/Domains.php @@ -1274,7 +1274,6 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $notryfiles = $result['notryfiles']; $writeaccesslog = $result['writeaccesslog']; $writeerrorlog = $result['writeerrorlog']; - $documentroot = $result['documentroot']; $ssl_protocols = $p_ssl_protocols; $override_tls = $result['override_tls']; } diff --git a/tests/Domains/DomainsTest.php b/tests/Domains/DomainsTest.php index a7081d34..716f18e6 100644 --- a/tests/Domains/DomainsTest.php +++ b/tests/Domains/DomainsTest.php @@ -172,12 +172,14 @@ class DomainsTest extends TestCase $reseller_userdata['adminsession'] = 1; $data = [ 'domainname' => 'test2.local', - 'ssl_protocols' => 'TLSv1' + 'ssl_protocols' => 'TLSv1', + 'documentroot' => '/var/customers/webs/test1/sub/' ]; $json_result = Domains::getLocal($reseller_userdata, $data)->update(); $result = json_decode($json_result, true)['data']; $this->assertEmpty($result['ssl_protocols']); $this->assertEquals('test2.local', $result['domain']); + $this->assertEquals('/var/customers/webs/test1/sub/', $result['documentroot']); } /** @@ -442,6 +444,7 @@ class DomainsTest extends TestCase } /** + * * @refs https://github.com/Froxlor/Froxlor/issues/899 */ public function testAdminIdn2DomainsAdd() From f4d9e648048d8c18fb0919859035e1281fb9e712 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 3 Dec 2021 15:30:09 +0100 Subject: [PATCH 296/319] set version to 0.10.31 for upcoming release Signed-off-by: Michael Kaufmann --- install/froxlor.sql | 2 +- install/updates/froxlor/0.10/update_0.10.inc.php | 5 +++++ lib/Froxlor/Froxlor.php | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index 9efd3337..248d1fd9 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -722,7 +722,7 @@ opcache.interned_strings_buffer'), ('panel', 'logo_image_login', ''), ('panel', 'logo_overridetheme', '0'), ('panel', 'logo_overridecustom', '0'), - ('panel', 'version', '0.10.30'), + ('panel', 'version', '0.10.31'), ('panel', 'db_version', '202109040'); diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index c2fe1167..698dc568 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -948,3 +948,8 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.29.1')) { showUpdateStep("Updating from 0.10.29.1 to 0.10.30", false); \Froxlor\Froxlor::updateToVersion('0.10.30'); } + +if (\Froxlor\Froxlor::isFroxlorVersion('0.10.30')) { + showUpdateStep("Updating from 0.10.30 to 0.10.31", false); + \Froxlor\Froxlor::updateToVersion('0.10.31'); +} diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index 8478d16c..538f1758 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -7,7 +7,7 @@ final class Froxlor { // Main version variable - const VERSION = '0.10.30'; + const VERSION = '0.10.31'; // Database version (YYYYMMDDC where C is a daily counter) const DBVERSION = '202109040'; From 5ccae3f9bb8545ca6c08168779f8639e76598bce Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Tue, 14 Dec 2021 11:23:36 +0100 Subject: [PATCH 297/319] do not check for allowed-phpconfigs if fpm/fcgid is not activated (no possibility to select a config anyway) Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/SubDomains.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/Froxlor/Api/Commands/SubDomains.php b/lib/Froxlor/Api/Commands/SubDomains.php index 3bc1efb5..c3a0a322 100644 --- a/lib/Froxlor/Api/Commands/SubDomains.php +++ b/lib/Froxlor/Api/Commands/SubDomains.php @@ -268,8 +268,11 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc } else { $allowed_phpconfigs = []; } - if (! in_array($phpsid_result['phpsettingid'], $allowed_phpconfigs)) { - \Froxlor\UI\Response::standard_error('notallowedphpconfigused', '', true); + // 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); + } } // actually insert domain @@ -654,8 +657,11 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc } else { $allowed_phpconfigs = []; } - if (! in_array($phpsettingid, $allowed_phpconfigs)) { - \Froxlor\UI\Response::standard_error('notallowedphpconfigused', '', true); + // 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); + } } // handle redirect From 8f0f89014537a4a915f8a4e830287392d4aefe51 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Mon, 27 Dec 2021 15:38:59 +0100 Subject: [PATCH 298/319] fix too strict comparison for isemaildomain check in Dns-Zone generation; fixes #1003 Signed-off-by: Michael Kaufmann --- lib/Froxlor/Dns/Dns.php | 2 +- tests/DomainZones/DomainZonesTest.php | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Froxlor/Dns/Dns.php b/lib/Froxlor/Dns/Dns.php index 1ff28999..c870e3cc 100644 --- a/lib/Froxlor/Dns/Dns.php +++ b/lib/Froxlor/Dns/Dns.php @@ -75,7 +75,7 @@ class Dns if (! $isMainButSubTo) { self::addRequiredEntry('@', 'NS', $required_entries); } - if ($domain['isemaildomain'] === '1') { + if ($domain['isemaildomain'] == '1') { self::addRequiredEntry('@', 'MX', $required_entries); if (Settings::Get('system.dns_createmailentry')) { foreach (array( diff --git a/tests/DomainZones/DomainZonesTest.php b/tests/DomainZones/DomainZonesTest.php index 73b21da8..69e25147 100644 --- a/tests/DomainZones/DomainZonesTest.php +++ b/tests/DomainZones/DomainZonesTest.php @@ -21,6 +21,7 @@ class DomainZonesTest extends TestCase global $admin_userdata; Settings::Set('system.dnsenabled', 1, true); + Settings::Set('system.mxservers', 'mx.hostname.tld', true); // get customer $json_result = Customers::getLocal($admin_userdata, array( @@ -35,6 +36,7 @@ class DomainZonesTest extends TestCase $result = json_decode($json_result, true)['data']; $this->assertTrue(count($result) > 1); $this->assertEquals('$ORIGIN test2.local.', $result[1]); + $this->assertEquals('@ 604800 IN MX 10 mx.hostname.tld.', $result[count($result)-2]); } /** From 61265778a517050495d9fc77c4f5248e4e6d09b3 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Mon, 27 Dec 2021 16:01:45 +0100 Subject: [PATCH 299/319] fix unit-test Signed-off-by: Michael Kaufmann --- tests/DomainZones/DomainZonesTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/DomainZones/DomainZonesTest.php b/tests/DomainZones/DomainZonesTest.php index 69e25147..dc6424ac 100644 --- a/tests/DomainZones/DomainZonesTest.php +++ b/tests/DomainZones/DomainZonesTest.php @@ -36,7 +36,7 @@ class DomainZonesTest extends TestCase $result = json_decode($json_result, true)['data']; $this->assertTrue(count($result) > 1); $this->assertEquals('$ORIGIN test2.local.', $result[1]); - $this->assertEquals('@ 604800 IN MX 10 mx.hostname.tld.', $result[count($result)-2]); + $this->assertEquals('@ 604800 IN MX 10 mx.hostname.tld.', $result[count($result)-2]); } /** From 5f41b37770f4b3606916f909b663e84523d45dc6 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Mon, 27 Dec 2021 16:08:46 +0100 Subject: [PATCH 300/319] test dns entry string without any whitespaces/tabs/etc. Signed-off-by: Michael Kaufmann --- tests/DomainZones/DomainZonesTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/DomainZones/DomainZonesTest.php b/tests/DomainZones/DomainZonesTest.php index dc6424ac..47f1d806 100644 --- a/tests/DomainZones/DomainZonesTest.php +++ b/tests/DomainZones/DomainZonesTest.php @@ -36,7 +36,9 @@ class DomainZonesTest extends TestCase $result = json_decode($json_result, true)['data']; $this->assertTrue(count($result) > 1); $this->assertEquals('$ORIGIN test2.local.', $result[1]); - $this->assertEquals('@ 604800 IN MX 10 mx.hostname.tld.', $result[count($result)-2]); + $resstr = preg_replace('/\s+/', '', $result[count($result)-2]); + $against = preg_replace('/\s+/', '', '@ 604800 IN MX 10 mx.hostname.tld.'); + $this->assertEquals($against, $resstr); } /** From d1d42f205553e3e3f25c26ce316b78285a611cec Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 31 Dec 2021 10:38:49 +0100 Subject: [PATCH 301/319] allow setting path to acme.sh installation; fixes #1002 Signed-off-by: Michael Kaufmann --- actions/admin/settings/131.ssl.php | 9 ++++++ install/froxlor.sql | 3 +- .../updates/froxlor/0.10/update_0.10.inc.php | 7 ++++ lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 32 +++++++++++++------ lib/Froxlor/FileDir.php | 2 +- lib/Froxlor/Froxlor.php | 2 +- lng/english.lng.php | 2 ++ lng/german.lng.php | 2 ++ 8 files changed, 46 insertions(+), 13 deletions(-) diff --git a/actions/admin/settings/131.ssl.php b/actions/admin/settings/131.ssl.php index cfdfbb48..2d30bf3c 100644 --- a/actions/admin/settings/131.ssl.php +++ b/actions/admin/settings/131.ssl.php @@ -133,6 +133,15 @@ return array( 'cronmodule' => 'froxlor/letsencrypt', 'save_method' => 'storeSettingField' ), + 'system_acmeshpath' => array( + 'label' => $lng['serversettings']['acmeshpath'], + 'settinggroup' => 'system', + 'varname' => 'acmeshpath', + 'type' => 'string', + 'string_type' => 'file', + 'default' => '/root/.acme.sh/acme.sh', + 'save_method' => 'storeSettingField' + ), 'system_letsencryptacmeconf' => array( 'label' => $lng['serversettings']['letsencryptacmeconf'], 'settinggroup' => 'system', diff --git a/install/froxlor.sql b/install/froxlor.sql index 248d1fd9..b937c16e 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -682,6 +682,7 @@ opcache.interned_strings_buffer'), ('system', 'createstdsubdom_default', '1'), ('system', 'froxlorusergroup', ''), ('system', 'froxlorusergroup_gid', ''), + ('system', 'acmeshpath', '/root/.acme.sh/acme.sh'), ('api', 'enabled', '0'), ('2fa', 'enabled', '1'), ('panel', 'decimal_places', '4'), @@ -723,7 +724,7 @@ opcache.interned_strings_buffer'), ('panel', 'logo_overridetheme', '0'), ('panel', 'logo_overridecustom', '0'), ('panel', 'version', '0.10.31'), - ('panel', 'db_version', '202109040'); + ('panel', 'db_version', '202112310'); DROP TABLE IF EXISTS `panel_tasks`; diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index 698dc568..1f6e01fd 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -953,3 +953,10 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.30')) { showUpdateStep("Updating from 0.10.30 to 0.10.31", false); \Froxlor\Froxlor::updateToVersion('0.10.31'); } + +if (\Froxlor\Froxlor::isDatabaseVersion('202109040')) { + showUpdateStep("Add setting for acme.sh install location", true); + Settings::AddNew("system.acmeshpath", '/root/.acme.sh/acme.sh'); + lastStepStatus(0); + \Froxlor\Froxlor::updateToDbVersion('202112310'); +} diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index 9b3938d6..da0c796a 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -310,7 +310,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron { if (! empty($domains)) { - $acmesh_cmd = self::$acmesh . " --server " . self::$apiserver . " --issue -d " . implode(" -d ", $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) { @@ -530,7 +530,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron if (Settings::Get('system.leecc') > 0 && ! $forced_noecc) { $domain .= "_ecc"; } - $env_file = FileDir::makeCorrectFile(dirname(self::$acmesh) . '/acme.sh.env'); + $env_file = FileDir::makeCorrectFile(dirname(self::getAcmeSh()) . '/acme.sh.env'); if (file_exists($env_file)) { $output = []; $cut = << 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::$acmesh . "'"); - echo PHP_EOL . "Download/installation of acme.sh seems to have failed. Re-run cronjob to try again or install manually to '" . self::$acmesh . "'" . PHP_EOL; + 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::$acmesh)) { + } 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", $return, array( + \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); } @@ -620,9 +632,9 @@ EOC; */ private static function checkUpgrade() { - $acmesh_result = \Froxlor\FileDir::safe_exec(self::$acmesh . " --upgrade --auto-upgrade 0"); + $acmesh_result = \Froxlor\FileDir::safe_exec(self::getAcmeSh() . " --upgrade --auto-upgrade 0"); // check for activated cron - $acmesh_result2 = \Froxlor\FileDir::safe_exec(self::$acmesh . " --install-cronjob"); + $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/FileDir.php b/lib/Froxlor/FileDir.php index 60251b0d..f19a4271 100644 --- a/lib/Froxlor/FileDir.php +++ b/lib/Froxlor/FileDir.php @@ -16,7 +16,7 @@ class FileDir * @param array $allowedChars * optional array of allowed characters in path/command * - * @return string result of exec() + * @return array result of exec() */ public static function safe_exec($exec_string, &$return_value = false, $allowedChars = null) { diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index 538f1758..a47986ec 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -10,7 +10,7 @@ final class Froxlor const VERSION = '0.10.31'; // Database version (YYYYMMDDC where C is a daily counter) - const DBVERSION = '202109040'; + const DBVERSION = '202112310'; // Distribution branding-tag (used for Debian etc.) const BRANDING = ''; diff --git a/lng/english.lng.php b/lng/english.lng.php index 64d33b3c..96e38fd6 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -2136,3 +2136,5 @@ $lng['error']['notallowedphpconfigused'] = 'Trying to use php-config which is no $lng['serversettings']['phpfpm_settings']['allow_all_customers']['title'] = 'Assign this configuration to all currently existing customers'; $lng['serversettings']['phpfpm_settings']['allow_all_customers']['description'] = 'Set this to "true" if you want to assign this configuration to all currently existing customers so it can be used by them. This setting is not permanent but can be run multiple times.'; $lng['error']['pathmustberelative'] = 'The user does not have the permission to specify directories outside the customers home-directory. Please specify a relative path (no leading /).'; +$lng['serversettings']['acmeshpath']['title'] = 'Path to acme.sh'; +$lng['serversettings']['acmeshpath']['description'] = 'Set this to where acme.sh is installed to, including the acme.sh script
Default is /root/.acme.sh/acme.sh'; diff --git a/lng/german.lng.php b/lng/german.lng.php index c5b7bcc6..be21e7b1 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -1782,3 +1782,5 @@ $lng['error']['notallowedphpconfigused'] = 'Nutzung einer PHP-Konfiguration welc $lng['serversettings']['phpfpm_settings']['allow_all_customers']['title'] = 'Für aktuelle Kunden automatisch hinzufügen'; $lng['serversettings']['phpfpm_settings']['allow_all_customers']['description'] = 'Ist diese Einstellung aktiv, wird die Konfiguration automatisch allen aktuell existierenden Kunden-Accounts zugewiesen. Diese Einstellung ist nicht permanent, kann aber mehrfach / nach Bedarf ausgeführt werden.'; $lng['error']['pathmustberelative'] = 'Der Benutzer hat nicht die benötigten Berechtigungen, um Pfade außerhalb des Kunden-Heimatverzeichnisses anzugeben. Bitte einen relativen Pfad angeben (kein führendes /).'; +$lng['serversettings']['acmeshpath']['title'] = 'Pfad zu acme.sh'; +$lng['serversettings']['acmeshpath']['description'] = 'Installationspfad zu acme.sh, inklusive acme.sh Script
Standard ist /root/.acme.sh/acme.sh'; From 965359ec792fa3b2d17a123f592a3aabcb9af227 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 2 Jan 2022 14:35:36 +0100 Subject: [PATCH 302/319] Update README.md --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bccca0f4..7d49d848 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![Froxlor-CI](https://github.com/Froxlor/Froxlor/actions/workflows/build-mariadb.yml/badge.svg?branch=master)](https://github.com/Froxlor/Froxlor/actions/workflows/build-mariadb.yml) [![Froxlor-CI](https://github.com/Froxlor/Froxlor/actions/workflows/build-mysql.yml/badge.svg?branch=master)](https://github.com/Froxlor/Froxlor/actions/workflows/build-mysql.yml) -[![Gitter](https://badges.gitter.im/Froxlor/community.svg)](https://gitter.im/Froxlor/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) +[![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.gg/7dqQQNbrNh) # Froxlor @@ -27,6 +27,10 @@ https://github.com/Froxlor/Froxlor/wiki/Install-froxlor-from-tarball You may find help in the following places: +### Discord + +The froxlor community discord server can be found here: https://discord.gg/7dqQQNbrNh + ### IRC froxlor may be found on libera.chat, channel #froxlor: From 8c998dd6f24b8129f3f2f282d2065eab5e6be681 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 2 Jan 2022 14:53:59 +0100 Subject: [PATCH 303/319] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7d49d848..24d65ad9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![Froxlor-CI](https://github.com/Froxlor/Froxlor/actions/workflows/build-mariadb.yml/badge.svg?branch=master)](https://github.com/Froxlor/Froxlor/actions/workflows/build-mariadb.yml) [![Froxlor-CI](https://github.com/Froxlor/Froxlor/actions/workflows/build-mysql.yml/badge.svg?branch=master)](https://github.com/Froxlor/Froxlor/actions/workflows/build-mysql.yml) -[![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.gg/7dqQQNbrNh) +[![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.froxlor.org) # Froxlor @@ -29,7 +29,7 @@ You may find help in the following places: ### Discord -The froxlor community discord server can be found here: https://discord.gg/7dqQQNbrNh +The froxlor community discord server can be found here: https://discord.froxlor.org ### IRC From 4b4770ab36c2e105cf3e21a9e3602c4aa13a9fb9 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Mon, 3 Jan 2022 20:27:19 +0100 Subject: [PATCH 304/319] add missing change-check when ssl-specialsettings are changed Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Domains.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php index 340ac88e..5718808b 100644 --- a/lib/Froxlor/Api/Commands/Domains.php +++ b/lib/Froxlor/Api/Commands/Domains.php @@ -1464,7 +1464,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $wwwserveralias = ($serveraliasoption == '1') ? '1' : '0'; $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'] || $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']) { + 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('1'); } From 5832346f75c4f6786e7f91cbf6909276abdacfdb Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 7 Jan 2022 15:38:12 +0100 Subject: [PATCH 305/319] set version to 0.10.32 for upcoming release Signed-off-by: Michael Kaufmann --- install/froxlor.sql | 2 +- install/updates/froxlor/0.10/update_0.10.inc.php | 5 +++++ lib/Froxlor/Froxlor.php | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index b937c16e..6bb494ca 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -723,7 +723,7 @@ opcache.interned_strings_buffer'), ('panel', 'logo_image_login', ''), ('panel', 'logo_overridetheme', '0'), ('panel', 'logo_overridecustom', '0'), - ('panel', 'version', '0.10.31'), + ('panel', 'version', '0.10.32'), ('panel', 'db_version', '202112310'); diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index 1f6e01fd..2351b9fb 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -960,3 +960,8 @@ if (\Froxlor\Froxlor::isDatabaseVersion('202109040')) { lastStepStatus(0); \Froxlor\Froxlor::updateToDbVersion('202112310'); } + +if (\Froxlor\Froxlor::isFroxlorVersion('0.10.31')) { + showUpdateStep("Updating from 0.10.31 to 0.10.32", false); + \Froxlor\Froxlor::updateToVersion('0.10.32'); +} diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index a47986ec..94675e99 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -7,7 +7,7 @@ final class Froxlor { // Main version variable - const VERSION = '0.10.31'; + const VERSION = '0.10.32'; // Database version (YYYYMMDDC where C is a daily counter) const DBVERSION = '202112310'; From c491f2c03ef7b76c33f5bde9b9c6706951753e09 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Thu, 13 Jan 2022 18:42:40 +0100 Subject: [PATCH 306/319] put commands for cronjob setup at the end of the list (should be the last thing to execute) Signed-off-by: Michael Kaufmann --- lib/configfiles/bionic.xml | 12 ++++++------ lib/configfiles/bullseye.xml | 12 ++++++------ lib/configfiles/buster.xml | 12 ++++++------ lib/configfiles/centos7.xml | 12 ++++++------ lib/configfiles/centos8.xml | 12 ++++++------ lib/configfiles/focal.xml | 12 ++++++------ lib/configfiles/gentoo.xml | 12 ++++++------ lib/configfiles/stretch.xml | 12 ++++++------ lib/configfiles/xenial.xml | 12 ++++++------ 9 files changed, 54 insertions(+), 54 deletions(-) diff --git a/lib/configfiles/bionic.xml b/lib/configfiles/bionic.xml index 4b7ae0b5..52774c2f 100644 --- a/lib/configfiles/bionic.xml +++ b/lib/configfiles/bionic.xml @@ -4545,12 +4545,6 @@ UPLOADGID= - - - scripts/froxlor_master_cronjob.php --run-task 99]]> - - @@ -4678,6 +4672,12 @@ aliases: files dirty work --> + + + scripts/froxlor_master_cronjob.php --run-task 99]]> + + diff --git a/lib/configfiles/bullseye.xml b/lib/configfiles/bullseye.xml index 0ed6c24d..45bcc26e 100644 --- a/lib/configfiles/bullseye.xml +++ b/lib/configfiles/bullseye.xml @@ -4756,12 +4756,6 @@ UPLOADGID= - - - scripts/froxlor_master_cronjob.php --run-task 99]]> - - @@ -4889,6 +4883,12 @@ aliases: files dirty work --> + + + scripts/froxlor_master_cronjob.php --run-task 99]]> + + diff --git a/lib/configfiles/buster.xml b/lib/configfiles/buster.xml index 057fd7aa..176e17b7 100644 --- a/lib/configfiles/buster.xml +++ b/lib/configfiles/buster.xml @@ -4747,12 +4747,6 @@ UPLOADGID= - - - scripts/froxlor_master_cronjob.php --run-task 99]]> - - @@ -4880,6 +4874,12 @@ aliases: files dirty work --> + + + scripts/froxlor_master_cronjob.php --run-task 99]]> + + diff --git a/lib/configfiles/centos7.xml b/lib/configfiles/centos7.xml index 5e6c3294..7dfd7344 100644 --- a/lib/configfiles/centos7.xml +++ b/lib/configfiles/centos7.xml @@ -2341,12 +2341,6 @@ ControlsLog /var/log/proftpd/controls.log - - - scripts/froxlor_master_cronjob.php --run-task 99]]> - - @@ -2484,6 +2478,12 @@ aliases: files nisplus
+ + + scripts/froxlor_master_cronjob.php --run-task 99]]> + + diff --git a/lib/configfiles/centos8.xml b/lib/configfiles/centos8.xml index 2e5999c9..d6b1539c 100644 --- a/lib/configfiles/centos8.xml +++ b/lib/configfiles/centos8.xml @@ -2343,12 +2343,6 @@ ControlsLog /var/log/proftpd/controls.log - - - scripts/froxlor_master_cronjob.php --run-task 99]]> - - @@ -2487,6 +2481,12 @@ aliases: files nisplus
+ + + scripts/froxlor_master_cronjob.php --run-task 99]]> + + diff --git a/lib/configfiles/focal.xml b/lib/configfiles/focal.xml index dbdbebfc..ccfd88ea 100644 --- a/lib/configfiles/focal.xml +++ b/lib/configfiles/focal.xml @@ -3961,12 +3961,6 @@ UPLOADGID= - - - scripts/froxlor_master_cronjob.php --run-task 99]]> - - @@ -4102,6 +4096,12 @@ aliases: files dirty work --> + + + scripts/froxlor_master_cronjob.php --run-task 99]]> + + diff --git a/lib/configfiles/gentoo.xml b/lib/configfiles/gentoo.xml index eb28ef51..31c50e00 100644 --- a/lib/configfiles/gentoo.xml +++ b/lib/configfiles/gentoo.xml @@ -3663,12 +3663,6 @@ account required pam_mysql.so user= passwd= - - - scripts/froxlor_master_cronjob.php --run-task 99]]> - - @@ -3875,6 +3869,12 @@ aliases: files dirty work --> + + + scripts/froxlor_master_cronjob.php --run-task 99]]> + + diff --git a/lib/configfiles/stretch.xml b/lib/configfiles/stretch.xml index 7f2f0294..c269c541 100644 --- a/lib/configfiles/stretch.xml +++ b/lib/configfiles/stretch.xml @@ -4534,12 +4534,6 @@ UPLOADGID= - - - scripts/froxlor_master_cronjob.php --run-task 99]]> - - @@ -4667,6 +4661,12 @@ aliases: files dirty work --> + + + scripts/froxlor_master_cronjob.php --run-task 99]]> + + diff --git a/lib/configfiles/xenial.xml b/lib/configfiles/xenial.xml index bbae02e3..e89737df 100644 --- a/lib/configfiles/xenial.xml +++ b/lib/configfiles/xenial.xml @@ -4545,12 +4545,6 @@ UPLOADGID= - - - scripts/froxlor_master_cronjob.php --run-task 99]]> - - @@ -4678,6 +4672,12 @@ aliases: files dirty work --> + + + scripts/froxlor_master_cronjob.php --run-task 99]]> + + From 4d289e2a7f9322b3ea4ec11e4f0a78301558a320 Mon Sep 17 00:00:00 2001 From: timdeluxe <5765175+timdeluxe@users.noreply.github.com> Date: Thu, 13 Jan 2022 19:50:39 +0100 Subject: [PATCH 307/319] Improves text for global open basedir setting (#1004) --- lng/english.lng.php | 2 +- lng/german.lng.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lng/english.lng.php b/lng/english.lng.php index 96e38fd6..fdbcac52 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -851,7 +851,7 @@ $lng['admin']['phpconfig']['pear_dir'] = 'Will be replaced with the global setti $lng['admin']['phpconfig']['open_basedir_c'] = 'Will insert a ; (semicolon) to comment-out/disable open_basedir when set'; $lng['admin']['phpconfig']['open_basedir'] = 'Will be replaced with the open_basedir setting of the domain.'; $lng['admin']['phpconfig']['tmp_dir'] = 'Will be replaced with the temporary directory of the domain.'; -$lng['admin']['phpconfig']['open_basedir_global'] = 'Will be replaced with the global value of the path which will be attached to the open_basedir.'; +$lng['admin']['phpconfig']['open_basedir_global'] = 'Will be replaced with the global value of the path which will be attached to the open_basedir (see webserver settings).'; $lng['admin']['phpconfig']['customer_email'] = 'Will be replaced with the e-mail address of the customer who owns this domain.'; $lng['admin']['phpconfig']['admin_email'] = 'Will be replaced with e-mail address of the admin who owns this domain.'; $lng['admin']['phpconfig']['domain'] = 'Will be replaced with the domain.'; diff --git a/lng/german.lng.php b/lng/german.lng.php index be21e7b1..a897f907 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -843,7 +843,7 @@ $lng['admin']['phpconfig']['pear_dir'] = 'Wird mit dem globalen Wert für das In $lng['admin']['phpconfig']['open_basedir_c'] = 'Wird mit einem ; (Semikolon) ersetzt, um open_basedir auszukommentieren/deaktivieren, wenn eingestellt.'; $lng['admin']['phpconfig']['open_basedir'] = 'Wird mit der open_basedir-Einstellung der Domain ersetzt.'; $lng['admin']['phpconfig']['tmp_dir'] = 'Wird mit der Einstellung für das temporäre Verzeichnis der Domain ersetzt.'; -$lng['admin']['phpconfig']['open_basedir_global'] = 'Wird mit der globalen Einstellung des Pfades ersetzt, der dem open_basedir hinzugefügt wird.'; +$lng['admin']['phpconfig']['open_basedir_global'] = 'Wird mit der globalen Einstellung des Pfades ersetzt, der dem open_basedir hinzugefügt wird (siehe Webserver Einstellungen).'; $lng['admin']['phpconfig']['customer_email'] = 'Wird mit der E-Mail-Adresse des Kunden ersetzt, dem die Domain gehört.'; $lng['admin']['phpconfig']['admin_email'] = 'Wird mit der E-Mail-Adresse des Admins ersetzt, dem die Domain gehört.'; $lng['admin']['phpconfig']['domain'] = 'Wird mit der Domain ersetzt.'; From c97f5f1e29b0a5c311f9fa366b1d86b1659f03ef Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Tue, 18 Jan 2022 09:29:13 +0100 Subject: [PATCH 308/319] updated README; sanitize script parameter in index.php; sanitize description fields of entities (thx to zerody for pointing these out) Signed-off-by: Michael Kaufmann --- README.md | 12 ++++++------ index.php | 2 ++ lib/Froxlor/Api/Commands/FpmDaemons.php | 8 ++++---- lib/Froxlor/Api/Commands/Ftps.php | 4 ++-- lib/Froxlor/Api/Commands/HostingPlans.php | 4 ++-- lib/Froxlor/Api/Commands/Mysqls.php | 4 ++-- lib/Froxlor/Api/Commands/PhpSettings.php | 4 ++-- lib/Froxlor/Cli/Action/ConfigServicesAction.php | 4 ++-- lib/Froxlor/UI/HTML.php | 4 ++-- lib/Froxlor/Validate/Validate.php | 2 ++ 10 files changed, 26 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 24d65ad9..9407c022 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Developed by experienced server administrators, this panel simplifies the effort 9. Have fun! ### Detailed installation -https://github.com/Froxlor/Froxlor/wiki/Install-froxlor-from-tarball +https://docs.froxlor.org/general/installation/index.html ## Help @@ -42,12 +42,12 @@ The community is located on https://forum.froxlor.org/ ### Wiki -More documentation may be found in the froxlor - wiki: -https://github.com/Froxlor/Froxlor/wiki +More documentation may be found in the froxlor - documentation: +https://docs.froxlor.org/ ## License -May be found in COPYING +May be found in [COPYING](COPYING) ## Downloads @@ -56,7 +56,7 @@ https://files.froxlor.org/releases/froxlor-latest.tar.gz [MD5](https://files.fro ### Debian repository -[HowTo](https://github.com/Froxlor/Froxlor/wiki/Install-froxlor-on-debian) +[HowTo](https://docs.froxlor.org/general/installation/aptpackage.html) ``` apt-get -y install apt-transport-https lsb-release ca-certificates @@ -66,7 +66,7 @@ echo "deb https://deb.froxlor.org/debian $(lsb_release -sc) main" > /etc/apt/sou ### Ubuntu repository -[HowTo](https://github.com/Froxlor/Froxlor/wiki/Install-froxlor-on-ubuntu) +[HowTo](https://docs.froxlor.org/general/installation/aptpackage.html) ``` apt-get -y install apt-transport-https lsb-release ca-certificates diff --git a/index.php b/index.php index 83ab7a4b..07a96e82 100644 --- a/index.php +++ b/index.php @@ -378,6 +378,8 @@ if ($action == '2fa_entercode') { $lastscript = ""; if (isset($_REQUEST['script']) && $_REQUEST['script'] != "") { $lastscript = $_REQUEST['script']; + $lastscript = str_replace("..", "", $lastscript); + $lastscript = htmlspecialchars($lastscript, ENT_QUOTES); if (! file_exists(__DIR__ . "/" . $lastscript)) { $lastscript = ""; diff --git a/lib/Froxlor/Api/Commands/FpmDaemons.php b/lib/Froxlor/Api/Commands/FpmDaemons.php index 52192591..36fed4e0 100644 --- a/lib/Froxlor/Api/Commands/FpmDaemons.php +++ b/lib/Froxlor/Api/Commands/FpmDaemons.php @@ -178,9 +178,9 @@ 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', '', '', array(), true); + $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', '', '', array(), true); + $config_dir = \Froxlor\Validate\Validate::validate($config_dir, 'config_dir', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true); if (! in_array($pmanager, array( 'static', 'dynamic', @@ -299,9 +299,9 @@ 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', '', '', array(), true); + $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', '', '', array(), true); + $config_dir = \Froxlor\Validate\Validate::validate($config_dir, 'config_dir', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true); if (! in_array($pmanager, array( 'static', 'dynamic', diff --git a/lib/Froxlor/Api/Commands/Ftps.php b/lib/Froxlor/Api/Commands/Ftps.php index 1e30bd4c..9d7664b4 100644 --- a/lib/Froxlor/Api/Commands/Ftps.php +++ b/lib/Froxlor/Api/Commands/Ftps.php @@ -79,7 +79,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit // 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', '', '', array(), true); + $description = \Froxlor\Validate\Validate::validate(trim($description), 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true); if (Settings::Get('system.allow_customer_shell') == '1') { $shell = \Froxlor\Validate\Validate::validate(trim($shell), 'shell', '', '', array(), true); @@ -396,7 +396,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit // validation $password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true); - $description = \Froxlor\Validate\Validate::validate(trim($description), 'description', '', '', array(), true); + $description = \Froxlor\Validate\Validate::validate(trim($description), 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true); if (Settings::Get('system.allow_customer_shell') == '1') { $shell = \Froxlor\Validate\Validate::validate(trim($shell), 'shell', '', '', array(), true); diff --git a/lib/Froxlor/Api/Commands/HostingPlans.php b/lib/Froxlor/Api/Commands/HostingPlans.php index 68373d52..dbaade04 100644 --- a/lib/Froxlor/Api/Commands/HostingPlans.php +++ b/lib/Froxlor/Api/Commands/HostingPlans.php @@ -216,7 +216,7 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou // validation $name = \Froxlor\Validate\Validate::validate(trim($name), 'name', '', '', array(), true); - $description = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $description), 'description', '/^[^\0]*$/'); + $description = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $description), 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT); if (Settings::Get('system.mail_quota_enabled') != '1') { $value_arr['email_quota'] = - 1; @@ -361,7 +361,7 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou // validation $name = \Froxlor\Validate\Validate::validate(trim($name), 'name', '', '', array(), true); - $description = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $description), 'description', '/^[^\0]*$/'); + $description = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $description), 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT); if (Settings::Get('system.mail_quota_enabled') != '1') { $value_arr['email_quota'] = - 1; diff --git a/lib/Froxlor/Api/Commands/Mysqls.php b/lib/Froxlor/Api/Commands/Mysqls.php index 5083efd5..b0b4b641 100644 --- a/lib/Froxlor/Api/Commands/Mysqls.php +++ b/lib/Froxlor/Api/Commands/Mysqls.php @@ -60,7 +60,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt // 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', '', '', array(), true); + $databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true); if (!empty($databasename)) { $databasename = \Froxlor\Validate\Validate::validate(trim($databasename), 'database_name', '/^[A-Za-z0-9][A-Za-z0-9\-_]+$/i', '', array(), true); } @@ -322,7 +322,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt // validation $password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true); - $databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', '', '', array(), true); + $databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true); if ($password != '') { // validate password diff --git a/lib/Froxlor/Api/Commands/PhpSettings.php b/lib/Froxlor/Api/Commands/PhpSettings.php index 26ef83eb..6689241a 100644 --- a/lib/Froxlor/Api/Commands/PhpSettings.php +++ b/lib/Froxlor/Api/Commands/PhpSettings.php @@ -266,7 +266,7 @@ 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', '', '', array(), true); + $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); if (Settings::Get('system.mod_fcgid') == 1) { $binary = \Froxlor\FileDir::makeCorrectFile(\Froxlor\Validate\Validate::validate($binary, 'binary', '', '', array(), true)); @@ -466,7 +466,7 @@ 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', '', '', array(), true); + $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); if (Settings::Get('system.mod_fcgid') == 1) { $binary = \Froxlor\FileDir::makeCorrectFile(\Froxlor\Validate\Validate::validate($binary, 'binary', '', '', array(), true)); diff --git a/lib/Froxlor/Cli/Action/ConfigServicesAction.php b/lib/Froxlor/Cli/Action/ConfigServicesAction.php index 8d6c5d68..1cd6a5d1 100644 --- a/lib/Froxlor/Cli/Action/ConfigServicesAction.php +++ b/lib/Froxlor/Cli/Action/ConfigServicesAction.php @@ -85,8 +85,8 @@ class ConfigServicesAction extends \Froxlor\Cli\Action $distributions_select_data = array(); //set default os. - $os_dist = array('ID' => 'buster'); - $os_version = array('0' => '10'); + $os_dist = array('ID' => 'bullseye'); + $os_version = array('0' => '11'); $os_default = $os_dist['ID']; //read os-release diff --git a/lib/Froxlor/UI/HTML.php b/lib/Froxlor/UI/HTML.php index 84caf1da..daffbc47 100644 --- a/lib/Froxlor/UI/HTML.php +++ b/lib/Froxlor/UI/HTML.php @@ -269,7 +269,7 @@ class HTML } $text = strtr($text, array( - '%s' => $targetname + '%s' => htmlspecialchars($targetname) )); eval("echo \"" . Template::getTemplate('misc/question_yesno', '1') . "\";"); exit(); @@ -302,7 +302,7 @@ class HTML } $text = strtr($text, array( - '%s' => $targetname + '%s' => htmlspecialchars($targetname) )); eval("echo \"" . Template::getTemplate('misc/question_yesno_checkbox', '1') . "\";"); exit(); diff --git a/lib/Froxlor/Validate/Validate.php b/lib/Froxlor/Validate/Validate.php index edd58587..e8632d06 100644 --- a/lib/Froxlor/Validate/Validate.php +++ b/lib/Froxlor/Validate/Validate.php @@ -10,6 +10,8 @@ class Validate const REGEX_CONF_TEXT = '/^[^\0]*$/'; + const REGEX_DESC_TEXT = '/^[^\0\r\n<>]*$/'; + /** * Validates the given string by matching against the pattern, prints an error on failure and exits * From bcb95e9b7da9937490c75888e76b54fd02c001d6 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Tue, 18 Jan 2022 23:18:54 +0100 Subject: [PATCH 309/319] check resource-usage for Mysql.add(), thx again to zerody Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Mysqls.php | 250 ++++++++++++++-------------- 1 file changed, 127 insertions(+), 123 deletions(-) diff --git a/lib/Froxlor/Api/Commands/Mysqls.php b/lib/Froxlor/Api/Commands/Mysqls.php index b0b4b641..e759ede2 100644 --- a/lib/Froxlor/Api/Commands/Mysqls.php +++ b/lib/Froxlor/Api/Commands/Mysqls.php @@ -1,4 +1,5 @@ getParam('mysql_password'); + if (($this->getUserDetail('mysqls_used') < $this->getUserDetail('mysqls') || $this->getUserDetail('mysqls') == '-1') || $this->isAdmin()) { + // required parameters + $password = $this->getParam('mysql_password'); - // parameters - $dbserver = $this->getParam('mysql_server', true, 0); - $databasedescription = $this->getParam('description', true, ''); - $databasename = $this->getParam('custom_suffix', true, ''); - $sendinfomail = $this->getBoolParam('sendinfomail', true, 0); - // get needed customer info to reduce the mysql-usage-counter by one - $customer = $this->getCustomerData('mysqls'); + // parameters + $dbserver = $this->getParam('mysql_server', true, 0); + $databasedescription = $this->getParam('description', true, ''); + $databasename = $this->getParam('custom_suffix', true, ''); + $sendinfomail = $this->getBoolParam('sendinfomail', true, 0); + // get needed customer info to reduce the mysql-usage-counter by one + $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); - if (!empty($databasename)) { - $databasename = \Froxlor\Validate\Validate::validate(trim($databasename), 'database_name', '/^[A-Za-z0-9][A-Za-z0-9\-_]+$/i', '', array(), true); - } - - // validate whether the dbserver exists - $dbserver = \Froxlor\Validate\Validate::validate($dbserver, html_entity_decode($this->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); - } - - if ($sendinfomail != 1) { - $sendinfomail = 0; - } - - $newdb_params = array( - '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()); - - if(strtoupper(Settings::Get('customer.mysqlprefix')) == 'DBNAME' && !empty($databasename)) { - $username = $dbm->createDatabase($newdb_params['loginname'].'_'.$databasename, $password); - } else { - $username = $dbm->createDatabase($newdb_params['loginname'], $password, $newdb_params['mysql_lastaccountnumber']); - } - - // we've checked against the password in dbm->createDatabase - if ($username == false) { - \Froxlor\UI\Response::standard_error('passwordshouldnotbeusername', '', true); - } - - // add database info to froxlor - $stmt = Database::prepare(" - INSERT INTO `" . TABLE_PANEL_DATABASES . "` - SET - `customerid` = :customerid, - `databasename` = :databasename, - `description` = :description, - `dbserver` = :dbserver - "); - $params = array( - "customerid" => $customer['customerid'], - "databasename" => $username, - "description" => $databasedescription, - "dbserver" => $dbserver - ); - Database::pexecute($stmt, $params, true, true); - $databaseid = Database::lastInsertId(); - $params['id'] = $databaseid; - - // update customer usage - Customers::increaseUsage($customer['customerid'], 'mysqls_used'); - Customers::increaseUsage($customer['customerid'], 'mysql_lastaccountnumber'); - - // send info-mail? - if ($sendinfomail == 1) { - $pma = $this->lng['admin']['notgiven']; - if (Settings::Get('panel.phpmyadmin_url') != '') { - $pma = Settings::Get('panel.phpmyadmin_url'); + // 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); + if (!empty($databasename)) { + $databasename = \Froxlor\Validate\Validate::validate(trim($databasename), 'database_name', '/^[A-Za-z0-9][A-Za-z0-9\-_]+$/i', '', array(), true); } + // validate whether the dbserver exists + $dbserver = \Froxlor\Validate\Validate::validate($dbserver, html_entity_decode($this->lng['mysql']['mysql_server']), '', '', 0, true); Database::needRoot(true, $dbserver); Database::needSqlData(); $sql_root = Database::getSqlData(); Database::needRoot(false); - $userinfo = $customer; + if (!isset($sql_root) || !is_array($sql_root)) { + throw new \Exception("Database server with index #" . $dbserver . " is unknown", 404); + } - $replace_arr = array( - 'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($userinfo), - 'CUST_NAME' => \Froxlor\User::getCorrectUserSalutation($userinfo), // < keep this for compatibility - 'NAME' => $userinfo['name'], - 'FIRSTNAME' => $userinfo['firstname'], - 'COMPANY' => $userinfo['company'], - 'CUSTOMER_NO' => $userinfo['customernumber'], - 'DB_NAME' => $username, - 'DB_PASS' => htmlentities(htmlentities($password)), - 'DB_DESC' => $databasedescription, - 'DB_SRV' => $sql_root['host'], - 'PMA_URI' => $pma + if ($sendinfomail != 1) { + $sendinfomail = 0; + } + + $newdb_params = array( + '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()); - // get template for mail subject - $mail_subject = $this->getMailTemplate($userinfo, 'mails', 'new_database_by_customer_subject', $replace_arr, $this->lng['mails']['new_database_by_customer']['subject']); - // get template for mail body - $mail_body = $this->getMailTemplate($userinfo, 'mails', 'new_database_by_customer_mailbody', $replace_arr, $this->lng['mails']['new_database_by_customer']['mailbody']); - - $_mailerror = false; - $mailerr_msg = ""; - try { - $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()->send(); - } catch (\PHPMailer\PHPMailer\Exception $e) { - $mailerr_msg = $e->errorMessage(); - $_mailerror = true; - } catch (\Exception $e) { - $mailerr_msg = $e->getMessage(); - $_mailerror = true; + if (strtoupper(Settings::Get('customer.mysqlprefix')) == 'DBNAME' && !empty($databasename)) { + $username = $dbm->createDatabase($newdb_params['loginname'] . '_' . $databasename, $password); + } else { + $username = $dbm->createDatabase($newdb_params['loginname'], $password, $newdb_params['mysql_lastaccountnumber']); } - 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); + // we've checked against the password in dbm->createDatabase + if ($username == false) { + \Froxlor\UI\Response::standard_error('passwordshouldnotbeusername', '', true); } - $this->mailer()->clearAddresses(); + // add database info to froxlor + $stmt = Database::prepare(" + INSERT INTO `" . TABLE_PANEL_DATABASES . "` + SET + `customerid` = :customerid, + `databasename` = :databasename, + `description` = :description, + `dbserver` = :dbserver + "); + $params = array( + "customerid" => $customer['customerid'], + "databasename" => $username, + "description" => $databasedescription, + "dbserver" => $dbserver + ); + Database::pexecute($stmt, $params, true, true); + $databaseid = Database::lastInsertId(); + $params['id'] = $databaseid; + + // update customer usage + Customers::increaseUsage($customer['customerid'], 'mysqls_used'); + Customers::increaseUsage($customer['customerid'], 'mysql_lastaccountnumber'); + + // send info-mail? + if ($sendinfomail == 1) { + $pma = $this->lng['admin']['notgiven']; + if (Settings::Get('panel.phpmyadmin_url') != '') { + $pma = Settings::Get('panel.phpmyadmin_url'); + } + + Database::needRoot(true, $dbserver); + Database::needSqlData(); + $sql_root = Database::getSqlData(); + Database::needRoot(false); + $userinfo = $customer; + + $replace_arr = array( + 'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($userinfo), + 'CUST_NAME' => \Froxlor\User::getCorrectUserSalutation($userinfo), // < keep this for compatibility + 'NAME' => $userinfo['name'], + 'FIRSTNAME' => $userinfo['firstname'], + 'COMPANY' => $userinfo['company'], + 'CUSTOMER_NO' => $userinfo['customernumber'], + 'DB_NAME' => $username, + 'DB_PASS' => htmlentities(htmlentities($password)), + '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, $this->lng['mails']['new_database_by_customer']['subject']); + // get template for mail body + $mail_body = $this->getMailTemplate($userinfo, 'mails', 'new_database_by_customer_mailbody', $replace_arr, $this->lng['mails']['new_database_by_customer']['mailbody']); + + $_mailerror = false; + $mailerr_msg = ""; + try { + $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()->send(); + } catch (\PHPMailer\PHPMailer\Exception $e) { + $mailerr_msg = $e->errorMessage(); + $_mailerror = true; + } 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->mailer()->clearAddresses(); + } + $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] added mysql-database '" . $username . "'"); + + $result = $this->apiCall('Mysqls.get', array( + 'dbname' => $username + )); + return $this->response(200, "successful", $result); } - $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] added mysql-database '" . $username . "'"); - - $result = $this->apiCall('Mysqls.get', array( - 'dbname' => $username - )); - return $this->response(200, "successful", $result); + throw new \Exception("No more resources available", 406); } /** @@ -202,7 +206,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $id = $this->getParam('id', true, 0); $dn_optional = ($id <= 0 ? false : true); $dbname = $this->getParam('dbname', $dn_optional, ''); - $dbserver = $this->getParam('mysql_server', true, - 1); + $dbserver = $this->getParam('mysql_server', true, -1); if ($this->isAdmin()) { if ($this->getUserDetail('customers_see_all') != 1) { @@ -302,7 +306,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $id = $this->getParam('id', true, 0); $dn_optional = ($id <= 0 ? false : true); $dbname = $this->getParam('dbname', $dn_optional, ''); - $dbserver = $this->getParam('mysql_server', true, - 1); + $dbserver = $this->getParam('mysql_server', true, -1); $customer = $this->getCustomerData(); if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'mysql')) { @@ -389,7 +393,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt public function listing() { $result = array(); - $dbserver = $this->getParam('mysql_server', true, - 1); + $dbserver = $this->getParam('mysql_server', true, -1); $customer_ids = $this->getAllowedCustomerIds('mysql'); $query_fields = array(); $result_stmt = Database::prepare(" @@ -486,7 +490,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $id = $this->getParam('id', true, 0); $dn_optional = ($id <= 0 ? false : true); $dbname = $this->getParam('dbname', $dn_optional, ''); - $dbserver = $this->getParam('mysql_server', true, - 1); + $dbserver = $this->getParam('mysql_server', true, -1); $customer = $this->getCustomerData(); if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'mysql')) { From 4a912e3902ea975e968afc75b48019d46c50d04f Mon Sep 17 00:00:00 2001 From: Oskar Eisemuth Date: Fri, 21 Jan 2022 10:03:45 +0100 Subject: [PATCH 310/319] Feature/crontaskid (#1005) * Add \Froxlor\Cron\TaskId for fixed task id naming * Replace Cronjob::inserttask numbers with \Froxlor\Cron\TaskId constants * Use TaskId in Froxlor\Cron\System\TasksCron * Use TaskId in Froxlor\System\Cronjob, simplify getOutstandingTasks. Rename lng['tasks'] cronjob task description. WARNING: DELETE_DOMAIN_PDNS, DELETE_DOMAIN_SSL now use %domain% * Remove Froxlor\System\Cronjob type 3 check --- admin_domains.php | 4 +- admin_settings.php | 14 +-- admin_updates.php | 2 +- lib/Froxlor/Api/Commands/Certificates.php | 4 +- lib/Froxlor/Api/Commands/Cronjobs.php | 2 +- lib/Froxlor/Api/Commands/CustomerBackups.php | 2 +- lib/Froxlor/Api/Commands/Customers.php | 30 +++--- lib/Froxlor/Api/Commands/DirOptions.php | 6 +- lib/Froxlor/Api/Commands/DirProtections.php | 6 +- lib/Froxlor/Api/Commands/DomainZones.php | 4 +- lib/Froxlor/Api/Commands/Domains.php | 20 ++-- lib/Froxlor/Api/Commands/EmailAccounts.php | 2 +- lib/Froxlor/Api/Commands/FpmDaemons.php | 6 +- lib/Froxlor/Api/Commands/Froxlor.php | 8 +- lib/Froxlor/Api/Commands/Ftps.php | 8 +- lib/Froxlor/Api/Commands/IpsAndPorts.php | 12 +-- lib/Froxlor/Api/Commands/PhpSettings.php | 6 +- lib/Froxlor/Api/Commands/SubDomains.php | 18 ++-- lib/Froxlor/Cron/MasterCron.php | 8 +- lib/Froxlor/Cron/System/TasksCron.php | 22 ++-- lib/Froxlor/Cron/TaskId.php | 105 +++++++++++++++++++ lib/Froxlor/Settings/Store.php | 2 +- lib/Froxlor/System/Cronjob.php | 100 ++++++------------ lng/czech.lng.php | 24 ++--- lng/dutch.lng.php | 10 +- lng/english.lng.php | 24 ++--- lng/german.lng.php | 24 ++--- lng/italian.lng.php | 18 ++-- phpunit.xml | 1 + tests/Cron/TaskIdTest.php | 84 +++++++++++++++ 30 files changed, 368 insertions(+), 208 deletions(-) create mode 100644 lib/Froxlor/Cron/TaskId.php create mode 100644 tests/Cron/TaskIdTest.php diff --git a/admin_domains.php b/admin_domains.php index e4170e8b..fc88f711 100644 --- a/admin_domains.php +++ b/admin_domains.php @@ -640,8 +640,8 @@ if ($page == 'domains' || $page == 'overview') { // update customer/admin counters \Froxlor\User::updateCounters(false); - \Froxlor\System\Cronjob::inserttask('1'); - \Froxlor\System\Cronjob::inserttask('4'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\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( diff --git a/admin_settings.php b/admin_settings.php index 4e9aba21..162fe4d3 100644 --- a/admin_settings.php +++ b/admin_settings.php @@ -66,11 +66,11 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') { '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('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask('4'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); // cron.d file - \Froxlor\System\Cronjob::inserttask('99'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_CRON); \Froxlor\UI\Response::standard_success('settingssaved', '', array( 'filename' => $filename, @@ -146,12 +146,12 @@ if ($page == 'overview' && $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('1'); - \Froxlor\System\Cronjob::inserttask('10'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_QUOTA); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask('4'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); // cron.d file - \Froxlor\System\Cronjob::inserttask('99'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_CRON); \Froxlor\UI\Response::standard_success('rebuildingconfigs', '', array( 'filename' => 'admin_index.php' diff --git a/admin_updates.php b/admin_updates.php index 2b0e3420..9f6357df 100644 --- a/admin_updates.php +++ b/admin_updates.php @@ -65,7 +65,7 @@ if ($page == 'overview') { eval("echo \"" . \Froxlor\UI\Template::getTemplate('update/update_end') . "\";"); \Froxlor\User::updateCounters(); - \Froxlor\System\Cronjob::inserttask('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); @chmod(\Froxlor\Froxlor::getInstallDir() . '/lib/userdata.inc.php', 0440); $successful_update = true; diff --git a/lib/Froxlor/Api/Commands/Certificates.php b/lib/Froxlor/Api/Commands/Certificates.php index 69ffc718..a611eedf 100644 --- a/lib/Froxlor/Api/Commands/Certificates.php +++ b/lib/Froxlor/Api/Commands/Certificates.php @@ -323,7 +323,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou )); // trigger removing of certificate from acme.sh if let's encrypt if ($chk['letsencrypt'] == '1') { - \Froxlor\System\Cronjob::inserttask('12', $chk['domain']); + \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(200, "successful", $result); @@ -421,7 +421,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou ); Database::pexecute($stmt, $params, true, true); // insert task to re-generate webserver-configs (#1260) - \Froxlor\System\Cronjob::inserttask('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); return true; } } diff --git a/lib/Froxlor/Api/Commands/Cronjobs.php b/lib/Froxlor/Api/Commands/Cronjobs.php index d6bd7889..34c0f218 100644 --- a/lib/Froxlor/Api/Commands/Cronjobs.php +++ b/lib/Froxlor/Api/Commands/Cronjobs.php @@ -114,7 +114,7 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE ), true, true); // insert task to re-generate the cron.d-file - \Froxlor\System\Cronjob::inserttask('99'); + \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( 'id' => $id diff --git a/lib/Froxlor/Api/Commands/CustomerBackups.php b/lib/Froxlor/Api/Commands/CustomerBackups.php index 84941cec..f899b6ca 100644 --- a/lib/Froxlor/Api/Commands/CustomerBackups.php +++ b/lib/Froxlor/Api/Commands/CustomerBackups.php @@ -108,7 +108,7 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re 'backup_web' => $backup_web ); // schedule backup job - \Froxlor\System\Cronjob::inserttask('20', $task_data); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\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); return $this->response(200, "successful", $task_data); diff --git a/lib/Froxlor/Api/Commands/Customers.php b/lib/Froxlor/Api/Commands/Customers.php index e89031c3..b1dd1034 100644 --- a/lib/Froxlor/Api/Commands/Customers.php +++ b/lib/Froxlor/Api/Commands/Customers.php @@ -645,10 +645,10 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource unset($ins_data); // insert task to create homedir etc. - \Froxlor\System\Cronjob::inserttask('2', $loginname, $guid, $guid, $store_defaultindex); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_HOME, $loginname, $guid, $guid, $store_defaultindex); // Using filesystem - quota, insert a task which cleans the filesystem - quota - \Froxlor\System\Cronjob::inserttask('10'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_QUOTA); // Add htpasswd for the stats-pages $htpasswdPassword = \Froxlor\System\Crypt::makeCryptPassword($password, true); @@ -674,7 +674,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $this->logger()->logAction(\Froxlor\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('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); // add default FTP-User // also, add froxlor-local user to ftp-group (if exists!) to @@ -739,7 +739,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource 'customerid' => $customerid ), true, true); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] automatically added standardsubdomain for user '" . $loginname . "'"); - \Froxlor\System\Cronjob::inserttask('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); } } @@ -1088,7 +1088,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource '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('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); } } @@ -1102,11 +1102,11 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource $this->logger()->logAction(\Froxlor\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('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); } if ($phpenabled != $result['phpenabled'] || $perlenabled != $result['perlenabled'] || $email != $result['email']) { - \Froxlor\System\Cronjob::inserttask('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); } // activate/deactivate customer services @@ -1192,7 +1192,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource ), true, true); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] " . ($deactivated ? 'deactivated' : 'reactivated') . " user '" . $result['loginname'] . "'"); - \Froxlor\System\Cronjob::inserttask('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); } // Disable or enable POP3 Login for customers Mail Accounts @@ -1304,7 +1304,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('10'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_QUOTA); $admin_update_query = "UPDATE `" . TABLE_PANEL_ADMINS . "` SET `customers_used` = `customers_used` "; @@ -1512,9 +1512,9 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource 'did' => $row['id'] ), true, true); // remove domains DNS from powerDNS if used, #581 - \Froxlor\System\Cronjob::inserttask('11', $row['domain']); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_PDNS, $row['domain']); // remove domain from acme.sh / lets encrypt if used - \Froxlor\System\Cronjob::inserttask('12', $row['domain']); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_SSL, $row['domain']); } // remove customer domains $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :id"); @@ -1643,18 +1643,18 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource } // rebuild configs - \Froxlor\System\Cronjob::inserttask('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask('4'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); if ($delete_userfiles == 1) { // insert task to remove the customers files from the filesystem - \Froxlor\System\Cronjob::inserttask('6', $result['loginname']); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_CUSTOMER_FILES, $result['loginname']); } // Using filesystem - quota, insert a task which cleans the filesystem - quota - \Froxlor\System\Cronjob::inserttask('10'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_QUOTA); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted customer '" . $result['loginname'] . "'"); return $this->response(200, "successful", $result); diff --git a/lib/Froxlor/Api/Commands/DirOptions.php b/lib/Froxlor/Api/Commands/DirOptions.php index fc54f0cb..d5c0c010 100644 --- a/lib/Froxlor/Api/Commands/DirOptions.php +++ b/lib/Froxlor/Api/Commands/DirOptions.php @@ -123,7 +123,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc 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('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); $result = $this->apiCall('DirOptions.get', array( 'id' => $id @@ -248,7 +248,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc } if (($options_indexes != $result['options_indexes']) || ($error404path != $result['error404path']) || ($error403path != $result['error403path']) || ($error500path != $result['error500path']) || ($options_cgi != $result['options_cgi'])) { - \Froxlor\System\Cronjob::inserttask('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); $stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_HTACCESS . "` SET `options_indexes` = :options_indexes, @@ -413,7 +413,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc "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('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); return $this->response(200, "successful", $result); } diff --git a/lib/Froxlor/Api/Commands/DirProtections.php b/lib/Froxlor/Api/Commands/DirProtections.php index 241592d2..8137b93e 100644 --- a/lib/Froxlor/Api/Commands/DirProtections.php +++ b/lib/Froxlor/Api/Commands/DirProtections.php @@ -106,7 +106,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res 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('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); $result = $this->apiCall('DirProtections.get', array( 'id' => $id @@ -251,7 +251,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res 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('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\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'] . ")'"); @@ -385,7 +385,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res )); $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('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); return $this->response(200, "successful", $result); } } diff --git a/lib/Froxlor/Api/Commands/DomainZones.php b/lib/Froxlor/Api/Commands/DomainZones.php index a51e59e0..7c0b385b 100644 --- a/lib/Froxlor/Api/Commands/DomainZones.php +++ b/lib/Froxlor/Api/Commands/DomainZones.php @@ -336,7 +336,7 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $dom_entries[] = $new_entry; // re-generate bind configs - \Froxlor\System\Cronjob::inserttask('4'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); $result = $this->apiCall('DomainZones.get', array( 'id' => $id @@ -542,7 +542,7 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour ), true, true); if ($del_stmt->rowCount() > 0) { // re-generate bind configs - \Froxlor\System\Cronjob::inserttask('4'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); return $this->response(200, "successful", true); } return $this->response(304, "successful", true); diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php index 5718808b..3113f528 100644 --- a/lib/Froxlor/Api/Commands/Domains.php +++ b/lib/Froxlor/Api/Commands/Domains.php @@ -857,9 +857,9 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn \Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger()); - \Froxlor\System\Cronjob::inserttask('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask('4'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added domain '" . $domain . "'"); @@ -1465,7 +1465,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('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); } if ($speciallogfile != $result['speciallogfile'] && $speciallogverified != '1') { @@ -1473,11 +1473,11 @@ 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('4'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); } // check whether nameserver has been disabled, #581 if ($isbinddomain != $result['isbinddomain'] && $isbinddomain == 0) { - \Froxlor\System\Cronjob::inserttask('11', $result['domain']); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_PDNS, $result['domain']); } if ($isemaildomain == '0' && $result['isemaildomain'] == '1') { @@ -1506,7 +1506,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn 'id' => $id ), true, true); // remove domain from acme.sh / lets encrypt if used - \Froxlor\System\Cronjob::inserttask('12', $result['domain']); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_SSL, $result['domain']); } $updatechildren = ''; @@ -1984,16 +1984,16 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn \Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger()); // remove domains DNS from powerDNS if used, #581 - \Froxlor\System\Cronjob::inserttask('11', $result['domain']); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_PDNS, $result['domain']); // remove domain from acme.sh / lets encrypt if used - \Froxlor\System\Cronjob::inserttask('12', $result['domain']); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\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('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask('4'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); return $this->response(200, "successful", $result); } 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 34b9d06b..9ee1d16c 100644 --- a/lib/Froxlor/Api/Commands/EmailAccounts.php +++ b/lib/Froxlor/Api/Commands/EmailAccounts.php @@ -499,7 +499,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso } if ($delete_userfiles) { - \Froxlor\System\Cronjob::inserttask('7', $customer['loginname'], $result['email_full']); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_EMAIL_DATA, $customer['loginname'], $result['email_full']); } // decrease usage for customer diff --git a/lib/Froxlor/Api/Commands/FpmDaemons.php b/lib/Froxlor/Api/Commands/FpmDaemons.php index 36fed4e0..b443798b 100644 --- a/lib/Froxlor/Api/Commands/FpmDaemons.php +++ b/lib/Froxlor/Api/Commands/FpmDaemons.php @@ -229,7 +229,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc Database::pexecute($ins_stmt, $ins_data); $id = Database::lastInsertId(); - \Froxlor\System\Cronjob::inserttask('1'); + \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( 'id' => $id @@ -351,7 +351,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc ); Database::pexecute($upd_stmt, $upd_data, true, true); - \Froxlor\System\Cronjob::inserttask('1'); + \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( 'id' => $id @@ -400,7 +400,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc 'id' => $id ), true, true); - \Froxlor\System\Cronjob::inserttask('1'); + \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') . "'"); return $this->response(200, "successful", $result); } diff --git a/lib/Froxlor/Api/Commands/Froxlor.php b/lib/Froxlor/Api/Commands/Froxlor.php index 78c772c9..7aecb886 100644 --- a/lib/Froxlor/Api/Commands/Froxlor.php +++ b/lib/Froxlor/Api/Commands/Froxlor.php @@ -123,12 +123,12 @@ class Froxlor extends \Froxlor\Api\ApiCommand $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "User " . $this->getUserDetail('loginname') . " imported settings"); try { \Froxlor\SImExporter::import($json_str); - \Froxlor\System\Cronjob::inserttask('1'); - \Froxlor\System\Cronjob::inserttask('10'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_QUOTA); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask('4'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); // cron.d file - \Froxlor\System\Cronjob::inserttask('99'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_CRON); return $this->response(200, "successful", true); } catch (\Exception $e) { throw new \Exception($e->getMessage(), 406); diff --git a/lib/Froxlor/Api/Commands/Ftps.php b/lib/Froxlor/Api/Commands/Ftps.php index 9d7664b4..5b05cf13 100644 --- a/lib/Froxlor/Api/Commands/Ftps.php +++ b/lib/Froxlor/Api/Commands/Ftps.php @@ -234,7 +234,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit } $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(5); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_FTP); if ($sendinfomail == 1) { $replace_arr = array( @@ -450,7 +450,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit } // it's the task for "new ftp" but that will // create all directories and correct their permissions - \Froxlor\System\Cronjob::inserttask(5); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_FTP); $stmt = Database::prepare(" UPDATE `" . TABLE_FTP_USERS . "` @@ -628,11 +628,11 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit // refs #293 if ($delete_userfiles == 1) { - \Froxlor\System\Cronjob::inserttask('8', $customer_data['loginname'], $result['homedir']); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\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(5); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_FTP); } } diff --git a/lib/Froxlor/Api/Commands/IpsAndPorts.php b/lib/Froxlor/Api/Commands/IpsAndPorts.php index 4f8fd1e4..71d836fb 100644 --- a/lib/Froxlor/Api/Commands/IpsAndPorts.php +++ b/lib/Froxlor/Api/Commands/IpsAndPorts.php @@ -298,9 +298,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour Database::pexecute($ins_stmt, $ins_data); $ins_data['id'] = Database::lastInsertId(); - \Froxlor\System\Cronjob::inserttask('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask('4'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { $ip = '[' . $ip . ']'; @@ -511,9 +511,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour ); Database::pexecute($upd_stmt, $upd_data); - \Froxlor\System\Cronjob::inserttask('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask('4'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] changed IP/port from '" . $result['ip'] . ":" . $result['port'] . "' to '" . $ip . ":" . $port . "'"); @@ -584,9 +584,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour 'id' => $id ), true, true); - \Froxlor\System\Cronjob::inserttask('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask('4'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted IP/port '" . $result['ip'] . ":" . $result['port'] . "'"); return $this->response(200, "successful", $result); diff --git a/lib/Froxlor/Api/Commands/PhpSettings.php b/lib/Froxlor/Api/Commands/PhpSettings.php index 6689241a..ae59726f 100644 --- a/lib/Froxlor/Api/Commands/PhpSettings.php +++ b/lib/Froxlor/Api/Commands/PhpSettings.php @@ -364,7 +364,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour Database::pexecute($ins_stmt, $ins_data, true, true); $ins_data['id'] = Database::lastInsertId(); - \Froxlor\System\Cronjob::inserttask('1'); + \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') . "'"); $result = $this->apiCall('PhpSettings.get', array( @@ -565,7 +565,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour ); Database::pexecute($upd_stmt, $upd_data, true, true); - \Froxlor\System\Cronjob::inserttask('1'); + \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') . "'"); $result = $this->apiCall('PhpSettings.get', array( @@ -622,7 +622,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour 'id' => $id ), true, true); - \Froxlor\System\Cronjob::inserttask('1'); + \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') . "'"); return $this->response(200, "successful", $result); } diff --git a/lib/Froxlor/Api/Commands/SubDomains.php b/lib/Froxlor/Api/Commands/SubDomains.php index c3a0a322..16717ea5 100644 --- a/lib/Froxlor/Api/Commands/SubDomains.php +++ b/lib/Froxlor/Api/Commands/SubDomains.php @@ -359,9 +359,9 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc \Froxlor\Domain\Domain::addRedirectToDomain($subdomain_id, $redirectcode); } - \Froxlor\System\Cronjob::inserttask('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask('4'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); Customers::increaseUsage($customer['customerid'], 'subdomains_used'); @@ -733,11 +733,11 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc 'id' => $id ), true, true); // remove domain from acme.sh / lets encrypt if used - \Froxlor\System\Cronjob::inserttask('12', $result['domain']); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_SSL, $result['domain']); } - \Froxlor\System\Cronjob::inserttask('1'); - \Froxlor\System\Cronjob::inserttask('4'); + \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']) . "'"); } @@ -1019,13 +1019,13 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc 'domainid' => $id ), true, true); - \Froxlor\System\Cronjob::inserttask('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); // Using nameserver, insert a task which rebuilds the server config - \Froxlor\System\Cronjob::inserttask('4'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); // remove domains DNS from powerDNS if used, #581 - \Froxlor\System\Cronjob::inserttask('11', $result['domain']); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_PDNS, $result['domain']); // remove domain from acme.sh / lets encrypt if used - \Froxlor\System\Cronjob::inserttask('12', $result['domain']); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_SSL, $result['domain']); // reduce subdomain-usage-counter Customers::decreaseUsage($customer['customerid'], 'subdomains_used'); diff --git a/lib/Froxlor/Cron/MasterCron.php b/lib/Froxlor/Cron/MasterCron.php index 0c4c88e4..2f2b52a0 100644 --- a/lib/Froxlor/Cron/MasterCron.php +++ b/lib/Froxlor/Cron/MasterCron.php @@ -63,13 +63,13 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron if (strtolower($argv[$x]) == '--force') { // really force re-generating of config-files by // inserting task 1 - \Froxlor\System\Cronjob::inserttask('1'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST); // bind (if enabled, \Froxlor\System\Cronjob::inserttask() checks this) - \Froxlor\System\Cronjob::inserttask('4'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); // set quotas (if enabled) - \Froxlor\System\Cronjob::inserttask('10'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_QUOTA); // also regenerate cron.d-file - \Froxlor\System\Cronjob::inserttask('99'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_CRON); array_push($jobs_to_run, 'tasks'); define('CRON_IS_FORCED', 1); } elseif (strtolower($argv[$x]) == '--debug') { diff --git a/lib/Froxlor/Cron/System/TasksCron.php b/lib/Froxlor/Cron/System/TasksCron.php index b78575f0..99c93944 100644 --- a/lib/Froxlor/Cron/System/TasksCron.php +++ b/lib/Froxlor/Cron/System/TasksCron.php @@ -4,6 +4,8 @@ namespace Froxlor\Cron\System; use Froxlor\Database\Database; use Froxlor\Settings; +use Froxlor\Cron\TaskId; + /** * This file is part of the Froxlor project. * Copyright (c) 2003-2009 the SysCP Team (see authors). @@ -45,55 +47,55 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron $row['data'] = json_decode($row['data'], true); } - if ($row['type'] == '1') { + if ($row['type'] == TaskId::REBUILD_VHOST) { /** * TYPE=1 MEANS TO REBUILD APACHE VHOSTS.CONF */ self::rebuildWebserverConfigs(); - } elseif ($row['type'] == '2') { + } elseif ($row['type'] == TaskId::CREATE_HOME) { /** * TYPE=2 MEANS TO CREATE A NEW HOME AND CHOWN */ self::createNewHome($row); - } elseif ($row['type'] == '4' && (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 */ self::rebuildDnsConfigs(); - } elseif ($row['type'] == '5') { + } elseif ($row['type'] == TaskId::CREATE_FTP) { /** * TYPE=5 MEANS THAT A NEW FTP-ACCOUNT HAS BEEN CREATED, CREATE THE DIRECTORY */ self::createNewFtpHome($row); - } elseif ($row['type'] == '6') { + } elseif ($row['type'] == TaskId::DELETE_CUSTOMER_FILES) { /** * TYPE=6 MEANS THAT A CUSTOMER HAS BEEN DELETED AND THAT WE HAVE TO REMOVE ITS FILES */ self::deleteCustomerData($row); - } elseif ($row['type'] == '7') { + } elseif ($row['type'] == TaskId::DELETE_EMAIL_DATA) { /** * TYPE=7 Customer deleted an email account and wants the data to be deleted on the filesystem */ self::deleteEmailData($row); - } elseif ($row['type'] == '8') { + } elseif ($row['type'] == TaskId::DELETE_FTP_DATA) { /** * TYPE=8 Customer deleted a ftp account and wants the homedir to be deleted on the filesystem * refs #293 */ self::deleteFtpData($row); - } elseif ($row['type'] == '10' && (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 */ self::setFilesystemQuota(); - } elseif ($row['type'] == '11' && Settings::Get('system.dns_server') == 'PowerDNS') { + } elseif ($row['type'] == TaskId::DELETE_DOMAIN_PDNS && Settings::Get('system.dns_server') == 'PowerDNS') { /** * 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']); - } elseif ($row['type'] == '12') { + } elseif ($row['type'] == TaskId::DELETE_DOMAIN_SSL) { /** * TYPE=12 domain has been deleted, remove from acme.sh/let's encrypt directory if used */ diff --git a/lib/Froxlor/Cron/TaskId.php b/lib/Froxlor/Cron/TaskId.php new file mode 100644 index 00000000..f862e2fe --- /dev/null +++ b/lib/Froxlor/Cron/TaskId.php @@ -0,0 +1,105 @@ +getConstants(); + } + return in_array($numericid, $reflContants, true); + } + + /** + * 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) { + static $reflContants; + if (!is_numeric($id)) { + return false; + } + $numericid = (int)$id; + if (!is_array($reflContants)) { + $reflClass = new \ReflectionClass(get_called_class()); + $reflContants = $reflClass->getConstants(); + } + return array_search($numericid, $reflContants, true); + } +} + diff --git a/lib/Froxlor/Settings/Store.php b/lib/Froxlor/Settings/Store.php index 1f8a3a60..d282947c 100644 --- a/lib/Froxlor/Settings/Store.php +++ b/lib/Froxlor/Settings/Store.php @@ -174,7 +174,7 @@ class Store $returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue); if ($returnvalue !== false) { - \Froxlor\System\Cronjob::inserttask('4'); + \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); } return $returnvalue; } diff --git a/lib/Froxlor/System/Cronjob.php b/lib/Froxlor/System/Cronjob.php index a08dbaa0..030b555b 100644 --- a/lib/Froxlor/System/Cronjob.php +++ b/lib/Froxlor/System/Cronjob.php @@ -4,6 +4,8 @@ namespace Froxlor\System; use Froxlor\Settings; use Froxlor\Database\Database; +use Froxlor\Cron\TaskId; + class Cronjob { @@ -109,13 +111,13 @@ class Cronjob INSERT INTO `" . TABLE_PANEL_TASKS . "` SET `type` = :type, `data` = :data "); - if ($type == '1' || $type == '3' || $type == '4' || $type == '5' || $type == '10' || $type == '99') { + if ($type == TaskId::REBUILD_VHOST || $type == TaskId::REBUILD_DNS || $type == TaskId::CREATE_FTP || $type == TaskId::CREATE_QUOTA || $type == TaskId::REBUILD_CRON) { // 4 = bind -> if bind disabled -> no task - if ($type == '4' && Settings::Get('system.bind_enable') == '0') { + if ($type == TaskId::REBUILD_DNS && Settings::Get('system.bind_enable') == '0') { return; } // 10 = quota -> if quota disabled -> no task - if ($type == '10' && Settings::Get('system.diskquota_enabled') == '0') { + if ($type == TaskId::CREATE_QUOTA && Settings::Get('system.diskquota_enabled') == '0') { return; } @@ -132,7 +134,7 @@ class Cronjob 'type' => $type, 'data' => '' )); - } elseif ($type == '2' && $param1 != '' && $param2 != '' && $param3 != '' && ($param4 == 0 || $param4 == 1)) { + } elseif ($type == TaskId::CREATE_HOME && $param1 != '' && $param2 != '' && $param3 != '' && ($param4 == 0 || $param4 == 1)) { $data = array(); $data['loginname'] = $param1; $data['uid'] = $param2; @@ -140,56 +142,56 @@ class Cronjob $data['store_defaultindex'] = $param4; $data = json_encode($data); Database::pexecute($ins_stmt, array( - 'type' => '2', + 'type' => TaskId::CREATE_HOME, 'data' => $data )); - } elseif ($type == '6' && $param1 != '') { + } elseif ($type == TaskId::DELETE_CUSTOMER_FILES && $param1 != '') { $data = array(); $data['loginname'] = $param1; $data = json_encode($data); Database::pexecute($ins_stmt, array( - 'type' => '6', + 'type' => TaskId::DELETE_CUSTOMER_FILES, 'data' => $data )); - } elseif ($type == '7' && $param1 != '' && $param2 != '') { + } elseif ($type == TaskId::DELETE_EMAIL_DATA && $param1 != '' && $param2 != '') { $data = array(); $data['loginname'] = $param1; $data['email'] = $param2; $data = json_encode($data); Database::pexecute($ins_stmt, array( - 'type' => '7', + 'type' => TaskId::DELETE_EMAIL_DATA, 'data' => $data )); - } elseif ($type == '8' && $param1 != '' && $param2 != '') { + } elseif ($type == TaskId::DELETE_FTP_DATA && $param1 != '' && $param2 != '') { $data = array(); $data['loginname'] = $param1; $data['homedir'] = $param2; $data = json_encode($data); Database::pexecute($ins_stmt, array( - 'type' => '8', + 'type' => TaskId::DELETE_FTP_DATA, 'data' => $data )); - } elseif ($type == '11' && $param1 != '' && Settings::Get('system.bind_enable') == '1' && Settings::Get('system.dns_server') == 'PowerDNS') { + } elseif ($type == TaskId::DELETE_DOMAIN_PDNS && $param1 != '' && 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['domain'] = $param1; $data = json_encode($data); Database::pexecute($ins_stmt, array( - 'type' => '11', + 'type' => TaskId::DELETE_DOMAIN_PDNS, 'data' => $data )); - } elseif ($type == '12' && $param1 != '') { + } elseif ($type == TaskId::DELETE_DOMAIN_SSL && $param1 != '') { $data = array(); $data['domain'] = $param1; $data = json_encode($data); Database::pexecute($ins_stmt, array( - 'type' => '12', + 'type' => TaskId::DELETE_DOMAIN_SSL, 'data' => $data )); - } elseif ($type == '20' && is_array($param1)) { + } elseif ($type == TaskId::CREATE_CUSTOMER_BACKUP && is_array($param1)) { $data = json_encode($param1); Database::pexecute($ins_stmt, array( - 'type' => '20', + 'type' => TaskId::CREATE_CUSTOMER_BACKUP, 'data' => $data )); } @@ -248,57 +250,23 @@ class Cronjob $row['data'] = json_decode($row['data'], true); } - // rebuilding webserver-configuration - if ($row['type'] == '1') { - $task_desc = $lng['tasks']['rebuild_webserverconfig']; - } elseif ($row['type'] == '2') { - // adding new user/ - $loginname = ''; + $task_id = $row['type']; + if (\Froxlor\Cron\TaskId::isValid($task_id)) { + $task_constname = \Froxlor\Cron\TaskId::convertToConstant($task_id); + $task_desc = isset($lng['tasks'][$task_constname]) ? $lng['tasks'][$task_constname] : $task_constname; + if (is_array($row['data'])) { - $loginname = $row['data']['loginname']; + // task includes loginname + if (isset($row['data']['loginname'])) { + $loginname = $row['data']['loginname']; + $task_desc = str_replace('%loginname%', $loginname, $task_desc); + } + // task includes domain data + if (isset($row['data']['domain'])) { + $domain = $row['data']['domain']; + $task_desc = str_replace('%domain%', $domain, $task_desc); + } } - $task_desc = $lng['tasks']['adding_customer']; - $task_desc = str_replace('%loginname%', $loginname, $task_desc); - } elseif ($row['type'] == '4') { - // rebuilding bind-configuration - $task_desc = $lng['tasks']['rebuild_bindconfig']; - } elseif ($row['type'] == '5') { - // creating ftp-user directory - $task_desc = $lng['tasks']['creating_ftpdir']; - } elseif ($row['type'] == '6') { - // deleting user-files - $loginname = ''; - if (is_array($row['data'])) { - $loginname = $row['data']['loginname']; - } - $task_desc = $lng['tasks']['deleting_customerfiles']; - $task_desc = str_replace('%loginname%', $loginname, $task_desc); - } elseif ($row['type'] == '7') { - // deleting email-account - $task_desc = $lng['tasks']['remove_emailacc_files']; - } elseif ($row['type'] == '8') { - // deleting ftp-account - $task_desc = $lng['tasks']['remove_ftpacc_files']; - } elseif ($row['type'] == '10') { - // Set FS - quota - $task_desc = $lng['tasks']['diskspace_set_quota']; - } elseif ($row['type'] == '11') { - // remove domain from pdns database if used - $task_desc = sprintf($lng['tasks']['remove_pdns_domain'], $row['data']['domain']); - } elseif ($row['type'] == '12') { - // remove domains ssl files - $task_desc = sprintf($lng['tasks']['remove_ssl_domain'], $row['data']['domain']); - } elseif ($row['type'] == '20') { - // deleting user-files - $loginname = ''; - if (is_array($row['data'])) { - $loginname = $row['data']['loginname']; - } - $task_desc = $lng['tasks']['backup_customerfiles']; - $task_desc = str_replace('%loginname%', $loginname, $task_desc); - } elseif ($row['type'] == '99') { - // re-generating of cron.d-file - $task_desc = $lng['tasks']['regenerating_crond']; } else { // unknown $task_desc = "ERROR: Unknown task type '" . $row['type'] . "'"; diff --git a/lng/czech.lng.php b/lng/czech.lng.php index 57340117..04c58dc6 100644 --- a/lng/czech.lng.php +++ b/lng/czech.lng.php @@ -954,11 +954,11 @@ $lng['update']['noupdatesavail'] = 'You already have the latest Froxlor $lng['admin']['specialsettingsforsubdomains'] = 'Apply specialsettings to all subdomains (*.example.com)'; $lng['serversettings']['specialsettingsforsubdomains']['description'] = 'If yes these custom vHost-settings will be added to all subdomains; if no subdomain-specialsettings are being removed.'; $lng['tasks']['outstanding_tasks'] = 'Outstanding cron-tasks'; -$lng['tasks']['rebuild_webserverconfig'] = 'Rebuilding webserver-configuration'; -$lng['tasks']['adding_customer'] = 'Adding new customer %loginname%'; -$lng['tasks']['rebuild_bindconfig'] = 'Rebuilding bind-configuration'; -$lng['tasks']['creating_ftpdir'] = 'Creating directory for new ftp-user'; -$lng['tasks']['deleting_customerfiles'] = 'Deleting customer-files %loginname%'; +$lng['tasks']['REBUILD_VHOST'] = 'Rebuilding webserver-configuration'; +$lng['tasks']['CREATE_HOME'] = 'Adding new customer %loginname%'; +$lng['tasks']['REBUILD_DNS'] = 'Rebuilding bind-configuration'; +$lng['tasks']['CREATE_FTP'] = 'Creating directory for new ftp-user'; +$lng['tasks']['DELETE_CUSTOMER_FILES'] = 'Deleting customer-files %loginname%'; $lng['tasks']['noneoutstanding'] = 'There are currently no outstanding tasks for Froxlor'; // ADDED IN FROXLOR 0.9.1 @@ -1524,7 +1524,7 @@ $lng['serversettings']['diskquota_enabled'] = 'Kvóta aktivována?'; $lng['serversettings']['diskquota_repquota_path']['description'] = 'Path to repquota'; $lng['serversettings']['diskquota_quotatool_path']['description'] = 'Path to quotatool'; $lng['serversettings']['diskquota_customer_partition']['description'] = 'Partition, on which the customer files are stored'; -$lng['tasks']['diskspace_set_quota'] = 'Set quota on filesystem'; +$lng['tasks']['CREATE_QUOTA'] = 'Set quota on filesystem'; $lng['error']['session_timeout'] = 'Moc nízká hodnota'; $lng['error']['session_timeout_desc'] = 'You should not set the session timeout lower than 1 minute.'; @@ -1554,7 +1554,7 @@ $lng['admin']['speciallogwarning'] = 'WARNING: By changing this setting you will // ADDED IN 0.9.28-svn2 $lng['serversettings']['vmail_maildirname']['title'] = 'Maildir name'; $lng['serversettings']['vmail_maildirname']['description'] = 'Maildir directory into user\'s account. Normally \'Maildir\', in some implementations \'.maildir\', and directly into user\'s directory if left blank.'; -$lng['tasks']['remove_emailacc_files'] = 'Delete customer e-mail data.'; +$lng['tasks']['DELETE_EMAIL_DATA'] = 'Delete customer e-mail data.'; // ADDED IN 0.9.28-svn5 $lng['error']['operationnotpermitted'] = 'Operace nepovolena!'; @@ -1683,8 +1683,8 @@ $lng['panel']['ftpdesc'] = 'FTP description'; $lng['admin']['cronsettings'] = 'Cronjob settings'; $lng['serversettings']['system_cronconfig']['title'] = 'Cron configuration file'; $lng['serversettings']['system_cronconfig']['description'] = 'Path to the cron-service configuration-file. This file will be updated regularly and automatically by froxlor.
Note: Please be sure to use the same filename as for the main froxlor cronjob (default: /etc/cron.d/froxlor)!

If you are using FreeBSD, please specify /etc/crontab here!'; -$lng['tasks']['remove_ftpacc_files'] = 'Delete customer ftp-account data.'; -$lng['tasks']['regenerating_crond'] = 'Rebuilding the cron.d-file'; +$lng['tasks']['DELETE_FTP_DATA'] = 'Delete customer ftp-account data.'; +$lng['tasks']['REBUILD_CRON'] = 'Rebuilding the cron.d-file'; $lng['serversettings']['system_crondreload']['title'] = 'Cron-daemon reload command'; $lng['serversettings']['system_crondreload']['description'] = 'Specify the command to execute in order to reload your systems cron-daemon'; $lng['admin']['integritycheck'] = 'Ověření databáze'; @@ -1889,7 +1889,7 @@ $lng['serversettings']['backupenabled']['title'] = "Povolit zálohy pro zákazn $lng['serversettings']['backupenabled']['description'] = "If activated, the customer will be able to schedule backup jobs (cron-backup) which generates an archive within his docroot (subdirectory chosable by customer)"; $lng['extras']['path_protection_label'] = 'Important'; $lng['extras']['path_protection_info'] = 'We strongly recommend protecting the given path, see "Extras" -> "Directory protection"'; -$lng['tasks']['backup_customerfiles'] = 'Backup job for customer %loginname%'; +$lng['tasks']['CREATE_CUSTOMER_BACKUP'] = 'Backup job for customer %loginname%'; $lng['error']['dns_domain_nodns'] = 'DNS pro tuto doménu je vypnuto'; $lng['error']['dns_content_empty'] = 'No content given'; @@ -2057,8 +2057,8 @@ $lng['panel']['ihave_configured'] = 'I have configured the services'; $lng['panel']['system_is_configured'] = 'System is already set as configured'; $lng['panel']['settings_before_configuration'] = 'Please be sure you adjusted the settings prior to configuring the services here'; $lng['panel']['alternative_cmdline_config'] = 'Alternatively, just run the following command as root-user in your shell to configure the services automatically'; -$lng['tasks']['remove_pdns_domain'] = 'Delete domain %s from PowerDNS database'; -$lng['tasks']['remove_ssl_domain'] = 'Delete ssl files of domain %s'; +$lng['tasks']['DELETE_DOMAIN_PDNS'] = 'Delete domain %domain% from PowerDNS database'; +$lng['tasks']['DELETE_DOMAIN_SSL'] = 'Delete ssl files of domain %domain%'; $lng['admin']['novhostcontainer'] = '

None of the IPs and ports has the "' . $lng['admin']['ipsandports']['create_vhostcontainer'] . '" option enabled, many settings here will not be available'; $lng['serversettings']['errorlog_level']['title'] = 'Error log-level'; $lng['serversettings']['errorlog_level']['description'] = 'Specify the error log level. Default is "warn" for apache-users and "error" for nginx-users.'; diff --git a/lng/dutch.lng.php b/lng/dutch.lng.php index 6198b37a..e38c1202 100644 --- a/lng/dutch.lng.php +++ b/lng/dutch.lng.php @@ -862,11 +862,11 @@ $lng['update']['noupdatesavail'] = 'U gebruikt reeds de meest recente ve $lng['admin']['specialsettingsforsubdomains'] = 'Speciale instellingen toepassen op alle subdomeinen (*.example.com)'; $lng['serversettings']['specialsettingsforsubdomains']['description'] = 'Indien "Ja" zullen deze aangepaste VHost-instellingen worden toegepast op alle subdomeinen.'; $lng['tasks']['outstanding_tasks'] = 'Uitstaande cron-taken'; -$lng['tasks']['rebuild_webserverconfig'] = 'Bezig met opnieuw opbouwen van de configuratie van de webserver'; -$lng['tasks']['adding_customer'] = 'Klant met naam %loginname% wordt toegevoegd'; -$lng['tasks']['rebuild_bindconfig'] = 'Opnieuw opbouwen bind-configuratie'; -$lng['tasks']['creating_ftpdir'] = 'Map aanmaken voor nieuwe FTP-gebruiker'; -$lng['tasks']['deleting_customerfiles'] = 'Verwijderen klantbestanden van %loginname%'; +$lng['tasks']['REBUILD_VHOST'] = 'Bezig met opnieuw opbouwen van de configuratie van de webserver'; +$lng['tasks']['CREATE_HOME'] = 'Klant met naam %loginname% wordt toegevoegd'; +$lng['tasks']['REBUILD_DNS'] = 'Opnieuw opbouwen bind-configuratie'; +$lng['tasks']['CREATE_FTP'] = 'Map aanmaken voor nieuwe FTP-gebruiker'; +$lng['tasks']['DELETE_CUSTOMER_FILES'] = 'Verwijderen klantbestanden van %loginname%'; $lng['tasks']['noneoutstanding'] = 'Er zijn op dit moment geen uitstaande taken voor Froxlor'; // ADDED IN FROXLOR 0.9.1 diff --git a/lng/english.lng.php b/lng/english.lng.php index fdbcac52..0fe92d57 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -957,11 +957,11 @@ $lng['update']['noupdatesavail'] = 'You already have the latest Froxlor $lng['admin']['specialsettingsforsubdomains'] = 'Apply specialsettings to all subdomains (*.example.com)'; $lng['serversettings']['specialsettingsforsubdomains']['description'] = 'If yes these custom vHost-settings will be added to all subdomains; if no subdomain-specialsettings are being removed.'; $lng['tasks']['outstanding_tasks'] = 'Outstanding cron-tasks'; -$lng['tasks']['rebuild_webserverconfig'] = 'Rebuilding webserver-configuration'; -$lng['tasks']['adding_customer'] = 'Adding new customer %loginname%'; -$lng['tasks']['rebuild_bindconfig'] = 'Rebuilding bind-configuration'; -$lng['tasks']['creating_ftpdir'] = 'Creating directory for new ftp-user'; -$lng['tasks']['deleting_customerfiles'] = 'Deleting customer-files %loginname%'; +$lng['tasks']['REBUILD_VHOST'] = 'Rebuilding webserver-configuration'; +$lng['tasks']['CREATE_HOME'] = 'Adding new customer %loginname%'; +$lng['tasks']['REBUILD_DNS'] = 'Rebuilding bind-configuration'; +$lng['tasks']['CREATE_FTP'] = 'Creating directory for new ftp-user'; +$lng['tasks']['DELETE_CUSTOMER_FILES'] = 'Deleting customer-files %loginname%'; $lng['tasks']['noneoutstanding'] = 'There are currently no outstanding tasks for Froxlor'; // ADDED IN FROXLOR 0.9.1 @@ -1527,7 +1527,7 @@ $lng['serversettings']['diskquota_enabled'] = 'Quota activated?'; $lng['serversettings']['diskquota_repquota_path']['description'] = 'Path to repquota'; $lng['serversettings']['diskquota_quotatool_path']['description'] = 'Path to quotatool'; $lng['serversettings']['diskquota_customer_partition']['description'] = 'Partition, on which the customer files are stored'; -$lng['tasks']['diskspace_set_quota'] = 'Set quota on filesystem'; +$lng['tasks']['CREATE_QUOTA'] = 'Set quota on filesystem'; $lng['error']['session_timeout'] = 'Value too low'; $lng['error']['session_timeout_desc'] = 'You should not set the session timeout lower than 1 minute.'; @@ -1557,7 +1557,7 @@ $lng['admin']['speciallogwarning'] = 'WARNING: By changing this setting you will // ADDED IN 0.9.28-svn2 $lng['serversettings']['vmail_maildirname']['title'] = 'Maildir name'; $lng['serversettings']['vmail_maildirname']['description'] = 'Maildir directory into user\'s account. Normally \'Maildir\', in some implementations \'.maildir\', and directly into user\'s directory if left blank.'; -$lng['tasks']['remove_emailacc_files'] = 'Delete customer e-mail data.'; +$lng['tasks']['DELETE_EMAIL_DATA'] = 'Delete customer e-mail data.'; // ADDED IN 0.9.28-svn5 $lng['error']['operationnotpermitted'] = 'Operation not permitted!'; @@ -1688,8 +1688,8 @@ $lng['panel']['ftpdesc'] = 'FTP description'; $lng['admin']['cronsettings'] = 'Cronjob settings'; $lng['serversettings']['system_cronconfig']['title'] = 'Cron configuration file'; $lng['serversettings']['system_cronconfig']['description'] = 'Path to the cron-service configuration-file. This file will be updated regularly and automatically by froxlor.
Note: Please be sure to use the same filename as for the main froxlor cronjob (default: /etc/cron.d/froxlor)!

If you are using FreeBSD, please specify /etc/crontab here!'; -$lng['tasks']['remove_ftpacc_files'] = 'Delete customer ftp-account data.'; -$lng['tasks']['regenerating_crond'] = 'Rebuilding the cron.d-file'; +$lng['tasks']['DELETE_FTP_DATA'] = 'Delete customer ftp-account data.'; +$lng['tasks']['REBUILD_CRON'] = 'Rebuilding the cron.d-file'; $lng['serversettings']['system_crondreload']['title'] = 'Cron-daemon reload command'; $lng['serversettings']['system_crondreload']['description'] = 'Specify the command to execute in order to reload your systems cron-daemon'; $lng['admin']['integritycheck'] = 'Database validation'; @@ -1894,7 +1894,7 @@ $lng['serversettings']['backupenabled']['title'] = "Enable backup for customers" $lng['serversettings']['backupenabled']['description'] = "If activated, the customer will be able to schedule backup jobs (cron-backup) which generates an archive within his docroot (subdirectory chosable by customer)"; $lng['extras']['path_protection_label'] = 'Important'; $lng['extras']['path_protection_info'] = 'We strongly recommend protecting the given path, see "Extras" -> "Directory protection"'; -$lng['tasks']['backup_customerfiles'] = 'Backup job for customer %loginname%'; +$lng['tasks']['CREATE_CUSTOMER_BACKUP'] = 'Backup job for customer %loginname%'; $lng['error']['dns_domain_nodns'] = 'DNS is not enabled for this domain'; $lng['error']['dns_content_empty'] = 'No content given'; @@ -2063,8 +2063,8 @@ $lng['panel']['ihave_configured'] = 'I have configured the services'; $lng['panel']['system_is_configured'] = 'System is already set as configured'; $lng['panel']['settings_before_configuration'] = 'Please be sure you adjusted the settings prior to configuring the services here'; $lng['panel']['alternative_cmdline_config'] = 'Alternatively, just run the following command as root-user in your shell to configure the services automatically'; -$lng['tasks']['remove_pdns_domain'] = 'Delete domain %s from PowerDNS database'; -$lng['tasks']['remove_ssl_domain'] = 'Delete ssl files of domain %s'; +$lng['tasks']['DELETE_DOMAIN_PDNS'] = 'Delete domain %domain% from PowerDNS database'; +$lng['tasks']['DELETE_DOMAIN_SSL'] = 'Delete ssl files of domain %domain%'; $lng['admin']['novhostcontainer'] = '

None of the IPs and ports has the "' . $lng['admin']['ipsandports']['create_vhostcontainer'] . '" option enabled, many settings here will not be available'; $lng['serversettings']['errorlog_level']['title'] = 'Error log-level'; $lng['serversettings']['errorlog_level']['description'] = 'Specify the error log level. Default is "warn" for apache-users and "error" for nginx-users.'; diff --git a/lng/german.lng.php b/lng/german.lng.php index a897f907..7be69d45 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -928,11 +928,11 @@ $lng['update']['noupdatesavail'] = 'Ihre Froxlor-Version ist aktuell.'; $lng['serversettings']['errorlog_level']['title'] = 'Ausführlichkeit des Fehlerprotokolls'; $lng['serversettings']['errorlog_level']['description'] = 'Steuert die Ausführlichkeit des Fehlerprotokolls. Voreinstellung ist "warn" bei Apache und "error" bei Nginx.'; diff --git a/lng/italian.lng.php b/lng/italian.lng.php index 0807cd92..24d937d3 100644 --- a/lng/italian.lng.php +++ b/lng/italian.lng.php @@ -884,11 +884,11 @@ $lng['update']['noupdatesavail'] = 'È già presente l\'ultima versione $lng['admin']['specialsettingsforsubdomains'] = 'Applica le impostazioni speciali a tutti i sottodomini (*.esempio.com)'; $lng['serversettings']['specialsettingsforsubdomains']['description'] = 'Se si queste impostazioni personalizzate dei vhost saranno aggiunte a tutti sottodomini; se no le impostazioni speciali dei sottodomini verranno rimosse.'; $lng['tasks']['outstanding_tasks'] = 'Processi Cron in sospeso'; -$lng['tasks']['rebuild_webserverconfig'] = 'Ricostruzione della configurazione del webserver'; -$lng['tasks']['adding_customer'] = 'Aggiunto il nuovo cliente %loginname%'; -$lng['tasks']['rebuild_bindconfig'] = 'Ricostruzione della configurazione di bind'; -$lng['tasks']['creating_ftpdir'] = 'Creazione delle cartelle per i nuovi utenti ftp'; -$lng['tasks']['deleting_customerfiles'] = 'Eliminazione dei file del cliente %loginname%'; +$lng['tasks']['REBUILD_VHOST'] = 'Ricostruzione della configurazione del webserver'; +$lng['tasks']['CREATE_HOME'] = 'Aggiunto il nuovo cliente %loginname%'; +$lng['tasks']['REBUILD_DNS'] = 'Ricostruzione della configurazione di bind'; +$lng['tasks']['CREATE_FTP'] = 'Creazione delle cartelle per i nuovi utenti ftp'; +$lng['tasks']['DELETE_CUSTOMER_FILES'] = 'Eliminazione dei file del cliente %loginname%'; $lng['tasks']['noneoutstanding'] = 'Attualmente non ci sono processi in sospeso per Froxlor'; // ADDED IN FROXLOR 0.9.1 @@ -1486,7 +1486,7 @@ $lng['serversettings']['diskquota_enabled'] = 'Quota attivita?'; $lng['serversettings']['diskquota_repquota_path']['description'] = 'Percorso a repquota'; $lng['serversettings']['diskquota_quotatool_path']['description'] = 'Percorso al quotatool'; $lng['serversettings']['diskquota_customer_partition']['description'] = 'Partizione, sulla quale sono salvati i dati dei clienti'; -$lng['tasks']['diskspace_set_quota'] = 'Setta quota al filesystem'; +$lng['tasks']['CREATE_QUOTA'] = 'Setta quota al filesystem'; $lng['error']['session_timeout'] = 'Valore troppo basso'; $lng['error']['session_timeout_desc'] = 'Non dovresti settare il timeout della sessione ad un valore minore di 1 minuto.'; $lng['admin']['assignedmax'] = 'Assegnato / Max'; @@ -1506,7 +1506,7 @@ $lng['admin']['delete_statistics'] = 'Elimina Statistiche'; $lng['admin']['speciallogwarning'] = 'AVVISO: Cambiando questa impostazione perderai tutte le vecchie statistiche per questo dominio. Se sei sicuro che vuoi cambiare questo digita "%s" nel campo sottostante e clicca il bottone "elimina".

'; $lng['serversettings']['vmail_maildirname']['title'] = 'nome Maildir'; $lng['serversettings']['vmail_maildirname']['description'] = 'cartella Maildir nell account utente. Normalmente \'Maildir\', in alcune implementazioni \'.maildir\', e direttamente nella cartella utente se lasciato vuoto.'; -$lng['tasks']['remove_emailacc_files'] = 'Elimina i dati di posta elettronica del cliente.'; +$lng['tasks']['DELETE_EMAIL_DATA'] = 'Elimina i dati di posta elettronica del cliente.'; $lng['error']['operationnotpermitted'] = 'Operazione non permessa!'; $lng['error']['featureisdisabled'] = 'Funzionalità %s è disabilitata. Perfavore contatta il tuo fornitore di servizi.'; $lng['serversettings']['catchall_enabled']['title'] = 'Usa Catchall'; @@ -1616,8 +1616,8 @@ $lng['admin']['cronsettings'] = 'Impostazioni Cronjob'; $lng['serversettings']['system_cronconfig']['title'] = 'File di configurazione Cron'; $lng['serversettings']['system_cronconfig']['description'] = 'Percorso al file di configurazione del servizio cron. Questo file verrà aggiornato regolarmente ed automaticamente da froxlor.
Nota: Perfavore sii sicuro di usare lo stesso nome di file come per il cronjob principale di froxlor (predefinito: /etc/cron.d/froxlor)!

Se usi FreeBSD, qui specifica: /etc/crontab!'; -$lng['tasks']['remove_ftpacc_files'] = 'Elimina i dati account-ftp del cliente.'; -$lng['tasks']['regenerating_crond'] = 'Ricostruisci il file cron.d'; +$lng['tasks']['DELETE_FTP_DATA'] = 'Elimina i dati account-ftp del cliente.'; +$lng['tasks']['REBUILD_CRON'] = 'Ricostruisci il file cron.d'; $lng['serversettings']['system_crondreload']['title'] = 'Commando per riavviare il servizio Cron'; $lng['serversettings']['system_crondreload']['description'] = 'Specifica il commando da eseguire per riavviare il servizio cron del tuo sistema'; $lng['admin']['integritycheck'] = 'Validazione Database'; diff --git a/phpunit.xml b/phpunit.xml index 94672a8c..aee8fd5b 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -30,6 +30,7 @@ tests/PhpAndFpm tests/Traffic tests/Froxlor + tests/Cron diff --git a/tests/Cron/TaskIdTest.php b/tests/Cron/TaskIdTest.php new file mode 100644 index 00000000..397ffe87 --- /dev/null +++ b/tests/Cron/TaskIdTest.php @@ -0,0 +1,84 @@ + 1, + + 'CREATE_HOME' => 2, + + 'REBUILD_DNS' => 4, + + 'CREATE_FTP' => 5, + + 'DELETE_CUSTOMER_FILES' => 6, + + 'DELETE_EMAIL_DATA' => 7, + + 'DELETE_FTP_DATA' => 8, + + 'CREATE_QUOTA' => 10, + + 'DELETE_DOMAIN_PDNS' => 11, + + 'DELETE_DOMAIN_SSL' => 12, + + 'CREATE_CUSTOMER_BACKUP' => 20, + + 'REBUILD_CRON' => 99, + ); + + public function testValidTaskId() + { + + $isId99Valid = TaskId::isValid(99); + $this->assertTrue($isId99Valid, "Task id 99 must be valid"); + + $isIdStringValid = TaskId::isValid('99'); + $this->assertTrue($isIdStringValid, "String task ids should be valid"); + + $isNegativeValid = TaskId::isValid(-1); + $this->assertFalse($isNegativeValid, "Negative task should be invalid"); + } + + public function testAcceptNewTaskId() + { + $isTESTTASKValid = TaskIdExtended::isValid(10101010); + $this->assertTrue($isTESTTASKValid); + } + + + public function testFixedTaskIdTable() + { + $isTESTTASKValid = TaskIdExtended::isValid(10101010); + $this->assertTrue($isTESTTASKValid); + } + + public function testIdMappingCorrect() { + foreach($this->fixedids as $name => $expected) { + $result = constant("\Froxlor\Cron\TaskId::$name"); + $this->assertEquals( $expected, $result, "Task $name has bad mapping"); + } + } + + public function testConvertToConstant() { + foreach($this->fixedids as $name => $taskid) { + $result = TaskId::convertToConstant($taskid); + $this->assertEquals( $name, $result, "Task $name has bad mapping from id to name"); + } + + $unknownIDResult = TaskId::isValid(10101010); + $this->assertFalse($unknownIDResult); + } +} + +class TaskIdExtended extends TaskId { + const TESTTASK = 10101010; +} From 06849133a835faeb7b498637da58ce4a1e77a443 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 21 Jan 2022 10:39:32 +0100 Subject: [PATCH 311/319] modernize parameters of Cronjob::inserttask() Signed-off-by: Michael Kaufmann --- lib/Froxlor/System/Cronjob.php | 48 ++++++++++++++++------------------ 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/lib/Froxlor/System/Cronjob.php b/lib/Froxlor/System/Cronjob.php index 030b555b..71f86e81 100644 --- a/lib/Froxlor/System/Cronjob.php +++ b/lib/Froxlor/System/Cronjob.php @@ -95,17 +95,13 @@ class Cronjob * @param * int Type of task * @param - * string Parameter 1 - * @param - * string Parameter 2 - * @param - * string Parameter 3 + * string Parameter (possible to pass multiple times) + * * @author Florian Lippert * @author Froxlor team */ - public static function inserttask($type, $param1 = '', $param2 = '', $param3 = '', $param4 = '') + public static function inserttask($type, ...$params) { - // prepare the insert-statement $ins_stmt = Database::prepare(" INSERT INTO `" . TABLE_PANEL_TASKS . "` SET `type` = :type, `data` = :data @@ -134,62 +130,62 @@ class Cronjob 'type' => $type, 'data' => '' )); - } elseif ($type == TaskId::CREATE_HOME && $param1 != '' && $param2 != '' && $param3 != '' && ($param4 == 0 || $param4 == 1)) { + } elseif ($type == TaskId::CREATE_HOME && count($params) == 4 && $params[0] != '' && $params[1] != '' && $params[2] != '' && ($params[3] == 0 || $params[3] == 1)) { $data = array(); - $data['loginname'] = $param1; - $data['uid'] = $param2; - $data['gid'] = $param3; - $data['store_defaultindex'] = $param4; + $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( 'type' => TaskId::CREATE_HOME, 'data' => $data )); - } elseif ($type == TaskId::DELETE_CUSTOMER_FILES && $param1 != '') { + } elseif ($type == TaskId::DELETE_CUSTOMER_FILES && isset($params[0]) && $params[0] != '') { $data = array(); - $data['loginname'] = $param1; + $data['loginname'] = $params[0]; $data = json_encode($data); Database::pexecute($ins_stmt, array( 'type' => TaskId::DELETE_CUSTOMER_FILES, 'data' => $data )); - } elseif ($type == TaskId::DELETE_EMAIL_DATA && $param1 != '' && $param2 != '') { + } elseif ($type == TaskId::DELETE_EMAIL_DATA && count($params) == 2 && $params[0] != '' && $params[1] != '') { $data = array(); - $data['loginname'] = $param1; - $data['email'] = $param2; + $data['loginname'] = $params[0]; + $data['email'] = $params[1]; $data = json_encode($data); Database::pexecute($ins_stmt, array( 'type' => TaskId::DELETE_EMAIL_DATA, 'data' => $data )); - } elseif ($type == TaskId::DELETE_FTP_DATA && $param1 != '' && $param2 != '') { + } elseif ($type == TaskId::DELETE_FTP_DATA && count($params) == 2 && $params[0] != '' && $params[1] != '') { $data = array(); - $data['loginname'] = $param1; - $data['homedir'] = $param2; + $data['loginname'] = $params[0]; + $data['homedir'] = $params[1]; $data = json_encode($data); Database::pexecute($ins_stmt, array( 'type' => TaskId::DELETE_FTP_DATA, 'data' => $data )); - } elseif ($type == TaskId::DELETE_DOMAIN_PDNS && $param1 != '' && Settings::Get('system.bind_enable') == '1' && Settings::Get('system.dns_server') == 'PowerDNS') { + } 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['domain'] = $param1; + $data['domain'] = $params[0]; $data = json_encode($data); Database::pexecute($ins_stmt, array( 'type' => TaskId::DELETE_DOMAIN_PDNS, 'data' => $data )); - } elseif ($type == TaskId::DELETE_DOMAIN_SSL && $param1 != '') { + } elseif ($type == TaskId::DELETE_DOMAIN_SSL && isset($params[0]) && $params[0] != '') { $data = array(); - $data['domain'] = $param1; + $data['domain'] = $params[0]; $data = json_encode($data); Database::pexecute($ins_stmt, array( 'type' => TaskId::DELETE_DOMAIN_SSL, 'data' => $data )); - } elseif ($type == TaskId::CREATE_CUSTOMER_BACKUP && is_array($param1)) { - $data = json_encode($param1); + } elseif ($type == TaskId::CREATE_CUSTOMER_BACKUP && isset($params[0]) && is_array($params[0])) { + $data = json_encode($params[0]); Database::pexecute($ins_stmt, array( 'type' => TaskId::CREATE_CUSTOMER_BACKUP, 'data' => $data From 5ab49e3f5093b9bac6a8a35741cfd4a725f39b97 Mon Sep 17 00:00:00 2001 From: Manuel Date: Fri, 21 Jan 2022 12:25:14 +0100 Subject: [PATCH 312/319] Call PHP-FPM only when file exists (#1006) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added `` to load only PHP files that exists. This is to prevent `File not found` error from PHP-FPM and let Apache handle the error output. It removes also unnecessary PHP-FPM calls and `AH01071: Got error ‘Primary script unknown` in PHP error log. Usually you can find the error whenever someone goes fishing for paths like wp-login.php. The `` directive is only available in Apache 2.4+ and not 2.2 or earlier. --- lib/Froxlor/Cron/Http/ApacheFcgi.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Froxlor/Cron/Http/ApacheFcgi.php b/lib/Froxlor/Cron/Http/ApacheFcgi.php index 1582144a..bc92455d 100644 --- a/lib/Froxlor/Cron/Http/ApacheFcgi.php +++ b/lib/Froxlor/Cron/Http/ApacheFcgi.php @@ -56,7 +56,9 @@ class ApacheFcgi extends Apache // start block, cut off last pipe and close block $filesmatch = '(' . str_replace(".", "\.", substr($filesmatch, 0, - 1)) . ')'; $php_options_text .= ' ' . "\n"; - $php_options_text .= ' SetHandler proxy:unix:' . $domain['fpm_socket'] . '|fcgi://localhost' . "\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']); From 7c80dc3d1d62410eb96ba745d1063df305fc099d Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 21 Jan 2022 16:02:21 +0100 Subject: [PATCH 313/319] add script for php-session cleanup Signed-off-by: Michael Kaufmann --- install/scripts/php-sessionclean.php | 31 ++++++ .../Cli/Action/PhpSessioncleanAction.php | 100 ++++++++++++++++++ lib/Froxlor/Cli/PhpSessioncleanCmd.php | 64 +++++++++++ 3 files changed, 195 insertions(+) create mode 100755 install/scripts/php-sessionclean.php create mode 100644 lib/Froxlor/Cli/Action/PhpSessioncleanAction.php create mode 100644 lib/Froxlor/Cli/PhpSessioncleanCmd.php diff --git a/install/scripts/php-sessionclean.php b/install/scripts/php-sessionclean.php new file mode 100755 index 00000000..41f633db --- /dev/null +++ b/install/scripts/php-sessionclean.php @@ -0,0 +1,31 @@ +#!/usr/bin/php + (2018-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Cron + * + */ + +// Check if we're in the CLI +if (@php_sapi_name() !== 'cli') { + die('This script will only work in the shell.'); +} + +require dirname(dirname(__DIR__)) . '/vendor/autoload.php'; + +// give control to command line handler +try { + \Froxlor\Cli\PhpSessioncleanCmd::processParameters($argc, $argv); +} catch (Exception $e) { + \Froxlor\Cli\PhpSessioncleanCmd::printerr($e->getMessage()); +} diff --git a/lib/Froxlor/Cli/Action/PhpSessioncleanAction.php b/lib/Froxlor/Cli/Action/PhpSessioncleanAction.php new file mode 100644 index 00000000..9ad09a15 --- /dev/null +++ b/lib/Froxlor/Cli/Action/PhpSessioncleanAction.php @@ -0,0 +1,100 @@ +validate(); + + if ((int) Settings::Get('phpfpm.enabled') == 1) { + if (isset($this->_args["max-lifetime"]) && is_numeric($this->_args["max-lifetime"]) && $this->_args["max-lifetime"] > 0) { + $this->cleanSessionfiles((int)$this->_args["max-lifetime"]); + } else { + // use default max-lifetime value + $this->cleanSessionfiles(); + } + } + } + + /** + * validates the parsed command line parameters + * + * @throws \Exception + */ + private function validate() + { + global $lng; + + $this->checkConfigParam(true); + $this->parseConfig(); + + require FROXLOR_INSTALL_DIR . '/lib/tables.inc.php'; + } + + private function cleanSessionfiles(int $maxlifetime = 1440) + { + // store paths to clean up + $paths_to_clean = []; + // 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)) { + $poolfiles = glob(\Froxlor\FileDir::makeCorrectFile($fpmd['config_dir'] . '/*.conf')); + foreach ($poolfiles as $cf) { + $contents = file_get_contents($cf); + $pattern = preg_quote('session.save_path', '/'); + $pattern = "/" . $pattern . ".+?\=(.*)/"; + if (preg_match_all($pattern, $contents, $matches)) { + $paths_to_clean[] = \Froxlor\FileDir::makeCorrectDir(trim($matches[1][0])); + } + } + } + + // every path is just needed once + $paths_to_clean = array_unique($paths_to_clean); + + if (count($paths_to_clean) > 0) { + foreach ($paths_to_clean as $ptc) { + // find all files older then maxlifetime and delete them + \Froxlor\FileDir::safe_exec("find -O3 \"" . $ptc . "\" -ignore_readdir_race -depth -mindepth 1 -name 'sess_*' -type f -cmin \"+" . $maxlifetime . "\" -delete"); + } + } + } + private function parseConfig() + { + define('FROXLOR_INSTALL_DIR', $this->_args['froxlor-dir']); + if (!class_exists('\\Froxlor\\Database\\Database')) { + throw new \Exception("Could not find froxlor's Database class. Is froxlor really installed to '" . FROXLOR_INSTALL_DIR . "'?"); + } + if (!file_exists(FROXLOR_INSTALL_DIR . '/lib/userdata.inc.php')) { + throw new \Exception("Could not find froxlor's userdata.inc.php file. You should use this script only with a fully installed and setup froxlor system."); + } + } + + private function checkConfigParam($needed = false) + { + if ($needed) { + if (!isset($this->_args["froxlor-dir"])) { + $this->_args["froxlor-dir"] = \Froxlor\Froxlor::getInstallDir(); + } elseif (!is_dir($this->_args["froxlor-dir"])) { + throw new \Exception("Given --froxlor-dir parameter is not a directory"); + } elseif (!file_exists($this->_args["froxlor-dir"])) { + throw new \Exception("Given froxlor directory cannot be found ('" . $this->_args["froxlor-dir"] . "')"); + } elseif (!is_readable($this->_args["froxlor-dir"])) { + throw new \Exception("Given froxlor directory cannot be read ('" . $this->_args["froxlor-dir"] . "')"); + } + } + } +} diff --git a/lib/Froxlor/Cli/PhpSessioncleanCmd.php b/lib/Froxlor/Cli/PhpSessioncleanCmd.php new file mode 100644 index 00000000..4d83e7c3 --- /dev/null +++ b/lib/Froxlor/Cli/PhpSessioncleanCmd.php @@ -0,0 +1,64 @@ + (2018-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Cron + * + */ +class PhpSessioncleanCmd extends CmdLineHandler +{ + + /** + * list of valid switches + * + * @var array + */ + public static $switches = array( + 'h' + ); + + /** + * list of valid parameters + * + * @var array + */ + public static $params = array( + 'froxlor-dir', + 'max-lifetime', + 'help' + ); + + public static $action_class = '\\Froxlor\\Cli\\Action\\PhpSessioncleanAction'; + + public static function printHelp() + { + self::println(""); + self::println("Help / command line parameters:"); + self::println(""); + // commands + self::println("--froxlor-dir\t\tpath to froxlor installation"); + self::println("\t\t\tExample: --froxlor-dir=/var/www/froxlor/"); + self::println(""); + self::println("--max-lifetime\t\tThe number of seconds after which data will be seen as 'garbage' and potentially cleaned up. Defaults to '1440'"); + self::println("\t\t\tExample: --max-lifetime=2000"); + self::println(""); + self::println("--help\t\t\tshow help screen (this)"); + self::println(""); + // switches + self::println("-h\t\t\tsame as --help"); + self::println(""); + + die(); // end of execution + } +} From 0a38d1ab5f99c8ad9e3983300342c29ab9a0f30b Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 21 Jan 2022 17:02:35 +0100 Subject: [PATCH 314/319] add workflow to automatically trigger api-docs generation in Froxlor/Documentation Signed-off-by: Michael Kaufmann --- .github/workflows/build-apidocs.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/workflows/build-apidocs.yml diff --git a/.github/workflows/build-apidocs.yml b/.github/workflows/build-apidocs.yml new file mode 100644 index 00000000..0e6e9df7 --- /dev/null +++ b/.github/workflows/build-apidocs.yml @@ -0,0 +1,14 @@ +name: build-docs + +on: + release: + types: [published] + +jobs: + build_docs: + runs-on: ubuntu-latest + steps: + - env: + GITHUB_TOKEN: ${{ secrets.ORG_GITHUB_TOKEN }} + run: | + gh workflow run --repo Froxlor/Documentation build-docs -f ref=${{github.ref_name}} From 6fdf2636fca172f5a483c817ef7c8e7fcf0d2a4c Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Tue, 25 Jan 2022 14:54:52 +0100 Subject: [PATCH 315/319] update docs url for api-documentation Signed-off-by: Michael Kaufmann --- actions/admin/settings/100.panel.php | 2 +- lib/navigation/00.froxlor.main.php | 6 ++++-- lng/czech.lng.php | 2 +- lng/english.lng.php | 2 +- lng/german.lng.php | 2 +- templates/Sparkle/header.tpl | 2 +- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/actions/admin/settings/100.panel.php b/actions/admin/settings/100.panel.php index e7a248cb..7f8cc794 100644 --- a/actions/admin/settings/100.panel.php +++ b/actions/admin/settings/100.panel.php @@ -249,7 +249,7 @@ return array( '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['menue']['logger']['logger'], + '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", diff --git a/lib/navigation/00.froxlor.main.php b/lib/navigation/00.froxlor.main.php index 241d048f..2eec35a1 100644 --- a/lib/navigation/00.froxlor.main.php +++ b/lib/navigation/00.froxlor.main.php @@ -44,7 +44,8 @@ return array( 'show_element' => (\Froxlor\Settings::Get('api.enabled') == true) ), array( - 'url' => 'https://api.froxlor.org/doc/?v='.\Froxlor\Froxlor::getVersion(), + 'url' => 'https://docs.froxlor.org/apiguide/index.html', + 'new_window' => true, 'label' => $lng['menue']['main']['apihelp'], 'show_element' => (\Froxlor\Settings::Get('api.enabled') == true) ), @@ -195,7 +196,8 @@ return array( 'show_element' => (\Froxlor\Settings::Get('api.enabled') == true) ), array( - 'url' => 'https://api.froxlor.org/doc/?v='.\Froxlor\Froxlor::getVersion(), + 'url' => 'https://docs.froxlor.org/apiguide/index.html', + 'new_window' => true, 'label' => $lng['menue']['main']['apihelp'], 'show_element' => (\Froxlor\Settings::Get('api.enabled') == true) ), diff --git a/lng/czech.lng.php b/lng/czech.lng.php index 04c58dc6..8bfecbd7 100644 --- a/lng/czech.lng.php +++ b/lng/czech.lng.php @@ -2032,7 +2032,7 @@ $lng['apikeys']['allowed_from_help'] = 'Comma separated list of ip addresses. De $lng['apikeys']['valid_until'] = 'Platné do'; $lng['apikeys']['valid_until_help'] = 'Date until valid, format YYYY-MM-DD'; $lng['serversettings']['enable_api']['title'] = 'Enable external API usage'; -$lng['serversettings']['enable_api']['description'] = 'In order to use the froxlor API you need to activate this option. For more detailed information see https://api.froxlor.org/'; +$lng['serversettings']['enable_api']['description'] = 'In order to use the froxlor API you need to activate this option. For more detailed information see https://docs.froxlor.org/'; $lng['serversettings']['dhparams_file']['title'] = 'DHParams file (Diffie–Hellman key exchange)'; $lng['serversettings']['dhparams_file']['description'] = 'If a dhparams.pem file is specified here it will be included in the webserver configuration. Leave empty to disable.
Example: /etc/apache2/ssl/dhparams.pem

If the file does not exist, it will be created automatically with the following command: openssl dhparam -out /etc/apache2/ssl/dhparams.pem 4096. It is recommended to create the file prior to specifying it here as the creation takes quite a while and blocks the cronjob.'; $lng['2fa']['2fa'] = '2FA možnosti'; diff --git a/lng/english.lng.php b/lng/english.lng.php index 0fe92d57..43aa2863 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -2038,7 +2038,7 @@ $lng['apikeys']['allowed_from_help'] = 'Comma separated list of ip addresses. De $lng['apikeys']['valid_until'] = 'Valid until'; $lng['apikeys']['valid_until_help'] = 'Date until valid, format YYYY-MM-DD'; $lng['serversettings']['enable_api']['title'] = 'Enable external API usage'; -$lng['serversettings']['enable_api']['description'] = 'In order to use the froxlor API you need to activate this option. For more detailed information see https://api.froxlor.org/'; +$lng['serversettings']['enable_api']['description'] = 'In order to use the froxlor API you need to activate this option. For more detailed information see https://docs.froxlor.org/'; $lng['serversettings']['dhparams_file']['title'] = 'DHParams file (Diffie–Hellman key exchange)'; $lng['serversettings']['dhparams_file']['description'] = 'If a dhparams.pem file is specified here it will be included in the webserver configuration. Leave empty to disable.
Example: /etc/ssl/webserver/dhparams.pem

If the file does not exist, it will be created automatically with the following command: openssl dhparam -out /etc/ssl/webserver/dhparams.pem 4096. It is recommended to create the file prior to specifying it here as the creation takes quite a while and blocks the cronjob.'; $lng['2fa']['2fa'] = '2FA options'; diff --git a/lng/german.lng.php b/lng/german.lng.php index 7be69d45..4f267204 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -1684,7 +1684,7 @@ $lng['apikeys']['allowed_from_help'] = 'Komma getrennte Liste von IPs. Standard $lng['apikeys']['valid_until'] = 'Gültig bis'; $lng['apikeys']['valid_until_help'] = 'Datum Gültigkeitsende, Format JJJJ-MM-TT'; $lng['serversettings']['enable_api']['title'] = 'Aktiviere externe API Nutzung'; -$lng['serversettings']['enable_api']['description'] = 'Um die froxlor API nutzen zu können, muss diese Option aktiviert sein. Für detaillierte Informationen siehe https://api.froxlor.org/'; +$lng['serversettings']['enable_api']['description'] = 'Um die froxlor API nutzen zu können, muss diese Option aktiviert sein. Für detaillierte Informationen siehe https://docs.froxlor.org/'; $lng['serversettings']['dhparams_file']['title'] = 'DHParams Datei (Diffie–Hellman key exchange)'; $lng['serversettings']['dhparams_file']['description'] = 'Wird eine dhparams.pem Datei hier angegeben, wir sie in die Webserver Konfiguration mit eingefügt.
Beispiel: /etc/ssl/webserver/dhparams.pem

Existiert die Datei nicht, wird sie wie folgt erstellt: openssl dhparam -out /etc/ssl/webserver/dhparams.pem 4096. Es wird empfohlen die Datei zu erstellen, bevor sie hier angegeben wird, da die Erstellung längere Zeit in Anspruch nimmt und den Cronjob blockiert.'; $lng['2fa']['2fa'] = '2FA Optionen'; diff --git a/templates/Sparkle/header.tpl b/templates/Sparkle/header.tpl index 3898bba1..f8271d25 100644 --- a/templates/Sparkle/header.tpl +++ b/templates/Sparkle/header.tpl @@ -63,7 +63,7 @@

  • {$lng['menue']['main']['apikeys']}
  • -
  • {$lng['menue']['main']['apihelp']}
  • +
  • {$lng['menue']['main']['apihelp']}
  • From 61dfeb947fff922219817b83e18a1cae19d23b35 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Tue, 25 Jan 2022 15:47:37 +0100 Subject: [PATCH 316/319] fix incorrect parameter type for mkdir() and chmod() Signed-off-by: Michael Kaufmann --- lib/Froxlor/Settings/Store.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/Froxlor/Settings/Store.php b/lib/Froxlor/Settings/Store.php index d282947c..d642de1c 100644 --- a/lib/Froxlor/Settings/Store.php +++ b/lib/Froxlor/Settings/Store.php @@ -2,6 +2,7 @@ namespace Froxlor\Settings; use Froxlor\Database\Database; +use Froxlor\FileDir; use Froxlor\Settings; class Store @@ -373,20 +374,21 @@ class Store 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); // New file? if (isset($_FILES[$fieldname]) && $_FILES[$fieldname]['tmp_name']) { // Make sure upload directory exists - if (!is_dir($path) && !mkdir($path, '0775')) { + 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')) { + 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'])) { From 9ec76c9fd622c8595492e2bc4b3c65fd5d84bf63 Mon Sep 17 00:00:00 2001 From: Kris Date: Wed, 26 Jan 2022 14:10:08 +0100 Subject: [PATCH 317/319] Improve composer.json syntax (#1008) * Improve composer.json syntax * Run composer upgrade with PHP 7.4 --- composer.json | 3 +- composer.lock | 615 +++++++++++++++++++++++++++++--------------------- 2 files changed, 361 insertions(+), 257 deletions(-) diff --git a/composer.json b/composer.json index 82326ce4..b1e6f0b1 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "docs": "https://github.com/Froxlor/Froxlor/wiki" }, "require": { - "php": ">=7.1", + "php": "^7.1 || ^8.0", "ext-session": "*", "ext-ctype": "*", "ext-pdo": "*", @@ -52,7 +52,6 @@ }, "require-dev": { "phpunit/phpunit": "^9", - "php": ">=7.3", "ext-pcntl": "*", "phpcompatibility/php-compatibility": "*", "squizlabs/php_codesniffer": "*", diff --git a/composer.lock b/composer.lock index 364abc0b..e026863c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "177d1e610535325c5fc0fec6ccd0f0c3", + "content-hash": "85144894a3d797cd463442147120549f", "packages": [ { "name": "froxlor/idna-convert-legacy", @@ -64,16 +64,16 @@ }, { "name": "monolog/monolog", - "version": "1.26.0", + "version": "1.26.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "2209ddd84e7ef1256b7af205d0717fb62cfc9c33" + "reference": "c6b00f05152ae2c9b04a448f99c7590beb6042f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/2209ddd84e7ef1256b7af205d0717fb62cfc9c33", - "reference": "2209ddd84e7ef1256b7af205d0717fb62cfc9c33", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/c6b00f05152ae2c9b04a448f99c7590beb6042f5", + "reference": "c6b00f05152ae2c9b04a448f99c7590beb6042f5", "shasum": "" }, "require": { @@ -134,7 +134,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/1.26.0" + "source": "https://github.com/Seldaek/monolog/tree/1.26.1" }, "funding": [ { @@ -146,20 +146,20 @@ "type": "tidelift" } ], - "time": "2020-12-14T12:56:38+00:00" + "time": "2021-05-28T08:32:12+00:00" }, { "name": "phpmailer/phpmailer", - "version": "v6.5.0", + "version": "v6.5.3", "source": { "type": "git", "url": "https://github.com/PHPMailer/PHPMailer.git", - "reference": "a5b5c43e50b7fba655f793ad27303cd74c57363c" + "reference": "baeb7cde6b60b1286912690ab0693c7789a31e71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a5b5c43e50b7fba655f793ad27303cd74c57363c", - "reference": "a5b5c43e50b7fba655f793ad27303cd74c57363c", + "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/baeb7cde6b60b1286912690ab0693c7789a31e71", + "reference": "baeb7cde6b60b1286912690ab0693c7789a31e71", "shasum": "" }, "require": { @@ -171,10 +171,12 @@ "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", "doctrine/annotations": "^1.2", + "php-parallel-lint/php-console-highlighter": "^0.5.0", + "php-parallel-lint/php-parallel-lint": "^1.3", "phpcompatibility/php-compatibility": "^9.3.5", "roave/security-advisories": "dev-latest", - "squizlabs/php_codesniffer": "^3.5.6", - "yoast/phpunit-polyfills": "^0.2.0" + "squizlabs/php_codesniffer": "^3.6.0", + "yoast/phpunit-polyfills": "^1.0.0" }, "suggest": { "ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses", @@ -214,7 +216,7 @@ "description": "PHPMailer is a full-featured email creation and transfer class for PHP", "support": { "issues": "https://github.com/PHPMailer/PHPMailer/issues", - "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.5.0" + "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.5.3" }, "funding": [ { @@ -222,7 +224,7 @@ "type": "github" } ], - "time": "2021-06-16T14:33:43+00:00" + "time": "2021-11-25T16:34:11+00:00" }, { "name": "psr/log", @@ -276,24 +278,29 @@ }, { "name": "robthree/twofactorauth", - "version": "1.7.0", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/RobThree/TwoFactorAuth.git", - "reference": "37983bf675c5baca09d19d6705170489d0df0002" + "reference": "5afcb45282f1c75562a48d479ecd1732c9bdb11b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/37983bf675c5baca09d19d6705170489d0df0002", - "reference": "37983bf675c5baca09d19d6705170489d0df0002", + "url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/5afcb45282f1c75562a48d479ecd1732c9bdb11b", + "reference": "5afcb45282f1c75562a48d479ecd1732c9bdb11b", "shasum": "" }, "require": { "php": ">=5.6.0" }, "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.2", "phpunit/phpunit": "@stable" }, + "suggest": { + "bacon/bacon-qr-code": "Needed for BaconQrCodeProvider provider", + "endroid/qr-code": "Needed for EndroidQrCodeProvider" + }, "type": "library", "autoload": { "psr-4": { @@ -327,32 +334,45 @@ "issues": "https://github.com/RobThree/TwoFactorAuth/issues", "source": "https://github.com/RobThree/TwoFactorAuth" }, - "time": "2020-01-02T19:56:46+00:00" + "funding": [ + { + "url": "https://paypal.me/robiii", + "type": "custom" + }, + { + "url": "https://github.com/RobThree", + "type": "github" + } + ], + "time": "2021-10-20T12:19:55+00:00" }, { "name": "symfony/polyfill-iconv", - "version": "v1.20.0", + "version": "v1.24.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-iconv.git", - "reference": "c536646fdb4f29104dd26effc2fdcb9a5b085024" + "reference": "f1aed619e28cb077fc83fac8c4c0383578356e40" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/c536646fdb4f29104dd26effc2fdcb9a5b085024", - "reference": "c536646fdb4f29104dd26effc2fdcb9a5b085024", + "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/f1aed619e28cb077fc83fac8c4c0383578356e40", + "reference": "f1aed619e28cb077fc83fac8c4c0383578356e40", "shasum": "" }, "require": { "php": ">=7.1" }, + "provide": { + "ext-iconv": "*" + }, "suggest": { "ext-iconv": "For best performance" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.20-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -391,7 +411,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-iconv/tree/v1.20.0" + "source": "https://github.com/symfony/polyfill-iconv/tree/v1.24.0" }, "funding": [ { @@ -407,20 +427,20 @@ "type": "tidelift" } ], - "time": "2020-10-23T14:02:19+00:00" + "time": "2022-01-04T09:04:05+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.20.0", + "version": "v1.24.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "c7cf3f858ec7d70b89559d6e6eb1f7c2517d479c" + "reference": "81b86b50cf841a64252b439e738e97f4a34e2783" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/c7cf3f858ec7d70b89559d6e6eb1f7c2517d479c", - "reference": "c7cf3f858ec7d70b89559d6e6eb1f7c2517d479c", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783", + "reference": "81b86b50cf841a64252b439e738e97f4a34e2783", "shasum": "" }, "require": { @@ -432,7 +452,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.20-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -472,7 +492,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.20.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.24.0" }, "funding": [ { @@ -488,20 +508,20 @@ "type": "tidelift" } ], - "time": "2020-10-23T14:02:19+00:00" + "time": "2021-11-23T21:10:46+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.20.0", + "version": "v1.24.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "727d1096295d807c309fb01a851577302394c897" + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/727d1096295d807c309fb01a851577302394c897", - "reference": "727d1096295d807c309fb01a851577302394c897", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8", + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8", "shasum": "" }, "require": { @@ -513,7 +533,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.20-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -556,7 +576,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.20.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.24.0" }, "funding": [ { @@ -572,32 +592,35 @@ "type": "tidelift" } ], - "time": "2020-10-23T14:02:19+00:00" + "time": "2021-02-19T12:13:01+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.20.0", + "version": "v1.24.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "39d483bdf39be819deabf04ec872eb0b2410b531" + "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/39d483bdf39be819deabf04ec872eb0b2410b531", - "reference": "39d483bdf39be819deabf04ec872eb0b2410b531", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825", + "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825", "shasum": "" }, "require": { "php": ">=7.1" }, + "provide": { + "ext-mbstring": "*" + }, "suggest": { "ext-mbstring": "For best performance" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.20-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -636,7 +659,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.20.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.24.0" }, "funding": [ { @@ -652,20 +675,20 @@ "type": "tidelift" } ], - "time": "2020-10-23T14:02:19+00:00" + "time": "2021-11-30T18:21:41+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.20.0", + "version": "v1.24.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "cede45fcdfabdd6043b3592e83678e42ec69e930" + "reference": "9a142215a36a3888e30d0a9eeea9766764e96976" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/cede45fcdfabdd6043b3592e83678e42ec69e930", - "reference": "cede45fcdfabdd6043b3592e83678e42ec69e930", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976", + "reference": "9a142215a36a3888e30d0a9eeea9766764e96976", "shasum": "" }, "require": { @@ -674,7 +697,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.20-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -712,7 +735,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.20.0" + "source": "https://github.com/symfony/polyfill-php72/tree/v1.24.0" }, "funding": [ { @@ -728,25 +751,25 @@ "type": "tidelift" } ], - "time": "2020-10-23T14:02:19+00:00" + "time": "2021-05-27T09:17:38+00:00" }, { "name": "voku/anti-xss", - "version": "4.1.31", + "version": "4.1.35", "source": { "type": "git", "url": "https://github.com/voku/anti-xss.git", - "reference": "22dea9be8dbffa466995ea87a12da5f3bce874bb" + "reference": "4d7ec2816cd6eeebb7d5abbde8b0349f66709496" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/voku/anti-xss/zipball/22dea9be8dbffa466995ea87a12da5f3bce874bb", - "reference": "22dea9be8dbffa466995ea87a12da5f3bce874bb", + "url": "https://api.github.com/repos/voku/anti-xss/zipball/4d7ec2816cd6eeebb7d5abbde8b0349f66709496", + "reference": "4d7ec2816cd6eeebb7d5abbde8b0349f66709496", "shasum": "" }, "require": { "php": ">=7.0.0", - "voku/portable-utf8": "~5.4.51" + "voku/portable-utf8": "~6.0.0" }, "require-dev": { "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" @@ -774,7 +797,7 @@ { "name": "Lars Moelleken", "email": "lars@moelleken.org", - "homepage": "http://www.moelleken.org/" + "homepage": "https://www.moelleken.org/" } ], "description": "anti xss-library", @@ -787,7 +810,7 @@ ], "support": { "issues": "https://github.com/voku/anti-xss/issues", - "source": "https://github.com/voku/anti-xss/tree/4.1.31" + "source": "https://github.com/voku/anti-xss/tree/4.1.35" }, "funding": [ { @@ -811,20 +834,20 @@ "type": "tidelift" } ], - "time": "2020-12-02T02:10:30+00:00" + "time": "2021-12-08T15:20:33+00:00" }, { "name": "voku/portable-ascii", - "version": "1.5.6", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/voku/portable-ascii.git", - "reference": "80953678b19901e5165c56752d087fc11526017c" + "reference": "9bd89e83cecdf8c37b64909454249eaed98b2c89" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/voku/portable-ascii/zipball/80953678b19901e5165c56752d087fc11526017c", - "reference": "80953678b19901e5165c56752d087fc11526017c", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/9bd89e83cecdf8c37b64909454249eaed98b2c89", + "reference": "9bd89e83cecdf8c37b64909454249eaed98b2c89", "shasum": "" }, "require": { @@ -861,7 +884,7 @@ ], "support": { "issues": "https://github.com/voku/portable-ascii/issues", - "source": "https://github.com/voku/portable-ascii/tree/1.5.6" + "source": "https://github.com/voku/portable-ascii/tree/2.0.0" }, "funding": [ { @@ -885,20 +908,20 @@ "type": "tidelift" } ], - "time": "2020-11-12T00:07:28+00:00" + "time": "2022-01-24T18:59:03+00:00" }, { "name": "voku/portable-utf8", - "version": "5.4.51", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/voku/portable-utf8.git", - "reference": "578f5266725dc9880483d24ad0cfb39f8ce170f7" + "reference": "17fc93430f64873ba7812893deb24e7644d31b71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/voku/portable-utf8/zipball/578f5266725dc9880483d24ad0cfb39f8ce170f7", - "reference": "578f5266725dc9880483d24ad0cfb39f8ce170f7", + "url": "https://api.github.com/repos/voku/portable-utf8/zipball/17fc93430f64873ba7812893deb24e7644d31b71", + "reference": "17fc93430f64873ba7812893deb24e7644d31b71", "shasum": "" }, "require": { @@ -908,7 +931,7 @@ "symfony/polyfill-intl-normalizer": "~1.0", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php72": "~1.0", - "voku/portable-ascii": "~1.5.6" + "voku/portable-ascii": "~2.0.0" }, "require-dev": { "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" @@ -960,7 +983,7 @@ ], "support": { "issues": "https://github.com/voku/portable-utf8/issues", - "source": "https://github.com/voku/portable-utf8/tree/5.4.51" + "source": "https://github.com/voku/portable-utf8/tree/6.0.2" }, "funding": [ { @@ -984,33 +1007,106 @@ "type": "tidelift" } ], - "time": "2020-12-02T01:58:49+00:00" + "time": "2022-01-24T19:06:57+00:00" } ], "packages-dev": [ { - "name": "composer/xdebug-handler", - "version": "2.0.1", + "name": "composer/pcre", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "964adcdd3a28bf9ed5d9ac6450064e0d71ed7496" + "url": "https://github.com/composer/pcre.git", + "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/964adcdd3a28bf9ed5d9ac6450064e0d71ed7496", - "reference": "964adcdd3a28bf9ed5d9ac6450064e0d71ed7496", + "url": "https://api.github.com/repos/composer/pcre/zipball/67a32d7d6f9f560b726ab25a061b38ff3a80c560", + "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0 || ^8.0", - "psr/log": "^1.0" + "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^0.12.55", + "phpstan/phpstan": "^1.3", + "phpstan/phpstan-strict-rules": "^1.1", "symfony/phpunit-bridge": "^4.2 || ^5" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/1.0.1" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-01-21T20:24:37+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "0c1a3925ec58a4ec98e992b9c7d171e9e184be0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/0c1a3925ec58a4ec98e992b9c7d171e9e184be0a", + "reference": "0c1a3925ec58a4ec98e992b9c7d171e9e184be0a", + "shasum": "" + }, + "require": { + "composer/pcre": "^1", + "php": "^5.3.2 || ^7.0 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0" + }, + "type": "library", "autoload": { "psr-4": { "Composer\\XdebugHandler\\": "src" @@ -1034,7 +1130,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/2.0.1" + "source": "https://github.com/composer/xdebug-handler/tree/2.0.4" }, "funding": [ { @@ -1050,7 +1146,7 @@ "type": "tidelift" } ], - "time": "2021-05-05T19:37:51+00:00" + "time": "2022-01-04T17:06:45+00:00" }, { "name": "doctrine/instantiator", @@ -1138,9 +1234,6 @@ "require": { "php": "^7.1 || ^8.0" }, - "replace": { - "myclabs/deep-copy": "self.version" - }, "require-dev": { "doctrine/collections": "^1.0", "doctrine/common": "^2.6", @@ -1181,16 +1274,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.10.5", + "version": "v4.13.2", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "4432ba399e47c66624bc73c8c0f811e5c109576f" + "reference": "210577fe3cf7badcc5814d99455df46564f3c077" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4432ba399e47c66624bc73c8c0f811e5c109576f", - "reference": "4432ba399e47c66624bc73c8c0f811e5c109576f", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077", + "reference": "210577fe3cf7badcc5814d99455df46564f3c077", "shasum": "" }, "require": { @@ -1231,22 +1324,22 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.5" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.2" }, - "time": "2021-05-03T19:11:20+00:00" + "time": "2021-11-30T19:35:32+00:00" }, { "name": "pdepend/pdepend", - "version": "2.9.1", + "version": "2.10.2", "source": { "type": "git", "url": "https://github.com/pdepend/pdepend.git", - "reference": "1632f0cee84512ffd6dde71e58536b3b06528c41" + "reference": "c8c1d2af43fb8c2b5387d50e9c42a9c56de13686" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pdepend/pdepend/zipball/1632f0cee84512ffd6dde71e58536b3b06528c41", - "reference": "1632f0cee84512ffd6dde71e58536b3b06528c41", + "url": "https://api.github.com/repos/pdepend/pdepend/zipball/c8c1d2af43fb8c2b5387d50e9c42a9c56de13686", + "reference": "c8c1d2af43fb8c2b5387d50e9c42a9c56de13686", "shasum": "" }, "require": { @@ -1282,7 +1375,7 @@ "description": "Official version of pdepend to be handled with Composer", "support": { "issues": "https://github.com/pdepend/pdepend/issues", - "source": "https://github.com/pdepend/pdepend/tree/2.9.1" + "source": "https://github.com/pdepend/pdepend/tree/2.10.2" }, "funding": [ { @@ -1290,20 +1383,20 @@ "type": "tidelift" } ], - "time": "2021-04-15T21:36:28+00:00" + "time": "2021-11-16T20:05:32+00:00" }, { "name": "phar-io/manifest", - "version": "2.0.1", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133" + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", - "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", "shasum": "" }, "require": { @@ -1348,9 +1441,9 @@ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/master" + "source": "https://github.com/phar-io/manifest/tree/2.0.3" }, - "time": "2020-06-27T14:33:11+00:00" + "time": "2021-07-20T11:28:43+00:00" }, { "name": "phar-io/version", @@ -1520,16 +1613,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.2.2", + "version": "5.3.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", "shasum": "" }, "require": { @@ -1540,7 +1633,8 @@ "webmozart/assert": "^1.9.1" }, "require-dev": { - "mockery/mockery": "~1.3.2" + "mockery/mockery": "~1.3.2", + "psalm/phar": "^4.8" }, "type": "library", "extra": { @@ -1570,22 +1664,22 @@ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/master" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" }, - "time": "2020-09-03T19:13:55+00:00" + "time": "2021-10-19T17:43:47+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.4.0", + "version": "1.6.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0" + "reference": "93ebd0014cab80c4ea9f5e297ea48672f1b87706" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/93ebd0014cab80c4ea9f5e297ea48672f1b87706", + "reference": "93ebd0014cab80c4ea9f5e297ea48672f1b87706", "shasum": "" }, "require": { @@ -1593,7 +1687,8 @@ "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { - "ext-tokenizer": "*" + "ext-tokenizer": "*", + "psalm/phar": "^4.8" }, "type": "library", "extra": { @@ -1619,9 +1714,9 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.4.0" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.0" }, - "time": "2020-09-17T18:55:26+00:00" + "time": "2022-01-04T19:58:01+00:00" }, { "name": "phploc/phploc", @@ -1686,22 +1781,22 @@ }, { "name": "phpmd/phpmd", - "version": "2.10.1", + "version": "2.11.1", "source": { "type": "git", "url": "https://github.com/phpmd/phpmd.git", - "reference": "bd5ef43d1dcaf7272605027c959c1c5ff3761f7a" + "reference": "08b60a2eb7e14c23f46ff8865b510ae08b75d0fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpmd/phpmd/zipball/bd5ef43d1dcaf7272605027c959c1c5ff3761f7a", - "reference": "bd5ef43d1dcaf7272605027c959c1c5ff3761f7a", + "url": "https://api.github.com/repos/phpmd/phpmd/zipball/08b60a2eb7e14c23f46ff8865b510ae08b75d0fd", + "reference": "08b60a2eb7e14c23f46ff8865b510ae08b75d0fd", "shasum": "" }, "require": { "composer/xdebug-handler": "^1.0 || ^2.0", "ext-xml": "*", - "pdepend/pdepend": "^2.9.1", + "pdepend/pdepend": "^2.10.2", "php": ">=5.3.9" }, "require-dev": { @@ -1757,7 +1852,7 @@ "support": { "irc": "irc://irc.freenode.org/phpmd", "issues": "https://github.com/phpmd/phpmd/issues", - "source": "https://github.com/phpmd/phpmd/tree/2.10.1" + "source": "https://github.com/phpmd/phpmd/tree/2.11.1" }, "funding": [ { @@ -1765,37 +1860,37 @@ "type": "tidelift" } ], - "time": "2021-05-11T17:16:16+00:00" + "time": "2021-12-17T11:25:43+00:00" }, { "name": "phpspec/prophecy", - "version": "1.13.0", + "version": "v1.15.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea" + "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/be1996ed8adc35c3fd795488a653f4b518be70ea", - "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13", + "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13", "shasum": "" }, "require": { "doctrine/instantiator": "^1.2", - "php": "^7.2 || ~8.0, <8.1", + "php": "^7.2 || ~8.0, <8.2", "phpdocumentor/reflection-docblock": "^5.2", "sebastian/comparator": "^3.0 || ^4.0", "sebastian/recursion-context": "^3.0 || ^4.0" }, "require-dev": { - "phpspec/phpspec": "^6.0", + "phpspec/phpspec": "^6.0 || ^7.0", "phpunit/phpunit": "^8.0 || ^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11.x-dev" + "dev-master": "1.x-dev" } }, "autoload": { @@ -1830,29 +1925,29 @@ ], "support": { "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/1.13.0" + "source": "https://github.com/phpspec/prophecy/tree/v1.15.0" }, - "time": "2021-03-17T13:42:18+00:00" + "time": "2021-12-08T12:19:24+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.6", + "version": "9.2.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "f6293e1b30a2354e8428e004689671b83871edde" + "reference": "d5850aaf931743067f4bfc1ae4cbd06468400687" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f6293e1b30a2354e8428e004689671b83871edde", - "reference": "f6293e1b30a2354e8428e004689671b83871edde", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d5850aaf931743067f4bfc1ae4cbd06468400687", + "reference": "d5850aaf931743067f4bfc1ae4cbd06468400687", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.10.2", + "nikic/php-parser": "^4.13.0", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -1901,7 +1996,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.6" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.10" }, "funding": [ { @@ -1909,20 +2004,20 @@ "type": "github" } ], - "time": "2021-03-28T07:26:59+00:00" + "time": "2021-12-05T09:12:13+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "3.0.5", + "version": "3.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8" + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/aa4be8575f26070b100fccb67faabb28f21f66f8", - "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", "shasum": "" }, "require": { @@ -1961,7 +2056,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.5" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" }, "funding": [ { @@ -1969,7 +2064,7 @@ "type": "github" } ], - "time": "2020-09-28T05:57:25+00:00" + "time": "2021-12-02T12:48:52+00:00" }, { "name": "phpunit/php-invoker", @@ -2154,16 +2249,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.5", + "version": "9.5.13", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "89ff45ea9d70e35522fb6654a2ebc221158de276" + "reference": "597cb647654ede35e43b137926dfdfef0fb11743" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/89ff45ea9d70e35522fb6654a2ebc221158de276", - "reference": "89ff45ea9d70e35522fb6654a2ebc221158de276", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/597cb647654ede35e43b137926dfdfef0fb11743", + "reference": "597cb647654ede35e43b137926dfdfef0fb11743", "shasum": "" }, "require": { @@ -2175,11 +2270,11 @@ "ext-xml": "*", "ext-xmlwriter": "*", "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.1", + "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", "php": ">=7.3", "phpspec/prophecy": "^1.12.1", - "phpunit/php-code-coverage": "^9.2.3", + "phpunit/php-code-coverage": "^9.2.7", "phpunit/php-file-iterator": "^3.0.5", "phpunit/php-invoker": "^3.1.1", "phpunit/php-text-template": "^2.0.3", @@ -2193,7 +2288,7 @@ "sebastian/global-state": "^5.0.1", "sebastian/object-enumerator": "^4.0.3", "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^2.3.2", + "sebastian/type": "^2.3.4", "sebastian/version": "^3.0.2" }, "require-dev": { @@ -2241,11 +2336,11 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.5" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.13" }, "funding": [ { - "url": "https://phpunit.de/donate.html", + "url": "https://phpunit.de/sponsors.html", "type": "custom" }, { @@ -2253,24 +2348,24 @@ "type": "github" } ], - "time": "2021-06-05T04:49:07+00:00" + "time": "2022-01-24T07:33:35+00:00" }, { "name": "psr/container", - "version": "1.1.1", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", "shasum": "" }, "require": { - "php": ">=7.2.0" + "php": ">=7.4.0" }, "type": "library", "autoload": { @@ -2299,9 +2394,9 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.1" + "source": "https://github.com/php-fig/container/tree/1.1.2" }, - "time": "2021-03-05T17:36:06+00:00" + "time": "2021-11-05T16:50:12+00:00" }, { "name": "sebastian/cli-parser", @@ -2732,16 +2827,16 @@ }, { "name": "sebastian/exporter", - "version": "4.0.3", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65" + "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d89cc98761b8cb5a1a235a6b703ae50d34080e65", - "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9", + "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9", "shasum": "" }, "require": { @@ -2790,14 +2885,14 @@ } ], "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", + "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ "export", "exporter" ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.3" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4" }, "funding": [ { @@ -2805,7 +2900,7 @@ "type": "github" } ], - "time": "2020-09-28T05:24:23+00:00" + "time": "2021-11-11T14:18:36+00:00" }, { "name": "sebastian/global-state", @@ -3330,16 +3425,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.5.8", + "version": "3.6.2", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "9d583721a7157ee997f235f327de038e7ea6dac4" + "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/9d583721a7157ee997f235f327de038e7ea6dac4", - "reference": "9d583721a7157ee997f235f327de038e7ea6dac4", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a", + "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a", "shasum": "" }, "require": { @@ -3382,39 +3477,39 @@ "source": "https://github.com/squizlabs/PHP_CodeSniffer", "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" }, - "time": "2020-10-23T02:01:07+00:00" + "time": "2021-12-12T21:44:58+00:00" }, { "name": "symfony/config", - "version": "v5.3.0", + "version": "v5.4.2", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "9f4a448c2d7fd2c90882dfff930b627ddbe16810" + "reference": "2e082dae50da563c639119b7b52347a2a3db4ba5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/9f4a448c2d7fd2c90882dfff930b627ddbe16810", - "reference": "9f4a448c2d7fd2c90882dfff930b627ddbe16810", + "url": "https://api.github.com/repos/symfony/config/zipball/2e082dae50da563c639119b7b52347a2a3db4ba5", + "reference": "2e082dae50da563c639119b7b52347a2a3db4ba5", "shasum": "" }, "require": { "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1", - "symfony/filesystem": "^4.4|^5.0", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/filesystem": "^4.4|^5.0|^6.0", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-php80": "^1.15", + "symfony/polyfill-php80": "^1.16", "symfony/polyfill-php81": "^1.22" }, "conflict": { "symfony/finder": "<4.4" }, "require-dev": { - "symfony/event-dispatcher": "^4.4|^5.0", - "symfony/finder": "^4.4|^5.0", - "symfony/messenger": "^4.4|^5.0", - "symfony/service-contracts": "^1.1|^2", - "symfony/yaml": "^4.4|^5.0" + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/finder": "^4.4|^5.0|^6.0", + "symfony/messenger": "^4.4|^5.0|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/yaml": "^4.4|^5.0|^6.0" }, "suggest": { "symfony/yaml": "To use the yaml reference dumper" @@ -3445,7 +3540,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v5.3.0" + "source": "https://github.com/symfony/config/tree/v5.4.2" }, "funding": [ { @@ -3461,27 +3556,28 @@ "type": "tidelift" } ], - "time": "2021-05-26T17:43:10+00:00" + "time": "2021-12-15T11:06:13+00:00" }, { "name": "symfony/dependency-injection", - "version": "v5.3.0", + "version": "v5.4.2", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "94d973cb742d8c5c5dcf9534220e6b73b09af1d4" + "reference": "ba94559be9738d77cd29e24b5d81cf3b89b7d628" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/94d973cb742d8c5c5dcf9534220e6b73b09af1d4", - "reference": "94d973cb742d8c5c5dcf9534220e6b73b09af1d4", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/ba94559be9738d77cd29e24b5d81cf3b89b7d628", + "reference": "ba94559be9738d77cd29e24b5d81cf3b89b7d628", "shasum": "" }, "require": { "php": ">=7.2.5", "psr/container": "^1.1.1", - "symfony/deprecation-contracts": "^2.1", - "symfony/polyfill-php80": "^1.15", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16", + "symfony/polyfill-php81": "^1.22", "symfony/service-contracts": "^1.1.6|^2" }, "conflict": { @@ -3496,9 +3592,9 @@ "symfony/service-implementation": "1.0|2.0" }, "require-dev": { - "symfony/config": "^5.3", - "symfony/expression-language": "^4.4|^5.0", - "symfony/yaml": "^4.4|^5.0" + "symfony/config": "^5.3|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/yaml": "^4.4|^5.0|^6.0" }, "suggest": { "symfony/config": "", @@ -3533,7 +3629,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v5.3.0" + "source": "https://github.com/symfony/dependency-injection/tree/v5.4.2" }, "funding": [ { @@ -3549,20 +3645,20 @@ "type": "tidelift" } ], - "time": "2021-05-26T17:57:12+00:00" + "time": "2021-12-29T10:10:35+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v2.4.0", + "version": "v2.5.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627" + "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627", - "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/6f981ee24cf69ee7ce9736146d1c57c2780598a8", + "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8", "shasum": "" }, "require": { @@ -3571,7 +3667,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.4-dev" + "dev-main": "2.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -3600,7 +3696,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.0" }, "funding": [ { @@ -3616,25 +3712,27 @@ "type": "tidelift" } ], - "time": "2021-03-23T23:28:01+00:00" + "time": "2021-07-12T14:48:14+00:00" }, { "name": "symfony/filesystem", - "version": "v5.3.0", + "version": "v5.4.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "348116319d7fb7d1faa781d26a48922428013eb2" + "reference": "731f917dc31edcffec2c6a777f3698c33bea8f01" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/348116319d7fb7d1faa781d26a48922428013eb2", - "reference": "348116319d7fb7d1faa781d26a48922428013eb2", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/731f917dc31edcffec2c6a777f3698c33bea8f01", + "reference": "731f917dc31edcffec2c6a777f3698c33bea8f01", "shasum": "" }, "require": { "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8" + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8", + "symfony/polyfill-php80": "^1.16" }, "type": "library", "autoload": { @@ -3662,7 +3760,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.3.0" + "source": "https://github.com/symfony/filesystem/tree/v5.4.0" }, "funding": [ { @@ -3678,25 +3776,28 @@ "type": "tidelift" } ], - "time": "2021-05-26T17:43:10+00:00" + "time": "2021-10-28T13:39:27+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.23.0", + "version": "v1.24.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce" + "reference": "30885182c981ab175d4d034db0f6f469898070ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce", - "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab", + "reference": "30885182c981ab175d4d034db0f6f469898070ab", "shasum": "" }, "require": { "php": ">=7.1" }, + "provide": { + "ext-ctype": "*" + }, "suggest": { "ext-ctype": "For best performance" }, @@ -3741,7 +3842,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.24.0" }, "funding": [ { @@ -3757,20 +3858,20 @@ "type": "tidelift" } ], - "time": "2021-02-19T12:13:01+00:00" + "time": "2021-10-20T20:35:02+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.23.0", + "version": "v1.24.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0" + "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/eca0bf41ed421bed1b57c4958bab16aa86b757d0", - "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/57b712b08eddb97c762a8caa32c84e037892d2e9", + "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9", "shasum": "" }, "require": { @@ -3824,7 +3925,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.24.0" }, "funding": [ { @@ -3840,20 +3941,20 @@ "type": "tidelift" } ], - "time": "2021-02-19T12:13:01+00:00" + "time": "2021-09-13T13:58:33+00:00" }, { "name": "symfony/polyfill-php81", - "version": "v1.23.0", + "version": "v1.24.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "e66119f3de95efc359483f810c4c3e6436279436" + "reference": "5de4ba2d41b15f9bd0e19b2ab9674135813ec98f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/e66119f3de95efc359483f810c4c3e6436279436", - "reference": "e66119f3de95efc359483f810c4c3e6436279436", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/5de4ba2d41b15f9bd0e19b2ab9674135813ec98f", + "reference": "5de4ba2d41b15f9bd0e19b2ab9674135813ec98f", "shasum": "" }, "require": { @@ -3903,7 +4004,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.23.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.24.0" }, "funding": [ { @@ -3919,25 +4020,29 @@ "type": "tidelift" } ], - "time": "2021-05-21T13:25:03+00:00" + "time": "2021-09-13T13:58:11+00:00" }, { "name": "symfony/service-contracts", - "version": "v2.4.0", + "version": "v2.5.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb" + "reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb", - "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc", + "reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc", "shasum": "" }, "require": { "php": ">=7.2.5", - "psr/container": "^1.1" + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1" + }, + "conflict": { + "ext-psr": "<1.1|>=2" }, "suggest": { "symfony/service-implementation": "" @@ -3945,7 +4050,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.4-dev" + "dev-main": "2.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -3982,7 +4087,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.4.0" + "source": "https://github.com/symfony/service-contracts/tree/v2.5.0" }, "funding": [ { @@ -3998,20 +4103,20 @@ "type": "tidelift" } ], - "time": "2021-04-01T10:43:52+00:00" + "time": "2021-11-04T16:48:04+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "75a63c33a8577608444246075ea0af0d052e452a" + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/75a63c33a8577608444246075ea0af0d052e452a", - "reference": "75a63c33a8577608444246075ea0af0d052e452a", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", "shasum": "" }, "require": { @@ -4040,7 +4145,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/master" + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" }, "funding": [ { @@ -4048,7 +4153,7 @@ "type": "github" } ], - "time": "2020-07-12T23:59:07+00:00" + "time": "2021-07-28T10:34:58+00:00" }, { "name": "webmozart/assert", @@ -4115,7 +4220,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=7.1", + "php": "^7.1 || ^8.0", "ext-session": "*", "ext-ctype": "*", "ext-pdo": "*", @@ -4127,11 +4232,11 @@ "ext-mbstring": "*", "ext-curl": "*", "ext-json": "*", - "ext-openssl": "*" + "ext-openssl": "*", + "ext-fileinfo": "*" }, "platform-dev": { - "php": ">=7.3", "ext-pcntl": "*" }, - "plugin-api-version": "2.1.0" + "plugin-api-version": "2.2.0" } From 9babcde3e52053ff41da6e3a5d95a60597ba0d14 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 4 Feb 2022 10:52:12 +0100 Subject: [PATCH 318/319] additional mkdir/chmod parameter fixes and cron-lock file adjustments Signed-off-by: Michael Kaufmann --- install/froxlor.sql | 4 ++-- install/updates/froxlor/0.10/update_0.10.inc.php | 2 +- lib/Froxlor/Cron/MasterCron.php | 10 +++++++++- lib/Froxlor/SImExporter.php | 4 ++-- lib/Froxlor/Settings/Store.php | 2 +- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index 6bb494ca..b9e7f8fa 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -495,7 +495,6 @@ opcache.load_comments opcache.revalidate_path opcache.save_comments opcache.use_cwd -opcache.validate_timestamps opcache.fast_shutdown'), ('phpfpm', 'ini_admin_values', 'cgi.redirect_status_env date.timezone @@ -519,7 +518,8 @@ opcache.restrict_api opcache.revalidate_freq opcache.max_accelerated_files opcache.memory_consumption -opcache.interned_strings_buffer'), +opcache.interned_strings_buffer +opcache.validate_timestamps'), ('nginx', 'fastcgiparams', '/etc/nginx/fastcgi_params'), ('system', 'lastaccountnumber', '0'), ('system', 'lastguid', '9999'), diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index 2351b9fb..5eb622bc 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -843,7 +843,7 @@ if (\Froxlor\Froxlor::isDatabaseVersion('202106270')) { throw new \Exception("img directory does not exist and cannot be created"); } if (!is_writable($path)) { - if (!chmod($path, '0775')) { + if (!chmod($path, 0775)) { throw new \Exception("Cannot write to img directory"); } } diff --git a/lib/Froxlor/Cron/MasterCron.php b/lib/Froxlor/Cron/MasterCron.php index 2f2b52a0..c280b7c4 100644 --- a/lib/Froxlor/Cron/MasterCron.php +++ b/lib/Froxlor/Cron/MasterCron.php @@ -24,6 +24,13 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron private static $debugHandler = null; + private static $noncron_params = [ + 'force', + 'debug', + 'no-fork', + 'run-task' + ]; + public static function setArguments($argv = null) { self::$argv = $argv; @@ -47,6 +54,7 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron echo "--run-task\t\trun a specific task [1 = re-generate configs, 4 = re-generate dns zones, 10 = re-set quotas, 99 = re-create cron.d-file]\n"; echo "--debug\t\t\toutput debug information about what is going on to STDOUT.\n"; echo "--no-fork\t\tdo not fork to backkground (traffic cron only).\n\n"; + exit(); } /** @@ -161,7 +169,7 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron $crontype = ""; if (isset(self::$argv) && is_array(self::$argv) && count(self::$argv) > 1) { for ($x = 1; $x < count(self::$argv); $x ++) { - if (substr(strtolower(self::$argv[$x]), 0, 2) == '--' && strlen(self::$argv[$x]) > 3) { + 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; diff --git a/lib/Froxlor/SImExporter.php b/lib/Froxlor/SImExporter.php index 91ba149f..2f4929c8 100644 --- a/lib/Froxlor/SImExporter.php +++ b/lib/Froxlor/SImExporter.php @@ -145,13 +145,13 @@ class SImExporter // 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')) { + 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')) { + if (!chmod($path, 0775)) { throw new \Exception("Cannot write to img directory"); } } diff --git a/lib/Froxlor/Settings/Store.php b/lib/Froxlor/Settings/Store.php index d642de1c..d19328f1 100644 --- a/lib/Froxlor/Settings/Store.php +++ b/lib/Froxlor/Settings/Store.php @@ -388,7 +388,7 @@ class Store 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'])) { From 1d7d32130a6ffa0e6b1529b92cd257c2b9becb6c Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 4 Feb 2022 13:24:41 +0100 Subject: [PATCH 319/319] setting version to 0.10.33 for upcoming release Signed-off-by: Michael Kaufmann --- install/froxlor.sql | 2 +- install/updates/froxlor/0.10/update_0.10.inc.php | 5 +++++ lib/Froxlor/Froxlor.php | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index b9e7f8fa..5b5a8b0a 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -723,7 +723,7 @@ opcache.validate_timestamps'), ('panel', 'logo_image_login', ''), ('panel', 'logo_overridetheme', '0'), ('panel', 'logo_overridecustom', '0'), - ('panel', 'version', '0.10.32'), + ('panel', 'version', '0.10.33'), ('panel', 'db_version', '202112310'); diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index 5eb622bc..7889077e 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -965,3 +965,8 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.31')) { showUpdateStep("Updating from 0.10.31 to 0.10.32", false); \Froxlor\Froxlor::updateToVersion('0.10.32'); } + +if (\Froxlor\Froxlor::isFroxlorVersion('0.10.32')) { + showUpdateStep("Updating from 0.10.32 to 0.10.33", false); + \Froxlor\Froxlor::updateToVersion('0.10.33'); +} diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index 94675e99..804aab8e 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -7,7 +7,7 @@ final class Froxlor { // Main version variable - const VERSION = '0.10.32'; + const VERSION = '0.10.33'; // Database version (YYYYMMDDC where C is a daily counter) const DBVERSION = '202112310';