public function __construct() { $this->mUserId = Runtime::$SESSION->getInt("_im_userid", 0); if ($this->mUserId < -1) { throw new SecurityException("User id '" . $this->mUserId . "' is lower than allowed"); } switch ($this->mUserId) { case -1: $rootPasswd = Runtime::$SETTINGS["AUTH_ROOT_PASSWD"]; if (!empty($rootPasswd)) { $this->mUserName = "******"; break; } else { $this->mUserId = 0; } /* * GoTo 'case 0' */ /* * GoTo 'case 0' */ case 0: $this->mUserName = "******"; /* * Allows terminal to login using cli arguments. * This is useful when running cron jobs that are group protected. * CLI information has it's own container within Runtime and is not placed any where * near input from the browser to avoid any form of outside bypassing. */ if (Runtime::$SYSTEM["REQUEST_CLIENT"] == "terminal" && Runtime::$SETTINGS->getBoolean("AUTH_ALLOW_CLI")) { $password = Runtime::$CLI["passwd"]; $username = Runtime::$CLI["user"]; if ($password !== null || $username !== null) { if (!$this->login($password, $username)) { Runtime::quit(["Authorization Failed", "Usage: --passwd [password] --user [username]"], 1); } } } break; default: if (Database::isConnected()) { $result = Database::select("users")->field("cName")->cond("cId", "i", $this->mUserId)->enquire(); if ($result !== null) { if ($result->numRows() > 0) { $row = $result->fetch(); if ($row !== null) { $this->mUserName = $row[0]; } } $result->destroy(); } } } }
public function request(string $request) { if ($this->mRequestLocked) { $this->mPendingRequest = $request; return; } $routes = Runtime::$SETTINGS->getArray("ROUTER"); $controller = null; $request = rtrim($request, "/"); if (empty($request)) { $request = "/"; } /* * Pages should be allowed to issue a special page defined in settings as ROUTER_[num]. * These however should not be available from te URI */ $special = preg_match("#^ROUTER_[0-9]+\$#", $request) && strcmp($request, Runtime::$SYSTEM->getString("URI_LOCATION", "/")) !== 0; if ($routes !== null && !$special) { $controller = $routes[$request] ?? null; if (empty($controller)) { foreach ($routes as $key => $value) { $key = str_replace([":alpha:", ":all:", ":num:"], ["[A-Za-z0-9\\-_]+", ".+", "[0-9]+"], $key); if (preg_match('#^' . $key . '$#', $request)) { if (!empty($value)) { if (substr($value, 0, 1) == ":") { $value = substr($value, 1); if (strpos($val, "\$") !== false) { $value = preg_replace("#^" . $key . "\$#", $value, $request); } $this->request($value); return; } else { $controller = $value; } break; } } } } elseif (substr($controller, 0, 1) == ":") { $this->request(substr($controller, 1)); return; } } elseif ($special) { $controller = Runtime::$SETTINGS->getString($request); } $request = trim($request, "/"); $controller = "page\\" . trim($controller, "\\"); if (!Runtime::loadClassFile($controller)) { $controller = "page\\" . trim(Runtime::$SETTINGS->getString("ROUTER_404"), "\\"); if (!Runtime::loadClassFile($controller)) { /* * Do not parse output through any controller if one was selected previously */ $this->mController = null; header(Runtime::$SERVER["SERVER_PROTOCOL"] . " 404 Not Found", 404, true); Runtime::quit(["404 Not Found", "The requested file does not exist"], 1); } } $this->mSegments = empty($request) ? [] : explode("/", $request); $this->mRequest = "/" . $request; /* * Let's say we redirect from with a controller * * 1. Controller1::__construct invokes a new assignment to $this->mController by calling $this->request() * However Controller1::__construct does not finish until $this->request() returns, so it stalls between * property assignments. * * 2. Controller2::__construct does a lot of page loading * * 3. Controller1::__construct finishes it's construct and is now assigned to $this->mController, overwriting Controller2 * * 4. Shutdown now executes, but uses Controller1 instead of Controller2 * * We need to finish the first controller before starting a new. * To do this, we add a pending feature. */ $this->mRequestLocked = true; $this->mController = new $controller(); $this->mRequestLocked = false; if ($this->mPendingRequest !== null) { $pending = $this->mPendingRequest; $this->mPendingRequest = null; $this->request($pending); } }