Skip to content

Commit f23fc4d

Browse files
authored
Merge pull request #48507 from nextcloud/backport/48451/stable29
2 parents 04d0d8e + 3f117cb commit f23fc4d

File tree

2 files changed

+91
-10
lines changed

2 files changed

+91
-10
lines changed

apps/dav/lib/CardDAV/SyncService.php

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -130,25 +130,54 @@ public function ensureSystemAddressBookExists(string $principal, string $uri, ar
130130
}, $this->dbConnection);
131131
}
132132

133+
private function prepareUri(string $host, string $path): string {
134+
/*
135+
* The trailing slash is important for merging the uris together.
136+
*
137+
* $host is stored in oc_trusted_servers.url and usually without a trailing slash.
138+
*
139+
* Example for a report request
140+
*
141+
* $host = 'https://server.internal/cloud'
142+
* $path = 'remote.php/dav/addressbooks/system/system/system'
143+
*
144+
* Without the trailing slash, the webroot is missing:
145+
* https://server.internal/remote.php/dav/addressbooks/system/system/system
146+
*
147+
* Example for a download request
148+
*
149+
* $host = 'https://server.internal/cloud'
150+
* $path = '/cloud/remote.php/dav/addressbooks/system/system/system/Database:alice.vcf'
151+
*
152+
* The response from the remote usually contains the webroot already and must be normalized to:
153+
* https://server.internal/cloud/remote.php/dav/addressbooks/system/system/system/Database:alice.vcf
154+
*/
155+
$host = rtrim($host, '/') . '/';
156+
157+
$uri = \GuzzleHttp\Psr7\UriResolver::resolve(
158+
\GuzzleHttp\Psr7\Utils::uriFor($host),
159+
\GuzzleHttp\Psr7\Utils::uriFor($path)
160+
);
161+
162+
return (string)$uri;
163+
}
164+
133165
/**
134166
* @throws ClientExceptionInterface
135167
*/
136168
protected function requestSyncReport(string $url, string $userName, string $addressBookUrl, string $sharedSecret, ?string $syncToken): array {
137169
$client = $this->clientService->newClient();
138-
139-
// the trailing slash is important for merging base_uri and uri
140-
$url = rtrim($url, '/') . '/';
170+
$uri = $this->prepareUri($url, $addressBookUrl);
141171

142172
$options = [
143173
'auth' => [$userName, $sharedSecret],
144-
'base_uri' => $url,
145174
'body' => $this->buildSyncCollectionRequestBody($syncToken),
146175
'headers' => ['Content-Type' => 'application/xml']
147176
];
148177

149178
$response = $client->request(
150179
'REPORT',
151-
$addressBookUrl,
180+
$uri,
152181
$options
153182
);
154183

@@ -160,17 +189,14 @@ protected function requestSyncReport(string $url, string $userName, string $addr
160189

161190
protected function download(string $url, string $userName, string $sharedSecret, string $resourcePath): string {
162191
$client = $this->clientService->newClient();
163-
164-
// the trailing slash is important for merging base_uri and uri
165-
$url = rtrim($url, '/') . '/';
192+
$uri = $this->prepareUri($url, $resourcePath);
166193

167194
$options = [
168195
'auth' => [$userName, $sharedSecret],
169-
'base_uri' => $url,
170196
];
171197

172198
$response = $client->get(
173-
$resourcePath,
199+
$uri,
174200
$options
175201
);
176202

apps/dav/tests/unit/CardDAV/SyncServiceTest.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,4 +446,59 @@ public function testDeleteAddressbookWhenAccessRevoked(): void {
446446
[]
447447
);
448448
}
449+
450+
/**
451+
* @dataProvider providerUseAbsoluteUriReport
452+
*/
453+
public function testUseAbsoluteUriReport(string $host, string $expected): void {
454+
$body = '<?xml version="1.0"?>
455+
<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">
456+
<d:sync-token>http://sabre.io/ns/sync/1</d:sync-token>
457+
</d:multistatus>';
458+
459+
$requestResponse = new Response(new PsrResponse(
460+
207,
461+
['Content-Type' => 'application/xml; charset=utf-8', 'Content-Length' => strlen($body)],
462+
$body
463+
));
464+
465+
$this->client
466+
->method('request')
467+
->with(
468+
'REPORT',
469+
$this->callback(function ($uri) use ($expected) {
470+
$this->assertEquals($expected, $uri);
471+
return true;
472+
}),
473+
$this->callback(function ($options) {
474+
$this->assertIsArray($options);
475+
return true;
476+
}),
477+
)
478+
->willReturn($requestResponse);
479+
480+
$this->service->syncRemoteAddressBook(
481+
$host,
482+
'system',
483+
'remote.php/dav/addressbooks/system/system/system',
484+
'1234567890',
485+
null,
486+
'1',
487+
'principals/system/system',
488+
[]
489+
);
490+
}
491+
492+
public function providerUseAbsoluteUriReport(): array {
493+
return [
494+
['https://server.internal', 'https://server.internal/remote.php/dav/addressbooks/system/system/system'],
495+
['https://server.internal/', 'https://server.internal/remote.php/dav/addressbooks/system/system/system'],
496+
['https://server.internal/nextcloud', 'https://server.internal/nextcloud/remote.php/dav/addressbooks/system/system/system'],
497+
['https://server.internal/nextcloud/', 'https://server.internal/nextcloud/remote.php/dav/addressbooks/system/system/system'],
498+
['https://server.internal:8080', 'https://server.internal:8080/remote.php/dav/addressbooks/system/system/system'],
499+
['https://server.internal:8080/', 'https://server.internal:8080/remote.php/dav/addressbooks/system/system/system'],
500+
['https://server.internal:8080/nextcloud', 'https://server.internal:8080/nextcloud/remote.php/dav/addressbooks/system/system/system'],
501+
['https://server.internal:8080/nextcloud/', 'https://server.internal:8080/nextcloud/remote.php/dav/addressbooks/system/system/system'],
502+
];
503+
}
449504
}

0 commit comments

Comments
 (0)