kabc Library API Documentation

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"
KDE Logo
This file is part of the documentation for kabc Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 14 00:35:17 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003