From 77937b1f3ad0b8cc9b805dd15f8c82e890b5a60e Mon Sep 17 00:00:00 2001 From: Tom Needham Date: Mon, 5 Jun 2017 16:44:51 +0200 Subject: [PATCH 01/12] Fix column lengths on migrations table to fix index --- core/Migrations/Version20170605143658.php | 27 +++++++++++++++++++++++ lib/private/DB/MigrationService.php | 6 +++-- 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 core/Migrations/Version20170605143658.php diff --git a/core/Migrations/Version20170605143658.php b/core/Migrations/Version20170605143658.php new file mode 100644 index 000000000000..c750eeb943f1 --- /dev/null +++ b/core/Migrations/Version20170605143658.php @@ -0,0 +1,27 @@ +getTable("{$prefix}migrations"); + + // Check column length to see if migration is necessary necessary + if($table->getColumn('app')->getLength() === 177) { + // then this server was installed after the fix + return; + } + + // Need to shorten columns + $table->getColumn('app')->setLength(177); + $table->getColumn('version')->setLength(14); + } +} diff --git a/lib/private/DB/MigrationService.php b/lib/private/DB/MigrationService.php index d38faa0443c6..b0ba9b64b6f5 100644 --- a/lib/private/DB/MigrationService.php +++ b/lib/private/DB/MigrationService.php @@ -114,8 +114,10 @@ private function createMigrationTable() { $tableName = $this->connection->getDatabasePlatform()->quoteIdentifier($tableName); $columns = [ - 'app' => new Column($this->connection->getDatabasePlatform()->quoteIdentifier('app'), Type::getType('string'), ['length' => 255]), - 'version' => new Column($this->connection->getDatabasePlatform()->quoteIdentifier('version'), Type::getType('string'), ['length' => 255]), + // Length = max indexable char length - length of other columns = 191 - 14 + 'app' => new Column($this->connection->getDatabasePlatform()->quoteIdentifier('app'), Type::getType('string'), ['length' => 177]), + // Datetime string. Eg: 20172605104128 + 'version' => new Column($this->connection->getDatabasePlatform()->quoteIdentifier('version'), Type::getType('string'), ['length' => 14]), ]; $table = new Table($tableName, $columns); $table->setPrimaryKey([ From 5ff25382f06c5cc792ec1dd0ab31f8ab6b439131 Mon Sep 17 00:00:00 2001 From: Tom Needham Date: Wed, 24 May 2017 10:30:17 +0100 Subject: [PATCH 02/12] Use dav appconfig for customisable remote contact search properties --- apps/files_sharing/lib/Controller/ShareesController.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/files_sharing/lib/Controller/ShareesController.php b/apps/files_sharing/lib/Controller/ShareesController.php index 7c585e9ce05f..891c5bb9b9d0 100644 --- a/apps/files_sharing/lib/Controller/ShareesController.php +++ b/apps/files_sharing/lib/Controller/ShareesController.php @@ -292,9 +292,12 @@ protected function getGroups($search) { protected function getRemote($search) { $this->result['remotes'] = []; + // Fetch remote search properties from app config + $searchProperties = explode(',', $this->config->getAppValue('dav', 'remote_search_properties', 'CLOUD,FN')); + // Search in contacts //@todo Pagination missing - $addressBookContacts = $this->contactsManager->search($search, ['CLOUD', 'FN']); + $addressBookContacts = $this->contactsManager->search($search, $searchProperties); $foundRemoteById = false; foreach ($addressBookContacts as $contact) { if (isset($contact['isLocalSystemBook'])) { From 505e9421ec55cca008e434b2cadb19ad706f9f44 Mon Sep 17 00:00:00 2001 From: Tom Needham Date: Wed, 24 May 2017 11:21:11 +0100 Subject: [PATCH 03/12] Add limit and offset to remote user search --- apps/dav/lib/CardDAV/AddressBookImpl.php | 6 ++++-- apps/dav/lib/CardDAV/CardDavBackend.php | 6 +++++- .../files_sharing/lib/Controller/ShareesController.php | 3 +-- lib/private/ContactsManager.php | 10 +++++++--- lib/public/Contacts/IManager.php | 4 +++- lib/public/IAddressBook.php | 4 +++- 6 files changed, 23 insertions(+), 10 deletions(-) diff --git a/apps/dav/lib/CardDAV/AddressBookImpl.php b/apps/dav/lib/CardDAV/AddressBookImpl.php index 030f341c27d6..3fac44ec1c82 100644 --- a/apps/dav/lib/CardDAV/AddressBookImpl.php +++ b/apps/dav/lib/CardDAV/AddressBookImpl.php @@ -86,11 +86,13 @@ public function getDisplayName() { * @param string $pattern which should match within the $searchProperties * @param array $searchProperties defines the properties within the query pattern should match * @param array $options - for future use. One should always have options! + * @param int $limit + * @param int $offset * @return array an array of contacts which are arrays of key-value-pairs * @since 5.0.0 */ - public function search($pattern, $searchProperties, $options) { - $results = $this->backend->search($this->getKey(), $pattern, $searchProperties); + public function search($pattern, $searchProperties, $options, $limit, $offset) { + $results = $this->backend->search($this->getKey(), $pattern, $searchProperties, $limit, $offset); $vCards = []; foreach ($results as $result) { diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php index e3987f172fc1..d42fa6d26136 100644 --- a/apps/dav/lib/CardDAV/CardDavBackend.php +++ b/apps/dav/lib/CardDAV/CardDavBackend.php @@ -790,9 +790,11 @@ public function updateShares(IShareable $shareable, $add, $remove) { * @param int $addressBookId * @param string $pattern which should match within the $searchProperties * @param array $searchProperties defines the properties within the query pattern should match + * @param int $limit + * @param int $offset * @return array an array of contacts which are arrays of key-value-pairs */ - public function search($addressBookId, $pattern, $searchProperties) { + public function search($addressBookId, $pattern, $searchProperties, $limit = 100, $offset = 0) { $query = $this->db->getQueryBuilder(); $query2 = $this->db->getQueryBuilder(); $query2->selectDistinct('cp.cardid')->from($this->dbCardsPropertiesTable, 'cp'); @@ -809,6 +811,8 @@ public function search($addressBookId, $pattern, $searchProperties) { $query->select('c.carddata', 'c.uri')->from($this->dbCardsTable, 'c') ->where($query->expr()->in('c.id', $query->createFunction($query2->getSQL()))); + $query->setFirstResult($limit)->setMaxResults($offset); + $result = $query->execute(); $cards = $result->fetchAll(); diff --git a/apps/files_sharing/lib/Controller/ShareesController.php b/apps/files_sharing/lib/Controller/ShareesController.php index 891c5bb9b9d0..df047137a91a 100644 --- a/apps/files_sharing/lib/Controller/ShareesController.php +++ b/apps/files_sharing/lib/Controller/ShareesController.php @@ -296,8 +296,7 @@ protected function getRemote($search) { $searchProperties = explode(',', $this->config->getAppValue('dav', 'remote_search_properties', 'CLOUD,FN')); // Search in contacts - //@todo Pagination missing - $addressBookContacts = $this->contactsManager->search($search, $searchProperties); + $addressBookContacts = $this->contactsManager->search($search, $searchProperties, $this->limit, $this->offset); $foundRemoteById = false; foreach ($addressBookContacts as $contact) { if (isset($contact['isLocalSystemBook'])) { diff --git a/lib/private/ContactsManager.php b/lib/private/ContactsManager.php index 4ff8c67b6101..ab542d5c7ef4 100644 --- a/lib/private/ContactsManager.php +++ b/lib/private/ContactsManager.php @@ -26,7 +26,9 @@ namespace OC { - class ContactsManager implements \OCP\Contacts\IManager { + use OCP\Contacts\IManager; + + class ContactsManager implements IManager { /** * This function is used to search and find contacts within the users address books. @@ -35,13 +37,15 @@ class ContactsManager implements \OCP\Contacts\IManager { * @param string $pattern which should match within the $searchProperties * @param array $searchProperties defines the properties within the query pattern should match * @param array $options - for future use. One should always have options! + * @param int $limit + * @param int $offset * @return array an array of contacts which are arrays of key-value-pairs */ - public function search($pattern, $searchProperties = [], $options = []) { + public function search($pattern, $searchProperties = [], $options = [], $limit = null, $offset = null) { $this->loadAddressBooks(); $result = []; foreach($this->addressBooks as $addressBook) { - $r = $addressBook->search($pattern, $searchProperties, $options); + $r = $addressBook->search($pattern, $searchProperties, $options, $limit, $offset); $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 2a1657c2cdae..9f733af57e76 100644 --- a/lib/public/Contacts/IManager.php +++ b/lib/public/Contacts/IManager.php @@ -92,10 +92,12 @@ interface IManager { * @param string $pattern which should match within the $searchProperties * @param array $searchProperties defines the properties within the query pattern should match * @param array $options - for future use. One should always have options! + * @param int $limit + * @param int $offset * @return array an array of contacts which are arrays of key-value-pairs * @since 6.0.0 */ - function search($pattern, $searchProperties = [], $options = []); + function search($pattern, $searchProperties = [], $options = [], $limit = null, $offset = null); /** * This function can be used to delete the contact identified by the given id diff --git a/lib/public/IAddressBook.php b/lib/public/IAddressBook.php index 00d458340976..f4e40de92ff6 100644 --- a/lib/public/IAddressBook.php +++ b/lib/public/IAddressBook.php @@ -55,10 +55,12 @@ public function getDisplayName(); * @param string $pattern which should match within the $searchProperties * @param array $searchProperties defines the properties within the query pattern should match * @param array $options - for future use. One should always have options! + * @param int $limit + * @param int $offset * @return array an array of contacts which are arrays of key-value-pairs * @since 5.0.0 */ - public function search($pattern, $searchProperties, $options); + public function search($pattern, $searchProperties, $options, $limit, $offset); // // dummy results // return array( // array('id' => 0, 'FN' => 'Thomas Müller', 'EMAIL' => 'a@b.c', 'GEO' => '37.386013;-122.082932'), From 311bf86c7f8f3652ee8be1fd4be16af4969f79d1 Mon Sep 17 00:00:00 2001 From: Tom Needham Date: Wed, 24 May 2017 11:54:07 +0100 Subject: [PATCH 04/12] Implement & fix carddavbackend search tests for limit and offset --- apps/dav/lib/CardDAV/CardDavBackend.php | 2 +- .../tests/unit/CardDAV/AddressBookImplTest.php | 6 +++--- .../tests/unit/CardDAV/CardDavBackendTest.php | 16 +++++++++------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php index d42fa6d26136..e92beab66aab 100644 --- a/apps/dav/lib/CardDAV/CardDavBackend.php +++ b/apps/dav/lib/CardDAV/CardDavBackend.php @@ -811,7 +811,7 @@ public function search($addressBookId, $pattern, $searchProperties, $limit = 100 $query->select('c.carddata', 'c.uri')->from($this->dbCardsTable, 'c') ->where($query->expr()->in('c.id', $query->createFunction($query2->getSQL()))); - $query->setFirstResult($limit)->setMaxResults($offset); + $query->setFirstResult($offset)->setMaxResults($limit); $result = $query->execute(); $cards = $result->fetchAll(); diff --git a/apps/dav/tests/unit/CardDAV/AddressBookImplTest.php b/apps/dav/tests/unit/CardDAV/AddressBookImplTest.php index 018b3809e831..98f63deafdd7 100644 --- a/apps/dav/tests/unit/CardDAV/AddressBookImplTest.php +++ b/apps/dav/tests/unit/CardDAV/AddressBookImplTest.php @@ -102,10 +102,10 @@ public function testSearch() { ->getMock(); $pattern = 'pattern'; - $searchProperties = 'properties'; + $searchProperties = ['properties']; $this->backend->expects($this->once())->method('search') - ->with($this->addressBookInfo['id'], $pattern, $searchProperties) + ->with($this->addressBookInfo['id'], $pattern, $searchProperties, 10, 0) ->willReturn( [ ['uri' => 'foo.vcf', 'carddata' => 'cardData1'], @@ -121,7 +121,7 @@ public function testSearch() { ['bar.vcf', $this->vCard] )->willReturn('vCard'); - $result = $addressBookImpl->search($pattern, $searchProperties, []); + $result = $addressBookImpl->search($pattern, $searchProperties, [], 10, 0); $this->assertTrue((is_array($result))); $this->assertSame(2, count($result)); } diff --git a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php index 892134b66315..04e81e908723 100644 --- a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php +++ b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php @@ -466,7 +466,7 @@ public function testGetCardIdFailed() { * @param array $properties * @param array $expected */ - public function testSearch($pattern, $properties, $expected) { + public function testSearch($pattern, $properties, $expected, $limit, $offset) { /** @var VCard $vCards */ $vCards = []; $vCards[0] = new VCard(); @@ -529,7 +529,7 @@ public function testSearch($pattern, $properties, $expected) { ); $query->execute(); - $result = $this->backend->search(0, $pattern, $properties); + $result = $this->backend->search(0, $pattern, $properties, $limit, $offset); // check result $this->assertSame(count($expected), count($result)); @@ -548,11 +548,13 @@ public function testSearch($pattern, $properties, $expected) { public function dataTestSearch() { return [ - ['John', ['FN'], [['uri0', 'John Doe'], ['uri1', 'John M. Doe']]], - ['M. Doe', ['FN'], [['uri1', 'John M. Doe']]], - ['Do', ['FN'], [['uri0', 'John Doe'], ['uri1', 'John M. Doe']]], - 'check if duplicates are handled correctly' => ['John', ['FN', 'CLOUD'], [['uri0', 'John Doe'], ['uri1', 'John M. Doe']]], - 'case insensitive' => ['john', ['FN'], [['uri0', 'John Doe'], ['uri1', 'John M. Doe']]] + ['John', ['FN'], [['uri0', 'John Doe'], ['uri1', 'John M. Doe']], 100, 0], + ['M. Doe', ['FN'], [['uri1', 'John M. Doe']], 100, 0], + ['Do', ['FN'], [['uri0', 'John Doe'], ['uri1', 'John M. Doe']], 100, 0], + 'check if duplicates are handled correctly' => ['John', ['FN', 'CLOUD'], [['uri0', 'John Doe'], ['uri1', 'John M. Doe']], 100, 0], + 'case insensitive' => ['john', ['FN'], [['uri0', 'John Doe'], ['uri1', 'John M. Doe']], 100, 0], + 'search limit' => ['John', ['FN'], [['uri0', 'John Doe']], 1, 0], + 'search offset' => ['John', ['FN'], [['uri1', 'John M. Doe']], 1, 1], ]; } From fe0244655faaeb2dd9b9a02e276192c94d263a6b Mon Sep 17 00:00:00 2001 From: Tom Needham Date: Wed, 24 May 2017 12:30:13 +0100 Subject: [PATCH 05/12] Fix sharee test to get search properties from config --- apps/files_sharing/tests/API/ShareesTest.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/files_sharing/tests/API/ShareesTest.php b/apps/files_sharing/tests/API/ShareesTest.php index 673f69d25016..ffe2c8eafcc6 100644 --- a/apps/files_sharing/tests/API/ShareesTest.php +++ b/apps/files_sharing/tests/API/ShareesTest.php @@ -1259,6 +1259,11 @@ public function testGetRemote($searchTerm, $contacts, $shareeEnumeration, $exact $this->invokePrivate($this->sharees, 'result', [$result]); } + $this->config->expects($this->once()) + ->method('getAppValue') + ->with('dav', 'remote_search_properties') + ->willReturn('CLOUD,FN'); + $this->invokePrivate($this->sharees, 'shareeEnumeration', [$shareeEnumeration]); $this->contactsManager->expects($this->any()) ->method('search') From 1b4cfe2472b242f8a0cbe76212a4ddb29b3fc8e2 Mon Sep 17 00:00:00 2001 From: Tom Needham Date: Wed, 24 May 2017 12:38:59 +0100 Subject: [PATCH 06/12] Improve sharee controller remote user search tests --- apps/files_sharing/lib/Controller/ShareesController.php | 2 +- apps/files_sharing/tests/API/ShareesTest.php | 7 ++++++- lib/private/ContactsManager.php | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/files_sharing/lib/Controller/ShareesController.php b/apps/files_sharing/lib/Controller/ShareesController.php index df047137a91a..907dc6055c6c 100644 --- a/apps/files_sharing/lib/Controller/ShareesController.php +++ b/apps/files_sharing/lib/Controller/ShareesController.php @@ -296,7 +296,7 @@ protected function getRemote($search) { $searchProperties = explode(',', $this->config->getAppValue('dav', 'remote_search_properties', 'CLOUD,FN')); // Search in contacts - $addressBookContacts = $this->contactsManager->search($search, $searchProperties, $this->limit, $this->offset); + $addressBookContacts = $this->contactsManager->search($search, $searchProperties, [], $this->limit, $this->offset); $foundRemoteById = false; foreach ($addressBookContacts as $contact) { if (isset($contact['isLocalSystemBook'])) { diff --git a/apps/files_sharing/tests/API/ShareesTest.php b/apps/files_sharing/tests/API/ShareesTest.php index ffe2c8eafcc6..1f22358f2220 100644 --- a/apps/files_sharing/tests/API/ShareesTest.php +++ b/apps/files_sharing/tests/API/ShareesTest.php @@ -1248,6 +1248,11 @@ public function dataGetRemote() { * @param array $previousExact */ public function testGetRemote($searchTerm, $contacts, $shareeEnumeration, $exactExpected, $expected, $reachedEnd, $previousExact = []) { + + // Set the limit and offset for remote user searching + $this->invokePrivate($this->sharees, 'limit', [2]); + $this->invokePrivate($this->sharees, 'offset', [0]); + $this->config->expects($this->any()) ->method('getSystemValue') ->with('trusted_domains') @@ -1267,7 +1272,7 @@ public function testGetRemote($searchTerm, $contacts, $shareeEnumeration, $exact $this->invokePrivate($this->sharees, 'shareeEnumeration', [$shareeEnumeration]); $this->contactsManager->expects($this->any()) ->method('search') - ->with($searchTerm, ['CLOUD', 'FN']) + ->with($searchTerm, ['CLOUD', 'FN'], [], 2, 0) ->willReturn($contacts); $this->invokePrivate($this->sharees, 'getRemote', [$searchTerm]); diff --git a/lib/private/ContactsManager.php b/lib/private/ContactsManager.php index ab542d5c7ef4..cb58159d66a8 100644 --- a/lib/private/ContactsManager.php +++ b/lib/private/ContactsManager.php @@ -41,7 +41,7 @@ class ContactsManager implements IManager { * @param int $offset * @return array an array of contacts which are arrays of key-value-pairs */ - public function search($pattern, $searchProperties = [], $options = [], $limit = null, $offset = null) { + public function search($pattern, $searchProperties = [], $options = [], $limit = 100, $offset = 0) { $this->loadAddressBooks(); $result = []; foreach($this->addressBooks as $addressBook) { From 81460c55dac39769c5a9fba1073d08c52b3996ce Mon Sep 17 00:00:00 2001 From: Tom Needham Date: Fri, 16 Jun 2017 12:39:19 +0100 Subject: [PATCH 07/12] Include custom search properties in sharee exact matches --- .../lib/Controller/ShareesController.php | 102 ++++++++++++------ apps/files_sharing/tests/API/ShareesTest.php | 32 +++++- 2 files changed, 102 insertions(+), 32 deletions(-) diff --git a/apps/files_sharing/lib/Controller/ShareesController.php b/apps/files_sharing/lib/Controller/ShareesController.php index 907dc6055c6c..e68ffc90c3cd 100644 --- a/apps/files_sharing/lib/Controller/ShareesController.php +++ b/apps/files_sharing/lib/Controller/ShareesController.php @@ -291,60 +291,102 @@ protected function getGroups($search) { */ protected function getRemote($search) { $this->result['remotes'] = []; - // Fetch remote search properties from app config $searchProperties = explode(',', $this->config->getAppValue('dav', 'remote_search_properties', 'CLOUD,FN')); - // Search in contacts $addressBookContacts = $this->contactsManager->search($search, $searchProperties, [], $this->limit, $this->offset); $foundRemoteById = false; foreach ($addressBookContacts as $contact) { + if (isset($contact['isLocalSystemBook'])) { + // We only want remote users continue; } - if (isset($contact['CLOUD'])) { - $cloudIds = $contact['CLOUD']; - if (!is_array($cloudIds)) { - $cloudIds = [$cloudIds]; + if (!isset($contact['CLOUD'])) { + // we need a cloud id to setup a remote share + continue; + } + + // we can have multiple cloud domains, always convert to an array + $cloudIds = $contact['CLOUD']; + if (!is_array($cloudIds)) { + $cloudIds = [$cloudIds]; + } + + $lowerSearch = strtolower($search); + foreach ($cloudIds as $cloudId) { + list(, $serverUrl) = $this->splitUserRemote($cloudId); + + + if (strtolower($cloudId) === $lowerSearch) { + $foundRemoteById = true; + // Save this as an exact match and continue with next CLOUD + $this->result['exact']['remotes'][] = [ + 'label' => $contact['FN'], + 'value' => [ + 'shareType' => Share::SHARE_TYPE_REMOTE, + 'shareWith' => $cloudId, + 'server' => $serverUrl, + ], + ]; + continue; } - $lowerSearch = strtolower($search); - foreach ($cloudIds as $cloudId) { - list(, $serverUrl) = $this->splitUserRemote($cloudId); - if (strtolower($contact['FN']) === $lowerSearch || strtolower($cloudId) === $lowerSearch) { - if (strtolower($cloudId) === $lowerSearch) { - $foundRemoteById = true; + + // CLOUD matching is done above + unset($searchProperties['CLOUD']); + foreach($searchProperties as $property) { + // do we even have this property for this contact/ + if(!isset($contact[$property])) { + // Skip this property since our contact doesnt have it + continue; + } + // check if we have a match + $values = $contact[$property]; + if(!is_array($values)) { + $values = [$values]; + } + foreach($values as $value) { + // check if we have an exact match + if(strtolower($value) === $lowerSearch) { + $this->result['exact']['remotes'][] = [ + 'label' => $contact['FN'], + 'value' => [ + 'shareType' => Share::SHARE_TYPE_REMOTE, + 'shareWith' => $cloudId, + 'server' => $serverUrl, + ], + ]; + + // Now skip to next CLOUD + continue 3; } - $this->result['exact']['remotes'][] = [ - 'label' => $contact['FN'], - 'value' => [ - 'shareType' => Share::SHARE_TYPE_REMOTE, - 'shareWith' => $cloudId, - 'server' => $serverUrl, - ], - ]; - } else { - $this->result['remotes'][] = [ - 'label' => $contact['FN'], - 'value' => [ - 'shareType' => Share::SHARE_TYPE_REMOTE, - 'shareWith' => $cloudId, - 'server' => $serverUrl, - ], - ]; } } + + // If we get here, we didnt find an exact match, so add to other matches + $this->result['remotes'][] = [ + 'label' => $contact['FN'], + 'value' => [ + 'shareType' => Share::SHARE_TYPE_REMOTE, + 'shareWith' => $cloudId, + 'server' => $serverUrl, + ], + ]; + } } + // remove the exact user results if we dont allow autocomplete if (!$this->shareeEnumeration) { $this->result['remotes'] = []; } + if (!$foundRemoteById && substr_count($search, '@') >= 1 && $this->offset === 0 // if an exact local user is found, only keep the remote entry if // its domain does not matches the trusted domains // (if it does, it is a user whose local login domain matches the ownCloud - // instance domain) + // instance domain) && (empty($this->result['exact']['users']) || !$this->isInstanceDomain($search)) ) { diff --git a/apps/files_sharing/tests/API/ShareesTest.php b/apps/files_sharing/tests/API/ShareesTest.php index 1f22358f2220..675ff3c5f176 100644 --- a/apps/files_sharing/tests/API/ShareesTest.php +++ b/apps/files_sharing/tests/API/ShareesTest.php @@ -1233,6 +1233,34 @@ public function dataGetRemote() { ] ] ], + // #16 check email property is matched for remote users + [ + 'user@example.com', + [ + [ + 'FN' => 'User3 @ Localhost', + ], + [ + 'FN' => 'User2 @ Localhost', + 'CLOUD' => [ + ], + ], + [ + 'FN' => 'User @ Localhost', + 'CLOUD' => [ + 'username@localhost', + ], + 'EMAIL' => 'user@example.com' + ], + ], + true, + [ + ['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']], + ['label' => 'user@example.com', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'user@example.com']] + ], + [], + true, + ], ]; } @@ -1267,12 +1295,12 @@ public function testGetRemote($searchTerm, $contacts, $shareeEnumeration, $exact $this->config->expects($this->once()) ->method('getAppValue') ->with('dav', 'remote_search_properties') - ->willReturn('CLOUD,FN'); + ->willReturn('EMAIL,CLOUD,FN'); $this->invokePrivate($this->sharees, 'shareeEnumeration', [$shareeEnumeration]); $this->contactsManager->expects($this->any()) ->method('search') - ->with($searchTerm, ['CLOUD', 'FN'], [], 2, 0) + ->with($searchTerm, ['EMAIL', 'CLOUD', 'FN'], [], 2, 0) ->willReturn($contacts); $this->invokePrivate($this->sharees, 'getRemote', [$searchTerm]); From 247222922d7d9e28256b80dbbce539250371e653 Mon Sep 17 00:00:00 2001 From: Tom Needham Date: Thu, 22 Jun 2017 12:14:48 +0100 Subject: [PATCH 08/12] Add explicit sorting of remote user searches --- apps/dav/lib/CardDAV/CardDavBackend.php | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php index e92beab66aab..199d52a1bdea 100644 --- a/apps/dav/lib/CardDAV/CardDavBackend.php +++ b/apps/dav/lib/CardDAV/CardDavBackend.php @@ -812,6 +812,7 @@ public function search($addressBookId, $pattern, $searchProperties, $limit = 100 ->where($query->expr()->in('c.id', $query->createFunction($query2->getSQL()))); $query->setFirstResult($offset)->setMaxResults($limit); + $query->orderBy('c.uri'); $result = $query->execute(); $cards = $result->fetchAll(); From 28c577da88177505e7051879663d2cab569b75c8 Mon Sep 17 00:00:00 2001 From: Tom Needham Date: Thu, 22 Jun 2017 13:13:41 +0100 Subject: [PATCH 09/12] Make addressbook search limit and offset optional --- apps/dav/lib/CardDAV/AddressBookImpl.php | 2 +- lib/public/IAddressBook.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/dav/lib/CardDAV/AddressBookImpl.php b/apps/dav/lib/CardDAV/AddressBookImpl.php index 3fac44ec1c82..b5d874f17393 100644 --- a/apps/dav/lib/CardDAV/AddressBookImpl.php +++ b/apps/dav/lib/CardDAV/AddressBookImpl.php @@ -91,7 +91,7 @@ public function getDisplayName() { * @return array an array of contacts which are arrays of key-value-pairs * @since 5.0.0 */ - public function search($pattern, $searchProperties, $options, $limit, $offset) { + public function search($pattern, $searchProperties, $options, $limit = null, $offset = null) { $results = $this->backend->search($this->getKey(), $pattern, $searchProperties, $limit, $offset); $vCards = []; diff --git a/lib/public/IAddressBook.php b/lib/public/IAddressBook.php index f4e40de92ff6..035a5c6c98c5 100644 --- a/lib/public/IAddressBook.php +++ b/lib/public/IAddressBook.php @@ -60,7 +60,7 @@ public function getDisplayName(); * @return array an array of contacts which are arrays of key-value-pairs * @since 5.0.0 */ - public function search($pattern, $searchProperties, $options, $limit, $offset); + public function search($pattern, $searchProperties, $options, $limit = null, $offset = null); // // dummy results // return array( // array('id' => 0, 'FN' => 'Thomas Müller', 'EMAIL' => 'a@b.c', 'GEO' => '37.386013;-122.082932'), From 62d660899abfc5acd11778486eed62fc79d9cb48 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Tue, 27 Jun 2017 10:47:10 +0200 Subject: [PATCH 10/12] Use "sharing" scope when sending notification --- lib/private/Share/Share.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/private/Share/Share.php b/lib/private/Share/Share.php index 3e00ec845cf3..773de34b2bf9 100644 --- a/lib/private/Share/Share.php +++ b/lib/private/Share/Share.php @@ -2864,7 +2864,7 @@ private static function verifyPassword($password) { * @return Group[] */ private static function getGroupsForUser($user) { - $groups = \OC::$server->getGroupManager()->getUserIdGroups($user); + $groups = \OC::$server->getGroupManager()->getUserIdGroups($user, 'sharing'); return array_values(array_map(function(Group $g) { return $g->getGID(); }, $groups)); From 812c859d48a03ec033269220ebd10499ed04cf71 Mon Sep 17 00:00:00 2001 From: kdslkdsaldsal Date: Fri, 23 Jun 2017 23:37:12 +0200 Subject: [PATCH 11/12] Add Win10 User Agent for FakeLockerPlugin. Add missing response status. --- apps/dav/lib/Connector/Sabre/FakeLockerPlugin.php | 1 + apps/dav/lib/Server.php | 1 + 2 files changed, 2 insertions(+) diff --git a/apps/dav/lib/Connector/Sabre/FakeLockerPlugin.php b/apps/dav/lib/Connector/Sabre/FakeLockerPlugin.php index 6c07b51b8720..9025109b334e 100644 --- a/apps/dav/lib/Connector/Sabre/FakeLockerPlugin.php +++ b/apps/dav/lib/Connector/Sabre/FakeLockerPlugin.php @@ -135,6 +135,7 @@ public function fakeLockProvider(RequestInterface $request, new LockDiscovery([$lockInfo]) ]); + $response->setStatus(200); $response->setBody($body); return false; diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php index 649a8d0f63f9..14d285f5de77 100644 --- a/apps/dav/lib/Server.php +++ b/apps/dav/lib/Server.php @@ -143,6 +143,7 @@ public function __construct(IRequest $request, $baseUri) { if($request->isUserAgent([ '/WebDAVFS/', '/Microsoft Office OneNote 2013/', + '/Microsoft-WebDAV-MiniRedir/', ])) { $this->server->addPlugin(new FakeLockerPlugin()); } From 8c25d78bad3b0a632aeaa9aaf032e99d3f8b119b Mon Sep 17 00:00:00 2001 From: Tom Needham Date: Mon, 5 Jun 2017 16:44:51 +0200 Subject: [PATCH 12/12] Fix column lengths on migrations table to fix index --- version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.php b/version.php index 05c9bc9e25d4..b681411a0629 100644 --- a/version.php +++ b/version.php @@ -25,7 +25,7 @@ // We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades // between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel // when updating major/minor version number. -$OC_Version = [10, 0, 2, 1]; +$OC_Version = [10, 0, 2, 2]; // The human readable string $OC_VersionString = '10.0.2';