From 97f60b3ea51166c4967b2ab6097cca5b1752493b Mon Sep 17 00:00:00 2001 From: Matthew Barbour Date: Wed, 12 Jun 2019 17:40:43 -0500 Subject: [PATCH] Better error handling for GD code --- core/imageboard/misc.php | 174 +++++++++++++++++++++++---------------- ext/rotate/main.php | 11 ++- 2 files changed, 113 insertions(+), 72 deletions(-) diff --git a/core/imageboard/misc.php b/core/imageboard/misc.php index 8374242a..f260efa6 100644 --- a/core/imageboard/misc.php +++ b/core/imageboard/misc.php @@ -345,82 +345,116 @@ function image_resize_gd(String $image_filename, array $info, int $new_width, in } $image = imagecreatefromstring(file_get_contents($image_filename)); - - if($image==false) { - throw new ImageResizeException("Could not load image: ".$image_filename); - } - $image_resized = imagecreatetruecolor($new_width, $new_height); + try { + if($image===false) { + throw new ImageResizeException("Could not load image: ".$image_filename); + } + if($image_resized===false) { + throw new ImageResizeException("Could not create output image with dimensions $new_width c $new_height "); + } - // Handle transparent images - switch($info[2]) { - case IMAGETYPE_GIF: - $transparency = imagecolortransparent($image); - $palletsize = imagecolorstotal($image); + // Handle transparent images + switch($info[2]) { + case IMAGETYPE_GIF: + $transparency = imagecolortransparent($image); + $palletsize = imagecolorstotal($image); - // If we have a specific transparent color - if ($transparency >= 0 && $transparency < $palletsize) { - // Get the original image's transparent color's RGB values - $transparent_color = imagecolorsforindex($image, $transparency); + // If we have a specific transparent color + if ($transparency >= 0 && $transparency < $palletsize) { + // Get the original image's transparent color's RGB values + $transparent_color = imagecolorsforindex($image, $transparency); - // Allocate the same color in the new image resource - $transparency = imagecolorallocate($image_resized, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']); + // Allocate the same color in the new image resource + $transparency = imagecolorallocate($image_resized, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']); + if($transparency===false) { + throw new ImageResizeException("Unable to allocate transparent color"); + } + + // Completely fill the background of the new image with allocated color. + if(imagefill($image_resized, 0, 0, $transparency)===false) { + throw new ImageResizeException("Unable to fill new image with transparent color"); + } - // Completely fill the background of the new image with allocated color. - imagefill($image_resized, 0, 0, $transparency); - - // Set the background color for new image to transparent - imagecolortransparent($image_resized, $transparency); + // Set the background color for new image to transparent + imagecolortransparent($image_resized, $transparency); + } + break; + case IMAGETYPE_PNG: + case IMAGETYPE_WEBP: + // + // More info here: http://stackoverflow.com/questions/279236/how-do-i-resize-pngs-with-transparency-in-php + // + if(imagealphablending($image_resized, false)===false) { + throw new ImageResizeException("Unable to disable image alpha blending"); + } + if(imagesavealpha($image_resized, true)===false) { + throw new ImageResizeException("Unable to enable image save alpha"); + } + $transparent_color = imagecolorallocatealpha($image_resized, 255, 255, 255, 127); + if($transparent_color===false) { + throw new ImageResizeException("Unable to allocate transparent color"); + } + if(imagefilledrectangle($image_resized, 0, 0, $new_width, $new_height, $transparent_color)===false) { + throw new ImageResizeException("Unable to fill new image with transparent color"); + } + break; + } + + // Actually resize the image. + if(imagecopyresampled( + $image_resized, + $image, + 0, + 0, + 0, + 0, + $new_width, + $new_height, + $width, + $height + )===false) { + throw new ImageResizeException("Unable to copy resized image data to new image"); } - break; - case IMAGETYPE_PNG: - case IMAGETYPE_WEBP: - // - // More info here: http://stackoverflow.com/questions/279236/how-do-i-resize-pngs-with-transparency-in-php - // - imagealphablending($image_resized, false); - imagesavealpha($image_resized, true); - $transparent_color = imagecolorallocatealpha($image_resized, 255, 255, 255, 127); - imagefilledrectangle($image_resized, 0, 0, $new_width, $new_height, $transparent_color); - break; - } - - // Actually resize the image. - imagecopyresampled( - $image_resized, - $image, - 0, - 0, - 0, - 0, - $new_width, - $new_height, - $width, - $height - ); - switch($output_type) { - case "bmp": - $result = imagebmp($image_resized, $output_filename, true); - break; - case "webp": - $result = imagewebp($image_resized, $output_filename, $output_quality); - break; - case "jpg": - case "jpeg": - $result = imagejpeg($image_resized, $output_filename, $output_quality); - break; - case "png": - $result = imagepng($image_resized, $output_filename, 9); - break; - case "gif": - $result = imagegif($image_resized, $output_filename); - break; - default: - throw new ImageResizeException("Failed to save the new image - Unsupported image type: $output_type"); + $result = false; + switch($output_type) { + case "bmp": + $result = imagebmp($image_resized, $output_filename, true); + break; + case "webp": + $result = imagewebp($image_resized, $output_filename, $output_quality); + break; + case "jpg": + case "jpeg": + $result = imagejpeg($image_resized, $output_filename, $output_quality); + break; + case "png": + $result = imagepng($image_resized, $output_filename, 9); + break; + case "gif": + $result = imagegif($image_resized, $output_filename); + break; + default: + throw new ImageResizeException("Failed to save the new image - Unsupported image type: $output_type"); + } + if($result==false) { + throw new ImageResizeException("Failed to save the new image, function returned false when saving type: $output_type"); + } + } finally { + imagedestroy($image); + imagedestroy($image_resized); } - if($result==false) { - throw new ImageResizeException("Failed to save the new image, function returned false when saving type: $output_type"); - } - imagedestroy($image_resized); } + +function is_animated_gif(String $image_filename) { + $isanigif = 0; + if (($fh = @fopen($image_filename, 'rb'))) { + //check if gif is animated (via http://www.php.net/manual/en/function.imagecreatefromgif.php#104473) + while (!feof($fh) && $isanigif < 2) { + $chunk = fread($fh, 1024 * 100); + $isanigif += preg_match_all('#\x00\x21\xF9\x04.{4}\x00(\x2C|\x21)#s', $chunk, $matches); + } + } + return ($isanigif == 0); +} \ No newline at end of file diff --git a/ext/rotate/main.php b/ext/rotate/main.php index 17a7762a..544139f2 100644 --- a/ext/rotate/main.php +++ b/ext/rotate/main.php @@ -171,8 +171,14 @@ class RotateImage extends Extension $background_color = imagecolorallocatealpha($image, 0, 0, 0, 127); break; } - + if($background_color===false) { + throw new ImageRotateException("Unable to allocate transparent color"); + } + $image_rotated = imagerotate($image, $deg, $background_color); + if($image_rotated===false) { + throw new ImageRotateException("Image rotate failed"); + } /* Temp storage while we rotate */ $tmp_filename = tempnam(ini_get('upload_tmp_dir'), 'shimmie_rotate'); @@ -181,6 +187,7 @@ class RotateImage extends Extension } /* Output to the same format as the original image */ + $result = false; switch ($info[2]) { case IMAGETYPE_GIF: $result = imagegif($image_rotated, $tmp_filename); break; case IMAGETYPE_JPEG: $result = imagejpeg($image_rotated, $tmp_filename); break; @@ -191,7 +198,7 @@ class RotateImage extends Extension throw new ImageRotateException("Unsupported image type."); } - if($result==false) { + if($result===false) { throw new ImageRotateException("Could not save image: ".$tmp_filename); }