diff --git a/include/class_ldap.inc b/include/class_ldap.inc index 7f12ee8cf862015ffa3453b48ed1e301defb94e1..427be0ee34e6f0e388681f1a5888ebf0fe0f1083 100644 --- a/include/class_ldap.inc +++ b/include/class_ldap.inc @@ -309,7 +309,7 @@ class LDAP * * \param string $scope Scope of the search: subtree/base/one */ - function search ($srp, $filter, $attrs = [], $scope = 'subtree') + function search ($srp, $filter, $attrs = [], $scope = 'subtree', array $controls = NULL) { if ($this->hascon) { if ($this->reconnect) { @@ -320,14 +320,26 @@ class LDAP $this->clearResult($srp); switch (strtolower($scope)) { case 'base': - $this->sr[$srp] = @ldap_read($this->cid, $this->basedn, $filter, $attrs); + if (isset($controls)) { + $this->sr[$srp] = @ldap_read($this->cid, $this->basedn, $filter, $attrs, 0, 0, 0, LDAP_DEREF_NEVER, $controls); + } else { + $this->sr[$srp] = @ldap_read($this->cid, $this->basedn, $filter, $attrs); + } break; case 'one': - $this->sr[$srp] = @ldap_list($this->cid, $this->basedn, $filter, $attrs); + if (isset($controls)) { + $this->sr[$srp] = @ldap_list($this->cid, $this->basedn, $filter, $attrs, 0, 0, 0, LDAP_DEREF_NEVER, $controls); + } else { + $this->sr[$srp] = @ldap_list($this->cid, $this->basedn, $filter, $attrs); + } break; case 'subtree': default: - $this->sr[$srp] = @ldap_search($this->cid, $this->basedn, $filter, $attrs); + if (isset($controls)) { + $this->sr[$srp] = @ldap_search($this->cid, $this->basedn, $filter, $attrs, 0, 0, 0, LDAP_DEREF_NEVER, $controls); + } else { + $this->sr[$srp] = @ldap_search($this->cid, $this->basedn, $filter, $attrs); + } break; } $this->error = @ldap_error($this->cid); @@ -348,6 +360,21 @@ class LDAP } } + /*! + * \brief Parse last result + * + * \param integer $srp srp + * + */ + function parse_result ($srp, &$errcode, &$matcheddn, &$errmsg, &$referrals, &$controls): bool + { + if ($this->hascon && $this->hasres[$srp]) { + return @ldap_parse_result($this->cid, $this->sr[$srp], $errcode, $matcheddn, $errmsg, $referrals, $controls); + } + + return FALSE; + } + /* * \brief List * diff --git a/include/class_ldapMultiplexer.inc b/include/class_ldapMultiplexer.inc index 9bbae6a8bfe1c0fc461f037fce861acb91f7cfce..6cb5c86d3ba7b682c3249400b90b94b9e6d06c42 100644 --- a/include/class_ldapMultiplexer.inc +++ b/include/class_ldapMultiplexer.inc @@ -61,7 +61,7 @@ class ldapMultiplexer public function __call ($methodName, $parameters) { /* Add resource pointer if the mentioned methods are used */ - if (in_array($methodName, ['search','ls','cat','fetch','clearResult','resetResult','count','getDN','rmdir_recursive','create_missing_trees','import_single_entry','import_complete_ldif'])) { + if (in_array($methodName, ['search','ls','cat','fetch','clearResult','resetResult','count','getDN','rmdir_recursive','create_missing_trees','import_single_entry','import_complete_ldif','parse_result'])) { array_unshift($parameters, $this->sr); } diff --git a/setup/class_setupStepMigrate.inc b/setup/class_setupStepMigrate.inc index 908753ce5b2a878b33de9f191a07fea4bc2184f7..1b868556740b922495db8faa4c18f258f309b2db 100644 --- a/setup/class_setupStepMigrate.inc +++ b/setup/class_setupStepMigrate.inc @@ -974,13 +974,6 @@ class setupStepMigrate extends setupStep /*********** * Search for all users ***********/ - $res = $ldap->search('(&(objectClass=inetOrgPerson)(!(uid=*$)))', ['dn']); - if (!$res) { - throw new CheckFailedException( - _('LDAP query failed'), - _('Possibly the "root object" is missing.') - ); - } $sizeLimitHit = FALSE; /*********** @@ -988,24 +981,56 @@ class setupStepMigrate extends setupStep ***********/ $this->outsideUsers_toMigrate = []; $people_ou = trim(get_ou('userRDN')); + $cookie = ''; - while ($attrs = $ldap->fetch()) { - $people_db_base = preg_replace('/^[^,]+,'.preg_quote($people_ou, '/').'/i', '', $attrs['dn']); + do { + $res = $ldap->search('(&(objectClass=inetOrgPerson)(!(uid=*$)))', ['dn'], 0, 0, 0, LDAP_DEREF_NEVER, + [['oid' => LDAP_CONTROL_PAGEDRESULTS, 'value' => ['size' => 500, 'cookie' => $cookie]]] + ); + if (!$res) { + throw new CheckFailedException( + _('LDAP query failed'), + _('Possibly the "root object" is missing.') + ); + } + if (!$ldap->parse_result($errcode, $matcheddn, $errmsg, $referrals, $controls)) { + throw new CheckFailedException( + _('LDAP result parsing failed'), + _('LDAP result parsing failed') + ); + } + if ($errcode !== 0) { + throw new CheckFailedException( + _('LDAP error'), + $errmsg + ); + } + if (isset($controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'])) { + // You need to pass the cookie from the last call to the next one + $cookie = $controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie']; + } else { + $cookie = ''; + } - /* Check if entry is not an addressbook only user - * and verify that he is in a valid department - */ - if (!preg_match('/dc=addressbook,/', $people_db_base) && - !in_array($people_db_base, $config->getDepartmentList())) { - $attrs['checked'] = FALSE; - $attrs['ldif'] = ''; - $this->outsideUsers_toMigrate[base64_encode($attrs['dn'])] = $attrs; - if (count($this->outsideUsers_toMigrate) >= static::$objectNumberLimit) { - $sizeLimitHit = TRUE; - break; + while ($attrs = $ldap->fetch()) { + $people_db_base = preg_replace('/^[^,]+,'.preg_quote($people_ou, '/').'/i', '', $attrs['dn']); + + /* Check if entry is not an addressbook only user + * and verify that he is in a valid department + */ + if (!preg_match('/dc=addressbook,/', $people_db_base) && + !in_array($people_db_base, $config->getDepartmentList())) { + $attrs['checked'] = FALSE; + $attrs['ldif'] = ''; + $this->outsideUsers_toMigrate[base64_encode($attrs['dn'])] = $attrs; + if (count($this->outsideUsers_toMigrate) >= static::$objectNumberLimit) { + $sizeLimitHit = TRUE; + break 2; + } } } - } + // Empty cookie means last page + } while (!empty($cookie)); if (count($this->outsideUsers_toMigrate) == 0) { return '';