From 5c9bb543601c832f0e58969db3063d9bf04659b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= <come.chilliet@nextcloud.com> Date: Mon, 11 Dec 2023 11:34:12 +0100 Subject: [PATCH] Catch and log error thrown while parsing dates from metadata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com> --- .../OriginalDateTimeMetadataProvider.php | 38 +++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/lib/Listener/OriginalDateTimeMetadataProvider.php b/lib/Listener/OriginalDateTimeMetadataProvider.php index 37b38a8e9..fdc8f9485 100644 --- a/lib/Listener/OriginalDateTimeMetadataProvider.php +++ b/lib/Listener/OriginalDateTimeMetadataProvider.php @@ -28,12 +28,15 @@ use OCP\EventDispatcher\IEventListener; use OCP\Files\File; use OCP\FilesMetadata\Event\MetadataLiveEvent; +use Psr\Log\LoggerInterface; /** * @template-implements IEventListener<MetadataLiveEvent> */ class OriginalDateTimeMetadataProvider implements IEventListener { - public function __construct() { + public function __construct( + private LoggerInterface $logger, + ) { } public array $regexpToDateFormatMap = [ @@ -43,6 +46,27 @@ public function __construct() { "/^([0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{4})/" => "Y-m-d-G-i-s", ]; + private function dateToTimestamp(string $format, string $date, File $node): int|false { + try { + $dateTime = DateTime::createFromFormat($format, $date); + if ($dateTime !== false) { + return $dateTime->getTimestamp(); + } + return false; + } catch (\Throwable $t) { + /* Date comes from user data and may trigger ValueError or DateRangeError */ + $this->logger->warning( + 'Failed to parse date {date} for file {path}', + [ + 'date' => $date, + 'path' => $node->getPath(), + 'exception' => $t, + ] + ); + return false; + } + } + public function handle(Event $event): void { if (!($event instanceof MetadataLiveEvent)) { return; @@ -63,9 +87,9 @@ public function handle(Event $event): void { // Try to use EXIF data. if ($metadata->hasKey('photos-exif') && array_key_exists('DateTimeOriginal', $metadata->getArray('photos-exif'))) { $rawDateTimeOriginal = $metadata->getArray('photos-exif')['DateTimeOriginal']; - $dateTimeOriginal = DateTime::createFromFormat("Y:m:d G:i:s", $rawDateTimeOriginal); - if ($dateTimeOriginal !== false) { - $metadata->setInt('photos-original_date_time', $dateTimeOriginal->getTimestamp(), true); + $timestampOriginal = $this->dateToTimestamp("Y:m:d G:i:s", $rawDateTimeOriginal, $node); + if ($timestampOriginal !== false) { + $metadata->setInt('photos-original_date_time', $timestampOriginal, true); return; } } @@ -80,9 +104,9 @@ public function handle(Event $event): void { continue; } - $dateTimeOriginal = DateTime::createFromFormat($format, $matches[1]); - if ($dateTimeOriginal !== false) { - $metadata->setInt('photos-original_date_time', $dateTimeOriginal->getTimestamp(), true); + $timestampOriginal = $this->dateToTimestamp($format, $matches[1], $node); + if ($timestampOriginal !== false) { + $metadata->setInt('photos-original_date_time', $timestampOriginal, true); return; } }