activeldap 4.0.5 → 6.1.0

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.
Files changed (57) hide show
  1. checksums.yaml +5 -5
  2. data/.yardopts +3 -1
  3. data/doc/text/development.md +26 -0
  4. data/doc/text/{news.textile → news.md} +451 -241
  5. data/doc/text/{rails.textile → rails.md} +44 -33
  6. data/doc/text/{tutorial.textile → tutorial.md} +177 -185
  7. data/lib/active_ldap/adapter/base.rb +40 -17
  8. data/lib/active_ldap/adapter/jndi.rb +21 -9
  9. data/lib/active_ldap/adapter/jndi_connection.rb +83 -20
  10. data/lib/active_ldap/adapter/ldap.rb +50 -28
  11. data/lib/active_ldap/adapter/ldap_ext.rb +32 -13
  12. data/lib/active_ldap/adapter/net_ldap.rb +26 -24
  13. data/lib/active_ldap/associations.rb +5 -5
  14. data/lib/active_ldap/attribute_methods/before_type_cast.rb +1 -1
  15. data/lib/active_ldap/attribute_methods/dirty.rb +4 -7
  16. data/lib/active_ldap/attribute_methods/query.rb +1 -1
  17. data/lib/active_ldap/attribute_methods/read.rb +5 -1
  18. data/lib/active_ldap/attribute_methods/write.rb +1 -1
  19. data/lib/active_ldap/attribute_methods.rb +1 -2
  20. data/lib/active_ldap/base.rb +61 -14
  21. data/lib/active_ldap/callbacks.rb +7 -8
  22. data/lib/active_ldap/configuration.rb +27 -3
  23. data/lib/active_ldap/connection.rb +4 -22
  24. data/lib/active_ldap/distinguished_name.rb +1 -1
  25. data/lib/active_ldap/human_readable.rb +5 -4
  26. data/lib/active_ldap/operations.rb +24 -4
  27. data/lib/active_ldap/persistence.rb +3 -2
  28. data/lib/active_ldap/populate.rb +5 -3
  29. data/lib/active_ldap/railties/controller_runtime.rb +1 -2
  30. data/lib/active_ldap/schema/syntaxes.rb +8 -4
  31. data/lib/active_ldap/validations.rb +12 -4
  32. data/lib/active_ldap/version.rb +1 -1
  33. data/lib/active_ldap.rb +0 -7
  34. data/po/en/active-ldap.po +2 -2
  35. data/po/ja/active-ldap.po +3 -3
  36. data/test/add-phonetic-attribute-options-to-slapd.ldif +3 -3
  37. data/test/al-test-utils.rb +125 -38
  38. data/test/command.rb +13 -16
  39. data/test/enable-dynamic-groups.ldif +22 -0
  40. data/test/enable-start-tls.ldif +27 -0
  41. data/test/run-test.rb +0 -4
  42. data/test/test_base.rb +223 -22
  43. data/test/test_base_per_instance.rb +33 -1
  44. data/test/test_callback.rb +10 -8
  45. data/test/test_connection.rb +4 -0
  46. data/test/test_connection_per_class.rb +34 -0
  47. data/test/test_dn.rb +7 -0
  48. data/test/test_entry.rb +1 -0
  49. data/test/test_find.rb +14 -3
  50. data/test/test_supported_control.rb +1 -1
  51. data/test/test_syntax.rb +5 -0
  52. data/test/test_validation.rb +28 -15
  53. metadata +23 -24
  54. data/README.textile +0 -141
  55. data/doc/text/development.textile +0 -54
  56. data/lib/active_ldap/timeout.rb +0 -75
  57. data/lib/active_ldap/timeout_stub.rb +0 -17
@@ -1,3 +1,5 @@
1
+ require 'timeout'
2
+
1
3
  require 'active_ldap/schema'
2
4
  require 'active_ldap/entry_attribute'
3
5
  require 'active_ldap/ldap_error'
@@ -12,6 +14,7 @@ module ActiveLdap
12
14
  :host,
13
15
  :port,
14
16
  :method,
17
+ :tls_options,
15
18
  :timeout,
16
19
  :retry_on_timeout,
17
20
  :retry_limit,
@@ -27,6 +30,8 @@ module ActiveLdap
27
30
  :scope,
28
31
  :sasl_options,
29
32
  :follow_referrals,
33
+ :use_paged_results,
34
+ :page_size,
30
35
  ]
31
36
 
32
37
  @@row_even = true
@@ -38,6 +43,7 @@ module ActiveLdap
38
43
  @bind_tried = false
39
44
  @entry_attributes = {}
40
45
  @follow_referrals = nil
46
+ @page_size = nil
41
47
  @configuration = configuration.dup
42
48
  @logger = @configuration.delete(:logger)
43
49
  @configuration.assert_valid_keys(VALID_ADAPTER_CONFIGURATION_KEYS)
@@ -45,6 +51,7 @@ module ActiveLdap
45
51
  instance_variable_set("@#{name}", configuration[name])
46
52
  end
47
53
  @follow_referrals = true if @follow_referrals.nil?
54
+ @page_size ||= Configuration::DEFAULT_CONFIG[:page_size]
48
55
  @instrumenter = ActiveSupport::Notifications.instrumenter
49
56
  end
50
57
 
@@ -166,23 +173,40 @@ module ActiveLdap
166
173
  end
167
174
 
168
175
  def search(options={})
169
- filter = parse_filter(options[:filter]) || 'objectClass=*'
170
- attrs = options[:attributes] || []
171
- scope = ensure_scope(options[:scope] || @scope)
172
176
  base = options[:base]
177
+ base = ensure_dn_string(base)
178
+ attributes = options[:attributes] || []
179
+ attributes = attributes.to_a # just in case
173
180
  limit = options[:limit] || 0
174
181
  limit = nil if limit <= 0
182
+ use_paged_results = options[:use_paged_results]
183
+ use_paged_results = @use_paged_results if use_paged_results.nil?
184
+ if use_paged_results
185
+ use_paged_results = limit != 1 && supported_control.paged_results?
186
+ end
187
+ search_options = {
188
+ base: base,
189
+ scope: ensure_scope(options[:scope] || @scope),
190
+ filter: parse_filter(options[:filter]) || 'objectClass=*',
191
+ attributes: attributes,
192
+ limit: limit,
193
+ use_paged_results: use_paged_results,
194
+ page_size: options[:page_size] || @page_size,
195
+ }
175
196
 
176
- attrs = attrs.to_a # just in case
177
- base = ensure_dn_string(base)
178
197
  begin
179
198
  operation(options) do
180
- yield(base, scope, filter, attrs, limit)
199
+ yield(search_options)
181
200
  end
182
- rescue LdapError::NoSuchObject, LdapError::InvalidDnSyntax
201
+ rescue LdapError::NoSuchObject, LdapError::InvalidDnSyntax => error
183
202
  # Do nothing on failure
184
203
  @logger.info do
185
- args = [$!.class, $!.message, filter, attrs.inspect]
204
+ args = [
205
+ error.class.class,
206
+ error.message,
207
+ search_options[:filter],
208
+ search_options[:attributes].inspect,
209
+ ]
186
210
  _("Ignore error %s(%s): filter %s: attributes: %s") % args
187
211
  end
188
212
  end
@@ -328,7 +352,7 @@ module ActiveLdap
328
352
  n_retries = 0
329
353
  retry_limit = options[:retry_limit] || @retry_limit
330
354
  begin
331
- do_in_timeout(@timeout, &block)
355
+ Timeout.timeout(@timeout, &block)
332
356
  rescue Timeout::Error => e
333
357
  @logger.error {_('Requested action timed out.')}
334
358
  if @retry_on_timeout and (retry_limit < 0 or n_retries <= retry_limit)
@@ -344,10 +368,6 @@ module ActiveLdap
344
368
  end
345
369
  end
346
370
 
347
- def do_in_timeout(timeout, &block)
348
- Timeout.alarm(timeout, &block)
349
- end
350
-
351
371
  def sasl_bind(bind_dn, options={})
352
372
  # Get all SASL mechanisms
353
373
  mechanisms = operation(options) do
@@ -601,9 +621,13 @@ module ActiveLdap
601
621
  raise
602
622
  rescue => detail
603
623
  @logger.error do
604
- _("Reconnect to server failed: %s\n" \
624
+ _("Reconnect to server failed: %s: %s\n" \
605
625
  "Reconnect to server failed backtrace:\n" \
606
- "%s") % [detail.message, detail.backtrace.join("\n")]
626
+ "%s") % [
627
+ detail.class,
628
+ detail.message,
629
+ detail.backtrace.join("\n"),
630
+ ]
607
631
  end
608
632
  # Do not loop if forced
609
633
  raise ConnectionError, detail.message if force
@@ -659,8 +683,7 @@ module ActiveLdap
659
683
  :scope => :base,
660
684
  :attributes => attrs,
661
685
  :limit => 1,
662
- :try_reconnect => try_reconnect,
663
- :use_paged_results => false) do |dn, attributes|
686
+ :try_reconnect => try_reconnect) do |dn, attributes|
664
687
  found_attributes = attributes
665
688
  end
666
689
  found_attributes
@@ -22,9 +22,23 @@ module ActiveLdap
22
22
  super do |host, port, method|
23
23
  uri = construct_uri(host, port, method == :ssl)
24
24
  with_start_tls = method == :start_tls
25
- info = {:uri => uri, :with_start_tls => with_start_tls}
26
- [log("connect", info) {JndiConnection.new(host, port, method, @timeout)},
27
- uri, with_start_tls]
25
+ follow_referrals = follow_referrals?(options)
26
+ info = {
27
+ :uri => uri,
28
+ :with_start_tls => with_start_tls,
29
+ :follow_referrals => follow_referrals,
30
+ }
31
+ [
32
+ log("connect", info) {
33
+ JndiConnection.new(host,
34
+ port,
35
+ method,
36
+ @timeout,
37
+ follow_referrals)
38
+ },
39
+ uri,
40
+ with_start_tls,
41
+ ]
28
42
  end
29
43
  end
30
44
 
@@ -46,12 +60,10 @@ module ActiveLdap
46
60
  end
47
61
 
48
62
  def search(options={}, &block)
49
- super(options) do |base, scope, filter, attrs, limit|
50
- info = {
51
- :base => base, :scope => scope_name(scope), :filter => filter,
52
- :attributes => attrs, :limit => limit,
53
- }
54
- execute(:search, info, base, scope, filter, attrs, limit, &block)
63
+ super(options) do |search_options|
64
+ scope = search_options[:scope]
65
+ info = search_options.merge(scope: scope_name(scope))
66
+ execute(:search, info, search_options, &block)
55
67
  end
56
68
  end
57
69
 
@@ -25,6 +25,8 @@ module ActiveLdap
25
25
  Context = naming.Context
26
26
  StartTlsRequest = ldap.StartTlsRequest
27
27
  Control = ldap.Control
28
+ PagedResultsControl = ldap.PagedResultsControl
29
+ PagedResultsResponseControl = ldap.PagedResultsResponseControl
28
30
 
29
31
  CommunicationException = naming.CommunicationException
30
32
  ServiceUnavailableException = naming.ServiceUnavailableException
@@ -73,13 +75,14 @@ module ActiveLdap
73
75
  end
74
76
  end
75
77
 
76
- def initialize(host, port, method, timeout)
78
+ def initialize(host, port, method, timeout, follow_referrals)
77
79
  @host = host
78
80
  @port = port
79
81
  @method = method
80
82
  @timeout = timeout
81
83
  @context = nil
82
84
  @tls = nil
85
+ @follow_referrals = follow_referrals
83
86
  end
84
87
 
85
88
  def unbind
@@ -108,23 +111,55 @@ module ActiveLdap
108
111
  bound?
109
112
  end
110
113
 
111
- def search(base, scope, filter, attrs, limit)
114
+ def search(options)
115
+ base = options[:base]
116
+ scope = options[:scope]
117
+ filter = options[:filter]
118
+ attributes = options[:attributes]
119
+ limit = options[:limit]
120
+ use_paged_results = options[:use_paged_results]
121
+ page_size = options[:page_size]
122
+
112
123
  controls = SearchControls.new
113
124
  controls.search_scope = scope
114
125
 
115
126
  controls.count_limit = limit if limit
116
- unless attrs.blank?
117
- controls.returning_attributes = attrs.to_java(:string)
127
+ unless attributes.blank?
128
+ controls.returning_attributes = attributes.to_java(:string)
129
+ end
130
+
131
+ page_cookie = nil
132
+ if use_paged_results
133
+ # https://devdocs.io/openjdk~8/javax/naming/ldap/pagedresultscontrol
134
+ @context.set_request_controls([build_paged_results_control(page_size)])
135
+ else
136
+ @context.set_request_controls([])
118
137
  end
119
138
 
120
- @context.search(base, filter, controls).each do |result|
121
- attributes = {}
122
- result.attributes.get_all.each do |attribute|
123
- attributes[attribute.get_id] = attribute.get_all.collect do |value|
124
- value.is_a?(String) ? value : String.from_java_bytes(value)
125
- end
139
+ escaped_base = escape_dn(base)
140
+
141
+ loop do
142
+ @context.search(escaped_base, filter, controls).each do |search_result|
143
+ yield(build_raw_search_result(search_result))
126
144
  end
127
- yield([result.name_in_namespace, attributes])
145
+
146
+ break unless use_paged_results
147
+
148
+ # Find the paged search cookie
149
+ response_controls = @context.get_response_controls
150
+ break unless response_controls
151
+ response_controls.each do |response_control|
152
+ next unless response_control.is_a?(PagedResultsResponseControl)
153
+ page_cookie = response_control.get_cookie
154
+ break
155
+ end
156
+
157
+ break unless page_cookie
158
+
159
+ # Set paged results control so we can keep getting results.
160
+ paged_results_control =
161
+ build_paged_results_control(page_size, page_cookie)
162
+ @context.set_request_controls([paged_results_control])
128
163
  end
129
164
  end
130
165
 
@@ -133,25 +168,32 @@ module ActiveLdap
133
168
  records.each do |record|
134
169
  attributes.put(record.to_java_attribute)
135
170
  end
136
- @context.create_subcontext(dn, attributes)
171
+ @context.set_request_controls([])
172
+ @context.create_subcontext(escape_dn(dn), attributes)
137
173
  end
138
174
 
139
175
  def modify(dn, records)
140
176
  items = records.collect(&:to_java_modification_item)
141
- @context.modify_attributes(dn, items.to_java(ModificationItem))
177
+ @context.set_request_controls([])
178
+ @context.modify_attributes(escape_dn(dn), items.to_java(ModificationItem))
142
179
  end
143
180
 
144
181
  def modify_rdn(dn, new_rdn, delete_old_rdn)
145
182
  # should use mutex
146
183
  delete_rdn_key = "java.naming.ldap.deleteRDN"
147
- @context.add_to_environment(delete_rdn_key, delete_old_rdn.to_s)
148
- @context.rename(dn, new_rdn)
149
- ensure
150
- @context.remove_from_environment(delete_rdn_key)
184
+ @context.set_request_controls([])
185
+ begin
186
+ @context.add_to_environment(delete_rdn_key, delete_old_rdn.to_s)
187
+ @context.rename(escape_dn(dn), escape_dn(new_rdn))
188
+ ensure
189
+ @context.remove_from_environment(delete_rdn_key)
190
+ end
151
191
  end
152
192
 
153
193
  def delete(dn)
154
- @context.destroy_subcontext(dn)
194
+ escaped_dn = escape_dn(dn)
195
+ @context.set_request_controls([])
196
+ @context.destroy_subcontext(escaped_dn)
155
197
  end
156
198
 
157
199
  private
@@ -162,9 +204,10 @@ module ActiveLdap
162
204
  Context::PROVIDER_URL => ldap_uri,
163
205
  'com.sun.jndi.ldap.connect.timeout' => (@timeout * 1000).to_i.to_s,
164
206
  'com.sun.jndi.ldap.read.timeout' => (@timeout * 1000).to_i.to_s,
207
+ 'java.naming.ldap.derefAliases' => 'never',
208
+ 'java.naming.referral' => @follow_referrals ? 'follow' : 'ignore',
165
209
  }
166
- environment = HashTable.new(environment)
167
- context = InitialLdapContext.new(environment, nil)
210
+ context = InitialLdapContext.new(HashTable.new(environment), nil)
168
211
  if @method == :start_tls
169
212
  @tls = context.extended_operation(StartTlsRequest.new)
170
213
  @tls.negotiate
@@ -185,6 +228,26 @@ module ActiveLdap
185
228
  protocol = @method == :ssl ? "ldaps" : "ldap"
186
229
  "#{protocol}://#{@host}:#{@port}/"
187
230
  end
231
+
232
+ def escape_dn(dn)
233
+ javax.naming.ldap.LdapName.new(dn)
234
+ rescue Java::JavaLang::IllegalArgumentException, Java::JavaxNaming::InvalidNameException
235
+ dn
236
+ end
237
+
238
+ def build_paged_results_control(page_size, page_cookie=nil)
239
+ PagedResultsControl.new(page_size, page_cookie, Control::CRITICAL)
240
+ end
241
+
242
+ def build_raw_search_result(search_result)
243
+ attributes = {}
244
+ search_result.attributes.get_all.each do |attribute|
245
+ attributes[attribute.get_id] = attribute.get_all.collect do |value|
246
+ value.is_a?(String) ? value : String.from_java_bytes(value)
247
+ end
248
+ end
249
+ [search_result.name_in_namespace, attributes]
250
+ end
188
251
  end
189
252
  end
190
253
  end
@@ -24,7 +24,7 @@ module ActiveLdap
24
24
  end
25
25
 
26
26
  class SSL < Base
27
- def connect(host, port)
27
+ def connect(host, port, options={})
28
28
  LDAP::SSLConn.new(host, port, false)
29
29
  end
30
30
 
@@ -34,8 +34,35 @@ module ActiveLdap
34
34
  end
35
35
 
36
36
  class TLS < Base
37
- def connect(host, port)
38
- LDAP::SSLConn.new(host, port, true)
37
+ def connect(host, port, options={})
38
+ connection = LDAP::Conn.new(host, port)
39
+ if connection.get_option(LDAP::LDAP_OPT_PROTOCOL_VERSION) < 3
40
+ connection.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3)
41
+ end
42
+ tls_options = options[:tls_options]
43
+ if tls_options and LDAP.const_defined?(:LDAP_OPT_X_TLS_NEWCTX)
44
+ tls_options.each do |key, value|
45
+ case key
46
+ when :verify_mode
47
+ case value
48
+ when :none, OpenSSL::SSL::SSL_VERIFY_NONE
49
+ connection.set_option(LDAP::LDAP_OPT_X_TLS_REQUIRE_CERT,
50
+ LDAP::LDAP_OPT_X_TLS_NEVER)
51
+ when :peer, OpenSSL::SSL::SSL_VERIFY_PEER
52
+ connection.set_option(LDAP::LDAP_OPT_X_TLS_REQUIRE_CERT,
53
+ LDAP::LDAP_OPT_X_TLS_DEMAND)
54
+ end
55
+ when :verify_hostname
56
+ unless value
57
+ connection.set_option(LDAP::LDAP_OPT_X_TLS_REQUIRE_CERT,
58
+ LDAP::LDAP_OPT_X_TLS_ALLOW)
59
+ end
60
+ end
61
+ end
62
+ connection.set_option(LDAP::LDAP_OPT_X_TLS_NEWCTX, 0)
63
+ end
64
+ connection.start_tls
65
+ connection
39
66
  end
40
67
 
41
68
  def start_tls?
@@ -44,7 +71,7 @@ module ActiveLdap
44
71
  end
45
72
 
46
73
  class Plain < Base
47
- def connect(host, port)
74
+ def connect(host, port, options={})
48
75
  LDAP::Conn.new(host, port)
49
76
  end
50
77
  end
@@ -54,9 +81,13 @@ module ActiveLdap
54
81
  super do |host, port, method|
55
82
  uri = construct_uri(host, port, method.ssl?)
56
83
  with_start_tls = method.start_tls?
57
- info = {:uri => uri, :with_start_tls => with_start_tls}
84
+ info = {
85
+ :uri => uri,
86
+ :with_start_tls => with_start_tls,
87
+ :tls_options => @tls_options,
88
+ }
58
89
  connection = log("connect", info) do
59
- method.connect(host, port)
90
+ method.connect(host, port, :tls_options => @tls_options)
60
91
  end
61
92
  [connection, uri, with_start_tls]
62
93
  end
@@ -82,25 +113,11 @@ module ActiveLdap
82
113
  end
83
114
 
84
115
  def search(options={})
85
- super(options) do |base, scope, filter, attrs, limit|
116
+ super(options) do |search_options|
86
117
  begin
87
- use_paged_results = options[:use_paged_results]
88
- if use_paged_results or use_paged_results.nil?
89
- use_paged_results = supported_control.paged_results?
90
- end
91
- info = {
92
- :base => base, :scope => scope_name(scope),
93
- :filter => filter, :attributes => attrs, :limit => limit,
94
- }
95
- options = {
96
- :base => base,
97
- :scope => scope,
98
- :filter => filter,
99
- :attributes => attrs,
100
- :limit => limit,
101
- :use_paged_results => use_paged_results
102
- }
103
- execute(:search_full, info, options) do |entry|
118
+ scope = search_options[:scope]
119
+ info = search_options.merge(scope: scope_name(scope))
120
+ execute(:search_full, info, search_options) do |entry|
104
121
  attributes = {}
105
122
  entry.attrs.each do |attr|
106
123
  value = entry.vals(attr)
@@ -111,7 +128,10 @@ module ActiveLdap
111
128
  rescue RuntimeError
112
129
  if $!.message == "no result returned by search"
113
130
  @logger.debug do
114
- args = [filter, attrs.inspect]
131
+ args = [
132
+ search_options[:filter],
133
+ search_options[:attributes].inspect,
134
+ ]
115
135
  _("No matches: filter: %s: attributes: %s") % args
116
136
  end
117
137
  else
@@ -189,15 +209,17 @@ module ActiveLdap
189
209
  def prepare_connection(options={})
190
210
  operation(options) do
191
211
  @connection.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3)
192
- unless follow_referrals?(options)
193
- @connection.set_option(LDAP::LDAP_OPT_REFERRALS, 0)
194
- end
212
+ @ldap_follow_referrals = follow_referrals?(options) ? 1 : 0
213
+ @connection.set_option(LDAP::LDAP_OPT_REFERRALS,
214
+ @ldap_follow_referrals)
195
215
  end
196
216
  end
197
217
 
198
218
  def execute(method, info=nil, *args, &block)
199
219
  begin
200
220
  name = (info || {}).delete(:name) || method
221
+ @connection.set_option(LDAP::LDAP_OPT_REFERRALS,
222
+ @ldap_follow_referrals)
201
223
  log(name, info) {@connection.send(method, *args, &block)}
202
224
  rescue LDAP::ResultError
203
225
  @connection.assert_error_code
@@ -65,12 +65,28 @@ module LDAP
65
65
  attributes = options[:attributes]
66
66
  limit = options[:limit] || 0
67
67
  use_paged_results = options[:use_paged_results]
68
+ page_size = options[:page_size]
68
69
  if @@have_search_ext
69
70
  if use_paged_results
70
- paged_search(base, scope, filter, attributes, limit, &block)
71
+ paged_search(base,
72
+ scope,
73
+ filter,
74
+ attributes,
75
+ limit,
76
+ page_size,
77
+ &block)
71
78
  else
72
- search_ext(base, scope, filter, attributes,
73
- false, nil, nil, 0, 0, limit, &block)
79
+ search_ext(base,
80
+ scope,
81
+ filter,
82
+ attributes,
83
+ false,
84
+ nil,
85
+ nil,
86
+ 0,
87
+ 0,
88
+ limit,
89
+ &block)
74
90
  end
75
91
  else
76
92
  i = 0
@@ -120,27 +136,30 @@ module LDAP
120
136
  end
121
137
  end
122
138
 
123
- def paged_search(base, scope, filter, attributes, limit, &block)
124
- # work around a bug with openldap
125
- page_size = 126
139
+ def paged_search(base, scope, filter, attributes, limit, page_size, &block)
126
140
  cookie = ""
127
141
  critical = true
128
-
129
142
  loop do
130
143
  ber_string = LDAP::Control.encode(page_size, cookie)
131
144
  control = LDAP::Control.new(LDAP::LDAP_CONTROL_PAGEDRESULTS,
132
145
  ber_string,
133
146
  critical)
134
-
135
- search_ext(base, scope, filter, attributes,
136
- false, [control], nil, 0, 0, limit, &block)
147
+ search_ext(base,
148
+ scope,
149
+ filter,
150
+ attributes,
151
+ false,
152
+ [control],
153
+ nil,
154
+ 0,
155
+ 0,
156
+ limit,
157
+ &block)
137
158
 
138
159
  control = find_paged_results_control(@controls)
139
160
  break if control.nil?
140
- returned_size, cookie = control.decode
141
- returned_size = returned_size.to_i
142
- page_size = returned_size if returned_size > 0
143
161
 
162
+ _estimated_result_set_size, cookie = control.decode
144
163
  break if cookie.empty?
145
164
  end
146
165
  end
@@ -26,15 +26,21 @@ module ActiveLdap
26
26
  :host => host,
27
27
  :port => port,
28
28
  }
29
- config[:encryption] = {:method => method} if method
29
+ if method
30
+ config[:encryption] = { :method => method }
31
+ config[:encryption][:tls_options] = @tls_options if @tls_options
32
+ end
30
33
  begin
31
34
  uri = construct_uri(host, port, method == :simple_tls)
32
35
  with_start_tls = method == :start_tls
33
36
  info = {:uri => uri, :with_start_tls => with_start_tls}
34
37
  [log("connect", info) {Net::LDAP::Connection.new(config)},
35
38
  uri, with_start_tls]
36
- rescue Net::LDAP::LdapError
37
- raise ConnectionError, $!.message
39
+ rescue Net::LDAP::ConnectionError => error
40
+ raise ConnectionError, error.message
41
+ rescue Net::LDAP::Error => error
42
+ message = "#{error.class}: #{error.message}"
43
+ raise ConnectionError, message, caller(0) + error.backtrace
38
44
  end
39
45
  end
40
46
  end
@@ -50,7 +56,7 @@ module ActiveLdap
50
56
  def bind(options={})
51
57
  begin
52
58
  super
53
- rescue Net::LDAP::LdapError
59
+ rescue Net::LDAP::Error
54
60
  raise AuthenticationError, $!.message
55
61
  end
56
62
  end
@@ -63,25 +69,16 @@ module ActiveLdap
63
69
  end
64
70
 
65
71
  def search(options={})
66
- use_paged_results = options[:use_paged_results]
67
- if use_paged_results or use_paged_results.nil?
68
- paged_results_supported = supported_control.paged_results?
69
- else
70
- paged_results_supported = false
71
- end
72
- super(options) do |base, scope, filter, attrs, limit|
72
+ super(options) do |search_options|
73
+ scope = search_options[:scope]
74
+ info = search_options.merge(scope: scope_name(scope))
73
75
  args = {
74
- :base => base,
75
- :scope => scope,
76
- :filter => filter,
77
- :attributes => attrs,
78
- :size => limit,
79
- :paged_searches_supported => paged_results_supported,
80
- }
81
- info = {
82
- :base => base, :scope => scope_name(scope),
83
- :filter => filter, :attributes => attrs, :limit => limit,
84
- :paged_results_supported => paged_results_supported,
76
+ base: search_options[:base],
77
+ scope: scope,
78
+ filter: search_options[:filter],
79
+ attributes: search_options[:attributes],
80
+ size: search_options[:limit],
81
+ paged_searcheds_supported: search_options[:paged_results_supported],
85
82
  }
86
83
  execute(:search, info, args) do |entry|
87
84
  attributes = {}
@@ -148,8 +145,13 @@ module ActiveLdap
148
145
  result = log(name, info) do
149
146
  begin
150
147
  @connection.send(method, *args, &block)
151
- rescue Errno::EPIPE, Errno::ECONNRESET
152
- raise ConnectionError, "#{$!.class}: #{$!.message}"
148
+ rescue SystemCallError => error
149
+ message = "#{error.class}: #{error.message}"
150
+ raise ConnectionError, message, caller(0) + error.backtrace
151
+ rescue Net::LDAP::ResponseMissingOrInvalidError => error
152
+ message = "#{error.class}: #{error.message}"
153
+ message << ": connection may be timed out"
154
+ raise ConnectionError, message, caller(0) + error.backtrace
153
155
  end
154
156
  end
155
157
  message = nil
@@ -75,15 +75,15 @@ module ActiveLdap
75
75
  association_class = Association::BelongsTo
76
76
  opts[:foreign_key_name] ||= "#{association_id}_id"
77
77
 
78
- before_save(<<-EOC)
79
- if defined?(@#{association_id})
80
- association = @#{association_id}
78
+ before_save do
79
+ if instance_variable_defined?(:"@#{association_id}")
80
+ association = instance_variable_get(:"@#{association_id}")
81
81
  if association and association.updated?
82
82
  self[association.__send__(:primary_key)] =
83
- association[#{opts[:foreign_key_name].dump}]
83
+ association[opts[:foreign_key_name]]
84
84
  end
85
85
  end
86
- EOC
86
+ end
87
87
  end
88
88
 
89
89
  association_accessor(association_id) do |target|
@@ -7,7 +7,7 @@ module ActiveLdap
7
7
  attribute_method_suffix '_before_type_cast'
8
8
  end
9
9
 
10
- protected
10
+ private
11
11
  def attribute_before_type_cast(attr)
12
12
  get_attribute_before_type_cast(attr)[1]
13
13
  end