3232
3333use OCP \AppFramework \Db \TTransactional ;
3434use OCP \AppFramework \Http ;
35+ use OCP \Http \Client \IClientService ;
3536use OCP \IDBConnection ;
3637use OCP \IUser ;
3738use OCP \IUserManager ;
39+ use Psr \Http \Client \ClientExceptionInterface ;
3840use Psr \Log \LoggerInterface ;
39- use Sabre \DAV \Client ;
4041use Sabre \DAV \Xml \Response \MultiStatus ;
4142use Sabre \DAV \Xml \Service ;
42- use Sabre \HTTP \ClientHttpException ;
4343use Sabre \VObject \Reader ;
4444use function is_null ;
4545
@@ -54,18 +54,21 @@ class SyncService {
5454 private ?array $ localSystemAddressBook = null ;
5555 private Converter $ converter ;
5656 protected string $ certPath ;
57+ private IClientService $ clientService ;
5758
5859 public function __construct (CardDavBackend $ backend ,
5960 IUserManager $ userManager ,
6061 IDBConnection $ dbConnection ,
6162 LoggerInterface $ logger ,
62- Converter $ converter ) {
63+ Converter $ converter ,
64+ IClientService $ clientService ) {
6365 $ this ->backend = $ backend ;
6466 $ this ->userManager = $ userManager ;
6567 $ this ->logger = $ logger ;
6668 $ this ->converter = $ converter ;
6769 $ this ->certPath = '' ;
6870 $ this ->dbConnection = $ dbConnection ;
71+ $ this ->clientService = $ clientService ;
6972 }
7073
7174 /**
@@ -79,7 +82,7 @@ public function syncRemoteAddressBook(string $url, string $userName, string $add
7982 // 2. query changes
8083 try {
8184 $ response = $ this ->requestSyncReport ($ url , $ userName , $ addressBookUrl , $ sharedSecret , $ syncToken );
82- } catch (ClientHttpException $ ex ) {
85+ } catch (ClientExceptionInterface $ ex ) {
8386 if ($ ex ->getCode () === Http::STATUS_UNAUTHORIZED ) {
8487 // remote server revoked access to the address book, remove it
8588 $ this ->backend ->deleteAddressBook ($ addressBookId );
@@ -99,9 +102,9 @@ public function syncRemoteAddressBook(string $url, string $userName, string $add
99102 $ this ->atomic (function () use ($ addressBookId , $ cardUri , $ vCard ) {
100103 $ existingCard = $ this ->backend ->getCard ($ addressBookId , $ cardUri );
101104 if ($ existingCard === false ) {
102- $ this ->backend ->createCard ($ addressBookId , $ cardUri , $ vCard[ ' body ' ] );
105+ $ this ->backend ->createCard ($ addressBookId , $ cardUri , $ vCard );
103106 } else {
104- $ this ->backend ->updateCard ($ addressBookId , $ cardUri , $ vCard[ ' body ' ] );
107+ $ this ->backend ->updateCard ($ addressBookId , $ cardUri , $ vCard );
105108 }
106109 }, $ this ->dbConnection );
107110 } else {
@@ -128,63 +131,57 @@ public function ensureSystemAddressBookExists(string $principal, string $uri, ar
128131 }
129132
130133 /**
131- * Check if there is a valid certPath we should use
134+ * @throws ClientExceptionInterface
132135 */
133- protected function getCertPath (): string {
134-
135- // we already have a valid certPath
136- if ($ this ->certPath !== '' ) {
137- return $ this ->certPath ;
138- }
139-
140- $ certManager = \OC ::$ server ->getCertificateManager ();
141- $ certPath = $ certManager ->getAbsoluteBundlePath ();
142- if (file_exists ($ certPath )) {
143- $ this ->certPath = $ certPath ;
144- }
136+ protected function requestSyncReport (string $ url , string $ userName , string $ addressBookUrl , string $ sharedSecret , ?string $ syncToken ): array {
137+ $ client = $ this ->clientService ->newClient ();
145138
146- return $ this -> certPath ;
147- }
139+ // the trailing slash is important for merging base_uri and uri
140+ $ url = rtrim ( $ url , ' / ' ) . ' / ' ;
148141
149- protected function getClient ( string $ url , string $ userName , string $ sharedSecret ): Client {
150- $ settings = [
151- 'baseUri ' => $ url . ' / ' ,
152- 'userName ' => $ userName ,
153- 'password ' => $ sharedSecret ,
142+ $ options = [
143+ ' auth ' => [ $ userName , $ sharedSecret ],
144+ 'base_uri ' => $ url ,
145+ 'body ' => $ this -> buildSyncCollectionRequestBody ( $ syncToken ) ,
146+ 'headers ' => [ ' Content-Type ' => ' application/xml ' ]
154147 ];
155- $ client = new Client ($ settings );
156- $ certPath = $ this ->getCertPath ();
157- $ client ->setThrowExceptions (true );
158148
159- if ($ certPath !== '' && !str_starts_with ($ url , 'http:// ' )) {
160- $ client ->addCurlSetting (CURLOPT_CAINFO , $ this ->certPath );
161- }
149+ $ response = $ client ->request (
150+ 'REPORT ' ,
151+ $ addressBookUrl ,
152+ $ options
153+ );
154+
155+ $ body = $ response ->getBody ();
156+ assert (is_string ($ body ));
162157
163- return $ client ;
158+ return $ this -> parseMultiStatus ( $ body ) ;
164159 }
165160
166- protected function requestSyncReport (string $ url , string $ userName , string $ addressBookUrl , string $ sharedSecret , ? string $ syncToken ): array {
167- $ client = $ this ->getClient ( $ url , $ userName , $ sharedSecret );
161+ protected function download (string $ url , string $ userName , string $ sharedSecret , string $ resourcePath ): string {
162+ $ client = $ this ->clientService -> newClient ( );
168163
169- $ body = $ this ->buildSyncCollectionRequestBody ($ syncToken );
164+ // the trailing slash is important for merging base_uri and uri
165+ $ url = rtrim ($ url , '/ ' ) . '/ ' ;
170166
171- $ response = $ client ->request ('REPORT ' , $ addressBookUrl , $ body , [
172- 'Content-Type ' => 'application/xml '
173- ]);
167+ $ options = [
168+ 'auth ' => [$ userName , $ sharedSecret ],
169+ 'base_uri ' => $ url ,
170+ ];
174171
175- return $ this ->parseMultiStatus ($ response ['body ' ]);
176- }
172+ $ response = $ client ->get (
173+ $ resourcePath ,
174+ $ options
175+ );
177176
178- protected function download (string $ url , string $ userName , string $ sharedSecret , string $ resourcePath ): array {
179- $ client = $ this ->getClient ($ url , $ userName , $ sharedSecret );
180- return $ client ->request ('GET ' , $ resourcePath );
177+ return (string )$ response ->getBody ();
181178 }
182179
183180 private function buildSyncCollectionRequestBody (?string $ syncToken ): string {
184181 $ dom = new \DOMDocument ('1.0 ' , 'UTF-8 ' );
185182 $ dom ->formatOutput = true ;
186183 $ root = $ dom ->createElementNS ('DAV: ' , 'd:sync-collection ' );
187- $ sync = $ dom ->createElement ('d:sync-token ' , $ syncToken );
184+ $ sync = $ dom ->createElement ('d:sync-token ' , $ syncToken ?? '' );
188185 $ prop = $ dom ->createElement ('d:prop ' );
189186 $ cont = $ dom ->createElement ('d:getcontenttype ' );
190187 $ etag = $ dom ->createElement ('d:getetag ' );
0 commit comments