mirror of
https://github.com/QRouland/UTPass.git
synced 2025-01-24 07:36:39 +00:00
Refactor gpg for more clean job handling
This commit is contained in:
parent
00116aea8c
commit
e589abd10c
@ -3,6 +3,7 @@
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QtCore/QStandardPaths>
|
||||
#include <QProcess>
|
||||
|
||||
#include <gpgme.h>
|
||||
#include <gpgme++/data.h>
|
||||
@ -22,9 +23,11 @@
|
||||
#include <qgpgme/keylistjob.h>
|
||||
#include <qgpgme/changeownertrustjob.h>
|
||||
|
||||
|
||||
#include "gpg.h"
|
||||
#include "passkeymodel.h"
|
||||
#include "passphraseprovider.h"
|
||||
#include "qprocess.h"
|
||||
|
||||
|
||||
|
||||
|
||||
@ -32,9 +35,9 @@
|
||||
using namespace GpgME;
|
||||
using namespace QGpgME;
|
||||
|
||||
Gpg::Gpg()
|
||||
Gpg::Gpg(QObject* windows)
|
||||
{
|
||||
m_window = nullptr;
|
||||
this->m_passphrase_provider = new UTPassphraseProvider(windows);
|
||||
|
||||
Gpg::initGpgConfig();
|
||||
|
||||
@ -50,6 +53,10 @@ Gpg::Gpg()
|
||||
qDebug() << "GNUPG Home is :" << engineInfo(OpenPGP).homeDirectory();
|
||||
}
|
||||
|
||||
Gpg::~Gpg(){
|
||||
delete this->m_passphrase_provider;
|
||||
}
|
||||
|
||||
|
||||
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 ctx = DecryptJob::context(job);
|
||||
|
||||
auto provider = new UTPassphraseProvider;
|
||||
ctx->setPassphraseProvider(provider);
|
||||
ctx->setPassphraseProvider(this->m_passphrase_provider);
|
||||
ctx->setPinentryMode(Context::PinentryLoopback);
|
||||
|
||||
QByteArray plain_text;
|
||||
auto decResult = job->exec(cipherText, plain_text);
|
||||
QObject::connect(job, &DecryptJob::result,
|
||||
this, &Gpg::decryptResultSlot);
|
||||
|
||||
delete job;
|
||||
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));
|
||||
return job->start(cipher_text);
|
||||
}
|
||||
|
||||
|
||||
QPair<Error, QString> Gpg::decryptFromFile(QString path)
|
||||
Error Gpg::decryptFromFile(QString path)
|
||||
{
|
||||
qDebug() << "Decrypt from " << path;
|
||||
QFile file(path);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
qWarning() << "Can't open the File";
|
||||
return QPair<Error, QString>(Error(), QString());;
|
||||
return Error();
|
||||
}
|
||||
QByteArray cipherText = file.readAll();
|
||||
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)
|
||||
{
|
||||
|
||||
qDebug() << "Encrypt to QByteArray";
|
||||
auto keys = getKeys(uid);
|
||||
if (keys.first) {
|
||||
return QPair<Error, QByteArray>(keys.first, QByteArray());
|
||||
if (result.error()) {
|
||||
qWarning() << "Something gone wrong on decrypt";
|
||||
qDebug() << "Code Error : " << result.error().code();
|
||||
qDebug() << "Error str : " << result.error().asString();
|
||||
}
|
||||
|
||||
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);
|
||||
emit decryptResult(result.error(), QString::fromUtf8(plainText));
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
// QPair<Error, QByteArray> Gpg::encrypt(QString str, QString uid, bool ascii_armor, bool text_mode)
|
||||
// {
|
||||
|
||||
// qDebug() << "Encrypt to QByteArray";
|
||||
// auto keys = getKeys(uid);
|
||||
// if (keys.first) {
|
||||
// return QPair<Error, QByteArray>(keys.first, QByteArray());
|
||||
// }
|
||||
|
||||
// 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);
|
||||
// }
|
||||
|
||||
|
||||
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 )
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
auto result = job->exec(QStringList() << pattern_uid, false, keys);
|
||||
QObject::connect(job, &KeyListJob::result,
|
||||
this, &Gpg::getKeysJobResultSlot);
|
||||
|
||||
qDebug() << "Got the keys " << pattern_uid;
|
||||
return QPair<Error, std::vector< Key >> (result.error(), keys);
|
||||
return job->start(QStringList() << pattern_uid, false);
|
||||
}
|
||||
|
||||
|
||||
QPair<Error, Key> Gpg::getKey(QString uid, bool remote, bool include_sigs, bool validate)
|
||||
void Gpg::getKeysJobResultSlot(const GpgME::KeyListResult &result, const std::vector<GpgME::Key> &keys, const QString &auditLogAsHtml , const GpgME::Error &auditLogError)
|
||||
{
|
||||
qDebug() << "Getting the key " << uid;
|
||||
auto keys = getKeys(uid, remote, include_sigs, validate);
|
||||
|
||||
if (keys.first or keys.second.size() != 1) {
|
||||
qWarning() << "Bad id";
|
||||
return QPair<Error, Key>(keys.first, Key::null);
|
||||
if (result.error()) {
|
||||
qWarning() << "Something gone wrong on decrypt";
|
||||
qDebug() << "Code Error : " << result.error().code();
|
||||
qDebug() << "Error str : " << result.error().asString();
|
||||
}
|
||||
qDebug() << "Got the key " << uid;
|
||||
return QPair<Error, Key>(keys.first, keys.second.front());
|
||||
emit getKeysResult(result.error(), keys);
|
||||
}
|
||||
|
||||
|
||||
Error Gpg::importKeysFromFile(QString path)
|
||||
{
|
||||
qDebug() << "Importing the key file" << path;
|
||||
@ -242,51 +246,52 @@ Error Gpg::importKeysFromFile(QString path)
|
||||
qWarning() << "Can't open the File";
|
||||
return Error();
|
||||
}
|
||||
auto data = file.readAll();
|
||||
file.close();
|
||||
|
||||
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() << "numSecretKeysImported" << result.numSecretKeysImported();
|
||||
qDebug() << "numSecretKeysConsidered" << result.numSecretKeysConsidered();
|
||||
qDebug() << "numSecretKeysUnchanged" << result.numSecretKeysUnchanged();
|
||||
qDebug() << "numUnchanged" << result.numUnchanged();
|
||||
|
||||
file.close();
|
||||
delete job;
|
||||
|
||||
if (result.error()) {
|
||||
qWarning() << "Import go wrong";
|
||||
qWarning() << "Something gone wrong on decrypt";
|
||||
qDebug() << "Code Error : " << result.error().code();
|
||||
qDebug() << "Error str : " << result.error().asString();
|
||||
}
|
||||
qDebug() << "Imported the key file" << path;
|
||||
return result.error();
|
||||
emit importKeysFromFileResult(result.error());
|
||||
}
|
||||
|
||||
Error Gpg::deleteKeyId(QString uid)
|
||||
Error Gpg::deleteKey(const Key key)
|
||||
{
|
||||
qDebug() << "Deleting key id " << uid;
|
||||
auto key = getKey(uid);
|
||||
auto job = openpgp()->deleteJob();
|
||||
|
||||
if (key.first) {
|
||||
return key.first;
|
||||
}
|
||||
QObject::connect(job, &DeleteJob::result,
|
||||
this, &Gpg::deleteKeySlot);
|
||||
|
||||
auto ctx = std::unique_ptr<Context>(Context::createForProtocol(OpenPGP));
|
||||
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;
|
||||
return openpgp()->deleteJob()->start(key, true);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1,61 +1,95 @@
|
||||
#ifndef GPG_H
|
||||
#define GPG_H
|
||||
|
||||
#include "passkeymodel.h"
|
||||
#include "passphraseprovider.h"
|
||||
#include <memory>
|
||||
#include <QQuickWindow>
|
||||
#include <gpgme++/context.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 QGpgME;
|
||||
|
||||
class Gpg
|
||||
class Gpg: public QObject
|
||||
{
|
||||
private:
|
||||
Gpg();
|
||||
Q_OBJECT
|
||||
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 initGpgHome();
|
||||
QString initGpgExec();
|
||||
void initGpgConfig();
|
||||
Error getKey(QString uid, bool remote = false, bool include_sigs = false,
|
||||
bool validate = false);
|
||||
|
||||
public:
|
||||
static std::shared_ptr<Gpg> instance()
|
||||
Gpg(QObject* window);
|
||||
~Gpg();
|
||||
|
||||
UTPassphraseProvider* passphrase_provider() const
|
||||
{
|
||||
static std::shared_ptr<Gpg> s{new Gpg};
|
||||
return s;
|
||||
return m_passphrase_provider;
|
||||
}
|
||||
Gpg(Gpg const &) = delete;
|
||||
void operator=(Gpg const &) = delete;
|
||||
|
||||
void setWindow(QObject *window)
|
||||
{
|
||||
m_window = window;
|
||||
};
|
||||
Error importKeysFromFile(const QString path);
|
||||
Error getKeys(const QString pattern_uid, const bool remote = false,
|
||||
const bool include_sigs = false,
|
||||
const bool validate = false);
|
||||
Error getAllKeys (bool remote = false, bool include_sigs = {}, bool
|
||||
validate = false);
|
||||
Error deleteKey(const Key key);
|
||||
Error decrypt(const QByteArray cipher_text);
|
||||
Error decryptFromFile(const QString path);
|
||||
//Error encrypt (QString str, QString uid, bool ascii_armor = true,
|
||||
// bool text_mode = true);
|
||||
|
||||
QObject *getWindow()
|
||||
{
|
||||
return m_window;
|
||||
};
|
||||
|
||||
|
||||
QPair<Error, std::vector<Key >> getAllKeys(bool remote = false, bool include_sigs = {}, bool
|
||||
validate = false);
|
||||
QPair<Error, std::vector<Key >> getKeys( QString pattern_uid, bool remote = false,
|
||||
bool include_sigs = false,
|
||||
bool validate = false);
|
||||
QPair<Error, Key> getKey( QString uid, bool remote = false, bool include_sigs = false,
|
||||
bool validate = false);
|
||||
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
|
||||
|
@ -8,8 +8,11 @@
|
||||
|
||||
|
||||
|
||||
Pass::Pass(): m_password_store (QStandardPaths::writableLocation(
|
||||
QStandardPaths::AppDataLocation).append("/.password-store"))
|
||||
Pass::Pass():
|
||||
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)
|
||||
@ -18,7 +21,13 @@ void Pass::initialize(QObject *window)
|
||||
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);
|
||||
if (!dir.exists()) {
|
||||
@ -27,38 +36,78 @@ void Pass::initialize(QObject *window)
|
||||
qInfo() << "Password Store is :" << m_password_store;
|
||||
}
|
||||
|
||||
void Pass::show(QUrl url)
|
||||
bool Pass::show(QUrl url)
|
||||
{
|
||||
qInfo() << "Decrypting";
|
||||
auto decrypt_ret = Gpg::instance()->decryptFromFile(url.toLocalFile());
|
||||
if (decrypt_ret.first) {
|
||||
qInfo() << "Decrypt Failed";
|
||||
emit decryptFailed();
|
||||
} else if (decrypt_ret.second.isNull()) {
|
||||
qInfo() << "Decrypt Canceled";
|
||||
emit decryptCanceled();
|
||||
} else {
|
||||
qInfo() << "Decrypt OK";
|
||||
emit decrypted(url.fileName(), decrypt_ret.second);
|
||||
}
|
||||
if (!this->m_sem->tryAcquire(1, 500)){ return false; }
|
||||
auto path = url.toLocalFile();
|
||||
qInfo() << "Staring decrypting job for " << path;
|
||||
QFileInfo file_info(path);
|
||||
this->m_show_filename = file_info.completeBaseName();
|
||||
return this->m_gpg->decryptFromFile(path);
|
||||
}
|
||||
|
||||
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;
|
||||
return !Gpg::instance()->deleteKeyId(id);
|
||||
if (!this->m_sem->tryAcquire(1, 500)){ return false;}
|
||||
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)
|
||||
{
|
||||
if (!this->m_sem->tryAcquire(1, 500)){ return false;}
|
||||
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 ";
|
||||
return QVariant::fromValue(PassKeyModel::keysToPassKey(
|
||||
Gpg::instance()->getAllKeys().second)); // TODO Error handling
|
||||
return this->m_gpg->getAllKeys();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -4,20 +4,44 @@
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
#include <QVariant>
|
||||
#include <gpgme++/context.h>
|
||||
|
||||
#include "gpg.h"
|
||||
|
||||
using namespace GpgME;
|
||||
|
||||
class Pass : public QObject
|
||||
{
|
||||
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:
|
||||
QString m_password_store;
|
||||
|
||||
signals:
|
||||
void decrypted(QString name, QString text);
|
||||
void decryptCanceled();
|
||||
void decryptFailed();
|
||||
std::unique_ptr<Gpg> m_gpg;
|
||||
std::unique_ptr<QSemaphore> m_sem;
|
||||
QString m_show_filename;
|
||||
|
||||
public:
|
||||
Pass();
|
||||
@ -29,10 +53,16 @@ public:
|
||||
}
|
||||
|
||||
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 QVariant getAllGPGKeys();
|
||||
Q_INVOKABLE bool getAllGPGKeys();
|
||||
Q_INVOKABLE void responsePassphraseDialog(bool cancel, QString passphrase);
|
||||
|
||||
// PASS
|
||||
Q_INVOKABLE bool show(QUrl url);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -9,14 +9,13 @@ using namespace GpgME;
|
||||
class UserIdModel : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString uid READ uid MEMBER m_uid CONSTANT)
|
||||
Q_PROPERTY(QString name READ name MEMBER m_name CONSTANT)
|
||||
Q_PROPERTY(QString email READ email MEMBER m_email CONSTANT)
|
||||
Q_PROPERTY(QString uid READ uid CONSTANT)
|
||||
Q_PROPERTY(QString name READ name CONSTANT)
|
||||
Q_PROPERTY(QString email READ email CONSTANT)
|
||||
|
||||
private:
|
||||
UserID m_user_id;
|
||||
public:
|
||||
|
||||
|
||||
UserIdModel(UserID key):
|
||||
m_user_id(key)
|
||||
{};
|
||||
@ -38,10 +37,11 @@ public:
|
||||
class PassKeyModel : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString uid READ uid MEMBER m_uid CONSTANT)
|
||||
Q_PROPERTY(QList<QObject *> userIds READ userIds MEMBER m_user_ids CONSTANT)
|
||||
Q_PROPERTY(bool isSecret READ isSecret MEMBER m_secret CONSTANT)
|
||||
Q_PROPERTY(bool isExpired READ isExpired MEMBER m_expired CONSTANT)
|
||||
Q_PROPERTY(Key key READ key MEMBER m_key CONSTANT)
|
||||
Q_PROPERTY(QString uid READ uid CONSTANT)
|
||||
Q_PROPERTY(QList<QObject *> userIds READ userIds CONSTANT)
|
||||
Q_PROPERTY(bool isSecret READ isSecret CONSTANT)
|
||||
Q_PROPERTY(bool isExpired READ isExpired CONSTANT)
|
||||
|
||||
Key m_key;
|
||||
public:
|
||||
@ -58,6 +58,11 @@ public:
|
||||
return ret;
|
||||
};
|
||||
|
||||
Key key() const
|
||||
{
|
||||
return m_key;
|
||||
};
|
||||
|
||||
QString uid() const
|
||||
{
|
||||
return QString::fromUtf8(m_key.keyID());
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef UTPASSPHRASEPROVIDER_H
|
||||
#define UTPASSPHRASEPROVIDER_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <stdio.h>
|
||||
#include <QObject>
|
||||
#include <QQmlProperty>
|
||||
@ -14,48 +15,57 @@
|
||||
class UTPassphraseProvider : public QObject, public PassphraseProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
std::unique_ptr<QEventLoop> m_loop;
|
||||
std::unique_ptr<QSemaphore> m_sem;
|
||||
char *m_passphrase;
|
||||
bool m_canceled;
|
||||
|
||||
public slots:
|
||||
void handleResponse(bool canceled, QString p)
|
||||
{
|
||||
if (!canceled)
|
||||
gpgrt_asprintf(&m_passphrase, "%s", p.toUtf8().constData());
|
||||
else
|
||||
m_canceled = true;
|
||||
m_loop->quit();
|
||||
};
|
||||
{
|
||||
qDebug() << "call handleResponse";
|
||||
if (!canceled)
|
||||
gpgrt_asprintf(&m_passphrase, "%s", p.toUtf8().constData());
|
||||
else
|
||||
m_canceled = true;
|
||||
emit unlockEventLoop();
|
||||
};
|
||||
|
||||
signals:
|
||||
void unlockEventLoop();
|
||||
|
||||
private:
|
||||
std::unique_ptr<QSemaphore> m_sem;
|
||||
char *m_passphrase;
|
||||
bool m_canceled;
|
||||
QObject* m_window;
|
||||
|
||||
|
||||
public:
|
||||
UTPassphraseProvider():
|
||||
m_loop(std::unique_ptr<QEventLoop>(new QEventLoop)),
|
||||
UTPassphraseProvider(QObject* window):
|
||||
m_sem(std::unique_ptr<QSemaphore>(new QSemaphore(1))),
|
||||
m_passphrase(nullptr),
|
||||
m_canceled(false)
|
||||
{}
|
||||
m_canceled(false),
|
||||
m_window(window)
|
||||
{
|
||||
qDebug() << "Initialize UTPassphraseProviderr";
|
||||
|
||||
}
|
||||
|
||||
char *getPassphrase( const char *useridHint,
|
||||
const char *description,
|
||||
bool previousWasBad,
|
||||
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.";
|
||||
canceled = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_passphrase = nullptr;
|
||||
m_canceled = false;
|
||||
this->m_passphrase = nullptr;
|
||||
this->m_canceled = false;
|
||||
|
||||
qDebug() << "Call the QML Dialog Passphrase Provider";
|
||||
QMetaObject::invokeMethod(
|
||||
Gpg::instance()->getWindow(), "callPassphraseDialog",
|
||||
this->m_window, "callPassphraseDialog",
|
||||
Q_ARG(QVariant, useridHint),
|
||||
Q_ARG(QVariant, description),
|
||||
Q_ARG(QVariant, previousWasBad)
|
||||
@ -63,24 +73,22 @@ public:
|
||||
|
||||
qDebug() << "Waiting for response";
|
||||
|
||||
QObject::connect(
|
||||
Gpg::instance()->getWindow(), SIGNAL(responsePassphraseDialog(bool, QString)),
|
||||
this, SLOT(handleResponse(bool, QString))
|
||||
);
|
||||
m_loop->exec();
|
||||
QEventLoop loop;
|
||||
QObject::connect(this, &UTPassphraseProvider::unlockEventLoop, &loop, &QEventLoop::quit);
|
||||
loop.exec();
|
||||
|
||||
qDebug() << "Prepare Returns";
|
||||
char *ret;
|
||||
gpgrt_asprintf(&ret, "%s", m_passphrase);
|
||||
canceled = m_canceled;
|
||||
canceled = this->m_canceled;
|
||||
|
||||
qDebug() << "Clean";
|
||||
if (m_passphrase)
|
||||
if (this->m_passphrase)
|
||||
{
|
||||
free(m_passphrase);
|
||||
}
|
||||
m_canceled = false;
|
||||
m_sem->release(1);
|
||||
this->m_canceled = false;
|
||||
this->m_sem->release(1);
|
||||
return ret;
|
||||
};
|
||||
};
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: utpass.qrouland\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"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -17,10 +17,6 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: ../qml/components/FileDir.qml:59
|
||||
msgid "Decryption failed !"
|
||||
msgstr ""
|
||||
|
||||
#: ../qml/dialogs/ErrorDialog.qml:12
|
||||
msgid "Error !"
|
||||
msgstr ""
|
||||
@ -83,21 +79,25 @@ msgstr ""
|
||||
msgid "Info"
|
||||
msgstr ""
|
||||
|
||||
#: ../qml/pages/PasswordList.qml:22
|
||||
#: ../qml/pages/PasswordList.qml:37
|
||||
msgid ""
|
||||
"No password found<br>You can import a password store by cloning or importing "
|
||||
"a zip in the settings"
|
||||
msgstr ""
|
||||
|
||||
#: ../qml/pages/PasswordList.qml:61
|
||||
#: ../qml/pages/PasswordList.qml:76
|
||||
msgid "Back"
|
||||
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
|
||||
msgid "UTPass"
|
||||
msgstr ""
|
||||
|
||||
#: ../qml/pages/PasswordList.qml:96
|
||||
msgid "Decryption failed !"
|
||||
msgstr ""
|
||||
|
||||
#: ../qml/pages/headers/MainHeader.qml:26 ../qml/pages/settings/Settings.qml:70
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
38
qml/Main.qml
38
qml/Main.qml
@ -10,8 +10,6 @@ MainView {
|
||||
|
||||
id: root
|
||||
|
||||
signal responsePassphraseDialog(bool canceled, string passphrase)
|
||||
|
||||
function initPass(rootView) {
|
||||
Pass.initialize(rootView);
|
||||
pageStack.push(Qt.resolvedUrl("pages/PasswordList.qml"));
|
||||
@ -19,30 +17,36 @@ MainView {
|
||||
|
||||
function callPassphraseDialog(useridHint, description, previousWasBad) {
|
||||
//TODO use parameters to impove passphrase dialog
|
||||
var passphraseDialog = PopupUtils.open(Qt.resolvedUrl("dialogs/PassphraseDialog.qml"));
|
||||
passphraseDialog.activateFocus();
|
||||
var validated = function validated(passphrase) {
|
||||
responsePassphraseDialog(false, passphrase);
|
||||
};
|
||||
var canceled = function canceled() {
|
||||
responsePassphraseDialog(true, "");
|
||||
};
|
||||
passphraseDialog.validated.connect(validated);
|
||||
passphraseDialog.canceled.connect(canceled);
|
||||
var pop = PopupUtils.open(passphraseDialog);
|
||||
pop.activateFocus();
|
||||
}
|
||||
|
||||
objectName: "mainView"
|
||||
applicationName: "utpass.qrouland"
|
||||
automaticOrientation: false
|
||||
width: units.gu(48)
|
||||
height: units.gu(80)
|
||||
automaticOrientation: true
|
||||
|
||||
width: units.gu(45)
|
||||
height: units.gu(75)
|
||||
|
||||
PageStack {
|
||||
id: pageStack
|
||||
|
||||
anchors.fill: parent
|
||||
Component.onCompleted: {
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: passphraseDialog
|
||||
|
||||
PassphraseDialog {
|
||||
onValidated: {
|
||||
console.info("valided");
|
||||
Pass.responsePassphraseDialog(false, passphrase);
|
||||
}
|
||||
onCanceled: {
|
||||
console.info("canceled");
|
||||
Pass.responsePassphraseDialog(true, "");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -33,12 +33,14 @@ Component {
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
var path = folderModel.folder + "/" + fileName;
|
||||
if (fileIsDir) {
|
||||
folderModel.folder = folderModel.folder + "/" + fileName;
|
||||
folderModel.folder = path;
|
||||
backAction.visible = true;
|
||||
passwordListHeader.title = fileName;
|
||||
} else {
|
||||
Pass.show(folderModel.folder + "/" + fileName);
|
||||
console.debug("pass show %1".arg(path))
|
||||
Pass.show(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -52,15 +54,6 @@ Component {
|
||||
borderColor: LomiriColors.warmGrey
|
||||
}
|
||||
|
||||
Component {
|
||||
id: passwordPageDecryptError
|
||||
|
||||
ErrorDialog {
|
||||
textError: i18n.tr("Decryption failed !")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -49,11 +49,11 @@ Page {
|
||||
iconName: "back"
|
||||
text: "Back"
|
||||
onTriggered: {
|
||||
// passwordPage.plainText = "";
|
||||
// for (var object in objects) {
|
||||
// object.text = "";
|
||||
// object.destroy();
|
||||
// }
|
||||
passwordPage.plainText = null;
|
||||
for (var object in objects) {
|
||||
object.text = null;
|
||||
object.destroy();
|
||||
}
|
||||
pageStack.pop();
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
import "headers"
|
||||
import "../components"
|
||||
import "../dialogs"
|
||||
import Lomiri.Components 1.3
|
||||
import Pass 1.0
|
||||
import Qt.labs.folderlistmodel 2.1
|
||||
import QtQuick 2.4
|
||||
import "headers"
|
||||
import Lomiri.Components.Popups 1.3
|
||||
|
||||
Page {
|
||||
id: passwordListPage
|
||||
@ -13,13 +15,13 @@ Page {
|
||||
anchors.fill: parent
|
||||
Component.onCompleted: {
|
||||
passwordStorePath = "file:" + Pass.password_store;
|
||||
Pass.onDecrypted.connect(function(filename, text) {
|
||||
Pass.onShowSucceed.connect(function(filename, text) {
|
||||
pageStack.push(Qt.resolvedUrl("../pages/Password.qml"), {
|
||||
"plainText": text,
|
||||
"title": filename
|
||||
});
|
||||
});
|
||||
Pass.onDecryptFailed.connect(function() {
|
||||
Pass.onShowFailed.connect(function(message) {
|
||||
PopupUtils.open(passwordPageDecryptError);
|
||||
});
|
||||
}
|
||||
@ -87,4 +89,13 @@ Page {
|
||||
]
|
||||
}
|
||||
|
||||
Component {
|
||||
id: passwordPageDecryptError
|
||||
|
||||
ErrorDialog {
|
||||
textError: i18n.tr("Decryption failed !")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user