Re: Old paradigms...

David Woodhouse <[email protected]> Thu, 15 Mar 2018 09:54:58 +0000
Newsgroups gmane.comp.gnome.gaim.devel
Message-ID <[email protected]>

On Mon, 2017-08-07 at 17:42 +0100, David Woodhouse wrote:
> On Mon, 2017-07-31 at 10:38 +0100, David Woodhouse wrote:
> > On Sun, 2017-07-30 at 23:04 -0500, Gary Kramlich wrote:
> > > On Tue, Jul 25, 2017 at 3:48 AM, David Woodhouse  wrote:
> > > > IF I get an incoming IM from someone I've never heard of, then for the
> > > > duration of that IM chat window, I *could* show that person's full name
> > > > and presence.
> > > > 
> > > > Right now it only works for individuals who *happen* to already be
> > > > known buddies. I have all the information in my prpl but no way to
> > > > convey it to libpurple/Pidgin.
> > > So you're thinking of something like always have a buddy or whatever
> > > we're calling it for everyone (and get rid of the just name thing for
> > > them) and have an option to not show/store them in the contact list?
> >
> > Do you mean 'get rid of the just name thing' for serv_got_im() and
> > purple_conv_chat_add_user(), and to pass a PurpleBuddy (or whatever
> > that's called) instead? 
> > 
> > I suppose we could, although that wasn't what I was thinking. It's fine
> > to just pass the name up from the prpl as we do now, and let
> > Pidgin/libpurple handle what happens next.
> > 
> > It so happens that Pidgin chooses to display the contact's presence at
> > the top of the IM window, and wants that information. And that it shows
> > the contact's full name by preference in the list of chat members, so
> > it wants that too.
> > 
> > Pidgin *already* creates a transient PurpleBuddy for that purpose, if
> > no known buddy already exists. My prpl already *receives* status
> > information for that buddy; it's just that there's no way for me to
> > make the two meet in the middle. My prpl doesn't even get a *signal*
> > let alone a direct invocation when code elsewhere creates a buddy for
> > the account, which seems odd.
> 
> Annoyingly, we already *have* a get_cb_real_name() function but Pidgin
> doesn't actually call it, so members in a chat window are shown by
> their ID (in my case email address). Unless, as I said, they were
> already known Buddies. That one is probably fairly simple to fix, but
> still doesn't get me presence for incoming IM from "random" people.
 
I finally got a chance to poke at this. Here's a really nasty hack :)

The problem is that throughout gtkconv.c we look up buddies by name
with purple_find_buddy() or purple_find_buddies() when we want to find
presence status or aliases. And none of that exists for the transient
buddy which is created in populate_menu_with_options().

So... I changed purple_buddy_new() to add the newly-created buddy tyo
the hash tables immediately, with hb.group==NULL. I extended the
purple_find_budd{y,ies}() functions with a parameter which allows them
to find those "transient" buddies. And I hacked my PRPL for now to
spuriously generate a new purple_prpl_got_user_status() and
purple_blist_server_alias_buddy() call when a conversation is created;
we can think about hooking into purple_buddy_new() later.

It does work, and now I see the full name and presence of people who IM
me but aren't "buddies". It's kind of horrid though, and would get
worse before it's complete.

 • I'd need to fix it for chat room members, who are also currently 
   showing up without their full name.

 • We'd probably need a *refcount* on the transient buddies, because
   if that same "unknown" person is in an IM window and chat rooms,
   there will be multiple consumers of the same transient buddy.

 • The purple_find_buddies_transient() API is kind of icky, although
   that was mostly a proof-of-concept and could probably be improved.

 • Various places which *assume* that a buddy will have a contact in
   node->parent need to be fixed to cope, if they can see transient
   buddies. I fixed the ones that actually crashed in my testing.

I suppose it could be bashed into shape, and it *is* an important
feature for a number of protocols. But before I press on and try to
make it tolerable, I'm interested in whether anyone has ideas for a
better approach?

One option is *not* to base it on buddies at all, and to provide new
PRPL methods to obtain presence/alias for individuals by name alone,
without there ever being a PurpleBuddy associated with them. The PRPL
*already* doesn't need a PurpleBuddy in order to call
purple_prpl_got_user_status(), and we could add a similar
purple_prpl_got_server_alias() to avoid the PRPL having to see a
PurpleBuddy for that too. Then we have to add a way for the code in
gtkconv.c to receive signals about those changes, which also aren't
based on a PurpleBuddy. Which is probably OK...


Another option is to stick with the "transient buddy" concept but to
let the PRPL manage them. My PRPL already *has* a big list of the
contacts that it's dealing with (in conversations and chat rooms), and
could create a PurpleBuddy for each. The refcounting requirement goes
away then (or at least is pushed down into the PRPL, which in my case
already does it). And instead of the 'hb.group==NULL' thing, maybe we
could just make a special group in the blist which *isn't* displayed in
the UI, and put the "transient" contacts there? That might make a lot
of the complexity of my hack go away...

_______________________________________________
Devel mailing list
[email protected]
https://pidgin.im/cgi-bin/mailman/listinfo/devel
pidgin-im-nonbuddy-status.patch (text/x-patch, 18.5 KB)
diff --git a/libpurple/blist.c b/libpurple/blist.c
index 2233835..143ff27 100644
--- a/libpurple/blist.c
+++ b/libpurple/blist.c
@@ -919,7 +919,7 @@ purple_blist_update_buddy_status(PurpleBuddy *buddy, PurpleStatus *old_status)
 		purple_signal_emit(purple_blist_get_handle(), "buddy-signed-on", buddy);
 
 		cnode = buddy->node.parent;
-		if (++(PURPLE_CONTACT(cnode)->online) == 1)
+		if (cnode && ++(PURPLE_CONTACT(cnode)->online) == 1)
 			PURPLE_GROUP(cnode->parent)->online++;
 	} else if (!purple_status_is_online(status) &&
 				purple_status_is_online(old_status)) {
@@ -928,7 +928,7 @@ purple_blist_update_buddy_status(PurpleBuddy *buddy, PurpleStatus *old_status)
 		purple_signal_emit(purple_blist_get_handle(), "buddy-signed-off", buddy);
 
 		cnode = buddy->node.parent;
-		if (--(PURPLE_CONTACT(cnode)->online) == 0)
+		if (cnode && --(PURPLE_CONTACT(cnode)->online) == 0)
 			PURPLE_GROUP(cnode->parent)->online--;
 	} else {
 		purple_signal_emit(purple_blist_get_handle(),
@@ -1367,6 +1367,8 @@ purple_chat_destroy(PurpleChat *chat)
 PurpleBuddy *purple_buddy_new(PurpleAccount *account, const char *name, const char *alias)
 {
 	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
+	GHashTable *account_buddies;
+	struct _purple_hbuddy *hb, *hb2;
 	PurpleBuddy *buddy;
 
 	g_return_val_if_fail(account != NULL, NULL);
@@ -1383,6 +1385,23 @@ PurpleBuddy *purple_buddy_new(PurpleAccount *account, const char *name, const ch
 
 	purple_blist_node_initialize_settings((PurpleBlistNode *)buddy);
 
+	hb = g_new(struct _purple_hbuddy, 1);
+	hb->name = g_strdup(purple_normalize(buddy->account, buddy->name));
+	hb->account = buddy->account;
+	hb->group = NULL;
+
+	g_hash_table_replace(purplebuddylist->buddies, hb, buddy);
+
+	account_buddies = g_hash_table_lookup(buddies_cache, buddy->account);
+
+	hb2 = g_new(struct _purple_hbuddy, 1);
+	hb2->name = g_strdup(hb->name);
+	hb2->account = buddy->account;
+	hb2->group = NULL;
+
+	g_hash_table_replace(account_buddies, hb2, buddy);
+
+	printf("new buddy %s %s\n", name, alias);
 	if (ops && ops->new_node)
 		ops->new_node((PurpleBlistNode *)buddy);
 
@@ -1657,6 +1676,15 @@ void purple_blist_add_buddy(PurpleBuddy *buddy, PurpleContact *contact, PurpleGr
 			if (ops && ops->update)
 				ops->update(purplebuddylist, bnode->parent);
 		}
+	} else {
+		struct _purple_hbuddy hb;
+		hb.name = (gchar *)purple_normalize(buddy->account, buddy->name);
+		hb.account = buddy->account;
+		hb.group = NULL;
+		g_hash_table_remove(purplebuddylist->buddies, &hb);
+
+		account_buddies = g_hash_table_lookup(buddies_cache, buddy->account);
+		g_hash_table_remove(account_buddies, &hb);
 	}
 
 	if (node && PURPLE_BLIST_NODE_IS_BUDDY(node)) {
@@ -2429,9 +2457,9 @@ const char *purple_chat_get_name(PurpleChat *chat)
 	return ret;
 }
 
-PurpleBuddy *purple_find_buddy(PurpleAccount *account, const char *name)
+PurpleBuddy *purple_find_buddy_transient(PurpleAccount *account, const char *name, gboolean transient)
 {
-	PurpleBuddy *buddy;
+	PurpleBuddy *buddy = NULL;
 	struct _purple_hbuddy hb;
 	PurpleBlistNode *group;
 
@@ -2452,7 +2480,17 @@ PurpleBuddy *purple_find_buddy(PurpleAccount *account, const char *name)
 		}
 	}
 
-	return NULL;
+	if (transient) {
+		hb.group = NULL;
+		buddy = g_hash_table_lookup(purplebuddylist->buddies, &hb);
+	}
+
+	return buddy;
+}
+
+PurpleBuddy *purple_find_buddy(PurpleAccount *account, const char *name)
+{
+	return purple_find_buddy_transient(account, name, FALSE);
 }
 
 PurpleBuddy *purple_find_buddy_in_group(PurpleAccount *account, const char *name,
@@ -2471,7 +2509,7 @@ PurpleBuddy *purple_find_buddy_in_group(PurpleAccount *account, const char *name
 	return g_hash_table_lookup(purplebuddylist->buddies, &hb);
 }
 
-static void find_acct_buddies(gpointer key, gpointer value, gpointer data)
+static void find_acct_buddies_transient(gpointer key, gpointer value, gpointer data)
 {
 	PurpleBuddy *buddy = value;
 	GSList **list = data;
@@ -2479,7 +2517,17 @@ static void find_acct_buddies(gpointer key, gpointer value, gpointer data)
 	*list = g_slist_prepend(*list, buddy);
 }
 
-GSList *purple_find_buddies(PurpleAccount *account, const char *name)
+static void find_acct_buddies(gpointer key, gpointer value, gpointer data)
+{
+	struct _purple_hbuddy *hb = key;
+	PurpleBuddy *buddy = value;
+	GSList **list = data;
+
+	if (hb->group)
+		*list = g_slist_prepend(*list, buddy);
+}
+
+GSList *purple_find_buddies_transient(PurpleAccount *account, const char *name, gboolean transient)
 {
 	PurpleBuddy *buddy;
 	PurpleBlistNode *node;
@@ -2493,6 +2541,10 @@ GSList *purple_find_buddies(PurpleAccount *account, const char *name)
 
 		hb.name = (gchar *)purple_normalize(account, name);
 		hb.account = account;
+		hb.group = NULL;
+
+		if (transient && (buddy = g_hash_table_lookup(purplebuddylist->buddies, &hb)) != NULL)
+			ret = g_slist_prepend(ret, buddy);
 
 		for (node = purplebuddylist->root; node != NULL; node = node->next) {
 			if (!node->child)
@@ -2505,13 +2557,21 @@ GSList *purple_find_buddies(PurpleAccount *account, const char *name)
 	} else {
 		GSList *list = NULL;
 		GHashTable *buddies = g_hash_table_lookup(buddies_cache, account);
-		g_hash_table_foreach(buddies, find_acct_buddies, &list);
+		if (transient)
+			g_hash_table_foreach(buddies, find_acct_buddies_transient, &list);
+		else
+			g_hash_table_foreach(buddies, find_acct_buddies, &list);
 		ret = list;
 	}
 
 	return ret;
 }
 
+GSList *purple_find_buddies(PurpleAccount *account, const char *name)
+{
+	return purple_find_buddies_transient(account, name, FALSE);
+}
+
 PurpleGroup *purple_find_group(const char *name)
 {
 	gchar* key;
diff --git a/libpurple/blist.h b/libpurple/blist.h
index d3cae7a..79e75bd 100644
--- a/libpurple/blist.h
+++ b/libpurple/blist.h
@@ -925,6 +925,7 @@ const char *purple_chat_get_name(PurpleChat *chat);
  * @return        The buddy or NULL if the buddy does not exist
  */
 PurpleBuddy *purple_find_buddy(PurpleAccount *account, const char *name);
+	PurpleBuddy *purple_find_buddy_transient(PurpleAccount *account, const char *name, gboolean transient);
 
 /**
  * Finds the buddy struct given a name, an account, and a group
@@ -947,6 +948,17 @@ PurpleBuddy *purple_find_buddy_in_group(PurpleAccount *account, const char *name
  */
 GSList *purple_find_buddies(PurpleAccount *account, const char *name);
 
+/**
+ * Finds all PurpleBuddy structs given a name and an account
+ *
+ * @param account The account this buddy belongs to
+ * @param name    The buddy's name (or NULL to return all buddies for the account)
+ * @param transient If TRUE, also return transient buddies which are not part of any group
+ *
+ * @return        A GSList of buddies (which must be freed), or NULL if the buddy doesn't exist
+ */
+GSList *purple_find_buddies_transient(PurpleAccount *account, const char *name, gboolean transient);
+
 
 /**
  * Finds a group by name
diff --git a/libpurple/conversation.c b/libpurple/conversation.c
index 9c7705c..f2267e5 100644
--- a/libpurple/conversation.c
+++ b/libpurple/conversation.c
@@ -742,7 +742,7 @@ purple_conversation_autoset_title(PurpleConversation *conv)
 	name = purple_conversation_get_name(conv);
 
 	if(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
-		if(account && ((b = purple_find_buddy(account, name)) != NULL))
+		if(account && ((b = purple_find_buddy_transient(account, name, TRUE)) != NULL))
 			text = purple_buddy_get_contact_alias(b);
 	} else if(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
 		if(account && ((chat = purple_blist_find_chat(account, name)) != NULL))
@@ -986,8 +986,8 @@ purple_conversation_write(PurpleConversation *conv, const char *who,
 			!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
 
 			if (flags & PURPLE_MESSAGE_SEND) {
-				b = purple_find_buddy(account,
-							purple_account_get_username(account));
+				b = purple_find_buddy_transient(account,
+								purple_account_get_username(account), TRUE);
 
 				if (purple_account_get_alias(account) != NULL)
 					alias = account->alias;
@@ -1000,7 +1000,7 @@ purple_conversation_write(PurpleConversation *conv, const char *who,
 			}
 			else
 			{
-				b = purple_find_buddy(account, who);
+				b = purple_find_buddy_transient(account, who, TRUE);
 
 				if (b != NULL)
 					alias = purple_buddy_get_contact_alias(b);
@@ -1695,7 +1695,7 @@ purple_conv_chat_add_users(PurpleConvChat *chat, GList *users, GList *extra_msgs
 				}
 			} else {
 				PurpleBuddy *buddy;
-				if ((buddy = purple_find_buddy(gc->account, user)) != NULL)
+				if ((buddy = purple_find_buddy_transient(gc->account, user, TRUE)) != NULL)
 					alias = purple_buddy_get_contact_alias(buddy);
 			}
 		}
@@ -1793,7 +1793,7 @@ purple_conv_chat_rename_user(PurpleConvChat *chat, const char *old_user,
 		}
 	} else if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
 		PurpleBuddy *buddy;
-		if ((buddy = purple_find_buddy(gc->account, new_user)) != NULL)
+		if ((buddy = purple_find_buddy_transient(gc->account, new_user, TRUE)) != NULL)
 			new_alias = purple_buddy_get_contact_alias(buddy);
 	}
 
@@ -1842,9 +1842,9 @@ purple_conv_chat_rename_user(PurpleConvChat *chat, const char *old_user,
 			if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
 				PurpleBuddy *buddy;
 
-				if ((buddy = purple_find_buddy(gc->account, old_user)) != NULL)
+				if ((buddy = purple_find_buddy_transient(gc->account, old_user, TRUE)) != NULL)
 					old_alias = purple_buddy_get_contact_alias(buddy);
-				if ((buddy = purple_find_buddy(gc->account, new_user)) != NULL)
+				if ((buddy = purple_find_buddy_transient(gc->account, new_user, TRUE)) != NULL)
 					new_alias = purple_buddy_get_contact_alias(buddy);
 			}
 
@@ -1919,7 +1919,7 @@ purple_conv_chat_remove_users(PurpleConvChat *chat, GList *users, const char *re
 			if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
 				PurpleBuddy *buddy;
 
-				if ((buddy = purple_find_buddy(gc->account, user)) != NULL)
+				if ((buddy = purple_find_buddy_transient(gc->account, user, TRUE)) != NULL)
 					alias = purple_buddy_get_contact_alias(buddy);
 			}
 
diff --git a/libpurple/prpl.c b/libpurple/prpl.c
index 5dc589a..c591456 100644
--- a/libpurple/prpl.c
+++ b/libpurple/prpl.c
@@ -203,7 +203,7 @@ purple_prpl_got_user_idle(PurpleAccount *account, const char *name,
 	g_return_if_fail(name    != NULL);
 	g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account));
 
-	if ((list = purple_find_buddies(account, name)) == NULL)
+	if ((list = purple_find_buddies_transient(account, name, TRUE)) == NULL)
 		return;
 
 	while (list) {
@@ -223,7 +223,7 @@ purple_prpl_got_user_login_time(PurpleAccount *account, const char *name,
 	g_return_if_fail(account != NULL);
 	g_return_if_fail(name    != NULL);
 
-	if ((list = purple_find_buddies(account, name)) == NULL)
+	if ((list = purple_find_buddies_transient(account, name, TRUE)) == NULL)
 		return;
 
 	if (login_time == 0)
@@ -259,7 +259,7 @@ purple_prpl_got_user_status(PurpleAccount *account, const char *name,
 	g_return_if_fail(status_id != NULL);
 	g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account));
 
-	if((list = purple_find_buddies(account, name)) == NULL)
+	if((list = purple_find_buddies_transient(account, name, TRUE)) == NULL)
 		return;
 
 	for(l = list; l != NULL; l = l->next) {
@@ -307,7 +307,7 @@ void purple_prpl_got_user_status_deactive(PurpleAccount *account, const char *na
 	g_return_if_fail(status_id != NULL);
 	g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account));
 
-	if((list = purple_find_buddies(account, name)) == NULL)
+	if((list = purple_find_buddies_transient(account, name, TRUE)) == NULL)
 		return;
 
 	for(l = list; l != NULL; l = l->next) {
@@ -446,7 +446,7 @@ purple_prpl_send_attention(PurpleConnection *gc, const char *who, guint type_cod
 
 	attn = purple_get_attention_type_from_code(gc->account, type_code);
 
-	if ((buddy = purple_find_buddy(purple_connection_get_account(gc), who)) != NULL)
+	if ((buddy = purple_find_buddy_transient(purple_connection_get_account(gc), who, TRUE)) != NULL)
 		alias = purple_buddy_get_contact_alias(buddy);
 	else
 		alias = who;
@@ -492,7 +492,7 @@ got_attention(PurpleConnection *gc, int id, const char *who, guint type_code)
 	/* TODO: if (attn->icon_name) is non-null, use it to lookup an emoticon and display
 	 * it next to the attention command. And if it is null, display a generic icon. */
 
-	if ((buddy = purple_find_buddy(purple_connection_get_account(gc), who)) != NULL)
+	if ((buddy = purple_find_buddy_transient(purple_connection_get_account(gc), who, TRUE)) != NULL)
 		alias = purple_buddy_get_contact_alias(buddy);
 	else
 		alias = who;
@@ -593,7 +593,7 @@ purple_prpl_got_media_caps(PurpleAccount *account, const char *name)
 	g_return_if_fail(account != NULL);
 	g_return_if_fail(name    != NULL);
 
-	if ((list = purple_find_buddies(account, name)) == NULL)
+	if ((list = purple_find_buddies_transient(account, name, TRUE)) == NULL)
 		return;
 
 	while (list) {
diff --git a/pidgin/gtkblist.c b/pidgin/gtkblist.c
index f200eb4..f2462fc 100644
--- a/pidgin/gtkblist.c
+++ b/pidgin/gtkblist.c
@@ -3995,7 +3995,7 @@ pidgin_blist_get_emblem(PurpleBlistNode *node)
 			return _pidgin_blist_get_cached_emblem(path);
 		}
 
-		if (((struct _pidgin_blist_node*)(node->parent->ui_data))->contact_expanded) {
+		if (node->parent && ((struct _pidgin_blist_node*)(node->parent->ui_data))->contact_expanded) {
 			if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons"))
 				return NULL;
 			return pidgin_create_prpl_icon(((PurpleBuddy*)node)->account, PIDGIN_PRPL_ICON_SMALL);
diff --git a/pidgin/gtkconv.c b/pidgin/gtkconv.c
index 5075783..ba1f4f2 100644
--- a/pidgin/gtkconv.c
+++ b/pidgin/gtkconv.c
@@ -1022,7 +1022,7 @@ menu_save_as_cb(gpointer data, guint action, GtkWidget *widget)
 {
 	PidginWindow *win = data;
 	PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win);
-	PurpleBuddy *buddy = purple_find_buddy(conv->account, conv->name);
+	PurpleBuddy *buddy = purple_find_buddy_transient(conv->account, conv->name, TRUE);
 	const char *name;
 	gchar *buf;
 	gchar *c;
@@ -2437,7 +2437,8 @@ pidgin_conv_get_tab_icons(PurpleConversation *conv)
 
 	/* Use the buddy icon, if possible */
 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
-		PurpleBuddy *b = purple_find_buddy(account, name);
+		PurpleBuddy *b = purple_find_buddy_transient(account, name, TRUE);
+		printf("icons, buddy for %p %s %p\n", account, name, b);
 		if (b != NULL) {
 			PurplePresence *p;
 			p = purple_buddy_get_presence(b);
@@ -2473,7 +2474,7 @@ pidgin_conv_get_icon_stock(PurpleConversation *conv)
 		const char *name = NULL;
 		PurpleBuddy *b;
 		name = purple_conversation_get_name(conv);
-		b = purple_find_buddy(account, name);
+		b = purple_find_buddy_transient(account, name, TRUE);
 		if (b != NULL) {
 			PurplePresence *p = purple_buddy_get_presence(b);
 			PurpleStatus *active = purple_presence_get_active_status(p);
@@ -2554,7 +2555,7 @@ update_tab_icon(PurpleConversation *conv)
 	status = infopane_status = pidgin_conv_get_icon_stock(conv);
 
 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
-		PurpleBuddy *b = purple_find_buddy(conv->account, conv->name);
+		PurpleBuddy *b = purple_find_buddy_transient(conv->account, conv->name, TRUE);
 		if (b)
 			emblem = pidgin_blist_get_emblem((PurpleBlistNode*)b);
 	}
@@ -4838,8 +4839,8 @@ pidgin_conv_create_tooltip(GtkWidget *tipwindow, gpointer userdata, int *w, int
 		if (!node)
 			node = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_chat");
 	} else {
-		node = (PurpleBlistNode*)(purple_find_buddy(conv->account, conv->name));
-#if 0
+		node = (PurpleBlistNode*)(purple_find_buddy_transient(conv->account, conv->name, TRUE));
+#if 1
 		/* Using the transient blist nodes to show the tooltip doesn't quite work yet. */
 		if (!node)
 			node = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_buddy");
@@ -4977,8 +4978,8 @@ setup_common_pane(PidginConversation *gtkconv)
 	else {
 		gtkconv->u.im->icon_container = gtk_vbox_new(FALSE, 0);
 
-		if ((buddy = purple_find_buddy(purple_conversation_get_account(conv),
-						purple_conversation_get_name(conv))) != NULL) {
+		if ((buddy = purple_find_buddy_transient(purple_conversation_get_account(conv),
+							 purple_conversation_get_name(conv), TRUE)) != NULL) {
 			PurpleContact *contact = purple_buddy_get_contact(buddy);
 			if (contact) {
 				buddyicon_size = purple_blist_node_get_int((PurpleBlistNode*)contact, "pidgin-infopane-iconsize");
@@ -5234,7 +5235,7 @@ static const GtkTargetEntry te[] =
 static PidginConversation *
 pidgin_conv_find_gtkconv(PurpleConversation * conv)
 {
-	PurpleBuddy *bud = purple_find_buddy(conv->account, conv->name);
+	PurpleBuddy *bud = purple_find_buddy_transient(conv->account, conv->name, TRUE);
 	PurpleContact *c;
 	PurpleBlistNode *cn, *bn;
 
@@ -6799,7 +6800,7 @@ pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields)
 			title = g_strdup(purple_conversation_get_title(conv));
 
 		if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
-			buddy = purple_find_buddy(account, conv->name);
+			buddy = purple_find_buddy_transient(account, conv->name, TRUE);
 			if (buddy) {
 				markup = pidgin_blist_get_name_markup(buddy, FALSE, FALSE);
 			} else {
@@ -7059,7 +7060,7 @@ pidgin_conv_update_buddy_icon(PurpleConversation *conv)
 	if (purple_conversation_get_gc(conv) == NULL)
 		return;
 
-	buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
+	buddy = purple_find_buddy_transient(account, purple_conversation_get_name(conv), TRUE);
 	if (buddy)
 	{
 		PurpleContact *contact = purple_buddy_get_contact(buddy);
@@ -7612,6 +7613,7 @@ update_buddy_status_changed(PurpleBuddy *buddy, PurpleStatus *old, PurpleStatus
 	PurpleConversation *conv;
 
 	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account);
+	printf("%s %s conv %p\n", __func__, buddy->name, conv);
 	if (conv)
 	{
 		pidgin_conv_update_fields(conv, PIDGIN_CONV_TAB_ICON
@@ -7658,7 +7660,9 @@ update_buddy_sign(PurpleBuddy *buddy, const char *which)
 	PurplePresence *presence;
 	PurpleStatus *on, *off;
 
+	printf("%s %s\n", __func__, which);
 	presence = purple_buddy_get_presence(buddy);
+	printf("presence %p\n", presence);
 	if (!presence)
 		return;
 	off = purple_presence_get_status(presence, "offline");
@@ -9064,7 +9068,7 @@ infopane_entry_activate(PidginConversation *gtkconv)
 	}
 
 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
-		PurpleBuddy *buddy = purple_find_buddy(gtkconv->active_conv->account, gtkconv->active_conv->name);
+		PurpleBuddy *buddy = purple_find_buddy_transient(gtkconv->active_conv->account, gtkconv->active_conv->name, TRUE);
 		if (!buddy)
 			/* This buddy isn't in your buddy list, so we can't alias him */
 			return FALSE;
smime.p7s (application/x-pkcs7-signature, 5.1 KB) - not displayed