diff --git a/public/install/forms.php b/public/install/forms.php index 4abda8ec..605ea0b9 100644 --- a/public/install/forms.php +++ b/public/install/forms.php @@ -1,16 +1,12 @@ load(); - include 'functions.php'; @@ -25,6 +21,8 @@ if (isset($_POST['checkDB'])) { 'DB_CONNECTION' => 'databasedriver', ]; + wh_log('Trying to connect to the Database', 'debug'); + $db = new mysqli($_POST['databasehost'], $_POST['databaseuser'], $_POST['databaseuserpass'], $_POST['database'], $_POST['databaseport']); if ($db->connect_error) { wh_log($db->connect_error, 'error'); @@ -37,13 +35,15 @@ if (isset($_POST['checkDB'])) { // if ($key == "DB_PASSWORD") { // $param = '"' . $_POST[$value] . '"'; // } - setenv($key, $param); + setEnvironmentValue($key, $param); } + wh_log('Database connection successful', 'debug'); header('LOCATION: index.php?step=2.5'); } if (isset($_POST['checkGeneral'])) { + wh_log('setting app settings', 'debug'); $appname = '"' . $_POST['name'] . '"'; $appurl = $_POST['url']; @@ -51,18 +51,20 @@ if (isset($_POST['checkGeneral'])) { $appurl = substr_replace($appurl, '', -1); } - setenv('APP_NAME', $appname); - setenv('APP_URL', $appurl); + setEnvironmentValue('APP_NAME', $appname); + setEnvironmentValue('APP_URL', $appurl); + wh_log('App settings set', 'debug'); header('LOCATION: index.php?step=4'); } if (isset($_POST['feedDB'])) { + wh_log('Feeding the Database', 'debug'); $logs = ''; - //$logs .= run_console(setenv('COMPOSER_HOME', dirname(__FILE__, 3) . '/vendor/bin/composer')); + //$logs .= run_console(setEnvironmentValue('COMPOSER_HOME', dirname(__FILE__, 3) . '/vendor/bin/composer')); //$logs .= run_console('composer install --no-dev --optimize-autoloader'); - if (!str_contains(getenv('APP_KEY'), 'base64')) { + if (!str_contains(getEnvironmentValue('APP_KEY'), 'base64')) { $logs .= run_console('php artisan key:generate --force'); } else { $logs .= "Key already exists. Skipping\n"; @@ -71,16 +73,19 @@ if (isset($_POST['feedDB'])) { $logs .= run_console('php artisan migrate --seed --force'); $logs .= run_console('php artisan db:seed --class=ExampleItemsSeeder --force'); - wh_log($logs, 'info'); + wh_log($logs, 'debug'); - if (strpos(getenv('APP_KEY'), 'base64') !== false) { + if (str_contains(getEnvironmentValue('APP_KEY'), 'base64')) { + wh_log('Feeding the Database successful', 'debug'); header('LOCATION: index.php?step=3'); } else { + wh_log('Feeding the Database failed', 'debug'); header('LOCATION: index.php?step=2.5&message=There was an error. Please check the .txt file in /var/www/controlpanel/public/install/logs !'); } } if (isset($_POST['checkSMTP'])) { + wh_log('Checking SMTP Settings', 'debug'); try { $mail = new PHPMailer(true); @@ -104,11 +109,14 @@ if (isset($_POST['checkSMTP'])) { $mail->send(); } catch (Exception $e) { + wh_log($mail->ErrorInfo, 'error'); header('LOCATION: index.php?step=4&message=Something wasnt right when sending the E-Mail!'); exit(); } - $db = new mysqli(getenv('DB_HOST'), getenv('DB_USERNAME'), getenv('DB_PASSWORD'), getenv('DB_DATABASE'), getenv('DB_PORT')); + wh_log('SMTP Settings are correct', 'debug'); + wh_log('Updating Database', 'debug'); + $db = new mysqli(getEnvironmentValue('DB_HOST'), getEnvironmentValue('DB_USERNAME'), getEnvironmentValue('DB_PASSWORD'), getEnvironmentValue('DB_DATABASE'), getEnvironmentValue('DB_PORT')); if ($db->connect_error) { wh_log($db->connect_error, 'error'); header('LOCATION: index.php?step=4&message=Could not connect to the Database: '); @@ -125,14 +133,17 @@ if (isset($_POST['checkSMTP'])) { ]; foreach ($values as $key => $value) { - $query = 'UPDATE `' . getenv('DB_DATABASE') . "`.`settings` SET `payload` = '$value' WHERE `name` = '$key' AND `group` = mail"; + $query = 'UPDATE `' . getEnvironmentValue('DB_DATABASE') . "`.`settings` SET `payload` = '$value' WHERE `name` = '$key' AND `group` = mail"; $db->query($query); } + wh_log('Database updated', 'debug'); header('LOCATION: index.php?step=5'); } if (isset($_POST['checkPtero'])) { + wh_log('Checking Pterodactyl Settings', 'debug'); + $url = $_POST['url']; $key = $_POST['key']; $clientkey = $_POST['clientkey']; @@ -178,14 +189,17 @@ if (isset($_POST['checkPtero'])) { wh_log('API CALL ERROR: ' . $callresult['errors'][0]['code'], 'error'); exit(); } else { + wh_log('Pterodactyl Settings are correct', 'debug'); + wh_log('Updating Database', 'debug'); + $key = encryptSettingsValue($key); $clientkey = encryptSettingsValue($clientkey); - $query1 = 'UPDATE `' . getenv('DB_DATABASE') . "`.`settings` SET `payload` = '" . json_encode($url) . "' WHERE (`name` = 'panel_url' AND `group` = 'pterodactyl')"; - $query2 = 'UPDATE `' . getenv('DB_DATABASE') . "`.`settings` SET `payload` = '" . json_encode($key) . "' WHERE (`name` = 'admin_token' AND `group` = 'pterodactyl')"; - $query3 = 'UPDATE `' . getenv('DB_DATABASE') . "`.`settings` SET `payload` = '" . json_encode($clientkey) . "' WHERE (`name` = 'user_token' AND `group` = 'pterodactyl')"; + $query1 = 'UPDATE `' . getEnvironmentValue('DB_DATABASE') . "`.`settings` SET `payload` = '" . json_encode($url) . "' WHERE (`name` = 'panel_url' AND `group` = 'pterodactyl')"; + $query2 = 'UPDATE `' . getEnvironmentValue('DB_DATABASE') . "`.`settings` SET `payload` = '" . json_encode($key) . "' WHERE (`name` = 'admin_token' AND `group` = 'pterodactyl')"; + $query3 = 'UPDATE `' . getEnvironmentValue('DB_DATABASE') . "`.`settings` SET `payload` = '" . json_encode($clientkey) . "' WHERE (`name` = 'user_token' AND `group` = 'pterodactyl')"; - $db = new mysqli(getenv('DB_HOST'), getenv('DB_USERNAME'), getenv('DB_PASSWORD'), getenv('DB_DATABASE'), getenv('DB_PORT')); + $db = new mysqli(getEnvironmentValue('DB_HOST'), getEnvironmentValue('DB_USERNAME'), getEnvironmentValue('DB_PASSWORD'), getEnvironmentValue('DB_DATABASE'), getEnvironmentValue('DB_PORT')); if ($db->connect_error) { wh_log($db->connect_error, 'error'); header('LOCATION: index.php?step=5&message=Could not connect to the Database'); @@ -193,6 +207,7 @@ if (isset($_POST['checkPtero'])) { } if ($db->query($query1) && $db->query($query2) && $db->query($query3)) { + wh_log('Database updated', 'debug'); header('LOCATION: index.php?step=6'); } else { wh_log($db->error, 'error'); @@ -202,7 +217,8 @@ if (isset($_POST['checkPtero'])) { } if (isset($_POST['createUser'])) { - $db = new mysqli(getenv('DB_HOST'), getenv('DB_USERNAME'), getenv('DB_PASSWORD'), getenv('DB_DATABASE'), getenv('DB_PORT')); + wh_log('Creating User', 'debug'); + $db = new mysqli(getEnvironmentValue('DB_HOST'), getEnvironmentValue('DB_USERNAME'), getEnvironmentValue('DB_PASSWORD'), getEnvironmentValue('DB_DATABASE'), getEnvironmentValue('DB_PORT')); if ($db->connect_error) { wh_log($db->connect_error, 'error'); header('LOCATION: index.php?step=6&message=Could not connect to the Database'); @@ -213,9 +229,9 @@ if (isset($_POST['createUser'])) { $pass = $_POST['pass']; $repass = $_POST['repass']; - $key = $db->query('SELECT `payload` FROM `' . getenv('DB_DATABASE') . "`.`settings` WHERE `name` = 'admin_token' AND `group` = 'pterodactyl'")->fetch_assoc(); + $key = $db->query('SELECT `payload` FROM `' . getEnvironmentValue('DB_DATABASE') . "`.`settings` WHERE `name` = 'admin_token' AND `group` = 'pterodactyl'")->fetch_assoc(); $key = encryptSettingsValue($key['value']); - $pterobaseurl = $db->query('SELECT `payload` FROM `' . getenv('DB_DATABASE') . "`.`settings` WHERE `name` = 'panel_url' AND `group` = 'pterodactyl'")->fetch_assoc(); + $pterobaseurl = $db->query('SELECT `payload` FROM `' . getEnvironmentValue('DB_DATABASE') . "`.`settings` WHERE `name` = 'panel_url' AND `group` = 'pterodactyl'")->fetch_assoc(); $pteroURL = $pterobaseurl['value'] . '/api/application/users/' . $pteroID; $ch = curl_init(); @@ -266,15 +282,15 @@ if (isset($_POST['createUser'])) { curl_close($ch); // Close the connection if (!is_array($result) or in_array($result['errors'][0]['code'], $result)) { - header('LOCATION: index.php?step=5&message=Couldnt connect to Pterodactyl. Make sure your API key has all read and write permissions!'); + header('LOCATION: index.php?step=5&message=Couldn\'t connect to Pterodactyl. Make sure your API key has all read and write permissions!'); exit(); } $random = generateRandomString(); - $query1 = 'INSERT INTO `' . getenv('DB_DATABASE') . "`.`users` (`name`, `role`, `credits`, `server_limit`, `pterodactyl_id`, `email`, `password`, `created_at`, `referral_code`) VALUES ('$name', 'admin', '250', '1', '$pteroID', '$mail', '$pass', CURRENT_TIMESTAMP, '$random')"; + $query1 = 'INSERT INTO `' . getEnvironmentValue('DB_DATABASE') . "`.`users` (`name`, `role`, `credits`, `server_limit`, `pterodactyl_id`, `email`, `password`, `created_at`, `referral_code`) VALUES ('$name', 'admin', '250', '1', '$pteroID', '$mail', '$pass', CURRENT_TIMESTAMP, '$random')"; if ($db->query($query1)) { - wh_log('[USER MAKER] Created user with Email ' . $mail . ' and pterodactyl ID ' . $pteroID, 'info'); + wh_log('Created user with Email ' . $mail . ' and pterodactyl ID ' . $pteroID, 'info'); header('LOCATION: index.php?step=7'); } else { wh_log($db->error, 'error'); diff --git a/public/install/functions.php b/public/install/functions.php index c231d2be..9806e125 100644 --- a/public/install/functions.php +++ b/public/install/functions.php @@ -3,7 +3,9 @@ require '../../vendor/autoload.php'; use Illuminate\Encryption\Encrypter; use Illuminate\Support\Str; -use Illuminate\Support\Facades\Log; +use Monolog\Formatter\LineFormatter; +use Monolog\Handler\StreamHandler; +use Monolog\Logger; $required_extensions = ['openssl', 'gd', 'mysql', 'PDO', 'mbstring', 'tokenizer', 'bcmath', 'xml', 'curl', 'zip', 'intl']; @@ -20,6 +22,8 @@ $requirements = [ function checkPhpVersion(): string { global $requirements; + + wh_log('php version: ' . phpversion(), 'debug'); if (version_compare(phpversion(), $requirements['minPhp'], '>=') && version_compare(phpversion(), $requirements['maxPhp'], '<=')) { return 'OK'; } @@ -42,6 +46,7 @@ function checkWriteable(): bool */ function checkHTTPS(): bool { + wh_log('https: ' . (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'true' : 'false', 'debug'); return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443; } @@ -54,10 +59,13 @@ function getMySQLVersion(): mixed { global $requirements; + wh_log('attempting to get mysql version', 'debug'); + $output = shell_exec('mysql -V') ?? ''; preg_match('@[0-9]+\.[0-9]+\.[0-9]+@', $output, $version); $versionoutput = $version[0] ?? '0'; + wh_log('mysql version: ' . $versionoutput, 'debug'); return intval($versionoutput) > intval($requirements['mysql']) ? 'OK' : $versionoutput; } @@ -68,10 +76,12 @@ function getMySQLVersion(): mixed */ function getZipVersion(): string { + wh_log('attempting to get zip version', 'debug'); $output = shell_exec('zip -v') ?? ''; preg_match('@[0-9]+\.[0-9]+\.[0-9]+@', $output, $version); $versionoutput = $version[0] ?? 0; + wh_log('zip version: ' . $versionoutput, 'debug'); return $versionoutput != 0 ? 'OK' : 'not OK'; } @@ -82,10 +92,12 @@ function getZipVersion(): string */ function getGitVersion(): string { + wh_log('attempting to get git version', 'debug'); $output = shell_exec('git --version') ?? ''; preg_match('@[0-9]+\.[0-9]+\.[0-9]+@', $output, $version); $versionoutput = $version[0] ?? 0; + wh_log('git version: ' . $versionoutput, 'debug'); return $versionoutput != 0 ? 'OK' : 'not OK'; } @@ -96,10 +108,12 @@ function getGitVersion(): string */ function getTarVersion(): string { + wh_log('attempting to get tar version', 'debug'); $output = shell_exec('tar --version') ?? ''; preg_match('@[0-9]+\.[0-9]+@', $output, $version); $versionoutput = $version[0] ?? 0; + wh_log('tar version: ' . $versionoutput, 'debug'); return $versionoutput != 0 ? 'OK' : 'not OK'; } @@ -112,6 +126,8 @@ function checkExtensions(): array { global $required_extensions; + wh_log('checking extensions', 'debug'); + $not_ok = []; $extentions = get_loaded_extensions(); @@ -121,6 +137,7 @@ function checkExtensions(): array } } + wh_log('extensions: ' . implode(', ', $not_ok), 'debug'); return $not_ok; } @@ -130,10 +147,40 @@ function checkExtensions(): array * @param string $envValue The environment variable to set * @return bool true on success or false on failure. */ -function setenv(string $envKey, $envValue) +function setEnvironmentValue($envKey, $envValue) { - $str = "{$envKey}={$envValue}"; - return putenv($str); + $envFile = dirname(__FILE__, 3).'/.env'; + $str = file_get_contents($envFile); + + $str .= "\n"; // In case the searched variable is in the last line without \n + $keyPosition = strpos($str, "{$envKey}="); + $endOfLinePosition = strpos($str, PHP_EOL, $keyPosition); + $oldLine = substr($str, $keyPosition, $endOfLinePosition - $keyPosition); + $str = str_replace($oldLine, "{$envKey}={$envValue}", $str); + $str = substr($str, 0, -1); + + $fp = fopen($envFile, 'w'); + fwrite($fp, $str); + fclose($fp); +} + +/** + * Gets the variable from the env file + * @param string $envKey The environment variable to look for + * @return array|false|string Returns the value if found, otherwise returns false. + */ +function getEnvironmentValue($envKey) +{ + $envFile = dirname(__FILE__, 3).'/.env'; + $str = file_get_contents($envFile); + + $str .= "\n"; // In case the searched variable is in the last line without \n + $keyPosition = strpos($str, "{$envKey}="); + $endOfLinePosition = strpos($str, PHP_EOL, $keyPosition); + $oldLine = substr($str, $keyPosition, $endOfLinePosition - $keyPosition); + $value = substr($oldLine, strpos($oldLine, '=') + 1); + + return $value; } @@ -191,38 +238,55 @@ function decryptSettingsValue(mixed $payload, $unserialize = true) */ function run_console(string $command, array $descriptors = null, string $cwd = null, array $options = null) { + wh_log('running command: ' . $command, 'debug'); + $path = dirname(__FILE__, 3); $descriptors = $descriptors ?? [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']]; $handle = proc_open("cd '$path' && bash -c 'exec -a ServerCPP $command'", $descriptors, $pipes, $cwd, null, $options); + wh_log('command result: ' . stream_get_contents($pipes[1]), 'debug'); return stream_get_contents($pipes[1]); } /** * Log to the default laravel.log file * @param string $message The message to log - * @param string $level The log level to use (info, warning, error, critical) - * @return void Returns nothing. + * @param string $level The log level to use (debug, info, warning, error, critical) + * @param array $context [optional] The context to log extra information + * @return void */ -function wh_log(string $message, $level = 'info') +function wh_log(string $message, string $level = 'info', array $context = []): void { - switch ($level) { + $formatter = new LineFormatter(null, null, true, true); + $stream = new StreamHandler(dirname(__FILE__, 3) . '/storage/logs/laravel.log', Logger::DEBUG); + $stream->setFormatter($formatter); + + $log = new Logger('ControlPanel'); + $log->pushHandler($stream); + + switch (strtolower($level)) { + case 'debug': // Only log debug messages if APP_DEBUG is true + wh_log('APP_DEBUG: ' . getEnvironmentValue('APP_DEBUG')); + if(getEnvironmentValue('APP_DEBUG') === false) return; + $log->debug($message, $context); + break; case 'info': - Log::info($message); + $log->info($message, $context); break; case 'warning': - Log::warning($message); + $log->warning($message, $context); break; case 'error': - Log::error($message); + $log->error($message, $context); break; case 'critical': - Log::critical($message); + $log->critical($message, $context); break; } + // Prevent memory leaks by resetting the logger + $log->reset(); } - /** * Generate a random string * @param int $length The length of the random string