diff options
Diffstat (limited to 'apps/dav/lib/Connector/Sabre/AppleQuirksPlugin.php')
-rw-r--r-- | apps/dav/lib/Connector/Sabre/AppleQuirksPlugin.php | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/apps/dav/lib/Connector/Sabre/AppleQuirksPlugin.php b/apps/dav/lib/Connector/Sabre/AppleQuirksPlugin.php new file mode 100644 index 00000000000..6c50f5682b7 --- /dev/null +++ b/apps/dav/lib/Connector/Sabre/AppleQuirksPlugin.php @@ -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; + } +} |