resourceldapkio.cpp

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