From 9e2350cbad418b283fa2cf3037ed51a732d18bdf Mon Sep 17 00:00:00 2001
From: Cerdic <cedric@yterium.com>
Date: Sun, 7 May 2006 12:00:19 +0000
Subject: [PATCH] #146 : pour eviter le plantage sur un calcul de vignette avec
 GD2 et une limite memoire trop basse par rapport a la taille de l'image : -
 on teste la quantite de memoire disponible si la fonction memory_get_usage
 est disponible - on compare le nombre de pixels de l'image source par rapport
 a la constante _IMG_GD_MAX_PIXELS qui permet de configurer manuellement une
 limite a la taille des images dont une vignette est calculee Si le calcul de
 vignette n'est pas possible, on ne renvoi rien (image source resizee cote
 client)

---
 ecrire/inc/logos.php | 89 ++++++++++++++++++++++++++------------------
 ecrire/inc/utils.php |  2 +
 2 files changed, 55 insertions(+), 36 deletions(-)

diff --git a/ecrire/inc/logos.php b/ecrire/inc/logos.php
index 898e52b93d..24eda7b401 100644
--- a/ecrire/inc/logos.php
+++ b/ecrire/inc/logos.php
@@ -306,21 +306,11 @@ function creer_vignette($image, $maxWidth, $maxHeight, $format, $destdir, $destf
 		}
 		// gd ou gd2
 		else if ($process == 'gd1' OR $process == 'gd2') {
-
-			// Recuperer l'image d'origine
-			if ($format == "jpg") {
-				$srcImage = @ImageCreateFromJPEG($image);
-			}
-			else if ($format == "gif"){
-				$srcImage = @ImageCreateFromGIF($image);
-			}
-			else if ($format == "png"){
-				$srcImage = @ImageCreateFromPNG($image);
-			}
-			if (!$srcImage) {
-				spip_log("echec gd1/gd2");
+			if (_IMG_GD_MAX_PIXELS && $srcWidth*$srcHeight>_IMG_GD_MAX_PIXELS){
+				spip_log("vignette gd1/gd2 impossible : ".$srcWidth*$srcHeight."pixels");
 				return;
 			}
+
 			// Choisir le format destination
 			// - on sauve de preference en JPEG (meilleure compression)
 			// - pour le GIF : les GD recentes peuvent le lire mais pas l'ecrire
@@ -340,31 +330,57 @@ function creer_vignette($image, $maxWidth, $maxHeight, $format, $destdir, $destf
 				return;
 			}
 
-			// Initialisation de l'image destination
-			if ($process == 'gd2' AND $destFormat != "gif")
-				$destImage = ImageCreateTrueColor($destWidth, $destHeight);
-			if (!$destImage)
-				$destImage = ImageCreate($destWidth, $destHeight);
-
-			// Recopie de l'image d'origine avec adaptation de la taille
-			$ok = false;
-			if (($process == 'gd2') AND function_exists('ImageCopyResampled')) {
-				if ($format == "gif") {
-					// Si un GIF est transparent,
-					// fabriquer un PNG transparent 
-					$transp = imagecolortransparent($srcImage);
-					if ($transp > 0) $destFormat = "png";
+			$memoryNeeded = round(($srcsize[0] * $srcsize[1] * $srcsize['bits'] * $srcsize['channels'] / 8 + 65536) * 1.65); 
+			#spip_log("GD : memory need $memoryNeeded");
+			#if (function_exists('memory_get_usage'))
+				#spip_log("GD : memory usage ".memory_get_usage());
+			#spip_log("GD : memory_limit ".ini_get('memory_limit'));
+			if (function_exists('memory_get_usage') && memory_get_usage() + $memoryNeeded > (integer) ini_get('memory_limit') * 1048576){
+				spip_log("vignette gd1/gd2 impossible : memoire insuffisante $memoryNeeded necessaire");
+				return;
+			}
+			else{ 
+				// Recuperer l'image d'origine 
+				if ($format == "jpg") { 
+					$srcImage = @ImageCreateFromJPEG($image);
+				}
+				else if ($format == "gif"){ 
+					$srcImage = @ImageCreateFromGIF($image); 				
 				}
-				if ($destFormat == "png") {
-					// Conserver la transparence
-					if (function_exists("imageAntiAlias")) imageAntiAlias($destImage,true);
-					@imagealphablending($destImage, false);
-         			@imagesavealpha($destImage,true);
+				else if ($format == "png"){ 
+					$srcImage = @ImageCreateFromPNG($image); 
+				} 
+				if (!$srcImage) { 
+					spip_log("echec gd1/gd2"); 
+					return; 
+				} 
+
+				// Initialisation de l'image destination 
+ 				if ($process == 'gd2' AND $destFormat != "gif") 
+					$destImage = ImageCreateTrueColor($destWidth, $destHeight); 
+				if (!$destImage) 
+					$destImage = ImageCreate($destWidth, $destHeight); 
+
+				// Recopie de l'image d'origine avec adaptation de la taille 
+				$ok = false; 
+				if (($process == 'gd2') AND function_exists('ImageCopyResampled')) { 
+					if ($format == "gif") { 
+						// Si un GIF est transparent, 
+						// fabriquer un PNG transparent  
+						$transp = imagecolortransparent($srcImage); 
+						if ($transp > 0) $destFormat = "png"; 
+					}
+					if ($destFormat == "png") { 
+						// Conserver la transparence 
+						if (function_exists("imageAntiAlias")) imageAntiAlias($destImage,true); 
+						@imagealphablending($destImage, false); 
+						@imagesavealpha($destImage,true); 
+					}
+					$ok = @ImageCopyResampled($destImage, $srcImage, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight);
 				}
-				$ok = @ImageCopyResampled($destImage, $srcImage, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight);
+				if (!$ok)
+					$ok = ImageCopyResized($destImage, $srcImage, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight);
 			}
-			if (!$ok)
-				$ok = ImageCopyResized($destImage, $srcImage, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight);
 
 			// Sauvegarde de l'image destination
 			$vignette = "$destination.$destFormat";
@@ -376,7 +392,8 @@ function creer_vignette($image, $maxWidth, $maxHeight, $format, $destdir, $destf
 			else if ($destFormat == "png")
 				ImagePNG($destImage, $vignette);
 
-			ImageDestroy($srcImage);
+			if ($srcImage)
+				ImageDestroy($srcImage);
 			ImageDestroy($destImage);
 		}
 	}
diff --git a/ecrire/inc/utils.php b/ecrire/inc/utils.php
index dad75a7414..10e28e129b 100644
--- a/ecrire/inc/utils.php
+++ b/ecrire/inc/utils.php
@@ -883,6 +883,8 @@ function spip_initialisation() {
 	define('_IMG_MAX_WIDTH', 0); # largeur en pixels
 	define('_IMG_MAX_HEIGHT', 0); # hauteur en pixels
 
+	define('_IMG_GD_MAX_PIXELS', 0); # nombre de pixels maxi pour calcul de la vignette avec gd
+	
 	// Le fichier de connexion a la base de donnees
 	define('_FILE_CONNECT_INS', (_DIR_RESTREINT . "inc_connect"));
 	define('_FILE_CONNECT',
-- 
GitLab