Merge pull request #56 from akallabeth/refactor_win_cred_store
Refactor win cred store
This commit is contained in:
commit
08be0593e1
|
@ -13,6 +13,13 @@ include(GNUInstallDirs)
|
|||
|
||||
option(BUILD_WITH_QT4 "Build qtkeychain with Qt4 no matter if Qt5 was found" OFF)
|
||||
|
||||
if (WIN32)
|
||||
option(USE_CREDENTIAL_STORE "Build with windows CredentialStore support" ON)
|
||||
|
||||
if (USE_CREDENTIAL_STORE)
|
||||
add_definitions(-DUSE_CREDENTIAL_STORE=1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if( NOT BUILD_WITH_QT4 )
|
||||
# try Qt5 first, and prefer that if found
|
||||
|
|
153
keychain.cpp
153
keychain.cpp
|
@ -11,9 +11,9 @@
|
|||
|
||||
using namespace QKeychain;
|
||||
|
||||
Job::Job( const QString& service, QObject *parent )
|
||||
Job::Job( JobPrivate *q, QObject *parent )
|
||||
: QObject( parent )
|
||||
, d ( new JobPrivate( service ) ) {
|
||||
, d ( q ) {
|
||||
}
|
||||
|
||||
Job::~Job() {
|
||||
|
@ -52,6 +52,10 @@ void Job::setInsecureFallback( bool insecureFallback ) {
|
|||
d->insecureFallback = insecureFallback;
|
||||
}
|
||||
|
||||
void Job::doStart() {
|
||||
JobExecutor::instance()->enqueue( this );
|
||||
}
|
||||
|
||||
void Job::emitFinished() {
|
||||
emit finished( this );
|
||||
if ( d->autoDelete )
|
||||
|
@ -64,6 +68,10 @@ void Job::emitFinishedWithError( Error error, const QString& errorString ) {
|
|||
emitFinished();
|
||||
}
|
||||
|
||||
void Job::scheduledStart() {
|
||||
d->scheduledStart();
|
||||
}
|
||||
|
||||
Error Job::error() const {
|
||||
return d->error;
|
||||
}
|
||||
|
@ -81,12 +89,11 @@ void Job::setErrorString( const QString& errorString ) {
|
|||
}
|
||||
|
||||
ReadPasswordJob::ReadPasswordJob( const QString& service, QObject* parent )
|
||||
: Job( service, parent )
|
||||
, d( new ReadPasswordJobPrivate( this ) )
|
||||
{}
|
||||
: Job( new ReadPasswordJobPrivate( service, this ), parent ) {
|
||||
|
||||
}
|
||||
|
||||
ReadPasswordJob::~ReadPasswordJob() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
QString ReadPasswordJob::textData() const {
|
||||
|
@ -97,126 +104,80 @@ QByteArray ReadPasswordJob::binaryData() const {
|
|||
return d->data;
|
||||
}
|
||||
|
||||
QString ReadPasswordJob::key() const {
|
||||
QString Job::key() const {
|
||||
return d->key;
|
||||
}
|
||||
|
||||
void ReadPasswordJob::setKey( const QString& key ) {
|
||||
d->key = key;
|
||||
}
|
||||
|
||||
void ReadPasswordJob::doStart() {
|
||||
JobExecutor::instance()->enqueue( this );
|
||||
void Job::setKey( const QString& key_ ) {
|
||||
d->key = key_;
|
||||
}
|
||||
|
||||
WritePasswordJob::WritePasswordJob( const QString& service, QObject* parent )
|
||||
: Job( service, parent )
|
||||
, d( new WritePasswordJobPrivate( this ) ) {
|
||||
: Job( new WritePasswordJobPrivate( service, this ), parent ) {
|
||||
}
|
||||
|
||||
WritePasswordJob::~WritePasswordJob() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
QString WritePasswordJob::key() const {
|
||||
return d->key;
|
||||
}
|
||||
|
||||
void WritePasswordJob::setKey( const QString& key ) {
|
||||
d->key = key;
|
||||
}
|
||||
|
||||
void WritePasswordJob::setBinaryData( const QByteArray& data ) {
|
||||
d->binaryData = data;
|
||||
d->mode = WritePasswordJobPrivate::Binary;
|
||||
d->data = data;
|
||||
d->mode = JobPrivate::Binary;
|
||||
}
|
||||
|
||||
void WritePasswordJob::setTextData( const QString& data ) {
|
||||
d->textData = data;
|
||||
d->mode = WritePasswordJobPrivate::Text;
|
||||
}
|
||||
|
||||
void WritePasswordJob::doStart() {
|
||||
JobExecutor::instance()->enqueue( this );
|
||||
d->data = data.toUtf8();
|
||||
d->mode = JobPrivate::Text;
|
||||
}
|
||||
|
||||
DeletePasswordJob::DeletePasswordJob( const QString& service, QObject* parent )
|
||||
: Job( service, parent )
|
||||
, d( new DeletePasswordJobPrivate( this ) ) {
|
||||
: Job( new DeletePasswordJobPrivate( service, this ), parent ) {
|
||||
}
|
||||
|
||||
DeletePasswordJob::~DeletePasswordJob() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
void DeletePasswordJob::doStart() {
|
||||
//Internally, to delete a password we just execute a write job with no data set (null byte array).
|
||||
//In all current implementations, this deletes the entry so this is sufficient
|
||||
WritePasswordJob* job = new WritePasswordJob( service(), this );
|
||||
connect( job, SIGNAL(finished(QKeychain::Job*)), d, SLOT(jobFinished(QKeychain::Job*)) );
|
||||
job->setInsecureFallback(true);
|
||||
job->setSettings(settings());
|
||||
job->setKey( d->key );
|
||||
job->doStart();
|
||||
}
|
||||
DeletePasswordJobPrivate::DeletePasswordJobPrivate(const QString &service_, DeletePasswordJob *qq) :
|
||||
JobPrivate(service_, qq) {
|
||||
|
||||
QString DeletePasswordJob::key() const {
|
||||
return d->key;
|
||||
}
|
||||
|
||||
void DeletePasswordJob::setKey( const QString& key ) {
|
||||
d->key = key;
|
||||
}
|
||||
|
||||
void DeletePasswordJobPrivate::jobFinished( Job* job ) {
|
||||
q->setError( job->error() );
|
||||
q->setErrorString( job->errorString() );
|
||||
q->emitFinished();
|
||||
}
|
||||
|
||||
JobExecutor::JobExecutor()
|
||||
: QObject( 0 )
|
||||
, m_runningJob( 0 )
|
||||
{
|
||||
, m_jobRunning( false ) {
|
||||
}
|
||||
|
||||
void JobExecutor::enqueue( Job* job ) {
|
||||
m_queue.append( job );
|
||||
m_queue.enqueue( job );
|
||||
startNextIfNoneRunning();
|
||||
}
|
||||
|
||||
void JobExecutor::startNextIfNoneRunning() {
|
||||
if ( m_queue.isEmpty() || m_runningJob )
|
||||
if ( m_queue.isEmpty() || m_jobRunning )
|
||||
return;
|
||||
QPointer<Job> next;
|
||||
while ( !next && !m_queue.isEmpty() ) {
|
||||
next = m_queue.first();
|
||||
m_queue.pop_front();
|
||||
next = m_queue.dequeue();
|
||||
}
|
||||
if ( next ) {
|
||||
connect( next, SIGNAL(finished(QKeychain::Job*)), this, SLOT(jobFinished(QKeychain::Job*)) );
|
||||
connect( next, SIGNAL(destroyed(QObject*)), this, SLOT(jobDestroyed(QObject*)) );
|
||||
m_runningJob = next;
|
||||
if ( ReadPasswordJob* rpj = qobject_cast<ReadPasswordJob*>( m_runningJob ) )
|
||||
rpj->d->scheduledStart();
|
||||
else if ( WritePasswordJob* wpj = qobject_cast<WritePasswordJob*>( m_runningJob) )
|
||||
wpj->d->scheduledStart();
|
||||
m_jobRunning = true;
|
||||
next->scheduledStart();
|
||||
}
|
||||
}
|
||||
|
||||
void JobExecutor::jobDestroyed( QObject* object ) {
|
||||
Job* job = static_cast<Job*>(object);
|
||||
Q_UNUSED( object ) // for release mode
|
||||
Q_ASSERT( object == m_runningJob );
|
||||
m_runningJob->disconnect( this );
|
||||
m_runningJob = 0;
|
||||
job->disconnect( this );
|
||||
m_jobRunning = false;
|
||||
startNextIfNoneRunning();
|
||||
}
|
||||
|
||||
void JobExecutor::jobFinished( Job* job ) {
|
||||
Q_UNUSED( job ) // for release mode
|
||||
Q_ASSERT( job == m_runningJob );
|
||||
m_runningJob->disconnect( this );
|
||||
m_runningJob = 0;
|
||||
job->disconnect( this );
|
||||
m_jobRunning = false;
|
||||
startNextIfNoneRunning();
|
||||
}
|
||||
|
||||
|
@ -227,3 +188,47 @@ JobExecutor* JobExecutor::instance() {
|
|||
s_instance = new JobExecutor;
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
ReadPasswordJobPrivate::ReadPasswordJobPrivate(const QString &service_, ReadPasswordJob *qq) :
|
||||
JobPrivate(service_, qq) {
|
||||
|
||||
}
|
||||
|
||||
JobPrivate::JobPrivate(const QString &service_, Job *qq)
|
||||
: error( NoError )
|
||||
, service( service_ )
|
||||
, autoDelete( true )
|
||||
, insecureFallback( false )
|
||||
, q(qq) {
|
||||
|
||||
}
|
||||
|
||||
QString JobPrivate::modeToString(Mode m)
|
||||
{
|
||||
switch (m) {
|
||||
case Text:
|
||||
return QLatin1String("Text");
|
||||
case Binary:
|
||||
return QLatin1String("Binary");
|
||||
}
|
||||
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, "Unhandled Mode value");
|
||||
return QString();
|
||||
}
|
||||
|
||||
JobPrivate::Mode JobPrivate::stringToMode(const QString& s)
|
||||
{
|
||||
if (s == QLatin1String("Text") || s == QLatin1String("1"))
|
||||
return Text;
|
||||
if (s == QLatin1String("Binary") || s == QLatin1String("2"))
|
||||
return Binary;
|
||||
|
||||
qCritical("Unexpected mode string '%s'", qPrintable(s));
|
||||
|
||||
return Text;
|
||||
}
|
||||
|
||||
WritePasswordJobPrivate::WritePasswordJobPrivate(const QString &service_, WritePasswordJob *qq) :
|
||||
JobPrivate(service_, qq) {
|
||||
|
||||
}
|
||||
|
|
45
keychain.h
45
keychain.h
|
@ -39,8 +39,7 @@ class JobPrivate;
|
|||
|
||||
class QKEYCHAIN_EXPORT Job : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Job( const QString& service, QObject* parent=0 );
|
||||
public:
|
||||
~Job();
|
||||
|
||||
QSettings* settings() const;
|
||||
|
@ -59,19 +58,32 @@ public:
|
|||
bool insecureFallback() const;
|
||||
void setInsecureFallback( bool insecureFallback );
|
||||
|
||||
QString key() const;
|
||||
void setKey( const QString& key );
|
||||
|
||||
Q_SIGNALS:
|
||||
void finished( QKeychain::Job* );
|
||||
|
||||
protected:
|
||||
Q_INVOKABLE virtual void doStart() = 0;
|
||||
explicit Job( JobPrivate *q, QObject* parent=0 );
|
||||
Q_INVOKABLE void doStart();
|
||||
|
||||
private:
|
||||
void setError( Error error );
|
||||
void setErrorString( const QString& errorString );
|
||||
void emitFinished();
|
||||
void emitFinishedWithError(Error, const QString& errorString);
|
||||
|
||||
private:
|
||||
void scheduledStart();
|
||||
|
||||
protected:
|
||||
JobPrivate* const d;
|
||||
|
||||
friend class JobExecutor;
|
||||
friend class JobPrivate;
|
||||
friend class ReadPasswordJobPrivate;
|
||||
friend class WritePasswordJobPrivate;
|
||||
friend class DeletePasswordJobPrivate;
|
||||
};
|
||||
|
||||
class ReadPasswordJobPrivate;
|
||||
|
@ -82,19 +94,11 @@ public:
|
|||
explicit ReadPasswordJob( const QString& service, QObject* parent=0 );
|
||||
~ReadPasswordJob();
|
||||
|
||||
QString key() const;
|
||||
void setKey( const QString& key );
|
||||
|
||||
QByteArray binaryData() const;
|
||||
QString textData() const;
|
||||
|
||||
protected:
|
||||
void doStart();
|
||||
|
||||
private:
|
||||
friend class QKeychain::ReadPasswordJobPrivate;
|
||||
friend class QKeychain::JobExecutor;
|
||||
ReadPasswordJobPrivate* const d;
|
||||
};
|
||||
|
||||
class WritePasswordJobPrivate;
|
||||
|
@ -105,20 +109,12 @@ public:
|
|||
explicit WritePasswordJob( const QString& service, QObject* parent=0 );
|
||||
~WritePasswordJob();
|
||||
|
||||
QString key() const;
|
||||
void setKey( const QString& key );
|
||||
|
||||
void setBinaryData( const QByteArray& data );
|
||||
void setTextData( const QString& data );
|
||||
|
||||
protected:
|
||||
void doStart();
|
||||
|
||||
private:
|
||||
friend class QKeychain::JobExecutor;
|
||||
|
||||
friend class QKeychain::WritePasswordJobPrivate;
|
||||
friend class DeletePasswordJob;
|
||||
WritePasswordJobPrivate* const d;
|
||||
};
|
||||
|
||||
class DeletePasswordJobPrivate;
|
||||
|
@ -129,15 +125,8 @@ public:
|
|||
explicit DeletePasswordJob( const QString& service, QObject* parent=0 );
|
||||
~DeletePasswordJob();
|
||||
|
||||
QString key() const;
|
||||
void setKey( const QString& key );
|
||||
|
||||
protected:
|
||||
void doStart();
|
||||
|
||||
private:
|
||||
friend class QKeychain::DeletePasswordJobPrivate;
|
||||
DeletePasswordJobPrivate* const d;
|
||||
};
|
||||
|
||||
} // namespace QtKeychain
|
||||
|
|
|
@ -29,9 +29,9 @@ static QString strForStatus( OSStatus os ) {
|
|||
const char * const buf = CFStringGetCStringPtr( str.value, kCFStringEncodingUTF8 );
|
||||
if ( !buf )
|
||||
return QObject::tr( "%1 (OSStatus %2)" )
|
||||
.arg( "OSX Keychain Error" ).arg( os );
|
||||
.arg( "OSX Keychain Error" ).arg( os );
|
||||
return QObject::tr( "%1 (OSStatus %2)" )
|
||||
.arg( QString::fromUtf8( buf, strlen( buf ) ) ).arg( os );
|
||||
.arg( QString::fromUtf8( buf, strlen( buf ) ) ).arg( os );
|
||||
}
|
||||
|
||||
static OSStatus readPw( QByteArray* pw,
|
||||
|
@ -148,14 +148,17 @@ void WritePasswordJobPrivate::scheduledStart()
|
|||
QString errorString;
|
||||
Error error = NoError;
|
||||
|
||||
if ( mode == Delete ) {
|
||||
const Error derr = deleteEntryImpl( q->service(), key, &errorString );
|
||||
if ( derr != NoError )
|
||||
error = CouldNotDeleteEntry;
|
||||
q->emitFinishedWithError( error, errorString );
|
||||
return;
|
||||
}
|
||||
const QByteArray data = mode == Text ? textData.toUtf8() : binaryData;
|
||||
error = writeEntryImpl( q->service(), key, data, &errorString );
|
||||
q->emitFinishedWithError( error, errorString );
|
||||
}
|
||||
|
||||
void DeletePasswordJobPrivate::scheduledStart()
|
||||
{
|
||||
QString errorString;
|
||||
Error error = NoError;
|
||||
|
||||
const Error derr = deleteEntryImpl( q->service(), key, &errorString );
|
||||
if ( derr != NoError )
|
||||
error = CouldNotDeleteEntry;
|
||||
q->emitFinishedWithError( error, errorString );
|
||||
}
|
||||
|
|
129
keychain_p.h
129
keychain_p.h
|
@ -13,7 +13,7 @@
|
|||
#include <QObject>
|
||||
#include <QPointer>
|
||||
#include <QSettings>
|
||||
#include <QVector>
|
||||
#include <QQueue>
|
||||
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
|
||||
|
||||
|
@ -35,105 +35,108 @@ class JobExecutor;
|
|||
class JobPrivate : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
JobPrivate( const QString& service_ )
|
||||
: error( NoError )
|
||||
, service( service_ )
|
||||
, autoDelete( true )
|
||||
, insecureFallback( false ) {}
|
||||
enum Mode {
|
||||
Text,
|
||||
Binary
|
||||
};
|
||||
|
||||
virtual void scheduledStart() = 0;
|
||||
|
||||
static QString modeToString(Mode m);
|
||||
static Mode stringToMode(const QString& s);
|
||||
|
||||
Mode mode;
|
||||
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
|
||||
org::kde::KWallet* iface;
|
||||
int walletHandle;
|
||||
|
||||
static void gnomeKeyring_readCb( int result, const char* string, JobPrivate* data );
|
||||
static void gnomeKeyring_writeCb( int result, JobPrivate* self );
|
||||
|
||||
virtual void fallbackOnError(const QDBusError& err) = 0;
|
||||
|
||||
protected Q_SLOTS:
|
||||
void kwalletWalletFound( QDBusPendingCallWatcher* watcher );
|
||||
virtual void kwalletFinished( QDBusPendingCallWatcher* watcher );
|
||||
virtual void kwalletOpenFinished( QDBusPendingCallWatcher* watcher );
|
||||
#else
|
||||
void kwalletWalletFound(QDBusPendingCallWatcher *watcher) {}
|
||||
virtual void kwalletFinished( QDBusPendingCallWatcher* watcher ) {}
|
||||
virtual void kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) {}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
JobPrivate( const QString& service_, Job *q );
|
||||
|
||||
protected:
|
||||
QKeychain::Error error;
|
||||
QString errorString;
|
||||
QString service;
|
||||
bool autoDelete;
|
||||
bool insecureFallback;
|
||||
QPointer<QSettings> settings;
|
||||
QString key;
|
||||
Job* const q;
|
||||
QByteArray data;
|
||||
|
||||
friend class Job;
|
||||
friend class JobExecutor;
|
||||
friend class ReadPasswordJob;
|
||||
friend class WritePasswordJob;
|
||||
};
|
||||
|
||||
class ReadPasswordJobPrivate : public QObject {
|
||||
class ReadPasswordJobPrivate : public JobPrivate {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ReadPasswordJobPrivate( ReadPasswordJob* qq ) : q( qq ), walletHandle( 0 ), dataType( Text ) {}
|
||||
explicit ReadPasswordJobPrivate( const QString &service_, ReadPasswordJob* qq );
|
||||
void scheduledStart();
|
||||
|
||||
ReadPasswordJob* const q;
|
||||
QByteArray data;
|
||||
QString key;
|
||||
int walletHandle;
|
||||
enum DataType {
|
||||
Binary,
|
||||
Text
|
||||
};
|
||||
DataType dataType;
|
||||
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
|
||||
org::kde::KWallet* iface;
|
||||
static void gnomeKeyring_cb( int result, const char* string, ReadPasswordJobPrivate* data );
|
||||
friend class QKeychain::JobExecutor;
|
||||
void fallbackOnError(const QDBusError& err);
|
||||
|
||||
private Q_SLOTS:
|
||||
void kwalletWalletFound( QDBusPendingCallWatcher* watcher );
|
||||
void kwalletOpenFinished( QDBusPendingCallWatcher* watcher );
|
||||
void kwalletEntryTypeFinished( QDBusPendingCallWatcher* watcher );
|
||||
void kwalletReadFinished( QDBusPendingCallWatcher* watcher );
|
||||
void kwalletFinished( QDBusPendingCallWatcher* watcher );
|
||||
#else //moc's too dumb to respect above macros, so just define empty slot implementations
|
||||
private Q_SLOTS:
|
||||
void kwalletWalletFound( QDBusPendingCallWatcher* ) {}
|
||||
void kwalletOpenFinished( QDBusPendingCallWatcher* ) {}
|
||||
void kwalletEntryTypeFinished( QDBusPendingCallWatcher* ) {}
|
||||
void kwalletReadFinished( QDBusPendingCallWatcher* ) {}
|
||||
void kwalletFinished( QDBusPendingCallWatcher* ) {}
|
||||
#endif
|
||||
|
||||
friend class ReadPasswordJob;
|
||||
};
|
||||
|
||||
class WritePasswordJobPrivate : public QObject {
|
||||
class WritePasswordJobPrivate : public JobPrivate {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit WritePasswordJobPrivate( WritePasswordJob* qq ) : q( qq ), mode( Delete ) {}
|
||||
explicit WritePasswordJobPrivate( const QString &service_, WritePasswordJob* qq );
|
||||
void scheduledStart();
|
||||
|
||||
enum Mode {
|
||||
Delete,
|
||||
Text,
|
||||
Binary
|
||||
};
|
||||
|
||||
static QString modeToString(Mode m);
|
||||
static Mode stringToMode(const QString& s);
|
||||
|
||||
WritePasswordJob* const q;
|
||||
Mode mode;
|
||||
QString key;
|
||||
QByteArray binaryData;
|
||||
QString textData;
|
||||
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
|
||||
org::kde::KWallet* iface;
|
||||
static void gnomeKeyring_cb( int result, WritePasswordJobPrivate* self );
|
||||
friend class QKeychain::JobExecutor;
|
||||
void fallbackOnError(const QDBusError& err);
|
||||
|
||||
private Q_SLOTS:
|
||||
void kwalletWalletFound( QDBusPendingCallWatcher* watcher );
|
||||
void kwalletOpenFinished( QDBusPendingCallWatcher* watcher );
|
||||
void kwalletWriteFinished( QDBusPendingCallWatcher* watcher );
|
||||
#else
|
||||
private Q_SLOTS:
|
||||
void kwalletWalletFound( QDBusPendingCallWatcher* ) {}
|
||||
void kwalletOpenFinished( QDBusPendingCallWatcher* ) {}
|
||||
void kwalletWriteFinished( QDBusPendingCallWatcher* ) {}
|
||||
#endif
|
||||
|
||||
friend class WritePasswordJob;
|
||||
};
|
||||
|
||||
class DeletePasswordJobPrivate : public QObject {
|
||||
class DeletePasswordJobPrivate : public JobPrivate {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DeletePasswordJobPrivate( DeletePasswordJob* qq ) : q( qq ) {}
|
||||
explicit DeletePasswordJobPrivate( const QString &service_, DeletePasswordJob* qq );
|
||||
|
||||
void scheduledStart();
|
||||
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
|
||||
void fallbackOnError(const QDBusError& err);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void doStart();
|
||||
DeletePasswordJob* const q;
|
||||
QString key;
|
||||
private Q_SLOTS:
|
||||
void jobFinished( QKeychain::Job* );
|
||||
|
||||
friend class DeletePasswordJob;
|
||||
};
|
||||
|
||||
class JobExecutor : public QObject {
|
||||
|
@ -154,8 +157,8 @@ private Q_SLOTS:
|
|||
|
||||
private:
|
||||
static JobExecutor* s_instance;
|
||||
Job* m_runningJob;
|
||||
QVector<QPointer<Job> > m_queue;
|
||||
QQueue<QPointer<Job> > m_queue;
|
||||
bool m_jobRunning;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ static KeyringBackend detectKeyringBackend()
|
|||
case DesktopEnv_Plasma5:
|
||||
return Backend_Kwallet5;
|
||||
break;
|
||||
// fall through
|
||||
// fall through
|
||||
case DesktopEnv_Gnome:
|
||||
case DesktopEnv_Unity:
|
||||
case DesktopEnv_Xfce:
|
||||
|
@ -125,7 +125,7 @@ static void kwalletReadPasswordScheduledStartImpl(const char * service, const ch
|
|||
}
|
||||
else
|
||||
{
|
||||
// D-Bus is not reachable so none can tell us something about KWalletd
|
||||
// D-Bus is not reachable so none can tell us something about KWalletd
|
||||
QDBusError err( QDBusError::NoServer, ReadPasswordJobPrivate::tr("D-Bus is not running") );
|
||||
priv->fallbackOnError( err );
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ void ReadPasswordJobPrivate::scheduledStart() {
|
|||
switch ( getKeyringBackend() ) {
|
||||
case Backend_GnomeKeyring:
|
||||
if ( !GnomeKeyring::find_network_password( key.toUtf8().constData(), q->service().toUtf8().constData(),
|
||||
reinterpret_cast<GnomeKeyring::OperationGetStringCallback>( &ReadPasswordJobPrivate::gnomeKeyring_cb ),
|
||||
reinterpret_cast<GnomeKeyring::OperationGetStringCallback>( &JobPrivate::gnomeKeyring_readCb ),
|
||||
this, 0 ) )
|
||||
q->emitFinishedWithError( OtherError, tr("Unknown error") );
|
||||
break;
|
||||
|
@ -149,13 +149,14 @@ void ReadPasswordJobPrivate::scheduledStart() {
|
|||
}
|
||||
}
|
||||
|
||||
void ReadPasswordJobPrivate::kwalletWalletFound(QDBusPendingCallWatcher *watcher)
|
||||
void JobPrivate::kwalletWalletFound(QDBusPendingCallWatcher *watcher)
|
||||
{
|
||||
watcher->deleteLater();
|
||||
const QDBusPendingReply<QString> reply = *watcher;
|
||||
const QDBusPendingReply<int> pendingReply = iface->open( reply.value(), 0, q->service() );
|
||||
QDBusPendingCallWatcher* pendingWatcher = new QDBusPendingCallWatcher( pendingReply, this );
|
||||
connect( pendingWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletOpenFinished(QDBusPendingCallWatcher*)) );
|
||||
connect( pendingWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
|
||||
this, SLOT(kwalletOpenFinished(QDBusPendingCallWatcher*)) );
|
||||
}
|
||||
|
||||
static QPair<Error, QString> mapGnomeKeyringError( int result )
|
||||
|
@ -188,10 +189,10 @@ static QPair<Error, QString> mapGnomeKeyringError( int result )
|
|||
return qMakePair( OtherError, QObject::tr("Unknown error") );
|
||||
}
|
||||
|
||||
void ReadPasswordJobPrivate::gnomeKeyring_cb( int result, const char* string, ReadPasswordJobPrivate* self )
|
||||
void JobPrivate::gnomeKeyring_readCb( int result, const char* string, JobPrivate* self )
|
||||
{
|
||||
if ( result == GnomeKeyring::RESULT_OK ) {
|
||||
if ( self->dataType == ReadPasswordJobPrivate::Text )
|
||||
if ( self->mode == JobPrivate::Text )
|
||||
self->data = string;
|
||||
else
|
||||
self->data = QByteArray::fromBase64( string );
|
||||
|
@ -209,11 +210,7 @@ void ReadPasswordJobPrivate::fallbackOnError(const QDBusError& err )
|
|||
|
||||
if ( q->insecureFallback() && actual->contains( dataKey( key ) ) ) {
|
||||
|
||||
const WritePasswordJobPrivate::Mode mode = WritePasswordJobPrivate::stringToMode( actual->value( typeKey( key ) ).toString() );
|
||||
if (mode == WritePasswordJobPrivate::Binary)
|
||||
dataType = Binary;
|
||||
else
|
||||
dataType = Text;
|
||||
mode = JobPrivate::stringToMode( actual->value( typeKey( key ) ).toString() );
|
||||
data = actual->value( dataKey( key ) ).toByteArray();
|
||||
|
||||
q->emitFinished();
|
||||
|
@ -300,10 +297,10 @@ void ReadPasswordJobPrivate::kwalletEntryTypeFinished( QDBusPendingCallWatcher*
|
|||
q->emitFinishedWithError( EntryNotFound, tr("Entry not found") );
|
||||
return;
|
||||
case Password:
|
||||
dataType = Text;
|
||||
mode = Text;
|
||||
break;
|
||||
case Stream:
|
||||
dataType = Binary;
|
||||
mode = Binary;
|
||||
break;
|
||||
case Map:
|
||||
q->emitFinishedWithError( EntryNotFound, tr("Unsupported entry type 'Map'") );
|
||||
|
@ -313,32 +310,28 @@ void ReadPasswordJobPrivate::kwalletEntryTypeFinished( QDBusPendingCallWatcher*
|
|||
return;
|
||||
}
|
||||
|
||||
const QDBusPendingCall nextReply = dataType == Text
|
||||
? QDBusPendingCall( iface->readPassword( walletHandle, q->service(), key, q->service() ) )
|
||||
: QDBusPendingCall( iface->readEntry( walletHandle, q->service(), key, q->service() ) );
|
||||
const QDBusPendingCall nextReply = (mode == Text)
|
||||
? QDBusPendingCall( iface->readPassword( walletHandle, q->service(), key, q->service() ) )
|
||||
: QDBusPendingCall( iface->readEntry( walletHandle, q->service(), key, q->service() ) );
|
||||
QDBusPendingCallWatcher* nextWatcher = new QDBusPendingCallWatcher( nextReply, this );
|
||||
connect( nextWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletReadFinished(QDBusPendingCallWatcher*)) );
|
||||
}
|
||||
|
||||
void ReadPasswordJobPrivate::kwalletReadFinished( QDBusPendingCallWatcher* watcher ) {
|
||||
watcher->deleteLater();
|
||||
if ( watcher->isError() ) {
|
||||
const QDBusError err = watcher->error();
|
||||
q->emitFinishedWithError( OtherError, tr("Could not read password: %1; %2").arg( QDBusError::errorString( err.type() ), err.message() ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( dataType == Binary ) {
|
||||
void ReadPasswordJobPrivate::kwalletFinished( QDBusPendingCallWatcher* watcher ) {
|
||||
if ( !watcher->isError() ) {
|
||||
if ( mode == Binary ) {
|
||||
QDBusPendingReply<QByteArray> reply = *watcher;
|
||||
data = reply.value();
|
||||
} else {
|
||||
QDBusPendingReply<QString> reply = *watcher;
|
||||
data = reply.value().toUtf8();
|
||||
}
|
||||
q->emitFinished();
|
||||
}
|
||||
|
||||
JobPrivate::kwalletFinished(watcher);
|
||||
}
|
||||
|
||||
static void kwalletWritePasswordScheduledStart( const char * service, const char * path, WritePasswordJobPrivate * priv ) {
|
||||
static void kwalletWritePasswordScheduledStart( const char * service, const char * path, JobPrivate * priv ) {
|
||||
if ( QDBusConnection::sessionBus().isConnected() )
|
||||
{
|
||||
priv->iface = new org::kde::KWallet( QLatin1String(service), QLatin1String(path), QDBusConnection::sessionBus(), priv );
|
||||
|
@ -356,21 +349,15 @@ static void kwalletWritePasswordScheduledStart( const char * service, const char
|
|||
|
||||
void WritePasswordJobPrivate::scheduledStart() {
|
||||
switch ( getKeyringBackend() ) {
|
||||
case Backend_GnomeKeyring:
|
||||
if ( mode == WritePasswordJobPrivate::Delete ) {
|
||||
if ( !GnomeKeyring::delete_network_password( key.toUtf8().constData(), q->service().toUtf8().constData(),
|
||||
reinterpret_cast<GnomeKeyring::OperationDoneCallback>( &WritePasswordJobPrivate::gnomeKeyring_cb ),
|
||||
this, 0 ) )
|
||||
q->emitFinishedWithError( OtherError, tr("Unknown error") );
|
||||
} else {
|
||||
QByteArray password = mode == WritePasswordJobPrivate::Text ? textData.toUtf8() : binaryData.toBase64();
|
||||
QByteArray service = q->service().toUtf8();
|
||||
if ( !GnomeKeyring::store_network_password( GnomeKeyring::GNOME_KEYRING_DEFAULT, service.constData(),
|
||||
key.toUtf8().constData(), service.constData(), password.constData(),
|
||||
reinterpret_cast<GnomeKeyring::OperationDoneCallback>( &WritePasswordJobPrivate::gnomeKeyring_cb ),
|
||||
this, 0 ) )
|
||||
q->emitFinishedWithError( OtherError, tr("Unknown error") );
|
||||
}
|
||||
case Backend_GnomeKeyring: {
|
||||
QByteArray password = (mode == JobPrivate::Text) ? data : data.toBase64();
|
||||
QByteArray service = q->service().toUtf8();
|
||||
if ( !GnomeKeyring::store_network_password( GnomeKeyring::GNOME_KEYRING_DEFAULT, service.constData(),
|
||||
key.toUtf8().constData(), service.constData(), password.constData(),
|
||||
reinterpret_cast<GnomeKeyring::OperationDoneCallback>( &JobPrivate::gnomeKeyring_writeCb ),
|
||||
this, 0 ) )
|
||||
q->emitFinishedWithError( OtherError, tr("Unknown error") );
|
||||
}
|
||||
break;
|
||||
|
||||
case Backend_Kwallet4:
|
||||
|
@ -382,35 +369,6 @@ void WritePasswordJobPrivate::scheduledStart() {
|
|||
}
|
||||
}
|
||||
|
||||
QString WritePasswordJobPrivate::modeToString(Mode m)
|
||||
{
|
||||
switch (m) {
|
||||
case Delete:
|
||||
return QLatin1String("Delete");
|
||||
case Text:
|
||||
return QLatin1String("Text");
|
||||
case Binary:
|
||||
return QLatin1String("Binary");
|
||||
}
|
||||
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, "Unhandled Mode value");
|
||||
return QString();
|
||||
}
|
||||
|
||||
WritePasswordJobPrivate::Mode WritePasswordJobPrivate::stringToMode(const QString& s)
|
||||
{
|
||||
if (s == QLatin1String("Delete") || s == QLatin1String("0"))
|
||||
return Delete;
|
||||
if (s == QLatin1String("Text") || s == QLatin1String("1"))
|
||||
return Text;
|
||||
if (s == QLatin1String("Binary") || s == QLatin1String("2"))
|
||||
return Binary;
|
||||
|
||||
qCritical("Unexpected mode string '%s'", qPrintable(s));
|
||||
|
||||
return Text;
|
||||
}
|
||||
|
||||
void WritePasswordJobPrivate::fallbackOnError(const QDBusError &err)
|
||||
{
|
||||
QScopedPointer<QSettings> local( !q->settings() ? new QSettings( q->service() ) : 0 );
|
||||
|
@ -421,25 +379,14 @@ void WritePasswordJobPrivate::fallbackOnError(const QDBusError &err)
|
|||
return;
|
||||
}
|
||||
|
||||
if ( mode == Delete ) {
|
||||
actual->remove( key );
|
||||
actual->sync();
|
||||
|
||||
q->emitFinished();
|
||||
return;
|
||||
}
|
||||
|
||||
actual->setValue( QString::fromLatin1( "%1/type" ).arg( key ), mode );
|
||||
if ( mode == Text )
|
||||
actual->setValue( QString::fromLatin1( "%1/data" ).arg( key ), textData.toUtf8() );
|
||||
else if ( mode == Binary )
|
||||
actual->setValue( QString::fromLatin1( "%1/data" ).arg( key ), binaryData );
|
||||
actual->setValue( QString::fromLatin1( "%1/data" ).arg( key ), data );
|
||||
actual->sync();
|
||||
|
||||
q->emitFinished();
|
||||
}
|
||||
|
||||
void WritePasswordJobPrivate::gnomeKeyring_cb( int result, WritePasswordJobPrivate* self )
|
||||
void JobPrivate::gnomeKeyring_writeCb(int result, JobPrivate* self )
|
||||
{
|
||||
if ( result == GnomeKeyring::RESULT_OK ) {
|
||||
self->q->emitFinished();
|
||||
|
@ -449,16 +396,7 @@ void WritePasswordJobPrivate::gnomeKeyring_cb( int result, WritePasswordJobPriva
|
|||
}
|
||||
}
|
||||
|
||||
void WritePasswordJobPrivate::kwalletWalletFound(QDBusPendingCallWatcher *watcher)
|
||||
{
|
||||
watcher->deleteLater();
|
||||
const QDBusPendingReply<QString> reply = *watcher;
|
||||
const QDBusPendingReply<int> pendingReply = iface->open( reply.value(), 0, q->service() );
|
||||
QDBusPendingCallWatcher* pendingWatcher = new QDBusPendingCallWatcher( pendingReply, this );
|
||||
connect( pendingWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletOpenFinished(QDBusPendingCallWatcher*)) );
|
||||
}
|
||||
|
||||
void WritePasswordJobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) {
|
||||
void JobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) {
|
||||
watcher->deleteLater();
|
||||
QDBusPendingReply<int> reply = *watcher;
|
||||
|
||||
|
@ -486,10 +424,10 @@ void WritePasswordJobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watc
|
|||
|
||||
QDBusPendingReply<int> nextReply;
|
||||
|
||||
if ( !textData.isEmpty() )
|
||||
nextReply = iface->writePassword( handle, q->service(), key, textData, q->service() );
|
||||
else if ( !binaryData.isEmpty() )
|
||||
nextReply = iface->writeEntry( handle, q->service(), key, binaryData, q->service() );
|
||||
if ( mode == Text )
|
||||
nextReply = iface->writePassword( handle, q->service(), key, QString::fromUtf8(data), q->service() );
|
||||
else if ( mode == Binary )
|
||||
nextReply = iface->writeEntry( handle, q->service(), key, data, q->service() );
|
||||
else
|
||||
nextReply = iface->removeEntry( handle, q->service(), key, q->service() );
|
||||
|
||||
|
@ -497,14 +435,54 @@ void WritePasswordJobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watc
|
|||
connect( nextWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletWriteFinished(QDBusPendingCallWatcher*)) );
|
||||
}
|
||||
|
||||
void WritePasswordJobPrivate::kwalletWriteFinished( QDBusPendingCallWatcher* watcher ) {
|
||||
void JobPrivate::kwalletFinished( QDBusPendingCallWatcher* watcher ) {
|
||||
watcher->deleteLater();
|
||||
QDBusPendingReply<int> reply = *watcher;
|
||||
if ( reply.isError() ) {
|
||||
const QDBusError err = reply.error();
|
||||
q->emitFinishedWithError( OtherError, tr("Could not open wallet: %1; %2").arg( QDBusError::errorString( err.type() ), err.message() ) );
|
||||
q->emitFinishedWithError( OtherError, tr("Could not open wallet: %1; %2")
|
||||
.arg( QDBusError::errorString( err.type() ), err.message() ) );
|
||||
return;
|
||||
}
|
||||
|
||||
q->emitFinished();
|
||||
}
|
||||
|
||||
void DeletePasswordJobPrivate::scheduledStart() {
|
||||
switch ( getKeyringBackend() ) {
|
||||
case Backend_GnomeKeyring: {
|
||||
if ( !GnomeKeyring::delete_network_password(
|
||||
key.toUtf8().constData(), q->service().toUtf8().constData(),
|
||||
reinterpret_cast<GnomeKeyring::OperationDoneCallback>( &JobPrivate::gnomeKeyring_writeCb ),
|
||||
this, 0 ) )
|
||||
q->emitFinishedWithError( OtherError, tr("Unknown error") );
|
||||
}
|
||||
break;
|
||||
|
||||
case Backend_Kwallet4:
|
||||
kwalletWritePasswordScheduledStart("org.kde.kwalletd", "/modules/kwalletd", this);
|
||||
break;
|
||||
case Backend_Kwallet5:
|
||||
kwalletWritePasswordScheduledStart("org.kde.kwalletd5", "/modules/kwalletd5", this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DeletePasswordJobPrivate::fallbackOnError(const QDBusError &err) {
|
||||
QScopedPointer<QSettings> local( !q->settings() ? new QSettings( q->service() ) : 0 );
|
||||
QSettings* actual = q->settings() ? q->settings() : local.data();
|
||||
|
||||
if ( !q->insecureFallback() ) {
|
||||
q->emitFinishedWithError( OtherError, tr("Could not open wallet: %1; %2")
|
||||
.arg( QDBusError::errorString( err.type() ), err.message() ) );
|
||||
return;
|
||||
}
|
||||
|
||||
actual->remove( key );
|
||||
actual->sync();
|
||||
|
||||
q->emitFinished();
|
||||
|
||||
|
||||
q->emitFinished();
|
||||
}
|
||||
|
|
111
keychain_win.cpp
111
keychain_win.cpp
|
@ -17,6 +17,82 @@
|
|||
|
||||
using namespace QKeychain;
|
||||
|
||||
#if defined(USE_CREDENTIAL_STORE)
|
||||
#include <wincred.h>
|
||||
|
||||
void ReadPasswordJobPrivate::scheduledStart() {
|
||||
std::wstring name = key.toStdWString();
|
||||
//Use settings member if there, create local settings object if not
|
||||
std::auto_ptr<QSettings> local( !q->settings() ? new QSettings( q->service() ) : 0 );
|
||||
PCREDENTIALW cred;
|
||||
|
||||
if (!CredReadW(name.c_str(), CRED_TYPE_GENERIC, 0, &cred)) {
|
||||
Error error;
|
||||
QString msg;
|
||||
switch(GetLastError()) {
|
||||
case ERROR_NOT_FOUND:
|
||||
error = EntryNotFound;
|
||||
msg = tr("Password entry not found");
|
||||
break;
|
||||
default:
|
||||
error = OtherError;
|
||||
msg = tr("Could not decrypt data");
|
||||
break;
|
||||
}
|
||||
|
||||
q->emitFinishedWithError( error, msg );
|
||||
return;
|
||||
}
|
||||
|
||||
data = QByteArray((char*)cred->CredentialBlob, cred->CredentialBlobSize);
|
||||
CredFree(cred);
|
||||
|
||||
q->emitFinished();
|
||||
}
|
||||
|
||||
void WritePasswordJobPrivate::scheduledStart() {
|
||||
CREDENTIALW cred;
|
||||
char *pwd = data.data();
|
||||
std::wstring name = key.toStdWString();
|
||||
|
||||
memset(&cred, 0, sizeof(cred));
|
||||
cred.Comment = L"QtKeychain";
|
||||
cred.Type = CRED_TYPE_GENERIC;
|
||||
cred.TargetName = (LPWSTR)name.c_str();
|
||||
cred.CredentialBlobSize = data.size();
|
||||
cred.CredentialBlob = (LPBYTE)pwd;
|
||||
cred.Persist = CRED_PERSIST_LOCAL_MACHINE;
|
||||
|
||||
if (!CredWriteW(&cred, 0)) {
|
||||
q->emitFinishedWithError( OtherError, tr("Encryption failed") ); //TODO more details available?
|
||||
} else {
|
||||
q->emitFinished();
|
||||
}
|
||||
}
|
||||
|
||||
void DeletePasswordJobPrivate::scheduledStart() {
|
||||
std::wstring name = key.toStdWString();
|
||||
|
||||
if (!CredDeleteW(name.c_str(), CRED_TYPE_GENERIC, 0)) {
|
||||
Error error;
|
||||
QString msg;
|
||||
switch(GetLastError()) {
|
||||
case ERROR_NOT_FOUND:
|
||||
error = EntryNotFound;
|
||||
msg = tr("Password entry not found");
|
||||
break;
|
||||
default:
|
||||
error = OtherError;
|
||||
msg = tr("Could not decrypt data");
|
||||
break;
|
||||
}
|
||||
|
||||
q->emitFinishedWithError( error, msg );
|
||||
} else {
|
||||
q->emitFinished();
|
||||
}
|
||||
}
|
||||
#else
|
||||
void ReadPasswordJobPrivate::scheduledStart() {
|
||||
//Use settings member if there, create local settings object if not
|
||||
std::auto_ptr<QSettings> local( !q->settings() ? new QSettings( q->service() ) : 0 );
|
||||
|
@ -53,24 +129,6 @@ void ReadPasswordJobPrivate::scheduledStart() {
|
|||
}
|
||||
|
||||
void WritePasswordJobPrivate::scheduledStart() {
|
||||
if ( mode == Delete ) {
|
||||
//Use settings member if there, create local settings object if not
|
||||
std::auto_ptr<QSettings> local( !q->settings() ? new QSettings( q->service() ) : 0 );
|
||||
QSettings* actual = q->settings() ? q->settings() : local.get();
|
||||
actual->remove( key );
|
||||
actual->sync();
|
||||
if ( actual->status() != QSettings::NoError ) {
|
||||
const QString err = actual->status() == QSettings::AccessError
|
||||
? tr("Could not delete encrypted data from settings: access error")
|
||||
: tr("Could not delete encrypted data from settings: format error");
|
||||
q->emitFinishedWithError( OtherError, err );
|
||||
} else {
|
||||
q->emitFinished();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray data = mode == Binary ? binaryData : textData.toUtf8();
|
||||
DATA_BLOB blob_in, blob_out;
|
||||
blob_in.pbData = reinterpret_cast<BYTE*>( data.data() );
|
||||
blob_in.cbData = data.size();
|
||||
|
@ -105,3 +163,20 @@ void WritePasswordJobPrivate::scheduledStart() {
|
|||
|
||||
q->emitFinished();
|
||||
}
|
||||
|
||||
void DeletePasswordJobPrivate::scheduledStart() {
|
||||
//Use settings member if there, create local settings object if not
|
||||
std::auto_ptr<QSettings> local( !q->settings() ? new QSettings( q->service() ) : 0 );
|
||||
QSettings* actual = q->settings() ? q->settings() : local.get();
|
||||
actual->remove( key );
|
||||
actual->sync();
|
||||
if ( actual->status() != QSettings::NoError ) {
|
||||
const QString err = actual->status() == QSettings::AccessError
|
||||
? tr("Could not delete encrypted data from settings: access error")
|
||||
: tr("Could not delete encrypted data from settings: format error");
|
||||
q->emitFinishedWithError( OtherError, err );
|
||||
} else {
|
||||
q->emitFinished();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue