Grosses mises à jour de shipmembers.php et adminstration.php pour revoir le process d'invitation sur un bateau mais aussi les sécurités de base sur les fichiers index.php et les fonctions_html.php

This commit is contained in:
2026-10-05 13:48:45 +00:00
parent 7146bce248
commit b7cb39bbe6
10 changed files with 2752 additions and 2511 deletions
+9 -8
View File
@@ -1,12 +1,13 @@
<?php <?php
require_once("fonctions_bdd.php"); // Contient les fonctions d'accès aux BDD. require_once(__DIR__.'/fonctions_acces.php'); // Contient les fonctions d'accès au site
require_once("fonctions_fichiers.php"); // Contient les fonctions de traitement des répertoires et des fichiers require_once(__DIR__.'/fonctions_bdd.php'); // Contient les fonctions d'accès aux BDD.
require_once("fonctions_ftp.php"); require_once(__DIR__.'/fonctions_fichiers.php'); // Contient les fonctions de traitement des répertoires et des fichiers
require_once("fonctions_html.php"); require_once(__DIR__.'/fonctions_ftp.php');
require_once("fonctions_mail.php"); // Contient les fonctions d'émission des emails require_once(__DIR__.'/fonctions_html.php');
require_once("fonctions_pdf.php"); // Contient les fonctions de création de fichiers PDF require_once(__DIR__.'/fonctions_mail.php'); // Contient les fonctions d'émission des emails
require_once("fonctions_traductions.php"); require_once(__DIR__.'/fonctions_pdf.php'); // Contient les fonctions de création de fichiers PDF
require_once("fonctions_utilitaires.php"); require_once(__DIR__.'/fonctions_traductions.php');
require_once(__DIR__.'/fonctions_utilitaires.php');
+324
View File
@@ -0,0 +1,324 @@
<?php
//************************************************************************************************************
// fonctions_acces.php - Accès des ShipMembers aux bateaux et invitations (synthèse §47)
//
// Regroupe ce qui était recopié dans shipmembers.php (5 blocs d'activation de code, 7 requêtes "accès actifs")
// et administration.php (1 + 1). Modèle de TB_Lien_bateau_shipmember :
// - Statut : 'en_attente' (invitation non acceptée), 'actif', 'suspendu', 'revoque' ;
// - une invitation désigne une adresse e-mail (Email_invite) : seul un compte ShipMember ACTIVÉ ayant cette
// adresse peut l'accepter (l'activation prouve le contrôle de la boîte - un compte non activé ne le prouve pas) ;
// - Expiration_invitation : date limite pour accepter ; Fin_validite : fin de l'accès accordé.
//
// Toutes les fonctions utilisent la connexion courante ($_SESSION['db'], ouverte par Ouverture_bdd()).
//************************************************************************************************************
// Alphabet des codes d'invitation : majuscules et chiffres SANS les caractères ambigus à la lecture (0/O, 1/I/L) -
// 31 symboles. 8 caractères présentés en deux groupes (ex : K7QX-M3PW), soit 31^8 = 8,5.10^11 combinaisons.
const CODE_INVITATION_ALPHABET = "23456789ABCDEFGHJKMNPQRSTUVWXYZ";
const CODE_INVITATION_LONGUEUR = 8;
// Durée de validité par défaut d'une invitation (jours), si TB_Configuration.Duree_validite_invitation n'est pas
// chargée en session :
const DUREE_VALIDITE_INVITATION_DEFAUT = 30;
//************************************************************************************************************
// Fonction : Nombre de lignes réellement modifiées par la DERNIÈRE requête exécutée sur la connexion courante.
// NB : mysqli_affected_rows() ne convient pas après Requete_preparee_bdd(), qui appelle
// mysqli_stmt_get_result() même pour un UPDATE - ce qui remet le compteur côté PHP à -1 (constaté en
// test). ROW_COUNT() interroge directement le serveur. À appeler IMMÉDIATEMENT après la requête.
// Reçoit : Rien
// Retour : Le nombre de lignes modifiées
//************************************************************************************************************
function Nb_lignes_modifiees()
{
$reponse = Requete_bdd("SELECT ROW_COUNT() AS nb", __FILE__, __LINE__);
$donnees = Recherche_ligne_bdd($reponse, MYSQLI_ASSOC);
Liberation_jeu_de_resultat_bdd($reponse);
return (int)$donnees['nb'];
}
//************************************************************************************************************
// Fonction : Liste des accès ACTIFS d'un ShipMember (statut 'actif' et Fin_validite non dépassée).
// Reçoit : La clé primaire du ShipMember
// Retour : Un tableau de lignes ['ID_Bateau', 'ID_Type_acces_bateau_shipmember'] (vide si aucun accès)
//************************************************************************************************************
function Acces_actifs_shipmember($id_shipmember)
{
$acces = [];
$requete = "SELECT ID_Bateau, ID_Type_acces_bateau_shipmember FROM TB_Lien_bateau_shipmember
WHERE ID_Shipmember=? AND Statut='actif' AND Fin_validite >= NOW()";
$reponse = Requete_preparee_bdd($requete, array(array('i', $id_shipmember)), __FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse, MYSQLI_ASSOC)) $acces[] = $donnees;
Liberation_jeu_de_resultat_bdd($reponse);
return $acces;
}
//************************************************************************************************************
// Fonction : Indique si le compte d'un ShipMember est activé, c'est-à-dire si son titulaire a prouvé qu'il
// contrôle l'adresse e-mail (connexion avec le mot de passe provisoire reçu, puis choix d'un mot de
// passe : la ligne TB_Activation est alors supprimée).
// Reçoit : La clé primaire du ShipMember
// Retour : true si activé
//************************************************************************************************************
function Compte_est_active($id_shipmember)
{
$reponse = Requete_preparee_bdd("SELECT COUNT(*) AS nb FROM TB_Activation WHERE ID_SHIPMEMBERS=?",
array(array('i', $id_shipmember)), __FILE__, __LINE__);
$donnees = Recherche_ligne_bdd($reponse, MYSQLI_ASSOC);
Liberation_jeu_de_resultat_bdd($reponse);
return ($donnees['nb'] == 0);
}
//************************************************************************************************************
// Fonction : Normalise un code d'invitation saisi ou reçu (majuscules, espaces et tirets retirés, puis tiret
// remis au milieu) et vérifie son format.
// Reçoit : La valeur brute (GET, POST, saisie manuelle...)
// Retour : Le code normalisé (ex : "K7QX-M3PW"), ou false si le format est invalide
//************************************************************************************************************
function Normaliser_code_invitation($valeur)
{
if (!is_string($valeur)) return false; // écarte ?code_acces[]=... (tableau)
$brut = strtoupper(preg_replace('/[\s-]/', '', $valeur));
$moitie = intdiv(CODE_INVITATION_LONGUEUR, 2);
if (preg_match('/^['.CODE_INVITATION_ALPHABET.']{'.CODE_INVITATION_LONGUEUR.'}\z/', $brut) !== 1) return false;
return substr($brut, 0, $moitie).'-'.substr($brut, $moitie);
}
//************************************************************************************************************
// Fonction : Génère un code d'invitation unique (générateur aléatoire cryptographique random_int).
// Reçoit : Rien
// Retour : Le code (ex : "K7QX-M3PW")
//************************************************************************************************************
function Generer_code_invitation()
{
$max = strlen(CODE_INVITATION_ALPHABET) - 1;
do
{
$brut = "";
for ($i = 0; $i < CODE_INVITATION_LONGUEUR; $i++) $brut .= CODE_INVITATION_ALPHABET[random_int(0, $max)];
$code = Normaliser_code_invitation($brut);
$reponse = Requete_preparee_bdd("SELECT COUNT(*) AS nb FROM TB_Lien_bateau_shipmember WHERE Code=?",
array(array('s', $code)), __FILE__, __LINE__);
$donnees = Recherche_ligne_bdd($reponse, MYSQLI_ASSOC);
Liberation_jeu_de_resultat_bdd($reponse);
}
while ($donnees['nb'] != 0);
return $code;
}
//************************************************************************************************************
// Fonction : Crée une invitation nominative (statut 'en_attente').
// Reçoit : Le bateau, l'adresse e-mail du destinataire (obligatoire), son prénom et son nom (facultatifs, pour
// l'affichage), le type d'accès, la fin de l'accès accordé (format 'Y-m-d', vide = sans limite) et le
// ShipMember qui invite.
// Retour : ['ok'=>true, 'id'=>int, 'code'=>string] ou ['ok'=>false, 'raison'=>string]
// NB : les droits de celui qui invite sont vérifiés par la page appelante.
//************************************************************************************************************
function Creer_invitation($id_bateau, $email, $prenom, $nom, $id_type_acces, $fin_acces, $id_cree_par)
{
$email = strtolower(trim((string)$email));
if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) return ['ok' => false, 'raison' => t("Adresse e-mail invalide.")];
$prenom = trim((string)$prenom);
$nom = trim((string)$nom);
$prenom = ($prenom === '') ? null : mb_substr($prenom, 0, 50);
$nom = ($nom === '') ? null : mb_substr($nom, 0, 50);
// Type d'accès : doit exister et être valide (l'ancien type "Administrateur" est dévalidé) :
$reponse = Requete_preparee_bdd("SELECT COUNT(*) AS nb FROM TB_Types_acces_bateau_shipmember WHERE Cle_primaire=? AND Validite=1",
array(array('i', $id_type_acces)), __FILE__, __LINE__);
$donnees = Recherche_ligne_bdd($reponse, MYSQLI_ASSOC);
Liberation_jeu_de_resultat_bdd($reponse);
if ($donnees['nb'] == 0) return ['ok' => false, 'raison' => t("Type d'accès invalide.")];
// Fin de l'accès accordé : date du jour en fin de journée, ou sans limite :
if ($fin_acces === null || trim($fin_acces) === '') $fin_validite = '9999-12-31 23:59:59';
else
{
$date = date_create_from_format('Y-m-d', trim($fin_acces));
if ($date === false) return ['ok' => false, 'raison' => t("Date de fin d'accès invalide.")];
$fin_validite = $date->format('Y-m-d').' 23:59:59';
}
$duree = isset($_SESSION['Config__Duree_validite_invitation']) ? (int)$_SESSION['Config__Duree_validite_invitation'] : DUREE_VALIDITE_INVITATION_DEFAUT;
if ($duree <= 0) $duree = DUREE_VALIDITE_INVITATION_DEFAUT;
$code = Generer_code_invitation();
$requete = "INSERT INTO TB_Lien_bateau_shipmember
(Statut, ID_Shipmember, ID_Bateau, Email_invite, Prenom_invite, Nom_invite, Code, Expiration_invitation,
Fin_validite, Cree_par, ID_Type_acces_bateau_shipmember)
VALUES ('en_attente', 0, ?, ?, ?, ?, ?, DATE_ADD(NOW(), INTERVAL ? DAY), ?, ?, ?)";
Requete_preparee_bdd($requete, array(
array('i', $id_bateau), array('s', $email), array('s', $prenom), array('s', $nom),
array('s', $code), array('i', $duree), array('s', $fin_validite),
array('i', $id_cree_par), array('i', $id_type_acces)),
__FILE__, __LINE__);
return ['ok' => true, 'id' => Recuperation_id_cree_bdd(), 'code' => $code];
}
//************************************************************************************************************
// Fonction : Informations sur une invitation à partir de son code (bandeau d'accueil d'un lien d'invitation).
// Reçoit : Le code (brut ou normalisé)
// Retour : Un tableau (ID, Statut, Email_invite, Prenom_invite, Nom_invite, Nom_bateau, Type_acces,
// Expiree [0/1]) ou null si le code est inconnu ou mal formé
//************************************************************************************************************
function Invitation_par_code($code)
{
$code = Normaliser_code_invitation($code);
if ($code === false) return null;
$colonne_type = (isset($_SESSION['langue']) && $_SESSION['langue'] == 'EN') ? 'Nom_en' : 'Nom_fr';
$requete = "SELECT L.ID, L.Statut, L.Email_invite, L.Prenom_invite, L.Nom_invite, B.Nom AS Nom_bateau,
T.".$colonne_type." AS Type_acces,
(L.Expiration_invitation IS NOT NULL AND L.Expiration_invitation <= NOW()) AS Expiree
FROM TB_Lien_bateau_shipmember L
JOIN TB_Bateaux B ON B.Cle_primaire = L.ID_Bateau
LEFT JOIN TB_Types_acces_bateau_shipmember T ON T.Cle_primaire = L.ID_Type_acces_bateau_shipmember
WHERE L.Code=?";
$reponse = Requete_preparee_bdd($requete, array(array('s', $code)), __FILE__, __LINE__);
$donnees = Recherche_ligne_bdd($reponse, MYSQLI_ASSOC);
Liberation_jeu_de_resultat_bdd($reponse);
return $donnees ?: null;
}
//************************************************************************************************************
// Fonction : Invitations en attente (non expirées) adressées à une adresse e-mail.
// Reçoit : L'adresse e-mail du ShipMember connecté
// Retour : Un tableau de lignes (ID, Nom_bateau, Type_acces, Expiration_invitation, Prenom_invitant, Nom_invitant)
//************************************************************************************************************
function Invitations_en_attente($email)
{
$invitations = [];
$colonne_type = (isset($_SESSION['langue']) && $_SESSION['langue'] == 'EN') ? 'Nom_en' : 'Nom_fr';
$requete = "SELECT L.ID, B.Nom AS Nom_bateau, T.".$colonne_type." AS Type_acces, L.Expiration_invitation,
S.Prenom AS Prenom_invitant, S.Nom AS Nom_invitant
FROM TB_Lien_bateau_shipmember L
JOIN TB_Bateaux B ON B.Cle_primaire = L.ID_Bateau
LEFT JOIN TB_Types_acces_bateau_shipmember T ON T.Cle_primaire = L.ID_Type_acces_bateau_shipmember
LEFT JOIN TB_Shipmembers S ON S.ID = L.Cree_par
WHERE L.Statut='en_attente' AND L.Email_invite=?
AND (L.Expiration_invitation IS NULL OR L.Expiration_invitation > NOW())
ORDER BY L.Date_creation";
$reponse = Requete_preparee_bdd($requete, array(array('s', strtolower(trim((string)$email)))), __FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse, MYSQLI_ASSOC)) $invitations[] = $donnees;
Liberation_jeu_de_resultat_bdd($reponse);
return $invitations;
}
//************************************************************************************************************
// Fonction : Accepte une invitation pour le ShipMember connecté.
// Toutes les conditions (en attente, adresse identique, non expirée) sont vérifiées DANS la requête de
// mise à jour elle-même : une invitation ne peut donc être acceptée qu'une fois, même par deux
// requêtes simultanées.
// Reçoit : L'ID de l'invitation, la clé primaire et l'adresse e-mail du ShipMember connecté
// Retour : ['ok'=>true] ou ['ok'=>false, 'raison'=>string]
//************************************************************************************************************
function Accepter_invitation($id_lien, $id_shipmember, $email)
{
if (!Compte_est_active($id_shipmember))
{
return ['ok' => false, 'raison' => t("Votre compte doit être activé (mot de passe provisoire reçu par e-mail) avant de pouvoir accepter une invitation.")];
}
$requete = "UPDATE TB_Lien_bateau_shipmember
SET Statut='actif', ID_Shipmember=?, Date_activation=NOW()
WHERE ID=? AND Statut='en_attente' AND Email_invite=?
AND (Expiration_invitation IS NULL OR Expiration_invitation > NOW())";
Requete_preparee_bdd($requete, array(
array('i', $id_shipmember), array('i', $id_lien), array('s', strtolower(trim((string)$email)))),
__FILE__, __LINE__);
if (Nb_lignes_modifiees() == 1) return ['ok' => true];
return ['ok' => false, 'raison' => t("Cette invitation n'est plus valable (déjà utilisée, expirée, révoquée, ou adressée à une autre adresse).")];
}
//************************************************************************************************************
// Fonction : Refuse une invitation (elle passe à 'revoque').
// Reçoit : L'ID de l'invitation et l'adresse e-mail du ShipMember connecté
// Retour : true si l'invitation a bien été refusée
//************************************************************************************************************
function Refuser_invitation($id_lien, $email)
{
$requete = "UPDATE TB_Lien_bateau_shipmember SET Statut='revoque'
WHERE ID=? AND Statut='en_attente' AND Email_invite=?";
Requete_preparee_bdd($requete, array(array('i', $id_lien), array('s', strtolower(trim((string)$email)))), __FILE__, __LINE__);
return (Nb_lignes_modifiees() == 1);
}
//************************************************************************************************************
// Fonction : Masque partiellement une adresse e-mail pour l'afficher à quelqu'un qui n'est pas encore connecté
// (ex : "pierre.durand@exemple.fr" -> "p•••@exemple.fr").
// Reçoit : L'adresse
// Retour : L'adresse masquée
//************************************************************************************************************
function Masquer_email($email)
{
$position = strpos((string)$email, '@');
if ($position === false || $position == 0) return "•••";
return mb_substr($email, 0, 1).'•••'.substr($email, $position);
}
//************************************************************************************************************
// Clé du type d'accès "Propriétaire" dans TB_Types_acces_bateau_shipmember (cf Devalidation_profils = 1 : tous
// les types SAUF Propriétaire).
//************************************************************************************************************
const TYPE_ACCES_PROPRIETAIRE = 2;
//************************************************************************************************************
// Fonction : Charge un accès (ou une invitation) À CONDITION qu'il appartienne au bateau indiqué - toute action
// sur un accès passe par là, pour qu'un identifiant envoyé par le navigateur ne puisse jamais viser
// l'accès d'un autre bateau.
// Reçoit : L'ID de l'accès et la clé primaire du bateau affiché
// Retour : La ligne (ID, Statut, Code, ID_Type_acces_bateau_shipmember, Expiration_invitation) ou null
//************************************************************************************************************
function Lien_du_bateau($id_lien, $id_bateau)
{
$requete = "SELECT ID, Statut, Code, ID_Type_acces_bateau_shipmember, Expiration_invitation
FROM TB_Lien_bateau_shipmember WHERE ID=? AND ID_Bateau=?";
$reponse = Requete_preparee_bdd($requete, array(array('i', $id_lien), array('i', $id_bateau)), __FILE__, __LINE__);
$donnees = Recherche_ligne_bdd($reponse, MYSQLI_ASSOC);
Liberation_jeu_de_resultat_bdd($reponse);
return $donnees ?: null;
}
//************************************************************************************************************
// Fonction : Indique si l'utilisateur peut suspendre, réactiver ou révoquer un accès d'un type donné.
// Administrateur : toujours. Devalidation_profils = 2 : tous les types. = 1 : tous sauf Propriétaire.
// Reçoit : Les droits de l'utilisateur sur le bateau ($acces_profil), s'il est administrateur, le type visé
// Retour : true si autorisé
//************************************************************************************************************
function Peut_devalider_acces($acces_profil, $est_administrateur, $id_type_cible)
{
if ($est_administrateur) return true;
$niveau = isset($acces_profil['Devalidation_profils']) ? (int)$acces_profil['Devalidation_profils'] : 0;
if ($niveau >= 2) return true;
if ($niveau == 1) return ((int)$id_type_cible != TYPE_ACCES_PROPRIETAIRE);
return false;
}
//************************************************************************************************************
// Fonction : Met à jour en session la liste des accès actifs du ShipMember connecté ($_SESSION['bateau_shipmember']
// et $_SESSION['acces']), à partir de la base - la liste est REMPLACÉE (l'ancien code y ajoutait des
// lignes sans la vider : des accès révoqués pouvaient y rester jusqu'à la déconnexion).
// Reçoit : La clé primaire du ShipMember
// Retour : Rien
//************************************************************************************************************
function Rafraichir_acces_session($id_shipmember)
{
$_SESSION['bateau_shipmember'] = Acces_actifs_shipmember($id_shipmember);
$_SESSION['acces'] = count($_SESSION['bateau_shipmember']);
}
+53 -1
View File
@@ -12,6 +12,7 @@ function Init_session($nom_page)
ini_set('arg_separator.output', '&amp;'); ini_set('arg_separator.output', '&amp;');
ini_set("url_rewriter.tags","a=href,area=href,frame=src,iframe=src,input=src"); // Ces deux lignes sont destinées à faire ajouter autoamtiquement &amp; au lieu de '&' dans la passage des variables de Session (nécessaire pour W3C validator...) ini_set("url_rewriter.tags","a=href,area=href,frame=src,iframe=src,input=src"); // Ces deux lignes sont destinées à faire ajouter autoamtiquement &amp; au lieu de '&' dans la passage des variables de Session (nécessaire pour W3C validator...)
// Cookie de session : sans attribut domain (cookie réservé exactement au site), SameSite=Lax (synthèse §47) :
session_set_cookie_params([ session_set_cookie_params([
'lifetime' => 3600, 'lifetime' => 3600,
'path' => '/', 'path' => '/',
@@ -22,6 +23,53 @@ function Init_session($nom_page)
session_start(); // Ouverture de session (avant tout autre envoi au client!!!) session_start(); // Ouverture de session (avant tout autre envoi au client!!!)
Initialiser_session();
}
//************************************************************************************************************
// Fonction : Initialise une session neuve, UNE fois : valeurs par défaut, paramètres de TB_Configuration, langues,
// textes. Auparavant fait uniquement par index.php : une page ouverte directement (lien d'invitation
// scanné sur un téléphone, favori...) utilisait des variables inexistantes (synthèse §47).
// Reçoit : Rien
// Retour : Rien
//************************************************************************************************************
function Initialiser_session()
{
if (isset($_SESSION['session_initialisee'])) return;
$_SESSION['acces_valide'] = false;
$_SESSION['display_menu'] = false;
$_SESSION['langue'] = 'FR'; // Valeur par défaut, remplacée par Langue_par_defaut de TB_Configuration
$_SESSION['shipmember'] = array('Cle_primaire' => 0, 'Prenom' => "", 'Nom' => "", 'Entreprise' => "", 'Rue' => "",
'Code_postal' => "", 'Ville' => "", 'ID_Pays' => 75, 'Telephone' => "", 'Email' => "",
'Commentaires' => "", 'Niveau_acces' => 0);
$_SESSION['droits_acces'] = 0;
$_SESSION['bateau_shipmember'] = array();
$_SESSION['acces'] = 0;
$_SESSION['modifier_texte'] = 0;
Ouverture_bdd();
// Paramètres de configuration générale :
$reponse = Requete_bdd('SELECT Nom, Valeur FROM TB_Configuration WHERE Validite=1', __FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse))
{
if ($donnees['Nom'] == "Langue_par_defaut") $_SESSION['langue'] = $donnees['Valeur'];
else $_SESSION['Config__'.$donnees['Nom']] = $donnees['Valeur'];
}
Liberation_jeu_de_resultat_bdd($reponse);
// ID des langues selon leur préfixe :
$reponse = Requete_bdd('SELECT ID, Prefix FROM TB_Langues', __FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse)) $_SESSION['id_langue'][$donnees['Prefix']] = $donnees['ID'];
Liberation_jeu_de_resultat_bdd($reponse);
Fermeture_bdd();
chargement_langue(); // Textes de la langue en cours
$_SESSION['session_initialisee'] = true;
} }
@@ -39,7 +87,11 @@ function Entete_page_html()
{ {
// Vérification à chaque ouverture de page que les variables de session sont bien initialisées (le test se fait sur quelques "échantillons" supposés représentatifs...) : // Vérification à chaque ouverture de page que les variables de session sont bien initialisées (le test se fait sur quelques "échantillons" supposés représentatifs...) :
if ((!isset($_SESSION['langue'])) OR if ((!isset($_SESSION['langue'])) OR
(!isset($_SESSION['display_menu']))) header('Location:index.php?origine='.basename($_SERVER['SCRIPT_FILENAME'])); (!isset($_SESSION['display_menu'])))
{
header('Location:index.php?origine='.basename($_SERVER['SCRIPT_FILENAME']));
exit();
}
// Entête HTML : // Entête HTML :
echo '<!DOCTYPE html>'; echo '<!DOCTYPE html>';
+91 -99
View File
@@ -251,92 +251,9 @@ class MYPDF2 extends TCPDF {
//******************************************************************************************************************************** //********************************************************************************************************************************
// Fonction : Génère le document PDF à partir des données reçues en paramètres // Fonction : URL d'activation d'un code d'invitation, portée par le QR code ET par le lien cliquable du PDF d'invitation.
// Reçoit : type du document (1er code généré pour le bateau, code généré par un autre utilisateur)
// client concerné a qui on envoie le pdf et le code d'accès pour générer le code QR.
// Retour : 0 si Ok, -1 si erreur
//********************************************************************************************************************************
function code_acces_pdf($code, $no, $no_serie = "XX:XX:XX:XX:XX:XX", $client = "")
{
$nom_piece = $no."_Code_acces_bateau_".$no_serie;
$pdf = new MYPDF2('LANDSCAPE', 'px', 'A4', true, 'UTF-8', false);
// set document (meta) information :
$pdf->SetCreator(PDF_CREATOR);
$pdf->SetAuthor('Koriolan');
$pdf->SetTitle($nom_piece);
$pdf->SetSubject('ShipHeart');
$pdf->SetKeywords('ShipHeart by Koriolan');
$pdf->SetTextColor(0, 69, 99);
$pdf->SetFont('helvetica', '', 10);
$pdf->AddPage();
$pdf->SetDrawColor(217,217,217);
$pdf->Line(421, 0, 421, 595);
// First page
$pdf->Image('images/logo_shipheart.png', 506, 214, 252, 167, 'PNG', 'https://shipheart.tech');
// Firth page
$pdf->Image('images/logo_shipheart.png', 12, 12, 64, 45, 'PNG', 'https://shipheart.tech');
$pdf->CreateTextBox("Nous vous remercions pour votre confiance et sommes ravis de vous offrir un accès complet aux informations de votre bateau via notre platforme Ship2net.
We thank you for your trust and are delighted to offer you full access to your boat information via our Ship2net platform.", 52, 166, 317, 195, 12);
$pdf->CreateTextBox($no_serie, 0, 520, 421, 46, 12, '', 'C', 0);
// $pdf->AddPage();
$pdf->SetDrawColor(217,217,217);
$pdf->Line(421, 0, 421, 595);
// Second page
$pdf->Image('images/logo_shipheart.png', 12, 12, 64, 45, 'PNG', 'https://shipheart.tech');
$pdf->Image('images/logo_shipheart.png', 766, 12, 64, 45, 'PNG', 'https://shipheart.tech');
$pdf->CreateTextBox("Pour activer votre accès au bateau merci de scanner le QR code ci-joint et de vous connecter à votre profil ShipMember existant ou d'en créer un.
To activate your boat access please scan the attached QR code and log in to your existing ShipMember profile or create one.", 52, 218, 317, 160, 12);
// Third page
$pdf->Image(generateCode($code), 546, 216, 164, 164, 'PNG', Url_activation_code_acces($code));
// ---------------------------------------------------------
// Fermeture de l'objet PDF et enreigistrement du fichier :
ob_clean(); // Semble nécessaire ; sinon erreur du 'output' suivant
$pdf_string = $pdf->Output('pseudo.pdf', 'S'); // export du flux dans une chaine (le nom du fichier est ignoré...)
// Copie de cette chaine dans le fichier final (cette solution en 2 temps permet d'éviter de devoir utiliser un nom de fichier absolu (semble obligatoire avec Output et l'option 'F')
file_put_contents('temp/PDF/'.$nom_piece.'.pdf', $pdf_string);
$_SESSION['pdf']['src'] = 'temp/PDF/'.$nom_piece.'.pdf';
// Sauvegarder le pdf automatiquement
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=".$nom_piece.".pdf");
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: binary");
// Read the file
readfile($_SESSION['pdf']['src']);
// Suppression du pdf et codeqr du serveur
unlink('temp/CodeQR/'.$code.'.png');
unlink($_SESSION['pdf']['src']);
return(0);
}
//********************************************************************************************************************************
// Fonction : URL d'activation d'un code d'accès bateau, portée par le QR code ET par le lien cliquable du PDF d'invitation.
// Construite à partir de URL_SITE (definitions.php) : plus d'adresse écrite en dur (synthèse §47). // Construite à partir de URL_SITE (definitions.php) : plus d'adresse écrite en dur (synthèse §47).
// Reçoit : le code d'accès // Reçoit : le code d'invitation
// Retour : l'URL complète // Retour : l'URL complète
//******************************************************************************************************************************** //********************************************************************************************************************************
function Url_activation_code_acces($code) function Url_activation_code_acces($code)
@@ -344,21 +261,96 @@ function Url_activation_code_acces($code)
return 'https://'.URL_SITE.'/shipmembers.php?code_acces='.urlencode($code); return 'https://'.URL_SITE.'/shipmembers.php?code_acces='.urlencode($code);
} }
function generateCode($code){
$tempDir = "temp/CodeQR/";
$codeContents = Url_activation_code_acces($code); //********************************************************************************************************************************
// Fonction : Image PNG d'un QR code, produite EN MÉMOIRE (aucun fichier temporaire : l'ancienne version écrivait le QR code
$fileName = $code.'.png'; // et le PDF dans html/temp/, donc dans la partie publique du site - synthèse §47).
// Reçoit : le texte à encoder
$pngAbsoluteFilePath = $tempDir.$fileName; // Retour : le contenu binaire de l'image PNG
$urlRelativeFilePath = $tempDir.$fileName; //********************************************************************************************************************************
function Qr_code_png($texte)
// generating {
if (!file_exists($pngAbsoluteFilePath)) { ob_start();
QRcode::png($codeContents, $pngAbsoluteFilePath); QRcode::png($texte, false, QR_ECLEVEL_M, 8, 2); // false = sortie standard, capturée par le tampon
} $png = ob_get_clean();
return $urlRelativeFilePath; header_remove('Content-Type'); // phpqrcode a posé un en-tête image/png : retiré, le PDF posera le sien
return $png;
} }
//********************************************************************************************************************************
// Fonction : Génère et ENVOIE au navigateur le PDF d'une invitation nominative à accéder à un bateau (synthèse §47).
// La page appelante doit s'arrêter juste après (exit) : rien ne doit suivre le PDF.
// Reçoit : l'invitation (tableau) : Code, Nom_bateau, Email_invite, Prenom_invite, Nom_invite, Type_acces,
// Expiration_invitation
// Retour : rien (le PDF est envoyé en téléchargement)
//********************************************************************************************************************************
function code_acces_pdf($invitation)
{
$code = $invitation['Code'];
$nom_bateau = $invitation['Nom_bateau'];
$email = $invitation['Email_invite'];
$destinataire = trim(($invitation['Prenom_invite'] ?? '').' '.($invitation['Nom_invite'] ?? ''));
$type_acces = $invitation['Type_acces'] ?? '';
$expiration = ($invitation['Expiration_invitation'] != NULL) ? date_format(date_create($invitation['Expiration_invitation']), 'd/m/Y') : '';
$nom_fichier = 'Invitation_'.preg_replace('/[^A-Za-z0-9_-]/', '_', $nom_bateau).'_'.$code.'.pdf';
$pdf = new MYPDF2('LANDSCAPE', 'px', 'A4', true, 'UTF-8', false);
// set document (meta) information :
$pdf->SetCreator(PDF_CREATOR);
$pdf->SetAuthor('Koriolan');
$pdf->SetTitle('Invitation - '.$nom_bateau);
$pdf->SetSubject('ShipHeart');
$pdf->SetKeywords('ShipHeart by Koriolan');
$pdf->SetTextColor(0, 69, 99);
$pdf->SetFont('helvetica', '', 10);
$pdf->SetAutoPageBreak(false); // Mise en page fixe sur 2 feuilles : pas de saut de page automatique (l'ancienne version
// obtenait sa 2e feuille par un saut automatique, déclenché par le texte du bas de la 1re)
//---------------------------------------------------------
// Feuille 1 (pliée en deux : à droite la couverture, à gauche le mot d'accueil) :
$pdf->AddPage();
$pdf->SetDrawColor(217,217,217);
$pdf->Line(421, 0, 421, 595);
$pdf->Image('images/logo_shipheart.png', 506, 214, 252, 167, 'PNG', 'https://shipheart.tech'); // Couverture
$pdf->Image('images/logo_shipheart.png', 12, 12, 64, 45, 'PNG', 'https://shipheart.tech');
$salutation = ($destinataire != '') ? $destinataire.",\n\n" : '';
$pdf->CreateTextBox($salutation."Nous vous remercions pour votre confiance et sommes ravis de vous offrir un accès aux informations du bateau ".$nom_bateau." via notre plateforme Ship2net.\n\n"
."We thank you for your trust and are delighted to offer you access to the information of the boat ".$nom_bateau." via our Ship2net platform.",
52, 150, 317, 230, 12, '', 'L');
$pdf->CreateTextBox($nom_bateau.(($type_acces != '') ? ' - '.$type_acces : ''), 0, 520, 421, 46, 12, 'B', 'C');
//---------------------------------------------------------
// Feuille 2 (à gauche le mode d'emploi, à droite le QR code et le code) :
$pdf->AddPage();
$pdf->SetDrawColor(217,217,217);
$pdf->Line(421, 0, 421, 595);
$pdf->Image('images/logo_shipheart.png', 12, 12, 64, 45, 'PNG', 'https://shipheart.tech');
$pdf->Image('images/logo_shipheart.png', 766, 12, 64, 45, 'PNG', 'https://shipheart.tech');
$pdf->CreateTextBox("Cette invitation est réservée à l'adresse ".$email.".\n"
."Pour l'activer, scannez le QR code ci-contre, puis connectez-vous à votre compte ShipMember avec cette adresse (ou créez votre compte avec cette adresse).\n"
."Sans appareil photo : rendez-vous sur ".URL_SITE." et connectez-vous avec cette adresse ; l'invitation apparaîtra dans « Mes invitations ».\n"
.(($expiration != '') ? "Invitation valable jusqu'au ".$expiration.".\n" : '')
."\n"
."This invitation is reserved for the address ".$email.".\n"
."To activate it, scan the QR code opposite, then log in to your ShipMember account with this address (or create your account with this address).\n"
."Without a camera: go to ".URL_SITE." and log in with this address; the invitation will appear in \"My invitations\".\n"
.(($expiration != '') ? "Invitation valid until ".$expiration."." : ''),
52, 110, 317, 400, 11, '', 'L');
$pdf->Image('@'.Qr_code_png(Url_activation_code_acces($code)), 546, 196, 164, 164, 'PNG', Url_activation_code_acces($code));
$pdf->CreateTextBox($code, 506, 372, 244, 30, 18, 'B', 'C');
$pdf->CreateTextBox(URL_SITE, 506, 400, 244, 20, 11, '', 'C');
//---------------------------------------------------------
// Envoi direct au navigateur, sans fichier intermédiaire. Tout ce qui aurait déjà été mis en tampon (espaces,
// avertissements...) est jeté : un seul octet parasite avant le PDF le corromprait.
while (ob_get_level() > 0) ob_end_clean();
$pdf->Output($nom_fichier, 'D');
}
+2 -30
View File
@@ -162,7 +162,7 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
// Récupération des informations sur le ou les bateaux accessibles à ce ShipMember : // Récupération des informations sur le ou les bateaux accessibles à ce ShipMember :
$nb_bateaux = 0; $nb_bateaux = 0;
$requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE ID_SHIPMEMBER=? '; $requete = "SELECT * FROM TB_Lien_bateau_shipmember WHERE ID_SHIPMEMBER=? AND Statut IN ('actif','suspendu')"; // Hors invitations et accès révoqués (synthèse §47)
$reponse = Requete_preparee_bdd($requete, $reponse = Requete_preparee_bdd($requete,
array( array(
array('i', $_SESSION['Administration']['id_shipmember'])), array('i', $_SESSION['Administration']['id_shipmember'])),
@@ -187,36 +187,8 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
} }
Liberation_jeu_de_resultat_bdd($reponse); Liberation_jeu_de_resultat_bdd($reponse);
} }
// Créer le lien bateau shipmember, affecter l'enregitrement a cet utilisateur
if (isset($_SESSION['code_acces']) && $_SESSION['code_acces']!=''){
$code = $_SESSION['code_acces'];
$requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND Code=? AND ID_Shipmember=0';
$reponse = Requete_preparee_bdd($requete, array(array('s', $code)), __FILE__, __LINE__);
$donnees = Recherche_ligne_bdd($reponse);
// Vérifier si le code est tjrs valable
if ($donnees == NULL){
$message_erreur .= "Code invalide ou déjà utilisé \n";
$_SESSION['code_acces'] = '';
}
else {
$sous_req = 'UPDATE TB_Lien_bateau_shipmember SET ID_Shipmember=? WHERE Validite=1 AND Code=? AND ID_Shipmember=0';
$sous_rep = Requete_preparee_bdd($sous_req, array(array('i', $_SESSION['shipmember']['Cle_primaire']), array('s', $code)), __FILE__, __LINE__);
$_SESSION['code_acces'] = '';
// $_SESSION['droits_acces'] = $donnees['Niveau_acces'];
}
}
// Récupération des liaisons shipmember - bateau Rafraichir_acces_session($_SESSION['shipmember']['Cle_primaire']); // Accès actifs (synthèse §47)
$current_timestamp = date_format(date_create(), 'Y-m-d H:i:s');
$requete = 'SELECT ID_Bateau, ID_Type_acces_bateau_shipmember FROM TB_Lien_bateau_shipmember WHERE ID_Shipmember='.$_SESSION['shipmember']['Cle_primaire'].' AND Validite=1 AND Validite_acces=1 AND Fin_validite>="'.$current_timestamp.'"';
$reponse = Requete_bdd($requete, __FILE__, __LINE__);
$nb_acces = 0;
// $bateau_shipmember = []
while ($donnees = Recherche_ligne_bdd($reponse)) {
$_SESSION['bateau_shipmember'][$nb_acces++] = $donnees;
}
$_SESSION['acces'] = $nb_acces;
// $_SESSION['acces_valide'] = true; // $_SESSION['acces_valide'] = true;
break; break;
+252 -188
View File
@@ -11,6 +11,11 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
$message_erreur = ""; $message_erreur = "";
$message_information = ""; $message_information = "";
// Messages transmis par une redirection (motif POST -> redirection -> GET, après une action sur les accès : un
// rafraîchissement de la page ne rejoue jamais l'action) :
if (isset($_SESSION['Bateaux']['flash_information'])) { $message_information .= $_SESSION['Bateaux']['flash_information']; unset($_SESSION['Bateaux']['flash_information']); }
if (isset($_SESSION['Bateaux']['flash_erreur'])) { $message_erreur .= $_SESSION['Bateaux']['flash_erreur']; unset($_SESSION['Bateaux']['flash_erreur']); }
Ouverture_bdd(); // Connexion à MySql Ouverture_bdd(); // Connexion à MySql
@@ -224,43 +229,9 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Modifier la validité des droits // NB : les actions sur les accès et invitations (création, suspension, réactivation, révocation, modification, PDF)
if (isset($_POST['validite_acces'])) { // sont traitées plus bas, dans la page Details_bateau, APRÈS le calcul des droits de l'utilisateur sur le bateau
// echo 'Validité = ON pour ID='.$_POST['ID'].'<br />'; // (elles étaient auparavant exécutées ici, avant tout contrôle - synthèse §47).
$requete = 'UPDATE TB_Lien_bateau_shipmember SET Validite_acces = 1 WHERE ID = '.$_POST['ID'];
$reponse = Requete_bdd($requete, __FILE__, __LINE__);
}
else if (!isset($_POST['validite_acces']) && isset($_POST['ID']) && !isset($_POST['supprimerAcces']) && !isset($_POST['modifierAcces'])){
// echo 'Validité = OFF pour ID='.$_POST['ID'].'<br />';
$requete = 'UPDATE TB_Lien_bateau_shipmember SET Validite_acces = 0 WHERE ID = '.$_POST['ID'];
$reponse = Requete_bdd($requete, __FILE__, __LINE__);
}
//---------------------------------------------------------------------------
// Supprimer l'accès
if (isset($_POST['supprimerAcces']) && isset($_POST['ID'])){
$id = $_POST['ID'];
$requete = 'UPDATE TB_Lien_bateau_shipmember SET Validite = 0 WHERE ID = ? ';
$reponse = Requete_preparee_bdd($requete,
array(
array('i', $id)),
__FILE__, __LINE__);
}
//---------------------------------------------------------------------------
// Modifier l'accès
if (isset($_POST['modifierAcces']) && isset($_POST['ID'])){
$id = $_POST['ID'];
$fin_validite = $_POST['fin_validite']." 23:59:59";
$type_profil = $_POST['type_profil'];
$requete = 'UPDATE TB_Lien_bateau_shipmember SET Fin_validite = ? , ID_Type_acces_bateau_shipmember = ? WHERE ID = ? ';
$reponse = Requete_preparee_bdd($requete,
array(
array('s', $fin_validite),
array('i', $type_profil),
array('i', $id)),
__FILE__, __LINE__);
}
@@ -283,7 +254,7 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
// Recherche des droits d'accès à un bateau en particulier : // Recherche des droits d'accès à un bateau en particulier :
if ($_SESSION['Bateaux']['page'] == "Details_bateau") if ($_SESSION['Bateaux']['page'] == "Details_bateau")
{ {
$requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND Validite_acces=1 AND ID_SHIPMEMBER=? AND ID_BATEAU=? '; $requete = "SELECT * FROM TB_Lien_bateau_shipmember WHERE Statut='actif' AND Fin_validite >= NOW() AND ID_SHIPMEMBER=? AND ID_BATEAU=? ";
$reponse = Requete_preparee_bdd($requete, $reponse = Requete_preparee_bdd($requete,
array( array(
array('i', $_SESSION['shipmember']['Cle_primaire']), array('i', $_SESSION['shipmember']['Cle_primaire']),
@@ -299,7 +270,13 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
} }
} while (0); } while (0);
if ($flag_sortie) header('Location:shipmembers.php?action=navigation&destination=Login'); if ($flag_sortie)
{
// exit indispensable : sans lui, le reste de la page (actions comprises) s'exécutait malgré la redirection (synthèse §47)
Fermeture_bdd();
header('Location:shipmembers.php?action=navigation&destination=Login');
exit();
}
switch ($_SESSION['Bateaux']['page']) switch ($_SESSION['Bateaux']['page'])
@@ -406,7 +383,9 @@ $requete .= ' TB_Bateaux.Date_derniere_maj AS Date_derniere_maj, ';
$acces_profil['Modification_acces'] = 0; $acces_profil['Modification_acces'] = 0;
// Recherche de l'ID de l'accès le plus élevé pour ce bateau et ce shipmember : // Recherche de l'ID de l'accès le plus élevé pour ce bateau et ce shipmember :
$requete = 'SELECT ID_Type_acces_bateau_shipmember FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND Validite_acces=1 AND ID_Shipmember=? AND ID_Bateau=? AND Fin_validite>=? ORDER BY ID_Type_acces_bateau_shipmember DESC LIMIT 1'; // NB : "ORDER BY ... ASC" - plus la clé du type est petite, plus il donne de droits (2 Propriétaire, 3 Installateur,
// 4 Skipper). L'ancien "DESC" retenait l'accès le plus FAIBLE quand un SM en avait plusieurs (synthèse §47).
$requete = "SELECT ID_Type_acces_bateau_shipmember FROM TB_Lien_bateau_shipmember WHERE Statut='actif' AND ID_Shipmember=? AND ID_Bateau=? AND Fin_validite>=? ORDER BY ID_Type_acces_bateau_shipmember ASC LIMIT 1";
$reponse = Requete_preparee_bdd($requete, $reponse = Requete_preparee_bdd($requete,
array( array(
array('i', $_SESSION['shipmember']['Cle_primaire']), array('i', $_SESSION['shipmember']['Cle_primaire']),
@@ -434,11 +413,11 @@ $requete .= ' TB_Bateaux.Date_derniere_maj AS Date_derniere_maj, ';
} }
Liberation_jeu_de_resultat_bdd($reponse); Liberation_jeu_de_resultat_bdd($reponse);
} }
$acces_profil['Modification_acces'] = 0; // Modification d'un accès (type, fin) : réservée aux administrateurs
} }
// Récupération des types d'accès possibles : // Récupération des types d'accès possibles :
//$requete = 'SELECT Nom, Niveau_acces FROM TB_Lien_bateau_shipmember_acces WHERE Validite = 1 AND Niveau_acces < 99';
$requete = 'SELECT * FROM TB_Types_acces_bateau_shipmember WHERE Validite=1 '; $requete = 'SELECT * FROM TB_Types_acces_bateau_shipmember WHERE Validite=1 ';
$reponse = Requete_bdd($requete, __FILE__, __LINE__); $reponse = Requete_bdd($requete, __FILE__, __LINE__);
$type_acces_nb = 0; $type_acces_nb = 0;
@@ -451,44 +430,97 @@ $requete .= ' TB_Bateaux.Date_derniere_maj AS Date_derniere_maj, ';
Liberation_jeu_de_resultat_bdd($reponse); Liberation_jeu_de_resultat_bdd($reponse);
// Génération d'un nouveau code d'acces : //------------------------------------------------------------------------------------------------------------
if (isset($_POST['generer_code_acces'])){ // Actions sur les accès et invitations de CE bateau (synthèse §47). Traitées ici, APRÈS le calcul des droits :
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; // - chaque action vérifie que l'accès visé appartient bien au bateau affiché ;
$charactersLength = strlen($characters); // - créer une invitation, télécharger son PDF : administrateur, ou Creation_profils = 1 ;
$unique = false; // - suspendre, réactiver, révoquer : administrateur, ou Devalidation_profils = 2 (tous types), ou = 1 (tous
do { // Vérifier si le code n'est pas déjà utilisé // sauf Propriétaire) ; une invitation en attente peut aussi être révoquée par qui peut en créer ;
$code_acces = ''; // - modifier le type ou la fin d'un accès : administrateur.
for ($i = 0; $i < 6; $i++) { // Après chaque action : redirection vers la page (motif POST -> redirection -> GET).
$code_acces .= $characters[random_int(0, $charactersLength - 1)]; //------------------------------------------------------------------------------------------------------------
} $est_administrateur = ($_SESSION['shipmember']['Niveau_acces'] >= NIVEAU_ACCES_MINI_ADMINISTRATEUR);
$req = 'SELECT Code FROM TB_Lien_bateau_shipmember WHERE Code="'.$code_acces.'"'; $peut_inviter = ($est_administrateur || $acces_profil['Creation_profils'] == 1);
$rep = Requete_bdd($req, __FILE__, __LINE__);
$donnees = Recherche_ligne_bdd($rep);
if ($donnees == NULL) $unique = true;
} while($unique == false);
if (isset($_POST['date_validite']) && (!empty($_POST['date_validite']))){ if (isset($_POST['creer_invitation']))
$date = $_POST['date_validite']." 00:00:00"; {
if (!$peut_inviter) $_SESSION['Bateaux']['flash_erreur'] = t("Vous n'avez pas le droit d'inviter sur ce bateau.");
else
{
$resultat = Creer_invitation($bateau['Cle_primaire'], $_POST['email_invite'] ?? '', $_POST['prenom_invite'] ?? '',
$_POST['nom_invite'] ?? '', (int)($_POST['type_acces'] ?? 0), $_POST['fin_acces'] ?? '',
$_SESSION['shipmember']['Cle_primaire']);
if ($resultat['ok']) $_SESSION['Bateaux']['flash_information'] = str_replace("[[Code]]", $resultat['code'],
t("Invitation créée (code [[Code]]). Téléchargez son PDF dans la liste ci-dessous."));
else $_SESSION['Bateaux']['flash_erreur'] = $resultat['raison'];
} }
else $date = '9999-12-31 23:59:59'; Fermeture_bdd();
$requete = 'INSERT INTO TB_Lien_bateau_shipmember(ID_Bateau, Code, Fin_validite, Cree_par, ID_Type_acces_bateau_shipmember) VALUES (?,?,?,?,?)'; header('Location: bateaux.php');
$reponse = Requete_preparee_bdd($requete, array( exit();
array('i', $bateau['Cle_primaire']), }
array('s', $code_acces),
array('s', $date),
array('i', $_SESSION['shipmember']['Cle_primaire']),
array('i', $_POST['type_acces'])
),__FILE__, __LINE__);
$no = Recuperation_id_cree_bdd();
if ( code_acces_pdf($code_acces, $no, $bateau['Adresse_mac'],"")== 0 ) Entete_page_html(); if (isset($_POST['action_acces']) && isset($_POST['ID']))
{
$lien = Lien_du_bateau((int)$_POST['ID'], $bateau['Cle_primaire']);
$action = (string)$_POST['action_acces'];
// Message d'information : if ($lien === null) $_SESSION['Bateaux']['flash_erreur'] = t("Accès introuvable pour ce bateau.");
else if ($action == 'pdf')
// if (isset($_SESSION['pdf']['src']) && $_SESSION['pdf']['src'] != '') {
// $message_information.= "Télécharger le code d'accès d'<a class='download' target='_blank' href= ".$_SESSION['pdf']['src']."> ici </a> "; if (!$peut_inviter || $lien['Statut'] != 'en_attente') $_SESSION['Bateaux']['flash_erreur'] = t("Action non autorisée.");
// $_SESSION['pdf']['src'] =''; else
{
$invitation = Invitation_par_code($lien['Code']);
$invitation['Code'] = $lien['Code'];
$invitation['Expiration_invitation'] = $lien['Expiration_invitation'];
Fermeture_bdd();
code_acces_pdf($invitation);
exit();
}
}
else
{
$autorise = Peut_devalider_acces($acces_profil, $est_administrateur, $lien['ID_Type_acces_bateau_shipmember'])
|| ($action == 'revoquer' && $lien['Statut'] == 'en_attente' && $peut_inviter);
$transitions = array( 'suspendre' => array("'actif'", 'suspendu'),
'reactiver' => array("'suspendu'", 'actif'),
'revoquer' => array("'en_attente','actif','suspendu'", 'revoque'));
if (!$autorise || !isset($transitions[$action])) $_SESSION['Bateaux']['flash_erreur'] = t("Action non autorisée.");
else
{
$requete = "UPDATE TB_Lien_bateau_shipmember SET Statut=? WHERE ID=? AND ID_Bateau=? AND Statut IN (".$transitions[$action][0].")";
Requete_preparee_bdd($requete, array(
array('s', $transitions[$action][1]), array('i', $lien['ID']), array('i', $bateau['Cle_primaire'])),
__FILE__, __LINE__);
if (Nb_lignes_modifiees() == 1) $_SESSION['Bateaux']['flash_information'] = t("Accès mis à jour.");
else $_SESSION['Bateaux']['flash_erreur'] = t("Cet accès a déjà changé d'état.");
}
}
Fermeture_bdd();
header('Location: bateaux.php');
exit();
}
if (isset($_POST['modifierAcces']) && isset($_POST['ID']))
{
$lien = Lien_du_bateau((int)$_POST['ID'], $bateau['Cle_primaire']);
$date = date_create_from_format('Y-m-d', (string)($_POST['fin_validite'] ?? ''));
if (!$est_administrateur || $lien === null || $lien['Statut'] == 'revoque') $_SESSION['Bateaux']['flash_erreur'] = t("Action non autorisée.");
else if ($date === false) $_SESSION['Bateaux']['flash_erreur'] = t("Date de fin d'accès invalide.");
else
{
$requete = "UPDATE TB_Lien_bateau_shipmember SET Fin_validite=?, ID_Type_acces_bateau_shipmember=?
WHERE ID=? AND ID_Bateau=? AND EXISTS (SELECT 1 FROM TB_Types_acces_bateau_shipmember WHERE Cle_primaire=? AND Validite=1)";
Requete_preparee_bdd($requete, array(
array('s', $date->format('Y-m-d').' 23:59:59'), array('i', (int)$_POST['type_profil']),
array('i', $lien['ID']), array('i', $bateau['Cle_primaire']), array('i', (int)$_POST['type_profil'])),
__FILE__, __LINE__);
if (Nb_lignes_modifiees() == 1) $_SESSION['Bateaux']['flash_information'] = t("Accès mis à jour.");
else $_SESSION['Bateaux']['flash_erreur'] = t("Aucune modification enregistrée (type d'accès invalide, ou valeurs identiques).");
}
Fermeture_bdd();
header('Location: bateaux.php');
exit();
} }
@@ -499,34 +531,29 @@ $requete .= ' TB_Bateaux.Date_derniere_maj AS Date_derniere_maj, ';
//========================= //=========================
case "gerer_les_acces": case "gerer_les_acces":
{ {
$requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND ID_Bateau='.$bateau['Cle_primaire'].' AND ID_Shipmember!=0 '; // Accès et invitations du bateau, hors révoqués (synthèse §47) - une seule requête au lieu de 3 par ligne :
$reponse = Requete_bdd($requete, __FILE__, __LINE__); $colonne_type = ($_SESSION['langue'] == "EN") ? 'Nom_en' : 'Nom_fr';
$requete = "SELECT L.*, S.Prenom AS sm_Prenom, S.Nom AS sm_Nom, S.Email AS sm_Email,
C.Prenom AS cree_par_Prenom, C.Nom AS cree_par_Nom, T.".$colonne_type." AS Niveau_acces_nom,
(L.Expiration_invitation IS NOT NULL AND L.Expiration_invitation <= NOW()) AS Expiree
FROM TB_Lien_bateau_shipmember L
LEFT JOIN TB_Shipmembers S ON S.ID = L.ID_Shipmember
LEFT JOIN TB_Shipmembers C ON C.ID = L.Cree_par
LEFT JOIN TB_Types_acces_bateau_shipmember T ON T.Cle_primaire = L.ID_Type_acces_bateau_shipmember
WHERE L.ID_Bateau=? AND L.Statut <> 'revoque'
ORDER BY FIELD(L.Statut, 'actif', 'suspendu', 'en_attente'), L.Date_creation";
$reponse = Requete_preparee_bdd($requete, array(array('i', $bateau['Cle_primaire'])), __FILE__, __LINE__);
$utilisateur_acces_nb = 0; $utilisateur_acces_nb = 0;
while ($donnees = Recherche_ligne_bdd($reponse)){ while ($donnees = Recherche_ligne_bdd($reponse, MYSQLI_ASSOC))
// Récupérer le nom et le prénom du shipmember qui a accès : {
$sous_req = ' SELECT Nom, Prenom, Email FROM TB_Shipmembers WHERE Validite=1 AND ID='.$donnees['ID_Shipmember'].''; // Destinataire affiché : le ShipMember s'il a accepté, sinon la personne invitée :
$sous_rep = Requete_bdd($sous_req, __FILE__, __LINE__); if ($donnees['Statut'] == 'en_attente') $donnees['Destinataire'] = trim($donnees['Prenom_invite'].' '.$donnees['Nom_invite']).' ['.$donnees['Email_invite'].']';
$sous_donnees = Recherche_ligne_bdd($sous_rep); else $donnees['Destinataire'] = trim($donnees['sm_Prenom'].' '.$donnees['sm_Nom']).' ['.$donnees['sm_Email'].']';
$donnees['sm_Nom'] = $sous_donnees['Nom']; $donnees['Cree_par_nom'] = trim($donnees['cree_par_Prenom'].' '.$donnees['cree_par_Nom']);
$donnees['sm_Prenom'] = $sous_donnees['Prenom']; unset($donnees['Code']); // Jamais envoyé au navigateur (le JSON de chaque ligne alimente le popup)
$donnees['sm_Email'] = $sous_donnees['Email'];
// Récupérer le nom et le prénom du shipmember qui a crée le lien :
$sous_req = ' SELECT Nom, Prenom FROM TB_Shipmembers WHERE Validite=1 AND ID='.$donnees['Cree_par'].'';
$sous_rep = Requete_bdd($sous_req, __FILE__, __LINE__);
$sous_donnees = Recherche_ligne_bdd($sous_rep);
$donnees['cree_par_Nom'] = $sous_donnees['Nom'];
$donnees['cree_par_Prenom'] = $sous_donnees['Prenom'];
// Récupérer le niveau accès garantie à l'utilisateur :
//$sous_req = ' SELECT Nom FROM TB_Lien_bateau_shipmember_acces WHERE Validite=1 AND Niveau_acces='.$donnees['Niveau_acces'].'';
$sous_req = 'SELECT * FROM TB_Types_acces_bateau_shipmember WHERE Validite=1 AND Cle_primaire='.$donnees['ID_Type_acces_bateau_shipmember'].' ';
$sous_rep = Requete_bdd($sous_req, __FILE__, __LINE__);
$sous_donnees = Recherche_ligne_bdd($sous_rep);
if ($_SESSION['langue'] == "EN") $donnees['Niveau_acces_nom'] = $sous_donnees['Nom_en'];
else $donnees['Niveau_acces_nom'] = $sous_donnees['Nom_fr'];
$utilisateur_acces[$utilisateur_acces_nb++] = $donnees; $utilisateur_acces[$utilisateur_acces_nb++] = $donnees;
} }
Liberation_jeu_de_resultat_bdd($reponse);
break; break;
} }
default: break; default: break;
@@ -713,99 +740,138 @@ $requete .= ' TB_Bateaux.Date_derniere_maj AS Date_derniere_maj, ';
//=========================================================== //===========================================================
case "gerer_les_acces": case "gerer_les_acces":
{ {
echo '<div class="gestion_acces">'; // Texte sûr pour le HTML (les données viennent des utilisateurs : noms, adresses...) :
echo ' <div class="generer_code"> $h = function($texte) { return htmlspecialchars((string)$texte, ENT_QUOTES, 'UTF-8'); };
<form action="bateaux.php" method="POST">';
echo ' <select name="type_acces" id="type_acces" required>
<option value="" disabled selected> -- '.$_SESSION['textes']['bateau']['details']['acces']['select'] .' -- </option>' ;
for ($i = 0; $i < $type_acces_nb; $i++){
echo '<option value="'.$type_acces[$i]['Cle_primaire'].'"> '.$type_acces[$i]['Nom'].' </option>';
}
echo ' </select>';
echo ' <input type="date" name="date_validite" id="date_validite"> ';
echo ' <button type="submit" name="generer_code_acces"> '.$_SESSION['textes']['bateau']['details']['acces']['generer'] .' </button>';
echo ' </form>
</div>';
echo ' <div class="users"> ';
echo ' <table>';
echo ' <tr>';
echo ' <th> '.t("Validite").' </th>';
echo ' <th> '.t("Shipmember").'</th>';
echo ' <th> '.t("Créé_par").'</th>';
echo ' <th> '.t("Type de profil").'</th>';
echo ' <th> '.t("Fin de validité").' </th>';
echo ' <th> </th>';
echo ' </tr>';
if ($utilisateur_acces_nb == 0) echo '<tr> <td colspan="5"> 0 shipmember / acces </td> </tr>';
else {
for($i = 0; $i < $utilisateur_acces_nb; $i++){
echo ' <form action="bateaux.php" method="POST">'; echo '<div class="gestion_acces">';
echo ' <tr>';
echo ' <td > <input name="validite_acces" onChange="this.form.submit()" type="checkbox" '; //--------------------------------------------
if (isset($acces_profil['Devalidation_profils']) && $acces_profil['Devalidation_profils'] == 0) echo ' disabled '; // Formulaire d'invitation nominative (synthèse §47) :
if (isset($acces_profil['Devalidation_profils']) && $acces_profil['Devalidation_profils'] == 1 && $utilisateur_acces[$i]['ID_Type_acces_bateau_shipmember'] == 2) echo ' disabled '; if ($peut_inviter)
if ($utilisateur_acces[$i]['Validite_acces'] == 1) echo 'checked'; {
echo '> </td>'; echo '<div class="generer_code">';
echo ' <td> '.$utilisateur_acces[$i]['sm_Prenom'].' '.$utilisateur_acces[$i]['sm_Nom'].' ['.$utilisateur_acces[$i]['sm_Email'].']</td>'; echo ' <form action="bateaux.php" method="POST">';
echo ' <td> '.$utilisateur_acces[$i]['cree_par_Prenom'].' '.$utilisateur_acces[$i]['cree_par_Nom'].'</td>'; echo ' <input type="email" name="email_invite" required maxlength="254" placeholder="'.$h(t("Adresse e-mail du destinataire")).'">';
echo ' <td name="niveau_acces" value="'.$utilisateur_acces[$i]['ID_Type_acces_bateau_shipmember'].'">'.$utilisateur_acces[$i]['Niveau_acces_nom'].'</td>'; echo ' <input type="text" name="prenom_invite" maxlength="50" placeholder="'.$h(t("Prénom (facultatif)")).'">';
echo ' <td name="fin_validite" value="'.$utilisateur_acces[$i]['Fin_validite'].'"> '; echo ' <input type="text" name="nom_invite" maxlength="50" placeholder="'.$h(t("Nom (facultatif)")).'">';
echo (substr($utilisateur_acces[$i]['Fin_validite'],0,-9) == "9999-12-31") ? Recuperer_texte("bateau","details","acces","aucune_fin") : substr($utilisateur_acces[$i]['Fin_validite'],0,-9) ; echo ' <select name="type_acces" required>';
echo ' </td>'; echo ' <option value="" disabled selected> -- '.$h(t("Type d'accès")).' -- </option>';
echo ' <input hidden name="ID" value="'.$utilisateur_acces[$i]['ID'].'">'; for ($i = 0; $i < $type_acces_nb; $i++) echo '<option value="'.(int)$type_acces[$i]['Cle_primaire'].'">'.$h($type_acces[$i]['Nom']).'</option>';
if ($acces_profil['Modification_acces'] == 1){ echo ' </select>';
echo ' <td id="modifier_acces" onclick="popUpEditAccess(' . htmlspecialchars(json_encode($utilisateur_acces[$i]), ENT_QUOTES, 'UTF-8') . ')"></td>'; echo ' <input type="date" name="fin_acces" title="'.$h(t("Fin de l'accès (facultatif)")).'">';
} echo ' <button type="submit" name="creer_invitation">'.$h(t("Inviter")).'</button>';
echo ' </tr>'; echo ' </form>';
echo ' </form>'; echo '</div>';
}
//--------------------------------------------
// Liste des accès et des invitations en attente :
echo '<div class="users">';
echo ' <table>';
echo ' <tr>';
echo ' <th>'.$h(t("Statut")).'</th>';
echo ' <th>'.$h(t("Shipmember")).'</th>';
echo ' <th>'.$h(t("Créé_par")).'</th>';
echo ' <th>'.$h(t("Type de profil")).'</th>';
echo ' <th>'.$h(t("Fin de validité")).'</th>';
echo ' <th></th>';
echo ' </tr>';
if ($utilisateur_acces_nb == 0) echo '<tr><td colspan="6">'.$h(t("Aucun accès ni invitation en cours.")).'</td></tr>';
for ($i = 0; $i < $utilisateur_acces_nb; $i++)
{
$acces = $utilisateur_acces[$i];
// Statut affiché :
switch ($acces['Statut'])
{
case 'actif': $statut = t("Actif"); break;
case 'suspendu': $statut = t("Suspendu"); break;
default:
if ($acces['Expiree']) $statut = t("Invitation expirée");
else $statut = str_replace("[[Date]]", date_format(date_create($acces['Expiration_invitation']), 'd/m/Y'), t("Invitation en attente (jusqu'au [[Date]])"));
break;
} }
// Actions permises sur cette ligne :
$peut_devalider = Peut_devalider_acces($acces_profil, $est_administrateur, $acces['ID_Type_acces_bateau_shipmember']);
$actions = array();
if ($acces['Statut'] == 'actif' && $peut_devalider) $actions['suspendre'] = t("Suspendre");
if ($acces['Statut'] == 'suspendu' && $peut_devalider) $actions['reactiver'] = t("Réactiver");
if ($acces['Statut'] == 'en_attente' && !$acces['Expiree'] && $peut_inviter) $actions['pdf'] = t("PDF");
if ($peut_devalider || ($acces['Statut'] == 'en_attente' && $peut_inviter)) $actions['revoquer'] = t("Révoquer");
echo ' <tr>';
echo ' <td>'.$h($statut).'</td>';
echo ' <td>'.$h($acces['Destinataire']).'</td>';
echo ' <td>'.$h($acces['Cree_par_nom']).'</td>';
echo ' <td>'.$h($acces['Niveau_acces_nom']).'</td>';
echo ' <td>'.((substr($acces['Fin_validite'], 0, 10) == "9999-12-31") ? $h(t("Aucune")) : $h(date_format(date_create($acces['Fin_validite']), 'd/m/Y'))).'</td>';
echo ' <td>';
if (count($actions) > 0)
{
echo '<form action="bateaux.php" method="POST">';
echo '<input type="hidden" name="ID" value="'.(int)$acces['ID'].'">';
foreach ($actions as $code_action => $libelle)
{
echo '<button type="submit" name="action_acces" value="'.$code_action.'"';
if ($code_action == 'revoquer') echo ' onclick="return window.confirm(\''.$h(addslashes(t("Révoquer définitivement cet accès ?"))).'\');"';
echo '>'.$h($libelle).'</button> ';
}
echo '</form>';
}
if ($acces_profil['Modification_acces'] == 1)
{
echo '<span id="modifier_acces" onclick="popUpEditAccess('.$h(json_encode($acces)).')"></span>';
}
echo ' </td>';
echo ' </tr>';
} }
echo ' </table>'; echo ' </table>';
echo ' </div>';
echo '</div>'; echo '</div>';
echo '<div id="popUpAcces" style="display: none;">'; echo '</div>'; // Fin de class="gestion_acces"
echo ' <div id="popUpAccesModal">';
echo ' <div id="top_part">';
echo ' <p> '.t("Titre du popup").' </p>';
echo ' <p id="close" onclick="closeEditAccess();"> </p>';
echo ' </div>';
echo ' <form action="bateaux.php" method="POST">';
echo ' <label for="shipmemberForm" id="ShipMember"> ';
echo ' <input id="shipmemberForm" type="text" value="" name="shipmember" readonly>';
echo ' <span>'.t("Shipmember").'</span>';
echo ' </label>';
echo ' <label for="cree_parForm" id="Cree_par"> ';
echo ' <input id="cree_parForm" type="text" value="" name="cree_par" readonly>';
echo ' <span>'.t("Créé par").'</span>';
echo ' </label>';
echo ' <label for="type_profilForm" id="Type_profil"> ';
echo ' <select name="type_profil" id="type_profilForm" required>
<option value="" disabled selected> -- '.$_SESSION['textes']['bateau']['details']['acces']['select'] .' -- </option>' ;
for ($i = 0; $i < $type_acces_nb; $i++){
echo '<option value="'.$type_acces[$i]['Cle_primaire'].'"> '.$type_acces[$i]['Nom'].' </option>';
}
echo ' </select>';
echo ' <span>'.t("Type de profil").'</span>';
echo ' </label>';
echo ' <label for="fin_validiteForm" id="Fin_validite"> ';
echo ' <input id="fin_validiteForm" type="date" value="" name="fin_validite" required>';
echo ' <span>'.t("Fin de validite").'</span>';
echo ' </label>';
echo ' <input hidden id="idForm" name="ID" value="">';
echo ' <button type="submit" name="supprimerAcces" onclick="return window.confirm(\''.$_SESSION["textes"]["bateau"]["edit_acces"]["popup"]["delete_confirm"].'\');"> '.t("Supprimer").' </button>';
echo ' <button type="submit" name="modifierAcces"> '.t("Mettre à jour").' </button>';
echo ' </form>';
echo ' </div>';
echo '</div>';
//--------------------------------------------
// Popup de modification (administrateurs) : type d'accès et fin de validité.
// (La suppression se fait désormais par le bouton "Révoquer" de chaque ligne.)
if ($acces_profil['Modification_acces'] == 1)
{
echo '<div id="popUpAcces" style="display: none;">';
echo ' <div id="popUpAccesModal">';
echo ' <div id="top_part">';
echo ' <p>'.$h(t("Titre du popup")).'</p>';
echo ' <p id="close" onclick="closeEditAccess();"> </p>';
echo ' </div>';
echo ' <form action="bateaux.php" method="POST">';
echo ' <label for="shipmemberForm" id="ShipMember">';
echo ' <input id="shipmemberForm" type="text" value="" readonly>';
echo ' <span>'.$h(t("Shipmember")).'</span>';
echo ' </label>';
echo ' <label for="cree_parForm" id="Cree_par">';
echo ' <input id="cree_parForm" type="text" value="" readonly>';
echo ' <span>'.$h(t("Créé par")).'</span>';
echo ' </label>';
echo ' <label for="type_profilForm" id="Type_profil">';
echo ' <select name="type_profil" id="type_profilForm" required>';
echo ' <option value="" disabled selected> -- '.$h(t("Type d'accès")).' -- </option>';
for ($i = 0; $i < $type_acces_nb; $i++) echo '<option value="'.(int)$type_acces[$i]['Cle_primaire'].'">'.$h($type_acces[$i]['Nom']).'</option>';
echo ' </select>';
echo ' <span>'.$h(t("Type de profil")).'</span>';
echo ' </label>';
echo ' <label for="fin_validiteForm" id="Fin_validite">';
echo ' <input id="fin_validiteForm" type="date" value="" name="fin_validite" required>';
echo ' <span>'.$h(t("Fin de validite")).'</span>';
echo ' </label>';
echo ' <input type="hidden" id="idForm" name="ID" value="">';
echo ' <button type="submit" name="modifierAcces">'.$h(t("Mettre à jour")).'</button>';
echo ' </form>';
echo ' </div>';
echo '</div>';
}
break; break;
} }
//=========================================================== //===========================================================
// 'resume' (et toute ancienne valeur de session) : // 'resume' (et toute ancienne valeur de session) :
default: default:
@@ -1008,18 +1074,16 @@ Pied_de_page();
document.getElementById('popUpAcces').style.display = "none"; document.getElementById('popUpAcces').style.display = "none";
} }
function popUpEditAccess(data){ function popUpEditAccess(acces){
acces = data;
document.getElementById('popUpAcces').style.display = "block"; document.getElementById('popUpAcces').style.display = "block";
document.getElementById('shipmemberForm').value = acces['sm_Nom']+" "+acces['sm_Prenom']+" ["+acces['sm_Email']+"] "; document.getElementById('shipmemberForm').value = acces['Destinataire'];
document.getElementById('cree_parForm').value = acces['cree_par_Nom']+" "+acces['cree_par_Prenom']; document.getElementById('cree_parForm').value = acces['Cree_par_nom'];
document.getElementById('idForm').value = acces['ID']; document.getElementById('idForm').value = acces['ID'];
// Sélection du type actuel (comparaison en texte : la valeur d'une option est une chaîne, l'ID reçu un nombre) :
const selectElement = document.getElementById('type_profilForm'); const selectElement = document.getElementById('type_profilForm');
for (let i = 0; i < selectElement.options.length; i++) { for (let i = 0; i < selectElement.options.length; i++) {
if (selectElement.options[i].value === acces['ID_Type_acces_bateau_shipmember']) { if (selectElement.options[i].value === String(acces['ID_Type_acces_bateau_shipmember'])) {
selectElement.options[i].selected = true; selectElement.options[i].selected = true;
break; break;
} }
+7 -135
View File
@@ -1,139 +1,11 @@
<?php <?php
session_start(); // Ouverture de session (avant tout autre envoi au client!!!) //************************************************************************************************************
// index.php - Point d'entrée du site. L'initialisation de la session, auparavant faite ici, est désormais assurée
// par Init_session() pour TOUTE page (une page ouverte directement fonctionne aussi - synthèse §47).
//************************************************************************************************************
require_once("../config/config.php"); require_once("../config/config.php");
Init_session(basename($_SERVER['SCRIPT_NAME']));
Ouverture_bdd(); // Connexion à MySql header('Location: shipmembers.php');
exit();
// A SUPPRIMER !!
//if (!isset($_SESSION['type_utilisateur'])) $_SESSION['type_utilisateur'] = TYPE_UTILISATEUR_PROFESSIONNEL; //TYPE_UTILISATEUR_INCONNU;
//--------------------------------------------------------------------------------------------------
// Init des variables de session générales :
if (!isset($_SESSION['acces_valide'])) $_SESSION['acces_valide'] = false;
if (!isset($_SESSION['display_menu'])) $_SESSION['display_menu'] = false;
if (!isset($_SESSION['langue'])) $_SESSION['langue'] = 'FR'; // Valeur par défaut
if (!isset($_SESSION['shipmember']['Cle_primaire'])) $_SESSION['shipmember']['Cle_primaire'] = 0;
if (!isset($_SESSION['shipmember']['Prenom'])) $_SESSION['shipmember']['Prenom'] = "";
if (!isset($_SESSION['shipmember']['Nom'])) $_SESSION['shipmember']['Nom'] = "";
if (!isset($_SESSION['shipmember']['Entreprise'])) $_SESSION['shipmember']['Entreprise'] = "";
if (!isset($_SESSION['shipmember']['Rue'])) $_SESSION['shipmember']['Rue'] = "";
if (!isset($_SESSION['shipmember']['Code_postal'])) $_SESSION['shipmember']['Code_postal'] = "";
if (!isset($_SESSION['shipmember']['Ville'])) $_SESSION['shipmember']['Ville'] = "";
if (!isset($_SESSION['shipmember']['ID_Pays'])) $_SESSION['shipmember']['ID_Pays'] = 75; // FR
if (!isset($_SESSION['shipmember']['Telephone'])) $_SESSION['shipmember']['Telephone'] = "";
if (!isset($_SESSION['shipmember']['Email'])) $_SESSION['shipmember']['Email'] = "";
if (!isset($_SESSION['shipmember']['Commentaires'])) $_SESSION['shipmember']['Commentaires'] = '';
if (!isset($_SESSION['shipmember']['Niveau_acces'])) $_SESSION['shipmember']['Niveau_acces'] = '';
if (!isset($_SESSION['droits_acces'])) $_SESSION['droits_acces'] = 0;
if (!isset($_SESSION['bateau_shipmember'])) $_SESSION['bateau_shipmember']['ID_Bateau'] = '';
if (!isset($_SESSION['bateau_shipmember'])) $_SESSION['bateau_shipmember']['Niveau_acces'] = '';
if (!isset($_SESSION['pdf']['src'])) $_SESSION['pdf']['src']['Niveau_acces'] = '';
if (!isset($_SESSION['modifier_texte'])) $_SESSION['modifier_texte'] = 0;
// if (!isset($_SESSION['shipmember']['code_acces'])) $_SESSION['shipmember']['code_acces'] = $_GET['code_acces'];
//--------------------------------------------------------------------------------------------------
// Recherche des paramètres de configuration générale pour mise à jour des variables de session associées :
$requete = 'SELECT Nom, Valeur FROM TB_Configuration';
$reponse = Requete_bdd($requete, __FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse)) // boucle sur tous les enregistrements de la table
{
switch($donnees['Nom'])
{
case "Langue_par_defaut":
{
$_SESSION['langue'] = $donnees['Valeur'];
break;
}
default :
{
$_SESSION['Config__'.$donnees['Nom'].''] = $donnees['Valeur'];
break;
}
}
}
Liberation_jeu_de_resultat_bdd($reponse);
//--------------------------------------------------------------------------------------------------
// Mise à jour des ID de langue en fonction du prefixe (évite un accès à quasiment chaque requête) :
$requete = 'SELECT ID, Prefix FROM TB_Langues';
$reponse = Requete_bdd($requete, __FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse))
{
$_SESSION['id_langue'][''.$donnees['Prefix'].''] = $donnees['ID'];
}
Liberation_jeu_de_resultat_bdd($reponse);
Fermeture_bdd(); // Déconnexion de MySQL
//--------------------------------------------------------------------------------------------------
// Recherche des textes à utiliser sur les différentes pages et dans la langue en cours
// Attention : doit être rechargé à chaque fois qu'un texte est modifié dans la base
// Attention 2 : doit être rechargé à chaque fois qu'on change de langue
chargement_langue();
//--------------------------------------------------------------------------------------------------
// Affichage des informations système dans le cas d'une demande VERBOSE :
if ((!PRODUCTION) AND (isset($_GET['verbose'])))
{
Entete_page_html();
echo '<div id="Index">';
echo '<table>
<thead>
<tr>
<th>Nom de la variable</th>
<th>Valeur</th>
</tr>
</thead>
<tbody>';
// Affichage des variables de session :
echo '<tr style="line-height:40px;"><td colspan=2><strong>Variables de session</strong></tr>';
foreach ($_SESSION as $k=>$v)
{
if ($k == "db") continue; // Car la valeur stockée est un objet de type "db" qui plante l'affichage....
echo '<tr>
<td>'.$k.'</td>
<td>'.htmlspecialchars(is_array($v) ? json_encode($v) : $v).'</td>
</tr>';
}
// Affichage des variables du serveur :
echo '<tr style="line-height:40px;"><td colspan=2><strong>Variables du serveur</strong></tr>';
foreach ($_SERVER as $k=>$v)
{
echo '<tr>
<td>'.$k.'</td>
<td>'.htmlspecialchars(is_array($v) ? json_encode($v) : $v).'</td>
</tr>';
}
echo '</tbody>
</table>';
echo '<div class="boutons_selection">
<a title="Accéder au logiciel..." href="shipmembers.php">Continuer</a>
<a title="Remettre à zéro toutes les variables de session..." href="shipmembers.php?action=deconnexion">Déconnexion</a>
</div>';
echo '</div>';
echo '</body>';
echo '</html>';
}
else header('Refresh: 0; URL=shipmembers.php'); // Une fois que les variables de version sont chargées
// else header('Refresh: 0; URL=accueil.php'); // Une fois que les variables de version sont chargées
+149 -201
View File
@@ -25,17 +25,19 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
// Variables GET : // Variables GET :
// Le code d'accès ne doit contenir que ce que produit le générateur (bateaux.php) : chiffres et // Code d'invitation reçu par le lien du QR code (synthèse §47) : normalisé et validé par Normaliser_code_invitation()
// lettres, 6 caractères aujourd'hui (colonne Code : 20 au maximum). Il est ensuite inséré dans des // (majuscules et chiffres sans caractères ambigus, 8 caractères) - toute autre valeur est ignorée. Il est conservé
// requêtes SQL : tout autre caractère est refusé. is_string() écarte ?code_acces[]=... (un tableau // en session jusqu'à ce que l'utilisateur soit connecté, puis examiné sur la page Accueil.
// ferait planter preg_match) ; \z (et non $) refuse aussi un retour à la ligne final. if (isset($_GET['code_acces']))
function Code_acces_est_valide($valeur)
{ {
return is_string($valeur) && preg_match('/^[0-9A-Za-z]{1,20}\z/', $valeur) === 1; $code = Normaliser_code_invitation($_GET['code_acces']);
if ($code !== false) $_SESSION['code_acces'] = $code;
else $message_erreur .= t("Le code d'invitation de ce lien n'est pas valide.");
} }
// Une valeur déjà présente en session (ouverte avant ce contrôle, ou par une autre voie) est vérifiée aussi :
if (isset($_SESSION['code_acces']) && !Code_acces_est_valide($_SESSION['code_acces'])) $_SESSION['code_acces'] = ''; // Messages transmis par une redirection (après acceptation ou refus d'une invitation) :
if (isset($_GET['code_acces']) && Code_acces_est_valide($_GET['code_acces']) && (!isset($_SESSION['code_acces']) || $_SESSION['code_acces']== '')) $_SESSION['code_acces'] = $_GET['code_acces']; if (isset($_SESSION['Shipmembers']['flash_information'])) { $message_information .= $_SESSION['Shipmembers']['flash_information']; unset($_SESSION['Shipmembers']['flash_information']); }
if (isset($_SESSION['Shipmembers']['flash_erreur'])) { $message_erreur .= $_SESSION['Shipmembers']['flash_erreur']; unset($_SESSION['Shipmembers']['flash_erreur']); }
if (isset($_GET['action'])) if (isset($_GET['action']))
@@ -77,7 +79,7 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
session_destroy(); // on détruit la session. session_destroy(); // on détruit la session.
header('Location:index.php'); // Redirection sur la page d'index pour rechercher les premières variables de session header('Location:index.php'); // Redirection sur la page d'index pour rechercher les premières variables de session
break; exit();
} }
//----------------------------------- //-----------------------------------
@@ -101,7 +103,9 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
} }
// if (!$flag_redirection) // if (!$flag_redirection)
Fermeture_bdd();
header('Location:shipmembers.php'.$_SESSION['Shipmembers']['ancre'].''); header('Location:shipmembers.php'.$_SESSION['Shipmembers']['ancre'].'');
exit();
} }
// Variables POST : // Variables POST :
@@ -167,7 +171,7 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
// Création du ShipMember : // Création du ShipMember :
$requete = 'INSERT INTO TB_Shipmembers(Nom, Prenom, Entreprise, Rue, Code_postal, Ville, ID_PAYS, Telephone, Email, ID_LANGUAGES, Mdp, Date_creation_compte) VALUES (?,?,?,?,?,?,?,?,?,(SELECT ID FROM TB_Langues WHERE Prefix=?),?,?,?)'; $requete = 'INSERT INTO TB_Shipmembers(Nom, Prenom, Entreprise, Rue, Code_postal, Ville, ID_PAYS, Telephone, Email, ID_LANGUAGES, Mdp, Date_creation_compte) VALUES (?,?,?,?,?,?,?,?,?,(SELECT ID FROM TB_Langues WHERE Prefix=?),?,?)';
Requete_preparee_bdd($requete, Requete_preparee_bdd($requete,
array( array(
array('s', $_SESSION['shipmember']['Nom']), array('s', $_SESSION['shipmember']['Nom']),
@@ -180,7 +184,6 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
array('s', $_SESSION['shipmember']['Telephone']), array('s', $_SESSION['shipmember']['Telephone']),
array('s', $_SESSION['shipmember']['Email']), array('s', $_SESSION['shipmember']['Email']),
array('s', $_SESSION['langue']), array('s', $_SESSION['langue']),
array('s', ""),
array('s', password_hash($password, PASSWORD_DEFAULT)), array('s', password_hash($password, PASSWORD_DEFAULT)),
array('s', date("Y-m-d H:i:s"))), array('s', date("Y-m-d H:i:s"))),
__FILE__, __LINE__); __FILE__, __LINE__);
@@ -250,40 +253,55 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
$message_information .= $message; $message_information .= $message;
//Fin......................................................................... //Fin.........................................................................
// Créer le lien bateau shipmember, affecter l'enregitrement a cet utilisateur :
if (isset($_SESSION['code_acces']) && $_SESSION['code_acces']!=''){
$code = $_SESSION['code_acces'];
$requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND Code=? AND ID_Shipmember=0';
$reponse = Requete_preparee_bdd($requete, array(array('s', $code)), __FILE__, __LINE__);
$donnees = Recherche_ligne_bdd($reponse);
Liberation_jeu_de_resultat_bdd($reponse);
if ($donnees == NULL) $message_erreur .= "Code invalide ou déjà utilisé \n";
else
{
$sous_req = 'UPDATE TB_Lien_bateau_shipmember SET ID_Shipmember=? WHERE Validite=1 AND Code=? AND ID_Shipmember=0';
$sous_rep = Requete_preparee_bdd($sous_req, array(array('i', $_SESSION['shipmember']['Cle_primaire']), array('s', $code)), __FILE__, __LINE__);
}
$_SESSION['code_acces'] = '';
}
// Récupération des liaisons shipmember - bateau // Pas de connexion automatique après la création : l'adresse e-mail n'est prouvée qu'à la première connexion avec
// le mot de passe provisoire reçu (activation). Sans cela, n'importe qui pourrait créer un compte avec l'adresse d'un
$current_timestamp = date_format(date_create(), 'Y-m-d H:i:s'); // autre et accepter aussitôt les invitations destinées à cette adresse (synthèse §47).
$requete = 'SELECT ID_Bateau, ID_Type_acces_bateau_shipmember FROM TB_Lien_bateau_shipmember WHERE ID_Shipmember='.$_SESSION['shipmember']['Cle_primaire'].' AND Validite=1 AND Validite_acces=1 AND Fin_validite>="'.$current_timestamp.'"'; $_SESSION['shipmember']['Cle_primaire'] = 0;
$reponse = Requete_bdd($requete, __FILE__, __LINE__); $_SESSION['Shipmembers']['page'] = "Login";
$nb_acces = 0; $message_information .= "<br />".t("Connectez-vous avec ce mot de passe provisoire pour activer votre compte.");
// $bateau_shipmember = []
while ($donnees = Recherche_ligne_bdd($reponse)) {
$_SESSION['bateau_shipmember'][$nb_acces++] = $donnees;
}
Liberation_jeu_de_resultat_bdd($reponse);
$_SESSION['acces'] = $nb_acces;
$_SESSION['acces_valide'] = true;
$_SESSION['Shipmembers']['page'] = "Accueil";
} }
} }
//---------------------------------------------------------------------------
// Invitations (synthèse §47) : acceptation, refus, saisie manuelle d'un code. Réservé à un utilisateur connecté
// (acceptation et refus) ; les conditions (adresse, statut, expiration, compte activé) sont vérifiées par
// Accepter_invitation() / Refuser_invitation(). Puis redirection (un rafraîchissement ne rejoue pas l'action).
if ((isset($_POST['accepter_invitation']) || isset($_POST['refuser_invitation'])) && $_SESSION['acces_valide'])
{
if (isset($_POST['accepter_invitation']))
{
$resultat = Accepter_invitation((int)$_POST['accepter_invitation'], $_SESSION['shipmember']['Cle_primaire'], $_SESSION['shipmember']['Email']);
if ($resultat['ok'])
{
Rafraichir_acces_session($_SESSION['shipmember']['Cle_primaire']);
$_SESSION['Shipmembers']['flash_information'] = t("Invitation acceptée : le bateau est maintenant accessible dans « Mon bateau ».");
}
else $_SESSION['Shipmembers']['flash_erreur'] = $resultat['raison'];
}
else
{
if (Refuser_invitation((int)$_POST['refuser_invitation'], $_SESSION['shipmember']['Email'])) $_SESSION['Shipmembers']['flash_information'] = t("Invitation refusée.");
else $_SESSION['Shipmembers']['flash_erreur'] = t("Cette invitation n'est plus valable.");
}
$_SESSION['Shipmembers']['page'] = "Accueil";
Fermeture_bdd();
header('Location: shipmembers.php');
exit();
}
if (isset($_POST['saisie_code_invitation']))
{
$code = Normaliser_code_invitation($_POST['code_invitation'] ?? '');
if ($code === false) $message_erreur .= t("Ce code n'a pas le bon format (8 caractères, par exemple K7QX-M3PW).");
else
{
$_SESSION['code_acces'] = $code; // Examiné ci-dessous (page Accueil, ou bandeau de la page Login)
if ($_SESSION['acces_valide']) $_SESSION['Shipmembers']['page'] = "Accueil";
}
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Lecture de l'email et du mot de passe et filtrage contre les injections SQL : // Lecture de l'email et du mot de passe et filtrage contre les injections SQL :
if (isset($_POST['validation_login_shipmember']) AND isset($_POST['email_validation']) AND isset($_POST['mdp_validation'])) if (isset($_POST['validation_login_shipmember']) AND isset($_POST['email_validation']) AND isset($_POST['mdp_validation']))
@@ -298,12 +316,14 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
$mdp = $_POST['mdp_validation']; // Le MDP n'est pas envoyé... $mdp = $_POST['mdp_validation']; // Le MDP n'est pas envoyé...
$requete = 'SELECT ID AS Cle_primaire, Validite, Nom, Prenom, Entreprise, Rue, Code_postal, Ville, Telephone, Email, Mdp, Date_creation_compte, Niveau_acces, ID_PAYS AS ID_Pays, ID_LANGUAGES, (SELECT 1 FROM TB_Activation WHERE ID_SHIPMEMBERS=ID) AS Compte_a_activer, (SELECT Date_creation_mdp FROM TB_Activation WHERE ID_SHIPMEMBERS=ID) AS Date_creation_mdp FROM TB_Shipmembers WHERE Email=? '; $requete = 'SELECT ID AS Cle_primaire, Validite, Nom, Prenom, Entreprise, Rue, Code_postal, Ville, Telephone, Email, Mdp, Date_creation_compte, Niveau_acces, ID_PAYS AS ID_Pays, ID_LANGUAGES, (SELECT 1 FROM TB_Activation WHERE ID_SHIPMEMBERS=ID) AS Compte_a_activer, (SELECT Date_creation_mdp FROM TB_Activation WHERE ID_SHIPMEMBERS=ID) AS Date_creation_mdp FROM TB_Shipmembers WHERE Email=? ';
$reponse = Requete_preparee_bdd($requete, // NB : variable dédiée ($reponse_login) - le corps de la boucle exécute d'autres requêtes qui réutilisaient $reponse ;
// la libération finale visait alors un résultat déjà libéré (erreur fatale en PHP 8 - synthèse §47) :
$reponse_login = Requete_preparee_bdd($requete,
array( array(
array('s', $email)), array('s', $email)),
__FILE__, __LINE__); __FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse)) while ($donnees = Recherche_ligne_bdd($reponse_login))
{ {
if (password_verify($mdp, $donnees['Mdp'])) if (password_verify($mdp, $donnees['Mdp']))
{ {
@@ -363,36 +383,8 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
$_SESSION['acces_valide'] = true; $_SESSION['acces_valide'] = true;
// Créer le lien bateau shipmember, affecter l'enregitrement a cet utilisateur
if (isset($_SESSION['code_acces']) && $_SESSION['code_acces']!=''){
$code = $_SESSION['code_acces'];
$requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND Code=? AND ID_Shipmember=0';
$reponse = Requete_preparee_bdd($requete, array(array('s', $code)), __FILE__, __LINE__);
$donnees = Recherche_ligne_bdd($reponse);
// Vérifier si le code est tjrs valable
if ($donnees == NULL){
$message_erreur .= "Code invalide ou déjà utilisé \n";
$_SESSION['code_acces'] = '';
}
else {
$sous_req = 'UPDATE TB_Lien_bateau_shipmember SET ID_Shipmember=? WHERE Validite=1 AND Code=? AND ID_Shipmember=0';
$sous_rep = Requete_preparee_bdd($sous_req, array(array('i', $_SESSION['shipmember']['Cle_primaire']), array('s', $code)), __FILE__, __LINE__);
$_SESSION['code_acces'] = '';
// $_SESSION['droits_acces'] = $donnees['Niveau_acces'];
}
}
// Récupération des liaisons shipmember - bateau Rafraichir_acces_session($_SESSION['shipmember']['Cle_primaire']); // Accès actifs (synthèse §47)
$current_timestamp = date_format(date_create(), 'Y-m-d H:i:s');
$requete = 'SELECT ID_Bateau, ID_Type_acces_bateau_shipmember FROM TB_Lien_bateau_shipmember WHERE ID_Shipmember='.$_SESSION['shipmember']['Cle_primaire'].' AND Validite=1 AND Validite_acces=1 AND Fin_validite>="'.$current_timestamp.'"';
$reponse = Requete_bdd($requete, __FILE__, __LINE__);
$nb_acces = 0;
// $bateau_shipmember = []
while ($donnees = Recherche_ligne_bdd($reponse)) {
$_SESSION['bateau_shipmember'][$nb_acces++] = $donnees;
}
$_SESSION['acces'] = $nb_acces;
$_SESSION['Shipmembers']['page'] = "Accueil"; $_SESSION['Shipmembers']['page'] = "Accueil";
} }
@@ -400,7 +392,7 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
} }
// else $message_information .= "MDP ne matchent pas. "; // else $message_information .= "MDP ne matchent pas. ";
} }
Liberation_jeu_de_resultat_bdd($reponse); Liberation_jeu_de_resultat_bdd($reponse_login);
} }
// else $message_information .= "Email ou MDP non valides : [".$_POST['email_validation']."] et [".$_POST['mdp_validation']."]."; // else $message_information .= "Email ou MDP non valides : [".$_POST['email_validation']."] et [".$_POST['mdp_validation']."].";
@@ -433,11 +425,12 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
else else
{ {
// Mise à jour du nouveau mot de passe : // Mise à jour du nouveau mot de passe :
$mdp_filtre = Protection_mysql($new_mdp); // NB : haché tel quel - l'ancien code hachait la version échappée pour SQL (Protection_mysql), qui ne correspond
// plus au mot de passe saisi à la connexion dès qu'il contient un caractère échappé (synthèse §47) :
$requete = 'UPDATE TB_Shipmembers SET Mdp=? WHERE ID=?'; $requete = 'UPDATE TB_Shipmembers SET Mdp=? WHERE ID=?';
Requete_preparee_bdd($requete, Requete_preparee_bdd($requete,
array( array(
array('s', password_hash($mdp_filtre, PASSWORD_DEFAULT)), array('s', password_hash($new_mdp, PASSWORD_DEFAULT)),
array('i', $_SESSION['shipmember']['Cle_primaire'])), array('i', $_SESSION['shipmember']['Cle_primaire'])),
__FILE__, __LINE__); __FILE__, __LINE__);
@@ -449,17 +442,7 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
$_SESSION['acces_valide'] = true; $_SESSION['acces_valide'] = true;
// Récupération des liaisons shipmember - bateau Rafraichir_acces_session($_SESSION['shipmember']['Cle_primaire']); // Accès actifs (synthèse §47)
$current_timestamp = date_format(date_create(), 'Y-m-d H:i:s');
$requete = 'SELECT ID_Bateau, ID_Type_acces_bateau_shipmember FROM TB_Lien_bateau_shipmember WHERE ID_Shipmember='.$_SESSION['shipmember']['Cle_primaire'].' AND Validite=1 AND Validite_acces=1 AND Fin_validite>="'.$current_timestamp.'"';
$reponse = Requete_bdd($requete, __FILE__, __LINE__);
$nb_acces = 0;
// $bateau_shipmember = []
while ($donnees = Recherche_ligne_bdd($reponse)) {
$_SESSION['bateau_shipmember'][$nb_acces++] = $donnees;
}
$_SESSION['acces'] = $nb_acces;
// $_SESSION['acces_valide'] = true; // $_SESSION['acces_valide'] = true;
$_SESSION['Shipmembers']['page'] = "Accueil"; $_SESSION['Shipmembers']['page'] = "Accueil";
@@ -589,16 +572,6 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
$message_information .= $message; $message_information .= $message;
//......................................................................... //.........................................................................
// Récupération des liaisons shipmember - bateau
$current_timestamp = date_format(date_create(), 'Y-m-d H:i:s');
$requete = 'SELECT ID_Bateau, ID_Type_acces_bateau_shipmember FROM TB_Lien_bateau_shipmember WHERE ID_Shipmember='.$cle_primaire_demande.' AND Validite=1 AND Validite_acces=1 AND Fin_validite>="'.$current_timestamp.'"';
$reponse = Requete_bdd($requete, __FILE__, __LINE__);
$nb_acces = 0;
// $bateau_shipmember = []
while ($donnees = Recherche_ligne_bdd($reponse)) {
$_SESSION['bateau_shipmember'][$nb_acces++] = $donnees;
}
$_SESSION['acces'] = $nb_acces;
// $_SESSION['acces_valide'] = true; // $_SESSION['acces_valide'] = true;
// $_SESSION['Shipmembers']['page'] = "Accueil"; // $_SESSION['Shipmembers']['page'] = "Accueil";
@@ -769,7 +742,7 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
if (($_SESSION['Shipmembers']['page'] != "Login") AND if (($_SESSION['Shipmembers']['page'] != "Login") AND
($_SESSION['Shipmembers']['page'] != "Activation") AND ($_SESSION['Shipmembers']['page'] != "Activation") AND
($_SESSION['Shipmembers']['page'] != "Generation_mdp") AND ($_SESSION['Shipmembers']['page'] != "Generation_mdp") AND
(!$_SESSION['acces_valide'])) header('Location:shipmembers.php?action=navigation&destination=Login'); (!$_SESSION['acces_valide'])) { Fermeture_bdd(); header('Location:shipmembers.php?action=navigation&destination=Login'); exit(); }
// $_SESSION['code_acces'] = $_GET['code_acces']; // $_SESSION['code_acces'] = $_GET['code_acces'];
// if (isset($_GET['code_acces']) && !isset($_SESSION['code_acces'])) $_SESSION['code_acces'] = $_GET['code_acces']; // if (isset($_GET['code_acces']) && !isset($_SESSION['code_acces'])) $_SESSION['code_acces'] = $_GET['code_acces'];
@@ -781,8 +754,20 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
{ {
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// Saut à l'accueil sans login si on est déjà identifié : // Saut à l'accueil sans login si on est déjà identifié :
if ($_SESSION['acces_valide'] && (!isset($_SESSION['code_acces']) || $_SESSION['code_acces'] == '') ) header('Location:shipmembers.php?action=navigation&destination=Accueil'); if ($_SESSION['acces_valide']) { Fermeture_bdd(); header('Location:shipmembers.php?action=navigation&destination=Accueil'); exit(); }
else if ($_SESSION['acces_valide'] && (isset($_SESSION['code_acces']) && $_SESSION['code_acces'] != '') ) header('Location:shipmembers.php?action=navigation&destination=Accueil&code_acces='.$_SESSION['code_acces']);
// Lien d'invitation ouvert sans être connecté : bandeau explicatif (synthèse §47) :
$invitation_login = null;
if (isset($_SESSION['code_acces']) && $_SESSION['code_acces'] != '')
{
$invitation_login = Invitation_par_code($_SESSION['code_acces']);
if ($invitation_login === null || $invitation_login['Statut'] != 'en_attente' || $invitation_login['Expiree'])
{
$message_erreur .= t("Cette invitation n'est plus valable (code inconnu, déjà utilisé, révoqué ou expiré).");
$invitation_login = null;
$_SESSION['code_acces'] = '';
}
}
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// Récupération des informations sur les pays : // Récupération des informations sur les pays :
$nb_pays = 0; $nb_pays = 0;
@@ -805,7 +790,7 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
{ {
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// Saut à l'accueil sans login si on est déjà identifié : // Saut à l'accueil sans login si on est déjà identifié :
if ($_SESSION['acces_valide']) header('Location:shipmembers.php?action=navigation&destination=Accueil'); if ($_SESSION['acces_valide']) { Fermeture_bdd(); header('Location:shipmembers.php?action=navigation&destination=Accueil'); exit(); }
break; break;
} }
@@ -815,7 +800,7 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
{ {
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// Saut à l'accueil sans login si on est déjà identifié : // Saut à l'accueil sans login si on est déjà identifié :
if ($_SESSION['acces_valide']) header('Location:shipmembers.php?action=navigation&destination=Accueil'); if ($_SESSION['acces_valide']) { Fermeture_bdd(); header('Location:shipmembers.php?action=navigation&destination=Accueil'); exit(); }
break; break;
} }
@@ -836,36 +821,29 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
Liberation_jeu_de_resultat_bdd($reponse); Liberation_jeu_de_resultat_bdd($reponse);
// Créer le lien bateau shipmember, affecter l'enregitrement a cet utilisateur
if (isset($_SESSION['code_acces']) && $_SESSION['code_acces']!=''){ Rafraichir_acces_session($_SESSION['shipmember']['Cle_primaire']); // Accès actifs (synthèse §47)
$code = $_SESSION['code_acces'];
$requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND Code=? AND ID_Shipmember=0'; // Code d'invitation reçu par lien ou saisi (synthèse §47) : on explique ce qu'il en est, l'acceptation elle-même
$reponse = Requete_preparee_bdd($requete, array(array('s', $code)), __FILE__, __LINE__); // se fait par le bouton de la liste "Mes invitations" ci-dessous :
$donnees = Recherche_ligne_bdd($reponse); if (isset($_SESSION['code_acces']) && $_SESSION['code_acces'] != '')
// Vérifier si le code est tjrs valable {
if ($donnees == NULL){ $invitation_code = Invitation_par_code($_SESSION['code_acces']);
$message_erreur .= "Code invalide ou déjà utilisé \n"; if ($invitation_code === null) $message_erreur .= t("Ce code d'invitation est inconnu.");
$_SESSION['code_acces'] = ''; else if ($invitation_code['Statut'] != 'en_attente') $message_erreur .= t("Cette invitation a déjà été utilisée ou révoquée.");
} else if ($invitation_code['Expiree']) $message_erreur .= t("Cette invitation a expiré : demandez-en une nouvelle à la personne qui vous l'a envoyée.");
else { else if (strtolower($invitation_code['Email_invite']) != strtolower($_SESSION['shipmember']['Email']))
$sous_req = 'UPDATE TB_Lien_bateau_shipmember SET ID_Shipmember=? WHERE Validite=1 AND Code=? AND ID_Shipmember=0'; {
$sous_rep = Requete_preparee_bdd($sous_req, array(array('i', $_SESSION['shipmember']['Cle_primaire']), array('s', $code)), __FILE__, __LINE__); $message_erreur .= str_replace("[[Email]]", Masquer_email($invitation_code['Email_invite']),
$_SESSION['code_acces'] = ''; t("Cette invitation est réservée à l'adresse [[Email]] : connectez-vous avec le compte ShipMember de cette adresse pour l'accepter."));
// $_SESSION['droits_acces'] = $donnees['Niveau_acces'];
} }
else $message_information .= str_replace("[[Bateau]]", htmlspecialchars($invitation_code['Nom_bateau']),
t("Vous avez été invité(e) à accéder au bateau [[Bateau]] : acceptez ou refusez l'invitation ci-dessous."));
$_SESSION['code_acces'] = '';
} }
// Récupération des liaisons shipmember - bateau // Invitations en attente adressées à ce compte (seul un compte activé peut en accepter) :
$invitations = Compte_est_active($_SESSION['shipmember']['Cle_primaire']) ? Invitations_en_attente($_SESSION['shipmember']['Email']) : array();
$current_timestamp = date_format(date_create(), 'Y-m-d H:i:s');
$requete = 'SELECT ID_Bateau, ID_Type_acces_bateau_shipmember FROM TB_Lien_bateau_shipmember WHERE ID_Shipmember='.$_SESSION['shipmember']['Cle_primaire'].' AND Validite=1 AND Validite_acces=1 AND Fin_validite>="'.$current_timestamp.'"';
$reponse = Requete_bdd($requete, __FILE__, __LINE__);
$nb_acces = 0;
// $bateau_shipmember = []
while ($donnees = Recherche_ligne_bdd($reponse)) {
$_SESSION['bateau_shipmember'][$nb_acces++] = $donnees;
}
$_SESSION['acces'] = $nb_acces;
// $_SESSION['acces_valide'] = true; // $_SESSION['acces_valide'] = true;
@@ -922,86 +900,20 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
//**************************************************************************************************************************** //****************************************************************************************************************************
case "Bateau": case "Bateau":
{ {
// Récupération des informations sur le ou les bateaux accessibles à ce ShipMember : // Bateaux accessibles : accès ACTIFS uniquement (synthèse §47). Le repli sur le bateau de démonstration
// (liens portant le code "0000") est retiré, comme le bateau 25 de bateaux.php - à reprendre plus tard.
Rafraichir_acces_session($_SESSION['shipmember']['Cle_primaire']);
$nb_bateaux = 0; $nb_bateaux = 0;
$requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND Validite_acces=1 AND ID_SHIPMEMBER=? '; foreach ($_SESSION['bateau_shipmember'] as $acces)
$reponse = Requete_preparee_bdd($requete,
array(
array('i', $_SESSION['shipmember']['Cle_primaire'])),
__FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse))
{ {
$bateaux[$nb_bateaux ++]['Cle_primaire'] = $donnees['ID_Bateau']; $reponse = Requete_preparee_bdd('SELECT * FROM TB_Bateaux WHERE Cle_primaire=? AND Validite=1',
} array(array('i', $acces['ID_Bateau'])), __FILE__, __LINE__);
Liberation_jeu_de_resultat_bdd($reponse); while ($donnees = Recherche_ligne_bdd($reponse)) $bateaux[$nb_bateaux ++] = $donnees;
// Bateau demonstration pour les SM affectés à aucun bateau
if ($nb_bateaux == 0){
$requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND Validite_acces=1 AND ID_SHIPMEMBER=? AND Code=? ';
$reponse = Requete_preparee_bdd($requete,
array(
array('i', 0),
array('s', "0000")),
__FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse))
{
$bateaux[$nb_bateaux ++]['Cle_primaire'] = $donnees['ID_Bateau'];
}
Liberation_jeu_de_resultat_bdd($reponse);
}
// Récupération des informations relatives à chacun des bateaux accessibles :
for ($i=0; $i<$nb_bateaux; $i ++)
{
$requete = 'SELECT * FROM TB_Bateaux WHERE Cle_primaire=? ';
$reponse = Requete_preparee_bdd($requete,
array(
array('i', $bateaux[$i]['Cle_primaire'])),
__FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse))
{
$bateaux[$i] = $donnees;
}
Liberation_jeu_de_resultat_bdd($reponse); Liberation_jeu_de_resultat_bdd($reponse);
} }
// Créer le lien bateau shipmember, affecter l'enregitrement a cet utilisateur
if (isset($_SESSION['code_acces']) && $_SESSION['code_acces']!=''){
$code = $_SESSION['code_acces'];
$requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND Code=? AND ID_Shipmember=0';
$reponse = Requete_preparee_bdd($requete, array(array('s', $code)), __FILE__, __LINE__);
$donnees = Recherche_ligne_bdd($reponse);
// Vérifier si le code est tjrs valable
if ($donnees == NULL){
$message_erreur .= "Code invalide ou déjà utilisé \n";
$_SESSION['code_acces'] = '';
}
else {
$sous_req = 'UPDATE TB_Lien_bateau_shipmember SET ID_Shipmember=? WHERE Validite=1 AND Code=? AND ID_Shipmember=0';
$sous_rep = Requete_preparee_bdd($sous_req, array(array('i', $_SESSION['shipmember']['Cle_primaire']), array('s', $code)), __FILE__, __LINE__);
$_SESSION['code_acces'] = '';
// $_SESSION['droits_acces'] = $donnees['Niveau_acces'];
}
}
// Récupération des liaisons shipmember - bateau
$current_timestamp = date_format(date_create(), 'Y-m-d H:i:s');
$requete = 'SELECT ID_Bateau, ID_Type_acces_bateau_shipmember FROM TB_Lien_bateau_shipmember WHERE ID_Shipmember='.$_SESSION['shipmember']['Cle_primaire'].' AND Validite=1 AND Validite_acces=1 AND Fin_validite>="'.$current_timestamp.'"';
$reponse = Requete_bdd($requete, __FILE__, __LINE__);
$nb_acces = 0;
// $bateau_shipmember = []
while ($donnees = Recherche_ligne_bdd($reponse)) {
$_SESSION['bateau_shipmember'][$nb_acces++] = $donnees;
}
$_SESSION['acces'] = $nb_acces;
// $_SESSION['acces_valide'] = true;
break; break;
} }
//****************************************************************************************************************************
default: default:
{ {
$_SESSION['Shipmembers']['page'] = "Accueil"; $_SESSION['Shipmembers']['page'] = "Accueil";
@@ -1037,6 +949,16 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
echo '<h1>'.t("Connectez-vous").'</h1>'; echo '<h1>'.t("Connectez-vous").'</h1>';
// Lien d'invitation ouvert sans être connecté (synthèse §47) :
if ($invitation_login !== null)
{
$texte = t("Vous avez été invité(e) à accéder au bateau [[Bateau]] ([[Type]]). Pour accepter cette invitation, connectez-vous - ou créez votre compte - avec l'adresse [[Email]].");
$texte = str_replace("[[Bateau]]", '<span class="gras">'.htmlspecialchars($invitation_login['Nom_bateau']).'</span>', $texte);
$texte = str_replace("[[Type]]", htmlspecialchars((string)$invitation_login['Type_acces']), $texte);
$texte = str_replace("[[Email]]", '<span class="gras">'.htmlspecialchars(Masquer_email($invitation_login['Email_invite'])).'</span>', $texte);
echo '<div class="message_information">'.$texte.'</div>';
}
echo '<form action="shipmembers.php" method="post">'; echo '<form action="shipmembers.php" method="post">';
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -1330,6 +1252,32 @@ Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session
echo '</div>'; echo '</div>';
//---------------------------------------------------------------------------
// Mes invitations (synthèse §47) :
echo '<div class="espace_shipmember invitations">';
echo '<h2>'.t("Mes invitations").'</h2>';
if (count($invitations) == 0) echo '<p>'.t("Aucune invitation en attente.").'</p>';
foreach ($invitations as $invitation)
{
$texte = t("Bateau [[Bateau]] - accès [[Type]], proposé par [[Invitant]] (valable jusqu'au [[Date]]).");
$texte = str_replace("[[Bateau]]", '<span class="gras">'.htmlspecialchars($invitation['Nom_bateau']).'</span>', $texte);
$texte = str_replace("[[Type]]", htmlspecialchars((string)$invitation['Type_acces']), $texte);
$texte = str_replace("[[Invitant]]", htmlspecialchars(trim($invitation['Prenom_invitant'].' '.$invitation['Nom_invitant'])), $texte);
$texte = str_replace("[[Date]]", date_format(date_create($invitation['Expiration_invitation']), 'd/m/Y'), $texte);
echo '<form action="shipmembers.php" method="post" class="invitation">';
echo '<p>'.$texte.'</p>';
echo '<button type="submit" name="accepter_invitation" value="'.(int)$invitation['ID'].'">'.t("Accepter").'</button> ';
echo '<button type="submit" name="refuser_invitation" value="'.(int)$invitation['ID'].'" onclick="return window.confirm(\''.addslashes(t("Refuser définitivement cette invitation ?")).'\');">'.t("Refuser").'</button>';
echo '</form>';
}
// Saisie manuelle d'un code (invitation papier, sans appareil photo) :
echo '<form action="shipmembers.php" method="post" class="saisie_code">';
echo '<label for="code_invitation">'.t("J'ai un code d'invitation :").'</label> ';
echo '<input type="text" name="code_invitation" id="code_invitation" maxlength="12" placeholder="K7QX-M3PW" autocomplete="off"> ';
echo '<button type="submit" name="saisie_code_invitation">'.t("Valider").'</button>';
echo '</form>';
echo '</div>';
echo '<div class="boutons_bas_de_page">'; echo '<div class="boutons_bas_de_page">';
echo '<a title="'.t("Voir les informations liées à votre compte ShipMember...").'" href="shipmembers.php?action=navigation&destination=Profil"> echo '<a title="'.t("Voir les informations liées à votre compte ShipMember...").'" href="shipmembers.php?action=navigation&destination=Profil">
'.t("Mes informations").' '.t("Mes informations").'
+4
View File
@@ -0,0 +1,4 @@
-- Durée de validité (jours) d'une invitation à accéder à un bateau (synthèse §47)
INSERT INTO TB_Configuration (Validite, Nom, Description, Valeur)
VALUES (1, 'Duree_validite_invitation',
'Nombre de jours pendant lesquels une invitation à accéder à un bateau peut être acceptée', '30');
@@ -0,0 +1,12 @@
-- ============================================================================
-- TB_Lien_bateau_shipmember - refonte, PARTIE 2/2 : suppression des
-- anciennes colonnes (synthèse §47). À exécuter UNIQUEMENT après le
-- déploiement du code PHP utilisant Statut (bateaux.php, shipmembers.php,
-- administration.php) : l'ancien code échouerait sur ces colonnes absentes.
-- ============================================================================
ALTER TABLE TB_Lien_bateau_shipmember
DROP COLUMN Validite,
DROP COLUMN Validite_acces,
DROP COLUMN Niveau_acces_OLD;
SHOW CREATE TABLE TB_Lien_bateau_shipmember;