Move the kwallet plugin to the plugins directory and make it autoload
Testing Done:
Ran from the devenv and verified that it autoloaded and was in the new location.
Reviewed at https://reviews.imfreedom.org/r/1125/
--- a/libpurple/plugins/keyrings/kwallet/meson.build Mon Nov 15 02:21:18 2021 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
- kwallet_moc = qt5.preprocess(
- moc_headers: 'purplekwallet.h',
- kwallet_plugin = library('purplekwallet', kwallet_sources,
- c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="Purple-KWalletKeyring"'],
- dependencies : [kwallet, qt5_dep, libpurple_dep],
- install : true, install_dir : PURPLE_PLUGINDIR)
- devenv.append('PURPLE_PLUGIN_PATH', meson.current_build_dir())
--- a/libpurple/plugins/keyrings/kwallet/purplekwallet.cpp Mon Nov 15 02:21:18 2021 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,617 +0,0 @@
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License along with
- * this library; if not, see <https://www.gnu.org/licenses/>.
-#include <glib/gi18n-lib.h>
-#include <QCoreApplication>
-#include "purplekwallet.h"
-/******************************************************************************
- *****************************************************************************/
-static QCoreApplication *qCoreApp = NULL;
-static PurpleCredentialProvider *instance = NULL;
-#define PURPLE_KWALLET_DOMAIN (g_quark_from_static_string("purple-kwallet"))
-#define PURPLE_KWALLET_WALLET_NAME (KWallet::Wallet::NetworkWallet())
-struct _PurpleKWalletProvider {
- PurpleCredentialProvider parent;
- PurpleKWalletPlugin::Engine *engine;
-G_DEFINE_DYNAMIC_TYPE(PurpleKWalletProvider, purple_kwallet_provider,
- PURPLE_TYPE_CREDENTIAL_PROVIDER)
-/******************************************************************************
- *****************************************************************************/
-purple_kwallet_get_ui_name(void) {
- PurpleUiInfo *ui_info = NULL;
- QString ui_name = NULL;
- ui_info = purple_core_get_ui_info();
- if(PURPLE_IS_UI_INFO(ui_info)) {
- ui_name = purple_ui_info_get_name(ui_info);
- g_object_unref(G_OBJECT(ui_info));
- if(ui_name.isEmpty()) {
-purple_kwallet_provider_account_key(PurpleAccount *account) {
- return QString(purple_account_get_protocol_id(account)) + ":" +
- purple_account_get_username(account);
-/******************************************************************************
- * Request Implementation
- *****************************************************************************/
-PurpleKWalletPlugin::Request::Request(QString key, GTask *task) {
- this->task = G_TASK(g_object_ref(G_OBJECT(task)));
-PurpleKWalletPlugin::Request::~Request(void) {
- g_clear_object(&this->task);
-/******************************************************************************
- * ReadRequest Implementation
- *****************************************************************************/
-PurpleKWalletPlugin::ReadRequest::ReadRequest(QString key, GTask *task) : PurpleKWalletPlugin::Request(key, task) {
-PurpleKWalletPlugin::ReadRequest::execute(KWallet::Wallet *wallet) {
- missing = KWallet::Wallet::keyDoesNotExist(PURPLE_KWALLET_WALLET_NAME,
- purple_kwallet_get_ui_name(),
- g_task_return_new_error(this->task, PURPLE_KWALLET_DOMAIN, 0,
- g_clear_object(&this->task);
- result = wallet->readPassword(this->key, password);
- g_task_return_new_error(this->task, PURPLE_KWALLET_DOMAIN, result,
- _("failed to read password, kwallet responded "
- "with error code %d"), result);
- gchar *c_password = g_strdup(password.toUtf8().constData());
- g_task_return_pointer(this->task, c_password, g_free);
- g_clear_object(&this->task);
-PurpleKWalletPlugin::ReadRequest::cancel(QString reason) {
- g_task_return_new_error(this->task, PURPLE_KWALLET_DOMAIN, 0,
- _("failed to read password: %s"),
- reason.toUtf8().constData());
- g_clear_object(&this->task);
-/******************************************************************************
- * WriteRequest Implementation
- *****************************************************************************/
-PurpleKWalletPlugin::WriteRequest::WriteRequest(QString key, GTask *task, QString password) : PurpleKWalletPlugin::Request(key, task) {
- this->password = password;
-PurpleKWalletPlugin::WriteRequest::execute(KWallet::Wallet *wallet) {
- result = wallet->writePassword(this->key, this->password);
- g_task_return_new_error(this->task, PURPLE_KWALLET_DOMAIN, result,
- _("failed to write password, kwallet "
- "responded with error code %d"), result);
- g_task_return_boolean(this->task, TRUE);
- g_clear_object(&this->task);
-PurpleKWalletPlugin::WriteRequest::cancel(QString reason) {
- g_task_return_new_error(this->task, PURPLE_KWALLET_DOMAIN, 0,
- _("failed to write password: %s"),
- reason.toUtf8().constData());
- g_clear_object(&this->task);
-/******************************************************************************
- * ClearRequest Implementation
- *****************************************************************************/
-PurpleKWalletPlugin::ClearRequest::ClearRequest(QString key, GTask *task) : PurpleKWalletPlugin::Request(key, task) {
-PurpleKWalletPlugin::ClearRequest::execute(KWallet::Wallet *wallet) {
- result = wallet->removeEntry(this->key);
- g_task_return_new_error(this->task, PURPLE_KWALLET_DOMAIN, result,
- _("failed to clear password, kwallet "
- "responded with error code %d"), result);
- g_task_return_boolean(this->task, TRUE);
- g_clear_object(&this->task);
-PurpleKWalletPlugin::ClearRequest::cancel(QString reason) {
- g_task_return_new_error(this->task, PURPLE_KWALLET_DOMAIN, 0,
- _("failed to clear password: %s"),
- reason.toUtf8().constData());
- g_clear_object(&this->task);
-/******************************************************************************
- * Engine Implementation
- *****************************************************************************/
-PurpleKWalletPlugin::Engine::Engine(void) {
- this->queue = QQueue<PurpleKWalletPlugin::Request *>();
- this->connected = false;
- this->externallyClosed = false;
-PurpleKWalletPlugin::Engine::~Engine(void) {
-PurpleKWalletPlugin::Engine::open(void) {
- purple_debug_misc("kwallet-provider", "attempting to open wallet");
- purple_debug_misc("kwallet-provider", "wallet already opened");
- // Reset our externallyClosed and failed states.
- this->externallyClosed = false;
- // No need to check this pointer as an async open always returns non-null.
- this->wallet = KWallet::Wallet::openWallet(PURPLE_KWALLET_WALLET_NAME,
- KWallet::Wallet::Asynchronous);
- this->failed |= !QObject::connect(this->wallet, SIGNAL(walletOpened(bool)),
- this->failed |= !QObject::connect(this->wallet, SIGNAL(walletClosed(void)),
- purple_debug_error("kwallet-provider",
- "Failed to connect KWallet signals");
-PurpleKWalletPlugin::Engine::close(void) {
- while(!this->queue.isEmpty()) {
- PurpleKWalletPlugin::Request *request = this->queue.dequeue();
- request->cancel("wallet is closing");
- if(this->wallet != NULL) {
- this->connected = false;
-PurpleKWalletPlugin::Engine::enqueue(PurpleKWalletPlugin::Request *request) {
- this->queue.enqueue(request);
-PurpleKWalletPlugin::Engine::opened(bool opened) {
- purple_debug_error("kwallet-provider", "failed to open wallet");
- this->connected = false;
- // Handle the case where the wallet opened signal connected, but the wallet
- // closed signal failed to connect.
- purple_debug_error("kwallet-provider",
- "wallet opened, but failed to connect the wallet "
- this->connected = true;
- folder_name = purple_kwallet_get_ui_name();
- if(!this->wallet->hasFolder(folder_name)) {
- if(!this->wallet->createFolder(folder_name)) {
- purple_debug_error("kwallet-provider",
- "failed to create folder %s in wallet.",
- folder_name.toUtf8().constData());
- if(!this->failed && !this->wallet->setFolder(folder_name)) {
- purple_debug_error("kwallet-provider", "failed to set folder to %s",
- folder_name.toUtf8().constData());
- purple_debug_misc("kwallet-provider", "successfully opened the wallet");
-PurpleKWalletPlugin::Engine::closed(void) {
- purple_debug_misc("kwallet-provider", "the wallet was closed externally");
- this->externallyClosed = true;
-PurpleKWalletPlugin::Engine::processQueue() {
- if(this->externallyClosed && this->queue.isEmpty() == false) {
- } else if(this->connected || this->failed) {
- while(!this->queue.isEmpty()) {
- PurpleKWalletPlugin::Request *request = this->queue.dequeue();
- request->cancel(_("failed to open kwallet"));
- request->execute(this->wallet);
-/******************************************************************************
- * PurpleCredentialProvider Implementation
- *****************************************************************************/
-purple_kwallet_provider_activate(PurpleCredentialProvider *provider) {
- PurpleKWalletProvider *kwallet_provider = NULL;
- kwallet_provider = PURPLE_KWALLET_PROVIDER(provider);
- kwallet_provider->engine->open();
-purple_kwallet_provider_deactivate(PurpleCredentialProvider *provider) {
- PurpleKWalletProvider *kwallet_provider = NULL;
- kwallet_provider = PURPLE_KWALLET_PROVIDER(provider);
- kwallet_provider->engine->close();
-purple_kwallet_read_password_async(PurpleCredentialProvider *provider,
- PurpleAccount *account,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- PurpleKWalletProvider *kwallet_provider = NULL;
- PurpleKWalletPlugin::ReadRequest *request = NULL;
- key = purple_kwallet_provider_account_key(account);
- task = g_task_new(G_OBJECT(provider), cancellable, callback, data);
- request = new PurpleKWalletPlugin::ReadRequest(key, task);
- kwallet_provider = PURPLE_KWALLET_PROVIDER(provider);
- kwallet_provider->engine->enqueue(request);
-purple_kwallet_read_password_finish(PurpleCredentialProvider *provider,
- GAsyncResult *result, GError **error)
- return (gchar *)g_task_propagate_pointer(G_TASK(result), error);
-purple_kwallet_write_password_async(PurpleCredentialProvider *provider,
- PurpleAccount *account,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- PurpleKWalletProvider *kwallet_provider = NULL;
- PurpleKWalletPlugin::WriteRequest *request = NULL;
- task = g_task_new(G_OBJECT(provider), cancellable, callback, data);
- key = purple_kwallet_provider_account_key(account);
- request = new PurpleKWalletPlugin::WriteRequest(key, task, password);
- kwallet_provider = PURPLE_KWALLET_PROVIDER(provider);
- kwallet_provider->engine->enqueue(request);
-purple_kwallet_write_password_finish(PurpleCredentialProvider *provider,
- GAsyncResult *result, GError **error)
- return g_task_propagate_boolean(G_TASK(result), error);
-purple_kwallet_clear_password_async(PurpleCredentialProvider *provider,
- PurpleAccount *account,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- PurpleKWalletProvider *kwallet_provider = NULL;
- PurpleKWalletPlugin::ClearRequest *request = NULL;
- task = g_task_new(G_OBJECT(provider), cancellable, callback, data);
- key = purple_kwallet_provider_account_key(account);
- request = new PurpleKWalletPlugin::ClearRequest(key, task);
- kwallet_provider = PURPLE_KWALLET_PROVIDER(provider);
- kwallet_provider->engine->enqueue(request);
-purple_kwallet_clear_password_finish(PurpleCredentialProvider *provider,
- GAsyncResult *result, GError **error)
- return g_task_propagate_boolean(G_TASK(result), error);
-/******************************************************************************
- * GObject Implementation
- *****************************************************************************/
-purple_kwallet_provider_dispose(GObject *obj) {
- PurpleKWalletProvider *provider = PURPLE_KWALLET_PROVIDER(obj);
- if(provider->engine != NULL) {
- provider->engine->close();
- G_OBJECT_CLASS(purple_kwallet_provider_parent_class)->dispose(obj);
-purple_kwallet_provider_finalize(GObject *obj) {
- PurpleKWalletProvider *provider = PURPLE_KWALLET_PROVIDER(obj);
- if(provider->engine != NULL) {
- delete provider->engine;
- provider->engine = NULL;
- G_OBJECT_CLASS(purple_kwallet_provider_parent_class)->finalize(obj);
-purple_kwallet_provider_init(PurpleKWalletProvider *provider) {
- provider->engine = new PurpleKWalletPlugin::Engine();
-purple_kwallet_provider_class_init(PurpleKWalletProviderClass *klass) {
- GObjectClass *obj_class = G_OBJECT_CLASS(klass);
- PurpleCredentialProviderClass *provider_class = NULL;
- provider_class = PURPLE_CREDENTIAL_PROVIDER_CLASS(klass);
- obj_class->dispose = purple_kwallet_provider_dispose;
- obj_class->finalize = purple_kwallet_provider_finalize;
- provider_class->activate = purple_kwallet_provider_activate;
- provider_class->deactivate = purple_kwallet_provider_deactivate;
- provider_class->read_password_async = purple_kwallet_read_password_async;
- provider_class->read_password_finish = purple_kwallet_read_password_finish;
- provider_class->write_password_async = purple_kwallet_write_password_async;
- provider_class->write_password_finish =
- purple_kwallet_write_password_finish;
- provider_class->clear_password_async = purple_kwallet_clear_password_async;
- provider_class->clear_password_finish =
- purple_kwallet_clear_password_finish;
-purple_kwallet_provider_class_finalize(PurpleKWalletProviderClass *klass) {
-/******************************************************************************
- *****************************************************************************/
-static PurpleCredentialProvider *
-purple_kwallet_provider_new(void) {
- return PURPLE_CREDENTIAL_PROVIDER(g_object_new(
- PURPLE_KWALLET_TYPE_PROVIDER,
- "description", _("A credentials management application for the KDE "
- "Software Compilation desktop environment"),
-/******************************************************************************
- *****************************************************************************/
-static GPluginPluginInfo *
-kwallet_query(G_GNUC_UNUSED GError **error) {
- const gchar * const authors[] = {
- "Pidgin Developers <devel@pidgin.im>",
- return GPLUGIN_PLUGIN_INFO(purple_plugin_info_new(
- "id", "keyring-kwallet",
- "version", DISPLAY_VERSION,
- "category", N_("Keyring"),
- "summary", "KWallet Keyring Plugin",
- "description", N_("This plugin will store passwords in KWallet."),
- "website", PURPLE_WEBSITE,
- "abi-version", PURPLE_ABI_VERSION,
- "flags", PURPLE_PLUGIN_INFO_FLAGS_INTERNAL,
-kwallet_load(GPluginPlugin *plugin, GError **error) {
- PurpleCredentialManager *manager = NULL;
- purple_kwallet_provider_register_type(G_TYPE_MODULE(plugin));
- qCoreApp = new QCoreApplication(argc, NULL);
- qCoreApp->setApplicationName(purple_kwallet_get_ui_name());
- if(!KWallet::Wallet::isEnabled()) {
- g_set_error(error, PURPLE_KWALLET_DOMAIN, 0,
- "KWallet service is disabled.");
- manager = purple_credential_manager_get_default();
- instance = purple_kwallet_provider_new();
- return purple_credential_manager_register(manager, instance, error);
-kwallet_unload(G_GNUC_UNUSED GPluginPlugin *plugin,
- G_GNUC_UNUSED gboolean shutdown,
- PurpleCredentialManager *manager = NULL;
- manager = purple_credential_manager_get_default();
- ret = purple_credential_manager_unregister(manager, instance, error);
- g_clear_object(&instance);
-GPLUGIN_NATIVE_PLUGIN_DECLARE(kwallet)
--- a/libpurple/plugins/keyrings/kwallet/purplekwallet.h Mon Nov 15 02:21:18 2021 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License along with
- * this library; if not, see <https://www.gnu.org/licenses/>.
-#define PURPLE_KWALLET_TYPE_PROVIDER (purple_kwallet_provider_get_type())
-G_DECLARE_FINAL_TYPE(PurpleKWalletProvider, purple_kwallet_provider,
- PURPLE_KWALLET, PROVIDER, PurpleCredentialProvider)
-namespace PurpleKWalletPlugin {
- Request(QString key, GTask *task);
- virtual ~Request(void);
- virtual void execute(KWallet::Wallet *wallet) = 0;
- virtual void cancel(QString reason) = 0;
-class ReadRequest : public Request {
- ReadRequest(QString key, GTask *task);
- void execute(KWallet::Wallet *wallet);
- void cancel(QString reason);
-class WriteRequest : public Request {
- WriteRequest(QString key, GTask *task, QString password);
- void execute(KWallet::Wallet *wallet);
- void cancel(QString reason);
-class ClearRequest : public Request {
- ClearRequest(QString key, GTask *task);
- void execute(KWallet::Wallet *wallet);
- void cancel(QString reason);
-class Engine : public QObject {
- void enqueue(Request *request);
- void opened(bool opened);
- void processQueue(void);
- KWallet::Wallet *wallet;
- QQueue<Request *> queue;
--- a/libpurple/plugins/keyrings/meson.build Mon Nov 15 02:21:18 2021 -0600
+++ b/libpurple/plugins/keyrings/meson.build Mon Nov 15 02:23:25 2021 -0600
@@ -1,5 +1,3 @@
internalkeyring_plugin = library('internalkeyring', 'internalkeyring.c',
c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="Purple-InternalKeyring"'],
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins/kwallet/meson.build Mon Nov 15 02:23:25 2021 -0600
@@ -0,0 +1,20 @@
+ kwallet_moc = qt5.preprocess( + moc_headers: 'purplekwallet.h', + kwallet_plugin = library('purplekwallet', kwallet_sources, + c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="Purple-KWalletKeyring"'], + dependencies : [kwallet, qt5_dep, libpurple_dep], + install : true, install_dir : PURPLE_PLUGINDIR) + devenv.append('PURPLE_PLUGIN_PATH', meson.current_build_dir()) --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins/kwallet/purplekwallet.cpp Mon Nov 15 02:23:25 2021 -0600
@@ -0,0 +1,618 @@
+ * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License along with + * this library; if not, see <https://www.gnu.org/licenses/>. +#include <glib/gi18n-lib.h> +#include <QCoreApplication> +#include "purplekwallet.h" +/****************************************************************************** + *****************************************************************************/ +static QCoreApplication *qCoreApp = NULL; +static PurpleCredentialProvider *instance = NULL; +#define PURPLE_KWALLET_DOMAIN (g_quark_from_static_string("purple-kwallet")) +#define PURPLE_KWALLET_WALLET_NAME (KWallet::Wallet::NetworkWallet()) +struct _PurpleKWalletProvider { + PurpleCredentialProvider parent; + PurpleKWalletPlugin::Engine *engine; +G_DEFINE_DYNAMIC_TYPE(PurpleKWalletProvider, purple_kwallet_provider, + PURPLE_TYPE_CREDENTIAL_PROVIDER) +/****************************************************************************** + *****************************************************************************/ +purple_kwallet_get_ui_name(void) { + PurpleUiInfo *ui_info = NULL; + QString ui_name = NULL; + ui_info = purple_core_get_ui_info(); + if(PURPLE_IS_UI_INFO(ui_info)) { + ui_name = purple_ui_info_get_name(ui_info); + g_object_unref(G_OBJECT(ui_info)); + if(ui_name.isEmpty()) { +purple_kwallet_provider_account_key(PurpleAccount *account) { + return QString(purple_account_get_protocol_id(account)) + ":" + + purple_account_get_username(account); +/****************************************************************************** + * Request Implementation + *****************************************************************************/ +PurpleKWalletPlugin::Request::Request(QString key, GTask *task) { + this->task = G_TASK(g_object_ref(G_OBJECT(task))); +PurpleKWalletPlugin::Request::~Request(void) { + g_clear_object(&this->task); +/****************************************************************************** + * ReadRequest Implementation + *****************************************************************************/ +PurpleKWalletPlugin::ReadRequest::ReadRequest(QString key, GTask *task) : PurpleKWalletPlugin::Request(key, task) { +PurpleKWalletPlugin::ReadRequest::execute(KWallet::Wallet *wallet) { + missing = KWallet::Wallet::keyDoesNotExist(PURPLE_KWALLET_WALLET_NAME, + purple_kwallet_get_ui_name(), + g_task_return_new_error(this->task, PURPLE_KWALLET_DOMAIN, 0, + g_clear_object(&this->task); + result = wallet->readPassword(this->key, password); + g_task_return_new_error(this->task, PURPLE_KWALLET_DOMAIN, result, + _("failed to read password, kwallet responded " + "with error code %d"), result); + gchar *c_password = g_strdup(password.toUtf8().constData()); + g_task_return_pointer(this->task, c_password, g_free); + g_clear_object(&this->task); +PurpleKWalletPlugin::ReadRequest::cancel(QString reason) { + g_task_return_new_error(this->task, PURPLE_KWALLET_DOMAIN, 0, + _("failed to read password: %s"), + reason.toUtf8().constData()); + g_clear_object(&this->task); +/****************************************************************************** + * WriteRequest Implementation + *****************************************************************************/ +PurpleKWalletPlugin::WriteRequest::WriteRequest(QString key, GTask *task, QString password) : PurpleKWalletPlugin::Request(key, task) { + this->password = password; +PurpleKWalletPlugin::WriteRequest::execute(KWallet::Wallet *wallet) { + result = wallet->writePassword(this->key, this->password); + g_task_return_new_error(this->task, PURPLE_KWALLET_DOMAIN, result, + _("failed to write password, kwallet " + "responded with error code %d"), result); + g_task_return_boolean(this->task, TRUE); + g_clear_object(&this->task); +PurpleKWalletPlugin::WriteRequest::cancel(QString reason) { + g_task_return_new_error(this->task, PURPLE_KWALLET_DOMAIN, 0, + _("failed to write password: %s"), + reason.toUtf8().constData()); + g_clear_object(&this->task); +/****************************************************************************** + * ClearRequest Implementation + *****************************************************************************/ +PurpleKWalletPlugin::ClearRequest::ClearRequest(QString key, GTask *task) : PurpleKWalletPlugin::Request(key, task) { +PurpleKWalletPlugin::ClearRequest::execute(KWallet::Wallet *wallet) { + result = wallet->removeEntry(this->key); + g_task_return_new_error(this->task, PURPLE_KWALLET_DOMAIN, result, + _("failed to clear password, kwallet " + "responded with error code %d"), result); + g_task_return_boolean(this->task, TRUE); + g_clear_object(&this->task); +PurpleKWalletPlugin::ClearRequest::cancel(QString reason) { + g_task_return_new_error(this->task, PURPLE_KWALLET_DOMAIN, 0, + _("failed to clear password: %s"), + reason.toUtf8().constData()); + g_clear_object(&this->task); +/****************************************************************************** + * Engine Implementation + *****************************************************************************/ +PurpleKWalletPlugin::Engine::Engine(void) { + this->queue = QQueue<PurpleKWalletPlugin::Request *>(); + this->connected = false; + this->externallyClosed = false; +PurpleKWalletPlugin::Engine::~Engine(void) { +PurpleKWalletPlugin::Engine::open(void) { + purple_debug_misc("kwallet-provider", "attempting to open wallet"); + purple_debug_misc("kwallet-provider", "wallet already opened"); + // Reset our externallyClosed and failed states. + this->externallyClosed = false; + // No need to check this pointer as an async open always returns non-null. + this->wallet = KWallet::Wallet::openWallet(PURPLE_KWALLET_WALLET_NAME, + KWallet::Wallet::Asynchronous); + this->failed |= !QObject::connect(this->wallet, SIGNAL(walletOpened(bool)), + this->failed |= !QObject::connect(this->wallet, SIGNAL(walletClosed(void)), + purple_debug_error("kwallet-provider", + "Failed to connect KWallet signals"); +PurpleKWalletPlugin::Engine::close(void) { + while(!this->queue.isEmpty()) { + PurpleKWalletPlugin::Request *request = this->queue.dequeue(); + request->cancel("wallet is closing"); + if(this->wallet != NULL) { + this->connected = false; +PurpleKWalletPlugin::Engine::enqueue(PurpleKWalletPlugin::Request *request) { + this->queue.enqueue(request); +PurpleKWalletPlugin::Engine::opened(bool opened) { + purple_debug_error("kwallet-provider", "failed to open wallet"); + this->connected = false; + // Handle the case where the wallet opened signal connected, but the wallet + // closed signal failed to connect. + purple_debug_error("kwallet-provider", + "wallet opened, but failed to connect the wallet " + this->connected = true; + folder_name = purple_kwallet_get_ui_name(); + if(!this->wallet->hasFolder(folder_name)) { + if(!this->wallet->createFolder(folder_name)) { + purple_debug_error("kwallet-provider", + "failed to create folder %s in wallet.", + folder_name.toUtf8().constData()); + if(!this->failed && !this->wallet->setFolder(folder_name)) { + purple_debug_error("kwallet-provider", "failed to set folder to %s", + folder_name.toUtf8().constData()); + purple_debug_misc("kwallet-provider", "successfully opened the wallet"); +PurpleKWalletPlugin::Engine::closed(void) { + purple_debug_misc("kwallet-provider", "the wallet was closed externally"); + this->externallyClosed = true; +PurpleKWalletPlugin::Engine::processQueue() { + if(this->externallyClosed && this->queue.isEmpty() == false) { + } else if(this->connected || this->failed) { + while(!this->queue.isEmpty()) { + PurpleKWalletPlugin::Request *request = this->queue.dequeue(); + request->cancel(_("failed to open kwallet")); + request->execute(this->wallet); +/****************************************************************************** + * PurpleCredentialProvider Implementation + *****************************************************************************/ +purple_kwallet_provider_activate(PurpleCredentialProvider *provider) { + PurpleKWalletProvider *kwallet_provider = NULL; + kwallet_provider = PURPLE_KWALLET_PROVIDER(provider); + kwallet_provider->engine->open(); +purple_kwallet_provider_deactivate(PurpleCredentialProvider *provider) { + PurpleKWalletProvider *kwallet_provider = NULL; + kwallet_provider = PURPLE_KWALLET_PROVIDER(provider); + kwallet_provider->engine->close(); +purple_kwallet_read_password_async(PurpleCredentialProvider *provider, + PurpleAccount *account, + GCancellable *cancellable, + GAsyncReadyCallback callback, + PurpleKWalletProvider *kwallet_provider = NULL; + PurpleKWalletPlugin::ReadRequest *request = NULL; + key = purple_kwallet_provider_account_key(account); + task = g_task_new(G_OBJECT(provider), cancellable, callback, data); + request = new PurpleKWalletPlugin::ReadRequest(key, task); + kwallet_provider = PURPLE_KWALLET_PROVIDER(provider); + kwallet_provider->engine->enqueue(request); +purple_kwallet_read_password_finish(PurpleCredentialProvider *provider, + GAsyncResult *result, GError **error) + return (gchar *)g_task_propagate_pointer(G_TASK(result), error); +purple_kwallet_write_password_async(PurpleCredentialProvider *provider, + PurpleAccount *account, + GCancellable *cancellable, + GAsyncReadyCallback callback, + PurpleKWalletProvider *kwallet_provider = NULL; + PurpleKWalletPlugin::WriteRequest *request = NULL; + task = g_task_new(G_OBJECT(provider), cancellable, callback, data); + key = purple_kwallet_provider_account_key(account); + request = new PurpleKWalletPlugin::WriteRequest(key, task, password); + kwallet_provider = PURPLE_KWALLET_PROVIDER(provider); + kwallet_provider->engine->enqueue(request); +purple_kwallet_write_password_finish(PurpleCredentialProvider *provider, + GAsyncResult *result, GError **error) + return g_task_propagate_boolean(G_TASK(result), error); +purple_kwallet_clear_password_async(PurpleCredentialProvider *provider, + PurpleAccount *account, + GCancellable *cancellable, + GAsyncReadyCallback callback, + PurpleKWalletProvider *kwallet_provider = NULL; + PurpleKWalletPlugin::ClearRequest *request = NULL; + task = g_task_new(G_OBJECT(provider), cancellable, callback, data); + key = purple_kwallet_provider_account_key(account); + request = new PurpleKWalletPlugin::ClearRequest(key, task); + kwallet_provider = PURPLE_KWALLET_PROVIDER(provider); + kwallet_provider->engine->enqueue(request); +purple_kwallet_clear_password_finish(PurpleCredentialProvider *provider, + GAsyncResult *result, GError **error) + return g_task_propagate_boolean(G_TASK(result), error); +/****************************************************************************** + * GObject Implementation + *****************************************************************************/ +purple_kwallet_provider_dispose(GObject *obj) { + PurpleKWalletProvider *provider = PURPLE_KWALLET_PROVIDER(obj); + if(provider->engine != NULL) { + provider->engine->close(); + G_OBJECT_CLASS(purple_kwallet_provider_parent_class)->dispose(obj); +purple_kwallet_provider_finalize(GObject *obj) { + PurpleKWalletProvider *provider = PURPLE_KWALLET_PROVIDER(obj); + if(provider->engine != NULL) { + delete provider->engine; + provider->engine = NULL; + G_OBJECT_CLASS(purple_kwallet_provider_parent_class)->finalize(obj); +purple_kwallet_provider_init(PurpleKWalletProvider *provider) { + provider->engine = new PurpleKWalletPlugin::Engine(); +purple_kwallet_provider_class_init(PurpleKWalletProviderClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleCredentialProviderClass *provider_class = NULL; + provider_class = PURPLE_CREDENTIAL_PROVIDER_CLASS(klass); + obj_class->dispose = purple_kwallet_provider_dispose; + obj_class->finalize = purple_kwallet_provider_finalize; + provider_class->activate = purple_kwallet_provider_activate; + provider_class->deactivate = purple_kwallet_provider_deactivate; + provider_class->read_password_async = purple_kwallet_read_password_async; + provider_class->read_password_finish = purple_kwallet_read_password_finish; + provider_class->write_password_async = purple_kwallet_write_password_async; + provider_class->write_password_finish = + purple_kwallet_write_password_finish; + provider_class->clear_password_async = purple_kwallet_clear_password_async; + provider_class->clear_password_finish = + purple_kwallet_clear_password_finish; +purple_kwallet_provider_class_finalize(PurpleKWalletProviderClass *klass) { +/****************************************************************************** + *****************************************************************************/ +static PurpleCredentialProvider * +purple_kwallet_provider_new(void) { + return PURPLE_CREDENTIAL_PROVIDER(g_object_new( + PURPLE_KWALLET_TYPE_PROVIDER, + "description", _("A credentials management application for the KDE " + "Software Compilation desktop environment"), +/****************************************************************************** + *****************************************************************************/ +static GPluginPluginInfo * +kwallet_query(G_GNUC_UNUSED GError **error) { + const gchar * const authors[] = { + "Pidgin Developers <devel@pidgin.im>", + return GPLUGIN_PLUGIN_INFO(purple_plugin_info_new( + "id", "keyring-kwallet", + "version", DISPLAY_VERSION, + "category", N_("Keyring"), + "summary", "KWallet Keyring Plugin", + "description", N_("This plugin will store passwords in KWallet."), + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", PURPLE_PLUGIN_INFO_FLAGS_INTERNAL | + PURPLE_PLUGIN_INFO_FLAGS_AUTO_LOAD, +kwallet_load(GPluginPlugin *plugin, GError **error) { + PurpleCredentialManager *manager = NULL; + purple_kwallet_provider_register_type(G_TYPE_MODULE(plugin)); + qCoreApp = new QCoreApplication(argc, NULL); + qCoreApp->setApplicationName(purple_kwallet_get_ui_name()); + if(!KWallet::Wallet::isEnabled()) { + g_set_error(error, PURPLE_KWALLET_DOMAIN, 0, + "KWallet service is disabled."); + manager = purple_credential_manager_get_default(); + instance = purple_kwallet_provider_new(); + return purple_credential_manager_register(manager, instance, error); +kwallet_unload(G_GNUC_UNUSED GPluginPlugin *plugin, + G_GNUC_UNUSED gboolean shutdown, + PurpleCredentialManager *manager = NULL; + manager = purple_credential_manager_get_default(); + ret = purple_credential_manager_unregister(manager, instance, error); + g_clear_object(&instance); +GPLUGIN_NATIVE_PLUGIN_DECLARE(kwallet) --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins/kwallet/purplekwallet.h Mon Nov 15 02:23:25 2021 -0600
@@ -0,0 +1,94 @@
+ * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License along with + * this library; if not, see <https://www.gnu.org/licenses/>. +#define PURPLE_KWALLET_TYPE_PROVIDER (purple_kwallet_provider_get_type()) +G_DECLARE_FINAL_TYPE(PurpleKWalletProvider, purple_kwallet_provider, + PURPLE_KWALLET, PROVIDER, PurpleCredentialProvider) +namespace PurpleKWalletPlugin { + Request(QString key, GTask *task); + virtual ~Request(void); + virtual void execute(KWallet::Wallet *wallet) = 0; + virtual void cancel(QString reason) = 0; +class ReadRequest : public Request { + ReadRequest(QString key, GTask *task); + void execute(KWallet::Wallet *wallet); + void cancel(QString reason); +class WriteRequest : public Request { + WriteRequest(QString key, GTask *task, QString password); + void execute(KWallet::Wallet *wallet); + void cancel(QString reason); +class ClearRequest : public Request { + ClearRequest(QString key, GTask *task); + void execute(KWallet::Wallet *wallet); + void cancel(QString reason); +class Engine : public QObject { + void enqueue(Request *request); + void opened(bool opened); + void processQueue(void); + KWallet::Wallet *wallet; + QQueue<Request *> queue; --- a/libpurple/plugins/meson.build Mon Nov 15 02:21:18 2021 -0600
+++ b/libpurple/plugins/meson.build Mon Nov 15 02:23:25 2021 -0600
@@ -1,4 +1,5 @@
subdir('notification-sound')
autoaccept = library('autoaccept', 'autoaccept.c',
--- a/po/POTFILES.in Mon Nov 15 02:21:18 2021 -0600
+++ b/po/POTFILES.in Mon Nov 15 02:23:25 2021 -0600
@@ -61,9 +61,9 @@
libpurple/plugins/joinpart.c
libpurple/plugins/keyrings/internalkeyring.c
-libpurple/plugins/keyrings/kwallet/purplekwallet.cpp
libpurple/plugins/keyrings/secretservice.c
libpurple/plugins/keyrings/wincred.c
+libpurple/plugins/kwallet/purplekwallet.cpp libpurple/plugins/notification-sound/notification-sound.c
libpurple/plugins/psychic.c
libpurple/plugins/purple-toast.c