[python-ldap] ldap.init_fd() patch for python-ldap-2.4.15

Mark R Bannister mark at proseconsulting.co.uk
Tue Sep 2 00:25:22 CEST 2014


Hi,

I needed ldap.init_fd(), so I wrote a patch.  Please find attached. Hope 
this works for you too.  I've only tested on OpenSuSE.

This is an example of how to use it:

###
import ldap
import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("localhost", 389))
l = ldap.init_fd(sock.fileno(), ldap.PROTO_TCP, "ldap://localhost:389")
...
###

I found I had to install openldap2-debugsource to get ldap_pvt.h.  I 
added /usr/src/debug/openldap-2.4.33/include to include_dirs in 
setup.cfg to get it to compile.  This header worked fine with 
openldap2-2.4.26.

Best regards,

Mark R. Bannister.
Author of DBIS: 
http://technicalprose.blogspot.co.uk/2013/08/introducing-dbis.html

-------------- next part --------------
diff -u -r a/python-ldap-2.4.15/Lib/ldap/functions.py b/python-ldap-2.4.15/Lib/ldap/functions.py
--- a/python-ldap-2.4.15/Lib/ldap/functions.py	2011-11-25 12:22:02.000000000 +0000
+++ b/python-ldap-2.4.15/Lib/ldap/functions.py	2014-09-01 22:34:16.881369666 +0100
@@ -21,7 +21,7 @@
 from ldap import __version__
 
 __all__ = [
-  'open','initialize','init',
+  'open','initialize','init_fd','init',
   'explode_dn','explode_rdn',
   'get_option','set_option',
 ]
@@ -32,7 +32,7 @@
 
 from ldap.dn import explode_dn,explode_rdn
 
-from ldap.ldapobject import LDAPObject
+from ldap.ldapobject import LDAPObject,LDAPObjectFromFD
 
 if __debug__:
   # Tracing is only supported in debugging mode
@@ -91,6 +91,29 @@
   return LDAPObject(uri,trace_level,trace_file,trace_stack_limit)
 
 
+def init_fd(fd,proto,uri=None,trace_level=0,trace_file=sys.stdout,trace_stack_limit=None):
+  """
+  Return LDAPObject instance by opening LDAP connection over
+  existing connection on the provided socket
+
+  Parameters:
+  fd
+        File descriptor of an already-opened socket, e.g. socket.fileno()
+  proto
+        One of ldap.PROTO_TCP, ldap.PROTO_UDP or ldap.PROTO_IPC.
+  uri
+        LDAP URL containing at least connection scheme and hostport,
+        e.g. ldap://localhost:389
+        This is optional and is provided for informational purposes.
+  trace_level
+        If non-zero a trace output of LDAP calls is generated.
+  trace_file
+        File object where to write the trace output to.
+        Default is to use stdout.
+  """
+  return LDAPObjectFromFD(fd,proto,uri,trace_level,trace_file,trace_stack_limit)
+
+
 def open(host,port=389,trace_level=0,trace_file=sys.stdout,trace_stack_limit=None):
   """
   Return LDAPObject instance by opening LDAP connection to
diff -u -r a/python-ldap-2.4.15/Lib/ldap/__init__.py b/python-ldap-2.4.15/Lib/ldap/__init__.py
--- a/python-ldap-2.4.15/Lib/ldap/__init__.py	2014-03-24 10:20:16.000000000 +0000
+++ b/python-ldap-2.4.15/Lib/ldap/__init__.py	2014-09-01 21:38:40.930387447 +0100
@@ -82,7 +82,7 @@
 # Create module-wide lock for serializing all calls into underlying LDAP lib
 _ldap_module_lock = LDAPLock(desc='Module wide')
 
-from functions import open,initialize,init,get_option,set_option
+from functions import open,initialize,init_fd,init,get_option,set_option
 
 from ldap.dn import explode_dn,explode_rdn,str2dn,dn2str
 del str2dn
diff -u -r a/python-ldap-2.4.15/Lib/ldap/ldapobject.py b/python-ldap-2.4.15/Lib/ldap/ldapobject.py
--- a/python-ldap-2.4.15/Lib/ldap/ldapobject.py	2014-03-07 20:01:12.000000000 +0000
+++ b/python-ldap-2.4.15/Lib/ldap/ldapobject.py	2014-09-01 22:58:01.736461427 +0100
@@ -23,6 +23,8 @@
 __all__ = [
   'LDAPObject',
   'SimpleLDAPObject',
+  'LDAPObjectFromFD',
+  'SimpleLDAPObjectFromFD',
   'NonblockingLDAPObject',
   'ReconnectLDAPObject',
 ]
@@ -879,6 +881,28 @@
     return self._apply_method_s(SimpleLDAPObject.whoami_s,*args,**kwargs)
 
 
+class SimpleLDAPObjectFromFD(SimpleLDAPObject):
+  """
+  Identical to SimpleLDAPObject except that it uses ldap_init_fd()
+  """
+
+  def __init__(
+    self,fd,proto,uri=None,
+    trace_level=0,trace_file=None,trace_stack_limit=5
+  ):
+    self._trace_level = trace_level
+    self._trace_file = trace_file or sys.stdout
+    self._trace_stack_limit = trace_stack_limit
+    self._fd = fd
+    self._proto = proto
+    self._uri = uri
+    self._ldap_object_lock = self._ldap_lock('opcall')
+    self._l = ldap.functions._ldap_function_call(ldap._ldap_module_lock,_ldap.init_fd,fd,proto,uri)
+    self.timeout = -1
+    self.protocol_version = ldap.VERSION3
+
+
 # The class called LDAPObject will be used as default for
 # ldap.open() and ldap.initialize()
 LDAPObject = SimpleLDAPObject
+LDAPObjectFromFD = SimpleLDAPObjectFromFD
diff -u -r a/python-ldap-2.4.15/Modules/constants.c b/python-ldap-2.4.15/Modules/constants.c
--- a/python-ldap-2.4.15/Modules/constants.c	2014-03-24 10:20:16.000000000 +0000
+++ b/python-ldap-2.4.15/Modules/constants.c	2014-09-01 22:24:39.152943357 +0100
@@ -6,6 +6,7 @@
 #include "constants.h"
 #include "lber.h"
 #include "ldap.h"
+#include "ldap_pvt.h"
 
 static PyObject* reverse;
 static PyObject* forward;
@@ -140,6 +141,10 @@
   add_int(d,DEREF_ALWAYS);
   add_int(d,NO_LIMIT);
 
+  add_int(d,PROTO_TCP);
+  add_int(d,PROTO_UDP);
+  add_int(d,PROTO_IPC);
+
   add_int(d,OPT_API_INFO);
   add_int(d,OPT_DEREF);
   add_int(d,OPT_SIZELIMIT);
diff -u -r a/python-ldap-2.4.15/Modules/functions.c b/python-ldap-2.4.15/Modules/functions.c
--- a/python-ldap-2.4.15/Modules/functions.c	2011-06-08 20:35:33.000000000 +0100
+++ b/python-ldap-2.4.15/Modules/functions.c	2014-09-01 22:43:23.434833804 +0100
@@ -7,6 +7,7 @@
 #include "berval.h"
 #include "errors.h"
 #include "options.h"
+#include "ldap_pvt.h"
 
 /* ldap_initialize */
 
@@ -29,6 +30,27 @@
 }
 
 
+/* ldap_init_fd */
+
+static PyObject*
+l_ldap_init_fd(PyObject* unused, PyObject *args)
+{
+    char *uri = NULL;
+    LDAP *ld = NULL;
+    int ret, fd, proto;
+
+    if (!PyArg_ParseTuple(args, "ii|s", &fd, &proto, &uri))
+    	return NULL;
+
+    Py_BEGIN_ALLOW_THREADS
+    ret = ldap_init_fd((ber_socket_t)fd, proto, uri, &ld);
+    Py_END_ALLOW_THREADS
+    if (ret != LDAP_SUCCESS)
+    	return LDAPerror(ld, "ldap_init_fd");
+    return (PyObject*)newLDAPObject(ld);
+}
+
+
 /* ldap_str2dn */
 
 static PyObject*
@@ -137,6 +159,7 @@
 
 static PyMethodDef methods[] = {
     { "initialize",	(PyCFunction)l_ldap_initialize,		METH_VARARGS },
+    { "init_fd",	(PyCFunction)l_ldap_init_fd,		METH_VARARGS },
     { "str2dn",	    (PyCFunction)l_ldap_str2dn,			METH_VARARGS },
     { "set_option", (PyCFunction)l_ldap_set_option,		METH_VARARGS },
     { "get_option", (PyCFunction)l_ldap_get_option,		METH_VARARGS },


More information about the python-ldap mailing list