]> source.dussan.org Git - nextcloud-server.git/commitdiff
apps/dav: add some OSX specific quirks. 36800/head
authorClaus-Justus Heine <himself@claus-justus-heine.de>
Tue, 21 Feb 2023 20:17:34 +0000 (21:17 +0100)
committerClaus-Justus Heine <himself@claus-justus-heine.de>
Tue, 7 Mar 2023 15:23:30 +0000 (16:23 +0100)
Signed-off-by: Claus-Justus Heine <himself@claus-justus-heine.de>
apps/dav/composer/composer/autoload_classmap.php
apps/dav/composer/composer/autoload_static.php
apps/dav/lib/Connector/Sabre/AppleQuirksPlugin.php [new file with mode: 0644]
apps/dav/lib/Server.php

index a100dac1d85c335da93bbc8a891f463f3c04077e..558934dd87c7050c3ede82da07605a2d8be75a8c 100644 (file)
@@ -143,6 +143,7 @@ return array(
     'OCA\\DAV\\Connector\\LegacyDAVACL' => $baseDir . '/../lib/Connector/LegacyDAVACL.php',
     'OCA\\DAV\\Connector\\PublicAuth' => $baseDir . '/../lib/Connector/PublicAuth.php',
     'OCA\\DAV\\Connector\\Sabre\\AnonymousOptionsPlugin' => $baseDir . '/../lib/Connector/Sabre/AnonymousOptionsPlugin.php',
+    'OCA\\DAV\\Connector\\Sabre\\AppleQuirksPlugin' => $baseDir . '/../lib/Connector/Sabre/AppleQuirksPlugin.php',
     'OCA\\DAV\\Connector\\Sabre\\Auth' => $baseDir . '/../lib/Connector/Sabre/Auth.php',
     'OCA\\DAV\\Connector\\Sabre\\BearerAuth' => $baseDir . '/../lib/Connector/Sabre/BearerAuth.php',
     'OCA\\DAV\\Connector\\Sabre\\BlockLegacyClientPlugin' => $baseDir . '/../lib/Connector/Sabre/BlockLegacyClientPlugin.php',
index 4187bb6c6f39eb6819f72922581cef041d14e015..11fa4031758db6e9ef92e479056611d9dc64709d 100644 (file)
@@ -158,6 +158,7 @@ class ComposerStaticInitDAV
         'OCA\\DAV\\Connector\\LegacyDAVACL' => __DIR__ . '/..' . '/../lib/Connector/LegacyDAVACL.php',
         'OCA\\DAV\\Connector\\PublicAuth' => __DIR__ . '/..' . '/../lib/Connector/PublicAuth.php',
         'OCA\\DAV\\Connector\\Sabre\\AnonymousOptionsPlugin' => __DIR__ . '/..' . '/../lib/Connector/Sabre/AnonymousOptionsPlugin.php',
+        'OCA\\DAV\\Connector\\Sabre\\AppleQuirksPlugin' => __DIR__ . '/..' . '/../lib/Connector/Sabre/AppleQuirksPlugin.php',
         'OCA\\DAV\\Connector\\Sabre\\Auth' => __DIR__ . '/..' . '/../lib/Connector/Sabre/Auth.php',
         'OCA\\DAV\\Connector\\Sabre\\BearerAuth' => __DIR__ . '/..' . '/../lib/Connector/Sabre/BearerAuth.php',
         'OCA\\DAV\\Connector\\Sabre\\BlockLegacyClientPlugin' => __DIR__ . '/..' . '/../lib/Connector/Sabre/BlockLegacyClientPlugin.php',
diff --git a/apps/dav/lib/Connector/Sabre/AppleQuirksPlugin.php b/apps/dav/lib/Connector/Sabre/AppleQuirksPlugin.php
new file mode 100644 (file)
index 0000000..6c50f56
--- /dev/null
@@ -0,0 +1,133 @@
+<?php
+/**
+ * @copyright Copyright (c) 2023 Claus-Justus Heine
+ *
+ * @author Claus-Justus Heine <himself@claus-justus-heine.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+namespace OCA\DAV\Connector\Sabre;
+
+use Sabre\DAV\Server;
+use Sabre\DAV\ServerPlugin;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+
+/**
+ * A plugin which tries to work-around peculiarities of the MacOS DAV client
+ * apps. The following problems are addressed:
+ *
+ * - OSX calendar client sends REPORT requests to a random principal
+ *   collection but expects to find all principals (forgot to set
+ *   {DAV:}principal-property-search flag?)
+ */
+class AppleQuirksPlugin extends ServerPlugin {
+
+       /*
+       private const OSX_CALENDAR_AGENT = 'CalendarAgent';
+       private const OSX_DATAACCESSD_AGENT = 'dataaccessd';
+       private const OSX_ACCOUNTSD_AGENT = 'accountsd';
+       private const OSX_CONTACTS_AGENT = 'AddressBookCore';
+       */
+
+       private const OSX_AGENT_PREFIX = 'macOS';
+
+       /** @var bool */
+       private $isMacOSDavAgent = false;
+
+       /**
+     * Sets up the plugin.
+     *
+     * This method is automatically called by the server class.
+        *
+        * @return void
+     */
+    public function initialize(Server $server)
+    {
+               $server->on('beforeMethod:REPORT', [$this, 'beforeReport'], 0);
+               $server->on('report', [$this, 'report'], 0);
+       }
+
+       /**
+     * Triggered before any method is handled.
+        *
+        * @return void
+     */
+    public function beforeReport(RequestInterface $request, ResponseInterface $response)
+    {
+               $userAgent = $request->getRawServerValue('HTTP_USER_AGENT') ?? 'unknown';
+               $this->isMacOSDavAgent = $this->isMacOSUserAgent($userAgent);
+       }
+
+       /**
+     * This method handles HTTP REPORT requests.
+     *
+     * @param string $reportName
+     * @param mixed  $report
+     * @param mixed  $path
+        *
+        * @return bool
+     */
+    public function report($reportName, $report, $path)
+    {
+               if ($reportName == '{DAV:}principal-property-search' && $this->isMacOSDavAgent) {
+                       /** @var \Sabre\DAVACL\Xml\Request\PrincipalPropertySearchReport $report */
+                       $report->applyToPrincipalCollectionSet = true;
+               }
+               return true;
+       }
+
+       /**
+        * Check whether the given $userAgent string pretends to originate from OSX.
+        *
+        * @param string $userAgent
+        *
+        * @return bool
+        */
+       protected function isMacOSUserAgent(string $userAgent):bool
+       {
+               return str_starts_with(self::OSX_AGENT_PREFIX, $userAgent);
+       }
+
+       /**
+        * Decode the given OSX DAV agent string.
+        *
+        * @param string $agent
+        *
+        * @return null|array
+        */
+       protected function decodeMacOSAgentString(string $userAgent):?array
+       {
+               // OSX agent string is like: macOS/13.2.1 (22D68) dataaccessd/1.0
+               if (preg_match('|^' . self::OSX_AGENT_PREFIX . '/([0-9]+)\\.([0-9]+)\\.([0-9]+)\s+\((\w+)\)\s+([^/]+)/([0-9]+)(?:\\.([0-9]+))?(?:\\.([0-9]+))?$|i', $userAgent, $matches)) {
+                       return [
+                               'macOSVersion' => [
+                                       'major' => $matches[1],
+                                       'minor' => $matches[2],
+                                       'patch' => $matches[3],
+                               ],
+                               'macOSAgent' => $matches[5],
+                               'macOSAgentVersion' => [
+                                       'major' => $matches[6],
+                                       'minor' => $matches[7] ?? null,
+                                       'patch' => $matches[8] ?? null,
+                               ],
+                       ];
+               }
+               return null;
+       }
+}
index a5833e5175f48ab3ddef9b8480d17918161f94d0..887f8c44dab2c471388565e566c647825153b80f 100644 (file)
@@ -110,6 +110,8 @@ class Server {
                // Add maintenance plugin
                $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\MaintenancePlugin(\OC::$server->getConfig(), \OC::$server->getL10N('dav')));
 
+               $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\AppleQuirksPlugin());
+
                // Backends
                $authBackend = new Auth(
                        \OC::$server->getSession(),