316 lines
11 KiB
PHP
Executable File
316 lines
11 KiB
PHP
Executable File
<?php
|
|
|
|
/**
|
|
* This file is part of O3-Shop.
|
|
*
|
|
* O3-Shop is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, version 3.
|
|
*
|
|
* O3-Shop is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with O3-Shop. If not, see <http://www.gnu.org/licenses/>
|
|
*
|
|
* @copyright Copyright (c) 2022 OXID eSales AG (https://www.oxid-esales.com)
|
|
* @copyright Copyright (c) 2022 O3-Shop (https://www.o3-shop.com)
|
|
* @license https://www.gnu.org/licenses/gpl-3.0 GNU General Public License 3 (GPLv3)
|
|
*/
|
|
|
|
error_reporting(E_ALL & ~E_DEPRECATED & ~E_NOTICE);
|
|
ini_set('display_errors', '0');
|
|
|
|
define('INSTALLATION_ROOT_PATH', dirname(__DIR__));
|
|
define('OX_BASE_PATH', INSTALLATION_ROOT_PATH . DIRECTORY_SEPARATOR . 'source' . DIRECTORY_SEPARATOR);
|
|
define('OX_LOG_FILE', OX_BASE_PATH . 'log' . DIRECTORY_SEPARATOR . 'oxideshop.log');
|
|
define('OX_OFFLINE_FILE', OX_BASE_PATH . 'offline.html');
|
|
define('VENDOR_PATH', INSTALLATION_ROOT_PATH . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR);
|
|
|
|
/**
|
|
* Provide a handler for catchable fatal errors, like failed requirement of files.
|
|
* No information about paths or file names must be disclosed to the frontend,
|
|
* as this would be a security problem on productive systems.
|
|
* This error handler is just a last resort for exceptions, which are not caught by the application.
|
|
*
|
|
* As this is the last resort no further errors must happen.
|
|
*/
|
|
register_shutdown_function(
|
|
function () {
|
|
$handledErrorTypes = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_RECOVERABLE_ERROR, E_USER_ERROR];
|
|
$sessionResetErrorTypes = [E_ERROR];
|
|
|
|
$error = error_get_last();
|
|
if ($error !== null && in_array($error['type'], $handledErrorTypes)) {
|
|
$errorType = array_flip(array_slice(get_defined_constants(true)['Core'], 0, 16, true))[$error['type']];
|
|
|
|
$errorMessage = $error['message'];
|
|
$unifiedNamespaceClassNotFound = preg_match(
|
|
'/^Class \'OxidEsales\\\\Eshop\\\\.*\' not found/',
|
|
$errorMessage,
|
|
$matches
|
|
);
|
|
if (1 === $unifiedNamespaceClassNotFound) {
|
|
$errorMessage .= '. Is an autogenerated class file missing? ' .
|
|
'Please run "composer oe:unified-namespace:generate" and double-check for errors. ' .
|
|
'Also double-check, if the class file for this very class was created.';
|
|
}
|
|
/** report the error */
|
|
$logMessage = "[uncaught error] [type $errorType] [file {$error['file']}] [line {$error['line']}] [code ]" .
|
|
" [message {$errorMessage}]";
|
|
|
|
/** write to log */
|
|
$time = microtime(true);
|
|
$micro = sprintf("%06d", ($time - floor($time)) * 1000000);
|
|
$date = new \DateTime(date('Y-m-d H:i:s.' . $micro, $time));
|
|
$timestamp = $date->format('d M H:i:s.u Y');
|
|
$message = "[$timestamp] " . $logMessage . PHP_EOL;
|
|
file_put_contents(OX_LOG_FILE, $message, FILE_APPEND);
|
|
|
|
|
|
$bootstrapConfigFileReader = new \BootstrapConfigFileReader();
|
|
if (!$bootstrapConfigFileReader->isDebugMode()) {
|
|
\oxTriggerOfflinePageDisplay();
|
|
}
|
|
|
|
if (in_array($error['type'], $sessionResetErrorTypes)) {
|
|
setcookie('sid', null, null, '/');
|
|
setcookie('admin_sid', null, null, '/');
|
|
}
|
|
}
|
|
}
|
|
);
|
|
|
|
// phpcs:disable
|
|
/**
|
|
* Helper for loading and getting the config file contents
|
|
*/
|
|
class BootstrapConfigFileReader
|
|
{
|
|
protected array $dynamicProperties = [];
|
|
|
|
/**
|
|
* @param string $name
|
|
* @param mixed $value
|
|
* @return void
|
|
*/
|
|
public function __set(string $name, $value): void
|
|
{
|
|
$this->dynamicProperties[$name] = $value;
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
* @return bool
|
|
*/
|
|
public function __isset(string $name): bool
|
|
{
|
|
return isset($this->dynamicProperties[$name]);
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
* @return mixed
|
|
*/
|
|
public function __get(string $name)
|
|
{
|
|
if (array_key_exists($name, $this->dynamicProperties)) {
|
|
return $this->dynamicProperties[$name];
|
|
}
|
|
|
|
$trace = debug_backtrace();
|
|
trigger_error(
|
|
'Undefined property via __get(): ' . $name .
|
|
' in ' . $trace[0]['file'] .
|
|
' on line ' . $trace[0]['line']);
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
* @return void
|
|
*/
|
|
public function __unset(string $name): void
|
|
{
|
|
unset($this->dynamicProperties[$name]);
|
|
}
|
|
|
|
/**
|
|
* BootstrapConfigFileReader constructor.
|
|
*/
|
|
public function __construct()
|
|
{
|
|
include OX_BASE_PATH . "config.inc.php";
|
|
}
|
|
|
|
/**
|
|
* Check if debug mode is On.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function isDebugMode()
|
|
{
|
|
return (bool) $this->iDebug;
|
|
}
|
|
}
|
|
// phpcs:enable
|
|
|
|
/**
|
|
* Ensure shop config and autoload files are available.
|
|
*/
|
|
$configMissing = !is_readable(OX_BASE_PATH . "config.inc.php");
|
|
if ($configMissing || !is_readable(VENDOR_PATH . 'autoload.php')) {
|
|
if ($configMissing) {
|
|
$message = sprintf(
|
|
"Error: Config file '%s' could not be found! Please use '%s.dist' to make a copy.",
|
|
OX_BASE_PATH . "config.inc.php",
|
|
OX_BASE_PATH . "config.inc.php"
|
|
);
|
|
} else {
|
|
$message = "Error: Autoload file missing. Make sure you have ran the 'composer install' command.";
|
|
}
|
|
|
|
trigger_error($message, E_USER_ERROR);
|
|
}
|
|
unset($configMissing);
|
|
|
|
/**
|
|
* Turn on display errors for debug mode
|
|
*/
|
|
$bootstrapConfigFileReader = new \BootstrapConfigFileReader();
|
|
if ($bootstrapConfigFileReader->isDebugMode()) {
|
|
ini_set('display_errors', '1');
|
|
error_reporting(E_ALL & ~E_DEPRECATED);
|
|
}
|
|
unset($bootstrapConfigFileReader);
|
|
|
|
/**
|
|
* Register basic the autoloaders. In this phase we still do not want to use other shop classes to make autoloading
|
|
* as decoupled as possible.
|
|
*/
|
|
|
|
/*
|
|
* Require and register composer autoloader.
|
|
* This autoloader will load classes in the real existing namespace like '\OxidEsales\EshopCommunity\Core\UtilsObject'
|
|
* It will always come first, even if you move it after the other autoloaders as it registers itself with prepend = true
|
|
*/
|
|
require_once VENDOR_PATH . 'autoload.php';
|
|
|
|
/**
|
|
* Where CORE_AUTOLOADER_PATH points depends on how O3-Shop has been installed. If it is installed as part of a
|
|
* compilation, the directory 'Core', where the auto load classes are located, does not reside inside OX_BASE_PATH,
|
|
* but inside VENDOR_PATH.
|
|
*/
|
|
if (!is_dir(OX_BASE_PATH . 'Core')) {
|
|
define('CORE_AUTOLOADER_PATH', (new \OxidEsales\Facts\Facts())->getCommunityEditionSourcePath() .
|
|
DIRECTORY_SEPARATOR .
|
|
'Core' . DIRECTORY_SEPARATOR .
|
|
'Autoload' . DIRECTORY_SEPARATOR);
|
|
} else {
|
|
define('CORE_AUTOLOADER_PATH', OX_BASE_PATH . 'Core' . DIRECTORY_SEPARATOR . 'Autoload' . DIRECTORY_SEPARATOR);
|
|
}
|
|
|
|
/*
|
|
* Register the backwards compatibility autoloader.
|
|
* This autoloader will load classes for reasons of backwards compatibility like 'oxArticle'.
|
|
*/
|
|
require_once CORE_AUTOLOADER_PATH . 'BackwardsCompatibilityAutoload.php';
|
|
spl_autoload_register([OxidEsales\EshopCommunity\Core\Autoload\BackwardsCompatibilityAutoload::class, 'autoload']);
|
|
|
|
/**
|
|
* Register the module autoloader.
|
|
* It will load classes classes defined in the metadata key 'files'
|
|
* When this autoloader is called a database connection will be triggered
|
|
*/
|
|
require_once CORE_AUTOLOADER_PATH . 'ModuleAutoload.php';
|
|
spl_autoload_register([\OxidEsales\EshopCommunity\Core\Autoload\ModuleAutoload::class, 'autoload']);
|
|
|
|
|
|
/**
|
|
* Store the shop configuration in the Registry prior including the custom bootstrap functionality.
|
|
* Like this the shop configuration is available there.
|
|
*/
|
|
$configFile = new \OxidEsales\Eshop\Core\ConfigFile(OX_BASE_PATH . "config.inc.php");
|
|
\OxidEsales\Eshop\Core\Registry::set(\OxidEsales\Eshop\Core\ConfigFile::class, $configFile);
|
|
unset($configFile);
|
|
|
|
/**
|
|
* Set exception handler before including modules/functions.php so it can be overwritten easiliy by shop operators.
|
|
*/
|
|
$debugMode = (bool) \OxidEsales\Eshop\Core\Registry::get(\OxidEsales\Eshop\Core\ConfigFile::class)->getVar('iDebug');
|
|
set_exception_handler(
|
|
[
|
|
new \OxidEsales\Eshop\Core\Exception\ExceptionHandler($debugMode),
|
|
'handleUncaughtException'
|
|
]
|
|
);
|
|
unset($debugMode);
|
|
|
|
/**
|
|
* Generic utility method file.
|
|
* The global object factory function oxNew is defined here.
|
|
*/
|
|
require_once OX_BASE_PATH . 'oxfunctions.php';
|
|
|
|
/**
|
|
* Custom bootstrap functionality.
|
|
*/
|
|
if (@is_readable(OX_BASE_PATH . 'modules/functions.php')) {
|
|
include OX_BASE_PATH . 'modules/functions.php';
|
|
}
|
|
|
|
/**
|
|
* The functions defined conditionally in this file may have been overwritten in 'modules/functions.php',
|
|
* so their functionality may have changed completely.
|
|
*/
|
|
require_once OX_BASE_PATH . 'overridablefunctions.php';
|
|
|
|
//sets default PHP ini params
|
|
ini_set('session.name', 'sid');
|
|
ini_set('session.use_cookies', 0);
|
|
ini_set('session.use_trans_sid', 0);
|
|
ini_set('url_rewriter.tags', '');
|
|
|
|
if (!function_exists('oxTriggerOfflinePageDisplay')) {
|
|
/**
|
|
* Bulletproof offline page loader
|
|
*/
|
|
function oxTriggerOfflinePageDisplay()
|
|
{
|
|
// Do not display the offline page, if this running in CLI mode
|
|
if ('cli' !== strtolower(php_sapi_name())) {
|
|
header("HTTP/1.1 500 Internal Server Error");
|
|
header("Connection: close");
|
|
|
|
/**
|
|
* Render an error message.
|
|
* If offline.php exists its content is displayed.
|
|
* Like this the error message is overridable within that file.
|
|
*/
|
|
if (is_readable(OX_OFFLINE_FILE)) {
|
|
echo file_get_contents(OX_OFFLINE_FILE);
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @deprecated since v6.3 (2018-04-18); This method will be removed completely.
|
|
* Use OxidEsales\Eshop\Core\Registry::getLogger() in the future.
|
|
*
|
|
* @param string $message
|
|
*/
|
|
function writeToLog($message)
|
|
{
|
|
$time = microtime(true);
|
|
$micro = sprintf("%06d", ($time - floor($time)) * 1000000);
|
|
$date = new \DateTime(date('Y-m-d H:i:s.' . $micro, $time));
|
|
$timestamp = $date->format('d M H:i:s.u Y');
|
|
|
|
$message = "[$timestamp] " . $message . PHP_EOL;
|
|
|
|
file_put_contents(OX_LOG_FILE, $message, FILE_APPEND);
|
|
}
|