@@ -336,6 +336,8 @@ class LdapError < StandardError; end
336
336
337
337
module LDAPControls
338
338
PAGED_RESULTS = "1.2.840.113556.1.4.319" # Microsoft evil from RFC 2696
339
+ SORT_REQUEST = "1.2.840.113556.1.4.473"
340
+ SORT_RESPONSE = "1.2.840.113556.1.4.474"
339
341
DELETE_TREE = "1.2.840.113556.1.4.805"
340
342
end
341
343
@@ -1328,6 +1330,35 @@ def bind_gss_spnego(auth)
1328
1330
end
1329
1331
private :bind_gss_spnego
1330
1332
1333
+
1334
+ #--
1335
+ # Allow the caller to specify a sort control
1336
+ #
1337
+ # The format of the sort control needs to be:
1338
+ #
1339
+ # :sort_control => ["cn"] # just a string
1340
+ # or
1341
+ # :sort_control => [["cn", "matchingRule", true]] #attribute, matchingRule, direction (true / false)
1342
+ # or
1343
+ # :sort_control => ["givenname","sn"] #multiple strings or arrays
1344
+ #
1345
+ def encode_sort_controls ( sort_definitions )
1346
+ return sort_definitions unless sort_definitions
1347
+
1348
+ sort_control_values = sort_definitions . map do |control |
1349
+ control = Array ( control ) # if there is only an attribute name as a string then infer the orderinrule and reverseorder
1350
+ control [ 0 ] = String ( control [ 0 ] ) . to_ber ,
1351
+ control [ 1 ] = String ( control [ 1 ] ) . to_ber ,
1352
+ control [ 2 ] = ( control [ 2 ] == true ) . to_ber
1353
+ control . to_ber_sequence
1354
+ end
1355
+ sort_control = [
1356
+ Net ::LDAP ::LDAPControls ::SORT_REQUEST . to_ber ,
1357
+ false . to_ber ,
1358
+ sort_control_values . to_ber_sequence . to_s . to_ber
1359
+ ] . to_ber_sequence
1360
+ end
1361
+
1331
1362
#--
1332
1363
# Alternate implementation, this yields each search entry to the caller as
1333
1364
# it are received.
@@ -1353,6 +1384,7 @@ def search(args = {})
1353
1384
scope = args [ :scope ] || Net ::LDAP ::SearchScope_WholeSubtree
1354
1385
raise Net ::LDAP ::LdapError , "invalid search scope" unless Net ::LDAP ::SearchScopes . include? ( scope )
1355
1386
1387
+ sort_control = encode_sort_controls ( args . fetch ( :sort_controls ) { false } )
1356
1388
# An interesting value for the size limit would be close to A/D's
1357
1389
# built-in page limit of 1000 records, but openLDAP newer than version
1358
1390
# 2.2.0 chokes on anything bigger than 126. You get a silent error that
@@ -1408,6 +1440,8 @@ def search(args = {})
1408
1440
false . to_ber ,
1409
1441
rfc2696_cookie . map { |v | v . to_ber } . to_ber_sequence . to_s . to_ber
1410
1442
] . to_ber_sequence if paged_searches_supported
1443
+
1444
+ controls << sort_control if sort_control
1411
1445
controls = controls . to_ber_contextspecific ( 0 )
1412
1446
1413
1447
pkt = [ next_msgid . to_ber , request , controls ] . to_ber_sequence
0 commit comments