From 87c9f9d188138dca07d4b37c2bfcb6fb5bf1315a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zden=C4=9Bk=20Borovec?= Date: Sat, 4 May 2024 23:02:24 +0200 Subject: [PATCH] Comment writing added --- assets/common/styles.css | 6 ++ docs/common/header.php | 3 + docs/common/utils.php | 22 ++++++ docs/www/blog/article.php | 153 ++++++++++++++++++++++++++++++++------ docs/www/login.php | 66 ++++++++-------- 5 files changed, 199 insertions(+), 51 deletions(-) diff --git a/assets/common/styles.css b/assets/common/styles.css index c21d08e..a4e6827 100755 --- a/assets/common/styles.css +++ b/assets/common/styles.css @@ -284,8 +284,13 @@ code { height: 5em; } +.comment-content { + margin: 0.5em; +} + .comment-author { margin: 0.5em; + max-width: 100%; display: inline-block; } @@ -312,4 +317,5 @@ input[type=checkbox]:checked ~ .comment-response{ .comment-response { display: none; border-top: double black; + padding: 0.5em; } diff --git a/docs/common/header.php b/docs/common/header.php index 215f951..9a51045 100755 --- a/docs/common/header.php +++ b/docs/common/header.php @@ -3,6 +3,9 @@ // Include config file include_once("config.php"); +// Include utils to have access to custom classes +include_once("utils.php"); + // Start session session_start(); diff --git a/docs/common/utils.php b/docs/common/utils.php index dfef57c..7b6908d 100644 --- a/docs/common/utils.php +++ b/docs/common/utils.php @@ -1,4 +1,26 @@ user_id = $userId; + $this->user_name = $username; + $this->email = $email; + $this->permissions = $permissions; + } +} + /** * Sanitize a given input string to be safe to display and process. */ diff --git a/docs/www/blog/article.php b/docs/www/blog/article.php index c9dd152..8b129d1 100644 --- a/docs/www/blog/article.php +++ b/docs/www/blog/article.php @@ -2,7 +2,6 @@ $COMMONS = $_SERVER['DOCUMENT_ROOT'] . "/../common"; include_once($COMMONS."/header.php"); -include_once($COMMONS."/utils.php"); class BlogpostComment { @@ -10,6 +9,7 @@ class BlogpostComment public $blogpost_id; public $poster_id; public $poster_name; + public $parent_id; public $timestamp; public $content; public $children; @@ -32,13 +32,26 @@ class BlogpostComment %s
- peepeepoopoo +
+ + + +
+ +
+ +
- ", $this->poster_name, date("Y-m-d H:i", - strtotime($this->timestamp)), $this->comment_id, $this->comment_id, - $this->content); +", + $this->poster_name, date("Y-m-d H:i", strtotime($this->timestamp)), + $this->comment_id, + $this->comment_id, + $this->content, + htmlspecialchars($_SERVER["PHP_SELF"]), + $this->blogpost_id, + $this->comment_id); if($this->children != null) { for($i = 0; $i < count($this->children); $i++) @@ -56,9 +69,8 @@ class BlogpostComment public function load_children($conn) { // Prepare new statement for selecting all the child comments. $stmt = $conn->prepare("SELECT comment_id, poster_id, timestamp, - content, username FROM (blogpost_comments INNER JOIN users ON - poster_id = user_id) WHERE blogpost_id = :blogpost_id - AND parent_id = :comment_id ORDER BY timestamp ASC;"); + content FROM blogpost_comments WHERE blogpost_id = :blogpost_id AND + parent_id = :comment_id ORDER BY timestamp ASC;"); // Bind and execute the comment select $stmt->bindParam(":blogpost_id", $this->blogpost_id); @@ -69,12 +81,37 @@ class BlogpostComment $results_arr = $stmt->fetchall(PDO::FETCH_ASSOC); $comments_arr = []; + // Prepare comment author selection statement + $stmt = $conn->prepare("SELECT username FROM users WHERE + user_id = :user_id;"); + // Recursively fetch all the child comments for($i = 0; $i < count($results_arr); $i++) { $com = $results_arr[$i]; + + // If comment has a registered author, fetch their name + if($com["poster_id"]) { + $stmt->bindParam(":user_id", $com["poster_id"]); + + $stmt->execute(); + + $result = $stmt->fetch(PDO::FETCH_ASSOC); + + // If user was erased from database, set name to [Deleted] + if(!$result) { + $username = "[Deleted]"; + } + else { + $username = $result["username"]; + } + } + else { + $username = "[Guest]"; + } + $commentObj = new BlogpostComment($com["comment_id"], - $com["poster_id"], $com["username"], $this->blogpost_id, - $com["timestamp"], $com["content"]); + $com["poster_id"], $username, $this->blogpost_id, + $com["timestamp"], $com["content"], $this->comment_id); $comments_arr[] = $commentObj; $commentObj->load_children($conn); } @@ -90,15 +127,17 @@ class BlogpostComment * $blogpost_id GUID of the blogpost this comment is under. * $timestamp Timestamp at comment creation. * $content Content of the comment. + * $parent_id GUID of the comment this is a reply to (or NULL). */ public function __construct($comment_id, $poster_id, $poster_name, - $blogpost_id, $timestamp, $content) { + $blogpost_id, $timestamp, $content, $parent_id) { $this->comment_id = $comment_id; $this->blogpost_id = $blogpost_id; $this->poster_id = $poster_id; $this->poster_name = $poster_name; $this->timestamp = $timestamp; $this->content = $content; + $this->parent_id = $parent_id; } } @@ -188,16 +227,42 @@ class Blogpost } } +/** + * Send a comment to the database. + * If the poster is not signed in, send "NULL" (as a string) as the $posterID + * The same goes for $parentId (that is the parent comment, + * if this one is a response) + * Returns: error message string or null on success. + */ +function send_comment($conn, $blogId, $posterId, $content, $parentId) { + // Prepare the statemtnt + $stmt = $conn->prepare("INSERT INTO blogpost_comments + ( parent_id, blogpost_id, poster_id, content) VALUES + (:parent_id, :blogpost_id, :poster_id, :content);"); + + // Bind all the parameters + $stmt->bindValue(":parent_id", $parentId == "NULL" + ? NULL : $parentId, PDO::PARAM_STR); + $stmt->bindValue(":blogpost_id", $blogId, PDO::PARAM_STR); + $stmt->bindValue(":poster_id", $posterId == "NULL" + ? NULL : $posterId, PDO::PARAM_STR); + $stmt->bindValue(":content", $content, PDO::PARAM_STR); + + // Execute the statement + $stmt->execute(); + + return null; +} + /** * Load comments under a given blog. * Returns array of BlogpostComment objects. */ function load_comments($conn, $blogId) { - // Prepare new statement for selecting all the "root" comments on the post. - $stmt = $conn->prepare("SELECT comment_id, poster_id, timestamp, content, - username FROM (blogpost_comments INNER JOIN users ON - poster_id = user_id) WHERE blogpost_id = :blogpost_id AND - parent_id IS NULL ORDER BY timestamp ASC;"); + // Prepare new statement for selecting all the child comments. + $stmt = $conn->prepare("SELECT comment_id, poster_id, timestamp, + content FROM blogpost_comments WHERE blogpost_id = :blogpost_id + AND parent_id IS NULL ORDER BY timestamp ASC;"); // Bind and execute the comment select $stmt->bindParam(":blogpost_id", $blogId); @@ -207,11 +272,36 @@ function load_comments($conn, $blogId) { $results_arr = $stmt->fetchall(PDO::FETCH_ASSOC); $comments_arr = []; + // Prepare comment author selection statement + $stmt = $conn->prepare("SELECT username FROM users WHERE + user_id = :user_id;"); + // Recursively fetch all the child comments for($i = 0; $i < count($results_arr); $i++) { $com = $results_arr[$i]; + + // If comment has a registered author, fetch their name + if($com["poster_id"]) { + $stmt->bindParam(":user_id", $com["poster_id"]); + + $stmt->execute(); + + $result = $stmt->fetch(PDO::FETCH_ASSOC); + + // If user was erased from database, set name to [Deleted] + if(!$result) { + $username = "[Deleted]"; + } + else { + $username = $result["username"]; + } + } + else { + $username = "[Guest]"; + } + $commentObj = new BlogpostComment($com["comment_id"], $com["poster_id"], - $com["username"], $blogId, $com["timestamp"], $com["content"]); + $username, $blogId, $com["timestamp"], $com["content"], NULL); $commentObj->load_children($conn); $comments_arr[] = $commentObj; } @@ -277,6 +367,23 @@ if($conn == null){ die(); } +// If the method is post (user submitted a comment), try to post it, +// Refill the appropriate comment sumbmission form and display +// error message on error. +if(isset($_POST["submit"])) { + // Sanitise the user-submitted data + $blogId = sanitize_input($_POST["blogpost_id"]); + $commentContent = sanitize_input($_POST["comment_entry"]); + $parentId = isset($_POST["comment_id"]) ? $_POST["comment_id"] : "NULL"; + $posterId = isset($_SESSION["current_user"]) ? $_SESSION["current_user"]->user_id : "NULL"; + + // Try to send the comment + send_comment($conn, $blogId, $posterId, $commentContent, $parentId); + + // Redirect to this page with GET + header("Location: http://www.zdenekborovec-dev.cz/blog/article?guid=".$blogId); +} + // Get the blog id. $blogId = sanitize_input($_GET["guid"]); @@ -318,14 +425,18 @@ printf("

Comments:

- + +
- +
- +
-", htmlspecialchars($_SERVER["PHP_SELF"]), $blogId); +", + htmlspecialchars($_SERVER["PHP_SELF"]), $blogId, + isset($_SESSION["current_user"]) ? $_SESSION["current_user"]->user_name : + "Guest"); // Display the blog comments $blogPost->display_comments(); diff --git a/docs/www/login.php b/docs/www/login.php index c02ba97..3112188 100644 --- a/docs/www/login.php +++ b/docs/www/login.php @@ -2,22 +2,21 @@ $COMMONS = $_SERVER['DOCUMENT_ROOT'] . "/../common"; include_once($COMMONS."/header.php"); -include_once($COMMONS."/utils.php"); display_header("Login"); // Define previous attempt and error variables and set to empty values. -$emailOld = $passwordOld = ""; -$emailErr = $passwordErr = ""; +$usernameOld = $passwordOld = ""; +$usernameErr = $passwordErr = ""; /** * Process the information, and if there are no errors, log the user in. */ -function attempt_login($email, $password) { +function attempt_login($conn, $username, $password) { // Access global variables - global $emailOld; + global $usernameOld; global $passwordOld; - global $emailErr; + global $usernameErr; global $passwordErr; global $conn; @@ -34,27 +33,27 @@ function attempt_login($email, $password) { } // Sanitize inputs - $email = sanitize_input($email); + $username = sanitize_input($username); $password = sanitize_input($password); // Check if both fields are filled, if not, set appropriate error messages. - if (empty($email)) - $emailErr = "Please enter your email"; + if (empty($username)) + $usernameErr = "Please enter your email"; if (empty($password)) $passwordErr = "Please enter your password"; // If either of the fields were empty, // set old values for prefill and return. - if(!empty($emailErr) || !empty($passwordErr)) { - $emailOld = $email; + if(!empty($usernameErr) || !empty($passwordErr)) { + $usernameOld = $username; $passwordOld = $password; return; } // Prepare and bind the sql statement - $stmt = $conn->prepare("SELECT user_id, username, email, password - FROM users WHERE email = :email;"); - $stmt->bindParam(":email", $email); + $stmt = $conn->prepare("SELECT user_id, email, password, + created_at, permissions FROM users WHERE username = :username;"); + $stmt->bindParam(":username", $username); // Execute the statement $stmt->execute(); @@ -64,41 +63,48 @@ function attempt_login($email, $password) { // If the user isn't in the database, set errors, old values, and return. if(!$result) { - $emailOld = $email; + $usernameOld = $username; $passwordOld = $password; - $emailErr = "This user either doesn't exist, + $usernameErr = "This user either doesn't exist, or has a different password."; return; } // Load results to variables $db_id = $result["user_id"]; - $db_username = $result["username"]; $db_email = $result["email"]; $db_password = $result["password"]; + $db_permissions = $result["permissions"]; // If user entered incorrect password, set errors, old values, and return. // Keep the error string the same as non-existing so that an attacker // cannot asses whether a given user has an account. if(!password_verify($password, $db_password)){ - $emailOld = $email; + $usernameOld = $username; $passwordOld = $password; - $emailErr = "This user either doesn't exist, + $usernameErr = "This user either doesn't exist, or has a different password."; return; } - $_SESSION["user_id"] = $db_id; - $_SESSION["user_name"] = $db_username; - $_SESSION["user_email"] = $db_email; + // Set the session logged in user. + $_SESSION["current_user"] = new User($db_id, $username, + $db_email, $db_permissions); } /** * If user sent the form, process it. - * Either login user or set error message variables. + * Either login user and redirect to index or set error message variables. */ -if ($_SERVER["REQUEST_METHOD"] == "POST") { - attempt_login($_POST["email"], $_POST["password"]); +if (isset($_POST["submit"])) { + // Log user out + $_SESSION["current_user"] = null; + // Attempt to log in + attempt_login($conn, $_POST["username"], $_POST["password"]); + // If login succeeded, go to index + if($_SESSION["current_user"] != null) { + header("Location: "."http://www.zdenekborovec-dev.cz"); + } } ?> @@ -107,13 +113,13 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") { echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">

Login:

- + @@ -124,7 +130,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
Email: Username: - + - +
Password:
- +