From beaad58af255b91255d8c8c9ed673fd6765c0f6f Mon Sep 17 00:00:00 2001 From: Quentin Rouland Date: Wed, 15 Jan 2025 23:40:35 +0100 Subject: [PATCH] Add docsting for pass plugin --- plugins/Pass/gpg.cpp | 21 ++-- plugins/Pass/gpg.h | 165 +++++++++++++++++++++++++++--- plugins/Pass/pass.cpp | 42 +++++--- plugins/Pass/pass.h | 141 ++++++++++++++++++++++--- plugins/Pass/passkeymodel.h | 86 +++++++++++++--- plugins/Pass/passphraseprovider.h | 99 +++++++++++++----- po/utpass.qrouland.pot | 30 +++--- qml/Main.qml | 2 +- qml/components/FileDir.qml | 4 +- qml/pages/PasswordList.qml | 22 ++-- qml/pages/settings/InfoKeys.qml | 20 +++- 11 files changed, 510 insertions(+), 122 deletions(-) diff --git a/plugins/Pass/gpg.cpp b/plugins/Pass/gpg.cpp index 189810a..c68c537 100644 --- a/plugins/Pass/gpg.cpp +++ b/plugins/Pass/gpg.cpp @@ -53,7 +53,8 @@ Gpg::Gpg(QObject* windows) qDebug() << "GNUPG Home is :" << engineInfo(OpenPGP).homeDirectory(); } -Gpg::~Gpg(){ +Gpg::~Gpg() +{ delete this->m_passphrase_provider; } @@ -141,7 +142,7 @@ Error Gpg::decrypt(QByteArray cipher_text) ctx->setPinentryMode(Context::PinentryLoopback); QObject::connect(job, &DecryptJob::result, - this, &Gpg::decryptResultSlot); + this, &Gpg::decryptResultSlot); return job->start(cipher_text); } @@ -161,7 +162,8 @@ Error Gpg::decryptFromFile(QString path) -void Gpg::decryptResultSlot(const GpgME::DecryptionResult &result, const QByteArray &plainText, const QString &auditLogAsHtml, const GpgME::Error &auditLogError) +void Gpg::decryptResultSlot(const GpgME::DecryptionResult &result, const QByteArray &plainText, + const QString &auditLogAsHtml, const GpgME::Error &auditLogError) { if (result.error()) { qWarning() << "Something gone wrong on decrypt"; @@ -210,13 +212,13 @@ void Gpg::decryptResultSlot(const GpgME::DecryptionResult &result, const QByteAr Error Gpg::getAllKeys ( bool remote, const bool include_sigs, - bool validate ) + bool validate ) { return getKeys(QString(""), remote, include_sigs, validate); } Error Gpg::getKeys(QString pattern_uid, bool remote, bool include_sigs, - bool validate) + bool validate) { qDebug() << "Getting the keys " << pattern_uid; auto job = openpgp()->keyListJob(remote, include_sigs, validate); @@ -227,7 +229,8 @@ Error Gpg::getKeys(QString pattern_uid, bool remote, bool include_sigs, return job->start(QStringList() << pattern_uid, false); } -void Gpg::getKeysJobResultSlot(const GpgME::KeyListResult &result, const std::vector &keys, const QString &auditLogAsHtml , const GpgME::Error &auditLogError) +void Gpg::getKeysJobResultSlot(const GpgME::KeyListResult &result, const std::vector &keys, + const QString &auditLogAsHtml, const GpgME::Error &auditLogError) { if (result.error()) { qWarning() << "Something gone wrong on decrypt"; @@ -258,7 +261,8 @@ Error Gpg::importKeysFromFile(QString path) return job->start(data); } -void Gpg::importKeysFromFileSlot(const GpgME::ImportResult &result, const QString &auditLogAsHtml, const GpgME::Error &auditLogError) +void Gpg::importKeysFromFileSlot(const GpgME::ImportResult &result, const QString &auditLogAsHtml, + const GpgME::Error &auditLogError) { qDebug() << "numImported" << result.numImported(); qDebug() << "numSecretKeysImported" << result.numSecretKeysImported(); @@ -285,7 +289,8 @@ Error Gpg::deleteKey(const Key key) return openpgp()->deleteJob()->start(key, true); } -void Gpg::deleteKeySlot(const GpgME::Error &error, const QString &auditLogAsHtml, const GpgME::Error &auditLogError) { +void Gpg::deleteKeySlot(const GpgME::Error &error, const QString &auditLogAsHtml, const GpgME::Error &auditLogError) +{ if (error) { qWarning() << "Something gone wrong on decrypt"; diff --git a/plugins/Pass/gpg.h b/plugins/Pass/gpg.h index fd7dfa6..b7eb32f 100644 --- a/plugins/Pass/gpg.h +++ b/plugins/Pass/gpg.h @@ -22,31 +22,67 @@ using namespace GpgME; using namespace QGpgME; +/** + * @class Gpg + * @brief A class for managing GPG key operations such as key import, decryption, and deletion. + * + * This class integrates with the GPGME (GnuPG Made Easy) library to provide functionalities + * for interacting with GPG keys, including decrypting messages, importing keys from files, + * listing keys, and deleting keys. The class also provides slots for handling results + * of asynchronous GPG operations and communicates with the user via signals. + */ class Gpg: public QObject { Q_OBJECT Q_PROPERTY(UTPassphraseProvider* passphrase_provider READ passphrase_provider MEMBER m_passphrase_provider ) private slots: + /** + * @brief Slot to handle the result of a decryption operation. + * @param result The result of the decryption operation. + * @param plain_text The decrypted text. + * @param auditLogAsHtml The HTML formatted audit log for the operation. + * @param auditLogError The error associated with the audit log, if any. + */ void decryptResultSlot( const DecryptionResult &result, const QByteArray &plain_text, const QString &auditLogAsHtml, const Error &auditLogError ); + + /** + * @brief Slot to handle the result of a key retrieval operation. + * @param result The result of the key retrieval operation. + * @param keys A vector of keys retrieved. + * @param auditLogAsHtml The HTML formatted audit log for the operation, if any. + * @param auditLogError The error associated with the audit log, if any. + */ void getKeysJobResultSlot( const GpgME::KeyListResult &result, const std::vector &keys, - const QString &auditLogAsHtml , + const QString &auditLogAsHtml, const GpgME::Error &auditLogError ); + /** + * @brief Slot to handle the result of a key import operation. + * @param result The result of the import operation. + * @param auditLogAsHtml The HTML formatted audit log for the operation, if any. + * @param auditLogError The error associated with the audit log, if any. + */ void importKeysFromFileSlot( const GpgME::ImportResult &result, const QString &auditLogAsHtml, const GpgME::Error &auditLogError ); + /** + * @brief Slot to handle the result of a key deletion operation. + * @param result The error result of the deletion operation. + * @param auditLogAsHtml The HTML formatted audit log for the operation, if any. + * @param auditLogError The error associated with the audit log, if any. + */ void deleteKeySlot( const GpgME::Error &result, const QString &auditLogAsHtml, @@ -54,42 +90,139 @@ private slots: ); signals: + /** + * @brief Signal emitted when keys are imported from a file. + * @param err The error that occurred during the import operation, if any. + */ void importKeysFromFileResult(Error err); + + /** + * @brief Signal emitted when keys are retrieved. + * @param err The error that occurred during the retrieval operation, if any. + * @param keys A vector of keys retrieved. + */ void getKeysResult(Error err, std::vector keys); + + /** + * @brief Signal emitted when a key is deleted. + * @param err The error that occurred during the deletion operation, if any. + */ void deleteKeyResult(Error err); + + /** + * @brief Signal emitted when a decryption operation completes. + * @param err The error that occurred during decryption, if any. + * @param plain_text The decrypted message. + */ void decryptResult(Error err, QString plain_text); private: - UTPassphraseProvider* m_passphrase_provider; + UTPassphraseProvider *m_passphrase_provider; /**< The passphrase provider used for authentication. */ + /** + * @brief Finds the path of a command in the system's environment. + * @param command The name of the command to find. + * @return The full path to the command. + */ QString findCommandPath(const QString &command); + + /** + * @brief Initializes the GPG home directory. + * @return The path to the GPG home directory. + */ QString initGpgHome(); + + /** + * @brief Initializes the GPG executable path. + * @return The path to the GPG executable. + */ QString initGpgExec(); + + /** + * @brief Initializes the GPG configuration. + */ void initGpgConfig(); - Error getKey(QString uid, bool remote = false, bool include_sigs = false, - bool validate = false); + + /** + * @brief Retrieves a GPG key by UID. + * @param uid The UID of the key to retrieve. + * @param remote Whether to fetch the key from a remote keyserver (default: false). + * @param include_sigs Whether to include signatures (default: false). + * @param validate Whether to validate the key (default: false). + * @return The error result of the operation. + */ + Error getKey(QString uid, bool remote = false, bool include_sigs = false, bool validate = false); public: + /** + * @brief Constructs a Gpg object and initializes necessary resources. + * @param window The window object for interacting with the user interface. + */ Gpg(QObject* window); + + /** + * @brief Destroys the Gpg object and cleans up resources. + */ ~Gpg(); - UTPassphraseProvider* passphrase_provider() const + /** + * @brief Gets the passphrase provider used for GPG authentication. + * @return The passphrase provider. + */ + UTPassphraseProvider *passphrase_provider() const { return m_passphrase_provider; } - Error importKeysFromFile(const QString path); - Error getKeys(const QString pattern_uid, const bool remote = false, - const bool include_sigs = false, - const bool validate = false); - Error getAllKeys (bool remote = false, bool include_sigs = {}, bool - validate = false); - Error deleteKey(const Key key); - Error decrypt(const QByteArray cipher_text); - Error decryptFromFile(const QString path); - //Error encrypt (QString str, QString uid, bool ascii_armor = true, - // bool text_mode = true); + /** + * @brief Imports GPG keys from a file. + * @param path The path to the file containing the keys. + * @return The error result of the import operation. + */ + Error importKeysFromFile(const QString path); + + /** + * @brief Retrieves keys matching the provided UID pattern. + * @param pattern_uid The UID pattern to search for. + * @param remote Whether to fetch the key from a remote keyserver (default: false). + * @param include_sigs Whether to include signatures (default: false). + * @param validate Whether to validate the key (default: false). + * @return The error result of the operation. + */ + Error getKeys(const QString pattern_uid, bool remote = false, bool include_sigs = false, bool validate = false); + + /** + * @brief Retrieves all keys from the GPG keyring. + * @param remote Whether to fetch the keys from a remote keyserver (default: false). + * @param include_sigs Whether to include signatures (default: false). + * @param validate Whether to validate the keys (default: false). + * @return The error result of the operation. + */ + Error getAllKeys(bool remote = false, bool include_sigs = false, bool validate = false); + + /** + * @brief Deletes a specified GPG key. + * @param key The key to delete. + * @return The error result of the deletion operation. + */ + Error deleteKey(const Key key); + + /** + * @brief Decrypts a given ciphertext. + * @param cipher_text The ciphertext to decrypt. + * @return The error result of the decryption operation. + */ + Error decrypt(const QByteArray cipher_text); + + /** + * @brief Decrypts the contents of a file. + * @param path The path to the file to decrypt. + * @return The error result of the decryption operation. + */ + Error decryptFromFile(const QString path); + + // Error encrypt (QString str, QString uid, bool ascii_armor = true, bool text_mode = true); }; #endif diff --git a/plugins/Pass/pass.cpp b/plugins/Pass/pass.cpp index 768aca1..0897020 100644 --- a/plugins/Pass/pass.cpp +++ b/plugins/Pass/pass.cpp @@ -10,7 +10,7 @@ Pass::Pass(): m_password_store (QStandardPaths::writableLocation( - QStandardPaths::AppDataLocation).append("/.password-store")), + QStandardPaths::AppDataLocation).append("/.password-store")), m_sem(std::unique_ptr(new QSemaphore(1))), m_show_filename(QString()) {} @@ -23,7 +23,8 @@ void Pass::initialize(QObject *window) this->m_gpg = std::unique_ptr(new Gpg(window)); - QObject::connect(this, &Pass::responsePassphraseDialogPropagate, this->m_gpg->passphrase_provider(), &UTPassphraseProvider::handleResponse); + QObject::connect(this, &Pass::responsePassphraseDialogPropagate, this->m_gpg->passphrase_provider(), + &UTPassphraseProvider::handleResponse); QObject::connect(this->m_gpg.get(), &Gpg::importKeysFromFileResult, this, &Pass::importGPGKeyResult); QObject::connect(this->m_gpg.get(), &Gpg::getKeysResult, this, &Pass::getAllGPGKeysResult); QObject::connect(this->m_gpg.get(), &Gpg::deleteKeyResult, this, &Pass::deleteGPGKeyResult); @@ -38,7 +39,9 @@ void Pass::initialize(QObject *window) bool Pass::show(QUrl url) { - if (!this->m_sem->tryAcquire(1, 500)){ return false; } + if (!this->m_sem->tryAcquire(1, 500)) { + return false; + } auto path = url.toLocalFile(); qInfo() << "Staring decrypting job for " << path; QFileInfo file_info(path); @@ -46,7 +49,8 @@ bool Pass::show(QUrl url) return this->m_gpg->decryptFromFile(path); } -void Pass::showResult(Error err, QString plain_text) { +void Pass::showResult(Error err, QString plain_text) +{ qInfo() << "Result for decrypting job"; if (err) { qInfo() << "Decrypt Failed"; @@ -61,13 +65,16 @@ void Pass::showResult(Error err, QString plain_text) { bool Pass::deleteGPGKey(Key key) { - if (!this->m_sem->tryAcquire(1, 500)){ return false;} + if (!this->m_sem->tryAcquire(1, 500)) { + return false; + } qInfo() << "Deleting Key"; return this->m_gpg->deleteKey(key); } -void Pass::deleteGPGKeyResult(Error err) { - if(err) { +void Pass::deleteGPGKeyResult(Error err) +{ + if (err) { emit deleteGPGKeyFailed(err.asString()); } else { emit deleteGPGKeySucceed(); @@ -77,13 +84,16 @@ void Pass::deleteGPGKeyResult(Error err) { bool Pass::importGPGKey(QUrl url) { - if (!this->m_sem->tryAcquire(1, 500)){ return false;} + if (!this->m_sem->tryAcquire(1, 500)) { + return false; + } qInfo() << "Importing Key from " << url; return this->m_gpg->importKeysFromFile(url.toLocalFile()); } -void Pass::importGPGKeyResult(Error err) { - if(err) { +void Pass::importGPGKeyResult(Error err) +{ + if (err) { emit importGPGKeyFailed(err.asString()); } else { emit importGPGKeySucceed(); @@ -93,13 +103,16 @@ void Pass::importGPGKeyResult(Error err) { bool Pass::getAllGPGKeys() { - if (!this->m_sem->tryAcquire(1, 500)){ return false; } + if (!this->m_sem->tryAcquire(1, 500)) { + return false; + } qInfo() << "Getting all key form gpg "; return this->m_gpg->getAllKeys(); } -void Pass::getAllGPGKeysResult(Error err, std::vector keys_info) { - if(err) { +void Pass::getAllGPGKeysResult(Error err, std::vector keys_info) +{ + if (err) { emit getAllGPGKeysFailed(err.asString()); } else { emit getAllGPGKeysSucceed(QVariant::fromValue(PassKeyModel::keysToPassKey(keys_info))); @@ -107,7 +120,8 @@ void Pass::getAllGPGKeysResult(Error err, std::vector keys_info) { this->m_sem->release(1); } -void Pass::responsePassphraseDialog(bool cancel, QString passphrase) { +void Pass::responsePassphraseDialog(bool cancel, QString passphrase) +{ qDebug() << "responsePassphraseDialog"; emit responsePassphraseDialogPropagate(cancel, passphrase); } diff --git a/plugins/Pass/pass.h b/plugins/Pass/pass.h index 95bfa52..fedf368 100644 --- a/plugins/Pass/pass.h +++ b/plugins/Pass/pass.h @@ -10,59 +10,174 @@ using namespace GpgME; +/** + * @class Pass + * @brief A class for managing password storage using GPG encryption. + * + * This class provides functionalities for interacting with password storage, including + * storing, showing, importing, and deleting passwords securely using GPG encryption. + * It communicates asynchronously with GPG operations, using signals and slots to propagate results. + * The class interacts with the `Gpg` class to perform GPG key operations and provides an interface + * for the user to manage the passwords. + */ class Pass : public QObject { Q_OBJECT Q_PROPERTY(QString password_store READ password_store MEMBER m_password_store CONSTANT) private slots: + /** + * @brief Slot to handle the result of a GPG decryption operation (to show password). + * @param err The error that occurred during the operation. + * @param plain_text The decrypted plain text (password). + */ void showResult(Error err, 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); + + /** + * @brief Slot to handle the result of a GPG key import operation. + * @param err The error that occurred during the operation. + */ void importGPGKeyResult(Error err); - void getAllGPGKeysResult(Error err, std::vector< GpgME::Key > keys_info); + + /** + * @brief Slot to handle the result of retrieving all GPG keys. + * @param err The error that occurred during the operation. + * @param keys_info The list of GPG keys retrieved. + */ + void getAllGPGKeysResult(Error err, std::vector keys_info); signals: - // GPG + // GPG-related signals + /** + * @brief Emitted when a GPG key is successfully deleted. + */ void deleteGPGKeySucceed(); + + /** + * @brief Emitted when a GPG key deletion fails. + * @param message The error message describing the failure. + */ void deleteGPGKeyFailed(QString message); + + /** + * @brief Emitted when a GPG key is successfully imported. + */ void importGPGKeySucceed(); + + /** + * @brief Emitted when a GPG key import fails. + * @param message The error message describing the failure. + */ void importGPGKeyFailed(QString message); + + /** + * @brief Emitted when all GPG keys are successfully retrieved. + * @param keys_info The list of retrieved keys. + */ void getAllGPGKeysSucceed(QVariant keys_info); + + /** + * @brief Emitted when retrieving GPG keys fails. + * @param message The error message describing the failure. + */ void getAllGPGKeysFailed(QString message); + + // Pass-related signals + /** + * @brief Emitted to propagate passphrase dialog response. + * @param cancel Whether the dialog was cancelled. + * @param passphrase The passphrase entered, if not cancelled. + */ void responsePassphraseDialogPropagate(bool cancel, QString passphrase); - // pass show + /** + * @brief Emitted when a password is successfully retrieved and shown. + * @param name The name of the password (e.g., service). + * @param text The password text. + */ void showSucceed(QString name, QString text); + + /** + * @brief Emitted when showing a password fails. + * @param message The error message describing the failure. + */ void showFailed(QString message); - - private: - QString m_password_store; - std::unique_ptr m_gpg; - std::unique_ptr m_sem; - QString m_show_filename; + QString m_password_store; /**< The path to the password store. */ + std::unique_ptr m_gpg; /**< The GPG instance used for encryption/decryption. */ + std::unique_ptr m_sem; /**< Semaphore for managing concurrent operations. */ + QString m_show_filename; /**< The filename associated with the password to show. */ public: + /** + * @brief Constructs the Pass object and initializes necessary resources. + */ Pass(); + + /** + * @brief Destructor for cleaning up resources used by the Pass object. + */ ~Pass() override = default; + /** + * @brief Gets the path to the password store. + * @return The path to the password store. + */ QString password_store() const { return m_password_store; - } + }; + /** + * @brief Initializes the Pass object with the given window. + * @param window The QObject window to interact with. + */ Q_INVOKABLE void initialize(QObject *window); - // GPG + // GPG-related methods + + /** + * @brief Deletes the specified GPG key. + * @param key The GPG key to delete. + * @return True if the operation was successful, false otherwise. + */ Q_INVOKABLE bool deleteGPGKey(Key key); + + /** + * @brief Imports a GPG key from the given URL. + * @param url The URL to import the GPG key from. + * @return True if the operation was successful, false otherwise. + */ Q_INVOKABLE bool importGPGKey(QUrl url); + + /** + * @brief Retrieves all GPG keys. + * @return True if the operation was successful, false otherwise. + */ Q_INVOKABLE bool getAllGPGKeys(); + + /** + * @brief Return the response from the passphrase dialog. + * @param cancel Whether the dialog was cancelled. + * @param passphrase The passphrase entered, if not cancelled. + */ Q_INVOKABLE void responsePassphraseDialog(bool cancel, QString passphrase); - // PASS - Q_INVOKABLE bool show(QUrl url); + // Password store-related methods + /** + * @brief Shows the password associated with the specified URL. + * @param url The URL pointing to the password store entry. + * @return True if the operation was successful, false otherwise. + */ + Q_INVOKABLE bool show(QUrl url); }; #endif diff --git a/plugins/Pass/passkeymodel.h b/plugins/Pass/passkeymodel.h index 638ec58..57c13b7 100644 --- a/plugins/Pass/passkeymodel.h +++ b/plugins/Pass/passkeymodel.h @@ -6,6 +6,14 @@ using namespace GpgME; +/** + * @class UserIdModel + * @brief A model representing a user ID associated with a GPG key. + * + * This class encapsulates the user ID information (UID) for a GPG key, providing access + * to the UID's identifier, name, and email. It is used as a model for user IDs in the + * `PassKeyModel` class. + */ class UserIdModel : public QObject { Q_OBJECT @@ -14,26 +22,51 @@ class UserIdModel : public QObject Q_PROPERTY(QString email READ email CONSTANT) private: - UserID m_user_id; -public: - UserIdModel(UserID key): - m_user_id(key) - {}; + UserID m_user_id; /**< The GPG UserID associated with the model. */ +public: + /** + * @brief Constructs a UserIdModel for the given UserID. + * @param key The GPG UserID to model. + */ + UserIdModel(UserID key) : m_user_id(key) {} + + /** + * @brief Gets the unique identifier (UID) for this user ID. + * @return The UID as a QString. + */ QString uid() const { return QString::fromUtf8(m_user_id.id()); }; + + /** + * @brief Gets the name associated with this user ID. + * @return The name as a QString. + */ QString name() const { return QString::fromUtf8(m_user_id.name()); }; + + /** + * @brief Gets the email associated with this user ID. + * @return The email as a QString. + */ QString email() const { return QString::fromUtf8(m_user_id.email()); }; }; +/** + * @class PassKeyModel + * @brief A model representing a GPG key. + * + * This class encapsulates the properties of a GPG key, including its key ID, associated + * user IDs, secret key status, and expiration status. It is used as a model for managing + * GPG keys within an application, providing access to the key's data and its associated user IDs. + */ class PassKeyModel : public QObject { Q_OBJECT @@ -43,12 +76,21 @@ class PassKeyModel : public QObject Q_PROPERTY(bool isSecret READ isSecret CONSTANT) Q_PROPERTY(bool isExpired READ isExpired CONSTANT) - Key m_key; -public: - PassKeyModel(Key key): - m_key(key) - {}; +private: + Key m_key; /**< The GPG key associated with the model. */ +public: + /** + * @brief Constructs a PassKeyModel for the given GPG key. + * @param key The GPG key to model. + */ + PassKeyModel(Key key) : m_key(key) {} + + /** + * @brief Converts a vector of GPG keys into a list of PassKeyModel objects. + * @param keys The vector of GPG keys to convert. + * @return A QList of PassKeyModel objects representing the keys. + */ static QList keysToPassKey(std::vector keys) { QList ret; @@ -58,16 +100,28 @@ public: return ret; }; + /** + * @brief Gets the GPG key associated with this model. + * @return The GPG key. + */ Key key() const { return m_key; }; + /** + * @brief Gets the unique identifier (UID) for this GPG key. + * @return The UID as a QString. + */ QString uid() const { return QString::fromUtf8(m_key.keyID()); }; + /** + * @brief Gets the list of user IDs associated with this GPG key. + * @return A list of UserIdModel objects representing the user IDs. + */ QList userIds() const { auto user_ids = m_key.userIDs(); @@ -78,17 +132,23 @@ public: return ret; }; + /** + * @brief Checks if the GPG key is a secret key. + * @return True if the key is a secret key, false otherwise. + */ bool isSecret() const { return m_key.hasSecret(); }; + /** + * @brief Checks if the GPG key is expired. + * @return True if the key is expired, false otherwise. + */ bool isExpired() const { - return m_key.hasSecret(); + return m_key.isExpired(); }; }; - - #endif diff --git a/plugins/Pass/passphraseprovider.h b/plugins/Pass/passphraseprovider.h index 31e2adf..4b00b35 100644 --- a/plugins/Pass/passphraseprovider.h +++ b/plugins/Pass/passphraseprovider.h @@ -10,49 +10,91 @@ #include #include "gpg.h" - - +/** + * @class UTPassphraseProvider + * @brief A passphrase provider for GPG operations that interacts with a QML dialog. + * + * This class implements the `PassphraseProvider` interface from GPGME and is responsible for + * obtaining passphrases for GPG operations. It does so by triggering a QML dialog to prompt the user + * for their passphrase. The response is then handled asynchronously, and the passphrase is returned to + * the calling GPGME function. + */ class UTPassphraseProvider : public QObject, public PassphraseProvider { Q_OBJECT public slots: - void handleResponse(bool canceled, QString p) - { - qDebug() << "call handleResponse"; - if (!canceled) - gpgrt_asprintf(&m_passphrase, "%s", p.toUtf8().constData()); - else - m_canceled = true; - emit unlockEventLoop(); - }; + /** + * @brief Slot to handle the user's response from the passphrase dialog. + * + * This method processes the response from the passphrase dialog. If the user provides a passphrase, + * it is stored; if the operation is canceled, a flag is set. + * + * @param canceled Whether the user canceled the passphrase entry. + * @param passphrase The passphrase entered by the user. + */ + void handleResponse(bool canceled, QString passphrase) + { + qDebug() << "call handleResponse"; + if (!canceled) + gpgrt_asprintf(&m_passphrase, "%s", passphrase.toUtf8().constData()); + else + m_canceled = true; + emit unlockEventLoop(); + }; signals: + /** + * @brief Signal to unlock the event loop. + * + * This signal is emitted when the passphrase has been entered or the operation has been canceled, + * unlocking the event loop waiting for the response. + */ void unlockEventLoop(); private: - std::unique_ptr m_sem; - char *m_passphrase; - bool m_canceled; - QObject* m_window; - + std::unique_ptr m_sem; /**< Semaphore for managing access. */ + char *m_passphrase; /**< The passphrase provided by the user. */ + bool m_canceled; /**< Flag indicating whether the passphrase operation was canceled. */ + QObject *m_window; /**< The window object that triggers the QML dialog. */ public: - UTPassphraseProvider(QObject* window): - m_sem(std::unique_ptr(new QSemaphore(1))), - m_passphrase(nullptr), - m_canceled(false), - m_window(window) + /** + * @brief Constructs a UTPassphraseProvider. + * + * Initializes the semaphore, passphrase, and canceled flag. Sets the window object that will + * trigger the passphrase dialog. + * + * @param window The QObject representing the window that interacts with QML. + */ + UTPassphraseProvider(QObject* window) + : m_sem(std::make_unique(1)), + m_passphrase(nullptr), + m_canceled(false), + m_window(window) { - qDebug() << "Initialize UTPassphraseProviderr"; - + qDebug() << "Initialize UTPassphraseProvider"; } - char *getPassphrase( const char *useridHint, - const char *description, - bool previousWasBad, - bool &canceled ) Q_DECL_OVERRIDE { - qDebug() << "Call the getPassphrase"; + /** + * @brief Implements the PassphraseProvider's `getPassphrase` method. + * + * This method is called by GPGME to retrieve the passphrase needed for GPG operations. It triggers + * a QML dialog for the user to input their passphrase. The method waits for the response and returns + * the passphrase if successful, or null if canceled. + * + * @param useridHint A hint for the user ID to which the passphrase corresponds. + * @param description A description of the passphrase request. + * @param previousWasBad Flag indicating whether the previous passphrase attempt was incorrect. + * @param canceled Reference to a boolean flag that will be set if the operation is canceled. + * + * @return The passphrase as a `char *` or `nullptr` if canceled. + */ + char *getPassphrase(const char *useridHint, + const char *description, + bool previousWasBad, + bool &canceled) Q_DECL_OVERRIDE { + qDebug() << "Call the getPassphrase"; if (!this->m_sem->tryAcquire(1, 500)) { qWarning() << "Cannot acquire UTPassphraseProvider semaphore."; @@ -92,4 +134,5 @@ public: return ret; }; }; + #endif diff --git a/po/utpass.qrouland.pot b/po/utpass.qrouland.pot index bdda7d1..2bb9c95 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-01-15 23:14+0100\n" +"POT-Creation-Date: 2025-01-15 23:39+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -85,19 +85,19 @@ msgid "" "a zip in the settings" msgstr "" -#: ../qml/pages/PasswordList.qml:76 +#: ../qml/pages/PasswordList.qml:71 ../qml/pages/settings/InfoKeys.qml:169 +msgid "Decryption failed !" +msgstr "" + +#: ../qml/pages/PasswordList.qml:85 msgid "Back" msgstr "" -#: ../qml/pages/PasswordList.qml:83 ../qml/pages/headers/MainHeader.qml:9 +#: ../qml/pages/PasswordList.qml:92 ../qml/pages/headers/MainHeader.qml:9 #: ../qml/pages/headers/StackHeader.qml:9 UTPass.desktop.in.h:1 msgid "UTPass" msgstr "" -#: ../qml/pages/PasswordList.qml:96 -msgid "Decryption failed !" -msgstr "" - #: ../qml/pages/headers/MainHeader.qml:26 ../qml/pages/settings/Settings.qml:70 msgid "Settings" msgstr "" @@ -126,7 +126,7 @@ msgstr "" #: ../qml/pages/settings/ImportGitClone.qml:91 #: ../qml/pages/settings/ImportZip.qml:62 -#: ../qml/pages/settings/InfoKeys.qml:122 +#: ../qml/pages/settings/InfoKeys.qml:131 msgid "Yes" msgstr "" @@ -168,31 +168,31 @@ msgstr "" msgid "Zip Password Store Import" msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:39 +#: ../qml/pages/settings/InfoKeys.qml:48 msgid "Key ID :" msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:73 +#: ../qml/pages/settings/InfoKeys.qml:82 msgid "Users IDs : " msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:99 +#: ../qml/pages/settings/InfoKeys.qml:108 msgid "Delete this key" msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:121 +#: ../qml/pages/settings/InfoKeys.qml:130 msgid "You're are about to delete
%1
Continue ?" msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:139 +#: ../qml/pages/settings/InfoKeys.qml:148 msgid "Key removal failed !" msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:148 +#: ../qml/pages/settings/InfoKeys.qml:157 msgid "Key successfully deleted !" msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:159 +#: ../qml/pages/settings/InfoKeys.qml:177 msgid "Info Keys" msgstr "" diff --git a/qml/Main.qml b/qml/Main.qml index bf800db..4b9da5c 100644 --- a/qml/Main.qml +++ b/qml/Main.qml @@ -24,7 +24,6 @@ MainView { objectName: "mainView" applicationName: "utpass.qrouland" automaticOrientation: true - width: units.gu(45) height: units.gu(75) @@ -49,4 +48,5 @@ MainView { } } + } diff --git a/qml/components/FileDir.qml b/qml/components/FileDir.qml index 1eb4376..1d8c6a4 100644 --- a/qml/components/FileDir.qml +++ b/qml/components/FileDir.qml @@ -34,12 +34,12 @@ Component { anchors.fill: parent onClicked: { var path = folderModel.folder + "/" + fileName; - if (fileIsDir) { + if (fileIsDir) { folderModel.folder = path; backAction.visible = true; passwordListHeader.title = fileName; } else { - console.debug("pass show %1".arg(path)) + console.debug("pass show %1".arg(path)); Pass.show(path); } } diff --git a/qml/pages/PasswordList.qml b/qml/pages/PasswordList.qml index e592ddb..4190646 100644 --- a/qml/pages/PasswordList.qml +++ b/qml/pages/PasswordList.qml @@ -1,11 +1,11 @@ -import "headers" import "../components" import "../dialogs" import Lomiri.Components 1.3 +import Lomiri.Components.Popups 1.3 import Pass 1.0 import Qt.labs.folderlistmodel 2.1 import QtQuick 2.4 -import Lomiri.Components.Popups 1.3 +import "headers" Page { id: passwordListPage @@ -64,6 +64,15 @@ Page { } + Component { + id: passwordPageDecryptError + + ErrorDialog { + textError: i18n.tr("Decryption failed !") + } + + } + header: MainHeader { id: passwordListHeader @@ -89,13 +98,4 @@ Page { ] } - Component { - id: passwordPageDecryptError - - ErrorDialog { - textError: i18n.tr("Decryption failed !") - } - - } - } diff --git a/qml/pages/settings/InfoKeys.qml b/qml/pages/settings/InfoKeys.qml index b852d29..2032fdc 100644 --- a/qml/pages/settings/InfoKeys.qml +++ b/qml/pages/settings/InfoKeys.qml @@ -11,6 +11,16 @@ Page { property string currentKey + Component.onCompleted: { + Pass.onGetAllGPGKeysSucceed.connect(function(keys_info) { + infoKeysListView.model = keys_info; + }); + Pass.getAllGPGKeysFailed.connect(function(message) { + PopupUtils.open(infoKeysPageGetAllError); + }); + Pass.getAllGPGKeys(); + } + ListView { id: infoKeysListView @@ -18,7 +28,6 @@ Page { anchors.bottom: parent.bottom anchors.right: parent.right anchors.left: parent.left - model: Pass.getAllGPGKeys() delegate: Grid { columns: 1 @@ -153,6 +162,15 @@ Page { } + Component { + id: infoKeysPageGetAllError + + ErrorDialog { + textError: i18n.tr("Decryption failed !") + } + + } + header: StackHeader { id: infoKeysHeader