# HG changeset patch # User Paul Aurich # Date 1249534752 0 # Node ID f9cf1e14838b6df72ddfa4c396cd8a1511398379 # Parent 0e516784bbaec40161bd78ee1c62adee055d8d59 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). diff -r 0e516784bbae -r f9cf1e14838b ChangeLog --- 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 diff -r 0e516784bbae -r f9cf1e14838b libpurple/protocols/irc/irc.c --- 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) diff -r 0e516784bbae -r f9cf1e14838b libpurple/protocols/irc/irc.h --- 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); diff -r 0e516784bbae -r f9cf1e14838b libpurple/protocols/irc/msgs.c --- 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);