* * @author Christoph Wurst * @author Georg Ehrke * @author Morris Jobke * @author Nils Wittenbrink * @author Roeland Jago Douma * * @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 . * */ namespace OCA\DAV\Provisioning\Apple; use OCP\IL10N; use OCP\IRequest; use OCP\IURLGenerator; use OCP\IUserSession; use Sabre\DAV\Server; use Sabre\DAV\ServerPlugin; use Sabre\HTTP\RequestInterface; use Sabre\HTTP\ResponseInterface; class AppleProvisioningPlugin extends ServerPlugin { /** * @var Server */ protected $server; /** * @var IURLGenerator */ protected $urlGenerator; /** * @var IUserSession */ protected $userSession; /** * @var \OC_Defaults */ protected $themingDefaults; /** * @var IRequest */ protected $request; /** * @var IL10N */ protected $l10n; /** * @var \Closure */ protected $uuidClosure; /** * AppleProvisioningPlugin constructor. */ public function __construct( IUserSession $userSession, IURLGenerator $urlGenerator, \OC_Defaults $themingDefaults, IRequest $request, IL10N $l10n, \Closure $uuidClosure ) { $this->userSession = $userSession; $this->urlGenerator = $urlGenerator; $this->themingDefaults = $themingDefaults; $this->request = $request; $this->l10n = $l10n; $this->uuidClosure = $uuidClosure; } /** * @param Server $server */ public function initialize(Server $server) { $this->server = $server; $this->server->on('method:GET', [$this, 'httpGet'], 90); } /** * @param RequestInterface $request * @param ResponseInterface $response * @return boolean */ public function httpGet(RequestInterface $request, ResponseInterface $response):bool { if ($request->getPath() !== 'provisioning/' . AppleProvisioningNode::FILENAME) { return true; } $user = $this->userSession->getUser(); if (!$user) { return true; } $serverProtocol = $this->request->getServerProtocol(); $useSSL = ($serverProtocol === 'https'); if (!$useSSL) { $response->setStatus(200); $response->setHeader('Content-Type', 'text/plain; charset=utf-8'); $response->setBody($this->l10n->t('Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS.', [$this->themingDefaults->getName()])); return false; } $absoluteURL = $this->urlGenerator->getBaseUrl(); $parsedUrl = parse_url($absoluteURL); if (isset($parsedUrl['port'])) { $serverPort = $parsedUrl['port']; } else { $serverPort = 443; } $server_url = $parsedUrl['host']; $description = $this->themingDefaults->getName(); $userId = $user->getUID(); $reverseDomain = implode('.', array_reverse(explode('.', $parsedUrl['host']))); $caldavUUID = call_user_func($this->uuidClosure); $carddavUUID = call_user_func($this->uuidClosure); $profileUUID = call_user_func($this->uuidClosure); $caldavIdentifier = $reverseDomain . '.' . $caldavUUID; $carddavIdentifier = $reverseDomain . '.' . $carddavUUID; $profileIdentifier = $reverseDomain . '.' . $profileUUID; $caldavDescription = $this->l10n->t('Configures a CalDAV account'); $caldavDisplayname = $description . ' CalDAV'; $carddavDescription = $this->l10n->t('Configures a CardDAV account'); $carddavDisplayname = $description . ' CardDAV'; $filename = $userId . '-' . AppleProvisioningNode::FILENAME; $xmlSkeleton = $this->getTemplate(); $body = vsprintf($xmlSkeleton, array_map(function ($v) { return \htmlspecialchars($v, ENT_XML1, 'UTF-8'); }, [ $description, $server_url, $userId, $serverPort, $caldavDescription, $caldavDisplayname, $caldavIdentifier, $caldavUUID, $description, $server_url, $userId, $serverPort, $carddavDescription, $carddavDisplayname, $carddavIdentifier, $carddavUUID, $description, $profileIdentifier, $profileUUID ] )); $response->setStatus(200); $response->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"'); $response->setHeader('Content-Type', 'application/xml; charset=utf-8'); $response->setBody($body); return false; } /** * @return string */ private function getTemplate():string { return << PayloadContent CalDAVAccountDescription %s CalDAVHostName %s CalDAVUsername %s CalDAVUseSSL CalDAVPort %s PayloadDescription %s PayloadDisplayName %s PayloadIdentifier %s PayloadType com.apple.caldav.account PayloadUUID %s PayloadVersion 1 CardDAVAccountDescription %s CardDAVHostName %s CardDAVUsername %s CardDAVUseSSL CardDAVPort %s PayloadDescription %s PayloadDisplayName %s PayloadIdentifier %s PayloadType com.apple.carddav.account PayloadUUID %s PayloadVersion 1 PayloadDisplayName %s PayloadIdentifier %s PayloadRemovalDisallowed PayloadType Configuration PayloadUUID %s PayloadVersion 1 EOF; } }