[telepathy-haze/master] Don't assume purple_account_new returns a new account.
Will Thompson
will.thompson at collabora.co.uk
Wed Mar 25 17:42:43 PDT 2009
If an existing account for a given (prpl, username) exists, it's
returned by purple_account_new (). If you called RequestConnection
for an already-connected account Haze would trample over that account's
ui_data before tp-glib failed RequestConnection (due to the connection
unique name being the same), and then it would point to freed memory and
crash Haze.
Fixes fd.o #18361
---
src/connection-manager.c | 6 ++++++
src/connection.c | 38 +++++++++++++++++++++++++++++---------
src/connection.h | 2 ++
3 files changed, 37 insertions(+), 9 deletions(-)
diff --git a/src/connection-manager.c b/src/connection-manager.c
index 7818a8a..54fcbe3 100644
--- a/src/connection-manager.c
+++ b/src/connection-manager.c
@@ -440,6 +440,12 @@ _haze_connection_manager_new_connection (TpBaseConnectionManager *base,
"parameters", params,
NULL);
+ if (!haze_connection_create_account (conn, error))
+ {
+ g_object_unref (conn);
+ return FALSE;
+ }
+
cm->connections = g_list_prepend(cm->connections, conn);
g_signal_connect (conn, "shutdown-finished",
G_CALLBACK (connection_shutdown_finished_cb),
diff --git a/src/connection.c b/src/connection.c
index f4dd7bb..069cf8e 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -289,23 +289,42 @@ _set_option (const PurpleAccountOption *option,
g_hash_table_remove (context->params, option->pref_name);
}
-static void
-_create_account (HazeConnection *self)
+/**
+ * haze_connection_create_account:
+ *
+ * Attempts to create a PurpleAccount corresponding to this connection. Must be
+ * called immediately after constructing a connection. It's a shame GObject
+ * constructors can't fail.
+ *
+ * Returns: %TRUE if the account was successfully created and hooked up;
+ * %FALSE with @error set in the TP_ERRORS domain if the account
+ * already existed or another error occurred.
+ */
+gboolean
+haze_connection_create_account (HazeConnection *self,
+ GError **error)
{
HazeConnectionPrivate *priv = HAZE_CONNECTION_GET_PRIVATE(self);
GHashTable *params = priv->parameters;
PurplePluginProtocolInfo *prpl_info = priv->protocol_info->prpl_info;
-
+ const gchar *prpl_id = priv->protocol_info->prpl_id;
const gchar *username, *password;
struct _i_want_closure context;
+ g_return_val_if_fail (self->account == NULL, FALSE);
+
username = _get_param_string (params, "account");
- g_assert (username);
+ g_assert (username != NULL);
+
+ if (purple_accounts_find (username, prpl_id) != NULL)
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ "a connection already exists to %s on %s", username, prpl_id);
+ return FALSE;
+ }
- g_assert (self->account == NULL);
self->account = purple_account_new (username, priv->protocol_info->prpl_id);
purple_accounts_add (self->account);
- g_assert (self->account);
g_hash_table_remove (params, "account");
self->account->ui_data = self;
@@ -322,6 +341,8 @@ _create_account (HazeConnection *self)
g_list_foreach (prpl_info->protocol_options, (GFunc) _set_option, &context);
g_hash_table_foreach (params, (GHFunc) _warn_unhandled_parameter, "lala");
+
+ return TRUE;
}
static gboolean
@@ -329,10 +350,11 @@ _haze_connection_start_connecting (TpBaseConnection *base,
GError **error)
{
HazeConnection *self = HAZE_CONNECTION(base);
-
TpHandleRepoIface *contact_handles =
tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT);
+ g_return_val_if_fail (self->account != NULL, FALSE);
+
base->self_handle = tp_handle_ensure (contact_handles,
purple_account_get_username (self->account), NULL, error);
if (!base->self_handle)
@@ -486,8 +508,6 @@ haze_connection_constructor (GType type,
priv->disconnecting = FALSE;
- _create_account (self);
-
tp_contacts_mixin_init (object,
G_STRUCT_OFFSET (HazeConnection, contacts));
tp_base_connection_register_with_contacts_mixin (
diff --git a/src/connection.h b/src/connection.h
index dda734b..8d9a1ef 100644
--- a/src/connection.h
+++ b/src/connection.h
@@ -86,6 +86,8 @@ haze_connection_handle_inspect (HazeConnection *conn,
TpHandleType handle_type,
TpHandle handle);
+gboolean haze_connection_create_account (HazeConnection *self, GError **error);
+
GType haze_connection_get_type (void);
/* TYPE MACROS */
--
1.5.6.5
More information about the telepathy-commits
mailing list