X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FUtil%2FImages.php;h=eb1e8c4375a491ca9f2ca7107082e52194cd5199;hb=fe442683efb8b75394d7df041716c47c81b05fbc;hp=6471ed526bdbcc3e7733b4c8abf574262774bfd8;hpb=01640a7045e146759bc936dd499ac27738b78940;p=friendica.git diff --git a/src/Util/Images.php b/src/Util/Images.php index 6471ed526b..eb1e8c4375 100644 --- a/src/Util/Images.php +++ b/src/Util/Images.php @@ -1,6 +1,6 @@ 'JPG', + 'image/jpg' => 'JPG', 'image/png' => 'PNG', - 'image/gif' => 'GIF' + 'image/gif' => 'GIF', ]; + } - return $m; + /** + * Return file extension for MIME type + * + * @param string $mimetype MIME type + * @return string File extension for MIME type + */ + public static function getExtensionByMimeType(string $mimetype): string + { + switch ($mimetype) { + case 'image/png': + $imagetype = IMAGETYPE_PNG; + break; + + case 'image/gif': + $imagetype = IMAGETYPE_GIF; + break; + + case 'image/jpeg': + case 'image/jpg': + $imagetype = IMAGETYPE_JPEG; + break; + + default: // Unknown type must be a blob then + return 'blob'; + break; + } + + return image_type_to_extension($imagetype); } /** @@ -52,11 +81,13 @@ class Images * * @return array */ - public static function supportedTypes() + public static function supportedTypes(): array { $types = [ - 'image/jpeg' => 'jpg' + 'image/jpeg' => 'jpg', + 'image/jpg' => 'jpg', ]; + if (class_exists('Imagick')) { // Imagick::queryFormats won't help us a lot there... // At least, not yet, other parts of friendica uses this array @@ -74,68 +105,85 @@ class Images } /** - * Guess image mimetype from filename or from Content-Type header + * Fetch image mimetype from the image data or guessing from the file name * - * @param string $filename Image filename - * @param boolean $fromcurl Check Content-Type header from curl request - * @param string $header passed headers to take into account + * @param string $image_data Image data + * @param string $filename File name (for guessing the type via the extension) + * @param string $default Default MIME type + * @return string MIME type + * @throws \Exception + */ + public static function getMimeTypeByData(string $image_data, string $filename = '', string $default = ''): string + { + if (substr($default, 0, 6) == 'image/') { + Logger::info('Using default mime type', ['filename' => $filename, 'mime' => $default]); + return $default; + } + + $image = @getimagesizefromstring($image_data); + if (!empty($image['mime'])) { + Logger::info('Mime type detected via data', ['filename' => $filename, 'default' => $default, 'mime' => $image['mime']]); + return $image['mime']; + } + + return self::guessTypeByExtension($filename); + } + + /** + * Fetch image mimetype from the image data or guessing from the file name * - * @return string|null + * @param string $sourcefile Source file of the image + * @param string $filename File name (for guessing the type via the extension) + * @param string $default default MIME type + * @return string MIME type * @throws \Exception */ - public static function guessType($filename, $fromcurl = false, $header = '') + public static function getMimeTypeBySource(string $sourcefile, string $filename = '', string $default = ''): string { - Logger::info('Image: guessType: ' . $filename . ($fromcurl ? ' from curl headers' : '')); - $type = null; - if ($fromcurl) { - $headers = []; - $h = explode("\n", $header); - foreach ($h as $l) { - $data = array_map("trim", explode(":", trim($l), 2)); - if (count($data) > 1) { - list($k, $v) = $data; - $headers[$k] = $v; - } - } + if (substr($default, 0, 6) == 'image/') { + Logger::info('Using default mime type', ['filename' => $filename, 'mime' => $default]); + return $default; + } - if (array_key_exists('Content-Type', $headers)) { - $type = $headers['Content-Type']; - } + $image = @getimagesize($sourcefile); + if (!empty($image['mime'])) { + Logger::info('Mime type detected via file', ['filename' => $filename, 'default' => $default, 'image' => $image]); + return $image['mime']; } - if (is_null($type)) { - // Guessing from extension? Isn't that... dangerous? - if (class_exists('Imagick') && file_exists($filename) && is_readable($filename)) { - /** - * Well, this not much better, - * but at least it comes from the data inside the image, - * we won't be tricked by a manipulated extension - */ - $image = new Imagick($filename); - $type = $image->getImageMimeType(); - } else { - $ext = pathinfo($filename, PATHINFO_EXTENSION); - $types = self::supportedTypes(); - $type = 'image/jpeg'; - foreach ($types as $m => $e) { - if ($ext == $e) { - $type = $m; - } - } + return self::guessTypeByExtension($filename); + } + + /** + * Guess image MIME type from the filename's extension + * + * @param string $filename Image filename + * @return string Guessed MIME type by extension + * @throws \Exception + */ + public static function guessTypeByExtension(string $filename): string + { + $ext = pathinfo(parse_url($filename, PHP_URL_PATH), PATHINFO_EXTENSION); + $types = self::supportedTypes(); + $type = 'image/jpeg'; + foreach ($types as $m => $e) { + if ($ext == $e) { + $type = $m; } } - Logger::info('Image: guessType: type=' . $type); + Logger::info('Mime type guessed via extension', ['filename' => $filename, 'type' => $type]); return $type; } - /** + * Gets info array from given URL, cached data has priority + * * @param string $url - * @return array + * @return array Info * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public static function getInfoFromURLCached($url) + public static function getInfoFromURLCached(string $url): array { $data = []; @@ -143,23 +191,27 @@ class Images return $data; } - $data = DI::cache()->get($url); + $cacheKey = 'getInfoFromURL:' . sha1($url); + + $data = DI::cache()->get($cacheKey); if (empty($data) || !is_array($data)) { $data = self::getInfoFromURL($url); - DI::cache()->set($url, $data); + DI::cache()->set($cacheKey, $data); } - return $data; + return $data ?? []; } /** + * Gets info from URL uncached + * * @param string $url - * @return array + * @return array Info array * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public static function getInfoFromURL($url) + public static function getInfoFromURL(string $url): array { $data = []; @@ -167,7 +219,17 @@ class Images return $data; } - $img_str = Network::fetchUrl($url, true, 4); + if (Network::isLocalLink($url) && ($data = Photo::getResourceData($url))) { + $photo = Photo::selectFirst([], ['resource-id' => $data['guid'], 'scale' => $data['scale']]); + if (!empty($photo)) { + $img_str = Photo::getImageDataForPhoto($photo); + } + // @todo Possibly add a check for locally stored files + } + + if (empty($img_str)) { + $img_str = DI::httpClient()->fetch($url, HttpClientAccept::IMAGE, 4); + } if (!$img_str) { return []; @@ -176,18 +238,7 @@ class Images $filesize = strlen($img_str); try { - if (function_exists("getimagesizefromstring")) { - $data = @getimagesizefromstring($img_str); - } else { - $tempfile = tempnam(get_temppath(), "cache"); - - $stamp1 = microtime(true); - file_put_contents($tempfile, $img_str); - DI::profiler()->saveTimestamp($stamp1, "file", System::callstack()); - - $data = getimagesize($tempfile); - unlink($tempfile); - } + $data = @getimagesizefromstring($img_str); } catch (\Exception $e) { return []; } @@ -196,16 +247,18 @@ class Images $data['size'] = $filesize; } - return $data; + return is_array($data) ? $data : []; } /** - * @param integer $width - * @param integer $height - * @param integer $max - * @return array + * Returns scaling information + * + * @param integer $width Width + * @param integer $height Height + * @param integer $max Max width/height + * @return array Scaling dimensions */ - public static function getScalingDimensions($width, $height, $max) + public static function getScalingDimensions(int $width, int $height, int $max): array { if ((!$width) || (!$height)) { return ['width' => 0, 'height' => 0];