diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php index eb2a1ab02d..0cec493d9e 100644 --- a/apps/user_ldap/lib/wizard.php +++ b/apps/user_ldap/lib/wizard.php @@ -994,6 +994,7 @@ class Wizard extends LDAPUtility { if(!$this->ldap->isResource($entry)) { continue 2; } + $rr = $entry; //will be expected by nextEntry next round $attributes = $this->ldap->getAttributes($cr, $entry); $dn = $this->ldap->getDN($cr, $entry); if($dn === false || in_array($dn, $dnRead)) { @@ -1007,7 +1008,6 @@ class Wizard extends LDAPUtility { $foundItems = array_merge($foundItems, $newItems); $this->resultCache[$dn][$attr] = $newItems; $dnRead[] = $dn; - $rr = $entry; //will be expected by nextEntry next round } while(($state === self::LRESULT_PROCESSED_SKIP || $this->ldap->isResource($entry)) && ($dnReadLimit === 0 || $dnReadCount < $dnReadLimit)); diff --git a/apps/user_ldap/tests/wizard.php b/apps/user_ldap/tests/wizard.php index ff5ee010b7..786769a88c 100644 --- a/apps/user_ldap/tests/wizard.php +++ b/apps/user_ldap/tests/wizard.php @@ -207,4 +207,82 @@ class Test_Wizard extends \PHPUnit_Framework_TestCase { unset($uidnumber); } + public function testCumulativeSearchOnAttributeSkipReadDN() { + // tests that there is no infinite loop, when skipping already processed + // DNs (they can be returned multiple times for multiple filters ) + list($wizard, $configuration, $ldap) = $this->getWizardAndMocks(); + + $configuration->expects($this->any()) + ->method('__get') + ->will($this->returnCallback(function($name) { + if($name === 'ldapBase') { + return array('base'); + } + return null; + })); + + $this->prepareLdapWrapperForConnections($ldap); + + $ldap->expects($this->any()) + ->method('isResource') + ->will($this->returnCallback(function($res) { + return (bool)$res; + })); + + $ldap->expects($this->any()) + ->method('search') + //dummy value, usually invalid + ->will($this->returnValue(true)); + + $ldap->expects($this->any()) + ->method('countEntries') + //an is_resource check will follow, so we need to return a dummy resource + ->will($this->returnValue(7)); + + //5 DNs per filter means 2x firstEntry and 8x nextEntry + $ldap->expects($this->any()) + ->method('firstEntry') + //dummy value, usually invalid + ->will($this->returnValue(1)); + + global $mark; + $mark = false; + // entries return order: 1, 2, 3, 4, 4, 5, 6 + $ldap->expects($this->any()) + ->method('nextEntry') + //dummy value, usually invalid + ->will($this->returnCallback(function($a, $prev){ + $current = $prev + 1; + if($current === 7) { + return false; + } + global $mark; + if($prev === 4 && !$mark) { + $mark = true; + return 4; + } + return $current; + })); + + $ldap->expects($this->any()) + ->method('getAttributes') + //dummy value, usually invalid + ->will($this->returnCallback(function($a, $entry) { + return array('cn' => array($entry), 'count' => 1); + })); + + $ldap->expects($this->any()) + ->method('getDN') + //dummy value, usually invalid + ->will($this->returnCallback(function($a, $b) { + return $b; + })); + + # The following expectations are the real test # + $filters = array('f1', 'f2', '*'); + $resultArray = $wizard->cumulativeSearchOnAttribute($filters, 'cn', true, 0); + $this->assertSame(6, count($resultArray)); + unset($mark); + } + }