--- a/ChangeLog.API Sat Jan 02 18:53:11 2021 -0600
+++ b/ChangeLog.API Sat Jan 02 19:06:28 2021 -0600
@@ -326,6 +326,10 @@
* PurpleAccountPrefsUiOps
* purple_account_add_buddies_with_invite
* purple_account_add_buddy_with_invite
+ * purple_account_get_password. Use + purple_credential_manager_read_password_async instead. + * purple_account_set_password. Use + purple_credential_manager_write_password_async instead. * purple_account_set_current_error
* purple_base64_*. Use g_base64_* instead
--- a/finch/gntaccount.c Sat Jan 02 18:53:11 2021 -0600
+++ b/finch/gntaccount.c Sat Jan 02 19:06:28 2021 -0600
@@ -90,12 +90,15 @@
save_account_cb(AccountEditDialog *dialog)
+ PurpleCredentialManager *manager = NULL; PurpleProtocol *protocol;
/* XXX: Do some error checking first. */
+ manager = purple_credential_manager_get_default(); protocol = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
/* Username && user-splits */
@@ -186,10 +189,13 @@
purple_account_set_remember_password(account,
gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->remember)));
value = gnt_entry_get_text(GNT_ENTRY(dialog->password));
- purple_account_set_password(account, value, NULL, NULL);
- purple_account_set_password(account, NULL, NULL, NULL);
+ purple_credential_manager_write_password_async(manager, account, value, + purple_credential_manager_clear_password_async(manager, account, NULL, purple_account_set_check_mail(account,
@@ -521,14 +527,19 @@
-edit_account_continue(PurpleAccount *account,
- const gchar *password, GError *error, gpointer user_data)
+edit_account_continue(GObject *obj, GAsyncResult *res, gpointer data) + PurpleAccount *account = PURPLE_ACCOUNT(data); + PurpleCredentialManager *manager = PURPLE_CREDENTIAL_MANAGER(obj); GntWidget *window, *hbox;
GntWidget *combo, *button, *entry;
AccountEditDialog *dialog;
PurpleProtocol *protocol;
+ gchar *password = NULL; + password = purple_credential_manager_read_password_finish(manager, res, @@ -605,8 +616,9 @@
gnt_entry_set_masked(GNT_ENTRY(entry), TRUE);
gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Password:")));
gnt_box_add_widget(GNT_BOX(hbox), entry);
gnt_entry_set_text(GNT_ENTRY(entry), password);
hbox = gnt_hbox_new(TRUE);
gnt_box_set_pad(GNT_BOX(hbox), 0);
@@ -654,13 +666,19 @@
gnt_box_readjust(GNT_BOX(window));
edit_account(PurpleAccount *account)
- purple_account_get_password(account, edit_account_continue, account);
+ PurpleCredentialManager *manager = NULL; + manager = purple_credential_manager_get_default(); + purple_credential_manager_read_password_async(manager, account, NULL, --- a/finch/gntprefs.c Sat Jan 02 18:53:11 2021 -0600
+++ b/finch/gntprefs.c Sat Jan 02 19:06:28 2021 -0600
@@ -270,9 +270,11 @@
finch_prefs_keyring_save(void *data, PurpleRequestFields *fields)
+ PurpleCredentialManager *manager = purple_credential_manager_get_default(); pref_request.keyring_window = NULL;
- purple_keyring_apply_settings(NULL, fields);
+ purple_credential_manager_write_settings(manager, fields, NULL); @@ -284,13 +286,15 @@
void finch_prefs_show_keyring(void)
PurpleRequestFields *fields;
+ PurpleCredentialManager *manager = NULL; if (pref_request.keyring_window != NULL) {
gnt_window_present(pref_request.keyring_window);
- fields = purple_keyring_read_settings();
+ manager = purple_credential_manager_get_default(); + fields = purple_credential_manager_read_settings(manager, NULL); purple_notify_info(NULL, _("Keyring settings"),
_("Selected keyring doesn't allow any configuration"),
--- a/libpurple/account.c Sat Jan 02 18:53:11 2021 -0600
+++ b/libpurple/account.c Sat Jan 02 19:06:28 2021 -0600
@@ -31,6 +31,7 @@
#include "purpleaccountpresence.h"
+#include "purplecredentialmanager.h" #include "purpleprivate.h"
#include "purpleprotocolclient.h"
@@ -52,7 +53,6 @@
char *username; /* The username. */
char *alias; /* How you appear to yourself. */
- char *password; /* The account password. */
char *user_info; /* User information. */
char *buddy_icon_path; /* The buddy icon's non-cached path. */
@@ -119,6 +119,7 @@
+ PurpleAccount *account; @@ -148,36 +149,54 @@
*****************************************************************************/
-purple_account_register_got_password_cb(PurpleAccount *account,
- const gchar *password, GError *error, gpointer data)
+purple_account_register_got_password_cb(GObject *obj, GAsyncResult *res, - g_return_if_fail(PURPLE_IS_ACCOUNT(account));
+ PurpleCredentialManager *manager = PURPLE_CREDENTIAL_MANAGER(obj); + PurpleAccount *account = PURPLE_ACCOUNT(data); + gchar *password = NULL; + password = purple_credential_manager_read_password_finish(manager, res, _purple_connection_new(account, TRUE, password);
purple_account_register(PurpleAccount *account)
+ PurpleCredentialManager *manager = NULL; g_return_if_fail(PURPLE_IS_ACCOUNT(account));
purple_debug_info("account", "Registering account %s\n",
purple_account_get_username(account));
- purple_keyring_get_password(account,
- purple_account_register_got_password_cb, NULL);
+ manager = purple_credential_manager_get_default(); + purple_credential_manager_read_password_async(manager, account, NULL, + purple_account_register_got_password_cb, -purple_account_unregister_got_password_cb(PurpleAccount *account,
- const gchar *password, GError *error, gpointer data)
+purple_account_unregister_got_password_cb(GObject *obj, GAsyncResult *res, + PurpleCredentialManager *manager = PURPLE_CREDENTIAL_MANAGER(obj); PurpleCallbackBundle *cbb = data;
PurpleAccountUnregistrationCb cb;
+ gchar *password = NULL; cb = (PurpleAccountUnregistrationCb)cbb->cb;
- _purple_connection_new_unregister(account, password, cb, cbb->data);
+ password = purple_credential_manager_read_password_finish(manager, res, + _purple_connection_new_unregister(cbb->account, password, cb, cbb->data); @@ -206,6 +225,37 @@
+request_password_write_cb(GObject *obj, GAsyncResult *res, gpointer data) { + PurpleCredentialManager *manager = PURPLE_CREDENTIAL_MANAGER(obj); + PurpleAccount *account = PURPLE_ACCOUNT(data); + gchar *password = NULL; + /* We stash the password on the account to get it to this call back... It's + * kind of gross but shouldn't be a big deal because any plugin has access + * to the credential store, so it's not really a security leak. + password = (gchar *)g_object_get_data(G_OBJECT(account), "_tmp_password"); + g_object_set_data(G_OBJECT(account), "_tmp_password", NULL); + if(!purple_credential_manager_write_password_finish(manager, res, &error)) { + const gchar *name = purple_account_get_name_for_display(account); + /* we can't error an account without a connection, so we just drop a + * debug message for now and continue to connect the account. + purple_debug_info("account", + "failed to save password for account \"%s\": %s", + error != NULL ? error->message : "unknown error"); + _purple_connection_new(account, FALSE, password); request_password_ok_cb(PurpleAccount *account, PurpleRequestFields *fields)
@@ -224,8 +274,23 @@
purple_account_set_remember_password(account, remember);
- purple_account_set_password(account, entry, NULL, NULL);
- _purple_connection_new(account, FALSE, entry);
+ PurpleCredentialManager *manager = NULL; + manager = purple_credential_manager_get_default(); + /* The requests field can be invalidated by the time we write the + * password and we want to use it in the write callback, so we need to + * duplicate it for that callback. + g_object_set_data(G_OBJECT(account), "_tmp_password", g_strdup(entry)); + purple_credential_manager_write_password_async(manager, account, entry, + request_password_write_cb, + _purple_connection_new(account, FALSE, entry); @@ -237,19 +302,31 @@
-purple_account_connect_got_password_cb(PurpleAccount *account,
- const gchar *password, GError *error, gpointer data)
+purple_account_connect_got_password_cb(GObject *obj, GAsyncResult *res, - PurpleProtocol *protocol = data;
- if ((password == NULL || *password == '\0') &&
+ PurpleCredentialManager *manager = PURPLE_CREDENTIAL_MANAGER(obj); + PurpleAccount *account = PURPLE_ACCOUNT(data); + PurpleProtocol *protocol = NULL; + gchar *password = NULL; + password = purple_credential_manager_read_password_finish(manager, res, + protocol = purple_protocols_find(purple_account_get_protocol_id(account)); + if((password == NULL || *password == '\0') && !(purple_protocol_get_options(protocol) & OPT_PROTO_NO_PASSWORD) &&
!(purple_protocol_get_options(protocol) & OPT_PROTO_PASSWORD_OPTIONAL))
purple_account_request_password(account,
G_CALLBACK(request_password_ok_cb),
G_CALLBACK(request_password_cancel_cb), account);
_purple_connection_new(account, FALSE, password);
static PurpleAccountRequestInfo *
@@ -431,28 +508,6 @@
return purple_connection_get_state(gc);
-purple_account_get_password_got(PurpleAccount *account,
- const gchar *password, GError *error, gpointer data)
- PurpleCallbackBundle *cbb = data;
- PurpleKeyringReadCallback cb;
- PurpleAccountPrivate *priv = purple_account_get_instance_private(account);
- purple_debug_info("account",
- "Read password for account %s from async keyring.\n",
- purple_account_get_username(account));
- purple_str_wipe(priv->password);
- priv->password = g_strdup(password);
- cb = (PurpleKeyringReadCallback)cbb->cb;
- cb(account, password, error, cbb->data);
* This makes sure your permit list contains all buddies from your
* buddy list and ONLY buddies from your buddy list.
@@ -1070,7 +1125,6 @@
- purple_str_wipe(priv->password);
g_free(priv->buddy_icon_path);
g_free(priv->protocol_id);
@@ -1171,9 +1225,9 @@
purple_account_connect(PurpleAccount *account)
- PurpleProtocol *protocol;
- PurpleAccountPrivate *priv;
+ PurpleCredentialManager *manager = NULL; + PurpleProtocol *protocol = NULL; + const char *username = NULL; g_return_if_fail(PURPLE_IS_ACCOUNT(account));
@@ -1197,17 +1251,12 @@
- priv = purple_account_get_instance_private(account);
purple_debug_info("account", "Connecting to account %s.\n", username);
- if (priv->password != NULL) {
- purple_account_connect_got_password_cb(account,
- priv->password, NULL, protocol);
- purple_keyring_get_password(account,
- purple_account_connect_got_password_cb, protocol);
+ manager = purple_credential_manager_get_default(); + purple_credential_manager_read_password_async(manager, account, NULL, + purple_account_connect_got_password_cb, @@ -1238,9 +1287,11 @@
-purple_account_unregister(PurpleAccount *account, PurpleAccountUnregistrationCb cb, void *user_data)
+purple_account_unregister(PurpleAccount *account, + PurpleAccountUnregistrationCb cb, gpointer user_data) PurpleCallbackBundle *cbb;
+ PurpleCredentialManager *manager = NULL; g_return_if_fail(PURPLE_IS_ACCOUNT(account));
@@ -1248,11 +1299,14 @@
purple_account_get_username(account));
cbb = g_new0(PurpleCallbackBundle, 1);
+ cbb->account = account; cbb->cb = PURPLE_CALLBACK(cb);
- purple_keyring_get_password(account,
- purple_account_unregister_got_password_cb, cbb);
+ manager = purple_credential_manager_get_default(); + purple_credential_manager_read_password_async(manager, account, NULL, + purple_account_unregister_got_password_cb, @@ -1567,33 +1621,6 @@
-purple_account_set_password(PurpleAccount *account, const gchar *password,
- PurpleKeyringSaveCallback cb, gpointer data)
- PurpleAccountPrivate *priv;
- g_return_if_fail(PURPLE_IS_ACCOUNT(account));
- priv = purple_account_get_instance_private(account);
- purple_str_wipe(priv->password);
- priv->password = g_strdup(password);
- purple_accounts_schedule_save();
- if (!purple_account_get_remember_password(account)) {
- purple_debug_info("account",
- "Password for %s set, not sent to keyring.\n",
- purple_account_get_username(account));
- cb(account, NULL, data);
- purple_keyring_set_password(account, password, cb, data);
purple_account_set_private_alias(PurpleAccount *account, const char *alias)
PurpleAccountPrivate *priv;
@@ -2094,37 +2121,6 @@
-purple_account_get_password(PurpleAccount *account,
- PurpleKeyringReadCallback cb, gpointer data)
- PurpleAccountPrivate *priv;
- cb(NULL, NULL, NULL, data);
- priv = purple_account_get_instance_private(account);
- if (priv->password != NULL) {
- purple_debug_info("account",
- "Reading password for account %s from cache.\n",
- purple_account_get_username(account));
- cb(account, priv->password, NULL, data);
- PurpleCallbackBundle *cbb = g_new0(PurpleCallbackBundle, 1);
- cbb->cb = PURPLE_CALLBACK(cb);
- purple_debug_info("account",
- "Reading password for account %s from async keyring.\n",
- purple_account_get_username(account));
- purple_keyring_get_password(account,
- purple_account_get_password_got, cbb);
purple_account_get_private_alias(PurpleAccount *account)
@@ -2987,10 +2983,16 @@
purple_account_change_password(PurpleAccount *account, const char *orig_pw,
+ PurpleCredentialManager *manager = NULL; PurpleProtocol *protocol = NULL;
PurpleConnection *gc = purple_account_get_connection(account);
- purple_account_set_password(account, new_pw, NULL, NULL);
+ /* just going to fire and forget this for now as not many protocols even + * implement the change password stuff. + manager = purple_credential_manager_get_default(); + purple_credential_manager_write_password_async(manager, account, new_pw, protocol = purple_connection_get_protocol(gc);
--- a/libpurple/account.h Sat Jan 02 18:53:11 2021 -0600
+++ b/libpurple/account.h Sat Jan 02 19:06:28 2021 -0600
@@ -311,23 +311,6 @@
void purple_account_set_username(PurpleAccount *account, const char *username);
- * purple_account_set_password:
- * @account: The account.
- * @password: The password.
- * @cb: (scope call): A callback for once the password is saved.
- * @data: A pointer to be passed to the callback.
- * Sets the account's password.
- * The password in the keyring might not be immediately updated, but the cached
- * version will be, and it is therefore safe to read the password back before
- * the callback has been triggered. One can also set a %NULL callback if
- * notification of saving to the keyring is not required.
-void purple_account_set_password(PurpleAccount *account, const gchar *password,
- PurpleKeyringSaveCallback cb, gpointer data);
* purple_account_set_private_alias:
@@ -653,22 +636,6 @@
const char *purple_account_get_username(PurpleAccount *account);
- * purple_account_get_password:
- * @account: The account.
- * @cb: (scope call): The callback to give the password.
- * @data: A pointer passed to the callback.
- * Reads the password for the account.
- * This is an asynchronous call, that will return the password in a callback
- * once it has been read from the keyring. If the account is connected, and you
- * require the password immediately, then consider using @ref
- * purple_connection_get_password instead.
-void purple_account_get_password(PurpleAccount *account,
- PurpleKeyringReadCallback cb, gpointer data);
* purple_account_get_private_alias:
--- a/libpurple/accounts.c Sat Jan 02 18:53:11 2021 -0600
+++ b/libpurple/accounts.c Sat Jan 02 19:06:28 2021 -0600
@@ -28,6 +28,7 @@
+#include "purplecredentialmanager.h" #include "purpleprivate.h"
static PurpleAccountUiOps *account_ui_ops = NULL;
@@ -580,8 +581,18 @@
-purple_accounts_delete_set(PurpleAccount *account, GError *error, gpointer data)
+purple_accounts_delete_set(GObject *obj, GAsyncResult *res, gpointer d) { + PurpleCredentialManager *manager = PURPLE_CREDENTIAL_MANAGER(obj); + PurpleAccount *account = PURPLE_ACCOUNT(d); + r = purple_credential_manager_clear_password_finish(manager, res, NULL); + purple_debug_warning("accounts", + "Failed to remove password for account %s", + purple_account_get_name_for_display(account)); g_object_unref(G_OBJECT(account));
@@ -589,6 +600,7 @@
purple_accounts_delete(PurpleAccount *account)
PurpleBlistNode *gnode, *cnode, *bnode;
+ PurpleCredentialManager *manager = NULL; g_return_if_fail(account != NULL);
@@ -656,8 +668,10 @@
/* This is async because we do not want the
* account being overwritten before we are done.
- purple_keyring_set_password(account, NULL,
- purple_accounts_delete_set, NULL);
+ manager = purple_credential_manager_get_default(); + purple_credential_manager_clear_password_async(manager, account, NULL, + purple_accounts_delete_set, --- a/libpurple/example/nullclient.c Sat Jan 02 18:53:11 2021 -0600
+++ b/libpurple/example/nullclient.c Sat Jan 02 19:06:28 2021 -0600
@@ -160,6 +160,7 @@
int main(int argc, char *argv[])
+ PurpleCredentialManager *manager = NULL; @@ -225,7 +226,10 @@
/* Get the password for the account */
password = getpass("Password: ");
- purple_account_set_password(account, password, NULL, NULL);
+ manager = purple_credential_manager_get_default(); + purple_credential_manager_write_password_async(manager, account, password, /* It's necessary to enable the account first. */
purple_account_set_enabled(account, UI_ID, TRUE);
--- a/libpurple/keyring.c Sat Jan 02 18:53:11 2021 -0600
+++ b/libpurple/keyring.c Sat Jan 02 19:06:28 2021 -0600
@@ -801,196 +801,6 @@
return export(account, mode, data, error, destroy);
-purple_keyring_get_password(PurpleAccount *account,
- PurpleKeyringReadCallback cb, gpointer data)
- PurpleKeyringRead read_cb;
- g_return_if_fail(account != NULL);
- if (purple_keyring_is_quitting) {
- purple_debug_error("keyring", "Cannot request a password while "
- error = g_error_new_literal(
- PURPLE_KEYRING_ERROR, PURPLE_KEYRING_ERROR_INTERNAL,
- _("Cannot request a password while quitting."));
- cb(account, NULL, error, data);
- inuse = purple_keyring_get_inuse();
- purple_debug_error("keyring", "No keyring configured.\n");
- error = g_error_new_literal(PURPLE_KEYRING_ERROR,
- PURPLE_KEYRING_ERROR_NOKEYRING,
- _("No keyring configured."));
- cb(account, NULL, error, data);
- read_cb = purple_keyring_get_read_password(inuse);
- g_assert(read_cb != NULL);
- purple_debug_info("keyring", "Reading password for account %s...\n",
- purple_keyring_print_account(account));
- read_cb(account, cb, data);
-purple_keyring_set_password_save_cb(PurpleAccount *account, GError *error,
- PurpleKeyringSetPasswordData *set_data = _set_data;
- g_return_if_fail(account != NULL);
- g_return_if_fail(set_data != NULL);
- if (error == NULL && purple_debug_is_verbose()) {
- purple_debug_misc("keyring", "Password for account %s "
- "saved successfully.\n",
- purple_keyring_print_account(account));
- } else if (purple_debug_is_verbose()) {
- purple_debug_warning("keyring", "Password for account %s "
- "not saved successfully.\n",
- purple_keyring_print_account(account));
- purple_notify_error(NULL, _("Keyrings"),
- _("Failed to save a password in keyring."),
- if (set_data->cb != NULL)
- set_data->cb(account, error, set_data->cb_data);
-purple_keyring_set_password(PurpleAccount *account, const gchar *password,
- PurpleKeyringSaveCallback cb, gpointer data)
- PurpleKeyringSave save_cb;
- PurpleKeyringSetPasswordData *set_data;
- g_return_if_fail(account != NULL);
- if (purple_keyring_is_quitting) {
- purple_debug_error("keyring", "Cannot save a password while "
- error = g_error_new_literal(
- PURPLE_KEYRING_ERROR, PURPLE_KEYRING_ERROR_INTERNAL,
- _("Cannot save a password while quitting."));
- cb(account, error, data);
- if (current_change_tracker != NULL) {
- purple_debug_error("keyring", "Cannot save a password during "
- "password migration.\n");
- error = g_error_new_literal(
- PURPLE_KEYRING_ERROR, PURPLE_KEYRING_ERROR_INTERNAL,
- _("Cannot save a password during password migration."));
- cb(account, error, data);
- inuse = purple_keyring_get_inuse();
- error = g_error_new_literal(PURPLE_KEYRING_ERROR,
- PURPLE_KEYRING_ERROR_NOKEYRING,
- _("No keyring configured."));
- cb(account, error, data);
- save_cb = purple_keyring_get_save_password(inuse);
- g_assert(save_cb != NULL);
- set_data = g_new(PurpleKeyringSetPasswordData, 1);
- set_data->cb_data = data;
- purple_debug_info("keyring", "%s password for account %s...\n",
- (password ? "Saving" : "Removing"),
- purple_keyring_print_account(account));
- save_cb(account, password, purple_keyring_set_password_save_cb, set_data);
-purple_keyring_read_settings(void)
- PurpleKeyringReadSettings read_settings;
- if (purple_keyring_is_quitting || current_change_tracker != NULL) {
- purple_debug_error("keyring", "Cannot read settngs at the "
- inuse = purple_keyring_get_inuse();
- purple_debug_error("keyring", "No keyring in use.\n");
- read_settings = purple_keyring_get_read_settings(inuse);
- if (read_settings == NULL)
- return read_settings();
-purple_keyring_apply_settings(void *notify_handle, PurpleRequestFields *fields)
- PurpleKeyringApplySettings apply_settings;
- g_return_val_if_fail(fields != NULL, FALSE);
- if (purple_keyring_is_quitting || current_change_tracker != NULL) {
- purple_debug_error("keyring", "Cannot apply settngs at the "
- inuse = purple_keyring_get_inuse();
- purple_debug_error("keyring", "No keyring in use.\n");
- apply_settings = purple_keyring_get_apply_settings(inuse);
- if (apply_settings == NULL) {
- purple_debug_warning("keyring", "Applying settings not "
- return apply_settings(notify_handle, fields);
/**************************************************************************/
/* PurpleKeyring accessors */
/**************************************************************************/
--- a/libpurple/keyring.h Sat Jan 02 18:53:11 2021 -0600
+++ b/libpurple/keyring.h Sat Jan 02 19:06:28 2021 -0600
@@ -333,55 +333,6 @@
const gchar **mode, gchar **data, GError **error,
GDestroyNotify *destroy);
- * purple_keyring_get_password:
- * @account: The account.
- * @cb: (scope call): A callback for once the password is read.
- * @data: Data passed to the callback.
- * Read a password from the current keyring.
-purple_keyring_get_password(PurpleAccount *account,
- PurpleKeyringReadCallback cb, gpointer data);
- * purple_keyring_set_password:
- * @account: The account.
- * @password: The password to save.
- * @cb: (scope call): A callback for once the password is saved.
- * @data: Data to be passed to the callback.
- * Save a password to the current keyring.
-purple_keyring_set_password(PurpleAccount *account, const gchar *password,
- PurpleKeyringSaveCallback cb, gpointer data);
- * purple_keyring_read_settings:
- * Reads settings from current keyring.
- * Returns: (transfer full): New copy of current settings (must be free'd with
- * purple_request_fields_destroy).
-purple_keyring_read_settings(void);
- * purple_keyring_apply_settings:
- * @notify_handle: A handle that can be passed to purple_notify_message.
- * @fields: Modified settings (originally taken from
- * PurpleKeyringReadSettings).
- * Applies modified settings to current keyring.
- * Returns: TRUE, if succeeded, FALSE otherwise.
-purple_keyring_apply_settings(void *notify_handle, PurpleRequestFields *fields);
/**************************************************************************/
/* PurpleKeyring accessors */
/**************************************************************************/
--- a/libpurple/protocols.c Sat Jan 02 18:53:11 2021 -0600
+++ b/libpurple/protocols.c Sat Jan 02 19:06:28 2021 -0600
@@ -30,6 +30,7 @@
#include "purpleaccountoption.h"
+#include "purplecredentialmanager.h" #include "purpleprotocolattention.h"
#include "purpleprotocolmedia.h"
@@ -285,8 +286,14 @@
if (!purple_account_is_disconnected(account))
purple_account_disconnect(account);
/* Clear out the unsaved password if we switch to offline status */
- if (!purple_account_get_remember_password(account))
- purple_account_set_password(account, NULL, NULL, NULL);
+ if (!purple_account_get_remember_password(account)) { + PurpleCredentialManager *manager = NULL; + manager = purple_credential_manager_get_default(); + purple_credential_manager_clear_password_async(manager, account, --- a/libpurple/protocols/jabber/auth.c Sat Jan 02 18:53:11 2021 -0600
+++ b/libpurple/protocols/jabber/auth.c Sat Jan 02 19:06:28 2021 -0600
@@ -99,10 +99,15 @@
+ PurpleCredentialManager *manager = NULL; purple_account_set_remember_password(account, TRUE);
- purple_account_set_password(account, entry, NULL, NULL);
+ manager = purple_credential_manager_get_default(); + purple_credential_manager_write_password_async(manager, account, entry, /* Restart our connection */
jabber_auth_start_old(js);
@@ -215,8 +220,15 @@
purple_strequal(err_code, "401")) {
reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
/* Clear the pasword if it isn't being saved */
- if (!purple_account_get_remember_password(account))
- purple_account_set_password(account, NULL, NULL, NULL);
+ if(!purple_account_get_remember_password(account)) { + PurpleCredentialManager *manager = NULL; + manager = purple_credential_manager_get_default(); + purple_credential_manager_clear_password_async(manager, account, purple_connection_error(js->gc, reason, msg);
--- a/libpurple/protocols/jabber/jabber.c Sat Jan 02 18:53:11 2021 -0600
+++ b/libpurple/protocols/jabber/jabber.c Sat Jan 02 19:06:28 2021 -0600
@@ -1266,8 +1266,18 @@
g_free(cbdata->js->user->node);
cbdata->js->user->node = g_strdup(value);
- if(cbdata->js->registration && purple_strequal(id, "password"))
- purple_account_set_password(purple_connection_get_account(cbdata->js->gc), value, NULL, NULL);
+ if(cbdata->js->registration && purple_strequal(id, "password")) { + PurpleCredentialManager *manager = NULL; + PurpleAccount *account = NULL; + account = purple_connection_get_account(cbdata->js->gc); + manager = purple_credential_manager_get_default(); + purple_credential_manager_write_password_async(manager, @@ -2477,11 +2487,17 @@
PurpleXmlNode *packet, gpointer data)
if (type == JABBER_IQ_RESULT) {
+ PurpleAccount *account = purple_connection_get_account(js->gc); + PurpleCredentialManager *manager = NULL; purple_notify_info(js->gc, _("Password Changed"), _("Password "
"Changed"), _("Your password has been changed."),
purple_request_cpar_from_connection(js->gc));
- purple_account_set_password(purple_connection_get_account(js->gc), (const char *)data, NULL, NULL);
+ manager = purple_credential_manager_get_default(); + purple_credential_manager_write_password_async(manager, account, char *msg = jabber_parse_error(js, packet, NULL);
@@ -2743,8 +2759,15 @@
} else if(purple_xmlnode_get_child(packet, "not-authorized")) {
SET_REASON(PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED);
/* Clear the pasword if it isn't being saved */
- if (!purple_account_get_remember_password(purple_connection_get_account(js->gc)))
- purple_account_set_password(purple_connection_get_account(js->gc), NULL, NULL, NULL);
+ if (!purple_account_get_remember_password(purple_connection_get_account(js->gc))) { + PurpleAccount *account = purple_connection_get_account(js->gc); + PurpleCredentialManager *manager = NULL; + manager = purple_credential_manager_get_default(); + purple_credential_manager_clear_password_async(manager, account, text = _("Not Authorized");
} else if(purple_xmlnode_get_child(packet, "temporary-auth-failure")) {
text = _("Temporary Authentication Failure");
--- a/libpurple/protocols/novell/novell.c Sat Jan 02 18:53:11 2021 -0600
+++ b/libpurple/protocols/novell/novell.c Sat Jan 02 19:06:28 2021 -0600
@@ -127,8 +127,18 @@
/* Don't attempt to auto-reconnect if our
- if (!purple_account_get_remember_password(purple_connection_get_account(gc)))
- purple_account_set_password(purple_connection_get_account(gc), NULL, NULL, NULL);
+ if (!purple_account_get_remember_password(purple_connection_get_account(gc))) { + PurpleAccount *account = NULL; + PurpleCredentialManager *manager = NULL; + account = purple_connection_get_account(gc); + manager = purple_credential_manager_get_default(); + purple_credential_manager_clear_password_async(manager, reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
@@ -2030,8 +2040,14 @@
gc = purple_account_get_connection(account);
- if (!purple_account_get_remember_password(account))
- purple_account_set_password(account, NULL, NULL, NULL);
+ if (!purple_account_get_remember_password(account)) { + PurpleCredentialManager *manager = NULL; + manager = purple_credential_manager_get_default(); + purple_credential_manager_clear_password_async(manager, account, purple_connection_error(gc,
PURPLE_CONNECTION_ERROR_NAME_IN_USE,
_("You have signed on from another location"));
--- a/libpurple/purplecredentialmanager.c Sat Jan 02 18:53:11 2021 -0600
+++ b/libpurple/purplecredentialmanager.c Sat Jan 02 19:06:28 2021 -0600
@@ -2,10 +2,6 @@
* Purple - Internet Messaging Library
* Copyright (C) Pidgin Developers <devel@pidgin.im>
- * 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
@@ -196,7 +192,7 @@
* PurpleCredentialManager::active-provider-changed:
* @manager: The #PurpleCredentialManager instance.
* @old: The #PurpleCredentialProvider that was previously active.
- * @current: The #PurpleCredenetialProvider that is now currently active.
+ * @current: The #PurpleCredentialProvider that is now currently active. * Emitted after @provider has become the active provider for @manager.
@@ -382,12 +378,10 @@
purple_credential_manager_read_password_finish(PurpleCredentialManager *manager,
- PurpleAccount *account,
g_return_val_if_fail(PURPLE_IS_CREDENTIAL_MANAGER(manager), NULL);
- g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
return g_task_propagate_pointer(G_TASK(result), error);
@@ -410,6 +404,19 @@
task = g_task_new(manager, cancellable, callback, data);
+ if(!purple_account_get_remember_password(account)) { + const gchar *name = purple_account_get_name_for_display(account); + error = g_error_new(PURPLE_CREDENTIAL_MANAGER_DOMAIN, 0, + _("account \"%s\" is not marked to be stored"), + g_task_return_error(task, error); if(priv->active_provider == NULL) {
@@ -431,12 +438,10 @@
purple_credential_manager_write_password_finish(PurpleCredentialManager *manager,
- PurpleAccount *account,
g_return_val_if_fail(PURPLE_IS_CREDENTIAL_MANAGER(manager), FALSE);
- g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), FALSE);
return g_task_propagate_boolean(G_TASK(result), error);
@@ -479,12 +484,10 @@
purple_credential_manager_clear_password_finish(PurpleCredentialManager *manager,
- PurpleAccount *account,
g_return_val_if_fail(PURPLE_IS_CREDENTIAL_MANAGER(manager), FALSE);
- g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), FALSE);
return g_task_propagate_boolean(G_TASK(result), error);
--- a/libpurple/purplecredentialmanager.h Sat Jan 02 18:53:11 2021 -0600
+++ b/libpurple/purplecredentialmanager.h Sat Jan 02 19:06:28 2021 -0600
@@ -2,10 +2,6 @@
* Purple - Internet Messaging Library
* Copyright (C) Pidgin Developers <devel@pidgin.im>
- * 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
@@ -172,7 +168,6 @@
* purple_credential_manager_read_password_finish:
* @manager: The #PurpleCredentialManager instance.
- * @account: The #PurpleAccount whose password we're looking up.
* @result: The #GAsyncResult from the previous
* purple_credential_manager_read_password_async() call.
* @error: (out) (optional): Return address for a #GError.
@@ -184,7 +179,7 @@
-gchar *purple_credential_manager_read_password_finish(PurpleCredentialManager *manager, PurpleAccount *account, GAsyncResult *result, GError **error);
+gchar *purple_credential_manager_read_password_finish(PurpleCredentialManager *manager, GAsyncResult *result, GError **error); * purple_credential_manager_write_password_async:
@@ -206,7 +201,6 @@
* purple_credential_manager_write_password_finish:
* @manager: The #PurpleCredentialManager instance.
- * @account: The #PurpleAccount whose password we're writing.
* @result: The #GAsyncResult from the previous
* purple_credential_provider_write_password_async() call.
* @error: (out) (optional) (nullable): Return address for a #GError.
@@ -218,7 +212,7 @@
-gboolean purple_credential_manager_write_password_finish(PurpleCredentialManager *manager, PurpleAccount *account, GAsyncResult *result, GError **error);
+gboolean purple_credential_manager_write_password_finish(PurpleCredentialManager *manager, GAsyncResult *result, GError **error); * purple_credential_manager_clear_password_async:
@@ -239,7 +233,6 @@
* purple_credential_manager_clear_password_finish:
* @manager: The #PurpleCredentialManager instance.
- * @account: The #PurpleAccount whose password we're clearing.
* @result: The #GAsyncResult from the previous
* purple_credential_provider_clear_password_async() call.
* @error: (out) (optional) (nullable): Return address for a #GError.
@@ -252,7 +245,7 @@
-gboolean purple_credential_manager_clear_password_finish(PurpleCredentialManager *manager, PurpleAccount *account, GAsyncResult *result, GError **error);
+gboolean purple_credential_manager_clear_password_finish(PurpleCredentialManager *manager, GAsyncResult *result, GError **error); * purple_credential_manager_read_settings:
--- a/libpurple/tests/test_credential_manager.c Sat Jan 02 18:53:11 2021 -0600
+++ b/libpurple/tests/test_credential_manager.c Sat Jan 02 19:06:28 2021 -0600
@@ -327,8 +327,8 @@
- password = purple_credential_manager_read_password_finish(manager, account,
+ password = purple_credential_manager_read_password_finish(manager, res, g_assert_error(error, PURPLE_CREDENTIAL_MANAGER_DOMAIN, 0);
@@ -371,8 +371,7 @@
- r = purple_credential_manager_write_password_finish(manager, account, res,
+ r = purple_credential_manager_write_password_finish(manager, res, &error); g_assert_error(error, PURPLE_CREDENTIAL_MANAGER_DOMAIN, 0);
@@ -416,8 +415,7 @@
- r = purple_credential_manager_clear_password_finish(manager, account, res,
+ r = purple_credential_manager_clear_password_finish(manager, res, &error); g_assert_error(error, PURPLE_CREDENTIAL_MANAGER_DOMAIN, 0);
@@ -493,8 +491,8 @@
- password = purple_credential_manager_read_password_finish(manager, account,
+ password = purple_credential_manager_read_password_finish(manager, res, g_assert_no_error(error);
g_assert_cmpstr(password, ==, "password");
@@ -558,8 +556,7 @@
- r = purple_credential_manager_write_password_finish(manager, account, res,
+ r = purple_credential_manager_write_password_finish(manager, res, &error); g_assert_no_error(error);
@@ -622,8 +619,7 @@
- r = purple_credential_manager_clear_password_finish(manager, account, res,
+ r = purple_credential_manager_clear_password_finish(manager, res, &error); g_assert_no_error(error);
--- a/pidgin/gtkaccount.c Sat Jan 02 18:53:11 2021 -0600
+++ b/pidgin/gtkaccount.c Sat Jan 02 19:06:28 2021 -0600
@@ -141,6 +141,11 @@
+ PurpleAccount *account; + PidginAccountDialogType type; +} PidginAccountDialogShowData; static AccountsWindow *accounts_window = NULL;
static GHashTable *account_pref_wins;
@@ -1277,6 +1282,7 @@
ok_account_prefs_cb(GtkWidget *w, AccountPrefsDialog *dialog)
+ PurpleCredentialManager *manager = NULL; PurpleProxyInfo *proxy_info = NULL;
@@ -1287,6 +1293,8 @@
PurpleBuddyIconSpec *icon_spec = NULL;
+ manager = purple_credential_manager_get_default(); /* Build the username string. */
username = g_strdup(gtk_entry_get_text(GTK_ENTRY(dialog->username_entry)));
@@ -1402,8 +1410,10 @@
remember = gtk_toggle_button_get_active(
GTK_TOGGLE_BUTTON(dialog->remember_pass_check));
- purple_keyring_set_password(account, NULL, NULL, NULL);
+ purple_credential_manager_clear_password_async(manager, account, NULL, purple_account_set_remember_password(account, remember);
@@ -1422,10 +1432,15 @@
* the account editor (but has not checked the 'save' box), then we
* don't want to prompt them.
- if ((purple_account_get_remember_password(account) || new_acct) && (*value != '\0'))
- purple_account_set_password(account, value, NULL, NULL);
- purple_account_set_password(account, NULL, NULL, NULL);
+ if ((purple_account_get_remember_password(account) || new_acct) && + purple_credential_manager_write_password_async(manager, account, value, + purple_credential_manager_clear_password_async(manager, account, NULL, purple_account_set_username(account, username);
@@ -1568,10 +1583,13 @@
-pidgin_account_dialog_show_continue(PurpleAccount *account,
- const gchar *password, GError *error, gpointer _type)
+pidgin_account_dialog_show_continue(GObject *obj, GAsyncResult *res, - PidginAccountDialogType type = GPOINTER_TO_INT(_type);
+ PurpleCredentialManager *manager = PURPLE_CREDENTIAL_MANAGER(obj); + PidginAccountDialogShowData *d = (PidginAccountDialogShowData *)data; + PurpleAccount *account = NULL; + PidginAccountDialogType type = 0; AccountPrefsDialog *dialog;
@@ -1579,6 +1597,14 @@
+ gchar *password = NULL; + /* we needed a struct to pass multiple pointers to here, but now that we + * have them, we can free it. if (accounts_window != NULL && account != NULL &&
(dialog = g_hash_table_lookup(account_pref_wins, account)) != NULL)
@@ -1615,8 +1641,12 @@
g_hash_table_insert(account_pref_wins, account, dialog);
+ /* The dialog will take ownership of this pointer */ + password = purple_credential_manager_read_password_finish(manager, res, dialog->account = account;
- dialog->password = g_strdup(password);
+ dialog->password = password; dialog->sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
dialog->protocol = purple_protocols_find(dialog->protocol_id);
@@ -1703,9 +1733,22 @@
pidgin_account_dialog_show(PidginAccountDialogType type, PurpleAccount *account)
+ PurpleCredentialManager *manager = NULL; + PidginAccountDialogShowData *data = NULL; + /* this is kind of dangerous, but it's no worse than the old version. + * Regardless this dialog needs a lot of TLC. + data = g_new0(PidginAccountDialogShowData, 1); + data->account = account; + manager = purple_credential_manager_get_default(); /* this is to make sure the password will be cached */
- purple_account_get_password(account,
- pidgin_account_dialog_show_continue, GINT_TO_POINTER(type));
+ purple_credential_manager_read_password_async(manager, account, NULL, + pidgin_account_dialog_show_continue, /**************************************************************************
--- a/pidgin/gtkprefs.c Sat Jan 02 18:53:11 2021 -0600
+++ b/pidgin/gtkprefs.c Sat Jan 02 19:06:28 2021 -0600
@@ -2060,8 +2060,10 @@
keyring_page_settings_apply(GtkButton *button, gpointer data)
PidginPrefsWindow *win = PIDGIN_PREFS_WINDOW(data);
- if (!purple_keyring_apply_settings(win, win->keyring.settings)) {
+ PurpleRequestFields *fields= win->keyring.settings; + PurpleCredentialManager *manager = purple_credential_manager_get_default(); + if(!purple_credential_manager_write_settings(manager, fields, NULL)) { @@ -2071,8 +2073,11 @@
keyring_page_update_settings(PidginPrefsWindow *win)
+ PurpleCredentialManager *manager = purple_credential_manager_get_default(); g_clear_pointer(&win->keyring.settings, purple_request_fields_destroy);
- win->keyring.settings = purple_keyring_read_settings();
+ win->keyring.settings = purple_credential_manager_read_settings(manager, if (!win->keyring.settings) {