diff --git a/components/Avatar/Avatar.php b/components/Avatar/Avatar.php index 423af64ad8..00e2d8b1e9 100644 --- a/components/Avatar/Avatar.php +++ b/components/Avatar/Avatar.php @@ -109,7 +109,7 @@ class Avatar extends Component * Returns the avatar file's hash, mimetype, title and path. * Ensures exactly one cached value exists */ - public static function getAvatarFileInfo(int $actor_id): array + public static function getAvatarFileInfo(int $actor_id, int $size = 0): array { $res = Cache::get("avatar-file-info-{$actor_id}", function () use ($actor_id) { diff --git a/components/Avatar/Controller/Avatar.php b/components/Avatar/Controller/Avatar.php index c46d08e2c1..0f1e9e2fc8 100644 --- a/components/Avatar/Controller/Avatar.php +++ b/components/Avatar/Controller/Avatar.php @@ -101,7 +101,7 @@ class Avatar extends Controller $data_user = base64_decode($data_user); $tempfile = new TemporaryFile(['prefix' => 'gs-avatar']); $tempfile->write($data_user); - $attachment = GSFile::sanitizeAndStoreFileAsAttachment($tempfile); + $attachment = GSFile::storeFileAsAttachment($tempfile); } else { Log::info('Avatar upload got an invalid encoding, something\'s fishy and/or wrong'); } @@ -109,7 +109,7 @@ class Avatar extends Controller } elseif (isset($data['avatar'])) { // Cropping failed (e.g. disabled js), use file as uploaded $file = $data['avatar']; - $attachment = GSFile::sanitizeAndStoreFileAsAttachment($file); + $attachment = GSFile::storeFileAsAttachment($file); } else { throw new ClientException('Invalid form'); } diff --git a/plugins/Cover/Controller/Cover.php b/plugins/Cover/Controller/Cover.php index 422b1f3cc7..bc5cafbbf5 100644 --- a/plugins/Cover/Controller/Cover.php +++ b/plugins/Cover/Controller/Cover.php @@ -96,7 +96,7 @@ class Cover if (explode('/',$sfile->getMimeType())[0] != 'image') { throw new ServerException('Invalid file type'); } - $file = GSFile::sanitizeAndStoreFileAsAttachment($sfile); + $file = GSFile::storeFileAsAttachment($sfile); $old_file = null; $cover = DB::find('cover', ['gctor_id' => $actor_id]); // Must get old id before inserting another one diff --git a/plugins/ImageEncoder/Controller/ImageThumbnail.php b/plugins/ImageEncoder/Controller/ImageThumbnail.php deleted file mode 100644 index 4fdd9fddf3..0000000000 --- a/plugins/ImageEncoder/Controller/ImageThumbnail.php +++ /dev/null @@ -1,60 +0,0 @@ -. - -// }}} - -namespace Plugin\ImageEncoder\Controller; - -use App\Core\Controller; -use App\Core\DB\DB; -use App\Core\GSFile; -use App\Entity\AttachmentThumbnail; -use App\Util\Common; -use Symfony\Component\HttpFoundation\Request; - -class ImageThumbnail extends Controller -{ - /** - * Get a thumbnail for the attachment with id $id - */ - public function thumbnail(Request $request, int $id) - { - $attachment = DB::findOneBy('attachment', ['id' => $id]); - if (!is_null($attachment->getScope())) { - // && ($attachment->scope | VisibilityScope::PUBLIC) != 0 - // $user = Common::ensureLoggedIn(); - assert(false, 'Attachment scope not implemented'); - } - - // TODO rate limit - - $max_width = Common::config('thumbnail', 'width'); - $max_height = Common::config('thumbnail', 'height'); - $width = Common::clamp($this->int('w') ?: $max_width, min: 0, max: $max_width); - $height = Common::clamp($this->int('h') ?: $max_height, min: 0, max: $max_height); - $crop = $this->bool('c') ?: false; - - $thumbnail = AttachmentThumbnail::getOrCreate(attachment: $attachment, width: $width, height: $height, crop: $crop); - - $filename = $thumbnail->getFilename(); - $path = $thumbnail->getPath(); - - return GSFile::sendFile(filepath: $path, mimetype: $attachment->getMimetype(), output_filename: $filename, disposition: 'inline'); - } -} diff --git a/plugins/ImageEncoder/ImageEncoder.php b/plugins/ImageEncoder/ImageEncoder.php index 0b5990304c..876cb09a35 100644 --- a/plugins/ImageEncoder/ImageEncoder.php +++ b/plugins/ImageEncoder/ImageEncoder.php @@ -53,6 +53,21 @@ class ImageEncoder extends Plugin return '3.0.0'; } + /** + * @param array $event_map + * @param string $mimetype + * + * @return bool + */ + public function onFileMetaAvailable(array &$event_map, string $mimetype): bool + { + if (GSFile::mimetypeMajor($mimetype) !== 'image') { + return Event::next; + } + $event_map['image'][] = [$this, 'fileMeta']; + return Event::next; + } + /** * @param array $event_map * @param string $mimetype @@ -83,8 +98,29 @@ class ImageEncoder extends Plugin return Event::next; } + public function fileMeta(SplFileInfo &$file, ?string &$mimetype, ?int &$width, ?int &$height): bool + { + $original_mimetype = $mimetype; + if (GSFile::mimetypeMajor($original_mimetype) !== 'image') { + // Nothing concerning us + return false; + } + + try { + $image = Vips\Image::newFromFile($file->getRealPath(), ['access' => 'sequential']); + } catch (Vips\Exception $e) { + Log::debug("ImageEncoder's Vips couldn't handle the image file, failed with {$e}."); + throw new UnsupportedFileTypeException(_m("Unsupported image file with {$mimetype}.", previous: $e)); + } + $width = $image->width; + $height = $image->height; + + // Only one plugin can handle meta + return true; + } + /** - * Re-encodes the image ensuring it's valid. + * Re-encodes the image ensuring it is valid. * Also ensures that the image is not greater than the max width and height configured. * * @param SplFileInfo $file @@ -103,7 +139,7 @@ class ImageEncoder extends Plugin public function fileSanitize(SplFileInfo &$file, ?string &$mimetype, ?int &$width, ?int &$height): bool { $original_mimetype = $mimetype; - if (GSFile::mimetypeMajor($original_mimetype) != 'image') { + if (GSFile::mimetypeMajor($original_mimetype) !== 'image') { // Nothing concerning us return false; } diff --git a/plugins/VideoEncoder/VideoEncoder.php b/plugins/VideoEncoder/VideoEncoder.php index 1af5a7be75..5a2e88f33a 100644 --- a/plugins/VideoEncoder/VideoEncoder.php +++ b/plugins/VideoEncoder/VideoEncoder.php @@ -55,6 +55,22 @@ class VideoEncoder extends Plugin return '1.0.0'; } + /** + * @param array $event_map + * @param string $mimetype + * + * @return bool + */ + public function onFileMetaAvailable(array &$event_map, string $mimetype): bool + { + if (GSFile::mimetypeMajor($mimetype) !== 'video' && $mimetype !== 'image/gif') { + return Event::next; + } + $event_map['video'][] = [$this, 'fileMeta']; + $event_map['image/gif'][] = [$this, 'fileMeta']; + return Event::next; + } + /** * @param array $event_map * @param string $mimetype @@ -66,8 +82,8 @@ class VideoEncoder extends Plugin if (GSFile::mimetypeMajor($mimetype) !== 'video' && $mimetype !== 'image/gif') { return Event::next; } - $event_map['video'][] = [$this, 'fileSanitize']; - $event_map['image/gif'][] = [$this, 'fileSanitize']; + $event_map['video'][] = [$this, 'fileMeta']; + $event_map['image/gif'][] = [$this, 'fileMeta']; return Event::next; } @@ -97,7 +113,7 @@ class VideoEncoder extends Plugin * * @return bool true if sanitized */ - public function fileSanitize(SplFileInfo &$file, ?string &$mimetype, ?int &$width, ?int &$height): bool + public function fileMeta(SplFileInfo &$file, ?string &$mimetype, ?int &$width, ?int &$height): bool { if (//GSFile::mimetypeMajor($mimetype) !== 'video' && $mimetype !== 'image/gif') { diff --git a/plugins/VideoEncoder/templates/videoEncoder/videoEncoderView.html.twig b/plugins/VideoEncoder/templates/videoEncoder/videoEncoderView.html.twig index e255dcf525..82af8f382f 100644 --- a/plugins/VideoEncoder/templates/videoEncoder/videoEncoderView.html.twig +++ b/plugins/VideoEncoder/templates/videoEncoder/videoEncoderView.html.twig @@ -1,6 +1,6 @@
-