--- a/libpurple/plugins/keyrings/meson.build Fri Dec 10 00:33:15 2021 -0600
+++ b/libpurple/plugins/keyrings/meson.build Fri Dec 10 01:44:32 2021 -0600
@@ -7,14 +7,6 @@
install : false, install_dir : PURPLE_PLUGINDIR)
- wincred_plugin = library('wincred', 'wincred.c',
- c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="Purple-WinCredKeyring"'],
- dependencies : [libpurple_dep],
- install : true, install_dir : PURPLE_PLUGINDIR)
-if nettle.found() or secretservice.found() or IS_WIN32
+if nettle.found() or secretservice.found() devenv.append('PURPLE_PLUGIN_PATH', meson.current_build_dir())
--- a/libpurple/plugins/keyrings/wincred.c Fri Dec 10 00:33:15 2021 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,432 +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 program ; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-#include <glib/gi18n-lib.h>
-#include <gplugin-native.h>
-#define WINCRED_ID "keyring-wincred"
-#define WINCRED_NAME N_("Windows credentials")
-#define WINCRED_DESCRIPTION N_("The built-in credential manager for Windows.")
-#define WINCRED_MAX_TARGET_NAME 256
-/******************************************************************************
- *****************************************************************************/
-static PurpleCredentialProvider *instance = NULL;
-#define PURPLE_TYPE_WINCRED (purple_wincred_get_type())
-G_DECLARE_FINAL_TYPE(PurpleWinCred, purple_wincred, PURPLE, SECRET_SERVICE,
- PurpleCredentialProvider)
- PurpleCredentialProvider parent;
-#define PURPLE_WINCRED_ERROR (g_quark_from_static_string("wincred"))
-G_DEFINE_DYNAMIC_TYPE(PurpleWinCred, purple_wincred,
- PURPLE_TYPE_CREDENTIAL_PROVIDER)
-/******************************************************************************
- * PurpleCredentialProvider Implementation
- *****************************************************************************/
-wincred_get_target_name(PurpleAccount *account, GError **error)
- gchar target_name_utf8[WINCRED_MAX_TARGET_NAME];
- gunichar2 *target_name_utf16;
- g_return_val_if_fail(account != NULL, NULL);
- g_snprintf(target_name_utf8, WINCRED_MAX_TARGET_NAME, "libpurple_%s_%s",
- purple_account_get_protocol_id(account),
- purple_account_get_username(account));
- g_utf8_to_utf16(target_name_utf8, -1, NULL, NULL, error);
- if (target_name_utf16 == NULL) {
- purple_debug_error("keyring-wincred", "Couldn't convert target name");
- return target_name_utf16;
-purple_wincred_read_password_async(PurpleCredentialProvider *provider,
- PurpleAccount *account,
- GCancellable *cancellable,
- GAsyncReadyCallback callback, gpointer data)
- gunichar2 *target_name = NULL;
- gchar *password = NULL;
- PCREDENTIALW credential = NULL;
- task = g_task_new(G_OBJECT(provider), cancellable, callback, data);
- target_name = wincred_get_target_name(account, &error);
- if (target_name == NULL) {
- g_task_return_error(task, error);
- g_object_unref(G_OBJECT(task));
- if (!CredReadW(target_name, CRED_TYPE_GENERIC, 0, &credential)) {
- DWORD error_code = GetLastError();
- if (error_code == ERROR_NOT_FOUND) {
- if (purple_debug_is_verbose()) {
- purple_debug_misc("keyring-wincred",
- "No password found for account %s\n",
- purple_account_get_username(account));
- error = g_error_new(PURPLE_WINCRED_ERROR,
- _("Password not found."));
- } else if (error_code == ERROR_NO_SUCH_LOGON_SESSION) {
- purple_debug_error("keyring-wincred",
- "Cannot read password, no valid logon "
- error = g_error_new(PURPLE_WINCRED_ERROR,
- _("Cannot read password, no valid logon "
- purple_debug_error("keyring-wincred",
- "Cannot read password, error %lx\n",
- error = g_error_new(PURPLE_WINCRED_ERROR,
- _("Cannot read password (error %lx)."), error_code);
- g_task_return_error(task, error);
- g_object_unref(G_OBJECT(task));
- password = g_utf16_to_utf8((gunichar2*)credential->CredentialBlob,
- credential->CredentialBlobSize / sizeof(gunichar2),
- memset(credential->CredentialBlob, 0, credential->CredentialBlobSize);
- if (password == NULL) {
- purple_debug_error("keyring-wincred",
- "Cannot convert password\n");
- error = g_error_new(PURPLE_WINCRED_ERROR,
- _("Cannot read password (unicode error)."));
- g_task_return_error(task, error);
- g_object_unref(G_OBJECT(task));
- purple_debug_misc("keyring-wincred",
- _("Got password for account %s.\n"),
- purple_account_get_username(account));
- g_task_return_pointer(task, password, g_free);
- g_object_unref(G_OBJECT(task));
-purple_wincred_read_password_finish(PurpleCredentialProvider *provider,
- GAsyncResult *result, GError **error)
- g_return_val_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider), FALSE);
- g_return_val_if_fail(G_IS_ASYNC_RESULT(result), FALSE);
- return g_task_propagate_pointer(G_TASK(result), error);
-purple_wincred_write_password_async(PurpleCredentialProvider *provider,
- PurpleAccount *account,
- GCancellable *cancellable,
- GAsyncReadyCallback callback, gpointer data)
- gunichar2 *target_name = NULL;
- gunichar2 *username_utf16 = NULL;
- gunichar2 *password_utf16 = NULL;
- glong password_len = 0;
- CREDENTIALW credential;
- task = g_task_new(G_OBJECT(provider), cancellable, callback, data);
- target_name = wincred_get_target_name(account, &error);
- if (target_name == NULL) {
- g_task_return_error(task, error);
- g_object_unref(G_OBJECT(task));
- username_utf16 = g_utf8_to_utf16(purple_account_get_username(account), -1,
- if (username_utf16 == NULL) {
- purple_debug_error("keyring-wincred", "Couldn't convert username");
- g_task_return_error(task, error);
- g_object_unref(G_OBJECT(task));
- password_utf16 = g_utf8_to_utf16(password, -1, NULL, &password_len, &error);
- if (password_utf16 == NULL) {
- g_free(username_utf16);
- purple_debug_error("keyring-wincred", "Couldn't convert password");
- g_task_return_error(task, error);
- g_object_unref(G_OBJECT(task));
- memset(&credential, 0, sizeof(CREDENTIALW));
- credential.Type = CRED_TYPE_GENERIC;
- credential.TargetName = target_name;
- credential.CredentialBlobSize = password_len * sizeof(gunichar2);
- credential.CredentialBlob = (LPBYTE)password_utf16;
- credential.Persist = CRED_PERSIST_LOCAL_MACHINE;
- credential.UserName = username_utf16;
- if (!CredWriteW(&credential, 0)) {
- DWORD error_code = GetLastError();
- if (error_code == ERROR_NO_SUCH_LOGON_SESSION) {
- purple_debug_error("keyring-wincred",
- "Cannot store password, no valid logon session");
- PURPLE_WINCRED_ERROR, error_code,
- _("Cannot remove password, no valid logon session."));
- purple_debug_error("keyring-wincred",
- "Cannot store password, error %lx\n",
- error = g_error_new(PURPLE_WINCRED_ERROR, error_code,
- _("Cannot store password (error %lx)."), error_code);
- purple_debug_misc("keyring-wincred", "Password updated for account %s.",
- purple_account_get_username(account));
- g_free(username_utf16);
- g_free(password_utf16);
- g_task_return_error(task, error);
- g_task_return_boolean(task, TRUE);
- g_object_unref(G_OBJECT(task));
-purple_wincred_write_password_finish(PurpleCredentialProvider *provider,
- GAsyncResult *result, GError **error)
- g_return_val_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider), FALSE);
- g_return_val_if_fail(G_IS_ASYNC_RESULT(result), FALSE);
- return g_task_propagate_boolean(G_TASK(result), error);
-purple_wincred_clear_password_async(PurpleCredentialProvider *provider,
- PurpleAccount *account,
- GCancellable *cancellable,
- GAsyncReadyCallback callback, gpointer data)
- gunichar2 *target_name = NULL;
- task = g_task_new(G_OBJECT(provider), cancellable, callback, data);
- target_name = wincred_get_target_name(account, &error);
- if (target_name == NULL) {
- g_task_return_error(task, error);
- g_object_unref(G_OBJECT(task));
- if (CredDeleteW(target_name, CRED_TYPE_GENERIC, 0)) {
- purple_debug_misc("keyring-wincred", "Password for account %s removed",
- purple_account_get_username(account));
- g_task_return_boolean(task, TRUE);
- DWORD error_code = GetLastError();
- if (error_code == ERROR_NOT_FOUND) {
- /* If there was no password we just return TRUE. */
- g_task_return_boolean(task, TRUE);
- if (error_code == ERROR_NO_SUCH_LOGON_SESSION) {
- "Cannot remove password, no valid logon session");
- PURPLE_WINCRED_ERROR, error_code,
- _("Cannot remove password, no valid logon session."));
- purple_debug_error("keyring-wincred",
- "Cannot remove password, error %lx", error_code);
- PURPLE_WINCRED_ERROR, error_code,
- _("Cannot remove password (error %lx)."), error_code);
- g_task_return_error(task, error);
- g_object_unref(G_OBJECT(task));
-purple_wincred_clear_password_finish(PurpleCredentialProvider *provider,
- GAsyncResult *result, GError **error)
- g_return_val_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider), FALSE);
- g_return_val_if_fail(G_IS_ASYNC_RESULT(result), FALSE);
- return g_task_propagate_boolean(G_TASK(result), error);
-/******************************************************************************
- * GObject Implementation
- *****************************************************************************/
-purple_wincred_init(PurpleWinCred *wincred)
-purple_wincred_class_init(PurpleWinCredClass *klass)
- PurpleCredentialProviderClass *provider_class = NULL;
- provider_class = PURPLE_CREDENTIAL_PROVIDER_CLASS(klass);
- provider_class->read_password_async = purple_wincred_read_password_async;
- provider_class->read_password_finish = purple_wincred_read_password_finish;
- provider_class->write_password_async = purple_wincred_write_password_async;
- provider_class->write_password_finish =
- purple_wincred_write_password_finish;
- provider_class->clear_password_async = purple_wincred_clear_password_async;
- provider_class->clear_password_finish =
- purple_wincred_clear_password_finish;
-purple_wincred_class_finalize(PurpleWinCredClass *klass)
-/******************************************************************************
- *****************************************************************************/
-static PurpleCredentialProvider *
-purple_wincred_new(void)
- return PURPLE_CREDENTIAL_PROVIDER(g_object_new(
- "name", _(WINCRED_NAME),
- "description", _(WINCRED_DESCRIPTION),
-/******************************************************************************
- *****************************************************************************/
-static GPluginPluginInfo *
-wincred_query(G_GNUC_UNUSED GError **error) {
- const gchar * const authors[] = {
- "Pidgin Developers <devel@pidgin.im>",
- return GPLUGIN_PLUGIN_INFO(purple_plugin_info_new(
- "version", DISPLAY_VERSION,
- "category", _("Keyring"),
- "summary", _("Store passwords using Windows credentials"),
- "description", _("This plugin stores passwords using Windows credentials."),
- "website", PURPLE_WEBSITE,
- "abi-version", PURPLE_ABI_VERSION,
- "flags", PURPLE_PLUGIN_INFO_FLAGS_INTERNAL |
- PURPLE_PLUGIN_INFO_FLAGS_AUTO_LOAD,
-wincred_load(GPluginPlugin *plugin, GError **error) {
- PurpleCredentialManager *manager = NULL;
- purple_wincred_register_type(G_TYPE_MODULE(plugin));
- manager = purple_credential_manager_get_default();
- instance = purple_wincred_new();
- return purple_credential_manager_register(manager, instance, error);
-wincred_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(wincred)
--- a/libpurple/plugins/meson.build Fri Dec 10 00:33:15 2021 -0600
+++ b/libpurple/plugins/meson.build Fri Dec 10 01:44:32 2021 -0600
@@ -3,6 +3,7 @@
subdir('notification-sound')
autoaccept = library('autoaccept', 'autoaccept.c',
c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="PurplePlugin-AutoAccept"'],
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins/wincred/meson.build Fri Dec 10 01:44:32 2021 -0600
@@ -0,0 +1,9 @@
+ wincred_plugin = library('wincred', 'wincred.c', + c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="Purple-WinCredKeyring"'], + dependencies : [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/wincred/wincred.c Fri Dec 10 01:44:32 2021 -0600
@@ -0,0 +1,432 @@
+ * 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 program ; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA +#include <glib/gi18n-lib.h> +#include <gplugin-native.h> +#define WINCRED_ID "keyring-wincred" +#define WINCRED_NAME N_("Windows credentials") +#define WINCRED_DESCRIPTION N_("The built-in credential manager for Windows.") +#define WINCRED_MAX_TARGET_NAME 256 +/****************************************************************************** + *****************************************************************************/ +static PurpleCredentialProvider *instance = NULL; +#define PURPLE_TYPE_WINCRED (purple_wincred_get_type()) +G_DECLARE_FINAL_TYPE(PurpleWinCred, purple_wincred, PURPLE, SECRET_SERVICE, + PurpleCredentialProvider) + PurpleCredentialProvider parent; +#define PURPLE_WINCRED_ERROR (g_quark_from_static_string("wincred")) +G_DEFINE_DYNAMIC_TYPE(PurpleWinCred, purple_wincred, + PURPLE_TYPE_CREDENTIAL_PROVIDER) +/****************************************************************************** + * PurpleCredentialProvider Implementation + *****************************************************************************/ +wincred_get_target_name(PurpleAccount *account, GError **error) + gchar target_name_utf8[WINCRED_MAX_TARGET_NAME]; + gunichar2 *target_name_utf16; + g_return_val_if_fail(account != NULL, NULL); + g_snprintf(target_name_utf8, WINCRED_MAX_TARGET_NAME, "libpurple_%s_%s", + purple_account_get_protocol_id(account), + purple_account_get_username(account)); + g_utf8_to_utf16(target_name_utf8, -1, NULL, NULL, error); + if (target_name_utf16 == NULL) { + purple_debug_error("keyring-wincred", "Couldn't convert target name"); + return target_name_utf16; +purple_wincred_read_password_async(PurpleCredentialProvider *provider, + PurpleAccount *account, + GCancellable *cancellable, + GAsyncReadyCallback callback, gpointer data) + gunichar2 *target_name = NULL; + gchar *password = NULL; + PCREDENTIALW credential = NULL; + task = g_task_new(G_OBJECT(provider), cancellable, callback, data); + target_name = wincred_get_target_name(account, &error); + if (target_name == NULL) { + g_task_return_error(task, error); + g_object_unref(G_OBJECT(task)); + if (!CredReadW(target_name, CRED_TYPE_GENERIC, 0, &credential)) { + DWORD error_code = GetLastError(); + if (error_code == ERROR_NOT_FOUND) { + if (purple_debug_is_verbose()) { + purple_debug_misc("keyring-wincred", + "No password found for account %s\n", + purple_account_get_username(account)); + error = g_error_new(PURPLE_WINCRED_ERROR, + _("Password not found.")); + } else if (error_code == ERROR_NO_SUCH_LOGON_SESSION) { + purple_debug_error("keyring-wincred", + "Cannot read password, no valid logon " + error = g_error_new(PURPLE_WINCRED_ERROR, + _("Cannot read password, no valid logon " + purple_debug_error("keyring-wincred", + "Cannot read password, error %lx\n", + error = g_error_new(PURPLE_WINCRED_ERROR, + _("Cannot read password (error %lx)."), error_code); + g_task_return_error(task, error); + g_object_unref(G_OBJECT(task)); + password = g_utf16_to_utf8((gunichar2*)credential->CredentialBlob, + credential->CredentialBlobSize / sizeof(gunichar2), + memset(credential->CredentialBlob, 0, credential->CredentialBlobSize); + if (password == NULL) { + purple_debug_error("keyring-wincred", + "Cannot convert password\n"); + error = g_error_new(PURPLE_WINCRED_ERROR, + _("Cannot read password (unicode error).")); + g_task_return_error(task, error); + g_object_unref(G_OBJECT(task)); + purple_debug_misc("keyring-wincred", + _("Got password for account %s.\n"), + purple_account_get_username(account)); + g_task_return_pointer(task, password, g_free); + g_object_unref(G_OBJECT(task)); +purple_wincred_read_password_finish(PurpleCredentialProvider *provider, + GAsyncResult *result, GError **error) + g_return_val_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider), FALSE); + g_return_val_if_fail(G_IS_ASYNC_RESULT(result), FALSE); + return g_task_propagate_pointer(G_TASK(result), error); +purple_wincred_write_password_async(PurpleCredentialProvider *provider, + PurpleAccount *account, + GCancellable *cancellable, + GAsyncReadyCallback callback, gpointer data) + gunichar2 *target_name = NULL; + gunichar2 *username_utf16 = NULL; + gunichar2 *password_utf16 = NULL; + glong password_len = 0; + CREDENTIALW credential; + task = g_task_new(G_OBJECT(provider), cancellable, callback, data); + target_name = wincred_get_target_name(account, &error); + if (target_name == NULL) { + g_task_return_error(task, error); + g_object_unref(G_OBJECT(task)); + username_utf16 = g_utf8_to_utf16(purple_account_get_username(account), -1, + if (username_utf16 == NULL) { + purple_debug_error("keyring-wincred", "Couldn't convert username"); + g_task_return_error(task, error); + g_object_unref(G_OBJECT(task)); + password_utf16 = g_utf8_to_utf16(password, -1, NULL, &password_len, &error); + if (password_utf16 == NULL) { + g_free(username_utf16); + purple_debug_error("keyring-wincred", "Couldn't convert password"); + g_task_return_error(task, error); + g_object_unref(G_OBJECT(task)); + memset(&credential, 0, sizeof(CREDENTIALW)); + credential.Type = CRED_TYPE_GENERIC; + credential.TargetName = target_name; + credential.CredentialBlobSize = password_len * sizeof(gunichar2); + credential.CredentialBlob = (LPBYTE)password_utf16; + credential.Persist = CRED_PERSIST_LOCAL_MACHINE; + credential.UserName = username_utf16; + if (!CredWriteW(&credential, 0)) { + DWORD error_code = GetLastError(); + if (error_code == ERROR_NO_SUCH_LOGON_SESSION) { + purple_debug_error("keyring-wincred", + "Cannot store password, no valid logon session"); + PURPLE_WINCRED_ERROR, error_code, + _("Cannot remove password, no valid logon session.")); + purple_debug_error("keyring-wincred", + "Cannot store password, error %lx\n", + error = g_error_new(PURPLE_WINCRED_ERROR, error_code, + _("Cannot store password (error %lx)."), error_code); + purple_debug_misc("keyring-wincred", "Password updated for account %s.", + purple_account_get_username(account)); + g_free(username_utf16); + g_free(password_utf16); + g_task_return_error(task, error); + g_task_return_boolean(task, TRUE); + g_object_unref(G_OBJECT(task)); +purple_wincred_write_password_finish(PurpleCredentialProvider *provider, + GAsyncResult *result, GError **error) + g_return_val_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider), FALSE); + g_return_val_if_fail(G_IS_ASYNC_RESULT(result), FALSE); + return g_task_propagate_boolean(G_TASK(result), error); +purple_wincred_clear_password_async(PurpleCredentialProvider *provider, + PurpleAccount *account, + GCancellable *cancellable, + GAsyncReadyCallback callback, gpointer data) + gunichar2 *target_name = NULL; + task = g_task_new(G_OBJECT(provider), cancellable, callback, data); + target_name = wincred_get_target_name(account, &error); + if (target_name == NULL) { + g_task_return_error(task, error); + g_object_unref(G_OBJECT(task)); + if (CredDeleteW(target_name, CRED_TYPE_GENERIC, 0)) { + purple_debug_misc("keyring-wincred", "Password for account %s removed", + purple_account_get_username(account)); + g_task_return_boolean(task, TRUE); + DWORD error_code = GetLastError(); + if (error_code == ERROR_NOT_FOUND) { + /* If there was no password we just return TRUE. */ + g_task_return_boolean(task, TRUE); + if (error_code == ERROR_NO_SUCH_LOGON_SESSION) { + "Cannot remove password, no valid logon session"); + PURPLE_WINCRED_ERROR, error_code, + _("Cannot remove password, no valid logon session.")); + purple_debug_error("keyring-wincred", + "Cannot remove password, error %lx", error_code); + PURPLE_WINCRED_ERROR, error_code, + _("Cannot remove password (error %lx)."), error_code); + g_task_return_error(task, error); + g_object_unref(G_OBJECT(task)); +purple_wincred_clear_password_finish(PurpleCredentialProvider *provider, + GAsyncResult *result, GError **error) + g_return_val_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider), FALSE); + g_return_val_if_fail(G_IS_ASYNC_RESULT(result), FALSE); + return g_task_propagate_boolean(G_TASK(result), error); +/****************************************************************************** + * GObject Implementation + *****************************************************************************/ +purple_wincred_init(PurpleWinCred *wincred) +purple_wincred_class_init(PurpleWinCredClass *klass) + PurpleCredentialProviderClass *provider_class = NULL; + provider_class = PURPLE_CREDENTIAL_PROVIDER_CLASS(klass); + provider_class->read_password_async = purple_wincred_read_password_async; + provider_class->read_password_finish = purple_wincred_read_password_finish; + provider_class->write_password_async = purple_wincred_write_password_async; + provider_class->write_password_finish = + purple_wincred_write_password_finish; + provider_class->clear_password_async = purple_wincred_clear_password_async; + provider_class->clear_password_finish = + purple_wincred_clear_password_finish; +purple_wincred_class_finalize(PurpleWinCredClass *klass) +/****************************************************************************** + *****************************************************************************/ +static PurpleCredentialProvider * +purple_wincred_new(void) + return PURPLE_CREDENTIAL_PROVIDER(g_object_new( + "name", _(WINCRED_NAME), + "description", _(WINCRED_DESCRIPTION), +/****************************************************************************** + *****************************************************************************/ +static GPluginPluginInfo * +wincred_query(G_GNUC_UNUSED GError **error) { + const gchar * const authors[] = { + "Pidgin Developers <devel@pidgin.im>", + return GPLUGIN_PLUGIN_INFO(purple_plugin_info_new( + "version", DISPLAY_VERSION, + "category", _("Keyring"), + "summary", _("Store passwords using Windows credentials"), + "description", _("This plugin stores passwords using Windows credentials."), + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", PURPLE_PLUGIN_INFO_FLAGS_INTERNAL | + PURPLE_PLUGIN_INFO_FLAGS_AUTO_LOAD, +wincred_load(GPluginPlugin *plugin, GError **error) { + PurpleCredentialManager *manager = NULL; + purple_wincred_register_type(G_TYPE_MODULE(plugin)); + manager = purple_credential_manager_get_default(); + instance = purple_wincred_new(); + return purple_credential_manager_register(manager, instance, error); +wincred_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(wincred) --- a/po/POTFILES.in Fri Dec 10 00:33:15 2021 -0600
+++ b/po/POTFILES.in Fri Dec 10 01:44:32 2021 -0600
@@ -62,13 +62,13 @@
libpurple/plugins/joinpart.c
libpurple/plugins/keychain-access/keychain-access.c
libpurple/plugins/keyrings/internalkeyring.c
-libpurple/plugins/keyrings/wincred.c
libpurple/plugins/kwallet/purplekwallet.cpp
libpurple/plugins/libsecret/libsecret.c
libpurple/plugins/notification-sound/notification-sound.c
libpurple/plugins/psychic.c
libpurple/plugins/purple-toast.c
libpurple/plugins/statenotify.c
+libpurple/plugins/wincred/wincred.c libpurple/protocols/bonjour/bonjour.c
libpurple/protocols/bonjour/bonjour_ft.c