Jump to content

Recommended Posts

Posted (edited)

Hi,

 

I am trying to pull information on all our student account from LDAP.

 

The issue i'm having is i can only get 2500 accounts but Active Directory holds 3500ish.

 

Is there way to increase the ldap result cache, you can do this in vbs by setting "pagesize" but i can't find how to do it in php.

 

Or is there a way to page the results by getting 2500 then the remainder in two calls?

Edited by penfold_99
Added: Its an AD Domain
Posted

Set PHP to use paging (not the same as setting the maxpagesize)

 

the code below is vbscript rather than PHP but I hope it's reasonably obvious what's going on. Key thing is that you specify how many results you want returning at a time (page size is set to 100 here). That doesn't mean you only get 100 results; magic stuff just happens in the background so that when you do a "movenext" it either takes a record from the 100 it just got or it fetches another 100 from the server.

 

In general, it's a bad idea to change the maxpagesize because it doesn't scale - you're potentially putting a huge load on the server (think about what happens when there are 10,000 or 100,000 records to return) for no real benefit.

 

Set oRootDSE = GetObject("LDAP://RootDSE")
sDNSDomain = oRootDSE.Get("defaultNamingContext")
Set ocommand = CreateObject("ADODB.Command")
Set oConn = CreateObject("ADODB.Connection")
oConn.Provider = "ADsDSOObject"
oConn.Open
ocommand.ActiveConnection = oConn
sBase = ""
'find users with email
'sFilter="(&(objectClass=user)(mail=*))"

sAttributes="distinguishedname"

sQuery = sBase & ";" & sFilter & ";" & sAttributes & ";subtree"

ocommand.CommandText = sQuery

'return records in groups of 100 - user doesn't see anything but it avoids stressing server.
'by default won't get more than 1000 records back so if more than 1000 records must set this
ocommand.Properties("Page Size") = 100
'how long to wait for results; if not returned in this time then script will give up
ocommand.Properties("Timeout") = 60
'don't store data locally; if query run again then will re-visit server
ocommand.Properties("Cache Results") = False
oCommand.properties("sort on")="samaccountname"
'execute the query against AD and get a recordset
Set oRS = ocommand.Execute
'check - did we get any results
if not oRS.eof then
 'yes, so process all of them
   Do Until oRS.EOF
   'code like this means you can have any number of fields; process each in turn
   for each sField in oRS.fields
   'write the returned value
     wscript.echo oRS.Fields(sField.name)
   next
   'next record
   oRS.MoveNext
 Loop
else
 'we didn't get any records so just give warning
  wscript.echo "No records found"
end if
ors.close

Posted
Set PHP to use paging (not the same as setting the maxpagesize)

 

I would have suggested it, but have not been able to figure out how to do such a thing with PHP...

Posted (edited)

It doesn't on it's own. However the API gives you the necessary tools to page through results yourself.

 

$continue = true;
while ($continue) {
    $paged_control = array(
                        array(
                            'oid' => PAGED_CONTROL_OID,
                            'iscritical' => true,
                            'value' => ldap_ber_printf ('{iO}',
                                                        PAGE_SIZE, $cookie)
                        )
                     );
    if (!ldap_set_option($l, LDAP_OPT_SERVER_CONTROLS, $paged_control)) {
        echo "Not OK: ldap_set_option (controls)\n";
        exit;
    }

    $sr = ldap_search($l, $query, $query_filter, $query_attribs, 0, 0, 0,
                      LDAP_DEREF_NEVER);

    if ($sr === FALSE) {
        echo "Not OK: ldap_search\n";
        exit;
    }

    if (!ldap_parse_result ($l, $sr, &$errcode, &$matcheddn, &$errmsg,
                            &$referrals, &$serverctrls)) {
        echo "Not OK: ldap_parse_result\n";
        exit;
    }

    $paged_control_found = FALSE;
    if (isset($serverctrls)) {
        foreach ($serverctrls as $i) {
            if ($i['oid'] == PAGED_CONTROL_OID) {
                ldap_ber_scanf($i['value'], '{iO}', &$pagesize, &$cookie);
                $paged_control_found = TRUE;
                break;
            }
        }
    }
    if (!$paged_control_found) {
        echo "Not OK: paged control not found in response \n";
        exit;
    }

    // process entries as usual here ...

    if ($cookie == '') {
        $continue = false;
    }
}

Edited by Geoff
  • Thanks 2
Posted

@Geoff,

 

Thanks for the script, i have tried to implement but when i do var_dump(ldap_count_entries($l,$sr); nothing is returned.

 

I have set $cookie to a value of 1000, so in theory it should loop three times to get all results.

 

or an i doing this all wrong?

  • 10 months later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now



×
×
  • Create New...