From 72016a5735e77634522e53975f3b2b63ba1f8a2d Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 7 May 2019 14:03:37 +0200
Subject: [PATCH 001/159] fix integrity-check language-file entries
Signed-off-by: Michael Kaufmann
---
lng/english.lng.php | 12 ++++++------
lng/german.lng.php | 12 ++++++------
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/lng/english.lng.php b/lng/english.lng.php
index 45bced52..bf55b07b 100644
--- a/lng/english.lng.php
+++ b/lng/english.lng.php
@@ -1743,12 +1743,12 @@ $lng['admin']['configfiles']['commands'] = 'Commands: T
$lng['admin']['configfiles']['files'] = 'Config files: The commands before the textfields should open an editor with the target file. Just copy and paste the contents into the editor and save the file.Please note: The MySQL-password has not been replaced for security reasons. Please replace "FROXLOR_MYSQL_PASSWORD" on your own or use the javascript form below to replace it on-site. If you forgot your MySQL-password you\'ll find it in "lib/userdata.inc.php"';
$lng['serversettings']['apache_itksupport']['title'] = 'Use modifications for Apache ITK-MPM';
$lng['serversettings']['apache_itksupport']['description'] = 'ATTENTION: use only if you actually have apache itk-mpm enabled otherwise your webserver will not be able to start';
-$lng['integrity_check']['DatabaseCharset'] = 'Character set of database (should be UTF-8)';
-$lng['integrity_check']['DomainIpTable'] = 'IP <‐> domain references';
-$lng['integrity_check']['SubdomainSslRedirect'] = 'False SSL-redirect flag for non-ssl domains';
-$lng['integrity_check']['FroxlorLocalGroupMemberForFcgidPhpFpm'] = 'froxlor-user in the customer groups (for FCGID/php-fpm)';
-$lng['integrity_check']['WebserverGroupMemberForFcgidPhpFpm'] = 'Webserver-user in the customer groups (for FCGID/php-fpm)';
-$lng['integrity_check']['SubdomainLetsencrypt'] = 'Main domains with no SSL-Port assigned don\'t have any subdomains with active SSL redirect';
+$lng['integrity_check']['databaseCharset'] = 'Character set of database (should be UTF-8)';
+$lng['integrity_check']['domainIpTable'] = 'IP <‐> domain references';
+$lng['integrity_check']['subdomainSslRedirect'] = 'False SSL-redirect flag for non-ssl domains';
+$lng['integrity_check']['froxlorLocalGroupMemberForFcgidPhpFpm'] = 'froxlor-user in the customer groups (for FCGID/php-fpm)';
+$lng['integrity_check']['webserverGroupMemberForFcgidPhpFpm'] = 'Webserver-user in the customer groups (for FCGID/php-fpm)';
+$lng['integrity_check']['subdomainLetsencrypt'] = 'Main domains with no SSL-Port assigned don\'t have any subdomains with active SSL redirect';
$lng['admin']['mod_fcgid_umask']['title'] = 'Umask (default: 022)';
// Added for apcuinfo
diff --git a/lng/german.lng.php b/lng/german.lng.php
index 551ff001..4e150a75 100644
--- a/lng/german.lng.php
+++ b/lng/german.lng.php
@@ -1467,12 +1467,12 @@ $lng['admin']['configfiles']['commands'] = 'Kommandos:
$lng['admin']['configfiles']['files'] = 'Konfigurationsdateien: Der Befehl direkt vor dem Textfeld sollte einen Editor mit der Zieldatei öffnen. Der Inhalt kann nun einfach kopiert und in den Editor eingefügt und die Datei gespeichert werden.Bitte beachten: Das MySQL-Passwort wurde aus Sicherheitsgründen nicht ersetzt. Bitte ersetzen Sie "FROXLOR_MYSQL_PASSWORD" manuell oder nutzen Sie das folgende Formular, um es temporär auf dieser Seite zu setzen. Falls das Passwort vergessen wurde, findet es sich in der Datei "lib/userdata.inc.php".';
$lng['serversettings']['apache_itksupport']['title'] = 'Anpassungen für Apache ITK-MPM verwenden';
$lng['serversettings']['apache_itksupport']['description'] = 'Achtung: Bitte nur verwenden, wenn wirklich Apache itk-mpm verwendet wird, ansonsten wird der Webserver nicht starten.
';
-$lng['integrity_check']['DatabaseCharset'] = 'Characterset der Datenbank (sollte UTF-8 sein)';
-$lng['integrity_check']['DomainIpTable'] = 'IP <‐> Domain Verknüpfung';
-$lng['integrity_check']['SubdomainSslRedirect'] = 'Falsches SSL-redirect Flag bei nicht-SSL Domains';
-$lng['integrity_check']['FroxlorLocalGroupMemberForFcgidPhpFpm'] = 'froxlor-Benutzer in Kunden-Gruppen (für FCGID/php-fpm)';
-$lng['integrity_check']['WebserverGroupMemberForFcgidPhpFpm'] = 'Webserver-Benutzer in Kunden-Gruppen (für FCGID/php-fpm)';
-$lng['integrity_check']['SubdomainLetsencrypt'] = 'Hauptdomains ohne zugewiesenen SSL-Port haben keine Subdomain mit aktiviertem SSL-Redirect';
+$lng['integrity_check']['databaseCharset'] = 'Characterset der Datenbank (sollte UTF-8 sein)';
+$lng['integrity_check']['domainIpTable'] = 'IP <‐> Domain Verknüpfung';
+$lng['integrity_check']['subdomainSslRedirect'] = 'Falsches SSL-redirect Flag bei nicht-SSL Domains';
+$lng['integrity_check']['froxlorLocalGroupMemberForFcgidPhpFpm'] = 'froxlor-Benutzer in Kunden-Gruppen (für FCGID/php-fpm)';
+$lng['integrity_check']['webserverGroupMemberForFcgidPhpFpm'] = 'Webserver-Benutzer in Kunden-Gruppen (für FCGID/php-fpm)';
+$lng['integrity_check']['subdomainLetsencrypt'] = 'Hauptdomains ohne zugewiesenen SSL-Port haben keine Subdomain mit aktiviertem SSL-Redirect';
$lng['admin']['mod_fcgid_umask']['title'] = 'Umask (Standard: 022)';
// Added for let's encrypt
From e2d69c664a92b05e580e10c111a1712b6861f9d5 Mon Sep 17 00:00:00 2001
From: Christian Schiffler
Date: Mon, 13 May 2019 19:53:55 +0200
Subject: [PATCH 002/159] Fixes #682 - mail log parsing regex character group
The mail log parsing regex was incorrectly using a character group of `\A`
---
lib/Froxlor/MailLogParser.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/Froxlor/MailLogParser.php b/lib/Froxlor/MailLogParser.php
index 1463da2f..f8800e89 100644
--- a/lib/Froxlor/MailLogParser.php
+++ b/lib/Froxlor/MailLogParser.php
@@ -101,13 +101,13 @@ class MailLogParser
$timestamp = $this->getLogTimestamp($line);
if ($this->startTime < $timestamp) {
- if (preg_match("/postfix\/qmgr.*(?::|\])\s([A-Z\d]+).*from=(?:.*\@([a-z\A-Z\d\.\-]+))?>?, size=(\d+),/", $line, $matches)) {
+ if (preg_match("/postfix\/qmgr.*(?::|\])\s([A-Z\d]+).*from=(?:.*\@([a-zA-Z\d\.\-]+))?>?, size=(\d+),/", $line, $matches)) {
// Postfix from
$this->mails[$matches[1]] = array(
"domainFrom" => strtolower($matches[2]),
"size" => $matches[3]
);
- } elseif (preg_match("/postfix\/(?:pipe|smtp).*(?::|\])\s([A-Z\d]+).*to=(?:.*\@([a-z\A-Z\d\.\-]+))?>?,/", $line, $matches)) {
+ } elseif (preg_match("/postfix\/(?:pipe|smtp).*(?::|\])\s([A-Z\d]+).*to=(?:.*\@([a-zA-Z\d\.\-]+))?>?,/", $line, $matches)) {
// Postfix to
if (array_key_exists($matches[1], $this->mails)) {
$this->mails[$matches[1]]["domainTo"] = strtolower($matches[2]);
From 68f55f95968f9108c12e24ad3149800b8790cc07 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Mon, 27 May 2019 08:33:36 +0200
Subject: [PATCH 003/159] dont allow bootstrap.php file from tests/ to be
called via browser
Signed-off-by: Michael Kaufmann
---
tests/bootstrap.php | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index a4e59d86..87344530 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -11,6 +11,11 @@ if (file_exists('/etc/froxlor-test.pwd') && file_exists('/etc/froxlor-test.rpwd'
define('TRAVIS_CI', 1);
}
+if (@php_sapi_name() !== 'cli') {
+ // not to be called via browser
+ die;
+}
+
$userdata_content = "
Date: Mon, 27 May 2019 11:47:58 +0200
Subject: [PATCH 004/159] set version to 0.10.0-rc2 for second release
candidate
Signed-off-by: Michael Kaufmann
---
install/froxlor.sql | 2 +-
install/updates/froxlor/0.10/update_0.10.inc.php | 4 ++++
lib/Froxlor/Froxlor.php | 2 +-
3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/install/froxlor.sql b/install/froxlor.sql
index 127fa073..ec917791 100644
--- a/install/froxlor.sql
+++ b/install/froxlor.sql
@@ -680,7 +680,7 @@ opcache.interned_strings_buffer'),
('panel', 'password_special_char', '!?<>§$%+#=@'),
('panel', 'customer_hide_options', ''),
('panel', 'is_configured', '0'),
- ('panel', 'version', '0.10.0-rc1'),
+ ('panel', 'version', '0.10.0-rc2'),
('panel', 'db_version', '201904250');
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 c4796636..d79ceb9e 100644
--- a/install/updates/froxlor/0.10/update_0.10.inc.php
+++ b/install/updates/froxlor/0.10/update_0.10.inc.php
@@ -255,3 +255,7 @@ if (\Froxlor\Froxlor::isDatabaseVersion('201904100')) {
\Froxlor\Froxlor::updateToDbVersion('201904250');
}
+
+if (\Froxlor\Froxlor::isFroxlorVersion('0.10.0-rc1')) {
+ \Froxlor\Froxlor::updateToVersion('0.10.0-rc2');
+}
diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php
index 99934a6d..53e32359 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.0-rc1';
+ const VERSION = '0.10.0-rc2';
// Database version (YYYYMMDDC where C is a daily counter)
const DBVERSION = '201904250';
From b75c9ddff63b6be19d0de8bb6257428471f5dacf Mon Sep 17 00:00:00 2001
From: Daniel Drexlmaier
Date: Mon, 27 May 2019 15:27:28 +0200
Subject: [PATCH 005/159] Update install.php
---
install/install.php | 3 +++
1 file changed, 3 insertions(+)
diff --git a/install/install.php b/install/install.php
index 1e06c9d1..3a93b420 100644
--- a/install/install.php
+++ b/install/install.php
@@ -15,6 +15,9 @@
* @package Install
*
*/
+if(!file_exists(dirname(__DIR__) . '/vendor/autoload.php')){
+ die('Vendor does not exist. Please run "Composer install". For more informationen https://github.com/Froxlor/Froxlor/wiki');
+}
require dirname(__DIR__) . '/vendor/autoload.php';
require __DIR__ . '/lib/class.FroxlorInstall.php';
From 79e5113e1298a21bb30035f710d8e00a765ba3e7 Mon Sep 17 00:00:00 2001
From: Daniel Drexlmaier
Date: Mon, 27 May 2019 15:28:08 +0200
Subject: [PATCH 006/159] Update init.php
---
lib/init.php | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/init.php b/lib/init.php
index 2e57aa1c..7d474ad4 100644
--- a/lib/init.php
+++ b/lib/init.php
@@ -16,6 +16,10 @@
* @package System
*
*/
+if(!file_exists(dirname(__DIR__) . '/vendor/autoload.php')){
+ die('Vendor does not exist. Please run "Composer install". For more informationen https://github.com/Froxlor/Froxlor/wiki');
+}
+
require dirname(__DIR__) . '/vendor/autoload.php';
use Froxlor\Database\Database;
From fb87129e294d510538e67bb5e7a995b3c773505f Mon Sep 17 00:00:00 2001
From: Daniel Drexlmaier
Date: Mon, 27 May 2019 15:46:39 +0200
Subject: [PATCH 007/159] Update init.php
---
lib/init.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/init.php b/lib/init.php
index 7d474ad4..bec161f6 100644
--- a/lib/init.php
+++ b/lib/init.php
@@ -17,7 +17,7 @@
*
*/
if(!file_exists(dirname(__DIR__) . '/vendor/autoload.php')){
- die('Vendor does not exist. Please run "Composer install". For more informationen https://github.com/Froxlor/Froxlor/wiki');
+ die('Vendor does not exist. Please run "composer install". For more informationen https://github.com/Froxlor/Froxlor/wiki');
}
require dirname(__DIR__) . '/vendor/autoload.php';
From 6ea91f55e5052df86e6d1e90dbbc03073b0e7d7e Mon Sep 17 00:00:00 2001
From: Daniel Drexlmaier
Date: Mon, 27 May 2019 15:47:30 +0200
Subject: [PATCH 008/159] Update install.php
---
install/install.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/install/install.php b/install/install.php
index 3a93b420..76723290 100644
--- a/install/install.php
+++ b/install/install.php
@@ -16,7 +16,7 @@
*
*/
if(!file_exists(dirname(__DIR__) . '/vendor/autoload.php')){
- die('Vendor does not exist. Please run "Composer install". For more informationen https://github.com/Froxlor/Froxlor/wiki');
+ die('Vendor does not exist. Please run "composer install". For more informationen https://github.com/Froxlor/Froxlor/wiki');
}
require dirname(__DIR__) . '/vendor/autoload.php';
require __DIR__ . '/lib/class.FroxlorInstall.php';
From a647d48fbed68a1f6646490ef9a1ed6bc12e9a39 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Mon, 27 May 2019 17:48:33 +0200
Subject: [PATCH 009/159] fix up testing/production switch and challengepath
for lets encrypt, fixes #696
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
index 07e1ec27..70b398fc 100644
--- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
+++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
@@ -272,7 +272,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
$acmesh_cmd = self::$acmesh . " --auto-upgrade 0 --server " . self::$apiserver . " --" . $cert_mode . " -d " . implode(" -d ", $domains);
if ($cert_mode == 'issue') {
- $acmesh_cmd .= " -w " . \Froxlor\Froxlor::getInstallDir();
+ $acmesh_cmd .= " -w " . Settings::Get('system.letsencryptchallengepath');
}
if (Settings::Get('system.leecc') > 0) {
$acmesh_cmd .= " --keylength ec-" . Settings::Get('system.leecc');
@@ -282,6 +282,9 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
if (Settings::Get('system.letsencryptreuseold') != '1') {
$acmesh_cmd .= " --always-force-new-domain-key";
}
+ if (Settings::Get('system.letsencryptca') == 'testing') {
+ $acmesh_cmd .= " --staging";
+ }
$acme_result = \Froxlor\FileDir::safe_exec($acmesh_cmd);
From 87a2f86365aeac3764e7ff705b2e3a5977582fb3 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Thu, 30 May 2019 17:44:08 +0200
Subject: [PATCH 010/159] do not set default ssl-ips if the frontend values are
left empty; if default ssl-ips are specified, preset them in the form when
adding a domain, fixes #697
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Api/Commands/Domains.php | 9 ++++++---
lib/formfields/admin/domains/formfield.domains_add.php | 2 +-
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php
index 05104b25..79009efd 100644
--- a/lib/Froxlor/Api/Commands/Domains.php
+++ b/lib/Froxlor/Api/Commands/Domains.php
@@ -170,7 +170,9 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* @param bool $letsencrypt
* optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires SSL to be enabled
* @param array $ssl_ipandport
- * optional, list of ssl-enabled ip/port id's to assign to this domain
+ * optional, list of ssl-enabled ip/port id's to assign to this domain, default empty
+ * @param bool $use_default_ssl_ipandport_if_empty
+ * optional, set the systems default ssl ip addresses if none are given via $ssl_ipandport parameter
* @param bool $http2
* optional, whether to enable http/2 for this domain (requires to be enabled in the settings), default 0 (false)
* @param int $hsts_maxage
@@ -223,7 +225,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$mod_fcgid_maxrequests = $this->getParam('mod_fcgid_maxrequests', true, - 1);
$ssl_redirect = $this->getBoolParam('ssl_redirect', true, 0);
$letsencrypt = $this->getBoolParam('letsencrypt', true, 0);
- $p_ssl_ipandports = $this->getParam('ssl_ipandport', true, explode(',', Settings::Get('system.defaultsslip')));
+ $use_default_ssl_ipandport_if_empty = $this->getBoolParam('use_default_ssl_ipandport_if_empty', true, 0);
+ $p_ssl_ipandports = $this->getParam('ssl_ipandport', true, $use_default_ssl_ipandport_if_empty ? explode(',', Settings::Get('system.defaultsslip')) : array());
$http2 = $this->getBoolParam('http2', true, 0);
$hsts_maxage = $this->getParam('hsts_maxage', true, 0);
$hsts_sub = $this->getBoolParam('hsts_sub', true, 0);
@@ -1633,7 +1636,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* @param boolean $ssl
* default false
* @param int $edit_id
- * default 0
+ * default 0
*
* @throws \Exception
* @return array
diff --git a/lib/formfields/admin/domains/formfield.domains_add.php b/lib/formfields/admin/domains/formfield.domains_add.php
index 48b7b243..ddbb6266 100644
--- a/lib/formfields/admin/domains/formfield.domains_add.php
+++ b/lib/formfields/admin/domains/formfield.domains_add.php
@@ -185,7 +185,7 @@ return array(
'desc' => $lng['domains']['ipandport_ssl_multi']['description'],
'type' => 'checkbox',
'values' => $ssl_ipsandports,
- 'value' => '',
+ 'value' => explode(',', \Froxlor\Settings::Get('system.defaultsslip')),
'is_array' => 1
),
'ssl_redirect' => array(
From 6806f896d62c0bc065d36b6885d5e77dba3c6b83 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Fri, 31 May 2019 08:02:03 +0200
Subject: [PATCH 011/159] fix proftp path of rhel/centos config template, fixes
#636
Signed-off-by: Michael Kaufmann
---
lib/configfiles/rhel_centos.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/configfiles/rhel_centos.xml b/lib/configfiles/rhel_centos.xml
index 68f9e544..0e3682f9 100644
--- a/lib/configfiles/rhel_centos.xml
+++ b/lib/configfiles/rhel_centos.xml
@@ -1826,7 +1826,7 @@ iterate_query = SELECT username AS user FROM mail_users
-
Date: Mon, 3 Jun 2019 11:59:56 +0200
Subject: [PATCH 012/159] fix vhost(parts)-merging in nginx cron, fixes #669
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Cron/Http/Nginx.php | 46 +++++++++++++++++++++------------
1 file changed, 29 insertions(+), 17 deletions(-)
diff --git a/lib/Froxlor/Cron/Http/Nginx.php b/lib/Froxlor/Cron/Http/Nginx.php
index ff6f3669..e38c9a6f 100644
--- a/lib/Froxlor/Cron/Http/Nginx.php
+++ b/lib/Froxlor/Cron/Http/Nginx.php
@@ -250,7 +250,7 @@ class Nginx extends HttpConfigBase
$aliases = "";
$froxlor_aliases = Settings::Get('system.froxloraliases');
- if (!empty($froxlor_aliases)) {
+ if (! empty($froxlor_aliases)) {
$froxlor_aliases = explode(",", $froxlor_aliases);
foreach ($froxlor_aliases as $falias) {
if (\Froxlor\Validate\Validate::validateDomain(trim($falias))) {
@@ -574,26 +574,38 @@ class Nginx extends HttpConfigBase
return $vhost_content;
}
+ private function cleanVhostStruct($vhost = null)
+ {
+ // Remove windows linebreaks
+ $vhost = str_replace("\r", "\n", $vhost);
+ // Break blocks into lines
+ $vhost = str_replace(array(
+ "{",
+ "}"
+ ), array(
+ " {\n",
+ "\n}"
+ ), $vhost);
+ // Break into array items
+ $vhost = explode("\n", preg_replace('/[ \t]+/', ' ', trim(preg_replace('/\t+/', '', $vhost))));
+ // Remove empty lines
+ $vhost = array_filter($vhost, function ($a) {
+ return preg_match("#\S#", $a);
+ });
+
+ // remove unnecessary whitespaces
+ $vhost = array_map("trim", $vhost);
+ // re-number array keys
+ $vhost = array_values($vhost);
+ return $vhost;
+ }
+
protected function mergeVhostCustom($vhost_frx, $vhost_usr)
{
// Clean froxlor defined settings
- $vhost_frx = explode("\n", preg_replace('/[ \t]+/', ' ', trim(preg_replace('/\t+/', '', $vhost_frx)))); // Break into array items
- $vhost_frx = array_map("trim", $vhost_frx); // remove unnecessary whitespaces
-
+ $vhost_frx = $this->cleanVhostStruct($vhost_frx);
// Clean user defined settings
- $vhost_usr = str_replace("\r", "\n", $vhost_usr); // Remove windows linebreaks
- $vhost_usr = str_replace(array(
- "{ ",
- " }"
- ), array(
- "{\n",
- "\n}"
- ), $vhost_usr); // Break blocks into lines
- $vhost_usr = explode("\n", preg_replace('/[ \t]+/', ' ', trim(preg_replace('/\t+/', '', $vhost_usr)))); // Break into array items
- // Remove empty lines
- $vhost_usr = array_filter($vhost_usr, function ($a) {
- return preg_match("#\S#", $a);
- });
+ $vhost_usr = $this->cleanVhostStruct($vhost_usr);
// Cycle through the user defined settings
$currentBlock = array();
From 13086d91d85862b676321667024ce47aabbef73b Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 4 Jun 2019 15:14:51 +0200
Subject: [PATCH 013/159] only validate and process ip-list if given at all
Signed-off-by: Michael Kaufmann
---
api_keys.php | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/api_keys.php b/api_keys.php
index fec078e7..0c3126e5 100644
--- a/api_keys.php
+++ b/api_keys.php
@@ -88,15 +88,17 @@ if ($action == 'delete') {
$valid_until = isset($_POST['valid_until']) ? (int) $_POST['valid_until'] : - 1;
// validate allowed_from
- $ip_list = array_map('trim', explode(",", $allowed_from));
- $_check_list = $ip_list;
- foreach ($_check_list as $idx => $ip) {
- if (\Froxlor\Validate\Validate::validate_ip2($ip, true, 'invalidip', true, true) == false) {
- unset($ip_list[$idx]);
+ if (! empty($allowed_from)) {
+ $ip_list = array_map('trim', explode(",", $allowed_from));
+ $_check_list = $ip_list;
+ foreach ($_check_list as $idx => $ip) {
+ if (\Froxlor\Validate\Validate::validate_ip2($ip, true, 'invalidip', true, true) == false) {
+ unset($ip_list[$idx]);
+ }
}
+ $ip_list = array_map('inet_ntop', array_map('inet_pton', $ip_list));
+ $allowed_from = implode(",", array_unique($ip_list));
}
- $ip_list = array_map('inet_ntop', array_map('inet_pton', $ip_list));
- $allowed_from = implode(",", array_unique($ip_list));
if ($valid_until <= 0 || ! is_numeric($valid_until)) {
$valid_until = - 1;
From 97703e7a0cd1c74e79b60d41e9a739d7cc10f164 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Wed, 5 Jun 2019 06:39:44 +0200
Subject: [PATCH 014/159] add a few tests for Settings
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Settings.php | 2 +
tests/Froxlor/SettingsTest.php | 94 ++++++++++++++++++++++++++++++++++
2 files changed, 96 insertions(+)
create mode 100644 tests/Froxlor/SettingsTest.php
diff --git a/lib/Froxlor/Settings.php b/lib/Froxlor/Settings.php
index 88edf132..17dd0c43 100644
--- a/lib/Froxlor/Settings.php
+++ b/lib/Froxlor/Settings.php
@@ -263,6 +263,8 @@ class Settings
self::init();
// empty update array
self::$updatedata = array();
+ // re-read in all settings
+ return self::readSettings();
}
public static function loadSettingsInto(&$settings_data)
diff --git a/tests/Froxlor/SettingsTest.php b/tests/Froxlor/SettingsTest.php
new file mode 100644
index 00000000..b0f9922d
--- /dev/null
+++ b/tests/Froxlor/SettingsTest.php
@@ -0,0 +1,94 @@
+assertEquals("dev.froxlor.org", $syshostname);
+ }
+
+ public function testSettingGetNoSeparator()
+ {
+ $nullval = \Froxlor\Settings::Get('system');
+ $this->assertNull($nullval);
+ }
+
+ public function testSettingGetUnknown()
+ {
+ $nullval = \Froxlor\Settings::Get('thissetting.doesnotexist');
+ $this->assertNull($nullval);
+ }
+
+ public function testSettingsAddNew()
+ {
+ \Froxlor\Settings::AddNew('temp.setting', 'empty');
+ $actval = \Froxlor\Settings::Get('temp.setting');
+ $this->assertEquals("empty", $actval);
+ }
+
+ public function testSettingsAddNewSettingExists()
+ {
+ $result = \Froxlor\Settings::AddNew('system.ipaddress', '127.0.0.1');
+ $this->assertFalse($result);
+ }
+
+ /**
+ *
+ * @depends testSettingsAddNew
+ */
+ public function testSettingSetNoSave()
+ {
+ $actval = \Froxlor\Settings::Get('temp.setting');
+ $this->assertEquals("empty", $actval);
+ \Froxlor\Settings::Set('temp.setting', 'temp-value', false);
+ $tmpval = \Froxlor\Settings::Get('temp.setting');
+ $this->assertEquals("temp-value", $tmpval);
+ \Froxlor\Settings::Stash();
+ $actval = \Froxlor\Settings::Get('temp.setting');
+ $this->assertEquals("empty", $actval);
+ }
+
+ /**
+ *
+ * @depends testSettingsAddNew
+ */
+ public function testSettingsSetInstantSave()
+ {
+ \Froxlor\Settings::Set('temp.setting', 'temp-value');
+ \Froxlor\Settings::Stash();
+ $tmpval = \Froxlor\Settings::Get('temp.setting');
+ $this->assertEquals("temp-value", $tmpval);
+ }
+
+ /**
+ *
+ * @depends testSettingsAddNew
+ */
+ public function testSettingsSetFlushSave()
+ {
+ \Froxlor\Settings::Set('temp.setting', 'another-temp-value', false);
+ \Froxlor\Settings::Flush();
+ $actval = \Froxlor\Settings::Get('temp.setting');
+ $this->assertEquals("another-temp-value", $actval);
+ }
+
+ public function testSettingsIsInList()
+ {
+ $result = \Froxlor\Settings::IsInList("system.mysql_access_host", "localhost");
+ $this->assertTrue($result);
+ $result = \Froxlor\Settings::IsInList("system.mysql_access_host", "my-super-domain.de");
+ $this->assertFalse($result);
+ }
+}
From 13bfd62ac5132c972c11f25f8fce41c0e6a6c6d0 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Wed, 5 Jun 2019 06:50:06 +0200
Subject: [PATCH 015/159] move validateUrl function to correct file
Signed-off-by: Michael Kaufmann
---
customer_domains.php | 2 +-
lib/Froxlor/Api/Commands/DirOptions.php | 2 +-
lib/Froxlor/Api/Commands/SubDomains.php | 4 +-
lib/Froxlor/Cron/Http/Apache.php | 4 +-
lib/Froxlor/Cron/Http/Lighttpd.php | 4 +-
lib/Froxlor/Cron/Http/Nginx.php | 8 ++--
lib/Froxlor/Validate/Form/Data.php | 60 +------------------------
lib/Froxlor/Validate/Validate.php | 56 +++++++++++++++++++++++
8 files changed, 70 insertions(+), 70 deletions(-)
diff --git a/customer_domains.php b/customer_domains.php
index 0e44156f..50681cf2 100644
--- a/customer_domains.php
+++ b/customer_domains.php
@@ -369,7 +369,7 @@ if ($page == 'overview') {
$domains .= \Froxlor\UI\HTML::makeoption($idna_convert->decode($row_domain['domain']), $row_domain['id'], $result['aliasdomain']);
}
- if (preg_match('/^https?\:\/\//', $result['documentroot']) && \Froxlor\Validate\Form\Data::validateUrl($result['documentroot'])) {
+ if (preg_match('/^https?\:\/\//', $result['documentroot']) && \Froxlor\Validate\Validate::validateUrl($result['documentroot'])) {
if (Settings::Get('panel.pathedit') == 'Dropdown') {
$urlvalue = $result['documentroot'];
$pathSelect = \Froxlor\FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']);
diff --git a/lib/Froxlor/Api/Commands/DirOptions.php b/lib/Froxlor/Api/Commands/DirOptions.php
index b2ec7fb4..ad5116b9 100644
--- a/lib/Froxlor/Api/Commands/DirOptions.php
+++ b/lib/Froxlor/Api/Commands/DirOptions.php
@@ -394,7 +394,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
{
if ($errdoc !== null && $errdoc != '') {
// not a URL
- if ((strtoupper(substr($errdoc, 0, 5)) != 'HTTP:' && strtoupper(substr($errdoc, 0, 6)) != 'HTTPS:') || ! \Froxlor\Validate\Form\Data::validateUrl($errdoc)) {
+ if ((strtoupper(substr($errdoc, 0, 5)) != 'HTTP:' && strtoupper(substr($errdoc, 0, 6)) != 'HTTPS:') || ! \Froxlor\Validate\Validate::validateUrl($errdoc)) {
// a file
if (substr($errdoc, 0, 1) != '"') {
$errdoc = \Froxlor\FileDir::makeCorrectFile($errdoc);
diff --git a/lib/Froxlor/Api/Commands/SubDomains.php b/lib/Froxlor/Api/Commands/SubDomains.php
index dbe329e5..4588a73d 100644
--- a/lib/Froxlor/Api/Commands/SubDomains.php
+++ b/lib/Froxlor/Api/Commands/SubDomains.php
@@ -852,7 +852,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
{
// check whether an URL was specified
$_doredirect = false;
- if (! empty($url) && \Froxlor\Validate\Form\Data::validateUrl($url)) {
+ if (! empty($url) && \Froxlor\Validate\Validate::validateUrl($url)) {
$path = $url;
$_doredirect = true;
} else {
@@ -860,7 +860,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
}
// check whether path is a real path
- if (! preg_match('/^https?\:\/\//', $path) || ! \Froxlor\Validate\Form\Data::validateUrl($path)) {
+ if (! preg_match('/^https?\:\/\//', $path) || ! \Froxlor\Validate\Validate::validateUrl($path)) {
if (strstr($path, ":") !== false) {
\Froxlor\UI\Response::standard_error('pathmaynotcontaincolon', '', true);
}
diff --git a/lib/Froxlor/Cron/Http/Apache.php b/lib/Froxlor/Cron/Http/Apache.php
index 2a6a9058..6b7d762b 100644
--- a/lib/Froxlor/Cron/Http/Apache.php
+++ b/lib/Froxlor/Cron/Http/Apache.php
@@ -144,7 +144,7 @@ class Apache extends HttpConfigBase
foreach ($statusCodes as $statusCode) {
if (Settings::Get('defaultwebsrverrhandler.err' . $statusCode) != '') {
$defhandler = Settings::Get('defaultwebsrverrhandler.err' . $statusCode);
- if (! \Froxlor\Validate\Form\Data::validateUrl($defhandler)) {
+ if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) {
if (substr($defhandler, 0, 1) != '"' && substr($defhandler, - 1, 1) != '"') {
$defhandler = '"' . \Froxlor\FileDir::makeCorrectFile($defhandler) . '"';
}
@@ -1209,7 +1209,7 @@ class Apache extends HttpConfigBase
foreach ($statusCodes as $statusCode) {
if (isset($row_diroptions['error' . $statusCode . 'path']) && $row_diroptions['error' . $statusCode . 'path'] != '') {
$defhandler = $row_diroptions['error' . $statusCode . 'path'];
- if (! \Froxlor\Validate\Form\Data::validateUrl($defhandler)) {
+ if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) {
if (substr($defhandler, 0, 1) != '"' && substr($defhandler, - 1, 1) != '"') {
$defhandler = '"' . \Froxlor\FileDir::makeCorrectFile($defhandler) . '"';
}
diff --git a/lib/Froxlor/Cron/Http/Lighttpd.php b/lib/Froxlor/Cron/Http/Lighttpd.php
index 25dd6d95..fd15c2b1 100644
--- a/lib/Froxlor/Cron/Http/Lighttpd.php
+++ b/lib/Froxlor/Cron/Http/Lighttpd.php
@@ -316,7 +316,7 @@ class Lighttpd extends HttpConfigBase
}
$defhandler = Settings::Get('defaultwebsrverrhandler.err404');
- if (! \Froxlor\Validate\Form\Data::validateUrl($defhandler)) {
+ if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) {
$defhandler = \Froxlor\FileDir::makeCorrectFile($defhandler);
}
$this->lighttpd_data[$vhost_filename] = 'server.error-handler-404 = "' . $defhandler . '"';
@@ -707,7 +707,7 @@ class Lighttpd extends HttpConfigBase
if (! empty($row['error404path'])) {
$defhandler = $row['error404path'];
- if (! \Froxlor\Validate\Form\Data::validateUrl($defhandler)) {
+ if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) {
$defhandler = \Froxlor\FileDir::makeCorrectFile($domain['documentroot'] . '/' . $defhandler);
}
$error_string .= ' server.error-handler-404 = "' . $defhandler . '"' . "\n\n";
diff --git a/lib/Froxlor/Cron/Http/Nginx.php b/lib/Froxlor/Cron/Http/Nginx.php
index e38c9a6f..c42f8775 100644
--- a/lib/Froxlor/Cron/Http/Nginx.php
+++ b/lib/Froxlor/Cron/Http/Nginx.php
@@ -137,7 +137,7 @@ class Nginx extends HttpConfigBase
foreach ($statusCodes as $statusCode) {
if (Settings::Get('defaultwebsrverrhandler.err' . $statusCode) != '') {
$defhandler = Settings::Get('defaultwebsrverrhandler.err' . $statusCode);
- if (! \Froxlor\Validate\Form\Data::validateUrl($defhandler)) {
+ if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) {
$defhandler = \Froxlor\FileDir::makeCorrectFile($defhandler);
}
$this->nginx_data[$vhosts_filename] .= 'error_page ' . $statusCode . ' ' . $defhandler . ';' . "\n";
@@ -757,7 +757,7 @@ class Nginx extends HttpConfigBase
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
if (! empty($row['error404path'])) {
$defhandler = $row['error404path'];
- if (! \Froxlor\Validate\Form\Data::validateUrl($defhandler)) {
+ if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) {
$defhandler = \Froxlor\FileDir::makeCorrectFile($defhandler);
}
$path_options .= "\t" . 'error_page 404 ' . $defhandler . ';' . "\n";
@@ -765,7 +765,7 @@ class Nginx extends HttpConfigBase
if (! empty($row['error403path'])) {
$defhandler = $row['error403path'];
- if (! \Froxlor\Validate\Form\Data::validateUrl($defhandler)) {
+ if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) {
$defhandler = \Froxlor\FileDir::makeCorrectFile($defhandler);
}
$path_options .= "\t" . 'error_page 403 ' . $defhandler . ';' . "\n";
@@ -773,7 +773,7 @@ class Nginx extends HttpConfigBase
if (! empty($row['error500path'])) {
$defhandler = $row['error500path'];
- if (! \Froxlor\Validate\Form\Data::validateUrl($defhandler)) {
+ if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) {
$defhandler = \Froxlor\FileDir::makeCorrectFile($defhandler);
}
$path_options .= "\t" . 'error_page 500 502 503 504 ' . $defhandler . ';' . "\n";
diff --git a/lib/Froxlor/Validate/Form/Data.php b/lib/Froxlor/Validate/Form/Data.php
index a746ed17..713266b3 100644
--- a/lib/Froxlor/Validate/Form/Data.php
+++ b/lib/Froxlor/Validate/Form/Data.php
@@ -33,7 +33,7 @@ class Data
if (isset($fielddata['string_type']) && $fielddata['string_type'] == 'mail') {
$returnvalue = (filter_var($newfieldvalue, FILTER_VALIDATE_EMAIL) == $newfieldvalue);
} elseif (isset($fielddata['string_type']) && $fielddata['string_type'] == 'url') {
- $returnvalue = self::validateUrl($newfieldvalue);
+ $returnvalue = \Froxlor\Validate\Validate::validateUrl($newfieldvalue);
} elseif (isset($fielddata['string_type']) && $fielddata['string_type'] == 'dir') {
// check for empty value (it might be allowed)
if (trim($newfieldvalue) == '') {
@@ -128,62 +128,6 @@ class Data
}
}
- /**
- * Returns whether a URL is in a correct format or not
- *
- * @param string $url
- * URL to be tested
- * @return bool
- * @author Christian Hoffmann
- * @author Froxlor team (2010-)
- *
- */
- public static function validateUrl($url)
- {
- if (strtolower(substr($url, 0, 7)) != "http://" && strtolower(substr($url, 0, 8)) != "https://") {
- $url = 'http://' . $url;
- }
-
- // needs converting
- try {
- $idna_convert = new \Froxlor\Idna\IdnaWrapper();
- $url = $idna_convert->encode($url);
- } catch (\Exception $e) {
- return false;
- }
-
- $pattern = '%^(?:(?:https?)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$%iuS';
- if (preg_match($pattern, $url)) {
- return true;
- }
-
- // not an fqdn
- if (strtolower(substr($url, 0, 7)) == "http://" || strtolower(substr($url, 0, 8)) == "https://") {
- if (strtolower(substr($url, 0, 7)) == "http://") {
- $ip = strtolower(substr($url, 7));
- }
-
- if (strtolower(substr($url, 0, 8)) == "https://") {
- $ip = strtolower(substr($url, 8));
- }
-
- $ip = substr($ip, 0, strpos($ip, '/'));
- // possible : in IP (when a port is given), #1173
- // but only if there actually IS ONE
- if (strpos($ip, ':') !== false) {
- $ip = substr($ip, 0, strpos($ip, ':'));
- }
-
- if (\Froxlor\Validate\Validate::validate_ip2($ip, true) !== false) {
- return true;
- } else {
- return false;
- }
- } else {
- return false;
- }
- }
-
public static function validateFormFieldBool($fieldname, $fielddata, $newfieldvalue)
{
if ($newfieldvalue === '1' || $newfieldvalue === 1 || $newfieldvalue === true || strtolower($newfieldvalue) === 'yes' || strtolower($newfieldvalue) === 'ja' || $newfieldvalue === '0' || $newfieldvalue === 0 || $newfieldvalue === false || strtolower($newfieldvalue) === 'no' || strtolower($newfieldvalue) === 'nein' || strtolower($newfieldvalue) === '') {
@@ -252,7 +196,7 @@ class Data
if (isset($fielddata['string_type']) && $fielddata['string_type'] == 'mail') {
$returnvalue = (filter_var($newfieldvalue, FILTER_VALIDATE_EMAIL) == $newfieldvalue);
} elseif (isset($fielddata['string_type']) && $fielddata['string_type'] == 'url') {
- $returnvalue = \Froxlor\Validate\Form\Data::validateUrl($newfieldvalue);
+ $returnvalue = \Froxlor\Validate\Validate::validateUrl($newfieldvalue);
} elseif (isset($fielddata['string_type']) && $fielddata['string_type'] == 'dir') {
// add trailing slash to validate path if needed
// refs #331
diff --git a/lib/Froxlor/Validate/Validate.php b/lib/Froxlor/Validate/Validate.php
index 150bf44a..c6989cd7 100644
--- a/lib/Froxlor/Validate/Validate.php
+++ b/lib/Froxlor/Validate/Validate.php
@@ -122,6 +122,62 @@ class Validate
}
}
+ /**
+ * Returns whether a URL is in a correct format or not
+ *
+ * @param string $url
+ * URL to be tested
+ * @return bool
+ * @author Christian Hoffmann
+ * @author Froxlor team (2010-)
+ *
+ */
+ public static function validateUrl($url)
+ {
+ if (strtolower(substr($url, 0, 7)) != "http://" && strtolower(substr($url, 0, 8)) != "https://") {
+ $url = 'http://' . $url;
+ }
+
+ // needs converting
+ try {
+ $idna_convert = new \Froxlor\Idna\IdnaWrapper();
+ $url = $idna_convert->encode($url);
+ } catch (\Exception $e) {
+ return false;
+ }
+
+ $pattern = '%^(?:(?:https?)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$%iuS';
+ if (preg_match($pattern, $url)) {
+ return true;
+ }
+
+ // not an fqdn
+ if (strtolower(substr($url, 0, 7)) == "http://" || strtolower(substr($url, 0, 8)) == "https://") {
+ if (strtolower(substr($url, 0, 7)) == "http://") {
+ $ip = strtolower(substr($url, 7));
+ }
+
+ if (strtolower(substr($url, 0, 8)) == "https://") {
+ $ip = strtolower(substr($url, 8));
+ }
+
+ $ip = substr($ip, 0, strpos($ip, '/'));
+ // possible : in IP (when a port is given), #1173
+ // but only if there actually IS ONE
+ if (strpos($ip, ':') !== false) {
+ $ip = substr($ip, 0, strpos($ip, ':'));
+ }
+
+ if (\Froxlor\Validate\Validate::validate_ip2($ip, true) !== false) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
/**
* Check if the submitted string is a valid domainname
*
From 4917b9c057928716b534030547f85b64b051128a Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Wed, 5 Jun 2019 09:07:21 +0200
Subject: [PATCH 016/159] added first validation tests
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Validate/Validate.php | 7 +--
tests/Froxlor/ValidateTest.php | 100 ++++++++++++++++++++++++++++++
tests/bootstrap.php | 2 +
3 files changed, 104 insertions(+), 5 deletions(-)
create mode 100644 tests/Froxlor/ValidateTest.php
diff --git a/lib/Froxlor/Validate/Validate.php b/lib/Froxlor/Validate/Validate.php
index c6989cd7..2a767fe6 100644
--- a/lib/Froxlor/Validate/Validate.php
+++ b/lib/Froxlor/Validate/Validate.php
@@ -35,8 +35,8 @@ class Validate
}
// Check if the $str is one of the values which represent the default for an 'empty' value
- if (is_array($emptydefault) && ! empty($emptydefault) && in_array($str, $emptydefault) && isset($emptydefault[0])) {
- return $emptydefault[0];
+ if (is_array($emptydefault) && ! empty($emptydefault) && in_array($str, $emptydefault)) {
+ return $str;
}
if ($pattern == '') {
@@ -61,7 +61,6 @@ class Validate
}
\Froxlor\UI\Response::standard_error($lng, $fieldname, $throw_exception);
- exit();
}
/**
@@ -99,7 +98,6 @@ class Validate
return false;
} else {
\Froxlor\UI\Response::standard_error($lng, $ip, $throw_exception);
- exit();
}
}
@@ -118,7 +116,6 @@ class Validate
return false;
} else {
\Froxlor\UI\Response::standard_error($lng, $ip, $throw_exception);
- exit();
}
}
diff --git a/tests/Froxlor/ValidateTest.php b/tests/Froxlor/ValidateTest.php
new file mode 100644
index 00000000..0c7edb15
--- /dev/null
+++ b/tests/Froxlor/ValidateTest.php
@@ -0,0 +1,100 @@
+assertEquals("user input", $teststr);
+ }
+
+ public function testValidateStrInEmptyDefault()
+ {
+ $teststr = Validate::validate("user input", "test-field", '', '', [
+ "user test",
+ "user input",
+ "user bla"
+ ], true);
+ $this->assertEquals("user input", $teststr);
+ }
+
+ public function testValidateEmptyDefaultNoArray()
+ {
+ $teststr = Validate::validate("user input", "test-field", '', '', "user input", true);
+ $this->assertEquals("user input", $teststr);
+ }
+
+ public function testValidateRemoveNotAllowedChar()
+ {
+ $teststr = Validate::validate("user " . PHP_EOL . "input", "test-field", '', '', [], true);
+ $this->assertEquals("user input", $teststr);
+ }
+
+ public function testValidateStringFormatError()
+ {
+ $this->expectException("Exception");
+ $this->expectExceptionCode(400);
+ Validate::validate("user input", "test-field", '/^[A-Z]+$/i', '', [], true);
+ }
+
+ public function testValidateIp()
+ {
+ $result = Validate::validate_ip2("12.34.56.78", false, 'invalidip', false, false, false, true);
+ $this->assertEquals("12.34.56.78", $result);
+ }
+
+ public function testValidateIpPrivNotAllowed()
+ {
+ $this->expectException("Exception");
+ $this->expectExceptionCode(400);
+ Validate::validate_ip2("10.0.0.1", false, 'invalidip', false, false, false, true);
+ }
+
+ public function testValidateIpPrivNotAllowedBool()
+ {
+ $result = Validate::validate_ip2("10.0.0.1", true, 'invalidip', false, false, false, true);
+ $this->assertFalse($result);
+ }
+
+ public function testValidateIpCidrNotAllowed()
+ {
+ $this->expectException("Exception");
+ $this->expectExceptionCode(400);
+ Validate::validate_ip2("12.34.56.78/24", false, 'invalidip', false, false, false, true);
+ }
+
+ public function testValidateIpCidrNotAllowedBool()
+ {
+ $result = Validate::validate_ip2("12.34.56.78/24", true, 'invalidip', false, false, false, true);
+ $this->assertFalse($result);
+ }
+
+ public function testValidateIpCidr()
+ {
+ $result = Validate::validate_ip2("12.34.56.78/24", false, 'invalidip', false, false, true, true);
+ $this->assertEquals("12.34.56.78/24", $result);
+ }
+
+ public function testValidateIpLocalhostAllowed()
+ {
+ $result = Validate::validate_ip2("127.0.0.1/32", false, 'invalidip', true, false, true, true);
+ $this->assertEquals("127.0.0.1/32", $result);
+ }
+
+ public function testValidateIpLocalhostAllowedWrongIp()
+ {
+ $this->expectException("Exception");
+ $this->expectExceptionCode(400);
+ Validate::validate_ip2("127.0.0.2", false, 'invalidip', true, false, false, true);
+ }
+}
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index 87344530..5b2f1210 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -148,6 +148,8 @@ $sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_ADMINS . "` WHERE
$admin_userdata = Database::pexecute_first($sel_stmt);
$admin_userdata['adminsession'] = 1;
+$log = \Froxlor\FroxlorLogger::getInstanceOf($admin_userdata);
+
Settings::Set('panel.standardlanguage', 'English', true);
Settings::Set('panel.adminmail', 'admin@dev.froxlor.org', true);
Settings::Set('panel.allow_domain_change_admin', '1', true);
From 0afbe3d13b67d439177ae23a4f60028b91cc7687 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Wed, 5 Jun 2019 20:52:37 +0200
Subject: [PATCH 017/159] add validation tests
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Database/Database.php | 15 +++++
lib/Froxlor/Validate/Validate.php | 105 ++++++++++++------------------
tests/Froxlor/ValidateTest.php | 99 ++++++++++++++++++++++++++++
3 files changed, 157 insertions(+), 62 deletions(-)
diff --git a/lib/Froxlor/Database/Database.php b/lib/Froxlor/Database/Database.php
index 466a948e..ccf5ad3b 100644
--- a/lib/Froxlor/Database/Database.php
+++ b/lib/Froxlor/Database/Database.php
@@ -183,6 +183,21 @@ class Database
return $return;
}
+ /**
+ * return number of characters that are allowed to use as username
+ *
+ * @return int
+ */
+ public static function getSqlUsernameLength()
+ {
+ // MySQL user names can be up to 32 characters long (16 characters before MySQL 5.7.8).
+ $mysql_max = 32;
+ if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.8', '<')) {
+ $mysql_max -= 16;
+ }
+ return $mysql_max;
+ }
+
/**
* let's us interact with the PDO-Object by using static
* call like "Database::function()"
diff --git a/lib/Froxlor/Validate/Validate.php b/lib/Froxlor/Validate/Validate.php
index 2a767fe6..3e77b595 100644
--- a/lib/Froxlor/Validate/Validate.php
+++ b/lib/Froxlor/Validate/Validate.php
@@ -124,10 +124,8 @@ class Validate
*
* @param string $url
* URL to be tested
+ *
* @return bool
- * @author Christian Hoffmann
- * @author Froxlor team (2010-)
- *
*/
public static function validateUrl($url)
{
@@ -148,31 +146,7 @@ class Validate
return true;
}
- // not an fqdn
- if (strtolower(substr($url, 0, 7)) == "http://" || strtolower(substr($url, 0, 8)) == "https://") {
- if (strtolower(substr($url, 0, 7)) == "http://") {
- $ip = strtolower(substr($url, 7));
- }
-
- if (strtolower(substr($url, 0, 8)) == "https://") {
- $ip = strtolower(substr($url, 8));
- }
-
- $ip = substr($ip, 0, strpos($ip, '/'));
- // possible : in IP (when a port is given), #1173
- // but only if there actually IS ONE
- if (strpos($ip, ':') !== false) {
- $ip = substr($ip, 0, strpos($ip, ':'));
- }
-
- if (\Froxlor\Validate\Validate::validate_ip2($ip, true) !== false) {
- return true;
- } else {
- return false;
- }
- } else {
- return false;
- }
+ return false;
}
/**
@@ -210,7 +184,7 @@ class Validate
*/
public static function validateLocalHostname($hostname)
{
- $pattern = '/^([a-zA-Z0-9\-])+$/i';
+ $pattern = '/^[a-z0-9][a-z0-9\-]{0,62}$/i';
if (preg_match($pattern, $hostname)) {
return $hostname;
}
@@ -233,52 +207,59 @@ class Validate
/**
* Returns if an username is in correct format or not.
*
- * @param
- * string The username to check
- * @return bool Correct or not
- * @author Michael Duergner
- *
+ * @param string $username
+ * The username to check
+ * @param bool $unix_names
+ * optional, default true, checks whether it must be UNIX compatible
+ * @param int $mysql_max
+ * optional, number of max mysql username characters, default empty
+ *
+ * @return bool
*/
public static function validateUsername($username, $unix_names = 1, $mysql_max = '')
{
+ if (empty($mysql_max) || ! is_numeric($mysql_max) || $mysql_max <= 0) {
+ $mysql_max = \Froxlor\Database\Database::getSqlUsernameLength() - 1;
+ } else {
+ $mysql_max --;
+ }
if ($unix_names == 0) {
if (strpos($username, '--') === false) {
- return (preg_match('/^[a-z][a-z0-9\-_]{0,' . (int) ($mysql_max - 1) . '}[a-z0-9]{1}$/Di', $username) != false);
- } else {
- return false;
+ return (preg_match('/^[a-z][a-z0-9\-_]{0,' . $mysql_max . '}[a-z0-9]{1}$/Di', $username) != false);
}
- } else {
- return (preg_match('/^[a-z][a-z0-9]{0,' . $mysql_max . '}$/Di', $username) != false);
+ return false;
}
+ return (preg_match('/^[a-z][a-z0-9]{0,' . $mysql_max . '}$/Di', $username) != false);
}
+ /**
+ * validate sql interval string
+ *
+ * @param string $interval
+ *
+ * @return boolean
+ */
public static function validateSqlInterval($interval = null)
{
- if (! $interval === null || $interval != '') {
- if (strstr($interval, ' ') !== false) {
- /*
- * [0] = ([0-9]+)
- * [1] = valid SQL-Interval expression
- */
- $valid_expr = array(
- 'SECOND',
- 'MINUTE',
- 'HOUR',
- 'DAY',
- 'WEEK',
- 'MONTH',
- 'YEAR'
- );
+ if (! empty($interval) && strstr($interval, ' ') !== false) {
+ /*
+ * [0] = ([0-9]+)
+ * [1] = valid SQL-Interval expression
+ */
+ $valid_expr = array(
+ 'SECOND',
+ 'MINUTE',
+ 'HOUR',
+ 'DAY',
+ 'WEEK',
+ 'MONTH',
+ 'YEAR'
+ );
- $interval_parts = explode(' ', $interval);
+ $interval_parts = explode(' ', $interval);
- if (is_array($interval_parts) && isset($interval_parts[0]) && isset($interval_parts[1])) {
- if (preg_match('/([0-9]+)/i', $interval_parts[0])) {
- if (in_array(strtoupper($interval_parts[1]), $valid_expr)) {
- return true;
- }
- }
- }
+ if (count($interval_parts) == 2 && preg_match('/[0-9]+/', $interval_parts[0]) && in_array(strtoupper($interval_parts[1]), $valid_expr)) {
+ return true;
}
}
return false;
diff --git a/tests/Froxlor/ValidateTest.php b/tests/Froxlor/ValidateTest.php
index 0c7edb15..a47dba82 100644
--- a/tests/Froxlor/ValidateTest.php
+++ b/tests/Froxlor/ValidateTest.php
@@ -8,6 +8,7 @@ use Froxlor\Validate\Validate;
* @covers \Froxlor\Validate\Validate
* @covers \Froxlor\UI\Response
* @covers \Froxlor\FroxlorLogger
+ * @covers \Froxlor\Idna\IdnaWrapper
*/
class ValidateTest extends TestCase
{
@@ -97,4 +98,102 @@ class ValidateTest extends TestCase
$this->expectExceptionCode(400);
Validate::validate_ip2("127.0.0.2", false, 'invalidip', true, false, false, true);
}
+
+ public function testValidateUrl()
+ {
+ $result = Validate::validateUrl("https://froxlor.org/");
+ $this->assertTrue($result);
+ $result = Validate::validateUrl("http://forum.froxlor.org/");
+ $this->assertTrue($result);
+ $result = Validate::validateUrl("https://api.froxlor.org/doc/0.10.0/index.php");
+ $this->assertTrue($result);
+ $result = Validate::validateUrl("#froxlor");
+ $this->assertFalse($result);
+ $result = Validate::validateUrl("https://82.149.225.211/");
+ $this->assertTrue($result);
+ $result = Validate::validateUrl("https://82.149.225.300");
+ $this->assertFalse($result);
+ $result = Validate::validateUrl("82.149.225.211:443");
+ $this->assertTrue($result);
+ }
+
+ public function testValidateDomain()
+ {
+ $result = Validate::validateDomain('froxlor.org');
+ $this->assertEquals('froxlor.org', $result);
+ $result = Validate::validateDomain('_dmarc.froxlor.org');
+ $this->assertFalse($result);
+ $result = Validate::validateDomain('_dmarc.froxlor.org', true);
+ $this->assertEquals('_dmarc.froxlor.org', $result);
+ $result = Validate::validateDomain('test._dmarc.froxlor.org', true);
+ $this->assertEquals('test._dmarc.froxlor.org', $result);
+ $result = Validate::validateDomain('0815');
+ $this->assertFalse($result);
+ $result = Validate::validateDomain('abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz');
+ $this->assertFalse($result);
+ }
+
+ public function testValidateHostname()
+ {
+ $result = Validate::validateLocalHostname('localhost');
+ $this->assertEquals('localhost', $result);
+ $result = Validate::validateLocalHostname('froxlor-srv02');
+ $this->assertEquals('froxlor-srv02', $result);
+ $result = Validate::validateLocalHostname('froxlor_org');
+ $this->assertFalse($result);
+ $result = Validate::validateLocalHostname('froxlor.org');
+ $this->assertFalse($result);
+ $result = Validate::validateLocalHostname('a--------------------------------------------------------------');
+ $this->assertEquals('a--------------------------------------------------------------', $result);
+ $result = Validate::validateLocalHostname('-hostname');
+ $this->assertFalse($result);
+ $result = Validate::validateLocalHostname('a-----------------------------------------------------------------');
+ $this->assertFalse($result);
+ }
+
+ public function testValidateEmail()
+ {
+ $result = Validate::validateEmail('team@froxlor.org');
+ $this->assertEquals('team@froxlor.org', $result);
+ $result = Validate::validateEmail('team.froxlor.org');
+ $this->assertFalse($result);
+ }
+
+ public function testValidateUsername()
+ {
+ $result = Validate::validateUsername('web123sql2');
+ $this->assertTrue($result);
+ $mysql_max = \Froxlor\Database\Database::getSqlUsernameLength() - strlen(\Froxlor\Settings::Get('customer.mysqlprefix'));
+ $result = Validate::validateUsername('web123sql2', true, $mysql_max);
+ $this->assertTrue($result);
+ // too long
+ $result = Validate::validateUsername('myperfectsuperduperwebuser123sql2', true, $mysql_max);
+ $this->assertFalse($result);
+ // not unix-conform
+ $result = Validate::validateUsername('web123-sql2', true, $mysql_max);
+ $this->assertFalse($result);
+ // non-unix-conform
+ $result = Validate::validateUsername('web123-sql2', false, $mysql_max);
+ $this->assertTrue($result);
+ $result = Validate::validateUsername('web123--sql2', false, $mysql_max);
+ $this->assertFalse($result);
+ $result = Validate::validateUsername('-web123sql2', false, $mysql_max);
+ $this->assertFalse($result);
+ $result = Validate::validateUsername('web123sql2-', false, $mysql_max);
+ $this->assertFalse($result);
+ }
+
+ public function testValidateSqlInterval()
+ {
+ $result = Validate::validateSqlInterval('60 HOUR');
+ $this->assertTrue($result);
+ $result = Validate::validateSqlInterval('2 MONTH');
+ $this->assertTrue($result);
+ $result = Validate::validateSqlInterval();
+ $this->assertFalse($result);
+ $result = Validate::validateSqlInterval('2 QUARTER');
+ $this->assertFalse($result);
+ $result = Validate::validateSqlInterval('1DAY');
+ $this->assertFalse($result);
+ }
}
From d8a8f76dc95866decedc8851f9690ce1fc4b5752 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Thu, 6 Jun 2019 10:18:03 +0200
Subject: [PATCH 018/159] update dev-environment to use more recent versions,
requries php-7.3 now (dev-only)
Signed-off-by: Michael Kaufmann
---
.travis.yml | 6 +-
build.xml | 17 +-
composer.json | 19 +-
composer.lock | 871 +++++++++++--------------
lib/Froxlor/Api/Commands/Customers.php | 7 +-
lib/Froxlor/Database/Database.php | 2 +-
lib/Froxlor/Validate/Check.php | 2 +-
phpunit.xml | 10 +-
tests/Customers/CustomersTest.php | 2 +-
tests/Froxlor/SettingsTest.php | 3 +-
tests/Traffic/TrafficTest.php | 2 +-
11 files changed, 439 insertions(+), 502 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index b751d37c..5014b70f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,8 +4,8 @@ php:
# - "5.4"
# - "5.6"
# - "7.0"
- - "7.1"
-# - "7.2"
+# - "7.1"
+ - "7.3"
branches:
only:
@@ -18,7 +18,7 @@ matrix:
# env: deps=highest
# - php: 5.4
# env: deps=lowest
- - php: 7.1
+ - php: 7.3
env: deps=highest
mysql:
diff --git a/build.xml b/build.xml
index 291013db..150eebdc 100644
--- a/build.xml
+++ b/build.xml
@@ -226,7 +226,20 @@
-
+
+
+
+
+
+
+
+
+
+
+
@@ -234,6 +247,8 @@
+
+
diff --git a/composer.json b/composer.json
index 4299118e..2b715393 100644
--- a/composer.json
+++ b/composer.json
@@ -49,17 +49,16 @@
"algo26-matthias/idna-convert": "^2.1"
},
"require-dev": {
- "phpunit/phpunit": "6.5.13",
- "pdepend/pdepend": "2.5.0",
- "phpmd/phpmd": "2.6.0",
- "sebastian/phpcpd": "3.0.1",
- "squizlabs/php_codesniffer": "3.3.2",
- "phploc/phploc": "3.0.1",
- "theseer/phpdox": "0.11.2",
- "phpunit/php-invoker": "1.1.4",
- "php": ">=7.1",
+ "phpunit/phpunit": "^8",
+ "php": ">=7.3",
"ext-pcntl": "*",
- "phpcompatibility/php-compatibility": "*"
+ "phpcompatibility/php-compatibility": "*",
+ "squizlabs/php_codesniffer": "*",
+ "pdepend/pdepend": "^2.5",
+ "sebastian/phpcpd": "^4.1",
+ "theseer/phpdox": "^0.12.0",
+ "phploc/phploc": "^5.0",
+ "phpmd/phpmd": "^2.6"
},
"suggest": {
"ext-bcmath": "*",
diff --git a/composer.lock b/composer.lock
index bbfe2827..21eb30fb 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": "5a09e82c87504e904337a4fc8a80e3a8",
+ "content-hash": "5be3ef1341b33f64d1eab9a4afa10f20",
"packages": [
{
"name": "algo26-matthias/idna-convert",
@@ -247,16 +247,16 @@
},
{
"name": "robthree/twofactorauth",
- "version": "1.6.5",
+ "version": "1.6.6",
"source": {
"type": "git",
"url": "https://github.com/RobThree/TwoFactorAuth.git",
- "reference": "f5f58a4c62d0336a0e6175856894a51f3565dad2"
+ "reference": "7477d5d65625b7fe33cb338b98e419d394e9e9fd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/f5f58a4c62d0336a0e6175856894a51f3565dad2",
- "reference": "f5f58a4c62d0336a0e6175856894a51f3565dad2",
+ "url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/7477d5d65625b7fe33cb338b98e419d394e9e9fd",
+ "reference": "7477d5d65625b7fe33cb338b98e419d394e9e9fd",
"shasum": ""
},
"require": {
@@ -294,33 +294,35 @@
"php",
"tfa"
],
- "time": "2018-06-09T10:09:59+00:00"
+ "time": "2019-03-19T21:51:19+00:00"
}
],
"packages-dev": [
{
"name": "doctrine/instantiator",
- "version": "1.1.0",
+ "version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
- "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda"
+ "reference": "a2c590166b2133a4633738648b6b064edae0814a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda",
- "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda",
+ "url": "https://api.github.com/repos/doctrine/instantiator/zipball/a2c590166b2133a4633738648b6b064edae0814a",
+ "reference": "a2c590166b2133a4633738648b6b064edae0814a",
"shasum": ""
},
"require": {
"php": "^7.1"
},
"require-dev": {
- "athletic/athletic": "~0.1.8",
+ "doctrine/coding-standard": "^6.0",
"ext-pdo": "*",
"ext-phar": "*",
- "phpunit/phpunit": "^6.2.3",
- "squizlabs/php_codesniffer": "^3.0.2"
+ "phpbench/phpbench": "^0.13",
+ "phpstan/phpstan-phpunit": "^0.11",
+ "phpstan/phpstan-shim": "^0.11",
+ "phpunit/phpunit": "^7.0"
},
"type": "library",
"extra": {
@@ -345,25 +347,25 @@
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
- "homepage": "https://github.com/doctrine/instantiator",
+ "homepage": "https://www.doctrine-project.org/projects/instantiator.html",
"keywords": [
"constructor",
"instantiate"
],
- "time": "2017-07-22T11:58:36+00:00"
+ "time": "2019-03-17T17:37:11+00:00"
},
{
"name": "myclabs/deep-copy",
- "version": "1.8.1",
+ "version": "1.9.1",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
- "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8"
+ "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8",
- "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72",
+ "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72",
"shasum": ""
},
"require": {
@@ -398,28 +400,28 @@
"object",
"object graph"
],
- "time": "2018-06-11T23:09:50+00:00"
+ "time": "2019-04-07T13:18:21+00:00"
},
{
"name": "nikic/php-parser",
- "version": "v3.1.5",
+ "version": "v4.2.2",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "bb87e28e7d7b8d9a7fda231d37457c9210faf6ce"
+ "reference": "1bd73cc04c3843ad8d6b0bfc0956026a151fc420"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/bb87e28e7d7b8d9a7fda231d37457c9210faf6ce",
- "reference": "bb87e28e7d7b8d9a7fda231d37457c9210faf6ce",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bd73cc04c3843ad8d6b0bfc0956026a151fc420",
+ "reference": "1bd73cc04c3843ad8d6b0bfc0956026a151fc420",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
- "php": ">=5.5"
+ "php": ">=7.0"
},
"require-dev": {
- "phpunit/phpunit": "~4.0|~5.0"
+ "phpunit/phpunit": "^6.5 || ^7.0"
},
"bin": [
"bin/php-parse"
@@ -427,7 +429,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.0-dev"
+ "dev-master": "4.2-dev"
}
},
"autoload": {
@@ -449,30 +451,30 @@
"parser",
"php"
],
- "time": "2018-02-28T20:30:58+00:00"
+ "time": "2019-05-25T20:07:01+00:00"
},
{
"name": "pdepend/pdepend",
- "version": "2.5.0",
+ "version": "2.5.2",
"source": {
"type": "git",
"url": "https://github.com/pdepend/pdepend.git",
- "reference": "0c50874333149c0dad5a2877801aed148f2767ff"
+ "reference": "9daf26d0368d4a12bed1cacae1a9f3a6f0adf239"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/pdepend/pdepend/zipball/0c50874333149c0dad5a2877801aed148f2767ff",
- "reference": "0c50874333149c0dad5a2877801aed148f2767ff",
+ "url": "https://api.github.com/repos/pdepend/pdepend/zipball/9daf26d0368d4a12bed1cacae1a9f3a6f0adf239",
+ "reference": "9daf26d0368d4a12bed1cacae1a9f3a6f0adf239",
"shasum": ""
},
"require": {
"php": ">=5.3.7",
- "symfony/config": "^2.3.0|^3",
- "symfony/dependency-injection": "^2.3.0|^3",
- "symfony/filesystem": "^2.3.0|^3"
+ "symfony/config": "^2.3.0|^3|^4",
+ "symfony/dependency-injection": "^2.3.0|^3|^4",
+ "symfony/filesystem": "^2.3.0|^3|^4"
},
"require-dev": {
- "phpunit/phpunit": "^4.4.0,<4.8",
+ "phpunit/phpunit": "^4.8|^5.7",
"squizlabs/php_codesniffer": "^2.0.0"
},
"bin": [
@@ -489,26 +491,26 @@
"BSD-3-Clause"
],
"description": "Official version of pdepend to be handled with Composer",
- "time": "2017-01-19T14:23:36+00:00"
+ "time": "2017-12-13T13:21:38+00:00"
},
{
"name": "phar-io/manifest",
- "version": "1.0.1",
+ "version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/phar-io/manifest.git",
- "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0"
+ "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0",
- "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0",
+ "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4",
+ "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-phar": "*",
- "phar-io/version": "^1.0.1",
+ "phar-io/version": "^2.0",
"php": "^5.6 || ^7.0"
},
"type": "library",
@@ -544,20 +546,20 @@
}
],
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
- "time": "2017-03-05T18:14:27+00:00"
+ "time": "2018-07-08T19:23:20+00:00"
},
{
"name": "phar-io/version",
- "version": "1.0.1",
+ "version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/phar-io/version.git",
- "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df"
+ "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df",
- "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df",
+ "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6",
+ "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6",
"shasum": ""
},
"require": {
@@ -591,7 +593,7 @@
}
],
"description": "Library for handling version information and constraints",
- "time": "2017-03-05T17:38:23+00:00"
+ "time": "2018-07-08T19:19:57+00:00"
},
{
"name": "phpcompatibility/php-compatibility",
@@ -707,16 +709,16 @@
},
{
"name": "phpdocumentor/reflection-docblock",
- "version": "4.3.0",
+ "version": "4.3.1",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
- "reference": "94fd0001232e47129dd3504189fa1c7225010d08"
+ "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08",
- "reference": "94fd0001232e47129dd3504189fa1c7225010d08",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c",
+ "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c",
"shasum": ""
},
"require": {
@@ -754,7 +756,7 @@
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
- "time": "2017-11-30T07:14:17+00:00"
+ "time": "2019-04-30T17:48:53+00:00"
},
{
"name": "phpdocumentor/type-resolver",
@@ -805,27 +807,23 @@
},
{
"name": "phploc/phploc",
- "version": "3.0.1",
+ "version": "5.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phploc.git",
- "reference": "74f917e6f80f291856989960d31afa44a4196859"
+ "reference": "5b714ccb7cb8ca29ccf9caf6eb1aed0131d3a884"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phploc/zipball/74f917e6f80f291856989960d31afa44a4196859",
- "reference": "74f917e6f80f291856989960d31afa44a4196859",
+ "url": "https://api.github.com/repos/sebastianbergmann/phploc/zipball/5b714ccb7cb8ca29ccf9caf6eb1aed0131d3a884",
+ "reference": "5b714ccb7cb8ca29ccf9caf6eb1aed0131d3a884",
"shasum": ""
},
"require": {
- "php": ">=5.6",
- "sebastian/finder-facade": "~1.1",
- "sebastian/git": "~2.1",
- "sebastian/version": "~1.0.3|~2.0",
- "symfony/console": "~2.5|~3.0"
- },
- "require-dev": {
- "phpunit/phpunit": "~5"
+ "php": "^7.2",
+ "sebastian/finder-facade": "^1.1",
+ "sebastian/version": "^2.0",
+ "symfony/console": "^4.0"
},
"bin": [
"phploc"
@@ -833,7 +831,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.0-dev"
+ "dev-master": "5.0-dev"
}
},
"autoload": {
@@ -854,7 +852,7 @@
],
"description": "A tool for quickly measuring the size of a PHP project.",
"homepage": "https://github.com/sebastianbergmann/phploc",
- "time": "2016-04-25T08:11:21+00:00"
+ "time": "2019-03-16T10:41:19+00:00"
},
{
"name": "phpmd/phpmd",
@@ -987,40 +985,40 @@
},
{
"name": "phpunit/php-code-coverage",
- "version": "5.3.2",
+ "version": "7.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "c89677919c5dd6d3b3852f230a663118762218ac"
+ "reference": "6024c8a6cb962d496b7bd049ed8f48473824176d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c89677919c5dd6d3b3852f230a663118762218ac",
- "reference": "c89677919c5dd6d3b3852f230a663118762218ac",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6024c8a6cb962d496b7bd049ed8f48473824176d",
+ "reference": "6024c8a6cb962d496b7bd049ed8f48473824176d",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-xmlwriter": "*",
- "php": "^7.0",
- "phpunit/php-file-iterator": "^1.4.2",
+ "php": "^7.2",
+ "phpunit/php-file-iterator": "^2.0.2",
"phpunit/php-text-template": "^1.2.1",
- "phpunit/php-token-stream": "^2.0.1",
+ "phpunit/php-token-stream": "^3.0.1",
"sebastian/code-unit-reverse-lookup": "^1.0.1",
- "sebastian/environment": "^3.0",
+ "sebastian/environment": "^4.1",
"sebastian/version": "^2.0.1",
"theseer/tokenizer": "^1.1"
},
"require-dev": {
- "phpunit/phpunit": "^6.0"
+ "phpunit/phpunit": "^8.0"
},
"suggest": {
- "ext-xdebug": "^2.5.5"
+ "ext-xdebug": "^2.6.1"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.3.x-dev"
+ "dev-master": "7.0-dev"
}
},
"autoload": {
@@ -1046,29 +1044,32 @@
"testing",
"xunit"
],
- "time": "2018-04-06T15:36:58+00:00"
+ "time": "2019-05-29T09:59:31+00:00"
},
{
"name": "phpunit/php-file-iterator",
- "version": "1.4.5",
+ "version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
- "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4"
+ "reference": "050bedf145a257b1ff02746c31894800e5122946"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4",
- "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946",
+ "reference": "050bedf145a257b1ff02746c31894800e5122946",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": "^7.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.1"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.4.x-dev"
+ "dev-master": "2.0.x-dev"
}
},
"autoload": {
@@ -1080,53 +1081,6 @@
"license": [
"BSD-3-Clause"
],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sb@sebastian-bergmann.de",
- "role": "lead"
- }
- ],
- "description": "FilterIterator implementation that filters files based on a list of suffixes.",
- "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
- "keywords": [
- "filesystem",
- "iterator"
- ],
- "time": "2017-11-27T13:52:08+00:00"
- },
- {
- "name": "phpunit/php-invoker",
- "version": "1.1.4",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/php-invoker.git",
- "reference": "86074bf0fc2caf02ec8819a93f65a37cd0b44c8e"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/86074bf0fc2caf02ec8819a93f65a37cd0b44c8e",
- "reference": "86074bf0fc2caf02ec8819a93f65a37cd0b44c8e",
- "shasum": ""
- },
- "require": {
- "ext-pcntl": "*",
- "php": ">=5.3.3",
- "phpunit/php-timer": ">=1.0.6"
- },
- "require-dev": {
- "phpunit/phpunit": "~4"
- },
- "type": "library",
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
"authors": [
{
"name": "Sebastian Bergmann",
@@ -1134,12 +1088,13 @@
"role": "lead"
}
],
- "description": "Utility class for invoking callables with a timeout.",
- "homepage": "https://github.com/sebastianbergmann/php-invoker/",
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+ "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
"keywords": [
- "process"
+ "filesystem",
+ "iterator"
],
- "time": "2015-06-21T13:32:55+00:00"
+ "time": "2018-09-13T20:33:42+00:00"
},
{
"name": "phpunit/php-text-template",
@@ -1184,28 +1139,28 @@
},
{
"name": "phpunit/php-timer",
- "version": "1.0.9",
+ "version": "2.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
- "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f"
+ "reference": "8b389aebe1b8b0578430bda0c7c95a829608e059"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
- "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b389aebe1b8b0578430bda0c7c95a829608e059",
+ "reference": "8b389aebe1b8b0578430bda0c7c95a829608e059",
"shasum": ""
},
"require": {
- "php": "^5.3.3 || ^7.0"
+ "php": "^7.1"
},
"require-dev": {
- "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
+ "phpunit/phpunit": "^7.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0-dev"
+ "dev-master": "2.1-dev"
}
},
"autoload": {
@@ -1220,7 +1175,7 @@
"authors": [
{
"name": "Sebastian Bergmann",
- "email": "sb@sebastian-bergmann.de",
+ "email": "sebastian@phpunit.de",
"role": "lead"
}
],
@@ -1229,33 +1184,33 @@
"keywords": [
"timer"
],
- "time": "2017-02-26T11:10:40+00:00"
+ "time": "2019-02-20T10:12:59+00:00"
},
{
"name": "phpunit/php-token-stream",
- "version": "2.0.2",
+ "version": "3.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
- "reference": "791198a2c6254db10131eecfe8c06670700904db"
+ "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db",
- "reference": "791198a2c6254db10131eecfe8c06670700904db",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c99e3be9d3e85f60646f152f9002d46ed7770d18",
+ "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
- "php": "^7.0"
+ "php": "^7.1"
},
"require-dev": {
- "phpunit/phpunit": "^6.2.4"
+ "phpunit/phpunit": "^7.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.0-dev"
+ "dev-master": "3.0-dev"
}
},
"autoload": {
@@ -1278,57 +1233,55 @@
"keywords": [
"tokenizer"
],
- "time": "2017-11-27T05:48:46+00:00"
+ "time": "2018-10-30T05:52:18+00:00"
},
{
"name": "phpunit/phpunit",
- "version": "6.5.13",
+ "version": "8.1.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "0973426fb012359b2f18d3bd1e90ef1172839693"
+ "reference": "e3c9da6e645492c461e0a11eca117f83f4f4c840"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0973426fb012359b2f18d3bd1e90ef1172839693",
- "reference": "0973426fb012359b2f18d3bd1e90ef1172839693",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e3c9da6e645492c461e0a11eca117f83f4f4c840",
+ "reference": "e3c9da6e645492c461e0a11eca117f83f4f4c840",
"shasum": ""
},
"require": {
+ "doctrine/instantiator": "^1.1",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xml": "*",
- "myclabs/deep-copy": "^1.6.1",
- "phar-io/manifest": "^1.0.1",
- "phar-io/version": "^1.0",
- "php": "^7.0",
+ "ext-xmlwriter": "*",
+ "myclabs/deep-copy": "^1.7",
+ "phar-io/manifest": "^1.0.2",
+ "phar-io/version": "^2.0",
+ "php": "^7.2",
"phpspec/prophecy": "^1.7",
- "phpunit/php-code-coverage": "^5.3",
- "phpunit/php-file-iterator": "^1.4.3",
+ "phpunit/php-code-coverage": "^7.0",
+ "phpunit/php-file-iterator": "^2.0.1",
"phpunit/php-text-template": "^1.2.1",
- "phpunit/php-timer": "^1.0.9",
- "phpunit/phpunit-mock-objects": "^5.0.9",
- "sebastian/comparator": "^2.1",
- "sebastian/diff": "^2.0",
- "sebastian/environment": "^3.1",
+ "phpunit/php-timer": "^2.1",
+ "sebastian/comparator": "^3.0",
+ "sebastian/diff": "^3.0",
+ "sebastian/environment": "^4.1",
"sebastian/exporter": "^3.1",
- "sebastian/global-state": "^2.0",
+ "sebastian/global-state": "^3.0",
"sebastian/object-enumerator": "^3.0.3",
- "sebastian/resource-operations": "^1.0",
+ "sebastian/resource-operations": "^2.0",
"sebastian/version": "^2.0.1"
},
- "conflict": {
- "phpdocumentor/reflection-docblock": "3.0.2",
- "phpunit/dbunit": "<3.0"
- },
"require-dev": {
"ext-pdo": "*"
},
"suggest": {
+ "ext-soap": "*",
"ext-xdebug": "*",
- "phpunit/php-invoker": "^1.1"
+ "phpunit/php-invoker": "^2.0"
},
"bin": [
"phpunit"
@@ -1336,7 +1289,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "6.5.x-dev"
+ "dev-master": "8.1-dev"
}
},
"autoload": {
@@ -1362,67 +1315,7 @@
"testing",
"xunit"
],
- "time": "2018-09-08T15:10:43+00:00"
- },
- {
- "name": "phpunit/phpunit-mock-objects",
- "version": "5.0.10",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
- "reference": "cd1cf05c553ecfec36b170070573e540b67d3f1f"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/cd1cf05c553ecfec36b170070573e540b67d3f1f",
- "reference": "cd1cf05c553ecfec36b170070573e540b67d3f1f",
- "shasum": ""
- },
- "require": {
- "doctrine/instantiator": "^1.0.5",
- "php": "^7.0",
- "phpunit/php-text-template": "^1.2.1",
- "sebastian/exporter": "^3.1"
- },
- "conflict": {
- "phpunit/phpunit": "<6.0"
- },
- "require-dev": {
- "phpunit/phpunit": "^6.5.11"
- },
- "suggest": {
- "ext-soap": "*"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "5.0.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
- }
- ],
- "description": "Mock Object library for PHPUnit",
- "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
- "keywords": [
- "mock",
- "xunit"
- ],
- "abandoned": true,
- "time": "2018-08-09T05:50:03+00:00"
+ "time": "2019-05-28T11:53:42+00:00"
},
{
"name": "psr/container",
@@ -1520,30 +1413,30 @@
},
{
"name": "sebastian/comparator",
- "version": "2.1.3",
+ "version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9"
+ "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9",
- "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da",
+ "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da",
"shasum": ""
},
"require": {
- "php": "^7.0",
- "sebastian/diff": "^2.0 || ^3.0",
+ "php": "^7.1",
+ "sebastian/diff": "^3.0",
"sebastian/exporter": "^3.1"
},
"require-dev": {
- "phpunit/phpunit": "^6.4"
+ "phpunit/phpunit": "^7.1"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.1.x-dev"
+ "dev-master": "3.0-dev"
}
},
"autoload": {
@@ -1580,32 +1473,33 @@
"compare",
"equality"
],
- "time": "2018-02-01T13:46:46+00:00"
+ "time": "2018-07-12T15:12:46+00:00"
},
{
"name": "sebastian/diff",
- "version": "2.0.1",
+ "version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
- "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd"
+ "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/347c1d8b49c5c3ee30c7040ea6fc446790e6bddd",
- "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29",
+ "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29",
"shasum": ""
},
"require": {
- "php": "^7.0"
+ "php": "^7.1"
},
"require-dev": {
- "phpunit/phpunit": "^6.2"
+ "phpunit/phpunit": "^7.5 || ^8.0",
+ "symfony/process": "^2 || ^3.3 || ^4"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.0-dev"
+ "dev-master": "3.0-dev"
}
},
"autoload": {
@@ -1630,34 +1524,40 @@
"description": "Diff implementation",
"homepage": "https://github.com/sebastianbergmann/diff",
"keywords": [
- "diff"
+ "diff",
+ "udiff",
+ "unidiff",
+ "unified diff"
],
- "time": "2017-08-03T08:09:46+00:00"
+ "time": "2019-02-04T06:01:07+00:00"
},
{
"name": "sebastian/environment",
- "version": "3.1.0",
+ "version": "4.2.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
- "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5"
+ "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5",
- "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/f2a2c8e1c97c11ace607a7a667d73d47c19fe404",
+ "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404",
"shasum": ""
},
"require": {
- "php": "^7.0"
+ "php": "^7.1"
},
"require-dev": {
- "phpunit/phpunit": "^6.1"
+ "phpunit/phpunit": "^7.5"
+ },
+ "suggest": {
+ "ext-posix": "*"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.1.x-dev"
+ "dev-master": "4.2-dev"
}
},
"autoload": {
@@ -1682,7 +1582,7 @@
"environment",
"hhvm"
],
- "time": "2017-07-01T08:51:00+00:00"
+ "time": "2019-05-05T09:05:15+00:00"
},
{
"name": "sebastian/exporter",
@@ -1790,71 +1690,28 @@
"homepage": "https://github.com/sebastianbergmann/finder-facade",
"time": "2017-11-18T17:31:49+00:00"
},
- {
- "name": "sebastian/git",
- "version": "2.1.4",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/git.git",
- "reference": "815bbbc963cf35e5413df195aa29df58243ecd24"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/git/zipball/815bbbc963cf35e5413df195aa29df58243ecd24",
- "reference": "815bbbc963cf35e5413df195aa29df58243ecd24",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.1-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- }
- ],
- "description": "Simple wrapper for Git",
- "homepage": "http://www.github.com/sebastianbergmann/git",
- "keywords": [
- "git"
- ],
- "abandoned": true,
- "time": "2017-01-23T20:57:12+00:00"
- },
{
"name": "sebastian/global-state",
- "version": "2.0.0",
+ "version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
- "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4"
+ "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4",
- "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4",
+ "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4",
"shasum": ""
},
"require": {
- "php": "^7.0"
+ "php": "^7.2",
+ "sebastian/object-reflector": "^1.1.1",
+ "sebastian/recursion-context": "^3.0"
},
"require-dev": {
- "phpunit/phpunit": "^6.0"
+ "ext-dom": "*",
+ "phpunit/phpunit": "^8.0"
},
"suggest": {
"ext-uopz": "*"
@@ -1862,7 +1719,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.0-dev"
+ "dev-master": "3.0-dev"
}
},
"autoload": {
@@ -1885,7 +1742,7 @@
"keywords": [
"global state"
],
- "time": "2017-04-27T15:39:26+00:00"
+ "time": "2019-02-01T05:30:01+00:00"
},
{
"name": "sebastian/object-enumerator",
@@ -1981,21 +1838,22 @@
},
{
"name": "sebastian/phpcpd",
- "version": "3.0.1",
+ "version": "4.1.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpcpd.git",
- "reference": "dfed51c1288790fc957c9433e2f49ab152e8a564"
+ "reference": "0d9afa762f2400de077b2192f4a9d127de0bb78e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpcpd/zipball/dfed51c1288790fc957c9433e2f49ab152e8a564",
- "reference": "dfed51c1288790fc957c9433e2f49ab152e8a564",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpcpd/zipball/0d9afa762f2400de077b2192f4a9d127de0bb78e",
+ "reference": "0d9afa762f2400de077b2192f4a9d127de0bb78e",
"shasum": ""
},
"require": {
- "php": "^5.6|^7.0",
- "phpunit/php-timer": "^1.0.6",
+ "ext-dom": "*",
+ "php": "^7.1",
+ "phpunit/php-timer": "^2.0",
"sebastian/finder-facade": "^1.1",
"sebastian/version": "^1.0|^2.0",
"symfony/console": "^2.7|^3.0|^4.0"
@@ -2006,7 +1864,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.0-dev"
+ "dev-master": "4.0-dev"
}
},
"autoload": {
@@ -2027,7 +1885,7 @@
],
"description": "Copy/Paste Detector (CPD) for PHP code.",
"homepage": "https://github.com/sebastianbergmann/phpcpd",
- "time": "2017-11-16T08:49:28+00:00"
+ "time": "2018-09-17T17:17:27+00:00"
},
{
"name": "sebastian/recursion-context",
@@ -2084,25 +1942,25 @@
},
{
"name": "sebastian/resource-operations",
- "version": "1.0.0",
+ "version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/resource-operations.git",
- "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52"
+ "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
- "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
+ "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
+ "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
"shasum": ""
},
"require": {
- "php": ">=5.6.0"
+ "php": "^7.1"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0.x-dev"
+ "dev-master": "2.0-dev"
}
},
"autoload": {
@@ -2122,7 +1980,7 @@
],
"description": "Provides a list of PHP built-in functions that operate on resources",
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
- "time": "2015-07-28T20:34:47+00:00"
+ "time": "2018-10-04T04:07:39+00:00"
},
{
"name": "sebastian/version",
@@ -2169,16 +2027,16 @@
},
{
"name": "squizlabs/php_codesniffer",
- "version": "3.3.2",
+ "version": "3.4.2",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
- "reference": "6ad28354c04b364c3c71a34e4a18b629cc3b231e"
+ "reference": "b8a7362af1cc1aadb5bd36c3defc4dda2cf5f0a8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/6ad28354c04b364c3c71a34e4a18b629cc3b231e",
- "reference": "6ad28354c04b364c3c71a34e4a18b629cc3b231e",
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/b8a7362af1cc1aadb5bd36c3defc4dda2cf5f0a8",
+ "reference": "b8a7362af1cc1aadb5bd36c3defc4dda2cf5f0a8",
"shasum": ""
},
"require": {
@@ -2211,41 +2069,41 @@
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
- "homepage": "http://www.squizlabs.com/php-codesniffer",
+ "homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [
"phpcs",
"standards"
],
- "time": "2018-09-23T23:08:17+00:00"
+ "time": "2019-04-10T23:49:02+00:00"
},
{
"name": "symfony/config",
- "version": "v3.4.23",
+ "version": "v4.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
- "reference": "177a276c01575253c95cefe0866e3d1b57637fe0"
+ "reference": "5455fc0ae8b46269b83a22949429ea878496408c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/config/zipball/177a276c01575253c95cefe0866e3d1b57637fe0",
- "reference": "177a276c01575253c95cefe0866e3d1b57637fe0",
+ "url": "https://api.github.com/repos/symfony/config/zipball/5455fc0ae8b46269b83a22949429ea878496408c",
+ "reference": "5455fc0ae8b46269b83a22949429ea878496408c",
"shasum": ""
},
"require": {
- "php": "^5.5.9|>=7.0.8",
- "symfony/filesystem": "~2.8|~3.0|~4.0",
+ "php": "^7.1.3",
+ "symfony/filesystem": "~3.4|~4.0",
"symfony/polyfill-ctype": "~1.8"
},
"conflict": {
- "symfony/dependency-injection": "<3.3",
- "symfony/finder": "<3.3"
+ "symfony/finder": "<3.4"
},
"require-dev": {
- "symfony/dependency-injection": "~3.3|~4.0",
- "symfony/event-dispatcher": "~3.3|~4.0",
- "symfony/finder": "~3.3|~4.0",
- "symfony/yaml": "~3.0|~4.0"
+ "symfony/dependency-injection": "~3.4|~4.0",
+ "symfony/event-dispatcher": "~3.4|~4.0",
+ "symfony/finder": "~3.4|~4.0",
+ "symfony/messenger": "~4.1",
+ "symfony/yaml": "~3.4|~4.0"
},
"suggest": {
"symfony/yaml": "To use the yaml reference dumper"
@@ -2253,7 +2111,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.4-dev"
+ "dev-master": "4.3-dev"
}
},
"autoload": {
@@ -2280,29 +2138,31 @@
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
- "time": "2019-02-23T15:06:07+00:00"
+ "time": "2019-05-20T16:16:12+00:00"
},
{
"name": "symfony/console",
- "version": "v3.4.23",
+ "version": "v4.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "71ce77f37af0c5ffb9590e43cc4f70e426945c5e"
+ "reference": "707b619d2c3bedf0224d56f95f77dabc60102305"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/71ce77f37af0c5ffb9590e43cc4f70e426945c5e",
- "reference": "71ce77f37af0c5ffb9590e43cc4f70e426945c5e",
+ "url": "https://api.github.com/repos/symfony/console/zipball/707b619d2c3bedf0224d56f95f77dabc60102305",
+ "reference": "707b619d2c3bedf0224d56f95f77dabc60102305",
"shasum": ""
},
"require": {
- "php": "^5.5.9|>=7.0.8",
- "symfony/debug": "~2.8|~3.0|~4.0",
- "symfony/polyfill-mbstring": "~1.0"
+ "php": "^7.1.3",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/polyfill-php73": "^1.8",
+ "symfony/service-contracts": "^1.1"
},
"conflict": {
"symfony/dependency-injection": "<3.4",
+ "symfony/event-dispatcher": "<4.3",
"symfony/process": "<3.3"
},
"provide": {
@@ -2310,11 +2170,12 @@
},
"require-dev": {
"psr/log": "~1.0",
- "symfony/config": "~3.3|~4.0",
+ "symfony/config": "~3.4|~4.0",
"symfony/dependency-injection": "~3.4|~4.0",
- "symfony/event-dispatcher": "~2.8|~3.0|~4.0",
+ "symfony/event-dispatcher": "^4.3",
"symfony/lock": "~3.4|~4.0",
- "symfony/process": "~3.3|~4.0"
+ "symfony/process": "~3.4|~4.0",
+ "symfony/var-dumper": "^4.3"
},
"suggest": {
"psr/log": "For using the console logger",
@@ -2325,7 +2186,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.4-dev"
+ "dev-master": "4.3-dev"
}
},
"autoload": {
@@ -2352,94 +2213,40 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
- "time": "2019-02-23T15:06:07+00:00"
+ "time": "2019-05-27T08:16:38+00:00"
},
{
- "name": "symfony/debug",
- "version": "v4.2.4",
+ "name": "symfony/dependency-injection",
+ "version": "v4.3.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/debug.git",
- "reference": "de73f48977b8eaf7ce22814d66e43a1662cc864f"
+ "url": "https://github.com/symfony/dependency-injection.git",
+ "reference": "aa6fe799fa5adc938fc55aeccd2f5fb0aa0b8eac"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/debug/zipball/de73f48977b8eaf7ce22814d66e43a1662cc864f",
- "reference": "de73f48977b8eaf7ce22814d66e43a1662cc864f",
+ "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/aa6fe799fa5adc938fc55aeccd2f5fb0aa0b8eac",
+ "reference": "aa6fe799fa5adc938fc55aeccd2f5fb0aa0b8eac",
"shasum": ""
},
"require": {
"php": "^7.1.3",
- "psr/log": "~1.0"
+ "psr/container": "^1.0",
+ "symfony/service-contracts": "^1.1.2"
},
"conflict": {
- "symfony/http-kernel": "<3.4"
- },
- "require-dev": {
- "symfony/http-kernel": "~3.4|~4.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "4.2-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Debug\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony Debug Component",
- "homepage": "https://symfony.com",
- "time": "2019-03-03T18:11:24+00:00"
- },
- {
- "name": "symfony/dependency-injection",
- "version": "v3.4.23",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/dependency-injection.git",
- "reference": "c3dd7b7ea8cd8ec12304a5e222d7dc01cac8fa11"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/c3dd7b7ea8cd8ec12304a5e222d7dc01cac8fa11",
- "reference": "c3dd7b7ea8cd8ec12304a5e222d7dc01cac8fa11",
- "shasum": ""
- },
- "require": {
- "php": "^5.5.9|>=7.0.8",
- "psr/container": "^1.0"
- },
- "conflict": {
- "symfony/config": "<3.3.7",
- "symfony/finder": "<3.3",
+ "symfony/config": "<4.3",
+ "symfony/finder": "<3.4",
"symfony/proxy-manager-bridge": "<3.4",
"symfony/yaml": "<3.4"
},
"provide": {
- "psr/container-implementation": "1.0"
+ "psr/container-implementation": "1.0",
+ "symfony/service-implementation": "1.0"
},
"require-dev": {
- "symfony/config": "~3.3|~4.0",
- "symfony/expression-language": "~2.8|~3.0|~4.0",
+ "symfony/config": "^4.3",
+ "symfony/expression-language": "~3.4|~4.0",
"symfony/yaml": "~3.4|~4.0"
},
"suggest": {
@@ -2452,7 +2259,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.4-dev"
+ "dev-master": "4.3-dev"
}
},
"autoload": {
@@ -2479,30 +2286,30 @@
],
"description": "Symfony DependencyInjection Component",
"homepage": "https://symfony.com",
- "time": "2019-02-23T15:06:07+00:00"
+ "time": "2019-05-28T07:50:59+00:00"
},
{
"name": "symfony/filesystem",
- "version": "v3.4.23",
+ "version": "v4.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "acf99758b1df8e9295e6b85aa69f294565c9fedb"
+ "reference": "988ab7d70c267c34efa85772ca20de3fad11c74b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/acf99758b1df8e9295e6b85aa69f294565c9fedb",
- "reference": "acf99758b1df8e9295e6b85aa69f294565c9fedb",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/988ab7d70c267c34efa85772ca20de3fad11c74b",
+ "reference": "988ab7d70c267c34efa85772ca20de3fad11c74b",
"shasum": ""
},
"require": {
- "php": "^5.5.9|>=7.0.8",
+ "php": "^7.1.3",
"symfony/polyfill-ctype": "~1.8"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.4-dev"
+ "dev-master": "4.3-dev"
}
},
"autoload": {
@@ -2529,20 +2336,20 @@
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
- "time": "2019-02-04T21:34:32+00:00"
+ "time": "2019-05-24T12:50:04+00:00"
},
{
"name": "symfony/finder",
- "version": "v4.2.4",
+ "version": "v4.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "267b7002c1b70ea80db0833c3afe05f0fbde580a"
+ "reference": "b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/267b7002c1b70ea80db0833c3afe05f0fbde580a",
- "reference": "267b7002c1b70ea80db0833c3afe05f0fbde580a",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176",
+ "reference": "b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176",
"shasum": ""
},
"require": {
@@ -2551,7 +2358,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.2-dev"
+ "dev-master": "4.3-dev"
}
},
"autoload": {
@@ -2578,20 +2385,20 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
- "time": "2019-02-23T15:42:05+00:00"
+ "time": "2019-05-26T20:47:49+00:00"
},
{
"name": "symfony/polyfill-ctype",
- "version": "v1.10.0",
+ "version": "v1.11.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
- "reference": "e3d826245268269cd66f8326bd8bc066687b4a19"
+ "reference": "82ebae02209c21113908c229e9883c419720738a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19",
- "reference": "e3d826245268269cd66f8326bd8bc066687b4a19",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a",
+ "reference": "82ebae02209c21113908c229e9883c419720738a",
"shasum": ""
},
"require": {
@@ -2603,7 +2410,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.9-dev"
+ "dev-master": "1.11-dev"
}
},
"autoload": {
@@ -2625,7 +2432,7 @@
},
{
"name": "Gert de Pagter",
- "email": "backendtea@gmail.com"
+ "email": "BackEndTea@gmail.com"
}
],
"description": "Symfony polyfill for ctype functions",
@@ -2636,20 +2443,20 @@
"polyfill",
"portable"
],
- "time": "2018-08-06T14:22:27+00:00"
+ "time": "2019-02-06T07:57:58+00:00"
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.10.0",
+ "version": "v1.11.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "c79c051f5b3a46be09205c73b80b346e4153e494"
+ "reference": "fe5e94c604826c35a32fa832f35bd036b6799609"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494",
- "reference": "c79c051f5b3a46be09205c73b80b346e4153e494",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609",
+ "reference": "fe5e94c604826c35a32fa832f35bd036b6799609",
"shasum": ""
},
"require": {
@@ -2661,7 +2468,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.9-dev"
+ "dev-master": "1.11-dev"
}
},
"autoload": {
@@ -2695,7 +2502,123 @@
"portable",
"shim"
],
- "time": "2018-09-21T13:07:52+00:00"
+ "time": "2019-02-06T07:57:58+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php73",
+ "version": "v1.11.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php73.git",
+ "reference": "d1fb4abcc0c47be136208ad9d68bf59f1ee17abd"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/d1fb4abcc0c47be136208ad9d68bf59f1ee17abd",
+ "reference": "d1fb4abcc0c47be136208ad9d68bf59f1ee17abd",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.11-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Php73\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ],
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "time": "2019-02-06T07:57:58+00:00"
+ },
+ {
+ "name": "symfony/service-contracts",
+ "version": "v1.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/service-contracts.git",
+ "reference": "191afdcb5804db960d26d8566b7e9a2843cab3a0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/191afdcb5804db960d26d8566b7e9a2843cab3a0",
+ "reference": "191afdcb5804db960d26d8566b7e9a2843cab3a0",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1.3"
+ },
+ "suggest": {
+ "psr/container": "",
+ "symfony/service-implementation": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\Service\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Generic abstractions related to writing services",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "time": "2019-05-28T07:50:59+00:00"
},
{
"name": "theseer/directoryscanner",
@@ -2826,16 +2749,16 @@
},
{
"name": "theseer/phpdox",
- "version": "0.11.2",
+ "version": "0.12.0",
"source": {
"type": "git",
"url": "https://github.com/theseer/phpdox.git",
- "reference": "0e1dbf4bd862ed0cf87797409407973b2c228958"
+ "reference": "a46438e723a2b5bfd6ea4f299ecc0c7a1db1112c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/theseer/phpdox/zipball/0e1dbf4bd862ed0cf87797409407973b2c228958",
- "reference": "0e1dbf4bd862ed0cf87797409407973b2c228958",
+ "url": "https://api.github.com/repos/theseer/phpdox/zipball/a46438e723a2b5bfd6ea4f299ecc0c7a1db1112c",
+ "reference": "a46438e723a2b5bfd6ea4f299ecc0c7a1db1112c",
"shasum": ""
},
"require": {
@@ -2845,9 +2768,9 @@
"ext-mbstring": "*",
"ext-tokenizer": "*",
"ext-xsl": "*",
- "nikic/php-parser": "^3.1",
- "php": ">=5.5",
- "phpunit/php-timer": "^1.0",
+ "nikic/php-parser": "^4.2",
+ "php": ">=7.1",
+ "phpunit/php-timer": "^2.0",
"theseer/directoryscanner": "^1.3.0",
"theseer/fdomdocument": "^1.6",
"theseer/fxsl": "^1.1"
@@ -2873,20 +2796,20 @@
}
],
"description": "A fast Documentation generator for PHP Code using standard technology (SRC, DOCBLOCK, XML and XSLT) with event based processing",
- "time": "2018-05-22T16:43:30+00:00"
+ "time": "2019-03-13T09:34:17+00:00"
},
{
"name": "theseer/tokenizer",
- "version": "1.1.0",
+ "version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
- "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b"
+ "reference": "1c42705be2b6c1de5904f8afacef5895cab44bf8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b",
- "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b",
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/1c42705be2b6c1de5904f8afacef5895cab44bf8",
+ "reference": "1c42705be2b6c1de5904f8afacef5895cab44bf8",
"shasum": ""
},
"require": {
@@ -2913,7 +2836,7 @@
}
],
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
- "time": "2017-04-07T12:08:54+00:00"
+ "time": "2019-04-04T09:56:43+00:00"
},
{
"name": "webmozart/assert",
@@ -2988,7 +2911,7 @@
"ext-openssl": "*"
},
"platform-dev": {
- "php": ">=7.1",
+ "php": ">=7.3",
"ext-pcntl": "*"
}
}
diff --git a/lib/Froxlor/Api/Commands/Customers.php b/lib/Froxlor/Api/Commands/Customers.php
index 271e1f6d..273ecd10 100644
--- a/lib/Froxlor/Api/Commands/Customers.php
+++ b/lib/Froxlor/Api/Commands/Customers.php
@@ -340,11 +340,12 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
'login' => $loginname
), true, true);
+ $mysql_maxlen = \Froxlor\Database\Database::getSqlUsernameLength() - strlen(Settings::Get('customer.mysqlprefix'));
if (strtolower($loginname_check['loginname']) == strtolower($loginname) || strtolower($loginname_check_admin['loginname']) == strtolower($loginname)) {
\Froxlor\UI\Response::standard_error('loginnameexists', $loginname, true);
- } elseif (! \Froxlor\Validate\Validate::validateUsername($loginname, Settings::Get('panel.unix_names'), 14 - strlen(Settings::Get('customer.mysqlprefix')))) {
- if (strlen($loginname) > 14 - strlen(Settings::Get('customer.mysqlprefix'))) {
- \Froxlor\UI\Response::standard_error('loginnameiswrong2', 14 - strlen(Settings::Get('customer.mysqlprefix')), true);
+ } elseif (! \Froxlor\Validate\Validate::validateUsername($loginname, Settings::Get('panel.unix_names'), $mysql_maxlen)) {
+ if (strlen($loginname) > $mysql_maxlen) {
+ \Froxlor\UI\Response::standard_error('loginnameiswrong2', $mysql_maxlen, true);
} else {
\Froxlor\UI\Response::standard_error('loginnameiswrong', $loginname, true);
}
diff --git a/lib/Froxlor/Database/Database.php b/lib/Froxlor/Database/Database.php
index ccf5ad3b..d0791148 100644
--- a/lib/Froxlor/Database/Database.php
+++ b/lib/Froxlor/Database/Database.php
@@ -193,7 +193,7 @@ class Database
// MySQL user names can be up to 32 characters long (16 characters before MySQL 5.7.8).
$mysql_max = 32;
if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.8', '<')) {
- $mysql_max -= 16;
+ $mysql_max = 16;
}
return $mysql_max;
}
diff --git a/lib/Froxlor/Validate/Check.php b/lib/Froxlor/Validate/Check.php
index 41901d31..d436616e 100644
--- a/lib/Froxlor/Validate/Check.php
+++ b/lib/Froxlor/Validate/Check.php
@@ -192,7 +192,7 @@ class Check
}
$returnvalue = array();
- if (Validate::validateUsername($newfieldvalue, Settings::Get('panel.unix_names'), 14 - strlen($allnewfieldvalues['customer_mysqlprefix'])) === true) {
+ if (Validate::validateUsername($newfieldvalue, Settings::Get('panel.unix_names'), \Froxlor\Database\Database::getSqlUsernameLength() - strlen($allnewfieldvalues['customer_mysqlprefix'])) === true) {
$returnvalue = array(
self::FORMFIELDS_PLAUSIBILITY_CHECK_OK
);
diff --git a/phpunit.xml b/phpunit.xml
index 4a31f67b..3ec18fd3 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -2,7 +2,7 @@
@@ -29,13 +29,11 @@
-
+
-
+
diff --git a/tests/Customers/CustomersTest.php b/tests/Customers/CustomersTest.php
index 3735d244..2fb75d71 100644
--- a/tests/Customers/CustomersTest.php
+++ b/tests/Customers/CustomersTest.php
@@ -545,7 +545,7 @@ class CustomersTest extends TestCase
'customernumber' => 1339
];
- $this->expectExceptionMessage('Loginname contains too many characters. Only ' . (14 - strlen(Settings::Get('customer.mysqlprefix'))) . ' characters are allowed.');
+ $this->expectExceptionMessage('Loginname contains too many characters. Only ' . (\Froxlor\Database\Database::getSqlUsernameLength() - strlen(Settings::Get('customer.mysqlprefix'))) . ' characters are allowed.');
Customers::getLocal($admin_userdata, $data)->add();
}
}
diff --git a/tests/Froxlor/SettingsTest.php b/tests/Froxlor/SettingsTest.php
index b0f9922d..c4afbb31 100644
--- a/tests/Froxlor/SettingsTest.php
+++ b/tests/Froxlor/SettingsTest.php
@@ -8,7 +8,8 @@ use PHPUnit\Framework\TestCase;
class SettingsTest extends TestCase
{
- protected function setUp() {
+ protected function setUp(): void
+ {
// start fresh
\Froxlor\Settings::Stash();
}
diff --git a/tests/Traffic/TrafficTest.php b/tests/Traffic/TrafficTest.php
index 24a737fd..3383dd61 100644
--- a/tests/Traffic/TrafficTest.php
+++ b/tests/Traffic/TrafficTest.php
@@ -16,7 +16,7 @@ use Froxlor\Api\Commands\Traffic;
class TrafficTest extends TestCase
{
- public static function setUpBeforeClass()
+ public static function setUpBeforeClass(): void
{
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_TRAFFIC . "` SET
From f266bb05c99c29b37a0a05491e9ed1aa9b7a459e Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Thu, 6 Jun 2019 13:04:43 +0200
Subject: [PATCH 019/159] testing \Froxlor\Settings\FroxlorVhostSettings
Signed-off-by: Michael Kaufmann
---
tests/Froxlor/SettingsTest.php | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/tests/Froxlor/SettingsTest.php b/tests/Froxlor/SettingsTest.php
index c4afbb31..343eadf7 100644
--- a/tests/Froxlor/SettingsTest.php
+++ b/tests/Froxlor/SettingsTest.php
@@ -4,6 +4,7 @@ use PHPUnit\Framework\TestCase;
/**
*
* @covers \Froxlor\Settings
+ * @covers \Froxlor\Settings\FroxlorVhostSettings
*/
class SettingsTest extends TestCase
{
@@ -92,4 +93,21 @@ class SettingsTest extends TestCase
$result = \Froxlor\Settings::IsInList("system.mysql_access_host", "my-super-domain.de");
$this->assertFalse($result);
}
+
+ public function testFroxlorVhostSettings()
+ {
+ // bootstrap.php adds two IPs, one ssl one non-ssl both with vhostcontainer = 1
+ $result = \Froxlor\Settings\FroxlorVhostSettings::hasVhostContainerEnabled(false);
+ $this->assertTrue($result);
+ $result = \Froxlor\Settings\FroxlorVhostSettings::hasVhostContainerEnabled(true);
+ $this->assertTrue($result);
+ // now disable both
+ \Froxlor\Database\Database::query("UPDATE `". TABLE_PANEL_IPSANDPORTS . "` SET `vhostcontainer` = '0'");
+ $result = \Froxlor\Settings\FroxlorVhostSettings::hasVhostContainerEnabled(false);
+ $this->assertFalse($result);
+ $result = \Froxlor\Settings\FroxlorVhostSettings::hasVhostContainerEnabled(true);
+ $this->assertFalse($result);
+ // and change back
+ \Froxlor\Database\Database::query("UPDATE `". TABLE_PANEL_IPSANDPORTS . "` SET `vhostcontainer` = '1'");
+ }
}
From 1ac304e5ac6b0450e5432262af795462dc06ac9d Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Mon, 10 Jun 2019 11:36:05 +0200
Subject: [PATCH 020/159] fix missing domainname parameter when manually adding
ssl-certificates for a domain, fixes #700
Signed-off-by: Michael Kaufmann
---
customer_domains.php | 11 +++++++++++
.../customer/domains/formfield.domain_ssleditor.php | 6 ++++++
2 files changed, 17 insertions(+)
diff --git a/customer_domains.php b/customer_domains.php
index 50681cf2..e50173e1 100644
--- a/customer_domains.php
+++ b/customer_domains.php
@@ -480,6 +480,17 @@ if ($page == 'overview') {
} elseif ($page == 'domainssleditor') {
if ($action == '' || $action == 'view') {
+
+ // get domain
+ try {
+ $json_result = SubDomains::getLocal($userinfo, array(
+ 'id' => $id
+ ))->get();
+ } catch (Exception $e) {
+ \Froxlor\UI\Response::dynamic_error($e->getMessage());
+ }
+ $result_domain = json_decode($json_result, true)['data'];
+
if (isset($_POST['send']) && $_POST['send'] == 'send') {
$do_insert = isset($_POST['do_insert']) ? (($_POST['do_insert'] == 1) ? true : false) : false;
try {
diff --git a/lib/formfields/customer/domains/formfield.domain_ssleditor.php b/lib/formfields/customer/domains/formfield.domain_ssleditor.php
index e6a14faa..3518ef39 100644
--- a/lib/formfields/customer/domains/formfield.domain_ssleditor.php
+++ b/lib/formfields/customer/domains/formfield.domain_ssleditor.php
@@ -23,6 +23,12 @@ return array(
'title' => 'SSL certificates',
'image' => 'icons/ssl.png',
'fields' => array(
+ 'domainname' => array(
+ 'label' => $lng['domains']['domainname'],
+ 'type' => 'hidden',
+ 'value' => $result_domain['domain'],
+ 'display' => $result_domain['domain']
+ ),
'ssl_cert_file' => array(
'style' => 'align-top',
'label' => $lng['admin']['ipsandports']['ssl_cert_file_content'],
From 028524291eff4979df25b6e16aabf4567b6db414 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Mon, 10 Jun 2019 11:38:47 +0200
Subject: [PATCH 021/159] test improvements and preparation for more tests
later
Signed-off-by: Michael Kaufmann
---
phpunit.xml | 2 +-
tests/Customers/CustomersTest.php | 8 +++++++-
tests/Domains/DomainsTest.php | 2 +-
3 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/phpunit.xml b/phpunit.xml
index 3ec18fd3..b0ff49e7 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -9,7 +9,6 @@
tests/Global
- tests/Froxlor
tests/Admins
tests/Customers
tests/IpsAndPorts
@@ -25,6 +24,7 @@
tests/Mysqls
tests/PhpAndFpm
tests/Traffic
+ tests/Froxlor
diff --git a/tests/Customers/CustomersTest.php b/tests/Customers/CustomersTest.php
index 2fb75d71..3c0a913a 100644
--- a/tests/Customers/CustomersTest.php
+++ b/tests/Customers/CustomersTest.php
@@ -5,6 +5,7 @@ use Froxlor\Settings;
use Froxlor\Database\Database;
use Froxlor\Api\Commands\Admins;
use Froxlor\Api\Commands\Customers;
+use Froxlor\Api\Commands\SubDomains;
/**
*
@@ -58,6 +59,11 @@ class CustomersTest extends TestCase
$this->assertEquals(1337, $result['customernumber']);
$this->assertEquals(15, $result['subdomains']);
$this->assertEquals('secret', $result['custom_notes']);
+
+ // validate that the std-subdomain has been added
+ $json_result = SubDomains::getLocal($admin_userdata, array('id' => $result['standardsubdomain']))->get();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals('test1.dev.froxlor.org', $result['domain']);
}
public function testAdminCustomersAddEmptyMail()
@@ -447,7 +453,7 @@ class CustomersTest extends TestCase
'mysqls' => 15,
'createstdsubdomain' => 1,
'new_customer_password' => 'h0lYmo1y',
- 'sendpassword' => 1,
+ 'sendpassword' => TRAVIS_CI == 1 ? 0 : 1,
'phpenabled' => 1,
'store_defaultindex' => 1,
'custom_notes' => 'secret',
diff --git a/tests/Domains/DomainsTest.php b/tests/Domains/DomainsTest.php
index b89f4eba..ead35c02 100644
--- a/tests/Domains/DomainsTest.php
+++ b/tests/Domains/DomainsTest.php
@@ -119,7 +119,7 @@ class DomainsTest extends TestCase
'customerid' => 1
];
$this->expectExceptionMessage('The server-hostname cannot be used as customer-domain.');
- $json_result = Domains::getLocal($admin_userdata, $data)->add();
+ Domains::getLocal($admin_userdata, $data)->add();
}
public function testAdminDomainsAddNoPunycode()
From 7a94a430536b0e93c5cfa4f7aa7c89a016693662 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Mon, 10 Jun 2019 13:37:22 +0200
Subject: [PATCH 022/159] started \Settings\Store unit tests
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Settings/Store.php | 125 +++++++++++-------------------
tests/Customers/CustomersTest.php | 4 +-
tests/Froxlor/StoreTest.php | 97 +++++++++++++++++++++++
3 files changed, 145 insertions(+), 81 deletions(-)
create mode 100644 tests/Froxlor/StoreTest.php
diff --git a/lib/Froxlor/Settings/Store.php b/lib/Froxlor/Settings/Store.php
index 5c567d31..d9e33144 100644
--- a/lib/Froxlor/Settings/Store.php
+++ b/lib/Froxlor/Settings/Store.php
@@ -27,29 +27,58 @@ class Store
$returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue);
if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'system' && isset($fielddata['varname']) && $fielddata['varname'] == 'defaultip') {
+ self::updateStdSubdomainDefaultIp($newfieldvalue, $defaultips_old);
+ }
- $customerstddomains_result_stmt = Database::prepare("
- SELECT `standardsubdomain` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `standardsubdomain` <> '0'
- ");
- Database::pexecute($customerstddomains_result_stmt);
+ return $returnvalue;
+ }
- $ids = array();
+ public static function storeSettingDefaultSslIp($fieldname, $fielddata, $newfieldvalue)
+ {
+ $defaultips_old = Settings::Get('system.defaultsslip');
- while ($customerstddomains_row = $customerstddomains_result_stmt->fetch(\PDO::FETCH_ASSOC)) {
- $ids[] = (int) $customerstddomains_row['standardsubdomain'];
+ $returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue);
+
+ if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'system' && isset($fielddata['varname']) && $fielddata['varname'] == 'defaultsslip') {
+ self::updateStdSubdomainDefaultIp($newfieldvalue, $defaultips_old);
+ }
+
+ return $returnvalue;
+ }
+
+ private static function updateStdSubdomainDefaultIp($newfieldvalue, $defaultips_old)
+ {
+ // update standard-subdomain of customer if exists
+ $customerstddomains_result_stmt = Database::prepare("
+ SELECT `standardsubdomain` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `standardsubdomain` <> '0'
+ ");
+ Database::pexecute($customerstddomains_result_stmt);
+
+ $ids = array();
+ while ($customerstddomains_row = $customerstddomains_result_stmt->fetch(\PDO::FETCH_ASSOC)) {
+ $ids[] = (int) $customerstddomains_row['standardsubdomain'];
+ }
+
+ if (count($ids) > 0) {
+ $defaultips_new = explode(',', $newfieldvalue);
+
+ if (! empty($defaultips_old) && ! empty($newfieldvalue)) {
+ $in_value = $defaultips_old . ", " . $newfieldvalue;
+ } elseif (! empty($defaultips_old) && empty($newfieldvalue)) {
+ $in_value = $defaultips_old;
+ } else {
+ $in_value = $newfieldvalue;
}
- if (count($ids) > 0) {
- $defaultips_new = explode(',', $newfieldvalue);
-
- // Delete the existing mappings linking to default IPs
- $del_stmt = Database::prepare("
- DELETE FROM `" . TABLE_DOMAINTOIP . "`
- WHERE `id_domain` IN (" . implode(', ', $ids) . ")
- AND `id_ipandports` IN (" . $defaultips_old . ", " . $newfieldvalue . ")
- ");
- Database::pexecute($del_stmt);
+ // Delete the existing mappings linking to default IPs
+ $del_stmt = Database::prepare("
+ DELETE FROM `" . TABLE_DOMAINTOIP . "`
+ WHERE `id_domain` IN (" . implode(', ', $ids) . ")
+ AND `id_ipandports` IN (" . $in_value . ")
+ ");
+ Database::pexecute($del_stmt);
+ if (count($defaultips_new) > 0) {
// Insert the new mappings
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_DOMAINTOIP . "`
@@ -66,68 +95,6 @@ class Store
}
}
}
-
- return $returnvalue;
- }
-
- public static function storeSettingDefaultSslIp($fieldname, $fielddata, $newfieldvalue)
- {
- $defaultips_old = Settings::Get('system.defaultsslip');
-
- $returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue);
-
- if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'system' && isset($fielddata['varname']) && $fielddata['varname'] == 'defaultsslip') {
-
- $customerstddomains_result_stmt = Database::prepare("
- SELECT `standardsubdomain` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `standardsubdomain` <> '0'
- ");
- Database::pexecute($customerstddomains_result_stmt);
-
- $ids = array();
-
- while ($customerstddomains_row = $customerstddomains_result_stmt->fetch(\PDO::FETCH_ASSOC)) {
- $ids[] = (int) $customerstddomains_row['standardsubdomain'];
- }
-
- if (count($ids) > 0) {
- $defaultips_new = explode(',', $newfieldvalue);
-
- if (! empty($defaultips_old) && ! empty($newfieldvalue)) {
- $in_value = $defaultips_old . ", " . $newfieldvalue;
- } elseif (! empty($defaultips_old) && empty($newfieldvalue)) {
- $in_value = $defaultips_old;
- } else {
- $in_value = $newfieldvalue;
- }
-
- // Delete the existing mappings linking to default IPs
- $del_stmt = Database::prepare("
- DELETE FROM `" . TABLE_DOMAINTOIP . "`
- WHERE `id_domain` IN (" . implode(', ', $ids) . ")
- AND `id_ipandports` IN (" . $in_value . ")
- ");
- Database::pexecute($del_stmt);
-
- if (count($defaultips_new) > 0) {
- // Insert the new mappings
- $ins_stmt = Database::prepare("
- INSERT INTO `" . TABLE_DOMAINTOIP . "`
- SET `id_domain` = :domainid, `id_ipandports` = :ipandportid
- ");
-
- foreach ($ids as $id) {
- foreach ($defaultips_new as $defaultip_new) {
- Database::pexecute($ins_stmt, array(
- 'domainid' => $id,
- 'ipandportid' => $defaultip_new
- ));
- }
- }
- }
- }
- }
-
- return $returnvalue;
}
/**
diff --git a/tests/Customers/CustomersTest.php b/tests/Customers/CustomersTest.php
index 3c0a913a..4de3fc0d 100644
--- a/tests/Customers/CustomersTest.php
+++ b/tests/Customers/CustomersTest.php
@@ -230,7 +230,7 @@ class CustomersTest extends TestCase
/**
*
- * @depends testAdminCustomersAdd
+ * @depends testAdminCustomerUpdateDeactivate
*/
public function testCustomerCustomersGetWhenDeactivated()
{
@@ -252,7 +252,7 @@ class CustomersTest extends TestCase
/**
*
- * @depends testAdminCustomersAdd
+ * @depends testCustomerCustomersGetWhenDeactivated
*/
public function testCustomerCustomersUpdate()
{
diff --git a/tests/Froxlor/StoreTest.php b/tests/Froxlor/StoreTest.php
new file mode 100644
index 00000000..f5a46f18
--- /dev/null
+++ b/tests/Froxlor/StoreTest.php
@@ -0,0 +1,97 @@
+ 'le_froxlor_enabled',
+ 'settinggroup' => 'system',
+ 'varname' => 'le_froxlor_enabled'
+ );
+ Store::storeSettingClearCertificates('system_le_froxlor_enabled', $fielddata, 0);
+
+ // there should be no entry in domain_ssl_settings now
+ $result = Database::query("SELECT COUNT(*) as entries FROM `domain_ssl_settings` WHERE `domainid` = '0'");
+ $result = $result->fetch(\PDO::FETCH_ASSOC);
+ $this->assertEquals(0, (int) $result['entries']);
+
+ // truncate the table for other tests
+ Database::query("TRUNCATE TABLE `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`;");
+ }
+
+ public function testStoreSettingDefaultIp()
+ {
+ global $admin_userdata;
+
+ // the customer should have a std-subdomin
+ Customers::getLocal($admin_userdata, array(
+ 'id' => 1,
+ 'createstdsubdomain' => 1
+ ))->update();
+
+ // we need a second non-ssl IP
+ Database::query("INSERT INTO `panel_ipsandports` SET `ip` = '82.149.225.47', `port` = '80'");
+ $ip_id = Database::lastInsertId();
+ $default_ip = Settings::Get('system.defaultip');
+
+ // get all std-subdomains
+ $customerstddomains_result_stmt = Database::prepare("
+ SELECT `standardsubdomain` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `standardsubdomain` <> '0'
+ ");
+ Database::pexecute($customerstddomains_result_stmt);
+
+ $ids = array();
+ while ($customerstddomains_row = $customerstddomains_result_stmt->fetch(\PDO::FETCH_ASSOC)) {
+ $ids[] = (int) $customerstddomains_row['standardsubdomain'];
+ }
+
+ if (count($ids) <= 0) {
+ $this->fail("There should be customer std-subdomains for this test to make sense");
+ }
+
+ // check that they have the current default IP set
+ $sel_stmt = Database::prepare("
+ SELECT * FROM `" . TABLE_DOMAINTOIP . "`
+ WHERE `id_domain` IN (" . implode(', ', $ids) . ") AND `id_ipandports` = :ipid
+ ");
+ Database::pexecute($sel_stmt, array('ipid' => $default_ip));
+ $current_result = $sel_stmt->fetchAll(\PDO::FETCH_ASSOC);
+ // we assume there are entries
+ $this->assertTrue(count($current_result) > 0);
+
+ $fielddata = array(
+ 'label' => 'serversettingsipaddress',
+ 'settinggroup' => 'system',
+ 'varname' => 'defaultip'
+ );
+ Store::storeSettingDefaultIp('serversettings_ipaddress', $fielddata, $ip_id);
+
+ // check that they do not have the current default IP set anymore
+ Database::pexecute($sel_stmt, array('ipid' => $default_ip));
+ $current_result = $sel_stmt->fetchAll(\PDO::FETCH_ASSOC);
+ // we assume there are entries
+ $this->assertTrue(count($current_result) == 0);
+
+ // check that they have the new default IP set
+ Database::pexecute($sel_stmt, array('ipid' => $ip_id));
+ $current_result = $sel_stmt->fetchAll(\PDO::FETCH_ASSOC);
+ // we assume there are entries
+ $this->assertTrue(count($current_result) > 0);
+ }
+}
From a07a9e6a88a9eb13c21dc85f17453d46b3b121f8 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 11 Jun 2019 12:10:56 +0200
Subject: [PATCH 023/159] more unit-testing, enhancements in Store-functions
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Settings/Store.php | 46 ++++++++-------------------
tests/Froxlor/StoreTest.php | 57 ++++++++++++++++++++++++++++++++++
2 files changed, 70 insertions(+), 33 deletions(-)
diff --git a/lib/Froxlor/Settings/Store.php b/lib/Froxlor/Settings/Store.php
index d9e33144..5a506e87 100644
--- a/lib/Froxlor/Settings/Store.php
+++ b/lib/Froxlor/Settings/Store.php
@@ -115,20 +115,20 @@ class Store
$returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue);
if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'panel' && isset($fielddata['varname']) && $fielddata['varname'] == 'default_theme') {
- // now, if changing themes is disabled we recursivly set
+ // now, if changing themes is disabled we manually set
// the new theme (customers and admin, depending on settings)
if (Settings::Get('panel.allow_theme_change_customer') == '0') {
$upd_stmt = Database::prepare("
- UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `theme` = :theme
- ");
+ UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `theme` = :theme
+ ");
Database::pexecute($upd_stmt, array(
'theme' => $newfieldvalue
));
}
if (Settings::Get('panel.allow_theme_change_admin') == '0') {
$upd_stmt = Database::prepare("
- UPDATE `" . TABLE_PANEL_ADMINS . "` SET `theme` = :theme
- ");
+ UPDATE `" . TABLE_PANEL_ADMINS . "` SET `theme` = :theme
+ ");
Database::pexecute($upd_stmt, array(
'theme' => $newfieldvalue
));
@@ -171,17 +171,13 @@ class Store
public static function storeSettingFieldInsertBindTask($fieldname, $fielddata, $newfieldvalue)
{
- if (is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] != '' && isset($fielddata['varname']) && $fielddata['varname'] != '') {
- if (Settings::Set($fielddata['settinggroup'] . '.' . $fielddata['varname'], $newfieldvalue) !== false) {
- return array(
- $fielddata['settinggroup'] . '.' . $fielddata['varname'] => $newfieldvalue
- );
- } else {
- return false;
- }
- } else {
- return false;
+ // first save the setting itself
+ $returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue);
+
+ if ($returnvalue !== false) {
+ \Froxlor\System\Cronjob::inserttask('4');
}
+ return false;
}
public static function storeSettingHostname($fieldname, $fielddata, $newfieldvalue)
@@ -297,25 +293,9 @@ class Store
$returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue);
if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'catchall' && isset($fielddata['varname']) && $fielddata['varname'] == 'catchall_enabled' && $newfieldvalue == '0') {
-
- $result_stmt = Database::query("
- SELECT `id`, `email`, `email_full`, `iscatchall` FROM `" . TABLE_MAIL_VIRTUAL . "`
- WHERE `iscatchall` = '1'
+ Database::query("
+ UPDATE `" . TABLE_MAIL_VIRTUAL . "` SET `iscatchall` = '0' WHERE `iscatchall` = '1'
");
-
- if (Database::num_rows() > 0) {
-
- $upd_stmt = Database::prepare("
- UPDATE `" . TABLE_MAIL_VIRTUAL . "` SET `email` = :email, `iscatchall` = '0' WHERE `id` = :id
- ");
-
- while ($result_row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
- Database::pexecute($upd_stmt, array(
- 'email' => $result_row['email_full'],
- 'id' => $result_row['id']
- ));
- }
- }
}
return $returnvalue;
diff --git a/tests/Froxlor/StoreTest.php b/tests/Froxlor/StoreTest.php
index f5a46f18..1316d3b4 100644
--- a/tests/Froxlor/StoreTest.php
+++ b/tests/Froxlor/StoreTest.php
@@ -94,4 +94,61 @@ class StoreTest extends TestCase
// we assume there are entries
$this->assertTrue(count($current_result) > 0);
}
+
+ public function testStoreSettingDefaultTheme()
+ {
+ $current_theme = Settings::Get('panel.default_theme');
+ // allow theme changing for admins/customers so a new default won't overwrite
+ Settings::Set('panel.allow_theme_change_customer', 1);
+ Settings::Set('panel.allow_theme_change_admin', 1);
+ $fielddata = array(
+ 'label' => 'panel_default_theme',
+ 'settinggroup' => 'panel',
+ 'varname' => 'default_theme'
+ );
+ Store::storeSettingDefaultTheme('panel_default_theme', $fielddata, "newTheme");
+ $this->assertTrue($current_theme != Settings::Get('panel.default_theme'));
+ $this->assertEquals("newTheme", Settings::Get('panel.default_theme'));
+ // validate admin/customer field did not change
+ $sel_stmt = Database::prepare("
+ SELECT * FROM `" . TABLE_PANEL_ADMINS . "`
+ WHERE `theme` = :newtheme
+ ");
+ Database::pexecute($sel_stmt, array('newtheme' => "newTheme"));
+ $current_result = $sel_stmt->fetchAll(\PDO::FETCH_ASSOC);
+ // we assume there are entries
+ $this->assertTrue(count($current_result) == 0);
+ $sel_stmt = Database::prepare("
+ SELECT * FROM `" . TABLE_PANEL_CUSTOMERS . "`
+ WHERE `theme` = :newtheme
+ ");
+ Database::pexecute($sel_stmt, array('newtheme' => "newTheme"));
+ $current_result = $sel_stmt->fetchAll(\PDO::FETCH_ASSOC);
+ // we assume there are entries
+ $this->assertTrue(count($current_result) == 0);
+ // now do not allow changing of themes so the theme should get updated for all admins/customers
+ // allow theme changing for admins/customers so a new default won't overwrite
+ Settings::Set('panel.allow_theme_change_customer', 0);
+ Settings::Set('panel.allow_theme_change_admin', 0);
+ Store::storeSettingDefaultTheme('panel_default_theme', $fielddata, "newTheme");
+ // validate admin/customer field did change
+ $sel_stmt = Database::prepare("
+ SELECT * FROM `" . TABLE_PANEL_ADMINS . "`
+ WHERE `theme` = :newtheme
+ ");
+ Database::pexecute($sel_stmt, array('newtheme' => "newTheme"));
+ $current_result = $sel_stmt->fetchAll(\PDO::FETCH_ASSOC);
+ // we assume there are entries
+ $this->assertTrue(count($current_result) > 0);
+ $sel_stmt = Database::prepare("
+ SELECT * FROM `" . TABLE_PANEL_CUSTOMERS . "`
+ WHERE `theme` = :newtheme
+ ");
+ Database::pexecute($sel_stmt, array('newtheme' => "newTheme"));
+ $current_result = $sel_stmt->fetchAll(\PDO::FETCH_ASSOC);
+ // we assume there are entries
+ $this->assertTrue(count($current_result) > 0);
+ // set back to default
+ Store::storeSettingDefaultTheme('panel_default_theme', $fielddata, $current_theme);
+ }
}
From 6e41c0ad2cc43998c37fbb3e3e079209cabb0b18 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Mon, 17 Jun 2019 14:11:40 +0200
Subject: [PATCH 024/159] add codecov.io to travis build for code-coverage
stats - yay
Signed-off-by: Michael Kaufmann
---
.travis.yml | 27 +++++----------------------
lib/Froxlor/Settings/Store.php | 1 -
2 files changed, 5 insertions(+), 23 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 5014b70f..2a4dd27c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,10 +1,6 @@
language: php
php:
-# - "5.4"
-# - "5.6"
-# - "7.0"
-# - "7.1"
- "7.3"
branches:
@@ -14,10 +10,6 @@ branches:
matrix:
include:
- # - php: 5.6
- # env: deps=highest
- # - php: 5.4
- # env: deps=lowest
- php: 7.3
env: deps=highest
@@ -30,10 +22,6 @@ addons:
apt:
update: true
-# build.xml includes that
-#install:
-# - composer install
-
service:
- mysql
@@ -43,18 +31,13 @@ before_script:
- mysql -u root -pfr0xl0r.TravisCI froxlor010 < install/froxlor.sql
- mysql -u root -pfr0xl0r.TravisCI -e "CREATE USER 'froxlor010'@'localhost' IDENTIFIED BY 'fr0xl0r.TravisCI';"
- mysql -u root -pfr0xl0r.TravisCI -e "GRANT ALL ON froxlor010.* TO 'froxlor010'@'localhost';"
+# - phpenv config-rm xdebug.ini
script:
-# sufficient for travis
- - ant phpunit-no-coverage
-# - ant full-build-parallel
-# -Dpdepend=$(pwd)/vendor/bin/pdepend
-# -Dphpmd=$(pwd)/vendor/bin/phpmd
-# -Dphpcpd=$(pwd)/vendor/bin/phpcpd
-# -Dphpcs=$(pwd)/vendor/bin/phpcs
-# -Dphploc=$(pwd)/vendor/bin/phploc
-# -Dphpdox=$(pwd)/vendor/bin/phpdox
-# -Dphpunit=$(pwd)/vendor/bin/phpunit
+ - ant phpunit
+
+after_success:
+ - bash <(curl -s https://codecov.io/bash) -f "build/logs/clover.xml"
notifications:
irc: "irc.freenode.org#froxlor"
diff --git a/lib/Froxlor/Settings/Store.php b/lib/Froxlor/Settings/Store.php
index 5a506e87..baaf3a93 100644
--- a/lib/Froxlor/Settings/Store.php
+++ b/lib/Froxlor/Settings/Store.php
@@ -110,7 +110,6 @@ class Store
*/
public static function storeSettingDefaultTheme($fieldname, $fielddata, $newfieldvalue)
{
-
// first save the setting itself
$returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue);
From 5dfb74701c2b4e15afcb0b492907defd505140b7 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 25 Jun 2019 11:10:32 +0200
Subject: [PATCH 025/159] improve error message display on missing
vendor-folder
Signed-off-by: Michael Kaufmann
---
install/install.php | 9 +++-
lib/init.php | 18 +++++---
templates/Sparkle/misc/ownershiphint.tpl | 2 +-
templates/Sparkle/misc/vendormissinghint.tpl | 45 ++++++++++++++++++++
4 files changed, 65 insertions(+), 9 deletions(-)
create mode 100644 templates/Sparkle/misc/vendormissinghint.tpl
diff --git a/install/install.php b/install/install.php
index 76723290..7a258149 100644
--- a/install/install.php
+++ b/install/install.php
@@ -15,8 +15,13 @@
* @package Install
*
*/
-if(!file_exists(dirname(__DIR__) . '/vendor/autoload.php')){
- die('Vendor does not exist. Please run "composer install". For more informationen https://github.com/Froxlor/Froxlor/wiki');
+if (! file_exists(dirname(__DIR__) . '/vendor/autoload.php')) {
+ // get hint-template
+ $vendor_hint = file_get_contents(dirname(__DIR__) . '/templates/Sparkle/misc/vendormissinghint.tpl');
+ // replace values
+ $vendor_hint = str_replace("", dirname(__DIR__), $vendor_hint);
+ $vendor_hint = str_replace("", date('Y', time()), $vendor_hint);
+ die($vendor_hint);
}
require dirname(__DIR__) . '/vendor/autoload.php';
require __DIR__ . '/lib/class.FroxlorInstall.php';
diff --git a/lib/init.php b/lib/init.php
index bec161f6..e3a050b5 100644
--- a/lib/init.php
+++ b/lib/init.php
@@ -16,8 +16,17 @@
* @package System
*
*/
-if(!file_exists(dirname(__DIR__) . '/vendor/autoload.php')){
- die('Vendor does not exist. Please run "composer install". For more informationen https://github.com/Froxlor/Froxlor/wiki');
+
+// define default theme for configurehint, etc.
+$_deftheme = 'Sparkle';
+
+if (! file_exists(dirname(__DIR__) . '/vendor/autoload.php')) {
+ // get hint-template
+ $vendor_hint = file_get_contents(dirname(__DIR__) . '/templates/' . $_deftheme . '/misc/vendormissinghint.tpl');
+ // replace values
+ $vendor_hint = str_replace("", dirname(__DIR__), $vendor_hint);
+ $vendor_hint = str_replace("", date('Y', time()), $vendor_hint);
+ die($vendor_hint);
}
require dirname(__DIR__) . '/vendor/autoload.php';
@@ -72,9 +81,6 @@ unset($key);
$filename = htmlentities(basename($_SERVER['PHP_SELF']));
-// define default theme for configurehint, etc.
-$_deftheme = 'Sparkle';
-
// check whether the userdata file exists
if (! file_exists(\Froxlor\Froxlor::getInstallDir() . '/lib/userdata.inc.php')) {
$config_hint = file_get_contents(\Froxlor\Froxlor::getInstallDir() . '/templates/' . $_deftheme . '/misc/configurehint.tpl');
@@ -92,7 +98,7 @@ if (! is_readable(\Froxlor\Froxlor::getInstallDir() . '/lib/userdata.inc.php'))
// replace values
$owner_hint = str_replace("", $posixusername['name'], $owner_hint);
$owner_hint = str_replace("", $posixgroup['name'], $owner_hint);
- $owner_hint = str_replace("<\Froxlor\Froxlor::getInstallDir()>", \Froxlor\Froxlor::getInstallDir(), $owner_hint);
+ $owner_hint = str_replace("", \Froxlor\Froxlor::getInstallDir(), $owner_hint);
$owner_hint = str_replace("", date('Y', time()), $owner_hint);
// show
die($owner_hint);
diff --git a/templates/Sparkle/misc/ownershiphint.tpl b/templates/Sparkle/misc/ownershiphint.tpl
index 9ab32641..ec510e87 100644
--- a/templates/Sparkle/misc/ownershiphint.tpl
+++ b/templates/Sparkle/misc/ownershiphint.tpl
@@ -25,7 +25,7 @@
This mostly happens due to wrong ownership. Try the following command to correct the ownership:
-
chown -R : <\Froxlor\Froxlor::getInstallDir()>
+
chown -R :
diff --git a/templates/Sparkle/misc/vendormissinghint.tpl b/templates/Sparkle/misc/vendormissinghint.tpl
new file mode 100644
index 00000000..69efff5a
--- /dev/null
+++ b/templates/Sparkle/misc/vendormissinghint.tpl
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+ Froxlor Server Management Panel - Installation
+
+
+
+
+
+
+
+
+
+
+
+
Whoops!
+
+
It seems you are missing some required files.
+
+
Froxlor uses composer for its external requirements. Try the following command to install them:
+
+
cd && composer install --no-dev
+
+
+
+
+
+
+
+
+
+
+
From e209989f2a6537c23dbbb40dbf7ea6ac590f2688 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Fri, 28 Jun 2019 11:07:29 +0200
Subject: [PATCH 026/159] use EmailAccounts.delete API call in Emails.delete
instead of repeating the code
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Api/Commands/Emails.php | 26 ++++++--------------------
1 file changed, 6 insertions(+), 20 deletions(-)
diff --git a/lib/Froxlor/Api/Commands/Emails.php b/lib/Froxlor/Api/Commands/Emails.php
index ef26a57e..f4cb959a 100644
--- a/lib/Froxlor/Api/Commands/Emails.php
+++ b/lib/Froxlor/Api/Commands/Emails.php
@@ -340,26 +340,12 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
}
// check whether this address is an account
if ($result['popaccountid'] != 0) {
- // Free the Quota used by the email account
- if (Settings::Get('system.mail_quota_enabled') == 1) {
- $stmt = Database::prepare("SELECT `quota` FROM `" . TABLE_MAIL_USERS . "` WHERE `customerid`= :customerid AND `id`= :id");
- $res_quota = Database::pexecute_first($stmt, array(
- "customerid" => $customer['customerid'],
- "id" => $result['popaccountid']
- ), true, true);
- Customers::decreaseUsage($customer['customerid'], 'email_quota_used', '', $res_quota['quota']);
- Admins::decreaseUsage($customer['customerid'], 'email_quota_used', '', $res_quota['quota']);
- $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted quota entries for email address '" . $result['email_full'] . "'");
- }
- // delete account
- $stmt = Database::prepare("DELETE FROM `" . TABLE_MAIL_USERS . "` WHERE `customerid`= :customerid AND `id`= :id");
- Database::pexecute($stmt, array(
- "customerid" => $customer['customerid'],
- "id" => $result['popaccountid']
- ), true, true);
- Customers::decreaseUsage($customer['customerid'], 'email_accounts_used');
- Admins::decreaseUsage($customer['customerid'], 'email_accounts_used');
- $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted email account '" . $result['email_full'] . "'");
+ // use EmailAccounts.delete
+ $this->apiCall('EmailAccounts.delete', array(
+ 'id' => $result['id'],
+ 'customerid' => $customer['customerid'],
+ 'delete_userfiles' => $delete_userfiles
+ ));
$number_forwarders --;
}
From 2ce517e84a6848962f6a9698a4524d9acb1166ca Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Fri, 28 Jun 2019 15:15:17 +0200
Subject: [PATCH 027/159] use Fts.add when adding new Customers to reduce
duplicate code
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Api/Commands/Customers.php | 59 ++++++++------------------
lib/Froxlor/Api/Commands/Ftps.php | 38 ++++++++++++++---
lib/Froxlor/FileDir.php | 2 +-
3 files changed, 51 insertions(+), 48 deletions(-)
diff --git a/lib/Froxlor/Api/Commands/Customers.php b/lib/Froxlor/Api/Commands/Customers.php
index 273ecd10..f888ad0f 100644
--- a/lib/Froxlor/Api/Commands/Customers.php
+++ b/lib/Froxlor/Api/Commands/Customers.php
@@ -543,37 +543,14 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
Database::pexecute($ins_stmt, $ins_data, true, true);
\Froxlor\System\Cronjob::inserttask('1');
- $cryptPassword = \Froxlor\System\Crypt::makeCryptPassword($password);
- // add FTP-User
- // @fixme use Ftp-ApiCommand later
- $ins_stmt = Database::prepare("
- INSERT INTO `" . TABLE_FTP_USERS . "` SET `customerid` = :customerid, `username` = :username, `description` = :desc,
- `password` = :passwd, `homedir` = :homedir, `login_enabled` = 'y', `uid` = :guid, `gid` = :guid
- ");
- $ins_data = array(
- 'customerid' => $customerid,
- 'username' => $loginname,
- 'passwd' => $cryptPassword,
- 'homedir' => $documentroot,
- 'guid' => $guid,
- 'desc' => "Default"
- );
- Database::pexecute($ins_stmt, $ins_data, true, true);
- // add FTP-Group
- // @fixme use Ftp-ApiCommand later
- $ins_stmt = Database::prepare("
- INSERT INTO `" . TABLE_FTP_GROUPS . "` SET `customerid` = :customerid, `groupname` = :groupname, `gid` = :guid, `members` = :members
- ");
- $ins_data = array(
- 'customerid' => $customerid,
- 'groupname' => $loginname,
- 'guid' => $guid,
- 'members' => $loginname . ',' . Settings::Get('system.httpuser')
- );
+ // add default FTP-User
// also, add froxlor-local user to ftp-group (if exists!) to
// allow access to customer-directories from within the panel, which
// is necessary when pathedit = Dropdown
+ $local_users = array(
+ Settings::Get('system.httpuser')
+ );
if ((int) Settings::Get('system.mod_fcgid_ownvhost') == 1 || (int) Settings::Get('phpfpm.enabled_ownvhost') == 1) {
if ((int) Settings::Get('system.mod_fcgid') == 1) {
$local_user = Settings::Get('system.mod_fcgid_httpuser');
@@ -582,22 +559,20 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
}
// check froxlor-local user membership in ftp-group
// without this check addition may duplicate user in list if httpuser == local_user
- if (strpos($ins_data['members'], $local_user) == false) {
- $ins_data['members'] .= ',' . $local_user;
+ if (in_array($local_user, $local_users) == false) {
+ $local_users[] = $local_user;
}
}
- Database::pexecute($ins_stmt, $ins_data, true, true);
-
- // FTP-Quotatallies
- // @fixme use Ftp-ApiCommand later
- $ins_stmt = Database::prepare("
- INSERT INTO `" . TABLE_FTP_QUOTATALLIES . "` SET `name` = :name, `quota_type` = 'user', `bytes_in_used` = '0',
- `bytes_out_used` = '0', `bytes_xfer_used` = '0', `files_in_used` = '0', `files_out_used` = '0', `files_xfer_used` = '0'
- ");
- Database::pexecute($ins_stmt, array(
- 'name' => $loginname
- ), true, true);
- $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] automatically added ftp-account for user '" . $loginname . "'");
+ $this->apiCall('Ftps.add', array(
+ 'customerid' => $customerid,
+ 'path' => $documentroot,
+ 'ftp_password' => $password,
+ 'ftp_description' => "Default",
+ 'sendinfomail' => 0,
+ 'ftp_username' => $loginname,
+ 'additional_members' => $local_users,
+ 'is_defaultuser' => 1
+ ));
$_stdsubdomain = '';
if ($createstdsubdomain == '1') {
@@ -898,7 +873,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true));
$customernumber = \Froxlor\Validate\Validate::validate($customernumber, 'customer number', '/^[A-Za-z0-9 \-]*$/Di', '', array(), true);
$custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', '/^[^\0]*$/', '', array(), true);
- if (!empty($allowed_phpconfigs)) {
+ if (! empty($allowed_phpconfigs)) {
$allowed_phpconfigs = array_map('intval', $allowed_phpconfigs);
}
}
diff --git a/lib/Froxlor/Api/Commands/Ftps.php b/lib/Froxlor/Api/Commands/Ftps.php
index 31f949d0..ec52947e 100644
--- a/lib/Froxlor/Api/Commands/Ftps.php
+++ b/lib/Froxlor/Api/Commands/Ftps.php
@@ -41,6 +41,10 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
* optional if customer.ftpatdomain is allowed, specify a domain (customer must be owner)
* @param int $customerid
* required when called as admin, not needed when called as customer
+ * @param array $additional_members
+ * optional whether to add additional usernames to the group
+ * @param bool $is_defaultuser
+ * optional whether this is the standard default ftp user which is being added so no usage is decreased
*
* @access admin, customer
* @throws \Exception
@@ -66,6 +70,9 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
$ftpusername = $this->getParam('ftp_username', true, '');
$ftpdomain = $this->getParam('ftp_domain', true, '');
+ $additional_members = $this->getParam('additional_members', true, array());
+ $is_defaultuser = $this->getBoolParam('is_defaultuser', true, 0);
+
// validation
$password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true);
$password = \Froxlor\System\Crypt::validatePassword($password, true);
@@ -87,7 +94,12 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
$params = array();
// get needed customer info to reduce the ftp-user-counter by one
- $customer = $this->getCustomerData('ftps');
+ if ($is_defaultuser) {
+ // no resource check for default user
+ $customer = $this->getCustomerData();
+ } else {
+ $customer = $this->getCustomerData('ftps');
+ }
if ($sendinfomail != 1) {
$sendinfomail = 0;
@@ -113,7 +125,11 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
}
$username = $ftpusername . "@" . $ftpdomain;
} else {
- $username = $customer['loginname'] . Settings::Get('customer.ftpprefix') . (intval($customer['ftp_lastaccountnumber']) + 1);
+ if ($is_defaultuser) {
+ $username = $customer['loginname'];
+ } else {
+ $username = $customer['loginname'] . Settings::Get('customer.ftpprefix') . (intval($customer['ftp_lastaccountnumber']) + 1);
+ }
}
$username_check_stmt = Database::prepare("
@@ -175,10 +191,22 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
);
Database::pexecute($stmt, $params, true, true);
- // update customer usage
- Customers::increaseUsage($customer['customerid'], 'ftps_used');
- Customers::increaseUsage($customer['customerid'], 'ftp_lastaccountnumber');
+ if (count($additional_members) > 0) {
+ foreach ($additional_members as $add_member) {
+ $params = array(
+ "username" => $add_member,
+ "customerid" => $customer['customerid'],
+ "guid" => $customer['guid']
+ );
+ Database::pexecute($stmt, $params, true, true);
+ }
+ }
+ // update customer usage
+ if (! $is_defaultuser) {
+ Customers::increaseUsage($customer['customerid'], 'ftps_used');
+ Customers::increaseUsage($customer['customerid'], 'ftp_lastaccountnumber');
+ }
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added ftp-account '" . $username . " (" . $path . ")'");
\Froxlor\System\Cronjob::inserttask(5);
diff --git a/lib/Froxlor/FileDir.php b/lib/Froxlor/FileDir.php
index 700ef2f7..d7a5e55c 100644
--- a/lib/Froxlor/FileDir.php
+++ b/lib/Froxlor/FileDir.php
@@ -217,7 +217,7 @@ class FileDir
'ADMIN_EMAIL' => $template['admin_email']
);
- // @fixme replaceVariables
+ // replaceVariables
$htmlcontent = PhpHelper::replaceVariables($template['value'], $replace_arr);
$indexhtmlpath = self::makeCorrectFile($destination . '/index.' . Settings::Get('system.index_file_extension'));
$index_html_handler = fopen($indexhtmlpath, 'w');
From 01bf81449636384d8a4494813b0a40764b0f8113 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Mon, 1 Jul 2019 20:32:13 +0200
Subject: [PATCH 028/159] remove domain ssl information from acme.sh and
filesystem on deletion to avoid trying to renew certificates
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Api/Commands/Domains.php | 3 +++
lib/Froxlor/Api/Commands/SubDomains.php | 2 ++
lib/Froxlor/Cron/System/TasksCron.php | 6 ++++++
lib/Froxlor/Domain/Domain.php | 24 ++++++++++++++++++++++++
lib/Froxlor/System/Cronjob.php | 8 ++++++++
5 files changed, 43 insertions(+)
diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php
index 79009efd..550d7da3 100644
--- a/lib/Froxlor/Api/Commands/Domains.php
+++ b/lib/Froxlor/Api/Commands/Domains.php
@@ -1619,6 +1619,9 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
// remove domains DNS from powerDNS if used, #581
\Froxlor\System\Cronjob::inserttask('11', $result['domain']);
+ // remove domain from acme.sh / lets encrypt if used
+ \Froxlor\System\Cronjob::inserttask('12', $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');
diff --git a/lib/Froxlor/Api/Commands/SubDomains.php b/lib/Froxlor/Api/Commands/SubDomains.php
index 4588a73d..59eb8298 100644
--- a/lib/Froxlor/Api/Commands/SubDomains.php
+++ b/lib/Froxlor/Api/Commands/SubDomains.php
@@ -828,6 +828,8 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
\Froxlor\System\Cronjob::inserttask('4');
// remove domains DNS from powerDNS if used, #581
\Froxlor\System\Cronjob::inserttask('11', $result['domain']);
+ // remove domain from acme.sh / lets encrypt if used
+ \Froxlor\System\Cronjob::inserttask('12', $result['domain']);
// reduce subdomain-usage-counter
Customers::decreaseUsage($customer['customerid'], 'subdomains_used');
diff --git a/lib/Froxlor/Cron/System/TasksCron.php b/lib/Froxlor/Cron/System/TasksCron.php
index 6cf0ea7e..ffa10f5c 100644
--- a/lib/Froxlor/Cron/System/TasksCron.php
+++ b/lib/Froxlor/Cron/System/TasksCron.php
@@ -92,6 +92,12 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
*/
\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') {
+ /**
+ * TYPE=12 domain has been deleted, remove from acme.sh/let's encrypt directory if used
+ */
+ \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, "Removing Let's Encrypt entries for domain " . $row['data']['domain']);
+ \Froxlor\Domain\Domain::doLetsEncryptCleanUp($row['data']['domain']);
}
}
diff --git a/lib/Froxlor/Domain/Domain.php b/lib/Froxlor/Domain/Domain.php
index b952e467..34e38238 100644
--- a/lib/Froxlor/Domain/Domain.php
+++ b/lib/Froxlor/Domain/Domain.php
@@ -291,6 +291,30 @@ class Domain
}
}
+ public static function doLetsEncryptCleanUp($domainname = null)
+ {
+ // @ see \Froxlor\Cron\Http\LetsEncrypt\AcmeSh.php
+ $acmesh = "/root/.acme.sh/acme.sh";
+ if (file_exists($acmesh)) {
+ $certificate_folder = dirname($acmesh) . "/" . $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) {
+ $params .= " -ecc";
+ }
+ // run remove command
+ \Froxlor\FileDir::safe_exec($acmesh . $params);
+ // remove certificates directory
+ @unlink($certificate_folder);
+ }
+ }
+ return true;
+ }
+
/**
* checks give path for security issues
* and returns a string that can be appended
diff --git a/lib/Froxlor/System/Cronjob.php b/lib/Froxlor/System/Cronjob.php
index bf7debfa..f5b32fe1 100644
--- a/lib/Froxlor/System/Cronjob.php
+++ b/lib/Froxlor/System/Cronjob.php
@@ -178,6 +178,14 @@ class Cronjob
'type' => '11',
'data' => $data
));
+ } elseif ($type == '12' && $param1 != '') {
+ $data = array();
+ $data['domain'] = $param1;
+ $data = json_encode($data);
+ Database::pexecute($ins_stmt, array(
+ 'type' => '12',
+ 'data' => $data
+ ));
} elseif ($type == '20' && is_array($param1)) {
$data = json_encode($param1);
Database::pexecute($ins_stmt, array(
From c43915c09d662803ea14cf5280f69174053512f4 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Wed, 3 Jul 2019 12:00:47 +0200
Subject: [PATCH 029/159] show task 12 in admin dashboard overview if active
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/System/Cronjob.php | 3 +++
lng/english.lng.php | 1 +
lng/german.lng.php | 1 +
3 files changed, 5 insertions(+)
diff --git a/lib/Froxlor/System/Cronjob.php b/lib/Froxlor/System/Cronjob.php
index f5b32fe1..660dd075 100644
--- a/lib/Froxlor/System/Cronjob.php
+++ b/lib/Froxlor/System/Cronjob.php
@@ -285,6 +285,9 @@ class Cronjob
} 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 = '';
diff --git a/lng/english.lng.php b/lng/english.lng.php
index bf55b07b..e76477c5 100644
--- a/lng/english.lng.php
+++ b/lng/english.lng.php
@@ -2051,6 +2051,7 @@ $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['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 4e150a75..f1f44c27 100644
--- a/lng/german.lng.php
+++ b/lng/german.lng.php
@@ -1698,6 +1698,7 @@ $lng['panel']['system_is_configured'] = 'Das System ist bereits konfiguriert';
$lng['panel']['settings_before_configuration'] = 'Stelle sicher, dass die Einstellungen angepasst wurden bevor die Dienste konfiguriert werden.';
$lng['panel']['alternative_cmdline_config'] = 'Alternativ, führe den folgenden Befehl als root-Benutzer auf der Shell aus, um die Dienste automatisch zu konfigurieren.';
$lng['tasks']['remove_pdns_domain'] = 'Lösche Domain %s von PowerDNS Datenbank';
+$lng['tasks']['remove_ssl_domain'] = 'Lösche SSL Dateien von Domain %s';
$lng['admin']['novhostcontainer'] = 'Keine der IPs und Ports hat die Option "' . $lng['admin']['ipsandports']['create_vhostcontainer'] . '" aktiviert, einige Einstellungen sind daher nicht verfügbar. ';
$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.';
From 98325a0f4089aca5ce69097ba0b8f7c2c5509692 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Wed, 3 Jul 2019 18:07:02 +0200
Subject: [PATCH 030/159] don't need NSCD when using libnss-extrausers
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Cron/MasterCron.php | 6 +++---
lib/Froxlor/Cron/System/TasksCron.php | 4 ++--
lib/configfiles/bionic.xml | 7 ++-----
lib/configfiles/buster.xml | 7 ++-----
lib/configfiles/jessie.xml | 9 +++------
lib/configfiles/stretch.xml | 7 ++-----
lib/configfiles/trusty.xml | 9 +++------
lib/configfiles/xenial.xml | 7 ++-----
8 files changed, 19 insertions(+), 37 deletions(-)
diff --git a/lib/Froxlor/Cron/MasterCron.php b/lib/Froxlor/Cron/MasterCron.php
index 48ca32ee..861f6522 100644
--- a/lib/Froxlor/Cron/MasterCron.php
+++ b/lib/Froxlor/Cron/MasterCron.php
@@ -90,7 +90,7 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
$tasks_cnt_stmt = \Froxlor\Database\Database::query("SELECT COUNT(*) as jobcnt FROM `panel_tasks`");
$tasks_cnt = $tasks_cnt_stmt->fetch(\PDO::FETCH_ASSOC);
-
+
// do we have anything to include?
if (count($jobs_to_run) > 0) {
// include all jobs we want to execute
@@ -107,8 +107,8 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
\Froxlor\Cron\System\Extrausers::generateFiles(self::$cronlog);
}
- // clear NSCD cache if using fcgid or fpm, #1570
- if (\Froxlor\Settings::Get('system.mod_fcgid') == 1 || (int) \Froxlor\Settings::Get('phpfpm.enabled') == 1) {
+ // clear NSCD cache if using fcgid or fpm, #1570 - not needed for nss-extrausers
+ if ((\Froxlor\Settings::Get('system.mod_fcgid') == 1 || (int) \Froxlor\Settings::Get('phpfpm.enabled') == 1) && \Froxlor\Settings::Get('system.nssextrausers') == 0) {
$false_val = false;
\Froxlor\FileDir::safe_exec('nscd -i passwd 1> /dev/null', $false_val, array(
'>'
diff --git a/lib/Froxlor/Cron/System/TasksCron.php b/lib/Froxlor/Cron/System/TasksCron.php
index ffa10f5c..2ceb1db9 100644
--- a/lib/Froxlor/Cron/System/TasksCron.php
+++ b/lib/Froxlor/Cron/System/TasksCron.php
@@ -237,8 +237,8 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
Extrausers::generateFiles($extrausers_log);
}
- // clear NSCD cache if using fcgid or fpm, #1570
- if (Settings::Get('system.mod_fcgid') == 1 || (int) Settings::Get('phpfpm.enabled') == 1) {
+ // clear NSCD cache if using fcgid or fpm, #1570 - not needed for nss-extrausers
+ if ((Settings::Get('system.mod_fcgid') == 1 || (int) Settings::Get('phpfpm.enabled') == 1) && Settings::Get('system.nssextrausers') == 0) {
$false_val = false;
\Froxlor\FileDir::safe_exec('nscd -i passwd 1> /dev/null', $false_val, array(
'>'
diff --git a/lib/configfiles/bionic.xml b/lib/configfiles/bionic.xml
index 314e1527..30fe1d6f 100644
--- a/lib/configfiles/bionic.xml
+++ b/lib/configfiles/bionic.xml
@@ -4568,8 +4568,8 @@ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
-
+ title="libnss-extrausers (required for FCGID/php-fpm/mpm-itk)">
+
@@ -4601,9 +4601,6 @@ aliases: files
]]>
-
-
-
diff --git a/lib/configfiles/buster.xml b/lib/configfiles/buster.xml
index f45784da..0d3cea61 100644
--- a/lib/configfiles/buster.xml
+++ b/lib/configfiles/buster.xml
@@ -4763,8 +4763,8 @@ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
-
+ title="libnss-extrausers (required for FCGID/php-fpm/mpm-itk)">
+
@@ -4796,9 +4796,6 @@ aliases: files
]]>
-
-
-
diff --git a/lib/configfiles/jessie.xml b/lib/configfiles/jessie.xml
index 2019e1c8..98f22751 100644
--- a/lib/configfiles/jessie.xml
+++ b/lib/configfiles/jessie.xml
@@ -4490,7 +4490,7 @@ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+ title="libnss-mysql (alternative for libnss-extrausers, required for FCGID/php-fpm/mpm-itk)">
-
+ title="libnss-extrausers (required for FCGID/php-fpm/mpm-itk)">
+
@@ -4696,9 +4696,6 @@ aliases: files
]]>
-
-
-
diff --git a/lib/configfiles/stretch.xml b/lib/configfiles/stretch.xml
index e79883cc..6dab29fc 100644
--- a/lib/configfiles/stretch.xml
+++ b/lib/configfiles/stretch.xml
@@ -4557,8 +4557,8 @@ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
-
+ title="libnss-extrausers (required for FCGID/php-fpm/mpm-itk)">
+
@@ -4590,9 +4590,6 @@ aliases: files
]]>
-
-
-
diff --git a/lib/configfiles/trusty.xml b/lib/configfiles/trusty.xml
index a37ea010..9613a357 100644
--- a/lib/configfiles/trusty.xml
+++ b/lib/configfiles/trusty.xml
@@ -1575,7 +1575,7 @@ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+ title="libnss-mysql (alternative to libnss-extrausers, required for FCGID/php-fpm/mpm-itk)">
@@ -1671,8 +1671,8 @@ aliases: files
-
+ title="libnss-extrausers (required for FCGID/php-fpm/mpm-itk)">
+
@@ -1704,9 +1704,6 @@ aliases: files
]]>
-
-
-
diff --git a/lib/configfiles/xenial.xml b/lib/configfiles/xenial.xml
index 50fc87c1..8df99edf 100644
--- a/lib/configfiles/xenial.xml
+++ b/lib/configfiles/xenial.xml
@@ -4568,8 +4568,8 @@ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
-
+ title="libnss-extrausers (required for FCGID/php-fpm/mpm-itk)">
+
@@ -4601,9 +4601,6 @@ aliases: files
]]>
-
-
-
From fd912dd161f1040792fcadef9eab7a28fe10cdde Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 9 Jul 2019 07:13:02 +0200
Subject: [PATCH 031/159] combine webserver-reload command to parent class to
avoid repeating code
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Cron/Http/Apache.php | 25 -----------------
lib/Froxlor/Cron/Http/ConfigIO.php | 4 +--
lib/Froxlor/Cron/Http/HttpConfigBase.php | 34 +++++++++++++++++++++++
lib/Froxlor/Cron/Http/Lighttpd.php | 34 +++--------------------
lib/Froxlor/Cron/Http/Nginx.php | 35 +-----------------------
5 files changed, 41 insertions(+), 91 deletions(-)
diff --git a/lib/Froxlor/Cron/Http/Apache.php b/lib/Froxlor/Cron/Http/Apache.php
index 6b7d762b..dec06991 100644
--- a/lib/Froxlor/Cron/Http/Apache.php
+++ b/lib/Froxlor/Cron/Http/Apache.php
@@ -3,7 +3,6 @@ namespace Froxlor\Cron\Http;
use Froxlor\Database\Database;
use Froxlor\Settings;
-use Froxlor\Cron\Http\Php\Fpm;
use Froxlor\Cron\Http\Php\PhpInterface;
/**
@@ -46,30 +45,6 @@ class Apache extends HttpConfigBase
*/
private $deactivated = false;
- public function reload()
- {
- if ((int) Settings::Get('phpfpm.enabled') == 1) {
- // get all start/stop commands
- $startstop_sel = Database::prepare("SELECT reload_cmd, config_dir FROM `" . TABLE_PANEL_FPMDAEMONS . "`");
- Database::pexecute($startstop_sel);
- $restart_cmds = $startstop_sel->fetchAll(\PDO::FETCH_ASSOC);
- // restart all php-fpm instances
- foreach ($restart_cmds as $restart_cmd) {
- // check whether the config dir is empty (no domains uses this daemon)
- // so we need to create a dummy
- $_conffiles = glob(\Froxlor\FileDir::makeCorrectFile($restart_cmd['config_dir'] . "/*.conf"));
- if ($_conffiles === false || empty($_conffiles)) {
- \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'apache::reload: fpm config directory "' . $restart_cmd['config_dir'] . '" is empty. Creating dummy.');
- Fpm::createDummyPool($restart_cmd['config_dir']);
- }
- \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'apache::reload: running ' . $restart_cmd['reload_cmd']);
- \Froxlor\FileDir::safe_exec(escapeshellcmd($restart_cmd['reload_cmd']));
- }
- }
- \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'apache::reload: reloading apache');
- \Froxlor\FileDir::safe_exec(escapeshellcmd(Settings::Get('system.apachereload_command')));
- }
-
/**
* define a standard -statement, bug #32
*/
diff --git a/lib/Froxlor/Cron/Http/ConfigIO.php b/lib/Froxlor/Cron/Http/ConfigIO.php
index a87e7a72..f82159a5 100644
--- a/lib/Froxlor/Cron/Http/ConfigIO.php
+++ b/lib/Froxlor/Cron/Http/ConfigIO.php
@@ -128,7 +128,7 @@ class ConfigIO
// iterate through all subdirs,
// look for vhost/diroption files
// and delete them
- foreach ($its as $fullFileName => $it) {
+ foreach ($its as $it) {
if ($it->isFile() && preg_match($pattern, $it->getFilename())) {
// remove file
\Froxlor\FileDir::safe_exec('rm -f ' . escapeshellarg(\Froxlor\FileDir::makeCorrectFile($its->getPathname())));
@@ -232,7 +232,7 @@ class ConfigIO
// look for php-fcgi-starter files
// and take immutable-flag away from them
// so we can delete them :)
- foreach ($its as $fullFileName => $it) {
+ foreach ($its as $it) {
if ($it->isFile() && $it->getFilename() == 'php-fcgi-starter') {
// set chattr -i
\Froxlor\FileDir::removeImmutable($its->getPathname());
diff --git a/lib/Froxlor/Cron/Http/HttpConfigBase.php b/lib/Froxlor/Cron/Http/HttpConfigBase.php
index 9e6daf20..3deeb8f0 100644
--- a/lib/Froxlor/Cron/Http/HttpConfigBase.php
+++ b/lib/Froxlor/Cron/Http/HttpConfigBase.php
@@ -3,6 +3,7 @@ namespace Froxlor\Cron\Http;
use Froxlor\Database\Database;
use Froxlor\Settings;
+use Froxlor\Cron\Http\Php\Fpm;
/**
* This file is part of the Froxlor project.
@@ -27,6 +28,39 @@ use Froxlor\Settings;
class HttpConfigBase
{
+ public function reload()
+ {
+ $called_class = get_called_class();
+ if ((int) Settings::Get('phpfpm.enabled') == 1) {
+ // get all start/stop commands
+ $startstop_sel = Database::prepare("SELECT reload_cmd, config_dir FROM `" . TABLE_PANEL_FPMDAEMONS . "`");
+ Database::pexecute($startstop_sel);
+ $restart_cmds = $startstop_sel->fetchAll(\PDO::FETCH_ASSOC);
+ // restart all php-fpm instances
+ foreach ($restart_cmds as $restart_cmd) {
+ // check whether the config dir is empty (no domains uses this daemon)
+ // so we need to create a dummy
+ $_conffiles = glob(\Froxlor\FileDir::makeCorrectFile($restart_cmd['config_dir'] . "/*.conf"));
+ if ($_conffiles === false || empty($_conffiles)) {
+ \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, $called_class . '::reload: fpm config directory "' . $restart_cmd['config_dir'] . '" is empty. Creating dummy.');
+ Fpm::createDummyPool($restart_cmd['config_dir']);
+ }
+ \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, $called_class . '::reload: running ' . $restart_cmd['reload_cmd']);
+ \Froxlor\FileDir::safe_exec(escapeshellcmd($restart_cmd['reload_cmd']));
+ }
+ }
+ \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, $called_class . '::reload: reloading ' . $called_class);
+ \Froxlor\FileDir::safe_exec(escapeshellcmd(Settings::Get('system.apachereload_command')));
+
+ /**
+ * nginx does not auto-spawn fcgi-processes
+ */
+ if (Settings::Get('system.webserver') == "nginx" && Settings::Get('system.phpreload_command') != '' && (int) Settings::Get('phpfpm.enabled') == 0) {
+ \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, $called_class . '::reload: restarting php processes');
+ \Froxlor\FileDir::safe_exec(Settings::Get('system.phpreload_command'));
+ }
+ }
+
/**
* process special config as template, by substituting {VARIABLE} with the
* respective value.
diff --git a/lib/Froxlor/Cron/Http/Lighttpd.php b/lib/Froxlor/Cron/Http/Lighttpd.php
index fd15c2b1..b57a5aeb 100644
--- a/lib/Froxlor/Cron/Http/Lighttpd.php
+++ b/lib/Froxlor/Cron/Http/Lighttpd.php
@@ -3,7 +3,6 @@ namespace Froxlor\Cron\Http;
use Froxlor\Database\Database;
use Froxlor\Settings;
-use Froxlor\Cron\Http\Php\Fpm;
use Froxlor\Cron\Http\Php\PhpInterface;
/**
@@ -45,30 +44,6 @@ class Lighttpd extends HttpConfigBase
*/
private $deactivated = false;
- public function reload()
- {
- if ((int) Settings::Get('phpfpm.enabled') == 1) {
- // get all start/stop commands
- $startstop_sel = Database::prepare("SELECT reload_cmd, config_dir FROM `" . TABLE_PANEL_FPMDAEMONS . "`");
- Database::pexecute($startstop_sel);
- $restart_cmds = $startstop_sel->fetchAll(\PDO::FETCH_ASSOC);
- // restart all php-fpm instances
- foreach ($restart_cmds as $restart_cmd) {
- // check whether the config dir is empty (no domains uses this daemon)
- // so we need to create a dummy
- $_conffiles = glob(\Froxlor\FileDir::makeCorrectFile($restart_cmd['config_dir'] . "/*.conf"));
- if ($_conffiles === false || empty($_conffiles)) {
- $this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'lighttpd::reload: fpm config directory "' . $restart_cmd['config_dir'] . '" is empty. Creating dummy.');
- Fpm::createDummyPool($restart_cmd['config_dir']);
- }
- $this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'lighttpd::reload: running ' . $restart_cmd['reload_cmd']);
- \Froxlor\FileDir::safe_exec(escapeshellcmd($restart_cmd['reload_cmd']));
- }
- }
- $this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'lighttpd::reload: reloading lighttpd');
- \Froxlor\FileDir::safe_exec(escapeshellcmd(Settings::Get('system.apachereload_command')));
- }
-
public function createIpPort()
{
$result_ipsandports_stmt = Database::query("SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` ORDER BY `ip` ASC, `port` ASC");
@@ -396,6 +371,7 @@ class Lighttpd extends HttpConfigBase
protected function createLighttpdHosts($ipid, $ssl, $vhost_filename)
{
$domains = WebserverBase::getVhostsToCreate();
+ $included_vhosts = array();
foreach ($domains as $domain) {
if (is_dir(Settings::Get('system.apacheconf_vhost'))) {
@@ -765,23 +741,21 @@ class Lighttpd extends HttpConfigBase
));
while ($row_htpasswds = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
- if ($auth_backend_loaded[$domain['ipandport']] != 'yes' && $auth_backend_loaded[$domain['ssl_ipandport']] != 'yes') {
+ if ($this->auth_backend_loaded[$domain['ipandport']] != 'yes' && $this->auth_backend_loaded[$domain['ssl_ipandport']] != 'yes') {
$filename = $domain['customerid'] . '.htpasswd';
if ($this->auth_backend_loaded[$domain['ipandport']] != 'yes') {
- $auth_backend_loaded[$domain['ipandport']] = 'yes';
+ $this->auth_backend_loaded[$domain['ipandport']] = 'yes';
$diroption_text .= 'auth.backend = "htpasswd"' . "\n";
$diroption_text .= 'auth.backend.htpasswd.userfile = "' . \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_htpasswddir') . '/' . $filename) . '"' . "\n";
$this->needed_htpasswds[$filename] = $row_htpasswds['username'] . ':' . $row_htpasswds['password'] . "\n";
$diroption_text .= 'auth.require = ( ' . "\n";
- $previous_domain_id = '1';
} elseif ($this->auth_backend_loaded[$domain['ssl_ipandport']] != 'yes') {
- $auth_backend_loaded[$domain['ssl_ipandport']] = 'yes';
+ $this->auth_backend_loaded[$domain['ssl_ipandport']] = 'yes';
$diroption_text .= 'auth.backend= "htpasswd"' . "\n";
$diroption_text .= 'auth.backend.htpasswd.userfile = "' . \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_htpasswddir') . '/' . $filename) . '"' . "\n";
$this->needed_htpasswds[$filename] = $row_htpasswds['username'] . ':' . $row_htpasswds['password'] . "\n";
$diroption_text .= 'auth.require = ( ' . "\n";
- $previous_domain_id = '1';
}
}
diff --git a/lib/Froxlor/Cron/Http/Nginx.php b/lib/Froxlor/Cron/Http/Nginx.php
index c42f8775..42d8c063 100644
--- a/lib/Froxlor/Cron/Http/Nginx.php
+++ b/lib/Froxlor/Cron/Http/Nginx.php
@@ -3,7 +3,6 @@ namespace Froxlor\Cron\Http;
use Froxlor\Database\Database;
use Froxlor\Settings;
-use Froxlor\Cron\Http\Php\Fpm;
use Froxlor\Cron\Http\Php\PhpInterface;
/**
@@ -55,39 +54,6 @@ class Nginx extends HttpConfigBase
$this->nginx_server = $nginx_server;
}
- public function reload()
- {
- if ((int) Settings::Get('phpfpm.enabled') == 1) {
- // get all start/stop commands
- $startstop_sel = Database::prepare("SELECT reload_cmd, config_dir FROM `" . TABLE_PANEL_FPMDAEMONS . "`");
- Database::pexecute($startstop_sel);
- $restart_cmds = $startstop_sel->fetchAll(\PDO::FETCH_ASSOC);
- // restart all php-fpm instances
- foreach ($restart_cmds as $restart_cmd) {
- // check whether the config dir is empty (no domains uses this daemon)
- // so we need to create a dummy
- $_conffiles = glob(\Froxlor\FileDir::makeCorrectFile($restart_cmd['config_dir'] . "/*.conf"));
- if ($_conffiles === false || empty($_conffiles)) {
- \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'nginx::reload: fpm config directory "' . $restart_cmd['config_dir'] . '" is empty. Creating dummy.');
- Fpm::createDummyPool($restart_cmd['config_dir']);
- }
- \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'nginx::reload: running ' . $restart_cmd['reload_cmd']);
- \Froxlor\FileDir::safe_exec(escapeshellcmd($restart_cmd['reload_cmd']));
- }
- }
-
- \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'nginx::reload: reloading nginx');
- \Froxlor\FileDir::safe_exec(Settings::Get('system.apachereload_command'));
-
- /**
- * nginx does not auto-spawn fcgi-processes
- */
- if (Settings::Get('system.phpreload_command') != '' && (int) Settings::Get('phpfpm.enabled') == 0) {
- \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'nginx::reload: restarting php processes');
- \Froxlor\FileDir::safe_exec(Settings::Get('system.phpreload_command'));
- }
- }
-
private function createLogformatEntry()
{
if (Settings::Get('system.logfiles_format') != '') {
@@ -923,6 +889,7 @@ class Nginx extends HttpConfigBase
$path = \Froxlor\FileDir::makeCorrectDir(substr($row_htpasswds['path'], strlen($domain['documentroot']) - 1));
} else {
// if the website contents is located in a subdirectory of the user
+ $matches = array();
preg_match('/^([\/[:print:]]*\/)([[:print:]\/]+){1}$/i', $row_htpasswds['path'], $matches);
$path = \Froxlor\FileDir::makeCorrectDir(substr($row_htpasswds['path'], strlen($matches[1]) - 1));
}
From 0f0dd91246486fc25e48e04f7f1e9107124e8f69 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 9 Jul 2019 07:50:11 +0200
Subject: [PATCH 032/159] combine Let's Encrypt cron with
webserver-vhost-generation but allow manually execution using --debug/--force
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Cron/CronConfig.php | 1 +
lib/Froxlor/Cron/Http/HttpConfigBase.php | 10 +++++
lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 45 ++++++++++++--------
lib/Froxlor/Cron/MasterCron.php | 1 +
lib/Froxlor/Cron/System/TasksCron.php | 1 +
5 files changed, 40 insertions(+), 18 deletions(-)
diff --git a/lib/Froxlor/Cron/CronConfig.php b/lib/Froxlor/Cron/CronConfig.php
index e5916ed0..18b2f8d8 100644
--- a/lib/Froxlor/Cron/CronConfig.php
+++ b/lib/Froxlor/Cron/CronConfig.php
@@ -61,6 +61,7 @@ class CronConfig
$month_delay = 7;
while ($row_cronentry = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
// create cron.d-entry
+ $matches = array();
if (preg_match("/(\d+) (MINUTE|HOUR|DAY|WEEK|MONTH)/", $row_cronentry['interval'], $matches)) {
if ($matches[1] == 1) {
$minvalue = "*";
diff --git a/lib/Froxlor/Cron/Http/HttpConfigBase.php b/lib/Froxlor/Cron/Http/HttpConfigBase.php
index 3deeb8f0..e5b68629 100644
--- a/lib/Froxlor/Cron/Http/HttpConfigBase.php
+++ b/lib/Froxlor/Cron/Http/HttpConfigBase.php
@@ -28,6 +28,16 @@ use Froxlor\Cron\Http\Php\Fpm;
class HttpConfigBase
{
+ public function init()
+ {
+ // if Let's Encrypt is activated, run it before regeneration of webserver configfiles
+ if (Settings::Get('system.leenabled') == 1) {
+ \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Running Let\'s Encrypt cronjob prior to regenerating webserver config files');
+ \Froxlor\Cron\Http\LetsEncrypt\AcmeSh::$no_inserttask = true;
+ \Froxlor\Cron\Http\LetsEncrypt\AcmeSh::run();
+ }
+ }
+
public function reload()
{
$called_class = get_called_class();
diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
index 70b398fc..98762abb 100644
--- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
+++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
@@ -43,13 +43,19 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
private static $do_update = true;
+ public static $no_inserttask = false;
+
public static function run()
{
+ if (! defined('CRON_IS_FORCED') && ! defined('CRON_DEBUG_FLAG')) {
+ FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Let's Encrypt cronjob is combined with regeneration of webserver configuration files.\nFor debugging purposes you can use the --debug switch and/or the --force switch to run the cron manually.");
+ }
+
self::checkInstall();
self::$apiserver = 'https://acme-v0' . \Froxlor\Settings::Get('system.leapiversion') . '.api.letsencrypt.org/directory';
- FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Updating Let's Encrypt certificates");
+ FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Requesting/renewing Let's Encrypt certificates");
$certificates_stmt = Database::query("
SELECT
@@ -174,7 +180,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
);
$froxlor_aliases = Settings::Get('system.froxloraliases');
- if (!empty($froxlor_aliases)) {
+ if (! empty($froxlor_aliases)) {
$froxlor_aliases = explode(",", $froxlor_aliases);
foreach ($froxlor_aliases as $falias) {
if (\Froxlor\Validate\Validate::validateDomain(trim($falias))) {
@@ -186,9 +192,9 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
// 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
if ($cert_mode == 'renew') {
- FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Creating certificate for " . $certrow['domain']);
+ FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Creating certificate for " . $certrow['domain']);
} else {
- FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Updating certificate for " . $certrow['domain']);
+ FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Updating certificate for " . $certrow['domain']);
}
$cronlog = FroxlorLogger::getInstanceOf(array(
@@ -216,18 +222,18 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
if (! empty($certrow['ssl_cert_file'])) {
$cert_mode = 'renew';
- $cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Updating certificate for " . $certrow['domain']);
+ $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Updating certificate for " . $certrow['domain']);
} else {
- $cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Creating certificate for " . $certrow['domain']);
+ $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Creating certificate for " . $certrow['domain']);
}
- $cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: " . $certrow['domain']);
+ $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: " . $certrow['domain']);
$domains = array(
$certrow['domain']
);
// add www. to SAN list
if ($certrow['wwwserveralias'] == 1) {
- $cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: www." . $certrow['domain']);
+ $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: www." . $certrow['domain']);
$domains[] = 'www.' . $certrow['domain'];
}
@@ -237,27 +243,30 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
));
$aliasdomains = $aliasdomains_stmt->fetchAll(\PDO::FETCH_ASSOC);
foreach ($aliasdomains as $aliasdomain) {
- $cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: " . $aliasdomain['domain']);
+ $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: " . $aliasdomain['domain']);
$domains[] = $aliasdomain['domain'];
if ($aliasdomain['wwwserveralias'] == 1) {
- $cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: www." . $aliasdomain['domain']);
+ $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: www." . $aliasdomain['domain']);
$domains[] = 'www.' . $aliasdomain['domain'];
}
}
self::runAcmeSh($certrow, $domains, $cert_mode, $cronlog, $changedetected);
} else {
- $cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $certrow['domain'] . " due to an enabled ssl_redirect");
+ $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $certrow['domain'] . " due to an enabled ssl_redirect");
}
}
// 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) {
- \Froxlor\System\Cronjob::inserttask(1);
+ 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");
}
-
- FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Let's Encrypt certificates have been updated");
}
private static function runAcmeSh($certrow = array(), $domains = array(), $cert_mode = 'issue', &$cronlog = null, &$changedetected = 0)
@@ -314,10 +323,10 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
));
}
- $cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Updated Let's Encrypt certificate for " . $certrow['domain']);
+ $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Updated Let's Encrypt certificate for " . $certrow['domain']);
$changedetected = 1;
} else {
- $cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, "Could not get Let's Encrypt certificate for " . $certrow['domain'] . ":\n" . implode("\n", $acme_result));
+ $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Could not get Let's Encrypt certificate for " . $certrow['domain'] . ":\n" . implode("\n", $acme_result));
}
}
}
@@ -342,7 +351,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
private static function checkInstall()
{
if (! file_exists(self::$acmesh)) {
- FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Could not find acme.sh - installing it to /root/.acme.sh/");
+ 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(
'|'
@@ -353,6 +362,6 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
private static function checkUpgrade()
{
$acmesh_result = \Froxlor\FileDir::safe_exec(self::$acmesh . " --upgrade");
- FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Checking for LetsEncrypt client upgrades before renewing certificates:\n" . implode("\n", $acmesh_result));
+ FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Checking for LetsEncrypt client upgrades before renewing certificates:\n" . implode("\n", $acmesh_result));
}
}
diff --git a/lib/Froxlor/Cron/MasterCron.php b/lib/Froxlor/Cron/MasterCron.php
index 861f6522..18839df2 100644
--- a/lib/Froxlor/Cron/MasterCron.php
+++ b/lib/Froxlor/Cron/MasterCron.php
@@ -70,6 +70,7 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
// also regenerate cron.d-file
\Froxlor\System\Cronjob::inserttask('99');
array_push($jobs_to_run, 'tasks');
+ define('CRON_IS_FORCED', 1);
} elseif (strtolower($argv[$x]) == '--debug') {
define('CRON_DEBUG_FLAG', 1);
} elseif (strtolower($argv[$x]) == '--no-fork') {
diff --git a/lib/Froxlor/Cron/System/TasksCron.php b/lib/Froxlor/Cron/System/TasksCron.php
index 2ceb1db9..7dc2a4f2 100644
--- a/lib/Froxlor/Cron/System/TasksCron.php
+++ b/lib/Froxlor/Cron/System/TasksCron.php
@@ -145,6 +145,7 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
$webserver = new $websrv();
if (isset($webserver)) {
+ $webserver->init();
$webserver->createIpPort();
$webserver->createVirtualHosts();
$webserver->createFileDirOptions();
From 5e3cfaf847e7df6ea22a5df87a3446d4790690dd Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Wed, 10 Jul 2019 09:58:12 +0200
Subject: [PATCH 033/159] insert task to regenerate config files after removing
old-format lets encrypt certificates
Signed-off-by: Michael Kaufmann
---
install/updates/froxlor/0.10/update_0.10.inc.php | 4 ++++
1 file changed, 4 insertions(+)
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 d79ceb9e..030b82a8 100644
--- a/install/updates/froxlor/0.10/update_0.10.inc.php
+++ b/install/updates/froxlor/0.10/update_0.10.inc.php
@@ -222,6 +222,10 @@ if (\Froxlor\Froxlor::isDatabaseVersion('201902120')) {
}
lastStepStatus(0);
+ showUpdateStep("Inserting job to regenerate configfiles");
+ \Froxlor\System\Cronjob::inserttask('1');
+ lastStepStatus(0);
+
\Froxlor\Froxlor::updateToDbVersion('201902170');
}
From 8b417c044cfde448e672951114c8520ddfa46e4c Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Thu, 11 Jul 2019 08:13:00 +0200
Subject: [PATCH 034/159] let nginx auto-detect the best ecdh-curve to use,
fixes #652
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Cron/Http/Nginx.php | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/lib/Froxlor/Cron/Http/Nginx.php b/lib/Froxlor/Cron/Http/Nginx.php
index 42d8c063..1845f215 100644
--- a/lib/Froxlor/Cron/Http/Nginx.php
+++ b/lib/Froxlor/Cron/Http/Nginx.php
@@ -671,8 +671,13 @@ class Nginx extends HttpConfigBase
}
$sslsettings .= 'ssl_dhparam ' . $dhparams . ';' . "\n";
}
- $sslsettings .= "\t" . 'ssl_ecdh_curve secp384r1;' . "\n";
+ // When <1.11.0: Defaults to prime256v1, similar to first curve recommendation by Mozilla.
+ // (When specifyng just one, there's no fallback when specific curve is not supported by client.)
+ // When >1.11.0: Defaults to auto, using recommended curves provided by OpenSSL.
+ // see https://github.com/Froxlor/Froxlor/issues/652
+ //$sslsettings .= "\t" . 'ssl_ecdh_curve secp384r1;' . "\n";
$sslsettings .= "\t" . 'ssl_prefer_server_ciphers on;' . "\n";
+ $sslsettings .= "\t" . 'ssl_session_cache shared:SSL:10m;' . "\n";
$sslsettings .= "\t" . 'ssl_certificate ' . \Froxlor\FileDir::makeCorrectFile($domain_or_ip['ssl_cert_file']) . ';' . "\n";
if ($domain_or_ip['ssl_key_file'] != '') {
From db3c95ea10006374a51b4764663029b816460f99 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Thu, 11 Jul 2019 08:39:26 +0200
Subject: [PATCH 035/159] set last run of letsencrypt cron when called in
webserver-cron
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Cron/Http/HttpConfigBase.php | 2 ++
lib/Froxlor/Cron/MasterCron.php | 12 +-----------
lib/Froxlor/System/Cronjob.php | 10 ++++++++++
3 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/lib/Froxlor/Cron/Http/HttpConfigBase.php b/lib/Froxlor/Cron/Http/HttpConfigBase.php
index e5b68629..b1c68993 100644
--- a/lib/Froxlor/Cron/Http/HttpConfigBase.php
+++ b/lib/Froxlor/Cron/Http/HttpConfigBase.php
@@ -35,6 +35,8 @@ class HttpConfigBase
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Running Let\'s Encrypt cronjob prior to regenerating webserver config files');
\Froxlor\Cron\Http\LetsEncrypt\AcmeSh::$no_inserttask = true;
\Froxlor\Cron\Http\LetsEncrypt\AcmeSh::run();
+ // set last run timestamp of cronjob
+ \Froxlor\System\Cronjob::updateLastRunOfCron('letsencrypt');
}
}
diff --git a/lib/Froxlor/Cron/MasterCron.php b/lib/Froxlor/Cron/MasterCron.php
index 18839df2..b640aa45 100644
--- a/lib/Froxlor/Cron/MasterCron.php
+++ b/lib/Froxlor/Cron/MasterCron.php
@@ -96,7 +96,7 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
if (count($jobs_to_run) > 0) {
// include all jobs we want to execute
foreach ($jobs_to_run as $cron) {
- self::updateLastRunOfCron($cron);
+ \Froxlor\System\Cronjob::updateLastRunOfCron($cron);
$cronfile = self::getCronModule($cron);
if ($cronfile && class_exists($cronfile)) {
$cronfile::run();
@@ -336,16 +336,6 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
}
}
- private static function updateLastRunOfCron($cronname)
- {
- $upd_stmt = Database::prepare("
- UPDATE `" . TABLE_PANEL_CRONRUNS . "` SET `lastrun` = UNIX_TIMESTAMP() WHERE `cronfile` = :cron;
- ");
- Database::pexecute($upd_stmt, array(
- 'cron' => $cronname
- ));
- }
-
private static function getCronModule($cronname)
{
$upd_stmt = Database::prepare("
diff --git a/lib/Froxlor/System/Cronjob.php b/lib/Froxlor/System/Cronjob.php
index 660dd075..a08dbaa0 100644
--- a/lib/Froxlor/System/Cronjob.php
+++ b/lib/Froxlor/System/Cronjob.php
@@ -361,4 +361,14 @@ class Cronjob
die($message);
}
+
+ public static function updateLastRunOfCron($cronname)
+ {
+ $upd_stmt = Database::prepare("
+ UPDATE `" . TABLE_PANEL_CRONRUNS . "` SET `lastrun` = UNIX_TIMESTAMP() WHERE `cronfile` = :cron;
+ ");
+ Database::pexecute($upd_stmt, array(
+ 'cron' => $cronname
+ ));
+ }
}
From 065fa0b58be231f61c454d82e50b63e78ba3bd04 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Sat, 13 Jul 2019 09:09:39 +0200
Subject: [PATCH 036/159] do not store punycode-notation of email-account
domain, fixes #703
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Api/Commands/EmailAccounts.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/Froxlor/Api/Commands/EmailAccounts.php b/lib/Froxlor/Api/Commands/EmailAccounts.php
index 9a5f3492..98f52b3c 100644
--- a/lib/Froxlor/Api/Commands/EmailAccounts.php
+++ b/lib/Froxlor/Api/Commands/EmailAccounts.php
@@ -81,9 +81,9 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
));
$id = $result['id'];
- $email_full = $result['email_full'];
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
- $username = $idna_convert->decode($email_full);
+ $email_full = $result['email_full'];
+ $username = $email_full;
$password = \Froxlor\Validate\Validate::validate($email_password, 'password', '', '', array(), true);
$password = \Froxlor\System\Crypt::validatePassword($password, true);
From e91debcbb1c3e543b1082f77f2e6c51d0305c378 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Sun, 14 Jul 2019 09:41:46 +0200
Subject: [PATCH 037/159] buster dovceot has ssl enabled by default
Signed-off-by: Michael Kaufmann
---
lib/configfiles/buster.xml | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/lib/configfiles/buster.xml b/lib/configfiles/buster.xml
index 0d3cea61..2775632b 100644
--- a/lib/configfiles/buster.xml
+++ b/lib/configfiles/buster.xml
@@ -2593,7 +2593,7 @@ dict {
# );
# Database driver: mysql, pgsql, sqlite
-driver = mysql
+driver = mysql
# Database connection string. This is driver-specific setting.
#
@@ -2707,11 +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 users
-
-
-# This file is commonly accessed via passdb {} or userdb {} section in
-# conf.d/auth-sql.conf.ext
+#iterate_query = SELECT username AS user FROM mail_users
]]>
@@ -3394,7 +3390,7 @@ service auth {
unix_listener auth-client {
mode = 0660
user = mail
- # group = Debian-exim
+ #group = Debian-exim
}
# Auth process is run as this user.
@@ -3428,14 +3424,14 @@ service dict {
##
# SSL/TLS support: yes, no, required.
-ssl = no
+ssl = yes
# 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 =
Date: Fri, 19 Jul 2019 01:39:01 +0200
Subject: [PATCH 038/159] Update stretch.xml
---
lib/configfiles/stretch.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/configfiles/stretch.xml b/lib/configfiles/stretch.xml
index 6dab29fc..ea88e2d0 100644
--- a/lib/configfiles/stretch.xml
+++ b/lib/configfiles/stretch.xml
@@ -1493,7 +1493,7 @@ user =
password =
dbname =
hosts =
-query = SELECT destination FROM mail_virtual WHERE email = '%s' AND trim(destination) <> ''
+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) <> ''
]]>
From 577e9d3b70374511f59d08bba3a9bbc6ef22aadd Mon Sep 17 00:00:00 2001
From: Dave
Date: Fri, 19 Jul 2019 01:40:55 +0200
Subject: [PATCH 039/159] Update buster.xml
---
lib/configfiles/buster.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/configfiles/buster.xml b/lib/configfiles/buster.xml
index 0d3cea61..3555b7b4 100644
--- a/lib/configfiles/buster.xml
+++ b/lib/configfiles/buster.xml
@@ -1463,7 +1463,7 @@ user =
password =
dbname =
hosts =
-query = SELECT destination FROM mail_virtual WHERE email = '%s' AND trim(destination) <> ''
+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) <> ''
]]>
From 77a7037072d9bd334137b0eb86c3f8a8433ca6ba Mon Sep 17 00:00:00 2001
From: Dave
Date: Fri, 19 Jul 2019 01:41:24 +0200
Subject: [PATCH 040/159] Update jessie.xml
---
lib/configfiles/jessie.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/configfiles/jessie.xml b/lib/configfiles/jessie.xml
index 98f22751..9339c6c8 100644
--- a/lib/configfiles/jessie.xml
+++ b/lib/configfiles/jessie.xml
@@ -1504,7 +1504,7 @@ user =
password =
dbname =
hosts =
-query = SELECT destination FROM mail_virtual WHERE email = '%s' AND trim(destination) <> ''
+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) <> ''
]]>
From 507a62f52df99d23c9f7a4a26d48dc615eb15ca1 Mon Sep 17 00:00:00 2001
From: Dave
Date: Fri, 19 Jul 2019 01:41:54 +0200
Subject: [PATCH 041/159] Update trusty.xml
---
lib/configfiles/trusty.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/configfiles/trusty.xml b/lib/configfiles/trusty.xml
index 9613a357..512cc921 100644
--- a/lib/configfiles/trusty.xml
+++ b/lib/configfiles/trusty.xml
@@ -502,7 +502,7 @@ user =
password =
dbname =
hosts =
-query = SELECT destination FROM mail_virtual WHERE email = '%s' AND trim(destination) <> ''
+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) <> ''
]]>
From 06694506767a41bf0751f6fbac1e1873fa9e3963 Mon Sep 17 00:00:00 2001
From: Dave
Date: Fri, 19 Jul 2019 01:42:14 +0200
Subject: [PATCH 042/159] Update bionic.xml
---
lib/configfiles/bionic.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/configfiles/bionic.xml b/lib/configfiles/bionic.xml
index 30fe1d6f..fac95592 100644
--- a/lib/configfiles/bionic.xml
+++ b/lib/configfiles/bionic.xml
@@ -1504,7 +1504,7 @@ user =
password =
dbname =
hosts =
-query = SELECT destination FROM mail_virtual WHERE email = '%s' AND trim(destination) <> ''
+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) <> ''
]]>
From de7c438315b7b257a083b1c0267e9404a3d803de Mon Sep 17 00:00:00 2001
From: Dave
Date: Fri, 19 Jul 2019 01:42:31 +0200
Subject: [PATCH 043/159] Update gentoo.xml
---
lib/configfiles/gentoo.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/configfiles/gentoo.xml b/lib/configfiles/gentoo.xml
index 87424ed7..e84a4439 100644
--- a/lib/configfiles/gentoo.xml
+++ b/lib/configfiles/gentoo.xml
@@ -1474,7 +1474,7 @@ user =
password =
dbname =
hosts =
-query = SELECT destination FROM mail_virtual WHERE email = '%s' AND trim(destination) <> ''
+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) <> ''
]]>
From 5698f8360e31dd9144c433f40654ad81179e7f53 Mon Sep 17 00:00:00 2001
From: Dave
Date: Fri, 19 Jul 2019 01:42:49 +0200
Subject: [PATCH 044/159] Update rhel_centos.xml
---
lib/configfiles/rhel_centos.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/configfiles/rhel_centos.xml b/lib/configfiles/rhel_centos.xml
index 0e3682f9..a31b2dfa 100644
--- a/lib/configfiles/rhel_centos.xml
+++ b/lib/configfiles/rhel_centos.xml
@@ -95,7 +95,7 @@ user =
password =
dbname =
hosts =
-query = SELECT destination FROM mail_virtual WHERE email = '%s' AND trim(destination) <> ''
+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) <> ''
]]>
From 7e9b373a58cac2eaec200c6a9307ec2a7664e7fe Mon Sep 17 00:00:00 2001
From: Dave
Date: Fri, 19 Jul 2019 01:43:07 +0200
Subject: [PATCH 045/159] Update xenial.xml
---
lib/configfiles/xenial.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/configfiles/xenial.xml b/lib/configfiles/xenial.xml
index 8df99edf..62f7ccd5 100644
--- a/lib/configfiles/xenial.xml
+++ b/lib/configfiles/xenial.xml
@@ -1504,7 +1504,7 @@ user =
password =
dbname =
hosts =
-query = SELECT destination FROM mail_virtual WHERE email = '%s' AND trim(destination) <> ''
+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) <> ''
]]>
From 6c0fb007e49acebb0604d42f1b71f4f3cca67f41 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Fri, 19 Jul 2019 08:43:42 +0200
Subject: [PATCH 046/159] travis changed the default OS to xenial, set it to
the previous trusty which works
Signed-off-by: Michael Kaufmann
---
.travis.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.travis.yml b/.travis.yml
index 2a4dd27c..827ec1af 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,5 @@
language: php
+dist: trusty
php:
- "7.3"
From 56587176535b88ca1d23284de473e8fbfef9318d Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Fri, 19 Jul 2019 11:43:14 +0200
Subject: [PATCH 047/159] fix wrong parameter for acme.sh --delete when ecc
certificates are used
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Domain/Domain.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/Froxlor/Domain/Domain.php b/lib/Froxlor/Domain/Domain.php
index 34e38238..bb0d2d7f 100644
--- a/lib/Froxlor/Domain/Domain.php
+++ b/lib/Froxlor/Domain/Domain.php
@@ -304,7 +304,7 @@ class Domain
if (file_exists($certificate_folder)) {
$params = " --remove -d " . $domainname;
if (\Froxlor\Settings::Get('system.leecc') > 0) {
- $params .= " -ecc";
+ $params .= " --ecc";
}
// run remove command
\Froxlor\FileDir::safe_exec($acmesh . $params);
From 7bc57ed2695aa3d44f7b113dffe7b96715ee6ce9 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Fri, 26 Jul 2019 07:34:32 +0200
Subject: [PATCH 048/159] set password directly when adding new mysql user
Signed-off-by: Michael Kaufmann
---
.../Database/Manager/DbManagerMySQL.php | 40 ++++++++++---------
tests/Mysqls/MysqlsTest.php | 11 ++++-
2 files changed, 32 insertions(+), 19 deletions(-)
diff --git a/lib/Froxlor/Database/Manager/DbManagerMySQL.php b/lib/Froxlor/Database/Manager/DbManagerMySQL.php
index e98ea86b..693e229b 100644
--- a/lib/Froxlor/Database/Manager/DbManagerMySQL.php
+++ b/lib/Froxlor/Database/Manager/DbManagerMySQL.php
@@ -82,9 +82,11 @@ class DbManagerMySQL
if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '8.0.11', '>=')) {
// create user
$stmt = Database::prepare("
- CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED BY 'password'
+ CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED BY :password
");
- Database::pexecute($stmt);
+ Database::pexecute($stmt, array(
+ "password" => $password
+ ));
// grant privileges
$stmt = Database::prepare("
GRANT ALL ON `" . $username . "`.* TO :username@:host
@@ -96,29 +98,31 @@ class DbManagerMySQL
} else {
// grant privileges
$stmt = Database::prepare("
- GRANT ALL PRIVILEGES ON `" . $username . "`.* TO :username@:host IDENTIFIED BY 'password'
+ GRANT ALL PRIVILEGES ON `" . $username . "`.* TO :username@:host IDENTIFIED BY :password
");
Database::pexecute($stmt, array(
"username" => $username,
- "host" => $access_host
+ "host" => $access_host,
+ "password" => $password
));
}
- }
- // set passoword
- if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.6', '<')) {
- if ($p_encrypted) {
- $stmt = Database::prepare("SET PASSWORD FOR :username@:host = :password");
- } else {
- $stmt = Database::prepare("SET PASSWORD FOR :username@:host = PASSWORD(:password)");
- }
} else {
- $stmt = Database::prepare("ALTER USER :username@:host IDENTIFIED BY :password");
+ // set passoword
+ if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.6', '<')) {
+ if ($p_encrypted) {
+ $stmt = Database::prepare("SET PASSWORD FOR :username@:host = :password");
+ } else {
+ $stmt = Database::prepare("SET PASSWORD FOR :username@:host = PASSWORD(:password)");
+ }
+ } else {
+ $stmt = Database::prepare("ALTER USER :username@:host IDENTIFIED BY :password");
+ }
+ Database::pexecute($stmt, array(
+ "username" => $username,
+ "host" => $access_host,
+ "password" => $password
+ ));
}
- Database::pexecute($stmt, array(
- "username" => $username,
- "host" => $access_host,
- "password" => $password
- ));
}
/**
diff --git a/tests/Mysqls/MysqlsTest.php b/tests/Mysqls/MysqlsTest.php
index 08117055..b0bd8527 100644
--- a/tests/Mysqls/MysqlsTest.php
+++ b/tests/Mysqls/MysqlsTest.php
@@ -26,8 +26,9 @@ class MysqlsTest extends TestCase
))->get();
$customer_userdata = json_decode($json_result, true)['data'];
+ $newPwd = \Froxlor\System\Crypt::generatePassword();
$data = [
- 'mysql_password' => \Froxlor\System\Crypt::generatePassword(),
+ 'mysql_password' => $newPwd,
'description' => 'testdb',
'sendinfomail' => TRAVIS_CI == 1 ? 0 : 1
];
@@ -35,6 +36,14 @@ class MysqlsTest extends TestCase
$result = json_decode($json_result, true)['data'];
$this->assertEquals('testdb', $result['description']);
$this->assertEquals(0, $result['dbserver']);
+
+ // test connection
+ try {
+ $test_conn = new \PDO("mysql:host=localhost", 'test1sql1', $newPwd);
+ unset($test_conn);
+ } catch (PDOException $e) {
+ $this->fail($e->getMessage());
+ }
}
/**
From dd87a7374e10f6d02c2c383bc712601bac7e41df Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Fri, 26 Jul 2019 07:45:38 +0200
Subject: [PATCH 049/159] fix ftp-group not added correctly when new customer
is added
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Api/Commands/Ftps.php | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/lib/Froxlor/Api/Commands/Ftps.php b/lib/Froxlor/Api/Commands/Ftps.php
index ec52947e..acefe14d 100644
--- a/lib/Froxlor/Api/Commands/Ftps.php
+++ b/lib/Froxlor/Api/Commands/Ftps.php
@@ -179,7 +179,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
), true, true);
}
- $stmt = Database::prepare("
+ $group_upd_stmt = Database::prepare("
UPDATE `" . TABLE_FTP_GROUPS . "`
SET `members` = CONCAT_WS(',',`members`, :username)
WHERE `customerid`= :customerid AND `gid`= :guid
@@ -189,7 +189,18 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
"customerid" => $customer['customerid'],
"guid" => $customer['guid']
);
- Database::pexecute($stmt, $params, true, true);
+
+ if ($is_defaultuser) {
+ // add the new group
+ $group_ins_stmt = Database::prepare("
+ INSERT INTO `" . TABLE_FTP_GROUPS . "`
+ SET `customerid`= :customerid, `gid`= :guid, `groupname` = :username, `members` = :username
+ ");
+ Database::pexecute($group_ins_stmt, $params, true, true);
+ } else {
+ // just update
+ Database::pexecute($group_upd_stmt, $params, true, true);
+ }
if (count($additional_members) > 0) {
foreach ($additional_members as $add_member) {
@@ -198,12 +209,12 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
"customerid" => $customer['customerid'],
"guid" => $customer['guid']
);
- Database::pexecute($stmt, $params, true, true);
+ Database::pexecute($group_upd_stmt, $params, true, true);
}
}
- // update customer usage
if (! $is_defaultuser) {
+ // update customer usage
Customers::increaseUsage($customer['customerid'], 'ftps_used');
Customers::increaseUsage($customer['customerid'], 'ftp_lastaccountnumber');
}
From d5e418287833d87c1a00aca147ad39b133c41e7b Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Fri, 26 Jul 2019 07:49:17 +0200
Subject: [PATCH 050/159] beautification and minor fixes
Signed-off-by: Michael Kaufmann
---
admin_logger.php | 2 +-
customer_logger.php | 2 +-
lib/Froxlor/Cron/Http/HttpConfigBase.php | 2 +-
lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 7 ++--
lib/Froxlor/Cron/MasterCron.php | 38 +++++++++++---------
5 files changed, 28 insertions(+), 23 deletions(-)
diff --git a/admin_logger.php b/admin_logger.php
index 34b519e1..3d317533 100644
--- a/admin_logger.php
+++ b/admin_logger.php
@@ -83,7 +83,7 @@ if ($page == 'log' && $userinfo['change_serversettings'] == '1') {
case \Froxlor\FroxlorLogger::LOGIN_ACTION:
$_action = $lng['logger']['login'];
break;
- case LOG_ERROR:
+ case \Froxlor\FroxlorLogger::LOG_ERROR:
$_action = $lng['logger']['intern'];
break;
default:
diff --git a/customer_logger.php b/customer_logger.php
index 01da2095..197e99a2 100644
--- a/customer_logger.php
+++ b/customer_logger.php
@@ -96,7 +96,7 @@ if ($page == 'log') {
case \Froxlor\FroxlorLogger::LOGIN_ACTION:
$_action = $lng['logger']['login'];
break;
- case LOG_ERROR:
+ case \Froxlor\FroxlorLogger::LOG_ERROR:
$_action = $lng['logger']['intern'];
break;
default:
diff --git a/lib/Froxlor/Cron/Http/HttpConfigBase.php b/lib/Froxlor/Cron/Http/HttpConfigBase.php
index b1c68993..c927423d 100644
--- a/lib/Froxlor/Cron/Http/HttpConfigBase.php
+++ b/lib/Froxlor/Cron/Http/HttpConfigBase.php
@@ -34,7 +34,7 @@ class HttpConfigBase
if (Settings::Get('system.leenabled') == 1) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Running Let\'s Encrypt cronjob prior to regenerating webserver config files');
\Froxlor\Cron\Http\LetsEncrypt\AcmeSh::$no_inserttask = true;
- \Froxlor\Cron\Http\LetsEncrypt\AcmeSh::run();
+ \Froxlor\Cron\Http\LetsEncrypt\AcmeSh::run(true);
// set last run timestamp of cronjob
\Froxlor\System\Cronjob::updateLastRunOfCron('letsencrypt');
}
diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
index 98762abb..e0967ca0 100644
--- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
+++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
@@ -45,10 +45,11 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
public static $no_inserttask = false;
- public static function run()
+ public static function run($internal = false)
{
- if (! defined('CRON_IS_FORCED') && ! defined('CRON_DEBUG_FLAG')) {
- FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Let's Encrypt cronjob is combined with regeneration of webserver configuration files.\nFor debugging purposes you can use the --debug switch and/or the --force switch to run the cron manually.");
+ if (! defined('CRON_IS_FORCED') && ! defined('CRON_DEBUG_FLAG') && $internal == false) {
+ //FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Let's Encrypt cronjob is combined with regeneration of webserver configuration files.\nFor debugging purposes you can use the --debug switch and/or the --force switch to run the cron manually.");
+ return 0;
}
self::checkInstall();
diff --git a/lib/Froxlor/Cron/MasterCron.php b/lib/Froxlor/Cron/MasterCron.php
index b640aa45..3179efb0 100644
--- a/lib/Froxlor/Cron/MasterCron.php
+++ b/lib/Froxlor/Cron/MasterCron.php
@@ -102,23 +102,7 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
$cronfile::run();
}
}
-
- if ($tasks_cnt['jobcnt'] > 0) {
- if (\Froxlor\Settings::Get('system.nssextrausers') == 1) {
- \Froxlor\Cron\System\Extrausers::generateFiles(self::$cronlog);
- }
-
- // clear NSCD cache if using fcgid or fpm, #1570 - not needed for nss-extrausers
- if ((\Froxlor\Settings::Get('system.mod_fcgid') == 1 || (int) \Froxlor\Settings::Get('phpfpm.enabled') == 1) && \Froxlor\Settings::Get('system.nssextrausers') == 0) {
- $false_val = false;
- \Froxlor\FileDir::safe_exec('nscd -i passwd 1> /dev/null', $false_val, array(
- '>'
- ));
- \Froxlor\FileDir::safe_exec('nscd -i group 1> /dev/null', $false_val, array(
- '>'
- ));
- }
- }
+ self::refreshUsers($tasks_cnt['jobcnt']);
}
/**
@@ -133,6 +117,26 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
self::shutdown();
}
+ private static function refreshUsers($jobcount = 0)
+ {
+ if ($jobcount > 0) {
+ if (\Froxlor\Settings::Get('system.nssextrausers') == 1) {
+ \Froxlor\Cron\System\Extrausers::generateFiles(self::$cronlog);
+ }
+
+ // clear NSCD cache if using fcgid or fpm, #1570 - not needed for nss-extrausers
+ if ((\Froxlor\Settings::Get('system.mod_fcgid') == 1 || (int) \Froxlor\Settings::Get('phpfpm.enabled') == 1) && \Froxlor\Settings::Get('system.nssextrausers') == 0) {
+ $false_val = false;
+ \Froxlor\FileDir::safe_exec('nscd -i passwd 1> /dev/null', $false_val, array(
+ '>'
+ ));
+ \Froxlor\FileDir::safe_exec('nscd -i group 1> /dev/null', $false_val, array(
+ '>'
+ ));
+ }
+ }
+ }
+
private static function init()
{
if (@php_sapi_name() != 'cli' && @php_sapi_name() != 'cgi' && @php_sapi_name() != 'cgi-fcgi') {
From d4e5e32c14e252840e1aa63302f0801eb4dcf65f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Kolly?=
Date: Sat, 27 Jul 2019 17:36:31 +0200
Subject: [PATCH 051/159] Implement CAA DNS record for letsencrypt.org
---
install/froxlor.sql | 1 +
install/updates/froxlor/0.10/update_0.10.inc.php | 6 ++++++
lib/Froxlor/Dns/Dns.php | 11 +++++++++++
.../admin/domains/formfield.domains_add.php | 13 +++++++++++++
.../admin/domains/formfield.domains_edit.php | 15 +++++++++++++++
.../customer/domains/formfield.domains_add.php | 13 +++++++++++++
.../customer/domains/formfield.domains_edit.php | 15 +++++++++++++++
lng/english.lng.php | 6 ++++++
lng/german.lng.php | 6 ++++++
9 files changed, 86 insertions(+)
diff --git a/install/froxlor.sql b/install/froxlor.sql
index ec917791..76fe4d6d 100644
--- a/install/froxlor.sql
+++ b/install/froxlor.sql
@@ -256,6 +256,7 @@ CREATE TABLE `panel_domains` (
`mod_fcgid_maxrequests` int(4) default '-1',
`ismainbutsubto` int(11) unsigned NOT NULL default '0',
`letsencrypt` tinyint(1) NOT NULL default '0',
+ `caa` tinyint(1) NOT NULL default '0',
`hsts` varchar(10) NOT NULL default '0',
`hsts_sub` tinyint(1) NOT NULL default '0',
`hsts_preload` tinyint(1) NOT NULL default '0',
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 030b82a8..41dfb662 100644
--- a/install/updates/froxlor/0.10/update_0.10.inc.php
+++ b/install/updates/froxlor/0.10/update_0.10.inc.php
@@ -263,3 +263,9 @@ if (\Froxlor\Froxlor::isDatabaseVersion('201904100')) {
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.0-rc1')) {
\Froxlor\Froxlor::updateToVersion('0.10.0-rc2');
}
+
+if (\Froxlor\Froxlor::isDatabaseVersion('201904250')) {
+
+ Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `caa` TINYINT(1) NOT NULL DEFAULT '0' AFTER `letsencrypt`;");
+ \Froxlor\Froxlor::updateToDbVersion('201907270');
+}
\ No newline at end of file
diff --git a/lib/Froxlor/Dns/Dns.php b/lib/Froxlor/Dns/Dns.php
index cfc77e93..c34a5543 100644
--- a/lib/Froxlor/Dns/Dns.php
+++ b/lib/Froxlor/Dns/Dns.php
@@ -130,6 +130,12 @@ class Dns
}
}
+ // additional required records for CAA if activated
+ if ($domain['caa'] == '1') {
+ // check for CAA content later
+ self::addRequiredEntry('@', 'CAA', $required_entries);
+ }
+
// additional required records for SPF and DKIM if activated
if ($domain['isemaildomain'] == '1') {
if (Settings::Get('spf.use_spf') == '1') {
@@ -278,6 +284,11 @@ class Dns
}
}
}
+
+ // CAA
+ if (array_key_exists("CAA", $required_entries)) {
+ $zonerecords[] = new DnsEntry('@', 'CAA', '0 issue "letsencrypt.org"');
+ }
}
if (empty($primary_ns)) {
diff --git a/lib/formfields/admin/domains/formfield.domains_add.php b/lib/formfields/admin/domains/formfield.domains_add.php
index ddbb6266..b3460fae 100644
--- a/lib/formfields/admin/domains/formfield.domains_add.php
+++ b/lib/formfields/admin/domains/formfield.domains_add.php
@@ -214,6 +214,19 @@ return array(
),
'value' => array()
),
+ 'caa' => array(
+ 'visible' => (\Froxlor\Settings::Get('system.leenabled') == '1' ? ($ssl_ipsandports != '' ? true : false) : false),
+ 'label' => $lng['admin']['caa']['title'],
+ 'desc' => $lng['admin']['caa']['description'],
+ 'type' => 'checkbox',
+ 'values' => array(
+ array(
+ 'label' => $lng['panel']['yes'],
+ 'value' => '1'
+ )
+ ),
+ 'value' => array()
+ ),
'http2' => array(
'visible' => ($ssl_ipsandports != '' ? true : false) && \Froxlor\Settings::Get('system.webserver') != 'lighttpd' && \Froxlor\Settings::Get('system.http2_support') == '1',
'label' => $lng['admin']['domain_http2']['title'],
diff --git a/lib/formfields/admin/domains/formfield.domains_edit.php b/lib/formfields/admin/domains/formfield.domains_edit.php
index 4c756ec1..7fe2fe54 100644
--- a/lib/formfields/admin/domains/formfield.domains_edit.php
+++ b/lib/formfields/admin/domains/formfield.domains_edit.php
@@ -250,6 +250,21 @@ return array(
$result['letsencrypt']
)
),
+ 'caa' => array(
+ 'visible' => (\Froxlor\Settings::Get('system.leenabled') == '1' ? ($ssl_ipsandports != '' ? true : false) : false),
+ 'label' => $lng['admin']['caa']['title'],
+ 'desc' => $lng['admin']['caa']['description'],
+ 'type' => 'checkbox',
+ 'values' => array(
+ array(
+ 'label' => $lng['panel']['yes'],
+ 'value' => '1'
+ )
+ ),
+ 'value' => array(
+ $result['caa']
+ )
+ ),
'http2' => array(
'visible' => ($ssl_ipsandports != '' ? true : false) && \Froxlor\Settings::Get('system.webserver') != 'lighttpd' && \Froxlor\Settings::Get('system.http2_support') == '1',
'label' => $lng['admin']['domain_http2']['title'],
diff --git a/lib/formfields/customer/domains/formfield.domains_add.php b/lib/formfields/customer/domains/formfield.domains_add.php
index 00d9fca6..b620dba1 100644
--- a/lib/formfields/customer/domains/formfield.domains_add.php
+++ b/lib/formfields/customer/domains/formfield.domains_add.php
@@ -108,6 +108,19 @@ return array(
),
'value' => array()
),
+ 'caa' => array(
+ 'visible' => \Froxlor\Settings::Get('system.leenabled') == '1' ? true : false,
+ 'label' => $lng['customer']['caa']['title'],
+ 'desc' => $lng['customer']['caa']['description'],
+ 'type' => 'checkbox',
+ 'values' => array(
+ array(
+ 'label' => $lng['panel']['yes'],
+ 'value' => '1'
+ )
+ ),
+ 'value' => array()
+ ),
'hsts_maxage' => array(
'label' => $lng['admin']['domain_hsts_maxage']['title'],
'desc' => $lng['admin']['domain_hsts_maxage']['description'],
diff --git a/lib/formfields/customer/domains/formfield.domains_edit.php b/lib/formfields/customer/domains/formfield.domains_edit.php
index 56a28543..c5315487 100644
--- a/lib/formfields/customer/domains/formfield.domains_edit.php
+++ b/lib/formfields/customer/domains/formfield.domains_edit.php
@@ -128,6 +128,21 @@ return array(
$result['letsencrypt']
)
),
+ 'caa' => array(
+ 'visible' => \Froxlor\Settings::Get('system.leenabled') == '1' ? true : false,
+ 'label' => $lng['customer']['caa']['title'],
+ 'desc' => $lng['customer']['caa']['description'],
+ 'type' => 'checkbox',
+ 'values' => array(
+ array(
+ 'label' => $lng['panel']['yes'],
+ 'value' => '1'
+ )
+ ),
+ 'value' => array(
+ $result['caa']
+ )
+ ),
'hsts_maxage' => array(
'label' => $lng['admin']['domain_hsts_maxage']['title'],
'desc' => $lng['admin']['domain_hsts_maxage']['description'],
diff --git a/lng/english.lng.php b/lng/english.lng.php
index e76477c5..3ee60eeb 100644
--- a/lng/english.lng.php
+++ b/lng/english.lng.php
@@ -1848,6 +1848,12 @@ $lng['serversettings']['leenabled']['title'] = "Enable Let's Encrypt";
$lng['serversettings']['leenabled']['description'] = "If activated, customers are able to let froxlor automatically generate and renew Let's Encrypt ssl-certificates for domains with a ssl IP/port. Please remember that you need to go through the webserver-configuration when enabled because this feature needs a special configuration.";
$lng['domains']['ssl_redirect_temporarilydisabled'] = " The SSL redirect is temporarily deactivated while a new Let's Encrypt certificate is generated. It will be activated again after the certificate was generated.";
+// Added for CAA record support
+$lng['admin']['caa']['title'] = 'Use CAA DNS record';
+$lng['admin']['caa']['description'] = 'DNS Certification Authority Authorization (CAA) is an Internet security policy mechanism which allows domain name holders to indicate to certificate authorities whether they are authorized to issue digital certificates for a particular domain name. It does this by means of a new "CAA" Domain Name System (DNS) resource record. Currently it only supports Let\'s Encrypt. This feature is still in beta.';
+$lng['customer']['caa']['title'] = 'Use CAA DNS record';
+$lng['customer']['caa']['description'] = 'DNS Certification Authority Authorization (CAA) is an Internet security policy mechanism which allows domain name holders to indicate to certificate authorities whether they are authorized to issue digital certificates for a particular domain name. It does this by means of a new "CAA" Domain Name System (DNS) resource record. Currently it only supports Let\'s Encrypt. This feature is still in beta.';
+
// Autoupdate
$lng['admin']['autoupdate'] = 'Auto-Update';
$lng['error']['customized_version'] = 'It looks like your Froxlor installation has been modified, no support sorry.';
diff --git a/lng/german.lng.php b/lng/german.lng.php
index f1f44c27..37c3f08f 100644
--- a/lng/german.lng.php
+++ b/lng/german.lng.php
@@ -1500,6 +1500,12 @@ $lng['serversettings']['leenabled']['title'] = "Let's Encrypt verwenden";
$lng['serversettings']['leenabled']['description'] = "Wenn dies aktiviert ist, können Kunden durch Froxlor automatisch generierte und verlängerbare Let's Encrypt SSL-Zertifikate für Domains mit SSL IP/Port nutzen. Bitte die Webserver-Konfiguration beachten wenn aktiviert, da dieses Feature eine spezielle Konfiguration benötigt.";
$lng['domains']['ssl_redirect_temporarilydisabled'] = " Die SSL-Umleitung ist, während ein neues Let's Encrypt - Zertifikat erstellt wird, temporär deaktiviert. Die Umleitung wird nach der Zertifikatserstellung wieder aktiviert.";
+// Added for CAA record support
+$lng['admin']['caa']['title'] = 'CAA DNS Eintrag erstellen';
+$lng['admin']['caa']['description'] = 'DNS Certification Authority Authorization (CAA) verwendet das Domain Name System, um dem Besitzer einer Domain die Möglichkeit zu bieten, gewisse Zertifizierungsstellen (CAs) dazu zu berechtigen, ein Zertifikat für die betroffene Domain auszustellen. CAA Records sollen verhindern, dass Zertifikate fälschlicherweise für eine Domain ausgestellt werden. Im Moment wird nur Let\'s Encrypt unterstützt. Dieses Feature befindet sich noch im Test.';
+$lng['customer']['caa']['title'] = 'CAA DNS Eintrag erstellen';
+$lng['customer']['caa']['description'] = 'DNS Certification Authority Authorization (CAA) verwendet das Domain Name System, um dem Besitzer einer Domain die Möglichkeit zu bieten, gewisse Zertifizierungsstellen (CAs) dazu zu berechtigen, ein Zertifikat für die betroffene Domain auszustellen. CAA Records sollen verhindern, dass Zertifikate fälschlicherweise für eine Domain ausgestellt werden. Im Moment wird nur Let\'s Encrypt unterstützt. Dieses Feature befindet sich noch im Test.';
+
// Autoupdate
$lng['admin']['autoupdate'] = 'Auto-Update';
$lng['error']['customized_version'] = 'Es scheint als wäre die Froxlor Installation angepasst worden. Kein Support, sorry.';
From 64fe300e426acbf85ae3d1a746ef060e261ae4b7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Kolly?=
Date: Sun, 28 Jul 2019 16:28:29 +0200
Subject: [PATCH 052/159] Implement general CAA DNS records for all issuers
---
install/froxlor.sql | 2 +-
.../updates/froxlor/0.10/update_0.10.inc.php | 2 +-
lib/Froxlor/Dns/Dns.php | 19 +++++++++++++++++--
.../admin/domains/formfield.domains_add.php | 15 ++++++---------
.../admin/domains/formfield.domains_edit.php | 17 ++++++-----------
.../domains/formfield.domains_add.php | 15 ++++++---------
.../domains/formfield.domains_edit.php | 17 ++++++-----------
lng/english.lng.php | 8 ++++----
lng/german.lng.php | 8 ++++----
9 files changed, 51 insertions(+), 52 deletions(-)
diff --git a/install/froxlor.sql b/install/froxlor.sql
index 76fe4d6d..f50c5c1f 100644
--- a/install/froxlor.sql
+++ b/install/froxlor.sql
@@ -256,7 +256,7 @@ CREATE TABLE `panel_domains` (
`mod_fcgid_maxrequests` int(4) default '-1',
`ismainbutsubto` int(11) unsigned NOT NULL default '0',
`letsencrypt` tinyint(1) NOT NULL default '0',
- `caa` tinyint(1) NOT NULL default '0',
+ `caa` text default NULL,
`hsts` varchar(10) NOT NULL default '0',
`hsts_sub` tinyint(1) NOT NULL default '0',
`hsts_preload` tinyint(1) NOT NULL default '0',
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 41dfb662..fae59b55 100644
--- a/install/updates/froxlor/0.10/update_0.10.inc.php
+++ b/install/updates/froxlor/0.10/update_0.10.inc.php
@@ -266,6 +266,6 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.0-rc1')) {
if (\Froxlor\Froxlor::isDatabaseVersion('201904250')) {
- Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `caa` TINYINT(1) NOT NULL DEFAULT '0' AFTER `letsencrypt`;");
+ Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `caa` text default NULL AFTER `letsencrypt`;");
\Froxlor\Froxlor::updateToDbVersion('201907270');
}
\ No newline at end of file
diff --git a/lib/Froxlor/Dns/Dns.php b/lib/Froxlor/Dns/Dns.php
index c34a5543..0d754f21 100644
--- a/lib/Froxlor/Dns/Dns.php
+++ b/lib/Froxlor/Dns/Dns.php
@@ -131,9 +131,15 @@ class Dns
}
// additional required records for CAA if activated
- if ($domain['caa'] == '1') {
+ if (!is_null($domain['caa'])) {
// check for CAA content later
self::addRequiredEntry('@', 'CAA', $required_entries);
+ // additional required records by subdomain setting
+ if ($domain['iswildcarddomain'] == '1') {
+ self::addRequiredEntry('*', 'CAA', $required_entries);
+ } elseif ($domain['wwwserveralias'] == '1') {
+ self::addRequiredEntry('www', 'CAA', $required_entries);
+ }
}
// additional required records for SPF and DKIM if activated
@@ -287,7 +293,16 @@ class Dns
// CAA
if (array_key_exists("CAA", $required_entries)) {
- $zonerecords[] = new DnsEntry('@', 'CAA', '0 issue "letsencrypt.org"');
+ foreach ($required_entries as $type => $records) {
+ if ($type == 'CAA') {
+ foreach ($records as $record) {
+ $caa_entries = explode(PHP_EOL, $domain['caa']);
+ foreach ($caa_entries as $entry) {
+ $zonerecords[] = new DnsEntry($record, 'CAA', self::encloseTXTContent($entry));
+ }
+ }
+ }
+ }
}
}
diff --git a/lib/formfields/admin/domains/formfield.domains_add.php b/lib/formfields/admin/domains/formfield.domains_add.php
index b3460fae..b2dde16b 100644
--- a/lib/formfields/admin/domains/formfield.domains_add.php
+++ b/lib/formfields/admin/domains/formfield.domains_add.php
@@ -215,17 +215,14 @@ return array(
'value' => array()
),
'caa' => array(
- 'visible' => (\Froxlor\Settings::Get('system.leenabled') == '1' ? ($ssl_ipsandports != '' ? true : false) : false),
+ 'visible' => $ssl_ipsandports != '' ? true : false,
+ 'style' => 'align-top',
'label' => $lng['admin']['caa']['title'],
'desc' => $lng['admin']['caa']['description'],
- 'type' => 'checkbox',
- 'values' => array(
- array(
- 'label' => $lng['panel']['yes'],
- 'value' => '1'
- )
- ),
- 'value' => array()
+ 'type' => 'textarea',
+ 'value' => (\Froxlor\Settings::Get('system.leenabled') == '1' ? ($ssl_ipsandports != '' ? '0 issue "letsencrypt.org"' : '') : ''),
+ 'cols' => 60,
+ 'rows' => 5
),
'http2' => array(
'visible' => ($ssl_ipsandports != '' ? true : false) && \Froxlor\Settings::Get('system.webserver') != 'lighttpd' && \Froxlor\Settings::Get('system.http2_support') == '1',
diff --git a/lib/formfields/admin/domains/formfield.domains_edit.php b/lib/formfields/admin/domains/formfield.domains_edit.php
index 7fe2fe54..5585a193 100644
--- a/lib/formfields/admin/domains/formfield.domains_edit.php
+++ b/lib/formfields/admin/domains/formfield.domains_edit.php
@@ -251,19 +251,14 @@ return array(
)
),
'caa' => array(
- 'visible' => (\Froxlor\Settings::Get('system.leenabled') == '1' ? ($ssl_ipsandports != '' ? true : false) : false),
+ 'visible' => $ssl_ipsandports != '' ? true : false,
+ 'style' => 'align-top',
'label' => $lng['admin']['caa']['title'],
'desc' => $lng['admin']['caa']['description'],
- 'type' => 'checkbox',
- 'values' => array(
- array(
- 'label' => $lng['panel']['yes'],
- 'value' => '1'
- )
- ),
- 'value' => array(
- $result['caa']
- )
+ 'type' => 'textarea',
+ 'value' => $result['caa'],
+ 'cols' => 60,
+ 'rows' => 5
),
'http2' => array(
'visible' => ($ssl_ipsandports != '' ? true : false) && \Froxlor\Settings::Get('system.webserver') != 'lighttpd' && \Froxlor\Settings::Get('system.http2_support') == '1',
diff --git a/lib/formfields/customer/domains/formfield.domains_add.php b/lib/formfields/customer/domains/formfield.domains_add.php
index b620dba1..15f352d2 100644
--- a/lib/formfields/customer/domains/formfield.domains_add.php
+++ b/lib/formfields/customer/domains/formfield.domains_add.php
@@ -109,17 +109,14 @@ return array(
'value' => array()
),
'caa' => array(
- 'visible' => \Froxlor\Settings::Get('system.leenabled') == '1' ? true : false,
+ 'visible' => $ssl_ipsandports != '' ? true : false,
+ 'style' => 'align-top',
'label' => $lng['customer']['caa']['title'],
'desc' => $lng['customer']['caa']['description'],
- 'type' => 'checkbox',
- 'values' => array(
- array(
- 'label' => $lng['panel']['yes'],
- 'value' => '1'
- )
- ),
- 'value' => array()
+ 'type' => 'textarea',
+ 'value' => (\Froxlor\Settings::Get('system.leenabled') == '1' ? ($ssl_ipsandports != '' ? '0 issue "letsencrypt.org"' : '') : ''),
+ 'cols' => 60,
+ 'rows' => 5
),
'hsts_maxage' => array(
'label' => $lng['admin']['domain_hsts_maxage']['title'],
diff --git a/lib/formfields/customer/domains/formfield.domains_edit.php b/lib/formfields/customer/domains/formfield.domains_edit.php
index c5315487..9a21d3e6 100644
--- a/lib/formfields/customer/domains/formfield.domains_edit.php
+++ b/lib/formfields/customer/domains/formfield.domains_edit.php
@@ -129,19 +129,14 @@ return array(
)
),
'caa' => array(
- 'visible' => \Froxlor\Settings::Get('system.leenabled') == '1' ? true : false,
+ 'visible' => $ssl_ipsandports != '' ? true : false,
+ 'style' => 'align-top',
'label' => $lng['customer']['caa']['title'],
'desc' => $lng['customer']['caa']['description'],
- 'type' => 'checkbox',
- 'values' => array(
- array(
- 'label' => $lng['panel']['yes'],
- 'value' => '1'
- )
- ),
- 'value' => array(
- $result['caa']
- )
+ 'type' => 'textarea',
+ 'value' => $result['caa'],
+ 'cols' => 60,
+ 'rows' => 5
),
'hsts_maxage' => array(
'label' => $lng['admin']['domain_hsts_maxage']['title'],
diff --git a/lng/english.lng.php b/lng/english.lng.php
index 3ee60eeb..e88c4d13 100644
--- a/lng/english.lng.php
+++ b/lng/english.lng.php
@@ -1849,10 +1849,10 @@ $lng['serversettings']['leenabled']['description'] = "If activated, customers ar
$lng['domains']['ssl_redirect_temporarilydisabled'] = " The SSL redirect is temporarily deactivated while a new Let's Encrypt certificate is generated. It will be activated again after the certificate was generated.";
// Added for CAA record support
-$lng['admin']['caa']['title'] = 'Use CAA DNS record';
-$lng['admin']['caa']['description'] = 'DNS Certification Authority Authorization (CAA) is an Internet security policy mechanism which allows domain name holders to indicate to certificate authorities whether they are authorized to issue digital certificates for a particular domain name. It does this by means of a new "CAA" Domain Name System (DNS) resource record. Currently it only supports Let\'s Encrypt. This feature is still in beta.';
-$lng['customer']['caa']['title'] = 'Use CAA DNS record';
-$lng['customer']['caa']['description'] = 'DNS Certification Authority Authorization (CAA) is an Internet security policy mechanism which allows domain name holders to indicate to certificate authorities whether they are authorized to issue digital certificates for a particular domain name. It does this by means of a new "CAA" Domain Name System (DNS) resource record. Currently it only supports Let\'s Encrypt. This feature is still in beta.';
+$lng['admin']['caa']['title'] = 'Use CAA DNS records';
+$lng['admin']['caa']['description'] = 'DNS Certification Authority Authorization (CAA) is an Internet security policy mechanism which allows domain name holders to indicate to certificate authorities whether they are authorized to issue digital certificates for a particular domain name. It does this by means of a new "CAA" Domain Name System (DNS) resource record. The content of this field will be included into the DNS zone directly (each line results in a CAA record). An example for the use with Let\'s Encrypt would be:0 issue "letsencrypt.org" To enable Incident Reporting, you would need to add an iodef record. An example for sending such report to me@example.com would be:0 iodef "mailto:me@example.com"Attention: The code won\'t be checked for any errors. If it contains errors, DNS server might not start again!';
+$lng['customer']['caa']['title'] = 'Use CAA DNS records';
+$lng['customer']['caa']['description'] = 'DNS Certification Authority Authorization (CAA) is an Internet security policy mechanism which allows domain name holders to indicate to certificate authorities whether they are authorized to issue digital certificates for a particular domain name. It does this by means of a new "CAA" Domain Name System (DNS) resource record. The content of this field will be included into the DNS zone directly (each line results in a CAA record). An example for the use with Let\'s Encrypt would be:0 issue "letsencrypt.org" To enable Incident Reporting, you would need to add an iodef record. An example for sending such report to me@example.com would be:0 iodef "mailto:me@example.com"Attention: The code won\'t be checked for any errors. If it contains errors, DNS server might not start again!';
// Autoupdate
$lng['admin']['autoupdate'] = 'Auto-Update';
diff --git a/lng/german.lng.php b/lng/german.lng.php
index 37c3f08f..a838ce0a 100644
--- a/lng/german.lng.php
+++ b/lng/german.lng.php
@@ -1501,10 +1501,10 @@ $lng['serversettings']['leenabled']['description'] = "Wenn dies aktiviert ist, k
$lng['domains']['ssl_redirect_temporarilydisabled'] = " Die SSL-Umleitung ist, während ein neues Let's Encrypt - Zertifikat erstellt wird, temporär deaktiviert. Die Umleitung wird nach der Zertifikatserstellung wieder aktiviert.";
// Added for CAA record support
-$lng['admin']['caa']['title'] = 'CAA DNS Eintrag erstellen';
-$lng['admin']['caa']['description'] = 'DNS Certification Authority Authorization (CAA) verwendet das Domain Name System, um dem Besitzer einer Domain die Möglichkeit zu bieten, gewisse Zertifizierungsstellen (CAs) dazu zu berechtigen, ein Zertifikat für die betroffene Domain auszustellen. CAA Records sollen verhindern, dass Zertifikate fälschlicherweise für eine Domain ausgestellt werden. Im Moment wird nur Let\'s Encrypt unterstützt. Dieses Feature befindet sich noch im Test.';
-$lng['customer']['caa']['title'] = 'CAA DNS Eintrag erstellen';
-$lng['customer']['caa']['description'] = 'DNS Certification Authority Authorization (CAA) verwendet das Domain Name System, um dem Besitzer einer Domain die Möglichkeit zu bieten, gewisse Zertifizierungsstellen (CAs) dazu zu berechtigen, ein Zertifikat für die betroffene Domain auszustellen. CAA Records sollen verhindern, dass Zertifikate fälschlicherweise für eine Domain ausgestellt werden. Im Moment wird nur Let\'s Encrypt unterstützt. Dieses Feature befindet sich noch im Test.';
+$lng['admin']['caa']['title'] = 'CAA DNS Einträge erstellen';
+$lng['admin']['caa']['description'] = 'DNS Certification Authority Authorization (CAA) verwendet das Domain Name System, um dem Besitzer einer Domain die Möglichkeit zu bieten, gewisse Zertifizierungsstellen (CAs) dazu zu berechtigen, ein Zertifikat für die betroffene Domain auszustellen. CAA Records sollen verhindern, dass Zertifikate fälschlicherweise für eine Domain ausgestellt werden. Der Inhalt dieses Feldes wird direkt in die DNS Zone übernommen (eine Zeile pro CAA Record). Ein Beispiel für Let\'s Encrypt wäre:0 issue "letsencrypt.org" Um Incident Reporting per Mail zu aktivieren, muss eine iodef Zeile angefügt werden. Ein Beispiel für einen Report an me@example.com wäre:0 iodef "mailto:me@example.com"ACHTUNG: Der Code wird nicht auf Fehler geprüft. Etwaige Fehler werden also auch übernommen. Der DNS-Server könnte nicht mehr starten!';
+$lng['customer']['caa']['title'] = 'CAA DNS Einträge erstellen';
+$lng['customer']['caa']['description'] = 'DNS Certification Authority Authorization (CAA) verwendet das Domain Name System, um dem Besitzer einer Domain die Möglichkeit zu bieten, gewisse Zertifizierungsstellen (CAs) dazu zu berechtigen, ein Zertifikat für die betroffene Domain auszustellen. CAA Records sollen verhindern, dass Zertifikate fälschlicherweise für eine Domain ausgestellt werden. Der Inhalt dieses Feldes wird direkt in die DNS Zone übernommen (eine Zeile pro CAA Record). Ein Beispiel für Let\'s Encrypt wäre:0 issue "letsencrypt.org" Um Incident Reporting per Mail zu aktivieren, muss eine iodef Zeile angefügt werden. Ein Beispiel für einen Report an me@example.com wäre:0 iodef "mailto:me@example.com"ACHTUNG: Der Code wird nicht auf Fehler geprüft. Etwaige Fehler werden also auch übernommen. Der DNS-Server könnte nicht mehr starten!';
// Autoupdate
$lng['admin']['autoupdate'] = 'Auto-Update';
From 57ac337ef7688fe52db083a31c1323b19486b2fb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Kolly?=
Date: Sun, 28 Jul 2019 16:52:05 +0200
Subject: [PATCH 053/159] Add a few more commonly used RR types to DNS editor
---
dns_editor.php | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/dns_editor.php b/dns_editor.php
index c1d28546..936193e0 100644
--- a/dns_editor.php
+++ b/dns_editor.php
@@ -108,11 +108,22 @@ if (! empty($dom_entries)) {
$type_select_values = array(
'A',
'AAAA',
- 'NS',
+ 'CAA',
+ 'CNAME',
+ 'DNAME',
+ 'DNSKEY',
+ 'DS',
+ 'LOC',
'MX',
+ 'NS',
+ 'NSEC',
+ 'NSEC3',
+ 'PTR',
+ 'RP',
+ 'RRSIG',
'SRV',
+ 'SSHFP',
'TXT',
- 'CNAME'
);
asort($type_select_values);
foreach ($type_select_values as $_type) {
From 5eef98fdfd0d3814b1796f1f72628d0b17cdab50 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Kolly?=
Date: Sun, 28 Jul 2019 18:10:01 +0200
Subject: [PATCH 054/159] Bump DB Version to 201907270
---
install/froxlor.sql | 2 +-
lib/Froxlor/Froxlor.php | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/install/froxlor.sql b/install/froxlor.sql
index f50c5c1f..169d7712 100644
--- a/install/froxlor.sql
+++ b/install/froxlor.sql
@@ -682,7 +682,7 @@ opcache.interned_strings_buffer'),
('panel', 'customer_hide_options', ''),
('panel', 'is_configured', '0'),
('panel', 'version', '0.10.0-rc2'),
- ('panel', 'db_version', '201904250');
+ ('panel', 'db_version', '201907270');
DROP TABLE IF EXISTS `panel_tasks`;
diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php
index 53e32359..eff34ca5 100644
--- a/lib/Froxlor/Froxlor.php
+++ b/lib/Froxlor/Froxlor.php
@@ -10,7 +10,7 @@ final class Froxlor
const VERSION = '0.10.0-rc2';
// Database version (YYYYMMDDC where C is a daily counter)
- const DBVERSION = '201904250';
+ const DBVERSION = '201907270';
// Distribution branding-tag (used for Debian etc.)
const BRANDING = '';
From b427212b00fd708b2969a6ed14fc410f69f422ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Kolly?=
Date: Sun, 28 Jul 2019 18:11:42 +0200
Subject: [PATCH 055/159] Properly implement migrations for caa field in
TABLE_DOMAIN_DNS using `showUpdateStep()` and `lastStepStatus()`
---
install/updates/froxlor/0.10/update_0.10.inc.php | 3 +++
1 file changed, 3 insertions(+)
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 fae59b55..a009fb54 100644
--- a/install/updates/froxlor/0.10/update_0.10.inc.php
+++ b/install/updates/froxlor/0.10/update_0.10.inc.php
@@ -266,6 +266,9 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.0-rc1')) {
if (\Froxlor\Froxlor::isDatabaseVersion('201904250')) {
+ showUpdateStep("Adding field caa for domains");
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `caa` text default NULL AFTER `letsencrypt`;");
+ lastStepStatus(0);
+
\Froxlor\Froxlor::updateToDbVersion('201907270');
}
\ No newline at end of file
From 358ca61a2698a137aa64b48dba24d254a016b229 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Kolly?=
Date: Sun, 28 Jul 2019 18:47:47 +0200
Subject: [PATCH 056/159] Implement validators to prevent breaking DNS server
when adding newly introduced RR types
---
dns_editor.php | 6 ---
lib/Froxlor/Api/Commands/DomainZones.php | 60 ++++++++++++++----------
2 files changed, 36 insertions(+), 30 deletions(-)
diff --git a/dns_editor.php b/dns_editor.php
index 936193e0..77f121ef 100644
--- a/dns_editor.php
+++ b/dns_editor.php
@@ -111,16 +111,10 @@ $type_select_values = array(
'CAA',
'CNAME',
'DNAME',
- 'DNSKEY',
- 'DS',
'LOC',
'MX',
'NS',
- 'NSEC',
- 'NSEC3',
- 'PTR',
'RP',
- 'RRSIG',
'SRV',
'SSHFP',
'TXT',
diff --git a/lib/Froxlor/Api/Commands/DomainZones.php b/lib/Froxlor/Api/Commands/DomainZones.php
index ccdcad79..e717d7c7 100644
--- a/lib/Froxlor/Api/Commands/DomainZones.php
+++ b/lib/Froxlor/Api/Commands/DomainZones.php
@@ -138,6 +138,34 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$errors[] = $this->lng['error']['dns_arec_noipv4'];
} elseif ($type == 'AAAA' && filter_var($content, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
$errors[] = $this->lng['error']['dns_aaaarec_noipv6'];
+ } elseif ($type == 'CAA' && ! empty($content)) {
+ // check that CAA content is enclosed in " "
+ $content = \Froxlor\Dns\Dns::encloseTXTContent($content);
+ } elseif ($type == 'CNAME' || $type == 'DNAME') {
+ // check for trailing dot
+ if (substr($content, - 1) == '.') {
+ // remove it for checks
+ $content = substr($content, 0, - 1);
+ } else {
+ // add domain name
+ $content .= '.' . $domain;
+ }
+ if (! \Froxlor\Validate\Validate::validateDomain($content, true)) {
+ $errors[] = $this->lng['error']['dns_cname_invaliddom'];
+ } else {
+ // check whether there are RR-records for the same resource
+ foreach ($dom_entries as $existing_entries) {
+ if (($existing_entries['type'] == 'A' || $existing_entries['type'] == 'AAAA' || $existing_entries['type'] == 'MX' || $existing_entries['type'] == 'NS') && $existing_entries['record'] == $record) {
+ $errors[] = $this->lng['error']['dns_cname_nomorerr'];
+ break;
+ }
+ }
+ }
+ // append trailing dot (again)
+ $content .= '.';
+ } elseif ($type == 'LOC' && ! empty($content)) {
+ // check that LOC content is enclosed in " "
+ $content = \Froxlor\Dns\Dns::encloseTXTContent($content);
} elseif ($type == 'MX') {
if ($prio === null || $prio < 0) {
$errors[] = $this->lng['error']['dns_mx_prioempty'];
@@ -161,28 +189,6 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
}
// append trailing dot (again)
$content .= '.';
- } elseif ($type == 'CNAME') {
- // check for trailing dot
- if (substr($content, - 1) == '.') {
- // remove it for checks
- $content = substr($content, 0, - 1);
- } else {
- // add domain name
- $content .= '.' . $domain;
- }
- if (! \Froxlor\Validate\Validate::validateDomain($content, true)) {
- $errors[] = $this->lng['error']['dns_cname_invaliddom'];
- } else {
- // check whether there are RR-records for the same resource
- foreach ($dom_entries as $existing_entries) {
- if (($existing_entries['type'] == 'A' || $existing_entries['type'] == 'AAAA' || $existing_entries['type'] == 'MX' || $existing_entries['type'] == 'NS') && $existing_entries['record'] == $record) {
- $errors[] = $this->lng['error']['dns_cname_nomorerr'];
- break;
- }
- }
- }
- // append trailing dot (again)
- $content .= '.';
} elseif ($type == 'NS') {
// check for trailing dot
if (substr($content, - 1) == '.') {
@@ -194,8 +200,8 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
}
// append trailing dot (again)
$content .= '.';
- } elseif ($type == 'TXT' && ! empty($content)) {
- // check that TXT content is enclosed in " "
+ } elseif ($type == 'RP' && ! empty($content)) {
+ // check that RP content is enclosed in " "
$content = \Froxlor\Dns\Dns::encloseTXTContent($content);
} elseif ($type == 'SRV') {
if ($prio === null || $prio < 0) {
@@ -232,6 +238,12 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
if (substr($content, - 1) != '.') {
$content .= '.';
}
+ } elseif ($type == 'SSHFP' && ! empty($content)) {
+ // check that SSHFP content is enclosed in " "
+ $content = \Froxlor\Dns\Dns::encloseTXTContent($content);
+ } elseif ($type == 'TXT' && ! empty($content)) {
+ // check that TXT content is enclosed in " "
+ $content = \Froxlor\Dns\Dns::encloseTXTContent($content);
}
$new_entry = array(
From 240178eba71d9e9389a874dc18b6bfc07e038a9c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Kolly?=
Date: Sun, 28 Jul 2019 19:49:32 +0200
Subject: [PATCH 057/159] Implement global CAA settings
---
actions/admin/settings/160.nameserver.php | 16 ++++++++++
install/froxlor.sql | 3 +-
.../updates/froxlor/0.10/update_0.10.inc.php | 5 +--
lib/Froxlor/Dns/Dns.php | 31 ++++++++++++-------
lng/english.lng.php | 6 ++--
lng/german.lng.php | 6 ++--
6 files changed, 45 insertions(+), 22 deletions(-)
diff --git a/actions/admin/settings/160.nameserver.php b/actions/admin/settings/160.nameserver.php
index a7df3322..8c24f75f 100644
--- a/actions/admin/settings/160.nameserver.php
+++ b/actions/admin/settings/160.nameserver.php
@@ -107,6 +107,22 @@ return array(
'default' => false,
'save_method' => 'storeSettingField'
),
+ 'system_dns_createcaaentry' => array(
+ 'label' => $lng['serversettings']['caa_entry'],
+ 'settinggroup' => 'system',
+ 'varname' => 'dns_createcaaentry',
+ 'type' => 'bool',
+ 'default' => true,
+ 'save_method' => 'storeSettingField'
+ ),
+ 'caa.caa_entry' => array(
+ 'label' => $lng['serversettings']['caa_entry_custom'],
+ 'settinggroup' => 'caa',
+ 'varname' => 'caa_entry',
+ 'type' => 'text',
+ 'default' => '',
+ 'save_method' => 'storeSettingField'
+ ),
'system_defaultttl' => array(
'label' => $lng['serversettings']['defaultttl'],
'settinggroup' => 'system',
diff --git a/install/froxlor.sql b/install/froxlor.sql
index 169d7712..f3cf318c 100644
--- a/install/froxlor.sql
+++ b/install/froxlor.sql
@@ -256,7 +256,6 @@ CREATE TABLE `panel_domains` (
`mod_fcgid_maxrequests` int(4) default '-1',
`ismainbutsubto` int(11) unsigned NOT NULL default '0',
`letsencrypt` tinyint(1) NOT NULL default '0',
- `caa` text default NULL,
`hsts` varchar(10) NOT NULL default '0',
`hsts_sub` tinyint(1) NOT NULL default '0',
`hsts_preload` tinyint(1) NOT NULL default '0',
@@ -376,6 +375,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES
('admin', 'show_news_feed', '0'),
('admin', 'show_version_login', '0'),
('admin', 'show_version_footer', '0'),
+ ('caa', 'caa_entry', ''),
('spf', 'use_spf', '0'),
('spf', 'spf_entry', '"v=spf1 a mx -all"'),
('dkim', 'dkim_algorithm', 'all'),
@@ -562,6 +562,7 @@ opcache.interned_strings_buffer'),
('system', 'mod_fcgid_defaultini', '1'),
('system', 'ftpserver', 'proftpd'),
('system', 'dns_createmailentry', '0'),
+ ('system', 'dns_createcaaentry', '1'),
('system', 'froxlordirectlyviahostname', '0'),
('system', 'report_enable', '1'),
('system', 'report_webmax', '90'),
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 a009fb54..bac449ea 100644
--- a/install/updates/froxlor/0.10/update_0.10.inc.php
+++ b/install/updates/froxlor/0.10/update_0.10.inc.php
@@ -266,8 +266,9 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.0-rc1')) {
if (\Froxlor\Froxlor::isDatabaseVersion('201904250')) {
- showUpdateStep("Adding field caa for domains");
- Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `caa` text default NULL AFTER `letsencrypt`;");
+ showUpdateStep("Adding new settings for CAA");
+ Settings::AddNew('caa.caa_entry', '', true);
+ Settings::AddNew('system.dns_createcaaentry', 1, true);
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201907270');
diff --git a/lib/Froxlor/Dns/Dns.php b/lib/Froxlor/Dns/Dns.php
index 0d754f21..bd0b4a78 100644
--- a/lib/Froxlor/Dns/Dns.php
+++ b/lib/Froxlor/Dns/Dns.php
@@ -131,15 +131,9 @@ class Dns
}
// additional required records for CAA if activated
- if (!is_null($domain['caa'])) {
+ if (Settings::Get('system.dns_createcaaentry') && Settings::Get('system.use_ssl') == "1" && !empty($domain['p_ssl_ipandports'])) {
// check for CAA content later
- self::addRequiredEntry('@', 'CAA', $required_entries);
- // additional required records by subdomain setting
- if ($domain['iswildcarddomain'] == '1') {
- self::addRequiredEntry('*', 'CAA', $required_entries);
- } elseif ($domain['wwwserveralias'] == '1') {
- self::addRequiredEntry('www', 'CAA', $required_entries);
- }
+ self::addRequiredEntry('@CAA@', 'CAA', $required_entries);
}
// additional required records for SPF and DKIM if activated
@@ -162,6 +156,10 @@ class Dns
if (array_key_exists($entry['type'], $required_entries) && array_key_exists(md5($entry['record']), $required_entries[$entry['type']])) {
unset($required_entries[$entry['type']][md5($entry['record'])]);
}
+ if (Settings::Get('system.dns_createcaaentry') == '1' && $entry['type'] == 'CAA' && strtolower(substr($entry['content'], 0, 7)) == '"v=caa1') {
+ // unset special CAA required-entry
+ unset($required_entries[$entry['type']][md5("@CAA@")]);
+ }
if (Settings::Get('spf.use_spf') == '1' && $entry['type'] == 'TXT' && $entry['record'] == '@' && strtolower(substr($entry['content'], 0, 7)) == '"v=spf1') {
// unset special spf required-entry
unset($required_entries[$entry['type']][md5("@SPF@")]);
@@ -296,9 +294,20 @@ class Dns
foreach ($required_entries as $type => $records) {
if ($type == 'CAA') {
foreach ($records as $record) {
- $caa_entries = explode(PHP_EOL, $domain['caa']);
- foreach ($caa_entries as $entry) {
- $zonerecords[] = new DnsEntry($record, 'CAA', self::encloseTXTContent($entry));
+ if ($record == '@CAA@') {
+ $caa_entries = explode(PHP_EOL, Settings::Get('caa.caa_entry'));
+ if ($domain['letsencrypt'] == 1) {
+ $le_entry = $domain['iswildcarddomain'] == '1' ? '0 issuewild "letsencrypt.org"' : '0 issue "letsencrypt.org"';
+ array_push($caa_entries, $le_entry);
+ }
+
+ foreach ($caa_entries as $entry) {
+ $zonerecords[] = new DnsEntry('@', 'CAA', self::encloseTXTContent($entry));
+ // additional required records by subdomain setting
+ if ($domain['wwwserveralias'] == '1') {
+ $zonerecords[] = new DnsEntry('www', 'CAA', self::encloseTXTContent($entry));
+ }
+ }
}
}
}
diff --git a/lng/english.lng.php b/lng/english.lng.php
index e88c4d13..289cdaa7 100644
--- a/lng/english.lng.php
+++ b/lng/english.lng.php
@@ -1849,10 +1849,8 @@ $lng['serversettings']['leenabled']['description'] = "If activated, customers ar
$lng['domains']['ssl_redirect_temporarilydisabled'] = " The SSL redirect is temporarily deactivated while a new Let's Encrypt certificate is generated. It will be activated again after the certificate was generated.";
// Added for CAA record support
-$lng['admin']['caa']['title'] = 'Use CAA DNS records';
-$lng['admin']['caa']['description'] = 'DNS Certification Authority Authorization (CAA) is an Internet security policy mechanism which allows domain name holders to indicate to certificate authorities whether they are authorized to issue digital certificates for a particular domain name. It does this by means of a new "CAA" Domain Name System (DNS) resource record. The content of this field will be included into the DNS zone directly (each line results in a CAA record). An example for the use with Let\'s Encrypt would be:0 issue "letsencrypt.org" To enable Incident Reporting, you would need to add an iodef record. An example for sending such report to me@example.com would be:0 iodef "mailto:me@example.com"Attention: The code won\'t be checked for any errors. If it contains errors, DNS server might not start again!';
-$lng['customer']['caa']['title'] = 'Use CAA DNS records';
-$lng['customer']['caa']['description'] = 'DNS Certification Authority Authorization (CAA) is an Internet security policy mechanism which allows domain name holders to indicate to certificate authorities whether they are authorized to issue digital certificates for a particular domain name. It does this by means of a new "CAA" Domain Name System (DNS) resource record. The content of this field will be included into the DNS zone directly (each line results in a CAA record). An example for the use with Let\'s Encrypt would be:0 issue "letsencrypt.org" To enable Incident Reporting, you would need to add an iodef record. An example for sending such report to me@example.com would be:0 iodef "mailto:me@example.com"Attention: The code won\'t be checked for any errors. If it contains errors, DNS server might not start again!';
+$lng['serversettings']['caa_entry'] = 'Generate CAA DNS records Automatically generates CAA records for SSL-enabled domains that are using Let\'s Encrypt';
+$lng['serversettings']['caa_custom'] = 'DNS Certification Authority Authorization (CAA) is an Internet security policy mechanism which allows domain name holders to indicate to certificate authorities whether they are authorized to issue digital certificates for a particular domain name. It does this by means of a new "CAA" Domain Name System (DNS) resource record. The content of this field will be included into the DNS zone directly (each line results in a CAA record). If Let\'s Encrypt is enabled for this domain, this entry will always be added automatically and does not need to be added manually:0 issue "letsencrypt.org" (If domain is a wildcard domain, issuewild will be used instead). To enable Incident Reporting, you can add an iodef record. An example for sending such report to me@example.com would be:0 iodef "mailto:me@example.com"Attention: The code won\'t be checked for any errors. If it contains errors, your CAA records might not work!';
// Autoupdate
$lng['admin']['autoupdate'] = 'Auto-Update';
diff --git a/lng/german.lng.php b/lng/german.lng.php
index a838ce0a..f4773dad 100644
--- a/lng/german.lng.php
+++ b/lng/german.lng.php
@@ -1501,10 +1501,8 @@ $lng['serversettings']['leenabled']['description'] = "Wenn dies aktiviert ist, k
$lng['domains']['ssl_redirect_temporarilydisabled'] = " Die SSL-Umleitung ist, während ein neues Let's Encrypt - Zertifikat erstellt wird, temporär deaktiviert. Die Umleitung wird nach der Zertifikatserstellung wieder aktiviert.";
// Added for CAA record support
-$lng['admin']['caa']['title'] = 'CAA DNS Einträge erstellen';
-$lng['admin']['caa']['description'] = 'DNS Certification Authority Authorization (CAA) verwendet das Domain Name System, um dem Besitzer einer Domain die Möglichkeit zu bieten, gewisse Zertifizierungsstellen (CAs) dazu zu berechtigen, ein Zertifikat für die betroffene Domain auszustellen. CAA Records sollen verhindern, dass Zertifikate fälschlicherweise für eine Domain ausgestellt werden. Der Inhalt dieses Feldes wird direkt in die DNS Zone übernommen (eine Zeile pro CAA Record). Ein Beispiel für Let\'s Encrypt wäre:0 issue "letsencrypt.org" Um Incident Reporting per Mail zu aktivieren, muss eine iodef Zeile angefügt werden. Ein Beispiel für einen Report an me@example.com wäre:0 iodef "mailto:me@example.com"ACHTUNG: Der Code wird nicht auf Fehler geprüft. Etwaige Fehler werden also auch übernommen. Der DNS-Server könnte nicht mehr starten!';
-$lng['customer']['caa']['title'] = 'CAA DNS Einträge erstellen';
-$lng['customer']['caa']['description'] = 'DNS Certification Authority Authorization (CAA) verwendet das Domain Name System, um dem Besitzer einer Domain die Möglichkeit zu bieten, gewisse Zertifizierungsstellen (CAs) dazu zu berechtigen, ein Zertifikat für die betroffene Domain auszustellen. CAA Records sollen verhindern, dass Zertifikate fälschlicherweise für eine Domain ausgestellt werden. Der Inhalt dieses Feldes wird direkt in die DNS Zone übernommen (eine Zeile pro CAA Record). Ein Beispiel für Let\'s Encrypt wäre:0 issue "letsencrypt.org" Um Incident Reporting per Mail zu aktivieren, muss eine iodef Zeile angefügt werden. Ein Beispiel für einen Report an me@example.com wäre:0 iodef "mailto:me@example.com"ACHTUNG: Der Code wird nicht auf Fehler geprüft. Etwaige Fehler werden also auch übernommen. Der DNS-Server könnte nicht mehr starten!';
+$lng['serversettings']['caa_entry']= 'CAA DNS Einträge generieren Generiert CAA Einträge automatisch für alle Domains mit aktiviertem SSL und Let\'s Encrypt';
+$lng['serversettings']['caa_custom']= 'DNS Certification Authority Authorization (CAA) verwendet das Domain Name System, um dem Besitzer einer Domain die Möglichkeit zu bieten, gewisse Zertifizierungsstellen (CAs) dazu zu berechtigen, ein Zertifikat für die betroffene Domain auszustellen. CAA Records sollen verhindern, dass Zertifikate fälschlicherweise für eine Domain ausgestellt werden. Der Inhalt dieses Feldes wird direkt in die DNS Zone übernommen (eine Zeile pro CAA Record). Wenn Let\'s Encrypt für eine Domain aktiviert wurde und die obige Option aktiviert wurde, wird immer automatisch dieser Eintrag angefügt und muss nicht selber angegeben werden:0 issue "letsencrypt.org" (Wenn wildcard aktiviert ist, wird statdessen issuewild benutzt). Um Incident Reporting per Mail zu aktivieren, muss eine iodef Zeile angefügt werden. Ein Beispiel für einen Report an me@example.com wäre:0 iodef "mailto:me@example.com"ACHTUNG: Der Code wird nicht auf Fehler geprüft. Etwaige Fehler werden also auch übernommen. Die CAA finalen Einträge könnten daher falsch sein!';
// Autoupdate
$lng['admin']['autoupdate'] = 'Auto-Update';
From be0470aec123ef652a1261ced99b175b794ff2da Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Kolly?=
Date: Sun, 28 Jul 2019 19:49:56 +0200
Subject: [PATCH 058/159] Revert per-domain CAA settings
---
lib/formfields/admin/domains/formfield.domains_add.php | 10 ----------
.../admin/domains/formfield.domains_edit.php | 10 ----------
.../customer/domains/formfield.domains_add.php | 10 ----------
.../customer/domains/formfield.domains_edit.php | 10 ----------
4 files changed, 40 deletions(-)
diff --git a/lib/formfields/admin/domains/formfield.domains_add.php b/lib/formfields/admin/domains/formfield.domains_add.php
index b2dde16b..ddbb6266 100644
--- a/lib/formfields/admin/domains/formfield.domains_add.php
+++ b/lib/formfields/admin/domains/formfield.domains_add.php
@@ -214,16 +214,6 @@ return array(
),
'value' => array()
),
- 'caa' => array(
- 'visible' => $ssl_ipsandports != '' ? true : false,
- 'style' => 'align-top',
- 'label' => $lng['admin']['caa']['title'],
- 'desc' => $lng['admin']['caa']['description'],
- 'type' => 'textarea',
- 'value' => (\Froxlor\Settings::Get('system.leenabled') == '1' ? ($ssl_ipsandports != '' ? '0 issue "letsencrypt.org"' : '') : ''),
- 'cols' => 60,
- 'rows' => 5
- ),
'http2' => array(
'visible' => ($ssl_ipsandports != '' ? true : false) && \Froxlor\Settings::Get('system.webserver') != 'lighttpd' && \Froxlor\Settings::Get('system.http2_support') == '1',
'label' => $lng['admin']['domain_http2']['title'],
diff --git a/lib/formfields/admin/domains/formfield.domains_edit.php b/lib/formfields/admin/domains/formfield.domains_edit.php
index 5585a193..4c756ec1 100644
--- a/lib/formfields/admin/domains/formfield.domains_edit.php
+++ b/lib/formfields/admin/domains/formfield.domains_edit.php
@@ -250,16 +250,6 @@ return array(
$result['letsencrypt']
)
),
- 'caa' => array(
- 'visible' => $ssl_ipsandports != '' ? true : false,
- 'style' => 'align-top',
- 'label' => $lng['admin']['caa']['title'],
- 'desc' => $lng['admin']['caa']['description'],
- 'type' => 'textarea',
- 'value' => $result['caa'],
- 'cols' => 60,
- 'rows' => 5
- ),
'http2' => array(
'visible' => ($ssl_ipsandports != '' ? true : false) && \Froxlor\Settings::Get('system.webserver') != 'lighttpd' && \Froxlor\Settings::Get('system.http2_support') == '1',
'label' => $lng['admin']['domain_http2']['title'],
diff --git a/lib/formfields/customer/domains/formfield.domains_add.php b/lib/formfields/customer/domains/formfield.domains_add.php
index 15f352d2..00d9fca6 100644
--- a/lib/formfields/customer/domains/formfield.domains_add.php
+++ b/lib/formfields/customer/domains/formfield.domains_add.php
@@ -108,16 +108,6 @@ return array(
),
'value' => array()
),
- 'caa' => array(
- 'visible' => $ssl_ipsandports != '' ? true : false,
- 'style' => 'align-top',
- 'label' => $lng['customer']['caa']['title'],
- 'desc' => $lng['customer']['caa']['description'],
- 'type' => 'textarea',
- 'value' => (\Froxlor\Settings::Get('system.leenabled') == '1' ? ($ssl_ipsandports != '' ? '0 issue "letsencrypt.org"' : '') : ''),
- 'cols' => 60,
- 'rows' => 5
- ),
'hsts_maxage' => array(
'label' => $lng['admin']['domain_hsts_maxage']['title'],
'desc' => $lng['admin']['domain_hsts_maxage']['description'],
diff --git a/lib/formfields/customer/domains/formfield.domains_edit.php b/lib/formfields/customer/domains/formfield.domains_edit.php
index 9a21d3e6..56a28543 100644
--- a/lib/formfields/customer/domains/formfield.domains_edit.php
+++ b/lib/formfields/customer/domains/formfield.domains_edit.php
@@ -128,16 +128,6 @@ return array(
$result['letsencrypt']
)
),
- 'caa' => array(
- 'visible' => $ssl_ipsandports != '' ? true : false,
- 'style' => 'align-top',
- 'label' => $lng['customer']['caa']['title'],
- 'desc' => $lng['customer']['caa']['description'],
- 'type' => 'textarea',
- 'value' => $result['caa'],
- 'cols' => 60,
- 'rows' => 5
- ),
'hsts_maxage' => array(
'label' => $lng['admin']['domain_hsts_maxage']['title'],
'desc' => $lng['admin']['domain_hsts_maxage']['description'],
From e67e2a85de7676857afa2a67d0a45e7743ff8014 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Kolly?=
Date: Sun, 28 Jul 2019 20:05:55 +0200
Subject: [PATCH 059/159] Implement test for Domain Zone CAA record
---
install/froxlor.sql | 4 ++--
tests/DomainZones/DomainZonesTest.php | 24 ++++++++++++++++++++++++
2 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/install/froxlor.sql b/install/froxlor.sql
index f3cf318c..51ffe079 100644
--- a/install/froxlor.sql
+++ b/install/froxlor.sql
@@ -375,7 +375,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES
('admin', 'show_news_feed', '0'),
('admin', 'show_version_login', '0'),
('admin', 'show_version_footer', '0'),
- ('caa', 'caa_entry', ''),
+ ('caa', 'caa_entry', ''),
('spf', 'use_spf', '0'),
('spf', 'spf_entry', '"v=spf1 a mx -all"'),
('dkim', 'dkim_algorithm', 'all'),
@@ -562,7 +562,7 @@ opcache.interned_strings_buffer'),
('system', 'mod_fcgid_defaultini', '1'),
('system', 'ftpserver', 'proftpd'),
('system', 'dns_createmailentry', '0'),
- ('system', 'dns_createcaaentry', '1'),
+ ('system', 'dns_createcaaentry', '1'),
('system', 'froxlordirectlyviahostname', '0'),
('system', 'report_enable', '1'),
('system', 'report_webmax', '90'),
diff --git a/tests/DomainZones/DomainZonesTest.php b/tests/DomainZones/DomainZonesTest.php
index fef9ba2f..03fe78d0 100644
--- a/tests/DomainZones/DomainZonesTest.php
+++ b/tests/DomainZones/DomainZonesTest.php
@@ -277,6 +277,30 @@ class DomainZonesTest extends TestCase
DomainZones::getLocal($admin_userdata, $data)->add();
}
+ public function testAdminDomainZonesAddCAA()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'domainname' => 'test2.local',
+ 'record' => '@',
+ 'type' => 'CAA',
+ 'content' => '0 issue "letsencrypt.org"'
+ ];
+ $json_result = DomainZones::getLocal($admin_userdata, $data)->add();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertTrue(count($result) > 1);
+ $found = false;
+ foreach ($result as $entry) {
+ if (substr($entry, strlen('0 issue "letsencrypt.org"') * - 1) == '0 issue "letsencrypt.org"') {
+ $found = true;
+ break;
+ }
+ }
+ $this->assertTrue($found);
+ $this->assertEquals('@ 18000 IN CAA 0 issue "letsencrypt.org"', $entry);
+ }
+
public function testAdminDomainZonesAddCname()
{
global $admin_userdata;
From a377c1e6c56e7a1bdc35696905167583f86440cf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Kolly?=
Date: Mon, 29 Jul 2019 07:39:11 +0200
Subject: [PATCH 060/159] Split l18n string into title and description
---
lng/english.lng.php | 6 ++++--
lng/german.lng.php | 6 ++++--
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/lng/english.lng.php b/lng/english.lng.php
index 289cdaa7..4996b77e 100644
--- a/lng/english.lng.php
+++ b/lng/english.lng.php
@@ -1849,8 +1849,10 @@ $lng['serversettings']['leenabled']['description'] = "If activated, customers ar
$lng['domains']['ssl_redirect_temporarilydisabled'] = " The SSL redirect is temporarily deactivated while a new Let's Encrypt certificate is generated. It will be activated again after the certificate was generated.";
// Added for CAA record support
-$lng['serversettings']['caa_entry'] = 'Generate CAA DNS records Automatically generates CAA records for SSL-enabled domains that are using Let\'s Encrypt';
-$lng['serversettings']['caa_custom'] = 'DNS Certification Authority Authorization (CAA) is an Internet security policy mechanism which allows domain name holders to indicate to certificate authorities whether they are authorized to issue digital certificates for a particular domain name. It does this by means of a new "CAA" Domain Name System (DNS) resource record. The content of this field will be included into the DNS zone directly (each line results in a CAA record). If Let\'s Encrypt is enabled for this domain, this entry will always be added automatically and does not need to be added manually:0 issue "letsencrypt.org" (If domain is a wildcard domain, issuewild will be used instead). To enable Incident Reporting, you can add an iodef record. An example for sending such report to me@example.com would be:0 iodef "mailto:me@example.com"Attention: The code won\'t be checked for any errors. If it contains errors, your CAA records might not work!';
+$lng['serversettings']['caa_entry']['title'] = 'Generate CAA DNS records';
+$lng['serversettings']['caa_entry']['description'] = 'Automatically generates CAA records for SSL-enabled domains that are using Let\'s Encrypt';
+$lng['serversettings']['caa_custom']['title'] = 'Additional CAA DNS records';
+$lng['serversettings']['caa_custom']['description'] = 'DNS Certification Authority Authorization (CAA) is an Internet security policy mechanism which allows domain name holders to indicate to certificate authorities whether they are authorized to issue digital certificates for a particular domain name. It does this by means of a new "CAA" Domain Name System (DNS) resource record. The content of this field will be included into the DNS zone directly (each line results in a CAA record). If Let\'s Encrypt is enabled for this domain, this entry will always be added automatically and does not need to be added manually:0 issue "letsencrypt.org" (If domain is a wildcard domain, issuewild will be used instead). To enable Incident Reporting, you can add an iodef record. An example for sending such report to me@example.com would be:0 iodef "mailto:me@example.com"Attention: The code won\'t be checked for any errors. If it contains errors, your CAA records might not work!';
// Autoupdate
$lng['admin']['autoupdate'] = 'Auto-Update';
diff --git a/lng/german.lng.php b/lng/german.lng.php
index f4773dad..eb861056 100644
--- a/lng/german.lng.php
+++ b/lng/german.lng.php
@@ -1501,8 +1501,10 @@ $lng['serversettings']['leenabled']['description'] = "Wenn dies aktiviert ist, k
$lng['domains']['ssl_redirect_temporarilydisabled'] = " Die SSL-Umleitung ist, während ein neues Let's Encrypt - Zertifikat erstellt wird, temporär deaktiviert. Die Umleitung wird nach der Zertifikatserstellung wieder aktiviert.";
// Added for CAA record support
-$lng['serversettings']['caa_entry']= 'CAA DNS Einträge generieren Generiert CAA Einträge automatisch für alle Domains mit aktiviertem SSL und Let\'s Encrypt';
-$lng['serversettings']['caa_custom']= 'DNS Certification Authority Authorization (CAA) verwendet das Domain Name System, um dem Besitzer einer Domain die Möglichkeit zu bieten, gewisse Zertifizierungsstellen (CAs) dazu zu berechtigen, ein Zertifikat für die betroffene Domain auszustellen. CAA Records sollen verhindern, dass Zertifikate fälschlicherweise für eine Domain ausgestellt werden. Der Inhalt dieses Feldes wird direkt in die DNS Zone übernommen (eine Zeile pro CAA Record). Wenn Let\'s Encrypt für eine Domain aktiviert wurde und die obige Option aktiviert wurde, wird immer automatisch dieser Eintrag angefügt und muss nicht selber angegeben werden:0 issue "letsencrypt.org" (Wenn wildcard aktiviert ist, wird statdessen issuewild benutzt). Um Incident Reporting per Mail zu aktivieren, muss eine iodef Zeile angefügt werden. Ein Beispiel für einen Report an me@example.com wäre:0 iodef "mailto:me@example.com"ACHTUNG: Der Code wird nicht auf Fehler geprüft. Etwaige Fehler werden also auch übernommen. Die CAA finalen Einträge könnten daher falsch sein!';
+$lng['serversettings']['caa_entry']['title'] = 'CAA DNS Einträge generieren';
+$lng['serversettings']['caa_entry']['description'] = 'Generiert CAA Einträge automatisch für alle Domains mit aktiviertem SSL und Let\'s Encrypt';
+$lng['serversettings']['caa_custom']['title'] = 'Zusätzliche CAA DNS Einträge';
+$lng['serversettings']['caa_custom']['description'] = 'DNS Certification Authority Authorization (CAA) verwendet das Domain Name System, um dem Besitzer einer Domain die Möglichkeit zu bieten, gewisse Zertifizierungsstellen (CAs) dazu zu berechtigen, ein Zertifikat für die betroffene Domain auszustellen. CAA Records sollen verhindern, dass Zertifikate fälschlicherweise für eine Domain ausgestellt werden. Der Inhalt dieses Feldes wird direkt in die DNS Zone übernommen (eine Zeile pro CAA Record). Wenn Let\'s Encrypt für eine Domain aktiviert wurde und die obige Option aktiviert wurde, wird immer automatisch dieser Eintrag angefügt und muss nicht selber angegeben werden:0 issue "letsencrypt.org" (Wenn wildcard aktiviert ist, wird statdessen issuewild benutzt). Um Incident Reporting per Mail zu aktivieren, muss eine iodef Zeile angefügt werden. Ein Beispiel für einen Report an me@example.com wäre:0 iodef "mailto:me@example.com"ACHTUNG: Der Code wird nicht auf Fehler geprüft. Etwaige Fehler werden also auch übernommen. Die CAA finalen Einträge könnten daher falsch sein!';
// Autoupdate
$lng['admin']['autoupdate'] = 'Auto-Update';
From 78ef2a4e236bc46fa947d10a1a92c58e02cf7c3a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Kolly?=
Date: Mon, 29 Jul 2019 07:41:09 +0200
Subject: [PATCH 061/159] Fix serversettings field
---
actions/admin/settings/160.nameserver.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/actions/admin/settings/160.nameserver.php b/actions/admin/settings/160.nameserver.php
index 8c24f75f..67260bfa 100644
--- a/actions/admin/settings/160.nameserver.php
+++ b/actions/admin/settings/160.nameserver.php
@@ -115,7 +115,7 @@ return array(
'default' => true,
'save_method' => 'storeSettingField'
),
- 'caa.caa_entry' => array(
+ 'caa_caa_entry' => array(
'label' => $lng['serversettings']['caa_entry_custom'],
'settinggroup' => 'caa',
'varname' => 'caa_entry',
From bfb3fb0a92bb02308797661eb549fc34d3711122 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Kolly?=
Date: Mon, 29 Jul 2019 11:36:34 +0200
Subject: [PATCH 062/159] Add Regex to check for invalid CAA entry
---
lib/Froxlor/Api/Commands/DomainZones.php | 11 +++++++++--
lng/english.lng.php | 1 +
lng/german.lng.php | 1 +
3 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/lib/Froxlor/Api/Commands/DomainZones.php b/lib/Froxlor/Api/Commands/DomainZones.php
index e717d7c7..9e233fec 100644
--- a/lib/Froxlor/Api/Commands/DomainZones.php
+++ b/lib/Froxlor/Api/Commands/DomainZones.php
@@ -139,8 +139,15 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
} elseif ($type == 'AAAA' && filter_var($content, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
$errors[] = $this->lng['error']['dns_aaaarec_noipv6'];
} elseif ($type == 'CAA' && ! empty($content)) {
- // check that CAA content is enclosed in " "
- $content = \Froxlor\Dns\Dns::encloseTXTContent($content);
+ $re = '/(?\'critical\'\d)\h*(?\'type\'iodef|issue|issuewild)\h*(?\'value\'(?\'issuevalue\'"(?\'domain\'(?=.{3,128}$)(?>(?>[a-zA-Z0-9]+[a-zA-Z0-9-]*[a-zA-Z0-9]+|[a-zA-Z0-9]+)\.)*(?>[a-zA-Z]{2,}|[a-zA-Z0-9]{2,}\.[a-zA-Z]{2,}))[;\h]*(?\'parameters\'(?>[a-zA-Z0-9]{1,60}=[a-zA-Z0-9]{1,60}\h*)+)?")|(?\'iodefvalue\'"(?\'url\'(mailto:.*|http:\/\/.*|https:\/\/.*))"))/';
+ preg_match($re, $content, $matches);
+
+ if (empty($matches)) {
+ $errors[] = $this->lng['error']['dns_content_invalid'];
+ } else {
+ // check that CAA content is enclosed in " "
+ $content = \Froxlor\Dns\Dns::encloseTXTContent($matches[0]);
+ }
} elseif ($type == 'CNAME' || $type == 'DNAME') {
// check for trailing dot
if (substr($content, - 1) == '.') {
diff --git a/lng/english.lng.php b/lng/english.lng.php
index 4996b77e..aad8a566 100644
--- a/lng/english.lng.php
+++ b/lng/english.lng.php
@@ -1892,6 +1892,7 @@ $lng['tasks']['backup_customerfiles'] = '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';
+$lng['error']['dns_content_invalid'] = 'DNS content invalid';
$lng['error']['dns_arec_noipv4'] = 'No valid IP address for A-record given';
$lng['error']['dns_aaaarec_noipv6'] = 'No valid IP address for AAAA-record given';
$lng['error']['dns_mx_prioempty'] = 'Invalid MX priority given';
diff --git a/lng/german.lng.php b/lng/german.lng.php
index eb861056..9c335afe 100644
--- a/lng/german.lng.php
+++ b/lng/german.lng.php
@@ -1543,6 +1543,7 @@ $lng['tasks']['backup_customerfiles'] = 'Datensicherung für Kunde %loginname%';
$lng['error']['dns_domain_nodns'] = 'DNS ist für diese Domain nicht aktiviert';
$lng['error']['dns_content_empty'] = 'Keinen Inhalt angegeben';
+$lng['error']['dns_content_invalid'] = 'DNS Eintrag ungültig';
$lng['error']['dns_arec_noipv4'] = 'Keine gültige IP-Adresse für A-Eintrag angegeben';
$lng['error']['dns_aaaarec_noipv6'] = 'Keine gültige IP-Adresse für AAAA-Eintrag angegeben';
$lng['error']['dns_mx_prioempty'] = 'Ungültige MX Priorität angegeben';
From 95d47eb6c9ecc9a28cff3f02ef03d29fe3aae8d1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Kolly?=
Date: Mon, 29 Jul 2019 11:53:00 +0200
Subject: [PATCH 063/159] Add unit tests for CAA entry validation
---
tests/DomainZones/DomainZonesTest.php | 320 +++++++++++++++++++++++++-
1 file changed, 319 insertions(+), 1 deletion(-)
diff --git a/tests/DomainZones/DomainZonesTest.php b/tests/DomainZones/DomainZonesTest.php
index 03fe78d0..42a3b493 100644
--- a/tests/DomainZones/DomainZonesTest.php
+++ b/tests/DomainZones/DomainZonesTest.php
@@ -277,7 +277,7 @@ class DomainZonesTest extends TestCase
DomainZones::getLocal($admin_userdata, $data)->add();
}
- public function testAdminDomainZonesAddCAA()
+ public function testAdminDomainZonesAddCAAIssue()
{
global $admin_userdata;
@@ -301,6 +301,324 @@ class DomainZonesTest extends TestCase
$this->assertEquals('@ 18000 IN CAA 0 issue "letsencrypt.org"', $entry);
}
+ public function testAdminDomainZonesAddCAAIssueWithParameters()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'domainname' => 'test2.local',
+ 'record' => '@',
+ 'type' => 'CAA',
+ 'content' => '0 issue "letsencrypt.org; account=230123"'
+ ];
+ $json_result = DomainZones::getLocal($admin_userdata, $data)->add();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertTrue(count($result) > 1);
+ $found = false;
+ foreach ($result as $entry) {
+ if (substr($entry, strlen('0 issue "letsencrypt.org; account=230123"') * - 1) == '0 issue "letsencrypt.org; account=230123"') {
+ $found = true;
+ break;
+ }
+ }
+ $this->assertTrue($found);
+ $this->assertEquals('@ 18000 IN CAA 0 issue "letsencrypt.org; account=230123"', $entry);
+ }
+
+ public function testAdminDomainZonesAddCAAIssueWithTwoParameters()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'domainname' => 'test2.local',
+ 'record' => '@',
+ 'type' => 'CAA',
+ 'content' => '0 issue "letsencrypt.org; account=230123 policy=ev"'
+ ];
+ $json_result = DomainZones::getLocal($admin_userdata, $data)->add();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertTrue(count($result) > 1);
+ $found = false;
+ foreach ($result as $entry) {
+ if (substr($entry, strlen('0 issue "letsencrypt.org; account=230123 policy=ev"') * - 1) == '0 issue "letsencrypt.org; account=230123 policy=ev"') {
+ $found = true;
+ break;
+ }
+ }
+ $this->assertTrue($found);
+ $this->assertEquals('@ 18000 IN CAA 0 issue "letsencrypt.org; account=230123 policy=ev"', $entry);
+ }
+
+ public function testAdminDomainZonesAddCAAInvalidIssueValue()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'domainname' => 'test2.local',
+ 'record' => '@',
+ 'type' => 'CAA',
+ 'content' => '0 issue ""letsencrypt.org"'
+ ];
+ $this->expectExceptionMessage("DNS content invalid");
+ DomainZones::getLocal($admin_userdata, $data)->add();
+ }
+
+ public function testAdminDomainZonesAddCAAInvalidIssueDomain()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'domainname' => 'test2.local',
+ 'record' => '@',
+ 'type' => 'CAA',
+ 'content' => '0 issue "no-valid-domain"'
+ ];
+ $this->expectExceptionMessage("DNS content invalid");
+ DomainZones::getLocal($admin_userdata, $data)->add();
+ }
+
+ public function testAdminDomainZonesAddCAAInvalidIssueTld()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'domainname' => 'test2.local',
+ 'record' => '@',
+ 'type' => 'CAA',
+ 'content' => '0 issue "no-valid-domai.n"'
+ ];
+ $this->expectExceptionMessage("DNS content invalid");
+ DomainZones::getLocal($admin_userdata, $data)->add();
+ }
+
+ public function testAdminDomainZonesAddCAAIssueWild()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'domainname' => 'test2.local',
+ 'record' => '@',
+ 'type' => 'CAA',
+ 'content' => '0 issuewild "letsencrypt.org"'
+ ];
+ $json_result = DomainZones::getLocal($admin_userdata, $data)->add();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertTrue(count($result) > 1);
+ $found = false;
+ foreach ($result as $entry) {
+ if (substr($entry, strlen('0 issuewild "letsencrypt.org"') * - 1) == '0 issuewild "letsencrypt.org"') {
+ $found = true;
+ break;
+ }
+ }
+ $this->assertTrue($found);
+ $this->assertEquals('@ 18000 IN CAA 0 issuewild "letsencrypt.org"', $entry);
+ }
+
+ public function testAdminDomainZonesAddCAAIssueWildWithParameters()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'domainname' => 'test2.local',
+ 'record' => '@',
+ 'type' => 'CAA',
+ 'content' => '0 issuewild "letsencrypt.org; account=230123"'
+ ];
+ $json_result = DomainZones::getLocal($admin_userdata, $data)->add();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertTrue(count($result) > 1);
+ $found = false;
+ foreach ($result as $entry) {
+ if (substr($entry, strlen('0 issuewild "letsencrypt.org; account=230123"') * - 1) == '0 issuewild "letsencrypt.org; account=230123"') {
+ $found = true;
+ break;
+ }
+ }
+ $this->assertTrue($found);
+ $this->assertEquals('@ 18000 IN CAA 0 issuewild "letsencrypt.org; account=230123"', $entry);
+ }
+
+ public function testAdminDomainZonesAddCAAIssueWildWithTwoParameters()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'domainname' => 'test2.local',
+ 'record' => '@',
+ 'type' => 'CAA',
+ 'content' => '0 issuewild "letsencrypt.org; account=230123 policy=ev"'
+ ];
+ $json_result = DomainZones::getLocal($admin_userdata, $data)->add();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertTrue(count($result) > 1);
+ $found = false;
+ foreach ($result as $entry) {
+ if (substr($entry, strlen('0 issuewild "letsencrypt.org; account=230123 policy=ev"') * - 1) == '0 issuewild "letsencrypt.org; account=230123 policy=ev"') {
+ $found = true;
+ break;
+ }
+ }
+ $this->assertTrue($found);
+ $this->assertEquals('@ 18000 IN CAA 0 issuewild "letsencrypt.org; account=230123 policy=ev"', $entry);
+ }
+
+ public function testAdminDomainZonesAddCAAInvalidIssueWildValue()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'domainname' => 'test2.local',
+ 'record' => '@',
+ 'type' => 'CAA',
+ 'content' => '0 issuewild ""letsencrypt.org"'
+ ];
+ $this->expectExceptionMessage("DNS content invalid");
+ DomainZones::getLocal($admin_userdata, $data)->add();
+ }
+
+ public function testAdminDomainZonesAddCAAInvalidIssueWildDomain()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'domainname' => 'test2.local',
+ 'record' => '@',
+ 'type' => 'CAA',
+ 'content' => '0 issuewild "no-valid-domain"'
+ ];
+ $this->expectExceptionMessage("DNS content invalid");
+ DomainZones::getLocal($admin_userdata, $data)->add();
+ }
+
+ public function testAdminDomainZonesAddCAAInvalidIssueWildTld()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'domainname' => 'test2.local',
+ 'record' => '@',
+ 'type' => 'CAA',
+ 'content' => '0 issuewild "no-valid-domai.n"'
+ ];
+ $this->expectExceptionMessage("DNS content invalid");
+ DomainZones::getLocal($admin_userdata, $data)->add();
+ }
+
+ public function testAdminDomainZonesAddCAAIodefMail()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'domainname' => 'test2.local',
+ 'record' => '@',
+ 'type' => 'CAA',
+ 'content' => '0 iodef "mailto:security@example.com"'
+ ];
+ $json_result = DomainZones::getLocal($admin_userdata, $data)->add();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertTrue(count($result) > 1);
+ $found = false;
+ foreach ($result as $entry) {
+ if (substr($entry, strlen('0 iodef "mailto:security@example.com"') * - 1) == '0 iodef "mailto:security@example.com"') {
+ $found = true;
+ break;
+ }
+ }
+ $this->assertTrue($found);
+ $this->assertEquals('@ 18000 IN CAA 0 iodef "mailto:security@example.com"', $entry);
+ }
+
+ public function testAdminDomainZonesAddCAAIodefMailInvalid()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'domainname' => 'test2.local',
+ 'record' => '@',
+ 'type' => 'CAA',
+ 'content' => '0 iodef "mailtosecurity@example.com"'
+ ];
+ $this->expectExceptionMessage("DNS content invalid");
+ DomainZones::getLocal($admin_userdata, $data)->add();
+ }
+
+ public function testAdminDomainZonesAddCAAIodefHttp()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'domainname' => 'test2.local',
+ 'record' => '@',
+ 'type' => 'CAA',
+ 'content' => '0 iodef "http://iodef.example.com/"'
+ ];
+ $json_result = DomainZones::getLocal($admin_userdata, $data)->add();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertTrue(count($result) > 1);
+ $found = false;
+ foreach ($result as $entry) {
+ if (substr($entry, strlen('0 iodef "http://iodef.example.com/"') * - 1) == '0 iodef "http://iodef.example.com/"') {
+ $found = true;
+ break;
+ }
+ }
+ $this->assertTrue($found);
+ $this->assertEquals('@ 18000 IN CAA 0 iodef "http://iodef.example.com/"', $entry);
+ }
+
+ public function testAdminDomainZonesAddCAAIodefHttpInvalid()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'domainname' => 'test2.local',
+ 'record' => '@',
+ 'type' => 'CAA',
+ 'content' => '0 iodef "http:/iodef.example.com/"'
+ ];
+ $this->expectExceptionMessage("DNS content invalid");
+ DomainZones::getLocal($admin_userdata, $data)->add();
+ }
+
+ public function testAdminDomainZonesAddCAAIodefHttps()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'domainname' => 'test2.local',
+ 'record' => '@',
+ 'type' => 'CAA',
+ 'content' => '0 iodef "https://iodef.example.com/"'
+ ];
+ $json_result = DomainZones::getLocal($admin_userdata, $data)->add();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertTrue(count($result) > 1);
+ $found = false;
+ foreach ($result as $entry) {
+ if (substr($entry, strlen('0 iodef "https://iodef.example.com/"') * - 1) == '0 iodef "https://iodef.example.com/"') {
+ $found = true;
+ break;
+ }
+ }
+ $this->assertTrue($found);
+ $this->assertEquals('@ 18000 IN CAA 0 iodef "https://iodef.example.com/"', $entry);
+ }
+
+ public function testAdminDomainZonesAddCAAIodefHttpsInvalid()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'domainname' => 'test2.local',
+ 'record' => '@',
+ 'type' => 'CAA',
+ 'content' => '0 iodef "https:/iodef.example.com/"'
+ ];
+ $this->expectExceptionMessage("DNS content invalid");
+ DomainZones::getLocal($admin_userdata, $data)->add();
+ }
+
public function testAdminDomainZonesAddCname()
{
global $admin_userdata;
From 16ccc273a9a112a49168305f347c301cf85a348e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Kolly?=
Date: Mon, 29 Jul 2019 14:27:44 +0200
Subject: [PATCH 064/159] Don't actually enclose CAA records in brackets
---
lib/Froxlor/Api/Commands/DomainZones.php | 12 ++++--------
lib/Froxlor/Dns/Dns.php | 4 ++--
lib/userdata.inc.php.bak | 10 ++++++++++
3 files changed, 16 insertions(+), 10 deletions(-)
create mode 100644 lib/userdata.inc.php.bak
diff --git a/lib/Froxlor/Api/Commands/DomainZones.php b/lib/Froxlor/Api/Commands/DomainZones.php
index 9e233fec..88b4eb80 100644
--- a/lib/Froxlor/Api/Commands/DomainZones.php
+++ b/lib/Froxlor/Api/Commands/DomainZones.php
@@ -145,8 +145,7 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
if (empty($matches)) {
$errors[] = $this->lng['error']['dns_content_invalid'];
} else {
- // check that CAA content is enclosed in " "
- $content = \Froxlor\Dns\Dns::encloseTXTContent($matches[0]);
+ $content = $matches[0];
}
} elseif ($type == 'CNAME' || $type == 'DNAME') {
// check for trailing dot
@@ -171,8 +170,7 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
// append trailing dot (again)
$content .= '.';
} elseif ($type == 'LOC' && ! empty($content)) {
- // check that LOC content is enclosed in " "
- $content = \Froxlor\Dns\Dns::encloseTXTContent($content);
+ $content = $content;
} elseif ($type == 'MX') {
if ($prio === null || $prio < 0) {
$errors[] = $this->lng['error']['dns_mx_prioempty'];
@@ -208,8 +206,7 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
// append trailing dot (again)
$content .= '.';
} elseif ($type == 'RP' && ! empty($content)) {
- // check that RP content is enclosed in " "
- $content = \Froxlor\Dns\Dns::encloseTXTContent($content);
+ $content = $content;
} elseif ($type == 'SRV') {
if ($prio === null || $prio < 0) {
$errors[] = $this->lng['error']['dns_srv_prioempty'];
@@ -246,8 +243,7 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$content .= '.';
}
} elseif ($type == 'SSHFP' && ! empty($content)) {
- // check that SSHFP content is enclosed in " "
- $content = \Froxlor\Dns\Dns::encloseTXTContent($content);
+ $content = $content;
} elseif ($type == 'TXT' && ! empty($content)) {
// check that TXT content is enclosed in " "
$content = \Froxlor\Dns\Dns::encloseTXTContent($content);
diff --git a/lib/Froxlor/Dns/Dns.php b/lib/Froxlor/Dns/Dns.php
index bd0b4a78..2bf9c371 100644
--- a/lib/Froxlor/Dns/Dns.php
+++ b/lib/Froxlor/Dns/Dns.php
@@ -302,10 +302,10 @@ class Dns
}
foreach ($caa_entries as $entry) {
- $zonerecords[] = new DnsEntry('@', 'CAA', self::encloseTXTContent($entry));
+ $zonerecords[] = new DnsEntry('@', 'CAA', $entry);
// additional required records by subdomain setting
if ($domain['wwwserveralias'] == '1') {
- $zonerecords[] = new DnsEntry('www', 'CAA', self::encloseTXTContent($entry));
+ $zonerecords[] = new DnsEntry('www', 'CAA', $entry);
}
}
}
diff --git a/lib/userdata.inc.php.bak b/lib/userdata.inc.php.bak
new file mode 100644
index 00000000..4f1b32db
--- /dev/null
+++ b/lib/userdata.inc.php.bak
@@ -0,0 +1,10 @@
+
Date: Mon, 29 Jul 2019 14:30:39 +0200
Subject: [PATCH 065/159] Simplify unit tests for CAA entry validation
---
tests/DomainZones/DomainZonesTest.php | 88 ++++++++++++++++-----------
1 file changed, 53 insertions(+), 35 deletions(-)
diff --git a/tests/DomainZones/DomainZonesTest.php b/tests/DomainZones/DomainZonesTest.php
index 42a3b493..e082fd22 100644
--- a/tests/DomainZones/DomainZonesTest.php
+++ b/tests/DomainZones/DomainZonesTest.php
@@ -281,18 +281,19 @@ class DomainZonesTest extends TestCase
{
global $admin_userdata;
+ $content = '0 issue "letsencrypt.org"';
$data = [
'domainname' => 'test2.local',
'record' => '@',
'type' => 'CAA',
- 'content' => '0 issue "letsencrypt.org"'
+ 'content' => $content,
];
$json_result = DomainZones::getLocal($admin_userdata, $data)->add();
$result = json_decode($json_result, true)['data'];
$this->assertTrue(count($result) > 1);
$found = false;
foreach ($result as $entry) {
- if (substr($entry, strlen('0 issue "letsencrypt.org"') * - 1) == '0 issue "letsencrypt.org"') {
+ if (substr($entry, -strlen($content)) == $content) {
$found = true;
break;
}
@@ -305,59 +306,62 @@ class DomainZonesTest extends TestCase
{
global $admin_userdata;
+ $content = '0 issue "letsencrypt.org; account=230123"';
$data = [
'domainname' => 'test2.local',
'record' => '@',
'type' => 'CAA',
- 'content' => '0 issue "letsencrypt.org; account=230123"'
+ 'content' => $content,
];
$json_result = DomainZones::getLocal($admin_userdata, $data)->add();
$result = json_decode($json_result, true)['data'];
$this->assertTrue(count($result) > 1);
$found = false;
foreach ($result as $entry) {
- if (substr($entry, strlen('0 issue "letsencrypt.org; account=230123"') * - 1) == '0 issue "letsencrypt.org; account=230123"') {
+ if (substr($entry, strlen($content) * - 1) == $content) {
$found = true;
break;
}
}
$this->assertTrue($found);
- $this->assertEquals('@ 18000 IN CAA 0 issue "letsencrypt.org; account=230123"', $entry);
+ $this->assertEquals('@ 18000 IN CAA '.$content, $entry);
}
public function testAdminDomainZonesAddCAAIssueWithTwoParameters()
{
global $admin_userdata;
+ $content = '0 issue "letsencrypt.org; account=230123 policy=ev"';
$data = [
'domainname' => 'test2.local',
'record' => '@',
'type' => 'CAA',
- 'content' => '0 issue "letsencrypt.org; account=230123 policy=ev"'
+ 'content' => $content,
];
$json_result = DomainZones::getLocal($admin_userdata, $data)->add();
$result = json_decode($json_result, true)['data'];
$this->assertTrue(count($result) > 1);
$found = false;
foreach ($result as $entry) {
- if (substr($entry, strlen('0 issue "letsencrypt.org; account=230123 policy=ev"') * - 1) == '0 issue "letsencrypt.org; account=230123 policy=ev"') {
+ if (substr($entry, strlen($content) * - 1) == $content) {
$found = true;
break;
}
}
$this->assertTrue($found);
- $this->assertEquals('@ 18000 IN CAA 0 issue "letsencrypt.org; account=230123 policy=ev"', $entry);
+ $this->assertEquals('@ 18000 IN CAA '.$content, $entry);
}
public function testAdminDomainZonesAddCAAInvalidIssueValue()
{
global $admin_userdata;
+ $content = '0 issue ""letsencrypt.org"';
$data = [
'domainname' => 'test2.local',
'record' => '@',
'type' => 'CAA',
- 'content' => '0 issue ""letsencrypt.org"'
+ 'content' => $content,
];
$this->expectExceptionMessage("DNS content invalid");
DomainZones::getLocal($admin_userdata, $data)->add();
@@ -367,11 +371,12 @@ class DomainZonesTest extends TestCase
{
global $admin_userdata;
+ $content = '0 issue "no-valid-domain"';
$data = [
'domainname' => 'test2.local',
'record' => '@',
'type' => 'CAA',
- 'content' => '0 issue "no-valid-domain"'
+ 'content' => $content,
];
$this->expectExceptionMessage("DNS content invalid");
DomainZones::getLocal($admin_userdata, $data)->add();
@@ -381,11 +386,12 @@ class DomainZonesTest extends TestCase
{
global $admin_userdata;
+ $content = '0 issue "no-valid-domai.n"';
$data = [
'domainname' => 'test2.local',
'record' => '@',
'type' => 'CAA',
- 'content' => '0 issue "no-valid-domai.n"'
+ 'content' => $content,
];
$this->expectExceptionMessage("DNS content invalid");
DomainZones::getLocal($admin_userdata, $data)->add();
@@ -395,83 +401,87 @@ class DomainZonesTest extends TestCase
{
global $admin_userdata;
+ $content = '0 issue "letsencrypt.org"';
$data = [
'domainname' => 'test2.local',
'record' => '@',
'type' => 'CAA',
- 'content' => '0 issuewild "letsencrypt.org"'
+ 'content' => $content,
];
$json_result = DomainZones::getLocal($admin_userdata, $data)->add();
$result = json_decode($json_result, true)['data'];
$this->assertTrue(count($result) > 1);
$found = false;
foreach ($result as $entry) {
- if (substr($entry, strlen('0 issuewild "letsencrypt.org"') * - 1) == '0 issuewild "letsencrypt.org"') {
+ if (substr($entry, strlen($content) * - 1) == $content) {
$found = true;
break;
}
}
$this->assertTrue($found);
- $this->assertEquals('@ 18000 IN CAA 0 issuewild "letsencrypt.org"', $entry);
+ $this->assertEquals('@ 18000 IN CAA '.$content, $entry);
}
public function testAdminDomainZonesAddCAAIssueWildWithParameters()
{
global $admin_userdata;
+ $content = '0 issuewild "letsencrypt.org; account=230123"';
$data = [
'domainname' => 'test2.local',
'record' => '@',
'type' => 'CAA',
- 'content' => '0 issuewild "letsencrypt.org; account=230123"'
+ 'content' => $content,
];
$json_result = DomainZones::getLocal($admin_userdata, $data)->add();
$result = json_decode($json_result, true)['data'];
$this->assertTrue(count($result) > 1);
$found = false;
foreach ($result as $entry) {
- if (substr($entry, strlen('0 issuewild "letsencrypt.org; account=230123"') * - 1) == '0 issuewild "letsencrypt.org; account=230123"') {
+ if (substr($entry, strlen($content) * - 1) == $content) {
$found = true;
break;
}
}
$this->assertTrue($found);
- $this->assertEquals('@ 18000 IN CAA 0 issuewild "letsencrypt.org; account=230123"', $entry);
+ $this->assertEquals('@ 18000 IN CAA '.$content, $entry);
}
public function testAdminDomainZonesAddCAAIssueWildWithTwoParameters()
{
global $admin_userdata;
+ $content = '0 issuewild "letsencrypt.org; account=230123 policy=ev"';
$data = [
'domainname' => 'test2.local',
'record' => '@',
'type' => 'CAA',
- 'content' => '0 issuewild "letsencrypt.org; account=230123 policy=ev"'
+ 'content' => $content,
];
$json_result = DomainZones::getLocal($admin_userdata, $data)->add();
$result = json_decode($json_result, true)['data'];
$this->assertTrue(count($result) > 1);
$found = false;
foreach ($result as $entry) {
- if (substr($entry, strlen('0 issuewild "letsencrypt.org; account=230123 policy=ev"') * - 1) == '0 issuewild "letsencrypt.org; account=230123 policy=ev"') {
+ if (substr($entry, strlen($content) * - 1) == $content) {
$found = true;
break;
}
}
$this->assertTrue($found);
- $this->assertEquals('@ 18000 IN CAA 0 issuewild "letsencrypt.org; account=230123 policy=ev"', $entry);
+ $this->assertEquals('@ 18000 IN CAA '.$content, $entry);
}
public function testAdminDomainZonesAddCAAInvalidIssueWildValue()
{
global $admin_userdata;
+ $content = '0 issuewild ""letsencrypt.org"';
$data = [
'domainname' => 'test2.local',
'record' => '@',
'type' => 'CAA',
- 'content' => '0 issuewild ""letsencrypt.org"'
+ 'content' => $content,
];
$this->expectExceptionMessage("DNS content invalid");
DomainZones::getLocal($admin_userdata, $data)->add();
@@ -481,11 +491,12 @@ class DomainZonesTest extends TestCase
{
global $admin_userdata;
+ $content = '0 issuewild "no-valid-domain"';
$data = [
'domainname' => 'test2.local',
'record' => '@',
'type' => 'CAA',
- 'content' => '0 issuewild "no-valid-domain"'
+ 'content' => $content,
];
$this->expectExceptionMessage("DNS content invalid");
DomainZones::getLocal($admin_userdata, $data)->add();
@@ -495,11 +506,12 @@ class DomainZonesTest extends TestCase
{
global $admin_userdata;
+ $content = '0 issuewild "no-valid-domai.n"';
$data = [
'domainname' => 'test2.local',
'record' => '@',
'type' => 'CAA',
- 'content' => '0 issuewild "no-valid-domai.n"'
+ 'content' => $content,
];
$this->expectExceptionMessage("DNS content invalid");
DomainZones::getLocal($admin_userdata, $data)->add();
@@ -509,35 +521,37 @@ class DomainZonesTest extends TestCase
{
global $admin_userdata;
+ $content = '0 iodef "mailto:security@example.com"';
$data = [
'domainname' => 'test2.local',
'record' => '@',
'type' => 'CAA',
- 'content' => '0 iodef "mailto:security@example.com"'
+ 'content' => $content,
];
$json_result = DomainZones::getLocal($admin_userdata, $data)->add();
$result = json_decode($json_result, true)['data'];
$this->assertTrue(count($result) > 1);
$found = false;
foreach ($result as $entry) {
- if (substr($entry, strlen('0 iodef "mailto:security@example.com"') * - 1) == '0 iodef "mailto:security@example.com"') {
+ if (substr($entry, strlen($content) * - 1) == $content) {
$found = true;
break;
}
}
$this->assertTrue($found);
- $this->assertEquals('@ 18000 IN CAA 0 iodef "mailto:security@example.com"', $entry);
+ $this->assertEquals('@ 18000 IN CAA '.$content, $entry);
}
public function testAdminDomainZonesAddCAAIodefMailInvalid()
{
global $admin_userdata;
+ $content = '0 iodef "mailtosecurity@example.com"';
$data = [
'domainname' => 'test2.local',
'record' => '@',
'type' => 'CAA',
- 'content' => '0 iodef "mailtosecurity@example.com"'
+ 'content' => $content,
];
$this->expectExceptionMessage("DNS content invalid");
DomainZones::getLocal($admin_userdata, $data)->add();
@@ -547,35 +561,37 @@ class DomainZonesTest extends TestCase
{
global $admin_userdata;
+ $content = '0 iodef "http://iodef.example.com/"';
$data = [
'domainname' => 'test2.local',
'record' => '@',
'type' => 'CAA',
- 'content' => '0 iodef "http://iodef.example.com/"'
+ 'content' => $content,
];
$json_result = DomainZones::getLocal($admin_userdata, $data)->add();
$result = json_decode($json_result, true)['data'];
$this->assertTrue(count($result) > 1);
$found = false;
foreach ($result as $entry) {
- if (substr($entry, strlen('0 iodef "http://iodef.example.com/"') * - 1) == '0 iodef "http://iodef.example.com/"') {
+ if (substr($entry, strlen($content) * - 1) == $content) {
$found = true;
break;
}
}
$this->assertTrue($found);
- $this->assertEquals('@ 18000 IN CAA 0 iodef "http://iodef.example.com/"', $entry);
+ $this->assertEquals('@ 18000 IN CAA '.$content, $entry);
}
public function testAdminDomainZonesAddCAAIodefHttpInvalid()
{
global $admin_userdata;
+ $content = '0 iodef "http:/iodef.example.com/"';
$data = [
'domainname' => 'test2.local',
'record' => '@',
'type' => 'CAA',
- 'content' => '0 iodef "http:/iodef.example.com/"'
+ 'content' => $content,
];
$this->expectExceptionMessage("DNS content invalid");
DomainZones::getLocal($admin_userdata, $data)->add();
@@ -585,35 +601,37 @@ class DomainZonesTest extends TestCase
{
global $admin_userdata;
+ $content = '0 iodef "https://iodef.example.com/"';
$data = [
'domainname' => 'test2.local',
'record' => '@',
'type' => 'CAA',
- 'content' => '0 iodef "https://iodef.example.com/"'
+ 'content' => $content,
];
$json_result = DomainZones::getLocal($admin_userdata, $data)->add();
$result = json_decode($json_result, true)['data'];
$this->assertTrue(count($result) > 1);
$found = false;
foreach ($result as $entry) {
- if (substr($entry, strlen('0 iodef "https://iodef.example.com/"') * - 1) == '0 iodef "https://iodef.example.com/"') {
+ if (substr($entry, strlen($content) * - 1) == $content) {
$found = true;
break;
}
}
$this->assertTrue($found);
- $this->assertEquals('@ 18000 IN CAA 0 iodef "https://iodef.example.com/"', $entry);
+ $this->assertEquals('@ 18000 IN CAA '.$content, $entry);
}
public function testAdminDomainZonesAddCAAIodefHttpsInvalid()
{
global $admin_userdata;
+ $content = '0 iodef "https:/iodef.example.com/"';
$data = [
'domainname' => 'test2.local',
'record' => '@',
'type' => 'CAA',
- 'content' => '0 iodef "https:/iodef.example.com/"'
+ 'content' => $content,
];
$this->expectExceptionMessage("DNS content invalid");
DomainZones::getLocal($admin_userdata, $data)->add();
From 84d80d695a6018fdf050640038ca6f63f81b00e9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Kolly?=
Date: Mon, 29 Jul 2019 15:02:13 +0200
Subject: [PATCH 066/159] Add Url and Domain validation for CAA records using
native Froxlor function
---
lib/Froxlor/Api/Commands/DomainZones.php | 4 ++++
tests/DomainZones/DomainZonesTest.php | 2 +-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/lib/Froxlor/Api/Commands/DomainZones.php b/lib/Froxlor/Api/Commands/DomainZones.php
index 88b4eb80..276dc571 100644
--- a/lib/Froxlor/Api/Commands/DomainZones.php
+++ b/lib/Froxlor/Api/Commands/DomainZones.php
@@ -144,6 +144,10 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
if (empty($matches)) {
$errors[] = $this->lng['error']['dns_content_invalid'];
+ } elseif (($matches['type'] == 'issue' || $matches['type'] == 'issuewild') && !\Froxlor\Validate\Validate::validateDomain($matches['domain'])) {
+ $errors[] = $this->lng['error']['dns_content_invalid'];
+ } elseif ($matches['type'] == 'iodef' && !\Froxlor\Validate\Validate::validateUrl($matches['url'])) {
+ $errors[] = $this->lng['error']['dns_content_invalid'];
} else {
$content = $matches[0];
}
diff --git a/tests/DomainZones/DomainZonesTest.php b/tests/DomainZones/DomainZonesTest.php
index e082fd22..c0bd3143 100644
--- a/tests/DomainZones/DomainZonesTest.php
+++ b/tests/DomainZones/DomainZonesTest.php
@@ -401,7 +401,7 @@ class DomainZonesTest extends TestCase
{
global $admin_userdata;
- $content = '0 issue "letsencrypt.org"';
+ $content = '0 issuewild "letsencrypt.org"';
$data = [
'domainname' => 'test2.local',
'record' => '@',
From 4ef78df27f52b01f87210f19cd4b9006445bf623 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Kolly?=
Date: Sun, 28 Jul 2019 23:45:05 +0200
Subject: [PATCH 067/159] Update Travis CI
---
.travis.yml | 56 ++++++++++++++++++++++++-------------
tests/Mysqls/MysqlsTest.php | 2 +-
tests/bootstrap.php | 6 ++--
3 files changed, 40 insertions(+), 24 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 827ec1af..597577b6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,8 +1,9 @@
language: php
-dist: trusty
-
+dist: bionic
+services:
+ - docker
php:
- - "7.3"
+ - 7.3
branches:
only:
@@ -11,34 +12,49 @@ branches:
matrix:
include:
+# - php: 7.3
+# env: "DOCKER_MYSQL_TYPE=mysql DOCKER_MYSQL_VERSION=5.6"
+# - php: 7.3
+# env: "DOCKER_MYSQL_TYPE=mysql DOCKER_MYSQL_VERSION=5.7"
+# - php: 7.3
+# env: "DOCKER_MYSQL_TYPE=mysql DOCKER_MYSQL_VERSION=8.0"
+# - php: 7.3
+# env: "DOCKER_MYSQL_TYPE=mariadb DOCKER_MYSQL_VERSION=10.3"
- php: 7.3
- env: deps=highest
-
-mysql:
- database: froxlor010
- username: root
- encoding: utf8
+ env: "DOCKER_MYSQL_TYPE=mariadb DOCKER_MYSQL_VERSION=10.4"
addons:
apt:
update: true
-service:
- - mysql
+before_install:
+ - export MYSQL_DATABASE=froxlor010
+ - docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=fr0xl0r.TravisCI -e MYSQL_DATABASE=$MYSQL_DATABASE -p 3306:3306 $DOCKER_MYSQL_TYPE:$DOCKER_MYSQL_VERSION
+ - sudo apt-get install -y ant
+ - >
+ export tries=0;
+ export max_tries=20;
+ while [[ true ]]; do
+ tries=$((tries + 1));
+ echo "waiting for database server to start up... [$tries]";
+ sleep 5;
+ # Now see that today's table is there, which would indicate that the cron job ran.
+ mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -s -e 'SHOW VARIABLES LIKE "%version%";'
+ look_exit=$?;
+ if [[ "$look_exit" = "0" ]]; then echo "Database server successfully started"; break; fi;
+ if [[ "$tries" -ge "$max_tries" ]]; then echo "Database server did not start in time"; exit 1; break; fi;
+ done;
-before_script:
- - mysql -e 'CREATE DATABASE IF NOT EXISTS froxlor010'
- - echo "USE mysql;\nUPDATE user SET password=PASSWORD('fr0xl0r.TravisCI') WHERE user='root';\nFLUSH PRIVILEGES;\n" | mysql -u root
- - mysql -u root -pfr0xl0r.TravisCI froxlor010 < install/froxlor.sql
- - mysql -u root -pfr0xl0r.TravisCI -e "CREATE USER 'froxlor010'@'localhost' IDENTIFIED BY 'fr0xl0r.TravisCI';"
- - mysql -u root -pfr0xl0r.TravisCI -e "GRANT ALL ON froxlor010.* TO 'froxlor010'@'localhost';"
-# - phpenv config-rm xdebug.ini
+install:
+ - mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "CREATE DATABASE IF NOT EXISTS froxlor010"
+ - mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "GRANT ALL ON froxlor010.* TO 'froxlor010'@'%' IDENTIFIED BY 'fr0xl0r.TravisCI';"
+ - mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI froxlor010 < install/froxlor.sql
script:
- - ant phpunit
+ - ant phpunit
after_success:
- - bash <(curl -s https://codecov.io/bash) -f "build/logs/clover.xml"
+ - bash <(curl -s https://codecov.io/bash) -f "build/logs/clover.xml"
notifications:
irc: "irc.freenode.org#froxlor"
diff --git a/tests/Mysqls/MysqlsTest.php b/tests/Mysqls/MysqlsTest.php
index b0bd8527..45947c68 100644
--- a/tests/Mysqls/MysqlsTest.php
+++ b/tests/Mysqls/MysqlsTest.php
@@ -39,7 +39,7 @@ class MysqlsTest extends TestCase
// test connection
try {
- $test_conn = new \PDO("mysql:host=localhost", 'test1sql1', $newPwd);
+ $test_conn = new \PDO("mysql:host=127.0.0.1", 'test1sql1', $newPwd);
unset($test_conn);
} catch (PDOException $e) {
$this->fail($e->getMessage());
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index 5b2f1210..da941459 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -19,11 +19,11 @@ if (@php_sapi_name() !== 'cli') {
$userdata_content = "
Date: Mon, 29 Jul 2019 15:12:35 +0200
Subject: [PATCH 068/159] Update Travis CI to run database tests on MySQL 5.6,
5.7 and 8.0 and on MariaDB 10.3 and 10.4.
---
.travis.yml | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 597577b6..65557eb7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,14 +12,14 @@ branches:
matrix:
include:
-# - php: 7.3
-# env: "DOCKER_MYSQL_TYPE=mysql DOCKER_MYSQL_VERSION=5.6"
-# - php: 7.3
-# env: "DOCKER_MYSQL_TYPE=mysql DOCKER_MYSQL_VERSION=5.7"
-# - php: 7.3
-# env: "DOCKER_MYSQL_TYPE=mysql DOCKER_MYSQL_VERSION=8.0"
-# - php: 7.3
-# env: "DOCKER_MYSQL_TYPE=mariadb DOCKER_MYSQL_VERSION=10.3"
+ - php: 7.3
+ env: "DOCKER_MYSQL_TYPE=mysql DOCKER_MYSQL_VERSION=5.6"
+ - php: 7.3
+ env: "DOCKER_MYSQL_TYPE=mysql DOCKER_MYSQL_VERSION=5.7"
+ - php: 7.3
+ env: "DOCKER_MYSQL_TYPE=mysql DOCKER_MYSQL_VERSION=8.0"
+ - php: 7.3
+ env: "DOCKER_MYSQL_TYPE=mariadb DOCKER_MYSQL_VERSION=10.3"
- php: 7.3
env: "DOCKER_MYSQL_TYPE=mariadb DOCKER_MYSQL_VERSION=10.4"
From 61b12e3f25f8d635a991a989d8ddda48f5ea1b2b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Kolly?=
Date: Mon, 29 Jul 2019 15:47:45 +0200
Subject: [PATCH 069/159] Extrawurst.
---
.travis.yml | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 65557eb7..65d9b92f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -46,8 +46,9 @@ before_install:
done;
install:
- - mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "CREATE DATABASE IF NOT EXISTS froxlor010"
- - mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "GRANT ALL ON froxlor010.* TO 'froxlor010'@'%' IDENTIFIED BY 'fr0xl0r.TravisCI';"
+ - mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "CREATE DATABASE IF NOT EXISTS froxlor010;"
+ - mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "CREATE USER 'froxlor010'@'%' IDENTIFIED BY 'fr0xl0r.TravisCI';"
+ - mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "GRANT ALL ON froxlor010.* TO 'froxlor010'@'%';"
- mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI froxlor010 < install/froxlor.sql
script:
From 24896583530728c0074c155d37ed908fba13f203 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Kolly?=
Date: Mon, 29 Jul 2019 16:03:27 +0200
Subject: [PATCH 070/159] Extrawurst 2.0.
---
.travis.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 65d9b92f..240af08f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,7 +17,7 @@ matrix:
- php: 7.3
env: "DOCKER_MYSQL_TYPE=mysql DOCKER_MYSQL_VERSION=5.7"
- php: 7.3
- env: "DOCKER_MYSQL_TYPE=mysql DOCKER_MYSQL_VERSION=8.0"
+ env: "DOCKER_MYSQL_TYPE=mysql DOCKER_MYSQL_VERSION=8.0 STARTCMD='mysqld --default-authentication-plugin=mysql_native_password'"
- php: 7.3
env: "DOCKER_MYSQL_TYPE=mariadb DOCKER_MYSQL_VERSION=10.3"
- php: 7.3
@@ -29,7 +29,7 @@ addons:
before_install:
- export MYSQL_DATABASE=froxlor010
- - docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=fr0xl0r.TravisCI -e MYSQL_DATABASE=$MYSQL_DATABASE -p 3306:3306 $DOCKER_MYSQL_TYPE:$DOCKER_MYSQL_VERSION
+ - docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=fr0xl0r.TravisCI -e MYSQL_DATABASE=$MYSQL_DATABASE -p 3306:3306 $DOCKER_MYSQL_TYPE:$DOCKER_MYSQL_VERSION $STARTCMD
- sudo apt-get install -y ant
- >
export tries=0;
From dd488106afd334734823824e0429b2d0b9f6ee81 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Kolly?=
Date: Mon, 29 Jul 2019 16:09:11 +0200
Subject: [PATCH 071/159] Remove lib/userdata.inc.php.bak
---
.gitignore | 1 +
lib/userdata.inc.php.bak | 10 ----------
2 files changed, 1 insertion(+), 10 deletions(-)
delete mode 100644 lib/userdata.inc.php.bak
diff --git a/.gitignore b/.gitignore
index 8c981d1d..3d547882 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
install/update.log
templates/*
lib/userdata.inc.php
+lib/userdata.inc.php.bak
logs/*
!logs/index.html
.buildpath
diff --git a/lib/userdata.inc.php.bak b/lib/userdata.inc.php.bak
deleted file mode 100644
index 4f1b32db..00000000
--- a/lib/userdata.inc.php.bak
+++ /dev/null
@@ -1,10 +0,0 @@
-
Date: Mon, 29 Jul 2019 16:29:39 +0200
Subject: [PATCH 072/159] Tell ant to fail the build when a php unit test fails
---
build.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/build.xml b/build.xml
index 150eebdc..e489f847 100644
--- a/build.xml
+++ b/build.xml
@@ -241,7 +241,7 @@
-
From 70ac914a86c9c31911c218155d271cea2bf06acc Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 30 Jul 2019 07:34:42 +0200
Subject: [PATCH 073/159] fix drop database on mysql-5.6 as there is no 'if
exists' for 'drop user' prior to mysql-5.7
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Database/Manager/DbManagerMySQL.php | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/lib/Froxlor/Database/Manager/DbManagerMySQL.php b/lib/Froxlor/Database/Manager/DbManagerMySQL.php
index 693e229b..5c9dd8c8 100644
--- a/lib/Froxlor/Database/Manager/DbManagerMySQL.php
+++ b/lib/Froxlor/Database/Manager/DbManagerMySQL.php
@@ -146,7 +146,11 @@ class DbManagerMySQL
));
// as of MySQL 5.0.2 this also revokes privileges. (requires MySQL 4.1.2+)
- $drop_stmt = Database::prepare("DROP USER IF EXISTS :dbname@:host");
+ if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.0', '<')) {
+ $drop_stmt = Database::prepare("DROP USER IF EXISTS :dbname@:host");
+ } else {
+ $drop_stmt = Database::prepare("DROP USER :dbname@:host");
+ }
while ($host = $host_res_stmt->fetch(\PDO::FETCH_ASSOC)) {
Database::pexecute($drop_stmt, array(
'dbname' => $dbname,
@@ -154,6 +158,7 @@ class DbManagerMySQL
), false);
}
+
$drop_stmt = Database::prepare("DROP DATABASE IF EXISTS `" . $dbname . "`");
Database::pexecute($drop_stmt);
}
@@ -172,7 +177,11 @@ class DbManagerMySQL
Database::pexecute($stmt);
}
// as of MySQL 5.0.2 this also revokes privileges. (requires MySQL 4.1.2+)
- $stmt = Database::prepare("DROP USER :username@:host");
+ if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.0', '<')) {
+ $stmt = Database::prepare("DROP USER IF EXISTS :username@:host");
+ } else {
+ $stmt = Database::prepare("DROP USER :username@:host");
+ }
Database::pexecute($stmt, array(
"username" => $username,
"host" => $host
From 2aec6a10ed6383eda4467d5bbc637fc01b9c7efb Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 30 Jul 2019 08:31:03 +0200
Subject: [PATCH 074/159] argh, mixed up the If statement for mysql-version
check
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Database/Manager/DbManagerMySQL.php | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lib/Froxlor/Database/Manager/DbManagerMySQL.php b/lib/Froxlor/Database/Manager/DbManagerMySQL.php
index 5c9dd8c8..c130ffcc 100644
--- a/lib/Froxlor/Database/Manager/DbManagerMySQL.php
+++ b/lib/Froxlor/Database/Manager/DbManagerMySQL.php
@@ -147,9 +147,9 @@ class DbManagerMySQL
// as of MySQL 5.0.2 this also revokes privileges. (requires MySQL 4.1.2+)
if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.0', '<')) {
- $drop_stmt = Database::prepare("DROP USER IF EXISTS :dbname@:host");
- } else {
$drop_stmt = Database::prepare("DROP USER :dbname@:host");
+ } else {
+ $drop_stmt = Database::prepare("DROP USER IF EXISTS :dbname@:host");
}
while ($host = $host_res_stmt->fetch(\PDO::FETCH_ASSOC)) {
Database::pexecute($drop_stmt, array(
@@ -178,9 +178,9 @@ class DbManagerMySQL
}
// as of MySQL 5.0.2 this also revokes privileges. (requires MySQL 4.1.2+)
if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.0', '<')) {
- $stmt = Database::prepare("DROP USER IF EXISTS :username@:host");
- } else {
$stmt = Database::prepare("DROP USER :username@:host");
+ } else {
+ $stmt = Database::prepare("DROP USER IF EXISTS :username@:host");
}
Database::pexecute($stmt, array(
"username" => $username,
From a98ae562b2153ca152e1c97d58aed61ad83fe85e Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 30 Jul 2019 08:48:44 +0200
Subject: [PATCH 075/159] change mysql-username-test so it generates a
loginname that fails depending on the mysql/mariadb version
Signed-off-by: Michael Kaufmann
---
tests/Customers/CustomersTest.php | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tests/Customers/CustomersTest.php b/tests/Customers/CustomersTest.php
index 4de3fc0d..4f30d31a 100644
--- a/tests/Customers/CustomersTest.php
+++ b/tests/Customers/CustomersTest.php
@@ -543,8 +543,9 @@ class CustomersTest extends TestCase
{
global $admin_userdata;
+ $loginname = str_repeat("x", \Froxlor\Database\Database::getSqlUsernameLength() + 1);
$data = [
- 'new_loginname' => 'useruseruseruseruseruserX',
+ 'new_loginname' => $loginname,
'email' => 'team@froxlor.org',
'firstname' => 'Test2',
'name' => 'Testman2',
From 90e7f7af0c7b8e2064c4a072b96c98239ad6d37c Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 30 Jul 2019 10:05:26 +0200
Subject: [PATCH 076/159] correct language-array and minor formatting in
serversettings.caa_entry_custom
Signed-off-by: Michael Kaufmann
---
lng/english.lng.php | 4 ++--
lng/german.lng.php | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/lng/english.lng.php b/lng/english.lng.php
index aad8a566..49bb6b51 100644
--- a/lng/english.lng.php
+++ b/lng/english.lng.php
@@ -1851,8 +1851,8 @@ $lng['domains']['ssl_redirect_temporarilydisabled'] = " The SSL redirect is t
// Added for CAA record support
$lng['serversettings']['caa_entry']['title'] = 'Generate CAA DNS records';
$lng['serversettings']['caa_entry']['description'] = 'Automatically generates CAA records for SSL-enabled domains that are using Let\'s Encrypt';
-$lng['serversettings']['caa_custom']['title'] = 'Additional CAA DNS records';
-$lng['serversettings']['caa_custom']['description'] = 'DNS Certification Authority Authorization (CAA) is an Internet security policy mechanism which allows domain name holders to indicate to certificate authorities whether they are authorized to issue digital certificates for a particular domain name. It does this by means of a new "CAA" Domain Name System (DNS) resource record. The content of this field will be included into the DNS zone directly (each line results in a CAA record). If Let\'s Encrypt is enabled for this domain, this entry will always be added automatically and does not need to be added manually:0 issue "letsencrypt.org" (If domain is a wildcard domain, issuewild will be used instead). To enable Incident Reporting, you can add an iodef record. An example for sending such report to me@example.com would be:0 iodef "mailto:me@example.com"Attention: The code won\'t be checked for any errors. If it contains errors, your CAA records might not work!';
+$lng['serversettings']['caa_entry_custom']['title'] = 'Additional CAA DNS records';
+$lng['serversettings']['caa_entry_custom']['description'] = 'DNS Certification Authority Authorization (CAA) is an Internet security policy mechanism which allows domain name holders to indicate to certificate authorities whether they are authorized to issue digital certificates for a particular domain name. It does this by means of a new "CAA" Domain Name System (DNS) resource record. The content of this field will be included into the DNS zone directly (each line results in a CAA record). If Let\'s Encrypt is enabled for this domain, this entry will always be added automatically and does not need to be added manually:0 issue "letsencrypt.org" (If domain is a wildcard domain, issuewild will be used instead). To enable Incident Reporting, you can add an iodef record. An example for sending such report to me@example.com would be:0 iodef "mailto:me@example.com"Attention: The code won\'t be checked for any errors. If it contains errors, your CAA records might not work!';
// Autoupdate
$lng['admin']['autoupdate'] = 'Auto-Update';
diff --git a/lng/german.lng.php b/lng/german.lng.php
index 9c335afe..f76758cc 100644
--- a/lng/german.lng.php
+++ b/lng/german.lng.php
@@ -1503,8 +1503,8 @@ $lng['domains']['ssl_redirect_temporarilydisabled'] = " Die SSL-Umleitung ist
// Added for CAA record support
$lng['serversettings']['caa_entry']['title'] = 'CAA DNS Einträge generieren';
$lng['serversettings']['caa_entry']['description'] = 'Generiert CAA Einträge automatisch für alle Domains mit aktiviertem SSL und Let\'s Encrypt';
-$lng['serversettings']['caa_custom']['title'] = 'Zusätzliche CAA DNS Einträge';
-$lng['serversettings']['caa_custom']['description'] = 'DNS Certification Authority Authorization (CAA) verwendet das Domain Name System, um dem Besitzer einer Domain die Möglichkeit zu bieten, gewisse Zertifizierungsstellen (CAs) dazu zu berechtigen, ein Zertifikat für die betroffene Domain auszustellen. CAA Records sollen verhindern, dass Zertifikate fälschlicherweise für eine Domain ausgestellt werden. Der Inhalt dieses Feldes wird direkt in die DNS Zone übernommen (eine Zeile pro CAA Record). Wenn Let\'s Encrypt für eine Domain aktiviert wurde und die obige Option aktiviert wurde, wird immer automatisch dieser Eintrag angefügt und muss nicht selber angegeben werden:0 issue "letsencrypt.org" (Wenn wildcard aktiviert ist, wird statdessen issuewild benutzt). Um Incident Reporting per Mail zu aktivieren, muss eine iodef Zeile angefügt werden. Ein Beispiel für einen Report an me@example.com wäre:0 iodef "mailto:me@example.com"ACHTUNG: Der Code wird nicht auf Fehler geprüft. Etwaige Fehler werden also auch übernommen. Die CAA finalen Einträge könnten daher falsch sein!';
+$lng['serversettings']['caa_entry_custom']['title'] = 'Zusätzliche CAA DNS Einträge';
+$lng['serversettings']['caa_entry_custom']['description'] = 'DNS Certification Authority Authorization (CAA) verwendet das Domain Name System, um dem Besitzer einer Domain die Möglichkeit zu bieten, gewisse Zertifizierungsstellen (CAs) dazu zu berechtigen, ein Zertifikat für die betroffene Domain auszustellen. CAA Records sollen verhindern, dass Zertifikate fälschlicherweise für eine Domain ausgestellt werden. Der Inhalt dieses Feldes wird direkt in die DNS Zone übernommen (eine Zeile pro CAA Record). Wenn Let\'s Encrypt für eine Domain aktiviert wurde und die obige Option aktiviert wurde, wird immer automatisch dieser Eintrag angefügt und muss nicht selber angegeben werden:0 issue "letsencrypt.org" (Wenn wildcard aktiviert ist, wird statdessen issuewild benutzt). Um Incident Reporting per Mail zu aktivieren, muss eine iodef Zeile angefügt werden. Ein Beispiel für einen Report an me@example.com wäre:0 iodef "mailto:me@example.com"ACHTUNG: Der Code wird nicht auf Fehler geprüft. Etwaige Fehler werden also auch übernommen. Die CAA finalen Einträge könnten daher falsch sein!';
// Autoupdate
$lng['admin']['autoupdate'] = 'Auto-Update';
From 7364dca53d3f3fdfd74eb13b8db131e493d01ada Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Wed, 7 Aug 2019 14:01:05 +0200
Subject: [PATCH 077/159] fix homedir of automatically added ftp-user for new
customers, thx Gamerboy59 for finding this
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 f888ad0f..11e0b014 100644
--- a/lib/Froxlor/Api/Commands/Customers.php
+++ b/lib/Froxlor/Api/Commands/Customers.php
@@ -565,7 +565,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
}
$this->apiCall('Ftps.add', array(
'customerid' => $customerid,
- 'path' => $documentroot,
+ 'path' => '/',
'ftp_password' => $password,
'ftp_description' => "Default",
'sendinfomail' => 0,
From 04898c6114248b86a8ad7520e6f2706eac3d6007 Mon Sep 17 00:00:00 2001
From: Timo Stramann <21283057+TimoStramann@users.noreply.github.com>
Date: Fri, 9 Aug 2019 09:40:55 +0200
Subject: [PATCH 078/159] Updating fastcgi_param
Use $request_filename instead of $document_root$fastcgi_script_name as described in: https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#use-request-filename-for-script-filename
---
lib/Froxlor/Cron/Http/Nginx.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/Froxlor/Cron/Http/Nginx.php b/lib/Froxlor/Cron/Http/Nginx.php
index 1845f215..c34cff9a 100644
--- a/lib/Froxlor/Cron/Http/Nginx.php
+++ b/lib/Froxlor/Cron/Http/Nginx.php
@@ -279,7 +279,7 @@ class Nginx extends HttpConfigBase
$this->nginx_data[$vhost_filename] .= "\tlocation ~ \.php {\n";
$this->nginx_data[$vhost_filename] .= "\t\tfastcgi_split_path_info ^(.+\.php)(/.+)\$;\n";
$this->nginx_data[$vhost_filename] .= "\t\tinclude " . Settings::Get('nginx.fastcgiparams') . ";\n";
- $this->nginx_data[$vhost_filename] .= "\t\tfastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;\n";
+ $this->nginx_data[$vhost_filename] .= "\t\tfastcgi_param SCRIPT_FILENAME \$request_filename;\n";
$this->nginx_data[$vhost_filename] .= "\t\tfastcgi_param PATH_INFO \$fastcgi_path_info;\n";
$this->nginx_data[$vhost_filename] .= "\t\ttry_files \$fastcgi_script_name =404;\n";
@@ -935,7 +935,7 @@ class Nginx extends HttpConfigBase
$phpopts .= "\tlocation @php {\n";
$phpopts .= "\t\tfastcgi_split_path_info ^(.+\.php)(/.+)\$;\n";
$phpopts .= "\t\tinclude " . Settings::Get('nginx.fastcgiparams') . ";\n";
- $phpopts .= "\t\tfastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;\n";
+ $phpopts .= "\t\tfastcgi_param SCRIPT_FILENAME \$request_filename;\n";
$phpopts .= "\t\tfastcgi_param PATH_INFO \$fastcgi_path_info;\n";
$phpopts .= "\t\ttry_files \$fastcgi_script_name =404;\n";
$phpopts .= "\t\tfastcgi_pass " . Settings::Get('system.nginx_php_backend') . ";\n";
From 69d7889f02dcd958daa0be24106d343b62240080 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Fri, 9 Aug 2019 17:55:39 +0200
Subject: [PATCH 079/159] do not require codecoverage to pass checks
Signed-off-by: Michael Kaufmann
---
.codecov.yml | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 .codecov.yml
diff --git a/.codecov.yml b/.codecov.yml
new file mode 100644
index 00000000..26cec6c2
--- /dev/null
+++ b/.codecov.yml
@@ -0,0 +1,4 @@
+codecov:
+ notify:
+ require_ci_to_pass: no
+
From 76c4486d269141830edff13f1c161d21b3898fea Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Sun, 11 Aug 2019 10:31:33 +0200
Subject: [PATCH 080/159] fix subcanemaildomain parameter for Domains.update();
allow exec() in froxlor default vhost php.ini or logfiles-viewer feature
Signed-off-by: Michael Kaufmann
---
install/froxlor.sql | 2 +-
lib/Froxlor/Api/Commands/Domains.php | 10 +++++-----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/install/froxlor.sql b/install/froxlor.sql
index 51ffe079..b09e50c3 100644
--- a/install/froxlor.sql
+++ b/install/froxlor.sql
@@ -873,7 +873,7 @@ CREATE TABLE `panel_phpconfigs` (
INSERT INTO `panel_phpconfigs` (`id`, `description`, `binary`, `file_extensions`, `mod_fcgid_starter`, `mod_fcgid_maxrequests`, `phpsettings`) VALUES
(1, 'Default Config', '/usr/bin/php-cgi', 'php', '-1', '-1', 'allow_call_time_pass_reference = Off\r\nallow_url_fopen = Off\r\nasp_tags = Off\r\ndisable_classes =\r\ndisable_functions = curl_exec,curl_multi_exec,exec,parse_ini_file,passthru,popen,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,shell_exec,show_source,system\r\ndisplay_errors = Off\r\ndisplay_startup_errors = Off\r\nenable_dl = Off\r\nerror_reporting = E_ALL & ~E_NOTICE\r\nexpose_php = Off\r\nfile_uploads = On\r\ncgi.force_redirect = 1\r\ngpc_order = "GPC"\r\nhtml_errors = Off\r\nignore_repeated_errors = Off\r\nignore_repeated_source = Off\r\ninclude_path = ".:{PEAR_DIR}"\r\nlog_errors = On\r\nlog_errors_max_len = 1024\r\nmagic_quotes_gpc = Off\r\nmagic_quotes_runtime = Off\r\nmagic_quotes_sybase = Off\r\nmax_execution_time = 30\r\nmax_input_time = 60\r\nmemory_limit = 128M\r\n{OPEN_BASEDIR_C}open_basedir = "{OPEN_BASEDIR}"\r\noutput_buffering = 4096\r\npost_max_size = 16M\r\nprecision = 14\r\nregister_argc_argv = Off\r\nregister_globals = Off\r\nreport_memleaks = On\r\nsendmail_path = "/usr/sbin/sendmail -t -i -f {CUSTOMER_EMAIL}"\r\nsession.auto_start = 0\r\nsession.bug_compat_42 = 0\r\nsession.bug_compat_warn = 1\r\nsession.cache_expire = 180\r\nsession.cache_limiter = nocache\r\nsession.cookie_domain =\r\nsession.cookie_lifetime = 0\r\nsession.cookie_path = /\r\nsession.entropy_file = /dev/urandom\r\nsession.entropy_length = 16\r\nsession.gc_divisor = 1000\r\nsession.gc_maxlifetime = 1440\r\nsession.gc_probability = 1\r\nsession.name = PHPSESSID\r\nsession.referer_check =\r\nsession.save_handler = files\r\nsession.save_path = "{TMP_DIR}"\r\nsession.serialize_handler = php\r\nsession.use_cookies = 1\r\nsession.use_trans_sid = 0\r\nshort_open_tag = On\r\nsuhosin.mail.protect = 1\r\nsuhosin.simulation = Off\r\ntrack_errors = Off\r\nupload_max_filesize = 32M\r\nupload_tmp_dir = "{TMP_DIR}"\r\nvariables_order = "GPCS"\r\n;mail.add_x_header = On\r\n;mail.log = "/var/log/phpmail.log"\r\nopcache.restrict_api = "{DOCUMENT_ROOT}"\r\n'),
-(2, 'Froxlor Vhost Config', '/usr/bin/php-cgi', 'php', '-1', '-1', 'allow_call_time_pass_reference = Off\r\nallow_url_fopen = On\r\nasp_tags = Off\r\ndisable_classes =\r\ndisable_functions = curl_multi_exec,exec,parse_ini_file,passthru,popen,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,shell_exec,show_source,system\r\ndisplay_errors = Off\r\ndisplay_startup_errors = Off\r\nenable_dl = Off\r\nerror_reporting = E_ALL & ~E_NOTICE\r\nexpose_php = Off\r\nfile_uploads = On\r\ncgi.force_redirect = 1\r\ngpc_order = "GPC"\r\nhtml_errors = Off\r\nignore_repeated_errors = Off\r\nignore_repeated_source = Off\r\ninclude_path = ".:{PEAR_DIR}"\r\nlog_errors = On\r\nlog_errors_max_len = 1024\r\nmagic_quotes_gpc = Off\r\nmagic_quotes_runtime = Off\r\nmagic_quotes_sybase = Off\r\nmax_execution_time = 60\r\nmax_input_time = 60\r\nmemory_limit = 128M\r\noutput_buffering = 4096\r\npost_max_size = 16M\r\nprecision = 14\r\nregister_argc_argv = Off\r\nregister_globals = Off\r\nreport_memleaks = On\r\nsendmail_path = "/usr/sbin/sendmail -t -i -f {CUSTOMER_EMAIL}"\r\nsession.auto_start = 0\r\nsession.bug_compat_42 = 0\r\nsession.bug_compat_warn = 1\r\nsession.cache_expire = 180\r\nsession.cache_limiter = nocache\r\nsession.cookie_domain =\r\nsession.cookie_lifetime = 0\r\nsession.cookie_path = /\r\nsession.entropy_file = /dev/urandom\r\nsession.entropy_length = 16\r\nsession.gc_divisor = 1000\r\nsession.gc_maxlifetime = 1440\r\nsession.gc_probability = 1\r\nsession.name = PHPSESSID\r\nsession.referer_check =\r\nsession.save_handler = files\r\nsession.save_path = "{TMP_DIR}"\r\nsession.serialize_handler = php\r\nsession.use_cookies = 1\r\nsession.use_trans_sid = 0\r\nshort_open_tag = On\r\nsuhosin.mail.protect = 1\r\nsuhosin.simulation = Off\r\ntrack_errors = Off\r\nupload_max_filesize = 32M\r\nupload_tmp_dir = "{TMP_DIR}"\r\nvariables_order = "GPCS"\r\n;mail.add_x_header = On\r\n;mail.log = "/var/log/phpmail.log"\r\nopcache.restrict_api = ""\r\n');
+(2, 'Froxlor Vhost Config', '/usr/bin/php-cgi', 'php', '-1', '-1', 'allow_call_time_pass_reference = Off\r\nallow_url_fopen = On\r\nasp_tags = Off\r\ndisable_classes =\r\ndisable_functions = curl_multi_exec,parse_ini_file,passthru,popen,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,shell_exec,show_source,system\r\ndisplay_errors = Off\r\ndisplay_startup_errors = Off\r\nenable_dl = Off\r\nerror_reporting = E_ALL & ~E_NOTICE\r\nexpose_php = Off\r\nfile_uploads = On\r\ncgi.force_redirect = 1\r\ngpc_order = "GPC"\r\nhtml_errors = Off\r\nignore_repeated_errors = Off\r\nignore_repeated_source = Off\r\ninclude_path = ".:{PEAR_DIR}"\r\nlog_errors = On\r\nlog_errors_max_len = 1024\r\nmagic_quotes_gpc = Off\r\nmagic_quotes_runtime = Off\r\nmagic_quotes_sybase = Off\r\nmax_execution_time = 60\r\nmax_input_time = 60\r\nmemory_limit = 128M\r\noutput_buffering = 4096\r\npost_max_size = 16M\r\nprecision = 14\r\nregister_argc_argv = Off\r\nregister_globals = Off\r\nreport_memleaks = On\r\nsendmail_path = "/usr/sbin/sendmail -t -i -f {CUSTOMER_EMAIL}"\r\nsession.auto_start = 0\r\nsession.bug_compat_42 = 0\r\nsession.bug_compat_warn = 1\r\nsession.cache_expire = 180\r\nsession.cache_limiter = nocache\r\nsession.cookie_domain =\r\nsession.cookie_lifetime = 0\r\nsession.cookie_path = /\r\nsession.entropy_file = /dev/urandom\r\nsession.entropy_length = 16\r\nsession.gc_divisor = 1000\r\nsession.gc_maxlifetime = 1440\r\nsession.gc_probability = 1\r\nsession.name = PHPSESSID\r\nsession.referer_check =\r\nsession.save_handler = files\r\nsession.save_path = "{TMP_DIR}"\r\nsession.serialize_handler = php\r\nsession.use_cookies = 1\r\nsession.use_trans_sid = 0\r\nshort_open_tag = On\r\nsuhosin.mail.protect = 1\r\nsuhosin.simulation = Off\r\ntrack_errors = Off\r\nupload_max_filesize = 32M\r\nupload_tmp_dir = "{TMP_DIR}"\r\nvariables_order = "GPCS"\r\n;mail.add_x_header = On\r\n;mail.log = "/var/log/phpmail.log"\r\nopcache.restrict_api = ""\r\n');
DROP TABLE IF EXISTS `cronjobs_run`;
diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php
index 550d7da3..414b638a 100644
--- a/lib/Froxlor/Api/Commands/Domains.php
+++ b/lib/Froxlor/Api/Commands/Domains.php
@@ -119,8 +119,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional, default is the calling admin's ID
* @param array $ipandport
* optional list of ip/ports to assign to domain, default is system-default-ips
- * @param bool $subcanemaildomain
- * optional, allow subdomains of this domain as email domains, default 0 (false)
+ * @param int $subcanemaildomain
+ * optional, allow subdomains of this domain as email domains, 1 = choosable (default no), 2 = choosable (default yes), 3 = always, default 0 (never)
* @param bool $isemaildomain
* optional, allow email usage with this domain, default 0 (false)
* @param bool $email_only
@@ -673,8 +673,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional, default is the calling admin's ID
* @param array $ipandport
* optional list of ip/ports to assign to domain, default is system-default-ips
- * @param bool $subcanemaildomain
- * optional, allow subdomains of this domain as email domains, default 0 (false)
+ * @param int $subcanemaildomain
+ * optional, allow subdomains of this domain as email domains, 1 = choosable (default no), 2 = choosable (default yes), 3 = always, default 0 (never)
* @param bool $isemaildomain
* optional, allow email usage with this domain, default 0 (false)
* @param bool $email_only
@@ -767,7 +767,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$customerid = intval($this->getParam('customerid', true, $result['customerid']));
$adminid = intval($this->getParam('adminid', true, $result['adminid']));
- $subcanemaildomain = $this->getBoolParam('subcanemaildomain', true, $result['subcanemaildomain']);
+ $subcanemaildomain = $this->getParam('subcanemaildomain', true, $result['subcanemaildomain']);
$isemaildomain = $this->getBoolParam('isemaildomain', true, $result['isemaildomain']);
$email_only = $this->getBoolParam('email_only', true, $result['email_only']);
$p_serveraliasoption = $this->getParam('selectserveralias', true, - 1);
From 7ba72269a4e0a0f073950332777ffccf3dfa5be2 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Sun, 11 Aug 2019 11:12:53 +0200
Subject: [PATCH 081/159] add dovecot stats service and use correct permissions
Signed-off-by: Michael Kaufmann
---
lib/configfiles/buster.xml | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/lib/configfiles/buster.xml b/lib/configfiles/buster.xml
index 092a5011..91b61db0 100644
--- a/lib/configfiles/buster.xml
+++ b/lib/configfiles/buster.xml
@@ -3413,6 +3413,17 @@ service dict {
#group =
}
}
+
+service stats {
+ unix_listener stats-reader {
+ group = vmail
+ mode = 0666
+ }
+ unix_listener stats-writer {
+ group = vmail
+ mode = 0666
+ }
+}
]]>
From bd6aba8875eac43b14b92f8517a6cc0bf3707f10 Mon Sep 17 00:00:00 2001
From: Timo Stramann <21283057+TimoStramann@users.noreply.github.com>
Date: Sat, 17 Aug 2019 13:04:18 +0200
Subject: [PATCH 082/159] Updating another fastcgi_param SCRIPT_FILENAME
Use $request_filename instead of $document_root$fastcgi_script_name as described in: https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#use-request-filename-for-script-filename
---
lib/Froxlor/Cron/Http/NginxFcgi.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/Froxlor/Cron/Http/NginxFcgi.php b/lib/Froxlor/Cron/Http/NginxFcgi.php
index 83da6cfe..8774f548 100644
--- a/lib/Froxlor/Cron/Http/NginxFcgi.php
+++ b/lib/Froxlor/Cron/Http/NginxFcgi.php
@@ -38,7 +38,7 @@ class NginxFcgi extends Nginx
$php_options_text .= "\t\t" . 'try_files $1 = 404;' . "\n\n";
$php_options_text .= "\t\t" . 'include ' . Settings::Get('nginx.fastcgiparams') . ";\n";
$php_options_text .= "\t\t" . 'fastcgi_split_path_info ^(.+\.php)(/.+)\$;' . "\n";
- $php_options_text .= "\t\t" . 'fastcgi_param SCRIPT_FILENAME $document_root$1;' . "\n";
+ $php_options_text .= "\t\t" . 'fastcgi_param SCRIPT_FILENAME $request_filename;' . "\n";
$php_options_text .= "\t\t" . 'fastcgi_param PATH_INFO $2;' . "\n";
if ($domain['ssl'] == '1' && $ssl_vhost) {
$php_options_text .= "\t\t" . 'fastcgi_param HTTPS on;' . "\n";
From 8e9ddd3d503d7035a9fa8472bc1a2e7625bc0a6f Mon Sep 17 00:00:00 2001
From: Timo Stramann <21283057+TimoStramann@users.noreply.github.com>
Date: Sun, 18 Aug 2019 16:07:59 +0200
Subject: [PATCH 083/159] Remove unnecessary slash for SSL redirect
Remove slash after hostname since requests directly to the hostname do not require a slash at the end and all other content goes to `$request_uri` which starts with shlash, hence no longer doubleslashes on hostname only queries.
---
lib/Froxlor/Cron/Http/Nginx.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/Froxlor/Cron/Http/Nginx.php b/lib/Froxlor/Cron/Http/Nginx.php
index c34cff9a..414eb11c 100644
--- a/lib/Froxlor/Cron/Http/Nginx.php
+++ b/lib/Froxlor/Cron/Http/Nginx.php
@@ -244,7 +244,7 @@ class Nginx extends HttpConfigBase
$is_redirect = false;
} else {
$_sslport = $this->checkAlternativeSslPort();
- $mypath = 'https://' . Settings::Get('system.hostname') . $_sslport . '/';
+ $mypath = 'https://' . Settings::Get('system.hostname') . $_sslport;
$this->nginx_data[$vhost_filename] .= "\t" . 'location / {' . "\n";
$this->nginx_data[$vhost_filename] .= "\t\t" . 'return 301 ' . $mypath . '$request_uri;' . "\n";
$this->nginx_data[$vhost_filename] .= "\t" . '}' . "\n";
From f5027695dd6c3e617dfbd9038592b40fd668b7be Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Thu, 22 Aug 2019 15:45:00 +0200
Subject: [PATCH 084/159] Create FUNDING.yml
---
.github/FUNDING.yml | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 .github/FUNDING.yml
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 00000000..21c83ab0
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,3 @@
+# These are supported funding model platforms
+
+custom: ['https://paypal.me/Froxlor']
From accd6e7416f0d5ad7934b484ae34e32a7686babc Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Thu, 22 Aug 2019 16:15:17 +0200
Subject: [PATCH 085/159] Update README.md
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index 6ae500ea..d9d5a83d 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,5 @@
[](https://travis-ci.com/Froxlor/Froxlor)
+[](https://gitter.im/Froxlor/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
# Froxlor
From 2d8b0181b310bb4b2a368fa9f2959b12d0bf5ec8 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Thu, 22 Aug 2019 16:20:42 +0200
Subject: [PATCH 086/159] add gitter notifications for travis-ci
Signed-off-by: Michael Kaufmann
---
.travis.yml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/.travis.yml b/.travis.yml
index 240af08f..4148f43a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -59,3 +59,9 @@ after_success:
notifications:
irc: "irc.freenode.org#froxlor"
+ webhooks:
+ urls:
+ - https://webhooks.gitter.im/e/bdf91d1c3f745e51f796
+ on_success: always
+ on_failure: always
+ on_start: never
From 9e2dcf51d7f148337d736da621d37f457c350dcf Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Mon, 9 Sep 2019 17:16:41 +0200
Subject: [PATCH 087/159] also remove let's encrypt certificate for
froxlor-hostname when updating to acme.sh; make installation more
mysql/mariadb compatible
Signed-off-by: Michael Kaufmann
---
install/lib/class.FroxlorInstall.php | 70 ++++++++++++-------
.../updates/froxlor/0.10/update_0.10.inc.php | 4 ++
2 files changed, 49 insertions(+), 25 deletions(-)
diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php
index ba101c35..7c61963c 100644
--- a/install/lib/class.FroxlorInstall.php
+++ b/install/lib/class.FroxlorInstall.php
@@ -104,7 +104,7 @@ class FroxlorInstall
// check if we have a valid installation already
$this->_checkUserdataFile();
// include the MySQL-Table-Definitions
- require $this->_basepath . '/lib/tables.inc.php';
+ require_once $this->_basepath . '/lib/tables.inc.php';
// include language
$this->_includeLanguageFile();
// show the action
@@ -643,21 +643,8 @@ class FroxlorInstall
$mysql_access_host_array[] = $this->_data['serverip'];
foreach ($mysql_access_host_array as $mysql_access_host) {
- $_db = str_replace('`', '', $this->_data['mysql_database']);
- $stmt = $db_root->prepare("
- GRANT ALL PRIVILEGES ON `" . $_db . "`.*
- TO :username@:host
- IDENTIFIED BY 'password'");
- $stmt->execute(array(
- "username" => $this->_data['mysql_unpriv_user'],
- "host" => $mysql_access_host
- ));
- $stmt = $db_root->prepare("SET PASSWORD FOR :username@:host = PASSWORD(:password)");
- $stmt->execute(array(
- "username" => $this->_data['mysql_unpriv_user'],
- "host" => $mysql_access_host,
- "password" => $this->_data['mysql_unpriv_pass']
- ));
+ $frox_db = str_replace('`', '', $this->_data['mysql_database']);
+ $this->_grantDbPrivilegesTo($db_root, $frox_db, $this->_data['mysql_unpriv_user'], $this->_data['mysql_unpriv_pass'], $mysql_access_host);
}
$db_root->query("FLUSH PRIVILEGES;");
@@ -667,6 +654,38 @@ class FroxlorInstall
return $content;
}
+ private function _grantDbPrivilegesTo(&$db_root, $database, $username, $password, $access_host)
+ {
+ // mysql8 compatibility
+ if (version_compare($db_root->getAttribute(\PDO::ATTR_SERVER_VERSION), '8.0.11', '>=')) {
+ // create user
+ $stmt = $db_root->prepare("
+ CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED BY :password
+ ");
+ $stmt->execute(array(
+ "password" => $password
+ ));
+ // grant privileges
+ $stmt = $db_root->prepare("
+ GRANT ALL ON `" . $database . "`.* TO :username@:host
+ ");
+ $stmt->execute(array(
+ "username" => $username,
+ "host" => $access_host
+ ));
+ } else {
+ // grant privileges
+ $stmt = $db_root->prepare("
+ GRANT ALL PRIVILEGES ON `" . $database . "`.* TO :username@:host IDENTIFIED BY :password
+ ");
+ $stmt->execute(array(
+ "username" => $username,
+ "host" => $access_host,
+ "password" => $password
+ ));
+ }
+ }
+
/**
* Check if an old database exists and back it up if necessary
*
@@ -1060,12 +1079,13 @@ class FroxlorInstall
*/
private function _sendHeaders()
{
- // no caching
- header("Cache-Control: no-store, no-cache, must-revalidate");
- header("Pragma: no-cache");
- header('Last-Modified: ' . gmdate('D, d M Y H:i:s \G\M\T', time()));
- header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time()));
-
+ if (@php_sapi_name() !== 'cli') {
+ // no caching
+ header("Cache-Control: no-store, no-cache, must-revalidate");
+ header("Pragma: no-cache");
+ header('Last-Modified: ' . gmdate('D, d M Y H:i:s \G\M\T', time()));
+ header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time()));
+ }
// ensure that default timezone is set
if (function_exists("date_default_timezone_set") && function_exists("date_default_timezone_get")) {
@date_default_timezone_set(@date_default_timezone_get());
@@ -1082,7 +1102,7 @@ class FroxlorInstall
if (file_exists($userdata)) {
// includes the usersettings (MySQL-Username/Passwort)
// to test if Froxlor is already installed
- require $this->_basepath . '/lib/userdata.inc.php';
+ require_once $this->_basepath . '/lib/userdata.inc.php';
if (isset($sql) && is_array($sql)) {
// use sparkle theme for the notice
@@ -1126,7 +1146,7 @@ class FroxlorInstall
$lngfile = $this->_basepath . '/install/lng/' . $standardlanguage . '.lng.php';
if (file_exists($lngfile)) {
// includes file /lng/$language.lng.php if it exists
- require $lngfile;
+ require_once $lngfile;
$this->_lng = $lng;
}
@@ -1135,7 +1155,7 @@ class FroxlorInstall
$lngfile = $this->_basepath . '/install/lng/' . $this->_activelng . '.lng.php';
if (file_exists($lngfile)) {
// includes file /lng/$language.lng.php if it exists
- require $lngfile;
+ require_once $lngfile;
$this->_lng = $lng;
}
}
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 bac449ea..f4f764ca 100644
--- a/install/updates/froxlor/0.10/update_0.10.inc.php
+++ b/install/updates/froxlor/0.10/update_0.10.inc.php
@@ -220,6 +220,10 @@ if (\Froxlor\Froxlor::isDatabaseVersion('201902120')) {
$domain_in = substr($domain_in, 0, - 1);
Database::query("DELETE FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` IN (" . $domain_in . ")");
}
+ // check for froxlor domain using let's encrypt
+ if (Settings::Get('system.le_froxlor_enabled') == 1) {
+ Database::query("DELETE FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = '0'");
+ }
lastStepStatus(0);
showUpdateStep("Inserting job to regenerate configfiles");
From 6ebb8dabc448a692c591c4286a5a39eae13c275b Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Thu, 12 Sep 2019 12:30:47 +0200
Subject: [PATCH 088/159] re-create certificate if SAN list or domain changes
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
index e0967ca0..32d7fae1 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
SELECT
domssl.`id`,
domssl.`domainid`,
- domssl.expirationdate,
+ domssl.`expirationdate`,
domssl.`ssl_cert_file`,
domssl.`ssl_key_file`,
domssl.`ssl_ca_file`,
@@ -221,9 +221,14 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
// Only renew let's encrypt certificate if no broken ssl_redirect is enabled
if ($certrow['ssl_redirect'] != 2) {
- if (! empty($certrow['ssl_cert_file'])) {
+ $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']);
}
@@ -252,7 +257,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
}
}
- self::runAcmeSh($certrow, $domains, $cert_mode, $cronlog, $changedetected);
+ 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");
}
@@ -270,7 +275,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
}
}
- private static function runAcmeSh($certrow = array(), $domains = array(), $cert_mode = 'issue', &$cronlog = null, &$changedetected = 0)
+ private static function runAcmeSh($certrow = array(), $domains = array(), $cert_mode = 'issue', &$cronlog = null, &$changedetected = 0, $force = false)
{
if (! empty($domains)) {
@@ -295,6 +300,9 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
if (Settings::Get('system.letsencryptca') == 'testing') {
$acmesh_cmd .= " --staging";
}
+ if ($force) {
+ $acmesh_cmd .= " --force";
+ }
$acme_result = \Froxlor\FileDir::safe_exec($acmesh_cmd);
From dc3f159c90375bd34cf2812a4ebf80ff24855686 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Sun, 15 Sep 2019 10:22:25 +0200
Subject: [PATCH 089/159] correctly trigger re-generation of let's encrypt
certificates
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Api/Commands/Domains.php | 10 ++++++----
lib/Froxlor/Api/Commands/SubDomains.php | 11 +++++++++--
lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 8 +++++---
3 files changed, 20 insertions(+), 9 deletions(-)
diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php
index 414b638a..88eb82ab 100644
--- a/lib/Froxlor/Api/Commands/Domains.php
+++ b/lib/Froxlor/Api/Commands/Domains.php
@@ -1450,14 +1450,15 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
}
}
}
- if ($result['aliasdomain'] != $aliasdomain) {
+ if ($result['aliasdomain'] != $aliasdomain && is_numeric($result['aliasdomain'])) {
// trigger when domain id for alias destination has changed: both for old and new destination
\Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger());
\Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger());
- } elseif ($result['wwwserveralias'] != $wwwserveralias || $result['letsencrypt'] != $letsencrypt) {
+ }
+ if ($result['wwwserveralias'] != $wwwserveralias || $result['letsencrypt'] != $letsencrypt) {
// or when wwwserveralias or letsencrypt was changed
\Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger());
- if ($aliasdomain === 0) {
+ if ((int) $aliasdomain === 0) {
// in case the wwwserveralias is set on a main domain, $aliasdomain is 0
// --> the call just above to triggerLetsEncryptCSRForAliasDestinationDomain
// is a noop...let's repeat it with the domain id of the main domain
@@ -1465,7 +1466,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
}
}
- $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] updated domain '" . $result['domain'] . "'");
+ $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);
}
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 59eb8298..e3f3db0a 100644
--- a/lib/Froxlor/Api/Commands/SubDomains.php
+++ b/lib/Froxlor/Api/Commands/SubDomains.php
@@ -623,13 +623,20 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
);
Database::pexecute($stmt, $params, true, true);
- if ($result['aliasdomain'] != $aliasdomain) {
+ if ($result['aliasdomain'] != $aliasdomain && is_numeric($result['aliasdomain'])) {
// trigger when domain id for alias destination has changed: both for old and new destination
\Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger());
\Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger());
- } elseif ($result['wwwserveralias'] != $wwwserveralias || $result['letsencrypt'] != $letsencrypt) {
+ }
+ if ($result['wwwserveralias'] != $wwwserveralias || $result['letsencrypt'] != $letsencrypt) {
// or when wwwserveralias or letsencrypt was changed
\Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger());
+ if ((int) $aliasdomain === 0) {
+ // in case the wwwserveralias is set on a main domain, $aliasdomain is 0
+ // --> the call just above to triggerLetsEncryptCSRForAliasDestinationDomain
+ // is a noop...let's repeat it with the domain id of the main domain
+ \Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($id, $this->logger());
+ }
}
// check whether LE has been disabled, so we remove the certificate
diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
index 32d7fae1..3c14caac 100644
--- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
+++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
@@ -192,10 +192,12 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
// 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, "Creating certificate for " . $certrow['domain']);
- } else {
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(
@@ -203,7 +205,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
'adminsession' => 0
));
- self::runAcmeSh($certrow, $domains, $cert_mode, $cronlog, $changedetected);
+ self::runAcmeSh($certrow, $domains, $cert_mode, $cronlog, $changedetected, $do_force);
}
}
From 1b968c885b8078b67035f6456340c924b8559c61 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Sun, 15 Sep 2019 10:28:19 +0200
Subject: [PATCH 090/159] remove old files from 0.9.x to avoid conflicts and
errors; change mod_proxy-usage and ACMEv2 default values to true
Signed-off-by: Michael Kaufmann
---
actions/admin/settings/131.ssl.php | 2 +-
actions/admin/settings/136.phpfpm.php | 2 +-
install/froxlor.sql | 6 +--
.../updates/froxlor/0.10/update_0.10.inc.php | 37 ++++++++++++++++++-
lib/Froxlor/Froxlor.php | 2 +-
5 files changed, 42 insertions(+), 7 deletions(-)
diff --git a/actions/admin/settings/131.ssl.php b/actions/admin/settings/131.ssl.php
index 6717e1b8..a9f3c091 100644
--- a/actions/admin/settings/131.ssl.php
+++ b/actions/admin/settings/131.ssl.php
@@ -128,7 +128,7 @@ return array(
'settinggroup' => 'system',
'varname' => 'leapiversion',
'type' => 'option',
- 'default' => '1',
+ 'default' => '2',
'option_mode' => 'one',
'option_options' => array(
'1' => 'ACME v1',
diff --git a/actions/admin/settings/136.phpfpm.php b/actions/admin/settings/136.phpfpm.php
index db1839ce..eca70ba4 100644
--- a/actions/admin/settings/136.phpfpm.php
+++ b/actions/admin/settings/136.phpfpm.php
@@ -99,7 +99,7 @@ return array(
'settinggroup' => 'phpfpm',
'varname' => 'use_mod_proxy',
'type' => 'bool',
- 'default' => false,
+ 'default' => true,
'visible' => \Froxlor\Settings::Get('system.apache24'),
'save_method' => 'storeSettingField'
),
diff --git a/install/froxlor.sql b/install/froxlor.sql
index b09e50c3..a000ed3e 100644
--- a/install/froxlor.sql
+++ b/install/froxlor.sql
@@ -405,7 +405,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES
('phpfpm', 'defaultini', '1'),
('phpfpm', 'vhost_defaultini', '2'),
('phpfpm', 'fastcgi_ipcdir', '/var/lib/apache2/fastcgi/'),
- ('phpfpm', 'use_mod_proxy', '0'),
+ ('phpfpm', 'use_mod_proxy', '1'),
('phpfpm', 'ini_flags', 'asp_tags
display_errors
display_startup_errors
@@ -615,7 +615,7 @@ opcache.interned_strings_buffer'),
('system', 'letsencryptkeysize', '4096'),
('system', 'letsencryptreuseold', 0),
('system', 'leenabled', '0'),
- ('system', 'leapiversion', '1'),
+ ('system', 'leapiversion', '2'),
('system', 'backupenabled', '0'),
('system', 'dnsenabled', '0'),
('system', 'dns_server', 'Bind'),
@@ -683,7 +683,7 @@ opcache.interned_strings_buffer'),
('panel', 'customer_hide_options', ''),
('panel', 'is_configured', '0'),
('panel', 'version', '0.10.0-rc2'),
- ('panel', 'db_version', '201907270');
+ ('panel', 'db_version', '201909150');
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 f4f764ca..78624fdd 100644
--- a/install/updates/froxlor/0.10/update_0.10.inc.php
+++ b/install/updates/froxlor/0.10/update_0.10.inc.php
@@ -276,4 +276,39 @@ if (\Froxlor\Froxlor::isDatabaseVersion('201904250')) {
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201907270');
-}
\ No newline at end of file
+}
+
+if (\Froxlor\Froxlor::isDatabaseVersion('201907270')) {
+
+ showUpdateStep("Cleaning up old files");
+ $to_clean = array(
+ "actions/admin/settings/000.version.php",
+ "actions/admin/settings/190.ticket.php",
+ "admin_tickets.php",
+ "customer_tickets.php",
+ "install/scripts/language-check.php",
+ "install/updates/froxlor/upgrade_syscp.inc.php",
+ "lib/classes",
+ "lib/configfiles/precise.xml",
+ "lib/cron_init.php",
+ "lib/cron_shutdown.php",
+ "lib/formfields/admin/tickets",
+ "lib/formfields/customer/tickets",
+ "lib/functions.php",
+ "lib/functions",
+ "lib/navigation/10.tickets.php",
+ "scripts/classes",
+ "scripts/jobs",
+ "templates/Sparkle/admin/tickets",
+ "templates/Sparkle/customer/tickets"
+ );
+ foreach ($to_clean as $filedir) {
+ $complete_filedir = \Froxlor\Froxlor::getInstallDir() . $filedir;
+ if (file_exsts($complete_filedir)) {
+ Froxlor\FileDir::safe_exec("rm -rf " . escapeshellarg($complete_filedir));
+ }
+ }
+ lastStepStatus(0);
+
+ \Froxlor\Froxlor::updateToDbVersion('201909150');
+}
diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php
index eff34ca5..f9a63b59 100644
--- a/lib/Froxlor/Froxlor.php
+++ b/lib/Froxlor/Froxlor.php
@@ -10,7 +10,7 @@ final class Froxlor
const VERSION = '0.10.0-rc2';
// Database version (YYYYMMDDC where C is a daily counter)
- const DBVERSION = '201907270';
+ const DBVERSION = '201909150';
// Distribution branding-tag (used for Debian etc.)
const BRANDING = '';
From 6ef2be8c1a8e7c46bd73c210d997409afaf1f60c Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Sun, 15 Sep 2019 13:42:32 +0200
Subject: [PATCH 091/159] fixed typo
Signed-off-by: Michael Kaufmann
---
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 78624fdd..435fc0b1 100644
--- a/install/updates/froxlor/0.10/update_0.10.inc.php
+++ b/install/updates/froxlor/0.10/update_0.10.inc.php
@@ -304,7 +304,7 @@ if (\Froxlor\Froxlor::isDatabaseVersion('201907270')) {
);
foreach ($to_clean as $filedir) {
$complete_filedir = \Froxlor\Froxlor::getInstallDir() . $filedir;
- if (file_exsts($complete_filedir)) {
+ if (file_exists($complete_filedir)) {
Froxlor\FileDir::safe_exec("rm -rf " . escapeshellarg($complete_filedir));
}
}
From 5a8ae0f75f580fd2370499613709036bd56cc357 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Sun, 15 Sep 2019 13:49:40 +0200
Subject: [PATCH 092/159] do not log multiple times due to pushing log-handlers
multiple times
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/FroxlorLogger.php | 32 +++++++++++++++++++++-----------
1 file changed, 21 insertions(+), 11 deletions(-)
diff --git a/lib/Froxlor/FroxlorLogger.php b/lib/Froxlor/FroxlorLogger.php
index 247c76f2..5db70013 100644
--- a/lib/Froxlor/FroxlorLogger.php
+++ b/lib/Froxlor/FroxlorLogger.php
@@ -40,6 +40,13 @@ class FroxlorLogger
*/
private static $userinfo = array();
+ /**
+ * whether the logger object has already been initialized
+ *
+ * @var bool
+ */
+ private static $is_initialized = false;
+
const USR_ACTION = '10';
const RES_ACTION = '20';
@@ -72,19 +79,22 @@ class FroxlorLogger
}
}
- foreach (self::$logtypes as $logger) {
+ if (self::$is_initialized == false) {
+ foreach (self::$logtypes as $logger) {
- switch ($logger) {
- case 'syslog':
- self::$ml->pushHandler(new SyslogHandler('froxlor', LOG_USER, Logger::DEBUG));
- break;
- case 'file':
- self::$ml->pushHandler(new StreamHandler(Settings::Get('logger.logfile'), Logger::DEBUG));
- break;
- case 'mysql':
- self::$ml->pushHandler(new MysqlHandler(Logger::DEBUG));
- break;
+ switch ($logger) {
+ case 'syslog':
+ self::$ml->pushHandler(new SyslogHandler('froxlor', LOG_USER, Logger::DEBUG));
+ break;
+ case 'file':
+ self::$ml->pushHandler(new StreamHandler(Settings::Get('logger.logfile'), Logger::DEBUG));
+ break;
+ case 'mysql':
+ self::$ml->pushHandler(new MysqlHandler(Logger::DEBUG));
+ break;
+ }
}
+ self::$is_initialized = true;
}
}
From aca22a9c94f36c07d199448eea6d17d2ef95c196 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Sun, 15 Sep 2019 15:40:13 +0200
Subject: [PATCH 093/159] only add lets encrypt certificate if cert is valid;
display acme.sh output if --debug is specified
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 44 +++++++++++---------
1 file changed, 25 insertions(+), 19 deletions(-)
diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
index 3c14caac..41974d8e 100644
--- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
+++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
@@ -307,6 +307,8 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
}
$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);
@@ -315,27 +317,31 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
$newcert = openssl_x509_parse($return['crt']);
- // 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']
+ 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'])
));
- }
- $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Updated Let's Encrypt certificate for " . $certrow['domain']);
- $changedetected = 1;
+ 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));
}
From 75f49e2ee2cfac759f52f769b05838813b974cb9 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Mon, 16 Sep 2019 12:31:02 +0200
Subject: [PATCH 094/159] added HostingPlans ApiCommand + unit-tests
Signed-off-by: Michael Kaufmann
---
admin_plans.php | 272 +++------------
lib/Froxlor/Api/Commands/HostingPlans.php | 389 +++++++++++++++++++++-
templates/Sparkle/assets/js/customers.js | 2 +-
tests/Customers/HostingPlansTest.php | 258 ++++++++++++++
4 files changed, 673 insertions(+), 248 deletions(-)
create mode 100644 tests/Customers/HostingPlansTest.php
diff --git a/admin_plans.php b/admin_plans.php
index cae7fb93..bf30d5ba 100644
--- a/admin_plans.php
+++ b/admin_plans.php
@@ -17,6 +17,7 @@
define('AREA', 'admin');
require './lib/init.php';
+use Froxlor\Api\Commands\HostingPlans;
use Froxlor\Database\Database;
use Froxlor\Settings;
@@ -69,22 +70,26 @@ if ($page == '' || $page == 'overview') {
eval("echo \"" . \Froxlor\UI\Template::getTemplate("plans/plans") . "\";");
} elseif ($action == 'delete' && $id != 0) {
- $result_stmt = Database::prepare("
- SELECT * FROM `" . TABLE_PANEL_PLANS . "` WHERE `id` = :id");
- $result = Database::pexecute_first($result_stmt, array(
- 'id' => $id
- ));
+ try {
+ $json_result = HostingPlans::getLocal($userinfo, array(
+ 'id' => $id
+ ))->get();
+ } catch (Exception $e) {
+ \Froxlor\UI\Response::dynamic_error($e->getMessage());
+ }
+ $result = json_decode($json_result, true)['data'];
if ($result['id'] != 0 && $result['id'] == $id && (int) $userinfo['adminid'] == $result['adminid']) {
if (isset($_POST['send']) && $_POST['send'] == 'send') {
- $del_stmt = Database::prepare("
- DELETE FROM `" . TABLE_PANEL_PLANS . "` WHERE `id` = :id");
- Database::pexecute($del_stmt, array(
- 'id' => $id
- ));
+ try {
+ HostingPlans::getLocal($userinfo, array(
+ 'id' => $id
+ ))->delete();
+ } catch (Exception $e) {
+ \Froxlor\UI\Response::dynamic_error($e->getMessage());
+ }
- $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "Plan '" . $result['name'] . "' has been deleted by '" . $userinfo['loginname'] . "'");
\Froxlor\UI\Response::redirectTo($filename, array(
'page' => $page,
's' => $s
@@ -102,113 +107,11 @@ if ($page == '' || $page == 'overview') {
} elseif ($action == 'add') {
if (isset($_POST['send']) && $_POST['send'] == 'send') {
- $name = \Froxlor\Validate\Validate::validate($_POST['name'], 'name');
- $description = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $_POST['description']), 'description', '/^[^\0]*$/');
-
- $value_arr = array();
-
- if (empty($name)) {
- \Froxlor\UI\Response::standard_error('stringmustntbeempty', 'name');
+ try {
+ HostingPlans::getLocal($userinfo, $_POST)->add();
+ } catch (Exception $e) {
+ \Froxlor\UI\Response::dynamic_error($e->getMessage());
}
-
- $value_arr['diskspace'] = (int)($_POST['diskspace']);
- if (isset($_POST['diskspace_ul'])) {
- $value_arr['diskspace'] = - 1;
- }
-
- $value_arr['traffic'] = $_POST['traffic'];
- if (isset($_POST['traffic_ul'])) {
- $value_arr['traffic'] = - 1;
- }
-
- $value_arr['subdomains'] = (int)($_POST['subdomains']);
- if (isset($_POST['subdomains_ul'])) {
- $value_arr['subdomains'] = - 1;
- }
-
- $value_arr['emails'] = (int)($_POST['emails']);
- if (isset($_POST['emails_ul'])) {
- $value_arr['emails'] = - 1;
- }
-
- $value_arr['email_accounts'] = (int)($_POST['email_accounts']);
- if (isset($_POST['email_accounts_ul'])) {
- $value_arr['email_accounts'] = - 1;
- }
-
- $value_arr['email_forwarders'] = (int)($_POST['email_forwarders']);
- if (isset($_POST['email_forwarders_ul'])) {
- $value_arr['email_forwarders'] = - 1;
- }
-
- if (Settings::Get('system.mail_quota_enabled') == '1') {
- $value_arr['email_quota'] = \Froxlor\Validate\Validate::validate($_POST['email_quota'], 'email_quota', '/^\d+$/', 'vmailquotawrong', array(
- '0',
- ''
- ));
- if (isset($_POST['email_quota_ul'])) {
- $value_arr['email_quota'] = - 1;
- }
- } else {
- $value_arr['email_quota'] = - 1;
- }
-
- $value_arr['email_imap'] = 0;
- if (isset($_POST['email_imap'])) {
- $value_arr['email_imap'] = (int)($_POST['email_imap']);
- }
-
- $value_arr['email_pop3'] = 0;
- if (isset($_POST['email_pop3'])) {
- $value_arr['email_pop3'] = (int)($_POST['email_pop3']);
- }
-
- $value_arr['ftps'] = (int)($_POST['ftps']);
- if (isset($_POST['ftps_ul'])) {
- $value_arr['ftps'] = - 1;
- }
-
- $value_arr['mysqls'] = (int)($_POST['mysqls']);
- if (isset($_POST['mysqls_ul'])) {
- $value_arr['mysqls'] = - 1;
- }
-
- $value_arr['phpenabled'] = 0;
- if (isset($_POST['phpenabled'])) {
- $value_arr['phpenabled'] = intval($_POST['phpenabled']);
- }
-
- $value_arr['allowed_phpconfigs'] = array();
- if (isset($_POST['allowed_phpconfigs']) && is_array($_POST['allowed_phpconfigs'])) {
- foreach ($_POST['allowed_phpconfigs'] as $allowed_phpconfig) {
- $allowed_phpconfig = intval($allowed_phpconfig);
- $value_arr['allowed_phpconfigs'][] = $allowed_phpconfig;
- }
- }
-
- $value_arr['perlenabled'] = 0;
- if (isset($_POST['perlenabled'])) {
- $value_arr['perlenabled'] = intval($_POST['perlenabled']);
- }
-
- $value_arr['dnsenabled'] = 0;
- if (isset($_POST['dnsenabled'])) {
- $value_arr['dnsenabled'] = intval($_POST['dnsenabled']);
- }
-
- $ins_stmt = Database::prepare("
- INSERT INTO `" . TABLE_PANEL_PLANS . "`
- SET `adminid` = :adminid, `name` = :name, `description` = :desc, `value` = :valuearr, `ts` = UNIX_TIMESTAMP();
- ");
- $ins_data = array(
- 'adminid' => $userinfo['adminid'],
- 'name' => $name,
- 'desc' => $description,
- 'valuearr' => json_encode($value_arr)
- );
- Database::pexecute($ins_stmt, $ins_data);
-
- $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "added plan '" . $name . "'");
\Froxlor\UI\Response::redirectTo($filename, array(
'page' => $page,
's' => $s
@@ -266,11 +169,14 @@ if ($page == '' || $page == 'overview') {
eval("echo \"" . \Froxlor\UI\Template::getTemplate("plans/plans_add") . "\";");
}
} elseif ($action == 'edit' && $id != 0) {
- $result_stmt = Database::prepare("
- SELECT * FROM `" . TABLE_PANEL_PLANS . "` WHERE `id` = :id");
- $result = Database::pexecute_first($result_stmt, array(
- 'id' => $id
- ));
+ try {
+ $json_result = HostingPlans::getLocal($userinfo, array(
+ 'id' => $id
+ ))->get();
+ } catch (Exception $e) {
+ \Froxlor\UI\Response::dynamic_error($e->getMessage());
+ }
+ $result = json_decode($json_result, true)['data'];
if ($result['name'] != '') {
@@ -284,110 +190,13 @@ if ($page == '' || $page == 'overview') {
if (isset($_POST['send']) && $_POST['send'] == 'send') {
- $name = \Froxlor\Validate\Validate::validate($_POST['name'], 'name');
- $description = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $_POST['description']), 'description', '/^[^\0]*$/');
-
- $value_arr = array();
-
- $value_arr['diskspace'] = (int)($_POST['diskspace']);
- if (isset($_POST['diskspace_ul'])) {
- $value_arr['diskspace'] = - 1;
+ try {
+ HostingPlans::getLocal($userinfo, array(
+ 'id' => $id
+ ))->update();
+ } catch (Exception $e) {
+ \Froxlor\UI\Response::dynamic_error($e->getMessage());
}
-
- $value_arr['traffic'] = $_POST['traffic'];
- if (isset($_POST['traffic_ul'])) {
- $value_arr['traffic'] = - 1;
- }
-
- $value_arr['subdomains'] = (int)($_POST['subdomains']);
- if (isset($_POST['subdomains_ul'])) {
- $value_arr['subdomains'] = - 1;
- }
-
- $value_arr['emails'] = (int)($_POST['emails']);
- if (isset($_POST['emails_ul'])) {
- $value_arr['emails'] = - 1;
- }
-
- $value_arr['email_accounts'] = (int)($_POST['email_accounts']);
- if (isset($_POST['email_accounts_ul'])) {
- $value_arr['email_accounts'] = - 1;
- }
-
- $value_arr['email_forwarders'] = (int)($_POST['email_forwarders']);
- if (isset($_POST['email_forwarders_ul'])) {
- $value_arr['email_forwarders'] = - 1;
- }
-
- if (Settings::Get('system.mail_quota_enabled') == '1') {
- $value_arr['email_quota'] = \Froxlor\Validate\Validate::validate($_POST['email_quota'], 'email_quota', '/^\d+$/', 'vmailquotawrong', array(
- '0',
- ''
- ));
- if (isset($_POST['email_quota_ul'])) {
- $value_arr['email_quota'] = - 1;
- }
- } else {
- $value_arr['email_quota'] = - 1;
- }
-
- $value_arr['email_imap'] = 0;
- if (isset($_POST['email_imap'])) {
- $value_arr['email_imap'] = (int)($_POST['email_imap']);
- }
-
- $value_arr['email_pop3'] = 0;
- if (isset($_POST['email_pop3'])) {
- $value_arr['email_pop3'] = (int)($_POST['email_pop3']);
- }
-
- $value_arr['ftps'] = (int)($_POST['ftps']);
- if (isset($_POST['ftps_ul'])) {
- $value_arr['ftps'] = - 1;
- }
-
- $value_arr['mysqls'] = (int)($_POST['mysqls']);
- if (isset($_POST['mysqls_ul'])) {
- $value_arr['mysqls'] = - 1;
- }
-
- $value_arr['phpenabled'] = 0;
- if (isset($_POST['phpenabled'])) {
- $value_arr['phpenabled'] = intval($_POST['phpenabled']);
- }
-
- $value_arr['allowed_phpconfigs'] = array();
- if (isset($_POST['allowed_phpconfigs']) && is_array($_POST['allowed_phpconfigs'])) {
- foreach ($_POST['allowed_phpconfigs'] as $allowed_phpconfig) {
- $allowed_phpconfig = intval($allowed_phpconfig);
- $value_arr['allowed_phpconfigs'][] = $allowed_phpconfig;
- }
- }
-
- $value_arr['perlenabled'] = 0;
- if (isset($_POST['perlenabled'])) {
- $value_arr['perlenabled'] = intval($_POST['perlenabled']);
- }
-
- $value_arr['dnsenabled'] = 0;
- if (isset($_POST['dnsenabled'])) {
- $value_arr['dnsenabled'] = intval($_POST['dnsenabled']);
- }
-
- $ins_stmt = Database::prepare("
- UPDATE `" . TABLE_PANEL_PLANS . "`
- SET `name` = :name, `description` = :desc, `value` = :valuearr, `ts` = UNIX_TIMESTAMP()
- WHERE `id` = :id
- ");
- $ins_data = array(
- 'name' => $name,
- 'desc' => $description,
- 'valuearr' => json_encode($value_arr),
- 'id' => $id
- );
- Database::pexecute($ins_stmt, $ins_data);
-
- $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "updated plan '" . $name . "'");
\Froxlor\UI\Response::redirectTo($filename, array(
'page' => $page,
's' => $s
@@ -502,11 +311,14 @@ if ($page == '' || $page == 'overview') {
}
} elseif ($action == 'jqGetPlanValues') {
$planid = isset($_POST['planid']) ? (int) $_POST['planid'] : 0;
- $result_stmt = Database::prepare("
- SELECT * FROM `" . TABLE_PANEL_PLANS . "` WHERE `id` = :id");
- $result = Database::pexecute_first($result_stmt, array(
- 'id' => $planid
- ));
+ try {
+ $json_result = HostingPlans::getLocal($userinfo, array(
+ 'id' => $planid
+ ))->get();
+ } catch (Exception $e) {
+ \Froxlor\UI\Response::dynamic_error($e->getMessage());
+ }
+ $result = json_decode($json_result, true)['data'];
echo $result['value'];
exit();
}
diff --git a/lib/Froxlor/Api/Commands/HostingPlans.php b/lib/Froxlor/Api/Commands/HostingPlans.php
index 60b275f3..b20db944 100644
--- a/lib/Froxlor/Api/Commands/HostingPlans.php
+++ b/lib/Froxlor/Api/Commands/HostingPlans.php
@@ -1,6 +1,9 @@
isAdmin()) {
+ $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list hosting-plans");
+ $result_stmt = Database::prepare("
+ SELECT p.*, a.loginname as adminname
+ FROM `" . TABLE_PANEL_PLANS . "` p, `" . TABLE_PANEL_ADMINS . "` a
+ WHERE `p`.`adminid` = `a`.`adminid`" . ($this->getUserDetail('customers_see_all') ? '' : " AND `p`.`adminid` = :adminid "));
+ $params = array();
+ if ($this->getUserDetail('customers_see_all') == '0') {
+ $params['adminid'] = $this->getUserDetail('adminid');
+ }
+ Database::pexecute($result_stmt, $params);
+ $result = array();
+ while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
+ $result[] = $row;
+ }
+ return $this->response(200, "successfull", array(
+ 'count' => count($result),
+ 'list' => $result
+ ));
+ }
+ throw new \Exception("Not allowed to execute given command.", 403);
}
+ /**
+ * return a hosting-plan entry by either id or plan-name
+ *
+ * @param int $id
+ * optional, the hosting-plan-id
+ * @param string $planname
+ * optional, the hosting-plan-name
+ *
+ * @access admin
+ * @throws \Exception
+ * @return string json-encoded array
+ */
+ public function get()
+ {
+ if ($this->isAdmin()) {
+ $id = $this->getParam('id', true, 0);
+ $dn_optional = ($id <= 0 ? false : true);
+ $planname = $this->getParam('planname', $dn_optional, '');
+ $result_stmt = Database::prepare("
+ SELECT * FROM `" . TABLE_PANEL_PLANS . "` WHERE " . ($id > 0 ? "`id` = :iddn" : "`name` = :iddn") . ($this->getUserDetail('customers_see_all') ? '' : " AND `adminid` = :adminid"));
+ $params = array(
+ 'iddn' => ($id <= 0 ? $planname : $id)
+ );
+ if ($this->getUserDetail('customers_see_all') == '0') {
+ $params['adminid'] = $this->getUserDetail('adminid');
+ }
+ $result = Database::pexecute_first($result_stmt, $params, true, true);
+ if ($result) {
+ $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get hosting-plan '" . $result['name'] . "'");
+ return $this->response(200, "successfull", $result);
+ }
+ $key = ($id > 0 ? "id #" . $id : "planname '" . $planname . "'");
+ throw new \Exception("Hosting-plan with " . $key . " could not be found", 404);
+ }
+ throw new \Exception("Not allowed to execute given command.", 403);
+ }
+
+ /**
+ * add new hosting-plan
+ *
+ * @param string $name
+ * name of the plan
+ * @param string $description
+ * optional, description for hosting-plan
+ * @param int $diskspace
+ * optional disk-space available for customer in MB, default 0
+ * @param bool $diskspace_ul
+ * optional, whether customer should have unlimited diskspace, default 0 (false)
+ * @param int $traffic
+ * optional traffic available for customer in GB, default 0
+ * @param bool $traffic_ul
+ * optional, whether customer should have unlimited traffic, default 0 (false)
+ * @param int $subdomains
+ * optional amount of subdomains available for customer, default 0
+ * @param bool $subdomains_ul
+ * optional, whether customer should have unlimited subdomains, default 0 (false)
+ * @param int $emails
+ * optional amount of emails available for customer, default 0
+ * @param bool $emails_ul
+ * optional, whether customer should have unlimited emails, default 0 (false)
+ * @param int $email_accounts
+ * optional amount of email-accounts available for customer, default 0
+ * @param bool $email_accounts_ul
+ * optional, whether customer should have unlimited email-accounts, default 0 (false)
+ * @param int $email_forwarders
+ * optional amount of email-forwarders available for customer, default 0
+ * @param bool $email_forwarders_ul
+ * optional, whether customer should have unlimited email-forwarders, default 0 (false)
+ * @param int $email_quota
+ * optional size of email-quota available for customer in MB, default is system-setting mail_quota
+ * @param bool $email_quota_ul
+ * optional, whether customer should have unlimited email-quota, default 0 (false)
+ * @param bool $email_imap
+ * optional, whether to allow IMAP access, default 0 (false)
+ * @param bool $email_pop3
+ * optional, whether to allow POP3 access, default 0 (false)
+ * @param int $ftps
+ * optional amount of ftp-accounts available for customer, default 0
+ * @param bool $ftps_ul
+ * optional, whether customer should have unlimited ftp-accounts, default 0 (false)
+ * @param int $mysqls
+ * optional amount of mysql-databases available for customer, default 0
+ * @param bool $mysqls_ul
+ * optional, whether customer should have unlimited mysql-databases, default 0 (false)
+ * @param bool $phpenabled
+ * optional, whether to allow usage of PHP, default 0 (false)
+ * @param array $allowed_phpconfigs
+ * optional, array of IDs of php-config that the customer is allowed to use, default empty (none)
+ * @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)
+ * @param bool $logviewenabled
+ * optional, ether to allow acccess to webserver access/error-logs, default 0 (false)
+ *
+ * @access admin
+ * @throws \Exception
+ * @return string json-encoded array
+ */
+ public function add()
+ {
+ if ($this->isAdmin()) {
+ $name = $this->getParam('name');
+ $description = $this->getParam('description', true, '');
+
+ $value_arr = array();
+ $value_arr['diskspace'] = $this->getUlParam('diskspace', 'diskspace_ul', true, 0);
+ $value_arr['traffic'] = $this->getUlParam('traffic', 'traffic_ul', true, 0);
+ $value_arr['subdomains'] = $this->getUlParam('subdomains', 'subdomains_ul', true, 0);
+ $value_arr['emails'] = $this->getUlParam('emails', 'emails_ul', true, 0);
+ $value_arr['email_accounts'] = $this->getUlParam('email_accounts', 'email_accounts_ul', true, 0);
+ $value_arr['email_forwarders'] = $this->getUlParam('email_forwarders', 'email_forwarders_ul', true, 0);
+ $value_arr['email_quota'] = $this->getUlParam('email_quota', 'email_quota_ul', true, Settings::Get('system.mail_quota'));
+ $value_arr['email_imap'] = $this->getBoolParam('email_imap', true, 0);
+ $value_arr['email_pop3'] = $this->getBoolParam('email_pop3', true, 0);
+ $value_arr['ftps'] = $this->getUlParam('ftps', 'ftps_ul', true, 0);
+ $value_arr['mysqls'] = $this->getUlParam('mysqls', 'mysqls_ul', true, 0);
+ $value_arr['phpenabled'] = $this->getBoolParam('phpenabled', true, 0);
+ $p_allowed_phpconfigs = $this->getParam('allowed_phpconfigs', true, array());
+ $value_arr['perlenabled'] = $this->getBoolParam('perlenabled', true, 0);
+ $value_arr['dnsenabled'] = $this->getBoolParam('dnsenabled', true, 0);
+ $value_arr['logviewenabled'] = $this->getBoolParam('logviewenabled', true, 0);
+
+ // validation
+ $name = \Froxlor\Validate\Validate::validate(trim($name), 'name', '', '', array(), true);
+ $description = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $description), 'description', '/^[^\0]*$/');
+
+ if (Settings::Get('system.mail_quota_enabled') != '1') {
+ $value_arr['email_quota'] = - 1;
+ }
+
+ $value_arr['allowed_phpconfigs'] = array();
+ if (! empty($p_allowed_phpconfigs) && is_array($p_allowed_phpconfigs)) {
+ foreach ($p_allowed_phpconfigs as $allowed_phpconfig) {
+ $allowed_phpconfig = intval($allowed_phpconfig);
+ $value_arr['allowed_phpconfigs'][] = $allowed_phpconfig;
+ }
+ }
+ $value_arr['allowed_phpconfigs'] = array_map('intval', $value_arr['allowed_phpconfigs']);
+
+ $ins_stmt = Database::prepare("
+ INSERT INTO `" . TABLE_PANEL_PLANS . "`
+ SET `adminid` = :adminid, `name` = :name, `description` = :desc, `value` = :valuearr, `ts` = UNIX_TIMESTAMP();
+ ");
+ $ins_data = array(
+ 'adminid' => $this->getUserDetail('adminid'),
+ 'name' => $name,
+ 'desc' => $description,
+ 'valuearr' => json_encode($value_arr)
+ );
+ Database::pexecute($ins_stmt, $ins_data, true, true);
+ $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added hosting-plan '" . $name . "'");
+ $result = $this->apiCall('HostingPlans.get', array(
+ 'planname' => $name
+ ));
+ return $this->response(200, "successfull", $result);
+ }
+ throw new \Exception("Not allowed to execute given command.", 403);
+ }
+
+ /**
+ * update hosting-plan by either id or plan-name
+ *
+ * @param int $id
+ * optional the hosting-plan-id
+ * @param string $planname
+ * optional the hosting-plan-name
+ * @param string $name
+ * optional name of the plan
+ * @param string $description
+ * optional description for hosting-plan
+ * @param int $diskspace
+ * optional disk-space available for customer in MB, default 0
+ * @param bool $diskspace_ul
+ * optional, whether customer should have unlimited diskspace, default 0 (false)
+ * @param int $traffic
+ * optional traffic available for customer in GB, default 0
+ * @param bool $traffic_ul
+ * optional, whether customer should have unlimited traffic, default 0 (false)
+ * @param int $subdomains
+ * optional amount of subdomains available for customer, default 0
+ * @param bool $subdomains_ul
+ * optional, whether customer should have unlimited subdomains, default 0 (false)
+ * @param int $emails
+ * optional amount of emails available for customer, default 0
+ * @param bool $emails_ul
+ * optional, whether customer should have unlimited emails, default 0 (false)
+ * @param int $email_accounts
+ * optional amount of email-accounts available for customer, default 0
+ * @param bool $email_accounts_ul
+ * optional, whether customer should have unlimited email-accounts, default 0 (false)
+ * @param int $email_forwarders
+ * optional amount of email-forwarders available for customer, default 0
+ * @param bool $email_forwarders_ul
+ * optional, whether customer should have unlimited email-forwarders, default 0 (false)
+ * @param int $email_quota
+ * optional size of email-quota available for customer in MB, default is system-setting mail_quota
+ * @param bool $email_quota_ul
+ * optional, whether customer should have unlimited email-quota, default 0 (false)
+ * @param bool $email_imap
+ * optional, whether to allow IMAP access, default 0 (false)
+ * @param bool $email_pop3
+ * optional, whether to allow POP3 access, default 0 (false)
+ * @param int $ftps
+ * optional amount of ftp-accounts available for customer, default 0
+ * @param bool $ftps_ul
+ * optional, whether customer should have unlimited ftp-accounts, default 0 (false)
+ * @param int $mysqls
+ * optional amount of mysql-databases available for customer, default 0
+ * @param bool $mysqls_ul
+ * optional, whether customer should have unlimited mysql-databases, default 0 (false)
+ * @param bool $phpenabled
+ * optional, whether to allow usage of PHP, default 0 (false)
+ * @param array $allowed_phpconfigs
+ * optional, array of IDs of php-config that the customer is allowed to use, default empty (none)
+ * @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)
+ * @param bool $logviewenabled
+ * optional, ether to allow acccess to webserver access/error-logs, default 0 (false)
+ *
+ * @access admin
+ * @throws \Exception
+ * @return string json-encoded array
+ */
+ public function update()
+ {
+ if ($this->isAdmin()) {
+
+ // parameters
+ $id = $this->getParam('id', true, 0);
+ $dn_optional = ($id <= 0 ? false : true);
+ $planname = $this->getParam('planname', $dn_optional, '');
+
+ // get requested hosting-plan
+ $result = $this->apiCall('HostingPlans.get', array(
+ 'id' => $id,
+ 'planname' => $planname
+ ));
+ $id = $result['id'];
+
+ $result['value'] = json_decode($result['value'], true);
+ foreach ($result['value'] as $index => $value) {
+ $result[$index] = $value;
+ }
+
+ $name = $this->getParam('name', true, $result['name']);
+ $description = $this->getParam('description', true, $result['description']);
+
+ $value_arr = array();
+ $value_arr['diskspace'] = $this->getUlParam('diskspace', 'diskspace_ul', true, $result['diskspace']);
+ $value_arr['traffic'] = $this->getUlParam('traffic', 'traffic_ul', true, $result['traffic']);
+ $value_arr['subdomains'] = $this->getUlParam('subdomains', 'subdomains_ul', true, $result['subdomains']);
+ $value_arr['emails'] = $this->getUlParam('emails', 'emails_ul', true, $result['emails']);
+ $value_arr['email_accounts'] = $this->getUlParam('email_accounts', 'email_accounts_ul', true, $result['email_accounts']);
+ $value_arr['email_forwarders'] = $this->getUlParam('email_forwarders', 'email_forwarders_ul', true, $result['email_forwarders']);
+ $value_arr['email_quota'] = $this->getUlParam('email_quota', 'email_quota_ul', true, $result['email_quota']);
+ $value_arr['email_imap'] = $this->getParam('email_imap', true, $result['email_imap']);
+ $value_arr['email_pop3'] = $this->getParam('email_pop3', true, $result['email_pop3']);
+ $value_arr['ftps'] = $this->getUlParam('ftps', 'ftps_ul', true, $result['ftps']);
+ $value_arr['mysqls'] = $this->getUlParam('mysqls', 'mysqls_ul', true, $result['mysqls']);
+ $value_arr['phpenabled'] = $this->getBoolParam('phpenabled', true, $result['phpenabled']);
+ $p_allowed_phpconfigs = $this->getParam('allowed_phpconfigs', true, $result['allowed_phpconfigs']);
+ $value_arr['perlenabled'] = $this->getBoolParam('perlenabled', true, $result['perlenabled']);
+ $value_arr['dnsenabled'] = $this->getBoolParam('dnsenabled', true, $result['dnsenabled']);
+ $value_arr['logviewenabled'] = $this->getBoolParam('logviewenabled', true, $result['logviewenabled']);
+
+ // validation
+ $name = \Froxlor\Validate\Validate::validate(trim($name), 'name', '', '', array(), true);
+ $description = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $description), 'description', '/^[^\0]*$/');
+
+ if (Settings::Get('system.mail_quota_enabled') != '1') {
+ $value_arr['email_quota'] = - 1;
+ }
+
+ if (empty($name)) {
+ $name = $result['name'];
+ }
+
+ $value_arr['allowed_phpconfigs'] = array();
+ if (! empty($p_allowed_phpconfigs) && is_array($p_allowed_phpconfigs)) {
+ foreach ($p_allowed_phpconfigs as $allowed_phpconfig) {
+ $allowed_phpconfig = intval($allowed_phpconfig);
+ $value_arr['allowed_phpconfigs'][] = $allowed_phpconfig;
+ }
+ }
+ $value_arr['allowed_phpconfigs'] = array_map('intval', $value_arr['allowed_phpconfigs']);
+
+ $upd_stmt = Database::prepare("
+ UPDATE `" . TABLE_PANEL_PLANS . "`
+ SET `name` = :name, `description` = :desc, `value` = :valuearr, `ts` = UNIX_TIMESTAMP()
+ WHERE `id` = :id
+ ");
+ $update_data = array(
+ 'name' => $name,
+ 'desc' => $description,
+ 'valuearr' => json_encode($value_arr),
+ 'id' => $id
+ );
+ Database::pexecute($upd_stmt, $update_data, true, true);
+ $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] updated hosting-plan '" . $result['name'] . "'");
+ return $this->response(200, "successfull", $update_data);
+ }
+ throw new \Exception("Not allowed to execute given command.", 403);
+ }
+
+ /**
+ * delete hosting-plan by either id or plan-name
+ *
+ * @param int $id
+ * optional the hosting-plan-id
+ * @param string $planname
+ * optional the hosting-plan-name
+ *
+ * @access admin
+ * @throws \Exception
+ * @return string json-encoded array
+ */
public function delete()
{
- throw new \Exception('noop', 303);
+ if ($this->isAdmin()) {
+ $id = $this->getParam('id', true, 0);
+ $dn_optional = ($id <= 0 ? false : true);
+ $planname = $this->getParam('planname', $dn_optional, '');
+
+ // get requested hosting-plan
+ $result = $this->apiCall('HostingPlans.get', array(
+ 'id' => $id,
+ 'planname' => $planname
+ ));
+ $id = $result['id'];
+
+ $del_stmt = Database::prepare("
+ DELETE FROM `" . TABLE_PANEL_PLANS . "` WHERE `id` = :id
+ ");
+ Database::pexecute($del_stmt, array(
+ '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);
+ }
+ throw new \Exception("Not allowed to execute given command.", 403);
}
}
diff --git a/templates/Sparkle/assets/js/customers.js b/templates/Sparkle/assets/js/customers.js
index 46ff6e1e..40d59bda 100644
--- a/templates/Sparkle/assets/js/customers.js
+++ b/templates/Sparkle/assets/js/customers.js
@@ -31,7 +31,7 @@ $(document).ready(function() {
dataType: "json",
success: function(json) {
for (var i in json) {
- if (i == 'email_imap' || i == 'email_pop3' || i == 'perlenabled' || i == 'phpenabled' || i == 'dnsenabled') {
+ if (i == 'email_imap' || i == 'email_pop3' || i == 'perlenabled' || i == 'phpenabled' || i == 'dnsenabled' || i == 'logviewenabled') {
/** handle checkboxes **/
if (json[i] == 1) {
$("input[name='"+i+"']").prop('checked', true);
diff --git a/tests/Customers/HostingPlansTest.php b/tests/Customers/HostingPlansTest.php
new file mode 100644
index 00000000..41cafd80
--- /dev/null
+++ b/tests/Customers/HostingPlansTest.php
@@ -0,0 +1,258 @@
+ 'test',
+ 'description' => 'first test plan',
+ 'diskspace' => 0,
+ 'diskspace_ul' => 1,
+ 'traffic' => - 1,
+ 'subdomains' => 15,
+ 'emails' => - 1,
+ 'email_accounts' => 15,
+ 'email_forwarders' => 15,
+ 'email_imap' => 1,
+ 'email_pop3' => 0,
+ 'ftps' => 15,
+ 'mysqls' => 15,
+ 'phpenabled' => 1,
+ 'dnsenabled' => 1,
+ 'allowed_phpconfigs' => array(
+ 1
+ )
+ ];
+
+ $json_result = HostingPlans::getLocal($admin_userdata, $data)->add();
+ $result = json_decode($json_result, true)['data'];
+ $result['value'] = json_decode($result['value'], true);
+ foreach ($result['value'] as $index => $value) {
+ $result[$index] = $value;
+ }
+ $this->assertEquals('test', $result['name']);
+ $this->assertEquals(- 1, $result['diskspace']);
+ $this->assertEquals(15, $result['email_accounts']);
+ $this->assertEquals([
+ 1
+ ], $result['allowed_phpconfigs']);
+ }
+
+ public function testAdminPlanAddEmptyName()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'description' => 'test plan'
+ ];
+
+ $this->expectExceptionMessage('Requested parameter "name" could not be found for "HostingPlans:add"');
+ HostingPlans::getLocal($admin_userdata, $data)->add();
+
+ $data['name'] = null;
+ $this->expectExceptionMessage('Requested parameter "name" is empty where it should not be for "HostingPlans:add"');
+ HostingPlans::getLocal($admin_userdata, $data)->add();
+ }
+
+ /**
+ *
+ * @depends testAdminPlanAdd
+ */
+ public function testAdminPlanList()
+ {
+ global $admin_userdata;
+
+ $json_result = HostingPlans::getLocal($admin_userdata)->listing();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals(1, $result['count']);
+ }
+
+ /**
+ *
+ * @depends testAdminPlanAdd
+ */
+ public function testResellerPlanList()
+ {
+ 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;
+ $json_result = HostingPlans::getLocal($reseller_userdata)->listing();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals(0, $result['count']);
+ }
+
+ /**
+ *
+ * @depends testAdminPlanAdd
+ */
+ public function testCustomerPlanList()
+ {
+ global $admin_userdata;
+ // get customer
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'id' => 1
+ ))->get();
+ $customer_userdata = json_decode($json_result, true)['data'];
+
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Not allowed to execute given command.");
+
+ $json_result = HostingPlans::getLocal($customer_userdata)->listing();
+ }
+
+ public function testCustomerPlanAdd()
+ {
+ global $admin_userdata;
+ // get customer
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'id' => 1
+ ))->get();
+ $customer_userdata = json_decode($json_result, true)['data'];
+
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Not allowed to execute given command.");
+
+ $json_result = HostingPlans::getLocal($customer_userdata)->add();
+ }
+
+ public function testCustomerPlanGet()
+ {
+ global $admin_userdata;
+ // get customer
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'id' => 1
+ ))->get();
+ $customer_userdata = json_decode($json_result, true)['data'];
+
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Not allowed to execute given command.");
+
+ $json_result = HostingPlans::getLocal($customer_userdata)->get();
+ }
+
+ public function testCustomerPlanUpdate()
+ {
+ global $admin_userdata;
+ // get customer
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'id' => 1
+ ))->get();
+ $customer_userdata = json_decode($json_result, true)['data'];
+
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Not allowed to execute given command.");
+
+ $json_result = HostingPlans::getLocal($customer_userdata)->update();
+ }
+
+ public function testCustomerPlanDelete()
+ {
+ global $admin_userdata;
+ // get customer
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'id' => 1
+ ))->get();
+ $customer_userdata = json_decode($json_result, true)['data'];
+
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Not allowed to execute given command.");
+
+ $json_result = HostingPlans::getLocal($customer_userdata)->delete();
+ }
+
+ public function testAdminPlanGetNotFound()
+ {
+ global $admin_userdata;
+ $this->expectExceptionCode(404);
+ $this->expectExceptionMessage("Hosting-plan with id #999 could not be found");
+ HostingPlans::getLocal($admin_userdata, array(
+ 'id' => 999
+ ))->get();
+ }
+
+ /**
+ *
+ * @depends testAdminPlanAdd
+ */
+ public function testAdminPlanUpdate()
+ {
+ global $admin_userdata;
+
+ HostingPlans::getLocal($admin_userdata, array(
+ 'planname' => 'test',
+ 'name' => '',
+ 'ftps' => '20'
+ ))->update();
+
+ $json_result = HostingPlans::getLocal($admin_userdata, array(
+ 'planname' => 'test'
+ ))->get();
+ $result = json_decode($json_result, true)['data'];
+ $result['value'] = json_decode($result['value'], true);
+ foreach ($result['value'] as $index => $value) {
+ $result[$index] = $value;
+ }
+ $this->assertEquals(20, $result['ftps']);
+ $this->assertEquals(- 1, $result['diskspace']);
+ $this->assertEquals(15, $result['email_accounts']);
+ $this->assertEquals([
+ 1
+ ], $result['allowed_phpconfigs']);
+ }
+
+ public function testResellerPlanDeleteNotOwned()
+ {
+ 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;
+ $this->expectExceptionCode(404);
+ HostingPlans::getLocal($reseller_userdata, array(
+ 'planname' => 'test'
+ ))->delete();
+ }
+
+ /**
+ *
+ * @depends testAdminPlanAdd
+ */
+ public function testAdminPlanDelete()
+ {
+ global $admin_userdata;
+ // add new customer
+ $data = [
+ 'name' => 'test2',
+ 'description' => 'second test plan'
+ ];
+ HostingPlans::getLocal($admin_userdata, $data)->add();
+ $json_result = HostingPlans::getLocal($admin_userdata, array(
+ 'planname' => 'test2'
+ ))->delete();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals('test2', $result['name']);
+ }
+}
From fd4d3cbcfd277d7fdc964d559da62dbf2d8e5531 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Thu, 19 Sep 2019 13:06:32 +0200
Subject: [PATCH 095/159] specify pop3_logout_format explicitly for dovecot to
satisfy maillogparser
Signed-off-by: Michael Kaufmann
---
lib/configfiles/bionic.xml | 2 +-
lib/configfiles/buster.xml | 2 +-
lib/configfiles/jessie.xml | 2 +-
lib/configfiles/rhel_centos.xml | 2 +-
lib/configfiles/stretch.xml | 2 +-
lib/configfiles/xenial.xml | 2 +-
6 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/lib/configfiles/bionic.xml b/lib/configfiles/bionic.xml
index fac95592..a716e732 100644
--- a/lib/configfiles/bionic.xml
+++ b/lib/configfiles/bionic.xml
@@ -3746,7 +3746,7 @@ protocol sieve {
# %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 = top=%t/%p, retr=%r/%b, del=%d/%m, size=%s
+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:
diff --git a/lib/configfiles/buster.xml b/lib/configfiles/buster.xml
index 91b61db0..82e1fa63 100644
--- a/lib/configfiles/buster.xml
+++ b/lib/configfiles/buster.xml
@@ -3838,7 +3838,7 @@ protocol sieve {
# %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 = top=%t/%p, retr=%r/%b, del=%d/%m, size=%s
+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:
diff --git a/lib/configfiles/jessie.xml b/lib/configfiles/jessie.xml
index 9339c6c8..d3ebfae2 100644
--- a/lib/configfiles/jessie.xml
+++ b/lib/configfiles/jessie.xml
@@ -3658,7 +3658,7 @@ protocol sieve {
# %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 = top=%t/%p, retr=%r/%b, del=%d/%m, size=%s
+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:
diff --git a/lib/configfiles/rhel_centos.xml b/lib/configfiles/rhel_centos.xml
index a31b2dfa..4f3c1e3d 100644
--- a/lib/configfiles/rhel_centos.xml
+++ b/lib/configfiles/rhel_centos.xml
@@ -1529,7 +1529,7 @@ protocol sieve {
# %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 = top=%t/%p, retr=%r/%b, del=%d/%m, size=%s
+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:
diff --git a/lib/configfiles/stretch.xml b/lib/configfiles/stretch.xml
index ea88e2d0..4c9c540c 100644
--- a/lib/configfiles/stretch.xml
+++ b/lib/configfiles/stretch.xml
@@ -3735,7 +3735,7 @@ protocol sieve {
# %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 = top=%t/%p, retr=%r/%b, del=%d/%m, size=%s
+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:
diff --git a/lib/configfiles/xenial.xml b/lib/configfiles/xenial.xml
index 62f7ccd5..c4c379c7 100644
--- a/lib/configfiles/xenial.xml
+++ b/lib/configfiles/xenial.xml
@@ -3746,7 +3746,7 @@ protocol sieve {
# %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 = top=%t/%p, retr=%r/%b, del=%d/%m, size=%s
+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:
From 6ca68f6a2d1fc50ff688e1d6133a71ea7540c822 Mon Sep 17 00:00:00 2001
From: Bobselp
Date: Sun, 22 Sep 2019 17:59:21 +0200
Subject: [PATCH 096/159] fix missing namespaces in PowerDNS cron
Some getDB calls were missing the `\Froxlor\Dns\` prefix
---
lib/Froxlor/Cron/Dns/PowerDNS.php | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/Froxlor/Cron/Dns/PowerDNS.php b/lib/Froxlor/Cron/Dns/PowerDNS.php
index 76e7bddd..fa0e8d69 100644
--- a/lib/Froxlor/Cron/Dns/PowerDNS.php
+++ b/lib/Froxlor/Cron/Dns/PowerDNS.php
@@ -111,7 +111,7 @@ class PowerDNS extends DnsBase
private function insertZone($domainname, $serial = 0)
{
- $ins_stmt = PowerDNS::getDB()->prepare("
+ $ins_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("
INSERT INTO domains set `name` = :domainname, `notified_serial` = :serial, `type` = 'NATIVE'
");
$ins_stmt->execute(array(
@@ -124,7 +124,7 @@ class PowerDNS extends DnsBase
private function insertRecords($domainid = 0, $records = array(), $origin = "")
{
- $ins_stmt = PowerDNS::getDB()->prepare("
+ $ins_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("
INSERT INTO records set
`domain_id` = :did,
`name` = :rec,
@@ -161,7 +161,7 @@ class PowerDNS extends DnsBase
private function insertAllowedTransfers($domainid)
{
- $ins_stmt = PowerDNS::getDB()->prepare("
+ $ins_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("
INSERT INTO domainmetadata set `domain_id` = :did, `kind` = 'ALLOW-AXFR-FROM', `content` = :value
");
From 14914fce4441c919e702328c6891e191c53cf25b Mon Sep 17 00:00:00 2001
From: Bobselp
Date: Mon, 23 Sep 2019 21:08:16 +0200
Subject: [PATCH 097/159] Get mailbox size with maildirsize file
---
lib/Froxlor/Cron/System/MailboxsizeCron.php | 49 +++++++++++++--------
1 file changed, 30 insertions(+), 19 deletions(-)
diff --git a/lib/Froxlor/Cron/System/MailboxsizeCron.php b/lib/Froxlor/Cron/System/MailboxsizeCron.php
index 154b5685..65749b6a 100644
--- a/lib/Froxlor/Cron/System/MailboxsizeCron.php
+++ b/lib/Froxlor/Cron/System/MailboxsizeCron.php
@@ -38,26 +38,37 @@ class MailboxsizeCron extends \Froxlor\Cron\FroxlorCron
$_maildir = \Froxlor\FileDir::makeCorrectDir($maildir['maildirpath']);
if (file_exists($_maildir) && is_dir($_maildir)) {
- // mail-address allows many special characters, see http://en.wikipedia.org/wiki/Email_address#Local_part
- $return = false;
- $back = \Froxlor\FileDir::safe_exec('du -sk ' . escapeshellarg($_maildir), $return, array(
- '|',
- '&',
- '`',
- '$',
- '~',
- '?'
- ));
- foreach ($back as $backrow) {
- $emailusage = explode(' ', $backrow);
+ // 1. Check if maildirsize exists (usually when quota is enabled)
+ $maildirsize = $_maildir.'maildirsize';
+ if (file_exists($maildirsize)) {
+ \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'found maildirsize file in ' . $_maildir);
+ $file = file($maildirsize, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
+ if (!empty($file[1])) {
+ $emailusage = floatval(explode(' ', $file[1])[0]);
+ }
+ } else {
+ // 2. If maildirsize file does not exist, compute with du
+ // mail-address allows many special characters, see http://en.wikipedia.org/wiki/Email_address#Local_part
+ $return = false;
+ $back = \Froxlor\FileDir::safe_exec('du -sk ' . escapeshellarg($_maildir), $return, array(
+ '|',
+ '&',
+ '`',
+ '$',
+ '~',
+ '?'
+ ));
+ foreach ($back as $backrow) {
+ $emailusage = explode(' ', $backrow);
+ }
+ $emailusage = floatval($emailusage['0']);
+
+ // as freebsd does not have the -b flag for 'du' which gives
+ // the size in bytes, we use "-sk" for all and calculate from KiB
+ $emailusage *= 1024;
+
+ unset($back);
}
- $emailusage = floatval($emailusage['0']);
-
- // as freebsd does not have the -b flag for 'du' which gives
- // the size in bytes, we use "-sk" for all and calculate from KiB
- $emailusage *= 1024;
-
- unset($back);
\Froxlor\Database\Database::pexecute($upd_stmt, array(
'size' => $emailusage,
'id' => $maildir['id']
From 8a145eca929afba54eb2ec4f385a025f77edc9e9 Mon Sep 17 00:00:00 2001
From: Erik Zettel
Date: Tue, 24 Sep 2019 12:44:33 +0200
Subject: [PATCH 098/159] lng/english.lng.php: fix typo
---
lng/english.lng.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lng/english.lng.php b/lng/english.lng.php
index 49bb6b51..aa21d61a 100644
--- a/lng/english.lng.php
+++ b/lng/english.lng.php
@@ -502,7 +502,7 @@ $lng['panel']['pathDescriptionSubdomain'] = $lng['panel']['pathDescription'] . $
// ADDED IN 1.2.16-svn6
-$lng['admin']['templates']['TRAFFIC'] = 'Replaced with the traffic in mB, which was assigned to the customer.';
+$lng['admin']['templates']['TRAFFIC'] = 'Replaced with the traffic in MB, which was assigned to the customer.';
$lng['admin']['templates']['TRAFFICUSED'] = 'Replaced with the traffic in MB, which was exhausted by the customer.';
// ADDED IN 1.2.16-svn7
From 31cebccd5d35c05cd396741b7ad3f8c288de87d6 Mon Sep 17 00:00:00 2001
From: Bobselp
Date: Tue, 24 Sep 2019 18:16:07 +0200
Subject: [PATCH 099/159] fix calc, add check if quota is enabled
---
lib/Froxlor/Cron/System/MailboxsizeCron.php | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/lib/Froxlor/Cron/System/MailboxsizeCron.php b/lib/Froxlor/Cron/System/MailboxsizeCron.php
index 65749b6a..d35df4ef 100644
--- a/lib/Froxlor/Cron/System/MailboxsizeCron.php
+++ b/lib/Froxlor/Cron/System/MailboxsizeCron.php
@@ -38,16 +38,24 @@ class MailboxsizeCron extends \Froxlor\Cron\FroxlorCron
$_maildir = \Froxlor\FileDir::makeCorrectDir($maildir['maildirpath']);
if (file_exists($_maildir) && is_dir($_maildir)) {
- // 1. Check if maildirsize exists (usually when quota is enabled)
- $maildirsize = $_maildir.'maildirsize';
- if (file_exists($maildirsize)) {
+ $maildirsize = \Froxlor\FileDir::makeCorrectFile($_maildir . '/maildirsize');
+
+ // When quota is enabled and maildirsize file exists, use that to calculate size
+ if (\Froxlor\Settings::Get('system.mail_quota_enabled') == 1 && file_exists($maildirsize)) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'found maildirsize file in ' . $_maildir);
$file = file($maildirsize, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
- if (!empty($file[1])) {
- $emailusage = floatval(explode(' ', $file[1])[0]);
+ // Remove header
+ array_shift($file);
+ $emailusage = 0;
+ // Sum up all the changes (line 2 -> end)
+ foreach ($file as $line) {
+ $parts = explode(' ', $line);
+ if (!empty($parts[0])) {
+ $emailusage += floatval($parts[0]);
+ }
}
} else {
- // 2. If maildirsize file does not exist, compute with du
+ // if quota is disabled or maildirsize file does not exist, compute with du
// mail-address allows many special characters, see http://en.wikipedia.org/wiki/Email_address#Local_part
$return = false;
$back = \Froxlor\FileDir::safe_exec('du -sk ' . escapeshellarg($_maildir), $return, array(
From 13ab7a598b63d369721abe62c51dca2beed76a52 Mon Sep 17 00:00:00 2001
From: Bobselp
Date: Wed, 25 Sep 2019 20:03:16 +0200
Subject: [PATCH 100/159] fix MysqlHandler user field
See lib/Froxlor/FroxlorLogger.php:152
---
lib/Froxlor/System/MysqlHandler.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/Froxlor/System/MysqlHandler.php b/lib/Froxlor/System/MysqlHandler.php
index b0dc3647..1703d34a 100644
--- a/lib/Froxlor/System/MysqlHandler.php
+++ b/lib/Froxlor/System/MysqlHandler.php
@@ -57,7 +57,7 @@ class MysqlHandler extends AbstractProcessingHandler
{
$this->insert([
':message' => $record['message'],
- ':contextUser' => (isset($record['context']['loginname']) ? $record['context']['loginname'] : 'unknown'),
+ ':contextUser' => (isset($record['context']['user']) ? $record['context']['user'] : 'unknown'),
':contextAction' => (isset($record['context']['action']) ? $record['context']['action'] : '0'),
':level' => self::$froxlorLevels[$record['level']],
':datetime' => $record['datetime']->format('U')
From eabad4917b0470aa16e5e49efce840d168adbc7a Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Thu, 26 Sep 2019 09:50:13 +0200
Subject: [PATCH 101/159] correct try_files in NginxFcgi, fixes #717
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Cron/Http/NginxFcgi.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/Froxlor/Cron/Http/NginxFcgi.php b/lib/Froxlor/Cron/Http/NginxFcgi.php
index 8774f548..b2031613 100644
--- a/lib/Froxlor/Cron/Http/NginxFcgi.php
+++ b/lib/Froxlor/Cron/Http/NginxFcgi.php
@@ -35,7 +35,7 @@ class NginxFcgi extends Nginx
$php_options_text .= "\t" . '}' . "\n\n";
$php_options_text .= "\t" . 'location @php {' . "\n";
- $php_options_text .= "\t\t" . 'try_files $1 = 404;' . "\n\n";
+ $php_options_text .= "\t\t" . 'try_files $1 =404;' . "\n\n";
$php_options_text .= "\t\t" . 'include ' . Settings::Get('nginx.fastcgiparams') . ";\n";
$php_options_text .= "\t\t" . 'fastcgi_split_path_info ^(.+\.php)(/.+)\$;' . "\n";
$php_options_text .= "\t\t" . 'fastcgi_param SCRIPT_FILENAME $request_filename;' . "\n";
From cc04e4403133c12194f255bc7e7e3c58ce466242 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Fri, 27 Sep 2019 12:54:43 +0200
Subject: [PATCH 102/159] add possibility to add customer using a hosting-plan
instead of specifying resources
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Api/Commands/Customers.php | 68 +++++++++++++++++++-------
tests/Customers/HostingPlansTest.php | 67 ++++++++++++++++++++-----
2 files changed, 105 insertions(+), 30 deletions(-)
diff --git a/lib/Froxlor/Api/Commands/Customers.php b/lib/Froxlor/Api/Commands/Customers.php
index 11e0b014..34f386bf 100644
--- a/lib/Froxlor/Api/Commands/Customers.php
+++ b/lib/Froxlor/Api/Commands/Customers.php
@@ -197,11 +197,13 @@ 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, wether 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, wether to allow acccess 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
+ * optional, specify a hosting-plan to set certain resource-values from the plan instead of specifying them
*
* @access admin
* @throws \Exception
@@ -230,29 +232,57 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$gender = (int) $this->getParam('gender', true, 0);
$custom_notes = $this->getParam('custom_notes', true, '');
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0);
-
- $diskspace = $this->getUlParam('diskspace', 'diskspace_ul', true, 0);
- $traffic = $this->getUlParam('traffic', 'traffic_ul', true, 0);
- $subdomains = $this->getUlParam('subdomains', 'subdomains_ul', true, 0);
- $emails = $this->getUlParam('emails', 'emails_ul', true, 0);
- $email_accounts = $this->getUlParam('email_accounts', 'email_accounts_ul', true, 0);
- $email_forwarders = $this->getUlParam('email_forwarders', 'email_forwarders_ul', true, 0);
- $email_quota = $this->getUlParam('email_quota', 'email_quota_ul', true, Settings::Get('system.mail_quota'));
- $email_imap = $this->getBoolParam('email_imap', true, 0);
- $email_pop3 = $this->getBoolParam('email_pop3', true, 0);
- $ftps = $this->getUlParam('ftps', 'ftps_ul', true, 0);
- $mysqls = $this->getUlParam('mysqls', 'mysqls_ul', true, 0);
$createstdsubdomain = $this->getBoolParam('createstdsubdomain', true, 0);
$password = $this->getParam('new_customer_password', true, '');
$sendpassword = $this->getBoolParam('sendpassword', true, 0);
- $phpenabled = $this->getBoolParam('phpenabled', true, 0);
- $p_allowed_phpconfigs = $this->getParam('allowed_phpconfigs', true, array());
- $perlenabled = $this->getBoolParam('perlenabled', true, 0);
- $dnsenabled = $this->getBoolParam('dnsenabled', true, 0);
- $logviewenabled = $this->getBoolParam('logviewenabled', true, 0);
$store_defaultindex = $this->getBoolParam('store_defaultindex', true, 0);
$loginname = $this->getParam('new_loginname', true, '');
+ // hosting-plan values
+ $hosting_plan_id = $this->getParam('hosting_plan_id', true, 0);
+ if ($hosting_plan_id > 0) {
+ $hp_result = $this->apiCall('HostingPlans.get', array(
+ 'id' => $hosting_plan_id
+ ));
+ $hp_result['value'] = json_decode($hp_result['value'], true);
+ foreach ($hp_result['value'] as $index => $value) {
+ $hp_result[$index] = $value;
+ }
+ $diskspace = $hp_result['diskspace'] ?? 0;
+ $traffic = $hp_result['traffic'] ?? 0;
+ $subdomains = $hp_result['subdomains'] ?? 0;
+ $emails = $hp_result['emails'] ?? 0;
+ $email_accounts = $hp_result['email_accounts'] ?? 0;
+ $email_forwarders = $hp_result['email_forwarders'] ?? 0;
+ $email_quota = $hp_result['email_quota'] ?? Settings::Get('system.mail_quota');
+ $email_imap = $hp_result['email_imap'] ?? 0;
+ $email_pop3 = $hp_result['email_pop3'] ?? 0;
+ $ftps = $hp_result['ftps'] ?? 0;
+ $mysqls = $hp_result['mysqls'] ?? 0;
+ $phpenabled = $hp_result['phpenabled'] ?? 0;
+ $p_allowed_phpconfigs = $hp_result['allowed_phpconfigs'] ?? 0;
+ $perlenabled = $hp_result['perlenabled'] ?? 0;
+ $dnsenabled = $hp_result['dnsenabled'] ?? 0;
+ $logviewenabled = $hp_result['logviewenabled'] ?? 0;
+ } else {
+ $diskspace = $this->getUlParam('diskspace', 'diskspace_ul', true, 0);
+ $traffic = $this->getUlParam('traffic', 'traffic_ul', true, 0);
+ $subdomains = $this->getUlParam('subdomains', 'subdomains_ul', true, 0);
+ $emails = $this->getUlParam('emails', 'emails_ul', true, 0);
+ $email_accounts = $this->getUlParam('email_accounts', 'email_accounts_ul', true, 0);
+ $email_forwarders = $this->getUlParam('email_forwarders', 'email_forwarders_ul', true, 0);
+ $email_quota = $this->getUlParam('email_quota', 'email_quota_ul', true, Settings::Get('system.mail_quota'));
+ $email_imap = $this->getBoolParam('email_imap', true, 0);
+ $email_pop3 = $this->getBoolParam('email_pop3', true, 0);
+ $ftps = $this->getUlParam('ftps', 'ftps_ul', true, 0);
+ $mysqls = $this->getUlParam('mysqls', 'mysqls_ul', true, 0);
+ $phpenabled = $this->getBoolParam('phpenabled', true, 0);
+ $p_allowed_phpconfigs = $this->getParam('allowed_phpconfigs', true, array());
+ $perlenabled = $this->getBoolParam('perlenabled', true, 0);
+ $dnsenabled = $this->getBoolParam('dnsenabled', true, 0);
+ $logviewenabled = $this->getBoolParam('logviewenabled', true, 0);
+ }
+
// validation
$name = \Froxlor\Validate\Validate::validate($name, 'name', '', '', array(), true);
$firstname = \Froxlor\Validate\Validate::validate($firstname, 'first name', '', '', array(), true);
diff --git a/tests/Customers/HostingPlansTest.php b/tests/Customers/HostingPlansTest.php
index 41cafd80..463fa64b 100644
--- a/tests/Customers/HostingPlansTest.php
+++ b/tests/Customers/HostingPlansTest.php
@@ -12,6 +12,7 @@ use Froxlor\Api\Commands\HostingPlans;
* @covers \Froxlor\Api\ApiCommand
* @covers \Froxlor\Api\ApiParameter
* @covers \Froxlor\Api\Commands\HostingPlans
+ * @covers \Froxlor\Api\Commands\Customers
*/
class HostingPlansTest extends TestCase
{
@@ -65,7 +66,7 @@ class HostingPlansTest extends TestCase
$this->expectExceptionMessage('Requested parameter "name" could not be found for "HostingPlans:add"');
HostingPlans::getLocal($admin_userdata, $data)->add();
-
+
$data['name'] = null;
$this->expectExceptionMessage('Requested parameter "name" is empty where it should not be for "HostingPlans:add"');
HostingPlans::getLocal($admin_userdata, $data)->add();
@@ -120,7 +121,7 @@ class HostingPlansTest extends TestCase
$json_result = HostingPlans::getLocal($customer_userdata)->listing();
}
-
+
public function testCustomerPlanAdd()
{
global $admin_userdata;
@@ -129,10 +130,10 @@ class HostingPlansTest extends TestCase
'id' => 1
))->get();
$customer_userdata = json_decode($json_result, true)['data'];
-
+
$this->expectExceptionCode(403);
$this->expectExceptionMessage("Not allowed to execute given command.");
-
+
$json_result = HostingPlans::getLocal($customer_userdata)->add();
}
@@ -144,13 +145,13 @@ class HostingPlansTest extends TestCase
'id' => 1
))->get();
$customer_userdata = json_decode($json_result, true)['data'];
-
+
$this->expectExceptionCode(403);
$this->expectExceptionMessage("Not allowed to execute given command.");
-
+
$json_result = HostingPlans::getLocal($customer_userdata)->get();
}
-
+
public function testCustomerPlanUpdate()
{
global $admin_userdata;
@@ -159,10 +160,10 @@ class HostingPlansTest extends TestCase
'id' => 1
))->get();
$customer_userdata = json_decode($json_result, true)['data'];
-
+
$this->expectExceptionCode(403);
$this->expectExceptionMessage("Not allowed to execute given command.");
-
+
$json_result = HostingPlans::getLocal($customer_userdata)->update();
}
@@ -174,10 +175,10 @@ class HostingPlansTest extends TestCase
'id' => 1
))->get();
$customer_userdata = json_decode($json_result, true)['data'];
-
+
$this->expectExceptionCode(403);
$this->expectExceptionMessage("Not allowed to execute given command.");
-
+
$json_result = HostingPlans::getLocal($customer_userdata)->delete();
}
@@ -255,4 +256,48 @@ class HostingPlansTest extends TestCase
$result = json_decode($json_result, true)['data'];
$this->assertEquals('test2', $result['name']);
}
+
+ /**
+ *
+ * @depends testAdminPlanAdd
+ */
+ public function testAdminCustomersAddWithHostingPlan()
+ {
+ global $admin_userdata;
+
+ $json_result = HostingPlans::getLocal($admin_userdata, array(
+ 'planname' => 'test'
+ ))->get();
+ $result = json_decode($json_result, true)['data'];
+
+ $data = [
+ 'new_loginname' => 'test1hp',
+ 'email' => 'team@froxlor.org',
+ 'firstname' => 'Test',
+ 'name' => 'Testman',
+ 'customernumber' => 1337,
+ 'createstdsubdomain' => 0,
+ 'new_customer_password' => 'h0lYmo1y',
+ 'sendpassword' => TRAVIS_CI == 1 ? 0 : 1,
+ 'store_defaultindex' => 1,
+ 'custom_notes' => 'secret',
+ 'custom_notes_show' => 0,
+ 'gender' => 5,
+ 'hosting_plan_id' => $result['id']
+ ];
+
+ $json_result = Customers::getLocal($admin_userdata, $data)->add();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals(- 1024, $result['diskspace']);
+ $this->assertEquals(15, $result['subdomains']);
+ $this->assertEquals(1, $result['phpenabled']);
+ $this->assertJsonStringEqualsJsonString(json_encode([
+ 1
+ ]), $result['allowed_phpconfigs']);
+
+ // remove customer
+ Customers::getLocal($admin_userdata, array(
+ 'loginname' => 'test1hp'
+ ))->delete();
+ }
}
From 47ca35012740181aa5d1b663c248fa7b25715004 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Fri, 27 Sep 2019 12:55:14 +0200
Subject: [PATCH 103/159] increase php requirement to 7.0 as 5.6 is way too old
Signed-off-by: Michael Kaufmann
---
install/lib/class.FroxlorInstall.php | 4 ++--
install/lng/english.lng.php | 4 ++--
install/lng/french.lng.php | 2 +-
install/lng/german.lng.php | 4 ++--
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php
index 7c61963c..1ae347a0 100644
--- a/install/lib/class.FroxlorInstall.php
+++ b/install/lib/class.FroxlorInstall.php
@@ -963,11 +963,11 @@ class FroxlorInstall
// check for correct php version
$content .= $this->_status_message('begin', $this->_lng['requirements']['phpversion']);
- if (version_compare("5.6.0", PHP_VERSION, ">=")) {
+ if (version_compare("7.0.0", PHP_VERSION, ">=")) {
$content .= $this->_status_message('red', $this->_lng['requirements']['notfound'] . ' (' . PHP_VERSION . ')');
$_die = true;
} else {
- if (version_compare("7.0.0", PHP_VERSION, ">=")) {
+ if (version_compare("7.1.0", PHP_VERSION, ">=")) {
$content .= $this->_status_message('orange', $this->_lng['requirements']['newerphpprefered'] . ' (' . PHP_VERSION . ')');
} else {
$content .= $this->_status_message('green', PHP_VERSION);
diff --git a/install/lng/english.lng.php b/install/lng/english.lng.php
index 4665033b..b7dd5ef8 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 >= 5.6';
-$lng['requirements']['newerphpprefered'] = 'Good, but php-7.0 is prefered.';
+$lng['requirements']['phpversion'] = 'PHP version >= 7.0';
+$lng['requirements']['newerphpprefered'] = 'Good, but php-7.1 is prefered.';
$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 ab44f688..fdb733ce 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 >= 5.6';
+$lng['requirements']['phpversion'] = 'PHP version >= 7.0';
$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 0de1ff0e..1f95decc 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 >= 5.6';
-$lng['requirements']['newerphpprefered'] = 'Passt, aber php-7.0 wird bevorzugt.';
+$lng['requirements']['phpversion'] = 'PHP Version >= 7.0';
+$lng['requirements']['newerphpprefered'] = 'Passt, aber php-7.1 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 c9d30654e02a7714f263c518bcd64245356b43df Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Wed, 2 Oct 2019 09:12:06 +0200
Subject: [PATCH 104/159] update link to openssl-ciphers manual, thx to lod
Signed-off-by: Michael Kaufmann
---
lng/english.lng.php | 2 +-
lng/german.lng.php | 2 +-
lng/italian.lng.php | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/lng/english.lng.php b/lng/english.lng.php
index aa21d61a..84c992e4 100644
--- a/lng/english.lng.php
+++ b/lng/english.lng.php
@@ -1626,7 +1626,7 @@ $lng['domains']['serveraliasoption_www'] = 'WWW (www.domain.tld)';
$lng['domains']['serveraliasoption_none'] = 'No alias';
$lng['error']['givendirnotallowed'] = 'The given directory in field %s is not allowed.';
$lng['serversettings']['ssl']['ssl_cipher_list']['title'] = 'Configure the allowed SSL ciphers';
-$lng['serversettings']['ssl']['ssl_cipher_list']['description'] = 'This is a list of ciphers that you want (or don\'t want) to use when talking SSL. For a list of ciphers and how to include/exclude them, see sections "CIPHER LIST FORMAT" and "CIPHER STRINGS" on the man-page for ciphers .Default value is: ECDH+AESGCM:ECDH+AES256:!aNULL:!MD5:!DSS:!DH:!AES128 ';
+$lng['serversettings']['ssl']['ssl_cipher_list']['description'] = 'This is a list of ciphers that you want (or don\'t want) to use when talking SSL. For a list of ciphers and how to include/exclude them, see sections "CIPHER LIST FORMAT" and "CIPHER STRINGS" on the man-page for ciphers .Default value is: ECDH+AESGCM:ECDH+AES256:!aNULL:!MD5:!DSS:!DH:!AES128 ';
// Added in Froxlor 0.9.31
$lng['panel']['dashboard'] = 'Dashboard';
diff --git a/lng/german.lng.php b/lng/german.lng.php
index f76758cc..c88c43d6 100644
--- a/lng/german.lng.php
+++ b/lng/german.lng.php
@@ -1350,7 +1350,7 @@ $lng['domains']['serveraliasoption_www'] = 'www (www.domain.tld)';
$lng['domains']['serveraliasoption_none'] = 'Kein Alias';
$lng['error']['givendirnotallowed'] = 'Das angegebene Verzeichnis im Feld %s ist nicht erlaubt.';
$lng['serversettings']['ssl']['ssl_cipher_list']['title'] = 'Erlaubte SSL Ciphers festlegen';
-$lng['serversettings']['ssl']['ssl_cipher_list']['description'] = 'Dies ist eine Liste von Ciphers, die genutzt werden sollen (oder auch nicht genutzt werden sollen), wenn eine SSL Verbindung besteht. Eine Liste aller Ciphers und wie diese hinzugefügt/ausgeschlossen werden ist in den Abschnitten "CIPHER LIST FORMAT" und "CIPHER STRINGS" in der man-page für Ciphers zu finden.Standard-Wert ist: ECDH+AESGCM:ECDH+AES256:!aNULL:!MD5:!DSS:!DH:!AES128 ';
+$lng['serversettings']['ssl']['ssl_cipher_list']['description'] = 'Dies ist eine Liste von Ciphers, die genutzt werden sollen (oder auch nicht genutzt werden sollen), wenn eine SSL Verbindung besteht. Eine Liste aller Ciphers und wie diese hinzugefügt/ausgeschlossen werden ist in den Abschnitten "CIPHER LIST FORMAT" und "CIPHER STRINGS" in der man-page für Ciphers zu finden.Standard-Wert ist: ECDH+AESGCM:ECDH+AES256:!aNULL:!MD5:!DSS:!DH:!AES128 ';
// Added in Froxlor 0.9.31
$lng['panel']['dashboard'] = 'Dashboard';
diff --git a/lng/italian.lng.php b/lng/italian.lng.php
index 90d953cd..fd6e21e6 100644
--- a/lng/italian.lng.php
+++ b/lng/italian.lng.php
@@ -1571,7 +1571,7 @@ $lng['domains']['serveraliasoption_www'] = 'WWW (www.dominio.tld)';
$lng['domains']['serveraliasoption_none'] = 'Nessun alias';
$lng['error']['givendirnotallowed'] = 'La cartella fornita nel campo %s non è permessa.';
$lng['serversettings']['ssl']['ssl_cipher_list']['title'] = 'Configura le cifrature SSL permesse';
-$lng['serversettings']['ssl']['ssl_cipher_list']['description'] = 'Questa è una lista di cifrature che vuoi (o non vuoi) usare nelle communicazioni SSL. Per una lista delle cifrature e come includerle od escluderle, vedi le sezioni "CIPHER LIST FORMAT" e "CIPHER STRINGS" sulla man-page per le cifrature .Il valore predefinito è: ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH ';
+$lng['serversettings']['ssl']['ssl_cipher_list']['description'] = 'Questa è una lista di cifrature che vuoi (o non vuoi) usare nelle communicazioni SSL. Per una lista delle cifrature e come includerle od escluderle, vedi le sezioni "CIPHER LIST FORMAT" e "CIPHER STRINGS" sulla man-page per le cifrature .Il valore predefinito è: ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH ';
$lng['panel']['dashboard'] = 'Cruscotto';
$lng['panel']['assigned'] = 'Assegnato';
$lng['panel']['available'] = 'Disponibile';
From 1657af8719ad91af40fb6554bcafc84f30141aa5 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Thu, 3 Oct 2019 12:31:27 +0200
Subject: [PATCH 105/159] updating external libraries prior to release
Signed-off-by: Michael Kaufmann
---
composer.lock | 486 +++++++++++++++++---------------
lib/Froxlor/Cron/CronConfig.php | 2 +-
2 files changed, 267 insertions(+), 221 deletions(-)
diff --git a/composer.lock b/composer.lock
index 21eb30fb..7d7f33b7 100644
--- a/composer.lock
+++ b/composer.lock
@@ -56,16 +56,16 @@
},
{
"name": "monolog/monolog",
- "version": "1.24.0",
+ "version": "1.25.1",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
- "reference": "bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266"
+ "reference": "70e65a5470a42cfec1a7da00d30edb6e617e8dcf"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Seldaek/monolog/zipball/bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266",
- "reference": "bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266",
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/70e65a5470a42cfec1a7da00d30edb6e617e8dcf",
+ "reference": "70e65a5470a42cfec1a7da00d30edb6e617e8dcf",
"shasum": ""
},
"require": {
@@ -130,20 +130,20 @@
"logging",
"psr-3"
],
- "time": "2018-11-05T09:00:11+00:00"
+ "time": "2019-09-06T13:49:17+00:00"
},
{
"name": "phpmailer/phpmailer",
- "version": "v6.0.7",
+ "version": "v6.1.1",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
- "reference": "0c41a36d4508d470e376498c1c0c527aa36a2d59"
+ "reference": "26bd96350b0b2fcbf0ef4e6f0f9cf3528302a9d8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/0c41a36d4508d470e376498c1c0c527aa36a2d59",
- "reference": "0c41a36d4508d470e376498c1c0c527aa36a2d59",
+ "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/26bd96350b0b2fcbf0ef4e6f0f9cf3528302a9d8",
+ "reference": "26bd96350b0b2fcbf0ef4e6f0f9cf3528302a9d8",
"shasum": ""
},
"require": {
@@ -176,17 +176,17 @@
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "LGPL-2.1"
+ "LGPL-2.1-only"
],
"authors": [
- {
- "name": "Jim Jagielski",
- "email": "jimjag@gmail.com"
- },
{
"name": "Marcus Bointon",
"email": "phpmailer@synchromedia.co.uk"
},
+ {
+ "name": "Jim Jagielski",
+ "email": "jimjag@gmail.com"
+ },
{
"name": "Andy Prevost",
"email": "codeworxtech@users.sourceforge.net"
@@ -196,7 +196,7 @@
}
],
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
- "time": "2019-02-01T15:04:28+00:00"
+ "time": "2019-09-27T21:33:43+00:00"
},
{
"name": "psr/log",
@@ -247,16 +247,16 @@
},
{
"name": "robthree/twofactorauth",
- "version": "1.6.6",
+ "version": "1.6.7",
"source": {
"type": "git",
"url": "https://github.com/RobThree/TwoFactorAuth.git",
- "reference": "7477d5d65625b7fe33cb338b98e419d394e9e9fd"
+ "reference": "3407c33775391fa8c36f7d766f26c5e59a736374"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/7477d5d65625b7fe33cb338b98e419d394e9e9fd",
- "reference": "7477d5d65625b7fe33cb338b98e419d394e9e9fd",
+ "url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/3407c33775391fa8c36f7d766f26c5e59a736374",
+ "reference": "3407c33775391fa8c36f7d766f26c5e59a736374",
"shasum": ""
},
"require": {
@@ -294,7 +294,7 @@
"php",
"tfa"
],
- "time": "2019-03-19T21:51:19+00:00"
+ "time": "2019-06-21T08:51:04+00:00"
}
],
"packages-dev": [
@@ -356,16 +356,16 @@
},
{
"name": "myclabs/deep-copy",
- "version": "1.9.1",
+ "version": "1.9.3",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
- "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72"
+ "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72",
- "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/007c053ae6f31bba39dfa19a7726f56e9763bbea",
+ "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea",
"shasum": ""
},
"require": {
@@ -400,20 +400,20 @@
"object",
"object graph"
],
- "time": "2019-04-07T13:18:21+00:00"
+ "time": "2019-08-09T12:45:53+00:00"
},
{
"name": "nikic/php-parser",
- "version": "v4.2.2",
+ "version": "v4.2.4",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "1bd73cc04c3843ad8d6b0bfc0956026a151fc420"
+ "reference": "97e59c7a16464196a8b9c77c47df68e4a39a45c4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bd73cc04c3843ad8d6b0bfc0956026a151fc420",
- "reference": "1bd73cc04c3843ad8d6b0bfc0956026a151fc420",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/97e59c7a16464196a8b9c77c47df68e4a39a45c4",
+ "reference": "97e59c7a16464196a8b9c77c47df68e4a39a45c4",
"shasum": ""
},
"require": {
@@ -421,7 +421,7 @@
"php": ">=7.0"
},
"require-dev": {
- "phpunit/phpunit": "^6.5 || ^7.0"
+ "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0"
},
"bin": [
"bin/php-parse"
@@ -451,7 +451,7 @@
"parser",
"php"
],
- "time": "2019-05-25T20:07:01+00:00"
+ "time": "2019-09-01T07:51:21+00:00"
},
{
"name": "pdepend/pdepend",
@@ -597,16 +597,16 @@
},
{
"name": "phpcompatibility/php-compatibility",
- "version": "9.1.1",
+ "version": "9.3.1",
"source": {
"type": "git",
"url": "https://github.com/PHPCompatibility/PHPCompatibility.git",
- "reference": "2b63c5d284ab8857f7b1d5c240ddb507a6b2293c"
+ "reference": "9999344e47e7af6b00e1a898eacc4e4368fb7196"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/2b63c5d284ab8857f7b1d5c240ddb507a6b2293c",
- "reference": "2b63c5d284ab8857f7b1d5c240ddb507a6b2293c",
+ "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9999344e47e7af6b00e1a898eacc4e4368fb7196",
+ "reference": "9999344e47e7af6b00e1a898eacc4e4368fb7196",
"shasum": ""
},
"require": {
@@ -620,7 +620,7 @@
"phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0"
},
"suggest": {
- "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.",
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.",
"roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues."
},
"type": "phpcodesniffer-standard",
@@ -629,10 +629,6 @@
"LGPL-3.0-or-later"
],
"authors": [
- {
- "name": "Contributors",
- "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors"
- },
{
"name": "Wim Godden",
"homepage": "https://github.com/wimg",
@@ -642,6 +638,10 @@
"name": "Juliette Reinders Folmer",
"homepage": "https://github.com/jrfnl",
"role": "lead"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors"
}
],
"description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.",
@@ -651,39 +651,37 @@
"phpcs",
"standards"
],
- "time": "2018-12-30T23:16:27+00:00"
+ "time": "2019-09-05T18:36:49+00:00"
},
{
"name": "phpdocumentor/reflection-common",
- "version": "1.0.1",
+ "version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
- "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6"
+ "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
- "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a",
+ "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a",
"shasum": ""
},
"require": {
- "php": ">=5.5"
+ "php": ">=7.1"
},
"require-dev": {
- "phpunit/phpunit": "^4.6"
+ "phpunit/phpunit": "~6"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0.x-dev"
+ "dev-master": "2.x-dev"
}
},
"autoload": {
"psr-4": {
- "phpDocumentor\\Reflection\\": [
- "src"
- ]
+ "phpDocumentor\\Reflection\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -705,30 +703,30 @@
"reflection",
"static analysis"
],
- "time": "2017-09-11T18:02:19+00:00"
+ "time": "2018-08-07T13:53:10+00:00"
},
{
"name": "phpdocumentor/reflection-docblock",
- "version": "4.3.1",
+ "version": "4.3.2",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
- "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c"
+ "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c",
- "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/b83ff7cfcfee7827e1e78b637a5904fe6a96698e",
+ "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e",
"shasum": ""
},
"require": {
"php": "^7.0",
- "phpdocumentor/reflection-common": "^1.0.0",
- "phpdocumentor/type-resolver": "^0.4.0",
+ "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0",
+ "phpdocumentor/type-resolver": "~0.4 || ^1.0.0",
"webmozart/assert": "^1.0"
},
"require-dev": {
- "doctrine/instantiator": "~1.0.5",
+ "doctrine/instantiator": "^1.0.5",
"mockery/mockery": "^1.0",
"phpunit/phpunit": "^6.4"
},
@@ -756,41 +754,40 @@
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
- "time": "2019-04-30T17:48:53+00:00"
+ "time": "2019-09-12T14:27:41+00:00"
},
{
"name": "phpdocumentor/type-resolver",
- "version": "0.4.0",
+ "version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
- "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7"
+ "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7",
- "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7",
+ "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/2e32a6d48972b2c1976ed5d8967145b6cec4a4a9",
+ "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9",
"shasum": ""
},
"require": {
- "php": "^5.5 || ^7.0",
- "phpdocumentor/reflection-common": "^1.0"
+ "php": "^7.1",
+ "phpdocumentor/reflection-common": "^2.0"
},
"require-dev": {
- "mockery/mockery": "^0.9.4",
- "phpunit/phpunit": "^5.2||^4.8.24"
+ "ext-tokenizer": "^7.1",
+ "mockery/mockery": "~1",
+ "phpunit/phpunit": "^7.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0.x-dev"
+ "dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
- "phpDocumentor\\Reflection\\": [
- "src/"
- ]
+ "phpDocumentor\\Reflection\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -803,7 +800,8 @@
"email": "me@mikevanriel.com"
}
],
- "time": "2017-07-14T14:27:02+00:00"
+ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
+ "time": "2019-08-22T18:11:29+00:00"
},
{
"name": "phploc/phploc",
@@ -856,16 +854,16 @@
},
{
"name": "phpmd/phpmd",
- "version": "2.6.0",
+ "version": "2.7.0",
"source": {
"type": "git",
"url": "https://github.com/phpmd/phpmd.git",
- "reference": "4e9924b2c157a3eb64395460fcf56b31badc8374"
+ "reference": "a05a999c644f4bc9a204846017db7bb7809fbe4c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpmd/phpmd/zipball/4e9924b2c157a3eb64395460fcf56b31badc8374",
- "reference": "4e9924b2c157a3eb64395460fcf56b31badc8374",
+ "url": "https://api.github.com/repos/phpmd/phpmd/zipball/a05a999c644f4bc9a204846017db7bb7809fbe4c",
+ "reference": "a05a999c644f4bc9a204846017db7bb7809fbe4c",
"shasum": ""
},
"require": {
@@ -874,13 +872,15 @@
"php": ">=5.3.9"
},
"require-dev": {
- "phpunit/phpunit": "^4.0",
+ "gregwar/rst": "^1.0",
+ "mikey179/vfsstream": "^1.6.4",
+ "phpunit/phpunit": "^4.8.36 || ^5.7.27",
"squizlabs/php_codesniffer": "^2.0"
},
"bin": [
"src/bin/phpmd"
],
- "type": "project",
+ "type": "library",
"autoload": {
"psr-0": {
"PHPMD\\": "src/main/php"
@@ -897,20 +897,20 @@
"homepage": "https://github.com/manuelpichler",
"role": "Project Founder"
},
- {
- "name": "Other contributors",
- "homepage": "https://github.com/phpmd/phpmd/graphs/contributors",
- "role": "Contributors"
- },
{
"name": "Marc Würth",
"email": "ravage@bluewin.ch",
"homepage": "https://github.com/ravage84",
"role": "Project Maintainer"
+ },
+ {
+ "name": "Other contributors",
+ "homepage": "https://github.com/phpmd/phpmd/graphs/contributors",
+ "role": "Contributors"
}
],
"description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.",
- "homepage": "http://phpmd.org/",
+ "homepage": "https://phpmd.org/",
"keywords": [
"mess detection",
"mess detector",
@@ -918,20 +918,20 @@
"phpmd",
"pmd"
],
- "time": "2017-01-20T14:41:10+00:00"
+ "time": "2019-07-30T21:13:32+00:00"
},
{
"name": "phpspec/prophecy",
- "version": "1.8.0",
+ "version": "1.8.1",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
- "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06"
+ "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06",
- "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06",
+ "url": "https://api.github.com/repos/phpspec/prophecy/zipball/1927e75f4ed19131ec9bcc3b002e07fb1173ee76",
+ "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76",
"shasum": ""
},
"require": {
@@ -952,8 +952,8 @@
}
},
"autoload": {
- "psr-0": {
- "Prophecy\\": "src/"
+ "psr-4": {
+ "Prophecy\\": "src/Prophecy"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -981,20 +981,20 @@
"spy",
"stub"
],
- "time": "2018-08-05T17:53:17+00:00"
+ "time": "2019-06-13T12:50:23+00:00"
},
{
"name": "phpunit/php-code-coverage",
- "version": "7.0.4",
+ "version": "7.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "6024c8a6cb962d496b7bd049ed8f48473824176d"
+ "reference": "aa0d179a13284c7420fc281fc32750e6cc7c9e2f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6024c8a6cb962d496b7bd049ed8f48473824176d",
- "reference": "6024c8a6cb962d496b7bd049ed8f48473824176d",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aa0d179a13284c7420fc281fc32750e6cc7c9e2f",
+ "reference": "aa0d179a13284c7420fc281fc32750e6cc7c9e2f",
"shasum": ""
},
"require": {
@@ -1003,17 +1003,17 @@
"php": "^7.2",
"phpunit/php-file-iterator": "^2.0.2",
"phpunit/php-text-template": "^1.2.1",
- "phpunit/php-token-stream": "^3.0.1",
+ "phpunit/php-token-stream": "^3.1.1",
"sebastian/code-unit-reverse-lookup": "^1.0.1",
- "sebastian/environment": "^4.1",
+ "sebastian/environment": "^4.2.2",
"sebastian/version": "^2.0.1",
- "theseer/tokenizer": "^1.1"
+ "theseer/tokenizer": "^1.1.3"
},
"require-dev": {
- "phpunit/phpunit": "^8.0"
+ "phpunit/phpunit": "^8.2.2"
},
"suggest": {
- "ext-xdebug": "^2.6.1"
+ "ext-xdebug": "^2.7.2"
},
"type": "library",
"extra": {
@@ -1044,7 +1044,7 @@
"testing",
"xunit"
],
- "time": "2019-05-29T09:59:31+00:00"
+ "time": "2019-09-17T06:24:36+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -1139,16 +1139,16 @@
},
{
"name": "phpunit/php-timer",
- "version": "2.1.1",
+ "version": "2.1.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
- "reference": "8b389aebe1b8b0578430bda0c7c95a829608e059"
+ "reference": "1038454804406b0b5f5f520358e78c1c2f71501e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b389aebe1b8b0578430bda0c7c95a829608e059",
- "reference": "8b389aebe1b8b0578430bda0c7c95a829608e059",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e",
+ "reference": "1038454804406b0b5f5f520358e78c1c2f71501e",
"shasum": ""
},
"require": {
@@ -1184,20 +1184,20 @@
"keywords": [
"timer"
],
- "time": "2019-02-20T10:12:59+00:00"
+ "time": "2019-06-07T04:22:29+00:00"
},
{
"name": "phpunit/php-token-stream",
- "version": "3.0.1",
+ "version": "3.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
- "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18"
+ "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c99e3be9d3e85f60646f152f9002d46ed7770d18",
- "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/995192df77f63a59e47f025390d2d1fdf8f425ff",
+ "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff",
"shasum": ""
},
"require": {
@@ -1210,7 +1210,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.0-dev"
+ "dev-master": "3.1-dev"
}
},
"autoload": {
@@ -1233,46 +1233,47 @@
"keywords": [
"tokenizer"
],
- "time": "2018-10-30T05:52:18+00:00"
+ "time": "2019-09-17T06:23:10+00:00"
},
{
"name": "phpunit/phpunit",
- "version": "8.1.6",
+ "version": "8.3.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "e3c9da6e645492c461e0a11eca117f83f4f4c840"
+ "reference": "302faed7059fde575cf3403a78c730c5e3a62750"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e3c9da6e645492c461e0a11eca117f83f4f4c840",
- "reference": "e3c9da6e645492c461e0a11eca117f83f4f4c840",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/302faed7059fde575cf3403a78c730c5e3a62750",
+ "reference": "302faed7059fde575cf3403a78c730c5e3a62750",
"shasum": ""
},
"require": {
- "doctrine/instantiator": "^1.1",
+ "doctrine/instantiator": "^1.2.0",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
- "myclabs/deep-copy": "^1.7",
- "phar-io/manifest": "^1.0.2",
- "phar-io/version": "^2.0",
+ "myclabs/deep-copy": "^1.9.1",
+ "phar-io/manifest": "^1.0.3",
+ "phar-io/version": "^2.0.1",
"php": "^7.2",
- "phpspec/prophecy": "^1.7",
- "phpunit/php-code-coverage": "^7.0",
- "phpunit/php-file-iterator": "^2.0.1",
+ "phpspec/prophecy": "^1.8.1",
+ "phpunit/php-code-coverage": "^7.0.7",
+ "phpunit/php-file-iterator": "^2.0.2",
"phpunit/php-text-template": "^1.2.1",
- "phpunit/php-timer": "^2.1",
- "sebastian/comparator": "^3.0",
- "sebastian/diff": "^3.0",
- "sebastian/environment": "^4.1",
- "sebastian/exporter": "^3.1",
- "sebastian/global-state": "^3.0",
+ "phpunit/php-timer": "^2.1.2",
+ "sebastian/comparator": "^3.0.2",
+ "sebastian/diff": "^3.0.2",
+ "sebastian/environment": "^4.2.2",
+ "sebastian/exporter": "^3.1.1",
+ "sebastian/global-state": "^3.0.0",
"sebastian/object-enumerator": "^3.0.3",
- "sebastian/resource-operations": "^2.0",
+ "sebastian/resource-operations": "^2.0.1",
+ "sebastian/type": "^1.1.3",
"sebastian/version": "^2.0.1"
},
"require-dev": {
@@ -1281,7 +1282,7 @@
"suggest": {
"ext-soap": "*",
"ext-xdebug": "*",
- "phpunit/php-invoker": "^2.0"
+ "phpunit/php-invoker": "^2.0.0"
},
"bin": [
"phpunit"
@@ -1289,7 +1290,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "8.1-dev"
+ "dev-master": "8.3-dev"
}
},
"autoload": {
@@ -1315,7 +1316,7 @@
"testing",
"xunit"
],
- "time": "2019-05-28T11:53:42+00:00"
+ "time": "2019-09-14T09:12:03+00:00"
},
{
"name": "psr/container",
@@ -1586,16 +1587,16 @@
},
{
"name": "sebastian/exporter",
- "version": "3.1.0",
+ "version": "3.1.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
- "reference": "234199f4528de6d12aaa58b612e98f7d36adb937"
+ "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937",
- "reference": "234199f4528de6d12aaa58b612e98f7d36adb937",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e",
+ "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e",
"shasum": ""
},
"require": {
@@ -1622,6 +1623,10 @@
"BSD-3-Clause"
],
"authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
@@ -1630,17 +1635,13 @@
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
- {
- "name": "Bernhard Schussek",
- "email": "bschussek@2bepublished.at"
- },
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- },
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
}
],
"description": "Provides the functionality to export PHP variables for visualization",
@@ -1649,7 +1650,7 @@
"export",
"exporter"
],
- "time": "2017-04-03T13:19:02+00:00"
+ "time": "2019-09-14T09:02:43+00:00"
},
{
"name": "sebastian/finder-facade",
@@ -1982,6 +1983,52 @@
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
"time": "2018-10-04T04:07:39+00:00"
},
+ {
+ "name": "sebastian/type",
+ "version": "1.1.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/type.git",
+ "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/3aaaa15fa71d27650d62a948be022fe3b48541a3",
+ "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^8.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Collection of value objects that represent the types of the PHP type system",
+ "homepage": "https://github.com/sebastianbergmann/type",
+ "time": "2019-07-02T08:10:15+00:00"
+ },
{
"name": "sebastian/version",
"version": "2.0.1",
@@ -2027,16 +2074,16 @@
},
{
"name": "squizlabs/php_codesniffer",
- "version": "3.4.2",
+ "version": "3.5.0",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
- "reference": "b8a7362af1cc1aadb5bd36c3defc4dda2cf5f0a8"
+ "reference": "0afebf16a2e7f1e434920fa976253576151effe9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/b8a7362af1cc1aadb5bd36c3defc4dda2cf5f0a8",
- "reference": "b8a7362af1cc1aadb5bd36c3defc4dda2cf5f0a8",
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/0afebf16a2e7f1e434920fa976253576151effe9",
+ "reference": "0afebf16a2e7f1e434920fa976253576151effe9",
"shasum": ""
},
"require": {
@@ -2074,20 +2121,20 @@
"phpcs",
"standards"
],
- "time": "2019-04-10T23:49:02+00:00"
+ "time": "2019-09-26T23:12:26+00:00"
},
{
"name": "symfony/config",
- "version": "v4.3.0",
+ "version": "v4.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
- "reference": "5455fc0ae8b46269b83a22949429ea878496408c"
+ "reference": "07d49c0f823e0bc367c6d84e35b61419188a5ece"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/config/zipball/5455fc0ae8b46269b83a22949429ea878496408c",
- "reference": "5455fc0ae8b46269b83a22949429ea878496408c",
+ "url": "https://api.github.com/repos/symfony/config/zipball/07d49c0f823e0bc367c6d84e35b61419188a5ece",
+ "reference": "07d49c0f823e0bc367c6d84e35b61419188a5ece",
"shasum": ""
},
"require": {
@@ -2138,20 +2185,20 @@
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
- "time": "2019-05-20T16:16:12+00:00"
+ "time": "2019-08-26T08:26:39+00:00"
},
{
"name": "symfony/console",
- "version": "v4.3.0",
+ "version": "v4.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "707b619d2c3bedf0224d56f95f77dabc60102305"
+ "reference": "de63799239b3881b8a08f8481b22348f77ed7b36"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/707b619d2c3bedf0224d56f95f77dabc60102305",
- "reference": "707b619d2c3bedf0224d56f95f77dabc60102305",
+ "url": "https://api.github.com/repos/symfony/console/zipball/de63799239b3881b8a08f8481b22348f77ed7b36",
+ "reference": "de63799239b3881b8a08f8481b22348f77ed7b36",
"shasum": ""
},
"require": {
@@ -2213,26 +2260,26 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
- "time": "2019-05-27T08:16:38+00:00"
+ "time": "2019-08-26T08:26:39+00:00"
},
{
"name": "symfony/dependency-injection",
- "version": "v4.3.0",
+ "version": "v4.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/dependency-injection.git",
- "reference": "aa6fe799fa5adc938fc55aeccd2f5fb0aa0b8eac"
+ "reference": "d3ad14b66ac773ba6123622eb9b5b010165fe3d9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/aa6fe799fa5adc938fc55aeccd2f5fb0aa0b8eac",
- "reference": "aa6fe799fa5adc938fc55aeccd2f5fb0aa0b8eac",
+ "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/d3ad14b66ac773ba6123622eb9b5b010165fe3d9",
+ "reference": "d3ad14b66ac773ba6123622eb9b5b010165fe3d9",
"shasum": ""
},
"require": {
"php": "^7.1.3",
"psr/container": "^1.0",
- "symfony/service-contracts": "^1.1.2"
+ "symfony/service-contracts": "^1.1.6"
},
"conflict": {
"symfony/config": "<4.3",
@@ -2286,20 +2333,20 @@
],
"description": "Symfony DependencyInjection Component",
"homepage": "https://symfony.com",
- "time": "2019-05-28T07:50:59+00:00"
+ "time": "2019-08-26T16:27:33+00:00"
},
{
"name": "symfony/filesystem",
- "version": "v4.3.0",
+ "version": "v4.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "988ab7d70c267c34efa85772ca20de3fad11c74b"
+ "reference": "9abbb7ef96a51f4d7e69627bc6f63307994e4263"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/988ab7d70c267c34efa85772ca20de3fad11c74b",
- "reference": "988ab7d70c267c34efa85772ca20de3fad11c74b",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/9abbb7ef96a51f4d7e69627bc6f63307994e4263",
+ "reference": "9abbb7ef96a51f4d7e69627bc6f63307994e4263",
"shasum": ""
},
"require": {
@@ -2336,20 +2383,20 @@
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
- "time": "2019-05-24T12:50:04+00:00"
+ "time": "2019-08-20T14:07:54+00:00"
},
{
"name": "symfony/finder",
- "version": "v4.3.0",
+ "version": "v4.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176"
+ "reference": "86c1c929f0a4b24812e1eb109262fc3372c8e9f2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176",
- "reference": "b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/86c1c929f0a4b24812e1eb109262fc3372c8e9f2",
+ "reference": "86c1c929f0a4b24812e1eb109262fc3372c8e9f2",
"shasum": ""
},
"require": {
@@ -2385,20 +2432,20 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
- "time": "2019-05-26T20:47:49+00:00"
+ "time": "2019-08-14T12:26:46+00:00"
},
{
"name": "symfony/polyfill-ctype",
- "version": "v1.11.0",
+ "version": "v1.12.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
- "reference": "82ebae02209c21113908c229e9883c419720738a"
+ "reference": "550ebaac289296ce228a706d0867afc34687e3f4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a",
- "reference": "82ebae02209c21113908c229e9883c419720738a",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4",
+ "reference": "550ebaac289296ce228a706d0867afc34687e3f4",
"shasum": ""
},
"require": {
@@ -2410,7 +2457,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.11-dev"
+ "dev-master": "1.12-dev"
}
},
"autoload": {
@@ -2426,13 +2473,13 @@
"MIT"
],
"authors": [
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- },
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
@@ -2443,20 +2490,20 @@
"polyfill",
"portable"
],
- "time": "2019-02-06T07:57:58+00:00"
+ "time": "2019-08-06T08:03:45+00:00"
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.11.0",
+ "version": "v1.12.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "fe5e94c604826c35a32fa832f35bd036b6799609"
+ "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609",
- "reference": "fe5e94c604826c35a32fa832f35bd036b6799609",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b42a2f66e8f1b15ccf25652c3424265923eb4f17",
+ "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17",
"shasum": ""
},
"require": {
@@ -2468,7 +2515,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.11-dev"
+ "dev-master": "1.12-dev"
}
},
"autoload": {
@@ -2502,20 +2549,20 @@
"portable",
"shim"
],
- "time": "2019-02-06T07:57:58+00:00"
+ "time": "2019-08-06T08:03:45+00:00"
},
{
"name": "symfony/polyfill-php73",
- "version": "v1.11.0",
+ "version": "v1.12.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php73.git",
- "reference": "d1fb4abcc0c47be136208ad9d68bf59f1ee17abd"
+ "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/d1fb4abcc0c47be136208ad9d68bf59f1ee17abd",
- "reference": "d1fb4abcc0c47be136208ad9d68bf59f1ee17abd",
+ "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/2ceb49eaccb9352bff54d22570276bb75ba4a188",
+ "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188",
"shasum": ""
},
"require": {
@@ -2524,7 +2571,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.11-dev"
+ "dev-master": "1.12-dev"
}
},
"autoload": {
@@ -2560,27 +2607,27 @@
"portable",
"shim"
],
- "time": "2019-02-06T07:57:58+00:00"
+ "time": "2019-08-06T08:03:45+00:00"
},
{
"name": "symfony/service-contracts",
- "version": "v1.1.2",
+ "version": "v1.1.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
- "reference": "191afdcb5804db960d26d8566b7e9a2843cab3a0"
+ "reference": "ea7263d6b6d5f798b56a45a5b8d686725f2719a3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/service-contracts/zipball/191afdcb5804db960d26d8566b7e9a2843cab3a0",
- "reference": "191afdcb5804db960d26d8566b7e9a2843cab3a0",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/ea7263d6b6d5f798b56a45a5b8d686725f2719a3",
+ "reference": "ea7263d6b6d5f798b56a45a5b8d686725f2719a3",
"shasum": ""
},
"require": {
- "php": "^7.1.3"
+ "php": "^7.1.3",
+ "psr/container": "^1.0"
},
"suggest": {
- "psr/container": "",
"symfony/service-implementation": ""
},
"type": "library",
@@ -2618,7 +2665,7 @@
"interoperability",
"standards"
],
- "time": "2019-05-28T07:50:59+00:00"
+ "time": "2019-08-20T14:44:19+00:00"
},
{
"name": "theseer/directoryscanner",
@@ -2800,16 +2847,16 @@
},
{
"name": "theseer/tokenizer",
- "version": "1.1.2",
+ "version": "1.1.3",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
- "reference": "1c42705be2b6c1de5904f8afacef5895cab44bf8"
+ "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/theseer/tokenizer/zipball/1c42705be2b6c1de5904f8afacef5895cab44bf8",
- "reference": "1c42705be2b6c1de5904f8afacef5895cab44bf8",
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9",
+ "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9",
"shasum": ""
},
"require": {
@@ -2836,20 +2883,20 @@
}
],
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
- "time": "2019-04-04T09:56:43+00:00"
+ "time": "2019-06-13T22:48:21+00:00"
},
{
"name": "webmozart/assert",
- "version": "1.4.0",
+ "version": "1.5.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/assert.git",
- "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9"
+ "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9",
- "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9",
+ "url": "https://api.github.com/repos/webmozart/assert/zipball/88e6d84706d09a236046d686bbea96f07b3a34f4",
+ "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4",
"shasum": ""
},
"require": {
@@ -2857,8 +2904,7 @@
"symfony/polyfill-ctype": "^1.8"
},
"require-dev": {
- "phpunit/phpunit": "^4.6",
- "sebastian/version": "^1.0.1"
+ "phpunit/phpunit": "^4.8.36 || ^7.5.13"
},
"type": "library",
"extra": {
@@ -2887,7 +2933,7 @@
"check",
"validate"
],
- "time": "2018-12-25T11:19:39+00:00"
+ "time": "2019-08-24T08:43:50+00:00"
}
],
"aliases": [],
diff --git a/lib/Froxlor/Cron/CronConfig.php b/lib/Froxlor/Cron/CronConfig.php
index 18b2f8d8..5c8e5cfc 100644
--- a/lib/Froxlor/Cron/CronConfig.php
+++ b/lib/Froxlor/Cron/CronConfig.php
@@ -102,7 +102,7 @@ class CronConfig
$binpath = "/usr/bin/nice -n 5 /usr/bin/php5 -q";
}
- $cronfile .= "root " . $binpath . " " . \Froxlor\Froxlor::getInstallDir() . "/scripts/froxlor_master_cronjob.php --" . $row_cronentry['cronfile'] . " 1> /dev/null\n";
+ $cronfile .= "root " . $binpath . " " . \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . "/scripts/froxlor_master_cronjob.php") . " --" . $row_cronentry['cronfile'] . " 1> /dev/null\n";
}
}
From 4b555b4ef2a97454fb16cc84a6272d7ea66b44ae Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Thu, 3 Oct 2019 12:35:42 +0200
Subject: [PATCH 106/159] set version to 0.10.0 for upcoming stable release
Signed-off-by: Michael Kaufmann
---
install/froxlor.sql | 2 +-
install/updates/froxlor/0.10/update_0.10.inc.php | 4 ++++
lib/Froxlor/Froxlor.php | 2 +-
3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/install/froxlor.sql b/install/froxlor.sql
index a000ed3e..c1ca6cf6 100644
--- a/install/froxlor.sql
+++ b/install/froxlor.sql
@@ -682,7 +682,7 @@ opcache.interned_strings_buffer'),
('panel', 'password_special_char', '!?<>§$%+#=@'),
('panel', 'customer_hide_options', ''),
('panel', 'is_configured', '0'),
- ('panel', 'version', '0.10.0-rc2'),
+ ('panel', 'version', '0.10.0'),
('panel', 'db_version', '201909150');
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 435fc0b1..18d11225 100644
--- a/install/updates/froxlor/0.10/update_0.10.inc.php
+++ b/install/updates/froxlor/0.10/update_0.10.inc.php
@@ -312,3 +312,7 @@ if (\Froxlor\Froxlor::isDatabaseVersion('201907270')) {
\Froxlor\Froxlor::updateToDbVersion('201909150');
}
+
+if (\Froxlor\Froxlor::isFroxlorVersion('0.10.0-rc2')) {
+ \Froxlor\Froxlor::updateToVersion('0.10.0');
+}
diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php
index f9a63b59..28262162 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.0-rc2';
+ const VERSION = '0.10.0';
// Database version (YYYYMMDDC where C is a daily counter)
const DBVERSION = '201909150';
From eb5ea51da1980c0e80b7ca48a393636bd13f4e67 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Thu, 3 Oct 2019 14:37:07 +0200
Subject: [PATCH 107/159] add explicit tlsv1.3 ciphersuite setting (used for
apache-only as of now)
---
actions/admin/settings/131.ssl.php | 10 ++++++++++
install/froxlor.sql | 3 ++-
install/updates/froxlor/0.10/update_0.10.inc.php | 9 +++++++++
lib/Froxlor/Cron/Http/Apache.php | 8 ++++++++
lib/Froxlor/Froxlor.php | 2 +-
lng/english.lng.php | 3 +++
lng/german.lng.php | 3 +++
7 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/actions/admin/settings/131.ssl.php b/actions/admin/settings/131.ssl.php
index a9f3c091..520a0b59 100644
--- a/actions/admin/settings/131.ssl.php
+++ b/actions/admin/settings/131.ssl.php
@@ -54,6 +54,16 @@ return array(
'default' => 'ECDH+AESGCM:ECDH+AES256:!aNULL:!MD5:!DSS:!DH:!AES128',
'save_method' => 'storeSettingField'
),
+ 'system_tlsv13_cipher_list' => array(
+ 'label' => $lng['serversettings']['ssl']['tlsv13_cipher_list'],
+ 'settinggroup' => 'system',
+ 'varname' => 'tlsv13_cipher_list',
+ 'type' => 'string',
+ 'string_emptyallowed' => true,
+ 'default' => '',
+ 'visible' => \Froxlor\Settings::Get('system.webserver') == "apache2" && \Froxlor\Settings::Get('system.apache24') == 1,
+ 'save_method' => 'storeSettingField',
+ ),
'system_ssl_cert_file' => array(
'label' => $lng['serversettings']['ssl']['ssl_cert_file'],
'settinggroup' => 'system',
diff --git a/install/froxlor.sql b/install/froxlor.sql
index c1ca6cf6..b150ab48 100644
--- a/install/froxlor.sql
+++ b/install/froxlor.sql
@@ -640,6 +640,7 @@ opcache.interned_strings_buffer'),
('system', 'nssextrausers', '0'),
('system', 'disable_le_selfcheck', '0'),
('system', 'ssl_protocols', 'TLSv1,TLSv1.2'),
+ ('system', 'tlsv13_cipher_list', ''),
('system', 'logfiles_format', ''),
('system', 'logfiles_type', '1'),
('system', 'logfiles_piped', '0'),
@@ -683,7 +684,7 @@ opcache.interned_strings_buffer'),
('panel', 'customer_hide_options', ''),
('panel', 'is_configured', '0'),
('panel', 'version', '0.10.0'),
- ('panel', 'db_version', '201909150');
+ ('panel', 'db_version', '201910030');
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 18d11225..a2469065 100644
--- a/install/updates/froxlor/0.10/update_0.10.inc.php
+++ b/install/updates/froxlor/0.10/update_0.10.inc.php
@@ -316,3 +316,12 @@ if (\Froxlor\Froxlor::isDatabaseVersion('201907270')) {
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.0-rc2')) {
\Froxlor\Froxlor::updateToVersion('0.10.0');
}
+
+if (\Froxlor\Froxlor::isDatabaseVersion('201909150')) {
+
+ showUpdateStep("Adding TLSv1.3-cipherlist setting");
+ Settings::AddNew("system.tlsv13_cipher_list", '');
+ lastStepStatus(0);
+
+ \Froxlor\Froxlor::updateToDbVersion('201910030');
+}
diff --git a/lib/Froxlor/Cron/Http/Apache.php b/lib/Froxlor/Cron/Http/Apache.php
index dec06991..1e13dc32 100644
--- a/lib/Froxlor/Cron/Http/Apache.php
+++ b/lib/Froxlor/Cron/Http/Apache.php
@@ -477,6 +477,10 @@ class Apache extends HttpConfigBase
// this makes it more secure, thx to Marcel (08/2013)
$this->virtualhosts_data[$vhosts_filename] .= ' SSLHonorCipherOrder On' . "\n";
$this->virtualhosts_data[$vhosts_filename] .= ' SSLCipherSuite ' . Settings::Get('system.ssl_cipher_list') . "\n";
+ $protocols = array_map('trim', explode(",", Settings::Get('system.ssl_protocols')));
+ if (in_array("TLSv1.3", $protocols) && !empty(Settings::Get('system.tlsv13_cipher_list')) && Settings::Get('system.apache24') == 1) {
+ $this->virtualhosts_data[$vhosts_filename] .= ' SSLCipherSuite TLSv1.3 ' . Settings::Get('system.tlsv13_cipher_list') . "\n";
+ }
$this->virtualhosts_data[$vhosts_filename] .= ' SSLVerifyDepth 10' . "\n";
$this->virtualhosts_data[$vhosts_filename] .= ' SSLCertificateFile ' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_cert_file']) . "\n";
@@ -973,6 +977,10 @@ class Apache extends HttpConfigBase
// this makes it more secure, thx to Marcel (08/2013)
$vhost_content .= ' SSLHonorCipherOrder On' . "\n";
$vhost_content .= ' SSLCipherSuite ' . Settings::Get('system.ssl_cipher_list') . "\n";
+ $protocols = array_map('trim', explode(",", Settings::Get('system.ssl_protocols')));
+ if (in_array("TLSv1.3", $protocols) && !empty(Settings::Get('system.tlsv13_cipher_list')) && Settings::Get('system.apache24') == 1) {
+ $vhost_content .= ' SSLCipherSuite TLSv1.3 ' . Settings::Get('system.tlsv13_cipher_list') . "\n";
+ }
$vhost_content .= ' SSLVerifyDepth 10' . "\n";
$vhost_content .= ' SSLCertificateFile ' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_cert_file']) . "\n";
diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php
index 28262162..6abe1274 100644
--- a/lib/Froxlor/Froxlor.php
+++ b/lib/Froxlor/Froxlor.php
@@ -10,7 +10,7 @@ final class Froxlor
const VERSION = '0.10.0';
// Database version (YYYYMMDDC where C is a daily counter)
- const DBVERSION = '201909150';
+ const DBVERSION = '201910030';
// Distribution branding-tag (used for Debian etc.)
const BRANDING = '';
diff --git a/lng/english.lng.php b/lng/english.lng.php
index 84c992e4..66c1debb 100644
--- a/lng/english.lng.php
+++ b/lng/english.lng.php
@@ -2066,3 +2066,6 @@ $lng['serversettings']['letsencryptecc']['title'] = "Issue ECC / ECDSA certifica
$lng['serversettings']['letsencryptecc']['description'] = "If set to a valid key-size the certificate issued will use ECC / ECDSA";
$lng['serversettings']['froxloraliases']['title'] = "Domain aliases for froxlor vhost";
$lng['serversettings']['froxloraliases']['description'] = "Comma separated list of domains to add as server alias to the froxlor vhost";
+
+$lng['serversettings']['ssl']['tlsv13_cipher_list']['title'] = 'Configure explicit TLSv1.3 ciphers if used';
+$lng['serversettings']['ssl']['tlsv13_cipher_list']['description'] = 'This is a list of ciphers that you want (or don\'t want) to use when talking TLSv1.3. For a list of ciphers and how to include/exclude them, see the docs for TLSv1.3 .Default value is empty ';
diff --git a/lng/german.lng.php b/lng/german.lng.php
index c88c43d6..0e012d30 100644
--- a/lng/german.lng.php
+++ b/lng/german.lng.php
@@ -1713,3 +1713,6 @@ $lng['serversettings']['letsencryptecc']['title'] = "ECC / ECDSA Zertifikate aus
$lng['serversettings']['letsencryptecc']['description'] = "Wenn eine Schlüsselgröße ausgewählt wird, werden ECC / ECDSA Zertifikate erstellt";
$lng['serversettings']['froxloraliases']['title'] = "Domain Aliase für Froxlor Vhost";
$lng['serversettings']['froxloraliases']['description'] = "Komma getrennte Liste von Domains, welche als Server Alias zum Froxlor Vhost hinzugefügt werden";
+
+$lng['serversettings']['ssl']['tlsv13_cipher_list']['title'] = 'Explizite TLSv1.3 Ciphers, wenn genutzt';
+$lng['serversettings']['ssl']['tlsv13_cipher_list']['description'] = 'Dies ist eine Liste von Ciphers, die genutzt werden sollen (oder auch nicht genutzt werden sollen), wenn eine TLSv1.3 Verbindung hergestellt werden soll. Eine Liste aller Ciphers und wie diese hinzugefügt/ausgeschlossen werden ist der Dokumentation für TLSv1.3 zu entnehmen.Standard-Wert ist leer ';
From 4d52c6b6d0e0ffa7bec17245df922dc9dd95e88f Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Fri, 4 Oct 2019 21:48:10 +0200
Subject: [PATCH 108/159] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index d9d5a83d..affecf3e 100644
--- a/README.md
+++ b/README.md
@@ -54,7 +54,7 @@ https://files.froxlor.org/releases/froxlor-latest.tar.gz [MD5](https://files.fro
[HowTo](https://github.com/Froxlor/Froxlor/wiki/Install-froxlor-on-debian)
/etc/apt/sources.list.d/froxlor.list
-> deb http://debian.froxlor.org {wheezy|jessie|stretch} main
+> deb http://debian.froxlor.org {stretch|buster} main
### Gentoo repository
From 05d66c034efd58d8d1c868742036a50a647d3522 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Sun, 6 Oct 2019 09:04:18 +0200
Subject: [PATCH 109/159] update min-required version of php in composer.json
Signed-off-by: Michael Kaufmann
---
composer.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/composer.json b/composer.json
index 2b715393..9312338c 100644
--- a/composer.json
+++ b/composer.json
@@ -30,7 +30,7 @@
"docs": "https://github.com/Froxlor/Froxlor/wiki"
},
"require": {
- "php": ">=5.6",
+ "php": ">=7.0",
"ext-session": "*",
"ext-ctype": "*",
"ext-pdo": "*",
From fa3e3da7ac263804f299532fdad12f6173ff539a Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Sun, 6 Oct 2019 14:47:04 +0200
Subject: [PATCH 110/159] only flush privileges if anything at all happened
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Api/Commands/Customers.php | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/lib/Froxlor/Api/Commands/Customers.php b/lib/Froxlor/Api/Commands/Customers.php
index 34f386bf..1fb82107 100644
--- a/lib/Froxlor/Api/Commands/Customers.php
+++ b/lib/Froxlor/Api/Commands/Customers.php
@@ -1067,6 +1067,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$dbm = new \Froxlor\Database\DbManager($this->logger());
// For each of them
+ $priv_changed = false;
while ($row_database = $databases_stmt->fetch(\PDO::FETCH_ASSOC)) {
if ($last_dbserver != $row_database['dbserver']) {
@@ -1087,10 +1088,13 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$dbm->getManager()->enableUser($row_database['databasename'], $mysql_access_host);
}
}
+ $priv_changed = true;
}
// At last flush the new privileges
- $dbm->getManager()->flushPrivileges();
+ if ($priv_changed) {
+ $dbm->getManager()->flushPrivileges();
+ }
Database::needRoot(false);
// reactivate/deactivate api-keys
@@ -1371,6 +1375,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$dbm = new \Froxlor\Database\DbManager($this->logger());
+ $priv_changed = false;
while ($row_database = $databases_stmt->fetch(\PDO::FETCH_ASSOC)) {
if ($last_dbserver != $row_database['dbserver']) {
Database::needRoot(true, $row_database['dbserver']);
@@ -1378,8 +1383,11 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$last_dbserver = $row_database['dbserver'];
}
$dbm->getManager()->deleteDatabase($row_database['databasename']);
+ $priv_changed = true;
+ }
+ if ($priv_changed) {
+ $dbm->getManager()->flushPrivileges();
}
- $dbm->getManager()->flushPrivileges();
Database::needRoot(false);
// delete customer itself
From 55d21e475d7e350d03b46557ca38878c8efb33b1 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Sun, 6 Oct 2019 18:53:30 +0200
Subject: [PATCH 111/159] set low timeout for version-check and output message
if check is not possible (due to connection error, downtime of server, etc.)
Signed-off-by: Michael Kaufmann
---
admin_autoupdate.php | 7 +++++--
lib/Froxlor/Api/Commands/Froxlor.php | 6 +++++-
lib/Froxlor/Http/HttpClient.php | 3 ++-
3 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/admin_autoupdate.php b/admin_autoupdate.php
index 8598a5b0..f9978700 100644
--- a/admin_autoupdate.php
+++ b/admin_autoupdate.php
@@ -43,8 +43,11 @@ if ($page == 'overview') {
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "checking auto-update");
// check for new version
- $latestversion = HttpClient::urlGet(UPDATE_URI);
-
+ try {
+ $latestversion = HttpClient::urlGet(UPDATE_URI, true, 3);
+ } catch (\Exception $e) {
+ \Froxlor\UI\Response::dynamic_error("Version-check currently unavailable, please try again later");
+ }
$latestversion = explode('|', $latestversion);
if (is_array($latestversion) && count($latestversion) >= 1) {
diff --git a/lib/Froxlor/Api/Commands/Froxlor.php b/lib/Froxlor/Api/Commands/Froxlor.php
index 1e427240..85bf5500 100644
--- a/lib/Froxlor/Api/Commands/Froxlor.php
+++ b/lib/Froxlor/Api/Commands/Froxlor.php
@@ -39,7 +39,11 @@ class Froxlor extends \Froxlor\Api\ApiCommand
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] checking for updates");
// check for new version
- $latestversion = \Froxlor\Http\HttpClient::urlGet(UPDATE_URI);
+ try {
+ $latestversion = \Froxlor\Http\HttpClient::urlGet(UPDATE_URI, true, 3);
+ } catch (\Exception $e) {
+ $latestversion = \Froxlor\Froxlor::getVersion()."|Version-check currently unavailable, please try again later";
+ }
$latestversion = explode('|', $latestversion);
if (is_array($latestversion) && count($latestversion) >= 1) {
diff --git a/lib/Froxlor/Http/HttpClient.php b/lib/Froxlor/Http/HttpClient.php
index 6f5acb00..5b0e764a 100644
--- a/lib/Froxlor/Http/HttpClient.php
+++ b/lib/Froxlor/Http/HttpClient.php
@@ -11,7 +11,7 @@ class HttpClient
*
* @return array
*/
- public static function urlGet($url, $follow_location = true)
+ public static function urlGet($url, $follow_location = true, $timeout = 10)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
@@ -19,6 +19,7 @@ class HttpClient
if ($follow_location) {
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
}
+ curl_setopt($ch, CURLOPT_TIMEOUT, (int)$timeout);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
if ($output === false) {
From 8f850ee7f3c9339db0c09793496474fe6ab1f41c Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Sun, 6 Oct 2019 22:54:54 +0200
Subject: [PATCH 112/159] simplify config-templates for cronjob setup
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Cli/Action/ConfigServicesAction.php | 2 +-
lib/Froxlor/Cron/MasterCron.php | 11 ++++++++++-
lib/configfiles/bionic.xml | 16 +---------------
lib/configfiles/buster.xml | 16 +---------------
lib/configfiles/gentoo.xml | 16 +---------------
lib/configfiles/jessie.xml | 16 +---------------
lib/configfiles/rhel_centos.xml | 16 +---------------
lib/configfiles/stretch.xml | 16 +---------------
lib/configfiles/trusty.xml | 16 +---------------
lib/configfiles/xenial.xml | 16 +---------------
10 files changed, 19 insertions(+), 122 deletions(-)
diff --git a/lib/Froxlor/Cli/Action/ConfigServicesAction.php b/lib/Froxlor/Cli/Action/ConfigServicesAction.php
index ca472b10..fccddc5f 100644
--- a/lib/Froxlor/Cli/Action/ConfigServicesAction.php
+++ b/lib/Froxlor/Cli/Action/ConfigServicesAction.php
@@ -103,7 +103,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", "stretch");
+ $_daemons_config['distro'] = ConfigServicesCmd::getInput("choose distribution", "buster");
}
// go through all services and let user check whether to include it or not
diff --git a/lib/Froxlor/Cron/MasterCron.php b/lib/Froxlor/Cron/MasterCron.php
index 3179efb0..0c4c88e4 100644
--- a/lib/Froxlor/Cron/MasterCron.php
+++ b/lib/Froxlor/Cron/MasterCron.php
@@ -44,8 +44,9 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
echo "Below are possible parameters for this file\n\n";
echo "--[cronname]\t\tincludes the given cron-file\n";
echo "--force\t\t\tforces re-generating of config-files (webserver, nameserver, etc.)\n";
+ 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\t\tdo not fork to backkground (traffic cron only).\n\n";
+ echo "--no-fork\t\tdo not fork to backkground (traffic cron only).\n\n";
}
/**
@@ -75,6 +76,14 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
define('CRON_DEBUG_FLAG', 1);
} elseif (strtolower($argv[$x]) == '--no-fork') {
define('CRON_NOFORK_FLAG', 1);
+ } elseif (strtolower($argv[$x]) == '--run-task') {
+ if (isset($argv[$x+1]) && in_array($argv[$x+1], [1,4,10,99])) {
+ \Froxlor\System\Cronjob::inserttask($argv[$x+1]);
+ array_push($jobs_to_run, 'tasks');
+ } else {
+ echo "Invalid argument for --run-task\n";
+ exit;
+ }
} elseif (substr(strtolower($argv[$x]), 0, 2) == '--') {
// --[cronname]
if (strlen($argv[$x]) > 3) {
diff --git a/lib/configfiles/bionic.xml b/lib/configfiles/bionic.xml
index a716e732..1c94f11b 100644
--- a/lib/configfiles/bionic.xml
+++ b/lib/configfiles/bionic.xml
@@ -4539,21 +4539,7 @@ UPLOADGID=
-
- scripts/froxlor_master_cronjob.php
-]]>
-
-
+ scripts/froxlor_master_cronjob.php --run-task 99]]>
diff --git a/lib/configfiles/buster.xml b/lib/configfiles/buster.xml
index 82e1fa63..d95e6d02 100644
--- a/lib/configfiles/buster.xml
+++ b/lib/configfiles/buster.xml
@@ -4741,21 +4741,7 @@ UPLOADGID=
-
- scripts/froxlor_master_cronjob.php
-]]>
-
-
+ scripts/froxlor_master_cronjob.php --run-task 99]]>
diff --git a/lib/configfiles/gentoo.xml b/lib/configfiles/gentoo.xml
index e84a4439..9f77e247 100644
--- a/lib/configfiles/gentoo.xml
+++ b/lib/configfiles/gentoo.xml
@@ -3657,21 +3657,7 @@ account required pam_mysql.so user= passwd=
-
- scripts/froxlor_master_cronjob.php
-]]>
-
-
+ scripts/froxlor_master_cronjob.php --run-task 99]]>
diff --git a/lib/configfiles/jessie.xml b/lib/configfiles/jessie.xml
index d3ebfae2..f46d836f 100644
--- a/lib/configfiles/jessie.xml
+++ b/lib/configfiles/jessie.xml
@@ -4461,21 +4461,7 @@ UPLOADGID=
-
- scripts/froxlor_master_cronjob.php
-]]>
-
-
+ scripts/froxlor_master_cronjob.php --run-task 99]]>
diff --git a/lib/configfiles/rhel_centos.xml b/lib/configfiles/rhel_centos.xml
index 4f3c1e3d..3f6ab36a 100644
--- a/lib/configfiles/rhel_centos.xml
+++ b/lib/configfiles/rhel_centos.xml
@@ -2289,21 +2289,7 @@ ControlsLog /var/log/proftpd/controls.log
-
- scripts/froxlor_master_cronjob.php
-]]>
-
-
+ scripts/froxlor_master_cronjob.php --run-task 99]]>
diff --git a/lib/configfiles/stretch.xml b/lib/configfiles/stretch.xml
index 4c9c540c..6d717862 100644
--- a/lib/configfiles/stretch.xml
+++ b/lib/configfiles/stretch.xml
@@ -4528,21 +4528,7 @@ UPLOADGID=
-
- scripts/froxlor_master_cronjob.php
-]]>
-
-
+ scripts/froxlor_master_cronjob.php --run-task 99]]>
diff --git a/lib/configfiles/trusty.xml b/lib/configfiles/trusty.xml
index 512cc921..e9a1cf4d 100644
--- a/lib/configfiles/trusty.xml
+++ b/lib/configfiles/trusty.xml
@@ -1546,21 +1546,7 @@ UPLOADGID=
-
- scripts/froxlor_master_cronjob.php
-]]>
-
-
+ scripts/froxlor_master_cronjob.php --run-task 99]]>
diff --git a/lib/configfiles/xenial.xml b/lib/configfiles/xenial.xml
index c4c379c7..0345c524 100644
--- a/lib/configfiles/xenial.xml
+++ b/lib/configfiles/xenial.xml
@@ -4539,21 +4539,7 @@ UPLOADGID=
-
- scripts/froxlor_master_cronjob.php
-]]>
-
-
+ scripts/froxlor_master_cronjob.php --run-task 99]]>
From 466ea0fa99abbc2ac078197212b28f23e1495fce Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 8 Oct 2019 10:54:08 +0200
Subject: [PATCH 113/159] show update steps for version updates (forgot that
once or twice); add fallback for file deletion if exec() is not allowed; fix
php7.4 warnings
Signed-off-by: Michael Kaufmann
---
.../updates/froxlor/0.10/update_0.10.inc.php | 18 ++++++++++++++++--
lib/Froxlor/Cron/Http/ConfigIO.php | 2 +-
lib/Froxlor/Cron/Http/HttpConfigBase.php | 2 +-
3 files changed, 18 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 a2469065..a3a1827f 100644
--- a/install/updates/froxlor/0.10/update_0.10.inc.php
+++ b/install/updates/froxlor/0.10/update_0.10.inc.php
@@ -265,6 +265,7 @@ if (\Froxlor\Froxlor::isDatabaseVersion('201904100')) {
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.0-rc1')) {
+ showUpdateStep("Updating from 0.10.0-rc1 to 0.10.0-rc2", false);
\Froxlor\Froxlor::updateToVersion('0.10.0-rc2');
}
@@ -302,18 +303,31 @@ if (\Froxlor\Froxlor::isDatabaseVersion('201907270')) {
"templates/Sparkle/admin/tickets",
"templates/Sparkle/customer/tickets"
);
+ $disabled = explode(',', ini_get('disable_functions'));
+ $exec_allowed = !in_array('exec', $disabled);
+ $del_list = "";
foreach ($to_clean as $filedir) {
$complete_filedir = \Froxlor\Froxlor::getInstallDir() . $filedir;
if (file_exists($complete_filedir)) {
- Froxlor\FileDir::safe_exec("rm -rf " . escapeshellarg($complete_filedir));
+ if ($exec_allowed) {
+ Froxlor\FileDir::safe_exec("rm -rf " . escapeshellarg($complete_filedir));
+ } else {
+ $del_list .= "rm -rf " . escapeshellarg($complete_filedir) . PHP_EOL;
+ }
}
}
- lastStepStatus(0);
+ if ($exec_allowed) {
+ lastStepStatus(0);
+ } else {
+ lastStepStatus(1, 'manual commands needed');
+ echo 'Please run the following commands manually: '.$del_list.' ';
+ }
\Froxlor\Froxlor::updateToDbVersion('201909150');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.0-rc2')) {
+ showUpdateStep("Updating from 0.10.0-rc2 to 0.10.0 final", false);
\Froxlor\Froxlor::updateToVersion('0.10.0');
}
diff --git a/lib/Froxlor/Cron/Http/ConfigIO.php b/lib/Froxlor/Cron/Http/ConfigIO.php
index f82159a5..55002285 100644
--- a/lib/Froxlor/Cron/Http/ConfigIO.php
+++ b/lib/Froxlor/Cron/Http/ConfigIO.php
@@ -191,7 +191,7 @@ class ConfigIO
/**
* don't do anything if the file does not exist
*/
- if (@file_exists($awstatsclean['fullentry'])) {
+ if (@file_exists($awstatsclean['fullentry']) && $awstatsclean['entry'] != '.' && $awstatsclean['entry'] != '..') {
$awstatsclean['fh'] = fopen($awstatsclean['fullentry'], 'r');
$awstatsclean['headerRead'] = fgets($awstatsclean['fh'], strlen($awstatsclean['header']) + 1);
fclose($awstatsclean['fh']);
diff --git a/lib/Froxlor/Cron/Http/HttpConfigBase.php b/lib/Froxlor/Cron/Http/HttpConfigBase.php
index c927423d..eecbfeff 100644
--- a/lib/Froxlor/Cron/Http/HttpConfigBase.php
+++ b/lib/Froxlor/Cron/Http/HttpConfigBase.php
@@ -133,7 +133,7 @@ class HttpConfigBase
");
$ssldestport = Database::pexecute_first($ssldestport_stmt);
- if ($ssldestport['port'] != '') {
+ if ($ssldestport && $ssldestport['port'] != '') {
$_sslport = ":" . $ssldestport['port'];
}
From c6a93fa3367177c79021adc4793f8d87b8808d21 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 8 Oct 2019 11:26:05 +0200
Subject: [PATCH 114/159] fix possible php-7.4 notice 'Trying to access array
offset on value of type bool'
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Cron/Http/Apache.php | 2 +-
lib/Froxlor/Cron/Http/Lighttpd.php | 2 +-
lib/Froxlor/Cron/Http/Nginx.php | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/Froxlor/Cron/Http/Apache.php b/lib/Froxlor/Cron/Http/Apache.php
index 9ce40564..e68800f7 100644
--- a/lib/Froxlor/Cron/Http/Apache.php
+++ b/lib/Froxlor/Cron/Http/Apache.php
@@ -928,7 +928,7 @@ class Apache extends HttpConfigBase
'domainid' => $domain['id']
));
- if ($ssldestport['port'] != '') {
+ if ($ssldestport && $ssldestport['port'] != '') {
$_sslport = ":" . $ssldestport['port'];
}
diff --git a/lib/Froxlor/Cron/Http/Lighttpd.php b/lib/Froxlor/Cron/Http/Lighttpd.php
index b57a5aeb..0dac0193 100644
--- a/lib/Froxlor/Cron/Http/Lighttpd.php
+++ b/lib/Froxlor/Cron/Http/Lighttpd.php
@@ -451,7 +451,7 @@ class Lighttpd extends HttpConfigBase
'domainid' => $domain['id']
));
- if ($ssldestport['port'] != '') {
+ if ($ssldestport && $ssldestport['port'] != '') {
$_sslport = ":" . $ssldestport['port'];
}
diff --git a/lib/Froxlor/Cron/Http/Nginx.php b/lib/Froxlor/Cron/Http/Nginx.php
index 414eb11c..9d6e1b1e 100644
--- a/lib/Froxlor/Cron/Http/Nginx.php
+++ b/lib/Froxlor/Cron/Http/Nginx.php
@@ -476,7 +476,7 @@ class Nginx extends HttpConfigBase
'domainid' => $domain['id']
));
- if ($ssldestport['port'] != '') {
+ if ($ssldestport && $ssldestport['port'] != '') {
$_sslport = ":" . $ssldestport['port'];
}
From 0f1c5506e27e9f063aafc0f14a84e79d9127e56c Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 8 Oct 2019 12:04:10 +0200
Subject: [PATCH 115/159] do not create username@domain ftp user if the
default-ftp-user is being created in Ftps.add, fixes #720
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 acefe14d..55632b71 100644
--- a/lib/Froxlor/Api/Commands/Ftps.php
+++ b/lib/Froxlor/Api/Commands/Ftps.php
@@ -105,7 +105,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
$sendinfomail = 0;
}
- if (Settings::Get('customer.ftpatdomain') == '1') {
+ if (Settings::Get('customer.ftpatdomain') == '1' && !$is_defaultuser) {
if ($ftpusername == '') {
\Froxlor\UI\Response::standard_error(array(
'stringisempty',
From 557b28a69d12a31b104f892c2ea6698b31bfbb84 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 8 Oct 2019 12:08:36 +0200
Subject: [PATCH 116/159] more php-7.4 compatibility
Signed-off-by: Michael Kaufmann
---
admin_customers.php | 14 ++++++++++----
lib/init.php | 2 +-
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/admin_customers.php b/admin_customers.php
index 16a46b05..39d961d0 100644
--- a/admin_customers.php
+++ b/admin_customers.php
@@ -91,10 +91,16 @@ if ($page == 'customers' && $userinfo['customers'] != '0') {
'cid' => $row['customerid']
));
- $row['webspace_used'] = round($usages['webspace'] / 1024, $dec_places);
- $row['mailspace_used'] = round($usages['mail'] / 1024, $dec_places);
- $row['dbspace_used'] = round($usages['mysql'] / 1024, $dec_places);
-
+ if ($usages)
+ {
+ $row['webspace_used'] = round($usages['webspace'] / 1024, $dec_places);
+ $row['mailspace_used'] = round($usages['mail'] / 1024, $dec_places);
+ $row['dbspace_used'] = round($usages['mysql'] / 1024, $dec_places);
+ } else {
+ $row['webspace_used'] = 0;
+ $row['mailspace_used'] = 0;
+ $row['dbspace_used'] = 0;
+ }
$row['traffic_used'] = round($row['traffic_used'] / (1024 * 1024), $dec_places);
$row['traffic'] = round($row['traffic'] / (1024 * 1024), $dec_places);
$row['diskspace_used'] = round($row['diskspace_used'] / 1024, $dec_places);
diff --git a/lib/init.php b/lib/init.php
index e3a050b5..acc2375c 100644
--- a/lib/init.php
+++ b/lib/init.php
@@ -220,7 +220,7 @@ if (isset($s) && $s != "" && $nosession != 1) {
$userinfo_stmt = Database::prepare($query);
$userinfo = Database::pexecute_first($userinfo_stmt, $userinfo_data);
- if ((($userinfo['adminsession'] == '1' && AREA == 'admin' && isset($userinfo['adminid'])) || ($userinfo['adminsession'] == '0' && (AREA == 'customer' || AREA == 'login') && isset($userinfo['customerid']))) && (! isset($userinfo['deactivated']) || $userinfo['deactivated'] != '1')) {
+ if ($userinfo && (($userinfo['adminsession'] == '1' && AREA == 'admin' && isset($userinfo['adminid'])) || ($userinfo['adminsession'] == '0' && (AREA == 'customer' || AREA == 'login') && isset($userinfo['customerid']))) && (! isset($userinfo['deactivated']) || $userinfo['deactivated'] != '1')) {
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_SESSIONS . "` SET
`lastactivity` = :lastactive
From 3a8d5a9517c13ca65c99e2c186462fa874b2c04c Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 8 Oct 2019 12:11:00 +0200
Subject: [PATCH 117/159] correct Mysql.add phpDoc to produce correct api-doc,
fixes #721
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Api/Commands/Mysqls.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/Froxlor/Api/Commands/Mysqls.php b/lib/Froxlor/Api/Commands/Mysqls.php
index 54109919..35f6062c 100644
--- a/lib/Froxlor/Api/Commands/Mysqls.php
+++ b/lib/Froxlor/Api/Commands/Mysqls.php
@@ -33,7 +33,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, description for database
* @param bool $sendinfomail
* optional, send created resource-information to customer, default: false
- * @param int $customer_id
+ * @param int $customerid
* required when called as admin, not needed when called as customer
*
* @access admin, customer
From 9b8a6e7e67fcf9a4fb93e1f24ce229467ecd8d99 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 8 Oct 2019 12:38:22 +0200
Subject: [PATCH 118/159] more php-7.4 compatibility
Signed-off-by: Michael Kaufmann
---
customer_index.php | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/customer_index.php b/customer_index.php
index d73f2555..6912b86a 100644
--- a/customer_index.php
+++ b/customer_index.php
@@ -93,11 +93,17 @@ if ($page == 'overview') {
'cid' => $userinfo['customerid']
));
+ if ($usages)
+ {
+ $userinfo['diskspace_used'] = round($usages['webspace'] / 1024, Settings::Get('panel.decimal_places'));
+ $userinfo['mailspace_used'] = round($usages['mail'] / 1024, Settings::Get('panel.decimal_places'));
+ $userinfo['dbspace_used'] = round($usages['mysql'] / 1024, Settings::Get('panel.decimal_places'));
+ } else {
+ $userinfo['diskspace_used'] = 0;
+ $userinfo['mailspace_used'] = 0;
+ $userinfo['dbspace_used'] = 0;
+ }
$userinfo['diskspace'] = round($userinfo['diskspace'] / 1024, Settings::Get('panel.decimal_places'));
- $userinfo['diskspace_used'] = round($usages['webspace'] / 1024, Settings::Get('panel.decimal_places'));
- $userinfo['mailspace_used'] = round($usages['mail'] / 1024, Settings::Get('panel.decimal_places'));
- $userinfo['dbspace_used'] = round($usages['mysql'] / 1024, Settings::Get('panel.decimal_places'));
-
$userinfo['traffic'] = round($userinfo['traffic'] / (1024 * 1024), Settings::Get('panel.decimal_places'));
$userinfo['traffic_used'] = round($userinfo['traffic_used'] / (1024 * 1024), Settings::Get('panel.decimal_places'));
$userinfo = \Froxlor\PhpHelper::strReplaceArray('-1', $lng['customer']['unlimited'], $userinfo, 'diskspace traffic mysqls emails email_accounts email_forwarders email_quota ftps subdomains');
From 20699a15a66de84dcbafa4ff19e8539480f5aa42 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 8 Oct 2019 12:54:15 +0200
Subject: [PATCH 119/159] update composer dependencies
Signed-off-by: Michael Kaufmann
---
composer.lock | 80 +++++++++++++++++++++++++--------------------------
1 file changed, 40 insertions(+), 40 deletions(-)
diff --git a/composer.lock b/composer.lock
index 7d7f33b7..f8c7a813 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": "5be3ef1341b33f64d1eab9a4afa10f20",
+ "content-hash": "77819131afd1abe70f1ea6caad9fc3e5",
"packages": [
{
"name": "algo26-matthias/idna-convert",
@@ -922,22 +922,22 @@
},
{
"name": "phpspec/prophecy",
- "version": "1.8.1",
+ "version": "1.9.0",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
- "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76"
+ "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpspec/prophecy/zipball/1927e75f4ed19131ec9bcc3b002e07fb1173ee76",
- "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76",
+ "url": "https://api.github.com/repos/phpspec/prophecy/zipball/f6811d96d97bdf400077a0cc100ae56aa32b9203",
+ "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": "^5.3|^7.0",
- "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0",
+ "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0",
"sebastian/comparator": "^1.1|^2.0|^3.0",
"sebastian/recursion-context": "^1.0|^2.0|^3.0"
},
@@ -981,7 +981,7 @@
"spy",
"stub"
],
- "time": "2019-06-13T12:50:23+00:00"
+ "time": "2019-10-03T11:07:50+00:00"
},
{
"name": "phpunit/php-code-coverage",
@@ -1237,16 +1237,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "8.3.5",
+ "version": "8.4.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "302faed7059fde575cf3403a78c730c5e3a62750"
+ "reference": "366a4a0f2b971fd43b7c351d621e8dd7d7131869"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/302faed7059fde575cf3403a78c730c5e3a62750",
- "reference": "302faed7059fde575cf3403a78c730c5e3a62750",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/366a4a0f2b971fd43b7c351d621e8dd7d7131869",
+ "reference": "366a4a0f2b971fd43b7c351d621e8dd7d7131869",
"shasum": ""
},
"require": {
@@ -1290,7 +1290,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "8.3-dev"
+ "dev-master": "8.4-dev"
}
},
"autoload": {
@@ -1316,7 +1316,7 @@
"testing",
"xunit"
],
- "time": "2019-09-14T09:12:03+00:00"
+ "time": "2019-10-07T12:57:41+00:00"
},
{
"name": "psr/container",
@@ -2125,16 +2125,16 @@
},
{
"name": "symfony/config",
- "version": "v4.3.4",
+ "version": "v4.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
- "reference": "07d49c0f823e0bc367c6d84e35b61419188a5ece"
+ "reference": "0acb26407a9e1a64a275142f0ae5e36436342720"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/config/zipball/07d49c0f823e0bc367c6d84e35b61419188a5ece",
- "reference": "07d49c0f823e0bc367c6d84e35b61419188a5ece",
+ "url": "https://api.github.com/repos/symfony/config/zipball/0acb26407a9e1a64a275142f0ae5e36436342720",
+ "reference": "0acb26407a9e1a64a275142f0ae5e36436342720",
"shasum": ""
},
"require": {
@@ -2185,20 +2185,20 @@
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
- "time": "2019-08-26T08:26:39+00:00"
+ "time": "2019-09-19T15:51:53+00:00"
},
{
"name": "symfony/console",
- "version": "v4.3.4",
+ "version": "v4.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "de63799239b3881b8a08f8481b22348f77ed7b36"
+ "reference": "929ddf360d401b958f611d44e726094ab46a7369"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/de63799239b3881b8a08f8481b22348f77ed7b36",
- "reference": "de63799239b3881b8a08f8481b22348f77ed7b36",
+ "url": "https://api.github.com/repos/symfony/console/zipball/929ddf360d401b958f611d44e726094ab46a7369",
+ "reference": "929ddf360d401b958f611d44e726094ab46a7369",
"shasum": ""
},
"require": {
@@ -2260,20 +2260,20 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
- "time": "2019-08-26T08:26:39+00:00"
+ "time": "2019-10-07T12:36:49+00:00"
},
{
"name": "symfony/dependency-injection",
- "version": "v4.3.4",
+ "version": "v4.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/dependency-injection.git",
- "reference": "d3ad14b66ac773ba6123622eb9b5b010165fe3d9"
+ "reference": "e1e0762a814b957a1092bff75a550db49724d05b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/d3ad14b66ac773ba6123622eb9b5b010165fe3d9",
- "reference": "d3ad14b66ac773ba6123622eb9b5b010165fe3d9",
+ "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/e1e0762a814b957a1092bff75a550db49724d05b",
+ "reference": "e1e0762a814b957a1092bff75a550db49724d05b",
"shasum": ""
},
"require": {
@@ -2333,11 +2333,11 @@
],
"description": "Symfony DependencyInjection Component",
"homepage": "https://symfony.com",
- "time": "2019-08-26T16:27:33+00:00"
+ "time": "2019-10-02T12:58:58+00:00"
},
{
"name": "symfony/filesystem",
- "version": "v4.3.4",
+ "version": "v4.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
@@ -2387,16 +2387,16 @@
},
{
"name": "symfony/finder",
- "version": "v4.3.4",
+ "version": "v4.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "86c1c929f0a4b24812e1eb109262fc3372c8e9f2"
+ "reference": "5e575faa95548d0586f6bedaeabec259714e44d1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/86c1c929f0a4b24812e1eb109262fc3372c8e9f2",
- "reference": "86c1c929f0a4b24812e1eb109262fc3372c8e9f2",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/5e575faa95548d0586f6bedaeabec259714e44d1",
+ "reference": "5e575faa95548d0586f6bedaeabec259714e44d1",
"shasum": ""
},
"require": {
@@ -2432,7 +2432,7 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
- "time": "2019-08-14T12:26:46+00:00"
+ "time": "2019-09-16T11:29:48+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -2611,16 +2611,16 @@
},
{
"name": "symfony/service-contracts",
- "version": "v1.1.6",
+ "version": "v1.1.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
- "reference": "ea7263d6b6d5f798b56a45a5b8d686725f2719a3"
+ "reference": "ffcde9615dc5bb4825b9f6aed07716f1f57faae0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/service-contracts/zipball/ea7263d6b6d5f798b56a45a5b8d686725f2719a3",
- "reference": "ea7263d6b6d5f798b56a45a5b8d686725f2719a3",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/ffcde9615dc5bb4825b9f6aed07716f1f57faae0",
+ "reference": "ffcde9615dc5bb4825b9f6aed07716f1f57faae0",
"shasum": ""
},
"require": {
@@ -2665,7 +2665,7 @@
"interoperability",
"standards"
],
- "time": "2019-08-20T14:44:19+00:00"
+ "time": "2019-09-17T11:12:18+00:00"
},
{
"name": "theseer/directoryscanner",
@@ -2942,7 +2942,7 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
- "php": ">=5.6",
+ "php": ">=7.0",
"ext-session": "*",
"ext-ctype": "*",
"ext-pdo": "*",
From 9ec03bade7d7edcb3c9eab54fd85009903ff45cb Mon Sep 17 00:00:00 2001
From: kionez
Date: Tue, 8 Oct 2019 17:32:03 +0200
Subject: [PATCH 120/159] Add expiration date to SSL certificates loaded via
API request
---
lib/Froxlor/Api/Commands/Certificates.php | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/lib/Froxlor/Api/Commands/Certificates.php b/lib/Froxlor/Api/Commands/Certificates.php
index a725a969..7a9adac0 100644
--- a/lib/Froxlor/Api/Commands/Certificates.php
+++ b/lib/Froxlor/Api/Commands/Certificates.php
@@ -271,6 +271,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
throw new \Exception("Unable to determine SSL certificate. Maybe no access?", 406);
}
+
/**
* insert or update certificates entry
*
@@ -292,6 +293,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
}
$do_verify = true;
+ $expirationdate = NULL;
// no cert-file given -> forget everything
if ($ssl_cert_file == '') {
$ssl_key_file = '';
@@ -332,6 +334,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
} else {
\Froxlor\UI\Response::standard_error('sslcertificateinvalidcert', '', true);
}
+ $expirationdate = $cert_content['validTo_time_t'];
}
// Add/Update database entry
@@ -345,7 +348,8 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
`ssl_cert_file` = :ssl_cert_file,
`ssl_key_file` = :ssl_key_file,
`ssl_ca_file` = :ssl_ca_file,
- `ssl_cert_chainfile` = :ssl_cert_chainfile
+ `ssl_cert_chainfile` = :ssl_cert_chainfile,
+ `expirationdate` = :expirationdate
" . $qrywhere . " `domainid`= :domainid
");
$params = array(
@@ -353,6 +357,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
"ssl_key_file" => $ssl_key_file,
"ssl_ca_file" => $ssl_ca_file,
"ssl_cert_chainfile" => $ssl_cert_chainfile,
+ "expirationdate" => date("Y-m-d H:i:s", $expirationdate),
"domainid" => $domainid
);
Database::pexecute($stmt, $params, true, true);
From 89b95d61d234d5c6c324b0d68ab1320c895c0495 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 8 Oct 2019 17:36:42 +0200
Subject: [PATCH 121/159] return empty array in FroxlorAPI.php example class if
last call was unsuccessful, fixes #722
Signed-off-by: Michael Kaufmann
---
doc/example/FroxlorAPI.php | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/doc/example/FroxlorAPI.php b/doc/example/FroxlorAPI.php
index 8bcb742d..9b2ef050 100644
--- a/doc/example/FroxlorAPI.php
+++ b/doc/example/FroxlorAPI.php
@@ -148,6 +148,11 @@ class FroxlorAPI
*/
public function getLastResponse(): array
{
+ if (!empty($this->getLastError())) {
+ // nothing is returned when the last call
+ // was not successful
+ return [];
+ }
return $this->last_body;
}
From 05f602d45775571141c508806da82ddd9b263760 Mon Sep 17 00:00:00 2001
From: kionez
Date: Tue, 8 Oct 2019 17:44:41 +0200
Subject: [PATCH 122/159] Fix for null expiration date and coding style
---
lib/Froxlor/Api/Commands/Certificates.php | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/Froxlor/Api/Commands/Certificates.php b/lib/Froxlor/Api/Commands/Certificates.php
index 7a9adac0..0b9b9505 100644
--- a/lib/Froxlor/Api/Commands/Certificates.php
+++ b/lib/Froxlor/Api/Commands/Certificates.php
@@ -293,7 +293,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
}
$do_verify = true;
- $expirationdate = NULL;
+ $expirationdate = null;
// no cert-file given -> forget everything
if ($ssl_cert_file == '') {
$ssl_key_file = '';
@@ -334,7 +334,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
} else {
\Froxlor\UI\Response::standard_error('sslcertificateinvalidcert', '', true);
}
- $expirationdate = $cert_content['validTo_time_t'];
+ $expirationdate = empty($cert_content['validTo_time_t']) ? null : $date("Y-m-d H:i:s", $cert_content['validTo_time_t']);
}
// Add/Update database entry
@@ -357,7 +357,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
"ssl_key_file" => $ssl_key_file,
"ssl_ca_file" => $ssl_ca_file,
"ssl_cert_chainfile" => $ssl_cert_chainfile,
- "expirationdate" => date("Y-m-d H:i:s", $expirationdate),
+ "expirationdate" => $expirationdate,
"domainid" => $domainid
);
Database::pexecute($stmt, $params, true, true);
From b4999fcc8336b69adc67ed85a4322af6fd6bbc7c Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 8 Oct 2019 18:01:59 +0200
Subject: [PATCH 123/159] Throw exception if domain used to call
Certificates.get() does not have a certificate, fixes #722
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Api/Commands/Certificates.php | 3 +++
1 file changed, 3 insertions(+)
diff --git a/lib/Froxlor/Api/Commands/Certificates.php b/lib/Froxlor/Api/Commands/Certificates.php
index a725a969..1d73bb54 100644
--- a/lib/Froxlor/Api/Commands/Certificates.php
+++ b/lib/Froxlor/Api/Commands/Certificates.php
@@ -110,6 +110,9 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
$result = Database::pexecute_first($stmt, array(
"domainid" => $domainid
));
+ if (! $result) {
+ throw new \Exception("Domain '" . $domain['domain'] . "' does not have a certificate.", 404);
+ }
return $this->response(200, "successfull", $result);
}
From 26cb53c8fbbc88708f7c656faa72555bcc682741 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Tue, 8 Oct 2019 18:44:42 +0200
Subject: [PATCH 124/159] correctly validate that a domain has not a
certificate in Certificates.add(), refs #722
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Api/Commands/Certificates.php | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/lib/Froxlor/Api/Commands/Certificates.php b/lib/Froxlor/Api/Commands/Certificates.php
index 1d73bb54..200e0151 100644
--- a/lib/Froxlor/Api/Commands/Certificates.php
+++ b/lib/Froxlor/Api/Commands/Certificates.php
@@ -63,10 +63,19 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
$ssl_cert_chainfile = $this->getParam('ssl_cert_chainfile', true, '');
// validate whether the domain does not already have an entry
- $result = $this->apiCall('Certificates.get', array(
- 'id' => $domainid
- ));
- if (empty($result)) {
+ $has_cert = true;
+ try {
+ $this->apiCall('Certificates.get', array(
+ 'id' => $domainid
+ ));
+ } catch (\Exception $e) {
+ if ($e->getCode() == 412) {
+ $has_cert = false;
+ } else {
+ throw $e;
+ }
+ }
+ if (!$has_cert) {
$this->addOrUpdateCertificate($domain['id'], $ssl_cert_file, $ssl_key_file, $ssl_ca_file, $ssl_cert_chainfile, true);
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added ssl-certificate for '" . $domain['domain'] . "'");
$result = $this->apiCall('Certificates.get', array(
@@ -111,7 +120,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
"domainid" => $domainid
));
if (! $result) {
- throw new \Exception("Domain '" . $domain['domain'] . "' does not have a certificate.", 404);
+ throw new \Exception("Domain '" . $domain['domain'] . "' does not have a certificate.", 412);
}
return $this->response(200, "successfull", $result);
}
From 1b3029b82634b60e5a8121dae8dd0d55eae976ac Mon Sep 17 00:00:00 2001
From: kionez
Date: Tue, 8 Oct 2019 18:50:10 +0200
Subject: [PATCH 125/159] Fix typo
---
lib/Froxlor/Api/Commands/Certificates.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/Froxlor/Api/Commands/Certificates.php b/lib/Froxlor/Api/Commands/Certificates.php
index 0b9b9505..46091869 100644
--- a/lib/Froxlor/Api/Commands/Certificates.php
+++ b/lib/Froxlor/Api/Commands/Certificates.php
@@ -334,7 +334,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
} else {
\Froxlor\UI\Response::standard_error('sslcertificateinvalidcert', '', true);
}
- $expirationdate = empty($cert_content['validTo_time_t']) ? null : $date("Y-m-d H:i:s", $cert_content['validTo_time_t']);
+ $expirationdate = empty($cert_content['validTo_time_t']) ? null : date("Y-m-d H:i:s", $cert_content['validTo_time_t']);
}
// Add/Update database entry
From 6102fabcb6078d3944c714e9d3b7075b4ed98015 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Wed, 9 Oct 2019 07:59:11 +0200
Subject: [PATCH 126/159] allow setting http2 flag for (sub)domains in customer
view, fixes #725
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/Api/Commands/SubDomains.php | 14 +++++++++++++-
lib/Froxlor/Cron/Http/Apache.php | 2 +-
.../customer/domains/formfield.domains_add.php | 13 +++++++++++++
.../customer/domains/formfield.domains_edit.php | 15 +++++++++++++++
4 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/lib/Froxlor/Api/Commands/SubDomains.php b/lib/Froxlor/Api/Commands/SubDomains.php
index e3f3db0a..3c54899d 100644
--- a/lib/Froxlor/Api/Commands/SubDomains.php
+++ b/lib/Froxlor/Api/Commands/SubDomains.php
@@ -45,6 +45,8 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* optional, whether to generate a https-redirect or not, default false; requires SSL to be enabled
* @param bool $letsencrypt
* optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires SSL to be enabled
+ * @param bool $http2
+ * optional, whether to enable http/2 for this subdomain (requires to be enabled in the settings), default 0 (false)
* @param int $hsts_maxage
* optional max-age value for HSTS header, default 0
* @param bool $hsts_sub
@@ -76,12 +78,14 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
if (Settings::Get('system.use_ssl')) {
$ssl_redirect = $this->getBoolParam('ssl_redirect', true, 0);
$letsencrypt = $this->getBoolParam('letsencrypt', true, 0);
+ $http2 = $this->getBoolParam('http2', true, 0);
$hsts_maxage = $this->getParam('hsts_maxage', true, 0);
$hsts_sub = $this->getBoolParam('hsts_sub', true, 0);
$hsts_preload = $this->getBoolParam('hsts_preload', true, 0);
} else {
$ssl_redirect = 0;
$letsencrypt = 0;
+ $http2 = 0;
$hsts_maxage = 0;
$hsts_sub = 0;
$hsts_preload = 0;
@@ -241,7 +245,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$phpsid_result['phpsettingid'] = intval($phpsettingid);
}
- // acutall insert domain
+ // actually insert domain
$stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_DOMAINS . "` SET
`customerid` = :customerid,
@@ -261,6 +265,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
`ssl_redirect` = :ssl_redirect,
`phpsettingid` = :phpsettingid,
`letsencrypt` = :letsencrypt,
+ `http2` = :http2,
`hsts` = :hsts,
`hsts_sub` = :hsts_sub,
`hsts_preload` = :hsts_preload
@@ -283,6 +288,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
"ssl_redirect" => $ssl_redirect,
"phpsettingid" => $phpsid_result['phpsettingid'],
"letsencrypt" => $letsencrypt,
+ "http2" => $http2,
"hsts" => $hsts_maxage,
"hsts_sub" => $hsts_sub,
"hsts_preload" => $hsts_preload
@@ -430,6 +436,8 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* optional, whether to generate a https-redirect or not, default false; requires SSL to be enabled
* @param bool $letsencrypt
* optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires SSL to be enabled
+ * @param bool $http2
+ * optional, whether to enable http/2 for this domain (requires to be enabled in the settings), default 0 (false)
* @param int $hsts_maxage
* optional max-age value for HSTS header
* @param bool $hsts_sub
@@ -473,12 +481,14 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
if (Settings::Get('system.use_ssl')) {
$ssl_redirect = $this->getBoolParam('ssl_redirect', true, $result['ssl_redirect']);
$letsencrypt = $this->getBoolParam('letsencrypt', true, $result['letsencrypt']);
+ $http2 = $this->getBoolParam('http2', true, $result['http2']);
$hsts_maxage = $this->getParam('hsts_maxage', true, $result['hsts']);
$hsts_sub = $this->getBoolParam('hsts_sub', true, $result['hsts_sub']);
$hsts_preload = $this->getBoolParam('hsts_preload', true, $result['hsts_preload']);
} else {
$ssl_redirect = 0;
$letsencrypt = 0;
+ $http2 = 0;
$hsts_maxage = 0;
$hsts_sub = 0;
$hsts_preload = 0;
@@ -599,6 +609,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
`openbasedir_path`= :openbasedir_path,
`ssl_redirect`= :ssl_redirect,
`letsencrypt`= :letsencrypt,
+ `http2` = :http2,
`hsts` = :hsts,
`hsts_sub` = :hsts_sub,
`hsts_preload` = :hsts_preload,
@@ -614,6 +625,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
"openbasedir_path" => $openbasedir_path,
"ssl_redirect" => $ssl_redirect,
"letsencrypt" => $letsencrypt,
+ "http2" => $http2,
"hsts" => $hsts_maxage,
"hsts_sub" => $hsts_sub,
"hsts_preload" => $hsts_preload,
diff --git a/lib/Froxlor/Cron/Http/Apache.php b/lib/Froxlor/Cron/Http/Apache.php
index e68800f7..ef48e075 100644
--- a/lib/Froxlor/Cron/Http/Apache.php
+++ b/lib/Froxlor/Cron/Http/Apache.php
@@ -963,7 +963,7 @@ class Apache extends HttpConfigBase
$vhost_content .= ' SSLProtocol -ALL +' . str_replace(",", " +", Settings::Get('system.ssl_protocols')) . "\n";
if (Settings::Get('system.apache24') == '1') {
if (isset($domain['http2']) && $domain['http2'] == '1' && Settings::Get('system.http2_support') == '1') {
- $vhost_content .= ' Protocols h2 http/1.1' . "\n";
+ $vhost_content .= ' Protocols h2 http/1.1' . "\n";
}
if (! empty(Settings::Get('system.dhparams_file'))) {
$dhparams = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.dhparams_file'));
diff --git a/lib/formfields/customer/domains/formfield.domains_add.php b/lib/formfields/customer/domains/formfield.domains_add.php
index 00d9fca6..1e6f47eb 100644
--- a/lib/formfields/customer/domains/formfield.domains_add.php
+++ b/lib/formfields/customer/domains/formfield.domains_add.php
@@ -108,6 +108,19 @@ return array(
),
'value' => array()
),
+ 'http2' => array(
+ 'visible' => ($ssl_ipsandports != '' ? true : false) && \Froxlor\Settings::Get('system.webserver') != 'lighttpd' && \Froxlor\Settings::Get('system.http2_support') == '1',
+ 'label' => $lng['admin']['domain_http2']['title'],
+ 'desc' => $lng['admin']['domain_http2']['description'],
+ 'type' => 'checkbox',
+ 'values' => array(
+ array(
+ 'label' => $lng['panel']['yes'],
+ 'value' => '1'
+ )
+ ),
+ 'value' => array()
+ ),
'hsts_maxage' => array(
'label' => $lng['admin']['domain_hsts_maxage']['title'],
'desc' => $lng['admin']['domain_hsts_maxage']['description'],
diff --git a/lib/formfields/customer/domains/formfield.domains_edit.php b/lib/formfields/customer/domains/formfield.domains_edit.php
index 56a28543..0fd54134 100644
--- a/lib/formfields/customer/domains/formfield.domains_edit.php
+++ b/lib/formfields/customer/domains/formfield.domains_edit.php
@@ -128,6 +128,21 @@ return array(
$result['letsencrypt']
)
),
+ 'http2' => array(
+ 'visible' => ($ssl_ipsandports != '' ? true : false) && \Froxlor\Settings::Get('system.webserver') != 'lighttpd' && \Froxlor\Settings::Get('system.http2_support') == '1',
+ 'label' => $lng['admin']['domain_http2']['title'],
+ 'desc' => $lng['admin']['domain_http2']['description'],
+ 'type' => 'checkbox',
+ 'values' => array(
+ array(
+ 'label' => $lng['panel']['yes'],
+ 'value' => '1'
+ )
+ ),
+ 'value' => array(
+ $result['http2']
+ )
+ ),
'hsts_maxage' => array(
'label' => $lng['admin']['domain_hsts_maxage']['title'],
'desc' => $lng['admin']['domain_hsts_maxage']['description'],
From 88d85fc02e51d53f5db9f63c438a363d13530508 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Wed, 9 Oct 2019 07:59:38 +0200
Subject: [PATCH 127/159] fix curly bracket array access (deprecated)
Signed-off-by: Michael Kaufmann
---
lib/Froxlor/UI/Paging.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/Froxlor/UI/Paging.php b/lib/Froxlor/UI/Paging.php
index 635f9ffd..6b7e5ee7 100644
--- a/lib/Froxlor/UI/Paging.php
+++ b/lib/Froxlor/UI/Paging.php
@@ -282,7 +282,7 @@ class Paging
$field .= '`';
}
- if ($field{0} != '`') {
+ if ($field[0] != '`') {
$field = '`' . $field;
}
@@ -352,7 +352,7 @@ class Paging
$field .= '`';
}
- if ($field{0} != '`') {
+ if ($field[0] != '`') {
$field = '`' . $field;
}
From 4543c73b4f89bf522f4d5a136533f0ece4d1e6f2 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Wed, 9 Oct 2019 11:43:22 +0200
Subject: [PATCH 128/159] add possibility to enable/disable api access on a per
user base
Signed-off-by: Michael Kaufmann
---
install/froxlor.sql | 4 +-
install/lib/class.FroxlorInstall.php | 1 +
.../updates/froxlor/0.10/update_0.10.inc.php | 10 ++++
lib/Froxlor/Api/Commands/Admins.php | 15 +++++-
lib/Froxlor/Api/Commands/Customers.php | 54 +++++--------------
lib/Froxlor/Api/FroxlorRPC.php | 11 +++-
lib/Froxlor/Froxlor.php | 2 +-
.../admin/admin/formfield.admin_add.php | 15 ++++++
.../admin/admin/formfield.admin_edit.php | 15 ++++++
.../admin/customer/formfield.customer_add.php | 19 ++++++-
.../customer/formfield.customer_edit.php | 15 ++++++
lng/english.lng.php | 2 +
lng/german.lng.php | 2 +
13 files changed, 115 insertions(+), 50 deletions(-)
diff --git a/install/froxlor.sql b/install/froxlor.sql
index b150ab48..da14ee16 100644
--- a/install/froxlor.sql
+++ b/install/froxlor.sql
@@ -132,6 +132,7 @@ CREATE TABLE `panel_admins` (
`custom_notes_show` tinyint(1) NOT NULL default '0',
`type_2fa` tinyint(1) NOT NULL default '0',
`data_2fa` varchar(500) NOT NULL default '',
+ `api_allowed` tinyint(1) NOT NULL default '1',
PRIMARY KEY (`adminid`),
UNIQUE KEY `loginname` (`loginname`)
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -199,6 +200,7 @@ CREATE TABLE `panel_customers` (
`allowed_phpconfigs` varchar(500) NOT NULL default '',
`type_2fa` tinyint(1) NOT NULL default '0',
`data_2fa` varchar(500) NOT NULL default '',
+ `api_allowed` tinyint(1) NOT NULL default '1',
`logviewenabled` tinyint(1) NOT NULL default '0',
PRIMARY KEY (`customerid`),
UNIQUE KEY `loginname` (`loginname`)
@@ -684,7 +686,7 @@ opcache.interned_strings_buffer'),
('panel', 'customer_hide_options', ''),
('panel', 'is_configured', '0'),
('panel', 'version', '0.10.0'),
- ('panel', 'db_version', '201910030');
+ ('panel', 'db_version', '201910090');
DROP TABLE IF EXISTS `panel_tasks`;
diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php
index 1ae347a0..ddc3166a 100644
--- a/install/lib/class.FroxlorInstall.php
+++ b/install/lib/class.FroxlorInstall.php
@@ -407,6 +407,7 @@ class FroxlorInstall
`name` = 'Froxlor-Administrator',
`email` = :email,
`def_language` = :deflang,
+ `api_allowed` = 1,
`customers` = -1,
`customers_see_all` = 1,
`caneditphpsettings` = 1,
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 a3a1827f..43bc0f99 100644
--- a/install/updates/froxlor/0.10/update_0.10.inc.php
+++ b/install/updates/froxlor/0.10/update_0.10.inc.php
@@ -339,3 +339,13 @@ if (\Froxlor\Froxlor::isDatabaseVersion('201909150')) {
\Froxlor\Froxlor::updateToDbVersion('201910030');
}
+
+if (\Froxlor\Froxlor::isDatabaseVersion('201910030')) {
+
+ showUpdateStep("Adding field api_allowed to admins and customers");
+ Database::query("ALTER TABLE `" . TABLE_PANEL_ADMINS . "` ADD `api_allowed` tinyint(1) NOT NULL default '1';");
+ Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` ADD `api_allowed` tinyint(1) NOT NULL default '1';");
+ lastStepStatus(0);
+
+ \Froxlor\Froxlor::updateToDbVersion('201910090');
+}
diff --git a/lib/Froxlor/Api/Commands/Admins.php b/lib/Froxlor/Api/Commands/Admins.php
index a29ac9ad..72b7bb48 100644
--- a/lib/Froxlor/Api/Commands/Admins.php
+++ b/lib/Froxlor/Api/Commands/Admins.php
@@ -97,6 +97,8 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, default auto-generated
* @param string $def_language
* optional, default is system-default language
+ * @param bool $api_allowed
+ * optional, default is true if system setting api.enabled is true, else false
* @param string $custom_notes
* optional, default empty
* @param bool $custom_notes_show
@@ -171,6 +173,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
// parameters
$def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage'));
+ $api_allowed = $this->getBoolParam('api_allowed', true, Settings::Get('api.enabled'));
$custom_notes = $this->getParam('custom_notes', true, '');
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0);
$password = $this->getParam('admin_password', true, '');
@@ -271,6 +274,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
'name' => $name,
'email' => $email,
'lang' => $def_language,
+ 'api_allowed' => $api_allowed,
'change_serversettings' => $change_serversettings,
'customers' => $customers,
'customers_see_all' => $customers_see_all,
@@ -299,6 +303,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
`name` = :name,
`email` = :email,
`def_language` = :lang,
+ `api_allowed` = :api_allowed,
`change_serversettings` = :change_serversettings,
`customers` = :customers,
`customers_see_all` = :customers_see_all,
@@ -350,6 +355,8 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, default auto-generated
* @param string $def_language
* optional, default is system-default language
+ * @param bool $api_allowed
+ * optional, default is true if system setting api.enabled is true, else false
* @param string $custom_notes
* optional, default empty
* @param string $theme
@@ -444,6 +451,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
// you cannot edit some of the details of yourself
if ($result['adminid'] == $this->getUserDetail('adminid')) {
+ $api_allowed = $result['api_allowed'];
$deactivated = $result['deactivated'];
$customers = $result['customers'];
$domains = $result['domains'];
@@ -462,6 +470,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$traffic = $result['traffic'];
$ipaddress = ($result['ip'] != - 1 ? json_decode($result['ip'], true) : - 1);
} else {
+ $api_allowed = $this->getBoolParam('api_allowed', true, $result['api_allowed']);
$deactivated = $this->getBoolParam('deactivated', true, $result['deactivated']);
$dec_places = Settings::Get('panel.decimal_places');
@@ -578,6 +587,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
'name' => $name,
'email' => $email,
'lang' => $def_language,
+ 'api_allowed' => $api_allowed,
'change_serversettings' => $change_serversettings,
'customers' => $customers,
'customers_see_all' => $customers_see_all,
@@ -607,6 +617,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
`name` = :name,
`email` = :email,
`def_language` = :lang,
+ `api_allowed` = :api_allowed,
`change_serversettings` = :change_serversettings,
`customers` = :customers,
`customers_see_all` = :customers_see_all,
@@ -793,7 +804,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* @param string $extra
* optional, default empty
* @param int $increase_by
- * optional, default 1
+ * optional, default 1
*/
public static function increaseUsage($adminid = 0, $resource = null, $extra = '', $increase_by = 1)
{
@@ -808,7 +819,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* @param string $extra
* optional, default empty
* @param int $decrease_by
- * optional, default 1
+ * optional, default 1
*/
public static function decreaseUsage($adminid = 0, $resource = null, $extra = '', $decrease_by = 1)
{
diff --git a/lib/Froxlor/Api/Commands/Customers.php b/lib/Froxlor/Api/Commands/Customers.php
index 1fb82107..8d500f9b 100644
--- a/lib/Froxlor/Api/Commands/Customers.php
+++ b/lib/Froxlor/Api/Commands/Customers.php
@@ -136,6 +136,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
* optional
* @param string $def_language,
* optional, default is system-default language
+ * @param bool $api_allowed
+ * optional, default is true if system setting api.enabled is true, else false
* @param int $gender
* optional, 0 = no-gender, 1 = male, 2 = female
* @param string $custom_notes
@@ -229,6 +231,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$fax = $this->getParam('fax', true, '');
$customernumber = $this->getParam('customernumber', true, '');
$def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage'));
+ $api_allowed = $this->getBoolParam('api_allowed', true, Settings::Get('api.enabled'));
$gender = (int) $this->getParam('gender', true, 0);
$custom_notes = $this->getParam('custom_notes', true, '');
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0);
@@ -388,26 +391,6 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
\Froxlor\UI\Response::standard_error('documentrootexists', $documentroot, true);
}
- if ($createstdsubdomain != '1') {
- $createstdsubdomain = '0';
- }
-
- if ($phpenabled != '0') {
- $phpenabled = '1';
- }
-
- if ($perlenabled != '0') {
- $perlenabled = '1';
- }
-
- if ($dnsenabled != '0') {
- $dnsenabled = '1';
- }
-
- if ($logviewenabled != '0') {
- $logviewenabled = '1';
- }
-
if ($password == '') {
$password = \Froxlor\System\Crypt::generatePassword();
}
@@ -430,6 +413,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
'email' => $email,
'customerno' => $customernumber,
'lang' => $def_language,
+ 'api_allowed' => $api_allowed,
'docroot' => $documentroot,
'guid' => $guid,
'diskspace' => $diskspace,
@@ -470,6 +454,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
`email` = :email,
`customernumber` = :customerno,
`def_language` = :lang,
+ `api_allowed` = :api_allowed,
`documentroot` = :docroot,
`guid` = :guid,
`diskspace` = :diskspace,
@@ -755,6 +740,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
* optional
* @param string $def_language,
* optional, default is system-default language
+ * @param bool $api_allowed
+ * optional, default is true if system setting api.enabled is true, else false
* @param int $gender
* optional, 0 = no-gender, 1 = male, 2 = female
* @param string $custom_notes
@@ -857,6 +844,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$fax = $this->getParam('fax', true, $result['fax']);
$customernumber = $this->getParam('customernumber', true, $result['customernumber']);
$def_language = $this->getParam('def_language', true, $result['def_language']);
+ $api_allowed = $this->getBoolParam('api_allowed', true, $result['api_allowed']);
$gender = (int) $this->getParam('gender', true, $result['gender']);
$custom_notes = $this->getParam('custom_notes', true, $result['custom_notes']);
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, $result['custom_notes_show']);
@@ -999,30 +987,10 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
\Froxlor\System\Cronjob::inserttask('1');
}
- if ($deactivated != '1') {
- $deactivated = '0';
- }
-
- if ($phpenabled != '0') {
- $phpenabled = '1';
- }
-
- if ($perlenabled != '0') {
- $perlenabled = '1';
- }
-
- if ($dnsenabled != '0') {
- $dnsenabled = '1';
- }
-
if ($phpenabled != $result['phpenabled'] || $perlenabled != $result['perlenabled']) {
\Froxlor\System\Cronjob::inserttask('1');
}
- if ($logviewenabled != '0') {
- $logviewenabled = '1';
- }
-
// activate/deactivate customer services
if ($deactivated != $result['deactivated']) {
@@ -1166,7 +1134,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
'dnsenabled' => $dnsenabled,
'logviewenabled' => $logviewenabled,
'custom_notes' => $custom_notes,
- 'custom_notes_show' => $custom_notes_show
+ 'custom_notes_show' => $custom_notes_show,
+ 'api_allowed' => $api_allowed
);
$upd_data = $upd_data + $admin_upd_data;
}
@@ -1207,7 +1176,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
`dnsenabled` = :dnsenabled,
`logviewenabled` = :logviewenabled,
`custom_notes` = :custom_notes,
- `custom_notes_show` = :custom_notes_show";
+ `custom_notes_show` = :custom_notes_show,
+ `api_allowed` = :api_allowed";
$upd_query .= $admin_upd_query;
}
$upd_query .= " WHERE `customerid` = :customerid";
diff --git a/lib/Froxlor/Api/FroxlorRPC.php b/lib/Froxlor/Api/FroxlorRPC.php
index d96e2c7c..f4dce617 100644
--- a/lib/Froxlor/Api/FroxlorRPC.php
+++ b/lib/Froxlor/Api/FroxlorRPC.php
@@ -55,13 +55,20 @@ class FroxlorRPC
*/
private static function validateAuth($key, $secret)
{
- $sel_stmt = \Froxlor\Database\Database::prepare("SELECT * FROM `api_keys` WHERE `apikey` = :ak AND `secret` = :as");
+ $sel_stmt = \Froxlor\Database\Database::prepare("
+ SELECT ak.*, a.api_allowed as admin_api_allowed, c.api_allowed as cust_api_allowed
+ 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
+ ");
$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())) {
+ 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))) {
+ // get user to check whether api call is allowed
if (! empty($result['allowed_from'])) {
// @todo allow specification and validating of whole subnets later
$ip_list = explode(",", $result['allowed_from']);
diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php
index 6abe1274..a9382f05 100644
--- a/lib/Froxlor/Froxlor.php
+++ b/lib/Froxlor/Froxlor.php
@@ -10,7 +10,7 @@ final class Froxlor
const VERSION = '0.10.0';
// Database version (YYYYMMDDC where C is a daily counter)
- const DBVERSION = '201910030';
+ const DBVERSION = '201910090';
// Distribution branding-tag (used for Debian etc.)
const BRANDING = '';
diff --git a/lib/formfields/admin/admin/formfield.admin_add.php b/lib/formfields/admin/admin/formfield.admin_add.php
index d2ac4b67..24b41211 100644
--- a/lib/formfields/admin/admin/formfield.admin_add.php
+++ b/lib/formfields/admin/admin/formfield.admin_add.php
@@ -44,6 +44,21 @@ return array(
'label' => $lng['login']['language'],
'type' => 'select',
'select_var' => $language_options
+ ),
+ 'api_allowed' => array(
+ 'label' => $lng['usersettings']['api_allowed']['title'],
+ 'desc' => $lng['usersettings']['api_allowed']['description'],
+ 'type' => 'checkbox',
+ 'values' => array(
+ array(
+ 'label' => $lng['panel']['yes'],
+ 'value' => '1'
+ )
+ ),
+ 'value' => array(
+ '1'
+ ),
+ 'visible' => (\Froxlor\Settings::Get('api.enabled') == '1' ? true : false)
)
)
),
diff --git a/lib/formfields/admin/admin/formfield.admin_edit.php b/lib/formfields/admin/admin/formfield.admin_edit.php
index b0b7f5a4..4827d4ae 100644
--- a/lib/formfields/admin/admin/formfield.admin_edit.php
+++ b/lib/formfields/admin/admin/formfield.admin_edit.php
@@ -59,6 +59,21 @@ return array(
'type' => 'select',
'select_var' => $language_options,
'visible' => ($result['adminid'] == $userinfo['userid'] ? false : true)
+ ),
+ 'api_allowed' => array(
+ 'label' => $lng['usersettings']['api_allowed']['title'],
+ 'desc' => $lng['usersettings']['api_allowed']['description'],
+ 'type' => 'checkbox',
+ 'values' => array(
+ array(
+ 'label' => $lng['panel']['yes'],
+ 'value' => '1'
+ )
+ ),
+ 'value' => array(
+ $result['api_allowed']
+ ),
+ 'visible' => (\Froxlor\Settings::Get('api.enabled') == '1' ? true : false)
)
)
),
diff --git a/lib/formfields/admin/customer/formfield.customer_add.php b/lib/formfields/admin/customer/formfield.customer_add.php
index 2afb1b2b..ede3cc94 100644
--- a/lib/formfields/admin/customer/formfield.customer_add.php
+++ b/lib/formfields/admin/customer/formfield.customer_add.php
@@ -81,6 +81,21 @@ return array(
'label' => $lng['login']['language'],
'type' => 'select',
'select_var' => $language_options
+ ),
+ 'api_allowed' => array(
+ 'label' => $lng['usersettings']['api_allowed']['title'],
+ 'desc' => $lng['usersettings']['api_allowed']['description'],
+ 'type' => 'checkbox',
+ 'values' => array(
+ array(
+ 'label' => $lng['panel']['yes'],
+ 'value' => '1'
+ )
+ ),
+ 'value' => array(
+ '1'
+ ),
+ 'visible' => (\Froxlor\Settings::Get('api.enabled') == '1' ? true : false)
)
)
),
@@ -294,9 +309,9 @@ return array(
'values' => $phpconfigs,
'value' => ((int) \Froxlor\Settings::Get('system.mod_fcgid') == 1 ? array(
\Froxlor\Settings::Get('system.mod_fcgid_defaultini')
- ) : (int) \Froxlor\Settings::Get('phpfpm.enabled') == 1 ? array(
+ ) : ((int) \Froxlor\Settings::Get('phpfpm.enabled') == 1 ? array(
\Froxlor\Settings::Get('phpfpm.defaultini')
- ) : array()),
+ ) : array())),
'is_array' => 1
),
'perlenabled' => array(
diff --git a/lib/formfields/admin/customer/formfield.customer_edit.php b/lib/formfields/admin/customer/formfield.customer_edit.php
index 9f5879da..47980f3c 100644
--- a/lib/formfields/admin/customer/formfield.customer_edit.php
+++ b/lib/formfields/admin/customer/formfield.customer_edit.php
@@ -74,6 +74,21 @@ return array(
'label' => $lng['login']['language'],
'type' => 'select',
'select_var' => $language_options
+ ),
+ 'api_allowed' => array(
+ 'label' => $lng['usersettings']['api_allowed']['title'],
+ 'desc' => $lng['usersettings']['api_allowed']['description'],
+ 'type' => 'checkbox',
+ 'values' => array(
+ array(
+ 'label' => $lng['panel']['yes'],
+ 'value' => '1'
+ )
+ ),
+ 'value' => array(
+ $result['api_allowed']
+ ),
+ 'visible' => (\Froxlor\Settings::Get('api.enabled') == '1' ? true : false)
)
)
),
diff --git a/lng/english.lng.php b/lng/english.lng.php
index 66c1debb..86980a64 100644
--- a/lng/english.lng.php
+++ b/lng/english.lng.php
@@ -2069,3 +2069,5 @@ $lng['serversettings']['froxloraliases']['description'] = "Comma separated list
$lng['serversettings']['ssl']['tlsv13_cipher_list']['title'] = 'Configure explicit TLSv1.3 ciphers if used';
$lng['serversettings']['ssl']['tlsv13_cipher_list']['description'] = 'This is a list of ciphers that you want (or don\'t want) to use when talking TLSv1.3. For a list of ciphers and how to include/exclude them, see the docs for TLSv1.3 .Default value is empty ';
+$lng['usersettings']['api_allowed']['title'] = 'Allow API access';
+$lng['usersettings']['api_allowed']['description'] = 'When enabled in the settings, this user can create API keys and access the froxlor API';
diff --git a/lng/german.lng.php b/lng/german.lng.php
index 0e012d30..a4988273 100644
--- a/lng/german.lng.php
+++ b/lng/german.lng.php
@@ -1716,3 +1716,5 @@ $lng['serversettings']['froxloraliases']['description'] = "Komma getrennte Liste
$lng['serversettings']['ssl']['tlsv13_cipher_list']['title'] = 'Explizite TLSv1.3 Ciphers, wenn genutzt';
$lng['serversettings']['ssl']['tlsv13_cipher_list']['description'] = 'Dies ist eine Liste von Ciphers, die genutzt werden sollen (oder auch nicht genutzt werden sollen), wenn eine TLSv1.3 Verbindung hergestellt werden soll. Eine Liste aller Ciphers und wie diese hinzugefügt/ausgeschlossen werden ist der Dokumentation für TLSv1.3 zu entnehmen.Standard-Wert ist leer ';
+$lng['usersettings']['api_allowed']['title'] = 'Erlaube API Zugriff';
+$lng['usersettings']['api_allowed']['description'] = 'Wenn in den Einstellungen aktiviert, kann der Benutzer API Schlüssel erstellen und auf die froxlor API Zugreifen';
From 2c23431daf1333c01deba9a70d7c06a27f39fddf Mon Sep 17 00:00:00 2001
From: Michael Kaufmann
Date: Wed, 9 Oct 2019 11:52:55 +0200
Subject: [PATCH 129/159] show on API keys page wether api access is allowed
Signed-off-by: Michael Kaufmann
---
lng/english.lng.php | 1 +
lng/german.lng.php | 1 +
templates/Sparkle/api_keys/keys_list.tpl | 13 +++++++++++++
3 files changed, 15 insertions(+)
diff --git a/lng/english.lng.php b/lng/english.lng.php
index 86980a64..076c67da 100644
--- a/lng/english.lng.php
+++ b/lng/english.lng.php
@@ -2071,3 +2071,4 @@ $lng['serversettings']['ssl']['tlsv13_cipher_list']['title'] = 'Configure explic
$lng['serversettings']['ssl']['tlsv13_cipher_list']['description'] = 'This is a list of ciphers that you want (or don\'t want) to use when talking TLSv1.3. For a list of ciphers and how to include/exclude them, see the docs for TLSv1.3 .Default value is empty ';
$lng['usersettings']['api_allowed']['title'] = 'Allow API access';
$lng['usersettings']['api_allowed']['description'] = 'When enabled in the settings, this user can create API keys and access the froxlor API';
+$lng['usersettings']['api_allowed']['notice'] = 'API access is not allowed for your account.';
diff --git a/lng/german.lng.php b/lng/german.lng.php
index a4988273..22fb4761 100644
--- a/lng/german.lng.php
+++ b/lng/german.lng.php
@@ -1718,3 +1718,4 @@ $lng['serversettings']['ssl']['tlsv13_cipher_list']['title'] = 'Explizite TLSv1.
$lng['serversettings']['ssl']['tlsv13_cipher_list']['description'] = 'Dies ist eine Liste von Ciphers, die genutzt werden sollen (oder auch nicht genutzt werden sollen), wenn eine TLSv1.3 Verbindung hergestellt werden soll. Eine Liste aller Ciphers und wie diese hinzugefügt/ausgeschlossen werden ist der Dokumentation für TLSv1.3 zu entnehmen.Standard-Wert ist leer ';
$lng['usersettings']['api_allowed']['title'] = 'Erlaube API Zugriff';
$lng['usersettings']['api_allowed']['description'] = 'Wenn in den Einstellungen aktiviert, kann der Benutzer API Schlüssel erstellen und auf die froxlor API Zugreifen';
+$lng['usersettings']['api_allowed']['notice'] = 'API Zugriff ist für dieses Konto deaktiviert.';
diff --git a/templates/Sparkle/api_keys/keys_list.tpl b/templates/Sparkle/api_keys/keys_list.tpl
index 43cdf15d..2c4407d1 100644
--- a/templates/Sparkle/api_keys/keys_list.tpl
+++ b/templates/Sparkle/api_keys/keys_list.tpl
@@ -16,6 +16,15 @@
+
+
+
+
{$lng['admin']['warning']}
+
{$lng['usersettings']['api_allowed']['notice']}
+
+
+
+