• Skip to content
  • Skip to link menu
KDE 4.4 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 #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       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         LdapControl::insert( ctrls, 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=" << (int)scope
00203            << "filter=" << filter << "attributes=" << attributes
00204            << "pagesize=" << pagesize;
00205   mAbandoned = false;
00206   mError = 0;
00207   mErrorString.clear();
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     mConn->setOption( 0x0008, NULL ); // Disable referals or paging won't work
00222     LdapControl::insert( ctrls, LdapControl::createPageControl( pagesize ) );
00223     mOp.setServerControls( ctrls );
00224   }
00225 
00226   mId = mOp.bind();
00227   if ( mId < 0 ) {
00228     if ( mId == KLDAP_SASL_ERROR ) {
00229       mError = mId;
00230       mErrorString = mConn->saslErrorString();
00231     } else {
00232       mError = mConn->ldapErrorCode();
00233       mErrorString = mConn->ldapErrorString();
00234       if ( mError == -1 && mErrorString.isEmpty() ) {
00235         mErrorString = i18n( "Cannot access to server. Please reconfigure it." );
00236       }
00237     }
00238     return false;
00239   }
00240   kDebug() << "startSearch msg id=" << mId;
00241 
00242    //maybe do this with threads?- need thread-safe client libs!!!
00243   QTimer::singleShot( 0, mParent, SLOT(result()) );
00244 
00245   return true;
00246 }
00247 
00249 
00250 LdapSearch::LdapSearch()
00251  : d( new Private( this ) )
00252 {
00253   d->mOwnConnection = true;
00254   d->mConn = 0;
00255 }
00256 
00257 LdapSearch::LdapSearch( LdapConnection &connection )
00258  : d( new Private( this ) )
00259 {
00260   d->mOwnConnection = false;
00261   d->mConn = &connection;
00262 }
00263 
00264 LdapSearch::~LdapSearch()
00265 {
00266   d->closeConnection();
00267   delete d;
00268 }
00269 
00270 void LdapSearch::setConnection( LdapConnection &connection )
00271 {
00272   d->closeConnection();
00273   d->mOwnConnection = false;
00274   d->mConn = &connection;
00275 }
00276 
00277 void LdapSearch::setClientControls( const LdapControls &ctrls )
00278 {
00279   d->mOp.setClientControls( ctrls );
00280 }
00281 
00282 void LdapSearch::setServerControls( const LdapControls &ctrls )
00283 {
00284   d->mOp.setServerControls( ctrls );
00285 }
00286 
00287 bool LdapSearch::search( const LdapServer &server,
00288                          const QStringList &attributes, int count )
00289 {
00290   if ( d->mOwnConnection ) {
00291     d->closeConnection();
00292     d->mConn = new LdapConnection( server );
00293     if ( !d->connect() ) {
00294       return false;
00295     }
00296   }
00297   return d->startSearch( server.baseDn(), server.scope(), server.filter(),
00298                          attributes, server.pageSize(), count );
00299 }
00300 
00301 bool LdapSearch::search( const LdapUrl &url, int count )
00302 {
00303   if ( d->mOwnConnection ) {
00304     d->closeConnection();
00305     d->mConn = new LdapConnection( url );
00306     if ( !d->connect() ) {
00307       return false;
00308     }
00309   }
00310   bool critical;
00311   int pagesize = url.extension( QLatin1String( "x-pagesize" ), critical ).toInt();
00312   return d->startSearch( url.dn(), url.scope(), url.filter(),
00313                          url.attributes(), pagesize, count );
00314 }
00315 
00316 bool LdapSearch::search( const LdapDN &base, LdapUrl::Scope scope,
00317                          const QString &filter, const QStringList &attributes,
00318                          int pagesize, int count )
00319 {
00320   Q_ASSERT( !d->mOwnConnection );
00321   return d->startSearch( base, scope, filter, attributes, pagesize, count );
00322 }
00323 
00324 void LdapSearch::continueSearch()
00325 {
00326   Q_ASSERT( !d->mFinished );
00327   d->mCount = 0;
00328   QTimer::singleShot( 0, this, SLOT(result()) );
00329 }
00330 
00331 bool LdapSearch::isFinished()
00332 {
00333   return d->mFinished;
00334 }
00335 
00336 void LdapSearch::abandon()
00337 {
00338   d->mAbandoned = true;
00339 }
00340 
00341 int LdapSearch::error() const
00342 {
00343   return d->mError;
00344 }
00345 
00346 QString LdapSearch::errorString() const
00347 {
00348   return d->mErrorString;
00349 }
00350 
00351 #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
  •   contact
  •   kmime
  • kabc
  • kblog
  • kcal
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.6.1
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