From 87798e5554eb0330cd2de255e5034f0472d410a4 Mon Sep 17 00:00:00 2001 From: polo Date: Tue, 20 Apr 2021 21:46:33 +0200 Subject: mot de passe --- controller/admin.php | 76 ++++++++++++++++ controller/backup.php | 80 +++++++++++++++++ controller/ckeditor.php | 92 +++++++++++++++++++ controller/installation.php | 75 ++++++++++++++++ controller/media.php | 212 ++++++++++++++++++++++++++++++++++++++++++++ controller/visitor.php | 110 +++++++++++++++++++++++ 6 files changed, 645 insertions(+) create mode 100644 controller/admin.php create mode 100644 controller/backup.php create mode 100644 controller/ckeditor.php create mode 100644 controller/installation.php create mode 100644 controller/media.php create mode 100644 controller/visitor.php (limited to 'controller') diff --git a/controller/admin.php b/controller/admin.php new file mode 100644 index 0000000..2b3583f --- /dev/null +++ b/controller/admin.php @@ -0,0 +1,76 @@ + $nombreDarticles || $numArticle < 0) // erreur nombre trop grand (bug?) + { + header('Location: index.php?page=melaine'); + } + elseif($numArticle == 0) // nouvel article + { + $texte = ''; + $numArticle = $nombreDarticles + 1; + } + else // modification d'un article + { + $texte = $articles[$numArticle - 1]; + } + + // traitement du contenu pré-existant + $initial = preparationCKeditor($page_actuelle, $numArticle, $texte); + + // variable $editeurHTML, $initial est inséré dedans + require('view/template-ckeditor.php'); + + // création des morceaux en HTML avant assemblage, c'est-à-dire; + // les variables $css, $js, $header et $content + require('view/melaine.php'); + // le tableau de données ($articles) et l'éditeur ($editeurHTML) + // font partie de $content + + // assemblage de la page! + require('view/template.php'); +} + +function changerMotDePasse($secret, $from) +{ + // vérification supplémentaire + if($_SESSION['admin'] !== 1) + { + $_SESSION['admin'] = 0; + header('Location: index.php?page=' . $_GET['from']); + } + + $title = "nouveau mot de passe"; + // Ajouter une sécurité par cpatcha avec un "input" supplémentaire + // Et créer une variable de session pour la réponse au CAPTCHA + + $title = "nouveau mot de passe"; + $subHeading = "Veuillez saisir votre actuel mot de passe suivi du nouveau."; + + // cette page utilise la même vue que la fonction connexion() dans controller/visiteur.php + require('view/connexion.php'); + + echo($header); + + // traitements: vérification ancien mot de passe et choix du nouveau + + echo($footer); +} diff --git a/controller/backup.php b/controller/backup.php new file mode 100644 index 0000000..bc84a86 --- /dev/null +++ b/controller/backup.php @@ -0,0 +1,80 @@ + + Veuillez prévenir l\'administrateur.
+ Vous pouvez aussi récupérer manuellement les fichiers en vous connectant au serveur avec un client FTP, il suffit de récupérer tout le dossier "data".

+ Retour au site'); + die(); + } + + // création du fichier zip vide + // j'ai utilisé l'option ZipArchive::OVERWRITE, + // ZipArchive::FL_OVERWRITE n'apparaît qu'avec PHP 8 + if ($zip->open($chemin . $nomFichier, ZipArchive::CREATE | ZipArchive::OVERWRITE)!==TRUE) { + exit("Impossible d'ouvrir le fichier " . $chemin . $nomFichier . ".\n"); + } + + // ajout des fichiers + // chemin complet = data/"pages"/"html ou images"/"tous les fichiers" + $zip->addGlob($chemin . '*/*/*', 0, array('')); + $zip->close(); + + // pour pouvoir manipuler le fichier depuis filezilla ou ssh + chmod($chemin . $nomFichier, 0666); // écriture 4 chiffres + +?> + + + extraction des données + + + +
+ Toutes les données du sites ont été rassemblées dans un gros fichier que vous pouvez garder par exemple sur votre ordinateur.
+ Vous pourrez l'utiliser plus tard pour restaurer le site dans l'état où il se trouve aujourd'hui. Ceci est utile dans le cas d'un changement d'hébergement ou dans le cas d'un problème affectant le serveur.
+ Ce fichier se nomme sauvegarde_site_melaine.zip.

+ Cliquez ici pour télécharger

+ Retour au site +
+ + + + + Restauration des données avec un backup + + + +
+ Restauration des données à partir d'une sauvegarde.

+ Vous devez avoir créé un fichier nommé sauvegarde_site_melaine.zip
+ en cliquant sur Extraire les données.

+ +
+
+ +

+ Retour au site +
+
+ + 0) + { + // supprimer espaces, tabulations et sauts de ligne en début et fin de chaine + $texte = trim($texte); + + // supprimer les sauts de ligne + $sautsDeLigne = array("\n", "\r", "\r\n"); + $texte = str_replace($sautsDeLigne, '', $texte); + + // échapper tous les ', ", \ et caractère NULL + $texte = addslashes($texte); + } + else + { + $texte = ''; // nouveau contenu + } + + return($texte); +} + +// réception du HTML créé par l'éditeur +function submitCKeditor($page, $article, $contenuPOST) +{ + // déjà fait mais on ne sait jamais + if(!isset($_SESSION['admin']) || $_SESSION['admin'] != 1) + { + header('Location: index.php?page=' . $page . '&erreur=connexion'); + } + else + { + // ne pas continuer si la variable est vide (javascript mal supporté ou utilisation de IE, bug?, erreur de l'utilisateur) + // on évitera de perdre un article existant par erreur !! + if($contenuPOST == '') + { + header('Location: index.php?page=' . $page . '&erreur=contenu_vide'); + } + else + { + $contenu = $_POST["contenu"]; + + // récupérer les liens multimedia + //require("media.php"); + //$contenu = mediaSubmit($contenu); + + // sécurité faille XSS + $configHtmLawed = array( + 'safe'=>1, // protection contre les élements et attributs dangereux + 'elements'=>'h2, h3, h4, p, br, span, i, strong, u, mark, blockquote, li, ol, ul, a, figure, hr, img, figcaption, table, tbody, tr, td', // paramètre optionnel: les balises non indiquées sont supprimées + // paramètre optionnel: les balises non indiquées sont supprimées + 'deny_attribute'=>'id', // gêner le JS hostile + // on garde 'class' et 'style' utilisés par l'ckediteur + ); + $specHtmLawed = ''; // optionnel: faire qu'un certain élément puisse n'avoir que certains attributs + $contenu = htmLawed($contenu, $configHtmLawed, $specHtmLawed); + + // supprimer espaces, tabulations et sauts de ligne en début et fin de chaine + $contenu = trim($contenu); + } + } + + // lien sans http:// + // un clic sur un lien dans l'éditeur affiche une infobulle montrant l'adresse cible du lien si celle-ci a déjà été précisée + // il est possible de cliquer sur ce lien, ce qui ouvre un onglet avec le site demandé + // toutefois si cette adresse est de type "domaine.fr" (sans http:// devant), le navigateur ne va pas rechercher un site mais un fichier comme si mon adresse était de type file:///fichier + // tomber ainsi sur une page d'erreur est déroutant: + // "ai-je perdu le texte que j'étais en train de taper?"" + // solution 1 (mauvaise): activer la redirection en cas d'erreur 404 dans le .htaccess + // solution 2 (façon pop-up): fermer ce nouvel onglet avec echo ''; + // pour faire passer par le .htaccess l'info comme quoi la page précédente comportait un éditeur ouvert... + + // enregistrement + require('model/melaine-write.php'); + nouvelArticle($page, $article, $contenu); + + // debuggage + //exit(); +} \ No newline at end of file diff --git a/controller/installation.php b/controller/installation.php new file mode 100644 index 0000000..f7d42fc --- /dev/null +++ b/controller/installation.php @@ -0,0 +1,75 @@ +'); + //echo('server name: ' . $_SERVER['SERVER_NAME'] . '
'); + // echo('dirname: ' . dirname(__FILE__) . '
'); + // echo('file: ' . __FILE__ . '
'); + // echo('dir: ' . __DIR__. '
'); + + // créer le .htaccess + //$lien_htaccess = $_SERVER['SERVER_NAME'] . "/.htaccess"; + //$nomDuSite = "melaine"; + if(!file_exists(".htaccess")) + { + echo('

Le .htaccess semble absent ce qui rend le site vulnérable aux attaques, veuillez contacter l\'administrateur.

'); + // $contenu = "# redirection en cas d'erreur 404\nErrorDocument 404 http://" . $_SERVER['SERVER_NAME'] . "/" . $nomDuSite . "/erreur404.php\n# Interdire exploration du répertoire\nOptions All -Indexes"; + // $fichier = fopen('.htaccess', 'w'); + // fputs($fichier, $contenu); + // fclose($fichier); + // chmod('.htaccess', 0666); // mettre 0644 en production + } + + // droits en lecture et écriture dans le cas d'une migration + // tester si le site est "vide" et prévoir un formulaire permettant d'upload le fichier .zip + // contenant toutes les données qu'il est possible de créer depuis le mode admin + // cette méthode a deux intérêts: + // - facilité pour l'utilisateur + // - toutes les données sont la "possession" du serveur apache, + // on prévient ainsi tous les futurs problèmes de droits + + // dans le cas de l'utilisation d'une base de données, le fichiers zip devrait contenir un "dump" + // (un fichier .sql), à voir si php est capable d'obtenir ou redonner ce fichier à la BDD + + // créer les dossiers (fait également à l'extraction du zip de données) + // attention: ne fonctionne pas sans une manipulation préalable + // - modifier soit-même les droits du dossier data (777), quoique 111 serait pas mal non plus + // - modifier ceux du dossier parent (nom du site) avec son client FTP à la mise en ligne chez l'hébergeur et ensuite remettre tout comme avant + + $listePages = array('melaine'); + foreach ($listePages as $page) + { + if(!file_exists('data/' . $page)) + { + mkdir('data/' . $page); + chmod('data/' . $page, 0777); + } + if(!file_exists('data/' . $page . '/html')) + { + mkdir('data/' . $page . '/html'); + chmod('data/' . $page . '/html', 0777); + } + if(!file_exists('data/' . $page . '/images')) + { + mkdir('data/' . $page . '/images'); + chmod('data/' . $page . '/images', 0777); + } + // if(!file_exists('data/' . $page . '/multimedia')) + // { + // mkdir('data/' . $page . '/multimedia'); + // chmod('data/' . $page . '/multimedia', 0777); + // } + } + // donner les droits 666 aux fichiers à l'intérieur +} diff --git a/controller/media.php b/controller/media.php new file mode 100644 index 0000000..8105b4d --- /dev/null +++ b/controller/media.php @@ -0,0 +1,212 @@ + + + // on vire les balises et ce qu'il y a entre les deux pour ne garder que les liens + // on pourra ensuite traiter ensemble les url avec et sans balises + // (?:) permet de matcher sans capturer, donc de retirer des choses + // pour la variable $tolere, on met: + // \w = [a-zA-Z0-9_], espace ' ', tabulation \t, CR et LF \r\n, + // /, @, %, deux-points ';', virgule ',' et point-virgule ; + // et devant être échappés: . # ( ) ] { } ? ! | et le tiret qui est placé au début ou la fin + $tolere = '\w\s\t\n\r/,;:éèàçù€\#@%\.\(\)[\]\{\}\?\!\|-'; + $pattern = '#(?:[' . $tolere . ']+)#'; + $chaine = preg_replace($pattern, '$2', $chaine); + //echo($chaine . "\n"); + + // on met les balises + $pattern = '#' . $regexListeNonGeree . '#'; + $remplacement = '$0'; + $chaine = preg_replace($pattern, $remplacement, $chaine); + + // c'est quoi cette merde? + // l'API DOM de PHP bien sur!! pour manipuler le "document object model" + // c'est du complètement calqué sur le javascript, avec une syntaxe PHP + // et en plus elle est super vieille, elle ne connaît pas les balises HTML5 ! + // mais une balise c'est une balise donc ça marche quand même + // la doc de PHP est comme toujours plutôt bonne, elle indique les types de données manipulées + // https://www.php.net/manual/fr/book.dom.php + $dom = new DOMDocument; + + // pour ne pas s'arrêter sur les erreurs à cause des "nouvelles" balises + libxml_use_internal_errors(true); + + if($dom->loadHTML($chaine)) // et non load() tout court qui sert à charger du XML + { + //
+ // détecter
+ // puis extraire le lien et supprimer les balises autour + if(preg_match("#
#", $chaine)) + { + $nbFigures = $dom->getElementsByTagName('figure')->length; + + $j = 0; + for($i = 0; $i < $nbFigures ; $i++) // boucle foreach impossible, une
disparaît à chaque tour + { + $balisesFigure = $dom->getElementsByTagName('figure'); + $figure = $balisesFigure->item($j); // l'item 1 devient 0 au deuxième passage, etc + $parent = $figure->parentNode; + + if($figure->getAttribute("class") == 'media') + { + $oembed = $figure->getElementsByTagName('oembed'); // tableau d'une seule case + $div = $figure->getElementsByTagName('div'); // tableau d'une seule case + if($oembed->length > 0) // si taille = 0, c'est que la balise figure contient autre chose qu'une oembed + { + $lien = $oembed->item(0)->getAttribute('url') . ' '; // un espace pour ne pas coller deux adresses + $span = $dom->createElement('span', $lien); + $class = $dom->createAttribute('class'); + $class->value = 'media_embed'; + $span->appendChild($class); + $parent->replaceChild($span, $figure); + } + elseif($div->length > 0) // cette div créée par le ckeditor contient notre lien, plus bas se trouve une iframe + { + $lien = $div->item(0)->getAttribute('data-oembed-url') . ' '; + $span = $dom->createElement('span', $lien); + $class = $dom->createAttribute('class'); + $class->value = 'media_embed'; + $span->appendChild($class); + $parent->replaceChild($span, $figure); + } + else + { + $j++; // la balise
n'est pas supprimée, on incrémente l'indice du tableau pour ne pas boucler à l'infini + } + } + } + } + + // #", $chaine)) + { + $nbIframes = $dom->getElementsByTagName('iframe')->length; + + for($i = 0; $i < $nbIframes ; $i++) + { + $balisesIframe = $dom->getElementsByTagName('iframe'); + $iframe = $balisesIframe->item(0); + $parent = $iframe->parentNode; + + $lien = $iframe->getAttribute('src') . ' '; + $span = $dom->createElement('span', $lien); + $class = $dom->createAttribute('class'); + $class->value = 'media_embed'; + $span->appendChild($class); + $parent->replaceChild($span, $$iframe); + } + } + + // + // pour tout les sites multimedia, remplacer les balises par les liens nus + // en effet, en revenant dans l'éditeur les liens ne déclenchent pas automatiquement "l'embarquement" + // cliquer à la fin d'un lien et passer à la ligne a pour effet de créer des balises + // ça pose un problème parce que la bibliothèque "embera" ne gère pas les liens dans des balises + if(preg_match("#.*#", $chaine)) + { + $nbA = $dom->getElementsByTagName('a')->length; + + $j = 0; + for($i = 0; $i < $nbA ; $i++) + { + $balisesA = $dom->getElementsByTagName('a'); + $a = $balisesA->item($j); + $parent = $a->parentNode; + + $lien = $a->getAttribute('href') . ' '; + + // seules les liens pointant vers une des adresses de la liste sont concernés + if(preg_match("#" . $listeMedia . "#", $lien)) + { + $span = $dom->createElement('span', $lien); + $class = $dom->createAttribute('class'); + $class->value = 'media_embed'; + $span->appendChild($class); + $parent->replaceChild($span, $a); + } + else + { + $j++; // la balise n'est pas supprimée, on incrémente l'indice du tableau pour ne pas boucler à l'infini + } + } + } + + // pour nettoyer tous les warnings qu'on vient de produire et purifier nos fichiers log + libxml_clear_errors(); + // pour au contraire pouvoir les regarder, remplacer la ligne au dessus par celles en dessous + //~ $errors = libxml_get_errors(); + //~ var_dump($errors); + + // mettre à jour le DOM et enlever le DOCTYPE et les balises et + $chaine = $dom->saveHTML($dom); + $pattern = array ('##', '##', '##'); + $remplacement = array ('', '', ''); + $chaine = preg_replace($pattern, $remplacement, $chaine); + } + else + { + echo "Impossible de charger le HTML"; + } + + + + // détecter soundcloud + // normallement il n'y a rien à faire ici mais on sait jamais (une mise à jour du ckeditor?) + if(preg_match("#soundcloud.com#", $chaine)) + {} + + // détecter facebook (éventuellement fb.watch) + // je crois que ça va être compliqué ici + if(preg_match("#facebook.com|fb.watch#", $chaine)) + {} + + return($chaine); // = $contenu +} + + +// embarquement !! +function mediaEmbed($chaine) +{ + //require("../Embera/src/Autoloader.php"); + //$embera = new Embera\Embera(); + //$chaine = $embera->autoEmbed($chaine); + + $pattern = '#(.+)#'; + $remplacement = ''; + $chaine = preg_replace($pattern, $remplacement, $chaine); + + // requête oembed + //~ echo('

'); + //~ print_r($embera->getUrlData([ + //~ 'https://vimeo.com/374131624', + //~ 'https://www.flickr.com/photos/bees/8597283706/in/photostream', + //~ ])); + + return($chaine); // = $contenu +} diff --git a/controller/visitor.php b/controller/visitor.php new file mode 100644 index 0000000..98d7a45 --- /dev/null +++ b/controller/visitor.php @@ -0,0 +1,110 @@ +