tAdd preliminary support for safe(1) backend - sailfish-safe - Sailfish frontend for safe(1)
 (HTM) git clone git://git.z3bra.org/sailfish-safe.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit c35f952e28e75d02cd12522f7e8c1989ece5ea63
 (DIR) parent 0ed509d5f40870ea967e063d606de64104af6e15
 (HTM) Author: Willy Goiffon <contact@z3bra.org>
       Date:   Tue, 13 Jul 2021 10:26:10 +0200
       
       Add preliminary support for safe(1) backend
       
       Diffstat:
         A src/safe.cpp                        |     122 +++++++++++++++++++++++++++++++
         A src/safe.h                          |      82 +++++++++++++++++++++++++++++++
       
       2 files changed, 204 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/src/safe.cpp b/src/safe.cpp
       t@@ -0,0 +1,122 @@
       +#include "safe.h"
       +
       +#include <QStandardPaths>
       +#include <QProcess>
       +#include <QIODevice>
       +#include <QRegularExpression>
       +#include <QRegularExpressionMatch>
       +#include <QTimer>
       +#include <QtConcurrent>
       +#include <QFutureWatcher>
       +
       +namespace {
       +
       +struct SafeExecutable {
       +    SafeExecutable(const QString &path)
       +        : path(path)
       +    {}
       +    QString path = {};
       +};
       +
       +SafeExecutable findSafeExecutable()
       +{
       +    return QStandardPaths::findExecutable(QStringLiteral("safe"));
       +}
       +
       +} // namespace
       +
       +Safe::EncryptTask *Safe::encrypt(const QString &file, const QString &content)
       +{
       +    return new EncryptTask(file, content);
       +}
       +
       +Safe::DecryptTask *Safe::decrypt(const QString &file)
       +{
       +    return new DecryptTask(file);
       +}
       +
       +
       +Safe::Task::Task(QObject *parent)
       +    : QObject(parent)
       +{
       +    QTimer::singleShot(0, this, &Task::start);
       +}
       +
       +bool Safe::Task::error() const
       +{
       +    return !mError.isNull();
       +}
       +
       +QString Safe::Task::errorString() const
       +{
       +    return mError;
       +}
       +
       +void Safe::Task::setError(const QString &error)
       +{
       +    mError = error;
       +}
       +
       +void Safe::Task::start()
       +{
       +    qDebug() << "Starting task" << this;
       +    auto future = QtConcurrent::run(this, &Task::run);
       +    auto *watcher = new QFutureWatcher<void>;
       +    connect(watcher, &QFutureWatcher<void>::finished, watcher, &QObject::deleteLater);
       +    connect(watcher, &QFutureWatcher<void>::finished, this, &Safe::Task::finished);
       +    connect(watcher, &QFutureWatcher<void>::finished, this, &QObject::deleteLater);
       +    watcher->setFuture(future);
       +}
       +
       +Safe::EncryptTask::EncryptTask(const QString &file, const QString &content)
       +    : mFile(file), mContent(content)
       +{}
       +
       +void Safe::EncryptTask::run()
       +{
       +    const auto safe = findSafeExecutable();
       +    QProcess process;
       +    process.setProgram(safe.path);
       +    process.setArguments({
       +        QStringLiteral("-a"),
       +        QStringLiteral("%1").arg(mFile)
       +    });
       +    process.start();
       +    process.waitForStarted();
       +    process.write(mContent.toUtf8());
       +    process.closeWriteChannel();
       +    process.waitForFinished();
       +    if (process.exitCode() != 0) {
       +        const auto err = process.readAllStandardError();
       +        qWarning() << "Failed to encrypt data:" << err;
       +        setError(QString::fromUtf8(err));
       +    }
       +}
       +
       +Safe::DecryptTask::DecryptTask(const QString &file)
       +    : Task(), mFile(file)
       +{}
       +
       +QString Safe::DecryptTask::content() const
       +{
       +    return mContent;
       +}
       +
       +void Safe::DecryptTask::run()
       +{
       +    const auto safe = findSafeExecutable();
       +    QProcess process;
       +    process.setProgram(safe.path);
       +    process.setArguments({QStringLiteral("%1").arg(mFile)});
       +    process.start();
       +    process.waitForStarted();
       +    process.closeWriteChannel();
       +    process.waitForFinished();
       +    if (process.exitCode() != 0) {
       +        const auto err = process.readAllStandardError();
       +        qWarning() << "Failed to decrypt data:" << err;
       +        setError(QString::fromUtf8(err));
       +    } else {
       +        mContent = QString::fromUtf8(process.readAllStandardOutput());
       +    }
       +}
 (DIR) diff --git a/src/safe.h b/src/safe.h
       t@@ -0,0 +1,82 @@
       +#ifndef SAFE_H
       +#define SAFE_H
       +
       +#include <QObject>
       +#include <QVector>
       +
       +namespace Safe
       +{
       +class DecryptTask;
       +class EncryptTask;
       +
       +struct Key {
       +    enum class Trust {
       +        Unknown = 1,
       +        Never = 2,
       +        Marginal = 3,
       +        Full = 4,
       +        Ultimate = 5
       +    };
       +
       +    QString id;
       +};
       +
       +DecryptTask *decrypt(const QString &file);
       +EncryptTask *encrypt(const QString &data, const QString &file);
       +
       +
       +class Task : public QObject {
       +    Q_OBJECT
       +public:
       +    bool error() const;
       +    QString errorString() const;
       +
       +Q_SIGNALS:
       +    void finished();
       +
       +protected:
       +    explicit Task(QObject *parent = nullptr);
       +
       +    virtual void run() = 0;
       +
       +    void setError(const QString &error);
       +
       +private Q_SLOTS:
       +    void start();
       +
       +private:
       +    QString mError;
       +};
       +
       +class DecryptTask : public Task {
       +    Q_OBJECT
       +    friend DecryptTask *Safe::decrypt(const QString &);
       +public:
       +    QString content() const;
       +
       +protected:
       +    void run() override;
       +
       +private:
       +    DecryptTask(const QString &file);
       +
       +    QString mFile;
       +    QString mContent;
       +};
       +
       +class EncryptTask : public Task {
       +    Q_OBJECT
       +    friend EncryptTask *Safe::encrypt(const QString &, const QString &);
       +protected:
       +    void run() override;
       +
       +private:
       +    EncryptTask(const QString &file, const QString &content);
       +
       +    QString mFile;
       +    QString mContent;
       +};
       +
       +} // namespace Safe
       +
       +#endif // SAFE_H