You've already forked Atomcms-edit
b1739cabbf
- SystemFixService: removed ALL shell_exec/sudo calls (30+ instances), replaced with safe PHP alternatives (mkdir, chmod, disk_total_space, Artisan calls) - InstallationController: added ALLOWED_SETTINGS whitelist to prevent arbitrary settings manipulation via request data - ExceptionHandler: removed dangerous npm run build execution and hardcoded chown/chmod paths from auto-recovery - AuthController: fixed user enumeration timing attack by running Hash::make() even when user doesn't exist (constant-time comparison) - DDoSDetectionCommand: added IP validation (FILTER_VALIDATE_IP) before blocking to prevent iptables manipulation with spoofed/malicious IPs - trackRequest: now validates IP before storing in cache
200 lines
7.2 KiB
PHP
Executable File
200 lines
7.2 KiB
PHP
Executable File
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use Illuminate\Support\Facades\Artisan;
|
|
|
|
class SystemFixService
|
|
{
|
|
private array $results = [];
|
|
|
|
public function checkAndFixAll(): array
|
|
{
|
|
$this->results = [];
|
|
|
|
$this->checkPhpExtensions();
|
|
$this->checkDatabase();
|
|
$this->fixPermissions();
|
|
$this->checkDiskSpace();
|
|
$this->clearOldCaches();
|
|
|
|
return $this->results;
|
|
}
|
|
|
|
private function checkPhpExtensions(): void
|
|
{
|
|
$requiredExtensions = ['pdo_mysql', 'curl', 'json', 'mbstring', 'xml', 'zip', 'bcmath'];
|
|
$missing = [];
|
|
|
|
foreach ($requiredExtensions as $ext) {
|
|
if (! extension_loaded($ext)) {
|
|
$missing[] = $ext;
|
|
}
|
|
}
|
|
|
|
if ($missing === []) {
|
|
$this->results[] = ['item' => 'PHP Extensions', 'status' => 'ok', 'message' => 'Alle vereiste extensies geïnstalleerd'];
|
|
} else {
|
|
$this->results[] = ['item' => 'PHP Extensions', 'status' => 'warning', 'message' => 'Ontbrekend: ' . implode(', ', $missing) . ' — installeer via: sudo apt install php-' . implode(' php-', $missing)];
|
|
}
|
|
}
|
|
|
|
private function checkDatabase(): void
|
|
{
|
|
try {
|
|
$host = setting('emulator_database_host', '127.0.0.1');
|
|
$port = setting('emulator_database_port', '3306');
|
|
$name = setting('emulator_database_name', config('database.connections.mysql.database', ''));
|
|
$username = setting('emulator_database_username', config('database.connections.mysql.username', ''));
|
|
$password = setting('emulator_database_password', config('database.connections.mysql.password', ''));
|
|
|
|
if (empty($name) || empty($username)) {
|
|
$this->results[] = ['item' => 'Emulator Database', 'status' => 'warning', 'message' => 'Niet geconfigureerd'];
|
|
$this->autoFixEmulatorDatabase();
|
|
|
|
return;
|
|
}
|
|
|
|
$validationErrors = $this->validateDatabaseInputs($host, $port, $name, $username);
|
|
if ($validationErrors !== []) {
|
|
$this->results[] = ['item' => 'Emulator Database', 'status' => 'error', 'message' => implode(', ', $validationErrors)];
|
|
|
|
return;
|
|
}
|
|
|
|
try {
|
|
$pdo = new \PDO(
|
|
"mysql:host={$host};port={$port};charset=utf8mb4",
|
|
$username,
|
|
$password,
|
|
[\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, \PDO::ATTR_TIMEOUT => 5],
|
|
);
|
|
|
|
$pdo->exec("USE `{$name}`");
|
|
$pdo->query('SELECT 1');
|
|
$this->results[] = ['item' => 'Emulator Database', 'status' => 'ok', 'message' => "Verbonden met {$name}"];
|
|
} catch (\PDOException $e) {
|
|
$this->results[] = ['item' => 'Emulator Database', 'status' => 'error', 'message' => $e->getMessage()];
|
|
}
|
|
} catch (\Exception $e) {
|
|
$this->results[] = ['item' => 'Emulator Database', 'status' => 'error', 'message' => $e->getMessage()];
|
|
}
|
|
}
|
|
|
|
private function validateDatabaseInputs(string $host, string $port, string $name, string $username): array
|
|
{
|
|
$errors = [];
|
|
|
|
if ($host === '' || $host === '0') {
|
|
$errors[] = 'Host is leeg';
|
|
} elseif (! filter_var($host, FILTER_VALIDATE_IP) && ! preg_match('/^[a-zA-Z0-9.-]+$/', $host)) {
|
|
$errors[] = 'Ongeldige host';
|
|
}
|
|
|
|
if ($port === '' || $port === '0') {
|
|
$errors[] = 'Port is leeg';
|
|
} elseif (! is_numeric($port) || $port < 1 || $port > 65535) {
|
|
$errors[] = 'Ongeldige port';
|
|
}
|
|
|
|
if ($name === '' || $name === '0') {
|
|
$errors[] = 'Database naam is leeg';
|
|
} elseif (! preg_match('/^\w+$/', $name)) {
|
|
$errors[] = 'Ongeldige database naam';
|
|
}
|
|
|
|
if ($username === '' || $username === '0') {
|
|
$errors[] = 'Gebruikersnaam is leeg';
|
|
} elseif (! preg_match('/^\w+$/', $username)) {
|
|
$errors[] = 'Ongeldige gebruikersnaam';
|
|
}
|
|
|
|
return $errors;
|
|
}
|
|
|
|
private function autoFixEmulatorDatabase(): void
|
|
{
|
|
$host = config('database.connections.mysql.host', '127.0.0.1');
|
|
$port = config('database.connections.mysql.port', '3306');
|
|
$name = config('database.connections.mysql.database', '');
|
|
$username = config('database.connections.mysql.username', '');
|
|
$password = config('database.connections.mysql.password', '');
|
|
|
|
if (empty($name) || empty($username)) {
|
|
$this->results[] = ['item' => 'Emulator Database Fix', 'status' => 'warning', 'message' => 'Kon geen geldige database vinden'];
|
|
|
|
return;
|
|
}
|
|
|
|
$settings = app(SettingsService::class);
|
|
$settings->set('emulator_database_host', $host);
|
|
$settings->set('emulator_database_port', (string) $port);
|
|
$settings->set('emulator_database_name', $name);
|
|
$settings->set('emulator_database_username', $username);
|
|
$settings->set('emulator_database_password', $password);
|
|
|
|
$this->results[] = ['item' => 'Emulator Database Fix', 'status' => 'fixed', 'message' => "Automatisch gefixt: {$name}@{$host}"];
|
|
}
|
|
|
|
private function fixPermissions(): void
|
|
{
|
|
$directories = [
|
|
storage_path(),
|
|
storage_path('logs'),
|
|
storage_path('framework'),
|
|
storage_path('framework/cache'),
|
|
storage_path('framework/sessions'),
|
|
storage_path('framework/views'),
|
|
bootstrap_path('cache'),
|
|
];
|
|
|
|
$fixed = false;
|
|
foreach ($directories as $dir) {
|
|
if (! is_dir($dir)) {
|
|
@mkdir($dir, 0775, true);
|
|
$fixed = true;
|
|
}
|
|
|
|
if (is_writable($dir)) {
|
|
continue;
|
|
}
|
|
|
|
@chmod($dir, 0775);
|
|
$fixed = true;
|
|
}
|
|
|
|
$this->results[] = ['item' => 'Permissions', 'status' => $fixed ? 'fixed' : 'ok', 'message' => $fixed ? 'Permissions gefixt' : 'Al correct geconfigureerd'];
|
|
}
|
|
|
|
private function checkDiskSpace(): void
|
|
{
|
|
$total = disk_total_space('/');
|
|
$free = disk_free_space('/');
|
|
|
|
if ($total === false || $free === false) {
|
|
$this->results[] = ['item' => 'Disk Space', 'status' => 'warning', 'message' => 'Kon schijfruimte niet bepalen'];
|
|
|
|
return;
|
|
}
|
|
|
|
$usagePercent = (int) ((($total - $free) / $total) * 100);
|
|
|
|
if ($usagePercent >= 90) {
|
|
$this->results[] = ['item' => 'Disk Space', 'status' => 'error', 'message' => "Schijf {$usagePercent}% vol!"];
|
|
} elseif ($usagePercent >= 75) {
|
|
$this->results[] = ['item' => 'Disk Space', 'status' => 'warning', 'message' => "Schijf {$usagePercent}% gebruikt"];
|
|
} else {
|
|
$this->results[] = ['item' => 'Disk Space', 'status' => 'ok', 'message' => "Schijf {$usagePercent}% gebruikt"];
|
|
}
|
|
}
|
|
|
|
private function clearOldCaches(): void
|
|
{
|
|
Artisan::call('cache:clear');
|
|
Artisan::call('view:clear');
|
|
Artisan::call('config:clear');
|
|
|
|
$this->results[] = ['item' => 'Cache Cleanup', 'status' => 'fixed', 'message' => 'Caches opgeruimd'];
|
|
}
|
|
}
|