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; } }