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/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
|