• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • 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 
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         ctrls.append( 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       for ( int i = 0; i < mOp.controls().count(); ++i ) {
00130         estsize = mOp.controls()[i].parsePageControl( cookie );
00131         if ( estsize != -1 ) {
00132           break;
00133         }
00134       }
00135       kDebug() << " estimated size:" << estsize;
00136       if ( estsize != -1 && !cookie.isEmpty() ) {
00137         LdapControls ctrls, savedctrls;
00138         savedctrls = mOp.serverControls();
00139         ctrls = savedctrls;
00140         ctrls.append( LdapControl::createPageControl( mPageSize, cookie ) );
00141         mOp.setServerControls( ctrls );
00142         mId = mOp.search( mBase, mScope, mFilter, mAttributes );
00143         mOp.setServerControls( savedctrls );
00144         if ( mId == -1 ) {
00145           mError = mConn->ldapErrorCode();
00146           mErrorString = mConn->ldapErrorString();
00147           emit mParent->result( mParent );
00148           return;
00149         }
00150         //continue with the next page
00151         QTimer::singleShot( 0, mParent, SLOT(result()) );
00152         return;
00153       }
00154     }
00155     mFinished = true;
00156     emit mParent->result( mParent );
00157     return;
00158   }
00159 
00160   //Found an entry
00161   if ( res == LdapOperation::RES_SEARCH_ENTRY ) {
00162     emit mParent->data( mParent, mOp.object() );
00163     mCount++;
00164   }
00165 
00166   //If not reached the requested entries, continue
00167   if ( mMaxCount <= 0 || mCount < mMaxCount ) {
00168     QTimer::singleShot( 0, mParent, SLOT(result()) );
00169   }
00170   //If reached the requested entries, indicate it
00171   if ( mMaxCount > 0 && mCount == mMaxCount ) {
00172     kDebug() << mCount << " entries reached";
00173     emit mParent->result( mParent );
00174   }
00175 }
00176 
00177 bool LdapSearch::Private::connect()
00178 {
00179   int ret = mConn->connect();
00180   if ( ret != KLDAP_SUCCESS ) {
00181     mError = ret;
00182     mErrorString = mConn->connectionError();
00183     closeConnection();
00184     return false;
00185   }
00186   return true;
00187 }
00188 
00189 void LdapSearch::Private::closeConnection()
00190 {
00191   if ( mOwnConnection && mConn ) {
00192     delete mConn;
00193     mConn = 0;
00194   }
00195 }
00196 
00197 //This starts the real job
00198 bool LdapSearch::Private::startSearch( const LdapDN &base, LdapUrl::Scope scope,
00199                                        const QString &filter,
00200                                        const QStringList &attributes, int pagesize, int count )
00201 {
00202   kDebug() << "search: base=" << base.toString() << "scope=" << scope
00203            << "filter=" << filter << "attributes=" << attributes
00204            << "pagesize=" << pagesize;
00205   mAbandoned = false;
00206   mError = 0;
00207   mErrorString = QString();
00208   mOp.setConnection( *mConn );
00209   mPageSize = pagesize;
00210   mBase = base;
00211   mScope = scope;
00212   mFilter = filter;
00213   mAttributes = attributes;
00214   mMaxCount = count;
00215   mCount = 0;
00216   mFinished = false;
00217 
00218   LdapControls savedctrls = mOp.serverControls();
00219   if ( pagesize ) {
00220     LdapControls ctrls = savedctrls;
00221     ctrls.append( LdapControl::createPageControl( pagesize ) );
00222     mOp.setServerControls( ctrls );
00223   }
00224 
00225   mId = mOp.bind();
00226   if ( mId < 0 ) {
00227     if ( mId == KLDAP_SASL_ERROR ) {
00228       mError = mId;
00229       mErrorString = mConn->saslErrorString();
00230     } else {
00231       mError = mConn->ldapErrorCode();
00232       mErrorString = mConn->ldapErrorString();
00233     }
00234     return false;
00235   }
00236   kDebug() << "startSearch msg id=" << mId;
00237 
00238    //maybe do this with threads?- need thread-safe client libs!!!
00239   QTimer::singleShot( 0, mParent, SLOT(result()) );
00240 
00241   return true;
00242 }
00243 
00245 
00246 LdapSearch::LdapSearch()
00247  : d( new Private( this ) )
00248 {
00249   d->mOwnConnection = true;
00250   d->mConn = 0;
00251 }
00252 
00253 LdapSearch::LdapSearch( LdapConnection &connection )
00254  : d( new Private( this ) )
00255 {
00256   d->mOwnConnection = false;
00257   d->mConn = &connection;
00258 }
00259 
00260 LdapSearch::~LdapSearch()
00261 {
00262   d->closeConnection();
00263   delete d;
00264 }
00265 
00266 void LdapSearch::setConnection( LdapConnection &connection )
00267 {
00268   d->closeConnection();
00269   d->mOwnConnection = false;
00270   d->mConn = &connection;
00271 }
00272 
00273 void LdapSearch::setClientControls( const LdapControls &ctrls )
00274 {
00275   d->mOp.setClientControls( ctrls );
00276 }
00277 
00278 void LdapSearch::setServerControls( const LdapControls &ctrls )
00279 {
00280   d->mOp.setServerControls( ctrls );
00281 }
00282 
00283 bool LdapSearch::search( const LdapServer &server,
00284                          const QStringList &attributes, int count )
00285 {
00286   if ( d->mOwnConnection ) {
00287     d->closeConnection();
00288     d->mConn = new LdapConnection( server );
00289     if ( !d->connect() ) {
00290       return false;
00291     }
00292   }
00293   return d->startSearch( server.baseDn(), server.scope(), server.filter(),
00294                          attributes, server.pageSize(), count );
00295 }
00296 
00297 bool LdapSearch::search( const LdapUrl &url, int count )
00298 {
00299   if ( d->mOwnConnection ) {
00300     d->closeConnection();
00301     d->mConn = new LdapConnection( url );
00302     if ( !d->connect() ) {
00303       return false;
00304     }
00305   }
00306   bool critical;
00307   int pagesize = url.extension( QLatin1String( "x-pagesize" ), critical ).toInt();
00308   return d->startSearch( url.dn(), url.scope(), url.filter(),
00309                          url.attributes(), pagesize, count );
00310 }
00311 
00312 bool LdapSearch::search( const LdapDN &base, LdapUrl::Scope scope,
00313                          const QString &filter, const QStringList &attributes,
00314                          int pagesize, int count )
00315 {
00316   Q_ASSERT( !d->mOwnConnection );
00317   return d->startSearch( base, scope, filter, attributes, pagesize, count );
00318 }
00319 
00320 void LdapSearch::continueSearch()
00321 {
00322   Q_ASSERT( !d->mFinished );
00323   d->mCount = 0;
00324   QTimer::singleShot( 0, this, SLOT(result()) );
00325 }
00326 
00327 bool LdapSearch::isFinished()
00328 {
00329   return d->mFinished;
00330 }
00331 
00332 void LdapSearch::abandon()
00333 {
00334   d->mAbandoned = true;
00335 }
00336 
00337 int LdapSearch::error() const
00338 {
00339   return d->mError;
00340 }
00341 
00342 QString LdapSearch::errorString() const
00343 {
00344   return d->mErrorString;
00345 }
00346 
00347 #include "ldapsearch.moc"

KLDAP Library

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

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  • kabc
  • kblog
  • kcal
  • kimap
  • kioslave
  •   imap4
  •   mbox
  • kldap
  • kmime
  • kpimidentities
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal