changeset 26277:cda506a2e825

propagate from branch 'im.pidgin.pidgin' (head 2476e13ecb1702a744a13c42956b29a962a0c7fb) to branch 'im.pidgin.cpw.darkrain42.xmpp.avatars' (head dc5e7754636d7f65cf3f87eba16b3ed7098c4382)
author Paul Aurich <paul@darkrain42.org>
date Fri, 27 Mar 2009 07:56:25 +0000
parents ba1799f21383 (diff) 7027cc42e56c (current diff)
children 14e1f9af369f
files
diffstat 27 files changed, 181 insertions(+), 143 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sat Mar 21 03:50:14 2009 +0000
+++ b/ChangeLog	Fri Mar 27 07:56:25 2009 +0000
@@ -4,6 +4,8 @@
 	General:
 	* Theme support in libpurple thanks to Justin Rodriguez's summer of code
 	  project.  With some minor additions and clean ups from Paul Aurich.
+	* It should no longer be possible to end up with duplicates of buddies
+	  in a group on the buddy list.
 
 	XMPP:
 	* Add support for in-band bytestreams for file transfers (XEP-0047).
@@ -22,6 +24,8 @@
 	* Created a unified Buddy Pounce notification window for all pounces
 	  where "Pop up a notification" is selected, which avoids having a
 	  new dialog box every time a pounce is triggered. (Jorge VillaseƱor) 
+	* The New Account dialog is now broken into three tabs.  Proxy
+	  configuration has been moved from the Advanced tab to the new tab.
 
 version 2.5.5 (03/01/2009):
 	libpurple:
--- a/ChangeLog.API	Sat Mar 21 03:50:14 2009 +0000
+++ b/ChangeLog.API	Fri Mar 27 07:56:25 2009 +0000
@@ -30,10 +30,10 @@
 
 		Changed:
 		* xmlnode_remove_attrib now removes all attributes with the
-		same name.  Previously, it would remove the first one found,
-		which was completely non-deterministic.  If you want to remove
-		the attribute with no namespace, then use NULL with
-		xmlnode_remove_with_namespace.
+		  same name.  Previously, it would remove the first one found,
+		  which was completely non-deterministic.  If you want to remove
+		  the attribute with no namespace, then use NULL with
+		  xmlnode_remove_with_namespace.
 
 		Deprecated:
 		* purple_buddy_get_local_alias
--- a/finch/gntblist.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/finch/gntblist.c	Fri Mar 27 07:56:25 2009 +0000
@@ -643,10 +643,14 @@
 		purple_blist_add_group(grp, NULL);
 	}
 
-	/* XXX: Ask if there's already the same buddy in the same group (#4553) */
-
-	buddy = purple_buddy_new(account, username, alias);
-	purple_blist_add_buddy(buddy, NULL, grp, NULL);
+	/* XXX: Ask to merge if there's already a buddy with the same alias in the same group (#4553) */
+
+	if ((buddy = purple_find_buddy_in_group(account, username, grp)) == NULL)
+	{
+		buddy = purple_buddy_new(account, username, alias);
+		purple_blist_add_buddy(buddy, NULL, grp, NULL);
+	}
+
 	purple_account_add_buddy(account, buddy);
 }
 
--- a/libpurple/protocols/bonjour/mdns_win32.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/libpurple/protocols/bonjour/mdns_win32.c	Fri Mar 27 07:56:25 2009 +0000
@@ -169,14 +169,17 @@
 	gboolean delete_buddy = FALSE;
 	PurpleBuddy *pb = NULL;
 
+	if ((pb = purple_find_buddy(args->account, args->res_data->name))) {
+		if (pb->proto_data != args->bb) {
+			purple_debug_error("bonjour", "Found purple buddy for %s not matching bonjour buddy record.",
+				args->res_data->name);
+			goto cleanup;
+		}
 	/* Make sure that the BonjourBuddy associated with this request is still around */
-	if (g_slist_find(pending_buddies, args->bb) == NULL)
+	} else if (g_slist_find(pending_buddies, args->bb) == NULL) {
+		purple_debug_error("bonjour", "host resolution - complete, but buddy no longer pending.\n");
 		goto cleanup;
-
-	if ((pb = purple_find_buddy(args->account, args->bb->name)))
-		if (pb->proto_data != args->bb)
-			purple_debug_error("bonjour", "Found purple buddy for %s not matching bonjour buddy record. "
-				"This is going to be ugly!.\n", args->bb->name);
+	}
 
 	if (!hosts || !hosts->data) {
 		purple_debug_error("bonjour", "host resolution - callback error.\n");
--- a/libpurple/protocols/irc/irc.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/libpurple/protocols/irc/irc.c	Fri Mar 27 07:56:25 2009 +0000
@@ -565,7 +565,7 @@
 	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_insert(irc->buddies, ib->name, ib);
+	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
--- a/libpurple/protocols/msn/contact.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/libpurple/protocols/msn/contact.c	Fri Mar 27 07:56:25 2009 +0000
@@ -1482,8 +1482,6 @@
 			  const gchar *passport, const MsnListId list)
 {
 	gchar *body = NULL, *member = NULL;
-	const char *type = "PassportMember";
-	gchar *federate = NULL;
 	MsnSoapPartnerScenario partner_scenario;
 	MsnUser *user;
 
@@ -1501,23 +1499,28 @@
 	msn_callback_state_set_who(state, passport);
 
 	user = msn_userlist_find_user(session->userlist, passport);
-	if (user && user->networkid != MSN_NETWORK_PASSPORT) {
-		type = "EmailMember";
-		federate = g_strdup_printf(MSN_MEMBER_FEDERATED_ANNOTATION_XML,
-		                           user->networkid);
-	}
 	
 	if (list == MSN_LIST_PL) {
 		partner_scenario = MSN_PS_CONTACT_API;
-		member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML,
-		                         type, user->membership_id[MSN_LIST_PL],
-		                         federate ? federate : "");
+		if (user && user->networkid != MSN_NETWORK_PASSPORT)
+			member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML,
+			                         "EmailMember", "Email",
+			                         user->membership_id[MSN_LIST_PL]);
+		else
+			member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML,
+			                         "PassportMember", "Passport",
+			                         user->membership_id[MSN_LIST_PL]);
 	} else {
 		/* list == MSN_LIST_AL || list == MSN_LIST_BL */
 		partner_scenario = MSN_PS_BLOCK_UNBLOCK;
-		member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
-		                         type, passport,
-		                         federate ? federate : "");
+		if (user && user->networkid != MSN_NETWORK_PASSPORT)
+			member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
+			                         "EmailMember", "Email",
+			                         "Email", passport, "Email");
+		else
+			member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
+			                         "PassportMember", "Passport",
+			                         "PassportName", passport, "PassportName");
 	}
 
 	body = g_strdup_printf(MSN_CONTACT_DELETE_FROM_LIST_TEMPLATE,
@@ -1530,7 +1533,6 @@
 	state->cb = msn_del_contact_from_list_read_cb;
 	msn_contact_request(state);
 
-	g_free(federate);
 	g_free(member);
 	g_free(body);
 }
@@ -1578,8 +1580,6 @@
 			const gchar *passport, const MsnListId list)
 {
 	gchar *body = NULL, *member = NULL;
-	const char *type = "PassportMember";
-	gchar *federate = NULL;
 	MsnSoapPartnerScenario partner_scenario;
 	MsnUser *user;
 
@@ -1596,15 +1596,16 @@
 	msn_callback_state_set_who(state, passport);
 
 	user = msn_userlist_find_user(session->userlist, passport);
-	if (user && user->networkid != MSN_NETWORK_PASSPORT) {
-		type = "EmailMember";
-		federate = g_strdup_printf(MSN_MEMBER_FEDERATED_ANNOTATION_XML,
-		                           user->networkid);
-	}
 
 	partner_scenario = (list == MSN_LIST_RL) ? MSN_PS_CONTACT_API : MSN_PS_BLOCK_UNBLOCK;
-	member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
-	                         type, state->who, federate ? federate : "");
+	if (user && user->networkid != MSN_NETWORK_PASSPORT)
+		member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
+		                         "EmailMember", "Email",
+		                         "Email", state->who, "Email");
+	else
+		member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
+		                         "PassportMember", "Passport",
+		                         "PassportName", state->who, "PassportName");
 
 	body = g_strdup_printf(MSN_CONTACT_ADD_TO_LIST_TEMPLATE,
 		MsnSoapPartnerScenarioText[partner_scenario],
@@ -1616,7 +1617,6 @@
 	state->cb = msn_add_contact_to_list_read_cb;
 	msn_contact_request(state);
 
-	g_free(federate);
 	g_free(member);
 	g_free(body);
 }
--- a/libpurple/protocols/msn/contact.h	Sat Mar 21 03:50:14 2009 +0000
+++ b/libpurple/protocols/msn/contact.h	Fri Mar 27 07:56:25 2009 +0000
@@ -397,28 +397,18 @@
 
 #define MSN_MEMBER_PASSPORT_XML	\
 	"<Member xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"%s\">"\
-		"<Type>Passport</Type>"\
+		"<Type>%s</Type>"\
 		"<State>Accepted</State>"\
-		"<PassportName>%s</PassportName>"\
-		"%s"\
+		"<%s>%s</%s>"\
 	"</Member>"
 
 #define MSN_MEMBER_MEMBERSHIPID_XML	\
 	"<Member xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"%s\">"\
-		"<Type>Passport</Type>"\
+		"<Type>%s</Type>"\
 		"<MembershipId>%u</MembershipId>"\
 		"<State>Accepted</State>"\
-		"%s"\
 	"</Member>"
 
-#define MSN_MEMBER_FEDERATED_ANNOTATION_XML \
-	"<Annotations>"\
-		"<Annotation>"\
-			"<Name>MSN.IM.BuddyType</Name>"\
-			"<Value>%02d:</Value>"\
-		"</Annotation>"\
-	"</Annotations>"
-
 /* first delete contact from allow list */
 
 #define MSN_CONTACT_DELETE_FROM_LIST_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--- a/libpurple/protocols/msn/notification.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/libpurple/protocols/msn/notification.c	Fri Mar 27 07:56:25 2009 +0000
@@ -1609,7 +1609,7 @@
 
 	if ( (root = xmlnode_from_str(cmd->payload, cmd->payload_len)) == NULL)
 	{
-		purple_debug_error("msn", "Unable to parse GCF payload into a XML tree");
+		purple_debug_error("msn", "Unable to parse GCF payload into a XML tree\n");
 		return;
 	}
 
@@ -1682,7 +1682,7 @@
 	user = msn_userlist_find_user(session->userlist, passport);
 	if (user == NULL) {
 		char *str = g_strndup(payload, len);
-		purple_debug_info("msn", "unknown user %s, payload is %s",
+		purple_debug_info("msn", "unknown user %s, payload is %s\n",
 			passport, str);
 		g_free(str);
 		return;
--- a/libpurple/protocols/msn/oim.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/libpurple/protocols/msn/oim.c	Fri Mar 27 07:56:25 2009 +0000
@@ -174,7 +174,7 @@
 		gchar *faultcode_str = xmlnode_get_data(faultcode);
 
 		if (faultcode_str && g_str_equal(faultcode_str, "q0:BadContextToken")) {
-			purple_debug_warning("msn", "OIM Request Error, Updating token now.");
+			purple_debug_warning("msn", "OIM Request Error, Updating token now.\n");
 			msn_nexus_update_token(data->oim->session->nexus,
 				data->send ? MSN_AUTH_LIVE_SECURE : MSN_AUTH_MESSENGER_WEB,
 				(GSourceFunc)msn_oim_request_helper, data);
@@ -183,7 +183,7 @@
 
 		} else if (faultcode_str && g_str_equal(faultcode_str, "q0:AuthenticationFailed")) {
 			if (xmlnode_get_child(fault, "detail/RequiredAuthPolicy") != NULL) {
-				purple_debug_warning("msn", "OIM Request Error, Updating token now.");
+				purple_debug_warning("msn", "OIM Request Error, Updating token now.\n");
 				msn_nexus_update_token(data->oim->session->nexus,
 					data->send ? MSN_AUTH_LIVE_SECURE : MSN_AUTH_MESSENGER_WEB,
 					(GSourceFunc)msn_oim_request_helper, data);
--- a/libpurple/protocols/msn/state.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/libpurple/protocols/msn/state.c	Fri Mar 27 07:56:25 2009 +0000
@@ -169,7 +169,7 @@
 	}
 	currentmediaNode = xmlnode_get_child(payloadNode, "CurrentMedia");
 	if (currentmediaNode == NULL) {
-		purple_debug_info("msn", "No CurrentMedia Node");
+		purple_debug_info("msn", "No CurrentMedia Node\n");
 		xmlnode_free(payloadNode);
 		return NULL;
 	}
@@ -195,7 +195,7 @@
 	}
 	psmNode = xmlnode_get_child(payloadNode, "PSM");
 	if (psmNode == NULL) {
-		purple_debug_info("msn", "No PSM status Node");
+		purple_debug_info("msn", "No PSM status Node\n");
 		xmlnode_free(payloadNode);
 		return NULL;
 	}
--- a/libpurple/protocols/msn/switchboard.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/libpurple/protocols/msn/switchboard.c	Fri Mar 27 07:56:25 2009 +0000
@@ -590,7 +590,7 @@
 	payload = msn_message_gen_payload(msg, &payload_len);
 
 #ifdef MSN_DEBUG_SB
-	purple_debug_info("msn", "SB length:{%" G_GSIZE_FORMAT "}", payload_len);
+	purple_debug_info("msn", "SB length:{%" G_GSIZE_FORMAT "}\n", payload_len);
 	msn_message_show_readable(msg, "SB SEND", FALSE);
 #endif
 
--- a/libpurple/protocols/msn/userlist.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/libpurple/protocols/msn/userlist.c	Fri Mar 27 07:56:25 2009 +0000
@@ -858,7 +858,7 @@
 	}
 
 	if ( (user = msn_userlist_find_user(userlist, who)) == NULL) {
-		purple_debug_error("msn", "User %s not found!", who);
+		purple_debug_error("msn", "User %s not found!\n", who);
 		return FALSE;
 	}
 
@@ -887,7 +887,7 @@
 	}
 
 	if ( (user = msn_userlist_find_user(userlist, who)) == NULL) {
-		purple_debug_error("msn", "User %s not found!", who);
+		purple_debug_error("msn", "User %s not found!\n", who);
 		return FALSE;
 	}
 
--- a/libpurple/protocols/myspace/myspace.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/libpurple/protocols/myspace/myspace.c	Fri Mar 27 07:56:25 2009 +0000
@@ -388,7 +388,7 @@
 
 	g_return_val_if_fail(buddy != NULL, NULL);
 
-	user = msim_get_user_from_buddy(buddy);
+	user = msim_get_user_from_buddy(buddy, TRUE);
 
 	account = purple_buddy_get_account(buddy);
 	gc = purple_account_get_connection(account);
@@ -436,7 +436,7 @@
 	g_return_if_fail(buddy != NULL);
 	g_return_if_fail(user_info != NULL);
 
-	user = msim_get_user_from_buddy(buddy);
+	user = msim_get_user_from_buddy(buddy, TRUE);
 
 	if (PURPLE_BUDDY_IS_ONLINE(buddy)) {
 		MsimSession *session;
@@ -1053,7 +1053,7 @@
 	g_free(display_name);
 
 	/* 3. Update buddy information */
-	user = msim_get_user_from_buddy(buddy);
+	user = msim_get_user_from_buddy(buddy, TRUE);
 
 	user->id = uid;
 	/* Keep track of the user ID across sessions */
@@ -1377,7 +1377,7 @@
 		buddy = purple_buddy_new(session->account, username, NULL);
 		purple_blist_add_buddy(buddy, NULL, NULL, NULL);
 
-		user = msim_get_user_from_buddy(buddy);
+		user = msim_get_user_from_buddy(buddy, TRUE);
 		user->id = msim_msg_get_integer(msg, "f");
 
 		/* Keep track of the user ID across sessions */
@@ -2641,6 +2641,9 @@
 	name = purple_buddy_get_name(buddy);
 	gname = group ? purple_group_get_name(group) : NULL;
 
+	if (msim_get_user_from_buddy(buddy, FALSE) != NULL)
+		return;
+
 	purple_debug_info("msim", "msim_add_buddy: want to add %s to %s\n",
 			name, gname ? gname : "(no group)");
 
--- a/libpurple/protocols/myspace/user.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/libpurple/protocols/myspace/user.c	Fri Mar 27 07:56:25 2009 +0000
@@ -41,10 +41,10 @@
 }
 
 /**
- * Get the MsimUser from a PurpleBuddy, creating it if needed.
+ * Get the MsimUser from a PurpleBuddy, optionally creating it if needed.
  */
 MsimUser *
-msim_get_user_from_buddy(PurpleBuddy *buddy)
+msim_get_user_from_buddy(PurpleBuddy *buddy, gboolean create)
 {
 	MsimUser *user;
 
@@ -52,7 +52,8 @@
 		return NULL;
 	}
 
-	if (!(user = purple_buddy_get_protocol_data(buddy))) {
+	user = purple_buddy_get_protocol_data(buddy);
+	if (create && !user) {
 		/* No MsimUser for this buddy; make one. */
 
 		user = g_new0(MsimUser, 1);
@@ -94,7 +95,7 @@
 		return NULL;
 	}
 
-	user = msim_get_user_from_buddy(buddy);
+	user = msim_get_user_from_buddy(buddy, TRUE);
 
 	return user;
 }
--- a/libpurple/protocols/myspace/user.h	Sat Mar 21 03:50:14 2009 +0000
+++ b/libpurple/protocols/myspace/user.h	Fri Mar 27 07:56:25 2009 +0000
@@ -46,7 +46,7 @@
  * initiated from a user lookup. */
 typedef void (*MSIM_USER_LOOKUP_CB)(MsimSession *session, const MsimMessage *userinfo, gpointer data);
 
-MsimUser *msim_get_user_from_buddy(PurpleBuddy *buddy);
+MsimUser *msim_get_user_from_buddy(PurpleBuddy *buddy, gboolean create);
 void msim_user_free(MsimUser *user);
 MsimUser *msim_find_user(MsimSession *session, const gchar *username);
 void msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full);
--- a/libpurple/protocols/novell/novell.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/libpurple/protocols/novell/novell.c	Fri Mar 27 07:56:25 2009 +0000
@@ -2547,7 +2547,7 @@
 	if (gc == NULL || buddy == NULL || group == NULL)
 		return;
 
-	user = (NMUser *) gc->proto_data;
+	user = (NMUser *) purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -2557,6 +2557,10 @@
 	if (!user->clist_synched)
 		return;
 
+	/* Don't re-add a buddy that is already on our contact list */
+	if (nm_find_user_record(user, purple_buddy_get_name(buddy)) != NULL)
+		return;
+
 	contact = nm_create_contact();
 	nm_contact_set_dn(contact, purple_buddy_get_name(buddy));
 
--- a/libpurple/protocols/oscar/oscar.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Fri Mar 27 07:56:25 2009 +0000
@@ -4917,17 +4917,24 @@
 		return;
 	}
 
-	if ((od->ssi.received_data) && !(aim_ssi_itemlist_finditem(od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY))) {
-		purple_debug_info("oscar",
-				   "ssi: adding buddy %s to group %s\n", bname, gname);
-		aim_ssi_addbuddy(od, bname, gname, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, 0);
-
-		/* Mobile users should always be online */
-		if (bname[0] == '+') {
-			purple_prpl_got_user_status(account,
-					bname, OSCAR_STATUS_ID_AVAILABLE, NULL);
-			purple_prpl_got_user_status(account,
-					bname, OSCAR_STATUS_ID_MOBILE, NULL);
+	if (od->ssi.received_data) {
+		if (!aim_ssi_itemlist_finditem(od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY)) {
+			purple_debug_info("oscar",
+					   "ssi: adding buddy %s to group %s\n", bname, gname);
+			aim_ssi_addbuddy(od, bname, gname, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, 0);
+
+			/* Mobile users should always be online */
+			if (bname[0] == '+') {
+				purple_prpl_got_user_status(account, bname,
+						OSCAR_STATUS_ID_AVAILABLE, NULL);
+				purple_prpl_got_user_status(account, bname,
+						OSCAR_STATUS_ID_MOBILE, NULL);
+			}
+		} else if (aim_ssi_waitingforauth(od->ssi.local,
+		                                  aim_ssi_itemlist_findparentname(od->ssi.local, bname),
+		                                  bname)) {
+			/* Not authorized -- Re-request authorization */
+			purple_auth_sendrequest(gc, bname);
 		}
 	}
 
--- a/libpurple/protocols/silc/buddy.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/libpurple/protocols/silc/buddy.c	Fri Mar 27 07:56:25 2009 +0000
@@ -1397,7 +1397,12 @@
 
 void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
 {
-	silcpurple_add_buddy_i(gc, buddy, FALSE);
+	/* Don't add if the buddy is already on the list.
+	 *
+	 * SILC doesn't have groups, so we also don't need to do anything
+	 * for a move. */
+	if (purple_buddy_get_protocol_data(buddy) == NULL)
+		silcpurple_add_buddy_i(gc, buddy, FALSE);
 }
 
 void silcpurple_send_buddylist(PurpleConnection *gc)
--- a/libpurple/protocols/silc10/buddy.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/libpurple/protocols/silc10/buddy.c	Fri Mar 27 07:56:25 2009 +0000
@@ -1390,7 +1390,12 @@
 
 void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
 {
-	silcpurple_add_buddy_i(gc, buddy, FALSE);
+	/* Don't add if the buddy is already on the list.
+	 *
+	 * SILC doesn't have groups, so we don't need to do anything
+	 * for a move. */
+	if (purple_buddy_get_protocol_data(buddy) == NULL)
+		silcpurple_add_buddy_i(gc, buddy, FALSE);
 }
 
 void silcpurple_send_buddylist(PurpleConnection *gc)
--- a/libpurple/protocols/yahoo/yahoo_packet.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/libpurple/protocols/yahoo/yahoo_packet.c	Fri Mar 27 07:56:25 2009 +0000
@@ -201,6 +201,8 @@
 		}
 		pos += 2;
 
+		if (pos + 1 > len) break;
+
 		/* Skip over garbage we've noticed in the mail notifications */
 		if (data[0] == '9' && data[pos] == 0x01)
 			pos++;
--- a/libpurple/prpl.h	Sat Mar 21 03:50:14 2009 +0000
+++ b/libpurple/prpl.h	Fri Mar 27 07:56:25 2009 +0000
@@ -296,6 +296,14 @@
 	void (*set_idle)(PurpleConnection *, int idletime);
 	void (*change_passwd)(PurpleConnection *, const char *old_pass,
 						  const char *new_pass);
+	/**
+	 * Add a buddy to a group on the server.
+	 *
+	 * This PRPL function may be called in situations in which the buddy is
+	 * already in the specified group. If the protocol supports
+	 * authorization and the user is not already authorized to see the
+	 * status of \a buddy, \a add_buddy should request authorization.
+	 */
 	void (*add_buddy)(PurpleConnection *, PurpleBuddy *buddy, PurpleGroup *group);
 	void (*add_buddies)(PurpleConnection *, GList *buddies, GList *groups);
 	void (*remove_buddy)(PurpleConnection *, PurpleBuddy *buddy, PurpleGroup *group);
--- a/libpurple/tests/test_util.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/libpurple/tests/test_util.c	Fri Mar 27 07:56:25 2009 +0000
@@ -5,7 +5,7 @@
 
 START_TEST(test_util_base16_encode)
 {
-	assert_string_equal_free("68656c6c6f2c20776f726c642100", purple_base16_encode("hello, world!", 14));
+	assert_string_equal_free("68656c6c6f2c20776f726c642100", purple_base16_encode((const unsigned char *)"hello, world!", 14));
 }
 END_TEST
 
@@ -14,14 +14,14 @@
 	gsize sz = 0;
 	guchar *out = purple_base16_decode("21646c726f77202c6f6c6c656800", &sz);
 	fail_unless(sz == 14, NULL);
-	fail_unless(strcmp("!dlrow ,olleh", out) == 0, NULL);
+	fail_unless(strcmp("!dlrow ,olleh", (const char *)out) == 0, NULL);
 	g_free(out);
 }
 END_TEST
 
 START_TEST(test_util_base64_encode)
 {
-	assert_string_equal_free("Zm9ydHktdHdvAA==", purple_base64_encode("forty-two", 10));
+	assert_string_equal_free("Zm9ydHktdHdvAA==", purple_base64_encode((const unsigned char *)"forty-two", 10));
 }
 END_TEST
 
@@ -30,7 +30,7 @@
 	gsize sz;
 	guchar *out = purple_base64_decode("b3d0LXl0cm9mAA==", &sz);
 	fail_unless(sz == 10, NULL);
-	fail_unless(strcmp("owt-ytrof", out) == 0, NULL);
+	fail_unless(strcmp("owt-ytrof", (const char *)out) == 0, NULL);
 	g_free(out);
 }
 END_TEST
--- a/pidgin/gtkaccount.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/pidgin/gtkaccount.c	Fri Mar 27 07:56:25 2009 +0000
@@ -106,8 +106,8 @@
 	GtkSizeGroup *sg;
 	GtkWidget *window;
 
+	GtkWidget *notebook;
 	GtkWidget *top_vbox;
-	GtkWidget *bottom_vbox;
 	GtkWidget *ok_button;
 	GtkWidget *register_button;
 
@@ -157,8 +157,7 @@
  **************************************************************************/
 static void add_login_options(AccountPrefsDialog *dialog, GtkWidget *parent);
 static void add_user_options(AccountPrefsDialog *dialog, GtkWidget *parent);
-static void add_protocol_options(AccountPrefsDialog *dialog,
-								 GtkWidget *parent);
+static void add_protocol_options(AccountPrefsDialog *dialog);
 static void add_proxy_options(AccountPrefsDialog *dialog, GtkWidget *parent);
 
 static GtkWidget *
@@ -237,7 +236,7 @@
 
 	add_login_options(dialog,    dialog->top_vbox);
 	add_user_options(dialog,     dialog->top_vbox);
-	add_protocol_options(dialog, dialog->bottom_vbox);
+	add_protocol_options(dialog);
 
 	gtk_widget_grab_focus(dialog->protocol_menu);
 
@@ -733,11 +732,11 @@
 }
 
 static void
-add_protocol_options(AccountPrefsDialog *dialog, GtkWidget *parent)
+add_protocol_options(AccountPrefsDialog *dialog)
 {
 	PurpleAccountOption *option;
 	PurpleAccount *account;
-	GtkWidget *frame, *vbox, *check, *entry, *combo;
+	GtkWidget *vbox, *check, *entry, *combo;
 	GList *list, *node;
 	gint i, idx, int_value;
 	GtkListStore *model;
@@ -752,14 +751,10 @@
 	ProtocolOptEntry *opt_entry;
 
 	if (dialog->protocol_frame != NULL) {
-		gtk_widget_destroy(dialog->protocol_frame);
+		gtk_notebook_remove_page (GTK_NOTEBOOK(dialog->notebook), 1);
 		dialog->protocol_frame = NULL;
 	}
 
-	if (dialog->prpl_info == NULL ||
-			dialog->prpl_info->protocol_options == NULL)
-		return;
-
 	while (dialog->protocol_opt_entries != NULL) {
 		ProtocolOptEntry *opt_entry = dialog->protocol_opt_entries->data;
 		g_free(opt_entry->setting);
@@ -767,21 +762,17 @@
 		dialog->protocol_opt_entries = g_list_delete_link(dialog->protocol_opt_entries, dialog->protocol_opt_entries);
 	}
 
+	if (dialog->prpl_info == NULL ||
+			dialog->prpl_info->protocol_options == NULL)
+		return;
+
 	account = dialog->account;
 
-	/* Build the protocol options frame. */
-	g_snprintf(buf, sizeof(buf), _("%s Options"), dialog->plugin->info->name);
-
-	frame = pidgin_make_frame(parent, buf);
-	dialog->protocol_frame =
-		gtk_widget_get_parent(gtk_widget_get_parent(frame));
-
-	gtk_box_reorder_child(GTK_BOX(parent), dialog->protocol_frame, 0);
-	gtk_widget_show(dialog->protocol_frame);
-
 	/* Main vbox */
-	vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
-	gtk_container_add(GTK_CONTAINER(frame), vbox);
+	dialog->protocol_frame = vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
+	gtk_container_set_border_width(GTK_CONTAINER(vbox), PIDGIN_HIG_BORDER);
+	gtk_notebook_insert_page(GTK_NOTEBOOK(dialog->notebook), vbox,
+			gtk_label_new_with_mnemonic(_("_Advanced")), 1);
 	gtk_widget_show(vbox);
 
 	for (l = dialog->prpl_info->protocol_options; l != NULL; l = l->next)
@@ -1046,22 +1037,15 @@
 add_proxy_options(AccountPrefsDialog *dialog, GtkWidget *parent)
 {
 	PurpleProxyInfo *proxy_info;
-	GtkWidget *frame;
 	GtkWidget *vbox;
 	GtkWidget *vbox2;
 
 	if (dialog->proxy_frame != NULL)
 		gtk_widget_destroy(dialog->proxy_frame);
 
-	frame = pidgin_make_frame(parent, _("Proxy Options"));
-	dialog->proxy_frame = gtk_widget_get_parent(gtk_widget_get_parent(frame));
-
-	gtk_box_reorder_child(GTK_BOX(parent), dialog->proxy_frame, 1);
-	gtk_widget_show(dialog->proxy_frame);
-
 	/* Main vbox */
-	vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
-	gtk_container_add(GTK_CONTAINER(frame), vbox);
+	dialog->proxy_frame = vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
+	gtk_container_add(GTK_CONTAINER(parent), vbox);
 	gtk_widget_show(vbox);
 
 	/* Proxy Type drop-down. */
@@ -1496,15 +1480,15 @@
 		dialog->prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(dialog->plugin);
 
 	dialog->window = win = pidgin_create_dialog((type == PIDGIN_ADD_ACCOUNT_DIALOG) ? _("Add Account") : _("Modify Account"),
-		PIDGIN_HIG_BORDER, "account", FALSE);
+		PIDGIN_HIG_BOX_SPACE, "account", FALSE);
 
 	g_signal_connect(G_OBJECT(win), "delete_event",
 					 G_CALLBACK(account_win_destroy_cb), dialog);
 
 	/* Setup the vbox */
-	main_vbox = pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(win), FALSE, PIDGIN_HIG_BORDER);
-
-	notebook = gtk_notebook_new();
+	main_vbox = pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(win), FALSE, PIDGIN_HIG_BOX_SPACE);
+
+	dialog->notebook = notebook = gtk_notebook_new();
 	gtk_box_pack_start(GTK_BOX(main_vbox), notebook, FALSE, FALSE, 0);
 	gtk_widget_show(GTK_WIDGET(notebook));
 
@@ -1530,15 +1514,15 @@
 	if (!dialog->prpl_info || !dialog->prpl_info->register_user)
 		gtk_widget_hide(button);
 
-	/* Setup the page with 'Advanced'. */
-	dialog->bottom_vbox = dbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER);
+	/* Setup the page with 'Advanced' (protocol options). */
+	add_protocol_options(dialog);
+
+	/* Setup the page with 'Proxy'. */
+	dbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER);
 	gtk_container_set_border_width(GTK_CONTAINER(dbox), PIDGIN_HIG_BORDER);
 	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), dbox,
-			gtk_label_new_with_mnemonic(_("_Advanced")));
+			gtk_label_new_with_mnemonic(_("_Proxy")));
 	gtk_widget_show(dbox);
-
-	/** Setup the bottom frames. */
-	add_protocol_options(dialog, dbox);
 	add_proxy_options(dialog, dbox);
 
 	/* Cancel button */
--- a/pidgin/gtkblist.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/pidgin/gtkblist.c	Fri Mar 27 07:56:25 2009 +0000
@@ -3898,7 +3898,7 @@
 	presence = purple_buddy_get_presence(b);
 
 	/* Name is all that is needed */
-	if (aliased && biglist) {
+	if (!aliased || biglist) {
 
 		/* Status Info */
 		prpl = purple_find_prpl(purple_account_get_protocol_id(b->account));
@@ -4038,7 +4038,7 @@
 	}
 
 	/* Put it all together */
-	if (aliased && biglist && (statustext || idletime)) {
+	if ((!aliased || biglist) && (statustext || idletime)) {
 		/* using <span size='smaller'> breaks the status, so it must be seperated into <small><span>*/
 		if (name_color) {
 			text = g_strdup_printf("<span font_desc='%s' foreground='%s'>%s</span>\n"
@@ -6443,7 +6443,7 @@
 		gboolean biglist = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons");
 		PidginBlistNode *ui;
 		PurpleConversation *conv;
-		gboolean hidden;
+		gboolean hidden = FALSE;
 		GdkColor *bgcolor = NULL;
 		FontColorPair *pair;
 		PidginBlistTheme *theme;
@@ -6701,14 +6701,27 @@
 			whoalias = NULL;
 
 		g = NULL;
-		if ((grp != NULL) && (*grp != '\0') && ((g = purple_find_group(grp)) == NULL))
+		if ((grp != NULL) && (*grp != '\0'))
 		{
-			g = purple_group_new(grp);
-			purple_blist_add_group(g, NULL);
-		}
-
-		b = purple_buddy_new(data->account, who, whoalias);
-		purple_blist_add_buddy(b, NULL, g, NULL);
+			if ((g = purple_find_group(grp)) == NULL)
+			{
+				g = purple_group_new(grp);
+				purple_blist_add_group(g, NULL);
+			}
+
+			b = purple_find_buddy_in_group(data->account, who, g);
+		}
+		else if ((b = purple_find_buddy(data->account, who)) != NULL)
+		{
+			g = purple_buddy_get_group(b);
+		}
+
+		if (b == NULL)
+		{
+			b = purple_buddy_new(data->account, who, whoalias);
+			purple_blist_add_buddy(b, NULL, g, NULL);
+		}
+
 		purple_account_add_buddy(data->account, b);
 
 		/* Offer to merge people with the same alias. */
--- a/pidgin/plugins/gevolution/gevo-util.c	Sat Mar 21 03:50:14 2009 +0000
+++ b/pidgin/plugins/gevolution/gevo-util.c	Fri Mar 27 07:56:25 2009 +0000
@@ -41,8 +41,12 @@
 		purple_blist_add_group(group, NULL);
 	}
 
-	buddy = purple_buddy_new(account, buddy_name, alias);
-	purple_blist_add_buddy(buddy, NULL, group, NULL);
+	if ((buddy = purple_find_buddy_in_group(account, buddy_name, group)))
+	{	
+		buddy = purple_buddy_new(account, buddy_name, alias);
+		purple_blist_add_buddy(buddy, NULL, group, NULL);
+	}
+
 	purple_account_add_buddy(account, buddy);
 
 	if (conv != NULL)
--- a/pidgin/plugins/gevolution/gevolution.h	Sat Mar 21 03:50:14 2009 +0000
+++ b/pidgin/plugins/gevolution/gevolution.h	Fri Mar 27 07:56:25 2009 +0000
@@ -75,7 +75,7 @@
 
 	GtkWidget *win;
 	GtkWidget *accounts_menu;
-	GtkWidget *screenname;
+	GtkWidget *username;
 	GtkWidget *firstname;
 	GtkWidget *lastname;
 	GtkWidget *email;
--- a/po/POTFILES.in	Sat Mar 21 03:50:14 2009 +0000
+++ b/po/POTFILES.in	Fri Mar 27 07:56:25 2009 +0000
@@ -62,6 +62,7 @@
 libpurple/plugins/mono/loader/mono.c
 libpurple/plugins/newline.c
 libpurple/plugins/offlinemsg.c
+libpurple/plugins/one_time_password.c
 libpurple/plugins/perl/perl.c
 libpurple/plugins/psychic.c
 libpurple/plugins/signals-test.c