ExternalAddressBook.php 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  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. private string $appId;
  29. private string $uri;
  30. public function __construct(string $appId, string $uri) {
  31. $this->appId = $appId;
  32. $this->uri = $uri;
  33. }
  34. /**
  35. * @inheritDoc
  36. */
  37. final public function getName() {
  38. return implode(self::DELIMITER, [
  39. self::PREFIX,
  40. $this->appId,
  41. $this->uri,
  42. ]);
  43. }
  44. /**
  45. * @inheritDoc
  46. */
  47. final public function setName($name) {
  48. throw new DAV\Exception\MethodNotAllowed('Renaming address books is not yet supported');
  49. }
  50. /**
  51. * @inheritDoc
  52. */
  53. final public function createDirectory($name) {
  54. throw new DAV\Exception\MethodNotAllowed('Creating collections in address book objects is not allowed');
  55. }
  56. /**
  57. * Checks whether the address book uri is app-generated
  58. *
  59. * @param string $uri
  60. *
  61. * @return bool
  62. */
  63. public static function isAppGeneratedAddressBook(string $uri): bool {
  64. return str_starts_with($uri, self::PREFIX) && substr_count($uri, self::DELIMITER) >= 2;
  65. }
  66. /**
  67. * Splits an app-generated uri into appId and uri
  68. *
  69. * @param string $uri
  70. *
  71. * @return array
  72. */
  73. public static function splitAppGeneratedAddressBookUri(string $uri): array {
  74. $array = array_slice(explode(self::DELIMITER, $uri, 3), 1);
  75. // Check the array has expected amount of elements
  76. // and none of them is an empty string
  77. if (\count($array) !== 2 || \in_array('', $array, true)) {
  78. throw new \InvalidArgumentException('Provided address book uri was not app-generated');
  79. }
  80. return $array;
  81. }
  82. /**
  83. * Checks whether a address book name the user wants to create violates
  84. * the reserved name for URIs
  85. *
  86. * @param string $uri
  87. *
  88. * @return bool
  89. */
  90. public static function doesViolateReservedName(string $uri): bool {
  91. return str_starts_with($uri, self::PREFIX);
  92. }
  93. }