# kabc Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# ldapclient.cpp

    00001 /* kldapclient.cpp - LDAP access
    00002  *      Copyright (C) 2002 Klarälvdalens Datakonsult AB
    00003  *
    00004  *      Author: Steffen Hansen <hansen@kde.org>
    00005  *
    00006  *      Ported to KABC by Daniel Molkentin <molkentin@kde.org>
    00007  *
    00008  * This file is free software; you can redistribute it and/or modify
    00009  * it under the terms of the GNU General Public License as published by
    00010  * the Free Software Foundation; either version 2 of the License, or
    00011  * (at your option) any later version.
    00012  *
    00013  * This file is distributed in the hope that it will be useful,
    00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00016  * GNU General Public License for more details.
    00017  *
    00018  * You should have received a copy of the GNU General Public License
    00019  * along with this program; if not, write to the Free Software
    00020  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
    00021  */
    00022
    00023
    00024
    00025 #include <qfile.h>
    00026 #include <qimage.h>
    00027 #include <qlabel.h>
    00028 #include <qpixmap.h>
    00029 #include <qtextstream.h>
    00030 #include <qurl.h>
    00031
    00032 #include <kapplication.h>
    00033 #include <kconfig.h>
    00034 #include <kdebug.h>
    00035 #include <kmdcodec.h>
    00036 #include <kprotocolinfo.h>
    00037
    00038 #include "ldapclient.h"
    00039 #include "ldif.h"
    00040 #include "ldapurl.h"
    00041
    00042 using namespace KABC;
    00043
    00044 class LdapClient::LdapClientPrivate{
    00045 public:
    00046   QString bindDN;
    00047   QString pwdBindDN;
    00048   LDIF ldif;
    00049 };
    00050
    00051 QString LdapObject::toString() const
    00052 {
    00053   QString result = QString::fromLatin1( "\ndn: %1\n" ).arg( dn );
    00054   for ( LdapAttrMap::ConstIterator it = attrs.begin(); it != attrs.end(); ++it ) {
    00055     QString attr = it.key();
    00056     for ( LdapAttrValue::ConstIterator it2 = (*it).begin(); it2 != (*it).end(); ++it2 ) {
    00057       result += QString::fromUtf8( LDIF::assembleLine( attr, *it2, 76 ) ) + "\n";
    00058     }
    00059   }
    00060
    00061   return result;
    00062 }
    00063
    00064 void LdapObject::clear()
    00065 {
    00066   dn = QString::null;
    00067   attrs.clear();
    00068 }
    00069
    00070 void LdapObject::assign( const LdapObject& that )
    00071 {
    00072   if ( &that != this ) {
    00073     dn = that.dn;
    00074     attrs = that.attrs;
    00075     client = that.client;
    00076   }
    00077 }
    00078
    00079 LdapClient::LdapClient( QObject* parent, const char* name )
    00080   : QObject( parent, name ), mJob( 0 ), mActive( false )
    00081 {
    00082   d = new LdapClientPrivate;
    00083 }
    00084
    00085 LdapClient::~LdapClient()
    00086 {
    00087   cancelQuery();
    00088   delete d; d = 0;
    00089 }
    00090
    00091 void LdapClient::setHost( const QString& host )
    00092 {
    00093   mHost = host;
    00094 }
    00095
    00096 void LdapClient::setPort( const QString& port )
    00097 {
    00098   mPort = port;
    00099 }
    00100
    00101 void LdapClient::setBase( const QString& base )
    00102 {
    00103   mBase = base;
    00104 }
    00105
    00106 void LdapClient::setBindDN( const QString& bindDN )
    00107 {
    00108   d->bindDN = bindDN;
    00109 }
    00110
    00111 void LdapClient::setPwdBindDN( const QString& pwdBindDN )
    00112 {
    00113   d->pwdBindDN = pwdBindDN;
    00114 }
    00115
    00116 void LdapClient::setAttrs( const QStringList& attrs )
    00117 {
    00118   mAttrs = attrs;
    00119 }
    00120
    00121 void LdapClient::startQuery( const QString& filter )
    00122 {
    00123   cancelQuery();
    00124   LDAPUrl url;
    00125
    00126   url.setProtocol( "ldap" );
    00127   url.setUser( d->bindDN );
    00128   url.setPass( d->pwdBindDN );
    00129   url.setHost( mHost );
    00130   url.setPort( mPort.toUInt() );
    00131   url.setDn( mBase );
    00132   url.setAttributes( mAttrs );
    00133   url.setScope( mScope == "one" ? LDAPUrl::One : LDAPUrl::Sub );
    00134   url.setFilter( "("+filter+")" );
    00135
    00136   kdDebug(5700) << "Doing query: " << url.prettyURL() << endl;
    00137
    00138   startParseLDIF();
    00139   mActive = true;
    00140   mJob = KIO::get( url, false, false );
    00141   connect( mJob, SIGNAL( data( KIO::Job*, const QByteArray& ) ),
    00142            this, SLOT( slotData( KIO::Job*, const QByteArray& ) ) );
    00143   connect( mJob, SIGNAL( infoMessage( KIO::Job*, const QString& ) ),
    00144            this, SLOT( slotInfoMessage( KIO::Job*, const QString& ) ) );
    00145   connect( mJob, SIGNAL( result( KIO::Job* ) ),
    00146            this, SLOT( slotDone() ) );
    00147 }
    00148
    00149 void LdapClient::cancelQuery()
    00150 {
    00151   if ( mJob ) {
    00152     mJob->kill();
    00153     mJob = 0;
    00154   }
    00155
    00156   mActive = false;
    00157 }
    00158
    00159 void LdapClient::slotData( KIO::Job*, const QByteArray& data )
    00160 {
    00161 #ifndef NDEBUG // don't create the QString
    00162 //  QString str( data );
    00163 //  kdDebug(5700) << "LdapClient: Got \"" << str << "\"\n";
    00164 #endif
    00165   parseLDIF( data );
    00166 }
    00167
    00168 void LdapClient::slotInfoMessage( KIO::Job*, const QString & )
    00169 {
    00170   //qDebug("Job said \"%s\"", info.latin1());
    00171 }
    00172
    00173 void LdapClient::slotDone()
    00174 {
    00175   endParseLDIF();
    00176   mActive = false;
    00177 #if 0
    00178   for ( QValueList<LdapObject>::Iterator it = mObjects.begin(); it != mObjects.end(); ++it ) {
    00179     qDebug( (*it).toString().latin1() );
    00180   }
    00181 #endif
    00182   int err = mJob->error();
    00183   if ( err && err != KIO::ERR_USER_CANCELED ) {
    00184     emit error( KIO::buildErrorString( err, QString("%1:%2").arg( mHost ).arg( mPort ) ) );
    00185   }
    00186   emit done();
    00187 }
    00188
    00189 void LdapClient::startParseLDIF()
    00190 {
    00191   mCurrentObject.clear();
    00192   mLastAttrName  = 0;
    00193   mLastAttrValue = 0;
    00194   mIsBase64 = false;
    00195   d->ldif.startParsing();
    00196 }
    00197
    00198 void LdapClient::endParseLDIF()
    00199 {
    00200 }
    00201
    00202 void LdapClient::parseLDIF( const QByteArray& data )
    00203 {
    00204   if ( data.size() ) {
    00205     d->ldif.setLDIF( data );
    00206   } else {
    00207     d->ldif.endLDIF();
    00208   }
    00209
    00210   LDIF::ParseVal ret;
    00211   QString name;
    00212   QByteArray value;
    00213   do {
    00214     ret = d->ldif.nextItem();
    00215     switch ( ret ) {
    00216       case LDIF::Item:
    00217         name = d->ldif.attr();
    00218         value = d->ldif.val();
    00219         mCurrentObject.attrs[ name ].append( value );
    00220         break;
    00221      case LDIF::EndEntry:
    00222         mCurrentObject.dn = d->ldif.dn();
    00223         mCurrentObject.client = this;
    00224         emit result( mCurrentObject );
    00225         mCurrentObject.clear();
    00226         break;
    00227       default:
    00228         break;
    00229     }
    00230   } while ( ret != LDIF::MoreData );
    00231 }
    00232
    00233 QString LdapClient::bindDN() const
    00234 {
    00235   return d->bindDN;
    00236 }
    00237
    00238 QString LdapClient::pwdBindDN() const
    00239 {
    00240   return d->pwdBindDN;
    00241 }
    00242
    00243 LdapSearch::LdapSearch()
    00244     : mActiveClients( 0 ), mNoLDAPLookup( false )
    00245 {
    00246   if ( !KProtocolInfo::isKnownProtocol( KURL("ldap://localhost") ) ) {
    00247     mNoLDAPLookup = true;
    00248     return;
    00249   }
    00250
    00251   // stolen from KAddressBook
    00252   KConfig config( "kabldaprc", true );
    00253   config.setGroup( "LDAP" );
    00254   int numHosts = config.readUnsignedNumEntry( "NumSelectedHosts");
    00255   if ( !numHosts ) {
    00256     mNoLDAPLookup = true;
    00257     return;
    00258   } else {
    00259     for ( int j = 0; j < numHosts; j++ ) {
    00260       LdapClient* ldapClient = new LdapClient( this );
    00261
    00262       QString host =  config.readEntry( QString( "SelectedHost%1" ).arg( j ), "" ).stripWhiteSpace();
    00263       if ( !host.isEmpty() )
    00264         ldapClient->setHost( host );
    00265
    00266       QString port = QString::number( config.readUnsignedNumEntry( QString( "SelectedPort%1" ).arg( j ) ) );
    00267       if ( !port.isEmpty() )
    00268         ldapClient->setPort( port );
    00269
    00270       QString base = config.readEntry( QString( "SelectedBase%1" ).arg( j ), "" ).stripWhiteSpace();
    00271       if ( !base.isEmpty() )
    00272         ldapClient->setBase( base );
    00273
    00274       QString bindDN = config.readEntry( QString( "SelectedBind%1" ).arg( j ) ).stripWhiteSpace();
    00275       if ( !bindDN.isEmpty() )
    00276         ldapClient->setBindDN( bindDN );
    00277
    00278       QString pwdBindDN = config.readEntry( QString( "SelectedPwdBind%1" ).arg( j ) );
    00279       if ( !pwdBindDN.isEmpty() )
    00280         ldapClient->setPwdBindDN( pwdBindDN );
    00281
    00282       QStringList attrs;
    00283       attrs << "cn" << "mail" << "givenname" << "sn";
    00284       ldapClient->setAttrs( attrs );
    00285
    00286       connect( ldapClient, SIGNAL( result( const KABC::LdapObject& ) ),
    00287                this, SLOT( slotLDAPResult( const KABC::LdapObject& ) ) );
    00288       connect( ldapClient, SIGNAL( done() ),
    00289                this, SLOT( slotLDAPDone() ) );
    00290       connect( ldapClient, SIGNAL( error( const QString& ) ),
    00291                this, SLOT( slotLDAPError( const QString& ) ) );
    00292
    00293       mClients.append( ldapClient );
    00294     }
    00295   }
    00296
    00297   connect( &mDataTimer, SIGNAL( timeout() ), SLOT( slotDataTimer() ) );
    00298 }
    00299
    00300 void LdapSearch::startSearch( const QString& txt )
    00301 {
    00302   if ( mNoLDAPLookup )
    00303     return;
    00304
    00305   cancelSearch();
    00306
    00307   int pos = txt.find( '\"' );
    00308   if( pos >= 0 )
    00309   {
    00310     ++pos;
    00311     int pos2 = txt.find( '\"', pos );
    00312     if( pos2 >= 0 )
    00313         mSearchText = txt.mid( pos , pos2 - pos );
    00314     else
    00315         mSearchText = txt.mid( pos );
    00316   } else
    00317     mSearchText = txt;
    00318
    00319   QString filter = QString( "|(cn=%1*)(mail=%2*)(givenName=%3*)(sn=%4*)" )
    00320       .arg( mSearchText ).arg( mSearchText ).arg( mSearchText ).arg( mSearchText );
    00321
    00322   QValueList< LdapClient* >::Iterator it;
    00323   for ( it = mClients.begin(); it != mClients.end(); ++it ) {
    00324     (*it)->startQuery( filter );
    00325     ++mActiveClients;
    00326   }
    00327 }
    00328
    00329 void LdapSearch::cancelSearch()
    00330 {
    00331   QValueList< LdapClient* >::Iterator it;
    00332   for ( it = mClients.begin(); it != mClients.end(); ++it )
    00333     (*it)->cancelQuery();
    00334
    00335   mActiveClients = 0;
    00336   mResults.clear();
    00337 }
    00338
    00339 void LdapSearch::slotLDAPResult( const KABC::LdapObject& obj )
    00340 {
    00341   mResults.append( obj );
    00342   if ( !mDataTimer.isActive() )
    00343     mDataTimer.start( 500, true );
    00344 }
    00345
    00346 void LdapSearch::slotLDAPError( const QString& )
    00347 {
    00348   slotLDAPDone();
    00349 }
    00350
    00351 void LdapSearch::slotLDAPDone()
    00352 {
    00353   if ( --mActiveClients > 0 )
    00354     return;
    00355
    00356   finish();
    00357 }
    00358
    00359 void LdapSearch::slotDataTimer()
    00360 {
    00361   QStringList lst;
    00362   LdapResultList reslist;
    00363   makeSearchData( lst, reslist );
    00364   if ( !lst.isEmpty() )
    00365     emit searchData( lst );
    00366   if ( !reslist.isEmpty() )
    00367     emit searchData( reslist );
    00368 }
    00369
    00370 void LdapSearch::finish()
    00371 {
    00372   mDataTimer.stop();
    00373
    00374   slotDataTimer(); // emit final bunch of data
    00375   emit searchDone();
    00376 }
    00377
    00378 void LdapSearch::makeSearchData( QStringList& ret, LdapResultList& resList )
    00379 {
    00380   QString search_text_upper = mSearchText.upper();
    00381
    00382   QValueList< KABC::LdapObject >::ConstIterator it1;
    00383   for ( it1 = mResults.begin(); it1 != mResults.end(); ++it1 ) {
    00384     QString name, mail, givenname, sn;
    00385
    00386     LdapAttrMap::ConstIterator it2;
    00387     for ( it2 = (*it1).attrs.begin(); it2 != (*it1).attrs.end(); ++it2 ) {
    00388       QString tmp = QString::fromUtf8( (*it2).first(), (*it2).first().size() );
    00389       if ( it2.key() == "cn" )
    00390         name = tmp; // TODO loop?
    00391       else if( it2.key() == "mail" )
    00392         mail = tmp;
    00393       else if( it2.key() == "givenName" )
    00394         givenname = tmp;
    00395       else if( it2.key() == "sn" )
    00396         sn = tmp;
    00397     }
    00398
    00399     if( mail.isEmpty())
    00400       continue; // nothing, bad entry
    00401     else if ( name.isEmpty() )
    00402       ret.append( mail );
    00403     else {
    00404       kdDebug(5700) << "<" << name << "><" << mail << ">" << endl;
    00405       ret.append( QString( "%1 <%2>" ).arg( name ).arg( mail ) );
    00406     }
    00407
    00408     LdapResult sr;
    00409     sr.clientNumber = mClients.findIndex( (*it1).client );
    00410     sr.name = name;
    00411     sr.email = mail;
    00412     resList.append( sr );
    00413   }
    00414
    00415   mResults.clear();
    00416 }
    00417
    00418 bool LdapSearch::isAvailable() const
    00419 {
    00420   return !mNoLDAPLookup;
    00421 }
    00422
    00423
    00424
    00425 #include "ldapclient.moc"

This file is part of the documentation for kabc Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:31:30 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003