sailfish-safe

Sailfish frontend for safe(1)
git clone git://git.z3bra.org/sailfish-safe.git
Log | Files | Refs | README | LICENSE

commit c35f952e28e75d02cd12522f7e8c1989ece5ea63
parent 0ed509d5f40870ea967e063d606de64104af6e15
Author: Willy Goiffon <contact@z3bra.org>
Date:   Tue, 13 Jul 2021 10:26:10 +0200

Add preliminary support for safe(1) backend

Diffstat:
Asrc/safe.cpp | 122+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/safe.h | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 204 insertions(+), 0 deletions(-)

diff --git a/src/safe.cpp b/src/safe.cpp @@ -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()); + } +} diff --git a/src/safe.h b/src/safe.h @@ -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