treequel 1.0.1 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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/exceptions.rb
CHANGED
@@ -3,18 +3,6 @@
|
|
3
3
|
require 'treequel'
|
4
4
|
|
5
5
|
|
6
|
-
# A collection of exceptions for Treequel.
|
7
|
-
#
|
8
|
-
# == Authors
|
9
|
-
#
|
10
|
-
# * Michael Granger <ged@FaerieMUD.org>
|
11
|
-
#
|
12
|
-
# :include: LICENSE
|
13
|
-
#
|
14
|
-
#--
|
15
|
-
#
|
16
|
-
# Please see the file LICENSE in the base directory for licensing details.
|
17
|
-
#
|
18
6
|
module Treequel
|
19
7
|
|
20
8
|
### The base Treequel exception type
|
@@ -27,6 +15,17 @@ module Treequel
|
|
27
15
|
### arguments given to Treequel::Filter.new
|
28
16
|
class ExpressionError < Treequel::Error; end
|
29
17
|
|
18
|
+
### Generic exception type for Controls.
|
19
|
+
class ControlError < Treequel::Error; end
|
20
|
+
|
21
|
+
### Exception type for a requested Control type that is nonexistent or
|
22
|
+
### unsupported on the current server.
|
23
|
+
class UnsupportedControl < Treequel::ControlError; end
|
24
|
+
|
25
|
+
### Exception raised from Treequel::Model due to misconfiguration or
|
26
|
+
### other problem.
|
27
|
+
class ModelError < Treequel::Error; end
|
28
|
+
|
30
29
|
end # module Treequel
|
31
30
|
|
32
31
|
|
data/lib/treequel/filter.rb
CHANGED
@@ -36,18 +36,6 @@ require 'treequel/sequel_integration'
|
|
36
36
|
# matchingrule = MatchingRuleId from Section 4.1.9 of [1]
|
37
37
|
# value = AttributeValue from Section 4.1.6 of [1]
|
38
38
|
#
|
39
|
-
#
|
40
|
-
# == Authors
|
41
|
-
#
|
42
|
-
# * Michael Granger <ged@FaerieMUD.org>
|
43
|
-
# * Mahlon E. Smith <mahlon@martini.nu>
|
44
|
-
#
|
45
|
-
# :include: LICENSE
|
46
|
-
#
|
47
|
-
#--
|
48
|
-
#
|
49
|
-
# Please see the file LICENSE in the base directory for licensing details.
|
50
|
-
#
|
51
39
|
class Treequel::Filter
|
52
40
|
include Treequel::Loggable,
|
53
41
|
Treequel::Constants::Patterns
|
@@ -78,6 +66,7 @@ class Treequel::Filter
|
|
78
66
|
|
79
67
|
|
80
68
|
### An abstract class for filter components.
|
69
|
+
### @abstract Subclass and override {#to_s} to implement a custom Component class.
|
81
70
|
class Component
|
82
71
|
include Treequel::Loggable
|
83
72
|
|
data/lib/treequel/mixins.rb
CHANGED
@@ -6,17 +6,64 @@ require 'etc'
|
|
6
6
|
require 'logger'
|
7
7
|
|
8
8
|
require 'treequel'
|
9
|
+
require 'treequel/constants'
|
9
10
|
|
10
11
|
|
11
|
-
|
12
|
-
# A collection of mixins shared between Treequel classes. Stolen mostly from ThingFish.
|
13
|
-
#
|
14
|
-
module Treequel # :nodoc:
|
12
|
+
module Treequel
|
15
13
|
|
16
14
|
# A collection of various delegation code-generators that can be used to define
|
17
15
|
# delegation through other methods, to instance variables, etc.
|
18
16
|
module Delegation
|
19
17
|
|
18
|
+
###############
|
19
|
+
module_function
|
20
|
+
###############
|
21
|
+
|
22
|
+
### Define the given +delegated_methods+ as delegators to the like-named method
|
23
|
+
### of the return value of the +delegate_method+.
|
24
|
+
###
|
25
|
+
### @example
|
26
|
+
### class MyClass
|
27
|
+
### extend Treequel::Delegation
|
28
|
+
###
|
29
|
+
### # Delegate the #bound?, #err, and #result2error methods to the connection
|
30
|
+
### # object returned by the #connection method. This allows the connection
|
31
|
+
### # to still be loaded on demand/overridden/etc.
|
32
|
+
### def_method_delegators :connection, :bound?, :err, :result2error
|
33
|
+
###
|
34
|
+
### def connection
|
35
|
+
### @connection ||= self.connect
|
36
|
+
### end
|
37
|
+
### end
|
38
|
+
###
|
39
|
+
def def_method_delegators( delegate_method, *delegated_methods )
|
40
|
+
delegated_methods.each do |name|
|
41
|
+
body = make_method_delegator( delegate_method, name )
|
42
|
+
define_method( name, &body )
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
### Define the given +delegated_methods+ as delegators to the like-named method
|
48
|
+
### of the specified +ivar+. This is pretty much identical with how 'Forwardable'
|
49
|
+
### from the stdlib does delegation, but it's reimplemented here for consistency.
|
50
|
+
###
|
51
|
+
### class MyClass
|
52
|
+
### extend Treequel::Delegation
|
53
|
+
###
|
54
|
+
### # Delegate the #each method to the @collection ivar
|
55
|
+
### def_ivar_delegators :@collection, :each
|
56
|
+
###
|
57
|
+
### end
|
58
|
+
###
|
59
|
+
def def_ivar_delegators( ivar, *delegated_methods )
|
60
|
+
delegated_methods.each do |name|
|
61
|
+
body = make_ivar_delegator( ivar, name )
|
62
|
+
define_method( name, &body )
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
20
67
|
#######
|
21
68
|
private
|
22
69
|
#######
|
@@ -64,59 +111,46 @@ module Treequel # :nodoc:
|
|
64
111
|
return eval( code, nil, file, line.to_i )
|
65
112
|
end
|
66
113
|
|
114
|
+
end # module Delegation
|
115
|
+
|
116
|
+
|
117
|
+
# A collection of key-normalization functions for various artifacts in LDAP like
|
118
|
+
# attribute names, objectclass OIDs, etc.
|
119
|
+
module Normalization
|
67
120
|
|
68
121
|
###############
|
69
122
|
module_function
|
70
123
|
###############
|
71
124
|
|
72
|
-
###
|
73
|
-
###
|
74
|
-
###
|
75
|
-
###
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
###
|
83
|
-
### def connection
|
84
|
-
### @connection ||= self.connect
|
85
|
-
### end
|
86
|
-
### end
|
87
|
-
###
|
88
|
-
def def_method_delegators( delegate_method, *delegated_methods )
|
89
|
-
delegated_methods.each do |name|
|
90
|
-
body = make_method_delegator( delegate_method, name )
|
91
|
-
define_method( name, &body )
|
92
|
-
end
|
125
|
+
### Normalize the given key
|
126
|
+
### @param [String] key the key to normalize
|
127
|
+
### @return a downcased Symbol stripped of any invalid characters, and
|
128
|
+
### with '-' characters converted to '_'.
|
129
|
+
def normalize_key( key )
|
130
|
+
return key if key.to_s =~ Treequel::Constants::Patterns::NUMERICOID
|
131
|
+
return key.to_s.downcase.
|
132
|
+
gsub( /[^[:alnum:]\-_]/, '' ).
|
133
|
+
gsub( '-', '_' ).
|
134
|
+
to_sym
|
93
135
|
end
|
94
136
|
|
95
|
-
|
96
|
-
###
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
###
|
103
|
-
### # Delegate the #each method to the @collection ivar
|
104
|
-
### def_ivar_delegators :@collection, :each
|
105
|
-
###
|
106
|
-
### end
|
107
|
-
###
|
108
|
-
def def_ivar_delegators( ivar, *delegated_methods )
|
109
|
-
delegated_methods.each do |name|
|
110
|
-
body = make_ivar_delegator( ivar, name )
|
111
|
-
define_method( name, &body )
|
137
|
+
### Return a copy of +hash+ with all of its keys normalized by #normalize_key.
|
138
|
+
### @param [Hash] hash the Hash to normalize
|
139
|
+
def normalize_hash( hash )
|
140
|
+
hash = hash.dup
|
141
|
+
hash.keys.each do |key|
|
142
|
+
nkey = normalize_key( key )
|
143
|
+
hash[ nkey ] = hash.delete( key ) if key != nkey
|
112
144
|
end
|
145
|
+
|
146
|
+
return hash
|
113
147
|
end
|
114
148
|
|
115
149
|
|
116
|
-
end #
|
150
|
+
end # Normalization
|
117
151
|
|
118
152
|
|
119
|
-
|
153
|
+
### Add logging to a Treequel class. Including classes get #log and #log_debug methods.
|
120
154
|
module Loggable
|
121
155
|
|
122
156
|
LEVEL = {
|
@@ -129,7 +163,8 @@ module Treequel # :nodoc:
|
|
129
163
|
|
130
164
|
### A logging proxy class that wraps calls to the logger into calls that include
|
131
165
|
### the name of the calling class.
|
132
|
-
|
166
|
+
### @private
|
167
|
+
class ClassNameProxy
|
133
168
|
|
134
169
|
### Create a new proxy for the given +klass+.
|
135
170
|
def initialize( klass, force_debug=false )
|
@@ -292,7 +327,8 @@ module Treequel # :nodoc:
|
|
292
327
|
def predicate_attr( *symbols )
|
293
328
|
symbols.each do |attrname|
|
294
329
|
define_method( "#{attrname}?" ) do
|
295
|
-
|
330
|
+
instance_variable_defined?( "@#{attrname}" ) &&
|
331
|
+
instance_variable_get( "@#{attrname}" ) ? true : false
|
296
332
|
end
|
297
333
|
define_method( "#{attrname}=" ) do |newval|
|
298
334
|
instance_variable_set( "@#{attrname}", newval ? true : false )
|
@@ -341,7 +377,7 @@ module Treequel # :nodoc:
|
|
341
377
|
return '' unless /(?:vt10[03]|xterm(?:-color)?|linux|screen)/i =~ ENV['TERM']
|
342
378
|
attributes = ANSI_ATTRIBUTES.values_at( *attributes ).compact.join(';')
|
343
379
|
|
344
|
-
if attributes.empty?
|
380
|
+
if attributes.empty?
|
345
381
|
return ''
|
346
382
|
else
|
347
383
|
return "\e[%sm" % attributes
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'ldap'
|
4
|
+
require 'ldap/control'
|
5
|
+
|
6
|
+
require 'treequel'
|
7
|
+
|
8
|
+
### Extensions to LDAP::Control to make them grok ==.
|
9
|
+
module Treequel::LDAPControlExtensions
|
10
|
+
|
11
|
+
### Returns +true+ if the +other+ LDAP::Control is equivalent to the receiver.
|
12
|
+
def ==( other )
|
13
|
+
return ( other.class == self.class ) &&
|
14
|
+
other.oid == self.oid &&
|
15
|
+
other.value == self.value &&
|
16
|
+
other.iscritical == self.iscritical
|
17
|
+
end
|
18
|
+
|
19
|
+
end # module Treequel::LDAPControlExtensions
|
20
|
+
|
21
|
+
|
22
|
+
# Include Treequel-specific extensions as a mixin.
|
23
|
+
# @private
|
24
|
+
class LDAP::Control
|
25
|
+
include Treequel::LDAPControlExtensions
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
|
data/lib/treequel/schema.rb
CHANGED
@@ -25,6 +25,7 @@ class Treequel::Schema
|
|
25
25
|
include Treequel::Loggable,
|
26
26
|
Treequel::Constants::Patterns
|
27
27
|
|
28
|
+
require 'treequel/schema/table'
|
28
29
|
require 'treequel/schema/objectclass'
|
29
30
|
require 'treequel/schema/attributetype'
|
30
31
|
require 'treequel/schema/matchingrule'
|
@@ -168,14 +169,14 @@ class Treequel::Schema
|
|
168
169
|
### return them as a Hash keyed both by numeric OID and by each of its NAME attributes (if it
|
169
170
|
### has any).
|
170
171
|
def parse_objectclasses( descriptions )
|
171
|
-
return descriptions.inject(
|
172
|
+
return descriptions.inject( Treequel::Schema::Table.new ) do |table, desc|
|
172
173
|
oc = Treequel::Schema::ObjectClass.parse( self, desc ) or
|
173
174
|
raise Treequel::Error, "couldn't create an objectClass from %p" % [ desc ]
|
174
175
|
|
175
|
-
|
176
|
-
oc.names.inject(
|
176
|
+
table[ oc.oid ] = oc
|
177
|
+
oc.names.inject( table ) {|h, name| h[name] = oc; h }
|
177
178
|
|
178
|
-
|
179
|
+
table
|
179
180
|
end
|
180
181
|
end
|
181
182
|
|
@@ -184,14 +185,14 @@ class Treequel::Schema
|
|
184
185
|
### and return them as a Hash keyed both by numeric OID and by each of its NAME attributes
|
185
186
|
### (if it has any).
|
186
187
|
def parse_attribute_types( descriptions )
|
187
|
-
return descriptions.inject(
|
188
|
+
return descriptions.inject( Treequel::Schema::Table.new ) do |table, desc|
|
188
189
|
attrtype = Treequel::Schema::AttributeType.parse( self, desc ) or
|
189
190
|
raise Treequel::Error, "couldn't create an attributeType from %p" % [ desc ]
|
190
191
|
|
191
|
-
|
192
|
-
attrtype.names.inject(
|
192
|
+
table[ attrtype.oid ] = attrtype
|
193
|
+
attrtype.names.inject( table ) {|h, name| h[name] = attrtype; h }
|
193
194
|
|
194
|
-
|
195
|
+
table
|
195
196
|
end
|
196
197
|
end
|
197
198
|
|
@@ -199,12 +200,13 @@ class Treequel::Schema
|
|
199
200
|
### Parse the given LDAP syntax +descriptions+ into Treequel::Schema::LDAPSyntax objects and
|
200
201
|
### return them as a Hash keyed by numeric OID.
|
201
202
|
def parse_ldap_syntaxes( descriptions )
|
202
|
-
|
203
|
+
descriptions ||= []
|
204
|
+
return descriptions.inject( Treequel::Schema::Table.new ) do |table, desc|
|
203
205
|
syntax = Treequel::Schema::LDAPSyntax.parse( self, desc ) or
|
204
206
|
raise Treequel::Error, "couldn't create an LDAPSyntax from %p" % [ desc ]
|
205
207
|
|
206
|
-
|
207
|
-
|
208
|
+
table[ syntax.oid ] = syntax
|
209
|
+
table
|
208
210
|
end
|
209
211
|
end
|
210
212
|
|
@@ -213,14 +215,15 @@ class Treequel::Schema
|
|
213
215
|
### and return them as a Hash keyed both by numeric OID and by each of its NAME attributes
|
214
216
|
### (if it has any).
|
215
217
|
def parse_matching_rules( descriptions )
|
216
|
-
|
218
|
+
descriptions ||= []
|
219
|
+
return descriptions.inject( Treequel::Schema::Table.new ) do |table, desc|
|
217
220
|
rule = Treequel::Schema::MatchingRule.parse( self, desc ) or
|
218
221
|
raise Treequel::Error, "couldn't create an matchingRule from %p" % [ desc ]
|
219
222
|
|
220
|
-
|
221
|
-
rule.names.inject(
|
223
|
+
table[ rule.oid ] = rule
|
224
|
+
rule.names.inject( table ) {|h, name| h[name] = rule; h }
|
222
225
|
|
223
|
-
|
226
|
+
table
|
224
227
|
end
|
225
228
|
end
|
226
229
|
|
@@ -229,14 +232,15 @@ class Treequel::Schema
|
|
229
232
|
### and return them as a Hash keyed both by numeric OID and by each of its NAME attributes
|
230
233
|
### (if it has any).
|
231
234
|
def parse_matching_rule_uses( descriptions )
|
232
|
-
|
235
|
+
descriptions ||= []
|
236
|
+
return descriptions.inject( Treequel::Schema::Table.new ) do |table, desc|
|
233
237
|
ruleuse = Treequel::Schema::MatchingRuleUse.parse( self, desc ) or
|
234
238
|
raise Treequel::Error, "couldn't create an matchingRuleUse from %p" % [ desc ]
|
235
239
|
|
236
|
-
|
237
|
-
ruleuse.names.inject(
|
240
|
+
table[ ruleuse.oid ] = ruleuse
|
241
|
+
ruleuse.names.inject( table ) {|h, name| h[name] = ruleuse; h }
|
238
242
|
|
239
|
-
|
243
|
+
table
|
240
244
|
end
|
241
245
|
end
|
242
246
|
|
@@ -23,6 +23,7 @@ require 'treequel/exceptions'
|
|
23
23
|
#
|
24
24
|
class Treequel::Schema::AttributeType
|
25
25
|
include Treequel::Loggable,
|
26
|
+
Treequel::Normalization,
|
26
27
|
Treequel::Constants::Patterns
|
27
28
|
|
28
29
|
extend Treequel::AttributeDeclarations
|
@@ -157,6 +158,20 @@ class Treequel::Schema::AttributeType
|
|
157
158
|
end
|
158
159
|
|
159
160
|
|
161
|
+
### Return the attributeType's names after normalizing them.
|
162
|
+
def normalized_names
|
163
|
+
return self.names.collect {|name| normalize_key(name) }
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
### Returns +true+ if the specified +name+ is one of the attribute's names
|
168
|
+
### after normalization of both.
|
169
|
+
def valid_name?( name )
|
170
|
+
normname = normalize_key( name )
|
171
|
+
return self.normalized_names.include?( normname )
|
172
|
+
end
|
173
|
+
|
174
|
+
|
160
175
|
### Return the Treequel::Schema::AttributeType instance that corresponds to
|
161
176
|
### the receiver's superior type. If the attributeType doesn't have a SUP
|
162
177
|
### attribute, this method returns +nil+.
|
@@ -236,14 +251,29 @@ class Treequel::Schema::AttributeType
|
|
236
251
|
protected
|
237
252
|
#########
|
238
253
|
|
254
|
+
OID_SPLIT_PATTERN = /
|
255
|
+
^
|
256
|
+
#{SQUOTE}?
|
257
|
+
(#{OID}) # OID = $1
|
258
|
+
#{SQUOTE}?
|
259
|
+
(?:
|
260
|
+
#{LCURLY}
|
261
|
+
(#{LEN}) # Length = $2
|
262
|
+
#{RCURLY}
|
263
|
+
)?$
|
264
|
+
/x
|
265
|
+
|
239
266
|
### Split a numeric OID with an optional length qualifier into a numeric OID and length. If
|
240
267
|
### no length qualifier is present, it will be nil.
|
268
|
+
### NOTE: Modified to support ActiveDirectory schemas, which have both quoted numeric OIDs
|
269
|
+
### and descriptors as syntax OIDs.
|
241
270
|
def split_syntax_oid( noidlen )
|
242
|
-
unless noidlen =~
|
243
|
-
raise Treequel::ParseError, "invalid
|
271
|
+
unless noidlen =~ OID_SPLIT_PATTERN
|
272
|
+
raise Treequel::ParseError, "invalid syntax OID: %p" % [ noidlen ]
|
244
273
|
end
|
245
274
|
|
246
|
-
|
275
|
+
oidstring, len = $1, $2
|
276
|
+
oid = Treequel::Schema.parse_oid( oidstring )
|
247
277
|
|
248
278
|
return oid, len ? Integer(len) : nil
|
249
279
|
end
|
@@ -9,17 +9,6 @@ require 'treequel/exceptions'
|
|
9
9
|
|
10
10
|
|
11
11
|
# This is a class for representing ldapSyntax declarations in a Treequel::Schema.
|
12
|
-
#
|
13
|
-
# == Authors
|
14
|
-
#
|
15
|
-
# * Michael Granger <ged@FaerieMUD.org>
|
16
|
-
#
|
17
|
-
# :include: LICENSE
|
18
|
-
#
|
19
|
-
#--
|
20
|
-
#
|
21
|
-
# Please see the file LICENSE in the base directory for licensing details.
|
22
|
-
#
|
23
12
|
class Treequel::Schema::LDAPSyntax
|
24
13
|
include Treequel::Loggable,
|
25
14
|
Treequel::Constants::Patterns
|