00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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 <tdeapplication.h>
00033 #include <tdeconfig.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 TDEABC;
00043
00044 class LdapClient::LdapClientPrivate{
00045 public:
00046 TQString bindDN;
00047 TQString pwdBindDN;
00048 LDIF ldif;
00049 };
00050
00051 TQString LdapObject::toString() const
00052 {
00053 TQString result = TQString::fromLatin1( "\ndn: %1\n" ).arg( dn );
00054 for ( LdapAttrMap::ConstIterator it = attrs.begin(); it != attrs.end(); ++it ) {
00055 TQString attr = it.key();
00056 for ( LdapAttrValue::ConstIterator it2 = (*it).begin(); it2 != (*it).end(); ++it2 ) {
00057 result += TQString::fromUtf8( LDIF::assembleLine( attr, *it2, 76 ) ) + "\n";
00058 }
00059 }
00060
00061 return result;
00062 }
00063
00064 void LdapObject::clear()
00065 {
00066 dn = TQString::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( TQObject* parent, const char* name )
00080 : TQObject( 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 TQString& host )
00092 {
00093 mHost = host;
00094 }
00095
00096 void LdapClient::setPort( const TQString& port )
00097 {
00098 mPort = port;
00099 }
00100
00101 void LdapClient::setBase( const TQString& base )
00102 {
00103 mBase = base;
00104 }
00105
00106 void LdapClient::setBindDN( const TQString& bindDN )
00107 {
00108 d->bindDN = bindDN;
00109 }
00110
00111 void LdapClient::setPwdBindDN( const TQString& pwdBindDN )
00112 {
00113 d->pwdBindDN = pwdBindDN;
00114 }
00115
00116 void LdapClient::setAttrs( const TQStringList& attrs )
00117 {
00118 mAttrs = attrs;
00119 }
00120
00121 void LdapClient::startQuery( const TQString& 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 = TDEIO::get( url, false, false );
00141 connect( mJob, TQT_SIGNAL( data( TDEIO::Job*, const TQByteArray& ) ),
00142 this, TQT_SLOT( slotData( TDEIO::Job*, const TQByteArray& ) ) );
00143 connect( mJob, TQT_SIGNAL( infoMessage( TDEIO::Job*, const TQString& ) ),
00144 this, TQT_SLOT( slotInfoMessage( TDEIO::Job*, const TQString& ) ) );
00145 connect( mJob, TQT_SIGNAL( result( TDEIO::Job* ) ),
00146 this, TQT_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( TDEIO::Job*, const TQByteArray& data )
00160 {
00161 #ifndef NDEBUG // don't create the QString
00162
00163
00164 #endif
00165 parseLDIF( data );
00166 }
00167
00168 void LdapClient::slotInfoMessage( TDEIO::Job*, const TQString & )
00169 {
00170
00171 }
00172
00173 void LdapClient::slotDone()
00174 {
00175 endParseLDIF();
00176 mActive = false;
00177 #if 0
00178 for ( TQValueList<LdapObject>::Iterator it = mObjects.begin(); it != mObjects.end(); ++it ) {
00179 tqDebug( (*it).toString().latin1() );
00180 }
00181 #endif
00182 int err = mJob->error();
00183 if ( err && err != TDEIO::ERR_USER_CANCELED ) {
00184 emit error( TDEIO::buildErrorString( err, TQString("%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 TQByteArray& data )
00203 {
00204 if ( data.size() ) {
00205 d->ldif.setLDIF( data );
00206 } else {
00207 d->ldif.endLDIF();
00208 }
00209
00210 LDIF::ParseVal ret;
00211 TQString name;
00212 do {
00213 ret = d->ldif.nextItem();
00214 switch ( ret ) {
00215 case LDIF::Item:
00216 {
00217 name = d->ldif.attr();
00218
00219 TQByteArray value = d->ldif.val().copy();
00220 mCurrentObject.attrs[ name ].append( value );
00221 break;
00222 }
00223 case LDIF::EndEntry:
00224 mCurrentObject.dn = d->ldif.dn();
00225 mCurrentObject.client = this;
00226 emit result( mCurrentObject );
00227 mCurrentObject.clear();
00228 break;
00229 default:
00230 break;
00231 }
00232 } while ( ret != LDIF::MoreData );
00233 }
00234
00235 TQString LdapClient::bindDN() const
00236 {
00237 return d->bindDN;
00238 }
00239
00240 TQString LdapClient::pwdBindDN() const
00241 {
00242 return d->pwdBindDN;
00243 }
00244
00245 LdapSearch::LdapSearch()
00246 : mActiveClients( 0 ), mNoLDAPLookup( false )
00247 {
00248 if ( !KProtocolInfo::isKnownProtocol( KURL("ldap://localhost") ) ) {
00249 mNoLDAPLookup = true;
00250 return;
00251 }
00252
00253
00254 TDEConfig config( "kabldaprc", true );
00255 config.setGroup( "LDAP" );
00256 int numHosts = config.readUnsignedNumEntry( "NumSelectedHosts");
00257 if ( !numHosts ) {
00258 mNoLDAPLookup = true;
00259 return;
00260 } else {
00261 for ( int j = 0; j < numHosts; j++ ) {
00262 LdapClient* ldapClient = new LdapClient( this );
00263
00264 TQString host = config.readEntry( TQString( "SelectedHost%1" ).arg( j ), "" ).stripWhiteSpace();
00265 if ( !host.isEmpty() )
00266 ldapClient->setHost( host );
00267
00268 TQString port = TQString::number( config.readUnsignedNumEntry( TQString( "SelectedPort%1" ).arg( j ) ) );
00269 if ( !port.isEmpty() )
00270 ldapClient->setPort( port );
00271
00272 TQString base = config.readEntry( TQString( "SelectedBase%1" ).arg( j ), "" ).stripWhiteSpace();
00273 if ( !base.isEmpty() )
00274 ldapClient->setBase( base );
00275
00276 TQString bindDN = config.readEntry( TQString( "SelectedBind%1" ).arg( j ) ).stripWhiteSpace();
00277 if ( !bindDN.isEmpty() )
00278 ldapClient->setBindDN( bindDN );
00279
00280 TQString pwdBindDN = config.readEntry( TQString( "SelectedPwdBind%1" ).arg( j ) );
00281 if ( !pwdBindDN.isEmpty() )
00282 ldapClient->setPwdBindDN( pwdBindDN );
00283
00284 TQStringList attrs;
00285 attrs << "cn" << "mail" << "givenname" << "sn";
00286 ldapClient->setAttrs( attrs );
00287
00288 connect( ldapClient, TQT_SIGNAL( result( const TDEABC::LdapObject& ) ),
00289 this, TQT_SLOT( slotLDAPResult( const TDEABC::LdapObject& ) ) );
00290 connect( ldapClient, TQT_SIGNAL( done() ),
00291 this, TQT_SLOT( slotLDAPDone() ) );
00292 connect( ldapClient, TQT_SIGNAL( error( const TQString& ) ),
00293 this, TQT_SLOT( slotLDAPError( const TQString& ) ) );
00294
00295 mClients.append( ldapClient );
00296 }
00297 }
00298
00299 connect( &mDataTimer, TQT_SIGNAL( timeout() ), TQT_SLOT( slotDataTimer() ) );
00300 }
00301
00302 void LdapSearch::startSearch( const TQString& txt )
00303 {
00304 if ( mNoLDAPLookup )
00305 return;
00306
00307 cancelSearch();
00308
00309 int pos = txt.find( '\"' );
00310 if( pos >= 0 )
00311 {
00312 ++pos;
00313 int pos2 = txt.find( '\"', pos );
00314 if( pos2 >= 0 )
00315 mSearchText = txt.mid( pos , pos2 - pos );
00316 else
00317 mSearchText = txt.mid( pos );
00318 } else
00319 mSearchText = txt;
00320
00321 TQString filter = TQString( "|(cn=%1*)(mail=%2*)(givenName=%3*)(sn=%4*)" )
00322 .arg( mSearchText ).arg( mSearchText ).arg( mSearchText ).arg( mSearchText );
00323
00324 TQValueList< LdapClient* >::Iterator it;
00325 for ( it = mClients.begin(); it != mClients.end(); ++it ) {
00326 (*it)->startQuery( filter );
00327 ++mActiveClients;
00328 }
00329 }
00330
00331 void LdapSearch::cancelSearch()
00332 {
00333 TQValueList< LdapClient* >::Iterator it;
00334 for ( it = mClients.begin(); it != mClients.end(); ++it )
00335 (*it)->cancelQuery();
00336
00337 mActiveClients = 0;
00338 mResults.clear();
00339 }
00340
00341 void LdapSearch::slotLDAPResult( const TDEABC::LdapObject& obj )
00342 {
00343 mResults.append( obj );
00344 if ( !mDataTimer.isActive() )
00345 mDataTimer.start( 500, true );
00346 }
00347
00348 void LdapSearch::slotLDAPError( const TQString& )
00349 {
00350 slotLDAPDone();
00351 }
00352
00353 void LdapSearch::slotLDAPDone()
00354 {
00355 if ( --mActiveClients > 0 )
00356 return;
00357
00358 finish();
00359 }
00360
00361 void LdapSearch::slotDataTimer()
00362 {
00363 TQStringList lst;
00364 LdapResultList reslist;
00365 makeSearchData( lst, reslist );
00366 if ( !lst.isEmpty() )
00367 emit searchData( lst );
00368 if ( !reslist.isEmpty() )
00369 emit searchData( reslist );
00370 }
00371
00372 void LdapSearch::finish()
00373 {
00374 mDataTimer.stop();
00375
00376 slotDataTimer();
00377 emit searchDone();
00378 }
00379
00380 void LdapSearch::makeSearchData( TQStringList& ret, LdapResultList& resList )
00381 {
00382 TQString search_text_upper = mSearchText.upper();
00383
00384 TQValueList< TDEABC::LdapObject >::ConstIterator it1;
00385 for ( it1 = mResults.begin(); it1 != mResults.end(); ++it1 ) {
00386 TQString name, mail, givenname, sn;
00387
00388 LdapAttrMap::ConstIterator it2;
00389 for ( it2 = (*it1).attrs.begin(); it2 != (*it1).attrs.end(); ++it2 ) {
00390 TQString tmp = TQString::fromUtf8( (*it2).first(), (*it2).first().size() );
00391 if ( it2.key() == "cn" )
00392 name = tmp;
00393 else if( it2.key() == "mail" )
00394 mail = tmp;
00395 else if( it2.key() == "givenName" )
00396 givenname = tmp;
00397 else if( it2.key() == "sn" )
00398 sn = tmp;
00399 }
00400
00401 if( mail.isEmpty())
00402 continue;
00403 else if ( name.isEmpty() )
00404 ret.append( mail );
00405 else {
00406 kdDebug(5700) << "<" << name << "><" << mail << ">" << endl;
00407 ret.append( TQString( "%1 <%2>" ).arg( name ).arg( mail ) );
00408 }
00409
00410 LdapResult sr;
00411 sr.clientNumber = mClients.findIndex( (*it1).client );
00412 sr.name = name;
00413 sr.email = mail;
00414 resList.append( sr );
00415 }
00416
00417 mResults.clear();
00418 }
00419
00420 bool LdapSearch::isAvailable() const
00421 {
00422 return !mNoLDAPLookup;
00423 }
00424
00425
00426
00427 #include "ldapclient.moc"