penfold_99 Posted February 9, 2009 Posted February 9, 2009 (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 February 9, 2009 by penfold_99 Added: Its an AD Domain
localzuk Posted February 9, 2009 Posted February 9, 2009 Active Directory has a page limit size by default. (I always thought it was 1000 objects, so I'm not sure how you're getting 2500). You can change this using How to view and set LDAP policy in Active Directory by using Ntdsutil.exe
srochford Posted February 9, 2009 Posted February 9, 2009 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
penfold_99 Posted February 9, 2009 Author Posted February 9, 2009 Active Directory has a page limit size by default. (I always thought it was 1000 objects, so I'm not sure how you're getting 2500). You can change this using How to view and set LDAP policy in Active Directory by using Ntdsutil.exe Thanks, I think the limit was increased ages ago before i started here.
localzuk Posted February 9, 2009 Posted February 9, 2009 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...
penfold_99 Posted February 9, 2009 Author Posted February 9, 2009 @srochford i trying to convert a vbs to php, but i think php doesn't have the ability to page like perl and pear can.
Geoff Posted February 9, 2009 Posted February 9, 2009 (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 February 9, 2009 by Geoff 2
penfold_99 Posted February 9, 2009 Author Posted February 9, 2009 @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?
igord Posted December 23, 2009 Posted December 23, 2009 Hello. Did you find any solution? See Reading paged LDAP results with PHP is a show-stopper <?php. Seems this is the only article that shed light on that problem. Hopefully the answers (still waiting for them) on my questions will help to solve the issue without patching PHP. Thanks, Igor
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now