<?php

/** ******************************************
 * LiteSpeed Web Server Plugin for WHM
 *
 * @author: LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
 * @copyright: (c) 2013-2020
 * ******************************************* */

namespace LsPanel;

use \Lsc\Wp\WPInstallStorage;
use \LsPanel\WhmMod_LiteSpeed_CPanelConf as CPanelConf;

class WhmMod_LiteSpeed_View
{

    private $icons;
    public static $isDone = false;

    public function __construct()
    {
        define('CP_TOKEN', $_ENV['cp_security_token']);
        define('MODULE_URL', '/cgi/lsws/');

        $this->css = array(
            'ie6' => '/themes/x/ie6.css'
        );

        $this->icons = array(
            'm_logo_lsws' => 'static/icons/Logo_centered.svg',
            'm_server_version' => 'static/icons/lsCurrentVersion.svg',
            'm_server_install' => 'static/icons/install.png',
            'm_server_php' => 'static/icons/suexec_conf.svg',
            'm_server_buildphp' => 'static/icons/buildMatchingLSPHP.svg',
            'm_server_definehome' => 'static/icons/lsws-home.png',
            'm_server_uninstall' => 'static/icons/uninstall.svg',
            'm_cache_root_setup' => 'static/icons/cacheRootSetup.svg',
            'm_cache_manage' => 'static/icons/manageCacheInstallations.svg',
            'm_cache_mass_op' => 'static/icons/massEnableDisableCache.svg',
            'm_cache_ver_manage' => 'static/icons/lscwpCurrentVersion.svg',
            'm_dash_notifier' => 'static/icons/wpNotifier.svg',
            'm_control_config' => 'static/icons/lsConfiguration.svg',
            'm_control_config_suexec' => 'static/icons/suexec_conf.svg',
            'm_control_restart' => 'static/icons/restartLs.svg',
            'm_control_restart_php' => 'static/icons/restartDetachedPHP.svg',
            'm_license_check' => 'static/icons/licenseStatus.svg',
            'm_license_change' => 'static/icons/changeLicense.svg',
            'm_license_transfer' => 'static/icons/transferLicense.svg',
            'm_switch_apache' => 'static/icons/switchToApache.svg',
            'm_switch_lsws' => 'static/icons/switchToLiteSpeed.svg',
            'm_switch_port' => 'static/icons/changePortOffset.svg',
            'm_cpanel_install' => 'static/icons/cPanelInstall.png',
            'm_cpanel_uninstall' => 'static/icons/cPanelUninstall.png',
            'm_cpanel_settings' => 'static/icons/cPanelSettings.png',
        );
    }

    public function PageHeader( $do )
    {
        $buf = <<<EEN
<html>
  <head>
    <title>LiteSpeed Web Server - WHM Plugin</title>
    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <!--[if lt IE 7]>
      <link rel="stylesheet" href="{$this->css['ie6']}" />
    <![endif]-->
    <!--[if IE]>
      <style type="text/css">
        h3{font-size:11px;}
      </style>
    <![endif]-->
  </head>
  <body>
    <div id="lsws-container">
      <form name="lswsform">
        <input type="hidden" name="step" value="1"/>
        <input type="hidden" name="do" value="{$do}"/>
EEN;
        echo $buf;
    }

    public function PageFooter()
    {
        echo "</form></div></body><!--BeGPL.com's Note: If you did not purchased from us the licensing system will not work at all even if you have source code provided by the leachers, the official versions of Syslic, GBLicense v15, and CPS (Scam), are avaliable at BeGPL only. Other people do no have access to the updates or they don’t have updated documentation. We provide free weekly updates on the source code and documentation.--></html>\n";
    }

    private function tool_list_block( $list )
    {
        $buf = '<div class="tools-list">';

        foreach ( $list as $li ) {
            $buf .= '<div class="item" role="page"><a class="item-link" ';

            if ( $li['link'] ) {
                $buf .= "href=\"{$li['link']}\" ";
            }

            if ( substr($li['link'], 0, 4) == 'http' ) {
                $buf .= 'target="_blank" rel="noopener noreferrer" ';
            }

            $buf .= 'title="';

            $buf .= ($li['info'] != '') ? $li['info'] : $li['name'];

            $buf .= '">';

            if ( $li['icon'] != '' ) {
                $buf .= "<img class=\"itemImageWrapper\" src=\"{$li['icon']}\"></img>";
            }

            $buf .= "<span class=\"itemTextWrapper\">{$li['name']}</span></a></div>";
        }

        $buf .= "</div>\n";

        return $buf;
    }

    public function MainMenu( $info )
    {
        $buf = '<div id="heading"><div class="center"><img class="header-logo" '
                . 'alt="LiteSpeed Web Server" '
                . "src=\"{$this->icons['m_logo_lsws']}\" "
                . 'onclick="window.open(\'https://www.litespeedtech.com\')" >'
                . '</div></div>';

        if ( $info['latest_whm_plugin_ver'] != WhmMod_LiteSpeed_ControlApp::MODULE_VERSION ) {
            $buf .= $this->info_msg(
                'LiteSpeed Web Server WHM plugin v'
                    . $info['latest_whm_plugin_ver'] . ' is available. '
                    . "<a href =\"?do=updateWhmPlugin\">Update Now</a>"
            );
        }

        $buf .= $this->show_running_status($info);

        if ( $info['spool_warning'] == true ) {
            $buf .= $this->getSpoolWarning();
        }

        $buf .= $this->checkFileProtectStatus($info['file_protect_warning']);

        if ( isset($info['timezonedb_warning']) ) {
            $buf .= $this->checkTimezoneDBStatus($info['timezonedb_warning']);
        }

        if ( isset($info['data_file_error']) ) {
            $buf .= $this->checkDataFile($info['data_file_error']);
        }

        $buf .= '<div>';

        if ( $info['is_installed'] ) {

            $buf .= $this->section_title('Manage LiteSpeed Web Server');
            $list = array();

            $li_version = array(
                'icon' => $this->icons['m_server_version'],
                'link' => '?do=versionManager',
                'name' => "Current Version: {$info['lsws_version']}",
                'info' => 'Version Management: upgrade/downgrade/force '
                        . 'reinstall.'
            );

            if ( !empty($info['lsws_build']) ) {
                $li_version['name'] .= " (build {$info['lsws_build']})";
            }

            $li_version['name'] .= '<div class="release-alert small red">';

            if ( !empty($info['new_build']) ) {
                $li_version['name'] .=
                        "<span>Latest Build: {$info['new_build']}</span><br />";
            }

            if ( $info['new_version'] != ''
                    && $info['new_version'] != $info['lsws_version'] ) {

                $li_version['name'] .=
                        "<span>Latest Release: {$info['new_version']}</span>";
            }

            $li_version['name'] .= '</div>';

            $list[] = $li_version;

            $list[] = array(
                'icon' => $this->icons['m_control_config'],
                'link' => '?do=config_lsws',
                'name' => 'LiteSpeed Configuration',
                'info' => 'Configure LiteSpeed settings.'
            );

            $list[] = array(
                'icon' => $this->icons['m_control_restart'],
                'link' => '?do=restart_lsws',
                'name' => 'Restart LiteSpeed',
                'info' => 'Gracefully restart LiteSpeed.'
            );

            $list[] = array(
                'icon' => $this->icons['m_control_restart_php'],
                'link' => '?do=restart_detached_php',
                'name' => 'Restart Detached PHP Processes.',
                'info' => ''
            );


            $buf .= $this->tool_list_block($list);

            $cache_check = $manage_link = $massEnableDisable_link
                    = $verManager_link = '';

            if ( $info['has_cache'] == WhmMod_LiteSpeed_Util::LSCACHE_STATUS_UNKNOWN ) {
                $cache_check =
                    '(Please start LiteSpeed to access these features)';
            }
            elseif ( $info['has_cache'] == WhmMod_LiteSpeed_Util::LSCACHE_STATUS_MISSING ) {
                $cache_check = '(This feature requires '
                        . '<a href="https://www.litespeedtech.com/support/wiki/doku.php/litespeed_wiki:licenses:add-lscache" '
                        . 'target="_blank" '
                        . 'rel="noopener noreferrer">LSCache</a>)';
            }
            elseif ( $info['has_cache'] == WhmMod_LiteSpeed_Util::LSCACHE_STATUS_DETECTED ) {
                $manage_link = '?do=lscwp_manage';
                $massEnableDisable_link = '?do=lscwp_mass_enable_disable';
                $verManager_link = '?do=lscwpVersionManager';
            }

            if ( $info['has_cache'] != WhmMod_LiteSpeed_Util::LSCACHE_STATUS_NOT_SUPPORTED ) {
                $title = 'LiteSpeed Cache For WordPress Management '
                        . $cache_check;

                $buf .= $this->section_title($title);
                $list = array();

                $list[] = array(
                    'icon' => $this->icons['m_cache_manage'],
                    'link' => $manage_link,
                    'name' => 'Manage Cache Installations',
                    'info' => 'Enable/Disable cache or set a flag for known '
                            . 'WordPress installations.'
                );

                $list[] = array(
                    'icon' => $this->icons['m_cache_mass_op'],
                    'link' => $massEnableDisable_link,
                    'name' => 'Mass Enable/Disable Cache',
                    'info' => 'Enable/Disable cache for all non-flagged '
                            . 'WordPress installations'
                );

                $ver_mgr = array(
                    'icon' => $this->icons['m_cache_ver_manage'],
                    'link' => $verManager_link,
                    'info' => 'Change active cache plugin version or force a '
                            . 'version change for existing installations.'
                );

                if ( $info['lscwp_curr_ver'] == false ) {
                    $ver_mgr['name'] = 'LSCWP Version Manager';
                }
                else {
                    $ver_mgr['name'] = 'Current Version: '
                            . htmlspecialchars($info['lscwp_curr_ver']);

                    if ( $info['lscwp_latest'] != false
                            && $info['lscwp_latest'] != $info['lscwp_curr_ver'] ) {

                        $ver_mgr['name'] .= '<br /><span class="small red">'
                                . 'Latest Release: '
                                . htmlspecialchars($info['lscwp_latest'])
                                . '</span>';
                    }
                }

                $list[] = $ver_mgr;

                $list[] = array(
                    'icon' => $this->icons['m_dash_notifier'],
                    'link' => '?do=dash_notifier',
                    'name' => 'WordPress Dash Notifier',
                    'info' => 'Recommend a plugin or broadcast a message to '
                            . 'all discovered WordPress installations.'
                );

                $list[] = array(
                    'icon' => WhmMod_LiteSpeed_ControlApp::ICON_DIR
                            . '/quicCloudIps.svg',
                    'link' => '?do=quicCloudIps',
                    'name' => 'QUIC.cloud IPs',
                    'info' => 'View QUIC.cloud related IPs.'
                );

                $buf .= $this->tool_list_block($list);
            }

            $buf .= $this->section_title('License Management');
            $list = array();

            if ($info['serial'] == 'TRIAL') {
                $serial = 'LSWS-712807uNavy';
            }
            else {
                $serial = $info['serial'];
            }

            $list[] = array(
                'icon' => $this->icons['m_license_check'],
                'link' => '?do=check_license',
                'name' => 'License Status <br/>'
                        . "<span class=\"small cornflower-blue\">{$serial}"
                        . '</span>',
                'info' => 'Check/Refresh current license.'
            );

            $list[] = array(
                'icon' => $this->icons['m_license_change'],
                'link' => '?do=change_license',
                'name' => 'Change License',
                'info' => 'Switch to another license.'
            );

            if ( $info['serial'] != 'LSWS-712807uNavy' ) {

                $list[] = array(
                    'icon' => $this->icons['m_license_transfer'],
                    'link' => '?do=transfer_license',
                    'name' => 'Transfer License',
                    'info' => 'Start license migration. Frees license for '
                            . 'registration on another server while leaving '
                            . 'license active on the current server for a '
                            . 'limited time.'
                );
            }

            $buf .= $this->tool_list_block($list);

            $buf .= $this->section_title('Switch between Apache and LiteSpeed');
            $list = array();

            $list[] = array(
                'icon' => $this->icons['m_switch_apache'],
                'link' => '?do=switch_apache',
                'name' => 'Switch to Apache',
                'info' => 'Use Apache as main web server. This will update rc '
                        . 'scripts.'
            );

            $list[] = array(
                'icon' => $this->icons['m_switch_lsws'],
                'link' => '?do=switch_lsws',
                'name' => 'Switch to LiteSpeed',
                'info' => 'Use LiteSpeed as main web server. This will update '
                        . 'rc scripts.'
            );

            $list[] = array(
                'icon' => $this->icons['m_switch_port'],
                'link' => '?do=change_port_offset',
                'name' => 'Change Port Offset',
                'info' => "LiteSpeed port offset is {$info['port_offset']}. "
                        . 'This allows LiteSpeed and Apache to run in parallel.'
            );

            $buf .= $this->tool_list_block($list);

            $buf .= $this->section_title('cPanel Plugin');
            $list = array();

            $list[] = array(
                'icon' => $this->icons['m_cpanel_settings'],
                'link' => '?do=cpanel_settings',
                'name' => 'Settings',
                'info' => 'LiteSpeed cPanel Plugin settings.'
            );

            if ( $info['cpanel_plugin_installed'] ) {

                $list[] = array(
                    'icon' => $this->icons['m_cpanel_uninstall'],
                    'link' => '?do=cpanel_uninstall',
                    'name' => 'Uninstall',
                    'info' => 'Uninstall the LiteSpeed cPanel Plugin.'
                );
            }
            else {

                $list[] = array(
                    'icon' => $this->icons['m_cpanel_install'],
                    'link' => '?do=cpanel_install',
                    'name' => 'Install',
                    'info' => 'Install the LiteSpeed cPanel Plugin.'
                );
            }

            $buf .= $this->tool_list_block($list);
        }
        else {
            $buf .= $this->section_title('Install LiteSpeed Web Server');
            $list = array();

            $list[] = array(
                'icon' => $this->icons['m_server_install'],
                'link' => '?do=install_lsws',
                'name' => 'Install LiteSpeed Web Server',
                'info' => 'Download and install the latest stable release.'
            );

            $list[] = array(
                'icon' => $this->icons['m_server_definehome'],
                'link' => '?do=define_home',
                'name' => 'Define LSWS_HOME',
                'info' => 'If you installed LiteSpeed Web Server before '
                        . 'installing this plugin, please specify your '
                        . 'LSWS_HOME direcotry before using the plugin.'
            );

            $buf .= $this->tool_list_block($list);
        }

        $buf .= '<p id="info-tag">This plugin is developed by LiteSpeed '
                . 'Technologies.<br />LiteSpeed Web Server Plugin for WHM '
                . '<a href="https://www.litespeedtech.com/products/litespeed-web-server/control-panel-plugins/release-log" '
                . 'title="Release Log" target="_blank" '
                . 'rel="noopener norefferer">v'
                . WhmMod_LiteSpeed_ControlApp::MODULE_VERSION . '</a></p>'
                . '</div>';

        echo $buf;
    }

    public function RestartLswsConfirm( $info )
    {
        $buf = $this->screen_title('Confirm Operation... Restart LiteSpeed',
                $this->icons['m_control_restart']);

        $buf .= $this->show_running_status($info);

        if ( $info['spool_warning'] == true ) {
            $buf .= $this->getSpoolWarning();
        }

        $goNext = 'Restart';

        $msg = array();

        if ( $info['port_offset'] != 0 ) {
            $msg[] = "Apache port offset is {$info['port_offset']}.";
            $msg[] = 'LiteSpeed will be running in parallel with Apache. When you are ready to '
                    . 'replace Apache with LiteSpeed, use the <b>Switch to LiteSpeed</b> option.';
        }

        if ( $info['ap_pid'] > 0 && $info['port_offset'] == 0 ) {
            /**
             * use switch no matter lsws run or not
             */
            $msg[] = 'Apache port offset is 0. If you wish to use LiteSpeed as your main web server, '
                    . 'please use the <b>Switch to LiteSpeed</b> option.';
            $msg[] = 'If you need to run LiteSpeed in parallel with Apache, please use the '
                    . '<b>Change Port Offset</b> option.';
            $goNext = NULL;
        }
        else {
            $msg[] = 'This will do a graceful restart of LiteSpeed Web Server.';
        }

        $buf .= $this->div_p_msg($msg);
        $buf .= $this->button_panel_back_next('Cancel', $goNext);

        echo $buf;
    }

    public function RestartLsws( $info )
    {
        $buf = $this->screen_title('Restart LiteSpeed', $this->icons['m_control_restart']);
        $buf .= $this->show_running_status($info);

        if ( $info['spool_warning'] == true ) {
            $buf .= $this->getSpoolWarning();
        }

        if ( $info['ls_pid'] > 0 ) {
            $buf .= $this->success_msg('LiteSpeed restarted successfully.');
        }
        else {
            $buf .= $this->error_msg($info['output'],
                    'LiteSpeed is not running! Please check the web server log file for errors.');
        }

        $buf .= $this->button_panel_back_next('OK');

        echo $buf;
    }

    private function extractMsgs( $msgs )
    {
        $buf = '';

        if ( !empty($msgs['succ']) ) {
            $buf .= $this->success_msg($msgs['succ']);
        }

        if ( !empty($msgs['warn']) ) {
            $buf .= $this->warning_msg($msgs['warn']);
        }

        if ( !empty($msgs['err']) ) {
            $buf .= $this->warning_msg($msgs['err']);
        }

        return $buf;
    }

    public function TimezoneDBResults( $action, $msgs )
    {
        $title = '';

        if ( $action == 'install' ) {
            $title = 'Install Missing TimezoneDB Extensions';
        }
        elseif ( $action == 'upgrade' ) {
            $title = 'Update TimezoneDB Extensions';
        }

        $buf = $this->screen_title($title, $this->icons['m_server_php']);

        $buf .= $this->extractMsgs($msgs);

        $buf .= $this->button_panel_back_next('OK');

        echo $buf;
    }

    public function TimezoneDBConfirm( $action )
    {
        $buf = '';
        $msg = array();

        if ( $action == 'install' ) {
            $title = 'Confirm Operation... Install Missing TimezoneDB Extensions';

            $buf = $this->screen_title($title, $this->icons['m_server_php']);

            $msg[] = 'Some pre-built EasyApache PHP installations may be missing the '
                    . 'timezoneDB extension. This will severely impact PHP performance.';

            $msg[] = 'By confirming below, the missing timezoneDB extensions will be added to your '
                    . 'EasyApache PHP installations automatically. Any existing timezoneDB '
                    . 'extensions will be updated to the latest version if a newer version is available';
        }
        elseif ( $action == 'update' ) {
            $buf = $this->screen_title('Confirm Operation... Update TimezoneDB Extensions',
                    $this->icons['m_server_php']);

            $msg[] = 'Update detected for installed EasyApache PHP timezoneDB extension(s).';

            $msg[] = 'By confirming below, all timezoneDB extensions will be updated to the '
                    . 'latest versions automatically.';
        }

        $buf .= $this->info_msg($msg);
        $buf .= $this->button_panel_back_next('Cancel', 'Confirm');

        echo $buf;
    }

    public function Switch2LswsConfirm( $info )
    {
        $buf = $this->screen_title('Confirm Operation... Switch to LiteSpeed',
                $this->icons['m_switch_lsws']);
        $buf .= $this->show_running_status($info);

        if ( $info['spool_warning'] == true ) {
            $buf .= $this->getSpoolWarning();
        }

        if ( $info['stop_msg'] != NULL ) {
            $buf .= $this->error_msg($info['stop_msg']);
            $buf .= $this->button_panel_back_next('OK');
        }
        else {
            $msg = array();

            if ( $info['ap_pid'] > 0 ) {
                $msg[] = 'This action will stop Apache and restart LiteSpeed as the main web server. '
                        . 'It may take a little while for Apache to stop completely.';
            }

            if ( $info['port_offset'] != 0 ) {
                $warn = "Apache port offset is {$info['port_offset']}. This action will change port "
                        . "offset to 0.";
                $buf .= $this->warning_msg($warn);
            }

            $msg[] = 'This will restart <strong>LiteSpeed as main web server</strong>!';

            $buf .= $this->div_p_msg($msg);
            $buf .= $this->button_panel_back_next('Cancel', 'Switch to LiteSpeed');
        }

        echo $buf;
    }

    public function Switch2Lsws( $info )
    {
        $buf = $this->screen_title('Switch To LiteSpeed', $this->icons['m_switch_lsws']);
        $buf .= $this->show_running_status($info);

        if ( $info['spool_warning'] == true ) {
            $buf .= $this->getSpoolWarning();
        }

        if ( $info['stop_msg'] != NULL ) {
            $buf .= $this->error_msg($info['stop_msg']);
        }
        else {
            $out = $info['output'];

            if ( $info['port_offset'] != 0 ) {
                $out[] = 'Failed to set Apache port offset to 0. Please check config file permissions.';
            }
            else {
                $out[] = 'Apache port offset has been set to 0.';
            }

            if ( $info['ls_pid'] > 0 ) {
                $buf .= $this->success_msg($out, 'Switched to LiteSpeed Successfully');
            }
            else {
                $buf .= $this->error_msg($out, 'Failed to bring up LiteSpeed');
            }
        }

        $buf .= $this->button_panel_back_next('OK');

        echo $buf;
    }

    public function Switch2ApacheConfirm( $info )
    {
        $buf = $this->screen_title('Confirm Operation... Switch to Apache',
                $this->icons['m_switch_apache']);
        $buf .= $this->show_running_status($info);

        if ( $info['spool_warning'] == true ) {
            $buf .= $this->getSpoolWarning();
        }

        if ( $info['stop_msg'] != NULL ) {
            $buf .= $this->error_msg($info['stop_msg']);
            $buf .= $this->button_panel_back_next('OK');
        }
        else {

            $msg = array();

            if ( $info['ls_pid'] > 0 ) {
                $msg[] = 'This action will stop LiteSpeed and restart Apache as the main web server. '
                        . 'It may take a little while for LiteSpeed to stop completely.';
            }

            $msg[] = 'This will restart <strong>Apache as main web server</strong>!';
            $buf .= $this->div_p_msg($msg);
            $buf .= $this->button_panel_back_next('Cancel', 'Switch to Apache');
        }

        echo $buf;
    }

    public function Switch2Apache( $info )
    {
        $buf = $this->screen_title('Switch To Apache', $this->icons['m_switch_apache']);
        $buf .= $this->show_running_status($info);

        if ( $info['spool_warning'] == true ) {
            $buf .= $this->getSpoolWarning();
        }

        if ( $info['stop_msg'] != NULL ) {
            $buf .= $this->error_msg($info['stop_msg']);
        }
        else {

            if ( $info['return'] != 0 ) {
                $buf .= $this->info_msg($info['output']);

                $msg = array();

                $msg[] = 'This may be due to a configuration error. To manually check this problem, '
                        . 'please ssh to your server.';
                $msg[] = 'Use the following steps to manually switch to Apache:';
                $msg[] = 'Stop LiteSpeed if lshttpd still running: <code>pkill -9 litespeed </code>';
                $msg[] = 'Restore Apache httpd if /usr/sbin/httpd_ls_bak exists: '
                        . '<code>mv -f /usr/sbin/httpd_ls_bak /usr/sbin/httpd</code>';
                $msg[] = 'Run the Apache restart command manually: '
                        . '<code>service httpd restart</code> and check for errors.';
                $buf .= $this->error_msg($msg, 'Failed to switch to Apache');
            }
            else {
                $buf .= $this->success_msg($info['output'],
                        'Switched to Apache Successfully');
            }
        }

        $buf .= $this->button_panel_back_next('OK');

        echo $buf;
    }

    public function ChangePortOffsetConfirm( $info )
    {
        $buf = $this->screen_title('Confirm Operation... Change LiteSpeed Port Offset',
                $this->icons['m_switch_port']);
        $buf .= $this->show_running_status($info);

        if ( $info['spool_warning'] == true ) {
            $buf .= $this->getSpoolWarning();
        }

        $buf .= '<div class="indent-box"><div class="hint"><p>Port offset allows you to run Apache '
                . 'and LiteSpeed in parallel by running LiteSpeed on a separate port.</p><p>For '
                . 'example, if Apache is running on port 80 and the LiteSpeed port offset is 2000, then '
                . 'you will be able to access LiteSpeed-powered web pages on port 2080.</p></div>'
                . '</div>';

        $warn = array();

        if ( $info['port_offset'] == 0 && $info['ap_pid'] == 0 ) {
            $warn[] = 'Apache is currently not running. We suggest your first <strong>switch to '
                    . 'Apache </strong> to avoid server down time.';
        }

        $buf .= $this->warning_msg($warn);

        $buf .= $this->section_title('Change Port Offset');

        $hint = "Current Port Offset is {$info['port_offset']}.";
        $input = $this->input_text('port_offset', $info['new_port_offset']);
        $buf .= $this->form_row_box('Set new port offset', $input, $info['error'], $hint);

        $buf .= $this->button_panel_back_next('Cancel', 'Change');

        echo $buf;
    }

    public function ChangePortOffset( $info )
    {
        $buf = $this->screen_title('Change LiteSpeed Port Offset',
                $this->icons['m_switch_port']);

        if ( $info['return'] != 0 ) {
            $buf .= $this->error_msg($info['output'], 'Failed to Change Port Offset');
        }
        else {
            $msg = "Port offset has been changed to {$info['new_port_offset']}.";

            $buf .= $this->success_msg($msg, 'Saved New Port Offset');
        }

        $buf .= $this->button_panel_back_next('OK');

        echo $buf;
    }

    public function cpanelInstallConfirm()
    {
        $title = $this->screen_title('Confirm Operation... Install LiteSpeed cPanel Plugin',
                $this->icons['m_cpanel_install']);

        $backBtn = $this->button_panel_back_next('Cancel', 'Install');

        $buf = <<<EOF
{$title}
<p>
  Install the LiteSpeed Web Cache Manager Plugin for cPanel.
  <br />
  <small>* This operation will automatically turn on the cPanel Plugin "Auto Install" setting.</small>
</p>
<h2>What Does It Do?</h2>
<p style="max-width: 760px;">
  The LiteSpeed Web Cache Manager facilitates the installation and management of LSCache plugins across
  all supported CMS sites. Sites with LSCache plugins installed have access to easy cache management
  tools, public and private cache, tag-based sma