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/be.naniguide.com/app/Http/Controllers/Refactor/Admin/SettingController.php
<?php

namespace App\Http\Controllers\Refactor\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Model\Setting;
use App\Library\UpgradeManager;
use App\Helpers\LicenseHelper;
use App\Notifications\Admin\UpgradePatchAvailable;
use App\Notifications\System\SystemUrlMismatch;
use App\Services\Notifications\Notifier;
use Illuminate\Support\Facades\Log;
use App;

class SettingController extends Controller
{
    public function index(Request $request)
    {
        $admin = $request->user()->admin;

        if ($admin->getPermission('setting_general') == 'yes') {
            return redirect()->route('refactor.admin.settings.general');
        }
        if ($admin->getPermission('setting_system_urls') == 'yes') {
            return redirect()->route('refactor.admin.settings.urls');
        }
        if ($admin->getPermission('setting_background_job') == 'yes') {
            return redirect()->route('refactor.admin.settings.cronjob');
        }

        return $this->notAuthorized();
    }

    public function general(Request $request)
    {
        if ($request->user()->admin->getPermission('setting_general') != 'yes') {
            return $this->notAuthorized();
        }

        if ($request->isMethod('post')) {
            // Read settings from either JSON body or settings[] wrapper (for file uploads)
            if ($request->isJson()) {
                $settings = $request->except(['_token']);
            } else {
                // FormData with settings[] wrapper preserves dot-notation keys
                $settings = $request->input('settings', []);
            }

            foreach ($settings as $name => $value) {
                if (is_array($value)) {
                    continue;
                }
                Setting::set($name, $value);
            }

            // Handle file uploads by known field names
            foreach (['site_logo_light', 'site_logo_dark', 'site_favicon'] as $fileField) {
                if ($request->hasFile($fileField) && $request->file($fileField)->isValid()) {
                    Setting::uploadFile($request->file($fileField), $fileField, false);
                }
            }

            if ($request->ajax()) {
                return response()->json(['status' => 'success', 'message' => trans('refactor/admin_settings.flash.saved')]);
            }

            $request->session()->flash('alert-success', trans('refactor/admin_settings.flash.saved'));
            return redirect()->route('refactor.admin.settings.general');
        }

        $settings = Setting::getAll();
        $tab = 'general';

        return view('refactor.pages.admin.settings.general', compact('settings', 'tab'));
    }

    public function mailer(Request $request)
    {
        if ($request->user()->admin->getPermission('setting_general') != 'yes') {
            return $this->notAuthorized();
        }

        if ($request->isMethod('post')) {
            $data = $request->isJson() ? $request->except(['_token']) : $request->input('settings', $request->except(['_token']));

            foreach ($data as $name => $value) {
                if (!is_array($value)) {
                    Setting::set($name, $value);
                }
            }

            if ($request->ajax()) {
                return response()->json(['status' => 'success', 'message' => trans('refactor/admin_settings.flash.saved')]);
            }

            $request->session()->flash('alert-success', trans('refactor/admin_settings.flash.saved'));
            return redirect()->route('refactor.admin.settings.mailer');
        }

        $settings = Setting::getAll();
        $tab = 'mailer';

        return view('refactor.pages.admin.settings.mailer', compact('settings', 'tab'));
    }

    public function mailerTest(Request $request)
    {
        if ($request->user()->admin->getPermission('setting_general') != 'yes') {
            return response()->json(['status' => 'error', 'message' => 'Not authorized'], 403);
        }

        try {
            $email = new \Symfony\Component\Mime\Email();
            $email->subject($request->input('subject'));
            $email->to($request->input('to_email'));
            $email->html($request->input('content'));

            $mailer = App::make('xmailer');
            $mailer->sendWithDefaultFromAddress($email);

            return response()->json(['status' => 'success', 'message' => trans('refactor/admin_settings.flash.test_sent')]);
        } catch (\Exception $e) {
            return response()->json(['status' => 'error', 'message' => trans('refactor/admin_settings.mailer.test_error', ['error' => $e->getMessage()])], 400);
        }
    }

    public function cronjob(Request $request)
    {
        if ($request->user()->admin->getPermission('setting_background_job') != 'yes') {
            return $this->notAuthorized();
        }

        if ($request->isMethod('post')) {
            $phpPath = $request->input('php_bin_path');
            $phpPathValue = $request->input('php_bin_path_value');

            if ($phpPath === 'manual' || empty($phpPath)) {
                $phpPath = $phpPathValue;
            }

            if (empty($phpPath)) {
                $errorMsg = trans('refactor/admin_settings.cronjob.path_required');
                if ($request->ajax()) {
                    return response()->json(['status' => 'error', 'message' => $errorMsg], 422);
                }
                return redirect()->route('refactor.admin.settings.cronjob')->withErrors(['php_bin_path' => $errorMsg]);
            }

            // Validate PHP binary path
            $check = \App\Library\Tool::checkPHPBinPath($phpPath);
            if ($check != 'ok') {
                if ($request->ajax()) {
                    return response()->json(['status' => 'error', 'message' => $check], 422);
                }

                return redirect()->route('refactor.admin.settings.cronjob')->withErrors(['php_bin_path' => $check]);
            }

            Setting::set('php_bin_path', $phpPath);

            if ($request->ajax()) {
                return response()->json(['status' => 'success', 'message' => trans('refactor/admin_settings.flash.saved')]);
            }

            $request->session()->flash('alert-success', trans('refactor/admin_settings.flash.saved'));
            return redirect()->route('refactor.admin.settings.cronjob');
        }

        // Detect PHP paths
        $paths = ['/usr/local/bin/php', '/usr/bin/php', '/bin/php', '/usr/bin/php8.1', '/usr/bin/php8.2', '/usr/bin/php8.3'];
        if (exec_enabled()) {
            try {
                $detected = explode(' ', exec('whereis php'));
                $paths = array_unique(array_merge($paths, $detected));
            } catch (\Exception $e) {
                // skip
            }
        }

        $php_paths = array_values(array_filter($paths, function ($path) {
            try {
                return is_executable($path) && preg_match("/php[0-9\.a-z]{0,3}$/i", $path);
            } catch (\Exception $ex) {
                return false;
            }
        }));

        $php_bin_path_value = Setting::get('php_bin_path');
        if (empty($php_bin_path_value)) {
            $php_bin_path_value = !empty($php_paths) ? $php_paths[0] : '/usr/bin/php';
        }

        $settings = Setting::getAll();
        $tab = 'cronjob';

        return view('refactor.pages.admin.settings.cronjob', compact('settings', 'tab', 'php_paths', 'php_bin_path_value'));
    }

    public function urls(Request $request)
    {
        if ($request->user()->admin->getPermission('setting_system_urls') != 'yes') {
            return $this->notAuthorized();
        }

        $urlSettings = array_filter(Setting::getAll(), function ($setting, $key) {
            return in_array($key, [
                'url_unsubscribe',
                'url_open_track',
                'url_click_track',
                'url_update_profile',
                'url_web_view',
            ]);
        }, ARRAY_FILTER_USE_BOTH);

        $current = url('/');
        $cached = config('app.url');
        $matched = ($cached == $current);

        $settings = Setting::getAll();
        $tab = 'urls';

        return view('refactor.pages.admin.settings.urls', compact('settings', 'tab', 'urlSettings', 'matched', 'current', 'cached'));
    }

    public function urlsUpdate(Request $request)
    {
        if ($request->user()->admin->getPermission('setting_system_urls') != 'yes') {
            return response()->json(['status' => 'error', 'message' => 'Not authorized'], 403);
        }

        \App\Helpers\reset_app_url(true);

        if (file_exists(base_path('bootstrap/cache/config.php'))) {
            unlink(base_path('bootstrap/cache/config.php'));
        }

        // 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.
        Setting::set('url_unsubscribe', rtrim(url('/'), '/') . '/c/SUBSCRIBER/unsubscribe-form/MESSAGE_ID?signature=SIGNATURE');
        Setting::set('url_open_track', route('openTrackingUrl', ['message_id' => 'MESSAGE_ID']));
        Setting::set('url_click_track', route('clickTrackingUrl', ['message_id' => 'MESSAGE_ID', 'url' => 'URL']));
        // Wave F: `url_delivery_handler` removed — see InstallController note.
        Setting::set('url_update_profile', action('Pub\MailListController@profileUpdateForm', [
            'list_uid' => 'LIST_UID',
            'id' => 'SUBSCRIBER_ID',
            'customer_uid' => 'CUSTOMER_UID',
        ]));
        Setting::set('url_web_view', route('webViewerUrl', ['message_id' => 'MESSAGE_ID']));

        $current = url('/');
        $cached  = config('app.url');
        $notifier = app(Notifier::class);
        if ($current === $cached) {
            $notifier->clearGroup('system-url-mismatch');
        } else {
            $notifier->shareWithAdmins(new SystemUrlMismatch($current, $cached));
        }

        return response()->json(['status' => 'success', 'message' => trans('refactor/admin_settings.urls.updated')]);
    }

    public function advanced(Request $request)
    {
        if ($request->user()->admin->getPermission('setting_general') != 'yes') {
            return $this->notAuthorized();
        }

        $settings = Setting::getAll();
        $tab = 'advanced';

        return view('refactor.pages.admin.settings.advanced', compact('settings', 'tab'));
    }

    public function advancedUpdate(Request $request, $name)
    {
        if ($request->user()->admin->getPermission('setting_general') != 'yes') {
            return response()->json(['status' => 'error', 'message' => 'Not authorized'], 403);
        }

        Setting::set($name, $request->input('value'));

        return response()->json(['status' => 'success', 'message' => trans('refactor/admin_settings.advanced.updated', ['name' => $name])]);
    }

    public function license(Request $request)
    {
        if ($request->user()->admin->getPermission('setting_general') != 'yes') {
            return $this->notAuthorized();
        }

        $license_error = '';

        if ($request->isMethod('post')) {
            try {
                LicenseHelper::updateLicense($request->license);

                if ($request->ajax()) {
                    return response()->json(['status' => 'success', 'message' => trans('refactor/admin_settings.license.verified')]);
                }

                $request->session()->flash('alert-success', trans('refactor/admin_settings.license.verified'));
                return redirect()->route('refactor.admin.settings.license');
            } catch (\Throwable $ex) {
                $license_error = $ex->getMessage();

                if ($request->ajax()) {
                    return response()->json(['status' => 'error', 'message' => trans('refactor/admin_settings.license.error', ['error' => $license_error])]);
                }
            }
        }

        $license = LicenseHelper::getCurrentLicense();
        $settings = Setting::getAll();
        $tab = 'license';

        return view('refactor.pages.admin.settings.license', compact('settings', 'tab', 'license', 'license_error'));
    }

    public function licenseRefresh(Request $request)
    {
        if ($request->user()->admin->getPermission('setting_general') != 'yes') {
            return response()->json(['status' => 'error', 'message' => 'Not authorized'], 403);
        }

        try {
            LicenseHelper::refreshLicense();
            return response()->json(['status' => 'success', 'message' => trans('refactor/admin_settings.license.refreshed')]);
        } catch (\Exception $e) {
            return response()->json(['status' => 'error', 'message' => $e->getMessage()], 400);
        }
    }

    public function licenseRemove(Request $request)
    {
        if ($request->user()->admin->getPermission('setting_general') != 'yes') {
            return response()->json(['status' => 'error', 'message' => 'Not authorized'], 403);
        }

        try {
            LicenseHelper::removeLicense();
            return response()->json(['status' => 'success', 'message' => trans('refactor/admin_settings.license.removed')]);
        } catch (\Exception $e) {
            return response()->json(['status' => 'error', 'message' => $e->getMessage()], 400);
        }
    }

    public function upgrade(Request $request)
    {
        session(['secret' => $request->input('secret')]);

        $manager = new UpgradeManager();
        $license = LicenseHelper::getCurrentLicense();

        $settings = Setting::getAll();
        $tab = 'upgrade';

        return view('refactor.pages.admin.settings.upgrade', compact('settings', 'tab', 'manager', 'license'))->with([
            'phpversion' => version_compare(PHP_VERSION, config('custom.php_recommended'), '>='),
            'failed' => null,
        ]);
    }

    public function doUpgrade(Request $request)
    {
        $manager = new UpgradeManager();
        $failed = $manager->test();

        if (!empty($failed)) {
            if ($request->ajax() || $request->expectsJson()) {
                return response()->json([
                    'status' => 'error',
                    'step' => 'apply',
                    'message' => trans('refactor/admin_settings.upgrade.cannot_write'),
                    'failed' => array_values($failed),
                ], 400);
            }

            $license = LicenseHelper::getCurrentLicense();
            $settings = Setting::getAll();
            $tab = 'upgrade';

            return view('refactor.pages.admin.settings.upgrade', compact('settings', 'tab', 'manager', 'license', 'failed'))->with([
                'phpversion' => version_compare(PHP_VERSION, config('custom.php_recommended'), '>='),
            ]);
        }

        try {
            $manager->run();
        } catch (\Throwable $e) {
            Log::error('Upgrade apply failed: ' . $e->getMessage());

            if ($request->ajax() || $request->expectsJson()) {
                return response()->json([
                    'status' => 'error',
                    'step' => 'apply',
                    'message' => $e->getMessage(),
                ], 500);
            }

            $request->session()->flash('alert-error', $e->getMessage());
            return redirect()->route('refactor.admin.settings.upgrade');
        }

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

        if ($request->ajax() || $request->expectsJson()) {
            return response()->json([
                'status' => 'success',
                'step' => 'apply',
            ]);
        }

        $pageUrl = url('/migrate/run');
        echo '<html><head><meta http-equiv="refresh" content="3;'.$pageUrl.'" /><title>Upgrading...</title></head><body>Upgrade is in progress, please wait...</body></html>';
        return;
    }

    public function cancelUpgrade(Request $request)
    {
        try {
            $manager = new UpgradeManager();
            $manager->cleanup();
            return response()->json(['status' => 'success', 'message' => trans('refactor/admin_settings.upgrade.cancelled')]);
        } catch (\Exception $e) {
            return response()->json(['status' => 'error', 'message' => $e->getMessage()], 400);
        }
    }

    public function uploadPatch(Request $request)
    {
        if (is_null(LicenseHelper::getCurrentLicense())) {
            if ($request->ajax()) {
                return response()->json(['status' => 'error', 'message' => trans('refactor/admin_settings.upgrade.license_required')], 400);
            }
            $request->session()->flash('alert-error', trans('refactor/admin_settings.upgrade.license_required'));
            return redirect()->route('refactor.admin.settings.upgrade');
        }

        try {
            $manager = new UpgradeManager();
            $request->file('file')->move(storage_path('tmp'), $request->file('file')->getClientOriginalName());
            $path = storage_path('tmp/' . $request->file('file')->getClientOriginalName());
            $manager->load($path);

            app(Notifier::class)->dispatch(new UpgradePatchAvailable(
                newVersion: (string) $manager->getNewVersion(),
                currentVersion: (string) $manager->getCurrentVersion(),
            ));

            if ($request->ajax()) {
                return response()->json([
                    'status' => 'success',
                    'message' => trans('refactor/admin_settings.upgrade.upload_success'),
                    'attachment' => [
                        'uid' => uniqid(),
                        'name' => $request->file('file')->getClientOriginalName(),
                        'size' => 0,
                        'mime_type' => 'application/zip',
                    ],
                ]);
            }

            $request->session()->flash('alert-success', trans('messages.upgrade.alert.upload_success'));
        } catch (\Exception $e) {
            Log::info('Upgrade failed. ' . $e->getMessage());

            if ($request->ajax()) {
                return response()->json(['status' => 'error', 'message' => $e->getMessage()], 400);
            }

            $request->session()->flash('alert-error', $e->getMessage());
        }

        return redirect()->route('refactor.admin.settings.upgrade');
    }

    public function downloadPatchFromUrl(Request $request)
    {
        if (is_null(LicenseHelper::getCurrentLicense())) {
            return response()->json(['status' => 'error', 'message' => trans('refactor/admin_settings.upgrade.license_required')], 400);
        }

        $url = $request->input('url');
        if (empty($url) || !filter_var($url, FILTER_VALIDATE_URL)) {
            return response()->json(['status' => 'error', 'message' => trans('refactor/admin_settings.upgrade.invalid_url')], 400);
        }

        // Only allow http/https
        $scheme = parse_url($url, PHP_URL_SCHEME);
        if (!in_array($scheme, ['http', 'https'])) {
            return response()->json(['status' => 'error', 'message' => trans('refactor/admin_settings.upgrade.invalid_url')], 400);
        }

        // Patch files can be up to 200MB — allow enough time for download + extract
        set_time_limit(600);

        try {
            $filename = basename(parse_url($url, PHP_URL_PATH)) ?: 'patch.zip';
            // Ensure .zip extension
            if (!str_ends_with(strtolower($filename), '.zip')) {
                $filename .= '.zip';
            }

            $tmpPath = storage_path('tmp/' . $filename);

            $manager = new UpgradeManager();
            $manager->downloadPatchTo($url, $tmpPath, ['timeout' => 600]);
            $manager->load($tmpPath);

            app(Notifier::class)->dispatch(new UpgradePatchAvailable(
                newVersion: (string) $manager->getNewVersion(),
                currentVersion: (string) $manager->getCurrentVersion(),
            ));

            return response()->json([
                'status' => 'success',
                'message' => trans('refactor/admin_settings.upgrade.download_success'),
            ]);
        } catch (\Exception $e) {
            Log::info('Upgrade download from URL failed. ' . $e->getMessage());
            return response()->json(['status' => 'error', 'message' => $e->getMessage()], 400);
        }
    }

    public function payment(Request $request)
    {
        if ($request->user()->admin->getPermission('setting_general') != 'yes') {
            return $this->notAuthorized();
        }

        if ($request->isMethod('post')) {
            $data = $request->isJson() ? $request->except(['_token']) : $request->input('settings', $request->except(['_token']));

            foreach ($data as $name => $value) {
                if (!is_array($value)) {
                    Setting::set($name, $value);
                }
            }

            if ($request->ajax()) {
                return response()->json(['status' => 'success', 'message' => trans('refactor/admin_settings.flash.saved')]);
            }

            $request->session()->flash('alert-success', trans('refactor/admin_settings.flash.saved'));
            return redirect()->route('refactor.admin.settings.payment');
        }

        $settings = Setting::getAll();
        $tab = 'payment';

        return view('refactor.pages.admin.settings.payment', compact('settings', 'tab'));
    }

    public function logs(Request $request)
    {
        $logFile = storage_path('logs/laravel.log');
        $error_logs = '';

        if (file_exists($logFile)) {
            $file = file($logFile);
            $lines = 300;
            for ($i = max(0, count($file) - $lines); $i < count($file); ++$i) {
                $error_logs .= $file[$i];
            }
        }

        $settings = Setting::getAll();
        $tab = 'logs';

        return view('refactor.pages.admin.settings.logs', compact('settings', 'tab', 'error_logs'));
    }
}