@@ -42,7 +42,7 @@ class LDAP::Request
42
42
}, Tag ::BindRequest ))
43
43
end
44
44
45
- alias SortControl = NamedTuple (name: String , rule: String , reverse: Bool )
45
+ alias SortControl = NamedTuple (name: String , rule: String , reverse: Bool ) | NamedTuple ( name: String , reverse: Bool )
46
46
47
47
PAGED_RESULTS = " 1.2.840.113556.1.4.319" # Microsoft evil from RFC 2696
48
48
DELETE_TREE = " 1.2.840.113556.1.4.805"
@@ -52,26 +52,31 @@ class LDAP::Request
52
52
def encode_sort_controls (* sort_controls : String | SortControl )
53
53
sort_controls = sort_controls.map do |control |
54
54
if control.is_a?(SortControl )
55
- {
55
+ LDAP .sequence( {
56
56
BER .new.set_string(control[:name ], UniversalTags ::OctetString ),
57
- BER .new.set_string(control[:rule ], UniversalTags ::OctetString ),
57
+ BER .new.set_string(control[:rule ]? || " " , UniversalTags ::OctetString ),
58
58
BER .new.set_boolean(control[:reverse ]),
59
- }
59
+ })
60
60
else
61
- {
61
+ LDAP .sequence( {
62
62
BER .new.set_string(control, UniversalTags ::OctetString ),
63
63
BER .new.set_string(" " , UniversalTags ::OctetString ),
64
64
BER .new.set_boolean(false ),
65
- }
65
+ })
66
66
end
67
67
end
68
68
69
- # TODO:: convert to actual message
70
- {
69
+ # Control sequence needs to be encoded as an OctetString
70
+ # https://tools.ietf.org/html/rfc2891
71
+ controls = BER .new.set_string(" " , UniversalTags ::OctetString )
72
+ controls.payload = LDAP .sequence(sort_controls).to_slice
73
+
74
+ # convert to actual message
75
+ LDAP .sequence({
71
76
BER .new.set_string(SORT_REQUEST , UniversalTags ::OctetString ),
72
77
BER .new.set_boolean(false ),
73
- sort_controls ,
74
- }
78
+ controls ,
79
+ })
75
80
end
76
81
77
82
# base: https://tools.ietf.org/html/rfc4511#section-4.5.1.1
@@ -94,16 +99,15 @@ class LDAP::Request
94
99
size : Int = 0 ,
95
100
time : Int = 0 ,
96
101
paged_searches_supported : Bool = false ,
97
- sort_control : BER ? = nil
102
+ sort : String | SortControl | BER | Nil = nil
98
103
)
99
104
attributes = attributes.map { |a | BER .new.set_string(a.to_s, UniversalTags ::OctetString ) }
100
105
101
106
# support string based filters
102
107
filter = FilterParser .parse(filter) if filter.is_a?(String )
103
108
104
- # TODO:: sort controls
105
-
106
- build(LDAP .app_sequence({
109
+ # Build search request
110
+ search_request = LDAP .app_sequence({
107
111
BER .new.set_string(base, UniversalTags ::OctetString ),
108
112
BER .new.set_integer(scope.to_u8, UniversalTags ::Enumerated ),
109
113
BER .new.set_integer(dereference.to_u8, UniversalTags ::Enumerated ),
@@ -112,6 +116,20 @@ class LDAP::Request
112
116
BER .new.set_boolean(attributes_only),
113
117
filter.to_ber,
114
118
LDAP .sequence(attributes),
115
- }, Tag ::SearchRequest ))
119
+ }, Tag ::SearchRequest )
120
+
121
+ # Sort controls
122
+ if sort
123
+ sort_control = case sort
124
+ when String | SortControl
125
+ encode_sort_controls(sort)
126
+ when BER
127
+ sort
128
+ end
129
+
130
+ build(search_request, sort_control)
131
+ else
132
+ build(search_request)
133
+ end
116
134
end
117
135
end
0 commit comments