From d47bb3736e6ff6b51817da220c8e4b22c2f8d60c Mon Sep 17 00:00:00 2001 From: Diogo Peralta Cordeiro Date: Fri, 19 Feb 2021 12:10:37 +0000 Subject: [PATCH] [Media] Document recently added settings and add some more Fix some buggy ones, especially Embed crop --- .../SYSTEM_ADMINISTRATORS/CONFIGURE.md | 24 +++++++++++- lib/media/mediafile.php | 22 ++++++++--- plugins/Embed/EmbedPlugin.php | 37 ++++++++++++------- plugins/Embed/README.md | 16 +++++--- plugins/StoreRemoteMedia/README.md | 13 ++++--- .../StoreRemoteMediaPlugin.php | 27 ++++++-------- 6 files changed, 93 insertions(+), 46 deletions(-) diff --git a/DOCUMENTATION/SYSTEM_ADMINISTRATORS/CONFIGURE.md b/DOCUMENTATION/SYSTEM_ADMINISTRATORS/CONFIGURE.md index 496ce46fd5..a4e9ef763b 100644 --- a/DOCUMENTATION/SYSTEM_ADMINISTRATORS/CONFIGURE.md +++ b/DOCUMENTATION/SYSTEM_ADMINISTRATORS/CONFIGURE.md @@ -679,7 +679,7 @@ set too low (it's optional, so it may not be there at all). * `file_quota`: maximum size for a single file upload in bytes. A user can send any amount of notices with attachments as long as each attachment - is smaller than file_quota. + is smaller than file_quota. Defaults to PHP's configured upload limit. * `user_quota`: total size in bytes a user can store on this server. Each user can store any number of files as long as their total size does @@ -717,6 +717,28 @@ set too low (it's optional, so it may not be there at all). * `filename_base`: for new files, choose one: 'upload', 'hash'. Defaults to hash. +* `memory_limit`: PHP's memory limit to use temporarily when handling images. Defaults to `1024M`. + +* `prefer_remote`: when a user uploads a file, if the first time this file was + retrieved was from an URL, prefer redirect to the attachment with the first known URL. + + +thumbnail +------------------------------------------------------------------------------- + +The software lets users upload media with their notes. You can configure +the way thumbnails are generated for them. + +* `dir`: Where to store, defaults to `File::path('thumb')` (equivalent to `['attachments']['dir']/thumb/`). +* `path`: URL path, relative to the server, to find thumbnails. Defaults to `File::url('thumb/$filename')` (equivalent to `['attachments']['path']/thumb/`). +* `server`: Only used if `['thumbnail']['path']` is NOT empty. In which case it defaults to `['site']['server']`, schema is decided from `GNUsocial::useHTTPS()` +* `crop`: Crop to the size (not preserving aspect ratio). Defaults to false. +* `maxsize`: Thumbs with an edge larger than this will not be generated. Defaults to 1000. +* `width`: Max width for the thumbnail. Defaults to 450. +* `height`: Max height for the thumbnail. Defaults to 600. +* `upscale`: Whether or not to scale smaller images up to larger thumbnail sizes. Defaults to false. +* `animated`: `null` means use file as thumbnail. `false` means that a still frame can be used. `true` requires `ImageMagickPlugin`. Defaults to false. + group ------------------------------------------------------------------------------- diff --git a/lib/media/mediafile.php b/lib/media/mediafile.php index 58c58c4b56..4f573baba5 100644 --- a/lib/media/mediafile.php +++ b/lib/media/mediafile.php @@ -450,12 +450,22 @@ class MediaFile return MediaFile::fromFileObject($file); } } - var_dump($file);die; - // If no exception is thrown then this file was already uploaded by a local actor once, so we'll use that and just add redirections. - // but if the _actual_ locally stored file doesn't exist, getPath will throw FileNotFoundException - $filepath = $file->getPath(); - $mimetype = $file->mimetype; - $fileid = $file->getID(); + // Assert: If we got to this line, then we only traversed URLs on the while loop above. + if (common_config('attachments', 'prefer_remote')) { + // Was this file imported from a remote source already? + $filepath = $file->getPath(); // This function will throw FileNotFoundException if not. + // Assert: If we got to this line, then we can use this file and just add redirections. + $mimetype = $file->mimetype; + $fileid = $file->getID(); + } else { + throw new FileNotFoundException('This isn\'t a path.'); // A bit of dadaist art. + // It's natural that a sysadmin prefers to not add redirections to the first remote link of an + // attachment, it's not a very consistent thing to do. On the other hand, lack of space can drive + // a person crazy. + + // Also note that if one configured StoreRemoteMedia to not save original images (very likely), then + // having prefer_remote enabled will never store the original attachment (sort of the idea here). + } } catch (FileNotFoundException | NoResultException $e) { // We have to save the upload as a new local file. This is the normal course of action. if ($scoped instanceof Profile) { diff --git a/plugins/Embed/EmbedPlugin.php b/plugins/Embed/EmbedPlugin.php index 3e6f4a7836..228a1e4912 100644 --- a/plugins/Embed/EmbedPlugin.php +++ b/plugins/Embed/EmbedPlugin.php @@ -55,9 +55,10 @@ class EmbedPlugin extends Plugin public $append_whitelist = []; // fill this array as domain_whitelist to add more trusted sources public $check_whitelist = false; // security/abuse precaution - public $thumbnail_width = 128; - public $thumbnail_height = 128; - public $thumbnail_crop = true; + public $thumbnail_width = null; + public $thumbnail_height = null; + public $crop = true; + public $max_size = null; protected $imgData = []; @@ -71,6 +72,11 @@ class EmbedPlugin extends Plugin parent::initialize(); $this->domain_whitelist = array_merge($this->domain_whitelist, $this->append_whitelist); + + // Load global configuration if specific not provided + $this->thumbnail_width = $this->thumbnail_width ?? common_config('thumbnail', 'width'); + $this->thumbnail_height = $this->thumbnail_height ?? common_config('thumbnail', 'height'); + $this->max_size = $this->max_size ?? common_config('attachments', 'file_quota'); } /** @@ -563,15 +569,21 @@ class EmbedPlugin extends Plugin } // If the image is not of the desired size, resize it - if ($info[0] > $this->thumbnail_width || $info[1] > $this->thumbnail_height) { + if ($this->crop && ($info[0] > $this->thumbnail_width || $info[1] > $this->thumbnail_height)) { // Temporary object, not stored in DB $img = new ImageFile(-1, $fullpath); - $box = $img->scaleToFit($this->thumbnail_width, $this->thumbnail_height, $this->thumbnail_crop); - $outpath = $img->resizeTo($fullpath, $box); - $filename = basename($outpath); - if ($fullpath !== $outpath) { - @unlink($fullpath); - } + list($width, $height, $x, $y, $w, $h) = $img->scaleToFit($this->thumbnail_width, $this->thumbnail_height, $this->crop); + + // The boundary box for our resizing + $box = [ + 'width' => $width, 'height' => $height, + 'x' => $x, 'y' => $y, + 'w' => $w, 'h' => $h, + ]; + + $width = $box['width']; + $height = $box['height']; + $img->resizeTo($fullpath, $box); } } else { throw new AlreadyFulfilledException('A thumbnail seems to already exist for remote file' . @@ -622,11 +634,10 @@ class EmbedPlugin extends Plugin try { $is_image = $this->isRemoteImage($url, $headers); if ($is_image == true) { - $max_size = common_get_preferred_php_upload_limit(); $file_size = $this->getRemoteFileSize($url, $headers); - if (($file_size!=false) && ($file_size > $max_size)) { + if (($file_size!=false) && ($file_size > $this->max_size)) { common_debug("Went to store remote thumbnail of size " . $file_size . - " but the upload limit is " . $max_size . " so we aborted."); + " but the upload limit is " . $this->max_size . " so we aborted."); return false; } } else { diff --git a/plugins/Embed/README.md b/plugins/Embed/README.md index 9551ada801..4bcbee9824 100644 --- a/plugins/Embed/README.md +++ b/plugins/Embed/README.md @@ -8,11 +8,17 @@ This plugin is enabled by default. Settings ======== -width: Maximum width of the thumbnail in pixels. -height: Maximum height of the thumbnail in pixels. -show_html: Whether to show HTML oEmbed data. -domain_whitelist: Array of regular expressions. Always escape your dots and end your strings. -check_whitelist: Whether to check the domain_whitelist. +* `domain_whitelist`: Array of regular expressions. Always escape your dots and end your strings. +* `check_whitelist`: Whether to check the domain_whitelist. +* `thumbnail_width`: Maximum width of the thumbnail in pixels. Defaults to global `[thumbnail][width]`. +* `thumbnail_height`: Maximum height of the thumbnail in pixels. Defaults to global `[thumbnail][height]`. +* `crop`: Crop to the thumbnail size and don't preserve the original file. Defaults to true. +* `max_size`: Max media size. Anything bigger than this is rejected. Defaults to global `[attachments][file_quota]`. + +Relevant GNU social global settings +=================================== + +* `[attachments][show_html]`: Whether to show HTML oEmbed data. Example ======= diff --git a/plugins/StoreRemoteMedia/README.md b/plugins/StoreRemoteMedia/README.md index 86679289a1..d42eca72b1 100644 --- a/plugins/StoreRemoteMedia/README.md +++ b/plugins/StoreRemoteMedia/README.md @@ -9,13 +9,16 @@ to the bottom of your config.php Settings ======== -domain_whitelist: Array of regular expressions. Always escape your dots and end your strings. -check_whitelist: Whether to check the domain_whitelist. - -max_size: Max media size. Anything bigger than this is rejected. 10MiB by default. +* `domain_whitelist`: Array of regular expressions. Always escape your dots and end your strings. +* `check_whitelist`: Whether to check the domain_whitelist. When check_whitelist is set, only images from URLs matching a regex in the -domain_whitelist array are accepted for local storage. +domain_whitelist array are accepted for local storage. + +* `thumbnail_width`: Maximum width of the thumbnail in pixels. Defaults to global `[thumbnail][width]`. +* `thumbnail_height`: Maximum height of the thumbnail in pixels. Defaults to global `[thumbnail][height]`. +* `crop`: Crop to the thumbnail size and don't preserve the original file. Defaults to false. +* `max_size`: Max media size. Anything bigger than this is rejected. Defaults to global `[attachments][file_quota]`. Example ======= diff --git a/plugins/StoreRemoteMedia/StoreRemoteMediaPlugin.php b/plugins/StoreRemoteMedia/StoreRemoteMediaPlugin.php index 341d4d5f95..5103b3f8b6 100644 --- a/plugins/StoreRemoteMedia/StoreRemoteMediaPlugin.php +++ b/plugins/StoreRemoteMedia/StoreRemoteMediaPlugin.php @@ -41,10 +41,11 @@ class StoreRemoteMediaPlugin extends Plugin public $append_whitelist = []; // fill this array as domain_whitelist to add more trusted sources public $check_whitelist = false; // security/abuse precaution - public $thumbnail_width = null; - public $thumbnail_height = 128; - public $thumbnail_crop = true; - public $max_size = 10 * 1024 * 1024; // 10MiB max image size by default + public $store_original = true; // Whether to maintain a copy of the original media or only a thumbnail of it + public $thumbnail_width = null; + public $thumbnail_height = null; + public $crop = false; + public $max_size = null; protected $imgData = []; @@ -57,12 +58,10 @@ class StoreRemoteMediaPlugin extends Plugin { parent::initialize(); - if (is_null($this->thumbnail_width)) { - $this->thumbnail_width = common_config('thumbnail', 'width'); - $this->thumbnail_height = common_config('thumbnail', 'height'); - $this->thumbnail_crop = common_config('thumbnail', 'crop'); - $this->max_size = common_get_preferred_php_upload_limit(); - } + // Load global configuration if specific not provided + $this->thumbnail_width = $this->thumbnail_width ?? common_config('thumbnail', 'width'); + $this->thumbnail_height = $this->thumbnail_height ?? common_config('thumbnail', 'height'); + $this->max_size = $this->max_size ?? common_config('attachments', 'file_quota'); $this->domain_whitelist = array_merge($this->domain_whitelist, $this->append_whitelist); } @@ -275,14 +274,10 @@ class StoreRemoteMediaPlugin extends Plugin } // If the image is not of the desired size, resize it - if ($info[0] > $this->thumbnail_width || $info[1] > $this->thumbnail_height) { + if ($this->crop && ($info[0] > $this->thumbnail_width || $info[1] > $this->thumbnail_height)) { // Temporary object, not stored in DB $img = new ImageFile(-1, $filepath); - // Get proper aspect ratio width and height before lookup - // We have to do it through an ImageFile object because of orientation etc. - // Only other solution would've been to rotate + rewrite uploaded files - // which we don't want to do because we like original, untouched data! - list($width, $height, $x, $y, $w, $h) = $img->scaleToFit($this->thumbnail_width, $this->thumbnail_height, $this->thumbnail_crop); + list($width, $height, $x, $y, $w, $h) = $img->scaleToFit($this->thumbnail_width, $this->thumbnail_height, $this->crop); // The boundary box for our resizing $box = [