Chapitre 1010 minIntermédiaire
Lire et écrire du code sur papier
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- lire un extrait de code inconnu avec une grille fixe ;
- indiquer clairement une ligne ajoutée, modifiée ou supprimée ;
- écrire une méthode juste en PHP ou en Java, sans ordinateur.
3 exercices corrigés
À l'E7, tu lis et tu écris du code sans ordinateur : pas de compilateur pour signaler une erreur, pas d'autocomplétion, pas de documentation en ligne. Les sujets mélangent les langages (PHP, Java, SQL, parfois C#, JavaScript ou Kotlin) et demandent presque toujours de n'écrire que les lignes modifiées, numérotées. Ce chapitre donne une méthode pour lire un extrait inconnu, les conventions pour indiquer une modification, un comparatif des syntaxes les plus utilisées et les erreurs qui coûtent des points.
Les langages des sujets récents
| Sujet | Langages et outils dans le dossier documentaire |
|---|---|
| 2023, Lama Zoo | PHP avec le framework CodeIgniter, SQL MySQL (déclencheur, transaction, vue) |
| 2024, GSIC | SQL Server (T-SQL, chiffrement de colonne), PHP, application mobile Android |
| 2025, Casterman | Java (classes métier, tests unitaires, journalisation), SQL MySQL (déclencheur, requêtes d'audit), API REST en PHP |
| 2025, Kirassur | PHP (DAO, contrôleur MVC, $_SERVER), SQL MySQL (déclencheur, requête), HTML |
| 2026, NDV | PHP avec PDO, HTML, SQL MySQL (droits, chiffrement AES, vue de journalisation) |
PHP et SQL sont présents chaque année ; Java revient régulièrement pour la programmation objet. Tu n'as pas besoin de maîtriser cinq langages : tu dois savoir lire les structures communes (conditions, boucles, appels de méthodes, requêtes) et écrire correctement dans le langage de l'extrait.
Lire un extrait inconnu
Applique la même grille à chaque extrait, quel que soit le langage.
- Les entrées. D'où viennent les données ? En PHP :
$_GET,$_POST,$_SESSION,$_SERVER,$_COOKIE. En Java : les paramètres de la méthode,request.getParameter(). En Node.js :req.params,req.query,req.body. Tout ce qui vient du client est contrôlé par l'attaquant, y compris les champs cachés et les cookies. - Les sorties. Où vont-elles ? Une requête SQL, un affichage (
echo), un fichier, une réponse HTTP. - Le chemin entre les deux. Une donnée d'entrée arrive-t-elle dans une sortie sans contrôle ? Dans une requête : injection. Dans un affichage : XSS. Dans une décision d'accès : contrôle d'accès à vérifier.
- Les décisions. Chaque
ifqui autorise ou refuse : que vérifie-t-il vraiment, et que ne vérifie-t-il pas ?
Indiquer une modification
Les sujets demandent d'« indiquer seulement le code ajouté et/ou modifié en renseignant les numéros de ligne concernés ». Trois conventions suffisent, à condition d'être claires :
| Cas | Comment l'écrire sur ta copie |
|---|---|
| Ligne modifiée | Ligne 10 (modifiée) : $newpasshash = password_hash($newpass, PASSWORD_ARGON2I); |
| Ligne ajoutée | Après la ligne 13 (ajout, notée 13a) : IF (v_nb > 5) THEN |
| Ligne supprimée | Ligne 7 : supprimée |
Recopie la ligne entière, pas seulement le morceau changé : le correcteur doit pouvoir la lire seule. Si tes ajouts dépassent une dizaine de lignes au même endroit, écris le bloc complet en indiquant « remplace les lignes 12 à 18 ».
Le même geste dans trois langages
| Besoin | PHP | Java | C# |
|---|---|---|---|
| Comparer deux chaînes | $a === $b | a.equals(b) | a == b ou a.Equals(b) |
| Parcourir une collection | foreach ($liste as $elt) | for (Droit d : liste) | foreach (Droit d in liste) |
| Concaténer | $a . $b | a + b | a + b ou $"{a}{b}" |
| Taille d'une liste | count($liste) | liste.size() | liste.Count |
| Requête préparée | $pdo->prepare(…) puis execute([…]) | connexion.prepareStatement(…) puis setString(1, …) | new SqlCommand(…) puis Parameters.AddWithValue(…) |
| Hacher un mot de passe | password_hash($mdp, PASSWORD_DEFAULT) | une bibliothèque (bcrypt, Argon2) | une bibliothèque (bcrypt, Argon2) |
| Lever une erreur | throw new Exception('…'); | throw new IllegalArgumentException("…"); | throw new ArgumentException("…"); |
Utiliser la documentation du sujet
Quand le dossier documentaire décrit une fonction, une classe ou une syntaxe, utilise-la telle qu'elle est décrite, même si elle diffère de ce que tu connais. En 2025, le sujet documentait une fonction datestampdiff(unite, date1, date2) ; la fonction réelle de MySQL s'appelle TIMESTAMPDIFF. La réponse attendue employait le nom du document. De même, en 2026, la documentation des droits MySQL utilisait la fonction PASSWORD(), qui n'existe plus depuis MySQL 8.0.
Les classes techniques suivent la même règle : si le document C2 décrit une classe ArrayList avec les méthodes get(i) et size(), sers-toi de ces méthodes et de rien d'autre. Le sujet te dit ce que tu as le droit d'utiliser.
Un exemple complet : écrire une méthode de contrôle
Énoncé : un Utilisateur possède une liste de Role (getLesRoles()), chaque Role une liste de Permission (getLesPermissions()), et chaque Permission une ressource et une action (getRessource(), getAction()). Écris la méthode boolean autorise(String uneRessource, String uneAction) de la classe Utilisateur.
public boolean autorise(String uneRessource, String uneAction) {
for (Role unRole : this.lesRoles) {
for (Permission unePerm : unRole.getLesPermissions()) {
if (unePerm.getRessource().equals(uneRessource)
&& unePerm.getAction().equals(uneAction)) {
return true; // une permission correspond : on arrête
}
}
}
return false; // aucune permission ne correspond
}
Trois points qui rapportent : la double boucle suit exactement le chemin du diagramme de classes (utilisateur, rôles, permissions) ; la comparaison porte sur la ressource et l'action ; le return false est après les boucles, pas dans un else à l'intérieur, sinon la méthode répondrait dès la première permission examinée.
Si la syntaxe te manque
Mieux vaut un algorithme juste avec une syntaxe approximative qu'une page blanche. Si un détail t'échappe (le nom exact d'une méthode, l'ordre des paramètres), écris ce que tu crois et ajoute un commentaire court qui dit ton intention : // vérifie que le jeton n'est pas expiré. Le correcteur peut accorder une partie des points à une logique correcte. En revanche, un pseudo-code vague (« si l'utilisateur a le droit alors… ») sans lien avec les classes du sujet ne rapporte presque rien.
Exercices
Exercice 1 sur 3 Dérouler une fonction Réussi À revoir
Voici une fonction PHP de vérification de mot de passe :
function verifierMdp(string $mdp): array {
$erreurs = [];
if (strlen($mdp) < 12) { $erreurs[] = 'longueur'; }
if (!preg_match('/[A-Z]/', $mdp)) { $erreurs[] = 'majuscule'; }
if (!preg_match('/[0-9]/', $mdp)) { $erreurs[] = 'chiffre'; }
if (!preg_match('/[^A-Za-z0-9]/', $mdp)) { $erreurs[] = 'special'; }
return $erreurs;
}
Donne le tableau renvoyé pour Soleil2027, correct-horse-battery et Tr0ub4dor&3xyz.
Voir la réponseMasquer la réponse de l'exercice 1
Soleil2027(10 caractères) :['longueur', 'special']. Il contient une majuscule (S) et des chiffres, mais aucun caractère hors lettres et chiffres.correct-horse-battery(21 caractères) :['majuscule', 'chiffre']. Le tiret est un caractère spécial ; il n'y a ni majuscule ni chiffre.Tr0ub4dor&3xyz(14 caractères) :[], tableau vide. Majuscule T, chiffres 0, 4 et 3, caractère spécial &.
Cette règle reprend l'un des exemples de la recommandation de la CNIL de 2022 sur les mots de passe : au moins 12 caractères mêlant majuscules, minuscules, chiffres et caractères spéciaux. Elle ne vérifie pas les minuscules : un mot de passe tout en majuscules passerait.
Tu avais trouvé ?
Exercice 2 sur 3 Écrire une méthode de blocage Réussi À revoir
La classe Compte possède une liste lesTentatives d'objets Tentative, chacun avec getDateHeure() (un LocalDateTime) et estReussie() (un boolean). Écris en Java la méthode boolean estBloque(LocalDateTime maintenant) qui renvoie vrai si le compte compte au moins 5 tentatives échouées dans les 15 dernières minutes. Méthodes utiles : minusMinutes(n) et isAfter(autreDate) de LocalDateTime.
Puis donne le résultat pour un compte dont les tentatives, toutes échouées, ont eu lieu il y a 40, 14, 12, 9, 5 et 2 minutes.
Voir la réponseMasquer la réponse de l'exercice 2
public boolean estBloque(LocalDateTime maintenant) {
LocalDateTime debut = maintenant.minusMinutes(15);
int nbEchecs = 0;
for (Tentative t : this.lesTentatives) {
if (!t.estReussie() && t.getDateHeure().isAfter(debut)) {
nbEchecs++;
}
}
return nbEchecs >= 5;
}
Résultat : vrai. La tentative d'il y a 40 minutes est hors de la fenêtre ; les cinq autres (14, 12, 9, 5 et 2 minutes) sont des échecs dans les 15 dernières minutes, et 5 ≥ 5. Avec des tentatives il y a 16 minutes (échec), 14 (échec), 12 (réussie), 9 et 2 minutes (échecs), le résultat serait faux : seulement 3 échecs dans la fenêtre.
Tu avais trouvé ?
Exercice 3 sur 3 Indiquer des modifications Réussi À revoir
Voici une méthode d'inscription :
1. $login = $_POST['login'];
2. $mdp = $_POST['mdp'];
3. $empreinte = sha1($mdp);
4. $sql = "INSERT INTO compte (login, mdp) VALUES ('$login', '$empreinte')";
5. $pdo->exec($sql);
6. header('Location: connexion.php');
Indique seulement les lignes à modifier ou à ajouter pour utiliser une requête préparée et une empreinte bcrypt.
Voir la réponseMasquer la réponse de l'exercice 3
- Ligne 3 (modifiée) :
$empreinte = password_hash($mdp, PASSWORD_BCRYPT); - Ligne 4 (modifiée) :
$sql = "INSERT INTO compte (login, mdp) VALUES (:login, :mdp)"; - Ligne 5 (modifiée) :
$stmt = $pdo->prepare($sql); - Après la ligne 5 (ajout, 5a) :
$stmt->execute([':login' => $login, ':mdp' => $empreinte]);
Une empreinte bcrypt fait 60 caractères : la colonne mdp doit pouvoir les contenir (VARCHAR(255) est le conseil de la documentation PHP, pour laisser de la marge aux algorithmes futurs).
Tu avais trouvé ?