[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-pim
Subject:    [Kde-pim] Threaded ldap search class
From:       Sean Harmer <sh () theharmers ! co ! uk>
Date:       2007-04-07 9:49:59
Message-ID: 200704071049.59155.sh () theharmers ! co ! uk
[Download RAW message or body]

Hi All,

I've put together the beginnings of a class to perform ldap searches in a 
separate thread so that it doesn't block the calling thread. I've called this 
class LdapSearchThread for want of a better name. I've included a patch 
against kdepimlibs revision 651209 that incorporates this class. The patch 
also includes a small local change that makes ldapconfigwidget and co use 
LdapDN objects to represent DNs rather than plain QStrings.

What I would like to know is what would you like me to do with this code? 
Should I incorporate similar changes into LdapSearch so that it is 
multithreaded by default fo should I add a new class to the kldap library 
(better names for the class are welcome)?

I realise that this is only the bare essentials to get something working at 
the moment, but I didn't want to go too far until I get some feedback as to 
whether this would be useful or not.

Kind regards,

Sean

["ldapsearchthread.diff" (text/x-diff)]

Index: kldap/ldapoperation.cpp
===================================================================
--- kldap/ldapoperation.cpp	(revision 651315)
+++ kldap/ldapoperation.cpp	(working copy)
@@ -31,8 +31,23 @@
 #include <lber.h>
 #endif
 
+#include <QTime>
+
 using namespace KLDAP;
 
+/*
+   Returns the difference between msecs and elapsed. If msecs is -1,
+   however, -1 is returned.
+*/
+static int kldap_timeout_value( int msecs, int elapsed )
+{
+  if ( msecs == -1 )
+    return -1;
+
+  int timeout = msecs - elapsed;
+  return timeout < 0 ? 0 : timeout;
+}
+
 class LdapOperation::LdapOperationPrivate {
   public:
   LdapControls mClientCtrls, mServerCtrls, mControls;
@@ -261,7 +276,7 @@
   }
 }
 
-int LdapOperation::search( const QString &base, LdapUrl::Scope scope,
+int LdapOperation::search( const LdapDN &base, LdapUrl::Scope scope,
                            const QString &filter, const QStringList &attributes )
 {
   Q_ASSERT( d->mConnection );
@@ -296,10 +311,10 @@
     break;
   }
 
-  kDebug(5322) << "asyncSearch() base=\"" << base << "\" scope=" << scope <<
+  kDebug(5322) << "asyncSearch() base=\"" << base.toString() << "\" scope=" << scope <<
     " filter=\"" << filter << "\" attrs=" << attributes << endl;
   int retval =
-    ldap_search_ext( ld, base.toUtf8(), lscope,
+    ldap_search_ext( ld, base.toString().toUtf8(), lscope,
                      filter.isEmpty() ? QByteArray("objectClass=*") : filter.toUtf8(),
                      attrs, 0, serverctrls, clientctrls, 0,
                      d->mConnection->sizeLimit(), &msgid );
@@ -690,16 +705,69 @@
   LDAP *ld = (LDAP*) d->mConnection->handle();
 
   LDAPMessage *msg;
-  int rescode, retval;
+  int rescode;
 
   rescode = ldap_result( ld, id, 0, NULL, &msg );
-  if ( rescode == -1 ) {
+  if ( rescode == -1 || processResult( rescode, msg ) == -1 ) {
     return -1;
   }
 
+  return rescode;
+}
+
+int LdapOperation::waitForResult( int id, int msecs )
+{
+  //kDebug() << "LdapOperation::waitForResult(" << id << ", " << msecs << ")" << endl;
+
+  Q_ASSERT( d->mConnection );
+  LDAP *ld = (LDAP*) d->mConnection->handle();
+
+  LDAPMessage *msg;
+  int rescode;
+
+  QTime stopWatch;
+  stopWatch.start();
+  int attempt( 1 );
+  int timeout( 0 );
+
+  do {
+    // Calculate the timeout value to use and assign it to a timeval structure
+    // see man select (2) for details
+    timeout = kldap_timeout_value( msecs, stopWatch.elapsed() );
+    kDebug() << "LdapOperation::waitForResult(" << id << ", " << msecs
+             << "):Waiting for " << timeout / 1000.0
+             << " secs for result. Attempt #" << attempt++ << endl;
+    struct timeval tv;
+    tv.tv_sec = timeout / 1000;
+    tv.tv_usec = ( timeout % 1000 ) * 1000;
+
+    // Wait for a result - or poll if timeout < 0
+    rescode = ldap_result( ld, id, 0, timeout < 0 ? 0 : &tv, &msg );
+
+    // Act on the return code
+    if ( rescode == -1 ) {
+      // No result is ready yet - let's go round again
+      continue;
+    }
+
+    // Some kind of result is available for processing
+    if ( processResult( rescode, msg ) == -1 )
+      return -1;
+  } while ( rescode == -1 && ( msecs == -1 || timeout < msecs ) );
+
+  return rescode;
+}
+
+int LdapOperation::processResult( int rescode, LDAPMessage *msg )
+{
+  kDebug() << "LdapOperation::processResult()" << endl;
+  int retval;
+  LDAP *ld = (LDAP*) d->mConnection->handle();
+
   switch ( rescode ) {
   case RES_SEARCH_ENTRY:
   {
+    kDebug() << "LdapOperation::processResult(): Found search entry" << endl;
     d->mObject.clear();
     LdapAttrMap attrs;
     char *name;
@@ -794,7 +862,7 @@
 }
 
 #else
-int LdapOperation::search( const QString &base, LdapUrl::Scope scope,
+int LdapOperation::search( const LdapDN &base, LdapUrl::Scope scope,
                            const QString &filter, const QStringList &attributes )
 {
   kError() << "LDAP support not compiled" << endl;
Index: kldap/ldapsearchthread.h
===================================================================
--- kldap/ldapsearchthread.h	(revision 0)
+++ kldap/ldapsearchthread.h	(revision 0)
@@ -0,0 +1,62 @@
+//
+// C++ Interface: ldapsearchthread
+//
+// Description:
+//
+//
+// Author:  <>, (C) 2007
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef LDAPSEARCHTHREAD_H
+#define LDAPSEARCHTHREAD_H
+
+#include <QThread>
+
+#include "ldapobject.h"
+#include "ldapserver.h"
+#include "kldap.h"
+
+namespace KLDAP {
+
+/**
+ * \brief A class to easily multithread LDAP searches.
+ */
+class KLDAP_EXPORT LdapSearchThread : public QThread
+{
+  Q_OBJECT
+  public:
+    explicit LdapSearchThread( const LdapServer& server );
+    virtual ~LdapSearchThread();
+
+    void setPollTimeout( int msecs = 100 );
+    int pollTimeout() const;
+
+    void search( const LdapDN &base,
+                 LdapUrl::Scope scope = LdapUrl::Sub,
+                 const QString &filter = QString(),
+                 const QStringList &attributes = QStringList(),
+                 int pagesize = 0 );
+
+  signals:
+    void data( LdapSearchThread*, const LdapObject& );
+    void result( LdapSearchThread* );
+
+  protected:
+    void run();
+    bool startSearch( const LdapDN &base, LdapUrl::Scope scope,
+                      const QString &filter,
+                      const QStringList &attributes,
+                      int pagesize );
+    bool pollForMessage();
+
+  private:
+    class LdapSearchThreadPrivate;
+    LdapSearchThreadPrivate *d;
+};
+
+}
+
+#endif
Index: kldap/ldapsearch.cpp
===================================================================
--- kldap/ldapsearch.cpp	(revision 651315)
+++ kldap/ldapsearch.cpp	(working copy)
@@ -19,6 +19,7 @@
 */
 
 #include "ldapsearch.h"
+#include "ldapdn.h"
 #include "ldapdefs.h"
 
 #include <QtCore/QEventLoop>
@@ -39,7 +40,7 @@
     void result();
     bool connect();
     void closeConnection();
-    bool startSearch( const QString &base, LdapUrl::Scope scope,
+    bool startSearch( const LdapDN &base, LdapUrl::Scope scope,
                       const QString &filter, const QStringList &attributes,
                       int pagesize );
 
@@ -48,7 +49,8 @@
     LdapOperation mOp;
     bool mOwnConnection, mAbandoned;
     int mId, mPageSize;
-    QString mBase, mFilter;
+    LdapDN mBase;
+    QString mFilter;
     QStringList mAttributes;
     LdapUrl::Scope mScope;
 
@@ -130,11 +132,11 @@
   }
 }
 
-bool LdapSearch::Private::startSearch( const QString &base, LdapUrl::Scope scope,
+bool LdapSearch::Private::startSearch( const LdapDN &base, LdapUrl::Scope scope,
                                        const QString &filter,
                                        const QStringList &attributes, int pagesize )
 {
-  kDebug(5322) << "search: base=" << base << " scope=" << scope << " filter=" << filter
+  kDebug(5322) << "search: base=" << base.toString() << " scope=" << scope << " filter=" << filter
     << " attributes=" << attributes << " pagesize=" << pagesize  << endl;
   mAbandoned = false;
   mError = 0;
@@ -233,7 +235,7 @@
                          url.attributes(), pagesize );
 }
 
-bool LdapSearch::search( const QString &base, LdapUrl::Scope scope,
+bool LdapSearch::search( const LdapDN &base, LdapUrl::Scope scope,
                          const QString &filter, const QStringList &attributes,
                          int pagesize )
 {
Index: kldap/ldapserver.cpp
===================================================================
--- kldap/ldapserver.cpp	(revision 651315)
+++ kldap/ldapserver.cpp	(working copy)
@@ -29,7 +29,7 @@
   public:
     QString mHost;
     int mPort;
-    QString mBaseDn;
+    LdapDN mBaseDn;
     QString mUser;
     QString mBindDn;
     QString mRealm;
@@ -98,7 +98,7 @@
   return d->mPort;
 }
 
-QString LdapServer::baseDn() const
+LdapDN LdapServer::baseDn() const
 {
   return d->mBaseDn;
 }
@@ -178,7 +178,7 @@
   d->mPort = port;
 }
 
-void LdapServer::setBaseDn( const QString &baseDn )
+void LdapServer::setBaseDn( const LdapDN &baseDn )
 {
   d->mBaseDn = baseDn;
 }
Index: kldap/ldapurl.h
===================================================================
--- kldap/ldapurl.h	(revision 651315)
+++ kldap/ldapurl.h	(working copy)
@@ -26,6 +26,7 @@
 
 #include <kurl.h>
 
+#include "ldapdn.h"
 #include "kldap.h"
 
 namespace KLDAP {
@@ -67,9 +68,9 @@
      * Returns the dn part of the LDAP Url (same as path(), but slash removed
      * from the beginning).
      */
-    QString dn() const;
+    LdapDN dn() const;
     /** Sets the the dn part of the LDAP Url. */
-    void setDn( const QString &dn );
+    void setDn( const LdapDN &dn );
 
     /** Returns the attributes part of the LDAP Url */
     QStringList attributes() const;
Index: kldap/ldapconfigwidget.h
===================================================================
--- kldap/ldapconfigwidget.h	(revision 651315)
+++ kldap/ldapconfigwidget.h	(working copy)
@@ -24,6 +24,7 @@
 #include <QtCore/QString>
 #include <QtGui/QWidget>
 
+#include "ldapdn.h"
 #include "kldap.h"
 #include "ldapobject.h"
 #include "ldapserver.h"
@@ -54,7 +55,7 @@
   Q_PROPERTY( QString host READ host WRITE setHost )
   Q_PROPERTY( int port READ port WRITE setPort )
   Q_PROPERTY( int version READ version WRITE setVersion )
-  Q_PROPERTY( QString dn READ dn WRITE setDn )
+  Q_PROPERTY( LdapDN dn READ dn WRITE setDn )
   Q_PROPERTY( QString filter READ filter WRITE setFilter )
   Q_PROPERTY( QString mech READ mech WRITE setMech )
   Q_PROPERTY( Security security READ security WRITE setSecurity )
@@ -141,9 +142,9 @@
     int version() const;
 
     /** Sets the LDAP Base DN. Kconfig widget name: kcfg_ldapdn */
-    void setDn( const QString &dn );
+    void setDn( const LdapDN &dn );
     /** Gets the LDAP Base DN. Kconfig widget name: kcfg_ldapdn */
-    QString dn() const;
+    LdapDN dn() const;
 
     /** Sets the LDAP Filter. Kconfig widget name: kcfg_ldapfilter */
     void setFilter( const QString &filter );
Index: kldap/ldapmodel_p.cpp
===================================================================
--- kldap/ldapmodel_p.cpp	(revision 651315)
+++ kldap/ldapmodel_p.cpp	(working copy)
@@ -70,7 +70,7 @@
                                           const QStringList &attributes,
                                           int pagesize )
 {
-  return m_search->search( searchBase.toString(), scope, filter, attributes, pagesize );
+  return m_search->search( searchBase, scope, filter, attributes, pagesize );
 }
 
 void LdapModel::LdapModelPrivate::setSearchType( SearchType t, LdapModelTreeItem *item )
Index: kldap/tests/testkldap.h
===================================================================
--- kldap/tests/testkldap.h	(revision 651315)
+++ kldap/tests/testkldap.h	(working copy)
@@ -24,6 +24,7 @@
 #include <ldapmodel.h>
 #include <ldapobject.h>
 #include <ldapsearch.h>
+#include <ldapsearchthread.h>
 
 
 using namespace KLDAP;
@@ -40,6 +41,7 @@
         void testLdapUrl();
         void testLdapConnection();
         void testLdapSearch();
+        void testLdapSearchThread();
         void testLdapDN();
         void testLdapModel();
 
@@ -47,6 +49,9 @@
         void searchResult( LdapSearch* );
         void searchData( LdapSearch*, const LdapObject& );
 
+        void searchResult( LdapSearchThread* );
+        void searchData( LdapSearchThread*, const LdapObject& );
+
     private:
         QString m_url;
         LdapSearch* m_search;
Index: kldap/tests/testkldap.cpp
===================================================================
--- kldap/tests/testkldap.cpp	(revision 651315)
+++ kldap/tests/testkldap.cpp	(working copy)
@@ -31,12 +31,15 @@
 #include "ldapmodel.h"
 #include "ldapoperation.h"
 #include "ldapsearch.h"
+#include "ldapsearchthread.h"
 #include "ber.h"
 
 #include "kldap.h"
 #include <kdebug.h>
 #include <qtest_kde.h>
 
+#include <unistd.h>
+
 #ifdef LDAP_FOUND
 #include <ldap.h>
 #include <lber.h>
@@ -91,7 +94,7 @@
 
     QCOMPARE( url.user(), QString::fromLatin1("cn=manager,dc=kde,dc=org") );
     QCOMPARE( url.password(), QString::fromLatin1("password") );
-    QCOMPARE( url.dn(), QString::fromLatin1("dc=kde,dc=org") );
+    QCOMPARE( url.dn().toString(), QString::fromLatin1("dc=kde,dc=org") );
     QCOMPARE( url.scope(), LdapUrl::Sub );
     QCOMPARE( url.attributes().at(0), QString::fromLatin1("cn") );
     QCOMPARE( url.attributes().at(1), QString::fromLatin1("mail") );
@@ -139,24 +142,70 @@
     kDebug() << "Search found " << m_objects.size() << " matching entries" << endl;
 }
 
+
 void KLdapTest::searchResult( LdapSearch* search )
 {
-    kDebug() << "KLdapTest::searchResult()" << endl;
-    int err = search->error();
-    if ( err )
-        kDebug() << "Search returned the following error: " << search->errorString() << endl;
-    QCOMPARE( err, 0 );
+  kDebug() << "KLdapTest::searchResult()" << endl;
+  int err = search->error();
+  if ( err )
+    kDebug() << "Search returned the following error: " << search->errorString() << endl;
+  QCOMPARE( err, 0 );
 }
 
 
 void KLdapTest::searchData( LdapSearch* /*search*/, const LdapObject& obj )
 {
-    //kDebug() << "KLdapTest::searchData()" << endl;
-    //kDebug() << "Object:" << endl << obj.toString() << endl;
-    m_objects.append( obj );
+  //kDebug() << "KLdapTest::searchData()" << endl;
+  //kDebug() << "Object:" << endl << obj.toString() << endl;
+  m_objects.append( obj );
 }
 
 
+void KLdapTest::testLdapSearchThread()
+{
+    LdapUrl url;
+    url.setUrl( m_url );
+    LdapServer server( url );
+    LdapSearchThread* searchThread = new LdapSearchThread( server );
+
+    qRegisterMetaType<LdapObject>("LdapObject");
+    connect( searchThread, SIGNAL( result( LdapSearchThread* ) ),
+             this, SLOT( searchResult( LdapSearchThread* ) ) );
+    connect( searchThread, SIGNAL( data( LdapSearchThread*, const LdapObject& ) ),
+             this, SLOT( searchData( LdapSearchThread*, const LdapObject& ) ) );
+
+    QStringList attributes = QStringList() << "cn" << "memberuid";
+    searchThread->search( LdapDN( "ou=groups,dc=esrtechnology,dc=com" ),
+                          LdapUrl::Sub,
+                          QString( "(cn=*)" ),
+                          attributes );
+
+    kDebug() << "Sleeping for 5 seconds to allow thread to do stuff" << endl;
+    sleep( 5 );
+
+    while( QCoreApplication::hasPendingEvents() )
+      qApp->processEvents();
+}
+
+
+void KLdapTest::searchResult( LdapSearchThread* /*search*/ )
+{
+  /*
+  kDebug() << "KLdapTest::searchResult()" << endl;
+  int err = search->error();
+  if ( err )
+    kDebug() << "Search returned the following error: " << search->errorString() << endl;
+  QCOMPARE( err, 0 );
+  */
+}
+
+
+void KLdapTest::searchData( LdapSearchThread*, const LdapObject& obj )
+{
+  kDebug() << "Object:" << endl << obj.toString() << endl;
+}
+
+
 void KLdapTest::testLdapDN()
 {
     QString strDN( "uid=Test\\+Person+ou=accounts\\,outgoing,dc=kde,dc=org" );
Index: kldap/CMakeLists.txt
===================================================================
--- kldap/CMakeLists.txt	(revision 651315)
+++ kldap/CMakeLists.txt	(working copy)
@@ -38,6 +38,7 @@
    ldapoperation.cpp
    ldapcontrol.cpp
    ldapsearch.cpp
+   ldapsearchthread.cpp
    ldapconfigwidget.cpp
    ldapdn.cpp
    ldapmodeltreeitem_p.cpp
@@ -60,5 +61,5 @@
 
 install( FILES ber.h kldap.h ldapdefs.h ldif.h ldapurl.h ldapserver.h ldapobject.h 
   ldapconnection.h ldapoperation.h 
-  ldapconfigwidget.h ldapcontrol.h ldapsearch.h
+  ldapconfigwidget.h ldapcontrol.h ldapsearch.h ldapsearchthread.h
   ldapdn.h ldapmodel.h DESTINATION ${INCLUDE_INSTALL_DIR}/kldap)
Index: kldap/ldapsearchthread.cpp
===================================================================
--- kldap/ldapsearchthread.cpp	(revision 0)
+++ kldap/ldapsearchthread.cpp	(revision 0)
@@ -0,0 +1,254 @@
+//
+// C++ Implementation: ldapsearchthread
+//
+// Description:
+//
+//
+// Author:  <>, (C) 2007
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include "ldapsearchthread.h"
+#include "ldapconnection.h"
+#include "ldapoperation.h"
+#include "ldapdefs.h"
+
+#include <QMutex>
+#include <QMutexLocker>
+#include <QWaitCondition>
+
+#include <kdebug.h>
+
+using namespace KLDAP;
+
+class LdapSearchThread::LdapSearchThreadPrivate
+{
+  public:
+    bool connect();
+
+    QMutex mMutex;
+    QWaitCondition mCondition;
+    bool mAbort;
+    bool mRestart;
+
+    LdapConnection mConn;
+    LdapOperation mOp;
+    int mTimeout;
+    int mId, mPageSize;
+    LdapDN mBase;
+    QString mFilter;
+    QStringList mAttributes;
+    LdapUrl::Scope mScope;
+
+    QString mErrorString;
+    int mError;
+};
+
+bool LdapSearchThread::LdapSearchThreadPrivate::connect()
+{
+  int ret = mConn.connect();
+  if ( ret != KLDAP_SUCCESS ) {
+    mConn.close();
+    return false;
+  }
+  ret = mConn.bind();
+  if ( ret != KLDAP_SUCCESS ) {
+    mConn.close();
+    return false;
+  }
+  return true;
+}
+
+
+LdapSearchThread::LdapSearchThread( const LdapServer& server )
+  : d( new LdapSearchThreadPrivate )
+{
+  d->mRestart = false;
+  d->mAbort = false;
+  d->mTimeout = 10 * 1000;
+  d->mConn.setServer( server );
+  d->connect();
+}
+
+LdapSearchThread::~LdapSearchThread()
+{
+  d->mMutex.lock();
+  d->mAbort = true;
+  d->mCondition.wakeOne();
+  d->mMutex.unlock();
+
+  // Wait for run() to exit before we destroy this object
+  wait();
+}
+
+void LdapSearchThread::setPollTimeout( int msecs )
+{
+  QMutexLocker( &(d->mMutex) );
+  d->mTimeout = msecs;
+}
+
+int LdapSearchThread::pollTimeout() const
+{
+  return d->mTimeout;
+}
+
+void LdapSearchThread::search( const LdapDN &base,
+                               LdapUrl::Scope scope,
+                               const QString &filter,
+                               const QStringList &attributes,
+                               int pagesize )
+{
+  kDebug() << "LdapSearchThread::search(): " << endl;
+  QMutexLocker locker( &(d->mMutex) );
+
+  d->mBase = base;
+  d->mScope = scope;
+  d->mFilter = filter;
+  d->mAttributes = attributes;
+  d->mPageSize = pagesize;
+
+  if ( !isRunning() ) {
+    kDebug() << "\tCalling start()" << endl;
+    start( LowPriority );
+  } else {
+    kDebug() << "\tCalling wakeOne()" << endl;
+    d->mRestart = true;
+    d->mCondition.wakeOne();
+  }
+}
+
+void LdapSearchThread::run()
+{
+  forever {
+    // Store the search parameters locally to prevent the calling thread from
+    // blocking for very long if it needs to start a different search.
+    d->mMutex.lock();
+    LdapDN base = d->mBase;
+    LdapUrl::Scope scope = d->mScope;
+    QString filter = d->mFilter;
+    QStringList attributes = d->mAttributes;
+    int pagesize = d->mPageSize;
+    d->mMutex.unlock();
+
+    // Start the search off
+    if ( !startSearch( base, scope, filter, attributes, pagesize ) )
+      return;
+
+    // Poll for responses from the server until the results have been
+    // completely returned or we are told to abort
+    bool pollAgain( true );
+    while ( pollAgain ) {
+      // Have we been told to abort or start a new search?
+      if ( d->mAbort )
+        return;
+      else if ( d->mRestart )
+        break;
+
+      // Poll for messages from the LDAP server
+      pollAgain = pollForMessage();
+    }
+
+    // Go to sleep until we are needed for another search
+    d->mMutex.lock();
+    d->mCondition.wait( &(d->mMutex) );
+    d->mMutex.unlock();
+  }
+}
+
+bool LdapSearchThread::startSearch( const LdapDN &base, LdapUrl::Scope scope,
+                                    const QString &filter,
+                                    const QStringList &attributes,
+                                    int pagesize )
+{
+  kDebug() << "search: base=" << base.toString() << " scope=" << scope << " filter=" << filter
+      << " attributes=" << attributes << " pagesize=" << pagesize  << endl;
+  d->mAbort = false;
+  d->mError = 0;
+  d->mErrorString = QString();
+  d->mOp.setConnection( d->mConn );
+  d->mPageSize = pagesize;
+  d->mBase = base;
+  d->mScope = scope;
+  d->mFilter = filter;
+  d->mAttributes = attributes;
+
+  LdapControls savedctrls = d->mOp.serverControls();
+  if ( pagesize ) {
+    LdapControls ctrls = savedctrls;
+    ctrls.append( LdapControl::createPageControl( pagesize ) );
+    d->mOp.setServerControls( ctrls );
+  }
+
+  d->mId = d->mOp.search( base, scope, filter, attributes );
+  if ( pagesize ) {
+    d->mOp.setServerControls( savedctrls );
+  }
+
+  if ( d->mId == -1 ) {
+    return false;
+  }
+
+  kDebug() << "search::startSearch msg id=" << d->mId << endl;
+  return true;
+}
+
+bool LdapSearchThread::pollForMessage()
+{
+  kDebug() << endl << "LdapSearchThread::pollForMessage()" << endl;
+  int res = d->mOp.waitForResult( d->mId, d->mTimeout );
+
+  if ( res == -1 || d->mConn.ldapErrorCode() != KLDAP_SUCCESS ) {
+    kDebug() << "Problem with the search" << endl;
+    d->mError = d->mConn.ldapErrorCode();
+    d->mErrorString = d->mConn.ldapErrorString();
+    emit result( this );
+    return false;
+  }
+
+  if ( res == LdapOperation::RES_SEARCH_RESULT ) {
+    kDebug() << "Got search result" << endl;
+    if ( d->mPageSize ) {
+      QByteArray cookie;
+      int estsize = -1;
+      for ( int i = 0; i < d->mOp.controls().count(); ++i ) {
+        estsize = d->mOp.controls()[i].parsePageControl( cookie );
+        if ( estsize != -1 ) {
+          break;
+        }
+      }
+      kDebug() << " estimated size: " << estsize << endl;
+      if ( estsize != -1 && !cookie.isEmpty() ) {
+        LdapControls ctrls, savedctrls;
+        savedctrls = d->mOp.serverControls();
+        ctrls = savedctrls;
+        ctrls.append( LdapControl::createPageControl( d->mPageSize, cookie ) );
+        d->mOp.setServerControls( ctrls );
+        d->mId = d->mOp.search( d->mBase, d->mScope, d->mFilter, d->mAttributes );
+        d->mOp.setServerControls( savedctrls );
+        if ( d->mId == -1 ) {
+          d->mError = d->mConn.ldapErrorCode();
+          d->mErrorString = d->mConn.ldapErrorString();
+          emit result( this );
+          return false;
+        }
+        //QTimer::singleShot( 0, this, SLOT(result()) );
+        return true;
+      }
+    }
+    emit result( this );
+    return false;
+  }
+
+  if ( res == LdapOperation::RES_SEARCH_ENTRY ) {
+    kDebug() << "Found search entry" << endl;
+    //kDebug() << "\tEmitting signal data(" << this << d->mOp.object().toString() << endl;
+    emit data( this, d->mOp.object() );
+    return true;
+  }
+
+  return true;
+}
+
+#include "ldapsearchthread.moc"
Index: kldap/ldapurl.cpp
===================================================================
--- kldap/ldapurl.cpp	(revision 651315)
+++ kldap/ldapurl.cpp	(working copy)
@@ -82,9 +82,9 @@
   delete d;
 }
 
-void LdapUrl::setDn( const QString &dn )
+void LdapUrl::setDn( const LdapDN &dn )
 {
-  QString tmp = dn;
+  QString tmp = dn.toString();
   if ( !QDir::isRelativePath( tmp ) )
 #ifdef Q_WS_WIN
     tmp.remove( 0, 3 ); // e.g. "c:/"
@@ -94,7 +94,7 @@
   setPath( tmp );
 }
 
-QString LdapUrl::dn() const
+LdapDN LdapUrl::dn() const
 {
   QString tmp = path();
   if ( !QDir::isRelativePath( tmp ) )
@@ -103,7 +103,8 @@
 #else
     tmp.remove( 0, 1 );
 #endif
-  return tmp;
+  LdapDN tmpDN( tmp );
+  return tmpDN;
 }
 
 QStringList LdapUrl::attributes() const
Index: kldap/ldapoperation.h
===================================================================
--- kldap/ldapoperation.h	(revision 651315)
+++ kldap/ldapoperation.h	(working copy)
@@ -29,8 +29,11 @@
 #include "ldapconnection.h"
 #include "ldapcontrol.h"
 #include "ldapobject.h"
+#include "ldapdn.h"
 #include "ldapserver.h"
 #include "ldapurl.h"
+#include "ldap.h"
+//typedef struct ldapmsg LDAPMessage;
 
 namespace KLDAP {
 
@@ -102,7 +105,7 @@
      * Starts a search operation with the given base DN, scope, filter and
      * result attributes. Returns a message id if successful, -1 if not.
      */
-    int search( const QString &base, LdapUrl::Scope scope,
+    int search( const LdapDN &base, LdapUrl::Scope scope,
                 const QString &filter, const QStringList &attrs );
     /**
      * Starts an addition operation.
@@ -188,6 +191,8 @@
      * connection().ldapErrorCode() to determine if the operation succeeded.
      */
     int result( int id );
+
+    int waitForResult( int id, int msecs = 30000 );
     /**
      * Returns the result object if result() returned RES_SEARCH_ENTRY.
      */
@@ -220,6 +225,9 @@
     QList<QByteArray> referrals() const;
 
   private:
+    int processResult( int rescode, LDAPMessage *msg );
+
+  private:
     class LdapOperationPrivate;
     LdapOperationPrivate *const d;
 
Index: kldap/ldapconfigwidget.cpp
===================================================================
--- kldap/ldapconfigwidget.cpp	(revision 651315)
+++ kldap/ldapconfigwidget.cpp	(working copy)
@@ -330,7 +330,7 @@
   if ( mPort ) {
     _url.setPort( mPort->value() );
   }
-  _url.setDn( "" );
+  _url.setDn( LdapDN( "" ) );
   _url.setAttributes( QStringList( mAttr ) );
   _url.setScope( LdapUrl::Base );
   if ( mVersion ) {
@@ -558,7 +558,7 @@
     _server.setPort( d->mPort->value() );
   }
   if ( d->mDn ) {
-    _server.setBaseDn( d->mDn->text() );
+    _server.setBaseDn( LdapDN( d->mDn->text() ) );
   }
   if ( d->mFilter ) {
     _server.setFilter( d->mFilter->text() );
@@ -717,16 +717,16 @@
   return d->mVersion ? d->mVersion->value() : 3;
 }
 
-void LdapConfigWidget::setDn( const QString &dn )
+void LdapConfigWidget::setDn( const LdapDN &dn )
 {
   if ( d->mDn ) {
-    d->mDn->setText( dn );
+    d->mDn->setText( dn.toString() );
   }
 }
 
-QString LdapConfigWidget::dn() const
+LdapDN LdapConfigWidget::dn() const
 {
-  return d->mDn ? d->mDn->text() : QString();
+  return d->mDn ? LdapDN( d->mDn->text() ) : LdapDN();
 }
 
 void LdapConfigWidget::setFilter( const QString &filter )
Index: kldap/ldapsearch.h
===================================================================
--- kldap/ldapsearch.h	(revision 651315)
+++ kldap/ldapsearch.h	(working copy)
@@ -89,7 +89,7 @@
      * Starts a search operation if the LdapConnection object already set
      * in the constructor.
      */
-    bool search( const QString &base,
+    bool search( const LdapDN &base,
                  LdapUrl::Scope scope = LdapUrl::Sub,
                  const QString &filter = QString(),
                  const QStringList &attributes = QStringList(),
Index: kldap/ldapserver.h
===================================================================
--- kldap/ldapserver.h	(revision 651315)
+++ kldap/ldapserver.h	(working copy)
@@ -24,6 +24,7 @@
 #include <QtCore/QString>
 
 #include "ldapurl.h"
+#include "ldapdn.h"
 #include "kldap.h"
 
 namespace KLDAP {
@@ -56,7 +57,7 @@
 
     QString host() const;
     int port() const;
-    QString baseDn() const;
+    LdapDN baseDn() const;
     QString user() const;
     QString bindDn() const;
     QString realm() const;
@@ -74,7 +75,7 @@
 
     void setHost( const QString &host );
     void setPort( int port );
-    void setBaseDn( const QString &baseDn );
+    void setBaseDn( const LdapDN &baseDn );
     void setUser( const QString &user );
     void setBindDn( const QString &bindDn );
     void setRealm( const QString &realm );
Index: kabc/plugins/ldapkio/resourceldapkioconfig.cpp
===================================================================
--- kabc/plugins/ldapkio/resourceldapkioconfig.cpp	(revision 651315)
+++ kabc/plugins/ldapkio/resourceldapkioconfig.cpp	(working copy)
@@ -93,7 +93,7 @@
   cfg->setVersion( resource->ver() );
   cfg->setTimeLimit( resource->timeLimit() );
   cfg->setSizeLimit( resource->sizeLimit() );
-  cfg->setDn( resource->dn() );
+  cfg->setDn( KLDAP::LdapDN( resource->dn() ) );
   cfg->setFilter( resource->filter() );
   cfg->setMech( resource->mech() );
   if ( resource->isTLS() ) cfg->setSecurity( KLDAP::LdapConfigWidget::TLS );
@@ -129,7 +129,7 @@
   resource->setVer( cfg->version() );
   resource->setTimeLimit( cfg->timeLimit() );
   resource->setSizeLimit( cfg->sizeLimit() );
-  resource->setDn( cfg->dn() );
+  resource->setDn( cfg->dn().toString() );
   resource->setFilter( cfg->filter() );
   resource->setIsAnonymous( cfg->auth() == KLDAP::LdapConfigWidget::Anonymous );
   resource->setIsSASL(  cfg->auth() == KLDAP::LdapConfigWidget::SASL );
Index: kabc/plugins/ldapkio/resourceldapkio.cpp
===================================================================
--- kabc/plugins/ldapkio/resourceldapkio.cpp	(revision 651315)
+++ kabc/plugins/ldapkio/resourceldapkio.cpp	(working copy)
@@ -36,6 +36,7 @@
 #include <kio/netaccess.h>
 
 #include "kldap/ldif.h"
+#include "kldap/ldapdn.h"
 #include "kldap/ldapurl.h"
 
 #include "resourceldapkio.h"
@@ -399,7 +400,7 @@
   d->mLDAPUrl.setProtocol( d->mSSL ? "ldaps" : "ldap");
   d->mLDAPUrl.setHost( d->mHost );
   d->mLDAPUrl.setPort( d->mPort );
-  d->mLDAPUrl.setDn( d->mDn );
+  d->mLDAPUrl.setDn( KLDAP::LdapDN( d->mDn ) );
 
   if (!d->mAttributes.empty()) {
     QMap<QString,QString>::Iterator it;


_______________________________________________
kde-pim mailing list
kde-pim@kde.org
https://mail.kde.org/mailman/listinfo/kde-pim
kde-pim home page at http://pim.kde.org/

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic