Ok... last call for 2.0.44 ... [and sorry that I neglected the apr crew :-( ]

My understanding of our apr-util library 'thunks' is that we want all
platforms to just 'play nice' and use their built-in support.  We do have
that on WinNT flavors after 4.0, as a download for 4.0 and with some
great effort for 9x LDAP users.  I suspect that our auth_ldap community
isn't huge on the 9x thing in the first place.

So the patches attached let us plug into apr-util and then provide
mod_auth_ldap using the native libraries.  I'll be darned if I'm about
to download three packages (openldap, sasl and regex) just to get
the thing to compile.  I'm not suggesting nobody should - just that
it's unreasonable for a binary maintainer of a platform to chase down
too many nonstandard packages (when some standards are present.)

So ... what say we [apr group] to including one openldap-copyrighted
bit of code [to provide ldap_url_parse() functionality]???  And if the apr
list can bite that one (and perhaps improve it in future iterations for our
pool-schema) ... shall we roll the following into 2.0.44?

I'm cool either way, but I don't plan to start 'experimenting' with the
modules/experimental/mod_auth_ldap before we come to the usual
consensus on how to deal with this platform :-)

Patches attached.

Bill

At 05:59 PM 12/1/2002, William A. Rowe, Jr. wrote:
>Attached is the patch for Win32 apr-util support with their build in library.
>
>It is included by default with Windows 2000 and XP; NT 4.0 users may
>download it for Windows NT from the address; 
>
>http://www.microsoft.com/ntworkstation/downloads/Other/adclient.asp
>
>It appears Windows 9x (ME) users have a bit more hassle, but it is available;
>
>http://support.microsoft.com/default.aspx?scid=kb;en-us;288358
>
>Attached also is the patch for httpd util_ldap and mod_auth_ldap.  Don't
>mind the const'ness warnings just now - since win32 does it's 'own thing'
>regarding what aught to accept const.  [Big surprise.]
>
>We also do the 'wrong thing' with respect to apr_ldap_url_parse() const'ness
>at the moment.  Needs some thinking through all the way around.
>
>And of course, a bit of this patch wouldn't be needed if we 'just' hack in
>the replacement ldap_url_parse() fn.  However, I'm very concerned about
>our proliferating namespace conflicts, so I chose another name while I was
>hacking this together.
>
>Anyway, patch attached, NT/2k/XP users please experiment and provide
>feedback... thanks!
>
>Bill
>
>>From: "William A. Rowe, Jr." <[EMAIL PROTECTED]>
>>To: "Apache Portable Runtime Developers" <[email protected]>
>>Subject: [PATCH] apr-util/ldap cleanups and Native Win32
>>Date: Sun, 1 Dec 2002 14:04:58 -0800
>>
>>First off, I'm not certain how APU_HAS_LDAP defined/undefined semantics ever
>>made it into our library, but it is most wrong.  We use APR_ as our namespace 
>>except
>>internally to apr-util or apr-iconv, and we always use APR_HAS_FOO 1 or 0 as 
>>our
>>markers.  This patch deprecates the APU_HAS_LDAP[_FOO] defined/undefined
>>semantics, and replaces all that conf gook with legitimate 0|1 values for 
>>APR_HAS
>>flavors of the same.  We should plan to ditch the APU_HAS_foo when we roll out
>>with APR 1.0.
>>
>>So I attacked the ldap using native win32 libraries.  Good news; it almost 
>>worked.
>>Bad news; we were missing ldap_url_* api functions.
>>
>>Only one is used in Apache (the most critical one), ldap_url_parse.  Based on 
>>OpenLDAP
>>this patch offers replacement support for that function alone.  Until someone 
>>hollers for
>>support of ldap_url_search* fn's, I didn't see a reason to bloat.
>>
>>Of course, this introduces a really interesting question; with or without 
>>compiled-in ldap
>>support, do we want to grok LDAP urls?  I've always been partial to the idea 
>>that
>>apr-util exists to extend apr only in RFC-directed quick-fixes, and this is 
>>one (2255).
>>
>>Anywho; for your consideration.  If any Win32/ldap hackers want to look at 
>>this, and
>>if a NetWare/Unix guru wants to make sure my APU->APR changes made sense,
>>please do!
>>
>>Bill
>>
Index: Apache.dsw
===================================================================
RCS file: /home/cvs/httpd-2.0/Apache.dsw,v
retrieving revision 1.91.2.3
diff -u -r1.91.2.3 Apache.dsw
--- Apache.dsw  1 Dec 2002 23:19:33 -0000       1.91.2.3
+++ Apache.dsw  1 Dec 2002 23:39:54 -0000
@@ -200,6 +200,12 @@
     Begin Project Dependency
     Project_Dep_Name wintty
     End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name mod_auth_ldap
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name util_ldap
+    End Project Dependency
 }}}
 
 ###############################################################################
Index: modules/experimental/mod_auth_ldap.c
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/experimental/mod_auth_ldap.c,v
retrieving revision 1.8
diff -u -r1.8 mod_auth_ldap.c
--- modules/experimental/mod_auth_ldap.c        27 Sep 2002 08:49:48 -0000      
1.8
+++ modules/experimental/mod_auth_ldap.c        1 Dec 2002 23:40:01 -0000
@@ -642,7 +642,7 @@
                                     const char *url)
 {
     int result;
-    LDAPURLDesc *urld;
+    apr_ldap_url_desc_t *urld;
 
     mod_auth_ldap_config_t *sec = config;
 
@@ -650,7 +650,7 @@
                 cmd->server, "[%d] auth_ldap url parse: `%s'", 
                 getpid(), url);
 
-    result = ldap_url_parse(url, &(urld));
+    result = apr_ldap_url_parse(url, &(urld));
     if (result != LDAP_SUCCESS) {
         switch (result) {
         case LDAP_URL_ERR_NOTLDAP:
@@ -755,7 +755,7 @@
     }
 
     sec->have_ldap_url = 1;
-    ldap_free_urldesc(urld);
+    apr_ldap_free_urldesc(urld);
     return NULL;
 }
 
Index: modules/experimental/mod_auth_ldap.dsp
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/experimental/mod_auth_ldap.dsp,v
retrieving revision 1.1.2.3
diff -u -r1.1.2.3 mod_auth_ldap.dsp
--- modules/experimental/mod_auth_ldap.dsp      1 Dec 2002 23:17:08 -0000       
1.1.2.3
+++ modules/experimental/mod_auth_ldap.dsp      1 Dec 2002 23:40:01 -0000
@@ -43,7 +43,7 @@
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "../../include" /I "../../srclib/apr/include" 
/I "../../srclib/apr-util/include" /I "../../srclib/ldap/include" /D "NDEBUG" 
/D "WIN32" /D "_WINDOWS" /Fd"Release\mod_auth_ldap" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /I "../../include" /I "../../srclib/apr/include" 
/I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" 
/Fd"Release\mod_auth_ldap" /FD /c
 # ADD BASE MTL /nologo /D "NDEBUG" /win32
 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
 # ADD BASE RSC /l 0x409 /d "NDEBUG"
@@ -53,7 +53,7 @@
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /map 
/machine:I386 /out:"Release/mod_auth_ldap.so" 
/base:@..\..\os\win32\BaseAddr.ref,mod_auth_ldap
-# ADD LINK32 kernel32.lib nsldap32v50.lib /nologo /subsystem:windows /dll /map 
/machine:I386 /out:"Release/mod_auth_ldap.so" /libpath:"..\..\srclib\ldap\lib" 
/base:@..\..\os\win32\BaseAddr.ref,mod_auth_ldap
+# ADD LINK32 kernel32.lib wldap32.lib /nologo /subsystem:windows /dll /map 
/machine:I386 /out:"Release/mod_auth_ldap.so" 
/base:@..\..\os\win32\BaseAddr.ref,mod_auth_ldap
 
 !ELSEIF  "$(CFG)" == "mod_auth_ldap - Win32 Debug"
 
@@ -69,7 +69,7 @@
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D 
"_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "../../include" /I 
"../../srclib/apr/include" /I "../../srclib/apr-util/include" /I 
"../../srclib/ldap/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" 
/Fd"Debug\mod_auth_ldap" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "../../include" /I 
"../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D 
"WIN32" /D "_WINDOWS" /Fd"Debug\mod_auth_ldap" /FD /c
 # ADD BASE MTL /nologo /D "_DEBUG" /win32
 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
 # ADD BASE RSC /l 0x409 /d "_DEBUG"
@@ -79,7 +79,7 @@
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no 
/map /debug /machine:I386 /out:"Debug/mod_auth_ldap.so" 
/base:@..\..\os\win32\BaseAddr.ref,mod_auth_ldap
-# ADD LINK32 kernel32.lib nsldap32v50.lib /nologo /subsystem:windows /dll 
/incremental:no /map /debug /machine:I386 /out:"Debug/mod_auth_ldap.so" 
/libpath:"..\..\srclib\ldap\lib" 
/base:@..\..\os\win32\BaseAddr.ref,mod_auth_ldap
+# ADD LINK32 kernel32.lib wldap32.lib /nologo /subsystem:windows /dll 
/incremental:no /map /debug /machine:I386 /out:"Debug/mod_auth_ldap.so" 
/base:@..\..\os\win32\BaseAddr.ref,mod_auth_ldap
 
 !ENDIF 
 
Index: util_ldap.dsp
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/experimental/util_ldap.dsp,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.4
diff -u -r1.1.2.5 -r1.1.2.4
--- util_ldap.dsp       3 Dec 2002 00:03:13 -0000       1.1.2.5
+++ util_ldap.dsp       1 Dec 2002 23:36:19 -0000       1.1.2.4
@@ -43,7 +43,7 @@
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "../../include" /I "../../srclib/apr/include" 
/I "../../srclib/apr-util/include" /I "../../srclib/ldap/include" /D "NDEBUG" 
/D "WIN32" /D "_WINDOWS" /D "LDAP_DECLARE_EXPORT" /Fd"Release\util_ldap" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /I "../../include" /I "../../srclib/apr/include" 
/I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D 
"LDAP_DECLARE_EXPORT" /Fd"Release\util_ldap" /FD /c
 # ADD BASE MTL /nologo /D "NDEBUG" /win32
 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
 # ADD BASE RSC /l 0x409 /d "NDEBUG"
@@ -53,7 +53,7 @@
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /map 
/machine:I386 /out:"Release/util_ldap.so" 
/base:@..\..\os\win32\BaseAddr.ref,util_ldap
-# ADD LINK32 kernel32.lib nsldap32v50.lib /nologo /subsystem:windows /dll /map 
/machine:I386 /out:"Release/util_ldap.so" 
/base:@..\..\os\win32\BaseAddr.ref,util_ldap
+# ADD LINK32 kernel32.lib wldap32.lib /nologo /subsystem:windows /dll /map 
/machine:I386 /out:"Release/util_ldap.so" 
/base:@..\..\os\win32\BaseAddr.ref,util_ldap
 
 !ELSEIF  "$(CFG)" == "util_ldap - Win32 Debug"
 
@@ -69,7 +69,7 @@
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D 
"_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "../../include" /I 
"../../srclib/apr/include" /I "../../srclib/apr-util/include" /I 
"../../srclib/ldap/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D 
"LDAP_DECLARE_EXPORT" /Fd"Debug\util_ldap" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "../../include" /I 
"../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D 
"WIN32" /D "_WINDOWS" /D "LDAP_DECLARE_EXPORT" /Fd"Debug\util_ldap" /FD /c
 # ADD BASE MTL /nologo /D "_DEBUG" /win32
 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
 # ADD BASE RSC /l 0x409 /d "_DEBUG"
@@ -79,7 +79,7 @@
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no 
/map /debug /machine:I386 /out:"Debug/util_ldap.so" 
/base:@..\..\os\win32\BaseAddr.ref,util_ldap
-# ADD LINK32 kernel32.lib nsldap32v50.lib /nologo /subsystem:windows /dll 
/incremental:no /map /debug /machine:I386 /out:"Debug/util_ldap.so" 
/base:@..\..\os\win32\BaseAddr.ref,util_ldap
+# ADD LINK32 kernel32.lib wldap32.lib /nologo /subsystem:windows /dll 
/incremental:no /map /debug /machine:I386 /out:"Debug/util_ldap.so" 
/base:@..\..\os\win32\BaseAddr.ref,util_ldap
 
 !ENDIF 
 
Index: aprutil.dsp
===================================================================
RCS file: /home/cvs/apr-util/aprutil.dsp,v
retrieving revision 1.46
diff -u -r1.46 aprutil.dsp
--- aprutil.dsp 21 Jul 2002 00:22:19 -0000      1.46
+++ aprutil.dsp 1 Dec 2002 21:52:35 -0000
@@ -206,7 +206,10 @@
 # Begin Source File
 
 SOURCE=.\ldap\apr_ldap_compat.c
-# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=.\ldap\apr_ldap_url.c
 # End Source File
 # End Group
 # Begin Group "misc"
@@ -323,7 +326,6 @@
 
 !ENDIF 
 
-# PROP Exclude_From_Build 1
 # End Source File
 # Begin Source File
 
@@ -476,6 +478,10 @@
 # Begin Source File
 
 SOURCE=.\include\apr_hooks.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_ldap_url.h
 # End Source File
 # Begin Source File
 
Index: libaprutil.dsp
===================================================================
RCS file: /home/cvs/apr-util/libaprutil.dsp,v
retrieving revision 1.41
diff -u -r1.41 libaprutil.dsp
--- libaprutil.dsp      23 Jul 2002 01:45:04 -0000      1.41
+++ libaprutil.dsp      1 Dec 2002 21:52:36 -0000
@@ -212,7 +212,10 @@
 # Begin Source File
 
 SOURCE=.\ldap\apr_ldap_compat.c
-# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=.\ldap\apr_ldap_url.c
 # End Source File
 # End Group
 # Begin Group "misc"
@@ -329,7 +332,6 @@
 
 !ENDIF 
 
-# PROP Exclude_From_Build 1
 # End Source File
 # Begin Source File
 
@@ -482,6 +484,10 @@
 # Begin Source File
 
 SOURCE=.\include\apr_hooks.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_ldap_url.h
 # End Source File
 # Begin Source File
 
Index: build/apu-conf.m4
===================================================================
RCS file: /home/cvs/apr-util/build/apu-conf.m4,v
retrieving revision 1.45
diff -u -r1.45 apu-conf.m4
--- build/apu-conf.m4   21 Aug 2002 21:42:41 -0000      1.45
+++ build/apu-conf.m4   1 Dec 2002 21:52:38 -0000
@@ -647,7 +647,7 @@
 dnl Find a particular LDAP library
 dnl
 AC_DEFUN(APU_FIND_LDAPLIB,[
-  if test ${apu_has_ldap} != "define"; then
+  if test ${apu_has_ldap} != "1"; then
     ldaplib=$1
     extralib=$2
     unset ac_cv_lib_${ldaplib}_ldap_init
@@ -655,9 +655,9 @@
       [
         APR_ADDTO(APRUTIL_EXPORT_LIBS,[-l${ldaplib} ${extralib}])
         APR_ADDTO(APRUTIL_LIBS,[-l${ldaplib} ${extralib}])
-        AC_CHECK_LIB(${ldaplib}, ldapssl_install_routines, 
apu_has_ldap_netscape_ssl="define", , ${extralib})
-        AC_CHECK_LIB(${ldaplib}, ldap_start_tls_s, 
apu_has_ldap_starttls="define", , ${extralib})
-        apu_has_ldap="define";
+        AC_CHECK_LIB(${ldaplib}, ldapssl_install_routines, 
apu_has_ldap_netscape_ssl="1", , ${extralib})
+        AC_CHECK_LIB(${ldaplib}, ldap_start_tls_s, apu_has_ldap_starttls="1", 
, ${extralib})
+        apu_has_ldap="1";
       ], , ${extralib})
   fi
 ])
@@ -670,9 +670,9 @@
 
 echo $ac_n "${nl}checking for ldap support..."
 
-apu_has_ldap="undef";
-apu_has_ldap_netscape_ssl="undef"
-apu_has_ldap_starttls="undef"
+apu_has_ldap="0";
+apu_has_ldap_netscape_ssl="0"
+apu_has_ldap_starttls="0"
 
 AC_ARG_WITH(ldap-include,[  --with-ldap-include=path  path to ldap include 
files with trailing slash])
 AC_ARG_WITH(ldap-lib,[  --with-ldap-lib=path    path to ldap lib file])
@@ -704,7 +704,7 @@
       APU_FIND_LDAPLIB($LDAPLIB)
     fi
 
-    test ${apu_has_ldap} != "define" && AC_MSG_ERROR(could not find an LDAP 
library)
+    test ${apu_has_ldap} != "1" && AC_MSG_ERROR(could not find an LDAP library)
     AC_CHECK_LIB(lber, ber_init)
 
     AC_CHECK_HEADERS(ldap.h, ldap_h=["#include <ldap.h>"])
Index: include/apr_ldap.h.in
===================================================================
RCS file: /home/cvs/apr-util/include/apr_ldap.h.in,v
retrieving revision 1.4
diff -u -r1.4 apr_ldap.h.in
--- include/apr_ldap.h.in       13 Mar 2002 20:40:48 -0000      1.4
+++ include/apr_ldap.h.in       1 Dec 2002 21:52:38 -0000
@@ -74,14 +74,40 @@
  */
 
 /* this will be defined if LDAP support was compiled into apr-util */
[EMAIL PROTECTED]@      APU_HAS_LDAP
+#define APR_HAS_LDAP             @apu_has_ldap@
 
 /* this whole thing disappears if LDAP is not enabled */
-#ifdef APU_HAS_LDAP
+#if !APR_HAS_LDAP
+
+#define APR_HAS_LDAP_URL_PARSE    0
+#define APU_HAS_LDAP_NETSCAPE_SSL 0
+#define APU_HAS_LDAP_STARTTLS     0
+
+#else
+
+/* presume all unices do, win32, for example, does not */
+#define APR_HAS_LDAP_URL_PARSE    1
 
 /* LDAP secure capabilities */
[EMAIL PROTECTED]@      APU_HAS_LDAP_NETSCAPE_SSL
[EMAIL PROTECTED]@      APU_HAS_LDAP_STARTTLS
+#define APR_HAS_LDAP_NETSCAPE_SSL @apu_has_ldap_netscape_ssl@
+#define APR_HAS_LDAP_STARTTLS     @apu_has_ldap_starttls@
+
+/* These are garbage, our public macros are always APR_HAS_ prefixed,
+ * and use 0/1 values, not defined/undef semantics.  
+ *
+ * Will be deprecated in APR 1.0
+ */
+#if APR_HAS_LDAP
+#define APU_HAS_LDAP
+#endif
+
+#if APR_HAS_LDAP_NETSCAPE_SSL
+#define APU_HAS_LDAP_NETSCAPE_SSL 
+#endif
+
+#if APR_HAS_LDAP_STARTTLS
+#define APU_HAS_LDAP_STARTTLS
+#endif
 
 /* LDAP header files */
 @ldap_h@
@@ -107,6 +133,8 @@
 #else
 #define const_cast(x) (x)
 #endif /* LDAP_VERSION_MAX */
+
+#include "apr_ldap_url.h"
 
 /* Define some errors that are mysteriously gone from OpenLDAP 2.x */
 #ifndef LDAP_URL_ERR_NOTLDAP
Index: include/apr_ldap.hnw
===================================================================
RCS file: /home/cvs/apr-util/include/apr_ldap.hnw,v
retrieving revision 1.2
diff -u -r1.2 apr_ldap.hnw
--- include/apr_ldap.hnw        13 Mar 2002 20:40:48 -0000      1.2
+++ include/apr_ldap.hnw        1 Dec 2002 21:52:38 -0000
@@ -74,14 +74,41 @@
  */
 
 /* this will be defined if LDAP support was compiled into apr-util */
-#define APU_HAS_LDAP
+#define APR_HAS_LDAP             @apu_has_ldap@
 
 /* this whole thing disappears if LDAP is not enabled */
-#ifdef APU_HAS_LDAP
+#if !APR_HAS_LDAP
+
+#define APR_HAS_LDAP_URL_PARSE    0
+#define APU_HAS_LDAP_NETSCAPE_SSL 0
+#define APU_HAS_LDAP_STARTTLS     0
+
+#else
+
+/* presume all unices do, win32, for example, does not */
+#define APR_HAS_LDAP_URL_PARSE    1
 
 /* LDAP secure capabilities */
-//#define APU_HAS_LDAP_NETSCAPE_SSL
-//#define APU_HAS_LDAP_STARTTLS
+#define APR_HAS_LDAP_NETSCAPE_SSL 0
+#define APR_HAS_LDAP_STARTTLS     0
+
+/* These are garbage, our public macros are always APR_HAS_ prefixed,
+ * and use 0/1 values, not defined/undef semantics.  
+ *
+ * Will be deprecated in APR 1.0
+ */
+#if APR_HAS_LDAP
+#define APU_HAS_LDAP
+#endif
+
+#if APR_HAS_LDAP_NETSCAPE_SSL
+#define APU_HAS_LDAP_NETSCAPE_SSL 
+#endif
+
+#if APR_HAS_LDAP_STARTTLS
+#define APU_HAS_LDAP_STARTTLS
+#endif
+
 
 /* LDAP header files */
 #include <ldap.h>
@@ -107,6 +134,8 @@
 #else
 #define const_cast(x) (x)
 #endif /* LDAP_VERSION_MAX */
+
+#include "apr_ldap_url.h"
 
 /* Define some errors that are mysteriously gone from OpenLDAP 2.x */
 #ifndef LDAP_URL_ERR_NOTLDAP
Index: include/apr_ldap.hw
===================================================================
RCS file: /home/cvs/apr-util/include/apr_ldap.hw,v
retrieving revision 1.2
diff -u -r1.2 apr_ldap.hw
--- include/apr_ldap.hw 1 Dec 2002 17:08:51 -0000       1.2
+++ include/apr_ldap.hw 1 Dec 2002 21:52:38 -0000
@@ -52,6 +52,9 @@
  * <http://www.apache.org/>.
  */
 
+#include "apr.h"
+#include "apu.h"
+
 /*
  * apr_ldap.h is generated from apr_ldap.h.in by configure -- do not edit 
apr_ldap.h
  */
@@ -74,25 +77,57 @@
  */
 
 /* this will be defined if LDAP support was compiled into apr-util */
-#define APU_HAS_LDAP
+#define APR_HAS_LDAP             1
 
 /* this whole thing disappears if LDAP is not enabled */
-#ifdef APU_HAS_LDAP
+#if !APR_HAS_LDAP
+
+#define APR_HAS_LDAP_URL_PARSE    0
+#define APU_HAS_LDAP_NETSCAPE_SSL 0
+#define APU_HAS_LDAP_STARTTLS     0
+
+#else
+
+/* presume all unices do, win32, for example, does not */
+#define APR_HAS_LDAP_URL_PARSE    0
 
 /* LDAP secure capabilities */
-//#define APU_HAS_LDAP_NETSCAPE_SSL
-//#define APU_HAS_LDAP_STARTTLS
+#define APR_HAS_LDAP_NETSCAPE_SSL 0
+#define APR_HAS_LDAP_STARTTLS     0
 
-/* LDAP header files */
-#include <ldap.h>
-#include <lber.h>
-#include <ldap_ssl.h>
+/* These are garbage, our public macros are always APR_HAS_ prefixed,
+ * and use 0/1 values, not defined/undef semantics.  
+ *
+ * Will be deprecated in APR 1.0
+ */
+#if APR_HAS_LDAP
+#define APU_HAS_LDAP
+#endif
 
+#if APR_HAS_LDAP_NETSCAPE_SSL
+#define APU_HAS_LDAP_NETSCAPE_SSL 
+#endif
+
+#if APR_HAS_LDAP_STARTTLS
+#define APU_HAS_LDAP_STARTTLS
+#endif
+
+/* Included in Windows 2000 and later, earlier 9x/NT 4.0 clients
+ * will need to obtain the Active Directory Client Extensions.
+ */
+#include <Winldap.h>
 
 /*
  * LDAP Compatibility
  */
 
+/* Empty declaration, Win32 const'ness in SDK library headers is
+ * generally bogus
+ */
+#define LDAP_CONST
+
+/* These don't apply on Win32, leave them in place for reference 
+ */
 #if LDAP_VERSION_MAX <= 2
 int ldap_search_ext_s(LDAP *ldap, char *base, int scope, char *filter,
                      char **attrs, int attrsonly, void *servertrls, void 
*clientctrls,
@@ -107,6 +142,8 @@
 #else
 #define const_cast(x) (x)
 #endif /* LDAP_VERSION_MAX */
+
+#include "apr_ldap_url.h"
 
 /* Define some errors that are mysteriously gone from OpenLDAP 2.x */
 #ifndef LDAP_URL_ERR_NOTLDAP
Index: include/apr_ldap_url.h
===================================================================
RCS file: include/apr_ldap_url.h
diff -N include/apr_ldap_url.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ include/apr_ldap_url.h      1 Dec 2002 21:52:38 -0000
@@ -0,0 +1,119 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000-2002 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact [EMAIL PROTECTED]
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
+ * ITS 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+#ifndef APR_LDAP_URL_H
+#define APR_LDAP_URL_H
+
+#include "apr_ldap.h"
+
+#if APR_HAS_LDAP_URL_PARSE
+
+#define apr_ldap_url_desc_t             LDAPURLDesc
+#define apr_ldap_is_ldap_url(url)       ldap_is_ldap_url(url)
+#define apr_ldap_is_ldaps_url(url)      ldap_is_ldaps_url(url)
+#define apr_ldap_is_ldapi_url(url)      ldap_is_ldapi_url(url)
+#define apr_ldap_url_parse(url, ludpp)  ldap_url_parse(url, ludpp)
+#define apr_ldap_free_urldesc(ludp)     ldap_free_urldesc(ludp)
+
+#else /* ! APR_HAS_LDAP_URL_PARSE */
+
+/*
+ * types for ldap URL handling
+ */
+typedef struct apr_ldap_url_desc_t {
+    struct  apr_ldap_url_desc_t  *lud_next;
+    char    *lud_scheme;
+    char    *lud_host;
+    int     lud_port;
+    char    *lud_dn;
+    char    **lud_attrs;
+    int     lud_scope;
+    char    *lud_filter;
+    char    **lud_exts;
+    int     lud_crit_exts;
+} apr_ldap_url_desc_t;
+
+#ifndef LDAP_URL_SUCCESS
+#define LDAP_URL_SUCCESS          0x00    /* Success */
+#define LDAP_URL_ERR_MEM          0x01    /* can't allocate memory space */
+#define LDAP_URL_ERR_PARAM        0x02    /* parameter is bad */
+#define LDAP_URL_ERR_BADSCHEME    0x03    /* URL doesn't begin with 
"ldap[si]://" */
+#define LDAP_URL_ERR_BADENCLOSURE 0x04    /* URL is missing trailing ">" */
+#define LDAP_URL_ERR_BADURL       0x05    /* URL is bad */
+#define LDAP_URL_ERR_BADHOST      0x06    /* host port is bad */
+#define LDAP_URL_ERR_BADATTRS     0x07    /* bad (or missing) attributes */
+#define LDAP_URL_ERR_BADSCOPE     0x08    /* scope string is invalid (or 
missing) */
+#define LDAP_URL_ERR_BADFILTER    0x09    /* bad or missing filter */
+#define LDAP_URL_ERR_BADEXTS      0x0a    /* bad or missing extensions */
+#endif
+
+/*
+ * in url.c
+ *
+ * need _ext varients
+ */
+APU_DECLARE(int) apr_ldap_is_ldap_url(LDAP_CONST char *url);
+
+APU_DECLARE(int) apr_ldap_is_ldaps_url(LDAP_CONST char *url);
+
+APU_DECLARE(int) apr_ldap_is_ldapi_url(LDAP_CONST char *url);
+
+APU_DECLARE(int) apr_ldap_url_parse(LDAP_CONST char *url, 
+                                    apr_ldap_url_desc_t **ludpp);
+
+APU_DECLARE(void) apr_ldap_free_urldesc(apr_ldap_url_desc_t *ludp);
+
+#endif /* ! APR_HAS_LDAP_URL_PARSE */
+
+#endif /* APR_LDAP_URL_H */
Index: ldap/Makefile.in
===================================================================
RCS file: /home/cvs/apr-util/ldap/Makefile.in,v
retrieving revision 1.6
diff -u -r1.6 Makefile.in
--- ldap/Makefile.in    8 May 2002 22:00:58 -0000       1.6
+++ ldap/Makefile.in    1 Dec 2002 21:52:39 -0000
@@ -2,6 +2,7 @@
 
 INCLUDES = @APRUTIL_PRIV_INCLUDES@ @APR_INCLUDES@ @APRUTIL_INCLUDES@
 
+# we presume Unicies aren't in need of apr_parse_uri
 TARGETS = apr_ldap_compat.lo
 
 # bring in rules.mk for standard functionality
Index: ldap/apr_ldap_url.c
===================================================================
RCS file: ldap/apr_ldap_url.c
diff -N ldap/apr_ldap_url.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ ldap/apr_ldap_url.c 1 Dec 2002 21:52:40 -0000
@@ -0,0 +1,753 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000-2002 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact [EMAIL PROTECTED]
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
+ * ITS 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+/* Portions Copyright 1998-2002 The OpenLDAP Foundation
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.  A copy of this license is available at
+ * http://www.OpenLDAP.org/license.html or in file LICENSE in the
+ * top-level directory of the distribution.
+ * 
+ * OpenLDAP is a registered trademark of the OpenLDAP Foundation.
+ * 
+ * Individual files and/or contributed packages may be copyright by
+ * other parties and subject to additional restrictions.
+ * 
+ * This work is derived from the University of Michigan LDAP v3.3
+ * distribution.  Information concerning this software is available
+ * at: http://www.umich.edu/~dirsvcs/ldap/
+ * 
+ * This work also contains materials derived from public sources.
+ * 
+ * Additional information about OpenLDAP can be obtained at:
+ *     http://www.openldap.org/
+ */
+
+/* 
+ * Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+/*  apr_ldap_url.c -- LDAP URL (RFC 2255) related routines
+ *
+ *  Win32 and perhaps other non-OpenLDAP based ldap libraries may be
+ *  missing ldap_url_* APIs.  We focus here on the one significant
+ *  aspect, which is parsing.  We have [for the time being] omitted
+ *  the ldap_url_search APIs.
+ *
+ *  LDAP URLs look like this:
+ *    ldap[is]://host:port[/[dn[?[attributes][?[scope][?[filter][?exts]]]]]]
+ *
+ *  where:
+ *   attributes is a comma separated list
+ *   scope is one of these three strings:  base one sub (default=base)
+ *   filter is an string-represented filter as in RFC 2254
+ *
+ *  e.g.,  ldap://host:port/dc=com?o,cn?base?o=openldap?extension
+ *
+ *  Tolerates URLs that look like: <ldapurl> and <URL:ldapurl>
+ */
+
+#include "apr_ldap.h"
+#include "apr_ldap_url.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+
+#ifndef LDAPS_PORT
+#define LDAPS_PORT              636  /* ldaps:/// default LDAP over TLS port */
+#endif
+
+#define LDAP_URL_PREFIX         "ldap://";
+#define LDAP_URL_PREFIX_LEN     (sizeof(LDAP_URL_PREFIX)-1)
+#define LDAPS_URL_PREFIX        "ldaps://"
+#define LDAPS_URL_PREFIX_LEN    (sizeof(LDAPS_URL_PREFIX)-1)
+#define LDAPI_URL_PREFIX        "ldapi://"
+#define LDAPI_URL_PREFIX_LEN    (sizeof(LDAPI_URL_PREFIX)-1)
+#define LDAP_URL_URLCOLON       "URL:"
+#define LDAP_URL_URLCOLON_LEN   (sizeof(LDAP_URL_URLCOLON)-1)
+
+#define LDAP_STRDUP(x) strdup(x)
+#define LDAP_CALLOC(n, s) calloc(n, s)
+#define LDAP_MALLOC(n) malloc(n)
+#define LDAP_REALLOC(x, n) realloc(x, n)
+#define LDAP_FREE(x) free(x)
+#define LDAP_VFREE(a) ldap_charray_free(a)
+
+#define ldap_utf8_strchr(x, s) strchr(x, *s)
+#define ldap_utf8_strtok(x, s, l) apr_strtok(x, s, l)
+
+/* local functions */
+static const char* skip_url_prefix(const char *url, int *enclosedp,
+                                   const char **scheme);
+
+static void ldap_pvt_hex_unescape(char *s);
+
+static int ldap_pvt_unhex(int c);
+
+static void ldap_charray_free(char **a);
+
+static char **ldap_str2charray(const char *str, const char *brkstr);
+
+APU_DECLARE(int) apr_ldap_is_ldap_url(LDAP_CONST char *url)
+{
+    int enclosed;
+    const char * scheme;
+
+    if( url == NULL ) {
+        return 0;
+    }
+
+    if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) {
+        return 0;
+    }
+
+    return 1;
+}
+
+APU_DECLARE(int) apr_ldap_is_ldaps_url(LDAP_CONST char *url)
+{
+    int enclosed;
+    const char * scheme;
+
+    if( url == NULL ) {
+        return 0;
+    }
+
+    if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) {
+        return 0;
+    }
+
+    return strcmp(scheme, "ldaps") == 0;
+}
+
+APU_DECLARE(int) apr_ldap_is_ldapi_url(LDAP_CONST char *url)
+{
+    int enclosed;
+    const char * scheme;
+
+    if( url == NULL ) {
+        return 0;
+    }
+
+    if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) {
+        return 0;
+    }
+
+    return strcmp(scheme, "ldapi") == 0;
+}
+
+static const char *skip_url_prefix(const char *url, int *enclosedp,
+                                   const char **scheme)
+{
+    /*
+     * return non-zero if this looks like a LDAP URL; zero if not
+     * if non-zero returned, *urlp will be moved past "ldap://"; part of URL
+     */
+    const char *p;
+
+    if ( url == NULL ) {
+        return( NULL );
+    }
+
+    p = url;
+
+    /* skip leading '<' (if any) */
+    if ( *p == '<' ) {
+        *enclosedp = 1;
+        ++p;
+    } else {
+        *enclosedp = 0;
+    }
+
+    /* skip leading "URL:" (if any) */
+    if ( strncasecmp( p, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) {
+        p += LDAP_URL_URLCOLON_LEN;
+    }
+
+    /* check for "ldap://"; prefix */
+    if ( strncasecmp( p, LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) == 0 ) {
+        /* skip over "ldap://"; prefix and return success */
+        p += LDAP_URL_PREFIX_LEN;
+        *scheme = "ldap";
+        return( p );
+    }
+
+    /* check for "ldaps://" prefix */
+    if ( strncasecmp( p, LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) {
+        /* skip over "ldaps://" prefix and return success */
+        p += LDAPS_URL_PREFIX_LEN;
+        *scheme = "ldaps";
+        return( p );
+    }
+
+    /* check for "ldapi://" prefix */
+    if ( strncasecmp( p, LDAPI_URL_PREFIX, LDAPI_URL_PREFIX_LEN ) == 0 ) {
+        /* skip over "ldapi://" prefix and return success */
+        p += LDAPI_URL_PREFIX_LEN;
+        *scheme = "ldapi";
+        return( p );
+    }
+
+    return( NULL );
+}
+
+
+static int str2scope(const char *p)
+{
+    if ( strcasecmp( p, "one" ) == 0 ) {
+        return LDAP_SCOPE_ONELEVEL;
+
+    } else if ( strcasecmp( p, "onetree" ) == 0 ) {
+        return LDAP_SCOPE_ONELEVEL;
+
+    } else if ( strcasecmp( p, "base" ) == 0 ) {
+        return LDAP_SCOPE_BASE;
+
+    } else if ( strcasecmp( p, "sub" ) == 0 ) {
+        return LDAP_SCOPE_SUBTREE;
+
+    } else if ( strcasecmp( p, "subtree" ) == 0 ) {
+        return LDAP_SCOPE_SUBTREE;
+    }
+
+    return( -1 );
+}
+
+
+static int ldap_url_parse_ext(LDAP_CONST char *url_in, 
+                              apr_ldap_url_desc_t **ludpp)
+{
+/*
+ *  Pick apart the pieces of an LDAP URL.
+ */
+    apr_ldap_url_desc_t *ludp;
+    char        *p, *q, *r;
+    int         i, enclosed;
+    const char  *scheme = NULL;
+    const char  *url_tmp;
+    char        *url;
+
+    if( url_in == NULL || ludpp == NULL ) {
+        return LDAP_URL_ERR_PARAM;
+    }
+
+    *ludpp = NULL;  /* pessimistic */
+
+    url_tmp = skip_url_prefix( url_in, &enclosed, &scheme );
+
+    if ( url_tmp == NULL ) {
+        return LDAP_URL_ERR_BADSCHEME;
+    }
+
+    /* make working copy of the remainder of the URL */
+    url = LDAP_STRDUP( url_tmp );
+    if ( url == NULL ) {
+        return LDAP_URL_ERR_MEM;
+    }
+
+    if ( enclosed ) {
+        p = &url[strlen(url)-1];
+
+        if( *p != '>' ) {
+            LDAP_FREE( url );
+            return LDAP_URL_ERR_BADENCLOSURE;
+        }
+
+        *p = '\0';
+    }
+
+    /* allocate return struct */
+    ludp = (apr_ldap_url_desc_t *)LDAP_CALLOC( 1, sizeof( apr_ldap_url_desc_t 
));
+
+    if ( ludp == NULL ) {
+        LDAP_FREE( url );
+        return LDAP_URL_ERR_MEM;
+    }
+
+    ludp->lud_next = NULL;
+    ludp->lud_host = NULL;
+    ludp->lud_port = LDAP_PORT;
+    ludp->lud_dn = NULL;
+    ludp->lud_attrs = NULL;
+    ludp->lud_filter = NULL;
+    ludp->lud_scope = -1;
+    ludp->lud_filter = NULL;
+    ludp->lud_exts = NULL;
+
+    ludp->lud_scheme = LDAP_STRDUP( scheme );
+
+    if ( ludp->lud_scheme == NULL ) {
+        LDAP_FREE( url );
+        apr_ldap_free_urldesc( ludp );
+        return LDAP_URL_ERR_MEM;
+    }
+
+    if( strcasecmp( ludp->lud_scheme, "ldaps" ) == 0 ) {
+        ludp->lud_port = LDAPS_PORT;
+    }
+
+    /* scan forward for '/' that marks end of hostport and begin. of dn */
+    p = strchr( url, '/' );
+
+    if( p != NULL ) {
+        /* terminate hostport; point to start of dn */
+        *p++ = '\0';
+    }
+
+    /* IPv6 syntax with [ip address]:port */
+    if ( *url == '[' ) {
+        r = strchr( url, ']' );
+        if ( r == NULL ) {
+            LDAP_FREE( url );
+            apr_ldap_free_urldesc( ludp );
+            return LDAP_URL_ERR_BADURL;
+        }
+        *r++ = '\0';
+        q = strchr( r, ':' );
+    } else {
+        q = strchr( url, ':' );
+    }
+
+    if ( q != NULL ) {
+        *q++ = '\0';
+        ldap_pvt_hex_unescape( q );
+
+        if( *q == '\0' ) {
+            LDAP_FREE( url );
+            apr_ldap_free_urldesc( ludp );
+            return LDAP_URL_ERR_BADURL;
+        }
+
+        ludp->lud_port = atoi( q );
+    }
+
+    ldap_pvt_hex_unescape( url );
+
+    /* If [ip address]:port syntax, url is [ip and we skip the [ */
+    ludp->lud_host = LDAP_STRDUP( url + ( *url == '[' ) );
+
+    if( ludp->lud_host == NULL ) {
+        LDAP_FREE( url );
+        apr_ldap_free_urldesc( ludp );
+        return LDAP_URL_ERR_MEM;
+    }
+
+    /*
+     * Kludge.  ldap://111.222.333.444:389??cn=abc,o=company
+     *
+     * On early Novell releases, search references/referrals were returned
+     * in this format, i.e., the dn was kind of in the scope position,
+     * but the required slash is missing. The whole thing is illegal syntax,
+     * but we need to account for it. Fortunately it can't be confused with
+     * anything real.
+     */
+    if( (p == NULL) && (q != NULL) && ((q = strchr( q, '?')) != NULL)) {
+        q++;
+        /* ? immediately followed by question */
+        if( *q == '?') {
+            q++;
+            if( *q != '\0' ) {
+                /* parse dn part */
+                ldap_pvt_hex_unescape( q );
+                ludp->lud_dn = LDAP_STRDUP( q );
+            } else {
+                ludp->lud_dn = LDAP_STRDUP( "" );
+            }
+
+            if( ludp->lud_dn == NULL ) {
+                LDAP_FREE( url );
+                apr_ldap_free_urldesc( ludp );
+                return LDAP_URL_ERR_MEM;
+            }
+        }
+    }
+
+    if( p == NULL ) {
+        LDAP_FREE( url );
+        *ludpp = ludp;
+        return LDAP_URL_SUCCESS;
+    }
+
+    /* scan forward for '?' that may marks end of dn */
+    q = strchr( p, '?' );
+
+    if( q != NULL ) {
+        /* terminate dn part */
+        *q++ = '\0';
+    }
+
+    if( *p != '\0' ) {
+        /* parse dn part */
+        ldap_pvt_hex_unescape( p );
+        ludp->lud_dn = LDAP_STRDUP( p );
+    } else {
+        ludp->lud_dn = LDAP_STRDUP( "" );
+    }
+
+    if( ludp->lud_dn == NULL ) {
+        LDAP_FREE( url );
+        apr_ldap_free_urldesc( ludp );
+        return LDAP_URL_ERR_MEM;
+    }
+
+    if( q == NULL ) {
+        /* no more */
+        LDAP_FREE( url );
+        *ludpp = ludp;
+        return LDAP_URL_SUCCESS;
+    }
+
+    /* scan forward for '?' that may marks end of attributes */
+    p = q;
+    q = strchr( p, '?' );
+
+    if( q != NULL ) {
+        /* terminate attributes part */
+        *q++ = '\0';
+    }
+
+    if( *p != '\0' ) {
+        /* parse attributes */
+        ldap_pvt_hex_unescape( p );
+        ludp->lud_attrs = ldap_str2charray( p, "," );
+
+        if( ludp->lud_attrs == NULL ) {
+            LDAP_FREE( url );
+            apr_ldap_free_urldesc( ludp );
+            return LDAP_URL_ERR_BADATTRS;
+        }
+    }
+
+    if ( q == NULL ) {
+        /* no more */
+        LDAP_FREE( url );
+        *ludpp = ludp;
+        return LDAP_URL_SUCCESS;
+    }
+
+    /* scan forward for '?' that may marks end of scope */
+    p = q;
+    q = strchr( p, '?' );
+
+    if( q != NULL ) {
+        /* terminate the scope part */
+        *q++ = '\0';
+    }
+
+    if( *p != '\0' ) {
+        /* parse the scope */
+        ldap_pvt_hex_unescape( p );
+        ludp->lud_scope = str2scope( p );
+
+        if( ludp->lud_scope == -1 ) {
+            LDAP_FREE( url );
+            apr_ldap_free_urldesc( ludp );
+            return LDAP_URL_ERR_BADSCOPE;
+        }
+    }
+
+    if ( q == NULL ) {
+        /* no more */
+        LDAP_FREE( url );
+        *ludpp = ludp;
+        return LDAP_URL_SUCCESS;
+    }
+
+    /* scan forward for '?' that may marks end of filter */
+    p = q;
+    q = strchr( p, '?' );
+
+    if( q != NULL ) {
+        /* terminate the filter part */
+        *q++ = '\0';
+    }
+
+    if( *p != '\0' ) {
+        /* parse the filter */
+        ldap_pvt_hex_unescape( p );
+
+        if( ! *p ) {
+            /* missing filter */
+            LDAP_FREE( url );
+            apr_ldap_free_urldesc( ludp );
+            return LDAP_URL_ERR_BADFILTER;
+        }
+
+        LDAP_FREE( ludp->lud_filter );
+        ludp->lud_filter = LDAP_STRDUP( p );
+
+        if( ludp->lud_filter == NULL ) {
+            LDAP_FREE( url );
+            apr_ldap_free_urldesc( ludp );
+            return LDAP_URL_ERR_MEM;
+        }
+    }
+
+    if ( q == NULL ) {
+        /* no more */
+        LDAP_FREE( url );
+        *ludpp = ludp;
+        return LDAP_URL_SUCCESS;
+    }
+
+    /* scan forward for '?' that may marks end of extensions */
+    p = q;
+    q = strchr( p, '?' );
+
+    if( q != NULL ) {
+        /* extra '?' */
+        LDAP_FREE( url );
+        apr_ldap_free_urldesc( ludp );
+        return LDAP_URL_ERR_BADURL;
+    }
+
+    /* parse the extensions */
+    ludp->lud_exts = ldap_str2charray( p, "," );
+
+    if( ludp->lud_exts == NULL ) {
+        LDAP_FREE( url );
+        apr_ldap_free_urldesc( ludp );
+        return LDAP_URL_ERR_BADEXTS;
+    }
+
+    for( i=0; ludp->lud_exts[i] != NULL; i++ ) {
+        ldap_pvt_hex_unescape( ludp->lud_exts[i] );
+
+        if( *ludp->lud_exts[i] == '!' ) {
+            /* count the number of critical extensions */
+            ludp->lud_crit_exts++;
+        }
+    }
+
+    if( i == 0 ) {
+        /* must have 1 or more */
+        LDAP_FREE( url );
+        apr_ldap_free_urldesc( ludp );
+        return LDAP_URL_ERR_BADEXTS;
+    }
+
+    /* no more */
+    *ludpp = ludp;
+    LDAP_FREE( url );
+    return LDAP_URL_SUCCESS;
+}
+
+APU_DECLARE(int) apr_ldap_url_parse(LDAP_CONST char *url_in, 
+                                    apr_ldap_url_desc_t **ludpp)
+{
+    int rc = ldap_url_parse_ext( url_in, ludpp );
+
+    if( rc != LDAP_URL_SUCCESS ) {
+        return rc;
+    }
+
+    if ((*ludpp)->lud_scope == -1) {
+        (*ludpp)->lud_scope = LDAP_SCOPE_BASE;
+    }
+
+    if ((*ludpp)->lud_host != NULL && *(*ludpp)->lud_host == '\0') {
+        LDAP_FREE( (*ludpp)->lud_host );
+        (*ludpp)->lud_host = NULL;
+    }
+
+    return rc;
+}
+
+APU_DECLARE(void) apr_ldap_free_urldesc(apr_ldap_url_desc_t *ludp)
+{
+    if ( ludp == NULL ) {
+        return;
+    }
+    
+    if ( ludp->lud_scheme != NULL ) {
+        LDAP_FREE( ludp->lud_scheme );
+    }
+
+    if ( ludp->lud_host != NULL ) {
+        LDAP_FREE( ludp->lud_host );
+    }
+
+    if ( ludp->lud_dn != NULL ) {
+        LDAP_FREE( ludp->lud_dn );
+    }
+
+    if ( ludp->lud_filter != NULL ) {
+        LDAP_FREE( ludp->lud_filter);
+    }
+
+    if ( ludp->lud_attrs != NULL ) {
+        LDAP_VFREE( ludp->lud_attrs );
+    }
+
+    if ( ludp->lud_exts != NULL ) {
+        LDAP_VFREE( ludp->lud_exts );
+    }
+
+    LDAP_FREE( ludp );
+}
+
+
+static void ldap_pvt_hex_unescape(char *s)
+{
+    /*
+     * Remove URL hex escapes from s... done in place.  The basic concept for
+     * this routine is borrowed from the WWW library HTUnEscape() routine.
+     */
+    char    *p;
+
+    for ( p = s; *s != '\0'; ++s ) {
+        if ( *s == '%' ) {
+            if ( *++s == '\0' ) {
+                break;
+            }
+            *p = ldap_pvt_unhex( *s ) << 4;
+            if ( *++s == '\0' ) {
+                break;
+            }
+            *p++ += ldap_pvt_unhex( *s );
+        } else {
+            *p++ = *s;
+        }
+    }
+
+    *p = '\0';
+}
+
+
+static int ldap_pvt_unhex(int c)
+{
+    return( c >= '0' && c <= '9' ? c - '0'
+        : c >= 'A' && c <= 'F' ? c - 'A' + 10
+        : c - 'a' + 10 );
+}
+
+
+static void ldap_charray_free(char **a)
+{
+    char    **p;
+
+    if ( a == NULL ) {
+        return;
+    }
+
+    for ( p = a; *p != NULL; p++ ) {
+        if ( *p != NULL ) {
+            LDAP_FREE( *p );
+        }
+    }
+
+    LDAP_FREE( (char *) a );
+}
+
+static char **ldap_str2charray(const char *str_in, const char *brkstr)
+{
+    char    **res;
+    char    *str, *s;
+    char    *lasts;
+    int i;
+
+    /* protect the input string from strtok */
+    str = LDAP_STRDUP( str_in );
+    if( str == NULL ) {
+        return NULL;
+    }
+
+    i = 1;
+    for ( s = str; *s; s++ ) {
+        if ( ldap_utf8_strchr( brkstr, s ) != NULL ) {
+            i++;
+        }
+    }
+
+    res = (char **) LDAP_MALLOC( (i + 1) * sizeof(char *) );
+
+    if( res == NULL ) {
+        LDAP_FREE( str );
+        return NULL;
+    }
+
+    i = 0;
+
+    for ( s = ldap_utf8_strtok( str, brkstr, &lasts );
+        s != NULL;
+        s = ldap_utf8_strtok( NULL, brkstr, &lasts ) )
+    {
+        res[i] = LDAP_STRDUP( s );
+
+        if(res[i] == NULL) {
+            for( --i ; i >= 0 ; i-- ) {
+                LDAP_FREE( res[i] );
+            }
+            LDAP_FREE( res );
+            LDAP_FREE( str );
+            return NULL;
+        }
+
+        i++;
+    }
+
+    res[i] = NULL;
+
+    LDAP_FREE( str );
+    return( res );
+}


Reply via email to