From 4f33b6937ba68b77e413250a9887f6bcd1ae011d Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Wed, 29 Dec 2021 14:18:45 +0100 Subject: Fix column/property type of the CalDAV deleted_at time stamp The timestamp is an int, but we treated it as string. With this patch the property map is enriched with types and settype casts the value if necessary. Signed-off-by: Christoph Wurst --- apps/dav/lib/CalDAV/CalDavBackend.php | 93 +++++++++++++++++------------------ 1 file changed, 46 insertions(+), 47 deletions(-) diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index d949f32c1fc..ab3409b3bf0 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -104,6 +104,7 @@ use function is_array; use function is_resource; use function pathinfo; use function rewind; +use function settype; use function sprintf; use function str_replace; use function strtolower; @@ -142,20 +143,19 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription public const CLASSIFICATION_CONFIDENTIAL = 2; /** - * List of CalDAV properties, and how they map to database field names + * List of CalDAV properties, and how they map to database field names and their type * Add your own properties by simply adding on to this array. * - * Note that only string-based properties are supported here. - * * @var array + * @psalm-var array */ public $propertyMap = [ - '{DAV:}displayname' => 'displayname', - '{urn:ietf:params:xml:ns:caldav}calendar-description' => 'description', - '{urn:ietf:params:xml:ns:caldav}calendar-timezone' => 'timezone', - '{http://apple.com/ns/ical/}calendar-order' => 'calendarorder', - '{http://apple.com/ns/ical/}calendar-color' => 'calendarcolor', - '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => 'deleted_at', + '{DAV:}displayname' => ['displayname', 'string'], + '{urn:ietf:params:xml:ns:caldav}calendar-description' => ['description', 'string'], + '{urn:ietf:params:xml:ns:caldav}calendar-timezone' => ['timezone', 'string'], + '{http://apple.com/ns/ical/}calendar-order' => ['calendarorder', 'string'], + '{http://apple.com/ns/ical/}calendar-color' => ['calendarcolor', 'string'], + '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => ['deleted_at', 'int'], ]; /** @@ -351,7 +351,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription public function getCalendarsForUser($principalUri) { $principalUriOriginal = $principalUri; $principalUri = $this->convertPrincipal($principalUri, true); - $fields = array_values($this->propertyMap); + $fields = array_column($this->propertyMap, 0); $fields[] = 'id'; $fields[] = 'uri'; $fields[] = 'synctoken'; @@ -392,10 +392,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}owner-principal' => $this->convertPrincipal($principalUri, !$this->legacyEndpoint), ]; - foreach ($this->propertyMap as $xmlName => $dbName) { - $calendar[$xmlName] = $row[$dbName]; - } - + $calendar = $this->rowToCalendar($row, $calendar); $calendar = $this->addOwnerPrincipalToCalendar($calendar); $calendar = $this->addResourceTypeToCalendar($row, $calendar); @@ -411,7 +408,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription $principals[] = $principalUri; - $fields = array_values($this->propertyMap); + $fields = array_column($this->propertyMap, 0); $fields[] = 'a.id'; $fields[] = 'a.uri'; $fields[] = 'a.synctoken'; @@ -469,10 +466,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription $readOnlyPropertyName => $readOnly, ]; - foreach ($this->propertyMap as $xmlName => $dbName) { - $calendar[$xmlName] = $row[$dbName]; - } - + $calendar = $this->rowToCalendar($row, $calendar); $calendar = $this->addOwnerPrincipalToCalendar($calendar); $calendar = $this->addResourceTypeToCalendar($row, $calendar); @@ -489,7 +483,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription */ public function getUsersOwnCalendars($principalUri) { $principalUri = $this->convertPrincipal($principalUri, true); - $fields = array_values($this->propertyMap); + $fields = array_column($this->propertyMap, 0); $fields[] = 'id'; $fields[] = 'uri'; $fields[] = 'synctoken'; @@ -518,10 +512,8 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription '{' . Plugin::NS_CALDAV . '}supported-calendar-component-set' => new SupportedCalendarComponentSet($components), '{' . Plugin::NS_CALDAV . '}schedule-calendar-transp' => new ScheduleCalendarTransp($row['transparent']?'transparent':'opaque'), ]; - foreach ($this->propertyMap as $xmlName => $dbName) { - $calendar[$xmlName] = $row[$dbName]; - } + $calendar = $this->rowToCalendar($row, $calendar); $calendar = $this->addOwnerPrincipalToCalendar($calendar); $calendar = $this->addResourceTypeToCalendar($row, $calendar); @@ -556,7 +548,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @return array */ public function getPublicCalendars() { - $fields = array_values($this->propertyMap); + $fields = array_column($this->propertyMap, 0); $fields[] = 'a.id'; $fields[] = 'a.uri'; $fields[] = 'a.synctoken'; @@ -595,10 +587,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}public' => (int)$row['access'] === self::ACCESS_PUBLIC, ]; - foreach ($this->propertyMap as $xmlName => $dbName) { - $calendar[$xmlName] = $row[$dbName]; - } - + $calendar = $this->rowToCalendar($row, $calendar); $calendar = $this->addOwnerPrincipalToCalendar($calendar); $calendar = $this->addResourceTypeToCalendar($row, $calendar); @@ -617,7 +606,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @throws NotFound */ public function getPublicCalendar($uri) { - $fields = array_values($this->propertyMap); + $fields = array_column($this->propertyMap, 0); $fields[] = 'a.id'; $fields[] = 'a.uri'; $fields[] = 'a.synctoken'; @@ -663,10 +652,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}public' => (int)$row['access'] === self::ACCESS_PUBLIC, ]; - foreach ($this->propertyMap as $xmlName => $dbName) { - $calendar[$xmlName] = $row[$dbName]; - } - + $calendar = $this->rowToCalendar($row, $calendar); $calendar = $this->addOwnerPrincipalToCalendar($calendar); $calendar = $this->addResourceTypeToCalendar($row, $calendar); @@ -679,7 +665,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @return array|null */ public function getCalendarByUri($principal, $uri) { - $fields = array_values($this->propertyMap); + $fields = array_column($this->propertyMap, 0); $fields[] = 'id'; $fields[] = 'uri'; $fields[] = 'synctoken'; @@ -717,10 +703,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription '{' . Plugin::NS_CALDAV . '}schedule-calendar-transp' => new ScheduleCalendarTransp($row['transparent']?'transparent':'opaque'), ]; - foreach ($this->propertyMap as $xmlName => $dbName) { - $calendar[$xmlName] = $row[$dbName]; - } - + $calendar = $this->rowToCalendar($row, $calendar); $calendar = $this->addOwnerPrincipalToCalendar($calendar); $calendar = $this->addResourceTypeToCalendar($row, $calendar); @@ -732,7 +715,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @return array|null */ public function getCalendarById($calendarId) { - $fields = array_values($this->propertyMap); + $fields = array_column($this->propertyMap, 0); $fields[] = 'id'; $fields[] = 'uri'; $fields[] = 'synctoken'; @@ -769,10 +752,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription '{' . Plugin::NS_CALDAV . '}schedule-calendar-transp' => new ScheduleCalendarTransp($row['transparent']?'transparent':'opaque'), ]; - foreach ($this->propertyMap as $xmlName => $dbName) { - $calendar[$xmlName] = $row[$dbName]; - } - + $calendar = $this->rowToCalendar($row, $calendar); $calendar = $this->addOwnerPrincipalToCalendar($calendar); $calendar = $this->addResourceTypeToCalendar($row, $calendar); @@ -863,7 +843,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription $values['transparent'] = (int) ($properties[$transp]->getValue() === 'transparent'); } - foreach ($this->propertyMap as $xmlName => $dbName) { + foreach ($this->propertyMap as $xmlName => [$dbName, $type]) { if (isset($properties[$xmlName])) { $values[$dbName] = $properties[$xmlName]; } @@ -912,7 +892,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription $newValues[$fieldName] = (int) ($propertyValue->getValue() === 'transparent'); break; default: - $fieldName = $this->propertyMap[$propertyName]; + $fieldName = $this->propertyMap[$propertyName][0]; $newValues[$fieldName] = $propertyValue; break; } @@ -1109,7 +1089,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription 'size' => (int) $row['size'], 'component' => strtolower($row['componenttype']), 'classification' => (int) $row['classification'], - '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => $row['deleted_at'], + '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => $row['deleted_at'] === null ? $row['deleted_at'] : (int) $row['deleted_at'], ]; } $stmt->closeCursor(); @@ -1148,7 +1128,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription 'size' => (int)$row['size'], 'component' => strtolower($row['componenttype']), 'classification' => (int)$row['classification'], - '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => $row['deleted_at'], + '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => $row['deleted_at'] === null ? $row['deleted_at'] : (int) $row['deleted_at'], ]; } $stmt->closeCursor(); @@ -3263,4 +3243,23 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription } return $calendar; } + + /** + * Amend the calendar info with database row data + * + * @param array $row + * @param array $calendar + * + * @return array + */ + private function rowToCalendar($row, array $calendar): array { + foreach ($this->propertyMap as $xmlName => [$dbName, $type]) { + $value = $row[$dbName]; + if ($value !== null) { + settype($value, $type); + } + $calendar[$xmlName] = $value; + } + return $calendar; + } } -- cgit v1.2.3 From 941e560b5e144591bfb7c5e57a2a5737f792b630 Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Wed, 29 Dec 2021 15:10:38 +0100 Subject: Fix column/property type of the calendar order Signed-off-by: Christoph Wurst --- apps/dav/lib/CalDAV/CalDavBackend.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index ab3409b3bf0..981f180b647 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -153,7 +153,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription '{DAV:}displayname' => ['displayname', 'string'], '{urn:ietf:params:xml:ns:caldav}calendar-description' => ['description', 'string'], '{urn:ietf:params:xml:ns:caldav}calendar-timezone' => ['timezone', 'string'], - '{http://apple.com/ns/ical/}calendar-order' => ['calendarorder', 'string'], + '{http://apple.com/ns/ical/}calendar-order' => ['calendarorder', 'int'], '{http://apple.com/ns/ical/}calendar-color' => ['calendarcolor', 'string'], '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => ['deleted_at', 'int'], ]; -- cgit v1.2.3 From 288f07a5a4c0e106672c5e1afee13fd85108f8a9 Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Wed, 29 Dec 2021 15:26:49 +0100 Subject: Fix CalDAV subscriptions calendarorder column/prop type Signed-off-by: Christoph Wurst --- apps/dav/lib/CalDAV/CalDavBackend.php | 58 ++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index 981f180b647..f0d332adab5 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -97,6 +97,7 @@ use Sabre\VObject\Reader; use Sabre\VObject\Recur\EventIterator; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\GenericEvent; +use function array_column; use function array_merge; use function array_values; use function explode; @@ -164,13 +165,13 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @var array */ public $subscriptionPropertyMap = [ - '{DAV:}displayname' => 'displayname', - '{http://apple.com/ns/ical/}refreshrate' => 'refreshrate', - '{http://apple.com/ns/ical/}calendar-order' => 'calendarorder', - '{http://apple.com/ns/ical/}calendar-color' => 'calendarcolor', - '{http://calendarserver.org/ns/}subscribed-strip-todos' => 'striptodos', - '{http://calendarserver.org/ns/}subscribed-strip-alarms' => 'stripalarms', - '{http://calendarserver.org/ns/}subscribed-strip-attachments' => 'stripattachments', + '{DAV:}displayname' => ['displayname', 'string'], + '{http://apple.com/ns/ical/}refreshrate' => ['refreshrate', 'string'], + '{http://apple.com/ns/ical/}calendar-order' => ['calendarorder', 'int'], + '{http://apple.com/ns/ical/}calendar-color' => ['calendarcolor', 'string'], + '{http://calendarserver.org/ns/}subscribed-strip-todos' => ['striptodos', 'bool'], + '{http://calendarserver.org/ns/}subscribed-strip-alarms' => ['stripalarms', 'string'], + '{http://calendarserver.org/ns/}subscribed-strip-attachments' => ['stripattachments', 'string'], ]; /** @@ -763,7 +764,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @param $subscriptionId */ public function getSubscriptionById($subscriptionId) { - $fields = array_values($this->subscriptionPropertyMap); + $fields = array_column($this->subscriptionPropertyMap, 0); $fields[] = 'id'; $fields[] = 'uri'; $fields[] = 'source'; @@ -795,13 +796,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription '{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0', ]; - foreach ($this->subscriptionPropertyMap as $xmlName => $dbName) { - if (!is_null($row[$dbName])) { - $subscription[$xmlName] = $row[$dbName]; - } - } - - return $subscription; + return $this->rowToSubscription($row, $subscription); } /** @@ -2432,7 +2427,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @return array */ public function getSubscriptionsForUser($principalUri) { - $fields = array_values($this->subscriptionPropertyMap); + $fields = array_column($this->subscriptionPropertyMap, 0); $fields[] = 'id'; $fields[] = 'uri'; $fields[] = 'source'; @@ -2460,13 +2455,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription '{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0', ]; - foreach ($this->subscriptionPropertyMap as $xmlName => $dbName) { - if (!is_null($row[$dbName])) { - $subscription[$xmlName] = $row[$dbName]; - } - } - - $subscriptions[] = $subscription; + $subscriptions[] = $this->rowToSubscription($row, $subscription); } return $subscriptions; @@ -2497,7 +2486,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription $propertiesBoolean = ['striptodos', 'stripalarms', 'stripattachments']; - foreach ($this->subscriptionPropertyMap as $xmlName => $dbName) { + foreach ($this->subscriptionPropertyMap as $xmlName => [$dbName, $type]) { if (array_key_exists($xmlName, $properties)) { $values[$dbName] = $properties[$xmlName]; if (in_array($dbName, $propertiesBoolean)) { @@ -2559,7 +2548,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription if ($propertyName === '{http://calendarserver.org/ns/}source') { $newValues['source'] = $propertyValue->getHref(); } else { - $fieldName = $this->subscriptionPropertyMap[$propertyName]; + $fieldName = $this->subscriptionPropertyMap[$propertyName][0]; $newValues[$fieldName] = $propertyValue; } } @@ -3262,4 +3251,23 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription } return $calendar; } + + /** + * Amend the subscription info with database row data + * + * @param array $row + * @param array $subscription + * + * @return array + */ + private function rowToSubscription($row, array $subscription): array { + foreach ($this->subscriptionPropertyMap as $xmlName => [$dbName, $type]) { + $value = $row[$dbName]; + if ($value !== null) { + settype($value, $type); + } + $subscription[$xmlName] = $value; + } + return $subscription; + } } -- cgit v1.2.3