HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
File: /home/xedaptot/ai.naniguide.com/app/Http/Controllers/InstallController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class InstallController extends Controller
{
    /**
     * Apply locale from cookie if present (DB-free locale switching during install).
     */
    public function __construct()
    {
        if (isset($_COOKIE['last_language_code'])) {
            $code = preg_replace('/[^a-zA-Z_-]/', '', $_COOKIE['last_language_code']);
            if ($code && is_dir(resource_path('lang/' . $code))) {
                \App::setLocale($code);
                \Carbon\Carbon::setLocale($code);
            }
        }
    }

    /**
     * Check for current step progress via session.
     */
    public function step($request)
    {
        $step = 0;

        if ($request->session()->has('compatibilities')) {
            $step = 1;
        } else {
            return $step;
        }

        if ($request->session()->has('site_info')) {
            $step = 3;
        } else {
            return $step;
        }

        if ($request->session()->has('database')) {
            $step = 4;
        } else {
            return $step;
        }

        if ($request->session()->has('database_imported')) {
            $step = 5;
        } else {
            return $step;
        }

        if ($request->session()->has('cron_jobs')) {
            $step = 6;
        } else {
            return $step;
        }

        return $step;
    }

    /**
     * Starting — redirect to system compatibility.
     */
    public function starting(Request $request)
    {
        return redirect()->route('install.compatibility');
    }

    /**
     * Step 1: System compatibility check.
     */
    public function systemCompatibility(Request $request)
    {
        $request->session()->forget('compatibilities');

        $compatibilities = $this->checkSystemCompatibility();
        $result = true;

        foreach ($compatibilities as $compatibility) {
            if (!$compatibility['check']) {
                $result = false;
            }
        }

        try {
            if ($result) {
                $request->session()->put('compatibilities', $compatibilities);
            }

            return view('install.compatibilities', [
                'compatibilities' => $compatibilities,
                'result' => $result,
                'step' => $this->step($request),
                'current' => 1,
            ]);
        } catch (\Exception $e) {
            return redirect()->route('install.compatibility');
        }
    }

    /**
     * Step 2: Site info / configuration.
     */
    public function siteInfo(Request $request)
    {
        if ($this->step($request) < 1) {
            return redirect()->route('install.compatibility');
        }

        $rules = [
            'site_name' => 'required',
            'site_description' => 'required',
            'name' => 'required',
            'first_name' => 'required',
            'last_name' => 'required',
            'email' => 'required|email',
            'password' => 'required',
            'timezone' => 'required',
        ];

        $mail_rules = [
            'smtp' => [
                'smtp_hostname' => 'required',
                'smtp_port' => 'required',
                'smtp_username' => 'required',
                'smtp_password' => 'required',
                'mail_from_email' => 'required|email',
                'mail_from_name' => 'required',
            ],
            'sendmail' => [
                'mail_from_email' => 'required|email',
                'mail_from_name' => 'required',
                'sendmail_path' => 'required',
            ],
        ];
        $smtp_rules = $mail_rules['smtp'];

        if ($request->isMethod('post')) {
            $request->session()->forget('site_info');

            $rules = array_merge($rules, $mail_rules[$request->mail_mailer]);
            $this->validate($request, $rules);

            $site_info = $request->all();

            // Check license
            if (!empty($request->license)) {
                try {
                    $license = \App\Helpers\LicenseHelper::getLicense($site_info['license']);
                    $site_info['license'] = $license['purchase_code'];
                    $site_info['license_type'] = $license['licence'];
                    $site_info['license_status'] = $license['status'];
                    $site_info['license_supported_until'] = $license['supported_until'];
                } catch (\Exception $ex) {
                    throw \Illuminate\Validation\ValidationException::withMessages([
                        'license' => $ex->getMessage(),
                    ]);
                }
            } else {
                $site_info['license'] = '';
                $site_info['license_type'] = '';
                $site_info['license_status'] = '';
                $site_info['license_supported_until'] = '';
            }

            // Check SMTP connection
            if ($request->mail_mailer == 'smtp') {
                $rules = [];
                try {
                    $useTls = match (strtolower((string) $request->smtp_encryption)) {
                        "ssl"   => true,
                        "tls"   => null,
                        default => false,
                    };
                    $transport = new \Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport(
                        $request->smtp_hostname,
                        (int) $request->smtp_port,
                        $useTls
                    );
                    $transport->setUsername($request->smtp_username);
                    $transport->setPassword($request->smtp_password);
                    $transport->start();
                } catch (\Symfony\Component\Mailer\Exception\TransportExceptionInterface $e) {
                    $rules['smtp_valid'] = 'required';
                } catch (\Exception $e) {
                    $rules['smtp_valid'] = 'required';
                }
                $this->validate($request, $rules);
            }

            $request->session()->put('site_info', $site_info);

            return redirect()->route('install.database');
        }

        $site_info = $request->session()->get('site_info');
        if (!empty($request->old())) {
            $site_info = $request->old();
        }

        return view('install.site_info', [
            'site_info' => $site_info,
            'rules' => $rules,
            'smtp_rules' => $smtp_rules,
            'step' => $this->step($request),
            'current' => 2,
        ]);
    }

    /**
     * Step 3: Database configuration.
     */
    public function database(Request $request)
    {
        if ($this->step($request) < 2) {
            return redirect()->route('install.site_info');
        }

        $rules = [
            'hostname' => 'required',
            'port' => 'required',
            'username' => 'required',
            'password' => 'required',
            'database_name' => 'required',
        ];

        if ($request->isMethod('post')) {
            $request->session()->forget('database');

            $this->validate($request, $rules);

            try {
                $port = (int) $request->port;
                $conn = new \mysqli($request->hostname, $request->username, $request->password, $request->database_name, $port);
            } catch (\Exception $e) {
                $rules['mysql_connection'] = 'required';
                $request->session()->flash('alert-error', $e->getMessage());
            }

            $this->validate($request, $rules);

            $database = $request->all();
            $request->session()->put('database', $database);

            // Write env
            $this->writeEnv($request);

            return redirect()->route('install.database_import');
        }

        $database = $request->session()->get('database');
        if (!empty($request->old())) {
            $database = $request->old();
        }

        return view('install.database', [
            'database' => $database,
            'rules' => $rules,
            'step' => $this->step($request),
            'current' => 3,
        ]);
    }

    /**
     * Step 3b: Database import warning page.
     */
    public function databaseImport(Request $request)
    {
        if ($this->step($request) < 3) {
            return redirect()->route('install.database');
        }

        $database = $request->session()->get('database');

        return view('install.database_import', [
            'database' => $database,
            'step' => $this->step($request),
            'current' => 3,
        ]);
    }

    /**
     * Step 3c: Execute database import.
     */
    public function import(Request $request)
    {
        if ($this->step($request) < 3) {
            return redirect()->route('install.database');
        }

        $database = $request->session()->get('database');
        $site_info = $request->session()->get('site_info');

        $mysqli = new \mysqli($database['hostname'], $database['username'], $database['password'], $database['database_name'], $database['port']);

        $request->session()->forget('database_imported');

        // Drop all existing tables
        $sql = 'SHOW TABLE STATUS';
        $statement = $mysqli->query($sql);
        while ($result = $statement->fetch_object()) {
            $tableName = $result->Name;
            $mysqli->query('SET FOREIGN_KEY_CHECKS = 0;');
            $mysqli->query("DROP TABLE IF EXISTS {$tableName};");
            $mysqli->query('SET FOREIGN_KEY_CHECKS = 1;');
        }

        $request->session()->put('database_imported', true);

        // Run migrate
        artisan_migrate();

        // Import database via seeder
        \Artisan::call('db:seed', ['--class' => 'DatabaseInit']);
        \Artisan::call('db:seed', ['--class' => 'TemplateSeeder']);

        // Reconnect
        $mysqli = new \mysqli($database['hostname'], $database['username'], $database['password'], $database['database_name'], $database['port']);

        // Locale / Language
        $locale = \App::getLocale();
        $language = \App\Model\Language::getFirstLanguageByCode($locale);

        [$user, $admin, $customer] = app(\App\Services\AccountManagement\AccountProvisioningService::class)
            ->createInstallAccount($site_info, $language->id);

        // Insert system URLs
        // Wave F: `url_delivery_handler` removed — see InstallController note.
        // Display-only template — signed routes embed a per-URL HMAC so we
        // can't use route() with placeholder values. Show the path shape with
        // a SIGNATURE token for admin reference.
        \App\Model\Setting::set('url_unsubscribe', rtrim(url('/'), '/') . '/c/SUBSCRIBER/unsubscribe-form/MESSAGE_ID?signature=SIGNATURE');
        \App\Model\Setting::set('url_open_track', route('openTrackingUrl', ['message_id' => 'MESSAGE_ID']));
        \App\Model\Setting::set('url_web_view', route('webViewerUrl', ['message_id' => 'MESSAGE_ID']));
        \App\Model\Setting::set('url_click_track', route('clickTrackingUrl', ['message_id' => 'MESSAGE_ID', 'url' => 'URL']));
        \App\Model\Setting::set('url_update_profile', action('Pub\MailListController@profileUpdateForm', ['list_uid' => 'LIST_UID', 'id' => 'SUBSCRIBER_ID', 'customer_uid' => 'CUSTOMER_UID']));

        // Site info settings
        \App\Model\Setting::set('site_name', $site_info['site_name']);
\App\Model\Setting::set('site_description', $site_info['site_description']);
        \App\Model\Setting::set('license', $site_info['license']);
        \App\Model\Setting::set('license_type', $site_info['license_type']);

        // Mail settings
        \App\Model\Setting::set('mailer.mailer', $site_info['mail_mailer']);
        \App\Model\Setting::set('mailer.host', $site_info['smtp_hostname']);
        \App\Model\Setting::set('mailer.port', $site_info['smtp_port']);
        \App\Model\Setting::set('mailer.encryption', $site_info['smtp_encryption']);
        \App\Model\Setting::set('mailer.username', $site_info['smtp_username']);
        \App\Model\Setting::set('mailer.password', $site_info['smtp_password']);
        \App\Model\Setting::set('mailer.from.name', $site_info['mail_from_name']);
        \App\Model\Setting::set('mailer.from.address', $site_info['mail_from_email']);
        \App\Model\Setting::set('mailer.sendmail_path', $site_info['sendmail_path']);

        // Generate translation files
        \App\Model\Language::dump();

        $request->session()->flash('alert-success', trans('install.database_import.import_success'));

        return redirect()->route('install.cron_jobs');
    }

    /**
     * Step 4: Cron jobs configuration.
     */
    public function cronJobs(Request $request)
    {
        if ($this->step($request) < 5) {
            return redirect()->route('install.database');
        }

        $respone = \App\Library\Tool::cronjobUpdateController($request, $this);
        if ($respone == 'done' || $respone == 'remote') {
            return redirect()->route('install.finishing');
        }

        return view('install.cron_jobs', $respone);
    }

    /**
     * Finishing — redirect to finish. Notifications table is recreated empty
     * by the redesign migration, so no cleanup pass is needed at install.
     */
    public function finishing(Request $request)
    {
        return redirect()->route('install.finish');
    }

    /**
     * Step 5: Installation complete.
     */
    public function finish(Request $request)
    {
        if ($this->step($request) < 6) {
            return redirect()->route('install.database');
        }

        $request->session()->put('install_finish', true);

        $file_path = storage_path('app/installed');
        $file = fopen($file_path, 'w') or die('Unable to open file!');
        fwrite($file, '');
        fclose($file);

        // Generate translation files again (after installed file is available)
        \App\Model\Language::dump();

        return view('install.finish', [
            'step' => $this->step($request),
            'current' => 6,
        ]);
    }

    /**
     * Check system compatibility requirements.
     */
    public function checkSystemCompatibility()
    {
        return [
            ['type' => 'requirement', 'name' => 'PHP', 'check' => version_compare(PHP_VERSION, config('custom.php'), '>='), 'note' => trans('messages.install.error.php', ['version' => config('custom.php')])],
            ['type' => 'requirement', 'name' => 'MySQLi', 'check' => function_exists('mysqli_connect'), 'note' => trans('messages.install.error.extension', ['name' => 'MySQLi'])],
            ['type' => 'requirement', 'name' => 'OpenSSL', 'check' => extension_loaded('openssl'), 'note' => trans('messages.install.error.extension', ['name' => 'OpenSSL'])],
            ['type' => 'requirement', 'name' => 'Multibyte String', 'check' => extension_loaded('mbstring'), 'note' => trans('messages.install.error.extension', ['name' => 'Multibyte String'])],
            ['type' => 'requirement', 'name' => 'PHP PDO', 'check' => extension_loaded('pdo'), 'note' => trans('messages.install.error.extension', ['name' => 'PHP PDO'])],
            ['type' => 'requirement', 'name' => 'Tokenizer', 'check' => extension_loaded('tokenizer'), 'note' => trans('messages.install.error.extension', ['name' => 'Tokenizer'])],
            ['type' => 'requirement', 'name' => 'PHP ZIP', 'check' => class_exists('ZipArchive', false), 'note' => trans('messages.install.error.extension', ['name' => 'PHP ZIP'])],
            ['type' => 'requirement', 'name' => 'IMAP', 'check' => extension_loaded('imap'), 'note' => trans('messages.install.error.extension', ['name' => 'IMAP'])],
            ['type' => 'requirement', 'name' => 'SQLite3', 'check' => class_exists('SQLite3'), 'note' => trans('messages.install.error.extension', ['name' => 'SQLite3'])],
            ['type' => 'requirement', 'name' => 'PHP GD', 'check' => (extension_loaded('gd') && function_exists('gd_info')), 'note' => trans('messages.install.error.extension', ['name' => 'PHP GD'])],
            ['type' => 'requirement', 'name' => 'PHP FileInfo', 'check' => extension_loaded('fileinfo'), 'note' => trans('messages.install.error.extension', ['name' => 'PHP FileInfo'])],
            ['type' => 'requirement', 'name' => 'PHP Curl', 'check' => extension_loaded('curl'), 'note' => trans('messages.install.error.extension', ['name' => 'PHP Curl'])],
            ['type' => 'requirement', 'name' => 'PHP XML', 'check' => extension_loaded('xml'), 'note' => trans('messages.install.error.extension', ['name' => 'PHP XML'])],
            ['type' => 'requirement', 'name' => 'proc_close()', 'check' => func_enabled('proc_close'), 'note' => trans('messages.install.error.function', ['name' => 'proc_close()'])],
            ['type' => 'requirement', 'name' => 'escapeshellarg()', 'check' => func_enabled('escapeshellarg'), 'note' => trans('messages.install.error.function', ['name' => 'escapeshellarg()'])],
            ['type' => 'permission', 'name' => base_path('storage/app'), 'check' => file_exists(base_path('/storage/app')) && is_dir(base_path('/storage/app')) && is_writable(base_path('/storage/app')), 'note' => trans('messages.install.notice.writable')],
            ['type' => 'permission', 'name' => base_path('storage/framework'), 'check' => file_exists(base_path('/storage/framework')) && is_dir(base_path('/storage/framework')) && is_writable(base_path('/storage/framework')), 'note' => trans('messages.install.notice.writable')],
            ['type' => 'permission', 'name' => base_path('storage/logs'), 'check' => file_exists(base_path('/storage/logs')) && is_dir(base_path('/storage/logs')) && is_writable(base_path('/storage/logs')), 'note' => trans('messages.install.notice.writable')],
            ['type' => 'permission', 'name' => base_path('storage/job'), 'check' => file_exists(base_path('/storage/job')) && is_dir(base_path('/storage/job')) && is_writable(base_path('/storage/job')), 'note' => trans('messages.install.notice.writable')],
            ['type' => 'permission', 'name' => base_path('bootstrap/cache'), 'check' => file_exists(base_path('/bootstrap/cache')) && is_dir(base_path('/bootstrap/cache')) && is_writable(base_path('/bootstrap/cache')), 'note' => trans('messages.install.notice.writable')],
        ];
    }

    /**
     * Write configuration values to .env file.
     */
    public function writeEnv($request)
    {
        $database = $request->session()->get('database');
        $database = !empty($database) ? $database : [];

        $smtp = $request->session()->get('site_info');
        $smtp = !empty($smtp) ? $smtp : [];

        \App\Helpers\write_envs([
            'APP_URL' => url('/'),
            'DB_HOST' => $database['hostname'] ?? '',
            'DB_DATABASE' => $database['database_name'] ?? '',
            'DB_USERNAME' => $database['username'] ?? '',
            'DB_PASSWORD' => isset($database['password']) ? quoteDotEnvValue($database['password']) : '',
            'DB_PORT' => $database['port'] ?? '',
            'DB_TABLES_PREFIX' => $database['tables_prefix'] ?? '',
            'MAIL_MAILER' => $smtp['mail_mailer'] ?? 'mail',
            'MAIL_HOST' => $smtp['smtp_hostname'] ?? '',
            'MAIL_PORT' => $smtp['smtp_port'] ?? '',
            'MAIL_USERNAME' => $smtp['smtp_username'] ?? '',
            'MAIL_PASSWORD' => isset($smtp['smtp_password']) ? quoteDotEnvValue($smtp['smtp_password']) : '',
            'MAIL_ENCRYPTION' => $smtp['smtp_encryption'] ?? '',
            'MAIL_FROM_ADDRESS' => $smtp['mail_from_email'] ?? '',
            'MAIL_FROM_NAME' => $smtp['mail_from_name'] ?? '',
        ]);
    }
}