%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /usr/local/prospamfilter/library/Installer/
Upload File :
Create Path :
Current File : //usr/local/prospamfilter/library/Installer/Installer.php

<?php

class Installer_Installer
{
    const API_TOKEN_ID = 'prospamfilter';

    /**
     * @var Filesystem_AbstractFilesystem
     */
    protected $filesystem;

    /**
     * @var Installer_InstallPaths
     */
    protected $paths;

    /**
     * @var SpamFilter_PanelSupport_Cpanel
     */
    protected $panelSupport;

    /**
     * @var SpamFilter_Logger
     */
    protected $logger;

    /**
     * @var string
     */
    protected $currentVersion;

    /**
     * @var Output_OutputInterface
     */
    protected $output;

    public function __construct(Installer_InstallPaths $paths, Filesystem_AbstractFilesystem $filesystem, Output_OutputInterface $output)
    {
        $this->output = $output;
        $this->filesystem = $filesystem;
        $this->paths = $paths;
        $this->logger = Zend_Registry::get('logger');
        $this->findCurrentVersionAndInitPanelSupport();
    }

    /**
     * Install prospamfilter for CPanel
     */
    public function install()
    {
        try {
            $this->doInstall();
        } catch (Exception $exception) {
            $this->output->error($exception->getMessage());
            $this->logger->debug($exception->getMessage());
            $this->logger->debug($exception->getTraceAsString());
        }
    }

    private function doInstall()
    {
        $this->outputInstallStartMessage('cpanel');
        $this->upgrade();

        $this->checkRequirementsAreMet();
        $this->checkUserIsRoot();
        $this->checkOldVersionIsUninstalled();

        $this->checkOldConfigurationFile();
        $this->cleanupOldPluginDynamicUi();

        if (! $this->panelSupport->minVerCheck()) {
            $this->output->error("The currently used version of your controlpanel doesn't match minimum requirement.");
            exit(1);
        }

        $this->copyFilesToDestination();
        $this->changeDestinationPermissions();

        $this->setupConfigDirectory();

        $this->warnAboutUpgradeTier();
        $this->removeOldVersion();
        $this->symlinkAddonToWebDirs();
        $this->generateConfigurationFile();

        // Brand regeneration, since it may have been replaced and should not be default :-)
        $this->output->info("Generating cPanel plugin configuration..");
        $this->configureBranding();

        $this->output->info("Registering hooks ...");
        $hooks = array(
            'file' => $this->paths->destination . '/bin/hook.php',
            'do' => 'add',
            'hooks' => SpamFilter_PanelSupport_Cpanel::getHooksList()
        );
        $this->panelSupport->manageHooks($hooks);
        $this->output->ok("Done.");

        $this->registerWhmAppInAppConfig();
        $this->registerCpanelAppInAppConfig();

        /** @see https://trac.spamexperts.com/ticket/21395#comment:18 */
        if (file_exists('/usr/local/cpanel/whostmgr/addonfeatures/prospamfilter3')) {
            unlink('/usr/local/cpanel/whostmgr/addonfeatures/prospamfilter3');
        }

        file_put_contents('/usr/local/cpanel/whostmgr/addonfeatures/prospamfilter', 'prospamfilter:SpamExperts');

        $this->setUpApiTokens();
        $this->setUpdateCronjob();
        $this->setupSuidPermissions();
        $this->removeMigrationFiles($this->currentVersion);
        $this->removeSrcFolder();
        $this->removeInstallFileAndDisplaySuccessMessage();
    }

    private function setUpApiTokens() {
        $accessTokenFile = "/root/.accesstoken";
        if (!file_exists($accessTokenFile) || !(trim(file_get_contents($accessTokenFile)))) {
            $this->createApiAuthToken($accessTokenFile);
        } else {
            $jsonOutput = shell_exec("/usr/sbin/whmapi1 api_token_list --output=json");
            $tokensInfo = json_decode($jsonOutput, true);
            if (empty($tokensInfo['data']['tokens'][self::API_TOKEN_ID]['acls']['all'])) {
                shell_exec("/usr/sbin/whmapi1 api_token_revoke token_name=" . self::API_TOKEN_ID);
                $this->createApiAuthToken($accessTokenFile);
            }

            $this->logger->debug("Access token for WHM API already exists and has correct permissions, skipping step.");
            $this->output->info("Access token for WHM API already exists and has correct permissions, skipping step.");
        }
    }

    private function createApiAuthToken($accessTokenFile)
    {
        $jsonOutput = shell_exec("/usr/sbin/whmapi1 api_token_create token_name=" . self::API_TOKEN_ID . " acl-1=all --output=json");
        $output = json_decode($jsonOutput, true);

        if (!empty($output['metadata'])) {
            if ($output['metadata']['reason'] != "OK") {
                $this->logger->debug("Access token couldn't be created. Reason: " . $output['metadata']['reason']);
                $this->output->error("Access token couldn't be created. Reason: " . $output['metadata']['reason']);
            } else {
                $token = $output['data']['token'];

                $accessTokenFile = fopen($accessTokenFile, "w");
                fwrite($accessTokenFile, $token);
                fclose($accessTokenFile);

                $this->logger->debug("Access token was successfully created.");
                $this->output->info("Access token was successfully created.");
            }
        } else {
            $this->logger->debug("Error when using Whm Api call. Response: " . $jsonOutput);
            $this->output->info("Error when using Whm Api call. Response: " . $jsonOutput);
        }
    }

    private function findCurrentVersionAndInitPanelSupport()
    {
        $options = array('skipapi' => true);

        if (file_exists("/usr/local/prospamfilter2/application/version.txt")) {
            $this->logger->debug("[Install] PSF2 version file exists");
            $this->currentVersion = trim(file_get_contents("/usr/local/prospamfilter2/application/version.txt"));
            if (version_compare($this->currentVersion, '3.0.0', '<')) {
                $this->logger->debug("[Install] Version is below 3.0.0");
                if (file_exists('/etc/prospamfilter2/settings.conf')) {
                    $this->logger->debug("[Install] Changing config to old");
                    $options['altconfig'] = "/etc/prospamfilter2/settings.conf";
                }
            }
        } elseif (file_exists($this->paths->destination . DS . 'application' . DS . 'version.txt')) {
            $this->logger->debug("[Install] New version file found post 3.0.0");
            $this->currentVersion = trim(file_get_contents($this->paths->destination . DS . 'application' . DS . 'version.txt'));
        } else {
            $this->logger->debug("[Install] No version file found, must be new install.");
            $this->currentVersion = null; //no version set, must be an upgrade
        }

        $this->panelSupport = new SpamFilter_PanelSupport_Cpanel($options);
    }

    protected function upgrade()
    {
        if (! $this->shouldUpgrade()) {
            return;
        }

        $this->output->info("Going to upgrade addon 2.x to 3.0.x structure...");

        if (file_exists("/usr/src/prospamfilter2")) {
            $this->output->info("Removing old source files..");
            $this->filesystem->removeDirectory("/usr/src/prospamfilter2");
        }

        // Copy config folder to unversioned one
        $this->output->info("Copying up current configuration to new location");
        smartCopy("/etc/prospamfilter2", $this->paths->config);

        // Run uninstaller for the old addon to get rid of all traces
        if (!file_exists("/usr/local/prospamfilter2/bin/uninstall.php")) {
            $this->output->error("Unable to uninstall the old version.");
            exit(1);
        } else {
            $this->output->info("Patching old uninstaller to skip confirmations..");
            system("sed -i 's/.*confirm();.*/#&/g' /usr/local/prospamfilter2/bin/uninstall.php");
            system(
                "sed -i 's/.*This program can only be ran from CLI.*/#&/g' /usr/local/prospamfilter2/bin/uninstall.php"
            );
            $this->output->info("Running uninstaller to remove old version..");

            $curdir = getcwd(); // retrieve current dir
            $this->logger->info("[Install] Current directory: {$curdir}");
            if (chdir("/usr/local/prospamfilter2/bin/")) {
                $this->logger->info("[Install] Moved into /usr/local/prospamfilter2/bin");
                $lastline = system("./uninstall.php >/tmp/upgrade_psf 2>&1", $return_var); // run
                $this->logger->info("[Install] Uninstaller last line: {$lastline}");
                chdir($curdir); // Change back to previous directory
                $this->logger->info("[Install] Changed back to {$curdir}");
                $this->output->info("Removal of addon completed with exitcode: {$return_var}.");
            } else {
                $this->output->error("Cannot run uninstaller, directory does not exist or incorrect permissions.");
                exit(1);
            }
        }

        clearstatcache(); // Clear cache just to be sure
        if (file_exists("/usr/local/prospamfilter2/bin/uninstall.php")) {
            // Crap, that file should no longer exist
            $this->output->error("Old version was not uninstalled properly. This may lead to issues.");
            exit(1);
        }

        // Remove leftover from partially integrated feature.
        if (file_exists("/usr/local/cpanel/hooks/email/setmxcheck")) {
            unlink("/usr/local/cpanel/hooks/email/setmxcheck");
        }

        // Create a dummy page to redirect the user to in case the updater reloads

        $this->logger->debug("[Install] Going to create backwards compatibility support file..");
        $file_content   = array();
        $file_content[] = "<?php\n";
        $file_content[] = "header( \"refresh:5;url=/cgi/addon_prospamfilter.cgi\" );\n";
        $file_content[] = 'echo "You\'ll be redirected in about 5 secs. If not, click <a href=\\"/cgi/addon_prospamfilter.cgi\\">here</a>.";' . "\n";
        $file_content[] = "?>";
        $bw_status      = file_put_contents(
            "/usr/local/cpanel/whostmgr/docroot/cgi/addon_prospamfilter2.php", $file_content
        );
        $this->logger->debug("[Install] Creating backwards compatibility file resulted in code: {$bw_status}");

        // Merge config file with apipass file
        $passfile = file_get_contents($this->paths->config . "/apipass.conf");
        if (file_put_contents($this->paths->config . "/settings.conf", $passfile, FILE_APPEND)) {
            $this->output->info("Removing old password file..");
            unlink("/etc/prospamfilter/apipass.conf");

            $this->updateSettingsFilePermissions();
        }

        // Copy branding to separate file.
        $this->output->info("Migrating branding..");
        system("egrep '(brandname|brandicon)' /etc/prospamfilter/settings.conf > /etc/prospamfilter/branding.conf");

        // Create Spampanel user (#10002)
        $this->output->info("Going to migrate API user...");

        $config = Zend_Registry::get('general_config');
        $api    = new SpamFilter_ResellerAPI;
        if ($api) {
            if (!isset($config)) {
                $this->output->error("Cannot migrate API user: Missing configuration");
            } elseif (!isset($config->apiuser)) {
                $this->output->error("Cannot migrate API user: Missing configuration: username");
            } elseif (!isset($config->apipass)) {
                $this->output->error("Cannot migrate API user: Missing configuration: password");
            } else {
                $data     = array(
                    'username'     => $config->apiuser,
                    'password'     => urlencode($config->apipass), // hopefully this works
                    'email'        => 'root@' . SpamFilter_Core::GetServerName(),
                );
                $response = $api->user()->adminadd($data);
                if ($response['status'] && $response['reason'] = "OK") {
                    $this->output->ok("The API user has been migrated");
                } else {
                    $this->output->info("API migration response: " . serialize($response));
                }
            }
        } else {
            $this->output->error("Cannot migrate API user: No API connection");
            sleep(2);
        }

        // Completed.
        $this->output->ok("Addon 2.x to 3.0 upgrade has completed succesfully.");
    }

    protected function shouldUpgrade()
    {
        if (!isset($this->currentVersion) || (empty($this->currentVersion))) {
            $this->output->info("No need to update the structure of the addon, there is no previous version.");

            return false;
        }

        if (file_exists("/usr/local/prospamfilter/application/bootstrap.php")) {
            $this->output->info("No need to update the structure of the addon, we are already past the upgrade point.");

            return false;
        }

        // Check if we are below 3.x.x
        if (!version_compare($this->currentVersion, '3.0.0', '<')) {
            $this->output->info("No need to update the structure of the addon, we are already at the correct version.");

            return false;
        }

        return true;
    }

    private function checkOldConfigurationFile()
    {
        // Before cleanup we must check there is no an old cpanelplugin file
        if (file_exists("/usr/local/prospamfilter/frontend/cpanel/cpanel11/prospamfilter.cpanelplugin")) {
            if (strstr(file_get_contents('/usr/local/prospamfilter/frontend/cpanel/cpanel11/prospamfilter.cpanelplugin'), 'name:prospamfilter3') === FALSE) {
                return;
            }

            // And unregister plugin with no valid name
            $this->output->info("Old configuration file found. Unregistering old plugin.");
            shell_exec("/usr/local/cpanel/bin/unregister_cpanelplugin /usr/local/prospamfilter/frontend/cpanel/cpanel11/prospamfilter.cpanelplugin");
            $this->output->ok("Done.");
        }

        return;
    }

    private function cleanupOldPluginDynamicUi()
    {
        // Cleanup dynamicui for old plugin
        $cPanelWebdirsRoot = '/usr/local/cpanel/base/frontend';
        foreach (scandir($cPanelWebdirsRoot) as $eachDir) {
            if (is_dir($cPanelWebdirsRoot . '/' . $eachDir)) {
                if (file_exists($cPanelWebdirsRoot . '/' . $eachDir . '/dynamicui/dynamicui_prospamfilter3.conf')) {
                    unlink($cPanelWebdirsRoot . '/' . $eachDir . '/dynamicui/dynamicui_prospamfilter3.conf');
                }
            }
        }
    }

    private function setupConfigDirectory()
    {
        $this->output->info("Prepopulating config folder");
        $this->createConfigDirectory();

        $cfgdir = $this->paths->config;
        // Settings file (world readable, root writable)
        touch("{$cfgdir}" . DS . "settings.conf");
        $this->updateSettingsFilePermissions();
        // Create branding file
        touch("{$cfgdir}" . DS . "branding.conf");

        $this->output->ok("Done");
    }

    private function createConfigDirectory()
    {
        $directory = $this->paths->config;

        if (!file_exists($directory)) {
            @mkdir("{$directory}" . DS, 0755, true);
            if (!file_exists($directory)) {
                die("[ERROR] Unable to create config folder!");
            }
        }
    }

    private function updateSettingsFilePermissions()
    {
        chown($this->paths->config . "/settings.conf", "root");
        chgrp($this->paths->config . "/settings.conf", "root");
        chmod($this->paths->config . "/settings.conf", 0660);
    }

    private function getCpanelVersion(){
        $output = shell_exec("/usr/local/cpanel/cpanel -V");
        $x = explode(" ", $output);

        return trim($x[0]);
    }

    protected function warnAboutUpgradeTier()
    {
        // Check cPanel update type and warn the user about that.
        try {
            $cpaneltier = trim(shell_exec('grep "CPANEL=" /etc/cpupdate.conf'));
            $cpaneltier = explode("=", $cpaneltier);
            if (is_array($cpaneltier)) {
                // Good, the explode worked.
                $cpaneltier = strtolower(trim($cpaneltier[1]));
                if (!in_array($cpaneltier, array('stable', 'release', 'current', 'edge'))) {
                    $this->output->warn("\n** Warning: Your cPanel product tier is set to '{$cpaneltier}'.");
                    $this->output->warn("We can only support stable product tiers, since during cPanel development changes can be introduced.");
                    $this->output->warn("The installation will proceed, but there may be unwanted sideeffects");
                    echo "\n";
                    sleep(5);
                }
            }
        } catch (Exception $e) {
            // So, reading the file failed. Not a big deal to break on.
        }
    }

    private function removeOldVersion()
    {
        // Remove old leftover from < 2.0.8
        if (file_exists("/usr/local/cpanel/whostmgr/docroot/cgi/prospamfilter.php")) {
            $this->output->info("Cleaning up old file from < 2.0.8...");
            @unlink("/usr/local/cpanel/whostmgr/docroot/cgi/prospamfilter.php");
            $this->output->ok("Done.");
            sleep(3);
        }

        // Remove old leftover from < 2.6.0
        if (file_exists("/tmp/prospamfilter2/")) {
            $this->output->info("Cleaning up old logfolder from < 2.6.0..");
            $this->filesystem->removeDirectory("/tmp/prospamfilter2");
            $this->output->ok("Done.");
        }
    }

    private function configureBranding()
    {
        $this->output->info("Configuring brand");
        // Generate this file
        $brand = new SpamFilter_Brand();
        if ($brand->hasBrandingData()) {
            $branding = array();
            $branding['brandname'] = $brand->getBrandUsed();
            $branding['brandicon'] = $brand->getBrandIcon();
            if ($this->panelSupport->setBrand($branding)) {
                $this->output->ok("Done");
            } else {
                $this->output->error("The cPanel plugin configuration could not be generated.");
            }
        } else {
            $this->output->error("The branding configuration cannot be initialized.");
        }
    }

    /**
     * @return array
     */
    private function symlinkAddonToWebDirs()
    {
        $whm_docroot = "/usr/local/cpanel/whostmgr/docroot";
        $this->output->info("Symlinking cPanel addon to webdirs");

        // Symlink cPanel indexes to webdirs.
        $cPanelWebdirsRoot = '/usr/local/cpanel/base/frontend';
        $cPanelVersion = $this->getCpanelVersion();
        foreach (scandir($cPanelWebdirsRoot) as $eachDir) {
            if (is_dir("{$cPanelWebdirsRoot}/{$eachDir}")
                && !in_array($eachDir, array('.', '..'))
                && !is_link("{$cPanelWebdirsRoot}/{$eachDir}")
            ) {
                $this->output->info("Symlinking cPanel addon to webdir {$eachDir}");
                if (in_array($eachDir, ['paper_lantern', 'jupiter']) && version_compare($cPanelVersion, '11.44.2') == 1) {
                    $ret_val = $this->filesystem->symlink(
                        "/usr/local/prospamfilter/frontend/templatetoolkit/",
                        "{$cPanelWebdirsRoot}/{$eachDir}/prospamfilter"
                    );
                } else {
                    $ret_val = $this->filesystem->symlink(
                        "/usr/local/prospamfilter/frontend/cpaneltags/",
                        "{$cPanelWebdirsRoot}/{$eachDir}/prospamfilter"
                    );
                }
                $this->logger->info("[Install] Symlinking to {$eachDir} completed: " . $ret_val);
            }
        }

        // Symlink cpanel folder to cpaneltags and templatetoolkit directories
        $ret_val = $this->filesystem->symlink(
            "/usr/local/prospamfilter/frontend/cpanel/psf.php",
            "/usr/local/prospamfilter/frontend/cpaneltags/psf.php"
        );
        $this->logger->info("[Install] Symlinking to /usr/local/prospamfilter/frontend/cpaneltags/psf.php completed: " . $ret_val);
        $ret_val = $this->filesystem->symlink(
            "/usr/local/prospamfilter/frontend/cpanel/psf.php",
            "/usr/local/prospamfilter/frontend/templatetoolkit/psf.php"
        );
        $this->logger->info("[Install] Symlinking to /usr/local/prospamfilter/frontend/templatetoolkit/psf.php completed: " . $ret_val);

        // Symlink WHM addon to CGI dir.
        $this->output->info("Symlinking WHM addon to webdir");
        $ret_val = $this->filesystem->symlink(
            "/usr/local/prospamfilter/frontend/whm/prospamfilter.php",
            $whm_docroot . "/cgi/addon_prospamfilter.cgi"
        );
        $this->logger->info("[Install] Symlinking to WHM webdir completed: " . $ret_val);

        // Symlink WHM icons to CGI dir.
        $this->output->info("Symlinking WHM addon icons to webdir");
        $ret_val = $this->filesystem->symlink("/usr/local/prospamfilter/public/images", $whm_docroot . "/cgi/psf");
        $this->logger->info("[Install] Symlinking icons to webdir completed with {$ret_val}");

        // Symlink cPanel icons to CGI dir.
        $this->output->info("Symlinking cPanel addon icons to webdir");
        $ret_val = $this->filesystem->symlink(
            "/usr/local/prospamfilter/public/images", "/usr/local/prospamfilter/frontend/templatetoolkit/psf"
        );
        $this->logger->info("[Install] Symlinking cPanel addon icons to webdir templatetoolkit completed with {$ret_val}");
        $this->output->info("Symlinking cPanel addon icons to webdir");
        $ret_val = $this->filesystem->symlink(
            "/usr/local/prospamfilter/public/images", "/usr/local/prospamfilter/frontend/cpaneltags/psf"
        );
        $this->logger->info("[Install] Symlinking cPanel addon icons to webdir cpaneltags completed with {$ret_val}");

        $this->output->info("Symlinking cPanel addon vendor js to webdir");
        $ret_val = $this->filesystem->symlink(
            "/usr/local/prospamfilter/public/js",
            "/usr/local/prospamfilter/frontend/templatetoolkit/vendor"
        );
        $this->logger->info("[Install] Symlinking cPanel addon vendor js to webdir templatetoolkit completed with {$ret_val}");

        // Make it executable (requirement for .cgi file)
        $this->output->info("Making WHM addon executable");
        system("chmod +x {$whm_docroot}/cgi/addon_prospamfilter.cgi", $ret_val);
        $this->logger->info("[Install] Executable setting (addon_prospamfilter.cgi) returned with {$ret_val}");

        $this->output->info("Symlinking WHM icon to webdir");
        $ret_val = $this->filesystem->symlink(
            "/usr/local/prospamfilter/public/images/prospamfilter.gif",
            $whm_docroot . "/themes/x/icons/prospamfilter.gif"
        );
        $this->logger->info("[Install] Symlink (WHM icon -> webdir) returned with {$ret_val}");
    }

    private function generateConfigurationFile()
    {
        $file = $this->paths->config.DS."settings.conf";

        if ((!file_exists($file)) || (filesize($file) == 0)) {
            $this->output->info("Configuration file '" . $file . "' does not exist (or is empty).");
            $this->output->info("Generating default configuration file..");
            $cfg = new SpamFilter_Configuration($file);

            if ($cfg) {
                $this->output->info("Configuring initial settings..");
                $cfg->setInitial();
                $this->output->ok("Done!");
            } else {
                $this->output->error("Failed!");
            }
        } else {
            $this->output->info("Configuration file '" . $file . "' already exists.");
        }
    }

    /**
     * @return array
     */
    private function registerWhmAppInAppConfig()
    {
        /** Register the WHM application in the AppConfig system */
        $statusAppConfig = trim(`/usr/local/cpanel/bin/is_registered_with_appconfig whostmgr prospamfilter_whm`);
        if ('0' == $statusAppConfig) {
            $appConfigFile = $this->getBinPath() . '/cpanel/appconfig/prospamfilter_whm.conf';
            $appConfigRegisterResult = trim(shell_exec("/usr/local/cpanel/bin/register_appconfig $appConfigFile"));

            if (false === stripos($appConfigRegisterResult, 'prospamfilter_whm registered')) {
                throw new RuntimeException('Failed to register the WHM application in the AppConfig: ' . $appConfigRegisterResult);
            }

            $this->output->ok("The WHM app has been successfully registered in the AppConfig registry");
        } else {
            $this->output->info("The WHM app in already registered in the AppConfig registry");
        }
    }

    private function registerCpanelAppInAppConfig()
    {
        /** Register the Cpanel application in the AppConfig system */
        $binPath = $this->getBinPath();
        $cPanelWebdirsRoot = '/usr/local/cpanel/base/frontend';
        foreach (scandir($cPanelWebdirsRoot) as $eachDir) {
            if (is_dir("{$cPanelWebdirsRoot}/{$eachDir}")
                && !in_array($eachDir, array('.', '..', 'x3.bak'))
                && !is_link("{$cPanelWebdirsRoot}/{$eachDir}")
            ) {
                $statusAppConfig = trim(shell_exec(
                    "/usr/local/cpanel/bin/is_registered_with_appconfig cpanel prospamfilter_cpanel_{$eachDir}"
                ));
                if ('0' == $statusAppConfig) {
                    $appConfigFile = $binPath . '/cpanel/appconfig/prospamfilter_cpanel.conf';

                    file_put_contents(
                        $binPath . "/cpanel/appconfig/prospamfilter_cpanel_{$eachDir}.conf",
                        strtr(file_get_contents($appConfigFile), array('%template%' => $eachDir))
                    );

                    $appConfigFile = $binPath . "/cpanel/appconfig/prospamfilter_cpanel_{$eachDir}.conf";
                    $appConfigRegisterResult = trim(shell_exec("/usr/local/cpanel/bin/register_appconfig $appConfigFile"));

                    if (false === stripos($appConfigRegisterResult, "prospamfilter_cpanel_{$eachDir} registered")) {
                        $this->output->error("Failed to register the Cpanel_{$eachDir} application in the AppConfig: ".$appConfigRegisterResult);
                    } else {
                        $this->output->ok("The Cpanel_{$eachDir} app has been successfully registered in the AppConfig registry");
                    }
                } else {
                    $this->output->info("The Cpanel_{$eachDir} app in already registered in the AppConfig registry");
                }
            }
        }
    }

    private function getBinPath()
    {
        return __DIR__.'/../../bin';
    }

    private function checkRequirementsAreMet()
    {
        // We *need* shell_exec.
        if (!function_exists('shell_exec')) {
            $this->output->error('shell_exec function is required for the installer to work.');
            exit(1);
        }

        try {
            $whoami = shell_exec('whoami');
        } catch (Exception $e) {
            $this->output->error(
                "Error checking current user (via whoami), do you have the command 'whoami' or did you disallow shell_exec?."
            );
            exit(1);
        }

        // More detailed testing
        $selfcheck = SpamFilter_Core::selfCheck(false, array('skipapi' => true));
        $this->output->info("Running selfcheck...");
        if ($selfcheck['status'] != true) {
            if ($selfcheck['critital'] == true) {
                $this->output->error("Failed\nThere are some issues detected, of whom there are critical ones:");
            } else {
                $this->output->warn("Warning\nThere are some (potential) issues detected:");
            }

            foreach ($selfcheck['reason'] as $issue) {
                echo " * {$issue}\n";
            }

            // Wait a short wile.
            sleep(10);
        } else {
            $this->output->ok("Finished without errors");
        }
    }

    private function checkUserIsRoot()
    {
        $whoami = shell_exec('whoami');
        $whoami = trim($whoami);
        if ($whoami != "root") {
            $this->output->error("This can only be installed by 'root' (not: '$whoami').");
            exit(1);
        }
    }

    private function checkOldVersionIsUninstalled()
    {
        if (file_exists('/usr/local/prospamfilter/uninstall.sh')) {
            die("Please uninstall the old version first (using 'sh /usr/local/prospamfilter/uninstall.sh') before installing this version.");
        }
    }

    private function copyFilesToDestination()
    {
        $this->output->info("Copying files to destination.");

        // Cleanup destination folder.
        $this->output->info("Cleaning up old folder (" . $this->paths->destination . ")..");
        $this->filesystem->removeDirectory($this->paths->destination);
        $this->output->ok("Done");

        // Make new destination folder
        $this->output->info("Creating new folder (" . $this->paths->destination . ")..");
        if(!file_exists($this->paths->destination)){
            if (!mkdir($this->paths->destination, 0777, true)) {
                $this->output->error("Unable to create destination folder.");
                exit(1);
            }
        }
        $this->output->ok("Done");

        // Move all files to the new location.

        $this->output->info("Copying files from '" . $this->paths->base . "' to '" . $this->paths->destination . "'...");
        smartCopy($this->paths->base, $this->paths->destination);

        $this->output->ok("Done");

        return true;
    }

    private function setUpdateCronjob()
    {
        $cronfile = "/etc/cron.d/prospamfilter";
        // Create crontab entry
        $hour = mt_rand(20, 23); // Decide on update hour (between 20 and 23)
        $min = mt_rand(0, 59); // Decide on update minutes (0 to 59)

        /** @see https://trac.spamexperts.com/ticket/24064 */
        $dayOfWeek = mt_rand(0, 6);

        /*
        // Test code to make sure the updater runs in 5 minutes after installing
        $test_time 	= strtotime("+5 minutes");
        $hour 		= date('H', $test_time);
        $min 		= date('i', $test_time);
        */

        $data = "## Skip mailing this cron output to prevent numerous emails\n";
        $data .= "#MAILTO=\"\"\n";
        $data .= "\n";
        $data .= "#TZ=UTC\n";
        $data .= "\n";
        $data .= "#TZ=" . date_default_timezone_get() . "\n";
        $data .= "## Automatically update Professional Spam Filter (if enabled in the settings)\n";
        $data .= "{$min} {$hour} * * {$dayOfWeek} root /usr/local/prospamfilter/bin/checkUpdate.php\n";

        // Write entry to crontab file.
        file_put_contents($cronfile, $data);
        $this->output->ok("Done");

        // Reload cron since placing a file does not work. (Support #711724)
        $this->output->info("Reloading cron...");
        touch("/etc/cron.d/prospamfilter");
        $cron = touch("/etc/cron.d"); // just in case

        $retval = '';

        // Here be some additional reload checks
        if (file_exists('/etc/init.d/crond')) {
            $this->output->info("Reloading cron via daemon reload (crond)");
            // In some cases, touching it does not work, so reloading must.
            system('/etc/init.d/crond reload >/dev/null', $retval);
        } elseif (file_exists('/etc/init.d/cron')) {
            $this->output->info("Reloading cron via daemon reload (cron)");
            // In some cases, touching it does not work, so reloading must.
            system('/etc/init.d/cron reload >/dev/null', $retval);
        }
        $this->output->info("Cron reload returned value {$retval}");

        if ($cron) {
            $this->output->ok("Done");
        } else {
            $this->output->error("FAILED!");
            $this->output->warn("** Unable to reload cron **");
            $this->output->warn("--> Please rotate the cron daemon to make sure the cronjob is loaded properly.");
            sleep(10);
        }
    }

    private function setupSuidPermissions()
    {
        $this->output->info("Setting up permissions for SUID binaries...");

        if (file_exists($this->paths->destination . DS . "bin" . DS . "getconfig64")) {
            $this->output->info("64-bits...");
            chown($this->paths->destination . "/bin/getconfig64", "root");
            chgrp($this->paths->destination . "/bin/getconfig64", "root");
            system("chmod 755 " . $this->paths->destination . "/bin/getconfig64");
            system("chmod +s " . $this->paths->destination . "/bin/getconfig64");
        }

        if (file_exists($this->paths->destination . "/bin/getconfig")) {
            $this->output->info("32-bits...");
            chown($this->paths->destination . "/bin/getconfig", "root");
            chgrp($this->paths->destination . "/bin/getconfig", "root");
            system("chmod 755 " . $this->paths->destination . "/bin/getconfig");
            system("chmod +s " . $this->paths->destination . "/bin/getconfig");
        }

        $this->output->ok("Done");
    }

    private function removeMigrationFiles($version)
    {
        if (version_compare($version, '3.0.0', '>')) {
            if (file_exists('/usr/local/cpanel/whostmgr/docroot/cgi/addon_prospamfilter2.php')) {
                $this->output->info("Removing some traces from PSF2->PSF3 migration.");
                unlink("/usr/local/cpanel/whostmgr/docroot/cgi/addon_prospamfilter2.php");
            }
        }
    }

    private function removeSrcFolder()
    {
        $this->output->info("Removing temporary files");
        $this->filesystem->removeDirectory($this->paths->base);
        $this->output->ok("Done");
    }

    private function removeInstallFileAndDisplaySuccessMessage()
    {
        // Remove installer as we do not need it anymore.
        unlink($this->paths->destination . "/bin/install.php");
        $this->output->ok("\n\n***** Congratulations, Professional Spam Filter for Cpanel has been installed on your system! *****");
        $this->output->ok("If the addon is not configured yet, you should setup initial configuration in the admin part of the control panel before using its features.");
    }

    private function outputInstallStartMessage($panelType)
    {
        $version = $this->getVersion();
        $this->output->info("This system will install Professional Spam Filter v{$version} for {$panelType}");
    }

    private function changeDestinationPermissions()
    {
        $permissions = array(
            0754 => array(
                'bin/bulkprotect.php',
                'bin/uninstall.php',
            ),
            0755 => array(
                'bin/checkUpdate.php',
                'bin/installer/installer.sh',
                'bin/hook.php',
                'frontend/cpanel/psf.php',
                'frontend/whm/prospamfilter.php',
            ),
        );

        foreach($permissions as $permission => $files) {
            foreach($files as $file) {
                @chmod($this->paths->destination . DS . $file, $permission);
            }
        }

        $this->output->info("Setting tmp folder permissions");
        // Chmod the tmp folder (and everything in it)
        system("chmod -R 1777 " . $this->paths->destination . DS . "tmp");
        $this->output->ok("Done");
    }

    private function getVersion()
    {
        return trim(file_get_contents($this->paths->base . DS . "application" . DS . "version.txt"));
    }
}

Zerion Mini Shell 1.0