<?php

if (!function_exists('str_starts_with')) {
	function str_starts_with($haystack, $needle) {
		$haystack = (string)$haystack;
		$needle = (string)$needle;
		if ($needle === '') return true;
		return substr($haystack, 0, strlen($needle)) === $needle;
	}
}
if (!function_exists('str_ends_with')) {
	function str_ends_with($haystack, $needle) {
		$haystack = (string)$haystack;
		$needle = (string)$needle;
		if ($needle === '') return true;
		return substr($haystack, -strlen($needle)) === $needle;
	}
}
if (!function_exists('str_contains')) {
	function str_contains($haystack, $needle) {
		$haystack = (string)$haystack;
		$needle = (string)$needle;
		if ($needle === '') return true;
		return strpos($haystack, $needle) !== false;
	}
}

if (!function_exists('ca_send_http_status')) {
	function ca_send_http_status($code) {
		$code = (int)$code;
		if ($code <= 0) return;
		http_response_code($code);
		if (!headers_sent()) {
			if ($code === 404) {
				header('Status: 404 Not Found');
			} elseif ($code === 403) {
				header('Status: 403 Forbidden');
			} elseif ($code === 500) {
				header('Status: 500 Internal Server Error');
			}
		}
	}
}

if (!function_exists('ca_strip_leading_output_artifacts')) {
	function ca_strip_leading_output_artifacts($buffer) {
		static $done = false;
		static $prefix = '';
		if ($done) return $buffer;
		if (!is_string($buffer) || $buffer === '') return '';

		$prefix .= $buffer;
		if (strlen($prefix) > 2048) {
			$done = true;
			$out = $prefix;
			$prefix = '';
			return $out;
		}

		$skip = 0;
		if (strlen($prefix) >= 3 && substr($prefix, 0, 3) === "\xEF\xBB\xBF") {
			$skip = 3;
		}
		$len = strlen($prefix);
		while ($skip < $len) {
			$b = ord($prefix[$skip]);
			if ($b === 9 || $b === 10 || $b === 13 || $b === 32) { $skip++; continue; }
			break;
		}
		if ($skip < $len && $prefix[$skip] === '?' && ($skip + 1) >= $len) {
			return '';
		}
		if ($skip + 2 <= $len && substr($prefix, $skip, 2) === '?>') {
			$skip += 2;
			while ($skip < $len) {
				$b = ord($prefix[$skip]);
				if ($b === 9 || $b === 10 || $b === 13 || $b === 32) { $skip++; continue; }
				break;
			}
			if ($skip < $len && $prefix[$skip] === '?' && ($skip + 1) >= $len) {
				return '';
			}
		}

		$done = true;
		$out = $skip > 0 ? substr($prefix, $skip) : $prefix;
		$prefix = '';
		return $out;
	}
}

if (isset($_SERVER['REQUEST_URI']) && is_string($_SERVER['REQUEST_URI'])) {
	$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
	if (is_string($path)) {
		if (preg_match('#^/([a-z]{2}/)?health\.php$#i', $path)) {
			$target = __DIR__ . DIRECTORY_SEPARATOR . 'health.php';
			if (is_file($target)) {
				require $target;
				exit;
			}
		}
		if (preg_match('#^/(?:([a-z]{2})/)?(ads\.txt|robots\.txt|sitemap\.xml|sitemap-[a-z0-9_-]+\.xml)$#i', $path, $m)) {
			$lang_req = isset($m[1]) ? strtolower((string)$m[1]) : '';
			$file_req = (string)$m[2];
			$target = __DIR__ . DIRECTORY_SEPARATOR . ltrim($file_req, '/');
			if (is_file($target)) {
				$ext = strtolower(pathinfo($target, PATHINFO_EXTENSION));
				if ($ext === 'txt') header('Content-Type: text/plain; charset=UTF-8');
				if ($ext === 'xml') header('Content-Type: application/xml; charset=UTF-8');
				$raw = @file_get_contents($target);
				if (!is_string($raw) || $raw === '') {
					readfile($target);
					exit;
				}

				$host = isset($_SERVER['HTTP_HOST']) ? strtolower((string)$_SERVER['HTTP_HOST']) : '';
				$host = preg_replace('/:\d+$/', '', $host);
				$host = preg_replace('/^www\./i', '', $host);
				$proto = 'http';
				if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
					$proto = strtolower(trim(explode(',', (string)$_SERVER['HTTP_X_FORWARDED_PROTO'])[0]));
				} elseif (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') {
					$proto = 'https';
				}
				if ($host !== '') {
					$base = ($proto === 'https' ? 'https' : 'http') . '://' . $host;
					if ($file_req === 'robots.txt') {
						$raw = preg_replace('#^Sitemap:\s*.*$#mi', 'Sitemap: ' . $base . '/sitemap.xml', $raw);
					} elseif ($ext === 'xml') {
						$raw = preg_replace_callback('#<loc>([^<]+)</loc>#i', function ($mm) use ($base) {
							$u = trim((string)$mm[1]);
							if ($u === '') return $mm[0];
							$parts = parse_url($u);
							if ($parts === false) return '<loc>' . htmlspecialchars($base . '/' . ltrim($u, '/'), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . '</loc>';
							$path = isset($parts['path']) ? (string)$parts['path'] : '/';
							$query = isset($parts['query']) ? (string)$parts['query'] : '';
							$path = '/' . ltrim($path, '/');
							$out = $base . $path . ($query !== '' ? ('?' . $query) : '');
							return '<loc>' . htmlspecialchars($out, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . '</loc>';
						}, $raw);
					}
				}

				echo $raw;
				exit;
			} else {
				// Graceful fallback: /{lang}/sitemap-*.xml -> /sitemap-{lang}.xml (legacy path)
				if ($lang_req !== '' && preg_match('#^sitemap-[a-z0-9_-]+\.xml$#i', $file_req)) {
					$redirect_to = '/sitemap-' . $lang_req . '.xml';
					header('Location: ' . $redirect_to, true, 301);
					exit;
				}
			}
		}
	}
}

if (PHP_SAPI !== 'cli' && !headers_sent() && !defined('CA_STRIP_OB_STARTED')) {
	define('CA_STRIP_OB_STARTED', true);
	$ae = isset($_SERVER['HTTP_ACCEPT_ENCODING']) ? strtolower((string)$_SERVER['HTTP_ACCEPT_ENCODING']) : '';
	$zlib_on = (bool)ini_get('zlib.output_compression');
	$has_gz_handler = false;
	if (function_exists('ob_list_handlers')) {
		foreach (ob_list_handlers() as $h) {
			if (stripos((string)$h, 'gz') !== false) { $has_gz_handler = true; break; }
		}
	}
	if (ob_get_level() === 0 && !$zlib_on && !$has_gz_handler && function_exists('ob_gzhandler') && $ae !== '' && strpos($ae, 'gzip') !== false) {
		header('Vary: Accept-Encoding');
		ob_start('ob_gzhandler');
	}
	ob_start('ca_strip_leading_output_artifacts');
}

$__host = isset($_SERVER['HTTP_HOST']) ? strtolower((string)$_SERVER['HTTP_HOST']) : '';
$__is_local_host = ($__host === '' || $__host === 'localhost' || $__host === '127.0.0.1' || $__host === '0.0.0.0' || str_ends_with($__host, '.local'));
if (!$__is_local_host && preg_match('/^10\./', $__host)) $__is_local_host = true;
if (!$__is_local_host && preg_match('/^192\.168\./', $__host)) $__is_local_host = true;
if (!$__is_local_host && preg_match('/^172\.(1[6-9]|2[0-9]|3[0-1])\./', $__host)) $__is_local_host = true;
if (!$__is_local_host && isset($_SERVER['REMOTE_ADDR']) && is_string($_SERVER['REMOTE_ADDR'])) {
	$__ra = (string)$_SERVER['REMOTE_ADDR'];
	if ($__ra === '127.0.0.1' || $__ra === '::1') $__is_local_host = true;
	if (!$__is_local_host && preg_match('/^10\./', $__ra)) $__is_local_host = true;
	if (!$__is_local_host && preg_match('/^192\.168\./', $__ra)) $__is_local_host = true;
	if (!$__is_local_host && preg_match('/^172\.(1[6-9]|2[0-9]|3[0-1])\./', $__ra)) $__is_local_host = true;
}

if (!$__is_local_host && PHP_SAPI !== 'cli') {
	$__req_uri = isset($_SERVER['REQUEST_URI']) ? (string)$_SERVER['REQUEST_URI'] : '/';
	$__proto = 'http';
	if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
		$__proto = strtolower(trim(explode(',', (string)$_SERVER['HTTP_X_FORWARDED_PROTO'])[0]));
	} elseif (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') {
		$__proto = 'https';
	}
	$__target_host = preg_replace('/^www\./i', '', $__host);
	$__need_https = ($__proto !== 'https');
	$__need_host = ($__target_host !== $__host);
	if ($__need_https || $__need_host) {
		$__redirect = 'https://' . $__target_host . $__req_uri;
		if (!headers_sent()) {
			header('Location: ' . $__redirect, true, 301);
		}
		exit;
	}
}

$is_https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off');
if (PHP_SAPI !== 'cli' && session_status() === PHP_SESSION_NONE) {
	ini_set('session.use_strict_mode', '1');
	ini_set('session.use_only_cookies', '1');
	ini_set('session.cookie_httponly', '1');
	ini_set('session.cookie_secure', $is_https ? '1' : '0');
	ini_set('session.cookie_samesite', 'Lax');
	if (defined('PHP_VERSION_ID') && PHP_VERSION_ID >= 70300) {
		session_set_cookie_params([
			'lifetime' => 0,
			'path' => '/',
			'secure' => $is_https,
			'httponly' => true,
			'samesite' => 'Lax'
		]);
	} else {
		session_set_cookie_params(0, '/', '', $is_https, true);
	}
	session_start();
}

ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
@ini_set('log_errors', '1');
$__front_log = __DIR__ . '/cache/php_front.log';
@ini_set('error_log', $__front_log);
@mkdir(__DIR__ . '/cache', 0755, true);
register_shutdown_function(function () use ($__front_log) {
	$e = error_get_last();
	if (!$e) return;
	$fatal = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR];
	if (!in_array($e['type'] ?? 0, $fatal, true)) return;
	$msg = 'FATAL: ' . ($e['message'] ?? '') . ' in ' . ($e['file'] ?? '') . ':' . ($e['line'] ?? '');
	@error_log($msg);
	if (!headers_sent()) {
		http_response_code(500);
		header('Content-Type: text/plain; charset=UTF-8');
	}
	echo "网站发生错误，请查看日志：cache/php_front.log";
});

if(!defined('IS_VISITOR_PAGE')){
	define('IS_VISITOR_PAGE', true);
}

if (!defined('NO_STATIC') && isset($_SERVER['REQUEST_URI']) && is_string($_SERVER['REQUEST_URI'])) {
	$__p = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
	if (is_string($__p) && $__p !== '') {
		$__p = '/' . ltrim($__p, '/');
		if (preg_match('#^/([a-z]{2}/)?(game|full|search|search-suggest)(/|$)#i', $__p)) {
			define('NO_STATIC', true);
		}
	}
}

if(!defined('NO_STATIC') && file_exists('index_static.php')){
	require_once('index_static.php');
	exit();
}

require( 'config.php' );
require( 'init.php' );
require( 'classes/Collection.php' );
require( 'includes/plugin.php' );

if (PHP_SAPI !== 'cli' && PRETTY_URL && get_setting_value('lang_code_in_url') && isset($_SERVER['REQUEST_URI']) && is_string($_SERVER['REQUEST_URI'])) {
	$__uri = $_SERVER['REQUEST_URI'];
	$__path = parse_url($__uri, PHP_URL_PATH);
	if (is_string($__path) && preg_match('#^/([a-z]{2})(/|$)#i', $__path, $__m)) {
		$__cur_prefix = strtolower((string)$__m[1]);
		$__query = parse_url($__uri, PHP_URL_QUERY);
		$__params = [];
		if (is_string($__query) && $__query !== '') parse_str($__query, $__params);
		if (isset($__params['lang'])) {
			$__target_lang = strtolower(trim((string)$__params['lang']));
			unset($__params['lang']);
			if (preg_match('/^[a-z]{2}$/', $__target_lang) && $__target_lang !== $__cur_prefix) {
				$__path = '/' . $__target_lang . substr($__path, 3);
			}
			$__qs = http_build_query($__params);
			$__to = $__path . ($__qs !== '' ? ('?' . $__qs) : '');
			header('Location: ' . rtrim(DOMAIN, '/') . $__to, true, 301);
			exit;
		}
	}
}

ca_apply_url_redirects();

$caching_system = null;

$_wgts = get_pref('widgets');
$_wgts = ($_wgts) ? json_decode($_wgts, true) : [];
$stored_widgets = $_wgts;

$lang_code = get_setting_value('language');
$lang_code_url = null; // Store language ID in url
$url_params = [];

if(PRETTY_URL){
	$url_params = array_values(array_filter(explode('/', urldecode(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)))));
	// Quick FIX login with raw url
	if(count($url_params) == 0 && isset($_GET['viewpage']) && $_GET['viewpage'] == 'login'){
		$url_params[0] = 'login';
	}
} else {
	if (isset($_GET['viewpage'])) {
		$url_params = array_values(array_filter(array_map('trim', explode('/', $_GET['viewpage']))));
	}
}
if(SUB_FOLDER != ""){
	// Is using sub-folder
	$fname = str_replace("/", "", SUB_FOLDER);
	if(isset($url_params[0]) && $url_params[0] == $fname){
		array_shift($url_params);
	}
}

if (!function_exists('ca_detect_lang_from_accept_language')) {
	function ca_detect_lang_from_accept_language($accept_language, $site_default_lang){
		$site_default_lang = strtolower(trim((string)$site_default_lang));
		if ($site_default_lang === '') $site_default_lang = 'cn';
		$accept_language = strtolower(trim((string)$accept_language));
		if ($accept_language === '') return $site_default_lang;
		$parts = explode(',', $accept_language);
		$cands = [];
		$idx = 0;
		foreach ($parts as $p) {
			$p = trim((string)$p);
			if ($p === '') continue;
			$q = 1.0;
			if (strpos($p, ';') !== false) {
				$tmp = explode(';', $p, 2);
				$p = trim((string)($tmp[0] ?? ''));
				$rest = (string)($tmp[1] ?? '');
				if (preg_match('/q=([0-9.]+)/', $rest, $m)) {
					$q = (float)$m[1];
				}
			}
			if ($p === '') continue;
			$primary = strtolower((string)explode('-', $p, 2)[0]);
			$cands[] = ['primary' => $primary, 'q' => $q, 'i' => $idx++];
		}
		if (!count($cands)) return $site_default_lang;
		usort($cands, function($a, $b){
			if ($a['q'] === $b['q']) return $a['i'] <=> $b['i'];
			return ($a['q'] < $b['q']) ? 1 : -1;
		});
		$primary = (string)($cands[0]['primary'] ?? '');
		if ($primary === 'en') return 'en';
		if ($primary === 'zh') return $site_default_lang;
		return $site_default_lang;
	}
}

// BEGIN MULTI-LANGUAGE
if (array_key_exists('lang', $_GET)) {
	// Switch language with ?lang=en parameter
	$lang_code = $_GET['lang'];
}

$__has_lang_prefix = false;
if (PRETTY_URL && isset($url_params[0]) && preg_match('/^[a-z]{2}$/i', (string)$url_params[0])) {
	$__has_lang_prefix = true;
}
if (!array_key_exists('lang', $_GET) && !isset($_COOKIE['lang']) && !$__has_lang_prefix) {
	if (!get_setting_value('disable_en_language')) {
		$__auto = ca_detect_lang_from_accept_language($_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '', get_setting_value('language'));
		if ($__auto === 'en' || $lang_code === get_setting_value('language')) {
			$lang_code = $__auto;
			if (!headers_sent()) {
				setcookie('lang', $lang_code, strtotime('+3 months'), '/');
			}
		}
	}
}

if (PRETTY_URL && isset($_GET['viewpage']) == 'search' && strpos($_SERVER['REQUEST_URI'], '?viewpage=search')) {
	// If search page with query string URL
	// Then redirect to pretty url version
	header('Location: '.get_permalink('search', $_GET['slug'], [], $lang_code), true, 301);
	exit();
}

$language_file_exist = true; // Set false if lang file not exist
$lang_url_enabled = get_setting_value('lang_code_in_url');
$__req_path_for_lang = isset($_SERVER['REQUEST_URI']) && is_string($_SERVER['REQUEST_URI']) ? parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) : null;
$__is_php_entry = (is_string($__req_path_for_lang) && preg_match('#\.php$#i', $__req_path_for_lang));
if($lang_url_enabled && PRETTY_URL && !$__is_php_entry){
	// Put language ID on url
	// example: domain.com/en/game
	if (!array_key_exists('lang', $_GET)) {
		$lang_code = isset($url_params[0]) ? $url_params[0] : (isset($_COOKIE['lang']) ? $_COOKIE['lang'] : $lang_code);
	}
	if (!preg_match('/^[a-z]{2}$/', $lang_code) || empty($url_params)) {
		// If url doesn't contain language ID on it's url
		// or current url is home page
		// then redirect to a new url (cur url) that contain language ID
		$is_search = (isset($url_params[1]) && $url_params[1] == 'search') ? true : false;
		$_prevent_redirect_lang_url = false;
		if(get_setting_value('hide_lang_code_on_homepage') && $lang_code === get_setting_value('language')){
			if(empty($url_params)){
				// Is home page
				$_prevent_redirect_lang_url = true;
			}
		}
		if(!$is_search && !$_prevent_redirect_lang_url){
			// Exception for search page
			$lang_code = isset($_COOKIE['lang']) ? $_COOKIE['lang'] : get_setting_value('language');
			$redirect_url = DOMAIN . "$lang_code{$_SERVER['REQUEST_URI']}";
			if(empty($url_params)){
				// Is home page
				if(get_setting_value('trailing_slash')){
					// If trailing slash is activated
				} else {
					if(substr($redirect_url, -1) == '/'){
						$redirect_url = substr($redirect_url, 0, -1);
					}
				}
				// Home page will be domain.com/en/
				// If trailing_slash is inactive, then '/' in the last character of the url will be removed
			}
			header("HTTP/1.1 301 Moved Permanently");
			header("Location: $redirect_url");
			exit();
		}
	} else {
		// url contain language ID
		$lang_code_url = $url_params[0];
	}
	if(isset($url_params[0]) && $url_params[0] == $lang_code){
		// Remove language ID from url array
		array_shift($url_params);
	}
	$file = ABSPATH . 'locales/public/' . $lang_code . '.json';
	if (!file_exists($file) && $lang_code != 'en') {
		$file = TEMPLATE_PATH . '/locales/' . $lang_code . '.json'; // Backward compatibility
		if (!file_exists($file)){
			// Language file does not exist
			$lang_code = 'en';
			$language_file_exist = false;
		}
	}
	$_GET['lang'] = $lang_code;
}
// END

if (PRETTY_URL && !($__is_php_entry ?? false)) {
	$_GET['viewpage'] = isset($url_params[0]) ? $url_params[0] : 'homepage';
	if(isset($url_params[1])) {
		$_GET['slug'] = $url_params[1];
	}
	if(get_setting_value('trailing_slash')){
		// If trailing slash is activated
		if(count($url_params)){
			$cur_url = $_SERVER['REQUEST_URI'];
			if(substr($cur_url, -1) != '/' && !strpos($cur_url, '?')){
				// Add trailing slash, then redirect
				header('Location: '.substr(DOMAIN, 0, -1).$cur_url.'/', true, 301);
				exit();
			}
		}
	} else {
		// Trailing slash is deactivated
		if(count($url_params)){
			$cur_url = $_SERVER['REQUEST_URI'];
			if(substr($cur_url, -1) == '/' && !strpos($cur_url, '?')){ // Have trailing slash
				// Remove trailing slash, then redirect
				header('Location: '.substr(DOMAIN, 0, -1).substr($cur_url, 0, -1), true, 301);
				exit();
			}
		}
	}
}

load_language('index');

$page_name = (isset($_GET['viewpage']) && !empty($_GET['viewpage'])) ? $_GET['viewpage'] : 'homepage';

$base_taxonomy = get_base_taxonomy($page_name);
$custom_path = $base_taxonomy;
if ($base_taxonomy === '404') {
	ca_send_http_status(404);
	if (!headers_sent()) header('X-Robots-Tag: noindex, nofollow');
}

if ((string)$page_name === '404') {
	$base_taxonomy = '404';
	ca_send_http_status(404);
	if (!headers_sent()) {
		header('X-Robots-Tag: noindex, nofollow');
	}
	require( ABSPATH . 'includes/page-404.php' );
	exit();
}
//
if ($base_taxonomy == $page_name && $page_name != get_custom_path($base_taxonomy)) {
    // Visitor is accessing old base_taxonomy, redirect to custom path
    $new_url = get_permalink('404'); // Default to 404
    if($base_taxonomy != 'login'){
    	switch (count($url_params)) {
	        case 1:
	            $new_url = get_permalink($page_name);
	            break;
	        case 2:
	            $new_url = get_permalink($page_name, $url_params[1]);
	            break;
	        default:
	            if (count($url_params) >= 3) {
	                $arrs = [];
	                for ($i = 2; $i < count($url_params); $i++) {
	                    $key = "param" . ($i - 1);
	                    $arrs[$key] = $url_params[$i];
	                }
	                $new_url = get_permalink($page_name, $url_params[1], $arrs);
	            }
	            break;
	    }
    }  
    header('Location: ' . $new_url, true, 301);
    exit();
}

if($base_taxonomy == 'search'){
	if(PRETTY_URL){
		if(isset($_GET['slug']) && strpos($_SERVER['REQUEST_URI'], 'viewpage=search')){
			header('Location: '.get_permalink('search', $_GET['slug']), true, 301);
			exit();
		}
	}
}

require_once( ABSPATH.'content/themes/theme-functions.php' );
load_plugins('index');
require_once( ABSPATH . TEMPLATE_PATH . '/functions.php' );

if($lang_url_enabled && PRETTY_URL){
	if(!$language_file_exist && ($lang_code_url != 'en')){
		// Language file requested in url is not exist
		// Show 404 page
		if (!headers_sent()) {
			http_response_code(404);
			header('X-Robots-Tag: noindex, nofollow');
		}
		require( 'includes/page-404.php' );
		exit();
	}
}

// ROUTING LOGIC
// DEBUG REMOVED

if(file_exists( ABSPATH . 'includes/page-' . $base_taxonomy . '.php' )){
	require( ABSPATH . 'includes/page-' . $base_taxonomy . '.php' );
} else {
	if(file_exists( ABSPATH . TEMPLATE_PATH.'/page-' . $page_name . '.php' )){
		require( ABSPATH . TEMPLATE_PATH.'/page-' . $page_name . '.php' );
	} else {
		if (!headers_sent()) {
			http_response_code(404);
			header('X-Robots-Tag: noindex, nofollow');
		}
		require( ABSPATH . 'includes/page-404.php' );
	}
}

?>
