Compare commits

..

3 Commits

Author SHA1 Message Date
JARNOUEN DE VILLARTAY Ulysse (SAFRAN AIRCRAFT ENGINES) 17a16feb2d ex3 2026-04-15 16:20:11 +02:00
JARNOUEN DE VILLARTAY Ulysse (SAFRAN AIRCRAFT ENGINES) 553b30bdcc tp4 ex2 2026-04-15 16:06:48 +02:00
JARNOUEN DE VILLARTAY Ulysse (SAFRAN AIRCRAFT ENGINES) 74ebab4b24 tp4 ex1 2026-04-15 16:03:11 +02:00
18 changed files with 566 additions and 114 deletions
+4
View File
@@ -0,0 +1,4 @@
CINEMA_DB_HOST=dwarves.iut-fbleau.fr
CINEMA_DB_USER=foo
CINEMA_DB_PASSWORD=foo
CINEMA_DB_NAME=foo
+1
View File
@@ -328,3 +328,4 @@ TSWLatexianTemp*
# Uncomment the next line to have this generated file ignored. # Uncomment the next line to have this generated file ignored.
#*Notes.bib #*Notes.bib
.env
+8
View File
@@ -19,6 +19,14 @@ SET time_zone = "+00:00";
-- -------------------------------------------------------- -- --------------------------------------------------------
CREATE TABLE IF NOT EXISTS `user` (
login VARCHAR(50) NOT NULL,
email VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
PRIMARY KEY (login)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --
-- Table structure for table `Artiste` -- Table structure for table `Artiste`
-- --
@@ -0,0 +1,46 @@
<?php
$login = isset($_GET['login']) ? trim($_GET['login']) : '';
$error = isset($_GET['error']);
$registered = isset($_GET['registered']);
$loggedOut = isset($_GET['logged_out']);
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Authentification</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
/>
</head>
<body>
<main class="container">
<h1>Authentification</h1>
<?php if ($registered) { ?>
<article>Inscription réussie. Vous pouvez maintenant vous connecter.</article>
<?php } ?>
<?php if ($loggedOut) { ?>
<article>Vous avez été déconnecté.</article>
<?php } ?>
<?php if ($error) { ?>
<article aria-invalid="true">Login ou mot de passe incorrect.</article>
<?php } ?>
<form action="./verification.php" method="post">
<label for="login">Login</label>
<input id="login" name="login" value="<?php echo htmlspecialchars($login, ENT_QUOTES); ?>">
<label for="password">Mot de passe</label>
<input id="password" name="password" type="password">
<button type="submit">Se connecter</button>
</form>
<p><a href="./inscription.php">Créer un compte</a></p>
</main>
</body>
</html>
+14
View File
@@ -0,0 +1,14 @@
<?php
session_start();
$_SESSION = array();
if (ini_get('session.use_cookies')) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 3600, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
}
session_destroy();
header('Location: ./authentification.php?logged_out=1');
exit;
+6 -6
View File
@@ -1,14 +1,14 @@
<?php <?php
include './modeles/modeleFilms.php'; include_once './securite.php';
include_once './modeles/modeleFilms.php';
$films = getFilms(); $films = getFilms();
// //
// on "charge" la vue // On charge les fichiers de vue une fois les données prêtes.
// //
include './vues/header.php'; include_once './vues/header.php';
include './vues/vueFilms.php'; include_once './vues/vueFilms.php';
include './vues/footer.php'; include_once './vues/footer.php';
?>
+98
View File
@@ -0,0 +1,98 @@
<?php
session_start();
include_once './modeles/modeleUtilisateurs.php';
$errors = array();
$values = array(
'login' => '',
'email' => '',
);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$values['login'] = isset($_POST['login']) ? trim($_POST['login']) : '';
$values['email'] = isset($_POST['email']) ? trim($_POST['email']) : '';
$password = isset($_POST['password']) ? $_POST['password'] : '';
// On valide champ par champ pour pouvoir réafficher proprement le formulaire.
if ($values['login'] === '') {
$errors['login'] = 'Le login est obligatoire.';
} elseif (!preg_match('/^[a-zA-Z0-9_-]{3,30}$/', $values['login'])) {
$errors['login'] = 'Le login doit contenir entre 3 et 30 caractères alphanumériques, _ ou -.';
}
if ($values['email'] === '') {
$errors['email'] = 'L\'email est obligatoire.';
} elseif (!filter_var($values['email'], FILTER_VALIDATE_EMAIL)) {
$errors['email'] = 'Le format de l\'email est invalide.';
}
if ($password === '') {
$errors['password'] = 'Le mot de passe est obligatoire.';
} elseif (strlen($password) < 8) {
$errors['password'] = 'Le mot de passe doit contenir au moins 8 caractères.';
}
if ($values['login'] !== '' && findUserByLogin($values['login']) !== null) {
$errors['login'] = 'Ce login est déjà utilisé.';
}
if (empty($errors)) {
$passwordHash = password_hash($password, PASSWORD_DEFAULT);
createUser($values['login'], $values['email'], $passwordHash);
header('Location: ./authentification.php?registered=1');
exit;
}
}
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Inscription</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
/>
</head>
<body>
<main class="container">
<h1>Inscription</h1>
<p>Créez un compte avant d'accéder aux pages du site.</p>
<form method="post">
<label for="login">Login</label>
<input
id="login"
name="login"
value="<?php echo htmlspecialchars($values['login'], ENT_QUOTES); ?>"
>
<?php if (isset($errors['login'])) { ?>
<small><?php echo htmlspecialchars($errors['login'], ENT_QUOTES); ?></small>
<?php } ?>
<label for="email">Email</label>
<input
id="email"
name="email"
type="email"
value="<?php echo htmlspecialchars($values['email'], ENT_QUOTES); ?>"
>
<?php if (isset($errors['email'])) { ?>
<small><?php echo htmlspecialchars($errors['email'], ENT_QUOTES); ?></small>
<?php } ?>
<label for="password">Mot de passe</label>
<input id="password" name="password" type="password">
<?php if (isset($errors['password'])) { ?>
<small><?php echo htmlspecialchars($errors['password'], ENT_QUOTES); ?></small>
<?php } ?>
<button type="submit">S'inscrire</button>
</form>
<p><a href="./authentification.php">Déjà inscrit ? Se connecter</a></p>
</main>
</body>
</html>
@@ -0,0 +1,33 @@
<?php
function getConnection()
{
static $conn = null;
if ($conn !== null) {
return $conn;
}
// On autorise deux modes de configuration :
// 1) via des variables d'environnement ;
// 2) en remplaçant directement les valeurs par votre login/mot de passe.
$host = getenv('CINEMA_DB_HOST') ? getenv('CINEMA_DB_HOST') : 'localhost';
$user = getenv('CINEMA_DB_USER') ? getenv('CINEMA_DB_USER') : '';
$password = getenv('CINEMA_DB_PASSWORD') ? getenv('CINEMA_DB_PASSWORD') : '';
$database = getenv('CINEMA_DB_NAME') ? getenv('CINEMA_DB_NAME') : '';
if ($user === '' || $database === '') {
die(
"Configurez d'abord l'accès MySQL dans modeles/connexion.php " .
"ou via les variables d'environnement CINEMA_DB_HOST, CINEMA_DB_USER, CINEMA_DB_PASSWORD et CINEMA_DB_NAME."
);
}
var_dump($host, $user, $password, $database);
$conn = mysqli_connect($host, $user, $password, $database, 3306);
if ($conn === false) {
die('Connexion MySQL impossible : ' . mysqli_connect_error());
}
mysqli_set_charset($conn, 'utf8mb4');
return $conn;
}
+23 -11
View File
@@ -1,16 +1,28 @@
<?php <?php
function _getConnection() include_once __DIR__ . '/connexion.php';
{
static $_conn = NULL;
if ($_conn === NULL){
$_conn = mysqli_connect("localhost","","","");
}
return $_conn;
}
function getFilms() function getFilms()
{ {
// A completer $conn = getConnection();
$sql = "
SELECT Film.idFilm, Film.titre, Film.annee, Genre.code AS genre, Artiste.nom, Artiste.prenom
FROM Film
JOIN Genre ON Genre.code = Film.genre
JOIN Artiste ON Artiste.idArtiste = Film.idMes
ORDER BY Film.titre ASC
";
$result = mysqli_query($conn, $sql);
if ($result === false) {
die('Erreur SQL lors de la récupération des films : ' . mysqli_error($conn));
}
$films = array();
while ($film = mysqli_fetch_assoc($result)) {
$films[] = $film;
}
mysqli_free_result($result);
return $films;
} }
?>
@@ -0,0 +1,53 @@
<?php
include_once __DIR__ . '/connexion.php';
function findUserByLogin($login)
{
$conn = getConnection();
$stmt = mysqli_prepare($conn, 'SELECT login, email, password FROM `user` WHERE login = ?');
if ($stmt === false) {
die('Préparation SQL impossible : ' . mysqli_error($conn));
}
mysqli_stmt_bind_param($stmt, 's', $login);
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt, $dbLogin, $dbEmail, $dbPassword);
$user = null;
if (mysqli_stmt_fetch($stmt)) {
$user = array(
'login' => $dbLogin,
'email' => $dbEmail,
'password' => $dbPassword,
);
}
mysqli_stmt_close($stmt);
return $user;
}
function createUser($login, $email, $passwordHash)
{
$conn = getConnection();
$stmt = mysqli_prepare($conn, 'INSERT INTO `user` (login, email, password) VALUES (?, ?, ?)');
if ($stmt === false) {
die('Préparation SQL impossible : ' . mysqli_error($conn));
}
mysqli_stmt_bind_param($stmt, 'sss', $login, $email, $passwordHash);
$success = mysqli_stmt_execute($stmt);
$errorCode = mysqli_errno($conn);
mysqli_stmt_close($stmt);
// 1062 = violation de clé unique (login déjà pris).
if (!$success && $errorCode === 1062) {
return false;
}
if (!$success) {
die('Insertion SQL impossible : ' . mysqli_error($conn));
}
return true;
}
+11
View File
@@ -0,0 +1,11 @@
<?php
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
// Ce fichier est inclus en tête de chaque page protégée.
// Si l'utilisateur n'est pas connecté, on le renvoie vers le formulaire.
if (!isset($_SESSION['user_login'])) {
header('Location: ./authentification.php');
exit;
}
+35
View File
@@ -0,0 +1,35 @@
<?php
session_start();
include_once './modeles/modeleUtilisateurs.php';
$login = isset($_POST['login']) ? trim($_POST['login']) : '';
$password = isset($_POST['password']) ? $_POST['password'] : '';
// Cette temporisation ralentit volontairement les tentatives répétées,
// ce qui rend les attaques par force brute moins efficaces.
usleep(500000);
if ($login === '' || $password === '') {
header('Location: ./authentification.php?error=1&login=' . urlencode($login));
exit;
}
$user = findUserByLogin($login);
if ($user === null) {
header('Location: ./authentification.php?error=1&login=' . urlencode($login));
exit;
}
if (!password_verify($password, $user['password'])) {
header('Location: ./authentification.php?error=1&login=' . urlencode($login));
exit;
}
session_regenerate_id(true);
$_SESSION['user_login'] = $user['login'];
$_SESSION['user_email'] = $user['email'];
header('Location: ./films.php');
exit;
+10
View File
@@ -12,3 +12,13 @@
</head> </head>
<body> <body>
<main class="container"> <main class="container">
<nav>
<ul>
<li><strong>Cinema</strong></li>
</ul>
<ul>
<li><a href="./films.php">Films</a></li>
<li>Connecté : <?php echo htmlspecialchars(isset($_SESSION['user_login']) ? $_SESSION['user_login'] : 'inconnu', ENT_QUOTES); ?></li>
<li><a href="./deconnexion.php">Déconnexion</a></li>
</ul>
</nav>
+25 -4
View File
@@ -1,6 +1,27 @@
<?php <?php
$osSet = ['linux','apple','windows']; // Les valeurs autorisées servent à la fois pour la validation
$os = "linux"; // du formulaire et pour l'affichage dans la vue.
$osSet = [
'linux' => 'Linux',
'windows' => 'Windows',
'apple' => 'MacOS',
];
include './views/main.php'; $cookieName = 'preferred_os';
?> $os = 'linux';
// Si le formulaire est soumis, on valide la valeur reçue avant
// de l'enregistrer dans un cookie valable 60 secondes.
if (isset($_POST['os']) && array_key_exists($_POST['os'], $osSet)) {
$os = $_POST['os'];
setcookie($cookieName, $os, time() + 60);
// On met aussi $_COOKIE à jour pour refléter immédiatement le choix
// sans attendre le rechargement suivant du navigateur.
$_COOKIE[$cookieName] = $os;
} elseif (isset($_COOKIE[$cookieName]) && array_key_exists($_COOKIE[$cookieName], $osSet)) {
// En l'absence de soumission, on relit la préférence mémorisée.
$os = $_COOKIE[$cookieName];
}
include_once './views/main.php';
+21 -15
View File
@@ -1,43 +1,49 @@
<!doctype html> <!doctype html>
<html> <html lang="fr">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Cookie OS préféré</title>
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
/> />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
</head> </head>
<body> <body>
<main class="container"> <main class="container">
<form method="POST"> <form method="POST">
<fieldset class="grid"> <fieldset class="grid">
<legend>Changez votre os</legend> <legend>Changez votre os</legend>
<?php foreach ($osSet as $value => $label) { ?>
<label> <label>
<input type="radio" name="os" value="linux"> <input
<i class="fa fa-linux fa-2x" aria-hidden="true"></i> type="radio"
</label> name="os"
<label> value="<?php echo htmlspecialchars($value, ENT_QUOTES); ?>"
<input type="radio" name="os" value="windows"> <?php echo $os === $value ? 'checked' : ''; ?>
<i class="fa fa-windows fa-2x" aria-hidden="true"></i> >
</label> <i class="fa fa-<?php echo htmlspecialchars($value, ENT_QUOTES); ?> fa-2x" aria-hidden="true"></i>
<label> <?php echo htmlspecialchars($label, ENT_QUOTES); ?>
<input type="radio" name="os" value="apple">
<i class="fa fa-apple fa-2x" aria-hidden="true"></i>
</label> </label>
<?php } ?>
</fieldset> </fieldset>
<button type="submit">Envoyer</button> <button type="submit">Envoyer</button>
</form> </form>
<article> <article>
<header>Votre os</header> <header>Votre os</header>
<?php echo "<i class='fa fa-$os fa-5x'></i>";?> <p>
<!-- On affiche l'icône et le nom de l'OS courant. -->
<i class="fa fa-<?php echo htmlspecialchars($os, ENT_QUOTES); ?> fa-5x" aria-hidden="true"></i>
</p>
<p><?php echo htmlspecialchars($osSet[$os], ENT_QUOTES); ?></p>
<footer> <footer>
Rafraîchir la page <a href=""><i class="fa fa-refresh" aria-hidden="true"></i></a> Rafraîchir la page
<a href="./" aria-label="Rafraîchir la page">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
</footer> </footer>
</article> </article>
</main> </main>
</body> </body>
</html> </html>
+54 -25
View File
@@ -1,54 +1,83 @@
<?php <?php
function initializeGame()
{
// Une grille vide contient 9 cases valant 0.
$_SESSION['grid'] = array_fill(0, 9, 0);
$_SESSION['playerTurn'] = 1;
}
function nextPlayer($player)
{
return $player === 1 ? 2 : 1;
}
function isWinner($grid, $player) function isWinner($grid, $player)
{ {
$winStates = array $winStates = array(
( array(0, 1, 2), array(3, 4, 5), array(6, 7, 8),
array(0, 1, 2), array(3, 4, 5), array(6, 7, 8), // Horizontal array(0, 3, 6), array(1, 4, 7), array(2, 5, 8),
array(0, 3, 6), array(1, 4, 7), array(2, 5, 8), // Vertical array(0, 4, 8), array(2, 4, 6)
array(0, 4, 8), array(2, 4, 6) // Diagonal
); );
foreach ($winStates as $winState) foreach ($winStates as $winState) {
{ if (
if ($grid[$winState[0]] == $player && $grid[$winState[0]] == $player &&
$grid[$winState[1]] == $player && $grid[$winState[1]] == $player &&
$grid[$winState[2]] == $player) $grid[$winState[2]] == $player
{ ) {
return true; return true;
} }
} }
return false; return false;
} }
function noWinner($grid) function noWinner($grid)
{ {
for($i = 0; $i < 9; $i++) for ($i = 0; $i < 9; $i++) {
if ($grid[$i] == 0) if ($grid[$i] == 0) {
return false; return false;
}
}
return true; return true;
} }
function displayGrid($grid) function getWinner($grid)
{
if (isWinner($grid, 1)) {
return 1;
}
if (isWinner($grid, 2)) {
return 2;
}
return 0;
}
function displayGrid($grid, $isInteractive = true)
{ {
echo '<table class="morpion">'; echo '<table class="morpion">';
for ($i = 0; $i < 3; $i ++){ for ($i = 0; $i < 3; $i++) {
echo "<tr>"; echo '<tr>';
for ($j = 0; $j < 3; $j ++){ for ($j = 0; $j < 3; $j++) {
echo '<td>';
echo "<td>"; $pos = 3 * $i + $j;
if ($grid[$pos] == 0 && $isInteractive) {
$pos = 3*$i + $j;
if ($grid[$pos] == 0)
echo "<a href='?pos=$pos'></a>"; echo "<a href='?pos=$pos'></a>";
if ($grid[$pos] == 1) }
if ($grid[$pos] == 1) {
echo '<i class="fa fa-times" aria-hidden="true"></i>'; echo '<i class="fa fa-times" aria-hidden="true"></i>';
if ($grid[$pos] == 2) }
if ($grid[$pos] == 2) {
echo '<i class="fa fa-circle-o" aria-hidden="true"></i>'; echo '<i class="fa fa-circle-o" aria-hidden="true"></i>';
}
echo "</td>"; echo '</td>';
} }
echo "</tr>"; echo '</tr>';
} }
echo "</table>"; echo '</table>';
} }
+65 -6
View File
@@ -1,11 +1,70 @@
<?php <?php
include 'helpers.php'; session_start();
// view variables include_once 'helpers.php';
$message = "";
$grid = [0,1,0,1,0,2,2,0,0];
$playerTurn = 1; // 1 or 2
// Si on demande une nouvelle partie, on réinitialise l'état stocké
// en session puis on recharge la page sans paramètre.
if (isset($_GET['reset'])) {
initializeGame();
header('Location: .');
exit;
}
include './views/tictactoe.php'; if (!isset($_SESSION['grid']) || !isset($_SESSION['playerTurn'])) {
initializeGame();
}
// Variables transmises à la vue.
$message = '';
$grid = $_SESSION['grid'];
$playerTurn = (int) $_SESSION['playerTurn'];
$winner = getWinner($grid);
$isGameOver = $winner !== 0 || noWinner($grid);
// On joue uniquement si la partie est encore en cours.
if (!$isGameOver && isset($_GET['pos'])) {
$pos = filter_input(
INPUT_GET,
'pos',
FILTER_VALIDATE_INT,
array('options' => array('min_range' => 0, 'max_range' => 8))
);
if ($pos === false || $pos === null) {
$message = 'Coup invalide.';
} elseif ($grid[$pos] !== 0) {
$message = 'Cette case est déjà occupée.';
} else {
// On enregistre le coup du joueur courant dans la grille.
$grid[$pos] = $playerTurn;
if (isWinner($grid, $playerTurn)) {
$message = "Le joueur $playerTurn gagne la partie.";
} elseif (noWinner($grid)) {
$message = 'Match nul.';
} else {
$playerTurn = nextPlayer($playerTurn);
}
$_SESSION['grid'] = $grid;
$_SESSION['playerTurn'] = $playerTurn;
}
$winner = getWinner($grid);
$isGameOver = $winner !== 0 || noWinner($grid);
}
// Si la page est simplement rafraîchie, on recalcule un message cohérent
// à partir de l'état stocké en session.
if ($message === '') {
if ($winner !== 0) {
$message = "Le joueur $winner gagne la partie.";
} elseif (noWinner($grid)) {
$message = 'Match nul.';
}
}
include_once './views/tictactoe.php';
+18 -6
View File
@@ -1,22 +1,34 @@
<html> <!DOCTYPE html>
<html lang="fr">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Tic Tac Toe</title>
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
/> />
<link rel="stylesheet" href="./css/style.css"> <link rel="stylesheet" href="./css/style.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
</head> </head>
<body> <body>
<main class="container center"> <main class="container center">
<h4>Tic Tac Toe : <?php echo "player $playerTurn turn";?></h4> <h4>
<?php if ($isGameOver) { ?>
Partie terminée
<?php } else { ?>
Tic Tac Toe : joueur <?php echo $playerTurn; ?> à vous de jouer
<?php } ?>
</h4>
<?php <?php
displayGrid($grid); // Quand la partie est finie, les liens dans les cases vides
// disparaissent pour empêcher tout coup supplémentaire.
displayGrid($grid, !$isGameOver);
if ($message != "") if ($message != '') {
echo "<h5>$message <a href='.'>new game</a></h5>"; echo '<h5>' . htmlspecialchars($message, ENT_QUOTES) . " <a href='?reset=1'>nouvelle partie</a></h5>";
} else {
echo "<p><a href='?reset=1'>Recommencer la partie</a></p>";
}
?> ?>
</main> </main>
</body> </body>