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:
@@ -1,12 +1,13 @@
|
||||
<?php
|
||||
|
||||
require_once("fonctions_bdd.php"); // Contient les fonctions d'accès aux BDD.
|
||||
require_once("fonctions_fichiers.php"); // Contient les fonctions de traitement des répertoires et des fichiers
|
||||
require_once("fonctions_ftp.php");
|
||||
require_once("fonctions_html.php");
|
||||
require_once("fonctions_mail.php"); // Contient les fonctions d'émission des emails
|
||||
require_once("fonctions_pdf.php"); // Contient les fonctions de création de fichiers PDF
|
||||
require_once("fonctions_traductions.php");
|
||||
require_once("fonctions_utilitaires.php");
|
||||
require_once(__DIR__.'/fonctions_acces.php'); // Contient les fonctions d'accès au site
|
||||
require_once(__DIR__.'/fonctions_bdd.php'); // Contient les fonctions d'accès aux BDD.
|
||||
require_once(__DIR__.'/fonctions_fichiers.php'); // Contient les fonctions de traitement des répertoires et des fichiers
|
||||
require_once(__DIR__.'/fonctions_ftp.php');
|
||||
require_once(__DIR__.'/fonctions_html.php');
|
||||
require_once(__DIR__.'/fonctions_mail.php'); // Contient les fonctions d'émission des emails
|
||||
require_once(__DIR__.'/fonctions_pdf.php'); // Contient les fonctions de création de fichiers PDF
|
||||
require_once(__DIR__.'/fonctions_traductions.php');
|
||||
require_once(__DIR__.'/fonctions_utilitaires.php');
|
||||
|
||||
|
||||
|
||||
@@ -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']);
|
||||
}
|
||||
+396
-344
@@ -1,344 +1,396 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Initialisation de la session. A appeler avant tout envoi au client.
|
||||
// Reçoit : Rien
|
||||
// Retour : Rien
|
||||
//************************************************************************************************************
|
||||
function Init_session($nom_page)
|
||||
{
|
||||
ini_set('arg_separator.output', '&');
|
||||
ini_set("url_rewriter.tags","a=href,area=href,frame=src,iframe=src,input=src"); // Ces deux lignes sont destinées à faire ajouter autoamtiquement & au lieu de '&' dans la passage des variables de Session (nécessaire pour W3C validator...)
|
||||
|
||||
session_set_cookie_params([
|
||||
'lifetime' => 3600,
|
||||
'path' => '/',
|
||||
'secure' => true,
|
||||
'httponly' => true,
|
||||
'samesite' => 'Lax',
|
||||
]);
|
||||
|
||||
session_start(); // Ouverture de session (avant tout autre envoi au client!!!)
|
||||
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Insertion de l'entête des pages HTML ; essentiellement la partie <header></header>.
|
||||
// Au passage, cette fonction étant la première appelée par chaque page (après l'ouverture
|
||||
// de session obligatoire pour pouvoir accéder aux variables de session), on vérifie si
|
||||
// l'environnement est correctement positionné. Si ce n'est pas le cas, par exemple avec
|
||||
// l'accès à la BDD non établi ou aucune langue sélectionnée, elle renvoit immédiatement
|
||||
// vers le fichier 'index.php' qui s'en chargera.
|
||||
// Reçoit : Rien
|
||||
// Retour : Rien
|
||||
//************************************************************************************************************
|
||||
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...) :
|
||||
if ((!isset($_SESSION['langue'])) OR
|
||||
(!isset($_SESSION['display_menu']))) header('Location:index.php?origine='.basename($_SERVER['SCRIPT_FILENAME']));
|
||||
|
||||
// Entête HTML :
|
||||
echo '<!DOCTYPE html>';
|
||||
|
||||
echo '<html lang="FR">';
|
||||
|
||||
echo '<head>';
|
||||
echo '<meta charset="UTF-8">';
|
||||
echo '<title>ShipHeart - Simplicity is true luxury</title>';
|
||||
echo '<meta name="description" content="'.t("ShipHeart by Koriolan, la première centrale de vie à bord pour les bateaux de plaisance").'" />';
|
||||
echo '<meta name="keywords" content="ShipHeart" />';
|
||||
echo '<meta content="text/html" http-equiv="content-type" />';
|
||||
echo '<meta name="viewport" content="width=device-width, initial-scale=1">';
|
||||
echo '<link rel="icon" type="image/png" href="images/favicon.png" />';
|
||||
|
||||
|
||||
echo "<link href='https://fonts.googleapis.com/css?family=Montserrat' rel='stylesheet'>";
|
||||
echo "<link href='https://fonts.googleapis.com/css2?family=Oswald&display=swap' rel='stylesheet'>";
|
||||
echo "<link rel='stylesheet' href='https://unpkg.com/leaflet@1.9.4/dist/leaflet.css' integrity='sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=' crossorigin=''/>";
|
||||
|
||||
echo "<link rel='stylesheet' href='/vendor/noUiSlider/dist/nouislider.min.css'>";
|
||||
echo "<script src='/vendor/noUiSlider/dist/nouislider.min.js'></script>";
|
||||
|
||||
// gestion des fichiers CSS (et de scripts spécifiques à certains fichiers) :
|
||||
switch(basename($_SERVER['SCRIPT_FILENAME']))
|
||||
{
|
||||
case "administration.php" : { echo '<link rel="stylesheet" type="text/css" media="screen" href="format_administration.css" />'; break; }
|
||||
case "textes.php" : { echo '<link rel="stylesheet" type="text/css" media="screen" href="format_textes.css" />'; break; }
|
||||
case "bateaux.php" : { echo '<link rel="stylesheet" type="text/css" media="screen" href="format_bateaux.css" />'; break; }
|
||||
case "cartes.php" : { echo '<link rel="stylesheet" type="text/css" media="screen" href="format_cartes.css" />'; break; }
|
||||
case "mentions_legales.php" : { echo '<link rel="stylesheet" type="text/css" media="screen" href="format_mentions_legales.css" />'; break; }
|
||||
case "shipmembers.php" : { echo '<link rel="stylesheet" type="text/css" media="screen" href="format_shipmembers.css" />'; break; }
|
||||
case "uploads.php" : { echo '<link rel="stylesheet" type="text/css" media="screen" href="format_uploads.css" />'; break; }
|
||||
case "versions.php" : { echo '<link rel="stylesheet" type="text/css" media="screen" href="format_versions.css" />'; break; }
|
||||
}
|
||||
|
||||
echo '<link rel="stylesheet" type="text/css" href="/vendor/bootstrap/bootstrap.min.css" />'; // CSS de Bootstrap
|
||||
echo '<link rel="stylesheet" type="text/css" media="screen" href="format.css" />'; // CSS général, tous écrans.
|
||||
echo '<link rel="stylesheet" type="text/css" media="screen and (max-device-width : 667px)" href="format__telephone.css" />'; // CSS pour les petits écrans (doit être placé à la fin car il override les CSS globaux)
|
||||
|
||||
// Chargement de srcipts JS généraux :
|
||||
echo '<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>'; // Pour Google Charts (graphiques)
|
||||
echo '<script src="/vendor/jQuery/jquery-3.6.0.min.js"></script>';
|
||||
|
||||
|
||||
|
||||
|
||||
echo '</head>';
|
||||
|
||||
echo '<body>';
|
||||
}
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Insertion de l'entête des pages avec l'affichage du bandeau de titre et les menus.
|
||||
// Puis affichage des messages d'erreur et d'information en les marquant de façon différenciée
|
||||
// selon que le menu est déployé ou non et/ou que le message d'erreur existe et/ou que le
|
||||
// message d'information existe.
|
||||
// Reçoit : Les message d'erreur et le message d'information (de plus, on retrouve le nom du fichier via les variables du serveur)
|
||||
// Retour : Rien
|
||||
//************************************************************************************************************
|
||||
function Entete_page($message_erreur, $message_information)
|
||||
{
|
||||
|
||||
$nom_page = basename($_SERVER['SCRIPT_FILENAME']);
|
||||
|
||||
// Détermination de la nouvelle langue par rapport à l'actuelle :
|
||||
if ($_SESSION['langue'] == "FR") $new_langue = "EN";
|
||||
else $new_langue = "FR";
|
||||
|
||||
|
||||
echo '<div id="entete">';
|
||||
|
||||
//----------------------------------
|
||||
// Bandeau gauche :
|
||||
echo '<div id="logo_home">
|
||||
<a id="home" href="">
|
||||
<a href="shipmembers.php" style="padding: 0;" id="logo_heart_a" title="'.t("Retour à l'accueil").'">
|
||||
<div id="logo_heart"> </div>
|
||||
<div id="logo_texte"> </div>
|
||||
</a>
|
||||
</a>
|
||||
</div>';
|
||||
|
||||
// echo '<div id="menu_mobile"> </div> ';
|
||||
// echo '<div id="nav_bar_global" style="display: none;">';
|
||||
|
||||
//----------------------------------
|
||||
// Bandeau droit :
|
||||
echo '<div id="navbar_right">';
|
||||
|
||||
//----------------------------------
|
||||
// Bouton LANGUE :
|
||||
echo '<div id="flag_lang">';
|
||||
echo '<a class="'.$new_langue.'_acc" title="'.t("Switch to English...").'" href="'.$nom_page.'?action=changement_langue&langue='.$new_langue.'">
|
||||
</a>';
|
||||
echo '</div>';
|
||||
|
||||
//----------------------------------
|
||||
// Bouton SHIPMEMBER ACCESS :
|
||||
echo '<div id="logo_shipmember">';
|
||||
echo '<div id="shipmember">';
|
||||
if ($_SESSION['acces_valide'])
|
||||
{
|
||||
echo '<a title="'.t("Accès validé pour ").' '.$_SESSION['shipmember']['Prenom'].'" href="shipmembers.php?action=navigation&destination=Accueil">
|
||||
<span class="acces_valide">'.substr($_SESSION['shipmember']['Prenom'],0,1).'</span>
|
||||
</a>';
|
||||
}
|
||||
// else echo '<a title="'.$_SESSION['textes']['fonctions']['entete']['ligne_icones']['shipmember_a_title'].'" href="shipmembers.php?action=navigation&destination=Accueil"> </a>';
|
||||
echo '</div>';
|
||||
echo "</div>";
|
||||
|
||||
echo '</div>';
|
||||
|
||||
|
||||
echo '</div>';
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
// Menu afficher / masquer -- Mobile
|
||||
//--------------------------------------------------------------------------------------------
|
||||
echo '<script>
|
||||
window.onload = function () {
|
||||
pro = document.getElementsByClassName("portail_pro");
|
||||
par = document.getElementsByClassName("portail_par");
|
||||
if ($(window).width() > 850) {
|
||||
if (pro.length > 0) { for (i = 0; i < pro.length ; i++){ pro[i].hidden=true; } document.getElementById(\'par_p\').hidden = true }
|
||||
if (par.length > 0) { for (i = 0; i < par.length ; i++){ par[i].hidden=true; } document.getElementById(\'pro_p\').hidden = true }
|
||||
document.getElementById(\'img_type\').hidden= false;
|
||||
document.getElementById(\'logo_heart_a\').href = "bienvenue.php";
|
||||
} else {
|
||||
if (pro.length > 0) { for (i = 0; i < pro.length ; i++){ pro[i].hidden=false; } document.getElementById(\'par_p\').hidden = false }
|
||||
if (par.length > 0) { for (i = 0; i < par.length ; i++){ par[i].hidden=false; } document.getElementById(\'pro_p\').hidden = false }
|
||||
document.getElementById(\'img_type\').hidden= true;
|
||||
document.getElementById(\'logo_heart_a\').href = "accueil.php";
|
||||
}
|
||||
} ;
|
||||
$(document).ready(function(){
|
||||
function menu_control(){
|
||||
hidden_div = document.getElementById("nav_bar_global").style.display;
|
||||
hidden_div.replace(/[\u200B-\u200D\uFEFF]/g, \'\');
|
||||
|
||||
if (hidden_div == "block") hidden_div = "none";
|
||||
else if (hidden_div == "none") hidden_div = "block";
|
||||
document.getElementById("nav_bar_global").style.display=hidden_div;
|
||||
};
|
||||
$("#menu_mobile").click(menu_control);
|
||||
});
|
||||
|
||||
|
||||
window.addEventListener(\'click\', function(e){
|
||||
if (!document.getElementById(\'nav_bar_global\').contains(e.target) && !document.getElementById(\'menu_mobile\').contains(e.target) ){
|
||||
document.getElementById("nav_bar_global").style.display="none";
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener(\'touchstart\', function(e){
|
||||
if (!document.getElementById(\'nav_bar_global\').contains(e.target) && !document.getElementById(\'menu_mobile\').contains(e.target) ){
|
||||
document.getElementById("nav_bar_global").style.display="none";
|
||||
}
|
||||
});
|
||||
|
||||
$(window).resize(function() {
|
||||
pro = document.getElementsByClassName("portail_pro");
|
||||
par = document.getElementsByClassName("portail_par");
|
||||
if ($(this).width() > 850) {
|
||||
if (pro.length > 0) { for (i = 0; i < pro.length ; i++){ pro[i].hidden=true; } document.getElementById(\'par_p\').hidden = true }
|
||||
if (par.length > 0) { for (i = 0; i < par.length ; i++){ par[i].hidden=true; } document.getElementById(\'pro_p\').hidden = true }
|
||||
document.getElementById(\'img_type\').hidden= false;
|
||||
document.getElementById(\'logo_heart_a\').href = "bienvenue.php";
|
||||
} else {
|
||||
if (pro.length > 0) { for (i = 0; i < pro.length ; i++){ pro[i].hidden=false; } document.getElementById(\'par_p\').hidden = false }
|
||||
if (par.length > 0) { for (i = 0; i < par.length ; i++){ par[i].hidden=false; } document.getElementById(\'pro_p\').hidden = false }
|
||||
document.getElementById(\'img_type\').hidden= true;
|
||||
document.getElementById(\'logo_heart_a\').href = "accueil.php";
|
||||
}
|
||||
});
|
||||
</script>';
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
// Script d'affichage/masquage du menu :
|
||||
//--------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
// Affichage des messages d'erreur et d'info sous le menu :
|
||||
//--------------------------------------------------------------------------------------------
|
||||
if (!PRODUCTION) $message_erreur .= "/!\ Base de données de test [".BDD_DATABASE."]<br />";
|
||||
// else $message_erreur .= "Base de données de production [".BDD_DATABASE."]<br />";
|
||||
|
||||
if ($message_erreur != "") echo '<div class="message_erreur">'.$message_erreur.'</div>';
|
||||
if ($message_information != "") echo '<div class="message_information">'.$message_information.'</div>';
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Insertion du pied de page
|
||||
// Reçoit : Rien (mais on retrouve le nom du fichier via les variables du serveur)
|
||||
// Retour : Rien
|
||||
//************************************************************************************************************
|
||||
function Pied_de_page()
|
||||
{
|
||||
$nom_page = basename($_SERVER['SCRIPT_FILENAME']);
|
||||
|
||||
// echo "<script src='https://unpkg.com/leaflet@1.9.4/dist/leaflet.js' integrity='sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=' crossorigin=''> </script>";
|
||||
|
||||
echo '<div id="pied_de_page" style="display: none;">';
|
||||
echo '<div class="gauche" id="gauche" style="height: 210px;">';
|
||||
echo '<div class="marque" id="marque">
|
||||
|
||||
<p id="marque_texte">'.t("ShipHeart ™ est une marque de Koriolan").'</p>
|
||||
|
||||
<div class="signature" id="signature">
|
||||
<a style="padding: 0;" title="'.t("Accéder à notre site Koriolan").'" href="https://koriolan.tech/" target="_blank">
|
||||
<img src="images/logo_koriolan_rvb.png">
|
||||
</a>
|
||||
</div>';
|
||||
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
|
||||
echo '<div class="droite" id="droite" style="height: 210px;">';
|
||||
|
||||
echo '<div class="mentions_legales" id="mentions_legales">';
|
||||
|
||||
if ($nom_page != "mentions_legales.php")
|
||||
{
|
||||
echo '<a title="'.t("Mentions légales").'" href="mentions_legales.php">
|
||||
'.t("Mentions légales").'
|
||||
</a>';
|
||||
}
|
||||
else
|
||||
{
|
||||
echo '<a title="'.t("Retour").'" href="shipmembers.php">
|
||||
'.t("Retour").'
|
||||
</a>';
|
||||
}
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
|
||||
echo '<div id="pied_de_page_mobile" >';
|
||||
echo '</div>';
|
||||
|
||||
|
||||
|
||||
//==================================================================================
|
||||
// Script JS pour pieds de page :
|
||||
?><script>
|
||||
|
||||
function footer ()
|
||||
{
|
||||
if (window.innerWidth <= 850) //Footer mobile :
|
||||
{
|
||||
document.getElementById('pied_de_page_mobile').appendChild(document.getElementById('mentions_legales'));
|
||||
document.getElementById('pied_de_page_mobile').appendChild(document.getElementById('marque_texte'));
|
||||
document.getElementById('pied_de_page_mobile').appendChild(document.getElementById('signature'));
|
||||
}
|
||||
else //Footer "normal" :
|
||||
{
|
||||
document.getElementById('droite').appendChild(document.getElementById('mentions_legales'));
|
||||
document.getElementById('marque').appendChild(document.getElementById('marque_texte'));
|
||||
document.getElementById('marque').appendChild(document.getElementById('signature'));
|
||||
}
|
||||
}
|
||||
|
||||
document.onreadystatechange = function()
|
||||
{
|
||||
footer();
|
||||
page = "<?php echo $nom_page ?>";
|
||||
if (page == "faq.php")
|
||||
{
|
||||
show_hide('0');
|
||||
|
||||
for(var k = 0; k < reponses.length; k++)
|
||||
{
|
||||
document.getElementById(reponses[k].id).hidden=true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('resize', function(event)
|
||||
{
|
||||
footer();
|
||||
});
|
||||
|
||||
</script><?php
|
||||
// Fin du script JS
|
||||
//====================================================================================
|
||||
|
||||
|
||||
echo '</body>';
|
||||
|
||||
echo '</html>';
|
||||
|
||||
} // Fin de la fonction Pied_de_page()
|
||||
|
||||
|
||||
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Initialisation de la session. A appeler avant tout envoi au client.
|
||||
// Reçoit : Rien
|
||||
// Retour : Rien
|
||||
//************************************************************************************************************
|
||||
function Init_session($nom_page)
|
||||
{
|
||||
ini_set('arg_separator.output', '&');
|
||||
ini_set("url_rewriter.tags","a=href,area=href,frame=src,iframe=src,input=src"); // Ces deux lignes sont destinées à faire ajouter autoamtiquement & 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([
|
||||
'lifetime' => 3600,
|
||||
'path' => '/',
|
||||
'secure' => true,
|
||||
'httponly' => true,
|
||||
'samesite' => 'Lax',
|
||||
]);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Insertion de l'entête des pages HTML ; essentiellement la partie <header></header>.
|
||||
// Au passage, cette fonction étant la première appelée par chaque page (après l'ouverture
|
||||
// de session obligatoire pour pouvoir accéder aux variables de session), on vérifie si
|
||||
// l'environnement est correctement positionné. Si ce n'est pas le cas, par exemple avec
|
||||
// l'accès à la BDD non établi ou aucune langue sélectionnée, elle renvoit immédiatement
|
||||
// vers le fichier 'index.php' qui s'en chargera.
|
||||
// Reçoit : Rien
|
||||
// Retour : Rien
|
||||
//************************************************************************************************************
|
||||
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...) :
|
||||
if ((!isset($_SESSION['langue'])) OR
|
||||
(!isset($_SESSION['display_menu'])))
|
||||
{
|
||||
header('Location:index.php?origine='.basename($_SERVER['SCRIPT_FILENAME']));
|
||||
exit();
|
||||
}
|
||||
|
||||
// Entête HTML :
|
||||
echo '<!DOCTYPE html>';
|
||||
|
||||
echo '<html lang="FR">';
|
||||
|
||||
echo '<head>';
|
||||
echo '<meta charset="UTF-8">';
|
||||
echo '<title>ShipHeart - Simplicity is true luxury</title>';
|
||||
echo '<meta name="description" content="'.t("ShipHeart by Koriolan, la première centrale de vie à bord pour les bateaux de plaisance").'" />';
|
||||
echo '<meta name="keywords" content="ShipHeart" />';
|
||||
echo '<meta content="text/html" http-equiv="content-type" />';
|
||||
echo '<meta name="viewport" content="width=device-width, initial-scale=1">';
|
||||
echo '<link rel="icon" type="image/png" href="images/favicon.png" />';
|
||||
|
||||
|
||||
echo "<link href='https://fonts.googleapis.com/css?family=Montserrat' rel='stylesheet'>";
|
||||
echo "<link href='https://fonts.googleapis.com/css2?family=Oswald&display=swap' rel='stylesheet'>";
|
||||
echo "<link rel='stylesheet' href='https://unpkg.com/leaflet@1.9.4/dist/leaflet.css' integrity='sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=' crossorigin=''/>";
|
||||
|
||||
echo "<link rel='stylesheet' href='/vendor/noUiSlider/dist/nouislider.min.css'>";
|
||||
echo "<script src='/vendor/noUiSlider/dist/nouislider.min.js'></script>";
|
||||
|
||||
// gestion des fichiers CSS (et de scripts spécifiques à certains fichiers) :
|
||||
switch(basename($_SERVER['SCRIPT_FILENAME']))
|
||||
{
|
||||
case "administration.php" : { echo '<link rel="stylesheet" type="text/css" media="screen" href="format_administration.css" />'; break; }
|
||||
case "textes.php" : { echo '<link rel="stylesheet" type="text/css" media="screen" href="format_textes.css" />'; break; }
|
||||
case "bateaux.php" : { echo '<link rel="stylesheet" type="text/css" media="screen" href="format_bateaux.css" />'; break; }
|
||||
case "cartes.php" : { echo '<link rel="stylesheet" type="text/css" media="screen" href="format_cartes.css" />'; break; }
|
||||
case "mentions_legales.php" : { echo '<link rel="stylesheet" type="text/css" media="screen" href="format_mentions_legales.css" />'; break; }
|
||||
case "shipmembers.php" : { echo '<link rel="stylesheet" type="text/css" media="screen" href="format_shipmembers.css" />'; break; }
|
||||
case "uploads.php" : { echo '<link rel="stylesheet" type="text/css" media="screen" href="format_uploads.css" />'; break; }
|
||||
case "versions.php" : { echo '<link rel="stylesheet" type="text/css" media="screen" href="format_versions.css" />'; break; }
|
||||
}
|
||||
|
||||
echo '<link rel="stylesheet" type="text/css" href="/vendor/bootstrap/bootstrap.min.css" />'; // CSS de Bootstrap
|
||||
echo '<link rel="stylesheet" type="text/css" media="screen" href="format.css" />'; // CSS général, tous écrans.
|
||||
echo '<link rel="stylesheet" type="text/css" media="screen and (max-device-width : 667px)" href="format__telephone.css" />'; // CSS pour les petits écrans (doit être placé à la fin car il override les CSS globaux)
|
||||
|
||||
// Chargement de srcipts JS généraux :
|
||||
echo '<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>'; // Pour Google Charts (graphiques)
|
||||
echo '<script src="/vendor/jQuery/jquery-3.6.0.min.js"></script>';
|
||||
|
||||
|
||||
|
||||
|
||||
echo '</head>';
|
||||
|
||||
echo '<body>';
|
||||
}
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Insertion de l'entête des pages avec l'affichage du bandeau de titre et les menus.
|
||||
// Puis affichage des messages d'erreur et d'information en les marquant de façon différenciée
|
||||
// selon que le menu est déployé ou non et/ou que le message d'erreur existe et/ou que le
|
||||
// message d'information existe.
|
||||
// Reçoit : Les message d'erreur et le message d'information (de plus, on retrouve le nom du fichier via les variables du serveur)
|
||||
// Retour : Rien
|
||||
//************************************************************************************************************
|
||||
function Entete_page($message_erreur, $message_information)
|
||||
{
|
||||
|
||||
$nom_page = basename($_SERVER['SCRIPT_FILENAME']);
|
||||
|
||||
// Détermination de la nouvelle langue par rapport à l'actuelle :
|
||||
if ($_SESSION['langue'] == "FR") $new_langue = "EN";
|
||||
else $new_langue = "FR";
|
||||
|
||||
|
||||
echo '<div id="entete">';
|
||||
|
||||
//----------------------------------
|
||||
// Bandeau gauche :
|
||||
echo '<div id="logo_home">
|
||||
<a id="home" href="">
|
||||
<a href="shipmembers.php" style="padding: 0;" id="logo_heart_a" title="'.t("Retour à l'accueil").'">
|
||||
<div id="logo_heart"> </div>
|
||||
<div id="logo_texte"> </div>
|
||||
</a>
|
||||
</a>
|
||||
</div>';
|
||||
|
||||
// echo '<div id="menu_mobile"> </div> ';
|
||||
// echo '<div id="nav_bar_global" style="display: none;">';
|
||||
|
||||
//----------------------------------
|
||||
// Bandeau droit :
|
||||
echo '<div id="navbar_right">';
|
||||
|
||||
//----------------------------------
|
||||
// Bouton LANGUE :
|
||||
echo '<div id="flag_lang">';
|
||||
echo '<a class="'.$new_langue.'_acc" title="'.t("Switch to English...").'" href="'.$nom_page.'?action=changement_langue&langue='.$new_langue.'">
|
||||
</a>';
|
||||
echo '</div>';
|
||||
|
||||
//----------------------------------
|
||||
// Bouton SHIPMEMBER ACCESS :
|
||||
echo '<div id="logo_shipmember">';
|
||||
echo '<div id="shipmember">';
|
||||
if ($_SESSION['acces_valide'])
|
||||
{
|
||||
echo '<a title="'.t("Accès validé pour ").' '.$_SESSION['shipmember']['Prenom'].'" href="shipmembers.php?action=navigation&destination=Accueil">
|
||||
<span class="acces_valide">'.substr($_SESSION['shipmember']['Prenom'],0,1).'</span>
|
||||
</a>';
|
||||
}
|
||||
// else echo '<a title="'.$_SESSION['textes']['fonctions']['entete']['ligne_icones']['shipmember_a_title'].'" href="shipmembers.php?action=navigation&destination=Accueil"> </a>';
|
||||
echo '</div>';
|
||||
echo "</div>";
|
||||
|
||||
echo '</div>';
|
||||
|
||||
|
||||
echo '</div>';
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
// Menu afficher / masquer -- Mobile
|
||||
//--------------------------------------------------------------------------------------------
|
||||
echo '<script>
|
||||
window.onload = function () {
|
||||
pro = document.getElementsByClassName("portail_pro");
|
||||
par = document.getElementsByClassName("portail_par");
|
||||
if ($(window).width() > 850) {
|
||||
if (pro.length > 0) { for (i = 0; i < pro.length ; i++){ pro[i].hidden=true; } document.getElementById(\'par_p\').hidden = true }
|
||||
if (par.length > 0) { for (i = 0; i < par.length ; i++){ par[i].hidden=true; } document.getElementById(\'pro_p\').hidden = true }
|
||||
document.getElementById(\'img_type\').hidden= false;
|
||||
document.getElementById(\'logo_heart_a\').href = "bienvenue.php";
|
||||
} else {
|
||||
if (pro.length > 0) { for (i = 0; i < pro.length ; i++){ pro[i].hidden=false; } document.getElementById(\'par_p\').hidden = false }
|
||||
if (par.length > 0) { for (i = 0; i < par.length ; i++){ par[i].hidden=false; } document.getElementById(\'pro_p\').hidden = false }
|
||||
document.getElementById(\'img_type\').hidden= true;
|
||||
document.getElementById(\'logo_heart_a\').href = "accueil.php";
|
||||
}
|
||||
} ;
|
||||
$(document).ready(function(){
|
||||
function menu_control(){
|
||||
hidden_div = document.getElementById("nav_bar_global").style.display;
|
||||
hidden_div.replace(/[\u200B-\u200D\uFEFF]/g, \'\');
|
||||
|
||||
if (hidden_div == "block") hidden_div = "none";
|
||||
else if (hidden_div == "none") hidden_div = "block";
|
||||
document.getElementById("nav_bar_global").style.display=hidden_div;
|
||||
};
|
||||
$("#menu_mobile").click(menu_control);
|
||||
});
|
||||
|
||||
|
||||
window.addEventListener(\'click\', function(e){
|
||||
if (!document.getElementById(\'nav_bar_global\').contains(e.target) && !document.getElementById(\'menu_mobile\').contains(e.target) ){
|
||||
document.getElementById("nav_bar_global").style.display="none";
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener(\'touchstart\', function(e){
|
||||
if (!document.getElementById(\'nav_bar_global\').contains(e.target) && !document.getElementById(\'menu_mobile\').contains(e.target) ){
|
||||
document.getElementById("nav_bar_global").style.display="none";
|
||||
}
|
||||
});
|
||||
|
||||
$(window).resize(function() {
|
||||
pro = document.getElementsByClassName("portail_pro");
|
||||
par = document.getElementsByClassName("portail_par");
|
||||
if ($(this).width() > 850) {
|
||||
if (pro.length > 0) { for (i = 0; i < pro.length ; i++){ pro[i].hidden=true; } document.getElementById(\'par_p\').hidden = true }
|
||||
if (par.length > 0) { for (i = 0; i < par.length ; i++){ par[i].hidden=true; } document.getElementById(\'pro_p\').hidden = true }
|
||||
document.getElementById(\'img_type\').hidden= false;
|
||||
document.getElementById(\'logo_heart_a\').href = "bienvenue.php";
|
||||
} else {
|
||||
if (pro.length > 0) { for (i = 0; i < pro.length ; i++){ pro[i].hidden=false; } document.getElementById(\'par_p\').hidden = false }
|
||||
if (par.length > 0) { for (i = 0; i < par.length ; i++){ par[i].hidden=false; } document.getElementById(\'pro_p\').hidden = false }
|
||||
document.getElementById(\'img_type\').hidden= true;
|
||||
document.getElementById(\'logo_heart_a\').href = "accueil.php";
|
||||
}
|
||||
});
|
||||
</script>';
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
// Script d'affichage/masquage du menu :
|
||||
//--------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
// Affichage des messages d'erreur et d'info sous le menu :
|
||||
//--------------------------------------------------------------------------------------------
|
||||
if (!PRODUCTION) $message_erreur .= "/!\ Base de données de test [".BDD_DATABASE."]<br />";
|
||||
// else $message_erreur .= "Base de données de production [".BDD_DATABASE."]<br />";
|
||||
|
||||
if ($message_erreur != "") echo '<div class="message_erreur">'.$message_erreur.'</div>';
|
||||
if ($message_information != "") echo '<div class="message_information">'.$message_information.'</div>';
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Insertion du pied de page
|
||||
// Reçoit : Rien (mais on retrouve le nom du fichier via les variables du serveur)
|
||||
// Retour : Rien
|
||||
//************************************************************************************************************
|
||||
function Pied_de_page()
|
||||
{
|
||||
$nom_page = basename($_SERVER['SCRIPT_FILENAME']);
|
||||
|
||||
// echo "<script src='https://unpkg.com/leaflet@1.9.4/dist/leaflet.js' integrity='sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=' crossorigin=''> </script>";
|
||||
|
||||
echo '<div id="pied_de_page" style="display: none;">';
|
||||
echo '<div class="gauche" id="gauche" style="height: 210px;">';
|
||||
echo '<div class="marque" id="marque">
|
||||
|
||||
<p id="marque_texte">'.t("ShipHeart ™ est une marque de Koriolan").'</p>
|
||||
|
||||
<div class="signature" id="signature">
|
||||
<a style="padding: 0;" title="'.t("Accéder à notre site Koriolan").'" href="https://koriolan.tech/" target="_blank">
|
||||
<img src="images/logo_koriolan_rvb.png">
|
||||
</a>
|
||||
</div>';
|
||||
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
|
||||
echo '<div class="droite" id="droite" style="height: 210px;">';
|
||||
|
||||
echo '<div class="mentions_legales" id="mentions_legales">';
|
||||
|
||||
if ($nom_page != "mentions_legales.php")
|
||||
{
|
||||
echo '<a title="'.t("Mentions légales").'" href="mentions_legales.php">
|
||||
'.t("Mentions légales").'
|
||||
</a>';
|
||||
}
|
||||
else
|
||||
{
|
||||
echo '<a title="'.t("Retour").'" href="shipmembers.php">
|
||||
'.t("Retour").'
|
||||
</a>';
|
||||
}
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
|
||||
echo '<div id="pied_de_page_mobile" >';
|
||||
echo '</div>';
|
||||
|
||||
|
||||
|
||||
//==================================================================================
|
||||
// Script JS pour pieds de page :
|
||||
?><script>
|
||||
|
||||
function footer ()
|
||||
{
|
||||
if (window.innerWidth <= 850) //Footer mobile :
|
||||
{
|
||||
document.getElementById('pied_de_page_mobile').appendChild(document.getElementById('mentions_legales'));
|
||||
document.getElementById('pied_de_page_mobile').appendChild(document.getElementById('marque_texte'));
|
||||
document.getElementById('pied_de_page_mobile').appendChild(document.getElementById('signature'));
|
||||
}
|
||||
else //Footer "normal" :
|
||||
{
|
||||
document.getElementById('droite').appendChild(document.getElementById('mentions_legales'));
|
||||
document.getElementById('marque').appendChild(document.getElementById('marque_texte'));
|
||||
document.getElementById('marque').appendChild(document.getElementById('signature'));
|
||||
}
|
||||
}
|
||||
|
||||
document.onreadystatechange = function()
|
||||
{
|
||||
footer();
|
||||
page = "<?php echo $nom_page ?>";
|
||||
if (page == "faq.php")
|
||||
{
|
||||
show_hide('0');
|
||||
|
||||
for(var k = 0; k < reponses.length; k++)
|
||||
{
|
||||
document.getElementById(reponses[k].id).hidden=true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('resize', function(event)
|
||||
{
|
||||
footer();
|
||||
});
|
||||
|
||||
</script><?php
|
||||
// Fin du script JS
|
||||
//====================================================================================
|
||||
|
||||
|
||||
echo '</body>';
|
||||
|
||||
echo '</html>';
|
||||
|
||||
} // Fin de la fonction Pied_de_page()
|
||||
|
||||
|
||||
|
||||
|
||||
+91
-99
@@ -251,92 +251,9 @@ class MYPDF2 extends TCPDF {
|
||||
|
||||
|
||||
//********************************************************************************************************************************
|
||||
// Fonction : Génère le document PDF à partir des données reçues en paramètres
|
||||
// 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.
|
||||
// Fonction : URL d'activation d'un code d'invitation, 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).
|
||||
// Reçoit : le code d'accès
|
||||
// Reçoit : le code d'invitation
|
||||
// Retour : l'URL complète
|
||||
//********************************************************************************************************************************
|
||||
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);
|
||||
}
|
||||
|
||||
function generateCode($code){
|
||||
$tempDir = "temp/CodeQR/";
|
||||
|
||||
$codeContents = Url_activation_code_acces($code);
|
||||
|
||||
$fileName = $code.'.png';
|
||||
|
||||
$pngAbsoluteFilePath = $tempDir.$fileName;
|
||||
$urlRelativeFilePath = $tempDir.$fileName;
|
||||
|
||||
// generating
|
||||
if (!file_exists($pngAbsoluteFilePath)) {
|
||||
QRcode::png($codeContents, $pngAbsoluteFilePath);
|
||||
}
|
||||
return $urlRelativeFilePath;
|
||||
//********************************************************************************************************************************
|
||||
// Fonction : Image PNG d'un QR code, produite EN MÉMOIRE (aucun fichier temporaire : l'ancienne version écrivait le QR code
|
||||
// et le PDF dans html/temp/, donc dans la partie publique du site - synthèse §47).
|
||||
// Reçoit : le texte à encoder
|
||||
// Retour : le contenu binaire de l'image PNG
|
||||
//********************************************************************************************************************************
|
||||
function Qr_code_png($texte)
|
||||
{
|
||||
ob_start();
|
||||
QRcode::png($texte, false, QR_ECLEVEL_M, 8, 2); // false = sortie standard, capturée par le tampon
|
||||
$png = ob_get_clean();
|
||||
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');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user