Import initial du site ship2net.fr : pages PHP, config, traductions t(), composer.json
This commit is contained in:
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
define("REPERTOIRE_HOME", "/home/koriolan/ship2net");
|
||||
|
||||
require_once("confidentiel.php");
|
||||
|
||||
|
||||
//=====================================================================
|
||||
// Paramètres du site de prod ou de test :
|
||||
if (PRODUCTION)
|
||||
{
|
||||
define("BDD_HOST", BDD_PROD_HOST);
|
||||
define("BDD_USER", BDD_PROD_USER);
|
||||
define("BDD_DATABASE", BDD_PROD_DATABASE);
|
||||
define("BDD_PASSWORD", BDD_PROD_PASSWORD);
|
||||
define("SHOW_DEBUG", false);
|
||||
|
||||
define("BDD_BATEAUX_HOST", BDD_BATEAUX_PROD_HOST);
|
||||
define("BDD_BATEAUX_PORT", BDD_BATEAUX_PROD_PORT);
|
||||
define("BDD_BATEAUX_USER", BDD_BATEAUX_PROD_USER);
|
||||
define("BDD_BATEAUX_PASSWORD", BDD_BATEAUX_PROD_PASSWORD);
|
||||
define("BDD_BATEAUX_DATABASE_PREFIXE", BDD_BATEAUX_PROD_DATABASE_PREFIXE);
|
||||
}
|
||||
else
|
||||
{
|
||||
define("BDD_HOST", BDD_DEV_HOST);
|
||||
define("BDD_USER", BDD_DEV_USER);
|
||||
define("BDD_DATABASE", BDD_DEV_DATABASE);
|
||||
define("BDD_PASSWORD", BDD_DEV_PASSWORD);
|
||||
define("SHOW_DEBUG", true);
|
||||
|
||||
define("BDD_BATEAUX_HOST", BDD_BATEAUX_DEV_HOST);
|
||||
define("BDD_BATEAUX_PORT", BDD_BATEAUX_DEV_PORT);
|
||||
define("BDD_BATEAUX_USER", BDD_BATEAUX_DEV_USER);
|
||||
define("BDD_BATEAUX_PASSWORD", BDD_BATEAUX_DEV_PASSWORD);
|
||||
define("BDD_BATEAUX_DATABASE_PREFIXE", BDD_BATEAUX_DEV_DATABASE_PREFIXE);
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================
|
||||
// Niveaux d'accès :
|
||||
define("NIVEAU_MINI_ACCES_ADMINISTATEUR", 25);
|
||||
define("NIVEAU_EDITEUR_ACCES_ADMINISTATEUR", 50);
|
||||
|
||||
|
||||
//=====================================================================
|
||||
// Types d'utilisateurs :
|
||||
define("TYPE_UTILISATEUR_INCONNU", 0);
|
||||
define("TYPE_UTILISATEUR_PARTICULIER", 1);
|
||||
define("TYPE_UTILISATEUR_PROFESSIONNEL", 2);
|
||||
|
||||
|
||||
//=====================================================================
|
||||
// Informations générales :
|
||||
define("NOM_SITE", "ShipHeart");
|
||||
define("TITRE_SITE", "ShipHeart - Simplicity is true luxury");
|
||||
define("MARQUE", "ShipHeart ™");
|
||||
define("SOCIETE", "Koriolan");
|
||||
define("ANNEE_CREATION", 2019);
|
||||
|
||||
|
||||
//=====================================================================
|
||||
// Paramètres de traitement des données, maps...
|
||||
define ("DATE_SEUIL_1", 90);
|
||||
define ("DATE_SEUIL_2", 180);
|
||||
define ("CLE_PRIMAIRE_BATEAU_DEMO", 25); // Bateau "DEMO". Les données de ce bateau sont décalées dans le temps chaque matin à 00hxx.
|
||||
|
||||
|
||||
//=====================================================================
|
||||
// Répertoires et fichiers :
|
||||
define("REPERTOIRE_TEMP", REPERTOIRE_HOME."/temp"); // Pas de '/' de terminaison
|
||||
|
||||
if (PRODUCTION)
|
||||
{
|
||||
define("REPERTOIRE_BATEAUX", REPERTOIRE_HOME."/bateaux"); // Pas de '/' de terminaison
|
||||
define("REPERTOIRE_BATEAUX_ARCHIVES", REPERTOIRE_HOME."/bateaux_archives"); // Pas de '/' de terminaison
|
||||
define("REPERTOIRE_FICHIERS_CRON", REPERTOIRE_HOME."/cron/prod"); // Pas de '/' de terminaison
|
||||
define("REPERTOIRE_LOGS", REPERTOIRE_HOME."/logs/prod"); // Pas de '/' de terminaison
|
||||
define("NB_JOURS_AVANT_SUPPRESSION_FICHIERS_ARCHIVES", 90);
|
||||
define("NB_JOURS_AVANT_SUPPRESSION_FICHIERS_ANOMALIES", 180);
|
||||
define("NB_JOURS_AVANT_SUPPRESSION_FICHIERS_LOGS", 90);
|
||||
}
|
||||
else
|
||||
{
|
||||
define("REPERTOIRE_BATEAUX", REPERTOIRE_HOME."/bateaux_dev"); // Pas de '/' de terminaison
|
||||
define("REPERTOIRE_BATEAUX_ARCHIVES", REPERTOIRE_HOME."/bateaux_dev_archives"); // Pas de '/' de terminaison
|
||||
define("REPERTOIRE_FICHIERS_CRON", REPERTOIRE_HOME."/cron/dev"); // Pas de '/' de terminaison
|
||||
define("REPERTOIRE_LOGS", REPERTOIRE_HOME."/logs/dev"); // Pas de '/' de terminaison
|
||||
define("NB_JOURS_AVANT_SUPPRESSION_FICHIERS_ARCHIVES", 30);
|
||||
define("NB_JOURS_AVANT_SUPPRESSION_FICHIERS_ANOMALIES", 30);
|
||||
define("NB_JOURS_AVANT_SUPPRESSION_FICHIERS_LOGS", 30);
|
||||
}
|
||||
|
||||
define("REPERTOIRE_VERSIONS", REPERTOIRE_HOME."/versions"); // Pas de '/' de terminaison
|
||||
define("REPERTOIRE_VERSIONS_SHIPHEART", REPERTOIRE_VERSIONS.'/shipheart'); // Pas de '/' de terminaison
|
||||
|
||||
define("REPERTOIRE_LOGS_UPLOADS", REPERTOIRE_LOGS."/uploads"); // Pas de '/' de terminaison
|
||||
define("REPERTOIRE_LOGS_SYNTHESE", REPERTOIRE_LOGS."/synthese"); // Pas de '/' de terminaison
|
||||
|
||||
define("PREFIXE_REPERTOIRE_BATEAU_ARCHIVES", "bateau_"); // La clé primaire du bateau dans TB_Bateaux est ajouté pour former le nom du répertoire du bateau dans 'bateaux_archives' (ou 'bateaux_dev_archives' pour DEV).
|
||||
|
||||
define("SOUS_REPERTOIRE_BATEAU_ANOMALIES", "uploads_anomalies"); // Pas de '/' de terminaison
|
||||
define("SOUS_REPERTOIRE_BATEAU_ARCHIVES", "uploads_ok"); // Pas de '/' de terminaison
|
||||
define("SOUS_REPERTOIRE_BATEAU_HISTORIQUE_BDD", "bdd_historique"); // Pas de '/' de terminaison
|
||||
define("SOUS_REPERTOIRE_BATEAU_TEMP", "temp"); // Pas de '/' de terminaison
|
||||
|
||||
|
||||
define("PREFIXE_FICHIER_SAUVEGARDE_BDD_BATEAU", "sauvegarde_bdd_"); // Le nom de la base de données est ensuite ajouté à la suite, avant le marqueur SQL. Par exemple 'sauvegarde_bdd_Bateau_22.sql'
|
||||
|
||||
|
||||
//=====================================================================
|
||||
// Types de fichiers :
|
||||
define("MARQUEUR_FICHIER_CRYPTE", ".enc");
|
||||
define("MARQUEUR_FICHIER_COMPRESSE", ".gz");
|
||||
define("MARQUEUR_FICHIER_SQL", ".sql");
|
||||
|
||||
|
||||
//=====================================================================
|
||||
// Valeurs mini et maxi :
|
||||
define("MAX_TENTATIVES_CONNEXIONS_BDD", 5);
|
||||
|
||||
define("MIN_LONGUEUR_PRENOM", 1);
|
||||
define("MAX_LONGUEUR_PRENOM", 50);
|
||||
define("MIN_LONGUEUR_NOM", 1);
|
||||
define("MAX_LONGUEUR_NOM", 50);
|
||||
define("MIN_LONGUEUR_RUE", 3);
|
||||
define("MAX_LONGUEUR_RUE", 100);
|
||||
define("MIN_LONGUEUR_CODE_POSTAL", 2);
|
||||
define("MAX_LONGUEUR_CODE_POSTAL", 16);
|
||||
define("MIN_LONGUEUR_VILLE", 1);
|
||||
define("MAX_LONGUEUR_VILLE", 60);
|
||||
define("MIN_LONGUEUR_TELEPHONE", 6);
|
||||
define("MAX_LONGUEUR_TELEPHONE", 24);
|
||||
|
||||
define("MIN_TAILLE_MOTS_DE_PASSE", 6);
|
||||
define("MAX_TAILLE_MOTS_DE_PASSE", 20);
|
||||
|
||||
define("MAX_TAILLE_FICHIER_VERSION", 5000000);
|
||||
|
||||
define ("MAX_BOUCLES_SUPPRESSION_FICHIER_REPERTOIRE", 100); // Nombre maxi d'itérations lors de la suppression des fichiers dans un répertoire (sur un marqueur donné)
|
||||
|
||||
|
||||
//=====================================================================
|
||||
// Types de cartes :
|
||||
define("TYPE_CARTE_COMPAGNON", 0);
|
||||
define("TYPE_CARTE_SP812", 1);
|
||||
define("TYPE_CARTE_SBS1224", 2);
|
||||
define("TYPE_CARTE_SP4AC", 3);
|
||||
define("TYPE_CARTE_SP8DC", 4);
|
||||
|
||||
|
||||
//=====================================================================
|
||||
// Etats d'une carte :
|
||||
define("ETAT_CARTE_INCONNU", 0);
|
||||
define("ETAT_CARTE_OK", 1);
|
||||
define("ETAT_CARTE_EN_PANNE", 2);
|
||||
define("ETAT_CARTE_REBUT", 3);
|
||||
|
||||
|
||||
//=====================================================================
|
||||
// Types et Sous_types d'historique :
|
||||
// A REVOIR COMPLETEMENT DEPUIS LE FICHIER 'gestion_bdd.h' de l'appli en C
|
||||
define ("SYSTEME", 1000);
|
||||
define ("SYSTEME_REINIT", 1001); // Réinitialisation de l'application
|
||||
define ("SYSTEME_ERREUR_MYSQL", 1002);
|
||||
define ("SYSTEME_CONNEXION_USER", 1003);
|
||||
define ("SYSTEME_REINIT_MDP_USER", 1004);
|
||||
define ("SYSTEME_REBOOT", 1005); // Reboot du système
|
||||
define ("SYSTEME_ARRET", 1006); // Arrêt du système (Shutdown -h)
|
||||
define ("SYSTEME_REINIT_BOX", 1007);
|
||||
define ("SYSTEME_TIME_OUT_CONNEXION", 1008);
|
||||
define ("SYSTEME_REINIT_TEIOT", 1009);
|
||||
define ("SYSTEME_DECONNEXION_USER", 1010);
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?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");
|
||||
|
||||
|
||||
@@ -0,0 +1,585 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Ouverture de la BDD
|
||||
// Reçoit : Le nom du Host, du User, son PWd et le nom de la BDD. Les valeurs par défaut sont celles de la base Ship2net qui est l'utilisation générale.
|
||||
// Retour : Rien
|
||||
//************************************************************************************************************
|
||||
function Ouverture_bdd($bdd_host = BDD_HOST, $bdd_user = BDD_USER, $bdd_password = BDD_PASSWORD, $bdd_database = BDD_DATABASE)
|
||||
{
|
||||
|
||||
$_SESSION['db'] = NULL; // SDIR # 289
|
||||
|
||||
// Initialisation des variables d'erreur :
|
||||
for ($i=0; $i<MAX_TENTATIVES_CONNEXIONS_BDD; $i++) $_SESSION['erreurs_connexion_db'][$i] = 0;
|
||||
|
||||
// Tentatives de connexion :
|
||||
for ($i=0; $i<MAX_TENTATIVES_CONNEXIONS_BDD; $i++)
|
||||
{
|
||||
$_SESSION['db'] = new mysqli($bdd_host, $bdd_user, $bdd_password, $bdd_database); // Connexion à MySQL : ("example.com", "user", "password", "database");
|
||||
|
||||
if ($_SESSION['db']->connect_error)
|
||||
{
|
||||
$_SESSION['erreurs_connexion_db'][$i] = $_SESSION['db']->connect_errno;
|
||||
$_SESSION['db'] = NULL;
|
||||
sleep($i+1); // Attente avant de recommencer (en secondes). NB : le délai d'attente augmente à chaque tentative...
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
|
||||
if ($_SESSION['db'] == NULL) // Erreur de la fonction de connexion, malgré plusieurs tentatives :
|
||||
{
|
||||
if (PRODUCTION)
|
||||
{
|
||||
// Préparation du texte d'erreur en dur et dans les 2 langues car si la BDD n'est pas accessible, on aura du mal à aller y chercher les messages d'erreur... :
|
||||
$message_erreur = '<p>Oups ! Une erreur est survenue.</p>
|
||||
<p>Essayez de rafraichir la page mais si le problème persiste, n\'hésitez pas à nous contacter à : '.$_SESSION['Config__Adresse_email_contact'].'</p>
|
||||
<p>NB : Ce message a été automatiquement envoyé aux services techniques de Koriolan pour être traité. <br />Car vous offrir un service irréprochable est notre priorité !</p>';
|
||||
$message_erreur .= '<br />';
|
||||
$message_erreur .= '<p>Oops! An error occurred.</p>
|
||||
<p>Try to refresh the page but if the problem persists, please contact us at : '.$_SESSION['Config__Adresse_email_contact'].'</p>
|
||||
<p>NB: This message has automatically been sent to Koriolan technical services for processing.<br />Because offering you an irreproachable service is our permanent concern !</p>';
|
||||
|
||||
// Affichage du message d'erreur :
|
||||
echo '<div class="message_erreur_mysql">'.$message_erreur.'</div>';
|
||||
|
||||
Enregistrement_log("\tOups ! Erreur de connexion à MYSQL", __FILE__, __LINE__);
|
||||
}
|
||||
else
|
||||
{
|
||||
$message_erreur = '<p>Oups ! Une erreur est survenue lors de l\'ouverture de la BDD.</p>
|
||||
<p>'.MAX_TENTATIVES_CONNEXIONS_BDD.' tentatives ont été effectuées et ont toutes échouées</p>';
|
||||
echo '<p>Les erreurs récupérées sont :';
|
||||
for ($i=0; $i<MAX_TENTATIVES_CONNEXIONS_BDD; $i++) echo $i.' : ['.$_SESSION['erreurs_connexion_db'][$x].']<br />';
|
||||
echo '</p>';
|
||||
}
|
||||
|
||||
exit(); // Arrêt du script.
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($_SESSION['erreurs_connexion_db'][0] != 0) // Si on s'est connecté mais qu'au moins une erreur a été détectée, on enregistre dans l'historique l'évènement).
|
||||
{
|
||||
for ($i=0; (($_SESSION['erreurs_connexion_db'][$i] != 0) AND ($i<MAX_TENTATIVES_CONNEXIONS_BDD)); $i++)
|
||||
{
|
||||
$requete = 'INSERT INTO `HISTORIQUE`(`Type`, `Sous_type`, `Valeur`, `Description`) VALUES (?, ?, ?, ?)';
|
||||
Requete_preparee_bdd($requete,
|
||||
array(
|
||||
array('i', SYSTEME),
|
||||
array('i', SYSTEME_ERREUR_MYSQL),
|
||||
array('i', $_SESSION['erreurs_connexion_db'][$i]),
|
||||
array('s', "Erreur de connexion à MySQL N°".$i.": code d'erreur = ".$_SESSION['erreurs_connexion_db'][$i])),
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Indique à la BDD que les prochains accès se feront en UTF-8 :
|
||||
mysqli_set_charset($_SESSION['db'], "utf8");
|
||||
|
||||
}
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Ouverture de la BDD d'un bateau
|
||||
// Reçoit : L'ID du bateau (sa clé_primaire dans TB_Bateaux)
|
||||
// Retour : Rien
|
||||
//************************************************************************************************************
|
||||
function Ouverture_bdd_bateau($id_bateau)
|
||||
{
|
||||
|
||||
Ouverture_bdd(BDD_BATEAUX_HOST.":".BDD_BATEAUX_PORT, BDD_BATEAUX_USER, BDD_BATEAUX_PASSWORD, BDD_BATEAUX_DATABASE_PREFIXE.$id_bateau);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Exécute une requête MYSQL
|
||||
// Reçoit : La requête, le fichier et la ligne d'où est appelée la fonction
|
||||
// Retour : Le résultat de la requête.
|
||||
// Attention : Si une erreur se produit lors de l'exécution, une page d'erreur est affichée et l'exécution est arrêtée !
|
||||
//************************************************************************************************************
|
||||
function Requete_bdd($requete, $fichier, $ligne)
|
||||
{
|
||||
|
||||
$retour = mysqli_query($_SESSION['db'], $requete);
|
||||
if ($retour == false) // Erreur de la fonction MYSQLI_QUERY :
|
||||
{
|
||||
// Préparation du texte d'erreur :
|
||||
$message_erreur = nl2br($_SESSION['textes']['fonctions_bdd']['all']['retour']['message_erreur']);
|
||||
|
||||
// Mise à jour des parametres du texte :
|
||||
$message_erreur = str_replace("[[Email]]", $_SESSION['Config__Adresse_email_contact'], $message_erreur);
|
||||
|
||||
// Affichage du message d'erreur :
|
||||
echo '<div class="message_erreur_mysql">'.$message_erreur.'</div>';
|
||||
|
||||
// Enregistrement dans le fichier de logs :
|
||||
Enregistrement_log("\tOups ! Erreur MYSQL. Requête = [".$requete."], message d'erreur = [".mysqli_error($_SESSION['db'])."]", $fichier, $ligne);
|
||||
|
||||
exit(); // Arrêt du script.
|
||||
}
|
||||
else return($retour); // Requete revenue sans erreur...
|
||||
|
||||
}
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Exécution d'une requête préparée dans la BDD
|
||||
// Reçoit : La requête à exécuter, un array avec les paramètres de la requête, le fichier d'origine et la ligne d'origine
|
||||
// Retour : Le retour de la requête si aucune erreur. En cas d'erreur, le script est arrêté après l'affichage d'une page d'erreur
|
||||
//************************************************************************************************************
|
||||
function Requete_preparee_bdd($requete, $parametres, $fichier, $ligne)
|
||||
{
|
||||
$texte_erreur = "";
|
||||
|
||||
|
||||
if ($stmt = mysqli_prepare($_SESSION['db'], $requete)) // Création de la requête préparée
|
||||
{
|
||||
// Récupération des éléments du tableau de paramètres reçu :
|
||||
$types = "";
|
||||
$nb = 0;
|
||||
foreach ($parametres as $parametre)
|
||||
{
|
||||
$types .= $parametre[0]; // Concaténation des types pour obtenir une chaine de tous les types, les uns derrière les autres
|
||||
$valeurs[$nb ++] = $parametre[1]; // Récupération de la valeur de chaque paramètre dans un tableau temporaire
|
||||
}
|
||||
|
||||
// Création d'un tableau avec tous les paramètres de la fonction 'mysqli_stmt_bind_param' :
|
||||
if ($nb > 0)
|
||||
{
|
||||
$params[] = $stmt; // Premier paramètre : identifiant de la requête préparée
|
||||
$params[] = &$types; // Second paramètre : chaine de caractère avec tous les types
|
||||
for ($i=0; $i<$nb; $i++) $params[] = &$valeurs[$i]; // Troisième et au-delà : une valeur par paramètre
|
||||
|
||||
// Appel de la fonction 'mysqli_stmt_bind_param' à travers 'call_user_func_array' qui permet de passer un tableau en argument :
|
||||
if (call_user_func_array("mysqli_stmt_bind_param", $params) == false) // NB : le retour de 'call_user_func_array' est celui de 'mysqli_stmt_bind_param'
|
||||
{
|
||||
$texte_erreur = "\tOups ! Le binding de la requête préparée [".$requete."] a échoué avec le message d'erreur [".mysqli_error($_SESSION['db'])."]";
|
||||
}
|
||||
} // Si le nombre de paramètres est nul, c'est qu'il n'y a pas de variable dans la requet et qu'on peut donc l'exécuter sans binding...
|
||||
|
||||
// exécution de la requête préparée avec le binding des variables fait :
|
||||
if (mysqli_stmt_execute($stmt) == false) // Exécution de la requête
|
||||
{
|
||||
$texte_erreur = "\tOups ! L'exécution de la requête préparée [".$requete."] a échoué avec le message d'erreur [".mysqli_error($_SESSION['db'])."]";
|
||||
}
|
||||
|
||||
// Récupération du jeu de résultats :
|
||||
$retour = mysqli_stmt_get_result($stmt);
|
||||
if (($retour == false) AND (mysqli_error($_SESSION['db']) != "")) // Il se peut que 'mysqli_stmt_get_result' renvoie 'false' si la requête exécutée n'attend pas de réponse (UPDATE, INSERT). On vériife donc si une erreur MySql a été déclenchée avant de passer en erreur...
|
||||
{
|
||||
$texte_erreur = "\tOups ! La recherche des résultats de la requête préparée [".$requete."] a échoué avec le message d'erreur [".mysqli_error($_SESSION['db'])."]";
|
||||
}
|
||||
|
||||
}
|
||||
else $texte_erreur = "\tOups ! La création de la requête préparée [".$requete."] a échoué avec le message d'erreur [".mysqli_error($_SESSION['db'])."]";
|
||||
|
||||
mysqli_stmt_close($stmt); // Libération de la requête préparée
|
||||
|
||||
// Traitement des cas d'erreur :
|
||||
// (NB : $texte_erreur est différent de $message_erreur !!)
|
||||
if ($texte_erreur != "")
|
||||
{
|
||||
// Préparation du texte d'erreur :
|
||||
$message_erreur = nl2br($_SESSION['textes']['fonctions_bdd']['all']['retour']['message_erreur']);
|
||||
|
||||
// Mise à jour des parametres du texte :
|
||||
$message_erreur = str_replace("[[Email]]", $_SESSION['Config__Adresse_email_contact'], $message_erreur);
|
||||
|
||||
// Affichage du message d'erreur :
|
||||
echo '<div class="message_erreur_mysql">'.$message_erreur.'</div>';
|
||||
|
||||
// Enregistrement dans le fichier de logs :
|
||||
Enregistrement_log($texte_erreur, $fichier, $ligne);
|
||||
|
||||
exit(); // Arrêt du script.
|
||||
}
|
||||
else return($retour); // Requete revenue sans erreur...
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Fetch de ligne de résultat MYSQL
|
||||
// Reçoit : La réponse complète de la requête (au sein de laquelle la ligne doit être cherchée)
|
||||
// Retour : La ligne de resultat suivante ou FALSE si aucune ligne supplémentaire n'existe.
|
||||
//************************************************************************************************************
|
||||
function Recherche_ligne_bdd($reponse)
|
||||
{
|
||||
// Récupération du type de retour à renvoyer :
|
||||
if (func_num_args() > 1)
|
||||
{
|
||||
$resulttype = func_get_arg(1);
|
||||
switch(func_get_arg(1))
|
||||
{
|
||||
case MYSQLI_ASSOC : {$resulttype = MYSQLI_ASSOC; break;} // ne renvoi que la version associative du tableau de retour
|
||||
case MYSQLI_NUM : {$resulttype = MYSQLI_NUM; break;} // ne renvoi que la version numérique du tableau de retour
|
||||
case MYSQLI_BOTH :
|
||||
default : {$resulttype = MYSQLI_BOTH; break;} // renvoi les deux versions (associative et numérique) du tableau de retour
|
||||
}
|
||||
}
|
||||
else $resulttype = MYSQLI_BOTH; // Valeur par défaut de la fonction.
|
||||
|
||||
// Recherche de la ligne
|
||||
return(mysqli_fetch_array($reponse, $resulttype));
|
||||
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Libération de jeu de résultat MYSQL
|
||||
// Reçoit : La variable à libérer
|
||||
// Retour : Rien
|
||||
//************************************************************************************************************
|
||||
function Liberation_jeu_de_resultat_bdd($reponse)
|
||||
{
|
||||
mysqli_free_result($reponse);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Récupération de l'id créé
|
||||
// Reçoit : Rien
|
||||
// Retour : L'ID de l'enregistrement qui vient d'être ajouté
|
||||
//************************************************************************************************************
|
||||
function Recuperation_id_cree_bdd()
|
||||
{
|
||||
return(mysqli_insert_id($_SESSION['db']));
|
||||
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Liste des champs de base de données
|
||||
// Reçoit : Rien
|
||||
// Retour : La liste des champs
|
||||
//************************************************************************************************************
|
||||
function Champs_bdd($reponse)
|
||||
{
|
||||
return(mysqli_fetch_fields($reponse));
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Comptage des résultats de la requête
|
||||
// Reçoit : La requête dont le comptage est recherché
|
||||
// Retour : Le nombre de lignes de résultats de la requête
|
||||
//************************************************************************************************************
|
||||
function Comptage_resultats_requete($requete)
|
||||
{
|
||||
|
||||
$reponse = Requete_bdd('SELECT COUNT(*) AS total FROM ('.$requete.') AS Total', __FILE__, __LINE__); // Le second AS est nécessaire mais ne sert pas...
|
||||
$donnees = Recherche_ligne_bdd($reponse);
|
||||
Liberation_jeu_de_resultat_bdd($reponse);
|
||||
return($donnees['total']);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Protection d'une requête contre les injections SQL
|
||||
// Reçoit : La requête à traiter
|
||||
// Retour : La requête après traitement
|
||||
//************************************************************************************************************
|
||||
function Protection_mysql($requete)
|
||||
{
|
||||
|
||||
return(mysqli_real_escape_string($_SESSION['db'], $requete));
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Fermeture de base de données
|
||||
// Reçoit : Rien
|
||||
// Retour : Rien
|
||||
//************************************************************************************************************
|
||||
function Fermeture_bdd()
|
||||
{
|
||||
if ($_SESSION['db'] != NULL) // SDIR # 289
|
||||
{
|
||||
mysqli_close($_SESSION['db']);
|
||||
$_SESSION['db'] = NULL; // SDIR # 289
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Encryptage d'un message
|
||||
// Reçoit : Le message à encrypter
|
||||
// Retour : Le message encrypté
|
||||
//************************************************************************************************************
|
||||
function Encryptage($message)
|
||||
{
|
||||
// La clé (secrète) est le mdp du user :
|
||||
$key = $_SESSION['login_key'];
|
||||
// algorythme choisi selon http://fr.php.net/manual/fr/mcrypt.ciphers.php
|
||||
$algo = MCRYPT_BLOWFISH;
|
||||
// mode choisi selon http://fr.php.net/manual/fr/mcrypt.constants.php
|
||||
$mode = MCRYPT_MODE_CBC ;
|
||||
|
||||
//Réduction de la taille de la clé selon la taille maximale supportée par l'algorythme mcrypt choisi :
|
||||
$key = substr($key, 0, mcrypt_module_get_algo_key_size($algo));
|
||||
// Création d'un vecteur d'initialisation selon la taille maximale possible :
|
||||
$iv = mcrypt_create_iv(mcrypt_get_iv_size($algo, $mode), MCRYPT_DEV_URANDOM);
|
||||
|
||||
// Chiffrage du message :
|
||||
$data = mcrypt_encrypt($algo, $key, $message, $mode, $iv);
|
||||
|
||||
// Retour du message après ajouté devant l'IV qui sera nécessaire au décodage (l'IV n'est pas confidentiel)
|
||||
// puis avoir encodé le tout en base64 (utile si l'on veut mettre le résultat dans une base de donnée)
|
||||
return(base64_encode($iv.$data));
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Décryptage d'un message
|
||||
// Reçoit : Le message crypté
|
||||
// Retour : Le message décrypté
|
||||
//************************************************************************************************************
|
||||
function Decryptage($message_crypte)
|
||||
{
|
||||
|
||||
// La clé (secrète) est le mdp du user :
|
||||
$key = $_SESSION['login_key'];
|
||||
// algorythme choisi selon http://fr.php.net/manual/fr/mcrypt.ciphers.php
|
||||
$algo = MCRYPT_BLOWFISH;
|
||||
// mode choisi selon http://fr.php.net/manual/fr/mcrypt.constants.php
|
||||
$mode = MCRYPT_MODE_CBC ;
|
||||
|
||||
//Réduction de la taille de la clé selon la taille maximale supportée par l'algorythme mcrypt choisi :
|
||||
$key = substr($key, 0, mcrypt_module_get_algo_key_size($algo));
|
||||
// Rechjerche de la taille du vecteur d'initialisation (dépend uniquement du mode de cryptage) :
|
||||
$size = mcrypt_get_iv_size($algo, $mode);
|
||||
// Désencodage en base64 :
|
||||
$message_crypte = base64_decode($message_crypte);
|
||||
// Extraction de l'IV qui est stocké en début de message :
|
||||
$iv = substr($message_crypte, 0, $size); // On extrait l'IV (qui est de longueur connue) du début du message.
|
||||
// Extraction du message crypté proprement dit :
|
||||
$message_crypte = substr($message_crypte, $size); // On ne garde que la fin du message (sans l'IV).
|
||||
// Retour du message décrypté :
|
||||
return(trim(mcrypt_decrypt($algo, $key, $message_crypte, $mode, $iv))); // Le TRIM permet de supprimer les 0x00 qui sont ajoutés à la fin pour former des blocs de 8 octets...
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Rencryptage d'un message
|
||||
// Reçoit : Le message à encrypter (les variables de session $_SESSION['login_key'] et $_SESSION['new_login_key'] sont utilisées pour assurer le décryptage puis le rencryptage)
|
||||
// Retour : Le message encrypté
|
||||
//************************************************************************************************************
|
||||
function Rencryptage($message_crypte)
|
||||
{
|
||||
// Décodage avec ancienne clé :
|
||||
|
||||
// La clé (secrète) est l'ancien mdp du user :
|
||||
$key = $_SESSION['login_key'];
|
||||
// algorythme choisi selon http://fr.php.net/manual/fr/mcrypt.ciphers.php
|
||||
$algo = MCRYPT_BLOWFISH;
|
||||
// mode choisi selon http://fr.php.net/manual/fr/mcrypt.constants.php
|
||||
$mode = MCRYPT_MODE_CBC ;
|
||||
|
||||
//Réduction de la taille de la clé selon la taille maximale supportée par l'algorythme mcrypt choisi :
|
||||
$key = substr($key, 0, mcrypt_module_get_algo_key_size($algo));
|
||||
// Rechjerche de la taille du vecteur d'initialisation (dépend uniquement du mode de cryptage) :
|
||||
$size = mcrypt_get_iv_size($algo, $mode);
|
||||
// Désencodage en base64 :
|
||||
$message_crypte = base64_decode($message_crypte);
|
||||
// Extraction de l'IV qui est stocké en début de message :
|
||||
$iv = substr($message_crypte, 0, $size); // On extrait l'IV (qui est de longueur connue) du début du message.
|
||||
// Extraction du message crypté proprement dit :
|
||||
$message_crypte = substr($message_crypte, $size); // On ne garde que la fin du message (sans l'IV).
|
||||
// Retour du message décrypté :
|
||||
$message_decrypte = trim(mcrypt_decrypt($algo, $key, $message_crypte, $mode, $iv)); // Le TRIM permet de supprimer les 0x00 qui sont ajoutés à la fin pour former des blocs de 8 octets...
|
||||
|
||||
|
||||
// Encodage avec nouvelle clé :
|
||||
|
||||
// La clé (secrète) est le nouveau mdp du user :
|
||||
$key = $_SESSION['new_login_key'];
|
||||
|
||||
//Réduction de la taille de la clé selon la taille maximale supportée par l'algorythme mcrypt choisi :
|
||||
$key = substr($key, 0, mcrypt_module_get_algo_key_size($algo));
|
||||
// Création d'un vecteur d'initialisation selon la taille maximale possible :
|
||||
$iv = mcrypt_create_iv(mcrypt_get_iv_size($algo, $mode), MCRYPT_DEV_URANDOM);
|
||||
|
||||
// Chiffrage du message :
|
||||
$data = mcrypt_encrypt($algo, $key, $message_decrypte, $mode, $iv);
|
||||
|
||||
// Retour du message après ajouté devant l'IV qui sera nécessaire au décodage (l'IV n'est pas confidentiel)
|
||||
// puis avoir encodé le tout en base64 (utile si l'on veut mettre le résultat dans une base de donnée)
|
||||
return(base64_encode($iv.$data));
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Génération de mot de passe aléatoire
|
||||
// Reçoit : La longueur du mot de passe à générer
|
||||
// Retour : Le mot de passe généré
|
||||
//************************************************************************************************************
|
||||
function Mdp_aleatoire($longueur)
|
||||
{
|
||||
|
||||
$password = "";
|
||||
$prec = 0;
|
||||
for($i = 0; $i < $longueur; $i++)
|
||||
{
|
||||
$random = rand(48,122); // chiffres de 48 à 57, maj de 65 à 90 et min de 97 à 122
|
||||
|
||||
// Suppression des caractères non alphanumériques :
|
||||
if (($random == ord("0")) OR
|
||||
(($random >= 58) AND ($random <= 64)) OR
|
||||
($random == ord("I")) OR
|
||||
($random == ord("O")) OR
|
||||
($random == ord("l")) OR
|
||||
($random == ord("o")) OR
|
||||
(($random >= 91) AND ($random <= 96)) OR
|
||||
($random == $prec)) // Evite les doublons de caractères identiques (difficile à lire)
|
||||
{
|
||||
$i--;
|
||||
continue;
|
||||
}
|
||||
$password .= chr($random);
|
||||
$prec = $random;
|
||||
}
|
||||
return($password);
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Vérification de la conformité d'un mot de passe (longueur, caractères utilisés, etc...)
|
||||
// Reçoit : Le mot de passe à vérifier
|
||||
// Retour : La liste des champs
|
||||
//************************************************************************************************************
|
||||
function Check_mdp($mdp)
|
||||
{
|
||||
global $message_erreur;
|
||||
|
||||
// $pattern = "#(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).{".MIN_TAILLE_MOTS_DE_PASSE.",".MAX_TAILLE_MOTS_DE_PASSE."}#";
|
||||
|
||||
// Nombre de caractères entre MIN et MAX, caractères minuscules ou majuscules ou chiffres ou '_' et '-' :
|
||||
// $pattern = "#^[a-zA-Z0-9_-]{".MIN_TAILLE_MOTS_DE_PASSE.",".."}#";
|
||||
|
||||
$longueur = strlen($mdp);
|
||||
if ($longueur < MIN_TAILLE_MOTS_DE_PASSE) return(0);
|
||||
if ($longueur > MAX_TAILLE_MOTS_DE_PASSE) return(0);
|
||||
|
||||
for ($i = 0; $i < $longueur; $i ++)
|
||||
{
|
||||
if (($mdp[$i] >= 'A') AND ($mdp[$i] <= 'Z')) continue;
|
||||
if (($mdp[$i] >= 'a') AND ($mdp[$i] <= 'z')) continue;
|
||||
if (($mdp[$i] >= '0') AND ($mdp[$i] <= '9')) continue;
|
||||
if ($mdp[$i] == '_') continue;
|
||||
if ($mdp[$i] == '-') continue;
|
||||
if ($mdp[$i] == '!') continue;
|
||||
if ($mdp[$i] == '*') continue;
|
||||
if ($mdp[$i] == '=') continue;
|
||||
if ($mdp[$i] == '.') continue;
|
||||
|
||||
return(-3);
|
||||
}
|
||||
|
||||
return(1);
|
||||
|
||||
// if (preg_match($pattern, $mdp)) return(true);
|
||||
// else return(false);
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Dump de base de données
|
||||
// Reçoit : La BDD à dumper, la table concernée, le nom du fichier de sortie et le type de sortie attendu. Voir documentation de la fonction PHP 'mysqldump' pour détails).
|
||||
// Retour : La liste des champs
|
||||
//************************************************************************************************************
|
||||
function Dump_bdd($bdd, $table, $fichier_sortie, $type_sortie)
|
||||
{
|
||||
|
||||
// Appel de la fonction de DUMP :
|
||||
system('mysqldump --host='.BDD_HOST.' --user='.BDD_USER.' --password='.BDD_PASSWORD.' '.BDD_DATABASE.' --tables '.$table.' '.$type_sortie.' '.$fichier_sortie.' ');
|
||||
|
||||
}
|
||||
|
||||
|
||||
//==================================================================================================================
|
||||
// Fonction : Création d'un fichier d'archive (compressé et encodé) à partir d'un répertoire
|
||||
// Reçoit : Le chemin complet du répertoire à archiver et le nom du fichier de sortie.
|
||||
// Retour : 0 si Ok, <0 si erreur
|
||||
//==================================================================================================================
|
||||
function creer_archive_chiffree(string $repertoire_a_chiffrer, string $fichier_sortie)
|
||||
{
|
||||
if (!is_dir($repertoire_a_chiffrer)) return (-1);
|
||||
|
||||
$tarFile = $fichier_sortie . '.tar';
|
||||
$gzFile = $tarFile . '.gz';
|
||||
$encFile = $gzFile . '.enc';
|
||||
|
||||
foreach ([$tarFile, $gzFile] as $f) {
|
||||
if (file_exists($f)) {
|
||||
unlink($f);
|
||||
}
|
||||
}
|
||||
|
||||
// 1. Archivage + compression (tar.gz)
|
||||
$phar = new PharData($tarFile);
|
||||
// $phar->buildFromDirectory($repertoire_a_chiffrer);
|
||||
$phar->buildFromDirectory(".");
|
||||
$phar->compress(Phar::GZ);
|
||||
unset($phar);
|
||||
unlink($tarFile);
|
||||
|
||||
// 2. Chiffrement AES-256-CBC avec clé dérivée par PBKDF2
|
||||
$contenu = file_get_contents($gzFile);
|
||||
$salt = openssl_random_pseudo_bytes(16);
|
||||
$iv = openssl_random_pseudo_bytes(16);
|
||||
$iterations = 100000;
|
||||
|
||||
$cle = openssl_pbkdf2(BDD_BATEAU_PASSWORD, $salt, 32, $iterations, 'sha256');
|
||||
|
||||
$chiffre = openssl_encrypt($contenu, 'aes-256-cbc', $cle, OPENSSL_RAW_DATA, $iv);
|
||||
|
||||
if ($chiffre === false) return (-2);
|
||||
|
||||
// Format du fichier : salt(16) + iv(16) + données chiffrées
|
||||
file_put_contents($encFile, $salt . $iv . $chiffre);
|
||||
|
||||
unlink($gzFile);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==================================================================================================================
|
||||
// Fonction :
|
||||
// Reçoit : Le chemin complet du répertoire à archiver et le nom du fichier de sortie.
|
||||
// Retour : 0 si Ok, <0 si erreur
|
||||
//==================================================================================================================
|
||||
function dechiffrer_archive(string $fichierChiffre, string $dossierDestination, string $motDePasse)
|
||||
{
|
||||
$contenu = file_get_contents($fichierChiffre);
|
||||
$salt = substr($contenu, 0, 16);
|
||||
$iv = substr($contenu, 16, 16);
|
||||
$donnees = substr($contenu, 32);
|
||||
|
||||
$iterations = 100000;
|
||||
$cle = openssl_pbkdf2($motDePasse, $salt, 32, $iterations, 'sha256');
|
||||
|
||||
$dechiffre = openssl_decrypt($donnees, 'aes-256-cbc', $cle, OPENSSL_RAW_DATA, $iv);
|
||||
|
||||
if ($dechiffre === false) return (-1);
|
||||
|
||||
if (!is_dir($dossierDestination)) mkdir($dossierDestination, 0755, true);
|
||||
|
||||
$tmpGz = tempnam(sys_get_temp_dir(), 'restore_') . '.tar.gz';
|
||||
file_put_contents($tmpGz, $dechiffre);
|
||||
|
||||
$phar = new PharData($tmpGz);
|
||||
$phar->extractTo($dossierDestination, null, true);
|
||||
|
||||
unlink($tmpGz);
|
||||
echo "Archive extraite dans : ".$dossierDestination."\n";
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
<?php
|
||||
|
||||
|
||||
//==================================================================================================================
|
||||
// Fonction : Lit le fichier JSON dont le nom est passé en paramètre et renvoit un tableau dénommé avec les
|
||||
// champs du fichier.
|
||||
// Reçoit : Le nom complet du fichier
|
||||
// Retour : Le tableau dénommé ou FALSE si erreur
|
||||
//==================================================================================================================
|
||||
function lecture_json($fichier)
|
||||
{
|
||||
$json = file_get_contents($fichier);
|
||||
if ($json === false) return (false); // Si erreur lors du 'file_get_contents'
|
||||
else return(json_decode($json, true));
|
||||
}
|
||||
|
||||
|
||||
//==================================================================================================================
|
||||
// Fonction : Copie le contenu du répertoire d'origine dans le répertoire de destination, y compris ses
|
||||
// sous-répertoires s'il y en a.
|
||||
// Reçoit : Le nom complet du répertoire origine et destination.
|
||||
// Retour : Le nombre de fichiers copiés
|
||||
//==================================================================================================================
|
||||
function copie_repertoire($source , $destination)
|
||||
{
|
||||
|
||||
if ((!file_exists($source)) && (!is_dir($source))) return -1; // Si le répertoire source n'existe pas ou est un fichier (pas un répertoire)
|
||||
$dossier_source = opendir($source); // Ouverture de la source
|
||||
|
||||
if (!file_exists($destination)) mkdir($destination, fileperms($source)); // Si la destination n'existe pas, on la créée
|
||||
|
||||
$total = 0;
|
||||
|
||||
while ($fichier = readdir($dossier_source))
|
||||
{
|
||||
$l = array('.', '..');
|
||||
if (!in_array( $fichier, $l))
|
||||
{
|
||||
if (is_dir($source."/".$fichier))
|
||||
{
|
||||
$total += copie_repertoire("$source/$fichier", "$destination/$fichier");
|
||||
}
|
||||
else
|
||||
{
|
||||
copy("$source/$fichier", "$destination/$fichier");
|
||||
$total++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $total;
|
||||
}
|
||||
|
||||
|
||||
//==================================================================================================================
|
||||
// Fonction : Ouvre et parcours le répertoire dont le nom est passé en 1er paramètre. Si un répertoire avec le nom
|
||||
// reçu en 2nd paramètre est trouvé, retour de TRUE.
|
||||
// Reçoit : Le nom complet du répertoire de recherche et le nom du répertoire à chercher.
|
||||
// Retour : TRUE si le répertoire recherché a été trouvé, FALSE sinon
|
||||
//==================================================================================================================
|
||||
function repertoire_contient_repertoire($repertoire, $recherche)
|
||||
{
|
||||
$retour = false;
|
||||
if ($handle = opendir($repertoire))
|
||||
{
|
||||
while (($file = readdir($handle)) !== false)
|
||||
{
|
||||
if ('.' === $file) continue;
|
||||
if ('..' === $file) continue;
|
||||
if ((is_dir($repertoire.'/'.$file)) AND
|
||||
($file == $recherche))
|
||||
{
|
||||
$retour = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
}
|
||||
|
||||
return($retour);
|
||||
}
|
||||
|
||||
|
||||
//==================================================================================================================
|
||||
// Fonction : Ouvre et parcours le répertoire dont le nom est passé en paramètre. Si un fichier avec le nom qui
|
||||
// contient le marqueur reçu en second paramètre, le nom du fichier est retourné. Sinon, une chaine
|
||||
// vide est retournée.
|
||||
// La fonction s'arrête sur le premier fichier répondant au marqueur. Le marqueur est cherché partout
|
||||
// dans le nom de fichier, pas uniquement au début ou à la fin.
|
||||
// Reçoit : Le nom complet du répertoire de recherche et le marqueur de fichier à chercher.
|
||||
// Retour : Le nom du fichier si trouvé ou une chaine vide
|
||||
//==================================================================================================================
|
||||
function recherche_fichier_repertoire($repertoire, $marqueur)
|
||||
{
|
||||
$fichier = "";
|
||||
if ($handle = opendir($repertoire))
|
||||
{
|
||||
while (($file = readdir($handle)) !== false)
|
||||
{
|
||||
if ('.' === $file) continue;
|
||||
if ('..' === $file) continue;
|
||||
if ((is_file($repertoire.'/'.$file)) AND
|
||||
(strstr($file, $marqueur) != false))
|
||||
{
|
||||
$fichier = $file;
|
||||
break;
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
}
|
||||
|
||||
return($fichier);
|
||||
}
|
||||
|
||||
|
||||
//==================================================================================================================
|
||||
// Fonction : Vérifie si le répertoire dont le nom est passé en paramètre est vide ou non.
|
||||
// Reçoit : Le nom complet du répertoire de recherche.
|
||||
// Retour : TRUE si vide, FALSE si Non vide
|
||||
//==================================================================================================================
|
||||
function repertoire_est_vide($repertoire)
|
||||
{
|
||||
$retour = true;
|
||||
|
||||
if ($handle = opendir($repertoire))
|
||||
{
|
||||
while (false !== ($entry = readdir($handle)))
|
||||
{
|
||||
if ($entry != "." && $entry != "..")
|
||||
{
|
||||
$retour = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
}
|
||||
|
||||
return $retour;
|
||||
}
|
||||
|
||||
|
||||
//==================================================================================================================
|
||||
// Fonction : Supprime du répertoire reçu en paramètre, tous les fichiers qui contiennent (pas forcément au début
|
||||
// ou à la fin) le marquer reçu.
|
||||
// Reçoit : Le nom complet du répertoire de recherche et le marqueur de fichier à chercher.
|
||||
// Retour : TRUE si Ok, FALSE si erreur
|
||||
//==================================================================================================================
|
||||
function suppression_fichier_repertoire($repertoire, $marqueur)
|
||||
{
|
||||
for ($max = 0; $max < MAX_BOUCLES_SUPPRESSION_FICHIER_REPERTOIRE; $max ++)
|
||||
{
|
||||
$fichier = recherche_fichier_repertoire($repertoire, $marqueur);
|
||||
if ($fichier == "") break;
|
||||
elseif (unlink($repertoire."/".$fichier) === false) return(false);
|
||||
}
|
||||
|
||||
if ($max == MAX_BOUCLES_SUPPRESSION_FICHIER_REPERTOIRE) return(false);
|
||||
else return(true);
|
||||
}
|
||||
|
||||
|
||||
//==================================================================================================================
|
||||
// Fonction : Supprime le répertoire reçu en paramètre, y compris les sous-répertoires de façon récursive.
|
||||
// Reçoit : Le nom complet du répertoire à supprimer.
|
||||
// Retour : TRUE si Ok, FALSE si erreur
|
||||
//==================================================================================================================
|
||||
function suppression_repertoire($repertoire)
|
||||
{
|
||||
$files = array_diff(scandir($repertoire), array('.','..'));
|
||||
foreach ($files as $file)
|
||||
{
|
||||
(is_dir($repertoire."/".$file) && !is_link($repertoire)) ? suppression_repertoire($repertoire."/".$file) : unlink($repertoire."/".$file);
|
||||
}
|
||||
return rmdir($repertoire);
|
||||
|
||||
|
||||
/* if(is_dir($repertoire))
|
||||
{
|
||||
$files = glob( $repertoire . '*', GLOB_MARK ); //GLOB_MARK adds a slash to directories returned
|
||||
foreach($files as $file) suppression_repertoire($file);
|
||||
rmdir($repertoire);
|
||||
}
|
||||
elseif(is_file($repertoire))
|
||||
{
|
||||
unlink($repertoire);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
//==================================================================================================================
|
||||
// Fonction : Supprime du répertoire passé en paramètres tous les fichiers dont la date de dernière modification
|
||||
// est antérieure à aujourd'hui de plus de N jours.
|
||||
// Reçoit : Le nom complet du répertoire à supprimer, le nombre de jours d'antériorité maximale et un flag Verbose
|
||||
// Retour : 0 si Ok, -1 si erreur
|
||||
//==================================================================================================================
|
||||
function purge_repertoire($repertoire, $nb_jours_anteriorite, $verbose = true)
|
||||
{
|
||||
$retour = 0;
|
||||
|
||||
$date_max = new DateTime('-'.$nb_jours_anteriorite.' days');
|
||||
|
||||
$iterator = new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator($repertoire, FilesystemIterator::SKIP_DOTS),
|
||||
RecursiveIteratorIterator::CHILD_FIRST
|
||||
);
|
||||
|
||||
foreach ($iterator as $fileInfo)
|
||||
{
|
||||
if ($fileInfo->isFile())
|
||||
{
|
||||
$filePath = $fileInfo->getPathname();
|
||||
$modificationTimestamp = $fileInfo->getMTime();
|
||||
$modificationDate = new DateTime('@' . $modificationTimestamp);
|
||||
|
||||
if ($modificationDate < $date_max)
|
||||
{
|
||||
if (unlink($filePath))
|
||||
{
|
||||
if ($verbose) echo "\tLe fichier [".$filePath."] a été supprimé.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($verbose) echo "\t/!\\ Le fichier [".$filePath."]. est antérieur a ".$nb_jours_anteriorite." jours mais n'a pas pu être supprimé...\n";
|
||||
$retour = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return($retour);
|
||||
|
||||
// Attention : non testé !! (Pierre 09/2024) :
|
||||
// Get a list of all directories inside the root directory and delete the empty ones
|
||||
// $subdirectories = array_filter(glob($repertoire . '*'), 'is_dir');
|
||||
|
||||
// foreach ($subdirectories as $subdirectory) {
|
||||
// if (count(scandir($subdirectory)) === 2) {
|
||||
// // if (rmdir($subdirectory)) {
|
||||
// // if ($verbose) echo "Directory: {$subdirectory} removed.<br>";
|
||||
// // } else {
|
||||
// // if ($verbose) echo "Error removing directory: {$subdirectory}.<br>";
|
||||
// // }
|
||||
// echo "Directory: {$subdirectory} removed.<br>";
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
|
||||
//*******************************************************************************************
|
||||
function Connexion_ftp()
|
||||
{
|
||||
$ftp_server = "ftp.trois-etoiles.fr";
|
||||
$ftp_user_name = "troiseto";
|
||||
$ftp_user_pass = "da6VMvRC";
|
||||
|
||||
// Mise en place de la connexion :
|
||||
$id_ftp = ftp_connect($ftp_server);
|
||||
if(!$id_ftp) return (-1); // Connexion impossible...
|
||||
|
||||
// Identification avec un nom d'utilisateur et un mot de passe :
|
||||
$login_result = ftp_login($id_ftp, $ftp_user_name, $ftp_user_pass);
|
||||
if (!$login_result) return(-1);
|
||||
|
||||
return($id_ftp);
|
||||
}
|
||||
|
||||
|
||||
//*******************************************************************************************
|
||||
function Copie_dir_ftp ($id_ftp, $dir_source, $dir_destination)
|
||||
{ // NB : il faut que le répertoire DIR_DESTINATION existe avant l'appel...
|
||||
// NB 2 : les adresses sont absolues...
|
||||
|
||||
// Changement vers le répertoire cible sur le servuer distant :
|
||||
if (!ftp_chdir ($id_ftp, $dir_destination)) return(false);
|
||||
|
||||
// On vérifie si $dir_source est un dossier :
|
||||
if (is_dir($dir_source))
|
||||
{
|
||||
// Si oui, on l'ouvre :
|
||||
if ($dh = opendir($dir_source))
|
||||
{
|
||||
// On liste les dossiers et fichiers de $dir_source
|
||||
while (($file = readdir($dh)) !== false)
|
||||
{
|
||||
|
||||
// S'il s'agit d'un dossier, on créé le sous-dossier destination et on relance la fonction récursive :
|
||||
if(is_dir($dir_source.'/'.$file) && $file != '..' && $file != '.')
|
||||
{
|
||||
// Création du sous-répertoire sur le serveur distant :
|
||||
if (!ftp_mkdir ($id_ftp, $file)) return(false);
|
||||
|
||||
// Lancement de la fonction récursive :
|
||||
Copie_dir_ftp ($id_ftp, $dir_source.'/'.$file, $dir_destination.'/'.$file);
|
||||
|
||||
// Changement vers le répertoire cible sur le servuer distant :
|
||||
if (!ftp_chdir ($id_ftp, $dir_destination)) return(false);
|
||||
}
|
||||
else // S'il sagit d'un fichier, on le copie simplement :
|
||||
{
|
||||
if(($file != '..') AND ($file != '.'))
|
||||
{
|
||||
if (!ftp_put($id_ftp, $dir_destination.'/'.$file, $dir_source.'/'.$file, FTP_BINARY)) return(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// On ferme $dir_source :
|
||||
closedir($dh);
|
||||
}
|
||||
else return(false); // Erreur d'ouverture du répertoire source...
|
||||
|
||||
}
|
||||
else return(false); // Le répertoire source n'est pas un répertoire...
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
//*******************************************************************************************
|
||||
function Suppression_dir_ftp($id_ftp, $dossier)
|
||||
{ // Supprime les sous-répertoire et les fichiers qu'ils contiennent puis supprime le répertoire passé en paramètre.
|
||||
|
||||
// Changement vers le répertoire cible :
|
||||
if (!@ftp_chdir ($id_ftp, $dossier)) return(false); // Le '@' devant l'appel de la focntion permet d'éviter l'affichage de message d'erreur (notamment si le répertoire qu'on demande de supprimer n'existe pas...)
|
||||
|
||||
// Recherche de la liste des fichiers et répertoires du répertoire en cours :
|
||||
$liste = ftp_nlist($id_ftp, ".");
|
||||
|
||||
// Boucle sur toute la liste pour supprimer les fichier ou vider les sous-répertoires (appel récursif) puis les supprimer :
|
||||
foreach($liste as $val)
|
||||
{
|
||||
if(ftp_size($id_ftp, $val) != -1) // Cas d'un fichier :
|
||||
{
|
||||
if (!ftp_delete ($id_ftp, $val)) return(false);
|
||||
}
|
||||
else // Cas d'un répertoire :
|
||||
{
|
||||
if (($val != '.') && ($val != '..'))
|
||||
{
|
||||
if (!Suppression_dir_ftp($id_ftp, $val)) return(false); // Appel récursif pour supprimer le sous-dossier...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Changement vers répertoire parent :
|
||||
if (!ftp_chdir ($id_ftp, "..")) return(false);
|
||||
|
||||
// Suppression du répertoire qui doit être vide :
|
||||
if (!ftp_rmdir ($id_ftp, $dossier)) return(false);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,338 @@
|
||||
<?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(3600, '/', 'shipheart.tech', 1, 1);
|
||||
|
||||
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()
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
|
||||
require_once("../vendor/autoload.php");
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction d'envoi d'un email avec PHPMail
|
||||
// NB : Un tuto assez complet, et à jour (!), sur l'utilisation de PHPMailer
|
||||
// est disponible à https://alexwebdevelop.com/phpmailer-tutorial/#why-you-should-use-phpmailer
|
||||
// Reçoit :
|
||||
// - le nom du destinataire (ce champs peut être vide)
|
||||
// - adresse email du destinataire
|
||||
// - objet du message
|
||||
// - texte brut (peut contenir de l'HTML)
|
||||
// - nom de l'expéditeur (peut être vide)
|
||||
// - adresse de l'expéditeur
|
||||
// - fichier(s) joint(s) sous forme de tableau "$fichier_joints[N]['fichier']" et "$fichier_joints[N]['nom']"
|
||||
// /!\ Le nombre maxi de fichier joints est limité à 10 (cf le code). Si vous en mettez plus, les derniers ne seront pas traités...
|
||||
// Mais on peut changer cette valeur sans soucis...
|
||||
// Retour : Rien
|
||||
//************************************************************************************************************
|
||||
function Envoi_email($nom_destinataire, $adresse_destinataire, $objet, $texte_brut, $nom_expediteur, $adresse_expediteur, $fichiers_joints)
|
||||
{
|
||||
global $message_information;
|
||||
|
||||
// Entête HTML :
|
||||
$message_html = '
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<style type="text/css">
|
||||
body {font-family: Calibri, Verdana; color:rgb(0, 69, 99); }
|
||||
gras {font-weight: bold; }
|
||||
souligne {text-decoration: underline; }
|
||||
p {margin:8px 0px; padding:0px; }
|
||||
table {border-collapse: collapse; }
|
||||
table th {border: 1px solid rgb(0, 69, 99); background-color: rgb(0, 69, 99); color: rgb(255, 255, 255); padding: 5px 10px; }
|
||||
table td {border: 1px solid rgb(0, 69, 99); padding: 5px 10px; font-size:0.9em;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
'.$texte_brut.'
|
||||
</body>
|
||||
</html>';
|
||||
|
||||
|
||||
$mail = new PHPMailer();
|
||||
|
||||
$mail->CharSet = 'UTF-8'; // Format d'encodage à utiliser pour les caractères
|
||||
|
||||
// $mail->SMTPDebug = 4; // Valeur entre 0 (normal) et 4 (full debug). Attention : mettre cette valeur > 0 dévoule certains paramètres confidentiels !
|
||||
|
||||
$mail->isSMTP();
|
||||
$mail->Host = 'ssl0.ovh.net'; // Adresse IP ou DNS du serveur SMTP
|
||||
$mail->Port = 587; // Port TCP du serveur SMTP (port SMTP chez OVH : 465=avec_SSL et 587=sans_SSL/avec_tls)
|
||||
$mail->SMTPAuth = TRUE; // Utiliser l'authentification
|
||||
|
||||
if($mail->SMTPAuth)
|
||||
{
|
||||
$mail->SMTPSecure = 'tls'; // Protocole de sécurisation des échanges avec le SMTP
|
||||
$mail->Username = 'do_not_answer@koriolan.tech'; // Adresse email à utiliser pour le compte SMTP
|
||||
$mail->Password = SMTP_PASSWORD; // Mot de passe de l'adresse email à utiliser
|
||||
}
|
||||
|
||||
if ($nom_expediteur == "") $mail->setFrom($adresse_expediteur);
|
||||
else $mail->setFrom($adresse_expediteur, $nom_expediteur); // L'email et l'alias (facultatif) à afficher pour l'envoi
|
||||
|
||||
if ($nom_destinataire == "") $mail->AddAddress($adresse_destinataire);
|
||||
else $mail->AddAddress($adresse_destinataire, $nom_destinataire); // L'email du destinataire et son alias (facultatif)
|
||||
|
||||
// $mail->addBCC('do_not_answer@koriolan.tech','ShipHeart by Koriolan'); // Destinataire BCC (idem AddAddress)
|
||||
|
||||
$mail->Subject = $objet; // Le sujet du mail
|
||||
|
||||
$mail->isHTML(TRUE); // Indique que le message dans Body sera en HTML
|
||||
$mail->Body = $message_html;
|
||||
$mail->AltBody = $texte_brut; // Texte brut alternatif
|
||||
|
||||
|
||||
for ($i = 0; $i < 10; $i ++) // Pièces jointes (limité à un maxi de 10 !):
|
||||
{
|
||||
if (!isset($fichiers_joints[$i]['fichier']) OR ($fichiers_joints[$i]['fichier'] == "")) break;
|
||||
else
|
||||
{
|
||||
if (isset($fichiers_joints[$i]['nom']) AND ($fichiers_joints[$i]['nom'] != "")) $mail->AddAttachment($fichiers_joints[$i]['fichier'], $fichiers_joints[$i]['nom']);
|
||||
else $mail->AddAttachment($fichiers_joints[$i]['fichier']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!$mail->Send()) // Envoi de l'email et test du résultat
|
||||
{
|
||||
// $message_information .= "Erreur lors de l'envoi de l'email. PHPMailer Error = [" . $mail->ErrorInfo."]";
|
||||
}
|
||||
else
|
||||
{
|
||||
// $message_information .= "L'email a été envoyé correctement.";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,353 @@
|
||||
<?php
|
||||
|
||||
require_once('../vendor/tecnickcom/tcpdf/tcpdf.php'); // Include the main TCPDF library
|
||||
require_once('../vendor/phpqrcode/qrlib.php');
|
||||
|
||||
|
||||
class MYPDF extends TCPDF {
|
||||
public function Header() {
|
||||
$this->Image('images/logo_koriolan.png', 10, 10, 60, 0, 'PNG', 'https://koriolan.tech');
|
||||
}
|
||||
|
||||
public function Footer() {
|
||||
$this->SetFont('helvetica', '', 7);
|
||||
$this->SetTextColor(150, 150, 150);
|
||||
|
||||
// Partie gauche :
|
||||
$this->SetXY(10, -23);
|
||||
$this->Cell(90, 10, 'Koriolan', 0, false, 'L');
|
||||
$this->SetXY(10, -19);
|
||||
$this->Cell(90, 10, 'SASU au capital social de 50 000€', 0, false, 'L');
|
||||
$this->SetXY(10, -15);
|
||||
$this->Cell(90, 10, '6 rue Grange Bruyère - 69110 Sainte-Foy-Lès-Lyon - FRANCE', 0, false, 'L');
|
||||
|
||||
// Partie droite :
|
||||
$this->SetXY(110, -23);
|
||||
$this->Cell(90, 10, 'RCS Lyon 879 809 341', 0, false, 'R');
|
||||
$this->SetXY(110, -19);
|
||||
$this->Cell(90, 10, 'SIRET 879 809 341 00016', 0, false, 'R');
|
||||
$this->SetXY(110, -15);
|
||||
$this->Cell(90, 10, 'TVA Intraco. FR29 879 809 341', 0, false, 'R');
|
||||
}
|
||||
|
||||
public function CreateTextBox($textval, $x = 0, $y = 0, $width = 0, $height = 10, $fontsize = 10, $fontstyle = '', $align = 'L', $border = 0) {
|
||||
$this->SetXY($x, $y);
|
||||
$this->SetFont('helvetica', $fontstyle, $fontsize);
|
||||
$this->Cell($width, $height, $textval, 0, false, $align);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//********************************************************************************************************************************
|
||||
// Fonction : Génère le document PDF à partir des données reçues en paramètres
|
||||
// Reçoit : une autre concernant la pièce ('Commande', 'Facture') et ses attributs, une variable concernant le client,
|
||||
// et une autre contenant les lignes de la pièce. Le fichier généré est stocké dans 'documents/commandes' ou 'documents/factures'.
|
||||
// Retour : 0 si Ok, -1 si erreur
|
||||
//********************************************************************************************************************************
|
||||
function document_pdf($piece, $client, $lignes)
|
||||
{
|
||||
|
||||
switch($piece['type'])
|
||||
{
|
||||
case "commande":
|
||||
{
|
||||
$nom_piece = $_SESSION['textes']['fonctions_pdf']['document']['piece']['type_commande'];
|
||||
$rep = "commandes";
|
||||
break;
|
||||
}
|
||||
case "facture":
|
||||
{
|
||||
$nom_piece = $_SESSION['textes']['fonctions_pdf']['document']['piece']['type_facture'];
|
||||
$rep = "factures";
|
||||
break;
|
||||
}
|
||||
default: return(-1);
|
||||
}
|
||||
|
||||
$pdf = new MYPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
|
||||
|
||||
// set document (meta) information :
|
||||
$pdf->SetCreator(PDF_CREATOR);
|
||||
$pdf->SetAuthor('Koriolan');
|
||||
$pdf->SetTitle($nom_piece.' '.$piece['no']);
|
||||
$pdf->SetSubject('ShipHeart');
|
||||
$pdf->SetKeywords('ShipHeart by Koriolan');
|
||||
|
||||
$pdf->SetTextColor(0, 69, 99);
|
||||
$pdf->SetFont('helvetica', '', 10);
|
||||
|
||||
$pdf->AddPage();
|
||||
|
||||
// L'abscisse x varie de 10 à 200 (soit une marge de 10 à gauche et 10 à droite)
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Adresse du client :
|
||||
$x = 120; // Doit rester < 200 qui est la marge droite !
|
||||
$y = 30;
|
||||
$pdf->CreateTextBox($client['entreprise'], $x, $y, (200 - $x), 12, 12, 'B', 'L');
|
||||
$y += 6;
|
||||
$pdf->CreateTextBox($client['nom_complet'], $x, $y, (200 - $x), 10, 10, '', 'L');
|
||||
$y += 5;
|
||||
$pdf->CreateTextBox($client['rue'], $x, $y, (200 - $x), 10, 10, '', 'L');
|
||||
$y += 5;
|
||||
$pdf->CreateTextBox($client['ville_complete'], $x, $y, (200 - $x), 10, 10, '', 'L');
|
||||
$y += 5;
|
||||
$pdf->CreateTextBox($client['libelle_pays'], $x, $y, (200 - $x), 10, 10, '', 'L');
|
||||
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// N° de commande :
|
||||
$x = 10;
|
||||
$y += 10;
|
||||
$pdf->CreateTextBox($nom_piece.' '.$piece['no'], $x, $y, (200 - $x), 20, 20, 'B', 'L');
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Date :
|
||||
$x = 120;
|
||||
$y += 15;
|
||||
|
||||
$pdf->CreateTextBox('Date : '.date(''.$_SESSION['textes']['all']['all']['date']['format_d_m_y'].''), $x, $y, (200 - $x), 10, 10, '', 'R');
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Tableau
|
||||
$x = 10;
|
||||
$y += 15;
|
||||
$pdf->Line($x, $y, (210 - $x), $y); // Ligne horizontale
|
||||
|
||||
$x = 10;
|
||||
// $y += 5;
|
||||
$largeur_1 = 90;
|
||||
$largeur_2 = 20;
|
||||
$largeur_3 = 30;
|
||||
$largeur_4 = 20;
|
||||
$largeur_5 = 30;
|
||||
$pdf->CreateTextBox($_SESSION['textes']['fonctions_pdf']['document']['piece']['designation_titre'], $x, $y, $largeur_1, 10, 10, 'B', 'L', 1); // Ligne d'entête
|
||||
$x += $largeur_1;
|
||||
$pdf->CreateTextBox($_SESSION['textes']['fonctions_pdf']['document']['piece']['quantite_titre'], $x, $y, $largeur_2, 10, 10, 'B', 'C', 1);
|
||||
$x += $largeur_2;
|
||||
$pdf->CreateTextBox($_SESSION['textes']['fonctions_pdf']['document']['piece']['pu_ht_titre'], $x, $y, $largeur_3, 10, 10, 'B', 'R', 1);
|
||||
$x += $largeur_3;
|
||||
$pdf->CreateTextBox($_SESSION['textes']['fonctions_pdf']['document']['piece']['taux_tva_titre'], $x, $y, $largeur_4, 10, 10, 'B', 'C', 1);
|
||||
$x += $largeur_4;
|
||||
$pdf->CreateTextBox($_SESSION['textes']['fonctions_pdf']['document']['piece']['pt_ttc_titre'], $x, $y, $largeur_5, 10, 10, 'B', 'R', 1);
|
||||
|
||||
$x = 10;
|
||||
$y += 10;
|
||||
$pdf->Line($x, $y, (210 - $x), $y); // Ligne horizontale
|
||||
|
||||
$x = 10;
|
||||
// $y += 5;
|
||||
for ($i = 0; $i < $piece['nb_lignes']; $i ++)
|
||||
{
|
||||
$pdf->CreateTextBox($lignes[$i]['designation'],
|
||||
$x, $y, $largeur_1, 10, 10, '', 'L');
|
||||
$x += $largeur_1;
|
||||
$pdf->CreateTextBox($lignes[$i]['qte'],
|
||||
$x, $y, $largeur_2, 10, 10, '', 'C');
|
||||
$x += $largeur_2;
|
||||
$pdf->CreateTextBox(number_format($lignes[$i]['pu_ht'], 2, ".", " ").' €',
|
||||
$x, $y, $largeur_3, 10, 10, '', 'R');
|
||||
$x += $largeur_3;
|
||||
$pdf->CreateTextBox(number_format($lignes[$i]['taux_tva'], 2, ".", " ").' %',
|
||||
$x, $y, $largeur_4, 10, 10, '', 'C');
|
||||
$x += $largeur_4;
|
||||
$pdf->CreateTextBox(number_format(($lignes[$i]['qte'] * $lignes[$i]['pu_ht'] * (1 + ($lignes[$i]['taux_tva']/100))), 2, ".", " ").' €',
|
||||
$x, $y, $largeur_5, 10, 10, '', 'R');
|
||||
$x = 10;
|
||||
$y += 5;
|
||||
|
||||
if ($y > 260) // Détection d'un saut de page nécessaire
|
||||
{
|
||||
$y = 30;
|
||||
$pdf->AddPage();
|
||||
}
|
||||
}
|
||||
|
||||
// Ligne horizontale :
|
||||
$x = 10;
|
||||
$y += 5;
|
||||
$pdf->Line($x, $y, (210 - $x), $y);
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Vérification si un saut de page est nécessaire :
|
||||
if ($y > 260)
|
||||
{
|
||||
$y = 30;
|
||||
$pdf->AddPage();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Totaux :
|
||||
$x = 10;
|
||||
// $y += 5;
|
||||
$pdf->CreateTextBox('TOTAL', $x, $y, $largeur_1, 10, 11, 'B', 'R');
|
||||
$x += $largeur_1;
|
||||
$x += $largeur_2;
|
||||
$pdf->CreateTextBox(number_format($piece['total_ht'], 2, ".", " ").' €',
|
||||
$x, $y, $largeur_3, 10, 11, '', 'R');
|
||||
$x += $largeur_3;
|
||||
$x += $largeur_4;
|
||||
$pdf->CreateTextBox(number_format($piece['total_ttc'], 2, ".", " ").' €',
|
||||
$x, $y, $largeur_5, 10, 11, 'B', 'R');
|
||||
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Commentaire :
|
||||
if ($piece['commentaire'] != "")
|
||||
{
|
||||
if ($y > 260) // Vérification si un saut de page est nécessaire
|
||||
{
|
||||
$y = 30;
|
||||
$pdf->AddPage();
|
||||
}
|
||||
|
||||
$x = 10;
|
||||
$y += 30;
|
||||
$pdf->SetFont('helvetica', '', 10);
|
||||
$pdf->MultiCell((200 - $x), 10, $piece['commentaire'],
|
||||
'TRBL', 'J', 0, 1, $x, $y, true, 0, true, true);
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Ajout des numéros de page :
|
||||
// NB : les fonctions usuelles ('getAliasNumPage()' et 'getAliasNbPages()') dans le Header ou le Footer fonctionnent bien mais posent des soucis d'alignement...
|
||||
$nb_pages = $pdf->getNumPages();
|
||||
|
||||
for($i = 1; $i < ($nb_pages + 1); $i ++)
|
||||
{
|
||||
$pdf->setPage($i);
|
||||
$pdf->SetFont('helvetica', '', 10);
|
||||
$pdf->SetTextColor(0, 69, 99);
|
||||
$pdf->SetXY(150,10);
|
||||
$pdf->Cell(50, 10, 'Page '.$i.'/'.$nb_pages, 0, false, 'R');
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// 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('../../documents/'.$rep.'/'.$piece['no'].'.pdf', $pdf_string);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
class MYPDF2 extends TCPDF {
|
||||
public function Header() {
|
||||
// $this->Image('images/logo_shipheart.png', 10, 10, 60, 0, 'PNG', 'https://shipheart.tech');
|
||||
}
|
||||
|
||||
public function CreateTextBox($textval, $x = 0, $y = 0, $width = 0, $height = 10, $fontsize = 10, $fontstyle = '', $align = 'J', $border = 0) {
|
||||
$this->SetXY($x, $y);
|
||||
$this->SetFont('helvetica', $fontstyle, $fontsize);
|
||||
$this->SetFillColor(255,255,255);
|
||||
$this->MultiCell($width, $height, $textval, 0, $align, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//********************************************************************************************************************************
|
||||
// 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', 'https://dev.shipheart.tech/shipmembers.php?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);
|
||||
}
|
||||
|
||||
function generateCode($code){
|
||||
$tempDir = "temp/CodeQR/";
|
||||
|
||||
$codeContents = 'https://shipheart.tech/shipmembers.php?code_acces='.$code;
|
||||
|
||||
$fileName = $code.'.png';
|
||||
|
||||
$pngAbsoluteFilePath = $tempDir.$fileName;
|
||||
$urlRelativeFilePath = $tempDir.$fileName;
|
||||
|
||||
// generating
|
||||
if (!file_exists($pngAbsoluteFilePath)) {
|
||||
QRcode::png($codeContents, $pngAbsoluteFilePath);
|
||||
}
|
||||
return $urlRelativeFilePath;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
$traductions_en = include __DIR__ . "/lang/en.php";
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Recherche dans le fichier de langue (de type 'lang/en.php') l'occurence du texte français reçu en paramètre.
|
||||
// S'il existe, retour de la traduction. Sinon, retour du texte en FR.
|
||||
// Reçoit : Texte en FR
|
||||
// Retour : Texte dans la langue en cours.
|
||||
//************************************************************************************************************
|
||||
function t($texte)
|
||||
{
|
||||
global $traductions_en;
|
||||
if ($_SESSION['langue'] === 'EN') {
|
||||
return $traductions_en[$texte] ?? $texte; // Repli sur le français si la traduction manque
|
||||
}
|
||||
return $texte;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
SELECT (SELECT Texte FROM TB_Textes_traduction WHERE ID_LANGUAGES=(SELECT ID FROM TB_Langues WHERE Prefix="FR") AND ID_TYPE=2 AND TB_Textes_traduction.ID_TEXTES=TB_Textes_acces.ID_TEXTES) AS Libelle FROM TB_Textes_acces
|
||||
WHERE Validite='1' AND
|
||||
Fichier="all" AND
|
||||
Page="all" AND
|
||||
Bloc="erreurs" AND
|
||||
Nom="email_invalide"
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// Remarque :
|
||||
// !!!!!!!!!!!!!!! Ne pas utiliser dans les attributs "title" "placeholder" et dans les buttons qui sont déjà des HREF !!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Récupération dans la base de données d'un texte
|
||||
// Reçoit : Nom du fichier, page, bloc et nom
|
||||
// Retour : Texte dans la langue en cours.
|
||||
// NB : Si l'accès est fait par un administrateur, un lien est ajouté au texte pour le rendre cliquable (dans le but de pouvoir le modifier)
|
||||
//************************************************************************************************************
|
||||
function Recuperer_texte($fichier, $page, $bloc, $nom){
|
||||
$texte = stripcslashes($_SESSION['textes'][$fichier][$page][$bloc][$nom]);
|
||||
if (($_SESSION['acces_valide']) && ($_SESSION['shipmember']['Niveau_acces'] >= NIVEAU_EDITEUR_ACCES_ADMINISTATEUR)){
|
||||
|
||||
if ($_SESSION['modifier_texte'] == 1) $texte = $texte.'<a id="" href="textes.php?action=navigation&destination=Accueil&fichier='.$fichier.'&page='.$page.'&bloc='.$bloc.'&nom='.$nom.'¤t_page='.basename($_SERVER['SCRIPT_FILENAME']).'" class="a_update"></a>';
|
||||
}
|
||||
|
||||
return $texte;
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Récupération dans la base de données du lien du texte (spécial pour les NAVBAR)
|
||||
// Reçoit : Nom du fichier, page, bloc et nom
|
||||
// Retour : Lien sous la forme d'un '<a>.....</a>" permettant l'accès à la modification du texte
|
||||
// Navbar spécial ( class update_navbar pour bien afficher)
|
||||
//************************************************************************************************************
|
||||
function Ajouter_lien_modif($fichier, $page, $bloc, $nom){
|
||||
$texte = "";
|
||||
if (($_SESSION['acces_valide']) && ($_SESSION['shipmember']['Niveau_acces'] >= NIVEAU_EDITEUR_ACCES_ADMINISTATEUR)){
|
||||
|
||||
if ($_SESSION['modifier_texte'] == 1) $texte = '<a id="" href="textes.php?action=navigation&destination=Accueil&fichier='.$fichier.'&page='.$page.'&bloc='.$bloc.'&nom='.$nom.'¤t_page='.basename($_SERVER['SCRIPT_FILENAME']).'" class="a_update update_navbar"></a>';
|
||||
}
|
||||
|
||||
return $texte;
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Récupération dans la base de données du lien du texte (pour les BUTTONS et les HREF)
|
||||
// Reçoit : Nom du fichier, page, bloc et nom
|
||||
// Retour : Lien sous la forme d'un '<a>.....</a>" permettant l'accès à la modification du texte
|
||||
// Le reste des buttons et href (suppression de la classe update_navbar)
|
||||
//************************************************************************************************************
|
||||
function Ajouter_lien_modif_buttons($fichier, $page, $bloc, $nom){
|
||||
$texte = "";
|
||||
if (($_SESSION['acces_valide']) && ($_SESSION['shipmember']['Niveau_acces'] >= NIVEAU_EDITEUR_ACCES_ADMINISTATEUR)){
|
||||
|
||||
if ($_SESSION['modifier_texte'] == 1) $texte = '<a id="" href="textes.php?action=navigation&destination=Accueil&fichier='.$fichier.'&page='.$page.'&bloc='.$bloc.'&nom='.$nom.'¤t_page='.basename($_SERVER['SCRIPT_FILENAME']).'" class="a_update"></a>';
|
||||
}
|
||||
|
||||
return $texte;
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Chargement d'une langue. Cela se traduit par charger dans une GROSSE variable de session tous les textes dans la langue choisie.
|
||||
// Reçoit : Rien
|
||||
// Retour : Rien (mais met à jour la variable de session contenant tous les textes)
|
||||
// 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
|
||||
//********************************************************************************************************************************
|
||||
function chargement_langue()
|
||||
{
|
||||
|
||||
Ouverture_bdd(); // Connexion à MySql
|
||||
|
||||
$requete = "SELECT Fichier, Page, Bloc, Nom, (SELECT Texte FROM TB_Textes_traduction WHERE ID_LANGUAGES=(SELECT ID FROM TB_Langues WHERE Prefix=?) AND ID_TYPE = ".TYPE_UTILISATEUR_PROFESSIONNEL." AND TB_Textes_traduction.ID_TEXTES=TB_Textes_acces.ID_TEXTES) AS Libelle FROM TB_Textes_acces WHERE Validite='1'";
|
||||
$reponse = Requete_preparee_bdd($requete,
|
||||
array(
|
||||
array('s', $_SESSION['langue'])),
|
||||
__FILE__, __LINE__);
|
||||
while ($donnees = Recherche_ligne_bdd($reponse)) // boucle sur tous les enregistrements de la table
|
||||
{
|
||||
$_SESSION['textes'][''.$donnees['Fichier'].''][''.$donnees['Page'].''][''.$donnees['Bloc'].''][''.$donnees['Nom'].''] = stripcslashes($donnees['Libelle']);
|
||||
}
|
||||
Liberation_jeu_de_resultat_bdd($reponse);
|
||||
|
||||
Fermeture_bdd(); // Déconnexion de MySQL
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,585 @@
|
||||
<?php
|
||||
|
||||
// Fonctions par ordre alphabétique...
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Affichage de la date et de l'heure courante
|
||||
// Reçoit : Rien
|
||||
// Retour : Rien (le résultat est renvoyé directement sur la page par 'echo')
|
||||
//************************************************************************************************************
|
||||
function Affichage_date_heure()
|
||||
{
|
||||
echo '<div id="affichage_date_heure">
|
||||
<p>'.Texte_jour_semaine(date("w")).'</p>
|
||||
<p>'.date("d").' '.Texte_mois(date("n")-1).'</p>
|
||||
<p>'.date("Y").'</p>
|
||||
<p>'.date("H:i").'</p>
|
||||
</div>';
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Affichage de la date en cours
|
||||
// Reçoit : Rien
|
||||
// Retour : Rien (le résultat est renvoyé directement sur la page par 'echo')
|
||||
//************************************************************************************************************
|
||||
function Affichage_date()
|
||||
{
|
||||
if (!isset($_SESSION['Prise_rendez_vous']['jour_en_cours'])) $_SESSION['Prise_rendez_vous']['jour_en_cours'] = date("Y-m-d");
|
||||
$current_date = $_SESSION['Prise_rendez_vous']['jour_en_cours'];
|
||||
|
||||
// On regarde si le jour en cours est dans ce mois pour le marquer de façon particulière :
|
||||
$month = substr($current_date, 5, 2);
|
||||
$year = substr($current_date, 0, 4);
|
||||
$day = substr($current_date, 8, 2);
|
||||
$time = mktime(0,0,0, $month, $day, $year);
|
||||
|
||||
echo '<div id="affichage_date">
|
||||
<p>'.Texte_jour_semaine(date("w", $time)).'</p>
|
||||
<p>'.date("d", $time).' '.Texte_mois(date("n", $time)-1).'</p>
|
||||
<p>'.date("Y", $time).'</p>
|
||||
</div>';
|
||||
// echo '<div style="text-align:center; margin-top:20px;">
|
||||
// <span style="font-size:2.5em; font-weight:bold;">'.Texte_jour_semaine(date("w", $time)).'<br />'
|
||||
// .date("j", $time).' '.Texte_mois(date("n", $time)-1).' '.date("Y", $time).'</span><br />
|
||||
// </div>';
|
||||
}
|
||||
|
||||
|
||||
//********************************************************************************************************************************
|
||||
// Fonction : Vérifie la longueur d'un paramètre de formulaire en fonction de valeurs mini et maxi reçues et
|
||||
// renvoie une chaine d'erreur dans la langue en cours
|
||||
// Reçoit : Le titre du champ, la chaine du champs à vérifier, la longueur mini et la longueur maxi
|
||||
// Retour : Une chaine d'erreur. Vide si aucune erreur ou message dans la langue en cours
|
||||
//********************************************************************************************************************************
|
||||
function check_longueur_champ($titre_champ, $champ, $min, $max)
|
||||
{
|
||||
$longueur = strlen($champ);
|
||||
$retour = "";
|
||||
if (($longueur < $min) OR ($longueur > $max))
|
||||
{
|
||||
$retour .= '['.$_SESSION['textes']['all']['all']['all'][''.$titre_champ.''].'] ';
|
||||
$retour .= $_SESSION['textes']['all']['all']['erreurs']['longueur_champ_invalide'];
|
||||
$retour .= ' (min = '.$min.' - max = '.$max.')';
|
||||
$retour .= '<br />';
|
||||
}
|
||||
return($retour);
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Affiche le comparatif des versions de ShipHeart qui est utilisé sur la Boutique et sur la page
|
||||
// d'Accueil.
|
||||
// Reçoit : Rien
|
||||
// Retour : Rien (le résultat est renvoyé directement sur la page par 'echo')
|
||||
//************************************************************************************************************
|
||||
function comparatif_shiphearts()
|
||||
{
|
||||
|
||||
$nom_page = basename($_SERVER['SCRIPT_FILENAME']);
|
||||
|
||||
// Variables spécifiques au fichier d'origine :
|
||||
switch($nom_page)
|
||||
{
|
||||
case 'accueil.php' :
|
||||
{
|
||||
$image_coche = "selection_blanc.png";
|
||||
$type_fond = "fond_fonce";
|
||||
break;
|
||||
}
|
||||
case 'boutique.php' :
|
||||
{
|
||||
$image_coche = "selection.png";
|
||||
$type_fond = "fond_clair";
|
||||
break;
|
||||
}
|
||||
default : { $image_coche = "selection_hover.png"; break; }
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Récupération des données :
|
||||
Ouverture_bdd(); // Connexion à MySql
|
||||
|
||||
// Variables spécifiques à la langue :
|
||||
switch($_SESSION['langue'])
|
||||
{
|
||||
case "EN" : { $texte_coche = "Yes"; break; }
|
||||
case "FR" : { $texte_coche = "Oui"; break; }
|
||||
default : { $texte_coche = "langue_non_féfinie"; break; } // Ce texte ne sera jamais trouvé, donc jamais remplacé....
|
||||
}
|
||||
|
||||
$nb_lignes_comparatif = 0;
|
||||
$nb_renvois_comparatif = 0;
|
||||
/* $requete = 'SELECT * FROM TB_Comparatif WHERE Validite=1 AND Visible_public=1 ORDER BY Priorite_affichage, Cle_primaire ';
|
||||
// echo "Requete = ".$requete.'<br />';
|
||||
$reponse = Requete_bdd($requete, __FILE__, __LINE__);
|
||||
*/
|
||||
$requete = 'SELECT ID, ';
|
||||
$requete .= 'Renvoi, ';
|
||||
$requete .= '(SELECT Texte FROM TB_Textes_traduction WHERE ID_LANGUAGES=(SELECT ID FROM TB_Langues WHERE Prefix=?) AND ID_TEXTES=ID_FONCTION) AS Texte, ';
|
||||
$requete .= 'CONCAT(\'{\',GROUP_CONCAT(CONCAT(\'"\',ID_PRODUITS,\'":"\',(SELECT Texte FROM TB_Textes_traduction WHERE ID_LANGUAGES=(SELECT ID FROM TB_Langues WHERE Prefix=?) AND ID_TEXTES=ID_RESULTAT),\'"\') ORDER BY ID_PRODUITS ASC SEPARATOR ","),"}") AS Produits ';
|
||||
$requete .= 'FROM TB_Galerie_comparatif LEFT JOIN TB_Comparatif ON TB_Galerie_comparatif.ID_COMPARATIF=TB_Comparatif.ID JOIN TB_Comparatif_produits ON TB_Comparatif.ID=TB_Comparatif_produits.ID_COMPARATIF ';
|
||||
$requete .= 'WHERE TB_Galerie_comparatif.Priorite!=0 GROUP BY TB_Comparatif.ID ORDER BY TB_Galerie_comparatif.Priorite ASC';
|
||||
$reponse = Requete_preparee_bdd($requete,
|
||||
array(
|
||||
array('s', $_SESSION['langue']),
|
||||
array('s', $_SESSION['langue'])),
|
||||
__FILE__, __LINE__);
|
||||
while ($donnees = Recherche_ligne_bdd($reponse))
|
||||
{
|
||||
$lignes_comparatif[$nb_lignes_comparatif]['id'] = $donnees['ID'];
|
||||
$lignes_comparatif[$nb_lignes_comparatif]['fonction'] = $donnees['Texte'];
|
||||
|
||||
// Traitement des renvois de bas de page :
|
||||
if ($donnees['Renvoi'] > 0)
|
||||
{
|
||||
// Recherche si le même texte de renvoi a déjà été utilisé :
|
||||
$renvoi_deja_utilise = 0;
|
||||
for ($i=0; $i<$nb_renvois_comparatif; $i++)
|
||||
{
|
||||
if ($renvois_comparatif[$i]['id'] == $donnees['Renvoi'])
|
||||
{
|
||||
$renvoi_deja_utilise = $renvois_comparatif[$i]['no'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($renvoi_deja_utilise != 0) $lignes_comparatif[$nb_lignes_comparatif]['fonction'] .= '<span class="renvoi">['.$renvoi_deja_utilise.']</span>';
|
||||
else
|
||||
{
|
||||
$renvois_comparatif[$nb_renvois_comparatif]['no'] = $nb_renvois_comparatif + 1;
|
||||
$renvois_comparatif[$nb_renvois_comparatif]['id'] = $donnees['Renvoi'];
|
||||
$renvois_comparatif[$nb_renvois_comparatif]['texte'] = nl2br($_SESSION['textes']['boutique']['accueil']['comparatif']['texte_renvoi_'.$donnees['Renvoi'].'']);
|
||||
|
||||
$lignes_comparatif[$nb_lignes_comparatif]['fonction'] .= '<span class="renvoi">['.($nb_renvois_comparatif + 1).']</span>';
|
||||
|
||||
$nb_renvois_comparatif++;
|
||||
}
|
||||
}
|
||||
|
||||
// Remplacement des textes "Oui"/"Yes" par l'image d'une case cochée + suppression de la langue dans la variable :
|
||||
$lignes_comparatif[$nb_lignes_comparatif]['Produits'] = array();
|
||||
foreach(json_decode($donnees['Produits'], true) as $id_produit => $produit)
|
||||
{
|
||||
$lignes_comparatif[$nb_lignes_comparatif]['Produits'][$id_produit] = str_replace($texte_coche, "<img src=\"images/".$image_coche."\">", $produit);
|
||||
}
|
||||
|
||||
// Demande de regroupement des lignes pour lesquelles les valeurs sont identiques :
|
||||
$lignes_comparatif[$nb_lignes_comparatif]['type_ligne'] = count(array_unique($lignes_comparatif[$nb_lignes_comparatif]['Produits'])) <= 1 ? "unique" : "multiple";
|
||||
|
||||
$nb_lignes_comparatif ++;
|
||||
}
|
||||
Liberation_jeu_de_resultat_bdd($reponse);
|
||||
|
||||
$requete = "SELECT CONCAT('{',GROUP_CONCAT(DISTINCT CONCAT('\"',ID_PRODUITS,'\":\"',(SELECT Texte FROM TB_Textes_traduction WHERE ID_LANGUAGES=(SELECT ID FROM TB_Langues WHERE Prefix=?) AND ID_TEXTES=(SELECT ID_NOM FROM TB_Produits WHERE ID=ID_PRODUITS)),'\"') ORDER BY ID_PRODUITS ASC SEPARATOR ','),'}') AS resultat FROM TB_Comparatif_produits";
|
||||
$reponse = Requete_preparee_bdd($requete,
|
||||
array(
|
||||
array('s', $_SESSION['langue'])),
|
||||
__FILE__, __LINE__);
|
||||
$donnees = Recherche_ligne_bdd($reponse);
|
||||
$title_comparatif = json_decode($donnees['resultat'], true);
|
||||
Liberation_jeu_de_resultat_bdd($reponse);
|
||||
|
||||
Fermeture_bdd(); // Déconnexion de MySQL
|
||||
|
||||
|
||||
//=========================================================================
|
||||
// Affichage :
|
||||
echo '<div class="comparatif">';
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Bouton de sélection de l'affichage ou non de la table de comparaison :
|
||||
echo '<div id="divButtonCollapseComparatif" class="bouton_comparatif plus '.$type_fond.'">';
|
||||
echo '<a title="'.$_SESSION['textes']['boutique']['accueil']['comparatif']['titre_plus_a_title'].'" class="btn" data-bs-toggle="collapse" href="#collapseComparatif" role="button" aria-expanded="false" aria-controls="collapseComparatif" id="buttonCollapseComparatif">
|
||||
'.nl2br($_SESSION['textes']['boutique']['accueil']['comparatif']['titre_plus_a_texte']); // Texte 111
|
||||
echo '</a>';
|
||||
echo '</div>';
|
||||
|
||||
|
||||
echo '<div class="collapse" id="collapseComparatif">';
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Table principale avec fonctions et valeur pour chaque version :
|
||||
echo '<table class="table_comparatif">';
|
||||
echo '<thead>
|
||||
<tr>';
|
||||
/* echo '<th>'.$_SESSION['textes']['boutique']['accueil']['comparatif']['titre_1'].'</th>';
|
||||
|
||||
foreach($title_comparatif as $id_produit => $produit)
|
||||
{
|
||||
echo '<th>'.$produit.'</th>';
|
||||
}
|
||||
*/
|
||||
echo '<th> </th>';
|
||||
echo '<th> </th>';
|
||||
echo '</tr>
|
||||
</thead>';
|
||||
|
||||
// $nb_lignes_comparatif = 0;
|
||||
|
||||
echo '<tbody>';
|
||||
for ($j = 0; $j < $nb_lignes_comparatif; $j ++)
|
||||
{
|
||||
echo '<tr>
|
||||
<td>'.nl2br($lignes_comparatif[$j]['fonction']).'</td>';
|
||||
|
||||
foreach($lignes_comparatif[$j]['Produits'] as $id_produit => $produit)
|
||||
{
|
||||
echo '<td class="version">'.nl2br($produit).'</td>';
|
||||
break;
|
||||
}
|
||||
/* if ($lignes_comparatif[$j]['type_ligne'] == "multiple")
|
||||
{
|
||||
foreach($lignes_comparatif[$j]['Produits'] as $id_produit => $produit)
|
||||
{
|
||||
echo '<td class="version">'.nl2br($produit).'</td>';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach($lignes_comparatif[$j]['Produits'] as $id_produit => $produit)
|
||||
{
|
||||
echo '<td class="version" colspan="4">'.nl2br($produit).'</td>';
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
echo '</tr>';
|
||||
}
|
||||
echo '</tbody>';
|
||||
|
||||
|
||||
echo '</table>';
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Table des renvois :
|
||||
echo '<table class="table_renvois_comparatif">
|
||||
<tbody>';
|
||||
for ($j = 0; $j < $nb_renvois_comparatif; $j ++)
|
||||
{
|
||||
echo '<tr>
|
||||
<td>['.$renvois_comparatif[$j]['no'].'] '.nl2br($renvois_comparatif[$j]['texte']).'</td>
|
||||
</tr>';
|
||||
}
|
||||
|
||||
echo '</tbody>
|
||||
</table>';
|
||||
|
||||
echo '</div>';
|
||||
|
||||
echo "<script>
|
||||
$('#collapseComparatif').on('shown.bs.collapse', function () {
|
||||
$('#divButtonCollapseComparatif').removeClass('plus');
|
||||
$('#divButtonCollapseComparatif').addClass('moins');
|
||||
$('buttonCollapseComparatif').attr('title','".$_SESSION['textes']['boutique']['accueil']['comparatif']['titre_moins_a_title']."');
|
||||
$('buttonCollapseComparatif').html('".nl2br($_SESSION['textes']['boutique']['accueil']['comparatif']['titre_moins_a_texte'])."');
|
||||
});
|
||||
|
||||
$('#collapseComparatif').on('hidden.bs.collapse', function () {
|
||||
$('#divButtonCollapseComparatif').removeClass('moins');
|
||||
$('#divButtonCollapseComparatif').addClass('plus');
|
||||
$('buttonCollapseComparatif').attr('title','".$_SESSION['textes']['boutique']['accueil']['comparatif']['titre_plus_a_title']."');
|
||||
$('buttonCollapseComparatif').html('".nl2br($_SESSION['textes']['boutique']['accueil']['comparatif']['titre_plus_a_texte'])."');
|
||||
});
|
||||
</script>";
|
||||
|
||||
echo '</div>';
|
||||
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Convertit une valeur de latitude/longitude décimale en chaine de caratères comprenant Degrés, Minutes et Secondes
|
||||
// Reçoit : L'indication "LAT" ou "LON" et la valeur décimale
|
||||
// Retour : La chaine convertie
|
||||
//************************************************************************************************************
|
||||
function Conversion_DECtoDMS($lat_lon, $valeur)
|
||||
{
|
||||
if ($lat_lon == "LAT") $direction = $valeur < 0 ? 'S': 'N';
|
||||
elseif ($lat_lon == "LON") $direction = $valeur < 0 ? 'W': 'E';
|
||||
else $direction = "";
|
||||
|
||||
$signe = $valeur < 0 ? '-': '';
|
||||
|
||||
$degres = floor(abs($valeur ?? 0));
|
||||
|
||||
$decimale = (abs($valeur ?? 0)-$degres) * 3600;
|
||||
|
||||
$min = floor($decimale / 60);
|
||||
$sec = round($decimale - ($min * 60), 1);
|
||||
|
||||
return (sprintf("%s%s°%02d'%04.1f\" %s", $signe, $degres, $min, $sec, $direction));
|
||||
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Enregistrement dans le fichier de log de l'évènement
|
||||
// Reçoit : Le texte à afficher dans le log, le fichier d'origine et la ligne d'origine
|
||||
// Retour : Rien
|
||||
//************************************************************************************************************
|
||||
function Enregistrement_log($texte, $fichier, $ligne)
|
||||
{
|
||||
$repertoire_logs = REPERTOIRE_LOGS."/www_shipheart";
|
||||
if (!file_exists($repertoire_logs) OR !is_dir($repertoire_logs)) // On vérifie d'abord que le répertoire existe, sinon on le créé.
|
||||
{
|
||||
mkdir($repertoire_logs);
|
||||
$message_information .= "Le répertoire de logs [".$repertoire_logs."] n'existait pas. Il vient d'êtrer crééé<br />";
|
||||
}
|
||||
|
||||
$fichier_log = $repertoire_logs.'/log_shipheart_'.date("Y-m-d").'.txt';
|
||||
$prefixe_ligne = date("d/m/Y H:i:s")." [".basename($fichier)." - ".$ligne."] \t: ";
|
||||
$suffixe_ligne = "\r\n";
|
||||
|
||||
$log = fopen($fichier_log, "a+"); // Ouverture en lecture/écriture en mode append...
|
||||
|
||||
fputs($log, $prefixe_ligne); // Entete de ligne
|
||||
fputs($log, $texte); // Ecriture du texte de log
|
||||
fputs($log, $suffixe_ligne); // Fin de ligne
|
||||
|
||||
fclose($log); // Fermetue du fichier.
|
||||
|
||||
if(SHOW_DEBUG)
|
||||
{
|
||||
echo $prefixe_ligne . $texte . $suffixe_ligne;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Conversion de format de dates
|
||||
// Reçoit : Date à convertir
|
||||
// Retour : la chaine mise en forme
|
||||
//************************************************************************************************************
|
||||
function Formatage_date($date)
|
||||
{
|
||||
if ($_SESSION['langue'] == "FR")
|
||||
{
|
||||
switch (substr($date, 5, 2))
|
||||
{
|
||||
case 1: {$mois="janvier"; break;}
|
||||
case 2: {$mois="février"; break;}
|
||||
case 3: {$mois="mars"; break;}
|
||||
case 4: {$mois="avril"; break;}
|
||||
case 5: {$mois="mai"; break;}
|
||||
case 6: {$mois="juin"; break;}
|
||||
case 7: {$mois="juillet"; break;}
|
||||
case 8: {$mois="août"; break;}
|
||||
case 9: {$mois="septembre"; break;}
|
||||
case 10: {$mois="octobre"; break;}
|
||||
case 11: {$mois="novembre"; break;}
|
||||
case 12: {$mois="décembre"; break;}
|
||||
default: $mois = substr($date, 5, 2);
|
||||
}
|
||||
|
||||
$retour = substr($date, 8, 2).' '.$mois.' '.substr($date, 0, 4);
|
||||
|
||||
$suffixe_heure = 'à';
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (substr($date, 5, 2))
|
||||
{
|
||||
case 1: {$mois="January"; break;}
|
||||
case 2: {$mois="February"; break;}
|
||||
case 3: {$mois="March"; break;}
|
||||
case 4: {$mois="April"; break;}
|
||||
case 5: {$mois="May"; break;}
|
||||
case 6: {$mois="June"; break;}
|
||||
case 7: {$mois="July"; break;}
|
||||
case 8: {$mois="August"; break;}
|
||||
case 9: {$mois="September"; break;}
|
||||
case 10: {$mois="October"; break;}
|
||||
case 11: {$mois="November"; break;}
|
||||
case 12: {$mois="December"; break;}
|
||||
default: $mois = substr($date, 5, 2);
|
||||
}
|
||||
|
||||
$jour = ltrim(substr($date, 8, 2), "0"); // Suppression du zéro initial s'il y en a un...
|
||||
switch($jour)
|
||||
{
|
||||
case 1:
|
||||
case 21:
|
||||
case 31: { $suffixe_jour = 'st'; break; }
|
||||
case 2:
|
||||
case 22: { $suffixe_jour = 'nd'; break; }
|
||||
case 3:
|
||||
case 23: { $suffixe_jour = 'rd'; break; }
|
||||
default: { $suffixe_jour = 'th'; break; }
|
||||
}
|
||||
|
||||
$retour = $mois.' '.$jour.'<sup>'.$suffixe_jour.'</sup>, '.substr($date, 0, 4);
|
||||
|
||||
$suffixe_heure = 'at';
|
||||
}
|
||||
|
||||
if (strpos($date, ' ') !== false) $retour .= ' '.$suffixe_heure.' '.substr($date, 11); // Ajout de l'heure si la chaine d'entrée comprend un espace (entre date et heure)
|
||||
|
||||
return($retour);
|
||||
}
|
||||
|
||||
|
||||
//********************************************************************************************************************************
|
||||
// Fonction : Recherche dans le BDD le prochain numéro de document, le formatte, et retourne le n° formatté du nouveau document.
|
||||
// Reçoit : le type de document (cd dans definition.php) et l'année concernée
|
||||
// Retour : Le numéro formatté du nouveau document, -1 si erreur de paramètres, -2 si dépassement de numérotation
|
||||
// ATTENTION : l'accès à la BDD doit être ouvert AVANT d'accéder à cette fonction.
|
||||
// NB : on pourrait l'ouvrir dedans mais on ne sait alors pas s'il faut la refermer...
|
||||
//********************************************************************************************************************************
|
||||
function nouveau_numero_document($type, $annee)
|
||||
{
|
||||
$nb_digits_numerotation = 4;
|
||||
$erreur = 0;
|
||||
|
||||
|
||||
// Contrôles et définition du préfixe au passage :
|
||||
switch($type)
|
||||
{
|
||||
case NUM_TYPE_DEVIS : { $prefixe = "D"; $fonctionRequete = ""; break; }
|
||||
case NUM_TYPE_COMMANDE : { $prefixe = "C"; $fonctionRequete = "porchainNoCommande"; break; }
|
||||
case NUM_TYPE_FACTURE : { $prefixe = "F"; $fonctionRequete = "porchainNoFacture"; break; }
|
||||
case NUM_TYPE_AVOIR : { $prefixe = "A"; $fonctionRequete = ""; break; }
|
||||
default: return (-1);
|
||||
}
|
||||
|
||||
// Recherche d'une numérotation existante :
|
||||
$dernier_no = -1;
|
||||
$requete = "SELECT $fonctionRequete(?) AS No";
|
||||
$reponse = Requete_preparee_bdd($requete,
|
||||
array(
|
||||
array('i', $annee)),
|
||||
__FILE__, __LINE__);
|
||||
$donnees = Recherche_ligne_bdd($reponse);
|
||||
$dernier_no = $donnees['No'];
|
||||
Liberation_jeu_de_resultat_bdd($reponse);
|
||||
|
||||
// Formattage du n° de document :
|
||||
if ($erreur != 0) return($erreur);
|
||||
else return($prefixe.($annee-2000).str_pad($dernier_no, $nb_digits_numerotation, '0', STR_PAD_LEFT));
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Affichage du nom du jour de la semaine en français en version courte (3 lettres)
|
||||
// Reçoit : Jour à convertir (entre 0: dimanche et 6: samedi voire 7:dimanche)
|
||||
// Retour : Le texte court du jour en français
|
||||
//************************************************************************************************************
|
||||
function Texte_court_jour_semaine($jour)
|
||||
{
|
||||
|
||||
switch ($jour)
|
||||
{
|
||||
case 0: {$texte_jour_semaine="Dim"; break;}
|
||||
case 1: {$texte_jour_semaine="Lun"; break;}
|
||||
case 2: {$texte_jour_semaine="Mar"; break;}
|
||||
case 3: {$texte_jour_semaine="Mer"; break;}
|
||||
case 4: {$texte_jour_semaine="Jeu"; break;}
|
||||
case 5: {$texte_jour_semaine="Ven"; break;}
|
||||
case 6: {$texte_jour_semaine="Sam"; break;}
|
||||
case 7: {$texte_jour_semaine="Dim"; break;}
|
||||
default: $texte_jour_semaine = "<Erreur de jour dans fonction 'texte_jour_semaine'>";
|
||||
}
|
||||
return($texte_jour_semaine);
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Affichage du nom du jour de la semaine en français
|
||||
// Reçoit : Jour à convertir (entre 0: dimanche et 6: samedi voire 7:dimanche)
|
||||
// Retour : Le texte du jour en français
|
||||
//************************************************************************************************************
|
||||
function Texte_jour_semaine($jour)
|
||||
{
|
||||
|
||||
switch ($jour)
|
||||
{
|
||||
case 0: {$texte_jour_semaine="dimanche"; break;}
|
||||
case 1: {$texte_jour_semaine="lundi"; break;}
|
||||
case 2: {$texte_jour_semaine="mardi"; break;}
|
||||
case 3: {$texte_jour_semaine="mercredi"; break;}
|
||||
case 4: {$texte_jour_semaine="jeudi"; break;}
|
||||
case 5: {$texte_jour_semaine="vendredi"; break;}
|
||||
case 6: {$texte_jour_semaine="samedi"; break;}
|
||||
case 7: {$texte_jour_semaine="dimanche"; break;}
|
||||
default: $texte_jour_semaine = "<Erreur de jour dans fonction 'texte_jour_semaine'>";
|
||||
}
|
||||
return($texte_jour_semaine);
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Affichage du nom du mois en français
|
||||
// Reçoit : Mois à convertir (entre 0: janvier et 11: décembre)
|
||||
// Retour : Le texte du mois en français
|
||||
//************************************************************************************************************
|
||||
function Texte_mois($mois)
|
||||
{
|
||||
|
||||
switch ($mois)
|
||||
{
|
||||
case 0: {$texte_mois="janvier"; break;}
|
||||
case 1: {$texte_mois="février"; break;}
|
||||
case 2: {$texte_mois="mars"; break;}
|
||||
case 3: {$texte_mois="avril"; break;}
|
||||
case 4: {$texte_mois="mai"; break;}
|
||||
case 5: {$texte_mois="juin"; break;}
|
||||
case 6: {$texte_mois="juillet"; break;}
|
||||
case 7: {$texte_mois="août"; break;}
|
||||
case 8: {$texte_mois="septembre"; break;}
|
||||
case 9: {$texte_mois="octobre"; break;}
|
||||
case 10: {$texte_mois="novembre"; break;}
|
||||
case 11: {$texte_mois="décembre"; break;}
|
||||
default: $texte_mois = "<Erreur de mois dans fonction 'Texte_mois'>";
|
||||
}
|
||||
return($texte_mois);
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// Fonction : Vérification d'un numero de téléphone + formatage
|
||||
// Reçoit : Chaine représentant le numéro
|
||||
// Retour : Le numéro formaté soud la forme "06 12 34 56 78 90"
|
||||
//************************************************************************************************************
|
||||
function Verification_numero_telephone($chaine_numero)
|
||||
{
|
||||
$numero_ok = true;
|
||||
do
|
||||
{
|
||||
switch (strlen($chaine_numero))
|
||||
{
|
||||
case 10 : // Aucun séparateur n'est présent dans la chaine reçue :
|
||||
{
|
||||
for ($i=0; $i<5; $i++) $numeros[$i] = substr($chaine_numero, ($i*2), 2);
|
||||
$chaine_numero = $numeros[0];
|
||||
for ($i=1; $i<5; $i++) $chaine_numero .= ' '.$numeros[$i]; // Ajout des ' ' comme séparateur
|
||||
break;
|
||||
}
|
||||
case 14 : // Un séparateur existe entre chaque groupe de deux chiffres :
|
||||
{
|
||||
for ($i=1; $i<5; $i++) $chaine_numero[($i*3)-1] = ' '; // Remplacement des séparateurs existants par des ' '
|
||||
break;
|
||||
}
|
||||
default : // Comibinaison de nombre de séparateurs ou de chiffres incohérent :
|
||||
{
|
||||
$numero_ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (! $numero_ok) break; // On sort de la boucle DO si une erreur a déjà été trouvée.
|
||||
|
||||
// On décompose les 5 groupes :
|
||||
$numeros = explode(" ", $chaine_numero);
|
||||
if (count($numeros) != 5) {$numero_ok = false; break;}
|
||||
foreach($numeros as $n)
|
||||
{
|
||||
if (strlen($n) != 2) {$numero_ok = false; break;}
|
||||
if (($n < 0) OR ($n > 99)) {$numero_ok = false; break;}
|
||||
}
|
||||
if (($numeros[0] < 1) OR ($numeros[0] > 9)) {$numero_ok = false; break;}
|
||||
} while (0);
|
||||
|
||||
if ($numero_ok) return($chaine_numero);
|
||||
else return ("Numéro non valide");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
// Fichier régénéré automatiquement par extraire_traductions.php
|
||||
// le 25/09/2026 à 16:53:47 - les valeurs vides sont à traduire manuellement.
|
||||
return [
|
||||
'[Email] est invalide !'
|
||||
=> '[Email] is invalid!',
|
||||
'[Email] est déjà utilisée par un ShipMember.<br />Si vous êtes le propriétaire de cette adresse, merci de vous connecter avec cette adresse. <br />Sinon, merci de choisir une autre adresse.'
|
||||
=> '[Email] is already in use by a ShipMember.<br />If you are the owner of this email address, please log in using it. <br />Otherwise, please choose a different email address.',
|
||||
'<p>Félicitations !</p>
|
||||
<p>Votre compte ShipMember est créé, vous y êtes presque.</p>
|
||||
<p>Nom : [[Prenom]] [[Nom]]</p>
|
||||
<p>Email : [[Email]]</p>
|
||||
<p>Mot de passe provisoire : [[Password]]</p>
|
||||
<p>Plus qu’un clic : Connectez-vous sur <a href="https://shipheart.tech">ShipHeart.tech</a> pour valider votre compte ShipMember en modifiant votre mot de passe provisoire (*). C’est une garantie de sécurité à ne pas négliger.</p>
|
||||
<p>Et ensuite, où que vous soyez et dès que votre ShipHeart est installé, accédez à votre bateau via votre accès privilégié ShipMember !</p>
|
||||
<p> </p>
|
||||
<p>Bienvenue parmi nous !</p>
|
||||
<p>L\'équipage ShipHeart</p>
|
||||
<p> </p>
|
||||
<p style="font-size: 0.8em;">(*) L\'activation devra être faite avant le [[Date_maxi_activation]]. Mais pas d\'inquiétude ; si vous ne le faites pas avant, vous pourrez toujours demander un nouveau mot de passe provisoire.</p>'
|
||||
=> '<p>Congratulations!</p>
|
||||
<p>Your ShipMember account has been created – you’re almost there.</p>
|
||||
<p>Surname: [[First name]] [[Surname]]</p>
|
||||
<p>Email: [[Email]]</p>
|
||||
<p>Temporary password: [[Password]]</p>
|
||||
<p>Just one more click: Log in to <a href="https://shipheart.tech">ShipHeart.tech</a> to verify your ShipMember account by changing your temporary password (*). This is an important security measure that should not be overlooked.</p>
|
||||
<p>And then, wherever you are and as soon as your ShipHeart is installed, access your boat via your exclusive ShipMember account!</p>
|
||||
<p> </p>
|
||||
<p>Welcome on board!</p>
|
||||
<p>The ShipHeart crew</p>
|
||||
<p> </p>
|
||||
<p style="font-size: 0.8em;">(*) Activation must be completed by [[Date_maxi_activation]]. But don’t worry; if you don’t manage to do so by then, you can always request a new temporary password.</p>',
|
||||
'Votre accès ShipMember - Un dernier clic pour accéder à votre bateau !'
|
||||
=> 'Your ShipMember login – Just one more click to access your boat!',
|
||||
'Un email vient d\'être envoyé à [[Prenom]] [[Nom]] ([[Email]]) avec un mot de passe provisoire.'
|
||||
=> 'An email has just been sent to [[First name]] [[Surname]] ([[Email]]) containing a temporary password.',
|
||||
'Désolé, votre compte n\'a pas été activé dans le délai maximal.<br />Vous pouvez demander la génération d\'un nouveau mot de passe provisoire en cliquant sur le bouton ci-dessous. Il vous sera adressé immédiatement par email.'
|
||||
=> 'Sorry, your account has not been activated within the maximum time limit.<br />You can request a new temporary password by clicking the button below. It will be sent to you immediately by email.',
|
||||
'Bienvenue !'
|
||||
=> 'Welcome!',
|
||||
'Pour des raisons de sécurité, votre nouveau mot de passe ne peut pas être identique au mot de passe provisoire.'
|
||||
=> 'For safety reason, your new password can\'t be the same than the temporary password.',
|
||||
'Félicitations : votre compte est maintenant activé et vous êtes d\'ores et déjà connecté.e.'
|
||||
=> 'Congratulations: your account is now active and you\'re already logged in.',
|
||||
'Les deux mots de passe saisis doivent être identiques.'
|
||||
=> 'Both passwords shall be the same.',
|
||||
'Le mot de passe renseigné n\'est pas conforme. Pour la sécurité de vos données, il doit contenir entre 6 et 20 caractères, et être composé exclusivement de minuscules, de majuscules, de chiffres ou des caractères spéciaux suivants _-!*=.'
|
||||
=> 'The password you have entered not valid. To insure the security of your data, it must contain between 6 and 20 characters, and must consist exclusively of lower-case letters, upper-case letters, numbers or the following special characters _-!*=.',
|
||||
'<p>Bonjour,</p>
|
||||
<p>Le mot de passe de votre compte ShipMember vient d\'être réinitialisé à votre demande.</p>
|
||||
<p>Nom : [[Prenom]] [[Nom]]</p>
|
||||
<p>Email : [[Email]]</p>
|
||||
<p>Mot de passe provisoire : [[Password]]</p>
|
||||
<p>Plus qu’un clic : Connectez-vous sur <a href="https://ship2net.fr">Ship2net.fr</a> pour activer votre compte ShipMember en modifiant votre mot de passe provisoire (*). C’est une garantie de sécurité à ne pas négliger...</p>
|
||||
<p>Bienvenue à nouveau parmi nous !</p>
|
||||
<p>L\'équipage ShipHeart</p>
|
||||
<p> </p>
|
||||
<p style="font-size: 0.8em;">(*) L\'activation devra être faite avant le [[Date_maxi_activation]]. Mais pas d\'inquiétude ; si vous ne le faites pas avant, vous pourrez toujours demander un nouveau mot de passe provisoire.</p>'
|
||||
=> '<p>Hello,</p>
|
||||
<p>The password for your ShipMember account has just been reset at your request.</p>
|
||||
<p>Surname: [[First name]] [[Surname]]</p>
|
||||
<p>Email: [[Email]]</p>
|
||||
<p>Temporary password: [[Password]]</p>
|
||||
<p>Just one more click: Log in to <a href="https://ship2net.fr">Ship2net.fr</a> to activate your ShipMember account by changing your temporary password (*). This is an important security measure that should not be overlooked...</p>
|
||||
<p>Welcome back!</p>
|
||||
<p>The ShipHeart team</p>
|
||||
<p> </p>
|
||||
<p style="font-size: 0.8em;">(*) Activation must be completed by [[Date_maxi_activation]]. But don’t worry; if you don’t manage to do so by then, you can always request a new temporary password.</p>',
|
||||
'Votre demande concernant votre accès ShipMember'
|
||||
=> 'Your enquiry regarding your ShipMember access',
|
||||
'Un email vient d\'être envoyé à [[Prenom]] [[Nom]] ([[Email]]) avec les informations relatives à votre inscription.'
|
||||
=> 'An email has just been sent to [[First name]] [[Surname]] ([[Email]]) containing details of your registration.',
|
||||
'<p>Bonjour,</p>
|
||||
<p>L\'adresse email associée à votre compte ShipMember vient d\'être modifiée à votre demande :</p>
|
||||
<p>Ancienne adresse : [[Old_email]]</p><p>Nouvelle adresse : [[New_email]]</p>
|
||||
<p>Si vous n\'êtes pas à l\'origine de ce changement d\'adresse, merci de contacter sans attendre l\'administrateur du site à : <a href="mailto:[[Adresse_email_alertes]]">[[Adresse_email_alertes]].\'</a></p>
|
||||
<p>L\'équipage ShipHeart</p>'
|
||||
=> '<p>Hello,</p>
|
||||
<p>The email address associated with your ShipMember account has just been changed at your request:</p>
|
||||
<p>Old address: [[Old_email]]</p><p>New address: [[New_email]]</p>
|
||||
<p>If you did not request this change of address, please contact the site administrator immediately at: <a href="mailto:[[Adresse_email_alertes]]">[[Alert_email_address]].\'</a></p>
|
||||
<p>The ShipHeart team</p>',
|
||||
'Modifications de votre accès ShipMember'
|
||||
=> 'Changes to your ShipMember access',
|
||||
'Connectez-vous'
|
||||
=> 'Log in',
|
||||
'Déjà ShipMember ?'
|
||||
=> 'Already ShipMember?',
|
||||
'Merci de vous identifier :'
|
||||
=> 'Thank you for logging in:',
|
||||
'Email'
|
||||
=> 'Email',
|
||||
'Saisissez votre adresse email...'
|
||||
=> 'Enter your email address...',
|
||||
'Mot de passe'
|
||||
=> 'Password',
|
||||
'Saisissez votre mot de passe...'
|
||||
=> 'Enter your password...',
|
||||
'Valider'
|
||||
=> 'Confirm',
|
||||
'Générer un nouveau mot de passe'
|
||||
=> 'Generate a new password',
|
||||
'Pas encore ShipMember ?'
|
||||
=> 'Not a ShipMember yet?',
|
||||
'Merci de renseigner vos coordonnées ; votre espace ShipMember sera créé immédiatement :'
|
||||
=> 'Please fill in your details; your ShipMember account will be created immediately.',
|
||||
'Prénom'
|
||||
=> 'First name',
|
||||
'Nom'
|
||||
=> 'Last name',
|
||||
'Entreprise'
|
||||
=> 'Company',
|
||||
'Numéro et rue'
|
||||
=> 'Number and street',
|
||||
'Numéro et nom de voie, bâtiment, appartement, lotissement, ...'
|
||||
=> 'Number and name of lane, building, flat, housing estate,...',
|
||||
'Code postal'
|
||||
=> 'Postcode',
|
||||
'Ville'
|
||||
=> 'City',
|
||||
'Pays'
|
||||
=> 'Country',
|
||||
'Téléphone'
|
||||
=> 'Phone',
|
||||
'Mon espace ShipMember'
|
||||
=> 'My ShipMember account',
|
||||
'Activation de mon compte'
|
||||
=> 'Activation of my account',
|
||||
'Votre compte n\'a pas encore été activé. Pour cela, merci de changer votre mot de passe provisoire ci-dessous.'
|
||||
=> 'Your account has not yet been activated. Please change your temporary password below.',
|
||||
'Nouveau mot de passe'
|
||||
=> 'New password',
|
||||
'Entre 6 et 20 caractères, et être composé exclusivement de minuscules, majuscules, de chiffres ou des caractères spéciaux suivants _-!*=.'
|
||||
=> 'Between 6 and 20 characters, and must consist exclusively of lower-case letters, upper-case letters, numbers or the following special characters _-!*=.',
|
||||
'Nouveau mot de passe (2)'
|
||||
=> 'New password (2)',
|
||||
'Saisissez à nouveau votre nouveau mot de passe...'
|
||||
=> 'Re-enter your new password...',
|
||||
'Générer un nouveau mot de passe provisoire'
|
||||
=> 'Generate a new temporary password',
|
||||
'Renseignez votre adresse email puis confirmez votre demande. <br />Si votre adresse existe bien dans la liste des ShipMembers, un email vous sera adressé immédiatement avec un nouveau mot de passe provisoire.'
|
||||
=> 'Fill in your email address and confirm your request.<br />If your address exists in the ShipMembers list, an email will be sent to you immediately with a new temporary password.',
|
||||
'Attention : dès validation, seul ce nouveau mot de passe provisoire sera valide pour vous connecter. Si vous n\'avez pas reçu cet email dans les prochaines minutes, merci de vérifier s\'il ne se trouve pas dans vos courriers indésirables. '
|
||||
=> 'Caution: as soon as you confirm, only this new temporary password will be valid to connect you. If you have not received this email within the next few minutes, please check your spam folder.',
|
||||
'Valider votre saisie...'
|
||||
=> 'Confirm your entry...',
|
||||
'Bienvenue dans votre espace ShipMember !'
|
||||
=> 'Welcome to your ShipMember area !',
|
||||
'Vous trouverez ici toutes les informations que nous conservons vous concernant. Notre objectif est de ne conserver que celles nécessaires au traitement de vos commandes et, surtout, vous permettant de profiter pleinement de toutes les fonctions de votre ShipHeart.'
|
||||
=> 'You\'ll find here all the information we keep about you. Our aim is to keep only the information necessary to process your orders and, above all, to allow you to take full advantage of all the functions of your ShipHeart.',
|
||||
'Enfin, nous vous rappelons que Koriolan ne diffuse et ne diffusera jamais la moindre de ces informations à d\'autres sociétés. Pour plus de précisions sur le traitement de vos données personnelles, n\'hésitez pas à consulter nos mentions légales accessibles en bas de cette page.'
|
||||
=> 'Finally, we would like to remind you that Koriolan does not and will never distribute any of this information to other companies. For more information on the processing of your personal data, please consult our legal notice at the bottom of this page.',
|
||||
'Voir les informations liées à votre compte ShipMember...'
|
||||
=> 'View your ShipMember account information...',
|
||||
'Mes informations'
|
||||
=> 'My information',
|
||||
'Accéder à mon bateau...'
|
||||
=> 'Getting to my boat...',
|
||||
'Mon bateau'
|
||||
=> 'My boat',
|
||||
'Fermer votre session...'
|
||||
=> 'Close your session...',
|
||||
'Déconnexion'
|
||||
=> 'Logout',
|
||||
'Numéro de ShipMember'
|
||||
=> 'ShipMember number',
|
||||
'Accéder au menu de modification de vos informations...'
|
||||
=> 'Go to the menu for changing your details...',
|
||||
'Modifier'
|
||||
=> 'Edit',
|
||||
'Retour à mon espace ShipMember...'
|
||||
=> 'Back to my ShipMember account...',
|
||||
'Retour'
|
||||
=> 'Back',
|
||||
'Modifier mes informations'
|
||||
=> 'Edit my details',
|
||||
'Si vous souhaitez modifier votre mot de passe, entrez votre nouveau mot de passe <u>deux fois</u> ci-dessous. Sinon, laissez ces deux champs vides.'
|
||||
=> 'If you wish to change your password, enter your new password <u>twice</u> below. Otherwise, leave these two fields blank.',
|
||||
'Saisissez votre nouveau mot de passe...'
|
||||
=> 'Enter your new password...',
|
||||
'Annuler la saisie...'
|
||||
=> 'Cancel your entry...',
|
||||
'Annuler'
|
||||
=> 'Cancel',
|
||||
'Accès à mes bateaux'
|
||||
=> 'Access to my boats',
|
||||
'Accès à mon bateau'
|
||||
=> 'Access to my boat',
|
||||
'Vous n\'avez pas encore de ShipHeart activé.'
|
||||
=> 'You do not yet have a ShipHeart activated.',
|
||||
'Mais dès que ce sera le cas, vous trouverez ici l\'accès à votre ou vos bateaux.'
|
||||
=> 'But as soon as that happens, you’ll find access to your boat or boats here.',
|
||||
'Pour chacun d\'eux, vous visualiserez l\'état de tous les circuits, leur consommation, le niveau des réservoirs et des batteries, mais aussi toutes les valeurs de vos capteurs : températures, pression atmosphérique, humidité, position géographique, etc... <br />Vous aurez également accès aux courbes historiques de toutes ces valeurs.'
|
||||
=> 'For each one, you will be able to view the status of all circuits, their power consumption, the levels of the tanks and batteries, as well as all the readings from your sensors: temperatures, atmospheric pressure, humidity, geographical position, etc... <br />You will also have access to historical trends for all these readings.',
|
||||
'C\'est également ici que vous pourrez créer des profils [Propriétaire], [Installateur] ou [Skipper] afin de donner accès de façon contrôlée à votre ou à vos bateaux. Sans aucune limite !'
|
||||
=> 'This is also where you can create [Owner], [Installer] or [Skipper] profiles to grant controlled access to your boat or boats. There are no limits!',
|
||||
'Revenir à mon espace ShipMember...'
|
||||
=> 'Back to my ShipMember dashboard...',
|
||||
'ShipHeart by Koriolan, la première centrale de vie à bord pour les bateaux de plaisance'
|
||||
=> 'ShipHeart by Koriolan, the first on-board life support system for pleasure craft',
|
||||
'Retour à l\'accueil'
|
||||
=> 'Back to home page...',
|
||||
'Switch to English...'
|
||||
=> 'Revenir en français...',
|
||||
'Accès validé pour '
|
||||
=> 'Access granted to ',
|
||||
'ShipHeart ™ est une marque de Koriolan'
|
||||
=> 'ShipHeart™ is a brand of Koriolan',
|
||||
'Accéder à notre site Koriolan'
|
||||
=> 'Visit our Koriolan website',
|
||||
'Mentions légales'
|
||||
=> 'Legal notices',
|
||||
];
|
||||
|
||||
/*
|
||||
// OBSOLÈTES au 25/09/2026 à 16:53:47 - plus utilisées dans le code.
|
||||
// À supprimer manuellement une fois confirmé qu'elles ne servent vraiment plus.
|
||||
'Bienvenue à bord' => 'Welcome aboard',
|
||||
*/
|
||||
Reference in New Issue
Block a user