Michael Granger avatar Michael Granger committed ccc779e

Checkpoint commit to toplevel patch

Comments (0)

Files changed (1)

  
  	self.rdoc_locations << "deveiate:/usr/local/www/public/code/#{remote_rdoc_dir}"
  end
+diff --git a/ext/connection.c b/ext/connection.c
+new file mode 100644
+--- /dev/null
++++ b/ext/connection.c
+@@ -0,0 +1,202 @@
++/*
++ * Ruby-OpenLDAP -- a Ruby binding to OpenLDAP's libldap
++ * $Id$
++ *
++ * Authors
++ *
++ * - Michael Granger <ged@FaerieMUD.org>
++ *
++ * Copyright (c) 2011 Michael Granger
++ *
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without modification, are
++ * permitted provided that the following conditions are met:
++ *
++ *  * Redistributions of source code must retain the above copyright notice, this
++ *    list of conditions and the following disclaimer.
++ *
++ *  * Redistributions in binary form must reproduce the above copyright notice, this
++ *    list of conditions and the following disclaimer in the documentation and/or
++ *    other materials provided with the distribution.
++ *
++ *  * Neither the name of the authors, nor the names of its contributors may be used to
++ *    endorse or promote products derived from this software without specific prior
++ *    written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
++ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ *
++ */
++
++#include "openldap.h"
++
++
++/* --------------------------------------------------------------
++ * Declarations
++ * -------------------------------------------------------------- */
++VALUE ropenldap_cOpenLDAPConnection;
++
++
++/* --------------------------------------------------
++ *	Memory-management functions
++ * -------------------------------------------------- */
++
++/*
++ * Allocation function
++ */
++static struct ropenldap_connection *
++ropenldap_conn_alloc( LDAP *ldp )
++{
++	struct ropenldap_connection *ptr = ALLOC( struct ropenldap_connection );
++
++	ptr->ldap = ldp;
++
++	return ptr;
++}
++
++
++/*
++ * GC Mark function
++ */
++static void
++ropenldap_conn_gc_mark( struct ropenldap_connection *ptr )
++{
++	/* No-op */
++}
++
++
++
++/*
++ * GC Free function
++ */
++static void
++ropenldap_conn_gc_free( struct ropenldap_connection *ptr )
++{
++	if ( ptr ) {
++		ptr->ldap = NULL;
++
++		xfree( ptr );
++		ptr = NULL;
++	}
++}
++
++
++/*
++ * Object validity checker. Returns the data pointer.
++ */
++static struct ropenldap_connection *
++check_conn( VALUE self )
++{
++	Check_Type( self, T_DATA );
++
++    if ( !IsConnection(self) ) {
++		rb_raise( rb_eTypeError, "wrong argument type %s (expected an OpenLDAP::Connection)",
++				  rb_obj_classname( self ) );
++    }
++
++	return DATA_PTR( self );
++}
++
++
++/*
++ * Fetch the data pointer and check it for sanity.
++ */
++static struct ropenldap_connection *
++ropenldap_get_conn( VALUE self )
++{
++	struct ropenldap_connection *conn = check_conn( self );
++
++	if ( !conn ) rb_fatal( "Use of uninitialized OpenLDAP::Connection" );
++
++	return conn;
++}
++
++
++
++/* --------------------------------------------------------------
++ * Class methods
++ * -------------------------------------------------------------- */
++
++/*
++ *  call-seq:
++ *     OpenLDAP::Connection.allocate   -> store
++ *
++ *  Allocate a new OpenLDAP::Connection object.
++ *
++ */
++static VALUE
++ropenldap_conn_s_allocate( VALUE klass ) {
++	return Data_Wrap_Struct( klass, ropenldap_conn_gc_mark, ropenldap_conn_gc_free, 0 );
++}
++
++
++/* --------------------------------------------------------------
++ * Instance methods
++ * -------------------------------------------------------------- */
++
++/*
++ *  call-seq:
++ *     OpenLDAP::Connection.new( url )           -> conn
++ *
++ *  Create a new OpenLDAP::Connection object using the given +uri+.
++ *
++ */
++static VALUE
++ropenldap_conn_initialize( VALUE self, VALUE uristring ) {
++	ropenldap_log_obj( self, "debug", "Initializing 0x%x", self );
++
++	if ( !check_conn(self) ) {
++		LDAP *ldp = NULL;
++		char *uri = StringValueCStr( uristring );
++		struct ropenldap_connection *conn;
++		int result = 0;
++
++		result = ldap_initialize( &ldp, uri );
++		ropenldap_check_result( ldp, result );
++		ropenldap_log_obj( self, "info", "Created a new %s (%s)", rb_obj_classname(self), uri );
++
++		conn = DATA_PTR( self ) = ropenldap_conn_alloc( ldp );
++
++	} else {
++		rb_raise( ropenldap_eOpenLDAPError,
++				  "Cannot re-initialize a store once it's been created." );
++	}
++
++	return Qnil;
++}
++
++
++
++
++
++/*
++ * OpenLDAP Connection class
++ */
++void
++ropenldap_init_connection( void ) {
++	ropenldap_log( "debug", "Initializing OpenLDAP::Connection" );
++
++#ifdef FOR_RDOC
++	ropenldap_mOpenLDAP = rb_define_module( "OpenLDAP" );
++#endif
++
++	/* OpenLDAP::Connection */
++	ropenldap_cOpenLDAPConnection =
++		rb_define_class_under( ropenldap_mOpenLDAP, "Connection", rb_cObject );
++	rb_define_alloc_func( ropenldap_cOpenLDAPConnection, ropenldap_conn_s_allocate );
++
++	rb_define_method( ropenldap_cOpenLDAPConnection, "initialize", ropenldap_conn_initialize, 1 );
++
++}
++
 diff --git a/ext/extconf.rb b/ext/extconf.rb
 --- a/ext/extconf.rb
 +++ b/ext/extconf.rb
 diff --git a/ext/openldap.c b/ext/openldap.c
 --- a/ext/openldap.c
 +++ b/ext/openldap.c
-@@ -43,9 +43,176 @@
+@@ -43,9 +43,303 @@
  
  VALUE ropenldap_mOpenLDAP;
  
++VALUE ropenldap_eOpenLDAPError;
++
++
 +/* --------------------------------------------------------------
 + * Logging Functions
 + * -------------------------------------------------------------- */
 + */
 +void
 +#ifdef HAVE_STDARG_PROTOTYPES
-+ropenldap_log_with_context( VALUE context, const char *level, const char *fmt, ... ) 
++ropenldap_log_obj( VALUE context, const char *level, const char *fmt, ... )
 +#else
-+ropenldap_log_with_context( VALUE context, const char *level, const char *fmt, va_dcl ) 
++ropenldap_log_obj( VALUE context, const char *level, const char *fmt, va_dcl )
 +#endif
 +{
 +	char buf[BUFSIZ];
 +	va_start( args, fmt );
 +	vsnprintf( buf, BUFSIZ, fmt, args );
 +	message = rb_str_new2( buf );
-+	
++
 +	logger = rb_funcall( context, rb_intern("log"), 0, 0 );
 +	rb_funcall( logger, rb_intern(level), 1, message );
 +
 +}
 +
 +
-+/* 
++/*
 + * Log a message to the global logger.
 + */
 +void
 +#ifdef HAVE_STDARG_PROTOTYPES
-+ropenldap_log( const char *level, const char *fmt, ... ) 
++ropenldap_log( const char *level, const char *fmt, ... )
 +#else
-+ropenldap_log( const char *level, const char *fmt, va_dcl ) 
++ropenldap_log( const char *level, const char *fmt, va_dcl )
 +#endif
 +{
 +	char buf[BUFSIZ];
 +	va_init_list( args, fmt );
 +	vsnprintf( buf, BUFSIZ, fmt, args );
 +	message = rb_str_new2( buf );
-+	
++
 +	logger = rb_funcall( ropenldap_mOpenLDAP, rb_intern("logger"), 0, 0 );
 +	rb_funcall( logger, rb_intern(level), 1, message );
 +
 +}
 +
 +
++/* 
++ * Raise an appropriate exception with an appropriate message for the given
++ * resultcode.
++ */
++void
++ropenldap_check_result( LDAP *ldp, int resultcode )
++{
++	if ( resultcode == LDAP_SUCCESS ) return;
++
++	
++}
++
 +
 +/*
 + * Convert an array of string pointers to a Ruby Array of Strings.
 +		ropenldap_log( "debug", "  adding %s to string array", *iter );
 +		rb_ary_push( ary, rb_str_new2(*iter) );
 +	}
-+	
++
 +	return ary;
 +}
 +
 +}
 +
 +
++/*
++ * call-seq:
++ *    OpenLDAP.err2string( resultcode )   -> string
++ *
++ * Return a short description of the +resultcode+ returned by routines in this library.
++ *
++ */
++static VALUE
++ropenldap_s_err2string( VALUE _, VALUE resultcode )
++{
++	int err = FIX2INT( resultcode );
++	char *string = ldap_err2string( err );
++
++	return rb_str_new2( string );
++}
++
++
++
  void
  Init_openldap_ext( void )
  {
  	ropenldap_mOpenLDAP = rb_define_module( "OpenLDAP" );
 +
-+	
++	ropenldap_eOpenLDAPError = rb_define_class_under( ropenldap_mOpenLDAP, "Error", rb_eRuntimeError );
 +
++	/* Constants */
++
++	/* versions */
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_API_VERSION", INT2FIX(LDAP_API_VERSION) );
++
++	/* search scopes */
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_SCOPE_BASE", INT2FIX(LDAP_SCOPE_BASE) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_SCOPE_BASEOBJECT", INT2FIX(LDAP_SCOPE_BASEOBJECT) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_SCOPE_ONELEVEL", INT2FIX(LDAP_SCOPE_ONELEVEL) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_SCOPE_ONE", INT2FIX(LDAP_SCOPE_ONE) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_SCOPE_SUBTREE", INT2FIX(LDAP_SCOPE_SUBTREE) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_SCOPE_SUB", INT2FIX(LDAP_SCOPE_SUB) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_SCOPE_SUBORDINATE", INT2FIX(LDAP_SCOPE_SUBORDINATE) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_SCOPE_CHILDREN", INT2FIX(LDAP_SCOPE_CHILDREN) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_SCOPE_DEFAULT", INT2FIX(LDAP_SCOPE_DEFAULT) );
++
++	/* result codes */
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_SUCCESS", INT2FIX(LDAP_SUCCESS) );
++
++ 	rb_define_const( ropenldap_mOpenLDAP, "LDAP_OPERATIONS_ERROR", INT2FIX(LDAP_OPERATIONS_ERROR) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_PROTOCOL_ERROR", INT2FIX(LDAP_PROTOCOL_ERROR) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_TIMELIMIT_EXCEEDED", INT2FIX(LDAP_TIMELIMIT_EXCEEDED) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_SIZELIMIT_EXCEEDED", INT2FIX(LDAP_SIZELIMIT_EXCEEDED) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_COMPARE_FALSE", INT2FIX(LDAP_COMPARE_FALSE) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_COMPARE_TRUE", INT2FIX(LDAP_COMPARE_TRUE) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_AUTH_METHOD_NOT_SUPPORTED", INT2FIX(LDAP_AUTH_METHOD_NOT_SUPPORTED) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_STRONG_AUTH_NOT_SUPPORTED", INT2FIX(LDAP_STRONG_AUTH_NOT_SUPPORTED) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_STRONG_AUTH_REQUIRED", INT2FIX(LDAP_STRONG_AUTH_REQUIRED) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_STRONGER_AUTH_REQUIRED", INT2FIX(LDAP_STRONGER_AUTH_REQUIRED) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_PARTIAL_RESULTS", INT2FIX(LDAP_PARTIAL_RESULTS) );
++
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_REFERRAL", INT2FIX(LDAP_REFERRAL) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_ADMINLIMIT_EXCEEDED", INT2FIX(LDAP_ADMINLIMIT_EXCEEDED) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_UNAVAILABLE_CRITICAL_EXTENSION", INT2FIX(LDAP_UNAVAILABLE_CRITICAL_EXTENSION) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_CONFIDENTIALITY_REQUIRED", INT2FIX(LDAP_CONFIDENTIALITY_REQUIRED) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_SASL_BIND_IN_PROGRESS", INT2FIX(LDAP_SASL_BIND_IN_PROGRESS) );
++
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_NO_SUCH_ATTRIBUTE", INT2FIX(LDAP_NO_SUCH_ATTRIBUTE) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_UNDEFINED_TYPE", INT2FIX(LDAP_UNDEFINED_TYPE) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_INAPPROPRIATE_MATCHING", INT2FIX(LDAP_INAPPROPRIATE_MATCHING) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_CONSTRAINT_VIOLATION", INT2FIX(LDAP_CONSTRAINT_VIOLATION) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_TYPE_OR_VALUE_EXISTS", INT2FIX(LDAP_TYPE_OR_VALUE_EXISTS) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_INVALID_SYNTAX", INT2FIX(LDAP_INVALID_SYNTAX) );
++
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_NO_SUCH_OBJECT", INT2FIX(LDAP_NO_SUCH_OBJECT) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_ALIAS_PROBLEM", INT2FIX(LDAP_ALIAS_PROBLEM) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_INVALID_DN_SYNTAX", INT2FIX(LDAP_INVALID_DN_SYNTAX) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_IS_LEAF", INT2FIX(LDAP_IS_LEAF) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_ALIAS_DEREF_PROBLEM", INT2FIX(LDAP_ALIAS_DEREF_PROBLEM) );
++
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_X_PROXY_AUTHZ_FAILURE", INT2FIX(LDAP_X_PROXY_AUTHZ_FAILURE) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_INAPPROPRIATE_AUTH", INT2FIX(LDAP_INAPPROPRIATE_AUTH) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_INVALID_CREDENTIALS", INT2FIX(LDAP_INVALID_CREDENTIALS) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_INSUFFICIENT_ACCESS", INT2FIX(LDAP_INSUFFICIENT_ACCESS) );
++
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_BUSY", INT2FIX(LDAP_BUSY) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_UNAVAILABLE", INT2FIX(LDAP_UNAVAILABLE) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_UNWILLING_TO_PERFORM", INT2FIX(LDAP_UNWILLING_TO_PERFORM) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_LOOP_DETECT", INT2FIX(LDAP_LOOP_DETECT) );
++
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_NAMING_VIOLATION", INT2FIX(LDAP_NAMING_VIOLATION) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_OBJECT_CLASS_VIOLATION", INT2FIX(LDAP_OBJECT_CLASS_VIOLATION) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_NOT_ALLOWED_ON_NONLEAF", INT2FIX(LDAP_NOT_ALLOWED_ON_NONLEAF) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_NOT_ALLOWED_ON_RDN", INT2FIX(LDAP_NOT_ALLOWED_ON_RDN) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_ALREADY_EXISTS", INT2FIX(LDAP_ALREADY_EXISTS) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_NO_OBJECT_CLASS_MODS", INT2FIX(LDAP_NO_OBJECT_CLASS_MODS) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_RESULTS_TOO_LARGE", INT2FIX(LDAP_RESULTS_TOO_LARGE) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_AFFECTS_MULTIPLE_DSAS", INT2FIX(LDAP_AFFECTS_MULTIPLE_DSAS) );
++
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_VLV_ERROR", INT2FIX(LDAP_VLV_ERROR) );
++
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_OTHER", INT2FIX(LDAP_OTHER) );
++
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_SERVER_DOWN", INT2FIX(LDAP_SERVER_DOWN) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_LOCAL_ERROR", INT2FIX(LDAP_LOCAL_ERROR) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_ENCODING_ERROR", INT2FIX(LDAP_ENCODING_ERROR) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_DECODING_ERROR", INT2FIX(LDAP_DECODING_ERROR) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_TIMEOUT", INT2FIX(LDAP_TIMEOUT) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_AUTH_UNKNOWN", INT2FIX(LDAP_AUTH_UNKNOWN) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_FILTER_ERROR", INT2FIX(LDAP_FILTER_ERROR) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_USER_CANCELLED", INT2FIX(LDAP_USER_CANCELLED) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_PARAM_ERROR", INT2FIX(LDAP_PARAM_ERROR) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_NO_MEMORY", INT2FIX(LDAP_NO_MEMORY) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_CONNECT_ERROR", INT2FIX(LDAP_CONNECT_ERROR) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_NOT_SUPPORTED", INT2FIX(LDAP_NOT_SUPPORTED) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_CONTROL_NOT_FOUND", INT2FIX(LDAP_CONTROL_NOT_FOUND) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_NO_RESULTS_RETURNED", INT2FIX(LDAP_NO_RESULTS_RETURNED) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_MORE_RESULTS_TO_RETURN", INT2FIX(LDAP_MORE_RESULTS_TO_RETURN) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_CLIENT_LOOP", INT2FIX(LDAP_CLIENT_LOOP) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_REFERRAL_LIMIT_EXCEEDED", INT2FIX(LDAP_REFERRAL_LIMIT_EXCEEDED) );
++	rb_define_const( ropenldap_mOpenLDAP, "LDAP_X_CONNECTING", INT2FIX(LDAP_X_CONNECTING) );
++
++	/* Module functions */
 +	rb_define_singleton_method( ropenldap_mOpenLDAP, "split_url", ropenldap_s_split_url, 1 );
++	rb_define_singleton_method( ropenldap_mOpenLDAP, "err2string", ropenldap_s_err2string, 1 );
 +
  }
  
  
  #include <ldap.h>
  
-@@ -44,6 +45,19 @@
+@@ -22,6 +23,8 @@
+ 
+ extern VALUE ropenldap_cOpenLDAPConnection;
+ 
++extern VALUE ropenldap_eOpenLDAPError;
++
+ 
+ /* --------------------------------------------------------------
+  * Typedefs
+@@ -44,12 +47,27 @@
   * Declarations
   * -------------------------------------------------------------- */
  
 +#ifdef HAVE_STDARG_PROTOTYPES
 +#include <stdarg.h>
 +#define va_init_list(a,b) va_start(a,b)
-+void ropenldap_log_with_context( VALUE, const char *, const char *, ... );
++void ropenldap_log_obj( VALUE, const char *, const char *, ... );
 +void ropenldap_log( const char *, const char *, ... );
 +#else
 +#include <varargs.h>
 +#define va_init_list(a,b) va_start(a)
-+void ropenldap_log_with_context( VALUE, const char *, const char *, va_dcl );
++void ropenldap_log_obj( VALUE, const char *, const char *, va_dcl );
 +void ropenldap_log( const char *, const char *, va_dcl );
 +#endif
 +
++void ropenldap_check_result				_(( LDAP *, int ));
 +
  
  /* --------------------------------------------------------------
   * Initializers
+  * -------------------------------------------------------------- */
+ 
+-void Init_openldap_ext( void );
++void Init_openldap_ext					_(( void ));
++void ropenldap_init_connection			_(( void ));
+ 
+ 
+ #endif /* __OPENLDAP_H__ */
 diff --git a/lib/openldap.rb b/lib/openldap.rb
 --- a/lib/openldap.rb
 +++ b/lib/openldap.rb
-@@ -12,7 +12,69 @@
+@@ -12,7 +12,68 @@
  	# Version-control revision constant
  	REVISION = %q$Revision$
  
 +		return vstring
 +	end
 +
-+
 +	### Load the extension
  	begin
  		require 'openldap_ext'
  	rescue LoadError => err
+@@ -27,5 +88,8 @@
+ 
+ 	end
+ 
++	# Load the Ruby parts of the library
++	require 'openldap/exceptions'
++
+ end # module OpenLDAP
+ 
+diff --git a/lib/openldap/exceptions.rb b/lib/openldap/exceptions.rb
+new file mode 100644
+--- /dev/null
++++ b/lib/openldap/exceptions.rb
+@@ -0,0 +1,159 @@
++#!/usr/bin/env ruby
++
++require 'openldap' unless defined?( OpenLDAP )
++
++
++module OpenLDAP
++
++	# A map of result codes to the corresponding exception class
++	RESULT_EXCEPTION_CLASS = {}
++
++	# The base class for all OpenLDAP exceptions
++	class Error < RuntimeError
++
++		# The result code that corresponds to the exception type
++		@result_code = nil
++		class << self; attr_accessor :result_code; end
++
++		### Inheritance hook -- Initialize the result code class instance variable
++		### for inheriting exception classes.
++		def self::inherited( subclass )
++			subclass.instance_variable_set( :@result_code, nil )
++		end
++
++	end # class Error
++
++
++	### Define a new Exception class named +classname+ for the specified +result_code+
++	### and inheriting from +superclass+.
++	def self::def_ldap_exception( classname, result_code, superclass=OpenLDAP::Error )
++		eclass = Class.new( superclass ) do
++			def initialize( message=nil )
++				ldapmsg = OpenLDAP.err2string( self.class.result_code )
++				ldapmsg += ': ' + message if message
++				super( ldapmsg )
++			end
++		end
++		eclass.result_code = result_code
++
++		const_set( classname, eclass )
++		RESULT_EXCEPTION_CLASS[ result_code ] = eclass
++	end
++
++
++	# The LDAP referral class -- raised when the target LDAP directory instructs
++	# the client to refer to another directory
++	class Referral < OpenLDAP::Error
++
++		### Create a new referral to the specified +url+.
++		def initialize( url )
++			super( "Referral to #{url}" )
++			@url = url
++		end
++
++		######
++		public
++		######
++
++		# The URL of the directory to refer to
++		attr_reader :url
++
++	end # class Referral
++
++
++	def_ldap_exception :OperationsError, LDAP_OPERATIONS_ERROR
++	def_ldap_exception :ProtocolError, LDAP_PROTOCOL_ERROR
++	def_ldap_exception :TimelimitExceeded, LDAP_TIMELIMIT_EXCEEDED
++	def_ldap_exception :SizelimitExceeded, LDAP_SIZELIMIT_EXCEEDED
++	def_ldap_exception :CompareFalse, LDAP_COMPARE_FALSE
++	def_ldap_exception :CompareTrue, LDAP_COMPARE_TRUE
++	def_ldap_exception :AuthMethodNotSupported, LDAP_AUTH_METHOD_NOT_SUPPORTED
++	def_ldap_exception :StrongAuthRequired, LDAP_STRONG_AUTH_REQUIRED
++	def_ldap_exception :PartialResults, LDAP_PARTIAL_RESULTS
++	def_ldap_exception :AdminlimitExceeded, LDAP_ADMINLIMIT_EXCEEDED
++	def_ldap_exception :UnavailableCriticalExtension, LDAP_UNAVAILABLE_CRITICAL_EXTENSION
++	def_ldap_exception :ConfidentialityRequired, LDAP_CONFIDENTIALITY_REQUIRED
++	def_ldap_exception :SASLBindInProgress, LDAP_SASL_BIND_IN_PROGRESS
++
++	#define LDAP_ATTR_ERROR(n)	LDAP_RANGE((n),0x10,0x15) /* 16-21 */
++	class AttrError < OpenLDAP::Error; end
++
++	def_ldap_exception :NoSuchAttribute, LDAP_NO_SUCH_ATTRIBUTE, OpenLDAP::AttrError
++	def_ldap_exception :UndefinedType, LDAP_UNDEFINED_TYPE, OpenLDAP::AttrError
++	def_ldap_exception :InappropriateMatching, LDAP_INAPPROPRIATE_MATCHING, OpenLDAP::AttrError
++	def_ldap_exception :ConstraintViolation, LDAP_CONSTRAINT_VIOLATION, OpenLDAP::AttrError
++	def_ldap_exception :TypeOrValueExists, LDAP_TYPE_OR_VALUE_EXISTS, OpenLDAP::AttrError
++	def_ldap_exception :InvalidSyntax, LDAP_INVALID_SYNTAX, OpenLDAP::AttrError
++
++	#define LDAP_NAME_ERROR(n)	LDAP_RANGE((n),0x20,0x24) /* 32-34,36 */
++	class NameError < OpenLDAP::Error; end
++
++	def_ldap_exception :NoSuchObject, LDAP_NO_SUCH_OBJECT, OpenLDAP::NameError
++	def_ldap_exception :AliasProblem, LDAP_ALIAS_PROBLEM, OpenLDAP::NameError
++	def_ldap_exception :InvalidDNSyntax, LDAP_INVALID_DN_SYNTAX, OpenLDAP::NameError
++	def_ldap_exception :IsLeaf, LDAP_IS_LEAF, OpenLDAP::NameError
++	def_ldap_exception :AliasDerefProblem, LDAP_ALIAS_DEREF_PROBLEM, OpenLDAP::NameError
++
++	#define LDAP_SECURITY_ERROR(n)	LDAP_RANGE((n),0x2F,0x32) /* 47-50 */
++	class SecurityError < OpenLDAP::Error; end
++
++	def_ldap_exception :XProxyAuthzFailure, LDAP_X_PROXY_AUTHZ_FAILURE, OpenLDAP::SecurityError
++	def_ldap_exception :InappropriateAuth, LDAP_INAPPROPRIATE_AUTH, OpenLDAP::SecurityError
++	def_ldap_exception :InvalidCredentials, LDAP_INVALID_CREDENTIALS, OpenLDAP::SecurityError
++	def_ldap_exception :InsufficientAccess, LDAP_INSUFFICIENT_ACCESS, OpenLDAP::SecurityError
++
++	#define LDAP_SERVICE_ERROR(n)	LDAP_RANGE((n),0x33,0x36) /* 51-54 */
++	class ServiceError < OpenLDAP::Error; end
++
++	def_ldap_exception :Busy, LDAP_BUSY, OpenLDAP::ServiceError
++	def_ldap_exception :Unavailable, LDAP_UNAVAILABLE, OpenLDAP::ServiceError
++	def_ldap_exception :UnwillingToPerform, LDAP_UNWILLING_TO_PERFORM, OpenLDAP::ServiceError
++	def_ldap_exception :LoopDetect, LDAP_LOOP_DETECT, OpenLDAP::ServiceError
++
++	#define LDAP_UPDATE_ERROR(n)	LDAP_RANGE((n),0x40,0x47) /* 64-69,71 */
++	class UpdateError < OpenLDAP::Error; end
++
++	def_ldap_exception :NamingViolation, LDAP_NAMING_VIOLATION, OpenLDAP::UpdateError
++	def_ldap_exception :ObjectClassViolation, LDAP_OBJECT_CLASS_VIOLATION, OpenLDAP::UpdateError
++	def_ldap_exception :NotAllowedOnNonleaf, LDAP_NOT_ALLOWED_ON_NONLEAF, OpenLDAP::UpdateError
++	def_ldap_exception :NotAllowedOnRdn, LDAP_NOT_ALLOWED_ON_RDN, OpenLDAP::UpdateError
++	def_ldap_exception :AlreadyExists, LDAP_ALREADY_EXISTS, OpenLDAP::UpdateError
++	def_ldap_exception :NoObjectClassMods, LDAP_NO_OBJECT_CLASS_MODS, OpenLDAP::UpdateError
++	def_ldap_exception :ResultsTooLarge, LDAP_RESULTS_TOO_LARGE, OpenLDAP::UpdateError
++	def_ldap_exception :AffectsMultipleDSAs, LDAP_AFFECTS_MULTIPLE_DSAS, OpenLDAP::UpdateError
++
++	def_ldap_exception :VLVError, LDAP_VLV_ERROR
++
++	# Implementation-specific errors
++	class OtherError < OpenLDAP::Error; end
++
++	# API Error Codes
++	# 
++	# Based on draft-ietf-ldap-c-api-xx
++	# but with new negative code values
++	# 
++	class APIError < OpenLDAP::Error; end
++
++	def_ldap_exception :ServerDown, LDAP_SERVER_DOWN, OpenLDAP::APIError
++	def_ldap_exception :LocalError, LDAP_LOCAL_ERROR, OpenLDAP::APIError
++	def_ldap_exception :EncodingError, LDAP_ENCODING_ERROR, OpenLDAP::APIError
++	def_ldap_exception :DecodingError, LDAP_DECODING_ERROR, OpenLDAP::APIError
++	def_ldap_exception :Timeout, LDAP_TIMEOUT, OpenLDAP::APIError
++	def_ldap_exception :AuthUnknown, LDAP_AUTH_UNKNOWN, OpenLDAP::APIError
++	def_ldap_exception :FilterError, LDAP_FILTER_ERROR, OpenLDAP::APIError
++	def_ldap_exception :UserCancelled, LDAP_USER_CANCELLED, OpenLDAP::APIError
++	def_ldap_exception :ParamError, LDAP_PARAM_ERROR, OpenLDAP::APIError
++	def_ldap_exception :NoMemory, LDAP_NO_MEMORY, OpenLDAP::APIError
++	def_ldap_exception :ConnectError, LDAP_CONNECT_ERROR, OpenLDAP::APIError
++	def_ldap_exception :NotSupported, LDAP_NOT_SUPPORTED, OpenLDAP::APIError
++	def_ldap_exception :ControlNotFound, LDAP_CONTROL_NOT_FOUND, OpenLDAP::APIError
++	def_ldap_exception :NoResultsReturned, LDAP_NO_RESULTS_RETURNED, OpenLDAP::APIError
++	def_ldap_exception :MoreResultsToReturn, LDAP_MORE_RESULTS_TO_RETURN, OpenLDAP::APIError
++	def_ldap_exception :ClientLoop, LDAP_CLIENT_LOOP, OpenLDAP::APIError
++	def_ldap_exception :ReferralLimitExceeded, LDAP_REFERRAL_LIMIT_EXCEEDED, OpenLDAP::APIError
++	def_ldap_exception :XConnecting, LDAP_X_CONNECTING, OpenLDAP::APIError
++
++
++end # module OpenLDAP
++
++
 diff --git a/lib/openldap/mixins.rb b/lib/openldap/mixins.rb
 new file mode 100644
 --- /dev/null
 new file mode 100644
 --- /dev/null
 +++ b/lib/openldap/utils.rb
-@@ -0,0 +1,127 @@
-+#!/usr/bin/ruby
+@@ -0,0 +1,123 @@
++#!/usr/bin/env ruby
 +
 +require 'logger'
 +require 'erb'
-+require 'bigdecimal'
-+require 'date'
 +
-+require 'openldap'
-+require 'openldap/mixins'
-+
++require 'openldap' unless defined?( OpenLDAP )
 +
 +module OpenLDAP # :nodoc:
 +
 +
 +# vim: set nosta noet ts=4 sw=4:
 +
+diff --git a/spec/openldap/connection_spec.rb b/spec/openldap/connection_spec.rb
+new file mode 100644
+--- /dev/null
++++ b/spec/openldap/connection_spec.rb
+@@ -0,0 +1,35 @@
++#!/usr/bin/env rspec -cfd -b
++
++BEGIN {
++	require 'pathname'
++	basedir = Pathname( __FILE__ ).dirname.parent.parent
++	libdir = basedir + 'lib'
++
++	$LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
++	$LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
++}
++
++require 'rspec'
++require 'spec/lib/helpers'
++require 'openldap/connection'
++
++describe OpenLDAP::Connection do
++
++	before( :all ) do
++		setup_logging( :debug )
++	end
++
++	after( :all ) do
++		reset_logging()
++	end
++
++
++	TEST_LDAP_URI = 'ldap://localhost/dc=acme,dc=com'
++
++	it "can be created with an LDAP uri" do
++		OpenLDAP::Connection.new( TEST_LDAP_URI )
++	end
++
++
++end
++
 diff --git a/spec/openldap_spec.rb b/spec/openldap_spec.rb
 --- a/spec/openldap_spec.rb
 +++ b/spec/openldap_spec.rb
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.