From ba52ddac5cf202799cd58179b53843a5af6a16db Mon Sep 17 00:00:00 2001 From: Quentin Rouland Date: Mon, 3 Feb 2025 21:46:21 +0100 Subject: [PATCH] Complete rewrite from gpgme to rnp --- plugins/Pass/CMakeLists.txt | 7 +- plugins/Pass/jobs/decryptjob.cpp | 10 +- plugins/Pass/jobs/decryptjob.h | 3 +- plugins/Pass/jobs/deletekeyjob.cpp | 42 +++++++ plugins/Pass/jobs/deletekeyjob.h | 46 ++++++++ plugins/Pass/jobs/getkeysjob.cpp | 2 +- plugins/Pass/jobs/getkeysjob.h | 3 +- plugins/Pass/jobs/importkeyjob.cpp | 49 +++++---- plugins/Pass/jobs/importkeyjob.h | 3 +- plugins/Pass/jobs/rmjob.h | 2 - plugins/Pass/jobs/rnpjob.cpp | 53 +++++++-- plugins/Pass/jobs/rnpjob.h | 60 ++++++---- plugins/Pass/pass.cpp | 103 ++++++++++-------- plugins/Pass/pass.h | 13 +-- plugins/Pass/passkeyringmodel.h | 12 +- plugins/Pass/passphraseprovider.h | 26 ++--- po/utpass.qrouland.pot | 18 +-- qml/pages/settings/InfoKeys.qml | 22 ++-- tests/plugins/TestsUtils/passphraseprovider.h | 21 ++-- tests/units/pass/tst_show.qml | 9 +- 20 files changed, 333 insertions(+), 171 deletions(-) create mode 100644 plugins/Pass/jobs/deletekeyjob.cpp create mode 100644 plugins/Pass/jobs/deletekeyjob.h diff --git a/plugins/Pass/CMakeLists.txt b/plugins/Pass/CMakeLists.txt index 99db636..38ff285 100644 --- a/plugins/Pass/CMakeLists.txt +++ b/plugins/Pass/CMakeLists.txt @@ -7,11 +7,12 @@ set( pass.cpp passkeyringmodel.h passphraseprovider.h - jobs/rmjob.cpp - jobs/rnpjob.cpp + jobs/decryptjob.cpp + jobs/deletekeyjob.cpp jobs/getkeysjob.cpp jobs/importkeyjob.cpp - jobs/decryptjob.cpp + jobs/rmjob.cpp + jobs/rnpjob.cpp ) set(CMAKE_AUTOMOC ON) diff --git a/plugins/Pass/jobs/decryptjob.cpp b/plugins/Pass/jobs/decryptjob.cpp index f9bb293..b89179b 100644 --- a/plugins/Pass/jobs/decryptjob.cpp +++ b/plugins/Pass/jobs/decryptjob.cpp @@ -16,12 +16,13 @@ DecryptJob::DecryptJob(QDir rnp_homedir, QString path): void DecryptJob::run() { qDebug() << "[DecryptJob] Starting"; - this->load_sec_keyring(NULL); + this->loadFullKeyring(NULL); rnp_input_t input = NULL; rnp_output_t output = NULL; - uint8_t * buf = NULL; + uint8_t *buf = NULL; size_t buf_len = 0; + QString data = QString::Null(); auto ret = rnp_input_from_path(&input, this->m_encrypted_file_path.toLocal8Bit().data()); if (ret == RNP_SUCCESS) { @@ -34,14 +35,13 @@ void DecryptJob::run() ret = rnp_output_memory_get_buf(output, &buf, &buf_len, false); } if (ret == RNP_SUCCESS) { - emit resultSuccess(this->m_encrypted_file_path, QString::fromUtf8((char*)buf)); + data = QString::fromUtf8((char*)buf); } rnp_input_destroy(input); rnp_output_destroy(output); terminateOnError(ret); - - emit resultSuccess(this->m_encrypted_file_path, QString::fromUtf8((char*)buf)); + emit resultSuccess(this->m_encrypted_file_path, data); qDebug() << "[DecryptJob] Finished Successfully "; } diff --git a/plugins/Pass/jobs/decryptjob.h b/plugins/Pass/jobs/decryptjob.h index f5f5eb7..c6be2b4 100644 --- a/plugins/Pass/jobs/decryptjob.h +++ b/plugins/Pass/jobs/decryptjob.h @@ -18,8 +18,7 @@ class DecryptJob : public RnpJob * @brief Executes the decryption operation. * * This method performs the actual decryption of the encrypted file specified during - * object construction. The operation is carried out in a separate background thread - * to prevent blocking the main application thread. + * object construction. */ void run() override; diff --git a/plugins/Pass/jobs/deletekeyjob.cpp b/plugins/Pass/jobs/deletekeyjob.cpp new file mode 100644 index 0000000..784fdb8 --- /dev/null +++ b/plugins/Pass/jobs/deletekeyjob.cpp @@ -0,0 +1,42 @@ +#include +#include +#include +#include "deletekeyjob.h" + +extern "C" { +#include +#include +} + +DeleteKeyJob::DeleteKeyJob(QDir rnp_homedir, QString fingerprint): + RnpJob(rnp_homedir), + m_fingerprint(fingerprint) +{ + this->setObjectName("ImportKeyJob"); +} + + +void DeleteKeyJob::run() +{ + qDebug() << "[DeleteKeyJob] Starting"; + + // Loading keyring + this->loadFullKeyring(NULL); + + // Delete key + rnp_key_handle_t key = NULL; + auto ret = rnp_locate_key(this->m_ffi, "fingerprint", this->m_fingerprint.toLocal8Bit().data(), &key); + + if (ret == RNP_SUCCESS) { + ret = rnp_key_remove(key, RNP_KEY_REMOVE_PUBLIC | RNP_KEY_REMOVE_SECRET | RNP_KEY_REMOVE_SUBKEYS); + }; + rnp_key_handle_destroy(key); + + // Save resulting keyring + this->saveFullKeyring(); + + // Emit result + terminateOnError(ret); + emit resultSuccess(); + qDebug() << "[DeleteKeyJob] Finished Successfully "; +} diff --git a/plugins/Pass/jobs/deletekeyjob.h b/plugins/Pass/jobs/deletekeyjob.h new file mode 100644 index 0000000..ff2e3b4 --- /dev/null +++ b/plugins/Pass/jobs/deletekeyjob.h @@ -0,0 +1,46 @@ +#ifndef DELETEKEYJOB_H +#define DELETEKEYJOB_H + +#include "rnpjob.h" + +/** + * @class DeleteKeyJob + * @brief A job to handle the deletion of a key in a separate thread. + * + */ +class DeleteKeyJob : public RnpJob +{ + Q_OBJECT + + /** + * @brief Executes the key deletion operation. + * + * This function performs the actual process of deleting the GPG key from the keyring. + */ + void run() override; + +signals: + /** + * @brief Emitted when the key deletion operation is successful. + * + * This signal is emitted when the key is successfully deleted from the keyring.. + */ + void resultSuccess(); + +private: + QString m_fingerprint; /**< The fingerprint of the key to delete. */ + +public: + /** + * @brief Constructs a DeleteKeyJob object with the specified fingerprint and keyring directory. + * + * This constructor initializes the DeleteKeyJob instance with the directory containing + * the keyrings and the fingerprint of the GPG key to delete. + * + * @param rnp_homedir The directory containing the keyrings where the key will be deleted. + * @param fingerprint The fingerprint of the key to delete. + */ + DeleteKeyJob(QDir rnp_homedir, QString fingerprint); +}; + +#endif // DELETEKEYJOB_H diff --git a/plugins/Pass/jobs/getkeysjob.cpp b/plugins/Pass/jobs/getkeysjob.cpp index 9318492..06c1f28 100644 --- a/plugins/Pass/jobs/getkeysjob.cpp +++ b/plugins/Pass/jobs/getkeysjob.cpp @@ -30,7 +30,7 @@ void GetKeysJob::run() // Loading keyring QSet fingerprints = QSet(); - this->load_full_keyring(&fingerprints); + this->loadFullKeyring(&fingerprints); //Get infos keys auto key_infos = QList(); diff --git a/plugins/Pass/jobs/getkeysjob.h b/plugins/Pass/jobs/getkeysjob.h index 7ff7413..d9fac14 100644 --- a/plugins/Pass/jobs/getkeysjob.h +++ b/plugins/Pass/jobs/getkeysjob.h @@ -16,8 +16,7 @@ class GetKeysJob : public RnpJob /** * @brief Executes the process of fetching all GPG keys. * - * This function performs the task of retrieving all keys from the keyrings. It is executed - * in a separate thread to avoid blocking the main application thread. + * This function performs the task of retrieving all keys from the keyrings. */ void run() override; diff --git a/plugins/Pass/jobs/importkeyjob.cpp b/plugins/Pass/jobs/importkeyjob.cpp index 8053af8..f8bb3a9 100644 --- a/plugins/Pass/jobs/importkeyjob.cpp +++ b/plugins/Pass/jobs/importkeyjob.cpp @@ -19,6 +19,11 @@ ImportKeyJob::ImportKeyJob(QDir rnp_homedir, QString key_file_path): void ImportKeyJob::run() { qDebug() << "[ImportKeyJob] Starting"; + + // Loading keyring + this->loadFullKeyring(NULL); + + // Import new key rnp_input_t input = NULL; auto ret = rnp_input_from_path(&input, this->m_key_file_path.toLocal8Bit().constData()); if (ret == RNP_SUCCESS) { @@ -35,29 +40,33 @@ void ImportKeyJob::run() rnp_input_destroy(input); terminateOnError(ret); - rnp_output_t output = NULL; - qDebug() << "[ImportKeyJob] Writing pubring to " << this->pubringPath(); - ret = rnp_output_to_file(&output, this->pubringPath().toLocal8Bit().constData(), RNP_OUTPUT_FILE_OVERWRITE); - if (ret == RNP_SUCCESS) { - qDebug() << "[ImportKeyJob] Saving key pubring "; - ret = rnp_save_keys(this->m_ffi, RNP_KEYSTORE_GPG, output, RNP_LOAD_SAVE_PUBLIC_KEYS); + // Save resulting keyring + this->saveFullKeyring(); + // rnp_output_t output = NULL; + // qDebug() << "[ImportKeyJob] Writing pubring to " << this->pubringPath(); + // ret = rnp_output_to_file(&output, this->pubringPath().toLocal8Bit().constData(), RNP_OUTPUT_FILE_OVERWRITE); + // if (ret == RNP_SUCCESS) { + // qDebug() << "[ImportKeyJob] Saving key pubring "; + // ret = rnp_save_keys(this->m_ffi, RNP_KEYSTORE_GPG, output, RNP_LOAD_SAVE_PUBLIC_KEYS); - } - if (ret == RNP_SUCCESS) { - ret = rnp_output_finish(output); - } - rnp_output_destroy(output); - terminateOnError(ret); + // } + // if (ret == RNP_SUCCESS) { + // ret = rnp_output_finish(output); + // } + // rnp_output_destroy(output); + // terminateOnError(ret); - qDebug() << "[ImportKeyJob] Writing secring to " << this->secringPath(); - ret = rnp_output_to_file(&output, this->secringPath().toLocal8Bit().constData(), RNP_OUTPUT_FILE_OVERWRITE); - if (ret == RNP_SUCCESS) { - qDebug() << "[ImportKeyJob] Saving key secring "; - ret = rnp_save_keys(this->m_ffi, RNP_KEYSTORE_GPG, output, RNP_LOAD_SAVE_SECRET_KEYS); - } + // qDebug() << "[ImportKeyJob] Writing secring to " << this->secringPath(); + // ret = rnp_output_to_file(&output, this->secringPath().toLocal8Bit().constData(), RNP_OUTPUT_FILE_OVERWRITE); + // if (ret == RNP_SUCCESS) { + // qDebug() << "[ImportKeyJob] Saving key secring "; + // ret = rnp_save_keys(this->m_ffi, RNP_KEYSTORE_GPG, output, RNP_LOAD_SAVE_SECRET_KEYS); + // } - rnp_output_destroy(output); - terminateOnError(ret); + // rnp_output_destroy(output); + // terminateOnError(ret); + + // Emit result emit resultSuccess(); qDebug() << "[ImportKeyJob] Finished Successfully "; } diff --git a/plugins/Pass/jobs/importkeyjob.h b/plugins/Pass/jobs/importkeyjob.h index 5b7241d..75b7b7d 100644 --- a/plugins/Pass/jobs/importkeyjob.h +++ b/plugins/Pass/jobs/importkeyjob.h @@ -16,8 +16,7 @@ class ImportKeyJob : public RnpJob * @brief Executes the key import operation. * * This function handles the actual process of importing the GPG key file into the - * keyring. It is executed in a separate thread to prevent UI freezing or blocking - * of the main application thread during the import. + * keyring. */ void run() override; diff --git a/plugins/Pass/jobs/rmjob.h b/plugins/Pass/jobs/rmjob.h index 57292e3..992ce07 100644 --- a/plugins/Pass/jobs/rmjob.h +++ b/plugins/Pass/jobs/rmjob.h @@ -17,8 +17,6 @@ class RmJob : public QThread * @brief Executes the recursive remove operation. * * This method performs the recursive removal of the specified target path. - * The operation is performed in the background to prevent blocking of the main - * application thread. */ void run() override; diff --git a/plugins/Pass/jobs/rnpjob.cpp b/plugins/Pass/jobs/rnpjob.cpp index 9c440da..e170c4c 100644 --- a/plugins/Pass/jobs/rnpjob.cpp +++ b/plugins/Pass/jobs/rnpjob.cpp @@ -50,7 +50,7 @@ bool RnpJob::passProvider(rnp_ffi_t ffi, } -void RnpJob::load_key_file(QSet *result_fingerprints, const QString path, const uint32_t flags) +void RnpJob::loadKeyFile(QSet *result_fingerprints, const QString path, const uint32_t flags) { qDebug() << "[RnpJob] Load keyring at" << path; rnp_input_t input = NULL; @@ -65,7 +65,7 @@ void RnpJob::load_key_file(QSet *result_fingerprints, const QString pat } QJsonDocument json_document = QJsonDocument::fromJson(json); qDebug() << "[RnpJob] json" << json_document; - if(result_fingerprints) { + if (result_fingerprints) { foreach (const QJsonValue fingerprint, json_document.object()["keys"].toArray()) { qDebug() << "[RnpJob] Add fingerprint" << fingerprint["fingerprint"].toString(); result_fingerprints->insert(fingerprint["fingerprint"].toString()); @@ -82,18 +82,53 @@ void RnpJob::load_key_file(QSet *result_fingerprints, const QString pat } -void RnpJob::load_pub_keyring(QSet *result_fingerprints = NULL) +void RnpJob::loadPubKeyring(QSet *result_fingerprints = NULL) { - this->load_key_file(result_fingerprints, this->pubringPath(), RNP_LOAD_SAVE_PUBLIC_KEYS); + this->loadKeyFile(result_fingerprints, this->pubringPath(), RNP_LOAD_SAVE_PUBLIC_KEYS); } -void RnpJob::load_sec_keyring(QSet *result_fingerprints = NULL) +void RnpJob::loadSecKeyring(QSet *result_fingerprints = NULL) { - this->load_key_file(result_fingerprints, this->secringPath(), RNP_LOAD_SAVE_SECRET_KEYS); + this->loadKeyFile(result_fingerprints, this->secringPath(), RNP_LOAD_SAVE_SECRET_KEYS); } -void RnpJob::load_full_keyring(QSet *result_fingerprints = NULL) +void RnpJob::loadFullKeyring(QSet *result_fingerprints = NULL) { - this->load_pub_keyring(result_fingerprints); - this->load_sec_keyring(result_fingerprints); + this->loadPubKeyring(result_fingerprints); + this->loadSecKeyring(result_fingerprints); } + + +void RnpJob::saveKeyFile(const QString path, const uint32_t flags) +{ + qDebug() << "[RnpJob] Saving keyring at" << path; + rnp_output_t output = NULL; + auto ret = rnp_output_to_file(&output, path.toLocal8Bit().data(), RNP_OUTPUT_FILE_OVERWRITE); + if (ret == RNP_SUCCESS) { + qDebug() << "[ImportKeyJob] Saving key pubring "; + ret = rnp_save_keys(this->m_ffi, RNP_KEYSTORE_GPG, output, flags); + + } + if (ret == RNP_SUCCESS) { + ret = rnp_output_finish(output); + } + rnp_output_destroy(output); + terminateOnError(ret); +} + +void RnpJob::savePubKeyring() +{ + this->saveKeyFile(this->pubringPath(), RNP_LOAD_SAVE_PUBLIC_KEYS); +} + +void RnpJob::saveSecKeyring() +{ + this->saveKeyFile(this->secringPath(), RNP_LOAD_SAVE_SECRET_KEYS); +} + +void RnpJob::saveFullKeyring() +{ + this->savePubKeyring(); + this->saveSecKeyring(); +} + diff --git a/plugins/Pass/jobs/rnpjob.h b/plugins/Pass/jobs/rnpjob.h index 2818c3c..53c142e 100644 --- a/plugins/Pass/jobs/rnpjob.h +++ b/plugins/Pass/jobs/rnpjob.h @@ -16,14 +16,14 @@ if(ret != RNP_SUCCESS) { \ return; \ } \ - /** +/** * @class RnpJob * @brief A base class that manages OpenPGP-related tasks using the librnp library. * * The RnpJob class serves as an abstraction for performing OpenPGP (RNP) operations, such as * encryption, decryption, and key management, using the RNP library. */ - class RnpJob : public QThread +class RnpJob : public QThread { Q_OBJECT @@ -73,7 +73,19 @@ private: * @param path The path to the key file. * @param flags Flags specifying options for loading keys (e.g., overwrite, secret keys, etc.). */ - void load_key_file(QSet *result_fingerprints, const QString path, const uint32_t flags); + void loadKeyFile(QSet *result_fingerprints, const QString path, const uint32_t flags); + + /** + * @brief Saves keys to the keyring file in the specified directory. + * + * This method saves a keyring to a file. It allows you to specify options such as overwriting + * existing files or including secret keys. + * + * @param path The path to the keyring file where the keys should be saved. + * @param flags Flags specifying options for saving the keys (e.g., overwrite, include secret keys, etc.). + */ + void saveKeyFile(const QString path, const uint32_t flags); + protected: rnp_ffi_t m_ffi; /**< RNP FFI (Foreign Function Interface) handle, used for interacting with the RNP library. */ @@ -105,34 +117,43 @@ protected: } /** - * @brief Loads the secret keyring into the RNP system. - * - * This method loads the secret keyring file (secring.pgp) into the system, adding keys - * to the keyring based on their fingerprints. + * @brief Loads the secret keyring into RNP. * * @param result_fingerprints A set that will hold the fingerprints of the loaded secret keys. */ - void load_sec_keyring(QSet *result_fingerprints); + void loadSecKeyring(QSet *result_fingerprints); /** - * @brief Loads the public keyring into the RNP system. - * - * This method loads the public keyring file (pubring.pgp) into the system, adding keys - * to the keyring based on their fingerprints. + * @brief Loads the public keyring into RNP. * * @param result_fingerprints A set that will hold the fingerprints of the loaded public keys. */ - void load_pub_keyring(QSet *result_fingerprints); + void loadPubKeyring(QSet *result_fingerprints); /** - * @brief Loads both the public and secret keyrings into the RNP system. - * - * This method loads both the public and secret keyring files into the system, adding keys - * to the keyring based on their fingerprints. It is a combined operation for full keyring loading. + * @brief Loads both the public and secret keyrings into RNP. * * @param result_fingerprints A set that will hold the fingerprints of all loaded keys. */ - void load_full_keyring(QSet *result_fingerprints); + void loadFullKeyring(QSet *result_fingerprints); + + /** + * @brief Saves the secret keyring to the RNP homedir. + * + */ + void saveSecKeyring(); + + /** + * @brief Saves the public keyring to the RNP homedir. + * + */ + void savePubKeyring(); + + /** + * @brief Saves both the public and secret keyrings to the RNP homedir. + * + */ + void saveFullKeyring(); public: /** @@ -155,7 +176,8 @@ public: ~RnpJob(); - void setPassProvider(rnp_password_cb pass_provider_cb) { + void setPassProvider(rnp_password_cb pass_provider_cb) + { rnp_ffi_set_pass_provider(this->m_ffi, pass_provider_cb, NULL); } }; diff --git a/plugins/Pass/pass.cpp b/plugins/Pass/pass.cpp index 5bc61b3..d291c62 100644 --- a/plugins/Pass/pass.cpp +++ b/plugins/Pass/pass.cpp @@ -3,8 +3,10 @@ #include #include "jobs/decryptjob.h" +#include "jobs/deletekeyjob.h" #include "jobs/getkeysjob.h" #include "jobs/importkeyjob.h" +#include "jobs/rmjob.h" #include "pass.h" #include "passphraseprovider.h" @@ -91,57 +93,62 @@ void Pass::slotShowSucceed(QString encrypted_file_path, QString plain_text) this->m_sem->release(1); } -// bool Pass::deletePasswordStore() -// { -// if (!this->m_sem->tryAcquire(1, 500)) { -// return false; -// } -// qInfo() << "Pass delete Password Store"; -// auto job = new RmJob(this->password_store()); -// qDebug() << "Delete Password Store at " << this->password_store(); -// connect(job, &RmJob::resultReady, this, &Pass::deletePasswordStoreResult); -// connect(job, &RmJob::finished, job, &QObject::deleteLater); -// job->start(); -// return true; -// } +bool Pass::deletePasswordStore() +{ + qInfo() << "[Pass] Delete Password Store at" << this->password_store(); + if (!this->m_sem->tryAcquire(1, 500)) { + qInfo() << "[Pass] A command is already running"; + return false; + } + auto job = new RmJob(this->password_store()); + connect(job, &RmJob::resultReady, this, &Pass::slotDeletePasswordStoreResult); + connect(job, &RmJob::finished, job, &QObject::deleteLater); + job->start(); + return true; +} -// void Pass::deletePasswordStoreResult(bool err) -// { - -// qDebug() << "Pass delete Password StoreResult"; -// if (err) { //dir.removeRecursively()) { -// qInfo() << "Pass delete Password Store Failed"; -// emit deletePasswordStoreFailed("failed to delete password store"); - -// } else { -// qInfo() << "Pass delete Password Store Succeed"; -// emit deletePasswordStoreSucceed(); -// } -// this->m_sem->release(1); -// } +void Pass::slotDeletePasswordStoreResult(bool err) +{ + if (err) { + qInfo() << "[Pass] delete Password Store Failed"; + emit deletePasswordStoreFailed("failed to delete password store"); + } else { + qInfo() << "[Pass] Delete Password Store Succeed"; + emit deletePasswordStoreSucceed(); + } + this->m_sem->release(1); +} -// bool Pass::deleteGPGKey(PassKeyModel* key) -// { -// if (!this->m_sem->tryAcquire(1, 500)) { -// return false; -// } -// qInfo() << "Delete Key " << key->uid(); -// return this->m_gpg->deleteKey(key->key()); -// } +bool Pass::deleteGPGKey(PassKeyModel* key) +{ + qInfo() << "[Pass] Delete GPG key fingerprint " << key->property("keyid").toString(); + if (!this->m_sem->tryAcquire(1, 500)) { + qInfo() << "[Pass] A command is already running"; + return false; + } + auto job = new DeleteKeyJob(this->m_gpg_home, key->property("fingerprint").toString()); + QObject::connect(job, &DeleteKeyJob::resultError, this, &Pass::slotDeleteGPGKeyError); + QObject::connect(job, &DeleteKeyJob::resultSuccess, this, &Pass::slotDeleteGPGKeySucceed); + connect(job, &DeleteKeyJob::finished, job, &QObject::deleteLater); + job->start(); + return true; +} + +void Pass::slotDeleteGPGKeyError(rnp_result_t err) +{ + qInfo() << "[Pass] Delete GPG key Failed"; + emit deleteGPGKeyFailed(rnp_result_to_string(err)); + this->m_sem->release(1); +} + +void Pass::slotDeleteGPGKeySucceed() +{ + qInfo() << "[Pass] Delete GPG key Succesfull"; + emit deleteGPGKeySucceed(); + this->m_sem->release(1); +} -// void Pass::deleteGPGKeyResult(Error err) -// { -// qDebug() << "Delete Ke yResult"; -// if (err) { -// qInfo() << "Delete Key Failed"; -// emit deleteGPGKeyFailed(err.asString()); -// } else { -// qInfo() << "Delete Key Succeed"; -// emit deleteGPGKeySucceed(); -// } -// this->m_sem->release(1); -// } bool Pass::importGPGKey(QUrl url) { @@ -206,6 +213,6 @@ void Pass::slotGetAllGPGKeysSucceed(QList result) void Pass::responsePassphraseDialog(bool cancel, QString passphrase) { - qDebug() << "Propagate responsePassphraseDialog"; + qDebug() << "[Pass] Propagate responsePassphraseDialog to UTPassphraseProvider"; emit responsePassphraseDialogPropagate(cancel, passphrase); } diff --git a/plugins/Pass/pass.h b/plugins/Pass/pass.h index e047048..f86ae37 100644 --- a/plugins/Pass/pass.h +++ b/plugins/Pass/pass.h @@ -35,11 +35,9 @@ private slots: void slotShowSucceed(QString encrypted_file_path, QString plain_text); - /** - * @brief Slot to handle the result of a GPG key deletion operation. - * @param err The error that occurred during the operation. - */ - // void deleteGPGKeyResult(Error err); + void slotDeleteGPGKeyError(rnp_result_t err); + + void slotDeleteGPGKeySucceed(); /** * @brief Slot to handle the error result of a GPG key import operation. @@ -67,7 +65,7 @@ private slots: * @brief Slot to handle the result of a delete Password Store operation. * @param err True if an error occurred during the operation. */ - void deletePasswordStoreResult(bool err); + void slotDeletePasswordStoreResult(bool err); signals: // GPG-related signals @@ -146,7 +144,8 @@ signals: private: QString m_password_store; /**< The path to the password store. */ QString m_gpg_home; /**< The path to the gpg home. */ - std::unique_ptr m_keyring_model; /**< Meta data on the keyring uid, name, secrecy ... of the availble keys. */ + std::unique_ptr + m_keyring_model; /**< Meta data on the keyring uid, name, secrecy ... of the availble keys. */ rnp_password_cb m_passphrase_provider; /**< Pointer on passphrase povider for operations using secret keys. */ std::unique_ptr m_sem; /**< Semaphore for managing concurrent operations. */ diff --git a/plugins/Pass/passkeyringmodel.h b/plugins/Pass/passkeyringmodel.h index 17f768b..9a62d10 100644 --- a/plugins/Pass/passkeyringmodel.h +++ b/plugins/Pass/passkeyringmodel.h @@ -39,10 +39,10 @@ public: PassKeyModel(QJsonDocument key_info) { this->m_fingerprint = key_info["fingerprint"].toString(); - qDebug() << "fingerprint : " << this->m_fingerprint; + qDebug() << "[PassKeyModel] fingerprint : " << this->m_fingerprint; this->m_keyid = key_info["keyid"].toString(); - qDebug() << "keyid : " << this->m_keyid; + qDebug() << "[PassKeyModel] keyid : " << this->m_keyid; auto user_ids_json_array = key_info["userids"].toArray(); auto userids = QList(); @@ -50,10 +50,10 @@ public: userids.append((*i).toString()); } this->m_userids = QVariant(userids); - qDebug() << "userids : " << this->m_userids; + qDebug() << "[PassKeyModel] userids : " << this->m_userids; this->m_hasSecret = key_info["secret key"]["present"].toBool(); - qDebug() << "hasSecret : " << this->m_hasSecret; + qDebug() << "[PassKeyModel] hasSecret : " << this->m_hasSecret; } }; @@ -92,13 +92,13 @@ public: PassKeyringModel(QList key_infos) { for (auto i = key_infos.begin(), end = key_infos.end(); i != end; ++i) { - qDebug() << *i; + qDebug() << "[PassKeyringModel]" << *i; // Ignore subkeys and only add primary keys to the model. if ((*i)["primary key grip"].isUndefined()) { this->m_keys.append(new PassKeyModel(*i)); } else { - qDebug() << "Subkey info " << (*i)["keyid"].toString() << "ignored"; + qDebug() << "[PassKeyringModel] Subkey info " << (*i)["keyid"].toString() << "ignored"; } } } diff --git a/plugins/Pass/passphraseprovider.h b/plugins/Pass/passphraseprovider.h index 31fd3a2..ea00a0a 100644 --- a/plugins/Pass/passphraseprovider.h +++ b/plugins/Pass/passphraseprovider.h @@ -66,8 +66,8 @@ private: */ explicit UTPassphraseProvider(QObject * parent = nullptr) : m_sem(std::make_unique(1)), - m_passphrase(QString::Null()), - m_canceled(true) + m_passphrase(QString::Null()), + m_canceled(true) {} QObject *m_window; /**< The window object that triggers the QML dialog. */ @@ -85,7 +85,7 @@ public: * * @return The singleton instance of UTPassphraseProvider. */ - static UTPassphraseProvider& instance() + static UTPassphraseProvider &instance() { static UTPassphraseProvider instance; return instance; @@ -125,11 +125,11 @@ public: */ static bool get_pass_provider( rnp_ffi_t ffi, - void * app_ctx, - rnp_key_handle_t key, - const char * pgp_context, - char buf[], - size_t buf_len) + void *app_ctx, + rnp_key_handle_t key, + const char *pgp_context, + char buf[], + size_t buf_len) { qDebug() << "[UTPassphraseProvider] Call the getPassphrase"; @@ -138,8 +138,7 @@ public: return false; } - if (!UTPassphraseProvider::instance().m_sem->tryAcquire(1, 500)) - { + if (!UTPassphraseProvider::instance().m_sem->tryAcquire(1, 500)) { qWarning() << "[UTPassphraseProvider] Aborting : Cannot acquire UTPassphraseProvider semaphore"; return false; } @@ -153,7 +152,7 @@ public: Q_ARG(QVariant, "useridHint"), // TODO Q_ARG(QVariant, "description"), // TODO Q_ARG(QVariant, "previousWasBad") // TODO - ); + ); qDebug() << "[UTPassphraseProvider] Waiting for response"; @@ -163,7 +162,7 @@ public: qDebug() << "[UTPassphraseProvider] Prepare Returns"; auto ret = false; - if(!UTPassphraseProvider::instance().m_canceled) { + if (!UTPassphraseProvider::instance().m_canceled) { strncpy(buf, UTPassphraseProvider::instance().m_passphrase.toLocal8Bit().data(), buf_len); ret = true; }; @@ -182,7 +181,8 @@ public: * * @param window The window object to set. */ - void setWindow(QObject* window){ + void setWindow(QObject* window) + { this->m_window = window; } }; diff --git a/po/utpass.qrouland.pot b/po/utpass.qrouland.pot index 9f5f147..5d93caf 100644 --- a/po/utpass.qrouland.pot +++ b/po/utpass.qrouland.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: utpass.qrouland\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-02-03 19:54+0100\n" +"POT-Creation-Date: 2025-02-03 21:35+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -123,7 +123,7 @@ msgstr "" #: ../qml/pages/settings/DeleteRepo.qml:56 #: ../qml/pages/settings/ImportZip.qml:64 -#: ../qml/pages/settings/InfoKeys.qml:167 +#: ../qml/pages/settings/InfoKeys.qml:170 #: ../qml/pages/settings/git/ImportGitClone.qml:56 msgid "Yes" msgstr "" @@ -137,7 +137,7 @@ msgid "Password Store deleted !" msgstr "" #: ../qml/pages/settings/DeleteRepo.qml:90 -#: ../qml/pages/settings/InfoKeys.qml:209 +#: ../qml/pages/settings/InfoKeys.qml:212 msgid "Info Keys" msgstr "" @@ -179,27 +179,27 @@ msgstr "" msgid "Key ID :" msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:117 +#: ../qml/pages/settings/InfoKeys.qml:120 msgid "Users IDs : " msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:144 +#: ../qml/pages/settings/InfoKeys.qml:147 msgid "Delete this key" msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:166 +#: ../qml/pages/settings/InfoKeys.qml:169 msgid "You're are about to delete
%1.
Continue ?" msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:180 +#: ../qml/pages/settings/InfoKeys.qml:183 msgid "Key removal failed !" msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:189 +#: ../qml/pages/settings/InfoKeys.qml:192 msgid "Key successfully deleted !" msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:201 +#: ../qml/pages/settings/InfoKeys.qml:204 msgid "An Error occured getting GPG keys !" msgstr "" diff --git a/qml/pages/settings/InfoKeys.qml b/qml/pages/settings/InfoKeys.qml index 62844b0..02ebf6d 100644 --- a/qml/pages/settings/InfoKeys.qml +++ b/qml/pages/settings/InfoKeys.qml @@ -88,7 +88,13 @@ Page { width: parent.width horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter - text: model.modelData.keyid + text: { + if (!model.modelData) { + ""; + } else { + model.modelData.keyid; + } + } color: theme.palette.normal.backgroundText } @@ -102,10 +108,12 @@ Page { id: userIdsModel Component.onCompleted: { - for (var i = 0; i < model.modelData.userids.length; ++i) { - userIdsModel.append({ - "model": model.modelData.userids[i] - }); + if (model.modelData) { + for (var i = 0; i < model.modelData.userids.length; ++i) { + userIdsModel.append({ + "model": model.modelData.userids[i] + }); + } } } } @@ -125,7 +133,7 @@ Page { width: parent.width horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter - text: modelData.uid + text: modelData color: theme.palette.normal.backgroundText } @@ -163,7 +171,7 @@ Page { id: infoKeysPageDeleteValidation SimpleValidationDialog { - text: i18n.tr("You're are about to delete
%1.
Continue ?").arg(infoKeysPage.__currentKey.uid) + text: i18n.tr("You're are about to delete
%1.
Continue ?").arg(infoKeysPage.__currentKey.keyid) continueText: i18n.tr("Yes") continueColor: theme.palette.normal.negative onValidated: { diff --git a/tests/plugins/TestsUtils/passphraseprovider.h b/tests/plugins/TestsUtils/passphraseprovider.h index 2452528..8a5bb8b 100644 --- a/tests/plugins/TestsUtils/passphraseprovider.h +++ b/tests/plugins/TestsUtils/passphraseprovider.h @@ -17,7 +17,7 @@ private: public: ~TesTPassphraseProvider() = default; - static TesTPassphraseProvider& instance() + static TesTPassphraseProvider &instance() { static TesTPassphraseProvider instance; return instance; @@ -26,15 +26,16 @@ public: void operator=(TesTPassphraseProvider const &) = delete; -static bool -example_pass_provider(rnp_ffi_t ffi, - void * app_ctx, - rnp_key_handle_t key, - const char * pgp_context, - char buf[], - size_t buf_len) -{ strncpy(buf, "utpasspassphrase", buf_len); + static bool + example_pass_provider(rnp_ffi_t ffi, + void *app_ctx, + rnp_key_handle_t key, + const char *pgp_context, + char buf[], + size_t buf_len) + { + strncpy(buf, "utpasspassphrase", buf_len); return true; -} + } }; #endif diff --git a/tests/units/pass/tst_show.qml b/tests/units/pass/tst_show.qml index f6b6391..6e05733 100644 --- a/tests/units/pass/tst_show.qml +++ b/tests/units/pass/tst_show.qml @@ -21,9 +21,8 @@ PassTestCase { } function test_pass_show(data) { - if (data.add_home_gpg_data === true) { + if (data.add_home_gpg_data === true) TestsUtils.copyFolder(Qt.resolvedUrl("../../assets/gpghome"), Qt.resolvedUrl(gpg_home)); - } var fname, ctext; Pass.showSucceed.connect(function(file_name, clear_text) { @@ -34,14 +33,12 @@ PassTestCase { Pass.showFailed.connect(function(err) { err_msg = err; }); - Pass.show(Qt.resolvedUrl(data.file)); data.spy.wait(); - if (data.err_msg) { + if (data.err_msg) verify(err_msg === data.err_msg, "Should return %1 but return %2".arg(data.err_msg).arg(err_msg)); - } else { + else verify(false); - } } SignalSpy {