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