diff --git a/database.php b/database.php index 68098c5..c12b9e5 100644 --- a/database.php +++ b/database.php @@ -13,7 +13,7 @@ class Database $hash_id = ''; for ($i = 0; $i < $length; $i++) - $hash_id .= $characters[rand (0, $characters_length - 1)]; + $hash_id .= $characters[mt_rand (0, $characters_length - 1)]; return $hash_id; } @@ -145,6 +145,69 @@ class Database } /** + * Retrieve a $user from database using remember_me token + */ + function get_remember_me ($token) + { + $user = array(); + + if (is_null ($this->database)) + return $user; + + $query = $this->database->prepare( + 'SELECT U.* ' . + 'FROM `user` AS U ' . + 'JOIN `remember_me` AS R ON R.`userId` = U.`id`' . + 'WHERE R.`token` = ? AND R.`expires` > NOW()'); + + $query->execute (array (hash ('sha512', $token))); + + $user = $query->fetch (PDO::FETCH_ASSOC); + + return $user; + } + + /** + * Set a new remember_me token to database + * + * @return secret token (cleartext) + */ + function set_remember_me ($user_id) + { + /* Set remember me token. + * The cleartext token is stored as a user cookie, while in our + * database we store hash(token). + */ + + // Delete all previous remember_me tokens for $user + self::delete_remember_me ($user_id); + + // Create a new secret token + $token = self::get_random_string (128); + + $query = $this->database->prepare ( + 'INSERT INTO `remember_me` (`token`, `userId`, `expires`)' . + 'VALUES (?, ?, NOW() + INTERVAL 30 DAY)'); + + $query->execute (array (hash('sha512', $token), $user_id)); + + return $token; + } + + /** + * Delete $user "remember_me" token + */ + function delete_remember_me ($user_id) + { + // Delete all previous remember_me tokens for $user + $query = $this->database->prepare( + 'DELETE FROM `remember_me`' . + 'WHERE `userId` = ?'); + + $query->execute (array ($user_id)); + } + + /** * Retrieve a post */ function get_post ($hash_id) @@ -815,15 +878,15 @@ class Database 'DELETE FROM `vote_post`' . 'WHERE `postId` = ? AND `userId` = ?'); - $query->execute (array ($post['id'], $user_id)); + $query->execute (array ($post['id'], $user_id)); + + // Remove upvote from post + $query = $this->database->prepare ( + 'UPDATE `post`' . + 'SET `vote` = `vote` - 1 ' . + 'WHERE `id` = ?'); - // Remove upvote from post - $query = $this->database->prepare ( - 'UPDATE `post`' . - 'SET `vote` = `vote` - 1 ' . - 'WHERE `id` = ?'); - - $query->execute (array ($post['id'])); + $query->execute (array ($post['id'])); } elseif ($vote['vote'] == -1) { // Already downvoted before. Change to upvote. diff --git a/login.php b/login.php index 70d7baf..9b87235 100644 --- a/login.php +++ b/login.php @@ -37,9 +37,26 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') if (is_null ($user) || empty ($user)) { $feedback = 'Bad login!'; + } else { + + // Set session Session::set ($user); + // Also set "remember_me" cookie + // Add "remember_me" cookie with secret token (30 days) + $token = $db->set_remember_me ($user['id']); + + setcookie ( + 'remember_me', // name + $token, // value + time()+60*60*24*30, // expire (30 days) + '/', // path + 'freepo.st', // domain + false, // secure (clients send cookie only through HTTPS) + true); // httponly (no javascript) + + // After login, redirect to homepage header ('Location: ./'); exit (); } diff --git a/logout.php b/logout.php index e8c7235..7d7a2c2 100644 --- a/logout.php +++ b/logout.php @@ -1,8 +1,38 @@ connect (); + $db->delete_remember_me (Session::get_userid ()); + + unset ($_COOKIE['remember_me']); + + // Invalidate cookie + setcookie ( + 'remember_me', // name + NULL, // value + -1, // expire + '/', // path + 'freepo.st', // domain + false, // secure (clients send cookie only through HTTPS) + true); // httponly (no javascript) +} + +// Delete session Session::delete (); +// Logged out, redirect to homepage header ('Location: ./'); exit (); \ No newline at end of file diff --git a/session.php b/session.php index ded267d..5a3abe2 100644 --- a/session.php +++ b/session.php @@ -1,7 +1,6 @@ array ( 'id' => $user['id'], @@ -60,11 +63,51 @@ class Session { $_SESSION['user'][$property] = $value; } + // Retrieve session from cookie + public static function remember_me () + { + // We already have a session, nothing to do here + if (Session::is_valid ()) + return; + + // Check if user does not have a "remember_me" cookie + if (!isset ($_COOKIE['remember_me'])) + return; + + // Validate token + $db = new Database (); + $db->connect (); + + $user = $db->get_remember_me ($_COOKIE['remember_me']); + + self::set ($user); + } + public static function delete () { unset ($_SESSION); session_destroy (); + // Delete session $_SESSION = NULL; } -} \ No newline at end of file +} + +session_name ('freepost'); +session_start (); + +/* Once the session is started, check for "remember_me" tokens. + * If the session is already set, this function doesn't do anything. + * If session is not set, and a valid token is set on user's cookies, + * than the user is retrieved. + */ +Session::remember_me (); + + + + + + + + +