• Skip to content
  • Skip to link menu
KDE 4.5 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

mailtransport

transport.cpp

00001 /*
00002     Copyright (c) 2006 - 2007 Volker Krause <vkrause@kde.org>
00003 
00004     This library is free software; you can redistribute it and/or modify it
00005     under the terms of the GNU Library General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or (at your
00007     option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful, but WITHOUT
00010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00012     License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to the
00016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017     02110-1301, USA.
00018 */
00019 
00020 #include "transport.h"
00021 #include "legacydecrypt.h"
00022 #include "mailtransport_defs.h"
00023 #include "transportmanager.h"
00024 #include "transporttype_p.h"
00025 
00026 #include <QTimer>
00027 
00028 #include <KConfigGroup>
00029 #include <KDebug>
00030 #include <KLocalizedString>
00031 #include <KMessageBox>
00032 #include <KStringHandler>
00033 #include <KWallet/Wallet>
00034 
00035 #include <akonadi/agentinstance.h>
00036 #include <akonadi/agentmanager.h>
00037 
00038 using namespace MailTransport;
00039 using namespace KWallet;
00040 
00045 class TransportPrivate
00046 {
00047   public:
00048     TransportType transportType;
00049     QString password;
00050     bool passwordLoaded;
00051     bool passwordDirty;
00052     bool storePasswordInFile;
00053     bool needsWalletMigration;
00054     QString oldName;
00055 };
00056 
00057 Transport::Transport( const QString &cfgGroup ) :
00058     TransportBase( cfgGroup ), d( new TransportPrivate )
00059 {
00060   kDebug() << cfgGroup;
00061   d->passwordLoaded = false;
00062   d->passwordDirty = false;
00063   d->storePasswordInFile = false;
00064   d->needsWalletMigration = false;
00065   readConfig();
00066 }
00067 
00068 Transport::~Transport()
00069 {
00070   delete d;
00071 }
00072 
00073 bool Transport::isValid() const
00074 {
00075   return ( id() > 0 ) && !host().isEmpty() && port() <= 65536;
00076 }
00077 
00078 QString Transport::password()
00079 {
00080   if ( !d->passwordLoaded && requiresAuthentication() && storePassword() &&
00081        d->password.isEmpty() ) {
00082     TransportManager::self()->loadPasswords();
00083     d->password = TransportManager::self()->transportById( id(), false )->password();
00084   }
00085   return d->password;
00086 }
00087 
00088 void Transport::setPassword( const QString &passwd )
00089 {
00090   d->passwordLoaded = true;
00091   if ( d->password == passwd ) {
00092     return;
00093   }
00094   d->passwordDirty = true;
00095   d->password = passwd;
00096 }
00097 
00098 void Transport::forceUniqueName()
00099 {
00100   QStringList existingNames;
00101   foreach ( Transport *t, TransportManager::self()->transports() ) {
00102     if ( t->id() != id() ) {
00103       existingNames << t->name();
00104     }
00105   }
00106   int suffix = 1;
00107   QString origName = name();
00108   while ( existingNames.contains( name() ) ) {
00109     setName( i18nc( "%1: name; %2: number appended to it to make "
00110                     "it unique among a list of names", "%1 #%2", origName, suffix ) );
00111     ++suffix;
00112   }
00113 
00114 }
00115 
00116 void Transport::updatePasswordState()
00117 {
00118   Transport *original = TransportManager::self()->transportById( id(), false );
00119   if ( original == this ) {
00120     kWarning() << "Tried to update password state of non-cloned transport.";
00121     return;
00122   }
00123   if ( original ) {
00124     d->password = original->d->password;
00125     d->passwordLoaded = original->d->passwordLoaded;
00126     d->passwordDirty = original->d->passwordDirty;
00127   } else {
00128     kWarning() << "Transport with this ID not managed by transport manager.";
00129   }
00130 }
00131 
00132 bool Transport::isComplete() const
00133 {
00134   return !requiresAuthentication() || !storePassword() || d->passwordLoaded;
00135 }
00136 
00137 QString Transport::authenticationTypeString() const
00138 {
00139   return Transport::authenticationTypeString( authenticationType() );
00140 }
00141 
00142 QString Transport::authenticationTypeString( int type )
00143 {
00144   switch ( type ) {
00145     case EnumAuthenticationType::LOGIN:
00146       return QLatin1String( "LOGIN" );
00147     case EnumAuthenticationType::PLAIN:
00148       return QLatin1String( "PLAIN" );
00149     case EnumAuthenticationType::CRAM_MD5:
00150       return QLatin1String( "CRAM-MD5" );
00151     case EnumAuthenticationType::DIGEST_MD5:
00152       return QLatin1String( "DIGEST-MD5" );
00153     case EnumAuthenticationType::NTLM:
00154       return QLatin1String( "NTLM" );
00155     case EnumAuthenticationType::GSSAPI:
00156       return QLatin1String( "GSSAPI" );
00157     case EnumAuthenticationType::CLEAR:
00158       return i18nc( "Authentication method", "Clear text" );
00159     case EnumAuthenticationType::APOP:
00160       return QLatin1String( "APOP" );
00161     case EnumAuthenticationType::ANONYMOUS:
00162       return i18nc( "Authentication method", "Anonymous" );
00163   }
00164   Q_ASSERT( false );
00165   return QString();
00166 }
00167 
00168 void Transport::usrReadConfig()
00169 {
00170   TransportBase::usrReadConfig();
00171 
00172   setHost( host().trimmed() );
00173 
00174   if ( d->oldName.isEmpty() ) {
00175     d->oldName = name();
00176   }
00177 
00178   // Set TransportType.
00179   {
00180     using namespace Akonadi;
00181     d->transportType = TransportType();
00182     d->transportType.d->mType = type();
00183     kDebug() << "type" << type();
00184     if ( type() == EnumType::Akonadi ) {
00185       const AgentInstance instance = AgentManager::self()->instance( host() );
00186       if ( !instance.isValid() ) {
00187         kWarning() << "Akonadi transport with invalid resource instance.";
00188       }
00189       d->transportType.d->mAgentType = instance.type();
00190       kDebug() << "agent type" << instance.type().name() << "id" << instance.type().identifier();
00191     }
00192     // Now we have the type and possibly agentType.  Get the name, description
00193     // etc. from TransportManager.
00194     const TransportType::List &types = TransportManager::self()->types();
00195     int index = types.indexOf( d->transportType );
00196     if ( index != -1 ) {
00197       d->transportType = types[ index ];
00198     } else {
00199       kWarning() << "Type unknown to manager.";
00200       d->transportType.d->mName = i18nc( "An unknown transport type", "Unknown" );
00201     }
00202   }
00203 
00204   // we have everything we need
00205   if ( !storePassword() || d->passwordLoaded ) {
00206     return;
00207   }
00208 
00209   // try to find a password in the config file otherwise
00210   KConfigGroup group( config(), currentGroup() );
00211   if ( group.hasKey( "password" ) ) {
00212     d->password = KStringHandler::obscure( group.readEntry( "password" ) );
00213   } else if ( group.hasKey( "password-kmail" ) ) {
00214     d->password = Legacy::decryptKMail( group.readEntry( "password-kmail" ) );
00215   } else if ( group.hasKey( "password-knode" ) ) {
00216     d->password = Legacy::decryptKNode( group.readEntry( "password-knode" ) );
00217   }
00218 
00219   if ( !d->password.isEmpty() ) {
00220     d->passwordLoaded = true;
00221     if ( Wallet::isEnabled() ) {
00222       d->needsWalletMigration = true;
00223     } else {
00224       d->storePasswordInFile = true;
00225     }
00226   } else {
00227     // read password if wallet is open, defer otherwise
00228     if ( Wallet::isOpen( Wallet::NetworkWallet() ) ) {
00229       // Don't read the password right away because this can lead
00230       // to reentrancy problems in KDBusServiceStarter when an application
00231       // run in Kontact creates the transports (due to a QEventLoop in the
00232       // synchronous KWallet openWallet call).
00233       QTimer::singleShot( 0, this, SLOT(readPassword()) );
00234     }
00235   }
00236 }
00237 
00238 void Transport::usrWriteConfig()
00239 {
00240   if ( requiresAuthentication() && storePassword() && d->passwordDirty ) {
00241     Wallet *wallet = TransportManager::self()->wallet();
00242     if ( !wallet || wallet->writePassword( QString::number( id() ), d->password ) != 0 ) {
00243       // wallet saving failed, ask if we should store in the config file instead
00244       if ( d->storePasswordInFile || KMessageBox::warningYesNo(
00245              0,
00246              i18n( "KWallet is not available. It is strongly recommended to use "
00247                    "KWallet for managing your passwords.\n"
00248                    "However, the password can be stored in the configuration "
00249                    "file instead. The password is stored in an obfuscated format, "
00250                    "but should not be considered secure from decryption efforts "
00251                    "if access to the configuration file is obtained.\n"
00252                    "Do you want to store the password for server '%1' in the "
00253                    "configuration file?", name() ),
00254              i18n( "KWallet Not Available" ),
00255              KGuiItem( i18n( "Store Password" ) ),
00256              KGuiItem( i18n( "Do Not Store Password" ) ) ) == KMessageBox::Yes ) {
00257         // write to config file
00258         KConfigGroup group( config(), currentGroup() );
00259         group.writeEntry( "password", KStringHandler::obscure( d->password ) );
00260         d->storePasswordInFile = true;
00261       }
00262     }
00263     d->passwordDirty = false;
00264   }
00265 
00266   TransportBase::usrWriteConfig();
00267   TransportManager::self()->emitChangesCommitted();
00268   if ( name() != d->oldName ) {
00269     emit TransportManager::self()->transportRenamed( id(), d->oldName, name() );
00270     d->oldName = name();
00271   }
00272 }
00273 
00274 void Transport::readPassword()
00275 {
00276   // no need to load a password if the account doesn't require auth
00277   if ( !requiresAuthentication() ) {
00278     return;
00279   }
00280   d->passwordLoaded = true;
00281 
00282   // check whether there is a chance to find our password at all
00283   if ( Wallet::folderDoesNotExist( Wallet::NetworkWallet(), WALLET_FOLDER ) ||
00284        Wallet::keyDoesNotExist( Wallet::NetworkWallet(), WALLET_FOLDER,
00285                                 QString::number( id() ) ) ) {
00286     // try migrating password from kmail
00287     if ( Wallet::folderDoesNotExist( Wallet::NetworkWallet(), KMAIL_WALLET_FOLDER ) ||
00288          Wallet::keyDoesNotExist( Wallet::NetworkWallet(), KMAIL_WALLET_FOLDER,
00289                                   QString::fromLatin1( "transport-%1" ).arg( id() ) ) ) {
00290       return;
00291     }
00292     kDebug() << "migrating password from kmail wallet";
00293     KWallet::Wallet *wallet = TransportManager::self()->wallet();
00294     if ( wallet ) {
00295       wallet->setFolder( KMAIL_WALLET_FOLDER );
00296       wallet->readPassword( QString::fromLatin1( "transport-%1" ).arg( id() ), d->password );
00297       wallet->removeEntry( QString::fromLatin1( "transport-%1" ).arg( id() ) );
00298       wallet->setFolder( WALLET_FOLDER );
00299       d->passwordDirty = true;
00300       writeConfig();
00301     }
00302     return;
00303   }
00304 
00305   // finally try to open the wallet and read the password
00306   KWallet::Wallet *wallet = TransportManager::self()->wallet();
00307   if ( wallet ) {
00308     wallet->readPassword( QString::number( id() ), d->password );
00309   }
00310 }
00311 
00312 bool Transport::needsWalletMigration() const
00313 {
00314   return d->needsWalletMigration;
00315 }
00316 
00317 void Transport::migrateToWallet()
00318 {
00319   kDebug() << "migrating" << id() << "to wallet";
00320   d->needsWalletMigration = false;
00321   KConfigGroup group( config(), currentGroup() );
00322   group.deleteEntry( "password" );
00323   group.deleteEntry( "password-kmail" );
00324   group.deleteEntry( "password-knode" );
00325   d->passwordDirty = true;
00326   d->storePasswordInFile = false;
00327   writeConfig();
00328 }
00329 
00330 Transport *Transport::clone() const
00331 {
00332   QString id = currentGroup().mid( 10 );
00333   return new Transport( id );
00334 }
00335 
00336 TransportType Transport::transportType() const
00337 {
00338   if ( !d->transportType.isValid() ) {
00339     kWarning() << "Invalid transport type.";
00340   }
00341   return d->transportType;
00342 }
00343 
00344 void Transport::setTransportType( const TransportType &type )
00345 {
00346   Q_ASSERT( type.isValid() );
00347   d->transportType = type;
00348   setType( type.type() );
00349 }
00350 
00351 #include "transport.moc"

mailtransport

Skip menu "mailtransport"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kblog
  • kcal
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.7.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal