ExternalAddressBook.php 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace OCA\DAV\CardDAV\Integration;
  8. use Sabre\CardDAV\IAddressBook;
  9. use Sabre\DAV;
  10. /**
  11. * @since 19.0.0
  12. */
  13. abstract class ExternalAddressBook implements IAddressBook, DAV\IProperties {
  14. /** @var string */
  15. private const PREFIX = 'z-app-generated';
  16. /**
  17. * @var string
  18. *
  19. * Double dash is a valid delimiter,
  20. * because it will always split the URIs correctly:
  21. * - our prefix contains only one dash and won't be split
  22. * - appIds are not allowed to contain dashes as per spec:
  23. * > must contain only lowercase ASCII characters and underscore
  24. * - explode has a limit of three, so even if the app-generated
  25. * URI has double dashes, it won't be split
  26. */
  27. private const DELIMITER = '--';
  28. public function __construct(
  29. private string $appId,
  30. private string $uri,
  31. ) {
  32. }
  33. /**
  34. * @inheritDoc
  35. */
  36. final public function getName() {
  37. return implode(self::DELIMITER, [
  38. self::PREFIX,
  39. $this->appId,
  40. $this->uri,
  41. ]);
  42. }
  43. /**
  44. * @inheritDoc
  45. */
  46. final public function setName($name) {
  47. throw new DAV\Exception\MethodNotAllowed('Renaming address books is not yet supported');
  48. }
  49. /**
  50. * @inheritDoc
  51. */
  52. final public function createDirectory($name) {
  53. throw new DAV\Exception\MethodNotAllowed('Creating collections in address book objects is not allowed');
  54. }
  55. /**
  56. * Checks whether the address book uri is app-generated
  57. *
  58. * @param string $uri
  59. *
  60. * @return bool
  61. */
  62. public static function isAppGeneratedAddressBook(string $uri): bool {
  63. return str_starts_with($uri, self::PREFIX) && substr_count($uri, self::DELIMITER) >= 2;
  64. }
  65. /**
  66. * Splits an app-generated uri into appId and uri
  67. *
  68. * @param string $uri
  69. *
  70. * @return array
  71. */
  72. public static function splitAppGeneratedAddressBookUri(string $uri): array {
  73. $array = array_slice(explode(self::DELIMITER, $uri, 3), 1);
  74. // Check the array has expected amount of elements
  75. // and none of them is an empty string
  76. if (\count($array) !== 2 || \in_array('', $array, true)) {
  77. throw new \InvalidArgumentException('Provided address book uri was not app-generated');
  78. }
  79. return $array;
  80. }
  81. /**
  82. * Checks whether a address book name the user wants to create violates
  83. * the reserved name for URIs
  84. *
  85. * @param string $uri
  86. *
  87. * @return bool
  88. */
  89. public static function doesViolateReservedName(string $uri): bool {
  90. return str_starts_with($uri, self::PREFIX);
  91. }
  92. }