merge of '61bd261a302f0ece4d517cd566e995e266f0d4c1' mxit

Mon, 04 Jun 2012 14:18:54 +0000

author
Daniel Atallah <datallah@pidgin.im>
date
Mon, 04 Jun 2012 14:18:54 +0000
branch
mxit
changeset 33003
f08d44ececa1
parent 32867
61bd261a302f (diff)
parent 32899
2b94245d2921 (current diff)
child 33038
854cd00e1ab4

merge of '61bd261a302f0ece4d517cd566e995e266f0d4c1'
and '2b94245d2921f94d3af6dd1421721c651b3676aa'

ChangeLog file | annotate | diff | comparison | revisions
--- a/ChangeLog	Mon Jan 09 11:24:26 2012 +0000
+++ b/ChangeLog	Mon Jun 04 14:18:54 2012 +0000
@@ -1,16 +1,11 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
 version 3.0.0 (??/??/????):
-	libpurple:
-	* Support new connection states and signals for NetworkManager 0.9+.
-	  (Dan Williams) (#13859)
+	Finch:
+	* Support the conversation-extended signal for extending the
+	  conversation menu. (Howard Chu) (#14818)
 
 	AIM and ICQ:
-	* Allow signing on with usernames containing periods and
-	  underscores. (#13500)
-	* Allow adding buddies containing periods and underscores. (#13500)
-	* Don't try to format ICQ usernames entered as email addresses.
-	  Gets rid of an "Unable to format username" error at login. (#13883)
 	* Make buddy list management code more efficient. (Oliver) (#4816)
 
 	Bonjour:
@@ -29,6 +24,8 @@
 	MSN:
 	* Fix file transfer with older Mac MSN clients.
 	* Support file transfers up to ~9 EiB.
+	* Support new protocol version MSNP18. (#14753)
+	* Fix messages to offline contacts. (#14302)
 
 	MXit:
 	* Remove all reference to Hidden Number.
@@ -48,6 +45,33 @@
 	* The Voice/Video Settings plugin supports using the sndio GStreamer
 	 backends. (Brad Smith) (#14414)
 
+version 2.10.2 (02/22/2012):
+	General:
+	* Fix compilation when using binutils 2.22 and new GDK pixbuf. (#14799)
+	* Fix compilation of the MXit protocol plugin with GLib 2.31. (#14773)
+
+	Pidgin:
+	* Add support for the GNOME3 Network dialog. (#13882)
+	* Fix rare crash. (#14392)
+
+	libpurple:
+	* Support new connection states and signals for NetworkManager 0.9+.
+	  (Dan Williams) (#13859)
+
+	AIM and ICQ:
+	* Allow signing on with usernames containing periods and
+	  underscores. (#13500)
+	* Allow adding buddies containing periods and underscores. (#13500)
+	* Don't try to format ICQ usernames entered as email addresses.
+	  Gets rid of an "Unable to format username" error at login. (#13883)
+
+	MSN:
+	* Fix possible crashes caused by not validating incoming messages as
+	  UTF-8. (Thijs Alkemade) (#14884)
+
+	Windows-Specific Changes:
+	* Fix compilation of the Bonjour protocol plugin. (#14802)
+
 version 2.10.1 (12/06/2011):
 	Finch:
 	* Fix compilation on OpenBSD.
--- a/ChangeLog.API	Mon Jan 09 11:24:26 2012 +0000
+++ b/ChangeLog.API	Mon Jun 04 14:18:54 2012 +0000
@@ -201,8 +201,8 @@
 		* purple_txt_cancel
 		* purple_txt_resolve_account
 		* purple_util_fetch_url_len. Use purple_util_fetch_url, instead.
-		* purple_util_fetch_url_request_len. Use purple_util_fetch_url_request,
-		  instead.
+		* purple_util_fetch_url_request_len. Use
+		* purple_util_fetch_url_request, instead.
 		* purple_util_fetch_url_request_len_with_account.  Use
 		  purple_util_fetch_url_request, instead.
 		* PurpleConnectionUiOps.report_disconnect_reason
--- a/finch/Makefile.am	Mon Jan 09 11:24:26 2012 +0000
+++ b/finch/Makefile.am	Mon Jun 04 14:18:54 2012 +0000
@@ -27,6 +27,7 @@
 	gntidle.c \
 	gntlog.c \
 	gntmedia.c \
+	gntmenuutil.c \
 	gntnotify.c \
 	gntplugin.c \
 	gntpounce.c \
@@ -49,6 +50,7 @@
 	gntidle.h \
 	gntlog.h \
 	gntmedia.h \
+	gntmenuutil.h \
 	gntnotify.h \
 	gntplugin.h \
 	gntpounce.h \
--- a/finch/gntblist.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/finch/gntblist.c	Mon Jun 04 14:18:54 2012 +0000
@@ -50,6 +50,7 @@
 #include "gntmenu.h"
 #include "gntmenuitem.h"
 #include "gntmenuitemcheck.h"
+#include "gntmenuutil.h"
 #include "gntpounce.h"
 #include "gntstyle.h"
 #include "gnttree.h"
@@ -1072,46 +1073,6 @@
 }
 
 static void
-context_menu_callback(GntMenuItem *item, gpointer data)
-{
-	PurpleMenuAction *action = data;
-	PurpleBlistNode *node = ggblist->cnode;
-	if (action) {
-		void (*callback)(PurpleBlistNode *, gpointer);
-		callback = (void (*)(PurpleBlistNode *, gpointer))
-			purple_menu_action_get_callback(action);
-		if (callback)
-			callback(node, purple_menu_action_get_data(action));
-		else
-			return;
-	}
-}
-
-static void
-gnt_append_menu_action(GntMenu *menu, PurpleMenuAction *action, gpointer parent)
-{
-	GList *list;
-	GntMenuItem *item;
-
-	if (action == NULL)
-		return;
-
-	item = gnt_menuitem_new(purple_menu_action_get_label(action));
-	if (purple_menu_action_get_callback(action))
-		gnt_menuitem_set_callback(GNT_MENU_ITEM(item), context_menu_callback, action);
-	gnt_menu_add_item(menu, GNT_MENU_ITEM(item));
-
-	list = purple_menu_action_get_children(action);
-
-	if (list) {
-		GntWidget *sub = gnt_menu_new(GNT_MENU_POPUP);
-		gnt_menuitem_set_submenu(item, GNT_MENU(sub));
-		for (; list; list = list->next)
-			gnt_append_menu_action(GNT_MENU(sub), list->data, action);
-	}
-}
-
-static void
 append_proto_menu(GntMenu *menu, PurpleConnection *gc, PurpleBlistNode *node)
 {
 	GList *list;
@@ -1127,9 +1088,7 @@
 		if (!act)
 			continue;
 		purple_menu_action_set_data(act, node);
-		gnt_append_menu_action(menu, act, NULL);
-		g_signal_connect_swapped(G_OBJECT(menu), "destroy",
-			G_CALLBACK(purple_menu_action_free), act);
+		gnt_append_menu_action(menu, act, node);
 	}
 }
 
@@ -1139,8 +1098,6 @@
 {
 	PurpleMenuAction *action = purple_menu_action_new(label, callback, data, NULL);
 	gnt_append_menu_action(menu, action, NULL);
-	g_signal_connect_swapped(G_OBJECT(menu), "destroy",
-			G_CALLBACK(purple_menu_action_free), action);
 }
 
 static void
@@ -1379,9 +1336,7 @@
 	for (iter = purple_blist_node_get_extended_menu(node);
 			iter; iter = g_list_delete_link(iter, iter))
 	{
-		gnt_append_menu_action(menu, iter->data, NULL);
-		g_signal_connect_swapped(G_OBJECT(menu), "destroy",
-				G_CALLBACK(purple_menu_action_free), iter->data);
+		gnt_append_menu_action(menu, iter->data, node);
 	}
 }
 
--- a/finch/gntconv.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/finch/gntconv.c	Mon Jun 04 14:18:54 2012 +0000
@@ -52,6 +52,7 @@
 #include "gntmenu.h"
 #include "gntmenuitem.h"
 #include "gntmenuitemcheck.h"
+#include "gntmenuutil.h"
 #include "gntstyle.h"
 #include "gnttextview.h"
 #include "gnttree.h"
@@ -404,6 +405,30 @@
 }
 
 static void
+gg_extended_menu(FinchConv *ggc)
+{
+	GntWidget *sub;
+	GList *list;
+
+	sub = gnt_menu_new(GNT_MENU_POPUP);
+	gnt_menuitem_set_submenu(ggc->plugins, GNT_MENU(sub));
+
+	for (list = purple_conversation_get_extended_menu(ggc->active_conv);
+			list; list = g_list_delete_link(list, list))
+	{
+		gnt_append_menu_action(GNT_MENU(sub), list->data, ggc->active_conv);
+	}
+}
+
+static void
+conv_updated(PurpleConversation *conv, PurpleConvUpdateType type)
+{
+	if (type == PURPLE_CONV_UPDATE_FEATURES) {
+		gg_extended_menu(purple_conversation_get_ui_data(conv));
+	}
+}
+
+static void
 clear_scrollback_cb(GntMenuItem *item, gpointer ggconv)
 {
 	FinchConv *ggc = ggconv;
@@ -595,6 +620,12 @@
 }
 
 static void
+plugin_changed_cb(PurplePlugin *p, gpointer data)
+{
+	gg_extended_menu(data);
+}
+
+static void
 gg_create_menu(FinchConv *ggc)
 {
 	GntWidget *menu, *sub;
@@ -665,6 +696,12 @@
 			!(ggc->flags & FINCH_CONV_NO_SOUND));
 	gnt_menu_add_item(GNT_MENU(sub), item);
 	gnt_menuitem_set_callback(item, toggle_sound_cb, ggc);
+
+	item = gnt_menuitem_new(_("Plugins"));
+	gnt_menu_add_item(GNT_MENU(menu), item);
+	ggc->plugins = item;
+
+	gg_extended_menu(ggc);
 }
 
 static void
@@ -876,6 +913,11 @@
 	purple_signal_connect(purple_cmds_get_handle(), "cmd-removed", ggc,
 			G_CALLBACK(cmd_removed_cb), ggc);
 
+	purple_signal_connect(purple_plugins_get_handle(), "plugin-load", ggc,
+				PURPLE_CALLBACK(plugin_changed_cb), ggc);
+	purple_signal_connect(purple_plugins_get_handle(), "plugin-unload", ggc,
+				PURPLE_CALLBACK(plugin_changed_cb), ggc);
+
 	g_free(title);
 	gnt_box_give_focus_to_child(GNT_BOX(ggc->window), ggc->entry);
 	g_signal_connect(G_OBJECT(ggc->window), "gained-focus", G_CALLBACK(gained_focus_cb), ggc);
@@ -1475,6 +1517,8 @@
 					PURPLE_CALLBACK(chat_left_cb), NULL);
 	purple_signal_connect(purple_conversations_get_handle(), "cleared-message-history", finch_conv_get_handle(),
 					PURPLE_CALLBACK(cleared_message_history_cb), NULL);
+	purple_signal_connect(purple_conversations_get_handle(), "conversation-updated", finch_conv_get_handle(),
+					PURPLE_CALLBACK(conv_updated), NULL);
 	purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", finch_conv_get_handle(),
 					PURPLE_CALLBACK(buddy_signed_on_off), NULL);
 	purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", finch_conv_get_handle(),
--- a/finch/gntconv.h	Mon Jan 09 11:24:26 2012 +0000
+++ b/finch/gntconv.h	Mon Jun 04 14:18:54 2012 +0000
@@ -59,6 +59,7 @@
 	GntWidget *tv;            /* text-view */
 	GntWidget *menu;
 	GntWidget *info;
+	GntMenuItem *plugins;
 	FinchConversationFlag flags;
 
 	union
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntmenuutil.c	Mon Jun 04 14:18:54 2012 +0000
@@ -0,0 +1,79 @@
+/**
+ * @file gntmenuutil.c GNT Menu Utility Functions
+ * @ingroup finch
+ */
+
+/* finch
+ *
+ * Finch is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#include <internal.h>
+#include "finch.h"
+
+#include "gnt.h"
+#include "gntmenu.h"
+#include "gntmenuitem.h"
+#include "gntmenuutil.h"
+
+static void
+context_menu_callback(GntMenuItem *item, gpointer data)
+{
+	PurpleMenuAction *action = data;
+	if (action) {
+		void (*callback)(gpointer, gpointer);
+		callback = (void (*)(gpointer, gpointer))
+			purple_menu_action_get_callback(action);
+		if (callback) {
+			gpointer ctx = g_object_get_data(G_OBJECT(item), "menuctx");
+			callback(ctx, purple_menu_action_get_data(action));
+		}
+	}
+}
+
+void
+gnt_append_menu_action(GntMenu *menu, PurpleMenuAction *action, gpointer ctx)
+{
+	GList *list;
+	GntMenuItem *item;
+
+	if (action == NULL)
+		return;
+
+	item = gnt_menuitem_new(purple_menu_action_get_label(action));
+	if (purple_menu_action_get_callback(action)) {
+		gnt_menuitem_set_callback(item, context_menu_callback, action);
+		g_object_set_data(G_OBJECT(item), "menuctx", ctx);
+	}
+	gnt_menu_add_item(menu, item);
+
+	list = purple_menu_action_get_children(action);
+
+	if (list) {
+		GntWidget *sub = gnt_menu_new(GNT_MENU_POPUP);
+		gnt_menuitem_set_submenu(item, GNT_MENU(sub));
+		for (; list; list = g_list_delete_link(list, list))
+			gnt_append_menu_action(GNT_MENU(sub), list->data, action);
+		purple_menu_action_set_children(action, NULL);
+	}
+
+	g_signal_connect_swapped(G_OBJECT(menu), "destroy",
+		G_CALLBACK(purple_menu_action_free), action);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntmenuutil.h	Mon Jun 04 14:18:54 2012 +0000
@@ -0,0 +1,49 @@
+/**
+ * @file gntmenuutil.h GNT Menu Utility Functions
+ * @ingroup finch
+ */
+
+/* finch
+ *
+ * Finch is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+#ifndef _GNT_MENUUTIL_H
+#define _GNT_MENUUTIL_H
+
+#include <gnt.h>
+#include <gntmenu.h>
+
+/***************************************************************************
+ * @name GNT Menu Utility Functions
+ ***************************************************************************/
+/*@{*/
+
+/**
+ * Add a PurpleMenuAction to a GntMenu.
+ *
+ * @param menu   the GntMenu to add to
+ * @param action the PurpleMenuAction to add
+ * @param ctx    the callback context, passed as the first argument to
+ *               the PurpleMenuAction's PurpleCallback function.
+ */
+void gnt_append_menu_action(GntMenu *menu, PurpleMenuAction *action, gpointer ctx);
+
+/*@}*/
+
+#endif
--- a/libpurple/blist.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/blist.c	Mon Jun 04 14:18:54 2012 +0000
@@ -2908,6 +2908,17 @@
 	return node->type;
 }
 
+gboolean
+purple_blist_node_has_setting(PurpleBlistNode* node, const char *key)
+{
+	g_return_val_if_fail(node != NULL, FALSE);
+	g_return_val_if_fail(node->settings != NULL, FALSE);
+	g_return_val_if_fail(key != NULL, FALSE);
+
+	/* Boxed type, so it won't ever be NULL, so no need for _extended */
+	return (g_hash_table_lookup(node->settings, key) != NULL);
+}
+
 void
 purple_blist_node_set_bool(PurpleBlistNode* node, const char *key, gboolean data)
 {
--- a/libpurple/blist.h	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/blist.h	Mon Jun 04 14:18:54 2012 +0000
@@ -1052,6 +1052,16 @@
 void purple_blist_request_add_group(void);
 
 /**
+ * Checks whether a named setting exists for a node in the buddy list
+ *
+ * @param node  The node to check from which to check settings
+ * @param key   The identifier of the data
+ *
+ * @return TRUE if a value exists, or FALSE if there is no setting
+ */
+gboolean purple_blist_node_has_setting(PurpleBlistNode *node, const char *key);
+
+/**
  * Associates a boolean with a node in the buddy list
  *
  * @param node  The node to associate the data with
--- a/libpurple/protocols/jabber/caps.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/jabber/caps.c	Mon Jun 04 14:18:54 2012 +0000
@@ -888,7 +888,8 @@
 					                                   field->values);
 				}
 			} else {
-				g_list_free_full(field->values, g_free);
+				g_list_foreach(field->values, (GFunc) g_free, NULL);
+				g_list_free(field->values);
 			}
 
 			g_free(field->var);
--- a/libpurple/protocols/msn/contact.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/msn/contact.c	Mon Jun 04 14:18:54 2012 +0000
@@ -740,6 +740,20 @@
 		}
 
 		passportName = xmlnode_get_child(contactInfo, "passportName");
+		if (passportName != NULL) {
+			xmlnode *messenger_user;
+			/* ignore non-messenger contacts */
+			if ((messenger_user = xmlnode_get_child(contactInfo, "isMessengerUser"))) {
+				char *is_messenger_user = xmlnode_get_data(messenger_user);
+
+				if (is_messenger_user && !strcmp(is_messenger_user, "false")) {
+					passportName = NULL;
+				}
+
+				g_free(is_messenger_user);
+			}
+		}
+
 		if (passportName == NULL) {
 			xmlnode *emailsNode, *contactEmailNode, *emailNode;
 			xmlnode *messengerEnabledNode;
@@ -773,19 +787,6 @@
 				}
 			}
 		} else {
-			xmlnode *messenger_user;
-			/* ignore non-messenger contacts */
-			if ((messenger_user = xmlnode_get_child(contactInfo, "isMessengerUser"))) {
-				char *is_messenger_user = xmlnode_get_data(messenger_user);
-
-				if (is_messenger_user && !strcmp(is_messenger_user, "false")) {
-					g_free(is_messenger_user);
-					continue;
-				}
-
-				g_free(is_messenger_user);
-			}
-
 			passport = xmlnode_get_data(passportName);
 		}
 
@@ -864,6 +865,21 @@
 	g_free(alias);
 }
 
+static void
+msn_parse_addressbook_circles(MsnSession *session, xmlnode *node)
+{
+	xmlnode *ticket;
+
+	/* TODO: Parse groups */
+
+	ticket = xmlnode_get_child(node, "CircleTicket");
+	if (ticket) {
+		char *data = xmlnode_get_data(ticket);
+		msn_notification_send_circle_auth(session, data);
+		g_free(data);
+	}
+}
+
 static gboolean
 msn_parse_addressbook(MsnSession *session, xmlnode *node)
 {
@@ -871,6 +887,7 @@
 	xmlnode *groups;
 	xmlnode *contacts;
 	xmlnode *abNode;
+	xmlnode *circleNode;
 	xmlnode *fault;
 
 	if ((fault = xmlnode_get_child(node, "Body/Fault"))) {
@@ -897,7 +914,7 @@
 		return FALSE;
 	}
 
-	result = xmlnode_get_child(node, "Body/ABFindAllResponse/ABFindAllResult");
+	result = xmlnode_get_child(node, "Body/ABFindContactsPagedResponse/ABFindContactsPagedResult");
 	if (result == NULL) {
 		purple_debug_misc("msn", "Received no address book update\n");
 		return TRUE;
@@ -906,7 +923,7 @@
 	/* I don't see this "groups" tag documented on msnpiki, need to find out
 	   if they are really there, and update msnpiki */
 	/*Process Group List*/
-	groups = xmlnode_get_child(result, "groups");
+	groups = xmlnode_get_child(result, "Groups");
 	if (groups != NULL) {
 		msn_parse_addressbook_groups(session, groups);
 	}
@@ -931,12 +948,12 @@
 
 	/*Process contact List*/
 	purple_debug_info("msn", "Process contact list...\n");
-	contacts = xmlnode_get_child(result, "contacts");
+	contacts = xmlnode_get_child(result, "Contacts");
 	if (contacts != NULL) {
 		msn_parse_addressbook_contacts(session, contacts);
 	}
 
-	abNode = xmlnode_get_child(result, "ab");
+	abNode = xmlnode_get_child(result, "Ab");
 	if (abNode != NULL) {
 		xmlnode *node2;
 		char *tmp = NULL;
@@ -954,6 +971,11 @@
 		g_free(tmp);
 	}
 
+	circleNode = xmlnode_get_child(result, "CircleResult");
+	if (circleNode != NULL) {
+		msn_parse_addressbook_circles(session, circleNode);
+	}
+
 	return TRUE;
 }
 
--- a/libpurple/protocols/msn/contact.h	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/msn/contact.h	Mon Jun 04 14:18:54 2012 +0000
@@ -62,7 +62,7 @@
 
 #define MSN_APPLICATION_ID "CFE80F9D-180F-4399-82AB-413F33A1FA11"
 
-#define MSN_CONTACT_SERVER	"omega.contacts.msn.com"
+#define MSN_CONTACT_SERVER	"local-bay.contacts.msn.com"
 
 /* Get Contact List */
 
@@ -142,11 +142,13 @@
 "</soap:Envelope>"
 
 /* Get AddressBook */
-#define MSN_GET_ADDRESS_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABFindAll"
+#define MSN_GET_ADDRESS_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABFindContactsPaged"
 #define MSN_GET_ADDRESS_FULL_TIME	"0001-01-01T00:00:00.0000000-08:00"
 #define MSN_GET_ADDRESS_UPDATE_XML \
-	"<deltasOnly>true</deltasOnly>"\
-	"<lastChange>%s</lastChange>"
+	"<filterOptions>"\
+		"<deltasOnly>true</deltasOnly>"\
+		"<lastChange>%s</lastChange>"\
+	"</filterOptions>"
 
 #define MSN_GET_GLEAM_UPDATE_XML \
 	"%s"\
@@ -171,11 +173,11 @@
 		"</ABAuthHeader>"\
 	"</soap:Header>"\
 	"<soap:Body>"\
-		"<ABFindAll xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
+		"<ABFindContactsPaged xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
 			"<abView>Full</abView>"\
+			"<extendedContent>AB AllGroups CircleResult</extendedContent>"\
 			"%s"\
-		"</ABFindAll>"\
+		"</ABFindContactsPaged>"\
 	"</soap:Body>"\
 "</soap:Envelope>"
 
--- a/libpurple/protocols/msn/msn.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/msn/msn.c	Mon Jun 04 14:18:54 2012 +0000
@@ -1223,7 +1223,7 @@
 	m = g_list_append(m, act);
 	m = g_list_append(m, NULL);
 
-	if (session->enable_mpop && session->protocol_ver >= 16)
+	if (session->enable_mpop)
 	{
 		act = purple_plugin_action_new(_("View Locations..."),
 		                               msn_show_locations);
@@ -1571,89 +1571,68 @@
 		return 0;
 	}
 
-	if (msn_user_is_online(account, who) ||
-		msn_user_is_yahoo(account, who) ||
-		swboard != NULL) {
-		/*User online or have a swboard open because it's invisible
-		 * and sent us a message,then send Online Instant Message*/
-
-		if (msglen + strlen(msgformat) + strlen(VERSION) > 1564)
-		{
-			g_free(msgformat);
-			g_free(msgtext);
-
-			return -E2BIG;
-		}
-
-		msg = msn_message_new_plain(msgtext);
-		msg->remote_user = g_strdup(who);
-		msn_message_set_header(msg, "X-MMS-IM-Format", msgformat);
-
+	if (msglen + strlen(msgformat) + strlen(VERSION) > 1564)
+	{
 		g_free(msgformat);
 		g_free(msgtext);
 
-		purple_debug_info("msn", "prepare to send online Message\n");
-		if (g_ascii_strcasecmp(who, username))
-		{
-			if (flags & PURPLE_MESSAGE_AUTO_RESP) {
-				msn_message_set_flag(msg, 'U');
-			}
-			if (msn_user_is_yahoo(account, who)) {
-				/*we send the online and offline Message to Yahoo User via UBM*/
-				purple_debug_info("msn", "send to Yahoo User\n");
-				uum_send_msg(session, msg);
-			} else {
-				purple_debug_info("msn", "send via switchboard\n");
-				msn_send_im_message(session, msg);
-			}
+		return -E2BIG;
+	}
+
+	msg = msn_message_new_plain(msgtext);
+	msg->remote_user = g_strdup(who);
+	msn_message_set_header(msg, "X-MMS-IM-Format", msgformat);
+
+	g_free(msgformat);
+	g_free(msgtext);
+
+	purple_debug_info("msn", "prepare to send online Message\n");
+	if (g_ascii_strcasecmp(who, username))
+	{
+		if (flags & PURPLE_MESSAGE_AUTO_RESP) {
+			msn_message_set_flag(msg, 'U');
+		}
+
+		if (msn_user_is_yahoo(account, who) || !(msn_user_is_online(account, who) || swboard != NULL)) {
+			/*we send the online and offline Message to Yahoo User via UBM*/
+			purple_debug_info("msn", "send to Yahoo User\n");
+			msn_notification_send_uum(session, msg);
+		} else {
+			purple_debug_info("msn", "send via switchboard\n");
+			msn_send_im_message(session, msg);
 		}
-		else
-		{
-			char *body_str, *body_enc, *pre, *post;
-			const char *format;
-			MsnIMData *imdata = g_new0(MsnIMData, 1);
-			/*
-			 * In MSN, you can't send messages to yourself, so
-			 * we'll fake like we received it ;)
-			 */
-			body_str = msn_message_to_string(msg);
-			body_enc = g_markup_escape_text(body_str, -1);
-			g_free(body_str);
-
-			format = msn_message_get_header_value(msg, "X-MMS-IM-Format");
-			msn_parse_format(format, &pre, &post);
-			body_str = g_strdup_printf("%s%s%s", pre ? pre :  "",
-									   body_enc ? body_enc : "", post ? post : "");
-			g_free(body_enc);
-			g_free(pre);
-			g_free(post);
-
-			serv_got_typing_stopped(gc, who);
-			imdata->gc = gc;
-			imdata->who = who;
-			imdata->msg = body_str;
-			imdata->flags = flags & ~PURPLE_MESSAGE_SEND;
-			imdata->when = time(NULL);
-			purple_timeout_add(0, msn_send_me_im, imdata);
-		}
-
-		msn_message_unref(msg);
-	} else {
-		/*send Offline Instant Message,only to MSN Passport User*/
-		char *friendname;
-
-		purple_debug_info("msn", "prepare to send offline Message\n");
-
-		friendname = msn_encode_mime(purple_account_get_username(account));
-		msn_oim_prep_send_msg_info(session->oim,
-			purple_account_get_username(account),
-			friendname, who, msgtext);
-		msn_oim_send_msg(session->oim);
-
-		g_free(msgformat);
-		g_free(msgtext);
-		g_free(friendname);
 	}
+	else
+	{
+		char *body_str, *body_enc, *pre, *post;
+		const char *format;
+		MsnIMData *imdata = g_new0(MsnIMData, 1);
+		/*
+		 * In MSN, you can't send messages to yourself, so
+		 * we'll fake like we received it ;)
+		 */
+		body_str = msn_message_to_string(msg);
+		body_enc = g_markup_escape_text(body_str, -1);
+		g_free(body_str);
+
+		format = msn_message_get_header_value(msg, "X-MMS-IM-Format");
+		msn_parse_format(format, &pre, &post);
+		body_str = g_strdup_printf("%s%s%s", pre ? pre :  "",
+								   body_enc ? body_enc : "", post ? post : "");
+		g_free(body_enc);
+		g_free(pre);
+		g_free(post);
+
+		serv_got_typing_stopped(gc, who);
+		imdata->gc = gc;
+		imdata->who = who;
+		imdata->msg = body_str;
+		imdata->flags = flags & ~PURPLE_MESSAGE_SEND;
+		imdata->when = time(NULL);
+		purple_timeout_add(0, msn_send_me_im, imdata);
+	}
+
+	msn_message_unref(msg);
 
 	return 1;
 }
--- a/libpurple/protocols/msn/msn.h	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/msn/msn.h	Mon Jun 04 14:18:54 2012 +0000
@@ -115,10 +115,10 @@
 #define MSN_SERVER "messenger.hotmail.com"
 #define MSN_HTTPCONN_SERVER "gateway.messenger.hotmail.com"
 #define MSN_PORT 1863
-#define WLM_PROT_VER		16
+#define WLM_PROT_VER		18
 
-#define WLM_MAX_PROTOCOL	16
-#define WLM_MIN_PROTOCOL	15
+#define WLM_MAX_PROTOCOL	18
+#define WLM_MIN_PROTOCOL	18
 
 #define MSN_TYPING_RECV_TIMEOUT 6
 #define MSN_TYPING_SEND_TIMEOUT	4
--- a/libpurple/protocols/msn/msnutils.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/msn/msnutils.c	Mon Jun 04 14:18:54 2012 +0000
@@ -490,6 +490,21 @@
 	*ret_port = port;
 }
 
+void
+msn_parse_user(const char *str, char **ret_user, int *ret_network)
+{
+	char **tokens;
+
+	tokens = g_strsplit(str, ":", 2);
+
+	*ret_network = atoi(tokens[0]);
+	*ret_user = tokens[1];
+
+	g_free(tokens[0]);
+	/* tokens[1] is returned */
+	g_free(tokens);
+}
+
 gboolean
 msn_email_is_valid(const char *passport)
 {
--- a/libpurple/protocols/msn/msnutils.h	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/msn/msnutils.h	Mon Jun 04 14:18:54 2012 +0000
@@ -76,6 +76,15 @@
 void msn_parse_socket(const char *str, char **ret_host, int *ret_port);
 
 /**
+ * Parses a user name
+ *
+ * @param str         A network:username string.
+ * @param ret_user    Return of the user's passport.
+ * @param ret_network Return of the user's network.
+ */
+void msn_parse_user(const char *str, char **ret_user, int *ret_network);
+
+/**
  * Verify if the email is a vaild passport.
  *
  * @param passport 	The email
--- a/libpurple/protocols/msn/nexus.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/msn/nexus.c	Mon Jun 04 14:18:54 2012 +0000
@@ -44,9 +44,8 @@
 	{"messenger.msn.com", "?id=507"},        /* Authentication for receiving OIMs. */
 	{"contacts.msn.com", "MBI"},             /* Authentication for the Contact server. */
 	{"messengersecure.live.com", "MBI_SSL"}, /* Authentication for sending OIMs. */
-	{"spaces.live.com", "MBI"},              /* Authentication for the Windows Live Spaces */
-	{"livecontacts.live.com", "MBI"},        /* Live Contacts API, a simplified version of the Contacts SOAP service */
 	{"storage.live.com", "MBI"},             /* Storage REST API */
+	{"sup.live.com", "MBI"},                 /* What's New service */
 };
 
 /**************************************************************************
--- a/libpurple/protocols/msn/nexus.h	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/msn/nexus.h	Mon Jun 04 14:18:54 2012 +0000
@@ -36,9 +36,8 @@
 	MSN_AUTH_MESSENGER_WEB = 1,
 	MSN_AUTH_CONTACTS      = 2,
 	MSN_AUTH_LIVE_SECURE   = 3,
-	MSN_AUTH_SPACES        = 4,
-	MSN_AUTH_LIVE_CONTACTS = 5,
-	MSN_AUTH_STORAGE       = 6
+	MSN_AUTH_STORAGE       = 4,
+	MSN_AUTH_WHATSNEW      = 5
 } MsnAuthDomains;
 
 #define MSN_SSO_SERVER	"login.live.com"
--- a/libpurple/protocols/msn/notification.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/msn/notification.c	Mon Jun 04 14:18:54 2012 +0000
@@ -164,10 +164,7 @@
 
 	msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_END);
 
-	if (session->protocol_ver >= 16)
-		trans = msn_transaction_new(cmdproc, "USR", "SSO S %s %s %s", ticket, response, session->guid);
-	else
-		trans = msn_transaction_new(cmdproc, "USR", "SSO S %s %s", ticket, response);
+	trans = msn_transaction_new(cmdproc, "USR", "SSO S %s %s %s", ticket, response, session->guid);
 
 	msn_cmdproc_send_trans(cmdproc, trans);
 }
@@ -359,23 +356,34 @@
 
 /*send Message to Yahoo Messenger*/
 void
-uum_send_msg(MsnSession *session,MsnMessage *msg)
+msn_notification_send_uum(MsnSession *session, MsnMessage *msg)
 {
 	MsnCmdProc *cmdproc;
 	MsnTransaction *trans;
 	char *payload;
 	gsize payload_len;
 	int type;
+	MsnUser *user;
+	int network;
+
+	g_return_if_fail(msg != NULL);
 
 	cmdproc = session->notification->cmdproc;
-	g_return_if_fail(msg     != NULL);
+
 	payload = msn_message_gen_payload(msg, &payload_len);
+	type = msg->type;
+	user = msn_userlist_find_user(session->userlist, msg->remote_user);
+	if (user)
+		network = msn_user_get_network(user);
+	else
+		network = MSN_NETWORK_PASSPORT;
+
 	purple_debug_info("msn",
 		"send UUM, payload{%s}, strlen:%" G_GSIZE_FORMAT ", len:%" G_GSIZE_FORMAT "\n",
 		payload, strlen(payload), payload_len);
-	type = msg->type;
-	trans = msn_transaction_new(cmdproc, "UUM", "%s 32 %d %" G_GSIZE_FORMAT,
-		msg->remote_user, type, payload_len);
+
+	trans = msn_transaction_new(cmdproc, "UUM", "%s %d %d %" G_GSIZE_FORMAT,
+		msg->remote_user, network, type, payload_len);
 	msn_transaction_set_payload(trans, payload, strlen(payload));
 	msn_cmdproc_send_trans(cmdproc, trans);
 }
@@ -390,10 +398,7 @@
 	 * command and we are processing it */
 	if (cmd->payload == NULL) {
 		cmdproc->last_cmd->payload_cb = msg_cmd_post;
-		if (cmdproc->session->protocol_ver >= 16)
-			cmd->payload_len = atoi(cmd->params[5]);
-		else
-			cmd->payload_len = atoi(cmd->params[3]);
+		cmd->payload_len = atoi(cmd->params[5]);
 	} else {
 		g_return_if_fail(cmd->payload_cb != NULL);
 
@@ -1042,7 +1047,7 @@
 		networkid = atoi(cmd->params[3]);
 		friendly = g_strdup(purple_url_decode(cmd->params[4]));
 		clientid = strtoul(cmd->params[5], &extcap_str, 10);
-		if (session->protocol_ver >= 16 && extcap_str && *extcap_str)
+		if (extcap_str && *extcap_str)
 			extcaps = strtoul(extcap_str+1, NULL, 10);
 		else
 			extcaps = 0;
@@ -1056,7 +1061,7 @@
 		networkid = atoi(cmd->params[3]);
 		friendly = g_strdup(purple_url_decode(cmd->params[4]));
 		clientid = strtoul(cmd->params[5], &extcap_str, 10);
-		if (session->protocol_ver >= 16 && extcap_str && *extcap_str)
+		if (extcap_str && *extcap_str)
 			extcaps = strtoul(extcap_str+1, NULL, 10);
 		else
 			extcaps = 0;
@@ -1069,7 +1074,7 @@
 			networkid = atoi(cmd->params[3]);
 			friendly = g_strdup(purple_url_decode(cmd->params[4]));
 			clientid = strtoul(cmd->params[5], &extcap_str, 10);
-			if (session->protocol_ver >= 16 && extcap_str && *extcap_str)
+			if (extcap_str && *extcap_str)
 				extcaps = strtoul(extcap_str+1, NULL, 10);
 			else
 				extcaps = 0;
@@ -1077,7 +1082,7 @@
 			/* MSNP8+ with Display Picture object */
 			friendly = g_strdup(purple_url_decode(cmd->params[3]));
 			clientid = strtoul(cmd->params[4], &extcap_str, 10);
-			if (session->protocol_ver >= 16 && extcap_str && *extcap_str)
+			if (extcap_str && *extcap_str)
 				extcaps = strtoul(extcap_str+1, NULL, 10);
 			else
 				extcaps = 0;
@@ -1087,7 +1092,7 @@
 		/* MSNP8+ without Display Picture object */
 		friendly = g_strdup(purple_url_decode(cmd->params[3]));
 		clientid = strtoul(cmd->params[4], &extcap_str, 10);
-		if (session->protocol_ver >= 16 && extcap_str && *extcap_str)
+		if (extcap_str && *extcap_str)
 			extcaps = strtoul(extcap_str+1, NULL, 10);
 		else
 			extcaps = 0;
@@ -1250,15 +1255,15 @@
 	MsnObject *msnobj;
 	unsigned long clientid, extcaps;
 	char *extcap_str;
+	char *passport;
 	int networkid;
-	const char *state, *passport, *friendly;
+	const char *state, *friendly;
 
 	session = cmdproc->session;
 
-	state    = cmd->params[0];
-	passport = cmd->params[1];
-	networkid = atoi(cmd->params[2]);
-	friendly = purple_url_decode(cmd->params[3]);
+	state = cmd->params[0];
+	msn_parse_user(cmd->params[1], &passport, &networkid);
+	friendly = purple_url_decode(cmd->params[2]);
 
 	user = msn_userlist_find_user(session->userlist, passport);
 	if (user == NULL) return;
@@ -1268,9 +1273,9 @@
 		msn_update_contact(session, passport, MSN_UPDATE_DISPLAY, friendly);
 	}
 
-	if (cmd->param_count == 6)
+	if (cmd->param_count == 5)
 	{
-		msnobj = msn_object_new_from_string(purple_url_decode(cmd->params[5]));
+		msnobj = msn_object_new_from_string(purple_url_decode(cmd->params[4]));
 		msn_user_set_object(user, msnobj);
 	}
 	else
@@ -1278,8 +1283,8 @@
 		msn_user_set_object(user, NULL);
 	}
 
-	clientid = strtoul(cmd->params[4], &extcap_str, 10);
-	if (session->protocol_ver >= 16 && extcap_str && *extcap_str)
+	clientid = strtoul(cmd->params[3], &extcap_str, 10);
+	if (extcap_str && *extcap_str)
 		extcaps = strtoul(extcap_str+1, NULL, 10);
 	else
 		extcaps = 0;
@@ -1292,6 +1297,8 @@
 
 	msn_user_set_state(user, state);
 	msn_user_update(user);
+
+	g_free(passport);
 }
 
 #if 0
@@ -1705,22 +1712,27 @@
 {
 	MsnSession *session;
 	MsnUser *user;
-	const char *passport;
+	char *passport;
+	int network;
 	xmlnode *payloadNode;
 	char *psm_str, *str;
 
 	session = cmdproc->session;
 
-	passport = cmd->params[0];
+	msn_parse_user(cmd->params[0], &passport, &network);
 	user = msn_userlist_find_user(session->userlist, passport);
+
 	if (user == NULL) {
-		char *str = g_strndup(payload, len);
+		str = g_strndup(payload, len);
 		purple_debug_info("msn", "unknown user %s, payload is %s\n",
 			passport, str);
+		g_free(passport);
 		g_free(str);
 		return;
 	}
 
+	g_free(passport);
+
 	/* Free any existing media info for this user */
 	if (user->extinfo) {
 		g_free(user->extinfo->media_album);
@@ -1767,7 +1779,7 @@
 {
 	purple_debug_misc("msn", "UBX received.\n");
 	cmdproc->last_cmd->payload_cb  = ubx_cmd_post;
-	cmd->payload_len = atoi(cmd->params[2]);
+	cmd->payload_len = atoi(cmd->params[1]);
 }
 
 static void
@@ -1812,10 +1824,7 @@
 	epDataNode = xmlnode_new("EndpointData");
 
 	capNode = xmlnode_new_child(epDataNode, "Capabilities");
-	if (session->protocol_ver >= 16)
-		caps = g_strdup_printf("%d:%02d", MSN_CLIENT_ID_CAPABILITIES, MSN_CLIENT_ID_EXT_CAPS);
-	else
-		caps = g_strdup_printf("%d", MSN_CLIENT_ID_CAPABILITIES);
+	caps = g_strdup_printf("%d:%02d", MSN_CLIENT_ID_CAPABILITIES, MSN_CLIENT_ID_EXT_CAPS);
 	xmlnode_insert_data(capNode, caps, -1);
 	g_free(caps);
 
@@ -1942,6 +1951,22 @@
 	msn_cmdproc_send_trans(cmdproc, trans);
 }
 
+void
+msn_notification_send_circle_auth(MsnSession *session, const char *ticket)
+{
+	MsnTransaction *trans;
+	MsnCmdProc *cmdproc;
+	char *encoded;
+
+	cmdproc = session->notification->cmdproc;
+
+	encoded = purple_base64_encode((guchar *)ticket, strlen(ticket));
+	trans = msn_transaction_new(cmdproc, "USR", "SHA A %s", encoded);
+	msn_cmdproc_send_trans(cmdproc, trans);
+
+	g_free(encoded);
+}
+
 /**************************************************************************
  * Message Types
  **************************************************************************/
--- a/libpurple/protocols/msn/notification.h	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/msn/notification.h	Mon Jun 04 14:18:54 2012 +0000
@@ -76,8 +76,6 @@
 
 } MsnUnifiedNotificationType;
 
-void uum_send_msg(MsnSession *session, MsnMessage *msg);
-
 void msn_notification_end(void);
 void msn_notification_init(void);
 
@@ -97,6 +95,8 @@
 void msn_notification_disconnect(MsnNotification *notification);
 void msn_notification_dump_contact(MsnSession *session);
 
+void msn_notification_send_uum(MsnSession *session, MsnMessage *msg);
+
 void msn_notification_send_uux(MsnSession *session, const char *payload);
 
 void msn_notification_send_uux_endpointdata(MsnSession *session);
@@ -108,6 +108,8 @@
                                MsnUnifiedNotificationType type,
                                const char *payload);
 
+void msn_notification_send_circle_auth(MsnSession *session, const char *ticket);
+
 /**
  * Closes a notification.
  *
--- a/libpurple/protocols/msn/oim.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/msn/oim.c	Mon Jun 04 14:18:54 2012 +0000
@@ -606,11 +606,12 @@
 	const char *date;
 	const char *from;
 	const char *boundary;
-	char *decode_msg = NULL;
+	char *decode_msg = NULL, *clean_msg = NULL;
 	gsize body_len;
 	char **tokens;
 	char *passport = NULL;
 	time_t stamp;
+	const char *charset = NULL;
 
 	message = msn_message_new(MSN_MSG_UNKNOWN);
 
@@ -638,6 +639,8 @@
 			type = msn_message_get_content_type(multipart);
 			if (type && !strcmp(type, "text/plain")) {
 				decode_msg = (char *)purple_base64_decode(multipart->body, &body_len);
+				charset = msn_message_get_charset(multipart);
+
 				msn_message_unref(multipart);
 				break;
 			}
@@ -654,6 +657,46 @@
 		}
 	} else {
 		decode_msg = (char *)purple_base64_decode(message->body, &body_len);
+		charset = msn_message_get_charset(message);
+	}
+
+	if (charset && !((strncasecmp(charset, "UTF-8", 5) == 0) || (strncasecmp(charset, "UTF8", 4) == 0))) {
+		clean_msg = g_convert(decode_msg, body_len, "UTF-8", charset, NULL, NULL, NULL);
+
+		if (!clean_msg) {
+			char *clean = purple_utf8_salvage(decode_msg);
+
+			purple_debug_error("msn", "Failed to convert charset from %s to UTF-8 for OIM message: %s\n", charset, clean);
+
+			clean_msg = g_strdup_printf(_("%s (There was an error receiving this message. "
+			                              "Converting the encoding from %s to UTF-8 failed.)"),
+			                            clean, charset);
+			g_free(clean);
+		}
+
+		g_free(decode_msg);
+
+	} else if (!g_utf8_validate(decode_msg, body_len, NULL)) {
+		char *clean = purple_utf8_salvage(decode_msg);
+
+		purple_debug_error("msn", "Received an OIM message that is not UTF-8,"
+		                          " and no encoding specified: %s\n", clean);
+
+		if (charset) {
+			clean_msg = g_strdup_printf(_("%s (There was an error receiving this message."
+			                              " The charset was %s, but it was not valid UTF-8.)"),
+			                            clean, charset);
+		} else {
+			clean_msg = g_strdup_printf(_("%s (There was an error receiving this message."
+			                              " The charset was missing, but it was not valid UTF-8.)"),
+			                            clean);
+		}
+
+		g_free(clean);
+		g_free(decode_msg);
+
+	} else {
+		clean_msg = decode_msg;
 	}
 
 	from = msn_message_get_header_value(message, "X-OIM-originatingSource");
@@ -695,7 +738,7 @@
 	purple_debug_info("msn", "oim Date:{%s},passport{%s}\n",
 	                  date, passport);
 
-	serv_got_im(purple_account_get_connection(rdata->oim->session->account), passport, decode_msg, 0,
+	serv_got_im(purple_account_get_connection(rdata->oim->session->account), passport, clean_msg, 0,
 	            stamp);
 
 	/*Now get the oim message ID from the oim_list.
@@ -704,7 +747,7 @@
 	msn_oim_post_delete_msg(rdata);
 
 	g_free(passport);
-	g_free(decode_msg);
+	g_free(clean_msg);
 	msn_message_unref(message);
 }
 
--- a/libpurple/protocols/msn/session.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/msn/session.c	Mon Jun 04 14:18:54 2012 +0000
@@ -491,11 +491,10 @@
 		msn_session_sync_users(session);
 	}
 
-	if (session->protocol_ver >= 16) {
-		/* TODO: Send this when updating status instead? */
-		msn_notification_send_uux_endpointdata(session);
-		msn_notification_send_uux_private_endpointdata(session);
-	}
+	/* TODO: Send this when updating status instead? */
+	msn_notification_send_uux_endpointdata(session);
+	msn_notification_send_uux_private_endpointdata(session);
+
 	msn_change_status(session);
 }
 
--- a/libpurple/protocols/msn/state.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/msn/state.c	Mon Jun 04 14:18:54 2012 +0000
@@ -186,7 +186,7 @@
 	statusline_stripped = purple_markup_strip_html(statusline);
 	media = create_media_string(presence);
 	g_free(session->psm);
-	session->psm = msn_build_psm(statusline_stripped, media, session->protocol_ver >= 16 ? session->guid : NULL, session->protocol_ver);
+	session->psm = msn_build_psm(statusline_stripped, media, session->guid, session->protocol_ver);
 
 	payload = session->psm;
 
@@ -245,10 +245,8 @@
 
 	if (msnobj == NULL)
 	{
-		if (session->protocol_ver >= 16)
-			trans = msn_transaction_new(cmdproc, "CHG", "%s %u:%02u 0", state_text, caps, MSN_CLIENT_ID_EXT_CAPS);
-		else
-			trans = msn_transaction_new(cmdproc, "CHG", "%s %u", state_text, caps);
+		trans = msn_transaction_new(cmdproc, "CHG", "%s %u:%02u 0", state_text,
+		                            caps, MSN_CLIENT_ID_EXT_CAPS);
 	}
 	else
 	{
@@ -256,12 +254,9 @@
 
 		msnobj_str = msn_object_to_string(msnobj);
 
-		if (session->protocol_ver >= 16)
-			trans = msn_transaction_new(cmdproc, "CHG", "%s %u:%02u %s", state_text,
-							 caps, MSN_CLIENT_ID_EXT_CAPS, purple_url_encode(msnobj_str));
-		else
-			trans = msn_transaction_new(cmdproc, "CHG", "%s %u %s", state_text,
-							 caps, purple_url_encode(msnobj_str));
+		trans = msn_transaction_new(cmdproc, "CHG", "%s %u:%02u %s", state_text,
+		                            caps, MSN_CLIENT_ID_EXT_CAPS,
+		                            purple_url_encode(msnobj_str));
 
 		g_free(msnobj_str);
 	}
--- a/libpurple/protocols/msn/switchboard.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/msn/switchboard.c	Mon Jun 04 14:18:54 2012 +0000
@@ -707,10 +707,7 @@
 ubm_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
 	purple_debug_misc("msn", "get UBM...\n");
-	if (cmdproc->session->protocol_ver >= 16)
-		cmd->payload_len = atoi(cmd->params[5]);
-	else
-		cmd->payload_len = atoi(cmd->params[3]);
+	cmd->payload_len = atoi(cmd->params[5]);
 	cmdproc->last_cmd->payload_cb = msg_cmd_post;
 }
 
@@ -867,12 +864,9 @@
 	swboard = cmdproc->data;
 	g_return_if_fail(swboard != NULL);
 
-	if (servconn->session->protocol_ver >= 16)
-		username = g_strdup_printf("%s;{%s}",
-		                           purple_account_get_username(account),
-		                           servconn->session->guid);
-	else
-		username = g_strdup(purple_account_get_username(account));
+	username = g_strdup_printf("%s;{%s}",
+	                           purple_account_get_username(account),
+	                           servconn->session->guid);
 
 	if (msn_switchboard_is_invited(swboard))
 	{
--- a/libpurple/protocols/msn/user.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/msn/user.c	Mon Jun 04 14:18:54 2012 +0000
@@ -699,6 +699,14 @@
 	return NULL;
 }
 
+MsnNetwork
+msn_user_get_network(const MsnUser *user)
+{
+	g_return_val_if_fail(user != NULL, MSN_NETWORK_UNKNOWN);
+
+	return user->networkid;
+}
+
 MsnObject *
 msn_user_get_object(const MsnUser *user)
 {
--- a/libpurple/protocols/oscar/family_feedbag.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/oscar/family_feedbag.c	Mon Jun 04 14:18:54 2012 +0000
@@ -769,7 +769,7 @@
  * @param od The oscar odion.
  * @return Return 0 if no errors, otherwise return the error number.
  */
-int aim_ssi_cleanlist(OscarData *od)
+static int aim_ssi_cleanlist(OscarData *od)
 {
 	struct aim_ssi_item *cur, *next;
 
@@ -971,7 +971,7 @@
 	aim_ssi_itemlist_del(&od->ssi.local, del);
 
 	/* Modify the parent group */
-	aim_ssi_itemlist_rebuildgroup(&od->ssi.local, group);
+	aim_ssi_itemlist_rebuildgroup(&od->ssi.local, NULL);
 
 	/* Sync our local list with the server list */
 	return aim_ssi_sync(od);
@@ -1336,6 +1336,9 @@
 		for (cur=od->ssi.official.data; cur; cur=cur->next)
 			aim_ssi_itemlist_add(&od->ssi.local, cur->name, cur->gid, cur->bid, cur->type, cur->data);
 
+		/* Clean the buddy list */
+		aim_ssi_cleanlist(od);
+
 		od->ssi.received_data = TRUE;
 
 		if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
--- a/libpurple/protocols/oscar/family_icbm.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/oscar/family_icbm.c	Mon Jun 04 14:18:54 2012 +0000
@@ -650,6 +650,9 @@
 	GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
 	ByteStream hdrbs;
 
+	g_return_if_fail(bn != NULL);
+	g_return_if_fail(ip != NULL);
+
 	conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
 	if (conn == NULL)
 		return;
--- a/libpurple/protocols/oscar/oscar.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Mon Jun 04 14:18:54 2012 +0000
@@ -3924,9 +3924,6 @@
 
 	purple_debug_info("oscar", "ssi: syncing local list and server list\n");
 
-	/* Clean the buddy list */
-	aim_ssi_cleanlist(od);
-
 	/*** Begin code for pruning buddies from local list if they're not in server list ***/
 
 	/* Buddies */
--- a/libpurple/protocols/oscar/oscar.h	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/oscar/oscar.h	Mon Jun 04 14:18:54 2012 +0000
@@ -940,7 +940,6 @@
 int aim_ssi_aliasbuddy(OscarData *od, const char *gn, const char *bn, const char *alias);
 int aim_ssi_editcomment(OscarData *od, const char *gn, const char *bn, const char *alias);
 int aim_ssi_rename_group(OscarData *od, const char *oldgn, const char *newgn);
-int aim_ssi_cleanlist(OscarData *od);
 int aim_ssi_deletelist(OscarData *od);
 int aim_ssi_setpermdeny(OscarData *od, guint8 permdeny);
 int aim_ssi_setpresence(OscarData *od, guint32 presence);
--- a/libpurple/protocols/oscar/peer.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/oscar/peer.c	Mon Jun 04 14:18:54 2012 +0000
@@ -656,6 +656,7 @@
 	char *tmp;
 	FlapConnection *bos_conn;
 	const char *listener_ip;
+	const guchar *ip_atoi;
 	unsigned short listener_port;
 
 	conn = data;
@@ -690,11 +691,28 @@
 		listener_ip = purple_network_get_my_ip(bos_conn->gsc->fd);
 	else
 		listener_ip = purple_network_get_my_ip(bos_conn->fd);
+
+	ip_atoi = purple_network_ip_atoi(listener_ip);
+	if (ip_atoi == NULL) {
+		/* Could not convert IP to 4 byte array--weird, but this does
+		   happen for some users (#4829, Adium #15839).  Maybe they're
+		   connecting with IPv6...?  Maybe through a proxy? */
+		purple_debug_error("oscar", "Can't ask peer to connect to us "
+				"because purple_network_ip_atoi(%s) returned NULL. "
+				"fd=%d. is_ssl=%d\n",
+				listener_ip ? listener_ip : "(null)",
+				bos_conn->gsc ? bos_conn->gsc->fd : bos_conn->fd,
+				bos_conn->gsc ? 1 : 0);
+		peer_connection_trynext(conn);
+		return;
+	}
+
 	listener_port = purple_network_get_port_from_fd(conn->listenerfd);
+
 	if (conn->type == OSCAR_CAPABILITY_DIRECTIM)
 	{
 		aim_im_sendch2_odc_requestdirect(od,
-				conn->cookie, conn->bn, purple_network_ip_atoi(listener_ip),
+				conn->cookie, conn->bn, ip_atoi,
 				listener_port, ++conn->lastrequestnumber);
 
 		/* Print a message to a local conversation window */
@@ -706,15 +724,6 @@
 	}
 	else if (conn->type == OSCAR_CAPABILITY_SENDFILE)
 	{
-		const guchar *ip_atoi = purple_network_ip_atoi(listener_ip);
-		if (ip_atoi == NULL) {
-			purple_debug_error("oscar", "Cannot send file. atoi(%s) failed.\n"
-					"Other possibly useful information: fd = %d, port = %d\n",
-					listener_ip ? listener_ip : "(null!)", conn->listenerfd,
-					listener_port);
-			purple_xfer_cancel_local(conn->xfer);
-			return;
-		}
 		aim_im_sendch2_sendfile_requestdirect(od,
 				conn->cookie, conn->bn,
 				ip_atoi,
--- a/libpurple/protocols/oscar/util.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/libpurple/protocols/oscar/util.c	Mon Jun 04 14:18:54 2012 +0000
@@ -142,7 +142,7 @@
 		return TRUE;
 
 	/* Normal AIM usernames can't start with a number, period or underscore */
-	if (isalnum(name[0]))
+	if (isalnum(name[0]) == 0)
 		return FALSE;
 
 	for (i = 0; name[i] != '\0'; i++) {
--- a/pidgin/gtkconv.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/pidgin/gtkconv.c	Mon Jun 04 14:18:54 2012 +0000
@@ -5759,7 +5759,7 @@
 	if (convnode == NULL || !purple_blist_node_get_bool(convnode, "gtk-mute-sound"))
 		gtkconv->make_sound = TRUE;
 
-	if (convnode != NULL) {
+	if (convnode != NULL && purple_blist_node_has_setting(convnode, "enable-logging")) {
 		gboolean logging = purple_blist_node_get_bool(convnode, "enable-logging");
 		purple_conversation_set_logging(conv, logging);
 	}
--- a/pidgin/gtkdialogs.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/pidgin/gtkdialogs.c	Mon Jun 04 14:18:54 2012 +0000
@@ -78,8 +78,6 @@
 	{"Hylke Bons",                         N_("artist"),          "hylkebons@gmail.com"},
 	{"Sadrul Habib Chowdhury",             NULL,                  NULL},
 	{"Mark 'KingAnt' Doliner",             NULL,                  "mark@kingant.net"},
-	{"Casey Harkins",                      NULL,                  NULL},
-	{"Ivan Komarov",                       NULL,                  "ivan.komarov@pidgin.im"},
 	{"Gary 'grim' Kramlich",               NULL,                  "grim@pidgin.im"},
 	{"Richard 'rlaager' Laager",           NULL,                  "rlaager@pidgin.im"},
 	{"Marcus 'malu' Lundblad",             NULL,                  NULL},
@@ -112,12 +110,14 @@
 	{"Herman Bloggs",               N_("win32 port"),          "herman@bluedigits.com"},
 	{"Thomas Butter",               NULL,                      NULL},
 	/* feel free to not translate this */
-	{N_("Ka-Hing Cheung"),                 NULL,                  NULL},
+	{N_("Ka-Hing Cheung"),          NULL,                      NULL},
 	{"Jim Duchek",                  N_("maintainer"),          "jim@linuxpimps.com"},
 	{"Sean Egan",                   NULL,                      "sean.egan@gmail.com"},
 	{"Rob Flynn",                   N_("maintainer"),          NULL},
 	{"Adam Fritzler",               N_("libfaim maintainer"),  NULL},
 	{"Christian 'ChipX86' Hammond", N_("webmaster"),           NULL},
+	{"Casey Harkins",               NULL,                      NULL},
+	{"Ivan Komarov",                NULL,                      "ivan.komarov@pidgin.im"},
 	/* If "lazy bum" translates literally into a serious insult, use something else or omit it. */
 	{"Syd Logan",                   N_("hacker and designated driver [lazy bum]"), NULL},
 	{"Christopher 'siege' O'Brien", NULL,                      "taliesein@users.sf.net"},
--- a/pidgin/plugins/disco/gtkdisco.c	Mon Jan 09 11:24:26 2012 +0000
+++ b/pidgin/plugins/disco/gtkdisco.c	Mon Jun 04 14:18:54 2012 +0000
@@ -462,6 +462,8 @@
 	gtk_tree_model_get_value(GTK_TREE_MODEL(pdl->model), &iter, SERVICE_COLUMN,
 	                         &val);
 	service = g_value_get_pointer(&val);
+	if (!service)
+		return FALSE;
 
 	switch (service->type) {
 		case XMPP_DISCO_SERVICE_TYPE_UNSET:

mercurial