<?php
$microstat = microtime(true);
define('VERSION', '1.5.6.5_rc');

if (file_exists('config.php')) {
	require_once('config.php');
}

$stat = false;

$ban = [
        'semrush',
        'www.sogou.com',
        'Mail.RU_Bot',
        'curl',
        'DotBot',
        'bing.com',
        'dotbot',
        'DataForSeoBot',
        'AhrefsBot',
        'webmeup-crawler',
        'PetalBot',
        'petalsearch.com',
        'YandexBot',
        //'gptbot',
        'Bytespider',
        'Amazonbot',
        'Applebot',
        'serpstatbot',
        'facebook',
];
if (isset($_SERVER['HTTP_USER_AGENT'])){
        foreach($ban as $one){
                if(strripos($_SERVER['HTTP_USER_AGENT'], $one)>0){
                      toLogFile( DIR_LOGS . 'global_stat/ban/' . $one . date('_Y-m-d-H') . '.log', date('Y-m-d H:i:s ') . $_SERVER['HTTP_HOST'] . '/' . ($_GET['_route_']??'') . chr(13) . chr(10) , FILE_APPEND | LOCK_EX);
                       die;
                }
        }
}
$AI = [
         'GPTBot',
			'ChatGPT-User',
			'Google-Extended',
			'anthropic-ai',
			'CCBot',
			'Claude-SearchBot',
			'Claude-User',
];
if (isset($_SERVER['HTTP_USER_AGENT'])){
        foreach($AI as $one){
                if(stripos($_SERVER['HTTP_USER_AGENT'], $one)!== false){
                     toLogFile( DIR_LOGS . 'global_stat/AI/' . $one . date('_Y-m-d-H') . '.log', date('Y-m-d H:i:s ') . $_SERVER['HTTP_HOST'] . '/' . $_GET['_route_'] . chr(13) . chr(10) , FILE_APPEND | LOCK_EX);
                     break;
                }
        }
}
require_once(DIR_SYSTEM . 'startup.php');

require_once(DIR_SYSTEM . 'library/customer.php');
require_once(DIR_SYSTEM . 'library/currency.php');
require_once(DIR_SYSTEM . 'library/dateFormatter.php');
require_once(DIR_SYSTEM . 'library/seo_text.php');

$registry = new Registry();

$loader = new Loader($registry);
$registry->set('load', $loader);
$registry->set('seo_text', new SeoText());

if (defined('REDIS_HOSTNAME') AND defined('REDIS_PORT') AND defined('REDIS_DB')) {
	$redis = new Redis();
	$redis->connect(REDIS_HOSTNAME, REDIS_PORT);
	if (defined('REDIS_PASSWORD')){
		$redis->auth(REDIS_PASSWORD);
	}
	$redis->select(REDIS_DB);
	$registry->set('redis', $redis);
}else{
	$redis = false;
	$registry->set('redis', false);
}

$hack_block = $redis->hGet('hack_block', $_SERVER['REMOTE_ADDR']);
if(!empty($hack_block)){
	if((microtime(true)-$hack_block)>120){
		$redis->hDel('hack_block', $_SERVER['REMOTE_ADDR']);
	}else{
		$redis->hSet('hack_block', $_SERVER['REMOTE_ADDR'], microtime(true));
		$md5 = date('Y-m-d H:i') . ';' . $_SERVER['SERVER_ADDR'];
		header($_SERVER['SERVER_PROTOCOL'] . ' 503 Service Unavailable');
		require("503.html");
		die;
	}
}

$config = new Config();
$registry->set('config', $config);

$cache = new Cache();

if($redis->hGet('relevant_cache_time',$_SERVER['SERVER_ADDR'])<time()){
	$cache->flush();
	$redis->hSet('relevant_cache_time',$_SERVER['SERVER_ADDR'],time()+24*60*60);
}

$registry->set('cache', $cache);

if (defined('DB_PORT')) {
	$db = new DB(DB_DRIVER, DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE, DB_PORT, $registry);
} else {
	$db = new DB(DB_DRIVER, DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE);
}
$registry->set('db', $db);

$query = $db->query("SELECT * FROM " . DB_PREFIX . "setting WHERE store_id = '0' OR store_id = '" . (int)$config->get('config_store_id') . "' ORDER BY store_id ASC");


foreach ($query->rows as $setting) {
	if (!$setting['serialized']) {
		$config->set($setting['key'], $setting['value']);
	} else {
		$config->set($setting['key'], unserialize($setting['value']));
	}	
}

foreach($_ENV as $name => $value){
	if (substr($name, 0, 7) === "CONFIG_") {
		$config->set(strtolower($name), $value);
	}
}

if(HTTPS_SERVER=='https://st.tbxshop.pp.ua/') {
	$config->set('config_template', 'ticket2025');
}

$config->set('config_url', HTTP_SERVER);
$config->set('config_ssl', HTTPS_SERVER);

// Response
$response = new Response();
$response->addHeader('Content-Type: text/html; charset=utf-8');

$response->addHeader("Content-Security-Policy: default-src https: 'unsafe-inline' 'unsafe-eval' wss://lc.pulse.is https://lc.pulse.is " . TICKETSBOX_API_HOST . " data:");

if(!defined('DOMAINS_ALLOWED_DISPLAYING_SITE') || !in_array($_SERVER['HTTP_REFERER']??'', explode(',',DOMAINS_ALLOWED_DISPLAYING_SITE)) || stripos($_GET['_route_'],'checkout')===false){
	$response->addHeader("X-Frame-Options: SAMEORIGIN");
}
$response->addHeader("Strict-Transport-Security: max-age=31536000; includeSubDomains");
$response->addHeader("X-Content-Type-Options: nosniff");
$response->addHeader("Referrer-Policy: no-referrer-when-downgrade");
$response->addHeader("Permissions-Policy: geolocation=(self), microphone=(self)");
if($config->get('config_template') == 'ticket2025' AND preg_match('#^/(?:en|ru)?checkout(/|$)#',$_SERVER['REQUEST_URI'])) {
   $response->addHeader("X-Robots-Tag: noindex, nofollow");
}
$response->setCompression($config->get('config_compression'));
$registry->set('response', $response);
if(
	!isset($_COOKIE['PHPSESSID']) AND 
	isset($_SERVER['HTTP_REFERER']) AND
	stripos($_SERVER['HTTP_REFERER'],'liqpay')!==false
	){
	if( (!empty($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1)) || (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') ){
		$link = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
	}else{
		$link = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
	}
	if(empty($_POST)){
		header('HTTP/1.1 301 Moved Permanently');
		header('Location: ' . 
			str_replace('&amp;', '&',
			$link));
		die;
	}else{
		echo '<div style="display:none;"><form method="post" action="' . $_SERVER['REQUEST_URI'] . '" id="recovery">';
		foreach($_POST as $key => $value){
			echo "<input type='hidden' name='" . $key . "' value='" . $value . "' />";
		}
		echo '</form><script>document.getElementById("recovery").submit();</script></div>';
		die;
	}
}
$session = new Session($registry);
$registry->set('session', $session);

$languages = array();

$query = $db->query("SELECT * FROM `" . DB_PREFIX . "language` WHERE status = '1'");

foreach ($query->rows as $result) {
	$languages[$result['code']] = $result;
}

define('BASE_LANGUAGE_', $config->get('config_language'));

$request = new Request();

$code = false;
if (isset($_GET['_route_']) and strpos($_GET['_route_'], 'sitemap')!==false){
	$code = BASE_LANGUAGE_??'ua';
}else{
	if (isset($_GET['_route_'])){
		$exclude = [
			'complete_checkout', 
			'checkout', 
			'tickets', 
			];
		$code = $config->get('config_language');
		$switch = explode('/', $_GET['_route_'])[0];
		if(in_array($switch, $exclude) AND isset($request->cookie['language'])){
			$code = $request->cookie['language'];
		}
		if(isset($languages[$switch]) AND $languages[$switch]['status']){
			$code = $switch;
		}
	}elseif(count($_GET)==0){
		$code = $config->get('config_language');
	}else{
		if (!$code AND isset($session->data['language']) AND array_key_exists($session->data['language'], $languages) AND $languages[$session->data['language']]['status']) {
			$code = $session->data['language'];
		} elseif (!$code AND isset($request->cookie['language']) AND array_key_exists($request->cookie['language'], $languages) AND $languages[$request->cookie['language']]['status']) {
			$code = $request->cookie['language'];
		}else{
			$code = $config->get('config_language');
			if (isset($request->server['HTTP_ACCEPT_LANGUAGE']) && $request->server['HTTP_ACCEPT_LANGUAGE']) {
				$browser_languages = explode(',', $request->server['HTTP_ACCEPT_LANGUAGE']);

				foreach ($browser_languages as $browser_language) {
					foreach ($languages as $key => $value) {
						if ($value['status']) {
							$locale = explode(',', $value['locale']);

							if (in_array($browser_language, $locale)) {
								$code = $key;
							}
						}
					}
				}
			}
		}
	}
	if (isset($languages[BASE_LANGUAGE_??'ua']) and in_array($code, explode(',', HIDDEN_LANGUAGES??'ru')) and !isset($request->cookie['language'])){ // стандартный вход без куки на "старый" дефолтный язык - переключение на новый дефолтный
		$code = BASE_LANGUAGE_??'ua';
	}
	if (!isset($session->data['language']) || $session->data['language'] != $code) {
		$session->data['language'] = $code;
	}

	if (!isset($request->cookie['language']) || $request->cookie['language'] != $code) {
		setcookie('language', $code, time() + 60 * 60 * 24 * 30, '/', (method_exists($session, 'getDomain') ? $session->getDomain() : $request->server['HTTP_HOST']));
	}
}

$config->set('config_language_id', $languages[$code]['language_id']);
$config->set('base_config_language', $config->get('config_language'));
$config->set('config_language', $languages[$code]['code']);

$url = new Url(HTTP_SERVER, $config->get('config_secure') ? HTTPS_SERVER : HTTP_SERVER);
$registry->set('url', $url);
$log = new Log($config->get('config_error_filename'));
$registry->set('log', $log);
function error_handler($errno, $errstr, $errfile, $errline) {
	global $log, $config;

	switch ($errno) {
		case E_NOTICE:
			$error = 'Notice';
			break;
		case E_WARNING:
		case E_USER_WARNING:
			$error = 'Warning';
			break;
		default:
			$error = 'Fatal Error';
			break;
	}

	global $redis;
	$base = explode('/',DIR_APPLICATION);
	$base = implode('/', array_slice($base,0,count($base)-2));
	$adres = [];
	
	foreach(debug_backtrace() as $level){
		$line = '';
		if (isset($level['file'])){
			$line .= str_replace($base, '', $level['file']);
		}
		if (isset($level['line'])){
			$line .= ' in ' . $level['line'];
		}
		if(substr($level['function'],-13)!='error_handler'){
			$line .= '(' . $level['function'] . ')';
		}
		if ($line!=''){
			$adres[] = $line;
		}
	}
	$cr = '\n';
	$error = $_SERVER['SERVER_ADDR'] . ' ' . $error;
	$message = $error . ':  ' . $errstr . $cr . 'in ' . str_replace($base, '', $errfile) . $cr . 'on line ' . $errline . $cr . $cr . serialize($_GET) . $cr . serialize($_POST) . $cr . implode($cr, $adres);
	$md5 = md5($errstr.str_replace($base, '', $errfile).$errline);
	$redis->hSet('error_last_date', $md5, date('Y-m-d H:i:s'));
	$redis->hSet('error_last_url', $md5, $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
	$redis->hIncrby('error_count_incident', $md5, 1);
	$redis->hSet('error_level', $md5, $error);
	$redis->hSet('error_text', $md5, $errstr);
	$redis->hSet('error_file', $md5, str_replace($base, '', $errfile));
	$redis->hSet('error_line', $md5, $errline);
	$redis->hSet('error_message', $md5, $message);
	if (defined('ERROR_DISPLAY') AND ERROR_DISPLAY ) {
		echo '<br><br><b>' . $error . '</b>: ' . $errstr . ' in <b>' . $errfile . '</b> on line <b>' . $errline . '</b></br></br>' . implode('<br>', $adres) . '<br>';
	}elseif($error=='Fatal Error' AND defined('ERROR_DISPLAY_FATAL') AND ERROR_DISPLAY_FATAL){
		echo '<br><br><b>' . $error . '</b>: ' . $errstr . ' in <b>' . $errfile . '</b> on line <b>' . $errline . '</b></br></br>' . implode('<br>', $adres);
	}
	return true;
}

set_error_handler('error_handler');

error_reporting(E_ALL);
$registry->set('ticketsbox_api', new Ticketsbox(TICKETSBOX_API_HOST, /*TICKETSBOX_API_CLIENT_ID, TICKETSBOX_API_CLIENT_SECRET, TICKETSBOX_API_SCOPE, */CRM_APIKEY2));

Class Error_handler{
	private $registry;
	public function __construct($registry) {
		$this->registry = $registry;
	}

	public function fatal_error_handler() {
		if ($error = error_get_last() AND $error['type'] & ( E_ERROR | E_PARSE | E_COMPILE_ERROR | E_CORE_ERROR)) {
			error_handler($error['type'], $error['message'], $error['file'], $error['line']);
			if (!defined('ERROR_DISPLAY_FATAL') OR !ERROR_DISPLAY_FATAL ) {
				$this->registry->get('load')->language('error/500');
				$data = $this->registry->get('language')->getAll();
				$tpl = DIR_TEMPLATE . $this->registry->get('config')->get('config_template') . "/template/error/500.tpl";
				$config = $this->registry->get('config');

				extract($data);

				ob_end_clean();
				ob_start();

				require(DIR_TEMPLATE . $this->registry->get('config')->get('config_template') . "/template/error/500.tpl");

				$output = ob_get_contents();

				ob_end_clean();

				header($_SERVER['SERVER_PROTOCOL'] . ' 500 Service Temporarily Unavailable');
				echo $output;
				die;

				header('HTTP/1.1 301 Moved Permanently');
				header('Location: ' . HTTPS_SERVER . '500.html');
			}
		}else{
			if(ob_get_length() > 0) {
				ob_end_flush();
			}
		}
	}
}
$error_handler = new Error_handler($registry);
register_shutdown_function([&$error_handler, 'fatal_error_handler']);


$registry->set('request', $request);

$language = new Language($languages[$code]['directory']);
$language->load($languages[$code]['filename']);
$registry->set('language', $language);

$registry->set('document', new Document());
$registry->set('storedLink', new StoredLink($registry));
$registry->set('subscription', new Subscription($registry));

$registry->set('customer', new Customer($registry));

if (isset($request->get['tracking'])) {
	setcookie('tracking', $request->get['tracking'], time() + 3600 * 24 * 1000, '/', (method_exists($session, 'getDomain') ? $session->getDomain() : $request->server['HTTP_HOST']));
}

	$currency = array();

	$query = $db->query("SELECT * FROM " . DB_PREFIX . "currency where status=1");

	foreach ($query->rows as $result) {
		$currency[$result['code']] = $result;
	}

	if(isset($session->data['currency']) and array_key_exists($session->data['currency'], $currency)){
	}elseif (array_key_exists('KZT', $currency)) {
		$session->data['currency'] = 'KZT';
	}elseif (array_key_exists('UAH', $currency)) {
		$session->data['currency'] = 'UAH';
	}

$session->data['active'] = time();
if(!isset($session->data['start'])){
	$session->data['start'] = time();
}
$session->data['type'] = 'catalog';
if(!isset($session->data['pages'])){
	$session->data['pages'] = 1;
}else{
	$session->data['pages']++;
}

$registry->set('currency', new Currency($registry));

$registry->set('dateFormatter', new dateFormatter($registry));

$controller = new Front($registry);
$block_countries = new BlockCountry($registry, ['block_country' => $config->get('block_country_module'), 'block_manufacturer' => $config->get('block_manufacturer_module')]);
$config->set('blocked_manufacturers', $block_countries->get());
$registry->set('block_ctrl', $block_countries);
$controller->addPreAction(new Action('common/blocked'));

$controller->addPreAction(new Action('common/maintenance'));

if (!$seo_type = $config->get('config_seo_url_type')) {
	$seo_type = 'seo_url';
}

$controller->addPreAction(new Action('common/' . $seo_type));

if (isset($request->get['route'])) {
	$action = new Action($request->get['route']);
} else {
	$action = new Action('common/home');
}

$controller->dispatch($action, new Action('error/not_found'));

$response->output();

$md5 = date('Y-m-d H:i') . ';' . $_SERVER['SERVER_ADDR'] . ';' . isset($_GET['route']);
$redis->hIncrby('loadnod_count', $md5, 1);
$redis->hIncrby('loadnod_time', $md5, (microtime(true)-$microstat)*1000);

function toLogFile($file, $data, $param=FILE_APPEND){
	if(!defined("IS_FILE_LOGS") or IS_FILE_LOGS==false){
		if(substr($file, 0, strlen(DIR_LOGS))==DIR_LOGS){
			$file = substr($file, strlen(DIR_LOGS));
		}
		$file = str_replace(['.log', '.json', '.txt'], '', $file);
		if(!is_string($data)){
			$data=json_encode($data);
		}
		$out = fopen('php://stdout', 'w');
		fputs($out, $file . ' ' . $data);
		fclose($out); 
	}else{
		file_put_contents($file, $data, $param);
	}
}
?>
