--- a/libpurple/plugins/keyrings/kwallet/purplekwallet.cpp Fri Mar 19 02:47:40 2021 -0500 +++ b/libpurple/plugins/keyrings/kwallet/purplekwallet.cpp Mon Mar 22 04:08:31 2021 -0500 @@ -1,9 +1,5 @@ -/** - * @file kwallet.cpp KWallet password storage - * @ingroup plugins - */ - -/* purple +/* + * purple * * 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 @@ -19,390 +15,46 @@ * 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 program ; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * 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.h> #include <glib/gi18n-lib.h> #include <purple.h> -#include <QQueue> #include <QCoreApplication> +#include <kwallet.h> + #include "purplekwallet.h" -#define KWALLET_NAME N_("KWallet") -#define KWALLET_DESCRIPTION N_("This plugin will store passwords in KWallet.") -#define KWALLET_AUTHORS { "QuLogic (qulogic[at]pidgin.im)", NULL } -#define KWALLET_ID "keyring-kwallet" -#define KWALLET_DOMAIN (g_quark_from_static_string(KWALLET_ID)) - -#define KWALLET_WALLET_NAME KWallet::Wallet::NetworkWallet() -#define KWALLET_APP_NAME "Libpurple" -#define KWALLET_FOLDER_NAME "libpurple" - -PurpleKeyring *keyring_handler = NULL; -QCoreApplication *qCoreApp = NULL; - -static gboolean -kwallet_is_enabled(void) -{ - return KWallet::Wallet::isEnabled() ? TRUE : FALSE; -} - -KWalletPlugin::engine *KWalletPlugin::engine::pinstance = NULL; - -KWalletPlugin::request::~request() -{ -} - -void -KWalletPlugin::request::abort() -{ - detailedAbort(PURPLE_KEYRING_ERROR_CANCELLED); -} - -KWalletPlugin::engine::engine() -{ - connected = false; - failed = false; - closing = false; - externallyClosed = false; - wallet = NULL; - busy = false; - closeAfterBusy = false; - - reopenWallet(); -} - -void -KWalletPlugin::engine::reopenWallet() -{ - if (closing) { - purple_debug_error("keyring-kwallet", - "wallet is closing right now\n"); - failed = true; - return; - } - - connected = false; - failed = false; - externallyClosed = false; - - wallet = KWallet::Wallet::openWallet(KWALLET_WALLET_NAME, 0, - KWallet::Wallet::Asynchronous); - if (wallet == NULL) { - failed = true; - purple_debug_error("keyring-kwallet", - "failed opening a wallet\n"); - return; - } - - failed |= !connect(wallet, SIGNAL(walletClosed()), - SLOT(walletClosed())); - failed |= !connect(wallet, SIGNAL(walletOpened(bool)), - SLOT(walletOpened(bool))); - if (failed) { - purple_debug_error("keyring-kwallet", - "failed connecting to wallet signal\n"); - } -} - -KWalletPlugin::engine::~engine() -{ - closing = true; - - abortAll(); - - delete wallet; +/****************************************************************************** + * Globals + *****************************************************************************/ +static QCoreApplication *qCoreApp = NULL; +static PurpleCredentialProvider *instance = NULL; - if (pinstance == this) - pinstance = NULL; -} - -void -KWalletPlugin::engine::abortAll() -{ - int abortedCount = 0; - - while (!isEmpty()) { - request *req = dequeue(); - req->abort(); - delete req; - abortedCount++; - } - - if (abortedCount > 0) { - purple_debug_info("keyring-kwallet", "aborted requests: %d\n", - abortedCount); - } -} - -KWalletPlugin::engine * -KWalletPlugin::engine::instance(bool create) -{ - if (pinstance == NULL && create) - pinstance = new engine; - return pinstance; -} +#define PURPLE_KWALLET_DOMAIN (g_quark_from_static_string("purple-kwallet")) +#define PURPLE_KWALLET_WALLET_NAME (KWallet::Wallet::NetworkWallet()) -void -KWalletPlugin::engine::closeInstance(void) -{ - if (pinstance == NULL) - return; - if (pinstance->closing) - return; - if (pinstance->busy) { - purple_debug_misc("keyring-kwallet", - "current instance is busy, will be freed later\n"); - pinstance->closeAfterBusy = true; - } else - delete pinstance; - pinstance = NULL; -} - -void -KWalletPlugin::engine::walletOpened(bool opened) -{ - connected = opened; - - if (!opened) { - purple_debug_warning("keyring-kwallet", - "failed to open a wallet\n"); - delete this; - return; - } - - if (!wallet->hasFolder(KWALLET_FOLDER_NAME)) { - if (!wallet->createFolder(KWALLET_FOLDER_NAME)) { - purple_debug_error("keyring-kwallet", - "couldn't create \"" KWALLET_FOLDER_NAME - "\" folder in wallet\n"); - failed = true; - } - } - if (!failed) - wallet->setFolder(KWALLET_FOLDER_NAME); - - executeRequests(); -} - -void -KWalletPlugin::engine::walletClosed() -{ - if (!closing) { - purple_debug_info("keyring-kwallet", - "wallet was externally closed\n"); - externallyClosed = true; - delete wallet; - wallet = NULL; - } -} - -void -KWalletPlugin::engine::queue(request *req) -{ - enqueue(req); - executeRequests(); -} +struct _PurpleKWalletProvider { + PurpleCredentialProvider parent; -void -KWalletPlugin::engine::executeRequests() -{ - if (closing || busy) - return; - busy = true; - if (externallyClosed) { - reopenWallet(); - } else if (connected || failed) { - while (!isEmpty()) { - request *req = dequeue(); - if (connected) - req->execute(wallet); - else - req->abort(); - delete req; - } - } else if (purple_debug_is_verbose()) { - purple_debug_misc("keyring-kwallet", "not yet connected\n"); - } - busy = false; - if (closeAfterBusy) { - purple_debug_misc("keyring-kwallet", - "instance freed after being busy\n"); - delete this; - } -} - -KWalletPlugin::save_request::save_request(PurpleAccount *acc, const char *pw, - PurpleKeyringSaveCallback cb, void *userdata) -{ - account = acc; - data = userdata; - callback = cb; - password = QString(pw); - noPassword = (pw == NULL); -} - -KWalletPlugin::read_request::read_request(PurpleAccount *acc, - PurpleKeyringReadCallback cb, void *userdata) -{ - account = acc; - data = userdata; - callback = cb; - password = QString(); -} + PurpleKWalletPlugin::Engine *engine; +}; -void -KWalletPlugin::save_request::detailedAbort(enum PurpleKeyringError error) -{ - GError *gerror; - if (callback == NULL) - return; - - gerror = g_error_new(PURPLE_KEYRING_ERROR, error, - _("Failed to save password.")); - callback(account, gerror, data); - g_error_free(gerror); -} - -void -KWalletPlugin::read_request::detailedAbort(enum PurpleKeyringError error) -{ - GError *gerror; - if (callback == NULL) - return; - - gerror = g_error_new(PURPLE_KEYRING_ERROR, error, - _("Failed to read password.")); - callback(account, NULL, gerror, data); - g_error_free(gerror); -} - -static QString -kwallet_account_key(PurpleAccount *account) -{ - return QString(purple_account_get_protocol_id(account)) + ":" + - purple_account_get_username(account); -} - -void -KWalletPlugin::read_request::execute(KWallet::Wallet *wallet) -{ - int result; - - g_return_if_fail(wallet != NULL); - - result = wallet->readPassword(kwallet_account_key(account), password); - - if (result != 0) { - purple_debug_warning("keyring-kwallet", - "failed to read password, result was %d\n", result); - abort(); - return; - } +G_DEFINE_DYNAMIC_TYPE(PurpleKWalletProvider, purple_kwallet_provider, + PURPLE_TYPE_CREDENTIAL_PROVIDER) - purple_debug_misc("keyring-kwallet", - "Got password for account %s (%s).\n", - purple_account_get_username(account), - purple_account_get_protocol_id(account)); - - if (callback != NULL) - callback(account, password.toUtf8().constData(), NULL, data); -} - -void -KWalletPlugin::save_request::execute(KWallet::Wallet *wallet) -{ - int result; - - g_return_if_fail(wallet != NULL); - - if (noPassword) - result = wallet->removeEntry(kwallet_account_key(account)); - else { - result = wallet->writePassword(kwallet_account_key(account), - password); - } - - if (result != 0) { - purple_debug_warning("keyring-kwallet", - "failed to write password, result was %d\n", result); - abort(); - return; - } - - purple_debug_misc("keyring-kwallet", - "Password %s for account %s (%s).\n", - (noPassword ? "removed" : "saved"), - purple_account_get_username(account), - purple_account_get_protocol_id(account)); - - if (callback != NULL) - callback(account, NULL, data); -} - -extern "C" -{ - -static void -kwallet_read(PurpleAccount *account, PurpleKeyringReadCallback cb, - gpointer data) -{ - KWalletPlugin::read_request *req = - new KWalletPlugin::read_request(account, cb, data); - - if (KWallet::Wallet::keyDoesNotExist(KWALLET_WALLET_NAME, - KWALLET_FOLDER_NAME, kwallet_account_key(account))) - { - req->detailedAbort(PURPLE_KEYRING_ERROR_NOPASSWORD); - delete req; - } - else - KWalletPlugin::engine::instance(true)->queue(req); -} - -static void -kwallet_save(PurpleAccount *account, const char *password, - PurpleKeyringSaveCallback cb, gpointer data) -{ - if (password == NULL && KWallet::Wallet::keyDoesNotExist( - KWALLET_WALLET_NAME, KWALLET_FOLDER_NAME, - kwallet_account_key(account))) - { - if (cb != NULL) - cb(account, NULL, data); - } - else - KWalletPlugin::engine::instance(true)->queue( - new KWalletPlugin::save_request(account, password, cb, - data)); -} - -static void -kwallet_cancel(void) -{ - KWalletPlugin::engine *instance = - KWalletPlugin::engine::instance(false); - if (instance) - instance->abortAll(); -} - -static void * -kwallet_get_handle(void) -{ - static int handle; - - return &handle; -} - -static const char *kwallet_get_ui_name(void) -{ +/****************************************************************************** + * Helpers + *****************************************************************************/ +static QString +purple_kwallet_get_ui_name(void) { PurpleUiInfo *ui_info = NULL; - const char *ui_name = NULL; + QString ui_name = NULL; ui_info = purple_core_get_ui_info(); if(PURPLE_IS_UI_INFO(ui_info)) { @@ -410,92 +62,551 @@ g_object_unref(G_OBJECT(ui_info)); } - if(ui_name == NULL) { - ui_name = KWALLET_APP_NAME; + if(ui_name.isEmpty()) { + ui_name = "libpurple"; } return ui_name; } -static PurplePluginInfo * -plugin_query(GError **error) +static QString +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->key = key; + 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) { +} + +void +PurpleKWalletPlugin::ReadRequest::execute(KWallet::Wallet *wallet) { + QString password; + int result = 0; + bool missing; + + missing = KWallet::Wallet::keyDoesNotExist(PURPLE_KWALLET_WALLET_NAME, + purple_kwallet_get_ui_name(), + key); + + if(missing) { + g_task_return_new_error(this->task, PURPLE_KWALLET_DOMAIN, 0, + "no password stored"); + + g_clear_object(&this->task); + + return; + } + + result = wallet->readPassword(this->key, password); + + if(result != 0) { + g_task_return_new_error(this->task, PURPLE_KWALLET_DOMAIN, result, + _("failed to read password, kwallet responded " + "with error code %d"), result); + } else { + gchar *c_password = g_strdup(password.toUtf8().constData()); + g_task_return_pointer(this->task, c_password, g_free); + } + + g_clear_object(&this->task); +} + +void +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; +} + +void +PurpleKWalletPlugin::WriteRequest::execute(KWallet::Wallet *wallet) { + int result; + + result = wallet->writePassword(this->key, this->password); + + if(result != 0) { + g_task_return_new_error(this->task, PURPLE_KWALLET_DOMAIN, result, + _("failed to write password, kwallet " + "responded with error code %d"), result); + } else { + g_task_return_boolean(this->task, TRUE); + } + + g_clear_object(&this->task); +} + +void +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) { +} + +void +PurpleKWalletPlugin::ClearRequest::execute(KWallet::Wallet *wallet) { + int result; + + result = wallet->removeEntry(this->key); + + if(result != 0) { + g_task_return_new_error(this->task, PURPLE_KWALLET_DOMAIN, result, + _("failed to clear password, kwallet " + "responded with error code %d"), result); + } else { + g_task_return_boolean(this->task, TRUE); + } + + g_clear_object(&this->task); +} + +void +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->failed = false; +} + +PurpleKWalletPlugin::Engine::~Engine(void) { + this->close(); +} + +void +PurpleKWalletPlugin::Engine::open(void) { + purple_debug_misc("kwallet-provider", "attempting to open wallet"); + + if(this->connected) { + purple_debug_misc("kwallet-provider", "wallet already opened"); + + return; + } + + // Reset our externallyClosed and failed states. + this->externallyClosed = false; + this->failed = false; + + // No need to check this pointer as an async open always returns non-null. + this->wallet = KWallet::Wallet::openWallet(PURPLE_KWALLET_WALLET_NAME, + 0, + KWallet::Wallet::Asynchronous); + + this->failed |= !QObject::connect(this->wallet, SIGNAL(walletOpened(bool)), + SLOT(opened(bool))); + this->failed |= !QObject::connect(this->wallet, SIGNAL(walletClosed(void)), + SLOT(closed())); + + if(this->failed) { + purple_debug_error("kwallet-provider", + "Failed to connect KWallet signals"); + } +} + +void +PurpleKWalletPlugin::Engine::close(void) { + while(!this->queue.isEmpty()) { + PurpleKWalletPlugin::Request *request = this->queue.dequeue(); + + request->cancel("wallet is closing"); + + delete request; + } + + if(this->wallet != NULL) { + delete this->wallet; + this->wallet = NULL; + } + + this->connected = false; + this->failed = false; +} + +void +PurpleKWalletPlugin::Engine::enqueue(PurpleKWalletPlugin::Request *request) { + this->queue.enqueue(request); + + processQueue(); +} + +void +PurpleKWalletPlugin::Engine::opened(bool opened) { + QString folder_name; + + if(!opened) { + purple_debug_error("kwallet-provider", "failed to open wallet"); + + delete this->wallet; + this->wallet = NULL; + + this->connected = false; + this->failed = true; + + return; + } + + // Handle the case where the wallet opened signal connected, but the wallet + // closed signal failed to connect. + if(this->failed) { + purple_debug_error("kwallet-provider", + "wallet opened, but failed to connect the wallet " + "closed signal"); + return; + } + + this->connected = true; + + // setup our folder + 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()); + this->failed = true; + } + } + + if(!this->failed && !this->wallet->setFolder(folder_name)) { + purple_debug_error("kwallet-provider", "failed to set folder to %s", + folder_name.toUtf8().constData()); + this->failed = true; + } + + purple_debug_misc("kwallet-provider", "successfully opened the wallet"); + + processQueue(); +} + +void +PurpleKWalletPlugin::Engine::closed(void) { + purple_debug_misc("kwallet-provider", "the wallet was closed externally"); + + this->externallyClosed = true; + this->close(); +} + +void +PurpleKWalletPlugin::Engine::processQueue() { + if(this->externallyClosed && this->queue.isEmpty() == false) { + this->open(); + } else if(this->connected || this->failed) { + while(!this->queue.isEmpty()) { + PurpleKWalletPlugin::Request *request = this->queue.dequeue(); + + if(this->failed) { + request->cancel(_("failed to open kwallet")); + } else { + request->execute(this->wallet); + } + + delete request; + } + } +} + +/****************************************************************************** + * PurpleCredentialProvider Implementation + *****************************************************************************/ +static void +purple_kwallet_provider_activate(PurpleCredentialProvider *provider) { + PurpleKWalletProvider *kwallet_provider = NULL; + + kwallet_provider = PURPLE_KWALLET_PROVIDER(provider); + + kwallet_provider->engine->open(); +} + +static void +purple_kwallet_provider_deactivate(PurpleCredentialProvider *provider) { + PurpleKWalletProvider *kwallet_provider = NULL; + + kwallet_provider = PURPLE_KWALLET_PROVIDER(provider); + + kwallet_provider->engine->close(); +} + +static void +purple_kwallet_read_password_async(PurpleCredentialProvider *provider, + PurpleAccount *account, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer data) { - const gchar * const authors[] = KWALLET_AUTHORS; + PurpleKWalletProvider *kwallet_provider = NULL; + PurpleKWalletPlugin::ReadRequest *request = NULL; + GTask *task = NULL; + QString key; + + 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); + + g_clear_object(&task); +} + +static gchar * +purple_kwallet_read_password_finish(PurpleCredentialProvider *provider, + GAsyncResult *result, GError **error) +{ + return (gchar *)g_task_propagate_pointer(G_TASK(result), error); +} + +static void +purple_kwallet_write_password_async(PurpleCredentialProvider *provider, + PurpleAccount *account, + const gchar *password, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer data) +{ + PurpleKWalletProvider *kwallet_provider = NULL; + PurpleKWalletPlugin::WriteRequest *request = NULL; + GTask *task = NULL; + QString key; + + 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); + + g_clear_object(&task); +} + +static gboolean +purple_kwallet_write_password_finish(PurpleCredentialProvider *provider, + GAsyncResult *result, GError **error) +{ + return g_task_propagate_boolean(G_TASK(result), error); +} + +static void +purple_kwallet_clear_password_async(PurpleCredentialProvider *provider, + PurpleAccount *account, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer data) +{ + PurpleKWalletProvider *kwallet_provider = NULL; + PurpleKWalletPlugin::ClearRequest *request = NULL; + GTask *task = NULL; + QString key; + + 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); + + g_clear_object(&task); +} + +static gboolean +purple_kwallet_clear_password_finish(PurpleCredentialProvider *provider, + GAsyncResult *result, GError **error) +{ + return g_task_propagate_boolean(G_TASK(result), error); +} - return purple_plugin_info_new( - "id", KWALLET_ID, - "name", KWALLET_NAME, +/****************************************************************************** + * GObject Implementation + *****************************************************************************/ +static void +purple_kwallet_provider_dispose(GObject *obj) { + PurpleKWalletProvider *provider = PURPLE_KWALLET_PROVIDER(obj); + + delete provider->engine; + provider->engine = NULL; + + G_OBJECT_CLASS(purple_kwallet_provider_parent_class)->dispose(obj); +} + +static void +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); +} + +static void +purple_kwallet_provider_init(PurpleKWalletProvider *provider) { + provider->engine = new PurpleKWalletPlugin::Engine(); +} + +static void +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; +} + +static void +purple_kwallet_provider_class_finalize(PurpleKWalletProviderClass *klass) { +} + +/****************************************************************************** + * API + *****************************************************************************/ +static PurpleCredentialProvider * +purple_kwallet_provider_new(void) { + return PURPLE_CREDENTIAL_PROVIDER(g_object_new( + PURPLE_KWALLET_TYPE_PROVIDER, + "id", "kwallet", + "name", _("KWallet"), + "description", _("A credentials management application for the KDE " + "Software Compilation desktop environment"), + NULL + )); +} + +/****************************************************************************** + * Plugin Exports + *****************************************************************************/ +G_BEGIN_DECLS + +G_MODULE_EXPORT GPluginPluginInfo * +gplugin_query(GError **error) { + const gchar * const authors[] = { + "Pidgin Developers <devel@pidgin.im>", + NULL + }; + + return GPLUGIN_PLUGIN_INFO(purple_plugin_info_new( + "id", "keyring-kwallet", + "name", N_("KWallet"), "version", DISPLAY_VERSION, "category", N_("Keyring"), "summary", "KWallet Keyring Plugin", - "description", KWALLET_DESCRIPTION, + "description", N_("This plugin will store passwords in KWallet."), "authors", authors, "website", PURPLE_WEBSITE, "abi-version", PURPLE_ABI_VERSION, "flags", PURPLE_PLUGIN_INFO_FLAGS_INTERNAL, - NULL - ); + )); } -static gboolean -plugin_load(PurplePlugin *plugin, GError **error) -{ - if (!qCoreApp) { +G_MODULE_EXPORT gboolean +gplugin_load(GPluginPlugin *plugin, GError **error) { + PurpleCredentialManager *manager = NULL; + + purple_kwallet_provider_register_type(G_TYPE_MODULE(plugin)); + + if(qCoreApp == NULL) { int argc = 0; qCoreApp = new QCoreApplication(argc, NULL); - qCoreApp->setApplicationName(kwallet_get_ui_name()); + qCoreApp->setApplicationName(purple_kwallet_get_ui_name()); } - if (!kwallet_is_enabled()) { - g_set_error(error, KWALLET_DOMAIN, 0, "KWallet service is disabled."); - purple_debug_info("keyring-kwallet", - "KWallet service is disabled\n"); + if(!KWallet::Wallet::isEnabled()) { + g_set_error(error, PURPLE_KWALLET_DOMAIN, 0, + "KWallet service is disabled."); + return FALSE; } - keyring_handler = purple_keyring_new(); + manager = purple_credential_manager_get_default(); + + instance = purple_kwallet_provider_new(); + + return purple_credential_manager_register_provider(manager, instance, + error); +} + +G_MODULE_EXPORT gboolean +gplugin_unload(GPluginPlugin *plugin, GError **error) { + PurpleCredentialManager *manager = NULL; + gboolean ret = FALSE; - purple_keyring_set_name(keyring_handler, _(KWALLET_NAME)); - purple_keyring_set_id(keyring_handler, KWALLET_ID); - purple_keyring_set_read_password(keyring_handler, kwallet_read); - purple_keyring_set_save_password(keyring_handler, kwallet_save); - purple_keyring_set_cancel_requests(keyring_handler, kwallet_cancel); - purple_keyring_set_close_keyring(keyring_handler, - KWalletPlugin::engine::closeInstance); + manager = purple_credential_manager_get_default(); + ret = purple_credential_manager_unregister_provider(manager, instance, + error); - purple_keyring_register(keyring_handler); + if(!ret) { + return ret; + } + + if(qCoreApp != NULL) { + delete qCoreApp; + qCoreApp = NULL; + } + + g_clear_object(&instance); return TRUE; } -static gboolean -plugin_unload(PurplePlugin *plugin, GError **error) -{ - if (purple_keyring_get_inuse() == keyring_handler) { - g_set_error(error, KWALLET_DOMAIN, 0, "The keyring is currently " - "in use."); - purple_debug_warning("keyring-kwallet", - "keyring in use, cannot unload\n"); - return FALSE; - } - - purple_signals_disconnect_by_handle(kwallet_get_handle()); - - KWalletPlugin::engine::closeInstance(); - - purple_keyring_unregister(keyring_handler); - purple_keyring_free(keyring_handler); - keyring_handler = NULL; - - if (qCoreApp) { - delete qCoreApp; - qCoreApp = NULL; - } - - return TRUE; -} - -PURPLE_PLUGIN_INIT(kwallet_keyring, plugin_query, plugin_load, plugin_unload); - -} /* extern "C" */ +G_END_DECLS