remove actions which are not supported, this way they are also not visible in shortcu...
[kdenetwork.git] / kopete / libkopete / kopetepassword.cpp
blobdca375fc9b3665eb44fd0252b3d52abe5600a93b
1 /*
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 *************************************************************************
8 * *
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. *
13 * *
14 *************************************************************************
17 #include "kopeteuiglobal.h"
18 #include "kopetepassword.h"
19 #include "kopetewalletmanager.h"
21 #include <kwallet.h>
23 #include <QApplication>
24 #include <QLabel>
25 #include <QLineEdit>
26 #include <QCheckBox>
27 #include <k3activelabel.h>
28 #include <kconfig.h>
29 #include <kdebug.h>
30 #include <kdialog.h>
31 #include <klocale.h>
32 #include <kmessagebox.h>
33 #include <kiconloader.h>
34 #include <kstringhandler.h>
35 #include <kpassworddialog.h>
37 class Kopete::Password::Private
39 public:
40 Private( const QString &group, bool blanksAllowed )
41 : refCount( 1 ), configGroup( group ), remembered( false ),
42 isWrong( false ), allowBlankPassword( blanksAllowed )
45 Private *incRef()
47 ++refCount;
48 return this;
50 void decRef()
52 if( --refCount == 0 )
53 delete this;
55 /** Reference count */
56 int refCount;
57 /** Group to use for KConfig and KWallet */
58 const QString configGroup;
59 /** Is the password being remembered? */
60 bool 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? */
64 bool isWrong;
65 /** Are we allowed to have blank passwords? */
66 bool allowBlankPassword;
67 /** The cached password */
68 QString cachedValue;
71 /**
72 * Implementation detail of Kopete::Password: manages a single password request
73 * @internal
74 * @author Richard Smith <kde@metafoo.co.uk>
76 class KopetePasswordRequest : public KopetePasswordRequestBase
78 public:
79 KopetePasswordRequest( QObject *owner, Kopete::Password &pass )
80 : QObject( owner ), mPassword( pass ), mWallet( 0 )
84 /**
85 * Start the request - ask for the wallet
87 void begin()
89 kDebug( 14010 );
91 Kopete::WalletManager::self()->openWallet( this, SLOT( walletReceived( KWallet::Wallet* ) ) );
94 void walletReceived( KWallet::Wallet *wallet )
96 kDebug( 14010 ) ;
97 mWallet = wallet;
98 processRequest();
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() {}
109 protected:
110 Kopete::Password mPassword;
111 KWallet::Wallet *mWallet;
115 * Implementation detail of Kopete::Password: manages a single password retrieval request
116 * @internal
117 * @author Richard Smith <kde@metafoo.co.uk>
119 class KopetePasswordGetRequest : public KopetePasswordRequest
121 public:
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.
131 QString pwd;
133 if ( mPassword.d->remembered && !mPassword.d->passwordFromKConfig.isNull() )
135 pwd = mPassword.d->passwordFromKConfig;
136 mPassword.set( pwd );
137 return pwd;
140 if ( mWallet && mWallet->readPassword( mPassword.d->configGroup, pwd ) == 0 && !pwd.isEmpty() )
141 return pwd;
143 if ( mPassword.d->remembered && !mPassword.d->passwordFromKConfig.isEmpty() )
144 return mPassword.d->passwordFromKConfig;
146 return QString();
149 void finished( const QString &result )
151 mPassword.d->cachedValue = result;
152 emit requestFinished( result );
153 delete this;
157 class KopetePasswordGetRequestPrompt : public KopetePasswordGetRequest
159 public:
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() )
169 doPasswordDialog();
170 else
171 finished( result );
174 void doPasswordDialog()
176 kDebug( 14010 ) ;
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)
191 if ( keep )
192 mPassword.set( pass );
194 finished( pass );
197 void slotCancelPressed()
199 finished( QString::null ); //krazy:exclude=nullstrassign for old broken gcc
202 private:
203 QPixmap mImage;
204 QString mPrompt;
205 Kopete::Password::PasswordSource mSource;
206 QWidget *mView;
209 class KopetePasswordGetRequestNoPrompt : public KopetePasswordGetRequest
211 public:
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
225 * @internal
226 * @author Richard Smith <kde@metafoo.co.uk>
228 class KopetePasswordSetRequest : public KopetePasswordRequest
230 public:
231 KopetePasswordSetRequest( Kopete::Password &pass, const QString &newPass )
232 : KopetePasswordRequest( 0, pass ), mNewPass( newPass )
234 KGlobal::ref();
236 ~KopetePasswordSetRequest()
238 KGlobal::deref();
239 kDebug( 14010 ) << "job complete";
241 void processRequest()
243 if ( setPassword() )
245 mPassword.setWrong( false );
246 mPassword.d->cachedValue = mNewPass;
248 delete this;
250 bool setPassword()
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();
259 return true;
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 )
277 return false;
280 mPassword.d->remembered = true;
281 mPassword.d->passwordFromKConfig = mNewPass;
282 mPassword.writeConfig();
283 return true;
286 private:
287 QString mNewPass;
290 class KopetePasswordClearRequest : public KopetePasswordRequest
292 public:
293 KopetePasswordClearRequest( Kopete::Password &pass )
294 : KopetePasswordRequest( 0, pass )
296 KGlobal::ref();
298 ~KopetePasswordClearRequest()
300 KGlobal::deref();
301 kDebug( 14010 ) << "job complete";
303 void processRequest()
305 if ( clearPassword() )
307 mPassword.setWrong( true );
308 mPassword.d->cachedValue = QString();
311 delete this;
313 bool clearPassword()
315 kDebug( 14010 ) << " clearing password";
317 mPassword.d->remembered = false;
318 mPassword.d->passwordFromKConfig = QString();
319 mPassword.writeConfig();
320 if ( mWallet )
321 mWallet->removeEntry( mPassword.d->configGroup );
322 return true;
327 Kopete::Password::Password( const QString &configGroup, bool allowBlankPassword )
328 : QObject( 0 ), d( new Private( configGroup, allowBlankPassword ) )
330 readConfig();
333 Kopete::Password::Password( const Password &other )
334 : QObject( 0 ), d( other.d->incRef() )
338 Kopete::Password::~Password()
340 d->decRef();
343 Kopete::Password &Kopete::Password::operator=( Password &other )
345 if ( d == other.d ) return *this;
346 d->decRef();
347 d = other.d->incRef();
348 return *this;
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();
358 else
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))
370 //### (KOPETE)
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.
373 // see Bug 106460
374 // (the problem is that when we remove the account, we remove the password
375 // also, which cause a call to this function )
376 return;
379 KConfigGroup group = config->group( d->configGroup );
381 if ( d->remembered && !d->passwordFromKConfig.isNull() )
382 group.writeEntry( "Password", KStringHandler::obscure( d->passwordFromKConfig ) );
383 else
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()
402 return d->isWrong;
405 void Kopete::Password::setWrong( bool bWrong )
407 d->isWrong = bWrong;
408 writeConfig();
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 );
418 request->begin();
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 );
425 request->begin();
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 )
439 if( remembered() )
440 clear();
441 return;
444 KopetePasswordRequest *request = new KopetePasswordSetRequest( *this, pass );
445 request->begin();
448 void Kopete::Password::clear()
450 KopetePasswordClearRequest *request = new KopetePasswordClearRequest( *this );
451 request->begin();
454 bool Kopete::Password::remembered()
456 return d->remembered;
459 #include "kopetepassword.moc"
461 // vim: set noet ts=4 sts=4 sw=4: