]> git.mxchange.org Git - friendica.git/blobdiff - src/Util/Images.php
Fixed max value check, improved request value fetching
[friendica.git] / src / Util / Images.php
index e5a4da5b1953304cb75ffe1b296d4d87c580effd..077509d3cb5e6e1c64105e2a7886bd131cf31be5 100644 (file)
@@ -1,11 +1,29 @@
 <?php
+/**
+ * @copyright Copyright (C) 2010-2022, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
 
 namespace Friendica\Util;
 
 use Friendica\Core\Logger;
-use Friendica\Core\System;
 use Friendica\DI;
-use Imagick;
+use Friendica\Model\Photo;
 
 /**
  * Image utilities
@@ -28,6 +46,30 @@ class Images
                return $m;
        }
 
+       /**
+        * Return file extension for mime type
+        * @param string $mimetype
+        * @return string
+        */
+       public static function getExtensionByMimeType(string $mimetype): string
+       {
+               switch ($mimetype) {
+                       case 'image/png':
+                               $imagetype = IMAGETYPE_PNG;
+                               break;
+
+                       case 'image/gif':
+                               $imagetype = IMAGETYPE_GIF;
+                               break;
+
+                       default:
+                               $imagetype = IMAGETYPE_JPEG;
+                               break;
+               }
+
+               return image_type_to_extension($imagetype);
+       }
+
        /**
         * Returns supported image mimetypes and corresponding file extensions
         *
@@ -55,62 +97,80 @@ 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 (substr($mime, 0, 6) == 'image/') {
+                       Logger::info('Using default mime type', ['filename' => $filename, 'mime' => $mime]);
+                       return $mime;
+               }
 
-                       if (array_key_exists('Content-Type', $headers)) {
-                               $type = $headers['Content-Type'];
-                       }
+               $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'];
                }
 
-               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);
+       }
+
+       /**
+        * 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('Image: guessType: type=' . $type);
+               Logger::info('Mime type guessed via extension', ['filename' => $filename, 'type' => $type]);
                return $type;
        }
 
-
        /**
         * @param string $url
         * @return array
@@ -148,7 +208,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, 4);
+               }
 
                if (!$img_str) {
                        return [];
@@ -157,18 +227,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 [];
                }