From 21a5dc8d1fbe7ef5d7c1ba5f9cc66b3ac78d5c20 Mon Sep 17 00:00:00 2001 From: Richard Steinmetz Date: Mon, 20 May 2024 13:58:56 +0200 Subject: [PATCH] fix(dav): fall back to generated avatar in image export plugin Signed-off-by: Richard Steinmetz --- apps/dav/appinfo/v1/carddav.php | 12 ++++--- apps/dav/lib/CardDAV/ImageExportPlugin.php | 31 ++++++++++++++++--- apps/dav/lib/Server.php | 10 ++++-- .../unit/CardDAV/ImageExportPluginTest.php | 6 +++- 4 files changed, 47 insertions(+), 12 deletions(-) diff --git a/apps/dav/appinfo/v1/carddav.php b/apps/dav/appinfo/v1/carddav.php index 70e5de1b481..5c6d6906fe0 100644 --- a/apps/dav/appinfo/v1/carddav.php +++ b/apps/dav/appinfo/v1/carddav.php @@ -39,6 +39,7 @@ use OCA\DAV\Connector\Sabre\MaintenancePlugin; use OCA\DAV\Connector\Sabre\Principal; use OCP\Accounts\IAccountManager; use OCP\App\IAppManager; +use OCP\IAvatarManager; use Psr\Log\LoggerInterface; use Sabre\CardDAV\Plugin; @@ -104,10 +105,13 @@ if ($debugging) { $server->addPlugin(new \Sabre\DAV\Sync\Plugin()); $server->addPlugin(new \Sabre\CardDAV\VCFExportPlugin()); -$server->addPlugin(new \OCA\DAV\CardDAV\ImageExportPlugin(new \OCA\DAV\CardDAV\PhotoCache( - \OC::$server->getAppDataDir('dav-photocache'), - \OC::$server->get(LoggerInterface::class) -))); +$server->addPlugin(new \OCA\DAV\CardDAV\ImageExportPlugin( + new \OCA\DAV\CardDAV\PhotoCache( + \OC::$server->getAppDataDir('dav-photocache'), + \OC::$server->get(LoggerInterface::class) + ), + \OC::$server->get(IAvatarManager::class), +)); $server->addPlugin(new ExceptionLoggerPlugin('carddav', \OC::$server->get(LoggerInterface::class))); // And off we go! diff --git a/apps/dav/lib/CardDAV/ImageExportPlugin.php b/apps/dav/lib/CardDAV/ImageExportPlugin.php index 3ebc91e5533..e079a54de4a 100644 --- a/apps/dav/lib/CardDAV/ImageExportPlugin.php +++ b/apps/dav/lib/CardDAV/ImageExportPlugin.php @@ -25,11 +25,13 @@ namespace OCA\DAV\CardDAV; use OCP\Files\NotFoundException; +use OCP\IAvatarManager; use Sabre\CardDAV\Card; use Sabre\DAV\Server; use Sabre\DAV\ServerPlugin; use Sabre\HTTP\RequestInterface; use Sabre\HTTP\ResponseInterface; +use Sabre\VObject\Reader; class ImageExportPlugin extends ServerPlugin { @@ -38,13 +40,14 @@ class ImageExportPlugin extends ServerPlugin { /** @var PhotoCache */ private $cache; + private IAvatarManager $avatarManager; + /** * ImageExportPlugin constructor. - * - * @param PhotoCache $cache */ - public function __construct(PhotoCache $cache) { + public function __construct(PhotoCache $cache, IAvatarManager $avatarManager) { $this->cache = $cache; + $this->avatarManager = $avatarManager; } /** @@ -99,6 +102,7 @@ class ImageExportPlugin extends ServerPlugin { $response->setHeader('Cache-Control', 'private, max-age=3600, must-revalidate'); $response->setHeader('Etag', $node->getETag()); + // Try to use embedded avatar image try { $file = $this->cache->get($addressbook->getResourceId(), $node->getName(), $size, $node); $response->setHeader('Content-Type', $file->getMimeType()); @@ -107,10 +111,29 @@ class ImageExportPlugin extends ServerPlugin { $response->setStatus(200); $response->setBody($file->getContent()); + return false; } catch (NotFoundException $e) { - $response->setStatus(404); + // Fall back to generated avatar + } + + $name = '?'; + $vObject = Reader::read($node->get()); + if (isset($vObject->FN)) { + $name = $vObject->FN->getValue(); + } elseif (isset($vObject->N)) { + [$lastName, $firstName] = $vObject->N->getParts(); + $name = "$firstName $lastName"; } + $avatar = $this->avatarManager->getGuestAvatar($name); + $image = $avatar->get($size); + + $response->setHeader('Content-Type', $image->mimeType()); + $fileName = $node->getName() . '.' . PhotoCache::ALLOWED_CONTENT_TYPES[$image->mimeType()]; + $response->setHeader('Content-Disposition', "attachment; filename=$fileName"); + $response->setStatus(200); + $response->setBody($image->data()); + return false; } } diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php index 37d04ba8190..c166be5be46 100644 --- a/apps/dav/lib/Server.php +++ b/apps/dav/lib/Server.php @@ -80,6 +80,7 @@ use OCP\AppFramework\Http\Response; use OCP\Diagnostics\IEventLogger; use OCP\EventDispatcher\IEventDispatcher; use OCP\FilesMetadata\IFilesMetadataManager; +use OCP\IAvatarManager; use OCP\ICacheFactory; use OCP\IRequest; use OCP\Profiler\IProfiler; @@ -204,9 +205,12 @@ class Server { $this->server->addPlugin(new VCFExportPlugin()); $this->server->addPlugin(new MultiGetExportPlugin()); $this->server->addPlugin(new HasPhotoPlugin()); - $this->server->addPlugin(new ImageExportPlugin(new PhotoCache( - \OC::$server->getAppDataDir('dav-photocache'), - $logger) + $this->server->addPlugin( + new ImageExportPlugin(new PhotoCache( + \OC::$server->getAppDataDir('dav-photocache'), + $logger, + ), + \OC::$server->get(IAvatarManager::class), )); } diff --git a/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php b/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php index 6f48927646e..d1b05c5d07e 100644 --- a/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php +++ b/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php @@ -30,6 +30,7 @@ use OCA\DAV\CardDAV\ImageExportPlugin; use OCA\DAV\CardDAV\PhotoCache; use OCP\Files\NotFoundException; use OCP\Files\SimpleFS\ISimpleFile; +use OCP\IAvatarManager; use Sabre\CardDAV\Card; use Sabre\DAV\Node; use Sabre\DAV\Server; @@ -51,6 +52,8 @@ class ImageExportPluginTest extends TestCase { private $tree; /** @var PhotoCache|\PHPUnit\Framework\MockObject\MockObject */ private $cache; + /** @var IAvatarManager|\PHPUnit\Framework\MockObject\MockObject */ + private $avatarManager; protected function setUp(): void { parent::setUp(); @@ -61,10 +64,11 @@ class ImageExportPluginTest extends TestCase { $this->tree = $this->createMock(Tree::class); $this->server->tree = $this->tree; $this->cache = $this->createMock(PhotoCache::class); + $this->avatarManager = $this->createMock(IAvatarManager::class); $this->plugin = $this->getMockBuilder(ImageExportPlugin::class) ->setMethods(['getPhoto']) - ->setConstructorArgs([$this->cache]) + ->setConstructorArgs([$this->cache, $this->avatarManager]) ->getMock(); $this->plugin->initialize($this->server); } -- 2.39.5