diff --git a/include/api.php b/include/api.php index bcfd5af246..8291d18926 100644 --- a/include/api.php +++ b/include/api.php @@ -4734,13 +4734,8 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $ } } - if ($filetype == "") { - $filetype = Images::guessType($filename); - } - $imagedata = @getimagesize($src); - if ($imagedata) { - $filetype = $imagedata['mime']; - } + $filetype = Images::getMimeTypeBySource($src, $filename, $filetype); + Logger::log( "File upload src: " . $src . " - filename: " . $filename . " - size: " . $filesize . " - type: " . $filetype, diff --git a/mod/photos.php b/mod/photos.php index ef957ad5b0..3f558429d4 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -706,9 +706,7 @@ function photos_post(App $a) return; } - if ($type == "") { - $type = Images::guessType($filename); - } + $type = Images::getMimeTypeBySource($src, $filename, $type); Logger::log('photos: upload: received file: ' . $filename . ' as ' . $src . ' ('. $type . ') ' . $filesize . ' bytes', Logger::DEBUG); diff --git a/mod/wall_upload.php b/mod/wall_upload.php index fd33cdd17a..3841ef97b5 100644 --- a/mod/wall_upload.php +++ b/mod/wall_upload.php @@ -174,23 +174,7 @@ function wall_upload_post(App $a, $desktopmode = true) exit(); } - // This is a special treatment for picture upload from Twidere - if (($filename == "octet-stream") && ($filetype != "")) { - $filename = $filetype; - $filetype = ""; - } - - if ($filetype == "") { - $filetype = Images::guessType($filename); - } - - // If there is a temp name, then do a manual check - // This is more reliable than the provided value - - $imagedata = getimagesize($src); - if ($imagedata) { - $filetype = $imagedata['mime']; - } + $filetype = Images::getMimeTypeBySource($src, $filename, $filetype); Logger::log("File upload src: " . $src . " - filename: " . $filename . " - size: " . $filesize . " - type: " . $filetype, Logger::DEBUG); diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index 7a316c251b..334efb32a7 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -453,6 +453,10 @@ class BBCode { $s = $srctext; + // Simplify image links + $s = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $s); + $s = preg_replace("/\[img\=(.*?)\](.*?)\[\/img\]/ism", '[img]$1[/img]', $s); + $matches = null; $c = preg_match_all('/\[img.*?\](.*?)\[\/img\]/ism', $s, $matches, PREG_SET_ORDER); if ($c) { @@ -464,13 +468,14 @@ class BBCode continue; } - $i = Network::fetchUrl($mtch[1]); - if (!$i) { - return $srctext; + $curlResult = Network::curl($mtch[1], true); + if (!$curlResult->isSuccess()) { + continue; } - // guess mimetype from headers or filename - $type = Images::guessType($mtch[1], true); + $i = $curlResult->getBody(); + $type = $curlResult->getContentType(); + $type = Images::getMimeTypeByData($i, $mtch[1], $type); if ($i) { $Image = new Image($i, $type); diff --git a/src/Model/Photo.php b/src/Model/Photo.php index 45a8a92e19..9d8b5611f7 100644 --- a/src/Model/Photo.php +++ b/src/Model/Photo.php @@ -432,9 +432,7 @@ class Photo return false; } - if (empty($type)) { - $type = Images::guessType($image_url, true); - } + $type = Images::getMimeTypeByData($img_str, $image_url, $type); $Image = new Image($img_str, $type); if ($Image->isValid()) { diff --git a/src/Model/User.php b/src/Model/User.php index 351982e8ad..4ef5ffa33c 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -839,9 +839,16 @@ class User $photo_failure = false; $filename = basename($photo); - $img_str = Network::fetchUrl($photo, true); - // guess mimetype from headers or filename - $type = Images::guessType($photo, true); + $curlResult = Network::curl($photo, true); + if ($curlResult->isSuccess()) { + $img_str = $curlResult->getBody(); + $type = $curlResult->getContentType(); + } else { + $img_str = ''; + $type = ''; + } + + $type = Images::getMimeTypeByData($img_str, $photo, $type); $Image = new Image($img_str, $type); if ($Image->isValid()) { diff --git a/src/Module/Settings/Profile/Photo/Index.php b/src/Module/Settings/Profile/Photo/Index.php index 40b4ab1539..3e4f9b8a4e 100644 --- a/src/Module/Settings/Profile/Photo/Index.php +++ b/src/Module/Settings/Profile/Photo/Index.php @@ -52,9 +52,8 @@ class Index extends BaseSettings $filename = basename($_FILES['userfile']['name']); $filesize = intval($_FILES['userfile']['size']); $filetype = $_FILES['userfile']['type']; - if ($filetype == '') { - $filetype = Images::guessType($filename); - } + + $filetype = Images::getMimeTypeBySource($src, $filename, $filetype); $maximagesize = DI::config()->get('system', 'maximagesize', 0); diff --git a/src/Object/Image.php b/src/Object/Image.php index 535eae0b33..4d064f3c3a 100644 --- a/src/Object/Image.php +++ b/src/Object/Image.php @@ -708,22 +708,6 @@ class Image return Images::getFormatsMap(); } - /** - * Guess image mimetype from filename or from Content-Type header - * - * @param string $filename Image filename - * @param boolean $fromcurl Check Content-Type header from curl request - * @param string $header passed headers to take into account - * - * @return string|null - * @throws Exception - * @deprecated in version 2019.12 please use Util\Images::guessType() instead. - */ - public static function guessType($filename, $fromcurl = false, $header = '') - { - return Images::guessType($filename, $fromcurl, $header); - } - /** * @param string $url url * @return array diff --git a/src/Util/Images.php b/src/Util/Images.php index 6471ed526b..35f0cfc042 100644 --- a/src/Util/Images.php +++ b/src/Util/Images.php @@ -24,7 +24,6 @@ namespace Friendica\Util; use Friendica\Core\Logger; use Friendica\Core\System; use Friendica\DI; -use Imagick; /** * Image utilities @@ -74,61 +73,79 @@ 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 $mime default mime type * - * @return string|null + * @return string * @throws \Exception */ - public static function guessType($filename, $fromcurl = false, $header = '') + public static function getMimeTypeByData(string $image_data, string $filename = '', string $mime = '') { - 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 (array_key_exists('Content-Type', $headers)) { - $type = $headers['Content-Type']; - } + if (substr($mime, 0, 6) == 'image/') { + Logger::info('Using default mime type', ['filename' => $filename, 'mime' => $mime]); + return $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; - } - } - } + $image = @getimagesizefromstring($image_data); + if (!empty($image['mime'])) { + Logger::info('Mime type detected via data', ['filename' => $filename, 'default' => $mime, 'mime' => $image['mime']]); + return $image['mime']; } - Logger::info('Image: guessType: type=' . $type); - return $type; + return self::guessTypeByExtension($filename); } + /** + * Fetch image mimetype from the image data or guessing from the file name + * + * @param string $sourcefile Source file of the image + * @param string $filename File name (for guessing the type via the extension) + * @param string $mime default mime type + * + * @return string + * @throws \Exception + */ + public static function getMimeTypeBySource(string $sourcefile, string $filename = '', string $mime = '') + { + if (substr($mime, 0, 6) == 'image/') { + Logger::info('Using default mime type', ['filename' => $filename, 'mime' => $mime]); + return $mime; + } + + $image = @getimagesize($sourcefile); + if (!empty($image['mime'])) { + Logger::info('Mime type detected via file', ['filename' => $filename, 'default' => $mime, 'image' => $image]); + return $image['mime']; + } + + return self::guessTypeByExtension($filename); + } + + /** + * Guess image mimetype from the filename + * + * @param string $filename Image filename + * + * @return string + * @throws \Exception + */ + public static function guessTypeByExtension(string $filename) + { + $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('Mime type guessed via extension', ['filename' => $filename, 'type' => $type]); + return $type; + } /** * @param string $url