treequel 1.0.0

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.
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
+