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