|
|
|
|
@ -46,6 +46,10 @@ use OCP\IImage; |
|
|
|
|
* Class for basic image manipulation |
|
|
|
|
*/ |
|
|
|
|
class OC_Image implements \OCP\IImage { |
|
|
|
|
|
|
|
|
|
// Default memory limit for images to load (128 MBytes). |
|
|
|
|
protected const DEFAULT_MEMORY_LIMIT = 128; |
|
|
|
|
|
|
|
|
|
/** @var false|resource|\GdImage */ |
|
|
|
|
protected $resource = false; // tmp resource. |
|
|
|
|
/** @var int */ |
|
|
|
|
@ -563,6 +567,71 @@ class OC_Image implements \OCP\IImage { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Check if allocating an image with the given size is allowed. |
|
|
|
|
* |
|
|
|
|
* @param int $width The image width. |
|
|
|
|
* @param int $height The image height. |
|
|
|
|
* @return bool true if allocating is allowed, false otherwise |
|
|
|
|
*/ |
|
|
|
|
private function checkImageMemory($width, $height) { |
|
|
|
|
$memory_limit = $this->config->getSystemValueInt('preview_max_memory', self::DEFAULT_MEMORY_LIMIT); |
|
|
|
|
if ($memory_limit < 0) { |
|
|
|
|
// Not limited. |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Assume 32 bits per pixel. |
|
|
|
|
if ($width * $height * 4 > $memory_limit * 1024 * 1024) { |
|
|
|
|
$this->logger->debug('Image size of ' . $width . 'x' . $height . ' would exceed allowed memory limit of ' . $memory_limit); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Check if loading an image file from the given path is allowed. |
|
|
|
|
* |
|
|
|
|
* @param string $path The path to a local file. |
|
|
|
|
* @return bool true if allocating is allowed, false otherwise |
|
|
|
|
*/ |
|
|
|
|
private function checkImageSize($path) { |
|
|
|
|
$size = getimagesize($path); |
|
|
|
|
if (!$size) { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
$width = $size[0]; |
|
|
|
|
$height = $size[1]; |
|
|
|
|
if (!$this->checkImageMemory($width, $height)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Check if loading an image from the given data is allowed. |
|
|
|
|
* |
|
|
|
|
* @param string $data A string of image data as read from a file. |
|
|
|
|
* @return bool true if allocating is allowed, false otherwise |
|
|
|
|
*/ |
|
|
|
|
private function checkImageDataSize($data) { |
|
|
|
|
$size = getimagesizefromstring($data); |
|
|
|
|
if (!$size) { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
$width = $size[0]; |
|
|
|
|
$height = $size[1]; |
|
|
|
|
if (!$this->checkImageMemory($width, $height)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Loads an image from a local file. |
|
|
|
|
* |
|
|
|
|
@ -578,6 +647,9 @@ class OC_Image implements \OCP\IImage { |
|
|
|
|
switch ($iType) { |
|
|
|
|
case IMAGETYPE_GIF: |
|
|
|
|
if (imagetypes() & IMG_GIF) { |
|
|
|
|
if (!$this->checkImageSize($imagePath)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
$this->resource = imagecreatefromgif($imagePath); |
|
|
|
|
if ($this->resource) { |
|
|
|
|
// Preserve transparency |
|
|
|
|
@ -592,6 +664,9 @@ class OC_Image implements \OCP\IImage { |
|
|
|
|
break; |
|
|
|
|
case IMAGETYPE_JPEG: |
|
|
|
|
if (imagetypes() & IMG_JPG) { |
|
|
|
|
if (!$this->checkImageSize($imagePath)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
if (getimagesize($imagePath) !== false) { |
|
|
|
|
$this->resource = @imagecreatefromjpeg($imagePath); |
|
|
|
|
} else { |
|
|
|
|
@ -603,6 +678,9 @@ class OC_Image implements \OCP\IImage { |
|
|
|
|
break; |
|
|
|
|
case IMAGETYPE_PNG: |
|
|
|
|
if (imagetypes() & IMG_PNG) { |
|
|
|
|
if (!$this->checkImageSize($imagePath)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
$this->resource = @imagecreatefrompng($imagePath); |
|
|
|
|
if ($this->resource) { |
|
|
|
|
// Preserve transparency |
|
|
|
|
@ -617,6 +695,9 @@ class OC_Image implements \OCP\IImage { |
|
|
|
|
break; |
|
|
|
|
case IMAGETYPE_XBM: |
|
|
|
|
if (imagetypes() & IMG_XPM) { |
|
|
|
|
if (!$this->checkImageSize($imagePath)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
$this->resource = @imagecreatefromxbm($imagePath); |
|
|
|
|
} else { |
|
|
|
|
$this->logger->debug('OC_Image->loadFromFile, XBM/XPM images not supported: ' . $imagePath, ['app' => 'core']); |
|
|
|
|
@ -624,6 +705,9 @@ class OC_Image implements \OCP\IImage { |
|
|
|
|
break; |
|
|
|
|
case IMAGETYPE_WBMP: |
|
|
|
|
if (imagetypes() & IMG_WBMP) { |
|
|
|
|
if (!$this->checkImageSize($imagePath)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
$this->resource = @imagecreatefromwbmp($imagePath); |
|
|
|
|
} else { |
|
|
|
|
$this->logger->debug('OC_Image->loadFromFile, WBMP images not supported: ' . $imagePath, ['app' => 'core']); |
|
|
|
|
@ -634,6 +718,9 @@ class OC_Image implements \OCP\IImage { |
|
|
|
|
break; |
|
|
|
|
case IMAGETYPE_WEBP: |
|
|
|
|
if (imagetypes() & IMG_WEBP) { |
|
|
|
|
if (!$this->checkImageSize($imagePath)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
$this->resource = @imagecreatefromwebp($imagePath); |
|
|
|
|
} else { |
|
|
|
|
$this->logger->debug('OC_Image->loadFromFile, webp images not supported: ' . $imagePath, ['app' => 'core']); |
|
|
|
|
@ -666,7 +753,11 @@ class OC_Image implements \OCP\IImage { |
|
|
|
|
default: |
|
|
|
|
|
|
|
|
|
// this is mostly file created from encrypted file |
|
|
|
|
$this->resource = imagecreatefromstring(file_get_contents($imagePath)); |
|
|
|
|
$data = file_get_contents($imagePath); |
|
|
|
|
if (!$this->checkImageDataSize($data)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
$this->resource = imagecreatefromstring($data); |
|
|
|
|
$iType = IMAGETYPE_PNG; |
|
|
|
|
$this->logger->debug('OC_Image->loadFromFile, Default', ['app' => 'core']); |
|
|
|
|
break; |
|
|
|
|
@ -689,6 +780,9 @@ class OC_Image implements \OCP\IImage { |
|
|
|
|
if (!is_string($str)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
if (!$this->checkImageDataSize($str)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
$this->resource = @imagecreatefromstring($str); |
|
|
|
|
if ($this->fileInfo) { |
|
|
|
|
$this->mimeType = $this->fileInfo->buffer($str); |
|
|
|
|
@ -717,6 +811,9 @@ class OC_Image implements \OCP\IImage { |
|
|
|
|
} |
|
|
|
|
$data = base64_decode($str); |
|
|
|
|
if ($data) { // try to load from string data |
|
|
|
|
if (!$this->checkImageDataSize($data)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
$this->resource = @imagecreatefromstring($data); |
|
|
|
|
if ($this->fileInfo) { |
|
|
|
|
$this->mimeType = $this->fileInfo->buffer($data); |
|
|
|
|
@ -793,6 +890,10 @@ class OC_Image implements \OCP\IImage { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (!$this->checkImageMemory($meta['width'], $meta['height'])) { |
|
|
|
|
fclose($fh); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
// create gd image |
|
|
|
|
$im = imagecreatetruecolor($meta['width'], $meta['height']); |
|
|
|
|
if ($im == false) { |
|
|
|
|
|