diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ab58ea9570..68306298ab2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ - Fix bug where some messages could get malformed in an import from a MBOX file (#9510) - Fix invalid line break characters in multi-line text in Sieve scripts (#9543) - Fix bug where "with attachment" filter could fail on some fts engines (#9514) +- Fix bug where an unhandled exception was caused by an invalid image attachment (#9475) ## Release 1.6.7 diff --git a/program/lib/Roundcube/rcube_image.php b/program/lib/Roundcube/rcube_image.php index 9dbeb470398..2d320ae4bd3 100644 --- a/program/lib/Roundcube/rcube_image.php +++ b/program/lib/Roundcube/rcube_image.php @@ -211,81 +211,85 @@ public function resize($size, $filename = null, $browser_compat = false) // use GD extension if ($props['gd_type'] && $props['width'] > 0 && $props['height'] > 0) { - if ($props['gd_type'] == \IMAGETYPE_JPEG && function_exists('imagecreatefromjpeg')) { - $image = @imagecreatefromjpeg($this->image_file); - $type = 'jpg'; - } elseif ($props['gd_type'] == \IMAGETYPE_GIF && function_exists('imagecreatefromgif')) { - $image = @imagecreatefromgif($this->image_file); - $type = 'gif'; - } elseif ($props['gd_type'] == \IMAGETYPE_PNG && function_exists('imagecreatefrompng')) { - $image = @imagecreatefrompng($this->image_file); - $type = 'png'; - } else { - // @TODO: print error to the log? - return false; - } + try { + if ($props['gd_type'] == \IMAGETYPE_JPEG && function_exists('imagecreatefromjpeg')) { + $image = imagecreatefromjpeg($this->image_file); + $type = 'jpg'; + } elseif ($props['gd_type'] == \IMAGETYPE_GIF && function_exists('imagecreatefromgif')) { + $image = imagecreatefromgif($this->image_file); + $type = 'gif'; + } elseif ($props['gd_type'] == \IMAGETYPE_PNG && function_exists('imagecreatefrompng')) { + $image = imagecreatefrompng($this->image_file); + $type = 'png'; + } else { + // @TODO: print error to the log? + return false; + } - if ($image === false) { - return false; - } + if ($image === false) { + return false; + } - $scale = $size / max($props['width'], $props['height']); + $scale = $size / max($props['width'], $props['height']); - // Imagemagick resize is implemented in shrinking mode (see -resize argument above) - // we do the same here, if an image is smaller than specified size - // we do nothing but copy original file to destination file - if ($scale >= 1) { - $result = $this->image_file == $filename || copy($this->image_file, $filename); - } else { - $width = intval($props['width'] * $scale); - $height = intval($props['height'] * $scale); - $new_image = imagecreatetruecolor($width, $height); + // Imagemagick resize is implemented in shrinking mode (see -resize argument above) + // we do the same here, if an image is smaller than specified size + // we do nothing but copy original file to destination file + if ($scale >= 1) { + $result = $this->image_file == $filename || copy($this->image_file, $filename); + } else { + $width = intval($props['width'] * $scale); + $height = intval($props['height'] * $scale); + $new_image = imagecreatetruecolor($width, $height); - if ($new_image === false) { - return false; - } + if ($new_image === false) { + return false; + } - // Fix transparency of gif/png image - if ($props['gd_type'] != \IMAGETYPE_JPEG) { - imagealphablending($new_image, false); - imagesavealpha($new_image, true); - $transparent = imagecolorallocatealpha($new_image, 255, 255, 255, 127); - imagefilledrectangle($new_image, 0, 0, $width, $height, $transparent); - } + // Fix transparency of gif/png image + if ($props['gd_type'] != \IMAGETYPE_JPEG) { + imagealphablending($new_image, false); + imagesavealpha($new_image, true); + $transparent = imagecolorallocatealpha($new_image, 255, 255, 255, 127); + imagefilledrectangle($new_image, 0, 0, $width, $height, $transparent); + } - imagecopyresampled($new_image, $image, 0, 0, 0, 0, $width, $height, $props['width'], $props['height']); - $image = $new_image; - - // fix orientation of image if EXIF data exists and specifies orientation (GD strips the EXIF data) - if ($this->image_file && $type == 'jpg' && function_exists('exif_read_data')) { - $exif = @exif_read_data($this->image_file); - if ($exif && !empty($exif['Orientation'])) { - switch ($exif['Orientation']) { - case 3: - $image = imagerotate($image, 180, 0); - break; - case 6: - $image = imagerotate($image, -90, 0); - break; - case 8: - $image = imagerotate($image, 90, 0); - break; + imagecopyresampled($new_image, $image, 0, 0, 0, 0, $width, $height, $props['width'], $props['height']); + $image = $new_image; + + // fix orientation of image if EXIF data exists and specifies orientation (GD strips the EXIF data) + if ($this->image_file && $type == 'jpg' && function_exists('exif_read_data')) { + $exif = @exif_read_data($this->image_file); + if ($exif && !empty($exif['Orientation'])) { + switch ($exif['Orientation']) { + case 3: + $image = imagerotate($image, 180, 0); + break; + case 6: + $image = imagerotate($image, -90, 0); + break; + case 8: + $image = imagerotate($image, 90, 0); + break; + } } } - } - if ($props['gd_type'] == \IMAGETYPE_JPEG) { - $result = imagejpeg($image, $filename, 75); - } elseif ($props['gd_type'] == \IMAGETYPE_GIF) { - $result = imagegif($image, $filename); - } elseif ($props['gd_type'] == \IMAGETYPE_PNG) { - $result = imagepng($image, $filename, 6, \PNG_ALL_FILTERS); + if ($props['gd_type'] == \IMAGETYPE_JPEG) { + $result = imagejpeg($image, $filename, 75); + } elseif ($props['gd_type'] == \IMAGETYPE_GIF) { + $result = imagegif($image, $filename); + } elseif ($props['gd_type'] == \IMAGETYPE_PNG) { + $result = imagepng($image, $filename, 6, \PNG_ALL_FILTERS); + } } - } - if ($result) { - @chmod($filename, 0600); - return $type; + if ($result) { + @chmod($filename, 0600); + return $type; + } + } catch (Throwable $e) { + rcube::raise_error($e, true, false); } } @@ -360,25 +364,29 @@ public function convert($type, $filename = null) } if ($props['gd_type']) { - if ($props['gd_type'] == \IMAGETYPE_JPEG && function_exists('imagecreatefromjpeg')) { - $image = imagecreatefromjpeg($this->image_file); - } elseif ($props['gd_type'] == \IMAGETYPE_GIF && function_exists('imagecreatefromgif')) { - $image = imagecreatefromgif($this->image_file); - } elseif ($props['gd_type'] == \IMAGETYPE_PNG && function_exists('imagecreatefrompng')) { - $image = imagecreatefrompng($this->image_file); - } elseif ($props['gd_type'] == \IMAGETYPE_WEBP && function_exists('imagecreatefromwebp')) { - $image = imagecreatefromwebp($this->image_file); - } else { - // @TODO: print error to the log? - return false; - } + try { + if ($props['gd_type'] == \IMAGETYPE_JPEG && function_exists('imagecreatefromjpeg')) { + $image = imagecreatefromjpeg($this->image_file); + } elseif ($props['gd_type'] == \IMAGETYPE_GIF && function_exists('imagecreatefromgif')) { + $image = imagecreatefromgif($this->image_file); + } elseif ($props['gd_type'] == \IMAGETYPE_PNG && function_exists('imagecreatefrompng')) { + $image = imagecreatefrompng($this->image_file); + } elseif ($props['gd_type'] == \IMAGETYPE_WEBP && function_exists('imagecreatefromwebp')) { + $image = imagecreatefromwebp($this->image_file); + } else { + // @TODO: print error to the log? + return false; + } - if ($type == self::TYPE_JPG) { - $result = imagejpeg($image, $filename, 75); - } elseif ($type == self::TYPE_GIF) { - $result = imagegif($image, $filename); - } elseif ($type == self::TYPE_PNG) { - $result = imagepng($image, $filename, 6, \PNG_ALL_FILTERS); + if ($type == self::TYPE_JPG) { + $result = imagejpeg($image, $filename, 75); + } elseif ($type == self::TYPE_GIF) { + $result = imagegif($image, $filename); + } elseif ($type == self::TYPE_PNG) { + $result = imagepng($image, $filename, 6, \PNG_ALL_FILTERS); + } + } catch (Throwable $e) { + rcube::raise_error($e, true, false); } if (!empty($result)) {