This commit is contained in:
Yarcio 2025-05-28 21:17:23 +02:00
commit 0356e455e6
21 changed files with 520 additions and 0 deletions

61
index.php Normal file
View file

@ -0,0 +1,61 @@
<?php
include $_SERVER["DOCUMENT_ROOT"] . "/php/pages.php";
?>
<!DOCTYPE html>
<html lang="pl-PL">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Menu - quiz.czem.eu</title>
<link rel="stylesheet" href="/styles/main.css">
<link rel="stylesheet" href="menu.css">
</head>
<body>
<h1>Witaj<i><?php if (isset($_SESSION["username"])) echo " ".$_SESSION["username"];?> </i>na quiz.czem.eu</h1>
<div class="wrap">
<main>
<h2>Wybierz typ quizu</h2>
<article>
<div onclick="window.location.href = '/single/'">
<h3>Jedno Pytanie</h3>
<p>Wyświetl jedno pytanie z bazy quizu oraz natychmiastowo dostań na nie odpowiedź</p>
</div>
<div onclick="window.location.href = '/test/'">
<h3>Test 20 pytań</h3>
<p>Wykonaj test 20 pytań, wynik oraz prawidłowość odpowiedzi pojawi się dopiero po oddaniu, w
trakcie możesz zmieniać odpowiedzi na już rozwiązane pytania</p>
</div>
<div onclick="window.location.href = '/test/?own'">
<h3>Własna długość testu</h3>
<p>Kiedy 20 pytań to za dużo bądź za mało, zmień długość testu zależnie od swoich potrzeb</p>
</div>
</article>
</main>
</div>
<div class="wrap">
<main>
<h2>Inne</h2>
<article>
<div onclick="window.location.href = '/'">
<h3>Twoje wyniki</h3>
</div>
<div onclick="window.location.href = '/'">
<h3>Rankingi</h3>
</div>
<div onclick="window.location.href = '/login/'">
<h3>Wyloguj się</h3>
</div>
<div onclick="window.open('https://czem.eu/', '_blank').focus()">
<h3>Przejdź do czem.eu</h3>
</div>
<div onclick="window.open('https://drive.czem.eu/index.php/s/fraNKJTyi4wN7Nw', '_blank').focus()">
<h3>Kod źródłowy</h3>
</div>
</article>
</main>
</div>
</body>
</html>

37
login/index.php Normal file
View file

@ -0,0 +1,37 @@
<?php
session_start();
session_destroy();
?>
<!DOCTYPE html>
<html lang="pl-PL">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Logowanie - quiz.czem.eu</title>
<link rel="stylesheet" href="/styles/main.css">
<link rel="stylesheet" href="login.css">
<script src="login.js"></script>
</head>
<body>
<h1>Logowanie do quizu o PHP</h1>
<div class="wrap">
<main>
<form id="loginForm">
<h3>Logowanie</h3>
<p>Login:<br><input type="text" name="username" autocomplete="off" required></p>
<p>Hasło:<br><input type="password" name="password" autocomplete="off" id="password" required></p>
<p id="info"></p>
<input type="button" value="Pokaż hasło" id="showPassword">
<input type="submit" value="Zaloguj">
</form>
<h4>Nie masz konta?</h4>
<input type="button" value="Dołącz jako gość" id="guest">
<a href="/login/register/">Zarejestruj się</a>
</main>
</div>
<h1></h1>
</body>
</html>

11
login/login.css Normal file
View file

@ -0,0 +1,11 @@
@import url("/styles/variables.css");
main form {
margin: auto;
width: min-content;
}
main form p {
text-align: left;
}

41
login/login.js Normal file
View file

@ -0,0 +1,41 @@
document.addEventListener('DOMContentLoaded', function () {
const output = document.getElementById("info");
document.getElementById("loginForm").addEventListener('submit', async function (formE) {
formE.preventDefault();
const formData = new FormData(formE.target);
const response = await fetch("login.php", {
method: "POST",
body: formData,
credentials: "include",
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
});
const result = await response.json();
output.innerHTML = result.msg;
output.style.display = "block";
setTimeout(function () { if (result.redirect) window.location.replace(result.redirect); }, 300);
});
document.getElementById("guest").addEventListener("click", async function () {
const formData = new FormData();
formData.append("guest", "true");
const response = await fetch("login.php", {
method: "POST",
body: formData,
credentials: "include",
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
});
const result = await response.json();
output.innerHTML = result.msg;
output.style.display = "block";
setTimeout(function () { if (result.redirect) window.location.replace(result.redirect); }, 300);
});
passwordI = document.getElementById("password");
document.getElementById("showPassword").addEventListener("mousedown", function () { passwordI.type = "text"; });
document.getElementById("showPassword").addEventListener("mouseup", function () { passwordI.type = "password"; });
document.getElementById("showPassword").addEventListener("mouseleave", function () { passwordI.type = "password"; });
});

28
login/login.php Normal file
View file

@ -0,0 +1,28 @@
<?php
include $_SERVER["DOCUMENT_ROOT"] . "/php/scripts.php";
session_start();
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["username"]) && isset($_POST["password"])) {
$conn = connectDB();
$stmt = $conn->prepare("SELECT UID, password FROM users WHERE username = ?");
$username = trim($_POST["username"]);
$password = trim($_POST["password"]);
$stmt->bind_param("s", $username);
$stmt->execute();
$stmt->bind_result($UID, $passwordHash);
if ($stmt->fetch()) {
if (password_verify($password, $passwordHash)) {
$_SESSION["UID"] = $UID;
$_SESSION["username"] = $username;
echo json_encode(["redirect" => "/", "msg" => "Zalogowano jako $username"]);
} else
jsonMsg("Nieprawidłowe hasło");
} else
jsonMsg("Nieprawidłowy login");
$stmt->close();
$conn->close();
} elseif ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["guest"])) {
$_SESSION["UID"] = 0;
echo json_encode(["redirect" => "/", "msg" => "Zalogowano jako gość"]);
} else
jsonMsg("Nieprawidłowy request");

37
login/register/index.php Normal file
View file

@ -0,0 +1,37 @@
<?php
session_start();
session_destroy();
?>
<!DOCTYPE html>
<html lang="pl-PL">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Rejestracja - quiz.czem.eu</title>
<link rel="stylesheet" href="/styles/main.css">
<link rel="stylesheet" href="/login/login.css">
<script src="register.js"></script>
</head>
<body>
<h1>Rejestracja do quizu o PHP</h1>
<div class="wrap">
<main>
<form id="regForm">
<h3>Rejestracja</h3>
<p>Login:<br><input type="text" name="username" autocomplete="off" required></p>
<p>Hasło:<br><input type="password" name="password" autocomplete="off" id="password" required></p>
<p>Potwierdź hasło:<br><input type="password" name="password2" autocomplete="off" id="password2" required></p>
<p id="info"></p>
<input type="button" value="Pokaż hasło" id="showPassword">
<input type="submit" value="Rejestruj">
</form>
<h4>Jednak masz konto?</h4>
<p><a href="/login/">Powróć do strony logowania</a></p>
</main>
</div>
<h1></h1>
</body>
</html>

View file

@ -0,0 +1,45 @@
document.addEventListener("DOMContentLoaded", function () {
document.getElementById("regForm").addEventListener("submit", async function (formE) {
formE.preventDefault();
formData = new FormData(formE.target);
if (formData.get("password") == formData.get("password2")) {
formData.delete("password2");
if (formData.get("username").trim().length < 4) msg("Login użytkownika musi mieć przynajmniej 4 znaki");
else if (formData.get("username").trim().length > 32) msg("Login nie może być dłuższa niż 32 znaki");
else if (formData.get("password").trim().length < 4) msg("Hasło musi mieć przynajmniej 4 znaki");
else if (formData.get("password").trim().length > 32) msg("Hasło nie może być dłuże niż 32 znaki");
else {
const response = await fetch("register.php", {
method: "POST",
body: formData,
credentials: "include",
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
});
const result = await response.json();
msg(result.msg);
setTimeout(function () { if (result.redirect) window.location.replace(result.redirect); }, 300);
}
} else msg("Hasła nie są identyczne");
});
passwordI = document.getElementById("password");
passwordI2 = document.getElementById("password2");
document.getElementById("showPassword").addEventListener("mousedown", function () {
passwordI.type = "text";
passwordI2.type = "text";
});
document.getElementById("showPassword").addEventListener("mouseup", function () {
passwordI.type = "password";
passwordI2.type = "password";
});
document.getElementById("showPassword").addEventListener("mouseleave", function () {
passwordI.type = "password";
passwordI2.type = "password";
});
});
function msg(msg) {
const output = document.getElementById("info");
output.innerHTML = msg;
output.style.display = "block";
}

View file

@ -0,0 +1,32 @@
<?php
include $_SERVER["DOCUMENT_ROOT"] . "/php/scripts.php";
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["username"]) && isset($_POST["password"])) {
$username = trim($_POST["username"]);
$password = trim($_POST["password"]);
if (strlen($username) < 4)
jsonMsg("Login użytkownika musi mieć przynajmniej 4 znaki");
elseif (strlen($username) > 32)
jsonMsg("Login nie może być dłuższa niż 32 znaki");
elseif (strlen($password) < 4)
jsonMsg("Hasło musi mieć przynajmniej 4 znaki");
elseif (strlen($password) > 32)
jsonMsg("Hasło nie może być dłuże niż 32 znaki");
else {
$conn = connectDB();
$stmt = $conn->prepare("SELECT 1 FROM users where username = ? LIMIT 1");
$stmt->bind_param("s", $username);
$stmt->execute();
if ($stmt->fetch())
jsonMsg("Użytkownik o takim loginie już istnieje");
else {
$password = password_hash($password, PASSWORD_ARGON2I);
$stmt = $conn->prepare("INSERT INTO users (username, password) VALUES (?, ?)");
$stmt->bind_param("ss", $username, $password);
if ($stmt->execute()) echo json_encode(["redirect" => "/login/", "msg" => "Utworzono użytkownika $username"]);
else jsonMsg("Nie udało się utworzyć użytkownika");
}
$stmt->close();
$conn->close();
}
} else
jsonMsg("Nieprawidłowy request");

1
main.sql Normal file
View file

@ -0,0 +1 @@
create table users (UID int PRIMARY KEY AUTO_INCREMENT, username TEXT UNIQUE NOT NULL, password TEXT NOT NULL);

31
menu.css Normal file
View file

@ -0,0 +1,31 @@
@import url("/styles/variables.css");
main {
min-width: 200px;
max-width: 90%;
}
main article {
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
}
main article div {
margin: 30px;
padding: 20px 35px;
width: 250px;
background-color: var(--color-alt);
border: 1px solid var(--border-basic);
border-radius: 20px;
transition: 0.2s;
user-select: none;
}
main article div:hover {
background-color: var(--color-alt-hover);
}
main article div:active {
background-color: var(--color-alt-active);
}
main article div h3 {
margin-bottom: 30px;
}

19
php/functions.php Normal file
View file

@ -0,0 +1,19 @@
<?php
const sqlHostname = "localhost";
const sqlUsername = "root";
const sqlPassword = "";
const sqlDatabase = "quizPHP";
function connectDB() {
$conn = new mysqli(sqlHostname, sqlUsername, sqlPassword, sqlDatabase);
if ($conn->connect_error)
exit("Błąd połączenia: " . $conn->connect_error);
return $conn;
}
function jsonMsg($messsage) {
echo json_encode(["msg" => $messsage]);
}
function checkLogin() {
session_start();
if (isset($_SESSION["UID"])) return true;
return false;
}

6
php/pages.php Normal file
View file

@ -0,0 +1,6 @@
<?php
include $_SERVER["DOCUMENT_ROOT"] . "/php/functions.php";
if (!checkLogin()) {
header("Location: /login/");
exit();
}

6
php/scripts.php Normal file
View file

@ -0,0 +1,6 @@
<?php
include $_SERVER["DOCUMENT_ROOT"] . "/php/functions.php";
if (!isset($_SERVER["HTTP_X_REQUESTED_WITH"]) || strtolower($_SERVER["HTTP_X_REQUESTED_WITH"]) != "xmlhttprequest") {
http_response_code(403);
exit('Odmowa dostępu');
}

25
single/index.php Normal file
View file

@ -0,0 +1,25 @@
<?php
include $_SERVER["DOCUMENT_ROOT"] . "/php/pages.php";
?>
<!DOCTYPE html>
<html lang="pl-PL">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pytanie - quiz.czem.eu</title>
<link rel="stylesheet" href="/styles/main.css">
<link rel="stylesheet" href="/styles/quiz.css">
</head>
<body>
<h1>Pojedyńcze pytanie - quiz PHP</h1>
<div class="wrap">
<main>
</main>
</div>
<h1></h1>
</body>
</html>

37
styles/main.css Normal file
View file

@ -0,0 +1,37 @@
@import url("/styles/variables.css");
h1 {
margin-left: 10px;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
display: flex;
flex-direction: column;
min-height: 100vh;
}
main {
border: solid 1px var(--border-basic);
text-align: center;
padding: 20px;
}
div.wrap {
display: flex;
flex: 1;
align-items: center;
justify-content: center;
margin: 10px;
}
main form p#info {
text-align: center;
display: none;
color: red;
font-size: smaller;
}

5
styles/quiz.css Normal file
View file

@ -0,0 +1,5 @@
@import url("/styles/variables.css");
main form p span.bigger {
font-size: larger;
}

7
styles/variables.css Normal file
View file

@ -0,0 +1,7 @@
:root {
--test: 1px;
--border-basic: black;
--color-alt: rgb(200, 228, 253);
--color-alt-hover: rgb(152, 205, 252);
--color-alt-active: rgb(63, 166, 255);
}

22
template.html Normal file
View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="pl-PL">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>quiz.czem.eu</title>
<link rel="stylesheet" href="/styles/main.css">
<link rel="stylesheet" href=".css">
</head>
<body>
<h1>q</h1>
<div class="wrap">
<main>
</main>
</div>
<h1></h1>
</body>
</html>

43
test/index.php Normal file
View file

@ -0,0 +1,43 @@
<?php
include $_SERVER["DOCUMENT_ROOT"] . "/php/pages.php";
?>
<!DOCTYPE html>
<html lang="pl-PL">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test - quiz.czem.eu</title>
<link rel="stylesheet" href="/styles/main.css">
<link rel="stylesheet" href="/styles/quiz.css">
<script src="test.js"></script>
</head>
<body>
<h1>Rozpocznij test - quiz PHP</h1>
<div class="wrap">
<main id="content">
<form id="startForm">
<?php
if (isset($_GET["own"]))
echo "<p><span class='bigger'>Długość testu:</span><br><input type='number' name='testLength' value='20' min='2' max='99'>pytań</p>";
else
echo "<input type='hidden' name='testLength' value='20'>";
?>
<p><input type="submit" value="Rozpocznij test"></p>
<?php
if (!isset($_SESSION["username"]))
echo "<p id='info' style='display: block;'>Nie jesteś zalogowany,<br>więc żaden postęp nie zostanie zapisany!</p>";
else
echo "<p id='info'></p>"
?>
</form>
<h4>Jednak nie chcesz zacząć?</h4>
<p><a href="/">Powrót do strony głównej</a></p>
</main>
</div>
<h1></h1>
</body>
</html>

16
test/test.js Normal file
View file

@ -0,0 +1,16 @@
document.addEventListener("DOMContentLoaded", function () {
document.getElementById("startForm").addEventListener("submit", async function (formE) {
formE.preventDefault();
formData = new FormData(formE.target);
const response = await fetch("test.php", {
method: "POST",
body: formData,
credentials: "include",
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
});
const result = await response.json();
document.getElementById("content").innerHTML = result.msg;
});
});

10
test/test.php Normal file
View file

@ -0,0 +1,10 @@
<?php
include $_SERVER["DOCUMENT_ROOT"] . "/php/scripts.php";
if (!checkLogin()) {
jsonMsg("Nie jesteś zalogowany");
exit();
}
if ($_SERVER['REQUEST_METHOD'] == "POST" && isset($_POST["testLength"])) {
jsonMsg("GENERATE TEST");
} else
jsonMsg("Nieprawidłowy request");