Skip to content

Commit

Permalink
check php-extension requirements not only on installation (e.g. when …
Browse files Browse the repository at this point in the history
…php version was changed)

Signed-off-by: Michael Kaufmann <[email protected]>
  • Loading branch information
d00p committed Nov 26, 2023
1 parent b13b1e8 commit 4f79d7c
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 22 deletions.
39 changes: 17 additions & 22 deletions lib/Froxlor/Install/Install.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@
namespace Froxlor\Install;

use Exception;
use PDO;
use Froxlor\Config\ConfigParser;
use Froxlor\Install\Install\Core;
use Froxlor\System\IPTools;
use Froxlor\UI\Panel\UI;
use Froxlor\UI\Request;
use Froxlor\Config\ConfigParser;
use Froxlor\Validate\Validate;
use Froxlor\System\IPTools;
use PDO;

class Install
{
Expand All @@ -41,9 +41,6 @@ class Install
public $maxSteps;
public $phpVersion;
public $formfield;
public string $requiredVersion = '7.4.0';
public array $requiredExtensions = ['session', 'ctype', 'xml', 'filter', 'posix', 'mbstring', 'curl', 'gmp', 'json', 'gd'];
public array $suggestedExtensions = ['bcmath', 'zip', 'gnupg'];
public array $suggestions = [];
public array $criticals = [];
public array $loadedExtensions;
Expand Down Expand Up @@ -99,7 +96,7 @@ public function __construct(array $cliData = [])
}

// check for url manipulation or wrong step
if ((isset($_SESSION['installation']['stepCompleted']) && ($this->currentStep + 1) > ($_SESSION['installation']['stepCompleted'] ?? 0))
if ((isset($_SESSION['installation']['stepCompleted']) && ($this->currentStep + 1) > $_SESSION['installation']['stepCompleted'])
|| (!isset($_SESSION['installation']['stepCompleted']) && $this->currentStep > 0)
) {
$this->currentStep = isset($_SESSION['installation']['stepCompleted']) ? $_SESSION['installation']['stepCompleted'] + 1 : 1;
Expand Down Expand Up @@ -151,16 +148,14 @@ private function handleFormData(array $formfield): void
if ($this->currentStep <= $this->maxSteps) {
// Validate user data
$validatedData = $this->validateRequest($formfield['sections']['step' . $this->currentStep]['fields']);
// Check database connection (
if ($this->currentStep == 1) {
// Check database connection
$this->checkDatabase($validatedData);
}
// Check validity of admin user data
elseif ($this->currentStep == 2) {
} elseif ($this->currentStep == 2) {
// Check validity of admin user data
$this->checkAdminUser($validatedData);
}
// Check validity of system data
elseif ($this->currentStep == 3) {
} elseif ($this->currentStep == 3) {
// Check validity of system data
$this->checkSystem($validatedData);
}
$validatedData['stepCompleted'] = ($this->currentStep < $this->maxSteps) ? $this->currentStep : ($this->maxSteps - 1);
Expand Down Expand Up @@ -192,15 +187,15 @@ private function handleFormData(array $formfield): void
private function checkInstallStateFinished(): bool
{
$core = new Core($_SESSION['installation']);
if (isset($_SESSION['installation']['manual_config']) && (int) $_SESSION['installation']['manual_config'] == 1) {
if (isset($_SESSION['installation']['manual_config']) && (int)$_SESSION['installation']['manual_config'] == 1) {
$core->createUserdataConf();
return true;
}
$pdo = $core->getUnprivilegedPdo();
$stmt = $pdo->prepare("SELECT `value` FROM `panel_settings` WHERE `settinggroup` = 'panel' AND `varname` = 'is_configured'");
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if ($result && (int) $result['value'] == 1) {
if ($result && (int)$result['value'] == 1) {
$core->createUserdataConf();
return true;
}
Expand All @@ -223,15 +218,15 @@ public function checkRequirements(): array
}

// check for required extensions
foreach ($this->requiredExtensions as $requiredExtension) {
foreach (Requirements::REQUIRED_EXTENSIONS as $requiredExtension) {
if (in_array($requiredExtension, $this->loadedExtensions)) {
continue;
}
$this->criticals['missing_extensions'][] = $requiredExtension;
}

// check for suggested extensions
foreach ($this->suggestedExtensions as $suggestedExtension) {
foreach (Requirements::SUGGESTED_EXTENSIONS as $suggestedExtension) {
if (in_array($suggestedExtension, $this->loadedExtensions)) {
continue;
}
Expand All @@ -250,11 +245,11 @@ public function checkRequirements(): array
*/
private function getInformationText(): string
{
if (version_compare($this->requiredVersion, PHP_VERSION, "<")) {
if (version_compare(Requirements::REQUIRED_VERSION, PHP_VERSION, "<")) {
$text = lng('install.phpinfosuccess', [$this->phpVersion]);
} else {
$text = lng('install.phpinfowarn', [$this->requiredVersion]);
$this->criticals[] = lng('install.phpinfoupdate', [$this->phpVersion, $this->requiredVersion]);
$text = lng('install.phpinfowarn', [Requirements::REQUIRED_VERSION]);
$this->criticals[] = lng('install.phpinfoupdate', [$this->phpVersion, Requirements::REQUIRED_VERSION]);
}
return $text;
}
Expand Down Expand Up @@ -302,7 +297,7 @@ public function checkSystem(array $validatedData): void
throw new Exception(lng('install.errors.nov4andnov6ip'));
} elseif (!empty($serveripv4) && (!Validate::validate_ip2($serveripv4, true, '', false, true) || IPTools::is_ipv6($serveripv4))) {
throw new Exception(lng('error.invalidip', [$serveripv4]));
} elseif (!empty($serveripv6) && (!Validate::validate_ip2($serveripv6, true, '', false, true) || IPTools::is_ipv6($serveripv6) == false)) {
} elseif (!empty($serveripv6) && (!Validate::validate_ip2($serveripv6, true, '', false, true) || !IPTools::is_ipv6($serveripv6))) {
throw new Exception(lng('error.invalidip', [$serveripv6]));
} elseif (!Validate::validateDomain($servername)) {
throw new Exception(lng('install.errors.servernameneedstobevalid'));
Expand Down
10 changes: 10 additions & 0 deletions lib/Froxlor/Install/Requirements.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Froxlor\Install;

class Requirements
{
const REQUIRED_VERSION = '7.4.0';
const REQUIRED_EXTENSIONS = ['session', 'ctype', 'xml', 'filter', 'posix', 'mbstring', 'curl', 'gmp', 'json', 'gd'];
const SUGGESTED_EXTENSIONS = ['bcmath', 'zip', 'gnupg'];
}
19 changes: 19 additions & 0 deletions lib/init.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
use Froxlor\UI\Panel\UI;
use Froxlor\UI\Request;
use Froxlor\UI\Response;
use Froxlor\Install\Requirements;

// include MySQL-tabledefinitions
require Froxlor::getInstallDir() . '/lib/tables.inc.php';
Expand Down Expand Up @@ -126,6 +127,24 @@
die();
}

// validate php-extensions requirements
$loadedExtensions = get_loaded_extensions();
$missingExtensions = [];
foreach (Requirements::REQUIRED_EXTENSIONS as $requiredExtension) {
if (in_array($requiredExtension, $loadedExtensions)) {
continue;
}
$missingExtensions[] = $requiredExtension;
}
if (!empty($missingExtensions)) {
UI::twig()->addGlobal('install_mode', '1');
echo UI::twig()->render($_deftheme . '/misc/missingextensionhint.html.twig', [
'phpversion' => phpversion(),
'missing_extensions' => implode(", ", $missingExtensions),
]);
die();
}

// set error-handler
@set_error_handler([
'\\Froxlor\\PhpHelper',
Expand Down
18 changes: 18 additions & 0 deletions templates/Froxlor/misc/missingextensionhint.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{% extends "Froxlor/base.html.twig" %}

{% block content %}
<div class="container my-auto">
<div class="alert alert-warning fade show" role="alert">
<h4 class="alert-heading">
Whoops!
</h4>
<p>It looks like you are missing some of the required php requirements.</p>
<p>Please ensure that the following extension for the currently used php version ({{ phpversion }}) are installed:</p>
<pre>{{ missing_extensions }}</pre>
<hr>
<p class="mt-1 text-center">
<a href="" class="btn btn-primary" title="Reload page">Reload</a>
</p>
</div>
</div>
{% endblock %}

0 comments on commit 4f79d7c

Please sign in to comment.