class ActiveLdap::Ldif::Parser

Constants

ATTRIBUTE_TYPE_CHARS
FILL
SAFE_CHAR
SAFE_INIT_CHAR
SAFE_STRING

Attributes

ldif[R]

Public Class Methods

new(source) click to toggle source
# File lib/active_ldap/ldif.rb, line 96
def initialize(source)
  @ldif = nil
  source = source.to_s if source.is_a?(LDIF)
  @source = source
end

Public Instance Methods

parse() click to toggle source
# File lib/active_ldap/ldif.rb, line 107
def parse
  return @ldif if @ldif

  @scanner = Scanner.new(@source)
  raise version_spec_is_missing unless @scanner.scan(/version:/)
  @scanner.scan(FILL)

  version = @scanner.scan(/\d+/)
  raise version_number_is_missing if version.nil?

  version = Integer(version)
  raise unsupported_version(version) if version != 1

  raise separator_is_missing unless @scanner.scan_separators

  records = parse_records

  @ldif = LDIF.new(records)
end

Private Instance Methods

attribute_spec_is_missing() click to toggle source
# File lib/active_ldap/ldif.rb, line 468
def attribute_spec_is_missing
  invalid_ldif(_("attribute spec is missing"))
end
attribute_type_is_missing() click to toggle source
# File lib/active_ldap/ldif.rb, line 428
def attribute_type_is_missing
  invalid_ldif(_("attribute type is missing"))
end
attribute_value_separator_is_missing() click to toggle source
# File lib/active_ldap/ldif.rb, line 436
def attribute_value_separator_is_missing
  invalid_ldif(_("':' is missing"))
end
change_type_is_missing() click to toggle source
# File lib/active_ldap/ldif.rb, line 452
def change_type_is_missing
  invalid_ldif(_("change type is missing"))
end
change_type_value_is_missing() click to toggle source
# File lib/active_ldap/ldif.rb, line 464
def change_type_value_is_missing
  invalid_ldif(_("change type value is missing"))
end
control_type_is_missing() click to toggle source
# File lib/active_ldap/ldif.rb, line 456
def control_type_is_missing
  invalid_ldif(_("control type is missing"))
end
criticality_is_missing() click to toggle source
# File lib/active_ldap/ldif.rb, line 460
def criticality_is_missing
  invalid_ldif(_("criticality is missing"))
end
delete_old_rdn_mark_is_missing() click to toggle source
# File lib/active_ldap/ldif.rb, line 480
def delete_old_rdn_mark_is_missing
  invalid_ldif(_("'deleteoldrdn:' is missing"))
end
delete_old_rdn_value_is_missing() click to toggle source
# File lib/active_ldap/ldif.rb, line 484
def delete_old_rdn_value_is_missing
  invalid_ldif(_("delete old RDN value is missing"))
end
dn_has_invalid_character(character) click to toggle source
# File lib/active_ldap/ldif.rb, line 424
def dn_has_invalid_character(character)
  invalid_ldif(_("DN has an invalid character: %s") % character)
end
dn_is_missing() click to toggle source
# File lib/active_ldap/ldif.rb, line 416
def dn_is_missing
  invalid_ldif(_("DN is missing"))
end
dn_mark_is_missing() click to toggle source
# File lib/active_ldap/ldif.rb, line 412
def dn_mark_is_missing
  invalid_ldif(_("'dn:' is missing"))
end
invalid_dn(dn_string, reason) click to toggle source
# File lib/active_ldap/ldif.rb, line 420
def invalid_dn(dn_string, reason)
  invalid_ldif(_("DN is invalid: %s: %s") % [dn_string, reason])
end
invalid_ldif(reason) click to toggle source
# File lib/active_ldap/ldif.rb, line 392
def invalid_ldif(reason)
  LdifInvalid.new(@source, reason, @scanner.line, @scanner.column)
end
invalid_uri(uri_string, message) click to toggle source
# File lib/active_ldap/ldif.rb, line 440
def invalid_uri(uri_string, message)
  invalid_ldif(_("URI is invalid: %s: %s") % [uri_string, message])
end
modify_spec_separator_is_missing() click to toggle source
# File lib/active_ldap/ldif.rb, line 444
def modify_spec_separator_is_missing
  invalid_ldif(_("'-' is missing"))
end
new_rdn_mark_is_missing() click to toggle source
# File lib/active_ldap/ldif.rb, line 472
def new_rdn_mark_is_missing
  invalid_ldif(_("'newrdn:' is missing"))
end
new_rdn_value_is_missing() click to toggle source
# File lib/active_ldap/ldif.rb, line 476
def new_rdn_value_is_missing
  invalid_ldif(_("new RDN value is missing"))
end
new_superior_value_is_missing() click to toggle source
# File lib/active_ldap/ldif.rb, line 488
def new_superior_value_is_missing
  invalid_ldif(_("new superior value is missing"))
end
option_is_missing() click to toggle source
# File lib/active_ldap/ldif.rb, line 432
def option_is_missing
  invalid_ldif(_("option is missing"))
end
parse_attribute() click to toggle source
# File lib/active_ldap/ldif.rb, line 201
def parse_attribute
  type, options = parse_attribute_description
  value = parse_attribute_value
  [type, options, value]
end
parse_attribute_description() click to toggle source
# File lib/active_ldap/ldif.rb, line 194
def parse_attribute_description
  type = @scanner.scan(ATTRIBUTE_TYPE_CHARS)
  raise attribute_type_is_missing if type.nil?
  options = parse_options
  [type, options]
end
parse_attribute_value(accept_external_file=true) click to toggle source
# File lib/active_ldap/ldif.rb, line 217
def parse_attribute_value(accept_external_file=true)
  raise attribute_value_separator_is_missing if @scanner.scan(/:/).nil?
  if @scanner.scan(/:/)
    @scanner.scan(FILL)
    read_base64_value
  elsif accept_external_file and @scanner.scan(/</)
    @scanner.scan(FILL)
    read_external_file
  else
    @scanner.scan(FILL)
    @scanner.scan(SAFE_STRING)
  end
end
parse_attributes(least=0, &block) click to toggle source
# File lib/active_ldap/ldif.rb, line 163
def parse_attributes(least=0, &block)
  i = 0
  attributes = {}
  block ||= Proc.new {@scanner.check_separator}
  loop do
    i += 1
    if i >= least
      break if block.call or @scanner.eos?
    end
    type, options, value = parse_attribute
    if @scanner.scan_separator.nil? and !@scanner.eos?
      raise separator_is_missing
    end
    attributes[type] ||= []
    container = attributes[type]
    options.each do |option|
      parent = container.find do |val|
        val.is_a?(Hash) and val.has_key?(option)
      end
      if parent.nil?
        parent = {option => []}
        container << parent
      end
      container = parent[option]
    end
    container << value
  end
  raise attribute_spec_is_missing if attributes.size < least
  attributes
end
parse_change_type() click to toggle source
# File lib/active_ldap/ldif.rb, line 256
def parse_change_type
  return nil unless @scanner.scan(/changetype:/)
  @scanner.scan(FILL)
  type = @scanner.check(ATTRIBUTE_TYPE_CHARS)
  raise change_type_value_is_missing if type.nil?
  unless @scanner.scan(/add|delete|modrdn|moddn|modify/)
    raise unknown_change_type(type)
  end

  raise separator_is_missing unless @scanner.scan_separator
  type
end
parse_change_type_record(dn, controls, change_type) click to toggle source
# File lib/active_ldap/ldif.rb, line 329
def parse_change_type_record(dn, controls, change_type)
  case change_type
  when "add"
    attributes = parse_attributes(1)
    AddRecord.new(dn, controls, attributes)
  when "delete"
    DeleteRecord.new(dn, controls)
  when "moddn"
    parse_modify_name_record(ModifyDNRecord, dn, controls)
  when "modrdn"
    parse_modify_name_record(ModifyRDNRecord, dn, controls)
  when "modify"
    parse_modify_record(dn, controls)
  else
    raise unknown_change_type(change_type)
  end
end
parse_control() click to toggle source
# File lib/active_ldap/ldif.rb, line 231
def parse_control
  return nil if @scanner.scan(/control:/).nil?
  @scanner.scan(FILL)
  type = @scanner.scan(/\d+(?:\.\d+)*/)
  raise control_type_is_missing if type.nil?
  criticality = nil
  if @scanner.scan(/ +/)
    criticality = @scanner.scan(/true|false/)
    raise criticality_is_missing if criticality.nil?
  end
  value = parse_attribute_value if @scanner.check(/:/)
  raise separator_is_missing unless @scanner.scan_separator
  ChangeRecord::Control.new(type, criticality, value)
end
parse_controls() click to toggle source
# File lib/active_ldap/ldif.rb, line 246
def parse_controls
  controls = []
  loop do
    control = parse_control
    break if control.nil?
    controls << control
  end
  controls
end
parse_dn(dn_string) click to toggle source
# File lib/active_ldap/ldif.rb, line 157
def parse_dn(dn_string)
  DN.parse(dn_string).to_s
rescue DistinguishedNameInvalid
  raise invalid_dn(dn_string, $!.reason)
end
parse_modify_name_record(klass, dn, controls) click to toggle source
# File lib/active_ldap/ldif.rb, line 269
def parse_modify_name_record(klass, dn, controls)
  raise new_rdn_mark_is_missing unless @scanner.scan(/newrdn\b/)
  new_rdn = parse_attribute_value(false)
  raise new_rdn_value_is_missing if new_rdn.nil?
  raise separator_is_missing unless @scanner.scan_separator

  unless @scanner.scan(/deleteoldrdn:/)
    raise delete_old_rdn_mark_is_missing
  end
  @scanner.scan(FILL)
  delete_old_rdn = @scanner.scan(/[01]/)
  raise delete_old_rdn_value_is_missing if delete_old_rdn.nil?
  raise separator_is_missing unless @scanner.scan_separator

  if @scanner.scan(/newsuperior\b/)
    @scanner.scan(FILL)
    new_superior = parse_attribute_value(false)
    raise new_superior_value_is_missing if new_superior.nil?
    new_superior = parse_dn(new_superior)
    raise separator_is_missing unless @scanner.scan_separator
  end
  klass.new(dn, controls, new_rdn, delete_old_rdn, new_superior)
end
parse_modify_record(dn, controls) click to toggle source
# File lib/active_ldap/ldif.rb, line 308
def parse_modify_record(dn, controls)
  operations = []
  loop do
    spec = parse_modify_spec
    break if spec.nil?
    type, attribute, options, attributes = spec
    case type
    when "add"
      klass = ModifyRecord::AddOperation
    when "delete"
      klass = ModifyRecord::DeleteOperation
    when "replace"
      klass = ModifyRecord::ReplaceOperation
    else
      unknown_modify_type(type)
    end
    operations << klass.new(attribute, options, attributes)
  end
  ModifyRecord.new(dn, controls, operations)
end
parse_modify_spec() click to toggle source
# File lib/active_ldap/ldif.rb, line 293
def parse_modify_spec
  return nil unless @scanner.check(/(#{ATTRIBUTE_TYPE_CHARS}):/)
  type = @scanner[1]
  unless @scanner.scan(/(?:add|delete|replace):/)
    raise unknown_modify_type(type)
  end
  @scanner.scan(FILL)
  attribute, options = parse_attribute_description
  raise separator_is_missing unless @scanner.scan_separator
  attributes = parse_attributes {@scanner.check(/-/)}
  raise modify_spec_separator_is_missing unless @scanner.scan(/-/)
  raise separator_is_missing unless @scanner.scan_separator
  [type, attribute, options, attributes]
end
parse_options() click to toggle source
# File lib/active_ldap/ldif.rb, line 207
def parse_options
  options = []
  while @scanner.scan(/;/)
    option = @scanner.scan(ATTRIBUTE_TYPE_CHARS)
    raise option_is_missing if option.nil?
    options << option
  end
  options
end
parse_record() click to toggle source
# File lib/active_ldap/ldif.rb, line 347
def parse_record
  raise dn_mark_is_missing unless @scanner.scan(/dn:/)
  if @scanner.scan(/:/)
    @scanner.scan(FILL)
    dn = read_base64_value
    raise dn_is_missing if dn.nil?
    dn = parse_dn(dn)
  else
    @scanner.scan(FILL)
    dn = @scanner.scan(/#{SAFE_STRING}$/)
    if dn.nil?
      partial_dn = @scanner.scan(SAFE_STRING)
      raise dn_has_invalid_character(@scanner.check(/./)) if partial_dn
      raise dn_is_missing
    end
    dn = parse_dn(dn)
  end

  raise separator_is_missing unless @scanner.scan_separator

  controls = parse_controls
  change_type = parse_change_type
  raise change_type_is_missing if change_type.nil? and !controls.empty?

  if change_type
    parse_change_type_record(dn, controls, change_type)
  else
    attributes = parse_attributes(1)
    ContentRecord.new(dn, attributes)
  end
end
parse_records() click to toggle source
# File lib/active_ldap/ldif.rb, line 379
def parse_records
  records = []
  loop do
    records << parse_record
    break if @scanner.eos?
    raise separator_is_missing if @scanner.scan_separator.nil?

    break if @scanner.eos?
    break if @scanner.scan_separators and @scanner.eos?
  end
  records
end
read_base64_value() click to toggle source
# File lib/active_ldap/ldif.rb, line 128
def read_base64_value
  value = @scanner.scan(/[a-zA-Z0-9\+\/=]+/)
  return nil if value.nil?
  encoding = value.encoding if value.respond_to?(:encoding)
  value = value.unpack("m")[0].chomp
  if value.respond_to?(:force_encoding)
    value.force_encoding(encoding)
    value.force_encoding("ascii-8bit") unless value.valid_encoding?
  end
  value
end
read_external_file() click to toggle source
# File lib/active_ldap/ldif.rb, line 140
def read_external_file
  uri_string = @scanner.scan(URI::ABS_URI)
  raise uri_is_missing if uri_string.nil?
  uri = nil
  begin
    uri = URI.parse(uri_string)
  rescue URI::Error
    raise invalid_uri(uri_string, $!.message)
  end

  if uri.scheme == "file"
    File.open(uri.path, "rb") {|file| file.read}
  else
    uri.read
  end
end
separator_is_missing() click to toggle source
# File lib/active_ldap/ldif.rb, line 408
def separator_is_missing
  invalid_ldif(_("separator is missing"))
end
unknown_change_type(change_type) click to toggle source
# File lib/active_ldap/ldif.rb, line 448
def unknown_change_type(change_type)
  invalid_ldif(_("unknown change type: %s") % change_type)
end
unknown_modify_type(type) click to toggle source
# File lib/active_ldap/ldif.rb, line 492
def unknown_modify_type(type)
  invalid_ldif(_("unknown modify type: %s") % type)
end
unsupported_version(version) click to toggle source
# File lib/active_ldap/ldif.rb, line 404
def unsupported_version(version)
  invalid_ldif(_("unsupported version: %d") % version)
end
version_number_is_missing() click to toggle source
# File lib/active_ldap/ldif.rb, line 400
def version_number_is_missing
  invalid_ldif(_("version number is missing"))
end
version_spec_is_missing() click to toggle source
# File lib/active_ldap/ldif.rb, line 396
def version_spec_is_missing
  invalid_ldif(_("version spec is missing"))
end