* @copyright (c) 2025, Robert Strutts * @license MIT */ namespace CodeHydrater\bootstrap; final class site_helper { private static $ROOT; private static $ROUTE; private static $PRJ; private static $FW_DIST; private static $REQUEST_URI; private static $REQUEST_METHOD; private static $USE_SECURE = true; private static $TESTING; private static $queryParams; private static $DEFAULT_PROJECT; private static $all_projects = []; private static $local_site_domains = ['localhost']; private static $Private_IPs_allowed = ['127.0.0.1', '::1']; private static $Public_IPs_allowed = []; private static $loaded_files = []; /** * Don't USE THIS method, instead use requires::secure_include * It validates that the file is not dangerous */ public static function load_file(string $file): void { if (defined('CountFiles') && CountFiles) { self::$loaded_files[] = $file; } require_once $file; } public static function get_loaded_files(): array { return self::$loaded_files; } public static function set_local_site_domains(string|array $domain_name): void { if (is_array($domain_name)) { foreach($domain_name as $domain) { self::$local_site_domains[] = $domain; } } elseif (is_string($domain_name)) { self::$local_site_domains[] = $domain_name; } } public static function set_allowed_Private_IPs(string|array $IP_addresses): void { if (is_array($IP_addresses)) { foreach($IP_addresses as $IP) { $s_ip = \CodeHydrater\security::is_private_or_local_IP_simple($IP); if ($s_ip === false) { continue; } self::$Private_IPs_allowed[] = $IP; } } elseif (is_string($IP_addresses)) { $s_ip = \CodeHydrater\security::is_private_or_local_IP_simple($IP); if ($s_ip === false) { return; } self::$Private_IPs_allowed[] = $IP_addresses; } } public static function set_allowed_Public_IPs(string|array $IP_addresses): void { if (is_array($IP_addresses)) { foreach($IP_addresses as $IP) { $s_ip = \CodeHydrater\security::get_valid_public_ip($IP); if ($s_ip === false) { continue; } self::$Public_IPs_allowed[] = $s_ip; } } elseif (is_string($IP_addresses)) { $s_ip = \CodeHydrater\ecurity::get_valid_public_ip($IP); if ($s_ip === false) { return; } self::$Public_IPs_allowed[] = $IP_addresses; } } public static function is_server_name_a_private_domain(): bool { $white_list = array_merge(self::$local_site_domains, self::$Private_IPs_allowed); return (\CodeHydrater\security::is_server_name_on_domain_list($white_list)); } public static function remote_not_allowed_force_live(): bool { return (self::is_allowed() === false) ? true : false; } public static function is_allowed(): bool { $remote_ip = \CodeHydrater\security::get_client_ip_address(); if (in_array($remote_ip, self::$Public_IPs_allowed)) { return true; } if (in_array($remote_ip, self::$Private_IPs_allowed)) { return true; } if (self::is_server_name_a_private_domain()) { return true; } return false; } public static function get_route(): string { return self::$ROUTE; } public static function get_root(): ?string { return self::$ROOT; } public static function get_testing() { return self::$TESTING; } public static function get_path_info(): string { return strtok(self::$REQUEST_URI, '?'); } public static function get_uri(): string { return self::$REQUEST_URI; } public static function get_method(): string { return strtoupper(self::$REQUEST_METHOD); } public static function get_params() { return self::$queryParams; } public static function get_use_secure(): bool { return self::$USE_SECURE; } /** * Because $_SERVER['REQUEST_URI'] May only available on Apache, * we generate an equivalent using other environment variables. * @return string */ public static function request_uri() { if (self::$REQUEST_URI !== null && !empty(self::$REQUEST_URI)) { $uri = self::$REQUEST_URI; } else if (isset($_SERVER['REQUEST_URI'])) { $uri = safer_io::get_clean_server_var('REQUEST_URI'); } else { if (isset($_SERVER['argv'])) { $uri = safer_io::get_clean_server_var('SCRIPT_NAME') . '?' . $_SERVER['argv'][0]; } elseif (isset($_SERVER['QUERY_STRING'])) { $uri = safer_io::get_clean_server_var('SCRIPT_NAME') . '?' . \bs_tts\safer_io::get_clean_server_var('QUERY_STRING'); } else { $uri = safer_io::get_clean_server_var('SCRIPT_NAME'); } } // Prevent multiple slashes to avoid cross site requests via the Form API. $uri = '/' . ltrim($uri, '/'); return $uri; } public static function get_clean_server_var(string $var): mixed { return filter_input(INPUT_SERVER, $var, FILTER_UNSAFE_RAW); } public static function site_url(): string { $server_port = self::get_clean_server_var('SERVER_PORT'); $secure_port_on = self::get_clean_server_var('HTTPS'); $use_secure = ($server_port == '443' || $secure_port_on == 'on'); self::$USE_SECURE = $use_secure; $protocol = ($use_secure) ? 'https://' : 'http://'; define('TTS_PROTOCOL', $protocol); $domainName = self::get_clean_server_var('HTTP_HOST'); return $protocol . $domainName . "/"; } public static function resolve($action, ...$params) { if (is_callable($action)) { return call_user_func($action, $params); } if (!is_array($action)) { return false; } [$class, $method] = $action; $call_class = "\\" . $class; if (class_exists($call_class)) { $auto_class = registry::get('di')->get_auto($call_class); if (method_exists($call_class, $method)) { return call_user_func_array([$auto_class, $method], $params); } } return false; } private static function set_route(): void { // Get just route $pos = strpos(self::$REQUEST_URI, "?"); $uri = ($pos !== false) ? substr(self::$REQUEST_URI, 0, $pos) : self::$REQUEST_URI; $root = str_replace(self::$ROOT, "", $uri); $routes = explode('/', trim($root, '/')); self::$ROUTE = implode('/', $routes); } private static function set_params(): void { // Get just query string $pos = strpos(self::$REQUEST_URI, "?"); $uri = ($pos !== false) ? substr(self::$REQUEST_URI, $pos + 1) : ""; if (empty($uri)) { return; } $queryParams = []; parse_str($uri, $queryParams); self::$queryParams = $queryParams; } public static function restrict_site(): void { if ($_SERVER['HTTP_REFERER'] != $_SERVER['HTTP_HOST']) { die("Form may not be used outside of parent site!"); } } public static function get_cli_args(): string { $argv = (isset($GLOBALS['argv'])) ? $GLOBALS['argv'] : []; $args = array_shift($argv); // POP out the SCRIPT_NAME!! if ($args === null) { return ""; // NO Args } $route = $argv[0] ?? ""; // Keep the Route $args = array_shift($argv); // POP out the ROUTE!! if ($args === null) { return $route; } return $route . "?" . ltrim(implode('&', $argv), "&"); } public static function init(string $ROOT, string $REQUEST_URI, string $REQUEST_METHOD, bool $testing = false) { self::$ROOT = $ROOT; self::$REQUEST_URI = $REQUEST_URI; self::$REQUEST_METHOD = $REQUEST_METHOD; self::$TESTING = $testing; self::set_route(); self::set_params(); if (! defined("ASSETS_BASE_REF")) { define('ASSETS_BASE_REF', "/assets/"); } define('SITE_URL', self::site_url()); define('PROJECT_BASE_REF', SITE_URL); define("BROWSER", self::get_clean_server_var('HTTP_USER_AGENT')); define("ASSETS_DIR", "/public/assets/"); define("PROJECT_ASSETS_BASE_REF", ASSETS_BASE_REF); } }