diff --git a/plugins/Embed/Embed.php b/plugins/Embed/Embed.php index 60b29e43b4..440f20700b 100644 --- a/plugins/Embed/Embed.php +++ b/plugins/Embed/Embed.php @@ -77,12 +77,15 @@ class Embed extends Plugin * Settings which can be set in social.local.yaml * WARNING, these are _regexps_ (slashes added later). Always escape your dots and end ('$') your strings */ + public bool $check_whitelist = false; + public bool $check_blacklist = false; public array $domain_whitelist = [ - // hostname => service provider - '.*' => '', // Default to allowing any host + // hostname + '.*', // Default to allowing any host ]; - - public bool $store_image = true; // Whether to maintain a copy of the original media or only a thumbnail of it + public array $domain_blacklist = []; + // Whether to maintain a copy of the original media or only a thumbnail of it + public bool $store_image = true; public ?int $thumbnail_width; public ?int $thumbnail_height; public ?int $max_size; @@ -198,28 +201,6 @@ class Embed extends Plugin return Event::next; } - /** - * @param string $url - * - * @return bool true if allowed by the lists, false otherwise - */ - private function allowedLink(string $url): bool - { - return true; - if ($this->check_whitelist ?? false) { - return false; // indicates "no check made" - } - - $host = parse_url($url, PHP_URL_HOST); - foreach ($this->domain_whitelist as $regex => $provider) { - if (preg_match("/{$regex}/", $host)) { - return $provider; // we trust this source, return provider name - } - } - - return false; - } - /** * This code executes when GNU social creates the page routing, and we hook * on this event to add our action handler for Embed. @@ -231,6 +212,7 @@ class Embed extends Plugin * @return bool * * + * */ public function onAddRoute(RouteLoader $m): bool { @@ -301,10 +283,11 @@ class Embed extends Plugin * @param Link $link * @param Note $note * - *@throws DuplicateFoundException + * @throws DuplicateFoundException * * @return bool * + * */ public function onNewLinkFromNote(Link $link, Note $note): bool { @@ -362,6 +345,39 @@ class Embed extends Plugin return Event::stop; } + /** + * @param string $url + * + * @return bool true if allowed by the lists, false otherwise + */ + private function allowedLink(string $url): bool + { + $passed_whitelist = !$this->check_whitelist; + $passed_blacklist = !$this->check_blacklist; + + if ($this->check_whitelist) { + $passed_whitelist = false; // don't trust be default + $host = parse_url($url, PHP_URL_HOST); + foreach ($this->domain_whitelist as $regex => $provider) { + if (preg_match("/{$regex}/", $host)) { + $passed_whitelist = true; // we trust this source + } + } + } + + if ($this->check_blacklist) { + // assume it passed by default + $host = parse_url($url, PHP_URL_HOST); + foreach ($this->domain_blacklist as $regex => $provider) { + if (preg_match("/{$regex}/", $host)) { + $passed_blacklist = false; // we blocked this source + } + } + } + + return $passed_whitelist && $passed_blacklist; + } + /** * Perform an oEmbed or OpenGraph lookup for the given $url. * @@ -481,6 +497,7 @@ class Embed extends Plugin * @throws ServerException * * @return bool true hook value + * */ public function onPluginVersion(array &$versions): bool { diff --git a/plugins/StoreRemoteMedia/StoreRemoteMedia.php b/plugins/StoreRemoteMedia/StoreRemoteMedia.php index c8d0cfe29d..d07127f955 100644 --- a/plugins/StoreRemoteMedia/StoreRemoteMedia.php +++ b/plugins/StoreRemoteMedia/StoreRemoteMedia.php @@ -22,6 +22,8 @@ use App\Core\DB\DB; use App\Core\Event; use App\Core\GSFile; use App\Core\HTTPClient; +use function App\Core\I18n\_m; +use App\Core\Log; use App\Core\Modules\Plugin; use App\Entity\AttachmentThumbnail; use App\Entity\AttachmentToLink; @@ -54,7 +56,19 @@ class StoreRemoteMedia extends Plugin return '3.0.0'; } - public bool $store_original = false; // Whether to maintain a copy of the original media or only a thumbnail of it + /** + * Settings which can be set in social.local.yaml + * WARNING, these are _regexps_ (slashes added later). Always escape your dots and end ('$') your strings + */ + public bool $check_whitelist = false; + public bool $check_blacklist = false; + public array $domain_whitelist = [ + // hostname + '.*', // Default to allowing any host + ]; + public array $domain_blacklist = []; + // Whether to maintain a copy of the original media or only a thumbnail of it + public bool $store_original = false; public ?int $thumbnail_width; public ?int $thumbnail_height; public ?int $max_size; @@ -64,6 +78,7 @@ class StoreRemoteMedia extends Plugin { return $this->store_original; } + private function getThumbnailWidth(): int { return $this->thumbnail_width ?? Common::config('thumbnail', 'width'); @@ -88,11 +103,12 @@ class StoreRemoteMedia extends Plugin * @param Link $link * @param Note $note * - * @throws DuplicateFoundException * @throws ServerException * @throws TemporaryFileException + * @throws DuplicateFoundException * * @return bool + * */ public function onNewLinkFromNote(Link $link, Note $note): bool { @@ -101,6 +117,12 @@ class StoreRemoteMedia extends Plugin return Event::next; } + // Is this URL trusted? + if (!$this->allowedLink($link->getUrl())) { + Log::info("Blocked URL ({$link->getUrl()}) in StoreRemoteMedia->onNewLinkFromNote."); + return Event::next; + } + // Have we handled it already? $attachment_to_link = DB::find('attachment_to_link', ['link_id' => $link->getId()]); @@ -165,6 +187,39 @@ class StoreRemoteMedia extends Plugin } } + /** + * @param string $url + * + * @return bool true if allowed by the lists, false otherwise + */ + private function allowedLink(string $url): bool + { + $passed_whitelist = !$this->check_whitelist; + $passed_blacklist = !$this->check_blacklist; + + if ($this->check_whitelist) { + $passed_whitelist = false; // don't trust be default + $host = parse_url($url, PHP_URL_HOST); + foreach ($this->domain_whitelist as $regex => $provider) { + if (preg_match("/{$regex}/", $host)) { + $passed_whitelist = true; // we trust this source + } + } + } + + if ($this->check_blacklist) { + // assume it passed by default + $host = parse_url($url, PHP_URL_HOST); + foreach ($this->domain_blacklist as $regex => $provider) { + if (preg_match("/{$regex}/", $host)) { + $passed_blacklist = false; // we blocked this source + } + } + } + + return $passed_whitelist && $passed_blacklist; + } + /** * Event raised when GNU social polls the plugin for information about it. * Adds this plugin's version information to $versions array