generate_session_key(); $this->session = $database->create( 'cora\session', [ 'session_key' => $session_key, 'timeout' => $timeout, 'life' => $life, 'user_id' => $user_id, 'created_by' => ip2long($_SERVER['REMOTE_ADDR']), 'last_used_by' => ip2long($_SERVER['REMOTE_ADDR']), 'last_used_at' => date('Y-m-d H:i:s') ] ); // Set the local cookie expiration. if($life !== null) { $expire = time() + $life; } else { if($timeout === null) { $expire = 4294967295; // 2038 } else { $expire = 0; // Browser close } } // Set all of the necessary cookies. Both *_session_key and *_user_id are // read every API request and made available to the API. $this->set_cookie('session_key', $session_key, $expire); if(isset($additional_cookie_values) === true) { foreach($additional_cookie_values as $key => $value) { $this->set_cookie($key, $value, $expire, false); } } return $session_key; } /** * Similar to the Linux touch command, this method "touches" the session and * updates last_used_at and last_used_by. This is executed every time a * request that requires a session is sent to the API. Note that this uses * the cookie sent by the client directly so there is no default way to * touch a session unless you are the one logged in to it. * * @param $string session_key The session_key to use. If not set, will use * $_COOKIE['session_key']. * * @return bool True if it was successfully updated, false if the session * does not exist or is expired. Basically, return bool whether or not the * sesion is valid. */ public function touch($session_key = null) { if($session_key === null && isset($_COOKIE['session_key']) === true) { $session_key = $_COOKIE['session_key']; } if($session_key === null) { return false; } $database = database::get_instance(); $sessions = $database->read( 'cora\session', [ 'session_key' => $session_key, 'deleted' => 0 ] ); if(count($sessions) === 1) { $session = $sessions[0]; // Check for expired session. if( ( $session['timeout'] !== null && (strtotime($session['last_used_at']) + strtotime($session['timeout'])) < time() ) || ( $session['life'] !== null && (strtotime($session['last_used_at']) + strtotime($session['life'])) < time() ) ) { $this->delete_cookie('session_key'); return false; } $this->session = $database->update( 'cora\session', [ 'session_id' => $session['session_id'], 'last_used_at' => date('Y-m-d H:i:s'), 'last_used_by' => ip2long($_SERVER['REMOTE_ADDR']) ] ); return true; } else { $this->delete_cookie('session_key'); return false; } } private function invalidate_cookies() { } /** * Delete the session with the provided session_key. If no session_key is * provided, delete the current session. This function is provided to aid * session management. Call it with no parameters for something like * user->log_out(), or set $session_key to end a specific session. You would * typically want to have your own permission layer on top of that to enable * only admins to do that. * * @param string $session_key The session key of the session to delete. * * @return bool True if it was successfully deleted. Could return false for * a non-existent session key or if it was already deleted. */ public function delete($session_key = null) { $database = database::get_instance(); if($session_key === null) { $session_key = $this->session['session_key']; } $sessions = $database->read('cora\session', ['session_key' => $session_key]); if(count($sessions) === 1) { $database->delete('cora\session', $sessions[0]['session_id']); // Remove these if the current session got logged out. if($session_key === $this->session['session_key']) { $this->session = null; } return true; } return false; } /** * Get the user_id on this session. Useful for getting things like the * user_id for the currently logged in user. * * @return int The current user_id. */ public function get_user_id() { if ($this->session !== null) { return $this->session['user_id']; } return null; } /** * Get the session. * * @return array The session. */ public function get() { return $this->session; } /** * Generate a random (enough) session key. * * @return string The generated session key. */ private function generate_session_key() { return bin2hex(random_bytes(20)); } /** * Sets a cookie. If you want to set custom cookies, use the * $additional_cookie_values argument on $session->create(). * * @param string $name The name of the cookie. * @param mixed $value The value of the cookie. * @param int $expire When the cookie should expire. * @param bool $httponly True if the cookie should only be accessible on the * server. * * @throws \Exception If The cookie fails to set. */ private function set_cookie($name, $value, $expire, $httponly = true) { $this->setting = setting::get_instance(); $path = '/'; // The current directory that the cookie is being set in. $secure = $this->setting->get('force_ssl'); preg_match( '/https?:\/\/(.*?)\//', $this->setting->get('beestat_root_uri'), $matches ); $domain = $matches[1]; $cookie_success = setcookie( $name, $value, $expire, $path, $domain, $secure, $httponly ); if($cookie_success === false) { throw new \Exception('Failed to set cookie.', 1400); } } /** * Delete a cookie. This will remove the cookie value and set it to expire 1 * day ago. * * @param string $name The name of the cookie to delete. */ private function delete_cookie($name) { $this->set_cookie($name, '', time() - 86400); } /** * Check if the session is valid. * * @return bool Whether or not the session is valid. */ public function is_valid() { return $this->session !== null; } }