/* * networkaccount.cpp * * Copyright (c) 2000-2002 Michael Haeckel * Copyright (c) 2002 Marc Mutz * * This file is based on work on pop3 and imap account implementations * by Don Sanders and Michael Haeckel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include "networkaccount.h" #include "accountmanager.h" #include "kmkernel.h" #include "globalsettings.h" #include #include #include #include #include #include using TDEIO::MetaData; using TDEWallet::Wallet; #include namespace KMail { // for restricting number of concurrent connections to the same server static TQMap s_serverConnections; NetworkAccount::NetworkAccount( AccountManager * parent, const TQString & name, uint id ) : KMAccount( parent, name, id ), mSlave( 0 ), mAuth( "*" ), mPort( 0 ), mStorePasswd( false ), mUseSSL( false ), mUseTLS( false ), mAskAgain( false ), mPasswdDirty( false ), mStorePasswdInConfig( false ) { } NetworkAccount::~NetworkAccount() { } void NetworkAccount::init() { KMAccount::init(); mSieveConfig = SieveConfig(); mLogin = TQString(); mPasswd = TQString(); mAuth = "*"; mHost = TQString(); mPort = defaultPort(); mStorePasswd = false; mUseSSL = false; mUseTLS = false; mAskAgain = false; } // // // Getters and Setters // // void NetworkAccount::setLogin( const TQString & login ) { mLogin = login; } TQString NetworkAccount::passwd() const { if ( storePasswd() && mPasswd.isEmpty() ) mOwner->readPasswords(); return decryptStr( mPasswd ); } void NetworkAccount::setPasswd( const TQString & passwd, bool storeInConfig ) { if ( mPasswd != encryptStr( passwd ) ) { mPasswd = encryptStr( passwd ); mPasswdDirty = true; } setStorePasswd( storeInConfig ); } void NetworkAccount::clearPasswd() { setPasswd( "", false ); } void NetworkAccount::setAuth( const TQString & auth ) { mAuth = auth; } void NetworkAccount::setStorePasswd( bool store ) { if( mStorePasswd != store && store ) mPasswdDirty = true; mStorePasswd = store; } void NetworkAccount::setHost( const TQString & host ) { mHost = host; } void NetworkAccount::setPort( unsigned short int port ) { mPort = port; } void NetworkAccount::setUseSSL( bool use ) { mUseSSL = use; } void NetworkAccount::setUseTLS( bool use ) { mUseTLS = use; } void NetworkAccount::setSieveConfig( const SieveConfig & config ) { mSieveConfig = config; } // // // read/write config // // void NetworkAccount::readConfig( /*const*/ TDEConfig/*Base*/ & config ) { KMAccount::readConfig( config ); setLogin( config.readEntry( "login" ) ); if ( config.readNumEntry( "store-passwd", false ) ) { // ### s/Num/Bool/ mStorePasswd = true; TQString encpasswd = config.readEntry( "pass" ); if ( encpasswd.isEmpty() ) { encpasswd = config.readEntry( "passwd" ); if ( !encpasswd.isEmpty() ) encpasswd = importPassword( encpasswd ); } if ( !encpasswd.isEmpty() ) { setPasswd( decryptStr( encpasswd ), true ); // migrate to TDEWallet if available if ( Wallet::isEnabled() ) { config.deleteEntry( "pass" ); config.deleteEntry( "passwd" ); mPasswdDirty = true; mStorePasswdInConfig = false; } else { mPasswdDirty = false; // set by setPasswd() on first read mStorePasswdInConfig = true; } } else { // read password if wallet is already open, otherwise defer to on-demand loading if ( Wallet::isOpen( Wallet::NetworkWallet() ) ) readPassword(); } } else { setPasswd( "", false ); } setHost( config.readEntry( "host" ) ); unsigned int port = config.readUnsignedNumEntry( "port", defaultPort() ); if ( port > USHRT_MAX ) port = defaultPort(); setPort( port ); setAuth( config.readEntry( "auth", "*" ) ); setUseSSL( config.readBoolEntry( "use-ssl", false ) ); setUseTLS( config.readBoolEntry( "use-tls", false ) ); mSieveConfig.readConfig( config ); } void NetworkAccount::writeConfig( TDEConfig/*Base*/ & config ) /*const*/ { KMAccount::writeConfig( config ); config.writeEntry( "login", login() ); config.writeEntry( "store-passwd", storePasswd() ); if ( storePasswd() ) { // write password to the wallet if possbile and necessary bool passwdStored = false; if ( mPasswdDirty ) { Wallet *wallet = kmkernel->wallet(); if ( wallet && wallet->writePassword( "account-" + TQString::number(mId), passwd() ) == 0 ) { passwdStored = true; mPasswdDirty = false; mStorePasswdInConfig = false; } } else { passwdStored = !mStorePasswdInConfig; // already in the wallet } // if wallet is not available, write to config file, since the account // manager deletes this group, we need to write it always if ( !passwdStored && ( mStorePasswdInConfig || KMessageBox::warningYesNo( 0, i18n("TDEWallet is not available. It is strongly recommended to use " "TDEWallet for managing your passwords.\n" "However, KMail can store the password in its configuration " "file instead. The password is stored in an obfuscated format, " "but should not be considered secure from decryption efforts " "if access to the configuration file is obtained.\n" "Do you want to store the password for account '%1' in the " "configuration file?").arg( name() ), i18n("TDEWallet Not Available"), KGuiItem( i18n("Store Password") ), KGuiItem( i18n("Do Not Store Password") ) ) == KMessageBox::Yes ) ) { config.writeEntry( "pass", encryptStr( passwd() ) ); mStorePasswdInConfig = true; } } // delete password from the wallet if password storage is disabled if (!storePasswd() && !Wallet::keyDoesNotExist( Wallet::NetworkWallet(), "kmail", "account-" + TQString::number(mId))) { Wallet *wallet = kmkernel->wallet(); if (wallet) wallet->removeEntry( "account-" + TQString::number(mId) ); } config.writeEntry( "host", host() ); config.writeEntry( "port", static_cast( port() ) ); config.writeEntry( "auth", auth() ); config.writeEntry( "use-ssl", useSSL() ); config.writeEntry( "use-tls", useTLS() ); mSieveConfig.writeConfig( config ); } // // // Network processing // // KURL NetworkAccount::getUrl() const { KURL url; url.setProtocol( protocol() ); url.setUser( login() ); url.setPass( passwd() ); url.setHost( host() ); url.setPort( port() ); return url; } MetaData NetworkAccount::slaveConfig() const { MetaData m; m.insert( "tls", useTLS() ? "on" : "off" ); return m; } void NetworkAccount::pseudoAssign( const KMAccount * a ) { KMAccount::pseudoAssign( a ); const NetworkAccount * n = dynamic_cast( a ); if ( !n ) return; setLogin( n->login() ); setPasswd( n->passwd(), n->storePasswd() ); setHost( n->host() ); setPort( n->port() ); setAuth( n->auth() ); setUseSSL( n->useSSL() ); setUseTLS( n->useTLS() ); setSieveConfig( n->sieveConfig() ); } void NetworkAccount::readPassword() { if ( !storePasswd() ) return; // ### workaround for broken Wallet::keyDoesNotExist() which returns wrong // results for new entries without closing and reopening the wallet if ( Wallet::isOpen( Wallet::NetworkWallet() ) ) { Wallet *wallet = kmkernel->wallet(); if (!wallet || !wallet->hasEntry( "account-" + TQString::number(mId) ) ) return; } else { if (Wallet::keyDoesNotExist( Wallet::NetworkWallet(), "kmail", "account-" + TQString::number(mId) ) ) return; } if ( kmkernel->wallet() ) { TQString passwd; kmkernel->wallet()->readPassword( "account-" + TQString::number(mId), passwd ); setPasswd( passwd, true ); mPasswdDirty = false; } } void NetworkAccount::setCheckingMail( bool checking ) { mCheckingMail = checking; if ( host().isEmpty() ) return; if ( checking ) { if ( s_serverConnections.find( host() ) != s_serverConnections.end() ) s_serverConnections[host()] += 1; else s_serverConnections[host()] = 1; kdDebug(5006) << "check mail started - connections for host " << host() << " now is " << s_serverConnections[host()] << endl; } else { if ( s_serverConnections.find( host() ) != s_serverConnections.end() && s_serverConnections[host()] > 0 ) { s_serverConnections[host()] -= 1; kdDebug(5006) << "connections to server " << host() << " now " << s_serverConnections[host()] << endl; } } } bool NetworkAccount::mailCheckCanProceed() const { bool offlineMode = KMKernel::isOffline(); kdDebug(5006) << "for host " << host() << " current connections=" << (s_serverConnections.find(host())==s_serverConnections.end() ? 0 : s_serverConnections[host()]) << " and limit is " << GlobalSettings::self()->maxConnectionsPerHost() << endl; bool connectionLimitForHostReached = !host().isEmpty() && GlobalSettings::self()->maxConnectionsPerHost() > 0 && s_serverConnections.find( host() ) != s_serverConnections.end() && s_serverConnections[host()] >= GlobalSettings::self()->maxConnectionsPerHost(); kdDebug(5006) << "connection limit reached: " << connectionLimitForHostReached << endl; return ( !connectionLimitForHostReached && !offlineMode ); } void NetworkAccount::resetConnectionList( NetworkAccount* acct ) { s_serverConnections[ acct->host() ] = 0; } } // namespace KMail #include "networkaccount.moc"