Webbserverprogrammering 1

Show sourcecode

The following files exists in this folder. Click to view.

webbsrvprg/exercises/slutprojekt/

actions.php
administer_users.php
create_code.php
database_include.php
dbconnection.php
index.php
login copy.php
login.php
main.php
password_renewals.php
play copy.php
play.php
setup.php
sign_up.php
statistics.php
verification.php
verify_mail.php

main.php

345 lines UTF-8 Windows (CRLF)
<?php
ini_set
('display_errors'1);
ini_set('display_startup_errors'1);
error_reporting(E_ALL);
session_start(["gc_maxlifetime" => 86400]);
?>

<!DOCTYPE html>
<html lang="sv">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Main</title>
    <style>
        fieldset {
            margin: 5px;
            padding: 5px;
            border: 2px solid black;
        }

        #show_password {
            width: 10em;
            border: 1px solid gray;
            background-color: lightgray;
        }

        #que_status {
            background-color: lightgreen;
            border: 2px solid black;
            box-shadow: 0px 0px 4px;
            border-radius: 10px;
            text-align: center;
            font-size: 2em;
        }

        #friend_cont {
            padding: 0 5px 5px 5px;
            border: 2px solid black;
        }

        #friend_request_cont {
            padding: 0 5px 5px 5px;
            border: 2px solid black;
        }

        .green {
            background-color: lightgreen;
        }

        .red {
            background-color: lightcoral;
        }

        h3 {
            margin: 3px;
        }

        b {
            font-weight: bold;
        }

        button {
            cursor: pointer;
        }

        * {
            box-sizing: border-box;
            font-family: Arial, Helvetica, sans-serif;
        }
    </style>
</head>

<body>
    <?php
    
echo ("<h1>" $_SESSION["username"] . "</h1>");
    try {
        
/** @var PDO $dbconn */
        
include("dbconnection.php");
        
$adminrequired FALSE;
        include(
"verification.php");

        if (isset(
$_POST["request_username"])) {
            
// Man har skickat en vänförfrågan
            
$username $_POST["request_username"];
            
$sql "SELECT id FROM bs_users WHERE username = ?";
            
$stmt $dbconn->prepare($sql);
            
$data = [$username];
            
$stmt->execute($data);
            
$row $stmt->fetch(PDO::FETCH_ASSOC);

            
// if ($row) { // Om användaren finns
                
$target_id $row["id"]; // id't av användaren man vill fråga.
                
$user_id $_SESSION["user_id"]; // Ens egna id.

                // Inget hinder mot att skicka till de som redan är ens vänner men det blockeras där vänrelationerna skapas
                
$sql "INSERT INTO bs_friend_requests (user_1_id, user_2_id)
            SELECT ?, ?
            WHERE NOT EXISTS (
            SELECT 1 FROM bs_friend_requests WHERE user_1_id = ? AND user_2_id = ?)"
;
                
$stmt $dbconn->prepare($sql);
                
$data = [$user_id$target_id$user_id$target_id];
                
$stmt->execute($data);
            
// }
        
}
    } catch (
PDOException $e) {
        echo (
$e->getMessage());
    }

    if (
$_SESSION["is_admin"]) {
        
// Eftersom det är ofarligt att rensa matchloggar så kan även vanliga användare göra det om de lyckas ta reda på hur koden ser ut.
        
echo ('<a href="administer_users.php">Överse användare</a><br><br><!-- <button>Rensa matchloggar</button> -->');
    }
    
?>

    <a href="login.php?log_out=true">Logga ut</a><br>
    <a href="password_renewals.php" target="_blank">Byt lösenord</a><br><br>
    <a href="statistics.php">Se statistik</a><br>


    <fieldset>
        <legend>SPELA</legend>
        <p id="que_status">Inte i kö</p>
        <button type="button" id="que_all" class="que_btn">Spela med vem som helst</button><br>
        <button type="button" id="que_friends" class="que_btn">Spela med vänner</button><br>
        <!-- <button type="button" id="que_individual" class="que_btn" disabled>Spela med markerad vän</button><br> -->
        <br>
        <button type="button" id="exit_que">Gå ur kön</button><br>
    </fieldset>
    <div id="friend_cont">
        <h3>Vänner</h3>
        <div id="friend_list"></div>
    </div>

    <div id="friend_request_cont">
        <h3>Inkommande vänförfrågningar</h3>
        <div id="friend_request_list"></div>
        <h3>Skicka vänföfrågning</h3>
        <form method="POST">
            <input type="text" required name="request_username" id="username"><label for="username">Användarnamn</label><br>
            <button type="submit">Skicka förfrågan (om användaren finns kommer den skickas)</button>
        </form>
        <script>
            let que_interval = null; // Används för att spara interval-id som checkar ens que-status.

            function get(id) {
                return (document.getElementById(id));
            }

            function checkIn() {
                fetch("actions.php?action=CHECKIN", {
                    cache: "no-store"
                });
            }

            function toggleQueInterval(toggle_to) { // Toggle_to är true ska vara true eller false för på eller av.
                if (toggle_to && !que_interval) {
                    // Den ska vara på och är inte det
                    que_interval = setInterval(updateQueStatus, 3000);
                } else if (!toggle_to && que_interval) {
                    // Den ska vara av och är på
                    clearInterval(que_interval);
                    que_interval = null;
                }
            }

            async function updateFriendList() {
                // Uppdaterar även vänförfrågningar till en.
                try {
                    const response = await fetch("actions.php?action=GET_FRIENDS", {
                        cache: "no-store"
                    });

                    if (!response.ok) {
                        throw new Error(`Response status: ${response.status}`);
                    }

                    const result = await response.json(); // Det är json-encodat.
                    let friend_list_element = get("friend_list");
                    let html = "";

                    html += '<b>AKTIVA:</b><br><span class="green">';
                    result.online.forEach((username) => {
                        html += username + "<br>";
                    });
                    html += '</span>';

                    html += '<br><b>INAKTIVA:</b><br><span class="red">'
                    result.offline.forEach((username) => {
                        html += username + "<br>";
                    });
                    html += '</span>';
                    friend_list_element.innerHTML = html;

                    const container = get("friend_request_list");
                    container.innerHTML = ""; // Tömmer den
                    result.pending.forEach((request) => {
                        // Skapar en liten ruta i för varje request där man får tacka ja eller nej

                        // request[0] är id't och [1] är username
                        const box = document.createElement("div");
                        box.style.border = "1px solid black";
                        box.style.padding = "10px";
                        box.style.margin = "10px";
                        box.style.width = "200px";
                        box.id = "request_box_" + request[0];

                        // Texten i rutan
                        const label = document.createElement("div");
                        label.innerText = request[1];

                        // Ja-knappen
                        const yes_btn = document.createElement("button");
                        yes_btn.innerText = "Acceptera";
                        yes_btn.style.backgroundColor = "lightgreen";
                        yes_btn.onclick = () => answerFriendRequest(1, request[0]); // Tackar ja

                        // Nej-knappen
                        const no_btn = document.createElement("button");
                        no_btn.innerText = "Neka";
                        no_btn.style.backgroundColor = "lightcoral";
                        no_btn.onclick = () => answerFriendRequest(0, request[0]); // Tackar nej

                        // Lägg ihop allt i lådan
                        box.appendChild(label);
                        box.appendChild(yes_btn);
                        box.appendChild(no_btn);

                        // Skapa lådan i listan
                        container.appendChild(box);
                    });

                } catch (error) {
                    console.error(error.message);
                }
            }

            function answerFriendRequest(answer, id) {
                // answer är 1 eller 0 för säga ja eller nej. id är id't på personen som skickat förfrågan
                box = get("request_box_" + id);
                box.remove(); // Tar bort förfrågningen
                const link = "actions.php?action=ANSWER_FRIEND_REQUEST" +
                    "&id=" + encodeURIComponent(id) +
                    "&answer=" + encodeURIComponent(answer);
                fetch(link, {
                    cache: "no-store"
                }); // Fipplar i databasen.
            }

            function setQueStatus(status) {
                // status är 1, 2 eller 3 för inte sökande, söker alla eller söker vänner
                let element = get("que_status")
                if (status == 1) {
                    element.style.background = "lightgreen";
                    element.innerHTML = "Inte i kö";
                } else if (status == 2) {
                    element.style.background = "lightcoral";
                    element.innerHTML = "Söker efter match";
                } else {
                    element.style.background = "lightcoral";
                    element.innerHTML = "Söker efter match med vänner";
                }
            }

            async function updateQueStatus() {
                // Kollar om man är i kön när man laddar in sidan och kollar om man hamnat i en match när man står i kön
                // Uppdaterar även ens bs_que.lastcheckin om man är i kö
                try {
                    const response = await fetch("actions.php?action=UPDATE_QUE_STATUS", {
                        cache: "no-store"
                    });

                    if (!response.ok) {
                        throw new Error(`Response status: ${response.status}`);
                    }

                    let result = await response.text();
                    result = result.trim();
                    // response är ALL eller FRIENDS eller ett tal (id på matchen man är i) eller tom
                    if (result == "ALL") {
                        setQueStatus(2);
                        toggleQueInterval(true);
                    } else if (result == "FRIENDS") {
                        setQueStatus(3);
                        toggleQueInterval(true);
                    } else if (result == "") {
                        // Om man inte är i kö
                        setQueStatus(1);
                        toggleQueInterval(false);
                    } else if (!isNaN(result)) {
                        // Konstig dubbelnegation men kommer hit om det är ett nummer, alltså id't på matchen man är i.
                        // Man är inne i en match
                        setQueStatus(1);
                        toggleQueInterval(false);

                        // Den som joinar är den som "skapar" matchen i databasen så det görs inte här.
                        window.location.href = 'play.php?game_id=' + result;
                    } else {
                        // Något har gått fel
                        console.error(result);
                    }

                } catch (error) {
                    console.error(error.message);
                }
            }

            updateQueStatus() // Hämtar direkt ens que-information.

            checkIn(); // Checkar in en gång direkt
            updateFriendList(); // Kollar vilka vänner som finns och är online
            setInterval(() => {
                // Checkar in och kollar efter vänner 2ggr per minut
                checkIn();
                updateFriendList();
                console.log("30s update ran");
            }, 30000);

            get("que_all").addEventListener("click", () => {
                fetch("actions.php?action=ENTER_QUE&scope=ALL", {
                    cache: "no-store"
                });
                setQueStatus(2); // Skriver ut för användaren hur det är med kön
                toggleQueInterval(true);
            })

            get("que_friends").addEventListener("click", () => {
                fetch("actions.php?action=ENTER_QUE&scope=FRIENDS", {
                    cache: "no-store"
                });
                setQueStatus(3)
                toggleQueInterval(true);
            })

            get("exit_que").addEventListener("click", () => {
                fetch("actions.php?action=EXIT_QUE", {
                    cache: "no-store"
                });
                setQueStatus(1)
                toggleQueInterval(false);
            })
        </script>
</body>

</html>