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 ++ erreur404.php | 24 + hello-debug.php | 22 + imageAJAX.php | 100 ++ index.php | 201 +++ lib/HtmlFormatter.php | 126 ++ lib/ckeditor5/LICENSE.md | 49 + lib/ckeditor5/README.md | 68 + lib/ckeditor5/build/ckeditor.js | 6 + lib/ckeditor5/build/ckeditor.js.map | 1 + lib/ckeditor5/build/translations/af.js | 1 + lib/ckeditor5/build/translations/ar.js | 1 + lib/ckeditor5/build/translations/ast.js | 1 + lib/ckeditor5/build/translations/az.js | 1 + lib/ckeditor5/build/translations/bg.js | 1 + lib/ckeditor5/build/translations/ca.js | 1 + lib/ckeditor5/build/translations/cs.js | 1 + lib/ckeditor5/build/translations/da.js | 1 + lib/ckeditor5/build/translations/de-ch.js | 1 + lib/ckeditor5/build/translations/de.js | 1 + lib/ckeditor5/build/translations/el.js | 1 + lib/ckeditor5/build/translations/en-au.js | 1 + lib/ckeditor5/build/translations/en-gb.js | 1 + lib/ckeditor5/build/translations/en.js | 1 + lib/ckeditor5/build/translations/eo.js | 1 + lib/ckeditor5/build/translations/es.js | 1 + lib/ckeditor5/build/translations/et.js | 1 + lib/ckeditor5/build/translations/eu.js | 1 + lib/ckeditor5/build/translations/fa.js | 1 + lib/ckeditor5/build/translations/fi.js | 1 + lib/ckeditor5/build/translations/gl.js | 1 + lib/ckeditor5/build/translations/gu.js | 1 + lib/ckeditor5/build/translations/he.js | 1 + lib/ckeditor5/build/translations/hi.js | 1 + lib/ckeditor5/build/translations/hr.js | 1 + lib/ckeditor5/build/translations/hu.js | 1 + lib/ckeditor5/build/translations/id.js | 1 + lib/ckeditor5/build/translations/it.js | 1 + lib/ckeditor5/build/translations/ja.js | 1 + lib/ckeditor5/build/translations/kk.js | 1 + lib/ckeditor5/build/translations/km.js | 1 + lib/ckeditor5/build/translations/kn.js | 1 + lib/ckeditor5/build/translations/ko.js | 1 + lib/ckeditor5/build/translations/ku.js | 1 + lib/ckeditor5/build/translations/lt.js | 1 + lib/ckeditor5/build/translations/lv.js | 1 + lib/ckeditor5/build/translations/nb.js | 1 + lib/ckeditor5/build/translations/ne.js | 1 + lib/ckeditor5/build/translations/nl.js | 1 + lib/ckeditor5/build/translations/no.js | 1 + lib/ckeditor5/build/translations/oc.js | 1 + lib/ckeditor5/build/translations/pl.js | 1 + lib/ckeditor5/build/translations/pt-br.js | 1 + lib/ckeditor5/build/translations/pt.js | 1 + lib/ckeditor5/build/translations/ro.js | 1 + lib/ckeditor5/build/translations/ru.js | 1 + lib/ckeditor5/build/translations/si.js | 1 + lib/ckeditor5/build/translations/sk.js | 1 + lib/ckeditor5/build/translations/sl.js | 1 + lib/ckeditor5/build/translations/sq.js | 1 + lib/ckeditor5/build/translations/sr-latn.js | 1 + lib/ckeditor5/build/translations/sr.js | 1 + lib/ckeditor5/build/translations/sv.js | 1 + lib/ckeditor5/build/translations/th.js | 1 + lib/ckeditor5/build/translations/tk.js | 1 + lib/ckeditor5/build/translations/tr.js | 1 + lib/ckeditor5/build/translations/tt.js | 1 + lib/ckeditor5/build/translations/ug.js | 1 + lib/ckeditor5/build/translations/uk.js | 1 + lib/ckeditor5/build/translations/vi.js | 1 + lib/ckeditor5/build/translations/zh-cn.js | 1 + lib/ckeditor5/build/translations/zh.js | 1 + lib/ckeditor5/package.json | 44 + lib/ckeditor5/sample/index.html | 164 ++ lib/ckeditor5/sample/styles.css | 465 ++++++ lib/ckeditor5/src/ckeditor.js | 79 + lib/ckeditor5/webpack.config.js | 96 ++ lib/htmlawed/htmLawed.php | 729 +++++++++ lib/htmlawed/htmLawedTest.php | 677 ++++++++ lib/htmlawed/htmLawed_README.htm | 2289 +++++++++++++++++++++++++++ lib/htmlawed/htmLawed_README.txt | 1817 +++++++++++++++++++++ lib/htmlawed/htmLawed_TESTCASE.txt | 455 ++++++ lisez-moi.txt | 30 + model/melaine-read.php | 26 + model/melaine-write.php | 17 + public/accueil.css | 454 ++++++ public/accueil/bienvenue.png | Bin 0 -> 563995 bytes public/accueil/bienvenue_mini.png | Bin 0 -> 188642 bytes public/accueil/bienvenue_petit.png | Bin 0 -> 394448 bytes public/courriel.png | Bin 0 -> 12979 bytes public/donnees_hors_editeur.css | 38 + public/fonts/you_are_loved.eot | Bin 0 -> 51939 bytes public/fonts/you_are_loved.ttf | Bin 0 -> 101100 bytes public/fonts/you_are_loved.woff | Bin 0 -> 57840 bytes public/fonts/you_are_loved.woff2 | Bin 0 -> 47048 bytes public/main.js | 55 + public/melaine.css | 161 ++ public/melaine/photo.png | Bin 0 -> 233561 bytes public/melaine/photo_mini.png | Bin 0 -> 66245 bytes public/melaine/photo_petit.png | Bin 0 -> 136131 bytes public/menu.css | 339 ++++ public/menu/.jpg | Bin 0 -> 9339 bytes public/menu/blonde.jpg | Bin 0 -> 39839 bytes public/menu/blonde_mini.jpg | Bin 0 -> 22167 bytes public/menu/blonde_petit.jpg | Bin 0 -> 29931 bytes public/menu/canoe.png | Bin 0 -> 58206 bytes public/menu/canoe_mini.png | Bin 0 -> 23013 bytes public/menu/canoe_petit.png | Bin 0 -> 37555 bytes public/menu/cavalier.jpg | Bin 0 -> 32299 bytes public/menu/cavalier_mini.jpg | Bin 0 -> 17202 bytes public/menu/cavalier_petit.jpg | Bin 0 -> 24059 bytes public/menu/fille_qui_tombe.jpg | Bin 0 -> 22520 bytes public/menu/fille_qui_tombe_mini.jpg | Bin 0 -> 14105 bytes public/menu/fille_qui_tombe_petit.jpg | Bin 0 -> 17566 bytes public/menu/mouette_ocean.jpg | Bin 0 -> 22830 bytes public/menu/mouette_ocean_mini.jpg | Bin 0 -> 13174 bytes public/menu/mouette_ocean_petit.jpg | Bin 0 -> 17474 bytes public/menu/pochette.png | Bin 0 -> 181497 bytes public/menu/pochette_mini.png | Bin 0 -> 63605 bytes public/menu/pochette_petit.png | Bin 0 -> 112208 bytes public/menu/pommes.jpg | Bin 0 -> 14565 bytes public/menu/pommes_mini.jpg | Bin 0 -> 11024 bytes public/menu/pommes_petit.jpg | Bin 0 -> 12177 bytes public/menu/redimensionnement.sh | 25 + public/menu/sirene.jpg | Bin 0 -> 27544 bytes public/menu/sirene_mini.jpg | Bin 0 -> 14850 bytes public/menu/sirene_petit.jpg | Bin 0 -> 20385 bytes public/mouette-logo.png | Bin 0 -> 5801 bytes public/mouette.png | Bin 0 -> 58803 bytes public/mouette_mini.png | Bin 0 -> 27649 bytes public/mouette_petit.png | Bin 0 -> 44334 bytes public/normalize.css | 349 ++++ public/timbre.png | Bin 0 -> 20779 bytes view/accueil.php | 24 + view/connexion.php | 62 + view/courriel.php | 10 + view/melaine.php | 113 ++ view/menu.php | 74 + view/nav.php | 13 + view/template-ckeditor.php | 189 +++ view/template.php | 90 ++ 146 files changed, 10188 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 create mode 100644 erreur404.php create mode 100644 hello-debug.php create mode 100644 imageAJAX.php create mode 100644 index.php create mode 100644 lib/HtmlFormatter.php create mode 100644 lib/ckeditor5/LICENSE.md create mode 100644 lib/ckeditor5/README.md create mode 100644 lib/ckeditor5/build/ckeditor.js create mode 100644 lib/ckeditor5/build/ckeditor.js.map create mode 100644 lib/ckeditor5/build/translations/af.js create mode 100644 lib/ckeditor5/build/translations/ar.js create mode 100644 lib/ckeditor5/build/translations/ast.js create mode 100644 lib/ckeditor5/build/translations/az.js create mode 100644 lib/ckeditor5/build/translations/bg.js create mode 100644 lib/ckeditor5/build/translations/ca.js create mode 100644 lib/ckeditor5/build/translations/cs.js create mode 100644 lib/ckeditor5/build/translations/da.js create mode 100644 lib/ckeditor5/build/translations/de-ch.js create mode 100644 lib/ckeditor5/build/translations/de.js create mode 100644 lib/ckeditor5/build/translations/el.js create mode 100644 lib/ckeditor5/build/translations/en-au.js create mode 100644 lib/ckeditor5/build/translations/en-gb.js create mode 100644 lib/ckeditor5/build/translations/en.js create mode 100644 lib/ckeditor5/build/translations/eo.js create mode 100644 lib/ckeditor5/build/translations/es.js create mode 100644 lib/ckeditor5/build/translations/et.js create mode 100644 lib/ckeditor5/build/translations/eu.js create mode 100644 lib/ckeditor5/build/translations/fa.js create mode 100644 lib/ckeditor5/build/translations/fi.js create mode 100644 lib/ckeditor5/build/translations/gl.js create mode 100644 lib/ckeditor5/build/translations/gu.js create mode 100644 lib/ckeditor5/build/translations/he.js create mode 100644 lib/ckeditor5/build/translations/hi.js create mode 100644 lib/ckeditor5/build/translations/hr.js create mode 100644 lib/ckeditor5/build/translations/hu.js create mode 100644 lib/ckeditor5/build/translations/id.js create mode 100644 lib/ckeditor5/build/translations/it.js create mode 100644 lib/ckeditor5/build/translations/ja.js create mode 100644 lib/ckeditor5/build/translations/kk.js create mode 100644 lib/ckeditor5/build/translations/km.js create mode 100644 lib/ckeditor5/build/translations/kn.js create mode 100644 lib/ckeditor5/build/translations/ko.js create mode 100644 lib/ckeditor5/build/translations/ku.js create mode 100644 lib/ckeditor5/build/translations/lt.js create mode 100644 lib/ckeditor5/build/translations/lv.js create mode 100644 lib/ckeditor5/build/translations/nb.js create mode 100644 lib/ckeditor5/build/translations/ne.js create mode 100644 lib/ckeditor5/build/translations/nl.js create mode 100644 lib/ckeditor5/build/translations/no.js create mode 100644 lib/ckeditor5/build/translations/oc.js create mode 100644 lib/ckeditor5/build/translations/pl.js create mode 100644 lib/ckeditor5/build/translations/pt-br.js create mode 100644 lib/ckeditor5/build/translations/pt.js create mode 100644 lib/ckeditor5/build/translations/ro.js create mode 100644 lib/ckeditor5/build/translations/ru.js create mode 100644 lib/ckeditor5/build/translations/si.js create mode 100644 lib/ckeditor5/build/translations/sk.js create mode 100644 lib/ckeditor5/build/translations/sl.js create mode 100644 lib/ckeditor5/build/translations/sq.js create mode 100644 lib/ckeditor5/build/translations/sr-latn.js create mode 100644 lib/ckeditor5/build/translations/sr.js create mode 100644 lib/ckeditor5/build/translations/sv.js create mode 100644 lib/ckeditor5/build/translations/th.js create mode 100644 lib/ckeditor5/build/translations/tk.js create mode 100644 lib/ckeditor5/build/translations/tr.js create mode 100644 lib/ckeditor5/build/translations/tt.js create mode 100644 lib/ckeditor5/build/translations/ug.js create mode 100644 lib/ckeditor5/build/translations/uk.js create mode 100644 lib/ckeditor5/build/translations/vi.js create mode 100644 lib/ckeditor5/build/translations/zh-cn.js create mode 100644 lib/ckeditor5/build/translations/zh.js create mode 100644 lib/ckeditor5/package.json create mode 100644 lib/ckeditor5/sample/index.html create mode 100644 lib/ckeditor5/sample/styles.css create mode 100644 lib/ckeditor5/src/ckeditor.js create mode 100644 lib/ckeditor5/webpack.config.js create mode 100755 lib/htmlawed/htmLawed.php create mode 100755 lib/htmlawed/htmLawedTest.php create mode 100644 lib/htmlawed/htmLawed_README.htm create mode 100755 lib/htmlawed/htmLawed_README.txt create mode 100755 lib/htmlawed/htmLawed_TESTCASE.txt create mode 100644 lisez-moi.txt create mode 100644 model/melaine-read.php create mode 100644 model/melaine-write.php create mode 100644 public/accueil.css create mode 100644 public/accueil/bienvenue.png create mode 100644 public/accueil/bienvenue_mini.png create mode 100644 public/accueil/bienvenue_petit.png create mode 100644 public/courriel.png create mode 100644 public/donnees_hors_editeur.css create mode 100644 public/fonts/you_are_loved.eot create mode 100644 public/fonts/you_are_loved.ttf create mode 100644 public/fonts/you_are_loved.woff create mode 100644 public/fonts/you_are_loved.woff2 create mode 100644 public/main.js create mode 100644 public/melaine.css create mode 100644 public/melaine/photo.png create mode 100644 public/melaine/photo_mini.png create mode 100644 public/melaine/photo_petit.png create mode 100644 public/menu.css create mode 100644 public/menu/.jpg create mode 100644 public/menu/blonde.jpg create mode 100644 public/menu/blonde_mini.jpg create mode 100644 public/menu/blonde_petit.jpg create mode 100644 public/menu/canoe.png create mode 100644 public/menu/canoe_mini.png create mode 100644 public/menu/canoe_petit.png create mode 100644 public/menu/cavalier.jpg create mode 100644 public/menu/cavalier_mini.jpg create mode 100644 public/menu/cavalier_petit.jpg create mode 100644 public/menu/fille_qui_tombe.jpg create mode 100644 public/menu/fille_qui_tombe_mini.jpg create mode 100644 public/menu/fille_qui_tombe_petit.jpg create mode 100644 public/menu/mouette_ocean.jpg create mode 100644 public/menu/mouette_ocean_mini.jpg create mode 100644 public/menu/mouette_ocean_petit.jpg create mode 100644 public/menu/pochette.png create mode 100644 public/menu/pochette_mini.png create mode 100644 public/menu/pochette_petit.png create mode 100644 public/menu/pommes.jpg create mode 100644 public/menu/pommes_mini.jpg create mode 100644 public/menu/pommes_petit.jpg create mode 100755 public/menu/redimensionnement.sh create mode 100644 public/menu/sirene.jpg create mode 100644 public/menu/sirene_mini.jpg create mode 100644 public/menu/sirene_petit.jpg create mode 100644 public/mouette-logo.png create mode 100644 public/mouette.png create mode 100644 public/mouette_mini.png create mode 100644 public/mouette_petit.png create mode 100644 public/normalize.css create mode 100644 public/timbre.png create mode 100644 view/accueil.php create mode 100644 view/connexion.php create mode 100644 view/courriel.php create mode 100644 view/melaine.php create mode 100644 view/menu.php create mode 100644 view/nav.php create mode 100644 view/template-ckeditor.php create mode 100644 view/template.php 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 @@ +javascript:window.close()'; + +// Le fichier .htaccess est situé dans le répertoire racine du site (et non du serveur), il comporte cette ligne: +// ErrorDocument 404 /ckeditor5/erreur404.php +// en cas d'erreur 404, le serveur apache renverra le visiteur vers ce fichier (erreur404.php) +// +// ATTENTION depuis apache en version 2.4 le .htaccess est ignoré par défaut, il y a deux méthodes pour y remedier: +// - méthode facile et moins sécurisée: trouver la ligne "AllowOverride None" dans le fichier de conf d'apache et changer "None" par "All" +// - méthode sécurisée consistant à autoriser uniquement la directive ErrorDocument pour notre site, +// ne rien modifier et ajouter une nouvelle section comme ci-dessous: +// +// AllowOverrideList ErrorDocument +// + + + + <?= $hello ?> + + +

Racine selon le serveur:

+

Nom du serveur:

+

Répertoire courant:

+

Chemin du script:

+

Langue:

+

+ + diff --git a/imageAJAX.php b/imageAJAX.php new file mode 100644 index 0000000..49c856d --- /dev/null +++ b/imageAJAX.php @@ -0,0 +1,100 @@ + $_FILES['upload']['name'], + //~ 'type' => $_FILES['upload']['type'], + //~ 'tmp_name' => $_FILES['upload']['tmp_name'], + //~ 'error' => $_FILES['upload']['error'], + //~ 'size' => $_FILES['upload']['size'] +//~ ); +// print_r sert à "afficher" un tableau, +// le 2ème paramètre 'true' permet de produire une simple chaine au lieu d'un affichage HTML +// $tableau = print_r($_FILES, true); +// $nom_fichier = "POST_AJAX.log"; +// $fichier = fopen('data/' . $page . '/images/' . $nom_fichier, 'w'); +// // w peut créer un fichier, si il existe déjà, il est effacé par le nouveau contenu +// fputs($fichier, $tableau); +// fclose($fichier); +// chmod('data/' . $page . '/images/' . $nom_fichier, 0666); + + +// déjà fait dans installation.php +if(!file_exists('data/' . $page . '/images')) +{ + mkdir('data/' . $page . '/images', 0777); + chmod('data/' . $page . '/images', 0777); +} + +// taille en Mo à adapter au serveur (2Mo est la valeur par défaut dans le php.ini) +$tailleMax = 2000000; +$erreur = ''; + +// traitement et enregistrement de l'image +if (isset($_FILES['upload']) AND $_FILES['upload']['error'] == 0) // 0 signifie ok +{ + if ($_FILES['upload']['size'] <= $tailleMax ) + { + $infos = pathinfo ($_FILES['upload']['name']); + $extension = $infos['extension']; + $extautorisées = array('jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'tiff'); + // on prend la même liste que celle côté javascript, le SVG est bloqué pour raison de sécurité (javascript à l'intérieur) + if (in_array ($extension, $extautorisées)) + { + move_uploaded_file ($_FILES['upload']['tmp_name'], 'data/' . $page . '/images/' . $_FILES['upload']['name']); + chmod('data/' . $page . '/images/' . $_FILES['upload']['name'], 0666); + } + else{$erreur = 'mauvais format, veuillez utiliser une image comportant un de ces formats: jpg ou jpeg, png, gif, bmp, webp, tiff
le format svg n\'est pas supporté';} + } + else{$erreur = 'fichier trop lourd';} +} +else{$erreur = $_FILES['upload']['error'];} +/* les erreurs retournées avec $_FILES['upload']['error']: +0 pas d'erreur +1 taille du fichier supérieure à la valeur de upload_max_filesize dans le fichier php.ini (par défaut = 2 MO) +2 taille du fichier supérieure à la valeur de MAX_FILE_SIZE dans le formulaire HTML +3 fichier partiellement téléchargé +4 pas de fichier du tout +6 pas de dossier temporaire pour mettre le fichier +7 echec de l'écriture sur le DD +8 envoi arrêté par une extension de PHP mais on ne nous dit pas pourquoi => diagnostic avec la fonction phpinfo() */ + +// nouveau chemin à renvoyer en format json +$chemin = '{"url": "data/' . $page . '/images/' . $_FILES['upload']['name'] . '"}'; +//echo json_encode($chemin); +echo $chemin; diff --git a/index.php b/index.php new file mode 100644 index 0000000..72791fd --- /dev/null +++ b/index.php @@ -0,0 +1,201 @@ + contrôleur +// | +// v +// vue ---> envoi de la page au client +// +// pour retrouver quelque chose dans le code, il suffit de suivre un chemin linéaire dont le départ est ici +// pas de croisement, pas de marche arrière, impossible de se perdre! +// +// à la racine de l'arbre des fichiers nous avons: +// - 1 fichier index.php sur lequel se greffe tout le reste +// - 4 dossiers pricipaux: controller - model - view - public +// un avantage est que les chemins sont tous relatifs, partent tous de la racine du site et sont toujours bons + +// Les dossiers: +// -> contrôleurs: traitements en PHP pur +// -> modèles: interface entre PHP et données, on y trouve le SQL ou la manipulation de fichiers textes, le PHP y est générlement orienté objet +// -> vues: le PHP y produit le HTML, il construit les pages, +// le mélange PHP/HTML étant très vite assez dégueulasse, le HTML figé à placé à part dans le fichier view/template.php +// -> le dossier public contient CSS, JS, images, polices, medias, etc, il est utilisé par le template +// -> le dossier lib contient les bibliothèques, il contient notamment le ckeditor qui occupe une place centrale dans le projet, on y trouve aussi la bibli htmLawed qui protège des données dangereuses (failles XSS) +// -> le dossier data qui est techniquement séparé du site +// +// pour le reste nous avons: +// - le fichier imageAJAX.php traitant les requêtes AJAX +// ce fichier est appelé sans index.php et est pour cette raison un peu spécial +// - 1 fichier .htaccess pour la sécurité (configurer le httpd.conf peut être nécessaire) +// - 1 fichier erreur404.php (fonctionne avec .htaccess) +// - des bibliothèques externes dans lib: +// ckeditor5, ckfinder, htmlawed et HtmlFormatter +// +// le dossier data et son contenu sont "normalement" autorisés en écriture pour deux raisons: +// - placer le contenu pré-existant avec son client FTP +// - autoriser PHP (sinon, c'est comme si on avait un site statique) +// +// pour pouvoir installer le site en n'ayant qu'à modifier les droits du dossier data uniquement et éviter les situations pénibles ou l'utilisateur est bloqué sans rien comprendre, on pourra créer ou utiliser des sauvegardes au format ZIP depuis une page spéciale accessible avec le compte admin + +// au premier démarrage du site +require('controller/installation.php'); +installation(); + +// à propos des sessions, penser aux attaques CSRF (cross-site request forgery): +// ça consite à faire qu'un utilisateur connecté avec une session envoie malgré lui une requête GET ou POST qu'un hacker aura cachée par exemple dans une fausse image clicable +// - solutionq: faire qu'un GET seul dans une session ne suffise pas à effectuer une action (les GET ne doivent servir qu'à afficher la bonne page), une attaque sur un POST nécessite d'injecter du javascript +// - on peut demander à l'utilisateur une vérification supplémentaire avant chaque action, mais c'est plutôt chiant +// - la méthode des jetons, "nonces" et horodatage +// - vérifier le "référent", c'est à dire l'URL de la page d'où vient normallement la requête +// infos: https://fr.wikipedia.org/wiki/Cross-site_request_forgery +session_start(); + +// sécurité failles XSS +require('lib/htmlawed/htmLawed.php'); + +// traitement des POST du ckeditor +// NOTER que le fichier "habituel" controller/admin.php n'est pas utilisé +// la fonction submitCKeditor n'affiche rien puis redirige sans GET +if(isset($_SESSION['admin']) && $_SESSION['admin'] == 1 + && isset($_GET['action']) && $_GET['action'] == 'submit' + && isset($_POST['contenu'])) +{ + require('controller/ckeditor.php'); + submitCKeditor($_GET['page'], $_GET['article'], $_POST['contenu']); + + // nettoyage (je ne sais pas si ça sert à quelque chose, mais c'est pas grave) + unlink($_GET['action']); + unlink($_POST['contenu']); + + // rechargement "nettoyage" à la fin du traitement + header('Location: index.php?page=' . $_GET['page']); +} + +// déconnexion: nettoyer et recharger la page +if(isset($_GET['action'])) +{ + if($_GET['action'] == "deconnexion") + { + $_SESSION['admin'] = 0; + header('Location: index.php'); + } +} + +// le site comporte deux modes: +// le mode normal en "lecture seule" utilisant le contrôleur visitor.php +// le mode admin avec droits en "écriture" utilisant le contrôleur admin.php + +// appelé tout le temps parce que certaines pages (accueil, menu) n'ont pas de version "admin" +// une optimisation serait bienvenue +require('controller/visitor.php'); + +if(isset($_SESSION['admin']) && $_SESSION['admin'] == 1) +{ + require('controller/admin.php'); +} +else +{ + // initialisation + $_SESSION['admin'] = 0; +} + +// mot de passe de connexion à protéger par le .htaccess !! +$secret = "julian"; + +// page du site demandée +if(isset($_GET['page'])) +{ + // page menu + if($_GET['page'] == 'menu') + { + menu(); + } + + // page melaine + elseif($_GET['page'] == 'melaine') + { + // ouverture de l'éditeur + if($_SESSION['admin'] == 1 && isset($_GET['action']) && $_GET['action'] == 'editor') + { + // modification + if(isset($_GET['article']) && is_numeric($_GET['article']) && $_GET['article'] > 0) + { + melaineAdmin($_GET['article']); + } + // nouvel article + else + { + melaineAdmin(0); + } + } + else + { + melaineVisitor(); + } + } + // page connexion au mode admin + elseif($_GET['page'] == 'connexion') + { + connexion($secret); + } + // $_GET['page'] = n'importe quoi! + else + { + menu(); + } +} + +// actions en mode admin recharger une des pages principales +elseif($_SESSION['admin'] == 1 && isset($_GET['action'])) +{ + if($_GET['action'] == 'nouveau_mdp') + { + changerMotDePasse($secret, $_GET['from']); + } + // extraction du contenu du dossier data + else if($_GET['action'] == 'extraction') + { + require('controller/backup.php'); + extraction($_GET['from']); + } + // l'inverse, insertion des données d'une sauvegarde + else if($_GET['action'] == 'insertion') + { + require('controller/backup.php'); + insertion($_GET['from']); + } + else + { + accueil(); + } +} + +// renvoi ici par le .htaccess si lien mort ou sans http:// au début +elseif(isset($_GET['erreur'])) +{ + //if($_GET['erreur'] == 404) + //{ + // echo('

ERREUR 404
Le lien sur lequel vous avez cliqué pointe vers un emplacement introuvable.
+ // Ce n\'est pas votre faute. Vous pouvez éventuellement rechercher la page demandée avec votre moteur de recherche ou prévenir le responsable du site.

'); + // echo('

Retour au site

'); + //} + //else + //{ + accueil(); + // accueil_404(); // à créer + //} +} + +// page d'accueil (adresse sans GET valable) +else +{ + accueil(); +} diff --git a/lib/HtmlFormatter.php b/lib/HtmlFormatter.php new file mode 100644 index 0000000..89605ac --- /dev/null +++ b/lib/HtmlFormatter.php @@ -0,0 +1,126 @@ +)/U', $html, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); + $dom = self::parseDom($elements); + + $indent = 0; + $output = array(); + foreach ($dom as $index => $element) + { + if ($element['opening']) + { + $output[] = "\n".str_repeat($indentWith, $indent).trim($element['content']); + + // make sure that only the elements who have not been blacklisted are being indented + if ( ! in_array($element['type'], explode(',', $tagsWithoutIndentation))) + { + ++$indent; + } + } + else if ($element['standalone']) + { + $output[] = "\n".str_repeat($indentWith, $indent).trim($element['content']); + } + else if ($element['closing']) + { + --$indent; + $lf = "\n".str_repeat($indentWith, abs($indent)); + if (isset($dom[$index - 1]) && $dom[$index - 1]['opening']) + { + $lf = ''; + } + $output[] = $lf.trim($element['content']); + } + else if ($element['text']) + { + // $output[] = "\n".str_repeat($indentWith, $indent).trim($element['content']); + $output[] = "\n".str_repeat($indentWith, $indent).preg_replace('/ [ \t]*/', ' ', $element['content']); + } + else if ($element['comment']) + { + $output[] = "\n".str_repeat($indentWith, $indent).trim($element['content']); + } + } + + return trim(implode('', $output)); + } + + /** + * Parses an array of HTML tokens and adds basic information about about the type of + * tag the token represents. + * + * @param Array $elements Array of HTML tokens (tags and text tokens). + * @return Array HTML elements with extra information. + */ + public static function parseDom(Array $elements) + { + $dom = array(); + foreach ($elements as $element) + { + $isText = false; + $isComment = false; + $isClosing = false; + $isOpening = false; + $isStandalone = false; + + $currentElement = trim($element); + + // comment + if (strpos($currentElement, '$/', $currentElement)) + { + $isStandalone = true; + } + // normal opening tag + else if (strpos($currentElement, '<') === 0) + { + $isOpening = true; + } + // text + else + { + $isText = true; + } + + $dom[] = array( + 'text' => $isText, + 'comment' => $isComment, + 'closing' => $isClosing, + 'opening' => $isOpening, + 'standalone' => $isStandalone, + 'content' => $element, + 'type' => preg_replace('/^<\/?(\w+)[ >].*$/U', '$1', $element) + ); + } + return $dom; + } +} diff --git a/lib/ckeditor5/LICENSE.md b/lib/ckeditor5/LICENSE.md new file mode 100644 index 0000000..95eabee --- /dev/null +++ b/lib/ckeditor5/LICENSE.md @@ -0,0 +1,49 @@ +Software License Agreement +========================== + +Copyright (c) 2014-2021, CKSource - Frederico Knabben. All rights reserved. + +Online builder code samples are licensed under the terms of the MIT License (see Appendix A): + + http://en.wikipedia.org/wiki/MIT_License + +CKEditor 5 collaboration features are only available under a commercial license. [Contact us](https://ckeditor.com/contact/) for more details. + +Free 30-days trials of CKEditor 5 collaboration features are available: + * https://ckeditor.com/collaboration/ - Real-time collaboration (with all features). + * https://ckeditor.com/collaboration/comments/ - Inline comments feature (without real-time collaborative editing). + * https://ckeditor.com/collaboration/track-changes/ - Track changes feature (without real-time collaborative editing). + +Trademarks +---------- + +CKEditor is a trademark of CKSource - Frederico Knabben. All other brand +and product names are trademarks, registered trademarks or service +marks of their respective holders. + +--- + +Appendix A: The MIT License +--------------------------- + +The MIT License (MIT) + +Copyright (c) 2014-2021, CKSource - Frederico Knabben + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/lib/ckeditor5/README.md b/lib/ckeditor5/README.md new file mode 100644 index 0000000..fc116c4 --- /dev/null +++ b/lib/ckeditor5/README.md @@ -0,0 +1,68 @@ +# CKEditor 5 editor generated with the online builder + +This repository presents a CKEditor 5 editor build generated by the [Online builder tool](https://ckeditor.com/ckeditor-5/online-builder) + +## Quick start + +1. Open the `sample/index.html` page in the browser. + +If you picked the real-time collaboration plugins: + +2. Fill the dialog with correct token, websocket and upload URL endpoints. If you do not have these yet or do not know their meaning, [contact us](https://ckeditor.com/contact/). + +3. Copy the URL and share it or paste in another tab to enjoy real-time collaborative editing. + +If you picked the non-real-time collaboration plugins: + +2. Fill the prompt with the license key. If you do not have the license key yet [contact us](https://ckeditor.com/contact/). + +## Configuring build + +Changes like changing toolbar items, changing order of icons or customizing plugin configurations should be relatively easy to make. Open the `sample/index.html` file and edit the script that initialized the CKEditor 5. Save the file and refresh the browser. That's all. + +*Note:* If you have any problems with browser caching use the `Ctrl + R` or `Cmd + R` shortcut depending on your system. + +However if you want to remove or add a plugin to the build you need to follow the next step of this guide. + +Note that it is also possible to go back to the [Online builder tool](https://ckeditor.com/ckeditor-5/online-builder) and pick other set of plugins. But we encourage you to try the harder way and to learn the principles of Node.js and CKEditor 5 ecosystems that will allow you to do more cool things in the future! + +### Installation + +In order to rebuild the application you need to install all dependencies first. To do it, open the terminal in the project directory and type: + +``` +npm install +``` + +Make sure that you have the `node` and `npm` installed first. If not, then follow the instructions on the [Node.js documentation page](https://nodejs.org/en/). + +### Adding or removing plugins + +Now you can install additional plugin in the build. Just follow the [Adding a plugin to an editor tutorial](https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/installing-plugins.html#adding-a-plugin-to-an-editor) + +### Rebuilding editor + +If you have already done the [Installation](#installation) and [Adding or removing plugins](#adding-or-removing-plugins) steps, you're ready to rebuild the editor by running the following command: + +``` +npm run build +``` + +This will build the CKEditor 5 to the `build` directory. You can open your browser and you should be able to see the changes you've made in the code. If not, then try to refresh also the browser cache by typing `Ctrl + R` or `Cmd + R` depending on your system. + +## What's next? + +Follow the guides available on https://ckeditor.com/docs/ckeditor5/latest/framework/index.html and enjoy the document editing. + +## FAQ +| Where is the place to report bugs and feature requests? + +You can create an issue on https://github.com/ckeditor/ckeditor5/issues including the build id - `aovpauzd25hi-dqoovaepm42n`. Make sure that the question / problem is unique, please look for a possibly asked questions in the search box. Duplicates will be closed. + +| Where can I learn more about the CKEditor 5 framework? + +Here: https://ckeditor.com/docs/ckeditor5/latest/framework/ + +| Is it possible to use online builder with common frameworks like React, Vue or Angular? + +Not yet, but it these integrations will be available at some point in the future. diff --git a/lib/ckeditor5/build/ckeditor.js b/lib/ckeditor5/build/ckeditor.js new file mode 100644 index 0000000..6de3d4e --- /dev/null +++ b/lib/ckeditor5/build/ckeditor.js @@ -0,0 +1,6 @@ +/*! + * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md. + */ +(function(t){const e=t["fr"]=t["fr"]||{};e.dictionary=Object.assign(e.dictionary||{},{"%0 of %1":"%0 sur %1","Align center":"Centrer","Align left":"Aligner à gauche","Align right":"Aligner à droite","Align table to the left":"Aligner le tableau à gauche","Align table to the right":"Aligner le tableau à droite",Alignment:"Alignement",Aquamarine:"Bleu vert",Background:"Fond",Big:"Grand",Black:"Noir","Block quote":"Citation",Blue:"Bleu","Blue marker":"Marqueur bleu",Bold:"Gras",Border:"Bordure","Bulleted List":"Liste à puces",Cancel:"Annuler","Center table":"Centrer le tableau ","Centered image":"Image centrée","Change image text alternative":"Changer le texte alternatif à l’image","Choose heading":"Choisir l'en-tête",Color:"Couleur","Color picker":"Pipette à couleurs",Column:"Colonne",Dashed:"Tirets",Default:"Par défaut","Delete column":"Supprimer la colonne","Delete row":"Supprimer la ligne","Dim grey":"Gris pâle",Dimensions:"Dimensions","Document colors":"Couleurs du document",Dotted:"Pointillés",Double:"Double",Downloadable:"Fichier téléchargeable","Dropdown toolbar":"Barre d'outils dans un menu déroulant","Edit block":"Modifier le bloc","Edit link":"Modifier le lien","Edit source":"Modifier la source","Editor toolbar":"Barre d'outils de l'éditeur","Empty snippet content":"Aucun contenu pour ce fragment de code","Enter image caption":"Saisir la légende de l’image","Font Color":"Couleur de police","Font Family":"Police","Font Size":"Taille de police","Full size image":"Image taille réelle",Green:"Vert","Green marker":"Marqueur vert","Green pen":"Crayon vert",Grey:"Gris",Groove:"Rainuré","Header column":"Colonne d'entête","Header row":"Ligne d'entête",Heading:"En-tête","Heading 1":"Titre 1","Heading 2":"Titre 2","Heading 3":"Titre 3","Heading 4":"Titre 4","Heading 5":"Titre 5","Heading 6":"Titre 6",Height:"Hauteur",Highlight:"Surlignage","Horizontal line":"Ligne horizontale","HTML snippet":"Code HTML",Huge:"Enorme","Image toolbar":"Barre d'outils des images","image widget":"Objet image",Insert:"Insérer","Insert column left":"Insérer une colonne à gauche","Insert column right":"Insérer une colonne à droite","Insert HTML":"Insérer du code HTML","Insert image":"Insérer une image","Insert image via URL":"Insérer une image à partir d'une URL","Insert paragraph after block":"Insérer du texte après ce bloc","Insert paragraph before block":"Insérer du texte avant ce bloc","Insert row above":"Insérer une ligne au-dessus","Insert row below":"Insérer une ligne en-dessous","Insert table":"Insérer un tableau",Inset:"Relief intérieur",Italic:"Italique",Justify:"Justifier","Left aligned image":"Image alignée à gauche","Light blue":"Bleu clair","Light green":"Vert clair","Light grey":"Gris clair",Link:"Lien","Link image":"Lien d'image","Link URL":"URL du lien","Merge cell down":"Fusionner la cellule en-dessous","Merge cell left":"Fusionner la cellule à gauche","Merge cell right":"Fusionner la cellule à droite","Merge cell up":"Fusionner la cellule au-dessus","Merge cells":"Fusionner les cellules",Next:"Suivant","No preview available":"Aucun aperçu disponible",None:"Aucun","Numbered List":"Liste numérotée","Open in a new tab":"Ouvrir dans un nouvel onglet","Open link in new tab":"Ouvrir le lien dans un nouvel onglet",Orange:"Orange",Outset:"Relief extérieur",Paragraph:"Paragraphe","Paste raw HTML here...":"Collez le code HTML brut ici...","Pink marker":"Marqueur rose",Previous:"Précedent",Purple:"Violet",Red:"Rouge","Red pen":"Crayon rouge",Redo:"Restaurer","Remove color":"Enlever la couleur","Remove highlight":"Enlever le surlignage","Rich Text Editor":"Éditeur de texte enrichi","Rich Text Editor, %0":"Éditeur de texte enrichi, %0",Ridge:"Relief","Right aligned image":"Image alignée à droite",Row:"Ligne",Save:"Enregistrer","Save changes":"Enregistrer les changements","Saving changes":"Enregistrement des modifications","Select all":"Sélectionner tout","Select column":"Sélectionner la colonne","Select row":"Sélectionner la ligne","Show more items":"Montrer plus d'éléments","Side image":"Image latérale",Small:"Petit",Solid:"Continu","Split cell horizontally":"Scinder la cellule horizontalement","Split cell vertically":"Scinder la cellule verticalement",Style:"Style","Table alignment toolbar":"Barre d'outils pour modifier l'alignement du tableau","Table properties":"Propriétés du tableau","Table toolbar":"Barre d'outils des tableaux","Text alignment":"Alignement du texte","Text alignment toolbar":"Barre d'outils d'alignement du texte","Text alternative":"Texte alternatif","Text highlight toolbar":"Barre d'outils du surlignage",'The color is invalid. Try "#FF0000" or "rgb(255,0,0)" or "red".':'La couleur est invalide. Essayez "#FF0000" ou "rgb(255,0,0)" ou "red".','The value is invalid. Try "10px" or "2em" or simply "2".':'La valeur est invalide. Essayez "10px" ou "2em" ou simplement "2".',"This link has no URL":"Ce lien n'a pas d'URL",Tiny:"Minuscule","To-do List":"Liste de tâches",Turquoise:"Turquoise",Underline:"Souligné",Undo:"Annuler",Unlink:"Supprimer le lien",Update:"Modifier","Update image URL":"Modifier l'URL de l'image","Upload failed":"Échec de l'envoi","Upload in progress":"Téléchargement en cours",White:"Blanc","Widget toolbar":"Barre d'outils du widget",Width:"Largeur",Yellow:"Jaune","Yellow marker":"Marqueur jaune"});e.getPluralForm=function(t){return t>1}})(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));(function t(e,n){if(typeof exports==="object"&&typeof module==="object")module.exports=n();else if(typeof define==="function"&&define.amd)define([],n);else if(typeof exports==="object")exports["ClassicEditor"]=n();else e["ClassicEditor"]=n()})(window,(function(){return function(t){var e={};function n(o){if(e[o]){return e[o].exports}var i=e[o]={i:o,l:false,exports:{}};t[o].call(i.exports,i,i.exports,n);i.l=true;return i.exports}n.m=t;n.c=e;n.d=function(t,e,o){if(!n.o(t,e)){Object.defineProperty(t,e,{enumerable:true,get:o})}};n.r=function(t){if(typeof Symbol!=="undefined"&&Symbol.toStringTag){Object.defineProperty(t,Symbol.toStringTag,{value:"Module"})}Object.defineProperty(t,"__esModule",{value:true})};n.t=function(t,e){if(e&1)t=n(t);if(e&8)return t;if(e&4&&typeof t==="object"&&t&&t.__esModule)return t;var o=Object.create(null);n.r(o);Object.defineProperty(o,"default",{enumerable:true,value:t});if(e&2&&typeof t!="string")for(var i in t)n.d(o,i,function(e){return t[e]}.bind(null,i));return o};n.n=function(t){var e=t&&t.__esModule?function e(){return t["default"]}:function e(){return t};n.d(e,"a",e);return e};n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)};n.p="";return n(n.s=74)}([function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));n.d(e,"b",(function(){return r}));const o="https://ckeditor.com/docs/ckeditor5/latest/framework/guides/support/error-codes.html";class i extends Error{constructor(t,e,n){const o=`${t}${n?` ${JSON.stringify(n)}`:""}${a(t)}`;super(o);this.name="CKEditorError";this.context=e;this.data=n}is(t){return t==="CKEditorError"}static rethrowUnexpectedError(t,e){if(t.is&&t.is("CKEditorError")){throw t}const n=new i(t.message,e);n.stack=t.stack;throw n}}function r(t,e){console.warn(...c(t,e))}function s(t,e){console.error(...c(t,e))}function a(t){return`\nRead more: ${o}#error-${t}`}function c(t,e){const n=a(t);return e?[t,e,n]:[t,n]}},function(t,e,n){"use strict";var o=function t(){var e;return function t(){if(typeof e==="undefined"){e=Boolean(window&&document&&document.all&&!window.atob)}return e}}();var i=function t(){var e={};return function t(n){if(typeof e[n]==="undefined"){var o=document.querySelector(n);if(window.HTMLIFrameElement&&o instanceof window.HTMLIFrameElement){try{o=o.contentDocument.head}catch(t){o=null}}e[n]=o}return e[n]}}();var r=[];function s(t){var e=-1;for(var n=0;nt.length)e=t.length;for(var n=0,o=new Array(e);n