MultiGetExportPlugin.php 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace OCA\DAV\CardDAV;
  8. use OCP\AppFramework\Http;
  9. use Sabre\DAV;
  10. use Sabre\DAV\Server;
  11. use Sabre\HTTP\RequestInterface;
  12. use Sabre\HTTP\ResponseInterface;
  13. class MultiGetExportPlugin extends DAV\ServerPlugin {
  14. /** @var Server */
  15. protected $server;
  16. /**
  17. * Initializes the plugin and registers event handlers
  18. *
  19. * @param Server $server
  20. * @return void
  21. */
  22. public function initialize(Server $server) {
  23. $this->server = $server;
  24. $this->server->on('afterMethod:REPORT', [$this, 'httpReport'], 90);
  25. }
  26. /**
  27. * Intercepts REPORT requests
  28. *
  29. * @param RequestInterface $request
  30. * @param ResponseInterface $response
  31. * @return bool
  32. */
  33. public function httpReport(RequestInterface $request, ResponseInterface $response) {
  34. $queryParams = $request->getQueryParameters();
  35. if (!array_key_exists('export', $queryParams)) {
  36. return;
  37. }
  38. // Only handling xml
  39. $contentType = (string)$response->getHeader('Content-Type');
  40. if (!str_contains($contentType, 'application/xml') && !str_contains($contentType, 'text/xml')) {
  41. return;
  42. }
  43. $this->server->transactionType = 'vcf-multi-get-intercept-and-export';
  44. // Get the xml response
  45. $responseBody = $response->getBodyAsString();
  46. $responseXml = $this->server->xml->parse($responseBody);
  47. // Reduce the vcards into one string
  48. $output = array_reduce($responseXml->getResponses(), function ($vcf, $card) {
  49. $vcf .= $card->getResponseProperties()[200]['{urn:ietf:params:xml:ns:carddav}address-data'] . PHP_EOL;
  50. return $vcf;
  51. }, '');
  52. // Build and override the response
  53. $filename = 'vcfexport-' . date('Y-m-d') . '.vcf';
  54. $response->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"');
  55. $response->setHeader('Content-Type', 'text/vcard');
  56. $response->setStatus(Http::STATUS_OK);
  57. $response->setBody($output);
  58. return true;
  59. }
  60. /**
  61. * Returns a plugin name.
  62. *
  63. * Using this name other plugins will be able to access other plugins
  64. * using \Sabre\DAV\Server::getPlugin
  65. *
  66. * @return string
  67. */
  68. public function getPluginName() {
  69. return 'vcf-multi-get-intercept-and-export';
  70. }
  71. /**
  72. * Returns a bunch of meta-data about the plugin.
  73. *
  74. * Providing this information is optional, and is mainly displayed by the
  75. * Browser plugin.
  76. *
  77. * The description key in the returned array may contain html and will not
  78. * be sanitized.
  79. *
  80. * @return array
  81. */
  82. public function getPluginInfo() {
  83. return [
  84. 'name' => $this->getPluginName(),
  85. 'description' => 'Intercept a multi-get request and return a single vcf file instead.'
  86. ];
  87. }
  88. }