diff options
author | Daniel Kesselberg <mail@danielkesselberg.de> | 2024-09-27 19:16:59 +0200 |
---|---|---|
committer | Daniel Kesselberg <mail@danielkesselberg.de> | 2024-10-01 21:37:18 +0200 |
commit | 8026f7afba51e24a9a24ef58d39762a6295b7dc1 (patch) | |
tree | b05be1915e198973d23924c72f506948bb050139 /apps | |
parent | 95f1a7b0beb28ed533ea6ebae8bf26879e105f70 (diff) | |
download | nextcloud-server-8026f7afba51e24a9a24ef58d39762a6295b7dc1.tar.gz nextcloud-server-8026f7afba51e24a9a24ef58d39762a6295b7dc1.zip |
fix: make federation address book sync work with allow_local_remote_servers = falsebackport/48451/stable30
Client.preventLocalAddress expects an absolute URL, which means the base_uri option cannot be used.
Signed-off-by: Daniel Kesselberg <mail@danielkesselberg.de>
Diffstat (limited to 'apps')
-rw-r--r-- | apps/dav/lib/CardDAV/SyncService.php | 46 | ||||
-rw-r--r-- | apps/dav/tests/unit/CardDAV/SyncServiceTest.php | 55 |
2 files changed, 91 insertions, 10 deletions
diff --git a/apps/dav/lib/CardDAV/SyncService.php b/apps/dav/lib/CardDAV/SyncService.php index 56cbe5255f4..356903b3f69 100644 --- a/apps/dav/lib/CardDAV/SyncService.php +++ b/apps/dav/lib/CardDAV/SyncService.php @@ -108,25 +108,54 @@ class SyncService { }, $this->dbConnection); } + private function prepareUri(string $host, string $path): string { + /* + * The trailing slash is important for merging the uris together. + * + * $host is stored in oc_trusted_servers.url and usually without a trailing slash. + * + * Example for a report request + * + * $host = 'https://server.internal/cloud' + * $path = 'remote.php/dav/addressbooks/system/system/system' + * + * Without the trailing slash, the webroot is missing: + * https://server.internal/remote.php/dav/addressbooks/system/system/system + * + * Example for a download request + * + * $host = 'https://server.internal/cloud' + * $path = '/cloud/remote.php/dav/addressbooks/system/system/system/Database:alice.vcf' + * + * The response from the remote usually contains the webroot already and must be normalized to: + * https://server.internal/cloud/remote.php/dav/addressbooks/system/system/system/Database:alice.vcf + */ + $host = rtrim($host, '/') . '/'; + + $uri = \GuzzleHttp\Psr7\UriResolver::resolve( + \GuzzleHttp\Psr7\Utils::uriFor($host), + \GuzzleHttp\Psr7\Utils::uriFor($path) + ); + + return (string)$uri; + } + /** * @throws ClientExceptionInterface */ protected function requestSyncReport(string $url, string $userName, string $addressBookUrl, string $sharedSecret, ?string $syncToken): array { $client = $this->clientService->newClient(); - - // the trailing slash is important for merging base_uri and uri - $url = rtrim($url, '/') . '/'; + $uri = $this->prepareUri($url, $addressBookUrl); $options = [ 'auth' => [$userName, $sharedSecret], - 'base_uri' => $url, 'body' => $this->buildSyncCollectionRequestBody($syncToken), 'headers' => ['Content-Type' => 'application/xml'] ]; $response = $client->request( 'REPORT', - $addressBookUrl, + $uri, $options ); @@ -138,17 +167,14 @@ class SyncService { protected function download(string $url, string $userName, string $sharedSecret, string $resourcePath): string { $client = $this->clientService->newClient(); - - // the trailing slash is important for merging base_uri and uri - $url = rtrim($url, '/') . '/'; + $uri = $this->prepareUri($url, $resourcePath); $options = [ 'auth' => [$userName, $sharedSecret], - 'base_uri' => $url, ]; $response = $client->get( - $resourcePath, + $uri, $options ); diff --git a/apps/dav/tests/unit/CardDAV/SyncServiceTest.php b/apps/dav/tests/unit/CardDAV/SyncServiceTest.php index 570c55eab05..db99f73306d 100644 --- a/apps/dav/tests/unit/CardDAV/SyncServiceTest.php +++ b/apps/dav/tests/unit/CardDAV/SyncServiceTest.php @@ -426,4 +426,59 @@ END:VCARD'; [] ); } + + /** + * @dataProvider providerUseAbsoluteUriReport + */ + public function testUseAbsoluteUriReport(string $host, string $expected): void { + $body = '<?xml version="1.0"?> +<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:card="urn:ietf:params:xml:ns:carddav" xmlns:oc="http://owncloud.org/ns"> + <d:sync-token>http://sabre.io/ns/sync/1</d:sync-token> +</d:multistatus>'; + + $requestResponse = new Response(new PsrResponse( + 207, + ['Content-Type' => 'application/xml; charset=utf-8', 'Content-Length' => strlen($body)], + $body + )); + + $this->client + ->method('request') + ->with( + 'REPORT', + $this->callback(function ($uri) use ($expected) { + $this->assertEquals($expected, $uri); + return true; + }), + $this->callback(function ($options) { + $this->assertIsArray($options); + return true; + }), + ) + ->willReturn($requestResponse); + + $this->service->syncRemoteAddressBook( + $host, + 'system', + 'remote.php/dav/addressbooks/system/system/system', + '1234567890', + null, + '1', + 'principals/system/system', + [] + ); + } + + public function providerUseAbsoluteUriReport(): array { + return [ + ['https://server.internal', 'https://server.internal/remote.php/dav/addressbooks/system/system/system'], + ['https://server.internal/', 'https://server.internal/remote.php/dav/addressbooks/system/system/system'], + ['https://server.internal/nextcloud', 'https://server.internal/nextcloud/remote.php/dav/addressbooks/system/system/system'], + ['https://server.internal/nextcloud/', 'https://server.internal/nextcloud/remote.php/dav/addressbooks/system/system/system'], + ['https://server.internal:8080', 'https://server.internal:8080/remote.php/dav/addressbooks/system/system/system'], + ['https://server.internal:8080/', 'https://server.internal:8080/remote.php/dav/addressbooks/system/system/system'], + ['https://server.internal:8080/nextcloud', 'https://server.internal:8080/nextcloud/remote.php/dav/addressbooks/system/system/system'], + ['https://server.internal:8080/nextcloud/', 'https://server.internal:8080/nextcloud/remote.php/dav/addressbooks/system/system/system'], + ]; + } } |