123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Framework\Error;
- use Magento\Framework\Serialize\Serializer\Json;
- /**
- * Error processor
- *
- * @SuppressWarnings(PHPMD.TooManyFields)
- */
- class Processor
- {
- const MAGE_ERRORS_LOCAL_XML = 'local.xml';
- const MAGE_ERRORS_DESIGN_XML = 'design.xml';
- const DEFAULT_SKIN = 'default';
- const ERROR_DIR = 'pub/errors';
- /**
- * Page title
- *
- * @var string
- */
- public $pageTitle;
- /**
- * Skin URL
- *
- * @var string
- */
- public $skinUrl;
- /**
- * Base URL
- *
- * @var string
- */
- public $baseUrl;
- /**
- * Post data
- *
- * @var array
- */
- public $postData;
- /**
- * Report data
- *
- * @var array
- */
- public $reportData;
- /**
- * Report action
- *
- * @var string
- */
- public $reportAction;
- /**
- * Report ID
- *
- * @var int
- */
- public $reportId;
- /**
- * Report file
- *
- * @var string
- */
- protected $_reportFile;
- /**
- * Show error message
- *
- * @var bool
- */
- public $showErrorMsg;
- /**
- * Show message after sending email
- *
- * @var bool
- */
- public $showSentMsg;
- /**
- * Show form for sending
- *
- * @var bool
- */
- public $showSendForm;
- /**
- * @var string
- */
- public $reportUrl;
- /**
- * Server script name
- *
- * @var string
- */
- protected $_scriptName;
- /**
- * Is root
- *
- * @var bool
- */
- protected $_root;
- /**
- * Internal config object
- *
- * @var \stdClass
- */
- protected $_config;
- /**
- * Http response
- *
- * @var \Magento\Framework\App\Response\Http
- */
- protected $_response;
- /**
- * JSON serializer
- *
- * @var Json
- */
- private $serializer;
- /**
- * @param \Magento\Framework\App\Response\Http $response
- * @param Json $serializer
- */
- public function __construct(\Magento\Framework\App\Response\Http $response, Json $serializer = null)
- {
- $this->_response = $response;
- $this->_errorDir = __DIR__ . '/';
- $this->_reportDir = dirname(dirname($this->_errorDir)) . '/var/report/';
- $this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance()->get(Json::class);
- if (!empty($_SERVER['SCRIPT_NAME'])) {
- if (in_array(basename($_SERVER['SCRIPT_NAME'], '.php'), ['404', '503', 'report'])) {
- $this->_scriptName = dirname($_SERVER['SCRIPT_NAME']);
- } else {
- $this->_scriptName = $_SERVER['SCRIPT_NAME'];
- }
- }
- $reportId = (isset($_GET['id'])) ? (int)$_GET['id'] : null;
- if ($reportId) {
- $this->loadReport($reportId);
- }
- $this->_indexDir = $this->_getIndexDir();
- $this->_root = is_dir($this->_indexDir . 'app');
- $this->_prepareConfig();
- if (isset($_GET['skin'])) {
- $this->_setSkin($_GET['skin']);
- }
- }
- /**
- * Process no cache error
- *
- * @return \Magento\Framework\App\Response\Http
- */
- public function processNoCache()
- {
- $this->pageTitle = 'Error : cached config data is unavailable';
- $this->_response->setBody($this->_renderPage('nocache.phtml'));
- return $this->_response;
- }
- /**
- * Process 404 error
- *
- * @return \Magento\Framework\App\Response\Http
- */
- public function process404()
- {
- $this->pageTitle = 'Error 404: Not Found';
- $this->_response->setHttpResponseCode(404);
- $this->_response->setBody($this->_renderPage('404.phtml'));
- return $this->_response;
- }
- /**
- * Process 503 error
- *
- * @return \Magento\Framework\App\Response\Http
- */
- public function process503()
- {
- $this->pageTitle = 'Error 503: Service Unavailable';
- $this->_response->setHttpResponseCode(503);
- $this->_response->setBody($this->_renderPage('503.phtml'));
- return $this->_response;
- }
- /**
- * Process report
- *
- * @return \Magento\Framework\App\Response\Http
- */
- public function processReport()
- {
- $this->pageTitle = 'There has been an error processing your request';
- $this->_response->setHttpResponseCode(500);
- $this->showErrorMsg = false;
- $this->showSentMsg = false;
- $this->showSendForm = false;
- $this->reportAction = $this->_config->action;
- $this->_setReportUrl();
- if ($this->reportAction == 'email') {
- $this->showSendForm = true;
- $this->sendReport();
- }
- $this->_response->setBody($this->_renderPage('report.phtml'));
- return $this->_response;
- }
- /**
- * Retrieve skin URL
- *
- * @return string
- */
- public function getViewFileUrl()
- {
- //The url needs to be updated base on Document root path.
- return $this->getBaseUrl() .
- str_replace(
- str_replace('\\', '/', $this->_indexDir),
- '',
- str_replace('\\', '/', $this->_errorDir)
- ) . $this->_config->skin . '/';
- }
- /**
- * Retrieve base host URL without path
- *
- * @return string
- */
- public function getHostUrl()
- {
- /**
- * Define server http host
- */
- $host = $this->resolveHostName();
- $isSecure = (!empty($_SERVER['HTTPS'])) && ($_SERVER['HTTPS'] !== 'off')
- || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && ($_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https');
- $url = ($isSecure ? 'https://' : 'http://') . $host;
- $port = explode(':', $host);
- if (isset($port[1]) && !in_array($port[1], [80, 443])
- && !preg_match('/.*?\:[0-9]+$/', $url)
- ) {
- $url .= ':' . $port[1];
- }
- return $url;
- }
- /**
- * Resolve hostname
- *
- * @return string
- */
- private function resolveHostName() : string
- {
- if (!empty($_SERVER['HTTP_HOST'])) {
- $host = $_SERVER['HTTP_HOST'];
- } elseif (!empty($_SERVER['SERVER_NAME'])) {
- $host = $_SERVER['SERVER_NAME'];
- } else {
- $host = 'localhost';
- }
- return $host;
- }
- /**
- * Retrieve base URL
- *
- * @param bool $param
- * @return string
- */
- public function getBaseUrl($param = false)
- {
- $path = $this->_scriptName;
- if ($param && !$this->_root) {
- $path = dirname($path);
- }
- $basePath = str_replace('\\', '/', dirname($path));
- return $this->getHostUrl() . ('/' == $basePath ? '' : $basePath) . '/';
- }
- /**
- * Retrieve client IP address
- *
- * @return string
- */
- protected function _getClientIp()
- {
- return (isset($_SERVER['REMOTE_ADDR'])) ? $_SERVER['REMOTE_ADDR'] : 'undefined';
- }
- /**
- * Get index dir
- *
- * @return string
- */
- protected function _getIndexDir()
- {
- $documentRoot = '';
- if (!empty($_SERVER['DOCUMENT_ROOT'])) {
- $documentRoot = rtrim(realpath($_SERVER['DOCUMENT_ROOT']), '/');
- }
- return dirname($documentRoot . $this->_scriptName) . '/';
- }
- /**
- * Prepare config data
- *
- * @return void
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- * @SuppressWarnings(PHPMD.NPathComplexity)
- */
- protected function _prepareConfig()
- {
- $local = $this->_loadXml(self::MAGE_ERRORS_LOCAL_XML);
- $design = $this->_loadXml(self::MAGE_ERRORS_DESIGN_XML);
- //initial settings
- $config = new \stdClass();
- $config->action = '';
- $config->subject = 'Store Debug Information';
- $config->email_address = '';
- $config->trash = 'leave';
- $config->skin = self::DEFAULT_SKIN;
- //combine xml data to one object
- if ($design !== null && (string)$design->skin) {
- $this->_setSkin((string)$design->skin, $config);
- }
- if ($local !== null) {
- if ((string)$local->report->action) {
- $config->action = $local->report->action;
- }
- if ((string)$local->report->subject) {
- $config->subject = $local->report->subject;
- }
- if ((string)$local->report->email_address) {
- $config->email_address = $local->report->email_address;
- }
- if ((string)$local->report->trash) {
- $config->trash = $local->report->trash;
- }
- if ((string)$local->skin) {
- $this->_setSkin((string)$local->skin, $config);
- }
- }
- if ((string)$config->email_address == '' && (string)$config->action == 'email') {
- $config->action = '';
- }
- $this->_config = $config;
- }
- /**
- * Load xml file
- *
- * @param string $xmlFile
- * @return \SimpleXMLElement
- */
- protected function _loadXml($xmlFile)
- {
- $configPath = $this->_getFilePath($xmlFile);
- return ($configPath) ? simplexml_load_file($configPath) : null;
- }
- /**
- * Render page
- *
- * @param string $template
- * @return string
- */
- protected function _renderPage($template)
- {
- $baseTemplate = $this->_getTemplatePath('page.phtml');
- $contentTemplate = $this->_getTemplatePath($template);
- $html = '';
- if ($baseTemplate && $contentTemplate) {
- ob_start();
- require_once $baseTemplate;
- $html = ob_get_clean();
- }
- return $html;
- }
- /**
- * Find file path
- *
- * @param string $file
- * @param array $directories
- * @return string
- */
- protected function _getFilePath($file, $directories = null)
- {
- if ($directories === null) {
- $directories[] = $this->_errorDir;
- }
- foreach ($directories as $directory) {
- if (file_exists($directory . $file)) {
- return $directory . $file;
- }
- }
- }
- /**
- * Find template path
- *
- * @param string $template
- * @return string
- */
- protected function _getTemplatePath($template)
- {
- $directories[] = $this->_errorDir . $this->_config->skin . '/';
- if ($this->_config->skin != self::DEFAULT_SKIN) {
- $directories[] = $this->_errorDir . self::DEFAULT_SKIN . '/';
- }
- return $this->_getFilePath($template, $directories);
- }
- /**
- * Set report data
- *
- * @param array $reportData
- * @return void
- */
- protected function _setReportData($reportData)
- {
- $this->reportData = $reportData;
- if (!isset($reportData['url'])) {
- $this->reportData['url'] = '';
- } else {
- $this->reportData['url'] = $this->getHostUrl() . $reportData['url'];
- }
- if ($this->reportData['script_name']) {
- $this->_scriptName = $this->reportData['script_name'];
- }
- }
- /**
- * Create report
- *
- * @param array $reportData
- * @return string
- */
- public function saveReport($reportData)
- {
- $this->reportData = $reportData;
- $this->reportId = abs((int)(microtime(true) * random_int(100, 1000)));
- $this->_reportFile = $this->_reportDir . '/' . $this->reportId;
- $this->_setReportData($reportData);
- if (!file_exists($this->_reportDir)) {
- @mkdir($this->_reportDir, 0777, true);
- }
- @file_put_contents($this->_reportFile, $this->serializer->serialize($reportData));
- if (isset($reportData['skin']) && self::DEFAULT_SKIN != $reportData['skin']) {
- $this->_setSkin($reportData['skin']);
- }
- $this->_setReportUrl();
- return $this->reportUrl;
- }
- /**
- * Get report
- *
- * @param int $reportId
- * @return void
- * @SuppressWarnings(PHPMD.ExitExpression)
- */
- public function loadReport($reportId)
- {
- $this->reportId = $reportId;
- $this->_reportFile = $this->_reportDir . '/' . $reportId;
- if (!file_exists($this->_reportFile) || !is_readable($this->_reportFile)) {
- header("Location: " . $this->getBaseUrl());
- die();
- }
- $this->_setReportData($this->serializer->unserialize(file_get_contents($this->_reportFile)));
- }
- /**
- * Send report
- *
- * @return void
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- * @SuppressWarnings(PHPMD.NPathComplexity)
- */
- public function sendReport()
- {
- $this->pageTitle = 'Error Submission Form';
- $this->postData['firstName'] = (isset($_POST['firstname'])) ? trim(htmlspecialchars($_POST['firstname'])) : '';
- $this->postData['lastName'] = (isset($_POST['lastname'])) ? trim(htmlspecialchars($_POST['lastname'])) : '';
- $this->postData['email'] = (isset($_POST['email'])) ? trim(htmlspecialchars($_POST['email'])) : '';
- $this->postData['telephone'] = (isset($_POST['telephone'])) ? trim(htmlspecialchars($_POST['telephone'])) : '';
- $this->postData['comment'] = (isset($_POST['comment'])) ? trim(htmlspecialchars($_POST['comment'])) : '';
- if (isset($_POST['submit'])) {
- if ($this->_validate()) {
- $msg = "URL: {$this->reportData['url']}\n"
- . "IP Address: {$this->_getClientIp()}\n"
- . "First Name: {$this->postData['firstName']}\n"
- . "Last Name: {$this->postData['lastName']}\n"
- . "Email Address: {$this->postData['email']}\n";
- if ($this->postData['telephone']) {
- $msg .= "Telephone: {$this->postData['telephone']}\n";
- }
- if ($this->postData['comment']) {
- $msg .= "Comment: {$this->postData['comment']}\n";
- }
- $subject = sprintf('%s [%s]', (string)$this->_config->subject, $this->reportId);
- @mail((string)$this->_config->email_address, $subject, $msg);
- $this->showSendForm = false;
- $this->showSentMsg = true;
- } else {
- $this->showErrorMsg = true;
- }
- } else {
- $time = gmdate('Y-m-d H:i:s \G\M\T');
- $msg = "URL: {$this->reportData['url']}\n"
- . "IP Address: {$this->_getClientIp()}\n"
- . "Time: {$time}\n"
- . "Error:\n{$this->reportData[0]}\n\n"
- . "Trace:\n{$this->reportData[1]}";
- $subject = sprintf('%s [%s]', (string)$this->_config->subject, $this->reportId);
- @mail((string)$this->_config->email_address, $subject, $msg);
- if ($this->_config->trash == 'delete') {
- @unlink($this->_reportFile);
- }
- }
- }
- /**
- * Validate submitted post data
- *
- * @return bool
- */
- protected function _validate()
- {
- $email = preg_match(
- '/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/',
- $this->postData['email']
- );
- return ($this->postData['firstName'] && $this->postData['lastName'] && $email);
- }
- /**
- * Skin setter
- *
- * @param string $value
- * @param \stdClass $config
- * @return void
- */
- protected function _setSkin($value, \stdClass $config = null)
- {
- if (preg_match('/^[a-z0-9_]+$/i', $value) && is_dir($this->_errorDir . $value)) {
- if (!$config) {
- if ($this->_config) {
- $config = $this->_config;
- }
- }
- if ($config) {
- $config->skin = $value;
- }
- }
- }
- /**
- * Set current report URL from current params
- *
- * @return void
- */
- protected function _setReportUrl()
- {
- if ($this->reportId && $this->_config && isset($this->_config->skin)) {
- $this->reportUrl = "{$this->getBaseUrl(true)}pub/errors/report.php?"
- . http_build_query(['id' => $this->reportId, 'skin' => $this->_config->skin]);
- }
- }
- }
|