summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--public/js/tinymce.js16
-rw-r--r--src/controller/Security.php10
-rw-r--r--src/controller/ajax.php42
3 files changed, 46 insertions, 22 deletions
diff --git a/public/js/tinymce.js b/public/js/tinymce.js
index 55a37cc..f8d78c8 100644
--- a/public/js/tinymce.js
+++ b/public/js/tinymce.js
@@ -49,9 +49,9 @@ function openEditor(id, page = '') {
49 } 49 }
50 }); 50 });
51 editor.on('PastePreProcess', function (e){ // déclenchement au collage AVANT insertion dans l'éditeur 51 editor.on('PastePreProcess', function (e){ // déclenchement au collage AVANT insertion dans l'éditeur
52 let parser = new DOMParser(); 52 const parser = new DOMParser();
53 let doc = parser.parseFromString(e.content, 'text/html'); 53 const doc = parser.parseFromString(e.content, 'text/html');
54 let images = doc.querySelectorAll('img'); 54 const images = doc.querySelectorAll('img');
55 55
56 let downloads_in_progress = []; 56 let downloads_in_progress = [];
57 57
@@ -59,11 +59,11 @@ function openEditor(id, page = '') {
59 if(img.src.startsWith('file://')){ // détection d'images non insérables 59 if(img.src.startsWith('file://')){ // détection d'images non insérables
60 console.warn('Image locale non insérable dans tinymce :', img.src); 60 console.warn('Image locale non insérable dans tinymce :', img.src);
61 img.outerHTML = '<div style="border:1px solid red; padding:10px; margin:5px 0; background-color:#ffe6e6; color:#a94442; font-size:14px;">' + 61 img.outerHTML = '<div style="border:1px solid red; padding:10px; margin:5px 0; background-color:#ffe6e6; color:#a94442; font-size:14px;">' +
62"Image locale non insérée. Pour insérer une image depuis LibreOffice, copiez l'image seule et recoller." + 62"Image locale non insérée (vient-elle de LibreOffice ?). Effacez cet encadré et copiez-collez l'image seule. Ensuite cliquez sur le bouton Insérer une image puis dans la nouvelle fenêtre sur Enregistrer." +
63'</div>'; 63'</div>';
64 } 64 }
65 else if(img.src.startsWith('http')){ // détection d'images web 65 else if(img.src.startsWith('http')){ // détection d'images web
66 let promise = fetch('index.php?action=upload_image_url', { // promesse d'un fichier téléchargeable sur le serveur 66 const promise = fetch('index.php?action=upload_image_url', { // promesse d'un fichier téléchargeable sur le serveur
67 method: 'POST', 67 method: 'POST',
68 headers: { 'Content-Type': 'application/json' }, 68 headers: { 'Content-Type': 'application/json' },
69 body: JSON.stringify({ image_url: img.src }) 69 body: JSON.stringify({ image_url: img.src })
@@ -75,7 +75,7 @@ function openEditor(id, page = '') {
75 } 75 }
76 }) 76 })
77 .catch(error => { 77 .catch(error => {
78 console.error('Erreur lors de l’upload de l’image :', error); 78 console.error('Erreur lors de l’upload de l’image distante:', error);
79 }); 79 });
80 80
81 downloads_in_progress.push(promise); 81 downloads_in_progress.push(promise);
@@ -96,7 +96,7 @@ function openEditor(id, page = '') {
96 } 96 }
97 }); // fin editor.on('PastePreProcess'... 97 }); // fin editor.on('PastePreProcess'...
98 }, 98 },
99 // upload d'image 99 // upload d'image natif de tinymce avec le bouton "Insérer une image"
100 images_upload_handler: (blobInfo, progress) => new Promise((resolve, reject) => { 100 images_upload_handler: (blobInfo, progress) => new Promise((resolve, reject) => {
101 const formData = new FormData(); 101 const formData = new FormData();
102 formData.append("file", blobInfo.blob()); 102 formData.append("file", blobInfo.blob());
@@ -107,7 +107,7 @@ function openEditor(id, page = '') {
107 }) 107 })
108 .then(response => response.json()) 108 .then(response => response.json())
109 .then(data => { 109 .then(data => {
110 if (data.location) { 110 if(data.location) {
111 resolve(data.location); 111 resolve(data.location);
112 } 112 }
113 else { 113 else {
diff --git a/src/controller/Security.php b/src/controller/Security.php
index 7d592e9..cd31cb8 100644
--- a/src/controller/Security.php
+++ b/src/controller/Security.php
@@ -59,11 +59,15 @@ class Security
59 // => on remplace tout par des _ 59 // => on remplace tout par des _
60 // filtrer / et \ semble inutile 60 // filtrer / et \ semble inutile
61 61
62 $cibles = [' ', '/', '\\', ':', '*', '?', '<', '>', '|', '=', "'", '`', '"', '%22', '#']; 62 /*$cibles = [' ', '/', '\\', ':', '*', '?', '<', '>', '|', '=', "'", '`', '"', '%22', '#'];
63 $chaine = str_replace($cibles, '_', $chaine); // nécéssite l'extension mbstring 63 $chaine = str_replace($cibles, '_', $chaine); // nécéssite l'extension mbstring
64 $chaine = mb_strtolower($chaine); 64 $chaine = mb_strtolower($chaine);
65 return($chaine); 65 return($chaine);*/
66 66
67 $chaine = preg_replace('/[^a-zA-Z0-9_-]/', '_', $chaine); // ne garder que les lettres, chiffres, tirets et underscores
68 $chaine = preg_replace('/_+/', '_', $chaine); // doublons d'underscores
69 return trim($chaine, '_');
70
67 // les problèmes avec \ persistent !! 71 // les problèmes avec \ persistent !!
68 // => javascript 72 // => javascript
69 // malheureusement document.getElementById('upload').files[0].name = chaine; ne marche pas! interdit! 73 // malheureusement document.getElementById('upload').files[0].name = chaine; ne marche pas! interdit!
diff --git a/src/controller/ajax.php b/src/controller/ajax.php
index 943c027..6813d45 100644
--- a/src/controller/ajax.php
+++ b/src/controller/ajax.php
@@ -9,15 +9,17 @@ use App\Entity\Article;
9 9
10 10
11// mettre ça ailleurs 11// mettre ça ailleurs
12function imagickCleanImage(string $image_data, string $local_path): bool // "string" parce que file_get_contents... 12function imagickCleanImage(string $image_data, string $local_path, string $format = 'jpeg'): bool // "string" parce que file_get_contents...
13{ 13{
14 try{ 14 try{
15 $imagick = new Imagick(); 15 $imagick = new Imagick();
16 $imagick->readImageBlob($image_data); 16 $imagick->readImageBlob($image_data);
17 $imagick->stripImage(); // nettoyage métadonnées 17 $imagick->stripImage(); // nettoyage métadonnées
18 $imagick->setImageFormat('jpeg'); 18 $imagick->setImageFormat($format);
19 $imagick->setImageCompression(Imagick::COMPRESSION_JPEG); 19 if($format === 'jpeg'){
20 $imagick->setImageCompressionQuality(85); // optionnel 20 $imagick->setImageCompression(Imagick::COMPRESSION_JPEG);
21 $imagick->setImageCompressionQuality(85); // optionnel
22 }
21 $imagick->writeImage($local_path); // enregistrement 23 $imagick->writeImage($local_path); // enregistrement
22 $imagick->clear(); 24 $imagick->clear();
23 $imagick->destroy(); 25 $imagick->destroy();
@@ -75,18 +77,23 @@ if(strpos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') !== false && isset($_
75 mkdir($dest_mini, 0700, true); 77 mkdir($dest_mini, 0700, true);
76 } 78 }
77 79
78 $filePath = $dest . basename($file['name']); 80 $allowed_extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'tiff', 'tif'];
81 $name = Security::secureFileName(pathinfo($file['name'], PATHINFO_FILENAME));
82 $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
83 if(!in_array($extension, $allowed_extensions) || $extension === 'jpg'){
84 $extension = 'jpeg';
85 }
86 $file_path = $dest . $name . '_' . uniqid() . '.' . $extension;
79 87
80 // créer une miniature de l'image 88 // créer une miniature de l'image
81 // 89 //
82 90
83 if(move_uploaded_file($file['tmp_name'], $filePath)) { 91 if(imagickCleanImage(file_get_contents($file['tmp_name']), $file_path, $extension)){ // recréer l’image pour la nettoyer
84 $image_url = str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']); 92 echo json_encode(['location' => $file_path]); // renvoyer l'URL de l'image téléchargée
85 echo json_encode(['location' => $image_url . $filePath]); // renvoyer l'URL de l'image téléchargée
86 } 93 }
87 else{ 94 else{
88 http_response_code(500); 95 http_response_code(500);
89 echo json_encode(['message' => 'Erreur 500: Internal Server Error']); 96 echo json_encode(['message' => 'Erreur image non valide']);
90 } 97 }
91 } 98 }
92 else{ 99 else{
@@ -101,15 +108,28 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_url'){
101 108
102 if(isset($json['image_url'])){ 109 if(isset($json['image_url'])){
103 $image_data = curlDownloadImage($json['image_url']); // téléchargement de l’image par le serveur avec cURL au lieu de file_get_contents 110 $image_data = curlDownloadImage($json['image_url']); // téléchargement de l’image par le serveur avec cURL au lieu de file_get_contents
111 $dest = 'images/';
104 112
113 if(!is_dir($dest)) { // Vérifier si le répertoire existe, sinon le créer
114 mkdir($dest, 0777, true);
115 }
116
105 if($image_data === false){ 117 if($image_data === false){
106 http_response_code(400); 118 http_response_code(400);
107 echo json_encode(['message' => "Erreur, le serveur n'a pas réussi à télécharger l'image."]); 119 echo json_encode(['message' => "Erreur, le serveur n'a pas réussi à télécharger l'image."]);
108 die; 120 die;
109 } 121 }
110 122
111 $local_path = 'images/' . uniqid() . '.jpg'; 123 $allowed_extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'tiff', 'tif'];
112 if(imagickCleanImage($image_data, $local_path)){ // recréer l’image pour la nettoyer 124 $url_path = parse_url($json['image_url'], PHP_URL_PATH);
125 $name = Security::secureFileName(pathinfo($url_path, PATHINFO_FILENAME));
126 $extension = strtolower(pathinfo($url_path, PATHINFO_EXTENSION));
127 if(!in_array($extension, $allowed_extensions) || $extension === 'jpg'){
128 $extension = 'jpeg';
129 }
130 $local_path = $dest . $name . '_' . uniqid() . '.' . $extension;
131
132 if(imagickCleanImage($image_data, $local_path, $extension)){ // recréer l’image pour la nettoyer
113 echo json_encode(['location' => $local_path]); // nouvelle adresse 133 echo json_encode(['location' => $local_path]); // nouvelle adresse
114 } 134 }
115 else{ 135 else{