Bug 1207551 - Remove libpurple msn prpl. r=clokep
authoraleth <aleth@instantbird.org>
Wed, 23 Sep 2015 15:32:00 +0200
changeset 786 d4ef6e84d8a0aa5f6dfd87f794a16b7f30ad09a4
parent 785 d8a03ccd5d668cbb0ed3f2dcc468f3ef091fcf5d
child 787 6476bd54c5ca7c4674095f2740aacaea06fb3047
push id61
push useraleth@instantbird.org
push dateWed, 30 Mar 2016 16:06:14 +0000
reviewersclokep
bugs1207551
Bug 1207551 - Remove libpurple msn prpl. r=clokep
configure.in
icons/prpl-msn-32.png
icons/prpl-msn-48.png
icons/prpl-msn.png
jar.mn
libpurple/moz.build
libpurple/protocols/msn/Makefile.in
libpurple/protocols/msn/cmdproc.c
libpurple/protocols/msn/cmdproc.h
libpurple/protocols/msn/command.c
libpurple/protocols/msn/command.h
libpurple/protocols/msn/contact.c
libpurple/protocols/msn/contact.h
libpurple/protocols/msn/directconn.c
libpurple/protocols/msn/directconn.h
libpurple/protocols/msn/error.c
libpurple/protocols/msn/error.h
libpurple/protocols/msn/group.c
libpurple/protocols/msn/group.h
libpurple/protocols/msn/history.c
libpurple/protocols/msn/history.h
libpurple/protocols/msn/httpconn.c
libpurple/protocols/msn/httpconn.h
libpurple/protocols/msn/moz.build
libpurple/protocols/msn/msg.c
libpurple/protocols/msn/msg.h
libpurple/protocols/msn/msn.c
libpurple/protocols/msn/msn.h
libpurple/protocols/msn/msnutils.c
libpurple/protocols/msn/msnutils.h
libpurple/protocols/msn/nexus.c
libpurple/protocols/msn/nexus.h
libpurple/protocols/msn/notification.c
libpurple/protocols/msn/notification.h
libpurple/protocols/msn/object.c
libpurple/protocols/msn/object.h
libpurple/protocols/msn/oim.c
libpurple/protocols/msn/oim.h
libpurple/protocols/msn/p2p.c
libpurple/protocols/msn/p2p.h
libpurple/protocols/msn/page.c
libpurple/protocols/msn/page.h
libpurple/protocols/msn/sbconn.c
libpurple/protocols/msn/sbconn.h
libpurple/protocols/msn/servconn.c
libpurple/protocols/msn/servconn.h
libpurple/protocols/msn/session.c
libpurple/protocols/msn/session.h
libpurple/protocols/msn/slp.c
libpurple/protocols/msn/slp.h
libpurple/protocols/msn/slpcall.c
libpurple/protocols/msn/slpcall.h
libpurple/protocols/msn/slplink.c
libpurple/protocols/msn/slplink.h
libpurple/protocols/msn/slpmsg.c
libpurple/protocols/msn/slpmsg.h
libpurple/protocols/msn/slpmsg_part.c
libpurple/protocols/msn/slpmsg_part.h
libpurple/protocols/msn/soap.c
libpurple/protocols/msn/soap.h
libpurple/protocols/msn/state.c
libpurple/protocols/msn/state.h
libpurple/protocols/msn/switchboard.c
libpurple/protocols/msn/switchboard.h
libpurple/protocols/msn/table.c
libpurple/protocols/msn/table.h
libpurple/protocols/msn/tlv.c
libpurple/protocols/msn/tlv.h
libpurple/protocols/msn/transaction.c
libpurple/protocols/msn/transaction.h
libpurple/protocols/msn/user.c
libpurple/protocols/msn/user.h
libpurple/protocols/msn/userlist.c
libpurple/protocols/msn/userlist.h
libpurple/protocols/msn/xfer.c
libpurple/protocols/msn/xfer.h
locales/en-US/msn.properties
locales/jar.mn
purplexpcom/src/prpl.manifest
purplexpcom/src/test/test_purplexpcom.js
tools/l10n/convert-purple-po-files-to-properties-files.py
--- a/configure.in
+++ b/configure.in
@@ -177,17 +177,17 @@ AC_DEFUN([PKG_CHECK_MODULES],
 
 dnl ========================================================
 dnl Check for libxml2.
 dnl ========================================================
 if test "${OS_TARGET}" = "Linux"; then
     PKG_CHECK_MODULES(LIBXML2, libxml-2.0)
 fi
 
-STATIC_PRPLS="jabber gg oscar msn myspace novell sametime simple yahoo netsoul"
+STATIC_PRPLS="jabber gg oscar myspace novell sametime simple yahoo netsoul"
 
 MOZ_ARG_ENABLE_BOOL(purple-plugins,
 [  --enable-purple-plugins      Enable usage of system libpurple plugins],
     PURPLE_PLUGINS=1,
     PURPLE_PLUGINS= )
 AC_SUBST(PURPLE_PLUGINS)
 
 dnl =========================================================
deleted file mode 100644
index c06eed2aa402eeb24e1d8083ef5b427227ba1bfe..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 1b960dd327dbeda55002d9fac245c07dbd04fd90..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 896d90cfbb9042179468285ab71647faffe2651c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/jar.mn
+++ b/jar.mn
@@ -14,20 +14,16 @@ purple.jar:
 % skin prpl-gg classic/1.0 %skin/classic/prpl/gg/
 	skin/classic/prpl/gg/icon32.png		(icons/prpl-gg-32.png)
 	skin/classic/prpl/gg/icon48.png		(icons/prpl-gg-48.png)
 	skin/classic/prpl/gg/icon.png		(icons/prpl-gg.png)
 % skin prpl-icq classic/1.0 %skin/classic/prpl/icq/
 	skin/classic/prpl/icq/icon32.png	(icons/prpl-icq-32.png)
 	skin/classic/prpl/icq/icon48.png	(icons/prpl-icq-48.png)
 	skin/classic/prpl/icq/icon.png		(icons/prpl-icq.png)
-% skin prpl-msn classic/1.0 %skin/classic/prpl/msn/
-	skin/classic/prpl/msn/icon32.png	(icons/prpl-msn-32.png)
-	skin/classic/prpl/msn/icon48.png	(icons/prpl-msn-48.png)
-	skin/classic/prpl/msn/icon.png		(icons/prpl-msn.png)
 % skin prpl-myspace classic/1.0 %skin/classic/prpl/myspace/
 	skin/classic/prpl/myspace/icon32.png	(icons/prpl-myspace-32.png)
 	skin/classic/prpl/myspace/icon48.png	(icons/prpl-myspace-48.png)
 	skin/classic/prpl/myspace/icon.png	(icons/prpl-myspace.png)
 % skin prpl-novell classic/1.0 %skin/classic/prpl/novell/
 	skin/classic/prpl/novell/icon32.png	(icons/prpl-novell-32.png)
 	skin/classic/prpl/novell/icon48.png	(icons/prpl-novell-48.png)
 	skin/classic/prpl/novell/icon.png	(icons/prpl-novell.png)
--- a/libpurple/moz.build
+++ b/libpurple/moz.build
@@ -1,14 +1,14 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-prpls = ['jabber', 'gg', 'oscar', 'msn', 'myspace', 'novell',
+prpls = ['jabber', 'gg', 'oscar', 'myspace', 'novell',
          'sametime', 'simple', 'yahoo', 'netsoul', 'sipe']
 
 if CONFIG['PURPLE_BONJOUR']:
     prpls += ['bonjour']
 
 if CONFIG['MOZ_DEBUG']:
     prpls += ['null']
 
deleted file mode 100644
--- a/libpurple/protocols/msn/Makefile.in
+++ /dev/null
@@ -1,15 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DEPTH		= @DEPTH@
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-PROTOCOL	= msn
-
-include $(srcdir)/../prpl.mk
-
-DEFINES		+= -DPACKAGE_NAME=\"purple\"
-
-include $(srcdir)/../prpl-rules.mk
deleted file mode 100644
--- a/libpurple/protocols/msn/cmdproc.c
+++ /dev/null
@@ -1,339 +0,0 @@
-/**
- * @file cmdproc.c MSN command processor functions
- *
- * purple
- *
- * Purple 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 "debug.h"
-
-#include "cmdproc.h"
-#include "error.h"
-
-MsnCmdProc *
-msn_cmdproc_new(MsnSession *session)
-{
-	MsnCmdProc *cmdproc;
-
-	cmdproc = g_new0(MsnCmdProc, 1);
-
-	cmdproc->session = session;
-	cmdproc->txqueue = g_queue_new();
-	cmdproc->history = msn_history_new();
-
-	cmdproc->multiparts = g_hash_table_new_full(g_str_hash, g_str_equal,
-	                                            NULL, (GDestroyNotify)msn_message_unref);
-
-	return cmdproc;
-}
-
-void
-msn_cmdproc_destroy(MsnCmdProc *cmdproc)
-{
-	MsnTransaction *trans;
-
-	while ((trans = g_queue_pop_head(cmdproc->txqueue)) != NULL)
-		msn_transaction_destroy(trans);
-
-	g_queue_free(cmdproc->txqueue);
-
-	msn_history_destroy(cmdproc->history);
-
-	if (cmdproc->last_cmd != NULL)
-		msn_command_unref(cmdproc->last_cmd);
-
-	g_hash_table_destroy(cmdproc->multiparts);
-
-	g_free(cmdproc);
-}
-
-void
-msn_cmdproc_process_queue(MsnCmdProc *cmdproc)
-{
-	MsnTransaction *trans;
-
-	while ((trans = g_queue_pop_head(cmdproc->txqueue)) != NULL)
-		msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-void
-msn_cmdproc_queue_trans(MsnCmdProc *cmdproc, MsnTransaction *trans)
-{
-	g_return_if_fail(cmdproc != NULL);
-	g_return_if_fail(trans   != NULL);
-
-	g_queue_push_tail(cmdproc->txqueue, trans);
-}
-
-static void
-show_debug_cmd(MsnCmdProc *cmdproc, gboolean incoming, const char *command)
-{
-	MsnServConn *servconn;
-	const char *names[] = { "NS", "SB" };
-	char *show;
-	char tmp;
-	size_t len;
-
-	servconn = cmdproc->servconn;
-	len = strlen(command);
-	show = g_strdup(command);
-
-	tmp = (incoming) ? 'S' : 'C';
-
-	if ((show[len - 1] == '\n') && (show[len - 2] == '\r'))
-	{
-		show[len - 2] = '\0';
-	}
-
-	purple_debug_misc("msn", "%c: %s %03d: %s\n", tmp,
-					names[servconn->type], servconn->num, show);
-
-	g_free(show);
-}
-
-gboolean
-msn_cmdproc_send_trans(MsnCmdProc *cmdproc, MsnTransaction *trans)
-{
-	MsnServConn *servconn;
-	char *data;
-	size_t len;
-	gboolean ret;
-
-	g_return_val_if_fail(cmdproc != NULL, TRUE);
-	g_return_val_if_fail(trans != NULL, TRUE);
-
-	servconn = cmdproc->servconn;
-
-	if (!servconn->connected) {
-		msn_transaction_destroy(trans);
-		return FALSE;
-	}
-
-	if (trans->saveable)
-		msn_history_add(cmdproc->history, trans);
-
-	data = msn_transaction_to_string(trans);
-
-	len = strlen(data);
-
-	show_debug_cmd(cmdproc, FALSE, data);
-
-	if (trans->callbacks == NULL)
-		trans->callbacks = g_hash_table_lookup(cmdproc->cbs_table->cmds,
-											   trans->command);
-
-	if (trans->payload != NULL)
-	{
-		data = g_realloc(data, len + trans->payload_len);
-		memcpy(data + len, trans->payload, trans->payload_len);
-		len += trans->payload_len;
-
-		/*
-		 * We're done with trans->payload.  Free it so that the memory
-		 * doesn't sit around in cmdproc->history.
-		 */
-		g_free(trans->payload);
-		trans->payload = NULL;
-		trans->payload_len = 0;
-	}
-
-	ret = msn_servconn_write(servconn, data, len) != -1;
-
-	if (!trans->saveable)
-		msn_transaction_destroy(trans);
-	g_free(data);
-	return ret;
-}
-
-void
-msn_cmdproc_process_payload(MsnCmdProc *cmdproc, char *payload,
-							int payload_len)
-{
-	MsnCommand *last;
-
-	g_return_if_fail(cmdproc != NULL);
-
-	last = cmdproc->last_cmd;
-	last->payload = g_memdup(payload, payload_len);
-	last->payload_len = payload_len;
-
-	if (last->payload_cb != NULL)
-		last->payload_cb(cmdproc, last, payload, payload_len);
-}
-
-void
-msn_cmdproc_process_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	MsnMsgTypeCb cb;
-	const char *message_id = NULL;
-
-	/* Multi-part messages */
-	message_id = msn_message_get_header_value(msg, "Message-ID");
-	if (message_id != NULL) {
-		/* This is the first in a series of chunks */
-
-		const char *chunk_text = msn_message_get_header_value(msg, "Chunks");
-		guint chunk;
-		if (chunk_text != NULL) {
-			chunk = strtol(chunk_text, NULL, 10);
-			/* 1024 chunks of ~1300 bytes is ~1MB, which seems OK to prevent
-			   some random client causing pidgin to hog a ton of memory.
-			   Probably should figure out the maximum that the official client
-			   actually supports, though. */
-			if (chunk > 0 && chunk < 1024) {
-				msg->total_chunks = chunk;
-				msg->received_chunks = 1;
-				g_hash_table_insert(cmdproc->multiparts, (gpointer)message_id, msn_message_ref(msg));
-				purple_debug_info("msn", "Received chunked message, message_id: '%s', total chunks: %d\n",
-				                  message_id, chunk);
-			} else {
-				purple_debug_error("msn", "MessageId '%s' has too many chunks: %d\n", message_id, chunk);
-			}
-			return;
-		} else {
-			chunk_text = msn_message_get_header_value(msg, "Chunk");
-			if (chunk_text != NULL) {
-				/* This is one chunk in a series of chunks */
-
-				MsnMessage *first = g_hash_table_lookup(cmdproc->multiparts, message_id);
-				chunk = strtol(chunk_text, NULL, 10);
-				if (first != NULL) {
-					if (first->received_chunks != chunk) {
-						/*
-						 * We received an out of order chunk number (i.e. not the
-						 * next one in the sequence).  Not sure if this can happen
-						 * legitimately, but we definitely don't handle it right
-						 * now.
-						 */
-						g_hash_table_remove(cmdproc->multiparts, message_id);
-						return;
-					}
-
-					/* Chunk is from 1 to total-1 (doesn't count first one) */
-					purple_debug_info("msn", "Received chunk %d of %d, message_id: '%s'\n",
-							chunk + 1, first->total_chunks, message_id);
-					first->body = g_realloc(first->body, first->body_len + msg->body_len);
-					memcpy(first->body + first->body_len, msg->body, msg->body_len);
-					first->body_len += msg->body_len;
-					first->received_chunks++;
-					if (first->received_chunks != first->total_chunks)
-						/* We're waiting for more chunks */
-						return;
-
-					/*
-					 * We have all the chunks for this message, great!  Send
-					 * it along... The caller takes care of freeing the old one.
-					 */
-					msg = first;
-				} else {
-					purple_debug_error("msn",
-					                   "Unable to find first chunk of message_id '%s' to correspond with chunk %d.\n",
-					                   message_id, chunk + 1);
-				}
-			} else {
-				purple_debug_error("msn", "Received MessageId '%s' with no chunk number!\n", message_id);
-			}
-		}
-	}
-
-	if (msn_message_get_content_type(msg) == NULL)
-	{
-		purple_debug_misc("msn", "failed to find message content\n");
-		return;
-	}
-
-	cb = g_hash_table_lookup(cmdproc->cbs_table->msgs,
-							 msn_message_get_content_type(msg));
-
-	if (cb != NULL)
-		cb(cmdproc, msg);
-	else
-		purple_debug_warning("msn", "Unhandled content-type '%s'\n",
-						   msn_message_get_content_type(msg));
-
-	if (message_id != NULL)
-		g_hash_table_remove(cmdproc->multiparts, message_id);
-}
-
-void
-msn_cmdproc_process_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnTransCb cb = NULL;
-	MsnTransaction *trans = NULL;
-
-	if (cmd->trId)
-		cmd->trans = trans = msn_history_find(cmdproc->history, cmd->trId);
-
-	if (trans != NULL)
-		if (trans->timer) {
-			purple_timeout_remove(trans->timer);
-			trans->timer = 0;
-		}
-
-	if (g_ascii_isdigit(cmd->command[0]) && trans != NULL)
-	{
-		MsnErrorCb error_cb;
-		int error;
-
-		error = atoi(cmd->command);
-
-		error_cb = trans->error_cb;
-		if (error_cb == NULL)
-			error_cb = g_hash_table_lookup(cmdproc->cbs_table->errors, trans->command);
-
-		if (error_cb != NULL)
-			error_cb(cmdproc, trans, error);
-		else
-			msn_error_handle(cmdproc->session, error);
-
-		return;
-	}
-
-	cb = g_hash_table_lookup(cmdproc->cbs_table->async, cmd->command);
-
-	if (cb == NULL && trans != NULL && trans->callbacks != NULL)
-		cb = g_hash_table_lookup(trans->callbacks, cmd->command);
-
-	if (cb == NULL)
-		cb = g_hash_table_lookup(cmdproc->cbs_table->fallback, cmd->command);
-
-	if (cb != NULL)
-		cb(cmdproc, cmd);
-	else
-		purple_debug_warning("msn", "Unhandled command '%s'\n",
-						   cmd->command);
-
-	if (trans != NULL && trans->pendent_cmd != NULL)
-		msn_transaction_unqueue_cmd(trans, cmdproc);
-}
-
-void
-msn_cmdproc_process_cmd_text(MsnCmdProc *cmdproc, const char *command)
-{
-	show_debug_cmd(cmdproc, TRUE, command);
-
-	if (cmdproc->last_cmd != NULL)
-		msn_command_unref(cmdproc->last_cmd);
-
-	cmdproc->last_cmd = msn_command_from_string(command);
-
-	msn_cmdproc_process_cmd(cmdproc, cmdproc->last_cmd);
-}
deleted file mode 100644
--- a/libpurple/protocols/msn/cmdproc.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
- * @file cmdproc.h MSN command processor functions
- *
- * purple
- *
- * Purple 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 MSN_CMDPROC_H
-#define MSN_CMDPROC_H
-
-typedef struct _MsnCmdProc MsnCmdProc;
-
-#include "command.h"
-#include "history.h"
-#include "servconn.h"
-#include "session.h"
-#include "table.h"
-
-struct _MsnCmdProc
-{
-	MsnSession *session;
-	MsnServConn *servconn;
-
-	GQueue *txqueue;
-
-	MsnCommand *last_cmd;
-
-	MsnTable *cbs_table;
-
-	MsnHistory *history;
-
-	GHashTable *multiparts; /**< Multi-part message ID's */
-
-	void *data; /**< Extra data, like the switchboard. */
-};
-
-/**
- * Creates a MsnCmdProc structure.
- *
- * @param session 	The session to associate with.
- *
- * @return A new MsnCmdProc structure.
- */
-MsnCmdProc *msn_cmdproc_new(MsnSession *session);
-
-/**
- * Destroys an MsnCmdProc.
- *
- * @param cmdproc 	The object structure.
- */
-void msn_cmdproc_destroy(MsnCmdProc *cmdproc);
-
-/**
- * Process the queued transactions.
- *
- * @param cmdproc 	The MsnCmdProc.
- */
-void msn_cmdproc_process_queue(MsnCmdProc *cmdproc);
-
-/**
- * Sends transaction using this servconn.
- *
- * @param cmdproc 	The MsnCmdProc to be used.
- * @param trans 	The MsnTransaction to be sent.
- */
-gboolean msn_cmdproc_send_trans(MsnCmdProc *cmdproc, MsnTransaction *trans);
-
-/**
- * Add a transaction to the queue to be processed latter.
- *
- * @param cmdproc 	The MsnCmdProc in which the transaction will be queued.
- * @param trans 	The MsnTransaction to be queued.
- */
-void msn_cmdproc_queue_trans(MsnCmdProc *cmdproc,
-							 MsnTransaction *trans);
-
-void msn_cmdproc_process_msg(MsnCmdProc *cmdproc,
-							 MsnMessage *msg);
-void msn_cmdproc_process_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd);
-void msn_cmdproc_process_cmd_text(MsnCmdProc *cmdproc, const char *command);
-void msn_cmdproc_process_payload(MsnCmdProc *cmdproc,
-								 char *payload, int payload_len);
-
-#endif /* MSN_CMDPROC_H */
deleted file mode 100644
--- a/libpurple/protocols/msn/command.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/**
- * @file command.c MSN command functions
- *
- * purple
- *
- * Purple 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 "command.h"
-
-static gboolean
-is_num(const char *str)
-{
-	const char *c;
-	for (c = str; *c; c++) {
-		if (!(g_ascii_isdigit(*c)))
-			return FALSE;
-	}
-
-	return TRUE;
-}
-
-MsnCommand *
-msn_command_from_string(const char *string)
-{
-	MsnCommand *cmd;
-	char *param_start;
-
-	g_return_val_if_fail(string != NULL, NULL);
-
-	cmd = g_new0(MsnCommand, 1);
-	cmd->command = g_strdup(string);
-	param_start = strchr(cmd->command, ' ');
-
-	if (param_start)
-	{
-		*param_start++ = '\0';
-		cmd->params = g_strsplit_set(param_start, " ", 0);
-	}
-
-	if (cmd->params != NULL)
-	{
-		guint c;
-
-		for (c = 0; cmd->params[c] && cmd->params[c][0]; c++);
-		cmd->param_count = c;
-
-		if (cmd->param_count) {
-			char *param = cmd->params[0];
-			cmd->trId = is_num(param) ? atoi(param) : 0;
-		} else {
-			cmd->trId = 0;
-		}
-	}
-	else
-	{
-		cmd->trId = 0;
-	}
-
-	msn_command_ref(cmd);
-
-	return cmd;
-}
-
-static void
-msn_command_destroy(MsnCommand *cmd)
-{
-	g_free(cmd->payload);
-	g_free(cmd->command);
-	g_strfreev(cmd->params);
-	g_free(cmd);
-}
-
-MsnCommand *
-msn_command_ref(MsnCommand *cmd)
-{
-	g_return_val_if_fail(cmd != NULL, NULL);
-
-	cmd->ref_count++;
-	return cmd;
-}
-
-void
-msn_command_unref(MsnCommand *cmd)
-{
-	g_return_if_fail(cmd != NULL);
-	g_return_if_fail(cmd->ref_count > 0);
-
-	cmd->ref_count--;
-
-	if (cmd->ref_count == 0)
-	{
-		msn_command_destroy(cmd);
-	}
-}
-
deleted file mode 100644
--- a/libpurple/protocols/msn/command.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * @file command.h MSN command functions
- *
- * purple
- *
- * Purple 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 MSN_COMMAND_H
-#define MSN_COMMAND_H
-
-typedef struct _MsnCommand MsnCommand;
-
-#include "cmdproc.h"
-#include "transaction.h"
-
-typedef void (*MsnPayloadCb)(MsnCmdProc *cmdproc, MsnCommand *cmd,
-							 char *payload, size_t len);
-
-/**
- * A received command.
- */
-struct _MsnCommand
-{
-	unsigned int trId;
-
-	char *command;
-	char **params;
-	guint param_count;
-
-	guint ref_count;
-
-	MsnTransaction *trans;
-
-	char *payload;
-	size_t payload_len;
-
-	MsnPayloadCb payload_cb;
-	void *payload_cbdata;
-};
-
-/**
- * Create a command object from the incoming string and ref it.
- *
- * @param string 	The incoming string.
- *
- * @return 			A MsnCommand object.
- */
-MsnCommand *msn_command_from_string(const char *string);
-
-/**
- * Increment the ref count.
- *
- * @param cmd 	The MsnCommand to be ref.
- *
- * @return 		The ref command.
- */
-MsnCommand *msn_command_ref(MsnCommand *cmd);
-
-/**
- * Decrement the ref count. If the count goes to 0, destroy it.
- *
- * @param cmd	The MsnCommand to be unref.
- *
- */
-void msn_command_unref(MsnCommand *cmd);
-
-#endif /* MSN_COMMAND_H */
-
deleted file mode 100644
--- a/libpurple/protocols/msn/contact.c
+++ /dev/null
@@ -1,2048 +0,0 @@
-/**
- * @file contact.c
- * 	get MSN contacts via SOAP request
- *	created by MaYuan<mayuan2006@gmail.com>
- *
- * purple
- *
- * Purple 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 02110-1301,  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-
-#include "contact.h"
-#include "xmlnode.h"
-#include "group.h"
-#include "msnutils.h"
-#include "soap.h"
-#include "nexus.h"
-#include "user.h"
-
-const char *MsnSoapPartnerScenarioText[] =
-{
-	"Initial",
-	"ContactSave",
-	"MessengerPendingList",
-	"ContactMsgrAPI",
-	"BlockUnblock",
-	"Timer"
-};
-
-const char *MsnMemberRole[] =
-{
-	"Forward",
-	"Allow",
-	"Block",
-	"Reverse",
-	"Pending"
-};
-
-typedef struct {
-	MsnSession *session;
-	MsnSoapPartnerScenario which;
-} GetContactListCbData;
-
-MsnCallbackState *
-msn_callback_state_new(MsnSession *session)
-{
-	MsnCallbackState *state = g_new0(MsnCallbackState, 1);
-
-	state->session = session;
-
-	return state;
-}
-
-MsnCallbackState *
-msn_callback_state_dup(MsnCallbackState *state)
-{
-	MsnCallbackState *new_state = g_new0(MsnCallbackState, 1);
-
-	new_state->session = state->session;
-	new_state->who = g_strdup(state->who);
-	new_state->uid = g_strdup(state->uid);
-	new_state->old_group_name = g_strdup(state->old_group_name);
-	new_state->new_group_name = g_strdup(state->new_group_name);
-	new_state->guid = g_strdup(state->guid);
-	/* The rest should be made new */
-
-	return new_state;
-}
-
-void
-msn_callback_state_free(MsnCallbackState *state)
-{
-	if (state == NULL)
-		return;
-
-	g_free(state->who);
-	g_free(state->uid);
-	g_free(state->old_group_name);
-	g_free(state->new_group_name);
-	g_free(state->guid);
-	if (state->body)
-		xmlnode_free(state->body);
-
-	g_free(state);
-}
-
-void
-msn_callback_state_set_who(MsnCallbackState *state, const gchar *who)
-{
-	g_return_if_fail(state != NULL);
-
-	g_free(state->who);
-	state->who = g_strdup(who);
-}
-
-void
-msn_callback_state_set_uid(MsnCallbackState *state, const gchar *uid)
-{
-	g_return_if_fail(state != NULL);
-
-	g_free(state->uid);
-	state->uid = g_strdup(uid);
-}
-
-void
-msn_callback_state_set_old_group_name(MsnCallbackState *state, const gchar *old_group_name)
-{
-	g_return_if_fail(state != NULL);
-
-	g_free(state->old_group_name);
-	state->old_group_name = g_strdup(old_group_name);
-}
-
-void
-msn_callback_state_set_new_group_name(MsnCallbackState *state, const gchar *new_group_name)
-{
-	g_return_if_fail(state != NULL);
-
-	g_free(state->new_group_name);
-	state->new_group_name = g_strdup(new_group_name);
-}
-
-void
-msn_callback_state_set_guid(MsnCallbackState *state, const gchar *guid)
-{
-	g_return_if_fail(state != NULL);
-
-	g_free(state->guid);
-	state->guid = g_strdup(guid);
-}
-
-
-void
-msn_callback_state_set_list_id(MsnCallbackState *state, MsnListId list_id)
-{
-	g_return_if_fail(state != NULL);
-
-	state->list_id = list_id;
-}
-
-void
-msn_callback_state_set_action(MsnCallbackState *state, MsnCallbackAction action)
-{
-	g_return_if_fail(state != NULL);
-
-	state->action |= action;
-}
-
-/***************************************************************
- * General SOAP handling
- ***************************************************************/
-
-static const char *
-msn_contact_operation_str(MsnCallbackAction action)
-{
-	/* Make sure this is large enough when adding more */
-	static char buf[BUF_LEN];
-	buf[0] = '\0';
-
-	if (action & MSN_ADD_BUDDY)
-		strcat(buf, "Adding Buddy,");
-	if (action & MSN_MOVE_BUDDY)
-		strcat(buf, "Moving Buddy,");
-	if (action & MSN_ACCEPTED_BUDDY)
-		strcat(buf, "Accepted Buddy,");
-	if (action & MSN_DENIED_BUDDY)
-		strcat(buf, "Denied Buddy,");
-	if (action & MSN_ADD_GROUP)
-		strcat(buf, "Adding Group,");
-	if (action & MSN_DEL_GROUP)
-		strcat(buf, "Deleting Group,");
-	if (action & MSN_RENAME_GROUP)
-		strcat(buf, "Renaming Group,");
-	if (action & MSN_UPDATE_INFO)
-		strcat(buf, "Updating Contact Info,");
-	if (action & MSN_ANNOTATE_USER)
-		strcat(buf, "Annotating Contact,");
-
-	return buf;
-}
-
-static gboolean msn_contact_request(MsnCallbackState *state);
-
-static void
-msn_contact_request_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = data;
-	xmlnode *fault;
-	char *faultcode_str;
-	xmlnode *cachekey;
-	char *changed;
-
-	if (resp == NULL) {
-		purple_debug_error("msn",
-		                   "Operation {%s} failed. No response received from server.\n",
-		                   msn_contact_operation_str(state->action));
-		msn_session_set_error(state->session, MSN_ERROR_BAD_BLIST, NULL);
-		msn_callback_state_free(state);
-		return;
-	}
-
- 	/* Update CacheKey if necessary */
- 	cachekey = xmlnode_get_child(resp->xml, "Header/ServiceHeader/CacheKeyChanged");
- 	if (cachekey != NULL) {
- 		changed = xmlnode_get_data(cachekey);
- 		if (changed && !strcmp(changed, "true")) {
- 			cachekey = xmlnode_get_child(resp->xml, "Header/ServiceHeader/CacheKey");
- 			g_free(state->session->abch_cachekey);
- 			state->session->abch_cachekey = xmlnode_get_data(cachekey);
- 			purple_debug_info("msn", "Updated CacheKey for %s to '%s'.\n",
- 			                  purple_account_get_username(state->session->account),
- 			                  state->session->abch_cachekey);
- 		}
- 		g_free(changed);
- 	}
-
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-
-	if (fault == NULL) {
-		/* No errors */
-		if (state->cb)
-			state->cb(req, resp, data);
-		msn_callback_state_free(state);
-		return;
-	}
-
-	faultcode_str = xmlnode_get_data(xmlnode_get_child(fault, "faultcode"));
-
-	if (faultcode_str && g_str_equal(faultcode_str, "q0:BadContextToken")) {
-		purple_debug_info("msn",
-		                  "Contact Operation {%s} failed because of bad token."
-		                  " Updating token now and retrying operation.\n",
-		                  msn_contact_operation_str(state->action));
-		/* Token has expired, so renew it, and try again later */
-		msn_nexus_update_token(state->session->nexus, MSN_AUTH_CONTACTS,
-		                       (GSourceFunc)msn_contact_request, data);
-	}
-	else
-	{
-		if (state->cb) {
-			state->cb(req, resp, data);
-		} else {
-			/* We don't know how to respond to this faultcode, so log it */
-			char *str = xmlnode_to_str(fault, NULL);
-			purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-			                   msn_contact_operation_str(state->action), str);
-			g_free(str);
-		}
-		msn_callback_state_free(state);
-	}
-
-	g_free(faultcode_str);
-}
-
-static gboolean
-msn_contact_request(MsnCallbackState *state)
-{
-	xmlnode *cachekey = xmlnode_get_child(state->body,
-	                                      "Header/ABApplicationHeader/CacheKey");
-	if (cachekey != NULL)
-		xmlnode_free(cachekey);
-	if (state->session->abch_cachekey != NULL) {
-		cachekey = xmlnode_new_child(xmlnode_get_child(state->body, "Header/ABApplicationHeader"), "CacheKey");
-		xmlnode_insert_data(cachekey, state->session->abch_cachekey, -1);
-	}
-	if (state->token == NULL)
-		state->token = xmlnode_get_child(state->body,
-			"Header/ABAuthHeader/TicketToken");
-	/* delete old & replace with new token */
-	xmlnode_free(state->token->child);
-	xmlnode_insert_data(state->token,
-		msn_nexus_get_token_str(state->session->nexus, MSN_AUTH_CONTACTS), -1);
-	msn_soap_message_send(state->session,
-		msn_soap_message_new(state->post_action, xmlnode_copy(state->body)),
-		MSN_CONTACT_SERVER, state->post_url, FALSE,
-		msn_contact_request_cb, state);
-	return FALSE;
-}
-
-/***************************************************************
- * Address Book and Membership List Operations
- ***************************************************************/
-
-/*get MSN member role utility*/
-static MsnListId
-msn_get_memberrole(const char *role)
-{
-	g_return_val_if_fail(role != NULL, 0);
-
-	if (!strcmp(role,"Allow")) {
-		return MSN_LIST_AL;
-	} else if (!strcmp(role,"Block")) {
-		return MSN_LIST_BL;
-	} else if (!strcmp(role,"Reverse")) {
-		return MSN_LIST_RL;
-	} else if (!strcmp(role,"Pending")) {
-		return MSN_LIST_PL;
-	}
-	return 0;
-}
-
-/* Create the AddressBook in the server, if we don't have one */
-static void
-msn_create_address_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
-{
-	MsnCallbackState *state = data;
-	if (resp && xmlnode_get_child(resp->xml, "Body/Fault") == NULL) {
-		purple_debug_info("msn", "Address Book successfully created!\n");
-		msn_get_address_book(state->session, MSN_PS_INITIAL, NULL, NULL);
-	} else {
-		purple_debug_info("msn", "Address Book creation failed!\n");
-	}
-}
-
-static void
-msn_create_address_book(MsnSession *session)
-{
-	gchar *body;
-	MsnCallbackState *state;
-
-	g_return_if_fail(session != NULL);
-	g_return_if_fail(session->user != NULL);
-	g_return_if_fail(session->user->passport != NULL);
-
-	purple_debug_info("msn", "Creating an Address Book.\n");
-
-	body = g_strdup_printf(MSN_ADD_ADDRESSBOOK_TEMPLATE,
-	                       session->user->passport);
-
-	state = msn_callback_state_new(session);
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_ADD_ADDRESSBOOK_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_create_address_cb;
-	msn_contact_request(state);
-
-	g_free(body);
-}
-
-static void
-msn_parse_each_member(MsnSession *session, xmlnode *member, const char *node,
-	MsnListId list)
-{
-	char *passport;
-	char *type;
-	char *member_id;
-	MsnUser *user;
-	xmlnode *annotation;
-	guint nid = MSN_NETWORK_UNKNOWN;
-	char *invite = NULL;
-
-	passport = xmlnode_get_data(xmlnode_get_child(member, node));
-	if (!msn_email_is_valid(passport)) {
-		g_free(passport);
-		return;
-	}
-
-	type = xmlnode_get_data(xmlnode_get_child(member, "Type"));
-	member_id = xmlnode_get_data(xmlnode_get_child(member, "MembershipId"));
-
-	user = msn_userlist_find_add_user(session->userlist, passport, NULL);
-
-	for (annotation = xmlnode_get_child(member, "Annotations/Annotation");
-	     annotation;
-	     annotation = xmlnode_get_next_twin(annotation)) {
-		char *name = xmlnode_get_data(xmlnode_get_child(annotation, "Name"));
-		char *value = xmlnode_get_data(xmlnode_get_child(annotation, "Value"));
-		if (name && value) {
-			if (!strcmp(name, "MSN.IM.BuddyType")) {
-				nid = strtoul(value, NULL, 10);
-			}
-			else if (!strcmp(name, "MSN.IM.InviteMessage")) {
-				invite = value;
-				value = NULL;
-			}
-		}
-		g_free(name);
-		g_free(value);
-	}
-
-	/* For EmailMembers, the network must be found in the annotations, above.
-	   Otherwise, PassportMembers are on the Passport network. */
-	if (!strcmp(node, "PassportName"))
-		nid = MSN_NETWORK_PASSPORT;
-
-	purple_debug_info("msn", "CL: %s name: %s, Type: %s, MembershipID: %s, NetworkID: %u\n",
-		node, passport, type, member_id == NULL ? "(null)" : member_id, nid);
-
-	msn_user_set_network(user, nid);
-	msn_user_set_invite_message(user, invite);
-
-	if (list == MSN_LIST_PL && member_id) {
-		user->member_id_on_pending_list = atoi(member_id);
-	}
-
-	msn_got_lst_user(session, user, 1 << list, NULL);
-
-	g_free(passport);
-	g_free(type);
-	g_free(member_id);
-	g_free(invite);
-}
-
-static void
-msn_parse_each_service(MsnSession *session, xmlnode *service)
-{
-	xmlnode *type;
-
-	if ((type = xmlnode_get_child(service, "Info/Handle/Type"))) {
-		char *type_str = xmlnode_get_data(type);
-
-		if (g_str_equal(type_str, "Profile")) {
-			/* Process Windows Live 'Messenger Roaming Identity' */
-		} else if (g_str_equal(type_str, "Messenger")) {
-			xmlnode *lastchange = xmlnode_get_child(service, "LastChange");
-			char *lastchange_str = xmlnode_get_data(lastchange);
-			xmlnode *membership;
-
-			purple_debug_info("msn", "CL last change: %s\n", lastchange_str);
-			purple_account_set_string(session->account,	"CLLastChange",
-				lastchange_str);
-
-			for (membership = xmlnode_get_child(service,
-					"Memberships/Membership");
-				 membership; membership = xmlnode_get_next_twin(membership)) {
-
-				xmlnode *role = xmlnode_get_child(membership, "MemberRole");
-				char *role_str = xmlnode_get_data(role);
-				MsnListId list = msn_get_memberrole(role_str);
-				xmlnode *member;
-
-				purple_debug_info("msn", "CL MemberRole role: %s, list: %d\n",
-					role_str, list);
-
-				for (member = xmlnode_get_child(membership, "Members/Member");
-					 member; member = xmlnode_get_next_twin(member)) {
-					const char *member_type = xmlnode_get_attrib(member, "type");
-					if (g_str_equal(member_type, "PassportMember")) {
-						msn_parse_each_member(session, member, "PassportName",
-							list);
-					} else if (g_str_equal(member_type, "PhoneMember")) {
-
-					} else if (g_str_equal(member_type, "EmailMember")) {
-						msn_parse_each_member(session, member, "Email",	list);
-					}
-				}
-
-				g_free(role_str);
-			}
-
-			g_free(lastchange_str);
-		}
-
-		g_free(type_str);
-	}
-}
-
-/*parse contact list*/
-static gboolean
-msn_parse_contact_list(MsnSession *session, xmlnode *node)
-{
-	xmlnode *fault, *faultnode;
-
-	/* we may get a response if our cache data is too old:
-	 *
-	 * <faultstring>Need to do full sync. Can't sync deltas Client
-	 * has too old a copy for us to do a delta sync</faultstring>
-	 *
-	 * this is not handled yet
-	 */
-	if ((fault = xmlnode_get_child(node, "Body/Fault"))) {
-		if ((faultnode = xmlnode_get_child(fault, "detail/errorcode"))) {
-			char *errorcode = xmlnode_get_data(faultnode);
-
-			if (g_str_equal(errorcode, "ABDoesNotExist")) {
-				msn_create_address_book(session);
-				g_free(errorcode);
-				return FALSE;
-			}
-
-			g_free(errorcode);
-		}
-
-		if ((faultnode = xmlnode_get_child(fault, "faultstring"))) {
-			char *faultstring = xmlnode_get_data(faultnode);
-			purple_debug_info("msn", "Retrieving contact list failed: %s\n",
-				faultstring);
-			msn_session_set_error(session, MSN_ERROR_BAD_BLIST, faultstring);
-			g_free(faultstring);
-		} else {
-			msn_session_set_error(session, MSN_ERROR_BAD_BLIST, NULL);
-		}
-		return FALSE;
-	} else {
-		xmlnode *service;
-
-		for (service = xmlnode_get_child(node, "Body/FindMembershipResponse/"
-				"FindMembershipResult/Services/Service");
-			 service; service = xmlnode_get_next_twin(service)) {
-			msn_parse_each_service(session, service);
-		}
-		return TRUE;
-	}
-}
-
-static void
-msn_get_contact_list_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = data;
-	MsnSession *session = state->session;
-
-	g_return_if_fail(session != NULL);
-
-	if (resp != NULL) {
-#ifdef MSN_PARTIAL_LISTS
-		const char *abLastChange;
-		const char *dynamicItemLastChange;
-#endif
-
-		purple_debug_misc("msn", "Got the contact list!\n");
-
-		if (msn_parse_contact_list(session, resp->xml)) {
-#ifdef MSN_PARTIAL_LISTS
-			abLastChange = purple_account_get_string(session->account,
-				"ablastChange", NULL);
-			dynamicItemLastChange = purple_account_get_string(session->account,
-				"DynamicItemLastChanged", NULL);
-#endif
-
-			if (state->partner_scenario == MSN_PS_INITIAL) {
-#ifdef MSN_PARTIAL_LISTS
-				/* XXX: this should be enabled when we can correctly do partial
-				   syncs with the server. Currently we need to retrieve the whole
-				   list to detect sync issues */
-				msn_get_address_book(session, MSN_PS_INITIAL, abLastChange, dynamicItemLastChange);
-#else
-				msn_get_address_book(session, MSN_PS_INITIAL, NULL, NULL);
-#endif
-			}
-		}
-	}
-}
-
-/*SOAP  get contact list*/
-void
-msn_get_contact_list(MsnSession *session,
-	const MsnSoapPartnerScenario partner_scenario, const char *update_time)
-{
-	gchar *body = NULL;
-	gchar *update_str = NULL;
-	MsnCallbackState *state;
-	const gchar *partner_scenario_str = MsnSoapPartnerScenarioText[partner_scenario];
-
-	purple_debug_misc("msn", "Getting Contact List.\n");
-
-	if (update_time != NULL) {
-		purple_debug_info("msn", "CL Last update time: %s\n", update_time);
-		update_str = g_strdup_printf(MSN_GET_CONTACT_UPDATE_XML, update_time);
-	}
-
-	body = g_strdup_printf(MSN_GET_CONTACT_TEMPLATE, partner_scenario_str,
-	                       update_str ? update_str : "");
-
-	state = msn_callback_state_new(session);
-	state->partner_scenario = partner_scenario;
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_GET_CONTACT_SOAP_ACTION;
-	state->post_url = MSN_GET_CONTACT_POST_URL;
-	state->cb = msn_get_contact_list_cb;
-	msn_contact_request(state);
-
-	g_free(update_str);
-	g_free(body);
-}
-
-static void
-msn_parse_addressbook_groups(MsnSession *session, xmlnode *node)
-{
-	xmlnode *group;
-
-	purple_debug_info("msn", "msn_parse_addressbook_groups()\n");
-
-	for(group = xmlnode_get_child(node, "Group"); group;
-					group = xmlnode_get_next_twin(group)){
-		xmlnode *groupId, *groupInfo, *groupname;
-		char *group_id = NULL, *group_name = NULL;
-
-		if ((groupId = xmlnode_get_child(group, "groupId")))
-			group_id = xmlnode_get_data(groupId);
-		if ((groupInfo = xmlnode_get_child(group, "groupInfo")) && (groupname = xmlnode_get_child(groupInfo, "name")))
-			group_name = xmlnode_get_data(groupname);
-
-		if (group_id == NULL) {
-			/* Group of ungroupped buddies */
-			g_free(group_name);
-			continue;
-		}
-
-		msn_group_new(session->userlist, group_id, group_name);
-
-		purple_debug_info("msn", "AB group_id: %s, name: %s\n", group_id, group_name ? group_name : "(null)");
-		if ((purple_find_group(group_name)) == NULL) {
-			PurpleGroup *g = purple_group_new(group_name);
-			purple_blist_add_group(g, NULL);
-		}
-		g_free(group_id);
-		g_free(group_name);
-	}
-}
-
-static gboolean
-msn_parse_addressbook_mobile(xmlnode *contactInfo, char **inout_mobile_number)
-{
-	xmlnode *phones;
-	char *mobile_number = NULL;
-	gboolean mobile = FALSE;
-
-	*inout_mobile_number = NULL;
-
-	if ((phones = xmlnode_get_child(contactInfo, "phones"))) {
-		xmlnode *contact_phone;
-		char *phone_type = NULL;
-
-		for (contact_phone = xmlnode_get_child(phones, "ContactPhone");
-			 contact_phone;
-			 contact_phone = xmlnode_get_next_twin(contact_phone)) {
-			xmlnode *contact_phone_type;
-
-			if (!(contact_phone_type =
-					xmlnode_get_child(contact_phone, "contactPhoneType")))
-				continue;
-
-			phone_type = xmlnode_get_data(contact_phone_type);
-
-			if (phone_type && !strcmp(phone_type, "ContactPhoneMobile")) {
-				xmlnode *number;
-
-				if ((number = xmlnode_get_child(contact_phone, "number"))) {
-					xmlnode *messenger_enabled;
-					char *is_messenger_enabled = NULL;
-
-					g_free(mobile_number);
-					mobile_number = xmlnode_get_data(number);
-
-					if (mobile_number &&
-							(messenger_enabled = xmlnode_get_child(contact_phone, "isMessengerEnabled"))
-							&& (is_messenger_enabled = xmlnode_get_data(messenger_enabled))
-							&& !strcmp(is_messenger_enabled, "true"))
-						mobile = TRUE;
-
-					g_free(is_messenger_enabled);
-				}
-			}
-
-			g_free(phone_type);
-		}
-	}
-
-	*inout_mobile_number = mobile_number;
-	return mobile;
-}
-
-static void
-msn_parse_addressbook_contacts(MsnSession *session, xmlnode *node)
-{
-	xmlnode *contactNode;
-	char *passport = NULL, *Name = NULL, *uid = NULL, *type = NULL, *mobile_number = NULL, *alias = NULL;
-	gboolean mobile = FALSE;
-	PurpleConnection *pc = purple_account_get_connection(session->account);
-
-	for(contactNode = xmlnode_get_child(node, "Contact"); contactNode;
-				contactNode = xmlnode_get_next_twin(contactNode)) {
-		xmlnode *contactId, *contactInfo, *contactType, *passportName, *displayName, *guid, *groupIds;
-		xmlnode *annotation;
-		MsnUser *user;
-
-		g_free(passport);
-		g_free(Name);
-		g_free(uid);
-		g_free(type);
-		g_free(mobile_number);
-		g_free(alias);
-		passport = Name = uid = type = mobile_number = alias = NULL;
-		mobile = FALSE;
-
-		if (!(contactId = xmlnode_get_child(contactNode,"contactId"))
-				|| !(contactInfo = xmlnode_get_child(contactNode, "contactInfo"))
-				|| !(contactType = xmlnode_get_child(contactInfo, "contactType")))
-			continue;
-
-		uid = xmlnode_get_data(contactId);
-		type = xmlnode_get_data(contactType);
-
-		/* Find out our settings */
-		if (type && !strcmp(type, "Me")) {
-			/* setup the Display Name */
-			if (purple_connection_get_display_name(pc) == NULL) {
-				char *friendly = NULL;
-				if ((displayName = xmlnode_get_child(contactInfo, "displayName")))
-					friendly = xmlnode_get_data(displayName);
-				purple_connection_set_display_name(pc,
-					friendly ? purple_url_decode(friendly) : NULL);
-				g_free(friendly);
-			}
-
-			for (annotation = xmlnode_get_child(contactInfo, "annotations/Annotation");
-			     annotation;
-			     annotation = xmlnode_get_next_twin(annotation)) {
-				char *name, *value;
-				name = xmlnode_get_data(xmlnode_get_child(annotation, "Name"));
-				value = xmlnode_get_data(xmlnode_get_child(annotation, "Value"));
-				if (name && g_str_equal(name, "MSN.IM.MPOP")) {
-					if (!value || atoi(value) != 0)
-						session->enable_mpop = TRUE;
-					else
-						session->enable_mpop = FALSE;
-				}
-				g_free(name);
-				g_free(value);
-			}
-
-			continue; /* Not adding own account as buddy to buddylist */
-		}
-
-		passportName = xmlnode_get_child(contactInfo, "passportName");
-		if (passportName == NULL) {
-			xmlnode *emailsNode, *contactEmailNode, *emailNode;
-			xmlnode *messengerEnabledNode;
-			char *msnEnabled;
-
-			/*TODO: add it to the non-instant Messenger group and recognize as email Membership*/
-			/* Yahoo/Federated User? */
-			emailsNode = xmlnode_get_child(contactInfo, "emails");
-			if (emailsNode == NULL) {
-				/*TODO:  need to support the Mobile type*/
-				continue;
-			}
-			for (contactEmailNode = xmlnode_get_child(emailsNode, "ContactEmail");
-			     contactEmailNode;
-			     contactEmailNode = xmlnode_get_next_twin(contactEmailNode)) {
-				if ((messengerEnabledNode = xmlnode_get_child(contactEmailNode, "isMessengerEnabled"))) {
-
-					msnEnabled = xmlnode_get_data(messengerEnabledNode);
-
-					if (msnEnabled && !strcmp(msnEnabled, "true")) {
-						if ((emailNode = xmlnode_get_child(contactEmailNode, "email")))
-							passport = xmlnode_get_data(emailNode);
-
-						/* Messenger enabled, Get the Passport*/
-						purple_debug_info("msn", "AB Yahoo/Federated User %s\n", passport ? passport : "(null)");
-						g_free(msnEnabled);
-						break;
-					}
-
-					g_free(msnEnabled);
-				}
-			}
-		} 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);
-		}
-
-		/* Couldn't find anything */
-		if (passport == NULL)
-			continue;
-
-		if (!msn_email_is_valid(passport))
-			continue;
-
-		if ((displayName = xmlnode_get_child(contactInfo, "displayName")))
-			Name = xmlnode_get_data(displayName);
-		else
-			Name = g_strdup(passport);
-
-		for (annotation = xmlnode_get_child(contactInfo, "annotations/Annotation");
-		     annotation;
-		     annotation = xmlnode_get_next_twin(annotation)) {
-			char *name;
-			name = xmlnode_get_data(xmlnode_get_child(annotation, "Name"));
-			if (!name)
-				continue;
-			if (!strcmp(name, "AB.NickName"))
-				alias = xmlnode_get_data(xmlnode_get_child(annotation, "Value"));
-			else if (!strcmp(name, "MSN.IM.HasSharedFolder"))
-				; /* Do nothing yet... */
-			else if (!strcmp(name, "AB.Spouse"))
-				; /* Do nothing yet... */
-			else if (!strcmp(name, "MSN.Mobile.ContactId"))
-				; /* Do nothing yet... */
-			else
-				purple_debug_info("msn",
-				                  "Unknown AB contact annotation: %s\n", name);
-			g_free(name);
-		}
-
-		mobile = msn_parse_addressbook_mobile(contactInfo, &mobile_number);
-
-		purple_debug_misc("msn", "AB passport:{%s} uid:{%s} display:{%s} alias: {%s} mobile:{%s} mobile number:{%s}\n",
-			passport, uid ? uid : "(null)", Name ? Name : "(null)", alias ? alias : "(null)",
-			mobile ? "true" : "false", mobile_number ? mobile_number : "(null)");
-
-		user = msn_userlist_find_add_user(session->userlist, passport, Name);
-		msn_user_set_uid(user, uid);
-		msn_user_set_mobile_phone(user, mobile_number);
-
-		groupIds = xmlnode_get_child(contactInfo, "groupIds");
-		if (groupIds) {
-			for (guid = xmlnode_get_child(groupIds, "guid"); guid;
-							guid = xmlnode_get_next_twin(guid)) {
-				char *group_id = xmlnode_get_data(guid);
-				msn_user_add_group_id(user, group_id);
-				purple_debug_misc("msn", "AB guid:%s\n", group_id ? group_id : "(null)");
-				g_free(group_id);
-			}
-		} else {
-			purple_debug_info("msn", "User not in any groups, adding to default group.\n");
-			/*not in any group,Then set default group*/
-			msn_user_add_group_id(user, MSN_INDIVIDUALS_GROUP_ID);
-		}
-
-		msn_got_lst_user(session, user, MSN_LIST_FL_OP, NULL);
-
-		if (mobile && user)
-		{
-			user->mobile = TRUE;
-			purple_prpl_got_user_status(session->account, user->passport, "mobile", NULL);
-			purple_prpl_got_user_status(session->account, user->passport, "available", NULL);
-		}
-		if (alias)
-			purple_serv_got_private_alias(pc, passport, alias);
-	}
-
-	g_free(passport);
-	g_free(Name);
-	g_free(uid);
-	g_free(type);
-	g_free(mobile_number);
-	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)
-{
-	xmlnode *result;
-	xmlnode *groups;
-	xmlnode *contacts;
-	xmlnode *abNode;
-	xmlnode *circleNode;
-	xmlnode *fault;
-
-	if ((fault = xmlnode_get_child(node, "Body/Fault"))) {
-		xmlnode *faultnode;
-
-		if ((faultnode = xmlnode_get_child(fault, "faultstring"))) {
-			gchar *faultstring = xmlnode_get_data(faultnode);
-			purple_debug_info("msn", "AB Faultstring: %s\n", faultstring);
-			g_free(faultstring);
-		}
-
-		if ((faultnode = xmlnode_get_child(fault, "detail/errorcode"))) {
-			gchar *errorcode = xmlnode_get_data(faultnode);
-
-			purple_debug_info("msn", "AB Error Code: %s\n", errorcode);
-
-			if (g_str_equal(errorcode, "ABDoesNotExist")) {
-				g_free(errorcode);
-				return TRUE;
-			}
-			g_free(errorcode);
-		}
-
-		return FALSE;
-	}
-
-	result = xmlnode_get_child(node, "Body/ABFindContactsPagedResponse/ABFindContactsPagedResult");
-	if (result == NULL) {
-		purple_debug_misc("msn", "Received no address book update\n");
-		return TRUE;
-	}
-
-	/* 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");
-	if (groups != NULL) {
-		msn_parse_addressbook_groups(session, groups);
-	}
-
-	/* Add an "Other Contacts" group for buddies who aren't in a group */
-	msn_group_new(session->userlist, MSN_INDIVIDUALS_GROUP_ID,
-				  MSN_INDIVIDUALS_GROUP_NAME);
-	purple_debug_misc("msn", "AB group_id:%s name:%s\n",
-					  MSN_INDIVIDUALS_GROUP_ID, MSN_INDIVIDUALS_GROUP_NAME);
-	if ((purple_find_group(MSN_INDIVIDUALS_GROUP_NAME)) == NULL){
-		PurpleGroup *g = purple_group_new(MSN_INDIVIDUALS_GROUP_NAME);
-		purple_blist_add_group(g, NULL);
-	}
-
-	/* Add a "Non-IM Contacts" group */
-	msn_group_new(session->userlist, MSN_NON_IM_GROUP_ID, MSN_NON_IM_GROUP_NAME);
-	purple_debug_misc("msn", "AB group_id:%s name:%s\n", MSN_NON_IM_GROUP_ID, MSN_NON_IM_GROUP_NAME);
-	if ((purple_find_group(MSN_NON_IM_GROUP_NAME)) == NULL) {
-		PurpleGroup *g = purple_group_new(MSN_NON_IM_GROUP_NAME);
-		purple_blist_add_group(g, NULL);
-	}
-
-	/*Process contact List*/
-	purple_debug_info("msn", "Process contact list...\n");
-	contacts = xmlnode_get_child(result, "Contacts");
-	if (contacts != NULL) {
-		msn_parse_addressbook_contacts(session, contacts);
-	}
-
-	abNode = xmlnode_get_child(result, "Ab");
-	if (abNode != NULL) {
-		xmlnode *node2;
-		char *tmp = NULL;
-
-		if ((node2 = xmlnode_get_child(abNode, "lastChange")))
-			tmp = xmlnode_get_data(node2);
-		purple_debug_info("msn", "AB lastchanged Time:{%s}\n", tmp ? tmp : "(null)");
-		purple_account_set_string(session->account, "ablastChange", tmp);
-
-		g_free(tmp); tmp = NULL;
-		if ((node2 = xmlnode_get_child(abNode, "DynamicItemLastChanged")))
-			tmp = xmlnode_get_data(node2);
-		purple_debug_info("msn", "AB DynamicItemLastChanged :{%s}\n", tmp ? tmp : "(null)");
-		purple_account_set_string(session->account, "DynamicItemLastChanged", tmp);
-		g_free(tmp);
-	}
-
-	circleNode = xmlnode_get_child(result, "CircleResult");
-	if (circleNode != NULL) {
-		msn_parse_addressbook_circles(session, circleNode);
-	}
-
-	return TRUE;
-}
-
-static void
-msn_get_address_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
-{
-	MsnCallbackState *state = data;
-	MsnSession *session = state->session;
-
-	g_return_if_fail(session != NULL);
-
-	purple_debug_misc("msn", "Got the Address Book!\n");
-
-	if (msn_parse_addressbook(session, resp->xml)) {
-		msn_send_privacy(session->account->gc);
-		msn_notification_dump_contact(session);
-	} else {
-		/* This is making us loop infinitely when we fail to parse the
-		  address book, disable for now (we should re-enable when we
-		  send timestamps)
-		*/
-		/*
-		msn_get_address_book(session, NULL, NULL);
-		*/
-		msn_session_set_error(session, MSN_ERROR_BAD_BLIST, NULL);
-	}
-}
-
-/*get the address book*/
-void
-msn_get_address_book(MsnSession *session,
-	MsnSoapPartnerScenario partner_scenario, const char *LastChanged,
-	const char *dynamicItemLastChange)
-{
-	char *body, *update_str = NULL;
-	MsnCallbackState *state;
-
-	purple_debug_misc("msn", "Getting Address Book\n");
-
-	/*build SOAP and POST it*/
-	if (dynamicItemLastChange != NULL)
-		update_str = g_strdup_printf(MSN_GET_ADDRESS_UPDATE_XML, dynamicItemLastChange);
-	else if (LastChanged != NULL)
-		update_str = g_strdup_printf(MSN_GET_ADDRESS_UPDATE_XML, LastChanged);
-
-	body = g_strdup_printf(MSN_GET_ADDRESS_TEMPLATE,
-		MsnSoapPartnerScenarioText[partner_scenario],
-		update_str ? update_str : "");
-
-	state = msn_callback_state_new(session);
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_GET_ADDRESS_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_get_address_cb;
-	msn_contact_request(state);
-
-	g_free(update_str);
-	g_free(body);
-}
-
-/***************************************************************
- * Contact Operations
- ***************************************************************/
-
-static void
-msn_add_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = data;
-	MsnSession *session = state->session;
-
-	MsnUserList *userlist;
-	MsnUser *user;
-	xmlnode *guid;
-
-	xmlnode *fault;
-
-	g_return_if_fail(session != NULL);
-	userlist = session->userlist;
-
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-	if (fault != NULL) {
-		char *errorcode = xmlnode_get_data(xmlnode_get_child(fault, "detail/errorcode"));
-		if (errorcode && !strcmp(errorcode, "EmailDomainIsFederated")) {
-			/* Do something special! */
-			purple_debug_error("msn", "Contact is from a federated domain, but don't know what to do yet!\n");
-
-		} else if (errorcode && !strcmp(errorcode, "InvalidPassportUser")) {
-			PurpleBuddy *buddy = purple_find_buddy(session->account, state->who);
-			char *str = g_strdup_printf(_("Unable to add \"%s\"."), state->who);
-			purple_notify_error(state->session, _("Buddy Add error"), str,
-			                    _("The username specified does not exist."));
-			g_free(str);
-			msn_userlist_rem_buddy(userlist, state->who);
-			if (buddy != NULL)
-				purple_blist_remove_buddy(buddy);
-
-		} else {
-			/* We don't know how to respond to this faultcode, so log it */
-			char *fault_str = xmlnode_to_str(fault, NULL);
-			if (fault_str != NULL) {
-				purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-				                   msn_contact_operation_str(state->action), fault_str);
-				g_free(fault_str);
-			}
-		}
-		return;
-	}
-
-	purple_debug_info("msn", "Contact added successfully\n");
-
-	msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_AL);
-	msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_FL);
-
-	user = msn_userlist_find_add_user(userlist, state->who, state->who);
-	msn_user_add_group_id(user, state->guid);
-
-	guid = xmlnode_get_child(resp->xml,
-		"Body/ABContactAddResponse/ABContactAddResult/guid");
-	if (guid != NULL) {
-		char *uid = xmlnode_get_data(guid);
-		msn_user_set_uid(user, uid);
-		purple_debug_info("msn", "Set %s guid to %s.\n", state->who, uid);
-		g_free(uid);
-	}
-}
-
-/* add a Contact in MSN_INDIVIDUALS_GROUP */
-void
-msn_add_contact(MsnSession *session, MsnCallbackState *state, const char *passport)
-{
-	MsnUser *user;
-	gchar *body = NULL;
-	gchar *contact_xml = NULL;
-
-	purple_debug_info("msn", "Adding contact %s to contact list\n", passport);
-
-	user = msn_userlist_find_user(session->userlist, passport);
-	if (user == NULL) {
-		purple_debug_warning("msn", "Unable to retrieve user %s from the userlist!\n", passport);
-		return; /* guess this never happened! */
-	}
-
-	if (user->networkid != MSN_NETWORK_PASSPORT) {
-		contact_xml = g_strdup_printf(MSN_CONTACT_EMAIL_XML,
-		                              user->networkid == MSN_NETWORK_YAHOO ?
-		                                  "Messenger2" :
-		                                  "Messenger3",
-		                              passport, 0);
-	} else {
-		contact_xml = g_strdup_printf(MSN_CONTACT_XML, passport);
-	}
-	body = g_strdup_printf(MSN_ADD_CONTACT_TEMPLATE, contact_xml);
-
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_CONTACT_ADD_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_add_contact_read_cb;
-	msn_contact_request(state);
-
-	g_free(contact_xml);
-	g_free(body);
-}
-
-static void
-msn_add_contact_to_group_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = data;
-	MsnSession *session = state->session;
-	MsnUserList *userlist;
-	xmlnode *fault;
-
-	g_return_if_fail(session != NULL);
-	userlist = session->userlist;
-
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-	if (fault != NULL) {
-		char *errorcode = xmlnode_get_data(xmlnode_get_child(fault, "detail/errorcode"));
-		if (errorcode && !strcmp(errorcode, "EmailDomainIsFederated")) {
-			/* Do something special! */
-			purple_debug_error("msn", "Contact is from a federated domain, but don't know what to do yet!\n");
-
-		} else if (errorcode && !strcmp(errorcode, "InvalidPassportUser")) {
-			PurpleBuddy *buddy = purple_find_buddy(session->account, state->who);
-			char *str = g_strdup_printf(_("Unable to add \"%s\"."), state->who);
-			purple_notify_error(session, _("Buddy Add error"), str,
-			                    _("The username specified does not exist."));
-			g_free(str);
-			msn_userlist_rem_buddy(userlist, state->who);
-			if (buddy != NULL)
-				purple_blist_remove_buddy(buddy);
-
-		} else {
-			/* We don't know how to respond to this faultcode, so log it */
-			char *fault_str = xmlnode_to_str(fault, NULL);
-			if (fault_str != NULL) {
-				purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-				                   msn_contact_operation_str(state->action), fault_str);
-				g_free(fault_str);
-			}
-		}
-		return;
-	}
-
-	if (msn_userlist_add_buddy_to_group(userlist, state->who,
-			state->new_group_name)) {
-		purple_debug_info("msn", "Contact %s added to group %s successfully!\n", state->who, state->new_group_name);
-	} else {
-		purple_debug_info("msn", "Contact %s added to group %s successfully on server, but failed in the local list\n", state->who, state->new_group_name);
-	}
-
-	if (state->action & MSN_ADD_BUDDY) {
-		MsnUser *user = msn_userlist_find_user(userlist, state->who);
-		xmlnode *guid = xmlnode_get_child(resp->xml,
-			"Body/ABGroupContactAddResponse/ABGroupContactAddResult/guid");
-
-		if (guid != NULL) {
-			char *uid = xmlnode_get_data(guid);
-			msn_user_set_uid(user, uid);
-			purple_debug_info("msn", "Set %s guid to %s.\n", state->who, uid);
-			g_free(uid);
-		}
-
-		msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_AL);
-		msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_FL);
-
-		if (msn_user_is_in_list(user, MSN_LIST_PL)) {
-			msn_del_contact_from_list(state->session, NULL, state->who, MSN_LIST_PL);
-			return;
-		}
-	}
-
-	if (state->action & MSN_MOVE_BUDDY) {
-		msn_del_contact_from_group(state->session, state->who, state->old_group_name);
-	}
-}
-
-void
-msn_add_contact_to_group(MsnSession *session, MsnCallbackState *state,
-			 const char *passport, const char *groupId)
-{
-	MsnUserList *userlist;
-	MsnUser *user;
-	gchar *body = NULL, *contact_xml, *invite;
-
-	g_return_if_fail(passport != NULL);
-	g_return_if_fail(groupId != NULL);
-
-	g_return_if_fail(session != NULL);
-
-	userlist = session->userlist;
-
-	if (!strcmp(groupId, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(groupId, MSN_NON_IM_GROUP_ID)) {
-
-		user = msn_userlist_find_add_user(userlist, passport, passport);
-
-		if (state->action & MSN_ADD_BUDDY) {
-			msn_add_contact(session, state, passport);
-			return;
-		}
-
-		if (state->action & MSN_MOVE_BUDDY) {
-			msn_user_add_group_id(user, groupId);
-			msn_del_contact_from_group(session, passport, state->old_group_name);
-		}
-
-		return;
-	}
-
-	purple_debug_info("msn", "Adding user %s to group %s\n", passport,
-			  msn_userlist_find_group_name(userlist, groupId));
-
-	user = msn_userlist_find_user(userlist, passport);
-	if (user == NULL) {
-		purple_debug_warning("msn", "Unable to retrieve user %s from the userlist!\n", passport);
-		msn_callback_state_free(state);
-		return; /* guess this never happened! */
-	}
-
-	if (user->uid != NULL) {
-		contact_xml = g_strdup_printf(MSN_CONTACT_ID_XML, user->uid);
-	} else if (user->networkid != MSN_NETWORK_PASSPORT) {
-		contact_xml = g_strdup_printf(MSN_CONTACT_EMAIL_XML,
-		                              user->networkid == MSN_NETWORK_YAHOO ?
-		                                  "Messenger2" :
-		                                  "Messenger3",
-		                              passport, 0);
-	} else {
-		contact_xml = g_strdup_printf(MSN_CONTACT_XML, passport);
-	}
-
-	if (user->invite_message) {
-		char *tmp;
-		body = g_markup_escape_text(user->invite_message, -1);
-
-		/* Ignore the cast, we treat it as const anyway. */
-		tmp = (char *)purple_connection_get_display_name(session->account->gc);
-		tmp = tmp ? g_markup_escape_text(tmp, -1) : g_strdup("");
-
-		invite = g_strdup_printf(MSN_CONTACT_INVITE_MESSAGE_XML, body, tmp);
-
-		g_free(body);
-		g_free(tmp);
-
-		/* We can free this now */
-		g_free(user->invite_message);
-		user->invite_message = NULL;
-
-	} else {
-		invite = g_strdup("");
-	}
-
-	body = g_strdup_printf(MSN_ADD_CONTACT_GROUP_TEMPLATE, groupId, contact_xml, invite);
-
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_ADD_CONTACT_GROUP_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_add_contact_to_group_read_cb;
-	msn_contact_request(state);
-
-	g_free(invite);
-	g_free(contact_xml);
-	g_free(body);
-}
-
-static void
-msn_delete_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = data;
-	MsnUserList *userlist = state->session->userlist;
-	MsnUser *user = msn_userlist_find_user_with_id(userlist, state->uid);
-	xmlnode *fault;
-
-	/* We don't know how to respond to this faultcode, so log it */
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-	if (fault != NULL) {
-		char *fault_str = xmlnode_to_str(fault, NULL);
-		purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-		                   msn_contact_operation_str(state->action), fault_str);
-		g_free(fault_str);
-		return;
-	}
-
-	purple_debug_info("msn", "Delete contact successful\n");
-
-	if (user != NULL) {
-		msn_userlist_remove_user(userlist, user);
-	}
-}
-
-/*delete a Contact*/
-void
-msn_delete_contact(MsnSession *session, MsnUser *user)
-{
-	gchar *body = NULL;
-	gchar *contact_id_xml = NULL ;
-	MsnCallbackState *state;
-
-	if (user->uid != NULL) {
-		contact_id_xml = g_strdup_printf(MSN_CONTACT_ID_XML, user->uid);
-		purple_debug_info("msn", "Deleting contact with contactId: %s\n", user->uid);
-	} else {
-		purple_debug_info("msn", "Unable to delete contact %s without a ContactId\n", user->passport);
-		return;
-	}
-
-	state = msn_callback_state_new(session);
-	msn_callback_state_set_uid(state, user->uid);
-
-	/* build SOAP request */
-	body = g_strdup_printf(MSN_DEL_CONTACT_TEMPLATE, contact_id_xml);
-
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_CONTACT_DEL_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_delete_contact_read_cb;
-	msn_contact_request(state);
-
-	g_free(contact_id_xml);
-	g_free(body);
-}
-
-static void
-msn_del_contact_from_group_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = data;
-	xmlnode *fault;
-
-	/* We don't know how to respond to this faultcode, so log it */
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-	if (fault != NULL) {
-		char *fault_str = xmlnode_to_str(fault, NULL);
-		purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-		                   msn_contact_operation_str(state->action), fault_str);
-		g_free(fault_str);
-		return;
-	}
-
-	if (msn_userlist_rem_buddy_from_group(state->session->userlist,
-			state->who, state->old_group_name)) {
-		purple_debug_info("msn", "Contact %s deleted successfully from group %s\n", state->who, state->old_group_name);
-	} else {
-		purple_debug_info("msn", "Contact %s deleted successfully from group %s in the server, but failed in the local list\n", state->who, state->old_group_name);
-	}
-}
-
-void
-msn_del_contact_from_group(MsnSession *session, const char *passport, const char *group_name)
-{
-	MsnUserList * userlist;
-	MsnUser *user;
-	MsnCallbackState *state;
-	gchar *body, *contact_id_xml;
-	const gchar *groupId;
-
-	g_return_if_fail(passport != NULL);
-	g_return_if_fail(group_name != NULL);
-	g_return_if_fail(session != NULL);
-
-	userlist = session->userlist;
-
-	groupId = msn_userlist_find_group_id(userlist, group_name);
-	if (groupId != NULL) {
-		purple_debug_info("msn", "Deleting user %s from group %s\n", passport, group_name);
-	} else {
-		purple_debug_warning("msn", "Unable to retrieve group id from group %s !\n", group_name);
-		return;
-	}
-
-	user = msn_userlist_find_user(userlist, passport);
-
-	if (user == NULL) {
-		purple_debug_warning("msn", "Unable to retrieve user from passport %s!\n", passport);
-		return;
-	}
-
-	if ( !strcmp(groupId, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(groupId, MSN_NON_IM_GROUP_ID)) {
-		msn_user_remove_group_id(user, groupId);
-		return;
-	}
-
-	state = msn_callback_state_new(session);
-	msn_callback_state_set_who(state, passport);
-	msn_callback_state_set_guid(state, groupId);
-	msn_callback_state_set_old_group_name(state, group_name);
-
-	if (user->uid != NULL)
-		contact_id_xml = g_strdup_printf(MSN_CONTACT_ID_XML, user->uid);
-	else
-		contact_id_xml = g_strdup_printf(MSN_CONTACT_XML, passport);
-	body = g_strdup_printf(MSN_CONTACT_DEL_GROUP_TEMPLATE, contact_id_xml, groupId);
-
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_CONTACT_DEL_GROUP_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_del_contact_from_group_read_cb;
-	msn_contact_request(state);
-
-	g_free(contact_id_xml);
-	g_free(body);
-}
-
-
-static void
-msn_update_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = (MsnCallbackState *)data;
-	xmlnode *fault;
-
-	/* We don't know how to respond to this faultcode, so log it */
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-	if (fault != NULL) {
-		char *fault_str = xmlnode_to_str(fault, NULL);
-		purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-		                   msn_contact_operation_str(state->action), fault_str);
-		g_free(fault_str);
-		return;
-	}
-
-	purple_debug_info("msn", "Contact updated successfully\n");
-}
-
-/* Update a contact's info */
-void
-msn_update_contact(MsnSession *session, const char *passport, MsnContactUpdateType type, const char* value)
-{
-	MsnCallbackState *state;
-	xmlnode *contact;
-	xmlnode *contact_info;
-	xmlnode *changes;
-	MsnUser *user = NULL;
-
-	purple_debug_info("msn", "Update contact information for %s with new %s: %s\n",
-		passport ? passport : "(null)",
-		type == MSN_UPDATE_DISPLAY ? "display name" : "alias",
-		value ? value : "(null)");
-	g_return_if_fail(passport != NULL);
-
-	if (strcmp(passport, "Me") != 0) {
-		user = msn_userlist_find_user(session->userlist, passport);
-		if (!user)
-			return;
-	}
-
-	contact_info = xmlnode_new("contactInfo");
-	changes = xmlnode_new("propertiesChanged");
-
-	switch (type) {
-		xmlnode *annotations;
-		xmlnode *display;
-		xmlnode *a, *n, *v;
-		case MSN_UPDATE_DISPLAY:
-			display = xmlnode_new_child(contact_info, "displayName");
-			xmlnode_insert_data(display, value, -1);
-			xmlnode_insert_data(changes, "DisplayName", -1);
-			break;
-
-		case MSN_UPDATE_ALIAS:
-			annotations = xmlnode_new_child(contact_info, "annotations");
-			xmlnode_insert_data(changes, "Annotation ", -1);
-
-			a = xmlnode_new_child(annotations, "Annotation");
-			n = xmlnode_new_child(a, "Name");
-			xmlnode_insert_data(n, "AB.NickName", -1);
-			v = xmlnode_new_child(a, "Value");
-			xmlnode_insert_data(v, value, -1);
-			break;
-
-		default:
-			g_return_if_reached();
-	}
-
-	state = msn_callback_state_new(session);
-
-	state->body = xmlnode_from_str(MSN_CONTACT_UPDATE_TEMPLATE, -1);
-	state->action = MSN_UPDATE_INFO;
-	state->post_action = MSN_CONTACT_UPDATE_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_update_contact_read_cb;
-
-	contact = xmlnode_get_child(state->body, "Body/ABContactUpdate/contacts/Contact");
-	xmlnode_insert_child(contact, contact_info);
-	xmlnode_insert_child(contact, changes);
-
-	xmlnode_insert_data(xmlnode_get_child(state->body,
-	                                      "Header/ABApplicationHeader/PartnerScenario"),
-	                    MsnSoapPartnerScenarioText[MSN_PS_SAVE_CONTACT], -1);
-
-	if (user) {
-		xmlnode *contactId = xmlnode_new_child(contact, "contactId");
-		msn_callback_state_set_uid(state, user->uid);
-		xmlnode_insert_data(contactId, state->uid, -1);
-	} else {
-		xmlnode *contactType = xmlnode_new_child(contact_info, "contactType");
-		xmlnode_insert_data(contactType, "Me", -1);
-	}
-
-	msn_contact_request(state);
-}
-
-static void
-msn_annotate_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = (MsnCallbackState *)data;
-	xmlnode *fault;
-
-	/* We don't know how to respond to this faultcode, so log it */
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-	if (fault != NULL) {
-		char *fault_str = xmlnode_to_str(fault, NULL);
-		purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-		                   msn_contact_operation_str(state->action), fault_str);
-		g_free(fault_str);
-		return;
-	}
-
-	purple_debug_info("msn", "Contact annotated successfully\n");
-}
-
-/* Update a contact's annotations */
-void
-msn_annotate_contact(MsnSession *session, const char *passport, ...)
-{
-	va_list params;
-	MsnCallbackState *state;
-	xmlnode *contact;
-	xmlnode *contact_info;
-	xmlnode *annotations;
-	MsnUser *user = NULL;
-
-	g_return_if_fail(passport != NULL);
-
-	if (strcmp(passport, "Me") != 0) {
-		user = msn_userlist_find_user(session->userlist, passport);
-		if (!user)
-			return;
-	}
-
-	contact_info = xmlnode_new("contactInfo");
-	annotations = xmlnode_new_child(contact_info, "annotations");
-
-	va_start(params, passport);
-	while (TRUE) {
-		const char *name;
-		const char *value;
-		xmlnode *a, *n, *v;
-
-		name = va_arg(params, const char *);
-		if (!name)
-			break;
-
-		value = va_arg(params, const char *);
-		if (!value)
-			break;
-
-		a = xmlnode_new_child(annotations, "Annotation");
-		n = xmlnode_new_child(a, "Name");
-		xmlnode_insert_data(n, name, -1);
-		v = xmlnode_new_child(a, "Value");
-		xmlnode_insert_data(v, value, -1);
-	}
-	va_end(params);
-
-	state = msn_callback_state_new(session);
-
-	state->body = xmlnode_from_str(MSN_CONTACT_ANNOTATE_TEMPLATE, -1);
-	state->action = MSN_ANNOTATE_USER;
-	state->post_action = MSN_CONTACT_ANNOTATE_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_annotate_contact_read_cb;
-
-	xmlnode_insert_data(xmlnode_get_child(state->body,
-	                                      "Header/ABApplicationHeader/PartnerScenario"),
-	                    MsnSoapPartnerScenarioText[MSN_PS_SAVE_CONTACT], -1);
-
-	contact = xmlnode_get_child(state->body, "Body/ABContactUpdate/contacts/Contact");
-	xmlnode_insert_child(contact, contact_info);
-
-	if (user) {
-		xmlnode *contactId = xmlnode_new_child(contact, "contactId");
-		msn_callback_state_set_uid(state, user->uid);
-		xmlnode_insert_data(contactId, state->uid, -1);
-	} else {
-		xmlnode *contactType = xmlnode_new_child(contact_info, "contactType");
-		xmlnode_insert_data(contactType, "Me", -1);
-	}
-
-	msn_contact_request(state);
-}
-
-static void
-msn_del_contact_from_list_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = data;
-	MsnSession *session = state->session;
-	xmlnode *fault;
-
-	/* We don't know how to respond to this faultcode, so log it */
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-	if (fault != NULL) {
-		char *fault_str = xmlnode_to_str(fault, NULL);
-		purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-		                   msn_contact_operation_str(state->action), fault_str);
-		g_free(fault_str);
-		return;
-	}
-
-	purple_debug_info("msn", "Contact %s deleted successfully from %s list on server!\n", state->who, MsnMemberRole[state->list_id]);
-
-	if (state->list_id == MSN_LIST_PL) {
-		MsnUser *user = msn_userlist_find_user(session->userlist, state->who);
-		MsnCallbackState *new_state = msn_callback_state_dup(state);
-
-		if (user != NULL)
-			msn_user_unset_op(user, MSN_LIST_PL_OP);
-
-		msn_add_contact_to_list(session, new_state, state->who, MSN_LIST_RL);
-		return;
-	} else if (state->list_id == MSN_LIST_AL) {
-		purple_privacy_permit_remove(session->account, state->who, TRUE);
-		msn_add_contact_to_list(session, NULL, state->who, MSN_LIST_BL);
-	} else if (state->list_id == MSN_LIST_BL) {
-		purple_privacy_deny_remove(session->account, state->who, TRUE);
-		msn_add_contact_to_list(session, NULL, state->who, MSN_LIST_AL);
-	}
-
-}
-
-void
-msn_del_contact_from_list(MsnSession *session, MsnCallbackState *state,
-			  const gchar *passport, const MsnListId list)
-{
-	gchar *body = NULL, *member = NULL;
-	MsnSoapPartnerScenario partner_scenario;
-	MsnUser *user;
-
-	g_return_if_fail(session != NULL);
-	g_return_if_fail(session->userlist != NULL);
-	g_return_if_fail(passport != NULL);
-	g_return_if_fail(list < 5);
-
-	purple_debug_info("msn", "Deleting contact %s from %s list\n", passport, MsnMemberRole[list]);
-
-	if (state == NULL) {
-		state = msn_callback_state_new(session);
-	}
-	msn_callback_state_set_list_id(state, list);
-	msn_callback_state_set_who(state, passport);
-
-	user = msn_userlist_find_user(session->userlist, passport);
-	g_return_if_fail(user != NULL);
-
-	if (list == MSN_LIST_PL) {
-		partner_scenario = MSN_PS_CONTACT_API;
-		if (user->networkid != MSN_NETWORK_PASSPORT)
-			member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML,
-			                         "EmailMember", "Email",
-			                         user->member_id_on_pending_list);
-		else
-			member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML,
-			                         "PassportMember", "Passport",
-			                         user->member_id_on_pending_list);
-	} else {
-		/* list == MSN_LIST_AL || list == MSN_LIST_BL */
-		partner_scenario = MSN_PS_BLOCK_UNBLOCK;
-		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,
-		MsnSoapPartnerScenarioText[partner_scenario],
-		MsnMemberRole[list], member);
-
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_DELETE_MEMBER_FROM_LIST_SOAP_ACTION;
-	state->post_url = MSN_SHARE_POST_URL;
-	state->cb = msn_del_contact_from_list_read_cb;
-	msn_contact_request(state);
-
-	g_free(member);
-	g_free(body);
-}
-
-static void
-msn_add_contact_to_list_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = data;
-	xmlnode *fault;
-
-	/* We don't know how to respond to this faultcode, so log it */
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-	if (fault != NULL) {
-		char *fault_str = xmlnode_to_str(fault, NULL);
-		purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-		                   msn_contact_operation_str(state->action), fault_str);
-		g_free(fault_str);
-		return;
-	}
-
-	g_return_if_fail(state->session != NULL);
-
-	purple_debug_info("msn", "Contact %s added successfully to %s list on server!\n", state->who, MsnMemberRole[state->list_id]);
-
-	if (state->list_id == MSN_LIST_RL) {
-		MsnUser *user = msn_userlist_find_user(state->session->userlist, state->who);
-
-		if (user != NULL) {
-			msn_user_set_op(user, MSN_LIST_RL_OP);
-		}
-
-		if (state->action & MSN_DENIED_BUDDY) {
-			msn_add_contact_to_list(state->session, NULL, state->who, MSN_LIST_BL);
-		} else if (state->list_id == MSN_LIST_AL) {
-			purple_privacy_permit_add(state->session->account, state->who, TRUE);
-		} else if (state->list_id == MSN_LIST_BL) {
-			purple_privacy_deny_add(state->session->account, state->who, TRUE);
-		}
-	}
-}
-
-void
-msn_add_contact_to_list(MsnSession *session, MsnCallbackState *state,
-			const gchar *passport, const MsnListId list)
-{
-	gchar *body = NULL, *member = NULL;
-	MsnSoapPartnerScenario partner_scenario;
-	MsnUser *user;
-
-	g_return_if_fail(session != NULL);
-	g_return_if_fail(passport != NULL);
-	g_return_if_fail(list < 5);
-
-	purple_debug_info("msn", "Adding contact %s to %s list\n", passport, MsnMemberRole[list]);
-
-	if (state == NULL) {
-		state = msn_callback_state_new(session);
-	}
-	msn_callback_state_set_list_id(state, list);
-	msn_callback_state_set_who(state, passport);
-
-	user = msn_userlist_find_user(session->userlist, passport);
-
-	partner_scenario = (list == MSN_LIST_RL) ? MSN_PS_CONTACT_API : MSN_PS_BLOCK_UNBLOCK;
-	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],
-		MsnMemberRole[list], member);
-
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_ADD_MEMBER_TO_LIST_SOAP_ACTION;
-	state->post_url = MSN_SHARE_POST_URL;
-	state->cb = msn_add_contact_to_list_read_cb;
-	msn_contact_request(state);
-
-	g_free(member);
-	g_free(body);
-}
-
-#if 0
-static void
-msn_gleams_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
-{
-	purple_debug_info("msn", "Gleams read done\n");
-}
-
-/*get the gleams info*/
-void
-msn_get_gleams(MsnSession *session)
-{
-	MsnSoapReq *soap_request;
-
-	purple_debug_info("msn", "msn get gleams info...\n");
-
-	state = msn_callback_state_new(session);
-	state->body = xmlnode_from_str(MSN_GLEAMS_TEMPLATE, -1);
-	state->post_action = MSN_GET_GLEAMS_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_gleams_read_cb;
-	msn_contact_request(state);
-}
-#endif
-
-
-/***************************************************************
- * Group Operations
- ***************************************************************/
-
-static void
-msn_group_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
-{
-	MsnCallbackState *state = data;
-	MsnSession *session;
-	MsnUserList *userlist;
-	xmlnode *fault;
-
-	/* We don't know how to respond to this faultcode, so log it */
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-	if (fault != NULL) {
-		char *fault_str = xmlnode_to_str(fault, NULL);
-		purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-		                   msn_contact_operation_str(state->action), fault_str);
-		g_free(fault_str);
-		return;
-	}
-
-	purple_debug_info("msn", "Group request successful.\n");
-
-	g_return_if_fail(state->session != NULL);
-	g_return_if_fail(state->session->userlist != NULL);
-
-	session = state->session;
-	userlist = session->userlist;
-
-	if (state->action & MSN_RENAME_GROUP) {
-		msn_userlist_rename_group_id(session->userlist,
-					     state->guid,
-					     state->new_group_name);
-	}
-
-	if (state->action & MSN_ADD_GROUP) {
-		/* the response is taken from
-		   http://telepathy.freedesktop.org/wiki/Pymsn/MSNP/ContactListActions
-		   should copy it to msnpiki some day */
-		xmlnode *guid_node = xmlnode_get_child(resp->xml,
-			"Body/ABGroupAddResponse/ABGroupAddResult/guid");
-
-		if (guid_node) {
-			char *guid = xmlnode_get_data(guid_node);
-
-			/* create and add the new group to the userlist */
-			purple_debug_info("msn", "Adding group %s with guid = %s to the userlist\n", state->new_group_name, guid);
-			msn_group_new(session->userlist, guid, state->new_group_name);
-
-			if (state->action & MSN_ADD_BUDDY) {
-				msn_userlist_add_buddy(session->userlist,
-					state->who,
-					state->new_group_name);
-			} else if (state->action & MSN_MOVE_BUDDY) {
-				/* This will be freed when the add contact callback fires */
-				MsnCallbackState *new_state = msn_callback_state_dup(state);
-				msn_add_contact_to_group(session, new_state, state->who, guid);
-				g_free(guid);
-				return;
-			}
-			g_free(guid);
-		} else {
-			purple_debug_info("msn", "Adding group %s failed\n",
-				state->new_group_name);
-		}
-	}
-
-	if (state->action & MSN_DEL_GROUP) {
-		GList *l;
-
-		msn_userlist_remove_group_id(session->userlist, state->guid);
-		for (l = userlist->users; l != NULL; l = l->next) {
-			msn_user_remove_group_id( (MsnUser *)l->data, state->guid);
-		}
-	}
-}
-
-/* add group */
-void
-msn_add_group(MsnSession *session, MsnCallbackState *state, const char* group_name)
-{
-	char *body = NULL;
-	char *escaped_group_name = NULL;
-
-	g_return_if_fail(session != NULL);
-	g_return_if_fail(group_name != NULL);
-
-	purple_debug_info("msn", "Adding group %s to contact list.\n", group_name);
-
-	if (state == NULL) {
-		state = msn_callback_state_new(session);
-	}
-
-	msn_callback_state_set_action(state, MSN_ADD_GROUP);
-	msn_callback_state_set_new_group_name(state, group_name);
-
-	/* escape group name's html special chars so it can safely be sent
-	* in a XML SOAP request
-	*/
-	escaped_group_name = g_markup_escape_text(group_name, -1);
-	body = g_strdup_printf(MSN_GROUP_ADD_TEMPLATE, escaped_group_name);
-
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_GROUP_ADD_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_group_read_cb;
-	msn_contact_request(state);
-
-	g_free(escaped_group_name);
-	g_free(body);
-}
-
-/* delete group */
-void
-msn_del_group(MsnSession *session, const gchar *group_name)
-{
-	MsnCallbackState *state;
-	char *body = NULL;
-	const gchar *guid;
-
-	g_return_if_fail(session != NULL);
-
-	g_return_if_fail(group_name != NULL);
-	purple_debug_info("msn", "Deleting group %s from contact list\n", group_name);
-
-	guid = msn_userlist_find_group_id(session->userlist, group_name);
-
-	/* if group uid we need to del is NULL,
-	*  we need to delete nothing
-	*/
-	if (guid == NULL) {
-		purple_debug_info("msn", "Group %s guid not found, returning.\n", group_name);
-		return;
-	}
-
-	if ( !strcmp(guid, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(guid, MSN_NON_IM_GROUP_ID) ) {
-		/* XXX add back PurpleGroup since it isn't really removed in the server? */
-		return;
-	}
-
-	state = msn_callback_state_new(session);
-	msn_callback_state_set_action(state, MSN_DEL_GROUP);
-	msn_callback_state_set_guid(state, guid);
-
-	body = g_strdup_printf(MSN_GROUP_DEL_TEMPLATE, guid);
-
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_GROUP_DEL_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_group_read_cb;
-	msn_contact_request(state);
-
-	g_free(body);
-}
-
-/* rename group */
-void
-msn_contact_rename_group(MsnSession *session, const char *old_group_name, const char *new_group_name)
-{
-	gchar *body = NULL;
-	const gchar * guid;
-	MsnCallbackState *state;
-	char *escaped_group_name;
-
-	g_return_if_fail(session != NULL);
-	g_return_if_fail(session->userlist != NULL);
-	g_return_if_fail(old_group_name != NULL);
-	g_return_if_fail(new_group_name != NULL);
-
-	purple_debug_info("msn", "Renaming group %s to %s.\n", old_group_name, new_group_name);
-
-	guid = msn_userlist_find_group_id(session->userlist, old_group_name);
-	if (guid == NULL)
-		return;
-
-	state = msn_callback_state_new(session);
-	msn_callback_state_set_guid(state, guid);
-	msn_callback_state_set_new_group_name(state, new_group_name);
-
-	if ( !strcmp(guid, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(guid, MSN_NON_IM_GROUP_ID) ) {
-		MsnCallbackState *new_state = msn_callback_state_dup(state);
-		msn_add_group(session, new_state, new_group_name);
-		/* XXX move every buddy there (we probably need to fix concurrent SOAP reqs first) */
-	}
-
-	msn_callback_state_set_action(state, MSN_RENAME_GROUP);
-
-	escaped_group_name = g_markup_escape_text(new_group_name, -1);
-	body = g_strdup_printf(MSN_GROUP_RENAME_TEMPLATE, guid, escaped_group_name);
-
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_GROUP_RENAME_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_group_read_cb;
-	msn_contact_request(state);
-
-	g_free(escaped_group_name);
-	g_free(body);
-}
-
deleted file mode 100644
--- a/libpurple/protocols/msn/contact.h
+++ /dev/null
@@ -1,747 +0,0 @@
-/**
- * @file contact.h			Header file for contact.c
- *	Author
- * 		MaYuan<mayuan2006@gmail.com>
- * purple
- *
- * Purple 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 02110-1301,  USA
- */
-#ifndef MSN_CONTACT_H
-#define MSN_CONTACT_H
-
-typedef struct _MsnCallbackState MsnCallbackState;
-
-typedef enum
-{
-	MSN_ADD_BUDDY       = 0x01,
-	MSN_MOVE_BUDDY      = 0x02,
-	MSN_ACCEPTED_BUDDY  = 0x04,
-	MSN_DENIED_BUDDY    = 0x08,
-	MSN_ADD_GROUP       = 0x10,
-	MSN_DEL_GROUP       = 0x20,
-	MSN_RENAME_GROUP    = 0x40,
-	MSN_UPDATE_INFO     = 0x80,
-	MSN_ANNOTATE_USER   = 0x100
-} MsnCallbackAction;
-
-typedef enum
-{
-	MSN_UPDATE_DISPLAY,	/* Real display name */
-	MSN_UPDATE_ALIAS,	/* Aliased display name */
-	MSN_UPDATE_COMMENT
-} MsnContactUpdateType;
-
-typedef enum
-{
-	MSN_PS_INITIAL,
-	MSN_PS_SAVE_CONTACT,
-	MSN_PS_PENDING_LIST,
-	MSN_PS_CONTACT_API,
-	MSN_PS_BLOCK_UNBLOCK,
-	MSN_PS_TIMER
-} MsnSoapPartnerScenario;
-
-#include "session.h"
-#include "soap.h"
-
-/* Thanks to TReKiE on the #pidgin channel for this new ID. */
-#define MSN_APPLICATION_ID "F6D2794D-501F-443A-ADBE-8F1490FF30FD"
-
-#define MSN_CONTACT_SERVER	"local-bay.contacts.msn.com"
-
-/* Get Contact List */
-
-#define MSN_GET_CONTACT_POST_URL	"/abservice/SharingService.asmx"
-#define MSN_GET_CONTACT_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/FindMembership"
-
-#define MSN_GET_CONTACT_UPDATE_XML \
-	"<View>Full</View>"\
-	"<deltasOnly>true</deltasOnly>"\
-	"<lastChange>%s</lastChange>"
-
-#define MSN_GET_CONTACT_TEMPLATE	"<?xml version='1.0' encoding='utf-8'?>"\
-"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
-	"<soap:Header xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId xmlns=\"http://www.msn.com/webservices/AddressBook\">" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration xmlns=\"http://www.msn.com/webservices/AddressBook\">false</IsMigration>"\
-			"<PartnerScenario xmlns=\"http://www.msn.com/webservices/AddressBook\">%s</PartnerScenario>"\
-		 "</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest xmlns=\"http://www.msn.com/webservices/AddressBook\">false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
-		"<FindMembership xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<serviceFilter xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-				"<Types xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-					"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Messenger</ServiceType>"\
-					"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Invitation</ServiceType>"\
-					"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">SocialNetwork</ServiceType>"\
-					"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Space</ServiceType>"\
-					"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Profile</ServiceType>"\
-				"</Types>"\
-			"</serviceFilter>"\
-			"%s"\
-		"</FindMembership>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/************************************************
- * Address Book SOAP
- * *********************************************/
-
-#define MSN_ADDRESS_BOOK_POST_URL	"/abservice/abservice.asmx"
-
-/* Create AddressBook template */
-#define MSN_ADD_ADDRESSBOOK_SOAP_ACTION     "http://www.msn.com/webservices/AddressBook/ABAdd"
-
-#define MSN_ADD_ADDRESSBOOK_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>Initial</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abInfo>"\
-				"<name/>"\
-				"<ownerPuid>0</ownerPuid>"\
-				"<ownerEmail>%s</ownerEmail>"\
-				"<fDefault>true</fDefault>"\
-			"</abInfo>"\
-		"</ABAdd>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/* Get AddressBook */
-#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 \
-	"<filterOptions>"\
-		"<deltasOnly>true</deltasOnly>"\
-		"<lastChange>%s</lastChange>"\
-	"</filterOptions>"
-
-#define MSN_GET_GLEAM_UPDATE_XML \
-	"%s"\
-	"<dynamicItemView>Gleam</dynamicItemView>"\
-	"<dynamicItemLastChange>%s</dynamicItemLastChange>"
-
-#define MSN_GET_ADDRESS_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>%s</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABFindContactsPaged xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abView>Full</abView>"\
-			"<extendedContent>AB AllGroups CircleResult</extendedContent>"\
-			"%s"\
-		"</ABFindContactsPaged>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-
-/*Gleams SOAP request template*/
-#define MSN_GET_GLEAMS_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABFindAll"
-#define MSN_GLEAMS_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>Initial</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABFindAll xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<abView>Full</abView>"\
-			"<dynamicItemView>Gleam</dynamicItemView>"\
-			"<dynamicItemLastChange>0001-01-01T00:00:00.0000000-08:00</dynamicItemLastChange>"\
-		"</ABFindAll>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-
-/*******************************************************
- * Contact Management SOAP actions
- *******************************************************/
-
-/* Add a new contact */
-#define MSN_CONTACT_ADD_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABContactAdd"
-#define MSN_CONTACT_LIVE_PENDING_XML \
-	"<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-		"<contactInfo>"\
-			"<contactType>LivePending</contactType>"\
-			"<passportName>%s</passportName>"\
-			"<isMessengerUser>true</isMessengerUser>"\
-		"</contactInfo>"\
-	"</Contact>"
-
-#define MSN_CONTACT_XML	\
-	"<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-		"<contactInfo>"\
-			"<passportName>%s</passportName>"\
-			"<isSmtp>false</isSmtp>"\
-			"<isMessengerUser>true</isMessengerUser>"\
-		"</contactInfo>"\
-	"</Contact>"
-
-#define MSN_CONTACT_DISPLAYNAME_XML	\
-	"<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-		"<contactInfo>"\
-			"<displayName>%s</displayName>"\
-			"<passportName>%s</passportName>"\
-			"<isMessengerUser>true</isMessengerUser>"\
-		"</contactInfo>"\
-	"</Contact>"
-
-#define MSN_CONTACT_ID_XML \
-	"<Contact>"\
-		"<contactId>%s</contactId>"\
-	"</Contact>"
-
-#define MSN_CONTACT_EMAIL_XML \
-	"<Contact>"\
-		"<contactInfo>"\
-			"<emails>"\
-				"<ContactEmail>"\
-					"<contactEmailType>%s</contactEmailType>"\
-					"<email>%s</email>"\
-					"<isMessengerEnabled>true</isMessengerEnabled>"\
-					"<Capability>%d</Capability>"\
-					"<MessengerEnabledExternally>false</MessengerEnabledExternally>"\
-					"<propertiesChanged/>"\
-				"</ContactEmail>"\
-			"</emails>"\
-		"</contactInfo>"\
-	"</Contact>"
-
-#define MSN_CONTACT_INVITE_MESSAGE_XML \
-	"<MessengerMemberInfo>"\
-		"<PendingAnnotations>"\
-			"<Annotation>"\
-				"<Name>MSN.IM.InviteMessage</Name>"\
-				"<Value>%s</Value>"\
-			"</Annotation>"\
-		"</PendingAnnotations>"\
-		"<DisplayName>%s</DisplayName>"\
-	"</MessengerMemberInfo>"
-
-#define MSN_ADD_CONTACT_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>ContactSave</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABContactAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<contacts>%s</contacts>"\
-			"<options>"\
-				"<EnableAllowListManagement>true</EnableAllowListManagement>"\
-			"</options>"\
-		"</ABContactAdd>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/* Add a contact to a group */
-#define MSN_ADD_CONTACT_GROUP_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABGroupContactAdd"
-#define MSN_ADD_CONTACT_GROUP_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>ContactSave</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABGroupContactAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<groupFilter>"\
-				"<groupIds>"\
-					"<guid>%s</guid>"\
-				"</groupIds>"\
-			"</groupFilter>"\
-			"<contacts>%s</contacts>"\
-			"<groupContactAddOptions>"\
-				"<fGenerateMissingQuickName>true</fGenerateMissingQuickName>"\
-				"<EnableAllowListManagement>true</EnableAllowListManagement>"\
-			"</groupContactAddOptions>"\
-			"%s"\
-		"</ABGroupContactAdd>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/* Delete a contact from the Contact List */
-#define MSN_CONTACT_DEL_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABContactDelete"
-#define MSN_DEL_CONTACT_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>Timer</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABContactDelete xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<contacts>%s</contacts>"\
-		"</ABContactDelete>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/* Remove a contact from a group */
-#define MSN_CONTACT_DEL_GROUP_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABGroupContactDelete"
-#define MSN_CONTACT_DEL_GROUP_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>Timer</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABGroupContactDelete xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<contacts>%s</contacts>"\
-			"<groupFilter>"\
-				"<groupIds>"\
-					"<guid>%s</guid>"\
-				"</groupIds>"\
-			"</groupFilter>"\
-		"</ABGroupContactDelete>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-
-/* Update Contact Information */
-#define MSN_CONTACT_UPDATE_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABContactUpdate"
-#define MSN_CONTACT_UPDATE_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario></PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABContactUpdate xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<contacts>"\
-				"<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-					""\
-				"</Contact>"\
-			"</contacts>"\
-		"</ABContactUpdate>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/* Update Contact Annotations */
-#define MSN_CONTACT_ANNOTATE_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABContactUpdate"
-#define MSN_CONTACT_ANNOTATE_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario></PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABContactUpdate xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<contacts>"\
-				"<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-					"<propertiesChanged>Annotation</propertiesChanged>"\
-				"</Contact>"\
-			"</contacts>"\
-		"</ABContactUpdate>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/*******************************************************
- * Add/Delete contact from lists SOAP actions
- *******************************************************/
-
-/* block means delete from allow list and add contact to block list */
-#define MSN_SHARE_POST_URL		"/abservice/SharingService.asmx"
-
-#define MSN_ADD_MEMBER_TO_LIST_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/AddMember"
-#define MSN_DELETE_MEMBER_FROM_LIST_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/DeleteMember"
-
-#define MSN_MEMBER_PASSPORT_XML	\
-	"<Member xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"%s\">"\
-		"<Type>%s</Type>"\
-		"<State>Accepted</State>"\
-		"<%s>%s</%s>"\
-	"</Member>"
-
-#define MSN_MEMBER_MEMBERSHIPID_XML	\
-	"<Member xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"%s\">"\
-		"<Type>%s</Type>"\
-		"<MembershipId>%u</MembershipId>"\
-		"<State>Accepted</State>"\
-	"</Member>"
-
-/* first delete contact from allow list */
-
-#define MSN_CONTACT_DELETE_FROM_LIST_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>%s</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<DeleteMember xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<serviceHandle>"\
-				"<Id>0</Id>"\
-				"<Type>Messenger</Type>"\
-				"<ForeignId></ForeignId>"\
-			"</serviceHandle>"\
-			"<memberships>"\
-				"<Membership>"\
-					"<MemberRole>%s</MemberRole>"\
-					"<Members>"\
-						"%s"\
-					"</Members>"\
-				"</Membership>"\
-			"</memberships>"\
-		"</DeleteMember>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-#define MSN_CONTACT_ADD_TO_LIST_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>%s</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<AddMember xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<serviceHandle>"\
-				"<Id>0</Id>"\
-				"<Type>Messenger</Type>"\
-				"<ForeignId></ForeignId>"\
-			"</serviceHandle>"\
-			"<memberships>"\
-				"<Membership>"\
-					"<MemberRole>%s</MemberRole>"\
-					"<Members>"\
-						"%s"\
-					"</Members>"\
-				"</Membership>"\
-			"</memberships>"\
-		"</AddMember>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-
-
-/*******************************************************
- * Group management SOAP actions
- *******************************************************/
-
-/* add a group */
-#define MSN_GROUP_ADD_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABGroupAdd"
-#define MSN_GROUP_ADD_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>GroupSave</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABGroupAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<groupAddOptions>"\
-				"<fRenameOnMsgrConflict>false</fRenameOnMsgrConflict>"\
-			"</groupAddOptions>"\
-			"<groupInfo>"\
-				"<GroupInfo>"\
-					"<name>%s</name>"\
-					"<groupType>C8529CE2-6EAD-434d-881F-341E17DB3FF8</groupType>"\
-					"<fMessenger>false</fMessenger>"\
-					"<annotations>"\
-						"<Annotation>"\
-							"<Name>MSN.IM.Display</Name>"\
-							"<Value>1</Value>"\
-						"</Annotation>"\
-					"</annotations>"\
-				"</GroupInfo>"\
-			"</groupInfo>"\
-		"</ABGroupAdd>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/* delete a group */
-#define MSN_GROUP_DEL_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABGroupDelete"
-#define MSN_GROUP_DEL_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>Timer</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABGroupDelete xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<groupFilter>"\
-				"<groupIds>"\
-					"<guid>%s</guid>"\
-				"</groupIds>"\
-			"</groupFilter>"\
-		"</ABGroupDelete>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/* change a group's name */
-#define MSN_GROUP_RENAME_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABGroupUpdate"
-#define MSN_GROUP_RENAME_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>Timer</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABGroupUpdate xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<groups>"\
-				"<Group>"\
-					"<groupId>%s</groupId>"\
-					"<groupInfo>"\
-						"<name>%s</name>"\
-					"</groupInfo>"\
-					"<propertiesChanged>GroupName </propertiesChanged>"\
-				"</Group>"\
-			"</groups>"\
-		"</ABGroupUpdate>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-struct _MsnCallbackState
-{
-	gchar * who;
-	gchar * uid;
-	gchar * old_group_name;
-	gchar * new_group_name;
-	gchar * guid;
-	MsnListId list_id;
-	MsnCallbackAction action;
-	MsnSession *session;
-	xmlnode *body;
-	xmlnode *token;
-	const gchar *post_action;
-	const gchar *post_url;
-	MsnSoapCallback cb;
-	/* For msn_get_contact_list only */
-	MsnSoapPartnerScenario partner_scenario;
-};
-
-/************************************************
- * function prototype
- ************************************************/
-MsnCallbackState * msn_callback_state_new(MsnSession *session);
-MsnCallbackState * msn_callback_state_dup(MsnCallbackState *state);
-void msn_callback_state_free(MsnCallbackState *state);
-void msn_callback_state_set_who(MsnCallbackState *state, const gchar *who);
-void msn_callback_state_set_uid(MsnCallbackState *state, const gchar *uid);
-void msn_callback_state_set_old_group_name(MsnCallbackState *state,
-					   const gchar *old_group_name);
-void msn_callback_state_set_new_group_name(MsnCallbackState *state,
-					   const gchar *new_group_name);
-void msn_callback_state_set_guid(MsnCallbackState *state, const gchar *guid);
-void msn_callback_state_set_list_id(MsnCallbackState *state, MsnListId list_id);
-void msn_callback_state_set_action(MsnCallbackState *state,
-				   MsnCallbackAction action);
-
-void msn_get_contact_list(MsnSession *session,
-			  const MsnSoapPartnerScenario partner_scenario,
-			  const char *update);
-void msn_get_address_book(MsnSession *session,
-			  const MsnSoapPartnerScenario partner_scenario,
-			  const char * update, const char * gupdate);
-
-/* contact SOAP operations */
-void msn_update_contact(MsnSession *session, const char *passport, MsnContactUpdateType type, const char* value);
-
-void msn_annotate_contact(MsnSession *session, const char *passport, ...) G_GNUC_NULL_TERMINATED;
-
-void msn_add_contact(MsnSession *session, MsnCallbackState *state,
-		     const char *passport);
-void msn_delete_contact(MsnSession *session, MsnUser *user);
-
-void msn_add_contact_to_group(MsnSession *session, MsnCallbackState *state,
-			      const char *passport, const char *groupId);
-void msn_del_contact_from_group(MsnSession *session, const char *passport,
-				const char *group_name);
-/* group operations */
-void msn_add_group(MsnSession *session, MsnCallbackState *state,
-					const char* group_name);
-void msn_del_group(MsnSession *session, const gchar *group_name);
-void msn_contact_rename_group(MsnSession *session, const char *old_group_name,
-						   const char *new_group_name);
-
-/* lists operations */
-void msn_add_contact_to_list(MsnSession *session, MsnCallbackState *state,
-			     const gchar *passport, const MsnListId list);
-void msn_del_contact_from_list(MsnSession *session, MsnCallbackState *state,
-			       const gchar *passport, const MsnListId list);
-
-#endif /* MSN_CONTACT_H */
deleted file mode 100644
--- a/libpurple/protocols/msn/directconn.c
+++ /dev/null
@@ -1,958 +0,0 @@
-/**
- * @file directconn.c MSN direct connection functions
- *
- * purple
- *
- * Purple 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 "cipher.h"
-#include "debug.h"
-
-#include "msn.h"
-#include "msnutils.h"
-#include "directconn.h"
-
-#include "slp.h"
-#include "slpmsg.h"
-#include "p2p.h"
-
-#define DC_MAX_BODY_SIZE      8*1024
-#define DC_MAX_PACKET_SIZE    (P2P_PACKET_HEADER_SIZE + DC_MAX_BODY_SIZE)
-
-static void
-msn_dc_calculate_nonce_hash(MsnDirectConnNonceType type,
-                            const guchar *nonce, gsize nonce_len, gchar nonce_hash[37])
-{
-	guchar digest[20];
-
-	if (type == DC_NONCE_SHA1) {
-		PurpleCipher *cipher = purple_ciphers_find_cipher("sha1");
-		PurpleCipherContext *context = purple_cipher_context_new(cipher, NULL);
-		purple_cipher_context_append(context, nonce, nonce_len);
-		purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
-		purple_cipher_context_destroy(context);
-	} else if (type == DC_NONCE_PLAIN) {
-		memcpy(digest, nonce, nonce_len);
-	} else {
-		nonce_hash[0] = '\0';
-		g_return_if_reached();
-	}
-
-	g_sprintf(nonce_hash,
-	          "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
-
-	          digest[3],
-	          digest[2],
-	          digest[1],
-	          digest[0],
-
-	          digest[5],
-	          digest[4],
-
-	          digest[7],
-	          digest[6],
-
-	          digest[8],
-	          digest[9],
-
-	          digest[10],
-	          digest[11],
-	          digest[12],
-	          digest[13],
-	          digest[14],
-	          digest[15]
-	);
-}
-
-static void
-msn_dc_generate_nonce(MsnDirectConn *dc)
-{
-	guint32 *nonce;
-	int i;
-
-	nonce = (guint32 *)&dc->nonce;
-	for (i = 0; i < 4; i++)
-		nonce[i] = rand();
-
-	msn_dc_calculate_nonce_hash(dc->nonce_type, dc->nonce, sizeof(dc->nonce), dc->nonce_hash);
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "DC %p generated nonce %s\n", dc, dc->nonce_hash);
-}
-
-static MsnDirectConnPacket *
-msn_dc_new_packet(guint32 length)
-{
-	MsnDirectConnPacket	*p;
-
-	p = g_new0(MsnDirectConnPacket, 1);
-	p->length = length;
-	p->data = g_malloc(length);
-
-	return p;
-}
-
-static void
-msn_dc_destroy_packet(MsnDirectConnPacket *p)
-{
-	g_free(p->data);
-
-	if (p->part)
-		msn_slpmsgpart_unref(p->part);
-
-	g_free(p);
-}
-
-MsnDirectConn *
-msn_dc_new(MsnSlpCall *slpcall)
-{
-	MsnDirectConn *dc;
-
-	g_return_val_if_fail(slpcall != NULL, NULL);
-
-	dc = g_new0(MsnDirectConn, 1);
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "msn_dc_new %p\n", dc);
-
-	dc->slplink = slpcall->slplink;
-	dc->slpcall = slpcall;
-
-	if (dc->slplink->dc != NULL)
-		purple_debug_warning("msn", "msn_dc_new: slplink already has an allocated DC!\n");
-
-	dc->slplink->dc = dc;
-
-	dc->msg_body = NULL;
-	dc->prev_ack = NULL;
-	dc->listen_data = NULL;
-	dc->connect_data = NULL;
-	dc->listenfd = -1;
-	dc->listenfd_handle = 0;
-	dc->connect_timeout_handle = 0;
-	dc->fd = -1;
-	dc->recv_handle = 0;
-	dc->send_handle = 0;
-	dc->state = DC_STATE_CLOSED;
-	dc->in_buffer = NULL;
-	dc->out_queue = g_queue_new();
-	dc->msg_pos = -1;
-	dc->send_connection_info_msg_cb = NULL;
-	dc->ext_ip = NULL;
-	dc->timeout_handle = 0;
-	dc->progress = FALSE;
-	/*dc->num_calls = 1;*/
-
-	/* TODO: Probably should set this based on buddy caps */
-	dc->nonce_type = DC_NONCE_PLAIN;
-	msn_dc_generate_nonce(dc);
-
-	return dc;
-}
-
-void
-msn_dc_destroy(MsnDirectConn *dc)
-{
-	MsnSlpLink *slplink;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "msn_dc_destroy %p\n", dc);
-
-	g_return_if_fail(dc != NULL);
-
-	if (dc->slpcall != NULL)
-		dc->slpcall->wait_for_socket = FALSE;
-
-	slplink = dc->slplink;
-	if (slplink) {
-		slplink->dc = NULL;
-		if (slplink->swboard == NULL)
-			msn_slplink_unref(slplink);
-	}
-
-	g_free(dc->msg_body);
-
-	if (dc->prev_ack) {
-		msn_slpmsg_destroy(dc->prev_ack);
-	}
-
-	if (dc->listen_data != NULL) {
-		purple_network_listen_cancel(dc->listen_data);
-	}
-
-	if (dc->connect_data != NULL) {
-		purple_proxy_connect_cancel(dc->connect_data);
-	}
-
-	if (dc->listenfd != -1) {
-		purple_network_remove_port_mapping(dc->listenfd);
-		close(dc->listenfd);
-	}
-
-	if (dc->listenfd_handle != 0) {
-		purple_input_remove(dc->listenfd_handle);
-	}
-
-	if (dc->connect_timeout_handle != 0) {
-		purple_timeout_remove(dc->connect_timeout_handle);
-	}
-
-	if (dc->fd != -1) {
-		close(dc->fd);
-	}
-
-	if (dc->send_handle != 0) {
-		purple_input_remove(dc->send_handle);
-	}
-
-	if (dc->recv_handle != 0) {
-		purple_input_remove(dc->recv_handle);
-	}
-
-	g_free(dc->in_buffer);
-
-	if (dc->out_queue != NULL) {
-		while (!g_queue_is_empty(dc->out_queue))
-			msn_dc_destroy_packet( g_queue_pop_head(dc->out_queue) );
-
-		g_queue_free(dc->out_queue);
-	}
-
-	g_free(dc->ext_ip);
-
-	if (dc->timeout_handle != 0) {
-		purple_timeout_remove(dc->timeout_handle);
-	}
-
-	g_free(dc);
-}
-
-/*
-void
-msn_dc_ref(MsnDirectConn *dc)
-{
-	g_return_if_fail(dc != NULL);
-
-	dc->num_calls++;
-}
-
-void
-msn_dc_unref(MsnDirectConn *dc)
-{
-	g_return_if_fail(dc != NULL);
-
-
-	if (dc->num_calls > 0) {
-		dc->num_calls--;
-	}
-}
-*/
-
-void
-msn_dc_send_invite(MsnDirectConn *dc)
-{
-	MsnSlpCall    *slpcall;
-	MsnSlpMessage *msg;
-	gchar *header;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "msn_dc_send_invite %p\n", dc);
-
-	g_return_if_fail(dc != NULL);
-
-	slpcall = dc->slpcall;
-	g_return_if_fail(slpcall != NULL);
-
-	header = g_strdup_printf(
-		"INVITE MSNMSGR:%s MSNSLP/1.0",
-		slpcall->slplink->remote_user
-	);
-
-	msg = msn_slpmsg_sip_new(
-		slpcall,
-		0,
-		header,
-		slpcall->branch,
-		"application/x-msnmsgr-transrespbody",
-		dc->msg_body
-	);
-	msg->info = "DC INVITE";
-	msg->text_body = TRUE;
-	g_free(header);
-	g_free(dc->msg_body);
-	dc->msg_body = NULL;
-
-	msn_slplink_queue_slpmsg(slpcall->slplink, msg);
-}
-
-void
-msn_dc_send_ok(MsnDirectConn *dc)
-{
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "msn_dc_send_ok %p\n", dc);
-
-	g_return_if_fail(dc != NULL);
-
-	msn_slp_send_ok(dc->slpcall, dc->slpcall->branch,
-		"application/x-msnmsgr-transrespbody", dc->msg_body);
-	g_free(dc->msg_body);
-	dc->msg_body = NULL;
-
-	msn_slplink_send_slpmsg(dc->slpcall->slplink, dc->prev_ack);
-	msn_slpmsg_destroy(dc->prev_ack);
-	dc->prev_ack = NULL;
-	msn_slplink_send_queued_slpmsgs(dc->slpcall->slplink);
-}
-
-void
-msn_dc_fallback_to_sb(MsnDirectConn *dc)
-{
-	MsnSlpLink *slplink;
-	MsnSlpCall *slpcall;
-	GQueue *queue = NULL;
-
-	purple_debug_info("msn", "msn_dc_fallback_to_sb %p\n", dc);
-
-	g_return_if_fail(dc != NULL);
-
-	slpcall = dc->slpcall;
-	slplink = msn_slplink_ref(dc->slplink);
-	if (slpcall && !g_queue_is_empty(dc->out_queue)) {
-		queue = dc->out_queue;
-		dc->out_queue = NULL;
-	}
-
-	msn_dc_destroy(dc);
-
-	if (slpcall) {
-		msn_slpcall_session_init(slpcall);
-		if (queue) {
-			while (!g_queue_is_empty(queue)) {
-				MsnDirectConnPacket *p = g_queue_pop_head(queue);
-				msn_slplink_send_msgpart(slplink, (MsnSlpMessage*)p->part->ack_data);
-				msn_dc_destroy_packet(p);
-			}
-			g_queue_free(queue);
-		}
-	}
-	msn_slplink_unref(slplink);
-}
-
-static void
-msn_dc_send_cb(gpointer data, gint fd, PurpleInputCondition cond)
-{
-	MsnDirectConn *dc = data;
-	MsnDirectConnPacket *p;
-	int bytes_to_send;
-	int bytes_sent;
-
-	g_return_if_fail(dc != NULL);
-	g_return_if_fail(fd != -1);
-
-	if (g_queue_is_empty(dc->out_queue)) {
-		if (dc->send_handle != 0) {
-			purple_input_remove(dc->send_handle);
-			dc->send_handle = 0;
-		}
-		return;
-	}
-
-	p = g_queue_peek_head(dc->out_queue);
-
-	if (dc->msg_pos < 0) {
-		/* First we send the length of the packet */
-		guint32 len = GUINT32_TO_LE(p->length);
-		bytes_sent = send(fd, &len, 4, 0);
-		if (bytes_sent < 0) {
-			if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-				return;
-
-			purple_debug_warning("msn", "msn_dc_send_cb: send error\n");
-			msn_dc_destroy(dc);
-			return;
-		}
-		dc->msg_pos = 0;
-	}
-
-	bytes_to_send = p->length - dc->msg_pos;
-	bytes_sent = send(fd, p->data + dc->msg_pos, bytes_to_send, 0);
-	if (bytes_sent < 0) {
-		if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-			return;
-
-		purple_debug_warning("msn", "msn_dc_send_cb: send error\n");
-		msn_dc_destroy(dc);
-		return;
-	}
-
-	dc->progress = TRUE;
-
-	dc->msg_pos += bytes_sent;
-	if ((guint32)dc->msg_pos == p->length) {
-		if (p->sent_cb != NULL)
-			p->sent_cb(p);
-
-		g_queue_pop_head(dc->out_queue);
-		msn_dc_destroy_packet(p);
-
-		dc->msg_pos = -1;
-	}
-}
-
-static void
-msn_dc_enqueue_packet(MsnDirectConn *dc, MsnDirectConnPacket *p)
-{
-	gboolean was_empty;
-
-	was_empty = g_queue_is_empty(dc->out_queue);
-	g_queue_push_tail(dc->out_queue, p);
-
-	if (was_empty && dc->send_handle == 0) {
-		dc->send_handle = purple_input_add(dc->fd, PURPLE_INPUT_WRITE, msn_dc_send_cb, dc);
-		msn_dc_send_cb(dc, dc->fd, PURPLE_INPUT_WRITE);
-	}
-}
-
-static void
-msn_dc_send_foo(MsnDirectConn *dc)
-{
-	MsnDirectConnPacket	*p;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "msn_dc_send_foo %p\n", dc);
-
-	p = msn_dc_new_packet(4);
-
-	memcpy(p->data, "foo\0", 4);
-
-	msn_dc_enqueue_packet(dc, p);
-}
-
-#if 0 /* We don't actually need this */
-typedef struct {
-	guint32 null;
-	guint32 id;
-	guint32 null[5];
-	guint32 flags;
-	guint8  nonce[16];
-} MsnDirectConnNoncePacket;
-#endif
-#define DC_NONCE_PACKET_SIZE (8 * 4 + 16)
-#define DC_NONCE_PACKET_NONCE (8 * 4)
-
-static void
-msn_dc_send_handshake(MsnDirectConn *dc)
-{
-	MsnDirectConnPacket *p;
-	gchar *h;
-
-	p = msn_dc_new_packet(DC_NONCE_PACKET_SIZE);
-	h = (gchar *)p->data;
-
-	msn_push32le(h, 0); /* NUL */
-
-	msn_push32le(h, dc->slpcall->slplink->slp_seq_id++);
-
-	/* More NUL stuff */
-	msn_push64le(h, 0);
-	msn_push64le(h, 0);
-	msn_push32le(h, 0);
-
-	/* Flags */
-	msn_push32le(h, P2P_DC_HANDSHAKE);
-
-	/* The real Nonce, yay! */
-	memcpy(h, dc->nonce, 16);
-
-	msn_dc_enqueue_packet(dc, p);
-}
-
-static gboolean
-msn_dc_verify_handshake(MsnDirectConn *dc, guint32 packet_length)
-{
-	guchar nonce[16];
-	gchar  nonce_hash[37];
-
-	if (packet_length != DC_NONCE_PACKET_SIZE)
-		return FALSE;
-
-	memcpy(nonce, dc->in_buffer + 4 + DC_NONCE_PACKET_NONCE, sizeof(nonce));
-
-	if (dc->nonce_type == DC_NONCE_PLAIN) {
-		if (memcmp(dc->nonce, nonce, sizeof(nonce)) == 0) {
-			purple_debug_info("msn",
-					"Nonce from buddy request and nonce from DC attempt match, "
-					"allowing direct connection\n");
-			return TRUE;
-		} else {
-			purple_debug_warning("msn",
-					"Nonce from buddy request and nonce from DC attempt "
-					"don't match, ignoring direct connection\n");
-			return FALSE;
-		}
-
-	} else if (dc->nonce_type == DC_NONCE_SHA1) {
-		msn_dc_calculate_nonce_hash(dc->nonce_type, nonce, sizeof(nonce), nonce_hash);
-
-		if (g_str_equal(dc->remote_nonce, nonce_hash)) {
-			purple_debug_info("msn",
-					"Received nonce %s from buddy request "
-					"and calculated nonce %s from DC attempt. "
-					"Nonces match, allowing direct connection\n",
-					dc->remote_nonce, nonce_hash);
-			return TRUE;
-		} else {
-			purple_debug_warning("msn",
-					"Received nonce %s from buddy request "
-					"and calculated nonce %s from DC attempt. "
-					"Nonces don't match, ignoring direct connection\n",
-					dc->remote_nonce, nonce_hash);
-			return FALSE;
-		}
-	} else
-		return FALSE;
-}
-
-static void
-msn_dc_send_packet_cb(MsnDirectConnPacket *p)
-{
-	if (p->part != NULL && p->part->ack_cb != NULL)
-		p->part->ack_cb(p->part, p->part->ack_data);
-}
-
-void
-msn_dc_enqueue_part(MsnDirectConn *dc, MsnSlpMessagePart *part)
-{
-	MsnDirectConnPacket *p;
-	size_t length;
-
-	p = msn_dc_new_packet(0);
-	p->data = (guchar *)msn_slpmsgpart_serialize(part, &length);
-	p->length = length - P2P_PACKET_FOOTER_SIZE; /* DC doesn't need footer? */
-
-	p->sent_cb = msn_dc_send_packet_cb;
-	p->part = msn_slpmsgpart_ref(part);
-
-	msn_dc_enqueue_packet(dc, p);
-}
-
-static int
-msn_dc_process_packet(MsnDirectConn *dc, guint32 packet_length)
-{
-	MsnSlpMessagePart *part;
-
-	g_return_val_if_fail(dc != NULL, DC_PROCESS_ERROR);
-
-	switch (dc->state) {
-	case DC_STATE_CLOSED:
-		break;
-
-	case DC_STATE_FOO:
-		/* FOO message is always 4 bytes long */
-		if (packet_length != 4 || memcmp(dc->in_buffer, "\4\0\0\0foo", 8) != 0)
-			return DC_PROCESS_FALLBACK;
-
-		dc->state = DC_STATE_HANDSHAKE;
-		break;
-
-	case DC_STATE_HANDSHAKE:
-		if (!msn_dc_verify_handshake(dc, packet_length))
-			return DC_PROCESS_FALLBACK;
-
-		msn_dc_send_handshake(dc);
-		dc->state = DC_STATE_ESTABLISHED;
-
-		msn_slpcall_session_init(dc->slpcall);
-		dc->slpcall = NULL;
-		break;
-
-	case DC_STATE_HANDSHAKE_REPLY:
-		if (!msn_dc_verify_handshake(dc, packet_length))
-			return DC_PROCESS_FALLBACK;
-
-		dc->state = DC_STATE_ESTABLISHED;
-
-		msn_slpcall_session_init(dc->slpcall);
-		dc->slpcall = NULL;
-		break;
-
-	case DC_STATE_ESTABLISHED:
-		if (packet_length) {
-			MsnP2PVersion p2p;
-			p2p = msn_slplink_get_p2p_version(dc->slplink);
-			part = msn_slpmsgpart_new_from_data(p2p, dc->in_buffer + 4, packet_length);
-			if (part) {
-				msn_slplink_process_msg(dc->slplink, part);
-				msn_slpmsgpart_unref(part);
-			}
-		}
-
-		/*
-		if (dc->num_calls == 0) {
-			msn_dc_destroy(dc);
-
-			return DC_PROCESS_CLOSE;
-		}
-		*/
-		break;
-	}
-
-	return DC_PROCESS_OK;
-}
-
-static void
-msn_dc_recv_cb(gpointer data, gint fd, PurpleInputCondition cond)
-{
-	MsnDirectConn *dc;
-	int free_buf_space;
-	int bytes_received;
-	guint32 packet_length;
-
-	g_return_if_fail(data != NULL);
-	g_return_if_fail(fd != -1);
-
-	dc = data;
-	free_buf_space = dc->in_size - dc->in_pos;
-
-	bytes_received = recv(fd, dc->in_buffer + dc->in_pos, free_buf_space, 0);
-	if (bytes_received < 0) {
-		if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-			return;
-
-		purple_debug_warning("msn", "msn_dc_recv_cb: recv error\n");
-
-		if(dc->state != DC_STATE_ESTABLISHED)
-			msn_dc_fallback_to_sb(dc);
-		else
-			msn_dc_destroy(dc);
-		return;
-
-	} else if (bytes_received == 0) {
-		/* EOF. Remote side closed connection. */
-		purple_debug_info("msn", "msn_dc_recv_cb: recv EOF\n");
-
-		if(dc->state != DC_STATE_ESTABLISHED)
-			msn_dc_fallback_to_sb(dc);
-		else
-			msn_dc_destroy(dc);
-		return;
-	}
-
-	dc->progress = TRUE;
-
-	dc->in_pos += bytes_received;
-
-	/* Wait for packet length */
-	while (dc->in_pos >= 4) {
-		packet_length = GUINT32_FROM_LE(*((guint32*)dc->in_buffer));
-
-		if (packet_length > DC_MAX_PACKET_SIZE) {
-			/* Oversized packet */
-			purple_debug_warning("msn", "msn_dc_recv_cb: oversized packet received\n");
-			return;
-		}
-
-		/* Wait for the whole packet to arrive */
-		if ((guint32)dc->in_pos < 4 + packet_length)
-			return;
-
-		switch (msn_dc_process_packet(dc, packet_length)) {
-		case DC_PROCESS_CLOSE:
-			return;
-
-		case DC_PROCESS_FALLBACK:
-			purple_debug_warning("msn", "msn_dc_recv_cb: packet processing error, fall back to SB\n");
-			msn_dc_fallback_to_sb(dc);
-			return;
-
-		}
-
-		if ((guint32)dc->in_pos > packet_length + 4) {
-			g_memmove(dc->in_buffer, dc->in_buffer + 4 + packet_length, dc->in_pos - packet_length - 4);
-		}
-
-		dc->in_pos -= packet_length + 4;
-	}
-}
-
-static gboolean
-msn_dc_timeout(gpointer data)
-{
-	MsnDirectConn *dc = data;
-
-	g_return_val_if_fail(dc != NULL, FALSE);
-
-	if (dc->progress) {
-		dc->progress = FALSE;
-		return TRUE;
-	} else {
-		dc->timeout_handle = 0;
-		msn_dc_destroy(dc);
-		return FALSE;
-	}
-}
-
-static void
-msn_dc_init(MsnDirectConn *dc)
-{
-	g_return_if_fail(dc != NULL);
-
-	dc->in_size = DC_MAX_PACKET_SIZE + 4;
-	dc->in_pos = 0;
-	dc->in_buffer = g_malloc(dc->in_size);
-
-	dc->recv_handle = purple_input_add(dc->fd, PURPLE_INPUT_READ, msn_dc_recv_cb, dc);
-	dc->send_handle = purple_input_add(dc->fd, PURPLE_INPUT_WRITE, msn_dc_send_cb, dc);
-
-	dc->timeout_handle = purple_timeout_add_seconds(DC_TIMEOUT, msn_dc_timeout, dc);
-}
-
-void
-msn_dc_connected_to_peer_cb(gpointer data, gint fd, const gchar *error_msg)
-{
-	MsnDirectConn *dc = data;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "msn_dc_connected_to_peer_cb %p\n", dc);
-
-	g_return_if_fail(dc != NULL);
-
-	dc->connect_data = NULL;
-	purple_timeout_remove(dc->connect_timeout_handle);
-	dc->connect_timeout_handle = 0;
-
-	dc->fd = fd;
-	if (dc->fd != -1) {
-		msn_dc_init(dc);
-		msn_dc_send_foo(dc);
-		msn_dc_send_handshake(dc);
-		dc->state = DC_STATE_HANDSHAKE_REPLY;
-	}
-}
-
-/*
- * This callback will be called when we're the server
- * and nobody has connected us in DC_INCOMING_TIMEOUT seconds
- */
-static gboolean
-msn_dc_incoming_connection_timeout_cb(gpointer data) {
-	MsnDirectConn *dc = data;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "msn_dc_incoming_connection_timeout_cb %p\n", dc);
-
-	g_return_val_if_fail(dc != NULL, FALSE);
-
-	if (dc->listen_data != NULL) {
-		purple_network_listen_cancel(dc->listen_data);
-		dc->listen_data = NULL;
-	}
-
-	if (dc->listenfd_handle != 0) {
-		purple_input_remove(dc->listenfd_handle);
-		dc->listenfd_handle = 0;
-	}
-
-	if (dc->listenfd != -1) {
-		purple_network_remove_port_mapping(dc->listenfd);
-		close(dc->listenfd);
-		dc->listenfd = -1;
-	}
-
-	dc->connect_timeout_handle = 0;
-	msn_dc_fallback_to_sb(dc);
-
-	return FALSE;
-}
-
-/*
- * This callback will be called when we're unable to connect to
- * the remote host in DC_OUTGOING_TIMEOUT seconds.
- */
-gboolean
-msn_dc_outgoing_connection_timeout_cb(gpointer data)
-{
-	MsnDirectConn *dc = data;
-
-	purple_debug_info("msn", "msn_dc_outgoing_connection_timeout_cb %p\n", dc);
-
-	g_return_val_if_fail(dc != NULL, FALSE);
-
-	dc->connect_timeout_handle = 0;
-
-	if (dc->connect_data != NULL) {
-		purple_proxy_connect_cancel(dc->connect_data);
-		dc->connect_data = NULL;
-	}
-
-	if (dc->ext_ip && dc->ext_port) {
-		/* Try external IP/port if available. */
-		dc->connect_data = purple_proxy_connect(
-			NULL,
-			dc->slpcall->slplink->session->account,
-			dc->ext_ip,
-			dc->ext_port,
-			msn_dc_connected_to_peer_cb,
-			dc
-		);
-
-		g_free(dc->ext_ip);
-		dc->ext_ip = NULL;
-
-		if (dc->connect_data) {
-			dc->connect_timeout_handle = purple_timeout_add_seconds(
-				DC_OUTGOING_TIMEOUT,
-				msn_dc_outgoing_connection_timeout_cb,
-				dc
-			);
-		} else {
-			/*
-			 * Connection failed
-			 * Fall back to SB transfer
-			 */
-			msn_dc_outgoing_connection_timeout_cb(dc);
-		}
-
-	} else {
-		/*
-		 * Both internal and external connection attempts failed.
-		 * Fall back to SB transfer.
-		 */
-		msn_dc_fallback_to_sb(dc);
-	}
-
-	return FALSE;
-}
-
-/*
- * This callback will be called when we're the server
- * and somebody has connected to us in DC_INCOMING_TIMEOUT seconds.
- */
-static void
-msn_dc_incoming_connection_cb(gpointer data, gint listenfd, PurpleInputCondition cond)
-{
-	MsnDirectConn *dc = data;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "msn_dc_incoming_connection_cb %p\n", dc);
-
-	g_return_if_fail(dc != NULL);
-
-	if (dc->connect_timeout_handle != 0) {
-		purple_timeout_remove(dc->connect_timeout_handle);
-		dc->connect_timeout_handle = 0;
-	}
-
-	if (dc->listenfd_handle != 0) {
-		purple_input_remove(dc->listenfd_handle);
-		dc->listenfd_handle = 0;
-	}
-
-	dc->fd = accept(listenfd, NULL, 0);
-
-	purple_network_remove_port_mapping(dc->listenfd);
-	close(dc->listenfd);
-	dc->listenfd = -1;
-
-	if (dc->fd != -1) {
-		msn_dc_init(dc);
-		dc->state = DC_STATE_FOO;
-	}
-}
-
-void
-msn_dc_listen_socket_created_cb(int listenfd, gpointer data)
-{
-	MsnDirectConn *dc = data;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "msn_dc_listen_socket_created_cb %p\n", dc);
-
-	g_return_if_fail(dc != NULL);
-
-	dc->listen_data = NULL;
-
-	if (listenfd != -1) {
-		const char *ext_ip;
-		const char *int_ip;
-		int port;
-
-		ext_ip = purple_network_get_my_ip(listenfd);
-		int_ip = purple_network_get_local_system_ip(listenfd);
-		port = purple_network_get_port_from_fd(listenfd);
-
-		dc->listenfd = listenfd;
-		dc->listenfd_handle = purple_input_add(
-			listenfd,
-			PURPLE_INPUT_READ,
-			msn_dc_incoming_connection_cb,
-			dc
-		);
-		dc->connect_timeout_handle = purple_timeout_add_seconds(
-			DC_INCOMING_TIMEOUT,
-			msn_dc_incoming_connection_timeout_cb,
-			dc
-		);
-
-		if (strcmp(int_ip, ext_ip) != 0) {
-			dc->msg_body = g_strdup_printf(
-				"Bridge: TCPv1\r\n"
-				"Listening: true\r\n"
-				"%sNonce: {%s}\r\n"
-				"IPv4External-Addrs: %s\r\n"
-				"IPv4External-Port: %d\r\n"
-				"IPv4Internal-Addrs: %s\r\n"
-				"IPv4Internal-Port: %d\r\n"
-				"\r\n",
-
-				dc->nonce_type != DC_NONCE_PLAIN ? "Hashed-" : "",
-				dc->nonce_hash,
-				ext_ip,
-				port,
-				int_ip,
-				port
-			);
-
-		} else {
-			dc->msg_body = g_strdup_printf(
-				"Bridge: TCPv1\r\n"
-				"Listening: true\r\n"
-				"%sNonce: {%s}\r\n"
-				"IPv4External-Addrs: %s\r\n"
-				"IPv4External-Port: %d\r\n"
-				"\r\n",
-
-				dc->nonce_type != DC_NONCE_PLAIN ? "Hashed-" : "",
-				dc->nonce_hash,
-				ext_ip,
-				port
-			);
-		}
-
-		if (dc->slpcall->wait_for_socket) {
-			if (dc->send_connection_info_msg_cb != NULL)
-				dc->send_connection_info_msg_cb(dc);
-
-			dc->slpcall->wait_for_socket = FALSE;
-		}
-	}
-}
-
deleted file mode 100644
--- a/libpurple/protocols/msn/directconn.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/**
- * @file directconn.h MSN direct connection functions
- *
- * purple
- *
- * Purple 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 MSN_DIRECTCONN_H
-#define MSN_DIRECTCONN_H
-
-typedef struct _MsnDirectConn MsnDirectConn;
-
-#include "network.h"
-#include "proxy.h"
-#include "circbuffer.h"
-
-#include "slp.h"
-#include "slplink.h"
-#include "slpmsg.h"
-#include "slpmsg_part.h"
-#include "p2p.h"
-
-#define MSN_DCCONN_MAX_SIZE 1352
-
-typedef enum
-{
-	DC_STATE_CLOSED,            /*< No socket opened yet */
-	DC_STATE_FOO,               /*< Waiting for FOO message */
-	DC_STATE_HANDSHAKE,         /*< Waiting for handshake message */
-	DC_STATE_HANDSHAKE_REPLY,   /*< Waiting for handshake reply message */
-	DC_STATE_ESTABLISHED        /*< Handshake complete */
-} MsnDirectConnState;
-
-typedef enum
-{
-	DC_PROCESS_OK = 0,
-	DC_PROCESS_ERROR,
-	DC_PROCESS_FALLBACK,
-	DC_PROCESS_CLOSE
-
-} MsnDirectConnProcessResult;
-
-typedef enum
-{
-	DC_NONCE_UNKNOWN,	/**< Invalid scheme */
-	DC_NONCE_PLAIN,     /**< No hashing */
-	DC_NONCE_SHA1       /**< First 16 bytes of SHA1 of nonce */
-
-} MsnDirectConnNonceType;
-
-typedef struct _MsnDirectConnPacket MsnDirectConnPacket;
-
-struct _MsnDirectConnPacket {
-	guint32     length;
-	guchar      *data;
-
-	void        (*sent_cb)(struct _MsnDirectConnPacket*);
-	MsnSlpMessagePart *part;
-};
-
-struct _MsnDirectConn
-{
-	MsnDirectConnState  state;      /**< Direct connection status */
-	MsnSlpLink          *slplink;   /**< The slplink using this direct connection */
-	MsnSlpCall          *slpcall;   /**< The slpcall which initiated the direct connection */
-	char                *msg_body;  /**< The body of message sent by send_connection_info_msg_cb */
-	MsnSlpMessage       *prev_ack;  /**< The saved SLP ACK message */
-
-	MsnDirectConnNonceType nonce_type;         /**< The type of nonce hashing */
-	guchar                 nonce[16];          /**< The nonce used for handshake */
-	gchar                  nonce_hash[37];     /**< The hash of nonce */
-	gchar                  remote_nonce[37];   /**< The remote side's nonce */
-
-	PurpleNetworkListenData *listen_data;           /**< The pending socket creation request */
-	PurpleProxyConnectData  *connect_data;          /**< The pending connection attempt */
-	int                     listenfd;               /**< The socket we're listening for incoming connections */
-	guint                   listenfd_handle;        /**< The timeout handle for incoming connection */
-	guint                   connect_timeout_handle; /**< The timeout handle for outgoing connection */
-
-	int     fd;             /**< The direct connection socket */
-	guint   recv_handle;    /**< The incoming data callback handle */
-	guint   send_handle;    /**< The outgoing data callback handle */
-
-	gchar   *in_buffer; /**< The receive buffer */
-	int     in_size;    /**< The receive buffer size */
-	int     in_pos;     /**< The first free position in receive buffer */
-	GQueue  *out_queue; /**< The outgoing packet queue */
-	int     msg_pos;    /**< The position of next byte to be sent in the actual packet */
-
-	/** The callback used for sending information to the peer about the opened socket */
-	void (*send_connection_info_msg_cb)(MsnDirectConn *);
-
-	gchar   *ext_ip;    /**< Our external IP address */
-	int     ext_port;   /**< Our external port */
-
-	guint       timeout_handle;
-	gboolean    progress;
-
-	/*int   num_calls;*/  /**< The number of slpcalls using this direct connection */
-};
-
-/* Outgoing attempt */
-#define DC_OUTGOING_TIMEOUT (5)
-/* Time for internal + external connection attempts */
-#define DC_INCOMING_TIMEOUT (DC_OUTGOING_TIMEOUT * 3)
-/* Timeout for lack of activity */
-#define DC_TIMEOUT          (60)
-
-/*
- * Queues an MSN message to be sent via direct connection.
- */
-void
-msn_dc_enqueue_part(MsnDirectConn *dc, MsnSlpMessagePart *part);
-
-/*
- * Creates, initializes, and returns a new MsnDirectConn structure.
- */
-MsnDirectConn *
-msn_dc_new(MsnSlpCall *slpcall);
-
-/*
- * Destroys an MsnDirectConn structure. Frees every buffer allocated earlier
- * restores saved callbacks, etc.
- */
-void
-msn_dc_destroy(MsnDirectConn *dc);
-
-/*
- * Fallback to switchboard connection. Used when neither side is able to
- * create a listening socket.
- */
-void
-msn_dc_fallback_to_sb(MsnDirectConn *dc);
-
-/*
- * Increases the slpcall counter in DC. The direct connection remains open
- * until all slpcalls using it are destroyed.
- */
-void
-msn_dc_ref(MsnDirectConn *dc);
-
-/*
- * Decrease the slpcall counter in DC. The direct connection remains open
- * until all slpcalls using it are destroyed.
- */
-void
-msn_dc_unref(MsnDirectConn *dc);
-
-/*
- * Sends a direct connect INVITE message on the associated slplink
- * with the corresponding connection type and information.
- */
-void
-msn_dc_send_invite(MsnDirectConn *dc);
-
-/*
- * Sends a direct connect OK message as a response to an INVITE received earliaer
- * on the corresponding slplink.
- */
-void
-msn_dc_send_ok(MsnDirectConn *dc);
-
-/*
- * This callback will be called when we're successfully connected to
- * the remote host.
- */
-void
-msn_dc_connected_to_peer_cb(gpointer data, gint fd, const gchar *error_msg);
-
-/*
- * This callback will be called when we're unable to connect to
- * the remote host in DC_CONNECT_TIMEOUT seconds.
- */
-gboolean
-msn_dc_outgoing_connection_timeout_cb(gpointer data);
-
-/*
- * This callback will be called when the listening socket is successfully
- * created and its parameters (IP/port) are available.
- */
-void
-msn_dc_listen_socket_created_cb(int listenfd, gpointer data);
-
-#endif /* MSN_DIRECTCONN_H */
deleted file mode 100644
--- a/libpurple/protocols/msn/error.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/**
- * @file error.c Error functions
- *
- * purple
- *
- * Purple 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 "debug.h"
-/* Masca: can we get rid of the sync issue dialog? */
-#include "request.h"
-
-#include "error.h"
-
-typedef struct
-{
-	MsnSession *session;
-	char *who;
-	char *group;
-	gboolean add;
-
-} MsnAddRemData;
-
-const char *
-msn_error_get_text(unsigned int type, gboolean *debug)
-{
-	static char msg[256];
-	const char *result;
-	*debug = FALSE;
-
-	switch (type) {
-		case 0:
-			result = _("Unable to parse message");
-			*debug = TRUE;
-			break;
-		case 200:
-			result = _("Syntax Error (probably a client bug)");
-			*debug = TRUE;
-			break;
-		case 201:
-			result = _("Invalid email address");
-			break;
-		case 205:
-			result = _("User does not exist");
-			break;
-		case 206:
-			result = _("Fully qualified domain name missing");
-			break;
-		case 207:
-			result = _("Already logged in");
-			break;
-		case 208:
-			result = _("Invalid username");
-			break;
-		case 209:
-			result = _("Invalid friendly name");
-			break;
-		case 210:
-			result = _("List full");
-			break;
-		case 215:
-			result = _("Already there");
-			*debug = TRUE;
-			break;
-		case 216:
-			result = _("Not on list");
-			break;
-		case 217:
-			result = _("User is offline");
-			break;
-		case 218:
-			result = _("Already in the mode");
-			*debug = TRUE;
-			break;
-		case 219:
-			result = _("Already in opposite list");
-			*debug = TRUE;
-			break;
-		case 223:
-			result = _("Too many groups");
-			break;
-		case 224:
-			result = _("Invalid group");
-			break;
-		case 225:
-			result = _("User not in group");
-			break;
-		case 229:
-			result = _("Group name too long");
-			break;
-		case 230:
-			result = _("Cannot remove group zero");
-			*debug = TRUE;
-			break;
-		case 231:
-			result = _("Tried to add a user to a group that doesn't exist");
-			break;
-		case 280:
-			result = _("Switchboard failed");
-			*debug = TRUE;
-			break;
-		case 281:
-			result = _("Notify transfer failed");
-			*debug = TRUE;
-			break;
-
-		case 300:
-			result = _("Required fields missing");
-			*debug = TRUE;
-			break;
-		case 301:
-			result = _("Too many hits to a FND");
-			*debug = TRUE;
-			break;
-		case 302:
-			result = _("Not logged in");
-			break;
-
-		case 500:
-			result = _("Service temporarily unavailable");
-			break;
-		case 501:
-			result = _("Database server error");
-			*debug = TRUE;
-			break;
-		case 502:
-			result = _("Command disabled");
-			*debug = TRUE;
-			break;
-		case 510:
-			result = _("File operation error");
-			*debug = TRUE;
-			break;
-		case 520:
-			result = _("Memory allocation error");
-			*debug = TRUE;
-			break;
-		case 540:
-			result = _("Wrong CHL value sent to server");
-			*debug = TRUE;
-			break;
-
-		case 600:
-			result = _("Server busy");
-			break;
-		case 601:
-			result = _("Server unavailable");
-			break;
-		case 602:
-			result = _("Peer notification server down");
-			*debug = TRUE;
-			break;
-		case 603:
-			result = _("Database connect error");
-			*debug = TRUE;
-			break;
-		case 604:
-			result = _("Server is going down (abandon ship)");
-			break;
-		case 605:
-			result = _("Server unavailable");
-			break;
-
-		case 707:
-			result = _("Error creating connection");
-			*debug = TRUE;
-			break;
-		case 710:
-			result = _("CVR parameters are either unknown or not allowed");
-			*debug = TRUE;
-			break;
-		case 711:
-			result = _("Unable to write");
-			break;
-		case 712:
-			result = _("Session overload");
-			*debug = TRUE;
-			break;
-		case 713:
-			result = _("User is too active");
-			break;
-		case 714:
-			result = _("Too many sessions");
-			break;
-		case 715:
-			result = _("Passport not verified");
-			break;
-		case 717:
-			result = _("Bad friend file");
-			*debug = TRUE;
-			break;
-		case 731:
-			result = _("Not expected");
-			*debug = TRUE;
-			break;
-
-		case 800:
-			result = _("Friendly name is changing too rapidly");
-			break;
-
-		case 910:
-		case 912:
-		case 918:
-		case 919:
-		case 921:
-		case 922:
-			result = _("Server too busy");
-			break;
-		case 911:
-		case 917:
-			result = _("Authentication failed");
-			break;
-		case 913:
-			result = _("Not allowed when offline");
-			break;
-		case 914:
-		case 915:
-		case 916:
-			result = _("Server unavailable");
-			break;
-		case 920:
-			result = _("Not accepting new users");
-			break;
-		case 923:
-			result = _("Kids Passport without parental consent");
-			break;
-		case 924:
-			result = _("Passport account not yet verified");
-			break;
-		case 927:
-			result = _("Passport account suspended");
-			break;
-		case 928:
-			result = _("Bad ticket");
-			*debug = TRUE;
-			break;
-
-		default:
-			g_snprintf(msg, sizeof(msg),
-			           _("Unknown Error Code %d"), type);
-			*debug = TRUE;
-			result = msg;
-			break;
-	}
-
-	return result;
-}
-
-void
-msn_error_handle(MsnSession *session, unsigned int type)
-{
-	char *buf;
-	gboolean debug;
-
-	buf = g_strdup_printf(_("MSN Error: %s\n"),
-	                      msn_error_get_text(type, &debug));
-	if (debug)
-		purple_debug_warning("msn", "error %d: %s\n", type, buf);
-	else
-		purple_notify_error(session->account->gc, NULL, buf, NULL);
-	g_free(buf);
-}
-
-/* Remove the buddy referenced by the MsnAddRemData before the serverside list
- * is changed.  If the buddy will be added, he'll be added back; if he will be
- * removed, he won't be. */
-/* Actually with our MSNP14 code that isn't true yet, he won't be added back :(
- * */
-static void
-msn_complete_sync_issue(MsnAddRemData *data)
-{
-	PurpleBuddy *buddy;
-	PurpleGroup *group = NULL;
-
-	if (data->group != NULL)
-		group = purple_find_group(data->group);
-
-	if (group != NULL)
-		buddy = purple_find_buddy_in_group(data->session->account, data->who, group);
-	else
-		buddy = purple_find_buddy(data->session->account, data->who);
-
-	if (buddy != NULL)
-		purple_blist_remove_buddy(buddy);
-}
-
-
-static void
-msn_add_cb(MsnAddRemData *data)
-{
-#if 0
-	/* this *should* be necessary !! */
-	msn_complete_sync_issue(data);
-#endif
-	MsnUserList *userlist = data->session->userlist;
-
-	msn_userlist_add_buddy(userlist, data->who, data->group);
-
-	g_free(data->group);
-	g_free(data->who);
-	g_free(data);
-}
-
-static void
-msn_rem_cb(MsnAddRemData *data)
-{
-	MsnUserList *userlist = data->session->userlist;
-	msn_complete_sync_issue(data);
-
-
-	if (data->group == NULL) {
-		msn_userlist_rem_buddy_from_list(userlist, data->who, MSN_LIST_FL);
-	} else {
-		g_free(data->group);
-	}
-
-	g_free(data->who);
-	g_free(data);
-}
-
-void
-msn_error_sync_issue(MsnSession *session, const char *passport,
-					const char *group_name)
-{
-	PurpleConnection *gc;
-	PurpleAccount *account;
-	MsnAddRemData *data;
-	char *msg, *reason;
-
-	account = session->account;
-	gc = purple_account_get_connection(account);
-
-	data          = g_new0(MsnAddRemData, 1);
-	data->who     = g_strdup(passport);
-	data->group   = g_strdup(group_name);
-	data->session = session;
-
-	msg = g_strdup_printf(_("Buddy list synchronization issue in %s (%s)"),
-						  purple_account_get_username(account),
-						  purple_account_get_protocol_name(account));
-
-	if (group_name != NULL)
-	{
-		reason = g_strdup_printf(_("%s on the local list is "
-								   "inside the group \"%s\" but not on "
-								   "the server list. "
-								   "Do you want this buddy to be added?"),
-								 passport, group_name);
-	}
-	else
-	{
-		reason = g_strdup_printf(_("%s is on the local list but "
-								   "not on the server list. "
-								   "Do you want this buddy to be added?"),
-								 passport);
-	}
-
-	purple_request_action(gc, NULL, msg, reason, PURPLE_DEFAULT_ACTION_NONE,
-						account, data->who, NULL,
-						data, 2,
-						_("Yes"), G_CALLBACK(msn_add_cb),
-						_("No"), G_CALLBACK(msn_rem_cb));
-
-	g_free(reason);
-	g_free(msg);
-}
-
deleted file mode 100644
--- a/libpurple/protocols/msn/error.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * @file error.h Error functions
- *
- * purple
- *
- * Purple 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 MSN_ERROR_H
-#define MSN_ERROR_H
-
-#include "session.h"
-
-/**
- * Returns the string representation of an error type.
- *
- * @param type The error type.
- * @param debug Whether this should be treated as a debug log message or a user-visible error
- *
- * @return The string representation of the error type.
- */
-const char *msn_error_get_text(unsigned int type, gboolean *debug);
-
-/**
- * Handles an error.
- *
- * @param session The current session.
- * @param type    The error type.
- */
-void msn_error_handle(MsnSession *session, unsigned int type);
-
-/**
- * Show the sync issue in a dialog using request api
- *
- * @param sesion 		MsnSession associated to this error.
- * @param passport 		The passport associated with the error.
- * @param group_name 	The group in the buddy is suppoused to be
- */
-void msn_error_sync_issue(MsnSession *session, const char *passport,
-						 const char *group_name);
-
-#endif /* MSN_ERROR_H */
deleted file mode 100644
--- a/libpurple/protocols/msn/group.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/**
- * @file group.c Group functions
- *
- * purple
- *
- * Purple 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 "msn.h"
-#include "group.h"
-
-MsnGroup *
-msn_group_new(MsnUserList *userlist, const char *id, const char *name)
-{
-	MsnGroup *group;
-
-	g_return_val_if_fail(id != NULL,      NULL);
-	g_return_val_if_fail(name != NULL, NULL);
-
-	group = g_new0(MsnGroup, 1);
-
-	msn_userlist_add_group(userlist, group);
-
-	group->id      = g_strdup(id);
-	group->name    = g_strdup(name);
-
-	return group;
-}
-
-void
-msn_group_destroy(MsnGroup *group)
-{
-	g_return_if_fail(group != NULL);
-
-	g_free(group->id);
-	g_free(group->name);
-	g_free(group);
-}
-
-void
-msn_group_set_id(MsnGroup *group, const char *id)
-{
-	g_return_if_fail(group != NULL);
-	g_return_if_fail(id != NULL);
-
-	g_free(group->id);
-	group->id = g_strdup(id);
-}
-
-void
-msn_group_set_name(MsnGroup *group, const char *name)
-{
-	g_return_if_fail(group != NULL);
-	g_return_if_fail(name  != NULL);
-
-	g_free(group->name);
-	group->name = g_strdup(name);
-}
-
-char*
-msn_group_get_id(const MsnGroup *group)
-{
-	g_return_val_if_fail(group != NULL, NULL);
-
-	return group->id;
-}
-
-const char *
-msn_group_get_name(const MsnGroup *group)
-{
-	g_return_val_if_fail(group != NULL, NULL);
-
-	return group->name;
-}
deleted file mode 100644
--- a/libpurple/protocols/msn/group.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/**
- * @file group.h Group functions
- *
- * purple
- *
- * Purple 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 MSN_GROUP_H
-#define MSN_GROUP_H
-
-typedef struct _MsnGroup  MsnGroup;
-
-#include "internal.h"
-
-#include "session.h"
-#include "user.h"
-#include "userlist.h"
-
-#define MSN_INDIVIDUALS_GROUP_ID	"1983"
-#define MSN_INDIVIDUALS_GROUP_NAME	_("Other Contacts")
-
-#define MSN_NON_IM_GROUP_ID		"email"
-#define MSN_NON_IM_GROUP_NAME	_("Non-IM Contacts")
-
-/**
- * A group.
- */
-struct _MsnGroup
-{
-	MsnSession *session;    /**< The MSN session.           */
-
-	char *id;                 /**< The group ID.              */
-	char *name;             /**< The name of the group.     */
-};
-
-/**************************************************************************
- ** @name Group API                                                       *
- **************************************************************************/
-/*@{*/
-
-/**
- * Creates a new group structure.
- *
- * @param session The MSN session.
- * @param id      The group ID.
- * @param name    The name of the group.
- *
- * @return A new group structure.
- */
-MsnGroup *msn_group_new(MsnUserList *userlist, const char *id, const char *name);
-
-/**
- * Destroys a group structure.
- *
- * @param group The group to destroy.
- */
-void msn_group_destroy(MsnGroup *group);
-
-/**
- * Sets the ID for a group.
- *
- * @param group The group.
- * @param id    The ID.
- */
-void msn_group_set_id(MsnGroup *group, const char *id);
-
-/**
- * Sets the name for a group.
- *
- * @param group The group.
- * @param name  The name.
- */
-void msn_group_set_name(MsnGroup *group, const char *name);
-
-/**
- * Returns the ID for a group.
- *
- * @param group The group.
- *
- * @return The ID.
- */
-char* msn_group_get_id(const MsnGroup *group);
-
-/**
- * Returns the name for a group.
- *
- * @param group The group.
- *
- * @return The name.
- */
-const char *msn_group_get_name(const MsnGroup *group);
-
-#endif /* MSN_GROUP_H */
deleted file mode 100644
--- a/libpurple/protocols/msn/history.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * @file history.c MSN history functions
- *
- * purple
- *
- * Purple 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 "msn.h"
-#include "history.h"
-
-MsnHistory *
-msn_history_new(void)
-{
-	MsnHistory *history = g_new0(MsnHistory, 1);
-
-	history->trId = 1;
-
-	history->queue = g_queue_new();
-
-	return history;
-}
-
-void
-msn_history_destroy(MsnHistory *history)
-{
-	MsnTransaction *trans;
-
-	while ((trans = g_queue_pop_head(history->queue)) != NULL)
-		msn_transaction_destroy(trans);
-
-	g_queue_free(history->queue);
-	g_free(history);
-}
-
-MsnTransaction *
-msn_history_find(MsnHistory *history, unsigned int trId)
-{
-	MsnTransaction *trans;
-	GList *list;
-
-	for (list = history->queue->head; list != NULL; list = list->next)
-	{
-		trans = list->data;
-		if (trans->trId == trId)
-			return trans;
-	}
-
-	return NULL;
-}
-
-void
-msn_history_add(MsnHistory *history, MsnTransaction *trans)
-{
-	GQueue *queue;
-	gsize max_elems;
-
-	g_return_if_fail(history != NULL);
-	g_return_if_fail(trans   != NULL);
-
-	queue = history->queue;
-
-	trans->trId = history->trId++;
-
-	g_queue_push_tail(queue, trans);
-
-	if (trans->cmdproc->servconn->type == MSN_SERVCONN_NS)
-		max_elems = MSN_NS_HIST_ELEMS;
-	else
-		max_elems = MSN_SB_HIST_ELEMS;
-
-	if (queue->length > max_elems)
-	{
-		trans = g_queue_pop_head(queue);
-		msn_transaction_destroy(trans);
-	}
-}
-
deleted file mode 100644
--- a/libpurple/protocols/msn/history.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * @file history.h MSN history functions
- *
- * purple
- *
- * Purple 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 MSN_HISTORY_H
-#define MSN_HISTORY_H
-
-#include "internal.h"
-
-typedef struct _MsnHistory MsnHistory;
-
-#include "transaction.h"
-
-#define MSN_NS_HIST_ELEMS 0x300
-#define MSN_SB_HIST_ELEMS 0x30
-
-/**
- * The history.
- */
-struct _MsnHistory
-{
-	GQueue *queue;
-	unsigned int trId;
-};
-
-MsnHistory *msn_history_new(void);
-void msn_history_destroy(MsnHistory *history);
-MsnTransaction *msn_history_find(MsnHistory *history, unsigned int triId);
-void msn_history_add(MsnHistory *history, MsnTransaction *trans);
-
-#endif /* MSN_HISTORY_H */
deleted file mode 100644
--- a/libpurple/protocols/msn/httpconn.c
+++ /dev/null
@@ -1,739 +0,0 @@
-/**
- * @file httpconn.c HTTP connection method
- *
- * purple
- *
- * Purple 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 "msn.h"
-#include "debug.h"
-#include "httpconn.h"
-
-typedef struct
-{
-	MsnHttpConn *httpconn;
-	char *body;
-	size_t body_len;
-} MsnHttpQueueData;
-
-static void
-msn_httpconn_process_queue(MsnHttpConn *httpconn)
-{
-	httpconn->waiting_response = FALSE;
-
-	if (httpconn->queue != NULL)
-	{
-		MsnHttpQueueData *queue_data;
-
-		queue_data = (MsnHttpQueueData *)httpconn->queue->data;
-
-		httpconn->queue = g_list_remove(httpconn->queue, queue_data);
-
-		msn_httpconn_write(queue_data->httpconn,
-						   queue_data->body,
-						   queue_data->body_len);
-
-		g_free(queue_data->body);
-		g_free(queue_data);
-	}
-}
-
-static gboolean
-msn_httpconn_parse_data(MsnHttpConn *httpconn, const char *buf,
-						size_t size, char **ret_buf, size_t *ret_size,
-						gboolean *error)
-{
-	const char *s, *c;
-	char *header, *body;
-	const char *body_start;
-	char *tmp;
-	size_t body_len = 0;
-
-	g_return_val_if_fail(httpconn != NULL, FALSE);
-	g_return_val_if_fail(buf      != NULL, FALSE);
-	g_return_val_if_fail(size      > 0,    FALSE);
-	g_return_val_if_fail(ret_buf  != NULL, FALSE);
-	g_return_val_if_fail(ret_size != NULL, FALSE);
-	g_return_val_if_fail(error    != NULL, FALSE);
-
-#if 0
-	purple_debug_info("msn", "HTTP: parsing data {%s}\n", buf);
-#endif
-
-	/* Healthy defaults. */
-	body = NULL;
-
-	*ret_buf  = NULL;
-	*ret_size = 0;
-	*error    = FALSE;
-
-	/* First, some tests to see if we have a full block of stuff. */
-	if (((strncmp(buf, "HTTP/1.1 200 OK\r\n", 17) != 0) &&
-		 (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) != 0)) &&
-		((strncmp(buf, "HTTP/1.0 200 OK\r\n", 17) != 0) &&
-		 (strncmp(buf, "HTTP/1.0 100 Continue\r\n", 23) != 0)))
-	{
-		*error = TRUE;
-
-		return FALSE;
-	}
-
-	if (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) == 0)
-	{
-		if ((s = strstr(buf, "\r\n\r\n")) == NULL)
-			return FALSE;
-
-		s += 4;
-
-		if (*s == '\0')
-		{
-			*ret_buf = g_strdup("");
-			*ret_size = 0;
-
-			msn_httpconn_process_queue(httpconn);
-
-			return TRUE;
-		}
-
-		size -= (s - buf);
-		buf = s;
-	}
-
-	if ((s = strstr(buf, "\r\n\r\n")) == NULL)
-		/* Need to wait for the full HTTP header to arrive */
-		return FALSE;
-
-	s += 4; /* Skip \r\n\r\n */
-	header = g_strndup(buf, s - buf);
-	body_start = s;
-	body_len = size - (body_start - buf);
-
-	if ((s = purple_strcasestr(header, "Content-Length: ")) != NULL)
-	{
-		size_t tmp_len;
-
-		s += strlen("Content-Length: ");
-
-		if ((c = strchr(s, '\r')) == NULL)
-		{
-			g_free(header);
-
-			return FALSE;
-		}
-
-		tmp = g_strndup(s, c - s);
-		tmp_len = atoi(tmp);
-		g_free(tmp);
-
-		if (body_len != tmp_len)
-		{
-			/* Need to wait for the full packet to arrive */
-
-			g_free(header);
-
-#if 0
-			purple_debug_warning("msn",
-							   "body length (%d) != content length (%d)\n",
-							   body_len, tmp_len);
-#endif
-
-			return FALSE;
-		}
-	}
-
-	body = g_malloc(body_len + 1);
-	memcpy(body, body_start, body_len);
-	body[body_len] = '\0';
-
-	if (purple_debug_is_verbose())
-		purple_debug_misc("msn", "Incoming HTTP buffer (header): {%s}\n",
-		                  header);
-
-	/* Now we should be able to process the data. */
-	if ((s = purple_strcasestr(header, "X-MSN-Messenger: ")) != NULL)
-	{
-		gchar *full_session_id = NULL, *gw_ip = NULL, *session_action = NULL;
-		char *t, *session_id;
-		char **elems, **cur, **tokens;
-
-		full_session_id = gw_ip = session_action = NULL;
-
-		s += strlen("X-MSN-Messenger: ");
-
-		if ((c = strchr(s, '\r')) == NULL)
-		{
-			msn_session_set_error(httpconn->session,
-								  MSN_ERROR_HTTP_MALFORMED, NULL);
-			purple_debug_error("msn", "Malformed X-MSN-Messenger field.\n{%s}\n",
-							 buf);
-
-			g_free(header);
-			g_free(body);
-			return FALSE;
-		}
-
-		tmp = g_strndup(s, c - s);
-
-		elems = g_strsplit(tmp, "; ", 0);
-
-		for (cur = elems; *cur != NULL; cur++)
-		{
-			tokens = g_strsplit(*cur, "=", 2);
-
-			if (strcmp(tokens[0], "SessionID") == 0) {
-				g_free(full_session_id);
-				full_session_id = tokens[1];
-			} else if (strcmp(tokens[0], "GW-IP") == 0) {
-				g_free(gw_ip);
-				gw_ip = tokens[1];
-			} else if (strcmp(tokens[0], "Session") == 0) {
-				g_free(session_action);
-				session_action = tokens[1];
-			} else
-				g_free(tokens[1]);
-
-			g_free(tokens[0]);
-			/* Don't free each of the tokens, only the array. */
-			g_free(tokens);
-		}
-
-		g_strfreev(elems);
-
-		g_free(tmp);
-
-		t = full_session_id ? strchr(full_session_id, '.') : NULL;
-		if (t != NULL)
-			session_id = g_strndup(full_session_id, t - full_session_id);
-		else {
-			purple_debug_error("msn", "Malformed full_session_id[%s]\n",
-					   full_session_id ? full_session_id : NULL);
-			session_id = g_strdup(full_session_id);
-		}
-
-		if (session_action == NULL || strcmp(session_action, "close") != 0)
-		{
-			g_free(httpconn->full_session_id);
-			httpconn->full_session_id = full_session_id;
-
-			g_free(httpconn->session_id);
-			httpconn->session_id = session_id;
-
-			g_free(httpconn->host);
-			httpconn->host = gw_ip;
-		}
-		else
-		{
-			/* I'll be honest, I don't fully understand all this, but this
-			 * causes crashes, Stu. */
-#if 0
-			MsnServConn *servconn;
-
-			/* It's going to die. */
-			/* poor thing */
-
-			servconn = httpconn->servconn;
-
-			if (servconn != NULL)
-				servconn->wasted = TRUE;
-#endif
-
-			g_free(full_session_id);
-			g_free(session_id);
-			g_free(gw_ip);
-		}
-
-		g_free(session_action);
-	}
-
-	g_free(header);
-
-	*ret_buf  = body;
-	*ret_size = body_len;
-
-	msn_httpconn_process_queue(httpconn);
-
-	return TRUE;
-}
-
-static void
-read_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
-	MsnHttpConn *httpconn;
-	MsnServConn *servconn;
-	char buf[MSN_BUF_LEN];
-	gssize len;
-	char *result_msg = NULL;
-	size_t result_len = 0;
-	gboolean error = FALSE;
-
-	httpconn = data;
-	servconn = httpconn->servconn;
-
-	if (servconn->type == MSN_SERVCONN_NS)
-		servconn->session->account->gc->last_received = time(NULL);
-
-	len = read(httpconn->fd, buf, sizeof(buf) - 1);
-	if (len < 0 && errno == EAGAIN)
-		return;
-	if (len <= 0) {
-		purple_debug_error("msn", "HTTP: servconn %03d read error, "
-			"len: %" G_GSSIZE_FORMAT ", errno: %d, error: %s\n",
-			servconn->num, len, error, g_strerror(errno));
-		msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ, NULL);
-
-		return;
-	}
-
-	buf[len] = '\0';
-
-	httpconn->rx_buf = g_realloc(httpconn->rx_buf, len + httpconn->rx_len + 1);
-	memcpy(httpconn->rx_buf + httpconn->rx_len, buf, len + 1);
-	httpconn->rx_len += len;
-
-	if (!msn_httpconn_parse_data(httpconn, httpconn->rx_buf, httpconn->rx_len,
-								 &result_msg, &result_len, &error))
-	{
-		/* Either we must wait for more input, or something went wrong */
-		if (error)
-			msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ, NULL);
-
-		return;
-	}
-
-	if (error)
-	{
-		purple_debug_error("msn", "HTTP: Special error\n");
-		msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ, NULL);
-
-		return;
-	}
-
-	g_free(httpconn->rx_buf);
-	httpconn->rx_buf = NULL;
-	httpconn->rx_len = 0;
-
-	if (result_len == 0)
-	{
-		/* Nothing to do here */
-#if 0
-		purple_debug_info("msn", "HTTP: nothing to do here\n");
-#endif
-		g_free(result_msg);
-		return;
-	}
-
-	g_free(servconn->rx_buf);
-	servconn->rx_buf = result_msg;
-	servconn->rx_len = result_len;
-
-	msn_servconn_process_data(servconn);
-}
-
-static void
-httpconn_write_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
-	MsnHttpConn *httpconn;
-	gssize ret;
-	int writelen;
-
-	httpconn = data;
-	writelen = purple_circ_buffer_get_max_read(httpconn->tx_buf);
-
-	if (writelen == 0)
-	{
-		purple_input_remove(httpconn->tx_handler);
-		httpconn->tx_handler = 0;
-		return;
-	}
-
-	ret = write(httpconn->fd, httpconn->tx_buf->outptr, writelen);
-	if (ret <= 0)
-	{
-		if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-			/* No worries */
-			return;
-
-		/* Error! */
-		msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_WRITE, NULL);
-		return;
-	}
-
-	purple_circ_buffer_mark_read(httpconn->tx_buf, ret);
-
-	/* TODO: I don't think these 2 lines are needed.  Remove them? */
-	if (ret == writelen)
-		httpconn_write_cb(data, source, cond);
-}
-
-static gboolean
-write_raw(MsnHttpConn *httpconn, const char *data, size_t data_len)
-{
-	gssize res; /* result of the write operation */
-
-	if (httpconn->tx_handler == 0)
-		res = write(httpconn->fd, data, data_len);
-	else
-	{
-		res = -1;
-		errno = EAGAIN;
-	}
-
-	if ((res <= 0) && ((errno != EAGAIN) && (errno != EWOULDBLOCK)))
-	{
-		msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_WRITE, NULL);
-		return FALSE;
-	}
-
-	if (res < 0 || (size_t)res < data_len)
-	{
-		if (res < 0)
-			res = 0;
-		if (httpconn->tx_handler == 0 && httpconn->fd)
-			httpconn->tx_handler = purple_input_add(httpconn->fd,
-				PURPLE_INPUT_WRITE, httpconn_write_cb, httpconn);
-		purple_circ_buffer_append(httpconn->tx_buf, data + res,
-			data_len - res);
-	}
-
-	return TRUE;
-}
-
-static char *
-msn_httpconn_proxy_auth(MsnHttpConn *httpconn)
-{
-	PurpleAccount *account;
-	PurpleProxyInfo *gpi;
-	const char *username, *password;
-	char *auth = NULL;
-
-	account = httpconn->session->account;
-
-	gpi = purple_proxy_get_setup(account);
-
-	if (gpi == NULL || !(purple_proxy_info_get_type(gpi) == PURPLE_PROXY_HTTP ||
-						 purple_proxy_info_get_type(gpi) == PURPLE_PROXY_USE_ENVVAR))
-		return NULL;
-
-	username = purple_proxy_info_get_username(gpi);
-	password = purple_proxy_info_get_password(gpi);
-
-	if (username != NULL) {
-		char *tmp;
-		auth = g_strdup_printf("%s:%s", username, password ? password : "");
-		tmp = purple_base64_encode((const guchar *)auth, strlen(auth));
-		g_free(auth);
-		auth = g_strdup_printf("Proxy-Authorization: Basic %s\r\n", tmp);
-		g_free(tmp);
-	}
-
-	return auth;
-}
-
-static gboolean
-msn_httpconn_poll(gpointer data)
-{
-	MsnHttpConn *httpconn;
-	char *header;
-	char *auth;
-
-	httpconn = data;
-
-	g_return_val_if_fail(httpconn != NULL, FALSE);
-
-	if ((httpconn->host == NULL) || (httpconn->full_session_id == NULL))
-	{
-		/* There's no need to poll if the session is not fully established */
-		return TRUE;
-	}
-
-	if (httpconn->waiting_response)
-	{
-		/* There's no need to poll if we're already waiting for a response */
-		return TRUE;
-	}
-
-	auth = msn_httpconn_proxy_auth(httpconn);
-
-	header = g_strdup_printf(
-		"POST http://%s/gateway/gateway.dll?Action=poll&SessionID=%s HTTP/1.1\r\n"
-		"Accept: */*\r\n"
-		"Accept-Language: en-us\r\n"
-		"User-Agent: MSMSGS\r\n"
-		"Host: %s\r\n"
-		"Proxy-Connection: Keep-Alive\r\n"
-		"%s" /* Proxy auth */
-		"Connection: Keep-Alive\r\n"
-		"Pragma: no-cache\r\n"
-		"Content-Type: application/x-msn-messenger\r\n"
-		"Content-Length: 0\r\n\r\n",
-		httpconn->host,
-		httpconn->full_session_id,
-		httpconn->host,
-		auth ? auth : "");
-
-	g_free(auth);
-
-	if (write_raw(httpconn, header, strlen(header)))
-		httpconn->waiting_response = TRUE;
-
-	g_free(header);
-
-	return TRUE;
-}
-
-gssize
-msn_httpconn_write(MsnHttpConn *httpconn, const char *body, size_t body_len)
-{
-	char *params;
-	char *data;
-	int header_len;
-	char *auth;
-	const char *server_types[] = { "NS", "SB" };
-	const char *server_type;
-	char *host;
-	MsnServConn *servconn;
-
-	/* TODO: remove http data from servconn */
-
-	g_return_val_if_fail(httpconn != NULL, 0);
-	g_return_val_if_fail(body != NULL, 0);
-	g_return_val_if_fail(body_len > 0, 0);
-
-	servconn = httpconn->servconn;
-
-	if (httpconn->waiting_response)
-	{
-		MsnHttpQueueData *queue_data = g_new0(MsnHttpQueueData, 1);
-
-		queue_data->httpconn = httpconn;
-		queue_data->body     = g_memdup(body, body_len);
-		queue_data->body_len = body_len;
-
-		httpconn->queue = g_list_append(httpconn->queue, queue_data);
-
-		return body_len;
-	}
-
-	server_type = server_types[servconn->type];
-
-	if (httpconn->virgin)
-	{
-		/* QuLogic: This doesn't look right to me, but it still seems to work */
-		host = MSN_HTTPCONN_SERVER;
-
-		/* The first time servconn->host is the host we should connect to. */
-		params = g_strdup_printf("Action=open&Server=%s&IP=%s",
-								 server_type,
-								 servconn->host);
-		httpconn->virgin = FALSE;
-	}
-	else
-	{
-		/* The rest of the times servconn->host is the gateway host. */
-		host = httpconn->host;
-
-		if (host == NULL || httpconn->full_session_id == NULL)
-		{
-			purple_debug_warning("msn", "Attempted HTTP write before session is established\n");
-			return -1;
-		}
-
-		params = g_strdup_printf("SessionID=%s",
-			httpconn->full_session_id);
-	}
-
-	auth = msn_httpconn_proxy_auth(httpconn);
-
-	data = g_strdup_printf(
-		"POST http://%s/gateway/gateway.dll?%s HTTP/1.1\r\n"
-		"Accept: */*\r\n"
-		"Accept-Language: en-us\r\n"
-		"User-Agent: MSMSGS\r\n"
-		"Host: %s\r\n"
-		"Proxy-Connection: Keep-Alive\r\n"
-		"%s" /* Proxy auth */
-		"Connection: Keep-Alive\r\n"
-		"Pragma: no-cache\r\n"
-		"Content-Type: application/x-msn-messenger\r\n"
-		"Content-Length: %d\r\n\r\n",
-		host,
-		params,
-		host,
-		auth ? auth : "",
-		(int) body_len);
-
-	g_free(params);
-
-	g_free(auth);
-
-	header_len = strlen(data);
-	data = g_realloc(data, header_len + body_len);
-	memcpy(data + header_len, body, body_len);
-
-	if (write_raw(httpconn, data, header_len + body_len))
-		httpconn->waiting_response = TRUE;
-
-	g_free(data);
-
-	return body_len;
-}
-
-MsnHttpConn *
-msn_httpconn_new(MsnServConn *servconn)
-{
-	MsnHttpConn *httpconn;
-
-	g_return_val_if_fail(servconn != NULL, NULL);
-
-	httpconn = g_new0(MsnHttpConn, 1);
-
-	purple_debug_info("msn", "new httpconn (%p)\n", httpconn);
-
-	/* TODO: Remove this */
-	httpconn->session = servconn->session;
-
-	httpconn->servconn = servconn;
-
-	httpconn->tx_buf = purple_circ_buffer_new(MSN_BUF_LEN);
-	httpconn->tx_handler = 0;
-
-	httpconn->fd = -1;
-
-	return httpconn;
-}
-
-void
-msn_httpconn_destroy(MsnHttpConn *httpconn)
-{
-	g_return_if_fail(httpconn != NULL);
-
-	purple_debug_info("msn", "destroy httpconn (%p)\n", httpconn);
-
-	if (httpconn->connected)
-		msn_httpconn_disconnect(httpconn);
-
-	g_free(httpconn->full_session_id);
-
-	g_free(httpconn->session_id);
-
-	g_free(httpconn->host);
-
-	while (httpconn->queue != NULL) {
-		MsnHttpQueueData *queue_data;
-
-		queue_data = (MsnHttpQueueData *) httpconn->queue->data;
-
-		httpconn->queue = g_list_delete_link(httpconn->queue, httpconn->queue);
-
-		g_free(queue_data->body);
-		g_free(queue_data);
-	}
-
-	purple_circ_buffer_destroy(httpconn->tx_buf);
-	if (httpconn->tx_handler > 0)
-		purple_input_remove(httpconn->tx_handler);
-
-	g_free(httpconn);
-}
-
-static void
-connect_cb(gpointer data, gint source, const gchar *error_message)
-{
-	MsnHttpConn *httpconn;
-
-	httpconn = data;
-	httpconn->connect_data = NULL;
-	httpconn->fd = source;
-
-	if (source >= 0)
-	{
-		httpconn->inpa = purple_input_add(httpconn->fd, PURPLE_INPUT_READ,
-			read_cb, data);
-
-		httpconn->timer = purple_timeout_add_seconds(2, msn_httpconn_poll, httpconn);
-
-		msn_httpconn_process_queue(httpconn);
-	}
-	else
-	{
-		purple_debug_error("msn", "HTTP: Connection error: %s\n",
-		                   error_message ? error_message : "(null)");
-		msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_CONNECT, error_message);
-	}
-}
-
-gboolean
-msn_httpconn_connect(MsnHttpConn *httpconn, const char *host, int port)
-{
-	g_return_val_if_fail(httpconn != NULL, FALSE);
-	g_return_val_if_fail(host     != NULL, FALSE);
-	g_return_val_if_fail(port      > 0,    FALSE);
-
-	if (httpconn->connected)
-		msn_httpconn_disconnect(httpconn);
-
-	httpconn->connect_data = purple_proxy_connect(NULL, httpconn->session->account,
-		host, 80, connect_cb, httpconn);
-
-	if (httpconn->connect_data != NULL)
-	{
-		httpconn->waiting_response = TRUE;
-		httpconn->connected = TRUE;
-	}
-
-	return httpconn->connected;
-}
-
-void
-msn_httpconn_disconnect(MsnHttpConn *httpconn)
-{
-	g_return_if_fail(httpconn != NULL);
-
-	if (!httpconn->connected)
-		return;
-
-	if (httpconn->connect_data != NULL)
-	{
-		purple_proxy_connect_cancel(httpconn->connect_data);
-		httpconn->connect_data = NULL;
-	}
-
-	if (httpconn->timer)
-	{
-		purple_timeout_remove(httpconn->timer);
-		httpconn->timer = 0;
-	}
-
-	if (httpconn->inpa > 0)
-	{
-		purple_input_remove(httpconn->inpa);
-		httpconn->inpa = 0;
-	}
-
-	close(httpconn->fd);
-	httpconn->fd = -1;
-
-	g_free(httpconn->rx_buf);
-	httpconn->rx_buf = NULL;
-	httpconn->rx_len = 0;
-
-	httpconn->connected = FALSE;
-
-	/* msn_servconn_disconnect(httpconn->servconn); */
-}
deleted file mode 100644
--- a/libpurple/protocols/msn/httpconn.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/**
- * @file httpconn.h HTTP connection
- *
- * purple
- *
- * Purple 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 MSN_HTTPCONN_H
-#define MSN_HTTPCONN_H
-
-typedef struct _MsnHttpConn MsnHttpConn;
-
-#include "circbuffer.h"
-#include "servconn.h"
-#include "session.h"
-
-/**
- * An HTTP Connection.
- */
-struct _MsnHttpConn
-{
-	MsnSession *session; /**< The MSN Session. */
-	MsnServConn *servconn; /**< The connection object. */
-
-	PurpleProxyConnectData *connect_data;
-
-	char *full_session_id; /**< The full session id. */
-	char *session_id; /**< The trimmed session id. */
-
-	int timer; /**< The timer for polling. */
-
-	gboolean waiting_response; /**< The flag that states if we are waiting
-								 a response from the server. */
-	gboolean connected;        /**< The flag that states if the connection is on. */
-	gboolean virgin;           /**< The flag that states if this connection
-								 should specify the host (not gateway) to
-								 connect to. */
-
-	char *host; /**< The HTTP gateway host. */
-	GList *queue; /**< The queue of data chunks to write. */
-
-	int fd; /**< The connection's file descriptor. */
-	guint inpa; /**< The connection's input handler. */
-
-	char *rx_buf; /**< The receive buffer. */
-	int rx_len; /**< The receive buffer length. */
-
-	PurpleCircBuffer *tx_buf;
-	guint tx_handler;
-};
-
-/**
- * Creates a new HTTP connection object.
- *
- * @param servconn The connection object.
- *
- * @return The new object.
- */
-MsnHttpConn *msn_httpconn_new(MsnServConn *servconn);
-
-/**
- * Destroys an HTTP connection object.
- *
- * @param httpconn The HTTP connection object.
- */
-void msn_httpconn_destroy(MsnHttpConn *httpconn);
-
-/**
- * Writes a chunk of data to the HTTP connection.
- *
- * @param servconn    The server connection.
- * @param data        The data to write.
- * @param data_len    The size of the data to write.
- *
- * @return The number of bytes written.
- */
-gssize msn_httpconn_write(MsnHttpConn *httpconn, const char *data, size_t data_len);
-
-/**
- * Connects the HTTP connection object to a host.
- *
- * @param httpconn The HTTP connection object.
- * @param host The host to connect to.
- * @param port The port to connect to.
- */
-gboolean msn_httpconn_connect(MsnHttpConn *httpconn,
-							  const char *host, int port);
-
-/**
- * Disconnects the HTTP connection object.
- *
- * @param httpconn The HTTP connection object.
- */
-void msn_httpconn_disconnect(MsnHttpConn *httpconn);
-
-#endif /* MSN_HTTPCONN_H */
deleted file mode 100644
--- a/libpurple/protocols/msn/moz.build
+++ /dev/null
@@ -1,45 +0,0 @@
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-SOURCES += [
-    'cmdproc.c',
-    'command.c',
-    'contact.c',
-    'directconn.c',
-    'error.c',
-    'group.c',
-    'history.c',
-    'httpconn.c',
-    'msg.c',
-    'msn.c',
-    'msnutils.c',
-    'nexus.c',
-    'notification.c',
-    'object.c',
-    'oim.c',
-    'p2p.c',
-    'page.c',
-    'sbconn.c',
-    'servconn.c',
-    'session.c',
-    'slp.c',
-    'slpcall.c',
-    'slplink.c',
-    'slpmsg.c',
-    'slpmsg_part.c',
-    'soap.c',
-    'state.c',
-    'switchboard.c',
-    'table.c',
-    'tlv.c',
-    'transaction.c',
-    'user.c',
-    'userlist.c',
-    'xfer.c',
-]
-
-protocol = 'msn'
-
-include('../prpl.py')
deleted file mode 100644
--- a/libpurple/protocols/msn/msg.c
+++ /dev/null
@@ -1,1219 +0,0 @@
-/**
- * @file msg.c Message functions
- *
- * purple
- *
- * Purple 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 "debug.h"
-
-#include "msn.h"
-#include "msg.h"
-#include "msnutils.h"
-#include "slpmsg.h"
-#include "slpmsg_part.h"
-
-MsnMessage *
-msn_message_new(MsnMsgType type)
-{
-	MsnMessage *msg;
-
-	msg = g_new0(MsnMessage, 1);
-	msg->type = type;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "message new (%p)(%d)\n", msg, type);
-
-	msg->header_table = g_hash_table_new_full(g_str_hash, g_str_equal,
-											g_free, g_free);
-
-	msn_message_ref(msg);
-
-	return msg;
-}
-
-/**
- * Destroys a message.
- *
- * @param msg The message to destroy.
- */
-static void
-msn_message_destroy(MsnMessage *msg)
-{
-	g_return_if_fail(msg != NULL);
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "message destroy (%p)\n", msg);
-
-	g_free(msg->remote_user);
-	g_free(msg->body);
-	g_free(msg->content_type);
-	g_free(msg->charset);
-
-	g_hash_table_destroy(msg->header_table);
-	g_list_free(msg->header_list);
-	if (msg->part)
-		msn_slpmsgpart_unref(msg->part);
-
-	g_free(msg);
-}
-
-MsnMessage *
-msn_message_ref(MsnMessage *msg)
-{
-	g_return_val_if_fail(msg != NULL, NULL);
-
-	msg->ref_count++;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "message ref (%p)[%u]\n", msg, msg->ref_count);
-
-	return msg;
-}
-
-void
-msn_message_unref(MsnMessage *msg)
-{
-	g_return_if_fail(msg != NULL);
-	g_return_if_fail(msg->ref_count > 0);
-
-	msg->ref_count--;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "message unref (%p)[%u]\n", msg, msg->ref_count);
-
-	if (msg->ref_count == 0)
-		msn_message_destroy(msg);
-}
-
-MsnMessage *
-msn_message_new_plain(const char *message)
-{
-	MsnMessage *msg;
-	char *message_cr;
-
-	msg = msn_message_new(MSN_MSG_TEXT);
-	msg->retries = 1;
-	msn_message_set_header(msg, "User-Agent", PACKAGE_NAME "/" VERSION);
-	msn_message_set_content_type(msg, "text/plain");
-	msn_message_set_charset(msg, "UTF-8");
-	msn_message_set_flag(msg, 'A');
-	msn_message_set_header(msg, "X-MMS-IM-Format",
-						 "FN=Segoe%20UI; EF=; CO=0; CS=1;PF=0");
-
-	message_cr = purple_str_add_cr(message);
-	msn_message_set_bin_data(msg, message_cr, strlen(message_cr));
-	g_free(message_cr);
-
-	return msg;
-}
-
-MsnMessage *
-msn_message_new_msnslp(void)
-{
-	MsnMessage *msg;
-
-	msg = msn_message_new(MSN_MSG_SLP);
-
-	msn_message_set_header(msg, "User-Agent", NULL);
-
-	msn_message_set_flag(msg, 'D');
-	msn_message_set_content_type(msg, "application/x-msnmsgrp2p");
-
-	return msg;
-}
-
-MsnMessage *
-msn_message_new_nudge(void)
-{
-	MsnMessage *msg;
-
-	msg = msn_message_new(MSN_MSG_NUDGE);
-	msn_message_set_content_type(msg, "text/x-msnmsgr-datacast");
-	msn_message_set_flag(msg, 'N');
-	msn_message_set_bin_data(msg, "ID: 1\r\n", 7);
-
-	return msg;
-}
-
-void
-msn_message_parse_payload(MsnMessage *msg,
-						  const char *payload, size_t payload_len,
-						  const char *line_dem,const char *body_dem)
-{
-	char *tmp_base, *tmp;
-	const char *content_type;
-	char *end;
-	char **elems, **cur, **tokens;
-
-	g_return_if_fail(payload != NULL);
-	tmp_base = tmp = g_malloc(payload_len + 1);
-	memcpy(tmp_base, payload, payload_len);
-	tmp_base[payload_len] = '\0';
-
-	/* Find the end of the headers */
-	end = strstr(tmp, body_dem);
-	/* TODO? some clients use \r delimiters instead of \r\n, the official client
-	 * doesn't send such messages, but does handle receiving them. We'll just
-	 * avoid crashing for now */
-	if (end == NULL) {
-		g_free(tmp_base);
-		g_return_if_reached();
-	}
-
-	/* NUL-terminate the end of the headers - it'll get skipped over below */
-	*end = '\0';
-
-	/* Split the headers and parse each one */
-	elems = g_strsplit(tmp, line_dem, 0);
-	for (cur = elems; *cur != NULL; cur++)
-	{
-		const char *key, *value;
-
-		/* If this line starts with whitespace, it's been folded from the
-		   previous line and won't have ':'. */
-		if ((**cur == ' ') || (**cur == '\t')) {
-			tokens = g_strsplit(g_strchug(*cur), "=\"", 2);
-			key = tokens[0];
-			value = tokens[1];
-
-			/* The only one I care about is 'boundary' (which is folded from
-			   the key 'Content-Type'), so only process that. */
-			if (!strcmp(key, "boundary") && value) {
-				char *end = strchr(value, '\"');
-				if (end) {
-					*end = '\0';
-					msn_message_set_header(msg, key, value);
-				}
-			}
-
-			g_strfreev(tokens);
-			continue;
-		}
-
-		tokens = g_strsplit(*cur, ": ", 2);
-
-		key = tokens[0];
-		value = tokens[1];
-
-		if (!strcmp(key, "MIME-Version"))
-		{
-			/* Ignore MIME-Version header */
-		}
-		else if (!strcmp(key, "Content-Type"))
-		{
-			char *charset, *c;
-
-			if (value && (c = strchr(value, ';')) != NULL)
-			{
-				if ((charset = strchr(c, '=')) != NULL)
-				{
-					charset++;
-					msn_message_set_charset(msg, charset);
-				}
-
-				*c = '\0';
-			}
-
-			msn_message_set_content_type(msg, value);
-		}
-		else
-		{
-			msn_message_set_header(msg, key, value);
-		}
-
-		g_strfreev(tokens);
-	}
-	g_strfreev(elems);
-
-	/* Proceed to the end of the "\r\n\r\n" */
-	tmp = end + strlen(body_dem);
-
-	/* Now we *should* be at the body. */
-	content_type = msn_message_get_content_type(msg);
-
-	if (payload_len - (tmp - tmp_base) > 0) {
-		msg->body_len = payload_len - (tmp - tmp_base);
-		g_free(msg->body);
-		msg->body = g_malloc(msg->body_len + 1);
-		memcpy(msg->body, tmp, msg->body_len);
-		msg->body[msg->body_len] = '\0';
-	}
-
-	if (msg->body && content_type && purple_str_has_prefix(content_type, "text/")) {
-		char *body = NULL;
-
-		if (msg->charset == NULL || g_str_equal(msg->charset, "UTF-8")) {
-			/* Charset is UTF-8 */
-			if (!g_utf8_validate(msg->body, msg->body_len, NULL)) {
-				purple_debug_warning("msn", "Message contains invalid "
-						"UTF-8. Attempting to salvage.\n");
-				body = purple_utf8_salvage(msg->body);
-				payload_len = strlen(body);
-			}
-		} else {
-			/* Charset is something other than UTF-8 */
-			GError *err = NULL;
-			body = g_convert(msg->body, msg->body_len, "UTF-8",
-					msg->charset, NULL, &payload_len, &err);
-			if (!body || err) {
-				purple_debug_warning("msn", "Unable to convert message from "
-						"%s to UTF-8: %s\n", msg->charset,
-						err ? err->message : "Unknown error");
-				if (err)
-					g_error_free(err);
-
-				/* Fallback to ISO-8859-1 */
-				g_free(body);
-				body = g_convert(msg->body, msg->body_len, "UTF-8",
-						"ISO-8859-1", NULL, &payload_len, NULL);
-				if (!body) {
-					g_free(msg->body);
-					msg->body = NULL;
-					msg->body_len = 0;
-				}
-			}
-		}
-
-		if (body) {
-			g_free(msg->body);
-			msg->body = body;
-			msg->body_len = payload_len;
-			msn_message_set_charset(msg, "UTF-8");
-		}
-	}
-
-	g_free(tmp_base);
-}
-
-MsnMessage *
-msn_message_new_from_cmd(MsnSession *session, MsnCommand *cmd)
-{
-	MsnMessage *msg;
-
-	g_return_val_if_fail(cmd != NULL, NULL);
-
-	msg = msn_message_new(MSN_MSG_UNKNOWN);
-
-	msg->remote_user = g_strdup(cmd->params[0]);
-	/* msg->size = atoi(cmd->params[2]); */
-	msg->cmd = cmd;
-
-	return msg;
-}
-
-char *
-msn_message_gen_payload(MsnMessage *msg, size_t *ret_size)
-{
-	GList *l;
-	char *n, *base, *end;
-	int len;
-	size_t body_len = 0;
-	const void *body;
-
-	g_return_val_if_fail(msg != NULL, NULL);
-
-	len = MSN_BUF_LEN;
-
-	base = n = end = g_malloc(len + 1);
-	end += len;
-
-	/* Standard header. */
-	if (msg->charset == NULL)
-	{
-		g_snprintf(n, len,
-				   "MIME-Version: 1.0\r\n"
-				   "Content-Type: %s\r\n",
-				   msg->content_type);
-	}
-	else
-	{
-		g_snprintf(n, len,
-				   "MIME-Version: 1.0\r\n"
-				   "Content-Type: %s; charset=%s\r\n",
-				   msg->content_type, msg->charset);
-	}
-
-	n += strlen(n);
-
-	for (l = msg->header_list; l != NULL; l = l->next)
-	{
-		const char *key;
-		const char *value;
-
-		key = l->data;
-		value = msn_message_get_header_value(msg, key);
-
-		g_snprintf(n, end - n, "%s: %s\r\n", key, value);
-		n += strlen(n);
-	}
-
-	if ((end - n) > 2)
-		n += g_strlcpy(n, "\r\n", end - n);
-
-	body = msn_message_get_bin_data(msg, &body_len);
-
-	if (body != NULL && (end - n) > (gssize)body_len)
-	{
-		memcpy(n, body, body_len);
-		n += body_len;
-		*n = '\0';
-	}
-
-	if (ret_size != NULL)
-	{
-		*ret_size = n - base;
-
-		if (*ret_size > 1664)
-			*ret_size = 1664;
-	}
-
-	return base;
-}
-
-void
-msn_message_set_flag(MsnMessage *msg, char flag)
-{
-	g_return_if_fail(msg != NULL);
-	g_return_if_fail(flag != 0);
-
-	msg->flag = flag;
-}
-
-char
-msn_message_get_flag(const MsnMessage *msg)
-{
-	g_return_val_if_fail(msg != NULL, 0);
-
-	return msg->flag;
-}
-
-void
-msn_message_set_bin_data(MsnMessage *msg, const void *data, size_t len)
-{
-	g_return_if_fail(msg != NULL);
-
-	/* There is no need to waste memory on data we cannot send anyway */
-	if (len > 1664)
-		len = 1664;
-
-	if (msg->body != NULL)
-		g_free(msg->body);
-
-	if (data != NULL && len > 0)
-	{
-		msg->body = g_malloc(len + 1);
-		memcpy(msg->body, data, len);
-		msg->body[len] = '\0';
-		msg->body_len = len;
-	}
-	else
-	{
-		msg->body = NULL;
-		msg->body_len = 0;
-	}
-}
-
-const void *
-msn_message_get_bin_data(const MsnMessage *msg, size_t *len)
-{
-	g_return_val_if_fail(msg != NULL, NULL);
-
-	if (len)
-		*len = msg->body_len;
-
-	return msg->body;
-}
-
-void
-msn_message_set_content_type(MsnMessage *msg, const char *type)
-{
-	g_return_if_fail(msg != NULL);
-
-	g_free(msg->content_type);
-	msg->content_type = g_strdup(type);
-}
-
-const char *
-msn_message_get_content_type(const MsnMessage *msg)
-{
-	g_return_val_if_fail(msg != NULL, NULL);
-
-	return msg->content_type;
-}
-
-void
-msn_message_set_charset(MsnMessage *msg, const char *charset)
-{
-	g_return_if_fail(msg != NULL);
-
-	g_free(msg->charset);
-	msg->charset = g_strdup(charset);
-}
-
-const char *
-msn_message_get_charset(const MsnMessage *msg)
-{
-	g_return_val_if_fail(msg != NULL, NULL);
-
-	return msg->charset;
-}
-
-void
-msn_message_set_header(MsnMessage *msg, const char *name, const char *value)
-{
-	const char *temp;
-	char *new_name;
-
-	g_return_if_fail(msg != NULL);
-	g_return_if_fail(name != NULL);
-
-	temp = msn_message_get_header_value(msg, name);
-
-	if (value == NULL)
-	{
-		if (temp != NULL)
-		{
-			GList *l;
-
-			for (l = msg->header_list; l != NULL; l = l->next)
-			{
-				if (!g_ascii_strcasecmp(l->data, name))
-				{
-					msg->header_list = g_list_remove(msg->header_list, l->data);
-
-					break;
-				}
-			}
-
-			g_hash_table_remove(msg->header_table, name);
-		}
-
-		return;
-	}
-
-	new_name = g_strdup(name);
-
-	g_hash_table_insert(msg->header_table, new_name, g_strdup(value));
-
-	if (temp == NULL)
-		msg->header_list = g_list_append(msg->header_list, new_name);
-}
-
-const char *
-msn_message_get_header_value(const MsnMessage *msg, const char *name)
-{
-	g_return_val_if_fail(msg != NULL, NULL);
-	g_return_val_if_fail(name != NULL, NULL);
-
-	return g_hash_table_lookup(msg->header_table, name);
-}
-
-GHashTable *
-msn_message_get_hashtable_from_body(const MsnMessage *msg)
-{
-	GHashTable *table;
-	size_t body_len;
-	const char *body;
-	char **elems, **cur, **tokens, *body_str;
-
-	g_return_val_if_fail(msg != NULL, NULL);
-
-	table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-
-	body = msn_message_get_bin_data(msg, &body_len);
-
-	g_return_val_if_fail(body != NULL, NULL);
-
-	body_str = g_strndup(body, body_len);
-	elems = g_strsplit(body_str, "\r\n", 0);
-	g_free(body_str);
-
-	for (cur = elems; *cur != NULL; cur++)
-	{
-		if (**cur == '\0')
-			break;
-
-		tokens = g_strsplit(*cur, ": ", 2);
-
-		if (tokens[0] != NULL && tokens[1] != NULL) {
-			g_hash_table_insert(table, tokens[0], tokens[1]);
-			g_free(tokens);
-		} else
-			g_strfreev(tokens);
-	}
-
-	g_strfreev(elems);
-
-	return table;
-}
-
-char *
-msn_message_to_string(MsnMessage *msg)
-{
-	size_t body_len;
-	const char *body;
-
-	g_return_val_if_fail(msg != NULL, NULL);
-	g_return_val_if_fail(msg->type == MSN_MSG_TEXT, NULL);
-
-	body = msn_message_get_bin_data(msg, &body_len);
-
-	return g_strndup(body, body_len);
-}
-
-void
-msn_message_show_readable(MsnMessage *msg, const char *info,
-						  gboolean text_body)
-{
-	GString *str;
-	size_t body_len;
-	const char *body;
-	GList *l;
-
-	g_return_if_fail(msg != NULL);
-
-	str = g_string_new(NULL);
-
-	/* Standard header. */
-	if (msg->charset == NULL)
-	{
-		g_string_append_printf(str,
-				   "MIME-Version: 1.0\r\n"
-				   "Content-Type: %s\r\n",
-				   msg->content_type);
-	}
-	else
-	{
-		g_string_append_printf(str,
-				   "MIME-Version: 1.0\r\n"
-				   "Content-Type: %s; charset=%s\r\n",
-				   msg->content_type, msg->charset);
-	}
-
-	for (l = msg->header_list; l; l = l->next)
-	{
-		char *key;
-		const char *value;
-
-		key = l->data;
-		value = msn_message_get_header_value(msg, key);
-
-		g_string_append_printf(str, "%s: %s\r\n", key, value);
-	}
-
-	g_string_append(str, "\r\n");
-
-	body = msn_message_get_bin_data(msg, &body_len);
-
-	if (body != NULL)
-	{
-		if (msg->type == MSN_MSG_TEXT)
-		{
-			g_string_append_len(str, body, body_len);
-			g_string_append(str, "\r\n");
-		}
-		else
-		{
-			size_t i;
-			for (i = 0; i < body_len; i++, body++)
-			{
-				g_string_append_printf(str, "%02x ", (unsigned char)*body);
-				if (i % 16 == 0 && i != 0)
-					g_string_append_c(str, '\n');
-			}
-			g_string_append_c(str, '\n');
-		}
-	}
-
-	purple_debug_info("msn", "Message %s:\n{%s}\n", info, str->str);
-
-	g_string_free(str, TRUE);
-}
-
-/**************************************************************************
- * Message Handlers
- **************************************************************************/
-void
-msn_plain_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	PurpleConnection *gc;
-	const char *body;
-	char *body_enc;
-	char *body_final;
-	size_t body_len;
-	const char *passport;
-	const char *value;
-
-	gc = cmdproc->session->account->gc;
-
-	body = msn_message_get_bin_data(msg, &body_len);
-	body_enc = g_markup_escape_text(body, body_len);
-
-	passport = msg->remote_user;
-
-	if (!strcmp(passport, "messenger@microsoft.com") &&
-		strstr(body, "immediate security update"))
-	{
-		return;
-	}
-
-#if 0
-	if ((value = msn_message_get_header_value(msg, "User-Agent")) != NULL)
-	{
-		purple_debug_misc("msn", "User-Agent = '%s'\n", value);
-	}
-#endif
-
-	if ((value = msn_message_get_header_value(msg, "X-MMS-IM-Format")) != NULL)
-	{
-		char *pre, *post;
-
-		msn_parse_format(value, &pre, &post);
-
-		body_final = g_strdup_printf("%s%s%s", pre ? pre : "",
-									 body_enc ? body_enc : "", post ? post : "");
-
-		g_free(pre);
-		g_free(post);
-		g_free(body_enc);
-	}
-	else
-	{
-		body_final = body_enc;
-	}
-
-	if (cmdproc->servconn->type == MSN_SERVCONN_SB) {
-		MsnSwitchBoard *swboard = cmdproc->data;
-
-		swboard->flag |= MSN_SB_FLAG_IM;
-
-		if (swboard->current_users > 1 ||
-			((swboard->conv != NULL) &&
-			 purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
-		{
-			/* If current_users is always ok as it should then there is no need to
-			 * check if this is a chat. */
-			if (swboard->current_users <= 1)
-				purple_debug_misc("msn", "plain_msg: current_users(%d)\n",
-								swboard->current_users);
-
-			serv_got_chat_in(gc, swboard->chat_id, passport, 0, body_final,
-							 time(NULL));
-			if (swboard->conv == NULL)
-			{
-				swboard->conv = purple_find_chat(gc, swboard->chat_id);
-				swboard->flag |= MSN_SB_FLAG_IM;
-			}
-		}
-		else if (!g_str_equal(passport, purple_account_get_username(gc->account)))
-		{
-			/* Don't im ourselves ... */
-			serv_got_im(gc, passport, body_final, 0, time(NULL));
-			if (swboard->conv == NULL)
-			{
-				swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
-										passport, purple_connection_get_account(gc));
-				swboard->flag |= MSN_SB_FLAG_IM;
-			}
-		}
-
-	} else {
-		serv_got_im(gc, passport, body_final, 0, time(NULL));
-	}
-
-	g_free(body_final);
-}
-
-void
-msn_control_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	PurpleConnection *gc;
-	char *passport;
-
-	gc = cmdproc->session->account->gc;
-	passport = msg->remote_user;
-
-	if (msn_message_get_header_value(msg, "TypingUser") == NULL)
-		return;
-
-	if (cmdproc->servconn->type == MSN_SERVCONN_SB) {
-		MsnSwitchBoard *swboard = cmdproc->data;
-
-		if (swboard->current_users == 1)
-		{
-			serv_got_typing(gc, passport, MSN_TYPING_RECV_TIMEOUT,
-							PURPLE_TYPING);
-		}
-
-	} else {
-		serv_got_typing(gc, passport, MSN_TYPING_RECV_TIMEOUT,
-						PURPLE_TYPING);
-	}
-}
-
-static void
-datacast_inform_user(MsnSwitchBoard *swboard, const char *who,
-                     const char *msg, const char *filename)
-{
-	char *username, *str;
-	PurpleAccount *account;
-	PurpleBuddy *b;
-	PurpleConnection *pc;
-	gboolean chat;
-
-	account = swboard->session->account;
-	pc = purple_account_get_connection(account);
-
-	if ((b = purple_find_buddy(account, who)) != NULL)
-		username = g_markup_escape_text(purple_buddy_get_alias(b), -1);
-	else
-		username = g_markup_escape_text(who, -1);
-	str = g_strdup_printf(msg, username, filename);
-	g_free(username);
-
-	swboard->flag |= MSN_SB_FLAG_IM;
-	if (swboard->current_users > 1)
-		chat = TRUE;
-	else
-		chat = FALSE;
-
-	if (swboard->conv == NULL) {
-		if (chat)
-			swboard->conv = purple_find_chat(account->gc, swboard->chat_id);
-		else {
-			swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
-									who, account);
-			if (swboard->conv == NULL)
-				swboard->conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, who);
-		}
-	}
-
-	if (chat)
-		serv_got_chat_in(pc,
-		                 purple_conv_chat_get_id(PURPLE_CONV_CHAT(swboard->conv)),
-		                 who, PURPLE_MESSAGE_RECV|PURPLE_MESSAGE_SYSTEM, str,
-		                 time(NULL));
-	else
-		serv_got_im(pc, who, str, PURPLE_MESSAGE_RECV|PURPLE_MESSAGE_SYSTEM,
-		            time(NULL));
-	g_free(str);
-
-}
-
-#define purple_mkstemp(a, b) NULL
-
-/* TODO: Make these not be such duplicates of each other */
-static void
-got_wink_cb(MsnSlpCall *slpcall, const guchar *data, gsize size)
-{
-	FILE *f = NULL;
-	char *path = NULL;
-	const char *who = slpcall->slplink->remote_user;
-	purple_debug_info("msn", "Received wink from %s\n", who);
-
-	if ((f = purple_mkstemp(&path, TRUE)) &&
-	    (fwrite(data, 1, size, f) == size)) {
-		datacast_inform_user(slpcall->slplink->swboard,
-		                     who,
-		                     _("%s sent a wink. <a href='msn-wink://%s'>Click here to play it</a>"),
-		                     path);
-	} else {
-		purple_debug_error("msn", "Couldn\'t create temp file to store wink\n");
-		datacast_inform_user(slpcall->slplink->swboard,
-		                     who,
-		                     _("%s sent a wink, but it could not be saved"),
-		                     NULL);
-	}
-	if (f)
-		fclose(f);
-	g_free(path);
-}
-
-static void
-got_voiceclip_cb(MsnSlpCall *slpcall, const guchar *data, gsize size)
-{
-	FILE *f = NULL;
-	char *path = NULL;
-	const char *who = slpcall->slplink->remote_user;
-	purple_debug_info("msn", "Received voice clip from %s\n", who);
-
-	if ((f = purple_mkstemp(&path, TRUE)) &&
-	    (fwrite(data, 1, size, f) == size)) {
-		datacast_inform_user(slpcall->slplink->swboard,
-		                     who,
-		                     _("%s sent a voice clip. <a href='audio://%s'>Click here to play it</a>"),
-		                     path);
-	} else {
-		purple_debug_error("msn", "Couldn\'t create temp file to store sound\n");
-		datacast_inform_user(slpcall->slplink->swboard,
-		                     who,
-		                     _("%s sent a voice clip, but it could not be saved"),
-		                     NULL);
-	}
-	if (f)
-		fclose(f);
-	g_free(path);
-}
-
-void
-msn_p2p_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	MsnSession *session;
-	MsnSlpLink *slplink;
-	MsnP2PVersion p2p;
-
-	session = cmdproc->servconn->session;
-	slplink = msn_session_get_slplink(session, msg->remote_user);
-
-	if (slplink->swboard == NULL)
-	{
-		/*
-		 * We will need swboard in order to change its flags.  If its
-		 * NULL, something has probably gone wrong earlier on.  I
-		 * didn't want to do this, but MSN 7 is somehow causing us
-		 * to crash here, I couldn't reproduce it to debug more,
-		 * and people are reporting bugs. Hopefully this doesn't
-		 * cause more crashes. Stu.
-		 */
-		if (cmdproc->data == NULL)
-			g_warning("msn_p2p_msg cmdproc->data was NULL\n");
-		else {
-			slplink->swboard = (MsnSwitchBoard *)cmdproc->data;
-			slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink);
-		}
-	}
-
-	p2p = msn_slplink_get_p2p_version(slplink);
-	msg->part = msn_slpmsgpart_new_from_data(p2p, msg->body, msg->body_len);
-
-	if (msg->part)
-		msn_slplink_process_msg(slplink, msg->part);
-	else
-		purple_debug_warning("msn", "P2P message failed to parse.\n");
-}
-
-static void
-got_emoticon(MsnSlpCall *slpcall,
-			 const guchar *data, gsize size)
-{
-	PurpleConversation *conv;
-	MsnSwitchBoard *swboard;
-
-	swboard = slpcall->slplink->swboard;
-	conv = swboard->conv;
-
-	if (conv) {
-		/* FIXME: it would be better if we wrote the data as we received it
-		   instead of all at once, calling write multiple times and
-		   close once at the very end
-		 */
-		purple_conv_custom_smiley_write(conv, slpcall->data_info, data, size);
-		purple_conv_custom_smiley_close(conv, slpcall->data_info );
-	}
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "Got smiley: %s\n", slpcall->data_info);
-}
-
-void msn_emoticon_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	MsnSession *session;
-	MsnSlpLink *slplink;
-	MsnSwitchBoard *swboard;
-	MsnObject *obj;
-	char **tokens;
-	char *smile, *body_str;
-	const char *body, *who, *sha1;
-	guint tok;
-	size_t body_len;
-
-	PurpleConversation *conv;
-
-	session = cmdproc->servconn->session;
-
-	if (!purple_account_get_bool(session->account, "custom_smileys", TRUE))
-		return;
-
-	swboard = cmdproc->data;
-	conv = swboard->conv;
-
-	body = msn_message_get_bin_data(msg, &body_len);
-	if (!body || !body_len)
-		return;
-	body_str = g_strndup(body, body_len);
-
-	/* MSN Messenger 7 may send more than one MSNObject in a single message...
-	 * Maybe 10 tokens is a reasonable max value. */
-	tokens = g_strsplit(body_str, "\t", 10);
-
-	g_free(body_str);
-
-	for (tok = 0; tok < 9; tok += 2) {
-		if (tokens[tok] == NULL || tokens[tok + 1] == NULL) {
-			break;
-		}
-
-		smile = tokens[tok];
-		obj = msn_object_new_from_string(purple_url_decode(tokens[tok + 1]));
-
-		if (obj == NULL)
-			break;
-
-		who = msn_object_get_creator(obj);
-		sha1 = msn_object_get_sha1(obj);
-
-		slplink = msn_session_get_slplink(session, who);
-		if (slplink->swboard != swboard) {
-			if (slplink->swboard != NULL)
-				/*
-				 * Apparently we're using a different switchboard now or
-				 * something?  I don't know if this is normal, but it
-				 * definitely happens.  So make sure the old switchboard
-				 * doesn't still have a reference to us.
-				 */
-				slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink);
-			slplink->swboard = swboard;
-			slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink);
-		}
-
-		/* If the conversation doesn't exist then this is a custom smiley
-		 * used in the first message in a MSN conversation: we need to create
-		 * the conversation now, otherwise the custom smiley won't be shown.
-		 * This happens because every GtkIMHtml has its own smiley tree: if
-		 * the conversation doesn't exist then we cannot associate the new
-		 * smiley with its GtkIMHtml widget. */
-		if (!conv) {
-			conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, session->account, who);
-		}
-
-		if (purple_conv_custom_smiley_add(conv, smile, "sha1", sha1, TRUE)) {
-			msn_slplink_request_object(slplink, smile, got_emoticon, NULL, obj);
-		}
-
-		msn_object_destroy(obj);
-		obj =   NULL;
-		who =   NULL;
-		sha1 = NULL;
-	}
-	g_strfreev(tokens);
-}
-
-void
-msn_datacast_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	GHashTable *body;
-	const char *id;
-	body = msn_message_get_hashtable_from_body(msg);
-
-	id = g_hash_table_lookup(body, "ID");
-
-	if (!strcmp(id, "1")) {
-		/* Nudge */
-		PurpleAccount *account;
-		const char *user;
-
-		account = cmdproc->session->account;
-		user = msg->remote_user;
-
-		if (cmdproc->servconn->type == MSN_SERVCONN_SB) {
-			MsnSwitchBoard *swboard = cmdproc->data;
-			if (swboard->current_users > 1 ||
-				((swboard->conv != NULL) &&
-				 purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
-				purple_prpl_got_attention_in_chat(account->gc, swboard->chat_id, user, MSN_NUDGE);
-
-			else
-				purple_prpl_got_attention(account->gc, user, MSN_NUDGE);
-		} else {
-			purple_prpl_got_attention(account->gc, user, MSN_NUDGE);
-		}
-
-	} else if (!strcmp(id, "2")) {
-		/* Wink */
-		MsnSession *session;
-		MsnSlpLink *slplink;
-		MsnObject *obj;
-		const char *who;
-		const char *data;
-
-		session = cmdproc->session;
-
-		data = g_hash_table_lookup(body, "Data");
-		obj = msn_object_new_from_string(data);
-		who = msn_object_get_creator(obj);
-
-		slplink = msn_session_get_slplink(session, who);
-		msn_slplink_request_object(slplink, data, got_wink_cb, NULL, obj);
-
-		msn_object_destroy(obj);
-
-
-	} else if (!strcmp(id, "3")) {
-		/* Voiceclip */
-		MsnSession *session;
-		MsnSlpLink *slplink;
-		MsnObject *obj;
-		const char *who;
-		const char *data;
-
-		session = cmdproc->session;
-
-		data = g_hash_table_lookup(body, "Data");
-		obj = msn_object_new_from_string(data);
-		who = msn_object_get_creator(obj);
-
-		slplink = msn_session_get_slplink(session, who);
-		msn_slplink_request_object(slplink, data, got_voiceclip_cb, NULL, obj);
-
-		msn_object_destroy(obj);
-
-	} else if (!strcmp(id, "4")) {
-		/* Action */
-
-	} else {
-		purple_debug_warning("msn", "Got unknown datacast with ID %s.\n", id);
-	}
-
-	g_hash_table_destroy(body);
-}
-
-void
-msn_invite_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	GHashTable *body;
-	const gchar *command;
-	const gchar *cookie;
-	gboolean accepted = FALSE;
-
-	g_return_if_fail(cmdproc != NULL);
-	g_return_if_fail(msg != NULL);
-
-	body = msn_message_get_hashtable_from_body(msg);
-
-	if (body == NULL) {
-		purple_debug_warning("msn",
-				"Unable to parse invite msg body.\n");
-		return;
-	}
-
-	/*
-	 * GUID is NOT always present but Invitation-Command and Invitation-Cookie
-	 * are mandatory.
-	 */
-	command = g_hash_table_lookup(body, "Invitation-Command");
-	cookie = g_hash_table_lookup(body, "Invitation-Cookie");
-
-	if (command == NULL || cookie == NULL) {
-		purple_debug_warning("msn",
-			"Invalid invitation message: either Invitation-Command "
-			"or Invitation-Cookie is missing or invalid.\n"
-		);
-		return;
-
-	} else if (!strcmp(command, "INVITE")) {
-		const gchar	*guid = g_hash_table_lookup(body, "Application-GUID");
-
-		if (guid == NULL) {
-			purple_debug_warning("msn",
-			                     "Invite msg missing Application-GUID.\n");
-
-			accepted = TRUE;
-
-		} else if (!strcmp(guid, MSN_FT_GUID)) {
-
-		} else if (!strcmp(guid, "{02D3C01F-BF30-4825-A83A-DE7AF41648AA}")) {
-			purple_debug_info("msn", "Computer call\n");
-
-			if (cmdproc->session) {
-				PurpleConversation *conv = NULL;
-				gchar *from = msg->remote_user;
-				gchar *buf = NULL;
-
-				if (from)
-					conv = purple_find_conversation_with_account(
-							PURPLE_CONV_TYPE_IM, from,
-							cmdproc->session->account);
-				if (conv)
-					buf = g_strdup_printf(
-							_("%s sent you a voice chat "
-							"invite, which is not yet "
-							"supported."), from);
-				if (buf) {
-					purple_conversation_write(conv, NULL, buf,
-							PURPLE_MESSAGE_SYSTEM |
-							PURPLE_MESSAGE_NOTIFY,
-							time(NULL));
-					g_free(buf);
-				}
-			}
-		} else {
-			const gchar *application = g_hash_table_lookup(body, "Application-Name");
-			purple_debug_warning("msn", "Unhandled invite msg with GUID %s: %s.\n",
-			                     guid, application ? application : "(null)");
-		}
-
-		if (!accepted) {
-			MsnSwitchBoard *swboard = cmdproc->data;
-			char *text;
-			MsnMessage *cancel;
-
-			cancel = msn_message_new(MSN_MSG_TEXT);
-			msn_message_set_content_type(cancel, "text/x-msmsgsinvite");
-			msn_message_set_charset(cancel, "UTF-8");
-			msn_message_set_flag(cancel, 'U');
-
-			text = g_strdup_printf("Invitation-Command: CANCEL\r\n"
-			                       "Invitation-Cookie: %s\r\n"
-			                       "Cancel-Code: REJECT_NOT_INSTALLED\r\n",
-			                       cookie);
-			msn_message_set_bin_data(cancel, text, strlen(text));
-			g_free(text);
-
-			msn_switchboard_send_msg(swboard, cancel, TRUE);
-			msn_message_unref(cancel);
-		}
-
-	} else if (!strcmp(command, "CANCEL")) {
-		const gchar *code = g_hash_table_lookup(body, "Cancel-Code");
-		purple_debug_info("msn", "MSMSGS invitation cancelled: %s.\n",
-		                  code ? code : "no reason given");
-
-	} else {
-		/*
-		 * Some other already established invitation session.
-		 * Can be retrieved by Invitation-Cookie.
-		 */
-	}
-
-	g_hash_table_destroy(body);
-}
-
-/* Only called from chats. Handwritten messages for IMs come as a SLP message */
-void
-msn_handwritten_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	const char *body;
-	size_t body_len;
-
-	body = msn_message_get_bin_data(msg, &body_len);
-	msn_switchboard_show_ink(cmdproc->data, msg->remote_user, body);
-}
-
deleted file mode 100644
--- a/libpurple/protocols/msn/msg.h
+++ /dev/null
@@ -1,325 +0,0 @@
-/**
- * @file msg.h Message functions
- *
- * purple
- *
- * Purple 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 MSN_MSG_H
-#define MSN_MSG_H
-
-typedef struct _MsnMessage MsnMessage;
-
-/*
-typedef enum
-{
-	MSN_MSG_NORMAL,
-	MSN_MSG_SLP_SB,
-	MSN_MSG_SLP_DC
-} MsnMsgType;
-*/
-
-typedef enum
-{
-	MSN_MSG_UNKNOWN,
-	MSN_MSG_TEXT,
-	MSN_MSG_TYPING,
-	MSN_MSG_CAPS,
-	MSN_MSG_SLP,
-	MSN_MSG_NUDGE
-} MsnMsgType;
-
-typedef enum
-{
-	MSN_MSG_ERROR_NONE, /**< No error. */
-	MSN_MSG_ERROR_TIMEOUT, /**< The message timedout. */
-	MSN_MSG_ERROR_NAK, /**< The message could not be sent. */
-	MSN_MSG_ERROR_SB, /**< The error comes from the switchboard. */
-	MSN_MSG_ERROR_UNKNOWN /**< An unknown error occurred. */
-} MsnMsgErrorType;
-
-#include "command.h"
-#include "session.h"
-#include "transaction.h"
-#include "user.h"
-#include "slpmsg.h"
-#include "slpmsg_part.h"
-
-typedef void (*MsnMsgCb)(MsnMessage *, void *data);
-
-#define MSG_BODY_DEM	"\r\n\r\n"
-#define MSG_LINE_DEM	"\r\n"
-
-#define MSG_OIM_BODY_DEM	"\n\n"
-#define MSG_OIM_LINE_DEM	"\n"
-
-/**
- * A message.
- */
-struct _MsnMessage
-{
-	guint ref_count;        /**< The reference count.       */
-
-	MsnMsgType type;
-
-	MsnSlpMessagePart *part;
-
-	char *remote_user;
-	char flag;
-
-	char *content_type;
-	char *charset;
-	char *body;
-	gsize body_len;
-	guint total_chunks;     /**< How many chunks in this multi-part message */
-	guint received_chunks;  /**< How many chunks we've received so far */
-
-	GHashTable *header_table;
-	GList *header_list;
-
-	gboolean ack_ref;           /**< A flag that states if this message has
-								  been ref'ed for using it in a callback. */
-
-	MsnCommand *cmd;
-
-	MsnMsgCb ack_cb; /**< The callback to call when we receive an ACK of this
-					   message. */
-	MsnMsgCb nak_cb; /**< The callback to call when we receive a NAK of this
-					   message. */
-	void *ack_data; /**< The data used by callbacks. */
-
-	guint32 retries;
-};
-
-/**
- * Creates a new, empty message.
- *
- * @return A new message.
- */
-MsnMessage *msn_message_new(MsnMsgType type);
-
-/**
- * Creates a new, empty MSNSLP message.
- *
- * @return A new MSNSLP message.
- */
-MsnMessage *msn_message_new_msnslp(void);
-
-/**
- * Creates a new nudge message.
- *
- * @return A new nudge message.
- */
-MsnMessage *msn_message_new_nudge(void);
-
-/**
- * Creates a new plain message.
- *
- * @return A new plain message.
- */
-MsnMessage *msn_message_new_plain(const char *message);
-
-/**
- * Creates a new message based off a command.
- *
- * @param session The MSN session.
- * @param cmd     The command.
- *
- * @return The new message.
- */
-MsnMessage *msn_message_new_from_cmd(MsnSession *session, MsnCommand *cmd);
-
-/**
- * Parses the payload of a message.
- *
- * @param msg         The message.
- * @param payload     The payload.
- * @param payload_len The length of the payload.
- */
-void msn_message_parse_payload(MsnMessage *msg, const char *payload,
-							   size_t payload_len,
-						  const char *line_dem,const char *body_dem);
-
-/**
- * Increments the reference count on a message.
- *
- * @param msg The message.
- *
- * @return @a msg
- */
-MsnMessage *msn_message_ref(MsnMessage *msg);
-
-/**
- * Decrements the reference count on a message.
- *
- * This will destroy the structure if the count hits 0.
- *
- * @param msg The message.
- *
- * @return @a msg, or @c NULL if the new count is 0.
- */
-void msn_message_unref(MsnMessage *msg);
-
-/**
- * Generates the payload data of a message.
- *
- * @param msg      The message.
- * @param ret_size The returned size of the payload.
- *
- * @return The payload data of the message.
- */
-char *msn_message_gen_payload(MsnMessage *msg, size_t *ret_size);
-
-/**
- * Sets the flag for an outgoing message.
- *
- * @param msg  The message.
- * @param flag The flag.
- */
-void msn_message_set_flag(MsnMessage *msg, char flag);
-
-/**
- * Returns the flag for an outgoing message.
- *
- * @param msg The message.
- *
- * @return The flag.
- */
-char msn_message_get_flag(const MsnMessage *msg);
-
-/**
- * Sets the binary content of the message.
- *
- * @param msg  The message.
- * @param data The binary data.
- * @param len  The length of the data.
- */
-void msn_message_set_bin_data(MsnMessage *msg, const void *data, size_t len);
-
-/**
- * Returns the binary content of the message.
- *
- * @param msg The message.
- * @param len The returned length of the data.
- *
- * @return The binary data.
- */
-const void *msn_message_get_bin_data(const MsnMessage *msg, size_t *len);
-
-/**
- * Sets the content type in a message.
- *
- * @param msg  The message.
- * @param type The content-type.
- */
-void msn_message_set_content_type(MsnMessage *msg, const char *type);
-
-/**
- * Returns the content type in a message.
- *
- * @param msg The message.
- *
- * @return The content-type.
- */
-const char *msn_message_get_content_type(const MsnMessage *msg);
-
-/**
- * Sets the charset in a message.
- *
- * @param msg     The message.
- * @param charset The charset.
- */
-void msn_message_set_charset(MsnMessage *msg, const char *charset);
-
-/**
- * Returns the charset in a message.
- *
- * @param msg The message.
- *
- * @return The charset.
- */
-const char *msn_message_get_charset(const MsnMessage *msg);
-
-/**
- * Sets a header in a message.
- *
- * @param msg    The message.
- * @param header The header name.
- * @param value  The header value.
- */
-void msn_message_set_header(MsnMessage *msg, const char *name,
-						  const char *value);
-
-/**
- * Returns the value of a header from a message.
- *
- * @param msg    The message.
- * @param header The header value.
- *
- * @return The value, or @c NULL if not found.
- */
-const char *msn_message_get_header_value(const MsnMessage *msg, const char *name);
-
-/**
- * Parses the body and returns it in the form of a hashtable.
- *
- * @param msg The message.
- *
- * @return The resulting hashtable.
- */
-GHashTable *msn_message_get_hashtable_from_body(const MsnMessage *msg);
-
-void msn_message_show_readable(MsnMessage *msg, const char *info,
-							   gboolean text_body);
-
-char *msn_message_to_string(MsnMessage *msg);
-
-void msn_plain_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
-
-void msn_control_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
-
-/**
- * Processes peer to peer messages.
- *
- * @param cmdproc The command processor.
- * @param msg     The message.
- */
-void msn_p2p_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
-
-/**
- * Processes emoticon messages.
- *
- * @param cmdproc The command processor.
- * @param msg     The message.
- */
-void msn_emoticon_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
-
-void msn_datacast_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
-
-/**
- * Processes INVITE messages.
- *
- * @param cmdproc The command processor.
- * @param msg     The message.
- */
-void msn_invite_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
-
-void msn_handwritten_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
-
-#endif /* MSN_MSG_H */
deleted file mode 100644
--- a/libpurple/protocols/msn/msn.c
+++ /dev/null
@@ -1,3069 +0,0 @@
-/**
- * @file msn.c The MSN protocol plugin
- *
- * purple
- *
- * Purple 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
- */
-#define PHOTO_SUPPORT 1
-
-#include "internal.h"
-
-#include "debug.h"
-#include "request.h"
-
-#include "accountopt.h"
-#include "contact.h"
-#include "msg.h"
-#include "page.h"
-#include "pluginpref.h"
-#include "prefs.h"
-#include "session.h"
-#include "smiley.h"
-#include "state.h"
-#include "util.h"
-#include "cmds.h"
-#include "core.h"
-#include "prpl.h"
-#include "msnutils.h"
-#include "version.h"
-
-#include "error.h"
-#include "msg.h"
-#include "switchboard.h"
-#include "notification.h"
-#include "slplink.h"
-
-#if PHOTO_SUPPORT
-#define MAX_HTTP_BUDDYICON_BYTES (200 * 1024)
-#include "imgstore.h"
-#endif
-
-typedef struct
-{
-	PurpleConnection *gc;
-	const char *passport;
-
-} MsnMobileData;
-
-typedef struct
-{
-	PurpleConnection *gc;
-	char *name;
-
-} MsnGetInfoData;
-
-typedef struct
-{
-	MsnGetInfoData *info_data;
-	char *stripped;
-	char *url_buffer;
-	PurpleNotifyUserInfo *user_info;
-	char *photo_url_text;
-
-} MsnGetInfoStepTwoData;
-
-typedef struct
-{
-	PurpleConnection *gc;
-	const char *who;
-	char *msg;
-	PurpleMessageFlags flags;
-	time_t when;
-} MsnIMData;
-
-typedef struct
-{
-	char *smile;
-	PurpleSmiley *ps;
-	MsnObject *obj;
-} MsnEmoticon;
-
-static const char *
-msn_normalize(const PurpleAccount *account, const char *str)
-{
-	static char buf[BUF_LEN];
-	char *tmp;
-
-	g_return_val_if_fail(str != NULL, NULL);
-
-	tmp = g_strchomp(g_utf8_strdown(str, -1));
-	g_snprintf(buf, sizeof(buf), "%s%s", tmp,
-			   (strchr(tmp, '@') ? "" : "@hotmail.com"));
-	g_free(tmp);
-
-	return buf;
-}
-
-static gboolean
-msn_send_attention(PurpleConnection *gc, const char *username, guint type)
-{
-	MsnMessage *msg;
-	MsnSession *session;
-	MsnSwitchBoard *swboard;
-
-	msg = msn_message_new_nudge();
-	session = gc->proto_data;
-	swboard = msn_session_get_swboard(session, username, MSN_SB_FLAG_IM);
-
-	msn_switchboard_send_msg(swboard, msg, TRUE);
-	msn_message_unref(msg);
-
-	return TRUE;
-}
-
-static GList *
-msn_attention_types(PurpleAccount *account)
-{
-	static GList *list = NULL;
-
-	if (!list) {
-		list = g_list_append(list, purple_attention_type_new("Nudge", _("Nudge"),
-				_("%s has nudged you!"), _("Nudging %s...")));
-	}
-
-	return list;
-}
-
-static GHashTable *
-msn_get_account_text_table(PurpleAccount *unused)
-{
-	GHashTable *table;
-
-	table = g_hash_table_new(g_str_hash, g_str_equal);
-
-	g_hash_table_insert(table, "login_label", (gpointer)_("Email Address..."));
-
-	return table;
-}
-
-static PurpleCmdRet
-msn_cmd_nudge(PurpleConversation *conv, const gchar *cmd, gchar **args, gchar **error, void *data)
-{
-	PurpleAccount *account = purple_conversation_get_account(conv);
-	PurpleConnection *gc = purple_account_get_connection(account);
-	const gchar *username;
-
-	username = purple_conversation_get_name(conv);
-
-	purple_prpl_send_attention(gc, username, MSN_NUDGE);
-
-	return PURPLE_CMD_RET_OK;
-}
-
-struct public_alias_closure
-{
-	PurpleAccount *account;
-	gpointer success_cb;
-	gpointer failure_cb;
-};
-
-static gboolean
-set_public_alias_length_error(gpointer data)
-{
-	struct public_alias_closure *closure = data;
-	PurpleSetPublicAliasFailureCallback failure_cb = closure->failure_cb;
-
-	failure_cb(closure->account, _("Your new MSN friendly name is too long."));
-	g_free(closure);
-
-	return FALSE;
-}
-
-static void
-prp_success_cb(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	const char *type, *friendlyname;
-	struct public_alias_closure *closure;
-
-	g_return_if_fail(cmd->param_count >= 3);
-	type = cmd->params[1];
-	g_return_if_fail(!strcmp(type, "MFN"));
-
-	closure = cmd->trans->data;
-	friendlyname = purple_url_decode(cmd->params[2]);
-
-	msn_update_contact(cmdproc->session, "Me", MSN_UPDATE_DISPLAY, friendlyname);
-
-	purple_connection_set_display_name(
-		purple_account_get_connection(closure->account),
-		friendlyname);
-	purple_account_set_string(closure->account, "display-name", friendlyname);
-
-	if (closure->success_cb) {
-		PurpleSetPublicAliasSuccessCallback success_cb = closure->success_cb;
-		success_cb(closure->account, friendlyname);
-	}
-}
-
-static void
-prp_error_cb(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
-{
-	struct public_alias_closure *closure = trans->data;
-	PurpleSetPublicAliasFailureCallback failure_cb = closure->failure_cb;
-	gboolean debug;
-	const char *error_text;
-
-	error_text = msn_error_get_text(error, &debug);
-	failure_cb(closure->account, error_text);
-}
-
-static void
-prp_timeout_cb(MsnCmdProc *cmdproc, MsnTransaction *trans)
-{
-	struct public_alias_closure *closure = trans->data;
-	PurpleSetPublicAliasFailureCallback failure_cb = closure->failure_cb;
-	failure_cb(closure->account, _("Connection Timeout"));
-}
-
-void
-msn_set_public_alias(PurpleConnection *pc, const char *alias,
-                     PurpleSetPublicAliasSuccessCallback success_cb,
-                     PurpleSetPublicAliasFailureCallback failure_cb)
-{
-	MsnCmdProc *cmdproc;
-	MsnSession *session;
-	MsnTransaction *trans;
-	PurpleAccount *account;
-	char real_alias[BUDDY_ALIAS_MAXLEN + 1];
-	struct public_alias_closure *closure;
-
-	session = purple_connection_get_protocol_data(pc);
-	cmdproc = session->notification->cmdproc;
-	account = purple_connection_get_account(pc);
-
-	if (alias && *alias) {
-		if (!msn_encode_spaces(alias, real_alias, BUDDY_ALIAS_MAXLEN + 1)) {
-			if (failure_cb) {
-				struct public_alias_closure *closure =
-					g_new0(struct public_alias_closure, 1);
-				closure->account = account;
-				closure->failure_cb = failure_cb;
-				purple_timeout_add(0, set_public_alias_length_error, closure);
-			} else {
-				purple_notify_error(pc, NULL,
-				                    _("Your new MSN friendly name is too long."),
-				                    NULL);
-			}
-			return;
-		}
-
-		if (real_alias[0] == '\0')
-			g_strlcpy(real_alias, purple_account_get_username(account), sizeof(real_alias));
-	} else
-		g_strlcpy(real_alias, purple_account_get_username(account), sizeof(real_alias));
-
-	closure = g_new0(struct public_alias_closure, 1);
-	closure->account = account;
-	closure->success_cb = success_cb;
-	closure->failure_cb = failure_cb;
-
-	trans = msn_transaction_new(cmdproc, "PRP", "MFN %s", real_alias);
-	msn_transaction_set_data(trans, closure);
-	msn_transaction_set_data_free(trans, g_free);
-	msn_transaction_add_cb(trans, "PRP", prp_success_cb);
-	if (failure_cb) {
-		msn_transaction_set_error_cb(trans, prp_error_cb);
-		msn_transaction_set_timeout_cb(trans, prp_timeout_cb);
-	}
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-static gboolean
-get_public_alias_cb(gpointer data)
-{
-	struct public_alias_closure *closure = data;
-	PurpleGetPublicAliasSuccessCallback success_cb = closure->success_cb;
-	const char *alias;
-
-	alias = purple_account_get_string(closure->account, "display-name",
-	                                  purple_account_get_username(closure->account));
-	success_cb(closure->account, alias);
-	g_free(closure);
-
-	return FALSE;
-}
-
-static void
-msn_get_public_alias(PurpleConnection *pc,
-                     PurpleGetPublicAliasSuccessCallback success_cb,
-                     PurpleGetPublicAliasFailureCallback failure_cb)
-{
-	struct public_alias_closure *closure = g_new0(struct public_alias_closure, 1);
-	PurpleAccount *account = purple_connection_get_account(pc);
-
-	closure->account = account;
-	closure->success_cb = success_cb;
-	purple_timeout_add(0, get_public_alias_cb, closure);
-}
-
-static void
-msn_act_id(PurpleConnection *gc, const char *entry)
-{
-	msn_set_public_alias(gc, entry, NULL, NULL);
-}
-
-static void
-msn_set_prp(PurpleConnection *gc, const char *type, const char *entry)
-{
-	MsnCmdProc *cmdproc;
-	MsnSession *session;
-	MsnTransaction *trans;
-
-	session = gc->proto_data;
-	cmdproc = session->notification->cmdproc;
-
-	if (entry == NULL || *entry == '\0')
-	{
-		trans = msn_transaction_new(cmdproc, "PRP", "%s", type);
-	}
-	else
-	{
-		trans = msn_transaction_new(cmdproc, "PRP", "%s %s", type,
-						 purple_url_encode(entry));
-	}
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-static void
-msn_set_home_phone_cb(PurpleConnection *gc, const char *entry)
-{
-	msn_set_prp(gc, "PHH", entry);
-}
-
-static void
-msn_set_work_phone_cb(PurpleConnection *gc, const char *entry)
-{
-	msn_set_prp(gc, "PHW", entry);
-}
-
-static void
-msn_set_mobile_phone_cb(PurpleConnection *gc, const char *entry)
-{
-	msn_set_prp(gc, "PHM", entry);
-}
-
-static void
-enable_msn_pages_cb(PurpleConnection *gc)
-{
-	msn_set_prp(gc, "MOB", "Y");
-}
-
-static void
-disable_msn_pages_cb(PurpleConnection *gc)
-{
-	msn_set_prp(gc, "MOB", "N");
-}
-
-static void
-send_to_mobile(PurpleConnection *gc, const char *who, const char *entry)
-{
-	MsnTransaction *trans;
-	MsnSession *session;
-	MsnCmdProc *cmdproc;
-	MsnPage *page;
-	MsnMessage *msg;
-	MsnUser *user;
-	char *payload = NULL;
-	const char *mobile_number = NULL;
-	gsize payload_len;
-
-	session = gc->proto_data;
-	cmdproc = session->notification->cmdproc;
-
-	page = msn_page_new();
-	msn_page_set_body(page, entry);
-
-	payload = msn_page_gen_payload(page, &payload_len);
-
-	if ((user = msn_userlist_find_user(session->userlist, who)) &&
-		(mobile_number = msn_user_get_mobile_phone(user)) &&
-		mobile_number[0] == '+') {
-		/* if msn_user_get_mobile_phone() has a + in front, it's a number
-		   that from the buddy's contact card */
-		trans = msn_transaction_new(cmdproc, "PGD", "tel:%s 1 %" G_GSIZE_FORMAT,
-			mobile_number, payload_len);
-	} else {
-		/* otherwise we send to whatever phone number the buddy registered
-		   with msn */
-		trans = msn_transaction_new(cmdproc, "PGD", "%s 1 %" G_GSIZE_FORMAT,
-			who, payload_len);
-	}
-
-	msn_transaction_set_payload(trans, payload, payload_len);
-	g_free(payload);
-
-	msg = msn_message_new_plain(entry);
-	msn_transaction_set_data(trans, msg);
-
-	msn_page_destroy(page);
-
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-static void
-send_to_mobile_cb(MsnMobileData *data, const char *entry)
-{
-	send_to_mobile(data->gc, data->passport, entry);
-	g_free(data);
-}
-
-static void
-close_mobile_page_cb(MsnMobileData *data, const char *entry)
-{
-	g_free(data);
-}
-
-/* -- */
-
-static void
-msn_show_set_friendly_name(PurplePluginAction *action)
-{
-	PurpleConnection *gc;
-	PurpleAccount *account;
-	char *tmp;
-
-	gc = (PurpleConnection *) action->context;
-	account = purple_connection_get_account(gc);
-
-	tmp = g_strdup_printf(_("Set friendly name for %s."),
-	                      purple_account_get_username(account));
-	purple_request_input(gc, _("Set Friendly Name"), tmp,
-					   _("This is the name that other MSN buddies will "
-						 "see you as."),
-					   purple_connection_get_display_name(gc), FALSE, FALSE, NULL,
-					   _("OK"), G_CALLBACK(msn_act_id),
-					   _("Cancel"), NULL,
-					   account, NULL, NULL,
-					   gc);
-	g_free(tmp);
-}
-
-typedef struct MsnLocationData {
-	PurpleAccount *account;
-	MsnSession *session;
-	PurpleRequestFieldGroup *group;
-} MsnLocationData;
-
-static void
-update_endpoint_cb(MsnLocationData *data, PurpleRequestFields *fields)
-{
-	PurpleAccount *account;
-	MsnSession *session;
-	const char *old_name;
-	const char *name;
-	GList *others;
-
-	session = data->session;
-	account = data->account;
-
-	/* Update the current location's name */
-	old_name = purple_account_get_string(account, "endpoint-name", NULL);
-	name = purple_request_fields_get_string(fields, "endpoint-name");
-	if (!g_str_equal(old_name, name)) {
-		purple_account_set_string(account, "endpoint-name", name);
-		msn_notification_send_uux_private_endpointdata(session);
-	}
-
-	/* Sign out other locations */
-	for (others = purple_request_field_group_get_fields(data->group);
-	     others;
-	     others = g_list_next(others)) {
-		PurpleRequestField *field = others->data;
-		if (purple_request_field_get_type(field) != PURPLE_REQUEST_FIELD_BOOLEAN)
-			continue;
-		if (purple_request_field_bool_get_value(field)) {
-			const char *id = purple_request_field_get_id(field);
-			char *user;
-			purple_debug_info("msn", "Disconnecting Endpoint %s\n", id);
-
-			user = g_strdup_printf("%s;%s", purple_account_get_username(account), id);
-			msn_notification_send_uun(session, user, MSN_UNIFIED_NOTIFICATION_MPOP, "goawyplzthxbye");
-			g_free(user);
-		}
-	}
-
-	g_free(data);
-}
-
-static void
-msn_show_locations(PurplePluginAction *action)
-{
-	PurpleConnection *pc;
-	PurpleAccount *account;
-	MsnSession *session;
-	PurpleRequestFields *fields;
-	PurpleRequestFieldGroup *group;
-	PurpleRequestField *field;
-	gboolean have_other_endpoints;
-	GSList *l;
-	MsnLocationData *data;
-
-	pc = (PurpleConnection *)action->context;
-	account = purple_connection_get_account(pc);
-	session = purple_connection_get_protocol_data(pc);
-
-	fields = purple_request_fields_new();
-
-	group = purple_request_field_group_new(_("This Location"));
-	purple_request_fields_add_group(fields, group);
-	field = purple_request_field_label_new("endpoint-label", _("This is the name that identifies this location"));
-	purple_request_field_group_add_field(group, field);
-	field = purple_request_field_string_new("endpoint-name",
-	                                        _("Name"),
-	                                        purple_account_get_string(account, "endpoint-name", NULL),
-	                                        FALSE);
-	purple_request_field_set_required(field, TRUE);
-	purple_request_field_group_add_field(group, field);
-
-	group = purple_request_field_group_new(_("Other Locations"));
-	purple_request_fields_add_group(fields, group);
-
-	have_other_endpoints = FALSE;
-	for (l = session->user->endpoints; l; l = l->next) {
-		MsnUserEndpoint *ep = l->data;
-
-		if (ep->id[0] != '\0' && g_ascii_strncasecmp(ep->id + 1, session->guid, 36) == 0)
-			/* Don't add myself to the list */
-			continue;
-
-		if (!have_other_endpoints) {
-			/* We do in fact have an endpoint other than ourselves... let's
-			   add a label */
-			field = purple_request_field_label_new("others-label",
-					_("You can sign out from other locations here"));
-			purple_request_field_group_add_field(group, field);
-		}
-
-		have_other_endpoints = TRUE;
-		field = purple_request_field_bool_new(ep->id, ep->name, FALSE);
-		purple_request_field_group_add_field(group, field);
-	}
-	if (!have_other_endpoints) {
-		/* TODO: Due to limitations in our current request field API, the
-		   following string will show up with a trailing colon.  This should
-		   be fixed either by adding an "include_colon" boolean, or creating
-		   a separate purple_request_field_label_new_without_colon function,
-		   or by never automatically adding the colon and requiring that
-		   callers add the colon themselves. */
-		field = purple_request_field_label_new("others-label", _("You are not signed in from any other locations."));
-		purple_request_field_group_add_field(group, field);
-	}
-
-	data = g_new0(MsnLocationData, 1);
-	data->account = account;
-	data->session = session;
-	data->group = group;
-
-	purple_request_fields(pc, NULL, NULL, NULL,
-	                      fields,
-	                      _("OK"), G_CALLBACK(update_endpoint_cb),
-	                      _("Cancel"), G_CALLBACK(g_free),
-	                      account, NULL, NULL,
-	                      data);
-}
-
-static void
-enable_mpop_cb(PurpleConnection *pc)
-{
-	MsnSession *session = purple_connection_get_protocol_data(pc);
-
-	purple_debug_info("msn", "Enabling MPOP\n");
-
-	session->enable_mpop = TRUE;
-	msn_annotate_contact(session, "Me", "MSN.IM.MPOP", "1", NULL);
-
-	purple_prpl_got_account_actions(purple_connection_get_account(pc));
-}
-
-static void
-disable_mpop_cb(PurpleConnection *pc)
-{
-	PurpleAccount *account = purple_connection_get_account(pc);
-	MsnSession *session = purple_connection_get_protocol_data(pc);
-	GSList *l;
-
-	purple_debug_info("msn", "Disabling MPOP\n");
-
-	session->enable_mpop = FALSE;
-	msn_annotate_contact(session, "Me", "MSN.IM.MPOP", "0", NULL);
-
-	for (l = session->user->endpoints; l; l = l->next) {
-		MsnUserEndpoint *ep = l->data;
-		char *user;
-
-		if (ep->id[0] != '\0' && g_ascii_strncasecmp(ep->id + 1, session->guid, 36) == 0)
-			/* Don't kick myself */
-			continue;
-
-		purple_debug_info("msn", "Disconnecting Endpoint %s\n", ep->id);
-
-		user = g_strdup_printf("%s;%s", purple_account_get_username(account), ep->id);
-		msn_notification_send_uun(session, user, MSN_UNIFIED_NOTIFICATION_MPOP, "goawyplzthxbye");
-		g_free(user);
-	}
-
-	purple_prpl_got_account_actions(account);
-}
-
-static void
-msn_show_set_mpop(PurplePluginAction *action)
-{
-	PurpleConnection *pc;
-
-	pc = (PurpleConnection *)action->context;
-
-	purple_request_action(pc, NULL, _("Allow multiple logins?"),
-						_("Do you want to allow or disallow connecting from "
-						  "multiple locations simultaneously?"),
-						PURPLE_DEFAULT_ACTION_NONE,
-						purple_connection_get_account(pc), NULL, NULL,
-						pc, 3,
-						_("Allow"), G_CALLBACK(enable_mpop_cb),
-						_("Disallow"), G_CALLBACK(disable_mpop_cb),
-						_("Cancel"), NULL);
-}
-
-static void
-msn_show_set_home_phone(PurplePluginAction *action)
-{
-	PurpleConnection *gc;
-	MsnSession *session;
-
-	gc = (PurpleConnection *) action->context;
-	session = gc->proto_data;
-
-	purple_request_input(gc, NULL, _("Set your home phone number."), NULL,
-					   msn_user_get_home_phone(session->user), FALSE, FALSE, NULL,
-					   _("OK"), G_CALLBACK(msn_set_home_phone_cb),
-					   _("Cancel"), NULL,
-					   purple_connection_get_account(gc), NULL, NULL,
-					   gc);
-}
-
-static void
-msn_show_set_work_phone(PurplePluginAction *action)
-{
-	PurpleConnection *gc;
-	MsnSession *session;
-
-	gc = (PurpleConnection *) action->context;
-	session = gc->proto_data;
-
-	purple_request_input(gc, NULL, _("Set your work phone number."), NULL,
-					   msn_user_get_work_phone(session->user), FALSE, FALSE, NULL,
-					   _("OK"), G_CALLBACK(msn_set_work_phone_cb),
-					   _("Cancel"), NULL,
-					   purple_connection_get_account(gc), NULL, NULL,
-					   gc);
-}
-
-static void
-msn_show_set_mobile_phone(PurplePluginAction *action)
-{
-	PurpleConnection *gc;
-	MsnSession *session;
-
-	gc = (PurpleConnection *) action->context;
-	session = gc->proto_data;
-
-	purple_request_input(gc, NULL, _("Set your mobile phone number."), NULL,
-					   msn_user_get_mobile_phone(session->user), FALSE, FALSE, NULL,
-					   _("OK"), G_CALLBACK(msn_set_mobile_phone_cb),
-					   _("Cancel"), NULL,
-					   purple_connection_get_account(gc), NULL, NULL,
-					   gc);
-}
-
-static void
-msn_show_set_mobile_pages(PurplePluginAction *action)
-{
-	PurpleConnection *gc;
-
-	gc = (PurpleConnection *) action->context;
-
-	purple_request_action(gc, NULL, _("Allow MSN Mobile pages?"),
-						_("Do you want to allow or disallow people on "
-						  "your buddy list to send you MSN Mobile pages "
-						  "to your cell phone or other mobile device?"),
-						PURPLE_DEFAULT_ACTION_NONE,
-						purple_connection_get_account(gc), NULL, NULL,
-						gc, 3,
-						_("Allow"), G_CALLBACK(enable_msn_pages_cb),
-						_("Disallow"), G_CALLBACK(disable_msn_pages_cb),
-						_("Cancel"), NULL);
-}
-
-/* QuLogic: Disabled until confirmed correct. */
-#if 0
-static void
-msn_show_blocked_text(PurplePluginAction *action)
-{
-	PurpleConnection *pc = (PurpleConnection *) action->context;
-	MsnSession *session;
-	char *title;
-
-	session = pc->proto_data;
-
-	title = g_strdup_printf(_("Blocked Text for %s"), session->account->username);
-	if (session->blocked_text == NULL) {
-		purple_notify_formatted(pc, title, title, NULL, _("No text is blocked for this account."), NULL, NULL);
-	} else {
-		char *blocked_text;
-		blocked_text = g_strdup_printf(_("MSN servers are currently blocking the following regular expressions:<br/>%s"),
-		                               session->blocked_text);
-
-		purple_notify_formatted(pc, title, title, NULL, blocked_text, NULL, NULL);
-		g_free(blocked_text);
-	}
-	g_free(title);
-}
-#endif
-
-static void
-msn_show_hotmail_inbox(PurplePluginAction *action)
-{
-	PurpleConnection *gc;
-	MsnSession *session;
-
-	gc = (PurpleConnection *) action->context;
-	session = gc->proto_data;
-
-	if (!session->passport_info.email_enabled) {
-		purple_notify_error(gc, NULL,
-						  _("This account does not have email enabled."), NULL);
-		return;
-	}
-
-	/** apparently the correct value is 777, use 750 as a failsafe */
-	if ((session->passport_info.mail_url == NULL)
-		|| (time (NULL) - session->passport_info.mail_timestamp >= 750)) {
-		MsnTransaction *trans;
-		MsnCmdProc *cmdproc;
-
-		cmdproc = session->notification->cmdproc;
-
-		trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
-		msn_transaction_set_data(trans, GUINT_TO_POINTER(TRUE));
-
-		msn_cmdproc_send_trans(cmdproc, trans);
-
-	} else
-		purple_notify_uri(gc, session->passport_info.mail_url);
-}
-
-static void
-show_send_to_mobile_cb(PurpleBlistNode *node, gpointer ignored)
-{
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-	MsnMobileData *data;
-	PurpleAccount *account;
-	const char *name;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *) node;
-	account = purple_buddy_get_account(buddy);
-	gc = purple_account_get_connection(account);
-	name = purple_buddy_get_name(buddy);
-
-	data = g_new0(MsnMobileData, 1);
-	data->gc = gc;
-	data->passport = name;
-
-	purple_request_input(gc, NULL, _("Send a mobile message."), NULL,
-					   NULL, TRUE, FALSE, NULL,
-					   _("Page"), G_CALLBACK(send_to_mobile_cb),
-					   _("Close"), G_CALLBACK(close_mobile_page_cb),
-					   account, name, NULL,
-					   data);
-}
-
-static gboolean
-msn_offline_message(const PurpleBuddy *buddy) {
-	return TRUE;
-}
-
-void
-msn_send_privacy(PurpleConnection *gc)
-{
-	PurpleAccount *account;
-	MsnSession *session;
-	MsnCmdProc *cmdproc;
-	MsnTransaction *trans;
-
-	account = purple_connection_get_account(gc);
-	session = gc->proto_data;
-	cmdproc = session->notification->cmdproc;
-
-	if (account->perm_deny == PURPLE_PRIVACY_ALLOW_ALL ||
-	    account->perm_deny == PURPLE_PRIVACY_DENY_USERS)
-		trans = msn_transaction_new(cmdproc, "BLP", "%s", "AL");
-	else
-		trans = msn_transaction_new(cmdproc, "BLP", "%s", "BL");
-
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-static void
-initiate_chat_cb(PurpleBlistNode *node, gpointer data)
-{
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-	PurpleAccount *account;
-
-	MsnSession *session;
-	MsnSwitchBoard *swboard;
-
-	const char *alias;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *) node;
-	account = purple_buddy_get_account(buddy);
-	gc = purple_account_get_connection(account);
-
-	session = gc->proto_data;
-
-	swboard = msn_switchboard_new(session);
-	msn_switchboard_request(swboard);
-	msn_switchboard_request_add_user(swboard, purple_buddy_get_name(buddy));
-
-	/* TODO: This might move somewhere else, after USR might be */
-	swboard->chat_id = msn_switchboard_get_chat_id();
-	swboard->conv = serv_got_joined_chat(gc, swboard->chat_id, "MSN Chat");
-	swboard->flag = MSN_SB_FLAG_IM;
-
-	/* Local alias > Display name > Username */
-	if ((alias = purple_account_get_alias(account)) == NULL)
-		if ((alias = purple_connection_get_display_name(gc)) == NULL)
-			alias = purple_account_get_username(account);
-
-	purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv),
-	                          alias, NULL, PURPLE_CBFLAGS_NONE, TRUE);
-}
-
-static void
-t_msn_xfer_init(PurpleXfer *xfer)
-{
-	msn_request_ft(xfer);
-}
-
-static void
-t_msn_xfer_cancel_send(PurpleXfer *xfer)
-{
-	MsnSlpLink *slplink = xfer->data;
-	msn_slplink_unref(slplink);
-}
-
-static PurpleXfer*
-msn_new_xfer(PurpleConnection *gc, const char *who)
-{
-	MsnSession *session;
-	PurpleXfer *xfer;
-
-	session = gc->proto_data;
-
-	xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who);
-
-	g_return_val_if_fail(xfer != NULL, NULL);
-
-	xfer->data = msn_slplink_ref(msn_session_get_slplink(session, who));
-
-	purple_xfer_set_init_fnc(xfer, t_msn_xfer_init);
-	purple_xfer_set_cancel_send_fnc(xfer, t_msn_xfer_cancel_send);
-
-	return xfer;
-}
-
-static void
-msn_send_file(PurpleConnection *gc, const char *who, const char *file)
-{
-	PurpleXfer *xfer = msn_new_xfer(gc, who);
-
-	if (file)
-		purple_xfer_request_accepted(xfer, file);
-	else
-		purple_xfer_request(xfer);
-}
-
-static gboolean
-msn_can_receive_file(PurpleConnection *gc, const char *who)
-{
-	PurpleAccount *account;
-	gchar *normal;
-	gboolean ret;
-
-	account = purple_connection_get_account(gc);
-
-	normal = g_strdup(msn_normalize(account, purple_account_get_username(account)));
-	ret = strcmp(normal, msn_normalize(account, who));
-	g_free(normal);
-
-	if (ret) {
-		MsnSession *session = gc->proto_data;
-		if (session) {
-			MsnUser *user = msn_userlist_find_user(session->userlist, who);
-			if (user) {
-				/* Include these too: MSN_CAP_MOBILE_ON|MSN_CAP_WEB_WATCH ? */
-				if ((user->clientid & MSN_CAP_VIA_WEBIM) ||
-						user->networkid == MSN_NETWORK_YAHOO)
-					ret = FALSE;
-				else
-					ret = TRUE;
-			}
-		} else
-			ret = FALSE;
-	}
-
-	return ret;
-}
-
-/**************************************************************************
- * Protocol Plugin ops
- **************************************************************************/
-
-static const char *
-msn_list_icon(PurpleAccount *a, PurpleBuddy *b)
-{
-	return "msn";
-}
-
-static const char *
-msn_list_emblems(PurpleBuddy *b)
-{
-	MsnUser *user = purple_buddy_get_protocol_data(b);
-
-	if (user != NULL) {
-		if (user->clientid & MSN_CAP_BOT)
-			return "bot";
-		if (user->clientid & MSN_CAP_VIA_MOBILE)
-			return "mobile";
-#if 0
-		/* XXX: Since we don't support this, there's no point in showing it just yet */
-		if (user->clientid & MSN_CAP_SCHANNEL)
-			return "secure";
-#endif
-		if (user->clientid & MSN_CAP_VIA_WEBIM)
-			return "external";
-		if (user->networkid == MSN_NETWORK_YAHOO)
-			return "yahoo";
-	}
-
-	return NULL;
-}
-
-/*
- * Set the User status text
- */
-static char *
-msn_status_text(PurpleBuddy *buddy)
-{
-	PurplePresence *presence;
-	PurpleStatus *status;
-	const char *msg;
-
-	presence = purple_buddy_get_presence(buddy);
-	status = purple_presence_get_active_status(presence);
-
-	/* Official client says media takes precedence over message */
-	/* I say message take precedence over media! Plus prpl-jabber agrees
-	   too */
-	msg = purple_status_get_attr_string(status, "message");
-	if (msg && *msg)
-		return g_markup_escape_text(msg, -1);
-
-	if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
-		const char *title, *game, *office;
-		char *media, *esc;
-		status = purple_presence_get_status(presence, "tune");
-		title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
-
-		game = purple_status_get_attr_string(status, "game");
-		office = purple_status_get_attr_string(status, "office");
-
-		if (title && *title) {
-			const char *artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
-			const char *album = purple_status_get_attr_string(status, PURPLE_TUNE_ALBUM);
-			media = purple_util_format_song_info(title, artist, album, NULL);
-			return media;
-		}
-		else if (game && *game)
-			media = g_strdup_printf("Playing %s", game);
-		else if (office && *office)
-			media = g_strdup_printf("Editing %s", office);
-		else
-			return NULL;
-		esc = g_markup_escape_text(media, -1);
-		g_free(media);
-		return esc;
-	}
-
-	return NULL;
-}
-
-static void
-msn_tooltip_text(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, gboolean full)
-{
-	MsnUser *user;
-	PurplePresence *presence = purple_buddy_get_presence(buddy);
-	PurpleStatus *status = purple_presence_get_active_status(presence);
-
-	user = purple_buddy_get_protocol_data(buddy);
-
-	if (purple_presence_is_online(presence))
-	{
-		const char *psm, *name;
-		const char *mediatype = NULL;
-		char *currentmedia = NULL;
-
-		psm = purple_status_get_attr_string(status, "message");
-		if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
-			PurpleStatus *tune = purple_presence_get_status(presence, "tune");
-			const char *title = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE);
-			const char *game = purple_status_get_attr_string(tune, "game");
-			const char *office = purple_status_get_attr_string(tune, "office");
-			if (title && *title) {
-				const char *artist = purple_status_get_attr_string(tune, PURPLE_TUNE_ARTIST);
-				const char *album = purple_status_get_attr_string(tune, PURPLE_TUNE_ALBUM);
-				mediatype = _("Now Listening");
-				currentmedia = purple_util_format_song_info(title, artist, album, NULL);
-			} else if (game && *game) {
-				mediatype = _("Playing a game");
-				currentmedia = g_strdup(game);
-			} else if (office && *office) {
-				mediatype = _("Working");
-				currentmedia = g_strdup(office);
-			}
-		}
-
-		if (!purple_status_is_available(status)) {
-			name = purple_status_get_name(status);
-		} else {
-			name = NULL;
-		}
-
-		if (name != NULL && *name) {
-			char *tmp2;
-
-			tmp2 = g_markup_escape_text(name, -1);
-			if (purple_presence_is_idle(presence)) {
-				char *idle;
-				char *tmp3;
-				/* Never know what those translations might end up like... */
-				idle = g_markup_escape_text(_("Idle"), -1);
-				tmp3 = g_strdup_printf("%s/%s", tmp2, idle);
-				g_free(idle);
-				g_free(tmp2);
-				tmp2 = tmp3;
-			}
-
-			if (psm != NULL && *psm) {
-				purple_notify_user_info_add_pair_plaintext(user_info, tmp2, psm);
-			} else {
-				purple_notify_user_info_add_pair(user_info, _("Status"), tmp2);
-			}
-
-			g_free(tmp2);
-		} else {
-			if (psm != NULL && *psm) {
-				if (purple_presence_is_idle(presence)) {
-					purple_notify_user_info_add_pair_plaintext(user_info, _("Idle"), psm);
-				} else {
-					purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), psm);
-				}
-			} else {
-				if (purple_presence_is_idle(presence)) {
-					purple_notify_user_info_add_pair(user_info, _("Status"),
-						_("Idle"));
-				} else {
-					purple_notify_user_info_add_pair(user_info, _("Status"),
-						purple_status_get_name(status));
-				}
-			}
-		}
-
-		if (currentmedia) {
-			purple_notify_user_info_add_pair(user_info, mediatype, currentmedia);
-			g_free(currentmedia);
-		}
-	}
-
-	/* XXX: This is being shown in non-full tooltips because the
-	 * XXX: blocked icon overlay isn't always accurate for MSN.
-	 * XXX: This can die as soon as purple_privacy_check() knows that
-	 * XXX: this prpl always honors both the allow and deny lists. */
-	/* While the above comment may be strictly correct (the privacy API needs
-	 * rewriteing), purple_privacy_check() is going to be more accurate at
-	 * indicating whether a particular buddy is going to be able to message
-	 * you, which is the important information that this is trying to convey.
-	 */
-	if (full && user)
-	{
-		const char *phone;
-
-		purple_notify_user_info_add_pair(user_info, _("Has you"),
-									   ((user->list_op & (1 << MSN_LIST_RL)) ? _("Yes") : _("No")));
-
-		purple_notify_user_info_add_pair(user_info, _("Blocked"),
-									   ((user->list_op & (1 << MSN_LIST_BL)) ? _("Yes") : _("No")));
-
-		phone = msn_user_get_home_phone(user);
-		if (phone != NULL)
-			purple_notify_user_info_add_pair(user_info, _("Home Phone Number"), phone);
-
-		phone = msn_user_get_work_phone(user);
-		if (phone != NULL)
-			purple_notify_user_info_add_pair(user_info, _("Work Phone Number"), phone);
-
-		phone = msn_user_get_mobile_phone(user);
-		if (phone != NULL)
-			purple_notify_user_info_add_pair(user_info, _("Mobile Phone Number"), phone);
-	}
-}
-
-static GList *
-msn_status_types(PurpleAccount *account)
-{
-	PurpleStatusType *status;
-	GList *types = NULL;
-
-	status = purple_status_type_new_with_attrs(
-				PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE, TRUE, FALSE,
-				"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-				NULL);
-	types = g_list_append(types, status);
-
-	status = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_AWAY, NULL, NULL, TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
-	types = g_list_append(types, status);
-
-	status = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_AWAY, "brb", _("Be Right Back"), TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
-	types = g_list_append(types, status);
-
-	status = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_UNAVAILABLE, "busy", _("Busy"), TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
-	types = g_list_append(types, status);
-	status = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_UNAVAILABLE, "phone", _("On the Phone"), TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
-	types = g_list_append(types, status);
-	status = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_AWAY, "lunch", _("Out to Lunch"), TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
-	types = g_list_append(types, status);
-
-	status = purple_status_type_new_full(PURPLE_STATUS_INVISIBLE,
-			NULL, NULL, TRUE, TRUE, FALSE);
-	types = g_list_append(types, status);
-
-	status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE,
-			NULL, NULL, TRUE, TRUE, FALSE);
-	types = g_list_append(types, status);
-
-	status = purple_status_type_new_full(PURPLE_STATUS_MOBILE,
-			"mobile", NULL, FALSE, FALSE, TRUE);
-	types = g_list_append(types, status);
-
-	status = purple_status_type_new_with_attrs(PURPLE_STATUS_TUNE,
-			"tune", NULL, FALSE, TRUE, TRUE,
-			PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING),
-			"game", _("Game Title"), purple_value_new(PURPLE_TYPE_STRING),
-			"office", _("Office Title"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
-	types = g_list_append(types, status);
-
-	return types;
-}
-
-static GList *
-msn_actions(PurplePlugin *plugin, gpointer context)
-{
-	PurpleConnection *gc;
-	MsnSession *session;
-	GList *m = NULL;
-	PurplePluginAction *act;
-
-	gc = (PurpleConnection *) context;
-	session = gc->proto_data;
-
-	act = purple_plugin_action_new(_("Set Friendly Name..."),
-								 msn_show_set_friendly_name);
-	m = g_list_append(m, act);
-	m = g_list_append(m, NULL);
-
-	if (session->enable_mpop)
-	{
-		act = purple_plugin_action_new(_("View Locations..."),
-		                               msn_show_locations);
-		m = g_list_append(m, act);
-		m = g_list_append(m, NULL);
-	}
-
-	act = purple_plugin_action_new(_("Set Home Phone Number..."),
-								 msn_show_set_home_phone);
-	m = g_list_append(m, act);
-
-	act = purple_plugin_action_new(_("Set Work Phone Number..."),
-			msn_show_set_work_phone);
-	m = g_list_append(m, act);
-
-	act = purple_plugin_action_new(_("Set Mobile Phone Number..."),
-			msn_show_set_mobile_phone);
-	m = g_list_append(m, act);
-	m = g_list_append(m, NULL);
-
-#if 0
-	act = purple_plugin_action_new(_("Enable/Disable Mobile Devices..."),
-			msn_show_set_mobile_support);
-	m = g_list_append(m, act);
-#endif
-
-	act = purple_plugin_action_new(_("Allow/Disallow Multiple Logins..."),
-			msn_show_set_mpop);
-	m = g_list_append(m, act);
-
-	act = purple_plugin_action_new(_("Allow/Disallow Mobile Pages..."),
-			msn_show_set_mobile_pages);
-	m = g_list_append(m, act);
-
-/* QuLogic: Disabled until confirmed correct. */
-#if 0
-	m = g_list_append(m, NULL);
-	act = purple_plugin_action_new(_("View Blocked Text..."),
-			msn_show_blocked_text);
-	m = g_list_append(m, act);
-#endif
-
-	m = g_list_append(m, NULL);
-	act = purple_plugin_action_new(_("Open Hotmail Inbox"),
-			msn_show_hotmail_inbox);
-	m = g_list_append(m, act);
-
-	return m;
-}
-
-static GList *
-msn_buddy_menu(PurpleBuddy *buddy)
-{
-	MsnUser *user;
-
-	GList *m = NULL;
-	PurpleMenuAction *act;
-
-	g_return_val_if_fail(buddy != NULL, NULL);
-
-	user = purple_buddy_get_protocol_data(buddy);
-
-	if (user != NULL)
-	{
-		if (user->mobile)
-		{
-			act = purple_menu_action_new(_("Send to Mobile"),
-			                           PURPLE_CALLBACK(show_send_to_mobile_cb),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		}
-	}
-
-	if (g_ascii_strcasecmp(purple_buddy_get_name(buddy),
-				purple_account_get_username(purple_buddy_get_account(buddy))))
-	{
-		act = purple_menu_action_new(_("Initiate _Chat"),
-		                           PURPLE_CALLBACK(initiate_chat_cb),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-	}
-
-	return m;
-}
-
-static GList *
-msn_blist_node_menu(PurpleBlistNode *node)
-{
-	if(PURPLE_BLIST_NODE_IS_BUDDY(node))
-	{
-		return msn_buddy_menu((PurpleBuddy *) node);
-	}
-	else
-	{
-		return NULL;
-	}
-}
-
-static void
-msn_login(PurpleAccount *account)
-{
-	PurpleConnection *gc;
-	MsnSession *session;
-	const char *username;
-	const char *host;
-	gboolean http_method = FALSE;
-	int port;
-
-	gc = purple_account_get_connection(account);
-
-	if (!purple_ssl_is_supported())
-	{
-		purple_connection_error_reason(gc,
-			PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
-			_("SSL support is needed for MSN. Please install a supported "
-			  "SSL library."));
-		return;
-	}
-
-	http_method = purple_account_get_bool(account, "http_method", FALSE);
-
-	if (http_method)
-		host = purple_account_get_string(account, "http_method_server", MSN_HTTPCONN_SERVER);
-	else
-		host = purple_account_get_string(account, "server", MSN_SERVER);
-	port = purple_account_get_int(account, "port", MSN_PORT);
-
-	session = msn_session_new(account);
-
-	gc->proto_data = session;
-	gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_FORMATTING_WBFO | PURPLE_CONNECTION_NO_BGCOLOR |
-		PURPLE_CONNECTION_NO_FONTSIZE | PURPLE_CONNECTION_NO_URLDESC | PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY;
-
-	msn_session_set_login_step(session, MSN_LOGIN_STEP_START);
-
-	/* Hmm, I don't like this. */
-	/* XXX shx: Me neither */
-	username = msn_normalize(account, purple_account_get_username(account));
-
-	if (strcmp(username, purple_account_get_username(account)))
-		purple_account_set_username(account, username);
-
-	username = purple_account_get_string(account, "display-name", NULL);
-	purple_connection_set_display_name(gc, username);
-
-	if (purple_account_get_string(account, "endpoint-name", NULL) == NULL) {
-		GHashTable *ui_info = purple_core_get_ui_info();
-		const gchar *ui_name = ui_info ? g_hash_table_lookup(ui_info, "name") : NULL;
-		purple_account_set_string(account, "endpoint-name",
-				ui_name && *ui_name ? ui_name : PACKAGE_NAME);
-	}
-
-	if (!msn_session_connect(session, host, port, http_method))
-		purple_connection_error_reason(gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("Unable to connect"));
-}
-
-static void
-msn_close(PurpleConnection *gc)
-{
-	MsnSession *session;
-
-	session = gc->proto_data;
-
-	g_return_if_fail(session != NULL);
-
-	msn_session_destroy(session);
-
-	gc->proto_data = NULL;
-}
-
-static gboolean
-msn_send_me_im(gpointer data)
-{
-	MsnIMData *imdata = data;
-	serv_got_im(imdata->gc, imdata->who, imdata->msg, imdata->flags, imdata->when);
-	g_free(imdata->msg);
-	g_free(imdata);
-	return FALSE;
-}
-
-static GString*
-msn_msg_emoticon_add(GString *current, MsnEmoticon *emoticon)
-{
-	MsnObject *obj;
-	char *strobj;
-
-	if (emoticon == NULL)
-		return current;
-
-	obj = emoticon->obj;
-
-	if (!obj)
-		return current;
-
-	strobj = msn_object_to_string(obj);
-
-	if (current)
-		g_string_append_printf(current, "\t%s\t%s", emoticon->smile, strobj);
-	else {
-		current = g_string_new("");
-		g_string_printf(current, "%s\t%s", emoticon->smile, strobj);
-	}
-
-	g_free(strobj);
-
-	return current;
-}
-
-static void
-msn_send_emoticons(MsnSwitchBoard *swboard, GString *body)
-{
-	MsnMessage *msg;
-
-	g_return_if_fail(body != NULL);
-
-	msg = msn_message_new(MSN_MSG_SLP);
-	msn_message_set_content_type(msg, "text/x-mms-emoticon");
-	msn_message_set_flag(msg, 'N');
-	msn_message_set_bin_data(msg, body->str, body->len);
-
-	msn_switchboard_send_msg(swboard, msg, TRUE);
-	msn_message_unref(msg);
-}
-
-static void msn_emoticon_destroy(MsnEmoticon *emoticon)
-{
-	if (emoticon->obj)
-		msn_object_destroy(emoticon->obj);
-	g_free(emoticon->smile);
-	g_free(emoticon);
-}
-
-static GSList* msn_msg_grab_emoticons(const char *msg, const char *username)
-{
-	GSList *list;
-	GList *smileys;
-	PurpleSmiley *smiley;
-	PurpleStoredImage *img;
-	char *ptr;
-	MsnEmoticon *emoticon;
-	int length;
-
-	list = NULL;
-	smileys = purple_smileys_get_all();
-	length = strlen(msg);
-
-	for (; smileys; smileys = g_list_delete_link(smileys, smileys)) {
-		smiley = smileys->data;
-
-		ptr = g_strstr_len(msg, length, purple_smiley_get_shortcut(smiley));
-
-		if (!ptr)
-			continue;
-
-		img = purple_smiley_get_stored_image(smiley);
-
-		emoticon = g_new0(MsnEmoticon, 1);
-		emoticon->smile = g_strdup(purple_smiley_get_shortcut(smiley));
-		emoticon->ps = smiley;
-		emoticon->obj = msn_object_new_from_image(img,
-				purple_imgstore_get_filename(img),
-				username, MSN_OBJECT_EMOTICON);
-
-		purple_imgstore_unref(img);
-		list = g_slist_prepend(list, emoticon);
-	}
-
-	return list;
-}
-
-void
-msn_send_im_message(MsnSession *session, MsnMessage *msg)
-{
-	MsnEmoticon *smile;
-	GSList *smileys;
-	GString *emoticons = NULL;
-	const char *username = purple_account_get_username(session->account);
-	MsnSwitchBoard *swboard = msn_session_get_swboard(session, msg->remote_user, MSN_SB_FLAG_IM);
-
-	smileys = msn_msg_grab_emoticons(msg->body, username);
-	while (smileys) {
-		smile = (MsnEmoticon *)smileys->data;
-		emoticons = msn_msg_emoticon_add(emoticons, smile);
-		msn_emoticon_destroy(smile);
-		smileys = g_slist_delete_link(smileys, smileys);
-	}
-
-	if (emoticons) {
-		msn_send_emoticons(swboard, emoticons);
-		g_string_free(emoticons, TRUE);
-	}
-
-	msn_switchboard_send_msg(swboard, msg, TRUE);
-}
-
-static int
-msn_send_im(PurpleConnection *gc, const char *who, const char *message,
-			PurpleMessageFlags flags)
-{
-	PurpleAccount *account;
-	PurpleBuddy *buddy = purple_find_buddy(gc->account, who);
-	MsnSession *session;
-	MsnSwitchBoard *swboard;
-	MsnMessage *msg;
-	char *msgformat;
-	char *msgtext;
-	size_t msglen;
-	const char *username;
-
-	purple_debug_info("msn", "send IM {%s} to %s\n", message, who);
-	account = purple_connection_get_account(gc);
-	username = purple_account_get_username(account);
-
-	session = gc->proto_data;
-	swboard = msn_session_find_swboard(session, who);
-
-	if (!strncmp("tel:+", who, 5)) {
-		char *text = purple_markup_strip_html(message);
-		send_to_mobile(gc, who, text);
-		g_free(text);
-		return 1;
-	}
-
-	if (buddy) {
-		PurplePresence *p = purple_buddy_get_presence(buddy);
-		if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_MOBILE)) {
-			char *text = purple_markup_strip_html(message);
-			send_to_mobile(gc, who, text);
-			g_free(text);
-			return 1;
-		}
-	}
-
-	msn_import_html(message, &msgformat, &msgtext);
-	msglen = strlen(msgtext);
-	if (msglen == 0) {
-		/* Stuff like <hr> will be ignored. Don't send an empty message
-		   if that's all there is. */
-		g_free(msgtext);
-		g_free(msgformat);
-
-		return 0;
-	}
-
-	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);
-
-	g_free(msgformat);
-	g_free(msgtext);
-
-	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 offline or 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);
-
-	return 1;
-}
-
-static unsigned int
-msn_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state)
-{
-	PurpleAccount *account;
-	MsnSession *session;
-	MsnSwitchBoard *swboard;
-	MsnMessage *msg;
-
-	account = purple_connection_get_account(gc);
-	session = gc->proto_data;
-
-	/*
-	 * TODO: I feel like this should be "if (state != PURPLE_TYPING)"
-	 *       but this is how it was before, and I don't want to break
-	 *       anything. --KingAnt
-	 */
-	if (state == PURPLE_NOT_TYPING)
-		return 0;
-
-	if (!g_ascii_strcasecmp(who, purple_account_get_username(account)))
-	{
-		/* We'll just fake it, since we're sending to ourself. */
-		serv_got_typing(gc, who, MSN_TYPING_RECV_TIMEOUT, PURPLE_TYPING);
-
-		return MSN_TYPING_SEND_TIMEOUT;
-	}
-
-	swboard = msn_session_find_swboard(session, who);
-
-	if (swboard == NULL || !msn_switchboard_can_send(swboard))
-		return 0;
-
-	swboard->flag |= MSN_SB_FLAG_IM;
-
-	msg = msn_message_new(MSN_MSG_TYPING);
-	msn_message_set_content_type(msg, "text/x-msmsgscontrol");
-	msn_message_set_flag(msg, 'U');
-	msn_message_set_header(msg, "TypingUser",
-						 purple_account_get_username(account));
-	msn_message_set_bin_data(msg, "\r\n", 2);
-
-	msn_switchboard_send_msg(swboard, msg, FALSE);
-
-	msn_message_unref(msg);
-
-	return MSN_TYPING_SEND_TIMEOUT;
-}
-
-static void
-msn_set_status(PurpleAccount *account, PurpleStatus *status)
-{
-	PurpleConnection *gc;
-	MsnSession *session;
-
-	gc = purple_account_get_connection(account);
-
-	if (gc != NULL)
-	{
-		session = gc->proto_data;
-		msn_change_status(session);
-	}
-}
-
-static void
-msn_set_idle(PurpleConnection *gc, int idle)
-{
-	MsnSession *session;
-
-	session = gc->proto_data;
-
-	msn_change_status(session);
-}
-
-/*
- * Actually adds a buddy once we have the response from FQY
- */
-static void
-add_pending_buddy(MsnSession *session,
-                  const char *who,
-                  MsnNetwork network,
-                  MsnUser *user)
-{
-	char *group;
-	MsnUserList *userlist;
-	MsnUser *user2;
-
-	g_return_if_fail(user != NULL);
-
-	if (network == MSN_NETWORK_UNKNOWN) {
-		purple_debug_error("msn", "Network in FQY response was unknown.  "
-				"Assuming %s is a passport user and adding anyway.\n", who);
-		network = MSN_NETWORK_PASSPORT;
-	}
-
-	group = msn_user_remove_pending_group(user);
-
-	userlist = session->userlist;
-	user2 = msn_userlist_find_user(userlist, who);
-	if (user2 != NULL) {
-		/* User already in userlist, so just update it. */
-		msn_user_unref(user);
-		user = user2;
-	} else {
-		msn_userlist_add_user(userlist, user);
-		msn_user_unref(user);
-	}
-
-	msn_user_set_network(user, network);
-	msn_userlist_add_buddy(userlist, who, group);