load = $load; $this->db = $load->db(); $this->main = $this->load->model('main'); $this->db_ready = file_exists('/status/ready'); } /** * @param string $path - the current request path * Gets the current route * @return array */ private function get_req_route($path): array { // trim the path $path = trim($path); // remove first '/' $path = substr($path, 1); // get path parts $parts = explode('/', $path); $len = count($parts); // get route info $route = array(); // e.g. / if ($path === '') { $route = array( 'app' => '', 'slug' => 'index', ); // e.g. /home /login } else if ($len === 1) { $route = array( 'app' => $parts[0], 'slug' => 'index', ); // e.g. /home/posts } else { $route = array ( 'app' => implode('/', array_slice($parts, 0, -1)), 'slug' => end($parts) ); }; $routes = $GLOBALS['routes']; if (array_key_exists($route['app'], $routes)) { $parts = explode('/', $routes[$route['app']]); if (count($parts) == 1) { $route['app'] = $parts[0]; } else { $route['app'] = $parts[0]; $route['slug'] = $parts[1]; } } return $route; } /** * Gets the users ip */ private function get_ip(): string { $ip = ''; if (!empty($_SERVER['HTTP_CLIENT_IP'])) { $ip = $_SERVER['HTTP_CLIENT_IP']; } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; } else { $ip = $_SERVER['REMOTE_ADDR']; } return $ip; } /** * Gets the curret request info * @return array */ private function get_req(): array|bool { $method = $_SERVER['REQUEST_METHOD']; $uri_str = $_SERVER['REQUEST_URI']; $uri = parse_url($uri_str); if (!$uri) { return FALSE; } $path = ''; if (array_key_exists('path', $uri)) { $path = $uri['path']; } return array_merge( array( 'uri' => $uri, 'uri_str' => $uri_str, 'method' => $method, 'ip' => $this->get_ip() ), $this->get_req_route($path), ); } /** * Handles a router error code * @param int $code - the http error code * @param bool $recursed */ private function handle_error($code, $recursed): void { if ($recursed) { die($code . ' (recursed)'); } $uri_str = $_SERVER['REQUEST_URI']; $req = array(); $req['slug'] = 'index'; $req['app'] = 'error'; $req['uri_str'] = $uri_str; $this->main->info = $req; $_GET['code'] = $code; $this->handle_req($req, TRUE); } private function load_htc($req, $recursed): void { $parts = explode('/', $req['uri_str']); $file = end($parts); $path = $GLOBALS['publicroot'] . '/polyfills/' . $file; if (file_exists($path)) { header('Content-type: text/x-component'); include($path); } else { $this->handle_error(400, $recursed); } } /** * @param array $req * @param bool $recursed */ private function handle_req($req, $recursed = FALSE): void { if ($recursed === false) { if ( $this->db_ready === false && in_array($req['app'], $GLOBALS['serviceable']) === false ) { $this->handle_error(503, $recursed); return; } if ($this->check_banned($req)) { $this->handle_error(401, $recursed); return; } } if (!$req) { $this->handle_error(500, $recursed); return; } if (str_ends_with($req['uri_str'], '.htc')) { $this->load_htc($req, $recursed); return; } $controller = $this->load->controller($req['app']); if ($controller === NULL) { $this->handle_error(404, $recursed); return; } $ref = NULL; try { $ref = new ReflectionMethod($controller, $req['slug']); } catch (Exception $_e) {} if ($ref === NULL || !$ref->isPublic()) { $this->handle_error(404, $recursed); return; } $ref->invoke($controller); } private function log_request($req): void { if ( $req === FALSE || $this->db_ready === FALSE || in_array($req['app'], $GLOBALS['serviceable']) ) { return; } $query = $this->db ->insert_into('admin.request_log', 'ip', 'method', 'uri') ->values( $req['ip'], $req['method'], $req['uri_str']); $query->execute(); } private function check_banned($req) { $ip = FALSE; if ($req) { $ip = $req['ip']; } else { $ip = $this->get_ip(); } $query = $this->db ->select('TRUE') ->from('admin.banned') ->where('ip')->eq($ip); return !!($query->row()); } /** * Handels the incomming reuqest */ public function handle_request(): void { $req = $this->get_req(); $this->log_request($req); $this->main->info = $req; $this->handle_req($req); } }