CasperSecurity

Current Path : /usr/share/phpmyadmin/libraries/classes/
Upload File :
Current File : //usr/share/phpmyadmin/libraries/classes/ErrorHandler.php

<?php

declare(strict_types=1);

namespace PhpMyAdmin;

use const E_COMPILE_ERROR;
use const E_COMPILE_WARNING;
use const E_CORE_ERROR;
use const E_CORE_WARNING;
use const E_DEPRECATED;
use const E_ERROR;
use const E_NOTICE;
use const E_PARSE;
use const E_RECOVERABLE_ERROR;
use const E_STRICT;
use const E_USER_DEPRECATED;
use const E_USER_ERROR;
use const E_USER_NOTICE;
use const E_USER_WARNING;
use const E_WARNING;
use function array_splice;
use function count;
use function defined;
use function error_reporting;
use function headers_sent;
use function htmlspecialchars;
use function set_error_handler;
use function trigger_error;
use const PHP_VERSION_ID;

/**
 * handling errors
 */
class ErrorHandler
{
    /**
     * holds errors to be displayed or reported later ...
     *
     * @var Error[]
     */
    protected $errors = [];

    /**
     * Hide location of errors
     *
     * @var bool
     */
    protected $hideLocation = false;

    /**
     * Initial error reporting state
     *
     * @var int
     */
    protected $errorReporting = 0;

    public function __construct()
    {
        /**
         * Do not set ourselves as error handler in case of testsuite.
         *
         * This behavior is not tested there and breaks other tests as they
         * rely on PHPUnit doing it's own error handling which we break here.
         */
        if (! defined('TESTSUITE')) {
            set_error_handler([$this, 'handleError']);
        }
        if (! Util::isErrorReportingAvailable()) {
            return;
        }

        $this->errorReporting = error_reporting();
    }

    /**
     * Destructor
     *
     * stores errors in session
     */
    public function __destruct()
    {
        if (! isset($_SESSION['errors'])) {
            $_SESSION['errors'] = [];
        }

        // remember only not displayed errors
        foreach ($this->errors as $key => $error) {
            /**
             * We don't want to store all errors here as it would
             * explode user session.
             */
            if (count($_SESSION['errors']) >= 10) {
                $error = new Error(
                    0,
                    __('Too many error messages, some are not displayed.'),
                    __FILE__,
                    __LINE__
                );
                $_SESSION['errors'][$error->getHash()] = $error;
                break;
            }

            if ((! ($error instanceof Error))
                || $error->isDisplayed()
            ) {
                continue;
            }

            $_SESSION['errors'][$key] = $error;
        }
    }

    /**
     * Toggles location hiding
     *
     * @param bool $hide Whether to hide
     */
    public function setHideLocation(bool $hide): void
    {
        $this->hideLocation = $hide;
    }

    /**
     * returns array with all errors
     *
     * @param bool $check Whether to check for session errors
     *
     * @return Error[]
     */
    public function getErrors(bool $check = true): array
    {
        if ($check) {
            $this->checkSavedErrors();
        }

        return $this->errors;
    }

    /**
     * returns the errors occurred in the current run only.
     * Does not include the errors saved in the SESSION
     *
     * @return Error[]
     */
    public function getCurrentErrors(): array
    {
        return $this->errors;
    }

    /**
     * Pops recent errors from the storage
     *
     * @param int $count Old error count
     *
     * @return Error[]
     */
    public function sliceErrors(int $count): array
    {
        $errors = $this->getErrors(false);
        $this->errors = array_splice($errors, 0, $count);

        return array_splice($errors, $count);
    }

    /**
     * Error handler - called when errors are triggered/occurred
     *
     * This calls the addError() function, escaping the error string
     * Ignores the errors wherever Error Control Operator (@) is used.
     *
     * @param int    $errno   error number
     * @param string $errstr  error string
     * @param string $errfile error file
     * @param int    $errline error line
     */
    public function handleError(
        int $errno,
        string $errstr,
        string $errfile,
        int $errline
    ): void {
        if (Util::isErrorReportingAvailable()) {
            /**
            * Check if Error Control Operator (@) was used, but still show
            * user errors even in this case.
            * See: https://github.com/phpmyadmin/phpmyadmin/issues/16729
            */
            $isSilenced = ! (error_reporting() & $errno);
            if (PHP_VERSION_ID < 80000) {
                $isSilenced = error_reporting() == 0;
            }
            if ($isSilenced &&
                $this->errorReporting != 0 &&
                ($errno & (E_USER_WARNING | E_USER_ERROR | E_USER_NOTICE | E_USER_DEPRECATED)) == 0
            ) {
                return;
            }
        } else {
            if (($errno & (E_USER_WARNING | E_USER_ERROR | E_USER_NOTICE | E_USER_DEPRECATED)) == 0) {
                return;
            }
        }

        $this->addError($errstr, $errno, $errfile, $errline, true);
    }

    /**
     * Add an error; can also be called directly (with or without escaping)
     *
     * The following error types cannot be handled with a user defined function:
     * E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR,
     * E_COMPILE_WARNING,
     * and most of E_STRICT raised in the file where set_error_handler() is called.
     *
     * Do not use the context parameter as we want to avoid storing the
     * complete $GLOBALS inside $_SESSION['errors']
     *
     * @param string $errstr  error string
     * @param int    $errno   error number
     * @param string $errfile error file
     * @param int    $errline error line
     * @param bool   $escape  whether to escape the error string
     */
    public function addError(
        string $errstr,
        int $errno,
        string $errfile,
        int $errline,
        bool $escape = true
    ): void {
        if ($escape) {
            $errstr = htmlspecialchars($errstr);
        }
        // create error object
        $error = new Error(
            $errno,
            $errstr,
            $errfile,
            $errline
        );
        $error->setHideLocation($this->hideLocation);

        // do not repeat errors
        $this->errors[$error->getHash()] = $error;

        switch ($error->getNumber()) {
            case E_STRICT:
            case E_DEPRECATED:
            case E_NOTICE:
            case E_WARNING:
            case E_CORE_WARNING:
            case E_COMPILE_WARNING:
            case E_RECOVERABLE_ERROR:
                /* Avoid rendering BB code in PHP errors */
                $error->setBBCode(false);
                break;
            case E_USER_NOTICE:
            case E_USER_WARNING:
            case E_USER_ERROR:
            case E_USER_DEPRECATED:
                // just collect the error
                // display is called from outside
                break;
            case E_ERROR:
            case E_PARSE:
            case E_CORE_ERROR:
            case E_COMPILE_ERROR:
            default:
                // FATAL error, display it and exit
                $this->dispFatalError($error);
                exit;
        }
    }

    /**
     * trigger a custom error
     *
     * @param string $errorInfo   error message
     * @param int    $errorNumber error number
     */
    public function triggerError(string $errorInfo, ?int $errorNumber = null): void
    {
        // we could also extract file and line from backtrace
        // and call handleError() directly
        trigger_error($errorInfo, $errorNumber);
    }

    /**
     * display fatal error and exit
     *
     * @param Error $error the error
     */
    protected function dispFatalError(Error $error): void
    {
        if (! headers_sent()) {
            $this->dispPageStart($error);
        }
        echo $error->getDisplay();
        $this->dispPageEnd();
        exit;
    }

    /**
     * Displays user errors not displayed
     */
    public function dispUserErrors(): void
    {
        echo $this->getDispUserErrors();
    }

    /**
     * Renders user errors not displayed
     */
    public function getDispUserErrors(): string
    {
        $retval = '';
        foreach ($this->getErrors() as $error) {
            if (! $error->isUserError() || $error->isDisplayed()) {
                continue;
            }

            $retval .= $error->getDisplay();
        }

        return $retval;
    }

    /**
     * display HTML header
     *
     * @param Error $error the error
     */
    protected function dispPageStart(?Error $error = null): void
    {
        Response::getInstance()->disable();
        echo '<html><head><title>';
        if ($error) {
            echo $error->getTitle();
        } else {
            echo 'phpMyAdmin error reporting page';
        }
        echo '</title></head>';
    }

    /**
     * display HTML footer
     */
    protected function dispPageEnd(): void
    {
        echo '</body></html>';
    }

    /**
     * renders errors not displayed
     */
    public function getDispErrors(): string
    {
        $retval = '';
        // display errors if SendErrorReports is set to 'ask'.
        if ($GLOBALS['cfg']['SendErrorReports'] !== 'never') {
            foreach ($this->getErrors() as $error) {
                if ($error->isDisplayed()) {
                    continue;
                }

                $retval .= $error->getDisplay();
            }
        } else {
            $retval .= $this->getDispUserErrors();
        }
        // if preference is not 'never' and
        // there are 'actual' errors to be reported
        if ($GLOBALS['cfg']['SendErrorReports'] !== 'never'
            && $this->countErrors() !=  $this->countUserErrors()
        ) {
            // add report button.
            $retval .= '<form method="post" action="' . Url::getFromRoute('/error-report')
                    . '" id="pma_report_errors_form"';
            if ($GLOBALS['cfg']['SendErrorReports'] === 'always') {
                // in case of 'always', generate 'invisible' form.
                $retval .= ' class="hide"';
            }
            $retval .=  '>';
            $retval .= Url::getHiddenFields([
                'exception_type' => 'php',
                'send_error_report' => '1',
                'server' => $GLOBALS['server'],
            ]);
            $retval .= '<input type="submit" value="'
                    . __('Report')
                    . '" id="pma_report_errors" class="btn btn-primary floatright">'
                    . '<input type="checkbox" name="always_send"'
                    . ' id="always_send_checkbox" value="true">'
                    . '<label for="always_send_checkbox">'
                    . __('Automatically send report next time')
                    . '</label>';

            if ($GLOBALS['cfg']['SendErrorReports'] === 'ask') {
                // add ignore buttons
                $retval .= '<input type="submit" value="'
                        . __('Ignore')
                        . '" id="pma_ignore_errors_bottom" class="btn btn-secondary floatright">';
            }
            $retval .= '<input type="submit" value="'
                    . __('Ignore All')
                    . '" id="pma_ignore_all_errors_bottom" class="btn btn-secondary floatright">';
            $retval .= '</form>';
        }

        return $retval;
    }

    /**
     * look in session for saved errors
     */
    protected function checkSavedErrors(): void
    {
        if (! isset($_SESSION['errors'])) {
            return;
        }

        // restore saved errors
        foreach ($_SESSION['errors'] as $hash => $error) {
            if (! ($error instanceof Error) || isset($this->errors[$hash])) {
                continue;
            }

            $this->errors[$hash] = $error;
        }

        // delete stored errors
        $_SESSION['errors'] = [];
        unset($_SESSION['errors']);
    }

    /**
     * return count of errors
     *
     * @param bool $check Whether to check for session errors
     *
     * @return int number of errors occurred
     */
    public function countErrors(bool $check = true): int
    {
        return count($this->getErrors($check));
    }

    /**
     * return count of user errors
     *
     * @return int number of user errors occurred
     */
    public function countUserErrors(): int
    {
        $count = 0;
        if ($this->countErrors()) {
            foreach ($this->getErrors() as $error) {
                if (! $error->isUserError()) {
                    continue;
                }

                $count++;
            }
        }

        return $count;
    }

    /**
     * whether use errors occurred or not
     */
    public function hasUserErrors(): bool
    {
        return (bool) $this->countUserErrors();
    }

    /**
     * whether errors occurred or not
     */
    public function hasErrors(): bool
    {
        return (bool) $this->countErrors();
    }

    /**
     * number of errors to be displayed
     *
     * @return int number of errors to be displayed
     */
    public function countDisplayErrors(): int
    {
        if ($GLOBALS['cfg']['SendErrorReports'] !== 'never') {
            return $this->countErrors();
        }

        return $this->countUserErrors();
    }

    /**
     * whether there are errors to display or not
     */
    public function hasDisplayErrors(): bool
    {
        return (bool) $this->countDisplayErrors();
    }

    /**
     * Deletes previously stored errors in SESSION.
     * Saves current errors in session as previous errors.
     * Required to save current errors in case  'ask'
     */
    public function savePreviousErrors(): void
    {
        unset($_SESSION['prev_errors']);
        $_SESSION['prev_errors'] = $GLOBALS['error_handler']->getCurrentErrors();
    }

    /**
     * Function to check if there are any errors to be prompted.
     * Needed because user warnings raised are
     *      also collected by global error handler.
     * This distinguishes between the actual errors
     *      and user errors raised to warn user.
     *
     * @return bool true if there are errors to be "prompted", false otherwise
     */
    public function hasErrorsForPrompt(): bool
    {
        return $GLOBALS['cfg']['SendErrorReports'] !== 'never'
            && $this->countErrors() !=  $this->countUserErrors();
    }

    /**
     * Function to report all the collected php errors.
     * Must be called at the end of each script
     *      by the $GLOBALS['error_handler'] only.
     */
    public function reportErrors(): void
    {
        // if there're no actual errors,
        if (! $this->hasErrors()
            || $this->countErrors() ==  $this->countUserErrors()
        ) {
            // then simply return.
            return;
        }
        // Delete all the prev_errors in session & store new prev_errors in session
        $this->savePreviousErrors();
        $response = Response::getInstance();
        $jsCode = '';
        if ($GLOBALS['cfg']['SendErrorReports'] === 'always') {
            if ($response->isAjax()) {
                // set flag for automatic report submission.
                $response->addJSON('sendErrorAlways', '1');
            } else {
                // send the error reports asynchronously & without asking user
                $jsCode .= '$("#pma_report_errors_form").submit();'
                        . 'Functions.ajaxShowMessage(
                            Messages.phpErrorsBeingSubmitted, false
                        );';
                // js code to appropriate focusing,
                $jsCode .= '$("html, body").animate({
                                scrollTop:$(document).height()
                            }, "slow");';
            }
        } elseif ($GLOBALS['cfg']['SendErrorReports'] === 'ask') {
            //ask user whether to submit errors or not.
            if (! $response->isAjax()) {
                // js code to show appropriate msgs, event binding & focusing.
                $jsCode = 'Functions.ajaxShowMessage(Messages.phpErrorsFound);'
                        . '$("#pma_ignore_errors_popup").on("click", function() {
                            Functions.ignorePhpErrors()
                        });'
                        . '$("#pma_ignore_all_errors_popup").on("click",
                            function() {
                                Functions.ignorePhpErrors(false)
                            });'
                        . '$("#pma_ignore_errors_bottom").on("click", function(e) {
                            e.preventDefault();
                            Functions.ignorePhpErrors()
                        });'
                        . '$("#pma_ignore_all_errors_bottom").on("click",
                            function(e) {
                                e.preventDefault();
                                Functions.ignorePhpErrors(false)
                            });'
                        . '$("html, body").animate({
                            scrollTop:$(document).height()
                        }, "slow");';
            }
        }
        // The errors are already sent from the response.
        // Just focus on errors division upon load event.
        $response->getFooter()->getScripts()->addCode($jsCode);
    }
}
Hacker Blog, Shell İndir, Sql İnjection, XSS Attacks, LFI Attacks, Social Hacking, Exploit Bot, Proxy Tools, Web Shell, PHP Shell, Alfa Shell İndir, Hacking Training Set, DDoS Script, Denial Of Service, Botnet, RFI Attacks, Encryption
Telegram @BIBIL_0DAY