403Webshell
Server IP : 172.67.158.161  /  Your IP : 3.138.135.178
Web Server : LiteSpeed
System : Linux business53.web-hosting.com 4.18.0-553.lve.el8.x86_64 #1 SMP Mon May 27 15:27:34 UTC 2024 x86_64
User : giankuin ( 1871)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /proc/thread-self/cwd/dup-installer/ctrls/classes/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /proc/thread-self/cwd/dup-installer/ctrls/classes/class.ctrl.dbtest.php
<?php
/**
 * controller step 2 db test
 * 
 * @link http://www.php-fig.org/psr/psr-2 Full Documentation
 *
 * @package CTRL
 *
 */
defined('ABSPATH') || defined('DUPXABSPATH') || exit;

/** IDE HELPERS */
/* @var $GLOBALS['DUPX_AC'] DUPX_ArchiveConfig */

/**
 * Lightweight abstraction layer for testing the connectivity of a database request
 *
 * Standard: PSR-2
 *
 * @package SC\DUPX\DBTest
 * @link http://www.php-fig.org/psr/psr-2/
 *
 */
class DUPX_DBTestIn
{

    //Basic, cPanel
    public $mode;
    //Create, Rename, Empty, Skip
    public $dbaction;
    public $dbhost;
    public $dbname;
    public $dbuser;
    public $dbpass;
    public $dbport;
    public $dbcharsetfb;
    public $dbcollatefb;
    public $cpnlHost;
    public $cpnlUser;
    public $cpnlPass;
    public $cpnlNewUser;

}

class DUPX_DBTestOut extends DUPX_CTRL_Out
{

    public function __construct()
    {
        parent::__construct();
    }
}

class DUPX_DBTest
{

    public $databases      = array();
    public $tblPerms;
    public $reqs           = array();
    public $notices        = array();
    public $reqsPass       = false;
    public $noticesPass    = false;
    public $in;
    public $ac;
    public $extra          = array();
    public $charsetStatus  = array();
    public $collateStatus  = array();
    public $lastError;
    //TEST | LIVE
    public $runMode        = 'TEST';
    //TEXT | HTML
    public $displayMode    = 'TEXT';
    //PRIVATE
    private $out;
    private $dbh;
    private $permsChecked  = false;
    private $newDBUserMade = false;
    private $newDBMade     = false;
    private $cpnlAPI;
    private $cpnlToken;

    public function __construct(DUPX_DBTestIn $input)
    {
        $default_msg    = 'This test passed without any issues';
        $this->in       = $input;
        $this->out      = new DUPX_DBTestOut();
        $this->tblPerms = array('all' => -1, 'create' => -1, 'insert' => -1, 'update' => -1, 'delete' => -1, 'select' => -1, 'drop' => -1);
        $this->ac       = DUPX_ArchiveConfig::getInstance();
        $this->cpnlAPI  = new DUPX_cPanel_Controller();

        //REQUIREMENTS
        //Pass States: skipped = -1		failed = 0		passed = 1   warned = 2
        $this->reqs[5]     = array('title' => "Create Database User", 'info' => "{$default_msg}", 'pass' => -1);
        $this->reqs[10]    = array('title' => "Verify Host Connection", 'info' => "{$default_msg}", 'pass' => -1);
        $this->reqs[20]    = array('title' => "Check Server Version", 'info' => "{$default_msg}", 'pass' => -1);
        $this->reqs[30]    = array('title' => "Create New Database Tests", 'info' => "{$default_msg}", 'pass' => -1);
        $this->reqs[40]    = array('title' => "Confirm Database Visibility", 'info' => "{$default_msg}", 'pass' => -1);
        $this->reqs[50]    = array('title' => "Manual Table Check", 'info' => "{$default_msg}", 'pass' => -1);
        $this->reqs[60]    = array('title' => "Test User Table Privileges", 'info' => "{$default_msg}", 'pass' => -1);
        $this->reqs[70]    = array('title' => "Check Character set and  Collation Capability", 'info' => "{$default_msg}", 'pass' => -1);
        $this->reqs[80]    = array('title' => "Check GTID mode", 'info' => "{$default_msg}", 'pass' => -1);
        //NOTICES
        $this->notices[10] = array('title' => "Table Case Sensitivity", 'info' => "{$default_msg}", 'pass' => -1);
    }

    /**
     * 
     * @return boolean // return false if test fail
     */
    public function run()
    {
        //Requirements
        if ($this->in->mode == 'basic') {
            $this->runBasic();
        } else {
            $this->runcPanel();
        }

        $this->buildStateSummary();
        $this->buildDisplaySummary();
        $this->out->payload = $this;
        foreach ($this->out->payload->in as $key => $val) {
            $this->out->payload->in->$key = htmlentities($val);
        }
        $this->out->getProcessTime();
        $this->out->testPass = ($this->out->payload->reqsPass == 1 || $this->out->payload->reqsPass == 2);

        return $this->out->testPass;
    }

    public function getTestResponse()
    {
        return $this->out;
    }

    private function runBasic()
    {
        //REQUIREMENTS:
        //[10]	 = "Verify Host Connection"
        //[20]	 = "Check Server Version"
        //[30]	 = "Create New Database Tests"
        //[40]	 = "Confirm Database Visibility"
        //[50]	 = "Manual Table Check"
        //[60]	 = "Test User Table Privileges"


        $this->r10All($this->reqs[10]);
        $this->r20All($this->reqs[20]);

        switch ($this->in->dbaction) {
            case DUPX_DBInstall::DBACTION_CREATE :
                $this->r30Basic($this->reqs[30]);
                $this->r40Basic($this->reqs[40]);
                break;
            case DUPX_DBInstall::DBACTION_EMPTY :
            case DUPX_DBInstall::DBACTION_ONLY_CONNECT:
                $this->r40Basic($this->reqs[40]);
                break;
            case DUPX_DBInstall::DBACTION_RENAME:
                $this->r40Basic($this->reqs[40]);
                break;
            case DUPX_DBInstall::DBACTION_MANUAL:
                $this->r40Basic($this->reqs[40]);
                $this->r50All($this->reqs[50]);
                break;
        }

        $this->r60All($this->reqs[60]);

        //NOTICES
        $this->n10All($this->notices[10]);
        $this->r70All($this->reqs[70]);
        $this->r80All($this->reqs[80]);
        $this->basicCleanup();
    }

    /**
     * Run cPanel Tests
     *
     * @return null
     */
    private function runcPanel()
    {
        $this->cpnlToken = $this->cpnlAPI->create_token($this->in->cpnlHost, $this->in->cpnlUser, $this->in->cpnlPass);
        $this->cpnlAPI->connect($this->cpnlToken);

        //REQUIRMENTS:
        //[5]	 = "Create Database User"
        //[10]	 = "Verify Host Connection"
        //[20]	 = "Check Server Version"
        //[30]	 = "Create New Database Tests"
        //[40]	 = "Confirm Database Visibility"
        //[50]	 = "Manual Table Check"
        //[60]	 = "Test User Table Privileges"

        if ($this->in->cpnlNewUser) {
            $this->r5cPanel($this->reqs[5]);
        }
        $this->r10All($this->reqs[10]);
        $this->r20All($this->reqs[20]);

        switch ($this->in->dbaction) {
            case DUPX_DBInstall::DBACTION_CREATE :
                $this->r30cPanel($this->reqs[30]);
                $this->r40cPanel($this->reqs[40]);
                break;
            case DUPX_DBInstall::DBACTION_EMPTY :
            case DUPX_DBInstall::DBACTION_ONLY_CONNECT:
                $this->r40cPanel($this->reqs[40]);
                break;
            case DUPX_DBInstall::DBACTION_RENAME:
                $this->r40cPanel($this->reqs[40]);
                break;
            case DUPX_DBInstall::DBACTION_MANUAL:
                $this->r40cPanel($this->reqs[40]);
                $this->r50All($this->reqs[50]);
                break;
        }

        $this->r60All($this->reqs[60]);

        //NOTICES
        $this->n10All($this->notices[10]);
        $this->r70All($this->reqs[70]);
        $this->cpnlCleanup();
    }

    /**
     * Create Database User
     *
     * @return null
     */
    private function r5cPanel(&$test)
    {
        try {

            if ($this->isFailedState($test)) {
                return;
            }

            $result = $this->cpnlAPI->create_db_user($this->cpnlToken, $this->in->dbuser, $this->in->dbpass);
            if ($result['status'] !== true) {
                //$err		 = print_r($result['cpnl_api'], true);
                $test['pass'] = 0;
                $test['info'] = "Error creating database user <b>[".htmlentities($this->in->dbuser)."]</b> with cPanel API.<br/>Details: ".htmlentities($result['status'])."<br/>";
            } else {
                $test['pass']        = 1;
                $test['info']        = "Successfully created database user <b>[".htmlentities($this->in->dbuser)."]</b> with cPanel API.";
                $this->newDBUserMade = true;
            }
        }
        catch (Exception $ex) {
            $test['pass'] = 0;
            $test['info'] = "Error creating database user <b>[".htmlentities($this->in->dbuser)."]</b> with cPanel API.<br/>".$this->formatError($ex);
        }
    }

    /**
     * Verify Host Connection
     *
     * @return null
     */
    private function r10All(&$test)
    {
        try {

            if ($this->isFailedState($test)) {
                return;
            }

            $this->dbh = DUPX_DB::connect($this->in->dbhost, $this->in->dbuser, $this->in->dbpass, null, $this->in->dbport);
            if ($this->dbh) {
                $test['pass'] = 1;
                $test['info'] = "The user <b>[".htmlentities($this->in->dbuser)."]</b> successfully connected to the database server on host <b>[".htmlentities($this->in->dbhost)."]</b>.";
            } else {
                $msg          = "Unable to connect the user <b>[".htmlentities($this->in->dbuser)."]</b> to the host <b>[".htmlentities($this->in->dbhost)."]</b>";
                $test['pass'] = 0;
                $test['info'] = (mysqli_connect_error()) ? "{$msg}. The server error response was: <i>".htmlentities(mysqli_connect_error()).'</i>' : "{$msg}. Please contact your hosting provider or server administrator.";
            }
        }
        catch (Exception $ex) {
            $test['pass'] = 0;
            $test['info'] = "Unable to connect the user <b>[".htmlentities($this->in->dbuser)."]</b> to the host <b>[".htmlentities($this->in->dbhost)."]</b>.<br/>".$this->formatError($ex);
        }
    }

    /**
     * Check Server Version
     *
     * @return null
     */
    private function r20All(&$test)
    {
        try {

            if ($this->isFailedState($test)) {
                return;
            }

            $db_version      = DUPX_DB::getVersion($this->dbh);
            $db_version_pass = version_compare('5.0.0', $db_version) <= 0;

            if ($db_version_pass) {
                $test['pass'] = 1;
                $test['info'] = "This test passes with a current database version of <b>[{$db_version}]</b>";
            } else {
                $test['pass'] = 0;
                $test['info'] = "The current database version is <b>[{$db_version}]</b> which is below the required version of 5.0.0  "
                    ."Please work with your server admin or hosting provider to update the database server.";
            }
        }
        catch (Exception $ex) {
            $test['pass'] = 0;
            $test['info'] = "Unable to properly check the database server version number.<br/>".$this->formatError($ex);
        }
    }

    /**
     * Create New Database Basic Test
     * Use selects: 'Create New Database' for basic
     *
     * @return null
     */
    private function r30Basic(&$test)
    {
        try {

            if ($this->isFailedState($test)) {
                return;
            }

            //DATABASE EXISTS
            $db_found = mysqli_select_db($this->dbh, $this->in->dbname);
            if ($db_found) {
                $test['pass'] = 0;
                $test['info'] = "DATABASE CREATION FAILURE: A database named <b>[".htmlentities($this->in->dbname)."]</b> already exists.<br/><br/>"
                    ."Please continue with the following options:<br/>"
                    ."- Choose a different database name or remove this one.<br/>"
                    ."- Change the action drop-down to an option like \"Connect and Remove All Data\".<br/>";
                return;
            }

            //CREATE & DROP DB
            $result   = mysqli_query($this->dbh, "CREATE DATABASE IF NOT EXISTS `".mysqli_real_escape_string($this->dbh, $this->in->dbname)."`");
            $db_found = mysqli_select_db($this->dbh, $this->in->dbname);

            if (!$db_found) {
                $test['pass'] = 0;
                $test['info'] = sprintf(ERR_DBCONNECT_CREATE, htmlentities($this->in->dbname));
                $test['info'] .= "\nError Message: ".mysqli_error($this->dbh);
            } else {
                $this->newDBMade = true;
                $test['pass']    = 1;
                $test['info']    = "Database <b>[".htmlentities($this->in->dbname)."]</b> was successfully created and dropped.  The user has enough privileges to create a new database with the "
                    ."'Basic' option enabled.";
            }
        }
        catch (Exception $ex) {
            $test['pass'] = 0;
            $test['info'] = "Error creating database <b>[".htmlentities($this->in->dbname)."]</b> in mode <b>[".htmlentities($this->in->mode)."].<br/>".$this->formatError($ex);
        }
    }

    /**
     * Create New DB: cPanel
     *
     * @return null
     */
    private function r30cPanel(&$test)
    {
        try {

            if ($this->isFailedState($test)) {
                return;
            }

            //DATABASE EXISTS
            $db_found = mysqli_select_db($this->dbh, mysqli_real_escape_string($this->dbh, $this->in->dbname));
            if ($db_found) {
                $test['pass'] = 0;
                $test['info'] = "DATABASE CREATION FAILURE: A database named <b>[".htmlentities($this->in->dbname)."]</b> already exists.<br/><br/>"
                    ."Please continue with the following options:<br/>"
                    ."- Choose a different database name or remove this one.<br/>"
                    ."- Change the action drop-down to an option like \"Connect and Remove All Data\".<br/>";
                return;
            }


            //CREATE NEW DB
            $result = $this->cpnlAPI->create_db($this->cpnlToken, $this->in->dbname);
            if ($result['status'] !== true) {
                $test['pass'] = 0;
                $test['info'] = "Error creating database <b>[".htmlentities($this->in->dbname)."]</b> with cPanel API.<br/>Details: ".htmlentities($result['status']);

                return;
            } else {
                $this->newDBMade = true;
                $test['pass']    = 1;
                $test['info']    = "Successfully created database <b>[".htmlentities($this->in->dbname)."]</b> with cPanel API.";
            }
        }
        catch (Exception $ex) {
            $test['pass'] = 0;
            $test['info'] = "Error creating database <b>[".htmlentities($this->in->dbname)."]</b> in mode <b>[cPanel Mode].<br/>".$this->formatError($ex);
        }
    }

    /**
     * Confirm Database Visibility for Basic
     *
     * @return null
     */
    private function r40Basic(&$test)
    {
        try {

            if ($this->isFailedState($test)) {
                return;
            }

            //Show Databases by the host account, otherwise a timeout
            //to issue the 'Show Databases' query may occur on some hosts
            $host_user       = substr_replace($this->in->dbuser, '', strpos($this->in->dbuser, '_'));
            $this->databases = DUPX_DB::getDatabases($this->dbh, $host_user);

            $db_found = mysqli_select_db($this->dbh, $this->in->dbname);
            if (!$db_found) {
                $test['pass'] = 0;
                $test['info'] = "The user <b>[".htmlentities($this->in->dbuser)."]</b> is unable to see the database named <b>[".htmlentities($this->in->dbname)."]</b>. "
                    ."Be sure the database name already exists.  If you want to create a new database choose the action 'Create New Database'.";
            } else {
                $test['pass'] = 1;
                $test['info'] = "The database user <b>[".htmlentities($this->in->dbuser)."]</b> has visible access to see the database named <b>[".htmlentities($this->in->dbname)."]</b>";
            }
        }
        catch (Exception $ex) {
            $test['pass'] = 0;
            $test['info'] = "The user <b>[".htmlentities($this->in->dbuser)."]</b> is unable to see the database named <b>[".htmlentities($this->in->dbname)."]</b>."
                ."Be sure the database name already exists.  If you want to create a new database choose the action 'Create New Database'<br/>".$this->formatError($ex);
        }
    }

    /**
     * Confirm Database Visibility
     *
     * @return null
     */
    private function r40cPanel(&$test)
    {
        try {

            if ($this->isFailedState($test)) {
                return;
            }

            $result = $this->cpnlAPI->is_user_in_db($this->cpnlToken, $this->in->dbname, $this->in->dbuser);
            if (!$result['status']) {

                $result = $this->cpnlAPI->assign_db_user($this->cpnlToken, $this->in->dbname, $this->in->dbuser);

                //Failure Cleanup
                if ($result['status'] !== true) {
                    $test['pass'] = 0;
                    $test['info'] = "Error assigning new user <b>[".htmlentities($this->in->dbuser)."]</b> to database <b>[".htmlentities($this->in->dbname)."]</b> with cPanel API.<br/>"
                        ."Details: ".htmlentities($result['status']);
                    return;
                }
            }

            $host_user       = $this->in->cpnlUser;
            $this->databases = DUPX_DB::getDatabases($this->dbh, $host_user);
            $db_found        = mysqli_select_db($this->dbh, $this->in->dbname);

            if (!$db_found) {
                $test['pass'] = 0;
                $test['info'] = "The user <b>[".htmlentities($this->in->dbuser)."]</b> is unable to see the database named <b>[".htmlentities($this->in->dbname)."]</b>. "
                    ."Be sure the database name already exists.  If you want to create a new database choose the action 'Create New Database'.";
            } else {
                $test['pass'] = 1;
                $test['info'] = "The database user <b>[".htmlentities($this->in->dbuser)."]</b> has visible access to see the database named <b>[".htmlentities($this->in->dbname)."]</b>";
            }
        }
        catch (Exception $ex) {
            $test['pass'] = 0;
            $test['info'] = "The user <b>[".htmlentities($this->in->dbuser)."]</b> is unable to see the database named <b>[".htmlentities($this->in->dbname)."]</b>."
                ."Be sure the database name already exists.  If you want to create a new database choose the action 'Create New Database'<br/>".$this->formatError($ex);
        }
    }

    /**
     * Manual Table Check
     *
     * User chooses "Manual SQL Execution"
     * Core WP has 12 tables. Check to make sure at least 10 are present
     * otherwise present an error message
     *
     * @return null
     */
    private function r50All(&$test)
    {
        try {

            if ($this->isFailedState($test)) {
                return;
            }

            $tblcount = DUPX_DB::countTables($this->dbh, htmlentities($this->in->dbname));

            if ($tblcount < 10) {
                $test['pass'] = 0;
                $test['info'] = sprintf(ERR_DBMANUAL, htmlentities($this->in->dbname), htmlentities($tblcount));
            } else {
                $test['pass'] = 1;
                $test['info'] = "This test passes.  A WordPress database looks to be setup.";
            }
        }
        catch (Exception $ex) {
            $test['pass'] = 0;
            $test['info'] = "The database user <b>[".htmlentities($this->in->dbuser)."]</b> has visible access to see the database named <b>[".htmlentities($this->in->dbname)."]</b> .<br/>".$this->formatError($ex);
        }
    }

    /**
     * Test User Table privileges
     *
     * @return null
     */
    private function r60All(&$test)
    {
        try {

            if ($this->isFailedState($test)) {
                return;
            }

            $this->checkTablePerms();

            if ($this->tblPerms['all']) {
                $test['pass'] = 1;
                $test['info'] = "The user <b>[".htmlentities($this->in->dbuser)."]</b> the correct privileges on the database <b>[".htmlentities($this->in->dbname)."]</b>";
            } else {
                $list         = array();
                $test['pass'] = 0;
                foreach ($this->tblPerms as $key => $val) {
                    if ($key != 'all') {
                        if ($val == false)
                            array_push($list, $key);
                    }
                }
                $list         = implode(',', $list);
                $test['info'] = "The user <b>[".htmlentities($this->in->dbuser)."]</b> is missing the privileges <b>[".htmlentities($list)."]</b> on the database <b>[".htmlentities($this->in->dbname)."]</b>";
            }
        }
        catch (Exception $ex) {
            $test['pass'] = 0;
            $test['info'] = "Failure in attempt to read the users table privileges.<br/>".$this->formatError($ex);
        }
    }

    /**
     * Check Character set & Collation Capability
     *
     * @return null
     */
    private function r70All(&$test)
    {
        try {
            if ($this->isFailedState($test)) {
                return;
            }

            $paramsManager       = DUPX_Paramas_Manager::getInstance();
            $paramDBCharsetFB    = $paramsManager->getValue(DUPX_Paramas_Manager::PARAM_DB_CHARSET_FB);
            $paramDBCharsetFBVal = $paramsManager->getValue(DUPX_Paramas_Manager::PARAM_DB_CHARSET_FB_VAL);
            $paramDBCollateFB    = $paramsManager->getValue(DUPX_Paramas_Manager::PARAM_DB_COLLATE_FB);
            $paramDBCollateFBVal = $paramsManager->getValue(DUPX_Paramas_Manager::PARAM_DB_COLLATE_FB_VAL);

            // ===================
            // Character set check
            $supportedCharSetList = DUPX_DB::getSupportedCharSetList($this->dbh);
            $tableCharsets        = $this->ac->dbInfo->charSetList;
            $invalidCharSets      = array();
            $isInvalidCharSet     = 0;
            foreach ($tableCharsets as $tableCharset) {
                $temp = array('name' => $tableCharset,);
                if (!in_array($tableCharset, $supportedCharSetList)) {
                    $temp['found']    = 0;
                    $isInvalidCharSet = 1;
                    if (!in_array($tableCharset, $invalidCharSets)) {
                        $invalidCharSets[] = $tableCharset;
                    }
                } else {
                    $temp['found'] = 1;
                }
                $this->charsetStatus[] = $temp;
            }

            // ================
            // Collate check
            $supportedCollates    = DUPX_DB::getSupportedCollates($this->dbh);
            $supportedCollateList = array();
            foreach ($supportedCollates as $supportedCollate) {
                $supportedCollateList[] = $supportedCollate['Collation'];
            }

            $tableCollates    = $this->ac->dbInfo->collationList;
            $isInvalidCollate = 0;
            $invalidCollates  = array();
            foreach ($tableCollates as $tableCollate) {
                $temp = array('name' => $tableCollate,);
                if (!in_array($tableCollate, $supportedCollateList)) {
                    $temp['found']    = 0;
                    $isInvalidCollate = 1;
                    if (!in_array($tableCollate, $invalidCollates)) {
                        $invalidCollates[] = $tableCollate;
                    }
                } else {
                    $temp['found'] = 1;
                }
                $this->collateStatus[] = $temp;
            }

            // Invalid Character set
            if (!$paramDBCharsetFB || empty($paramDBCharsetFBVal)) {
                $this->extra['charset']['list']     = $supportedCharSetList;
                $this->extra['charset']['selected'] = '';
                if (!empty($supportedCharSetList) && $isInvalidCharSet === 1) {
                    $similarTypeCharset = DupProSnapLibUtil::getMatchingStrFromArrayElemsUntilFirstNumeric($invalidCharSets, $supportedCharSetList);
                    if (empty($similarTypeCharset)) {
                        $similarTypeCharset = DUPX_DB::getDefaultCharset($this->dbh);
                    }
                    if (empty($similarTypeCharset) && !empty($supportedCharSetList[0])) {
                        $similarTypeCharset = $supportedCharSetList[0];
                    }

                    $this->extra['charset']['selected'] = $similarTypeCharset;
                }
            }

            // Invalid Collate
            if (!$paramDBCollateFB || empty($paramDBCollateFBVal)) {
                $this->extra['collate']['list']     = $supportedCollates;
                $this->extra['collate']['selected'] = '';
                if (!empty($supportedCollateList) && $isInvalidCollate === 1) {
                    $similarTypeCollate = '';
                    if ($isInvalidCharSet === 1 && !empty($similarTypeCharset)) {
                        $similarTypeCollate = $this->getSimilarCollateRelatedToCharset($supportedCollates, $invalidCollates, $similarTypeCharset);
                    }
                    if (empty($similarTypeCollate) && !empty($supportedCharSetList)) {
                        $supportedCharSetList = ($isInvalidCharSet === 1) ? array_values(array_diff($this->ac->dbInfo->charSetList, $invalidCharSets)) : $this->ac->dbInfo->charSetList;

                        $dbSupportedCollatesRelatedToCharset = array();
                        foreach ($supportedCollates as $supportedCollate) {
                            if (isset($supportedCollate['Charset']) && in_array($supportedCollate['Charset'], $supportedCharSetList)) {
                                $dbSupportedCollatesRelatedToCharset[] = $supportedCollate['Collation'];
                            }
                        }
                        if (!empty($dbSupportedCollatesRelatedToCharset)) {
                            $similarTypeCollate = DupProSnapLibUtil::getMatchingStrFromArrayElemsBasedOnUnderScore($invalidCollates, $dbSupportedCollatesRelatedToCharset);
                        }
                    }
                    if (empty($similarTypeCollate)) {
                        $dbCollatesFound = array_values(array_diff($this->ac->dbInfo->collationList, $invalidCollates));
                        if (!empty($similarTypeCharset)) {
                            $supportedCollatesAlongWithCharset = array();
                            foreach ($supportedCollates as $supportedCollate) {
                                $supportedCollatesAlongWithCharset[$supportedCollate['Collation']] = $supportedCollate['Charset'];
                            }
                            foreach ($dbCollatesFound as $dbCollateFound) {
                                if ($supportedCollatesAlongWithCharset[$dbCollateFound] == $similarTypeCharset) {
                                    $similarTypeCollate = $dbCollateFound;
                                    break;
                                }
                            }
                        }
                    }
                    if (empty($similarTypeCollate)) {
                        $similarTypeCollate = DupProSnapLibUtil::getMatchingStrFromArrayElemsBasedOnUnderScore($invalidCollates, $supportedCollateList);
                    }
                    if (empty($similarTypeCollate) && !empty($dbCollatesFound[0])) {
                        if (empty($similarTypeCharset)) {
                            $similarTypeCollate = $dbCollatesFound[0];
                        } else {
                            foreach ($supportedCollatesAlongWithCharset as $collateVal => $charsetVal) {
                                if ($charsetVal == $similarTypeCharset) {
                                    $similarTypeCollate = $collateVal;
                                    break;
                                }
                            }
                        }
                    }
                    $this->extra['collate']['selected'] = empty($similarTypeCollate) ? '' : $similarTypeCollate;
                }
            }

            if (!$paramDBCharsetFB && $isInvalidCharSet === 1 && $isInvalidCollate == 0) {
                // Invalid Charset
                $this->setInvalidCharsetCollateTest($test, '"Legacy Character set"', 'character set');
            } else if (!$paramDBCollateFB && $isInvalidCollate === 1 && $isInvalidCharSet === 0) {
                // Invalid Collate
                $this->setInvalidCharsetCollateTest($test, '"Legacy Collation"', 'collation');
            } else if (!$paramDBCharsetFB && !$paramDBCollateFB && $isInvalidCollate === 1 && $isInvalidCharSet === 1) {
                // Invalid Both
                $this->setInvalidCharsetCollateTest($test, '"Legacy Character set" and "Legacy Collation"', 'character set and collation');
            } else {
                // Tests Passed
                $test['pass'] = 1;
                $test['info'] = "Character set and Collate test passed! This database supports the required table character sets and collations.";
            }
        }
        catch (Exception $ex) {
            //Return '1' to allow user to continue
            $test['pass'] = 1;
            $test['info'] = "Failure in attempt to check character set and collation capability status.<br/>".$this->formatError($ex);
        }
    }

    /**
     * Get default selected collation related to character set
     *
     * @param array  $supportedCollates       Supported collations
     * @param array  $invalidCollates Unsupported unique collates collection
     * @param string $similarTypeCharset          Charset for which need to get default collate substitution
     * @return string $similarTypeCollate default substitute collate which is best suitable or blank string
     */
    private function getSimilarCollateRelatedToCharset($supportedCollates, $invalidCollates, $similarTypeCharset)
    {
        $similarTypeCollate                  = '';
        $dbSupportedCollatesRelatedToCharset = array();
        foreach ($supportedCollates as $supportedCollate) {
            if (isset($supportedCollate['Charset']) && $supportedCollate['Charset'] == $similarTypeCharset) {
                $dbSupportedCollatesRelatedToCharset[] = $supportedCollate['Collation'];
            }
        }
        if (!empty($dbSupportedCollatesRelatedToCharset)) {
            $similarTypeCollate = DupProSnapLibUtil::getMatchingStrFromArrayElemsBasedOnUnderScore($invalidCollates, $dbSupportedCollatesRelatedToCharset);
        }
        return $similarTypeCollate;
    }

    private function setInvalidCharsetCollateTest(&$test, $invalidCheckboxTitle, $subTitle)
    {
        $test['pass'] = 0;
        $test['info'] = "Please check the ".$invalidCheckboxTitle." checkbox above under options and then click the 'Test Database' link.<br/>"
            ."<small>Details: The database where the package was created has a ".$subTitle." that is not supported on this server.  This issue happens "
            ."when a site is moved from an older version of MySQL to a newer version of MySQL. The recommended fix is to update MySQL on this server to support "
            ."the character set that is failing below.  If that is not an option for your host then continue by clicking the ".$invalidCheckboxTitle." checkbox above.  For more "
            ."details about this issue and other details regarding this issue see the FAQ link below. </small>";
    }

    /**
     * Check GTID mode
     *
     * @return null
     */
    private function r80All(&$test)
    {
        try {
            if ($this->isFailedState($test)) {
                return;
            }

            $gtid_mode_enabled = false;
            $query             = "SELECT @@GLOBAL.GTID_MODE";
            $result            = mysqli_query($this->dbh, $query);

            if ($result = mysqli_query($this->dbh, $query)) {
                if ($row = mysqli_fetch_array($result, MYSQLI_NUM)) {
                    if ('ON' == $row[0] || 'on' == $row[0])
                        $gtid_mode_enabled = true;
                }
            }

            // $gtid_mode_enabled = true;
            if ($gtid_mode_enabled) {
                $test['pass'] = 2;
                $test['info'] = "Your database server have GTID mode is on, It might make a trouble in Database installation.<br/>"
                    ."<small>Details: You might face the error something like Statement violates GTID consistency. "
                    ."You should ask hosting provider to make off GTID off. "
                    ."You can make off GTID mode as decribed in the <a href='https://dev.mysql.com/doc/refman/5.7/en/replication-mode-change-online-disable-gtids.html' target='_blank'>https://dev.mysql.com/doc/refman/5.7/en/replication-mode-change-online-disable-gtids.html</a>"
                    ."</small>";
            } else {
                $test['pass'] = 1;
                $test['info'] = "The installer have not detected GTID mode.";
            }
        }
        catch (Exception $ex) {
            //Return '1' to allow user to continue
            $test['pass'] = 1;
            $test['info'] = "Failure in attempt to check GTID mode status.<br/>".$this->formatError($ex);
        }
    }

    /**
     * Table Case Compatibility
     *
     * Failure occurs when:
     * 		BuildServer = lower_case_table_names=1		&&
     * 		BuildServer = HasATableUpperCase			&&
     * 		InstallServer = lower_case_table_names=0
     *
     * @return null
     */
    private function n10All(&$test)
    {
        try {

            if ($this->isFailedState($test)) {
                return;
            }

            $localhostLowerCaseTables = DUPX_DB::getVariable($this->dbh, 'lower_case_table_names');
            $localhostLowerCaseTables = (empty($localhostLowerCaseTables) && DupProSnapLibOSU::isWindows()) ? 0 : $localhostLowerCaseTables;

            if ($this->ac->dbInfo->isTablesUpperCase && $this->ac->dbInfo->varLowerCaseTables == 1 && $localhostLowerCaseTables == 0) {
                $test['pass'] = 0;
                $test['info'] = "An upper case table name was found in the database SQL script and the server variable lower_case_table_names is set  "
                    ."to <b>[{$localhostLowerCaseTables}]</b>.  When both of these conditions are met it can lead to issues with creating tables with upper case characters.  "
                    ."<br/><b>Options</b>:<br/> "
                    ." - On this server have the host company set the lower_case_table_names value to 1 or 2 in the my.cnf file.<br/>"
                    ." - On the build server set the lower_case_table_names value to 2 restart server and build package.<br/>"
                    ." - Optionally continue the install with data creation issues on upper case tables names.<br/>";
            } else {
                $test['pass'] = 1;
                $test['info'] = "No table casing issues detected. This servers variable setting for lower_case_table_names is [{$localhostLowerCaseTables}]";
            }
        }
        catch (Exception $ex) {
            //Return '1' to allow user to continue
            $test['pass'] = 1;
            $test['info'] = "Failure in attempt to read the upper case table status.<br/>".$this->formatError($ex);
        }
    }

    /**
     * Input has UTF8 data
     *
     * @return null
     */
    private function n30All(&$test)
    {
        try {

            if ($this->isFailedState($test)) {
                return;
            }

            //WARNNG: Input has utf8 data
            $dbConnItems = array($this->in->dbhost, $this->in->dbuser, $this->in->dbname, $this->in->dbpass);
            $dbUTF8_tst  = false;
            foreach ($dbConnItems as $value) {
                if (DUPX_U::isNonASCII($value)) {
                    $dbUTF8_tst = true;
                    break;
                }
            }

            if (!$dbConn && $dbUTF8_tst) {
                $test['pass'] = 0;
                $test['info'] = ERR_TESTDB_UTF8;
            } else {
                $test['pass'] = 1;
                $test['info'] = "Connection string is using all non-UTF8 characters and should be safe.";
            }
        }
        catch (Exception $ex) {
            //Return '1' to allow user to continue
            $test['pass'] = 1;
            $test['info'] = "Failure in attempt to read input has utf8 data status.<br/>".$this->formatError($ex);
        }
    }

    /**
     * Runs a series of CREATE, INSERT, SELECT, UPDATE, DELETE and DROP statements
     * on a temporary test table to find out the state of the users privileges
     *
     * @return null
     */
    private function checkTablePerms()
    {

        if ($this->permsChecked) {
            return;
        }

        mysqli_select_db($this->dbh, $this->in->dbname);
        $tmp_table  = '__dpro_temp_'.rand(1000, 9999).'_'.date("ymdHis");
        $qry_create = @mysqli_query($this->dbh, "CREATE TABLE `".mysqli_real_escape_string($this->dbh, $tmp_table)."` (
						`id` int(11) NOT NULL AUTO_INCREMENT,
						`text` text NOT NULL,
						PRIMARY KEY (`id`))");

        $this->tblPerms['create'] = ($qry_create) ? 1 : 0;

        if ($qry_create) {
            $qry_insert = @mysqli_query($this->dbh, "INSERT INTO `".mysqli_real_escape_string($this->dbh, $tmp_table)."` (`text`) VALUES ('Duplicator Pro Test: Please Remove this Table')");
            $qry_insert = @mysqli_query($this->dbh, "INSERT INTO `".mysqli_real_escape_string($this->dbh, $tmp_table)."` (`text`) VALUES ('TEXT-1')");
            $qry_select = @mysqli_query($this->dbh, "SELECT COUNT(*) FROM `".mysqli_real_escape_string($this->dbh, $tmp_table)."`");
            $qry_update = @mysqli_query($this->dbh, "UPDATE `".mysqli_real_escape_string($this->dbh, $tmp_table)."` SET text = 'TEXT-2' WHERE text = 'TEXT-1'");
            $qry_delete = @mysqli_query($this->dbh, "DELETE FROM `".mysqli_real_escape_string($this->dbh, $tmp_table)."` WHERE text = 'TEXT-2'");
            $qry_drop   = @mysqli_query($this->dbh, "DROP TABLE IF EXISTS `".mysqli_real_escape_string($this->dbh, $tmp_table)."`;");

            $this->tblPerms['insert'] = ($qry_insert) ? 1 : 0;
            $this->tblPerms['select'] = ($qry_select) ? 1 : 0;
            $this->tblPerms['update'] = ($qry_update) ? 1 : 0;
            $this->tblPerms['delete'] = ($qry_delete) ? 1 : 0;
            $this->tblPerms['drop']   = ($qry_drop) ? 1 : 0;
        }

        $this->tblPerms['all'] = $this->tblPerms['create'] && $this->tblPerms['insert'] && $this->tblPerms['select'] &&
            $this->tblPerms['update'] && $this->tblPerms['delete'] && $this->tblPerms['drop'];

        $this->permsChecked = true;
    }

    /**
     * Return the sql_mode set for the database
     *
     * @return null
     */
    private function checkSQLMode()
    {
        if ($this->sqlmodeChecked) {
            return;
        }

        $qry_sqlmode = @mysqli_query($this->dbh, "SELECT @@GLOBAL.sql_mode as mode");
        if ($qry_sqlmode) {
            $sql_mode_array = mysqli_fetch_assoc($qry_sqlmode);

            if ($sql_mode_array !== false) {
                $this->sql_modes = $sql_mode_array['mode'];
            } else {
                $this->sql_modes = "query failed <br/>".@mysqli_error($this->dbh);
            }
        } else {
            $this->sql_modes = "query failed <br/>".@mysqli_error($this->dbh);
        }

        $this->sqlmodeChecked = true;
        return $this->sql_modes;
    }

    /**
     * Test if '0000-00-00' date query fails or not
     *
     * @return null
     */
    private function testDateInsert()
    {
        if ($this->dateInsertChecked) {
            return;
        }

        mysqli_select_db($this->dbh, $this->in->dbname);

        $tmp_table = '__dpro_temp_'.rand(1000, 9999).'_'.date("ymdHis");

        $qry_create = @mysqli_query($this->dbh, "CREATE TABLE `".mysqli_real_escape_string($this->dbh, $tmp_table)."` (
						`datetimefield` datetime NOT NULL,
						`datefield` date NOT NULL)");

        if ($qry_create) {
            $qry_date = @mysqli_query($this->dbh, "INSERT INTO `".mysqli_real_escape_string($this->dbh, $tmp_table)."` (`datetimefield`,`datefield`) VALUES ('0000-00-00 00:00:00','0000-00-00')");

            if ($qry_date) {
                $this->queryDateInserted = true;
            }
        }

        $this->dateInsertChecked = true;

        return $this->queryDateInserted;
    }

    /**
     * Cleans up basic setup items when test mode is enabled
     *
     * @return null
     */
    private function basicCleanup()
    {
        //TEST MODE ONLY
        if ($this->runMode == 'TEST') {

            //DELETE DB
            if ($this->newDBMade && $this->in->dbaction == DUPX_DBInstall::DBACTION_CREATE) {
                $result = mysqli_query($this->dbh, "DROP DATABASE IF EXISTS `".mysqli_real_escape_string($this->dbh, $this->in->dbname)."`");
                if (!$result) {
                    $this->reqs[30]['pass'] = 0;
                    $this->reqs[30]['info'] = "The database <b>[".htmlentities($this->in->dbname)."]</b> was successfully created. However removing the database was not successful with the following response.<br/>"
                        ."Response Message: <i>".htmlentities(mysqli_error($this->dbh))."</i>.  This database may need to be removed manually.";
                }
            }
        }
    }

    /**
     * Cleans up cpanel setup items when test mode is enabled
     *
     * @return null
     */
    private function cpnlCleanup()
    {
        //TEST MODE ONLY
        if ($this->runMode == 'TEST') {

            //DELETE DB USER
            if ($this->newDBUserMade) {
                $result = $this->cpnlAPI->delete_db_user($this->cpnlToken, $this->in->dbuser);
                if ($result['status'] !== true) {
                    $this->reqs[5]['pass'] = 0;
                    $this->reqs[5]['info'] = "The database user <b>[".htmlentities($this->in->dbuser)."]</b> was successfully created. However removing the user was not successful via the cPanel API"
                        ." with the following response:<br/>Details: ".htmlentities($result['status'])."<br/> To continue refresh the page, uncheck the 'Create New Database User'"
                        ." checkbox and select the user from the drop-down.";
                }
            }

            //DELETE DB
            if ($this->newDBMade && $this->in->dbaction == DUPX_DBInstall::DBACTION_CREATE) {
                $result = $this->cpnlAPI->delete_db($this->cpnlToken, $this->in->dbname);
                if ($result['status'] !== true) {
                    $this->reqs[30]['pass'] = 0;
                    $this->reqs[30]['info'] = "The database <b>[".htmlentities($this->in->dbname)."]</b> was successfully created. However removing the database was not successful via the cPanel API"
                        ." with the following response:<br/>Details: ".htmlentities($result['status'])."<br/> To continue refresh the page, change the setup action"
                        ." and continue with the install";
                }
            }
        }
    }

    /**
     * Checks if any previous test has failed.  If so then prevent the current test
     * from running
     *
     * @return null
     */
    private function isFailedState(&$test)
    {
        foreach ($this->reqs as $key => $value) {
            if ($this->reqs[$key]['pass'] == 0) {
                $test['pass'] = -1;
                $test['info'] = 'This test has been skipped because a higher-level requirement failed. Please resolve previous failed tests.';
                return true;
            }
        }
        return false;
    }

    /**
     * Gathers all the test data and builds a summary result
     *
     * @return null
     */
    private function buildStateSummary()
    {
        $req_status    = 1;
        $notice_status = -1;
        $last_error    = 'Unable to determine error response';
        foreach ($this->reqs as $key => $value) {
            if ($this->reqs[$key]['pass'] == 0) {
                $req_status = 0;
                $last_error = $this->reqs[$key]['info'];
                break;
            }
        }

        if (1 == $req_status) {
            foreach ($this->reqs as $key => $value) {
                if ($this->reqs[$key]['pass'] == 2) {
                    $req_status = 2;
                    break;
                }
            }
        }

        //Only show notice summary if a test was ran
        foreach ($this->notices as $key => $value) {
            if ($this->notices[$key]['pass'] == 0) {
                $notice_status = 0;
                break;
            } elseif ($this->notices[$key]['pass'] == 1) {
                $notice_status = 1;
            }
        }

        $this->lastError   = $last_error;
        $this->reqsPass    = $req_status;
        $this->noticesPass = $notice_status;
    }

    /**
     * Converts all test info messages to either TEXT or HTML format
     *
     * @return null
     */
    private function buildDisplaySummary()
    {
        if ($this->displayMode == 'TEXT') {
            //TODO: Format for text
        } else {
            //TODO: Format for html
        }
    }

    private function formatError(Exception $ex)
    {
        return "Message: ".htmlentities($ex->getMessage())."<br/>Line: ".htmlentities($ex->getFile()).':'.htmlentities($ex->getLine());
    }
}

Youez - 2016 - github.com/yon3zu
LinuXploit