From 90673ef19133e037cf401773f4262ba3d7d050bf Mon Sep 17 00:00:00 2001 From: polo Date: Sun, 3 Aug 2025 04:06:53 +0200 Subject: =?UTF-8?q?r=C3=A9organisation=204:=20d=C3=A9placement=20de=20fich?= =?UTF-8?q?iers,=20plus=20que=20des=20contr=C3=B4leurs=20dans=20/src/contr?= =?UTF-8?q?oller?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/index.php | 4 +- src/Captcha.php | 52 ++++++++ src/Config.php | 2 +- src/Security.php | 117 +++++++++++++++++ src/URL.php | 88 +++++++++++++ src/controller/Captcha.php | 52 -------- src/controller/Security.php | 117 ----------------- src/controller/URL.php | 88 ------------- src/controller/installation.php | 178 -------------------------- src/controller/request_router.php | 256 -------------------------------------- src/installation.php | 178 ++++++++++++++++++++++++++ src/request_router.php | 256 ++++++++++++++++++++++++++++++++++++++ 12 files changed, 694 insertions(+), 694 deletions(-) create mode 100644 src/Captcha.php create mode 100644 src/Security.php create mode 100644 src/URL.php delete mode 100644 src/controller/Captcha.php delete mode 100644 src/controller/Security.php delete mode 100644 src/controller/URL.php delete mode 100644 src/controller/installation.php delete mode 100644 src/controller/request_router.php create mode 100644 src/installation.php create mode 100644 src/request_router.php diff --git a/public/index.php b/public/index.php index ba0e354..b7eeeae 100644 --- a/public/index.php +++ b/public/index.php @@ -13,7 +13,7 @@ require "../vendor/autoload.php"; Config::load('../config/config.ini'); // les messages d'erreur de déploiement qu'on aime -require('../src/controller/installation.php'); +require('../src/installation.php'); phpDependancies(); //installation(); // des mkdir et chmod, chiant en dev @@ -54,7 +54,7 @@ if(!empty($_GET['id'])) } /* -- routeur des données de formulaires et requêtes AJAX -- */ -require '../src/controller/request_router.php'; +require '../src/request_router.php'; /* -- affichage d'une page -- */ diff --git a/src/Captcha.php b/src/Captcha.php new file mode 100644 index 0000000..c60a186 --- /dev/null +++ b/src/Captcha.php @@ -0,0 +1,52 @@ +a = rand(2, 9); + $this->b = rand(2, 9); + $this->solution = $this->a * $this->b; + } + + public function getA(): string + { + return $this->toLettersFrench($this->a); + } + public function getB(): string + { + return $this->toLettersFrench($this->b); + } + public function getSolution(): int + { + return $this->solution; + } + + 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 + }; + } + 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/Config.php b/src/Config.php index caa91d0..e25c180 100644 --- a/src/Config.php +++ b/src/Config.php @@ -1,5 +1,5 @@ 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 = ''; + + // ATTENTION, n'applique pas htmlspecialchars() !! + public static function secureString(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 + } +} + +// erreurs à la création des mots de passe +function removeSpacesTabsCRLF(string $chaine): string +{ + $cibles = [' ', "\t", "\n", "\r"]; // doubles quotes !! + return(str_replace($cibles, '', $chaine)); +} + +// 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/URL.php b/src/URL.php new file mode 100644 index 0000000..689332f --- /dev/null +++ b/src/URL.php @@ -0,0 +1,88 @@ +params = $gets; + if($anchor != ''){ + $this->setAnchor($anchor); + } + } + + //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/controller/Captcha.php b/src/controller/Captcha.php deleted file mode 100644 index da61a53..0000000 --- a/src/controller/Captcha.php +++ /dev/null @@ -1,52 +0,0 @@ -a = rand(2, 9); - $this->b = rand(2, 9); - $this->solution = $this->a * $this->b; - } - - public function getA(): string - { - return $this->toLettersFrench($this->a); - } - public function getB(): string - { - return $this->toLettersFrench($this->b); - } - public function getSolution(): int - { - return $this->solution; - } - - 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 - }; - } - 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/controller/Security.php b/src/controller/Security.php deleted file mode 100644 index b882d42..0000000 --- a/src/controller/Security.php +++ /dev/null @@ -1,117 +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 = ''; - - // ATTENTION, n'applique pas htmlspecialchars() !! - public static function secureString(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 - } -} - -// erreurs à la création des mots de passe -function removeSpacesTabsCRLF(string $chaine): string -{ - $cibles = [' ', "\t", "\n", "\r"]; // doubles quotes !! - return(str_replace($cibles, '', $chaine)); -} - -// 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/controller/URL.php b/src/controller/URL.php deleted file mode 100644 index 3ebc488..0000000 --- a/src/controller/URL.php +++ /dev/null @@ -1,88 +0,0 @@ -params = $gets; - if($anchor != ''){ - $this->setAnchor($anchor); - } - } - - //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/controller/installation.php b/src/controller/installation.php deleted file mode 100644 index d9ea44b..0000000 --- a/src/controller/installation.php +++ /dev/null @@ -1,178 +0,0 @@ -l'extension " . $extension . ' 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; - } - 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; - } -} - -// inutilisée pour l'instant -function installation(): void -{ - /* -- droits des fichiers et dossiers -- */ - $droits_dossiers = 0700; - $droits_fichiers = 0600; - - // accès interdit en HTTP - if(!file_exists('../config/.htaccess')){ - $contenu = <<< HTACCESS - - Order Allow,Deny - Deny from all - -HTACCESS; - - $fichier = fopen('../config/.htaccess', 'w'); - fputs($fichier, $contenu); - fclose($fichier); - chmod('../config/.htaccess', $droits_fichiers); - //echo("danger
pas de .htaccess dans config
prévenez le responsable du site"); - //die; - } - - // accès limité en local (600) pour config.ini - if(substr(sprintf('%o', fileperms('../config/config.ini')), -4) != 600){ - chmod('../config/config.ini', $droits_fichiers); - } - - // création de data et sous-dossiers - if(!file_exists('../data')){ - mkdir('../data/'); - chmod('../data/', $droits_dossiers); - } - if(!touch('../data')){ - echo("dossier data non autorisé en écriture"); - die; - } - $sous_dossiers = array('images', 'images-mini', 'videos'); - foreach ($sous_dossiers as $sous_dossier){ - if(!file_exists('../data/' . $sous_dossier)){ - mkdir('../data/' . $sous_dossier); - chmod('../data/' . $sous_dossier, $droits_dossiers); - } - if(!touch('../data/' . $sous_dossier)){ - echo("dossier data non autorisé en écriture"); - die; - } - } -} - -// création d'un site minimal avec une page d'accueil à la toute 1ère visite du site -// fonctiona appelée après la première requête envoyée en BDD, -// en l'occurence dans Menu parce que count($bulk_data) === 0 -function makeStartPage(EntityManager $entityManager){ - /* -- table page -- */ - // paramètres: name_page, end_of_path, reachable, in_menu, hidden, position, parent - $accueil = new Page('Accueil', 'accueil', true, true, false, 1, NULL); - $article = new Page('Article', 'article', true, false, false, NULL, NULL); - $connection = new Page('Connexion', 'connexion', true, false, false, NULL, NULL); - $menu_paths = new Page("Menu et chemins", 'menu_chemins', true, false, false, NULL, NULL); - //$edit_page = new Page("Modification d'une page", 'modif_page', true, false, false, NULL, NULL); // pas de page "Modification de la page" - $new_page = new Page('Nouvelle page', 'nouvelle_page', true, false, false, NULL, NULL); - - /* -- table node -- */ - // paramètres: name_node, article_timestamp, attributes, position, parent, page, article - $head_accueil = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'foot'], 'js_array' => ['main']], 1, NULL, $accueil, NULL); - $head_article = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'foot'], 'js_array' => ['main']], 1, NULL, $article, NULL); - $header = new Node('header', NULL, [], 2, NULL, NULL, NULL); - $nav = new Node('nav', NULL, [], 1, $header, NULL, NULL); - $main = new Node('main', NULL, [], 3, NULL, NULL, NULL); - $footer = new Node('footer', NULL, [], 4, NULL, NULL, NULL); - $breadcrumb = new Node('breadcrumb', NULL, [], 2, $header, NULL, NULL); - $head_login = new Node('head', NULL, ["stop" => true, 'css_array' => ['body', 'head', 'nav'], 'js_array' => ['main']], 1, NULL, $connection, NULL); - $login = new Node('login', NULL, [], 1, $main, $connection, NULL); - $head_edit_menu = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'menu', 'foot'], 'js_array' => ['main', 'menu']], 1, NULL, $menu_paths, NULL); - $bloc_edit_menu = new Node('menu', NULL, [], 1, $main, $menu_paths, NULL); - $head_new_page = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'new_page', 'foot'], 'js_array' => ['main', 'new_page']], 1, NULL, $new_page, NULL); - $bloc_new_page = new Node('new_page', NULL, [], 1, $main, $new_page, NULL); - - /* -- table image -- */ - // paramètres: file_name, file_path, file_path_mini, mime_type, alt - $favicon = new Image("favicon48x48.png", NULL, "assets/favicon48x48.png", "image/png", "favicon"); - $facebook = new Image("facebook.svg", NULL, "assets/facebook.svg", "image/svg+xml", "facebook"); - $instagram = new Image("instagram.svg", NULL, "assets/instagram.svg", "image/svg+xml", "instagram"); - $linkedin = new Image("linkedin.svg", NULL, "assets/linkedin.svg", "image/svg+xml", "linkedin"); - $github = new Image("github.svg", NULL, "assets/github.svg", "image/svg+xml", "github"); - - /* -- table node_data -- */ - // paramètres: data, node, images - $head_accueil_data = new NodeData(["description" => "page d'accueil"], $head_accueil, new ArrayCollection([$favicon])); - $head_login_data = new NodeData(["description" => "Connexion"], $head_login, new ArrayCollection([$favicon])); - $head_article_data = new NodeData(["description" => ""], $head_article, new ArrayCollection([$favicon])); - $head_edit_menu_data = new NodeData(["description" => "Menu et chemins"], $head_edit_menu, new ArrayCollection([$favicon])); - $head_new_page_data = new NodeData(["description" => "Nouvelle page"], $head_new_page, new ArrayCollection([$favicon])); - $header_data = new NodeData(["title" => "Titre", "description" => "Sous-titre", "header_logo" => "assets/logo-nb-et-ffn.png", "header_background" => "assets/fond-piscine.jpg", - "social" => ["facebook" => "https://www.facebook.com", "instagram" => "https://www.instagram.com", "linkedin" => "https://www.linkedin.com"]], - $header, new ArrayCollection([$facebook, $instagram, $linkedin, $github])); - $footer_data = new NodeData(["contact_nom" => "Nom", "adresse" => "adresse", "e_mail" => "e-mail", "footer_logo" => "assets/logo-nb-et-ffn.png"], $footer); - - /* -- table page -- */ - $entityManager->persist($accueil); - $entityManager->persist($article); - $entityManager->persist($connection); - $entityManager->persist($menu_paths); - //$entityManager->persist($edit_page); // pas de page "Modification de la page" - $entityManager->persist($new_page); - - /* -- table node -- */ - $entityManager->persist($head_accueil); - $entityManager->persist($header); - $entityManager->persist($nav); - $entityManager->persist($main); - $entityManager->persist($footer); - $entityManager->persist($breadcrumb); - $entityManager->persist($head_login); - $entityManager->persist($login); - $entityManager->persist($head_article); - $entityManager->persist($head_edit_menu); - $entityManager->persist($bloc_edit_menu); - $entityManager->persist($head_new_page); - $entityManager->persist($bloc_new_page); - - /* -- table image -- */ - $entityManager->persist($favicon); - $entityManager->persist($facebook); - $entityManager->persist($instagram); - $entityManager->persist($linkedin); - $entityManager->persist($github); - - /* -- table node_data -- */ - $entityManager->persist($head_accueil_data); - $entityManager->persist($header_data); - $entityManager->persist($footer_data); - $entityManager->persist($head_login_data); - $entityManager->persist($head_article_data); - $entityManager->persist($head_edit_menu_data); - $entityManager->persist($head_new_page_data); - - $entityManager->flush(); - header('Location: ' . new URL); - die; -} \ No newline at end of file diff --git a/src/controller/request_router.php b/src/controller/request_router.php deleted file mode 100644 index 157bc80..0000000 --- a/src/controller/request_router.php +++ /dev/null @@ -1,256 +0,0 @@ -: position = nombre d'éléments de la fraterie + 1, l'élément précédent devient le parent - if($_GET['menu_edit'] === 'move_one_level_down' && isset($json['id'])){ - MenuAndPathsController::MoveOneLevelDown($entityManager, $json); - } - - if($_GET['menu_edit'] === 'switch_positions' && isset($json['id1']) && isset($json['id2'])){ - MenuAndPathsController::switchPositions($entityManager, $json); - } - - if($_GET['menu_edit'] === 'displayInMenu' && isset($json['id']) && isset($json['checked'])){ - MenuAndPathsController::displayInMenu($entityManager, $json); - } - } - - /* -- mode Modification d'une page -- */ - // partie "page" - elseif(isset($_GET['page_edit'])) - { - // titre de la page - if($_GET['page_edit'] === 'page_title'){ - PageManagementController::setPageTitle($entityManager, $json); - } - // description dans les métadonnées - elseif($_GET['page_edit'] === 'page_description'){ - PageManagementController::setPageDescription($entityManager, $json); - } - } - - // partie "blocs" - elseif(isset($_GET['bloc_edit'])) - { - // renommage d'un bloc - if($_GET['bloc_edit'] === 'rename_page_bloc') - { - PageManagementController::renameBloc($entityManager, $json); - } - // inversion des positions de deux blocs - elseif($_GET['bloc_edit'] === 'switch_blocs_positions') - { - PageManagementController::SwitchBlocsPositions($entityManager, $json); - } - } - - /* -- upload d'image dans tinymce par copier-coller -- */ - // collage de HTML contenant une ou plusieurs balises - if(isset($_GET['action']) && $_GET['action'] == 'upload_image_html'){ - ImageUploadController::uploadImageHtml(); - } - // collage d'une image (code base64 dans le presse-papier) non encapsulée dans du HTML - elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_base64'){ - ImageUploadController::uploadImageBase64(); - } - - /* -- requêtes spécifiques au calendrier -- */ - if($_GET['action'] === 'new_event'){ - CalendarController::newEvent($json, $entityManager); - } - elseif($_GET['action'] === 'update_event'){ - CalendarController::updateEvent($json, $entityManager); - } - elseif($_GET['action'] === 'remove_event'){ - CalendarController::removeEvent($json, $entityManager); - } - else{ - echo json_encode(['success' => false]); - } - die; - } - - // upload d'image dans tinymce avec le plugin (bouton "insérer une image" de l'éditeur) - elseif(strpos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') !== false && isset($_GET['action']) && $_GET['action'] === 'upload_image') - { - ImageUploadController::imageUploadTinyMce(); - } - // requêtes XMLHttpRequest - elseif(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') - { - //echo "requête XMLHttpRequest reçue par le serveur"; - echo json_encode(['success' => false]); // ça marche mais ça marche pas... - die; - } - - /* -- envoi d'un formulaire HTML -- */ - elseif($_SERVER['CONTENT_TYPE'] === 'application/x-www-form-urlencoded') - { - /* -- nouvelle page -- */ - if(isset($_POST['page_name']) && $_POST['page_name'] !== null - && isset($_POST['page_name_path']) && $_POST['page_name_path'] !== null - && isset($_POST['page_location']) && $_POST['page_location'] !== null - && isset($_POST['page_description']) && $_POST['page_description'] !== null - && isset($_POST['new_page_hidden']) && $_POST['new_page_hidden'] === '') - { - PageManagementController::newPage($entityManager); - } - - /* -- suppression d'une page -- */ - elseif(isset($_POST['page_id']) && $_POST['page_id'] !== null - && isset($_POST['submit_hidden']) && $_POST['submit_hidden'] === '') - { - PageManagementController::deletePage($entityManager); - } - - /* -- mode Modification d'une page -- */ - - // modification du chemins en snake_case - elseif(isset($_POST['page_menu_path']) && $_POST['page_menu_path'] !== null - && isset($_POST['page_id']) && $_POST['page_id'] !== null - && isset($_POST['page_name_path_hidden']) && $_POST['page_name_path_hidden'] === '') - { - PageManagementController::updatePageMenuPath($entityManager); - } - // ajout d'un bloc dans une page - elseif(isset($_POST['bloc_title']) && $_POST['bloc_title'] !== null - && isset($_POST['bloc_select']) && $_POST['bloc_select'] !== null - && isset($_POST['bloc_title_hidden']) && $_POST['bloc_title_hidden'] === '') // contrôle anti-robot avec input hidden - { - PageManagementController::addBloc($entityManager); - } - // suppression d'un bloc de page - elseif(isset($_POST['delete_bloc_id']) && $_POST['delete_bloc_id'] !== null - && isset($_POST['delete_bloc_hidden']) && $_POST['delete_bloc_hidden'] === '') // contrôle anti-robot avec input hidden - { - PageManagementController::deleteBloc($entityManager); - } - - - /* -- page Menu et chemins -- */ - - // création d'une entrée de menu avec une URL - elseif(isset($_POST["label_input"]) && isset($_POST["url_input"]) && isset($_POST["location"])){ - MenuAndPathsController::newUrlMenuEntry($entityManager); - } - // suppression d'une entrée de menu avec une URL - elseif(isset($_POST['delete']) && isset($_POST['x']) && isset($_POST['y'])){ // 2 params x et y sont là parce qu'on a cliqué sur une image - MenuAndPathsController::deleteUrlMenuEntry($entityManager); - } - - // redirection page d'accueil - else{ - header("Location: " . new URL(['error' => 'paramètres inconnus'])); - die; - } - } - } -} - -// cas particulier d'un GET ajax non-admin par fullcalendar -elseif($_SERVER['REQUEST_METHOD'] === 'GET'){ - /* -- non-admin -- */ - // chargement des évènements à la création du calendrier - // et au changement de dates affichées (boutons flèches mais pas changement de vue) - if($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['action']) && $_GET['action'] === 'get_events' - && isset($_GET['start']) && isset($_GET['end']) && empty($_POST)) - { - CalendarController::getData($entityManager); - } - - if($_SESSION['admin'] === true){ - // ... - } -} \ No newline at end of file diff --git a/src/installation.php b/src/installation.php new file mode 100644 index 0000000..295c583 --- /dev/null +++ b/src/installation.php @@ -0,0 +1,178 @@ +l'extension " . $extension . ' 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; + } + 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; + } +} + +// inutilisée pour l'instant +function installation(): void +{ + /* -- droits des fichiers et dossiers -- */ + $droits_dossiers = 0700; + $droits_fichiers = 0600; + + // accès interdit en HTTP + if(!file_exists('../config/.htaccess')){ + $contenu = <<< HTACCESS + + Order Allow,Deny + Deny from all + +HTACCESS; + + $fichier = fopen('../config/.htaccess', 'w'); + fputs($fichier, $contenu); + fclose($fichier); + chmod('../config/.htaccess', $droits_fichiers); + //echo("danger
pas de .htaccess dans config
prévenez le responsable du site"); + //die; + } + + // accès limité en local (600) pour config.ini + if(substr(sprintf('%o', fileperms('../config/config.ini')), -4) != 600){ + chmod('../config/config.ini', $droits_fichiers); + } + + // création de data et sous-dossiers + if(!file_exists('../data')){ + mkdir('../data/'); + chmod('../data/', $droits_dossiers); + } + if(!touch('../data')){ + echo("dossier data non autorisé en écriture"); + die; + } + $sous_dossiers = array('images', 'images-mini', 'videos'); + foreach ($sous_dossiers as $sous_dossier){ + if(!file_exists('../data/' . $sous_dossier)){ + mkdir('../data/' . $sous_dossier); + chmod('../data/' . $sous_dossier, $droits_dossiers); + } + if(!touch('../data/' . $sous_dossier)){ + echo("dossier data non autorisé en écriture"); + die; + } + } +} + +// création d'un site minimal avec une page d'accueil à la toute 1ère visite du site +// fonctiona appelée après la première requête envoyée en BDD, +// en l'occurence dans Menu parce que count($bulk_data) === 0 +function makeStartPage(EntityManager $entityManager){ + /* -- table page -- */ + // paramètres: name_page, end_of_path, reachable, in_menu, hidden, position, parent + $accueil = new Page('Accueil', 'accueil', true, true, false, 1, NULL); + $article = new Page('Article', 'article', true, false, false, NULL, NULL); + $connection = new Page('Connexion', 'connexion', true, false, false, NULL, NULL); + $menu_paths = new Page("Menu et chemins", 'menu_chemins', true, false, false, NULL, NULL); + //$edit_page = new Page("Modification d'une page", 'modif_page', true, false, false, NULL, NULL); // pas de page "Modification de la page" + $new_page = new Page('Nouvelle page', 'nouvelle_page', true, false, false, NULL, NULL); + + /* -- table node -- */ + // paramètres: name_node, article_timestamp, attributes, position, parent, page, article + $head_accueil = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'foot'], 'js_array' => ['main']], 1, NULL, $accueil, NULL); + $head_article = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'foot'], 'js_array' => ['main']], 1, NULL, $article, NULL); + $header = new Node('header', NULL, [], 2, NULL, NULL, NULL); + $nav = new Node('nav', NULL, [], 1, $header, NULL, NULL); + $main = new Node('main', NULL, [], 3, NULL, NULL, NULL); + $footer = new Node('footer', NULL, [], 4, NULL, NULL, NULL); + $breadcrumb = new Node('breadcrumb', NULL, [], 2, $header, NULL, NULL); + $head_login = new Node('head', NULL, ["stop" => true, 'css_array' => ['body', 'head', 'nav'], 'js_array' => ['main']], 1, NULL, $connection, NULL); + $login = new Node('login', NULL, [], 1, $main, $connection, NULL); + $head_edit_menu = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'menu', 'foot'], 'js_array' => ['main', 'menu']], 1, NULL, $menu_paths, NULL); + $bloc_edit_menu = new Node('menu', NULL, [], 1, $main, $menu_paths, NULL); + $head_new_page = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'new_page', 'foot'], 'js_array' => ['main', 'new_page']], 1, NULL, $new_page, NULL); + $bloc_new_page = new Node('new_page', NULL, [], 1, $main, $new_page, NULL); + + /* -- table image -- */ + // paramètres: file_name, file_path, file_path_mini, mime_type, alt + $favicon = new Image("favicon48x48.png", NULL, "assets/favicon48x48.png", "image/png", "favicon"); + $facebook = new Image("facebook.svg", NULL, "assets/facebook.svg", "image/svg+xml", "facebook"); + $instagram = new Image("instagram.svg", NULL, "assets/instagram.svg", "image/svg+xml", "instagram"); + $linkedin = new Image("linkedin.svg", NULL, "assets/linkedin.svg", "image/svg+xml", "linkedin"); + $github = new Image("github.svg", NULL, "assets/github.svg", "image/svg+xml", "github"); + + /* -- table node_data -- */ + // paramètres: data, node, images + $head_accueil_data = new NodeData(["description" => "page d'accueil"], $head_accueil, new ArrayCollection([$favicon])); + $head_login_data = new NodeData(["description" => "Connexion"], $head_login, new ArrayCollection([$favicon])); + $head_article_data = new NodeData(["description" => ""], $head_article, new ArrayCollection([$favicon])); + $head_edit_menu_data = new NodeData(["description" => "Menu et chemins"], $head_edit_menu, new ArrayCollection([$favicon])); + $head_new_page_data = new NodeData(["description" => "Nouvelle page"], $head_new_page, new ArrayCollection([$favicon])); + $header_data = new NodeData(["title" => "Titre", "description" => "Sous-titre", "header_logo" => "assets/logo-nb-et-ffn.png", "header_background" => "assets/fond-piscine.jpg", + "social" => ["facebook" => "https://www.facebook.com", "instagram" => "https://www.instagram.com", "linkedin" => "https://www.linkedin.com"]], + $header, new ArrayCollection([$facebook, $instagram, $linkedin, $github])); + $footer_data = new NodeData(["contact_nom" => "Nom", "adresse" => "adresse", "e_mail" => "e-mail", "footer_logo" => "assets/logo-nb-et-ffn.png"], $footer); + + /* -- table page -- */ + $entityManager->persist($accueil); + $entityManager->persist($article); + $entityManager->persist($connection); + $entityManager->persist($menu_paths); + //$entityManager->persist($edit_page); // pas de page "Modification de la page" + $entityManager->persist($new_page); + + /* -- table node -- */ + $entityManager->persist($head_accueil); + $entityManager->persist($header); + $entityManager->persist($nav); + $entityManager->persist($main); + $entityManager->persist($footer); + $entityManager->persist($breadcrumb); + $entityManager->persist($head_login); + $entityManager->persist($login); + $entityManager->persist($head_article); + $entityManager->persist($head_edit_menu); + $entityManager->persist($bloc_edit_menu); + $entityManager->persist($head_new_page); + $entityManager->persist($bloc_new_page); + + /* -- table image -- */ + $entityManager->persist($favicon); + $entityManager->persist($facebook); + $entityManager->persist($instagram); + $entityManager->persist($linkedin); + $entityManager->persist($github); + + /* -- table node_data -- */ + $entityManager->persist($head_accueil_data); + $entityManager->persist($header_data); + $entityManager->persist($footer_data); + $entityManager->persist($head_login_data); + $entityManager->persist($head_article_data); + $entityManager->persist($head_edit_menu_data); + $entityManager->persist($head_new_page_data); + + $entityManager->flush(); + header('Location: ' . new URL); + die; +} \ No newline at end of file diff --git a/src/request_router.php b/src/request_router.php new file mode 100644 index 0000000..0b31755 --- /dev/null +++ b/src/request_router.php @@ -0,0 +1,256 @@ +: position = nombre d'éléments de la fraterie + 1, l'élément précédent devient le parent + if($_GET['menu_edit'] === 'move_one_level_down' && isset($json['id'])){ + MenuAndPathsController::MoveOneLevelDown($entityManager, $json); + } + + if($_GET['menu_edit'] === 'switch_positions' && isset($json['id1']) && isset($json['id2'])){ + MenuAndPathsController::switchPositions($entityManager, $json); + } + + if($_GET['menu_edit'] === 'displayInMenu' && isset($json['id']) && isset($json['checked'])){ + MenuAndPathsController::displayInMenu($entityManager, $json); + } + } + + /* -- mode Modification d'une page -- */ + // partie "page" + elseif(isset($_GET['page_edit'])) + { + // titre de la page + if($_GET['page_edit'] === 'page_title'){ + PageManagementController::setPageTitle($entityManager, $json); + } + // description dans les métadonnées + elseif($_GET['page_edit'] === 'page_description'){ + PageManagementController::setPageDescription($entityManager, $json); + } + } + + // partie "blocs" + elseif(isset($_GET['bloc_edit'])) + { + // renommage d'un bloc + if($_GET['bloc_edit'] === 'rename_page_bloc') + { + PageManagementController::renameBloc($entityManager, $json); + } + // inversion des positions de deux blocs + elseif($_GET['bloc_edit'] === 'switch_blocs_positions') + { + PageManagementController::SwitchBlocsPositions($entityManager, $json); + } + } + + /* -- upload d'image dans tinymce par copier-coller -- */ + // collage de HTML contenant une ou plusieurs balises + if(isset($_GET['action']) && $_GET['action'] == 'upload_image_html'){ + ImageUploadController::uploadImageHtml(); + } + // collage d'une image (code base64 dans le presse-papier) non encapsulée dans du HTML + elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_base64'){ + ImageUploadController::uploadImageBase64(); + } + + /* -- requêtes spécifiques au calendrier -- */ + if($_GET['action'] === 'new_event'){ + CalendarController::newEvent($json, $entityManager); + } + elseif($_GET['action'] === 'update_event'){ + CalendarController::updateEvent($json, $entityManager); + } + elseif($_GET['action'] === 'remove_event'){ + CalendarController::removeEvent($json, $entityManager); + } + else{ + echo json_encode(['success' => false]); + } + die; + } + + // upload d'image dans tinymce avec le plugin (bouton "insérer une image" de l'éditeur) + elseif(strpos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') !== false && isset($_GET['action']) && $_GET['action'] === 'upload_image') + { + ImageUploadController::imageUploadTinyMce(); + } + // requêtes XMLHttpRequest + elseif(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') + { + //echo "requête XMLHttpRequest reçue par le serveur"; + echo json_encode(['success' => false]); // ça marche mais ça marche pas... + die; + } + + /* -- envoi d'un formulaire HTML -- */ + elseif($_SERVER['CONTENT_TYPE'] === 'application/x-www-form-urlencoded') + { + /* -- nouvelle page -- */ + if(isset($_POST['page_name']) && $_POST['page_name'] !== null + && isset($_POST['page_name_path']) && $_POST['page_name_path'] !== null + && isset($_POST['page_location']) && $_POST['page_location'] !== null + && isset($_POST['page_description']) && $_POST['page_description'] !== null + && isset($_POST['new_page_hidden']) && $_POST['new_page_hidden'] === '') + { + PageManagementController::newPage($entityManager); + } + + /* -- suppression d'une page -- */ + elseif(isset($_POST['page_id']) && $_POST['page_id'] !== null + && isset($_POST['submit_hidden']) && $_POST['submit_hidden'] === '') + { + PageManagementController::deletePage($entityManager); + } + + /* -- mode Modification d'une page -- */ + + // modification du chemins en snake_case + elseif(isset($_POST['page_menu_path']) && $_POST['page_menu_path'] !== null + && isset($_POST['page_id']) && $_POST['page_id'] !== null + && isset($_POST['page_name_path_hidden']) && $_POST['page_name_path_hidden'] === '') + { + PageManagementController::updatePageMenuPath($entityManager); + } + // ajout d'un bloc dans une page + elseif(isset($_POST['bloc_title']) && $_POST['bloc_title'] !== null + && isset($_POST['bloc_select']) && $_POST['bloc_select'] !== null + && isset($_POST['bloc_title_hidden']) && $_POST['bloc_title_hidden'] === '') // contrôle anti-robot avec input hidden + { + PageManagementController::addBloc($entityManager); + } + // suppression d'un bloc de page + elseif(isset($_POST['delete_bloc_id']) && $_POST['delete_bloc_id'] !== null + && isset($_POST['delete_bloc_hidden']) && $_POST['delete_bloc_hidden'] === '') // contrôle anti-robot avec input hidden + { + PageManagementController::deleteBloc($entityManager); + } + + + /* -- page Menu et chemins -- */ + + // création d'une entrée de menu avec une URL + elseif(isset($_POST["label_input"]) && isset($_POST["url_input"]) && isset($_POST["location"])){ + MenuAndPathsController::newUrlMenuEntry($entityManager); + } + // suppression d'une entrée de menu avec une URL + elseif(isset($_POST['delete']) && isset($_POST['x']) && isset($_POST['y'])){ // 2 params x et y sont là parce qu'on a cliqué sur une image + MenuAndPathsController::deleteUrlMenuEntry($entityManager); + } + + // redirection page d'accueil + else{ + header("Location: " . new URL(['error' => 'paramètres inconnus'])); + die; + } + } + } +} + +// cas particulier d'un GET ajax non-admin par fullcalendar +elseif($_SERVER['REQUEST_METHOD'] === 'GET'){ + /* -- non-admin -- */ + // chargement des évènements à la création du calendrier + // et au changement de dates affichées (boutons flèches mais pas changement de vue) + if($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['action']) && $_GET['action'] === 'get_events' + && isset($_GET['start']) && isset($_GET['end']) && empty($_POST)) + { + CalendarController::getData($entityManager); + } + + if($_SESSION['admin'] === true){ + // ... + } +} \ No newline at end of file -- cgit v1.2.3