aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorDaniel <mail@danielkesselberg.de>2024-10-02 14:53:11 +0200
committerGitHub <noreply@github.com>2024-10-02 14:53:11 +0200
commit39c6aafe72984c732ff6e27ad82684a69877efc9 (patch)
tree521f4f6c85775d9546108bfb4a040fbbb22fafc2 /apps
parent7d3bf7cf59fc7c121b94caf20f492a27481fc51a (diff)
parent8026f7afba51e24a9a24ef58d39762a6295b7dc1 (diff)
downloadnextcloud-server-39c6aafe72984c732ff6e27ad82684a69877efc9.tar.gz
nextcloud-server-39c6aafe72984c732ff6e27ad82684a69877efc9.zip
Merge pull request #48506 from nextcloud/backport/48451/stable30
[stable30] fix: make federation address book sync work with allow_local_remote_servers = false
Diffstat (limited to 'apps')
-rw-r--r--apps/dav/lib/CardDAV/SyncService.php46
-rw-r--r--apps/dav/tests/unit/CardDAV/SyncServiceTest.php55
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'],
+ ];
+ }
}