treequel 1.0.1 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +176 -14
- data/LICENSE +1 -1
- data/Rakefile +61 -45
- data/Rakefile.local +20 -0
- data/bin/treequel +502 -269
- data/examples/ldap-rack-auth.rb +2 -0
- data/lib/treequel.rb +221 -18
- data/lib/treequel/branch.rb +410 -201
- data/lib/treequel/branchcollection.rb +25 -13
- data/lib/treequel/branchset.rb +42 -40
- data/lib/treequel/constants.rb +233 -3
- data/lib/treequel/control.rb +95 -0
- data/lib/treequel/controls/contentsync.rb +138 -0
- data/lib/treequel/controls/pagedresults.rb +162 -0
- data/lib/treequel/controls/sortedresults.rb +216 -0
- data/lib/treequel/directory.rb +212 -65
- data/lib/treequel/exceptions.rb +11 -12
- data/lib/treequel/filter.rb +1 -12
- data/lib/treequel/mixins.rb +83 -47
- data/lib/treequel/monkeypatches.rb +29 -0
- data/lib/treequel/schema.rb +23 -19
- data/lib/treequel/schema/attributetype.rb +33 -3
- data/lib/treequel/schema/ldapsyntax.rb +0 -11
- data/lib/treequel/schema/matchingrule.rb +0 -11
- data/lib/treequel/schema/matchingruleuse.rb +0 -11
- data/lib/treequel/schema/objectclass.rb +36 -10
- data/lib/treequel/schema/table.rb +159 -0
- data/lib/treequel/sequel_integration.rb +7 -7
- data/lib/treequel/utils.rb +4 -66
- data/rake/documentation.rb +89 -0
- data/rake/helpers.rb +375 -307
- data/rake/hg.rb +16 -2
- data/rake/manual.rb +11 -6
- data/rake/packaging.rb +20 -35
- data/rake/publishing.rb +22 -62
- data/spec/lib/constants.rb +20 -0
- data/spec/lib/control_behavior.rb +44 -0
- data/spec/lib/matchers.rb +51 -0
- data/spec/treequel/branch_spec.rb +88 -29
- data/spec/treequel/branchcollection_spec.rb +24 -1
- data/spec/treequel/branchset_spec.rb +123 -51
- data/spec/treequel/control_spec.rb +48 -0
- data/spec/treequel/controls/contentsync_spec.rb +38 -0
- data/spec/treequel/controls/pagedresults_spec.rb +138 -0
- data/spec/treequel/controls/sortedresults_spec.rb +171 -0
- data/spec/treequel/directory_spec.rb +186 -16
- data/spec/treequel/mixins_spec.rb +42 -3
- data/spec/treequel/schema/attributetype_spec.rb +22 -20
- data/spec/treequel/schema/objectclass_spec.rb +67 -46
- data/spec/treequel/schema/table_spec.rb +134 -0
- data/spec/treequel_spec.rb +277 -15
- metadata +89 -108
- data/bin/treequel.orig +0 -963
- data/examples/ldap-monitor.rb +0 -143
- data/examples/ldap-monitor/public/css/master.css +0 -328
- data/examples/ldap-monitor/public/images/card_small.png +0 -0
- data/examples/ldap-monitor/public/images/chain_small.png +0 -0
- data/examples/ldap-monitor/public/images/globe_small.png +0 -0
- data/examples/ldap-monitor/public/images/globe_small_green.png +0 -0
- data/examples/ldap-monitor/public/images/plug.png +0 -0
- data/examples/ldap-monitor/public/images/shadows/large-30-down.png +0 -0
- data/examples/ldap-monitor/public/images/tick.png +0 -0
- data/examples/ldap-monitor/public/images/tick_circle.png +0 -0
- data/examples/ldap-monitor/public/images/treequel-favicon.png +0 -0
- data/examples/ldap-monitor/views/backends.erb +0 -41
- data/examples/ldap-monitor/views/connections.erb +0 -74
- data/examples/ldap-monitor/views/databases.erb +0 -39
- data/examples/ldap-monitor/views/dump_subsystem.erb +0 -14
- data/examples/ldap-monitor/views/index.erb +0 -14
- data/examples/ldap-monitor/views/layout.erb +0 -35
- data/examples/ldap-monitor/views/listeners.erb +0 -30
- data/rake/rdoc.rb +0 -30
- data/rake/win32.rb +0 -190
data/lib/treequel/directory.rb
CHANGED
@@ -13,18 +13,6 @@ require 'treequel/constants'
|
|
13
13
|
|
14
14
|
# The object in Treequel that represents a connection to a directory, the
|
15
15
|
# binding to that directory, and the base from which all DNs start.
|
16
|
-
#
|
17
|
-
# == Authors
|
18
|
-
#
|
19
|
-
# * Michael Granger <ged@FaerieMUD.org>
|
20
|
-
# * Mahlon E. Smith <mahlon@martini.nu>
|
21
|
-
#
|
22
|
-
# :include: LICENSE
|
23
|
-
#
|
24
|
-
#--
|
25
|
-
#
|
26
|
-
# Please see the file LICENSE in the base directory for licensing details.
|
27
|
-
#
|
28
16
|
class Treequel::Directory
|
29
17
|
include Treequel::Loggable,
|
30
18
|
Treequel::Constants,
|
@@ -99,33 +87,37 @@ class Treequel::Directory
|
|
99
87
|
|
100
88
|
### Create a new Treequel::Directory with the given +options+. Options is a hash with one
|
101
89
|
### or more of the following key-value pairs:
|
102
|
-
###
|
103
|
-
### [
|
104
|
-
###
|
105
|
-
###
|
106
|
-
###
|
107
|
-
###
|
108
|
-
###
|
109
|
-
###
|
110
|
-
###
|
111
|
-
###
|
112
|
-
###
|
113
|
-
### [:
|
114
|
-
###
|
90
|
+
###
|
91
|
+
### @param [Hash] options the connection options
|
92
|
+
### @option options [String] :host ('localhost')
|
93
|
+
### The LDAP host to connect to
|
94
|
+
### @option options [Fixnum] :port (LDAP::LDAP_PORT)
|
95
|
+
### The port number to connect to
|
96
|
+
### @option options [Symbol] :connect_type (:tls)
|
97
|
+
### The type of connection to establish; :tls, :ssl, or :plain.
|
98
|
+
### @option options [String] :base_dn (nil)
|
99
|
+
### The base DN of the directory; defaults to the first naming context of
|
100
|
+
### the directory's root DSE.
|
101
|
+
### @option options [String] :bind_dn (nil)
|
102
|
+
### The DN of the user to bind as; if unset, binds anonymously.
|
103
|
+
### @option options [String] :pass (nil)
|
104
|
+
### The password to use when binding.
|
115
105
|
def initialize( options={} )
|
116
|
-
options
|
106
|
+
options = DEFAULT_OPTIONS.merge( options )
|
117
107
|
|
118
|
-
@host
|
119
|
-
@port
|
120
|
-
@connect_type
|
108
|
+
@host = options[:host]
|
109
|
+
@port = options[:port]
|
110
|
+
@connect_type = options[:connect_type]
|
121
111
|
|
122
|
-
@conn
|
123
|
-
@
|
112
|
+
@conn = nil
|
113
|
+
@bound_user = nil
|
124
114
|
|
125
|
-
@base_dn
|
126
|
-
@syntax_mapping = DEFAULT_SYNTAX_MAPPING.dup
|
115
|
+
@base_dn = options[:base_dn] || self.get_default_base_dn
|
127
116
|
|
128
|
-
@base
|
117
|
+
@base = nil
|
118
|
+
|
119
|
+
@syntax_mapping = DEFAULT_SYNTAX_MAPPING.dup
|
120
|
+
@registered_controls = []
|
129
121
|
|
130
122
|
# Immediately bind if credentials are passed to the initializer.
|
131
123
|
if ( options[:bind_dn] && options[:pass] )
|
@@ -141,38 +133,57 @@ class Treequel::Directory
|
|
141
133
|
# Delegate some methods to the #base Branch.
|
142
134
|
def_method_delegators :base, *DELEGATED_BRANCH_METHODS
|
143
135
|
|
136
|
+
# Delegate some methods to the connection via the #conn method
|
137
|
+
def_method_delegators :conn, :controls, :referrals
|
138
|
+
|
139
|
+
|
144
140
|
# The host to connect to.
|
141
|
+
# @return [String]
|
145
142
|
attr_accessor :host
|
146
143
|
|
147
144
|
# The port to connect to.
|
145
|
+
# @return [Fixnum]
|
148
146
|
attr_accessor :port
|
149
147
|
|
150
148
|
# The type of connection to establish
|
149
|
+
# @return [Symbol]
|
151
150
|
attr_accessor :connect_type
|
152
151
|
|
153
152
|
# The base DN of the directory
|
153
|
+
# @return [String]
|
154
154
|
attr_accessor :base_dn
|
155
155
|
|
156
|
+
# The control modules that are registered with the directory
|
157
|
+
# @return [Array<Module>]
|
158
|
+
attr_reader :registered_controls
|
159
|
+
|
160
|
+
# The DN of the user the directory is bound as
|
161
|
+
# @return [String]
|
162
|
+
attr_reader :bound_user
|
163
|
+
|
156
164
|
|
157
165
|
### Fetch the Branch for the base node of the directory.
|
166
|
+
### @return [Treequel::Branch]
|
158
167
|
def base
|
159
168
|
return @base ||= Treequel::Branch.new( self, self.base_dn )
|
160
169
|
end
|
161
170
|
|
162
171
|
|
163
172
|
### Returns a string that describes the directory
|
173
|
+
### @return [String]
|
164
174
|
def to_s
|
165
175
|
return "%s:%d (%s, %s, %s)" % [
|
166
176
|
self.host,
|
167
177
|
self.port,
|
168
178
|
self.base_dn,
|
169
179
|
self.connect_type,
|
170
|
-
self.bound? ? @
|
180
|
+
self.bound? ? @bound_user : 'anonymous'
|
171
181
|
]
|
172
182
|
end
|
173
183
|
|
174
184
|
|
175
185
|
### Return a human-readable representation of the object suitable for debugging
|
186
|
+
### @return [String]
|
176
187
|
def inspect
|
177
188
|
return %{#<%s:0x%0x %s:%d (%s) base_dn=%p, bound as=%s, schema=%s>} % [
|
178
189
|
self.class.name,
|
@@ -181,7 +192,7 @@ class Treequel::Directory
|
|
181
192
|
self.port,
|
182
193
|
@conn ? "connected" : "not connected",
|
183
194
|
self.base_dn,
|
184
|
-
@
|
195
|
+
@bound_user ? @bound_user.dump : "anonymous",
|
185
196
|
@schema ? @schema.inspect : "(schema not loaded)",
|
186
197
|
]
|
187
198
|
end
|
@@ -189,12 +200,14 @@ class Treequel::Directory
|
|
189
200
|
|
190
201
|
### Return the LDAP::Conn object associated with this directory, creating it with the
|
191
202
|
### current options if necessary.
|
203
|
+
### @return [LDAP::Conn, LDAP::SSLConn]
|
192
204
|
def conn
|
193
205
|
return @conn ||= self.connect
|
194
206
|
end
|
195
207
|
|
196
208
|
|
197
209
|
### Return the URI object that corresponds to the directory.
|
210
|
+
### @return [URI::LDAP]
|
198
211
|
def uri
|
199
212
|
uri_parts = {
|
200
213
|
:scheme => self.connect_type == :ssl ? 'ldaps' : 'ldap',
|
@@ -208,30 +221,41 @@ class Treequel::Directory
|
|
208
221
|
|
209
222
|
|
210
223
|
### Bind as the specified +user_dn+ and +password+.
|
224
|
+
###
|
225
|
+
### @param [String, #dn] user_dn the DN of the user to bind as
|
226
|
+
### @param [String] password the password to bind with
|
227
|
+
###
|
228
|
+
### @return [void]
|
211
229
|
def bind( user_dn, password )
|
212
230
|
user_dn = user_dn.dn if user_dn.respond_to?( :dn )
|
213
231
|
|
214
232
|
self.log.info "Binding with connection %p as: %s" % [ self.conn, user_dn ]
|
215
233
|
self.conn.bind( user_dn.to_s, password )
|
216
|
-
@
|
234
|
+
@bound_user = user_dn.to_s
|
217
235
|
end
|
236
|
+
alias_method :bind_as, :bind
|
218
237
|
|
219
238
|
|
220
239
|
### Execute the provided +block+ after binding as +user_dn+ with the given +password+. After
|
221
240
|
### the block returns, the original binding (if any) will be restored.
|
241
|
+
###
|
242
|
+
### @param (see #bind)
|
243
|
+
###
|
244
|
+
### @return [void]
|
222
245
|
def bound_as( user_dn, password )
|
223
246
|
raise LocalJumpError, "no block given" unless block_given?
|
224
|
-
previous_bind_dn = @
|
247
|
+
previous_bind_dn = @bound_user
|
225
248
|
self.with_duplicate_conn do
|
226
249
|
self.bind( user_dn, password )
|
227
250
|
yield
|
228
251
|
end
|
229
252
|
ensure
|
230
|
-
@
|
253
|
+
@bound_user = previous_bind_dn
|
231
254
|
end
|
232
255
|
|
233
256
|
|
234
|
-
### Returns +true+ if the directory's connection
|
257
|
+
### Returns +true+ if the directory's connection is already bound to the directory.
|
258
|
+
### @return [Boolean]
|
235
259
|
def bound?
|
236
260
|
return self.conn.bound?
|
237
261
|
end
|
@@ -239,6 +263,7 @@ class Treequel::Directory
|
|
239
263
|
|
240
264
|
|
241
265
|
### Ensure that the the receiver's connection is unbound.
|
266
|
+
### @return [void]
|
242
267
|
def unbind
|
243
268
|
if @conn.bound?
|
244
269
|
old_conn = @conn
|
@@ -249,6 +274,7 @@ class Treequel::Directory
|
|
249
274
|
|
250
275
|
|
251
276
|
### Return the RDN string to the given +dn+ from the base of the directory.
|
277
|
+
### @param [#to_s] dn the DN of the entry
|
252
278
|
def rdn_to( dn )
|
253
279
|
base_re = Regexp.new( ',' + Regexp.quote(self.base_dn) + '$' )
|
254
280
|
return dn.to_s.sub( base_re, '' )
|
@@ -257,6 +283,8 @@ class Treequel::Directory
|
|
257
283
|
|
258
284
|
### Given a Treequel::Branch object, find its corresponding LDAP::Entry and return
|
259
285
|
### it.
|
286
|
+
###
|
287
|
+
### @param [Treequel::Branch] branch the branch to look up
|
260
288
|
def get_entry( branch )
|
261
289
|
self.log.debug "Looking up entry for %p" % [ branch.dn ]
|
262
290
|
return self.conn.search_ext2( branch.dn, SCOPE[:base], '(objectClass=*)' ).first
|
@@ -269,6 +297,8 @@ class Treequel::Directory
|
|
269
297
|
### Given a Treequel::Branch object, find its corresponding LDAP::Entry and return
|
270
298
|
### it with its operational attributes (http://tools.ietf.org/html/rfc4512#section-3.4)
|
271
299
|
### included.
|
300
|
+
###
|
301
|
+
### @param [Treequel::Branch] branch the branch to look up
|
272
302
|
def get_extended_entry( branch )
|
273
303
|
self.log.debug "Looking up entry (with operational attributes) for %p" % [ branch.dn ]
|
274
304
|
return self.conn.search_ext2( branch.dn, SCOPE[:base], '(objectClass=*)', %w[* +] ).first
|
@@ -289,47 +319,96 @@ class Treequel::Directory
|
|
289
319
|
end
|
290
320
|
|
291
321
|
|
292
|
-
### Perform a +scope+ search at +base+ using the specified +filter+.
|
293
|
-
###
|
294
|
-
### of the
|
295
|
-
|
322
|
+
### Perform a +scope+ search at +base+ using the specified +filter+.
|
323
|
+
###
|
324
|
+
### @param [String, #dn] base The base DN of the search.
|
325
|
+
### @param [Symbol] scope The scope to use in the search; can be one of
|
326
|
+
### +:onelevel+, +:base+, or +:subtree+.
|
327
|
+
### @param [#to_s] filter The search filter (RFC4515), either as a String
|
328
|
+
### or something that stringifies to an filter string.
|
329
|
+
### @param [Hash] options Search options.
|
330
|
+
###
|
331
|
+
### @option options [Class] :results_class (Treequel::Branch)
|
332
|
+
### The Class to use when wrapping results; if not specified, defaults to the class
|
333
|
+
### of +base+ if it responds to #new_from_entry, or Treequel::Branch
|
334
|
+
### if it does not.
|
335
|
+
### @option options [Array<String, Symbol>] :selectattrs (['*'])
|
336
|
+
### The attributes to return from the search; defaults to '*', which means to
|
337
|
+
### return all non-operational attributes. Specifying '+' will cause the search
|
338
|
+
### to include operational parameters as well.
|
339
|
+
### @option options [Boolean] :attrsonly (false)
|
340
|
+
### If +true, the LDAP::Entry objects returned from the search won't have attribute values.
|
341
|
+
### This has no real effect on Treequel::Branches, but is provided in case other
|
342
|
+
### +results_class+ classes need it.
|
343
|
+
### @option options [Array<LDAP::Control>] :server_controls (nil)
|
344
|
+
### Any server controls that should be sent with the search.
|
345
|
+
### @option options [Array<LDAP::Control>] :client_controls (nil)
|
346
|
+
### Any client controls that should be applied to the search.
|
347
|
+
### @option options [Fixnum] :timeout_s (0)
|
348
|
+
### The number of seconds (in addition to :timeout_us) after which the search request should
|
349
|
+
### be aborted.
|
350
|
+
### @option options [Fixnum] :timeout_us (0)
|
351
|
+
### The number of microseconds (in addition to :timeout_s) after which the search request
|
352
|
+
### should be aborted.
|
353
|
+
### @option options [Fixnum] :limit
|
354
|
+
### The maximum number of results to return from the server.
|
355
|
+
### @option options [Array<String>] :sort_attribute
|
356
|
+
### An Array of String attribute names to sort by.
|
357
|
+
### @option options [Proc] :sort_func
|
358
|
+
### A function that will provide sorting.
|
359
|
+
###
|
360
|
+
### @return [Array] the array of results, each of which is wrapped in the
|
361
|
+
### options[:results_class]. If a block is given, it acts like a filter:
|
362
|
+
### the return vaule from the block is returned instead.
|
363
|
+
###
|
364
|
+
### @yield [branch] an optional block, which will receive the results one at a time
|
365
|
+
### @yieldparam [Treequel::Branch] branch the resulting entry, wrapped in
|
366
|
+
### the options[:results_class].
|
367
|
+
def search( base, scope=:subtree, filter='(objectClass=*)', options={} )
|
296
368
|
collectclass = nil
|
297
369
|
|
298
370
|
# If the base argument is an object whose class knows how to create instances of itself
|
299
371
|
# from an LDAP::Entry, use it instead of Treequel::Branch to wrap results
|
300
|
-
if
|
301
|
-
collectclass =
|
372
|
+
if options.key?( :results_class )
|
373
|
+
collectclass = options.delete( :results_class )
|
302
374
|
else
|
303
375
|
collectclass = base.class.respond_to?( :new_from_entry ) ? base.class : Treequel::Branch
|
304
376
|
end
|
305
377
|
|
306
378
|
# Format the arguments in the way #search_ext2 expects them
|
307
|
-
|
308
|
-
self.normalize_search_parameters( base, scope, filter,
|
379
|
+
base_dn, scope, filter, searchopts =
|
380
|
+
self.normalize_search_parameters( base, scope, filter, options )
|
309
381
|
|
310
|
-
# Unwrap the search
|
382
|
+
# Unwrap the search options from the hash in the correct order
|
311
383
|
self.log.debug {
|
312
384
|
attrlist = SEARCH_PARAMETER_ORDER.inject([]) do |list, param|
|
313
|
-
list << "%s: %p" % [ param,
|
385
|
+
list << "%s: %p" % [ param, searchopts[param] ]
|
314
386
|
end
|
315
387
|
"searching with base: %p, scope: %p, filter: %p, %s" %
|
316
|
-
[
|
388
|
+
[ base_dn, scope, filter, attrlist.join(', ') ]
|
317
389
|
}
|
318
|
-
parameters =
|
390
|
+
parameters = searchopts.values_at( *SEARCH_PARAMETER_ORDER )
|
319
391
|
|
320
392
|
# Wrap each result in the class derived from the 'base' argument
|
321
393
|
self.log.debug "Searching via search_ext2 with arguments: %p" % [[
|
322
|
-
|
394
|
+
base_dn, scope, filter, *parameters
|
323
395
|
]]
|
324
|
-
|
325
|
-
|
326
|
-
|
396
|
+
|
397
|
+
results = []
|
398
|
+
|
399
|
+
self.conn.search_ext2( base_dn, scope, filter, *parameters ).each do |entry|
|
400
|
+
branch = collectclass.new_from_entry( entry, self )
|
401
|
+
branch.include_operational_attrs = base.include_operational_attrs? if
|
402
|
+
base.respond_to?( :include_operational_attrs? )
|
403
|
+
|
404
|
+
if block_given?
|
405
|
+
results << yield( branch )
|
406
|
+
else
|
407
|
+
results << branch
|
327
408
|
end
|
328
|
-
else
|
329
|
-
return self.conn.search_ext2( base, scope, filter, *parameters ).
|
330
|
-
collect {|entry| collectclass.new_from_entry(entry, self) }
|
331
409
|
end
|
332
410
|
|
411
|
+
return results
|
333
412
|
rescue RuntimeError => err
|
334
413
|
conn = self.conn
|
335
414
|
|
@@ -347,9 +426,14 @@ class Treequel::Directory
|
|
347
426
|
### Modify the entry specified by the given +dn+ with the specified +mods+, which can be
|
348
427
|
### either an Array of LDAP::Mod objects or a Hash of attribute/value pairs.
|
349
428
|
def modify( branch, mods )
|
350
|
-
|
351
|
-
|
352
|
-
|
429
|
+
if mods.first.respond_to?( :mod_op )
|
430
|
+
self.log.debug "Modifying %s with LDAP mod objects: %p" % [ branch.dn, mods ]
|
431
|
+
self.conn.modify( branch.dn, mods )
|
432
|
+
else
|
433
|
+
normattrs = self.normalize_attributes( mods )
|
434
|
+
self.log.debug "Modifying %s with: %p" % [ branch.dn, normattrs ]
|
435
|
+
self.conn.modify( branch.dn, normattrs )
|
436
|
+
end
|
353
437
|
end
|
354
438
|
|
355
439
|
|
@@ -368,7 +452,7 @@ class Treequel::Directory
|
|
368
452
|
# Merge RDN attributes with existing ones, combining any that exist in both
|
369
453
|
self.log.debug "Smushing rdn attributes %p into %p" % [ branch.rdn_attributes, newdn ]
|
370
454
|
newattrs.merge!( branch.rdn_attributes ) do |key, *values|
|
371
|
-
values.flatten
|
455
|
+
values.flatten.uniq
|
372
456
|
end
|
373
457
|
|
374
458
|
normattrs = self.normalize_attributes( newattrs )
|
@@ -421,6 +505,25 @@ class Treequel::Directory
|
|
421
505
|
end
|
422
506
|
|
423
507
|
|
508
|
+
### Register the specified +modules+
|
509
|
+
def register_controls( *modules )
|
510
|
+
dse = self.conn.root_dse.first
|
511
|
+
supported_controls = dse['supportedControl']
|
512
|
+
|
513
|
+
modules.each do |mod|
|
514
|
+
oid = mod.const_get( :OID ) if mod.const_defined?( :OID )
|
515
|
+
raise NotImplementedError, "%s doesn't define an OID" % [ mod.name ] if oid.nil?
|
516
|
+
|
517
|
+
if supported_controls.include?( oid )
|
518
|
+
@registered_controls << mod
|
519
|
+
else
|
520
|
+
raise Treequel::UnsupportedControl,
|
521
|
+
"%s is not supported by %s" % [ mod.name, self.uri ]
|
522
|
+
end
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
|
424
527
|
### Map the specified +value+ to its Ruby datatype if one is registered for the given
|
425
528
|
### syntax +oid+. If there is no conversion registered, just return the +value+ as-is.
|
426
529
|
def convert_syntax_value( oid, value )
|
@@ -435,6 +538,50 @@ class Treequel::Directory
|
|
435
538
|
end
|
436
539
|
|
437
540
|
|
541
|
+
### Return an Array of Symbols for the controls supported by the Directory, as listed
|
542
|
+
### in the directory's root DSE. Any controls which aren't known (i.e., don't have an
|
543
|
+
### entry in Treequel::Constants::CONTROL_NAMES), the numeric OID will be returned as-is.
|
544
|
+
def supported_controls
|
545
|
+
return self.supported_control_oids.collect {|oid| CONTROL_NAMES[oid] || oid }
|
546
|
+
end
|
547
|
+
|
548
|
+
|
549
|
+
### Return an Array of OID strings representing the controls supported by the Directory,
|
550
|
+
### as listed in the directory's root DSE.
|
551
|
+
def supported_control_oids
|
552
|
+
return self.conn.root_dse.first['supportedControl']
|
553
|
+
end
|
554
|
+
|
555
|
+
|
556
|
+
### Return an Array of Symbols for the extensions supported by the Directory, as listed
|
557
|
+
### in the directory's root DSE. Any extensions which aren't known (i.e., don't have an
|
558
|
+
### entry in Treequel::Constants::EXTENSION_NAMES), the numeric OID will be returned as-is.
|
559
|
+
def supported_extensions
|
560
|
+
return self.supported_extension_oids.collect {|oid| EXTENSION_NAMES[oid] || oid }
|
561
|
+
end
|
562
|
+
|
563
|
+
|
564
|
+
### Return an Array of OID strings representing the extensions supported by the Directory,
|
565
|
+
### as listed in the directory's root DSE.
|
566
|
+
def supported_extension_oids
|
567
|
+
return self.conn.root_dse.first['supportedExtension']
|
568
|
+
end
|
569
|
+
|
570
|
+
|
571
|
+
### Return an Array of Symbols for the features supported by the Directory, as listed
|
572
|
+
### in the directory's root DSE. Any features which aren't known (i.e., don't have an
|
573
|
+
### entry in Treequel::Constants::FEATURE_NAMES), the numeric OID will be returned as-is.
|
574
|
+
def supported_features
|
575
|
+
return self.supported_feature_oids.collect {|oid| FEATURE_NAMES[oid] || oid }
|
576
|
+
end
|
577
|
+
|
578
|
+
|
579
|
+
### Return an Array of OID strings representing the features supported by the Directory,
|
580
|
+
### as listed in the directory's root DSE.
|
581
|
+
def supported_feature_oids
|
582
|
+
return self.conn.root_dse.first['supportedFeatures']
|
583
|
+
end
|
584
|
+
|
438
585
|
|
439
586
|
#########
|
440
587
|
protected
|
@@ -457,10 +604,10 @@ class Treequel::Directory
|
|
457
604
|
conn = LDAP::SSLConn.new( @host, @port, true )
|
458
605
|
when :ssl
|
459
606
|
self.log.debug "Connecting using SSL to %s:%d" % [ @host, @port ]
|
460
|
-
conn = LDAP::SSLConn.new( host, port )
|
607
|
+
conn = LDAP::SSLConn.new( @host, @port )
|
461
608
|
else
|
462
609
|
self.log.debug "Connecting using an unencrypted connection to %s:%d" % [ @host, @port ]
|
463
|
-
conn = LDAP::Conn.new( host, port )
|
610
|
+
conn = LDAP::Conn.new( @host, @port )
|
464
611
|
end
|
465
612
|
|
466
613
|
conn.set_option( LDAP::LDAP_OPT_PROTOCOL_VERSION, 3 )
|