| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525 |
- <?php
- /**
- * Controller file.
- *
- * Provides a class to handle all posible request.
- *
- * @author Iñigo Valentin <i@inigovalentin.com>
- * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
- * @package SWDB
- */
- require_once(__DIR__ . "/config.php");
- require_once(PATH::HELPER . "DB_Helper.php");
- require_once(PATH::HELPER . "TEXT_Helper.php");
- require_once(PATH::HELPER . "NET_Helper.php");
- require_once(PATH::HELPER . "HTML_Helper.php");
- require_once(PATH::HELPER . "APPLICATION_Helper.php");
- require_once(PATH::ENTITY . "User.php");
- require_once(PATH::ENTITY . "Player.php");
- require_once(__DIR__ . "/Constant.php");
- require_once(__DIR__ . "/Context.php");
- /**
- * Application controller.
- *
- * Handles every request, creating the required models and selecting the
- * view.
- *
- * @category Controller
- */
- class Controller extends Context{
- /**
- * @var string[] GET parameters received by the controller.
- */
- private $params = [];
- /**
- * @var Context Publicly available context.
- */
- private $context;
-
- private $command = "";
-
- private $status = 201;
- private $message = "OK";
- /**
- * Retrieves the application context.
- *
- * @return Context The context.
- */
- public function get_context(){
- return $this->context;
- }
- /**
- * Controller constructor.
- *
- * Initializes a database connection and sets up the public context.
- */
- public function __construct(){
- $this->context = new Context();
- session_start();
- $this->db = DB::start();
- $this->context->set_db($this->db);
- }
-
- private function execute_action($action){
- require_once(PATH::ACTION . $action . ".php");
- action();
- return;
- }
- /**
- * Handles the request parameters.
- *
- * Receives the request params and gets itself ready. Authenticates the user (if needed)
- * and validates the URL.
- *
- * @param string[] $params GET parameters of the request.
- */
- public function prepare($params){
- // Parse parameters.
- foreach($params as $p){
- if (strlen($p) > 0){
- array_push($this->params, $p);
- }
- }
-
- // Chack if a user is authenticated.
- if (array_key_exists("user_token", $_COOKIE) && array_key_exists("user_id", $_COOKIE)){
- // Authenticated user, check token.
- $statement = $this->db->prepare("
- SELECT count(token) AS c
- FROM token
- WHERE
- user = :user AND
- token = :token AND
- strftime('%s', datetime(expiry, 'unixepoch', 'localtime')) > strftime('%s','now')
- ");
- $statement->bindValue(":user", $_COOKIE["user_id"], SQLITE3_INTEGER);
- $statement->bindValue(":token", hash('sha256', $_COOKIE["user_token"]), SQLITE3_TEXT);
- $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
- if ($r["c"] == 0){
- // Token is invalid, expired, clear cookies, session, and logout.
- execute_action("logout");
- return;
- }
- else{
- // Token is valid, renew session, and assign user.
- $_SESSION["user_id"] = $_COOKIE["user_id"];
- $_SESSION["session"] = true;
- $this->context->set_user(new User($_COOKIE["user_id"]));
- }
-
- }
- else{
- // Unauthenticated user. Continue
- }
-
- $auth_required = false;
- $player_id = null;
-
- // Obtain the command and process it
- if (sizeof($this->params) > 0){
- $this->command = strtoupper($this->params[0]);
- }
- switch ($this->command){
- case "": // Main page
- break;
- case "API": // An API call
- return; // End preparation here, the API controller will deal with everything.
- break;
- case "ACTION": // Execute an action
- $auth_required = true;
- break;
- case "PLAYER": // A player page
- if (sizeof($this->params) > 1){
- $player_id = $this->params[1];
- }
- else{
- $this->status = 400;
- $this->message = "Bad request";
- return;
- }
- break;
- case "LOGIN": // The login page
- break;
- case "REGISTER": // Registration page
- break;
- case "SEARCH": // Search results
- break;
- case "DUNGEON": // Dungeon static pages
- break;
- case "BUILDING": // Building static pages
- break;
- case "FUSION": // Fusion static pages
- break;
- case "HELP": // Help static page
- break;
- case "ERROR": // Error page
- break;
- default: // Unknown page
-
- }
-
- if ($player_id != null){
- $this->context->set_player(new Player($player_id));
- if ($this->context->get_player()->get_id() == null){
- $this->status = 404;
- $this->message = "Requested player doesn't exist";
- return;
- }
- }
-
- if ($auth_required && $this->context->get_user() == null){
- $this->status = 401;
- $this->message = "Authentication required to perform this action";
- return;
- }
- // Get game mode
- if ($this->context->get_player() == null){
- $this->context->set_game_mode(GAME_MODE_ID::NORMAL);
- }
- else{
- $statement = $this->db->prepare("SELECT mode FROM player WHERE id = :id;");
- $statement->bindValue(":id", $this->context->get_player()->get_id(), SQLITE3_INTEGER);
- $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
- if ($r && $r["mode"] == GAME_MODE_ID::RTA){
- $this->context->set_game_mode(GAME_MODE_ID::RTA);
- }
- else{
- $this->context->set_game_mode(GAME_MODE_ID::NORMAL);
- }
- }
- }
- /**
- * Executes the required action.
- *
- * Must be called after {@see Controller::prepare()}.
- * @return void|number
- */
- public function action(){
-
- // If there was an error in preparation, it's time to throw it.
- if ($this->status >= 400 && $this->status < 500){
- $page = new Error_Page($this->status, $this->message);
- require_once($page->get_view());
- http_response_code(404);
- return 404;
- }
-
- // Process the command
- error_log("SWITCH COMMAND: " . $this->command);
- $page = null;
- switch ($this->command){
- case "": // Main page
- // Two options:
- // If user authenticated, retrieve last used player acocunt and load main page
- // If not, login page.
- if ($this->context->get_user() == null){
- require_once(PATH::PAGE . "Login_Page.php");
- $page = new Login_Page();
- }
- else{
- $statement = $this->context->get_db()->prepare("
- SELECT id
- FROM player
- WHERE user = :user
- ORDER BY last_access DESC
- LIMIT 1;
- ");
- $statement->bindValue(":user", $this->context->get_user()->get_id(), SQLITE3_INTEGER);
- $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
- if ($r){
- header("Location: " . URL::BASE . "player/" . $r["id"]);
- return;
- //$this->context->set_player(new Player($r["id"]));
- //require_once(PATH::PAGE . "Player_Page.php");
- //$page = new Player_Page();
- }
- else{
- // TODO: weird case: user with no players
- }
- }
- break;
- case "API": // An API call
- error_log("STARTING API CALL");
- if (count($this->params) == 1){
- // TODO: Redirect to current version
- }
- else{
- $version = strtolower($this->params[1]);
- $api_params = $this->params;
- array_shift($api_params);
- array_shift($api_params);
- switch ($version){
- case "v1":
- error_log("STARTING API V1 Controller");
- require_once(__DIR__ . "/API/v1/API_Controller.php");
- new API_Controller($this->params);
- return;
- break;
- default:
- require_once(PATH::PAGE . "Error_Page.php");
- $page = new Error_Page(404, "API version doesn't exist.");
- require_once($page->get_view());
- http_response_code(404);
- return 404;
- }
- }
- break;
- case "ACTION": // Execute an action
- // If no action specified
- if (sizeof($this->params) < 2){
- require_once(PATH::PAGE . "Error_Page.php");
- $page = new Error_Page(400, "No action specified.");
- require_once($page->get_view());
- http_response_code(400);
- return 400;
- }
-
- // Process action
- $action = strtoupper($this->params[1]);
- switch ($action){
- // Special cases where the output must be printed:
- case "OPTIMIZE_LIST":
- require_once(PATH::ACTION . "Optimize_List_Action.php");
- $action = new Optimize_List_Action();
- break;
- case "OPTIMIZE_OPTIONS":
- require_once(PATH::ACTION . "Optimize_Options_Action.php");
- $action = new Optimize_Options_Action();
- break;
- case "CHANGE_GAME_MODE":
- require_once(PATH::ACTION . "Change_Game_Mode_Action.php");
- $action = new Change_Game_Mode_Action();
- break;
- case "LOGIN":
- require_once(PATH::ACTION . "Login_Action.php");
- $action = new Login_Action();
- break;
- case "LOGOUT":
- require_once(PATH::ACTION . "Logout_Action.php");
- $action = new Logout_Action();
- break;
- case "REGISTER":
- require_once(PATH::ACTION . "Register_Action.php");
- $action = new Register_Action();
- break;
- case "ADD_TEAM":
- require_once(PATH::ACTION . "Add_Team_Action.php");
- $action = new Add_Team_Action();
- break;
- case "EDIT_PROFILE":
- require_once(PATH::ACTION . "Edit_Profile_Action.php");
- $action = new Edit_Profile_Action();
- break;
- case "DELETE_TEAM":
- require_once(PATH::ACTION . "Delete_Team_Action.php");
- $action = new Delete_Team_Action();
- break;
- case "RATE_TEAM":
- require_once(PATH::ACTION . "rate_team.php");
- $action = new Rate_Team_Action();
- break;
- case "SAVE_TEAM":
- require_once(PATH::ACTION . "Save_Team_Action.php");
- $action = new Save_Team_Action();
- break;
- default:
- require_once(PATH::PAGE . "Error_Page.php");
- $page = new Error_Page(404, "Action not found");
- require_once($page->get_view());
- http_response_code(404);
- return;
- }
- $action->execute();
- if ($action->get_code() >= 400 && $action->get_code() < 500){
- require_once(PATH::PAGE . "Error_Page.php");
- $page = new Error_Page($action->get_code(), $action->get_message());
- require_once($page->get_view());
- http_response_code($action->get_code());
- }
- if (strlen($action->get_output()) > 0){
- echo($action->get_output());
- }
- return $action->get_code();
- break;
- case "PLAYER": // A player page
- error_log("CASE PLAYER");
- if ($this->context->get_player() == null || $this->context->get_player()->get_id() == null){
- require_once(PATH::PAGE . "Error_Page.php");
- $page = new Error_Page(404, "Player not found");
- require_once($page->get_view());
- http_response_code(404);
- return;
- }
- if (
- $this->context->get_player()->is_public() == false &&
- (
- $this->context->get_user() == null ||
- $this->context->get_player()->get_user() != $this->context->get_user()->get_id()
- )
- ){
- require_once(PATH::PAGE . "Error_Page.php");
- $page = new Error_Page(401, "Player profile set to private");
- require_once($page->get_view());
- http_response_code(401);
- }
- $subcommand = "";
- if (sizeof($this->params) > 2){
- $subcommand = strtoupper($this->params[2]);
- }
- $page = null;
- switch ($subcommand){
- case "": // Player profile
- require_once(PATH::PAGE . "Player_Page.php");
- $page = new Player_Page($this->context->get_player()->get_id());
- break;
- case "RUNES":
- require_once(PATH::PAGE . "Runes_Page.php");
- $page = new Runes_Page();
- break;
- case "ENCHANTMENTS":
- require_once(PATH::PAGE . "Enchantments_Page.php");
- $page = new Enchantments_Page();
- break;
- case "ARTIFACTS":
- require_once(PATH::PAGE . "Artifacts_Page.php");
- $page = new Artifacts_Page();
- break;
- case "GUILD":
- require_once(PATH::PAGE . "Guild_Page.php");
- $page = new Guild_Page();
- break;
- case "RUNS":
- require_once(PATH::PAGE . "Runs_Page.php");
- $page = new Runs_Page();
- break;
- /*case "STATS":
- require_once(PATH::PAGE . "Stats_Page.php");
- $page = new Stats_Page();
- break;*/
- case "TEAMS":
- require_once(PATH::PAGE . "Teams_Page.php");
- $page = new Teams_Page();
- break;
- case "UNITS":
- if (sizeof($this->params) > 3){
- require_once(PATH::PAGE . "Unit_Page.php");
- $page = new Unit_Page($this->params[3]);
- }
- else{
- require_once(PATH::PAGE . "Units_Page.php");
- $page = new Units_Page();
- }
- break;
- case "REPORT":
- if (sizeof($this->params) > 3){
- if (strtoupper($this->params[3]) == "SKILLUP"){
- require_once(PATH::PAGE . "Report_Skillup_Page.php");
- $page = new Report_Skillup_Page();
- }
- elseif (strtoupper($this->params[3]) == "RUNE_ENCHANTMENT"){
- require_once(PATH::PAGE . "Report_Rune_Enchantment_Page.php");
- $page = new Report_Rune_Enchantment_Page();
- }
- }
- else{
- require_once(PATH::PAGE . "Report_Page.php");
- $page = new Report_Page();
- }
- break;
- case "OPTIMIZER":
- if (sizeof($this->params) > 3){
- require_once(PATH::PAGE . "Optimizer_Unit_Page.php");
- $page = new Optimizer_Unit_Page($this->params[3]);
- }
- else{
- require_once(PATH::PAGE . "Optimizer_Page.php");
- $page = new Optimizer_Page();
- }
- break;
- }
- break;
- case "MONSTERS":
- error_log("PARAM2: " . $this->params[1]);
- if (sizeof($this->params) > 1){
- require_once(PATH::PAGE . "Monster_Page.php");
- $page = new Monster_Page($this->params[1]);
- }
- else{
- require_once(PATH::PAGE . "Monsters_Page.php");
- $page = new Monsters_Page();
- }
- break;
- case "LOGIN": // The login page
- require_once(PATH::PAGE . "Login_Page.php");
- $page = new Login_Page();
- break;
- case "REGISTER": // Registration page
- require_once(PATH::PAGE . "Register_Page.php");
- $page = new Register_Page();
- break;
- case "SEARCH": // Search results
- require_once(PATH::PAGE . "Search_Page.php");
- $page = new Search_Page();
- break;
- /*case "DUNGEONS": // Dungeon static pages
- require_once(PATH::PAGE . "Login_Page.php");
- $page = new Dungeons_Page();
- break;*/
- case "BUILDINGS": // Building static pages
- if (sizeof($this->params) > 1){
- require_once(PATH::PAGE . "Building_Page.php");
- $page = new Building_Page($this->params[1]);
- }
- else{
- require_once(PATH::PAGE . "Buildings_Page.php");
- $page = new Buildings_Page();
- }
- break;
- break;
- /*case "FUSION": // Fusion static pages
- require_once(PATH::PAGE . "Fusion_Page.php");
- $page = new Fusion_Page();
- break;*/
- case "HELP": // Help static page
- require_once(PATH::PAGE . "Help_Page.php");
- $page = new Help_Page();
- break;
- }
-
- // If page is not set, it's a not found.
- if ($page == null){
- require_once(PATH::PAGE . "Error_Page.php");
- $page = new Error_Page(404, "Page not found");
- }
-
- // Once the page is loaded, chack if it can be seen
- // TODO verify
- if (! $page->is_public() && $this->get_user() == null){
- require_once(PATH::PAGE . "Error_Page.php");
- $page = new Error_Page(401, "Authentication required");
- http_response_code(401);
- }
-
- if ($page->get_code() >= 400 && $page->get_code() < 600){
- require_once(PATH::PAGE . "Error_Page.php");
- $page = new Error_Page($page->get_code(), $page->get_message());
- http_response_code($page->get_code());
- }
-
-
- // Load the view, or set an error code.
- require_once($page->get_view());
- http_response_code($page->get_code());
- }
- }
|