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 <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
00163
00164
#endif
00165
parseLDIF( data );
00166 }
00167
00168
void LdapClient::slotInfoMessage( KIO::Job*,
const QString & )
00169 {
00170
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
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 ) ).stripWhiteSpace();
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();
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;
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;
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"