Import initial du site ship2net.fr : pages PHP, config, traductions t(), composer.json

This commit is contained in:
2026-09-28 08:04:25 +00:00
commit 82f431b3ae
175 changed files with 25531 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
config/config.php
config/confidentiel.php
config/lang/*.bak
temp/
*.bak
vendor/*
!vendor/phpqrcode/
vendor/phpqrcode/cache/
html/vendor_OLD/
+175
View File
@@ -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 &#153;");
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);
+12
View File
@@ -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");
+585
View File
@@ -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);
}
+250
View File
@@ -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>";
// }
// }
}
+108
View File
@@ -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);
}
+338
View File
@@ -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', '&amp;');
ini_set("url_rewriter.tags","a=href,area=href,frame=src,iframe=src,input=src"); // Ces deux lignes sont destinées à faire ajouter autoamtiquement &amp; au lieu de '&' dans la passage des variables de Session (nécessaire pour W3C validator...)
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()
+103
View File
@@ -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.";
}
}
+353
View File
@@ -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;
}
+123
View File
@@ -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.'&current_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.'&current_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.'&current_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
}
+585
View File
@@ -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");
}
+219
View File
@@ -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',
*/
+89
View File
@@ -0,0 +1,89 @@
<?php
// Parcourt tous les fichiers .php sous /var/www/html et /var/www/config,
// repère chaque appel t("...") et régénère lang/en.php en conséquence -
// équivalent de 'lupdate' pour ce mécanisme de traduction "à la Qt".
//
// - Les traductions déjà faites, pour des chaînes encore utilisées dans le
// code, sont conservées telles quelles.
// - Les nouvelles chaînes (trouvées dans le code, absentes de en.php)
// sont ajoutées avec une valeur vide, à traduire manuellement.
// - Les entrées obsolètes (présentes dans en.php, plus utilisées dans le
// code) sont déplacées en fin de fichier, en commentaire - à supprimer à
// la main une fois vérifié qu'elles ne servent vraiment plus à rien.
//
// Limite connue et acceptée (même limite que qsTr()/gettext) : ne détecte
// que les chaînes littérales simples (pas de concaténation dynamique).
// Pour du texte avec contenu variable, utiliser un espace réservé :
// sprintf(t("Bonjour %s"), $nom)
// plutôt que t("Bonjour " . $nom) - la seconde forme ne sera pas détectée.
$racine = "/var/www";
$fichier_en = "$racine/config/lang/en.php";
$chaines_trouvees = [];
$iterateur = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($racine));
foreach ($iterateur as $fichier) {
if (!str_ends_with($fichier->getFilename(), ".php")) continue;
if (str_contains($fichier->getPathname(), "/lang/")) continue; // ne pas s'auto-analyser
if ($fichier->getFilename() === basename(__FILE__)) continue; // idem, pour le script lui-même
$contenu = file_get_contents($fichier->getPathname());
if (preg_match_all('/\bt\(\s*"((?:[^"\\\\]|\\\\.)*)"\s*\)/', $contenu, $matches)) {
foreach ($matches[1] as $chaine) {
$chaine = stripcslashes($chaine);
$chaines_trouvees[$chaine][] = $fichier->getPathname();
}
}
}
$traductions_en = file_exists($fichier_en) ? include $fichier_en : [];
// --- Rapport console, comme avant ---
echo "=== Chaînes utilisées dans le code : " . count($chaines_trouvees) . " ===\n\n";
$manquantes = [];
foreach ($chaines_trouvees as $chaine => $fichiers) {
if (!array_key_exists($chaine, $traductions_en)) {
$manquantes[$chaine] = $fichiers[0];
}
}
echo count($manquantes) . " nouvelle(s) chaîne(s) à traduire.\n";
$obsoletes = array_diff(array_keys($traductions_en), array_keys($chaines_trouvees));
echo count($obsoletes) . " entrée(s) obsolète(s), déplacée(s) en commentaire.\n\n";
// --- Régénération de lang/en.php ---
// Sauvegarde de précaution avant d'écraser :
if (file_exists($fichier_en)) {
copy($fichier_en, "$fichier_en.bak");
}
// Fusion : traductions existantes conservées pour les chaînes encore utilisées,
// nouvelles chaînes ajoutées avec une valeur vide :
$nouveau_tableau = [];
foreach ($chaines_trouvees as $chaine => $fichiers) {
$nouveau_tableau[$chaine] = $traductions_en[$chaine] ?? "";
}
$contenu = "<?php\n";
$contenu .= "// Fichier régénéré automatiquement par extraire_traductions.php\n";
$contenu .= "// le " . date("d/m/Y à H:i:s") . " - les valeurs vides sont à traduire manuellement.\n";
$contenu .= "return [\n";
foreach ($nouveau_tableau as $cle => $valeur) {
$contenu .= " " . var_export($cle, true) . " => " . var_export($valeur, true) . ",\n";
}
$contenu .= "];\n";
if (!empty($obsoletes)) {
$contenu .= "\n/*\n";
$contenu .= "// OBSOLÈTES au " . date("d/m/Y à H:i:s") . " - plus utilisées dans le code.\n";
$contenu .= "// À supprimer manuellement une fois confirmé qu'elles ne servent vraiment plus.\n";
foreach ($obsoletes as $chaine) {
$contenu .= var_export($chaine, true) . " => " . var_export($traductions_en[$chaine], true) . ",\n";
}
$contenu .= "*/\n";
}
file_put_contents($fichier_en, $contenu);
echo "Fichier régénéré : $fichier_en\n";
echo "(sauvegarde de l'ancienne version : $fichier_en.bak)\n";
+2
View File
@@ -0,0 +1,2 @@
# Activation du HSTS :
#Header set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" env=HTTPS
+461
View File
@@ -0,0 +1,461 @@
<?php
include "../config/config.php";
Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session et vérifiant que les accès sont autorisés.
Entete_page_html();
//************************************************************************************************************************************
// Initialisation des variables globales
//************************************************************************************************************************************
$message_erreur = "";
$message_information = "";
$flag_redirection = false;
Ouverture_bdd(); // Connexion à MySql
//************************************************************************************************************************************
// Traitement des variables d'entrées
//************************************************************************************************************************************
// Variables de SESSION :
if (!isset($_SESSION['Administration']['page'])) $_SESSION['Administration']['page'] = 'Accueil';
if (!isset($_SESSION['Administration']['ancre'])) $_SESSION['Administration']['ancre'] = "#";
if (!isset($_SESSION['Administration']['questionnaire'])) $_SESSION['Administration']['questionnaire'] = 'Nautic2021';
// Variables GET :
if (isset($_GET['action']))
{
switch ($_GET['action'])
{
//===================================
case "navigation":
{
if (isset($_GET['destination']))
{
$_SESSION['Administration']['page'] = $_GET['destination'];
$_SESSION['display_menu'] = false;
}
if (isset($_GET['ancre']))
{
$_SESSION['Administration']['ancre'] = $_GET['ancre'];
$_SESSION['display_menu'] = false;
}
break;
}
//===================================
case "changement_langue":
{
if (isset($_GET['langue']))
{
$_SESSION['langue'] = $_GET['langue'];
chargement_langue();
}
break;
}
//===================================
case "changement_type":
{
if (isset($_GET['type']))
{
$_SESSION['type_utilisateur'] = $_GET['type'];
chargement_langue();
}
break;
}
case "toggle_edit":
{
if ($_SESSION['modifier_texte'] == 0) $_SESSION['modifier_texte'] = 1;
else if ($_SESSION['modifier_texte'] == 1) $_SESSION['modifier_texte'] = 0;
break;
}
}
if (!$flag_redirection) header('Location:administration.php');
}
// Variables POST :
//************************************************************************************************************************************
// Traitement des données
//************************************************************************************************************************************
// Protection contre les accès directs :
if ((!$_SESSION['acces_valide']) OR ($_SESSION['shipmember']['Niveau_acces'] < NIVEAU_MINI_ACCES_ADMINISTATEUR)) header('Location:shipmembers.php?action=navigation&destination=Login');
switch ($_SESSION['Administration']['page'])
{
//****************************************************************************************************************************
case "Accueil":
{
break;
}
//****************************************************************************************************************************
case "Purge_bdd":
{
$nb_tables = 0;
$tables[$nb_tables ++]['Nom'] = "TB_BATEAUX_Mesures_circuits";
$tables[$nb_tables ++]['Nom'] = "TB_BATEAUX_Mesures_batteries";
$tables[$nb_tables ++]['Nom'] = "TB_BATEAUX_Mesures_reservoirs";
$tables[$nb_tables ++]['Nom'] = "TB_BATEAUX_Mesures_capteurs";
$max_lignes_traitees = 500000;
for ($x = 0; $x < $nb_tables; $x ++)
{
$nom_table = $tables[$x]['Nom'];
$start_time = microtime(true);
//------------------------------------------------------
// Recherche de la taille de la table avant traitement :
$requete = 'SELECT COUNT(*) AS Nb FROM '.$nom_table.' ';
$reponse = Requete_bdd($requete, __FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse))
{
$taille_table_avant_traitement = $donnees['Nb'];
}
Liberation_jeu_de_resultat_bdd($reponse);
//---------------------------------------------------
// Recherche des bateaux concernés dans cette table :
$nb_bateaux = 0;
$requete = 'SELECT DISTINCT(ID_Bateau) FROM '.$nom_table.' WHERE 1';
$reponse = Requete_preparee_bdd($requete,
array(),
__FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse))
{
$bateaux[$nb_bateaux ++] = $donnees;
}
Liberation_jeu_de_resultat_bdd($reponse);
//--------------------------------------------------------------------------------------------------------
// Boucle sur tous les bateaux pour rechercher les éléments concernés par chaque bateau dans cette table :
for ($i = 0; $i < $nb_bateaux ; $i ++)
{
// Recherche des éléments (circuits, réservoirs, batteries, ...) concernés sur chaque bateau :
$bateaux[$i]['nb_elements'] = 0;
$requete = 'SELECT DISTINCT(ID) FROM '.$nom_table.' WHERE ID_Bateau=? ';
$reponse = Requete_preparee_bdd($requete,
array(
array('i', $bateaux[$i]['ID_Bateau'])),
__FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse))
{
$bateaux[$i][$bateaux[$i]['nb_elements'] ++] = $donnees['ID'];
// echo '<p>'.$bateaux[$i]['nb_elements'].' : ID = '.$donnees['ID'].'</p>';
}
Liberation_jeu_de_resultat_bdd($reponse);
}
//-------------------------------------------------------------------
// Boucle sur tous les bateaux pour traiter les entrées redondantes:
$nb_total_lignes_supprimees = 0;
for ($i = 0; $i < $nb_bateaux ; $i ++)
{
// Boucle sur tous les éléments :
for ($j = 0; $j < $bateaux[$i]['nb_elements']; $j ++)
{
$nb_redondants = 0;
$val_1 = -1;
$val_2 = 0;
$id_2 = 0;
$requete = 'SELECT Cle_primaire, Date, Valeur FROM '.$nom_table.' WHERE ID_Bateau=? AND ID=? ORDER BY Date ';
$reponse = Requete_preparee_bdd($requete,
array(
array('i', $bateaux[$i]['ID_Bateau']),
array('i', $bateaux[$i][$j])),
__FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse))
{
// Recherche des conditions de redondance :
if (($val_1 == $val_2) AND ($val_2 == $donnees['Valeur'])) // Si la valeur actuelle est égale à la précédente et à celle encore avant :
{
$redondants[$nb_redondants ++] = $id_2; // ... on mémorise l'entrée intermédiaire (N-1)
$nb_total_lignes_supprimees ++;
if ($nb_total_lignes_supprimees >= $max_lignes_traitees) break;
}
$val_1 = $val_2;
$val_2 = $donnees['Valeur'];
$id_2 = $donnees['Cle_primaire'];
}
Liberation_jeu_de_resultat_bdd($reponse);
// Suppression des enregistrements redondants :
for ($k = 0; $k < $nb_redondants; $k ++)
{
// Création d'une chaine avec les différentes clés à supprimer afin de réduire le nombre de requêtes DELETE (impact sur temps de traitement d'environ / 50 avec la valeur de 100) :
$max_l = 100;
$chaine_cles_primaires = '(Cle_primaire='.$redondants[$k ++].' ';
if ($k < ($nb_redondants - 1))
{
for ($l = 1; $l < $max_l; $l ++)
{
$chaine_cles_primaires .= 'OR Cle_primaire='.$redondants[$k].' ';
if (($k >= ($nb_redondants - 1)) OR ($l >= ($max_l - 1))) break;
$k ++;
}
}
$chaine_cles_primaires .= ')';
$requete = 'DELETE FROM '.$nom_table.' WHERE ID_Bateau='.$bateaux[$i]['ID_Bateau'].' AND '.$chaine_cles_primaires.' ';
// echo 'Requête = ['.$requete.']<br />';
Requete_bdd($requete, __FILE__, __LINE__); // Pas de requête préparée pour accélérer le traitement...
}
if ($nb_total_lignes_supprimees >= $max_lignes_traitees) break;
}
if ($nb_total_lignes_supprimees >= $max_lignes_traitees) break;
}
// Recherche de la taille de la table après traitement :
$requete = 'SELECT COUNT(*) AS Nb FROM '.$nom_table.' ';
$reponse = Requete_bdd($requete, __FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse))
{
$taille_table_apres_traitement = $donnees['Nb'];
}
Liberation_jeu_de_resultat_bdd($reponse);
// Calculate script execution time
$execution_time = number_format((microtime(true) - $start_time), 1, ".", " ");
$tables[$x]['Taille_avant_traitement'] = $taille_table_avant_traitement;
$tables[$x]['Nb_total_lignes_supprimees'] = $nb_total_lignes_supprimees;
$tables[$x]['Execution_time'] = $execution_time;
$tables[$x]['Taille_apres_traitement'] = $taille_table_apres_traitement;
}
break;
}
//****************************************************************************************************************************
case "Questionnaires":
{
switch($_SESSION['Administration']['questionnaire'])
{
default:
{
$message_erreur .= "Le questionnaire ".$_SESSION['Administration']['questionnaire']." est inconnu. Le questionnaire en cours est repassé à sa valeur par défaut.";
$_SESSION['Administration']['questionnaire'] = "Nautic2021";
}
case "Nautic2021" :
{
$table_questionnaire = "TB_Nautic2021";
break;
}
}
// Nombre de réponses :
$requete = 'SELECT COUNT(*) AS Nb FROM '.$table_questionnaire.' WHERE Validite=1';
$reponse = Requete_preparee_bdd($requete,
array(),
__FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse))
{
$reponses_questionnaire['Nb'] = $donnees['Nb'];
}
Liberation_jeu_de_resultat_bdd($reponse);
// Dernier enregistrement :
$requete = 'SELECT DATE_FORMAT(Date_creation,"%d/%m/%Y à %H:%i:%s") as Date_creation FROM '.$table_questionnaire.' WHERE Validite=1 ORDER BY Date_creation DESC LIMIT 1';
// echo 'Requête = '.$requete.'<br />';
$reponse = Requete_preparee_bdd($requete,
array(),
__FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse))
{
$reponses_questionnaire['Date_creation'] = $donnees['Date_creation'];
}
Liberation_jeu_de_resultat_bdd($reponse);
// Nombre d'enregistrements par jour :
$nb_jours = 0;
$requete = 'SELECT COUNT(*) as Nb_jours, DATE_FORMAT(Date_creation, "%d-%m-%Y") as Date_creations FROM '.$table_questionnaire.' WHERE Validite=1 GROUP BY DATE_FORMAT(Date_creation, "%Y-%m-%d")';
// echo 'Requête = '.$requete.'<br />';
$reponse = Requete_preparee_bdd($requete,
array(),
__FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse))
{
$reponses_questionnaire['Creations_par_jour'][$nb_jours ++] = $donnees;
}
Liberation_jeu_de_resultat_bdd($reponse);
break;
}
}
Fermeture_bdd(); // Déconnexion de MySQL
//************************************************************************************************************************************
// Affichage
//************************************************************************************************************************************
//********************************************************************************************************************************
// Affichage principal :
echo '<div id="Administration">';
//=========================================================================================
// Entête :
Entete_page($message_erreur, $message_information);
switch ($_SESSION['Administration']['page'])
{
//************************************************************************************************************************
case "Accueil":
{
echo '<div id="accueil" class="page_principale">';
echo '<h1>Administration</h1>';
echo '<h2>Accueil</h2>';
echo '<p>Attention : toute la partie Administration n\'est disponible qu\'en français.</p>';
echo '<h2>ShipMembers et Bateaux</h2>';
echo '<div class="boutons_bas_de_page">';
echo '<a title="" href="shipmembers.php?action=navigation&destination=Administration">ShipMembers</a>';
echo '<a title="" href="bateaux.php?action=navigation&destination=Accueil">Gestion des bateaux</a>';
echo '</div>';
echo '<h2>Site web</h2>';
echo '<div class="boutons_bas_de_page">';
// echo '<a title="" href="administration.php?action=navigation&destination=Commandes">Commandes</a>';
echo '<a title="" href="faq.php?action=navigation&destination=Administration">Faq</a>';
echo '<a title="" href="actualites.php?action=navigation&destination=Administration">Actualités</a>';
echo '<a title="" href="produit_desc.php?action=navigation&destination=Administration">Produits</a>';
echo '<a title="" href="galerie.php?action=navigation&destination=Administration">Galerie photos</a>';
echo '<a title="" href="videos.php?action=navigation&destination=Administration">Videos</a>';
echo '<a title="" href="devis.php?action=navigation&destination=Administration">Devis</a>';
// echo '<a title="" href="administration.php?action=navigation&destination=Questionnaires">Questionnaires</a>';
echo '<a title="" href="textes.php?action=navigation&destination=Accueil">Gestion des textes</a>';
echo '</div>';
echo '<h2>Technique</h2>';
echo '<div class="boutons_bas_de_page">';
echo '<a title="" href="versions.php?action=navigation&destination=Accueil">Gestion des versions</a>';
echo '<a title="" href="cartes.php?action=navigation&destination=Accueil">Gestion des cartes</a>';
echo '<a title="" href="uploads.php?action=navigation&destination=Accueil" onclick="return confirm(\'Vous êtes sur vous voulez traiter les uploads ?\');">Traitement des uploads</a>';
//echo '<a title="" href="c_tech_api.php" onclick="return confirm(\'Etes-vous sûr de vouloir lancer le traitement de l\'API C-Technology ?\');">Traitement de l\'API C-Technology</a>';
//echo '<a title="" href="data_treatment.php" onclick="return confirm(\'Etes-vous sûr de vouloir lancer DATE_TREATMENT.PHP pour traiter les tables [old] ?\');">Traitement des tables OLD</a>';
//echo '<a title="" href="administration.php?action=navigation&destination=Purge_bdd" onclick="return confirm(\'Vous allez faire un purge de la BDD, avancer ?\');">Purge de la BDD</a>';
//echo '<a title="" href="check_payments.php?verbose">Test check factures</a>';
echo '</div>';
echo '<div class="boutons_bas_de_page">';
echo '<a title="" href="shipmembers.php?action=navigation&destination=Accueil">Retour au menu ShipMember</a>';
echo '</div>';
echo '</div>';
break;
}
//************************************************************************************************************************
case "Purge_bdd":
{
echo '<div id="purge_bdd" class="page_principale">';
echo '<h1>Administration</h1>';
echo '<h2>Purge de la base de données</h2>';
for ($x = 0; $x < $nb_tables; $x ++)
{
echo '<h3>'.$tables[$x]['Nom'].'</h3>';
echo '<p>Taille de la table AVANT traitement = <span class="gras">'.number_format($tables[$x]['Taille_avant_traitement'], 0, ".", " ").'</span> lignes</p>';
echo '<p>Le nombre total de lignes supprimées est de <span class="gras">'.number_format($tables[$x]['Nb_total_lignes_supprimees'], 0, ".", " ").'</span> (maxi = '.number_format($max_lignes_traitees, 0, ".", " ").') en '.$tables[$x]['Execution_time'].' secondes</p>';
echo '<p>Taille de la table APRES traitement = <span class="gras">'.number_format($tables[$x]['Taille_apres_traitement'], 0, ".", " ").'</span> lignes</p>';
}
echo '<div class="boutons_bas_de_page">';
echo '<a class=retour" title="" href="administration.php?action=navigation&destination=Accueil">Retour à l\'accueil</a>';
echo '<a title="" href="administration.php?action=navigation&destination=Purge_bdd">Relancer la purge de la BDD</a>';
echo '</div>';
echo '</div>';
break;
}
//****************************************************************************************************************************
case "Questionnaires":
{
echo '<div id="questionnaires" class="page_principale">';
echo '<h1>Administration</h1>';
echo '<h2>Questionnaire : '.$_SESSION['Administration']['questionnaire'].'</h2>';
// Nb de fiche réponse :
echo '<div class="indicateur">
<div class="libelle_indicateur">Le nombre total de questionnaires enregistrés est : </div>
<div class="valeur_indicateur">'.$reponses_questionnaire['Nb'].'</div>
</div>';
// Date dernière réponse :
echo '<div class="indicateur">
<div class="libelle_indicateur">La date du dernier formulaire rempli est : </div>
<div class="valeur_indicateur">'.$reponses_questionnaire['Date_creation'].'</div>
</div>';
// Nb créations par jour :
echo '<div class="indicateur">';
foreach($reponses_questionnaire['Creations_par_jour'] as $key => $creations)
{
echo '<div class="libelle_indicateur">Le nombre de formulaires saisis le '.$creations['Date_creations'].' est de : </div>
<div class="valeur_indicateur">'.$creations['Nb_jours'].'</div>';
}
echo '</div>';
echo '<div class="boutons_bas_de_page">';
echo '<a class=retour" title="" href="administration.php?action=navigation&destination=Accueil">Retour à l\'accueil</a>';
echo '</div>';
echo '</div>';
break;
}
}
echo '</div>';
Pied_de_page();
+3684
View File
File diff suppressed because it is too large Load Diff
+712
View File
@@ -0,0 +1,712 @@
<?php
include "../config/config.php";
Init_session(basename($_SERVER['SCRIPT_NAME'])); // Fonction ouvrant la session et vérifiant que les accès sont autorisés.
Entete_page_html();
//************************************************************************************************************************************
// Initialisation des variables globales
//************************************************************************************************************************************
$message_erreur = "";
$message_information = "";
$types_carte = array( "ShipBase", // Attention : ne pas changer l'ordre (l'indice est utilisé en BDD); Sinon, ajouter un champ explicite pour le type (1=ShipBase, 2=ShipPower, etc....).
"ShipPower812",
"ShipBS",
"ShipPower4AC",
"ShipPower8DC",
"Module bipolaire pour SP812",
"Ecran Densitron",
""); // Attention : Doit finir par une chaine vide
Ouverture_bdd(); // Connexion à MySql
//************************************************************************************************************************************
// Traitement des variables d'entrées
//************************************************************************************************************************************
// Variables de SESSION :
if (!isset($_SESSION['Cartes']['page'])) $_SESSION['Cartes']['page'] = 'Accueil';
if (!isset($_SESSION['Cartes']['ancre'])) $_SESSION['Cartes']['ancre'] = "#";
if (!isset($_SESSION['Cartes']['carte']['Cle_primaire'])) $_SESSION['Cartes']['carte']['Cle_primaire'] = 0;
if (!isset($_SESSION['Cartes']['carte']['Type'])) $_SESSION['Cartes']['carte']['Type'] = 0;
if (!isset($_SESSION['Cartes']['carte']['No_serie'])) $_SESSION['Cartes']['carte']['No_serie'] = "";
if (!isset($_SESSION['Cartes']['carte']['Version'])) $_SESSION['Cartes']['carte']['Version'] = "";
if (!isset($_SESSION['Cartes']['carte']['Revision'])) $_SESSION['Cartes']['carte']['Revision'] = "";
if (!isset($_SESSION['Cartes']['carte']['Adresse_mac'])) $_SESSION['Cartes']['carte']['Adresse_mac'] = "";
if (!isset($_SESSION['Cartes']['carte']['Date_reception'])) $_SESSION['Cartes']['carte']['Date_reception'] = date("Y-m-d");
if (!isset($_SESSION['Cartes']['carte']['Modifications'])) $_SESSION['Cartes']['carte']['Modifications'] = "";
if (!isset($_SESSION['Cartes']['carte']['Tests'])) $_SESSION['Cartes']['carte']['Tests'] = "";
if (!isset($_SESSION['Cartes']['carte']['Etat'])) $_SESSION['Cartes']['carte']['Etat'] = 0;
if (!isset($_SESSION['Cartes']['carte']['Destination'])) $_SESSION['Cartes']['carte']['Destination'] = "";
if (!isset($_SESSION['Cartes']['carte']['Commentaires'])) $_SESSION['Cartes']['carte']['Commentaires'] = "";
// Variables GET :
if (isset($_GET['action']))
{
switch ($_GET['action'])
{
//===================================
case "navigation":
{
if (isset($_GET['destination']))
{
$_SESSION['Cartes']['page'] = $_GET['destination'];
// $_SESSION['display_menu'] = false;
}
if (isset($_GET['ancre']))
{
$_SESSION['Cartes']['ancre'] = $_GET['ancre'];
// $_SESSION['display_menu'] = false;
}
break;
}
//===================================
case "changement_langue":
{
if (isset($_GET['langue']))
{
$_SESSION['langue'] = $_GET['langue'];
chargement_langue();
}
break;
}
//===================================
case "changement_type":
{
if (isset($_GET['type']))
{
$_SESSION['type_utilisateur'] = $_GET['type'];
chargement_langue();
}
break;
}
//===================================
case "affichage_liste_cartes":
{
if (isset($_GET['type_carte']))
{
$_SESSION['Cartes']['carte']['Type'] = $_GET['type_carte'];
$_SESSION['Cartes']['page'] = "Liste_cartes";
}
break;
}
case "toggle_edit":
{
if ($_SESSION['modifier_texte'] == 0) $_SESSION['modifier_texte'] = 1;
else if ($_SESSION['modifier_texte'] == 1) $_SESSION['modifier_texte'] = 0;
break;
}
//===================================
case "modification_carte":
{
if (isset($_GET['id_carte']))
{
$_SESSION['Cartes']['carte']['Cle_primaire'] = $_GET['id_carte'];
$_SESSION['Cartes']['page'] = "Modification_carte";
}
break;
}
//===================================
case "creation_carte":
{
if (isset($_GET['type_carte']))
{
$_SESSION['Cartes']['carte']['Type'] = $_GET['type_carte'];
$_SESSION['Cartes']['page'] = "Creation_carte";
}
break;
}
//===================================
case "demande_suppression_carte":
{
if (isset($_GET['id_carte']))
{
$_SESSION['Cartes']['carte']['Cle_primaire'] = $_GET['id_carte'];
// Recherche des cartes de ShipHeart qui utiliseraient cette sous-carte :
$nb_cartes = 0;
/* $requete = 'SELECT * FROM TB_Versions WHERE Validite=1 AND '.$types_carte[$_SESSION['Cartes']['type_carte']][4].'='.$_SESSION['Cartes']['carte']['Cle_primaire'].' ';
$flag_redirection = true;
echo 'Requête = '.$requete.'<br />';
$reponse = Requete_preparee_bdd($requete,
array(),
__FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse))
{
$cartes[$nb_cartes ++] = $donnees;
}
Liberation_jeu_de_resultat_bdd($reponse);
*/
if ($nb_cartes == 0) $_SESSION['Cartes']['page'] = "Confirmation_suppression_carte"; // Si aucune carte de ShipHeart ne l'utilise, on passe à l'étape de confitmation finale.
else // Sinon, on indique une erreur et on affiche les cartes l'utilisant (limitée à N lignes...)
{
$flag_redirection = true; // Evite que le message d'erreur soit supprimé par la redirection de purge d'URL
$message_erreur = "Vous ne pouvez pas supprimer cette carte qui est utilisée dans les cartes de ShipHeart suivantes :";
/* for ($i = 0; $i < $nb_cartes; $i ++)
{
if ($i < 10) $message_erreur .= "<br />".$cartes[$i]['Nom']." ";
else
{
$message_erreur .= "<br />[...]";
break;
}
}
*/
}
}
break;
}
//===================================
case "confirmation_suppression_carte":
{
if (isset($_GET['id_carte']))
{
$_SESSION['Cartes']['carte']['Cle_primaire'] = $_GET['id_carte'];
// Suppression de la carte :
$requete = 'UPDATE TB_Cartes SET Validite=0 WHERE Cle_primaire=?';
Requete_preparee_bdd($requete,
array(
array('s', $_SESSION['Cartes']['carte']['Cle_primaire'])),
__FILE__, __LINE__);
$flag_redirection = true; // Evite que le message d'erreur soit supprimé par la redirection de purge d'URL
$message_information = "La carte ".$types_carte[$_SESSION['Cartes']['carte']['Type']]." n° ".$_SESSION['Cartes']['carte']['No_serie']." a été supprimée de la base de données.";
$_SESSION['Cartes']['page'] = "Liste_cartes";
}
break;
}
}
if (!$flag_redirection) header('Location:cartes.php'.$_SESSION['Cartes']['ancre'].'');
}
// Variables POST :
//---------------------------------------------------------------------------
// Création Version :
if (isset($_POST['validation_creation_carte']) OR
isset($_POST['validation_modification_carte']))
{
// Mémorisation des valeurs saisies pour éviter de les perdre en cas d'erreur rendant la création impossible :
$_SESSION['Cartes']['carte']['No_serie'] = isset($_POST['No_serie']) ? addslashes ($_POST['No_serie']) : "";
$nb_cartes_a_creer = isset($_POST['nb_cartes_a_creer']) ? $_POST['nb_cartes_a_creer'] : 1;
$_SESSION['Cartes']['carte']['Version'] = isset($_POST['Version']) ? addslashes ($_POST['Version']) : "";
$_SESSION['Cartes']['carte']['Revision'] = isset($_POST['Revision']) ? addslashes ($_POST['Revision']) : "";
$_SESSION['Cartes']['carte']['Adresse_mac'] = isset($_POST['Adresse_mac']) ? addslashes ($_POST['Adresse_mac']) : "";
$_SESSION['Cartes']['carte']['Date_reception'] = isset($_POST['Date_reception']) ? addslashes ($_POST['Date_reception']) : date("Y-m-d");
$_SESSION['Cartes']['carte']['Modifications'] = isset($_POST['Modifications']) ? addslashes ($_POST['Modifications']) : "";
$_SESSION['Cartes']['carte']['Tests'] = isset($_POST['Tests']) ? addslashes ($_POST['Tests']) : "";
$_SESSION['Cartes']['carte']['Etat'] = isset($_POST['Etat']) ? addslashes ($_POST['Etat']) : 0;
$_SESSION['Cartes']['carte']['Destination'] = isset($_POST['Destination']) ? addslashes ($_POST['Destination']) : "";
$_SESSION['Cartes']['carte']['Commentaires'] = isset($_POST['Commentaires']) ? addslashes ($_POST['Commentaires']) : "";
if (isset($_POST['validation_creation_carte']))
{
for ($i = 0; $i < $nb_cartes_a_creer; $i ++)
{
// Création de la carte :
$requete = 'INSERT INTO TB_Cartes (Type, No_serie, Version, Revision, Adresse_mac, Date_reception, Modifications, Tests, Etat, Destination, Commentaires) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
Requete_preparee_bdd($requete,
array(
array('i', $_SESSION['Cartes']['carte']['Type']),
array('s', $_SESSION['Cartes']['carte']['No_serie']),
array('s', $_SESSION['Cartes']['carte']['Version']),
array('s', $_SESSION['Cartes']['carte']['Revision']),
array('s', $_SESSION['Cartes']['carte']['Adresse_mac']),
array('s', $_SESSION['Cartes']['carte']['Date_reception']),
array('s', $_SESSION['Cartes']['carte']['Modifications']),
array('s', $_SESSION['Cartes']['carte']['Tests']),
array('i', $_SESSION['Cartes']['carte']['Etat']),
array('s', $_SESSION['Cartes']['carte']['Destination']),
array('s', $_SESSION['Cartes']['carte']['Commentaires'])),
__FILE__, __LINE__);
// Récup de la clé primaire de l'enregistrement créé :
$_SESSION['Cartes']['carte']['Cle_primaire'] = Recuperation_id_cree_bdd();
// Préparation des champs pour les cartes suivantes :
if ($nb_cartes_a_creer > 1)
{
$cartes_a_creer[$i]['No_serie'] = $_SESSION['Cartes']['carte']['No_serie'];
list($annee, $no) = explode("-", $_SESSION['Cartes']['carte']['No_serie']);
$lg_no = strlen($no);
$_SESSION['Cartes']['carte']['No_serie'] = $annee.'-'.str_pad(($no+1), $lg_no, '0', STR_PAD_LEFT);
$_SESSION['Cartes']['carte']['Adresse_mac'] = ""; // Seule la première carte aura l'adresse MAC enregistrée
}
}
// Message d'information :
if ($nb_cartes_a_creer <= 1) $message_information = "La carte ".$types_carte[$_SESSION['Cartes']['carte']['Type']]." n° ".$_SESSION['Cartes']['carte']['No_serie']." vient d'être créée";
else $message_information = $nb_cartes_a_creer." cartes ".$types_carte[$_SESSION['Cartes']['carte']['Type']].", du n° [".$cartes_a_creer[0]['No_serie']."] au n° [".$cartes_a_creer[$nb_cartes_a_creer-1]['No_serie']."], viennent d'être créées";
// Retour à la liste si la création s'est bien passée :
$_SESSION['Cartes']['page'] = "Liste_cartes";
}
else if (isset($_POST['validation_modification_carte']))
{
// Mise à jour de la carte :
$requete = 'UPDATE TB_Cartes SET Type=?, No_serie=?, Version=?, Revision=?, Adresse_mac=?, Date_reception=?, Modifications=?, Tests=?, Etat=?, Destination=?, Commentaires=? WHERE Cle_primaire=?';
Requete_preparee_bdd($requete,
array(
array('i', $_SESSION['Cartes']['carte']['Type']),
array('s', $_SESSION['Cartes']['carte']['No_serie']),
array('s', $_SESSION['Cartes']['carte']['Version']),
array('s', $_SESSION['Cartes']['carte']['Revision']),
array('s', $_SESSION['Cartes']['carte']['Adresse_mac']),
array('s', $_SESSION['Cartes']['carte']['Date_reception']),
array('s', $_SESSION['Cartes']['carte']['Modifications']),
array('s', $_SESSION['Cartes']['carte']['Tests']),
array('i', $_SESSION['Cartes']['carte']['Etat']),
array('s', $_SESSION['Cartes']['carte']['Destination']),
array('s', $_SESSION['Cartes']['carte']['Commentaires']),
array('i', $_SESSION['Cartes']['carte']['Cle_primaire'])),
__FILE__, __LINE__);
// Message d'information :
$message_information = "La carte ".$types_carte[$_SESSION['Cartes']['carte']['Type']]." n° ".$_SESSION['Cartes']['carte']['No_serie']." vient d'être modifiée";
// Retour à la liste si la modification s'est bien passée :
$_SESSION['Cartes']['page'] = "Liste_cartes";
}
}
//************************************************************************************************************************************
// Traitement des données
//************************************************************************************************************************************
// Protection contre les accès directs :
if ((!$_SESSION['acces_valide']) OR ($_SESSION['shipmember']['Niveau_acces'] < NIVEAU_MINI_ACCES_ADMINISTATEUR)) header('Location:shipmembers.php?action=navigation&destination=Login');
switch ($_SESSION['Cartes']['page'])
{
//****************************************************************************************************************************
case "Accueil":
{
break;
}
//****************************************************************************************************************************
case "Liste_cartes":
{
// Récupération des informations sur les cartes :
$nb_cartes = 0;
$requete = 'SELECT * FROM TB_Cartes WHERE Validite=1 AND Type=? ORDER BY Version ASC, No_serie ASC';
$reponse = Requete_preparee_bdd($requete,
array(
array('i', $_SESSION['Cartes']['carte']['Type'])),
__FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse))
{
$cartes[$nb_cartes] = $donnees;
// Mise en forme de textes :
$cartes[$nb_cartes]['Modifications'] = htmlspecialchars(stripcslashes($cartes[$nb_cartes]['Modifications']));
$cartes[$nb_cartes]['Tests'] = htmlspecialchars(stripcslashes($cartes[$nb_cartes]['Tests']));
$cartes[$nb_cartes]['Destination'] = htmlspecialchars(stripcslashes($cartes[$nb_cartes]['Destination']));
$cartes[$nb_cartes]['Commentaires'] = htmlspecialchars(stripcslashes($cartes[$nb_cartes]['Commentaires']));
$nb_cartes ++;
}
Liberation_jeu_de_resultat_bdd($reponse);
break;
}
//****************************************************************************************************************************
case "Creation_carte":
case "Modification_carte":
{
if ($_SESSION['Cartes']['page'] == "Creation_carte")
{
$_SESSION['Cartes']['carte']['Cle_primaire'] = 0;
// $_SESSION['Cartes']['carte']['Type'] = 0;
$_SESSION['Cartes']['carte']['No_serie'] = "";
$_SESSION['Cartes']['carte']['Version'] = "";
$_SESSION['Cartes']['carte']['Revision'] = "";
$_SESSION['Cartes']['carte']['Adresse_mac'] = "";
$_SESSION['Cartes']['carte']['Date_reception'] = date("Y-m-d");
$_SESSION['Cartes']['carte']['Modifications'] = "";
$_SESSION['Cartes']['carte']['Tests'] = "";
$_SESSION['Cartes']['carte']['Etat'] = 0;
$_SESSION['Cartes']['carte']['Destination'] = "";
$_SESSION['Cartes']['carte']['Commentaires'] = "";
}
else // Modification :
{
$requete = 'SELECT * FROM TB_Cartes WHERE Cle_primaire=? ';
$reponse = Requete_preparee_bdd($requete,
array(
array('i', $_SESSION['Cartes']['carte']['Cle_primaire'])),
__FILE__, __LINE__);
while ($donnees = Recherche_ligne_bdd($reponse))
{
$_SESSION['Cartes']['carte'] = $donnees;
// Mise en forme de textes :
$_SESSION['Cartes']['carte']['Modifications'] = htmlspecialchars(stripcslashes($_SESSION['Cartes']['carte']['Modifications']));
$_SESSION['Cartes']['carte']['Tests'] = htmlspecialchars(stripcslashes($_SESSION['Cartes']['carte']['Tests']));
$_SESSION['Cartes']['carte']['Destination'] = htmlspecialchars(stripcslashes($_SESSION['Cartes']['carte']['Destination']));
$_SESSION['Cartes']['carte']['Commentaires'] = htmlspecialchars(stripcslashes($_SESSION['Cartes']['carte']['Commentaires']));
}
Liberation_jeu_de_resultat_bdd($reponse);
}
break;
}
//****************************************************************************************************************************
case "Confirmation_suppression_carte":
{
break;
}
//****************************************************************************************************************************
default:
{
$_SESSION['Cartes']['page'] = "Accueil";
break;
}
}
Fermeture_bdd(); // Déconnexion de MySQL
//************************************************************************************************************************************
// Affichage
//************************************************************************************************************************************
//********************************************************************************************************************************
// Affichage principal :
echo '<div id="Cartes">';
//=========================================================================================
// Entête :
Entete_page($message_erreur, $message_information);
switch ($_SESSION['Cartes']['page'])
{
//************************************************************************************************************************
case "Accueil":
{
echo '<div id="accueil" class="page_principale">';
echo '<h1>Cartes</h1>';
echo '<h2>Type de cartes</h2>';
echo '<div class="choix_type_carte">';
for ($i=0; $types_carte[$i] != ""; $i ++)
{
echo '<a title="" href="cartes.php?action=affichage_liste_cartes&type_carte='.$i.'">'.$types_carte[$i].'</a>';
}
echo '</div>';
echo '<div class="boutons_bas_de_page">';
echo '<a title="" href="administration.php?action=navigation&destination=Accueil">Retour au menu Administration</a>';
echo '</div>';
echo '</div>';
break;
}
//************************************************************************************************************************
case "Liste_cartes":
{
echo '<div id="liste_cartes" class="page_principale">';
echo '<h1>Cartes</h1>';
echo '<h2>Liste des cartes <span class="gras">'.$types_carte[$_SESSION['Cartes']['carte']['Type']].'</span></h2>';
echo '<table class="carte">
<thead>
<tr>
<th>N° de série</th>
<th>Version</th>
<th>Rév.</th>
<th>Adresse MAC</th>
<th>Date réception</th>
<th>Destination</th>
</tr>
</thead>
<tbody>';
for ($i = 0; $i < $nb_cartes; $i ++)
{
switch($cartes[$i]['Etat'])
{
default:
case ETAT_CARTE_INCONNU: { echo '<tr class="carte_etat_inconnu">'; break; }
case ETAT_CARTE_OK: { echo '<tr>'; break; }
case ETAT_CARTE_EN_PANNE: { echo '<tr class="carte_en_panne">'; break; }
case ETAT_CARTE_REBUT: { echo '<tr class="carte_rebut">'; break; }
}
echo '<td>
<a title="Modifications : '.$cartes[$i]['Modifications'].'&#13&#13Tests : '.$cartes[$i]['Tests'].'&#13&#13Commentaires : '.$cartes[$i]['Commentaires'].'"
href="cartes.php?action=modification_carte&id_carte='.$cartes[$i]['Cle_primaire'].'">
'.$cartes[$i]['No_serie'].'
</a>
</td>
<td>'.$cartes[$i]['Version'].'</td>
<td>'.$cartes[$i]['Revision'].'</td>
<td>'.$cartes[$i]['Adresse_mac'].'</td>
<td>'.$cartes[$i]['Date_reception'].'</td>
<td>'.$cartes[$i]['Destination'].'</td>
</tr>';
}
echo '</tbody>
</table>';
echo '<div class="boutons_bas_de_page">';
echo '<a title="" href="cartes.php?action=navigation&destination=Accueil">Retour aux types de cartes</a>';
echo '<a title="" href="cartes.php?action=creation_carte&type_carte='.$_SESSION['Cartes']['carte']['Type'].'">Créer une nouvelle carte</a>';
echo '</div>';
echo '</div>';
break;
}
//************************************************************************************************************************
case "Creation_carte":
case "Modification_carte":
{
echo '<div id="creation_carte" class="page_principale">';
echo '<h1>Cartes</h1>';
echo '<form action="cartes.php" method="post">';
if ($_SESSION['Cartes']['page'] == "Creation_carte") echo '<h2>Nouvelle carte <span class="gras">'.$types_carte[$_SESSION['Cartes']['carte']['Type']].'</span></h2>';
else echo '<h2>Modification de la carte <span class="gras">'.$types_carte[$_SESSION['Cartes']['carte']['Type']].'</span> n° <span class="gras">'.$_SESSION['Cartes']['carte']['No_serie'].'</span></h2>';
//----------------------------------------
// N° de série :
echo '<div class="champs">
<div class="champs_titre">
N° de série
</div>
<div class="champs_valeur">
<input name="No_serie" placeholder="Par exemple : 2021-001" value="'.$_SESSION['Cartes']['carte']['No_serie'].'" >
</div>
</div>';
//----------------------------------------
// Nombre de cartes à créer :
if ($_SESSION['Cartes']['page'] == "Creation_carte")
{
echo '<div class="champs">
<div class="champs_titre">
Nombre de cartes à créer
</div>
<div class="champs_valeur">
<input name="nb_cartes_a_creer" placeholder="Si vous souhaitez créer plusieurs cartes à partir du numéro de série ci-dessus..." value="1" >
</div>
<div class="champs_nb">
Si cette valeur est > 1, plusieurs cartes seront créées avec un numéro de série incrémenté de 1 et avec les mêmes champs (sauf adresse MAC)
</div>
</div>';
}
//----------------------------------------
// Version :
echo '<div class="champs">
<div class="champs_titre">
Version
</div>
<div class="champs_valeur">
<input name="Version" placeholder="Par exemple : SC009020-1C" value="'.$_SESSION['Cartes']['carte']['Version'].'" >
</div>
</div>';
//----------------------------------------
// Révision :
echo '<div class="champs">
<div class="champs_titre">
Révision
</div>
<div class="champs_valeur">
<input name="Revision" placeholder="Par exemple : b" value="'.$_SESSION['Cartes']['carte']['Revision'].'" >
</div>
</div>';
//----------------------------------------
// Adresse MAC :
echo '<div class="champs">
<div class="champs_titre">
Adresse MAC
</div>
<div class="champs_valeur">
<input name="Adresse_mac" placeholder="Par exemple : 80:1F:12:EB:AA:1A" value="'.$_SESSION['Cartes']['carte']['Adresse_mac'].'" >
</div>
</div>';
//----------------------------------------
// Date de réception :
echo '<div class="champs">
<div class="champs_titre">
Date de réception
</div>
<div class="champs_valeur">
<input name="Date_reception" placeholder="Format Y-m-d" value="'.$_SESSION['Cartes']['carte']['Date_reception'].'" >
</div>
</div>';
//----------------------------------------
// Modifications :
echo '<div class="champs">
<div class="champs_titre">
Modificationss
</div>
<div class="champs_valeur">
<textarea cols="" rows="" name="Modifications" placeholder="Entrer les modifications apportées à la carte par rapport au dossier de fabrication" autocomplete="off">'.$_SESSION['Cartes']['carte']['Modifications'].'</textarea>
</div>
</div>';
//----------------------------------------
// Tests :
echo '<div class="champs">
<div class="champs_titre">
Tests
</div>
<div class="champs_valeur">
<textarea cols="" rows="" name="Tests" placeholder="Entrer les tests effectués sur la carte" autocomplete="off">'.$_SESSION['Cartes']['carte']['Tests'].'</textarea>
</div>
</div>';
//----------------------------------------
// Etat :
echo '<div class="champs">
<div class="champs_titre">Etat</div>
<div class="champs_valeur">
<select name="Etat">';
echo ' <option value="'.ETAT_CARTE_INCONNU.'" '; if ($_SESSION['Cartes']['carte']['Etat'] == ETAT_CARTE_INCONNU) echo 'selected'; echo '>Inconnu</option>';
echo ' <option value="'.ETAT_CARTE_OK.'" '; if ($_SESSION['Cartes']['carte']['Etat'] == ETAT_CARTE_OK) echo 'selected'; echo '>OK</option>';
echo ' <option value="'.ETAT_CARTE_EN_PANNE.'" '; if ($_SESSION['Cartes']['carte']['Etat'] == ETAT_CARTE_EN_PANNE) echo 'selected'; echo '>En panne</option>';
echo ' <option value="'.ETAT_CARTE_REBUT.'" '; if ($_SESSION['Cartes']['carte']['Etat'] == ETAT_CARTE_REBUT) echo 'selected'; echo '>Au rebut (irréparable)</option>';
echo '</select>
</div>
</div>';
//----------------------------------------
// Destination :
echo '<div class="champs">
<div class="champs_titre">
Destination
</div>
<div class="champs_valeur">
<input name="Destination" placeholder="Par exemple : Et Si... 2" value="'.$_SESSION['Cartes']['carte']['Destination'].'" >
</div>
</div>';
//----------------------------------------
// Commentaires :
echo '<div class="champs">
<div class="champs_titre">
Commentaires
</div>
<div class="champs_valeur">
<textarea cols="" rows="" name="Commentaires" placeholder="Vos commentaires sur la carte" autocomplete="off">'.$_SESSION['Cartes']['carte']['Commentaires'].'</textarea>
</div>
</div>';
//----------------------------------------
// Boutons de bas de page :
echo '<div class="boutons_bas_de_page">';
if ($_SESSION['Cartes']['page'] == "Creation_carte") /// Création :
{
echo '<a title="" href="cartes.php?action=affichage_liste_cartes&type_carte='.$_SESSION['Cartes']['carte']['Type'].'">Annuler</a>';
echo '<button type="submit" name="validation_creation_carte" title="Valider la création de la carte">Créer la carte</button>';
}
else // Modification :
{
echo '<a title="" href="cartes.php?action=affichage_liste_cartes&type_carte='.$_SESSION['Cartes']['carte']['Type'].'">Retour à la liste des cartes</a>';
echo '<button type="submit" name="validation_modification_carte" title="Valider les modification de la carte">Enregistrer les modifications</button>';
echo '<a title="" href="cartes.php?action=demande_suppression_carte&id_carte='.$_SESSION['Cartes']['carte']['Cle_primaire'].'">Supprimer la carte</a>';
}
echo '</div>';
echo '</form>';
echo '</div>';
break;
}
//****************************************************************************************************************************
case "Confirmation_suppression_carte":
{
echo '<div id="confirmation_suppression_carte" class="page_principale">';
echo '<h1>Cartes</h1>';
echo '<div class="message_confirmation">';
echo '<p>
Confirmez-vous la suppression de la carte
<span class="gras">'.$types_carte[$_SESSION['Cartes']['carte']['Type']].'</span>
n°
<span class="gras">'.$_SESSION['Cartes']['carte']['No_serie'].'</span> ?
</p>';
echo '</div>';
echo '<div class="boutons_bas_de_page">';
echo '<a title="" href="cartes.php?action=affichage_liste_cartes&type_carte='.$_SESSION['Cartes']['carte']['Type'].'">Annuler</a>';
echo '<a title="" href="cartes.php?action=confirmation_suppression_carte&id_carte='.$_SESSION['Cartes']['carte']['Cle_primaire'].'">Confirmer la suppression</a>';
echo '</div>';
echo '</div>';
break;
}
}
echo '</div>';
Pied_de_page();
+2
View File
@@ -0,0 +1,2 @@
<?php
include "../../cron/prod/data_archive_treatment.php";
+2
View File
@@ -0,0 +1,2 @@
<?php
include "../../cron/prod/data_treatment.php";
+1071
View File
File diff suppressed because it is too large Load Diff
+742
View File
@@ -0,0 +1,742 @@
/************************************************** DECLARATION DE VARIABLE ***************************************/
:root {
--hauteur_menu: 80px;
}
/************************************************************ PAGE *************************************************/
html
{
/* font-size:2.0em; */
}
/***************************************************** ZONE DE TRAVAIL *********************************************/
body {
max-width:99%;
}
/********************************************************* ENTETE **************************************************/
#entete #ligne_icones {
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
}
#entete #ligne_icones a {
background-size: 50%;
width: 90%;
}
#entete #ligne_icones #home {
text-align:center;
padding-left:0px;
}
#entete nav {
grid-template-columns: 1fr;
grid-row-gap: 0px;
}
#entete nav .menu {
/* font-size:2em; */
}
#entete nav .menu a {
background-color: var(--bleu_koriolan_fonce);
color: var(--bleu_koriolan);
/* display: block; */
/* width: 96%; */
padding:20px 0px;
margin: auto;
/* line-height: 2em; */
}
#espace_menu.replie {
padding-top:40px;
}
#espace_menu.deploye {
padding-top:360px;
}
/*********************************************************** PIED DE PAGE *********************************************/
#pied_de_page {
grid-template-columns: 1fr;
grid-row-gap: 0px;
grid-template-rows: 100px 1em;
}
#pied_de_page .marque {
text-align: center;
height: 100px;
padding: 20px;
grid-column: 1 / span 3 !important;
}
#pied_de_page .mentions_legales {
text-align: center;
grid-column: 1 / span 3 !important;
grid-row: 2 / span 3 !important;
}
#pied_de_page .mentions_legales a {
text-align: center;
display: inline-block;
width: 90%;
margin: 20px auto;
border: 1px solid var(--bleu_koriolan);
}
#pied_de_page .signature {
grid-column: 1 / span 3 !important;
text-align: center;
padding: 50px;
height: 100px;
}
#pied_de_page a {
padding:20px 0px;
}
/********************************************************* TITRES ********************************************/
h1 {
font-size:2.0em;
}
h2 {
font-size:1.4em;
}
/****************************************************** TABLEAUX STANDARD *****************************************/
/***************************************************** FORMULAIRES ***************************************************/
input, textarea, select {
/* padding:10px 10px; */
font-size: 1.0em;
}
select {
/* height: 40px; */
/* font-size: 1.5em; */
}
::placeholder {
/* font-size: 1.8em; */
}
.boutons_formulaire button {
padding:50px 30px;
/* font-size: 1.8em; */
}
/********************************************************* LIENS HYPERTEXTES ***************************************/
a.renforce {
padding:3px 30px;
}
ul {
padding-inline-start: 20px; /* C'est une valeur par défaut de 40px, ce qui est beaucoup sur un affichage téléphone... */
}
ul li {
margin-bottom: 0px;
}
/********************************************************* PARAGRAPHES ***************************************/
p {
margin:10px 0px;
/* line-height:50px; */
/* font-size:1.8em; */
}
/********************************************************* ANCRES ***************************************/
.ancre {
/* padding-top: 350px; /* Taille du menu déployé */
/*margin-top: -350px; Même valeur que ci-dessus pour compenser */
}
.ancre.sans_menu {
/*padding-top: 40px;*/ /* Taille du menu replié */
/*margin-top: -40px;*/ /* Même valeur que ci-dessus pour compenser */
}
/************************************* MESSAGE D'ERREUR ***************************************/
/************************************* COMPARATIF SHIPHEARTS ***************************************/
.comparatif {
/* font-size:1.5em; */
}
.comparatif .bouton_comparatif a {
margin-bottom: 50px;
width: calc(99% - 50px);
padding: 20px 0px 20px 50px;
background-position: left 10px top 50%;
}
.comparatif table.table_comparatif th {
font-size: 0.7em;
}
.comparatif table.table_comparatif th:not(:first-child) {
border: 1px solid var(--bleu_koriolan);
height: 80px;
padding: 0px;
transform: rotate(-90deg);
}
.comparatif table.table_comparatif td {
font-size:0.8em;
}
.comparatif table.table_comparatif td.version img {
/* width:60px; */
}
.comparatif table.table_renvois_comparatif tr td {
font-size:0.8em;
}
/************************************* IMAGES ZOOMEES ***************************************/
#zoom {
grid-template-columns: 1fr;
row-gap: 20px;
width: 95%;
padding:5px;
}
#zoom a {
display: block;
text-align: center;
}
#zoom a img {
width: 50px;
}
#zoom .photo_zoomee {
width: 100%;
}
#zoom .photo_zoomee img {
max-height: 250px;
max-width: 90%;
border-radius: 5px;
}
/***********************************************************************************************************************
Fichier accueil.php
***********************************************************************************************************************/
#Accueil h1 {
/* height: 300px; */
}
#Accueil h2 {
font-size:2em;
}
#Accueil p {
line-height:1.2em;
margin: auto;
}
#Accueil #bandeau_accueil {
height:300px; /* Fige la hauteur du bloc 'bandeau-accueil' sinon on n'arrive à rien... */
line-height: 300px; /* Permet ensuite d'utiliser le vertical-align sur le <p> inclus */
}
#Accueil #bandeau_accueil p {
font-size:1.8em;
}
#Accueil #notre_actualite p {
margin-bottom: 2em;
}
#Accueil #notre_actualite a {
width: 90%;
border-radius: 1em;
padding: 30px 0px;
}
#Accueil #qu_est_ce_que_shipheart .corps {
padding:50px 0px 50px 0px;
border-bottom:10px solid var(--bleu_koriolan_transparent);
font-weight: 300;
font-size: 1em;
}
#Accueil #qu_est_ce_que_shipheart .corps p {
margin-top: 10px;
margin-bottom: 10px;
}
#Accueil #qu_est_ce_que_shipheart .corps .made_in_france {
margin:20px 5% 50px 5%;
}
#Accueil #qu_est_ce_que_shipheart .corps .made_in_france img {
width: 99%;
}
#Accueil #marguerite {
padding:0.5em 0px;
}
#Accueil #marguerite .corps {
grid-template-columns: 1fr;
row-gap:60px;
}
#Accueil #marguerite .corps .rubrique {
border: none;
border-bottom:10px solid var(--bleu_koriolan_transparent);
padding:10px 10px;
}
#Accueil #boutique .corps a {
margin: 20px auto 20px auto;
padding: 30px 0px;
width: 96%;
/* font-size: 2.0em; */
}
#Accueil #faq .corps .rubriques {
grid-template-columns: 1fr;
row-gap: 50px;
}
#Accueil #qui_sommes_nous img {
/* width:100%; */
}
#Accueil #qui_sommes_nous .image_bandeau {
height:200px;
}
#Accueil #qui_sommes_nous .corps {
/* padding:50px 0px; */
}
#Accueil #qui_sommes_nous .carte_de_visite {
grid-template-columns: 1% 1fr 2fr;
}
#Accueil #qui_sommes_nous .carte_de_visite .texte p {
font-size: 0.8em;
}
#Accueil #qui_sommes_nous .contact {
/* grid-template-columns: 20px 1fr 20px; */
padding-top: 50px;
/* font-size: 1.8em; */
}
#Accueil #qui_sommes_nous .contact a {
width: 95%;
margin: 60px auto;
padding: 30px 0px;
}
/***********************************************************************************************************************
Fichier actualites.php
***********************************************************************************************************************/
/*----------------------------------------*/
#Actualites #accueil .photos {
grid-template-columns: 1fr;
}
/***********************************************************************************************************************
Fichier boutique.php
***********************************************************************************************************************/
#Boutique .info_mobile {
display: inline-block;
}
#Boutique .boutons_bas_de_page {
grid-template-columns: 1fr;
grid-template-areas:
" suivant "
" retour ";
margin-top: 20px;
}
#Boutique .boutons_bas_de_page a {
margin: 30px 0px;
}
/*--------------------------------------------------*/
#Boutique #bandeau_avancement {
grid-template-columns: repeat(7, auto);
font-size:0.6em;
}
#Boutique #bandeau_avancement .etape:first-child {
border-radius: 0px;
}
#Boutique #bandeau_avancement .etape:last-child {
border-radius: 0px;
}
/*--------------------------------------------------*/
#Boutique #accueil .famille {
grid-template-columns: 1fr;
}
#Boutique #accueil .famille .produit {
/* border-top:10px solid var(--bleu_koriolan_fonce); */
grid-template-rows: auto;
row-gap:20px;
}
#Boutique #accueil .famille .produit .image img {
height: auto;
width: min(80%, 350px);
margin-top: 20px;
}
#Boutique #accueil .famille .produit .boutons a {
width: calc(96% - 20px);
/* padding: 40px 10px; */
margin-bottom: 20px;
}
#Boutique #accueil .famille .produit .boutons a:hover {
}
/*--------------------------------------------------*/
#Boutique #panier .liste_produits {
grid-row-gap: 10px;
}
#Boutique #panier .liste_produits .titre {
display:none;
}
#Boutique #panier .liste_produits .produit {
border: 3px solid var(--bleu_koriolan_fonce);
grid-template-columns: 1fr 1fr;
grid-template-rows: auto;
row-gap: 10px;
grid-template-areas:
" image image "
" nom nom "
" descriptif descriptif "
" delai delai "
" boutons quantite "
" prix_ht prix_ht "
" prix_ttc prix_ttc ";
align-items: center;
justify-items: center;
margin: 10px 0px 50px 0px;
padding: 20px 10px;
/* font-size: 0.8em; */
}
#Boutique #panier .liste_produits .produit .image {
text-align: center;
}
#Boutique #panier .liste_produits .produit .image img {
height: auto;
width: min(80%, 350px);
}
#Boutique #panier .liste_produits .produit .descriptif {
font-style: normal;
}
#Boutique #panier .liste_produits .produit .quantite {
/* font-size:1.5em; */
}
#Boutique #panier .liste_produits .produit .quantite .info_mobile {
font-size:0.8em;
}
#Boutique #panier .liste_produits .produit .boutons {
grid-template-columns: 1fr 1fr;
grid-template-areas:
" moins plus ";
grid-column-gap: 20px;
align-items: center;
}
#Boutique #panier .liste_produits .produit .boutons a {
height: 100%;
width: 100%;
}
#Boutique #panier .liste_produits .produit .boutons a img {
width: 100%;
}
#Boutique #panier .liste_produits .produit .delai {
line-height: normal;
}
#Boutique #panier .liste_produits .produit .prix_ht {
line-height: normal;
}
#Boutique #panier .liste_produits .produit .prix_ttc {
line-height: normal;
font-size:1.2em;
}
#Boutique #panier .liste_produits .synthese {
grid-template-columns: 2fr 2fr 2fr;
}
#Boutique #panier .liste_produits .synthese.titres.info_mobile {
display: block;
}
/*--------------------------------------------------*/
#Boutique #identification form {
grid-template-columns: 1fr;
grid-template-areas:
" shipmember "
" new_shipmember ";
row-gap:10px;
}
/*--------------------------------------------------*/
#Boutique #validation .liste_produits .titre {
display:none;
}
#Boutique #validation .liste_produits .produit {
border: 3px solid var(--bleu_koriolan_fonce);
grid-template-columns: 1fr 1fr;
grid-template-rows: auto;
row-gap: 20px;
grid-template-areas:
" image image "
" nom nom "
" descriptif descriptif "
" delai delai "
" prix_ht prix_ht "
" prix_ttc prix_ttc "
" boutons quantite ";
align-items: center;
justify-items: center;
margin: 10px 0px 10px 0px;
padding: 20px 10px;
/* font-size: 0.8em; */
}
#Boutique #validation .liste_produits .produit .image {
text-align: center;
}
#Boutique #validation .liste_produits .produit .image img {
height: auto;
width: min(80%, 350px);
}
#Boutique #validation .liste_produits .produit .descriptif {
font-style: normale;
}
#Boutique #validation .liste_produits .produit .quantite {
font-size:1.5em;
line-height: 1.5em;
}
#Boutique #validation .liste_produits .produit .quantite .info_mobile {
font-size:0.8em;
}
#Boutique #validation .liste_produits .produit .boutons {
grid-template-columns: 1fr 1fr;
grid-template-areas:
" moins plus ";
grid-column-gap: 20px;
align-items: center;
}
#Boutique #validation .liste_produits .produit .boutons a {
height: 200px;
width: 200px;
line-height: 200px;
}
#Boutique #validation .liste_produits .produit .boutons a img {
width: 100px;
}
#Boutique #validation .liste_produits .produit .delai {
line-height: normal;
}
#Boutique #validation .liste_produits .produit .prix_ht {
line-height: normal;
}
#Boutique #validation .liste_produits .produit .prix_ttc {
line-height: normal;
font-size:1.2em;
}
#Boutique #validation .liste_produits .synthese {
grid-template-columns: 2fr 2fr 2fr;
}
#Boutique #validation .liste_produits .synthese.titres.info_mobile {
display: inline;
}
#Boutique #validation .message_validation_cgv input {
width: 40px;
}
#Boutique #validation .message_validation_cgv label {
line-height: 20px;
}
#Boutique #validation .message_validation_cgv a {
padding: 0px 30px;
/* background-color: var(--bleu_koriolan_fonce); */
}
/*--------------------------------------------------*/
#Boutique #paiement .saisie_paiement form {
/* padding: 20px 0px 100px 0px; */
}
#Boutique #paiement .saisie_paiement #card-element {
width: 90%;
margin-bottom: 50px;
/* margin: 50px 0px 150px 0px; */
/* background: var(--bleu_koriolan_transparent); */
}
/*--------------------------------------------------*/
#Boutique #cloture h2 {
margin-top: 50px;
}
/***********************************************************************************************************************
Fichier faq.php
***********************************************************************************************************************/
/*----------------------------------------*/
#Faq #accueil h2 {
border-bottom: none;
}
#Faq #accueil .famille a {
padding-bottom:10px;
border: 2px solid var(--bleu_koriolan);
margin: 5px 0px;
}
#Faq #accueil .famille .reponse {
margin:0px 10px 30px 10px;
}
#Faq #accueil .famille .reponse .photos {
grid-template-columns: 1fr;
}
/***********************************************************************************************************************
Fichier galerie.php
***********************************************************************************************************************/
#Galerie #accueil #photos {
grid-template-columns: 1fr;
}
#Galerie #accueil #photos .photo .legende {
/* font-size:1.6em; */
}
#Galerie #accueil #photos .photo {
grid-template-rows: 1fr auto;
}
/***********************************************************************************************************************
Fichier mentions_legales.php
***********************************************************************************************************************/
#Mentions_legales #accueil {
}
#Mentions_legales #accueil a {
padding:0px 5px 1px 5px;
}
#Mentions_legales #accueil p {
/* text-align: justify; */
/* margin: 0px; */
}
#Mentions_legales #accueil .adresse {
/* padding-left:10%; */
}
/***********************************************************************************************************************
Fichier nautic2021.php
***********************************************************************************************************************/
#Nautic2021 .logo_sh {
height:80px;
}
#Nautic2021 .logo_nautic {
height:80px;
}
#Nautic2021 .champs .champs_valeur {
min-height: 50px;
line-height: 50px;
vertical-align: middle;
}
#Nautic2021 .champs .champs_valeur input[type="checkbox"] {
margin-left: 30px;
}
#Nautic2021 .champs .champs_valeur label {
width: 70%;
min-height: 50px;
}
/***********************************************************************************************************************
Fichier produits.php
***********************************************************************************************************************/
#Produits .boutons_bas_de_page {
grid-template-columns: 1fr;
grid-template-areas:
"retour"
"suivant";
}
/*----------------------------------------*/
#Produits #accueil .produit {
grid-template-columns: 1fr;
grid-template-rows: auto;
grid-template-areas:
"photo_principale"
"nom"
"descriptif"
"photos";
}
/***********************************************************************************************************************
Fichier shipmembers.php
***********************************************************************************************************************/
/*--------------------------------------------------*/
#Shipmember {
/* font-size: 1.5em; */
}
#Shipmember .message {
/* font-size: 0.9em; */
}
#Shipmember .boutons_bas_de_page a {
margin: 50px 0px 30px 0px;
padding: 30px 10px;
}
#Shipmember .boutons_bas_de_page button {
display:block;
margin: 50px 0px 30px 0px;
padding: 30px 10px;
/* font-size: 1.2em; */
}
/*--------------------------------------------------*/
#Shipmember #login form {
grid-template-columns: 1fr;
}
#Shipmember #login form table td:nth-child(1) {
width: 30%;
}
/*--------------------------------------------------*/
#Shipmember #profil .profil {
row-gap:50px;
}
#Shipmember #profil .profil .champs {
display: grid;
grid-template-columns: 1fr;
row-gap: 20px;
}
+51
View File
@@ -0,0 +1,51 @@
/***********************************************************************************************************************
Fichier administration.php
***********************************************************************************************************************/
#Administration #accueil p {
text-align: justify;
}
#Administration .boutons_bas_de_page {
text-align: center;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-areas:
"retour suivant";
grid-column-gap: 20px;
grid-row-gap: 20px;
align-items: center;
margin-top: 50px;
}
#Administration .boutons_bas_de_page a {
background-color: var(--bleu_koriolan_fonce);
color: var(--blanc);
}
#Administration .boutons_bas_de_page .retour {
grid-area: retour;
}
#Administration .boutons_bas_de_page .suivant {
grid-area: suivant;
}
#Administration .boutons_bas_de_page a:hover {
color: var(--bleu_koriolan);
background-color: var(--bleu_koriolan_fonce);
}
#Administration #questionnaires .indicateur {
margin: 20px 0px 30px 0px;
}
#Administration #questionnaires .libelle_indicateur {
/* display: inline-block; */
width: 100%;
text-align: center;
}
#Administration #questionnaires .valeur_indicateur {
/* display: inline-block; */
width: 100%;
text-align: center;
font-weight: bold;
font-size: 2em;
}
+604
View File
@@ -0,0 +1,604 @@
/***********************************************************************************************************************
Fichier bateaux.php
***********************************************************************************************************************/
#Bateaux .entete_bateau {
border-bottom: 2px solid var(--bleu_koriolan_fonce);
height: 60px;
}
#Bateaux .entete_bateau .derniere_maj {
width: 60%;
padding: 10px 0px;
}
#Bateaux .entete_bateau .bouton_gestion_acces {
text-align: right;
float: right
}
#Bateaux .entete_bateau .bouton_gestion_acces a {
background-color: var(--bleu_koriolan_fonce);
color: var(--blanc);
width: 100%;
padding: 5px 20px;
display: block;
}
#Bateaux .entete_bateau .bouton_gestion_acces a:hover {
color: var(--bleu_koriolan);
background-color: var(--bleu_koriolan_fonce);
}
#Bateaux .entete_bateau .bouton_gestion_acces a.actif {
background-color: var(--bleu_koriolan);
color: var(--bleu_koriolan_fonce);
}
#Bateaux .boutons_haut_de_page {
text-align: center;
display: grid;
grid-template-columns: repeat(6, 1fr);
grid-column-gap: 20px;
grid-row-gap: 20px;
align-items: center;
margin: 20px 0px 30px 0px;
}
#Bateaux .boutons_haut_de_page a {
background-color: var(--bleu_koriolan_fonce);
color: var(--blanc);
width: 100%;
display: block;
}
#Bateaux .boutons_haut_de_page a:hover {
color: var(--bleu_koriolan);
background-color: var(--bleu_koriolan_fonce);
}
#Bateaux .boutons_haut_de_page a.actif {
background-color: var(--bleu_koriolan);
color: var(--bleu_koriolan_fonce);
}
#Bateaux #details_bateau .graphique .top_part_graph .vars .var{
cursor: pointer;
}
#Bateaux #details_bateau .graphique .top_part_graph .vars .var.actif {
border-radius: 5px;
background-color: var(--bleu_koriolan_transparent);
color: var(--bleu_koriolan_fonce);
font-weight: 600;
}
.page_principale {
width: 80% !important;
max-width: unset !important;
}
.table_wrapper {
overflow-x: auto;
}
#Bateaux #accueil table {
width: 100%;
margin-top: 20px;
text-align: center;
}
#Bateaux #accueil table th {
text-align: center;
padding: 3px 10px;
}
#Bateaux #accueil table td {
border-top: 1px solid var(--gris_tres_tres_pale);
text-align: center;
padding: 3px 10px;
font-size: 0.9em;
}
#Bateaux #accueil table td:nth-child(7) {
text-align: left;
}
#Bateaux #accueil table td a {
margin: 0px;
padding: 0px;
}
#Bateaux #details_bateau .onglets a {
background-color: var(--bleu_koriolan_fonce);
border-radius: 1em 1em 0 0;
color: var(--blanc);
display: inline-block;
padding: 3px 20px;
margin: 1px 1px 0px 1px;
}
#Bateaux #details_bateau .onglets a:hover {
color: var(--bleu_koriolan);
background-color: var(--bleu_koriolan_fonce);
}
#Bateaux #details_bateau .onglets a.actif {
background-color: var(--bleu_koriolan);
color: var(--bleu_koriolan_fonce);
}
#Bateaux #details_bateau .corps_details_bateau {
background-color: var(--blanc_casse);
}
#Bateaux #details_bateau .corps_details_bateau h2:nth-child(2) {
margin: 0px;
/* border-top: 0px;*/
}
#Bateaux #details_bateau .corps_details_bateau .champs {
display: grid;
grid-template-columns: 1fr 1fr;
margin-top: 5px;
}
#Bateaux #details_bateau .corps_details_bateau .champs .champs_titre {
text-align: left;
font-weight: bold;
padding-left: 20px;
/* background-color: var(--blanc_casse); */
}
#Bateaux #details_bateau .corps_details_bateau .champs .champs_valeur {
text-align: left;
/* background-color: var(--blanc_casse); */
}
.red {
color: red;
}
.orange {
color: #ffa600;
}
.green {
color: #02a602;
}
.capteur_state{
display: block;
padding: 0px;
height: 60px;
line-height: 60px;
width: 80px;
text-align: center !important;
font-size: 1.5em;
border-radius: 5px;
}
.capteur_off{
background-color: rgba(255, 30, 0, 0.2);
color: rgb(255,30,0);
}
.consommation_instantanee {
font-size: 1em;
padding: 6px;
background-image: url(images/icone_consommation_electrique.png);
background-size: contain;
background-position: center;
background-repeat: no-repeat;
margin-right: 5px;
}
.capteur_on{
background-color: rgba(177, 251, 23, 0.3);
color: rgb(177, 251, 23);
}
#Bateaux #details_bateau .corps_details_bateau .champs .champs_description {
grid-column: 1 / span 2;
text-align: justify;
font-size:0.8em;
}
#Bateaux #details_bateau .boutons_graphique {
text-align: center;
display: grid;
grid-template-columns: 1fr ;
grid-column-gap: 20px;
align-items: center;
margin: 20px 0px 20px 0px;
}
#Bateaux #details_bateau .boutons_graphique a {
background-color: var(--bleu_koriolan_fonce);
color: var(--blanc);
width: 300px;
margin: auto;
}
#Bateaux #details_bateau .boutons_graphique a:hover {
color: var(--bleu_koriolan);
background-color: var(--bleu_koriolan_fonce);
}
#Bateaux #details_bateau .boutons_graphique a.actif {
background-color: var(--bleu_koriolan);
color: var(--bleu_koriolan_fonce);
}
#Bateaux #details_bateau .corps_details_bateau .titre_composant {
display: grid;
grid-template-columns: 2fr 3fr 60px;
/* height: 70px; */
padding: 15px 0px 15px 0px;
margin: 2em 0px 0.2em 0px;
border-top: 1px solid var(--bleu_koriolan_fonce);
border-bottom: 1px solid var(--bleu_koriolan_fonce);
}
#Bateaux #details_bateau .corps_details_bateau .titre_composant p{
margin: unset;
text-align : unset;
}
#Bateaux #details_bateau .corps_details_bateau .titre_composant .titre_text{
font-size: 1.8em;
font-weight: 500;
}
#Bateaux #details_bateau .corps_details_bateau .titre_composant .titre_desc{
/* font-size: 1.8em; */
}
#Bateaux #details_bateau .corps_details_bateau .titre_composant .titre_capt{
display: flex;
}
#Bateaux #details_bateau .corps_details_bateau .titre_composant .titre_icon {
background-size: contain;
background-repeat: no-repeat;
cursor: pointer;
background-position: center;
margin-right: 10px;
}
#Bateaux #details_bateau .corps_details_bateau .titre_composant .more {
background-image: url("images/show_more.png");
}
#Bateaux #details_bateau .corps_details_bateau .titre_composant .less {
background-image: url("images/show_less.png");
}
#Bateaux #creation_bateau .champs {
display: grid;
grid-template-columns: 1fr;
}
#Bateaux #creation_bateau .champs .champs_titre {
text-align: left;
margin-top: 20px;
}
#Bateaux #creation_bateau .champs .champs_valeur {
text-align: left;
}
#Bateaux #creation_bateau .champs .champs_valeur select option.selection_actuelle {
color: var(--bleu_koriolan_fonce);
font-weight: bold;
}
#Bateaux #creation_bateau .champs .champs_valeur select option[disabled] {
color: var(--gris_tres_pale);
background-color: var(--gris_tres_tres_pale);
}
#Bateaux #creation_bateau .champs .champs_valeur input {
text-align: left;
}
#Bateaux #creation_bateau .champs .champs_valeur textarea {
border:1px solid var(--bleu_koriolan);
border-radius: 10px;
text-align: left;
}
#Bateaux #creation_bateau .champs .champs_valeur a img {
width: 60%;
}
#Bateaux #creation_bateau .champs .champs_nb {
font-size: 0.8em;
font-style: italic;
}
#Bateaux #confirmation_suppression_bateau .message_confirmation {
border-radius: 10px;
padding: 20px;
background-color: var(--rouge);
color: var(--jaune_post_it);
}
#Bateaux .boutons_bas_de_page {
text-align: center;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-column-gap: 20px;
grid-row-gap: 20px;
align-items: center;
margin-top: 50px;
}
#Bateaux .boutons_bas_de_page a {
background-color: var(--bleu_koriolan_fonce);
color: var(--blanc);
}
#Bateaux .boutons_bas_de_page a:hover {
color: var(--bleu_koriolan);
background-color: var(--bleu_koriolan_fonce);
}
.graphique {
display: flex;
flex-direction: column;
height: unset !important;
margin: 20px 0px 20px 0px !important;
}
.graphique .graph {
width: 100%;
height: 100%;
position: relative;
}
.graphique .titre{
margin-bottom: 20px;
}
.top_part_graph {
display: flex;
height: 100%;
}
.var {
/* display: flex; */
flex-direction: row;
}
.var input{
width: unset !important;
margin-right: 10px !important;
}
.var label{
display: unset !important;
}
.date_pick form{
display: flex;
flex-direction: column;
}
.date_pick input {
width: 100%;
position: relative;
margin: auto;
}
.date_pick label {
display: grid;
grid-template-columns: 2fr 3fr;
}
.date_pick span {
position: relative;
margin: auto;
}
.date_maj_version{
display: flex;
}
.date_maj_version input,.date_maj_version select{
width: 200px !important;
margin-left: 30px !important;
margin-right: 30px !important;
}
.gestion_acces{
/* height: 100; */
/* display: flex; */
}
.gestion_acces .users{
margin-bottom: 50px;
overflow-x: auto;
}
.gestion_acces .users table {
text-align: center;
}
.gestion_acces .users table tr {
height: 35px;
}
.gestion_acces .users table td {
border-top: 1px solid var(--gris_tres_tres_pale);
padding: 3px 10px;
font-size: 0.9em;
}
.gestion_acces .users table td#modifier_acces {
background-image: url(images/stylo.png);
background-repeat: no-repeat;
background-size: 80%;
background-position: center;
cursor: pointer;
}
.gestion_acces .generer_code form{
display: grid;
grid-template-columns: 2fr 2fr 1fr;
margin-bottom: 30px;
margin-top: 30px;
}
.download{
font-weight: 800;
padding: 0;
color: red;
}
.download:hover {
background: red;
color: var(--blanc_casse);
}
#type_acces {
height: unset;
}
form.variables {
display: grid;
padding-left: 100px;
grid-template-columns: 2fr 2fr 100px;
padding-right: 100px;
}
form.variables input{
padding: 5px 10px;
}
.variables button{
height: 40px;
padding: 0;
top: 20;
position: relative;
}
.help {
position: fixed;
height: 50px;
width: 50px;
background-size: contain;
background-repeat: no-repeat;
cursor: pointer;
bottom: 20px;
right: 20px;
z-index: 100;
}
.help_open {
background-image: url("images/question.png");
}
.help_close{
background-image: url("images/fermer_aide.png");
}
.help:hover{
animation: heart_pulse 2s ease-in 0s infinite;
}
.help_note{
width: 300px;
background-color: var(--blanc_casse);
min-height: 40px;
max-height: 600px;
position: fixed;
bottom: 26px;
right: 26px;
border-radius: 5px;
border: var(--bleu_koriolan) 1px solid;
padding-bottom: 20px;
z-index: 50;
}
#maCarte {
height: 600px;
z-index: 1;
}
/* --------------------- POP UP EDIT ACCESS----------------------*/
#popUpAcces{
display: block;
width: 100vw;
height: 100vh;
position: fixed;
background: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(3px);
left: 0;
top: 0;
z-index: 9999;
}
#popUpAccesModal{
width: 50%;
background: white;
height: 45%;
border-radius: 10px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
position: fixed;
box-shadow: 0px 0px 7px 2px var(--bleu_koriolan);
overflow-y: auto;
}
#popUpAccesModal #top_part{
display: grid;
grid-template-columns: auto 50px;
}
#popUpAccesModal #top_part p{
margin: unset;
text-align: left;
margin-left: 30px;
margin-top: 20px;
margin-bottom: 20px;
color: var(--bleu_koriolan_fonce);
font-weight: 600;
font-size: 25px;
}
#popUpAccesModal #top_part p#close{
background-image: url(images/croix_carre.png);
background-repeat: no-repeat;
background-size: contain;
cursor: pointer;
width: 30px;
height: 30px;
margin: 10px;
}
#popUpAccesModal form{
display: grid;
grid-template-columns: 1fr 1fr;
padding: 20px;
column-gap: 30px;
row-gap: 50px;
}
#popUpAccesModal form label{
position: relative;
}
#popUpAccesModal form label input, #popUpAccesModal form label select{
width: 100%;
}
#popUpAccesModal form label span {
position: absolute;
top: 0;
left: 10px;
transform: translateY(-18px);
font-size: 18px;
transition-duration: 300ms;
padding-left: 10px;
padding-right: 10px;
color: var(--bleu_koriolan_fonce);
font-weight: 600;
background-color: white;
}
#popUpAccesModal form .buttons_acces{
display: grid;
}
/* ------------------ Autres ---------------- */
#dateSlider{
margin-bottom: 50px !important;
margin-top: 50px !important;
}
#dateSlider .noUi-connect{
background-color: var(--bleu_koriolan);
}
@media only screen and (max-width: 580px) {
#Bateaux .boutons_haut_de_page {
grid-template-columns: minmax(50px, auto);
}
form.variables {
display: flex;
margin-bottom: 50px;
flex-direction: column;
padding : 0;
}
.vars {
display: grid !important;
grid-template-columns: 1fr !important;
}
#popUpAccesModal{
width: 95% !important;
height: 60% !important;
}
#popUpAccesModal form {
grid-template-columns: 1fr;
row-gap: 30px;
}
}
@media only screen and (max-width: 850px) {
.top_part_graph {
flex-direction: column-reverse;
}
.vars {
display: grid !important;
grid-template-columns: 1fr 1fr;
}
.page_principale {
width: 96% !important;
}
.gestion_acces{
flex-direction: column-reverse;
}
form.variables {
padding : 0;
}
#popUpAccesModal{
width: 80%;
height: 40%;
}
#dateSlider{
margin: auto;
width: 80%;
}
}
+106
View File
@@ -0,0 +1,106 @@
/***********************************************************************************************************************
Fichier cartes.php
***********************************************************************************************************************/
#Cartes #accueil .choix_type_carte {
display: grid;
grid-template-columns: 1fr 1fr;
grid-row-gap: 10px;
grid-column-gap: 10px;
margin:50px 0px;
}
#Cartes #accueil .choix_type_carte a {
background-color: var(--bleu_koriolan);
color: var(--bleu_koriolan_fonce);
}
#Cartes #accueil .choix_type_carte a:hover {
color: var(--bleu_koriolan);
background-color: var(--bleu_koriolan_fonce);
}
#Cartes #liste_cartes table {
width: 100%;
margin-top: 20px;
}
#Cartes #liste_cartes table th {
text-align: center;
padding: 3px 10px;
}
#Cartes #liste_cartes table td {
border-top: 1px solid var(--gris_tres_tres_pale);
text-align: center;
padding: 3px 10px;
font-size: 0.9em;
}
#Cartes #liste_cartes table td:nth-child(6) {
text-align: left;
}
#Cartes #liste_cartes table tr.carte_etat_inconnu td {
background-color: var(--blanc_casse);
}
#Cartes #liste_cartes table tr.carte_en_panne td {
background-color: var(--rouge_transparent);
}
#Cartes #liste_cartes table tr.carte_rebut td {
background-color: var(--gris_moyen);
}
#Cartes #liste_cartes table td a {
margin: 0px;
padding: 0px;
}
#Cartes #creation_carte .champs {
display: grid;
grid-template-columns: 1fr;
}
#Cartes #creation_carte .champs .champs_titre {
text-align: left;
margin-top: 20px;
}
#Cartes #creation_carte .champs .champs_valeur {
text-align: left;
}
#Cartes #creation_carte .champs .champs_valeur input {
text-align: left;
}
#Cartes #creation_carte .champs .champs_valeur textarea {
border:1px solid var(--bleu_koriolan);
border-radius: 10px;
text-align: left;
}
#Cartes #creation_carte .champs .champs_valeur a img {
width: 60%;
}
#Cartes #creation_carte .champs .champs_nb {
font-size: 0.8em;
font-style: italic;
}
#Cartes #confirmation_suppression_carte .message_confirmation {
border-radius: 10px;
padding: 20px;
background-color: var(--rouge);
color: var(--jaune_post_it);
}
#Cartes .boutons_bas_de_page {
text-align: center;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-column-gap: 20px;
grid-row-gap: 20px;
align-items: center;
margin-top: 20px;
}
#Cartes .boutons_bas_de_page a {
background-color: var(--bleu_koriolan_fonce);
color: var(--blanc);
}
#Cartes .boutons_bas_de_page a:hover {
color: var(--bleu_koriolan);
background-color: var(--bleu_koriolan_fonce);
}
+152
View File
@@ -0,0 +1,152 @@
#Contact{
height: 60vh;
width: 100%;
position: relative;
margin: auto;
display: flex;
flex-direction: column;
}
.text_contact{
height: 50%;
padding-left: 20%;
padding-right: 20%;
align-items: center;
display: flex;
}
.text_contact p{
font-size: 25px;
font-style: unset;
position: relative;
margin: auto;
}
.content_contact{
height: 50%;
padding-left: 5%;
padding-right: 5%;
display: flex;
}
.linkedin{
width: 33%;
height: 100%;
/* padding: 5%; */
display: flex;
}
.linkedin img{
height: 50px;
position: relative;
object-fit: contain;
margin: auto;
}
.linkedin a {
margin: auto;
}
.mail{
width: 43%;
height: 100%;
display: flex;
}
.mail p{
position: relative;
margin: auto;
padding: 20px;
padding-left: 40px;
padding-right: 40px;
background-color: var(--bleu_koriolan);
border-radius: 10px;
color: white;
font-size: 20px;
}
.phone{
width: 33%;
height: 100%;
/* padding: 5%; */
display: flex;
}
.phone p{
position: relative;
margin: auto;
padding: 20px;
padding-left: 40px;
padding-right: 40px;
background-color: var(--bleu_koriolan);
border-radius: 10px;
color: white;
font-size: 20px;
white-space: nowrap;
}
a:hover {
color: white !important;
}
@media only screen and (max-width: 850px) {
.content_contact{
display: flex;
flex-direction: column;
margin-top: -10px;
padding-left: 10%;
padding-right: 10%;
}
.linkedin{
width: 80vw;
height: 33%;
padding: 5%;
}
.mail{
width: 80vw;
height: 33%;
padding: 5%;
}
.phone{
width: 80vw;
height: 33%;
padding: 5%;
}
.text_contact{
height: 50%;
padding-left: 5%;
padding-right: 5%;
align-items: center;
display: flex;
}
.text_contact p{
font-size: 18px;
background-color: var(--bleu_koriolan_transparent);
padding: 22px;
border: 3px solid var(--bleu_koriolan_transparent);
border-radius: 15px;
}
.linkedin img{
height: 50px;
position: relative;
object-fit: contain;
margin: auto;
border-radius: 14px;
}
.mail p{
position: relative;
margin: auto;
margin-top: -10px;
width: 80vw;
padding: 20px;
padding-left: 30px;
padding-right: 30px;
background-color: var(--bleu_koriolan);
border-radius: 10px;
color: white;
font-size: 18px;
max-height: 67px;
}
.phone p{
position: relative;
width: 80vw;
margin: auto;
margin-top: -10px;
padding: 20px;
padding-left: 30px;
padding-right: 30px;
background-color: var(--bleu_koriolan);
border-radius: 10px;
color: white;
font-size: 18px;
max-height: 67px;
}
}
+23
View File
@@ -0,0 +1,23 @@
/***********************************************************************************************************************
Fichier mentions_legales.php
***********************************************************************************************************************/
#Mentions_legales {
display: grid;
grid-template-columns: 1fr;
}
#Mentions_legales #accueil a {
padding:0px 5px 1px 5px;
background-color: var(--bleu_koriolan);
}
#Mentions_legales #accueil a:hover {
padding:0px 5px 1px 5px;
background-color: var(--blanc);
}
#Mentions_legales #accueil p {
text-align: justify;
margin: 0px;
}
#Mentions_legales #accueil .adresse {
padding-left:10%;
}
+306
View File
@@ -0,0 +1,306 @@
/***********************************************************************************************************************
Fichier shipmembers.php
***********************************************************************************************************************/
#Shipmembers h2 {
margin-bottom: 30px;
}
#Shipmembers .message p {
text-align: justify;
}
#Shipmembers .boutons_bas_de_page a {
background-color: var(--bleu_koriolan_fonce);
color: var(--blanc);
text-align: center;
margin: 10px 0px 30px 0px;
display:block;
}
#Shipmembers .boutons_bas_de_page a:hover {
color: var(--bleu_koriolan);
}
#Shipmembers .boutons_bas_de_page button {
display:block;
margin: 10px 0px 30px 0px;
width: 100%;
}
/*--------------------------------------------------*/
#Shipmembers #login form {
display: grid;
grid-template-columns: 1fr 1fr;
column-gap:40px;
row-gap:80px;
align-items: start;
}
#Shipmembers #login .login {
display: grid;
grid-template-columns: 1fr;
row-gap:20px;
}
#Shipmembers #login .login .message_login {
text-align: justify;
}
#Shipmembers #login .login .champs {
display: grid;
grid-template-columns: 1fr;
}
#Shipmembers #login .login .champs .champs_titre {
text-align: left;
}
#Shipmembers #login .login .champs .champs_valeur {
text-align: left;
}
#Shipmembers #login .login .champs .champs_valeur input {
text-align: left;
}
#Shipmembers #login .login .champs .champs_valeur textarea {
border:1px solid var(--bleu_koriolan);
border-radius: 10px;
text-align: left;
}
/*--------------------------------------------------*/
#Shipmembers #activation form {
display: grid;
grid-template-columns: 1fr;
row-gap:80px;
align-items: start;
}
#Shipmembers #activation .shipmember {
display: grid;
grid-template-columns: 1fr;
row-gap:10px;
}
#Shipmembers #activation .shipmember .lignes {
display: grid;
grid-template-columns: 1fr;
row-gap:10px;
}
#Shipmembers #activation .shipmember .ligne {
display: grid;
grid-template-columns: 1fr 3fr;
}
#Shipmembers #activation .shipmember .ligne .titre_ligne {
border-bottom: 1px solid var(--bleu_koriolan);
}
/*--------------------------------------------------*/
#Shipmembers #generation_mdp form {
display: grid;
grid-template-columns: 1fr;
row-gap:80px;
align-items: start;
}
#Shipmembers #generation_mdp .shipmember {
display: grid;
grid-template-columns: 1fr;
row-gap:10px;
}
#Shipmembers #generation_mdp .shipmember .lignes {
display: grid;
grid-template-columns: 1fr;
row-gap:10px;
}
#Shipmembers #generation_mdp .shipmember .ligne {
display: grid;
grid-template-columns: 1fr 3fr;
}
#Shipmembers #generation_mdp .shipmember .ligne .titre_ligne {
border-bottom: 1px solid var(--bleu_koriolan);
}
/*--------------------------------------------------*/
#Shipmembers #accueil {
display: grid;
grid-template-columns: 1fr;
column-gap:40px;
row-gap:80px;
align-items: start;
}
#Shipmembers #accueil .message {
text-align: justify;
}
/*--------------------------------------------------*/
#Shipmembers #administration table {
width: 100%;
margin: 20px 0px 50px 0px;
}
#Shipmembers #administration table th {
text-align: center;
padding: 3px 10px;
}
#Shipmembers #administration table td {
border-top: 1px solid var(--gris_tres_tres_pale);
text-align: left;
padding: 3px 10px;
font-size: 0.9em;
}
#Shipmembers #administration table td:nth-child(3) {
text-align: center;
}
#Shipmembers #administration table td a {
margin: 0px;
padding: 0px;
}
/*--------------------------------------------------*/
#Shipmembers #details table {
width: 100%;
margin: 20px 0px 50px 0px;
}
#Shipmembers #details table td {
border-top: 1px solid var(--gris_tres_tres_pale);
text-align: left;
padding: 3px 10px;
font-size: 0.9em;
}
/*--------------------------------------------------*/
#Shipmembers #profil form {
display: grid;
grid-template-columns: 1fr;
column-gap:40px;
row-gap:80px;
align-items: start;
}
#Shipmembers #profil .profil {
display: grid;
grid-template-columns: 1fr;
row-gap:10px;
}
#Shipmembers #profil .profil .champs {
display: grid;
grid-template-columns: 1fr 3fr;
}
#Shipmembers #profil .profil .champs .champs_titre {
text-align: left;
padding-left:20px;
line-height: 30px;
background-color: var(--bleu_koriolan_transparent);
border-bottom: 1px solid var(--bleu_koriolan);
border-radius: 5px 0px 0px 5px;
}
#Shipmembers #profil .profil .champs .champs_valeur {
text-align: left;
padding-left:20px;
line-height: 30px;
border-bottom: 1px solid var(--bleu_koriolan);
border-radius: 0px 5px 5px 0px;
}
/*--------------------------------------------------*/
#Shipmembers #modifier_profil form {
display: grid;
grid-template-columns: 1fr;
column-gap:40px;
row-gap:80px;
align-items: start;
}
#Shipmembers #modifier_profil .profil {
display: grid;
grid-template-columns: 1fr;
row-gap:10px;
}
#Shipmembers #modifier_profil .profil .message {
margin-top: 20px;
}
/*--------------------------------------------------*/
#Shipmembers #historique form {
display: grid;
grid-template-columns: 1fr;
column-gap:40px;
row-gap:80px;
}
#Shipmembers #historique .liste_commandes {
display: grid;
grid-template-columns: 1fr;
text-align: center;
}
#Shipmembers #historique .liste_commandes .titre {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
background-color: var(--bleu_koriolan_fonce);
color: var(--blanc);
line-height:40px;
}
#Shipmembers #historique .liste_commandes .commande {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
line-height:30px;
}
#Shipmembers #historique .liste_commandes .commande:nth-child(even) {
background-color: var(--bleu_koriolan_transparent);
}
#Shipmembers #historique .liste_commandes .commande .prix_ttc {
text-align: right;
}
#Shipmembers #historique .liste_commandes .commande .download a {
line-height:30px;
}
#Shipmembers #historique .liste_commandes .commande .download img {
width: 30px;
vertical-align: middle;
}
/*--------------------------------------------------*/
#Shipmembers #bateau form {
display: grid;
grid-template-columns: 1fr;
column-gap:40px;
row-gap:80px;
/* align-items: start; */
}
#Shipmembers #bateau form a {
display: grid;
grid-template-columns: 1fr;
column-gap:40px;
row-gap:80px;
/* align-items: start; */
}
#Shipmembers #bateau .acces_bateau a {
background-color: var(--bleu_koriolan_fonce);
color: var(--blanc);
text-align: left;
padding-left: 20px;
margin: 10px 30px 30px 30px;
display:block;
}
#Shipmembers #bateau .acces_bateau a:hover {
color: var(--bleu_koriolan);
}
#Shipmembers #bateau .acces_bateau button {
display:block;
margin: 10px 0px 30px 0px;
width: 100%;
}
+90
View File
@@ -0,0 +1,90 @@
.page_principale {
max-width: 80vw !important;
}
.create_text{
max-width: var(--largeur_maxi);
position: relative;
margin: auto;
}
.boutons_bas_de_page {
text-align: center;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-areas:
"retour suivant";
grid-column-gap: 20px;
grid-row-gap: 20px;
align-items: center;
margin-top: 50px;
}
.top_part {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
margin-bottom: 50px;
margin-top: 50px;
position: relative;
margin-left: auto;
margin-right: auto;
width: 100%;
}
.textes {
display: grid;
margin-bottom: 50px;
grid-template-columns: 1fr 1fr;
row-gap: 30px;
}
label{
width: 90%;
position: relative;
margin-left: auto;
margin-right: auto;
}
label select, label input , label textarea {
width: 100%;
}
label span{
position:absolute;
top:0;
left:10px;
transform: translateY(-20px);
font-size:20px;
transition-duration:300ms;
padding-left : 10px;
padding-right : 10px;
color : var(--bleu_koriolan_fonce);
font-weight: 600;
background-color: white;
}
#label_chemin_acces{
margin-top: 10px;
}
#chemin_acces{
height: 120px;
}
.create_text form{
display: grid;
grid-template-columns: 1fr;
}
@media only screen and (max-width: 850px) {
.top_part, .textes{
grid-template-columns: 1fr;
margin-bottom: 10px;
}
label select, label input , label textarea {
margin-bottom: 20px;
}
label span {
transform: translateY(-15px);
font-size: 15px;
}
}
+38
View File
@@ -0,0 +1,38 @@
/***********************************************************************************************************************
Fichier uploads.php
***********************************************************************************************************************/
#Uploads #accueil p {
text-align: justify;
}
#Uploads #accueil th:nth-child(2) {
text-align: center;
}
#Uploads #accueil td:nth-child(2) {
text-align: center;
}
#Uploads #accueil td.erreur_fichier {
color: var(--rouge);
font-weight: bold;
}
#Uploads .boutons_bas_de_page {
text-align: center;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-column-gap: 20px;
grid-row-gap: 20px;
align-items: center;
margin-top: 20px;
}
#Uploads .boutons_bas_de_page a {
background-color: var(--bleu_koriolan_fonce);
color: var(--blanc);
}
#Uploads .boutons_bas_de_page a:hover {
color: var(--bleu_koriolan);
background-color: var(--bleu_koriolan_fonce);
}
+138
View File
@@ -0,0 +1,138 @@
/***********************************************************************************************************************
Fichier versions.php
***********************************************************************************************************************/
#Versions #accueil .choix_type_version {
display: grid;
grid-template-columns: 1fr 1fr;
grid-row-gap: 10px;
grid-column-gap: 10px;
margin:50px 0px;
}
#Versions #accueil .choix_type_version a {
background-color: var(--bleu_koriolan);
color: var(--bleu_koriolan_fonce);
}
#Versions #accueil .choix_type_version a.package {
grid-column: 1 / 3;
background-color: var(--bleu_koriolan_fonce);
color: var(--blanc);
}
#Versions #accueil .choix_type_version a:hover {
color: var(--bleu_koriolan);
background-color: var(--bleu_koriolan_fonce);
}
#Versions #liste_versions table {
width: 100%;
margin-top: 20px;
}
#Versions #liste_versions table th {
text-align: left;
padding: 3px 10px;
}
#Versions #liste_versions table td {
border-top: 1px solid var(--gris_tres_tres_pale);
text-align: left;
padding: 3px 10px;
font-size: 0.9em;
}
#Versions #liste_versions table td a {
margin: 0px;
padding: 0px;
}
#Versions #liste_versions table.package th:nth-child(1) {
width: 8%;
}
#Versions #liste_versions table.package th:nth-child(2) {
width: 12%;
}
#Versions #liste_versions table.package td:nth-child(1) {
font-weight: bold;
text-align: center;
}
#Versions #liste_versions table.version th:nth-child(2) {
width: 80%;
}
#Versions #creation_version .champs {
display: grid;
grid-template-columns: 1fr;
}
#Versions #creation_version .champs .champs_titre {
text-align: left;
margin-top: 20px;
}
#Versions #creation_version .champs .champs_valeur {
text-align: left;
}
#Versions #creation_version .champs .champs_valeur input {
text-align: left;
}
#Versions #creation_version .champs .champs_valeur textarea {
border:1px solid var(--bleu_koriolan);
border-radius: 10px;
text-align: left;
}
#Versions #creation_version .champs .champs_valeur a img {
width: 60%;
}
#Versions #confirmation_suppression_carte .message_confirmation {
border-radius: 10px;
padding: 20px;
background-color: var(--rouge);
color: var(--jaune_post_it);
}
#Versions #generation_archive .champs {
display: grid;
grid-template-columns: 1fr;
}
#Versions #generation_archive .champs .champs_titre {
text-align: left;
margin-top: 20px;
}
#Versions #generation_archive .champs .champs_valeur {
text-align: left;
}
#Versions .boutons_haut_bas_de_page {
text-align: center;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-column-gap: 20px;
grid-row-gap: 20px;
align-items: center;
margin-top: 20px;
}
#Versions #liste_versions .boutons_haut_bas_de_page {
grid-template-columns: 1fr 1fr;
}
#Versions #creation_version .boutons_haut_bas_de_page {
grid-template-columns: 1fr 1fr;
}
#Versions #creation_version .boutons_haut_bas_de_page.modification {
grid-template-columns: 1fr 1fr 1fr;
}
#Versions #generation_archive .boutons_haut_bas_de_page {
grid-template-columns: 1fr 1fr;
}
#Versions .boutons_haut_bas_de_page a {
background-color: var(--bleu_koriolan_fonce);
color: var(--blanc);
}
#Versions .boutons_haut_bas_de_page a:hover {
color: var(--bleu_koriolan);
background-color: var(--bleu_koriolan_fonce);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Some files were not shown because too many files have changed in this diff Show More