ruby-activeldap 0.8.2 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/test/test_adapter.rb +17 -0
- data/test/test_associations.rb +19 -0
- data/test/test_attributes.rb +2 -1
- data/test/test_base.rb +28 -1
- data/test/test_base_per_instance.rb +2 -1
- data/test/test_callback.rb +2 -2
- data/test/test_connection.rb +2 -1
- data/test/test_connection_per_dn.rb +81 -0
- data/test/test_dn.rb +3 -2
- data/test/test_find.rb +35 -1
- data/test/test_object_class.rb +12 -1
- data/test/test_reflection.rb +16 -10
- data/test/test_schema.rb +141 -2
- data/test/test_user.rb +14 -4
- metadata +7 -104
- data/CHANGES +0 -397
- data/COPYING +0 -340
- data/LICENSE +0 -58
- data/Manifest.txt +0 -99
- data/README +0 -85
- data/Rakefile +0 -70
- data/TODO +0 -23
- data/benchmark/bench-al.rb +0 -152
- data/examples/config.yaml.example +0 -5
- data/examples/example.der +0 -0
- data/examples/example.jpg +0 -0
- data/examples/groupadd +0 -41
- data/examples/groupdel +0 -35
- data/examples/groupls +0 -49
- data/examples/groupmod +0 -42
- data/examples/lpasswd +0 -55
- data/examples/objects/group.rb +0 -13
- data/examples/objects/ou.rb +0 -4
- data/examples/objects/user.rb +0 -20
- data/examples/ouadd +0 -38
- data/examples/useradd +0 -45
- data/examples/useradd-binary +0 -50
- data/examples/userdel +0 -34
- data/examples/userls +0 -50
- data/examples/usermod +0 -42
- data/examples/usermod-binary-add +0 -47
- data/examples/usermod-binary-add-time +0 -51
- data/examples/usermod-binary-del +0 -48
- data/examples/usermod-lang-add +0 -43
- data/lib/active_ldap.rb +0 -964
- data/lib/active_ldap/adapter/base.rb +0 -461
- data/lib/active_ldap/adapter/ldap.rb +0 -232
- data/lib/active_ldap/adapter/ldap_ext.rb +0 -69
- data/lib/active_ldap/adapter/net_ldap.rb +0 -288
- data/lib/active_ldap/adapter/net_ldap_ext.rb +0 -29
- data/lib/active_ldap/association/belongs_to.rb +0 -40
- data/lib/active_ldap/association/belongs_to_many.rb +0 -39
- data/lib/active_ldap/association/collection.rb +0 -80
- data/lib/active_ldap/association/has_many.rb +0 -40
- data/lib/active_ldap/association/has_many_wrap.rb +0 -55
- data/lib/active_ldap/association/proxy.rb +0 -89
- data/lib/active_ldap/associations.rb +0 -162
- data/lib/active_ldap/attributes.rb +0 -203
- data/lib/active_ldap/base.rb +0 -1510
- data/lib/active_ldap/callbacks.rb +0 -19
- data/lib/active_ldap/command.rb +0 -46
- data/lib/active_ldap/configuration.rb +0 -106
- data/lib/active_ldap/connection.rb +0 -142
- data/lib/active_ldap/distinguished_name.rb +0 -246
- data/lib/active_ldap/ldap_error.rb +0 -74
- data/lib/active_ldap/object_class.rb +0 -74
- data/lib/active_ldap/schema.rb +0 -299
- data/lib/active_ldap/timeout.rb +0 -75
- data/lib/active_ldap/timeout_stub.rb +0 -17
- data/lib/active_ldap/user_password.rb +0 -92
- data/lib/active_ldap/validations.rb +0 -76
- data/rails/plugin/active_ldap/README +0 -54
- data/rails/plugin/active_ldap/generators/scaffold_al/scaffold_al_generator.rb +0 -7
- data/rails/plugin/active_ldap/generators/scaffold_al/templates/ldap.yml +0 -21
- data/rails/plugin/active_ldap/init.rb +0 -12
- data/test/TODO +0 -2
- data/test/al-test-utils.rb +0 -381
- data/test/command.rb +0 -62
- data/test/config.yaml.sample +0 -6
- data/test/run-test.rb +0 -29
- data/test/test-unit-ext.rb +0 -2
- data/test/test-unit-ext/always-show-result.rb +0 -28
- data/test/test-unit-ext/priority.rb +0 -163
@@ -1,19 +0,0 @@
|
|
1
|
-
require 'active_record/callbacks'
|
2
|
-
|
3
|
-
module ActiveLdap
|
4
|
-
module Callbacks
|
5
|
-
def self.append_features(base)
|
6
|
-
super
|
7
|
-
|
8
|
-
base.class_eval do
|
9
|
-
include ActiveRecord::Callbacks
|
10
|
-
|
11
|
-
def callback(method)
|
12
|
-
super
|
13
|
-
rescue ActiveRecord::ActiveRecordError
|
14
|
-
raise Error, $!.message
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
data/lib/active_ldap/command.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
require 'optparse'
|
2
|
-
require 'ostruct'
|
3
|
-
|
4
|
-
module ActiveLdap
|
5
|
-
module Command
|
6
|
-
module_function
|
7
|
-
def parse_options(argv=nil, version=nil)
|
8
|
-
argv ||= ARGV.dup
|
9
|
-
options = OpenStruct.new
|
10
|
-
opts = OptionParser.new do |opts|
|
11
|
-
yield(opts, options)
|
12
|
-
|
13
|
-
opts.separator ""
|
14
|
-
opts.separator "Common options:"
|
15
|
-
|
16
|
-
opts.on_tail("--config=CONFIG",
|
17
|
-
"Specify configuration file written as YAML") do |file|
|
18
|
-
require 'yaml'
|
19
|
-
config = YAML.load(File.read(file)).symbolize_keys
|
20
|
-
Configuration::DEFAULT_CONFIG.update(config)
|
21
|
-
end
|
22
|
-
|
23
|
-
opts.on_tail("-h", "--help", "Show this message") do
|
24
|
-
puts opts
|
25
|
-
exit
|
26
|
-
end
|
27
|
-
|
28
|
-
opts.on_tail("--version", "Show version") do
|
29
|
-
puts(version || VERSION)
|
30
|
-
exit
|
31
|
-
end
|
32
|
-
end
|
33
|
-
opts.parse!(argv)
|
34
|
-
[argv, opts, options]
|
35
|
-
end
|
36
|
-
|
37
|
-
def read_password(prompt, input=$stdin, output=$stdout)
|
38
|
-
output.print prompt
|
39
|
-
system "/bin/stty -echo" if input.tty?
|
40
|
-
input.gets.chomp
|
41
|
-
ensure
|
42
|
-
system "/bin/stty echo" if input.tty?
|
43
|
-
output.puts
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,106 +0,0 @@
|
|
1
|
-
|
2
|
-
module ActiveLdap
|
3
|
-
# Configuration
|
4
|
-
#
|
5
|
-
# Configuration provides the default settings required for
|
6
|
-
# ActiveLdap to work with your LDAP server. All of these
|
7
|
-
# settings can be passed in at initialization time.
|
8
|
-
module Configuration
|
9
|
-
def self.included(base)
|
10
|
-
base.extend(ClassMethods)
|
11
|
-
end
|
12
|
-
|
13
|
-
DEFAULT_CONFIG = {}
|
14
|
-
DEFAULT_CONFIG[:host] = '127.0.0.1'
|
15
|
-
DEFAULT_CONFIG[:port] = 389
|
16
|
-
DEFAULT_CONFIG[:method] = :plain # :ssl, :tls, :plain allowed
|
17
|
-
|
18
|
-
DEFAULT_CONFIG[:bind_dn] = nil
|
19
|
-
DEFAULT_CONFIG[:password_block] = nil
|
20
|
-
DEFAULT_CONFIG[:password] = nil
|
21
|
-
DEFAULT_CONFIG[:store_password] = true
|
22
|
-
DEFAULT_CONFIG[:allow_anonymous] = true
|
23
|
-
DEFAULT_CONFIG[:sasl_quiet] = false
|
24
|
-
DEFAULT_CONFIG[:try_sasl] = false
|
25
|
-
# See http://www.iana.org/assignments/sasl-mechanisms
|
26
|
-
DEFAULT_CONFIG[:sasl_mechanisms] = ["GSSAPI", "DIGEST-MD5",
|
27
|
-
"CRAM-MD5", "EXTERNAL"]
|
28
|
-
|
29
|
-
DEFAULT_CONFIG[:retry_limit] = 3
|
30
|
-
DEFAULT_CONFIG[:retry_wait] = 3
|
31
|
-
DEFAULT_CONFIG[:timeout] = 0 # in seconds; 0 <= Never timeout
|
32
|
-
# Whether or not to retry on timeouts
|
33
|
-
DEFAULT_CONFIG[:retry_on_timeout] = true
|
34
|
-
|
35
|
-
DEFAULT_CONFIG[:logger] = nil
|
36
|
-
|
37
|
-
module ClassMethods
|
38
|
-
@@defined_configurations = {}
|
39
|
-
|
40
|
-
def default_configuration
|
41
|
-
DEFAULT_CONFIG.dup
|
42
|
-
end
|
43
|
-
|
44
|
-
def ensure_configuration(config=nil)
|
45
|
-
if config.nil?
|
46
|
-
if defined?(LDAP_ENV)
|
47
|
-
config = LDAP_ENV
|
48
|
-
elsif defined?(RAILS_ENV)
|
49
|
-
config = RAILS_ENV
|
50
|
-
else
|
51
|
-
config = {}
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
if config.is_a?(Symbol) or config.is_a?(String)
|
56
|
-
_config = configurations[config.to_s]
|
57
|
-
unless _config
|
58
|
-
raise ConnectionError, "#{config} connection is not configured"
|
59
|
-
end
|
60
|
-
config = _config
|
61
|
-
end
|
62
|
-
|
63
|
-
config
|
64
|
-
end
|
65
|
-
|
66
|
-
def configuration(key=nil)
|
67
|
-
@@defined_configurations[key || active_connection_name]
|
68
|
-
end
|
69
|
-
|
70
|
-
def define_configuration(key, config)
|
71
|
-
@@defined_configurations[key] = config
|
72
|
-
end
|
73
|
-
|
74
|
-
def defined_configurations
|
75
|
-
@@defined_configurations
|
76
|
-
end
|
77
|
-
|
78
|
-
def remove_configuration_by_configuration(config)
|
79
|
-
@@defined_configurations.delete_if {|key, value| value == config}
|
80
|
-
end
|
81
|
-
|
82
|
-
CONNECTION_CONFIGURATION_KEYS = [:base, :ldap_scope, :adapter]
|
83
|
-
def remove_connection_related_configuration(config)
|
84
|
-
config.reject do |key, value|
|
85
|
-
CONNECTION_CONFIGURATION_KEYS.include?(key)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def merge_configuration(config)
|
90
|
-
configuration = default_configuration
|
91
|
-
config.symbolize_keys.each do |key, value|
|
92
|
-
case key
|
93
|
-
when :base
|
94
|
-
# Scrub before inserting
|
95
|
-
self.base = value.gsub(/['}{#]/, '')
|
96
|
-
when :ldap_scope
|
97
|
-
self.ldap_scope = value
|
98
|
-
else
|
99
|
-
configuration[key] = value
|
100
|
-
end
|
101
|
-
end
|
102
|
-
configuration
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
@@ -1,142 +0,0 @@
|
|
1
|
-
module ActiveLdap
|
2
|
-
module Connection
|
3
|
-
def self.included(base)
|
4
|
-
base.extend(ClassMethods)
|
5
|
-
end
|
6
|
-
|
7
|
-
module ClassMethods
|
8
|
-
@@active_connections = {}
|
9
|
-
|
10
|
-
def active_connections
|
11
|
-
@@active_connections[Thread.current.object_id] ||= {}
|
12
|
-
end
|
13
|
-
|
14
|
-
def active_connection_name
|
15
|
-
@active_connection_name ||= determine_active_connection_name
|
16
|
-
end
|
17
|
-
|
18
|
-
def clear_active_connections!
|
19
|
-
connections = active_connections
|
20
|
-
connections.each do |key, connection|
|
21
|
-
connection.disconnect!
|
22
|
-
end
|
23
|
-
connections.clear
|
24
|
-
end
|
25
|
-
|
26
|
-
def clear_active_connection_name
|
27
|
-
@active_connection_name = nil
|
28
|
-
ObjectSpace.each_object(Class) do |klass|
|
29
|
-
if klass < self and !klass.name.empty?
|
30
|
-
klass.instance_variable_set("@active_connection_name", nil)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def connection
|
36
|
-
conn = nil
|
37
|
-
@active_connection_name ||= nil
|
38
|
-
if @active_connection_name
|
39
|
-
conn = active_connections[@active_connection_name]
|
40
|
-
end
|
41
|
-
unless conn
|
42
|
-
conn = retrieve_connection
|
43
|
-
active_connections[@active_connection_name] = conn
|
44
|
-
end
|
45
|
-
conn
|
46
|
-
end
|
47
|
-
|
48
|
-
def connection=(adapter)
|
49
|
-
if adapter.is_a?(Adapter::Base)
|
50
|
-
@schema = nil
|
51
|
-
active_connections[active_connection_name] = adapter
|
52
|
-
elsif adapter.is_a?(Hash)
|
53
|
-
config = adapter
|
54
|
-
adapter = (config[:adapter] || "ldap")
|
55
|
-
normalized_adapter = adapter.downcase.gsub(/-/, "_")
|
56
|
-
adapter_method = "#{normalized_adapter}_connection"
|
57
|
-
unless Adapter::Base.respond_to?(adapter_method)
|
58
|
-
raise AdapterNotFound.new(adapter)
|
59
|
-
end
|
60
|
-
config = remove_connection_related_configuration(config)
|
61
|
-
self.connection = Adapter::Base.send(adapter_method, config)
|
62
|
-
elsif adapter.nil?
|
63
|
-
raise ConnectionNotEstablished
|
64
|
-
else
|
65
|
-
establish_connection(adapter)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def connected?
|
70
|
-
active_connections[active_connection_name] ? true : false
|
71
|
-
end
|
72
|
-
|
73
|
-
def retrieve_connection
|
74
|
-
conn = nil
|
75
|
-
name = active_connection_name
|
76
|
-
raise ConnectionNotEstablished unless name
|
77
|
-
conn = active_connections[name]
|
78
|
-
if conn.nil?
|
79
|
-
config = configuration(name)
|
80
|
-
raise ConnectionNotEstablished unless config
|
81
|
-
self.connection = config
|
82
|
-
conn = active_connections[name]
|
83
|
-
end
|
84
|
-
raise ConnectionNotEstablished if conn.nil?
|
85
|
-
conn
|
86
|
-
end
|
87
|
-
|
88
|
-
def remove_connection(klass=self)
|
89
|
-
key = active_connection_key(klass)
|
90
|
-
config = configuration(key)
|
91
|
-
conn = active_connections[key]
|
92
|
-
remove_configuration_by_configuration(config)
|
93
|
-
active_connections.delete_if {|key, value| value == conn}
|
94
|
-
conn.disconnect! if conn
|
95
|
-
config
|
96
|
-
end
|
97
|
-
|
98
|
-
def establish_connection(config=nil)
|
99
|
-
config = ensure_configuration(config)
|
100
|
-
remove_connection
|
101
|
-
|
102
|
-
clear_active_connection_name
|
103
|
-
key = active_connection_key
|
104
|
-
@active_connection_name = key
|
105
|
-
define_configuration(key, merge_configuration(config))
|
106
|
-
end
|
107
|
-
|
108
|
-
# Return the schema object
|
109
|
-
def schema
|
110
|
-
@schema ||= connection.schema
|
111
|
-
end
|
112
|
-
|
113
|
-
private
|
114
|
-
def active_connection_key(k=self)
|
115
|
-
k.name.empty? ? k.object_id : k.name
|
116
|
-
end
|
117
|
-
|
118
|
-
def determine_active_connection_name
|
119
|
-
key = active_connection_key
|
120
|
-
if active_connections[key] or configuration(key)
|
121
|
-
key
|
122
|
-
elsif self == ActiveLdap::Base
|
123
|
-
nil
|
124
|
-
else
|
125
|
-
superclass.active_connection_name
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
def connection
|
131
|
-
self.class.connection
|
132
|
-
end
|
133
|
-
|
134
|
-
# schema
|
135
|
-
#
|
136
|
-
# Returns the value of self.class.schema
|
137
|
-
# This is just syntactic sugar
|
138
|
-
def schema
|
139
|
-
self.class.schema
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
@@ -1,246 +0,0 @@
|
|
1
|
-
require 'strscan'
|
2
|
-
|
3
|
-
module ActiveLdap
|
4
|
-
class DistinguishedName
|
5
|
-
class Parser
|
6
|
-
attr_reader :dn
|
7
|
-
def initialize(source)
|
8
|
-
@dn = nil
|
9
|
-
@source = source
|
10
|
-
end
|
11
|
-
|
12
|
-
def parse
|
13
|
-
return @dn if @dn
|
14
|
-
|
15
|
-
rdns = []
|
16
|
-
scanner = StringScanner.new(@source)
|
17
|
-
|
18
|
-
scanner.scan(/\s*/)
|
19
|
-
raise rdn_is_missing if scanner.scan(/\s*\+\s*/)
|
20
|
-
raise name_component_is_missing if scanner.scan(/\s*,\s*/)
|
21
|
-
|
22
|
-
rdn = {}
|
23
|
-
until scanner.eos?
|
24
|
-
type = scan_attribute_type(scanner)
|
25
|
-
skip_attribute_type_and_value_separator(scanner)
|
26
|
-
value = scan_attribute_value(scanner)
|
27
|
-
rdn[type] = value
|
28
|
-
if scanner.scan(/\s*\+\s*/)
|
29
|
-
raise rdn_is_missing if scanner.eos?
|
30
|
-
elsif scanner.scan(/\s*\,\s*/)
|
31
|
-
rdns << rdn
|
32
|
-
rdn = {}
|
33
|
-
raise name_component_is_missing if scanner.eos?
|
34
|
-
else
|
35
|
-
scanner.scan(/\s*/)
|
36
|
-
rdns << rdn if scanner.eos?
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
@dn = DN.new(*rdns)
|
41
|
-
@dn
|
42
|
-
end
|
43
|
-
|
44
|
-
private
|
45
|
-
ATTRIBUTE_TYPE_RE = /\s*([a-zA-Z][a-zA-Z\d\-]*|\d+(?:\.\d+)*)\s*/
|
46
|
-
def scan_attribute_type(scanner)
|
47
|
-
raise attribute_type_is_missing unless scanner.scan(ATTRIBUTE_TYPE_RE)
|
48
|
-
scanner[1]
|
49
|
-
end
|
50
|
-
|
51
|
-
def skip_attribute_type_and_value_separator(scanner)
|
52
|
-
raise attribute_value_is_missing unless scanner.scan(/\s*=\s*/)
|
53
|
-
end
|
54
|
-
|
55
|
-
HEX_PAIR = "(?:[\\da-fA-F]{2})"
|
56
|
-
STRING_CHARS_RE = /[^,=\+<>\#;\\\"]*/ #
|
57
|
-
PAIR_RE = /\\([,=\+<>\#;]|\\|\"|(#{HEX_PAIR}))/ #
|
58
|
-
HEX_STRING_RE = /\#(#{HEX_PAIR}+)/ #
|
59
|
-
def scan_attribute_value(scanner)
|
60
|
-
if scanner.scan(HEX_STRING_RE)
|
61
|
-
value = scanner[1].scan(/../).collect do |hex_pair|
|
62
|
-
hex_pair.hex
|
63
|
-
end.pack("C*")
|
64
|
-
elsif scanner.scan(/\"/)
|
65
|
-
value = scan_quoted_attribute_value(scanner)
|
66
|
-
else
|
67
|
-
value = scan_not_quoted_attribute_value(scanner)
|
68
|
-
end
|
69
|
-
raise attribute_value_is_missing if value.blank?
|
70
|
-
|
71
|
-
value
|
72
|
-
end
|
73
|
-
|
74
|
-
def scan_quoted_attribute_value(scanner)
|
75
|
-
result = ""
|
76
|
-
until scanner.scan(/\"/)
|
77
|
-
scanner.scan(/([^\\\"]*)/)
|
78
|
-
quoted_strings = scanner[1]
|
79
|
-
pairs = collect_pairs(scanner)
|
80
|
-
|
81
|
-
if scanner.eos? or (quoted_strings.empty? and pairs.empty?)
|
82
|
-
raise found_unmatched_quotation
|
83
|
-
end
|
84
|
-
|
85
|
-
result << quoted_strings
|
86
|
-
result << pairs
|
87
|
-
end
|
88
|
-
result
|
89
|
-
end
|
90
|
-
|
91
|
-
def scan_not_quoted_attribute_value(scanner)
|
92
|
-
result = ""
|
93
|
-
until scanner.eos?
|
94
|
-
prev_size = result.size
|
95
|
-
pairs = collect_pairs(scanner)
|
96
|
-
strings = scanner.scan(STRING_CHARS_RE)
|
97
|
-
result << pairs if !pairs.nil? and !pairs.empty?
|
98
|
-
unless strings.nil?
|
99
|
-
if scanner.peek(1) == ","
|
100
|
-
result << strings.rstrip
|
101
|
-
else
|
102
|
-
result << strings
|
103
|
-
end
|
104
|
-
end
|
105
|
-
break if prev_size == result.size
|
106
|
-
end
|
107
|
-
result
|
108
|
-
end
|
109
|
-
|
110
|
-
def collect_pairs(scanner)
|
111
|
-
result = ""
|
112
|
-
while scanner.scan(PAIR_RE)
|
113
|
-
if scanner[2]
|
114
|
-
result << [scanner[2].hex].pack("C*")
|
115
|
-
else
|
116
|
-
result << scanner[1]
|
117
|
-
end
|
118
|
-
end
|
119
|
-
result
|
120
|
-
end
|
121
|
-
|
122
|
-
def invalid_dn(reason)
|
123
|
-
DistinguishedNameInvalid.new(@source, reason)
|
124
|
-
end
|
125
|
-
|
126
|
-
def name_component_is_missing
|
127
|
-
invalid_dn("name component is missing")
|
128
|
-
end
|
129
|
-
|
130
|
-
def rdn_is_missing
|
131
|
-
invalid_dn("relative distinguished name (RDN) is missing")
|
132
|
-
end
|
133
|
-
|
134
|
-
def attribute_type_is_missing
|
135
|
-
invalid_dn("attribute type is missing")
|
136
|
-
end
|
137
|
-
|
138
|
-
def attribute_value_is_missing
|
139
|
-
invalid_dn("attribute value is missing")
|
140
|
-
end
|
141
|
-
|
142
|
-
def found_unmatched_quotation
|
143
|
-
invalid_dn("found unmatched quotation")
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
class << self
|
148
|
-
def parse(source)
|
149
|
-
Parser.new(source).parse
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
attr_reader :rdns
|
154
|
-
def initialize(*rdns)
|
155
|
-
@rdns = rdns.collect do |rdn|
|
156
|
-
rdn = {rdn[0] => rdn[1]} if rdn.is_a?(Array) and rdn.size == 2
|
157
|
-
rdn
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
def -(other)
|
162
|
-
rdns = @rdns.dup
|
163
|
-
normalized_rdns = normalize(@rdns)
|
164
|
-
normalize(other.rdns).reverse_each do |rdn|
|
165
|
-
if rdn == normalized_rdns.pop
|
166
|
-
rdns.pop
|
167
|
-
else
|
168
|
-
raise ArgumentError, "#{other} isn't sub DN of #{self}"
|
169
|
-
end
|
170
|
-
end
|
171
|
-
self.class.new(*rdns)
|
172
|
-
end
|
173
|
-
|
174
|
-
def <<(rdn)
|
175
|
-
@rdns << rdn
|
176
|
-
end
|
177
|
-
|
178
|
-
def unshift(rdn)
|
179
|
-
@rdns.unshift(rdn)
|
180
|
-
end
|
181
|
-
|
182
|
-
def <=>(other)
|
183
|
-
normalize_for_comparing(@rdns) <=>
|
184
|
-
normalize_for_comparing(other.rdns)
|
185
|
-
end
|
186
|
-
|
187
|
-
def ==(other)
|
188
|
-
other.is_a?(self.class) and
|
189
|
-
normalize(@rdns) == normalize(other.rdns)
|
190
|
-
end
|
191
|
-
|
192
|
-
def eql?(other)
|
193
|
-
other.is_a?(self.class) and
|
194
|
-
normalize(@rdns).to_s.eql?(normalize(other.rdns).to_s)
|
195
|
-
end
|
196
|
-
|
197
|
-
def hash
|
198
|
-
normalize(@rdns).to_s.hash
|
199
|
-
end
|
200
|
-
|
201
|
-
def inspect
|
202
|
-
super
|
203
|
-
end
|
204
|
-
|
205
|
-
def to_s
|
206
|
-
@rdns.collect do |rdn|
|
207
|
-
rdn.sort_by do |type, value|
|
208
|
-
type.upcase
|
209
|
-
end.collect do |type, value|
|
210
|
-
"#{type}=#{escape(value)}"
|
211
|
-
end.join("+")
|
212
|
-
end.join(",")
|
213
|
-
end
|
214
|
-
|
215
|
-
private
|
216
|
-
def normalize(rdns)
|
217
|
-
rdns.collect do |rdn|
|
218
|
-
normalized_rdn = {}
|
219
|
-
rdn.each do |key, value|
|
220
|
-
normalized_rdn[key.upcase] = value.upcase
|
221
|
-
end
|
222
|
-
normalized_rdn
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
def normalize_for_comparing(rdns)
|
227
|
-
normalize(rdns).collect do |rdn|
|
228
|
-
rdn.sort_by do |key, value|
|
229
|
-
key
|
230
|
-
end
|
231
|
-
end.collect do |key, value|
|
232
|
-
[key, value]
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
def escape(value)
|
237
|
-
if /(\A | \z)/.match(value)
|
238
|
-
'"' + value.gsub(/([\\\"])/, '\\\\\1') + '"'
|
239
|
-
else
|
240
|
-
value.gsub(/([,=\+<>#;\\\"])/, '\\\\\1')
|
241
|
-
end
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
DN = DistinguishedName
|
246
|
-
end
|