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