# class ActiveLdap::Base

Base

Base is the primary class which contains all of the core ActiveLdap functionality. It is meant to only ever be subclassed by extension classes.

### Constants

VALID_LDAP_MAPPING_OPTIONS

### Attributes

abstract_class[RW]

### Public Class Methods

abstract_class?() click to toggle source

    # File lib/active_ldap/base.rb, line 511
    def abstract_class?
      defined?(@abstract_class) && @abstract_class
    end

base() click to toggle source

::base

This method when included into Base provides an inheritable, overwritable configuration setting

This should be a string with the base of the ldap server such as 'dc=example,dc=com', and it should be overwritten by including configuration.rb into this class. When subclassing, the specified prefix will be concatenated.

    # File lib/active_ldap/base.rb, line 438
    def base
      @base ||= compute_base
    end

Also aliased as: parsed_base
base=(value) click to toggle source

    # File lib/active_ldap/base.rb, line 443
    def base=(value)
      self.inheritable_base = value
      @base = nil
    end

base_class() click to toggle source

    # File lib/active_ldap/base.rb, line 471
    def base_class
      if self == Base or superclass == Base
        self
      else
        superclass.base_class
      end
    end

class_local_attr_accessor(search_ancestors, *syms) click to toggle source

    # File lib/active_ldap/base.rb, line 302
        def self.class_local_attr_accessor(search_ancestors, *syms)
          syms.flatten.each do |sym|
            class_eval("          def self.#{sym}(search_superclasses=#{search_ancestors})
                @#{sym} ||= nil
                return @#{sym} if @#{sym}
                if search_superclasses
                  target = superclass
                  value = nil
                  loop do
                    break nil unless target.respond_to?(:#{sym})
                    value = target.#{sym}
                    break if value
                    target = target.superclass
                  end
                  value
                else
                  nil
                end
              end
              def #{sym}; self.class.#{sym}; end
              def self.#{sym}=(value); @#{sym} = value; end
    ", __FILE__, __LINE__ + 1)
          end
        end

class_of_active_ldap_descendant(klass) click to toggle source

    # File lib/active_ldap/base.rb, line 515
    def class_of_active_ldap_descendant(klass)
      if klass.superclass == Base or klass.superclass.abstract_class?
        klass
      elsif klass.superclass.nil?
        raise Error, _("%s doesn't belong in a hierarchy descending "                           "from ActiveLdap") % (name || to_s)
      else
        class_of_active_ldap_descendant(klass.superclass)
      end
    end

create(attributes=nil, &block) click to toggle source

    # File lib/active_ldap/base.rb, line 394
    def create(attributes=nil, &block)
      if attributes.is_a?(Array)
        attributes.collect {|attrs| create(attrs, &block)}
      else
        object = new(attributes, &block)
        object.save
        object
      end
    end

default_search_attribute() click to toggle source

    # File lib/active_ldap/base.rb, line 479
    def default_search_attribute
      dn_attribute
    end

establish_connection(config=nil) click to toggle source

::establish_connection is deprecated since 1.1.0. Please use ::setup_connection() instead.

    # File lib/active_ldap/base.rb, line 385
    def establish_connection(config=nil)
      message =
        _("ActiveLdap::Base.establish_connection has been deprecated "              "since 1.1.0. "              "Please use ActiveLdap::Base.setup_connection instead.")
      ActiveSupport::Deprecation.warn(message)
      setup_connection(config)
    end

human_name(options={}) click to toggle source

    # File lib/active_ldap/base.rb, line 537
    def human_name(options={})
      defaults = self_and_descendants_from_active_ldap.collect do |klass|
        if klass.name.blank?
          nil
        else
          :"#{klass.name.underscore}"
        end
      end
      defaults << name.humanize
      defaults = defaults.compact
      defaults.first || name || to_s
    end

inherited(sub_class) click to toggle source

Hide new in Base

Calls superclass method

    # File lib/active_ldap/base.rb, line 337
    def inherited(sub_class)
      super
      sub_class.module_eval do
        include GetTextSupport
      end
    end

inspect() click to toggle source
Calls superclass method

    # File lib/active_ldap/base.rb, line 483
    def inspect
      if self == Base
        super
      elsif abstract_class?
        "#{super}(abstract)"
      else
        detail = nil
        begin
          must = []
          may = []
          class_names = classes.collect do |object_class|
            must.concat(object_class.must)
            may.concat(object_class.may)
            object_class.name
          end
          detail = ["objectClass:<#{class_names.join(', ')}>",
                    "must:<#{inspect_attributes(must)}>",
                    "may:<#{inspect_attributes(may)}>"].join(", ")
        rescue ActiveLdap::ConnectionNotSetup
          detail = "not-connected"
        rescue ActiveLdap::Error
          detail = "connection-failure"
        end
        "#{super}(#{detail})"
      end
    end

ldap_mapping(options={}) click to toggle source

This class function is used to setup all mappings between the subclass and ldap for use in activeldap

Example:

    ldap_mapping :dn_attribute => 'uid', :prefix => 'ou=People',
                 :classes => ['top', 'posixAccount'],
                 :scope => :sub

    # File lib/active_ldap/base.rb, line 411
    def ldap_mapping(options={})
      options = options.symbolize_keys
      validate_ldap_mapping_options(options)

      self.dn_attribute = options[:dn_attribute] || default_dn_attribute
      self.dn_attribute = dn_attribute.to_s if dn_attribute.is_a?(Symbol)
      self.prefix = options[:prefix] || default_prefix
      self.scope = options[:scope]
      self.required_classes = options[:classes]
      self.recommended_classes = options[:recommended_classes]
      self.excluded_classes = options[:excluded_classes]
      self.sort_by = options[:sort_by]
      self.order = options[:order]

      public_class_method :new
    end

new(attributes=nil) { |self| ... } click to toggle source

new

Creates a new instance of Base initializing all class and all initialization. Defines local defaults. See examples If multiple values exist for #dn_attribute, the first one put here will be authoritative

    # File lib/active_ldap/base.rb, line 665
    def initialize(attributes=nil)
      init_base
      @new_entry = true
      initial_classes = required_classes | recommended_classes
      case attributes
      when nil
        self.classes = initial_classes
      when String, Array, DN
        self.classes = initial_classes
        self.dn = attributes
      when Hash
        attributes = attributes.clone
        classes = extract_object_class!(attributes)
        self.classes = classes | initial_classes
        self.attributes = attributes
      else
        format = _("'%s' must be either nil, DN value as ActiveLdap::DN, "                     "String or Array or attributes as Hash")
        raise ArgumentError, format % attributes.inspect
      end
      yield self if block_given?
      run_callbacks :initialize unless _initialize_callbacks.empty?
    end

parsed_base()
Alias for: base
prefix() click to toggle source

    # File lib/active_ldap/base.rb, line 448
    def prefix
      @prefix ||= inheritable_prefix and DN.parse(inheritable_prefix)
    end

prefix=(value) click to toggle source

    # File lib/active_ldap/base.rb, line 452
    def prefix=(value)
      self.inheritable_prefix = value
      @prefix = nil
      @base = nil
    end

scope=(scope) click to toggle source

    # File lib/active_ldap/base.rb, line 459
    def scope=(scope)
      validate_scope(scope)
      self.scope_without_validation = scope
    end

Also aliased as: scope_without_validation=
scope_without_validation=(scope)
Alias for: scope=
self_and_descendants_from_active_ldap() click to toggle source

    # File lib/active_ldap/base.rb, line 526
    def self_and_descendants_from_active_ldap
      klass = self
      classes = [klass]
      while klass != klass.base_class
        classes << klass = klass.superclass
      end
      classes
    rescue
      [self]
    end

setup_connection(config=nil) click to toggle source

Set LDAP connection configuration up. It doesn't connect and bind to LDAP server. A connection to LDAP server is created when it's needed.

## `config`¶ ↑

`config` must be a hash that may contain any of the following fields: :password_block, :logger, :host, :port, :base, :bind_dn, :try_sasl, :allow_anonymous :bind_dn specifies the DN to bind with. :password_block specifies a Proc object that will yield a String to

    be used as the password when called.

:logger specifies a logger object (Logger, Log4r::Logger and s on) :host sets the LDAP server hostname :port sets the LDAP server port :base overwrites ::base - this affects EVERYTHING :try_sasl indicates that a SASL bind should be attempted when binding

    to the server (default: false)

:sasl_mechanisms is an array of SASL mechanism to try

    (default: ["GSSAPI", "CRAM-MD5", "EXTERNAL"])

:allow_anonymous indicates that a true anonymous bind is allowed when

    trying to bind to the server (default: true)

:retries - indicates the number of attempts to reconnect that will be

    undertaken when a stale connection occurs. -1 means infinite.

:sasl_quiet - if true, sets @sasl_quiet on the Ruby/LDAP connection :method - whether to use :ssl, :tls, or :plain (unencrypted) :retry_wait - seconds to wait before retrying a connection :scope - dictates how to find objects. ONELEVEL by default to

    avoid dn_attr collisions across OUs. Think before changing.

:timeout - time in seconds - defaults to disabled. This CAN interrupt

    search() requests. Be warned.

:retry_on_timeout - whether to reconnect when timeouts occur. Defaults

    to true

See lib/active_ldap/configuration.rb for defaults for each option

Calls superclass method ActiveLdap::Connection#setup_connection

    # File lib/active_ldap/base.rb, line 377
    def setup_connection(config=nil)
      super
      ensure_logger
      nil
    end

validate_scope(scope) click to toggle source

    # File lib/active_ldap/base.rb, line 464
    def validate_scope(scope)
      scope = scope.to_sym if scope.is_a?(String)
      return if scope.nil? or scope.is_a?(Symbol)
      raise ConfigurationError,
              _("scope '%s' must be a Symbol") % scope.inspect
    end

### Private Class Methods

compute_base() click to toggle source

    # File lib/active_ldap/base.rb, line 630
    def compute_base
      _base = inheritable_base
      _base = configuration[:base] if _base.nil? and configuration
      if _base.nil?
        target = superclass
        loop do
          break unless target.respond_to?(:base)
          _base = target.base
          break if _base
          target = target.superclass
        end
      end
      _prefix = prefix

      _base ||= connection.naming_contexts.first
      return _prefix if _base.blank?

      _base = DN.parse(_base)
      _base = _prefix + _base if _prefix
      _base
    end

default_dn_attribute() click to toggle source

    # File lib/active_ldap/base.rb, line 613
    def default_dn_attribute
      dn_attribute = nil
      parent_class = ancestors[1]
      if parent_class.respond_to?(:dn_attribute)
        dn_attribute = parent_class.dn_attribute
      end
      dn_attribute || "cn"
    end

default_prefix() click to toggle source

    # File lib/active_ldap/base.rb, line 622
    def default_prefix
      if name.blank?
        nil
      else
        "ou=#{name.demodulize.pluralize}"
      end
    end

ensure_logger() click to toggle source

    # File lib/active_ldap/base.rb, line 581
    def ensure_logger
      @@logger ||= configuration[:logger]
      # Setup default logger to console
      if @@logger.nil?
        require 'logger'
        @@logger = Logger.new(STDERR)
        @@logger.progname = 'ActiveLdap'
        @@logger.level = Logger::ERROR
      end
      configuration[:logger] ||= @@logger
    end

inspect_attribute(attribute) click to toggle source

    # File lib/active_ldap/base.rb, line 563
    def inspect_attribute(attribute)
      syntax = attribute.syntax
      result = "#{attribute.name}"
      if syntax and !syntax.description.blank?
        result << ": #{syntax.description}"
      end
      properties = []
      properties << "read-only" if attribute.read_only?
      properties << "binary" if attribute.binary?
      properties << "binary-required" if attribute.binary_required?
      result << "(#{properties.join(', ')})" unless properties.empty?
      result
    end

inspect_attributes(attributes) click to toggle source

    # File lib/active_ldap/base.rb, line 551
    def inspect_attributes(attributes)
      inspected_attribute_names = {}
      attributes.collect do |attribute|
        if inspected_attribute_names.has_key?(attribute.name)
          nil
        else
          inspected_attribute_names[attribute.name] = true
          inspect_attribute(attribute)
        end
      end.compact.join(', ')
    end

instantiate(args) click to toggle source

    # File lib/active_ldap/base.rb, line 593
    def instantiate(args)
      dn, attributes, options = args
      options ||= {}
      if self.class == Class
        klass = self.ancestors[0].to_s.split(':').last
        real_klass = self.ancestors[0]
      else
        klass = self.class.to_s.split(':').last
        real_klass = self.class
      end

      obj = real_klass.allocate
      conn = options[:connection] || connection
      obj.connection = conn if conn != connection
      obj.instance_eval do
        initialize_by_ldap_data(dn, attributes)
      end
      obj
    end

validate_ldap_mapping_options(options) click to toggle source

    # File lib/active_ldap/base.rb, line 577
    def validate_ldap_mapping_options(options)
      options.assert_valid_keys(VALID_LDAP_MAPPING_OPTIONS)
    end

### Public Instance Methods

==(comparison_object) click to toggle source

Returns true if the `comparison_object` is the same object, or is of the same type and has the same dn.

    # File lib/active_ldap/base.rb, line 691
    def ==(comparison_object)
      comparison_object.equal?(self) or
        (comparison_object.instance_of?(self.class) and
         comparison_object.dn == dn and
         !comparison_object.new_entry?)
    end

[](name, force_array=false) click to toggle source

    # File lib/active_ldap/base.rb, line 878
    def [](name, force_array=false)
      if name == "dn"
        array_of(dn, force_array)
      else
        get_attribute(name, force_array)
      end
    end

[]=(name, value) click to toggle source

    # File lib/active_ldap/base.rb, line 886
    def []=(name, value)
      set_attribute(name, value)
    end

assign_attributes(new_attributes) click to toggle source

    # File lib/active_ldap/base.rb, line 824
    def assign_attributes(new_attributes)
      return if new_attributes.blank?

      _schema = _local_entry_attribute = nil
      targets = sanitize_for_mass_assignment(new_attributes)
      targets.each do |key, value|
        setter = "#{key}="
        unless respond_to?(setter)
          _schema ||= schema
          attribute = _schema.attribute(key)
          next if attribute.id.nil?
          _local_entry_attribute ||= local_entry_attribute
          _local_entry_attribute.register(attribute)
        end
        send(setter, value)
      end
    end

attribute_names(normalize=false) click to toggle source

attributes

Return attribute methods so that a program can determine available attributes dynamically without schema awareness

    # File lib/active_ldap/base.rb, line 733
    def attribute_names(normalize=false)
      entry_attribute.names(normalize)
    end

attribute_present?(name) click to toggle source

    # File lib/active_ldap/base.rb, line 737
    def attribute_present?(name)
      values = get_attribute(name, true)
      !values.empty? or values.any? {|x| !(x and x.empty?)}
    end

attributes() click to toggle source

This returns the key value pairs in @data with all values cloned

    # File lib/active_ldap/base.rb, line 808
    def attributes
      @simplified_data ||= simplify_data(@data)
      @simplified_data.clone
    end

attributes=(new_attributes) click to toggle source

This allows a bulk update to the attributes of a record without forcing an immediate save or validation.

It is unwise to attempt objectClass updates this way. Also be sure to only pass in key-value pairs of your choosing. Do not let URL/form hackers supply the keys.

    # File lib/active_ldap/base.rb, line 819
    def attributes=(new_attributes)
      return if new_attributes.blank?
      assign_attributes(new_attributes)
    end

base() click to toggle source

    # File lib/active_ldap/base.rb, line 944
    def base
      @base ||= compute_base
    end

base=(object_local_base) click to toggle source

    # File lib/active_ldap/base.rb, line 948
    def base=(object_local_base)
      ensure_update_dn
      @dn = nil
      @base = nil
      @base_value = object_local_base
    end

bind(config_or_password={}, config_or_ignore=nil, &block) click to toggle source

    # File lib/active_ldap/base.rb, line 890
    def bind(config_or_password={}, config_or_ignore=nil, &block)
      if config_or_password.is_a?(String)
        config = (config_or_ignore || {}).merge(:password => config_or_password)
      else
        config = config_or_password
      end
      config = {:bind_dn => dn, :allow_anonymous => false}.merge(config)
      config[:password_block] ||= block if block_given?
      setup_connection(config)

      before_connection = @connection
      begin
        @connection = nil
        connection.connect
        @connection = connection
        clear_connection_based_cache
        clear_association_cache
      rescue ActiveLdap::Error
        remove_connection
        @connection = before_connection
        raise
      end
      true
    end

clear_connection_based_cache() click to toggle source

    # File lib/active_ldap/base.rb, line 915
    def clear_connection_based_cache
      @schema = nil
      @local_entry_attribute = nil
      clear_object_class_based_cache
    end

clear_object_class_based_cache() click to toggle source

    # File lib/active_ldap/base.rb, line 921
    def clear_object_class_based_cache
      @entry_attribute = nil
      @real_names = {}
      @changed_attributes.reject! do |key, _|
        not attribute_method?(key)
      end
    end

clear_removed_attributes_data(removed_attributes) click to toggle source

    # File lib/active_ldap/base.rb, line 929
    def clear_removed_attributes_data(removed_attributes)
      return if removed_attributes.empty?
      removed_entry_attribute = EntryAttribute.new(nil, [])
      removed_attributes.each do |attribute|
        removed_entry_attribute.register(attribute)
      end
      @data.reject! do |key, _|
        removed_entry_attribute.exist?(key)
      end
    end

default_search_attribute() click to toggle source

    # File lib/active_ldap/base.rb, line 784
    def default_search_attribute
      self.class.default_search_attribute
    end

delete_all(options={}) click to toggle source
Calls superclass method

    # File lib/active_ldap/base.rb, line 965
    def delete_all(options={})
      super({:base => dn}.merge(options || {}))
    end

destroy_all(options={}) click to toggle source
Calls superclass method

    # File lib/active_ldap/base.rb, line 969
    def destroy_all(options={})
      super({:base => dn}.merge(options || {}))
    end

dn() click to toggle source

dn

Return the authoritative dn

    # File lib/active_ldap/base.rb, line 753
    def dn
      @dn ||= compute_dn
    end

dn=(value) click to toggle source

    # File lib/active_ldap/base.rb, line 772
    def dn=(value)
      set_attribute(dn_attribute_with_fallback, value)
    end

Also aliased as: id=
dn_attribute() click to toggle source

    # File lib/active_ldap/base.rb, line 778
    def dn_attribute
      ensure_update_dn
      _dn_attribute = @dn_attribute || dn_attribute_of_class
      to_real_attribute_name(_dn_attribute) || _dn_attribute
    end

Also aliased as: dn_attribute_of_class
dn_attribute_of_class()
Alias for: dn_attribute
eql?(comparison_object) click to toggle source

Delegates to ==

    # File lib/active_ldap/base.rb, line 699
    def eql?(comparison_object)
      self == (comparison_object)
    end

exist?() click to toggle source

exist?

Return whether the entry exists in LDAP or not

    # File lib/active_ldap/base.rb, line 745
    def exist?
      self.class.exists?(dn)
    end

Also aliased as: exists?
exists?()
Alias for: exist?
has_attribute?(name, except=[])
Alias for: have_attribute?
hash() click to toggle source

Delegates to id in order to allow two records of the same type and id to work with something like:

    [ User.find("a"), User.find("b"), User.find("c") ] &
      [ User.find("a"), User.find("d") ] # => [ User.find("a") ]

Calls superclass method

    # File lib/active_ldap/base.rb, line 707
    def hash
      return super if @_hashing # workaround for GetText :<
      _dn = nil
      begin
        @_hashing = true
        _dn = dn
      rescue DistinguishedNameInvalid, DistinguishedNameNotSetError
        return super
      ensure
        @_hashing = false
      end
      _dn.hash
    end

have_attribute?(name, except=[]) click to toggle source

    # File lib/active_ldap/base.rb, line 872
    def have_attribute?(name, except=[])
      real_name = to_real_attribute_name(name)
      !real_name.nil? and !except.include?(real_name)
    end

Also aliased as: has_attribute?
id() click to toggle source

    # File lib/active_ldap/base.rb, line 757
    def id
      get_attribute(dn_attribute_with_fallback)
    end

id=(value)
Alias for: dn=
inspect() click to toggle source

    # File lib/active_ldap/base.rb, line 973
    def inspect
      object_classes = entry_attribute.object_classes
      inspected_object_classes = object_classes.collect do |object_class|
        object_class.name
      end.join(', ')
      must_attributes = must.collect(&:name).sort.join(', ')
      may_attributes = may.collect(&:name).sort.join(', ')
      inspected_attributes = attribute_names.sort.collect do |name|
        inspect_attribute(name)
      end.join(', ')
      result = "\#<#{self.class} objectClass:<#{inspected_object_classes}>, "
      result << "must:<#{must_attributes}>, may:<#{may_attributes}>, "
      result << "#{inspected_attributes}>"
      result
    end

may() click to toggle source

    # File lib/active_ldap/base.rb, line 721
    def may
      entry_attribute.may
    end

must() click to toggle source

    # File lib/active_ldap/base.rb, line 725
    def must
      entry_attribute.must
    end

schema() click to toggle source
Calls superclass method ActiveLdap::Connection#schema

    # File lib/active_ldap/base.rb, line 940
    def schema
      @schema ||= super
    end

scope() click to toggle source

    # File lib/active_ldap/base.rb, line 956
    def scope
      @scope || scope_of_class
    end

Also aliased as: scope_of_class
scope=(scope) click to toggle source

    # File lib/active_ldap/base.rb, line 960
    def scope=(scope)
      self.class.validate_scope(scope)
      @scope = scope
    end

scope_of_class()
Alias for: scope
to_key() click to toggle source

Returns this entity’s dn wrapped in an Array or nil if the entity' s dn is not set.

    # File lib/active_ldap/base.rb, line 766
    def to_key
      [dn]
    rescue DistinguishedNameNotSetError
      nil
    end

to_ldif() click to toggle source

    # File lib/active_ldap/base.rb, line 846
    def to_ldif
      Ldif.new([to_ldif_record]).to_s
    end

to_ldif_record() click to toggle source
Calls superclass method

    # File lib/active_ldap/base.rb, line 842
    def to_ldif_record
      super(dn, normalize_data(@data))
    end

to_param() click to toggle source

    # File lib/active_ldap/base.rb, line 761
    def to_param
      id
    end

to_s() click to toggle source

    # File lib/active_ldap/base.rb, line 868
    def to_s
      to_ldif
    end

to_xml(options={}) click to toggle source

    # File lib/active_ldap/base.rb, line 850
    def to_xml(options={})
      options = options.dup
      options[:root] ||= (self.class.name || '').underscore
      options[:root] = 'anonymous' if options[:root].blank?
      [:only, :except].each do |attribute_names_key|
        names = options[attribute_names_key]
        next if names.nil?
        options[attribute_names_key] = names.collect do |name|
          if name.to_s.downcase == "dn"
            "dn"
          else
            to_real_attribute_name(name)
          end
        end.compact
      end
      XML.new(dn, normalize_data(@data), schema).to_s(options)
    end

update_attribute(name, value) click to toggle source

Updates a given attribute and saves immediately

    # File lib/active_ldap/base.rb, line 789
    def update_attribute(name, value)
      send("#{name}=", value)
      save
    end

update_attributes(attrs) click to toggle source

This performs a bulk update of attributes and immediately calls save.

    # File lib/active_ldap/base.rb, line 796
    def update_attributes(attrs)
      self.attributes = attrs
      save
    end

update_attributes!(attrs) click to toggle source

    # File lib/active_ldap/base.rb, line 801
    def update_attributes!(attrs)
      self.attributes = attrs
      save!
    end

### Private Instance Methods

array_of(value, to_a=true) click to toggle source

#array_of

Returns the array form of a value, or not an array if false is passed in.

    # File lib/active_ldap/base.rb, line 1277
    def array_of(value, to_a=true)
      case value
      when Array
        if to_a or value.size > 1
          value.collect {|v| array_of(v, false)}.compact
        else
          if value.empty?
            nil
          else
            array_of(value.first, to_a)
          end
        end
      when Hash
        if to_a
          [value]
        else
          result = {}
          value.each {|k, v| result[k] = array_of(v, to_a)}
          result
        end
      else
        to_a ? [value] : value
      end
    end

attribute_name_resolvable_without_connection?() click to toggle source

    # File lib/active_ldap/base.rb, line 1019
    def attribute_name_resolvable_without_connection?
      @entry_attribute and @local_entry_attribute
    end

collect_all_attributes(data) click to toggle source

    # File lib/active_ldap/base.rb, line 1374
    def collect_all_attributes(data)
      dn_attr = dn_attribute
      dn_value = data[dn_attr]

      attributes = []
      attributes.push([dn_attr, dn_value])

      oc_value = data['objectClass']
      attributes.push(['objectClass', oc_value])
      except_keys = ['objectClass', dn_attr].collect(&:downcase)
      data.each do |key, value|
        next if except_keys.include?(key.downcase)
        value = self.class.remove_blank_value(value)
        next if self.class.blank_value?(value)

        attributes.push([key, value])
      end

      attributes
    end

collect_modified_attributes(ldap_data, data) click to toggle source

    # File lib/active_ldap/base.rb, line 1330
    def collect_modified_attributes(ldap_data, data)
      klass = self.class
      _dn_attribute = dn_attribute
      new_dn_value = nil
      attributes = []

      # Now that all the options will be treated as unique attributes
      # we can see what's changed and add anything that is brand-spankin'
      # new.
      ldap_data.each do |k, v|
        value = data[k] || []

        next if v == value

        value = klass.remove_blank_value(value) || []
        next if v == value

        if klass.blank_value?(value) and
            schema.attribute(k).binary_required?
          value = [{'binary' => []}]
        end
        if k == _dn_attribute
          new_dn_value = value[0]
        else
          attributes.push([:replace, k, value])
        end
      end

      data.each do |k, v|
        value = v || []
        next if ldap_data.has_key?(k)

        value = klass.remove_blank_value(value) || []
        next if klass.blank_value?(value)

        # Detect subtypes and account for them
        # REPLACE will function like ADD, but doesn't hit EQUALITY problems
        # TODO: Added equality(attr) to Schema
        attributes.push([:replace, k, value])
      end

      [new_dn_value, attributes]
    end

compute_base() click to toggle source

    # File lib/active_ldap/base.rb, line 1262
    def compute_base
      base_of_class = self.class.base
      if @base_value.nil?
        base_of_class
      else
        base_of_object = DN.parse(@base_value)
        base_of_object += base_of_class if base_of_class
        base_of_object
      end
    end

compute_dn() click to toggle source

    # File lib/active_ldap/base.rb, line 1246
    def compute_dn
      return base if @dn_is_base

      ensure_update_dn
      dn_value = id
      if dn_value.nil?
        format = _("%s's DN attribute (%s) isn't set")
        message = format % [self.inspect, dn_attribute]
        raise DistinguishedNameNotSetError.new, message
      end
      dn_value = DN.escape_value(dn_value.to_s)
      _base = base
      _base = nil if _base.blank?
      DN.parse(["#{dn_attribute}=#{dn_value}", _base].compact.join(","))
    end

dn_attribute_with_fallback() click to toggle source

    # File lib/active_ldap/base.rb, line 990
    def dn_attribute_with_fallback
      begin
        dn_attribute
      rescue DistinguishedNameInvalid
        _dn_attribute = @dn_attribute || dn_attribute_of_class
        _dn_attribute = to_real_attribute_name(_dn_attribute) || _dn_attribute
        raise if _dn_attribute.nil?
        _dn_attribute
      end
    end

enforce_type(key, value) click to toggle source

#enforce_type

#enforce_type applies your changes without attempting to write to LDAP. This means that if you set userCertificate to somebinary value, it will wrap it up correctly.

    # File lib/active_ldap/base.rb, line 1128
    def enforce_type(key, value)
      # Enforce attribute value formatting
      normalize_attribute(key, value)[1]
    end

ensure_update_dn() click to toggle source

    # File lib/active_ldap/base.rb, line 1236
    def ensure_update_dn
      return unless need_update_dn?
      @mutex.synchronize do
        if @dn_split_value
          update_dn(*@dn_split_value)
          @dn_split_value = nil
        end
      end
    end

entry_attribute() click to toggle source

    # File lib/active_ldap/base.rb, line 1023
    def entry_attribute
      @entry_attribute ||=
        connection.entry_attribute(find_object_class_values(@data) || [])
    end

extract_object_class!(attributes) click to toggle source

    # File lib/active_ldap/base.rb, line 1032
    def extract_object_class!(attributes)
      classes = []
      attributes.keys.each do |key|
        string_key = key.to_s
        if /\Aobject_?class\z/i =~ string_key
          classes.concat(attributes[key].to_a)
          attributes.delete(key)
        end
      end
      classes
    end

find_object_class_values(data) click to toggle source

    # File lib/active_ldap/base.rb, line 1015
    def find_object_class_values(data)
      data["objectClass"] || data["objectclass"]
    end

init_base() click to toggle source

    # File lib/active_ldap/base.rb, line 1059
    def init_base
      init_instance_variables
    end

init_instance_variables() click to toggle source

    # File lib/active_ldap/base.rb, line 1133
    def init_instance_variables
      @mutex = Mutex.new
      @data = {} # where the r/w entry data is stored
      @ldap_data = {} # original ldap entry data
      @dn_attribute = nil
      @base = nil
      @scope = nil
      @dn = nil
      @dn_is_base = false
      @dn_split_value = nil
      @connection ||= nil
      @_hashing = false
      @previously_changed = []
      @changed_attributes = {}
      clear_connection_based_cache
    end

initialize_attributes(attributes) click to toggle source

    # File lib/active_ldap/base.rb, line 1083
    def initialize_attributes(attributes)
      _schema = _local_entry_attribute = nil
      targets = sanitize_for_mass_assignment(attributes)
      targets.each do |key, value|
        unless have_attribute?(key)
          _schema ||= schema
          attribute = _schema.attribute(key)
          _local_entry_attribute ||= local_entry_attribute
          _local_entry_attribute.register(attribute)
        end
        set_attribute(key, value)
      end
      @changed_attributes.clear
    end

initialize_by_ldap_data(dn, attributes) { |self| ... } click to toggle source

    # File lib/active_ldap/base.rb, line 1063
    def initialize_by_ldap_data(dn, attributes)
      init_base
      dn = Compatible.convert_to_utf8_encoded_object(dn)
      attributes = Compatible.convert_to_utf8_encoded_object(attributes)
      @original_dn = dn.clone
      @dn = dn
      @base = nil
      @base_value = nil
      @new_entry = false
      @dn_is_base = false
      @ldap_data = attributes
      attributes = attributes.clone
      classes = extract_object_class!(attributes)
      self.classes = classes
      self.dn = dn
      remove_dn_attribute!(attributes)
      initialize_attributes(attributes)
      yield self if block_given?
    end

inspect_attribute(name) click to toggle source

    # File lib/active_ldap/base.rb, line 1001
    def inspect_attribute(name)
      values = get_attribute(name, true)
      values.collect do |value|
        if value.is_a?(String) and value.length > 50
          "#{value[0, 50]}...".inspect
        elsif value.is_a?(Date) || value.is_a?(Time)
          "#{value.to_s(:db)}"
        else
          value.inspect
        end
      end
      "#{name}: #{values.inspect}"
    end

instantiate(args) click to toggle source

    # File lib/active_ldap/base.rb, line 1099
    def instantiate(args)
      dn, attributes, options = args
      options ||= {}

      obj = self.class.allocate
      obj.connection = options[:connection] || @connection
      obj.instance_eval do
        initialize_by_ldap_data(dn, attributes)
      end
      obj
    end

local_entry_attribute() click to toggle source

    # File lib/active_ldap/base.rb, line 1028
    def local_entry_attribute
      @local_entry_attribute ||= connection.entry_attribute([])
    end

need_update_dn?() click to toggle source

    # File lib/active_ldap/base.rb, line 1232
    def need_update_dn?
      not @dn_split_value.nil?
    end

normalize_data(data, except=[]) click to toggle source

    # File lib/active_ldap/base.rb, line 1302
    def normalize_data(data, except=[])
      _schema = schema
      result = {}
      data.each do |key, values|
        next if except.include?(key)
        real_name = to_real_attribute_name(key)
        next if real_name and except.include?(real_name)
        real_name ||= key
        next if _schema.attribute(real_name).id.nil?
        result[real_name] ||= []
        result[real_name].concat(enforce_type(real_name, values))
      end
      result
    end

prepare_data_for_saving() { |data, ldap_data| ... } click to toggle source

    # File lib/active_ldap/base.rb, line 1395
    def prepare_data_for_saving
      # Expand subtypes to real ldap_data attributes
      # We can't reuse @ldap_data because an exception would leave
      # an object in an unknown state
      ldap_data = normalize_data(@ldap_data)

      # Expand subtypes to real data attributes, but leave @data alone
      object_classes = find_object_class_values(@ldap_data) || []
      original_attributes =
        connection.entry_attribute(object_classes).names
      bad_attrs = original_attributes - entry_attribute.names
      data = normalize_data(@data, bad_attrs)

      success = yield(data, ldap_data)

      if success
        @ldap_data = data.clone
        # Delete items disallowed by objectclasses.
        # They should have been removed from ldap.
        bad_attrs.each do |remove_me|
          @ldap_data.delete(remove_me)
        end
        @original_dn = dn.clone
      end

      success
    end

register_new_dn_attribute(name, value) click to toggle source

    # File lib/active_ldap/base.rb, line 1150
    def register_new_dn_attribute(name, value)
      @dn = nil
      @dn_is_base = false
      if value.blank?
        @dn_split_value = nil
        [name, nil]
      else
        new_name, new_value, raw_new_value, new_bases = split_dn_value(value)
        @dn_split_value = [new_name, new_value, new_bases]
        if new_name.nil? and new_value.nil?
          new_name, raw_new_value = new_bases[0].to_a[0]
        end
        [to_real_attribute_name(new_name) || name,
         raw_new_value || value]
      end
    end

remove_dn_attribute!(attributes) click to toggle source

    # File lib/active_ldap/base.rb, line 1044
    def remove_dn_attribute!(attributes)
      _dn_attribute = dn_attribute
      attributes.keys.each do |key|
        case key
        when "id", :id, "dn", :dn
          attributes.delete(key)
        else
          normalized_key = to_real_attribute_name(key) || key
          if normalized_key == _dn_attribute
            attributes.delete(key)
          end
        end
      end
    end

simplify_data(data) click to toggle source

    # File lib/active_ldap/base.rb, line 1317
    def simplify_data(data)
      _schema = schema
      result = {}
      data.each do |key, values|
        attribute = _schema.attribute(key)
        if attribute.single_value? and values.is_a?(Array) and values.size == 1
          values = values[0]
        end
        result[key] = type_cast(attribute, values)
      end
      result
    end

split_dn_value(value) click to toggle source

    # File lib/active_ldap/base.rb, line 1194
    def split_dn_value(value)
      dn_value = relative_dn_value = nil
      value = value.first if value.is_a?(Array) and value.size == 1
      dn_value = value if value.is_a?(DN)
      begin
        dn_value ||= DN.parse(value)
      rescue DistinguishedNameInvalid
        begin
          dn_value = DN.parse("#{dn_attribute}=#{value}")
        rescue DistinguishedNameInvalid
          return [nil, value, value, []]
        end
      end

      val = bases = nil
      begin
        relative_dn_value = dn_value
        base_of_class = self.class.base
        relative_dn_value -= base_of_class if base_of_class
        if relative_dn_value.rdns.empty?
          val = []
          bases = dn_value.rdns
        else
          val, *bases = relative_dn_value.rdns
        end
      rescue ArgumentError
        val, *bases = dn_value.rdns
      end

      dn_attribute_name, dn_attribute_value = val.to_a[0]
      escaped_dn_attribute_value = nil
      unless dn_attribute_value.nil?
        escaped_dn_attribute_value = DN.escape_value(dn_attribute_value)
      end
      [dn_attribute_name, escaped_dn_attribute_value,
       dn_attribute_value, bases]
    end

to_real_attribute_name(name, allow_normalized_name=true) click to toggle source

    # File lib/active_ldap/base.rb, line 1111
    def to_real_attribute_name(name, allow_normalized_name=true)
      return name if name.nil?
      if allow_normalized_name
        entry_attribute.normalize(name, allow_normalized_name) ||
          local_entry_attribute.normalize(name, allow_normalized_name)
      else
        @real_names[name] ||=
          entry_attribute.normalize(name, false) ||
          local_entry_attribute.normalize(name, false)
      end
    end

update_dn(new_name, new_value, bases) click to toggle source

    # File lib/active_ldap/base.rb, line 1167
    def update_dn(new_name, new_value, bases)
      if new_name.nil? and new_value.nil?
        @dn_is_base = true
        @base = nil
        @base_value = nil
        attr, value = bases[0].to_a[0]
        @dn_attribute = attr
        _ = value # for suppress a warning on Ruby 1.9.3
      else
        new_name ||= @dn_attribute || dn_attribute_of_class
        new_name = to_real_attribute_name(new_name)
        if new_name.nil?
          new_name = @dn_attribute || dn_attribute_of_class
          new_name = to_real_attribute_name(new_name)
        end
        new_bases = bases.empty? ? nil : DN.new(*bases).to_s
        dn_components = ["#{new_name}=#{new_value}",
                         new_bases,
                         self.class.base.to_s]
        dn_components = dn_components.find_all {|component| !component.blank?}
        DN.parse(dn_components.join(','))
        @base = nil
        @base_value = new_bases
        @dn_attribute = new_name
      end
    end