From 4a5cecd6fa64b33a63c39d289565837e6d8ac340 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Wed, 7 Oct 2015 18:57:49 +0200 Subject: [PATCH 1/6] allow an attribute to return more than one value --- apps/user_ldap/lib/access.php | 41 +++++++++++------------------------ apps/user_ldap/lib/wizard.php | 2 +- 2 files changed, 14 insertions(+), 29 deletions(-) diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index a2fdd88a24..c7ec06f356 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -710,6 +710,9 @@ class Access extends LDAPUtility implements user\IUserTools { if($manyAttributes) { return $list; } else { + $list = array_reduce($list, function($carry, $item) { + $carry[] = $item[0]; + }, array()); return array_unique($list, SORT_LOCALE_STRING); } } @@ -982,44 +985,26 @@ class Access extends LDAPUtility implements user\IUserTools { if(!is_null($attr)) { $selection = array(); - $multiArray = false; - if(count($attr) > 1) { - $multiArray = true; - $i = 0; - } + $i = 0; foreach($findings as $item) { if(!is_array($item)) { continue; } $item = \OCP\Util::mb_array_change_key_case($item, MB_CASE_LOWER, 'UTF-8'); - - if($multiArray) { - foreach($attr as $key) { - $key = mb_strtolower($key, 'UTF-8'); - if(isset($item[$key])) { - if($key !== 'dn') { - $selection[$i][$key] = $this->resemblesDN($key) ? - $this->sanitizeDN($item[$key][0]) - : $item[$key][0]; - } else { - $selection[$i][$key] = $this->sanitizeDN($item[$key]); - } - } - - } - $i++; - } else { - //tribute to case insensitivity - $key = mb_strtolower($attr[0], 'UTF-8'); - + foreach($attr as $key) { + $key = mb_strtolower($key, 'UTF-8'); if(isset($item[$key])) { - if($this->resemblesDN($key)) { - $selection[] = $this->sanitizeDN($item[$key]); + if($key !== 'dn') { + $selection[$i][$key] = $this->resemblesDN($key) ? + $this->sanitizeDN($item[$key]) + : $item[$key]; } else { - $selection[] = $item[$key]; + $selection[$i][$key] = $this->sanitizeDN($item[$key]); } } + } + $i++; } $findings = $selection; } diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php index 18a0412a63..a8fcae6314 100644 --- a/apps/user_ldap/lib/wizard.php +++ b/apps/user_ldap/lib/wizard.php @@ -435,7 +435,7 @@ class Wizard extends LDAPUtility { // detection will fail later $result = $this->access->searchGroups($filter, array('cn', 'dn'), $limit, $offset); foreach($result as $item) { - $groupNames[] = $item['cn']; + $groupNames[] = $item['cn'][0]; $groupEntries[] = $item; } $offset += $limit; From dd2e887a8d9be9cb95a52582612bf95e2f8eb247 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 8 Oct 2015 20:32:15 +0200 Subject: [PATCH 2/6] adjust handling changed return array structure from search() and fetchList() --- apps/user_ldap/group_ldap.php | 2 +- apps/user_ldap/lib/access.php | 23 ++++++++++++++++++----- apps/user_ldap/lib/user/user.php | 17 ++++++++++------- apps/user_ldap/lib/wizard.php | 4 ++++ 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/apps/user_ldap/group_ldap.php b/apps/user_ldap/group_ldap.php index 97ed8fa91a..200ee6ea4a 100644 --- a/apps/user_ldap/group_ldap.php +++ b/apps/user_ldap/group_ldap.php @@ -653,7 +653,7 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { str_replace('%uid', $member, $this->access->connection->ldapLoginFilter), $this->access->getFilterPartForUserSearch($search) )); - $ldap_users = $this->access->fetchListOfUsers($filter, 'dn'); + $ldap_users = $this->access->fetchListOfUsers($filter, 'dn', 1); if(count($ldap_users) < 1) { continue; } diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index c7ec06f356..1809700b1b 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -489,7 +489,7 @@ class Access extends LDAPUtility implements user\IUserTools { /** * gives back the user names as they are used ownClod internally - * @param array $ldapUsers an array with the ldap Users result in style of array ( array ('dn' => foo, 'uid' => bar), ... ) + * @param array $ldapUsers as returned by fetchList() * @return array an array with the user names to use in ownCloud * * gives back the user names as they are used ownClod internally @@ -500,7 +500,7 @@ class Access extends LDAPUtility implements user\IUserTools { /** * gives back the group names as they are used ownClod internally - * @param array $ldapGroups an array with the ldap Groups result in style of array ( array ('dn' => foo, 'cn' => bar), ... ) + * @param array $ldapGroups as returned by fetchList() * @return array an array with the group names to use in ownCloud * * gives back the group names as they are used ownClod internally @@ -510,7 +510,7 @@ class Access extends LDAPUtility implements user\IUserTools { } /** - * @param array $ldapObjects + * @param array $ldapObjects as returned by fetchList() * @param bool $isUsers * @return array */ @@ -523,7 +523,15 @@ class Access extends LDAPUtility implements user\IUserTools { $ownCloudNames = array(); foreach($ldapObjects as $ldapObject) { - $nameByLDAP = isset($ldapObject[$nameAttribute]) ? $ldapObject[$nameAttribute] : null; + $nameByLDAP = null; + if( isset($ldapObject[$nameAttribute]) + && is_array($ldapObject[$nameAttribute]) + && isset($ldapObject[$nameAttribute][0]) + ) { + // might be set, but not necessarily. if so, we use it. + $nameByLDAP = $ldapObject[$nameAttribute][0]; + } + $ocName = $this->dn2ocname($ldapObject['dn'], $nameByLDAP, $isUsers); if($ocName) { $ownCloudNames[] = $ocName; @@ -531,7 +539,9 @@ class Access extends LDAPUtility implements user\IUserTools { //cache the user names so it does not need to be retrieved //again later (e.g. sharing dialogue). $this->cacheUserExists($ocName); - $this->cacheUserDisplayName($ocName, $nameByLDAP); + if(!is_null($nameByLDAP)) { + $this->cacheUserDisplayName($ocName, $nameByLDAP); + } } } continue; @@ -994,6 +1004,9 @@ class Access extends LDAPUtility implements user\IUserTools { foreach($attr as $key) { $key = mb_strtolower($key, 'UTF-8'); if(isset($item[$key])) { + if(is_array($item[$key]) && isset($item[$key]['count'])) { + unset($item[$key]['count']); + } if($key !== 'dn') { $selection[$i][$key] = $this->resemblesDN($key) ? $this->sanitizeDN($item[$key]) diff --git a/apps/user_ldap/lib/user/user.php b/apps/user_ldap/lib/user/user.php index 6498cdf913..d8148035d3 100644 --- a/apps/user_ldap/lib/user/user.php +++ b/apps/user_ldap/lib/user/user.php @@ -147,21 +147,21 @@ class User { //Quota $attr = strtolower($this->connection->ldapQuotaAttribute); if(isset($ldapEntry[$attr])) { - $this->updateQuota($ldapEntry[$attr]); + $this->updateQuota($ldapEntry[$attr][0]); } unset($attr); //Email $attr = strtolower($this->connection->ldapEmailAttribute); if(isset($ldapEntry[$attr])) { - $this->updateEmail($ldapEntry[$attr]); + $this->updateEmail($ldapEntry[$attr][0]); } unset($attr); //displayName $attr = strtolower($this->connection->ldapUserDisplayName); if(isset($ldapEntry[$attr])) { - $displayName = $ldapEntry[$attr]; + $displayName = $ldapEntry[$attr][0]; if(!empty($displayName)) { $this->storeDisplayName($displayName); $this->access->cacheUserDisplayName($this->getUsername(), $displayName); @@ -171,18 +171,20 @@ class User { // LDAP Username, needed for s2s sharing if(isset($ldapEntry['uid'])) { - $this->storeLDAPUserName($ldapEntry['uid']); + $this->storeLDAPUserName($ldapEntry['uid'][0]); } else if(isset($ldapEntry['samaccountname'])) { - $this->storeLDAPUserName($ldapEntry['samaccountname']); + $this->storeLDAPUserName($ldapEntry['samaccountname'][0]); } + //homePath if(strpos($this->connection->homeFolderNamingRule, 'attr:') === 0) { $attr = strtolower(substr($this->connection->homeFolderNamingRule, strlen('attr:'))); if(isset($ldapEntry[$attr])) { $this->access->cacheUserHome( - $this->getUsername(), $this->getHomePath($ldapEntry[$attr])); + $this->getUsername(), $this->getHomePath($ldapEntry[$attr][0])); } } + //memberOf groups $cacheKey = 'getMemberOf'.$this->getUsername(); $groups = false; @@ -190,11 +192,12 @@ class User { $groups = $ldapEntry['memberof']; } $this->connection->writeToCache($cacheKey, $groups); + //Avatar $attrs = array('jpegphoto', 'thumbnailphoto'); foreach ($attrs as $attr) { if(isset($ldapEntry[$attr])) { - $this->avatarImage = $ldapEntry[$attr]; + $this->avatarImage = $ldapEntry[$attr][0]; $this->updateAvatar(); break; } diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php index a8fcae6314..64b3557e31 100644 --- a/apps/user_ldap/lib/wizard.php +++ b/apps/user_ldap/lib/wizard.php @@ -435,6 +435,10 @@ class Wizard extends LDAPUtility { // detection will fail later $result = $this->access->searchGroups($filter, array('cn', 'dn'), $limit, $offset); foreach($result as $item) { + if(!isset($item['cn']) && !is_array($item['cn']) && !isset($item['cn'][0])) { + // just in case - no issue known + continue; + } $groupNames[] = $item['cn'][0]; $groupEntries[] = $item; } From a876efda50680f7d8652299cb5265dc552be45cf Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 8 Oct 2015 21:18:34 +0200 Subject: [PATCH 3/6] treat dn as any other attribute when building the search() return array --- apps/user_ldap/group_ldap.php | 2 +- apps/user_ldap/lib/access.php | 6 +++--- apps/user_ldap/user_ldap.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/user_ldap/group_ldap.php b/apps/user_ldap/group_ldap.php index 200ee6ea4a..0b9c9d9d5f 100644 --- a/apps/user_ldap/group_ldap.php +++ b/apps/user_ldap/group_ldap.php @@ -491,7 +491,7 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { array($this->access->connection->ldapGroupDisplayName, 'dn')); if (is_array($groups)) { foreach ($groups as $groupobj) { - $groupDN = $groupobj['dn']; + $groupDN = $groupobj['dn'][0]; $allGroups[$groupDN] = $groupobj; $nestedGroups = $this->access->connection->ldapNestedGroups; if (!empty($nestedGroups)) { diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index 1809700b1b..adfb11da67 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -532,7 +532,7 @@ class Access extends LDAPUtility implements user\IUserTools { $nameByLDAP = $ldapObject[$nameAttribute][0]; } - $ocName = $this->dn2ocname($ldapObject['dn'], $nameByLDAP, $isUsers); + $ocName = $this->dn2ocname($ldapObject['dn'][0], $nameByLDAP, $isUsers); if($ocName) { $ownCloudNames[] = $ocName; if($isUsers) { @@ -692,7 +692,7 @@ class Access extends LDAPUtility implements user\IUserTools { */ public function batchApplyUserAttributes(array $ldapRecords){ foreach($ldapRecords as $userRecord) { - $ocName = $this->dn2ocname($userRecord['dn'], $userRecord[$this->connection->ldapUserDisplayName]); + $ocName = $this->dn2ocname($userRecord['dn'][0], $userRecord[$this->connection->ldapUserDisplayName]); $this->cacheUserExists($ocName); $user = $this->userManager->get($ocName); $user->processAttributes($userRecord); @@ -1012,7 +1012,7 @@ class Access extends LDAPUtility implements user\IUserTools { $this->sanitizeDN($item[$key]) : $item[$key]; } else { - $selection[$i][$key] = $this->sanitizeDN($item[$key]); + $selection[$i][$key] = [$this->sanitizeDN($item[$key])]; } } diff --git a/apps/user_ldap/user_ldap.php b/apps/user_ldap/user_ldap.php index 59c61524c9..fc8ce36163 100644 --- a/apps/user_ldap/user_ldap.php +++ b/apps/user_ldap/user_ldap.php @@ -78,7 +78,7 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn public function loginName2UserName($loginName) { try { $ldapRecord = $this->getLDAPUserByLoginName($loginName); - $user = $this->access->userManager->get($ldapRecord['dn']); + $user = $this->access->userManager->get($ldapRecord['dn'][0]); if($user instanceof OfflineUser) { return false; } @@ -119,7 +119,7 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn } catch(\Exception $e) { return false; } - $dn = $ldapRecord['dn']; + $dn = $ldapRecord['dn'][0]; $user = $this->access->userManager->get($dn); if(!$user instanceof User) { From 2fddb1367acc381de965234588c84779ca178756 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Fri, 9 Oct 2015 14:12:59 +0200 Subject: [PATCH 4/6] fix primary group retrieval --- apps/user_ldap/group_ldap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/user_ldap/group_ldap.php b/apps/user_ldap/group_ldap.php index 0b9c9d9d5f..cf58e5b902 100644 --- a/apps/user_ldap/group_ldap.php +++ b/apps/user_ldap/group_ldap.php @@ -247,7 +247,7 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { if(empty($result)) { return false; } - $dn = $result[0]; + $dn = $result[0]['dn'][0]; //and now the group name //NOTE once we have separate ownCloud group IDs and group names we can From d127b3f0d274547e1806bb33819b9966a6b544cb Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Fri, 9 Oct 2015 14:30:49 +0200 Subject: [PATCH 5/6] adjust tests --- apps/user_ldap/tests/group_ldap.php | 4 ++-- apps/user_ldap/tests/user_ldap.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/user_ldap/tests/group_ldap.php b/apps/user_ldap/tests/group_ldap.php index 132fbfdf68..8ed2bc5c67 100644 --- a/apps/user_ldap/tests/group_ldap.php +++ b/apps/user_ldap/tests/group_ldap.php @@ -145,7 +145,7 @@ class Test_Group_Ldap extends \Test\TestCase { $access->expects($this->once()) ->method('searchGroups') - ->will($this->returnValue(array('cn=foo,dc=barfoo,dc=bar'))); + ->will($this->returnValue([['dn' => ['cn=foo,dc=barfoo,dc=bar']]])); $access->expects($this->once()) ->method('dn2groupname') @@ -221,7 +221,7 @@ class Test_Group_Ldap extends \Test\TestCase { $access->expects($this->once()) ->method('searchGroups') - ->will($this->returnValue(array('cn=foo,dc=barfoo,dc=bar'))); + ->will($this->returnValue([['dn' => ['cn=foo,dc=barfoo,dc=bar']]])); $access->expects($this->once()) ->method('dn2groupname') diff --git a/apps/user_ldap/tests/user_ldap.php b/apps/user_ldap/tests/user_ldap.php index 69a76c0b7a..0f70c43fc1 100644 --- a/apps/user_ldap/tests/user_ldap.php +++ b/apps/user_ldap/tests/user_ldap.php @@ -124,7 +124,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase { ->method('fetchListOfUsers') ->will($this->returnCallback(function($filter) { if($filter === 'roland') { - return array(array('dn' => 'dnOfRoland,dc=test')); + return array(array('dn' => ['dnOfRoland,dc=test'])); } return array(); })); @@ -133,7 +133,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase { ->method('fetchUsersByLoginName') ->will($this->returnCallback(function($uid) { if($uid === 'roland') { - return array(array('dn' => 'dnOfRoland,dc=test')); + return array(array('dn' => ['dnOfRoland,dc=test'])); } return array(); })); From e3a148584a434fe9748a4164dcddf77a402e0966 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Fri, 9 Oct 2015 20:07:35 +0200 Subject: [PATCH 6/6] adjust fetchList with a single requested attribute accordingly --- apps/user_ldap/lib/access.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index adfb11da67..c3a15c3ee4 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -721,7 +721,9 @@ class Access extends LDAPUtility implements user\IUserTools { return $list; } else { $list = array_reduce($list, function($carry, $item) { - $carry[] = $item[0]; + $attribute = array_keys($item)[0]; + $carry[] = $item[$attribute][0]; + return $carry; }, array()); return array_unique($list, SORT_LOCALE_STRING); }