• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.8.3 API Reference
  • KDE Home
  • Contact Us
 

KLDAP Library

ldapsearch.cpp
00001 /*
00002   This file is part of libkldap.
00003   Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
00004 
00005   This library is free software; you can redistribute it and/or
00006   modify it under the terms of the GNU Library General  Public
00007   License as published by the Free Software Foundation; either
00008   version 2 of the License, or (at your option) any later version.
00009 
00010   This library is distributed in the hope that it will be useful,
00011   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013   Library General Public License for more details.
00014 
00015   You should have received a copy of the GNU Library General Public License
00016   along with this library; see the file COPYING.LIB.  If not, write to
00017   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018   Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "ldapsearch.h"
00022 #include "ldapdn.h"
00023 #include "ldapdefs.h"
00024 
00025 #include <QtCore/QEventLoop>
00026 #include <QtCore/QTimer>
00027 
00028 #include <kdebug.h>
00029 #include <KLocale>
00030 using namespace KLDAP;
00031 
00032 //blocking the GUI for xxx milliseconds
00033 #define LDAPSEARCH_BLOCKING_TIMEOUT 10
00034 
00035 class LdapSearch::Private
00036 {
00037   public:
00038     Private( LdapSearch *parent )
00039       : mParent( parent )
00040     {
00041     }
00042 
00043     void result();
00044     bool connect();
00045     void closeConnection();
00046     bool startSearch( const LdapDN &base, LdapUrl::Scope scope,
00047                       const QString &filter, const QStringList &attributes,
00048                       int pagesize, int count );
00049 
00050     LdapSearch *mParent;
00051     LdapConnection *mConn;
00052     LdapOperation mOp;
00053     bool mOwnConnection, mAbandoned;
00054     int mId, mPageSize;
00055     LdapDN mBase;
00056     QString mFilter;
00057     QStringList mAttributes;
00058     LdapUrl::Scope mScope;
00059 
00060     QString mErrorString;
00061     int mError;
00062     int mCount, mMaxCount;
00063     bool mFinished;
00064 };
00065 
00066 void LdapSearch::Private::result()
00067 {
00068   if ( mAbandoned ) {
00069     mOp.abandon( mId );
00070     return;
00071   }
00072   int res = mOp.waitForResult( mId, LDAPSEARCH_BLOCKING_TIMEOUT );
00073 
00074   kDebug() << "LDAP result:" << res;
00075 
00076   if ( res != 0 &&
00077        ( res == -1 ||
00078          ( mConn->ldapErrorCode() != KLDAP_SUCCESS &&
00079            mConn->ldapErrorCode() != KLDAP_SASL_BIND_IN_PROGRESS ) ) ) {
00080     //error happened, but no timeout
00081     mError = mConn->ldapErrorCode();
00082     mErrorString = mConn->ldapErrorString();
00083     emit mParent->result( mParent );
00084     return;
00085   }
00086 
00087   //binding
00088   if ( res == LdapOperation::RES_BIND ) {
00089 
00090     QByteArray servercc;
00091     servercc = mOp.serverCred();
00092 
00093     kDebug() << "LdapSearch RES_BIND";
00094     if ( mConn->ldapErrorCode() == KLDAP_SUCCESS ) { //bind succeeded
00095       kDebug() << "bind succeeded";
00096       LdapControls savedctrls = mOp.serverControls();
00097       if ( mPageSize ) {
00098         LdapControls ctrls = savedctrls;
00099         LdapControl::insert( ctrls, LdapControl::createPageControl( mPageSize ) );
00100         mOp.setServerControls( ctrls );
00101       }
00102 
00103       mId = mOp.search( mBase, mScope, mFilter, mAttributes );
00104       mOp.setServerControls( savedctrls );
00105     } else { //next bind step
00106       kDebug() << "bind next step";
00107       mId = mOp.bind( servercc );
00108     }
00109     if ( mId < 0 ) {
00110       if ( mId == KLDAP_SASL_ERROR ) {
00111         mError = mId;
00112         mErrorString = mConn->saslErrorString();
00113       } else {
00114         mError = mConn->ldapErrorCode();
00115         mErrorString = mConn->ldapErrorString();
00116       }
00117       emit mParent->result( mParent );
00118       return;
00119     }
00120     QTimer::singleShot( 0, mParent, SLOT(result()) );
00121     return;
00122   }
00123 
00124   //End of entries
00125   if ( res == LdapOperation::RES_SEARCH_RESULT ) {
00126     if ( mPageSize ) {
00127       QByteArray cookie;
00128       int estsize = -1;
00129       const int numberOfControls( mOp.controls().count() );
00130       for ( int i = 0; i < numberOfControls; ++i ) {
00131         estsize = mOp.controls()[i].parsePageControl( cookie );
00132         if ( estsize != -1 ) {
00133           break;
00134         }
00135       }
00136       kDebug() << " estimated size:" << estsize;
00137       if ( estsize != -1 && !cookie.isEmpty() ) {
00138         LdapControls ctrls, savedctrls;
00139         savedctrls = mOp.serverControls();
00140         ctrls = savedctrls;
00141         LdapControl::insert( ctrls, LdapControl::createPageControl ( mPageSize, cookie ) );
00142         mOp.setServerControls( ctrls );
00143         mId = mOp.search( mBase, mScope, mFilter, mAttributes );
00144         mOp.setServerControls( savedctrls );
00145         if ( mId == -1 ) {
00146           mError = mConn->ldapErrorCode();
00147           mErrorString = mConn->ldapErrorString();
00148           emit mParent->result( mParent );
00149           return;
00150         }
00151         //continue with the next page
00152         QTimer::singleShot( 0, mParent, SLOT(result()) );
00153         return;
00154       }
00155     }
00156     mFinished = true;
00157     emit mParent->result( mParent );
00158     return;
00159   }
00160 
00161   //Found an entry
00162   if ( res == LdapOperation::RES_SEARCH_ENTRY ) {
00163     emit mParent->data( mParent, mOp.object() );
00164     mCount++;
00165   }
00166 
00167   //If not reached the requested entries, continue
00168   if ( mMaxCount <= 0 || mCount < mMaxCount ) {
00169     QTimer::singleShot( 0, mParent, SLOT(result()) );
00170   }
00171   //If reached the requested entries, indicate it
00172   if ( mMaxCount > 0 && mCount == mMaxCount ) {
00173     kDebug() << mCount << " entries reached";
00174     emit mParent->result( mParent );
00175   }
00176 }
00177 
00178 bool LdapSearch::Private::connect()
00179 {
00180   int ret = mConn->connect();
00181   if ( ret != KLDAP_SUCCESS ) {
00182     mError = ret;
00183     mErrorString = mConn->connectionError();
00184     closeConnection();
00185     return false;
00186   }
00187   return true;
00188 }
00189 
00190 void LdapSearch::Private::closeConnection()
00191 {
00192   if ( mOwnConnection && mConn ) {
00193     delete mConn;
00194     mConn = 0;
00195   }
00196 }
00197 
00198 //This starts the real job
00199 bool LdapSearch::Private::startSearch( const LdapDN &base, LdapUrl::Scope scope,
00200                                        const QString &filter,
00201                                        const QStringList &attributes, int pagesize, int count )
00202 {
00203   kDebug() << "search: base=" << base.toString() << "scope=" << (int)scope
00204            << "filter=" << filter << "attributes=" << attributes
00205            << "pagesize=" << pagesize;
00206   mAbandoned = false;
00207   mError = 0;
00208   mErrorString.clear();
00209   mOp.setConnection( *mConn );
00210   mPageSize = pagesize;
00211   mBase = base;
00212   mScope = scope;
00213   mFilter = filter;
00214   mAttributes = attributes;
00215   mMaxCount = count;
00216   mCount = 0;
00217   mFinished = false;
00218 
00219   LdapControls savedctrls = mOp.serverControls();
00220   if ( pagesize ) {
00221     LdapControls ctrls = savedctrls;
00222     mConn->setOption( 0x0008, NULL ); // Disable referals or paging won't work
00223     LdapControl::insert( ctrls, LdapControl::createPageControl( pagesize ) );
00224     mOp.setServerControls( ctrls );
00225   }
00226 
00227   mId = mOp.bind();
00228   if ( mId < 0 ) {
00229     if ( mId == KLDAP_SASL_ERROR ) {
00230       mError = mId;
00231       mErrorString = mConn->saslErrorString();
00232     } else {
00233       mError = mConn->ldapErrorCode();
00234       mErrorString = mConn->ldapErrorString();
00235       if ( mError == -1 && mErrorString.isEmpty() ) {
00236         mErrorString = i18n( "Cannot access to server. Please reconfigure it." );
00237       }
00238     }
00239     return false;
00240   }
00241   kDebug() << "startSearch msg id=" << mId;
00242 
00243    //maybe do this with threads?- need thread-safe client libs!!!
00244   QTimer::singleShot( 0, mParent, SLOT(result()) );
00245 
00246   return true;
00247 }
00248 
00250 
00251 LdapSearch::LdapSearch()
00252  : d( new Private( this ) )
00253 {
00254   d->mOwnConnection = true;
00255   d->mConn = 0;
00256 }
00257 
00258 LdapSearch::LdapSearch( LdapConnection &connection )
00259  : d( new Private( this ) )
00260 {
00261   d->mOwnConnection = false;
00262   d->mConn = &connection;
00263 }
00264 
00265 LdapSearch::~LdapSearch()
00266 {
00267   d->closeConnection();
00268   delete d;
00269 }
00270 
00271 void LdapSearch::setConnection( LdapConnection &connection )
00272 {
00273   d->closeConnection();
00274   d->mOwnConnection = false;
00275   d->mConn = &connection;
00276 }
00277 
00278 void LdapSearch::setClientControls( const LdapControls &ctrls )
00279 {
00280   d->mOp.setClientControls( ctrls );
00281 }
00282 
00283 void LdapSearch::setServerControls( const LdapControls &ctrls )
00284 {
00285   d->mOp.setServerControls( ctrls );
00286 }
00287 
00288 bool LdapSearch::search( const LdapServer &server,
00289                          const QStringList &attributes, int count )
00290 {
00291   if ( d->mOwnConnection ) {
00292     d->closeConnection();
00293     d->mConn = new LdapConnection( server );
00294     if ( !d->connect() ) {
00295       return false;
00296     }
00297   }
00298   return d->startSearch( server.baseDn(), server.scope(), server.filter(),
00299                          attributes, server.pageSize(), count );
00300 }
00301 
00302 bool LdapSearch::search( const LdapUrl &url, int count )
00303 {
00304   if ( d->mOwnConnection ) {
00305     d->closeConnection();
00306     d->mConn = new LdapConnection( url );
00307     if ( !d->connect() ) {
00308       return false;
00309     }
00310   }
00311   bool critical;
00312   int pagesize = url.extension( QLatin1String( "x-pagesize" ), critical ).toInt();
00313   return d->startSearch( url.dn(), url.scope(), url.filter(),
00314                          url.attributes(), pagesize, count );
00315 }
00316 
00317 bool LdapSearch::search( const LdapDN &base, LdapUrl::Scope scope,
00318                          const QString &filter, const QStringList &attributes,
00319                          int pagesize, int count )
00320 {
00321   Q_ASSERT( !d->mOwnConnection );
00322   return d->startSearch( base, scope, filter, attributes, pagesize, count );
00323 }
00324 
00325 void LdapSearch::continueSearch()
00326 {
00327   Q_ASSERT( !d->mFinished );
00328   d->mCount = 0;
00329   QTimer::singleShot( 0, this, SLOT(result()) );
00330 }
00331 
00332 bool LdapSearch::isFinished()
00333 {
00334   return d->mFinished;
00335 }
00336 
00337 void LdapSearch::abandon()
00338 {
00339   d->mAbandoned = true;
00340 }
00341 
00342 int LdapSearch::error() const
00343 {
00344   return d->mError;
00345 }
00346 
00347 QString LdapSearch::errorString() const
00348 {
00349   return d->mErrorString;
00350 }
00351 
00352 #include "ldapsearch.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu May 10 2012 22:18:18 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KLDAP Library

Skip menu "KLDAP Library"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Related Pages

kdepimlibs-4.8.3 API Reference

Skip menu "kdepimlibs-4.8.3 API Reference"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal