From f27cca08ff786ceff1870147f6d6bad14d71117f Mon Sep 17 00:00:00 2001
From: polo
Date: Fri, 23 Oct 2026 00:47:32 +0200
Subject: =?UTF-8?q?dossiers=20avec=20majuscule,=20namespace=20pour=20toute?=
=?UTF-8?q?s=20les=20classes,=20autoload=20psr-4,=20UserDataService::creat?=
=?UTF-8?q?eZip=20d=C3=A9plac=C3=A9=20dans=20Backup?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/service/Backup.php | 233 -------------------------
src/service/Captcha.php | 55 ------
src/service/Config.php | 88 ----------
src/service/EmailService.php | 104 -----------
src/service/FormValidation.php | 214 -----------------------
src/service/Installation.php | 107 ------------
src/service/Router.php | 376 ----------------------------------------
src/service/Security.php | 110 ------------
src/service/URL.php | 88 ----------
src/service/User.php | 23 ---
src/service/UserDataService.php | 46 -----
src/service/session.php | 90 ----------
12 files changed, 1534 deletions(-)
delete mode 100644 src/service/Backup.php
delete mode 100644 src/service/Captcha.php
delete mode 100644 src/service/Config.php
delete mode 100644 src/service/EmailService.php
delete mode 100644 src/service/FormValidation.php
delete mode 100644 src/service/Installation.php
delete mode 100644 src/service/Router.php
delete mode 100644 src/service/Security.php
delete mode 100644 src/service/URL.php
delete mode 100644 src/service/User.php
delete mode 100644 src/service/UserDataService.php
delete mode 100644 src/service/session.php
(limited to 'src/service')
diff --git a/src/service/Backup.php b/src/service/Backup.php
deleted file mode 100644
index 2ee69c1..0000000
--- a/src/service/Backup.php
+++ /dev/null
@@ -1,233 +0,0 @@
-format('Y-m-d') . '_' . $type . '.sql';
-
- // les versions de mysql sont comme ci: 8.0.36
- // celles de mariadb sont comme ça: 10.11.6-MariaDB
- $version = $entityManager->getConnection()->fetchOne('SELECT VERSION()');
- $engine = stripos($version, 'mariadb') !== false ? 'mariadb-dump' : 'mysqldump';
-
- $tmp = tempnam('../var', 'tmp_db_codes_'); // crée un fichier avec un nom aléatoire et des droits 600 (concurrence)
- // attention, si le dossier de destination n'est pas disponible, le fichier est placé avec les fichiers temporaires
- file_put_contents($tmp,
- "[client]\n
- user=" . Config::$user . "\n
- password=" . Config::$password . "\n
- host=" . Config::$db_host . "\n");
-
- $command = new Process([
- $engine,
- '--defaults-extra-file=' . $tmp, // pour ne pas enregistrer les codes dans l'historique de la console ou dans les processus de l'OS
- '--single-transaction',
- '--quick', // évite d'exploser la RAM si beaucoup de données
- '--result-file=' . $file_path,
- Config::$database
- ]);
-
- try{
- // unlink et chmod permettent que le serveur et l'utilisateur appelant bin/mysqldump.php réussissent
- if(file_exists($file_path)){
- unlink($file_path);
- }
- $command->mustRun(); // comme run() mais lance une ProcessFailedException
-
- //$file_path = self::gzipCompress($file_path); // '.gz' ajouté à la fin
-
- chmod($file_path, 0666);
- return $file_path;
- }
- finally{
- // exécuté même quand situé après "return"
- unlink($tmp);
- self::cleanBackups();
- }
- }
-
- // compression gzip (gros gain de place sur le serveur), nécessite l'extension zlib
- static public function gzipCompress(string $file_path): string
- {
- try{
- file_put_contents(
- $file_path . '.gz',
- gzencode(file_get_contents($file_path), 5), // plus rapide que 9 et taille identique d'après mes essais
- );
- unlink($file_path);
- $file_path .= '.gz';
- }
- finally{
- return $file_path;
- }
- }
-
- static public function getBackupList(): array
- {
- $files = scandir(Backup::$backup_dir); // affiche un warning si échoue (à cacher en prod)
- if(!$files){
- throw new RuntimeException("Le serveur a rencontré une erreur:
Accès aux backups impossible faute de permissions.");
- }
-
- $backup_array = [];
- foreach($files as $file){
- if($file[0] === '.'){
- continue;
- }
- $backup_array[] = $file;
- }
- return $backup_array;
- }
-
- static public function cleanBackups(): void
- {
- $files = glob(self::$backup_dir . '/*.sql');
- //usort($files, fn($a, $b) => filemtime($b) <=> filemtime($a)); // filemtime = date de dernière modification
- arsort($files);
-
- // tri par nom de BDD puis par date
- $sorted_files = [];
- $list_by_database = []; // pour le nettoyage 2
- foreach($files as $file){
- $exploded = explode('_', basename($file));
- $sorted_files[$exploded[0]][$exploded[1]][] = $file;
- $list_by_database[$exploded[0]][] = $file;
- }
-
- $date = new DateTime;
- foreach($sorted_files as $db_name => $from_one_database){
- // on garde une "quantité à garder" par BDD
- if(count($from_one_database) > self::$amount_to_keep){
- // nettoyage 1
- foreach($from_one_database as $date_key => $with_same_date){
- // pas touche à aujourd'hui
- if($date_key != $date->format('Y-m-d')){
- self::cleanBackupsByPriority($with_same_date);
- }
- }
- // nettoyage 2
- $files_to_delete = array_slice($list_by_database[$db_name], self::$amount_to_keep);
- foreach($files_to_delete as $file){
- unlink($file);
- }
- }
- }
- }
-
- // conserver un seul backup par jour choisi dans cet ordre de préférence: console => before-restore => download => auto
- // cet ordre correspond à: volonté de l'utilisateur => état du jour avant changement => volonté de changement => automatique sans contrôle
- static private function cleanBackupsByPriority(array $files): void
- {
- $priorities = [
- 'console' => 1,
- 'before-restore' => 2,
- 'uploaded' => 3,
- 'auto' => 4,
- ];
- $best_priority = PHP_INT_MAX;
-
- // recherche du fichier à conserver
- $to_keep = null;
- foreach($files as $file){
- foreach($priorities as $keyword => $priority){
- if(str_contains(basename($file), $keyword) && $priority < $best_priority){
- $best_priority = $priority;
- $to_keep = $file;
- break;
- }
- }
- }
- // suppression des autres
- foreach($files as $file){
- if($file !== $to_keep){
- unlink($file);
- }
- }
- }
-
- static public function restoreDatabase(EntityManager $entityManager, string $file_name, array $exclusion_list = []): void
- {
- // création d'un backup de sécurité non écrasable
- $date = new DateTime;
- if(!file_exists(self::$backup_dir . '/' . Config::$database . '_' . $date->format('Y-m-d') . '_before-restore.sql')){
- Backup::mySQLdump($entityManager, 'before-restore');
- }
-
- $version = $entityManager->getConnection()->fetchOne('SELECT VERSION()');
- $engine = stripos($version, 'mariadb') !== false ? 'mariadb' : 'mysql';
-
- $tables = self::getDBListOfTables($entityManager, $exclusion_list); // choisir les tables à effacer et restaurer, exclure "user"
-
- $tmp_db_codes = tempnam('../var', 'tmp_db_codes_'); // crée un fichier avec un nom aléatoire et des droits 600 (concurrence)
- file_put_contents($tmp_db_codes,
- "[client]\n
- user=" . Config::$user . "\n
- password=" . Config::$password . "\n
- host=" . Config::$db_host . "\n");
-
- //$file_name = self::gzipExtract($file_name); // '.gz' ajouté à la fin
-
- $command = new Process([
- $engine, // mariadb ou mysql
- '--defaults-extra-file=' . $tmp_db_codes, // pour ne pas enregistrer les codes dans l'historique de la console ou dans les processus de l'OS
- Config::$database
- ]);
- $command->setInput(file_get_contents(Backup::$backup_dir . '/' . $file_name)); // l'entrée <
-
- // utiliser une liste de tables à exclure dynamique
- try{
- // tout effacer
- $tables_with_backquotes = array_map(fn($t) => '`' . $t . '`', $tables);
- if(!empty($tables_with_backquotes)){
- $sql = "SET FOREIGN_KEY_CHECKS=0; DROP TABLE " . implode(', ', $tables_with_backquotes) . "; SET FOREIGN_KEY_CHECKS=1;";
- $entityManager->getConnection()->executeStatement($sql);
- }
-
- // copie des tables à ne pas restaurer
- foreach($exclusion_list as $excluded){
- $entityManager->getConnection()->executeStatement('RENAME TABLE `' . TABLE_PREFIX . $excluded . '` TO `' . TABLE_PREFIX . $excluded . '_dont_touch`;');
- }
-
- // restaurer
- $command->mustRun(); // comme run() mais lance une ProcessFailedException
-
- // remettre table user comme avant
- foreach($exclusion_list as $excluded){
- $entityManager->getConnection()->executeStatement('DROP TABLE `' . TABLE_PREFIX . $excluded . '`;');
- $entityManager->getConnection()->executeStatement('RENAME TABLE `' . TABLE_PREFIX . $excluded . '_dont_touch` TO `' . TABLE_PREFIX . $excluded . '`;');
- }
- }
- finally{
- // exécuté même quand situé après "return"
- unlink($tmp_db_codes);
- }
- }
-
- static private function getDBListOfTables(EntityManager $entityManager, array $exclusion_list = []): array
- {
- $tables = $entityManager->getConnection()->createSchemaManager()->listTableNames();
- foreach($tables as $key => $elem){
- foreach($exclusion_list as $excluded){
- if(!is_string($excluded)){ // cas pas du tout censé arriver!
- throw new LogicException("Un nom de table doit etre une chaîne de caractères.");
- }
- if($elem === TABLE_PREFIX . $excluded){
- unset($tables[$key]);
- break; // petite optimisation
- }
- }
- }
- return $tables;
- }
-}
\ No newline at end of file
diff --git a/src/service/Captcha.php b/src/service/Captcha.php
deleted file mode 100644
index d57f912..0000000
--- a/src/service/Captcha.php
+++ /dev/null
@@ -1,55 +0,0 @@
- on pourrait appliquer le pattern "singleton" (justification = le captcha devient une sorte de ressource partagée)
-
-declare(strict_types=1);
-
-class Captcha
-{
- private int $a;
- private int $b;
-
- public function __construct(){
- $this->a = rand(2, 9);
- $this->b = rand(2, 9);
- }
-
- public function getA(): string
- {
- return $this->toLettersFrench($this->a);
- }
- public function getB(): string
- {
- return $this->toLettersFrench($this->b);
- }
- public function getSolution(): int
- {
- return ($this->a * $this->b);
- }
-
- private function toLettersFrench(int $number): string
- {
- return match($number){
- 2 => 'deux',
- 3 => 'trois',
- 4 => 'quatre',
- 5 => 'cinq',
- 6 => 'six',
- 7 => 'sept',
- 8 => 'huit',
- 9 => 'neuf',
- default => '', // erreur
- };
- }
-
- // (à déplacer dans FormValidation?)
- static public function controlInput(string $input = '0'): int
- {
- // un POST est une chaîne qu'on doit convertir en nombre dans deux conditions:
- // test de format: $input est un nombre
- // test d'intégrité: supprimer les décimales avec (int) ne change pas la valeur du nombre
- return is_numeric($input) && $input == (int)$input ? (int)$input : 0;
- }
-}
\ No newline at end of file
diff --git a/src/service/Config.php b/src/service/Config.php
deleted file mode 100644
index 7077e01..0000000
--- a/src/service/Config.php
+++ /dev/null
@@ -1,88 +0,0 @@
-Le fichier config/config.ini n'existe pas ou n'est pas lisible.
";
- }
- define('TABLE_PREFIX', self::$table_prefix);
- }
-
- // renseigner les variables internes de Config
- static private function hydrate(array $raw_data): void
- {
- foreach($raw_data as $field => $value)
- {
- if($value != '') // valeur par défaut
- {
- if(isset(self::$$field)) // le champ existe dans Config
- {
- // problème du slash à la fin du nom d'un dossier
- $value = self::slashAtEndOfPath($field, $value);
- self::$$field = $value;
- }
- else
- {
- echo "debug: le fichier config.ini comporte une erreur, le champ: " . $field . " est incorrect,\nl'information contenue sur cette ligne ne sera pas utilisée\n";
- }
- }
- /*else
- {
- echo "debug: le champ " . $field . " est vide, la valeur par défaut " . self::$$field . " sera utilisée.\n";
- }*/
- }
- }
-
-
- // pour que les chemins finissent toujours par un /
- static private function slashAtEndOfPath(string $field, string $value): string
- {
- foreach(self::$path_vars as $item)
- {
- if($field === $item){
- return !str_ends_with($value, '/') ? $value . '/' : $value;
- }
- }
- return $value;
- }
-}
diff --git a/src/service/EmailService.php b/src/service/EmailService.php
deleted file mode 100644
index 1579bdb..0000000
--- a/src/service/EmailService.php
+++ /dev/null
@@ -1,104 +0,0 @@
- exceptions
- $mail->CharSet = 'UTF-8';
-
- $smtp_host = $form_data->getData()['smtp_host'] ?? Config::$smtp_host;
- $smtp_secure = $form_data->getData()['smtp_secure'] ?? Config::$smtp_secure;
- $smtp_username = $form_data->getData()['smtp_username'] ?? Config::$smtp_username;
- $smtp_password = $form_data->getData()['smtp_password'] ?? Config::$smtp_password;
-
- $email_from = $form_data->getData()['email_from'] ?? Config::$email_from; // adresse de l'expéditeur affichée
- $email_from = empty($email_from) ? $smtp_username : $email_from; // si vide
- $email_from_name = $form_data->getData()['email_from_name'] ?? Config::$email_from_name; // = nom de l'expéditeur affiché
- $email_dest = $form_data->getData()['email_dest'] ?? Config::$email_dest;
- $email_dest_name = $form_data->getData()['email_dest_name'] ?? Config::$email_dest_name; // = destinataire formulaire
-
- try{
- // Paramètres du serveur
- $mail->isSMTP();
- $mail->Host = $smtp_host;
- $mail->SMTPAuth = true;
- $mail->Port = 25;
-
- if($mail->SMTPAuth){
- $mail->Username = $smtp_username; // e-mail
- $mail->Password = $smtp_password;
- $mail->SMTPSecure = $smtp_secure; // tls (starttls) ou ssl (smtps)
- if($mail->SMTPSecure === 'tls'){
- $mail->Port = 587;
- }
- elseif($mail->SMTPSecure === 'ssl'){
- $mail->Port = 465;
- }
- }
- //var_dump($mail->smtpConnect());die; // test de connexion
-
- // Expéditeur et destinataire
- // $email_from, $email_from_name et $email_dest_name sont modifiables uniquement dans le config.ini pour l'instant
- $mail->setFrom(strtolower($email_from), $email_from_name);
- $mail->addAddress(strtolower($email_dest), $email_dest_name);
-
- // Contenu
- $mail->isHTML(true);
- if($test_email){
- $mail->Subject = "TEST d'un envoi d'e-mail depuis le site web";
- }
- else{
- $mail->Subject = 'Message envoyé par: ' . $name . ' (' . $email . ') depuis le site web';
- }
- $mail->Body = $message;
- $mail->AltBody = $message;
-
- $mail->send();
-
- // copie en BDD
- if(!$test_email && ($form_data->getData()['keep_emails'] ?? self::KEEP_EMAILS_DEFAULT)){
- $db_email = new Email($name, $email, $email_dest, $message, $form_data);
- $entityManager->persist($db_email);
- self::updateLastContactDate($entityManager, $email);
- $entityManager->flush();
- }
-
- return true;
- }
- catch(Exception $e){
- echo "Le message n'a pas pu être envoyé. Erreur : {$e}
{$mail->ErrorInfo}";
- return false;
- }
- }
-
- static public function updateLastContactDate(EntityManager $entityManager, string $sender): void
- {
- foreach($entityManager->getRepository('App\Entity\Email')->findAll() as $email){
- $email->getSenderAddress() === $sender ? $email->updateLastContactDate() : null;
- }
- }
-
- // peut être appelée par bin/clean_emails_cron.php
- static public function cleanEmails(EntityManager $entityManager): void
- {
- $emails = $entityManager->getRepository('App\Entity\Email')->findAll();
- foreach($emails as $email){
- if($email->getDeletionDate() < new \DateTime()){
- $entityManager->remove($email);
- }
- }
- $entityManager->flush();
- }
-}
\ No newline at end of file
diff --git a/src/service/FormValidation.php b/src/service/FormValidation.php
deleted file mode 100644
index 9d0b838..0000000
--- a/src/service/FormValidation.php
+++ /dev/null
@@ -1,214 +0,0 @@
- 'emailSendStrategy',
- self::EmailParam => 'emailParamStrategy',
- self::CreateUser => 'createUserStrategy',
- self::Connection => 'connectionStrategy',
- self::UsernameUpdate => 'usernameUpdateStrategy',
- self::PasswordUpdate => 'passwordUpdateStrategy'
- };
- }
-}
-
-class FormValidation
-{
- private array $data; // tableau associatif (probablement $_POST)
- private Closure $callStrategy;
- private ?string $error;
-
- public function __construct(array $data, ValidationStrategy $strategy){
- $this->data = $data;
- $method = $strategy->method();
- $this->callStrategy = fn() => $this->$method();
- }
-
- public function validate(): bool
- {
- $this->error = ($this->callStrategy)(); // appel de la callback
- return empty($this->errors);
- }
-
- public function getError(): string
- {
- return $this->error;
- }
-
- public function getField(string $field): string
- {
- return $this->data[$field] ?? '';
- }
-
- // méthodes de validation
- private function captchaValidate(bool $clean_session = true): ?string
- {
- $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0;
- $captcha_try = isset($this->data['captcha']) ? Captcha::controlInput($this->data['captcha']) : 0;
- if($clean_session){
- unset($_SESSION['captcha']);
- }
-
- if($captcha_try == 0){
- return 'error_non_valid_captcha';
- }
- elseif($captcha_solution == 0){ // ne peut pas arriver, si?
- return 'captcha_server_error';
- }
- elseif($captcha_try !== $captcha_solution){
- return 'bad_solution_captcha';
- }
- return null;
- }
-
- // erreurs à la création des mots de passe
- static private function removeSpacesTabsCRLF(string $chaine): string
- {
- $cibles = [' ', "\t", "\n", "\r"]; // doubles quotes !!
- return(str_replace($cibles, '', $chaine));
- }
-
-
- // stratégies
- private function emailSendStrategy(): ?string
- {
- if($error = $this->captchaValidate(false)){
- return $error;
- }
-
- if(empty($this->data['name']) || empty($this->data['email']) || empty($this->data['message'])
- || !isset($this->data['hidden']) || !empty($this->data['hidden'])){
- return 'missing_fields';
- }
-
- elseif(!filter_var(trim($this->data['email']), FILTER_VALIDATE_EMAIL)){
- return 'bad_email_address';
- }
-
- $this->data['name'] = htmlspecialchars(trim($this->data['name']));
- $this->data['email'] = htmlspecialchars(trim($this->data['email']));
- $this->data['message'] = htmlspecialchars($this->data['message']);
-
- return null;
- }
- private function emailParamStrategy(): ?string
- {
- if(empty($this->data['id']) || empty($this->data['what_param']) || empty($this->data['value'])
- || !isset($this->data['hidden']) || !empty($this->data['hidden'])){
- return 'missing_fields';
- }
-
- if(!in_array($this->data['what_param'], ['smtp_host', 'smtp_secure', 'smtp_username', 'smtp_password', 'email_dest'])){
- return 'unknown_parameter';
- }
- elseif($this->data['what_param'] === 'smtp_username' || $this->data['what_param'] === 'email_dest'){
- if(!filter_var($this->data['value'], FILTER_VALIDATE_EMAIL)){
- return 'invalide_email_address';
- }
- }
- return null;
- }
- private function createUserStrategy(): ?string
- {
- if($error = $this->captchaValidate()){
- return $error;
- }
-
- // test mauvais paramètres
- if(empty($this->data['login']) || empty($this->data['password']) || empty($this->data['password_confirmation'])
- || !isset($this->data['create_user_hidden']) || !empty($this->data['create_user_hidden']))
- {
- return 'bad_login_or_password';
- }
-
- if($this->data['password'] !== $this->data['password_confirmation']){
- return 'different_passwords';
- }
-
- if($this->data['login'] !== self::removeSpacesTabsCRLF(htmlspecialchars($this->data['login']))
- || $this->data['password'] !== self::removeSpacesTabsCRLF(htmlspecialchars($this->data['password']))){
- return 'forbidden_characters';
- }
- return null;
- }
- private function connectionStrategy(): ?string
- {
- if($error = $this->captchaValidate()){
- return $error;
- }
-
- if(empty($this->data['login']) || empty($this->data['password'])
- || !isset($this->data['connection_hidden']) || !empty($this->data['connection_hidden']))
- {
- return 'bad_login_or_password';
- }
- return null;
- }
- private function usernameUpdateStrategy(): ?string
- {
- if($error = $this->captchaValidate()){
- return $error;
- }
-
- if(empty($this->data['login']) || empty($this->data['password']) || empty($this->data['new_login'])
- || !isset($this->data['modify_username_hidden']) || !empty($this->data['modify_username_hidden']))
- {
- return 'bad_login_or_password';
- }
-
- $new_login = self::removeSpacesTabsCRLF(htmlspecialchars($this->data['new_login']));
- if($new_login !== $this->data['new_login']){
- return 'forbidden_characters';
- }
-
- if($this->data['login'] !== $_SESSION['user']['username']){
- return 'bad_login_or_password';
- }
- if($this->data['login'] === $new_login){
- return 'same_username_as_before';
- }
- return null;
- }
- private function passwordUpdateStrategy(): ?string
- {
- if($error = $this->captchaValidate()){
- return $error;
- }
-
- if(empty($this->data['login']) || empty($this->data['password']) || empty($this->data['new_password'])
- || !isset($this->data['modify_password_hidden']) || !empty($this->data['modify_password_hidden']))
- {
- return 'bad_login_or_password';
- }
-
- $new_password = self::removeSpacesTabsCRLF(htmlspecialchars($this->data['new_password']));
- if($new_password !== $this->data['new_password']){
- return 'forbidden_characters';
- }
-
- if($this->data['login'] !== $_SESSION['user']['username']){
- return 'bad_login_or_password';
- }
- if($this->data['password'] === $new_password){
- return 'same_password_as_before';
- }
- return null;
- }
-}
\ No newline at end of file
diff --git a/src/service/Installation.php b/src/service/Installation.php
deleted file mode 100644
index f7de2cf..0000000
--- a/src/service/Installation.php
+++ /dev/null
@@ -1,107 +0,0 @@
-L'extension " . $extension . " est manquante.");
- $flag = true;
- }
- }
- if(!class_exists(DOMDocument::class)){ // théoriquement plus fiable que extension_loaded()
- echo("L'extension dom est manquante.
");
- $flag = true;
- }
-
- /*if(!extension_loaded('imagick') && !extension_loaded('gd')){
- echo("il manque une de ces extensions au choix pour le traitement des images: imagick (de préférence) ou gd.
");
- $flag = true;
- }*/
- // si imagick n'est pas disponible, essayer gd (reste encore à coder)
-
- if($flag){
- echo 'Réalisez les actions nécéssaires sur le serveur ou contactez l\'administrateur du site.
- Quand le problème sera résolu, il vous suffira de recharger la page.
';
- die;
- }
- }
-
- static public function checkFilesAndFoldersRights(): void
- {
- // -- droits des fichiers et dossiers --
- $droits_dossiers = 0777;
-
- $flag = false;
- if(!file_exists('user_data')){
- try{
- mkdir('user_data/');
- chmod('user_data/', $droits_dossiers);
- }
- catch(Exception $e){
- echo 'Le dossier public/user_data introuvable et le serveur n\'a pas la permission de le créer.
- Pour faire ça bien:
sudo -u "serveur web" mkdir /chemin/du/site/public/user_data
';
- echo $e;
- $flag = true;
- }
- }
- if(!file_exists('../var')){
- try{
- mkdir('../var');
- chmod('../var', $droits_dossiers);
- }
- catch(Exception $e){
- echo $e;
- $flag = true;
- }
- }
- if(!file_exists('../var/backups')){
- try{
- mkdir('../var/backups');
- chmod('../var/backups', $droits_dossiers); // autoriser à la fois le serveur et les scripts dans bin/
- }
- catch(Exception $e){
- echo $e;
- $flag = true;
- }
- }
-
- // droits 600 pour celui-ci
- if(!file_exists('../config/config.ini')){
- // aide à la création du config.ini
- echo 'Le fichier config/config.ini est introuvable.
';
- echo 'Il doit obligatoirement contenir les codes de la base de données, le protocole http ou https (et éventuellement le port) utilisé pour créer les liens internes.
- Un modèle est disponible, il s\'agit du fichier config/config-template.ini
- Ce fichier a une importance critique. Si vous le pouvez faites en sorte que le serveur en soit le propriétaire et donner lui des droits 600.
';
- $flag = true;
- }
- /*else{
- // propriétaire du fichier
- if(fileowner('../config/config.ini') != posix_geteuid()){
- echo "le fichier config/config.ini n'appartient pas au serveur.
";
- }
- else{
- // droits du config.ini
- if(substr(sprintf('%o', fileperms('../config/config.ini')), -4) != 600){
- echo 'Attention, le
';
- //chmod('../config/config.ini', $droits_fichiers);
- }
- }
- }*/
- if($flag){
- die;
- }
-
- // tester les liens internes
- //
-
- // le test de connexion à la BDD est dans le doctrine bootstrap
- }
-}
\ No newline at end of file
diff --git a/src/service/Router.php b/src/service/Router.php
deleted file mode 100644
index 28a6c39..0000000
--- a/src/service/Router.php
+++ /dev/null
@@ -1,376 +0,0 @@
- 1er test, méthode http GET? POST?
-=> 2ème test, type de contenu:
-"application/x-www-form-urlencoded" = formulaire
-"application/json" = requête AJAX avec fetch()
-"multipart/form-data" = upload d'image par tinymce
-$_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' requête AJAX xhs, non utilisée
-=> 3ème test, comme le 2ème test mais uniquement si IS_ADMIN est vrai */
-
-/* classes de réponses pour les contrôleurs
-Response($html, Response::HTTP_OK) page html
-JsonResponse(['success' => true, 'data' => $data]) ajax
-RedirectResponse('index.php?page=login') redirection
-BinaryFileResponse($filePath) téléchargement
-StreamedResponse(function () {echo "ligne 1\n";echo "ligne 2\n";}) gros fichier */
-
-// relire ça à l'occaz:
-// https://symfony.com/doc/current/introduction/from_flat_php_to_symfony.html
-
-declare(strict_types=1);
-
-use Symfony\Component\HttpFoundation\Request;
-use Doctrine\ORM\EntityManager;
-use Symfony\Component\HttpFoundation\JsonResponse;
-use Symfony\Component\HttpFoundation\RedirectResponse;
-use Symfony\Component\HttpFoundation\Response;
-
-class Router{
- private Request $request;
- private EntityManager $entityManager;
- private string $route = ''; // défaut page d'accueil
-
- public function __construct(Request $request, EntityManager $entityManager){
- $this->request = $request;
- $this->entityManager = $entityManager;
-
- if(!User::existUsers($entityManager)){ // table "user" vide
- $this->route = 'no_user';
- }
- }
-
- public function dispatch(): Response
- {
- if($this->request->getMethod() === 'GET'){
- // table "user" vide
- if($this->route === 'no_user'){
- ob_start();
- require AbstractBuilder::VIEWS_PATH . 'user_create.php';
- return new Response(ob_get_clean());
- }
-
- // bouton déconnexion (méthode GET parce que l'utilisateur ne modifie plus de données à partir de là)
- if($this->request->query->get('action') === 'deconnection'){
- return UserController::disconnect(); // retourne un RedirectResponse
- }
-
- // articles suivants
- if($this->request->query->get('fetch') === 'next_articles'){
- return ArticleController::fetch($this->entityManager, $this->request); // retourne un JsonResponse
- }
-
- // données du calendrier
- // création du calendrier ou changement de dates affichées (boutons flèches mais pas changement de vue)
- if($this->request->query->get('action') === 'get_events'
- && $this->request->query->has('start') && $this->request->query->has('end') && empty($this->request->getPayload()->all())){ // getPayload ne récupère pas que des POST
- return CalendarController::getData($this->entityManager);
- }
-
- // pages interdites
- if(!IS_ADMIN && in_array(CURRENT_PAGE, ['menu_paths', 'new_page', 'user_edit', 'emails', 'maintenance'])){
- return new RedirectResponse((string)new URL);
- }
-
- if(IS_ADMIN){
- if($this->request->query->get('action') === 'get_mysqldump'){
- return MaintenanceController::getLastDump($this->entityManager);
- }
- if($this->request->query->get('action') === 'get_all_media'){
- return MaintenanceController::getAllMedia();
- }
- }
-
- // affichage d'une page
- return ViewController::getWebPage($this->entityManager, $this->request);
- }
-
-
- elseif($this->request->getMethod() === 'POST'){
- /* -- contrôleurs appelables par tout le monde -- */
-
- // table "user" vide
- if($this->route === 'no_user'){
- return UserController::createAdminUser($this->entityManager);
- }
-
- // requête JSON avec fetch()
- if($this->request->headers->get('Content-Type') === 'application/json')
- {
- $json = json_decode($this->request->getContent(), true); // = json_decode(file_get_contents('php://input'), true);
-
- // formulaire de contact
- if($this->request->query->get('action') === 'send_email'){
- return ContactFormController::sendVisitorEmail($this->entityManager, $json);
- }
- /*else{
- return new JsonResponse(['success' => false, 'error' => 'tu fais quoi là mec?'], JsonResponse::HTTP_BAD_REQUEST);
- }*/
- }
-
- // envoi formulaire HTML
- elseif($this->request->headers->get('Content-Type') === 'application/x-www-form-urlencoded'){
- // tentative de connexion
- if($this->request->query->get('action') === 'connection'){
- return UserController::connect($this->entityManager);
- }
- /*else{
- return new RedirectResponse((string)new URL(['error' => 'tu fais quoi là mec?']));
- }*/
- }
-
- if(IS_ADMIN){
- /* -- requêtes AJAX -- */
-
- // requêtes JSON avec fetch()
- if($this->request->headers->get('Content-Type') === 'application/json'){
- $json = json_decode($this->request->getContent(), true); // = json_decode(file_get_contents('php://input'), true);
-
- if($this->request->query->has('action')){
- /* -- manipulation des articles -- */
- if($this->request->query->get('action') === 'editor_submit' && isset($json['id']) && isset($json['content'])){
- return ArticleController::editorSubmit($this->entityManager, $json);
- }
- elseif($this->request->query->get('action') === 'delete_article' && isset($json['id'])){
- return ArticleController::deleteArticle($this->entityManager, $this->request); // version AJAX
- }
- elseif($this->request->query->get('action') === 'switch_positions' && isset($json['id1']) && isset($json['id2'])){
- return ArticleController::switchPositions($this->entityManager, $json);
- }
- elseif($this->request->query->get('action') === 'date_submit' && isset($json['id']) && isset($json['date'])){
- return ArticleController::dateSubmit($this->entityManager, $json);
- }
-
- switch($this->request->query->get('action')){
- /* -- bloc Formulaire -- */
- case 'keep_emails':
- return ContactFormController::keepEmails($this->entityManager, $json);
- case 'set_retention_period':
- return ContactFormController::setEmailsRetentionPeriod($this->entityManager, $json);
- case 'set_email_param':
- return ContactFormController::setEmailParam($this->entityManager, $json);
- case 'test_email':
- return ContactFormController::sendTestEmail($this->entityManager, $json);
-
- /* -- page emails -- */
- case 'delete_email':
- return ContactFormController::deleteEmail($this->entityManager, $json);
- case 'toggle_sensitive_email':
- return ContactFormController::toggleSensitiveEmail($this->entityManager, $json);
-
- /* -- upload d'image dans tinymce par copier-coller -- */
- // collage de HTML contenant une ou plusieurs balises
- case 'upload_image_url':
- return ImageUploadController::uploadImageHtml();
- // collage d'une image (code base64 dans le presse-papier) non encapsulée dans du HTML
- case 'upload_image_base64':
- return ImageUploadController::uploadImageBase64();
-
- /* -- requêtes spécifiques au calendrier -- */
- case 'new_event':
- return CalendarController::newEvent($json, $this->entityManager);
- case 'update_event':
- return CalendarController::updateEvent($json, $this->entityManager);
- case 'remove_event':
- return CalendarController::removeEvent($json, $this->entityManager);
-
- /* -- mode maintenance -- */
- case 'get_logs':
- return MaintenanceController::getLogs($this->entityManager);
- case 'erase_logs':
- return MaintenanceController::eraseLogs($this->entityManager);
-
- default:
- return new JsonResponse(['success' => false, 'error' => 'bad parameters'], JsonResponse::HTTP_BAD_REQUEST);
- }
- }
-
- /* -- site entier (header, footer, favicon) -- */
- elseif($this->request->query->has('head_foot_text')){
- return HeadFootController::setTextData($this->entityManager, $this->request->query->get('head_foot_text'), $json);
- }
- elseif($this->request->query->has('head_foot_social_check')){
- return HeadFootController::displaySocialNetwork($this->entityManager, $this->request->query->get('head_foot_social_check'), $json);
- }
-
- /* -- page Menu et chemins -- */
- elseif($this->request->query->has('menu_edit')){
- // ne suit pas la règle, faire ça dans un contrôleur?
- Model::$menu = new Menu($this->entityManager); // récupération des données
-
- // flèche gauche <=: position = position du parent + 1, parent = grand-parent, recalculer les positions
- if($this->request->query->get('menu_edit') === 'move_one_level_up' && isset($json['id'])){
- return MenuAndPathsController::MoveOneLevelUp($this->entityManager, $json);
- }
- // flèche droite =>: position (léments de a fraterie + 1, l'élément précédent devient le parent
- elseif($this->request->query->get('menu_edit') === 'move_one_level_down' && isset($json['id'])){
- return MenuAndPathsController::MoveOneLevelDown($this->entityManager, $json);
- }
- elseif($this->request->query->get('menu_edit') === 'switch_positions' && isset($json['id1']) && isset($json['id2'])){
- return MenuAndPathsController::switchPositions($this->entityManager, $json);
- }
- elseif($this->request->query->get('menu_edit') === 'display_in_menu' && isset($json['id']) && isset($json['checked'])){
- return MenuAndPathsController::displayInMenu($this->entityManager, $json);
- }
- elseif($this->request->query->get('menu_edit') === 'url_edit' && isset($json['id']) && isset($json['field']) && isset($json['input_data'])){
- return MenuAndPathsController::editUrl($this->entityManager, $json);
- }
- else{
- return new JsonResponse(['success' => false, 'error' => 'bad parameters'], JsonResponse::HTTP_BAD_REQUEST); // code 400
- }
- }
-
- /* -- mode Modification d'une page -- */
- // partie "page"
- elseif($this->request->query->has('page_edit')){
- switch($this->request->query->get('page_edit')){
- case 'page_title':
- return PageManagementController::setPageTitle($this->entityManager, $json);
- case 'page_description':
- return PageManagementController::setPageDescription($this->entityManager, $json);
- default:
- return new JsonResponse(['success' => false, 'error' => 'bad parameters'], JsonResponse::HTTP_BAD_REQUEST); // code 400
- }
- }
-
- // partie "blocs"
- elseif($this->request->query->has('bloc_edit')){
- switch($this->request->query->get('bloc_edit')){
- case 'rename_page_bloc':
- return PageManagementController::renameBloc($this->entityManager, $json);
- case 'switch_blocs_positions':
- return PageManagementController::SwitchBlocsPositions($this->entityManager, $json, $this->request->query->get('page'));
- case 'change_articles_order':
- return PageManagementController::changeArticlesOrder($this->entityManager, $json);
- case 'change_presentation':
- return PageManagementController::changePresentation($this->entityManager, $json);
- case 'change_cols_min_width':
- return PageManagementController::changeColsMinWidth($this->entityManager, $json);
- case 'change_pagination_limit':
- return PageManagementController::changePaginationLimit($this->entityManager, $json);
- default:
- return new JsonResponse(['success' => false, 'error' => 'bad parameters'], JsonResponse::HTTP_BAD_REQUEST); // code 400
- }
- }
-
- else{
- return new JsonResponse(['success' => false, 'error' => 'bad parameters'], JsonResponse::HTTP_BAD_REQUEST); // code 400
- }
- }
-
- /* -- upload avec FormData OU formulaire HTML avec fichier -- */
- elseif(str_starts_with($this->request->headers->get('Content-Type'), 'multipart/form-data')){ // = $_SERVER['CONTENT_TYPE']
- // dans tinymce avec le plugin (bouton "insérer une image" de l'éditeur ou glisser-déposer)
- if($this->request->query->get('action') === 'upload_image_tinymce'){
- return ImageUploadController::imageUploadTinyMce();
- }
- // dans tinymce, des quatre méthodes: bouton "link", drag & drop, html, base64
- elseif($this->request->query->get('action') === 'upload_file_tinymce'){
- return FileUploadController::fileUploadTinyMce();
- }
- elseif($this->request->query->has('head_foot_image')){
- return HeadFootController::uploadAsset($this->entityManager, $this->request->query->get('head_foot_image'));
- }
-
- /* -- page Maintenance -- */
- elseif($this->request->query->get('action') === 'restore_database' && $this->request->request->get('hidden') === ''
- && $this->request->files->has('uploaded_sql')){
- return MaintenanceController::downloadSQL($entityManager, $request);
- }
- else{
- // choix ici entre répondre en JSON ou par une redirection, choix du JSON pour pouvoir passer un message
- return new JsonResponse(['success' => false, 'error' => 'bad parameters'], JsonResponse::HTTP_BAD_REQUEST); // code 400
- }
- }
-
- /* -- formulaire HTML sans fichier -- */
- elseif($this->request->headers->get('Content-Type') === 'application/x-www-form-urlencoded'){
- if($this->request->query->get('action') === 'delete_article' && $this->request->query->has('id')){
- return ArticleController::deleteArticle($this->entityManager, $this->request); // version formulaire
- }
-
- /* -- nouvelle page -- */
- elseif($this->request->request->get('page_name') !== null
- && $this->request->request->get('page_name_path') !== null
- && $this->request->request->get('page_location') !== null
- && $this->request->request->get('page_description') !== null
- && $this->request->request->get('new_page_hidden') === ''){
- return PageManagementController::newPage($this->entityManager, $this->request->request);
- }
-
- /* -- suppression d'une page -- */
- elseif($this->request->request->get('page_id') !== null
- && $this->request->request->get('submit_hidden') === ''){
- return PageManagementController::deletePage($this->entityManager, $this->request->request->get('page_id'));
- }
-
-
- /* -- mode Modification d'une page -- */
- // modification du chemins en snake_case
- elseif($this->request->request->get('page_menu_path') !== null
- && $this->request->request->get('page_id') !== null
- && $this->request->request->get('page_name_path_hidden') === ''){
- return PageManagementController::updatePageMenuPath($this->entityManager, $this->request->request->get('page_menu_path'));
- }
- // ajout d'un bloc dans une page
- elseif($this->request->request->get('bloc_title') !== null
- && $this->request->request->get('bloc_select') !== null
- && $this->request->request->get('bloc_title_hidden') === ''){ // contrôle anti-robot avec input hidden
- return PageManagementController::addBloc($this->entityManager, $this->request);
- }
- // suppression d'un bloc de page
- elseif($this->request->request->get('delete_bloc_id') !== null
- && $this->request->request->get('delete_bloc_hidden') === ''){ // contrôle anti-robot avec input hidden
- return PageManagementController::deleteBloc($this->entityManager, $this->request);
- }
-
-
- /* -- page Menu et chemins -- */
- // création d'une entrée de menu avec une URL
- elseif($this->request->request->has("label_input") && $this->request->request->has("url_input") && $this->request->request->has("location")){
- return MenuAndPathsController::newUrlMenuEntry($this->entityManager);
- }
- // suppression d'une entrée de menu avec une URL
- elseif($this->request->request->has('delete') && $this->request->request->has('x') && $this->request->request->has('y')){ // 2 params x et y sont là parce qu'on a cliqué sur une image
- return MenuAndPathsController::deleteUrlMenuEntry($this->entityManager);
- }
-
-
- /* -- page Mon compte -- */
- elseif($this->request->query->get('action') === 'update_username'){
- return UserController::updateUsername($this->entityManager);
- }
- elseif($this->request->query->get('action') === 'update_password'){
- return UserController::updatePassword($this->entityManager);
- }
-
- /* -- page Maintenance -- */
- elseif($this->request->query->get('action') === 'restore_database' && $this->request->get('hidden') === '' && $this->request->request->has('selected_sql')){
- return MaintenanceController::handleBackupSelection($this->entityManager, $this->request);
- }
-
- // redirection page d'accueil
- return new RedirectResponse((string)new URL(['error' => 'paramètres inconnus']));
- }
-
- // requêtes XMLHttpRequest
- elseif($this->request->isXmlHttpRequest()){
- return new JsonResponse(['success' => false]); // noyer le poisson en laissant penser que le site gère les requêtes XHR
- }
-
- // POST admin ne matchant pas
- return new Response('bad parameters', Response::HTTP_BAD_REQUEST); // code 400
- }
-
- // POST non-admin ne matchant pas
- return new Response('bad parameters', Response::HTTP_BAD_REQUEST); // code 400
- }
-
- // méthode HTTP inconnue
- else{
- return new RedirectResponse((string)new URL(['error' => 'tu fais quoi là mec?']));
- }
- }
-}
\ No newline at end of file
diff --git a/src/service/Security.php b/src/service/Security.php
deleted file mode 100644
index 356f4f4..0000000
--- a/src/service/Security.php
+++ /dev/null
@@ -1,110 +0,0 @@
-1, // protection contre les élements et attributs dangereux
-
- // liste blanche d'éléments HTML
- 'elements'=> 'h1, h2, h3, h4, h5, h6, p, br, s, em, span, strong, a, ul, ol, li, sup, sub, code, blockquote, div, pre, table, caption, colgroup, col, tbody, tr, th, td, figure, img, figcaption, iframe, small',
-
- // liste noire d'attributs HTML
- 'deny_attribute'=> 'id, class' // on garde 'style'
- );
- // faire qu'un certain élément puisse n'avoir que certains attributs, regarder la doc
- private static $specHtmLawed = '';
-
- // obtenir du HTML non dangereur sans appliquer htmlspecialchars
- public static function secureHTML(string $chaine): string
- {
- return trim(htmLawed($chaine, self::$configHtmLawed, self::$specHtmLawed));
- }
-
- public static function secureFileName(string $chaine): string
- {
- // sécuriser un nom avec chemin avec basename?
- //$chaine = basename($chaine);
-
- /*
- - caractères interdits sous windows / \ : * ? " < > |
- - mac autorise les /
- - mac interdit :
- - linux autorise tout sauf les /
- - imagemagick ne supporte pas les :
-
- - 'espace' fonctionne
- - / remplacé par firefox en :
- - \ retire ce qui est devant le \
- - * fonctionne
- - ? permet le téléchargement mais pas l'affichage
- - " ne fonctionne pas, remplacé par %22, filtrer %22
- - < > fonctionnent
- - | fonctionne
- - = fonctionne, mais je filtre parce qu'on en trouve dans une URL
- - ' ` fonctionnent
- - % fonctionne
- - (){}[] fonctionnent
- - ^ fonctionne
- - # ne fonctionne pas
- - ~ fonctionne
- - & fonctionne
- - ^ pas encore testé
- */
-
- // => on remplace tout par des _
- // filtrer / et \ semble inutile
-
- /*$cibles = [' ', '/', '\\', ':', '*', '?', '<', '>', '|', '=', "'", '`', '"', '%22', '#'];
- $chaine = str_replace($cibles, '_', $chaine); // nécéssite l'extension mbstring
- $chaine = mb_strtolower($chaine);
- return($chaine);*/
-
- $chaine = preg_replace('/[^a-zA-Z0-9_-]/', '_', $chaine); // ne garder que les lettres, chiffres, tirets et underscores
- $chaine = preg_replace('/_+/', '_', $chaine); // doublons d'underscores
- return trim($chaine, '_');
-
- // les problèmes avec \ persistent !!
- // => javascript
- // malheureusement document.getElementById('upload').files[0].name = chaine; ne marche pas! interdit!
- // javascript ne doit pas pouvoir accéder au système de fichiers
- // solutions:
- // - au lieu de fournir une chaine (le chemin du fichier), donner un objet à files[0].name
- // - créer une copie du fichier et l'envoyer à la place
- // - envoyer le fichier en AJAX
- // - envoyer le nom du fichier à part puis renommer en PHP
- }
-}
-
-// lien sans http://
-function fixLinks($data)
-{
- // 1/
- // si une adresse est de type "domaine.fr" sans le http:// devant, le comportement des navigateurs est de rechercher un fichier comme si mon adresse commençait par file://
- // tomber ainsi sur une page d'erreur est parfaitement déroutant
-
- // regex pour détecter les balises et ajouter http:// au début des liens si nécessaire
- $pattern = '#(]+href=")((?!https?://)[^>]+>)#';
- //$data = preg_replace($pattern, '$1http://$2', $data);
-
- // 2/
- // cas où la regex fait mal son boulot:
- // l'erreur 404 est gérée par le .htaccess
- // et le visiteur est redirigé à la page "menu"
- // (ça ne règle pas le problème mais c'est mieux)
-
- // 3/
- // quand l'éditeur est ouvert (avant de valider l'article),
- // le lien qu'on vient de créer apparaît dans l'infobulle,
- // cliquer dessus ouvre un onglet sur une erreur 404
- // solution partielle avec le .htaccess
- //
- // solution? fermer ce nouvel onglet avec echo '';
- // comment déclencher le JS? en faisant qu'une erreur 404 causée pour cette raison soit particulière?
-
- return($data);
-}
diff --git a/src/service/URL.php b/src/service/URL.php
deleted file mode 100644
index 5bd2594..0000000
--- a/src/service/URL.php
+++ /dev/null
@@ -1,88 +0,0 @@
-params = $gets;
- if($anchor != ''){
- $this->setAnchor($anchor);
- }
- }
-
- // setters statiques
- static public function setProtocol(string $protocol = 'http'): void
- {
- self::$protocol = $protocol === 'https' ? 'https://' : 'http://';
- }
- static public function setPort(int|string $port = 80): void
- {
- if((int)$port === 443){
- self::$protocol = 'https://';
- self::$port = '';
- }
- elseif((int)$port === 80){
- self::$protocol = 'http://';
- self::$port = '';
- }
- else{
- self::$port = ':' . (string)$port;
- }
- }
- static public function setHost(string $host): void
- {
- self::$host = $host;
- }
- static public function setPath(string $path): void
- {
- self::$path = '/' . ltrim($path, '/');
- }
-
- //setters normaux
- public function addParams(array $gets): void
- {
- // array_merge est préféré à l'opérateur d'union +, si une clé existe déjà la valeur est écrasée
- $this->params = array_merge($this->params, $gets);
- }
- public function setAnchor(string $anchor = ''): void
- {
- if($anchor != ''){
- $this->anchor = '#' . ltrim($anchor, '#');
- }
- else{
- $this->anchor = '';
- }
- }
-
- private function makeParams(): string
- {
- $output = '';
- $first = true;
-
- foreach($this->params as $key => $value) {
- if($first){
- $output .= '?';
- $first = false;
- }
- else{
- $output .= '&';
- }
- $output .= $key . '=' . $value;
- }
- return $output;
- }
-
- public function __toString(): string
- {
- return self::$protocol . self::$host . self::$port . self::$path . $this->makeParams() . $this->anchor;
- }
-}
\ No newline at end of file
diff --git a/src/service/User.php b/src/service/User.php
deleted file mode 100644
index bd17dce..0000000
--- a/src/service/User.php
+++ /dev/null
@@ -1,23 +0,0 @@
-createQuery("SELECT u FROM App\Entity\User u")
- ->setMaxResults(1)
- ->getOneOrNullResult())
- {
- unset($_SESSION['user']);
- return false;
- }
- else{
- return true;
- }
- }
-}
\ No newline at end of file
diff --git a/src/service/UserDataService.php b/src/service/UserDataService.php
deleted file mode 100644
index e0156e2..0000000
--- a/src/service/UserDataService.php
+++ /dev/null
@@ -1,46 +0,0 @@
-open($file_path, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE){ // ou ZipArchive::FL_OVERWRITE, à comparer à ZipArchive::OVERWRITE
- throw new RuntimeException("Création ou ouverture du fichier demandé impossible à cause d'une erreur de permissions sur le serveur.");
- }
-
- // recherche récursive dans les dossiers dans $source_directories, c'est comme le paramètre "-r" dans la console
- $counter = 0;
- foreach($source_directories as $path){
- $directory = new RecursiveDirectoryIterator($path);
- $iterator = new RecursiveIteratorIterator($directory);
-
- foreach($iterator as $info){
- if($info->getFilename() != "." && $info->getFilename() != ".." && $info->getFilename() != '.htaccess'){ // chemins inutiles . et .. et le .htaccess
- $Zip->addGlob($info->getPathname(), 0, array(''));
- $counter++;
- }
- }
- }
- // recherche à la racine avec des pattern de noms de fichiers (optionnel)
- foreach($pattern_to_target_in_user_data as $one_pattern){
- $Zip->addGlob($one_pattern, 0, array(''));
- }
-
- $Zip->close();
- if($counter > 0){
- //chmod($file_path, 0666);
- return $zip_name;
- }
- else{
- throw new RuntimeException("Téléchargement des fichiers impossible, aucun fichier n'a été trouvé sur le serveur.");
- }
- }
-}
\ No newline at end of file
diff --git a/src/service/session.php b/src/service/session.php
deleted file mode 100644
index 24023e9..0000000
--- a/src/service/session.php
+++ /dev/null
@@ -1,90 +0,0 @@
- 'session_invalide']));
- die;
- }
-
- // MAJ de la session avec CERTAINES données
- $_SESSION['user']['username'] = $user->getLogin();
- $_SESSION['user']['role'] = $user->getRole();
-
- $is_admin = $user->getRole() === 'admin';
- }
-
- define('IS_ADMIN', $is_admin);
-
- // si on a un jour besoin d'une variable globale au lieu d'une constante
- //$GLOBALS['is_admin'] = $is_admin; // version modifiable 1
- /*function isAdmin(): bool { // version modifiable 2
- return $_SESSION['user']['role'] ?? null === 'admin';
- }*/
-
-
- // => système de cache à ajouter pour ne pas lire la BDD à chaque fois
- //remplacer ce qui est en haut
- /*$user = $_SESSION['user'] ?? null;
- if (!$user) {
- // visiteur
- }
- // Vérification périodique (ex: toutes les 5 minutes)
- if (time() - $user['last_check'] > 300) {
- $user = UserController::getUserById($user['id'], $entityManager);
- if (!$user) {
- session_destroy();
- header('Location: /login.php');
- exit;
- }
- // cache pour ne pas avoir à lire la BDD à chaque page
- $_SESSION['user'] = [
- 'id' => $user['id'],
- 'role' => $user['role'],
- 'username' => $user['username'],
- 'last_check' => time()
- ];
- $user = $_SESSION['user'];
- }
- $is_admin = ($user['role'] === 'admin');*/
-
-
- // améliorations possibles: ajouter expiration automatique + protection contre vol de session (IP / user-agent) sans casser ton app.
-}
-
-// nettoyage complet
-/*function cleanSession(){
- unset($_SESSION['user']); // mémoire vive
- session_destroy(); // fichier côté serveur
- setcookie('PHPSESSID', '', time() - 86400, '/'); // cookie de session
-}*/
\ No newline at end of file
--
cgit v1.2.3