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

KDE's Doxygen guidelines are available online.

mailtransport

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

kdepimlibs-4.8.3 API Reference

Skip menu "kdepimlibs-4.8.3 API Reference"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal