Polar Code 🎭

Command Palette

Search for a command to run...

05
Pièce N°05

Module 5 : Les Formulaires - Portes d'Entrée

Le bureau était silencieux, mais la porte d'entrée grinçait toujours. Les formulaires, c'étaient ces portes. Des brèches dans le système où les utilisateurs glissaient leurs histoires, leurs demandes, leurs mensonges. En PHP, on les attendait de l'autre côté. Avec GET ou POST. Prêts à récupérer, filtrer, valider. Ou à se faire piéger.

Méthodes GET et POST Deux façons de faire passer l'information. Comme deux types de courriers : l'un visible, l'autre discret.

<!-- formulaire.html -->
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <title>Contact Risqué</title>
</head>
<body style="font-family: 'Courier New', monospace; background: #1a1a1a; color: #ccc;">
    <h2 style="color: #8b0000;">▪ LAISSER UN MESSAGE ▪</h2>
    
    <!-- GET : visible dans l'URL -->
    <form method="GET" action="traitement.php">
        <p><strong>Message public (GET) :</strong></p>
        <input type="text" name="message_public" placeholder="Tout le monde verra ceci..." style="background: #333; color: #ccc; border: 1px solid #555;">
        <button type="submit" style="background: #555; color: #ccc; border: none; padding: 5px 10px;">Envoyer</button>
    </form>
    
    <hr style="border-color: #444;">
    
    <!-- POST : caché dans le corps -->
    <form method="POST" action="traitement.php">
        <p><strong>Message secret (POST) :</strong></p>
        <input type="password" name="message_secret" placeholder="Ceci restera caché..." style="background: #333; color: #ccc; border: 1px solid #555;">
        <br><br>
        <input type="text" name="contact" placeholder="Votre nom de code..." style="background: #333; color: #ccc; border: 1px solid #555;">
        <br><br>
        <button type="submit" style="background: #8b0000; color: #ccc; border: none; padding: 5px 15px;">Transmettre Secrètement</button>
    </form>
</body>
</html>

Récupération des données ($_GET, $_POST) De l'autre côté de la porte. PHP tend la main et récupère ce qui a été glissé.

<?php
// traitement.php
echo "<div style='font-family: monospace; background: #222; color: #ccc; padding: 20px;'>";
echo "<h3 style='color: #8b0000;'>▪ RÉCEPTION DU MESSAGE ▪</h3>";

// Données GET (visibles dans l'URL : traitement.php?message_public=...)
if (!empty($_GET['message_public'])) {
    $messagePublic = $_GET['message_public'];
    echo "<p style='color: #999;'>Message public reçu : <strong>" . htmlspecialchars($messagePublic) . "</strong></p>";
    echo "<p style='font-size: 0.9em; color: #666;'>Visible dans l'URL. Pas discret.</p>";
}

// Données POST (cachées)
if (!empty($_POST['message_secret'])) {
    $messageSecret = $_POST['message_secret'];
    $contact = $_POST['contact'] ?? 'Anonyme'; // ?? = opérateur de coalescence
    
    echo "<hr style='border-color: #444;'>";
    echo "<p style='color: #4caf50;'>Message secret décrypté :</p>";
    echo "<div style='background: #111; padding: 10px; border-left: 3px solid #8b0000;'>";
    echo "De : <strong>" . htmlspecialchars($contact) . "</strong><br>";
    echo "Contenu : <strong>" . htmlspecialchars($messageSecret) . "</strong>";
    echo "</div>";
    echo "<p style='font-size: 0.9em; color: #666;'>Transmission sécurisée. Pas de trace dans l'URL.</p>";
}

// Afficher tout ce qui est arrivé (pour débug, en vrai on ne fait pas ça)
echo "<hr style='border-color: #444;'>";
echo "<details style='color: #777;'>";
echo "<summary>▪ DONNÉES BRUTES (à ne pas montrer en production) ▪</summary>";
echo "<pre>GET : ";
print_r($_GET);
echo "POST : ";
print_r($_POST);
echo "</pre>";
echo "</details>";

echo "</div>";
?>

Validation et sécurisation des données Chaque donnée qui entre est potentiellement une lame. On la désarme. On la vérifie. On la filtre.

<?php
// validation.php
function nettoyerInput($data) {
    $data = trim($data);               // Enlève espaces inutiles
    $data = stripslashes($data);       // Enlève les antislashes
    $data = htmlspecialchars($data);   // Convertit < > & " ' en entités HTML
    return $data;
}

function validerEmail($email) {
    if (empty($email)) {
        return false;
    }
    // Filtre pour email
    $email = filter_var($email, FILTER_SANITIZE_EMAIL);
    return filter_var($email, FILTER_VALIDATE_EMAIL);
}

function validerNombre($nombre, $min = 1, $max = 100) {
    if (!is_numeric($nombre)) {
        return false;
    }
    $nombre = intval($nombre);
    return ($nombre >= $min && $nombre <= $max);
}

// Exemple de traitement sécurisé
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $erreurs = [];
    
    // Nettoyage
    $nom = nettoyerInput($_POST['nom'] ?? '');
    $email = nettoyerInput($_POST['email'] ?? '');
    $quantite = nettoyerInput($_POST['quantite'] ?? '');
    
    // Validation
    if (empty($nom) || strlen($nom) < 2) {
        $erreurs[] = "Le nom doit faire au moins 2 caractères.";
    }
    
    if (!validerEmail($email)) {
        $erreurs[] = "L'email est invalide.";
    }
    
    if (!validerNombre($quantite, 1, 10)) {
        $erreurs[] = "La quantité doit être entre 1 et 10.";
    }
    
    // Si pas d'erreurs
    if (empty($erreurs)) {
        echo "<p style='color: #4caf50;'>▪ TRANSACTION ACCEPTÉE ▪</p>";
        echo "<p>Nom : <strong>$nom</strong></p>";
        echo "<p>Email : <strong>$email</strong></p>";
        echo "<p>Quantité : <strong>$quantite</strong></p>";
        
        // Ici, on pourrait enregistrer en base de données
        // après avoir utilisé des requêtes préparées, bien sûr
    } else {
        echo "<p style='color: #8b0000;'>▪ ERREURS DÉTECTÉES ▪</p>";
        foreach ($erreurs as $erreur) {
            echo "<p>▪ $erreur</p>";
        }
    }
}
?>

Gestion des erreurs utilisateurs Parfois ils se trompent. Parfois ils mentent. Il faut le gérer avec élégance. Sans tout casser.

<?php
// contact.php
session_start();

// Réinitialiser les messages d'erreur/succès
if (!isset($_SESSION['erreurs'])) {
    $_SESSION['erreurs'] = [];
}
if (!isset($_SESSION['succes'])) {
    $_SESSION['succes'] = '';
}

// Traitement du formulaire
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $nom = trim($_POST['nom'] ?? '');
    $message = trim($_POST['message'] ?? '');
    
    // Validation
    $estValide = true;
    
    if (empty($nom)) {
        $_SESSION['erreurs']['nom'] = "Un nom de code est requis.";
        $estValide = false;
    } elseif (strlen($nom) < 3) {
        $_SESSION['erreurs']['nom'] = "Le nom doit faire au moins 3 caractères.";
        $estValide = false;
    }
    
    if (empty($message)) {
        $_SESSION['erreurs']['message'] = "Le message ne peut pas être vide.";
        $estValide = false;
    } elseif (strlen($message) > 500) {
        $_SESSION['erreurs']['message'] = "Le message est trop long (500 caractères max).";
        $estValide = false;
    }
    
    // Si valide
    if ($estValide) {
        $_SESSION['succes'] = "Message transmis. Attendez les instructions.";
        
        // Redirection pour éviter le rechargement du formulaire
        header('Location: ' . $_SERVER['PHP_SELF']);
        exit();
    }
}
?>

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <title>Contact</title>
    <style>
        body { font-family: monospace; background: #111; color: #ccc; padding: 20px; }
        .container { max-width: 500px; margin: auto; background: #222; padding: 20px; border: 1px solid #444; }
        h2 { color: #8b0000; border-bottom: 1px solid #444; padding-bottom: 10px; }
        input, textarea { width: 100%; padding: 8px; margin: 5px 0; background: #333; color: #ccc; border: 1px solid #555; }
        button { background: #8b0000; color: #ccc; border: none; padding: 10px 20px; cursor: pointer; }
        .erreur { color: #ff5555; font-size: 0.9em; margin-top: -5px; margin-bottom: 10px; }
        .succes { color: #55ff55; background: #003300; padding: 10px; margin: 10px 0; border-left: 3px solid #55ff55; }
    </style>
</head>
<body>
    <div class="container">
        <h2>▪ CONTACT URGENT ▪</h2>
        
        <!-- Message de succès -->
        <?php if (!empty($_SESSION['succes'])): ?>
            <div class="succes"><?php echo htmlspecialchars($_SESSION['succes']); unset($_SESSION['succes']); ?></div>
        <?php endif; ?>
        
        <form method="POST" action="">
            <!-- Champ nom -->
            <label>Votre nom de code :</label>
            <input type="text" name="nom" value="<?php echo htmlspecialchars($_POST['nom'] ?? ''); ?>">
            <?php if (isset($_SESSION['erreurs']['nom'])): ?>
                <div class="erreur"><?php echo $_SESSION['erreurs']['nom']; unset($_SESSION['erreurs']['nom']); ?></div>
            <?php endif; ?>
            
            <!-- Champ message -->
            <label>Message :</label>
            <textarea name="message" rows="5"><?php echo htmlspecialchars($_POST['message'] ?? ''); ?></textarea>
            <?php if (isset($_SESSION['erreurs']['message'])): ?>
                <div class="erreur"><?php echo $_SESSION['erreurs']['message']; unset($_SESSION['erreurs']['message']); ?></div>
            <?php endif; ?>
            
            <!-- Bouton -->
            <button type="submit">▪ ENVOYER ▪</button>
        </form>
    </div>
</body>
</html>

<?php
// Nettoyer les erreurs restantes
if (isset($_SESSION['erreurs']) && empty($_SESSION['erreurs'])) {
    unset($_SESSION['erreurs']);
}
?>

Je posai les mains sur le clavier. Les formulaires étaient des portes ouvertes sur le système. GET pour ce qui pouvait être vu. POST pour ce qui devait rester caché. Mais chaque donnée qui entrait était un inconnu. Un étranger qu'il fallait fouiller, vérifier, nettoyer. La validation n'était pas une option. C'était la première ligne de défense. La dernière aussi, parfois.