ruby-activeldap 0.8.2 → 0.8.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|