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:
A | src/safe.cpp | | | 122 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/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