cache = $cache; $this->linkExplorer = $linkExplorer; $this->logger = $logger; $this->client = $clientService->newClient(); $this->enabled = $config->getAppValue('bookmarks', 'privacy.enableScraping', 'false'); } /** * @param Bookmark $bookmark * * @return Image|null */ public function getImage($bookmark): ?IImage { if ($this->enabled === 'false') { return null; } if (!isset($bookmark)) { return null; } if (!$bookmark->isWebLink()) { return null; } $key = self::CACHE_PREFIX . '-' . md5($bookmark->getUrl()); // Try cache first try { if ($image = $this->cache->get($key)) { if ($image === 'null') { return null; } return Image::deserialize($image); } } catch (NotFoundException $e) { } catch (NotPermittedException $e) { } $url = $bookmark->getUrl(); $site = $this->scrapeUrl($url); if (isset($site['favicon'])) { $image = $this->fetchImage($site['favicon']); if ($image !== null) { $this->cache->set($key, $image->serialize(), self::CACHE_TTL); return $image; } } $url_parts = parse_url($bookmark->getUrl()); if (isset($url_parts['scheme'], $url_parts['host'])) { $image = $this->fetchImage( $url_parts['scheme'] . '://' . $url_parts['host'] . '/favicon.ico' ); if ($image !== null) { $this->cache->set($key, $image->serialize(), self::CACHE_TTL); return $image; } } $this->cache->set($key, 'null', self::CACHE_TTL); return null; } public function scrapeUrl($url): array { return $this->linkExplorer->get($url); } /** * @param $url * @return Image|null */ protected function fetchImage(string $url): ?Image { try { $response = $this->client->get($url, ['timeout' => self::HTTP_TIMEOUT]); } catch (Exception $e) { $this->logger->debug($e->getMessage(), ['app' => 'bookmarks']); return null; } $body = $response->getBody(); $contentType = $response->getHeader('Content-Type'); // Some HTPP Error occured :/ if (200 !== $response->getStatusCode()) { return null; } // It's not actually an image, doh. if (!isset($contentType) || stripos($contentType, 'image') !== 0) { return null; } return new Image($contentType, $body); } }