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