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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 00021 */ 00022 00023 00024 00025 #include <tqfile.h> 00026 #include <tqimage.h> 00027 #include <tqlabel.h> 00028 #include <tqpixmap.h> 00029 #include <tqtextstream.h> 00030 #include <tqurl.h> 00031 00032 #include <tdeabc/ldapurl.h> 00033 #include <tdeabc/ldif.h> 00034 #include <tdeapplication.h> 00035 #include <tdeconfig.h> 00036 #include <kdebug.h> 00037 #include <kdirwatch.h> 00038 #include <kmdcodec.h> 00039 #include <kprotocolinfo.h> 00040 #include <kstandarddirs.h> 00041 #include <kstaticdeleter.h> 00042 00043 #include "ldapclient.h" 00044 00045 using namespace KPIM; 00046 00047 TDEConfig *KPIM::LdapSearch::s_config = 0L; 00048 static KStaticDeleter<TDEConfig> configDeleter; 00049 00050 TQString LdapObject::toString() const 00051 { 00052 TQString result = TQString::fromLatin1( "\ndn: %1\n" ).arg( dn ); 00053 for ( LdapAttrMap::ConstIterator it = attrs.begin(); it != attrs.end(); ++it ) { 00054 TQString attr = it.key(); 00055 for ( LdapAttrValue::ConstIterator it2 = (*it).begin(); it2 != (*it).end(); ++it2 ) { 00056 result += TQString::fromUtf8( TDEABC::LDIF::assembleLine( attr, *it2, 76 ) ) + "\n"; 00057 } 00058 } 00059 00060 return result; 00061 } 00062 00063 void LdapObject::clear() 00064 { 00065 dn = TQString(); 00066 objectClass = TQString(); 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( int clientNumber, TQObject* parent, const char* name ) 00080 : TQObject( parent, name ), mJob( 0 ), mActive( false ), mReportObjectClass( false ) 00081 { 00082 // d = new LdapClientPrivate; 00083 mClientNumber = clientNumber; 00084 mCompletionWeight = 50 - mClientNumber; 00085 } 00086 00087 LdapClient::~LdapClient() 00088 { 00089 cancelQuery(); 00090 // delete d; d = 0; 00091 } 00092 00093 void LdapClient::setAttrs( const TQStringList& attrs ) 00094 { 00095 mAttrs = attrs; 00096 for ( TQStringList::Iterator it = mAttrs.begin(); it != mAttrs.end(); ++it ) 00097 if( (*it).lower() == "objectclass" ){ 00098 mReportObjectClass = true; 00099 return; 00100 } 00101 mAttrs << "objectClass"; // via objectClass we detect distribution lists 00102 mReportObjectClass = false; 00103 } 00104 00105 void LdapClient::startQuery( const TQString& filter ) 00106 { 00107 cancelQuery(); 00108 TDEABC::LDAPUrl url; 00109 00110 url.setProtocol( ( mServer.security() == LdapServer::SSL ) ? "ldaps" : "ldap" ); 00111 if ( mServer.auth() != LdapServer::Anonymous ) { 00112 url.setUser( mServer.user() ); 00113 url.setPass( mServer.pwdBindDN() ); 00114 } 00115 url.setHost( mServer.host() ); 00116 url.setPort( mServer.port() ); 00117 url.setExtension( "x-ver", TQString::number( mServer.version() ) ); 00118 url.setDn( mServer.baseDN() ); 00119 url.setDn( mServer.baseDN() ); 00120 if ( mServer.security() == LdapServer::TLS ) url.setExtension( "x-tls","" ); 00121 if ( mServer.auth() == LdapServer::SASL ) { 00122 url.setExtension( "x-sasl","" ); 00123 if ( !mServer.bindDN().isEmpty() ) url.setExtension( "x-bindname", mServer.bindDN() ); 00124 if ( !mServer.mech().isEmpty() ) url.setExtension( "x-mech", mServer.mech() ); 00125 } 00126 if ( mServer.timeLimit() != 0 ) url.setExtension( "x-timelimit", 00127 TQString::number( mServer.timeLimit() ) ); 00128 if ( mServer.sizeLimit() != 0 ) url.setExtension( "x-sizelimit", 00129 TQString::number( mServer.sizeLimit() ) ); 00130 00131 url.setAttributes( mAttrs ); 00132 url.setScope( mScope == "one" ? TDEABC::LDAPUrl::One : TDEABC::LDAPUrl::Sub ); 00133 url.setFilter( "("+filter+")" ); 00134 00135 kdDebug(5300) << "LdapClient: Doing query: " << url.prettyURL() << endl; 00136 00137 startParseLDIF(); 00138 mActive = true; 00139 mJob = TDEIO::get( url, false, false ); 00140 connect( mJob, TQT_SIGNAL( data( TDEIO::Job*, const TQByteArray& ) ), 00141 this, TQT_SLOT( slotData( TDEIO::Job*, const TQByteArray& ) ) ); 00142 connect( mJob, TQT_SIGNAL( infoMessage( TDEIO::Job*, const TQString& ) ), 00143 this, TQT_SLOT( slotInfoMessage( TDEIO::Job*, const TQString& ) ) ); 00144 connect( mJob, TQT_SIGNAL( result( TDEIO::Job* ) ), 00145 this, TQT_SLOT( slotDone() ) ); 00146 } 00147 00148 void LdapClient::cancelQuery() 00149 { 00150 if ( mJob ) { 00151 mJob->kill(); 00152 mJob = 0; 00153 } 00154 00155 mActive = false; 00156 } 00157 00158 void LdapClient::slotData( TDEIO::Job*, const TQByteArray& data ) 00159 { 00160 parseLDIF( data ); 00161 } 00162 00163 void LdapClient::slotInfoMessage( TDEIO::Job*, const TQString & ) 00164 { 00165 //tqDebug("Job said \"%s\"", info.latin1()); 00166 } 00167 00168 void LdapClient::slotDone() 00169 { 00170 endParseLDIF(); 00171 mActive = false; 00172 #if 0 00173 for ( TQValueList<LdapObject>::Iterator it = mObjects.begin(); it != mObjects.end(); ++it ) { 00174 tqDebug( (*it).toString().latin1() ); 00175 } 00176 #endif 00177 int err = mJob->error(); 00178 if ( err && err != TDEIO::ERR_USER_CANCELED ) { 00179 emit error( mJob->errorString() ); 00180 } 00181 emit done(); 00182 } 00183 00184 void LdapClient::startParseLDIF() 00185 { 00186 mCurrentObject.clear(); 00187 mLdif.startParsing(); 00188 } 00189 00190 void LdapClient::endParseLDIF() 00191 { 00192 } 00193 00194 void LdapClient::finishCurrentObject() 00195 { 00196 mCurrentObject.dn = mLdif.dn(); 00197 const TQString sClass( mCurrentObject.objectClass.lower() ); 00198 if( sClass == "groupofnames" || sClass == "kolabgroupofnames" ){ 00199 LdapAttrMap::ConstIterator it = mCurrentObject.attrs.find("mail"); 00200 if( it == mCurrentObject.attrs.end() ){ 00201 // No explicit mail address found so far? 00202 // Fine, then we use the address stored in the DN. 00203 TQString sMail; 00204 TQStringList lMail = TQStringList::split(",dc=", mCurrentObject.dn); 00205 const int n = lMail.count(); 00206 if( n ){ 00207 if( lMail.first().lower().startsWith("cn=") ){ 00208 sMail = lMail.first().simplifyWhiteSpace().mid(3); 00209 if( 1 < n ) 00210 sMail.append('@'); 00211 for( int i=1; i<n; ++i){ 00212 sMail.append( lMail[i] ); 00213 if( i < n-1 ) 00214 sMail.append('.'); 00215 } 00216 mCurrentObject.attrs["mail"].append( sMail.utf8() ); 00217 } 00218 } 00219 } 00220 } 00221 mCurrentObject.client = this; 00222 emit result( mCurrentObject ); 00223 mCurrentObject.clear(); 00224 } 00225 00226 void LdapClient::parseLDIF( const TQByteArray& data ) 00227 { 00228 //kdDebug(5300) << "LdapClient::parseLDIF( " << TQCString(data.data(), data.size()+1) << " )" << endl; 00229 if ( data.size() ) { 00230 mLdif.setLDIF( data ); 00231 } else { 00232 mLdif.endLDIF(); 00233 } 00234 00235 TDEABC::LDIF::ParseVal ret; 00236 TQString name; 00237 do { 00238 ret = mLdif.nextItem(); 00239 switch ( ret ) { 00240 case TDEABC::LDIF::Item: 00241 { 00242 name = mLdif.attr(); 00243 // Must make a copy! TQByteArray is explicitely shared 00244 TQByteArray value = mLdif.val().copy(); 00245 bool bIsObjectClass = name.lower() == "objectclass"; 00246 if( bIsObjectClass ) 00247 mCurrentObject.objectClass = TQString::fromUtf8( value, value.size() ); 00248 if( mReportObjectClass || !bIsObjectClass ) 00249 mCurrentObject.attrs[ name ].append( value ); 00250 //kdDebug(5300) << "LdapClient::parseLDIF(): name=" << name << " value=" << TQCString(value.data(), value.size()+1) << endl; 00251 } 00252 break; 00253 case TDEABC::LDIF::EndEntry: 00254 finishCurrentObject(); 00255 break; 00256 default: 00257 break; 00258 } 00259 } while ( ret != TDEABC::LDIF::MoreData ); 00260 } 00261 00262 int LdapClient::clientNumber() const 00263 { 00264 return mClientNumber; 00265 } 00266 00267 int LdapClient::completionWeight() const 00268 { 00269 return mCompletionWeight; 00270 } 00271 00272 void LdapClient::setCompletionWeight( int weight ) 00273 { 00274 mCompletionWeight = weight; 00275 } 00276 00277 void LdapSearch::readConfig( LdapServer &server, TDEConfig *config, int j, bool active ) 00278 { 00279 TQString prefix; 00280 if ( active ) prefix = "Selected"; 00281 TQString host = config->readEntry( prefix + TQString( "Host%1" ).arg( j ), "" ).stripWhiteSpace(); 00282 if ( !host.isEmpty() ) 00283 server.setHost( host ); 00284 00285 int port = config->readNumEntry( prefix + TQString( "Port%1" ).arg( j ), 389 ); 00286 server.setPort( port ); 00287 00288 TQString base = config->readEntry( prefix + TQString( "Base%1" ).arg( j ), "" ).stripWhiteSpace(); 00289 if ( !base.isEmpty() ) 00290 server.setBaseDN( base ); 00291 00292 TQString user = config->readEntry( prefix + TQString( "User%1" ).arg( j ) ).stripWhiteSpace(); 00293 if ( !user.isEmpty() ) 00294 server.setUser( user ); 00295 00296 TQString bindDN = config->readEntry( prefix + TQString( "Bind%1" ).arg( j ) ).stripWhiteSpace(); 00297 if ( !bindDN.isEmpty() ) 00298 server.setBindDN( bindDN ); 00299 00300 TQString pwdBindDN = config->readEntry( prefix + TQString( "PwdBind%1" ).arg( j ) ); 00301 if ( !pwdBindDN.isEmpty() ) 00302 server.setPwdBindDN( pwdBindDN ); 00303 00304 server.setTimeLimit( config->readNumEntry( prefix + TQString( "TimeLimit%1" ).arg( j ) ) ); 00305 server.setSizeLimit( config->readNumEntry( prefix + TQString( "SizeLimit%1" ).arg( j ) ) ); 00306 server.setVersion( config->readNumEntry( prefix + TQString( "Version%1" ).arg( j ), 3 ) ); 00307 server.setSecurity( config->readNumEntry( prefix + TQString( "Security%1" ).arg( j ) ) ); 00308 server.setAuth( config->readNumEntry( prefix + TQString( "Auth%1" ).arg( j ) ) ); 00309 server.setMech( config->readEntry( prefix + TQString( "Mech%1" ).arg( j ) ) ); 00310 } 00311 00312 void LdapSearch::writeConfig( const LdapServer &server, TDEConfig *config, int j, bool active ) 00313 { 00314 TQString prefix; 00315 if ( active ) prefix = "Selected"; 00316 config->writeEntry( prefix + TQString( "Host%1" ).arg( j ), server.host() ); 00317 config->writeEntry( prefix + TQString( "Port%1" ).arg( j ), server.port() ); 00318 config->writeEntry( prefix + TQString( "Base%1" ).arg( j ), server.baseDN() ); 00319 config->writeEntry( prefix + TQString( "User%1" ).arg( j ), server.user() ); 00320 config->writeEntry( prefix + TQString( "Bind%1" ).arg( j ), server.bindDN() ); 00321 config->writeEntry( prefix + TQString( "PwdBind%1" ).arg( j ), server.pwdBindDN() ); 00322 config->writeEntry( prefix + TQString( "TimeLimit%1" ).arg( j ), server.timeLimit() ); 00323 config->writeEntry( prefix + TQString( "SizeLimit%1" ).arg( j ), server.sizeLimit() ); 00324 config->writeEntry( prefix + TQString( "Version%1" ).arg( j ), server.version() ); 00325 config->writeEntry( prefix + TQString( "Security%1" ).arg( j ), server.security() ); 00326 config->writeEntry( prefix + TQString( "Auth%1" ).arg( j ), server.auth() ); 00327 config->writeEntry( prefix + TQString( "Mech%1" ).arg( j ), server.mech() ); 00328 } 00329 00330 TDEConfig* LdapSearch::config() 00331 { 00332 if ( !s_config ) 00333 configDeleter.setObject( s_config, new TDEConfig( "kabldaprc", false, false ) ); // Open read-write, no kdeglobals 00334 00335 return s_config; 00336 } 00337 00338 00339 LdapSearch::LdapSearch() 00340 : mActiveClients( 0 ), mNoLDAPLookup( false ) 00341 { 00342 if ( !KProtocolInfo::isKnownProtocol( KURL("ldap://localhost") ) ) { 00343 mNoLDAPLookup = true; 00344 return; 00345 } 00346 00347 readConfig(); 00348 connect(KDirWatch::self(), TQT_SIGNAL(dirty (const TQString&)),this, 00349 TQT_SLOT(slotFileChanged(const TQString&))); 00350 } 00351 00352 void LdapSearch::readWeighForClient( LdapClient *client, TDEConfig *config, int clientNumber ) 00353 { 00354 const int completionWeight = config->readNumEntry( TQString( "SelectedCompletionWeight%1" ).arg( clientNumber ), -1 ); 00355 if ( completionWeight != -1 ) 00356 client->setCompletionWeight( completionWeight ); 00357 } 00358 00359 void LdapSearch::updateCompletionWeights() 00360 { 00361 TDEConfig *config = KPIM::LdapSearch::config(); 00362 config->setGroup( "LDAP" ); 00363 for ( uint i = 0; i < mClients.size(); i++ ) { 00364 readWeighForClient( mClients[i], config, i ); 00365 } 00366 } 00367 00368 void LdapSearch::readConfig() 00369 { 00370 cancelSearch(); 00371 TQValueList< LdapClient* >::Iterator it; 00372 for ( it = mClients.begin(); it != mClients.end(); ++it ) 00373 delete *it; 00374 mClients.clear(); 00375 00376 // stolen from KAddressBook 00377 TDEConfig *config = KPIM::LdapSearch::config(); 00378 config->setGroup( "LDAP" ); 00379 int numHosts = config->readUnsignedNumEntry( "NumSelectedHosts"); 00380 if ( !numHosts ) { 00381 mNoLDAPLookup = true; 00382 } else { 00383 for ( int j = 0; j < numHosts; j++ ) { 00384 LdapClient* ldapClient = new LdapClient( j, this ); 00385 LdapServer server; 00386 readConfig( server, config, j, true ); 00387 if ( !server.host().isEmpty() ) mNoLDAPLookup = false; 00388 ldapClient->setServer( server ); 00389 00390 readWeighForClient( ldapClient, config, j ); 00391 00392 TQStringList attrs; 00393 // note: we need "objectClass" to detect distribution lists 00394 attrs << "cn" << "mail" << "givenname" << "sn" << "objectClass"; 00395 ldapClient->setAttrs( attrs ); 00396 00397 connect( ldapClient, TQT_SIGNAL( result( const KPIM::LdapObject& ) ), 00398 this, TQT_SLOT( slotLDAPResult( const KPIM::LdapObject& ) ) ); 00399 connect( ldapClient, TQT_SIGNAL( done() ), 00400 this, TQT_SLOT( slotLDAPDone() ) ); 00401 connect( ldapClient, TQT_SIGNAL( error( const TQString& ) ), 00402 this, TQT_SLOT( slotLDAPError( const TQString& ) ) ); 00403 00404 mClients.append( ldapClient ); 00405 } 00406 00407 connect( &mDataTimer, TQT_SIGNAL( timeout() ), TQT_SLOT( slotDataTimer() ) ); 00408 } 00409 mConfigFile = locateLocal( "config", "kabldaprc" ); 00410 KDirWatch::self()->addFile( mConfigFile ); 00411 } 00412 00413 void LdapSearch::slotFileChanged( const TQString& file ) 00414 { 00415 if ( file == mConfigFile ) 00416 readConfig(); 00417 } 00418 00419 void LdapSearch::startSearch( const TQString& txt ) 00420 { 00421 if ( mNoLDAPLookup ) 00422 return; 00423 00424 cancelSearch(); 00425 00426 int pos = txt.find( '\"' ); 00427 if( pos >= 0 ) 00428 { 00429 ++pos; 00430 int pos2 = txt.find( '\"', pos ); 00431 if( pos2 >= 0 ) 00432 mSearchText = txt.mid( pos , pos2 - pos ); 00433 else 00434 mSearchText = txt.mid( pos ); 00435 } else 00436 mSearchText = txt; 00437 00438 /* The reasoning behind this filter is: 00439 * If it's a person, or a distlist, show it, even if it doesn't have an email address. 00440 * If it's not a person, or a distlist, only show it if it has an email attribute. 00441 * This allows both resource accounts with an email address which are not a person and 00442 * person entries without an email address to show up, while still not showing things 00443 * like structural entries in the ldap tree. */ 00444 TQString filter = TQString( "&(|(objectclass=person)(objectclass=groupOfNames)(mail=*))(|(cn=%1*)(mail=%2*)(mail=*@%3*)(givenName=%4*)(sn=%5*))" ) 00445 .arg( mSearchText ).arg( mSearchText ).arg( mSearchText ).arg( mSearchText ).arg( mSearchText ); 00446 00447 TQValueList< LdapClient* >::Iterator it; 00448 for ( it = mClients.begin(); it != mClients.end(); ++it ) { 00449 (*it)->startQuery( filter ); 00450 kdDebug(5300) << "LdapSearch::startSearch() " << filter << endl; 00451 ++mActiveClients; 00452 } 00453 } 00454 00455 void LdapSearch::cancelSearch() 00456 { 00457 TQValueList< LdapClient* >::Iterator it; 00458 for ( it = mClients.begin(); it != mClients.end(); ++it ) 00459 (*it)->cancelQuery(); 00460 00461 mActiveClients = 0; 00462 mResults.clear(); 00463 } 00464 00465 void LdapSearch::slotLDAPResult( const KPIM::LdapObject& obj ) 00466 { 00467 mResults.append( obj ); 00468 if ( !mDataTimer.isActive() ) 00469 mDataTimer.start( 500, true ); 00470 } 00471 00472 void LdapSearch::slotLDAPError( const TQString& ) 00473 { 00474 slotLDAPDone(); 00475 } 00476 00477 void LdapSearch::slotLDAPDone() 00478 { 00479 if ( --mActiveClients > 0 ) 00480 return; 00481 00482 finish(); 00483 } 00484 00485 void LdapSearch::slotDataTimer() 00486 { 00487 TQStringList lst; 00488 LdapResultList reslist; 00489 makeSearchData( lst, reslist ); 00490 if ( !lst.isEmpty() ) 00491 emit searchData( lst ); 00492 if ( !reslist.isEmpty() ) 00493 emit searchData( reslist ); 00494 } 00495 00496 void LdapSearch::finish() 00497 { 00498 mDataTimer.stop(); 00499 00500 slotDataTimer(); // emit final bunch of data 00501 emit searchDone(); 00502 } 00503 00504 void LdapSearch::makeSearchData( TQStringList& ret, LdapResultList& resList ) 00505 { 00506 TQString search_text_upper = mSearchText.upper(); 00507 00508 TQValueList< KPIM::LdapObject >::ConstIterator it1; 00509 for ( it1 = mResults.begin(); it1 != mResults.end(); ++it1 ) { 00510 TQString name, mail, givenname, sn; 00511 TQStringList mails; 00512 bool isDistributionList = false; 00513 bool wasCN = false; 00514 bool wasDC = false; 00515 00516 //kdDebug(5300) << "\n\nLdapSearch::makeSearchData()\n\n" << endl; 00517 00518 LdapAttrMap::ConstIterator it2; 00519 for ( it2 = (*it1).attrs.begin(); it2 != (*it1).attrs.end(); ++it2 ) { 00520 TQByteArray val = (*it2).first(); 00521 int len = val.size(); 00522 if( len > 0 && '\0' == val[len-1] ) 00523 --len; 00524 const TQString tmp = TQString::fromUtf8( val, len ); 00525 //kdDebug(5300) << " key: \"" << it2.key() << "\" value: \"" << tmp << "\"" << endl; 00526 if ( it2.key() == "cn" ) { 00527 name = tmp; 00528 if( mail.isEmpty() ) 00529 mail = tmp; 00530 else{ 00531 if( wasCN ) 00532 mail.prepend( "." ); 00533 else 00534 mail.prepend( "@" ); 00535 mail.prepend( tmp ); 00536 } 00537 wasCN = true; 00538 } else if ( it2.key() == "dc" ) { 00539 if( mail.isEmpty() ) 00540 mail = tmp; 00541 else{ 00542 if( wasDC ) 00543 mail.append( "." ); 00544 else 00545 mail.append( "@" ); 00546 mail.append( tmp ); 00547 } 00548 wasDC = true; 00549 } else if( it2.key() == "mail" ) { 00550 mail = tmp; 00551 LdapAttrValue::ConstIterator it3 = it2.data().begin(); 00552 for ( ; it3 != it2.data().end(); ++it3 ) { 00553 mails.append( TQString::fromUtf8( (*it3).data(), (*it3).size() ) ); 00554 } 00555 } else if( it2.key() == "givenName" ) 00556 givenname = tmp; 00557 else if( it2.key() == "sn" ) 00558 sn = tmp; 00559 else if( it2.key() == "objectClass" && 00560 (tmp == "groupOfNames" || tmp == "kolabGroupOfNames") ) { 00561 isDistributionList = true; 00562 } 00563 } 00564 00565 if( mails.isEmpty()) { 00566 if ( !mail.isEmpty() ) mails.append( mail ); 00567 if( isDistributionList ) { 00568 //kdDebug(5300) << "\n\nLdapSearch::makeSearchData() found a list: " << name << "\n\n" << endl; 00569 ret.append( name ); 00570 // following lines commented out for bugfixing kolab issue #177: 00571 // 00572 // Unlike we thought previously we may NOT append the server name here. 00573 // 00574 // The right server is found by the SMTP server instead: Kolab users 00575 // must use the correct SMTP server, by definition. 00576 // 00577 //mail = (*it1).client->base().simplifyWhiteSpace(); 00578 //mail.replace( ",dc=", ".", false ); 00579 //if( mail.startsWith("dc=", false) ) 00580 // mail.remove(0, 3); 00581 //mail.prepend( '@' ); 00582 //mail.prepend( name ); 00583 //mail = name; 00584 } else { 00585 //kdDebug(5300) << "LdapSearch::makeSearchData() found BAD ENTRY: \"" << name << "\"" << endl; 00586 continue; // nothing, bad entry 00587 } 00588 } else if ( name.isEmpty() ) { 00589 //kdDebug(5300) << "LdapSearch::makeSearchData() mail: \"" << mail << "\"" << endl; 00590 ret.append( mail ); 00591 } else { 00592 //kdDebug(5300) << "LdapSearch::makeSearchData() name: \"" << name << "\" mail: \"" << mail << "\"" << endl; 00593 ret.append( TQString( "%1 <%2>" ).arg( name ).arg( mail ) ); 00594 } 00595 00596 LdapResult sr; 00597 sr.clientNumber = (*it1).client->clientNumber(); 00598 sr.completionWeight = (*it1).client->completionWeight(); 00599 sr.name = name; 00600 sr.email = mails; 00601 resList.append( sr ); 00602 } 00603 00604 mResults.clear(); 00605 } 00606 00607 bool LdapSearch::isAvailable() const 00608 { 00609 return !mNoLDAPLookup; 00610 } 00611 00612 00613 #include "ldapclient.moc"