2 kopetepassword.cpp - Kopete Password
4 Copyright (c) 2004 by Richard Smith <kde@metafoo.co.uk>
5 Kopete (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>
7 *************************************************************************
9 * This library is free software; you can redistribute it and/or *
10 * modify it under the terms of the GNU Lesser General Public *
11 * License as published by the Free Software Foundation; either *
12 * version 2 of the License, or (at your option) any later version. *
14 *************************************************************************
17 #include "kopeteuiglobal.h"
18 #include "kopetepassword.h"
19 #include "kopetewalletmanager.h"
23 #include <QApplication>
27 #include <k3activelabel.h>
32 #include <kmessagebox.h>
33 #include <kiconloader.h>
34 #include <kstringhandler.h>
35 #include <kpassworddialog.h>
37 class Kopete::Password::Private
40 Private( const QString
&group
, bool blanksAllowed
)
41 : refCount( 1 ), configGroup( group
), remembered( false ),
42 isWrong( false ), allowBlankPassword( blanksAllowed
)
55 /** Reference count */
57 /** Group to use for KConfig and KWallet */
58 const QString configGroup
;
59 /** Is the password being remembered? */
61 /** The current password in the KConfig file, or QString() if no password there */
62 QString passwordFromKConfig
;
63 /** Is the current password known to be wrong? */
65 /** Are we allowed to have blank passwords? */
66 bool allowBlankPassword
;
67 /** The cached password */
72 * Implementation detail of Kopete::Password: manages a single password request
74 * @author Richard Smith <kde@metafoo.co.uk>
76 class KopetePasswordRequest
: public KopetePasswordRequestBase
79 KopetePasswordRequest( QObject
*owner
, Kopete::Password
&pass
)
80 : QObject( owner
), mPassword( pass
), mWallet( 0 )
85 * Start the request - ask for the wallet
91 Kopete::WalletManager::self()->openWallet( this, SLOT( walletReceived( KWallet::Wallet
* ) ) );
94 void walletReceived( KWallet::Wallet
*wallet
)
102 * Got wallet; now carry out whatever action this request represents
104 virtual void processRequest() = 0;
106 void gotPassword(const QString
&, bool) {}
107 void slotCancelPressed() {}
110 Kopete::Password mPassword
;
111 KWallet::Wallet
*mWallet
;
115 * Implementation detail of Kopete::Password: manages a single password retrieval request
117 * @author Richard Smith <kde@metafoo.co.uk>
119 class KopetePasswordGetRequest
: public KopetePasswordRequest
122 KopetePasswordGetRequest( QObject
*owner
, Kopete::Password
&pass
)
123 : KopetePasswordRequest( owner
, pass
)
127 QString
grabPassword()
129 // Before trying to read from the wallet, check if the config file holds a password.
130 // If so, remove it from the config and set it through KWallet instead.
133 if ( mPassword
.d
->remembered
&& !mPassword
.d
->passwordFromKConfig
.isNull() )
135 pwd
= mPassword
.d
->passwordFromKConfig
;
136 mPassword
.set( pwd
);
140 if ( mWallet
&& mWallet
->readPassword( mPassword
.d
->configGroup
, pwd
) == 0 && !pwd
.isEmpty() )
143 if ( mPassword
.d
->remembered
&& !mPassword
.d
->passwordFromKConfig
.isEmpty() )
144 return mPassword
.d
->passwordFromKConfig
;
149 void finished( const QString
&result
)
151 mPassword
.d
->cachedValue
= result
;
152 emit
requestFinished( result
);
157 class KopetePasswordGetRequestPrompt
: public KopetePasswordGetRequest
160 KopetePasswordGetRequestPrompt( QObject
*owner
, Kopete::Password
&pass
, const QPixmap
&image
, const QString
&prompt
, Kopete::Password::PasswordSource source
)
161 : KopetePasswordGetRequest( owner
, pass
), mImage( image
), mPrompt( prompt
), mSource( source
), mView( 0 )
165 void processRequest()
167 QString result
= grabPassword();
168 if ( mSource
== Kopete::Password::FromUser
|| result
.isNull() )
174 void doPasswordDialog()
178 KPasswordDialog
*passwdDialog
= new KPasswordDialog( Kopete::UI::Global::mainWidget(), KPasswordDialog::ShowKeepPassword
);
179 passwdDialog
->setWindowTitle( i18n( "Password Required" ) );
180 passwdDialog
->setPrompt( mPrompt
);
181 passwdDialog
->setPixmap( mImage
);
183 connect( passwdDialog
, SIGNAL( gotPassword(const QString
&, bool) ), SLOT( gotPassword( const QString
&, bool) )) ;
184 connect( passwdDialog
, SIGNAL( rejected() ), SLOT( slotCancelPressed() ) );
185 connect( this, SIGNAL( destroyed() ), passwdDialog
, SLOT( deleteLater() ) );
186 passwdDialog
->show();
189 void gotPassword(const QString
& pass
, bool keep
)
192 mPassword
.set( pass
);
197 void slotCancelPressed()
199 finished( QString::null
); //krazy:exclude=nullstrassign for old broken gcc
205 Kopete::Password::PasswordSource mSource
;
209 class KopetePasswordGetRequestNoPrompt
: public KopetePasswordGetRequest
212 KopetePasswordGetRequestNoPrompt( QObject
*owner
, Kopete::Password
&pass
)
213 : KopetePasswordGetRequest( owner
, pass
)
217 void processRequest()
219 finished( grabPassword() );
224 * Implementation detail of Kopete::Password: manages a single password change request
226 * @author Richard Smith <kde@metafoo.co.uk>
228 class KopetePasswordSetRequest
: public KopetePasswordRequest
231 KopetePasswordSetRequest( Kopete::Password
&pass
, const QString
&newPass
)
232 : KopetePasswordRequest( 0, pass
), mNewPass( newPass
)
236 ~KopetePasswordSetRequest()
239 kDebug( 14010 ) << "job complete";
241 void processRequest()
245 mPassword
.setWrong( false );
246 mPassword
.d
->cachedValue
= mNewPass
;
252 kDebug( 14010 ) << " setting password for " << mPassword
.d
->configGroup
;
254 if ( mWallet
&& mWallet
->writePassword( mPassword
.d
->configGroup
, mNewPass
) == 0 )
256 mPassword
.d
->remembered
= true;
257 mPassword
.d
->passwordFromKConfig
= QString();
258 mPassword
.writeConfig();
262 if ( KWallet::Wallet::isEnabled() )
264 // If we end up here, the wallet is enabled, but failed somehow.
265 // Ask the user what to do now.
267 //NOTE: This will start a nested event loop. However, this is fine; the only code we
268 // call after this point is in Kopete::Password, so as long as we've not been deleted
269 // everything should work out OK. We have no parent QObject, so we should survive.
270 if ( KMessageBox::warningContinueCancel( Kopete::UI::Global::mainWidget(),
271 i18n( "<qt>Kopete is unable to save your password securely in your wallet;<br />"
272 "do you want to save the password in the <b>unsafe</b> configuration file instead?</qt>" ),
273 i18n( "Unable to Store Secure Password" ),
274 KGuiItem( i18n( "Store &Unsafe" ), QString::fromLatin1( "unlock" ) ), KStandardGuiItem::cancel(),
275 QString::fromLatin1( "KWalletFallbackToKConfig" ) ) != KMessageBox::Continue
)
280 mPassword
.d
->remembered
= true;
281 mPassword
.d
->passwordFromKConfig
= mNewPass
;
282 mPassword
.writeConfig();
290 class KopetePasswordClearRequest
: public KopetePasswordRequest
293 KopetePasswordClearRequest( Kopete::Password
&pass
)
294 : KopetePasswordRequest( 0, pass
)
298 ~KopetePasswordClearRequest()
301 kDebug( 14010 ) << "job complete";
303 void processRequest()
305 if ( clearPassword() )
307 mPassword
.setWrong( true );
308 mPassword
.d
->cachedValue
= QString();
315 kDebug( 14010 ) << " clearing password";
317 mPassword
.d
->remembered
= false;
318 mPassword
.d
->passwordFromKConfig
= QString();
319 mPassword
.writeConfig();
321 mWallet
->removeEntry( mPassword
.d
->configGroup
);
327 Kopete::Password::Password( const QString
&configGroup
, bool allowBlankPassword
)
328 : QObject( 0 ), d( new Private( configGroup
, allowBlankPassword
) )
333 Kopete::Password::Password( const Password
&other
)
334 : QObject( 0 ), d( other
.d
->incRef() )
338 Kopete::Password::~Password()
343 Kopete::Password
&Kopete::Password::operator=( Password
&other
)
345 if ( d
== other
.d
) return *this;
347 d
= other
.d
->incRef();
351 void Kopete::Password::readConfig()
353 KConfigGroup
config(KGlobal::config(), d
->configGroup
);
355 QString passwordCrypted
= config
.readEntry( "Password", QString() );
356 if ( passwordCrypted
.isNull() )
357 d
->passwordFromKConfig
= QString();
359 d
->passwordFromKConfig
= KStringHandler::obscure( passwordCrypted
);
361 d
->remembered
= config
.readEntry( "RememberPassword", false );
362 d
->isWrong
= config
.readEntry( "PasswordIsWrong", false );
365 void Kopete::Password::writeConfig()
367 KSharedConfig::Ptr config
= KGlobal::config();
368 if(!config
->hasGroup(d
->configGroup
))
371 // if the kopete account has been removed, we have no way to know it.
372 // but we don't want in any case to recreate the group.
374 // (the problem is that when we remove the account, we remove the password
375 // also, which cause a call to this function )
379 KConfigGroup group
= config
->group( d
->configGroup
);
381 if ( d
->remembered
&& !d
->passwordFromKConfig
.isNull() )
382 group
.writeEntry( "Password", KStringHandler::obscure( d
->passwordFromKConfig
) );
384 group
.deleteEntry( "Password" );
386 group
.writeEntry( "RememberPassword", d
->remembered
);
387 group
.writeEntry( "PasswordIsWrong", d
->isWrong
);
390 int Kopete::Password::preferredImageSize()
392 return IconSize(KIconLoader::Toolbar
);
395 bool Kopete::Password::allowBlankPassword()
397 return d
->allowBlankPassword
;
400 bool Kopete::Password::isWrong()
405 void Kopete::Password::setWrong( bool bWrong
)
410 if ( bWrong
) d
->cachedValue
= QString();
413 void Kopete::Password::requestWithoutPrompt( QObject
*returnObj
, const char *slot
)
415 KopetePasswordRequest
*request
= new KopetePasswordGetRequestNoPrompt( returnObj
, *this );
416 // call connect on returnObj so we can still connect if 'slot' is protected/private
417 returnObj
->connect( request
, SIGNAL( requestFinished( const QString
& ) ), slot
);
421 void Kopete::Password::request( QObject
*returnObj
, const char *slot
, const QPixmap
&image
, const QString
&prompt
, Kopete::Password::PasswordSource source
)
423 KopetePasswordRequest
*request
= new KopetePasswordGetRequestPrompt( returnObj
, *this, image
, prompt
, source
);
424 returnObj
->connect( request
, SIGNAL( requestFinished( const QString
& ) ), slot
);
428 QString
Kopete::Password::cachedValue()
430 return d
->cachedValue
;
433 void Kopete::Password::set( const QString
&pass
)
435 // if we're being told to forget the password, and we aren't remembering one,
436 // don't try to open the wallet. fixes bug #71804.
437 if( pass
.isNull() && !d
->allowBlankPassword
)
444 KopetePasswordRequest
*request
= new KopetePasswordSetRequest( *this, pass
);
448 void Kopete::Password::clear()
450 KopetePasswordClearRequest
*request
= new KopetePasswordClearRequest( *this );
454 bool Kopete::Password::remembered()
456 return d
->remembered
;
459 #include "kopetepassword.moc"
461 // vim: set noet ts=4 sts=4 sw=4: