networkaccount.cpp
00001 00026 #ifdef HAVE_CONFIG_H 00027 #include <config.h> 00028 #endif 00029 00030 #include "networkaccount.h" 00031 #include "accountmanager.h" 00032 #include "kmkernel.h" 00033 #include "globalsettings.h" 00034 00035 #include <kconfig.h> 00036 #include <kio/global.h> 00037 #include <klocale.h> 00038 #include <kmessagebox.h> 00039 #include <kdebug.h> 00040 #include <kwallet.h> 00041 using KIO::MetaData; 00042 using KWallet::Wallet; 00043 00044 #include <climits> 00045 00046 namespace KMail { 00047 00048 00049 // for restricting number of concurrent connections to the same server 00050 static TQMap<TQString, int> s_serverConnections; 00051 00052 NetworkAccount::NetworkAccount( AccountManager * parent, const TQString & name, uint id ) 00053 : KMAccount( parent, name, id ), 00054 mSlave( 0 ), 00055 mAuth( "*" ), 00056 mPort( 0 ), 00057 mStorePasswd( false ), 00058 mUseSSL( false ), 00059 mUseTLS( false ), 00060 mAskAgain( false ), 00061 mPasswdDirty( false ), 00062 mStorePasswdInConfig( false ) 00063 { 00064 00065 } 00066 00067 NetworkAccount::~NetworkAccount() { 00068 00069 } 00070 00071 void NetworkAccount::init() { 00072 KMAccount::init(); 00073 00074 mSieveConfig = SieveConfig(); 00075 mLogin = TQString(); 00076 mPasswd = TQString(); 00077 mAuth = "*"; 00078 mHost = TQString(); 00079 mPort = defaultPort(); 00080 mStorePasswd = false; 00081 mUseSSL = false; 00082 mUseTLS = false; 00083 mAskAgain = false; 00084 } 00085 00086 // 00087 // 00088 // Getters and Setters 00089 // 00090 // 00091 00092 void NetworkAccount::setLogin( const TQString & login ) { 00093 mLogin = login; 00094 } 00095 00096 TQString NetworkAccount::passwd() const { 00097 if ( storePasswd() && mPasswd.isEmpty() ) 00098 mOwner->readPasswords(); 00099 return decryptStr( mPasswd ); 00100 } 00101 00102 void NetworkAccount::setPasswd( const TQString & passwd, bool storeInConfig ) { 00103 if ( mPasswd != encryptStr( passwd ) ) { 00104 mPasswd = encryptStr( passwd ); 00105 mPasswdDirty = true; 00106 } 00107 setStorePasswd( storeInConfig ); 00108 } 00109 00110 void NetworkAccount::clearPasswd() { 00111 setPasswd( "", false ); 00112 } 00113 00114 void NetworkAccount::setAuth( const TQString & auth ) { 00115 mAuth = auth; 00116 } 00117 00118 void NetworkAccount::setStorePasswd( bool store ) { 00119 if( mStorePasswd != store && store ) 00120 mPasswdDirty = true; 00121 mStorePasswd = store; 00122 } 00123 00124 void NetworkAccount::setHost( const TQString & host ) { 00125 mHost = host; 00126 } 00127 00128 void NetworkAccount::setPort( unsigned short int port ) { 00129 mPort = port; 00130 } 00131 00132 void NetworkAccount::setUseSSL( bool use ) { 00133 mUseSSL = use; 00134 } 00135 00136 void NetworkAccount::setUseTLS( bool use ) { 00137 mUseTLS = use; 00138 } 00139 00140 void NetworkAccount::setSieveConfig( const SieveConfig & config ) { 00141 mSieveConfig = config; 00142 } 00143 00144 // 00145 // 00146 // read/write config 00147 // 00148 // 00149 00150 void NetworkAccount::readConfig( /*const*/ KConfig/*Base*/ & config ) { 00151 KMAccount::readConfig( config ); 00152 00153 setLogin( config.readEntry( "login" ) ); 00154 00155 if ( config.readNumEntry( "store-passwd", false ) ) { // ### s/Num/Bool/ 00156 mStorePasswd = true; 00157 TQString encpasswd = config.readEntry( "pass" ); 00158 if ( encpasswd.isEmpty() ) { 00159 encpasswd = config.readEntry( "passwd" ); 00160 if ( !encpasswd.isEmpty() ) encpasswd = importPassword( encpasswd ); 00161 } 00162 00163 if ( !encpasswd.isEmpty() ) { 00164 setPasswd( decryptStr( encpasswd ), true ); 00165 // migrate to KWallet if available 00166 if ( Wallet::isEnabled() ) { 00167 config.deleteEntry( "pass" ); 00168 config.deleteEntry( "passwd" ); 00169 mPasswdDirty = true; 00170 mStorePasswdInConfig = false; 00171 } else { 00172 mPasswdDirty = false; // set by setPasswd() on first read 00173 mStorePasswdInConfig = true; 00174 } 00175 } else { 00176 // read password if wallet is already open, otherwise defer to on-demand loading 00177 if ( Wallet::isOpen( Wallet::NetworkWallet() ) ) 00178 readPassword(); 00179 } 00180 00181 } else { 00182 setPasswd( "", false ); 00183 } 00184 00185 setHost( config.readEntry( "host" ) ); 00186 00187 unsigned int port = config.readUnsignedNumEntry( "port", defaultPort() ); 00188 if ( port > USHRT_MAX ) port = defaultPort(); 00189 setPort( port ); 00190 00191 setAuth( config.readEntry( "auth", "*" ) ); 00192 setUseSSL( config.readBoolEntry( "use-ssl", false ) ); 00193 setUseTLS( config.readBoolEntry( "use-tls", false ) ); 00194 00195 mSieveConfig.readConfig( config ); 00196 } 00197 00198 void NetworkAccount::writeConfig( KConfig/*Base*/ & config ) /*const*/ { 00199 KMAccount::writeConfig( config ); 00200 00201 config.writeEntry( "login", login() ); 00202 config.writeEntry( "store-passwd", storePasswd() ); 00203 00204 if ( storePasswd() ) { 00205 // write password to the wallet if possbile and necessary 00206 bool passwdStored = false; 00207 if ( mPasswdDirty ) { 00208 Wallet *wallet = kmkernel->wallet(); 00209 if ( wallet && wallet->writePassword( "account-" + TQString::number(mId), passwd() ) == 0 ) { 00210 passwdStored = true; 00211 mPasswdDirty = false; 00212 mStorePasswdInConfig = false; 00213 } 00214 } else { 00215 passwdStored = !mStorePasswdInConfig; // already in the wallet 00216 } 00217 // if wallet is not available, write to config file, since the account 00218 // manager deletes this group, we need to write it always 00219 if ( !passwdStored && ( mStorePasswdInConfig || KMessageBox::warningYesNo( 0, 00220 i18n("KWallet is not available. It is strongly recommended to use " 00221 "KWallet for managing your passwords.\n" 00222 "However, KMail can store the password in its configuration " 00223 "file instead. The password is stored in an obfuscated format, " 00224 "but should not be considered secure from decryption efforts " 00225 "if access to the configuration file is obtained.\n" 00226 "Do you want to store the password for account '%1' in the " 00227 "configuration file?").arg( name() ), 00228 i18n("KWallet Not Available"), 00229 KGuiItem( i18n("Store Password") ), 00230 KGuiItem( i18n("Do Not Store Password") ) ) 00231 == KMessageBox::Yes ) ) { 00232 config.writeEntry( "pass", encryptStr( passwd() ) ); 00233 mStorePasswdInConfig = true; 00234 } 00235 } 00236 00237 // delete password from the wallet if password storage is disabled 00238 if (!storePasswd() && !Wallet::keyDoesNotExist( 00239 Wallet::NetworkWallet(), "kmail", "account-" + TQString::number(mId))) { 00240 Wallet *wallet = kmkernel->wallet(); 00241 if (wallet) 00242 wallet->removeEntry( "account-" + TQString::number(mId) ); 00243 } 00244 00245 config.writeEntry( "host", host() ); 00246 config.writeEntry( "port", static_cast<unsigned int>( port() ) ); 00247 config.writeEntry( "auth", auth() ); 00248 config.writeEntry( "use-ssl", useSSL() ); 00249 config.writeEntry( "use-tls", useTLS() ); 00250 00251 mSieveConfig.writeConfig( config ); 00252 } 00253 00254 // 00255 // 00256 // Network processing 00257 // 00258 // 00259 00260 KURL NetworkAccount::getUrl() const { 00261 KURL url; 00262 url.setProtocol( protocol() ); 00263 url.setUser( login() ); 00264 url.setPass( passwd() ); 00265 url.setHost( host() ); 00266 url.setPort( port() ); 00267 return url; 00268 } 00269 00270 MetaData NetworkAccount::slaveConfig() const { 00271 MetaData m; 00272 m.insert( "tls", useTLS() ? "on" : "off" ); 00273 return m; 00274 } 00275 00276 void NetworkAccount::pseudoAssign( const KMAccount * a ) { 00277 KMAccount::pseudoAssign( a ); 00278 00279 const NetworkAccount * n = dynamic_cast<const NetworkAccount*>( a ); 00280 if ( !n ) return; 00281 00282 setLogin( n->login() ); 00283 setPasswd( n->passwd(), n->storePasswd() ); 00284 setHost( n->host() ); 00285 setPort( n->port() ); 00286 setAuth( n->auth() ); 00287 setUseSSL( n->useSSL() ); 00288 setUseTLS( n->useTLS() ); 00289 setSieveConfig( n->sieveConfig() ); 00290 } 00291 00292 void NetworkAccount::readPassword() { 00293 if ( !storePasswd() ) 00294 return; 00295 00296 // ### workaround for broken Wallet::keyDoesNotExist() which returns wrong 00297 // results for new entries without closing and reopening the wallet 00298 if ( Wallet::isOpen( Wallet::NetworkWallet() ) ) 00299 { 00300 Wallet *wallet = kmkernel->wallet(); 00301 if (!wallet || !wallet->hasEntry( "account-" + TQString::number(mId) ) ) 00302 return; 00303 } 00304 else 00305 { 00306 if (Wallet::keyDoesNotExist( Wallet::NetworkWallet(), "kmail", "account-" + TQString::number(mId) ) ) 00307 return; 00308 } 00309 00310 if ( kmkernel->wallet() ) { 00311 TQString passwd; 00312 kmkernel->wallet()->readPassword( "account-" + TQString::number(mId), passwd ); 00313 setPasswd( passwd, true ); 00314 mPasswdDirty = false; 00315 } 00316 } 00317 00318 void NetworkAccount::setCheckingMail( bool checking ) 00319 { 00320 mCheckingMail = checking; 00321 if ( host().isEmpty() ) 00322 return; 00323 if ( checking ) { 00324 if ( s_serverConnections.find( host() ) != s_serverConnections.end() ) 00325 s_serverConnections[host()] += 1; 00326 else 00327 s_serverConnections[host()] = 1; 00328 kdDebug(5006) << "check mail started - connections for host " 00329 << host() << " now is " 00330 << s_serverConnections[host()] << endl; 00331 } else { 00332 if ( s_serverConnections.find( host() ) != s_serverConnections.end() && 00333 s_serverConnections[host()] > 0 ) { 00334 s_serverConnections[host()] -= 1; 00335 kdDebug(5006) << "connections to server " << host() 00336 << " now " << s_serverConnections[host()] << endl; 00337 } 00338 } 00339 } 00340 00341 bool NetworkAccount::mailCheckCanProceed() const 00342 { 00343 bool offlineMode = KMKernel::isOffline(); 00344 00345 kdDebug(5006) << "for host " << host() 00346 << " current connections=" 00347 << (s_serverConnections.find(host())==s_serverConnections.end() ? 0 : s_serverConnections[host()]) 00348 << " and limit is " << GlobalSettings::self()->maxConnectionsPerHost() 00349 << endl; 00350 bool connectionLimitForHostReached = !host().isEmpty() 00351 && GlobalSettings::self()->maxConnectionsPerHost() > 0 00352 && s_serverConnections.find( host() ) != s_serverConnections.end() 00353 && s_serverConnections[host()] >= GlobalSettings::self()->maxConnectionsPerHost(); 00354 kdDebug(5006) << "connection limit reached: " 00355 << connectionLimitForHostReached << endl; 00356 00357 return ( !connectionLimitForHostReached && !offlineMode ); 00358 } 00359 00360 void NetworkAccount::resetConnectionList( NetworkAccount* acct ) 00361 { 00362 s_serverConnections[ acct->host() ] = 0; 00363 } 00364 00365 } // namespace KMail 00366 00367 #include "networkaccount.moc"