| Class | ActiveLdap::Ldif::Parser |
| In: |
lib/active_ldap/ldif.rb
|
| Parent: | Object |
| ATTRIBUTE_TYPE_CHARS | = | /[a-zA-Z][a-zA-Z0-9\-]*/u |
| SAFE_CHAR | = | /[\x01-\x09\x0B-\x0C\x0E-\x7F]/u |
| SAFE_INIT_CHAR | = | /[\x01-\x09\x0B-\x0C\x0E-\x1F\x21-\x39\x3B\x3D-\x7F]/u |
| SAFE_STRING | = | /#{SAFE_INIT_CHAR}#{SAFE_CHAR}*/u |
| FILL | = | / */u |
| ldif | [R] |
# File lib/active_ldap/ldif.rb, line 84
84: def initialize(source)
85: @ldif = nil
86: source = source.to_s if source.is_a?(LDIF)
87: @source = source
88: end
# File lib/active_ldap/ldif.rb, line 95
95: def parse
96: return @ldif if @ldif
97:
98: @scanner = Scanner.new(@source)
99: raise version_spec_is_missing unless @scanner.scan(/version:/u)
100: @scanner.scan(FILL)
101:
102: version = @scanner.scan(/\d+/u)
103: raise version_number_is_missing if version.nil?
104:
105: version = Integer(version)
106: raise unsupported_version(version) if version != 1
107:
108: raise separator_is_missing unless @scanner.scan_separators
109:
110: records = parse_records
111:
112: @ldif = LDIF.new(records)
113: end
# File lib/active_ldap/ldif.rb, line 447
447: def attribute_spec_is_missing
448: invalid_ldif(_("attribute spec is missing"))
449: end
# File lib/active_ldap/ldif.rb, line 407
407: def attribute_type_is_missing
408: invalid_ldif(_("attribute type is missing"))
409: end
# File lib/active_ldap/ldif.rb, line 415
415: def attribute_value_separator_is_missing
416: invalid_ldif(_("':' is missing"))
417: end
# File lib/active_ldap/ldif.rb, line 431
431: def change_type_is_missing
432: invalid_ldif(_("change type is missing"))
433: end
# File lib/active_ldap/ldif.rb, line 443
443: def change_type_value_is_missing
444: invalid_ldif(_("change type value is missing"))
445: end
# File lib/active_ldap/ldif.rb, line 435
435: def control_type_is_missing
436: invalid_ldif(_("control type is missing"))
437: end
# File lib/active_ldap/ldif.rb, line 439
439: def criticality_is_missing
440: invalid_ldif(_("criticality is missing"))
441: end
# File lib/active_ldap/ldif.rb, line 459
459: def delete_old_rdn_mark_is_missing
460: invalid_ldif(_("'deleteoldrdn:' is missing"))
461: end
# File lib/active_ldap/ldif.rb, line 463
463: def delete_old_rdn_value_is_missing
464: invalid_ldif(_("delete old RDN value is missing"))
465: end
# File lib/active_ldap/ldif.rb, line 403
403: def dn_has_invalid_character(character)
404: invalid_ldif(_("DN has an invalid character: %s") % character)
405: end
# File lib/active_ldap/ldif.rb, line 395
395: def dn_is_missing
396: invalid_ldif(_("DN is missing"))
397: end
# File lib/active_ldap/ldif.rb, line 391
391: def dn_mark_is_missing
392: invalid_ldif(_("'dn:' is missing"))
393: end
# File lib/active_ldap/ldif.rb, line 399
399: def invalid_dn(dn_string, reason)
400: invalid_ldif(_("DN is invalid: %s: %s") % [dn_string, reason])
401: end
# File lib/active_ldap/ldif.rb, line 371
371: def invalid_ldif(reason)
372: LdifInvalid.new(@source, reason, @scanner.line, @scanner.column)
373: end
# File lib/active_ldap/ldif.rb, line 419
419: def invalid_uri(uri_string, message)
420: invalid_ldif(_("URI is invalid: %s: %s") % [uri_string, message])
421: end
# File lib/active_ldap/ldif.rb, line 423
423: def modify_spec_separator_is_missing
424: invalid_ldif(_("'-' is missing"))
425: end
# File lib/active_ldap/ldif.rb, line 451
451: def new_rdn_mark_is_missing
452: invalid_ldif(_("'newrdn:' is missing"))
453: end
# File lib/active_ldap/ldif.rb, line 455
455: def new_rdn_value_is_missing
456: invalid_ldif(_("new RDN value is missing"))
457: end
# File lib/active_ldap/ldif.rb, line 467
467: def new_superior_value_is_missing
468: invalid_ldif(_("new superior value is missing"))
469: end
# File lib/active_ldap/ldif.rb, line 411
411: def option_is_missing
412: invalid_ldif(_("option is missing"))
413: end
# File lib/active_ldap/ldif.rb, line 183
183: def parse_attribute
184: type, options = parse_attribute_description
185: value = parse_attribute_value
186: [type, options, value]
187: end
# File lib/active_ldap/ldif.rb, line 176
176: def parse_attribute_description
177: type = @scanner.scan(ATTRIBUTE_TYPE_CHARS)
178: raise attribute_type_is_missing if type.nil?
179: options = parse_options
180: [type, options]
181: end
# File lib/active_ldap/ldif.rb, line 199
199: def parse_attribute_value(accept_external_file=true)
200: raise attribute_value_separator_is_missing if @scanner.scan(/:/u).nil?
201: if @scanner.scan(/:/u)
202: @scanner.scan(FILL)
203: read_base64_value
204: elsif accept_external_file and @scanner.scan(/</u)
205: @scanner.scan(FILL)
206: read_external_file
207: else
208: @scanner.scan(FILL)
209: @scanner.scan(SAFE_STRING)
210: end
211: end
# File lib/active_ldap/ldif.rb, line 145
145: def parse_attributes(least=0, &block)
146: i = 0
147: attributes = {}
148: block ||= Proc.new {@scanner.check_separator}
149: loop do
150: i += 1
151: if i >= least
152: break if block.call or @scanner.eos?
153: end
154: type, options, value = parse_attribute
155: if @scanner.scan_separator.nil? and !@scanner.eos?
156: raise separator_is_missing
157: end
158: attributes[type] ||= []
159: container = attributes[type]
160: options.each do |option|
161: parent = container.find do |val|
162: val.is_a?(Hash) and val.has_key?(option)
163: end
164: if parent.nil?
165: parent = {option => []}
166: container << parent
167: end
168: container = parent[option]
169: end
170: container << value
171: end
172: raise attribute_spec_is_missing if attributes.size < least
173: attributes
174: end
# File lib/active_ldap/ldif.rb, line 238
238: def parse_change_type
239: return nil unless @scanner.scan(/changetype:/u)
240: @scanner.scan(FILL)
241: type = @scanner.check(ATTRIBUTE_TYPE_CHARS)
242: raise change_type_value_is_missing if type.nil?
243: unless @scanner.scan(/add|delete|modrdn|moddn|modify/u)
244: raise unknown_change_type(type)
245: end
246:
247: raise separator_is_missing unless @scanner.scan_separator
248: type
249: end
# File lib/active_ldap/ldif.rb, line 311
311: def parse_change_type_record(dn, controls, change_type)
312: case change_type
313: when "add"
314: attributes = parse_attributes(1)
315: AddRecord.new(dn, controls, attributes)
316: when "delete"
317: DeleteRecord.new(dn, controls)
318: when "moddn"
319: parse_modify_name_record(ModifyDNRecord, dn, controls)
320: when "modrdn"
321: parse_modify_name_record(ModifyRDNRecord, dn, controls)
322: when "modify"
323: parse_modify_record(dn, controls)
324: else
325: raise unknown_change_type(change_type)
326: end
327: end
# File lib/active_ldap/ldif.rb, line 213
213: def parse_control
214: return nil if @scanner.scan(/control:/u).nil?
215: @scanner.scan(FILL)
216: type = @scanner.scan(/\d+(?:\.\d+)*/u)
217: raise control_type_is_missing if type.nil?
218: criticality = nil
219: if @scanner.scan(/ +/u)
220: criticality = @scanner.scan(/true|false/u)
221: raise criticality_is_missing if criticality.nil?
222: end
223: value = parse_attribute_value if @scanner.check(/:/u)
224: raise separator_is_missing unless @scanner.scan_separator
225: ChangeRecord::Control.new(type, criticality, value)
226: end
# File lib/active_ldap/ldif.rb, line 228
228: def parse_controls
229: controls = []
230: loop do
231: control = parse_control
232: break if control.nil?
233: controls << control
234: end
235: controls
236: end
# File lib/active_ldap/ldif.rb, line 139
139: def parse_dn(dn_string)
140: DN.parse(dn_string).to_s
141: rescue DistinguishedNameInvalid
142: raise invalid_dn(dn_string, $!.reason)
143: end
# File lib/active_ldap/ldif.rb, line 251
251: def parse_modify_name_record(klass, dn, controls)
252: raise new_rdn_mark_is_missing unless @scanner.scan(/newrdn\b/u)
253: new_rdn = parse_attribute_value(false)
254: raise new_rdn_value_is_missing if new_rdn.nil?
255: raise separator_is_missing unless @scanner.scan_separator
256:
257: unless @scanner.scan(/deleteoldrdn:/u)
258: raise delete_old_rdn_mark_is_missing
259: end
260: @scanner.scan(FILL)
261: delete_old_rdn = @scanner.scan(/[01]/u)
262: raise delete_old_rdn_value_is_missing if delete_old_rdn.nil?
263: raise separator_is_missing unless @scanner.scan_separator
264:
265: if @scanner.scan(/newsuperior\b/u)
266: @scanner.scan(FILL)
267: new_superior = parse_attribute_value(false)
268: raise new_superior_value_is_missing if new_superior.nil?
269: new_superior = parse_dn(new_superior)
270: raise separator_is_missing unless @scanner.scan_separator
271: end
272: klass.new(dn, controls, new_rdn, delete_old_rdn, new_superior)
273: end
# File lib/active_ldap/ldif.rb, line 290
290: def parse_modify_record(dn, controls)
291: operations = []
292: loop do
293: spec = parse_modify_spec
294: break if spec.nil?
295: type, attribute, options, attributes = spec
296: case type
297: when "add"
298: klass = ModifyRecord::AddOperation
299: when "delete"
300: klass = ModifyRecord::DeleteOperation
301: when "replace"
302: klass = ModifyRecord::ReplaceOperation
303: else
304: unknown_modify_type(type)
305: end
306: operations << klass.new(attribute, options, attributes)
307: end
308: ModifyRecord.new(dn, controls, operations)
309: end
# File lib/active_ldap/ldif.rb, line 275
275: def parse_modify_spec
276: return nil unless @scanner.check(/(#{ATTRIBUTE_TYPE_CHARS}):/u)
277: type = @scanner[1]
278: unless @scanner.scan(/(?:add|delete|replace):/u)
279: raise unknown_modify_type(type)
280: end
281: @scanner.scan(FILL)
282: attribute, options = parse_attribute_description
283: raise separator_is_missing unless @scanner.scan_separator
284: attributes = parse_attributes {@scanner.check(/-/u)}
285: raise modify_spec_separator_is_missing unless @scanner.scan(/-/u)
286: raise separator_is_missing unless @scanner.scan_separator
287: [type, attribute, options, attributes]
288: end
# File lib/active_ldap/ldif.rb, line 189
189: def parse_options
190: options = []
191: while @scanner.scan(/;/u)
192: option = @scanner.scan(ATTRIBUTE_TYPE_CHARS)
193: raise option_is_missing if option.nil?
194: options << option
195: end
196: options
197: end
# File lib/active_ldap/ldif.rb, line 329
329: def parse_record
330: raise dn_mark_is_missing unless @scanner.scan(/dn:/u)
331: if @scanner.scan(/:/u)
332: @scanner.scan(FILL)
333: dn = read_base64_value
334: raise dn_is_missing if dn.nil?
335: dn = parse_dn(dn)
336: else
337: @scanner.scan(FILL)
338: dn = @scanner.scan(/#{SAFE_STRING}$/u)
339: if dn.nil?
340: partial_dn = @scanner.scan(SAFE_STRING)
341: raise dn_has_invalid_character(@scanner.check(/./u)) if partial_dn
342: raise dn_is_missing
343: end
344: dn = parse_dn(dn)
345: end
346:
347: raise separator_is_missing unless @scanner.scan_separator
348:
349: controls = parse_controls
350: change_type = parse_change_type
351: raise change_type_is_missing if change_type.nil? and !controls.empty?
352:
353: if change_type
354: parse_change_type_record(dn, controls, change_type)
355: else
356: attributes = parse_attributes(1)
357: ContentRecord.new(dn, attributes)
358: end
359: end
# File lib/active_ldap/ldif.rb, line 361
361: def parse_records
362: records = []
363: loop do
364: records << parse_record
365: break if @scanner.eos?
366: raise separator_is_missing if @scanner.scan_separator.nil?
367: end
368: records
369: end
# File lib/active_ldap/ldif.rb, line 116
116: def read_base64_value
117: value = @scanner.scan(/[a-zA-Z0-9\+\/=]+/u)
118: return nil if value.nil?
119: value.unpack("m")[0].chomp
120: end
# File lib/active_ldap/ldif.rb, line 122
122: def read_external_file
123: uri_string = @scanner.scan(URI::REGEXP::ABS_URI)
124: raise uri_is_missing if uri_string.nil?
125: uri = nil
126: begin
127: uri = URI.parse(uri_string)
128: rescue URI::Error
129: raise invalid_uri(uri_string, $!.message)
130: end
131:
132: if uri.scheme == "file"
133: File.open(uri.path, "rb").read
134: else
135: uri.read
136: end
137: end
# File lib/active_ldap/ldif.rb, line 387
387: def separator_is_missing
388: invalid_ldif(_("separator is missing"))
389: end
# File lib/active_ldap/ldif.rb, line 427
427: def unknown_change_type(change_type)
428: invalid_ldif(_("unknown change type: %s") % change_type)
429: end
# File lib/active_ldap/ldif.rb, line 471
471: def unknown_modify_type(type)
472: invalid_ldif(_("unknown modify type: %s") % type)
473: end
# File lib/active_ldap/ldif.rb, line 383
383: def unsupported_version(version)
384: invalid_ldif(_("unsupported version: %d") % version)
385: end
# File lib/active_ldap/ldif.rb, line 379
379: def version_number_is_missing
380: invalid_ldif(_("version number is missing"))
381: end