lib/active_ldap/adapter/base.rb in activeldap-1.0.2 vs lib/active_ldap/adapter/base.rb in activeldap-1.0.9

- old
+ new

@@ -22,10 +22,12 @@ attr_reader :runtime def initialize(configuration={}) @runtime = 0 @connection = nil @disconnected = false + @bound = false + @bind_tried = false @entry_attributes = {} @configuration = configuration.dup @logger = @configuration.delete(:logger) @configuration.assert_valid_keys(VALID_ADAPTER_CONFIGURATION_KEYS) VALID_ADAPTER_CONFIGURATION_KEYS.each do |name| @@ -42,27 +44,31 @@ host = options[:host] || @host method = options[:method] || @method || :plain port = options[:port] || @port || ensure_port(method) method = ensure_method(method) @disconnected = false + @bound = false + @bind_tried = false @connection, @uri, @with_start_tls = yield(host, port, method) prepare_connection(options) bind(options) end def disconnect!(options={}) - return if @connection.nil? unbind(options) @connection = @uri = @with_start_tls = nil + @disconnected = true end def rebind(options={}) unbind(options) if bound? connect(options) end def bind(options={}) + @bind_tried = true + bind_dn = options[:bind_dn] || @bind_dn try_sasl = options.has_key?(:try_sasl) ? options[:try_sasl] : @try_sasl if options.has_key?(:allow_anonymous) allow_anonymous = options[:allow_anonymous] else @@ -84,23 +90,31 @@ message = yield if block_given? message ||= _('All authentication methods for %s exhausted.') % target raise AuthenticationError, message end - bound? + @bound = true + @bound end + def unbind(options={}) + yield if @connection and (@bind_tried or bound?) + @bind_tried = @bound = false + end + def bind_as_anonymous(options={}) - operation(options) do - yield - end + yield end def connecting? !@connection.nil? and !@disconnected end + def bound? + connecting? and @bound + end + def schema(options={}) @schema ||= operation(options) do base = options[:base] attrs = options[:attributes] @@ -162,11 +176,10 @@ end def delete(targets, options={}) targets = [targets] unless targets.is_a?(Array) return if targets.empty? - target = nil begin operation(options) do targets.each do |target| begin yield(target) @@ -291,15 +304,23 @@ passwd end def with_timeout(try_reconnect=true, options={}, &block) + n_retries = 0 + retry_limit = options[:retry_limit] || @retry_limit begin Timeout.alarm(@timeout, &block) rescue Timeout::Error => e @logger.error {_('Requested action timed out.')} - retry if @retry_on_timeout and try_reconnect and reconnect(options) + if @retry_on_timeout and retry_limit < 0 and n_retries <= retry_limit + if connecting? + retry + elsif try_reconnect + retry if with_timeout(false, options) {reconnect(options)} + end + end @logger.error {e.message} raise TimeoutError, e.message end end @@ -316,14 +337,11 @@ end sasl_mechanisms = options[:sasl_mechanisms] || @sasl_mechanisms sasl_mechanisms.each do |mechanism| next unless mechanisms.include?(mechanism) - operation(options) do - yield(bind_dn, mechanism, sasl_quiet) - return true if bound? - end + return true if yield(bind_dn, mechanism, sasl_quiet) end false end def simple_bind(bind_dn, options={}) @@ -341,14 +359,11 @@ _("Can't use empty password for simple bind.") end end begin - operation(options) do - yield(bind_dn, passwd) - bound? - end + yield(bind_dn, passwd) rescue LdapError::InvalidDnSyntax raise DistinguishedNameInvalid.new(bind_dn) rescue LdapError::InvalidCredentials false end @@ -482,11 +497,15 @@ value.gsub(/(?:[()\\\0]|\*\*?)/) do |s| if s == "*" s else s = "*" if s == "**" - "\\%02X" % s[0] + if s.respond_to?(:getbyte) + "\\%02X" % s.getbyte(0) + else + "\\%02X" % s[0] + end end end end def construct_filter(components, operator=nil) @@ -542,51 +561,56 @@ retry_limit = options[:retry_limit] || @retry_limit retry_wait = options[:retry_wait] || @retry_wait options[:reconnect_attempts] ||= 0 loop do - unless can_reconnect?(options) - raise ConnectionError, - _('Giving up trying to reconnect to LDAP server.') - end - @logger.debug {_('Attempting to reconnect')} disconnect! # Reset the attempts if this was forced. options[:reconnect_attempts] = 0 if force options[:reconnect_attempts] += 1 if retry_limit >= 0 begin connect(options) break + rescue AuthenticationError + raise rescue => detail @logger.error do _("Reconnect to server failed: %s\n" \ "Reconnect to server failed backtrace:\n" \ "%s") % [detail.exception, detail.backtrace.join("\n")] end # Do not loop if forced raise ConnectionError, detail.message if force end + unless can_reconnect?(options) + raise ConnectionError, + _('Giving up trying to reconnect to LDAP server.') + end + # Sleep before looping sleep retry_wait end true end def reconnect_if_need(options={}) - reconnect(options) if !connecting? and can_reconnect?(options) + return if connecting? + with_timeout(false, options) do + reconnect(options) + end end # Determine if we have exceed the retry limit or not. # True is reconnecting is allowed - False if not. def can_reconnect?(options={}) retry_limit = options[:retry_limit] || @retry_limit reconnect_attempts = options[:reconnect_attempts] || 0 - retry_limit < 0 or reconnect_attempts < (retry_limit - 1) + retry_limit < 0 or reconnect_attempts <= retry_limit end def root_dse_values(key, options={}) dse = root_dse([key], options)[0] return [] if dse.nil?