* @copyright Since 2007 PrestaShop SA and Contributors * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) */ /** * @since 1.5.0 */ class PrestaShopExceptionCore extends Exception { /** * This method acts like an error handler, if dev mode is on, display the error else use a better silent way. */ public function displayMessage() { if (getenv('kernel.environment') === 'test') { throw $this; } header('HTTP/1.1 500 Internal Server Error'); if (ToolsCore::isPHPCLI()) { echo get_class($this) . ' in ' . $this->getFile() . ' line ' . $this->getLine() . "\n"; echo $this->getTraceAsString() . "\n"; } elseif (_PS_MODE_DEV_) { // Display error message echo ''; echo '
'; echo '

[' . get_class($this) . ']

'; echo $this->getExtendedMessage(); $this->displayFileDebug($this->getFile(), $this->getLine()); // Display debug backtrace echo ''; echo '
'; } else { // If not in mode dev, display an error page if (file_exists(_PS_ROOT_DIR_ . '/error500.html')) { echo file_get_contents(_PS_ROOT_DIR_ . '/error500.html'); } } // Log the error in the disk $this->logError(); //We only need the error code 1 in cli context exit((int) ToolsCore::isPHPCLI()); } /** * Display lines around current line. * * @param string $file * @param int $line * @param int|null $id */ protected function displayFileDebug($file, $line, $id = null) { $lines = file($file); $offset = $line - 6; $total = 11; if ($offset < 0) { $total += $offset; $offset = 0; } $lines = array_slice($lines, $offset, $total); ++$offset; echo '
';
        foreach ($lines as $k => $l) {
            $string = ($offset + $k) . '. ' . htmlspecialchars($l);
            if ($offset + $k == $line) {
                echo '' . $string . '';
            } else {
                echo $string;
            }
        }
        echo '
'; } /** * Prevent critical arguments to be displayed in the debug trace page (e.g. database password) * Returns the array of args with critical arguments replaced by placeholders. * * @param array $trace * * @return array */ protected function hideCriticalArgs(array $trace) { $args = $trace['args']; if (empty($trace['class']) || empty($trace['function'])) { return $args; } $criticalParameters = [ 'pwd', 'pass', 'passwd', 'password', 'database', 'server', ]; $hiddenArgs = []; try { $class = new \ReflectionClass($trace['class']); /** @var \ReflectionMethod $method */ $method = $class->getMethod($trace['function']); /** @var \ReflectionParameter $parameter */ foreach ($method->getParameters() as $argIndex => $parameter) { if ($argIndex >= count($args)) { break; } if (in_array(strtolower($parameter->getName()), $criticalParameters)) { $hiddenArgs[] = '**hidden_' . $parameter->getName() . '**'; } else { $hiddenArgs[] = $args[$argIndex]; } } } catch (ReflectionException $e) { //In worst case scenario there are some critical args we could't detect so we return an empty array } return $hiddenArgs; } /** * Display arguments list of traced function. * * @param array $args List of arguments * @param int $id ID of argument */ protected function displayArgsDebug($args, $id) { echo '
';
        foreach ($args as $arg => $value) {
            echo 'Argument [' . Tools::safeOutput($arg) . "]\n";
            echo Tools::safeOutput(print_r($value, true));
            echo "\n";
        }
        echo '
'; } /** * Log the error on the disk. */ protected function logError() { $logger = new FileLogger(); $logger->setFilename(_PS_ROOT_DIR_ . '/var/logs/' . date('Ymd') . '_exception.log'); $logger->logError($this->getExtendedMessage(false)); } /** * Return the content of the Exception. * * @return string content of the exception */ protected function getExtendedMessage($html = true) { $format = '

%s
at line %d in file %s

'; if (!$html) { $format = strip_tags(str_replace('
', ' ', $format)); } return sprintf( $format, Tools::safeOutput($this->getMessage(), true), $this->getLine(), ltrim(str_replace([_PS_ROOT_DIR_, '\\'], ['', '/'], $this->getFile()), '/') ); } }