changeset 9158:c30d81b4dd22

[gaim-migrate @ 9942] Patch from Felipe Contreras to sync our MSN prpl with what's in his tree. He says this may fix a couple bugs, but the important thing is the restructuring of how MsnMessages work. Lots of style changes and other stuff as well. committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Tue, 01 Jun 2004 06:42:20 +0000
parents bd1ea0a717d7
children 31be05742be9
files ChangeLog src/protocols/msn/cmdproc.c src/protocols/msn/cmdproc.h src/protocols/msn/httpmethod.c src/protocols/msn/httpmethod.h src/protocols/msn/msg.c src/protocols/msn/msg.h src/protocols/msn/msn.c src/protocols/msn/msnslp.c src/protocols/msn/notification.c src/protocols/msn/page.h src/protocols/msn/servconn.c src/protocols/msn/servconn.h src/protocols/msn/session.c src/protocols/msn/session.h src/protocols/msn/switchboard.c src/protocols/msn/switchboard.h src/protocols/msn/transaction.c
diffstat 18 files changed, 570 insertions(+), 723 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Jun 01 01:55:55 2004 +0000
+++ b/ChangeLog	Tue Jun 01 06:42:20 2004 +0000
@@ -4,6 +4,7 @@
 	New Features:
 	* Display name changes are now shown in the conversation windows.
 	  (Robert Mibus)
+
 	Bug Fixes:
 	* Non-looping animated icons no longer cause Gaim to freeze
 	* Fixed a crash in SILC that sometimes happened when resolving
--- a/src/protocols/msn/cmdproc.c	Tue Jun 01 01:55:55 2004 +0000
+++ b/src/protocols/msn/cmdproc.c	Tue Jun 01 06:42:20 2004 +0000
@@ -120,7 +120,7 @@
 {
 	MsnServConn *servconn;
 	char *data;
-	size_t len;
+	gsize len;
 
 	g_return_if_fail(cmdproc != NULL);
 	g_return_if_fail(trans != NULL);
@@ -129,7 +129,7 @@
 	msn_history_add(cmdproc->history, trans);
 
 	data = msn_transaction_to_string(trans);
-	
+
 	cmdproc->last_trans = g_strdup(data);
 
 	len = strlen(data);
@@ -167,7 +167,8 @@
 
 	servconn = cmdproc->servconn;
 
-	if (format != NULL) {
+	if (format != NULL)
+	{
 		va_start(arg, format);
 		params = g_strdup_vprintf(format, arg);
 		va_end(arg);
@@ -203,7 +204,8 @@
 
 	trans->command = g_strdup(command);
 
-	if (format != NULL) {
+	if (format != NULL)
+	{
 		va_start(arg, format);
 		trans->params = g_strdup_vprintf(format, arg);
 		va_end(arg);
@@ -213,6 +215,16 @@
 }
 
 void
+msn_cmdproc_process_payload(MsnCmdProc *cmdproc, char *payload,
+							int payload_len)
+{
+	g_return_if_fail(cmdproc             != NULL);
+	g_return_if_fail(cmdproc->payload_cb != NULL);
+
+	cmdproc->payload_cb(cmdproc, payload, payload_len);
+}
+
+void
 msn_cmdproc_process_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
 {
 	MsnServConn *servconn;
@@ -225,9 +237,8 @@
 
 	if (cb == NULL)
 	{
-		gaim_debug_warning("msn", "Unhandled content-type '%s': %s\n",
-						   msn_message_get_content_type(msg),
-						   msn_message_get_body(msg));
+		gaim_debug_warning("msn", "Unhandled content-type '%s'\n",
+						   msn_message_get_content_type(msg));
 
 		return;
 	}
@@ -236,15 +247,6 @@
 }
 
 void
-msn_cmdproc_process_payload(MsnCmdProc *cmdproc, char *payload, int payload_len)
-{
-	g_return_if_fail(cmdproc             != NULL);
-	g_return_if_fail(cmdproc->payload_cb != NULL);
-
-	cmdproc->payload_cb(cmdproc, payload, payload_len);
-}
-
-void
 msn_cmdproc_process_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
 	MsnSession *session;
@@ -305,7 +307,7 @@
 	else
 	{
 		gaim_debug_warning("msn", "Unhandled command '%s'\n",
-							cmd->command);
+						   cmd->command);
 
 		return;
 	}
--- a/src/protocols/msn/cmdproc.h	Tue Jun 01 01:55:55 2004 +0000
+++ b/src/protocols/msn/cmdproc.h	Tue Jun 01 06:42:20 2004 +0000
@@ -25,7 +25,7 @@
 typedef struct _MsnCmdProc MsnCmdProc;
 
 #include "session.h"
-#include "server.h"
+#include "servconn.h"
 #include "error.h"
 #include "command.h"
 #include "table.h"
@@ -69,7 +69,7 @@
 void msn_cmdproc_send(MsnCmdProc *cmdproc, const char *command,
 					  const char *format, ...);
 void msn_cmdproc_send_quick(MsnCmdProc *cmdproc, const char *command,
-					  const char *format, ...);
+							const char *format, ...);
 void msn_cmdproc_process_msg(MsnCmdProc *cmdproc,
 							 MsnMessage *msg);
 void msn_cmdproc_process_cmd_text(MsnCmdProc *cmdproc, const char *command);
--- a/src/protocols/msn/httpmethod.c	Tue Jun 01 01:55:55 2004 +0000
+++ b/src/protocols/msn/httpmethod.c	Tue Jun 01 06:42:20 2004 +0000
@@ -60,7 +60,7 @@
 		{
 #if 0
 			gaim_debug_info("msn", "Polling server %s.\n",
-							servconn->http_data->gateway_ip);
+							servconn->http_data->gateway_host);
 #endif
 			msn_http_servconn_poll(servconn);
 		}
@@ -141,12 +141,12 @@
 		{
 			params = g_strdup_printf("Action=open&Server=%s&IP=%s",
 									 server_type,
-									 servconn->http_data->gateway_ip);
+									 servconn->http_data->gateway_host);
 		}
 		else
 		{
 			params = g_strdup_printf("Action=open&IP=%s",
-									 servconn->http_data->gateway_ip);
+									 servconn->http_data->gateway_host);
 		}
 	}
 	else
@@ -170,9 +170,9 @@
 		"%s",
 		((strcmp(server_type, "SB") == 0) && first
 		 ? "gateway.messenger.hotmail.com"
-		 : servconn->http_data->gateway_ip),
+		 : servconn->http_data->gateway_host),
 		params,
-		servconn->http_data->gateway_ip,
+		servconn->http_data->gateway_host,
 		(int)size,
 		buf);
 
@@ -186,11 +186,13 @@
 	s = 0;
 	needed = strlen(temp);
 
-	do {
+	do
+	{
 		res = write(servconn->fd, temp, needed);
 		if (res >= 0)
 			s += res;
-		else if (errno != EAGAIN) {
+		else if (errno != EAGAIN)
+		{
 			char *msg = g_strdup_printf("Unable to write to MSN server via HTTP (error %d)", errno);
 			gaim_connection_error(servconn->session->account->gc, msg);
 			g_free(msg);
@@ -234,9 +236,9 @@
 		"Content-Type: application/x-msn-messenger\r\n"
 		"Content-Length: 0\r\n"
 		"\r\n",
-		servconn->http_data->gateway_ip,
+		servconn->http_data->gateway_host,
 		servconn->http_data->session_id,
-		servconn->http_data->gateway_ip);
+		servconn->http_data->gateway_host);
 
 #if 0
 	gaim_debug_misc("msn", "Writing to HTTP: {%s}\n", temp);
@@ -273,7 +275,8 @@
 	g_return_val_if_fail(error    != NULL, FALSE);
 
 #if 0
-	gaim_debug_info("msn", "parsing data {%s} from fd %d\n", buf, servconn->fd);
+	gaim_debug_info("msn", "parsing data {%s} from fd %d\n",
+					buf, servconn->fd);
 #endif
 	servconn->http_data->waiting_response = FALSE;
 
@@ -286,11 +289,12 @@
 
 	/* 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)))
+		 (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;
 	}
 
@@ -408,13 +412,14 @@
 		if (servconn->http_data->session_id != NULL)
 			g_free(servconn->http_data->session_id);
 
-		if (servconn->http_data->old_gateway_ip != NULL)
-			g_free(servconn->http_data->old_gateway_ip);
+		if (servconn->http_data->old_gateway_host != NULL)
+			g_free(servconn->http_data->old_gateway_host);
 
-		servconn->http_data->old_gateway_ip = servconn->http_data->gateway_ip;
+		servconn->http_data->old_gateway_host =
+			servconn->http_data->gateway_host;
 
 		servconn->http_data->session_id = session_id;
-		servconn->http_data->gateway_ip = gw_ip;
+		servconn->http_data->gateway_host = gw_ip;
 	}
 
 	g_free(headers);
--- a/src/protocols/msn/httpmethod.h	Tue Jun 01 01:55:55 2004 +0000
+++ b/src/protocols/msn/httpmethod.h	Tue Jun 01 06:42:20 2004 +0000
@@ -29,8 +29,8 @@
 struct _MsnHttpMethodData
 {
 	char *session_id;
-	char *old_gateway_ip;
-	char *gateway_ip;
+	char *old_gateway_host;
+	char *gateway_host;
 	const char *server_type;
 
 	int timer;
--- a/src/protocols/msn/msg.c	Tue Jun 01 01:55:55 2004 +0000
+++ b/src/protocols/msn/msg.c	Tue Jun 01 06:42:20 2004 +0000
@@ -54,17 +54,6 @@
 		(((*((buf)+3)    )&0x000000ff)))
 
 
-/*
- * "MIME-Version: 1.0\r\n" == 19
- * "Content-Type: "        == 14
- * "\r\n"                  ==  2
- * "\r\n" before body      ==  2
- *                           ----
- *                            37
- *  MATH PAYS OFF!!
- */
-#define MSN_MESSAGE_BASE_SIZE 37
-
 MsnMessage *
 msn_message_new(void)
 {
@@ -74,14 +63,29 @@
 
 	msg->attr_table = g_hash_table_new_full(g_str_hash, g_str_equal,
 											g_free, g_free);
-	msg->size = MSN_MESSAGE_BASE_SIZE;
+
+	msn_message_ref(msg);
+
+	return msg;
+}
 
+MsnMessage *
+msn_message_new_plain(const char *message)
+{
+	MsnMessage *msg;
+	char *message_cr;
+
+	msg = msn_message_new();
 	msn_message_set_attr(msg, "User-Agent", "Gaim/" VERSION);
 	msn_message_set_content_type(msg, "text/plain");
 	msn_message_set_charset(msg, "UTF-8");
-	msn_message_set_flag(msg, 'U');
+	msn_message_set_flag(msg, 'N');
+	msn_message_set_attr(msg, "X-MMS-IM-Format",
+						 "FN=MS%20Sans%20Serif; EF=; CO=0; PF=0");
 
-	msn_message_ref(msg);
+	message_cr = gaim_str_add_cr(message);
+	msn_message_set_bin_data(msg, message_cr, strlen(message_cr));
+	g_free(message_cr);
 
 	return msg;
 }
@@ -96,11 +100,9 @@
 	msn_message_set_attr(msg, "User-Agent", NULL);
 
 	msg->msnslp_message = TRUE;
-	msg->size += 52;
 
 	msn_message_set_flag(msg, 'D');
 	msn_message_set_content_type(msg, "application/x-msnmsgrp2p");
-	msn_message_set_charset(msg, NULL);
 
 	return msg;
 }
@@ -118,35 +120,31 @@
 	msg->msnslp_ack_message = TRUE;
 	msg->acked_msg = msn_message_ref(acked_msg);
 
-	msg->msnslp_header.session_id     = acked_msg->msnslp_header.session_id;
-	msg->msnslp_header.total_size_1   = acked_msg->msnslp_header.total_size_1;
-	msg->msnslp_header.total_size_2   = acked_msg->msnslp_header.total_size_2;
-	msg->msnslp_header.flags          = 0x02;
-	msg->msnslp_header.ack_session_id = acked_msg->msnslp_header.session_id;
-	msg->msnslp_header.ack_unique_id  = acked_msg->msnslp_header.ack_session_id;
-	msg->msnslp_header.ack_length_1   = acked_msg->msnslp_header.total_size_1;
-	msg->msnslp_header.ack_length_2   = acked_msg->msnslp_header.total_size_2;
+	msg->msnslp_header.session_id  = acked_msg->msnslp_header.session_id;
+	msg->msnslp_header.total_size  = acked_msg->msnslp_header.total_size;
+	msg->msnslp_header.flags       = 0x02;
+	msg->msnslp_header.ack_id      = acked_msg->msnslp_header.id;
+	msg->msnslp_header.ack_sub_id  = acked_msg->msnslp_header.ack_id;
+	msg->msnslp_header.ack_size    = acked_msg->msnslp_header.total_size;
 
 	return msg;
 }
 
 void
-msn_message_parse_payload(MsnMessage *msg, const char *payload,
-						  size_t payload_len)
+msn_message_parse_payload(MsnMessage *msg,
+						  const char *payload, size_t payload_len)
 {
-	char *tmp_base, *tmp, *c;
+	char *tmp_base, *tmp;
 	const char *content_type;
 
-	tmp_base = g_malloc(payload_len + 1);
-	memcpy(tmp_base, payload, payload_len);
-	tmp_base[payload_len] = '\0';
+	g_return_if_fail(payload != NULL);
 
-	tmp = tmp_base;
+	tmp_base = tmp = g_memdup(payload, payload_len);
 
 	/* Back to the parsination. */
 	while (*tmp != '\r')
 	{
-		char *key, *value;
+		char *key, *value, *c;
 
 		key = tmp;
 
@@ -159,6 +157,9 @@
 		if ((c = strchr(key, ':')) != NULL)
 			*c = '\0';
 
+		if (!g_ascii_strcasecmp(key, "MIME-Version"))
+			continue;
+
 		if (!g_ascii_strcasecmp(key, "Content-Type"))
 		{
 			char *charset;
@@ -189,83 +190,43 @@
 	if (content_type != NULL &&
 		!strcmp(content_type, "application/x-msnmsgrp2p"))
 	{
-		char header[48];
-		char footer[4];
-		size_t body_len;
-		char *tmp2;
+		MsnSlpHeader header;
+		MsnSlpFooter footer;
 
 		msg->msnslp_message = TRUE;
 
-		memcpy(header, tmp, 48);
-
-		tmp += 48;
-
-		body_len = payload_len - (tmp - tmp_base) - 4;
-
-		if (body_len > 0)
-		{
-			msg->body = g_malloc(body_len + 1);
-			memcpy(msg->body, tmp, body_len);
-			msg->body[body_len] = '\0';
-
-			tmp++;
-		}
-		else
-			msg->body = NULL;
-
-		memcpy(footer, tmp, 4);
-
-		tmp += 4;
+		/* Import the header. */
+		memcpy(&header, tmp, sizeof(header));
+		tmp += sizeof(header);
 
-		/* Import the header. */
-		tmp2 = header;
-		msg->msnslp_header.session_id     = msn_get32(tmp2); tmp2 += 4;
-		msg->msnslp_header.id             = msn_get32(tmp2); tmp2 += 4;
-		msg->msnslp_header.offset_1       = msn_get32(tmp2); tmp2 += 4;
-		msg->msnslp_header.offset_2       = msn_get32(tmp2); tmp2 += 4;
-		msg->msnslp_header.total_size_1   = msn_get32(tmp2); tmp2 += 4;
-		msg->msnslp_header.total_size_2   = msn_get32(tmp2); tmp2 += 4;
-		msg->msnslp_header.length         = msn_get32(tmp2); tmp2 += 4;
-		msg->msnslp_header.flags          = msn_get32(tmp2); tmp2 += 4;
-		msg->msnslp_header.ack_session_id = msn_get32(tmp2); tmp2 += 4;
-		msg->msnslp_header.ack_unique_id  = msn_get32(tmp2); tmp2 += 4;
-		msg->msnslp_header.ack_length_1   = msn_get32(tmp2); tmp2 += 4;
-		msg->msnslp_header.ack_length_2   = msn_get32(tmp2); tmp2 += 4;
+		msg->msnslp_header.session_id = GUINT32_FROM_LE(header.session_id);
+		msg->msnslp_header.id         = GUINT64_FROM_LE(header.id);
+		msg->msnslp_header.offset     = GUINT64_FROM_LE(header.offset);
+		msg->msnslp_header.total_size = GUINT32_FROM_LE(header.total_size);
+		msg->msnslp_header.length     = GUINT32_FROM_LE(header.length);
+		msg->msnslp_header.flags      = GUINT32_FROM_LE(header.flags);
+		msg->msnslp_header.ack_id     = GUINT32_FROM_LE(header.ack_id);
+		msg->msnslp_header.ack_sub_id = GUINT32_FROM_LE(header.ack_sub_id);
+		msg->msnslp_header.ack_size   = GUINT64_FROM_LE(header.ack_size);
 
-		/* Convert to the right endianness */
-		msg->msnslp_header.session_id = ntohl(msg->msnslp_header.session_id);
-		msg->msnslp_header.id         = ntohl(msg->msnslp_header.id);
-		msg->msnslp_header.length     = ntohl(msg->msnslp_header.length);
-		msg->msnslp_header.flags      = ntohl(msg->msnslp_header.flags);
-		msg->msnslp_header.ack_length_1 =
-			ntohl(msg->msnslp_header.ack_length_1);
-		msg->msnslp_header.ack_length_2 =
-			ntohl(msg->msnslp_header.ack_length_2);
-		msg->msnslp_header.ack_session_id =
-			ntohl(msg->msnslp_header.ack_session_id);
-		msg->msnslp_header.ack_unique_id =
-			ntohl(msg->msnslp_header.ack_unique_id);
+		/* Import the body. */
+		msg->body_len = payload_len - (tmp - tmp_base) - sizeof(footer);
+		
+		if (msg->body_len > 0)
+			msg->body = g_memdup(tmp, msg->body_len);
+
+		tmp += msg->body_len;
 
 		/* Import the footer. */
-		msg->msnslp_footer.app_id = (long)footer;
+		memcpy(&footer, tmp, sizeof(footer));
+		tmp += sizeof(footer);
+
+		msg->msnslp_footer.value = GUINT32_FROM_BE(footer.value);
 	}
 	else
 	{
-		char *tmp2;
-		size_t body_len;
-
-		body_len = payload_len - (tmp - tmp_base);
-
-		tmp2 = g_malloc(body_len + 1);
-
-		if (body_len > 0)
-			memcpy(tmp2, tmp, body_len);
-
-		tmp2[body_len] = '\0';
-
-		msn_message_set_body(msg, tmp2);
-
-		g_free(tmp2);
+		msg->body_len = payload_len - (tmp - tmp_base);
+		msg->body = g_memdup(tmp, msg->body_len);
 	}
 
 	g_free(tmp_base);
@@ -300,7 +261,6 @@
 	if (msg->msnslp_ack_message)
 		msn_message_unref(msg->acked_msg);
 
-	gaim_debug(GAIM_DEBUG_INFO, "msn", "Destroying message\n");
 	g_free(msg);
 }
 
@@ -337,151 +297,99 @@
 msn_message_gen_payload(const MsnMessage *msg, size_t *ret_size)
 {
 	GList *l;
-	char *str;
-	char buf[MSN_BUF_LEN];
+	char *n, *base, *end;
 	int len;
+	size_t body_len;
+	const void *body;
 
-	/*
-	 * Okay, how we do things here is just bad. I don't like writing to
-	 * a static buffer and then copying to the string. Unfortunately,
-	 * just trying to append to the string is causing issues.. Such as
-	 * the string you're appending to being erased. Ugh. So, this is
-	 * good enough for now.
-	 *
-	 *     -- ChipX86
-	 */
 	g_return_val_if_fail(msg != NULL, NULL);
 
-	len = msg->size + 1;
+	len = MSN_BUF_LEN;
 
-	str = g_new0(char, len + 1);
+	base = n = end = g_malloc(len + 1);
+	end += len;
 
 	/* Standard header. */
 	if (msg->charset == NULL)
 	{
-		g_snprintf(buf, sizeof(buf),
+		g_snprintf(n, len,
 				   "MIME-Version: 1.0\r\n"
 				   "Content-Type: %s\r\n",
 				   msg->content_type);
 	}
 	else
 	{
-		g_snprintf(buf, sizeof(buf),
+		g_snprintf(n, len,
 				   "MIME-Version: 1.0\r\n"
 				   "Content-Type: %s; charset=%s\r\n",
 				   msg->content_type, msg->charset);
 	}
 
-	g_strlcat(str, buf, len);
+	n += strlen(n);
 
 	for (l = msg->attr_list; l != NULL; l = l->next)
 	{
-		const char *key = (char *)l->data;
+		const char *key;
 		const char *value;
 
+		key = l->data;
 		value = msn_message_get_attr(msg, key);
 
-		g_snprintf(buf, sizeof(buf), "%s: %s\r\n", key, value);
-
-		g_strlcat(str, buf, len);
+		g_snprintf(n, end - n, "%s: %s\r\n", key, value);
+		n += strlen(n);
 	}
 
-	g_strlcat(str, "\r\n", len);
+	n += g_strlcpy(n, "\r\n", end - n);
+
+	body = msn_message_get_bin_data(msg, &body_len);
 
 	if (msg->msnslp_message)
 	{
-		char *c;
-		long session_id, id, offset_1, offset_2, total_size_1, total_size_2;
-		long length, flags;
-		long ack_session_id, ack_unique_id, ack_length_1, ack_length_2;
-
-		c = str + strlen(str);
-
-		session_id      = htonl(msg->msnslp_header.session_id);
-		id              = htonl(msg->msnslp_header.id);
-		offset_1        = htonl(msg->msnslp_header.offset_1);
-		offset_2        = htonl(msg->msnslp_header.offset_2);
-		total_size_1    = htonl(msg->msnslp_header.total_size_1);
-		total_size_2    = htonl(msg->msnslp_header.total_size_2);
-		length          = htonl(msg->msnslp_header.length);
-		flags           = htonl(msg->msnslp_header.flags);
-		ack_session_id  = htonl(msg->msnslp_header.ack_session_id);
-		ack_unique_id   = htonl(msg->msnslp_header.ack_unique_id);
-		ack_length_1    = htonl(msg->msnslp_header.ack_length_1);
-		ack_length_2    = htonl(msg->msnslp_header.ack_length_2);
+		MsnSlpHeader header;
+		MsnSlpFooter footer;
 
-		c += msn_put32(c, session_id);
-		c += msn_put32(c, id);
-		c += msn_put32(c, offset_1);
-		c += msn_put32(c, offset_2);
-		c += msn_put32(c, total_size_1);
-		c += msn_put32(c, total_size_2);
-		c += msn_put32(c, length);
-		c += msn_put32(c, flags);
-		c += msn_put32(c, ack_session_id);
-		c += msn_put32(c, ack_unique_id);
-		c += msn_put32(c, ack_length_1);
-		c += msn_put32(c, ack_length_2);
-
-		if (msg->bin_content)
-		{
-			size_t bin_len;
-			const void *body = msn_message_get_bin_data(msg, &bin_len);
+		header.session_id = GUINT32_TO_LE(msg->msnslp_header.session_id);
+		header.id         = GUINT64_TO_LE(msg->msnslp_header.id);
+		header.offset     = GUINT64_TO_LE(msg->msnslp_header.offset);
+		header.total_size = GUINT32_TO_LE(msg->msnslp_header.total_size);
+		header.length     = GUINT32_TO_LE(msg->msnslp_header.length);
+		header.flags      = GUINT32_TO_LE(msg->msnslp_header.flags);
+		header.ack_id     = GUINT32_TO_LE(msg->msnslp_header.ack_id);
+		header.ack_sub_id = GUINT32_TO_LE(msg->msnslp_header.ack_sub_id);
+		header.ack_size   = GUINT64_TO_LE(msg->msnslp_header.ack_size);
 
-			if (body != NULL)
-			{
-				memcpy(c, body, bin_len);
+		memcpy(n, &header, 48);
+		n += 48;
 
-				c += bin_len;
-			}
-		}
-		else
+		if (body != NULL)
 		{
-			const char *body = msn_message_get_body(msg);
-
-			if (body != NULL)
-			{
-				g_strlcpy(c, body, msg->size - (c - str));
-
-				c += strlen(body);
-
-				if (strlen(body) > 0)
-					*c++ = '\0';
-			}
+			memcpy(n, body, body_len);
+			n += body_len;
 		}
 
-		c += msn_put32(c, msg->msnslp_footer.app_id);
+		footer.value = GUINT32_TO_BE(msg->msnslp_footer.value);
 
-		if (msg->size != (c - str))
-		{
-			gaim_debug(GAIM_DEBUG_ERROR, "msn",
-					   "Outgoing message size (%d) and data length (%d) "
-					   "do not match!\n", msg->size, (c - str));
-		}
+		memcpy(n, &footer, 4);
+		n += 4;
 	}
 	else
 	{
-		const char *body = msn_message_get_body(msg);
-
-		g_strlcat(str, body, len);
-
-		if (msg->size != strlen(str))
+		if (body != NULL)
 		{
-			gaim_debug(GAIM_DEBUG_ERROR, "msn",
-					   "Outgoing message size (%d) and string length (%d) "
-					   "do not match!\n", msg->size, strlen(str));
+			memcpy(n, body, body_len);
+			n += body_len;
 		}
 	}
 
 	if (ret_size != NULL)
 	{
-		*ret_size = len - 1;
+		*ret_size = n - base;
 
 		if (*ret_size > 1664)
 			*ret_size = 1664;
 	}
 
-	return str;
+	return base;
 }
 
 void
@@ -502,98 +410,26 @@
 }
 
 void
-msn_message_set_body(MsnMessage *msg, const char *body)
-{
-	const char *c;
-	char *buf, *d;
-	int newline_count = 0;
-	size_t new_len;
-
-	g_return_if_fail(msg  != NULL);
-
-	if (msg->bin_content)
-	{
-		msn_message_set_bin_data(msg, NULL, 0);
-		return;
-	}
-
-	if (msg->body != NULL) {
-		msg->size -= strlen(msg->body);
-		g_free(msg->body);
-
-		if (msg->msnslp_message)
-			msg->size--;
-	}
-
-	if (body != NULL)
-	{
-		for (c = body; *c != '\0'; c++)
-		{
-			if (*c == '\n' && (c == body || *(c - 1) != '\r'))
-				newline_count++;
-		}
-
-		new_len = strlen(body) + newline_count;
-
-		buf = g_new0(char, new_len + 1);
-
-		for (c = body, d = buf; *c != '\0'; c++) {
-			if (*c == '\n' && (c == body || *(c - 1) != '\r')) {
-				*d++ = '\r';
-				*d++ = '\n';
-			}
-			else
-				*d++ = *c;
-		}
-
-		msg->body = buf;
-		msg->size += new_len;
-
-		msg->bin_content = FALSE;
-
-		if (msg->msnslp_message)
-			msg->size++;
-	}
-	else
-		msg->body = NULL;
-}
-
-const char *
-msn_message_get_body(const MsnMessage *msg)
-{
-	g_return_val_if_fail(msg != NULL, NULL);
-	g_return_val_if_fail(!msg->bin_content, NULL);
-
-	return msg->body;
-}
-
-void
 msn_message_set_bin_data(MsnMessage *msg, const void *data, size_t len)
 {
 	g_return_if_fail(msg != NULL);
 
-	if (!msg->bin_content)
-		msn_message_set_body(msg, NULL);
-
-	msg->bin_content = TRUE;
+	/* There is no need to waste memory on data we cannot send anyway */
+	if (len > 1664)
+		len = 1664;
 
 	if (msg->body != NULL)
-	{
-		msg->size -= msg->bin_len;
 		g_free(msg->body);
-	}
 
 	if (data != NULL && len > 0)
 	{
 		msg->body = g_memdup(data, len);
-		msg->bin_len = len;
-
-		msg->size += len;
+		msg->body_len = len;
 	}
 	else
 	{
 		msg->body = NULL;
-		msg->bin_len = 0;
+		msg->body_len = 0;
 	}
 }
 
@@ -601,10 +437,9 @@
 msn_message_get_bin_data(const MsnMessage *msg, size_t *len)
 {
 	g_return_val_if_fail(msg != NULL, NULL);
-	g_return_val_if_fail(len != NULL, NULL);
-	g_return_val_if_fail(msg->bin_content, NULL);
 
-	*len = msg->bin_len;
+	if (len)
+		*len = msg->body_len;
 
 	return msg->body;
 }
@@ -614,16 +449,11 @@
 {
 	g_return_if_fail(msg != NULL);
 
-	if (msg->content_type != NULL) {
-		msg->size -= strlen(msg->content_type);
+	if (msg->content_type != NULL)
 		g_free(msg->content_type);
-	}
 
-	if (type != NULL) {
+	if (type != NULL)
 		msg->content_type = g_strdup(type);
-
-		msg->size += strlen(type);
-	}
 	else
 		msg->content_type = NULL;
 }
@@ -641,16 +471,11 @@
 {
 	g_return_if_fail(msg != NULL);
 
-	if (msg->charset != NULL) {
-		msg->size -= strlen(msg->charset) + strlen("; charset=");
+	if (msg->charset != NULL)
 		g_free(msg->charset);
-	}
 
-	if (charset != NULL) {
+	if (charset != NULL)
 		msg->charset = g_strdup(charset);
-
-		msg->size += strlen(charset) + strlen("; charset=");
-	}
 	else
 		msg->charset = NULL;
 }
@@ -674,14 +499,16 @@
 
 	temp = msn_message_get_attr(msg, attr);
 
-	if (value == NULL) {
-		if (temp != NULL) {
+	if (value == NULL)
+	{
+		if (temp != NULL)
+		{
 			GList *l;
 
-			msg->size -= strlen(temp) + strlen(attr) + 4;
-
-			for (l = msg->attr_list; l != NULL; l = l->next) {
-				if (!g_ascii_strcasecmp(l->data, attr)) {
+			for (l = msg->attr_list; l != NULL; l = l->next)
+			{
+				if (!g_ascii_strcasecmp(l->data, attr))
+				{
 					msg->attr_list = g_list_remove(msg->attr_list, l->data);
 
 					break;
@@ -698,14 +525,8 @@
 
 	g_hash_table_insert(msg->attr_table, new_attr, g_strdup(value));
 
-	if (temp == NULL) {
+	if (temp == NULL)
 		msg->attr_list = g_list_append(msg->attr_list, new_attr);
-		msg->size += strlen(attr) + 4;
-	}
-	else
-		msg->size -= strlen(temp);
-
-	msg->size += strlen(value);
 }
 
 const char *
@@ -724,13 +545,15 @@
 	char *body, *s, *c;
 
 	g_return_val_if_fail(msg != NULL, NULL);
-	g_return_val_if_fail(msn_message_get_body(msg) != NULL, NULL);
 
-	s = body = g_strdup(msn_message_get_body(msg));
+	s = body = g_strdup(msn_message_get_bin_data(msg, NULL));
+
+	g_return_val_if_fail(body != NULL, NULL);
 
 	table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
 
-	while (*s != '\r' && *s != '\0') {
+	while (*s != '\r' && *s != '\0')
+	{
 		char *key, *value;
 
 		key = s;
@@ -741,7 +564,8 @@
 
 		GET_NEXT_LINE(s);
 
-		if ((c = strchr(key, ':')) != NULL) {
+		if ((c = strchr(key, ':')) != NULL)
+		{
 			*c = '\0';
 
 			g_hash_table_insert(table, g_strdup(key), g_strdup(value));
@@ -752,4 +576,3 @@
 
 	return table;
 }
-
--- a/src/protocols/msn/msg.h	Tue Jun 01 01:55:55 2004 +0000
+++ b/src/protocols/msn/msg.h	Tue Jun 01 06:42:20 2004 +0000
@@ -29,24 +29,21 @@
 
 typedef struct
 {
-	long session_id;
-	long id;
-	long offset_1;
-	long offset_2;
-	long total_size_1;
-	long total_size_2;
-	long length;
-	long flags;
-	long ack_session_id;
-	long ack_unique_id;
-	long ack_length_1;
-	long ack_length_2;
+	guint32 session_id;
+	guint32 id;
+	guint64 offset;
+	guint64 total_size;
+	guint32 length;
+	guint32 flags;
+	guint32 ack_id;
+	guint32 ack_sub_id;
+	guint64 ack_size;
 
 } MsnSlpHeader;
 
 typedef struct
 {
-	long app_id;
+	guint32 value;
 
 } MsnSlpFooter;
 
@@ -61,18 +58,12 @@
 	gboolean msnslp_ack_message;
 
 	char *passport;
-
-	unsigned int tid;
 	char flag;
 
-	size_t size;
-
-	gboolean bin_content;
-
 	char *content_type;
 	char *charset;
 	char *body;
-	size_t bin_len;
+	size_t body_len;
 
 	MsnSlpHeader msnslp_header;
 	MsnSlpFooter msnslp_footer;
@@ -92,6 +83,8 @@
  */
 MsnMessage *msn_message_new(void);
 
+MsnMessage *msn_message_new_plain(const char *message);
+
 /**
  * Creates a new, empty MSNSLP message.
  *
@@ -113,10 +106,9 @@
  *
  * @param msg         The message.
  * @param payload     The payload.
- * @param payload_len The length payload.
+ * @param payload_len The length of the payload.
  */
-void msn_message_parse_payload(MsnMessage *msg,
-							   const char *payload,
+void msn_message_parse_payload(MsnMessage *msg, const char *payload,
 							   size_t payload_len);
 
 /**
--- a/src/protocols/msn/msn.c	Tue Jun 01 01:55:55 2004 +0000
+++ b/src/protocols/msn/msn.c	Tue Jun 01 06:42:20 2004 +0000
@@ -41,8 +41,6 @@
 
 static GaimPlugin *my_protocol = NULL;
 
-static const char *msn_normalize(const GaimAccount *account, const char *str);
-
 typedef struct
 {
 	GaimConnection *gc;
@@ -57,38 +55,49 @@
 
 } MsnGetInfoData;
 
+static const char *
+msn_normalize(const GaimAccount *account, const char *str)
+{
+	static char buf[BUF_LEN];
+	char *tmp;
+
+	g_return_val_if_fail(str != NULL, NULL);
+
+	g_snprintf(buf, sizeof(buf), "%s%s", str,
+			   (strchr(str, '@') ? "" : "@hotmail.com"));
+
+	tmp = g_utf8_strdown(buf, -1);
+	strncpy(buf, tmp, sizeof(buf));
+	g_free(tmp);
+
+	return buf;
+}
+
 static void
 msn_act_id(GaimConnection *gc, const char *entry)
 {
 	MsnCmdProc *cmdproc;
 	MsnSession *session;
 	GaimAccount *account;
-	char *alias;
+	const char *alias;
 
 	session = gc->proto_data;
 	cmdproc = session->notification_conn->cmdproc;
 	account = gaim_connection_get_account(gc);
 
-	if (entry == NULL || *entry == '\0')
-		alias = g_strdup("");
-	else
-		alias = g_strdup(entry);
+	alias = (entry && *entry) ? entry : "";
 
 	if (strlen(alias) > BUDDY_ALIAS_MAXLEN)
 	{
 		gaim_notify_error(gc, NULL,
 						  _("Your new MSN friendly name is too long."), NULL);
 
-		g_free(alias);
-
 		return;
 	}
 
 	msn_cmdproc_send(cmdproc, "REA", "%s %s",
 					 gaim_account_get_username(account),
 					 gaim_url_encode(alias));
-
-	g_free(alias);
 }
 
 static void
@@ -102,7 +111,7 @@
 
 	if (entry == NULL || *entry == '\0')
 	{
-		msn_cmdproc_send(cmdproc, "PRP", "%s  ", type);
+		msn_cmdproc_send(cmdproc, "PRP", "%s", type);
 	}
 	else
 	{
@@ -188,7 +197,10 @@
 static void
 msn_show_set_friendly_name(GaimPluginAction *action)
 {
-	GaimConnection *gc = (GaimConnection *) action->context;
+	GaimConnection *gc;
+
+	gc = (GaimConnection *) action->context;
+
 	gaim_request_input(gc, NULL, _("Set your friendly name."),
 					   _("This is the name that other MSN buddies will "
 						 "see you as."),
@@ -200,8 +212,11 @@
 static void
 msn_show_set_home_phone(GaimPluginAction *action)
 {
-	GaimConnection *gc = (GaimConnection *) action->context;
-	MsnSession *session = gc->proto_data;
+	GaimConnection *gc;
+	MsnSession *session;
+
+	gc = (GaimConnection *) action->context;
+	session = gc->proto_data;
 
 	gaim_request_input(gc, NULL, _("Set your home phone number."), NULL,
 					   msn_user_get_home_phone(session->user), FALSE, FALSE, NULL,
@@ -212,8 +227,11 @@
 static void
 msn_show_set_work_phone(GaimPluginAction *action)
 {
-	GaimConnection *gc = (GaimConnection *) action->context;
-	MsnSession *session = gc->proto_data;
+	GaimConnection *gc;
+	MsnSession *session;
+
+	gc = (GaimConnection *) action->context;
+	session = gc->proto_data;
 
 	gaim_request_input(gc, NULL, _("Set your work phone number."), NULL,
 					   msn_user_get_work_phone(session->user), FALSE, FALSE, NULL,
@@ -224,8 +242,11 @@
 static void
 msn_show_set_mobile_phone(GaimPluginAction *action)
 {
-	GaimConnection *gc = (GaimConnection *) action->context;
-	MsnSession *session = gc->proto_data;
+	GaimConnection *gc;
+	MsnSession *session;
+
+	gc = (GaimConnection *) action->context;
+	session = gc->proto_data;
 
 	gaim_request_input(gc, NULL, _("Set your mobile phone number."), NULL,
 					   msn_user_get_mobile_phone(session->user), FALSE, FALSE, NULL,
@@ -236,7 +257,10 @@
 static void
 msn_show_set_mobile_pages(GaimPluginAction *action)
 {
-	GaimConnection *gc = (GaimConnection *) action->context;
+	GaimConnection *gc;
+
+	gc = (GaimConnection *) action->context;
+
 	gaim_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 "
@@ -308,7 +332,7 @@
 	swboard->chat = serv_got_joined_chat(gc, swboard->chat_id, "MSN Chat");
 
 	gaim_conv_chat_add_user(GAIM_CONV_CHAT(swboard->chat),
-			gaim_account_get_username(buddy->account), NULL);
+							gaim_account_get_username(buddy->account), NULL);
 }
 
 /**************************************************************************
@@ -339,7 +363,8 @@
 	else if (away_type != 0)
 		emblems[i++] = "away";
 
-	if (user == NULL) {
+	if (user == NULL)
+	{
 		emblems[0] = "offline";
 	}
 	else if (user->mobile)
@@ -365,7 +390,8 @@
 {
 	char *text = NULL;
 
-	if (GAIM_BUDDY_IS_ONLINE(b)) {
+	if (GAIM_BUDDY_IS_ONLINE(b))
+	{
 		text = g_strdup_printf("\n<b>%s:</b> %s", _("Status"),
 							   msn_away_get_text(MSN_AWAY_TYPE(b->uc)));
 	}
@@ -396,12 +422,12 @@
 	GaimPluginAction *act;
 
 	act = gaim_plugin_action_new(_("Set Friendly Name"),
-			msn_show_set_friendly_name);
+								 msn_show_set_friendly_name);
 	m = g_list_append(m, act);
 	m = g_list_append(m, NULL);
 
 	act = gaim_plugin_action_new(_("Set Home Phone Number"),
-			msn_show_set_home_phone);
+								 msn_show_set_home_phone);
 	m = g_list_append(m, act);
 
 	act = gaim_plugin_action_new(_("Set Work Phone Number"),
@@ -435,45 +461,48 @@
 	GaimBlistNodeAction *act;
 
 	user = buddy->proto_data;
+
 	if (user != NULL)
 	{
 		if (user->mobile)
 		{
 			act = gaim_blist_node_action_new(_("Send to Mobile"),
-					show_send_to_mobile_cb, NULL);
+											 show_send_to_mobile_cb, NULL);
 			m = g_list_append(m, act);
 		}
 	}
 
-	if (g_ascii_strcasecmp(buddy->name, gaim_account_get_username(buddy->account)))
+	if (g_ascii_strcasecmp(buddy->name,
+						   gaim_account_get_username(buddy->account)))
 	{
 		act = gaim_blist_node_action_new(_("Initiate Chat"),
-				initiate_chat_cb, NULL);
+										 initiate_chat_cb, NULL);
 		m = g_list_append(m, act);
 	}
 
 	return m;
 }
 
-
 static GList *
 msn_blist_node_menu(GaimBlistNode *node)
 {
-	if(GAIM_BLIST_NODE_IS_BUDDY(node)) {
+	if(GAIM_BLIST_NODE_IS_BUDDY(node))
+	{
 		return msn_buddy_menu((GaimBuddy *) node);
-	} else {
+	}
+	else
+	{
 		return NULL;
 	}
 }
 
-
 static void
 msn_login(GaimAccount *account)
 {
 	GaimConnection *gc;
 	MsnSession *session;
 	const char *username;
-	const char *server;
+	const char *host;
 	gboolean http_method = FALSE;
 	int port;
 
@@ -495,16 +524,16 @@
 
 		gaim_debug(GAIM_DEBUG_INFO, "msn", "using http method\n");
 
-		server = "gateway.messenger.hotmail.com";
+		host = "gateway.messenger.hotmail.com";
 		port   = 80;
 	}
 	else
 	{
-		server = gaim_account_get_string(account, "server", MSN_SERVER);
-		port   = gaim_account_get_int(account,    "port",   MSN_PORT);
+		host = gaim_account_get_string(account, "server", MSN_SERVER);
+		port = gaim_account_get_int(account,    "port",   MSN_PORT);
 	}
 
-	session = msn_session_new(account, server, port);
+	session = msn_session_new(account, host, port);
 	session->http_method = http_method;
 	session->prpl = my_protocol;
 
@@ -551,27 +580,26 @@
 			GaimConvImFlags flags)
 {
 	GaimAccount *account;
-	MsnSession *session;
-	MsnSwitchBoard *swboard;
 
 	account = gaim_connection_get_account(gc);
-	session = gc->proto_data;
-	swboard = msn_session_find_switch_with_passport(session, who);
 
 	if (g_ascii_strcasecmp(who, gaim_account_get_username(account)))
 	{
+		MsnSession *session;
+		MsnSwitchBoard *swboard;
 		MsnMessage *msg;
 		MsnUser *user;
 		char *msgformat;
 		char *msgtext;
 
+		session = gc->proto_data;
+		swboard = msn_session_find_switch_with_passport(session, who);
 		user = msn_user_new(session, who, NULL);
 
 		msn_import_html(message, &msgformat, &msgtext);
 
-		msg = msn_message_new();
+		msg = msn_message_new_plain(msgtext);
 		msn_message_set_attr(msg, "X-MMS-IM-Format", msgformat);
-		msn_message_set_body(msg, msgtext);
 
 		g_free(msgformat);
 		g_free(msgtext);
@@ -616,7 +644,6 @@
 	MsnSession *session;
 	MsnSwitchBoard *swboard;
 	MsnMessage *msg;
-	MsnUser *user;
 
 	account = gaim_connection_get_account(gc);
 	session = gc->proto_data;
@@ -637,20 +664,16 @@
 	if (swboard == NULL)
 		return 0;
 
-	user = msn_user_new(session, who, NULL);
-
 	msg = msn_message_new();
 	msn_message_set_content_type(msg, "text/x-msmsgscontrol");
-	msn_message_set_charset(msg, NULL);
 	msn_message_set_flag(msg, 'U');
 	msn_message_set_attr(msg, "TypingUser",
 						 gaim_account_get_username(account));
-	msn_message_set_attr(msg, "User-Agent", NULL);
-	msn_message_set_body(msg, "\r\n");
+	msn_message_set_bin_data(msg, "\r\n", 2);
 
 	msn_switchboard_send_msg(swboard, msg);
 
-	msn_user_destroy(user);
+	msn_message_destroy(msg);
 
 	return MSN_TYPING_SEND_TIMEOUT;
 }
@@ -659,7 +682,7 @@
 msn_set_away(GaimConnection *gc, const char *state, const char *msg)
 {
 	MsnSession *session;
-	const char *away;
+	const char *status;
 
 	session = gc->proto_data;
 
@@ -672,37 +695,37 @@
 	if (msg != NULL)
 	{
 		gc->away = g_strdup("");
-		away = "AWY";
+		status = "AWY";
 	}
 	else if (state)
 	{
 		gc->away = g_strdup("");
 
 		if (!strcmp(state, _("Away From Computer")))
-			away = "AWY";
+			status = "AWY";
 		else if (!strcmp(state, _("Be Right Back")))
-			away = "BRB";
+			status = "BRB";
 		else if (!strcmp(state, _("Busy")))
-			away = "BSY";
+			status = "BSY";
 		else if (!strcmp(state, _("On The Phone")))
-			away = "PHN";
+			status = "PHN";
 		else if (!strcmp(state, _("Out To Lunch")))
-			away = "LUN";
+			status = "LUN";
 		else if (!strcmp(state, _("Hidden")))
-			away = "HDN";
+			status = "HDN";
 		else
 		{
 			g_free(gc->away);
 			gc->away = NULL;
-			away = "NLN";
+			status = "NLN";
 		}
 	}
 	else if (gc->is_idle)
-		away = "IDL";
+		status = "IDL";
 	else
-		away = "NLN";
+		status = "NLN";
 
-	msn_session_change_status(session, away);
+	msn_session_change_status(session, status);
 }
 
 static void
@@ -1069,37 +1092,35 @@
 {
 	MsnSession *session;
 	MsnSwitchBoard *swboard;
+	MsnCmdProc *cmdproc;
 
 	session = gc->proto_data;
+
 	swboard = msn_session_find_switch_with_id(session, id);
+	g_return_if_fail(swboard != NULL);
 
-	if (swboard == NULL)
-		return;
+	cmdproc = swboard->cmdproc;
 
-	msn_cmdproc_send(swboard->cmdproc, "CAL", "%s", who);
+	msn_cmdproc_send(cmdproc, "CAL", "%s", who);
 }
 
 static void
 msn_chat_leave(GaimConnection *gc, int id)
 {
-	GaimAccount *account;
 	MsnSession *session;
 	MsnSwitchBoard *swboard;
+	MsnCmdProc *cmdproc;
 
 	session = gc->proto_data;
-	account = gaim_connection_get_account(gc);
 	swboard = msn_session_find_switch_with_id(session, id);
+	g_return_if_fail(swboard != NULL);
 
-	if (swboard == NULL)
-	{
-		serv_got_chat_left(gc, id);
-		return;
-	}
+	cmdproc = swboard->servconn->cmdproc;
 
-	msn_cmdproc_send_quick(swboard->cmdproc, "OUT", NULL, NULL);
+	msn_cmdproc_send_quick(cmdproc, "OUT", NULL, NULL);
 	msn_switchboard_destroy(swboard);
 
-	serv_got_chat_left(gc, id);
+	/* serv_got_chat_left(gc, id); */
 }
 
 static int
@@ -1121,9 +1142,8 @@
 
 	msn_import_html(message, &msgformat, &msgtext);
 
-	msg = msn_message_new();
+	msg = msn_message_new_plain(msgtext);
 	msn_message_set_attr(msg, "X-MMS-IM-Format", msgformat);
-	msn_message_set_body(msg, msgtext);
 
 	g_free(msgformat);
 	g_free(msgtext);
@@ -1132,8 +1152,8 @@
 
 	msn_message_destroy(msg);
 
-	serv_got_chat_in(gc, id, gaim_account_get_username(account),
-					 0, message, time(NULL));
+	serv_got_chat_in(gc, id, gaim_account_get_username(account), 0,
+					 message, time(NULL));
 
 	return 0;
 }
@@ -1210,11 +1230,13 @@
 		if (cmdproc->error)
 			return;
 
+#if 0
 		if (msn_users_get_count(msn_group_get_users(old_group)) <= 0)
 		{
 			msn_cmdproc_send(cmdproc, "RMG", "%d",
 							 msn_group_get_id(old_group));
 		}
+#endif
 	}
 }
 
@@ -1225,16 +1247,17 @@
 	MsnSession *session;
 	MsnCmdProc *cmdproc;
 	MsnGroup *old_group;
+	const char *enc_new_group_name;
 
 	session = gc->proto_data;
 	cmdproc = session->notification_conn->cmdproc;
+	enc_new_group_name = gaim_url_encode(new_group_name);
 
 	if ((old_group = msn_groups_find_with_name(session->groups,
 											   old_group_name)) != NULL)
 	{
 		msn_cmdproc_send(cmdproc, "REG", "%d %s 0",
-						 msn_group_get_id(old_group),
-						 gaim_url_encode(new_group_name));
+						 msn_group_get_id(old_group), enc_new_group_name);
 
 		if (cmdproc->error)
 			return;
@@ -1243,8 +1266,7 @@
 	}
 	else
 	{
-		msn_cmdproc_send(cmdproc, "ADG", "%s 0",
-						 gaim_url_encode(new_group_name));
+		msn_cmdproc_send(cmdproc, "ADG", "%s 0", enc_new_group_name);
 	}
 }
 
@@ -1261,46 +1283,38 @@
 static void
 msn_convo_closed(GaimConnection *gc, const char *who)
 {
-	GaimAccount *account;
 	MsnSession *session;
 	MsnSwitchBoard *swboard;
+	MsnCmdProc *cmdproc;
 
-	account = gaim_connection_get_account(gc);
 	session = gc->proto_data;
+
 	swboard = msn_session_find_switch_with_passport(session, who);
+	g_return_if_fail(swboard != NULL);
 
-	if (swboard != NULL && swboard->chat == NULL)
+	cmdproc = swboard->servconn->cmdproc;
+
+	if (swboard->chat == NULL)
 	{
-		msn_cmdproc_send_quick(swboard->cmdproc, "BYE", "%s",
+		GaimAccount *account;
+
+		account = gaim_connection_get_account(gc);
+
+		msn_cmdproc_send_quick(cmdproc, "BYE", "%s",
 							   gaim_account_get_username(account));
 
 		msn_switchboard_destroy(swboard);
 	}
 }
 
-static const char *
-msn_normalize(const GaimAccount *account, const char *str)
-{
-	static char buf[BUF_LEN];
-	char *tmp;
-
-	g_return_val_if_fail(str != NULL, NULL);
-
-	g_snprintf(buf, sizeof(buf), "%s%s", str,
-			   (strchr(str, '@') ? "" : "@hotmail.com"));
-
-	tmp = g_utf8_strdown(buf, -1);
-	strncpy(buf, tmp, sizeof(buf));
-	g_free(tmp);
-
-	return buf;
-}
-
 static void
 msn_set_buddy_icon(GaimConnection *gc, const char *filename)
 {
-	MsnSession *session = (MsnSession *)gc->proto_data;
-	MsnUser *user = session->user;
+	MsnSession *session;
+	MsnUser *user;
+
+	session = gc->proto_data;
+	user = session->user;
 
 	msn_user_set_buddy_icon(user, filename);
 
@@ -1341,9 +1355,9 @@
 	if (url_text == NULL || strcmp(url_text, "") == 0)
 	{
 		gaim_notify_formatted(info_data->gc, NULL,
-			_("Buddy Information"), NULL,
-			_("<html><body><b>Error retrieving profile</b></body></html>"),
-			  NULL, NULL);
+							  _("Buddy Information"), NULL,
+							  _("<html><body><b>Error retrieving profile</b></body></html>"),
+							  NULL, NULL);
 
 		return;
 	}
@@ -1411,15 +1425,16 @@
 		has_info = TRUE;
 
 	/* Extract their Age and put it in */
-	found = gaim_markup_extract_info_field(stripped, stripped_len, s,"\tAge",
-			0, "\t", '\n', "Undisclosed", _("Age"), 0, NULL);
+	found = gaim_markup_extract_info_field(stripped, stripped_len, s,
+			"\tAge", 0, "\t", '\n', "Undisclosed", _("Age"), 0, NULL);
 
 	if (found)
 		has_info = TRUE;
 
 	/* Extract their Gender and put it in */
-	found = gaim_markup_extract_info_field(stripped, stripped_len, s,"\tGender",
-			6, "\t", '\n', "Undisclosed", _("Gender"), 0, NULL);
+	found = gaim_markup_extract_info_field(stripped, stripped_len, s,
+			"\tGender", 6, "\t", '\n', "Undisclosed", _("Gender"), 0,
+			NULL);
 
 	if (found)
 		has_info = TRUE;
@@ -1434,8 +1449,8 @@
 
 	/* Extract their Location and put it in */
 	found = gaim_markup_extract_info_field(stripped, stripped_len, s,
-			"\tLocation", 0, "\t", '\n', "Undisclosed", _("Location"),
-			0, NULL);
+			"\tLocation", 0, "\t", '\n', "Undisclosed", _("Location"), 0,
+			NULL);
 
 	if (found)
 		has_info = TRUE;
@@ -1494,8 +1509,8 @@
 
 	/* Check if they have Favorite Things */
 	found = gaim_markup_extract_info_field(stripped, stripped_len, s,
-				"Favorite Things", 1, "Hobbies and Interests", '\n', NULL,
-				_("Favorite Things"), 0, NULL);
+			"Favorite Things", 1, "Hobbies and Interests", '\n', NULL,
+			_("Favorite Things"), 0, NULL);
 
 	if (!found)
 	{
@@ -1507,8 +1522,8 @@
 	if (!found)
 	{
 		found = gaim_markup_extract_info_field(stripped, stripped_len, s,
-				"Favorite Things", 1, "My Homepage\tTake a look", '\n', NULL,
-				_("Favorite Things"), 0, NULL);
+				"Favorite Things", 1, "My Homepage\tTake a look", '\n',
+				NULL, _("Favorite Things"), 0, NULL);
 	}
 
 	if (!found)
@@ -1560,8 +1575,8 @@
 
 	/* Extract the last updated date and put it in */
 	found = gaim_markup_extract_info_field(stripped, stripped_len, s,
-			"\tlast updated:", 1, "\n", '\n', NULL, _("Last Updated"),
-			0, NULL);
+			"\tlast updated:", 1, "\n", '\n', NULL, _("Last Updated"), 0,
+			NULL);
 
 	if (found)
 		has_info = TRUE;
@@ -1593,7 +1608,8 @@
 		char primary[256];
 
 		g_snprintf(primary, sizeof(primary),
-				   _("User information for %s unavailable"), info_data->name);
+				   _("User information for %s unavailable"),
+				   info_data->name);
 		gaim_notify_error(info_data->gc, NULL, primary,
 						  _("The user's profile is empty."));
 	}
@@ -1618,8 +1634,8 @@
 	url = g_strdup_printf("%s%s", PROFILE_URL, name);
 
 	gaim_url_fetch(url, FALSE,
-				   "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)", TRUE,
-				   msn_got_info, data);
+				   "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
+				   TRUE, msn_got_info, data);
 
 	g_free(url);
 }
@@ -1768,8 +1784,8 @@
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
 											   option);
 
-	option = gaim_account_option_bool_new(_("Use HTTP Method"), "http_method",
-										  FALSE);
+	option = gaim_account_option_bool_new(_("Use HTTP Method"),
+										  "http_method", FALSE);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
 											   option);
 
--- a/src/protocols/msn/msnslp.c	Tue Jun 01 01:55:55 2004 +0000
+++ b/src/protocols/msn/msnslp.c	Tue Jun 01 06:42:20 2004 +0000
@@ -99,7 +99,7 @@
 
 	invite_msg = msn_message_new_msnslp();
 
-	msn_message_set_body(invite_msg, body);
+	msn_message_set_bin_data(invite_msg, body, strlen(body));
 
 	g_free(body);
 
@@ -166,7 +166,7 @@
 
 	account = slpsession->swboard->servconn->session->account;
 
-	body = msn_message_get_body(msg);
+	body = msn_message_get_bin_data(msg, NULL);
 
 	gaim_debug_misc("msn", "MSNSLP Message: {%s}\n", body);
 
@@ -329,7 +329,7 @@
 
 			new_msg = msn_message_new_msnslp();
 			msn_message_set_bin_data(new_msg, nil_body, 4);
-			new_msg->msnslp_footer.app_id = 1;
+			new_msg->msnslp_footer.value = 1;
 
 			msn_slp_session_send_msg(slpsession, new_msg);
 
@@ -362,20 +362,12 @@
 
 	if (slpsession->offset > 0)
 	{
-		if (msg->bin_content)
-		{
-			msn_message_set_bin_data(msg,
-				slpsession->orig_body + slpsession->offset,
-				msg->msnslp_header.length);
-		}
-		else
-		{
-			msn_message_set_body(msg,
-				slpsession->orig_body + slpsession->offset);
-		}
+		msn_message_set_bin_data(msg,
+			slpsession->orig_body + slpsession->offset,
+			msg->msnslp_header.length);
 	}
 
-	msg->msnslp_header.offset_1 = slpsession->offset;
+	msg->msnslp_header.offset = slpsession->offset;
 
 	msn_switchboard_send_msg(slpsession->swboard, msg);
 
@@ -397,6 +389,8 @@
 void
 msn_slp_session_send_msg(MsnSlpSession *slpsession, MsnMessage *msg)
 {
+	const void *temp;
+
 	g_return_if_fail(slpsession != NULL);
 	g_return_if_fail(msg != NULL);
 	g_return_if_fail(msg->msnslp_message);
@@ -415,29 +409,19 @@
 		slpsession->prev_msg_id = ++slpsession->base_id;
 
 	msg->msnslp_header.id = slpsession->prev_msg_id;
-	/*msg->msnslp_header.ack_session_id = rand() % 0xFFFFFF00;*/
-	msg->msnslp_header.ack_session_id = 0x1407C7DE;
+	/*msg->msnslp_header.ack_id = rand() % 0xFFFFFF00;*/
+	msg->msnslp_header.ack_id = 0x1407C7DE;
 
 	msn_message_set_charset(msg, NULL);
 
 	if (msg->msnslp_header.session_id != 0)
-		msg->msnslp_footer.app_id = 1;
+		msg->msnslp_footer.value = 1;
 
-	if (msg->bin_content)
-	{
-		const void *temp;
-
-		temp = msn_message_get_bin_data(msg, &slpsession->orig_len);
+	temp = msn_message_get_bin_data(msg, &slpsession->orig_len);
 
-		slpsession->orig_body = g_memdup(temp, slpsession->orig_len);
-	}
-	else
-	{
-		slpsession->orig_body = g_strdup(msn_message_get_body(msg));
-		slpsession->orig_len  = strlen(slpsession->orig_body);
-	}
+	slpsession->orig_body = g_memdup(temp, slpsession->orig_len);
 
-	msg->msnslp_header.total_size_1 = slpsession->orig_len;
+	msg->msnslp_header.total_size = slpsession->orig_len;
 	msg->msnslp_header.length = slpsession->orig_len;
 
 	send_msg_part(slpsession, msg);
--- a/src/protocols/msn/notification.c	Tue Jun 01 01:55:55 2004 +0000
+++ b/src/protocols/msn/notification.c	Tue Jun 01 06:42:20 2004 +0000
@@ -196,10 +196,8 @@
 cvr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
 	GaimAccount *account;
-	GaimConnection *gc;
 
 	account = cmdproc->session->account;
-	gc = gaim_account_get_connection(account);
 
 	msn_cmdproc_send(cmdproc, "USR", "TWN I %s",
 					 gaim_account_get_username(account));
@@ -237,7 +235,6 @@
 	MsnSession *session;
 	GaimAccount *account;
 	GaimConnection *gc;
-	char outparams[MSN_BUF_LEN];
 
 	session = cmdproc->session;
 	account = session->account;
@@ -310,8 +307,6 @@
 		md5_append(&st, (const md5_byte_t *)password, strlen(password));
 		md5_finish(&st, di);
 
-		g_snprintf(outparams, sizeof(outparams), "MD5 S ");
-
 		for (i = 0; i < 16; i++)
 			g_snprintf(buf + (i*2), 3, "%02x", di[i]);
 
@@ -417,8 +412,6 @@
 static void
 msg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
-	gaim_debug(GAIM_DEBUG_INFO, "msn", "Found message. Parsing.\n");
-
 	cmdproc->payload_cb  = msg_cmd_post;
 	cmdproc->servconn->payload_len = atoi(cmd->params[2]);
 	cmdproc->temp = g_strdup(cmd->params[0]);
@@ -431,9 +424,8 @@
 chl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
 	MsnSession *session;
-	GaimConnection *gc;
 	MsnTransaction *trans;
-	char buf[MSN_BUF_LEN];
+	char buf[33];
 	const char *challenge_resp;
 	const char *challenge_str;
 	md5_state_t st;
@@ -441,10 +433,10 @@
 	int i;
 
 	session = cmdproc->session;
-	gc = session->account->gc;
 
 	md5_init(&st);
-	md5_append(&st, (const md5_byte_t *)cmd->params[1], strlen(cmd->params[1]));
+	md5_append(&st, (const md5_byte_t *)cmd->params[1],
+			   strlen(cmd->params[1]));
 
 	if (session->protocol_ver >= 8)
 	{
@@ -551,8 +543,6 @@
 	list     = params[0];
 	passport = params[1];
 
-	reason = "invalid user";
-
 	if (!strcmp(list, "FL"))
 		msg = g_strdup("Unable to add user on MSN");
 	else if (!strcmp(list, "BL"))
@@ -711,7 +701,7 @@
 
 	gc = cmdproc->session->account->gc;
 
-	serv_got_update(gc, (char *)cmd->params[0], 0, 0, 0, 0, 0);
+	serv_got_update(gc, cmd->params[0], 0, 0, 0, 0, 0);
 }
 
 static void
@@ -734,7 +724,7 @@
 
 	user = msn_users_find_with_passport(session->users, passport);
 
-	serv_got_alias(gc, (char *)passport, (char *)friend);
+	serv_got_alias(gc, passport, friend);
 
 	msn_user_set_name(user, friend);
 
@@ -1150,7 +1140,7 @@
 
 	user = msn_users_find_with_passport(session->users, passport);
 
-	serv_got_alias(gc, (char *)passport, (char *)friend);
+	serv_got_alias(gc, passport, friend);
 
 	msn_user_set_name(user, friend);
 
@@ -1173,14 +1163,22 @@
 	else if (!g_ascii_strcasecmp(state, "LUN"))
 		status |= UC_UNAVAILABLE | (MSN_LUNCH << 1);
 
-	serv_got_update(gc, (char *)passport, 1, 0, 0, 0, status);
+	serv_got_update(gc, passport, 1, 0, 0, 0, status);
+}
+
+static void
+not_cmd_post(MsnCmdProc *cmdproc, char *payload, size_t len)
+{
+#if 0
+	gaim_debug_misc("msn", "Notification: {%s}\n", payload);
+#endif
 }
 
 static void
 not_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
-	cmdproc->payload_cb  = NULL;
 	cmdproc->servconn->payload_len = atoi(cmd->params[0]);
+	cmdproc->payload_cb = not_cmd_post;
 }
 
 static void
@@ -1277,12 +1275,14 @@
 
 		if (group == NULL)
 		{
-			gaim_debug(GAIM_DEBUG_ERROR, "msn",
-					   "Still don't have a group ID for %s while moving %s!\n",
-					   session->dest_group_name, passport);
+			gaim_debug_error("msn",
+							 "Still don't have a group ID for %s while moving %s!\n",
+							 session->dest_group_name, passport);
 
 			g_free(session->dest_group_name);
 			session->dest_group_name = NULL;
+
+			return;
 		}
 
 		g_free(session->dest_group_name);
@@ -1432,7 +1432,7 @@
 			  "<head>\n"
 			  "<noscript>\n"
 			  "<meta http-equiv=\"Refresh\" content=\"0; "
-			        "url=http://www.hotmail.com\">\n"
+			  "url=http://www.hotmail.com\">\n"
 			  "</noscript>\n"
 			  "</head>\n\n",
 			  fd);
@@ -1465,9 +1465,9 @@
 
 		if (fclose(fd))
 		{
-			gaim_debug(GAIM_DEBUG_ERROR, "msn",
-					   "Error closing temp passport file: %s\n",
-					   strerror(errno));
+			gaim_debug_error("msn",
+							 "Error closing temp passport file: %s\n",
+							 strerror(errno));
 
 			unlink(session->passport_info.file);
 			g_free(session->passport_info.file);
@@ -1480,8 +1480,7 @@
 			 */
 			char *tmp;
 
-			if ((tmp = g_strdup_printf("%s.html",
-					session->passport_info.file)) != NULL)
+			if ((tmp = g_strdup_printf("%s.html", session->passport_info.file)) != NULL)
 			{
 				if (rename(session->passport_info.file, tmp) == 0)
 				{
@@ -1534,9 +1533,9 @@
 
 	if (!msn_switchboard_connect(swboard, host, port))
 	{
-		gaim_debug(GAIM_DEBUG_ERROR, "msn",
-				   "Unable to connect to switchboard on %s, port %d\n",
-				   host, port);
+		gaim_debug_error("msn",
+						 "Unable to connect to switchboard on %s, port %d\n",
+						 host, port);
 
 		g_free(host);
 
@@ -1697,9 +1696,12 @@
 
 		if (count != 0)
 		{
-			const char *passport = msn_user_get_passport(session->user);
-			const char *file = session->passport_info.file;
+			const char *passport;
+			const char *file;
 			gchar *url;
+
+			passport = msn_user_get_passport(session->user);
+			file = session->passport_info.file;
 			while (*file && *file == '/')
 				++file;
 			url = g_strconcat ("file:///", file, 0);
@@ -1755,9 +1757,11 @@
 	if (tmp != NULL)
 		subject = gaim_mime_decode_field(tmp);
 
-	if (from != NULL && subject != NULL)	
-		gaim_notify_email(gc, subject, from, msn_user_get_passport(session->user),
-						session->passport_info.file, NULL, NULL);
+	gaim_notify_email(gc,
+					  (subject != NULL ? subject : ""),
+					  (from != NULL ?  from : ""),
+					  msn_user_get_passport(session->user),
+					  session->passport_info.file, NULL, NULL);
 
 	if (from != NULL)
 		g_free(from);
@@ -1796,19 +1800,19 @@
 			case 1:
 				minutes = atoi(g_hash_table_lookup(table, "Arg1"));
 				g_snprintf(buf, sizeof(buf), ngettext(
-						   "The MSN server will shut down for maintenance "
-						   "in %d minute. You will automatically be "
-						   "signed out at that time.  Please finish any "
-						   "conversations in progress.\n\nAfter the "
-						   "maintenance has been completed, you will be "
-						   "able to successfully sign in.",
-						   "The MSN server will shut down for maintenance "
-						   "in %d minutes. You will automatically be "
-						   "signed out at that time.  Please finish any "
-						   "conversations in progress.\n\nAfter the "
-						   "maintenance has been completed, you will be "
-						   "able to successfully sign in.", minutes),
-						   minutes);
+							"The MSN server will shut down for maintenance "
+							"in %d minute. You will automatically be "
+							"signed out at that time.  Please finish any "
+							"conversations in progress.\n\nAfter the "
+							"maintenance has been completed, you will be "
+							"able to successfully sign in.",
+							"The MSN server will shut down for maintenance "
+							"in %d minutes. You will automatically be "
+							"signed out at that time.  Please finish any "
+							"conversations in progress.\n\nAfter the "
+							"maintenance has been completed, you will be "
+							"able to successfully sign in.", minutes),
+						minutes);
 			default:
 				break;
 		}
@@ -1922,17 +1926,17 @@
 
 	/* Register the message type callbacks. */
 	msn_table_add_msg_type(cbs_table,
-							"text/x-msmsgsprofile",
-							profile_msg);
+						   "text/x-msmsgsprofile",
+						   profile_msg);
 	msn_table_add_msg_type(cbs_table,
-							"text/x-msmsgsinitialemailnotification",
-							initial_email_msg);
+						   "text/x-msmsgsinitialemailnotification",
+						   initial_email_msg);
 	msn_table_add_msg_type(cbs_table,
-							"text/x-msmsgsemailnotification",
-							email_msg);
+						   "text/x-msmsgsemailnotification",
+						   email_msg);
 	msn_table_add_msg_type(cbs_table,
-							"application/x-msmsgssystemmessage",
-							system_msg);
+						   "application/x-msmsgssystemmessage",
+						   system_msg);
 }
 
 void
--- a/src/protocols/msn/page.h	Tue Jun 01 01:55:55 2004 +0000
+++ b/src/protocols/msn/page.h	Tue Jun 01 06:42:20 2004 +0000
@@ -25,7 +25,6 @@
 typedef struct _MsnPage MsnPage;
 
 #include "session.h"
-#include "user.h"
 
 /**
  * A page.
--- a/src/protocols/msn/servconn.c	Tue Jun 01 01:55:55 2004 +0000
+++ b/src/protocols/msn/servconn.c	Tue Jun 01 06:42:20 2004 +0000
@@ -34,7 +34,7 @@
 
 	const char *names[] = { "Notification", "Switchboard" };
 	const char *name;
-
+	
 	gc = gaim_account_get_connection(servconn->session->account);
 	name = names[servconn->type];
 
@@ -49,8 +49,7 @@
 			break;
 		case MSN_ERROR_READ:
 			cmd = servconn->cmdproc->last_trans;
-			tmp = g_strdup_printf(_("Error reading from %s server. Last"
-									"command was:\n %s"), name, cmd);
+			tmp = g_strdup_printf(_("Error reading from %s server"), name);
 			gaim_debug_info("msn", "Last command was: %s\n", cmd);
 			break;
 		default:
@@ -59,7 +58,7 @@
 	}
 
 	gaim_connection_error(gc, tmp);
-
+	
 	g_free(tmp);
 }
 
@@ -68,8 +67,6 @@
 {
 	MsnServConn *servconn = data;
 
-	gaim_debug_info("msn", "In servconn's connect_cb\n");
-
 	servconn->fd = source;
 
 	if (source > 0)
@@ -87,7 +84,7 @@
 }
 
 MsnServConn *
-msn_servconn_new(MsnSession *session, MsnServerType type)
+msn_servconn_new(MsnSession *session, MsnServConnType type)
 {
 	MsnServConn *servconn;
 
@@ -113,11 +110,36 @@
 	return servconn;
 }
 
+void
+msn_servconn_destroy(MsnServConn *servconn)
+{
+	MsnSession *session;
+
+	g_return_if_fail(servconn != NULL);
+
+	if (servconn->processing)
+	{
+		servconn->wasted = TRUE;
+		return;
+	}
+
+	session = servconn->session;
+
+	session->servconns = g_list_remove(session->servconns, servconn);
+
+	if (servconn->connected)
+		msn_servconn_disconnect(servconn);
+
+	msn_cmdproc_destroy(servconn->cmdproc);
+
+	g_free(servconn);
+}
+
 gboolean
 msn_servconn_connect(MsnServConn *servconn, const char *host, int port)
 {
 	MsnSession *session;
-	int i;
+	int r;
 
 	g_return_val_if_fail(servconn != NULL, FALSE);
 	g_return_val_if_fail(host     != NULL, FALSE);
@@ -130,13 +152,13 @@
 
 	if (session->http_method)
 	{
-		servconn->http_data->gateway_ip = g_strdup(host);
+		servconn->http_data->gateway_host = g_strdup(host);
 	}
 
-	i = gaim_proxy_connect(session->account, host, port, connect_cb,
+	r = gaim_proxy_connect(session->account, host, port, connect_cb,
 						   servconn);
 
-	if (i == 0)
+	if (r == 0)
 		servconn->connected = TRUE;
 
 	return servconn->connected;
@@ -165,16 +187,17 @@
 		if (servconn->http_data->session_id != NULL)
 			g_free(servconn->http_data->session_id);
 
-		if (servconn->http_data->old_gateway_ip != NULL)
-			g_free(servconn->http_data->old_gateway_ip);
+		if (servconn->http_data->old_gateway_host != NULL)
+			g_free(servconn->http_data->old_gateway_host);
 
-		if (servconn->http_data->gateway_ip != NULL)
-			g_free(servconn->http_data->gateway_ip);
+		if (servconn->http_data->gateway_host != NULL)
+			g_free(servconn->http_data->gateway_host);
 
 		if (servconn->http_data->timer)
 			gaim_timeout_remove(servconn->http_data->timer);
 
 		g_free(servconn->http_data);
+		servconn->http_data = NULL;
 	}
 
 	servconn->rx_len = 0;
@@ -187,30 +210,6 @@
 }
 
 void
-msn_servconn_destroy(MsnServConn *servconn)
-{
-	MsnSession *session;
-
-	g_return_if_fail(servconn != NULL);
-
-	if (servconn->processing)
-	{
-		servconn->wasted = TRUE;
-		return;
-	}
-
-	session = servconn->session;
-
-	session->servconns = g_list_remove(session->servconns, servconn);
-
-	if (servconn->connected)
-		msn_servconn_disconnect(servconn);
-
-	msn_cmdproc_destroy(servconn->cmdproc);
-	g_free(servconn);
-}
-
-void
 msn_servconn_set_connect_cb(MsnServConn *servconn,
 							gboolean (*connect_cb)(MsnServConn *servconn))
 {
@@ -232,13 +231,15 @@
 static void
 failed_io(MsnServConn *servconn)
 {
+	g_return_if_fail(servconn != NULL);
+
 	show_error(servconn);
 
 	msn_servconn_disconnect(servconn);
 }
 
 size_t
-msn_servconn_write(MsnServConn *servconn, const char *buf, size_t size)
+msn_servconn_write(MsnServConn *servconn, const char *buf, size_t len)
 {
 	size_t ret = FALSE;
 
@@ -246,12 +247,12 @@
 
 	if (servconn->session->http_method)
 	{
-		ret = msn_http_servconn_write(servconn, buf, size,
-									   servconn->http_data->server_type);
+		ret = msn_http_servconn_write(servconn, buf, len,
+									  servconn->http_data->server_type);
 	}
 	else
 	{
-		ret = write(servconn->fd, buf, size);
+		ret = write(servconn->fd, buf, len);
 	}
 
 	if (ret < 0)
@@ -276,6 +277,7 @@
 	session = servconn->session;
 
 	len = read(servconn->fd, buf, sizeof(buf) - 1);
+	buf[len] = '\0';
 
 	if (len <= 0)
 	{
@@ -299,9 +301,9 @@
 
 		tmp = g_strndup(servconn->rx_buf, servconn->rx_len);
 
-		if (!msn_http_servconn_parse_data(servconn, tmp,
-										  servconn->rx_len, &result_msg,
-										  &result_len, &error))
+		if (!msn_http_servconn_parse_data(servconn, tmp, servconn->rx_len,
+										  &result_msg, &result_len,
+										  &error))
 		{
 			g_free(tmp);
 			return;
@@ -311,9 +313,8 @@
 
 		if (error)
 		{
-			gaim_connection_error(
-				gaim_account_get_connection(session->account),
-				_("Received HTTP error. Please report this."));
+			gaim_connection_error(gaim_account_get_connection(session->account),
+								  _("Received HTTP error. Please report this."));
 
 			return;
 		}
@@ -342,8 +343,7 @@
 			close(servconn->fd);
 
 			i = gaim_proxy_connect(session->account, servconn->host,
-								   servconn->port, servconn->login_cb,
-								   servconn);
+								   servconn->port, read_cb, servconn);
 
 			if (i == 0)
 				servconn->connected = TRUE;
--- a/src/protocols/msn/servconn.h	Tue Jun 01 01:55:55 2004 +0000
+++ b/src/protocols/msn/servconn.h	Tue Jun 01 06:42:20 2004 +0000
@@ -40,11 +40,11 @@
 	MSN_SERVER_DC,
 	MSN_SERVER_HT
 
-} MsnServerType;
+} MsnServConnType;
 
 struct _MsnServConn
 {
-	MsnServerType type;
+	MsnServConnType type;
 	MsnSession *session;
 	MsnCmdProc *cmdproc;
 
@@ -70,7 +70,7 @@
 	void *data;
 };
 
-MsnServConn *msn_servconn_new(MsnSession *session, MsnServerType type);
+MsnServConn *msn_servconn_new(MsnSession *session, MsnServConnType type);
 
 void msn_servconn_destroy(MsnServConn *servconn);
 
--- a/src/protocols/msn/session.c	Tue Jun 01 01:55:55 2004 +0000
+++ b/src/protocols/msn/session.c	Tue Jun 01 06:42:20 2004 +0000
@@ -24,7 +24,7 @@
 #include "notification.h"
 
 MsnSession *
-msn_session_new(GaimAccount *account, const char *server, int port)
+msn_session_new(GaimAccount *account, const char *host, int port)
 {
 	MsnSession *session;
 
@@ -32,9 +32,9 @@
 
 	session = g_new0(MsnSession, 1);
 
-	session->account         = account;
-	session->dispatch_server = g_strdup(server);
-	session->dispatch_port   = port;
+	session->account       = account;
+	session->dispatch_host = g_strdup(host);
+	session->dispatch_port = port;
 
 	session->away_state = NULL;
 
@@ -58,8 +58,8 @@
 	if (session->connected)
 		msn_session_disconnect(session);
 
-	if (session->dispatch_server != NULL)
-		g_free(session->dispatch_server);
+	if (session->dispatch_host != NULL)
+		g_free(session->dispatch_host);
 
 	while (session->switches != NULL)
 		msn_switchboard_destroy(session->switches->data);
@@ -114,8 +114,8 @@
 	session->notification_conn = msn_notification_new(session);
 
 	if (msn_notification_connect(session->notification_conn,
-									 session->dispatch_server,
-									 session->dispatch_port))
+								 session->dispatch_host,
+								 session->dispatch_port))
 	{
 		return TRUE;
 	}
@@ -129,13 +129,15 @@
 	g_return_if_fail(session != NULL);
 	g_return_if_fail(session->connected);
 
-	while (session->switches != NULL) {
+	while (session->switches != NULL)
+	{
 		MsnSwitchBoard *board = (MsnSwitchBoard *)session->switches->data;
 
 		msn_switchboard_destroy(board);
 	}
 
-	if (session->notification_conn != NULL) {
+	if (session->notification_conn != NULL)
+	{
 		msn_servconn_destroy(session->notification_conn);
 		session->notification_conn = NULL;
 	}
@@ -208,7 +210,7 @@
 	GList *l;
 	MsnSwitchBoard *swboard;
 
-	g_return_val_if_fail(session != NULL, NULL);
+	g_return_val_if_fail(session  != NULL, NULL);
 	g_return_val_if_fail(passport != NULL, NULL);
 
 	for (l = session->switches; l != NULL; l = l->next)
@@ -235,7 +237,8 @@
 	g_return_val_if_fail(session != NULL, NULL);
 	g_return_val_if_fail(chat_id > 0, NULL);
 
-	for (l = session->switches; l != NULL; l = l->next) {
+	for (l = session->switches; l != NULL; l = l->next)
+	{
 		swboard = (MsnSwitchBoard *)l->data;
 
 		if (swboard->chat_id == chat_id)
@@ -253,7 +256,8 @@
 
 	g_return_val_if_fail(session != NULL, NULL);
 
-	for (l = session->switches; l != NULL; l = l->next) {
+	for (l = session->switches; l != NULL; l = l->next)
+	{
 		swboard = (MsnSwitchBoard *)l->data;
 
 		if (!swboard->in_use)
--- a/src/protocols/msn/session.h	Tue Jun 01 01:55:55 2004 +0000
+++ b/src/protocols/msn/session.h	Tue Jun 01 06:42:20 2004 +0000
@@ -40,7 +40,7 @@
 
 	guint protocol_ver;
 
-	char *dispatch_server;
+	char *dispatch_host;
 	int dispatch_port;
 
 	gboolean connected;
@@ -108,13 +108,13 @@
  * Creates an MSN session.
  *
  * @param account The account.
- * @param server  The dispatch server.
- * @param port    The dispatch port.
+ * @param server  The dispatch server host.
+ * @param port    The dispatch server port.
  *
  * @return The new MSN session.
  */
 MsnSession *msn_session_new(GaimAccount *account,
-							const char *server, int port);
+							const char *host, int port);
 
 /**
  * Destroys an MSN session.
--- a/src/protocols/msn/switchboard.c	Tue Jun 01 01:55:55 2004 +0000
+++ b/src/protocols/msn/switchboard.c	Tue Jun 01 06:42:20 2004 +0000
@@ -37,9 +37,8 @@
 
 	msg = msn_message_new();
 	msn_message_set_content_type(msg, "text/x-clientcaps");
-	msn_message_set_charset(msg, NULL);
-	msn_message_set_attr(msg, "User-Agent", NULL);
-	msn_message_set_body(msg, MSN_CLIENTINFO);
+	msn_message_set_flag(msg, 'U');
+	msn_message_set_bin_data(msg, MSN_CLIENTINFO, strlen(MSN_CLIENTINFO));
 
 	msn_switchboard_send_msg(swboard, msg);
 
@@ -98,45 +97,45 @@
 		return;
 
 	if (swboard->chat != NULL)
+	{
 		gaim_conv_chat_remove_user(GAIM_CONV_CHAT(swboard->chat), user, NULL);
+	}
 	else
 	{
 		const char *username;
 		GaimConversation *conv;
 		GaimBuddy *b;
-		char buf[MSN_BUF_LEN];
+		char *str = NULL;
 
 		if ((b = gaim_find_buddy(account, user)) != NULL)
 			username = gaim_get_buddy_alias(b);
 		else
 			username = user;
 
-		*buf = '\0';
-
 		if (cmd->param_count == 2 && atoi(cmd->params[1]) == 1)
 		{
 			if (gaim_prefs_get_bool("/plugins/prpl/msn/conv_timeout_notice"))
 			{
-				g_snprintf(buf, sizeof(buf),
-						   _("The conversation has become inactive "
-							 "and timed out."));
+				str = g_strdup_printf(_("The conversation has become "
+										"inactive and timed out."));
 			}
 		}
 		else
 		{
 			if (gaim_prefs_get_bool("/plugins/prpl/msn/conv_close_notice"))
 			{
-				g_snprintf(buf, sizeof(buf),
-						   _("%s has closed the conversation window."),
-						   username);
+				str = g_strdup_printf(_("%s has closed the conversation "
+										"window."), username);
 			}
 		}
 
-		if (*buf != '\0' &&
+		if (str != NULL &&
 			(conv = gaim_find_conversation_with_account(user, account)) != NULL)
 		{
-			gaim_conversation_write(conv, NULL, buf, GAIM_MESSAGE_SYSTEM,
+			gaim_conversation_write(conv, NULL, str, GAIM_MESSAGE_SYSTEM,
 									time(NULL));
+
+			g_free(str);
 		}
 
 		msn_switchboard_destroy(swboard);
@@ -171,7 +170,7 @@
 												 "MSN Chat");
 
 			gaim_conv_chat_add_user(GAIM_CONV_CHAT(swboard->chat),
-							   gaim_account_get_username(account), NULL);
+									gaim_account_get_username(account), NULL);
 
 			gaim_conversation_destroy(conv);
 		}
@@ -243,8 +242,6 @@
 static void
 msg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
-	gaim_debug(GAIM_DEBUG_INFO, "msn", "Found message. Parsing.\n");
-
 	cmdproc->payload_cb  = msg_cmd_post;
 	cmdproc->servconn->payload_len = atoi(cmd->params[2]);
 	cmdproc->temp = g_strdup(cmd->params[0]);
@@ -301,28 +298,34 @@
 {
 	GaimConnection *gc;
 	MsnSwitchBoard *swboard;
-	char *body;
-	char *passport;
+	const char *body;
+	char *body_str;
+	char *body_enc;
+	char *body_final;
+	int body_len;
+	const char *passport;
 	const char *value;
 
 	gc = cmdproc->session->account->gc;
 	swboard = cmdproc->servconn->data;
-	body = gaim_escape_html(msn_message_get_body(msg));
+
+	body = msn_message_get_bin_data(msg, &body_len);
+	body_str = g_strndup(body, body_len);
+	body_enc = gaim_escape_html(body_str);
+	g_free(body_str);
+
 	passport = msg->passport;
 
 	if (!strcmp(passport, "messenger@microsoft.com") &&
 		strstr(body, "immediate security update"))
 	{
-		g_free(body);
-
 		return;
 	}
 
 #if 0
-	gaim_debug(GAIM_DEBUG_INFO, "msn", "Checking User-Agent...\n");
-
-	if ((value = msn_message_get_attr(msg, "User-Agent")) != NULL) {
-		gaim_debug(GAIM_DEBUG_MISC, "msn", "value = '%s'\n", value);
+	if ((value = msn_message_get_attr(msg, "User-Agent")) != NULL)
+	{
+		gaim_debug_misc("msn", "User-Agent = '%s'\n", value);
 	}
 #endif
 
@@ -332,22 +335,27 @@
 
 		msn_parse_format(value, &pre_format, &post_format);
 
-		body = g_strdup_printf("%s%s%s", pre_format, body, post_format);
+		body_final = g_strdup_printf("%s%s%s", pre_format, body_enc, post_format);
 
 		g_free(pre_format);
 		g_free(post_format);
+		g_free(body_enc);
+	}
+	else
+	{
+		body_final = body_enc;
 	}
 
 	if (swboard->chat != NULL)
 	{
 		serv_got_chat_in(gc,
 						 gaim_conv_chat_get_id(GAIM_CONV_CHAT(swboard->chat)),
-						 passport, 0, body, time(NULL));
+						 passport, 0, body_final, time(NULL));
 	}
 	else
-		serv_got_im(gc, passport, body, 0, time(NULL));
+		serv_got_im(gc, passport, body_final, 0, time(NULL));
 
-	g_free(body);
+	g_free(body_final);
 }
 
 static void
@@ -389,31 +397,63 @@
 #endif
 }
 
+void
+msn_switchboard_send_msg(MsnSwitchBoard *swboard, MsnMessage *msg)
+{
+	MsnCmdProc *cmdproc;
+	MsnTransaction *trans;
+	char *payload;
+	size_t payload_len;
+
+	g_return_if_fail(swboard != NULL);
+	g_return_if_fail(msg     != NULL);
+
+	cmdproc = swboard->servconn->cmdproc;
+
+	payload = msn_message_gen_payload(msg, &payload_len);
+
+	trans = msn_transaction_new("MSG", "%c %d", msn_message_get_flag(msg),
+								payload_len);
+
+	trans->payload = payload;
+	trans->payload_len = payload_len;
+
+	if (!g_queue_is_empty(cmdproc->txqueue) || !swboard->joined)
+		msn_cmdproc_queue_trans(cmdproc, trans);
+	else
+		msn_cmdproc_send_trans(cmdproc, trans);
+}
+
 /**************************************************************************
  * Connect stuff
  **************************************************************************/
 static gboolean
 connect_cb(MsnServConn *servconn)
 {
+	MsnSwitchBoard *swboard;
+	MsnCmdProc *cmdproc;
 	GaimAccount *account;
-	MsnSwitchBoard *swboard;
+
+	cmdproc = servconn->cmdproc;
+	g_return_val_if_fail(cmdproc != NULL, FALSE);
 
 	account = servconn->session->account;
 	swboard = servconn->data;
+	g_return_val_if_fail(swboard != NULL, FALSE);
+
+	/* swboard->user_joined = TRUE; */
 
 	swboard->in_use = TRUE;
 
-	gaim_debug_info("msn", "Connecting to switchboard...\n");
-
 	if (msn_switchboard_is_invited(swboard))
 	{
-		msn_cmdproc_send(swboard->cmdproc, "ANS", "%s %s %s",
+		msn_cmdproc_send(cmdproc, "ANS", "%s %s %s",
 						 gaim_account_get_username(account),
 						 swboard->auth_key, swboard->session_id);
 	}
 	else
 	{
-		msn_cmdproc_send(swboard->cmdproc, "USR", "%s %s",
+		msn_cmdproc_send(cmdproc, "USR", "%s %s",
 						 gaim_account_get_username(account),
 						 swboard->auth_key);
 	}
@@ -459,16 +499,16 @@
 
 	/* Register the message type callbacks. */
 	msn_table_add_msg_type(cbs_table, "text/plain",
-							plain_msg);
+						   plain_msg);
 	msn_table_add_msg_type(cbs_table, "text/x-msmsgscontrol",
-							control_msg);
+						   control_msg);
 	msn_table_add_msg_type(cbs_table, "text/x-clientcaps",
-							clientcaps_msg);
+						   clientcaps_msg);
 	msn_table_add_msg_type(cbs_table, "text/x-clientinfo",
-							clientcaps_msg);
+						   clientcaps_msg);
 #if 0
 	msn_table_add_msg_type(cbs_table, "application/x-msnmsgrp2p",
-									msn_p2p_msg);
+						   msn_p2p_msg);
 #endif
 }
 
@@ -496,13 +536,13 @@
 	msn_servconn_set_disconnect_cb(servconn, disconnect_cb);
 
 	if (session->http_method)
-		swboard->servconn->http_data->server_type = "SB";
+		servconn->http_data->server_type = "SB";
 
 	servconn->data = swboard;
 
 	session->switches = g_list_append(session->switches, swboard);
 
-	cmdproc->cbs_table  = cbs_table;
+	cmdproc->cbs_table = cbs_table;
 
 	return swboard;
 }
@@ -629,29 +669,3 @@
 
 	swboard->in_use = FALSE;
 }
-
-void
-msn_switchboard_send_msg(MsnSwitchBoard *swboard, MsnMessage *msg)
-{
-	MsnCmdProc *cmdproc;
-	MsnTransaction *trans;
-	char *payload;
-	size_t payload_len;
-
-	g_return_if_fail(swboard != NULL);
-	g_return_if_fail(msg     != NULL);
-
-	cmdproc = swboard->servconn->cmdproc;
-	payload = msn_message_gen_payload(msg, &payload_len);
-
-	trans = msn_transaction_new("MSG", "%c %d", msn_message_get_flag(msg),
-								payload_len);
-
-	trans->payload = payload;
-	trans->payload_len = payload_len;
-
-	if (!g_queue_is_empty(cmdproc->txqueue) || !swboard->joined)
-		msn_cmdproc_queue_trans(cmdproc, trans);
-	else
-		msn_cmdproc_send_trans(cmdproc, trans);
-}
--- a/src/protocols/msn/switchboard.h	Tue Jun 01 01:55:55 2004 +0000
+++ b/src/protocols/msn/switchboard.h	Tue Jun 01 06:42:20 2004 +0000
@@ -159,8 +159,8 @@
  * Connects to a switchboard.
  *
  * @param swboard The switchboard.
- * @param host    The host.
- * @param port    The port.
+ * @param host    The switchboard server host.
+ * @param port    The switcbharod server port.
  *
  * @return @c TRUE if able to connect, or @c FALSE otherwise.
  */
--- a/src/protocols/msn/transaction.c	Tue Jun 01 01:55:55 2004 +0000
+++ b/src/protocols/msn/transaction.c	Tue Jun 01 06:42:20 2004 +0000
@@ -34,9 +34,12 @@
 
 	trans->command = g_strdup(command);
 
-	va_start(arg, format);
-	trans->params = g_strdup_vprintf(format, arg);
-	va_end(arg);
+	if (format != NULL)
+	{
+		va_start(arg, format);
+		trans->params = g_strdup_vprintf(format, arg);
+		va_end(arg);
+	}
 
 	/* trans->queue = g_queue_new(); */