diff --git a/CHANGELOG.md b/CHANGELOG.md index de691d7fd2..2d7c55d42e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ You can also check [on GitHub](https://github.com/nextcloud/news/releases), the ### Fixed +- Use updated user agent when fetching feeds and favicons (#2788) - Allow feed title to be null in DB. (#2745) - Store HTTP last modified date from response header (#2724) - Admin settings could not be saved (#2533) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index e8e548c4b2..df52cdeb5b 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -32,6 +32,7 @@ use OCP\AppFramework\Bootstrap\IRegistrationContext; use OCP\AppFramework\App; +use OCA\News\Fetcher\FaviconDataAccess; use OCA\News\Fetcher\FeedFetcher; use OCA\News\Fetcher\Fetcher; use OCP\User\Events\BeforeUserDeletedEvent; @@ -135,9 +136,15 @@ public function register(IRegistrationContext $context): void return new Explorer($config->getClient(), $c->get(LoggerInterface::class)); }); + $context->registerService(FaviconDataAccess::class, function (ContainerInterface $c): FaviconDataAccess { + $config = $c->get(FetcherConfig::class); + return new FaviconDataAccess($config); + }); + $context->registerService(Favicon::class, function (ContainerInterface $c): Favicon { $favicon = new Favicon(); $favicon->cache(['dir' => $c->get(Cache::class)->getCache("feedFavicon")]); + $favicon->setDataAccess($c->get(FaviconDataAccess::class)); return $favicon; }); } diff --git a/lib/Config/FetcherConfig.php b/lib/Config/FetcherConfig.php index 710c41e245..b7d15e6b1c 100644 --- a/lib/Config/FetcherConfig.php +++ b/lib/Config/FetcherConfig.php @@ -44,6 +44,12 @@ class FetcherConfig */ protected $redirects; + /** + * Version number for the news application. + * @var string + */ + private $version; + /** * User agent for the client. * @var string @@ -75,6 +81,11 @@ public function __construct(IConfig $config) 'maxRedirects', Application::DEFAULT_SETTINGS['maxRedirects'] ); + $this->version = $config->getAppValue( + Application::NAME, + 'installed_version', + '1.0' + ); $proxy = $config->getSystemValue('proxy', null); if (is_null($proxy)) { @@ -127,7 +138,7 @@ public function getClient(): ClientInterface $config = [ 'timeout' => $this->client_timeout, 'headers' => [ - 'User-Agent' => static::DEFAULT_USER_AGENT, + 'User-Agent' => $this->getUserAgent(), 'Accept' => static::DEFAULT_ACCEPT, 'Accept-Encoding' => $this->checkEncoding() ], @@ -143,4 +154,18 @@ public function getClient(): ClientInterface $client = new Client($config); return new FeedIoClient($client); } + + /** + * Gets a user agent name for the client + * + * @return string + */ + public function getUserAgent(): string + { + if (is_null($this->version)) { + return self::DEFAULT_USER_AGENT; + } + + return 'NextCloud-News/' . $this->version; + } } diff --git a/lib/Fetcher/FaviconDataAccess.php b/lib/Fetcher/FaviconDataAccess.php new file mode 100644 index 0000000000..bbe7476dcc --- /dev/null +++ b/lib/Fetcher/FaviconDataAccess.php @@ -0,0 +1,61 @@ + + * @copyright 2024 Ben Vidulich + */ + +namespace OCA\News\Fetcher; + +use Favicon\DataAccess; + +use OCA\News\Config\FetcherConfig; + +/** + * Modified version of DataAccess with a configurable user agent header. + */ +class FaviconDataAccess extends DataAccess +{ + /** + * @var FetcherConfig + */ + private $fetcherConfig; + + public function __construct( + FetcherConfig $fetcherConfig, + ) { + $this->fetcherConfig = $fetcherConfig; + } + + public function retrieveUrl($url) + { + $this->setContext(); + return @file_get_contents($url); + } + + public function retrieveHeader($url) + { + $this->setContext(); + $headers = @get_headers($url, 1); + return is_array($headers) ? array_change_key_case($headers) : []; + } + + private function setContext() + { + stream_context_set_default( + [ + 'http' => [ + 'method' => 'GET', + 'follow_location' => 0, + 'max_redirects' => 1, + 'timeout' => 10, + 'header' => 'User-Agent: ' . $this->fetcherConfig->getUserAgent(), + ] + ] + ); + } +} diff --git a/lib/Fetcher/FeedFetcher.php b/lib/Fetcher/FeedFetcher.php index f826461b4e..eb0bdc952e 100755 --- a/lib/Fetcher/FeedFetcher.php +++ b/lib/Fetcher/FeedFetcher.php @@ -384,7 +384,7 @@ protected function getFavicon(FeedInterface $feed, string $url): ?string $favicon = trim($feed_logo); } - ini_set('user_agent', FetcherConfig::DEFAULT_USER_AGENT); + ini_set('user_agent', $this->fetcherConfig->getUserAgent()); $base_url = new Net_URL2($url); $base_url->setPath(""); diff --git a/tests/Unit/Config/FetcherConfigTest.php b/tests/Unit/Config/FetcherConfigTest.php index 6f5364490e..2a84a30b3d 100644 --- a/tests/Unit/Config/FetcherConfigTest.php +++ b/tests/Unit/Config/FetcherConfigTest.php @@ -62,4 +62,35 @@ public function testGetClient() $this->assertInstanceOf(FeedIoClient::class, $this->class->getClient()); } + + public function testGetUserAgent() + { + $this->config->expects($this->exactly(3)) + ->method('getAppValue') + ->willReturnMap([ + ['news', 'feedFetcherTimeout', 60, '60'], + ['news', 'maxRedirects', 10, '10'], + ['news', 'installed_version', '1.0', '123.45'] + ]); + $this->class = new FetcherConfig($this->config); + + $expected = 'NextCloud-News/123.45'; + $response = $this->class->getUserAgent(); + $this->assertEquals($expected, $response); + } + + public function testGetUserAgentUnknownVersion() + { + $this->config->expects($this->exactly(3)) + ->method('getAppValue') + ->willReturnMap([ + ['news', 'feedFetcherTimeout', 60, '60'], + ['news', 'maxRedirects', 10, '10'] + ]); + $this->class = new FetcherConfig($this->config); + + $expected = 'NextCloud-News/1.0'; + $response = $this->class->getUserAgent(); + $this->assertEquals($expected, $response); + } }