<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Login extends CI_Controller
{
	private $messages 			= array();
	private $errors 			= array();
	private $location_denied 	= false;

	public function __construct()
	{
		parent::__construct();

		// Force SSL if the constant is set but the HTTPS server variable is not set or set but false.
		if(defined("FORCE_SSL") && FORCE_SSL && preg_match('/^http:/', current_url()) && !is_cli())
		{
			if(defined("LOGGING")) { error_log(PRODUCT_NAME . ": Redirecting to HTTPS."); }
			redirect(str_replace("http://", "https://", current_url()), 'auto', 301);
		}

		Mainframe::init();

		if(!$this->check_ip())
		{
			$this->errors[] = "Access Denied";
			$this->location_denied = true;
		}
	}

	public function index()
	{
		$data = array("show_menu" => false, "dashboard" => false);

		$this->load->view("common/header", $data);
		$this->load->view("common/message", array("messages" => $this->messages, "errors" => $this->errors));
		if(!$this->location_denied)
		{
			$this->load->view("login/form", $data);
		}
		$this->load->view("common/footer", $data);
	}

	private function check_ip()
	{
		$ip 	= $this->input->server("REMOTE_ADDR");
		$ch 	= curl_init("http://ip-api.com/json/" . $ip);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
		curl_setopt($ch, CURLOPT_TIMEOUT, 3);
		$result = json_decode(curl_exec($ch));
		curl_close($ch);

		if(isset($result->status))
		{
			// In the event that the IP to country service fails, we'll allow the user to login.
			if($result->status == "fail")
			{
				return true;
			}
			else
			{
				// Only allow users from Canada or United States.
				return ($result->countryCode == "CA" || $result->countryCode == "US");
			}
		}
		else
		{
			// In the event that the IP to country service fails, we'll allow the user to login.
			return true;
		}
	}

	/**
	 * Process a login attempt.
	 *
	 * @access public
	 * @return void
	 */
	public function process()
	{
		if($this->location_denied)
		{
			$this->index();
		}
		csrf_verify();

		$this->load->helper('url');
		$this->load->library('encryption');

		$user = $this->user->authenticate($this->input->post("username", true), $this->input->post("password"), true);

		if($user === false)
		{
			$this->errors[] = "Access Denied";
			setcookie("user_id", "", 1, $this->config->item("cookie_path"), $this->config->item("cookie_domain"), $this->config->item("cookie_secure"), $this->config->item("cookie_httponly"));
			$this->index();
		}
		else if($user !== false)
		{
			setcookie("user_id", $this->encryption->encrypt($user->user_id), time() + $this->config->item("sess_expiration"), $this->config->item("cookie_path"), $this->config->item("cookie_domain"), $this->config->item("cookie_secure"), $this->config->item("cookie_httponly"));
			$redirect = ($this->input->post("redirect") ? html_escape(urldecode($this->input->post("redirect"))) : "/admin");
			redirect($redirect);
		}
	}

	/**
	 * Authenticate a user - custom CodeIgniter validation function.
	 *
	 * @access public
	 * @param mixed $str
	 * @return void
	 */
	public function authenticate_check($str)
	{
		$user = $this->user->authenticate($this->input->post("username", true), $this->input->post("password"));

		if($user !== false)
		{
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}

	public function pwreset()
	{
		if($this->location_denied)
		{
			$this->index();
		}

		$this->load->helper("password");

		$email = $this->input->get_post("email", true);

		$user = new User();
		$user->LoadByEmail($email);

		if(!isset($user->user_id) || $user->user_id <= 0)
		{
			$user->LoadByUsername($email);
		}

		if(isset($user->user_id) && $user->user_id > 0)
		{
			$code = generatePassword(5, '0123456789');
			$user->password_reset = password_hash($code, PASSWORD_BCRYPT);
			$user->save();

			$this->messages[] = "A password reset code has been emailed to you.";
			send_notification($user, "Password Reset", "<p>Hello $user->fname,</p><p>Somebody (hopefully you) has requested that your password for " . LIVE_SITE . " be reset.</p><p>Your password reset code is: <b>$code</b></p><p>You'll need to enter that code on the password reset screen where you started this process.</p>");
		}
		else
		{
			$this->errors[] = "No user was found with this username or email address.";
			return $this->index();
		}

		$this->_pwreset($user);
	}

	private function _pwreset($user)
	{
		$data = array("show_menu" => false, "dashboard" => false);
		$data["user_id"] = $user->user_id;

		$this->load->view("common/header", $data);
		$this->load->view("common/message", array("messages" => $this->messages, "errors" => $this->errors));
		if(!$this->location_denied)
		{
			$this->load->view("login/reset", $data);
		}
		$this->load->view("common/footer", $data);
	}

	public function pwsave()
	{
		if($this->location_denied)
		{
			$this->index();
		}
		csrf_verify();

		$this->load->helper("password");
		$user_id   = (int)$this->input->post("user_id");
		$code      = $this->input->post("resetcode");
		$password  = $this->input->post("password");
		$password2 = $this->input->post("password2");

		$result = $this->db->query("SELECT * FROM users WHERE user_id=?", array($user_id));

	    if($result->num_rows() > 0)
	    {
	    	$row = $result->row();

	    	$user = new User();
			$user->populate($row);

			if(password_verify($code, $row->password_reset))
			{
				if($password != $password2)
				{
					$this->errors[] = "Your new password and retyped new password don't match.";
					return $this->_pwreset($user);
				}

				$user->password       = password_hash($password, PASSWORD_BCRYPT);
				$user->password_reset = null;

				if($user->save())
				{
					$this->messages[] = "Your password has been changed.";
				}
				else
				{
					$this->errors[] = "There was an error saving your new password.";
					return $this->_pwreset($user);
				}
			}
			else
			{
				$this->errors[] = "The password reset code entered is invalid.";
				return $this->_pwreset($user);
			}
		}

		$this->index();
	}

	/**
	 * Logout a user and kill their session.
	 *
	 * @access public
	 * @return void
	 */
	function logout()
	{
		setcookie("user_id", "", 1, $this->config->item("cookie_path"), $this->config->item("cookie_domain"), $this->config->item("cookie_secure"), $this->config->item("cookie_httponly"));

		$this->messages[] = "You Have Logged Out";
		$this->index();
	}

	/**
	 * Access is denied to a specific page or attempt to otherwise access something you're not supposed to.
	 *
	 * @access public
	 * @return void
	 */
	public function denied()
	{
		$data = array("show_menu" => true, "dashboard" => true);

		$this->errors[] = "Access Denied";
		$this->index();
	}
}
