Merge remote-tracking branch 'refs/remotes/origin/0.11-dev' into 0.11-dev

This commit is contained in:
envoyr
2022-08-21 17:49:21 +02:00
89 changed files with 1169 additions and 960 deletions

View File

@@ -35,6 +35,7 @@ use Froxlor\Settings;
use Froxlor\UI\Panel\UI; use Froxlor\UI\Panel\UI;
use Froxlor\UI\Response; use Froxlor\UI\Response;
use Froxlor\PhpHelper; use Froxlor\PhpHelper;
use Froxlor\User;
if (Settings::Get('2fa.enabled') != '1') { if (Settings::Get('2fa.enabled') != '1') {
Response::dynamicError('2fa.2fa_not_activated'); Response::dynamicError('2fa.2fa_not_activated');

View File

@@ -42,7 +42,7 @@ return [
'settinggroup' => 'system', 'settinggroup' => 'system',
'varname' => 'froxlordirectlyviahostname', 'varname' => 'froxlordirectlyviahostname',
'type' => 'checkbox', 'type' => 'checkbox',
'default' => false, 'default' => true,
'save_method' => 'storeSettingField' 'save_method' => 'storeSettingField'
], ],
'system_froxloraliases' => [ 'system_froxloraliases' => [

View File

@@ -62,14 +62,6 @@ return [
'type' => 'checkbox', 'type' => 'checkbox',
'default' => false, 'default' => false,
'save_method' => 'storeSettingField' 'save_method' => 'storeSettingField'
],
'system_debug_cron' => [
'label' => lng('serversettings.cron.debug'),
'settinggroup' => 'system',
'varname' => 'debug_cron',
'type' => 'checkbox',
'default' => false,
'save_method' => 'storeSettingField'
] ]
] ]
] ]

View File

@@ -29,7 +29,7 @@ return [
'title' => lng('admin.spfsettings'), 'title' => lng('admin.spfsettings'),
'icon' => 'fa-solid fa-clipboard-check', 'icon' => 'fa-solid fa-clipboard-check',
'fields' => [ 'fields' => [
'spf_enabled' => [ 'use_spf' => [
'label' => lng('spf.use_spf'), 'label' => lng('spf.use_spf'),
'settinggroup' => 'spf', 'settinggroup' => 'spf',
'varname' => 'use_spf', 'varname' => 'use_spf',

View File

@@ -37,6 +37,7 @@ use Froxlor\UI\Panel\UI;
use Froxlor\UI\Request; use Froxlor\UI\Request;
use Froxlor\UI\Response; use Froxlor\UI\Response;
use Froxlor\Validate\Validate; use Froxlor\Validate\Validate;
use Froxlor\CurrentUser;
$id = (int)Request::get('id'); $id = (int)Request::get('id');
$subjectid = intval(Request::get('subjectid')); $subjectid = intval(Request::get('subjectid'));

View File

@@ -26,11 +26,12 @@
const AREA = 'admin'; const AREA = 'admin';
require __DIR__ . '/lib/init.php'; require __DIR__ . '/lib/init.php';
use Exception;
use Froxlor\Cron\TaskId; use Froxlor\Cron\TaskId;
use Froxlor\Database\Database;
use Froxlor\Froxlor; use Froxlor\Froxlor;
use Froxlor\FroxlorLogger; use Froxlor\FroxlorLogger;
use Froxlor\Install\Preconfig; use Froxlor\Install\Preconfig;
use Froxlor\Install\Update;
use Froxlor\Settings; use Froxlor\Settings;
use Froxlor\System\Cronjob; use Froxlor\System\Cronjob;
use Froxlor\UI\Panel\UI; use Froxlor\UI\Panel\UI;
@@ -40,32 +41,8 @@ use Froxlor\User;
if ($page == 'overview') { if ($page == 'overview') {
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_updates"); $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_updates");
/**
* this is a dirty hack but syscp 1.4.2.1 does not
* have any version/dbversion in the database (don't know why)
* so we have to set them both to run a correct upgrade
*/
if (!Froxlor::isFroxlor()) { if (!Froxlor::isFroxlor()) {
if (Settings::Get('panel.version') == null || Settings::Get('panel.version') == '') { throw new Exception('SysCP/customized upgrades are not supported');
Settings::Set('panel.version', '1.4.2.1');
}
if (Settings::Get('system.dbversion') == null || Settings::Get('system.dbversion') == '') {
/**
* for syscp-stable (1.4.2.1) this value has to be 0
* so the required table-fields are added correctly
* and the svn-version has its value in the database
* -> bug #54
*/
$result_stmt = Database::query("
SELECT `value` FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `varname` = 'dbversion'");
$result = $result_stmt->fetch(PDO::FETCH_ASSOC);
if (isset($result['value'])) {
Settings::Set('system.dbversion', (int)$result['value'], false);
} else {
Settings::Set('system.dbversion', 0, false);
}
}
} }
if (Froxlor::hasDbUpdates() || Froxlor::hasUpdates()) { if (Froxlor::hasDbUpdates() || Froxlor::hasUpdates()) {
@@ -81,7 +58,7 @@ if ($page == 'overview') {
@chmod(Froxlor::getInstallDir() . '/lib/userdata.inc.php', 0400); @chmod(Froxlor::getInstallDir() . '/lib/userdata.inc.php', 0400);
UI::view('install/update.html.twig', [ UI::view('install/update.html.twig', [
'checks' => $update_tasks 'checks' => Update::getUpdateTasks()
]); ]);
exit; exit;
} else { } else {

View File

@@ -33,6 +33,8 @@ use Froxlor\Cli\PhpSessionclean;
use Froxlor\Cli\SwitchServerIp; use Froxlor\Cli\SwitchServerIp;
use Froxlor\Cli\UpdateCommand; use Froxlor\Cli\UpdateCommand;
use Froxlor\Cli\InstallCommand; use Froxlor\Cli\InstallCommand;
use Froxlor\Cli\MasterCron;
use Froxlor\Cli\UserCommand;
use Froxlor\Froxlor; use Froxlor\Froxlor;
// validate correct php version // validate correct php version
@@ -55,4 +57,6 @@ $application->add(new PhpSessionclean());
$application->add(new SwitchServerIp()); $application->add(new SwitchServerIp());
$application->add(new UpdateCommand()); $application->add(new UpdateCommand());
$application->add(new InstallCommand()); $application->add(new InstallCommand());
$application->add(new MasterCron());
$application->add(new UserCommand());
$application->run(); $application->run();

View File

@@ -19,7 +19,6 @@
"email": "team@froxlor.org", "email": "team@froxlor.org",
"issues": "https://github.com/Froxlor/Froxlor/issues", "issues": "https://github.com/Froxlor/Froxlor/issues",
"forum": "https://forum.froxlor.org/", "forum": "https://forum.froxlor.org/",
"irc": "irc://irc.libera.chat/froxlor",
"source": "https://github.com/Froxlor/Froxlor", "source": "https://github.com/Froxlor/Froxlor",
"docs": "https://docs.froxlor.org/", "docs": "https://docs.froxlor.org/",
"chat": "https://discord.froxlor.org/" "chat": "https://discord.froxlor.org/"
@@ -64,7 +63,8 @@
"sebastian/phpcpd": "^6.0", "sebastian/phpcpd": "^6.0",
"phploc/phploc": "^7.0", "phploc/phploc": "^7.0",
"phpmd/phpmd": "^2.10", "phpmd/phpmd": "^2.10",
"phpunit/php-timer" : "^5" "phpunit/php-timer" : "^5",
"phpstan/phpstan": "^1.8"
}, },
"suggest": { "suggest": {
"ext-bcmath": "*", "ext-bcmath": "*",

359
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "050664b27120307bec7721bac4ecb395", "content-hash": "f8370edea3c85bcb7b681926a1fff04e",
"packages": [ "packages": [
{ {
"name": "erusev/parsedown", "name": "erusev/parsedown",
@@ -114,16 +114,16 @@
}, },
{ {
"name": "monolog/monolog", "name": "monolog/monolog",
"version": "1.27.0", "version": "1.27.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/Seldaek/monolog.git", "url": "https://github.com/Seldaek/monolog.git",
"reference": "52ebd235c1f7e0d5e1b16464b695a28335f8e44a" "reference": "904713c5929655dc9b97288b69cfeedad610c9a1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/52ebd235c1f7e0d5e1b16464b695a28335f8e44a", "url": "https://api.github.com/repos/Seldaek/monolog/zipball/904713c5929655dc9b97288b69cfeedad610c9a1",
"reference": "52ebd235c1f7e0d5e1b16464b695a28335f8e44a", "reference": "904713c5929655dc9b97288b69cfeedad610c9a1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -184,7 +184,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/Seldaek/monolog/issues", "issues": "https://github.com/Seldaek/monolog/issues",
"source": "https://github.com/Seldaek/monolog/tree/1.27.0" "source": "https://github.com/Seldaek/monolog/tree/1.27.1"
}, },
"funding": [ "funding": [
{ {
@@ -196,20 +196,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-03-13T20:29:46+00:00" "time": "2022-06-09T08:53:42+00:00"
}, },
{ {
"name": "phpmailer/phpmailer", "name": "phpmailer/phpmailer",
"version": "v6.6.0", "version": "v6.6.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git", "url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "e43bac82edc26ca04b36143a48bde1c051cfd5b1" "reference": "9400f305a898f194caff5521f64e5dfa926626f3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/e43bac82edc26ca04b36143a48bde1c051cfd5b1", "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/9400f305a898f194caff5521f64e5dfa926626f3",
"reference": "e43bac82edc26ca04b36143a48bde1c051cfd5b1", "reference": "9400f305a898f194caff5521f64e5dfa926626f3",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -221,8 +221,8 @@
"require-dev": { "require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"doctrine/annotations": "^1.2", "doctrine/annotations": "^1.2",
"php-parallel-lint/php-console-highlighter": "^0.5.0", "php-parallel-lint/php-console-highlighter": "^1.0.0",
"php-parallel-lint/php-parallel-lint": "^1.3.1", "php-parallel-lint/php-parallel-lint": "^1.3.2",
"phpcompatibility/php-compatibility": "^9.3.5", "phpcompatibility/php-compatibility": "^9.3.5",
"roave/security-advisories": "dev-latest", "roave/security-advisories": "dev-latest",
"squizlabs/php_codesniffer": "^3.6.2", "squizlabs/php_codesniffer": "^3.6.2",
@@ -266,7 +266,7 @@
"description": "PHPMailer is a full-featured email creation and transfer class for PHP", "description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"support": { "support": {
"issues": "https://github.com/PHPMailer/PHPMailer/issues", "issues": "https://github.com/PHPMailer/PHPMailer/issues",
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.6.0" "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.6.3"
}, },
"funding": [ "funding": [
{ {
@@ -274,7 +274,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2022-02-28T15:31:21+00:00" "time": "2022-06-20T09:21:02+00:00"
}, },
{ {
"name": "psr/container", "name": "psr/container",
@@ -446,16 +446,16 @@
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v5.4.7", "version": "v5.4.11",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "900275254f0a1a2afff1ab0e11abd5587a10e1d6" "reference": "535846c7ee6bc4dd027ca0d93220601456734b10"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/900275254f0a1a2afff1ab0e11abd5587a10e1d6", "url": "https://api.github.com/repos/symfony/console/zipball/535846c7ee6bc4dd027ca0d93220601456734b10",
"reference": "900275254f0a1a2afff1ab0e11abd5587a10e1d6", "reference": "535846c7ee6bc4dd027ca0d93220601456734b10",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -525,7 +525,7 @@
"terminal" "terminal"
], ],
"support": { "support": {
"source": "https://github.com/symfony/console/tree/v5.4.7" "source": "https://github.com/symfony/console/tree/v5.4.11"
}, },
"funding": [ "funding": [
{ {
@@ -541,11 +541,11 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-03-31T17:09:19+00:00" "time": "2022-07-22T10:42:43+00:00"
}, },
{ {
"name": "symfony/deprecation-contracts", "name": "symfony/deprecation-contracts",
"version": "v2.5.1", "version": "v2.5.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git", "url": "https://github.com/symfony/deprecation-contracts.git",
@@ -592,7 +592,7 @@
"description": "A generic function and convention to trigger deprecation notices", "description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.1" "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2"
}, },
"funding": [ "funding": [
{ {
@@ -612,16 +612,16 @@
}, },
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",
"version": "v1.25.0", "version": "v1.26.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git", "url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "30885182c981ab175d4d034db0f6f469898070ab" "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab", "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
"reference": "30885182c981ab175d4d034db0f6f469898070ab", "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -636,7 +636,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-main": "1.23-dev" "dev-main": "1.26-dev"
}, },
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
@@ -674,7 +674,7 @@
"portable" "portable"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0" "source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
}, },
"funding": [ "funding": [
{ {
@@ -690,20 +690,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-10-20T20:35:02+00:00" "time": "2022-05-24T11:49:31+00:00"
}, },
{ {
"name": "symfony/polyfill-iconv", "name": "symfony/polyfill-iconv",
"version": "v1.25.0", "version": "v1.26.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-iconv.git", "url": "https://github.com/symfony/polyfill-iconv.git",
"reference": "f1aed619e28cb077fc83fac8c4c0383578356e40" "reference": "143f1881e655bebca1312722af8068de235ae5dc"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/f1aed619e28cb077fc83fac8c4c0383578356e40", "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/143f1881e655bebca1312722af8068de235ae5dc",
"reference": "f1aed619e28cb077fc83fac8c4c0383578356e40", "reference": "143f1881e655bebca1312722af8068de235ae5dc",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -718,7 +718,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-main": "1.23-dev" "dev-main": "1.26-dev"
}, },
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
@@ -757,7 +757,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-iconv/tree/v1.25.0" "source": "https://github.com/symfony/polyfill-iconv/tree/v1.26.0"
}, },
"funding": [ "funding": [
{ {
@@ -773,20 +773,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-01-04T09:04:05+00:00" "time": "2022-05-24T11:49:31+00:00"
}, },
{ {
"name": "symfony/polyfill-intl-grapheme", "name": "symfony/polyfill-intl-grapheme",
"version": "v1.25.0", "version": "v1.26.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "81b86b50cf841a64252b439e738e97f4a34e2783" "reference": "433d05519ce6990bf3530fba6957499d327395c2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783", "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2",
"reference": "81b86b50cf841a64252b439e738e97f4a34e2783", "reference": "433d05519ce6990bf3530fba6957499d327395c2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -798,7 +798,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-main": "1.23-dev" "dev-main": "1.26-dev"
}, },
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
@@ -838,7 +838,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.25.0" "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0"
}, },
"funding": [ "funding": [
{ {
@@ -854,20 +854,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-11-23T21:10:46+00:00" "time": "2022-05-24T11:49:31+00:00"
}, },
{ {
"name": "symfony/polyfill-intl-normalizer", "name": "symfony/polyfill-intl-normalizer",
"version": "v1.25.0", "version": "v1.26.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8" "reference": "219aa369ceff116e673852dce47c3a41794c14bd"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8", "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8", "reference": "219aa369ceff116e673852dce47c3a41794c14bd",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -879,7 +879,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-main": "1.23-dev" "dev-main": "1.26-dev"
}, },
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
@@ -922,7 +922,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0" "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
}, },
"funding": [ "funding": [
{ {
@@ -938,20 +938,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-02-19T12:13:01+00:00" "time": "2022-05-24T11:49:31+00:00"
}, },
{ {
"name": "symfony/polyfill-mbstring", "name": "symfony/polyfill-mbstring",
"version": "v1.25.0", "version": "v1.26.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git", "url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825" "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825", "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825", "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -966,7 +966,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-main": "1.23-dev" "dev-main": "1.26-dev"
}, },
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
@@ -1005,7 +1005,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0" "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
}, },
"funding": [ "funding": [
{ {
@@ -1021,20 +1021,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-11-30T18:21:41+00:00" "time": "2022-05-24T11:49:31+00:00"
}, },
{ {
"name": "symfony/polyfill-php72", "name": "symfony/polyfill-php72",
"version": "v1.25.0", "version": "v1.26.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-php72.git", "url": "https://github.com/symfony/polyfill-php72.git",
"reference": "9a142215a36a3888e30d0a9eeea9766764e96976" "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976", "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/bf44a9fd41feaac72b074de600314a93e2ae78e2",
"reference": "9a142215a36a3888e30d0a9eeea9766764e96976", "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1043,7 +1043,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-main": "1.23-dev" "dev-main": "1.26-dev"
}, },
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
@@ -1081,7 +1081,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-php72/tree/v1.25.0" "source": "https://github.com/symfony/polyfill-php72/tree/v1.26.0"
}, },
"funding": [ "funding": [
{ {
@@ -1097,20 +1097,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-05-27T09:17:38+00:00" "time": "2022-05-24T11:49:31+00:00"
}, },
{ {
"name": "symfony/polyfill-php73", "name": "symfony/polyfill-php73",
"version": "v1.25.0", "version": "v1.26.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-php73.git", "url": "https://github.com/symfony/polyfill-php73.git",
"reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5" "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/cc5db0e22b3cb4111010e48785a97f670b350ca5", "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/e440d35fa0286f77fb45b79a03fedbeda9307e85",
"reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5", "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1119,7 +1119,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-main": "1.23-dev" "dev-main": "1.26-dev"
}, },
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
@@ -1160,7 +1160,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-php73/tree/v1.25.0" "source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0"
}, },
"funding": [ "funding": [
{ {
@@ -1176,20 +1176,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-06-05T21:20:04+00:00" "time": "2022-05-24T11:49:31+00:00"
}, },
{ {
"name": "symfony/polyfill-php80", "name": "symfony/polyfill-php80",
"version": "v1.25.0", "version": "v1.26.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-php80.git", "url": "https://github.com/symfony/polyfill-php80.git",
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c" "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c", "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c", "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1198,7 +1198,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-main": "1.23-dev" "dev-main": "1.26-dev"
}, },
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
@@ -1243,7 +1243,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0" "source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
}, },
"funding": [ "funding": [
{ {
@@ -1259,20 +1259,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-03-04T08:16:47+00:00" "time": "2022-05-10T07:21:04+00:00"
}, },
{ {
"name": "symfony/service-contracts", "name": "symfony/service-contracts",
"version": "v2.5.1", "version": "v2.5.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/service-contracts.git", "url": "https://github.com/symfony/service-contracts.git",
"reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c" "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/24d9dc654b83e91aa59f9d167b131bc3b5bea24c", "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
"reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c", "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1326,7 +1326,7 @@
"standards" "standards"
], ],
"support": { "support": {
"source": "https://github.com/symfony/service-contracts/tree/v2.5.1" "source": "https://github.com/symfony/service-contracts/tree/v2.5.2"
}, },
"funding": [ "funding": [
{ {
@@ -1342,20 +1342,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-03-13T20:07:29+00:00" "time": "2022-05-30T19:17:29+00:00"
}, },
{ {
"name": "symfony/string", "name": "symfony/string",
"version": "v5.4.3", "version": "v5.4.11",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/string.git", "url": "https://github.com/symfony/string.git",
"reference": "92043b7d8383e48104e411bc9434b260dbeb5a10" "reference": "5eb661e49ad389e4ae2b6e4df8d783a8a6548322"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/92043b7d8383e48104e411bc9434b260dbeb5a10", "url": "https://api.github.com/repos/symfony/string/zipball/5eb661e49ad389e4ae2b6e4df8d783a8a6548322",
"reference": "92043b7d8383e48104e411bc9434b260dbeb5a10", "reference": "5eb661e49ad389e4ae2b6e4df8d783a8a6548322",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1412,7 +1412,7 @@
"utf8" "utf8"
], ],
"support": { "support": {
"source": "https://github.com/symfony/string/tree/v5.4.3" "source": "https://github.com/symfony/string/tree/v5.4.11"
}, },
"funding": [ "funding": [
{ {
@@ -1428,20 +1428,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-01-02T09:53:40+00:00" "time": "2022-07-24T16:15:25+00:00"
}, },
{ {
"name": "twig/twig", "name": "twig/twig",
"version": "v3.3.10", "version": "v3.4.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/twigphp/Twig.git", "url": "https://github.com/twigphp/Twig.git",
"reference": "8442df056c51b706793adf80a9fd363406dd3674" "reference": "e939eae92386b69b49cfa4599dd9bead6bf4a342"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/8442df056c51b706793adf80a9fd363406dd3674", "url": "https://api.github.com/repos/twigphp/Twig/zipball/e939eae92386b69b49cfa4599dd9bead6bf4a342",
"reference": "8442df056c51b706793adf80a9fd363406dd3674", "reference": "e939eae92386b69b49cfa4599dd9bead6bf4a342",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1456,7 +1456,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "3.3-dev" "dev-master": "3.4-dev"
} }
}, },
"autoload": { "autoload": {
@@ -1492,7 +1492,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/twigphp/Twig/issues", "issues": "https://github.com/twigphp/Twig/issues",
"source": "https://github.com/twigphp/Twig/tree/v3.3.10" "source": "https://github.com/twigphp/Twig/tree/v3.4.1"
}, },
"funding": [ "funding": [
{ {
@@ -1504,7 +1504,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-04-06T06:47:41+00:00" "time": "2022-05-17T05:48:52+00:00"
}, },
{ {
"name": "voku/anti-xss", "name": "voku/anti-xss",
@@ -2032,16 +2032,16 @@
}, },
{ {
"name": "nikic/php-parser", "name": "nikic/php-parser",
"version": "v4.13.2", "version": "v4.14.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nikic/PHP-Parser.git", "url": "https://github.com/nikic/PHP-Parser.git",
"reference": "210577fe3cf7badcc5814d99455df46564f3c077" "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077", "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/34bea19b6e03d8153165d8f30bba4c3be86184c1",
"reference": "210577fe3cf7badcc5814d99455df46564f3c077", "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2082,9 +2082,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/nikic/PHP-Parser/issues", "issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.13.2" "source": "https://github.com/nikic/PHP-Parser/tree/v4.14.0"
}, },
"time": "2021-11-30T19:35:32+00:00" "time": "2022-05-31T20:59:12+00:00"
}, },
{ {
"name": "pdepend/pdepend", "name": "pdepend/pdepend",
@@ -2687,6 +2687,65 @@
}, },
"time": "2021-12-08T12:19:24+00:00" "time": "2021-12-08T12:19:24+00:00"
}, },
{
"name": "phpstan/phpstan",
"version": "1.8.2",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/c53312ecc575caf07b0e90dee43883fdf90ca67c",
"reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c",
"shasum": ""
},
"require": {
"php": "^7.2|^8.0"
},
"conflict": {
"phpstan/phpstan-shim": "*"
},
"bin": [
"phpstan",
"phpstan.phar"
],
"type": "library",
"autoload": {
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPStan - PHP Static Analysis Tool",
"support": {
"issues": "https://github.com/phpstan/phpstan/issues",
"source": "https://github.com/phpstan/phpstan/tree/1.8.2"
},
"funding": [
{
"url": "https://github.com/ondrejmirtes",
"type": "github"
},
{
"url": "https://github.com/phpstan",
"type": "github"
},
{
"url": "https://www.patreon.com/phpstan",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan",
"type": "tidelift"
}
],
"time": "2022-07-20T09:57:31+00:00"
},
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",
"version": "9.2.15", "version": "9.2.15",
@@ -3007,16 +3066,16 @@
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "9.5.20", "version": "9.5.21",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "12bc8879fb65aef2138b26fc633cb1e3620cffba" "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/12bc8879fb65aef2138b26fc633cb1e3620cffba", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0e32b76be457de00e83213528f6bb37e2a38fcb1",
"reference": "12bc8879fb65aef2138b26fc633cb1e3620cffba", "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3050,7 +3109,6 @@
"sebastian/version": "^3.0.2" "sebastian/version": "^3.0.2"
}, },
"require-dev": { "require-dev": {
"ext-pdo": "*",
"phpspec/prophecy-phpunit": "^2.0.1" "phpspec/prophecy-phpunit": "^2.0.1"
}, },
"suggest": { "suggest": {
@@ -3094,7 +3152,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues", "issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.20" "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.21"
}, },
"funding": [ "funding": [
{ {
@@ -3106,7 +3164,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2022-04-01T12:37:26+00:00" "time": "2022-06-19T12:14:25+00:00"
}, },
{ {
"name": "sebastian/cli-parser", "name": "sebastian/cli-parser",
@@ -4135,16 +4193,16 @@
}, },
{ {
"name": "squizlabs/php_codesniffer", "name": "squizlabs/php_codesniffer",
"version": "3.6.2", "version": "3.7.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "5e4e71592f69da17871dba6e80dd51bce74a351a" "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a", "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619",
"reference": "5e4e71592f69da17871dba6e80dd51bce74a351a", "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -4187,20 +4245,20 @@
"source": "https://github.com/squizlabs/PHP_CodeSniffer", "source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
}, },
"time": "2021-12-12T21:44:58+00:00" "time": "2022-06-18T07:21:10+00:00"
}, },
{ {
"name": "symfony/config", "name": "symfony/config",
"version": "v5.4.7", "version": "v5.4.11",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/config.git", "url": "https://github.com/symfony/config.git",
"reference": "05624c386afa1b4ccc1357463d830fade8d9d404" "reference": "ec79e03125c1d2477e43dde8528535d90cc78379"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/config/zipball/05624c386afa1b4ccc1357463d830fade8d9d404", "url": "https://api.github.com/repos/symfony/config/zipball/ec79e03125c1d2477e43dde8528535d90cc78379",
"reference": "05624c386afa1b4ccc1357463d830fade8d9d404", "reference": "ec79e03125c1d2477e43dde8528535d90cc78379",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -4250,7 +4308,7 @@
"description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "description": "Helps you find, load, combine, autofill and validate configuration values of any kind",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/config/tree/v5.4.7" "source": "https://github.com/symfony/config/tree/v5.4.11"
}, },
"funding": [ "funding": [
{ {
@@ -4266,20 +4324,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-03-21T13:42:03+00:00" "time": "2022-07-20T13:00:38+00:00"
}, },
{ {
"name": "symfony/dependency-injection", "name": "symfony/dependency-injection",
"version": "v5.4.7", "version": "v5.4.11",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/dependency-injection.git", "url": "https://github.com/symfony/dependency-injection.git",
"reference": "35588b2afb08ea3a142d62fefdcad4cb09be06ed" "reference": "a8b9251016e9476db73e25fa836904bc0bf74c62"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/35588b2afb08ea3a142d62fefdcad4cb09be06ed", "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/a8b9251016e9476db73e25fa836904bc0bf74c62",
"reference": "35588b2afb08ea3a142d62fefdcad4cb09be06ed", "reference": "a8b9251016e9476db73e25fa836904bc0bf74c62",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -4339,7 +4397,7 @@
"description": "Allows you to standardize and centralize the way objects are constructed in your application", "description": "Allows you to standardize and centralize the way objects are constructed in your application",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/dependency-injection/tree/v5.4.7" "source": "https://github.com/symfony/dependency-injection/tree/v5.4.11"
}, },
"funding": [ "funding": [
{ {
@@ -4355,20 +4413,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-03-08T15:43:06+00:00" "time": "2022-07-20T13:00:38+00:00"
}, },
{ {
"name": "symfony/filesystem", "name": "symfony/filesystem",
"version": "v5.4.7", "version": "v5.4.11",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/filesystem.git", "url": "https://github.com/symfony/filesystem.git",
"reference": "3a4442138d80c9f7b600fb297534ac718b61d37f" "reference": "6699fb0228d1bc35b12aed6dd5e7455457609ddd"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/3a4442138d80c9f7b600fb297534ac718b61d37f", "url": "https://api.github.com/repos/symfony/filesystem/zipball/6699fb0228d1bc35b12aed6dd5e7455457609ddd",
"reference": "3a4442138d80c9f7b600fb297534ac718b61d37f", "reference": "6699fb0228d1bc35b12aed6dd5e7455457609ddd",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -4403,7 +4461,7 @@
"description": "Provides basic utilities for the filesystem", "description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/filesystem/tree/v5.4.7" "source": "https://github.com/symfony/filesystem/tree/v5.4.11"
}, },
"funding": [ "funding": [
{ {
@@ -4419,20 +4477,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-04-01T12:33:59+00:00" "time": "2022-07-20T13:00:38+00:00"
}, },
{ {
"name": "symfony/polyfill-php81", "name": "symfony/polyfill-php81",
"version": "v1.25.0", "version": "v1.26.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-php81.git", "url": "https://github.com/symfony/polyfill-php81.git",
"reference": "5de4ba2d41b15f9bd0e19b2ab9674135813ec98f" "reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/5de4ba2d41b15f9bd0e19b2ab9674135813ec98f", "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/13f6d1271c663dc5ae9fb843a8f16521db7687a1",
"reference": "5de4ba2d41b15f9bd0e19b2ab9674135813ec98f", "reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -4441,7 +4499,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-main": "1.23-dev" "dev-main": "1.26-dev"
}, },
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
@@ -4482,7 +4540,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-php81/tree/v1.25.0" "source": "https://github.com/symfony/polyfill-php81/tree/v1.26.0"
}, },
"funding": [ "funding": [
{ {
@@ -4498,7 +4556,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-09-13T13:58:11+00:00" "time": "2022-05-24T11:49:31+00:00"
}, },
{ {
"name": "theseer/tokenizer", "name": "theseer/tokenizer",
@@ -4552,21 +4610,21 @@
}, },
{ {
"name": "webmozart/assert", "name": "webmozart/assert",
"version": "1.10.0", "version": "1.11.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/webmozarts/assert.git", "url": "https://github.com/webmozarts/assert.git",
"reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
"reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.2 || ^8.0", "ext-ctype": "*",
"symfony/polyfill-ctype": "^1.8" "php": "^7.2 || ^8.0"
}, },
"conflict": { "conflict": {
"phpstan/phpstan": "<0.12.20", "phpstan/phpstan": "<0.12.20",
@@ -4604,9 +4662,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/webmozarts/assert/issues", "issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/1.10.0" "source": "https://github.com/webmozarts/assert/tree/1.11.0"
}, },
"time": "2021-03-09T10:59:23+00:00" "time": "2022-06-03T18:03:27+00:00"
} }
], ],
"aliases": [], "aliases": [],
@@ -4628,7 +4686,8 @@
"ext-curl": "*", "ext-curl": "*",
"ext-json": "*", "ext-json": "*",
"ext-openssl": "*", "ext-openssl": "*",
"ext-fileinfo": "*" "ext-fileinfo": "*",
"ext-gmp": "*"
}, },
"platform-dev": { "platform-dev": {
"ext-pcntl": "*" "ext-pcntl": "*"

View File

@@ -411,7 +411,7 @@ if ($action == 'forgotpwd') {
if (isset($_POST['send']) && $_POST['send'] == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
$loginname = Validate::validate($_POST['loginname'], 'loginname'); $loginname = Validate::validate($_POST['loginname'], 'loginname');
$email = Validate::validateEmail($_POST['loginemail'], 'email'); $email = Validate::validateEmail($_POST['loginemail']);
$result_stmt = Database::prepare("SELECT `adminid`, `customerid`, `customernumber`, `firstname`, `name`, `company`, `email`, `loginname`, `def_language`, `deactivated` FROM `" . TABLE_PANEL_CUSTOMERS . "` $result_stmt = Database::prepare("SELECT `adminid`, `customerid`, `customernumber`, `firstname`, `name`, `company`, `email`, `loginname`, `def_language`, `deactivated` FROM `" . TABLE_PANEL_CUSTOMERS . "`
WHERE `loginname`= :loginname WHERE `loginname`= :loginname
AND `email`= :email"); AND `email`= :email");

View File

@@ -598,7 +598,7 @@ opcache.validate_timestamps'),
('system', 'ftpserver', 'proftpd'), ('system', 'ftpserver', 'proftpd'),
('system', 'dns_createmailentry', '0'), ('system', 'dns_createmailentry', '0'),
('system', 'dns_createcaaentry', '1'), ('system', 'dns_createcaaentry', '1'),
('system', 'froxlordirectlyviahostname', '0'), ('system', 'froxlordirectlyviahostname', '1'),
('system', 'report_enable', '1'), ('system', 'report_enable', '1'),
('system', 'report_webmax', '90'), ('system', 'report_webmax', '90'),
('system', 'report_trafficmax', '90'), ('system', 'report_trafficmax', '90'),

View File

@@ -51,10 +51,9 @@ if (!file_exists(dirname(__DIR__) . '/vendor/autoload.php')) {
} }
// check installation status // check installation status
// @fixme userdata.inc.php is created iun step3 so step4 is never shown
if (file_exists(dirname(__DIR__) . '/lib/userdata.inc.php')) { if (file_exists(dirname(__DIR__) . '/lib/userdata.inc.php')) {
http_response_code(404); header("Location: ../");
die(); exit;
} }
require dirname(__DIR__) . '/vendor/autoload.php'; require dirname(__DIR__) . '/vendor/autoload.php';

View File

@@ -24,10 +24,12 @@
*/ */
use Froxlor\Froxlor; use Froxlor\Froxlor;
use Froxlor\FileDir;
use Froxlor\Database\Database; use Froxlor\Database\Database;
use Froxlor\Settings; use Froxlor\Settings;
use Froxlor\Install\Update; use Froxlor\Install\Update;
use Froxlor\System\Cronjob; use Froxlor\System\Cronjob;
use Froxlor\System\IPTools;
if (!defined('_CRON_UPDATE')) { if (!defined('_CRON_UPDATE')) {
if (!defined('AREA') || (defined('AREA') && AREA != 'admin') || !isset($userinfo['loginname']) || (isset($userinfo['loginname']) && $userinfo['loginname'] == '')) { if (!defined('AREA') || (defined('AREA') && AREA != 'admin') || !isset($userinfo['loginname']) || (isset($userinfo['loginname']) && $userinfo['loginname'] == '')) {
@@ -96,7 +98,7 @@ if (Froxlor::isDatabaseVersion('201809280')) {
if (Froxlor::isDatabaseVersion('201811180')) { if (Froxlor::isDatabaseVersion('201811180')) {
Update::showUpdateStep("Adding new settings for 2FA"); Update::showUpdateStep("Adding new settings for 2FA");
Settings::AddNew('2fa.enabled', '1', true); Settings::AddNew('2fa.enabled', '1');
Update::lastStepStatus(0); Update::lastStepStatus(0);
Update::showUpdateStep("Adding new fields to admin-table for 2FA"); Update::showUpdateStep("Adding new fields to admin-table for 2FA");
@@ -125,7 +127,7 @@ if (Froxlor::isDatabaseVersion('201812010')) {
Update::showUpdateStep("Adding new is_configured-flag"); Update::showUpdateStep("Adding new is_configured-flag");
// updated systems are already configured (most likely :P) // updated systems are already configured (most likely :P)
Settings::AddNew('panel.is_configured', '1', true); Settings::AddNew('panel.is_configured', '1');
Update::lastStepStatus(0); Update::lastStepStatus(0);
Froxlor::updateToDbVersion('201812100'); Froxlor::updateToDbVersion('201812100');
@@ -285,8 +287,8 @@ if (Froxlor::isFroxlorVersion('0.10.0-rc1')) {
if (Froxlor::isDatabaseVersion('201904250')) { if (Froxlor::isDatabaseVersion('201904250')) {
Update::showUpdateStep("Adding new settings for CAA"); Update::showUpdateStep("Adding new settings for CAA");
Settings::AddNew('caa.caa_entry', '', true); Settings::AddNew('caa.caa_entry', '');
Settings::AddNew('system.dns_createcaaentry', 1, true); Settings::AddNew('system.dns_createcaaentry', 1);
Update::lastStepStatus(0); Update::lastStepStatus(0);
Froxlor::updateToDbVersion('201907270'); Froxlor::updateToDbVersion('201907270');
@@ -323,7 +325,7 @@ if (Froxlor::isDatabaseVersion('201907270')) {
$complete_filedir = Froxlor::getInstallDir() . $filedir; $complete_filedir = Froxlor::getInstallDir() . $filedir;
if (file_exists($complete_filedir)) { if (file_exists($complete_filedir)) {
if ($exec_allowed) { if ($exec_allowed) {
Froxlor\FileDir::safe_exec("rm -rf " . escapeshellarg($complete_filedir)); FileDir::safe_exec("rm -rf " . escapeshellarg($complete_filedir));
} else { } else {
$del_list .= "rm -rf " . escapeshellarg($complete_filedir) . PHP_EOL; $del_list .= "rm -rf " . escapeshellarg($complete_filedir) . PHP_EOL;
} }
@@ -889,7 +891,7 @@ if (Froxlor::isDatabaseVersion('202107210')) {
Database::pexecute($result_stmt); Database::pexecute($result_stmt);
$upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_IPSANDPORTS . "` SET `ip` = :ip WHERE `id` = :id"); $upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_IPSANDPORTS . "` SET `ip` = :ip WHERE `id` = :id");
while ($iprow = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { while ($iprow = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
if (Validate::is_ipv6($iprow['ip'])) { if (IPTools::is_ipv6($iprow['ip'])) {
$ip = inet_ntop(inet_pton($iprow['ip'])); $ip = inet_ntop(inet_pton($iprow['ip']));
Database::pexecute($upd_stmt, [ Database::pexecute($upd_stmt, [
'ip' => $ip, 'ip' => $ip,
@@ -926,7 +928,7 @@ if (Froxlor::isFroxlorVersion('0.10.27')) {
if (Froxlor::isDatabaseVersion('202108180')) { if (Froxlor::isDatabaseVersion('202108180')) {
Update::showUpdateStep("Adding czech language file", true); Update::showUpdateStep("Adding czech language file", true);
Database::query("INSERT INTO `" . TABLE_PANEL_LANGUAGE . "` SET `language` = '&#268;esk&aacute; republika', `iso` = 'cs', `file` = 'lng/czech.lng.php'"); Database::query("INSERT INTO `panel_languages` SET `language` = '&#268;esk&aacute; republika', `iso` = 'cs', `file` = 'lng/czech.lng.php'");
Update::lastStepStatus(0); Update::lastStepStatus(0);
Froxlor::updateToDbVersion('202109040'); Froxlor::updateToDbVersion('202109040');
} }

View File

@@ -24,6 +24,7 @@
*/ */
use Froxlor\Froxlor; use Froxlor\Froxlor;
use Froxlor\FileDir;
use Froxlor\Database\Database; use Froxlor\Database\Database;
use Froxlor\Settings; use Froxlor\Settings;
use Froxlor\Install\Update; use Froxlor\Install\Update;
@@ -78,7 +79,7 @@ if (Froxlor::isFroxlorVersion('0.10.99')) {
"); ");
$upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `allowed_mysqlserver` = :allowed_mysqlserver WHERE `customerid` = :customerid"); $upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `allowed_mysqlserver` = :allowed_mysqlserver WHERE `customerid` = :customerid");
while ($dbserver = $dbservers_stmt->fetch(PDO::FETCH_ASSOC)) { while ($dbserver = $dbservers_stmt->fetch(PDO::FETCH_ASSOC)) {
if (isset($dbserver['allowed_mysqlserver']) && !empt($dbserver['allowed_mysqlserver'])) { if (isset($dbserver['allowed_mysqlserver']) && !empty($dbserver['allowed_mysqlserver'])) {
$allowed_mysqlserver = json_encode(explode(",", $dbserver['allowed_mysqlserver'])); $allowed_mysqlserver = json_encode(explode(",", $dbserver['allowed_mysqlserver']));
Database::pexecute($upd_stmt, ['allowed_mysql_server' => $allowed_mysqlserver, 'customerid' => $dbserver['customerid']]); Database::pexecute($upd_stmt, ['allowed_mysql_server' => $allowed_mysqlserver, 'customerid' => $dbserver['customerid']]);
} }
@@ -105,15 +106,16 @@ if (Froxlor::isFroxlorVersion('0.10.99')) {
"lng/lng_references.php", "lng/lng_references.php",
"lng/portugues.lng.php", "lng/portugues.lng.php",
"lng/swedish.lng.php", "lng/swedish.lng.php",
"scripts",
); );
$disabled = explode(',', ini_get('disable_functions')); $disabled = explode(',', ini_get('disable_functions'));
$exec_allowed = !in_array('exec', $disabled); $exec_allowed = !in_array('exec', $disabled);
$del_list = ""; $del_list = "";
foreach ($to_clean as $filedir) { foreach ($to_clean as $filedir) {
$complete_filedir = \Froxlor\Froxlor::getInstallDir() . $filedir; $complete_filedir = Froxlor::getInstallDir() . $filedir;
if (file_exists($complete_filedir)) { if (file_exists($complete_filedir)) {
if ($exec_allowed) { if ($exec_allowed) {
Froxlor\FileDir::safe_exec("rm -rf " . escapeshellarg($complete_filedir)); FileDir::safe_exec("rm -rf " . escapeshellarg($complete_filedir));
} else { } else {
$del_list .= "rm -rf " . escapeshellarg($complete_filedir) . PHP_EOL; $del_list .= "rm -rf " . escapeshellarg($complete_filedir) . PHP_EOL;
} }
@@ -154,6 +156,7 @@ if (Froxlor::isFroxlorVersion('0.10.99')) {
'&#268;esk&aacute; republika' => 'cs' '&#268;esk&aacute; republika' => 'cs'
]; ];
Settings::Set('panel.standardlanguage', $lang_map[Settings::Get('panel_standardlanguage')] ?? 'en'); Settings::Set('panel.standardlanguage', $lang_map[Settings::Get('panel_standardlanguage')] ?? 'en');
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'system' AND `varname` = 'debug_cron'");
Update::lastStepStatus(0); Update::lastStepStatus(0);
Froxlor::updateToVersion($update_to); Froxlor::updateToVersion($update_to);

View File

@@ -51,12 +51,7 @@ try {
if (Froxlor::isFroxlor()) { if (Froxlor::isFroxlor()) {
// will be filled and increased by the update include-files below
$update_tasks = [];
$task_counter = 0;
include_once(FileDir::makeCorrectFile(dirname(__FILE__) . '/updates/froxlor/update_0.10.inc.php')); include_once(FileDir::makeCorrectFile(dirname(__FILE__) . '/updates/froxlor/update_0.10.inc.php'));
include_once(FileDir::makeCorrectFile(dirname(__FILE__) . '/updates/froxlor/update_0.11.inc.php')); include_once(FileDir::makeCorrectFile(dirname(__FILE__) . '/updates/froxlor/update_0.11.inc.php'));
// Check Froxlor - database integrity (only happens after all updates are done, so we know the db-layout is okay) // Check Froxlor - database integrity (only happens after all updates are done, so we know the db-layout is okay)
@@ -64,10 +59,10 @@ if (Froxlor::isFroxlor()) {
$integrity = new IntegrityCheck(); $integrity = new IntegrityCheck();
if (!$integrity->checkAll()) { if (!$integrity->checkAll()) {
Update::lastStepStatus(1, 'Monkeys ate the integrity'); Update::lastStepStatus(1, 'Integrity could not be validated');
Update::showUpdateStep("Trying to remove monkeys, feeding bananas"); Update::showUpdateStep("Trying to automatically restore integrity");
if (!$integrity->fixAll()) { if (!$integrity->fixAll()) {
Update::lastStepStatus(2, 'failed', 'Some monkeys just would not move, you should contact team@froxlor.org'); Update::lastStepStatus(2, 'failed', 'Check "database validation" as admin on the left-side menu to see where the problem is');
} else { } else {
Update::lastStepStatus(0, 'Integrity restored'); Update::lastStepStatus(0, 'Integrity restored');
} }

View File

@@ -105,7 +105,7 @@ abstract class ApiCommand extends ApiParameter
* *
* @throws Exception * @throws Exception
*/ */
public function __construct($header = null, $params = null, $userinfo = null, $internal = false) final public function __construct($header = null, $params = null, $userinfo = null, $internal = false)
{ {
parent::__construct($params); parent::__construct($params);

View File

@@ -117,7 +117,7 @@ class Admins extends ApiCommand implements ResourceEntity
* returns the total number of admins for the given admin * returns the total number of admins for the given admin
* *
* @access admin * @access admin
* @return string json-encoded array * @return string json-encoded response message
* @throws Exception * @throws Exception
*/ */
public function listingCount() public function listingCount()
@@ -131,6 +131,7 @@ class Admins extends ApiCommand implements ResourceEntity
if ($result) { if ($result) {
return $this->response($result['num_admins']); return $this->response($result['num_admins']);
} }
$this->response(0);
} }
throw new Exception("Not allowed to execute given command.", 403); throw new Exception("Not allowed to execute given command.", 403);
} }

View File

@@ -371,7 +371,7 @@ class Certificates extends ApiCommand implements ResourceEntity
* returns the total number of certificates for the given user * returns the total number of certificates for the given user
* *
* @access admin, customer * @access admin, customer
* @return string json-encoded array * @return string json-encoded response message
* @throws Exception * @throws Exception
*/ */
public function listingCount() public function listingCount()
@@ -399,6 +399,7 @@ class Certificates extends ApiCommand implements ResourceEntity
if ($result) { if ($result) {
return $this->response($result['num_certs']); return $this->response($result['num_certs']);
} }
return $this->response(0);
} }
/** /**

View File

@@ -185,7 +185,7 @@ class Cronjobs extends ApiCommand implements ResourceEntity
* returns the total number of cronjobs * returns the total number of cronjobs
* *
* @access admin * @access admin
* @return string json-encoded array * @return string json-encoded response message
* @throws Exception * @throws Exception
*/ */
public function listingCount() public function listingCount()
@@ -198,6 +198,7 @@ class Cronjobs extends ApiCommand implements ResourceEntity
if ($result) { if ($result) {
return $this->response($result['num_crons']); return $this->response($result['num_crons']);
} }
return $this->response(0);
} }
throw new Exception("Not allowed to execute given command.", 403); throw new Exception("Not allowed to execute given command.", 403);
} }

View File

@@ -210,7 +210,7 @@ class CustomerBackups extends ApiCommand implements ResourceEntity
* optional, admin-only, select backup-jobs of a specific customer by loginname * optional, admin-only, select backup-jobs of a specific customer by loginname
* *
* @access admin, customer * @access admin, customer
* @return string json-encoded array * @return string json-encoded response message
* @throws Exception * @throws Exception
*/ */
public function listingCount() public function listingCount()

View File

@@ -143,7 +143,7 @@ class Customers extends ApiCommand implements ResourceEntity
* returns the total number of customers for the given admin * returns the total number of customers for the given admin
* *
* @access admin * @access admin
* @return string json-encoded array * @return string json-encoded response message
* @throws Exception * @throws Exception
*/ */
public function listingCount() public function listingCount()
@@ -163,6 +163,7 @@ class Customers extends ApiCommand implements ResourceEntity
if ($result) { if ($result) {
return $this->response($result['num_customers']); return $this->response($result['num_customers']);
} }
return $this->response(0);
} }
throw new Exception("Not allowed to execute given command.", 403); throw new Exception("Not allowed to execute given command.", 403);
} }

View File

@@ -396,7 +396,7 @@ class DirOptions extends ApiCommand implements ResourceEntity
* optional, admin-only, select directory-protections of a specific customer by loginname * optional, admin-only, select directory-protections of a specific customer by loginname
* *
* @access admin, customer * @access admin, customer
* @return string json-encoded array count|list * @return string json-encoded response message
* @throws Exception * @throws Exception
*/ */
public function listingCount() public function listingCount()
@@ -415,6 +415,7 @@ class DirOptions extends ApiCommand implements ResourceEntity
if ($result) { if ($result) {
return $this->response($result['num_htaccess']); return $this->response($result['num_htaccess']);
} }
return $this->response(0);
} }
/** /**

View File

@@ -339,7 +339,7 @@ class DirProtections extends ApiCommand implements ResourceEntity
* optional, admin-only, select directory-protections of a specific customer by loginname * optional, admin-only, select directory-protections of a specific customer by loginname
* *
* @access admin, customer * @access admin, customer
* @return string json-encoded array count|list * @return string json-encoded response message
* @throws Exception * @throws Exception
*/ */
public function listingCount() public function listingCount()
@@ -358,6 +358,7 @@ class DirProtections extends ApiCommand implements ResourceEntity
if ($result) { if ($result) {
return $this->response($result['num_htpasswd']); return $this->response($result['num_htpasswd']);
} }
return $this->response(0);
} }
/** /**

View File

@@ -491,7 +491,7 @@ class DomainZones extends ApiCommand implements ResourceEntity
* optional, the domain name * optional, the domain name
* *
* @access admin, customer * @access admin, customer
* @return bool * @return string json-encoded response message
* @throws Exception * @throws Exception
*/ */
public function listingCount() public function listingCount()
@@ -522,6 +522,7 @@ class DomainZones extends ApiCommand implements ResourceEntity
if ($result) { if ($result) {
return $this->response($result['num_dns']); return $this->response($result['num_dns']);
} }
return $this->response(0);
} }
/** /**

View File

@@ -1743,9 +1743,6 @@ class Domains extends ApiCommand implements ResourceEntity
$upd_specialsettings = ", `specialsettings` = :specialsettings, `ssl_specialsettings` = :ssl_specialsettings, `include_specialsettings` = :include_specialsettings "; $upd_specialsettings = ", `specialsettings` = :specialsettings, `ssl_specialsettings` = :ssl_specialsettings, `include_specialsettings` = :include_specialsettings ";
} else { } else {
$upd_specialsettings = ''; $upd_specialsettings = '';
unset($_update_data['specialsettings']);
unset($_update_data['ssl_specialsettings']);
unset($_update_data['include_specialsettings']);
$upd_stmt = Database::prepare(" $upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `specialsettings`='', `ssl_specialsettings`='', `include_specialsettings`='0' WHERE `parentdomainid` = :id UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `specialsettings`='', `ssl_specialsettings`='', `include_specialsettings`='0' WHERE `parentdomainid` = :id
"); ");

View File

@@ -216,7 +216,6 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
// replacer array for mail to create account on server // replacer array for mail to create account on server
$replace_arr = [ $replace_arr = [
'EMAIL' => $email_full, 'EMAIL' => $email_full,
'USERNAME' => $username,
'PASSWORD' => htmlentities(htmlentities($password)), 'PASSWORD' => htmlentities(htmlentities($password)),
'SALUTATION' => User::getCorrectUserSalutation($customer), 'SALUTATION' => User::getCorrectUserSalutation($customer),
'NAME' => $customer['name'], 'NAME' => $customer['name'],

View File

@@ -206,7 +206,7 @@ class EmailForwarders extends ApiCommand implements ResourceEntity
* optional, admin-only, the loginname * optional, admin-only, the loginname
* *
* @access admin,customer * @access admin,customer
* @return string json-encoded array * @return string json-encoded response message
* @throws Exception * @throws Exception
*/ */
public function listingCount() public function listingCount()

View File

@@ -356,7 +356,7 @@ class Emails extends ApiCommand implements ResourceEntity
* optional, admin-only, select email addresses of a specific customer by loginname * optional, admin-only, select email addresses of a specific customer by loginname
* *
* @access admin, customer * @access admin, customer
* @return string json-encoded array * @return string json-encoded response message
* @throws Exception * @throws Exception
*/ */
public function listingCount() public function listingCount()
@@ -373,6 +373,7 @@ class Emails extends ApiCommand implements ResourceEntity
if ($result) { if ($result) {
return $this->response($result['num_emails']); return $this->response($result['num_emails']);
} }
return $this->response(0);
} }
/** /**

View File

@@ -105,7 +105,7 @@ class FpmDaemons extends ApiCommand implements ResourceEntity
* returns the total number of accessible fpm daemons * returns the total number of accessible fpm daemons
* *
* @access admin * @access admin
* @return string json-encoded array * @return string json-encoded response message
* @throws Exception * @throws Exception
*/ */
public function listingCount() public function listingCount()
@@ -118,6 +118,7 @@ class FpmDaemons extends ApiCommand implements ResourceEntity
if ($result) { if ($result) {
return $this->response($result['num_fpms']); return $this->response($result['num_fpms']);
} }
return $this->response(0);
} }
throw new Exception("Not allowed to execute given command.", 403); throw new Exception("Not allowed to execute given command.", 403);
} }

View File

@@ -549,7 +549,7 @@ class Ftps extends ApiCommand implements ResourceEntity
* optional, admin-only, select ftp-users of a specific customer by loginname * optional, admin-only, select ftp-users of a specific customer by loginname
* *
* @access admin, customer * @access admin, customer
* @return string json-encoded array * @return string json-encoded response message
* @throws Exception * @throws Exception
*/ */
public function listingCount() public function listingCount()
@@ -564,6 +564,7 @@ class Ftps extends ApiCommand implements ResourceEntity
if ($result) { if ($result) {
return $this->response($result['num_ftps']); return $this->response($result['num_ftps']);
} }
return $this->response(0);
} }
/** /**

View File

@@ -89,7 +89,7 @@ class HostingPlans extends ApiCommand implements ResourceEntity
* returns the total number of accessible hosting plans * returns the total number of accessible hosting plans
* *
* @access admin * @access admin
* @return string json-encoded array * @return string json-encoded response message
* @throws Exception * @throws Exception
*/ */
public function listingCount() public function listingCount()
@@ -107,6 +107,7 @@ class HostingPlans extends ApiCommand implements ResourceEntity
if ($result) { if ($result) {
return $this->response($result['num_plans']); return $this->response($result['num_plans']);
} }
return $this->response(0);
} }
throw new Exception("Not allowed to execute given command.", 403); throw new Exception("Not allowed to execute given command.", 403);
} }

View File

@@ -92,7 +92,7 @@ class IpsAndPorts extends ApiCommand implements ResourceEntity
* returns the total number of accessible ip/port entries * returns the total number of accessible ip/port entries
* *
* @access admin * @access admin
* @return string json-encoded array * @return string json-encoded response message
* @throws Exception * @throws Exception
*/ */
public function listingCount() public function listingCount()
@@ -108,6 +108,7 @@ class IpsAndPorts extends ApiCommand implements ResourceEntity
if ($result) { if ($result) {
return $this->response($result['num_ips']); return $this->response($result['num_ips']);
} }
return $this->response(0);
} }
throw new Exception("Not allowed to execute given command.", 403); throw new Exception("Not allowed to execute given command.", 403);
} }

View File

@@ -124,11 +124,14 @@ class MysqlServer extends ApiCommand implements ResourceEntity
} }
} }
$sql = [];
$sql_root = [];
// get all data from lib/userdata // get all data from lib/userdata
require Froxlor::getInstallDir() . "/lib/userdata.inc.php"; require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
// le format // le format
if (isset($sql['root_user']) && isset($sql['root_password']) && (!isset($sql_root) || !is_array($sql_root))) { if (isset($sql['root_user']) && isset($sql['root_password']) &&!is_array($sql_root)) {
$sql_root = array( $sql_root = array(
0 => array( 0 => array(
'caption' => 'Default', 'caption' => 'Default',
@@ -151,7 +154,7 @@ class MysqlServer extends ApiCommand implements ResourceEntity
'password' => $privileged_password, 'password' => $privileged_password,
'ssl' => [ 'ssl' => [
'caFile' => $mysql_ca ?? "", 'caFile' => $mysql_ca ?? "",
'verifyServerCertificate' => $mysql_verifycert ?? false 'verifyServerCertificate' => $mysql_verifycert
] ]
]; ];
@@ -192,6 +195,7 @@ class MysqlServer extends ApiCommand implements ResourceEntity
throw new Exception('Cannot delete first/default mysql-server', 406); throw new Exception('Cannot delete first/default mysql-server', 406);
} }
$sql_root = [];
// get all data from lib/userdata // get all data from lib/userdata
require Froxlor::getInstallDir() . "/lib/userdata.inc.php"; require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
@@ -222,6 +226,8 @@ class MysqlServer extends ApiCommand implements ResourceEntity
*/ */
public function listing() public function listing()
{ {
$sql = [];
$sql_root = [];
// get all data from lib/userdata // get all data from lib/userdata
require Froxlor::getInstallDir() . "/lib/userdata.inc.php"; require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
@@ -255,7 +261,7 @@ class MysqlServer extends ApiCommand implements ResourceEntity
* returns the total number of mysql servers * returns the total number of mysql servers
* *
* @access admin, customer * @access admin, customer
* @return string json-encoded array * @return string json-encoded response message
*/ */
public function listingCount() public function listingCount()
{ {
@@ -266,6 +272,7 @@ class MysqlServer extends ApiCommand implements ResourceEntity
} }
return $this->response(0); return $this->response(0);
} }
$sql_root = [];
// get all data from lib/userdata // get all data from lib/userdata
require Froxlor::getInstallDir() . "/lib/userdata.inc.php"; require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
return $this->response(count($sql_root)); return $this->response(count($sql_root));
@@ -290,9 +297,14 @@ class MysqlServer extends ApiCommand implements ResourceEntity
$dbserver = (int) $this->getParam('dbserver', $dn_optional, -1); $dbserver = (int) $this->getParam('dbserver', $dn_optional, -1);
$dbserver = $id >= 0 ? $id : $dbserver; $dbserver = $id >= 0 ? $id : $dbserver;
$sql_root = [];
// get all data from lib/userdata // get all data from lib/userdata
require Froxlor::getInstallDir() . "/lib/userdata.inc.php"; require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
if (!isset($sql_root[$dbserver])) {
throw new Exception('Mysql server not found', 404);
}
// limit customer to its allowed servers // limit customer to its allowed servers
if ($this->isAdmin() == false) { if ($this->isAdmin() == false) {
$allowed_mysqls = json_decode($this->getUserDetail('allowed_mysqlserver'), true); $allowed_mysqls = json_decode($this->getUserDetail('allowed_mysqlserver'), true);
@@ -300,11 +312,7 @@ class MysqlServer extends ApiCommand implements ResourceEntity
throw new Exception("You cannot access this resource", 405); throw new Exception("You cannot access this resource", 405);
} }
// no usernames required for non-admins // no usernames required for non-admins
unset($sqlrootdata['user']); unset($sql_root[$dbserver]['user']);
}
if (!isset($sql_root[$dbserver])) {
throw new Exception('Mysql server not found', 404);
} }
unset($sql_root[$dbserver]['password']); unset($sql_root[$dbserver]['password']);
@@ -351,6 +359,7 @@ class MysqlServer extends ApiCommand implements ResourceEntity
$dbserver = (int) $this->getParam('dbserver', $dn_optional, -1); $dbserver = (int) $this->getParam('dbserver', $dn_optional, -1);
$dbserver = $id >= 0 ? $id : $dbserver; $dbserver = $id >= 0 ? $id : $dbserver;
$sql_root = [];
require Froxlor::getInstallDir() . "/lib/userdata.inc.php"; require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
if (!isset($sql_root[$dbserver])) { if (!isset($sql_root[$dbserver])) {

View File

@@ -94,7 +94,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
Database::needSqlData(); Database::needSqlData();
$sql_root = Database::getSqlData(); $sql_root = Database::getSqlData();
Database::needRoot(false); Database::needRoot(false);
if (!isset($sql_root) || !is_array($sql_root)) { if (!is_array($sql_root)) {
throw new Exception("Database server with index #" . $dbserver . " is unknown", 404); throw new Exception("Database server with index #" . $dbserver . " is unknown", 404);
} }
@@ -481,7 +481,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
* optional, admin-only, select dbs of a specific customer by loginname * optional, admin-only, select dbs of a specific customer by loginname
* *
* @access admin, customer * @access admin, customer
* @return string json-encoded array * @return string json-encoded response message
* @throws Exception * @throws Exception
*/ */
public function listingCount() public function listingCount()
@@ -495,6 +495,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
if ($result) { if ($result) {
return $this->response($result['num_dbs']); return $this->response($result['num_dbs']);
} }
return $this->response(0);
} }
/** /**

View File

@@ -123,7 +123,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
} }
// check whether we use that config as froxor-vhost config // check whether we use that config as froxor-vhost config
if (Settings::Get('system.mod_fcgid_defaultini_ownvhost') == $row['id'] || Settings::Get('phpfpm.vhost_defaultini') == $row['id']) { if ((Settings::Get('system.mod_fcgid') == '1' && Settings::Get('system.mod_fcgid_defaultini_ownvhost') == $row['id']) || (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.vhost_defaultini') == $row['id'])) {
$domains[] = Settings::Get('system.hostname'); $domains[] = Settings::Get('system.hostname');
} }
@@ -178,7 +178,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
* returns the total number of accessible php-setting entries * returns the total number of accessible php-setting entries
* *
* @access admin * @access admin
* @return string json-encoded array * @return string json-encoded response message
* @throws Exception * @throws Exception
*/ */
public function listingCount() public function listingCount()
@@ -192,6 +192,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
if ($result) { if ($result) {
return $this->response($result['num_phps']); return $this->response($result['num_phps']);
} }
return $this->response(0);
} }
throw new Exception("Not allowed to execute given command.", 403); throw new Exception("Not allowed to execute given command.", 403);
} }

View File

@@ -1017,7 +1017,7 @@ class SubDomains extends ApiCommand implements ResourceEntity
* optional, admin-only, select (sub)domains of a specific customer by loginname * optional, admin-only, select (sub)domains of a specific customer by loginname
* *
* @access admin, customer * @access admin, customer
* @return string json-encoded array * @return string json-encoded response message
* @throws Exception * @throws Exception
*/ */
public function listingCount() public function listingCount()
@@ -1069,6 +1069,7 @@ class SubDomains extends ApiCommand implements ResourceEntity
if ($result) { if ($result) {
return $this->response($result['num_subdom']); return $this->response($result['num_subdom']);
} }
return $this->response(0);
} }
/** /**

View File

@@ -103,7 +103,7 @@ class SysLog extends ApiCommand implements ResourceEntity
* returns the total number of log-entries * returns the total number of log-entries
* *
* @access admin * @access admin
* @return string json-encoded array * @return string json-encoded response message
* @throws Exception * @throws Exception
*/ */
public function listingCount() public function listingCount()
@@ -150,6 +150,7 @@ class SysLog extends ApiCommand implements ResourceEntity
if ($result) { if ($result) {
return $this->response($result['num_logs']); return $this->response($result['num_logs']);
} }
return $this->response(0);
} }
/** /**

View File

@@ -76,7 +76,7 @@ abstract class BulkAction
* *
* @return object BulkAction instance * @return object BulkAction instance
*/ */
protected function __construct($import_file = null, $userinfo = []) protected function __construct(string $import_file = null, array $userinfo = [])
{ {
if (!empty($import_file)) { if (!empty($import_file)) {
$this->impFile = FileDir::makeCorrectFile($import_file); $this->impFile = FileDir::makeCorrectFile($import_file);
@@ -93,7 +93,7 @@ abstract class BulkAction
* *
* @return array 'all' => amount of records processed, 'imported' => number of imported records * @return array 'all' => amount of records processed, 'imported' => number of imported records
*/ */
abstract public function doImport($separator = ";", $offset = 0); abstract public function doImport(string $separator = ";", int $offset = 0);
/** /**
* setter for import-file * setter for import-file

View File

@@ -34,10 +34,12 @@ class DomainBulkAction extends BulkAction
{ {
/** /**
* @param string $import_file
* @param array $userinfo
* *
* @return object DomainBulkAction instance * @return DomainBulkAction
*/ */
public function __construct($import_file = null, $userinfo) public function __construct(string $import_file = null, array $userinfo = [])
{ {
parent::__construct($import_file, $userinfo); parent::__construct($import_file, $userinfo);
$this->setApiCall('Domains.add'); $this->setApiCall('Domains.add');
@@ -52,7 +54,7 @@ class DomainBulkAction extends BulkAction
* *
* @return array 'all' => amount of records processed, 'imported' => number of imported records * @return array 'all' => amount of records processed, 'imported' => number of imported records
*/ */
public function doImport($separator = ";", $offset = 0) public function doImport(string $separator = ";", int $offset = 0)
{ {
if ($this->userinfo['domains'] == "-1") { if ($this->userinfo['domains'] == "-1") {
$dom_unlimited = true; $dom_unlimited = true;

View File

@@ -25,7 +25,11 @@
namespace Froxlor\Cli; namespace Froxlor\Cli;
use PDO;
use Exception;
use Froxlor\Froxlor; use Froxlor\Froxlor;
use Froxlor\Settings;
use Froxlor\Database\Database;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@@ -39,10 +43,96 @@ class CliCommand extends Command
$output->writeln("<error>Could not find froxlor's userdata.inc.php file. You should use this script only with an installed froxlor system.</>"); $output->writeln("<error>Could not find froxlor's userdata.inc.php file. You should use this script only with an installed froxlor system.</>");
return self::INVALID; return self::INVALID;
} }
// try database connection
try {
Database::query("SELECT 1");
} catch (Exception $e) {
// Do not proceed further if no database connection could be established
$output->writeln("<error>" . $e->getMessage() . "</>");
return self::INVALID;
}
if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) { if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) {
if ((int)Settings::Get('system.cron_allowautoupdate') == 1) {
return $this->runUpdate($output);
} else {
$output->writeln("<error>It seems that the froxlor files have been updated. Please login and finish the update procedure.</>"); $output->writeln("<error>It seems that the froxlor files have been updated. Please login and finish the update procedure.</>");
return self::INVALID; return self::INVALID;
} }
}
return self::SUCCESS; return self::SUCCESS;
} }
protected function getUserByName(?string $loginname, bool $deactivated_check = true): array
{
if (empty($loginname)) {
throw new Exception("Empty username");
}
$stmt = Database::prepare("
SELECT `loginname` AS `customer`
FROM `" . TABLE_PANEL_CUSTOMERS . "`
WHERE `loginname`= :loginname
");
Database::pexecute($stmt, [
"loginname" => $loginname
]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row && $row['customer'] == $loginname) {
$table = "`" . TABLE_PANEL_CUSTOMERS . "`";
$adminsession = '0';
} else {
$stmt = Database::prepare("
SELECT `loginname` AS `admin` FROM `" . TABLE_PANEL_ADMINS . "`
WHERE `loginname`= :loginname
");
Database::pexecute($stmt, [
"loginname" => $loginname
]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row && $row['admin'] == $loginname) {
$table = "`" . TABLE_PANEL_ADMINS . "`";
$adminsession = '1';
} else {
throw new Exception("Unknown user '" . $loginname . "'");
}
}
$userinfo_stmt = Database::prepare("
SELECT * FROM $table
WHERE `loginname`= :loginname
");
Database::pexecute($userinfo_stmt, [
"loginname" => $loginname
]);
$userinfo = $userinfo_stmt->fetch(PDO::FETCH_ASSOC);
$userinfo['adminsession'] = $adminsession;
if ($deactivated_check && $userinfo['deactivated']) {
throw new Exception("User '" . $loginname . "' is currently deactivated");
}
return $userinfo;
}
private function runUpdate(OutputInterface $output): int
{
$output->writeln('<comment>Automatic update is activated and we are going to proceed without any notices</>');
include_once Froxlor::getInstallDir() . '/lib/tables.inc.php';
define('_CRON_UPDATE', 1);
ob_start([
'this',
'cleanUpdateOutput'
]);
include_once Froxlor::getInstallDir() . '/install/updatesql.php';
ob_end_flush();
$output->writeln('<info>Automatic update done - you should check your settings to be sure everything is fine</>');
return self::SUCCESS;
}
private function cleanUpdateOutput($buffer)
{
return strip_tags(preg_replace("/<br\W*?\/>/", "\n", $buffer));
}
} }

View File

@@ -410,7 +410,7 @@ final class ConfigServices extends CliCommand
// set is_configured flag // set is_configured flag
Settings::Set('panel.is_configured', '1', true); Settings::Set('panel.is_configured', '1', true);
// run cronjob at the end to ensure configs are all up to date // run cronjob at the end to ensure configs are all up to date
exec('php ' . Froxlor::getInstallDir() . 'scripts/froxlor_master_cronjob.php --force'); exec('php ' . Froxlor::getInstallDir() . 'bin/froxlor-cli froxlor:cron --force');
// and done // and done
$output->writeln('<info>All services have been configured</>'); $output->writeln('<info>All services have been configured</>');
return self::SUCCESS; return self::SUCCESS;

View File

@@ -49,13 +49,26 @@ final class InstallCommand extends Command
$this->setName('froxlor:install'); $this->setName('froxlor:install');
$this->setDescription('Installation process to use instead of web-ui'); $this->setDescription('Installation process to use instead of web-ui');
$this->addArgument('input-file', InputArgument::OPTIONAL, 'Optional JSON array file to use for unattended installations'); $this->addArgument('input-file', InputArgument::OPTIONAL, 'Optional JSON array file to use for unattended installations');
$this->addOption('print-example-file', 'p', InputOption::VALUE_NONE, 'Outputs an example JSON content to be used with the input file parameter'); $this->addOption('print-example-file', 'p', InputOption::VALUE_NONE, 'Outputs an example JSON content to be used with the input file parameter')
->addOption('create-userdata-from-str', 'c', InputOption::VALUE_REQUIRED, 'Creates lib/userdata.inc.php file from string created by web-install process');
} }
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$result = self::SUCCESS; $result = self::SUCCESS;
if ($input->getOption('create-userdata-from-str') !== null) {
$ud_str = $input->getOption('create-userdata-from-str');
$ud_dec = @json_decode(@base64_decode($ud_str), true);
if (is_array($ud_dec) && !empty($ud_dec) && count($ud_dec) == 8) {
$core = new Core($ud_dec);
$core->createUserdataConf();
return $result;
}
$output->writeln("<error>Invalid parameter value.</>");
return self::INVALID;
}
session_start(); session_start();
require __DIR__ . '/install.functions.php'; require __DIR__ . '/install.functions.php';
@@ -121,6 +134,7 @@ final class InstallCommand extends Command
$this->io->info('Running unattended installation'); $this->io->info('Running unattended installation');
} else { } else {
$extended = $this->io->confirm('Use advanced installation mode?', false); $extended = $this->io->confirm('Use advanced installation mode?', false);
$decoded_input = [];
} }
$result = $this->showStep(0, $extended, $decoded_input); $result = $this->showStep(0, $extended, $decoded_input);
@@ -237,7 +251,7 @@ final class InstallCommand extends Command
if ($step == 3) { if ($step == 3) {
// do actual install with data from $this->formfielddata // do actual install with data from $this->formfielddata
$core = new Core($this->formfielddata); $core = new Core($this->formfielddata);
$core->doInstall(); $core->doInstall(false);
$core->createUserdataConf(); $core->createUserdataConf();
} }
return $this->showStep(++$step, $extended, $decoded_input); return $this->showStep(++$step, $extended, $decoded_input);

View File

@@ -0,0 +1,260 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can also view it online at
* https://files.froxlor.org/misc/COPYING.txt
*
* @copyright the authors
* @author Froxlor team <team@froxlor.org>
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
*/
namespace Froxlor\Cli;
use PDO;
use Froxlor\Froxlor;
use Froxlor\FileDir;
use Froxlor\Settings;
use Froxlor\FroxlorLogger;
use Froxlor\Database\Database;
use Froxlor\System\Cronjob;
use Froxlor\Cron\TaskId;
use Froxlor\Cron\CronConfig;
use Froxlor\Cron\System\Extrausers;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
final class MasterCron extends CliCommand
{
private $lockFile = null;
private $cronLog = null;
protected function configure()
{
$this->setName('froxlor:cron');
$this->setDescription('Regulary perform tasks created by froxlor');
$this->addArgument('job', InputArgument::IS_ARRAY, 'Job(s) to run');
$this->addOption('run-task', 'r', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Run a specific task [1 = re-generate configs, 4 = re-generate dns zones, 10 = re-set quotas, 99 = re-create cron.d-file]')
->addOption('force', 'f', InputOption::VALUE_NONE, 'Forces re-generating of config-files (webserver, nameserver, etc.)')
->addOption('debug', 'd', InputOption::VALUE_NONE, 'Output debug information about what is going on to STDOUT.')
->addOption('no-fork', 'N', InputOption::VALUE_NONE, 'Do not fork to background (traffic cron only).');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$result = self::SUCCESS;
$result = $this->validateRequirements($input, $output);
$jobs = $input->getArgument('job');
// handle force option
if ($input->getOption('force')) {
// rebuild all config files
Cronjob::inserttask(TaskId::REBUILD_VHOST);
Cronjob::inserttask(TaskId::REBUILD_DNS);
Cronjob::inserttask(TaskId::CREATE_QUOTA);
Cronjob::inserttask(TaskId::REBUILD_CRON);
array_push($jobs, 'tasks');
define('CRON_IS_FORCED', 1);
}
// handle debug option
if ($input->getOption('debug')) {
define('CRON_DEBUG_FLAG', 1);
}
// handle no-fork option
if ($input->getOption('no-fork')) {
define('CRON_NOFORK_FLAG', 1);
}
// handle run-task option
if ($input->getOption('run-task')) {
$tasks_to_run = $input->getOption('run-task');
foreach ($tasks_to_run as $ttr) {
if (in_array($ttr, [1, 4, 10, 99])) {
Cronjob::inserttask($ttr);
array_push($jobs, 'tasks');
} else {
$output->writeln('<comment>Unknown task number "' . $ttr . '"</>');
}
}
}
// unique job-array
$jobs = array_unique($jobs);
// check for given job(s) to execute and return if empty
if (empty($jobs)) {
$output->writeln('<error>No job given. Nothing to do.</>');
return self::INVALID;
}
$this->validateOwnership($output);
$this->cronLog = FroxlorLogger::getInstanceOf([
'loginname' => 'cronjob'
]);
$this->cronLog->setCronDebugFlag(defined('CRON_DEBUG_FLAG'));
// check whether there are actual tasks to perform by 'tasks'-cron so
// we dont regenerate files unnecessarily
$tasks_cnt_stmt = Database::query("SELECT COUNT(*) as jobcnt FROM `panel_tasks`");
$tasks_cnt = $tasks_cnt_stmt->fetch(PDO::FETCH_ASSOC);
// iterate through all needed jobs
foreach ($jobs as $job) {
// lock the job
if ($this->lockJob($job, $output)) {
// get FQDN of cron-class
$cronfile = $this->getCronModule($job, $output);
// validate
if ($cronfile && class_exists($cronfile)) {
// info
$output->writeln('<info>Running "' . $job . '" job' . (defined('CRON_IS_FORCED') ? ' (forced)' : '') . (defined('CRON_DEBUG_FLAG') ? ' (debug)' : '') . (defined('CRON_NOFORK_FLAG') ? ' (not forking)' : '') . '</>');
// update time of last run
Cronjob::updateLastRunOfCron($job);
// set logger
$cronfile::setCronlog($this->cronLog);
// run the job
$cronfile::run();
}
// free the lockfile
$this->unlockJob($job);
}
}
// regenerate nss-extrausers files / invalidate nscd cache (if used)
$this->refreshUsers((int) $tasks_cnt['jobcnt']);
// we have to check the system's last guid with every cron run
// in case the admin installed new software which added a new user
//so users in the database don't conflict with system users
$this->cronLog->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Checking system\'s last guid');
Cronjob::checkLastGuid();
// check for cron.d-generation task and create it if necessary
CronConfig::checkCrondConfigurationFile();
// reset cronlog-flag if set to "once"
if ((int) Settings::Get('logger.log_cron') == 1) {
FroxlorLogger::getInstanceOf()->setCronLog(0);
}
return $result;
}
private function refreshUsers(int $jobcount = 0)
{
if ($jobcount > 0) {
if (Settings::Get('system.nssextrausers') == 1) {
Extrausers::generateFiles($this->cronLog);
return;
}
// clear NSCD cache if using fcgid or fpm, #1570 - not needed for nss-extrausers
if ((Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) && Settings::Get('system.nssextrausers') == 0) {
$false_val = false;
FileDir::safe_exec('nscd -i passwd 1> /dev/null', $false_val, [
'>'
]);
FileDir::safe_exec('nscd -i group 1> /dev/null', $false_val, [
'>'
]);
}
}
}
private function validateOwnership(OutputInterface $output)
{
// when using fcgid or fpm for froxlor-vhost itself, we have to check
// whether the permission of the files are still correct
$output->write('Checking froxlor file permissions...');
$_mypath = FileDir::makeCorrectDir(Froxlor::getInstallDir());
if (((int)Settings::Get('system.mod_fcgid') == 1 && (int)Settings::Get('system.mod_fcgid_ownvhost') == 1) || ((int)Settings::Get('phpfpm.enabled') == 1 && (int)Settings::Get('phpfpm.enabled_ownvhost') == 1)) {
$user = Settings::Get('system.mod_fcgid_httpuser');
$group = Settings::Get('system.mod_fcgid_httpgroup');
if (Settings::Get('phpfpm.enabled') == 1) {
$user = Settings::Get('phpfpm.vhost_httpuser');
$group = Settings::Get('phpfpm.vhost_httpgroup');
}
// all the files and folders have to belong to the local user
FileDir::safe_exec('chown -R ' . $user . ':' . $group . ' ' . escapeshellarg($_mypath));
} else {
// back to webserver permission
$user = Settings::Get('system.httpuser');
$group = Settings::Get('system.httpgroup');
FileDir::safe_exec('chown -R ' . $user . ':' . $group . ' ' . escapeshellarg($_mypath));
}
$output->writeln('OK');
}
private function getCronModule(string $cronname, OutputInterface $output)
{
$upd_stmt = Database::prepare("
SELECT `cronclass` FROM `" . TABLE_PANEL_CRONRUNS . "` WHERE `cronfile` = :cron;
");
$cron = Database::pexecute_first($upd_stmt, [
'cron' => $cronname
]);
if ($cron) {
return $cron['cronclass'];
}
$output->writeln("<error>Requested cronjob '" . $cronname . "' could not be found.</>");
return false;
}
private function lockJob(string $job, OutputInterface $output): bool
{
$this->lockFile = '/run/lock/froxlor_' . $job . '.lock';
if (file_exists($this->lockFile)) {
$jobinfo = json_decode(file_get_contents($this->lockFile), true);
$check_pid_return = null;
// get status of process
system("kill -CHLD " . (int)$jobinfo['pid'] . " 1> /dev/null 2> /dev/null", $check_pid_return);
if ($check_pid_return == 1) {
// Process does not seem to run, most likely it has died
$this->unlockJob($job);
} else {
// cronjob still running, output info and stop
$output->writeln([
'<comment>Job "' . $jobinfo['job'] . '" is currently running.',
'Started: ' . date('d.m.Y H:i', (int) $jobinfo['startts']),
'PID: ' . $jobinfo['pid'] . '</>'
]);
return false;
}
}
$jobinfo = [
'job' => $job,
'startts' => time(),
'pid' => getmypid()
];
file_put_contents($this->lockFile, json_encode($jobinfo));
return true;
}
private function unlockJob(string $job): bool
{
return @unlink($this->lockFile);
}
}

View File

@@ -126,57 +126,4 @@ final class RunApiCommand extends CliCommand
return ['class' => $command[0], 'function' => $command[1]]; return ['class' => $command[0], 'function' => $command[1]];
} }
private function getUserByName(?string $loginname): array
{
if (empty($loginname)) {
throw new Exception("Empty username");
}
$stmt = Database::prepare("
SELECT `loginname` AS `customer`
FROM `" . TABLE_PANEL_CUSTOMERS . "`
WHERE `loginname`= :loginname
");
Database::pexecute($stmt, [
"loginname" => $loginname
]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row && $row['customer'] == $loginname) {
$table = "`" . TABLE_PANEL_CUSTOMERS . "`";
$adminsession = '0';
} else {
$stmt = Database::prepare("
SELECT `loginname` AS `admin` FROM `" . TABLE_PANEL_ADMINS . "`
WHERE `loginname`= :loginname
");
Database::pexecute($stmt, [
"loginname" => $loginname
]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row && $row['admin'] == $loginname) {
$table = "`" . TABLE_PANEL_ADMINS . "`";
$adminsession = '1';
} else {
throw new Exception("Unknown user '" . $loginname . "'");
}
}
$userinfo_stmt = Database::prepare("
SELECT * FROM $table
WHERE `loginname`= :loginname
");
Database::pexecute($userinfo_stmt, [
"loginname" => $loginname
]);
$userinfo = $userinfo_stmt->fetch(PDO::FETCH_ASSOC);
$userinfo['adminsession'] = $adminsession;
if ($userinfo['deactivated']) {
throw new Exception("User '" . $loginname . "' is currently deactivated");
}
return $userinfo;
}
} }

View File

@@ -143,7 +143,7 @@ final class UpdateCommand extends CliCommand
$auex = AutoUpdate::extractZip($audl); $auex = AutoUpdate::extractZip($audl);
if ($auex == 0) { if ($auex == 0) {
$output->writeln("<info>Froxlor files updated successfully.</>"); $output->writeln("<info>Froxlor files updated successfully.</>");
$result = self::SUCCCESS; $result = self::SUCCESS;
$question = new ConfirmationQuestion('Update database? [no] ', false, '/^(y|j)/i'); $question = new ConfirmationQuestion('Update database? [no] ', false, '/^(y|j)/i');
if ($yestoall || $helper->ask($input, $output, $question)) { if ($yestoall || $helper->ask($input, $output, $question)) {
$result = $this->updateDatabase(); $result = $this->updateDatabase();
@@ -193,7 +193,7 @@ final class UpdateCommand extends CliCommand
]); ]);
include_once Froxlor::getInstallDir() . '/install/updatesql.php'; include_once Froxlor::getInstallDir() . '/install/updatesql.php';
ob_end_flush(); ob_end_flush();
return self::SUCCCESS; return self::SUCCESS;
} }
private function cleanUpdateOutput($buffer) private function cleanUpdateOutput($buffer)

View File

@@ -0,0 +1,135 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can also view it online at
* https://files.froxlor.org/misc/COPYING.txt
*
* @copyright the authors
* @author Froxlor team <team@froxlor.org>
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
*/
namespace Froxlor\Cli;
use Exception;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Froxlor\Api\Commands\Admins;
use Froxlor\Api\Commands\Customers;
use Froxlor\System\Crypt;
use Froxlor\Froxlor;
final class UserCommand extends CliCommand
{
protected function configure()
{
$this->setName('froxlor:user');
$this->setDescription('Various user actions');
$this->addArgument('user', InputArgument::REQUIRED, 'Loginname of the target user')
->addArgument('admin', InputArgument::OPTIONAL, 'Loginname of the executing admin/reseller user', 'admin');
$this->addOption('unlock', 'u', InputOption::VALUE_NONE, 'Unock user after too many failed login attempts')
->addOption('change-passwd', 'p', InputOption::VALUE_NONE, 'Set new password for given user')
->addOption('show-info', 's', InputOption::VALUE_NONE, 'Output information details of given user');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$result = self::SUCCESS;
$result = $this->validateRequirements($input, $output);
require Froxlor::getInstallDir() . '/lib/functions.php';
// set error-handler
@set_error_handler([
'\\Froxlor\\Api\\Api',
'phpErrHandler'
]);
if ($result == self::SUCCESS) {
try {
$adminname = $input->getArgument('admin');
$admininfo = $this->getUserByName($adminname);
$loginname = $input->getArgument('user');
$userinfo = $this->getUserByName($loginname, false);
$do_unlock = $input->getOption('unlock');
$do_passwd = $input->getOption('change-passwd');
$do_show = $input->getOption('show-info');
if ($do_unlock === false && $do_passwd === false && $do_show === false) {
$output->writeln('<error>No option given, nothing to do.</>');
$result = self::INVALID;
}
if ($do_unlock !== false) {
// unlock given user
if ((int)$userinfo['adminsession'] == 1) {
Admins::getLocal($admininfo, ['loginname' => $loginname])->unlock();
} else {
Customers::getLocal($admininfo, ['loginname' => $loginname])->unlock();
}
$output->writeln('<info>User ' . $loginname . ' unlocked successfully</>');
$result = self::SUCCESS;
}
if ($result == self::SUCCESS && $do_passwd !== false) {
$io = new SymfonyStyle($input, $output);
$passwd = $io->askHidden("Enter new password", function ($value) {
if (empty($value)) {
throw new \RuntimeException('You must enter a value.');
}
$value = Crypt::validatePassword($value, 'new password');
return $value;
});
$passwd2 = $io->askHidden("Confirm new password", function ($value) use ($passwd) {
if (empty($value)) {
throw new \RuntimeException('You must enter a value.');
} elseif ($value != $passwd) {
throw new \RuntimeException('Passwords do not match');
}
return $value;
});
if ((int)$userinfo['adminsession'] == 1) {
Admins::getLocal($admininfo, ['id' => $userinfo['adminid'], 'admin_password' => $passwd])->update();
} else {
Customers::getLocal($admininfo, ['id' => $userinfo['customerid'], 'new_customer_password' => $passwd])->update();
}
$output->writeln('<info>Changed password for ' . $loginname . '</>');
$result = self::SUCCESS;
}
if ($result == self::SUCCESS && $do_show !== false) {
$userinfo['password'] = '[hidden]';
$userinfo['data_2fa'] = '[hidden]';
$io = new SymfonyStyle($input, $output);
$io->horizontalTable(
array_keys($userinfo),
[array_values($userinfo)]
);
}
} catch (Exception $e) {
$output->writeln('<error>' . $e->getMessage() . '</>');
$result = self::FAILURE;
}
}
return $result;
}
}

View File

@@ -127,6 +127,8 @@ class ConfigDaemon
if (is_null($this->sqldata_cache)) { if (is_null($this->sqldata_cache)) {
// read in sql-data (if exists) // read in sql-data (if exists)
if (file_exists(Froxlor::getInstallDir() . "/lib/userdata.inc.php")) { if (file_exists(Froxlor::getInstallDir() . "/lib/userdata.inc.php")) {
$sql = [];
$sql_root = [];
require Froxlor::getInstallDir() . "/lib/userdata.inc.php"; require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
unset($sql_root); unset($sql_root);
$this->sqldata_cache = $sql; $this->sqldata_cache = $sql;

View File

@@ -109,7 +109,7 @@ class ConfigDisplay
} }
} }
Database::needSqlData(true); Database::needSqlData();
$sql = Database::getSqlData(); $sql = Database::getSqlData();
self::$replace_arr = [ self::$replace_arr = [

View File

@@ -110,7 +110,7 @@ class CronConfig
} }
// create entry-line // create entry-line
$cronfile .= "root " . $binpath . " " . FileDir::makeCorrectFile(Froxlor::getInstallDir() . "/scripts/froxlor_master_cronjob.php") . " --" . $row_cronentry['cronfile'] . " 1> /dev/null\n"; $cronfile .= "root " . $binpath . " " . FileDir::makeCorrectFile(Froxlor::getInstallDir() . "/bin/froxlor-cli") . " froxlor:cron " . escapeshellarg($row_cronentry['cronfile']) . " -q 1> /dev/null\n";
} }
} }
@@ -135,7 +135,7 @@ class CronConfig
$newcrontab = ""; $newcrontab = "";
foreach ($crontablines as $ctl) { foreach ($crontablines as $ctl) {
$ctl = trim($ctl); $ctl = trim($ctl);
if (!empty($ctl) && !preg_match("/(.*)froxlor_master_cronjob\.php(.*)/", $ctl)) { if (!empty($ctl) && !preg_match("/(.*)froxlor\:cron(.*)/", $ctl)) {
$newcrontab .= $ctl . "\n"; $newcrontab .= $ctl . "\n";
} }
} }

View File

@@ -42,4 +42,9 @@ abstract class FroxlorCron
{ {
static::$lockfile = $lockfile; static::$lockfile = $lockfile;
} }
public static function setCronlog($cronlog = null)
{
static::$cronlog = $cronlog;
}
} }

View File

@@ -25,6 +25,7 @@
namespace Froxlor\Cron\Http; namespace Froxlor\Cron\Http;
use Froxlor\Froxlor;
use Froxlor\Cron\Http\Php\PhpInterface; use Froxlor\Cron\Http\Php\PhpInterface;
use Froxlor\Customer\Customer; use Froxlor\Customer\Customer;
use Froxlor\Database\Database; use Froxlor\Database\Database;
@@ -39,16 +40,10 @@ use Froxlor\Validate\Validate;
use Froxlor\System\Crypt; use Froxlor\System\Crypt;
use PDO; use PDO;
/**
* @author Florian Lippert <flo@syscp.org> (2003-2009)
* @author Froxlor team <team@froxlor.org> (2010-)
*/
class Apache extends HttpConfigBase class Apache extends HttpConfigBase
{ {
// protected // protected
protected $known_vhostfilenames = [];
protected $known_diroptionsfilenames = []; protected $known_diroptionsfilenames = [];
protected $known_htpasswdsfilenames = []; protected $known_htpasswdsfilenames = [];
@@ -161,6 +156,27 @@ class Apache extends HttpConfigBase
} }
if (!$is_redirect) { if (!$is_redirect) {
// protect lib/userdata.inc.php
$this->virtualhosts_data[$vhosts_filename] .= ' <Directory "' . rtrim(Froxlor::getInstallDir(), "/") . '/lib/">' . "\n";
$this->virtualhosts_data[$vhosts_filename] .= ' <Files "userdata.inc.php">' . "\n";
if (Settings::Get('system.apache24') == '1') {
$this->virtualhosts_data[$vhosts_filename] .= ' Require all denied' . "\n";
} else {
$this->virtualhosts_data[$vhosts_filename] .= ' Order deny,allow' . "\n";
$this->virtualhosts_data[$vhosts_filename] .= ' deny from all' . "\n";
}
$this->virtualhosts_data[$vhosts_filename] .= ' </Files>' . "\n";
$this->virtualhosts_data[$vhosts_filename] .= ' </Directory>' . "\n";
// protect bin/
$this->virtualhosts_data[$vhosts_filename] .= ' <Directory "' . rtrim(Froxlor::getInstallDir(), "/") . '/bin/">' . "\n";
if (Settings::Get('system.apache24') == '1') {
$this->virtualhosts_data[$vhosts_filename] .= ' Require all denied' . "\n";
} else {
$this->virtualhosts_data[$vhosts_filename] .= ' Order deny,allow' . "\n";
$this->virtualhosts_data[$vhosts_filename] .= ' deny from all' . "\n";
}
$this->virtualhosts_data[$vhosts_filename] .= ' </Directory>' . "\n";
// create fcgid <Directory>-Part (starter is created in apache_fcgid) // create fcgid <Directory>-Part (starter is created in apache_fcgid)
if (Settings::Get('system.mod_fcgid_ownvhost') == '1' && Settings::Get('system.mod_fcgid') == '1') { if (Settings::Get('system.mod_fcgid_ownvhost') == '1' && Settings::Get('system.mod_fcgid') == '1') {
$configdir = FileDir::makeCorrectDir(Settings::Get('system.mod_fcgid_configdir') . '/froxlor.panel/' . Settings::Get('system.hostname')); $configdir = FileDir::makeCorrectDir(Settings::Get('system.mod_fcgid_configdir') . '/froxlor.panel/' . Settings::Get('system.hostname'));
@@ -1438,8 +1454,6 @@ class Apache extends HttpConfigBase
// Write a single file for every vhost // Write a single file for every vhost
foreach ($this->virtualhosts_data as $vhosts_filename => $vhosts_file) { foreach ($this->virtualhosts_data as $vhosts_filename => $vhosts_file) {
$this->known_vhostfilenames[] = basename($vhosts_filename);
// Apply header // Apply header
$vhosts_file = '# ' . basename($vhosts_filename) . "\n" . '# Created ' . date('d.m.Y H:i') . "\n" . '# Do NOT manually edit this file, all changes will be deleted after the next domain change at the panel.' . "\n" . "\n" . $vhosts_file; $vhosts_file = '# ' . basename($vhosts_filename) . "\n" . '# Created ' . date('d.m.Y H:i') . "\n" . '# Do NOT manually edit this file, all changes will be deleted after the next domain change at the panel.' . "\n" . "\n" . $vhosts_file;
$vhosts_file_handler = fopen($vhosts_filename, 'w'); $vhosts_file_handler = fopen($vhosts_filename, 'w');

View File

@@ -65,10 +65,10 @@ class AcmeSh extends FroxlorCron
/** /**
* run the task * run the task
* *
* @param boolean $internal * @param bool $internal
* @return number * @return number
*/ */
public static function run($internal = false) public static function run(bool $internal = false)
{ {
// usually, this is action is called from within the tasks-jobs // usually, this is action is called from within the tasks-jobs
if (!defined('CRON_IS_FORCED') && !defined('CRON_DEBUG_FLAG') && $internal == false) { if (!defined('CRON_IS_FORCED') && !defined('CRON_DEBUG_FLAG') && $internal == false) {
@@ -201,6 +201,7 @@ class AcmeSh extends FroxlorCron
} else { } else {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "No new certificates or certificate updates found"); FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "No new certificates or certificate updates found");
} }
return 0;
} }
/** /**

View File

@@ -29,6 +29,7 @@ use Froxlor\Cron\Http\Php\PhpInterface;
use Froxlor\Customer\Customer; use Froxlor\Customer\Customer;
use Froxlor\Database\Database; use Froxlor\Database\Database;
use Froxlor\Domain\Domain; use Froxlor\Domain\Domain;
use Froxlor\Froxlor;
use Froxlor\FileDir; use Froxlor\FileDir;
use Froxlor\FroxlorLogger; use Froxlor\FroxlorLogger;
use Froxlor\Http\Directory; use Froxlor\Http\Directory;
@@ -36,14 +37,9 @@ use Froxlor\Http\Statistics;
use Froxlor\Settings; use Froxlor\Settings;
use Froxlor\Validate\Validate; use Froxlor\Validate\Validate;
use Froxlor\System\Crypt; use Froxlor\System\Crypt;
use Froxlor\Idna\IdnaWrapper;
use PDO; use PDO;
/**
* @author Florian Lippert <flo@syscp.org> (2003-2009)
* @author Froxlor team <team@froxlor.org> (2010-)
*
* @todo ssl-redirect to non-standard port
*/
class Lighttpd extends HttpConfigBase class Lighttpd extends HttpConfigBase
{ {
@@ -81,7 +77,7 @@ class Lighttpd extends HttpConfigBase
$ipv6 = ''; $ipv6 = '';
} }
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'lighttpd::createIpPort: creating ip/port settings for ' . $ip . ":" . $port); FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'lighttpd::createIpPort: creating ip/port settings for ' . $ip . ":" . $port);
$vhost_filename = FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/10_froxlor_ipandport_' . trim(str_replace(':', '.', $row_ipsandports['ip']), '.') . '.' . $row_ipsandports['port'] . '.conf'); $vhost_filename = FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/10_froxlor_ipandport_' . trim(str_replace(':', '.', $row_ipsandports['ip']), '.') . '.' . $row_ipsandports['port'] . '.conf');
if (!isset($this->lighttpd_data[$vhost_filename])) { if (!isset($this->lighttpd_data[$vhost_filename])) {
@@ -125,6 +121,15 @@ class Lighttpd extends HttpConfigBase
} }
if (!$is_redirect) { if (!$is_redirect) {
// protect lib/userdata.inc.php
$this->lighttpd_data[$vhost_filename] .= ' $HTTP["host"] =~ "' . rtrim(Froxlor::getInstallDir(), "/") . '/lib" {' . "\n";
$this->lighttpd_data[$vhost_filename] .= ' url.access-deny = ("userdata.inc.php")' . "\n";
$this->lighttpd_data[$vhost_filename] .= ' }' . "\n";
// protect bin/
$this->lighttpd_data[$vhost_filename] .= ' $HTTP["host"] =~ "' . rtrim(Froxlor::getInstallDir(), "/") . '/bin" {' . "\n";
$this->lighttpd_data[$vhost_filename] .= ' url.access-deny = ("")' . "\n";
$this->lighttpd_data[$vhost_filename] .= ' }' . "\n";
/** /**
* dirprotection, see #72 * dirprotection, see #72
* *
@@ -213,7 +218,7 @@ class Lighttpd extends HttpConfigBase
if (($row_ipsandports['ssl_cert_file'] == '' || !file_exists($row_ipsandports['ssl_cert_file'])) && (Settings::Get('system.le_froxlor_enabled') == '0' || $this->froxlorVhostHasLetsEncryptCert() == false)) { if (($row_ipsandports['ssl_cert_file'] == '' || !file_exists($row_ipsandports['ssl_cert_file'])) && (Settings::Get('system.le_froxlor_enabled') == '0' || $this->froxlorVhostHasLetsEncryptCert() == false)) {
$row_ipsandports['ssl_cert_file'] = Settings::Get('system.ssl_cert_file'); $row_ipsandports['ssl_cert_file'] = Settings::Get('system.ssl_cert_file');
if (!file_exists($row_ipsandports['ssl_cert_file'])) { if (!file_exists($row_ipsandports['ssl_cert_file'])) {
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Creating self-signed certificate...'); FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Creating self-signed certificate...');
Crypt::createSelfSignedCertificate(); Crypt::createSelfSignedCertificate();
} }
} }
@@ -255,7 +260,7 @@ class Lighttpd extends HttpConfigBase
if ($domain['ssl_cert_file'] != '') { if ($domain['ssl_cert_file'] != '') {
// check for existence, #1485 // check for existence, #1485
if (!file_exists($domain['ssl_cert_file'])) { if (!file_exists($domain['ssl_cert_file'])) {
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, $ip . ':' . $port . ' :: certificate file "' . $domain['ssl_cert_file'] . '" does not exist! Cannot create ssl-directives'); FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, $ip . ':' . $port . ' :: certificate file "' . $domain['ssl_cert_file'] . '" does not exist! Cannot create ssl-directives');
echo $ip . ':' . $port . ' :: certificate file "' . $domain['ssl_cert_file'] . '" does not exist! Cannot create SSL-directives' . "\n"; echo $ip . ':' . $port . ' :: certificate file "' . $domain['ssl_cert_file'] . '" does not exist! Cannot create SSL-directives' . "\n";
} else { } else {
$this->lighttpd_data[$vhost_filename] .= 'ssl.engine = "enable"' . "\n"; $this->lighttpd_data[$vhost_filename] .= 'ssl.engine = "enable"' . "\n";
@@ -277,7 +282,7 @@ class Lighttpd extends HttpConfigBase
if ($domain['ssl_ca_file'] != '') { if ($domain['ssl_ca_file'] != '') {
// check for existence, #1485 // check for existence, #1485
if (!file_exists($domain['ssl_ca_file'])) { if (!file_exists($domain['ssl_ca_file'])) {
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, $ip . ':' . $port . ' :: certificate CA file "' . $domain['ssl_ca_file'] . '" does not exist! Cannot create ssl-directives'); FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, $ip . ':' . $port . ' :: certificate CA file "' . $domain['ssl_ca_file'] . '" does not exist! Cannot create ssl-directives');
echo $ip . ':' . $port . ' :: certificate CA file "' . $domain['ssl_ca_file'] . '" does not exist! SSL-directives might not be working' . "\n"; echo $ip . ':' . $port . ' :: certificate CA file "' . $domain['ssl_ca_file'] . '" does not exist! SSL-directives might not be working' . "\n";
} else { } else {
$this->lighttpd_data[$vhost_filename] .= 'ssl.ca-file = "' . FileDir::makeCorrectFile($domain['ssl_ca_file']) . '"' . "\n"; $this->lighttpd_data[$vhost_filename] .= 'ssl.ca-file = "' . FileDir::makeCorrectFile($domain['ssl_ca_file']) . '"' . "\n";
@@ -562,21 +567,19 @@ class Lighttpd extends HttpConfigBase
$this->deactivated = true; $this->deactivated = true;
} else { } else {
if ($ssl === false && $domain['ssl_redirect'] == '1') { if ($ssl === false && $domain['ssl_redirect'] == '1') {
$redirect_domain = $this->idnaConvert->encode('https://' . $domain['domain']); $redirect_domain = (new IdnaWrapper)->encode('https://' . $domain['domain']);
$webroot_text .= ' url.redirect = (' . "\n";
$webroot_text .= "\t" . '"^/(.*)" => "' . $redirect_domain . '/$1",' . "\n";
$webroot_text .= "\t" . '"" => "' . $redirect_domain . '",' . "\n";
$webroot_text .= "\t" . '"/" => "' . $redirect_domain . '"' . "\n";
$webroot_text .= ' )' . "\n";
} elseif (preg_match("#^https?://#i", $domain['documentroot'])) { } elseif (preg_match("#^https?://#i", $domain['documentroot'])) {
$redirect_domain = $this->idnaConvert->encode($domain['documentroot']); $redirect_domain = (new IdnaWrapper)->encode($domain['documentroot']);
$webroot_text .= ' url.redirect = (' . "\n";
$webroot_text .= "\t" . '"^/(.*)" => "' . $redirect_domain . '/$1",' . "\n";
$webroot_text .= "\t" . '"" => "' . $redirect_domain . '",' . "\n";
$webroot_text .= "\t" . '"/" => "' . $redirect_domain . '"' . "\n";
$webroot_text .= ' )' . "\n";
} else { } else {
$webroot_text .= ' server.document-root = "' . FileDir::makeCorrectDir($domain['documentroot']) . "\"\n"; $webroot_text .= ' server.document-root = "' . FileDir::makeCorrectDir($domain['documentroot']) . "\"\n";
$redirect_domain = '';
}
if (!empty($redirect_domain)) {
$webroot_text .= ' url.redirect = (' . "\n";
$webroot_text .= "\t" . '"^/(.*)" => "' . $redirect_domain . '/$1",' . "\n";
$webroot_text .= "\t" . '"" => "' . $redirect_domain . '",' . "\n";
$webroot_text .= "\t" . '"/" => "' . $redirect_domain . '"' . "\n";
$webroot_text .= ' )' . "\n";
} }
$this->deactivated = false; $this->deactivated = false;
} }
@@ -756,7 +759,7 @@ class Lighttpd extends HttpConfigBase
if (!file_exists($domain['ssl_cert_file'])) { if (!file_exists($domain['ssl_cert_file'])) {
// explicitly disable ssl for this vhost // explicitly disable ssl for this vhost
$domain['ssl_cert_file'] = ""; $domain['ssl_cert_file'] = "";
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Disabling SSL-vhost for "' . $domain['domain'] . '"'); FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Disabling SSL-vhost for "' . $domain['domain'] . '"');
} }
} }
@@ -914,7 +917,7 @@ class Lighttpd extends HttpConfigBase
public function writeConfigs() public function writeConfigs()
{ {
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "lighttpd::writeConfigs: rebuilding " . Settings::Get('system.apacheconf_vhost')); FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "lighttpd::writeConfigs: rebuilding " . Settings::Get('system.apacheconf_vhost'));
$vhostDir = new Directory(Settings::Get('system.apacheconf_vhost')); $vhostDir = new Directory(Settings::Get('system.apacheconf_vhost'));
if (!$vhostDir->isConfigDir()) { if (!$vhostDir->isConfigDir()) {
@@ -941,14 +944,12 @@ class Lighttpd extends HttpConfigBase
fclose($vhosts_file_handler); fclose($vhosts_file_handler);
} else { } else {
if (!file_exists(Settings::Get('system.apacheconf_vhost'))) { if (!file_exists(Settings::Get('system.apacheconf_vhost'))) {
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'lighttpd::writeConfigs: mkdir ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'lighttpd::writeConfigs: mkdir ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost'))));
FileDir::safe_exec('mkdir ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); FileDir::safe_exec('mkdir ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost'))));
} }
// Write a single file for every vhost // Write a single file for every vhost
foreach ($this->lighttpd_data as $vhosts_filename => $vhosts_file) { foreach ($this->lighttpd_data as $vhosts_filename => $vhosts_file) {
$this->known_filenames[] = basename($vhosts_filename);
// Apply header // Apply header
$vhosts_file = '# ' . basename($vhosts_filename) . "\n" . '# Created ' . date('d.m.Y H:i') . "\n" . '# Do NOT manually edit this file, all changes will be deleted after the next domain change at the panel.' . "\n" . "\n" . $vhosts_file; $vhosts_file = '# ' . basename($vhosts_filename) . "\n" . '# Created ' . date('d.m.Y H:i') . "\n" . '# Do NOT manually edit this file, all changes will be deleted after the next domain change at the panel.' . "\n" . "\n" . $vhosts_file;

View File

@@ -29,6 +29,7 @@ use Froxlor\Cron\Http\Php\PhpInterface;
use Froxlor\Customer\Customer; use Froxlor\Customer\Customer;
use Froxlor\Database\Database; use Froxlor\Database\Database;
use Froxlor\Domain\Domain; use Froxlor\Domain\Domain;
use Froxlor\Froxlor;
use Froxlor\FileDir; use Froxlor\FileDir;
use Froxlor\FroxlorLogger; use Froxlor\FroxlorLogger;
use Froxlor\Http\Directory; use Froxlor\Http\Directory;
@@ -50,8 +51,7 @@ class Nginx extends HttpConfigBase
protected $known_htpasswdsfilenames = []; protected $known_htpasswdsfilenames = [];
protected $mod_accesslog_loaded = '0'; protected $mod_accesslog_loaded = '0';
protected $vhost_root_autoindex = false; protected $vhost_root_autoindex = false;
protected $known_vhostfilenames = [];
private $nginx_server = [];
/** /**
* indicator whether a customer is deactivated or not * indicator whether a customer is deactivated or not
* if yes, only the webroot will be generated * if yes, only the webroot will be generated
@@ -60,11 +60,6 @@ class Nginx extends HttpConfigBase
*/ */
private $deactivated = false; private $deactivated = false;
public function __construct($nginx_server = [])
{
$this->nginx_server = $nginx_server;
}
public function createVirtualHosts() public function createVirtualHosts()
{ {
return; return;
@@ -218,6 +213,16 @@ class Nginx extends HttpConfigBase
$this->nginx_data[$vhost_filename] .= "\t" . 'index index.php index.html index.htm;' . "\n\n"; $this->nginx_data[$vhost_filename] .= "\t" . 'index index.php index.html index.htm;' . "\n\n";
$this->nginx_data[$vhost_filename] .= "\t" . 'location / {' . "\n"; $this->nginx_data[$vhost_filename] .= "\t" . 'location / {' . "\n";
$this->nginx_data[$vhost_filename] .= "\t" . '}' . "\n"; $this->nginx_data[$vhost_filename] .= "\t" . '}' . "\n";
// protect lib/userdata.inc.php
$this->nginx_data[$vhost_filename] .= "\t" . 'location = ' . rtrim(Froxlor::getInstallDir(), "/") . '/lib/userdata.inc.php {' . "\n";
$this->nginx_data[$vhost_filename] .= "\t" . ' deny all;' . "\n";
$this->nginx_data[$vhost_filename] .= "\t" . '}' . "\n";
// protect bin/
$this->nginx_data[$vhost_filename] .= "\t" . 'location = ' . rtrim(Froxlor::getInstallDir(), "/") . '/bin {' . "\n";
$this->nginx_data[$vhost_filename] .= "\t" . ' deny all;' . "\n";
$this->nginx_data[$vhost_filename] .= "\t" . '}' . "\n";
} }
if ($row_ipsandports['specialsettings'] != '' && ($row_ipsandports['ssl'] == '0' || ($row_ipsandports['ssl'] == '1' && Settings::Get('system.use_ssl') == '1' && $row_ipsandports['include_specialsettings'] == '1'))) { if ($row_ipsandports['specialsettings'] != '' && ($row_ipsandports['ssl'] == '0' || ($row_ipsandports['ssl'] == '1' && Settings::Get('system.use_ssl') == '1' && $row_ipsandports['include_specialsettings'] == '1'))) {
@@ -1242,8 +1247,6 @@ class Nginx extends HttpConfigBase
// Write a single file for every vhost // Write a single file for every vhost
foreach ($this->nginx_data as $vhosts_filename => $vhosts_file) { foreach ($this->nginx_data as $vhosts_filename => $vhosts_file) {
$this->known_filenames[] = basename($vhosts_filename);
// Apply header // Apply header
$vhosts_file = '# ' . basename($vhosts_filename) . "\n" . '# Created ' . date('d.m.Y H:i') . "\n" . '# Do NOT manually edit this file, all changes will be deleted after the next domain change at the panel.' . "\n" . "\n" . $vhosts_file; $vhosts_file = '# ' . basename($vhosts_filename) . "\n" . '# Created ' . date('d.m.Y H:i') . "\n" . '# Do NOT manually edit this file, all changes will be deleted after the next domain change at the panel.' . "\n" . "\n" . $vhosts_file;

View File

@@ -46,11 +46,11 @@ class PhpInterface
private $interface = null; private $interface = null;
/** /**
* Admin-User data array * PHP-Config data array
* *
* @var array * @var array
*/ */
private $admin_cache = []; private $php_configs_cache = [];
/** /**
* main constructor * main constructor
@@ -93,10 +93,8 @@ class PhpInterface
* *
* @return array * @return array
*/ */
public function getPhpConfig($php_config_id) public function getPhpConfig(int $php_config_id)
{ {
$php_config_id = intval($php_config_id);
// If domain has no config, we will use the default one. // If domain has no config, we will use the default one.
if ($php_config_id == 0) { if ($php_config_id == 0) {
$php_config_id = 1; $php_config_id = 1;
@@ -104,24 +102,26 @@ class PhpInterface
if (!isset($this->php_configs_cache[$php_config_id])) { if (!isset($this->php_configs_cache[$php_config_id])) {
$stmt = Database::prepare(" $stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `id` = :id"); SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `id` = :id
$this->_php_configs_cache[$php_config_id] = Database::pexecute_first($stmt, [ ");
$this->php_configs_cache[$php_config_id] = Database::pexecute_first($stmt, [
'id' => $php_config_id 'id' => $php_config_id
]); ]);
if ((int)Settings::Get('phpfpm.enabled') == 1) { if ((int)Settings::Get('phpfpm.enabled') == 1) {
$stmt = Database::prepare(" $stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "` WHERE `id` = :id"); SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "` WHERE `id` = :id
$this->_php_configs_cache[$php_config_id]['fpm_settings'] = Database::pexecute_first($stmt, [ ");
'id' => $this->_php_configs_cache[$php_config_id]['fpmsettingid'] $this->php_configs_cache[$php_config_id]['fpm_settings'] = Database::pexecute_first($stmt, [
'id' => $this->php_configs_cache[$php_config_id]['fpmsettingid']
]); ]);
// override fpm daemon settings if set in php-config // override fpm daemon settings if set in php-config
if ($this->_php_configs_cache[$php_config_id]['override_fpmconfig'] == 1) { if ($this->php_configs_cache[$php_config_id]['override_fpmconfig'] == 1) {
$this->_php_configs_cache[$php_config_id]['fpm_settings']['limit_extensions'] = $this->_php_configs_cache[$php_config_id]['limit_extensions']; $this->php_configs_cache[$php_config_id]['fpm_settings']['limit_extensions'] = $this->php_configs_cache[$php_config_id]['limit_extensions'];
$this->_php_configs_cache[$php_config_id]['fpm_settings']['idle_timeout'] = $this->_php_configs_cache[$php_config_id]['idle_timeout']; $this->php_configs_cache[$php_config_id]['fpm_settings']['idle_timeout'] = $this->php_configs_cache[$php_config_id]['idle_timeout'];
} }
} }
} }
return $this->_php_configs_cache[$php_config_id]; return $this->php_configs_cache[$php_config_id];
} }
} }

View File

@@ -1,392 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can also view it online at
* https://files.froxlor.org/misc/COPYING.txt
*
* @copyright the authors
* @author Froxlor team <team@froxlor.org>
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
*/
namespace Froxlor\Cron;
use Exception;
use Froxlor\Cron\System\Extrausers;
use Froxlor\Database\Database;
use Froxlor\FileDir;
use Froxlor\Froxlor;
use Froxlor\FroxlorLogger;
use Froxlor\Settings;
use Froxlor\System\Cronjob;
use PDO;
class MasterCron extends FroxlorCron
{
private static $argv = null;
private static $debugHandler = null;
private static $noncron_params = [
'force',
'debug',
'no-fork',
'run-task'
];
public static function setArguments($argv = null)
{
self::$argv = $argv;
}
public static function run()
{
self::init();
$jobs_to_run = [];
$argv = self::$argv;
/**
* check for --help
*/
if (count($argv) < 2 || (isset($argv[1]) && strtolower($argv[1]) == '--help')) {
echo "\n*** Froxlor Master Cronjob ***\n\n";
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\tdo not fork to backkground (traffic cron only).\n\n";
exit();
}
/**
* check for parameters
*
* --[cronname] include [cronname]
* --force to include cron_tasks even if it's not its turn
* --debug to output debug information
*/
for ($x = 1; $x < count($argv); $x++) {
// check argument
if (isset($argv[$x])) {
// --force
if (strtolower($argv[$x]) == '--force') {
// really force re-generating of config-files by
// inserting task 1
Cronjob::inserttask(TaskId::REBUILD_VHOST);
// bind (if enabled, \Froxlor\System\Cronjob::inserttask() checks this)
Cronjob::inserttask(TaskId::REBUILD_DNS);
// set quotas (if enabled)
Cronjob::inserttask(TaskId::CREATE_QUOTA);
// also regenerate cron.d-file
Cronjob::inserttask(TaskId::REBUILD_CRON);
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') {
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])) {
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) {
$cronname = substr(strtolower($argv[$x]), 2);
array_push($jobs_to_run, $cronname);
}
}
}
}
$jobs_to_run = array_unique($jobs_to_run);
self::$cronlog->setCronDebugFlag(defined('CRON_DEBUG_FLAG'));
$tasks_cnt_stmt = Database::query("SELECT COUNT(*) as jobcnt FROM `panel_tasks`");
$tasks_cnt = $tasks_cnt_stmt->fetch(PDO::FETCH_ASSOC);
// do we have anything to include?
if (count($jobs_to_run) > 0) {
// include all jobs we want to execute
foreach ($jobs_to_run as $cron) {
Cronjob::updateLastRunOfCron($cron);
$cronfile = self::getCronModule($cron);
if ($cronfile && class_exists($cronfile)) {
$cronfile::run();
}
}
self::refreshUsers($tasks_cnt['jobcnt']);
}
/**
* we have to check the system's last guid with every cron run
* in case the admin installed new software which added a new user
* so users in the database don't conflict with system users
*/
self::$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Checking system\'s last guid');
Cronjob::checkLastGuid();
// shutdown cron
self::shutdown();
}
private static function init()
{
if (@php_sapi_name() != 'cli' && @php_sapi_name() != 'cgi' && @php_sapi_name() != 'cgi-fcgi') {
die('This script will only work in the shell.');
}
// 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());
}
$basename = basename($_SERVER['PHP_SELF'], '.php');
$crontype = "";
if (isset(self::$argv) && is_array(self::$argv) && count(self::$argv) > 1) {
for ($x = 1; $x < count(self::$argv); $x++) {
if (substr(self::$argv[$x], 0, 2) == '--' && strlen(self::$argv[$x]) > 3 && !in_array(substr(strtolower(self::$argv[$x]), 2), self::$noncron_params)) {
$crontype = substr(strtolower(self::$argv[$x]), 2);
$basename .= "-" . $crontype;
break;
}
}
}
$lockdir = '/var/run/';
$lockFilename = 'froxlor_' . $basename . '.lock-';
$lockfName = $lockFilename . getmypid();
$lockfile = $lockdir . $lockfName;
self::setLockfile($lockfile);
// create and open the lockfile!
self::$debugHandler = fopen($lockfile, 'w');
fwrite(self::$debugHandler, 'Setting Lockfile to ' . $lockfile . "\n");
fwrite(self::$debugHandler, 'Setting Froxlor installation path to ' . Froxlor::getInstallDir() . "\n");
if (!file_exists(Froxlor::getInstallDir() . '/lib/userdata.inc.php')) {
die("Froxlor does not seem to be installed yet - skipping cronjob");
}
$sql = [];
$sql_root = [];
// Includes the Usersettings eg. MySQL-Username/Passwort etc.
require Froxlor::getInstallDir() . '/lib/userdata.inc.php';
fwrite(self::$debugHandler, 'Userdatas included' . "\n");
// Legacy sql-root-information
if (isset($sql['root_user']) && isset($sql['root_password']) && (!isset($sql_root) || !is_array($sql_root))) {
$sql_root = [
0 => [
'caption' => 'Default',
'host' => $sql['host'],
'user' => $sql['root_user'],
'password' => $sql['root_password']
]
];
unset($sql['root_user']);
unset($sql['root_password']);
}
require Froxlor::getInstallDir() . '/lib/functions.php';
// Includes the MySQL-Tabledefinitions etc.
require Froxlor::getInstallDir() . '/lib/tables.inc.php';
fwrite(self::$debugHandler, 'Table definitions included' . "\n");
// try database connection, it will throw
// and exception itself if failed
try {
Database::query("SELECT 1");
} catch (Exception $e) {
// Do not proceed further if no database connection could be established
fclose(self::$debugHandler);
unlink($lockfile);
die($e->getMessage());
}
fwrite(self::$debugHandler, 'Database-connection established' . "\n");
// open the lockfile directory and scan for existing lockfiles
$lockDirHandle = opendir($lockdir);
while ($fName = readdir($lockDirHandle)) {
if ($lockFilename == substr($fName, 0, strlen($lockFilename)) && $lockfName != $fName) {
// Check if last run jailed out with an exception
$croncontent = file($lockdir . $fName);
$lastline = $croncontent[(count($croncontent) - 1)];
if ($lastline == '=== Keep lockfile because of exception ===') {
fclose(self::$debugHandler);
unlink($lockfile);
Cronjob::dieWithMail('Last cron jailed out with an exception. Exiting...' . "\n" . 'Take a look into the contents of ' . $lockdir . $fName . '* for more information!' . "\n");
}
// Check if cron is running or has died.
$check_pid = substr(strrchr($fName, "-"), 1);
$check_pid_return = null;
system("kill -CHLD " . (int)$check_pid . " 1> /dev/null 2> /dev/null", $check_pid_return);
if ($check_pid_return == 1) {
// Result: Existing lockfile/pid isn't running
// Most likely it has died
//
// Action: Remove it and continue
//
fwrite(self::$debugHandler, 'Previous cronjob didn\'t exit clean. PID: ' . $check_pid . "\n");
fwrite(self::$debugHandler, 'Removing lockfile: ' . $lockdir . $fName . "\n");
@unlink($lockdir . $fName);
} else {
// Result: A Cronscript with this pid
// is still running
// Action: remove my own Lock and die
//
// close the current lockfile
fclose(self::$debugHandler);
// ... and delete it
unlink($lockfile);
Cronjob::dieWithMail('There is already a Cronjob for ' . $crontype . ' in progress. Exiting...' . "\n" . 'Take a look into the contents of ' . $lockdir . $lockFilename . '* for more information!' . "\n");
}
}
}
/**
* if using fcgid or fpm for froxlor-vhost itself, we have to check
* whether the permission of the files are still correct
*/
fwrite(self::$debugHandler, 'Checking froxlor file permissions' . "\n");
$_mypath = FileDir::makeCorrectDir(Froxlor::getInstallDir());
if (((int)Settings::Get('system.mod_fcgid') == 1 && (int)Settings::Get('system.mod_fcgid_ownvhost') == 1) || ((int)Settings::Get('phpfpm.enabled') == 1 && (int)Settings::Get('phpfpm.enabled_ownvhost') == 1)) {
$user = Settings::Get('system.mod_fcgid_httpuser');
$group = Settings::Get('system.mod_fcgid_httpgroup');
if (Settings::Get('phpfpm.enabled') == 1) {
$user = Settings::Get('phpfpm.vhost_httpuser');
$group = Settings::Get('phpfpm.vhost_httpgroup');
}
// all the files and folders have to belong to the local user
// now because we also use fcgid for our own vhost
FileDir::safe_exec('chown -R ' . $user . ':' . $group . ' ' . escapeshellarg($_mypath));
} else {
// back to webserver permission
$user = Settings::Get('system.httpuser');
$group = Settings::Get('system.httpgroup');
FileDir::safe_exec('chown -R ' . $user . ':' . $group . ' ' . escapeshellarg($_mypath));
}
// Initialize logging
self::$cronlog = FroxlorLogger::getInstanceOf([
'loginname' => 'cronjob'
]);
fwrite(self::$debugHandler, 'Logger has been included' . "\n");
if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) {
if (Settings::Get('system.cron_allowautoupdate') == null || Settings::Get('system.cron_allowautoupdate') == 0) {
/**
* Do not proceed further if the Database version is not the same as the script version
*/
fclose(self::$debugHandler);
unlink($lockfile);
$errormessage = "Version of file doesn't match version of database. Exiting...\n\n";
$errormessage .= "Possible reason: Froxlor update\n";
$errormessage .= "Information: Current version in database: " . Settings::Get('panel.version') . (!empty(Froxlor::BRANDING) ? "-" . Froxlor::BRANDING : "") . " (DB: " . Settings::Get('panel.db_version') . ") - version of Froxlor files: " . Froxlor::getVersionString() . ")\n";
$errormessage .= "Solution: Please visit your Foxlor admin interface for further information.\n";
Cronjob::dieWithMail($errormessage);
}
if (Settings::Get('system.cron_allowautoupdate') == 1) {
/**
* let's walk the walk - do the dangerous shit
*/
self::$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, 'Automatic update is activated and we are going to proceed without any notices');
self::$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, 'all new settings etc. will be stored with the default value, that might not always be right for your system!');
self::$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "If you don't want this to happen in the future consider removing the --allow-autoupdate flag from the cronjob");
fwrite(self::$debugHandler, '*** WARNING *** - Automatic update is activated and we are going to proceed without any notices' . "\n");
fwrite(self::$debugHandler, '*** WARNING *** - all new settings etc. will be stored with the default value, that might not always be right for your system!' . "\n");
fwrite(self::$debugHandler, "*** WARNING *** - If you don't want this to happen in the future consider removing the --allow-autoupdate flag from the cronjob\n");
// including update procedures
define('_CRON_UPDATE', 1);
include_once Froxlor::getInstallDir() . '/install/updatesql.php';
// pew - everything went better than expected
self::$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, 'Automatic update done - you should check your settings to be sure everything is fine');
fwrite(self::$debugHandler, '*** WARNING *** - Automatic update done - you should check your settings to be sure everything is fine' . "\n");
}
}
fwrite(self::$debugHandler, 'Froxlor version and database version are correct' . "\n");
}
private static function getCronModule($cronname)
{
$upd_stmt = Database::prepare("
SELECT `cronclass` FROM `" . TABLE_PANEL_CRONRUNS . "` WHERE `cronfile` = :cron;
");
$cron = Database::pexecute_first($upd_stmt, [
'cron' => $cronname
]);
if ($cron) {
return $cron['cronclass'];
}
self::$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Requested cronjob '" . $cronname . "' could not be found.");
return false;
}
private static function refreshUsers($jobcount = 0)
{
if ($jobcount > 0) {
if (Settings::Get('system.nssextrausers') == 1) {
Extrausers::generateFiles(self::$cronlog);
}
// clear NSCD cache if using fcgid or fpm, #1570 - not needed for nss-extrausers
if ((Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) && Settings::Get('system.nssextrausers') == 0) {
$false_val = false;
FileDir::safe_exec('nscd -i passwd 1> /dev/null', $false_val, [
'>'
]);
FileDir::safe_exec('nscd -i group 1> /dev/null', $false_val, [
'>'
]);
}
}
}
private static function shutdown()
{
// check for cron.d-generation task and create it if necessary
CronConfig::checkCrondConfigurationFile();
if (Settings::Get('logger.log_cron') == '1') {
FroxlorLogger::getInstanceOf()->setCronLog(0);
fwrite(self::$debugHandler, 'Logging for cron has been shutdown' . "\n");
}
fclose(self::$debugHandler);
if (Settings::Get('system.debug_cron') != '1') {
unlink(self::getLockfile());
}
}
}

View File

@@ -27,6 +27,7 @@ namespace Froxlor\Cron\System;
use Froxlor\Cron\FroxlorCron; use Froxlor\Cron\FroxlorCron;
use Froxlor\Cron\Http\ConfigIO; use Froxlor\Cron\Http\ConfigIO;
use Froxlor\Cron\Http\HttpConfigBase;
use Froxlor\Cron\TaskId; use Froxlor\Cron\TaskId;
use Froxlor\Database\Database; use Froxlor\Database\Database;
use Froxlor\Dns\PowerDNS; use Froxlor\Dns\PowerDNS;
@@ -158,7 +159,7 @@ class TasksCron extends FroxlorCron
// get webserver object // get webserver object
$webserver = new $websrv(); $webserver = new $websrv();
if (isset($webserver)) { if ($webserver instanceof HttpConfigBase) {
$webserver->init(); $webserver->init();
// clean up old configs // clean up old configs
$configio->cleanUp(); $configio->cleanUp();

View File

@@ -45,6 +45,7 @@ use PDOStatement;
* object * object
* @method static string lastInsertId ($name = null) Returns the ID of the last inserted row or sequence value * @method static string lastInsertId ($name = null) Returns the ID of the last inserted row or sequence value
* @method static string quote ($string, $parameter_type = null) Quotes a string for use in a query. * @method static string quote ($string, $parameter_type = null) Quotes a string for use in a query.
* @method static mixed getAttribute(int $attribute) Retrieve a database connection attribute
*/ */
class Database class Database
{ {
@@ -127,11 +128,14 @@ class Database
{ {
global $userinfo, $theme, $linker; global $userinfo, $theme, $linker;
$sql = [];
$sql_root = [];
// include userdata.inc.php // include userdata.inc.php
require Froxlor::getInstallDir() . "/lib/userdata.inc.php"; require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
// le format // le format
if (isset($sql['root_user']) && isset($sql['root_password']) && (!isset($sql_root) || !is_array($sql_root))) { if (isset($sql['root_user']) && isset($sql['root_password']) && !is_array($sql_root)) {
$sql_root = [ $sql_root = [
0 => [ 0 => [
'caption' => 'Default', 'caption' => 'Default',
@@ -291,13 +295,13 @@ class Database
*/ */
private static function genUniqueToken(int $length = 16) private static function genUniqueToken(int $length = 16)
{ {
if (!isset($length) || intval($length) <= 8) { if (intval($length) <= 8) {
$length = 16; $length = 16;
} }
if (function_exists('random_bytes')) { if (function_exists('random_bytes')) {
return bin2hex(random_bytes($length)); return bin2hex(random_bytes($length));
} }
if (function_exists('mcrypt_create_iv')) { if (function_exists('mcrypt_create_iv') && defined('MCRYPT_DEV_URANDOM')) {
return bin2hex(mcrypt_create_iv($length, MCRYPT_DEV_URANDOM)); return bin2hex(mcrypt_create_iv($length, MCRYPT_DEV_URANDOM));
} }
if (function_exists('openssl_random_pseudo_bytes')) { if (function_exists('openssl_random_pseudo_bytes')) {

View File

@@ -26,12 +26,10 @@
namespace Froxlor; namespace Froxlor;
use Exception; use Exception;
use Froxlor\Customer\Customer;
use Froxlor\Database\Database;
use PDO; use PDO;
use RecursiveCallbackFilterIterator; use RecursiveCallbackFilterIterator;
use RecursiveDirectoryIterator; use Froxlor\Customer\Customer;
use RecursiveIteratorIterator; use Froxlor\Database\Database;
class FileDir class FileDir
{ {
@@ -315,9 +313,9 @@ class FileDir
* *
* @return string the corrected filename * @return string the corrected filename
*/ */
public static function makeCorrectFile($filename) public static function makeCorrectFile(string $filename)
{ {
if (!isset($filename) || trim($filename) == '') { if (trim($filename) == '') {
$error = 'Given filename for function ' . __FUNCTION__ . ' is empty.' . "\n"; $error = 'Given filename for function ' . __FUNCTION__ . ' is empty.' . "\n";
$error .= 'This is very dangerous and should not happen.' . "\n"; $error .= 'This is very dangerous and should not happen.' . "\n";
$error .= 'Please inform the Froxlor team about this issue so they can fix it.'; $error .= 'Please inform the Froxlor team about this issue so they can fix it.';
@@ -527,7 +525,7 @@ class FileDir
new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS),
$filter $filter
), ),
\RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::SELF_FIRST,
\RecursiveIteratorIterator::CATCH_GET_CHILD \RecursiveIteratorIterator::CATCH_GET_CHILD
); );
// we can limit the recursion-depth, but will it be helpful or // we can limit the recursion-depth, but will it be helpful or
@@ -550,26 +548,24 @@ class FileDir
/** /**
* set the immutable flag for a file * set the immutable flag for a file
* *
* @param string $filename * @param string $filename the file to set the flag for
* the file to set the flag for
* *
* @return boolean * @return void
*/ */
public static function setImmutable($filename = null) public static function setImmutable(string $filename)
{ {
FileDir::safe_exec(self::getImmutableFunction(false) . escapeshellarg($filename)); self::safe_exec(self::getImmutableFunction(false) . escapeshellarg($filename));
} }
/** /**
* internal function to check whether * internal function to check whether
* to use chattr (Linux) or chflags (FreeBSD) * to use chattr (Linux) or chflags (FreeBSD)
* *
* @param boolean $remove * @param bool $remove whether to use +i|schg (false) or -i|noschg (true)
* whether to use +i|schg (false) or -i|noschg (true)
* *
* @return string functionname + parameter (not the file) * @return string functionname + parameter (not the file)
*/ */
private static function getImmutableFunction($remove = false) private static function getImmutableFunction(bool $remove = false)
{ {
if (self::isFreeBSD()) { if (self::isFreeBSD()) {
// FreeBSD style // FreeBSD style
@@ -585,12 +581,11 @@ class FileDir
* or BSD-based (NetBSD, OpenBSD, etc. * or BSD-based (NetBSD, OpenBSD, etc.
* if exact = false [default]) * if exact = false [default])
* *
* @param boolean $exact * @param bool $exact whether to check explicitly for FreeBSD or *BSD
* whether to check explicitly for FreeBSD or *BSD
* *
* @return boolean * @return bool
*/ */
public static function isFreeBSD($exact = false) public static function isFreeBSD(bool $exact = false)
{ {
if (($exact && PHP_OS == 'FreeBSD') || (!$exact && stristr(PHP_OS, 'BSD'))) { if (($exact && PHP_OS == 'FreeBSD') || (!$exact && stristr(PHP_OS, 'BSD'))) {
return true; return true;
@@ -601,16 +596,19 @@ class FileDir
/** /**
* removes the immutable flag for a file * removes the immutable flag for a file
* *
* @param string $filename * @param string $filename the file to set the flag for
* the file to set the flag for
* *
* @return boolean * @return void
*/ */
public static function removeImmutable($filename = null) public static function removeImmutable(string $filename)
{ {
FileDir::safe_exec(self::getImmutableFunction(true) . escapeshellarg($filename)); FileDir::safe_exec(self::getImmutableFunction(true) . escapeshellarg($filename));
} }
/**
*
* @return array|false
*/
public static function getFilesystemQuota() public static function getFilesystemQuota()
{ {
// enabled at all? // enabled at all?

View File

@@ -234,13 +234,13 @@ final class Froxlor
*/ */
public static function genSessionId(int $length = 16) public static function genSessionId(int $length = 16)
{ {
if (!isset($length) || intval($length) <= 8) { if (intval($length) <= 8) {
$length = 16; $length = 16;
} }
if (function_exists('random_bytes')) { if (function_exists('random_bytes')) {
return bin2hex(random_bytes($length)); return bin2hex(random_bytes($length));
} }
if (function_exists('mcrypt_create_iv')) { if (function_exists('mcrypt_create_iv') && defined('MCRYPT_DEV_URANDOM')) {
return bin2hex(mcrypt_create_iv($length, MCRYPT_DEV_URANDOM)); return bin2hex(mcrypt_create_iv($length, MCRYPT_DEV_URANDOM));
} }
if (function_exists('openssl_random_pseudo_bytes')) { if (function_exists('openssl_random_pseudo_bytes')) {

View File

@@ -258,30 +258,28 @@ class FroxlorLogger
/** /**
* Set whether to log cron-runs * Set whether to log cron-runs
* *
* @param bool $_cronlog * @param int $cronlog
* *
* @return boolean * @return int
*/ */
public function setCronLog($_cronlog = 0) public function setCronLog(int $cronlog = 0)
{ {
$_cronlog = (int)$_cronlog; if ($cronlog < 0 || $cronlog > 2) {
$cronlog = 0;
if ($_cronlog < 0 || $_cronlog > 2) {
$_cronlog = 0;
} }
Settings::Set('logger.log_cron', $_cronlog); Settings::Set('logger.log_cron', $cronlog);
return $_cronlog; return $cronlog;
} }
/** /**
* setter for crondebug-flag * setter for crondebug-flag
* *
* @param bool $_flag * @param bool $flag
* *
* @return void * @return void
*/ */
public function setCronDebugFlag($_flag = false) public function setCronDebugFlag(bool $flag = false)
{ {
self::$crondebug_flag = (bool)$_flag; self::$crondebug_flag = $flag;
} }
} }

View File

@@ -26,6 +26,7 @@
namespace Froxlor\Install; namespace Froxlor\Install;
use Exception; use Exception;
use ZipArchive;
use Froxlor\Froxlor; use Froxlor\Froxlor;
use Froxlor\Settings; use Froxlor\Settings;
use Froxlor\Http\HttpClient; use Froxlor\Http\HttpClient;

View File

@@ -332,7 +332,7 @@ class Install
throw new Exception(lng('error.emailiswrong', [$email])); throw new Exception(lng('error.emailiswrong', [$email]));
} elseif (empty($password) || $password != $password_confirm) { } elseif (empty($password) || $password != $password_confirm) {
throw new Exception(lng('error.newpasswordconfirmerror')); throw new Exception(lng('error.newpasswordconfirmerror'));
} elseif (!empty($password) && $password == $loginname) { } elseif ($password == $loginname) {
throw new Exception(lng('error.passwordshouldnotbeusername')); throw new Exception(lng('error.passwordshouldnotbeusername'));
} }
} }
@@ -404,8 +404,20 @@ class Install
$default = 'bullseye'; $default = 'bullseye';
// read os-release // read os-release
if (@file_exists('/etc/os-release')) { if (@file_exists('/etc/os-release') && is_readable('/etc/os-release')) {
if (function_exists('parse_ini_file')) {
$os_dist = parse_ini_file('/etc/os-release', false); $os_dist = parse_ini_file('/etc/os-release', false);
} else {
$osrf = explode("\n", file_get_contents('/etc/os-release'));
foreach ($osrf as $line) {
$osrfline = explode("\n", $line);
if ($osrfline[0] == 'VERSION_CODENAME') {
$os_dist['VERSION_CODENAME'] = $osrfline[1];
} else if ($osrfline[0] == 'ID') {
$os_dist['ID'] = $osrfline[1];
}
}
}
return strtolower($os_dist['VERSION_CODENAME'] ?? ($os_dist['ID'] ?? $default)); return strtolower($os_dist['VERSION_CODENAME'] ?? ($os_dist['ID'] ?? $default));
} }
return $default; return $default;

View File

@@ -52,7 +52,7 @@ class Core
* @return void * @return void
* @throws Exception * @throws Exception
*/ */
public function doInstall() public function doInstall(bool $create_ud_str = true)
{ {
$options = [ $options = [
'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8' 'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8'
@@ -116,6 +116,9 @@ class Core
$this->doDataEntries($pdo); $this->doDataEntries($pdo);
// create JSON array for config-services // create JSON array for config-services
$this->createJsonArray(); $this->createJsonArray();
if ($create_ud_str) {
$this->createUserdataParamStr();
}
} }
public function getUnprivilegedPdo(): PDO public function getUnprivilegedPdo(): PDO
@@ -675,4 +678,23 @@ class Core
]; ];
$_SESSION['installation']['json_params'] = json_encode($json_params); $_SESSION['installation']['json_params'] = json_encode($json_params);
} }
private function createUserdataParamStr()
{
$req_fields = [
'mysql_host',
'mysql_unprivileged_user',
'mysql_unprivileged_pass',
'mysql_database',
'mysql_root_user',
'mysql_root_pass',
'mysql_ssl_ca_file',
'mysql_ssl_verify_server_certificate'
];
$json_params = [];
foreach ($req_fields as $field) {
$json_params[$field] = $this->validatedData[$field] ?? "";
}
$_SESSION['installation']['ud_str'] = base64_encode(json_encode($json_params));
}
} }

View File

@@ -31,6 +31,9 @@ use Froxlor\Settings;
class Update class Update
{ {
private static $update_tasks = [];
private static $task_counter = 0;
/** /**
* Function showUpdateStep * Function showUpdateStep
@@ -42,20 +45,18 @@ class Update
* *
* @return void * @return void
*/ */
public static function showUpdateStep($task = null, $needs_status = true) public static function showUpdateStep(string $task, bool $needs_status = true)
{ {
global $update_tasks, $task_counter;
set_time_limit(30); set_time_limit(30);
// output // output
$update_tasks[$task_counter] = ['title' => $task, 'result' => 0]; self::$update_tasks[self::$task_counter] = ['title' => $task, 'result' => 0];
if (!$needs_status) { if (!$needs_status) {
$task_counter++; self::$task_counter++;
} }
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, $task); FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::ADM_ACTION, \LOG_WARNING, $task);
} }
/** /**
@@ -67,35 +68,33 @@ class Update
* @param string $message * @param string $message
* @param string $additional_info * @param string $additional_info
* *
* @return string formatted output and log-entry * @return void
*/ */
public static function lastStepStatus(int $status = -1, string $message = '', string $additional_info = '') public static function lastStepStatus(int $status = -1, string $message = 'OK', string $additional_info = '')
{ {
global $update_tasks, $task_counter; self::$update_tasks[self::$task_counter]['result_txt'] = $message;
self::$update_tasks[self::$task_counter]['result_desc'] = $additional_info;
$update_tasks[$task_counter]['result_txt'] = $message ?? 'OK';
$update_tasks[$task_counter]['result_desc'] = $additional_info ?? '';
switch ($status) { switch ($status) {
case 0: case 0:
break; break;
case 1: case 1:
$update_tasks[$task_counter]['result'] = 2; self::$update_tasks[self::$task_counter]['result'] = 2;
break; break;
case 2: case 2:
$update_tasks[$task_counter]['result'] = 1; self::$update_tasks[self::$task_counter]['result'] = 1;
break; break;
default: default:
$update_tasks[$task_counter]['result'] = -1; self::$update_tasks[self::$task_counter]['result'] = -1;
break; break;
} }
$task_counter++; self::$task_counter++;
if ($status == -1 || $status == 2) { if ($status == -1 || $status == 2) {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, 'Attention - last update task failed!!!'); FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::ADM_ACTION, \LOG_WARNING, 'Attention - last update task failed!!!');
} elseif ($status == 0 || $status == 1) { } elseif ($status == 0 || $status == 1) {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, 'Success'); FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::ADM_ACTION, \LOG_WARNING, 'Success');
} }
} }
@@ -127,4 +126,14 @@ class Update
} }
return null; return null;
} }
public static function getUpdateTasks(): array
{
return self::$update_tasks;
}
public static function getTaskCounter(): int
{
return self::$task_counter;
}
} }

View File

@@ -458,7 +458,7 @@ class PhpHelper
'ssl_default_vhostconf_domain', 'ssl_default_vhostconf_domain',
'filecontent' 'filecontent'
]; ];
if (isset($global) && !empty($global)) { if (!empty($global)) {
$tmp = $global; $tmp = $global;
foreach ($tmp as $index => $value) { foreach ($tmp as $index => $value) {
if (!in_array($index, $ignored_fields)) { if (!in_array($index, $ignored_fields)) {
@@ -516,7 +516,7 @@ class PhpHelper
$str .= self::tabPrefix(($depth-1), "[\n"); $str .= self::tabPrefix(($depth-1), "[\n");
} }
foreach ($array as $key => $value) { foreach ($array as $key => $value) {
if (isset($key) && !is_array($value)) { if (!is_array($value)) {
if (is_bool($value)) { if (is_bool($value)) {
$str .= self::tabPrefix($depth, sprintf("'%s' => %s,\n", $key, $value ? 'true' : 'false')); $str .= self::tabPrefix($depth, sprintf("'%s' => %s,\n", $key, $value ? 'true' : 'false'));
} elseif (is_int($value)) { } elseif (is_int($value)) {

View File

@@ -34,11 +34,11 @@ class Mailer extends PHPMailer
/** /**
* class constructor * class constructor
* *
* @param string $exceptions * @param bool $exceptions
* whether to throw exceptions or not * whether to throw exceptions or not
* *
*/ */
public function __construct($exceptions = false) public function __construct(bool $exceptions = false)
{ {
parent::__construct($exceptions); parent::__construct($exceptions);
$this->CharSet = "UTF-8"; $this->CharSet = "UTF-8";

View File

@@ -66,6 +66,21 @@ class Style
return $attributes['fields']['deactivated'] ? 'bg-info' : $termination_css; return $attributes['fields']['deactivated'] ? 'bg-info' : $termination_css;
} }
public static function resultCustomerLockedOrDeactivated(array $attributes): string
{
$row_css = '';
if ((int)$attributes['fields']['deactivated'] == 1) {
$row_css = 'bg-info';
} elseif (
$attributes['fields']['loginfail_count'] >= Settings::Get('login.maxloginattempts')
&& $attributes['fields']['lastlogin_fail'] > (time() - Settings::Get('login.deactivatetime'))
) {
$row_css = 'bg-warning';
}
return $row_css;
}
public static function diskspaceWarning(array $attributes): string public static function diskspaceWarning(array $attributes): string
{ {
return self::getWarningStyle('diskspace', $attributes['fields'], (int)Settings::Get('system.report_webmax')); return self::getWarningStyle('diskspace', $attributes['fields'], (int)Settings::Get('system.report_webmax'));

View File

@@ -153,7 +153,7 @@ class Linker
} }
// Encode parameters and add them to the link // Encode parameters and add them to the link
$link .= urlencode($key) . (!empty($value) ? '=' . urlencode($value) : ''); $link .= urlencode($key) . ($value !== "" ? '=' . urlencode($value) : '');
} }
// Reset our class for further use // Reset our class for further use

View File

@@ -52,7 +52,7 @@ class Listing
'is_search' => $collection->getPagination() instanceof Pagination && $collection->getPagination()->isSearchResult(), 'is_search' => $collection->getPagination() instanceof Pagination && $collection->getPagination()->isSearchResult(),
'self_overview' => $tabellisting['self_overview'] ?? [], 'self_overview' => $tabellisting['self_overview'] ?? [],
'available_columns' => self::getAvailableColumnsForListing($tabellisting), 'available_columns' => self::getAvailableColumnsForListing($tabellisting),
'listing_search_additional_param' => $listing_search_additional_param ?? [], 'listing_search_additional_param' => $listing_search_additional_param,
]; ];
} }
@@ -60,7 +60,6 @@ class Listing
{ {
return [ return [
'title' => $tabellisting['title'], 'title' => $tabellisting['title'],
'icon' => $tabellisting['icon'],
'description' => $tabellisting['description'] ?? null, 'description' => $tabellisting['description'] ?? null,
'icon' => $tabellisting['icon'] ?? null, 'icon' => $tabellisting['icon'] ?? null,
'table' => [ 'table' => [

View File

@@ -163,11 +163,14 @@ class UI
self::$install_mode = $install_mode; self::$install_mode = $install_mode;
// init twig template engine // init twig template engine
$loader = new FilesystemLoader(Froxlor::getInstallDir() . '/templates/'); $loader = new FilesystemLoader(Froxlor::getInstallDir() . '/templates/');
self::$twig = new Environment($loader, [ $twig_params = [
'debug' => true, 'auto_reload' => true,
'cache' => Froxlor::getInstallDir() . '/cache', 'debug' => false,
'auto_reload' => true ];
]); if (is_writable(Froxlor::getInstallDir() . '/cache')) {
$twig_params['cache'] = Froxlor::getInstallDir() . '/cache';
}
self::$twig = new Environment($loader, $twig_params);
self::$twig->addExtension(new DebugExtension()); self::$twig->addExtension(new DebugExtension());
self::$twig->addExtension(new CustomReflection()); self::$twig->addExtension(new CustomReflection());
self::$twig->addExtension(new FroxlorTwig()); self::$twig->addExtension(new FroxlorTwig());
@@ -279,7 +282,7 @@ class UI
} }
} }
if (!file_exists(Froxlor::getInstallDir() . '/templates/' . $theme)) { if (!file_exists(Froxlor::getInstallDir() . '/templates/' . $theme)) {
PhpHelper::phpErrHandler(E_USER_WARNING, "Theme '" . $theme . "' could not be found.", __FILE__, __LINE__, null); PhpHelper::phpErrHandler(E_USER_WARNING, "Theme '" . $theme . "' could not be found.", __FILE__, __LINE__);
$theme = self::$default_theme; $theme = self::$default_theme;
} }
return $theme; return $theme;

View File

@@ -46,23 +46,19 @@ class Validate
const REGEX_YYYY_MM_DD = '/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/'; const REGEX_YYYY_MM_DD = '/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/';
/** /**
* Validates the given string by matching against the pattern, prints an error on failure and exits * Validates the given string by matching against the pattern, prints an error on failure and exits.
* If the default pattern is used and the string does not match, we try to replace the 'bad' values and log the action.
* *
* @param string $str * @param string $str the string to be tested (user input)
* the string to be tested (user input) * @param string $fieldname to be used in error messages
* @param * @param string $pattern the regular expression to be used for testing
* string the $fieldname to be used in error messages * @param string|array $lng id for the error
* @param string $pattern * @param string|array $emptydefault fallback value
* the regular expression to be used for testing * @param bool $throw_exception whether to display error or throw an exception, default false
* @param
* string language id for the error
* @return string the clean string
*
* If the default pattern is used and the string does not match, we try to replace the
* 'bad' values and log the action.
* *
* @return string|void the clean string or error
*/ */
public static function validate($str, $fieldname, $pattern = '', $lng = '', $emptydefault = [], $throw_exception = false) public static function validate($str, string $fieldname, string $pattern = '', $lng = '', $emptydefault = [], bool $throw_exception = false)
{ {
if (!is_array($emptydefault)) { if (!is_array($emptydefault)) {
$emptydefault_array = [ $emptydefault_array = [
@@ -122,9 +118,9 @@ class Validate
* @param bool $throw_exception * @param bool $throw_exception
* whether to throw an exception on failure * whether to throw an exception on failure
* *
* @return string|bool ip address on success, false on failure * @return string|bool|void ip address on success, false on failure (or nothing if error is displayed)
*/ */
public static function validate_ip2($ip, $return_bool = false, $lng = 'invalidip', $allow_localhost = false, $allow_priv = false, $allow_cidr = false, $cidr_as_netmask = false, $throw_exception = false) public static function validate_ip2($ip, bool $return_bool = false, string $lng = 'invalidip', bool $allow_localhost = false, bool $allow_priv = false, bool $allow_cidr = false, bool $cidr_as_netmask = false, bool $throw_exception = false)
{ {
$cidr = ""; $cidr = "";
if ($allow_cidr) { if ($allow_cidr) {
@@ -136,15 +132,17 @@ class Validate
$cidr_range_max = 128; $cidr_range_max = 128;
} }
if (strlen($ip_cidr[1]) <= 3 && in_array((int)$ip_cidr[1], array_values(range(1, $cidr_range_max)), true) === false) { if (strlen($ip_cidr[1]) <= 3 && in_array((int)$ip_cidr[1], array_values(range(1, $cidr_range_max)), true) === false) {
if ($return_bool) {
return false;
}
Response::standardError($lng, $ip, $throw_exception); Response::standardError($lng, $ip, $throw_exception);
} }
if ($cidr_as_netmask && IPTools::is_ipv6($ip_cidr[0])) { if ($cidr_as_netmask && IPTools::is_ipv6($ip_cidr[0])) {
// MySQL does not handle CIDR of IPv6 addresses, return error // MySQL does not handle CIDR of IPv6 addresses, return error
if ($return_bool) { if ($return_bool) {
return false; return false;
} else {
Response::standardError($lng, $ip, $throw_exception);
} }
Response::standardError($lng, $ip, $throw_exception);
} }
$ip = $ip_cidr[0]; $ip = $ip_cidr[0];
if ($cidr_as_netmask && strlen($ip_cidr[1]) <= 3) { if ($cidr_as_netmask && strlen($ip_cidr[1]) <= 3) {
@@ -157,9 +155,8 @@ class Validate
} elseif (strpos($ip, "/") !== false) { } elseif (strpos($ip, "/") !== false) {
if ($return_bool) { if ($return_bool) {
return false; return false;
} else {
Response::standardError($lng, $ip, $throw_exception);
} }
Response::standardError($lng, $ip, $throw_exception);
} }
$filter_lan = $allow_priv ? FILTER_FLAG_NO_RES_RANGE : (FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE); $filter_lan = $allow_priv ? FILTER_FLAG_NO_RES_RANGE : (FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE);
@@ -175,9 +172,8 @@ class Validate
if ($return_bool) { if ($return_bool) {
return false; return false;
} else {
Response::standardError($lng, $ip, $throw_exception);
} }
Response::standardError($lng, $ip, $throw_exception);
} }
/** /**

View File

@@ -4646,7 +4646,7 @@ aliases: files
</commands> </commands>
<!-- instead of just restarting apache, we let the cronjob do all the <!-- instead of just restarting apache, we let the cronjob do all the
dirty work --> dirty work -->
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command> <command><![CDATA[php {{const.install_dir}}bin/froxlor-cli froxlor:cron --force]]></command>
</daemon> </daemon>
<!-- PHP-FPM --> <!-- PHP-FPM -->
<daemon name="php-fpm" <daemon name="php-fpm"
@@ -4679,12 +4679,12 @@ aliases: files
</commands> </commands>
<!-- instead of just restarting apache, we let the cronjob do all the <!-- instead of just restarting apache, we let the cronjob do all the
dirty work --> dirty work -->
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command> <command><![CDATA[php {{const.install_dir}}bin/froxlor-cli froxlor:cron --force]]></command>
</daemon> </daemon>
<!-- Cronjob --> <!-- Cronjob -->
<daemon name="cron" title="Cronjob for froxlor" <daemon name="cron" title="Cronjob for froxlor"
mandatory="true"> mandatory="true">
<command><![CDATA[/usr/bin/php <BASE_PATH>scripts/froxlor_master_cronjob.php --run-task 99]]></command> <command><![CDATA[/usr/bin/php <BASE_PATH>bin/froxlor-cli froxlor:cron --run-task 99]]></command>
<command><![CDATA[{{settings.system.crondreload}}]]></command> <command><![CDATA[{{settings.system.crondreload}}]]></command>
</daemon> </daemon>
</service> </service>

View File

@@ -4857,7 +4857,7 @@ aliases: files
</commands> </commands>
<!-- instead of just restarting apache, we let the cronjob do all the <!-- instead of just restarting apache, we let the cronjob do all the
dirty work --> dirty work -->
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command> <command><![CDATA[php {{const.install_dir}}bin/froxlor-cli froxlor:cron --force]]></command>
</daemon> </daemon>
<!-- PHP-FPM --> <!-- PHP-FPM -->
<daemon name="php-fpm" <daemon name="php-fpm"
@@ -4890,12 +4890,12 @@ aliases: files
</commands> </commands>
<!-- instead of just restarting apache, we let the cronjob do all the <!-- instead of just restarting apache, we let the cronjob do all the
dirty work --> dirty work -->
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command> <command><![CDATA[php {{const.install_dir}}bin/froxlor-cli froxlor:cron --force]]></command>
</daemon> </daemon>
<!-- Cronjob --> <!-- Cronjob -->
<daemon name="cron" title="Cronjob for froxlor" <daemon name="cron" title="Cronjob for froxlor"
mandatory="true"> mandatory="true">
<command><![CDATA[/usr/bin/php <BASE_PATH>scripts/froxlor_master_cronjob.php --run-task 99]]></command> <command><![CDATA[/usr/bin/php <BASE_PATH>bin/froxlor-cli froxlor:cron --run-task 99]]></command>
<command><![CDATA[{{settings.system.crondreload}}]]></command> <command><![CDATA[{{settings.system.crondreload}}]]></command>
</daemon> </daemon>
</service> </service>

View File

@@ -4848,7 +4848,7 @@ aliases: files
</commands> </commands>
<!-- instead of just restarting apache, we let the cronjob do all the <!-- instead of just restarting apache, we let the cronjob do all the
dirty work --> dirty work -->
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command> <command><![CDATA[php {{const.install_dir}}bin/froxlor-cli froxlor:cron --force]]></command>
</daemon> </daemon>
<!-- PHP-FPM --> <!-- PHP-FPM -->
<daemon name="php-fpm" <daemon name="php-fpm"
@@ -4881,12 +4881,12 @@ aliases: files
</commands> </commands>
<!-- instead of just restarting apache, we let the cronjob do all the <!-- instead of just restarting apache, we let the cronjob do all the
dirty work --> dirty work -->
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command> <command><![CDATA[php {{const.install_dir}}bin/froxlor-cli froxlor:cron --force]]></command>
</daemon> </daemon>
<!-- Cronjob --> <!-- Cronjob -->
<daemon name="cron" title="Cronjob for froxlor" <daemon name="cron" title="Cronjob for froxlor"
mandatory="true"> mandatory="true">
<command><![CDATA[/usr/bin/php <BASE_PATH>scripts/froxlor_master_cronjob.php --run-task 99]]></command> <command><![CDATA[/usr/bin/php <BASE_PATH>bin/froxlor-cli froxlor:cron --run-task 99]]></command>
<command><![CDATA[{{settings.system.crondreload}}]]></command> <command><![CDATA[{{settings.system.crondreload}}]]></command>
</daemon> </daemon>
</service> </service>

View File

@@ -4071,7 +4071,7 @@ aliases: files
</commands> </commands>
<!-- instead of just restarting apache, we let the cronjob do all the <!-- instead of just restarting apache, we let the cronjob do all the
dirty work --> dirty work -->
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command> <command><![CDATA[php {{const.install_dir}}bin/froxlor-cli froxlor:cron --force]]></command>
</daemon> </daemon>
<!-- PHP-FPM --> <!-- PHP-FPM -->
<daemon name="php-fpm" <daemon name="php-fpm"
@@ -4104,12 +4104,12 @@ aliases: files
</commands> </commands>
<!-- instead of just restarting apache, we let the cronjob do all the <!-- instead of just restarting apache, we let the cronjob do all the
dirty work --> dirty work -->
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command> <command><![CDATA[php {{const.install_dir}}bin/froxlor-cli froxlor:cron --force]]></command>
</daemon> </daemon>
<!-- Cronjob --> <!-- Cronjob -->
<daemon name="cron" title="Cronjob for froxlor" <daemon name="cron" title="Cronjob for froxlor"
mandatory="true"> mandatory="true">
<command><![CDATA[/usr/bin/php <BASE_PATH>scripts/froxlor_master_cronjob.php --run-task 99]]></command> <command><![CDATA[/usr/bin/php <BASE_PATH>bin/froxlor-cli froxlor:cron --run-task 99]]></command>
<command><![CDATA[{{settings.system.crondreload}}]]></command> <command><![CDATA[{{settings.system.crondreload}}]]></command>
</daemon> </daemon>
</service> </service>

View File

@@ -3859,7 +3859,7 @@ aliases: files
</commands> </commands>
<!-- instead of just restarting apache, we let the cronjob do all the <!-- instead of just restarting apache, we let the cronjob do all the
dirty work --> dirty work -->
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command> <command><![CDATA[php {{const.install_dir}}bin/froxlor-cli froxlor:cron --force]]></command>
</daemon> </daemon>
<!-- PHP-FPM --> <!-- PHP-FPM -->
<daemon name="php-fpm" <daemon name="php-fpm"
@@ -3903,12 +3903,12 @@ aliases: files
</commands> </commands>
<!-- instead of just restarting apache, we let the cronjob do all the <!-- instead of just restarting apache, we let the cronjob do all the
dirty work --> dirty work -->
<command><![CDATA[php {{const.install_dir}}scripts/froxlor_master_cronjob.php --force]]></command> <command><![CDATA[php {{const.install_dir}}bin/froxlor-cli froxlor:cron --force]]></command>
</daemon> </daemon>
<!-- Cronjob --> <!-- Cronjob -->
<daemon name="cron" title="Cronjob for froxlor" <daemon name="cron" title="Cronjob for froxlor"
mandatory="true"> mandatory="true">
<command><![CDATA[/usr/bin/php <BASE_PATH>scripts/froxlor_master_cronjob.php --run-task 99]]></command> <command><![CDATA[/usr/bin/php <BASE_PATH>bin/froxlor-cli froxlor:cron --run-task 99]]></command>
<command><![CDATA[{{settings.system.crondreload}}]]></command> <command><![CDATA[{{settings.system.crondreload}}]]></command>
</daemon> </daemon>
</service> </service>

View File

@@ -195,49 +195,49 @@ return [
'diskspace' => [ 'diskspace' => [
'label' => lng('customer.diskspace') . ' (' . lng('customer.mib') . ')', 'label' => lng('customer.diskspace') . ' (' . lng('customer.mib') . ')',
'type' => 'textul', 'type' => 'textul',
'value' => $result['diskspace'], 'value' => empty($result['diskspace']) ? '0' : $result['diskspace'],
'maxlength' => 16, 'maxlength' => 16,
'mandatory' => true 'mandatory' => true
], ],
'traffic' => [ 'traffic' => [
'label' => lng('customer.traffic') . ' (' . lng('customer.gib') . ')', 'label' => lng('customer.traffic') . ' (' . lng('customer.gib') . ')',
'type' => 'textul', 'type' => 'textul',
'value' => $result['traffic'], 'value' => empty($result['traffic']) ? '0' : $result['traffic'],
'maxlength' => 14, 'maxlength' => 14,
'mandatory' => true 'mandatory' => true
], ],
'subdomains' => [ 'subdomains' => [
'label' => lng('customer.subdomains'), 'label' => lng('customer.subdomains'),
'type' => 'textul', 'type' => 'textul',
'value' => $result['subdomains'], 'value' => empty($result['subdomains']) ? '0' : $result['subdomains'],
'maxlength' => 9, 'maxlength' => 9,
'mandatory' => true 'mandatory' => true
], ],
'emails' => [ 'emails' => [
'label' => lng('customer.emails'), 'label' => lng('customer.emails'),
'type' => 'textul', 'type' => 'textul',
'value' => $result['emails'], 'value' => empty($result['emails']) ? '0' : $result['emails'],
'maxlength' => 9, 'maxlength' => 9,
'mandatory' => true 'mandatory' => true
], ],
'email_accounts' => [ 'email_accounts' => [
'label' => lng('customer.accounts'), 'label' => lng('customer.accounts'),
'type' => 'textul', 'type' => 'textul',
'value' => $result['email_accounts'], 'value' => empty($result['email_accounts']) ? '0' : $result['email_accounts'],
'maxlength' => 9, 'maxlength' => 9,
'mandatory' => true 'mandatory' => true
], ],
'email_forwarders' => [ 'email_forwarders' => [
'label' => lng('customer.forwarders'), 'label' => lng('customer.forwarders'),
'type' => 'textul', 'type' => 'textul',
'value' => $result['email_forwarders'], 'value' => empty($result['email_forwarders']) ? '0' : $result['email_forwarders'],
'maxlength' => 9, 'maxlength' => 9,
'mandatory' => true 'mandatory' => true
], ],
'email_quota' => [ 'email_quota' => [
'label' => lng('customer.email_quota') . ' (' . lng('customer.mib') . ')', 'label' => lng('customer.email_quota') . ' (' . lng('customer.mib') . ')',
'type' => 'textul', 'type' => 'textul',
'value' => $result['email_quota'], 'value' => empty($result['email_quota']) ? '0' : $result['email_quota'],
'maxlength' => 9, 'maxlength' => 9,
'visible' => Settings::Get('system.mail_quota_enabled') == '1', 'visible' => Settings::Get('system.mail_quota_enabled') == '1',
'mandatory' => true 'mandatory' => true
@@ -259,13 +259,14 @@ return [
'ftps' => [ 'ftps' => [
'label' => lng('customer.ftps'), 'label' => lng('customer.ftps'),
'type' => 'textul', 'type' => 'textul',
'value' => $result['ftps'], 'value' => empty($result['ftps']) ? '0' : $result['ftps'],
'maxlength' => 9 'maxlength' => 9,
'mandatory' => true
], ],
'mysqls' => [ 'mysqls' => [
'label' => lng('customer.mysqls'), 'label' => lng('customer.mysqls'),
'type' => 'textul', 'type' => 'textul',
'value' => $result['mysqls'], 'value' => empty($result['mysql']) ? '0' : $result['mysqls'],
'maxlength' => 9, 'maxlength' => 9,
'mandatory' => true 'mandatory' => true
], ],

View File

@@ -220,16 +220,22 @@ return [
'system' => [ 'system' => [
'label' => lng('install.install.runcmd'), 'label' => lng('install.install.runcmd'),
'type' => 'textarea', 'type' => 'textarea',
'value' => !empty($_SESSION['installation']['json_params']) ? Froxlor::getInstallDir() . "bin/froxlor-cli froxlor:config-services -a '" . $_SESSION['installation']['json_params'] . "' --yes-to-all" : "something went wrong...", 'value' => (!empty($_SESSION['installation']['ud_str']) ? Froxlor::getInstallDir() . "bin/froxlor-cli froxlor:install -c '" . $_SESSION['installation']['ud_str'] . "'\n" : "") .
(!empty($_SESSION['installation']['json_params']) ? Froxlor::getInstallDir() . "bin/froxlor-cli froxlor:config-services -a '" . $_SESSION['installation']['json_params'] . "' --yes-to-all" : "something went wrong..."),
'readonly' => true, 'readonly' => true,
'rows' => 3 'rows' => 10,
'style' => 'min-height:16rem;'
], ],
'manual_config' => [ 'manual_config' => [
'label' => lng('install.install.manual_config'), 'label' => lng('install.install.manual_config'),
'type' => 'checkbox', 'type' => 'checkbox',
'value' => '1', 'value' => '1',
'checked' => old('manual_config', '0', 'installation'), 'checked' => old('manual_config', '0', 'installation'),
] ],
'target_servername' => [
'type' => 'hidden',
'value' => $_SESSION['installation']['servername'] ?? "",
],
] ]
] ]
] ]

View File

@@ -62,6 +62,7 @@ use Froxlor\UI\Linker;
use Froxlor\UI\Panel\UI; use Froxlor\UI\Panel\UI;
use Froxlor\UI\Request; use Froxlor\UI\Request;
use Froxlor\UI\Response; use Froxlor\UI\Response;
use Froxlor\Install\Update;
// include MySQL-tabledefinitions // include MySQL-tabledefinitions
require Froxlor::getInstallDir() . '/lib/tables.inc.php'; require Froxlor::getInstallDir() . '/lib/tables.inc.php';
@@ -153,14 +154,15 @@ UI::setLinker($linker);
/** /**
* Global Theme-variable * Global Theme-variable
*/ */
if (Update::versionInUpdate(Settings::Get('panel.version'), '0.11.0-dev1')) {
$theme = $_deftheme;
} else {
$theme = (Settings::Get('panel.default_theme') !== null) ? Settings::Get('panel.default_theme') : $_deftheme; $theme = (Settings::Get('panel.default_theme') !== null) ? Settings::Get('panel.default_theme') : $_deftheme;
// Overwrite with customer/admin theme if defined
/**
* Overwrite with customer/admin theme if defined
*/
if (CurrentUser::hasSession() && CurrentUser::getField('theme') != $theme) { if (CurrentUser::hasSession() && CurrentUser::getField('theme') != $theme) {
$theme = CurrentUser::getField('theme'); $theme = CurrentUser::getField('theme');
} }
}
// Check if a different variant of the theme is used // Check if a different variant of the theme is used
$themevariant = "default"; $themevariant = "default";
@@ -221,7 +223,7 @@ if (!CurrentUser::hasSession() && AREA != 'login') {
} }
$userinfo = CurrentUser::getData(); $userinfo = CurrentUser::getData();
UI::twig()->addGlobal('userinfo', ($userinfo ?? [])); UI::twig()->addGlobal('userinfo', $userinfo);
UI::setCurrentUser($userinfo); UI::setCurrentUser($userinfo);
// Initialize logger // Initialize logger
if (CurrentUser::hasSession()) { if (CurrentUser::hasSession()) {

View File

@@ -27,6 +27,7 @@ use Froxlor\UI\Callbacks\Customer;
use Froxlor\UI\Callbacks\Impersonate; use Froxlor\UI\Callbacks\Impersonate;
use Froxlor\UI\Callbacks\ProgressBar; use Froxlor\UI\Callbacks\ProgressBar;
use Froxlor\UI\Callbacks\Text; use Froxlor\UI\Callbacks\Text;
use Froxlor\UI\Callbacks\Style;
use Froxlor\UI\Listing; use Froxlor\UI\Listing;
return [ return [
@@ -155,7 +156,7 @@ return [
'unlock' => [ 'unlock' => [
'icon' => 'fa fa-unlock', 'icon' => 'fa fa-unlock',
'title' => lng('panel.unlock'), 'title' => lng('panel.unlock'),
'class' => 'text-warning', 'class' => 'btn-outline-secondary',
'href' => [ 'href' => [
'section' => 'customers', 'section' => 'customers',
'page' => 'customers', 'page' => 'customers',
@@ -186,5 +187,8 @@ return [
], ],
], ],
], ],
'format_callback' => [
[Style::class, 'resultCustomerLockedOrDeactivated']
]
] ]
]; ];

View File

@@ -1559,12 +1559,6 @@ Vielen Dank, Ihr Administrator',
'title' => 'Erlaube Verschieben von Domains unter Kunden', 'title' => 'Erlaube Verschieben von Domains unter Kunden',
'description' => 'Wenn diese Option aktiviert ist, kann unter Domaineinstellungen die Domain einem anderen Kunden zugewiesen werden.<br /><b>Achtung:</b> Der Dokumenten-Pfad der Domain wird auf den Heimatpfad (+ Domain-Ordner, sofern aktiviert) des neuen Kunden gesetzt.', 'description' => 'Wenn diese Option aktiviert ist, kann unter Domaineinstellungen die Domain einem anderen Kunden zugewiesen werden.<br /><b>Achtung:</b> Der Dokumenten-Pfad der Domain wird auf den Heimatpfad (+ Domain-Ordner, sofern aktiviert) des neuen Kunden gesetzt.',
], ],
'cron' => [
'debug' => [
'title' => 'Debuggen des Cronscripts',
'description' => 'Wenn aktiviert, wird die Lockdatei nach dem Cronlauf zum Debuggen nicht gelöscht<br /><b>Achtung:</b> Eine alte Lockdatei kann weitere Cronjobs behindern und dafür sorgen, dass diese nicht vollständig ausgeführt werden.',
],
],
'specialsettingsforsubdomains' => [ 'specialsettingsforsubdomains' => [
'description' => 'Wenn ja, werden die individuellen Einstellungen für alle Subdomains übernommen.<br />Wenn nein, werden Subdomain-Specialsettings entfernt.', 'description' => 'Wenn ja, werden die individuellen Einstellungen für alle Subdomains übernommen.<br />Wenn nein, werden Subdomain-Specialsettings entfernt.',
], ],
@@ -2175,6 +2169,7 @@ Vielen Dank, Ihr Administrator',
'description' => 'Der untenstehende Befehl lädt, installiert und konfiguriert die benötigten Dienste auf dem System aufgrund der Angaben die während des Installationsprozessen gesammelt wurden.', 'description' => 'Der untenstehende Befehl lädt, installiert und konfiguriert die benötigten Dienste auf dem System aufgrund der Angaben die während des Installationsprozessen gesammelt wurden.',
'runcmd' => 'Folgenden Befehl als root-Benutzer in der Shell auf dem Server ausführen:', 'runcmd' => 'Folgenden Befehl als root-Benutzer in der Shell auf dem Server ausführen:',
'manual_config' => 'Ich werden die Dienste manuell konfigurieren, direkt zum Login umleiten', 'manual_config' => 'Ich werden die Dienste manuell konfigurieren, direkt zum Login umleiten',
'waitforconfig' => 'Warte auf Abschluss der Dienstkonfiguration...',
], ],
'errors' => [ 'errors' => [
'wrong_ownership' => 'Die froxlor Dateien gehören nicht vollständig dem Benutzer %s:%s', 'wrong_ownership' => 'Die froxlor Dateien gehören nicht vollständig dem Benutzer %s:%s',

View File

@@ -1935,12 +1935,6 @@ Yours sincerely, your administrator',
'title' => 'Allow moving domains between customers', 'title' => 'Allow moving domains between customers',
'description' => 'If activated you can change the customer of a domain at domainsettings.<br /><b>Attention:</b> Froxlor changes the documentroot to the new customer\'s default homedir (+ domain-folder if activated)', 'description' => 'If activated you can change the customer of a domain at domainsettings.<br /><b>Attention:</b> Froxlor changes the documentroot to the new customer\'s default homedir (+ domain-folder if activated)',
], ],
'cron' => [
'debug' => [
'title' => 'Cronscript debugging',
'description' => 'Activate to keep the lockfile after a cron-run for debugging.<br /><b>Attention:</b>Keeping the lockfile can cause the next scheduled cron not to run properly.',
],
],
'specialsettingsforsubdomains' => [ 'specialsettingsforsubdomains' => [
'description' => 'If yes these custom vHost-settings will be added to all subdomains; if no subdomain-specialsettings are being removed.', 'description' => 'If yes these custom vHost-settings will be added to all subdomains; if no subdomain-specialsettings are being removed.',
], ],
@@ -2561,6 +2555,7 @@ Yours sincerely, your administrator',
'description' => 'The command below will download, install and configure required services on your system according to the data you have given in this installation process.', 'description' => 'The command below will download, install and configure required services on your system according to the data you have given in this installation process.',
'runcmd' => 'Run the following command as root-user in your shell on this server:', 'runcmd' => 'Run the following command as root-user in your shell on this server:',
'manual_config' => 'I will manually configure the services, just take me to the login', 'manual_config' => 'I will manually configure the services, just take me to the login',
'waitforconfig' => 'Waiting for services to be configured...',
], ],
'errors' => [ 'errors' => [
'wrong_ownership' => 'Make sure the froxlor files are owned by %s:%s', 'wrong_ownership' => 'Make sure the froxlor files are owned by %s:%s',

View File

@@ -1,34 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can also view it online at
* https://files.froxlor.org/misc/COPYING.txt
*
* @copyright the authors
* @author Froxlor team <team@froxlor.org>
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
*/
// validate correct php version
if (version_compare("7.4.0", PHP_VERSION, ">=")) {
die('Froxlor requires at least php-7.4. Please validate that your php-cli version and the cron execution command are correct.');
}
require dirname(__DIR__) . '/vendor/autoload.php';
\Froxlor\Cron\MasterCron::setArguments($argv);
\Froxlor\Cron\MasterCron::run();

View File

View File

@@ -201,7 +201,7 @@
{% endmacro %} {% endmacro %}
{% macro textarea(id, field) %} {% macro textarea(id, field) %}
<textarea {% if field.visible is defined and field.visible == false %} disabled {% endif %} rows="{{ field.rows|default('12') }}" cols="{{ field.cols|default('60') }}" id="{{ id }}" name="{{ id }}" class="form-control {% if field.valid is defined and field.valid == false %}is-invalid{% endif %}" {% if field.mandatory is defined and field.mandatory %} required {% endif %} {% if field.readonly is defined and field.readonly %} readonly {% endif %} {% if field.placeholder is defined %} placeholder="{{ field.placeholder }}" {% endif %}>{{ field.value }}</textarea> <textarea {% if field.visible is defined and field.visible == false %} disabled {% endif %} rows="{{ field.rows|default('12') }}" cols="{{ field.cols|default('60') }}" id="{{ id }}" name="{{ id }}" class="form-control {% if field.valid is defined and field.valid == false %}is-invalid{% endif %}" {% if field.mandatory is defined and field.mandatory %} required {% endif %} {% if field.readonly is defined and field.readonly %} readonly {% endif %} {% if field.placeholder is defined %} placeholder="{{ field.placeholder }}" {% endif %} {% if field.style is defined %} style="{{ field.style }}" {% endif %}>{{ field.value }}</textarea>
{% endmacro %} {% endmacro %}
{% macro link(id, field) %} {% macro link(id, field) %}

View File

@@ -60,7 +60,8 @@
<a href="?step={{ setup.step - 1 }}" class="btn btn-secondary">&laquo; {{ lng('panel.back') }}</a> <a href="?step={{ setup.step - 1 }}" class="btn btn-secondary">&laquo; {{ lng('panel.back') }}</a>
<button type="submit" name="submit" class="btn btn-primary">{{ lng('panel.next') }} &raquo;</button> <button type="submit" name="submit" class="btn btn-primary">{{ lng('panel.next') }} &raquo;</button>
{% else %} {% else %}
<button type="submit" name="submit" class="btn btn-success">{{ lng('install.install.top') }} &raquo;</button> <span id="submitAuto"><i class="fas fa-spinner fa-pulse"></i> {{ lng('install.install.waitforconfig') }}</span>
<button id="submitManual" type="submit" name="submit" class="btn btn-success d-none">{{ lng('install.install.top') }} &raquo;</button>
{% endif %} {% endif %}
</div> </div>
{% else %} {% else %}

View File

@@ -11,7 +11,7 @@
<pre>chown -R {{ user }}:{{ group }} {{ installdir }}</pre> <pre>chown -R {{ user }}:{{ group }} {{ installdir }}</pre>
<hr> <hr>
<p class="mt-1 text-center"> <p class="mt-1 text-center">
<a href="./install/install.php" class="btn btn-primary" title="Click to start the install process">Start install</a> <a href="" class="btn btn-primary" title="Reload page">Reload</a>
</p> </p>
</div> </div>
</div> </div>

View File

@@ -4,7 +4,7 @@ $(function () {
*/ */
$('#switchInstallMode').on('click', function () { $('#switchInstallMode').on('click', function () {
var checked = $(this).prop('checked'); var checked = $(this).prop('checked');
window.location = '/install/install.php' + replaceQueryParam('extended', +checked, window.location.search); window.location = window.location.pathname + replaceQueryParam('extended', +checked, window.location.search);
}); });
function replaceQueryParam(param, newval, search) { function replaceQueryParam(param, newval, search) {
@@ -14,4 +14,49 @@ $(function () {
} }
return search + '&' + param + '=' + newval; return search + '&' + param + '=' + newval;
} }
function checkConfigState() {
$.ajax({
url: window.location.href,
type: "GET",
success: function (data, textStatus, request) {
if (request.status >= 300) {
window.location = "http://" + srvName;
}
},
error: function (request, textStatus, errorThrown) {
// continue
if (request.status >= 300) {
window.location = "http://" + srvName;
}
}
});
}
var cTimer;
/**
* check manual-config switch
*/
$('#manual_config').on('click', function () {
clearInterval(cTimer);
var checked = $(this).prop('checked');
if (checked) {
// button zum login
$('#submitAuto').addClass('d-none');
$('#submitManual').removeClass('d-none');
} else {
cTimer = setInterval(checkConfigState, 1000);
// spinner fürs warten
$('#submitAuto').removeClass('d-none');
$('#submitManual').addClass('d-none');
}
});
if ($('#manual_config').length > 0) {
var srvName = $('#target_servername').val();
clearInterval(cTimer);
cTimer = setInterval(checkConfigState, 1000);
}
}); });