changeset 28184:f9cf1e14838b

irc: Handle a buddy appearing in multiple groups properly. Handle multiple PurpleBuddy's corresponding to the same buddy with a reference count in struct irc_buddy and fix a string corruption that would be caused by using g_hash_table_insert instead of replace (the wrong string is freed).
author Paul Aurich <paul@darkrain42.org>
date Thu, 06 Aug 2009 04:59:12 +0000
parents 0e516784bbae
children 36f23fdb58b6 975fc5f64438
files ChangeLog libpurple/protocols/irc/irc.c libpurple/protocols/irc/irc.h libpurple/protocols/irc/msgs.c
diffstat 4 files changed, 24 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Aug 06 03:23:05 2009 +0000
+++ b/ChangeLog	Thu Aug 06 04:59:12 2009 +0000
@@ -45,6 +45,7 @@
 	  the dialog icons, and the Buddy List emblems.
 	* Build properly on Hurd.  (Marc Dequènes)
 	* Various memory leaks fixed as reported by Josh Mueller.
+	* Properly handle an IRC buddy appearing in multiple groups.
 
 	AIM and ICQ:
 	* Preliminary support for a new authentication scheme called
--- a/libpurple/protocols/irc/irc.c	Thu Aug 06 03:23:05 2009 +0000
+++ b/libpurple/protocols/irc/irc.c	Thu Aug 06 04:59:12 2009 +0000
@@ -569,9 +569,20 @@
 static void irc_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
 {
 	struct irc_conn *irc = (struct irc_conn *)gc->proto_data;
-	struct irc_buddy *ib = g_new0(struct irc_buddy, 1);
-	ib->name = g_strdup(purple_buddy_get_name(buddy));
-	g_hash_table_replace(irc->buddies, ib->name, ib);
+	struct irc_buddy *ib;
+	const char *bname = purple_buddy_get_name(buddy);
+
+	ib = g_hash_table_lookup(irc->buddies, bname);
+	if (ib != NULL) {
+		ib->ref++;
+		purple_prpl_got_user_status(irc->account, bname,
+				ib->online ? "available" : "offline", NULL);
+	} else {
+		ib = g_new0(struct irc_buddy, 1);
+		ib->name = g_strdup(bname);
+		ib->ref = 1;
+		g_hash_table_replace(irc->buddies, ib->name, ib);
+	}
 
 	/* if the timer isn't set, this is during signon, so we don't want to flood
 	 * ourself off with ISON's, so we don't, but after that we want to know when
@@ -583,7 +594,12 @@
 static void irc_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
 {
 	struct irc_conn *irc = (struct irc_conn *)gc->proto_data;
-	g_hash_table_remove(irc->buddies, purple_buddy_get_name(buddy));
+	struct irc_buddy *ib;
+
+	ib = g_hash_table_lookup(irc->buddies, purple_buddy_get_name(buddy));
+	if (ib && --ib->ref == 0) {
+		g_hash_table_remove(irc->buddies, purple_buddy_get_name(buddy));
+	}
 }
 
 static void read_input(struct irc_conn *irc, int len)
--- a/libpurple/protocols/irc/irc.h	Thu Aug 06 03:23:05 2009 +0000
+++ b/libpurple/protocols/irc/irc.h	Thu Aug 06 04:59:12 2009 +0000
@@ -97,6 +97,7 @@
 	char *name;
 	gboolean online;
 	gboolean flag;
+	int ref;
 };
 
 typedef int (*IRCCmdCallback) (struct irc_conn *irc, const char *cmd, const char *target, const char **args);
--- a/libpurple/protocols/irc/msgs.c	Thu Aug 06 03:23:05 2009 +0000
+++ b/libpurple/protocols/irc/msgs.c	Thu Aug 06 04:59:12 2009 +0000
@@ -103,7 +103,8 @@
 		PurpleBuddy *b = buddies->data;
 		struct irc_buddy *ib = g_new0(struct irc_buddy, 1);
 		ib->name = g_strdup(purple_buddy_get_name(b));
-		g_hash_table_insert(irc->buddies, ib->name, ib);
+		ib->ref = 1;
+		g_hash_table_replace(irc->buddies, ib->name, ib);
 	}
 
 	irc_blist_timeout(irc);