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