Skip to content

Commit

Permalink
fix(caldav): encode calendar URIs with umlauts for activities
Browse files Browse the repository at this point in the history
Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
  • Loading branch information
st3iny committed Jun 20, 2024
1 parent 392ee62 commit df28c04
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 8 deletions.
17 changes: 15 additions & 2 deletions apps/dav/lib/CalDAV/Activity/Provider/Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,15 @@ protected function generateObjectParameter(array $eventData, string $affectedUse
// The calendar app needs to be manually loaded for the routes to be loaded
OC_App::loadApp('calendar');
$linkData = $eventData['link'];
$calendarUri = $this->urlencodeLowerHex($linkData['calendar_uri']);
if ($affectedUser === $linkData['owner']) {
$objectId = base64_encode($this->url->getWebroot() . '/remote.php/dav/calendars/' . $linkData['owner'] . '/' . $linkData['calendar_uri'] . '/' . $linkData['object_uri']);
$objectId = base64_encode($this->url->getWebroot() . '/remote.php/dav/calendars/' . $linkData['owner'] . '/' . $calendarUri . '/' . $linkData['object_uri']);
} else {
// Can't use the "real" owner and calendar names here because we create a custom
// calendar for incoming shares with the name "<calendar>_shared_by_<sharer>".
// Hack: Fix the link by generating it for the incoming shared calendar instead,
// as seen from the affected user.
$objectId = base64_encode($this->url->getWebroot() . '/remote.php/dav/calendars/' . $affectedUser . '/' . $linkData['calendar_uri'] . '_shared_by_' . $linkData['owner'] . '/' . $linkData['object_uri']);
$objectId = base64_encode($this->url->getWebroot() . '/remote.php/dav/calendars/' . $affectedUser . '/' . $calendarUri . '_shared_by_' . $linkData['owner'] . '/' . $linkData['object_uri']);
}
$link = [
'view' => 'dayGridMonth',
Expand Down Expand Up @@ -241,4 +242,16 @@ private function generateClassifiedObjectParameter(array $eventData, string $aff
}
return $parameter;
}

/**
* Return urlencoded string but with lower cased hex sequences.
* The remaining casing will be untouched.
*/
private function urlencodeLowerHex(string $raw): string {
return preg_replace_callback(
'/%[0-9A-F]{2}/',
static fn (array $matches) => strtolower($matches[0]),
urlencode($raw),
);
}
}
53 changes: 47 additions & 6 deletions apps/dav/tests/unit/CalDAV/Activity/Provider/EventTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,17 +129,58 @@ public function testGenerateObjectParameter(int $id, string $name, ?array $link,
$this->assertEquals($result, $this->invokePrivate($this->provider, 'generateObjectParameter', [$objectParameter, $affectedUser]));
}

public function testGenerateObjectParameterWithSharedCalendar(): void {
$link = [
'object_uri' => 'someuuid.ics',
'calendar_uri' => 'personal',
'owner' => 'sharer'
public static function generateObjectParameterLinkEncodingDataProvider(): array {
return [
[ // Shared calendar
[
'object_uri' => 'someuuid.ics',
'calendar_uri' => 'personal',
'owner' => 'sharer'
],
base64_encode('/remote.php/dav/calendars/sharee/personal_shared_by_sharer/someuuid.ics'),
],
[ // Shared calendar with umlauts
[
'object_uri' => 'someuuid.ics',
'calendar_uri' => 'umlaut_äüöß',
'owner' => 'sharer'
],
base64_encode('/remote.php/dav/calendars/sharee/umlaut_%c3%a4%c3%bc%c3%b6%c3%9f_shared_by_sharer/someuuid.ics'),
],
[ // Shared calendar with umlauts and mixed casing
[
'object_uri' => 'someuuid.ics',
'calendar_uri' => 'Umlaut_äüöß',
'owner' => 'sharer'
],
base64_encode('/remote.php/dav/calendars/sharee/Umlaut_%c3%a4%c3%bc%c3%b6%c3%9f_shared_by_sharer/someuuid.ics'),
],
[ // Owned calendar with umlauts
[
'object_uri' => 'someuuid.ics',
'calendar_uri' => 'umlaut_äüöß',
'owner' => 'sharee'
],
base64_encode('/remote.php/dav/calendars/sharee/umlaut_%c3%a4%c3%bc%c3%b6%c3%9f/someuuid.ics'),
],
[ // Owned calendar with umlauts and mixed casing
[
'object_uri' => 'someuuid.ics',
'calendar_uri' => 'Umlaut_äüöß',
'owner' => 'sharee'
],
base64_encode('/remote.php/dav/calendars/sharee/Umlaut_%c3%a4%c3%bc%c3%b6%c3%9f/someuuid.ics'),
],
];
}

/** @dataProvider generateObjectParameterLinkEncodingDataProvider */
public function testGenerateObjectParameterLinkEncoding(array $link, string $objectId): void {
$generatedLink = [
'view' => 'dayGridMonth',
'timeRange' => 'now',
'mode' => 'sidebar',
'objectId' => base64_encode('/remote.php/dav/calendars/sharee/' . $link['calendar_uri'] . '_shared_by_sharer/' . $link['object_uri']),
'objectId' => $objectId,
'recurrenceId' => 'next'
];
$this->appManager->expects($this->once())
Expand Down

0 comments on commit df28c04

Please sign in to comment.