1
0
mirror of https://github.com/QRouland/UTPass.git synced 2025-01-24 15:46:40 +00:00

Refactor gpg for more clean job handling

This commit is contained in:
Quentin Rouland 2025-01-15 23:15:00 +01:00
parent 00116aea8c
commit e589abd10c
11 changed files with 381 additions and 242 deletions

View File

@ -3,6 +3,7 @@
#include <QFile> #include <QFile>
#include <QDir> #include <QDir>
#include <QtCore/QStandardPaths> #include <QtCore/QStandardPaths>
#include <QProcess>
#include <gpgme.h> #include <gpgme.h>
#include <gpgme++/data.h> #include <gpgme++/data.h>
@ -22,9 +23,11 @@
#include <qgpgme/keylistjob.h> #include <qgpgme/keylistjob.h>
#include <qgpgme/changeownertrustjob.h> #include <qgpgme/changeownertrustjob.h>
#include "gpg.h" #include "gpg.h"
#include "passkeymodel.h"
#include "passphraseprovider.h" #include "passphraseprovider.h"
#include "qprocess.h"
@ -32,9 +35,9 @@
using namespace GpgME; using namespace GpgME;
using namespace QGpgME; using namespace QGpgME;
Gpg::Gpg() Gpg::Gpg(QObject* windows)
{ {
m_window = nullptr; this->m_passphrase_provider = new UTPassphraseProvider(windows);
Gpg::initGpgConfig(); Gpg::initGpgConfig();
@ -50,6 +53,10 @@ Gpg::Gpg()
qDebug() << "GNUPG Home is :" << engineInfo(OpenPGP).homeDirectory(); qDebug() << "GNUPG Home is :" << engineInfo(OpenPGP).homeDirectory();
} }
Gpg::~Gpg(){
delete this->m_passphrase_provider;
}
QString Gpg::initGpgHome() QString Gpg::initGpgHome()
{ {
@ -124,37 +131,28 @@ void Gpg::initGpgConfig()
} }
QPair<Error, QString> Gpg::decrypt(QByteArray cipherText) Error Gpg::decrypt(QByteArray cipher_text)
{ {
auto job = openpgp()->decryptJob(); auto job = openpgp()->decryptJob();
auto ctx = DecryptJob::context(job); auto ctx = DecryptJob::context(job);
auto provider = new UTPassphraseProvider; ctx->setPassphraseProvider(this->m_passphrase_provider);
ctx->setPassphraseProvider(provider);
ctx->setPinentryMode(Context::PinentryLoopback); ctx->setPinentryMode(Context::PinentryLoopback);
QByteArray plain_text; QObject::connect(job, &DecryptJob::result,
auto decResult = job->exec(cipherText, plain_text); this, &Gpg::decryptResultSlot);
delete job; return job->start(cipher_text);
delete provider;
if (decResult.error()) {
qWarning() << "something gone wrong on decrypt";
qDebug() << "Code Error : " << decResult.error().code();
qDebug() << "Error str : " << decResult.error().asString();
}
return QPair<Error, QString>(decResult.error(), QString::fromUtf8(plain_text));
} }
Error Gpg::decryptFromFile(QString path)
QPair<Error, QString> Gpg::decryptFromFile(QString path)
{ {
qDebug() << "Decrypt from " << path; qDebug() << "Decrypt from " << path;
QFile file(path); QFile file(path);
if (!file.open(QIODevice::ReadOnly)) { if (!file.open(QIODevice::ReadOnly)) {
qWarning() << "Can't open the File"; qWarning() << "Can't open the File";
return QPair<Error, QString>(Error(), QString());; return Error();
} }
QByteArray cipherText = file.readAll(); QByteArray cipherText = file.readAll();
file.close(); file.close();
@ -162,77 +160,83 @@ QPair<Error, QString> Gpg::decryptFromFile(QString path)
} }
QPair<Error, QByteArray> Gpg::encrypt(QString str, QString uid, bool ascii_armor, bool text_mode)
void Gpg::decryptResultSlot(const GpgME::DecryptionResult &result, const QByteArray &plainText, const QString &auditLogAsHtml, const GpgME::Error &auditLogError)
{ {
if (result.error()) {
qDebug() << "Encrypt to QByteArray"; qWarning() << "Something gone wrong on decrypt";
auto keys = getKeys(uid); qDebug() << "Code Error : " << result.error().code();
if (keys.first) { qDebug() << "Error str : " << result.error().asString();
return QPair<Error, QByteArray>(keys.first, QByteArray());
} }
emit decryptResult(result.error(), QString::fromUtf8(plainText));
auto job = std::unique_ptr<EncryptJob>(openpgp()->encryptJob(ascii_armor, text_mode));
QByteArray cipherText;
auto result = job->exec(keys.second, str.toUtf8(), Context::AlwaysTrust, cipherText);
qDebug() << "Encrypted to QByteArray";
return QPair<Error, QByteArray>(result.error(), cipherText);
} }
Error Gpg::encryptToFile(QString str, QString path, QString uid, bool ascii_armor, // QPair<Error, QByteArray> Gpg::encrypt(QString str, QString uid, bool ascii_armor, bool text_mode)
bool text_mode) // {
{
qDebug() << "Encrypting to file " << path; // qDebug() << "Encrypt to QByteArray";
QFile file(path); // auto keys = getKeys(uid);
if (!file.open(QIODevice::WriteOnly)) { // if (keys.first) {
qWarning() << "Can't open the file to write it" ; // return QPair<Error, QByteArray>(keys.first, QByteArray());
return Error(); // }
}
auto encrypt_ret = encrypt(str, uid, ascii_armor, text_mode); // auto job = std::unique_ptr<EncryptJob>(openpgp()->encryptJob(ascii_armor, text_mode));
if (encrypt_ret.first) {
file.write(encrypt_ret.second); // QByteArray cipherText;
} // auto result = job->exec(keys.second, str.toUtf8(), Context::AlwaysTrust, cipherText);
qDebug() << "Encrypting to file " << path;
return encrypt_ret.first; // qDebug() << "Encrypted to QByteArray";
} // return QPair<Error, QByteArray>(result.error(), cipherText);
// }
QPair<Error, std::vector< GpgME::Key >> Gpg::getAllKeys ( bool remote, const bool include_sigs, // Error Gpg::encryptToFile(QString str, QString path, QString uid, bool ascii_armor,
// bool text_mode)
// {
// qDebug() << "Encrypting to file " << path;
// QFile file(path);
// if (!file.open(QIODevice::WriteOnly)) {
// qWarning() << "Can't open the file to write it" ;
// return Error();
// }
// auto encrypt_ret = encrypt(str, uid, ascii_armor, text_mode);
// if (encrypt_ret.first) {
// file.write(encrypt_ret.second);
// }
// qDebug() << "Encrypting to file " << path;
// return encrypt_ret.first;
// }
Error Gpg::getAllKeys ( bool remote, const bool include_sigs,
bool validate ) bool validate )
{ {
return getKeys(QString(""), remote, include_sigs, validate); return getKeys(QString(""), remote, include_sigs, validate);
} }
QPair<Error, std::vector<Key >> Gpg::getKeys(QString pattern_uid, bool remote, bool include_sigs, Error Gpg::getKeys(QString pattern_uid, bool remote, bool include_sigs,
bool validate) bool validate)
{ {
qDebug() << "Getting the keys " << pattern_uid; qDebug() << "Getting the keys " << pattern_uid;
auto job = std::unique_ptr<KeyListJob>(openpgp()->keyListJob(remote, include_sigs, validate)); auto job = openpgp()->keyListJob(remote, include_sigs, validate);
std::vector<Key> keys; QObject::connect(job, &KeyListJob::result,
auto result = job->exec(QStringList() << pattern_uid, false, keys); this, &Gpg::getKeysJobResultSlot);
qDebug() << "Got the keys " << pattern_uid; return job->start(QStringList() << pattern_uid, false);
return QPair<Error, std::vector< Key >> (result.error(), keys);
} }
void Gpg::getKeysJobResultSlot(const GpgME::KeyListResult &result, const std::vector<GpgME::Key> &keys, const QString &auditLogAsHtml , const GpgME::Error &auditLogError)
QPair<Error, Key> Gpg::getKey(QString uid, bool remote, bool include_sigs, bool validate)
{ {
qDebug() << "Getting the key " << uid; if (result.error()) {
auto keys = getKeys(uid, remote, include_sigs, validate); qWarning() << "Something gone wrong on decrypt";
qDebug() << "Code Error : " << result.error().code();
if (keys.first or keys.second.size() != 1) { qDebug() << "Error str : " << result.error().asString();
qWarning() << "Bad id";
return QPair<Error, Key>(keys.first, Key::null);
} }
qDebug() << "Got the key " << uid; emit getKeysResult(result.error(), keys);
return QPair<Error, Key>(keys.first, keys.second.front());
} }
Error Gpg::importKeysFromFile(QString path) Error Gpg::importKeysFromFile(QString path)
{ {
qDebug() << "Importing the key file" << path; qDebug() << "Importing the key file" << path;
@ -242,51 +246,52 @@ Error Gpg::importKeysFromFile(QString path)
qWarning() << "Can't open the File"; qWarning() << "Can't open the File";
return Error(); return Error();
} }
auto data = file.readAll();
file.close();
auto job = openpgp()->importJob(); auto job = openpgp()->importJob();
auto ctx = ImportJob::context(job);
auto result = job->exec(file.readAll()); QObject::connect(job, &ImportJob::result,
this, &Gpg::importKeysFromFileSlot);
return job->start(data);
}
void Gpg::importKeysFromFileSlot(const GpgME::ImportResult &result, const QString &auditLogAsHtml, const GpgME::Error &auditLogError)
{
qDebug() << "numImported" << result.numImported(); qDebug() << "numImported" << result.numImported();
qDebug() << "numSecretKeysImported" << result.numSecretKeysImported(); qDebug() << "numSecretKeysImported" << result.numSecretKeysImported();
qDebug() << "numSecretKeysConsidered" << result.numSecretKeysConsidered(); qDebug() << "numSecretKeysConsidered" << result.numSecretKeysConsidered();
qDebug() << "numSecretKeysUnchanged" << result.numSecretKeysUnchanged(); qDebug() << "numSecretKeysUnchanged" << result.numSecretKeysUnchanged();
qDebug() << "numUnchanged" << result.numUnchanged(); qDebug() << "numUnchanged" << result.numUnchanged();
file.close();
delete job;
if (result.error()) { if (result.error()) {
qWarning() << "Import go wrong"; qWarning() << "Something gone wrong on decrypt";
qDebug() << "Code Error : " << result.error().code(); qDebug() << "Code Error : " << result.error().code();
qDebug() << "Error str : " << result.error().asString(); qDebug() << "Error str : " << result.error().asString();
} }
qDebug() << "Imported the key file" << path; emit importKeysFromFileResult(result.error());
return result.error();
} }
Error Gpg::deleteKeyId(QString uid) Error Gpg::deleteKey(const Key key)
{ {
qDebug() << "Deleting key id " << uid; auto job = openpgp()->deleteJob();
auto key = getKey(uid);
if (key.first) { QObject::connect(job, &DeleteJob::result,
return key.first; this, &Gpg::deleteKeySlot);
}
auto ctx = std::unique_ptr<Context>(Context::createForProtocol(OpenPGP)); return openpgp()->deleteJob()->start(key, true);
auto err = ctx->deleteKey(key.second, true);
if (err) {
qWarning() << "Delete go wrong";
qDebug() << "Code Error : " << err.code();
qDebug() << "Error str : " << err.asString();
return err;
}
qDebug() << "Deleted key id" << uid;
return err;
} }
void Gpg::deleteKeySlot(const GpgME::Error &error, const QString &auditLogAsHtml, const GpgME::Error &auditLogError) {
if (error) {
qWarning() << "Something gone wrong on decrypt";
qDebug() << "Code Error : " << error.code();
qDebug() << "Error str : " << error.asString();
}
emit deleteKeyResult(error);
}

View File

@ -1,61 +1,95 @@
#ifndef GPG_H #ifndef GPG_H
#define GPG_H #define GPG_H
#include "passkeymodel.h"
#include "passphraseprovider.h"
#include <memory> #include <memory>
#include <QQuickWindow> #include <QQuickWindow>
#include <gpgme++/context.h> #include <gpgme++/context.h>
#include <qgpgme/changeownertrustjob.h> #include <qgpgme/changeownertrustjob.h>
#include <QSemaphore>
#include <gpgme.h>
#include <qgpgme/importjob.h>
#include <qgpgme/deletejob.h>
#include <qgpgme/decryptjob.h>
#include <qgpgme/encryptjob.h>
#include <qgpgme/protocol.h>
#include <qgpgme/keylistjob.h>
#include <qgpgme/changeownertrustjob.h>
using namespace GpgME; using namespace GpgME;
using namespace QGpgME;
class Gpg class Gpg: public QObject
{ {
private: Q_OBJECT
Gpg(); Q_PROPERTY(UTPassphraseProvider* passphrase_provider READ passphrase_provider MEMBER m_passphrase_provider )
QObject *m_window; private slots:
void decryptResultSlot(
const DecryptionResult &result,
const QByteArray &plain_text,
const QString &auditLogAsHtml,
const Error &auditLogError
);
void getKeysJobResultSlot(
const GpgME::KeyListResult &result,
const std::vector<GpgME::Key> &keys,
const QString &auditLogAsHtml ,
const GpgME::Error &auditLogError
);
void importKeysFromFileSlot(
const GpgME::ImportResult &result,
const QString &auditLogAsHtml,
const GpgME::Error &auditLogError
);
void deleteKeySlot(
const GpgME::Error &result,
const QString &auditLogAsHtml,
const GpgME::Error &auditLogError
);
signals:
void importKeysFromFileResult(Error err);
void getKeysResult(Error err, std::vector<GpgME::Key> keys);
void deleteKeyResult(Error err);
void decryptResult(Error err, QString plain_text);
private:
UTPassphraseProvider* m_passphrase_provider;
QString findCommandPath(const QString &command); QString findCommandPath(const QString &command);
QString initGpgHome(); QString initGpgHome();
QString initGpgExec(); QString initGpgExec();
void initGpgConfig(); void initGpgConfig();
Error getKey(QString uid, bool remote = false, bool include_sigs = false,
bool validate = false);
public: public:
static std::shared_ptr<Gpg> instance() Gpg(QObject* window);
~Gpg();
UTPassphraseProvider* passphrase_provider() const
{ {
static std::shared_ptr<Gpg> s{new Gpg}; return m_passphrase_provider;
return s;
} }
Gpg(Gpg const &) = delete;
void operator=(Gpg const &) = delete;
void setWindow(QObject *window) Error importKeysFromFile(const QString path);
{ Error getKeys(const QString pattern_uid, const bool remote = false,
m_window = window; const bool include_sigs = false,
}; const bool validate = false);
Error getAllKeys (bool remote = false, bool include_sigs = {}, bool
QObject *getWindow()
{
return m_window;
};
QPair<Error, std::vector<Key >> getAllKeys(bool remote = false, bool include_sigs = {}, bool
validate = false); validate = false);
QPair<Error, std::vector<Key >> getKeys( QString pattern_uid, bool remote = false, Error deleteKey(const Key key);
bool include_sigs = false, Error decrypt(const QByteArray cipher_text);
bool validate = false); Error decryptFromFile(const QString path);
QPair<Error, Key> getKey( QString uid, bool remote = false, bool include_sigs = false, //Error encrypt (QString str, QString uid, bool ascii_armor = true,
bool validate = false); // bool text_mode = true);
QPair<Error, QString> decrypt( QByteArray cipherText);
QPair<Error, QString> decryptFromFile( QString path);
QPair<Error, QByteArray> encrypt( QString str, QString uid, bool ascii_armor = true,
bool text_mode = true);
Error encryptToFile( QString str, QString path, QString uid, bool ascii_armor = true,
bool text_mode = true);
Error importKeysFromFile( QString path);
Error deleteKeyId( QString uid);
}; };
#endif #endif

View File

@ -8,8 +8,11 @@
Pass::Pass(): m_password_store (QStandardPaths::writableLocation( Pass::Pass():
QStandardPaths::AppDataLocation).append("/.password-store")) m_password_store (QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation).append("/.password-store")),
m_sem(std::unique_ptr<QSemaphore>(new QSemaphore(1))),
m_show_filename(QString())
{} {}
void Pass::initialize(QObject *window) void Pass::initialize(QObject *window)
@ -18,7 +21,13 @@ void Pass::initialize(QObject *window)
qFatal("window is invalid. Abording."); qFatal("window is invalid. Abording.");
} }
Gpg::instance()->setWindow(window); this->m_gpg = std::unique_ptr<Gpg>(new Gpg(window));
QObject::connect(this, &Pass::responsePassphraseDialogPropagate, this->m_gpg->passphrase_provider(), &UTPassphraseProvider::handleResponse);
QObject::connect(this->m_gpg.get(), &Gpg::importKeysFromFileResult, this, &Pass::importGPGKeyResult);
QObject::connect(this->m_gpg.get(), &Gpg::getKeysResult, this, &Pass::getAllGPGKeysResult);
QObject::connect(this->m_gpg.get(), &Gpg::deleteKeyResult, this, &Pass::deleteGPGKeyResult);
QObject::connect(this->m_gpg.get(), &Gpg::decryptResult, this, &Pass::showResult);
QDir dir(m_password_store); QDir dir(m_password_store);
if (!dir.exists()) { if (!dir.exists()) {
@ -27,38 +36,78 @@ void Pass::initialize(QObject *window)
qInfo() << "Password Store is :" << m_password_store; qInfo() << "Password Store is :" << m_password_store;
} }
void Pass::show(QUrl url) bool Pass::show(QUrl url)
{ {
qInfo() << "Decrypting"; if (!this->m_sem->tryAcquire(1, 500)){ return false; }
auto decrypt_ret = Gpg::instance()->decryptFromFile(url.toLocalFile()); auto path = url.toLocalFile();
if (decrypt_ret.first) { qInfo() << "Staring decrypting job for " << path;
qInfo() << "Decrypt Failed"; QFileInfo file_info(path);
emit decryptFailed(); this->m_show_filename = file_info.completeBaseName();
} else if (decrypt_ret.second.isNull()) { return this->m_gpg->decryptFromFile(path);
qInfo() << "Decrypt Canceled";
emit decryptCanceled();
} else {
qInfo() << "Decrypt OK";
emit decrypted(url.fileName(), decrypt_ret.second);
}
} }
bool Pass::deleteGPGKey(QString id) void Pass::showResult(Error err, QString plain_text) {
qInfo() << "Result for decrypting job";
if (err) {
qInfo() << "Decrypt Failed";
emit showFailed(err.asString());
} else {
qInfo() << "Decrypt OK";
emit showSucceed(this->m_show_filename, plain_text);
}
this->m_show_filename = QString();
this->m_sem->release(1);
}
bool Pass::deleteGPGKey(Key key)
{ {
qInfo() << "Deleting Key id " << id; if (!this->m_sem->tryAcquire(1, 500)){ return false;}
return !Gpg::instance()->deleteKeyId(id); qInfo() << "Deleting Key";
return this->m_gpg->deleteKey(key);
}
void Pass::deleteGPGKeyResult(Error err) {
if(err) {
emit deleteGPGKeyFailed(err.asString());
} else {
emit deleteGPGKeySucceed();
}
this->m_sem->release(1);
} }
bool Pass::importGPGKey(QUrl url) bool Pass::importGPGKey(QUrl url)
{ {
if (!this->m_sem->tryAcquire(1, 500)){ return false;}
qInfo() << "Importing Key from " << url; qInfo() << "Importing Key from " << url;
return !Gpg::instance()->importKeysFromFile(url.toLocalFile()); return this->m_gpg->importKeysFromFile(url.toLocalFile());
} }
QVariant Pass::getAllGPGKeys() void Pass::importGPGKeyResult(Error err) {
if(err) {
emit importGPGKeyFailed(err.asString());
} else {
emit importGPGKeySucceed();
}
this->m_sem->release(1);
}
bool Pass::getAllGPGKeys()
{ {
if (!this->m_sem->tryAcquire(1, 500)){ return false; }
qInfo() << "Getting all key form gpg "; qInfo() << "Getting all key form gpg ";
return QVariant::fromValue(PassKeyModel::keysToPassKey( return this->m_gpg->getAllKeys();
Gpg::instance()->getAllKeys().second)); // TODO Error handling
} }
void Pass::getAllGPGKeysResult(Error err, std::vector<GpgME::Key> keys_info) {
if(err) {
emit getAllGPGKeysFailed(err.asString());
} else {
emit getAllGPGKeysSucceed(QVariant::fromValue(PassKeyModel::keysToPassKey(keys_info)));
}
this->m_sem->release(1);
}
void Pass::responsePassphraseDialog(bool cancel, QString passphrase) {
qDebug() << "responsePassphraseDialog";
emit responsePassphraseDialogPropagate(cancel, passphrase);
}

View File

@ -4,20 +4,44 @@
#include <QObject> #include <QObject>
#include <QUrl> #include <QUrl>
#include <QVariant> #include <QVariant>
#include <gpgme++/context.h>
#include "gpg.h"
using namespace GpgME;
class Pass : public QObject class Pass : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString password_store READ password_store) Q_PROPERTY(QString password_store READ password_store MEMBER m_password_store CONSTANT)
private slots:
void showResult(Error err, QString plain_text);
void deleteGPGKeyResult(Error err);
void importGPGKeyResult(Error err);
void getAllGPGKeysResult(Error err, std::vector< GpgME::Key > keys_info);
signals:
// GPG
void deleteGPGKeySucceed();
void deleteGPGKeyFailed(QString message);
void importGPGKeySucceed();
void importGPGKeyFailed(QString message);
void getAllGPGKeysSucceed(QVariant keys_info);
void getAllGPGKeysFailed(QString message);
void responsePassphraseDialogPropagate(bool cancel, QString passphrase);
// pass show
void showSucceed(QString name, QString text);
void showFailed(QString message);
private: private:
QString m_password_store; QString m_password_store;
std::unique_ptr<Gpg> m_gpg;
signals: std::unique_ptr<QSemaphore> m_sem;
void decrypted(QString name, QString text); QString m_show_filename;
void decryptCanceled();
void decryptFailed();
public: public:
Pass(); Pass();
@ -29,10 +53,16 @@ public:
} }
Q_INVOKABLE void initialize(QObject *window); Q_INVOKABLE void initialize(QObject *window);
Q_INVOKABLE void show(QUrl url);
Q_INVOKABLE bool deleteGPGKey(QString id); // GPG
Q_INVOKABLE bool deleteGPGKey(Key key);
Q_INVOKABLE bool importGPGKey(QUrl url); Q_INVOKABLE bool importGPGKey(QUrl url);
Q_INVOKABLE QVariant getAllGPGKeys(); Q_INVOKABLE bool getAllGPGKeys();
Q_INVOKABLE void responsePassphraseDialog(bool cancel, QString passphrase);
// PASS
Q_INVOKABLE bool show(QUrl url);
}; };
#endif #endif

View File

@ -9,14 +9,13 @@ using namespace GpgME;
class UserIdModel : public QObject class UserIdModel : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString uid READ uid MEMBER m_uid CONSTANT) Q_PROPERTY(QString uid READ uid CONSTANT)
Q_PROPERTY(QString name READ name MEMBER m_name CONSTANT) Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(QString email READ email MEMBER m_email CONSTANT) Q_PROPERTY(QString email READ email CONSTANT)
private:
UserID m_user_id; UserID m_user_id;
public: public:
UserIdModel(UserID key): UserIdModel(UserID key):
m_user_id(key) m_user_id(key)
{}; {};
@ -38,10 +37,11 @@ public:
class PassKeyModel : public QObject class PassKeyModel : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString uid READ uid MEMBER m_uid CONSTANT) Q_PROPERTY(Key key READ key MEMBER m_key CONSTANT)
Q_PROPERTY(QList<QObject *> userIds READ userIds MEMBER m_user_ids CONSTANT) Q_PROPERTY(QString uid READ uid CONSTANT)
Q_PROPERTY(bool isSecret READ isSecret MEMBER m_secret CONSTANT) Q_PROPERTY(QList<QObject *> userIds READ userIds CONSTANT)
Q_PROPERTY(bool isExpired READ isExpired MEMBER m_expired CONSTANT) Q_PROPERTY(bool isSecret READ isSecret CONSTANT)
Q_PROPERTY(bool isExpired READ isExpired CONSTANT)
Key m_key; Key m_key;
public: public:
@ -58,6 +58,11 @@ public:
return ret; return ret;
}; };
Key key() const
{
return m_key;
};
QString uid() const QString uid() const
{ {
return QString::fromUtf8(m_key.keyID()); return QString::fromUtf8(m_key.keyID());

View File

@ -1,6 +1,7 @@
#ifndef UTPASSPHRASEPROVIDER_H #ifndef UTPASSPHRASEPROVIDER_H
#define UTPASSPHRASEPROVIDER_H #define UTPASSPHRASEPROVIDER_H
#include <QDebug>
#include <stdio.h> #include <stdio.h>
#include <QObject> #include <QObject>
#include <QQmlProperty> #include <QQmlProperty>
@ -14,48 +15,57 @@
class UTPassphraseProvider : public QObject, public PassphraseProvider class UTPassphraseProvider : public QObject, public PassphraseProvider
{ {
Q_OBJECT Q_OBJECT
private:
std::unique_ptr<QEventLoop> m_loop;
std::unique_ptr<QSemaphore> m_sem;
char *m_passphrase;
bool m_canceled;
public slots: public slots:
void handleResponse(bool canceled, QString p) void handleResponse(bool canceled, QString p)
{ {
qDebug() << "call handleResponse";
if (!canceled) if (!canceled)
gpgrt_asprintf(&m_passphrase, "%s", p.toUtf8().constData()); gpgrt_asprintf(&m_passphrase, "%s", p.toUtf8().constData());
else else
m_canceled = true; m_canceled = true;
m_loop->quit(); emit unlockEventLoop();
}; };
signals:
void unlockEventLoop();
private:
std::unique_ptr<QSemaphore> m_sem;
char *m_passphrase;
bool m_canceled;
QObject* m_window;
public: public:
UTPassphraseProvider(): UTPassphraseProvider(QObject* window):
m_loop(std::unique_ptr<QEventLoop>(new QEventLoop)),
m_sem(std::unique_ptr<QSemaphore>(new QSemaphore(1))), m_sem(std::unique_ptr<QSemaphore>(new QSemaphore(1))),
m_passphrase(nullptr), m_passphrase(nullptr),
m_canceled(false) m_canceled(false),
{} m_window(window)
{
qDebug() << "Initialize UTPassphraseProviderr";
}
char *getPassphrase( const char *useridHint, char *getPassphrase( const char *useridHint,
const char *description, const char *description,
bool previousWasBad, bool previousWasBad,
bool &canceled ) Q_DECL_OVERRIDE { bool &canceled ) Q_DECL_OVERRIDE {
if (!m_sem->tryAcquire(1, 3000)) qDebug() << "Call the getPassphrase";
if (!this->m_sem->tryAcquire(1, 500))
{ {
qWarning() << "Cannot acquire UTPassphraseProvider semaphore."; qWarning() << "Cannot acquire UTPassphraseProvider semaphore.";
canceled = true; canceled = true;
return nullptr; return nullptr;
} }
m_passphrase = nullptr; this->m_passphrase = nullptr;
m_canceled = false; this->m_canceled = false;
qDebug() << "Call the QML Dialog Passphrase Provider"; qDebug() << "Call the QML Dialog Passphrase Provider";
QMetaObject::invokeMethod( QMetaObject::invokeMethod(
Gpg::instance()->getWindow(), "callPassphraseDialog", this->m_window, "callPassphraseDialog",
Q_ARG(QVariant, useridHint), Q_ARG(QVariant, useridHint),
Q_ARG(QVariant, description), Q_ARG(QVariant, description),
Q_ARG(QVariant, previousWasBad) Q_ARG(QVariant, previousWasBad)
@ -63,24 +73,22 @@ public:
qDebug() << "Waiting for response"; qDebug() << "Waiting for response";
QObject::connect( QEventLoop loop;
Gpg::instance()->getWindow(), SIGNAL(responsePassphraseDialog(bool, QString)), QObject::connect(this, &UTPassphraseProvider::unlockEventLoop, &loop, &QEventLoop::quit);
this, SLOT(handleResponse(bool, QString)) loop.exec();
);
m_loop->exec();
qDebug() << "Prepare Returns"; qDebug() << "Prepare Returns";
char *ret; char *ret;
gpgrt_asprintf(&ret, "%s", m_passphrase); gpgrt_asprintf(&ret, "%s", m_passphrase);
canceled = m_canceled; canceled = this->m_canceled;
qDebug() << "Clean"; qDebug() << "Clean";
if (m_passphrase) if (this->m_passphrase)
{ {
free(m_passphrase); free(m_passphrase);
} }
m_canceled = false; this->m_canceled = false;
m_sem->release(1); this->m_sem->release(1);
return ret; return ret;
}; };
}; };

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: utpass.qrouland\n" "Project-Id-Version: utpass.qrouland\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-01-14 13:57+0100\n" "POT-Creation-Date: 2025-01-15 23:14+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -17,10 +17,6 @@ msgstr ""
"Content-Type: text/plain; charset=CHARSET\n" "Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
#: ../qml/components/FileDir.qml:59
msgid "Decryption failed !"
msgstr ""
#: ../qml/dialogs/ErrorDialog.qml:12 #: ../qml/dialogs/ErrorDialog.qml:12
msgid "Error !" msgid "Error !"
msgstr "" msgstr ""
@ -83,21 +79,25 @@ msgstr ""
msgid "Info" msgid "Info"
msgstr "" msgstr ""
#: ../qml/pages/PasswordList.qml:22 #: ../qml/pages/PasswordList.qml:37
msgid "" msgid ""
"No password found<br>You can import a password store by cloning or importing " "No password found<br>You can import a password store by cloning or importing "
"a zip in the settings" "a zip in the settings"
msgstr "" msgstr ""
#: ../qml/pages/PasswordList.qml:61 #: ../qml/pages/PasswordList.qml:76
msgid "Back" msgid "Back"
msgstr "" msgstr ""
#: ../qml/pages/PasswordList.qml:68 ../qml/pages/headers/MainHeader.qml:9 #: ../qml/pages/PasswordList.qml:83 ../qml/pages/headers/MainHeader.qml:9
#: ../qml/pages/headers/StackHeader.qml:9 UTPass.desktop.in.h:1 #: ../qml/pages/headers/StackHeader.qml:9 UTPass.desktop.in.h:1
msgid "UTPass" msgid "UTPass"
msgstr "" msgstr ""
#: ../qml/pages/PasswordList.qml:96
msgid "Decryption failed !"
msgstr ""
#: ../qml/pages/headers/MainHeader.qml:26 ../qml/pages/settings/Settings.qml:70 #: ../qml/pages/headers/MainHeader.qml:26 ../qml/pages/settings/Settings.qml:70
msgid "Settings" msgid "Settings"
msgstr "" msgstr ""

View File

@ -10,8 +10,6 @@ MainView {
id: root id: root
signal responsePassphraseDialog(bool canceled, string passphrase)
function initPass(rootView) { function initPass(rootView) {
Pass.initialize(rootView); Pass.initialize(rootView);
pageStack.push(Qt.resolvedUrl("pages/PasswordList.qml")); pageStack.push(Qt.resolvedUrl("pages/PasswordList.qml"));
@ -19,30 +17,36 @@ MainView {
function callPassphraseDialog(useridHint, description, previousWasBad) { function callPassphraseDialog(useridHint, description, previousWasBad) {
//TODO use parameters to impove passphrase dialog //TODO use parameters to impove passphrase dialog
var passphraseDialog = PopupUtils.open(Qt.resolvedUrl("dialogs/PassphraseDialog.qml")); var pop = PopupUtils.open(passphraseDialog);
passphraseDialog.activateFocus(); pop.activateFocus();
var validated = function validated(passphrase) {
responsePassphraseDialog(false, passphrase);
};
var canceled = function canceled() {
responsePassphraseDialog(true, "");
};
passphraseDialog.validated.connect(validated);
passphraseDialog.canceled.connect(canceled);
} }
objectName: "mainView" objectName: "mainView"
applicationName: "utpass.qrouland" applicationName: "utpass.qrouland"
automaticOrientation: false automaticOrientation: true
width: units.gu(48)
height: units.gu(80) width: units.gu(45)
height: units.gu(75)
PageStack { PageStack {
id: pageStack id: pageStack
anchors.fill: parent anchors.fill: parent
Component.onCompleted: { }
Component {
id: passphraseDialog
PassphraseDialog {
onValidated: {
console.info("valided");
Pass.responsePassphraseDialog(false, passphrase);
}
onCanceled: {
console.info("canceled");
Pass.responsePassphraseDialog(true, "");
} }
} }
}
} }

View File

@ -33,12 +33,14 @@ Component {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
var path = folderModel.folder + "/" + fileName;
if (fileIsDir) { if (fileIsDir) {
folderModel.folder = folderModel.folder + "/" + fileName; folderModel.folder = path;
backAction.visible = true; backAction.visible = true;
passwordListHeader.title = fileName; passwordListHeader.title = fileName;
} else { } else {
Pass.show(folderModel.folder + "/" + fileName); console.debug("pass show %1".arg(path))
Pass.show(path);
} }
} }
} }
@ -52,15 +54,6 @@ Component {
borderColor: LomiriColors.warmGrey borderColor: LomiriColors.warmGrey
} }
Component {
id: passwordPageDecryptError
ErrorDialog {
textError: i18n.tr("Decryption failed !")
}
}
} }
} }

View File

@ -49,11 +49,11 @@ Page {
iconName: "back" iconName: "back"
text: "Back" text: "Back"
onTriggered: { onTriggered: {
// passwordPage.plainText = ""; passwordPage.plainText = null;
// for (var object in objects) { for (var object in objects) {
// object.text = ""; object.text = null;
// object.destroy(); object.destroy();
// } }
pageStack.pop(); pageStack.pop();
} }
} }

View File

@ -1,9 +1,11 @@
import "headers"
import "../components" import "../components"
import "../dialogs"
import Lomiri.Components 1.3 import Lomiri.Components 1.3
import Pass 1.0 import Pass 1.0
import Qt.labs.folderlistmodel 2.1 import Qt.labs.folderlistmodel 2.1
import QtQuick 2.4 import QtQuick 2.4
import "headers" import Lomiri.Components.Popups 1.3
Page { Page {
id: passwordListPage id: passwordListPage
@ -13,13 +15,13 @@ Page {
anchors.fill: parent anchors.fill: parent
Component.onCompleted: { Component.onCompleted: {
passwordStorePath = "file:" + Pass.password_store; passwordStorePath = "file:" + Pass.password_store;
Pass.onDecrypted.connect(function(filename, text) { Pass.onShowSucceed.connect(function(filename, text) {
pageStack.push(Qt.resolvedUrl("../pages/Password.qml"), { pageStack.push(Qt.resolvedUrl("../pages/Password.qml"), {
"plainText": text, "plainText": text,
"title": filename "title": filename
}); });
}); });
Pass.onDecryptFailed.connect(function() { Pass.onShowFailed.connect(function(message) {
PopupUtils.open(passwordPageDecryptError); PopupUtils.open(passwordPageDecryptError);
}); });
} }
@ -87,4 +89,13 @@ Page {
] ]
} }
Component {
id: passwordPageDecryptError
ErrorDialog {
textError: i18n.tr("Decryption failed !")
}
}
} }