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