mirror of
https://github.com/QRouland/UTPass.git
synced 2025-06-25 23:12:28 +00:00
Initial Commit : 0.0.1
This commit is contained in:
2
plugins/CMakeLists.txt
Normal file
2
plugins/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
||||
add_subdirectory(Pass)
|
||||
add_subdirectory(Utils)
|
54
plugins/Pass/CMakeLists.txt
Normal file
54
plugins/Pass/CMakeLists.txt
Normal file
@ -0,0 +1,54 @@
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
set(PLUGIN "Pass")
|
||||
|
||||
set(
|
||||
SRC
|
||||
plugin.cpp
|
||||
pass.cpp
|
||||
gpg.cpp
|
||||
passkeymodel.h
|
||||
passphraseprovider.h
|
||||
)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
||||
execute_process(
|
||||
COMMAND dpkg-architecture -qDEB_HOST_MULTIARCH
|
||||
OUTPUT_VARIABLE ARCH_TRIPLET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
if(ARCH_TRIPLET STREQUAL "")
|
||||
set(ARCH_TRIPLET x86_64-linux-gnu)
|
||||
endif()
|
||||
|
||||
add_library(${PLUGIN} MODULE ${SRC})
|
||||
set_target_properties(${PLUGIN} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGIN})
|
||||
qt5_use_modules(${PLUGIN} Qml Quick DBus)
|
||||
|
||||
set(EXTERNAL_LIBS "${CMAKE_SOURCE_DIR}/build/${ARCH_TRIPLET}/gpg/local/")
|
||||
|
||||
INCLUDE_DIRECTORIES(${EXTERNAL_LIBS}/include)
|
||||
|
||||
add_library(GpgError STATIC IMPORTED)
|
||||
set_property(TARGET GpgError PROPERTY IMPORTED_LOCATION "${EXTERNAL_LIBS}/lib/libgpg-error.a")
|
||||
|
||||
add_library(GpgAssuan STATIC IMPORTED)
|
||||
set_property(TARGET GpgAssuan PROPERTY IMPORTED_LOCATION "${EXTERNAL_LIBS}/lib/libassuan.a")
|
||||
|
||||
add_library(Gpgme STATIC IMPORTED)
|
||||
set_property(TARGET Gpgme PROPERTY IMPORTED_LOCATION "${EXTERNAL_LIBS}/lib/libgpgme.a")
|
||||
|
||||
add_library(Gpgmepp STATIC IMPORTED)
|
||||
set_property(TARGET Gpgmepp PROPERTY IMPORTED_LOCATION "${EXTERNAL_LIBS}/lib/libgpgmepp.a")
|
||||
|
||||
add_library(QGpgme STATIC IMPORTED)
|
||||
set_property(TARGET QGpgme PROPERTY IMPORTED_LOCATION "${EXTERNAL_LIBS}/lib/libqgpgme.a")
|
||||
|
||||
target_link_libraries(${PLUGIN} QGpgme Gpgmepp Gpgme GpgAssuan GpgError)
|
||||
|
||||
|
||||
set(QT_IMPORTS_DIR "/lib/${ARCH_TRIPLET}")
|
||||
|
||||
install(TARGETS ${PLUGIN} DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN}/)
|
||||
install(FILES qmldir DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN}/)
|
270
plugins/Pass/gpg.cpp
Normal file
270
plugins/Pass/gpg.cpp
Normal file
@ -0,0 +1,270 @@
|
||||
#include <memory>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QtCore/QStandardPaths>
|
||||
|
||||
|
||||
#include <gpgme.h>
|
||||
#include <gpgme++/data.h>
|
||||
#include <gpgme++/global.h>
|
||||
#include <gpgme++/context.h>
|
||||
#include <gpgme++/engineinfo.h>
|
||||
#include <gpgme++/keylistresult.h>
|
||||
#include <gpgme++/importresult.h>
|
||||
#include <gpgme++/encryptionresult.h>
|
||||
#include <gpgme++/decryptionresult.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>
|
||||
|
||||
#include "gpg.h"
|
||||
#include "pass.h"
|
||||
#include "passphraseprovider.h"
|
||||
|
||||
|
||||
|
||||
|
||||
using namespace GpgME;
|
||||
using namespace QGpgME;
|
||||
|
||||
Gpg::Gpg()
|
||||
{
|
||||
m_window = nullptr;
|
||||
|
||||
initializeLibrary();
|
||||
|
||||
Gpg::initGpgConfig();
|
||||
|
||||
auto error = checkEngine(OpenPGP);
|
||||
if (error) {
|
||||
qDebug() << "Code Error : " << error.code();
|
||||
qDebug() << "Error str : " << error.asString();
|
||||
qFatal("GNUPG Engine check Fail");
|
||||
}
|
||||
|
||||
qDebug() << "GNUPG Engine Version is :" << engineInfo(OpenPGP).version();
|
||||
qDebug() << "GNUPG Executable is :" << engineInfo(OpenPGP).fileName();
|
||||
qDebug() << "GNUPG Home is :" << engineInfo(OpenPGP).homeDirectory();
|
||||
}
|
||||
|
||||
|
||||
QString Gpg::initGpgHome()
|
||||
{
|
||||
QString path = QStandardPaths::writableLocation(
|
||||
QStandardPaths::AppDataLocation).append("/.gpghome");
|
||||
QDir dir(path);
|
||||
if (!dir.exists()) {
|
||||
dir.mkpath(".");
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
QString Gpg::initGpgExec()
|
||||
{
|
||||
QString path = QDir::currentPath().append("/lib/bin/gpg");
|
||||
QFileInfo file(path);
|
||||
if (!file.isFile()) {
|
||||
qFatal("GNUPGEXEC file not found !");
|
||||
}
|
||||
if (!file.isExecutable()) {
|
||||
qFatal("GNUPGEXEC file not executable !");
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
void Gpg::initGpgConfig()
|
||||
{
|
||||
auto home = initGpgHome();
|
||||
auto exec = initGpgExec();
|
||||
|
||||
QFile agentConf(home + QStringLiteral("/gpg-agent.conf"));
|
||||
agentConf.remove();
|
||||
agentConf.open(QIODevice::WriteOnly);
|
||||
agentConf.write("allow-loopback-pinentry");
|
||||
agentConf.close();
|
||||
|
||||
gpgme_set_engine_info (
|
||||
GPGME_PROTOCOL_OpenPGP,
|
||||
exec.toLocal8Bit().data(),
|
||||
home.toLocal8Bit().data()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
QPair<Error, QString> Gpg::decrypt(QByteArray cipherText)
|
||||
{
|
||||
auto job = openpgp()->decryptJob();
|
||||
auto ctx = DecryptJob::context(job);
|
||||
|
||||
auto provider = new UTPassphraseProvider;
|
||||
ctx->setPassphraseProvider(provider);
|
||||
ctx->setPinentryMode(Context::PinentryLoopback);
|
||||
|
||||
QByteArray plain_text;
|
||||
auto decResult = job->exec(cipherText, plain_text);
|
||||
|
||||
delete job;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
QPair<Error, QString> 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());;
|
||||
}
|
||||
QByteArray cipherText = file.readAll();
|
||||
file.close();
|
||||
return decrypt(cipherText);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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, std::vector< GpgME::Key >> 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,
|
||||
bool validate)
|
||||
{
|
||||
qDebug() << "Getting the keys " << pattern_uid;
|
||||
auto job = std::unique_ptr<KeyListJob>(openpgp()->keyListJob(remote, include_sigs, validate));
|
||||
|
||||
std::vector<Key> keys;
|
||||
auto result = job->exec(QStringList() << pattern_uid, false, keys);
|
||||
|
||||
qDebug() << "Got the keys " << pattern_uid;
|
||||
return QPair<Error, std::vector< Key >>(result.error(), keys);
|
||||
}
|
||||
|
||||
|
||||
QPair<Error, Key> Gpg::getKey(QString uid, bool remote, bool include_sigs, bool validate)
|
||||
{
|
||||
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);
|
||||
}
|
||||
qDebug() << "Got the key " << uid;
|
||||
return QPair<Error, Key>(keys.first, keys.second.front());
|
||||
}
|
||||
|
||||
|
||||
Error Gpg::importKeysFromFile(QString path)
|
||||
{
|
||||
qDebug() << "Importing the key file" << path;
|
||||
qDebug() << "Decrypt from " << path;
|
||||
QFile file(path);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
qWarning() << "Can't open the File";
|
||||
return Error();
|
||||
}
|
||||
|
||||
auto job = openpgp()->importJob();
|
||||
auto ctx = ImportJob::context(job);
|
||||
|
||||
auto provider = new UTPassphraseProvider;
|
||||
ctx->setPassphraseProvider(provider);
|
||||
ctx->setPinentryMode(Context::PinentryLoopback);
|
||||
auto result = job->exec(file.readAll());
|
||||
|
||||
qDebug() << "numImported" << result.numImported();
|
||||
qDebug() << "numSecretKeysImported" << result.numSecretKeysImported();
|
||||
qDebug() << "numSecretKeysConsidered" << result.numSecretKeysConsidered();
|
||||
qDebug() << "numSecretKeysUnchanged" << result.numSecretKeysUnchanged();
|
||||
qDebug() << "numUnchanged" << result.numUnchanged();
|
||||
|
||||
file.close();
|
||||
delete job;
|
||||
delete provider;
|
||||
|
||||
if (result.error()) {
|
||||
qWarning() << "Import go wrong";
|
||||
qDebug() << "Code Error : " << result.error().code();
|
||||
qDebug() << "Error str : " << result.error().asString();
|
||||
}
|
||||
qDebug() << "Imported the key file" << path;
|
||||
return result.error();
|
||||
}
|
||||
|
||||
Error Gpg::deleteKeyId(QString uid)
|
||||
{
|
||||
qDebug() << "Deleting key id " << uid;
|
||||
auto key = getKey(uid);
|
||||
|
||||
if (key.first) {
|
||||
return key.first;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
61
plugins/Pass/gpg.h
Normal file
61
plugins/Pass/gpg.h
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef GPG_H
|
||||
#define GPG_H
|
||||
|
||||
#include <memory>
|
||||
#include <QQuickWindow>
|
||||
#include <gpgme++/context.h>
|
||||
#include <qgpgme/changeownertrustjob.h>
|
||||
|
||||
|
||||
using namespace GpgME;
|
||||
|
||||
class Gpg
|
||||
{
|
||||
private:
|
||||
Gpg();
|
||||
QObject *m_window;
|
||||
|
||||
QString initGpgHome();
|
||||
QString initGpgExec();
|
||||
void initGpgConfig();
|
||||
|
||||
public:
|
||||
~Gpg();
|
||||
|
||||
static std::shared_ptr<Gpg> instance()
|
||||
{
|
||||
static std::shared_ptr<Gpg> s{new Gpg};
|
||||
return s;
|
||||
}
|
||||
Gpg(Gpg const &) = delete;
|
||||
void operator=(Gpg const &) = delete;
|
||||
|
||||
void setWindow(QObject *window)
|
||||
{
|
||||
m_window = window;
|
||||
};
|
||||
|
||||
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
|
66
plugins/Pass/pass.cpp
Normal file
66
plugins/Pass/pass.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
#include <QUrl>
|
||||
#include <QtCore/QStandardPaths>
|
||||
#include <QtCore/QDir>
|
||||
|
||||
#include "pass.h"
|
||||
#include "gpg.h"
|
||||
#include "passphraseprovider.h"
|
||||
#include "passkeymodel.h"
|
||||
|
||||
|
||||
|
||||
Pass::Pass(): m_password_store (QStandardPaths::writableLocation(
|
||||
QStandardPaths::AppDataLocation).append("/.password-store"))
|
||||
{}
|
||||
|
||||
void Pass::init(QObject *window)
|
||||
{
|
||||
if (!window) {
|
||||
qFatal("window is invalid. Abording.");
|
||||
}
|
||||
Gpg::instance()->setWindow(window);
|
||||
|
||||
QDir dir(m_password_store);
|
||||
if (!dir.exists())
|
||||
dir.mkpath(".");
|
||||
qDebug() << "Password Store is :" << m_password_store;
|
||||
}
|
||||
|
||||
void Pass::decrypt(QUrl url)
|
||||
{
|
||||
qDebug() << "Start decrypting";
|
||||
auto decrypt_ret = Gpg::instance()->decryptFromFile(url.toLocalFile());
|
||||
if (decrypt_ret.first) {
|
||||
qDebug() << "Decrypt Failed";
|
||||
emit decryptFailed();
|
||||
} else if (decrypt_ret.second.isNull()) {
|
||||
qDebug() << "Decrypt Canceled";
|
||||
emit decryptCanceled();
|
||||
} else {
|
||||
qDebug() << "Decrypt OK";
|
||||
emit decrypted(decrypt_ret.second);
|
||||
}
|
||||
}
|
||||
|
||||
bool Pass::gpgDeleteKeyId(QString id)
|
||||
{
|
||||
qDebug() << "Start deleting Key id " << id;
|
||||
return !Gpg::instance()->deleteKeyId(id);
|
||||
}
|
||||
|
||||
bool Pass::gpgImportKeyFromFile(QUrl url)
|
||||
{
|
||||
qDebug() << "Start importing Key from " << url;
|
||||
return !Gpg::instance()->importKeysFromFile(url.toLocalFile());
|
||||
}
|
||||
|
||||
QVariant Pass::gpgGetAllKeysModel()
|
||||
{
|
||||
return QVariant::fromValue(PassKeyModel::keysToPassKeyQObjectList(
|
||||
Gpg::instance()->getAllKeys().second));
|
||||
}
|
||||
|
||||
QString Pass::getPasswordStore()
|
||||
{
|
||||
return m_password_store;
|
||||
}
|
32
plugins/Pass/pass.h
Normal file
32
plugins/Pass/pass.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef PASS_H
|
||||
#define PASS_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
#include <QVariant>
|
||||
|
||||
|
||||
class Pass : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QString m_password_store;
|
||||
|
||||
signals:
|
||||
void decrypted(QString text);
|
||||
void decryptCanceled();
|
||||
void decryptFailed();
|
||||
|
||||
|
||||
public:
|
||||
Pass();
|
||||
~Pass() override = default;
|
||||
|
||||
Q_INVOKABLE void init(QObject *window);
|
||||
Q_INVOKABLE QString getPasswordStore();
|
||||
Q_INVOKABLE void decrypt(QUrl url);
|
||||
Q_INVOKABLE bool gpgDeleteKeyId(QString id);
|
||||
Q_INVOKABLE bool gpgImportKeyFromFile(QUrl url);
|
||||
Q_INVOKABLE QVariant gpgGetAllKeysModel();
|
||||
};
|
||||
|
||||
#endif
|
74
plugins/Pass/passkeymodel.h
Normal file
74
plugins/Pass/passkeymodel.h
Normal file
@ -0,0 +1,74 @@
|
||||
#ifndef PASSKEYMODEL_H
|
||||
#define PASSKEYMODEL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <gpgme++/key.h>
|
||||
|
||||
using namespace GpgME;
|
||||
|
||||
class PassKeyModel : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString uid READ uid WRITE setUid NOTIFY uidChanged MEMBER m_uid)
|
||||
Q_PROPERTY(bool secret READ secret WRITE setSecret NOTIFY secretChanged MEMBER m_secret)
|
||||
Q_PROPERTY(bool expired READ expired WRITE setExpired NOTIFY expiredChanged MEMBER m_expired)
|
||||
|
||||
QString m_uid;
|
||||
bool m_secret;
|
||||
bool m_expired;
|
||||
|
||||
public:
|
||||
PassKeyModel(QString uid, bool secret, bool expired):
|
||||
m_uid(uid),
|
||||
m_secret(secret),
|
||||
m_expired(expired)
|
||||
{};
|
||||
|
||||
PassKeyModel(Key key):
|
||||
PassKeyModel(QString::fromUtf8(key.keyID()), key.hasSecret(), key.isExpired())
|
||||
{};
|
||||
|
||||
static QList<QObject *> keysToPassKeyQObjectList(std::vector<Key> keys)
|
||||
{
|
||||
QList<QObject *> r;
|
||||
std::for_each(keys.begin(), keys.end(), [&r](Key k) {
|
||||
r.append(new PassKeyModel(k));
|
||||
});
|
||||
return r;
|
||||
};
|
||||
|
||||
QString uid() const
|
||||
{
|
||||
return m_uid;
|
||||
};
|
||||
bool secret() const
|
||||
{
|
||||
return m_secret;
|
||||
};
|
||||
bool expired() const
|
||||
{
|
||||
return m_expired;
|
||||
};
|
||||
|
||||
void setUid(QString uid)
|
||||
{
|
||||
m_uid = uid;
|
||||
emit uidChanged(uid);
|
||||
}
|
||||
void setSecret(bool secret)
|
||||
{
|
||||
m_secret = secret;
|
||||
emit secretChanged(secret);
|
||||
}
|
||||
void setExpired(bool expired)
|
||||
{
|
||||
m_expired = expired;
|
||||
emit expiredChanged(expired);
|
||||
}
|
||||
|
||||
signals:
|
||||
void uidChanged(QString);
|
||||
void secretChanged(bool);
|
||||
void expiredChanged(bool);
|
||||
};
|
||||
#endif
|
88
plugins/Pass/passphraseprovider.h
Normal file
88
plugins/Pass/passphraseprovider.h
Normal file
@ -0,0 +1,88 @@
|
||||
#ifndef UTPASSPHRASEPROVIDER_H
|
||||
#define UTPASSPHRASEPROVIDER_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <QObject>
|
||||
#include <QQmlProperty>
|
||||
#include <QEventLoop>
|
||||
#include <QSemaphore>
|
||||
#include <gpgme++/interfaces/passphraseprovider.h>
|
||||
#include "passphraseprovider.h"
|
||||
#include "gpg.h"
|
||||
|
||||
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
UTPassphraseProvider():
|
||||
m_loop(std::unique_ptr<QEventLoop>(new QEventLoop)),
|
||||
m_sem(std::unique_ptr<QSemaphore>(new QSemaphore(1))),
|
||||
m_passphrase(nullptr),
|
||||
m_canceled(false)
|
||||
{}
|
||||
|
||||
char *getPassphrase( const char *useridHint,
|
||||
const char *description,
|
||||
bool previousWasBad,
|
||||
bool &canceled ) Q_DECL_OVERRIDE {
|
||||
if (!m_sem->tryAcquire(1, 3000))
|
||||
{
|
||||
qWarning() << "Cannot acquire UTPassphraseProvider semaphore.";
|
||||
canceled = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_passphrase = nullptr;
|
||||
m_canceled = false;
|
||||
|
||||
qDebug() << "Call the QML Dialog Passphrase Provider";
|
||||
QMetaObject::invokeMethod(
|
||||
Gpg::instance()->getWindow(), "callPassphraseDialog",
|
||||
Q_ARG(QVariant, useridHint),
|
||||
Q_ARG(QVariant, description),
|
||||
Q_ARG(QVariant, previousWasBad)
|
||||
);
|
||||
|
||||
qDebug() << "Waiting for response";
|
||||
|
||||
QObject::connect(
|
||||
Gpg::instance()->getWindow(), SIGNAL(responsePassphraseDialog(bool, QString)),
|
||||
this, SLOT(handleResponse(bool, QString))
|
||||
);
|
||||
m_loop->exec();
|
||||
|
||||
qDebug() << "Prepare Returns";
|
||||
char *ret;
|
||||
gpgrt_asprintf(&ret, "%s", m_passphrase);
|
||||
canceled = m_canceled;
|
||||
|
||||
qDebug() << "Clean";
|
||||
if (m_passphrase)
|
||||
{
|
||||
free(m_passphrase);
|
||||
}
|
||||
m_canceled = false;
|
||||
m_sem->release(1);
|
||||
return ret;
|
||||
};
|
||||
};
|
||||
#endif
|
10
plugins/Pass/plugin.cpp
Normal file
10
plugins/Pass/plugin.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include <QtQml>
|
||||
|
||||
#include "plugin.h"
|
||||
#include "pass.h"
|
||||
|
||||
void PassPlugin::registerTypes(const char *uri)
|
||||
{
|
||||
//@uri Pass
|
||||
qmlRegisterSingletonType<Pass>(uri, 1, 0, "Pass", [](QQmlEngine *, QJSEngine *) -> QObject * { return new Pass; });
|
||||
}
|
16
plugins/Pass/plugin.h
Normal file
16
plugins/Pass/plugin.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef PASSPLUGIN_H
|
||||
#define PASSPLUGIN_H
|
||||
|
||||
#include <QQmlExtensionPlugin>
|
||||
|
||||
class PassPlugin : public QQmlExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID
|
||||
"org.qt-project.Qt.QQmlExtensionInterface")
|
||||
|
||||
public:
|
||||
void registerTypes(const char *uri) override;
|
||||
};
|
||||
|
||||
#endif
|
2
plugins/Pass/qmldir
Normal file
2
plugins/Pass/qmldir
Normal file
@ -0,0 +1,2 @@
|
||||
module Pass
|
||||
plugin Pass
|
39
plugins/Utils/CMakeLists.txt
Normal file
39
plugins/Utils/CMakeLists.txt
Normal file
@ -0,0 +1,39 @@
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
set(PLUGIN "Utils")
|
||||
|
||||
set(
|
||||
SRC
|
||||
plugin.cpp
|
||||
utils.cpp
|
||||
)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
||||
execute_process(
|
||||
COMMAND dpkg-architecture -qDEB_HOST_MULTIARCH
|
||||
OUTPUT_VARIABLE ARCH_TRIPLET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
if(ARCH_TRIPLET STREQUAL "")
|
||||
set(ARCH_TRIPLET x86_64-linux-gnu)
|
||||
endif()
|
||||
|
||||
add_library(${PLUGIN} MODULE ${SRC})
|
||||
set_target_properties(${PLUGIN} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGIN})
|
||||
qt5_use_modules(${PLUGIN} Qml Quick DBus)
|
||||
|
||||
set(EXTERNAL_LIBS "${CMAKE_SOURCE_DIR}/build/${ARCH_TRIPLET}/quazip/install/")
|
||||
|
||||
INCLUDE_DIRECTORIES(${EXTERNAL_LIBS}/include)
|
||||
|
||||
add_library(quazip STATIC IMPORTED)
|
||||
set_property(TARGET quazip PROPERTY IMPORTED_LOCATION "${EXTERNAL_LIBS}/lib/libquazip5.a")
|
||||
|
||||
target_link_libraries(${PLUGIN} quazip)
|
||||
|
||||
|
||||
set(QT_IMPORTS_DIR "/lib/${ARCH_TRIPLET}")
|
||||
|
||||
install(TARGETS ${PLUGIN} DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN}/)
|
||||
install(FILES qmldir DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN}/)
|
10
plugins/Utils/plugin.cpp
Normal file
10
plugins/Utils/plugin.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include <QtQml>
|
||||
|
||||
#include "plugin.h"
|
||||
#include "utils.h"
|
||||
|
||||
void UtilsPlugin::registerTypes(const char *uri)
|
||||
{
|
||||
//@uri Utils
|
||||
qmlRegisterSingletonType<Utils>(uri, 1, 0, "Utils", [](QQmlEngine *, QJSEngine *) -> QObject * { return new Utils; });
|
||||
}
|
16
plugins/Utils/plugin.h
Normal file
16
plugins/Utils/plugin.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef UTILSPLUGIN_H
|
||||
#define UTILSPLUGIN_H
|
||||
|
||||
#include <QQmlExtensionPlugin>
|
||||
|
||||
class UtilsPlugin : public QQmlExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID
|
||||
"org.qt-project.Qt.QQmlExtensionInterface")
|
||||
|
||||
public:
|
||||
void registerTypes(const char *uri) override;
|
||||
};
|
||||
|
||||
#endif
|
2
plugins/Utils/qmldir
Normal file
2
plugins/Utils/qmldir
Normal file
@ -0,0 +1,2 @@
|
||||
module Utils
|
||||
plugin Utils
|
62
plugins/Utils/utils.cpp
Normal file
62
plugins/Utils/utils.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QUrl>
|
||||
#include <QtCore/QStandardPaths>
|
||||
#include <quazip5/JlCompress.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
Utils::Utils() {};
|
||||
|
||||
bool Utils::unzip(QUrl zip_url, QString dir_out_path)
|
||||
{
|
||||
auto tmp_dir_path = QStandardPaths::writableLocation(
|
||||
QStandardPaths::CacheLocation).append("/unzip");
|
||||
|
||||
QDir tmp_dir(tmp_dir_path);
|
||||
tmp_dir.removeRecursively();
|
||||
tmp_dir.mkpath(".");
|
||||
|
||||
qDebug() << "Temp dir path is " << tmp_dir_path;
|
||||
auto status = !JlCompress::extractDir(
|
||||
zip_url.toLocalFile(),
|
||||
tmp_dir_path
|
||||
).isEmpty();
|
||||
|
||||
if (!status) {
|
||||
tmp_dir.removeRecursively();
|
||||
return false;
|
||||
}
|
||||
|
||||
qDebug() << "Guessing if it should remove a single root folder";
|
||||
QStringList files_in_tmp_dir = tmp_dir.entryList(QDir::AllEntries | QDir::Hidden |
|
||||
QDir::NoDotAndDotDot);
|
||||
|
||||
auto dir_import_path =
|
||||
files_in_tmp_dir.length() == 1 ?
|
||||
tmp_dir_path.append("/" + files_in_tmp_dir.first()) : tmp_dir_path;
|
||||
qDebug() << "Final imported tmp path dir is " << dir_import_path;
|
||||
|
||||
qDebug() << "Removing destination";
|
||||
QDir dir_out(dir_out_path);
|
||||
dir_out.removeRecursively();
|
||||
|
||||
qDebug() << "Moving zip content to destination";
|
||||
QDir dir;
|
||||
qDebug() << dir_import_path << " to " << dir_out_path;
|
||||
auto ret = dir.rename(dir_import_path, dir_out_path);
|
||||
tmp_dir.removeRecursively();;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Utils::rmFile(QUrl file_url)
|
||||
{
|
||||
return QFile::remove(file_url.toLocalFile());
|
||||
}
|
||||
|
||||
bool Utils::rmDir(QUrl dir_url)
|
||||
{
|
||||
QDir dir(dir_url.toLocalFile());
|
||||
return dir.removeRecursively();
|
||||
}
|
21
plugins/Utils/utils.h
Normal file
21
plugins/Utils/utils.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
#include <QQuickWindow>
|
||||
|
||||
class Utils : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Utils();
|
||||
~Utils() override = default;
|
||||
|
||||
Q_INVOKABLE bool unzip(QUrl zip_url, QString dir_out);
|
||||
Q_INVOKABLE bool rmFile(QUrl file_url);
|
||||
Q_INVOKABLE bool rmDir(QUrl dir_url);
|
||||
};
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user