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
+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
// 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');
}