From 11eafc253c1281c5a5ae55d4fc187bebedc44626 Mon Sep 17 00:00:00 2001
From: Randy Kunkee <kunkee@openldap.org>
Date: Tue, 3 Aug 1999 07:23:03 +0000
Subject: [PATCH] Ldaptcl package version 1.2:

- Filter no longer a required controlArray member, defaults to objectclass=*.
- Sets errorCode with LDAP macro string value (better to test than the more
  human readable values).
- Shorten minimum required characters for search scope definitions: now allows
  "base", "one", and "sub".  For the latter two, additional characters are
  ignored.
- Now compiles successfully with -devel branch (though less tested).
- Client cache management code enabled for OpenLDAP versions <= 1.2.4.  (This
  code is relatively untested and feedback is welcome.)
- More installation cleanups to work easily as a dynamically loadable Tcl
  package.
---
 contrib/ldaptcl/CHANGES      | 11 +++++
 contrib/ldaptcl/Makefile.in  | 14 ++++--
 contrib/ldaptcl/configure    |  8 ++--
 contrib/ldaptcl/configure.in |  7 +--
 contrib/ldaptcl/ldaperr.tcl  | 33 +++++++++++++
 contrib/ldaptcl/neoXldap.c   | 91 +++++++++++++++++++++++++++---------
 6 files changed, 130 insertions(+), 34 deletions(-)
 create mode 100644 contrib/ldaptcl/CHANGES
 create mode 100644 contrib/ldaptcl/ldaperr.tcl

diff --git a/contrib/ldaptcl/CHANGES b/contrib/ldaptcl/CHANGES
new file mode 100644
index 0000000000..2a7b8ce6ae
--- /dev/null
+++ b/contrib/ldaptcl/CHANGES
@@ -0,0 +1,11 @@
+Package version 1.2:
+
+- Filter no longer a required controlArray member, defaults to objectclass=*.
+- Sets errorCode with LDAP macro string value (better to test than the more
+  human readable values).
+- Shorten minimum required characters for search scope definitions: now allows
+  "base", "one", and "sub".  For the latter two, additional characters are
+  ignored.
+- Now compiles successfully with -devel branch.
+- Client cache management code enabled for OpenLDAP versions <= 1.2.4.  (This
+  code is relatively untested and feedback is welcome.)
diff --git a/contrib/ldaptcl/Makefile.in b/contrib/ldaptcl/Makefile.in
index a7db9517eb..c195b1b392 100644
--- a/contrib/ldaptcl/Makefile.in
+++ b/contrib/ldaptcl/Makefile.in
@@ -85,6 +85,7 @@ SHLIB_LD = @SHLIB_LD@
 
 LDAP_LIBFLAGS	= @ldaplibflags@
 LDAP_CFLAGS	= @ldapinclude@
+LDAP_INCDIR	= @ldapincdir@
 LDAP_BUILD	= @ldapbuild@
 LDAP_DIR	= @ldapdir@
 
@@ -120,13 +121,11 @@ LIBS= @LIBS@ @TCLX_LIB_SPEC@ @TCL_LIB_SPEC@ @TCL_LIBS@ $(LDAP_LIBFLAGS) -lc
 TK_LIBS=@TKX_LIB_SPEC@ @TK_LIB_SPEC@ @TK_LIBS@
 TK_VERSION=@TK_VERSION@
 
-LDAPINCDIR=/usr/local/include
-
 CC =        @CC@
 CC_SWITCHES =   ${CFLAGS} @NEO_SHLIB_CFLAGS@ -I. \
 -I@prefix@/include ${AC_FLAGS} ${PROTO_FLAGS} \
 ${SECURITY_FLAGS} ${MEM_DEBUG_FLAGS} ${KEYSYM_FLAGS} \
--DNEO_LIBRARY=\"${NEO_LIBRARY}\"
+-DNEO_LIBRARY=\"${NEO_LIBRARY}\" -DVERSION=\"${VERSION}\" 
 
 TK_SWITCHES = ${CC_SWITCHES} @TK_XINCLUDES@
 
@@ -140,15 +139,20 @@ all:	@NEO_LIB_FILE@ ldaptclsh @LDAPWISH@
 	@MAKE_LIB@
 	$(RANLIB) @NEO_LIB_FILE@
 
-neoXldap.o: neoXldap.c
+neoXldap.o: neoXldap.c ldaptclerr.h
 	$(CC) -c $(LDAP_CFLAGS) $(CC_SWITCHES) $<
 
+ldaptclerr.h: ldaperr.tcl
+	tcl ldaperr.tcl $(LDAP_INCDIR)/ldap.h > ldaptclerr.h
+	
+
 clean:
 	-rm -f ldaptclsh ldapwish
 	-rm -f *.o *.a *.so*
 
 distclean: clean
-	rm -f Makefile pkgIndex.tcl config.cache config.log config.status
+	rm -f Makefile pkgIndex.tcl config.cache config.log config.status \
+		ldaptclerr.h
 
 install: install-binaries install-man
 
diff --git a/contrib/ldaptcl/configure b/contrib/ldaptcl/configure
index 2acc11f62e..4472c774e4 100755
--- a/contrib/ldaptcl/configure
+++ b/contrib/ldaptcl/configure
@@ -539,11 +539,11 @@ else
 fi
 
 
-# $Id: configure.in,v 1.1 1999/02/10 22:56:49 kunkee Exp $
+# $Id: configure.in,v 1.2 1999/07/27 05:29:27 kunkee Exp $
 
-NEO_VERSION=1.1
+NEO_VERSION=1.2
 NEO_MAJOR_VERSION=1
-NEO_MINOR_VERSION=1
+NEO_MINOR_VERSION=2
 VERSION=${NEO_VERSION}
 
 if test "${prefix}" = "NONE"; then
@@ -1387,6 +1387,7 @@ ldapbuild=yes
 
 
 
+
 VERSION=${NEO_VERSION}
 # Note:  in the following variable, it's important to use the absolute
 # path name of the Tcl directory rather than "..":  this is because
@@ -1596,6 +1597,7 @@ s%@ldaplibflags@%$ldaplibflags%g
 s%@ldapinclude@%$ldapinclude%g
 s%@ldapbuild@%$ldapbuild%g
 s%@ldapdir@%$ldapdir%g
+s%@ldapincdir@%$ldapincdir%g
 s%@DL_LIBS@%$DL_LIBS%g
 s%@LD_FLAGS@%$LD_FLAGS%g
 s%@MATH_LIBS@%$MATH_LIBS%g
diff --git a/contrib/ldaptcl/configure.in b/contrib/ldaptcl/configure.in
index 7efa1aa14a..bed2a399ce 100644
--- a/contrib/ldaptcl/configure.in
+++ b/contrib/ldaptcl/configure.in
@@ -2,11 +2,11 @@ dnl	This file is an input file used by the GNU "autoconf" program to
 dnl	generate the file "configure", which is run during Tk installation
 dnl	to configure the system for the local environment.
 AC_INIT(neoXldap.c)
-# $Id: configure.in,v 1.1 1999/02/10 22:56:49 kunkee Exp $
+# $Id: configure.in,v 1.2 1999/07/27 05:29:27 kunkee Exp $
 
-NEO_VERSION=1.1
+NEO_VERSION=1.2
 NEO_MAJOR_VERSION=1
-NEO_MINOR_VERSION=1
+NEO_MINOR_VERSION=2
 VERSION=${NEO_VERSION}
 
 if test "${prefix}" = "NONE"; then
@@ -169,6 +169,7 @@ AC_SUBST(ldaplibflags)
 AC_SUBST(ldapinclude)
 AC_SUBST(ldapbuild)
 AC_SUBST(ldapdir)
+AC_SUBST(ldapincdir)
 
 
 VERSION=${NEO_VERSION}
diff --git a/contrib/ldaptcl/ldaperr.tcl b/contrib/ldaptcl/ldaperr.tcl
new file mode 100644
index 0000000000..31872f66f9
--- /dev/null
+++ b/contrib/ldaptcl/ldaperr.tcl
@@ -0,0 +1,33 @@
+#
+# ldaperr.tcl: scan ldap.h for error return codes for initializing
+# errorCode table.
+#
+
+proc genstrings {path} {
+    set fp [open $path]
+    while {[gets $fp line] != -1 &&
+	![string match "#define LDAP_SUCCESS*" $line]} { }
+    puts "/* This file automatically generated, hand edit at your own risk! */"
+    puts -nonewline "char *ldaptclerrorcode\[\] = {
+	NULL"
+    set lasterr 0
+    while {[gets $fp line] != -1} {
+	if {[clength $line] == 0 || [ctype space $line]} continue
+	if {![string match #define* $line]} break
+	if {![string match "#define LDAP_*" $line]} continue
+	lassign $line define macro value
+	incr lasterr
+	while {$lasterr < $value} {
+	    puts -nonewline ",\n\tNULL"
+	    incr lasterr
+	}
+	puts -nonewline ",\n\t\"$macro\""
+    }
+    puts "\n};"
+    puts "#define LDAPTCL_MAXERR\t$value"
+}
+
+#cmdtrace on
+if !$tcl_interactive {
+    genstrings [lindex $argv 0]
+}
diff --git a/contrib/ldaptcl/neoXldap.c b/contrib/ldaptcl/neoXldap.c
index 88f55de555..a2c6d90878 100644
--- a/contrib/ldaptcl/neoXldap.c
+++ b/contrib/ldaptcl/neoXldap.c
@@ -23,7 +23,7 @@
  * Requests for permission may be sent to NeoSoft Inc, 1770 St. James Place,
  * Suite 500, Houston, TX, 77056.
  *
- * $Id$
+ * $Id: neoXldap.c,v 1.4 1999/07/27 05:29:27 kunkee Exp $
  *
  */
 
@@ -34,7 +34,7 @@
  * Umich-3.3 client code.  The UMICH_LDAP define is used to include
  * code that will work with the Umich-3.3 LDAP, but not with Netscape's
  * SDK.  OpenLDAP may support some of these, but they have not been tested.
- * Current support is by Randy Kunkee.
+ * Currently supported by Randy Kunkee (kunkee@OpenLDAP.org).
  */
 
 /*
@@ -57,6 +57,8 @@
 
 #define STREQU(str1, str2) \
 	(((str1) [0] == (str2) [0]) && (strcmp (str1, str2) == 0))
+#define STRNEQU(str1, str2, n) \
+	(((str1) [0] == (str2) [0]) && (strncmp (str1, str2, n) == 0))
 
 /*
  * The following section defines some common macros used by the rest
@@ -76,8 +78,13 @@
        */
 #define ldap_attributefree(p) ldap_memfree(p)
 #define ldap_memfree(p) free(p)
+#ifdef LDAP_OPT_ERROR_NUMBER
+#define ldap_get_lderrno(ld)	(ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &lderrno), lderrno)
+#else
+#define ldap_get_lderrno(ld) (ld->ld_errno)
+#endif
 #define LDAP_ERR_STRING(ld)  \
-	ldap_err2string(ldap->ld_errno)
+	ldap_err2string(ldap_get_lderrno(ld))
 #elif defined( LDAP_OPT_SIZELIMIT )
        /*
        ** Netscape SDK w/ ldap_set_option, ldap_get_option
@@ -93,11 +100,38 @@
 #define ldap_ber_free(p, n) ber_free(p, n)
 #define ldap_value_free_len(bvals) ber_bvecfree(bvals)
 #define ldap_attributefree(p) 
+#define ldap_get_lderrno(ld) (ld->ld_errno)
 #define LDAP_ERR_STRING(ld)  \
 	ldap_err2string(ld->ld_errno)
 #endif
 
+typedef struct ldaptclobj {
+    LDAP	*ldap;
+    int		flags
+} LDAPTCL;
+
+#define LDAPTCL_INTERRCODES	0x001
+
+#include "ldaptclerr.h"
 
+static
+LDAP_SetErrorCode(LDAPTCL *ldaptcl, int code, Tcl_Interp *interp)
+{
+    char shortbuf[6];
+    char *errp;
+    int   lderrno;
+
+    if (code == -1)
+	code = ldap_get_lderrno(ldaptcl->ldap);
+    if ((ldaptcl->flags & LDAPTCL_INTERRCODES) || code > LDAPTCL_MAXERR ||
+      ldaptclerrorcode[code] == NULL) {
+	sprintf(shortbuf, "0x%03x", code);
+	errp = shortbuf;
+    } else
+	errp = ldaptclerrorcode[code];
+
+    Tcl_SetErrorCode(interp, errp, NULL);
+}
 
 /*-----------------------------------------------------------------------------
  * LDAP_ProcessOneSearchResult --
@@ -130,6 +164,7 @@ LDAP_ProcessOneSearchResult (interp, ldap, entry, destArrayNameObj, evalCodeObj)
     BerElement     *ber; 
     struct berval **bvals;
     char	   *dn;
+    int		    lderrno;
 
     Tcl_UnsetVar (interp, Tcl_GetStringFromObj (destArrayNameObj, NULL), 0);
 
@@ -210,9 +245,9 @@ LDAP_ProcessOneSearchResult (interp, ldap, entry, destArrayNameObj, evalCodeObj)
  *-----------------------------------------------------------------------------
  */
 static int 
-LDAP_PerformSearch (interp, ldap, base, scope, attrs, filtpatt, value, destArrayNameObj, evalCodeObj, timeout_p)
+LDAP_PerformSearch (interp, ldaptcl, base, scope, attrs, filtpatt, value, destArrayNameObj, evalCodeObj, timeout_p)
     Tcl_Interp     *interp;
-    LDAP           *ldap;
+    LDAPTCL        *ldaptcl;
     char           *base;
     int             scope;
     char          **attrs;
@@ -222,6 +257,7 @@ LDAP_PerformSearch (interp, ldap, base, scope, attrs, filtpatt, value, destArray
     Tcl_Obj        *evalCodeObj;
     struct timeval *timeout_p;
 {
+    LDAP	 *ldap = ldaptcl->ldap;
     char          filter[BUFSIZ];
     int           resultCode;
     int           errorCode;
@@ -232,7 +268,7 @@ LDAP_PerformSearch (interp, ldap, base, scope, attrs, filtpatt, value, destArray
     LDAPMessage  *entryMessage;
 
     Tcl_Obj      *resultObj;
-    int		  lderr;
+    int		  lderrno;
 
     resultObj = Tcl_GetObjResult (interp);
 
@@ -243,6 +279,7 @@ LDAP_PerformSearch (interp, ldap, base, scope, attrs, filtpatt, value, destArray
 			        "LDAP start search error: ",
 					LDAP_ERR_STRING(ldap),
 			        (char *)NULL);
+	LDAP_SetErrorCode(ldaptcl, -1, interp);
 	return TCL_ERROR;
     }
 
@@ -297,6 +334,7 @@ LDAP_PerformSearch (interp, ldap, base, scope, attrs, filtpatt, value, destArray
 				      ldap_err2string(errorCode),
 				      (char *)NULL);
 	      ldap_msgfree(resultMessage);
+	      LDAP_SetErrorCode(ldaptcl, errorCode, interp);
 	      return TCL_ERROR;
 	    }
 	}
@@ -307,6 +345,7 @@ LDAP_PerformSearch (interp, ldap, base, scope, attrs, filtpatt, value, destArray
 				    "LDAP result search error: ",
 				    LDAP_ERR_STRING(ldap),
 				    (char *)NULL);
+	    LDAP_SetErrorCode(ldaptcl, -1, interp);
 	    return TCL_ERROR;
 	} else
 	    ldap_msgfree(resultMessage);
@@ -336,7 +375,8 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv)
 {
     char         *command;
     char         *subCommand;
-    LDAP         *ldap = (LDAP *)clientData;
+    LDAPTCL      *ldaptcl = (LDAPTCL *)clientData;
+    LDAP         *ldap = ldaptcl->ldap;
     char         *dn;
     int           is_add = 0;
     int           is_add_or_modify = 0;
@@ -422,6 +462,7 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv)
 			            "LDAP bind error: ",
 				    ldap_err2string(errcode),
 				    (char *)NULL);
+	    LDAP_SetErrorCode(ldaptcl, errcode, interp);
 	    return TCL_ERROR;
 	}
 	return TCL_OK;
@@ -445,6 +486,7 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv)
 			           "LDAP delete error: ",
 				   ldap_err2string(errcode),
 				   (char *)NULL);
+	   LDAP_SetErrorCode(ldaptcl, errcode, interp);
 	   return TCL_ERROR;
        }
        return TCL_OK;
@@ -473,6 +515,7 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv)
 				    " error: ",
 				    ldap_err2string(errcode),
 				    (char *)NULL);
+	    LDAP_SetErrorCode(ldaptcl, errcode, interp);
 	    return TCL_ERROR;
 	}
 	return TCL_OK;
@@ -594,6 +637,7 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv)
 				    " error: ",
 				    ldap_err2string(result),
 				    (char *)NULL);
+	    LDAP_SetErrorCode(ldaptcl, result, interp);
 	    return TCL_ERROR;
 	}
 	return TCL_OK;
@@ -657,14 +701,7 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv)
 				           "filter",
 				           0);
 	if (filterPatternString == (char *)NULL) {
-	    Tcl_AppendStringsToObj (resultObj,
-				    "required element \"filter\" ",
-				    "is missing from ldap control array \"",
-				    controlArrayName,
-				    "\"",
-				    (char *)NULL);
-
-	    return TCL_ERROR;
+	    filterPatternString = "objectclass=*";
 	}
 
 	/* Fetch scope setting from control array.
@@ -676,16 +713,16 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv)
 	} else {
 	    if (STREQU(scopeString, "base")) 
 		scope = LDAP_SCOPE_BASE;
-	    else if (STREQU(scopeString, "onelevel"))
+	    else if (STRNEQU(scopeString, "one", 3))
 		scope = LDAP_SCOPE_ONELEVEL;
-	    else if (STREQU(scopeString, "subtree"))
+	    else if (STRNEQU(scopeString, "sub", 3))
 		scope = LDAP_SCOPE_SUBTREE;
 	    else {
 		Tcl_AppendStringsToObj (resultObj,
 				        "\"scope\" element of \"",
 				        controlArrayName,
 				        "\" array is not one of ",
-				        "\"base\", \"one_level\", ",
+				        "\"base\", \"onelevel\", ",
 					"or \"subtree\"",
 				      (char *) NULL);
 		return TCL_ERROR;
@@ -766,7 +803,7 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv)
 #endif
 
 	 return LDAP_PerformSearch (interp, 
-			            ldap, 
+			            ldaptcl, 
 			            baseString, 
 			            scope, 
 			            attributesArray, 
@@ -777,7 +814,7 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv)
 				    timeout_p);
     }
 
-#if UMICH_LDAP
+#if defined(UMICH_LDAP) || (defined(OPEN_LDAP) && !defined(LDAP_API_VERSION))
     if (STREQU (subCommand, "cache")) {
 	char *cacheCommand;
 
@@ -822,6 +859,7 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv)
 					"LDAP cache enable error: ",
 					LDAP_ERR_STRING(ldap),
 					(char *)NULL);
+		LDAP_SetErrorCode(ldaptcl, -1, interp);
 		return TCL_ERROR;
 	    }
 	    return TCL_OK;
@@ -907,9 +945,11 @@ static void
 NeoX_LdapObjDeleteCmd(clientData)
     ClientData    clientData;
 {
-    LDAP         *ldap = (LDAP *)clientData;
+    LDAPTCL      *ldaptcl = (LDAPTCL *)clientData;
+    LDAP         *ldap = ldaptcl->ldap;
 
     ldap_unbind(ldap);
+    ckfree((char*) ldaptcl);
 }
 
 /*-----------------------------------------------------------------------------
@@ -939,6 +979,7 @@ NeoX_LdapObjCmd (clientData, interp, objc, objv)
     char         *ldapHost;
     int           ldapPort = 389;
     LDAP         *ldap;
+    LDAPTCL	 *ldaptcl;
 
     Tcl_Obj      *resultObj = Tcl_GetObjResult (interp);
 
@@ -1040,10 +1081,14 @@ NeoX_LdapObjCmd (clientData, interp, objc, objv)
     ldap->ld_deref = LDAP_DEREF_NEVER;  /* Turn off alias dereferencing */
 #endif
 
+    ldaptcl = (LDAPTCL *) ckalloc(sizeof(LDAPTCL));
+    ldaptcl->ldap = ldap;
+    ldaptcl->flags = 0;
+
     Tcl_CreateObjCommand (interp,
 			  newCommand,
                           NeoX_LdapTargetObjCmd,
-                          (ClientData) ldap,
+                          (ClientData) ldaptcl,
                           NeoX_LdapObjDeleteCmd);
     return TCL_OK;
 }
@@ -1062,6 +1107,6 @@ Tcl_Interp   *interp;
                           NeoX_LdapObjCmd,
                           (ClientData) NULL,
                           (Tcl_CmdDeleteProc*) NULL);
-    Tcl_PkgProvide(interp, "Ldaptcl", "1.1");
+    Tcl_PkgProvide(interp, "Ldaptcl", VERSION);
     return TCL_OK;
 }
-- 
GitLab