00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "resourceldapkio.h"
00023 #include "resourceldapkioconfig.h"
00024
00025 #include "kldap/ldif.h"
00026 #include "kldap/ldapdn.h"
00027 #include "kldap/ldapurl.h"
00028
00029 #include <kio/netaccess.h>
00030 #include <kio/udsentry.h>
00031 #include <kdebug.h>
00032 #include <kde_file.h>
00033 #include <kglobal.h>
00034 #include <kstandarddirs.h>
00035 #include <klineedit.h>
00036 #include <klocale.h>
00037 #include <kconfig.h>
00038 #include <kstringhandler.h>
00039 #include <ktemporaryfile.h>
00040
00041 #include <QtCore/QBuffer>
00042 #include <QtCore/QEventLoop>
00043 #include <QtCore/QFile>
00044
00045 #include <stdlib.h>
00046
00047 using namespace KABC;
00048
00049 class ResourceLDAPKIO::Private
00050 {
00051 public:
00052 Private( ResourceLDAPKIO *parent )
00053 : mParent( parent ), mPort( 389 ), mAnonymous( true ), mTLS( false ),
00054 mSSL( false ), mSubTree( false ), mSASL( false ), mVer( 3 ),
00055 mRDNPrefix( 0 ), mTimeLimit( 0 ), mSizeLimit( 0 ),
00056 mCachePolicy( Cache_No ), mAutoCache( true )
00057 {
00058 }
00059
00060 KIO::Job *loadFromCache();
00061 void createCache();
00062 void activateCache();
00063 void enter_loop();
00064 QByteArray addEntry( const QString &attr, const QString &value, bool mod );
00065 QString findUid( const QString &uid );
00066 bool AddresseeToLDIF( QByteArray &ldif, const Addressee &addr, const QString &olddn );
00067
00068 ResourceLDAPKIO *mParent;
00069 QString mUser;
00070 QString mPassword;
00071 QString mDn;
00072 QString mHost;
00073 QString mFilter;
00074 int mPort;
00075 bool mAnonymous;
00076 QMap<QString, QString> mAttributes;
00077
00078 QString mErrorMsg;
00079
00080 KLDAP::Ldif mLdif;
00081 bool mTLS, mSSL, mSubTree;
00082 QString mResultDn;
00083 Addressee mAddr;
00084 Address mAd;
00085 Resource::Iterator mSaveIt;
00086 bool mSASL;
00087 QString mMech;
00088 QString mRealm, mBindDN;
00089 KLDAP::LdapUrl mLDAPUrl;
00090 int mVer;
00091 int mRDNPrefix;
00092 int mTimeLimit;
00093 int mSizeLimit;
00094 int mError;
00095 int mCachePolicy;
00096 bool mReadOnly;
00097 bool mAutoCache;
00098 QString mCacheDst;
00099 KTemporaryFile *mTmp;
00100 };
00101
00102 ResourceLDAPKIO::ResourceLDAPKIO()
00103 : Resource(), d( new Private( this ) )
00104 {
00105 d->mCacheDst = KGlobal::dirs()->saveLocation( "cache", "ldapkio" ) + '/' +
00106 type() + '_' + identifier();
00107 init();
00108 }
00109
00110 ResourceLDAPKIO::ResourceLDAPKIO( const KConfigGroup &group )
00111 : Resource( group ), d( new Private( this ) )
00112 {
00113 QMap<QString, QString> attrList;
00114 QStringList attributes = group.readEntry( "LdapAttributes", QStringList() );
00115 for ( int pos = 0; pos < attributes.count(); pos += 2 ) {
00116 d->mAttributes.insert( attributes[ pos ], attributes[ pos + 1 ] );
00117 }
00118
00119 d->mUser = group.readEntry( "LdapUser" );
00120 d->mPassword = KStringHandler::obscure( group.readEntry( "LdapPassword" ) );
00121 d->mDn = group.readEntry( "LdapDn" );
00122 d->mHost = group.readEntry( "LdapHost" );
00123 d->mPort = group.readEntry( "LdapPort", 389 );
00124 d->mFilter = group.readEntry( "LdapFilter" );
00125 d->mAnonymous = group.readEntry( "LdapAnonymous", false );
00126 d->mTLS = group.readEntry( "LdapTLS", false );
00127 d->mSSL = group.readEntry( "LdapSSL", false );
00128 d->mSubTree = group.readEntry( "LdapSubTree", false );
00129 d->mSASL = group.readEntry( "LdapSASL", false );
00130 d->mMech = group.readEntry( "LdapMech" );
00131 d->mRealm = group.readEntry( "LdapRealm" );
00132 d->mBindDN = group.readEntry( "LdapBindDN" );
00133 d->mVer = group.readEntry( "LdapVer", 3 );
00134 d->mTimeLimit = group.readEntry( "LdapTimeLimit", 0 );
00135 d->mSizeLimit = group.readEntry( "LdapSizeLimit", 0 );
00136 d->mRDNPrefix = group.readEntry( "LdapRDNPrefix", 0 );
00137 d->mCachePolicy = group.readEntry( "LdapCachePolicy", 0 );
00138 d->mAutoCache = group.readEntry( "LdapAutoCache", true );
00139 d->mCacheDst = KGlobal::dirs()->saveLocation( "cache", "ldapkio" ) + '/' +
00140 type() + '_' + identifier();
00141 init();
00142 }
00143
00144 ResourceLDAPKIO::~ResourceLDAPKIO()
00145 {
00146 delete d;
00147 }
00148
00149 void ResourceLDAPKIO::Private::enter_loop()
00150 {
00151 QEventLoop eventLoop;
00152 mParent->connect( mParent, SIGNAL( leaveModality() ), &eventLoop, SLOT( quit() ) );
00153 eventLoop.exec( QEventLoop::ExcludeUserInputEvents );
00154 }
00155
00156 void ResourceLDAPKIO::entries( KIO::Job *, const KIO::UDSEntryList &list )
00157 {
00158 KIO::UDSEntryList::ConstIterator it = list.begin();
00159 KIO::UDSEntryList::ConstIterator end = list.end();
00160 for ( ; it != end; ++it ) {
00161 const QString urlStr = (*it).stringValue( KIO::UDSEntry::UDS_URL );
00162 if ( !urlStr.isEmpty() ) {
00163 KUrl tmpurl( urlStr );
00164 d->mResultDn = tmpurl.path();
00165 kDebug() << "findUid():" << d->mResultDn;
00166 if ( d->mResultDn.startsWith( '/' ) ) {
00167 d->mResultDn.remove( 0, 1 );
00168 }
00169 return;
00170 }
00171 }
00172 }
00173
00174 void ResourceLDAPKIO::listResult( KJob *job )
00175 {
00176 d->mError = job->error();
00177 if ( d->mError && d->mError != KIO::ERR_USER_CANCELED ) {
00178 d->mErrorMsg = job->errorString();
00179 } else {
00180 d->mErrorMsg = "";
00181 }
00182 emit leaveModality();
00183 }
00184
00185 QString ResourceLDAPKIO::Private::findUid( const QString &uid )
00186 {
00187 KLDAP::LdapUrl url( mLDAPUrl );
00188 KIO::UDSEntry entry;
00189
00190 mErrorMsg.clear();
00191 mResultDn.clear();
00192
00193 url.setAttributes( QStringList( "dn" ) );
00194 url.setFilter( '(' + mAttributes[ "uid" ] + '=' + uid + ')' + mFilter );
00195 url.setExtension( "x-dir", "one" );
00196
00197 kDebug() << uid << "url" << url.prettyUrl();
00198
00199 KIO::ListJob *listJob = KIO::listDir( url, KIO::HideProgressInfo );
00200 mParent->connect( listJob, SIGNAL( entries( KIO::Job *, const KIO::UDSEntryList& ) ),
00201 SLOT( entries( KIO::Job*, const KIO::UDSEntryList& ) ) );
00202 mParent->connect( listJob, SIGNAL( result( KJob* ) ),
00203 mParent, SLOT( listResult( KJob* ) ) );
00204
00205 enter_loop();
00206 return mResultDn;
00207 }
00208
00209 QByteArray ResourceLDAPKIO::Private::addEntry( const QString &attr, const QString &value, bool mod )
00210 {
00211 QByteArray tmp;
00212 if ( !attr.isEmpty() ) {
00213 if ( mod ) {
00214 tmp += KLDAP::Ldif::assembleLine( "replace", attr ) + '\n';
00215 }
00216 tmp += KLDAP::Ldif::assembleLine( attr, value ) + '\n';
00217 if ( mod ) {
00218 tmp += "-\n";
00219 }
00220 }
00221 return tmp;
00222 }
00223
00224 bool ResourceLDAPKIO::Private::AddresseeToLDIF( QByteArray &ldif, const Addressee &addr,
00225 const QString &olddn )
00226 {
00227 QByteArray tmp;
00228 QString dn;
00229 QByteArray data;
00230 bool mod = false;
00231
00232 if ( olddn.isEmpty() ) {
00233
00234 switch ( mRDNPrefix ) {
00235 case 1:
00236 dn = mAttributes[ "uid" ] + '=' + addr.uid() + ',' + mDn;
00237 break;
00238 case 0:
00239 default:
00240 dn = mAttributes[ "commonName" ] + '=' + addr.assembledName() + ',' + mDn;
00241 break;
00242 }
00243 } else {
00244
00245 mod = true;
00246 if ( olddn.startsWith( mAttributes[ "uid" ] ) ) {
00247 dn = mAttributes[ "uid" ] + '=' + addr.uid() + ',' + olddn.section( ',', 1 );
00248 } else if ( olddn.startsWith( mAttributes[ "commonName" ] ) ) {
00249 dn = mAttributes[ "commonName" ] + '=' + addr.assembledName() + ',' +
00250 olddn.section( ',', 1 );
00251 } else {
00252 dn = olddn;
00253 }
00254
00255 if ( olddn.toLower() != dn.toLower() ) {
00256 tmp = KLDAP::Ldif::assembleLine( "dn", olddn ) + '\n';
00257 tmp += "changetype: modrdn\n";
00258 tmp += KLDAP::Ldif::assembleLine( "newrdn", dn.section( ',', 0, 0 ) ) + '\n';
00259 tmp += "deleteoldrdn: 1\n\n";
00260 }
00261 }
00262
00263 tmp += KLDAP::Ldif::assembleLine( "dn", dn ) + '\n';
00264 if ( mod ) {
00265 tmp += "changetype: modify\n";
00266 }
00267 if ( !mod ) {
00268 tmp += "objectClass: top\n";
00269 QStringList obclass = mAttributes[ "objectClass" ].split( ',', QString::SkipEmptyParts );
00270 for ( QStringList::const_iterator it = obclass.constBegin(); it != obclass.constEnd(); ++it ) {
00271 tmp += KLDAP::Ldif::assembleLine( "objectClass", *it ) + '\n';
00272 }
00273 }
00274
00275 tmp += addEntry( mAttributes[ "commonName" ], addr.assembledName(), mod );
00276 tmp += addEntry( mAttributes[ "formattedName" ], addr.formattedName(), mod );
00277 tmp += addEntry( mAttributes[ "givenName" ], addr.givenName(), mod );
00278 tmp += addEntry( mAttributes[ "familyName" ], addr.familyName(), mod );
00279 tmp += addEntry( mAttributes[ "uid" ], addr.uid(), mod );
00280
00281 PhoneNumber number;
00282 number = addr.phoneNumber( PhoneNumber::Home );
00283 tmp += addEntry( mAttributes[ "phoneNumber" ], number.number().toUtf8(), mod );
00284 number = addr.phoneNumber( PhoneNumber::Work );
00285 tmp += addEntry( mAttributes[ "telephoneNumber" ], number.number().toUtf8(), mod );
00286 number = addr.phoneNumber( PhoneNumber::Fax );
00287 tmp += addEntry( mAttributes[ "facsimileTelephoneNumber" ], number.number().toUtf8(), mod );
00288 number = addr.phoneNumber( PhoneNumber::Cell );
00289 tmp += addEntry( mAttributes[ "mobile" ], number.number().toUtf8(), mod );
00290 number = addr.phoneNumber( PhoneNumber::Pager );
00291 tmp += addEntry( mAttributes[ "pager" ], number.number().toUtf8(), mod );
00292
00293 tmp += addEntry( mAttributes[ "description" ], addr.note(), mod );
00294 tmp += addEntry( mAttributes[ "title" ], addr.title(), mod );
00295 tmp += addEntry( mAttributes[ "organization" ], addr.organization(), mod );
00296
00297 Address ad = addr.address( Address::Home );
00298 if ( !ad.isEmpty() ) {
00299 tmp += addEntry( mAttributes[ "street" ], ad.street(), mod );
00300 tmp += addEntry( mAttributes[ "state" ], ad.region(), mod );
00301 tmp += addEntry( mAttributes[ "city" ], ad.locality(), mod );
00302 tmp += addEntry( mAttributes[ "postalcode" ], ad.postalCode(), mod );
00303 }
00304
00305 QStringList emails = addr.emails();
00306 QStringList::ConstIterator mailIt = emails.begin();
00307
00308 if ( !mAttributes[ "mail" ].isEmpty() ) {
00309 if ( mod ) {
00310 tmp += KLDAP::Ldif::assembleLine( "replace", mAttributes[ "mail" ] ) + '\n';
00311 }
00312 if ( mailIt != emails.end() ) {
00313 tmp += KLDAP::Ldif::assembleLine( mAttributes[ "mail" ], *mailIt ) + '\n';
00314 mailIt ++;
00315 }
00316 if ( mod && mAttributes[ "mail" ] != mAttributes[ "mailAlias" ] ) {
00317 tmp += "-\n";
00318 }
00319 }
00320
00321 if ( !mAttributes[ "mailAlias" ].isEmpty() ) {
00322 if ( mod && mAttributes[ "mail" ] != mAttributes[ "mailAlias" ] ) {
00323 tmp += KLDAP::Ldif::assembleLine( "replace", mAttributes[ "mailAlias" ] ) + '\n';
00324 }
00325 for ( ; mailIt != emails.end(); ++mailIt ) {
00326 tmp += KLDAP::Ldif::assembleLine( mAttributes[ "mailAlias" ], *mailIt ) + '\n';
00327 }
00328 if ( mod ) {
00329 tmp += "-\n";
00330 }
00331 }
00332
00333 if ( !mAttributes[ "jpegPhoto" ].isEmpty() ) {
00334 QByteArray pic;
00335 QBuffer buffer( &pic );
00336 buffer.open( QIODevice::WriteOnly );
00337 addr.photo().data().save( &buffer, "JPEG" );
00338
00339 if ( mod ) {
00340 tmp += KLDAP::Ldif::assembleLine( "replace", mAttributes[ "jpegPhoto" ] ) + '\n';
00341 }
00342 tmp += KLDAP::Ldif::assembleLine( mAttributes[ "jpegPhoto" ], pic, 76 ) + '\n';
00343 if ( mod ) {
00344 tmp += "-\n";
00345 }
00346 }
00347
00348 tmp += '\n';
00349 kDebug() << "ldif:" << QString::fromUtf8( tmp );
00350 ldif = tmp;
00351 return true;
00352 }
00353
00354 void ResourceLDAPKIO::setReadOnly( bool value )
00355 {
00356
00357 d->mReadOnly = true;
00358 Resource::setReadOnly( value );
00359 }
00360
00361 void ResourceLDAPKIO::init()
00362 {
00363 if ( d->mPort == 0 ) {
00364 d->mPort = 389;
00365 }
00366
00373 if ( !d->mAttributes.contains( "objectClass" ) ) {
00374 d->mAttributes.insert( "objectClass", "inetOrgPerson" );
00375 }
00376 if ( !d->mAttributes.contains( "commonName" ) ) {
00377 d->mAttributes.insert( "commonName", "cn" );
00378 }
00379 if ( !d->mAttributes.contains( "formattedName" ) ) {
00380 d->mAttributes.insert( "formattedName", "displayName" );
00381 }
00382 if ( !d->mAttributes.contains( "familyName" ) ) {
00383 d->mAttributes.insert( "familyName", "sn" );
00384 }
00385 if ( !d->mAttributes.contains( "givenName" ) ) {
00386 d->mAttributes.insert( "givenName", "givenName" );
00387 }
00388 if ( !d->mAttributes.contains( "mail" ) ) {
00389 d->mAttributes.insert( "mail", "mail" );
00390 }
00391 if ( !d->mAttributes.contains( "mailAlias" ) ) {
00392 d->mAttributes.insert( "mailAlias", "" );
00393 }
00394 if ( !d->mAttributes.contains( "phoneNumber" ) ) {
00395 d->mAttributes.insert( "phoneNumber", "homePhone" );
00396 }
00397 if ( !d->mAttributes.contains( "telephoneNumber" ) ) {
00398 d->mAttributes.insert( "telephoneNumber", "telephoneNumber" );
00399 }
00400 if ( !d->mAttributes.contains( "facsimileTelephoneNumber" ) ) {
00401 d->mAttributes.insert( "facsimileTelephoneNumber", "facsimileTelephoneNumber" );
00402 }
00403 if ( !d->mAttributes.contains( "mobile" ) ) {
00404 d->mAttributes.insert( "mobile", "mobile" );
00405 }
00406 if ( !d->mAttributes.contains( "pager" ) ) {
00407 d->mAttributes.insert( "pager", "pager" );
00408 }
00409 if ( !d->mAttributes.contains( "description" ) ) {
00410 d->mAttributes.insert( "description", "description" );
00411 }
00412 if ( !d->mAttributes.contains( "title" ) ) {
00413 d->mAttributes.insert( "title", "title" );
00414 }
00415 if ( !d->mAttributes.contains( "street" ) ) {
00416 d->mAttributes.insert( "street", "street" );
00417 }
00418 if ( !d->mAttributes.contains( "state" ) ) {
00419 d->mAttributes.insert( "state", "st" );
00420 }
00421 if ( !d->mAttributes.contains( "city" ) ) {
00422 d->mAttributes.insert( "city", "l" );
00423 }
00424 if ( !d->mAttributes.contains( "organization" ) ) {
00425 d->mAttributes.insert( "organization", "o" );
00426 }
00427 if ( !d->mAttributes.contains( "postalcode" ) ) {
00428 d->mAttributes.insert( "postalcode", "postalCode" );
00429 }
00430 if ( !d->mAttributes.contains( "uid" ) ) {
00431 d->mAttributes.insert( "uid", "uid" );
00432 }
00433 if ( !d->mAttributes.contains( "jpegPhoto" ) ) {
00434 d->mAttributes.insert( "jpegPhoto", "jpegPhoto" );
00435 }
00436
00437 d->mLDAPUrl = KLDAP::LdapUrl( KUrl() );
00438 if ( !d->mAnonymous ) {
00439 d->mLDAPUrl.setUser( d->mUser );
00440 d->mLDAPUrl.setPass( d->mPassword );
00441 }
00442 d->mLDAPUrl.setProtocol( d->mSSL ? "ldaps" : "ldap" );
00443 d->mLDAPUrl.setHost( d->mHost );
00444 d->mLDAPUrl.setPort( d->mPort );
00445 d->mLDAPUrl.setDn( KLDAP::LdapDN( d->mDn ) );
00446
00447 if ( !d->mAttributes.empty() ) {
00448 QMap<QString,QString>::Iterator it;
00449 QStringList attr;
00450 for ( it = d->mAttributes.begin(); it != d->mAttributes.end(); ++it ) {
00451 if ( !it.value().isEmpty() && it.key() != "objectClass" ) {
00452 attr.append( it.value() );
00453 }
00454 }
00455 d->mLDAPUrl.setAttributes( attr );
00456 }
00457
00458 d->mLDAPUrl.setScope( d->mSubTree ? KLDAP::LdapUrl::Sub : KLDAP::LdapUrl::One );
00459 if ( !d->mFilter.isEmpty() && d->mFilter != "(objectClass=*)" ) {
00460 d->mLDAPUrl.setFilter( d->mFilter );
00461 }
00462 d->mLDAPUrl.setExtension( "x-dir", "base" );
00463 if ( d->mTLS ) {
00464 d->mLDAPUrl.setExtension( "x-tls", "" );
00465 }
00466 d->mLDAPUrl.setExtension( "x-ver", QString::number( d->mVer ) );
00467 if ( d->mSizeLimit ) {
00468 d->mLDAPUrl.setExtension( "x-sizelimit", QString::number( d->mSizeLimit ) );
00469 }
00470 if ( d->mTimeLimit ) {
00471 d->mLDAPUrl.setExtension( "x-timelimit", QString::number( d->mTimeLimit ) );
00472 }
00473 if ( d->mSASL ) {
00474 d->mLDAPUrl.setExtension( "x-sasl", "" );
00475 if ( !d->mBindDN.isEmpty() ) {
00476 d->mLDAPUrl.setExtension( "bindname", d->mBindDN );
00477 }
00478 if ( !d->mMech.isEmpty() ) {
00479 d->mLDAPUrl.setExtension( "x-mech", d->mMech );
00480 }
00481 if ( !d->mRealm.isEmpty() ) {
00482 d->mLDAPUrl.setExtension( "x-realm", d->mRealm );
00483 }
00484 }
00485
00486 d->mReadOnly = readOnly();
00487
00488 kDebug() << "resource_ldapkio url:" << d->mLDAPUrl.prettyUrl();
00489 }
00490
00491 void ResourceLDAPKIO::writeConfig( KConfigGroup &group )
00492 {
00493 Resource::writeConfig( group );
00494
00495 group.writeEntry( "LdapUser", d->mUser );
00496 group.writeEntry( "LdapPassword", KStringHandler::obscure( d->mPassword ) );
00497 group.writeEntry( "LdapDn", d->mDn );
00498 group.writeEntry( "LdapHost", d->mHost );
00499 group.writeEntry( "LdapPort", d->mPort );
00500 group.writeEntry( "LdapFilter", d->mFilter );
00501 group.writeEntry( "LdapAnonymous", d->mAnonymous );
00502 group.writeEntry( "LdapTLS", d->mTLS );
00503 group.writeEntry( "LdapSSL", d->mSSL );
00504 group.writeEntry( "LdapSubTree", d->mSubTree );
00505 group.writeEntry( "LdapSASL", d->mSASL );
00506 group.writeEntry( "LdapMech", d->mMech );
00507 group.writeEntry( "LdapVer", d->mVer );
00508 group.writeEntry( "LdapTimeLimit", d->mTimeLimit );
00509 group.writeEntry( "LdapSizeLimit", d->mSizeLimit );
00510 group.writeEntry( "LdapRDNPrefix", d->mRDNPrefix );
00511 group.writeEntry( "LdapRealm", d->mRealm );
00512 group.writeEntry( "LdapBindDN", d->mBindDN );
00513 group.writeEntry( "LdapCachePolicy", d->mCachePolicy );
00514 group.writeEntry( "LdapAutoCache", d->mAutoCache );
00515
00516 QStringList attributes;
00517 QMap<QString, QString>::const_iterator it;
00518 for ( it = d->mAttributes.constBegin(); it != d->mAttributes.constEnd(); ++it ) {
00519 attributes << it.key() << it.value();
00520 }
00521
00522 group.writeEntry( "LdapAttributes", attributes );
00523 }
00524
00525 Ticket *ResourceLDAPKIO::requestSaveTicket()
00526 {
00527 if ( !addressBook() ) {
00528 kDebug() << "no addressbook";
00529 return 0;
00530 }
00531
00532 return createTicket( this );
00533 }
00534
00535 void ResourceLDAPKIO::releaseSaveTicket( Ticket *ticket )
00536 {
00537 delete ticket;
00538 }
00539
00540 bool ResourceLDAPKIO::doOpen()
00541 {
00542 return true;
00543 }
00544
00545 void ResourceLDAPKIO::doClose()
00546 {
00547 }
00548
00549 void ResourceLDAPKIO::Private::createCache()
00550 {
00551 mTmp = 0;
00552 if ( mCachePolicy == Cache_NoConnection && mAutoCache ) {
00553 mTmp = new KTemporaryFile;
00554 mTmp->setPrefix( mCacheDst );
00555 mTmp->setSuffix( "tmp" );
00556 mTmp->open();
00557 }
00558 }
00559
00560 void ResourceLDAPKIO::Private::activateCache()
00561 {
00562 if ( mTmp && mError == 0 ) {
00563 QString filename = mTmp->fileName();
00564 delete mTmp;
00565 mTmp = 0;
00566 KDE_rename( QFile::encodeName( filename ), QFile::encodeName( mCacheDst ) );
00567 }
00568 }
00569
00570 KIO::Job *ResourceLDAPKIO::Private::loadFromCache()
00571 {
00572 KIO::Job *job = 0;
00573 if ( mCachePolicy == Cache_Always ||
00574 ( mCachePolicy == Cache_NoConnection &&
00575 mError == KIO::ERR_COULD_NOT_CONNECT ) ) {
00576
00577 mAddr = Addressee();
00578 mAd = Address( Address::Home );
00579
00580 mLdif.startParsing();
00581
00582 mParent->Resource::setReadOnly( true );
00583
00584 KUrl url( mCacheDst );
00585 job = KIO::get( url, KIO::Reload, KIO::HideProgressInfo );
00586 mParent->connect( job, SIGNAL( data( KIO::Job*, const QByteArray& ) ),
00587 mParent, SLOT( data( KIO::Job*, const QByteArray& ) ) );
00588 }
00589
00590 return job;
00591 }
00592
00593 bool ResourceLDAPKIO::load()
00594 {
00595 kDebug();
00596 KIO::Job *job;
00597
00598 clear();
00599
00600 d->mAddr = Addressee();
00601 d->mAd = Address( Address::Home );
00602
00603 d->mLdif.startParsing();
00604
00605
00606 Resource::setReadOnly( d->mReadOnly );
00607
00608 d->createCache();
00609 if ( d->mCachePolicy != Cache_Always ) {
00610 job = KIO::get( d->mLDAPUrl, KIO::Reload, KIO::HideProgressInfo );
00611 connect( job, SIGNAL( data( KIO::Job*, const QByteArray& ) ),
00612 this, SLOT( data( KIO::Job*, const QByteArray& ) ) );
00613 connect( job, SIGNAL( result( KJob* ) ),
00614 this, SLOT( syncLoadSaveResult( KJob* ) ) );
00615 d->enter_loop();
00616 }
00617
00618 job = d->loadFromCache();
00619 if ( job ) {
00620 connect( job, SIGNAL( result( KJob* ) ),
00621 this, SLOT( syncLoadSaveResult( KJob* ) ) );
00622 d->enter_loop();
00623 }
00624 if ( d->mErrorMsg.isEmpty() ) {
00625 kDebug() << "ResourceLDAPKIO load ok!";
00626 return true;
00627 } else {
00628 kDebug() << "ResourceLDAPKIO load finished with error:" << d->mErrorMsg;
00629 addressBook()->error( d->mErrorMsg );
00630 return false;
00631 }
00632 }
00633
00634 bool ResourceLDAPKIO::asyncLoad()
00635 {
00636 clear();
00637
00638 d->mAddr = Addressee();
00639 d->mAd = Address( Address::Home );
00640
00641 d->mLdif.startParsing();
00642
00643 Resource::setReadOnly( d->mReadOnly );
00644
00645 d->createCache();
00646 if ( d->mCachePolicy != Cache_Always ) {
00647 KIO::Job *job = KIO::get( d->mLDAPUrl, KIO::Reload, KIO::HideProgressInfo );
00648 connect( job, SIGNAL( data( KIO::Job*, const QByteArray& ) ),
00649 this, SLOT( data( KIO::Job*, const QByteArray& ) ) );
00650 connect( job, SIGNAL( result( KJob* ) ),
00651 this, SLOT( result( KJob* ) ) );
00652 } else {
00653 result( 0 );
00654 }
00655 return true;
00656 }
00657
00658 void ResourceLDAPKIO::data( KIO::Job *job, const QByteArray &data )
00659 {
00660 Q_UNUSED( job );
00661 if ( data.size() ) {
00662 d->mLdif.setLdif( data );
00663 if ( d->mTmp ) {
00664 d->mTmp->write( data );
00665 }
00666 } else {
00667 d->mLdif.endLdif();
00668 }
00669
00670 KLDAP::Ldif::ParseValue ret;
00671 QString name;
00672 QByteArray value;
00673 do {
00674 ret = d->mLdif.nextItem();
00675 switch ( ret ) {
00676 case KLDAP::Ldif::NewEntry:
00677 kDebug() << "new entry:" << d->mLdif.dn().toString();
00678 break;
00679 case KLDAP::Ldif::Item:
00680 name = d->mLdif.attr().toLower();
00681 value = d->mLdif.value();
00682 if ( name == d->mAttributes[ "commonName" ].toLower() ) {
00683 if ( !d->mAddr.formattedName().isEmpty() ) {
00684 QString fn = d->mAddr.formattedName();
00685 d->mAddr.setNameFromString( QString::fromUtf8( value, value.size() ) );
00686 d->mAddr.setFormattedName( fn );
00687 } else {
00688 d->mAddr.setNameFromString( QString::fromUtf8( value, value.size() ) );
00689 }
00690 } else if ( name == d->mAttributes[ "formattedName" ].toLower() ) {
00691 d->mAddr.setFormattedName( QString::fromUtf8( value, value.size() ) );
00692 } else if ( name == d->mAttributes[ "givenName" ].toLower() ) {
00693 d->mAddr.setGivenName( QString::fromUtf8( value, value.size() ) );
00694 } else if ( name == d->mAttributes[ "mail" ].toLower() ) {
00695 d->mAddr.insertEmail( QString::fromUtf8( value, value.size() ), true );
00696 } else if ( name == d->mAttributes[ "mailAlias" ].toLower() ) {
00697 d->mAddr.insertEmail( QString::fromUtf8( value, value.size() ), false );
00698 } else if ( name == d->mAttributes[ "phoneNumber" ].toLower() ) {
00699 PhoneNumber phone;
00700 phone.setNumber( QString::fromUtf8( value, value.size() ) );
00701 d->mAddr.insertPhoneNumber( phone );
00702 } else if ( name == d->mAttributes[ "telephoneNumber" ].toLower() ) {
00703 PhoneNumber phone( QString::fromUtf8( value, value.size() ),
00704 PhoneNumber::Work );
00705 d->mAddr.insertPhoneNumber( phone );
00706 } else if ( name == d->mAttributes[ "facsimileTelephoneNumber" ].toLower() ) {
00707 PhoneNumber phone( QString::fromUtf8( value, value.size() ),
00708 PhoneNumber::Fax );
00709 d->mAddr.insertPhoneNumber( phone );
00710 } else if ( name == d->mAttributes[ "mobile" ].toLower() ) {
00711 PhoneNumber phone( QString::fromUtf8( value, value.size() ),
00712 PhoneNumber::Cell );
00713 d->mAddr.insertPhoneNumber( phone );
00714 } else if ( name == d->mAttributes[ "pager" ].toLower() ) {
00715 PhoneNumber phone( QString::fromUtf8( value, value.size() ),
00716 PhoneNumber::Pager );
00717 d->mAddr.insertPhoneNumber( phone );
00718 } else if ( name == d->mAttributes[ "description" ].toLower() ) {
00719 d->mAddr.setNote( QString::fromUtf8( value, value.size() ) );
00720 } else if ( name == d->mAttributes[ "title" ].toLower() ) {
00721 d->mAddr.setTitle( QString::fromUtf8( value, value.size() ) );
00722 } else if ( name == d->mAttributes[ "street" ].toLower() ) {
00723 d->mAd.setStreet( QString::fromUtf8( value, value.size() ) );
00724 } else if ( name == d->mAttributes[ "state" ].toLower() ) {
00725 d->mAd.setRegion( QString::fromUtf8( value, value.size() ) );
00726 } else if ( name == d->mAttributes[ "city" ].toLower() ) {
00727 d->mAd.setLocality( QString::fromUtf8( value, value.size() ) );
00728 } else if ( name == d->mAttributes[ "postalcode" ].toLower() ) {
00729 d->mAd.setPostalCode( QString::fromUtf8( value, value.size() ) );
00730 } else if ( name == d->mAttributes[ "organization" ].toLower() ) {
00731 d->mAddr.setOrganization( QString::fromUtf8( value, value.size() ) );
00732 } else if ( name == d->mAttributes[ "familyName" ].toLower() ) {
00733 d->mAddr.setFamilyName( QString::fromUtf8( value, value.size() ) );
00734 } else if ( name == d->mAttributes[ "uid" ].toLower() ) {
00735 d->mAddr.setUid( QString::fromUtf8( value, value.size() ) );
00736 } else if ( name == d->mAttributes[ "jpegPhoto" ].toLower() ) {
00737 KABC::Picture photo;
00738 QImage img = QImage::fromData( value );
00739 if ( !img.isNull() ) {
00740 photo.setData( img );
00741 photo.setType( "image/jpeg" );
00742 d->mAddr.setPhoto( photo );
00743 }
00744 }
00745
00746 break;
00747 case KLDAP::Ldif::EndEntry:
00748 {
00749 d->mAddr.setResource( this );
00750 d->mAddr.insertAddress( d->mAd );
00751 d->mAddr.setChanged( false );
00752 insertAddressee( d->mAddr );
00753
00754 d->mAddr = Addressee();
00755 d->mAd = Address( Address::Home );
00756 }
00757 break;
00758 default:
00759 break;
00760 }
00761 } while ( ret != KLDAP::Ldif::MoreData );
00762 }
00763
00764 void ResourceLDAPKIO::loadCacheResult( KJob *job )
00765 {
00766 d->mErrorMsg.clear();
00767 d->mError = job->error();
00768 if ( d->mError && d->mError != KIO::ERR_USER_CANCELED ) {
00769 d->mErrorMsg = job->errorString();
00770 }
00771 if ( !d->mErrorMsg.isEmpty() ) {
00772 emit loadingError( this, d->mErrorMsg );
00773 } else {
00774 emit loadingFinished( this );
00775 }
00776 }
00777
00778 void ResourceLDAPKIO::result( KJob *job )
00779 {
00780 d->mErrorMsg.clear();
00781 if ( job ) {
00782 d->mError = job->error();
00783 if ( d->mError && d->mError != KIO::ERR_USER_CANCELED ) {
00784 d->mErrorMsg = job->errorString();
00785 }
00786 } else {
00787 d->mError = 0;
00788 }
00789 d->activateCache();
00790
00791 KIO::Job *cjob;
00792 cjob = d->loadFromCache();
00793 if ( cjob ) {
00794 connect( cjob, SIGNAL( result( KJob* ) ),
00795 this, SLOT( loadCacheResult( KJob* ) ) );
00796 } else {
00797 if ( !d->mErrorMsg.isEmpty() ) {
00798 emit loadingError( this, d->mErrorMsg );
00799 } else {
00800 emit loadingFinished( this );
00801 }
00802 }
00803 }
00804
00805 bool ResourceLDAPKIO::save( Ticket *ticket )
00806 {
00807 Q_UNUSED( ticket );
00808 kDebug();
00809
00810 d->mSaveIt = begin();
00811 KIO::Job *job = KIO::put( d->mLDAPUrl, -1, KIO::Overwrite | KIO::HideProgressInfo );
00812 connect( job, SIGNAL( dataReq( KIO::Job*, QByteArray& ) ),
00813 this, SLOT( saveData( KIO::Job*, QByteArray& ) ) );
00814 connect( job, SIGNAL( result( KJob* ) ),
00815 this, SLOT( syncLoadSaveResult( KJob* ) ) );
00816 d->enter_loop();
00817 if ( d->mErrorMsg.isEmpty() ) {
00818 kDebug() << "ResourceLDAPKIO save ok!";
00819 return true;
00820 } else {
00821 kDebug() << "ResourceLDAPKIO finished with error:" << d->mErrorMsg;
00822 addressBook()->error( d->mErrorMsg );
00823 return false;
00824 }
00825 }
00826
00827 bool ResourceLDAPKIO::asyncSave( Ticket *ticket )
00828 {
00829 Q_UNUSED( ticket );
00830 kDebug();
00831 d->mSaveIt = begin();
00832 KIO::Job *job = KIO::put( d->mLDAPUrl, -1, KIO::Overwrite | KIO::HideProgressInfo );
00833 connect( job, SIGNAL( dataReq( KIO::Job*, QByteArray& ) ),
00834 this, SLOT( saveData( KIO::Job*, QByteArray& ) ) );
00835 connect( job, SIGNAL( result( KJob* ) ),
00836 this, SLOT( saveResult( KJob* ) ) );
00837 return true;
00838 }
00839
00840 void ResourceLDAPKIO::syncLoadSaveResult( KJob *job )
00841 {
00842 d->mError = job->error();
00843 if ( d->mError && d->mError != KIO::ERR_USER_CANCELED ) {
00844 d->mErrorMsg = job->errorString();
00845 } else {
00846 d->mErrorMsg.clear();
00847 }
00848 d->activateCache();
00849
00850 emit leaveModality();
00851 }
00852
00853 void ResourceLDAPKIO::saveResult( KJob *job )
00854 {
00855 d->mError = job->error();
00856 if ( d->mError && d->mError != KIO::ERR_USER_CANCELED ) {
00857 emit savingError( this, job->errorString() );
00858 } else {
00859 emit savingFinished( this );
00860 }
00861 }
00862
00863 void ResourceLDAPKIO::saveData( KIO::Job *job, QByteArray &data )
00864 {
00865 Q_UNUSED( job );
00866 while ( d->mSaveIt != end() && !(*d->mSaveIt).changed() ) {
00867 d->mSaveIt++;
00868 }
00869
00870 if ( d->mSaveIt == end() ) {
00871 kDebug() << "ResourceLDAPKIO endData";
00872 data.resize( 0 );
00873 return;
00874 }
00875
00876 kDebug() << "ResourceLDAPKIO saveData:" << (*d->mSaveIt).assembledName();
00877
00878 d->AddresseeToLDIF( data, *d->mSaveIt, d->findUid( (*d->mSaveIt).uid() ) );
00879
00880
00881 (*d->mSaveIt).setChanged( false );
00882
00883 d->mSaveIt++;
00884 }
00885
00886 void ResourceLDAPKIO::removeAddressee( const Addressee &addr )
00887 {
00888 QString dn = d->findUid( addr.uid() );
00889
00890 kDebug() << dn;
00891
00892 if ( !d->mErrorMsg.isEmpty() ) {
00893 addressBook()->error( d->mErrorMsg );
00894 return;
00895 }
00896 if ( !dn.isEmpty() ) {
00897 kDebug() << "ResourceLDAPKIO: found uid:" << dn;
00898 KLDAP::LdapUrl url( d->mLDAPUrl );
00899 url.setPath( '/' + dn );
00900 url.setExtension( "x-dir", "base" );
00901 url.setScope( KLDAP::LdapUrl::Base );
00902 if ( KIO::NetAccess::del( url, 0 ) ) {
00903 mAddrMap.remove( addr.uid() );
00904 }
00905 } else {
00906
00907 mAddrMap.remove( addr.uid() );
00908 }
00909 }
00910
00911 void ResourceLDAPKIO::setUser( const QString &user )
00912 {
00913 d->mUser = user;
00914 }
00915
00916 QString ResourceLDAPKIO::user() const
00917 {
00918 return d->mUser;
00919 }
00920
00921 void ResourceLDAPKIO::setPassword( const QString &password )
00922 {
00923 d->mPassword = password;
00924 }
00925
00926 QString ResourceLDAPKIO::password() const
00927 {
00928 return d->mPassword;
00929 }
00930
00931 void ResourceLDAPKIO::setDn( const QString &dn )
00932 {
00933 d->mDn = dn;
00934 }
00935
00936 QString ResourceLDAPKIO::dn() const
00937 {
00938 return d->mDn;
00939 }
00940
00941 void ResourceLDAPKIO::setHost( const QString &host )
00942 {
00943 d->mHost = host;
00944 }
00945
00946 QString ResourceLDAPKIO::host() const
00947 {
00948 return d->mHost;
00949 }
00950
00951 void ResourceLDAPKIO::setPort( int port )
00952 {
00953 d->mPort = port;
00954 }
00955
00956 int ResourceLDAPKIO::port() const
00957 {
00958 return d->mPort;
00959 }
00960
00961 void ResourceLDAPKIO::setVer( int ver )
00962 {
00963 d->mVer = ver;
00964 }
00965
00966 int ResourceLDAPKIO::ver() const
00967 {
00968 return d->mVer;
00969 }
00970
00971 void ResourceLDAPKIO::setSizeLimit( int sizelimit )
00972 {
00973 d->mSizeLimit = sizelimit;
00974 }
00975
00976 int ResourceLDAPKIO::sizeLimit()
00977 {
00978 return d->mSizeLimit;
00979 }
00980
00981 void ResourceLDAPKIO::setTimeLimit( int timelimit )
00982 {
00983 d->mTimeLimit = timelimit;
00984 }
00985
00986 int ResourceLDAPKIO::timeLimit()
00987 {
00988 return d->mTimeLimit;
00989 }
00990
00991 void ResourceLDAPKIO::setFilter( const QString &filter )
00992 {
00993 d->mFilter = filter;
00994 }
00995
00996 QString ResourceLDAPKIO::filter() const
00997 {
00998 return d->mFilter;
00999 }
01000
01001 void ResourceLDAPKIO::setIsAnonymous( bool value )
01002 {
01003 d->mAnonymous = value;
01004 }
01005
01006 bool ResourceLDAPKIO::isAnonymous() const
01007 {
01008 return d->mAnonymous;
01009 }
01010
01011 void ResourceLDAPKIO::setIsTLS( bool value )
01012 {
01013 d->mTLS = value;
01014 }
01015
01016 bool ResourceLDAPKIO::isTLS() const
01017 {
01018 return d->mTLS;
01019 }
01020 void ResourceLDAPKIO::setIsSSL( bool value )
01021 {
01022 d->mSSL = value;
01023 }
01024
01025 bool ResourceLDAPKIO::isSSL() const
01026 {
01027 return d->mSSL;
01028 }
01029
01030 void ResourceLDAPKIO::setIsSubTree( bool value )
01031 {
01032 d->mSubTree = value;
01033 }
01034
01035 bool ResourceLDAPKIO::isSubTree() const
01036 {
01037 return d->mSubTree;
01038 }
01039
01040 void ResourceLDAPKIO::setAttributes( const QMap<QString, QString> &attributes )
01041 {
01042 d->mAttributes = attributes;
01043 }
01044
01045 QMap<QString, QString> ResourceLDAPKIO::attributes() const
01046 {
01047 return d->mAttributes;
01048 }
01049
01050 void ResourceLDAPKIO::setRDNPrefix( int value )
01051 {
01052 d->mRDNPrefix = value;
01053 }
01054
01055 int ResourceLDAPKIO::RDNPrefix() const
01056 {
01057 return d->mRDNPrefix;
01058 }
01059
01060 void ResourceLDAPKIO::setIsSASL( bool value )
01061 {
01062 d->mSASL = value;
01063 }
01064
01065 bool ResourceLDAPKIO::isSASL() const
01066 {
01067 return d->mSASL;
01068 }
01069
01070 void ResourceLDAPKIO::setMech( const QString &mech )
01071 {
01072 d->mMech = mech;
01073 }
01074
01075 QString ResourceLDAPKIO::mech() const
01076 {
01077 return d->mMech;
01078 }
01079
01080 void ResourceLDAPKIO::setRealm( const QString &realm )
01081 {
01082 d->mRealm = realm;
01083 }
01084
01085 QString ResourceLDAPKIO::realm() const
01086 {
01087 return d->mRealm;
01088 }
01089
01090 void ResourceLDAPKIO::setBindDN( const QString &binddn )
01091 {
01092 d->mBindDN = binddn;
01093 }
01094
01095 QString ResourceLDAPKIO::bindDN() const
01096 {
01097 return d->mBindDN;
01098 }
01099
01100 void ResourceLDAPKIO::setCachePolicy( int pol )
01101 {
01102 d->mCachePolicy = pol;
01103 }
01104
01105 int ResourceLDAPKIO::cachePolicy() const
01106 {
01107 return d->mCachePolicy;
01108 }
01109
01110 void ResourceLDAPKIO::setAutoCache( bool value )
01111 {
01112 d->mAutoCache = value;
01113 }
01114
01115 bool ResourceLDAPKIO::autoCache()
01116 {
01117 return d->mAutoCache;
01118 }
01119
01120 QString ResourceLDAPKIO::cacheDst() const
01121 {
01122 return d->mCacheDst;
01123 }
01124
01125 #include "resourceldapkio.moc"