From 631b5fc64b3c61a683b2b595f2237b5dcd6adb59 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Wed, 8 Dec 2021 16:40:39 +0100 Subject: [PATCH 1/7] Only wildcard search if enumeration is allowed Signed-off-by: Joas Schilling --- apps/dav/lib/CardDAV/AddressBookImpl.php | 1 + apps/dav/lib/CardDAV/CardDavBackend.php | 6 +++++- lib/private/Collaboration/Collaborators/MailPlugin.php | 10 +++++++++- lib/private/ContactsManager.php | 1 + lib/public/Contacts/IManager.php | 1 + lib/public/IAddressBook.php | 1 + 6 files changed, 18 insertions(+), 2 deletions(-) diff --git a/apps/dav/lib/CardDAV/AddressBookImpl.php b/apps/dav/lib/CardDAV/AddressBookImpl.php index 8b0d494fd0167..1b74f329f1fa9 100644 --- a/apps/dav/lib/CardDAV/AddressBookImpl.php +++ b/apps/dav/lib/CardDAV/AddressBookImpl.php @@ -107,6 +107,7 @@ public function getDisplayName() { * - 'escape_like_param' - If set to false wildcards _ and % are not escaped * - 'limit' - Set a numeric limit for the search results * - 'offset' - Set the offset for the limited search results + * - 'wildcard' - Whether the search should use wildcards * @return array an array of contacts which are arrays of key-value-pairs * example result: * [ diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php index 13926ef12ce38..403c4646e4784 100644 --- a/apps/dav/lib/CardDAV/CardDavBackend.php +++ b/apps/dav/lib/CardDAV/CardDavBackend.php @@ -1024,6 +1024,7 @@ public function updateShares(IShareable $shareable, $add, $remove) { * - 'escape_like_param' - If set to false wildcards _ and % are not escaped, otherwise they are * - 'limit' - Set a numeric limit for the search results * - 'offset' - Set the offset for the limited search results + * - 'wildcard' - Whether the search should use wildcards * @return array an array of contacts which are arrays of key-value-pairs */ public function search($addressBookId, $pattern, $searchProperties, $options = []): array { @@ -1062,6 +1063,7 @@ private function searchByAddressBookIds(array $addressBookIds, array $searchProperties, array $options = []): array { $escapePattern = !\array_key_exists('escape_like_param', $options) || $options['escape_like_param'] !== false; + $useWildcards = !\array_key_exists('wildcard', $options) || $options['wildcard'] !== false; $query2 = $this->db->getQueryBuilder(); @@ -1103,7 +1105,9 @@ private function searchByAddressBookIds(array $addressBookIds, // No need for like when the pattern is empty if ('' !== $pattern) { - if (!$escapePattern) { + if (!$useWildcards) { + $query2->andWhere($query2->expr()->eq('cp.value', $query2->createNamedParameter($pattern))); + } elseif (!$escapePattern) { $query2->andWhere($query2->expr()->ilike('cp.value', $query2->createNamedParameter($pattern))); } else { $query2->andWhere($query2->expr()->ilike('cp.value', $query2->createNamedParameter('%' . $this->db->escapeLikeParameter($pattern) . '%'))); diff --git a/lib/private/Collaboration/Collaborators/MailPlugin.php b/lib/private/Collaboration/Collaborators/MailPlugin.php index 7245501a8bf7d..59861247ced6d 100644 --- a/lib/private/Collaboration/Collaborators/MailPlugin.php +++ b/lib/private/Collaboration/Collaborators/MailPlugin.php @@ -101,7 +101,15 @@ public function search($search, $limit, $offset, ISearchResult $searchResult) { $emailType = new SearchResultType('emails'); // Search in contacts - $addressBookContacts = $this->contactsManager->search($search, ['EMAIL', 'FN'], ['limit' => $limit, 'offset' => $offset]); + $addressBookContacts = $this->contactsManager->search( + $search, + ['EMAIL', 'FN'], + [ + 'limit' => $limit, + 'offset' => $offset, + 'wildcard' => $this->shareeEnumeration, + ] + ); $lowerSearch = strtolower($search); foreach ($addressBookContacts as $contact) { if (isset($contact['EMAIL'])) { diff --git a/lib/private/ContactsManager.php b/lib/private/ContactsManager.php index e702a4391538f..7bdb8293857e6 100644 --- a/lib/private/ContactsManager.php +++ b/lib/private/ContactsManager.php @@ -42,6 +42,7 @@ class ContactsManager implements IManager { * - 'escape_like_param' - If set to false wildcards _ and % are not escaped * - 'limit' - Set a numeric limit for the search results * - 'offset' - Set the offset for the limited search results + * - 'wildcard' - Whether the search should use wildcards * @return array an array of contacts which are arrays of key-value-pairs */ public function search($pattern, $searchProperties = [], $options = []) { diff --git a/lib/public/Contacts/IManager.php b/lib/public/Contacts/IManager.php index 8d24249e99706..6bf569e9bbd4d 100644 --- a/lib/public/Contacts/IManager.php +++ b/lib/public/Contacts/IManager.php @@ -93,6 +93,7 @@ interface IManager { * - 'escape_like_param' - If set to false wildcards _ and % are not escaped * - 'limit' - Set a numeric limit for the search results * - 'offset' - Set the offset for the limited search results + * - 'wildcard' - Whether the search should use wildcards * @return array an array of contacts which are arrays of key-value-pairs * @since 6.0.0 */ diff --git a/lib/public/IAddressBook.php b/lib/public/IAddressBook.php index b0196764be34f..738745376d3e1 100644 --- a/lib/public/IAddressBook.php +++ b/lib/public/IAddressBook.php @@ -67,6 +67,7 @@ public function getDisplayName(); * - 'escape_like_param' - If set to false wildcards _ and % are not escaped * - 'limit' - Set a numeric limit for the search results * - 'offset' - Set the offset for the limited search results + * - 'wildcard' - Whether the search should use wildcards * @return array an array of contacts which are arrays of key-value-pairs * example result: * [ From 1d7971bf41b289a8548c6dbe8a5303e663a4e88e Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Wed, 8 Dec 2021 16:59:32 +0100 Subject: [PATCH 2/7] Only limit search in the system address book Signed-off-by: Joas Schilling --- .../Collaboration/Collaborators/MailPlugin.php | 3 ++- lib/private/ContactsManager.php | 16 ++++++++++++++-- lib/public/Contacts/IManager.php | 3 ++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/private/Collaboration/Collaborators/MailPlugin.php b/lib/private/Collaboration/Collaborators/MailPlugin.php index 59861247ced6d..7c245c4f9c42b 100644 --- a/lib/private/Collaboration/Collaborators/MailPlugin.php +++ b/lib/private/Collaboration/Collaborators/MailPlugin.php @@ -107,7 +107,8 @@ public function search($search, $limit, $offset, ISearchResult $searchResult) { [ 'limit' => $limit, 'offset' => $offset, - 'wildcard' => $this->shareeEnumeration, + 'enumeration' => $this->shareeEnumeration, + 'fullmatch' => $this->shareeEnumerationFullMatch, ] ); $lowerSearch = strtolower($search); diff --git a/lib/private/ContactsManager.php b/lib/private/ContactsManager.php index 7bdb8293857e6..557cf98c66b40 100644 --- a/lib/private/ContactsManager.php +++ b/lib/private/ContactsManager.php @@ -42,14 +42,26 @@ class ContactsManager implements IManager { * - 'escape_like_param' - If set to false wildcards _ and % are not escaped * - 'limit' - Set a numeric limit for the search results * - 'offset' - Set the offset for the limited search results - * - 'wildcard' - Whether the search should use wildcards + * - 'enumeration' - Whether user enumeration on system address book is allowed + * - 'fullmatch' - Whether matching on full detail in system address book is allowed * @return array an array of contacts which are arrays of key-value-pairs */ public function search($pattern, $searchProperties = [], $options = []) { $this->loadAddressBooks(); $result = []; foreach ($this->addressBooks as $addressBook) { - $r = $addressBook->search($pattern, $searchProperties, $options); + $searchOptions = $options; + + if ($addressBook->isSystemAddressBook()) { + $fullMatch = !\array_key_exists('fullmatch', $options) || $options['fullmatch'] !== false; + if (!$fullMatch) { + // Neither full match is allowed, so skip the system address book + continue; + } + $searchOptions['wildcard'] = !\array_key_exists('enumeration', $options) || $options['enumeration'] !== false; + } + + $r = $addressBook->search($pattern, $searchProperties, $searchOptions); $contacts = []; foreach ($r as $c) { $c['addressbook-key'] = $addressBook->getKey(); diff --git a/lib/public/Contacts/IManager.php b/lib/public/Contacts/IManager.php index 6bf569e9bbd4d..6d5f318cfa8d1 100644 --- a/lib/public/Contacts/IManager.php +++ b/lib/public/Contacts/IManager.php @@ -93,7 +93,8 @@ interface IManager { * - 'escape_like_param' - If set to false wildcards _ and % are not escaped * - 'limit' - Set a numeric limit for the search results * - 'offset' - Set the offset for the limited search results - * - 'wildcard' - Whether the search should use wildcards + * - 'enumeration' - Whether user enumeration on system address book is allowed + * - 'fullmatch' - Whether matching on full detail in system addresss book is allowed * @return array an array of contacts which are arrays of key-value-pairs * @since 6.0.0 */ From 3879c2eb1e2a9ee9698f3c26483b123125e4453d Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Wed, 8 Dec 2021 17:26:30 +0100 Subject: [PATCH 3/7] Limit more contact searches Signed-off-by: Joas Schilling --- apps/federatedfilesharing/lib/Notifier.php | 7 ++++++- apps/files/lib/Activity/Provider.php | 7 ++++++- apps/files_sharing/lib/Activity/Providers/Base.php | 7 ++++++- .../lib/Controller/ShareAPIController.php | 8 ++++++-- .../tests/Controller/ShareAPIControllerTest.php | 12 ++++++++++-- apps/sharebymail/lib/Activity.php | 7 ++++++- .../Collaboration/Collaborators/RemotePlugin.php | 7 ++++++- lib/private/Contacts/ContactsMenu/ContactsStore.php | 5 ++++- lib/private/Federation/CloudIdManager.php | 7 ++++++- lib/private/Share/Share.php | 7 ++++++- 10 files changed, 62 insertions(+), 12 deletions(-) diff --git a/apps/federatedfilesharing/lib/Notifier.php b/apps/federatedfilesharing/lib/Notifier.php index a551a3cca0c89..7eabbba56fdb1 100644 --- a/apps/federatedfilesharing/lib/Notifier.php +++ b/apps/federatedfilesharing/lib/Notifier.php @@ -255,7 +255,12 @@ protected function getDisplayNameFromContact($federatedCloudId) { } } - $addressBookEntries = $this->contactsManager->search($federatedCloudId, ['CLOUD']); + $addressBookEntries = $this->contactsManager->search($federatedCloudId, ['CLOUD'], [ + 'limit' => 1, + 'enumeration' => false, + 'fullmatch' => false, + 'strict_search' => true, + ]); foreach ($addressBookEntries as $entry) { if (isset($entry['CLOUD'])) { foreach ($entry['CLOUD'] as $cloudID) { diff --git a/apps/files/lib/Activity/Provider.php b/apps/files/lib/Activity/Provider.php index 8f3a5a4f417c4..a7db85a0de1ec 100644 --- a/apps/files/lib/Activity/Provider.php +++ b/apps/files/lib/Activity/Provider.php @@ -560,7 +560,12 @@ protected function getDisplayNameFromAddressBook(string $search): string { return $this->displayNames[$search]; } - $addressBookContacts = $this->contactsManager->search($search, ['CLOUD']); + $addressBookContacts = $this->contactsManager->search($search, ['CLOUD'], [ + 'limit' => 1, + 'enumeration' => false, + 'fullmatch' => false, + 'strict_search' => true, + ]); foreach ($addressBookContacts as $contact) { if (isset($contact['isLocalSystemBook'])) { continue; diff --git a/apps/files_sharing/lib/Activity/Providers/Base.php b/apps/files_sharing/lib/Activity/Providers/Base.php index 948d629c8fc99..e61bdffadcd52 100644 --- a/apps/files_sharing/lib/Activity/Providers/Base.php +++ b/apps/files_sharing/lib/Activity/Providers/Base.php @@ -203,7 +203,12 @@ protected function getDisplayNameFromAddressBook(string $search): string { return $this->displayNames[$search]; } - $addressBookContacts = $this->contactsManager->search($search, ['CLOUD']); + $addressBookContacts = $this->contactsManager->search($search, ['CLOUD'], [ + 'limit' => 1, + 'enumeration' => false, + 'fullmatch' => false, + 'strict_search' => true, + ]); foreach ($addressBookContacts as $contact) { if (isset($contact['isLocalSystemBook'])) { continue; diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php index d82584ed4162c..2080a6f2e7b8d 100644 --- a/apps/files_sharing/lib/Controller/ShareAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareAPIController.php @@ -334,8 +334,12 @@ protected function formatShare(IShare $share, Node $recipientNode = null): array * @return string */ private function getDisplayNameFromAddressBook(string $query, string $property): string { - // FIXME: If we inject the contacts manager it gets initialized bofore any address books are registered - $result = \OC::$server->getContactsManager()->search($query, [$property]); + // FIXME: If we inject the contacts manager it gets initialized before any address books are registered + $result = \OC::$server->getContactsManager()->search($query, [$property], [ + 'limit' => 1, + 'enumeration' => false, + 'strict_search' => true, + ]); foreach ($result as $r) { foreach ($r[$property] as $value) { if ($value === $query && $r['FN']) { diff --git a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php index 400291c0c1b6d..dd8d573d3d029 100644 --- a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php +++ b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php @@ -4417,7 +4417,11 @@ public function testFormatShare(array $expects, \OCP\Share\IShare $share, array $cm->method('search') ->willReturnMap([ - ['user@server.com', ['CLOUD'], [], + ['user@server.com', ['CLOUD'], [ + 'limit' => 1, + 'enumeration' => false, + 'strict_search' => true, + ], [ [ 'CLOUD' => [ @@ -4427,7 +4431,11 @@ public function testFormatShare(array $expects, \OCP\Share\IShare $share, array ], ], ], - ['user@server.com', ['EMAIL'], [], + ['user@server.com', ['EMAIL'], [ + 'limit' => 1, + 'enumeration' => false, + 'strict_search' => true, + ], [ [ 'EMAIL' => [ diff --git a/apps/sharebymail/lib/Activity.php b/apps/sharebymail/lib/Activity.php index ff012654834d4..3992f0f942b51 100644 --- a/apps/sharebymail/lib/Activity.php +++ b/apps/sharebymail/lib/Activity.php @@ -362,7 +362,12 @@ protected function generateUserParameter($uid) { * @return string */ protected function getContactName($email) { - $addressBookContacts = $this->contactsManager->search($email, ['EMAIL']); + $addressBookContacts = $this->contactsManager->search($email, ['EMAIL'], [ + 'limit' => 1, + 'enumeration' => false, + 'fullmatch' => false, + 'strict_search' => true, + ]); foreach ($addressBookContacts as $contact) { if (isset($contact['isLocalSystemBook'])) { diff --git a/lib/private/Collaboration/Collaborators/RemotePlugin.php b/lib/private/Collaboration/Collaborators/RemotePlugin.php index 4fe62523b6601..7d7a013a38c84 100644 --- a/lib/private/Collaboration/Collaborators/RemotePlugin.php +++ b/lib/private/Collaboration/Collaborators/RemotePlugin.php @@ -67,7 +67,12 @@ public function search($search, $limit, $offset, ISearchResult $searchResult) { $resultType = new SearchResultType('remotes'); // Search in contacts - $addressBookContacts = $this->contactsManager->search($search, ['CLOUD', 'FN'], ['limit' => $limit, 'offset' => $offset]); + $addressBookContacts = $this->contactsManager->search($search, ['CLOUD', 'FN'], [ + 'limit' => $limit, + 'offset' => $offset, + 'enumeration' => false, + 'fullmatch' => false, + ]); foreach ($addressBookContacts as $contact) { if (isset($contact['isLocalSystemBook'])) { continue; diff --git a/lib/private/Contacts/ContactsMenu/ContactsStore.php b/lib/private/Contacts/ContactsMenu/ContactsStore.php index 31e13bbe8f229..77cca794d6bae 100644 --- a/lib/private/Contacts/ContactsMenu/ContactsStore.php +++ b/lib/private/Contacts/ContactsMenu/ContactsStore.php @@ -73,7 +73,10 @@ public function __construct(IManager $contactsManager, * @return IEntry[] */ public function getContacts(IUser $user, $filter, ?int $limit = null, ?int $offset = null) { - $options = []; + $options = [ + 'enumeration' => $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes', + 'fullmatch' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match', 'yes') === 'yes', + ]; if ($limit !== null) { $options['limit'] = $limit; } diff --git a/lib/private/Federation/CloudIdManager.php b/lib/private/Federation/CloudIdManager.php index 694f48eb1cc90..d76a67d70d191 100644 --- a/lib/private/Federation/CloudIdManager.php +++ b/lib/private/Federation/CloudIdManager.php @@ -82,7 +82,12 @@ public function resolveCloudId(string $cloudId): ICloudId { } protected function getDisplayNameFromContact(string $cloudId): ?string { - $addressBookEntries = $this->contactsManager->search($cloudId, ['CLOUD']); + $addressBookEntries = $this->contactsManager->search($cloudId, ['CLOUD'], [ + 'limit' => 1, + 'enumeration' => false, + 'fullmatch' => false, + 'strict_search' => true, + ]); foreach ($addressBookEntries as $entry) { if (isset($entry['CLOUD'])) { foreach ($entry['CLOUD'] as $cloudID) { diff --git a/lib/private/Share/Share.php b/lib/private/Share/Share.php index a857a850f9b7b..548c8a2c4517f 100644 --- a/lib/private/Share/Share.php +++ b/lib/private/Share/Share.php @@ -593,7 +593,12 @@ public static function getItems($itemType, $item = null, $shareType = null, $sha $row['share_with_displayname'] = $shareWithUser === null ? $row['share_with'] : $shareWithUser->getDisplayName(); } elseif (isset($row['share_with']) && $row['share_with'] != '' && $row['share_type'] === IShare::TYPE_REMOTE) { - $addressBookEntries = \OC::$server->getContactsManager()->search($row['share_with'], ['CLOUD']); + $addressBookEntries = \OC::$server->getContactsManager()->search($row['share_with'], ['CLOUD'], [ + 'limit' => 1, + 'enumeration' => false, + 'fullmatch' => false, + 'strict_search' => true, + ]); foreach ($addressBookEntries as $entry) { foreach ($entry['CLOUD'] as $cloudID) { if ($cloudID === $row['share_with']) { From 0b717bd0562f53d0e035326c119cb84ab7b0b8f1 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Wed, 8 Dec 2021 18:53:54 +0100 Subject: [PATCH 4/7] Convert strict_search to wildcard property and add psalm docs Signed-off-by: Joas Schilling --- apps/dav/lib/CardDAV/AddressBookImpl.php | 1 + apps/dav/lib/CardDAV/CardDavBackend.php | 2 ++ lib/private/ContactsManager.php | 15 ++++++++++++--- lib/public/Contacts/IManager.php | 6 ++++-- lib/public/IAddressBook.php | 3 ++- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/apps/dav/lib/CardDAV/AddressBookImpl.php b/apps/dav/lib/CardDAV/AddressBookImpl.php index 1b74f329f1fa9..3db20cb4220a3 100644 --- a/apps/dav/lib/CardDAV/AddressBookImpl.php +++ b/apps/dav/lib/CardDAV/AddressBookImpl.php @@ -108,6 +108,7 @@ public function getDisplayName() { * - 'limit' - Set a numeric limit for the search results * - 'offset' - Set the offset for the limited search results * - 'wildcard' - Whether the search should use wildcards + * @psalm-param array{types?: bool, escape_like_param?: bool, limit?: int, offset?: int, wildcard?: bool} $options * @return array an array of contacts which are arrays of key-value-pairs * example result: * [ diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php index 403c4646e4784..3e360fb2e414d 100644 --- a/apps/dav/lib/CardDAV/CardDavBackend.php +++ b/apps/dav/lib/CardDAV/CardDavBackend.php @@ -1025,6 +1025,7 @@ public function updateShares(IShareable $shareable, $add, $remove) { * - 'limit' - Set a numeric limit for the search results * - 'offset' - Set the offset for the limited search results * - 'wildcard' - Whether the search should use wildcards + * @psalm-param array{escape_like_param?: bool, limit?: int, offset?: int, wildcard?: bool} $options * @return array an array of contacts which are arrays of key-value-pairs */ public function search($addressBookId, $pattern, $searchProperties, $options = []): array { @@ -1056,6 +1057,7 @@ public function searchPrincipalUri(string $principalUri, * @param string $pattern * @param array $searchProperties * @param array $options + * @psalm-param array{types?: bool, escape_like_param?: bool, limit?: int, offset?: int, wildcard?: bool} $options * @return array */ private function searchByAddressBookIds(array $addressBookIds, diff --git a/lib/private/ContactsManager.php b/lib/private/ContactsManager.php index 557cf98c66b40..937fb94a09ac6 100644 --- a/lib/private/ContactsManager.php +++ b/lib/private/ContactsManager.php @@ -42,8 +42,10 @@ class ContactsManager implements IManager { * - 'escape_like_param' - If set to false wildcards _ and % are not escaped * - 'limit' - Set a numeric limit for the search results * - 'offset' - Set the offset for the limited search results - * - 'enumeration' - Whether user enumeration on system address book is allowed - * - 'fullmatch' - Whether matching on full detail in system address book is allowed + * - 'enumeration' - (since 23.0.0) Whether user enumeration on system address book is allowed + * - 'fullmatch' - (since 23.0.0) Whether matching on full detail in system address book is allowed + * - 'strict_search' - (since 23.0.0) Whether the search pattern is full string or partial search + * @psalm-param array{escape_like_param?: bool, limit?: int, offset?: int, enumeration?: bool, fullmatch?: bool, strict_search?: bool} $options * @return array an array of contacts which are arrays of key-value-pairs */ public function search($pattern, $searchProperties = [], $options = []) { @@ -51,6 +53,7 @@ public function search($pattern, $searchProperties = [], $options = []) { $result = []; foreach ($this->addressBooks as $addressBook) { $searchOptions = $options; + $strictSearch = array_key_exists('strict_search', $options) && $options['strict_search'] === true; if ($addressBook->isSystemAddressBook()) { $fullMatch = !\array_key_exists('fullmatch', $options) || $options['fullmatch'] !== false; @@ -58,7 +61,13 @@ public function search($pattern, $searchProperties = [], $options = []) { // Neither full match is allowed, so skip the system address book continue; } - $searchOptions['wildcard'] = !\array_key_exists('enumeration', $options) || $options['enumeration'] !== false; + if ($strictSearch) { + $searchOptions['wildcard'] = false; + } else { + $searchOptions['wildcard'] = !\array_key_exists('enumeration', $options) || $options['enumeration'] !== false; + } + } else { + $searchOptions['wildcard'] = !$strictSearch; } $r = $addressBook->search($pattern, $searchProperties, $searchOptions); diff --git a/lib/public/Contacts/IManager.php b/lib/public/Contacts/IManager.php index 6d5f318cfa8d1..e9bdc01c060cb 100644 --- a/lib/public/Contacts/IManager.php +++ b/lib/public/Contacts/IManager.php @@ -93,8 +93,10 @@ interface IManager { * - 'escape_like_param' - If set to false wildcards _ and % are not escaped * - 'limit' - Set a numeric limit for the search results * - 'offset' - Set the offset for the limited search results - * - 'enumeration' - Whether user enumeration on system address book is allowed - * - 'fullmatch' - Whether matching on full detail in system addresss book is allowed + * - 'enumeration' - (since 23.0.0) Whether user enumeration on system address book is allowed + * - 'fullmatch' - (since 23.0.0) Whether matching on full detail in system addresss book is allowed + * - 'strict_search' - (since 23.0.0) Whether the search pattern is full string or partial search + * @psalm-param array{escape_like_param?: bool, limit?: int, offset?: int, enumeration?: bool, fullmatch?: bool, strict_search?: bool} $options * @return array an array of contacts which are arrays of key-value-pairs * @since 6.0.0 */ diff --git a/lib/public/IAddressBook.php b/lib/public/IAddressBook.php index 738745376d3e1..4bb632ae07099 100644 --- a/lib/public/IAddressBook.php +++ b/lib/public/IAddressBook.php @@ -67,7 +67,8 @@ public function getDisplayName(); * - 'escape_like_param' - If set to false wildcards _ and % are not escaped * - 'limit' - Set a numeric limit for the search results * - 'offset' - Set the offset for the limited search results - * - 'wildcard' - Whether the search should use wildcards + * - 'wildcard' - (since 23.0.0) Whether the search should use wildcards + * @psalm-param array{types?: bool, escape_like_param?: bool, limit?: int, offset?: int, wildcard?: bool} $options * @return array an array of contacts which are arrays of key-value-pairs * example result: * [ From 76f5436f9ba4e7c9b44ecfb44b73efe3c93a67cf Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 9 Dec 2021 09:18:53 +0100 Subject: [PATCH 5/7] Fix docs to make Psalm happier Signed-off-by: Joas Schilling --- lib/private/Collaboration/Collaborators/MailPlugin.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/private/Collaboration/Collaborators/MailPlugin.php b/lib/private/Collaboration/Collaborators/MailPlugin.php index 7c245c4f9c42b..80f2906b5100a 100644 --- a/lib/private/Collaboration/Collaborators/MailPlugin.php +++ b/lib/private/Collaboration/Collaborators/MailPlugin.php @@ -86,12 +86,7 @@ public function __construct(IManager $contactsManager, } /** - * @param $search - * @param $limit - * @param $offset - * @param ISearchResult $searchResult - * @return bool - * @since 13.0.0 + * {@inheritdoc} */ public function search($search, $limit, $offset, ISearchResult $searchResult) { $currentUserId = $this->userSession->getUser()->getUID(); From e552806d46e84bc0c985dda487e5db8e9f57c466 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 9 Dec 2021 09:25:50 +0100 Subject: [PATCH 6/7] Make psalm more happy Signed-off-by: Joas Schilling --- lib/private/Collaboration/Collaborators/MailPlugin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/private/Collaboration/Collaborators/MailPlugin.php b/lib/private/Collaboration/Collaborators/MailPlugin.php index 80f2906b5100a..c0d0a55a1a183 100644 --- a/lib/private/Collaboration/Collaborators/MailPlugin.php +++ b/lib/private/Collaboration/Collaborators/MailPlugin.php @@ -102,8 +102,8 @@ public function search($search, $limit, $offset, ISearchResult $searchResult) { [ 'limit' => $limit, 'offset' => $offset, - 'enumeration' => $this->shareeEnumeration, - 'fullmatch' => $this->shareeEnumerationFullMatch, + 'enumeration' => (bool) $this->shareeEnumeration, + 'fullmatch' => (bool) $this->shareeEnumerationFullMatch, ] ); $lowerSearch = strtolower($search); From 6a1a9485cfea2916ce1daddc2e6bd2d4dedcc841 Mon Sep 17 00:00:00 2001 From: Louis Chemineau Date: Mon, 13 Dec 2021 15:35:05 +0100 Subject: [PATCH 7/7] Fix backport Signed-off-by: Louis Chemineau --- lib/private/Contacts/ContactsMenu/ContactsStore.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/private/Contacts/ContactsMenu/ContactsStore.php b/lib/private/Contacts/ContactsMenu/ContactsStore.php index 77cca794d6bae..3d8bc15eba777 100644 --- a/lib/private/Contacts/ContactsMenu/ContactsStore.php +++ b/lib/private/Contacts/ContactsMenu/ContactsStore.php @@ -245,7 +245,9 @@ public function findOne(IUser $user, $shareType, $shareWith) { } $userId = $user->getUID(); - $allContacts = $this->contactsManager->search($shareWith, $filter); + $allContacts = $this->contactsManager->search($shareWith, $filter, [ + 'strict_search' => true, + ]); $contacts = array_filter($allContacts, function ($contact) use ($userId) { return $contact['UID'] !== $userId; });