treequel 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/ChangeLog +354 -0
  2. data/LICENSE +27 -0
  3. data/README +66 -0
  4. data/Rakefile +345 -0
  5. data/Rakefile.local +43 -0
  6. data/bin/treeirb +14 -0
  7. data/bin/treequel +229 -0
  8. data/examples/company-directory.rb +112 -0
  9. data/examples/ldap-monitor.rb +143 -0
  10. data/examples/ldap-monitor/public/css/master.css +328 -0
  11. data/examples/ldap-monitor/public/images/card_small.png +0 -0
  12. data/examples/ldap-monitor/public/images/chain_small.png +0 -0
  13. data/examples/ldap-monitor/public/images/globe_small.png +0 -0
  14. data/examples/ldap-monitor/public/images/globe_small_green.png +0 -0
  15. data/examples/ldap-monitor/public/images/plug.png +0 -0
  16. data/examples/ldap-monitor/public/images/shadows/large-30-down.png +0 -0
  17. data/examples/ldap-monitor/public/images/tick.png +0 -0
  18. data/examples/ldap-monitor/public/images/tick_circle.png +0 -0
  19. data/examples/ldap-monitor/public/images/treequel-favicon.png +0 -0
  20. data/examples/ldap-monitor/views/backends.erb +41 -0
  21. data/examples/ldap-monitor/views/connections.erb +74 -0
  22. data/examples/ldap-monitor/views/databases.erb +39 -0
  23. data/examples/ldap-monitor/views/dump_subsystem.erb +14 -0
  24. data/examples/ldap-monitor/views/index.erb +14 -0
  25. data/examples/ldap-monitor/views/layout.erb +35 -0
  26. data/examples/ldap-monitor/views/listeners.erb +30 -0
  27. data/examples/ldap_state.rb +62 -0
  28. data/lib/treequel.rb +145 -0
  29. data/lib/treequel/branch.rb +589 -0
  30. data/lib/treequel/branchcollection.rb +204 -0
  31. data/lib/treequel/branchset.rb +360 -0
  32. data/lib/treequel/constants.rb +604 -0
  33. data/lib/treequel/directory.rb +541 -0
  34. data/lib/treequel/exceptions.rb +32 -0
  35. data/lib/treequel/filter.rb +704 -0
  36. data/lib/treequel/mixins.rb +325 -0
  37. data/lib/treequel/schema.rb +245 -0
  38. data/lib/treequel/schema/attributetype.rb +252 -0
  39. data/lib/treequel/schema/ldapsyntax.rb +96 -0
  40. data/lib/treequel/schema/matchingrule.rb +124 -0
  41. data/lib/treequel/schema/matchingruleuse.rb +124 -0
  42. data/lib/treequel/schema/objectclass.rb +289 -0
  43. data/lib/treequel/sequel_integration.rb +26 -0
  44. data/lib/treequel/utils.rb +169 -0
  45. data/rake/191_compat.rb +26 -0
  46. data/rake/dependencies.rb +76 -0
  47. data/rake/helpers.rb +434 -0
  48. data/rake/hg.rb +261 -0
  49. data/rake/manual.rb +782 -0
  50. data/rake/packaging.rb +135 -0
  51. data/rake/publishing.rb +318 -0
  52. data/rake/rdoc.rb +30 -0
  53. data/rake/style.rb +62 -0
  54. data/rake/svn.rb +668 -0
  55. data/rake/testing.rb +187 -0
  56. data/rake/verifytask.rb +64 -0
  57. data/rake/win32.rb +190 -0
  58. data/spec/lib/constants.rb +93 -0
  59. data/spec/lib/helpers.rb +100 -0
  60. data/spec/treequel/branch_spec.rb +569 -0
  61. data/spec/treequel/branchcollection_spec.rb +213 -0
  62. data/spec/treequel/branchset_spec.rb +376 -0
  63. data/spec/treequel/directory_spec.rb +487 -0
  64. data/spec/treequel/filter_spec.rb +482 -0
  65. data/spec/treequel/mixins_spec.rb +330 -0
  66. data/spec/treequel/schema/attributetype_spec.rb +237 -0
  67. data/spec/treequel/schema/ldapsyntax_spec.rb +83 -0
  68. data/spec/treequel/schema/matchingrule_spec.rb +158 -0
  69. data/spec/treequel/schema/matchingruleuse_spec.rb +137 -0
  70. data/spec/treequel/schema/objectclass_spec.rb +262 -0
  71. data/spec/treequel/schema_spec.rb +118 -0
  72. data/spec/treequel/utils_spec.rb +49 -0
  73. data/spec/treequel_spec.rb +179 -0
  74. metadata +169 -0
@@ -0,0 +1,604 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'ldap'
4
+ require 'treequel'
5
+
6
+
7
+ ### A collection of constants that are shared across the library
8
+ module Treequel::Constants
9
+
10
+ ### Mapping of various symbolic names to LDAP integer LDAP_SCOPE_* values. Valid
11
+ ### values are:
12
+ ###
13
+ ### :onelevel, :one, :base, :subtree, :sub
14
+ ###
15
+ SCOPE = {
16
+ :onelevel => LDAP::LDAP_SCOPE_ONELEVEL,
17
+ :one => LDAP::LDAP_SCOPE_ONELEVEL,
18
+ :base => LDAP::LDAP_SCOPE_BASE,
19
+ :subtree => LDAP::LDAP_SCOPE_SUBTREE,
20
+ :sub => LDAP::LDAP_SCOPE_SUBTREE,
21
+ }.freeze
22
+
23
+ ### Mapping of LDAP integer scope (LDAP_SCOPE_*) values to their names.
24
+ SCOPE_NAME = {
25
+ LDAP::LDAP_SCOPE_ONELEVEL => 'one',
26
+ LDAP::LDAP_SCOPE_BASE => 'base',
27
+ LDAP::LDAP_SCOPE_SUBTREE => 'subtree',
28
+ }
29
+
30
+
31
+ ### OIDs of RFC values
32
+ module OIDS
33
+
34
+ # :stopdoc:
35
+
36
+ ### Object Classes (from RFC 4519)
37
+ TOP_OBJECTCLASS = '2.5.6.0'
38
+
39
+ ### Syntaxes (from RFC 4517)
40
+ RDN_SYNTAX = '1.2.36.79672281.1.5.0'
41
+ RFC2307_NIS_NETGROUP_TRIPLE_SYNTAX = '1.3.6.1.1.1.0.0'
42
+ RFC2307_BOOT_PARAMETER_SYNTAX = '1.3.6.1.1.1.0.1'
43
+ UUID_SYNTAX = '1.3.6.1.1.16.1'
44
+ AUDIO_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.4'
45
+ BINARY_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.5'
46
+ BIT_STRING_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.6'
47
+ BOOLEAN_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.7'
48
+ CERTIFICATE_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.8'
49
+ CERTIFICATE_LIST_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.9'
50
+ CERTIFICATE_PAIR_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.10'
51
+ COUNTRY_STRING_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.11'
52
+ DISTINGUISHED_NAME_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.12'
53
+ DELIVERY_METHOD_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.14'
54
+ DIRECTORY_STRING_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.15'
55
+ STRING_SYNTAX = DIRECTORY_STRING_SYNTAX # Alias
56
+ FACSIMILE_TELEPHONE_NUMBER_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.22'
57
+ GENERALIZED_TIME_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.24'
58
+ IA5_STRING_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.26'
59
+ INTEGER_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.27'
60
+ JPEG_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.28'
61
+ NAME_AND_OPTIONAL_UID_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.34'
62
+ NUMERIC_STRING_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.36'
63
+ OID_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.38'
64
+ OTHER_MAILBOX_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.39'
65
+ OCTET_STRING_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.40'
66
+ POSTAL_ADDRESS_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.41'
67
+ PRINTABLE_STRING_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.44'
68
+ SUBTREESPECIFICATION_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.45'
69
+ SUPPORTED_ALGORITHM_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.49'
70
+ TELEPHONE_NUMBER_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.50'
71
+ TELEX_NUMBER_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.52'
72
+ UTC_TIME_SYNTAX = '1.3.6.1.4.1.1466.115.121.1.53'
73
+
74
+ constants.each do |constname|
75
+ const_get( constname ).freeze
76
+ end
77
+ end
78
+
79
+
80
+ ### A collection of Regexps to match various LDAP values
81
+ module Patterns
82
+
83
+ # :stopdoc:
84
+
85
+ # Schema-parsing patterns based on the BNF in
86
+ # RFC 4512 (http://tools.ietf.org/html/rfc4512#section-4.1.1)
87
+
88
+ # ALPHA = %x41-5A / %x61-7A ; "A"-"Z" / "a"-"z"
89
+ ALPHA = '[:alpha:]'
90
+
91
+ # LDIGIT = %x31-39 ; "1"-"9"
92
+ LDIGIT = '1-9'
93
+
94
+ # DIGIT = %x30 / LDIGIT ; "0"-"9"
95
+ DIGIT = '\d'
96
+
97
+ # HEX = DIGIT / %x41-46 / %x61-66 ; "0"-"9" / "A"-"F" / "a"-"f"
98
+ HEX = '[:xdigit:]'
99
+
100
+ #
101
+ # SP = 1*SPACE ; one or more " "
102
+ # WSP = 0*SPACE ; zero or more " "
103
+ SP = '[ ]+'
104
+ WSP = '[ ]*'
105
+
106
+ ### These are inlined for simplicity
107
+ # NULL = %x00 ; null (0)
108
+ NULL = '\x00'
109
+
110
+ # SPACE = %x20 ; space (" ")
111
+ SPACE = '\x20'
112
+
113
+ # DQUOTE = %x22 ; quote (""")
114
+ DQUOTE = '\x22'
115
+
116
+ # SHARP = %x23 ; octothorpe (or sharp sign) ("#")
117
+ SHARP = '\x23'
118
+
119
+ # DOLLAR = %x24 ; dollar sign ("$")
120
+ DOLLAR = '\x24'
121
+
122
+ # SQUOTE = %x27 ; single quote ("'")
123
+ SQUOTE = '\x27'
124
+
125
+ # LPAREN = %x28 ; left paren ("(")
126
+ # RPAREN = %x29 ; right paren (")")
127
+ LPAREN = '\x28'
128
+ RPAREN = '\x29'
129
+
130
+ # PLUS = %x2B ; plus sign ("+")
131
+ PLUS = '\x2b'
132
+
133
+ # COMMA = %x2C ; comma (",")
134
+ COMMA = '\x2c'
135
+
136
+ # HYPHEN = %x2D ; hyphen ("-")
137
+ HYPHEN = '\x2d'
138
+
139
+ # DOT = %x2E ; period (".")
140
+ DOT = '\x2e'
141
+
142
+ # SEMI = %x3B ; semicolon (";")
143
+ SEMI = '\x3b'
144
+
145
+ # LANGLE = %x3C ; left angle bracket ("<")
146
+ # EQUALS = %x3D ; equals sign ("=")
147
+ # RANGLE = %x3E ; right angle bracket (">")
148
+ LANGLE = '\x3c'
149
+ EQUALS = '\x3d'
150
+ RANGLE = '\x3e'
151
+
152
+ # ESC = %x5C ; backslash ("\")
153
+ ESC = '\x5c'
154
+
155
+ # USCORE = %x5F ; underscore ("_")
156
+ USCORE = '\x5f'
157
+
158
+ # LCURLY = %x7B ; left curly brace "{"
159
+ # RCURLY = %x7D ; right curly brace "}"
160
+ LCURLY = '\x7b'
161
+ RCURLY = '\x7d'
162
+
163
+ # EXCLAMATION = %x21 ; exclamation mark ("!")
164
+ # AMPERSAND = %x26 ; ampersand (or AND symbol) ("&")
165
+ # ASTERISK = %x2A ; asterisk ("*")
166
+ # COLON = %x3A ; colon (":")
167
+ # VERTBAR = %x7C ; vertical bar (or pipe) ("|")
168
+ # TILDE = %x7E ; tilde ("~")
169
+ EXCLAMATION = '\x21'
170
+ AMPERSAND = '\x26'
171
+ ASTERISK = '\x2a'
172
+ COLON = '\x3a'
173
+ VERTBAR = '\x7c'
174
+ TILDE = '\x7e'
175
+
176
+ # ; Any UTF-8 [RFC3629] encoded Unicode [Unicode] character
177
+ # UTF0 = %x80-BF
178
+ # UTF1 = %x00-7F
179
+ # UTF2 = %xC2-DF UTF0
180
+ UTF0 = /[\x80-\xbf]/
181
+ UTF1 = /[\x00-\x7f]/
182
+ UTF2 = /[\xc2-\xdf] #{UTF0}/x
183
+
184
+ # UTF3 = %xE0 %xA0-BF UTF0 / %xE1-EC 2(UTF0) / %xED %x80-9F UTF0 / %xEE-EF 2(UTF0)
185
+ UTF3 = /
186
+ \xe0 [\xa0-\xbf] #{UTF0}
187
+ |
188
+ [\xe1-\xec] #{UTF0}{2}
189
+ |
190
+ \xed [\x80-\x9f] #{UTF0}
191
+ |
192
+ [\xee-\xef] #{UTF0}{2}
193
+ /x
194
+
195
+ # UTF4 = %xF0 %x90-BF 2(UTF0) / %xF1-F3 3(UTF0) / %xF4 %x80-8F 2(UTF0)
196
+ UTF4 = /
197
+ \xf0 [\x90-\xbf] #{UTF0}{2}
198
+ |
199
+ [\xf1-\xf3] #{UTF0}{3}
200
+ |
201
+ \xf4 [\x80-\x8f] #{UTF0}{2}
202
+ /x
203
+
204
+ # UTFMB = UTF2 / UTF3 / UTF4
205
+ UTFMB = Regexp.union( UTF2, UTF3, UTF4 )
206
+
207
+ # UTF8 = UTF1 / UTFMB
208
+ UTF8 = Regexp.union( UTF1, UTFMB )
209
+
210
+ # OCTET = %x00-FF ; Any octet (8-bit data unit)
211
+ OCTET = '.'
212
+
213
+ # leadkeychar = ALPHA
214
+ LEADKEYCHAR = /[#{ALPHA}]/
215
+
216
+ # keychar = ALPHA / DIGIT / HYPHEN
217
+ KEYCHAR = /[#{ALPHA}#{DIGIT}\-]/
218
+
219
+ # number = DIGIT / ( LDIGIT 1*DIGIT )
220
+ NUMBER = /[#{LDIGIT}]#{DIGIT}+|#{DIGIT}/ # Reversed for greediness
221
+
222
+ # keystring = leadkeychar *keychar
223
+ KEYSTRING = /#{LEADKEYCHAR}#{KEYCHAR}*/
224
+
225
+ # Object identifiers (OIDs) [X.680] are represented in LDAP using a
226
+ # dot-decimal format conforming to the ABNF:
227
+
228
+ # numericoid = number 1*( DOT number )
229
+ NUMERICOID = /#{NUMBER}(?: #{DOT} #{NUMBER} )+/x
230
+
231
+
232
+ # Short names, also known as ¨iptors, are used as more readable
233
+ # aliases for object identifiers. Short names are case insensitive and
234
+ # conform to the ABNF:
235
+
236
+ # descr = keystring
237
+ DESCR = KEYSTRING
238
+
239
+ # Where either an object identifier or a short name may be specified,
240
+ # the following production is used:
241
+
242
+ # oid = descr / numericoid
243
+ OID = / #{DESCR} | #{NUMERICOID} /x
244
+
245
+
246
+ # len = number
247
+ LEN = NUMBER
248
+
249
+ # noidlen = numericoid [ LCURLY len RCURLY ]
250
+ NOIDLEN = /#{NUMERICOID} (?:#{LCURLY} #{LEN} #{RCURLY})?/x
251
+
252
+ # oidlist = oid *( WSP DOLLAR WSP oid )
253
+ OIDLIST = /#{OID} (?: #{WSP} #{DOLLAR} #{WSP} #{OID} )*/x
254
+
255
+ # oids = oid / ( LPAREN WSP oidlist WSP RPAREN )
256
+ OIDS = / #{OID} | #{LPAREN} #{WSP} #{OIDLIST} #{WSP} #{RPAREN} /x
257
+
258
+ # xstring = "X" HYPHEN 1*( ALPHA / HYPHEN / USCORE )
259
+ XSTRING = / X #{HYPHEN} [#{ALPHA}#{HYPHEN}#{USCORE}]+ /x
260
+
261
+ # qdescr = SQUOTE descr SQUOTE
262
+ # qdescrlist = [ qdescr *( SP qdescr ) ]
263
+ # qdescrs = qdescr / ( LPAREN WSP qdescrlist WSP RPAREN )
264
+ QDESCR = / #{SQUOTE} #{DESCR} #{SQUOTE} /x
265
+ QDESCRLIST = /(?: #{QDESCR} (?: #{SP} #{QDESCR} )* )?/x
266
+ QDESCRS = / #{QDESCR} | #{LPAREN} #{WSP} #{QDESCRLIST} #{WSP} #{RPAREN} /x
267
+
268
+ # ; Any ASCII character except %x27 ("\'") and %x5C ("\")
269
+ # QUTF1 = %x00-26 / %x28-5B / %x5D-7F
270
+ QUTF1 = /[\x00-\x26\x28-\x5b\x5d-\x7f]/
271
+
272
+ # ; Any UTF-8 encoded Unicode character
273
+ # ; except %x27 ("\'") and %x5C ("\")
274
+ # QUTF8 = QUTF1 / UTFMB
275
+ QUTF8 = Regexp.union( QUTF1, UTFMB )
276
+
277
+ # QQ = ESC %x32 %x37 ; "\27"
278
+ # QS = ESC %x35 ( %x43 / %x63 ) ; "\5C" / "\5c"
279
+ QQ = / #{ESC} 27 /x
280
+ QS = / #{ESC} 5c /xi
281
+
282
+
283
+ ### NOTE: QDSTRING is zero-or-more despite the RFC's specifying it as 1 or more
284
+ ### to support empty DESC attributes in the wild (e.g., the ones in the
285
+ ### attributeTypes from the 'retcode' overlay in OpenLDAP)
286
+
287
+ # dstring = 1*( QS / QQ / QUTF8 ) ; escaped UTF-8 string
288
+ # qdstring = SQUOTE dstring SQUOTE
289
+ # qdstringlist = [ qdstring *( SP qdstring ) ]
290
+ # qdstrings = qdstring / ( LPAREN WSP qdstringlist WSP RPAREN )
291
+ DSTRING = / (?: #{QS} | #{QQ} | #{QUTF8} )* /x
292
+ QDSTRING = / #{SQUOTE} #{DSTRING} #{SQUOTE} /x
293
+ QDSTRINGLIST = /(?: #{QDSTRING} (?: #{SP} #{QDSTRING} )* )?/x
294
+ QDSTRINGS = / #{QDSTRING} | #{LPAREN} #{WSP} #{QDSTRINGLIST} #{WSP} #{RPAREN} /x
295
+
296
+ # extensions = *( SP xstring SP qdstrings )
297
+ EXTENSIONS = /(?: #{SP} #{XSTRING} #{SP} #{QDSTRINGS} )*/x
298
+
299
+ # kind = "ABSTRACT" / "STRUCTURAL" / "AUXILIARY"
300
+ KIND = Regexp.union( 'ABSTRACT', 'STRUCTURAL', 'AUXILIARY' )
301
+
302
+ # Object Class definitions are written according to the ABNF:
303
+
304
+ # ObjectClassDescription = LPAREN WSP
305
+ # numericoid ; object identifier
306
+ # [ SP "NAME" SP qdescrs ] ; short names (descriptors)
307
+ # [ SP "DESC" SP qdstring ] ; description
308
+ # [ SP "OBSOLETE" ] ; not active
309
+ # [ SP "SUP" SP oids ] ; superior object classes
310
+ # [ SP kind ] ; kind of class
311
+ # [ SP "MUST" SP oids ] ; attribute types
312
+ # [ SP "MAY" SP oids ] ; attribute types
313
+ # extensions WSP RPAREN
314
+
315
+ LDAP_OBJECTCLASS_DESCRIPTION = %r{
316
+ #{LPAREN} #{WSP}
317
+ (#{NUMERICOID}) # $1 = oid
318
+ (?:#{SP} NAME #{SP} (#{QDESCRS}) )? # $2 = name
319
+ (?:#{SP} DESC #{SP} (#{QDSTRING}))? # $3 = desc
320
+ (?:#{SP} (OBSOLETE) )? # $4 = obsolete
321
+ (?:#{SP} SUP #{SP} (#{OIDS}) )? # $5 = sup
322
+ (?:#{SP} (#{KIND}) )? # $6 = kind
323
+ (?:#{SP} MUST #{SP} (#{OIDS}) )? # $7 = must attrs
324
+ (?:#{SP} MAY #{SP} (#{OIDS}) )? # $8 = may attrs
325
+ (#{EXTENSIONS}) # $9 = extensions
326
+ #{WSP} #{RPAREN}
327
+ }x
328
+
329
+
330
+ # usage = "userApplications" / ; user
331
+ # "directoryOperation" / ; directory operational
332
+ # "distributedOperation" / ; DSA-shared operational
333
+ # "dSAOperation" ; DSA-specific operational
334
+ USAGE = Regexp.union(
335
+ 'userApplications',
336
+ 'directoryOperation',
337
+ 'distributedOperation',
338
+ 'dSAOperation'
339
+ )
340
+
341
+ # Attribute Type definitions are written according to the ABNF:
342
+ #
343
+ # AttributeTypeDescription = LPAREN WSP
344
+ # numericoid ; object identifier
345
+ # [ SP "NAME" SP qdescrs ] ; short names (descriptors)
346
+ # [ SP "DESC" SP qdstring ] ; description
347
+ # [ SP "OBSOLETE" ] ; not active
348
+ # [ SP "SUP" SP oid ] ; supertype
349
+ # [ SP "EQUALITY" SP oid ] ; equality matching rule
350
+ # [ SP "ORDERING" SP oid ] ; ordering matching rule
351
+ # [ SP "SUBSTR" SP oid ] ; substrings matching rule
352
+ # [ SP "SYNTAX" SP noidlen ] ; value syntax
353
+ # [ SP "SINGLE-VALUE" ] ; single-value
354
+ # [ SP "COLLECTIVE" ] ; collective
355
+ # [ SP "NO-USER-MODIFICATION" ] ; not user modifiable
356
+ # [ SP "USAGE" SP usage ] ; usage
357
+ # extensions WSP RPAREN ; extensions
358
+ LDAP_ATTRIBUTE_TYPE_DESCRIPTION = %r{
359
+ #{LPAREN} #{WSP}
360
+ (#{NUMERICOID}) # $1 = oid
361
+ (?:#{SP} NAME #{SP} (#{QDESCRS}) )? # $2 = name
362
+ (?:#{SP} DESC #{SP} (#{QDSTRING}) )? # $3 = description
363
+ (?:#{SP} (OBSOLETE) )? # $4 = obsolete flag
364
+ (?:#{SP} SUP #{SP} (#{OID}) )? # $5 = superior type oid
365
+ (?:#{SP} EQUALITY #{SP} (#{OID}) )? # $6 = equality matching rule oid
366
+ (?:#{SP} ORDERING #{SP} (#{OID}) )? # $7 = ordering matching rule oid
367
+ (?:#{SP} SUBSTR #{SP} (#{OID}) )? # $8 = substring matching rule oid
368
+ (?:#{SP} SYNTAX #{SP} (#{NOIDLEN}) )? # $9 = value syntax matching oid
369
+ (?:#{SP} (SINGLE-VALUE) )? # $10 = single value flag
370
+ (?:#{SP} (COLLECTIVE) )? # $11 = collective flag
371
+ (?:#{SP} (NO-USER-MODIFICATION) )? # $12 = no user modification flag
372
+ (?:#{SP} USAGE #{SP} (#{USAGE}) )? # $13 = usage type
373
+ (#{EXTENSIONS}) # $14 = extensions
374
+ #{WSP} #{RPAREN}
375
+ }x
376
+
377
+
378
+ # MatchingRuleDescription = LPAREN WSP
379
+ # numericoid ; object identifier
380
+ # [ SP "NAME" SP qdescrs ] ; short names (descriptors)
381
+ # [ SP "DESC" SP qdstring ] ; description
382
+ # [ SP "OBSOLETE" ] ; not active
383
+ # SP "SYNTAX" SP numericoid ; assertion syntax
384
+ # extensions WSP RPAREN ; extensions
385
+ LDAP_MATCHING_RULE_DESCRIPTION = %r{
386
+ #{LPAREN} #{WSP}
387
+ (#{NUMERICOID}) # $1 = oid
388
+ (?:#{SP} NAME #{SP} (#{QDESCRS}) )? # $2 = name
389
+ (?:#{SP} DESC #{SP} (#{QDSTRING}) )? # $3 = description
390
+ (?:#{SP} (OBSOLETE) )? # $4 = obsolete flag
391
+ #{SP} SYNTAX #{SP} (#{NUMERICOID}) # $5 = syntax numeric OID
392
+ (#{EXTENSIONS}) # $6 = extensions
393
+ #{WSP} #{RPAREN}
394
+ }x
395
+
396
+
397
+ # Matching rule use descriptions are written according to the following
398
+ # ABNF:
399
+ #
400
+ # MatchingRuleUseDescription = LPAREN WSP
401
+ # numericoid ; object identifier
402
+ # [ SP "NAME" SP qdescrs ] ; short names (descriptors)
403
+ # [ SP "DESC" SP qdstring ] ; description
404
+ # [ SP "OBSOLETE" ] ; not active
405
+ # SP "APPLIES" SP oids ; attribute types
406
+ # extensions WSP RPAREN ; extensions
407
+ LDAP_MATCHING_RULE_USE_DESCRIPTION = %r{
408
+ #{LPAREN} #{WSP}
409
+ (#{NUMERICOID}) # $1 = oid
410
+ (?:#{SP} NAME #{SP} (#{QDESCRS}) )? # $2 = name
411
+ (?:#{SP} DESC #{SP} (#{QDSTRING}) )? # $3 = description
412
+ (?:#{SP} (OBSOLETE) )? # $4 = obsolete flag
413
+ #{SP} APPLIES #{SP} (#{OIDS}) # $5 = attribute types
414
+ (#{EXTENSIONS}) # $6 = extensions
415
+ #{WSP} #{RPAREN}
416
+ }x
417
+
418
+
419
+ # LDAP syntax definitions are written according to the ABNF:
420
+ #
421
+ # SyntaxDescription = LPAREN WSP
422
+ # numericoid ; object identifier
423
+ # [ SP "DESC" SP qdstring ] ; description
424
+ # extensions WSP RPAREN ; extensions
425
+ #
426
+ LDAP_SYNTAX_DESCRIPTION = %r{
427
+ #{LPAREN} #{WSP}
428
+ (#{NUMERICOID}) # $1 = oid
429
+ (?:#{SP} DESC #{SP} (#{QDSTRING}) )? # $2 = description
430
+ (#{EXTENSIONS}) # $3 = extensions
431
+ #{WSP} #{RPAREN}
432
+ }x
433
+
434
+
435
+ # UTF1SUBSET = %x01-27 / %x2B-5B / %x5D-7F
436
+ # ; UTF1SUBSET excludes 0x00 (NUL), LPAREN,
437
+ # ; RPAREN, ASTERISK, and ESC.
438
+ UTF1SUBSET = %r{
439
+ [\x01-\x27\x2b-\x5b\x50-\x7f]
440
+ }x
441
+
442
+ # normal = UTF1SUBSET / UTFMB
443
+ NORMAL = %r{ #{UTF1SUBSET} | #{UTFMB} }x
444
+
445
+ # escaped = ESC HEX HEX
446
+ ESCAPED = %r{ #{ESC} [[:xdigit:]]{2} }x
447
+
448
+ # valueencoding = 0*(normal / escaped)
449
+ VALUEENCODING = %r{ (?:#{NORMAL} | #{ESCAPED})* }x
450
+
451
+ # assertionvalue = valueencoding
452
+ # ; The <valueencoding> rule is used to encode an <AssertionValue>
453
+ # ; from Section 4.1.6 of [RFC4511].
454
+ ASSERTIONVALUE = VALUEENCODING
455
+
456
+ # The value part of a substring filter
457
+ # initial = assertionvalue
458
+ # any = ASTERISK *(assertionvalue ASTERISK)
459
+ # final = assertionvalue
460
+ LDAP_SUBSTRING_FILTER_VALUE = %r{
461
+ #{ASSERTIONVALUE}
462
+ #{ASTERISK}
463
+ (?: #{ASSERTIONVALUE} #{ASTERISK} )*
464
+ #{ASSERTIONVALUE}
465
+ }x
466
+
467
+ # An AttributeDescription (same as LDAPString)
468
+ # attributedescription = attributetype options
469
+ # attributetype = oid
470
+ # options = *( SEMI option )
471
+ # option = 1*keychar
472
+ LDAP_ATTRIBUTE_DESCRIPTION = %r{
473
+ (#{OID}) # $1: the OID
474
+ ( # $2: attribute options
475
+ (?:;#{KEYCHAR}+)*
476
+ )
477
+ }x
478
+
479
+ # A substring filter, from RFC4511, section 4.5.1
480
+ # SubstringFilter ::= SEQUENCE {
481
+ # type AttributeDescription,
482
+ # substrings SEQUENCE SIZE (1..MAX) OF substring CHOICE {
483
+ # initial [0] AssertionValue, -- can occur at most once
484
+ # any [1] AssertionValue,
485
+ # final [2] AssertionValue } -- can occur at most once
486
+ # }
487
+ LDAP_SUBSTRING_FILTER = %r{
488
+ (#{LDAP_ATTRIBUTE_DESCRIPTION}) # $1: AttributeDescription
489
+ =
490
+ (#{LDAP_SUBSTRING_FILTER_VALUE}) # $2: value
491
+ }x
492
+
493
+
494
+ #
495
+ # Distinguished Names (RFC4514)
496
+ #
497
+
498
+ # hexpair = HEX HEX
499
+ HEXPAIR = /#{HEX}{2}/
500
+
501
+ # hexstring = SHARP 1*hexpair
502
+ HEXSTRING = %r{ #{SHARP} #{HEXPAIR}+ }x
503
+
504
+ # escaped = DQUOTE / PLUS / COMMA / SEMI / LANGLE / RANGLE
505
+ DN_ESCAPED = %r{ #{DQUOTE} | #{PLUS} | #{COMMA} | #{SEMI} | #{LANGLE} | #{RANGLE} }x
506
+
507
+ # special = escaped / SPACE / SHARP / EQUALS
508
+ SPECIAL = %r{ #{DN_ESCAPED} | #{SPACE} | #{SHARP} | #{EQUALS} }x
509
+
510
+ # pair = ESC ( ESC / special / hexpair )
511
+ PAIR = %r{
512
+ #{ESC}
513
+ (?:
514
+ #{ESC}
515
+ | #{SPECIAL}
516
+ | #{HEXPAIR}
517
+ )
518
+ }x
519
+
520
+ # SUTF1 = %x01-21 / %x23-2A / %x2D-3A / %x3D / %x3F-5B / %x5D-7F
521
+ SUTF1 = /[\x01-\x21\x23-\x2a\x2d-\x3a\x3d\x3f-\x5b\x5d-\x7f]/
522
+
523
+ # stringchar = SUTF1 / UTFMB
524
+ STRINGCHAR = %r{ #{SUTF1} | #{UTFMB} }x
525
+
526
+ # TUTF1 = %x01-1F / %x21 / %x23-2A / %x2D-3A / %x3D / %x3F-5B / %x5D-7F
527
+ TUTF1 = /[\x01-\x1f\x21\x23-\x2a\x2d-\x3a\x3d\x3f-\x5b\x5d-\x7f]/
528
+
529
+ # trailchar = TUTF1 / UTFMB
530
+ TRAILCHAR = %r{ #{TUTF1} | #{UTFMB} }x
531
+
532
+ # LUTF1 = %x01-1F / %x21 / %x24-2A / %x2D-3A / %x3D / %x3F-5B / %x5D-7F
533
+ LUTF1 = /[\x01-\x1f\x21\x24-\x2a\x2d-\x3a\x3d\x3f-\x5b\x5d-\x7f]/
534
+
535
+ # leadchar = LUTF1 / UTFMB
536
+ LEADCHAR = %r{ #{LUTF1} | #{UTFMB} }x
537
+
538
+ # ; The following characters are to be escaped when they appear
539
+ # ; in the value to be encoded: ESC, one of <escaped>, leading
540
+ # ; SHARP or SPACE, trailing SPACE, and NULL.
541
+ # string = [ ( leadchar / pair ) [ *( stringchar / pair )
542
+ # ( trailchar / pair ) ] ]
543
+ # NOTE: the RFC specifies that all characters are optional in a STRING, which means that
544
+ # the RDN 'cn=' is valid. While I hesitate to deviate from the RFC, I can't currently
545
+ # conceive of a way such an RDN would be useful, so I'm defining this as requiring at
546
+ # least one character. If this becomes a problem later, we can just surround it
547
+ # with non-capturing parens with a optional qualifier.
548
+ STRING = %r{
549
+ (?:
550
+ #{LEADCHAR}
551
+ | #{PAIR}
552
+ )
553
+ (?:
554
+ (?: #{STRINGCHAR} | #{PAIR} )*
555
+ #{TRAILCHAR} | #{PAIR}
556
+ )?
557
+ }x
558
+
559
+ # attributeValue = string / hexstring
560
+ ATTRIBUTE_VALUE = %r{
561
+ #{HEXSTRING} # Since STRING can match the empty string, try HEXSTRING first
562
+ | #{STRING}
563
+ }x
564
+
565
+ # attributeType = descr / numericoid
566
+ ATTRIBUTE_TYPE = %r{
567
+ #{DESCR}
568
+ |
569
+ #{NUMERICOID}
570
+ }x
571
+
572
+ # attributeTypeAndValue = attributeType EQUALS attributeValue
573
+ ATTRIBUTE_TYPE_AND_VALUE = %r{
574
+ #{ATTRIBUTE_TYPE} = #{ATTRIBUTE_VALUE}
575
+ }x
576
+
577
+ # relativeDistinguishedName = attributeTypeAndValue
578
+ # *( PLUS attributeTypeAndValue )
579
+ RELATIVE_DISTINGUISHED_NAME = %r{
580
+ #{ATTRIBUTE_TYPE_AND_VALUE}
581
+ (?:
582
+ \+
583
+ #{ATTRIBUTE_TYPE_AND_VALUE}
584
+ )*
585
+ }x
586
+
587
+ # distinguishedName = [ relativeDistinguishedName
588
+ # *( COMMA relativeDistinguishedName ) ]
589
+ DISTINGUISHED_NAME = %r{
590
+ #{RELATIVE_DISTINGUISHED_NAME}
591
+ (?:
592
+ ,
593
+ #{RELATIVE_DISTINGUISHED_NAME}
594
+ )*
595
+ }x
596
+
597
+
598
+ end # module Patterns
599
+
600
+ end # module Treequel::Constants
601
+
602
+ # vim: set nosta noet ts=4 sw=4:
603
+
604
+