changeset 22975:d50194ab3016

Bonjour buddies will be saved persistently if they're moved out of the "Bonjour" group. Thanks to Eion Robb for the patch (blame me if something is broken as I tweaked a few things). Fixes #5753.
author Daniel Atallah <daniel.atallah@gmail.com>
date Fri, 16 May 2008 18:21:09 +0000
parents 8ac3ffa6841e
children 0f2bf1d5fdfc
files ChangeLog libpurple/protocols/bonjour/bonjour.c libpurple/protocols/bonjour/buddy.c libpurple/protocols/bonjour/buddy.h libpurple/protocols/bonjour/mdns_avahi.c libpurple/protocols/bonjour/mdns_win32.c
diffstat 6 files changed, 82 insertions(+), 59 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri May 16 16:04:05 2008 +0000
+++ b/ChangeLog	Fri May 16 18:21:09 2008 +0000
@@ -20,6 +20,8 @@
 	  and not those that have simply moved groups.
 	* IRC will now try to append 1-9 to your nick if it is in use, instead
 	  of substituting the last character with 1-9 where possible.
+	* Bonjour buddies will be saved persistently if they're moved out of
+	  the "Bonjour" group. (Eion Robb)
 
 	Pidgin:
 	* The typing notification in the conversation history can be disabled or
--- a/libpurple/protocols/bonjour/bonjour.c	Fri May 16 16:04:05 2008 +0000
+++ b/libpurple/protocols/bonjour/bonjour.c	Fri May 16 18:21:09 2008 +0000
@@ -49,48 +49,39 @@
 static char *default_hostname;
 
 static void
-bonjour_removeallfromlocal(PurpleConnection *gc)
+bonjour_removeallfromlocal(PurpleConnection *conn, PurpleGroup *bonjour_group)
 {
-	PurpleAccount *account = purple_connection_get_account(gc);
-	PurpleBuddyList *blist;
-	PurpleBlistNode *gnode, *cnode, *cnodenext, *bnode, *bnodenext;
+	PurpleAccount *account = purple_connection_get_account(conn);
+	PurpleBlistNode *cnode, *cnodenext, *bnode, *bnodenext;
 	PurpleBuddy *buddy;
 
-	blist = purple_get_blist();
-	if (blist == NULL)
+	if (bonjour_group == NULL)
 		return;
 
 	/* Go through and remove all buddies that belong to this account */
-	for (gnode = blist->root; gnode; gnode = gnode->next)
-	{
-		if (!PURPLE_BLIST_NODE_IS_GROUP(gnode))
+	for (cnode = ((PurpleBlistNode *) bonjour_group)->child; cnode; cnode = cnodenext) {
+		cnodenext = cnode->next;
+		if (!PURPLE_BLIST_NODE_IS_CONTACT(cnode))
 			continue;
-		for (cnode = gnode->child; cnode; cnode = cnodenext)
-		{
-			cnodenext = cnode->next;
-			if (!PURPLE_BLIST_NODE_IS_CONTACT(cnode))
+		for (bnode = cnode->child; bnode; bnode = bnodenext) {
+			bnodenext = bnode->next;
+			if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode))
 				continue;
-			for (bnode = cnode->child; bnode; bnode = bnodenext)
-			{
-				bnodenext = bnode->next;
-				if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode))
-					continue;
-				buddy = (PurpleBuddy *)bnode;
-				if (buddy->account != account)
-					continue;
-				purple_prpl_got_user_status(account, buddy->name, "offline", NULL);
-				purple_account_remove_buddy(account, buddy, NULL);
-				purple_blist_remove_buddy(buddy);
-			}
+			buddy = (PurpleBuddy *) bnode;
+			if (buddy->account != account)
+				continue;
+			purple_prpl_got_user_status(account, buddy->name, "offline", NULL);
+			purple_account_remove_buddy(account, buddy, NULL);
+			purple_blist_remove_buddy(buddy);
 		}
 	}
+
 }
 
 static void
 bonjour_login(PurpleAccount *account)
 {
 	PurpleConnection *gc = purple_account_get_connection(account);
-	PurpleGroup *bonjour_group;
 	BonjourData *bd;
 	PurpleStatus *status;
 	PurplePresence *presence;
@@ -151,10 +142,6 @@
 
 	bonjour_dns_sd_update_buddy_icon(bd->dns_sd_data);
 
-	/* Create a group for bonjour buddies */
-	bonjour_group = purple_group_new(BONJOUR_GROUP_NAME);
-	purple_blist_add_group(bonjour_group, NULL);
-
 	/* Show the buddy list by telling Purple we have already connected */
 	purple_connection_set_state(gc, PURPLE_CONNECTED);
 }
@@ -165,8 +152,10 @@
 	PurpleGroup *bonjour_group;
 	BonjourData *bd = connection->proto_data;
 
+	bonjour_group = purple_find_group(BONJOUR_GROUP_NAME);
+
 	/* Remove all the bonjour buddies */
-	bonjour_removeallfromlocal(connection);
+	bonjour_removeallfromlocal(connection, bonjour_group);
 
 	/* Stop looking for buddies in the LAN */
 	if (bd != NULL && bd->dns_sd_data != NULL)
@@ -183,7 +172,6 @@
 	}
 
 	/* Delete the bonjour group */
-	bonjour_group = purple_find_group(BONJOUR_GROUP_NAME);
 	if (bonjour_group != NULL)
 		purple_blist_remove_group(bonjour_group);
 
@@ -405,6 +393,25 @@
 		purple_notify_user_info_add_pair(user_info, _("XMPP Account"), bb->jid);
 }
 
+static void
+bonjour_group_buddy(PurpleConnection *connection, const char *who, const char *old_group, const char *new_group)
+{
+	PurpleBlistNodeFlags oldflags;
+	PurpleBuddy *buddy = purple_find_buddy(connection->account, who);
+
+	if (buddy == NULL)
+		return;
+
+	oldflags = purple_blist_node_get_flags((PurpleBlistNode *)buddy);
+
+	/* If we're moving them out of the bonjour group, make them persistent */
+	if (strcmp(new_group, BONJOUR_GROUP_NAME) == 0)
+		purple_blist_node_set_flags((PurpleBlistNode *)buddy, oldflags | PURPLE_BLIST_NODE_FLAG_NO_SAVE);
+	else
+		purple_blist_node_set_flags((PurpleBlistNode *)buddy, oldflags ^ PURPLE_BLIST_NODE_FLAG_NO_SAVE);
+
+}
+
 static gboolean
 plugin_unload(PurplePlugin *plugin)
 {
@@ -463,7 +470,7 @@
 	NULL,                                                    /* get_cb_info */
 	NULL,                                                    /* get_cb_away */
 	NULL,                                                    /* alias_buddy */
-	NULL,                                                    /* group_buddy */
+	bonjour_group_buddy,                                     /* group_buddy */
 	NULL,                                                    /* rename_group */
 	NULL,                                                    /* buddy_free */
 	bonjour_convo_closed,                                    /* convo_closed */
--- a/libpurple/protocols/bonjour/buddy.c	Fri May 16 16:04:05 2008 +0000
+++ b/libpurple/protocols/bonjour/buddy.c	Fri May 16 18:21:09 2008 +0000
@@ -153,11 +153,12 @@
 
 	if (buddy == NULL) {
 		buddy = purple_buddy_new(account, bonjour_buddy->name, NULL);
-		buddy->proto_data = bonjour_buddy;
 		purple_blist_node_set_flags((PurpleBlistNode *)buddy, PURPLE_BLIST_NODE_FLAG_NO_SAVE);
 		purple_blist_add_buddy(buddy, NULL, group, NULL);
 	}
-
+	
+	buddy->proto_data = bonjour_buddy;
+	
 	/* Create the alias for the buddy using the first and the last name */
 	if (bonjour_buddy->nick)
 		serv_got_alias(purple_account_get_connection(account), buddy->name, bonjour_buddy->nick);
@@ -201,6 +202,20 @@
 }
 
 /**
+ * The buddy has signed off Bonjour.
+ * If the buddy is being saved, mark as offline, otherwise delete
+ */
+void bonjour_buddy_signed_off(PurpleBuddy *pb) {
+	if (PURPLE_BLIST_NODE_SHOULD_SAVE(pb))
+		purple_prpl_got_user_status(purple_buddy_get_account(pb),
+					    purple_buddy_get_name(pb), "offline", NULL);
+	else {
+		purple_account_remove_buddy(purple_buddy_get_account(pb), pb, NULL);
+		purple_blist_remove_buddy(pb);
+	}
+}
+
+/**
  * We got the buddy icon data; deal with it
  */
 void bonjour_buddy_got_buddy_icon(BonjourBuddy *buddy, gconstpointer data, gsize len) {
--- a/libpurple/protocols/bonjour/buddy.h	Fri May 16 16:04:05 2008 +0000
+++ b/libpurple/protocols/bonjour/buddy.h	Fri May 16 18:21:09 2008 +0000
@@ -90,12 +90,18 @@
 gboolean bonjour_buddy_check(BonjourBuddy *buddy);
 
 /**
- * If the buddy doesn't previoulsy exists, it is created. Else, its data is changed (???)
+ * If the buddy doesn't previously exists, it is created. Else, its data is changed (???)
  * purple_buddy is optional; it saves an additional lookup if we already have it
  */
 void bonjour_buddy_add_to_purple(BonjourBuddy *bonjour_buddy, PurpleBuddy *purple_buddy);
 
 /**
+ * The buddy has signed off Bonjour.
+ * If the buddy is being saved, mark as offline, otherwise delete
+ */
+void bonjour_buddy_signed_off(PurpleBuddy *purple_buddy);
+
+/**
  * We got the buddy icon data; deal with it
  */
 void bonjour_buddy_got_buddy_icon(BonjourBuddy *buddy, gconstpointer data, gsize len);
--- a/libpurple/protocols/bonjour/mdns_avahi.c	Fri May 16 16:04:05 2008 +0000
+++ b/libpurple/protocols/bonjour/mdns_avahi.c	Fri May 16 18:21:09 2008 +0000
@@ -144,10 +144,8 @@
 					_cleanup_resolver_data(rd);
 
 					/* If this was the last resolver, remove the buddy */
-					if (b_impl->resolvers == NULL) {
-						purple_account_remove_buddy(account, pb, NULL);
-						purple_blist_remove_buddy(pb);
-					}
+					if (b_impl->resolvers == NULL)
+						bonjour_buddy_signed_off(pb);
 				}
 			}
 			break;
@@ -206,10 +204,9 @@
 				b_impl->resolvers = g_slist_remove(b_impl->resolvers, rd);
 				/* If this was the last resolver, remove the buddy */
 				if (b_impl->resolvers == NULL) {
-					if (pb != NULL) {
-						purple_account_remove_buddy(account, pb, NULL);
-						purple_blist_remove_buddy(pb);
-					} else
+					if (pb != NULL)
+						bonjour_buddy_signed_off(pb);
+					else
 						bonjour_buddy_delete(bb);
 				}
 			} else
@@ -288,10 +285,8 @@
 					_cleanup_resolver_data(rd);
 
 					/* If this was the last resolver, remove the buddy */
-					if (b_impl->resolvers == NULL) {
-						purple_account_remove_buddy(account, pb, NULL);
-						purple_blist_remove_buddy(pb);
-					}
+					if (b_impl->resolvers == NULL)
+						bonjour_buddy_signed_off(pb);
 				}
 			}
 			break;
--- a/libpurple/protocols/bonjour/mdns_win32.c	Fri May 16 16:04:05 2008 +0000
+++ b/libpurple/protocols/bonjour/mdns_win32.c	Fri May 16 18:21:09 2008 +0000
@@ -222,10 +222,9 @@
 
 		/* If this was the last resolver, remove the buddy */
 		if (idata->resolvers == NULL) {
-			if (pb) {
-				purple_account_remove_buddy(args->account, pb, NULL);
-				purple_blist_remove_buddy(pb);
-			} else
+			if (pb)
+				bonjour_buddy_signed_off(pb);
+			else
 				bonjour_buddy_delete(args->bb);
 
 			/* Remove from the pending list */
@@ -282,10 +281,9 @@
 	if (idata->resolvers == NULL) {
 		PurpleBuddy *pb;
 		/* See if this is now attached to a PurpleBuddy */
-		if ((pb = purple_find_buddy(args->account, args->bb->name))) {
-			purple_account_remove_buddy(args->account, pb, NULL);
-			purple_blist_remove_buddy(pb);
-		} else {
+		if ((pb = purple_find_buddy(args->account, args->bb->name)))
+			bonjour_buddy_signed_off(pb);
+		else {
 			/* Remove from the pending list */
 			pending_buddies = g_slist_remove(pending_buddies, args->bb);
 			bonjour_buddy_delete(args->bb);
@@ -427,9 +425,9 @@
 
 				/* If this was the last resolver, remove the buddy */
 				if (idata->resolvers == NULL) {
-					purple_debug_info("bonjour", "Removed last presence for buddy '%s'; removing buddy.\n", serviceName);
-					purple_account_remove_buddy(account, pb, NULL);
-					purple_blist_remove_buddy(pb);
+					purple_debug_info("bonjour", "Removed last presence for buddy '%s'; signing off buddy.\n",
+							  serviceName);
+					bonjour_buddy_signed_off(pb);
 				}
 			}
 		} else {