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

actions.php

434 lines UTF-8 Windows (CRLF)
<?php
// Denna sida anropas av de andra för att kontakta databasen $_GET["action"] beskriver vad som ska utföras
ini_set('display_errors'1);
ini_set('display_startup_errors'1);
error_reporting(E_ALL);
session_start(["gc_maxlifetime" => 86400]);
?>

<?php
if (!isset($_GET["action"])) {
    exit(); 
// Om den inte är satt finns ingenting att göra
}

function 
getTime()
{
    
// php's time är två timmar bakom Sverige så justerar
    
return (time() + 3600);
}

function 
generatePlacements(): string
{
    
$GAMEWIDTH 5// Måste också justeras i play.php
    
$GAMEHEIGHT 5;
    
$SHIPCOUNT 5// En-pixels-skepp

    
$placings = [];
    while (
count($placings) < $SHIPCOUNT) {
        
$x rand(0$GAMEWIDTH 1);
        
$y rand(0$GAMEHEIGHT 1);

        
$coord "$x,$y";

        if (!isset(
$placings[$coord])) {
            
$placings[$coord] = [$x$y];
        }
    }

    
$json json_encode($placings); // Gör om till sträng som sen kan sparas i tabellen och tolkas överallt
    
return ($json);
}

$action $_GET["action"]; // Används för att ta reda på vad som ska göras
$user_id $_SESSION["user_id"];
try {
    include(
"dbconnection.php");
    
/** @var PDO $dbconn */

    // Skapar variabeln $user_id i nästan varje men kan inte göra det utanför för då blir check_username paj

    
if ($action == "CHECKIN") {
        
$sql "UPDATE bs_users SET last_checkin = NOW() WHERE id = ?";
        
$stmt $dbconn->prepare($sql);
        
$data = [$user_id];
        
$stmt->execute($data);
    } else if (
$action == "EXIT_QUE") {
        
$sql "DELETE FROM bs_que WHERE user_id = ?";
        
$stmt $dbconn->prepare($sql);
        
$data = [$user_id];
        
$stmt->execute($data);
    } else if (
$action == "ENTER_QUE") {
        
// Börjar med att plocka bort que-entries där användaren inte checkat in på 12s plus ens egna gamla.
        
$sql 'DELETE FROM bs_que
        WHERE user_id = ? OR last_checkin < (NOW() - INTERVAL 12 SECOND)'
;
        
$stmt $dbconn->prepare($sql);
        
$data = [$user_id];
        
$stmt->execute($data);

        
// Scope bör vara satt men säkerhet
        
if (isset($_GET["scope"])) {
            
$scope $_GET["scope"];
        } else {
            
$scope "ALL";
        }

        if (
$scope == "ALL") {
            
// Alla som söker till "ALL" eller är vän med dig. Plockar bara första posten.
            
$sql 'SELECT * 
            FROM bs_que 
            WHERE scope="ALL" 
                OR EXISTS (
                    SELECT 1
                    FROM bs_relations
                    WHERE bs_relations.id_1 = bs_que.user_id
                        AND bs_relations.id_2 = ?)
            ORDER BY bs_que.id ASC
            LIMIT 1'
;
        } else { 
// $scope == "FRIENDS"
            // Tar bara de där den som söker är vän med en. Plockar bara första posten.
            
$sql 'SELECT * 
            FROM bs_que 
            WHERE EXISTS (
                SELECT 1
                FROM bs_relations
                WHERE bs_relations.id_1 = bs_que.user_id
                    AND bs_relations.id_2 = ?)
            ORDER BY bs_que.id ASC
            LIMIT 1'
;
        }
        
$data = [$user_id];
        
$stmt $dbconn->prepare($sql);
        
$stmt->execute($data);

        
$game $stmt->fetch(PDO::FETCH_ASSOC);

        if (
$game) { // Om en match hittades
            // Tar bort den matchen ur que'n
            
$sql 'DELETE FROM bs_que WHERE id = ?';
            
$stmt $dbconn->prepare($sql);
            
$data = [$game["id"]];
            
$stmt->execute($data);

            
$user_1_placements generatePlacements();
            
$user_2_placements generatePlacements();

            
$user_1_id $_SESSION["user_id"];
            
$user_2_id $game["user_id"];

            
// Slumpar vem som startar
            
if (rand(01) === 0) {
                
$turn $user_1_id;
            } else {
                
$turn $user_2_id;
            }

            
$sql 'INSERT INTO bs_ongoing (user_1_id, user_2_id, user_1_placements, user_2_placements, turn) VALUES (?,?,?,?,?)';
            
$stmt $dbconn->prepare($sql);
            
$data = [$user_1_id$user_2_id$user_1_placements$user_2_placements$turn];
            
$stmt->execute($data);
        } else {
            
// Ställer sig i kön om man inte redan är i en match för säkerhet

            // Udda INSERT-kommando men SELECT plockar fram de värden man vill ha om den inte finns i current_games
            
$sql "
            INSERT INTO bs_que (user_id, scope)
            SELECT ?, ?
            WHERE NOT EXISTS (
                SELECT 1
                FROM bs_ongoing
                WHERE user_1_id = ? OR user_2_id = ?
            )"
;
            
$stmt $dbconn->prepare($sql);
            
$data = [$user_id$scope$user_id$user_id];
            
$stmt->execute($data);
        }
    } else if (
$action == "GET_FRIENDS") {
        
// Tar  fram de som är online (checkat in mindre än en minut sen)
        // Tar även de friend requests man fått.
        
$sql "SELECT * FROM bs_relations JOIN bs_users ON bs_relations.id_2 = bs_users.id WHERE bs_relations.id_1=? AND bs_users.last_checkin > NOW() - INTERVAL 1 MINUTE";
        
$stmt $dbconn->prepare($sql);
        
$data = [$user_id];
        
$stmt->execute($data);
        
$online = [];
        while (
$online_friend $stmt->fetch(PDO::FETCH_ASSOC)) {
            
$online[] = $online_friend["username"];
        }

        
// Tar  fram de som inte är online (checkat in längre än en minut sen)
        
$sql "SELECT * FROM bs_relations JOIN bs_users ON bs_relations.id_2 = bs_users.id WHERE bs_relations.id_1=? AND bs_users.last_checkin <= NOW() - INTERVAL 1 MINUTE";
        
$stmt $dbconn->prepare($sql);
        
$data = [$user_id];
        
$stmt->execute($data);
        
$offline = [];
        while (
$offline_friend $stmt->fetch(PDO::FETCH_ASSOC)) {
            
$offline[] = $offline_friend["username"];
        }

        
// Tar fram de vänförfrågningar man har
        
$sql "SELECT bs_users.id, bs_users.username FROM bs_friend_requests JOIN bs_users ON bs_friend_requests.user_1_id = bs_users.id WHERE bs_friend_requests.user_2_id=?";
        
$stmt $dbconn->prepare($sql);
        
$data = [$user_id];
        
$stmt->execute($data);
        
$pending = [];
        while (
$request $stmt->fetch(PDO::FETCH_ASSOC)) {
            
$pending[] = [$request["id"], $request["username"]];
        }

        
// Vet inte riktigt hur detta fungerar men då kan jag tolka det som en array
        
header('Content-Type: application/json; charset=utf-8');
        echo 
json_encode([
            
"online" => $online,
            
"offline" => $offline,
            
"pending" => $pending
        
]);
    } else if (
$action == "CHECK_USERNAME") {
        
// Kollar om ett användarnamn är upptaget samt städar i tabellen.

        // Tar bort gamla overifierade konton så att de inte tar onödig plats och tar upp användarnamn
        
$sql "DELETE FROM bs_users WHERE verified = 0 AND last_checkin < NOW() - INTERVAL 15 MINUTE";
        
$dbconn->exec($sql);

        
// Kollar om användarnamnet är upptaget
        
$username $_GET["username"]; // Man behöver ha angett ett username
        
$sql "SELECT 1 FROM bs_users WHERE username = ?";
        
$stmt $dbconn->prepare($sql);
        
$data = [$username];
        
$stmt->execute($data);
        if (
$stmt->fetchColumn()) {
            echo (
"taken");
        } else {
            echo (
"free");
        }
    } else if (
$action == "UPDATE_QUE_STATUS") {

        
// Förnyar ens eventuella last_checkin
        
$sql "UPDATE bs_que SET last_checkin = NOW() WHERE user_id = ?";
        
$stmt $dbconn->prepare($sql);
        
$data = [$user_id];
        
$stmt->execute($data);

        
// Kollar om man är i kö, vad man är i för kö och ifall man är i en match
        
$sql "SELECT scope FROM bs_que WHERE user_id = ? LIMIT 1";
        
$stmt $dbconn->prepare($sql);
        
$data = [$user_id];
        
$stmt->execute($data);
        
$row $stmt->fetch(PDO::FETCH_ASSOC);
        if (
$row) {
            
// Om man är i kön så får man sitt scope
            
echo ($row["scope"]);
        } else {
            
$sql "SELECT id FROM bs_ongoing WHERE user_1_id = ? OR user_2_id = ? LIMIT 1";
            
$stmt $dbconn->prepare($sql);
            
$data = [$user_id$user_id];
            
$stmt->execute($data);
            
$row $stmt->fetch(PDO::FETCH_ASSOC);
            if (
$row) {
                
// Om man är i en match
                
echo ($row["id"]);
            }
        }
        
// Om man inte är i varken kön eller en match returneras ingenting.
    
} else if ($action == "SHOOT") {
        
// Gjord av AI men kontrollerad, justerad och kommenterad
        
$game_id $_GET["game_id"];
        
$x $_GET["x"];
        
$y $_GET["y"];
        
$coord "$x,$y"// !!STRÄNG!!

        
$stmt $dbconn->prepare("SELECT * FROM bs_ongoing WHERE id=?");
        
$data = [$game_id];
        
$stmt->execute($data);
        
$game $stmt->fetch(PDO::FETCH_ASSOC);
        if (!
$game) {
            exit;
        } 
// Om den matchen inte finns

        
if ($game["turn"] != $user_id) {
            exit;
        } 
// Om det inte är ens tur (sorterar bort försök att försöka skjuta i andras matcher också)

        // Blockera dubbelskott
        
$stmt $dbconn->prepare("SELECT 1 FROM bs_moves WHERE game_id=? AND target=? AND user_id=?");
        
$data = [$game_id$coord$user_id];
        
$stmt->execute($data);
        if (
$stmt->fetch()) {
            exit;
        }

        
// Hitta fiende och dess placements
        
if ($user_id == $game["user_1_id"]) {
            
$enemy_id $game["user_2_id"];
            
$placements json_decode($game["user_2_placements"], true); // En array (tror jag det heter i php) med coords som keys
        
} else {
            
$enemy_id $game["user_1_id"];
            
$placements json_decode($game["user_1_placements"], true);
        }

        
$hit = isset($placements[$coord]) ? 0;

        
$stmt $dbconn->prepare("INSERT INTO bs_moves (game_id,user_id,target,hit)
        VALUES (?,?,?,?)"
);
        
$data = [$game_id$user_id$coord$hit];
        
$stmt->execute($data);

        
// Kollar om man vunnit
        
$stmt $dbconn->prepare("SELECT COUNT(*) FROM bs_moves 
        WHERE game_id=? AND user_id=? AND hit=1"
); // Kollar hur många träffar man har
        
$data = [$game_id$user_id];
        
$stmt->execute($data);

        if (
$stmt->fetchColumn() >= 5) {
            
$sql "INSERT INTO bs_logs 
            (user_1_id, user_2_id, winner, user_1_placements, user_2_placements, game_id)
            VALUES (?,?,?,?,?,?)"
;
            
$stmt $dbconn->prepare($sql);
            
$data = [
                
$game["user_1_id"],
                
$game["user_2_id"],
                
$user_id,
                
$game["user_1_placements"],
                
$game["user_2_placements"],
                
$game_id
            
];
            
$stmt->execute($data);

            
$sql "DELETE FROM bs_ongoing WHERE id=?";
            
$stmt $dbconn->prepare($sql);
            
$data = [$game_id];
            
$stmt->execute($data);
            
// exit;
        
}

        
// Byt tur
        
$next = ($user_id == $game["user_1_id"])
            ? 
$game["user_2_id"]
            : 
$game["user_1_id"];

        
$stmt $dbconn->prepare("UPDATE bs_ongoing SET turn=? WHERE id=?");
        
$data = [$next$game_id];
        
$stmt->execute($data);
    } else if (
$action == "GET_GAME") {
        
// AI-gjord men kontrollerad, justerad och kommenterad
        
$game_id $_GET["game_id"];

        
$stmt $dbconn->prepare("SELECT * FROM bs_ongoing WHERE id=?");
        
$data = [$game_id];
        
$stmt->execute([$game_id]);
        
$game $stmt->fetch(PDO::FETCH_ASSOC);
        if (!
$game) {
            
$sql "SELECT winner FROM bs_logs WHERE game_id=?";
            
$stmt $dbconn->prepare($sql);
            
$stmt->execute($data); // data nyss satt rätt
            
$row $stmt->fetch(PDO::FETCH_ASSOC); // Borde kanske ha fetchColumn
            
$winner $row $row["winner"] : null;

            
// Om matchen inte finns är den slut
            
echo json_encode([ // Fattar inte riktigt hur json fungerar men smidigt
                
"game_over" => true,
                
"winner" => $winner// Hämtat ur loggen
                
"reason" => "win" // Till skillnad från timeout
            
]);
            exit;
        }

        
// Timeout. Man förlorar om man inte gjort ett drag på 20s
        
$sql "SELECT created FROM bs_moves WHERE game_id=? ORDER BY created DESC LIMIT 1";
        
$stmt $dbconn->prepare($sql);
        
$data = [$game_id];
        
$stmt->execute($data);
        
$last $stmt->fetchColumn(); // Sista draget som gjorts 

        
$sql "SELECT started FROM bs_ongoing WHERE id=?";
        
$stmt $dbconn->prepare($sql);
        
// $data = [$game_id]; // Redan satt
        
$stmt->execute($data);
        
$started $stmt->fetchColumn();

        if ((
$last && strtotime($last) < getTime() - 20) || (!$last && strtotime($started) < getTime() - 30)) {
            
// Om det funnits tidigare drag och det är längre än 20s sen dessa eller om det inte funnits tidigare och mer än 30s från start.

            
$loser $game["turn"];
            
$winner = ($loser == $game["user_1_id"])
                ? 
$game["user_2_id"]
                : 
$game["user_1_id"];

            
$sql "INSERT INTO bs_logs 
            (user_1_id, user_2_id ,winner, user_1_placements, user_2_placements, game_id) 
            VALUES (?,?,?,?,?,?)"
;
            
$stmt $dbconn->prepare($sql);
            
$data = [
                
$game["user_1_id"],
                
$game["user_2_id"],
                
$winner,
                
$game["user_1_placements"],
                
$game["user_2_placements"],
                
$game_id
            
];
            
$stmt->execute($data);

            
$sql "DELETE FROM bs_ongoing WHERE id=?";
            
$stmt $dbconn->prepare($sql);
            
$data = [$game_id];
            
$stmt->execute($data);

            echo 
json_encode([
                
"game_over" => true,
                
"winner" => $winner,
                
"reason" => "timeout",
            ]);
            exit;
        }

        
// Moves
        
$stmt $dbconn->prepare("SELECT * FROM bs_moves WHERE game_id=?");
        
$data = [$game_id];
        
$stmt->execute($data);

        
$moves = [];
        while (
$move $stmt->fetch(PDO::FETCH_ASSOC)) {
            list(
$x$y) = explode(","$move["target"]);
            
$moves[] = [
                
"x" => $x,
                
"y" => $y,
                
"hit" => $move["hit"],
                
"user_id" => $move["user_id"]
            ];
        }

        
header('Content-Type: application/json');

        echo 
json_encode([
            
"turn" => $game["turn"],
            
"moves" => $moves,
            
"user_1_id" => $game["user_1_id"],
            
"user_1_placements" => $game["user_1_placements"],
            
"user_2_placements" => $game["user_2_placements"],
            
"game_over" => false
        
]);
    } else if (
$action == "ANSWER_FRIEND_REQUEST") {
        
$id $_GET["id"]; // id't på användaren som skickade requesten.
        
$answer $_GET["answer"];
        
// $user_id är ens EGNA id.

        // Tar bort requesten (Alla likadana om man har skickat dubletter)
        
$sql "DELETE FROM bs_friend_requests WHERE user_1_id = ? AND user_2_id = ?";
        
$stmt $dbconn->prepare($sql);
        
$data = [$id$user_id];
        
$stmt->execute($data);

        if(
$answer == 1){
        
// Skapar två speglade relationer om man tackar ja och om relationen inte redan finns
        
$sql "INSERT IGNORE INTO bs_relations (id_1, id_2) VALUES (?, ?)";
        
$stmt $dbconn->prepare($sql);
        
$stmt->execute([$user_id$id]);

        
$sql "INSERT IGNORE INTO bs_relations (id_1, id_2) VALUES (?, ?)";
        
$stmt $dbconn->prepare($sql);
        
$stmt->execute([$id$user_id]);
        }

    }
} catch (
PDOException $e) {
    echo(
$e->getMessage());
}
?>