Blame SOURCES/kwalletd-new.patch

feb621
diff -Nur kwalletd.than/backend/backendpersisthandler.cpp kwalletd/backend/backendpersisthandler.cpp
feb621
--- kwalletd.than/backend/backendpersisthandler.cpp	1970-01-01 01:00:00.000000000 +0100
feb621
+++ kwalletd/backend/backendpersisthandler.cpp	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -0,0 +1,731 @@
feb621
+/**
feb621
+  * This file is part of the KDE project
feb621
+  * Copyright (C) 2013 Valentin Rusu <kde@rusu.info>
feb621
+  *
feb621
+  * This library is free software; you can redistribute it and/or
feb621
+  * modify it under the terms of the GNU Library General Public
feb621
+  * License version 2 as published by the Free Software Foundation.
feb621
+  *
feb621
+  * This library is distributed in the hope that it will be useful,
feb621
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
feb621
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
feb621
+  * Library General Public License for more details.
feb621
+  *
feb621
+  * You should have received a copy of the GNU Library General Public License
feb621
+  * along with this library; see the file COPYING.LIB.  If not, write to
feb621
+  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
feb621
+  * Boston, MA 02110-1301, USA.
feb621
+  */
feb621
+
feb621
+#include <QIODevice>
feb621
+#include <QFile>
feb621
+#include <QTextDocument>
feb621
+#include <assert.h>
feb621
+#include <ksavefile.h>
feb621
+#include <kdebug.h>
feb621
+#include <kmessagebox.h>
feb621
+#include <klocalizedstring.h>
feb621
+#ifdef HAVE_QGPGME
feb621
+#include <gpgme.h>
feb621
+#include <gpgme++/context.h>
feb621
+#include <gpgme++/key.h>
feb621
+#include <gpgme++/keylistresult.h>
feb621
+#include <gpgme++/data.h>
feb621
+#include <gpgme++/encryptionresult.h>
feb621
+#include <gpgme++/decryptionresult.h>
feb621
+#endif
feb621
+#include "backendpersisthandler.h"
feb621
+#include "kwalletbackend.h"
feb621
+#include "blowfish.h"
feb621
+#include "sha1.h"
feb621
+#include "cbc.h"
feb621
+
feb621
+#ifdef Q_OS_WIN 
feb621
+#include <windows.h>
feb621
+#include <wincrypt.h>
feb621
+#endif
feb621
+
feb621
+#define KWALLET_CIPHER_BLOWFISH_CBC 0
feb621
+#define KWALLET_CIPHER_3DES_CBC     1 // unsupported
feb621
+#define KWALLET_CIPHER_GPG          2
feb621
+
feb621
+#define KWALLET_HASH_SHA1       0
feb621
+#define KWALLET_HASH_MD5        1 // unsupported
feb621
+
feb621
+namespace KWallet {
feb621
+
feb621
+static int getRandomBlock(QByteArray& randBlock) {
feb621
+
feb621
+#ifdef Q_OS_WIN //krazy:exclude=cpp
feb621
+
feb621
+    // Use windows crypto API to get randomness on win32
feb621
+    // HACK: this should be done using qca
feb621
+    HCRYPTPROV hProv;
feb621
+
feb621
+    if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
feb621
+        CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) return -1; // couldn't get random data
feb621
+
feb621
+    if (!CryptGenRandom(hProv, static_cast<DWORD>(randBlock.size()),
feb621
+        (BYTE*)randBlock.data())) {
feb621
+        return -3; // read error
feb621
+    }
feb621
+
feb621
+    // release the crypto context
feb621
+    CryptReleaseContext(hProv, 0);
feb621
+
feb621
+    return randBlock.size();
feb621
+
feb621
+#else
feb621
+
feb621
+    // First try /dev/urandom
feb621
+    if (QFile::exists("/dev/urandom")) {
feb621
+        QFile devrand("/dev/urandom");
feb621
+        if (devrand.open(QIODevice::ReadOnly)) {
feb621
+            int rc = devrand.read(randBlock.data(), randBlock.size());
feb621
+
feb621
+            if (rc != randBlock.size()) {
feb621
+                return -3;      // not enough data read
feb621
+            }
feb621
+
feb621
+            return 0;
feb621
+        }
feb621
+    }
feb621
+
feb621
+    // If that failed, try /dev/random
feb621
+    // FIXME: open in noblocking mode!
feb621
+    if (QFile::exists("/dev/random")) {
feb621
+        QFile devrand("/dev/random");
feb621
+        if (devrand.open(QIODevice::ReadOnly)) {
feb621
+            int rc = 0;
feb621
+            int cnt = 0;
feb621
+
feb621
+            do {
feb621
+                int rc2 = devrand.read(randBlock.data() + rc, randBlock.size());
feb621
+
feb621
+                if (rc2 < 0) {
feb621
+                    return -3;  // read error
feb621
+                }
feb621
+
feb621
+                rc += rc2;
feb621
+                cnt++;
feb621
+                if (cnt > randBlock.size()) {
feb621
+                    return -4;  // reading forever?!
feb621
+                }
feb621
+            } while(rc < randBlock.size());
feb621
+
feb621
+            return 0;
feb621
+        }
feb621
+    }
feb621
+
feb621
+    // EGD method
feb621
+    QString randFilename = QString::fromLocal8Bit(qgetenv("RANDFILE"));
feb621
+    if (!randFilename.isEmpty()) {
feb621
+        if (QFile::exists(randFilename)) {
feb621
+            QFile devrand(randFilename);
feb621
+            if (devrand.open(QIODevice::ReadOnly)) {
feb621
+                int rc = devrand.read(randBlock.data(), randBlock.size());
feb621
+                if (rc != randBlock.size()) {
feb621
+                    return -3;      // not enough data read
feb621
+                }
feb621
+                return 0;
feb621
+            }
feb621
+        }
feb621
+    }
feb621
+
feb621
+    // Couldn't get any random data!!
feb621
+    return -1;
feb621
+
feb621
+#endif
feb621
+}
feb621
+
feb621
+
feb621
+
feb621
+static BlowfishPersistHandler *blowfishHandler =0;
feb621
+#ifdef HAVE_QGPGME
feb621
+static GpgPersistHandler *gpgHandler =0;
feb621
+#endif // HAVE_QGPGME
feb621
+
feb621
+BackendPersistHandler *BackendPersistHandler::getPersistHandler(BackendCipherType cipherType)
feb621
+{
feb621
+    switch (cipherType){
feb621
+        case BACKEND_CIPHER_BLOWFISH:
feb621
+            if (0 == blowfishHandler)
feb621
+                blowfishHandler = new BlowfishPersistHandler;
feb621
+            return blowfishHandler;
feb621
+#ifdef HAVE_QGPGME
feb621
+        case BACKEND_CIPHER_GPG:
feb621
+            if (0 == gpgHandler)
feb621
+                gpgHandler = new GpgPersistHandler;
feb621
+            return gpgHandler;
feb621
+#endif // HAVE_QGPGME
feb621
+        default:
feb621
+            Q_ASSERT(0);
feb621
+            return 0;
feb621
+    }
feb621
+}
feb621
+    
feb621
+BackendPersistHandler *BackendPersistHandler::getPersistHandler(char magicBuf[12])
feb621
+{
feb621
+    if (magicBuf[2] == KWALLET_CIPHER_BLOWFISH_CBC && 
feb621
+        magicBuf[3] == KWALLET_HASH_SHA1) {
feb621
+        if (0 == blowfishHandler)
feb621
+            blowfishHandler = new BlowfishPersistHandler;
feb621
+        return blowfishHandler;
feb621
+    }
feb621
+#ifdef HAVE_QGPGME
feb621
+    if (magicBuf[2] == KWALLET_CIPHER_GPG &&
feb621
+        magicBuf[3] == 0) {
feb621
+        if (0 == gpgHandler)
feb621
+            gpgHandler = new GpgPersistHandler;
feb621
+        return gpgHandler;
feb621
+    }
feb621
+#endif // HAVE_QGPGME
feb621
+    return 0;    // unknown cipher or hash
feb621
+}
feb621
+  
feb621
+int BlowfishPersistHandler::write(Backend* wb, KSaveFile& sf, QByteArray& version, WId)
feb621
+{
feb621
+    assert(wb->_cipherType == BACKEND_CIPHER_BLOWFISH);
feb621
+
feb621
+    version[2] = KWALLET_CIPHER_BLOWFISH_CBC;
feb621
+    version[3] = KWALLET_HASH_SHA1;
feb621
+    if (sf.write(version, 4) != 4) {
feb621
+        sf.abort();
feb621
+        return -4; // write error
feb621
+    }
feb621
+
feb621
+    // Holds the hashes we write out
feb621
+    QByteArray hashes;
feb621
+    QDataStream hashStream(&hashes, QIODevice::WriteOnly);
feb621
+    KMD5 md5;
feb621
+    hashStream << static_cast<quint32>(wb->_entries.count());
feb621
+
feb621
+    // Holds decrypted data prior to encryption
feb621
+    QByteArray decrypted;
feb621
+
feb621
+    // FIXME: we should estimate the amount of data we will write in each
feb621
+    // buffer and resize them approximately in order to avoid extra
feb621
+    // resizes.
feb621
+
feb621
+    // populate decrypted
feb621
+    QDataStream dStream(&decrypted, QIODevice::WriteOnly);
feb621
+    for (Backend::FolderMap::ConstIterator i = wb->_entries.constBegin(); i != wb->_entries.constEnd(); ++i) {
feb621
+        dStream << i.key();
feb621
+        dStream << static_cast<quint32>(i.value().count());
feb621
+
feb621
+        md5.reset();
feb621
+        md5.update(i.key().toUtf8());
feb621
+        hashStream.writeRawData(reinterpret_cast<const char*>(&(md5.rawDigest()[0])), 16);
feb621
+        hashStream << static_cast<quint32>(i.value().count());
feb621
+
feb621
+        for (Backend::EntryMap::ConstIterator j = i.value().constBegin(); j != i.value().constEnd(); ++j) {
feb621
+            dStream << j.key();
feb621
+            dStream << static_cast<qint32>(j.value()->type());
feb621
+            dStream << j.value()->value();
feb621
+
feb621
+            md5.reset();
feb621
+            md5.update(j.key().toUtf8());
feb621
+            hashStream.writeRawData(reinterpret_cast<const char*>(&(md5.rawDigest()[0])), 16);
feb621
+        }
feb621
+    }
feb621
+
feb621
+    if (sf.write(hashes, hashes.size()) != hashes.size()) {
feb621
+        sf.abort();
feb621
+        return -4; // write error
feb621
+    }
feb621
+
feb621
+    // calculate the hash of the file
feb621
+    SHA1 sha;
feb621
+    BlowFish _bf;
feb621
+    CipherBlockChain bf(&_bf);
feb621
+
feb621
+    sha.process(decrypted.data(), decrypted.size());
feb621
+
feb621
+    // prepend and append the random data
feb621
+    QByteArray wholeFile;
feb621
+    long blksz = bf.blockSize();
feb621
+    long newsize = decrypted.size() +
feb621
+               blksz            +    // encrypted block
feb621
+               4                +    // file size
feb621
+               20;      // size of the SHA hash
feb621
+
feb621
+    int delta = (blksz - (newsize % blksz));
feb621
+    newsize += delta;
feb621
+    wholeFile.resize(newsize);
feb621
+
feb621
+    QByteArray randBlock;
feb621
+    randBlock.resize(blksz+delta);
feb621
+    if (getRandomBlock(randBlock) < 0) {
feb621
+        sha.reset();
feb621
+        decrypted.fill(0);
feb621
+        sf.abort();
feb621
+        return -3;      // Fatal error: can't get random
feb621
+    }
feb621
+
feb621
+    for (int i = 0; i < blksz; i++) {
feb621
+        wholeFile[i] = randBlock[i];
feb621
+    }
feb621
+
feb621
+    for (int i = 0; i < 4; i++) {
feb621
+        wholeFile[(int)(i+blksz)] = (decrypted.size() >> 8*(3-i))&0xff;
feb621
+    }
feb621
+
feb621
+    for (int i = 0; i < decrypted.size(); i++) {
feb621
+        wholeFile[(int)(i+blksz+4)] = decrypted[i];
feb621
+    }
feb621
+
feb621
+    for (int i = 0; i < delta; i++) {
feb621
+        wholeFile[(int)(i+blksz+4+decrypted.size())] = randBlock[(int)(i+blksz)];
feb621
+    }
feb621
+
feb621
+    const char *hash = (const char *)sha.hash();
feb621
+    for (int i = 0; i < 20; i++) {
feb621
+        wholeFile[(int)(newsize - 20 + i)] = hash[i];
feb621
+    }
feb621
+
feb621
+    sha.reset();
feb621
+    decrypted.fill(0);
feb621
+
feb621
+    // encrypt the data
feb621
+    if (!bf.setKey(wb->_passhash.data(), wb->_passhash.size() * 8)) {
feb621
+        wholeFile.fill(0);
feb621
+        sf.abort();
feb621
+        return -2; // encrypt error
feb621
+    }
feb621
+
feb621
+    int rc = bf.encrypt(wholeFile.data(), wholeFile.size());
feb621
+    if (rc < 0) {
feb621
+        wholeFile.fill(0);
feb621
+        sf.abort();
feb621
+        return -2;  // encrypt error
feb621
+    }
feb621
+
feb621
+    // write the file
feb621
+    if (sf.write(wholeFile, wholeFile.size()) != wholeFile.size()) {
feb621
+        wholeFile.fill(0);
feb621
+        sf.abort();
feb621
+        return -4; // write error
feb621
+    }
feb621
+    if (!sf.finalize()) {
feb621
+        kDebug() << "WARNING: wallet sync to disk failed! KSaveFile status was " << sf.errorString();
feb621
+        wholeFile.fill(0);
feb621
+        return -4; // write error
feb621
+    }
feb621
+
feb621
+    wholeFile.fill(0);
feb621
+
feb621
+    return 0;
feb621
+}
feb621
+
feb621
+
feb621
+int BlowfishPersistHandler::read(Backend* wb, QFile& db, WId)
feb621
+{
feb621
+    wb->_cipherType = BACKEND_CIPHER_BLOWFISH;
feb621
+    wb->_hashes.clear();
feb621
+    // Read in the hashes
feb621
+    QDataStream hds(&db);
feb621
+    quint32 n;
feb621
+    hds >> n;
feb621
+    if (n > 0xffff) { // sanity check
feb621
+        return -43;
feb621
+    }
feb621
+
feb621
+    for (size_t i = 0; i < n; ++i) {
feb621
+        KMD5::Digest d, d2; // judgment day
feb621
+        MD5Digest ba;
feb621
+        QMap<MD5Digest,QList<MD5Digest> >::iterator it;
feb621
+        quint32 fsz;
feb621
+        if (hds.atEnd()) return -43;
feb621
+        hds.readRawData(reinterpret_cast<char *>(d), 16);
feb621
+        hds >> fsz;
feb621
+        ba = MD5Digest(reinterpret_cast<char *>(d));
feb621
+        it = wb->_hashes.insert(ba, QList<MD5Digest>());
feb621
+        for (size_t j = 0; j < fsz; ++j) {
feb621
+            hds.readRawData(reinterpret_cast<char *>(d2), 16);
feb621
+            ba = MD5Digest(reinterpret_cast<char *>(d2));
feb621
+            (*it).append(ba);
feb621
+        }
feb621
+    }
feb621
+
feb621
+    // Read in the rest of the file.
feb621
+    QByteArray encrypted = db.readAll();
feb621
+    assert(encrypted.size() < db.size());
feb621
+
feb621
+    BlowFish _bf;
feb621
+    CipherBlockChain bf(&_bf);
feb621
+    int blksz = bf.blockSize();
feb621
+    if ((encrypted.size() % blksz) != 0) {
feb621
+        return -5;     // invalid file structure
feb621
+    }
feb621
+
feb621
+    bf.setKey((void *)wb->_passhash.data(), wb->_passhash.size()*8);
feb621
+
feb621
+    if (!encrypted.data()) {
feb621
+        wb->_passhash.fill(0);
feb621
+        encrypted.fill(0);
feb621
+        return -7; // file structure error
feb621
+    }
feb621
+
feb621
+    int rc = bf.decrypt(encrypted.data(), encrypted.size());
feb621
+    if (rc < 0) {
feb621
+        wb->_passhash.fill(0);
feb621
+        encrypted.fill(0);
feb621
+        return -6;  // decrypt error
feb621
+    }
feb621
+
feb621
+    const char *t = encrypted.data();
feb621
+
feb621
+    // strip the leading data
feb621
+    t += blksz;    // one block of random data
feb621
+
feb621
+    // strip the file size off
feb621
+    long fsize = 0;
feb621
+
feb621
+    fsize |= (long(*t) << 24) & 0xff000000;
feb621
+    t++;
feb621
+    fsize |= (long(*t) << 16) & 0x00ff0000;
feb621
+    t++;
feb621
+    fsize |= (long(*t) <<  8) & 0x0000ff00;
feb621
+    t++;
feb621
+    fsize |= long(*t) & 0x000000ff;
feb621
+    t++;
feb621
+
feb621
+    if (fsize < 0 || fsize > long(encrypted.size()) - blksz - 4) {
feb621
+        //kDebug() << "fsize: " << fsize << " encrypted.size(): " << encrypted.size() << " blksz: " << blksz;
feb621
+        encrypted.fill(0);
feb621
+        return -9;         // file structure error.
feb621
+    }
feb621
+
feb621
+    // compute the hash ourself
feb621
+    SHA1 sha;
feb621
+    sha.process(t, fsize);
feb621
+    const char *testhash = (const char *)sha.hash();
feb621
+
feb621
+    // compare hashes
feb621
+    int sz = encrypted.size();
feb621
+    for (int i = 0; i < 20; i++) {
feb621
+        if (testhash[i] != encrypted[sz - 20 + i]) {
feb621
+            encrypted.fill(0);
feb621
+            sha.reset();
feb621
+            return -8;         // hash error.
feb621
+        }
feb621
+    }
feb621
+
feb621
+    sha.reset();
feb621
+
feb621
+    // chop off the leading blksz+4 bytes
feb621
+    QByteArray tmpenc(encrypted.data()+blksz+4, fsize);
feb621
+    encrypted = tmpenc;
feb621
+    tmpenc.fill(0);
feb621
+
feb621
+    // Load the data structures up
feb621
+    QDataStream eStream(encrypted);
feb621
+
feb621
+    while (!eStream.atEnd()) {
feb621
+        QString folder;
feb621
+        quint32 n;
feb621
+
feb621
+        eStream >> folder;
feb621
+        eStream >> n;
feb621
+
feb621
+        // Force initialisation
feb621
+        wb->_entries[folder].clear();
feb621
+
feb621
+        for (size_t i = 0; i < n; ++i) {
feb621
+            QString key;
feb621
+            KWallet::Wallet::EntryType et = KWallet::Wallet::Unknown;
feb621
+            Entry *e = new Entry;
feb621
+            eStream >> key;
feb621
+            qint32 x = 0; // necessary to read properly
feb621
+            eStream >> x;
feb621
+            et = static_cast<KWallet::Wallet::EntryType>(x);
feb621
+
feb621
+            switch (et) {
feb621
+            case KWallet::Wallet::Password:
feb621
+            case KWallet::Wallet::Stream:
feb621
+            case KWallet::Wallet::Map:
feb621
+            break;
feb621
+            default: // Unknown entry
feb621
+                delete e;
feb621
+                continue;
feb621
+            }
feb621
+
feb621
+            QByteArray a;
feb621
+            eStream >> a;
feb621
+            e->setValue(a);
feb621
+            e->setType(et);
feb621
+            e->setKey(key);
feb621
+            wb->_entries[folder][key] = e;
feb621
+        }
feb621
+    }
feb621
+
feb621
+    wb->_open = true;
feb621
+    encrypted.fill(0);
feb621
+    return 0;
feb621
+}
feb621
+
feb621
+#ifdef HAVE_QGPGME
feb621
+GpgME::Error initGpgME()
feb621
+{
feb621
+    GpgME::Error err;
feb621
+    static bool alreadyInitialized = false;
feb621
+    if (!alreadyInitialized) {
feb621
+        GpgME::initializeLibrary();
feb621
+        err = GpgME::checkEngine(GpgME::OpenPGP);
feb621
+        if (err){
feb621
+            kDebug() << "OpenPGP not supported!";
feb621
+        }
feb621
+        alreadyInitialized = true;
feb621
+    }
feb621
+    return err;
feb621
+}
feb621
+
feb621
+int GpgPersistHandler::write(Backend* wb, KSaveFile& sf, QByteArray& version, WId w)
feb621
+{
feb621
+    version[2] = KWALLET_CIPHER_GPG;
feb621
+    version[3] = 0;
feb621
+    if (sf.write(version, 4) != 4) {
feb621
+        sf.abort();
feb621
+        return -4; // write error
feb621
+    }
feb621
+
feb621
+    GpgME::Error err = initGpgME();
feb621
+    if (err) {
feb621
+        kDebug() << "initGpgME returned " << err.code();
feb621
+        KMessageBox::errorWId( w, i18n("<qt>Error when attempting to initialize OpenPGP while attempting to save the wallet %1. Error code is %2. Please fix your system configuration, then try again!</qt>", Qt::escape(wb->_name), err.code()));
feb621
+        sf.abort();
feb621
+        return -5;
feb621
+    }
feb621
+    
feb621
+    boost::shared_ptr< GpgME::Context > ctx( GpgME::Context::createForProtocol(GpgME::OpenPGP) );
feb621
+    if (0 == ctx) {
feb621
+        kDebug() << "Cannot setup OpenPGP context!";
feb621
+        KMessageBox::errorWId(w, i18n("<qt>Error when attempting to initialize OpenPGP while attempting to save the wallet %1. Please fix your system configuration, then try again!</qt>"), Qt::escape(wb->_name));
feb621
+        return -6;
feb621
+    }
feb621
+
feb621
+    assert(wb->_cipherType == BACKEND_CIPHER_GPG);
feb621
+    
feb621
+    QByteArray hashes;
feb621
+    QDataStream hashStream(&hashes, QIODevice::WriteOnly);
feb621
+    KMD5 md5;
feb621
+    hashStream << static_cast<quint32>(wb->_entries.count());
feb621
+
feb621
+    QByteArray values;
feb621
+    QDataStream valueStream(&values, QIODevice::WriteOnly);
feb621
+    Backend::FolderMap::ConstIterator i = wb->_entries.constBegin();
feb621
+    Backend::FolderMap::ConstIterator ie = wb->_entries.constEnd();
feb621
+    for ( ; i != ie; ++i) {
feb621
+        valueStream << i.key();
feb621
+        valueStream << static_cast<quint32>(i.value().count());
feb621
+
feb621
+        md5.reset();
feb621
+        md5.update(i.key().toUtf8());
feb621
+        hashStream.writeRawData(reinterpret_cast<const char*>(&(md5.rawDigest()[0])), 16);
feb621
+        hashStream << static_cast<quint32>(i.value().count());
feb621
+
feb621
+        Backend::EntryMap::ConstIterator j = i.value().constBegin();
feb621
+        Backend::EntryMap::ConstIterator je = i.value().constEnd();
feb621
+        for (; j != je; ++j) {
feb621
+            valueStream << j.key();
feb621
+            valueStream << static_cast<qint32>(j.value()->type());
feb621
+            valueStream << j.value()->value();
feb621
+
feb621
+            md5.reset();
feb621
+            md5.update(j.key().toUtf8());
feb621
+            hashStream.writeRawData(reinterpret_cast<const char*>(&(md5.rawDigest()[0])), 16);
feb621
+        }
feb621
+    }
feb621
+
feb621
+    QByteArray dataBuffer;
feb621
+    QDataStream dataStream(&dataBuffer, QIODevice::WriteOnly);
feb621
+    QString keyID(wb->_gpgKey.keyID());
feb621
+    dataStream << keyID;
feb621
+    dataStream << hashes;
feb621
+    dataStream << values;
feb621
+    
feb621
+    GpgME::Data decryptedData(dataBuffer.data(), dataBuffer.size(), false);
feb621
+    GpgME::Data encryptedData;
feb621
+    std::vector< GpgME::Key > keys;
feb621
+    keys.push_back(wb->_gpgKey);
feb621
+    GpgME::EncryptionResult res = ctx->encrypt(keys, decryptedData, encryptedData, GpgME::Context::None);
feb621
+    if (res.error()){
feb621
+        int gpgerr = res.error().code();
feb621
+        KMessageBox::errorWId( w, i18n("<qt>Encryption error while attempting to save the wallet %1. Error code is %2 (%3). Please fix your system configuration, then try again!</qt>",
feb621
+                                       Qt::escape(wb->_name), gpgerr, gpgme_strerror(gpgerr)));
feb621
+        kDebug() << "GpgME encryption error: " << res.error().code();
feb621
+        sf.abort();
feb621
+        return -7;
feb621
+    }
feb621
+
feb621
+    char buffer[4096];
feb621
+    ssize_t bytes =0;
feb621
+    encryptedData.seek(0, SEEK_SET);
feb621
+    while (bytes = encryptedData.read(buffer, sizeof(buffer)/sizeof(buffer[0]))){
feb621
+        if (sf.write(buffer, bytes) != bytes){
feb621
+            KMessageBox::errorWId( w, i18n("<qt>File handling error while attempting to save the wallet %1. Error was %2. Please fix your system configuration, then try again!</qt>", Qt::escape(wb->_name), sf.errorString()));
feb621
+            sf.abort();
feb621
+            return -4; // write error
feb621
+        }
feb621
+    }
feb621
+    
feb621
+    return 0;
feb621
+}
feb621
+
feb621
+int GpgPersistHandler::read(Backend* wb, QFile& sf, WId w)
feb621
+{
feb621
+    GpgME::Error err = initGpgME();
feb621
+    if (err){
feb621
+        KMessageBox::errorWId( w, i18n("<qt>Error when attempting to initialize OpenPGP while attempting to open the wallet %1. Error code is %2. Please fix your system configuration, then try again!</qt>", Qt::escape(wb->_name), err.code()));
feb621
+        return -1;
feb621
+    }
feb621
+
feb621
+    wb->_cipherType = BACKEND_CIPHER_GPG;
feb621
+    wb->_hashes.clear();
feb621
+
feb621
+    // the remainder of the file is GPG encrypted. Let's decrypt it
feb621
+    GpgME::Data encryptedData;
feb621
+    char buffer[4096];
feb621
+    ssize_t bytes = 0;
feb621
+    while (bytes = sf.read(buffer, sizeof(buffer)/sizeof(buffer[0]))){
feb621
+        encryptedData.write(buffer, bytes);
feb621
+    }
feb621
+    
feb621
+  retry_label:
feb621
+    boost::shared_ptr< GpgME::Context > ctx( GpgME::Context::createForProtocol(GpgME::OpenPGP) );
feb621
+    if (0 == ctx) {
feb621
+        KMessageBox::errorWId(w, i18n("<qt>Error when attempting to initialize OpenPGP while attempting to open the wallet %1. Please fix your system configuration, then try again!</qt>", Qt::escape(wb->_name)));
feb621
+        kDebug() << "Cannot setup OpenPGP context!";
feb621
+        return -1;
feb621
+    }
feb621
+
feb621
+    GpgME::Data decryptedData;
feb621
+    encryptedData.seek(0, SEEK_SET);
feb621
+    GpgME::DecryptionResult res = ctx->decrypt(encryptedData, decryptedData);
feb621
+    if (res.error()){
feb621
+        kDebug() << "Error decrypting message: " << res.error().asString() << ", code " << res.error().code() << ", source " << res.error().source();
feb621
+        KGuiItem btnRetry(i18n("Retry"));
feb621
+        // FIXME the logic here should be a little more elaborate; a dialog box should be used with "retry", "cancel", but also "troubleshoot" with options to show card status and to kill scdaemon
feb621
+        int userChoice = KMessageBox::warningYesNoWId(w, i18n("<qt>Error when attempting to decrypt the wallet %1 using GPG. If you're using a SmartCard, please ensure it's inserted then try again.

GPG error was %2</qt>", Qt::escape(wb->_name), res.error().asString()),
feb621
+            i18n("kwalletd GPG backend"), btnRetry, KStandardGuiItem::cancel());
feb621
+        if (userChoice == KMessageBox::Yes) {
feb621
+            decryptedData.seek(0, SEEK_SET);
feb621
+            goto retry_label;
feb621
+        }
feb621
+        return -1;
feb621
+    }
feb621
+    
feb621
+    decryptedData.seek(0, SEEK_SET);
feb621
+    QByteArray dataBuffer;
feb621
+    while (bytes = decryptedData.read(buffer, sizeof(buffer)/sizeof(buffer[0]))){
feb621
+        dataBuffer.append(buffer, bytes);
feb621
+    }
feb621
+    
feb621
+    // load the wallet from the decrypted data
feb621
+    QDataStream dataStream(dataBuffer);
feb621
+    QString keyID;
feb621
+    QByteArray hashes;
feb621
+    QByteArray values;
feb621
+    dataStream >> keyID;
feb621
+    dataStream >> hashes;
feb621
+    dataStream >> values;
feb621
+
feb621
+    // locate the GPG key having the ID found inside the file. This will be needed later, when writing changes to disk.
feb621
+    QDataStream fileStream(&sf);
feb621
+    fileStream.unsetDevice();
feb621
+    kDebug() << "This wallet was encrypted using GPG key with ID " << keyID;
feb621
+
feb621
+    ctx->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL);
feb621
+    std::vector< GpgME::Key > keys;
feb621
+    int row =0;
feb621
+    err = ctx->startKeyListing();
feb621
+    while (!err) {
feb621
+        GpgME::Key k = ctx->nextKey(err);
feb621
+        if (err)
feb621
+            break;
feb621
+        if (keyID == k.keyID()){
feb621
+            kDebug() << "The key was found.";
feb621
+            wb->_gpgKey = k;
feb621
+            break;
feb621
+        }
feb621
+    }
feb621
+    ctx->endKeyListing();
feb621
+    if (wb->_gpgKey.isNull()){
feb621
+        KMessageBox::errorWId(w, i18n("<qt>Error when attempting to open the wallet %1. The wallet was encrypted using the GPG Key ID %2 but this key was not found on your system.</qt>", Qt::escape(wb->_name), keyID));
feb621
+        return -1;
feb621
+    }
feb621
+
feb621
+    
feb621
+    QDataStream hashStream(hashes);
feb621
+    QDataStream valueStream(values);
feb621
+    
feb621
+    quint32 hashCount;
feb621
+    hashStream >> hashCount;
feb621
+    if (hashCount > 0xFFFF) {
feb621
+        return -43;
feb621
+    }
feb621
+
feb621
+    quint32 folderCount = hashCount;
feb621
+    while (hashCount--){
feb621
+        KMD5::Digest d;
feb621
+        hashStream.readRawData(reinterpret_cast<char *>(d), 16);
feb621
+        
feb621
+        quint32 folderSize;
feb621
+        hashStream >> folderSize;
feb621
+        
feb621
+        MD5Digest ba = MD5Digest(reinterpret_cast<char *>(d));
feb621
+        QMap<MD5Digest, QList<MD5Digest> >::iterator it = wb->_hashes.insert(ba, QList<MD5Digest>());
feb621
+        while (folderSize--){
feb621
+            KMD5::Digest d2;
feb621
+            hashStream.readRawData(reinterpret_cast<char *>(d2), 16);
feb621
+            ba = MD5Digest(reinterpret_cast<char *>(d2));
feb621
+            (*it).append(ba);
feb621
+        }
feb621
+    }
feb621
+    
feb621
+    while (folderCount--){
feb621
+        QString folder;
feb621
+        valueStream >> folder;
feb621
+        
feb621
+        quint32 entryCount;
feb621
+        valueStream >> entryCount;
feb621
+        
feb621
+        wb->_entries[folder].clear();
feb621
+        
feb621
+        while (entryCount--){
feb621
+            KWallet::Wallet::EntryType et = KWallet::Wallet::Unknown;
feb621
+            Entry *e = new Entry;
feb621
+            
feb621
+            QString key;
feb621
+            valueStream >> key;
feb621
+            
feb621
+            qint32 x =0; // necessary to read properly
feb621
+            valueStream >> x;
feb621
+            et = static_cast<KWallet::Wallet::EntryType>(x);
feb621
+            
feb621
+            switch (et) {
feb621
+            case KWallet::Wallet::Password:
feb621
+            case KWallet::Wallet::Stream:
feb621
+            case KWallet::Wallet::Map:
feb621
+            break;
feb621
+            default: // Unknown entry
feb621
+                delete e;
feb621
+                continue;
feb621
+            }
feb621
+            
feb621
+            QByteArray a;
feb621
+            valueStream >> a;
feb621
+            e->setValue(a);
feb621
+            e->setType(et);
feb621
+            e->setKey(key);
feb621
+            wb->_entries[folder][key] = e;
feb621
+        }
feb621
+    }
feb621
+    
feb621
+    wb->_open = true;
feb621
+
feb621
+    return 0;
feb621
+}
feb621
+#endif // HAVE_QGPGME
feb621
+
feb621
+} // namespace
feb621
diff -Nur kwalletd.than/backend/backendpersisthandler.h kwalletd/backend/backendpersisthandler.h
feb621
--- kwalletd.than/backend/backendpersisthandler.h	1970-01-01 01:00:00.000000000 +0100
feb621
+++ kwalletd/backend/backendpersisthandler.h	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -0,0 +1,83 @@
feb621
+/**
feb621
+  * This file is part of the KDE project
feb621
+  * Copyright (C) 2013 Valentin Rusu <kde@rusu.info>
feb621
+  *
feb621
+  * This library is free software; you can redistribute it and/or
feb621
+  * modify it under the terms of the GNU Library General Public
feb621
+  * License version 2 as published by the Free Software Foundation.
feb621
+  *
feb621
+  * This library is distributed in the hope that it will be useful,
feb621
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
feb621
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
feb621
+  * Library General Public License for more details.
feb621
+  *
feb621
+  * You should have received a copy of the GNU Library General Public License
feb621
+  * along with this library; see the file COPYING.LIB.  If not, write to
feb621
+  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
feb621
+  * Boston, MA 02110-1301, USA.
feb621
+  */
feb621
+#ifndef BACKENDPERSISTHANDLER_H
feb621
+#define BACKENDPERSISTHANDLER_H
feb621
+
feb621
+#define KWMAGIC_LEN 12
feb621
+
feb621
+#include <qwindowdefs.h>
feb621
+
feb621
+class QFile;
feb621
+class KSaveFile;
feb621
+namespace KWallet {
feb621
+
feb621
+class Backend;
feb621
+
feb621
+enum BackendCipherType {
feb621
+    BACKEND_CIPHER_UNKNOWN,  /// this is used by freshly allocated wallets
feb621
+    BACKEND_CIPHER_BLOWFISH, /// use the legacy blowfish cipher type
feb621
+#ifdef HAVE_QGPGME
feb621
+    BACKEND_CIPHER_GPG       /// use GPG backend to encrypt wallet contents
feb621
+#endif // HAVE_QGPGME
feb621
+};
feb621
+        
feb621
+
feb621
+class BackendPersistHandler {
feb621
+protected:
feb621
+    BackendPersistHandler() {}
feb621
+public:
feb621
+    virtual ~BackendPersistHandler() {}
feb621
+    /**
feb621
+     * This is a factory method used to get an instance of the backend suitable
feb621
+     * for reading/writing using the given cipher type
feb621
+     * 
feb621
+     * @param cypherType indication of the backend that should be returned
feb621
+     * @return a pointer to an instance of the requested handler type. No need to delete this pointer, it's lifetime is taken care of by this factory
feb621
+     */
feb621
+    static BackendPersistHandler *getPersistHandler(BackendCipherType cipherType);
feb621
+    static BackendPersistHandler *getPersistHandler(char magicBuf[KWMAGIC_LEN]);
feb621
+    
feb621
+    virtual int write(Backend* wb, KSaveFile& sf, QByteArray& version, WId w) =0;
feb621
+    virtual int read(Backend* wb, QFile& sf, WId w) =0;
feb621
+};
feb621
+
feb621
+
feb621
+class BlowfishPersistHandler : public BackendPersistHandler {
feb621
+public:
feb621
+    BlowfishPersistHandler() {}
feb621
+    virtual ~BlowfishPersistHandler() {}
feb621
+    
feb621
+    virtual int write(Backend* wb, KSaveFile& sf, QByteArray& version, WId w);
feb621
+    virtual int read(Backend* wb, QFile& sf, WId w);
feb621
+};
feb621
+
feb621
+#ifdef HAVE_QGPGME
feb621
+class GpgPersistHandler : public BackendPersistHandler {
feb621
+public:
feb621
+    GpgPersistHandler() {}
feb621
+    virtual ~GpgPersistHandler() {}
feb621
+    
feb621
+    virtual int write(Backend* wb, KSaveFile& sf, QByteArray& version, WId w);
feb621
+    virtual int read(Backend* wb, QFile& sf, WId w);
feb621
+};
feb621
+#endif // HAVE_QGPGME
feb621
+
feb621
+} // namespace
feb621
+
feb621
+#endif // BACKENDPERSISTHANDLER_H
feb621
diff -Nur kwalletd.than/backend/CMakeLists.txt kwalletd/backend/CMakeLists.txt
feb621
--- kwalletd.than/backend/CMakeLists.txt	2013-06-28 19:12:33.338802909 +0200
feb621
+++ kwalletd/backend/CMakeLists.txt	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -2,6 +2,9 @@
feb621
 
feb621
 check_include_files(stdint.h HAVE_STDINT_H)
feb621
 check_include_files(sys/bitypes.h HAVE_SYS_BITYPES_H)
feb621
+if (QGPGME_FOUND)
feb621
+    add_definitions(-DHAVE_QGPGME)
feb621
+endif(QGPGME_FOUND)
feb621
 
feb621
 configure_file (config-kwalletbackend.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kwalletbackend.h )
feb621
 
feb621
@@ -14,11 +17,15 @@
feb621
    sha1.cc
feb621
    kwalletentry.cc
feb621
    kwalletbackend.cc
feb621
+   backendpersisthandler.cpp
feb621
 )
feb621
 
feb621
 kde4_add_library(kwalletbackend SHARED ${kwalletbackend_LIB_SRCS})
feb621
 
feb621
 target_link_libraries(kwalletbackend ${KDE4_KDEUI_LIBS} )
feb621
+if(QGPGME_FOUND)
feb621
+target_link_libraries(kwalletbackend ${QGPGME_LIBRARIES} )
feb621
+endif(QGPGME_FOUND)
feb621
 
feb621
 # link with advapi32 on windows
feb621
 if(WIN32 AND NOT WINCE)
feb621
diff -Nur kwalletd.than/backend/kwalletbackend.cc kwalletd/backend/kwalletbackend.cc
feb621
--- kwalletd.than/backend/kwalletbackend.cc	2013-06-28 19:12:33.339802869 +0200
feb621
+++ kwalletd/backend/kwalletbackend.cc	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -28,6 +28,10 @@
feb621
 #include <kcodecs.h>
feb621
 #include <ksavefile.h>
feb621
 #include <kstandarddirs.h>
feb621
+#ifdef HAVE_QGPGME
feb621
+#include <gpgme++/key.h>
feb621
+#endif
feb621
+#include <knotification.h>
feb621
 
feb621
 #include <QtCore/QFile>
feb621
 #include <QtCore/QFileInfo>
feb621
@@ -48,17 +52,10 @@
feb621
 #define KWALLET_VERSION_MAJOR		0
feb621
 #define KWALLET_VERSION_MINOR		0
feb621
 
feb621
-#define KWALLET_CIPHER_BLOWFISH_CBC	0
feb621
-#define KWALLET_CIPHER_3DES_CBC		1 // unsupported
feb621
-
feb621
-#define KWALLET_HASH_SHA1		0
feb621
-#define KWALLET_HASH_MD5		1 // unsupported
feb621
-
feb621
 
feb621
 using namespace KWallet;
feb621
 
feb621
 #define KWMAGIC "KWALLET\n\r\0\r\n"
feb621
-#define KWMAGIC_LEN 12
feb621
 
feb621
 class Backend::BackendPrivate
feb621
 {
feb621
@@ -69,7 +66,7 @@
feb621
     KGlobal::dirs()->addResourceType("kwallet", 0, "share/apps/kwallet");
feb621
 }
feb621
 
feb621
-Backend::Backend(const QString& name, bool isPath) : d(0), _name(name), _ref(0) {
feb621
+Backend::Backend(const QString& name, bool isPath) : d(0), _name(name), _ref(0), _cipherType(KWallet::BACKEND_CIPHER_UNKNOWN) {
feb621
 	initKWalletDir();
feb621
 	if (isPath) {
feb621
 		_path = name;
feb621
@@ -88,91 +85,13 @@
feb621
 	delete d;
feb621
 }
feb621
 
feb621
-static int getRandomBlock(QByteArray& randBlock) {
feb621
-
feb621
-#ifdef Q_OS_WIN //krazy:exclude=cpp
feb621
-
feb621
-	// Use windows crypto API to get randomness on win32
feb621
-	// HACK: this should be done using qca
feb621
-	HCRYPTPROV hProv;
feb621
-
feb621
-	if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
feb621
-	    CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) return -1; // couldn't get random data
feb621
-
feb621
-	if (!CryptGenRandom(hProv, static_cast<DWORD>(randBlock.size()),
feb621
-	    (BYTE*)randBlock.data())) {
feb621
-		return -3; // read error
feb621
-	}
feb621
-
feb621
-	// release the crypto context
feb621
-	CryptReleaseContext(hProv, 0);
feb621
-
feb621
-	return randBlock.size();
feb621
-
feb621
-#else
feb621
-
feb621
-	// First try /dev/urandom
feb621
-	if (QFile::exists("/dev/urandom")) {
feb621
-		QFile devrand("/dev/urandom");
feb621
-		if (devrand.open(QIODevice::ReadOnly)) {
feb621
-			int rc = devrand.read(randBlock.data(), randBlock.size());
feb621
-
feb621
-			if (rc != randBlock.size()) {
feb621
-				return -3;		// not enough data read
feb621
-			}
feb621
-
feb621
-			return 0;
feb621
-		}
feb621
-	}
feb621
-
feb621
-	// If that failed, try /dev/random
feb621
-	// FIXME: open in noblocking mode!
feb621
-	if (QFile::exists("/dev/random")) {
feb621
-		QFile devrand("/dev/random");
feb621
-		if (devrand.open(QIODevice::ReadOnly)) {
feb621
-			int rc = 0;
feb621
-			int cnt = 0;
feb621
-
feb621
-			do {
feb621
-				int rc2 = devrand.read(randBlock.data() + rc, randBlock.size());
feb621
-
feb621
-				if (rc2 < 0) {
feb621
-					return -3;	// read error
feb621
-				}
feb621
-
feb621
-				rc += rc2;
feb621
-				cnt++;
feb621
-				if (cnt > randBlock.size()) {
feb621
-					return -4;	// reading forever?!
feb621
-				}
feb621
-			} while(rc < randBlock.size());
feb621
-
feb621
-			return 0;
feb621
-		}
feb621
-	}
feb621
-
feb621
-	// EGD method
feb621
-	QString randFilename = QString::fromLocal8Bit(qgetenv("RANDFILE"));
feb621
-	if (!randFilename.isEmpty()) {
feb621
-		if (QFile::exists(randFilename)) {
feb621
-			QFile devrand(randFilename);
feb621
-			if (devrand.open(QIODevice::ReadOnly)) {
feb621
-				int rc = devrand.read(randBlock.data(), randBlock.size());
feb621
-				if (rc != randBlock.size()) {
feb621
-					return -3;      // not enough data read
feb621
-				}
feb621
-				return 0;
feb621
-			}
feb621
-		}
feb621
-	}
feb621
-
feb621
-	// Couldn't get any random data!!
feb621
-	return -1;
feb621
-
feb621
-#endif
feb621
+void Backend::setCipherType(BackendCipherType ct)
feb621
+{
feb621
+    // changing cipher type on already initialed wallets is not permitted
feb621
+    assert(_cipherType == KWallet::BACKEND_CIPHER_UNKNOWN);
feb621
+    _cipherType = ct;
feb621
 }
feb621
 
feb621
-
feb621
 // this should be SHA-512 for release probably
feb621
 static int password2hash(const QByteArray& password, QByteArray& hash) {
feb621
 	SHA1 sha;
feb621
@@ -309,15 +228,26 @@
feb621
 }
feb621
 
feb621
 
feb621
-int Backend::open(const QByteArray& password) {
feb621
+int Backend::open(const QByteArray& password, WId w) {
feb621
 	if (_open) {
feb621
 		return -255;  // already open
feb621
 	}
feb621
 	
feb621
 	setPassword(password);
feb621
-   return openInternal();
feb621
+   return openInternal(w);
feb621
 }
feb621
 
feb621
+#ifdef HAVE_QGPGME
feb621
+int Backend::open(const GpgME::Key& key)
feb621
+{
feb621
+    if (_open) {
feb621
+        return -255;  // already open
feb621
+    }
feb621
+    _gpgKey = key;
feb621
+    return openInternal();
feb621
+}
feb621
+#endif // HAVE_QGPGME
feb621
+
feb621
 int Backend::openPreHashed(const QByteArray &passwordHash)
feb621
 {
feb621
    if (_open) {
feb621
@@ -334,7 +264,7 @@
feb621
    return openInternal();
feb621
 }
feb621
  
feb621
-int Backend::openInternal()
feb621
+int Backend::openInternal(WId w)
feb621
 {
feb621
 	// No wallet existed.  Let's create it.
feb621
 	// Note: 60 bytes is presently the minimum size of a wallet file.
feb621
@@ -346,8 +276,11 @@
feb621
 		}
feb621
 		newfile.close();
feb621
 		_open = true;
feb621
-		sync();
feb621
-		return 1;          // new file opened, but OK
feb621
+		if (sync(w)) {
feb621
+            return -2;
feb621
+        } else {
feb621
+            return 1;          // new file opened, but OK
feb621
+        }
feb621
 	}
feb621
 
feb621
 	QFile db(_path);
feb621
@@ -373,159 +306,15 @@
feb621
 		return -4;	   // unknown version
feb621
 	}
feb621
 
feb621
-	if (magicBuf[2] != KWALLET_CIPHER_BLOWFISH_CBC) {
feb621
-		return -42;	   // unknown cipher
feb621
-	}
feb621
-
feb621
-	if (magicBuf[3] != KWALLET_HASH_SHA1) {
feb621
-		return -42;	   // unknown hash
feb621
-	}
feb621
-
feb621
-	_hashes.clear();
feb621
-	// Read in the hashes
feb621
-	QDataStream hds(&db);
feb621
-	quint32 n;
feb621
-	hds >> n;
feb621
-	if (n > 0xffff) { // sanity check
feb621
-		return -43;
feb621
-	}
feb621
-
feb621
-	for (size_t i = 0; i < n; ++i) {
feb621
-		KMD5::Digest d, d2; // judgment day
feb621
-		MD5Digest ba;
feb621
-		QMap<MD5Digest,QList<MD5Digest> >::iterator it;
feb621
-		quint32 fsz;
feb621
-		if (hds.atEnd()) return -43;
feb621
-		hds.readRawData(reinterpret_cast<char *>(d), 16);
feb621
-		hds >> fsz;
feb621
-		ba = MD5Digest(reinterpret_cast<char *>(d));
feb621
-		it = _hashes.insert(ba, QList<MD5Digest>());
feb621
-		for (size_t j = 0; j < fsz; ++j) {
feb621
-			hds.readRawData(reinterpret_cast<char *>(d2), 16);
feb621
-			ba = MD5Digest(reinterpret_cast<char *>(d2));
feb621
-			(*it).append(ba);
feb621
-		}
feb621
-	}
feb621
-
feb621
-	// Read in the rest of the file.
feb621
-	QByteArray encrypted = db.readAll();
feb621
-	assert(encrypted.size() < db.size());
feb621
-
feb621
-	BlowFish _bf;
feb621
-	CipherBlockChain bf(&_bf);
feb621
-	int blksz = bf.blockSize();
feb621
-	if ((encrypted.size() % blksz) != 0) {
feb621
-		return -5;	   // invalid file structure
feb621
-	}
feb621
-
feb621
-	bf.setKey((void *)_passhash.data(), _passhash.size()*8);
feb621
-
feb621
-	if (!encrypted.data()) {
feb621
-		_passhash.fill(0);
feb621
-		encrypted.fill(0);
feb621
-		return -7; // file structure error
feb621
-	}
feb621
-
feb621
-	int rc = bf.decrypt(encrypted.data(), encrypted.size());
feb621
-	if (rc < 0) {
feb621
-		_passhash.fill(0);
feb621
-		encrypted.fill(0);
feb621
-		return -6;	// decrypt error
feb621
-	}
feb621
-
feb621
-	const char *t = encrypted.data();
feb621
-
feb621
-	// strip the leading data
feb621
-	t += blksz;    // one block of random data
feb621
-
feb621
-	// strip the file size off
feb621
-	long fsize = 0;
feb621
-
feb621
-	fsize |= (long(*t) << 24) & 0xff000000;
feb621
-	t++;
feb621
-	fsize |= (long(*t) << 16) & 0x00ff0000;
feb621
-	t++;
feb621
-	fsize |= (long(*t) <<  8) & 0x0000ff00;
feb621
-	t++;
feb621
-	fsize |= long(*t) & 0x000000ff;
feb621
-	t++;
feb621
-
feb621
-	if (fsize < 0 || fsize > long(encrypted.size()) - blksz - 4) {
feb621
-		//kDebug() << "fsize: " << fsize << " encrypted.size(): " << encrypted.size() << " blksz: " << blksz;
feb621
-		encrypted.fill(0);
feb621
-		return -9;         // file structure error.
feb621
-	}
feb621
-
feb621
-	// compute the hash ourself
feb621
-	SHA1 sha;
feb621
-	sha.process(t, fsize);
feb621
-	const char *testhash = (const char *)sha.hash();
feb621
-
feb621
-	// compare hashes
feb621
-	int sz = encrypted.size();
feb621
-	for (int i = 0; i < 20; i++) {
feb621
-		if (testhash[i] != encrypted[sz - 20 + i]) {
feb621
-			encrypted.fill(0);
feb621
-			sha.reset();
feb621
-			return -8;         // hash error.
feb621
-		}
feb621
-	}
feb621
-
feb621
-	sha.reset();
feb621
-
feb621
-	// chop off the leading blksz+4 bytes
feb621
-	QByteArray tmpenc(encrypted.data()+blksz+4, fsize);
feb621
-	encrypted = tmpenc;
feb621
-	tmpenc.fill(0);
feb621
-
feb621
-	// Load the data structures up
feb621
-	QDataStream eStream(encrypted);
feb621
-
feb621
-	while (!eStream.atEnd()) {
feb621
-		QString folder;
feb621
-		quint32 n;
feb621
-
feb621
-		eStream >> folder;
feb621
-		eStream >> n;
feb621
-
feb621
-		// Force initialisation
feb621
-		_entries[folder].clear();
feb621
-
feb621
-		for (size_t i = 0; i < n; ++i) {
feb621
-			QString key;
feb621
-			KWallet::Wallet::EntryType et = KWallet::Wallet::Unknown;
feb621
-			Entry *e = new Entry;
feb621
-			eStream >> key;
feb621
-			qint32 x = 0; // necessary to read properly
feb621
-			eStream >> x;
feb621
-			et = static_cast<KWallet::Wallet::EntryType>(x);
feb621
-
feb621
-			switch (et) {
feb621
-			case KWallet::Wallet::Password:
feb621
-			case KWallet::Wallet::Stream:
feb621
-			case KWallet::Wallet::Map:
feb621
-			break;
feb621
-			default: // Unknown entry
feb621
-				delete e;
feb621
-				continue;
feb621
-			}
feb621
-
feb621
-			QByteArray a;
feb621
-		 	eStream >> a;
feb621
-			e->setValue(a);
feb621
-			e->setType(et);
feb621
-			e->setKey(key);
feb621
-			_entries[folder][key] = e;
feb621
-		}
feb621
-	}
feb621
-
feb621
-	_open = true;
feb621
-	encrypted.fill(0);
feb621
-	return 0;
feb621
+	BackendPersistHandler *phandler = BackendPersistHandler::getPersistHandler(magicBuf);
feb621
+    if (0 == phandler){
feb621
+        return 42; // unknown cipher or hash
feb621
+    }
feb621
+    return phandler->read(this, db, w);
feb621
 }
feb621
 
feb621
 
feb621
-int Backend::sync() {
feb621
+int Backend::sync(WId w) {
feb621
 	if (!_open) {
feb621
 		return -255;  // not open yet
feb621
 	}
feb621
@@ -546,140 +335,27 @@
feb621
 	QByteArray version(4, 0);
feb621
 	version[0] = KWALLET_VERSION_MAJOR;
feb621
 	version[1] = KWALLET_VERSION_MINOR;
feb621
-	version[2] = KWALLET_CIPHER_BLOWFISH_CBC;
feb621
-	version[3] = KWALLET_HASH_SHA1;
feb621
-	if (sf.write(version, 4) != 4) {
feb621
-		sf.abort();
feb621
-		return -4; // write error
feb621
-	}
feb621
-
feb621
-	// Holds the hashes we write out
feb621
-	QByteArray hashes;
feb621
-	QDataStream hashStream(&hashes, QIODevice::WriteOnly);
feb621
-	KMD5 md5;
feb621
-	hashStream << static_cast<quint32>(_entries.count());
feb621
-
feb621
-	// Holds decrypted data prior to encryption
feb621
-	QByteArray decrypted;
feb621
-
feb621
-	// FIXME: we should estimate the amount of data we will write in each
feb621
-	// buffer and resize them approximately in order to avoid extra
feb621
-	// resizes.
feb621
-
feb621
-	// populate decrypted
feb621
-	QDataStream dStream(&decrypted, QIODevice::WriteOnly);
feb621
-	for (FolderMap::ConstIterator i = _entries.constBegin(); i != _entries.constEnd(); ++i) {
feb621
-		dStream << i.key();
feb621
-		dStream << static_cast<quint32>(i.value().count());
feb621
-
feb621
-		md5.reset();
feb621
-		md5.update(i.key().toUtf8());
feb621
-		hashStream.writeRawData(reinterpret_cast<const char*>(&(md5.rawDigest()[0])), 16);
feb621
-		hashStream << static_cast<quint32>(i.value().count());
feb621
-
feb621
-		for (EntryMap::ConstIterator j = i.value().constBegin(); j != i.value().constEnd(); ++j) {
feb621
-			dStream << j.key();
feb621
-			dStream << static_cast<qint32>(j.value()->type());
feb621
-			dStream << j.value()->value();
feb621
-
feb621
-			md5.reset();
feb621
-			md5.update(j.key().toUtf8());
feb621
-			hashStream.writeRawData(reinterpret_cast<const char*>(&(md5.rawDigest()[0])), 16);
feb621
-		}
feb621
-	}
feb621
-
feb621
-	if (sf.write(hashes, hashes.size()) != hashes.size()) {
feb621
-		sf.abort();
feb621
-		return -4; // write error
feb621
-	}
feb621
-
feb621
-	// calculate the hash of the file
feb621
-	SHA1 sha;
feb621
-	BlowFish _bf;
feb621
-	CipherBlockChain bf(&_bf);
feb621
 
feb621
-	sha.process(decrypted.data(), decrypted.size());
feb621
-
feb621
-	// prepend and append the random data
feb621
-	QByteArray wholeFile;
feb621
-	long blksz = bf.blockSize();
feb621
-	long newsize = decrypted.size() +
feb621
-		       blksz            +    // encrypted block
feb621
-		       4                +    // file size
feb621
-		       20;      // size of the SHA hash
feb621
-
feb621
-	int delta = (blksz - (newsize % blksz));
feb621
-	newsize += delta;
feb621
-	wholeFile.resize(newsize);
feb621
-
feb621
-	QByteArray randBlock;
feb621
-	randBlock.resize(blksz+delta);
feb621
-	if (getRandomBlock(randBlock) < 0) {
feb621
-		sha.reset();
feb621
-		decrypted.fill(0);
feb621
-		sf.abort();
feb621
-		return -3;		// Fatal error: can't get random
feb621
-	}
feb621
-
feb621
-	for (int i = 0; i < blksz; i++) {
feb621
-		wholeFile[i] = randBlock[i];
feb621
-	}
feb621
-
feb621
-	for (int i = 0; i < 4; i++) {
feb621
-		wholeFile[(int)(i+blksz)] = (decrypted.size() >> 8*(3-i))&0xff;
feb621
-	}
feb621
-
feb621
-	for (int i = 0; i < decrypted.size(); i++) {
feb621
-		wholeFile[(int)(i+blksz+4)] = decrypted[i];
feb621
-	}
feb621
-
feb621
-	for (int i = 0; i < delta; i++) {
feb621
-		wholeFile[(int)(i+blksz+4+decrypted.size())] = randBlock[(int)(i+blksz)];
feb621
-	}
feb621
-
feb621
-	const char *hash = (const char *)sha.hash();
feb621
-	for (int i = 0; i < 20; i++) {
feb621
-		wholeFile[(int)(newsize - 20 + i)] = hash[i];
feb621
-	}
feb621
-
feb621
-	sha.reset();
feb621
-	decrypted.fill(0);
feb621
-
feb621
-	// encrypt the data
feb621
-	if (!bf.setKey(_passhash.data(), _passhash.size() * 8)) {
feb621
-		wholeFile.fill(0);
feb621
-		sf.abort();
feb621
-		return -2; // encrypt error
feb621
-	}
feb621
-
feb621
-	int rc = bf.encrypt(wholeFile.data(), wholeFile.size());
feb621
-	if (rc < 0) {
feb621
-		wholeFile.fill(0);
feb621
-		sf.abort();
feb621
-		return -2;	// encrypt error
feb621
-	}
feb621
-
feb621
-	// write the file
feb621
-	if (sf.write(wholeFile, wholeFile.size()) != wholeFile.size()) {
feb621
-		wholeFile.fill(0);
feb621
-		sf.abort();
feb621
-		return -4; // write error
feb621
-	}
feb621
-	if (!sf.finalize()) {
feb621
-		wholeFile.fill(0);
feb621
-		return -4; // write error
feb621
-	}
feb621
-
feb621
-	wholeFile.fill(0);
feb621
-
feb621
-	return 0;
feb621
+    BackendPersistHandler *phandler = BackendPersistHandler::getPersistHandler(_cipherType);
feb621
+    if (0 == phandler) {
feb621
+        return -4; // write error
feb621
+    }
feb621
+    int rc = phandler->write(this, sf, version, w);
feb621
+    if (rc<0) {
feb621
+        // Oops! wallet file sync filed! Display a notification about that
feb621
+        // TODO: change kwalletd status flags, when status flags will be implemented
feb621
+        KNotification *notification = new KNotification( "syncFailed" );
feb621
+        notification->setText( i18n("Failed to sync wallet %1 to disk. Error codes are:\nRC %2\nSF %3. Please file a BUG report using this information to bugs.kde.org").arg(_name).arg(rc).arg(sf.errorString()) );
feb621
+        notification->sendEvent();
feb621
+    }
feb621
+    return rc;
feb621
 }
feb621
 
feb621
 
feb621
 int Backend::close(bool save) {
feb621
 	// save if requested
feb621
 	if (save) {
feb621
-		int rc = sync();
feb621
+		int rc = sync(0);
feb621
 		if (rc != 0) {
feb621
 			return rc;
feb621
 		}
feb621
@@ -902,3 +578,8 @@
feb621
 	password2hash(password, _passhash);
feb621
 }
feb621
 
feb621
+#ifdef HAVE_QGPGME
feb621
+const GpgME::Key &Backend::gpgKey() const {
feb621
+    return _gpgKey;
feb621
+}
feb621
+#endif
feb621
diff -Nur kwalletd.than/backend/kwalletbackend.h kwalletd/backend/kwalletbackend.h
feb621
--- kwalletd.than/backend/kwalletbackend.h	2013-06-28 19:12:33.339802869 +0200
feb621
+++ kwalletd/backend/kwalletbackend.h	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -28,7 +28,11 @@
feb621
 #include <QtCore/QStringList>
feb621
 #include <QtCore/QMap>
feb621
 #include "kwalletentry.h"
feb621
+#include "backendpersisthandler.h"
feb621
 
feb621
+#ifdef HAVE_QGPGME
feb621
+#include <gpgme++/key.h>
feb621
+#endif // HAVE_QGPGME
feb621
 
feb621
 namespace KWallet {
feb621
 
feb621
@@ -70,7 +74,10 @@
feb621
 		// Open and unlock the wallet.
feb621
 		// If opening succeeds, the password's hash will be remembered.
feb621
 		// If opening fails, the password's hash will be cleared.
feb621
-		int open(const QByteArray& password);
feb621
+		int open(const QByteArray& password, WId w=0);
feb621
+#ifdef HAVE_QGPGME
feb621
+        int open(const GpgME::Key& key);
feb621
+#endif
feb621
       
feb621
       // Open and unlock the wallet using a pre-hashed password.
feb621
       // If opening succeeds, the password's hash will be remembered.
feb621
@@ -82,7 +89,7 @@
feb621
 		int close(bool save = false);
feb621
 
feb621
 		// Write the wallet to disk
feb621
-		int sync();
feb621
+		int sync(WId w);
feb621
 
feb621
 		// Returns true if the current wallet is open.
feb621
 		bool isOpen() const;
feb621
@@ -148,6 +155,12 @@
feb621
 
feb621
 		static QString openRCToString(int rc);
feb621
 
feb621
+        void setCipherType(BackendCipherType ct);
feb621
+        BackendCipherType cipherType() const { return _cipherType; }
feb621
+#ifdef HAVE_QGPGME
feb621
+        const GpgME::Key &gpgKey() const;
feb621
+#endif
feb621
+
feb621
 	private:
feb621
 		Q_DISABLE_COPY( Backend )
feb621
 		class BackendPrivate;
feb621
@@ -163,11 +176,18 @@
feb621
 		FolderMap _entries;
feb621
 		typedef QMap<MD5Digest, QList<MD5Digest> > HashMap;
feb621
 		HashMap _hashes;
feb621
-		QByteArray _passhash; // password hash used for saving the wallet
feb621
+		QByteArray _passhash;   // password hash used for saving the wallet
feb621
+		BackendCipherType _cipherType; // the kind of encryption used for this wallet
feb621
+#ifdef HAVE_QGPGME
feb621
+        GpgME::Key      _gpgKey;
feb621
+#endif
feb621
+		friend class BlowfishPersistHandler;
feb621
+        friend class GpgPersistHandler;
feb621
       
feb621
       // open the wallet with the password already set. This is
feb621
       // called internally by both open and openPreHashed.
feb621
-      int openInternal();
feb621
+      int openInternal(WId w=0);
feb621
+
feb621
 };
feb621
 
feb621
 }
feb621
diff -Nur kwalletd.than/CMakeLists.txt kwalletd/CMakeLists.txt
feb621
--- kwalletd.than/CMakeLists.txt	2013-06-28 19:12:33.338802909 +0200
feb621
+++ kwalletd/CMakeLists.txt	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -1,5 +1,17 @@
feb621
 project(kwalletd)
feb621
 
feb621
+########### find needed packages ######
feb621
+find_package(Gpgme)  # Called by FindQGpgme, but since we call some gpgme
feb621
+                     # functions ourselves we need to link against it directly.
feb621
+find_package(QGpgme) # provided by kdepimlibs
feb621
+
feb621
+if (GPGME_FOUND AND QGPGME_FOUND)
feb621
+    add_definitions(-DHAVE_QGPGME)
feb621
+    include_directories(${GPGME_INCLUDES} ${QGPGME_INCLUDE_DIR})
feb621
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}")
feb621
+endif(GPGME_FOUND AND QGPGME_FOUND)
feb621
+
feb621
+########### build backends #########
feb621
 add_subdirectory(backend)
feb621
 
feb621
 ########### kwalletd ###############
feb621
@@ -12,13 +24,11 @@
feb621
    main.cpp
feb621
    kbetterthankdialog.cpp
feb621
    kwalletd.cpp
feb621
-   kwalletopenloop.cpp
feb621
    kwalletwizard.cpp
feb621
    ktimeout.cpp
feb621
    kwalletsessionstore.cpp
feb621
 )
feb621
 
feb621
-
feb621
 kde4_add_ui_files(kwalletd_KDEINIT_SRCS
feb621
    kbetterthankdialogbase.ui
feb621
    kwalletwizardpageexplanation.ui
feb621
@@ -27,13 +37,30 @@
feb621
    kwalletwizardpagepassword.ui
feb621
 )
feb621
 
feb621
+if (GPGME_FOUND AND QGPGME_FOUND)
feb621
+    set(kwalletd_KDEINIT_SRCS
feb621
+        ${kwalletd_KDEINIT_SRCS}
feb621
+        knewwalletdialog.cpp
feb621
+    )
feb621
+    kde4_add_ui_files(kwalletd_KDEINIT_SRCS
feb621
+        kwalletwizardpagepasswordgpg.ui
feb621
+        kwalletwizardpagegpgkey.ui
feb621
+        knewwalletdialogintro.ui
feb621
+        knewwalletdialoggpg.ui
feb621
+    )
feb621
+endif(GPGME_FOUND AND QGPGME_FOUND)
feb621
+
feb621
 find_file(kwallet_xml org.kde.KWallet.xml HINTS ${KDE4_DBUS_INTERFACES_DIR} )
feb621
 
feb621
 qt4_add_dbus_adaptor( kwalletd_KDEINIT_SRCS ${kwallet_xml} kwalletd.h KWalletD )
feb621
 
feb621
 kde4_add_kdeinit_executable( kwalletd NOGUI ${kwalletd_KDEINIT_SRCS} )
feb621
 
feb621
-target_link_libraries(kdeinit_kwalletd  ${KDE4_KDEUI_LIBS} kwalletbackend )
feb621
+target_link_libraries(kdeinit_kwalletd ${KDE4_KDEUI_LIBS} kwalletbackend )
feb621
+if (GPGME_FOUND AND QGPGME_FOUND)
feb621
+    target_link_libraries(kdeinit_kwalletd ${QGPGME_LIBRARIES} )
feb621
+endif(GPGME_FOUND AND QGPGME_FOUND)
feb621
+
feb621
 install(TARGETS kdeinit_kwalletd  ${INSTALL_TARGETS_DEFAULT_ARGS})
feb621
 
feb621
 target_link_libraries(kwalletd kdeinit_kwalletd)
feb621
@@ -45,3 +72,4 @@
feb621
 install( FILES kwalletd.notifyrc DESTINATION  ${DATA_INSTALL_DIR}/kwalletd )
feb621
 
feb621
 add_subdirectory(tests)
feb621
+
feb621
diff -Nur kwalletd.than/knewwalletdialog.cpp kwalletd/knewwalletdialog.cpp
feb621
--- kwalletd.than/knewwalletdialog.cpp	1970-01-01 01:00:00.000000000 +0100
feb621
+++ kwalletd/knewwalletdialog.cpp	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -0,0 +1,186 @@
feb621
+/**
feb621
+  * This file is part of the KDE project
feb621
+  * Copyright (C) 2013 Valentin Rusu <kde@rusu.info>
feb621
+  *
feb621
+  * This library is free software; you can redistribute it and/or
feb621
+  * modify it under the terms of the GNU Library General Public
feb621
+  * License version 2 as published by the Free Software Foundation.
feb621
+  *
feb621
+  * This library is distributed in the hope that it will be useful,
feb621
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
feb621
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
feb621
+  * Library General Public License for more details.
feb621
+  *
feb621
+  * You should have received a copy of the GNU Library General Public License
feb621
+  * along with this library; see the file COPYING.LIB.  If not, write to
feb621
+  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
feb621
+  * Boston, MA 02110-1301, USA.
feb621
+  */
feb621
+
feb621
+#include "knewwalletdialog.h"
feb621
+#include <klocalizedstring.h>
feb621
+#include <QLabel>
feb621
+#include <QTextDocument>
feb621
+#include <QTimer>
feb621
+#include <QTableWidget>
feb621
+#include <QTableWidgetItem>
feb621
+#include <gpgme.h>
feb621
+#include <gpgme++/context.h>
feb621
+#include <gpgme++/key.h>
feb621
+#include <gpgme++/keylistresult.h>
feb621
+#include <kmessagebox.h>
feb621
+#include <kdebug.h>
feb621
+
feb621
+Q_DECLARE_METATYPE(GpgME::Key)
feb621
+
feb621
+namespace KWallet {
feb621
+
feb621
+KNewWalletDialog::KNewWalletDialog(const QString &appName, const QString &walletName, QWidget* parent): 
feb621
+    QWizard(parent), _intro(0), _introId(0), _gpg(0), _gpgId(0)
feb621
+{
feb621
+    setOption(HaveFinishButtonOnEarlyPages);
feb621
+    _intro = new KNewWalletDialogIntro(appName, walletName, this);
feb621
+    _introId = addPage(_intro);
feb621
+
feb621
+    _gpg = new KNewWalletDialogGpg(appName, walletName, this);
feb621
+    _gpgId = addPage(_gpg);
feb621
+}
feb621
+
feb621
+bool KNewWalletDialog::isBlowfish() const
feb621
+{
feb621
+    return _intro->isBlowfish();
feb621
+}
feb621
+
feb621
+GpgME::Key KNewWalletDialog::gpgKey() const
feb621
+{
feb621
+    QVariant varKey = field("key");
feb621
+    return varKey.value< GpgME::Key >();
feb621
+}
feb621
+
feb621
+KNewWalletDialogIntro::KNewWalletDialogIntro(const QString& appName, const QString& walletName, QWidget* parent): QWizardPage(parent)
feb621
+{
feb621
+    _ui.setupUi(this);
feb621
+    if (appName.isEmpty()){
feb621
+        _ui.labelIntro->setText(i18n("<qt>KDE has requested to create a new wallet named '%1'. This is used to store sensitive data in a secure fashion. Please choose the new wallet's type below or click cancel to deny the application's request.</qt>", Qt::escape(walletName)));
feb621
+    } else {
feb621
+        _ui.labelIntro->setText(i18n("<qt>The application '%1' has requested to create a new wallet named '%2'. This is used to store sensitive data in a secure fashion. Please choose the new wallet's type below or click cancel to deny the application's request.</qt>", Qt::escape(appName), Qt::escape(walletName)));
feb621
+    }
feb621
+}
feb621
+
feb621
+void KNewWalletDialogIntro::onBlowfishToggled(bool blowfish)
feb621
+{
feb621
+    setFinalPage(blowfish);
feb621
+}
feb621
+
feb621
+
feb621
+bool KNewWalletDialogIntro::isBlowfish() const
feb621
+{
feb621
+    return _ui.radioBlowfish->isChecked();
feb621
+}
feb621
+
feb621
+int KNewWalletDialogIntro::nextId() const
feb621
+{
feb621
+    if (isBlowfish()){
feb621
+        return -1;
feb621
+    } else {
feb621
+        return qobject_cast< const KNewWalletDialog* >(wizard())->gpgId();
feb621
+    }
feb621
+}
feb621
+
feb621
+KNewWalletDialogGpg::KNewWalletDialogGpg(const QString& appName, const QString& walletName, QWidget* parent): 
feb621
+    QWizardPage(parent), _alreadyInitialized(false), _complete(false)
feb621
+{
feb621
+    _ui.setupUi(this);
feb621
+}
feb621
+
feb621
+struct AddKeyToList {
feb621
+    QTableWidget *_list;
feb621
+    int _row;
feb621
+    AddKeyToList(QTableWidget *list) : _list(list), _row(0) {}
feb621
+    void operator()( const GpgME::Key &k) {
feb621
+        GpgME::UserID uid = k.userID(0);
feb621
+        QString name(uid.name());
feb621
+        if (uid.comment()){
feb621
+            name = QString("%1 (%2)").arg(name).arg(uid.comment());
feb621
+        }
feb621
+        _list->setItem(_row, 0, new QTableWidgetItem(name));
feb621
+        _list->setItem(_row, 1, new QTableWidgetItem(uid.email()));
feb621
+        _list->setItem(_row, 2, new QTableWidgetItem(k.shortKeyID()));
feb621
+        QVariant varKey;
feb621
+        varKey.setValue(k);
feb621
+        _list->item(_row, 0)->setData(Qt::UserRole, varKey);
feb621
+        ++_row;
feb621
+    }
feb621
+};
feb621
+
feb621
+void KNewWalletDialogGpg::initializePage()
feb621
+{
feb621
+    if (_alreadyInitialized)
feb621
+        return;
feb621
+    
feb621
+    registerField("key", this);
feb621
+    
feb621
+    GpgME::initializeLibrary();
feb621
+    GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP);
feb621
+    if (err){
feb621
+        kDebug() << "OpenPGP not supported on your system!";
feb621
+        KMessageBox::error(this, i18n("The QGpgME library failed to initialize for the OpenPGP protocol. Please check your system's configuration then try again."));
feb621
+        emit completeChanged();
feb621
+        return;
feb621
+    }
feb621
+    boost::shared_ptr< GpgME::Context >   _ctx( GpgME::Context::createForProtocol(GpgME::OpenPGP) );
feb621
+    if (0 == _ctx) {
feb621
+        KMessageBox::error(this, i18n("The QGpgME library failed to initialize for the OpenPGP protocol. Please check your system's configuration then try again."));
feb621
+        emit completeChanged();
feb621
+        return;
feb621
+    }
feb621
+    _ctx->setKeyListMode(GpgME::Local);
feb621
+
feb621
+    std::vector< GpgME::Key > keys;
feb621
+    int row =0;
feb621
+    err = _ctx->startKeyListing();
feb621
+    while (!err) {
feb621
+        GpgME::Key k = _ctx->nextKey(err);
feb621
+        if (err)
feb621
+            break;
feb621
+        if (!k.isInvalid() && k.canEncrypt()) {
feb621
+            keys.push_back(k);
feb621
+        }
feb621
+    }
feb621
+    _ctx->endKeyListing();
feb621
+    
feb621
+    if (keys.size() == 0) {
feb621
+        KMessageBox::error(this, i18n("Seems that your system has no keys suitable for encryption. Please set-up at least an encryption key, then try again."));
feb621
+        emit completeChanged();
feb621
+        return;
feb621
+    }
feb621
+    
feb621
+    _ui.listCertificates->setRowCount(keys.size());
feb621
+    std::for_each(keys.begin(), keys.end(), AddKeyToList(_ui.listCertificates));
feb621
+    _ui.listCertificates->resizeColumnsToContents();
feb621
+    _ui.listCertificates->setCurrentCell(0, 0);
feb621
+    
feb621
+    _alreadyInitialized = true;
feb621
+}
feb621
+
feb621
+void KNewWalletDialogGpg::onItemSelectionChanged()
feb621
+{
feb621
+    _complete = _ui.listCertificates->currentRow() >= 0;
feb621
+    QVariant varKey = _ui.listCertificates->item(_ui.listCertificates->currentRow(), 0)->data(Qt::UserRole);
feb621
+    setField("key", varKey);
feb621
+    emit completeChanged();
feb621
+}
feb621
+
feb621
+bool KNewWalletDialogGpg::isComplete() const
feb621
+{
feb621
+    return _complete;
feb621
+}
feb621
+
feb621
+bool KNewWalletDialogGpg::validateCurrentPage()
feb621
+{
feb621
+    return false;
feb621
+}
feb621
+
feb621
+
feb621
+} // namespace
feb621
+#include "moc_knewwalletdialog.cpp"
feb621
diff -Nur kwalletd.than/knewwalletdialoggpg.ui kwalletd/knewwalletdialoggpg.ui
feb621
--- kwalletd.than/knewwalletdialoggpg.ui	1970-01-01 01:00:00.000000000 +0100
feb621
+++ kwalletd/knewwalletdialoggpg.ui	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -0,0 +1,91 @@
feb621
+
feb621
+<ui version="4.0">
feb621
+ <class>KNewWalletDialogGpg</class>
feb621
+ <widget class="QWidget" name="KNewWalletDialogGpg">
feb621
+  <property name="geometry">
feb621
+   <rect>
feb621
+    <x>0</x>
feb621
+    <y>0</y>
feb621
+    <width>400</width>
feb621
+    <height>300</height>
feb621
+   </rect>
feb621
+  </property>
feb621
+  <layout class="QVBoxLayout" name="verticalLayout">
feb621
+   <item>
feb621
+    <widget class="QLabel" name="label">
feb621
+     <property name="text">
feb621
+      <string>Please select the signing key from the list below:</string>
feb621
+     </property>
feb621
+    </widget>
feb621
+   </item>
feb621
+   <item>
feb621
+    <widget class="QTableWidget" name="listCertificates">
feb621
+     <property name="showDropIndicator" stdset="0">
feb621
+      <bool>false</bool>
feb621
+     </property>
feb621
+     <property name="dragDropOverwriteMode">
feb621
+      <bool>false</bool>
feb621
+     </property>
feb621
+     <property name="selectionBehavior">
feb621
+      <enum>QAbstractItemView::SelectRows</enum>
feb621
+     </property>
feb621
+     <property name="showGrid">
feb621
+      <bool>false</bool>
feb621
+     </property>
feb621
+     <property name="columnCount">
feb621
+      <number>3</number>
feb621
+     </property>
feb621
+     <attribute name="horizontalHeaderCascadingSectionResizes">
feb621
+      <bool>true</bool>
feb621
+     </attribute>
feb621
+     <attribute name="horizontalHeaderShowSortIndicator" stdset="0">
feb621
+      <bool>true</bool>
feb621
+     </attribute>
feb621
+     <attribute name="verticalHeaderVisible">
feb621
+      <bool>false</bool>
feb621
+     </attribute>
feb621
+     <attribute name="verticalHeaderHighlightSections">
feb621
+      <bool>false</bool>
feb621
+     </attribute>
feb621
+     <column>
feb621
+      <property name="text">
feb621
+       <string>Name</string>
feb621
+      </property>
feb621
+     </column>
feb621
+     <column>
feb621
+      <property name="text">
feb621
+       <string>E-Mail</string>
feb621
+      </property>
feb621
+     </column>
feb621
+     <column>
feb621
+      <property name="text">
feb621
+       <string>Key-ID</string>
feb621
+      </property>
feb621
+     </column>
feb621
+    </widget>
feb621
+   </item>
feb621
+  </layout>
feb621
+ </widget>
feb621
+ <resources/>
feb621
+ <connections>
feb621
+  <connection>
feb621
+   <sender>listCertificates</sender>
feb621
+   <signal>itemSelectionChanged()</signal>
feb621
+   <receiver>KNewWalletDialogGpg</receiver>
feb621
+   <slot>onItemSelectionChanged()</slot>
feb621
+   <hints>
feb621
+    <hint type="sourcelabel">
feb621
+     <x>48</x>
feb621
+     <y>89</y>
feb621
+    </hint>
feb621
+    <hint type="destinationlabel">
feb621
+     <x>0</x>
feb621
+     <y>81</y>
feb621
+    </hint>
feb621
+   </hints>
feb621
+  </connection>
feb621
+ </connections>
feb621
+ <slots>
feb621
+  <slot>onItemSelectionChanged()</slot>
feb621
+ </slots>
feb621
+</ui>
feb621
diff -Nur kwalletd.than/knewwalletdialog.h kwalletd/knewwalletdialog.h
feb621
--- kwalletd.than/knewwalletdialog.h	1970-01-01 01:00:00.000000000 +0100
feb621
+++ kwalletd/knewwalletdialog.h	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -0,0 +1,81 @@
feb621
+/**
feb621
+  * This file is part of the KDE project
feb621
+  * Copyright (C) 2013 Valentin Rusu <kde@rusu.info>
feb621
+  *
feb621
+  * This library is free software; you can redistribute it and/or
feb621
+  * modify it under the terms of the GNU Library General Public
feb621
+  * License version 2 as published by the Free Software Foundation.
feb621
+  *
feb621
+  * This library is distributed in the hope that it will be useful,
feb621
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
feb621
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
feb621
+  * Library General Public License for more details.
feb621
+  *
feb621
+  * You should have received a copy of the GNU Library General Public License
feb621
+  * along with this library; see the file COPYING.LIB.  If not, write to
feb621
+  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
feb621
+  * Boston, MA 02110-1301, USA.
feb621
+  */
feb621
+#ifndef KNEWWALLETDIALOG_H
feb621
+#define KNEWWALLETDIALOG_H
feb621
+
feb621
+#include <QWizard>
feb621
+
feb621
+#include "ui_knewwalletdialogintro.h"
feb621
+#include "ui_knewwalletdialoggpg.h"
feb621
+#include <boost/shared_ptr.hpp>
feb621
+
feb621
+namespace GpgME {
feb621
+class Key;
feb621
+}
feb621
+
feb621
+namespace KWallet {
feb621
+
feb621
+class KNewWalletDialogIntro;
feb621
+class KNewWalletDialogGpg;
feb621
+
feb621
+class KNewWalletDialog : public QWizard {
feb621
+    Q_OBJECT
feb621
+public:
feb621
+    KNewWalletDialog(const QString &appName, const QString &walletName, QWidget* parent = 0);
feb621
+
feb621
+    bool isBlowfish() const;
feb621
+    int gpgId() const { return _gpgId; }
feb621
+    GpgME::Key gpgKey() const;
feb621
+private:
feb621
+    KNewWalletDialogIntro   *_intro;
feb621
+    int                     _introId;
feb621
+    KNewWalletDialogGpg     *_gpg;
feb621
+    int                     _gpgId;
feb621
+};
feb621
+
feb621
+class KNewWalletDialogIntro : public QWizardPage {
feb621
+    Q_OBJECT
feb621
+public:
feb621
+    KNewWalletDialogIntro(const QString &appName, const QString &walletName, QWidget* parent = 0);
feb621
+    bool isBlowfish() const;
feb621
+    virtual int nextId() const;
feb621
+protected Q_SLOTS:
feb621
+    void onBlowfishToggled(bool);
feb621
+private:
feb621
+    Ui_KNewWalletDialogIntro _ui;
feb621
+};
feb621
+
feb621
+class KNewWalletDialogGpg : public QWizardPage {
feb621
+    Q_OBJECT
feb621
+public:
feb621
+    KNewWalletDialogGpg(const QString &appName, const QString &walletName, QWidget* parent = 0);
feb621
+    virtual void initializePage();
feb621
+    virtual bool isComplete() const;
feb621
+    virtual bool validateCurrentPage();
feb621
+protected Q_SLOTS:
feb621
+    void onItemSelectionChanged();
feb621
+private:
feb621
+    bool                    _alreadyInitialized;
feb621
+    Ui_KNewWalletDialogGpg  _ui;
feb621
+    bool                    _complete;
feb621
+};
feb621
+
feb621
+} // namespace
feb621
+
feb621
+#endif // KNEWWALLETDIALOG_H
feb621
diff -Nur kwalletd.than/knewwalletdialogintro.ui kwalletd/knewwalletdialogintro.ui
feb621
--- kwalletd.than/knewwalletdialogintro.ui	1970-01-01 01:00:00.000000000 +0100
feb621
+++ kwalletd/knewwalletdialogintro.ui	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -0,0 +1,128 @@
feb621
+
feb621
+<ui version="4.0">
feb621
+ <class>KNewWalletDialogIntro</class>
feb621
+ <widget class="QWidget" name="KNewWalletDialogIntro">
feb621
+  <property name="geometry">
feb621
+   <rect>
feb621
+    <x>0</x>
feb621
+    <y>0</y>
feb621
+    <width>341</width>
feb621
+    <height>190</height>
feb621
+   </rect>
feb621
+  </property>
feb621
+  <layout class="QVBoxLayout" name="verticalLayout_2">
feb621
+   <item>
feb621
+    <widget class="KTitleWidget" name="ktitlewidget">
feb621
+     <property name="comment">
feb621
+      <string>The KDE Wallet System</string>
feb621
+     </property>
feb621
+    </widget>
feb621
+   </item>
feb621
+   <item>
feb621
+    <widget class="QLabel" name="labelIntro">
feb621
+     <property name="sizePolicy">
feb621
+      <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
feb621
+       <horstretch>0</horstretch>
feb621
+       <verstretch>0</verstretch>
feb621
+      </sizepolicy>
feb621
+     </property>
feb621
+     <property name="text">
feb621
+      <string><html><head/><body><p>The application '<span style=" font-weight:600;">%1</span>' has requested to open the KDE wallet. This is used to store sensitive data in a secure fashion. Please choose the new wallet's type below or click cancel to deny the application's request.</p></body></html></string>
feb621
+     </property>
feb621
+     <property name="textFormat">
feb621
+      <enum>Qt::RichText</enum>
feb621
+     </property>
feb621
+     <property name="alignment">
feb621
+      <set>Qt::AlignVCenter</set>
feb621
+     </property>
feb621
+     <property name="wordWrap">
feb621
+      <bool>true</bool>
feb621
+     </property>
feb621
+     <property name="margin">
feb621
+      <number>12</number>
feb621
+     </property>
feb621
+    </widget>
feb621
+   </item>
feb621
+   <item>
feb621
+    <layout class="QHBoxLayout" name="horizontalLayout">
feb621
+     <item>
feb621
+      <spacer name="horizontalSpacer">
feb621
+       <property name="orientation">
feb621
+        <enum>Qt::Horizontal</enum>
feb621
+       </property>
feb621
+       <property name="sizeHint" stdset="0">
feb621
+        <size>
feb621
+         <width>40</width>
feb621
+         <height>20</height>
feb621
+        </size>
feb621
+       </property>
feb621
+      </spacer>
feb621
+     </item>
feb621
+     <item>
feb621
+      <layout class="QVBoxLayout" name="verticalLayout">
feb621
+       <item>
feb621
+        <widget class="QRadioButton" name="radioBlowfish">
feb621
+         <property name="text">
feb621
+          <string>Classic, blowfish encrypted file</string>
feb621
+         </property>
feb621
+        </widget>
feb621
+       </item>
feb621
+       <item>
feb621
+        <widget class="QRadioButton" name="radioGpg">
feb621
+         <property name="text">
feb621
+          <string>Use GPG encryption, for better protection</string>
feb621
+         </property>
feb621
+         <property name="checked">
feb621
+          <bool>true</bool>
feb621
+         </property>
feb621
+        </widget>
feb621
+       </item>
feb621
+      </layout>
feb621
+     </item>
feb621
+     <item>
feb621
+      <spacer name="horizontalSpacer_2">
feb621
+       <property name="orientation">
feb621
+        <enum>Qt::Horizontal</enum>
feb621
+       </property>
feb621
+       <property name="sizeHint" stdset="0">
feb621
+        <size>
feb621
+         <width>40</width>
feb621
+         <height>20</height>
feb621
+        </size>
feb621
+       </property>
feb621
+      </spacer>
feb621
+     </item>
feb621
+    </layout>
feb621
+   </item>
feb621
+  </layout>
feb621
+ </widget>
feb621
+ <customwidgets>
feb621
+  <customwidget>
feb621
+   <class>KTitleWidget</class>
feb621
+   <extends>QWidget</extends>
feb621
+   <header>ktitlewidget.h</header>
feb621
+  </customwidget>
feb621
+ </customwidgets>
feb621
+ <resources/>
feb621
+ <connections>
feb621
+  <connection>
feb621
+   <sender>radioBlowfish</sender>
feb621
+   <signal>toggled(bool)</signal>
feb621
+   <receiver>KNewWalletDialogIntro</receiver>
feb621
+   <slot>onBlowfishToggled(bool)</slot>
feb621
+   <hints>
feb621
+    <hint type="sourcelabel">
feb621
+     <x>31</x>
feb621
+     <y>144</y>
feb621
+    </hint>
feb621
+    <hint type="destinationlabel">
feb621
+     <x>2</x>
feb621
+     <y>138</y>
feb621
+    </hint>
feb621
+   </hints>
feb621
+  </connection>
feb621
+ </connections>
feb621
+ <slots>
feb621
+  <slot>onBlowfishToggled(bool)</slot>
feb621
+ </slots>
feb621
+</ui>
feb621
diff -Nur kwalletd.than/kwalletd.cpp kwalletd/kwalletd.cpp
feb621
--- kwalletd.than/kwalletd.cpp	2013-06-28 19:12:33.340802830 +0200
feb621
+++ kwalletd/kwalletd.cpp	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -27,6 +27,10 @@
feb621
 #include "kbetterthankdialog.h"
feb621
 #include "kwalletwizard.h"
feb621
 
feb621
+#ifdef HAVE_QGPGME
feb621
+#include "knewwalletdialog.h"
feb621
+#endif
feb621
+
feb621
 #include <kuniqueapplication.h>
feb621
 #include <ktoolinvocation.h>
feb621
 #include <kconfig.h>
feb621
@@ -45,6 +49,9 @@
feb621
 #include <kpluginfactory.h>
feb621
 #include <kpluginloader.h>
feb621
 #include <KNotification>
feb621
+#ifdef HAVE_QGPGME
feb621
+#include <gpgme++/key.h>
feb621
+#endif
feb621
 
feb621
 #include <QtCore/QDir>
feb621
 #include <QTextDocument> // Qt::escape
feb621
@@ -55,13 +62,12 @@
feb621
 #include <assert.h>
feb621
 
feb621
 #include "kwalletadaptor.h"
feb621
-#include "kwalletopenloop.h"
feb621
 
feb621
 class KWalletTransaction {
feb621
 
feb621
     public:
feb621
-        KWalletTransaction()
feb621
-            : tType(Unknown), cancelled(false), tId(nextTransactionId)
feb621
+        explicit KWalletTransaction(QDBusConnection conn)
feb621
+            : tType(Unknown), cancelled(false), tId(nextTransactionId), res(-1), connection(conn)
feb621
         {
feb621
             nextTransactionId++;
feb621
             // make sure the id is never < 0 as that's used for the
feb621
@@ -90,6 +96,9 @@
feb621
         bool modal;
feb621
         bool isPath;
feb621
         int tId; // transaction id
feb621
+        int res;
feb621
+        QDBusMessage message;
feb621
+        QDBusConnection connection;
feb621
 
feb621
     private:
feb621
         static int nextTransactionId;
feb621
@@ -98,7 +107,10 @@
feb621
 int KWalletTransaction::nextTransactionId = 0;
feb621
 
feb621
 KWalletD::KWalletD()
feb621
- : QObject(0), _failed(0), _syncTime(5000), _curtrans(0) {
feb621
+ : QObject(0), _failed(0), _syncTime(5000), _curtrans(0), _useGpg(false) {
feb621
+#ifdef HAVE_QGPGME
feb621
+     _useGpg = true;
feb621
+#endif
feb621
 
feb621
 	srand(time(0));
feb621
 	_showingFailureNotify = false;
feb621
@@ -113,7 +125,7 @@
feb621
 	QDBusConnection::sessionBus().registerObject(QLatin1String("/modules/kwalletd"), this);
feb621
 
feb621
 #ifdef Q_WS_X11
feb621
-	screensaver = new QDBusInterface("org.freedesktop.ScreenSaver", "/ScreenSaver", "org.freedesktop.ScreenSaver");
feb621
+    screensaver = 0;
feb621
 #endif
feb621
 
feb621
 	reconfigure();
feb621
@@ -138,6 +150,20 @@
feb621
 	qDeleteAll(_transactions);
feb621
 }
feb621
 
feb621
+#ifdef Q_WS_X11
feb621
+void KWalletD::connectToScreenSaver()
feb621
+{
feb621
+    screensaver = new QDBusInterface("org.freedesktop.ScreenSaver", "/ScreenSaver", "org.freedesktop.ScreenSaver");
feb621
+    if (!screensaver->isValid()) {
feb621
+        kDebug() << "Service org.freedesktop.ScreenSaver not found. Retrying in 10 seconds...";
feb621
+        // keep attempting every 10 seconds
feb621
+        QTimer::singleShot(10000, this, SLOT(connectToScreenSaver()));
feb621
+    } else {
feb621
+        connect(screensaver, SIGNAL(ActiveChanged(bool)), SLOT(screenSaverChanged(bool)));
feb621
+        kDebug() << "connected to screen saver service.";
feb621
+    }
feb621
+}
feb621
+#endif
feb621
 
feb621
 int KWalletD::generateHandle() {
feb621
 	int rc;
feb621
@@ -198,7 +224,7 @@
feb621
 				} else if (_curtrans->cancelled) {
feb621
 					// the wallet opened successfully but the application
feb621
 					// opening exited/crashed while the dialog was still shown.
feb621
-					KWalletTransaction *_xact = new KWalletTransaction();
feb621
+					KWalletTransaction *_xact = new KWalletTransaction(_curtrans->connection);
feb621
 					_xact->tType = KWalletTransaction::CloseCancelled;
feb621
 					_xact->appid = _curtrans->appid;
feb621
 					_xact->wallet = _curtrans->wallet;
feb621
@@ -207,11 +233,13 @@
feb621
 				}
feb621
 
feb621
 				// emit the AsyncOpened signal as a reply
feb621
+				_curtrans->res = res;
feb621
 				emit walletAsyncOpened(_curtrans->tId, res);
feb621
 				break;
feb621
 
feb621
 			case KWalletTransaction::OpenFail:
feb621
 				// emit the AsyncOpened signal with an invalid handle
feb621
+                _curtrans->res = -1;
feb621
 				emit walletAsyncOpened(_curtrans->tId, -1);
feb621
 				break;
feb621
 
feb621
@@ -230,6 +258,15 @@
feb621
 				break;
feb621
 		}
feb621
 
feb621
+		// send delayed dbus message reply to the caller
feb621
+		if (_curtrans->message.type() != QDBusMessage::InvalidMessage) {
feb621
+            if (_curtrans->connection.isConnected()) {
feb621
+                QDBusMessage reply = _curtrans->message.createReply();
feb621
+                reply << _curtrans->res;
feb621
+                _curtrans->connection.send(reply);
feb621
+            }
feb621
+        }
feb621
+
feb621
 		delete _curtrans;
feb621
 		_curtrans = 0;
feb621
 	}
feb621
@@ -237,28 +274,45 @@
feb621
 	_processing = false;
feb621
 }
feb621
 
feb621
-
feb621
-
feb621
 int KWalletD::openPath(const QString& path, qlonglong wId, const QString& appid) {
feb621
 	int tId = openPathAsync(path, wId, appid, false);
feb621
 	if (tId < 0) {
feb621
 		return tId;
feb621
 	}
feb621
 
feb621
+	// NOTE the real return value will be sent by the dbusmessage delayed reply
feb621
+	return 0;
feb621
 	// wait for the open-transaction to be processed
feb621
-	KWalletOpenLoop loop(this);
feb621
-	return loop.waitForAsyncOpen(tId);
feb621
+// 	KWalletOpenLoop loop(this);
feb621
+// 	return loop.waitForAsyncOpen(tId);
feb621
 }
feb621
 
feb621
 int KWalletD::open(const QString& wallet, qlonglong wId, const QString& appid) {
feb621
-	int tId = openAsync(wallet, wId, appid, false);
feb621
-	if (tId < 0) {
feb621
-		return tId;
feb621
-	}
feb621
-
feb621
-	// wait for the open-transaction to be processed
feb621
-	KWalletOpenLoop loop(this);
feb621
-	return loop.waitForAsyncOpen(tId);
feb621
+    if (!_enabled) { // guard
feb621
+        return -1;
feb621
+    }
feb621
+
feb621
+    if (!QRegExp("^[\\w\\^\\&\\'\\@\\{\\}\\[\\]\\,\\$\\=\\!\\-\\#\\(\\)\\%\\.\\+\\_\\s]+$").exactMatch(wallet)) {
feb621
+        return -1;
feb621
+    }
feb621
+
feb621
+    KWalletTransaction *xact = new KWalletTransaction(connection());
feb621
+    _transactions.append(xact);
feb621
+
feb621
+    message().setDelayedReply(true);
feb621
+    xact->message = message();
feb621
+
feb621
+    xact->appid = appid;
feb621
+    xact->wallet = wallet;
feb621
+    xact->wId = wId;
feb621
+    xact->modal = true; // mark dialogs as modal, the app has blocking wait
feb621
+    xact->tType = KWalletTransaction::Open;
feb621
+    xact->isPath = false;
feb621
+
feb621
+    QTimer::singleShot(0, this, SLOT(processTransactions()));
feb621
+    checkActiveDialog();
feb621
+    // NOTE the real return value will be sent by the dbusmessage delayed reply
feb621
+    return 0;
feb621
 }
feb621
 
feb621
 int KWalletD::openAsync(const QString& wallet, qlonglong wId, const QString& appid,
feb621
@@ -271,8 +325,8 @@
feb621
 		return -1;
feb621
 	}
feb621
 
feb621
-	KWalletTransaction *xact = new KWalletTransaction;
feb621
-	_transactions.append(xact);
feb621
+	KWalletTransaction *xact = new KWalletTransaction(connection());
feb621
+    _transactions.append(xact);
feb621
 
feb621
 	xact->appid = appid;
feb621
 	xact->wallet = wallet;
feb621
@@ -298,8 +352,8 @@
feb621
 		return -1;
feb621
 	}
feb621
 
feb621
-	KWalletTransaction *xact = new KWalletTransaction;
feb621
-	_transactions.append(xact);
feb621
+    KWalletTransaction *xact = new KWalletTransaction(connection());
feb621
+    _transactions.append(xact);
feb621
 
feb621
 	xact->appid = appid;
feb621
 	xact->wallet = path;
feb621
@@ -365,6 +419,7 @@
feb621
                                 qlonglong wId, bool modal, const QString& service) {
feb621
 	if (_firstUse && !wallets().contains(KWallet::Wallet::LocalWallet()) && !isPath) {
feb621
 		// First use wizard
feb621
+		// TODO GPG adjust new smartcard options gathered by the wizard
feb621
 		QPointer<KWalletWizard> wiz = new KWalletWizard(0);
feb621
 		wiz->setWindowTitle(i18n("KDE Wallet Service"));
feb621
 		setupDialog( wiz, (WId)wId, appid, modal );
feb621
@@ -386,11 +441,23 @@
feb621
 			}
feb621
 
feb621
 			// Create the wallet
feb621
+            // TODO GPG select the correct wallet type upon cretion (GPG or blowfish based)
feb621
 			KWallet::Backend *b = new KWallet::Backend(KWallet::Wallet::LocalWallet());
feb621
-			QString pass = wiz->field("pass1").toString();
feb621
-			QByteArray p(pass.toUtf8(), pass.length());
feb621
-			b->open(p);
feb621
-			p.fill(0);
feb621
+#ifdef HAVE_QGPGME
feb621
+            if (wiz->field("useBlowfish").toBool()) {
feb621
+                b->setCipherType(KWallet::BACKEND_CIPHER_BLOWFISH);
feb621
+#endif
feb621
+                QString pass = wiz->field("pass1").toString();
feb621
+                QByteArray p(pass.toUtf8(), pass.length());
feb621
+                b->open(p);
feb621
+                p.fill(0);
feb621
+#ifdef HAVE_QGPGME
feb621
+            } else {
feb621
+                assert(wiz->field("useGpg").toBool());
feb621
+                b->setCipherType(KWallet::BACKEND_CIPHER_GPG);
feb621
+                b->open(wiz->gpgKey());
feb621
+            }
feb621
+#endif
feb621
 			b->createFolder(KWallet::Wallet::PasswordFolder());
feb621
 			b->createFolder(KWallet::Wallet::FormDataFolder());
feb621
 			b->close(true);
feb621
@@ -439,7 +506,20 @@
feb621
 		QString password;
feb621
 		bool emptyPass = false;
feb621
 		if ((isPath && QFile::exists(wallet)) || (!isPath && KWallet::Backend::exists(wallet))) {
feb621
-			int pwless = b->open(QByteArray());
feb621
+            // this open attempt will set wallet type from the file header, even if password is needed
feb621
+			int pwless = b->open(QByteArray(), w);
feb621
+#ifdef HAVE_QGPGME
feb621
+            assert(b->cipherType() != KWallet::BACKEND_CIPHER_UNKNOWN);
feb621
+            if (b->cipherType() == KWallet::BACKEND_CIPHER_GPG) {
feb621
+                // GPG based wallets do not prompt for password here. Instead, GPG should already have popped pinentry utility for wallet decryption
feb621
+                if (!b->isOpen()){
feb621
+                    // for some reason, GPG operation failed
feb621
+                    delete b;
feb621
+                    return -1;
feb621
+                }
feb621
+                emptyPass = true;
feb621
+            } else {
feb621
+#endif
feb621
 			if (0 != pwless || !b->isOpen()) {
feb621
 				if (pwless == 0) {
feb621
 					// release, start anew
feb621
@@ -500,7 +580,33 @@
feb621
 			} else {
feb621
 				emptyPass = true;
feb621
 			}
feb621
+#ifdef HAVE_QGPGME
feb621
+            }
feb621
+#endif
feb621
 		} else {
feb621
+            brandNew = true;
feb621
+#ifdef HAVE_QGPGME
feb621
+            // prompt the user for the new wallet format here
feb621
+            KWallet::BackendCipherType newWalletType = KWallet::BACKEND_CIPHER_UNKNOWN;
feb621
+
feb621
+            boost::shared_ptr<KWallet::KNewWalletDialog> newWalletDlg( new KWallet::KNewWalletDialog(appid, wallet, QWidget::find(w)));
feb621
+            GpgME::Key gpgKey;
feb621
+            setupDialog( newWalletDlg.get(), (WId)w, appid, true );
feb621
+            if (newWalletDlg->exec() == QDialog::Accepted) {
feb621
+                newWalletType = newWalletDlg->isBlowfish() ? KWallet::BACKEND_CIPHER_BLOWFISH : KWallet::BACKEND_CIPHER_GPG;
feb621
+                gpgKey = newWalletDlg->gpgKey();
feb621
+            } else {
feb621
+                // user cancelled the dialog box
feb621
+                delete b;
feb621
+                return -1;
feb621
+            }
feb621
+            
feb621
+            if (newWalletType == KWallet::BACKEND_CIPHER_GPG) {
feb621
+                b->setCipherType(newWalletType);
feb621
+                b->open(gpgKey);
feb621
+            } else if (newWalletType == KWallet::BACKEND_CIPHER_BLOWFISH) {
feb621
+#endif // HAVE_QGPGME
feb621
+            b->setCipherType(KWallet::BACKEND_CIPHER_BLOWFISH);
feb621
 			KNewPasswordDialog *kpd = new KNewPasswordDialog();
feb621
 			if (wallet == KWallet::Wallet::LocalWallet() ||
feb621
 						 wallet == KWallet::Wallet::NetworkWallet())
feb621
@@ -518,7 +624,6 @@
feb621
 					kpd->setPrompt(i18n("<qt>The application '%1' has requested to create a new wallet named '%2'. Please choose a password for this wallet, or cancel to deny the application's request.</qt>", Qt::escape(appid), Qt::escape(wallet)));
feb621
 				}
feb621
 			}
feb621
-			brandNew = true;
feb621
 			kpd->setCaption(i18n("KDE Wallet Service"));
feb621
 			kpd->setButtonGuiItem(KDialog::Ok,KGuiItem(i18n("C&reate"),"document-new"));
feb621
 			kpd->setPixmap(KIcon("kwalletmanager").pixmap(96, 96));
feb621
@@ -535,16 +640,19 @@
feb621
 				}
feb621
 			}
feb621
 			delete kpd;
feb621
+#ifdef HAVE_QGPGME
feb621
+            }
feb621
+#endif
feb621
 		}
feb621
 
feb621
-
feb621
-
feb621
-		if (!emptyPass && (password.isNull() || !b->isOpen())) {
feb621
+        
feb621
+		if ((b->cipherType() == KWallet::BACKEND_CIPHER_BLOWFISH) && 
feb621
+            !emptyPass && (password.isNull() || !b->isOpen())) {
feb621
 			delete b;
feb621
 			return -1;
feb621
 		}
feb621
 
feb621
-		if (emptyPass && _openPrompt && !isAuthorizedApp(appid, wallet, w)) {
feb621
+		if (emptyPass && !isAuthorizedApp(appid, wallet, w)) {
feb621
 			delete b;
feb621
 			return -1;
feb621
 		}
feb621
@@ -598,6 +706,10 @@
feb621
 
feb621
 
feb621
 bool KWalletD::isAuthorizedApp(const QString& appid, const QString& wallet, WId w) {
feb621
+	if (!_openPrompt) {
feb621
+		return true;
feb621
+	}
feb621
+
feb621
 	int response = 0;
feb621
 
feb621
 	QString thisApp;
feb621
@@ -655,6 +767,7 @@
feb621
 
feb621
 
feb621
 int KWalletD::deleteWallet(const QString& wallet) {
feb621
+    int result = -1;
feb621
 	QString path = KGlobal::dirs()->saveLocation("kwallet") + QDir::separator() + wallet + ".kwl";
feb621
 
feb621
 	if (QFile::exists(path)) {
feb621
@@ -662,17 +775,27 @@
feb621
 		internalClose(walletInfo.second, walletInfo.first, true);
feb621
 		QFile::remove(path);
feb621
 		emit walletDeleted(wallet);
feb621
-		return 0;
feb621
+        // also delete access control entries
feb621
+        KConfigGroup cfgAllow = KSharedConfig::openConfig("kwalletrc")->group("Auto Allow");
feb621
+        cfgAllow.deleteEntry(wallet);
feb621
+
feb621
+        KConfigGroup cfgDeny = KSharedConfig::openConfig("kwalletrc")->group("Auto Deny");
feb621
+        cfgDeny.deleteEntry(wallet);
feb621
+
feb621
+        result = 0;
feb621
 	}
feb621
 
feb621
-	return -1;
feb621
+	return result;
feb621
 }
feb621
 
feb621
 
feb621
 void KWalletD::changePassword(const QString& wallet, qlonglong wId, const QString& appid) {
feb621
-	KWalletTransaction *xact = new KWalletTransaction;
feb621
+	KWalletTransaction *xact = new KWalletTransaction(connection());
feb621
+
feb621
+    message().setDelayedReply(true);
feb621
+    xact->message = message();
feb621
+	// TODO GPG this shouldn't be allowed on a GPG managed wallet; a warning should be displayed about this
feb621
 
feb621
-	//msg.setDelayedReply(true);
feb621
 	xact->appid = appid;
feb621
 	xact->wallet = wallet;
feb621
 	xact->wId = wId;
feb621
@@ -712,30 +835,40 @@
feb621
 
feb621
 	assert(w);
feb621
 
feb621
-	QPointer<KNewPasswordDialog> kpd = new KNewPasswordDialog();
feb621
-	kpd->setPrompt(i18n("<qt>Please choose a new password for the wallet '%1'.</qt>", Qt::escape(wallet)));
feb621
-	kpd->setCaption(i18n("KDE Wallet Service"));
feb621
-	kpd->setAllowEmptyPasswords(true);
feb621
-	setupDialog( kpd, (WId)wId, appid, false );
feb621
-	if (kpd->exec() == KDialog::Accepted && kpd) {
feb621
-		QString p = kpd->password();
feb621
-		if (!p.isNull()) {
feb621
-			w->setPassword(p.toUtf8());
feb621
-			int rc = w->close(true);
feb621
-			if (rc < 0) {
feb621
-				KMessageBox::sorryWId((WId)wId, i18n("Error re-encrypting the wallet. Password was not changed."), i18n("KDE Wallet Service"));
feb621
-				reclose = true;
feb621
-			} else {
feb621
-				rc = w->open(p.toUtf8());
feb621
-				if (rc < 0) {
feb621
-					KMessageBox::sorryWId((WId)wId, i18n("Error reopening the wallet. Data may be lost."), i18n("KDE Wallet Service"));
feb621
-					reclose = true;
feb621
-				}
feb621
-			}
feb621
-		}
feb621
-	}
feb621
+#ifdef HAVE_QGPGME
feb621
+    if (w->cipherType() == KWallet::BACKEND_CIPHER_GPG) {
feb621
+        QString keyID = w->gpgKey().shortKeyID();
feb621
+        assert(!keyID.isNull());
feb621
+        KMessageBox::errorWId((WId)wId, i18n("<qt>The %1 wallet is encrypted using GPG key %2. Please use GPG tools (such as kleopatra) to change the passphrase associated to that key.</qt>", Qt::escape(wallet), keyID));
feb621
+    } else {
feb621
+#endif
feb621
+        QPointer<KNewPasswordDialog> kpd = new KNewPasswordDialog();
feb621
+        kpd->setPrompt(i18n("<qt>Please choose a new password for the wallet '%1'.</qt>", Qt::escape(wallet)));
feb621
+        kpd->setCaption(i18n("KDE Wallet Service"));
feb621
+        kpd->setAllowEmptyPasswords(true);
feb621
+        setupDialog( kpd, (WId)wId, appid, false );
feb621
+        if (kpd->exec() == KDialog::Accepted && kpd) {
feb621
+            QString p = kpd->password();
feb621
+            if (!p.isNull()) {
feb621
+                w->setPassword(p.toUtf8());
feb621
+                int rc = w->close(true);
feb621
+                if (rc < 0) {
feb621
+                    KMessageBox::sorryWId((WId)wId, i18n("Error re-encrypting the wallet. Password was not changed."), i18n("KDE Wallet Service"));
feb621
+                    reclose = true;
feb621
+                } else {
feb621
+                    rc = w->open(p.toUtf8());
feb621
+                    if (rc < 0) {
feb621
+                        KMessageBox::sorryWId((WId)wId, i18n("Error reopening the wallet. Data may be lost."), i18n("KDE Wallet Service"));
feb621
+                        reclose = true;
feb621
+                    }
feb621
+                }
feb621
+            }
feb621
+        }
feb621
 
feb621
-	delete kpd;
feb621
+        delete kpd;
feb621
+#ifdef HAVE_QGPGME
feb621
+    }
feb621
+#endif
feb621
 
feb621
 	if (reclose) {
feb621
 		internalClose(w, handle, true);
feb621
@@ -842,14 +975,14 @@
feb621
 	// get the wallet and check if we have a password for it (safety measure)
feb621
 	if ((b = getWallet(appid, handle))) {
feb621
 		QString wallet = b->walletName();
feb621
-		b->sync();
feb621
+		b->sync(0);
feb621
 	}
feb621
 }
feb621
 
feb621
 void KWalletD::timedOutSync(int handle) {
feb621
 	_syncTimers.removeTimer(handle);
feb621
 	if (_wallets.contains(handle) && _wallets[handle]) {
feb621
-		_wallets[handle]->sync();
feb621
+		_wallets[handle]->sync(0);
feb621
 	}
feb621
 }
feb621
 
feb621
@@ -1317,18 +1450,22 @@
feb621
 	_leaveOpen = walletGroup.readEntry("Leave Open", false);
feb621
 	bool idleSave = _closeIdle;
feb621
 	_closeIdle = walletGroup.readEntry("Close When Idle", false);
feb621
-	_openPrompt = walletGroup.readEntry("Prompt on Open", true);
feb621
+	_openPrompt = walletGroup.readEntry("Prompt on Open", false);
feb621
 	int timeSave = _idleTime;
feb621
 	// in minutes!
feb621
 	_idleTime = walletGroup.readEntry("Idle Timeout", 10) * 60 * 1000;
feb621
 #ifdef Q_WS_X11
feb621
-	if ( screensaver->isValid() ) {
feb621
-		if (walletGroup.readEntry("Close on Screensaver", false)) {
feb621
-			connect(screensaver, SIGNAL(ActiveChanged(bool)), SLOT(screenSaverChanged(bool)));
feb621
-		} else {
feb621
-			screensaver->disconnect(SIGNAL(ActiveChanged(bool)), this, SLOT(screenSaverChanged(bool)));
feb621
-		}
feb621
-	}
feb621
+    if (walletGroup.readEntry("Close on Screensaver", false)) {
feb621
+        // BUG 254273 : if kwalletd starts before the screen saver, then the connection fails and kwalletd never receives it's notifications
feb621
+        // To fix this, we use a timer and perform periodic connection attempts until connection succeeds
feb621
+        QTimer::singleShot(0, this, SLOT(connectToScreenSaver()));
feb621
+    } else {
feb621
+        if (screensaver && screensaver->isValid()) {
feb621
+            screensaver->disconnect(SIGNAL(ActiveChanged(bool)), this, SLOT(screenSaverChanged(bool)));
feb621
+            delete screensaver;
feb621
+            screensaver = 0;
feb621
+        }
feb621
+    }
feb621
 #endif
feb621
 	// Handle idle changes
feb621
 	if (_closeIdle) {
feb621
diff -Nur kwalletd.than/kwalletd.desktop kwalletd/kwalletd.desktop
feb621
--- kwalletd.than/kwalletd.desktop	2013-06-28 19:12:33.340802830 +0200
feb621
+++ kwalletd/kwalletd.desktop	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -18,13 +18,13 @@
feb621
 Name[cs]=Server úschovny
feb621
 Name[csb]=Serwera Wallet
feb621
 Name[da]=Wallet-server
feb621
-Name[de]=Digitale Brieftasche
feb621
+Name[de]=Passwortspeicher-Server
feb621
 Name[el]=Εξυπηρετητής πορτοφολιού
feb621
 Name[en_GB]=Wallet Server
feb621
 Name[eo]=Servilo de portilo
feb621
 Name[es]=Servidor de carteras
feb621
 Name[et]=Turvalaeka server
feb621
-Name[eu]=Zorro-zerbitzua
feb621
+Name[eu]=Zorro-zerbitzaria
feb621
 Name[fa]=خادم کیف‌پول
feb621
 Name[fi]=Lompakkopalvelin
feb621
 Name[fr]=Serveur de portefeuilles
feb621
@@ -62,7 +62,7 @@
feb621
 Name[pa]=ਵਾਲਿਟ ਸਰਵਰ
feb621
 Name[pl]=Serwer Portfela
feb621
 Name[pt]=Servidor da Carteira
feb621
-Name[pt_BR]=Servidor da carteira
feb621
+Name[pt_BR]=Servidor de carteiras
feb621
 Name[ro]=Server de portofel
feb621
 Name[ru]=Wallet Server
feb621
 Name[si]=පසුම්බි ධාරකය
feb621
@@ -98,13 +98,13 @@
feb621
 Comment[cs]=Server úschovny
feb621
 Comment[csb]=Serwera Wallet
feb621
 Comment[da]=Wallet-server
feb621
-Comment[de]=Dienst für die digitale Brieftasche
feb621
+Comment[de]=Passwortspeicher-Server
feb621
 Comment[el]=Εξυπηρετητής πορτοφολιού
feb621
 Comment[en_GB]=Wallet Server
feb621
 Comment[eo]=Servilo de portilo
feb621
 Comment[es]=Servidor de carteras
feb621
 Comment[et]=Turvalaeka server
feb621
-Comment[eu]=Zorro-zerbitzua
feb621
+Comment[eu]=Zorro-zerbitzaria
feb621
 Comment[fa]=خادم کیف‌پول
feb621
 Comment[fi]=Lompakkopalvelin
feb621
 Comment[fr]=Serveur de portefeuilles
feb621
@@ -142,7 +142,7 @@
feb621
 Comment[pa]=ਵਾਲਿਟ ਸਰਵਰ
feb621
 Comment[pl]=Serwer Portfela
feb621
 Comment[pt]=Servidor da Carteira
feb621
-Comment[pt_BR]=Servidor da carteira
feb621
+Comment[pt_BR]=Servidor de carteiras
feb621
 Comment[ro]=Server de portofel
feb621
 Comment[ru]=Служба бумажника
feb621
 Comment[si]=පසුම්බි ධාරකය
feb621
diff -Nur kwalletd.than/kwalletd.h kwalletd/kwalletd.h
feb621
--- kwalletd.than/kwalletd.h	2013-06-28 19:12:33.340802830 +0200
feb621
+++ kwalletd/kwalletd.h	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -42,7 +42,6 @@
feb621
 
feb621
 // @Private
feb621
 class KWalletTransaction;
feb621
-class KWalletSyncTimer;
feb621
 class KWalletSessionStore;
feb621
 
feb621
 class KWalletD : public QObject, protected QDBusContext {
feb621
@@ -183,6 +182,9 @@
feb621
 		void notifyFailures();
feb621
 		void processTransactions();
feb621
 		void activatePasswordDialog();
feb621
+#ifdef Q_WS_X11
feb621
+        void connectToScreenSaver();
feb621
+#endif
feb621
 
feb621
 	private:
feb621
 		// Internal - open a wallet
feb621
@@ -241,6 +243,8 @@
feb621
 		// sessions
feb621
 		KWalletSessionStore _sessions;
feb621
         QDBusServiceWatcher _serviceWatcher;
feb621
+
feb621
+        bool _useGpg;
feb621
 };
feb621
 
feb621
 
feb621
diff -Nur kwalletd.than/kwalletd.notifyrc kwalletd/kwalletd.notifyrc
feb621
--- kwalletd.than/kwalletd.notifyrc	2013-06-28 19:12:33.555794274 +0200
feb621
+++ kwalletd/kwalletd.notifyrc	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -10,7 +10,7 @@
feb621
 Comment[ca@valencia]=Cartera
feb621
 Comment[cs]=Úschovna
feb621
 Comment[da]=Tegnebog
feb621
-Comment[de]=Brieftasche
feb621
+Comment[de]=Passwortspeicher
feb621
 Comment[el]=Πορτοφόλι
feb621
 Comment[en_GB]=Wallet
feb621
 Comment[eo]=Portilo
feb621
@@ -226,18 +226,20 @@
feb621
 Comment[cs]=Démon úschovny KDE požaduje heslo
feb621
 Comment[csb]=Demóna KDE Wallet żądô parolë
feb621
 Comment[da]=Dæmonen for KDE's tegnebog anmoder om en adgangskode
feb621
-Comment[de]=Die digitale Brieftasche benötigt ein Passwort
feb621
+Comment[de]=Der Passwortspeicher benötigt ein Passwort
feb621
 Comment[el]=Ο δαίμονας πορτοφολιού του KDE απαιτεί έναν κωδικό πρόσβασης
feb621
 Comment[en_GB]=The KDE Wallet Dæmon requests a password
feb621
 Comment[eo]=la demono de portilo de KDE postulas pasvorton
feb621
 Comment[es]=El demonio de la cartera de KDE requiere una contraseña
feb621
 Comment[et]=KDE turvalaeka deemon nõuab parooli
feb621
-Comment[eu]=KDE diruzorroaren deabruak pasahitza eskatzen du
feb621
+Comment[eu]=KDEren zorroaren daemon-ak pasahitza eskatzen du
feb621
+Comment[fa]=شبح Wallte کی‌دی‌ای رمزعبوری را درخواست میکند
feb621
 Comment[fi]=KDE:n Lompakkotaustaprosessi pyytää salasanaa
feb621
 Comment[fr]=Le démon du portefeuille de KDE demande un mot de passe
feb621
 Comment[fy]=The KDE slûf daemon fereasket in wachtwurd
feb621
 Comment[ga]=Tá Deamhan Sparáin KDE ag iarraidh focal faire
feb621
 Comment[gl]=O Daemon de carteiras de KDE pide un contrasinal
feb621
+Comment[gu]=KDE વોલેટ ડેમને પાસવર્ડની માંગ કરી છે
feb621
 Comment[he]=תהליך הרקע של הארנק של KDE מבקש סיסמא
feb621
 Comment[hi]=केडीई वॉलेट डेमॉन एक पासवर्ड का अनुरोध करता है
feb621
 Comment[hr]=KDE-ov novčanik daemon zahtijeva zaporku
feb621
@@ -264,12 +266,12 @@
feb621
 Comment[pa]=KDE ਵਾਲਿਟ ਡੈਮਨ ਨੇ ਪਾਸਵਰਡ ਦੀ ਮੰਗ ਕੀਤੀ ਹੈ
feb621
 Comment[pl]=Demon Portfela KDE wymaga hasła
feb621
 Comment[pt]=O Servidor da Carteira do KDE está a pedir uma senha
feb621
-Comment[pt_BR]=O servidor da carteira do KDE está solicitando uma senha
feb621
+Comment[pt_BR]=O servidor de carteiras do KDE está solicitando uma senha
feb621
 Comment[ro]=Demonul de portofel KDE cere o parolă
feb621
 Comment[ru]=Бумажник KDE запрашивает пароль
feb621
 Comment[si]=The KDE පසුම්බි ඩීමනය මුරපදයක් ඉල්ලයි
feb621
 Comment[sk]=Démon KDE Wallet vyžaduje heslo
feb621
-Comment[sl]=Pritajeni program KDE-jeve Listnice zahteva geslo
feb621
+Comment[sl]=Ozadnji program KDE-jeve Listnice zahteva geslo
feb621
 Comment[sr]=КДЕ‑ов демон новчаника захтева лозинку
feb621
 Comment[sr@ijekavian]=КДЕ‑ов демон новчаника захтијева лозинку
feb621
 Comment[sr@ijekavianlatin]=KDE‑ov demon novčanika zahtijeva lozinku
feb621
@@ -279,10 +281,93 @@
feb621
 Comment[th]=บริการกระเป๋าคุมข้อมูลของ KDE ร้องขอรหัสผ่าน
feb621
 Comment[tr]=KDE Cüzdan Servisi bir parola ister
feb621
 Comment[ug]=KDE ھەميان نازارەتچىسى ئىم سورايدۇ
feb621
-Comment[uk]=Фонова служба кишені KDE надіслала запит на пароль
feb621
+Comment[uk]=Фонова служба торбинок KDE надіслала запит на пароль
feb621
 Comment[vi]=Trình nền Wallet KDE yêu cầu một mật khẩu
feb621
 Comment[wa]=Li démon poite-manoye di KDE dimande on scret
feb621
 Comment[x-test]=xxThe KDE Wallet Daemon requests a passwordxx
feb621
 Comment[zh_CN]=KDE 钱包守护程序请求密码
feb621
 Comment[zh_TW]=KDE 錢包守護程式需要密碼
feb621
 Action=Popup
feb621
+
feb621
+[Event/syncFailed]
feb621
+Name=Sync Failed
feb621
+Name[bs]=Sinhronizacija neuspjela
feb621
+Name[ca]=La sincronització ha fallat
feb621
+Name[ca@valencia]=La sincronització ha fallat
feb621
+Name[cs]=Synchronizace selhala
feb621
+Name[da]=Synkronisering mislykkedes
feb621
+Name[de]=Abgleich fehlgeschlagen
feb621
+Name[el]=Αποτυχία συγχρονισμού
feb621
+Name[es]=Sincronización fallida
feb621
+Name[eu]=Sinkronizatzeak huts egin du
feb621
+Name[fi]=Synkronointi epäonnistui
feb621
+Name[fr]=Échec de la synchronisation
feb621
+Name[gl]=Fallou a sincronización
feb621
+Name[hu]=A szinkronizálás meghiúsult
feb621
+Name[ia]=Il falleva synchronisar
feb621
+Name[id]=Sinkronisasi Gagal
feb621
+Name[is]=Samræming mistókst
feb621
+Name[it]=Sincronizzazione non riuscita
feb621
+Name[kk]=Қадамдастыру жаңылды
feb621
+Name[nb]=Synkronisering mislyktes
feb621
+Name[nds]=Synkroniseren is fehlslaan
feb621
+Name[nl]=Synchronisatie mislukt
feb621
+Name[nn]=Feil ved synkronisering
feb621
+Name[pa]=ਸਿੰਕ ਫੇਲ੍ਹ ਹੈ
feb621
+Name[pl]=Nieudana synchronizacja
feb621
+Name[pt]=A Sincronização Falhou
feb621
+Name[pt_BR]=Falha na sincronização
feb621
+Name[ro]=Sincronizare eșuată
feb621
+Name[ru]=Сбой записи
feb621
+Name[sk]=Synchronizácia zlyhala
feb621
+Name[sl]=Uskladitev spodletela
feb621
+Name[sr]=Синхронизација пропала
feb621
+Name[sr@ijekavian]=Синхронизација пропала
feb621
+Name[sr@ijekavianlatin]=Sinhronizacija propala
feb621
+Name[sr@latin]=Sinhronizacija propala
feb621
+Name[sv]=Synkronisering misslyckades
feb621
+Name[tr]=Eşitleme Başarısız
feb621
+Name[uk]=Спроба синхронізації зазнала невдачі
feb621
+Name[x-test]=xxSync Failedxx
feb621
+Name[zh_TW]=同步失敗
feb621
+Comment=KDE Wallet System failed to sync a wallet file to disk
feb621
+Comment[bs]=KDE Wallet Sistem nije uspio da sinhronizuje datoteku novčanika na disk
feb621
+Comment[ca]=El sistema de cartera del KDE ha fallat en sincronitzar un fitxer de cartera al disc
feb621
+Comment[ca@valencia]=El sistema de cartera del KDE ha fallat en sincronitzar un fitxer de cartera al disc
feb621
+Comment[cs]=Systému úschovny pro KDE selhala synchronizace úschovny na disk
feb621
+Comment[da]=KDE's tegnebogsystem kunne ikke synkronisere en tegnebogsfil til disken
feb621
+Comment[de]=Abgleich des KDE-Passwortspeicher mit einer Passwortspeicherdatei auf der Festplatte ist fehlgeschlagen.
feb621
+Comment[el]=Το σύστημα πορτοφολιού του KDE απέτυχε να συγχρονίσει ενός πορτοφολιού στον δίσκο
feb621
+Comment[es]=El sistema de carteras de KDE ha fallado al sincronizar un archivo de cartera con el disco
feb621
+Comment[eu]=KDE zorro-sistemak ezin izan du zorro bat diskora sinkronizatu
feb621
+Comment[fi]=KDE:n lompakkojärjestelmä ei onnistunut tallentamaan lompakkotiedostoa levylle
feb621
+Comment[fr]=Le système du portefeuille de KDE n'a pas réussi à synchroniser un fichier de portefeuille sur le disque
feb621
+Comment[gl]=O sistema de carteiras de KDE non conseguiu sincronizar un ficheiro de carteira co disco
feb621
+Comment[hu]=A KDE jelszókezelő rendszer nem tudta szinkronizálni a jelszófájlt a lemezre
feb621
+Comment[ia]=Le sistema de portafolio de KDE (KDE Wallet System) falleva synchronisar un file de portafolio con le disco
feb621
+Comment[id]=Sistem Dompet KDE gagal sinkronisasi berkas dompet ke cakram
feb621
+Comment[is]=KDE veskjakerfinu (wallet system) mistókst að samstilla veskisskrá við disk
feb621
+Comment[it]=Il sistema di portafogli di KDE non è riuscito a sincronizzare il file del portafogli sul disco
feb621
+Comment[kk]=KDE әмиян жүйесінің дискідегі әмиян файлымен қадамдастыру жаңылысы
feb621
+Comment[nb]=KDE Wallet System klarte ikke å synkronisere en lommebokfil til disk
feb621
+Comment[nds]=Binnen KDE sien Knippsystem lett sik en Knipp nich mit de Datei op de Fastplaat synkroniseren
feb621
+Comment[nl]=Het lukte het KDE portefeuillesysteem niet om een portefeuillebestand naar schijf te synchroniseren
feb621
+Comment[nn]=Lommeboktenesta klarte ikkje synkronisera lommebokfila til disken
feb621
+Comment[pa]=KDE ਵਾਲਿਟ ਸਿਸਟਮ ਡਿਸਕ ਉੱਤੇ ਵਾਲਿਟ ਫਾਇਲ ਨਾਲ ਸਿੰਕ ਕਰਨ ਲਈ ਫੇਲ੍ਹ ਹੈ
feb621
+Comment[pl]=Nieudana synchronizacja pliku portfela przez System portfela KDE
feb621
+Comment[pt]=O sistema da Carteira do KDE não conseguiu sincronizar um ficheiro da carteira para o disco
feb621
+Comment[pt_BR]=O Sistema da Carteiras do KDE não conseguiu sincronizar um arquivo de carteira com o disco
feb621
+Comment[ro]=Sistemul de portofele KDE nu a putut sincroniza fișierul unui portofel cu discul
feb621
+Comment[ru]=Служба бумажника KDE не смогла записать файл бумажника на диск
feb621
+Comment[sk]=Systému KDE peňaženky sa nepodarilo synchronizovať súbor peňaženky na disk
feb621
+Comment[sl]=Sistem listnic za KDE ni uspel uskladiti datoteke z listnico na disku
feb621
+Comment[sr]=К‑новчаник не може да синхронизује фајл новчаника на диск
feb621
+Comment[sr@ijekavian]=К‑новчаник не може да синхронизује фајл новчаника на диск
feb621
+Comment[sr@ijekavianlatin]=K‑novčanik ne može da sinhronizuje fajl novčanika na disk
feb621
+Comment[sr@latin]=K‑novčanik ne može da sinhronizuje fajl novčanika na disk
feb621
+Comment[sv]=KDE:s plånbokssystem misslyckades synkronisera en plånboksfil till disk
feb621
+Comment[tr]=KDE Cüzdan Sistemi diske bir cüzdan dosyası eşitlerken başarısız oldu
feb621
+Comment[uk]=Система торбинок KDE не змогла синхронізувати дані файла торбинок з диском
feb621
+Comment[x-test]=xxKDE Wallet System failed to sync a wallet file to diskxx
feb621
+Comment[zh_TW]=KDE 錢包系統在將錢包檔同步到磁碟時失敗
feb621
+Action=Popup
feb621
diff -Nur kwalletd.than/kwalletopenloop.cpp kwalletd/kwalletopenloop.cpp
feb621
--- kwalletd.than/kwalletopenloop.cpp	2013-06-28 19:12:33.340802830 +0200
feb621
+++ kwalletd/kwalletopenloop.cpp	1970-01-01 01:00:00.000000000 +0100
feb621
@@ -1,46 +0,0 @@
feb621
-// -*- indent-tabs-mode: t; tab-width: 4; c-basic-offset: 4; -*-
feb621
-/*
feb621
-   This file is part of the KDE libraries
feb621
-
feb621
-   Copyright (c) 2008 Michael Leupold <lemma@confuego.org>
feb621
-
feb621
-   This library is free software; you can redistribute it and/or
feb621
-   modify it under the terms of the GNU Library General Public
feb621
-   License as published by the Free Software Foundation; either
feb621
-   version 2 of the License, or (at your option) any later version.
feb621
-
feb621
-   This library is distributed in the hope that it will be useful,
feb621
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
feb621
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
feb621
-   Library General Public License for more details.
feb621
-
feb621
-   You should have received a copy of the GNU Library General Public License
feb621
-   along with this library; see the file COPYING.LIB.  If not, write to
feb621
-   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
feb621
-   Boston, MA 02110-1301, USA.
feb621
-
feb621
-*/
feb621
-
feb621
-#include "kwalletopenloop.h"
feb621
-#include "kwalletd.h"
feb621
-
feb621
-int KWalletOpenLoop::waitForAsyncOpen(int tId)
feb621
-{
feb621
-	transaction = tId;
feb621
-	connect(wallet, SIGNAL(walletAsyncOpened(int, int)),
feb621
-                    SLOT(walletAsyncOpened(int, int)));
feb621
-	exec();
feb621
-	disconnect(this, SLOT(walletAsyncOpened(int, int)));
feb621
-	return result;
feb621
-}
feb621
-
feb621
-void KWalletOpenLoop::walletAsyncOpened(int tId, int handle)
feb621
-{
feb621
-	// if our transaction finished, stop waiting
feb621
-	if (tId == transaction) {
feb621
-		result = handle;
feb621
-		quit();
feb621
-	}
feb621
-}
feb621
-
feb621
-#include "kwalletopenloop.moc"
feb621
diff -Nur kwalletd.than/kwalletopenloop.h kwalletd/kwalletopenloop.h
feb621
--- kwalletd.than/kwalletopenloop.h	2013-06-28 19:12:33.340802830 +0200
feb621
+++ kwalletd/kwalletopenloop.h	1970-01-01 01:00:00.000000000 +0100
feb621
@@ -1,50 +0,0 @@
feb621
-// -*- indent-tabs-mode: t; tab-width: 4; c-basic-offset: 4; -*-
feb621
-/*
feb621
-   This file is part of the KDE libraries
feb621
-
feb621
-   Copyright (c) 2008 Michael Leupold <lemma@confuego.org>
feb621
-
feb621
-   This library is free software; you can redistribute it and/or
feb621
-   modify it under the terms of the GNU Library General Public
feb621
-   License as published by the Free Software Foundation; either
feb621
-   version 2 of the License, or (at your option) any later version.
feb621
-
feb621
-   This library is distributed in the hope that it will be useful,
feb621
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
feb621
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
feb621
-   Library General Public License for more details.
feb621
-
feb621
-   You should have received a copy of the GNU Library General Public License
feb621
-   along with this library; see the file COPYING.LIB.  If not, write to
feb621
-   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
feb621
-   Boston, MA 02110-1301, USA.
feb621
-
feb621
-*/
feb621
-
feb621
-#ifndef KWALLETOPENLOOP_H
feb621
-#define KWALLETOPENLOOP_H
feb621
-
feb621
-#include <QtCore/QEventLoop>
feb621
-
feb621
-class KWalletD;
feb621
-
feb621
-class KWalletOpenLoop : public QEventLoop {
feb621
-	Q_OBJECT
feb621
-	
feb621
-	public:
feb621
-		explicit KWalletOpenLoop(KWalletD* w, QObject* parent = 0)
feb621
-		    : QEventLoop(parent), wallet(w) {}
feb621
-		
feb621
-		// returns the open handle
feb621
-		int waitForAsyncOpen(int tId);
feb621
-		
feb621
-	public slots:
feb621
-		void walletAsyncOpened(int tId, int handle);
feb621
-		
feb621
-	private:
feb621
-		KWalletD* wallet;
feb621
-		int transaction;
feb621
-		int result;
feb621
-};
feb621
-
feb621
-#endif
feb621
diff -Nur kwalletd.than/kwalletwizard.cpp kwalletd/kwalletwizard.cpp
feb621
--- kwalletd.than/kwalletwizard.cpp	2013-06-28 19:12:33.341802790 +0200
feb621
+++ kwalletd/kwalletwizard.cpp	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -23,11 +23,25 @@
feb621
 #include "ui_kwalletwizardpageintro.h"
feb621
 #include "ui_kwalletwizardpageoptions.h"
feb621
 #include "ui_kwalletwizardpagepassword.h"
feb621
+#ifdef HAVE_QGPGME
feb621
+#include "ui_kwalletwizardpagepasswordgpg.h"
feb621
+#include "ui_kwalletwizardpagegpgkey.h"
feb621
+#endif
feb621
 
feb621
 #include <QButtonGroup>
feb621
 
feb621
 #include <klocale.h>
feb621
 
feb621
+#ifdef HAVE_QGPGME
feb621
+#include <QComboBox>
feb621
+#include <gpgme++/context.h>
feb621
+#include <gpgme++/key.h>
feb621
+#include <gpgme++/keylistresult.h>
feb621
+#include <kdebug.h>
feb621
+#include <kmessagebox.h>
feb621
+#include <gpgme.h>
feb621
+#endif
feb621
+
feb621
 class PageIntro : public QWizardPage
feb621
 {
feb621
 public:
feb621
@@ -59,18 +73,23 @@
feb621
     Ui::KWalletWizardPageIntro ui;
feb621
 };
feb621
 
feb621
-
feb621
 class PagePassword : public QWizardPage
feb621
 {
feb621
 public:
feb621
     PagePassword(QWidget *parent)
feb621
         : QWizardPage(parent)
feb621
     {
feb621
+
feb621
         ui.setupUi(this);
feb621
 
feb621
         registerField("useWallet", ui._useWallet);
feb621
         registerField("pass1", ui._pass1);
feb621
         registerField("pass2", ui._pass2);
feb621
+#ifdef HAVE_QGPGME
feb621
+        registerField("useGPG", ui._radioGpg);
feb621
+        registerField("useBlowfish", ui._radioBlowfish);
feb621
+        connect(ui._radioBlowfish, SIGNAL(toggled(bool)), parent, SLOT(passwordPageUpdate()));
feb621
+#endif
feb621
 
feb621
         connect(ui._useWallet, SIGNAL(clicked()), parent, SLOT(passwordPageUpdate()));
feb621
         connect(ui._pass1, SIGNAL(textChanged(QString)), parent, SLOT(passwordPageUpdate()));
feb621
@@ -79,7 +98,20 @@
feb621
 
feb621
     virtual int nextId() const
feb621
     {
feb621
+#ifdef HAVE_QGPGME
feb621
+        int nextId = -1;
feb621
+        if (field("useWallet").toBool()) {
feb621
+            if (field("useBlowfish").toBool()) {
feb621
+                nextId = static_cast<KWalletWizard*>(wizard())->wizardType() == KWalletWizard::Basic ? -1 : KWalletWizard::PageOptionsId; // same as non QGPGME case
feb621
+            } else {
feb621
+                nextId = KWalletWizard::PageGpgKeyId;
feb621
+            }
feb621
+        }
feb621
+
feb621
+        return nextId;
feb621
+#else
feb621
         return static_cast<KWalletWizard*>(wizard())->wizardType() == KWalletWizard::Basic ? -1 : KWalletWizard::PageOptionsId;
feb621
+#endif
feb621
     }
feb621
 
feb621
     void setMatchLabelText(const QString &text)
feb621
@@ -88,9 +120,96 @@
feb621
     }
feb621
 
feb621
 private:
feb621
+#ifdef HAVE_QGPGME
feb621
+    Ui::KWalletWizardPagePasswordGpg ui;
feb621
+#else
feb621
     Ui::KWalletWizardPagePassword ui;
feb621
+#endif
feb621
+};
feb621
+
feb621
+#ifdef HAVE_QGPGME
feb621
+typedef std::vector< GpgME::Key > KeysVector;
feb621
+Q_DECLARE_METATYPE(GpgME::Key)
feb621
+
feb621
+struct AddKeyToCombo {
feb621
+    QComboBox *_list;
feb621
+    AddKeyToCombo(QComboBox *list) : _list(list) {}
feb621
+    void operator()( const GpgME::Key &k) {
feb621
+        QString text = QString("%1 (%2)").arg(k.shortKeyID()).arg(k.userID(0).email());
feb621
+        QVariant varKey;
feb621
+        varKey.setValue(k);
feb621
+        _list->addItem(text, varKey);
feb621
+    }
feb621
 };
feb621
 
feb621
+class PageGpgKey : public QWizardPage
feb621
+{
feb621
+public:
feb621
+    PageGpgKey(QWidget* parent) 
feb621
+        : QWizardPage(parent)
feb621
+        , userHasGpgKeys(false)
feb621
+    {
feb621
+        ui.setupUi(this);
feb621
+
feb621
+        registerField("gpgKey", ui._gpgKey);
feb621
+
feb621
+        KeysVector keys;
feb621
+        GpgME::initializeLibrary();
feb621
+        GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP);
feb621
+        if (err){
feb621
+            kDebug() << "OpenPGP not supported on your system!";
feb621
+            KMessageBox::error(this, i18n("The QGpgME library failed to initialize for the OpenPGP protocol. Please check your system's configuration then try again."));
feb621
+        } else {
feb621
+            boost::shared_ptr< GpgME::Context > ctx( GpgME::Context::createForProtocol(GpgME::OpenPGP) );
feb621
+            if (0 == ctx) {
feb621
+                KMessageBox::error(this, i18n("The QGpgME library failed to initialize for the OpenPGP protocol. Please check your system's configuration then try again."));
feb621
+            } else {
feb621
+
feb621
+            ctx->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL);
feb621
+            int row =0;
feb621
+            err = ctx->startKeyListing();
feb621
+            while (!err) {
feb621
+                GpgME::Key k = ctx->nextKey(err);
feb621
+                if (err)
feb621
+                    break;
feb621
+                if (!k.isInvalid() && k.canEncrypt()) {
feb621
+                    keys.push_back(k);
feb621
+                }
feb621
+            }
feb621
+            ctx->endKeyListing();
feb621
+            }
feb621
+        }
feb621
+        std::for_each(keys.begin(), keys.end(), AddKeyToCombo(ui._gpgKey));
feb621
+
feb621
+        userHasGpgKeys = keys.size() >0;
feb621
+        if (userHasGpgKeys) {
feb621
+            ui.stackedWidget->setCurrentWidget(ui._pageWhenHasKeys);
feb621
+        } else {
feb621
+            ui.stackedWidget->setCurrentWidget(ui._pageNoKeys);
feb621
+            setFinalPage(true);
feb621
+        }
feb621
+        emit completeChanged();
feb621
+    }
feb621
+    
feb621
+    virtual int nextId() const {
feb621
+        return static_cast<KWalletWizard*>(wizard())->wizardType() == KWalletWizard::Basic ? -1 : KWalletWizard::PageOptionsId;
feb621
+    }
feb621
+
feb621
+    virtual bool isComplete() const {
feb621
+        return userHasGpgKeys;
feb621
+    }
feb621
+    
feb621
+    bool hasGpgKeys() const { return userHasGpgKeys; }
feb621
+
feb621
+    GpgME::Key gpgKey() const {
feb621
+        QVariant varKey = ui._gpgKey->itemData(field("gpgKey").toInt());
feb621
+        return varKey.value< GpgME::Key >();
feb621
+    }
feb621
+private:
feb621
+    Ui::KWalletWizardPageGpgKey ui;
feb621
+    bool userHasGpgKeys;
feb621
+};
feb621
+#endif
feb621
 
feb621
 class PageOptions : public QWizardPage
feb621
 {
feb621
@@ -134,24 +253,42 @@
feb621
     setPage(PageIntroId, m_pageIntro);
feb621
     m_pagePasswd = new PagePassword(this);
feb621
     setPage(PagePasswordId, m_pagePasswd);
feb621
+#ifdef HAVE_QGPGME
feb621
+    m_pageGpgKey = new PageGpgKey(this);
feb621
+    setPage(PageGpgKeyId, m_pageGpgKey);
feb621
+#endif
feb621
     setPage(PageOptionsId, new PageOptions(this));
feb621
     setPage(PageExplanationId, new PageExplanation(this));
feb621
+    
feb621
+    resize(500, 420);
feb621
 }
feb621
 
feb621
 void KWalletWizard::passwordPageUpdate()
feb621
 {
feb621
     bool complete = true;
feb621
     if (field("useWallet").toBool()) {
feb621
-        if (field("pass1").toString() == field("pass2").toString()) {
feb621
-            if (field("pass1").toString().isEmpty()) {
feb621
-                m_pagePasswd->setMatchLabelText(i18n("<qt>Password is empty.  (WARNING: Insecure)</qt>"));
feb621
+#ifdef HAVE_QGPGME
feb621
+        if (field("useBlowfish").toBool()) {
feb621
+            m_pagePasswd->setFinalPage(wizardType() == Basic);
feb621
+            button(NextButton)->setVisible(wizardType() != Basic);
feb621
+#endif
feb621
+            if (field("pass1").toString() == field("pass2").toString()) {
feb621
+                if (field("pass1").toString().isEmpty()) {
feb621
+                    m_pagePasswd->setMatchLabelText(i18n("<qt>Password is empty.  (WARNING: Insecure)</qt>"));
feb621
+                } else {
feb621
+                    m_pagePasswd->setMatchLabelText(i18n("Passwords match."));
feb621
+                }
feb621
             } else {
feb621
-                m_pagePasswd->setMatchLabelText(i18n("Passwords match."));
feb621
+                m_pagePasswd->setMatchLabelText(i18n("Passwords do not match."));
feb621
+                complete = false;
feb621
             }
feb621
+#ifdef HAVE_QGPGME
feb621
         } else {
feb621
-            m_pagePasswd->setMatchLabelText(i18n("Passwords do not match."));
feb621
-            complete = false;
feb621
+            m_pagePasswd->setFinalPage(false);
feb621
+            button(NextButton)->setEnabled(true);
feb621
+            return;
feb621
         }
feb621
+#endif
feb621
     } else {
feb621
         m_pagePasswd->setMatchLabelText(QString());
feb621
     }
feb621
@@ -176,3 +313,8 @@
feb621
     }
feb621
 }
feb621
 
feb621
+#ifdef HAVE_QGPGME
feb621
+GpgME::Key KWalletWizard::gpgKey() const {
feb621
+    return m_pageGpgKey->gpgKey();
feb621
+}
feb621
+#endif
feb621
diff -Nur kwalletd.than/kwalletwizard.h kwalletd/kwalletwizard.h
feb621
--- kwalletd.than/kwalletwizard.h	2013-06-28 19:12:33.341802790 +0200
feb621
+++ kwalletd/kwalletwizard.h	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -20,9 +20,13 @@
feb621
 #define KWALLETWIZARD_H
feb621
 
feb621
 #include <QWizard>
feb621
+#ifdef HAVE_QGPGME
feb621
+#include <gpgme++/key.h>
feb621
+#endif
feb621
 
feb621
-class PageIntro;
feb621
+class PageGpgKey;
feb621
 class PagePassword;
feb621
+class PageIntro;
feb621
 
feb621
 class KWalletWizard : public QWizard
feb621
 {
feb621
@@ -37,13 +41,20 @@
feb621
 
feb621
         static const int PageIntroId = 0;
feb621
         static const int PagePasswordId = 1;
feb621
-        static const int PageOptionsId = 2;
feb621
-        static const int PageExplanationId = 3;
feb621
+#ifdef HAVE_QGPGME
feb621
+        static const int PageGpgKeyId =2;
feb621
+#endif
feb621
+        static const int PageOptionsId = 3;
feb621
+        static const int PageExplanationId = 4;
feb621
 
feb621
     KWalletWizard( QWidget *parent = 0 );
feb621
 
feb621
         WizardType wizardType() const;
feb621
 
feb621
+#ifdef HAVE_QGPGME
feb621
+        GpgME::Key gpgKey() const;
feb621
+#endif // HAVE_QGPGME
feb621
+
feb621
     protected:
feb621
         virtual void initializePage(int id);
feb621
 
feb621
@@ -53,6 +64,9 @@
feb621
     private:
feb621
         PageIntro *m_pageIntro;
feb621
         PagePassword *m_pagePasswd;
feb621
+#ifdef HAVE_QGPGME
feb621
+        PageGpgKey *m_pageGpgKey;
feb621
+#endif
feb621
 };
feb621
 
feb621
 #endif
feb621
diff -Nur kwalletd.than/kwalletwizardpageexplanation.ui kwalletd/kwalletwizardpageexplanation.ui
feb621
--- kwalletd.than/kwalletwizardpageexplanation.ui	2013-06-28 19:12:33.341802790 +0200
feb621
+++ kwalletd/kwalletwizardpageexplanation.ui	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -1,7 +1,8 @@
feb621
-<ui version="4.0" >
feb621
+
feb621
+<ui version="4.0">
feb621
  <class>KWalletWizardPageExplanation</class>
feb621
- <widget class="QWidget" name="KWalletWizardPageExplanation" >
feb621
-  <property name="geometry" >
feb621
+ <widget class="QWidget" name="KWalletWizardPageExplanation">
feb621
+  <property name="geometry">
feb621
    <rect>
feb621
     <x>0</x>
feb621
     <y>0</y>
feb621
@@ -9,16 +10,16 @@
feb621
     <height>215</height>
feb621
    </rect>
feb621
   </property>
feb621
-  <layout class="QVBoxLayout" >
feb621
+  <layout class="QVBoxLayout">
feb621
    <item>
feb621
-    <widget class="QLabel" name="textLabel2_3" >
feb621
-     <property name="text" >
feb621
-      <string>The KDE Wallet system stores your data in a <i>wallet</i> file on your local hard disk.  The data is only written in encrypted form, presently using the blowfish algorithm with your password as the key.  When a wallet is opened, the wallet manager application will launch and display an icon in the system tray.  You can use this application to manage your wallets.  It even permits you to drag wallets and wallet contents, allowing you to easily copy a wallet to a remote system.</string>
feb621
+    <widget class="QLabel" name="textLabel2_3">
feb621
+     <property name="text">
feb621
+      <string><html><head/><body><p>The KDE Wallet system stores your data in a <span style=" font-style:italic;">wallet</span> file on your local hard disk. The data is only written in the encrypted form of your choice - blowfish algorithm with your password as the key or using a GPG encryption key. When a wallet is opened, the wallet manager application will launch and display an icon in the system tray. You can use this application to manage all of your wallets. It even permits you to drag wallets and wallet contents, allowing you to easily copy a wallet to a remote system.</p></body></html></string>
feb621
      </property>
feb621
-     <property name="textFormat" >
feb621
+     <property name="textFormat">
feb621
       <enum>Qt::RichText</enum>
feb621
      </property>
feb621
-     <property name="wordWrap" >
feb621
+     <property name="wordWrap">
feb621
       <bool>true</bool>
feb621
      </property>
feb621
     </widget>
feb621
diff -Nur kwalletd.than/kwalletwizardpagegpgkey.ui kwalletd/kwalletwizardpagegpgkey.ui
feb621
--- kwalletd.than/kwalletwizardpagegpgkey.ui	1970-01-01 01:00:00.000000000 +0100
feb621
+++ kwalletd/kwalletwizardpagegpgkey.ui	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -0,0 +1,93 @@
feb621
+
feb621
+<ui version="4.0">
feb621
+ <class>KWalletWizardPageGpgKey</class>
feb621
+ <widget class="QWidget" name="KWalletWizardPageGpgKey">
feb621
+  <property name="geometry">
feb621
+   <rect>
feb621
+    <x>0</x>
feb621
+    <y>0</y>
feb621
+    <width>436</width>
feb621
+    <height>309</height>
feb621
+   </rect>
feb621
+  </property>
feb621
+  <layout class="QVBoxLayout" name="verticalLayout_3">
feb621
+   <item>
feb621
+    <widget class="QStackedWidget" name="stackedWidget">
feb621
+     <property name="currentIndex">
feb621
+      <number>0</number>
feb621
+     </property>
feb621
+     <widget class="QWidget" name="_pageWhenHasKeys">
feb621
+      <layout class="QVBoxLayout" name="verticalLayout_2">
feb621
+       <item>
feb621
+        <widget class="QLabel" name="label_3">
feb621
+         <property name="text">
feb621
+          <string><html><head/><body><p>The GPG-based wallet use a GPG encryption key to securely encrypt data on disk. The key must be available when decrypting is needed or your wallet will not be accessible. For example, if you choose a SmartCard-based encryption key, the GPG system will prompt you to enter it and its associated PIN when attempting to open the wallet.</p></body></html></string>
feb621
+         </property>
feb621
+         <property name="wordWrap">
feb621
+          <bool>true</bool>
feb621
+         </property>
feb621
+        </widget>
feb621
+       </item>
feb621
+       <item>
feb621
+        <layout class="QHBoxLayout" name="horizontalLayout">
feb621
+         <item>
feb621
+          <widget class="QLabel" name="label">
feb621
+           <property name="enabled">
feb621
+            <bool>true</bool>
feb621
+           </property>
feb621
+           <property name="text">
feb621
+            <string>Select encryption GPG key:</string>
feb621
+           </property>
feb621
+          </widget>
feb621
+         </item>
feb621
+         <item>
feb621
+          <widget class="QComboBox" name="_gpgKey">
feb621
+           <property name="enabled">
feb621
+            <bool>true</bool>
feb621
+           </property>
feb621
+          </widget>
feb621
+         </item>
feb621
+        </layout>
feb621
+       </item>
feb621
+       <item>
feb621
+        <spacer name="verticalSpacer">
feb621
+         <property name="orientation">
feb621
+          <enum>Qt::Vertical</enum>
feb621
+         </property>
feb621
+         <property name="sizeHint" stdset="0">
feb621
+          <size>
feb621
+           <width>20</width>
feb621
+           <height>173</height>
feb621
+          </size>
feb621
+         </property>
feb621
+        </spacer>
feb621
+       </item>
feb621
+      </layout>
feb621
+     </widget>
feb621
+     <widget class="QWidget" name="_pageNoKeys">
feb621
+      <layout class="QVBoxLayout" name="verticalLayout">
feb621
+       <item>
feb621
+        <widget class="QLabel" name="label_2">
feb621
+         <property name="sizePolicy">
feb621
+          <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
feb621
+           <horstretch>0</horstretch>
feb621
+           <verstretch>0</verstretch>
feb621
+          </sizepolicy>
feb621
+         </property>
feb621
+         <property name="text">
feb621
+          <string>Unable to locate at least one <b>encrypting GPG key</b>. KDE Wallet needs such <b>encrypting key</b> to securely store passwords or other sensitive data on disk. If you still want to setup a GPG-based wallet, then cancel this wizard, set-up an <b>encrypting GPG key</b>, then retry this assistant. Otherwise, you may still click back, then choose a classic, blowfish encrypted file format on the previous page.</string>
feb621
+         </property>
feb621
+         <property name="wordWrap">
feb621
+          <bool>true</bool>
feb621
+         </property>
feb621
+        </widget>
feb621
+       </item>
feb621
+      </layout>
feb621
+     </widget>
feb621
+    </widget>
feb621
+   </item>
feb621
+  </layout>
feb621
+ </widget>
feb621
+ <resources/>
feb621
+ <connections/>
feb621
+</ui>
feb621
diff -Nur kwalletd.than/kwalletwizardpageintro.ui kwalletd/kwalletwizardpageintro.ui
feb621
--- kwalletd.than/kwalletwizardpageintro.ui	2013-06-28 19:12:33.341802790 +0200
feb621
+++ kwalletd/kwalletwizardpageintro.ui	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -6,8 +6,8 @@
feb621
    <rect>
feb621
     <x>0</x>
feb621
     <y>0</y>
feb621
-    <width>275</width>
feb621
-    <height>283</height>
feb621
+    <width>449</width>
feb621
+    <height>327</height>
feb621
    </rect>
feb621
   </property>
feb621
   <layout class="QVBoxLayout" name="verticalLayout">
feb621
diff -Nur kwalletd.than/kwalletwizardpagepasswordgpg.ui kwalletd/kwalletwizardpagepasswordgpg.ui
feb621
--- kwalletd.than/kwalletwizardpagepasswordgpg.ui	1970-01-01 01:00:00.000000000 +0100
feb621
+++ kwalletd/kwalletwizardpagepasswordgpg.ui	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -0,0 +1,350 @@
feb621
+
feb621
+<ui version="4.0">
feb621
+ <class>KWalletWizardPagePasswordGpg</class>
feb621
+ <widget class="QWidget" name="KWalletWizardPagePasswordGpg">
feb621
+  <property name="geometry">
feb621
+   <rect>
feb621
+    <x>0</x>
feb621
+    <y>0</y>
feb621
+    <width>448</width>
feb621
+    <height>385</height>
feb621
+   </rect>
feb621
+  </property>
feb621
+  <layout class="QVBoxLayout" name="verticalLayout_2">
feb621
+   <item>
feb621
+    <widget class="QLabel" name="textLabel3">
feb621
+     <property name="text">
feb621
+      <string><html><head/><body><p>Various applications may attempt to use the KDE wallet to store passwords or other information such as web form data and cookies. If you would like these applications to use the wallet, you must enable it now and choose method for its encryption.</p><p>GPG method is more secure, but you must have configured at least one encrypting key on your system.</p><p>If you choose the classic format, be warned that the password you choose <span style=" font-style:italic;">cannot</span> be recovered if it is lost, and will allow anyone who knows it to obtain all the information contained in the wallet.</p></body></html></string>
feb621
+     </property>
feb621
+     <property name="textFormat">
feb621
+      <enum>Qt::RichText</enum>
feb621
+     </property>
feb621
+     <property name="wordWrap">
feb621
+      <bool>true</bool>
feb621
+     </property>
feb621
+    </widget>
feb621
+   </item>
feb621
+   <item>
feb621
+    <widget class="QCheckBox" name="_useWallet">
feb621
+     <property name="text">
feb621
+      <string>Yes, I wish to use the KDE wallet to store my personal information.</string>
feb621
+     </property>
feb621
+    </widget>
feb621
+   </item>
feb621
+   <item>
feb621
+    <widget class="QGroupBox" name="_groupBox">
feb621
+     <property name="enabled">
feb621
+      <bool>false</bool>
feb621
+     </property>
feb621
+     <property name="sizePolicy">
feb621
+      <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
feb621
+       <horstretch>0</horstretch>
feb621
+       <verstretch>0</verstretch>
feb621
+      </sizepolicy>
feb621
+     </property>
feb621
+     <property name="title">
feb621
+      <string>What kind of encryption do you wish?</string>
feb621
+     </property>
feb621
+     <layout class="QVBoxLayout" name="verticalLayout">
feb621
+      <item>
feb621
+       <widget class="QRadioButton" name="_radioGpg">
feb621
+        <property name="enabled">
feb621
+         <bool>false</bool>
feb621
+        </property>
feb621
+        <property name="text">
feb621
+         <string>Use GPG encryption, for better protection</string>
feb621
+        </property>
feb621
+        <property name="checked">
feb621
+         <bool>true</bool>
feb621
+        </property>
feb621
+       </widget>
feb621
+      </item>
feb621
+      <item>
feb621
+       <widget class="QRadioButton" name="_radioBlowfish">
feb621
+        <property name="enabled">
feb621
+         <bool>false</bool>
feb621
+        </property>
feb621
+        <property name="text">
feb621
+         <string>Classic, blowfish encrypted file</string>
feb621
+        </property>
feb621
+       </widget>
feb621
+      </item>
feb621
+      <item>
feb621
+       <layout class="QHBoxLayout" name="horizontalLayout_2">
feb621
+        <item>
feb621
+         <spacer>
feb621
+          <property name="orientation">
feb621
+           <enum>Qt::Horizontal</enum>
feb621
+          </property>
feb621
+          <property name="sizeType">
feb621
+           <enum>QSizePolicy::Expanding</enum>
feb621
+          </property>
feb621
+          <property name="sizeHint" stdset="0">
feb621
+           <size>
feb621
+            <width>28</width>
feb621
+            <height>28</height>
feb621
+           </size>
feb621
+          </property>
feb621
+         </spacer>
feb621
+        </item>
feb621
+        <item>
feb621
+         <layout class="QHBoxLayout" name="horizontalLayout">
feb621
+          <item>
feb621
+           <layout class="QVBoxLayout">
feb621
+            <property name="spacing">
feb621
+             <number>6</number>
feb621
+            </property>
feb621
+            <property name="margin">
feb621
+             <number>0</number>
feb621
+            </property>
feb621
+            <item>
feb621
+             <widget class="QLabel" name="textLabel1_3">
feb621
+              <property name="enabled">
feb621
+               <bool>false</bool>
feb621
+              </property>
feb621
+              <property name="text">
feb621
+               <string>Enter a new password:</string>
feb621
+              </property>
feb621
+              <property name="alignment">
feb621
+               <set>Qt::AlignAbsolute|Qt::AlignBottom|Qt::AlignCenter|Qt::AlignHCenter|Qt::AlignHorizontal_Mask|Qt::AlignJustify|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing|Qt::AlignVCenter|Qt::AlignVertical_Mask</set>
feb621
+              </property>
feb621
+              <property name="buddy">
feb621
+               <cstring>_pass1</cstring>
feb621
+              </property>
feb621
+             </widget>
feb621
+            </item>
feb621
+            <item>
feb621
+             <widget class="QLabel" name="textLabel2_3">
feb621
+              <property name="enabled">
feb621
+               <bool>false</bool>
feb621
+              </property>
feb621
+              <property name="text">
feb621
+               <string>Verify password:</string>
feb621
+              </property>
feb621
+              <property name="alignment">
feb621
+               <set>Qt::AlignAbsolute|Qt::AlignBottom|Qt::AlignCenter|Qt::AlignHCenter|Qt::AlignHorizontal_Mask|Qt::AlignJustify|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing|Qt::AlignVCenter|Qt::AlignVertical_Mask</set>
feb621
+              </property>
feb621
+              <property name="buddy">
feb621
+               <cstring>_pass2</cstring>
feb621
+              </property>
feb621
+             </widget>
feb621
+            </item>
feb621
+           </layout>
feb621
+          </item>
feb621
+          <item>
feb621
+           <layout class="QVBoxLayout">
feb621
+            <property name="spacing">
feb621
+             <number>6</number>
feb621
+            </property>
feb621
+            <property name="margin">
feb621
+             <number>0</number>
feb621
+            </property>
feb621
+            <item>
feb621
+             <widget class="KLineEdit" name="_pass1">
feb621
+              <property name="enabled">
feb621
+               <bool>false</bool>
feb621
+              </property>
feb621
+              <property name="echoMode">
feb621
+               <enum>QLineEdit::Password</enum>
feb621
+              </property>
feb621
+             </widget>
feb621
+            </item>
feb621
+            <item>
feb621
+             <widget class="KLineEdit" name="_pass2">
feb621
+              <property name="enabled">
feb621
+               <bool>false</bool>
feb621
+              </property>
feb621
+              <property name="echoMode">
feb621
+               <enum>QLineEdit::Password</enum>
feb621
+              </property>
feb621
+             </widget>
feb621
+            </item>
feb621
+           </layout>
feb621
+          </item>
feb621
+         </layout>
feb621
+        </item>
feb621
+        <item>
feb621
+         <spacer>
feb621
+          <property name="orientation">
feb621
+           <enum>Qt::Horizontal</enum>
feb621
+          </property>
feb621
+          <property name="sizeType">
feb621
+           <enum>QSizePolicy::Expanding</enum>
feb621
+          </property>
feb621
+          <property name="sizeHint" stdset="0">
feb621
+           <size>
feb621
+            <width>98</width>
feb621
+            <height>18</height>
feb621
+           </size>
feb621
+          </property>
feb621
+         </spacer>
feb621
+        </item>
feb621
+       </layout>
feb621
+      </item>
feb621
+      <item>
feb621
+       <widget class="QLabel" name="_matchLabel">
feb621
+        <property name="text">
feb621
+         <string/>
feb621
+        </property>
feb621
+        <property name="alignment">
feb621
+         <set>Qt::AlignAbsolute|Qt::AlignBottom|Qt::AlignCenter|Qt::AlignHCenter|Qt::AlignHorizontal_Mask|Qt::AlignJustify|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing|Qt::AlignVCenter|Qt::AlignVertical_Mask</set>
feb621
+        </property>
feb621
+       </widget>
feb621
+      </item>
feb621
+      <item>
feb621
+       <spacer name="verticalSpacer">
feb621
+        <property name="orientation">
feb621
+         <enum>Qt::Vertical</enum>
feb621
+        </property>
feb621
+        <property name="sizeHint" stdset="0">
feb621
+         <size>
feb621
+          <width>20</width>
feb621
+          <height>31</height>
feb621
+         </size>
feb621
+        </property>
feb621
+       </spacer>
feb621
+      </item>
feb621
+     </layout>
feb621
+    </widget>
feb621
+   </item>
feb621
+  </layout>
feb621
+ </widget>
feb621
+ <customwidgets>
feb621
+  <customwidget>
feb621
+   <class>KLineEdit</class>
feb621
+   <extends>QLineEdit</extends>
feb621
+   <header>klineedit.h</header>
feb621
+  </customwidget>
feb621
+ </customwidgets>
feb621
+ <resources/>
feb621
+ <connections>
feb621
+  <connection>
feb621
+   <sender>_radioBlowfish</sender>
feb621
+   <signal>toggled(bool)</signal>
feb621
+   <receiver>textLabel1_3</receiver>
feb621
+   <slot>setEnabled(bool)</slot>
feb621
+   <hints>
feb621
+    <hint type="sourcelabel">
feb621
+     <x>239</x>
feb621
+     <y>220</y>
feb621
+    </hint>
feb621
+    <hint type="destinationlabel">
feb621
+     <x>213</x>
feb621
+     <y>249</y>
feb621
+    </hint>
feb621
+   </hints>
feb621
+  </connection>
feb621
+  <connection>
feb621
+   <sender>_radioBlowfish</sender>
feb621
+   <signal>toggled(bool)</signal>
feb621
+   <receiver>_pass1</receiver>
feb621
+   <slot>setEnabled(bool)</slot>
feb621
+   <hints>
feb621
+    <hint type="sourcelabel">
feb621
+     <x>239</x>
feb621
+     <y>220</y>
feb621
+    </hint>
feb621
+    <hint type="destinationlabel">
feb621
+     <x>331</x>
feb621
+     <y>249</y>
feb621
+    </hint>
feb621
+   </hints>
feb621
+  </connection>
feb621
+  <connection>
feb621
+   <sender>_radioBlowfish</sender>
feb621
+   <signal>toggled(bool)</signal>
feb621
+   <receiver>textLabel2_3</receiver>
feb621
+   <slot>setEnabled(bool)</slot>
feb621
+   <hints>
feb621
+    <hint type="sourcelabel">
feb621
+     <x>239</x>
feb621
+     <y>220</y>
feb621
+    </hint>
feb621
+    <hint type="destinationlabel">
feb621
+     <x>142</x>
feb621
+     <y>277</y>
feb621
+    </hint>
feb621
+   </hints>
feb621
+  </connection>
feb621
+  <connection>
feb621
+   <sender>_radioBlowfish</sender>
feb621
+   <signal>toggled(bool)</signal>
feb621
+   <receiver>_pass2</receiver>
feb621
+   <slot>setEnabled(bool)</slot>
feb621
+   <hints>
feb621
+    <hint type="sourcelabel">
feb621
+     <x>239</x>
feb621
+     <y>220</y>
feb621
+    </hint>
feb621
+    <hint type="destinationlabel">
feb621
+     <x>331</x>
feb621
+     <y>277</y>
feb621
+    </hint>
feb621
+   </hints>
feb621
+  </connection>
feb621
+  <connection>
feb621
+   <sender>_radioBlowfish</sender>
feb621
+   <signal>clicked()</signal>
feb621
+   <receiver>_pass1</receiver>
feb621
+   <slot>setFocus()</slot>
feb621
+   <hints>
feb621
+    <hint type="sourcelabel">
feb621
+     <x>239</x>
feb621
+     <y>220</y>
feb621
+    </hint>
feb621
+    <hint type="destinationlabel">
feb621
+     <x>331</x>
feb621
+     <y>249</y>
feb621
+    </hint>
feb621
+   </hints>
feb621
+  </connection>
feb621
+  <connection>
feb621
+   <sender>_useWallet</sender>
feb621
+   <signal>toggled(bool)</signal>
feb621
+   <receiver>_groupBox</receiver>
feb621
+   <slot>setEnabled(bool)</slot>
feb621
+   <hints>
feb621
+    <hint type="sourcelabel">
feb621
+     <x>42</x>
feb621
+     <y>112</y>
feb621
+    </hint>
feb621
+    <hint type="destinationlabel">
feb621
+     <x>33</x>
feb621
+     <y>193</y>
feb621
+    </hint>
feb621
+   </hints>
feb621
+  </connection>
feb621
+  <connection>
feb621
+   <sender>_useWallet</sender>
feb621
+   <signal>toggled(bool)</signal>
feb621
+   <receiver>_radioGpg</receiver>
feb621
+   <slot>setEnabled(bool)</slot>
feb621
+   <hints>
feb621
+    <hint type="sourcelabel">
feb621
+     <x>50</x>
feb621
+     <y>112</y>
feb621
+    </hint>
feb621
+    <hint type="destinationlabel">
feb621
+     <x>63</x>
feb621
+     <y>166</y>
feb621
+    </hint>
feb621
+   </hints>
feb621
+  </connection>
feb621
+  <connection>
feb621
+   <sender>_useWallet</sender>
feb621
+   <signal>toggled(bool)</signal>
feb621
+   <receiver>_radioBlowfish</receiver>
feb621
+   <slot>setEnabled(bool)</slot>
feb621
+   <hints>
feb621
+    <hint type="sourcelabel">
feb621
+     <x>85</x>
feb621
+     <y>112</y>
feb621
+    </hint>
feb621
+    <hint type="destinationlabel">
feb621
+     <x>97</x>
feb621
+     <y>220</y>
feb621
+    </hint>
feb621
+   </hints>
feb621
+  </connection>
feb621
+ </connections>
feb621
+</ui>
feb621
diff -Nur kwalletd.than/main.cpp kwalletd/main.cpp
feb621
--- kwalletd.than/main.cpp	2013-06-28 19:12:33.342802750 +0200
feb621
+++ kwalletd/main.cpp	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -38,10 +38,11 @@
feb621
 {
feb621
     KAboutData aboutdata("kwalletd", 0, ki18n("KDE Wallet Service"),
feb621
                          "0.2", ki18n("KDE Wallet Service"),
feb621
-                         KAboutData::License_LGPL, ki18n("(C) 2002-2008 George Staikos, Michael Leupold, Thiago Maceira"));
feb621
+                         KAboutData::License_LGPL, ki18n("(C) 2002-2008 George Staikos, Michael Leupold, Thiago Maceira, Valentin Rusu"));
feb621
     aboutdata.addAuthor(ki18n("Michael Leupold"),ki18n("Maintainer"),"lemma@confuego.org");
feb621
     aboutdata.addAuthor(ki18n("George Staikos"),ki18n("Former maintainer"),"staikos@kde.org");
feb621
     aboutdata.addAuthor(ki18n("Thiago Maceira"),ki18n("D-Bus Interface"),"thiago@kde.org");
feb621
+    aboutdata.addAuthor(ki18n("Valentin Rusu"),ki18n("GPG backend support"),"kde@rusu.info");
feb621
 
feb621
     aboutdata.setProgramIconName("kwalletmanager");
feb621
 
feb621
@@ -65,6 +66,7 @@
feb621
       return (0);
feb621
     }
feb621
 
feb621
+    kDebug() << "kwalletd started";
feb621
     KWalletD walletd;
feb621
     return app.exec();
feb621
 }
feb621
diff -Nur kwalletd.than/tests/CMakeLists.txt kwalletd/tests/CMakeLists.txt
feb621
--- kwalletd.than/tests/CMakeLists.txt	2013-06-28 19:12:33.342802750 +0200
feb621
+++ kwalletd/tests/CMakeLists.txt	2014-02-26 09:34:12.000000000 +0100
feb621
@@ -14,10 +14,20 @@
feb621
    ../kwalletwizardpageintro.ui
feb621
    ../kwalletwizardpageoptions.ui
feb621
    ../kwalletwizardpagepassword.ui
feb621
+   ../kwalletwizardpagegpgkey.ui
feb621
 )
feb621
 
feb621
+if (QGPGME_FOUND)
feb621
+    kde4_add_ui_files(kwalletwizardtest_SRCS
feb621
+        ../kwalletwizardpagepasswordgpg.ui)
feb621
+endif(QGPGME_FOUND)
feb621
+
feb621
 kde4_add_executable(kwalletwizardtest TEST ${kwalletwizardtest_SRCS})
feb621
 target_link_libraries(kwalletwizardtest ${KDE4_KDECORE_LIBS} ${KDE4_KDEUI_LIBS} ${QT_QTGUI_LIBRARY})
feb621
+if (QGPGME_FOUND)
feb621
+    target_link_libraries(kwalletwizardtest ${QGPGME_LIBRARIES})
feb621
+endif(QGPGME_FOUND)
feb621
+
feb621
 set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} )
feb621
 
feb621
 include_directories( ${KDE4_KDEUI_INCLUDES} ) # for kwallet.h