Module: Ldaptic

Defined in:
lib/ldaptic.rb,
lib/ldaptic/dn.rb,
lib/ldaptic/entry.rb,
lib/ldaptic/errors.rb,
lib/ldaptic/escape.rb,
lib/ldaptic/filter.rb,
lib/ldaptic/schema.rb,
lib/ldaptic/methods.rb,
lib/ldaptic/adapters.rb,
lib/ldaptic/syntaxes.rb,
lib/ldaptic/error_set.rb,
lib/ldaptic/attribute_set.rb,
lib/ldaptic/matching_rules.rb,
lib/ldaptic/adapters/abstract_adapter.rb,
lib/ldaptic/adapters/net_ldap_adapter.rb,
lib/ldaptic/adapters/ldap_conn_adapter.rb,
lib/ldaptic/adapters/active_directory_adapter.rb

Overview

Getting started

See the methods of the Ldaptic module (below) for information on connecting.

See the Ldaptic::Methods module for information on searching with your connection object.

Search results are Ldaptic::Entry objects. See the documentation for this class for information on manipulating and updating them, as well as creating new entries.

Defined Under Namespace

Modules: Adapters, Errors, Filter, MatchingRules, Methods, Schema, Syntaxes Classes: AttributeSet, Class, DN, Entry, EntryNotSaved, Error, ErrorSet, Module, RDN, ServerError

Constant Summary collapse

SCOPES =
{
  :base     => 0, # ::LDAP::LDAP_SCOPE_BASE,
  :onelevel => 1, # ::LDAP::LDAP_SCOPE_ONELEVEL,
  :subtree  => 2  # ::LDAP::LDAP_SCOPE_SUBTREE
}
SYNTAXES =
{}

Class Method Summary collapse

Class Method Details

.Class(options = {}) ⇒ Object Also known as: Namespace

The core constructor of Ldaptic. This method returns an anonymous class which can then be inherited from.

The new class is not intended to be instantiated, instead serving as a namespace. Included in this namespace is a set of class methods, as found in Ldaptic::Methods, and a class hierarchy mirroring the object classes found on the server.

options = {
  :adapter  => :active_directory,
  :host     => "pdc.mycompany.com",
  :username => "[email protected]",
  :password => "mypassword"
}

class MyCompany < Ldaptic::Class(options)
  # This class and many others are created automatically based on
  # information from the server.
  class User
    alias  sAMAccountName
  end
end

me = MyCompany.search(:filter => {:cn => "Name, My"}).first
puts me.

Options given to this method are relayed to Ldaptic::Adapters.for. The documentation for this method should be consulted for further information.



110
111
112
113
114
# File 'lib/ldaptic.rb', line 110

def self.Class(options={})
  klass = ::Class.new(Class)
  klass.instance_variable_set(:@options, Ldaptic::Adapters.for(options))
  klass
end

.DN(dn, source = nil) ⇒ Object

Instantiate a new Ldaptic::DN object with the arguments given. Unlike Ldaptic::DN.new(dn), this method coerces the first argument to a string, unless it is already a string or an array. If the first argument is nil, nil is returned.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/ldaptic/dn.rb', line 9

def self.DN(dn, source = nil)
  return if dn.nil?
  dn = dn.dn if dn.respond_to?(:dn)
  if dn.kind_of?(::Ldaptic::DN)
    if source
      dn = dn.dup
      dn.source = source
    end
    return dn
  end
  if dn.respond_to?(:to_hash)
    dn = [dn]
  elsif ! dn.respond_to?(:to_ary)
    dn = dn.to_s
  end
  DN.new(dn, source)
end

.encode(value) ⇒ Object

Encode an object with LDAP semantics. Generally this is just to_s, but dates and booleans get special treatment.

If a symbol is passed in, underscores are replaced by dashes, aiding in bridging the gap between LDAP and Ruby conventions.



8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/ldaptic/escape.rb', line 8

def self.encode(value)
  if value.respond_to?(:utc)
    value.dup.utc.strftime("%Y%m%d%H%M%S") + ".%06dZ" % value.usec
  elsif [true, false].include?(value)
    value.to_s.upcase
  elsif value.respond_to?(:dn)
    value.dn.dup
  elsif value.kind_of?(Symbol)
    value.to_s.gsub('_', '-')
  else
    value.to_s.dup
  end
end

.escape(string, allow_asterisks = false) ⇒ Object

Escape a string for use in an LDAP filter, or in a DN. If the second argument is true, asterisks are not escaped.

If the first argument is not a string, it is handed off to LDAP::encode.



26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/ldaptic/escape.rb', line 26

def self.escape(string, allow_asterisks = false)
  string = Ldaptic.encode(string)
  enc = lambda { |l| "\\%02X" % l.ord }
  string.gsub!(/[()\\\0-\37"+,;<>]/, &enc)
  string.gsub!(/\A[# ]| \Z/, &enc)
  if allow_asterisks
    string.gsub!('**', '\\\\2A')
  else
    string.gsub!('*', '\\\\2A')
  end
  string
end

.Filter(argument) ⇒ Object

If the argument is already a valid Ldaptic::Filter object, return it untouched. Otherwise, pass it to the appropriate constructer of the appropriate subclass.

Ldaptic::Filter("(cn=Wu*)").to_s        #=> '(cn=Wu*)'
Ldaptic::Filter({:cn=>"Wu*"}).to_s      #=> '(cn=Wu\2A)'
Ldaptic::Filter(["(cn=?*)","Wu*"]).to_s #=> '(cn=Wu\2A*)'


12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/ldaptic/filter.rb', line 12

def self.Filter(argument)
  case argument
  when Filter::Abstract then argument
  when [],nil then nil
  when Array  then Filter::Array    .new(argument)
  when Hash   then Filter::Hash     .new(argument)
  when String then Filter::String   .new(argument)
  when Symbol then Filter::Attribute.new(argument)
  when Proc, Method
    Ldaptic::Filter(if argument.arity > 0
      argument.call(Filter::Spawner)
    elsif Filter::Spawner.respond_to?(:instance_exec)
      Filter::Spawner.instance_exec(&argument)
    else
      Filter::Spawner.instance_eval(&argument)
    end)
  else raise TypeError, "Unknown LDAP Filter type", caller
  end
end

.loggerObject

Default logger. If none given, creates a new logger on $stderr.



31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/ldaptic.rb', line 31

def self.logger
  unless @logger
    if defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
      return Rails.logger
    else
      require 'logger'
      @logger = Logger.new($stderr)
      @logger.level = Logger::WARN
    end
  end
  @logger
end

.logger=(logger) ⇒ Object



44
45
46
# File 'lib/ldaptic.rb', line 44

def self.logger=(logger)
  @logger = logger
end

.Module(options = {}) ⇒ Object

Similar to Ldaptic::Class, accepting the same options. Instead of returning an anonymous class that activates upon inheritance, it returns an anonymous module that activates upon inclusion.

module MyCompany
  include Ldaptic::Module(options)
  # This class and many others are created automatically based on
  # information from the server.
  class User
    alias  sAMAccountName
  end
end

me = MyCompany.search(:filter => {:cn => "Name, My"}).first
puts me.


78
79
80
# File 'lib/ldaptic.rb', line 78

def self.Module(options={})
  Ldaptic::Module.new(options)
end

.Object(options = {}, &block) ⇒ Object

Returns an object that can be assigned directly to a variable. This allows for an “anonymous” Ldaptic object.

@my_company = Ldaptic::Object(options)
@my_company::User.class_eval do
  alias  sAMAccountName
end


54
55
56
57
58
59
60
61
62
# File 'lib/ldaptic.rb', line 54

def self.Object(options={}, &block)
  base = ::Module.new do
    include Ldaptic::Module(options)
  end
  if block_given?
    base.class_eval(&block)
  end
  base
end

.RDN(rdn) ⇒ Object



197
198
199
200
201
202
203
204
# File 'lib/ldaptic/dn.rb', line 197

def self.RDN(rdn)
  rdn = rdn.rdn if rdn.respond_to?(:rdn)
  if rdn.respond_to?(:to_rdn)
    rdn.to_rdn
  else
    RDN.new(rdn||{})
  end
end

.split(string, character) ⇒ Object

Split on a given character where it is not escaped. Either an integer or string represenation of the character may be used.

Ldaptic.split("a*b", '*')    # => ["a","b"]
Ldaptic.split("a\\*b", '*')  # => ["a\\*b"]
Ldaptic.split("a\\\\*b", ?*) # => ["a\\\\","b"]


80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/ldaptic/escape.rb', line 80

def self.split(string, character)
  return [] if string.empty?
  array = [""]
  character = character.to_str.ord if character.respond_to?(:to_str)
  backslash = false

  string.each_byte do |byte|
    if backslash
      array.last << byte
      backslash = false
    elsif byte == 92 # ?\\
      array.last << byte
      backslash = true
    elsif byte == character
      array << ""
    else
      array.last << byte
    end
  end
  array
end

.unescape(string) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/ldaptic/escape.rb', line 39

def self.unescape(string)
  dest = ""
  string = string.strip # Leading and trailing whitespace MUST be encoded
  if string[0,1] == "#"
    [string[1..-1]].pack("H*")
  else
    backslash = nil
    string.each_byte do |byte|
      case backslash
      when true
        char = byte.chr
        if ('0'..'9').include?(char) || ('a'..'f').include?(char.downcase)
          backslash = char
        else
          dest << byte
          backslash = nil
        end

      when String
        dest << (backslash << byte).to_i(16)
        backslash = nil

      else
        backslash = nil
        if byte == 92 # ?\\
          backslash = true
        else
          dest << byte
        end
      end
    end
    dest
  end
end