summaryrefslogtreecommitdiff
path: root/public/index.php
diff options
context:
space:
mode:
Diffstat (limited to 'public/index.php')
-rw-r--r--public/index.php69
1 files changed, 48 insertions, 21 deletions
diff --git a/public/index.php b/public/index.php
index c423162..5f5d904 100644
--- a/public/index.php
+++ b/public/index.php
@@ -1,19 +1,21 @@
1<?php 1<?php
2function imagickCleanImage(string $image_data, string $local_path): bool // "string" parce que file_get_contents... 2function imagickCleanImage(string $image_data, string $local_path, string $format = 'jpeg'): bool // "string" parce que file_get_contents...
3{ 3{
4 try{ 4 try{
5 $imagick = new Imagick(); 5 $imagick = new Imagick();
6 $imagick->readImageBlob($image_data); 6 $imagick->readImageBlob($image_data);
7 $imagick->stripImage(); // nettoyage métadonnées 7 $imagick->stripImage(); // nettoyage métadonnées
8 $imagick->setImageFormat('jpeg'); 8 $imagick->setImageFormat($format);
9 $imagick->setImageCompression(Imagick::COMPRESSION_JPEG); 9 if($format === 'jpeg'){
10 $imagick->setImageCompressionQuality(85); // optionnel 10 $imagick->setImageCompression(Imagick::COMPRESSION_JPEG);
11 $imagick->setImageCompressionQuality(85); // optionnel
12 }
11 $imagick->writeImage($local_path); // enregistrement 13 $imagick->writeImage($local_path); // enregistrement
12 $imagick->clear(); 14 $imagick->clear();
13 $imagick->destroy(); 15 $imagick->destroy();
14 return true; 16 return true;
15 } 17 }
16 catch (Exception $e) { 18 catch(Exception $e){
17 return false; 19 return false;
18 } 20 }
19} 21}
@@ -23,7 +25,7 @@ function curlDownloadImage(string $url, $maxRetries = 3, $timeout = 10): string|
23 $attempt = 0; 25 $attempt = 0;
24 $imageData = false; 26 $imageData = false;
25 27
26 while($attempt < $maxRetries) { 28 while($attempt < $maxRetries){
27 $ch = curl_init($url); // instance de CurlHandle 29 $ch = curl_init($url); // instance de CurlHandle
28 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 30 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
29 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 31 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
@@ -34,7 +36,7 @@ function curlDownloadImage(string $url, $maxRetries = 3, $timeout = 10): string|
34 36
35 $imageData = curl_exec($ch); 37 $imageData = curl_exec($ch);
36 $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); 38 $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
37 $curlError = curl_error($ch); 39 //$curlError = curl_error($ch);
38 40
39 curl_close($ch); 41 curl_close($ch);
40 42
@@ -49,6 +51,12 @@ function curlDownloadImage(string $url, $maxRetries = 3, $timeout = 10): string|
49 return false; // échec après trois tentatives 51 return false; // échec après trois tentatives
50} 52}
51 53
54function sanitizeFileName(string $filename): string {
55 $filename = preg_replace('/[^a-zA-Z0-9_-]/', '_', $filename); // ne garder que les lettres, chiffres, tirets et underscores
56 $filename = preg_replace('/_+/', '_', $filename); // doublons d'underscores
57 return trim($filename, '_');
58}
59
52if(isset($_GET['action']) && $_GET['action'] == 'editor_submit'){ 60if(isset($_GET['action']) && $_GET['action'] == 'editor_submit'){
53 // récupération des données 61 // récupération des données
54 $data = file_get_contents('php://input'); 62 $data = file_get_contents('php://input');
@@ -95,10 +103,16 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image'){
95 mkdir($dest, 0777, true); 103 mkdir($dest, 0777, true);
96 } 104 }
97 105
98 $file_path = 'images/' . uniqid() . '.jpg'; 106 $allowed_extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'tiff', 'tif'];
99 if(imagickCleanImage(file_get_contents($file['tmp_name']), $file_path)){ // recréer l’image pour la nettoyer 107 $name = sanitizeFileName(pathinfo($file['name'], PATHINFO_FILENAME));
100 $image_url = str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']); 108 $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
101 echo json_encode(['location' => $image_url . $file_path]); // renvoyer l'URL de l'image téléchargée 109 if(!in_array($extension, $allowed_extensions) || $extension === 'jpg'){
110 $extension = 'jpeg';
111 }
112 $file_path = $dest . $name . '_' . uniqid() . '.' . $extension;
113
114 if(imagickCleanImage(file_get_contents($file['tmp_name']), $file_path, $extension)){ // recréer l’image pour la nettoyer
115 echo json_encode(['location' => $file_path]); // renvoyer l'URL de l'image téléchargée
102 } 116 }
103 else{ 117 else{
104 http_response_code(500); 118 http_response_code(500);
@@ -116,6 +130,11 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_url'){
116 130
117 if(isset($json['image_url'])){ 131 if(isset($json['image_url'])){
118 $image_data = curlDownloadImage($json['image_url']); // téléchargement de l’image par le serveur avec cURL au lieu de file_get_contents 132 $image_data = curlDownloadImage($json['image_url']); // téléchargement de l’image par le serveur avec cURL au lieu de file_get_contents
133 $dest = 'images/';
134
135 if(!is_dir($dest)) { // Vérifier si le répertoire existe, sinon le créer
136 mkdir($dest, 0777, true);
137 }
119 138
120 if($image_data === false){ 139 if($image_data === false){
121 http_response_code(400); 140 http_response_code(400);
@@ -123,8 +142,16 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_url'){
123 die; 142 die;
124 } 143 }
125 144
126 $local_path = 'images/' . uniqid() . '.jpg'; 145 $allowed_extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'tiff', 'tif'];
127 if(imagickCleanImage($image_data, $local_path)){ // recréer l’image pour la nettoyer 146 $url_path = parse_url($json['image_url'], PHP_URL_PATH);
147 $name = sanitizeFileName(pathinfo($url_path, PATHINFO_FILENAME));
148 $extension = strtolower(pathinfo($url_path, PATHINFO_EXTENSION));
149 if(!in_array($extension, $allowed_extensions) || $extension === 'jpg'){
150 $extension = 'jpeg';
151 }
152 $local_path = $dest . $name . '_' . uniqid() . '.' . $extension;
153
154 if(imagickCleanImage($image_data, $local_path, $extension)){ // recréer l’image pour la nettoyer
128 echo json_encode(['location' => $local_path]); // nouvelle adresse 155 echo json_encode(['location' => $local_path]); // nouvelle adresse
129 } 156 }
130 else{ 157 else{
@@ -173,7 +200,7 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_url'){
173 menubar: false, 200 menubar: false,
174 toolbar_mode: 'wrap', 201 toolbar_mode: 'wrap',
175 statusbar: false, 202 statusbar: false,
176 paste_data_images: true, 203 //paste_data_images: true,
177 setup: function (editor) { 204 setup: function (editor) {
178 editor.on('init', function () { 205 editor.on('init', function () {
179 editors[articleId] = editor; 206 editors[articleId] = editor;
@@ -185,9 +212,9 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_url'){
185 document.querySelector(`#submit-${articleId}`).classList.remove('hidden'); 212 document.querySelector(`#submit-${articleId}`).classList.remove('hidden');
186 }); 213 });
187 editor.on('PastePreProcess', function (e){ // déclenchement au collage AVANT insertion dans l'éditeur 214 editor.on('PastePreProcess', function (e){ // déclenchement au collage AVANT insertion dans l'éditeur
188 let parser = new DOMParser(); 215 const parser = new DOMParser();
189 let doc = parser.parseFromString(e.content, 'text/html'); 216 const doc = parser.parseFromString(e.content, 'text/html');
190 let images = doc.querySelectorAll('img'); 217 const images = doc.querySelectorAll('img');
191 218
192 let downloads_in_progress = []; 219 let downloads_in_progress = [];
193 220
@@ -195,11 +222,11 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_url'){
195 if(img.src.startsWith('file://')){ // détection d'images non insérables 222 if(img.src.startsWith('file://')){ // détection d'images non insérables
196 console.warn('Image locale non insérable dans tinymce :', img.src); 223 console.warn('Image locale non insérable dans tinymce :', img.src);
197 img.outerHTML = '<div style="border:1px solid red; padding:10px; margin:5px 0; background-color:#ffe6e6; color:#a94442; font-size:14px;">' + 224 img.outerHTML = '<div style="border:1px solid red; padding:10px; margin:5px 0; background-color:#ffe6e6; color:#a94442; font-size:14px;">' +
198 "Image locale non insérée. Pour insérer une image depuis LibreOffice, copiez l'image seule et recoller." + 225 "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." +
199 '</div>'; 226 '</div>';
200 } 227 }
201 else if(img.src.startsWith('http')){ // détection d'images web 228 else if(img.src.startsWith('http')){ // détection d'images web
202 let promise = fetch('index.php?action=upload_image_url', { // promesse d'un fichier téléchargeable sur le serveur 229 const promise = fetch('index.php?action=upload_image_url', { // promesse d'un fichier téléchargeable sur le serveur
203 method: 'POST', 230 method: 'POST',
204 headers: { 'Content-Type': 'application/json' }, 231 headers: { 'Content-Type': 'application/json' },
205 body: JSON.stringify({ image_url: img.src }) 232 body: JSON.stringify({ image_url: img.src })
@@ -211,7 +238,7 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_url'){
211 } 238 }
212 }) 239 })
213 .catch(error => { 240 .catch(error => {
214 console.error('Erreur lors de l’upload de l’image :', error); 241 console.error('Erreur lors de l’upload de l’image distante:', error);
215 }); 242 });
216 243
217 downloads_in_progress.push(promise); 244 downloads_in_progress.push(promise);
@@ -232,7 +259,7 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_url'){
232 } 259 }
233 }); 260 });
234 }, 261 },
235 // upload d'image 262 // upload d'image natif de tinymce avec le bouton "Insérer une image"
236 images_upload_handler: (blobInfo, progress) => new Promise((resolve, reject) => { 263 images_upload_handler: (blobInfo, progress) => new Promise((resolve, reject) => {
237 const formData = new FormData(); 264 const formData = new FormData();
238 formData.append("file", blobInfo.blob()); 265 formData.append("file", blobInfo.blob());