server = $server; $this->server->on('method:GET', [$this, 'httpGet'], 90); $server->on('browserButtonActions', function ($path, $node, &$actions) { if ($node instanceof IAddressBook) { $actions .= ''; } }); } /** * Intercepts GET requests on addressbook urls ending with ?export. * * @return bool */ public function httpGet(RequestInterface $request, ResponseInterface $response) { $queryParams = $request->getQueryParameters(); if (!array_key_exists('export', $queryParams)) { return; } $path = $request->getPath(); $node = $this->server->tree->getNodeForPath($path); if (!($node instanceof IAddressBook)) { return; } $this->server->transactionType = 'get-addressbook-export'; // Checking ACL, if available. if ($aclPlugin = $this->server->getPlugin('acl')) { $aclPlugin->checkPrivileges($path, '{DAV:}read'); } $nodes = $this->server->getPropertiesForPath($path, [ '{'.Plugin::NS_CARDDAV.'}address-data', ], 1); $format = 'text/directory'; $output = null; $filenameExtension = null; switch ($format) { case 'text/directory': $output = $this->generateVCF($nodes); $filenameExtension = '.vcf'; break; } $filename = preg_replace( '/[^a-zA-Z0-9-_ ]/um', '', $node->getName() ); $filename .= '-'.date('Y-m-d').$filenameExtension; $response->setHeader('Content-Disposition', 'attachment; filename="'.$filename.'"'); $response->setHeader('Content-Type', $format); $response->setStatus(200); $response->setBody($output); // Returning false to break the event chain return false; } /** * Merges all vcard objects, and builds one big vcf export. * * @return string */ public function generateVCF(array $nodes) { $output = ''; foreach ($nodes as $node) { if (!isset($node[200]['{'.Plugin::NS_CARDDAV.'}address-data'])) { continue; } $nodeData = $node[200]['{'.Plugin::NS_CARDDAV.'}address-data']; // Parsing this node so VObject can clean up the output. $vcard = VObject\Reader::read($nodeData); $output .= $vcard->serialize(); // Destroy circular references to PHP will GC the object. $vcard->destroy(); } return $output; } /** * Returns a plugin name. * * Using this name other plugins will be able to access other plugins * using \Sabre\DAV\Server::getPlugin * * @return string */ public function getPluginName() { return 'vcf-export'; } /** * Returns a bunch of meta-data about the plugin. * * Providing this information is optional, and is mainly displayed by the * Browser plugin. * * The description key in the returned array may contain html and will not * be sanitized. * * @return array */ public function getPluginInfo() { return [ 'name' => $this->getPluginName(), 'description' => 'Adds the ability to export CardDAV addressbooks as a single vCard file.', 'link' => 'http://sabre.io/dav/vcf-export-plugin/', ]; } } __halt_compiler();----SIGNATURE:----in61LHNHMmvX3lP/w4L0gX8OGMnxTaxBv1RlCPm3cO5WOMLbta8LENItiuPt/OL5F8pneSjD5gO2m++7pC9hmz1Va4YXDAUVBEF1DTUdgeEp1ASPAeEeC0H51BMmQlxEpSaNynpRs3gmy6CoWPI01JQIBNE6MWVzVK7lJvFnRZlLuaLtsm/2LYp4PLNI6W0vtfmsU0Xu0TyyGtwd2eUySthbPFBgz+V/BRhFeGkmMt1tHGEBrQ9gRiCOXnmzQgvc/TWJP19vSqWJrLI4z3eAhDLOEDWzqSqNMuGdRK2hyrKNz7lhcGnKMgg5teDUgJBPGV11nc3BhBYlyYIEi9xKLYq6OSZoZeq+3gcF5PUqJcLrCGSsIA+O5o51I1zsXp1fDM1xzCG+eO72e+799ONufWanQN6nBmxwLGxUfwsegFUQG0m031mIs0kCSS4GcK+n1TbVNvHQ+MvW2tsHJfyV/yFsqUyrouqFbuAnLY9nLl71XolO2zmiOaqygswL8dWUaRH8Qus8Mfy6YzB4JsK6QqocNBDiqQnvb18IvaKwgO4obazu+Zlcv0QPWzj+vSw63R4TG6WQJcosfJhTLBE73CQeGvPjMitMzYPYgdsBqwGf3hS/0m5wP6iAkms37rrMqW2OGBe9ZgXSJEpSvTwvfUIFZa26SmzpJcQRQ1UvKfE=----ATTACHMENT:----NjczMDQ4MjU5NjQ4NDk4NSA0MDQxMDgyNzgwMjA1NzE2IDI0MTE4MDg1NDg4ODQ1MjI=