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

KLDAP Library

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

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • 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.5
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