From 93361f9ba57a74f547e1af753f688f9e5b74ee9c Mon Sep 17 00:00:00 2001 From: Quentin Rouland Date: Mon, 3 Feb 2025 17:48:30 +0100 Subject: [PATCH] Fix build rnp for arm64 --- .gitmodules | 3 + clickable.yaml | 25 ++-- libs/botan | 1 + libs/rnp | 2 +- plugins/Pass/CMakeLists.txt | 34 ++--- plugins/Pass/jobs/decryptjob.cpp | 42 +++++- plugins/Pass/jobs/decryptjob.h | 5 +- plugins/Pass/jobs/getkeysjob.cpp | 3 +- plugins/Pass/jobs/rnpjob.cpp | 9 +- plugins/Pass/jobs/rnpjob.h | 5 + plugins/Pass/pass.cpp | 71 +++++----- plugins/Pass/pass.h | 22 +-- plugins/Pass/passkeymodel.h | 6 - plugins/Pass/passphraseprovider2.h | 132 ++++++++++++++++++ ...der.h => passphraseprovider_tobedeleted.h} | 0 po/utpass.qrouland.pot | 22 +-- qml/Main.qml | 3 - qml/pages/settings/InfoKeys.qml | 11 +- tests/assets/gpg/clear_text.txt | 1 + tests/assets/gpg/clear_text.txt.gpg | 1 + tests/assets/gpg/encrypted.gpg | 0 tests/plugins/TestsUtils/passphraseprovider.h | 37 +++-- tests/plugins/TestsUtils/utils.cpp | 2 +- tests/plugins/TestsUtils/utils.h | 3 - tests/units/pass/tst_get_keys.qml | 4 +- tests/units/pass/tst_import_key.qml | 7 +- tests/units/pass/tst_show.qml | 61 ++++++++ 27 files changed, 365 insertions(+), 147 deletions(-) create mode 160000 libs/botan create mode 100644 plugins/Pass/passphraseprovider2.h rename plugins/Pass/{passphraseprovider.h => passphraseprovider_tobedeleted.h} (100%) create mode 100644 tests/assets/gpg/clear_text.txt create mode 100644 tests/assets/gpg/clear_text.txt.gpg create mode 100644 tests/assets/gpg/encrypted.gpg create mode 100644 tests/units/pass/tst_show.qml diff --git a/.gitmodules b/.gitmodules index c57440e..e596011 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "libs/rnp"] path = libs/rnp url = https://github.com/rnpgp/rnp +[submodule "libs/botan"] + path = libs/botan + url = https://github.com/randombit/botan diff --git a/clickable.yaml b/clickable.yaml index 08a20e5..e30f61d 100644 --- a/clickable.yaml +++ b/clickable.yaml @@ -10,12 +10,19 @@ scripts: dependencies_target: - libgit2-dev - libquazip5-dev -- libgpgmepp-dev -- libgpgme-dev - libjson-c-dev -- gpg libraries: + botan: + builder: custom + make_jobs: 2 + dependencies_host: + - python + prebuild: + - $SRC_DIR/configure.py --cpu $ARCH --prefix $INSTALL_DIR --with-build-dir $BUILD_DIR + build: + - make + - make install rnp: builder: cmake make_jobs: 2 @@ -23,9 +30,8 @@ libraries: - libbz2-dev - zlib1g-dev - libjson-c-dev - build_args: [ - -DCRYPTO_BACKEND=openssl - ] + build_args: -DBUILD_SHARED_LIBS=on -DBUILD_TESTING=off -DCRYPTO_BACKEND=botan + install_lib: - "libgit2.so*" @@ -35,9 +41,6 @@ install_lib: - "libhttp_parser.so*" - "libssh2.so*" - "libquazip5.so*" -- "libgpg-error.so.0.28.0" -- "libassuan.so*" -- "libgpgme.so*" -- "libgpgmepp.so*" -- "libqgpgme.so*" +- "librnp.so*" +- "libbotan-2.so*" diff --git a/libs/botan b/libs/botan new file mode 160000 index 0000000..935055e --- /dev/null +++ b/libs/botan @@ -0,0 +1 @@ +Subproject commit 935055e839794a076d209c9e9a1e9cd2255aae01 diff --git a/libs/rnp b/libs/rnp index c41cef1..2e24942 160000 --- a/libs/rnp +++ b/libs/rnp @@ -1 +1 @@ -Subproject commit c41cef116443d1572118844ecff0292f3ed4e55b +Subproject commit 2e249423d617cf91714624a76bfe4ff613b41ac4 diff --git a/plugins/Pass/CMakeLists.txt b/plugins/Pass/CMakeLists.txt index 972b1ee..511bc8f 100644 --- a/plugins/Pass/CMakeLists.txt +++ b/plugins/Pass/CMakeLists.txt @@ -6,10 +6,12 @@ set( plugin.cpp pass.cpp passkeymodel.h + passphraseprovider2.h jobs/rmjob.cpp jobs/rnpjob.cpp jobs/getkeysjob.cpp jobs/importkeyjob.cpp + jobs/decryptjob.cpp ) set(CMAKE_AUTOMOC ON) @@ -29,37 +31,23 @@ set_target_properties(${PLUGIN} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGIN}) qt5_use_modules(${PLUGIN} Qml Quick DBus) - -set(RNP_BUILD_DIR "${CMAKE_SOURCE_DIR}/build/${ARCH_TRIPLET}/rnp/install") +set(RNP_INSTALL_DIR "${CMAKE_SOURCE_DIR}/build/${ARCH_TRIPLET}/rnp/install") find_package(OpenSSL REQUIRED) find_package(JSON-C 0.11) -INCLUDE_DIRECTORIES(${RNP_BUILD_DIR}/include) +INCLUDE_DIRECTORIES(${RNP_INSTALL_DIR}/include) -add_library(rnp STATIC IMPORTED) -set_property(TARGET rnp PROPERTY IMPORTED_LOCATION "${RNP_BUILD_DIR}/lib/librnp.a") +# add_library(rnp STATIC IMPORTED) +# set_property(TARGET rnp PROPERTY IMPORTED_LOCATION "${RNP_BUILD_DIR}/lib/librnp.a") -add_library(sexpp STATIC IMPORTED) -set_property(TARGET sexpp PROPERTY IMPORTED_LOCATION "${RNP_BUILD_DIR}/lib/libsexpp.a") +# add_library(sexpp STATIC IMPORTED) +# set_property(TARGET sexpp PROPERTY IMPORTED_LOCATION "${RNP_BUILD_DIR}/lib/libsexpp.a") -add_library(gpgerror SHARED IMPORTED) -set_property(TARGET gpgerror PROPERTY IMPORTED_LOCATION "/usr/lib/${ARCH_TRIPLET}/libgpg-error.so.0.28.0") +add_library(rnp SHARED IMPORTED) +set_property(TARGET rnp PROPERTY IMPORTED_LOCATION "${RNP_INSTALL_DIR}/lib/librnp.so") -add_library(libassuan SHARED IMPORTED) -set_property(TARGET libassuan PROPERTY IMPORTED_LOCATION "/usr/lib/${ARCH_TRIPLET}/libassuan.so") - -add_library(libgpgme SHARED IMPORTED) -set_property(TARGET libgpgme PROPERTY IMPORTED_LOCATION "/usr/lib/${ARCH_TRIPLET}/libgpgme.so") - -add_library(libgpgmepp SHARED IMPORTED) -set_property(TARGET libgpgmepp PROPERTY IMPORTED_LOCATION "/usr/lib/${ARCH_TRIPLET}/libgpgmepp.so") - -add_library(libqgpgme SHARED IMPORTED) -set_property(TARGET libqgpgme PROPERTY IMPORTED_LOCATION "/usr/lib/${ARCH_TRIPLET}/libqgpgme.so") - - -target_link_libraries(${PLUGIN} rnp sexpp gpgerror libassuan libgpgme libgpgmepp libqgpgme OpenSSL::Crypto JSON-C::JSON-C) +target_link_libraries(${PLUGIN} rnp OpenSSL::Crypto JSON-C::JSON-C) set(QT_IMPORTS_DIR "/lib/${ARCH_TRIPLET}") install(TARGETS ${PLUGIN} DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN}/) diff --git a/plugins/Pass/jobs/decryptjob.cpp b/plugins/Pass/jobs/decryptjob.cpp index 23cd022..f9bb293 100644 --- a/plugins/Pass/jobs/decryptjob.cpp +++ b/plugins/Pass/jobs/decryptjob.cpp @@ -1,7 +1,13 @@ #include "decryptjob.h" +#include "qdebug.h" +extern "C" { +#include +#include +} -DecryptJob::DecryptJob(QString path, QString keyfile): - m_path(path) +DecryptJob::DecryptJob(QDir rnp_homedir, QString path): + RnpJob(rnp_homedir), + m_encrypted_file_path(path) { this->setObjectName("DecryptJob"); } @@ -9,7 +15,33 @@ DecryptJob::DecryptJob(QString path, QString keyfile): void DecryptJob::run() { - this->load_sec_keyring(); - rnp_input_from_path(&keyfile, "secring.pgp")); - qFatal("To be implemented !") + qDebug() << "[DecryptJob] Starting"; + this->load_sec_keyring(NULL); + + rnp_input_t input = NULL; + rnp_output_t output = NULL; + uint8_t * buf = NULL; + size_t buf_len = 0; + + auto ret = rnp_input_from_path(&input, this->m_encrypted_file_path.toLocal8Bit().data()); + if (ret == RNP_SUCCESS) { + ret = rnp_output_to_memory(&output, 0); + } + if (ret == RNP_SUCCESS) { + ret = rnp_decrypt(this->m_ffi, input, output); + } + if (ret == RNP_SUCCESS) { + 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)); + } + + rnp_input_destroy(input); + rnp_output_destroy(output); + + terminateOnError(ret); + + emit resultSuccess(this->m_encrypted_file_path, QString::fromUtf8((char*)buf)); + qDebug() << "[DecryptJob] Finished Successfully "; } diff --git a/plugins/Pass/jobs/decryptjob.h b/plugins/Pass/jobs/decryptjob.h index 2b185d1..f5f5eb7 100644 --- a/plugins/Pass/jobs/decryptjob.h +++ b/plugins/Pass/jobs/decryptjob.h @@ -34,7 +34,7 @@ signals: * @param encrypted_file_path The path to the encrypted file that was decrypted. * @param clear_txt The decrypted content in clear-text. If an error occurs, this may be empty. */ - void resultReady(QString encrypted_file_path, QString clear_txt); + void resultSuccess(QString encrypted_file_path, QString clear_txt); private: QString m_encrypted_file_path; /**< The path to the encrypted file that is to be decrypted. */ @@ -46,9 +46,10 @@ public: * This constructor initializes the DecryptJob with the encrypted file path. The decryption * operation will be executed in a background thread when the job is started. * + * @param rnp_homedir The directory containing the keyrings. * @param path The path to the encrypted file that needs to be decrypted. */ - DecryptJob(QString path); + DecryptJob(QDir rnp_homedir, QString path); }; #endif // DECRYPTJOB_H diff --git a/plugins/Pass/jobs/getkeysjob.cpp b/plugins/Pass/jobs/getkeysjob.cpp index 135d914..9318492 100644 --- a/plugins/Pass/jobs/getkeysjob.cpp +++ b/plugins/Pass/jobs/getkeysjob.cpp @@ -32,13 +32,14 @@ void GetKeysJob::run() QSet fingerprints = QSet(); this->load_full_keyring(&fingerprints); + //Get infos keys auto key_infos = QList(); QList::iterator i; for (auto i = fingerprints.begin(), end = fingerprints.end(); i != end; ++i) { key_infos.append(this->fingerprint_map_key_info(*i)); } - //Get all infos keys + // Emit result emit resultSuccess(key_infos); qDebug() << "[GetKeysJob] Finished Successfully "; } diff --git a/plugins/Pass/jobs/rnpjob.cpp b/plugins/Pass/jobs/rnpjob.cpp index e01d7dc..9c440da 100644 --- a/plugins/Pass/jobs/rnpjob.cpp +++ b/plugins/Pass/jobs/rnpjob.cpp @@ -52,7 +52,7 @@ bool RnpJob::passProvider(rnp_ffi_t ffi, void RnpJob::load_key_file(QSet *result_fingerprints, const QString path, const uint32_t flags) { - qDebug() << "[RnpJob] load keyring at" << path; + qDebug() << "[RnpJob] Load keyring at" << path; rnp_input_t input = NULL; if (QFileInfo::exists(this->pubringPath())) { auto ret = rnp_input_from_path(&input, path.toLocal8Bit().constData()); @@ -75,9 +75,9 @@ void RnpJob::load_key_file(QSet *result_fingerprints, const QString pat rnp_input_destroy(input); rnp_buffer_destroy(json); terminateOnError(ret); - qDebug() << "[RnpJob] keyring loaded successfully"; + qDebug() << "[RnpJob] Keyring loaded successfully"; } else { - qDebug() << "[RnpJob] No keyring" << path << "not found"; + qDebug() << "[RnpJob] Keyring" << path << "not found"; } } @@ -85,18 +85,15 @@ void RnpJob::load_key_file(QSet *result_fingerprints, const QString pat void RnpJob::load_pub_keyring(QSet *result_fingerprints = NULL) { this->load_key_file(result_fingerprints, this->pubringPath(), RNP_LOAD_SAVE_PUBLIC_KEYS); - qDebug() << "[RnpJob] pub fingerprints" << *result_fingerprints; } void RnpJob::load_sec_keyring(QSet *result_fingerprints = NULL) { this->load_key_file(result_fingerprints, this->secringPath(), RNP_LOAD_SAVE_SECRET_KEYS); - qDebug() << "[RnpJob] sec fingerprints" << *result_fingerprints; } void RnpJob::load_full_keyring(QSet *result_fingerprints = NULL) { this->load_pub_keyring(result_fingerprints); this->load_sec_keyring(result_fingerprints); - qDebug() << "[RnpJob] full fingerprints" << *result_fingerprints; } diff --git a/plugins/Pass/jobs/rnpjob.h b/plugins/Pass/jobs/rnpjob.h index f8fe877..2818c3c 100644 --- a/plugins/Pass/jobs/rnpjob.h +++ b/plugins/Pass/jobs/rnpjob.h @@ -153,6 +153,11 @@ public: * the RNP FFI handle. */ ~RnpJob(); + + + void setPassProvider(rnp_password_cb pass_provider_cb) { + rnp_ffi_set_pass_provider(this->m_ffi, pass_provider_cb, NULL); + } }; #endif // RNPJOB_H diff --git a/plugins/Pass/pass.cpp b/plugins/Pass/pass.cpp index 85ac847..f6edadb 100644 --- a/plugins/Pass/pass.cpp +++ b/plugins/Pass/pass.cpp @@ -2,9 +2,12 @@ #include #include +#include "jobs/decryptjob.h" #include "jobs/getkeysjob.h" #include "jobs/importkeyjob.h" #include "pass.h" +#include "passphraseprovider2.h" +//#include "passphraseprovider2.h" @@ -13,18 +16,19 @@ Pass::Pass(): QStandardPaths::AppDataLocation).append("/.password-store")), m_gpg_home (QStandardPaths::writableLocation( QStandardPaths::AppDataLocation).append("/.rnp")), + m_passphrase_provider(&UTPassphraseProvider::get_pass_provider), m_sem(std::unique_ptr(new QSemaphore(1))) -{ - -} +{} void Pass::initialize(QObject *window) { - if (!window) { - qWarning("[Pass] Window should be null only for testing"); - } this->initGpgHome(); this->initPasswordStore(); + if (!window) { + qWarning("[Pass] Window should be null only for testing"); + } else { + UTPassphraseProvider::instance().setWindow(window); + } } @@ -53,36 +57,37 @@ void Pass::initPasswordStore() qInfo() << "[Pass] Password Store is :" << m_password_store; } -// bool Pass::show(QUrl url) -// { -// if (!this->m_sem->tryAcquire(1, 500)) { -// return false; -// } -// auto path = url.toLocalFile(); -// qInfo() << "Pass show " << path; -// QFileInfo file_info(path); -// this->m_show_filename = file_info.completeBaseName(); -// return this->m_gpg->decryptFromFile(path); -// } +bool Pass::show(QUrl url) +{ + if (!this->m_sem->tryAcquire(1, 500)) { + qInfo() << "[Pass] A command is already running"; + return false; + } + auto job = new DecryptJob(this->m_gpg_home, url.toLocalFile()); + job->setPassProvider(this->m_passphrase_provider); + QObject::connect(job, &DecryptJob::resultError, this, &Pass::slotShowError); + QObject::connect(job, &DecryptJob::resultSuccess, this, &Pass::slotShowSucceed); + connect(job, &DecryptJob::finished, job, &QObject::deleteLater); + job->start(); + return true; +} -// void Pass::showResult(Error err, QString plain_text) -// { -// qDebug() << "Pass show Result"; -// if (err) { -// qInfo() << "Pass show Failed"; -// emit showFailed(err.asString()); +void Pass::slotShowError(rnp_result_t err) +{ + qInfo() << "[Pass] Show Failed"; + emit showFailed(rnp_result_to_string(err)); + this->m_sem->release(1); +} -// } else if (err.isCanceled()) { -// qInfo() << "Pass show Cancelled"; -// emit showCancelled(); -// } else { -// qInfo() << "Pass show Succeed"; -// emit showSucceed(this->m_show_filename, plain_text); -// } -// this->m_show_filename = QString(); -// this->m_sem->release(1); -// } + +void Pass::slotShowSucceed(QString encrypted_file_path, QString plain_text) +{ + qDebug() << "[Pass] Show Succeed"; + QFileInfo file_info(encrypted_file_path); + emit showSucceed(file_info.completeBaseName(), plain_text); + this->m_sem->release(1); +} // bool Pass::deletePasswordStore() // { diff --git a/plugins/Pass/pass.h b/plugins/Pass/pass.h index 6fc6a0c..d06bbb8 100644 --- a/plugins/Pass/pass.h +++ b/plugins/Pass/pass.h @@ -6,14 +6,10 @@ #include #include #include -#include #include extern "C" { #include } - -using namespace GpgME; - /** * @class Pass * @brief A class for managing password storage using GPG encryption. @@ -33,13 +29,15 @@ private slots: * @param err The error that occurred during the operation. * @param plain_text The decrypted plain text (password). */ - void showResult(Error err, QString plain_text); + void slotShowError(rnp_result_t err); + + 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 deleteGPGKeyResult(Error err); /** * @brief Slot to handle the error result of a GPG key import operation. @@ -148,7 +146,7 @@ private: 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. */ - PassphraseProvider *m_passphrase_provider; /**< Pointer on passphrase povider for operations using secret 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. */ @@ -206,14 +204,8 @@ public: this->m_gpg_home = gpg_home; }; - /** - * @brief Sets the window passphrase provider used for GPG authentication. - * - * PassphraseProvider will be deleted with destructor. - * - * @param The window used by passphrase provider. - */ - void set_passphrase_provider(PassphraseProvider* passphrase_provider) + + void set_passphrase_provider(rnp_password_cb passphrase_provider) { this->m_passphrase_provider = passphrase_provider; } diff --git a/plugins/Pass/passkeymodel.h b/plugins/Pass/passkeymodel.h index 618eaf8..eb1c994 100644 --- a/plugins/Pass/passkeymodel.h +++ b/plugins/Pass/passkeymodel.h @@ -11,12 +11,6 @@ * @class PassKeyModel * @brief A model representing a GPG (GNU Privacy Guard) key. * - * This class encapsulates the properties of a GPG key, such as its key ID, associated - * user IDs, secret key status, and expiration status. It is used within an application - * to manage and represent GPG keys, providing easy access to key data and related user information. - * - * This class supports properties such as the key's fingerprint, key ID, user IDs, and whether - * the key has a secret key associated with it. */ class PassKeyModel : public QObject { diff --git a/plugins/Pass/passphraseprovider2.h b/plugins/Pass/passphraseprovider2.h new file mode 100644 index 0000000..b648013 --- /dev/null +++ b/plugins/Pass/passphraseprovider2.h @@ -0,0 +1,132 @@ +#ifndef UTPASSPHRASEPROVIDER2_H +#define UTPASSPHRASEPROVIDER2_H + +#include +#include +#include +#include +#include +#include +#include +extern "C" { +#include +} + +/** + * @class UTPassphraseProvider + * @brief A passphrase provider for GPG operations that interacts with a QML dialog. + */ + +class UTPassphraseProvider : public QObject +{ + Q_OBJECT + +public slots: + /** + * @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) + this->m_passphrase = passphrase; + 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: + explicit UTPassphraseProvider(QObject * parent = nullptr) + : m_sem(std::make_unique(1)), + m_passphrase(QString::Null()), + m_canceled(false) + {} + QObject *m_window; /**< The window object that triggers the QML dialog. */ + std::unique_ptr m_sem; /**< Semaphore for managing access. */ + QString m_passphrase; /**< The passphrase provided by the user. */ + bool m_canceled; /**< Flag indicating whether the passphrase operation was canceled. */ + +public: + ~UTPassphraseProvider() = default; + + static UTPassphraseProvider& instance() + { + static UTPassphraseProvider instance; + return instance; + } + UTPassphraseProvider(UTPassphraseProvider const &) = delete; + void operator=(UTPassphraseProvider const &) = delete; + + 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) + { + qDebug() << "Call the getPassphrase"; + + if (!UTPassphraseProvider::instance().m_sem->tryAcquire(1, 500)) + { + qWarning() << "Cannot acquire UTPassphraseProvider semaphore."; + UTPassphraseProvider::instance().m_canceled = true; + return false; + } + + UTPassphraseProvider::instance().m_passphrase = nullptr; + UTPassphraseProvider::instance().m_canceled = false; + + qDebug() << "Call the QML Dialog Passphrase Provider"; + QMetaObject::invokeMethod( + UTPassphraseProvider::instance().m_window, "callPassphraseDialog", + Q_ARG(QVariant, "useridHint"), // TODO + Q_ARG(QVariant, "description"), // TODO + Q_ARG(QVariant, "previousWasBad") // TODO + ); + + qDebug() << "Waiting for response"; + + QEventLoop loop; + QObject::connect(&UTPassphraseProvider::instance(), &UTPassphraseProvider::unlockEventLoop, &loop, &QEventLoop::quit); + loop.exec(); + + qDebug() << "Prepare Returns"; + auto ret = false; + if(!UTPassphraseProvider::instance().m_canceled) { + strncpy(buf, UTPassphraseProvider::instance().m_passphrase.toLocal8Bit().data(), buf_len); + ret = true; + }; + + qDebug() << "Clean"; + if (UTPassphraseProvider::instance().m_passphrase.isNull()) + { + UTPassphraseProvider::instance().m_passphrase = QString::Null(); + } + UTPassphraseProvider::instance().m_canceled = false; + UTPassphraseProvider::instance().m_sem->release(1); + return ret; + } + + void setWindow(QObject* window){ + this->m_window = window; + } +}; + +#endif diff --git a/plugins/Pass/passphraseprovider.h b/plugins/Pass/passphraseprovider_tobedeleted.h similarity index 100% rename from plugins/Pass/passphraseprovider.h rename to plugins/Pass/passphraseprovider_tobedeleted.h diff --git a/po/utpass.qrouland.pot b/po/utpass.qrouland.pot index 056400a..7fdaf64 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-01 14:08+0100\n" +"POT-Creation-Date: 2025-02-03 16:44+0000\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:170 +#: ../qml/pages/settings/InfoKeys.qml:167 #: ../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:212 +#: ../qml/pages/settings/InfoKeys.qml:209 msgid "Info Keys" msgstr "" @@ -171,35 +171,35 @@ msgstr "" msgid "Zip Password Store Import" msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:50 +#: ../qml/pages/settings/InfoKeys.qml:47 msgid "No key found" msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:86 +#: ../qml/pages/settings/InfoKeys.qml:83 msgid "Key ID :" msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:120 +#: ../qml/pages/settings/InfoKeys.qml:117 msgid "Users IDs : " msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:147 +#: ../qml/pages/settings/InfoKeys.qml:144 msgid "Delete this key" msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:169 +#: ../qml/pages/settings/InfoKeys.qml:166 msgid "You're are about to delete
%1.
Continue ?" msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:183 +#: ../qml/pages/settings/InfoKeys.qml:180 msgid "Key removal failed !" msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:192 +#: ../qml/pages/settings/InfoKeys.qml:189 msgid "Key successfully deleted !" msgstr "" -#: ../qml/pages/settings/InfoKeys.qml:204 +#: ../qml/pages/settings/InfoKeys.qml:201 msgid "An Error occured getting GPG keys !" msgstr "" diff --git a/qml/Main.qml b/qml/Main.qml index d11ef96..4b9da5c 100644 --- a/qml/Main.qml +++ b/qml/Main.qml @@ -26,9 +26,6 @@ MainView { automaticOrientation: true width: units.gu(45) height: units.gu(75) - Component.onCompleted: { - myWorker.sendMessage("Hello World !"); - } PageStack { id: pageStack diff --git a/qml/pages/settings/InfoKeys.qml b/qml/pages/settings/InfoKeys.qml index 8399bff..62844b0 100644 --- a/qml/pages/settings/InfoKeys.qml +++ b/qml/pages/settings/InfoKeys.qml @@ -14,10 +14,7 @@ Page { Component.onCompleted: { Pass.getAllGPGKeysSucceed.connect(function(keys_info) { - infoKeysPage.__keys = keys_info; - for (var i = 0; i < keys_info.length; ++i) { - console.debug("is secret " + keys_info[i].isSecret); - } + infoKeysPage.__keys = keys_info.keys; }); Pass.getAllGPGKeysFailed.connect(function(message) { PopupUtils.open(infoKeysPageGetAllError); @@ -91,7 +88,7 @@ Page { width: parent.width horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter - text: model.modelData.uid + text: model.modelData.keyid color: theme.palette.normal.backgroundText } @@ -105,9 +102,9 @@ Page { id: userIdsModel Component.onCompleted: { - for (var i = 0; i < model.modelData.userIds.length; ++i) { + for (var i = 0; i < model.modelData.userids.length; ++i) { userIdsModel.append({ - "model": model.modelData.userIds[i] + "model": model.modelData.userids[i] }); } } diff --git a/tests/assets/gpg/clear_text.txt b/tests/assets/gpg/clear_text.txt new file mode 100644 index 0000000..408135f --- /dev/null +++ b/tests/assets/gpg/clear_text.txt @@ -0,0 +1 @@ +SomePassword diff --git a/tests/assets/gpg/clear_text.txt.gpg b/tests/assets/gpg/clear_text.txt.gpg new file mode 100644 index 0000000..a946887 --- /dev/null +++ b/tests/assets/gpg/clear_text.txt.gpg @@ -0,0 +1 @@ +„^ûÚáÝÎ8m@ã¢z­,fLƒ?ÕŽ¥ÀjÜö—'œ§!ø[Pfi0 pˆ—:ÊÉ0Cï9e;¼Óþ/¤¢ëcñ;Y­\ìÉ×ÙÃL‡GwšHßÔ` ÔPt.E8Ääšy—ù[z[mŠ˜Îåï ÖÑOÞôƒXkL´°c·°ëœìpC+ÒÔ$¹ÔIéI{ÝHîv³ÂÎ0±]Œr‹ÓHÿ·Žl/‚!lžÁ´õÌÃ0 \ No newline at end of file diff --git a/tests/assets/gpg/encrypted.gpg b/tests/assets/gpg/encrypted.gpg new file mode 100644 index 0000000..e69de29 diff --git a/tests/plugins/TestsUtils/passphraseprovider.h b/tests/plugins/TestsUtils/passphraseprovider.h index 78631ab..2452528 100644 --- a/tests/plugins/TestsUtils/passphraseprovider.h +++ b/tests/plugins/TestsUtils/passphraseprovider.h @@ -3,23 +3,38 @@ #include #include -#include +extern "C" { +#include +} -class TesTPassphraseProvider : public QObject, public GpgME::PassphraseProvider +class TesTPassphraseProvider : public QObject { Q_OBJECT +private: + explicit TesTPassphraseProvider(QObject * parent = nullptr) + {} public: - char *getPassphrase(const char *useridHint, - const char *description, - bool previousWasBad, - bool &canceled) override + ~TesTPassphraseProvider() = default; + + static TesTPassphraseProvider& instance() { + static TesTPassphraseProvider instance; + return instance; + } + TesTPassphraseProvider(TesTPassphraseProvider const &) = delete; + void operator=(TesTPassphraseProvider const &) = delete; - char *ret; - gpgrt_asprintf(&ret, "%s", "utpasspassphrase"); - return ret; - }; + +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/plugins/TestsUtils/utils.cpp b/tests/plugins/TestsUtils/utils.cpp index 16206af..86e6f49 100644 --- a/tests/plugins/TestsUtils/utils.cpp +++ b/tests/plugins/TestsUtils/utils.cpp @@ -70,7 +70,7 @@ void TestsUtils::copyFolder(QUrl sourceFolderUrl, QUrl destFolderUrl) QObject *TestsUtils::getTestPassphraseProvider() { - return this->m_passphrase_povider.get(); + return &TesTPassphraseProvider::instance(); } diff --git a/tests/plugins/TestsUtils/utils.h b/tests/plugins/TestsUtils/utils.h index d4b1c24..28f39a8 100644 --- a/tests/plugins/TestsUtils/utils.h +++ b/tests/plugins/TestsUtils/utils.h @@ -11,9 +11,6 @@ class TestsUtils : public QObject { Q_OBJECT -private: - std::unique_ptr m_passphrase_povider; - public: TestsUtils(); ~TestsUtils() override = default; diff --git a/tests/units/pass/tst_get_keys.qml b/tests/units/pass/tst_get_keys.qml index 71c04e2..259f105 100644 --- a/tests/units/pass/tst_get_keys.qml +++ b/tests/units/pass/tst_get_keys.qml @@ -9,13 +9,11 @@ PassTestCase { function init_data() { return [{ "spy": getAllGPGKeysSucceed, - "signal": Pass.getAllGPGKeysSucceed, "err_msg": null, "add_home_gpg_data": false, "keys": [] }, { "spy": getAllGPGKeysSucceed, - "signal": Pass.getAllGPGKeysSucceed, "err_msg": null, "add_home_gpg_data": true, "keys": [{ @@ -32,7 +30,7 @@ PassTestCase { TestsUtils.copyFolder(Qt.resolvedUrl("../../assets/gpghome"), Qt.resolvedUrl(gpg_home)); var keys; - data.signal.connect(function(keys_info) { + Pass.getAllGPGKeysSucceed.connect(function(keys_info) { keys = keys_info; }); Pass.getAllGPGKeys(); diff --git a/tests/units/pass/tst_import_key.qml b/tests/units/pass/tst_import_key.qml index b468d93..f712ec3 100644 --- a/tests/units/pass/tst_import_key.qml +++ b/tests/units/pass/tst_import_key.qml @@ -8,30 +8,27 @@ PassTestCase { return [{ "file": Qt.resolvedUrl("../../assets/gpg/test_key.gpg"), "spy": importGPGKeySucceed, - "signal": Pass.importGPGKeySucceed, "err_msg": null }, { "file": Qt.resolvedUrl("../../assets/gpg/test_key_do_not_exist.gpg"), "spy": importGPGKeyFailed, - "signal": Pass.importGPGKeyFailed, "err_msg": "Error reading file" }, { "file": Qt.resolvedUrl("../../assets/gpg/test_key_invalid.gpg"), "spy": importGPGKeyFailed, - "signal": Pass.importGPGKeyFailed, "err_msg": "Bad state" }]; } function test_import_key(data) { var err_msg; - data.signal.connect(function(message) { + Pass.importGPGKeyFailed.connect(function(message) { err_msg = message; }); Pass.importGPGKey(data.file); data.spy.wait(); if (data.err_msg) { - verify(err_msg === data.err_msg, "Should return arg msg %1 but return %2".arg(data.err_msg).arg(err_msg)); + verify(err_msg === data.err_msg, "Should return %1 but return %2".arg(data.err_msg).arg(err_msg)); } else { console.info(Qt.resolvedUrl("%1/pubkeyring.pgp".arg(gpg_home))); verify(TestsUtils.fileExists(Qt.resolvedUrl("%1/pubring.pgp".arg(gpg_home))), "%1/pubring.pgp should be created".arg(gpg_home)); diff --git a/tests/units/pass/tst_show.qml b/tests/units/pass/tst_show.qml new file mode 100644 index 0000000..f6b6391 --- /dev/null +++ b/tests/units/pass/tst_show.qml @@ -0,0 +1,61 @@ +import Pass 1.0 +import QtQuick 2.9 +import QtTest 1.2 +import TestsUtils 1.0 + +PassTestCase { + //TODO some additionanl error test + + function init_data() { + return [{ + "spy": showFailed, + "err_msg": "Bad password", + "add_home_gpg_data": true, + "file": "../../assets/gpg/clear_text.txt.gpg" + }, { + "spy": showFailed, + "err_msg": "No suitable key", + "add_home_gpg_data": false, + "file": "../../assets/gpg/clear_text.txt.gpg" + }]; + } + + function test_pass_show(data) { + 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) { + fname = file_name; + ctext = clear_text; + }); + var err_msg; + Pass.showFailed.connect(function(err) { + err_msg = err; + }); + + Pass.show(Qt.resolvedUrl(data.file)); + data.spy.wait(); + if (data.err_msg) { + verify(err_msg === data.err_msg, "Should return %1 but return %2".arg(data.err_msg).arg(err_msg)); + } else { + verify(false); + } + } + + SignalSpy { + id: showSucceed + + target: Pass + signalName: "showSucceed" + } + + SignalSpy { + id: showFailed + + target: Pass + signalName: "showFailed" + } + +}