@@ -626,6 +626,10 @@ def open
626626 # array, so we can provide sort methods and what-not.
627627 #
628628 def search args = { }
629+ unless args [ :ignore_server_caps ]
630+ args [ :paged_searches_supported ] = paged_searches_supported?
631+ end
632+
629633 args [ :base ] ||= @base
630634 result_set = ( args and args [ :return_result ] == false ) ? nil : [ ]
631635
@@ -1011,16 +1015,30 @@ def delete args
10111015 # On failure, the empty Entry will have a nil DN. There's no real reason for that,
10121016 # so it can be changed if desired.
10131017 # The funky number-disagreements in the set of attribute names is correct per the RFC.
1018+ # We may be called by #search itself, which may need to determine things like paged
1019+ # search capabilities. So to avoid an infinite regress, set :ignore_server_caps,
1020+ # which prevents us getting called recursively.
10141021 #
10151022 def search_root_dse
10161023 rs = search (
1024+ :ignore_server_caps => true ,
10171025 :base => "" ,
10181026 :scope => SearchScope_BaseObject ,
10191027 :attributes => [ :namingContexts , :supportedLdapVersion , :altServer , :supportedControl , :supportedExtension , :supportedFeatures , :supportedSASLMechanisms ]
10201028 )
10211029 ( rs and rs . first ) or Entry . new
10221030 end
10231031
1032+ #--
1033+ # Convenience method to query server capabilities.
1034+ # Only do this once per Net::LDAP object.
1035+ # Note, we call a search, and we might be called from inside a search!
1036+ # MUST refactor the root_dse call out.
1037+ def paged_searches_supported?
1038+ @server_caps ||= search_root_dse
1039+ @server_caps [ :supportedcontrol ] . include? ( LdapControls ::PagedResults )
1040+ end
1041+
10241042 end # class LDAP
10251043
10261044
@@ -1153,6 +1171,7 @@ def search args = {}
11531171 return_referrals = args && args [ :return_referrals ] == true
11541172 sizelimit = ( args && args [ :size ] . to_i ) || 0
11551173 raise LdapError . new ( "invalid search-size" ) unless sizelimit >= 0
1174+ paged_searches_supported = ( args && args [ :paged_searches_supported ] )
11561175
11571176 attributes_only = ( args and args [ :attributes_only ] == true )
11581177 scope = args [ :scope ] || Net ::LDAP ::SearchScope_WholeSubtree
@@ -1182,10 +1201,13 @@ def search args = {}
11821201 loop {
11831202 # should collect this into a private helper to clarify the structure
11841203
1185- query_limit = if ( sizelimit > 0 ) && ( ( sizelimit - n_results ) < 126 )
1186- sizelimit - n_results
1187- else
1188- 0
1204+ query_limit = 0
1205+ if sizelimit > 0
1206+ if paged_searches_supported
1207+ query_limit = ( ( ( sizelimit - n_results ) < 126 ) ? ( sizelimit - n_results ) : 0 )
1208+ else
1209+ query_limit = sizelimit
1210+ end
11891211 end
11901212
11911213 request = [
@@ -1273,7 +1295,6 @@ def search args = {}
12731295
12741296
12751297
1276-
12771298 #--
12781299 # modify
12791300 # TODO, need to support a time limit, in case the server fails to respond.
0 commit comments