From 694ece4a86a7beecc936c1377ec928ca957f8d70 Mon Sep 17 00:00:00 2001 From: polo Date: Thu, 19 Jun 2025 02:27:13 +0200 Subject: =?UTF-8?q?nom=20d'origine=20+=20uniqid=20+=20extension=20d'origin?= =?UTF-8?q?e=20dans=20une=20liste=20autoris=C3=A9e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/index.php | 69 +++++++++++++++++++++++++++++++++++++++----------------- 1 file 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 @@ readImageBlob($image_data); $imagick->stripImage(); // nettoyage métadonnées - $imagick->setImageFormat('jpeg'); - $imagick->setImageCompression(Imagick::COMPRESSION_JPEG); - $imagick->setImageCompressionQuality(85); // optionnel + $imagick->setImageFormat($format); + if($format === 'jpeg'){ + $imagick->setImageCompression(Imagick::COMPRESSION_JPEG); + $imagick->setImageCompressionQuality(85); // optionnel + } $imagick->writeImage($local_path); // enregistrement $imagick->clear(); $imagick->destroy(); return true; } - catch (Exception $e) { + catch(Exception $e){ return false; } } @@ -23,7 +25,7 @@ function curlDownloadImage(string $url, $maxRetries = 3, $timeout = 10): string| $attempt = 0; $imageData = false; - while($attempt < $maxRetries) { + while($attempt < $maxRetries){ $ch = curl_init($url); // instance de CurlHandle curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); @@ -34,7 +36,7 @@ function curlDownloadImage(string $url, $maxRetries = 3, $timeout = 10): string| $imageData = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); - $curlError = curl_error($ch); + //$curlError = curl_error($ch); curl_close($ch); @@ -49,6 +51,12 @@ function curlDownloadImage(string $url, $maxRetries = 3, $timeout = 10): string| return false; // échec après trois tentatives } +function sanitizeFileName(string $filename): string { + $filename = preg_replace('/[^a-zA-Z0-9_-]/', '_', $filename); // ne garder que les lettres, chiffres, tirets et underscores + $filename = preg_replace('/_+/', '_', $filename); // doublons d'underscores + return trim($filename, '_'); +} + if(isset($_GET['action']) && $_GET['action'] == 'editor_submit'){ // récupération des données $data = file_get_contents('php://input'); @@ -95,10 +103,16 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image'){ mkdir($dest, 0777, true); } - $file_path = 'images/' . uniqid() . '.jpg'; - if(imagickCleanImage(file_get_contents($file['tmp_name']), $file_path)){ // recréer l’image pour la nettoyer - $image_url = str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']); - echo json_encode(['location' => $image_url . $file_path]); // renvoyer l'URL de l'image téléchargée + $allowed_extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'tiff', 'tif']; + $name = sanitizeFileName(pathinfo($file['name'], PATHINFO_FILENAME)); + $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION)); + if(!in_array($extension, $allowed_extensions) || $extension === 'jpg'){ + $extension = 'jpeg'; + } + $file_path = $dest . $name . '_' . uniqid() . '.' . $extension; + + if(imagickCleanImage(file_get_contents($file['tmp_name']), $file_path, $extension)){ // recréer l’image pour la nettoyer + echo json_encode(['location' => $file_path]); // renvoyer l'URL de l'image téléchargée } else{ http_response_code(500); @@ -116,6 +130,11 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_url'){ if(isset($json['image_url'])){ $image_data = curlDownloadImage($json['image_url']); // téléchargement de l’image par le serveur avec cURL au lieu de file_get_contents + $dest = 'images/'; + + if(!is_dir($dest)) { // Vérifier si le répertoire existe, sinon le créer + mkdir($dest, 0777, true); + } if($image_data === false){ http_response_code(400); @@ -123,8 +142,16 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_url'){ die; } - $local_path = 'images/' . uniqid() . '.jpg'; - if(imagickCleanImage($image_data, $local_path)){ // recréer l’image pour la nettoyer + $allowed_extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'tiff', 'tif']; + $url_path = parse_url($json['image_url'], PHP_URL_PATH); + $name = sanitizeFileName(pathinfo($url_path, PATHINFO_FILENAME)); + $extension = strtolower(pathinfo($url_path, PATHINFO_EXTENSION)); + if(!in_array($extension, $allowed_extensions) || $extension === 'jpg'){ + $extension = 'jpeg'; + } + $local_path = $dest . $name . '_' . uniqid() . '.' . $extension; + + if(imagickCleanImage($image_data, $local_path, $extension)){ // recréer l’image pour la nettoyer echo json_encode(['location' => $local_path]); // nouvelle adresse } else{ @@ -173,7 +200,7 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_url'){ menubar: false, toolbar_mode: 'wrap', statusbar: false, - paste_data_images: true, + //paste_data_images: true, setup: function (editor) { editor.on('init', function () { editors[articleId] = editor; @@ -185,9 +212,9 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_url'){ document.querySelector(`#submit-${articleId}`).classList.remove('hidden'); }); editor.on('PastePreProcess', function (e){ // déclenchement au collage AVANT insertion dans l'éditeur - let parser = new DOMParser(); - let doc = parser.parseFromString(e.content, 'text/html'); - let images = doc.querySelectorAll('img'); + const parser = new DOMParser(); + const doc = parser.parseFromString(e.content, 'text/html'); + const images = doc.querySelectorAll('img'); let downloads_in_progress = []; @@ -195,11 +222,11 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_url'){ if(img.src.startsWith('file://')){ // détection d'images non insérables console.warn('Image locale non insérable dans tinymce :', img.src); img.outerHTML = '
' + - "Image locale non insérée. Pour insérer une image depuis LibreOffice, copiez l'image seule et recoller." + + "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." + '
'; } else if(img.src.startsWith('http')){ // détection d'images web - let promise = fetch('index.php?action=upload_image_url', { // promesse d'un fichier téléchargeable sur le serveur + const promise = fetch('index.php?action=upload_image_url', { // promesse d'un fichier téléchargeable sur le serveur method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ image_url: img.src }) @@ -211,7 +238,7 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_url'){ } }) .catch(error => { - console.error('Erreur lors de l’upload de l’image :', error); + console.error('Erreur lors de l’upload de l’image distante:', error); }); downloads_in_progress.push(promise); @@ -232,7 +259,7 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_url'){ } }); }, - // upload d'image + // upload d'image natif de tinymce avec le bouton "Insérer une image" images_upload_handler: (blobInfo, progress) => new Promise((resolve, reject) => { const formData = new FormData(); formData.append("file", blobInfo.blob()); -- cgit v1.2.3