You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
368 lines
11 KiB
368 lines
11 KiB
15 years ago
|
/** -*- c++ -*-
|
||
|
* networkaccount.cpp
|
||
|
*
|
||
|
* Copyright (c) 2000-2002 Michael Haeckel <haeckel@kde.org>
|
||
|
* Copyright (c) 2002 Marc Mutz <mutz@kde.org>
|
||
|
*
|
||
|
* This file is based on work on pop3 and imap account implementations
|
||
|
* by Don Sanders <sanders@kde.org> and Michael Haeckel <haeckel@kde.org>
|
||
|
*
|
||
|
* 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 <config.h>
|
||
|
#endif
|
||
|
|
||
|
#include "networkaccount.h"
|
||
|
#include "accountmanager.h"
|
||
|
#include "kmkernel.h"
|
||
|
#include "globalsettings.h"
|
||
|
|
||
|
#include <kconfig.h>
|
||
|
#include <kio/global.h>
|
||
|
#include <klocale.h>
|
||
|
#include <kmessagebox.h>
|
||
|
#include <kdebug.h>
|
||
|
#include <kwallet.h>
|
||
|
using KIO::MetaData;
|
||
|
using KWallet::Wallet;
|
||
|
|
||
|
#include <climits>
|
||
|
|
||
|
namespace KMail {
|
||
|
|
||
|
|
||
|
// for restricting number of concurrent connections to the same server
|
||
|
static QMap<QString, int> s_serverConnections;
|
||
|
|
||
|
NetworkAccount::NetworkAccount( AccountManager * parent, const QString & 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 = QString::null;
|
||
|
mPasswd = QString::null;
|
||
|
mAuth = "*";
|
||
|
mHost = QString::null;
|
||
|
mPort = defaultPort();
|
||
|
mStorePasswd = false;
|
||
|
mUseSSL = false;
|
||
|
mUseTLS = false;
|
||
|
mAskAgain = false;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
//
|
||
|
// Getters and Setters
|
||
|
//
|
||
|
//
|
||
|
|
||
|
void NetworkAccount::setLogin( const QString & login ) {
|
||
|
mLogin = login;
|
||
|
}
|
||
|
|
||
|
QString NetworkAccount::passwd() const {
|
||
|
if ( storePasswd() && mPasswd.isEmpty() )
|
||
|
mOwner->readPasswords();
|
||
|
return decryptStr( mPasswd );
|
||
|
}
|
||
|
|
||
|
void NetworkAccount::setPasswd( const QString & passwd, bool storeInConfig ) {
|
||
|
if ( mPasswd != encryptStr( passwd ) ) {
|
||
|
mPasswd = encryptStr( passwd );
|
||
|
mPasswdDirty = true;
|
||
|
}
|
||
|
setStorePasswd( storeInConfig );
|
||
|
}
|
||
|
|
||
|
void NetworkAccount::clearPasswd() {
|
||
|
setPasswd( "", false );
|
||
|
}
|
||
|
|
||
|
void NetworkAccount::setAuth( const QString & auth ) {
|
||
|
mAuth = auth;
|
||
|
}
|
||
|
|
||
|
void NetworkAccount::setStorePasswd( bool store ) {
|
||
|
if( mStorePasswd != store && store )
|
||
|
mPasswdDirty = true;
|
||
|
mStorePasswd = store;
|
||
|
}
|
||
|
|
||
|
void NetworkAccount::setHost( const QString & 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*/ KConfig/*Base*/ & config ) {
|
||
|
KMAccount::readConfig( config );
|
||
|
|
||
|
setLogin( config.readEntry( "login" ) );
|
||
|
|
||
|
if ( config.readNumEntry( "store-passwd", false ) ) { // ### s/Num/Bool/
|
||
|
mStorePasswd = true;
|
||
|
QString 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 KWallet 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( KConfig/*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-" + QString::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("KWallet is not available. It is strongly recommended to use "
|
||
|
"KWallet 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("KWallet 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-" + QString::number(mId))) {
|
||
|
Wallet *wallet = kmkernel->wallet();
|
||
|
if (wallet)
|
||
|
wallet->removeEntry( "account-" + QString::number(mId) );
|
||
|
}
|
||
|
|
||
|
config.writeEntry( "host", host() );
|
||
|
config.writeEntry( "port", static_cast<unsigned int>( 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<const NetworkAccount*>( 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-" + QString::number(mId) ) )
|
||
|
return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (Wallet::keyDoesNotExist( Wallet::NetworkWallet(), "kmail", "account-" + QString::number(mId) ) )
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( kmkernel->wallet() ) {
|
||
|
QString passwd;
|
||
|
kmkernel->wallet()->readPassword( "account-" + QString::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"
|