mailtransport
transport.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "transport.h"
00021 #include "transportmanager.h"
00022 #include "mailtransport_defs.h"
00023 #include "legacydecrypt.h"
00024
00025 #include <kdebug.h>
00026 #include <klocale.h>
00027 #include <kmessagebox.h>
00028 #include <kstringhandler.h>
00029 #include <kwallet.h>
00030 #include <kconfiggroup.h>
00031
00032 using namespace MailTransport;
00033 using namespace KWallet;
00034
00039 class TransportPrivate
00040 {
00041 public:
00042 QString password;
00043 bool passwordLoaded;
00044 bool passwordDirty;
00045 bool storePasswordInFile;
00046 bool needsWalletMigration;
00047 QString oldName;
00048 };
00049
00050 Transport::Transport( const QString &cfgGroup ) :
00051 TransportBase( cfgGroup ), d( new TransportPrivate )
00052 {
00053 kDebug() << cfgGroup;
00054 d->passwordLoaded = false;
00055 d->passwordDirty = false;
00056 d->storePasswordInFile = false;
00057 d->needsWalletMigration = false;
00058 readConfig();
00059 }
00060
00061 Transport::~Transport()
00062 {
00063 delete d;
00064 }
00065
00066 bool Transport::isValid() const
00067 {
00068 return ( id() > 0 ) && !host().isEmpty() && port() <= 65536;
00069 }
00070
00071 QString Transport::password()
00072 {
00073 if ( !d->passwordLoaded && requiresAuthentication() && storePassword() &&
00074 d->password.isEmpty() ) {
00075 TransportManager::self()->loadPasswords();
00076 d->password = TransportManager::self()->transportById( id(), false )->password();
00077 }
00078 return d->password;
00079 }
00080
00081 void Transport::setPassword( const QString &passwd )
00082 {
00083 d->passwordLoaded = true;
00084 if ( d->password == passwd ) {
00085 return;
00086 }
00087 d->passwordDirty = true;
00088 d->password = passwd;
00089 }
00090
00091 void Transport::updatePasswordState()
00092 {
00093 Transport *original = TransportManager::self()->transportById( id(), false );
00094 if ( original == this ) {
00095 kWarning() << "Tried to update password state of non-cloned transport.";
00096 return;
00097 }
00098 if ( original ) {
00099 d->password = original->d->password;
00100 d->passwordLoaded = original->d->passwordLoaded;
00101 d->passwordDirty = original->d->passwordDirty;
00102 }
00103 else
00104 kWarning() << "Transport with this ID not managed by transport manager.";
00105 }
00106
00107 bool Transport::isComplete() const
00108 {
00109 return !requiresAuthentication() || !storePassword() || d->passwordLoaded;
00110 }
00111
00112 QString Transport::authenticationTypeString() const
00113 {
00114 switch ( authenticationType() ) {
00115 case EnumAuthenticationType::LOGIN:
00116 return QLatin1String( "LOGIN" );
00117 case EnumAuthenticationType::PLAIN:
00118 return QLatin1String( "PLAIN" );
00119 case EnumAuthenticationType::CRAM_MD5:
00120 return QLatin1String( "CRAM-MD5" );
00121 case EnumAuthenticationType::DIGEST_MD5:
00122 return QLatin1String( "DIGEST-MD5" );
00123 case EnumAuthenticationType::NTLM:
00124 return QLatin1String( "NTLM" );
00125 case EnumAuthenticationType::GSSAPI:
00126 return QLatin1String( "GSSAPI" );
00127 }
00128 Q_ASSERT( false );
00129 return QString();
00130 }
00131
00132 void Transport::usrReadConfig()
00133 {
00134 TransportBase::usrReadConfig();
00135
00136 setHost( host().trimmed() );
00137
00138 if ( d->oldName.isEmpty() ) {
00139 d->oldName = name();
00140 }
00141
00142
00143 if ( !storePassword() || d->passwordLoaded ) {
00144 return;
00145 }
00146
00147
00148 KConfigGroup group( config(), currentGroup() );
00149 if ( group.hasKey( "password" ) ) {
00150 d->password = KStringHandler::obscure( group.readEntry( "password" ) );
00151 } else if ( group.hasKey( "password-kmail" ) ) {
00152 d->password = Legacy::decryptKMail( group.readEntry( "password-kmail" ) );
00153 } else if ( group.hasKey( "password-knode" ) ) {
00154 d->password = Legacy::decryptKNode( group.readEntry( "password-knode" ) );
00155 }
00156
00157 if ( !d->password.isEmpty() ) {
00158 d->passwordLoaded = true;
00159 if ( Wallet::isEnabled() ) {
00160 d->needsWalletMigration = true;
00161 } else {
00162 d->storePasswordInFile = true;
00163 }
00164 } else {
00165
00166 if ( Wallet::isOpen( Wallet::NetworkWallet() ) ) {
00167 readPassword();
00168 }
00169 }
00170 }
00171
00172 void Transport::usrWriteConfig()
00173 {
00174 if ( requiresAuthentication() && storePassword() && d->passwordDirty ) {
00175 Wallet *wallet = TransportManager::self()->wallet();
00176 if ( !wallet || wallet->writePassword( QString::number( id() ), d->password ) != 0 ) {
00177
00178 if ( d->storePasswordInFile || KMessageBox::warningYesNo(
00179 0,
00180 i18n( "KWallet is not available. It is strongly recommended to use "
00181 "KWallet for managing your passwords.\n"
00182 "However, the password can be stored in the configuration "
00183 "file instead. The password is stored in an obfuscated format, "
00184 "but should not be considered secure from decryption efforts "
00185 "if access to the configuration file is obtained.\n"
00186 "Do you want to store the password for server '%1' in the "
00187 "configuration file?", name() ),
00188 i18n( "KWallet Not Available" ),
00189 KGuiItem( i18n( "Store Password" ) ),
00190 KGuiItem( i18n( "Do Not Store Password" ) ) ) == KMessageBox::Yes ) {
00191
00192 KConfigGroup group( config(), currentGroup() );
00193 group.writeEntry( "password", KStringHandler::obscure( d->password ) );
00194 d->storePasswordInFile = true;
00195 }
00196 }
00197 d->passwordDirty = false;
00198 }
00199
00200 TransportBase::usrWriteConfig();
00201 TransportManager::self()->emitChangesCommitted();
00202 if ( name() != d->oldName ) {
00203 emit TransportManager::self()->transportRenamed( id(), d->oldName, name() );
00204 d->oldName = name();
00205 }
00206 }
00207
00208 void Transport::readPassword()
00209 {
00210
00211 if ( !requiresAuthentication() ) {
00212 return;
00213 }
00214 d->passwordLoaded = true;
00215
00216
00217 if ( Wallet::folderDoesNotExist( Wallet::NetworkWallet(), WALLET_FOLDER ) ||
00218 Wallet::keyDoesNotExist( Wallet::NetworkWallet(), WALLET_FOLDER,
00219 QString::number( id() ) ) ) {
00220
00221 if ( Wallet::folderDoesNotExist( Wallet::NetworkWallet(), KMAIL_WALLET_FOLDER ) ||
00222 Wallet::keyDoesNotExist( Wallet::NetworkWallet(), KMAIL_WALLET_FOLDER,
00223 QString::fromLatin1( "transport-%1" ).arg( id() ) ) ) {
00224 return;
00225 }
00226 kDebug() << "migrating password from kmail wallet";
00227 KWallet::Wallet *wallet = TransportManager::self()->wallet();
00228 if ( wallet ) {
00229 wallet->setFolder( KMAIL_WALLET_FOLDER );
00230 wallet->readPassword( QString::fromLatin1( "transport-%1" ).arg( id() ), d->password );
00231 wallet->removeEntry( QString::fromLatin1( "transport-%1" ).arg( id() ) );
00232 wallet->setFolder( WALLET_FOLDER );
00233 d->passwordDirty = true;
00234 writeConfig();
00235 }
00236 return;
00237 }
00238
00239
00240 KWallet::Wallet *wallet = TransportManager::self()->wallet();
00241 if ( wallet ) {
00242 wallet->readPassword( QString::number( id() ), d->password );
00243 }
00244 }
00245
00246 bool Transport::needsWalletMigration() const
00247 {
00248 return d->needsWalletMigration;
00249 }
00250
00251 void Transport::migrateToWallet()
00252 {
00253 kDebug() << "migrating" << id() << "to wallet";
00254 d->needsWalletMigration = false;
00255 KConfigGroup group( config(), currentGroup() );
00256 group.deleteEntry( "password" );
00257 d->passwordDirty = true;
00258 d->storePasswordInFile = false;
00259 writeConfig();
00260 }
00261
00262 Transport *Transport::clone() const
00263 {
00264 QString id = currentGroup().mid( 10 );
00265 return new Transport( id );
00266 }