Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions lib/net/ldap/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -289,21 +289,21 @@ def bind(auth)
#
# The format of the sort control needs to be:
#
# :sort_control => ["cn"] # just a string
# :sort_controls => ["cn"] # just a string
# or
# :sort_control => [["cn", "matchingRule", true]] #attribute, matchingRule, direction (true / false)
# :sort_controls => [["cn", "orderingRule", true]] #attribute, orderingRule, reverseOrder (true / false)
# or
# :sort_control => ["givenname","sn"] #multiple strings or arrays
# :sort_controls => ["givenname","sn"] #multiple strings or arrays
#
def encode_sort_controls(sort_definitions)
return sort_definitions unless sort_definitions

sort_control_values = sort_definitions.map do |control|
control = Array(control) # if there is only an attribute name as a string then infer the orderinrule and reverseorder
control[0] = String(control[0]).to_ber,
control[1] = String(control[1]).to_ber,
control[2] = (control[2] == true).to_ber
control.to_ber_sequence
attribute, rule, reverse = Array(control) # a bare string is just the attribute name
key = [String(attribute).to_ber]
key << String(rule).to_ber_contextspecific(0) unless rule.nil? || rule.to_s.empty?
key << "\xFF".b.to_ber_contextspecific(1) if reverse == true
key.to_ber_sequence
end
[
Net::LDAP::LDAPControls::SORT_REQUEST.to_ber,
Expand Down
49 changes: 49 additions & 0 deletions test/test_ldap_connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,55 @@ def test_modify_ops_replace
assert_equal(expected, result)
end

def sort_keys(control)
oid, criticality, value = control.read_ber
assert_equal(Net::LDAP::LDAPControls::SORT_REQUEST, oid)
assert_equal(false, criticality)
value.read_ber(Net::LDAP::AsnSyntax)
end

def test_encode_sort_controls_attribute_only
conn = Net::LDAP::Connection.new
keys = sort_keys(conn.encode_sort_controls(["cn"]))
assert_equal([["cn"]], keys)
end

def test_encode_sort_controls_rule_and_reverse
conn = Net::LDAP::Connection.new
control = conn.encode_sort_controls([["cn", "caseIgnoreOrderingMatch", true]])
_oid, _criticality, value = control.read_ber
assert_equal("0\x22" \
"0\x20" \
"\x04\x02cn" \
"\x80\x17caseIgnoreOrderingMatch" \
"\x81\x01\xFF".b, value)
attribute, rule, reverse = sort_keys(control).first
assert_equal("cn", attribute)
assert_equal("caseIgnoreOrderingMatch", rule)
assert_equal(0x80, rule.ber_identifier)
assert_equal("\xFF".b, reverse)
assert_equal(0x81, reverse.ber_identifier)
end

def test_encode_sort_controls_omits_defaults
conn = Net::LDAP::Connection.new
keys = sort_keys(conn.encode_sort_controls([["cn", nil, false]]))
assert_equal(["cn"], keys.first)
end

def test_encode_sort_controls_multiple_keys
conn = Net::LDAP::Connection.new
keys = sort_keys(conn.encode_sort_controls(["givenname", ["sn", nil, true]]))
assert_equal(["givenname"], keys[0])
assert_equal(["sn", "\xFF".b], keys[1])
end

def test_encode_sort_controls_passes_through_false
conn = Net::LDAP::Connection.new
assert_equal(false, conn.encode_sort_controls(false))
assert_nil(conn.encode_sort_controls(nil))
end

def test_write
mock = flexmock("socket")
mock.should_receive(:write).with([1.to_ber, "request"].to_ber_sequence).and_return(true)
Expand Down