MultiGetExportPlugin.php 2.6 KB

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