Bug 1316000 - Remove old Yahoo! Messenger and MySpace IM support. r=aleth
authorPatrick Cloke <clokep@gmail.com>
Wed, 09 Nov 2016 10:17:34 -0500
changeset 791 b9d75e616955a6271c488a84443c14129ee666e1
parent 790 9774e2a68837a2ab11f9dc717c04511b67af6db9
child 792 1db1403c8d5fb2e8a4b95fd37f75253d08581792
push id66
push userclokep@gmail.com
push dateWed, 09 Nov 2016 15:17:47 +0000
reviewersaleth
bugs1316000
Bug 1316000 - Remove old Yahoo! Messenger and MySpace IM support. r=aleth
configure.in
icons/prpl-myspace-32.png
icons/prpl-myspace-48.png
icons/prpl-myspace.png
jar.mn
libpurple/moz.build
libpurple/protocols/myspace/Makefile.in
libpurple/protocols/myspace/README
libpurple/protocols/myspace/markup.c
libpurple/protocols/myspace/markup.h
libpurple/protocols/myspace/message.c
libpurple/protocols/myspace/message.h
libpurple/protocols/myspace/moz.build
libpurple/protocols/myspace/myspace.c
libpurple/protocols/myspace/myspace.h
libpurple/protocols/myspace/persist.h
libpurple/protocols/myspace/session.c
libpurple/protocols/myspace/session.h
libpurple/protocols/myspace/user.c
libpurple/protocols/myspace/user.h
libpurple/protocols/myspace/zap.c
libpurple/protocols/myspace/zap.h
libpurple/protocols/yahoo/Makefile.in
libpurple/protocols/yahoo/libyahoo.c
libpurple/protocols/yahoo/libyahoojp.c
libpurple/protocols/yahoo/libymsg.c
libpurple/protocols/yahoo/libymsg.h
libpurple/protocols/yahoo/moz.build
libpurple/protocols/yahoo/util.c
libpurple/protocols/yahoo/yahoo_aliases.c
libpurple/protocols/yahoo/yahoo_aliases.h
libpurple/protocols/yahoo/yahoo_doodle.c
libpurple/protocols/yahoo/yahoo_doodle.h
libpurple/protocols/yahoo/yahoo_filexfer.c
libpurple/protocols/yahoo/yahoo_filexfer.h
libpurple/protocols/yahoo/yahoo_friend.c
libpurple/protocols/yahoo/yahoo_friend.h
libpurple/protocols/yahoo/yahoo_packet.c
libpurple/protocols/yahoo/yahoo_packet.h
libpurple/protocols/yahoo/yahoo_picture.c
libpurple/protocols/yahoo/yahoo_picture.h
libpurple/protocols/yahoo/yahoo_profile.c
libpurple/protocols/yahoo/yahoochat.c
libpurple/protocols/yahoo/yahoochat.h
libpurple/protocols/yahoo/ycht.c
libpurple/protocols/yahoo/ycht.h
locales/en-US/myspace.properties
locales/en-US/yahoo.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
@@ -178,17 +178,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 myspace novell sametime simple yahoo netsoul"
+STATIC_PRPLS="jabber gg oscar novell sametime simple 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 be84393d82d58a453055160ba45669d3821a3fff..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index a07f8e1f9f914d473879a9feada8ad09d0916772..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index ae8ed7782683f3af3f35a85e042fa99109e4df38..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-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)
 % skin prpl-meanwhile classic/1.0 %skin/classic/prpl/meanwhile/
 	skin/classic/prpl/meanwhile/icon32.png	(icons/prpl-meanwhile-32.png)
 	skin/classic/prpl/meanwhile/icon48.png	(icons/prpl-meanwhile-48.png)
 	skin/classic/prpl/meanwhile/icon.png	(icons/prpl-meanwhile.png)
--- a/libpurple/moz.build
+++ b/libpurple/moz.build
@@ -1,15 +1,15 @@
 # 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', 'myspace', 'novell',
-         'sametime', 'simple', 'yahoo', 'netsoul', 'sipe']
+prpls = ['jabber', 'gg', 'oscar', 'novell',
+         'sametime', 'simple', 'netsoul', 'sipe']
 
 if CONFIG['PURPLE_BONJOUR']:
     prpls += ['bonjour']
 
 if CONFIG['MOZ_DEBUG']:
     prpls += ['null']
 
 DIRS += ['protocols/' + proto for proto in prpls]
deleted file mode 100644
--- a/libpurple/protocols/myspace/Makefile.in
+++ /dev/null
@@ -1,13 +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	= myspace
-
-include $(srcdir)/../prpl.mk
-
-include $(srcdir)/../prpl-rules.mk
deleted file mode 100644
--- a/libpurple/protocols/myspace/README
+++ /dev/null
@@ -1,27 +0,0 @@
-MySpaceIM Protocol Plugin for libpurple by Jeff Connelly 2007-08-07
-
-Greetings. This package contains a plugin for libpurple (as used in
-Pidgin, formerly Gaim) to connect to the new MySpaceIM instant messaging
-network and send/receive messages. Functionality is only basic as of yet,
-and this code should be considered alpha quality.
-
-This code was initially developed under Google Summer of Code 2007.
-
-For features and TODO, see http://developer.pidgin.im/wiki/MySpaceIM
-
-Usage:
-
-Login using your _email address_ you use to login to myspace.com. You can't
-login using your numeric ID or alias.
-
-To test it out, send a message to yourself (by your username or numeric
-uid (email not yet supported)) or tom (6221). In either case you should
-get a reply. You should also be able to talk to other MySpaceIM users if
-you desire. Replies will always be shown as coming from a user's username,
-even if you IM by email or userid.
-
-Feedback welcome. You can IM my test account at "msimprpl" if you feel like it.
-
-Enjoy,
--Jeff Connelly
-msimprpl@xyzzy.cjb.net
deleted file mode 100644
--- a/libpurple/protocols/myspace/markup.c
+++ /dev/null
@@ -1,763 +0,0 @@
-/* MySpaceIM Protocol Plugin - markup
- *
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- *
- * 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 "myspace.h"
-
-typedef int (*MSIM_XMLNODE_CONVERT)(MsimSession *, xmlnode *, gchar **, gchar **);
-
-/* Globals */
-
-/* The names in in emoticon_names (for <i n=whatever>) map to corresponding
- * entries in emoticon_symbols (for the ASCII representation of the emoticon).
- *
- * Multiple emoticon symbols in Pidgin can map to one name. List the
- * canonical form, as inserted by the "Smile!" dialog, first. For example,
- * :) comes before :-), because although both are recognized as 'happy',
- * the first is inserted by the smiley button (first symbol in theme).
- *
- * Note that symbols are case-sensitive in Pidgin -- :-X is not :-x. */
-static struct MSIM_EMOTICON
-{
-	gchar *name;
-	gchar *symbol;
-} msim_emoticons[] = {
-	/* Unfortunately, this list duplicates much of the file
-	 * pidgin/pidgin/pixmaps/emotes/default/22/default.theme.in, because
-	 * that file is part of Pidgin, but we're part of libpurple.
-	 */
-	{ "bigsmile", ":D" },
-	{ "bigsmile", ":-D" },
-	{ "devil", "}:)" },
-	{ "frazzled", ":Z" },
-	{ "geek", "B)" },
-	{ "googles", "%)" },
-	{ "growl", ":E" },
-	{ "laugh", ":))" },		/* Must be before ':)' */
-	{ "happy", ":)" },
-	{ "happy", ":-)" },
-	{ "happi", ":)" },
-	{ "heart", ":X" },
-	{ "mohawk", "-:" },
-	{ "mad", "X(" },
-	{ "messed", "X)" },
-	{ "nerd", "Q)" },
-	{ "oops", ":G" },
-	{ "pirate", "P)" },
-	{ "scared", ":O" },
-	{ "sidefrown", ":{" },
-	{ "sinister", ":B" },
-	{ "smirk", ":," },
-	{ "straight", ":|" },
-	{ "tongue", ":P" },
-	{ "tongue", ":p" },
-	{ "tongy", ":P" },
-	{ "upset", "B|" },
-	{ "wink", ";-)" },
-	{ "wink", ";)" },
-	{ "winc", ";)" },
-	{ "worried", ":[" },
-	{ "kiss", ":x" },
-	{ NULL, NULL }
-};
-
-/* Indexes of this array + 1 map HTML font size to scale of normal font size. *
- * Based on _point_sizes from libpurple/gtkimhtml.c
- *                                 1    2  3    4     5      6       7 */
-static gdouble _font_scale[] = { .85, .95, 1, 1.2, 1.44, 1.728, 2.0736 };
-
-/* Purple maximum font size.  Equivalent to sizeof(_font_scale) / sizeof(_font_scale[0]) */
-#define MAX_FONT_SIZE                   7
-
-#define POINTS_PER_INCH                 72      /* How many pt's in an inch */
-
-/* Text formatting bits for <f s=#> */
-#define MSIM_TEXT_BOLD                  1
-#define MSIM_TEXT_ITALIC                2
-#define MSIM_TEXT_UNDERLINE             4
-
-/* Default baseline size of purple's fonts, in points. What is size 3 in points.
- * _font_scale specifies scaling factor relative to this point size. Note this
- * is only the default; it is configurable in account options. */
-#define MSIM_BASE_FONT_POINT_SIZE       8
-
-/* Default display's DPI. 96 is common but it can differ. Also configurable
- * in account options. */
-#define MSIM_DEFAULT_DPI                96
-
-/* round is part of C99, but sometimes is unavailable before then.
- * Based on http://forums.belution.com/en/cpp/000/050/13.shtml
- */
-static double msim_round(double value)
-{
-	if (value < 0) {
-		return -(floor(-value + 0.5));
-	} else {
-		return   floor( value + 0.5);
-	}
-}
-
-/**
- * Convert typographical font point size to HTML font size.
- * Based on libpurple/gtkimhtml.c
- */
-static guint
-msim_point_to_purple_size(MsimSession *session, guint point)
-{
-	guint size, this_point, base;
-
-	base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE);
-
-	for (size = 0; size < MAX_FONT_SIZE; ++size) {
-		this_point = (guint)msim_round(base * _font_scale[size]);
-
-		if (this_point >= point) {
-			purple_debug_info("msim", "msim_point_to_purple_size: %d pt -> size=%d\n",
-					point, size);
-			return size;
-		}
-	}
-
-	/* No HTML font size was this big; return largest possible. */
-	return this_point;
-}
-
-/**
- * Convert HTML font size to point size.
- */
-static guint
-msim_purple_size_to_point(MsimSession *session, guint size)
-{
-	gdouble scale;
-	guint point;
-	guint base;
-
-	scale = _font_scale[CLAMP(size, 1, MAX_FONT_SIZE) - 1];
-
-	base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE);
-
-	point = (guint)msim_round(scale * base);
-
-	purple_debug_info("msim", "msim_purple_size_to_point: size=%d -> %d pt\n",
-					size, point);
-
-	return point;
-}
-
-/**
- * Convert a msim markup font pixel height to the more usual point size, for incoming messages.
- */
-static guint
-msim_height_to_point(MsimSession *session, guint height)
-{
-	guint dpi;
-
-	dpi = purple_account_get_int(session->account, "dpi", MSIM_DEFAULT_DPI);
-
-	return (guint)msim_round((POINTS_PER_INCH * 1. / dpi) * height);
-
-	/* See also: libpurple/protocols/bonjour/jabber.c
-	 * _font_size_ichat_to_purple */
-}
-
-/**
- * Convert point size to msim pixel height font size specification, for outgoing messages.
- */
-static guint
-msim_point_to_height(MsimSession *session, guint point)
-{
-	guint dpi;
-
-	dpi = purple_account_get_int(session->account, "dpi", MSIM_DEFAULT_DPI);
-
-	return (guint)msim_round((dpi * 1. / POINTS_PER_INCH) * point);
-}
-
-/**
- * Convert the msim markup <f> (font) tag into HTML.
- */
-static void
-msim_markup_f_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
-{
-	const gchar *face, *height_str, *decor_str;
-	GString *gs_end, *gs_begin;
-	guint decor, height;
-
-	face = xmlnode_get_attrib(root, "f");
-	height_str = xmlnode_get_attrib(root, "h");
-	decor_str = xmlnode_get_attrib(root, "s");
-
-	/* Validate the font face, to avoid constructing invalid HTML later */
-	if (face != NULL && strchr(face, '\'') != NULL)
-		face = NULL;
-
-	height = height_str != NULL ? atol(height_str) : 12;
-	decor = decor_str != NULL ? atol(decor_str) : 0;
-
-	/*
-	 * The HTML we're constructing here is a bit redudant.  Ideally we
-	 * would use only the font-family and font-size CSS span, but Pidgin
-	 * doesn't support it (it's included for other UIs).  For Pidgin we
-	 * wrap the whole thing in an ugly font tag, and Pidgin will happily
-	 * ignore the <span>.
-	 */
-	gs_begin = g_string_new("");
-	if (height && !face) {
-		guint point_size = msim_height_to_point(session, height);
-		g_string_printf(gs_begin,
-				"<font size='%d'><span style='font-size: %dpt'>",
-				msim_point_to_purple_size(session, point_size),
-				point_size);
-	} else if (height && face) {
-		guint point_size = msim_height_to_point(session, height);
-		g_string_printf(gs_begin,
-				"<font face='%s' size='%d'><span style='font-family: %s; font-size: %dpt'>",
-				face, msim_point_to_purple_size(session, point_size),
-				face, point_size);
-	} else {
-		g_string_printf(gs_begin, "<font><span>");
-	}
-
-	gs_end = g_string_new("</span></font>");
-
-	if (decor & MSIM_TEXT_BOLD) {
-		g_string_append(gs_begin, "<b>");
-		g_string_prepend(gs_end, "</b>");
-	}
-
-	if (decor & MSIM_TEXT_ITALIC) {
-		g_string_append(gs_begin, "<i>");
-		g_string_append(gs_end, "</i>");
-	}
-
-	if (decor & MSIM_TEXT_UNDERLINE) {
-		g_string_append(gs_begin, "<u>");
-		g_string_append(gs_end, "</u>");
-	}
-
-	*begin = g_string_free(gs_begin, FALSE);
-	*end = g_string_free(gs_end, FALSE);
-}
-
-/**
- * Convert a msim markup color to a color suitable for libpurple.
- *
- * @param msim Either a color name, or an rgb(x,y,z) code.
- *
- * @return A new string, either a color name or #rrggbb code. Must g_free().
- */
-static char *
-msim_color_to_purple(const char *msim)
-{
-	guint red, green, blue;
-
-	if (!msim) {
-		return g_strdup("black");
-	}
-
-	if (sscanf(msim, "rgb(%d,%d,%d)", &red, &green, &blue) != 3) {
-		/* Color name. */
-		return g_strdup(msim);
-	}
-	/* TODO: rgba (alpha). */
-
-	return g_strdup_printf("#%.2x%.2x%.2x", red, green, blue);
-}
-
-/**
- * Convert the msim markup <a> (anchor) tag into HTML.
- */
-static void
-msim_markup_a_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
-{
-	const gchar *href;
-
-	href = xmlnode_get_attrib(root, "h");
-	if (!href) {
-		href = "";
-	}
-
-	*begin = g_strdup_printf("<a href=\"%s\">%s", href, href);
-	*end = g_strdup("</a>");
-}
-
-/**
- * Convert the msim markup <p> (paragraph) tag into HTML.
- */
-static void
-msim_markup_p_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
-{
-	/* Just pass through unchanged.
-	 *
-	 * Note: attributes currently aren't passed, if there are any. */
-	*begin = g_strdup("<p>");
-	*end = g_strdup("</p>");
-}
-
-/**
- * Convert the msim markup <c> tag (text color) into HTML.
- */
-static void
-msim_markup_c_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
-{
-	const gchar *color;
-	gchar *purple_color;
-
-	color = xmlnode_get_attrib(root, "v");
-	if (!color) {
-		purple_debug_info("msim", "msim_markup_c_to_html: <c> tag w/o v attr\n");
-		*begin = g_strdup("");
-		*end = g_strdup("");
-		/* TODO: log as unrecognized */
-		return;
-	}
-
-	purple_color = msim_color_to_purple(color);
-
-#ifdef USE_CSS_FORMATTING
-	*begin = g_strdup_printf("<span style='color: %s'>", purple_color);
-	*end = g_strdup("</span>");
-#else
-	*begin = g_strdup_printf("<font color='%s'>", purple_color);
-	*end = g_strdup("</font>");
-#endif
-
-	g_free(purple_color);
-}
-
-/**
- * Convert the msim markup <b> tag (background color) into HTML.
- */
-static void
-msim_markup_b_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
-{
-	const gchar *color;
-	gchar *purple_color;
-
-	color = xmlnode_get_attrib(root, "v");
-	if (!color) {
-		*begin = g_strdup("");
-		*end = g_strdup("");
-		purple_debug_info("msim", "msim_markup_b_to_html: <b> w/o v attr\n");
-		/* TODO: log as unrecognized. */
-		return;
-	}
-
-	purple_color = msim_color_to_purple(color);
-
-#ifdef USE_CSS_FORMATTING
-	*begin = g_strdup_printf("<span style='background-color: %s'>", purple_color);
-	*end = g_strdup("</span>");
-#else
-	*begin = g_strdup_printf("<body bgcolor='%s'>", purple_color);
-	*end = g_strdup("</body>");
-#endif
-
-	g_free(purple_color);
-}
-
-/**
- * Convert the msim markup <i> tag (emoticon image) into HTML.
- */
-static void
-msim_markup_i_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
-{
-	const gchar *name;
-	guint i;
-	struct MSIM_EMOTICON *emote;
-
-	name = xmlnode_get_attrib(root, "n");
-	if (!name) {
-		purple_debug_info("msim", "msim_markup_i_to_html: <i> w/o n\n");
-		*begin = g_strdup("");
-		*end = g_strdup("");
-		/* TODO: log as unrecognized */
-		return;
-	}
-
-	/* Find and use canonical form of smiley symbol. */
-	for (i = 0; (emote = &msim_emoticons[i]) && emote->name != NULL; ++i) {
-		if (g_str_equal(name, emote->name)) {
-			*begin = g_strdup(emote->symbol);
-			*end = g_strdup("");
-			return;
-		}
-	}
-
-	/* Couldn't find it, sorry. Try to degrade gracefully. */
-	*begin = g_strdup_printf("**%s**", name);
-	*end = g_strdup("");
-}
-
-/**
- * Convert an individual msim markup tag to HTML.
- */
-static int
-msim_markup_tag_to_html(MsimSession *session, xmlnode *root, gchar **begin,
-		gchar **end)
-{
-	g_return_val_if_fail(root != NULL, 0);
-
-	if (g_str_equal(root->name, "f")) {
-		msim_markup_f_to_html(session, root, begin, end);
-	} else if (g_str_equal(root->name, "a")) {
-		msim_markup_a_to_html(session, root, begin, end);
-	} else if (g_str_equal(root->name, "p")) {
-		msim_markup_p_to_html(session, root, begin, end);
-	} else if (g_str_equal(root->name, "c")) {
-		msim_markup_c_to_html(session, root, begin, end);
-	} else if (g_str_equal(root->name, "b")) {
-		msim_markup_b_to_html(session, root, begin, end);
-	} else if (g_str_equal(root->name, "i")) {
-		msim_markup_i_to_html(session, root, begin, end);
-	} else {
-		purple_debug_info("msim", "msim_markup_tag_to_html: "
-				"unknown tag name=%s, ignoring\n",
-				root->name ? root->name : "(NULL)");
-		*begin = g_strdup("");
-		*end = g_strdup("");
-	}
-	return 0;
-}
-
-/**
- * Convert an individual HTML tag to msim markup.
- */
-static int
-html_tag_to_msim_markup(MsimSession *session, xmlnode *root, gchar **begin,
-		gchar **end)
-{
-	int ret = 0;
-
-	if (!purple_utf8_strcasecmp(root->name, "root") ||
-	    !purple_utf8_strcasecmp(root->name, "html")) {
-		*begin = g_strdup("");
-		*end = g_strdup("");
-	/* TODO: Coalesce nested tags into one <f> tag!
-	 * Currently, the 's' value will be overwritten when b/i/u is nested
-	 * within another one, and only the inner-most formatting will be
-	 * applied to the text. */
-	} else if (!purple_utf8_strcasecmp(root->name, "b")) {
-		if (root->child->type == XMLNODE_TYPE_DATA) {
-			*begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_BOLD);
-			*end = g_strdup("</f>");
-		} else {
-			if (!purple_utf8_strcasecmp(root->child->name,"i")) {
-				ret++;
-				if (root->child->child->type == XMLNODE_TYPE_DATA) {
-					*begin = g_strdup_printf("<f s='%d'>", (MSIM_TEXT_BOLD + MSIM_TEXT_ITALIC));
-					*end = g_strdup("</f>");
-				} else {
-					if (!purple_utf8_strcasecmp(root->child->child->name,"u")) {
-						ret++;
-						*begin = g_strdup_printf("<f s='%d'>", (MSIM_TEXT_BOLD + MSIM_TEXT_ITALIC + MSIM_TEXT_UNDERLINE));
-						*end = g_strdup("</f>");
-					}
-				}
-			} else if (!purple_utf8_strcasecmp(root->child->name,"u")) {
-				ret++;
-				*begin = g_strdup_printf("<f s='%d'>", (MSIM_TEXT_BOLD + MSIM_TEXT_UNDERLINE));
-				*end = g_strdup("</f>");
-			}
-		}
-	} else if (!purple_utf8_strcasecmp(root->name, "i")) {
-		if (root->child->type == XMLNODE_TYPE_DATA) {
-			*begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_ITALIC);
-			*end = g_strdup("</f>");
-		} else {
-			if (!purple_utf8_strcasecmp(root->child->name,"u")) {
-				ret++;
-				*begin = g_strdup_printf("<f s='%d'>", (MSIM_TEXT_ITALIC + MSIM_TEXT_UNDERLINE));
-				*end = g_strdup("</f>");
-			}
-		}
-	} else if (!purple_utf8_strcasecmp(root->name, "u")) {
-		*begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_UNDERLINE);
-		*end = g_strdup("</f>");
-	} else if (!purple_utf8_strcasecmp(root->name, "a")) {
-		const gchar *href;
-		gchar *link_text;
-
-		href = xmlnode_get_attrib(root, "href");
-
-		if (!href) {
-			href = xmlnode_get_attrib(root, "HREF");
-		}
-
-		link_text = xmlnode_get_data(root);
-
-		if (href) {
-			if (g_str_equal(link_text, href)) {
-				/* Purple gives us: <a href="URL">URL</a>
-				 * Translate to <a h='URL' />
-				 * Displayed as text of URL with link to URL
-				 */
-				*begin = g_strdup_printf("<a h='%s' />", href);
-			} else {
-				/* But if we get: <a href="URL">text</a>
-				 * Translate to: text: <a h='URL' />
-				 *
-				 * Because official client only supports self-closed <a>
-				 * tags; you can't change the link text.
-				 */
-				*begin = g_strdup_printf("%s: <a h='%s' />", link_text, href);
-			}
-		} else {
-			*begin = g_strdup("<a />");
-		}
-
-		/* Sorry, kid. MySpace doesn't support you within <a> tags. */
-		xmlnode_free(root->child);
-		g_free(link_text);
-		root->child = NULL;
-
-		*end = g_strdup("");
-	} else if (!purple_utf8_strcasecmp(root->name, "font")) {
-		GString *tmpbegin, *tmpend;
-		const gchar *size;
-		const gchar *face;
-		const gchar *color;
-
-		size = xmlnode_get_attrib(root, "size");
-		face = xmlnode_get_attrib(root, "face");
-		color = xmlnode_get_attrib(root, "color");
-
-		tmpbegin = g_string_new("<f");
-		tmpend = g_string_new("</f>");
-
-		if (face != NULL)
-			g_string_append_printf(tmpbegin, " f='%s'", face);
-
-		if (size != NULL)
-			g_string_append_printf(tmpbegin, " h='%d'",
-					 msim_point_to_height(session,
-						 msim_purple_size_to_point(session, atoi(size))));
-
-		/* Close the <f> tag */
-		g_string_append(tmpbegin, ">");
-
-		if (color != NULL) {
-			g_string_append_printf(tmpbegin, "<c v='%s'>", color);
-			g_string_prepend(tmpend, "</c>");
-		}
-
-		*begin = g_string_free(tmpbegin, FALSE);
-		*end = g_string_free(tmpend, FALSE);
-
-	} else if (!purple_utf8_strcasecmp(root->name, "body")) {
-		const gchar *bgcolor;
-
-		bgcolor = xmlnode_get_attrib(root, "bgcolor");
-
-		if (bgcolor != NULL) {
-			*begin = g_strdup_printf("<b v='%s'>", bgcolor);
-			*end = g_strdup("</b>");
-		}
-
-	} else {
-		gchar *err;
-
-#ifdef MSIM_MARKUP_SHOW_UNKNOWN_TAGS
-		*begin = g_strdup_printf("[%s]", root->name);
-		*end = g_strdup_printf("[/%s]", root->name);
-#else
-		*begin = g_strdup("");
-		*end = g_strdup("");
-#endif
-
-		err = g_strdup_printf("html_tag_to_msim_markup: unrecognized "
-			"HTML tag %s was sent by the IM client; ignoring",
-			root->name ? root->name : "(NULL)");
-		msim_unrecognized(NULL, NULL, err);
-		g_free(err);
-	}
-	return ret;
-}
-
-/**
- * Convert an xmlnode of msim markup or HTML to an HTML string or msim markup.
- *
- * @param f Function to convert tags.
- *
- * @return An HTML string. Caller frees.
- */
-static void
-msim_convert_xmlnode(MsimSession *session, GString *out, xmlnode *root, MSIM_XMLNODE_CONVERT f, int nodes_processed)
-{
-	xmlnode *node;
-	gchar *begin, *end, *tmp;
-	int descended = nodes_processed;
-
-	if (!root || !root->name)
-		return;
-
-	purple_debug_info("msim", "msim_convert_xmlnode: got root=%s\n",
-			root->name);
-
-	begin = end = NULL;
-
-	if (descended == 0) /* We've not formatted this yet.. :) */
-		descended = f(session, root, &begin, &end); /* Get the value that our format function has already descended for us */
-
-	g_string_append(out, begin);
-	g_free(begin);
-
-	/* Loop over all child nodes. */
-	for (node = root->child; node != NULL; node = node->next) {
-		switch (node->type) {
-			case XMLNODE_TYPE_ATTRIB:
-				/* Attributes handled above. */
-				break;
-
-			case XMLNODE_TYPE_TAG:
-				/* A tag or tag with attributes. Recursively descend. */
-				msim_convert_xmlnode(session, out, node, f, descended);
-
-				purple_debug_info("msim", " ** node name=%s\n",
-						node->name ? node->name : "(NULL)");
-				break;
-
-			case XMLNODE_TYPE_DATA:
-				/* Literal text. */
-				/*
-				 * TODO: Why is it necessary to escape here?  I thought
-				 *       node->data was already escaped?
-				 */
-				tmp = g_markup_escape_text(node->data, node->data_sz);
-				g_string_append(out, tmp);
-				g_free(tmp);
-				break;
-
-			default:
-				purple_debug_warning("msim",
-						"msim_convert_xmlnode: unknown node type\n");
-		}
-	}
-
-	/* TODO: Note that msim counts each piece of text enclosed by <f> as
-	 * a paragraph and will display each on its own line. You actually have
-	 * to _nest_ <f> tags to intersperse different text in one paragraph!
-	 * Comment out this line below to see. */
-	g_string_append(out, end);
-	g_free(end);
-}
-
-/**
- * Convert XML to something based on MSIM_XMLNODE_CONVERT.
- */
-static gchar *
-msim_convert_xml(MsimSession *session, const gchar *raw, MSIM_XMLNODE_CONVERT f)
-{
-	xmlnode *root;
-	GString *str;
-	gchar *enclosed_raw;
-
-	g_return_val_if_fail(raw != NULL, NULL);
-
-	/* Enclose text in one root tag, to try to make it valid XML for parsing. */
-	enclosed_raw = g_strconcat("<root>", raw, "</root>", NULL);
-
-	root = xmlnode_from_str(enclosed_raw, -1);
-
-	if (!root) {
-		purple_debug_warning("msim", "msim_markup_to_html: couldn't parse "
-				"%s as XML, returning raw: %s\n", enclosed_raw, raw);
-		/* TODO: msim_unrecognized */
-		g_free(enclosed_raw);
-		return g_strdup(raw);
-	}
-
-	g_free(enclosed_raw);
-
-	str = g_string_new(NULL);
-	msim_convert_xmlnode(session, str, root, f, 0);
-	xmlnode_free(root);
-
-	purple_debug_info("msim", "msim_markup_to_html: returning %s\n", str->str);
-
-	return g_string_free(str, FALSE);
-}
-
-/**
- * Convert plaintext smileys to <i> markup tags.
- *
- * @param before Original text with ASCII smileys. Will be freed.
- * @return A new string with <i> tags, if applicable. Must be g_free()'d.
- */
-static gchar *
-msim_convert_smileys_to_markup(gchar *before)
-{
-	gchar *old, *new, *replacement;
-	guint i;
-	struct MSIM_EMOTICON *emote;
-
-	old = before;
-	new = NULL;
-
-	for (i = 0; (emote = &msim_emoticons[i]) && emote->name != NULL; ++i) {
-		gchar *name, *symbol;
-
-		name = emote->name;
-		symbol = emote->symbol;
-
-		replacement = g_strdup_printf("<i n=\"%s\"/>", name);
-
-		purple_debug_info("msim", "msim_convert_smileys_to_markup: %s->%s\n",
-				symbol ? symbol : "(NULL)",
-				replacement ? replacement : "(NULL)");
-		new = purple_strreplace(old, symbol, replacement);
-
-		g_free(replacement);
-		g_free(old);
-
-		old = new;
-	}
-
-	return new;
-}
-
-/**
- * High-level function to convert MySpaceIM markup to Purple (HTML) markup.
- *
- * @return Purple markup string, must be g_free()'d. */
-gchar *
-msim_markup_to_html(MsimSession *session, const gchar *raw)
-{
-	return msim_convert_xml(session, raw, msim_markup_tag_to_html);
-}
-
-/**
- * High-level function to convert Purple (HTML) to MySpaceIM markup.
- *
- * TODO: consider using purple_markup_html_to_xhtml() to make valid XML.
- *
- * @return HTML markup string, must be g_free()'d. */
-gchar *
-html_to_msim_markup(MsimSession *session, const gchar *raw)
-{
-	gchar *markup;
-
-	markup = msim_convert_xml(session, raw, html_tag_to_msim_markup);
-
-	if (purple_account_get_bool(session->account, "emoticons", TRUE)) {
-		/* Frees markup and allocates a new one. */
-		markup = msim_convert_smileys_to_markup(markup);
-	}
-
-	return markup;
-}
deleted file mode 100644
--- a/libpurple/protocols/myspace/markup.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* MySpaceIM Protocol Plugin - markup
- *
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- *
- * 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 _MYSPACE_MARKUP_H
-#define _MYSPACE_MARKUP_H
-
-/* High-level msim markup <=> Purple html conversion functions. */
-gchar *msim_markup_to_html(MsimSession *, const gchar *raw);
-gchar *html_to_msim_markup(MsimSession *, const gchar *raw);
-
-#endif /* !_MYSPACE_MARKUP_H */
deleted file mode 100644
--- a/libpurple/protocols/myspace/message.c
+++ /dev/null
@@ -1,1413 +0,0 @@
-/** MySpaceIM protocol messages
- *
- * \author Jeff Connelly
- *
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- *
- * 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 "myspace.h"
-#include "message.h"
-
-static void msim_msg_debug_string_element(gpointer data, gpointer user_data);
-
-/**
- * Escape codes and associated replacement text, used for protocol message
- * escaping and unescaping.
- */
-static struct MSIM_ESCAPE_REPLACEMENT {
-	gchar *code;
-	gchar text;
-} msim_escape_replacements[] = {
-	{ "/1", '/' },
-	{ "/2", '\\' },
-	/* { "/3", "|" }, */      /* Not used here -- only for within arrays */
-	{ NULL, 0 }
-};
-
-/**
- * Escape a protocol message.
- *
- * @return The escaped message. Caller must g_free().
- */
-gchar *
-msim_escape(const gchar *msg)
-{
-	GString *gs;
-	guint i, j;
-	guint msg_len;
-
-	gs = g_string_new("");
-	msg_len = strlen(msg);
-
-	for (i = 0; i < msg_len; ++i) {
-		struct MSIM_ESCAPE_REPLACEMENT *replacement;
-		gchar *replace;
-
-		replace = NULL;
-
-		/* Check for characters that need to be escaped, and escape them. */
-		for (j = 0; (replacement = &msim_escape_replacements[j]) &&
-				replacement->code != NULL; ++j) {
-			if (msg[i] == replacement->text) {
-				replace = replacement->code;
-				break;
-			}
-		}
-
-		if (replace) {
-			g_string_append(gs, replace);
-		} else {
-			g_string_append_c(gs, msg[i]);
-		}
-	}
-
-#ifdef MSIM_DEBUG_ESCAPE
-	purple_debug_info("msim", "msim_escape: msg=%s, ret=%s\n", msg, gs->str);
-#endif
-
-	return g_string_free(gs, FALSE);
-}
-
-/**
- * Unescape a protocol message.
- *
- * @return The unescaped message, caller must g_free().
- */
-gchar *
-msim_unescape(const gchar *msg)
-{
-	GString *gs;
-	guint i, j;
-	guint msg_len;
-
-	gs = g_string_new("");
-	msg_len = strlen(msg);
-
-	for (i = 0; i < msg_len; ++i) {
-		struct MSIM_ESCAPE_REPLACEMENT *replacement;
-		gchar replace;
-
-		replace = msg[i];
-
-		for (j = 0; (replacement = &msim_escape_replacements[j]) &&
-				replacement->code != NULL; ++j) {
-			if (msg[i] == replacement->code[0] &&
-			    i + 1 < msg_len &&
-			    msg[i + 1] == replacement->code[1]) {
-				replace = replacement->text;
-				++i;
-				break;
-			}
-		}
-
-		g_string_append_c(gs, replace);
-	}
-
-#ifdef MSIM_DEBUG_ESCAPE
-	purple_debug_info("msim", "msim_unescape: msg=%s, ret=%s\n", msg, gs->str);
-#endif
-
-	return g_string_free(gs, FALSE);
-}
-
-/**
- * Create a new message from va_list and its first argument.
- *
- * @param first_key The first argument (a key), or NULL to take all arguments
- *    from argp.
- * @param argp A va_list of variadic arguments, already started with va_start().
- * @return New MsimMessage *, must be freed with msim_msg_free().
- *
- * For internal use - users probably want msim_msg_new() or msim_send().
- */
-static MsimMessage *
-msim_msg_new_v(gchar *first_key, va_list argp)
-{
-	gchar *key, *value;
-	MsimMessageType type;
-	MsimMessage *msg;
-	gboolean first;
-
-	GString *gs;
-	GList *gl;
-	MsimMessage *dict;
-
-	/* Begin with an empty message. */
-	msg = NULL;
-
-	/* First parameter can be given explicitly. */
-	first = first_key != NULL;
-
-	/* Read key, type, value triplets until NULL. */
-	do {
-		if (first) {
-			key = first_key;
-			first = FALSE;
-		} else {
-			key = va_arg(argp, gchar *);
-			if (!key) {
-				break;
-			}
-		}
-
-		type = va_arg(argp, int);
-
-		/* Interpret variadic arguments. */
-		switch (type) {
-			case MSIM_TYPE_INTEGER:
-			case MSIM_TYPE_BOOLEAN:
-				msg = msim_msg_append(msg, key, type, GUINT_TO_POINTER(va_arg(argp, int)));
-				break;
-
-			case MSIM_TYPE_STRING:
-				value = va_arg(argp, char *);
-
-				g_return_val_if_fail(value != NULL, FALSE);
-
-				msg = msim_msg_append(msg, key, type, value);
-				break;
-
-			case MSIM_TYPE_BINARY:
-				gs = va_arg(argp, GString *);
-
-				g_return_val_if_fail(gs != NULL, FALSE);
-
-				/* msim_msg_free() will free this GString the caller created. */
-				msg = msim_msg_append(msg, key, type, gs);
-				break;
-
-			case MSIM_TYPE_LIST:
-				gl = va_arg(argp, GList *);
-
-				g_return_val_if_fail(gl != NULL, FALSE);
-
-				msg = msim_msg_append(msg, key, type, gl);
-				break;
-
-			case MSIM_TYPE_DICTIONARY:
-				dict = va_arg(argp, MsimMessage *);
-
-				g_return_val_if_fail(dict != NULL, FALSE);
-
-				msg = msim_msg_append(msg, key, type, dict);
-				break;
-
-			default:
-				purple_debug_info("msim", "msim_send: unknown type %d\n", type);
-				break;
-		}
-	} while(key);
-
-	return msg;
-}
-
-/**
- * Create a new MsimMessage.
- *
- * @param first_key The first key in the sequence, or NULL for an empty message.
- * @param ... A sequence of gchar* key/type/value triplets, terminated with NULL.
- *
- * See msim_msg_append() documentation for details on types.
- */
-MsimMessage *
-msim_msg_new(gchar *first_key, ...)
-{
-	MsimMessage *ret = NULL;
-	va_list argp;
-
-	if (first_key) {
-		va_start(argp, first_key);
-		ret = msim_msg_new_v(first_key, argp);
-		va_end(argp);
-	}
-
-	return ret;
-}
-
-/**
- * Pack a string using the given GFunc and seperator.
- * Used by msim_msg_dump() and msim_msg_pack().
- */
-static gchar *
-msim_msg_pack_using(MsimMessage *msg,
-		GFunc gf,
-		const gchar *sep,
-		const gchar *begin, const gchar *end)
-{
-	int num_items;
-	gchar **strings;
-	gchar **strings_tmp;
-	gchar *joined;
-	gchar *final;
-	int i;
-
-	g_return_val_if_fail(msg != NULL, NULL);
-
-	num_items = g_list_length(msg);
-
-	/* Add one for NULL terminator for g_strjoinv(). */
-	strings = (gchar **)g_new0(gchar *, num_items + 1);
-
-	strings_tmp = strings;
-	g_list_foreach(msg, gf, &strings_tmp);
-
-	joined = g_strjoinv(sep, strings);
-	final = g_strconcat(begin, joined, end, NULL);
-	g_free(joined);
-
-	/* Clean up. */
-	for (i = 0; i < num_items; ++i) {
-		g_free(strings[i]);
-	}
-
-	g_free(strings);
-
-	return final;
-}
-
-/**
- * Return a human-readable string of the message.
- *
- * @return A new gchar *, must be g_free()'d.
- */
-static gchar *
-msim_msg_dump_to_str(MsimMessage *msg)
-{
-	gchar *debug_str;
-
-	if (!msg) {
-		debug_str = g_strdup("<MsimMessage: empty>");
-	} else {
-		debug_str = msim_msg_pack_using(msg, msim_msg_debug_string_element,
-				"\n", "<MsimMessage: \n", "\n/MsimMessage>");
-	}
-
-	return debug_str;
-}
-
-/**
- * Store a human-readable string describing the element.
- *
- * @param data Pointer to an MsimMessageElement.
- * @param user_data
- */
-static void
-msim_msg_debug_string_element(gpointer data, gpointer user_data)
-{
-	MsimMessageElement *elem;
-	gchar *string;
-	GString *gs;
-	gchar *binary;
-	gchar ***items;  /* wow, a pointer to a pointer to a pointer */
-
-	gchar *s;
-	GList *gl;
-	guint i;
-
-	elem = (MsimMessageElement *)data;
-	items = user_data;
-
-	switch (elem->type) {
-		case MSIM_TYPE_INTEGER:
-			string = g_strdup_printf("%s(integer): %d", elem->name,
-					GPOINTER_TO_UINT(elem->data));
-			break;
-
-		case MSIM_TYPE_RAW:
-			string = g_strdup_printf("%s(raw): %s", elem->name,
-					elem->data ? (gchar *)elem->data : "(NULL)");
-			break;
-
-		case MSIM_TYPE_STRING:
-			string = g_strdup_printf("%s(string): %s", elem->name,
-					elem->data ? (gchar *)elem->data : "(NULL)");
-			break;
-
-		case MSIM_TYPE_BINARY:
-			gs = (GString *)elem->data;
-			binary = purple_base64_encode((guchar*)gs->str, gs->len);
-			string = g_strdup_printf("%s(binary, %d bytes): %s", elem->name, (int)gs->len, binary);
-			g_free(binary);
-			break;
-
-		case MSIM_TYPE_BOOLEAN:
-			string = g_strdup_printf("%s(boolean): %s", elem->name,
-					elem->data ? "TRUE" : "FALSE");
-			break;
-
-		case MSIM_TYPE_DICTIONARY:
-			if (!elem->data) {
-				s = g_strdup("(NULL)");
-			} else {
-				s = msim_msg_dump_to_str((MsimMessage *)elem->data);
-			}
-
-			if (!s) {
-				s = g_strdup("(NULL, couldn't msim_msg_dump_to_str)");
-			}
-
-			string = g_strdup_printf("%s(dict): %s", elem->name, s);
-
-			g_free(s);
-			break;
-
-		case MSIM_TYPE_LIST:
-			gs = g_string_new("");
-			g_string_append_printf(gs, "%s(list): \n", elem->name);
-
-			i = 0;
-			for (gl = (GList *)elem->data; gl != NULL; gl = g_list_next(gl)) {
-				g_string_append_printf(gs, " %d. %s\n", i, (gchar *)(gl->data));
-				++i;
-			}
-
-			string = g_string_free(gs, FALSE);
-			break;
-
-		default:
-			string = g_strdup_printf("%s(unknown type %d",
-					elem->name ? elem->name : "(NULL)", elem->type);
-			break;
-	}
-
-	**items = string;
-	++(*items);
-}
-
-/**
- * Search for and return the node in msg, matching name, or NULL.
- *
- * @param msg Message to search within.
- * @param name Field name to search for.
- *
- * @return The GList * node for the MsimMessageElement with the given name, or NULL if not found or name is NULL.
- *
- * For internal use - users probably want to use msim_msg_get() to
- * access the MsimMessageElement *, instead of the GList * container.
- *
- */
-static GList *
-msim_msg_get_node(const MsimMessage *msg, const gchar *name)
-{
-	GList *node;
-
-	if (!name || !msg) {
-		return NULL;
-	}
-
-	/* Linear search for the given name. O(n) but n is small. */
-	for (node = (GList*)msg; node != NULL; node = g_list_next(node)) {
-		MsimMessageElement *elem;
-
-		elem = (MsimMessageElement *)node->data;
-
-		g_return_val_if_fail(elem != NULL, NULL);
-		g_return_val_if_fail(elem->name != NULL, NULL);
-
-		if (strcmp(elem->name, name) == 0) {
-			return node;
-		}
-	}
-	return NULL;
-}
-
-/**
- * Create a new MsimMessageElement * - must be g_free()'d.
- *
- * For internal use; users probably want msim_msg_append() or msim_msg_insert_before().
- *
- * @param dynamic_name Whether 'name' should be freed when the message is destroyed.
- */
-static MsimMessageElement *
-msim_msg_element_new(const gchar *name, MsimMessageType type, gpointer data, gboolean dynamic_name)
-{
-	MsimMessageElement *elem;
-
-	elem = g_new0(MsimMessageElement, 1);
-
-	elem->name = name;
-	elem->dynamic_name = dynamic_name;
-	elem->type = type;
-	elem->data = data;
-
-	return elem;
-}
-
-/**
- * Append a new element to a message.
- *
- * @param name Textual name of element (static string, neither copied nor freed).
- * @param type An MSIM_TYPE_* code.
- * @param data Pointer to data, see below.
- *
- * @return The new message - must be assigned to as with GList*. For example:
- *
- *     msg = msim_msg_append(msg, ...)
- *
- * The data parameter depends on the type given:
- *
- * * MSIM_TYPE_INTEGER: Use GUINT_TO_POINTER(x).
- *
- * * MSIM_TYPE_BINARY: Same as integer, non-zero is TRUE and zero is FALSE.
- *
- * * MSIM_TYPE_STRING: gchar *. The data WILL BE FREED - use g_strdup() if needed.
- *
- * * MSIM_TYPE_RAW: gchar *. The data WILL BE FREED - use g_strdup() if needed.
- *
- * * MSIM_TYPE_BINARY: g_string_new_len(data, length). The data AND GString will be freed.
- *
- * * MSIM_TYPE_DICTIONARY: An MsimMessage *. Freed when message is destroyed.
- *
- * * MSIM_TYPE_LIST: GList * of gchar *. Again, everything will be freed.
- *
- * */
-MsimMessage *
-msim_msg_append(MsimMessage *msg, const gchar *name,
-		MsimMessageType type, gpointer data)
-{
-	return g_list_append(msg, msim_msg_element_new(name, type, data, FALSE));
-}
-
-/**
- * Append a new element, but with a dynamically-allocated name.
- * Exactly the same as msim_msg_append(), except 'name' will be freed when
- * the message is destroyed. Normally, it isn't, because a static string is given.
- */
-static MsimMessage *
-msim_msg_append_dynamic_name(MsimMessage *msg, gchar *name,
-		MsimMessageType type, gpointer data)
-{
-	return g_list_append(msg, msim_msg_element_new(name, type, data, TRUE));
-}
-
-/**
- * Insert a new element into a message, before the given element name.
- *
- * @param name_before Name of the element to insert the new element before. If
- *                    could not be found or NULL, new element will be inserted at end.
- *
- * See msim_msg_append() for usage of other parameters, and an important note about return value.
- */
-MsimMessage *
-msim_msg_insert_before(MsimMessage *msg, const gchar *name_before,
-		const gchar *name, MsimMessageType type, gpointer data)
-{
-	MsimMessageElement *new_elem;
-	GList *node_before;
-
-	new_elem = msim_msg_element_new(name, type, data, FALSE);
-
-	node_before = msim_msg_get_node(msg, name_before);
-
-	return g_list_insert_before(msg, node_before, new_elem);
-}
-
-/**
- * Perform a deep copy on a GList * of gchar * strings. Free with msim_msg_list_free().
- */
-static GList *
-msim_msg_list_copy(const GList *old)
-{
-	GList *new_list;
-
-	new_list = NULL;
-
-	/* Deep copy (g_list_copy is shallow). Copy each string. */
-	for (; old != NULL; old = g_list_next(old)) {
-		new_list = g_list_append(new_list, g_strdup(old->data));
-	}
-
-	return new_list;
-}
-
-/**
- * Clone an individual element.
- *
- * @param data MsimMessageElement * to clone.
- * @param user_data Pointer to MsimMessage * to add cloned element to.
- */
-static void
-msim_msg_clone_element(gpointer data, gpointer user_data)
-{
-	MsimMessageElement *elem;
-	MsimMessage **new;
-	gpointer new_data;
-
-	GString *gs;
-	MsimMessage *dict;
-
-	elem = (MsimMessageElement *)data;
-	new = (MsimMessage **)user_data;
-
-	switch (elem->type) {
-		case MSIM_TYPE_BOOLEAN:
-		case MSIM_TYPE_INTEGER:
-			new_data = elem->data;
-			break;
-
-		case MSIM_TYPE_RAW:
-		case MSIM_TYPE_STRING:
-			new_data = g_strdup((gchar *)elem->data);
-			break;
-
-		case MSIM_TYPE_LIST:
-			new_data = (gpointer)msim_msg_list_copy((GList *)(elem->data));
-			break;
-
-		case MSIM_TYPE_BINARY:
-			gs = (GString *)elem->data;
-
-			new_data = g_string_new_len(gs->str, gs->len);
-			break;
-		case MSIM_TYPE_DICTIONARY:
-			dict = (MsimMessage *)elem->data;
-
-			new_data = msim_msg_clone(dict);
-			break;
-
-		default:
-			purple_debug_info("msim", "msim_msg_clone_element: unknown type %d\n", elem->type);
-			g_return_if_reached();
-	}
-
-	/* Append cloned data. Note that the 'name' field is a static string, so it
-	 * never needs to be copied nor freed. */
-	if (elem->dynamic_name)
-		*new = msim_msg_append_dynamic_name(*new, g_strdup(elem->name), elem->type, new_data);
-	else
-		*new = msim_msg_append(*new, elem->name, elem->type, new_data);
-}
-
-/**
- * Clone an existing MsimMessage.
- *
- * @return Cloned message; caller should free with msim_msg_free().
- */
-MsimMessage *
-msim_msg_clone(MsimMessage *old)
-{
-	MsimMessage *new;
-
-	if (old == NULL) {
-		return NULL;
-	}
-
-	new = msim_msg_new(FALSE);
-
-	g_list_foreach(old, msim_msg_clone_element, &new);
-
-	return new;
-}
-
-/**
- * Free the data of a message element.
- *
- * @param elem The MsimMessageElement *
- *
- * Note this only frees the element data; you may also want to free the
- * element itself with g_free() (see msim_msg_free_element()).
- */
-void
-msim_msg_free_element_data(MsimMessageElement *elem)
-{
-	switch (elem->type) {
-		case MSIM_TYPE_BOOLEAN:
-		case MSIM_TYPE_INTEGER:
-			/* Integer value stored in gpointer - no need to free(). */
-			break;
-
-		case MSIM_TYPE_RAW:
-		case MSIM_TYPE_STRING:
-			/* Always free strings - caller should have g_strdup()'d if
-			 * string was static or temporary and not to be freed. */
-			g_free(elem->data);
-			break;
-
-		case MSIM_TYPE_BINARY:
-			/* Free the GString itself and the binary data. */
-			g_string_free((GString *)elem->data, TRUE);
-			break;
-
-		case MSIM_TYPE_DICTIONARY:
-			msim_msg_free((MsimMessage *)elem->data);
-			break;
-
-		case MSIM_TYPE_LIST:
-			g_list_free((GList *)elem->data);
-			break;
-
-		default:
-			purple_debug_info("msim", "msim_msg_free_element_data: "
-					"not freeing unknown type %d\n", elem->type);
-			break;
-	}
-}
-
-/**
- * Free a GList * of MsimMessageElement *'s.
- */
-void
-msim_msg_list_free(GList *l)
-{
-
-	for (; l != NULL; l = g_list_next(l)) {
-		MsimMessageElement *elem;
-
-		elem = (MsimMessageElement *)l->data;
-
-		/* Note that name is almost never dynamically allocated elsewhere;
-		 * it is usually a static string, but not in lists. So cast it. */
-		g_free((gchar *)elem->name);
-		g_free(elem->data);
-		g_free(elem);
-	}
-	g_list_free(l);
-}
-
-/**
- * Free an individual message element.
- *
- * @param data MsimMessageElement * to free.
- * @param user_data Not used; required to match g_list_foreach() callback prototype.
- *
- * Frees both the element data and the element itself.
- * Also frees the name if dynamic_name is TRUE.
- */
-static void
-msim_msg_free_element(gpointer data, gpointer user_data)
-{
-	MsimMessageElement *elem;
-
-	elem = (MsimMessageElement *)data;
-
-	msim_msg_free_element_data(elem);
-
-	if (elem->dynamic_name)
-		/* Need to cast to remove const-ness, because
-		 * elem->name is almost always a constant, static
-		 * string, but not in this case. */
-		g_free((gchar *)elem->name);
-
-	g_free(elem);
-}
-
-/**
- * Free a complete message.
- */
-void
-msim_msg_free(MsimMessage *msg)
-{
-	if (!msg) {
-		/* already free as can be */
-		return;
-	}
-
-	g_list_foreach(msg, msim_msg_free_element, NULL);
-	g_list_free(msg);
-}
-
-/**
- * Pack an element into its protocol representation.
- *
- * @param data Pointer to an MsimMessageElement.
- * @param user_data Pointer to a gchar ** array of string items.
- *
- * Called by msim_msg_pack(). Will pack the MsimMessageElement into
- * a part of the protocol string and append it to the array. Caller
- * is responsible for creating array to correct dimensions, and
- * freeing each string element of the array added by this function.
- */
-static void
-msim_msg_pack_element(gpointer data, gpointer user_data)
-{
-	MsimMessageElement *elem;
-	gchar *string, *data_string;
-	gchar ***items;
-
-	elem = (MsimMessageElement *)data;
-	items = (gchar ***)user_data;
-
-	/* Exclude elements beginning with '_' from packed protocol messages. */
-	if (elem->name[0] == '_') {
-		return;
-	}
-
-	data_string = msim_msg_pack_element_data(elem);
-
-	switch (elem->type) {
-		/* These types are represented by key name/value pairs (converted above). */
-		case MSIM_TYPE_INTEGER:
-		case MSIM_TYPE_RAW:
-		case MSIM_TYPE_STRING:
-		case MSIM_TYPE_BINARY:
-		case MSIM_TYPE_DICTIONARY:
-		case MSIM_TYPE_LIST:
-			string = g_strconcat(elem->name, "\\", data_string, NULL);
-			break;
-
-		/* Boolean is represented by absence or presence of name. */
-		case MSIM_TYPE_BOOLEAN:
-			if (GPOINTER_TO_UINT(elem->data)) {
-				/* True - leave in, with blank value. */
-				string = g_strdup_printf("%s\\", elem->name);
-			} else {
-				/* False - leave out. */
-				string = g_strdup("");
-			}
-			break;
-
-		default:
-			g_free(data_string);
-			g_return_if_reached();
-			break;
-	}
-
-	g_free(data_string);
-
-	**items = string;
-	++(*items);
-}
-
-/**
- * Pack an element into its protcol representation inside a dictionary.
- *
- * See msim_msg_pack_element().
- */
-static void
-msim_msg_pack_element_dict(gpointer data, gpointer user_data)
-{
-	MsimMessageElement *elem;
-	gchar *string, *data_string, ***items;
-
-	elem = (MsimMessageElement *)data;
-	items = (gchar ***)user_data;
-
-	/* Exclude elements beginning with '_' from packed protocol messages. */
-	if (elem->name[0] == '_') {
-		return;
-	}
-
-	data_string = msim_msg_pack_element_data(elem);
-
-	g_return_if_fail(data_string != NULL);
-
-	switch (elem->type) {
-		/* These types are represented by key name/value pairs (converted above). */
-		case MSIM_TYPE_INTEGER:
-		case MSIM_TYPE_RAW:
-		case MSIM_TYPE_STRING:
-		case MSIM_TYPE_BINARY:
-		case MSIM_TYPE_DICTIONARY:
-		case MSIM_TYPE_LIST:
-		case MSIM_TYPE_BOOLEAN: /* Boolean is On or Off */
-			string = g_strconcat(elem->name, "=", data_string, NULL);
-			break;
-
-		default:
-			g_free(data_string);
-			g_return_if_fail(FALSE);
-			break;
-	}
-
-	g_free(data_string);
-
-	**items = string;
-	++(*items);
-}
-
-/**
- * Return a packed string of a message suitable for sending over the wire.
- *
- * @return A string. Caller must g_free().
- */
-gchar *
-msim_msg_pack(MsimMessage *msg)
-{
-	g_return_val_if_fail(msg != NULL, NULL);
-
-	return msim_msg_pack_using(msg, msim_msg_pack_element, "\\", "\\", "\\final\\");
-}
-
-/**
- * Return a packed string of a dictionary, suitable for embedding in MSIM_TYPE_DICTIONARY.
- *
- * @return A string; caller must g_free().
- */
-static gchar *
-msim_msg_pack_dict(MsimMessage *msg)
-{
-	g_return_val_if_fail(msg != NULL, NULL);
-
-	return msim_msg_pack_using(msg, msim_msg_pack_element_dict, "\034", "", "");
-}
-
-/**
- * Send an existing MsimMessage.
- */
-gboolean
-msim_msg_send(MsimSession *session, MsimMessage *msg)
-{
-	gchar *raw;
-	gboolean success;
-
-	raw = msim_msg_pack(msg);
-	g_return_val_if_fail(raw != NULL, FALSE);
-	success = msim_send_raw(session, raw);
-	g_free(raw);
-
-	return success;
-}
-
-/**
- * Return a message element data as a new string for a raw protocol message,
- * converting from other types (integer, etc.) if necessary.
- *
- * @return const gchar * The data as a string, or NULL. Caller must g_free().
- *
- * Returns a string suitable for inclusion in a raw protocol message, not necessarily
- * optimal for human consumption. For example, strings are escaped. Use
- * msim_msg_get_string() if you want a string, which in some cases is same as this.
- */
-gchar *
-msim_msg_pack_element_data(MsimMessageElement *elem)
-{
-	GString *gs;
-	GList *gl;
-
-	g_return_val_if_fail(elem != NULL, NULL);
-
-	switch (elem->type) {
-		case MSIM_TYPE_INTEGER:
-			return g_strdup_printf("%d", GPOINTER_TO_UINT(elem->data));
-
-		case MSIM_TYPE_RAW:
-			/* Not un-escaped - this is a raw element, already escaped if necessary. */
-			return (gchar *)g_strdup((gchar *)elem->data);
-
-		case MSIM_TYPE_STRING:
-			/* Strings get escaped. msim_escape() creates a new string. */
-			g_return_val_if_fail(elem->data != NULL, NULL);
-			return elem->data ? msim_escape((gchar *)elem->data) :
-				g_strdup("(NULL)");
-
-		case MSIM_TYPE_BINARY:
-			gs = (GString *)elem->data;
-			/* Do not escape! */
-			return purple_base64_encode((guchar *)gs->str, gs->len);
-
-		case MSIM_TYPE_BOOLEAN:
-			/* Not used by messages in the wire protocol * -- see msim_msg_pack_element.
-			 * Only used by dictionaries, see msim_msg_pack_element_dict. */
-			return elem->data ? g_strdup("On") : g_strdup("Off");
-
-		case MSIM_TYPE_DICTIONARY:
-			return msim_msg_pack_dict((MsimMessage *)elem->data);
-
-		case MSIM_TYPE_LIST:
-			/* Pack using a|b|c|d|... */
-			gs = g_string_new("");
-
-			for (gl = (GList *)elem->data; gl != NULL; gl = g_list_next(gl)) {
-				g_string_append_printf(gs, "%s", (gchar*)(gl->data));
-
-				/* All but last element is separated by a bar. */
-				if (g_list_next(gl))
-					g_string_append(gs, "|");
-			}
-
-			return g_string_free(gs, FALSE);
-
-		default:
-			purple_debug_info("msim", "field %s, unknown type %d\n",
-					elem->name ? elem->name : "(NULL)",
-					elem->type);
-			return NULL;
-	}
-}
-
-/**
- * Send a message to the server, whose contents is specified using
- * variable arguments.
- *
- * @param session
- * @param ... A sequence of gchar* key/type/value triplets, terminated with NULL.
- *
- * This function exists for coding convenience: it allows a message to be created
- * and sent in one line of code. Internally it calls msim_msg_send().
- *
- * IMPORTANT: See msim_msg_append() documentation for details on element types.
- *
- */
-gboolean
-msim_send(MsimSession *session, ...)
-{
-	gboolean success;
-	MsimMessage *msg;
-	va_list argp;
-
-	va_start(argp, session);
-	msg = msim_msg_new_v(NULL, argp);
-	va_end(argp);
-
-	/* Actually send the message. */
-	success = msim_msg_send(session, msg);
-
-	/* Cleanup. */
-	msim_msg_free(msg);
-
-	return success;
-}
-
-/**
- * Print a human-readable string of the message to Purple's debug log.
- *
- * @param fmt_string A static string, in which '%s' will be replaced.
- */
-void
-msim_msg_dump(const gchar *fmt_string, MsimMessage *msg)
-{
-	gchar *debug_str;
-
-	g_return_if_fail(fmt_string != NULL);
-
-	debug_str = msim_msg_dump_to_str(msg);
-
-	g_return_if_fail(debug_str != NULL);
-
-	purple_debug_info("msim", fmt_string, debug_str);
-
-	g_free(debug_str);
-}
-
-/**
- * Parse a raw protocol message string into a MsimMessage *.
- *
- * @param raw The raw message string to parse, will be g_free()'d.
- *
- * @return MsimMessage *. Caller should msim_msg_free() when done.
- */
-MsimMessage *
-msim_parse(const gchar *raw)
-{
-	MsimMessage *msg;
-	gchar *token;
-	gchar **tokens;
-	gchar *key;
-	gchar *value;
-	int i;
-
-	g_return_val_if_fail(raw != NULL, NULL);
-
-	purple_debug_info("msim", "msim_parse: got <%s>\n", raw);
-
-	key = NULL;
-
-	/* All messages begin with a \. */
-	if (raw[0] != '\\' || raw[1] == 0) {
-		purple_debug_info("msim", "msim_parse: incomplete/bad string, "
-				"missing initial backslash: <%s>\n", raw);
-		/* XXX: Should we try to recover, and read to first backslash? */
-
-		return NULL;
-	}
-
-	msg = msim_msg_new(FALSE);
-
-	for (tokens = g_strsplit(raw + 1, "\\", 0), i = 0;
-			(token = tokens[i]);
-			i++) {
-#ifdef MSIM_DEBUG_PARSE
-		purple_debug_info("msim", "tok=<%s>, i%2=%d\n", token, i % 2);
-#endif
-		if (i % 2) {
-			/* Odd-numbered ordinal is a value. */
-
-			value = token;
-
-			/* Incoming protocol messages get tagged as MSIM_TYPE_RAW, which
-			 * represents an untyped piece of data. msim_msg_get_* will
-			 * convert to appropriate types for caller, and handle unescaping if needed. */
-			msg = msim_msg_append_dynamic_name(msg, g_strdup(key), MSIM_TYPE_RAW, g_strdup(value));
-#ifdef MSIM_DEBUG_PARSE
-			purple_debug_info("msim", "insert string: |%s|=|%s|\n", key, value);
-#endif
-		} else {
-			/* Even numbered indexes are key names. */
-			key = token;
-		}
-	}
-	g_strfreev(tokens);
-
-	return msg;
-}
-
-/**
- * Return the first MsimMessageElement * with given name in the MsimMessage *.
- *
- * @param name Name to search for.
- *
- * @return MsimMessageElement * matching name, or NULL.
- *
- * Note: useful fields of MsimMessageElement are 'data' and 'type', which
- * you can access directly. But it is often more convenient to use
- * another msim_msg_get_* that converts the data to what type you want.
- */
-MsimMessageElement *
-msim_msg_get(const MsimMessage *msg, const gchar *name)
-{
-	GList *node;
-
-	node = msim_msg_get_node(msg, name);
-	if (node) {
-		return (MsimMessageElement *)node->data;
-	} else {
-		return NULL;
-	}
-}
-
-gchar *
-msim_msg_get_string_from_element(MsimMessageElement *elem)
-{
-	g_return_val_if_fail(elem != NULL, NULL);
-	switch (elem->type) {
-		case MSIM_TYPE_INTEGER:
-			return g_strdup_printf("%d", GPOINTER_TO_UINT(elem->data));
-
-		case MSIM_TYPE_RAW:
-			/* Raw element from incoming message - if its a string, it'll
-			 * be escaped. */
-			return msim_unescape((gchar *)elem->data);
-
-		case MSIM_TYPE_STRING:
-			/* Already unescaped. */
-			return g_strdup((gchar *)elem->data);
-
-		default:
-			purple_debug_info("msim", "msim_msg_get_string_element: type %d unknown, name %s\n",
-					elem->type, elem->name ? elem->name : "(NULL)");
-			return NULL;
-	}
-}
-
-/**
- * Return the data of an element of a given name, as a string.
- *
- * @param name Name of element.
- *
- * @return gchar * The data as a string, or NULL if not found.
- *     Caller must g_free().
- *
- * Note that msim_msg_pack_element_data() is similar, but returns a string
- * for inclusion into a raw protocol string (escaped and everything).
- * This function unescapes the string for you, if needed.
- */
-gchar *
-msim_msg_get_string(const MsimMessage *msg, const gchar *name)
-{
-	MsimMessageElement *elem;
-
-	elem = msim_msg_get(msg, name);
-	if (!elem) {
-		return NULL;
-	}
-
-	return msim_msg_get_string_from_element(elem);
-}
-
-/**
- * Parse a |-separated string into a new GList. Free with msim_msg_list_free().
- */
-static GList *
-msim_msg_list_parse(const gchar *raw)
-{
-	gchar **array;
-	GList *list;
-	guint i;
-
-	array = g_strsplit(raw, "|", 0);
-	list = NULL;
-
-	/* TODO: escape/unescape /3 <-> | within list elements */
-
-	for (i = 0; array[i] != NULL; ++i) {
-		MsimMessageElement *elem;
-
-		/* Freed in msim_msg_list_free() */
-		elem = g_new0(MsimMessageElement, 1);
-
-		/* Give the element a name for debugging purposes.
-		 * Not supposed to be looked up by this name; instead,
-		 * lookup the elements by indexing the array. */
-		elem->name = g_strdup_printf("(list item #%d)", i);
-		elem->type = MSIM_TYPE_RAW;
-		elem->data = g_strdup(array[i]);
-
-		list = g_list_append(list, elem);
-	}
-
-	g_strfreev(array);
-
-	return list;
-}
-
-static GList *
-msim_msg_get_list_from_element(MsimMessageElement *elem)
-{
-	g_return_val_if_fail(elem != NULL, NULL);
-	switch (elem->type) {
-		case MSIM_TYPE_LIST:
-			return msim_msg_list_copy((GList *)elem->data);
-
-		case MSIM_TYPE_RAW:
-			return msim_msg_list_parse((gchar *)elem->data);
-
-		default:
-			purple_debug_info("msim_msg_get_list", "type %d unknown, name %s\n",
-					elem->type, elem->name ? elem->name : "(NULL)");
-			return NULL;
-	}
-}
-
-/**
- * Return an element as a new list. Caller frees with msim_msg_list_free().
- */
-GList *
-msim_msg_get_list(const MsimMessage *msg, const gchar *name)
-{
-	MsimMessageElement *elem;
-
-	elem = msim_msg_get(msg, name);
-	if (!elem) {
-		return NULL;
-	}
-
-	return msim_msg_get_list_from_element(elem);
-}
-
-/**
- * Parse a \x1c-separated "dictionary" of key=value pairs into a hash table.
- *
- * @param raw The text of the dictionary to parse. Often the
- *                 value for the 'body' field.
- *
- * @return A new MsimMessage *. Must msim_msg_free() when done.
- */
-static MsimMessage *
-msim_msg_dictionary_parse(const gchar *raw)
-{
-	MsimMessage *dict;
-	gchar *item;
-	gchar **items;
-	gchar **elements;
-	guint i;
-
-	g_return_val_if_fail(raw != NULL, NULL);
-
-	dict = msim_msg_new(NULL);
-
-	for (items = g_strsplit(raw, "\x1c", 0), i = 0;
-		(item = items[i]);
-		i++) {
-		gchar *key, *value;
-
-		elements = g_strsplit(item, "=", 2);
-
-		key = elements[0];
-		if (!key) {
-			purple_debug_info("msim", "msim_msg_dictionary_parse(%s): null key\n",
-					raw);
-			g_strfreev(elements);
-			break;
-		}
-
-		value = elements[1];
-		if (!value) {
-			purple_debug_info("msim", "msim_msg_dictionary_prase(%s): null value\n",
-					raw);
-			g_strfreev(elements);
-			break;
-		}
-
-#ifdef MSIM_DEBUG_PARSE
-		purple_debug_info("msim_msg_dictionary_parse","-- %s: %s\n", key ? key : "(NULL)",
-				value ? value : "(NULL)");
-#endif
-		/* Append with _dynamic_name since g_strdup(key) is dynamic, and
-		 * needs to be freed when the message is destroyed. It isn't static as usual. */
-		dict = msim_msg_append_dynamic_name(dict, g_strdup(key), MSIM_TYPE_RAW, g_strdup(value));
-
-		g_strfreev(elements);
-	}
-
-	g_strfreev(items);
-
-	return dict;
-}
-
-static MsimMessage *
-msim_msg_get_dictionary_from_element(MsimMessageElement *elem)
-{
-	g_return_val_if_fail(elem != NULL, NULL);
-	switch (elem->type) {
-		case MSIM_TYPE_DICTIONARY:
-			return msim_msg_clone((MsimMessage *)elem->data);
-
-		case MSIM_TYPE_RAW:
-			return msim_msg_dictionary_parse(elem->data);
-
-		default:
-			purple_debug_info("msim_msg_get_dictionary", "type %d unknown, name %s\n",
-					elem->type, elem->name ? elem->name : "(NULL)");
-			return NULL;
-	}
-}
-
-/**
- * Return an element as a new dictionary. Caller frees with msim_msg_free().
- */
-MsimMessage *
-msim_msg_get_dictionary(const MsimMessage *msg, const gchar *name)
-{
-	MsimMessageElement *elem;
-
-	elem = msim_msg_get(msg, name);
-	if (!elem) {
-		return NULL;
-	}
-
-	return msim_msg_get_dictionary_from_element(elem);
-}
-
-guint
-msim_msg_get_integer_from_element(MsimMessageElement *elem)
-{
-	g_return_val_if_fail(elem != NULL, 0);
-	switch (elem->type) {
-		case MSIM_TYPE_INTEGER:
-			return GPOINTER_TO_UINT(elem->data);
-
-		case MSIM_TYPE_RAW:
-		case MSIM_TYPE_STRING:
-			/* TODO: find out if we need larger integers */
-			return (guint)atoi((gchar *)elem->data);
-
-		default:
-			return 0;
-	}
-}
-
-/**
- * Return the data of an element of a given name, as an unsigned integer.
- *
- * @param name Name of element.
- *
- * @return guint Numeric representation of data, or 0 if could not be converted / not found.
- *
- * Useful to obtain an element's data if you know it should be an integer,
- * even if it is not stored as an MSIM_TYPE_INTEGER. MSIM_TYPE_STRING will
- * be converted handled correctly, for example.
- */
-guint
-msim_msg_get_integer(const MsimMessage *msg, const gchar *name)
-{
-	MsimMessageElement *elem;
-
-	elem = msim_msg_get(msg, name);
-
-	if (!elem) {
-		return 0;
-	}
-
-	return msim_msg_get_integer_from_element(elem);
-}
-
-static gboolean
-msim_msg_get_binary_from_element(MsimMessageElement *elem, gchar **binary_data, gsize *binary_length)
-{
-	GString *gs;
-
-	g_return_val_if_fail(elem != NULL, FALSE);
-
-	switch (elem->type) {
-		case MSIM_TYPE_RAW:
-			 /* Incoming messages are tagged with MSIM_TYPE_RAW, and
-			 * converted appropriately. They can still be "strings", just they won't
-			 * be tagged as MSIM_TYPE_STRING (as MSIM_TYPE_STRING is intended to be used
-			 * by msimprpl code for things like instant messages - stuff that should be
-			 * escaped if needed). DWIM.
-			 */
-
-			/* Previously, incoming messages were stored as MSIM_TYPE_STRING.
-			 * This was fine for integers and strings, since they can easily be
-			 * converted in msim_get_*, as desirable. However, it does not work
-			 * well for binary strings. Consider:
-			 *
-			 * If incoming base64'd elements were tagged as MSIM_TYPE_STRING.
-			 * msim_msg_get_binary() sees MSIM_TYPE_STRING, base64 decodes, returns.
-			 * everything is fine.
-			 * But then, msim_send() is called on the incoming message, which has
-			 * a base64'd MSIM_TYPE_STRING that really is encoded binary. The values
-			 * will be escaped since strings are escaped, and / becomes /2; no good.
-			 *
-			 */
-			*binary_data = (gchar *)purple_base64_decode((const gchar *)elem->data, binary_length);
-			return ((*binary_data) != NULL);
-
-		case MSIM_TYPE_BINARY:
-			gs = (GString *)elem->data;
-
-			/* Duplicate data, so caller can g_free() it. */
-			*binary_data = g_memdup(gs->str, gs->len);
-			*binary_length = gs->len;
-
-			return TRUE;
-
-
-			/* Rejected because if it isn't already a GString, have to g_new0 it and
-			 * then caller has to ALSO free the GString!
-			 *
-			 * return (GString *)elem->data; */
-
-		default:
-			purple_debug_info("msim", "msim_msg_get_binary: unhandled type %d for key %s\n",
-					elem->type, elem->name ? elem->name : "(NULL)");
-			return FALSE;
-	}
-}
-
-/**
- * Return the data of an element of a given name, as a binary GString.
- *
- * @param binary_data A pointer to a new pointer, which will be filled in with the binary data. CALLER MUST g_free().
- *
- * @param binary_length A pointer to an integer, which will be set to the binary data length.
- *
- * @return TRUE if successful, FALSE if not.
- */
-gboolean
-msim_msg_get_binary(const MsimMessage *msg, const gchar *name,
-		gchar **binary_data, gsize *binary_length)
-{
-	MsimMessageElement *elem;
-
-	elem = msim_msg_get(msg, name);
-	if (!elem) {
-		return FALSE;
-	}
-
-	return msim_msg_get_binary_from_element(elem, binary_data, binary_length);
-}
deleted file mode 100644
--- a/libpurple/protocols/myspace/message.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/** MySpaceIM protocol messages
- *
- * \author Jeff Connelly
- *
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- *
- * 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 _MYSPACE_MESSAGE_H
-#define _MYSPACE_MESSAGE_H
-
-#include <glib.h>
-
-#define MsimMessage GList               /* #define instead of typedef to avoid casting */
-typedef gchar MsimMessageType;
-typedef struct _MsimMessageElement MsimMessageElement;
-
-#include "session.h"
-
-/* Types */
-struct _MsimMessageElement
-{
-	const gchar *name;              /**< Textual name of element. */
-	gboolean dynamic_name;          /**< TRUE if 'name' is a dynamic string to be freed, not static. */
-	guint type;                     /**< MSIM_TYPE_* code. */
-	gpointer data;                  /**< Pointer to data, or GUINT_TO_POINTER for int/bool. */
-};
-
-#define msim_msg_get_next_element_node(msg)    ((MsimMessage *)(msg->next))
-
-/* Protocol field types */
-#define MSIM_TYPE_RAW            '-'
-#define MSIM_TYPE_INTEGER        'i'
-#define MSIM_TYPE_STRING         's'
-#define MSIM_TYPE_BINARY         'b'
-#define MSIM_TYPE_BOOLEAN        'f'
-#define MSIM_TYPE_DICTIONARY     'd'
-#define MSIM_TYPE_LIST           'l'
-
-gchar *msim_escape(const gchar *msg);
-gchar *msim_unescape(const gchar *msg);
-
-MsimMessage *msim_msg_new(gchar *first_key, ...);
-/* No sentinel attribute, because can leave off varargs if not_empty is FALSE. */
-
-MsimMessage *msim_msg_clone(MsimMessage *old);
-void msim_msg_free_element_data(MsimMessageElement *elem);
-void msim_msg_free(MsimMessage *msg);
-MsimMessage *msim_msg_append(MsimMessage *msg, const gchar *name, MsimMessageType type, gpointer data);
-MsimMessage *msim_msg_insert_before(MsimMessage *msg, const gchar *name_before, const gchar *name, MsimMessageType type, gpointer data);
-gchar *msim_msg_pack_element_data(MsimMessageElement *elem);
-void msim_msg_dump(const char *fmt_string, MsimMessage *msg);
-gchar *msim_msg_pack(MsimMessage *msg);
-
-void msim_msg_list_free(GList *l);
-
-/* Based on http://permalink.gmane.org/gmane.comp.parsers.sparse/695
- * Define macros for useful gcc attributes. */
-#ifdef __GNUC__
-#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
-#define FORMAT_ATTR(pos) __attribute__ ((__format__ (__printf__, pos, pos+1)))
-#define NORETURN_ATTR __attribute__ ((__noreturn__))
-/* __sentinel__ attribute was introduced in gcc 3.5 */
-#if (GCC_VERSION >= 3005)
-	#define SENTINEL_ATTR __attribute__ ((__sentinel__(0)))
-#else
-	#define SENTINEL_ATTR
-#endif /* gcc >= 3.5 */
-#else
-	#define FORMAT_ATTR(pos)
-	#define NORETURN_ATTR
-	#define SENTINEL_ATTR
-#endif
-
-/* Cause gcc to emit "a missing sentinel in function call" if forgot
- * to write NULL as last, terminating parameter. */
-gboolean msim_send(struct _MsimSession *session, ...) SENTINEL_ATTR;
-
-gboolean msim_msg_send(struct _MsimSession *session, MsimMessage *msg);
-
-MsimMessage *msim_parse(const gchar *raw);
-
-MsimMessageElement *msim_msg_get(const MsimMessage *msg, const gchar *name);
-
-/* Retrieve data by name */
-gchar *msim_msg_get_string(const MsimMessage *msg, const gchar *name);
-GList *msim_msg_get_list(const MsimMessage *msg, const gchar *name);
-MsimMessage *msim_msg_get_dictionary(const MsimMessage *msg, const gchar *name);
-guint msim_msg_get_integer(const MsimMessage *msg, const gchar *name);
-gboolean msim_msg_get_binary(const MsimMessage *msg, const gchar *name, gchar **binary_data, gsize *binary_length);
-
-/* Retrieve data by element (MsimMessageElement *), returned from msim_msg_get() */
-gchar *msim_msg_get_string_from_element(MsimMessageElement *elem);
-guint msim_msg_get_integer_from_element(MsimMessageElement *elem);
-
-#endif /* _MYSPACE_MESSAGE_H */
deleted file mode 100644
--- a/libpurple/protocols/myspace/moz.build
+++ /dev/null
@@ -1,17 +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 += [
-    'markup.c',
-    'message.c',
-    'myspace.c',
-    'session.c',
-    'user.c',
-    'zap.c',
-]
-
-protocol = 'myspace'
-
-include('../prpl.py')
deleted file mode 100644
--- a/libpurple/protocols/myspace/myspace.c
+++ /dev/null
@@ -1,3667 +0,0 @@
-/**
- * MySpaceIM Protocol Plugin
- *
- * \author Jeff Connelly
- *
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- *
- * Based on Purple's "C Plugin HOWTO" hello world example.
- *
- * Code also drawn from mockprpl:
- *  http://snarfed.org/space/purple+mock+protocol+plugin
- *  Copyright (C) 2004-2007, Ryan Barrett <mockprpl@ryanb.org>
- *
- * and some constructs also based on existing Purple plugins, which are:
- *   Copyright (C) 2003, Robbert Haarman <purple@inglorion.net>
- *   Copyright (C) 2003, Ethan Blanton <eblanton@cs.purdue.edu>
- *   Copyright (C) 2000-2003, Rob Flynn <rob@tgflinux.com>
- *   Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
- *
- * 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 PURPLE_PLUGIN
-
-#include "myspace.h"
-
-#include "privacy.h"
-
-static void msim_set_status(PurpleAccount *account, PurpleStatus *status);
-static void msim_set_idle(PurpleConnection *gc, int time);
-
-/**
- * Perform actual postprocessing on a message, adding userid as specified.
- *
- * @param msg The message to postprocess.
- * @param uid_before Name of field where to insert new field before, or NULL for end.
- * @param uid_field_name Name of field to add uid to.
- * @param uid The userid to insert.
- *
- * If the field named by uid_field_name already exists, then its string contents will
- * be used for the field, except "<uid>" will be replaced by the userid.
- *
- * If the field named by uid_field_name does not exist, it will be added before the
- * field named by uid_before, as an integer, with the userid.
- *
- * Does not handle sending, or scheduling userid lookup. For that, see msim_postprocess_outgoing().
- */
-static MsimMessage *
-msim_do_postprocessing(MsimMessage *msg, const gchar *uid_before,
-		const gchar *uid_field_name, guint uid)
-{
-	MsimMessageElement *elem;
-
-	/* First, check - if the field already exists, replace <uid> within it */
-	if ((elem = msim_msg_get(msg, uid_field_name)) != NULL) {
-		gchar *fmt_string;
-		gchar *uid_str, *new_str;
-
-		/* Get the packed element, flattening it. This allows <uid> to be
-		 * replaced within nested data structures, since the replacement is done
-		 * on the linear, packed data, not on a complicated data structure.
-		 *
-		 * For example, if the field was originally a dictionary or a list, you
-		 * would have to iterate over all the items in it to see what needs to
-		 * be replaced. But by packing it first, the <uid> marker is easily replaced
-		 * just by a string replacement.
-		 */
-		fmt_string = msim_msg_pack_element_data(elem);
-
-		uid_str = g_strdup_printf("%d", uid);
-		new_str = purple_strreplace(fmt_string, "<uid>", uid_str);
-		g_free(uid_str);
-		g_free(fmt_string);
-
-		/* Free the old element data */
-		msim_msg_free_element_data(elem->data);
-
-		/* Replace it with our new data */
-		elem->data = new_str;
-		elem->type = MSIM_TYPE_RAW;
-
-	} else {
-		/* Otherwise, insert new field into outgoing message. */
-		msg = msim_msg_insert_before(msg, uid_before, uid_field_name, MSIM_TYPE_INTEGER, GUINT_TO_POINTER(uid));
-	}
-
-	return msg;
-}
-
-/**
- * Callback for msim_postprocess_outgoing() to add a userid to a message, and send it (once receiving userid).
- *
- * @param session
- * @param userinfo The user information reply message, containing the user ID
- * @param data The message to postprocess and send.
- *
- * The data message should contain these fields:
- *
- *  _uid_field_name: string, name of field to add with userid from userinfo message
- *  _uid_before: string, name of field before field to insert, or NULL for end
- */
-static void
-msim_postprocess_outgoing_cb(MsimSession *session, const MsimMessage *userinfo,
-		gpointer data)
-{
-	gchar *uid_field_name, *uid_before, *username;
-	guint uid;
-	MsimMessage *msg, *body;
-
-	msg = (MsimMessage *)data;
-
-	/* Obtain userid from userinfo message. */
-	body = msim_msg_get_dictionary(userinfo, "body");
-	g_return_if_fail(body != NULL);
-
-	uid = msim_msg_get_integer(body, "UserID");
-	msim_msg_free(body);
-
-	username = msim_msg_get_string(msg, "_username");
-
-	if (!uid) {
-		gchar *msg;
-
-		msg = g_strdup_printf(_("No such user: %s"), username);
-		if (!purple_conv_present_error(username, session->account, msg)) {
-			purple_notify_error(NULL, NULL, _("User lookup"), msg);
-		}
-
-		g_free(msg);
-		g_free(username);
-		/* TODO: free
-		 * msim_msg_free(msg);
-		 */
-		return;
-	}
-
-	uid_field_name = msim_msg_get_string(msg, "_uid_field_name");
-	uid_before = msim_msg_get_string(msg, "_uid_before");
-
-	msg = msim_do_postprocessing(msg, uid_before, uid_field_name, uid);
-
-	/* Send */
-	if (!msim_msg_send(session, msg)) {
-		msim_msg_dump("msim_postprocess_outgoing_cb: sending failed for message: %s\n", msg);
-	}
-
-
-	/* Free field names AFTER sending message, because MsimMessage does NOT copy
-	 * field names - instead, treats them as static strings (which they usually are).
-	 */
-	g_free(uid_field_name);
-	g_free(uid_before);
-	g_free(username);
-	/* TODO: free
-	 * msim_msg_free(msg);
-	 */
-}
-
-/**
- * Postprocess and send a message.
- *
- * @param session
- * @param msg Message to postprocess. Will NOT be freed.
- * @param username Username to resolve. Assumed to be a static string (will not be freed or copied).
- * @param uid_field_name Name of new field to add, containing uid of username. Static string.
- * @param uid_before Name of existing field to insert username field before. Static string.
- *
- * @return TRUE if successful.
- */
-static gboolean
-msim_postprocess_outgoing(MsimSession *session, MsimMessage *msg,
-		const gchar *username, const gchar *uid_field_name,
-		const gchar *uid_before)
-{
-	PurpleBuddy *buddy;
-	guint uid;
-	gboolean rc;
-
-	g_return_val_if_fail(msg != NULL, FALSE);
-
-	/* Store information for msim_postprocess_outgoing_cb(). */
-	msg = msim_msg_append(msg, "_username", MSIM_TYPE_STRING, g_strdup(username));
-	msg = msim_msg_append(msg, "_uid_field_name", MSIM_TYPE_STRING, g_strdup(uid_field_name));
-	msg = msim_msg_append(msg, "_uid_before", MSIM_TYPE_STRING, g_strdup(uid_before));
-
-	/* First, try the most obvious. If numeric userid is given, use that directly. */
-	if (msim_is_userid(username)) {
-		uid = atol(username);
-	} else {
-		/* Next, see if on buddy list and know uid. */
-		buddy = purple_find_buddy(session->account, username);
-		if (buddy) {
-			uid = purple_blist_node_get_int(PURPLE_BLIST_NODE(buddy), "UserID");
-		} else {
-			uid = 0;
-		}
-
-		if (!buddy || !uid) {
-			/* Don't have uid offhand - need to ask for it, and wait until hear back before sending. */
-			purple_debug_info("msim", ">>> msim_postprocess_outgoing: couldn't find username %s in blist\n",
-					username ? username : "(NULL)");
-			msim_lookup_user(session, username, msim_postprocess_outgoing_cb, msim_msg_clone(msg));
-			return TRUE;       /* not sure of status yet - haven't sent! */
-		}
-	}
-
-	/* Already have uid, postprocess and send msg immediately. */
-	purple_debug_info("msim", "msim_postprocess_outgoing: found username %s has uid %d\n",
-			username ? username : "(NULL)", uid);
-
-	msg = msim_do_postprocessing(msg, uid_before, uid_field_name, uid);
-
-	rc = msim_msg_send(session, msg);
-
-	/* TODO: free
-	 * msim_msg_free(msg);
-	 */
-
-	return rc;
-}
-
-/**
- * Send a buddy message of a given type.
- *
- * @param session
- * @param who Username to send message to.
- * @param text Message text to send. Not freed; will be copied.
- * @param type A MSIM_BM_* constant.
- *
- * @return TRUE if success, FALSE if fail.
- *
- * Buddy messages ('bm') include instant messages, action messages, status messages, etc.
- */
-gboolean
-msim_send_bm(MsimSession *session, const gchar *who, const gchar *text,
-		int type)
-{
-	gboolean rc;
-	MsimMessage *msg;
-	const gchar *from_username;
-
-	g_return_val_if_fail(who != NULL, FALSE);
-	g_return_val_if_fail(text != NULL, FALSE);
-
-	from_username = session->account->username;
-
-	g_return_val_if_fail(from_username != NULL, FALSE);
-
-	purple_debug_info("msim", "sending %d message from %s to %s: %s\n",
-				  type, from_username, who, text);
-
-	msg = msim_msg_new(
-			"bm", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(type),
-			"sesskey", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(session->sesskey),
-			/* 't' will be inserted here */
-			"cv", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(MSIM_CLIENT_VERSION),
-			"msg", MSIM_TYPE_STRING, g_strdup(text),
-			NULL);
-
-	rc = msim_postprocess_outgoing(session, msg, who, "t", "cv");
-
-	msim_msg_free(msg);
-
-	return rc;
-}
-
-/**
- * Lookup a username by userid, from buddy list.
- *
- * @param wanted_uid
- *
- * @return Username of wanted_uid, if on blist, or NULL.
- *         This is a static string, so don't free it. Copy it if needed.
- *
- */
-static const gchar *
-msim_uid2username_from_blist(PurpleAccount *account, guint wanted_uid)
-{
-	GSList *buddies, *cur;
-	const gchar *ret;
-
-	buddies = purple_find_buddies(account, NULL);
-
-	if (!buddies)
-	{
-		purple_debug_info("msim", "msim_uid2username_from_blist: no buddies?\n");
-		return NULL;
-	}
-
-	ret = NULL;
-
-	for (cur = buddies; cur != NULL; cur = g_slist_next(cur))
-	{
-		PurpleBuddy *buddy;
-		guint uid;
-		const gchar *name;
-
-		/* See finch/gnthistory.c */
-		buddy = cur->data;
-
-		uid = purple_blist_node_get_int(PURPLE_BLIST_NODE(buddy), "UserID");
-		name = purple_buddy_get_name(buddy);
-
-		if (uid == wanted_uid)
-		{
-			ret = name;
-			break;
-		}
-	}
-
-	g_slist_free(buddies);
-	return ret;
-}
-
-/**
- * Setup a callback, to be called when a reply is received with the returned rid.
- *
- * @param cb The callback, an MSIM_USER_LOOKUP_CB.
- * @param data Arbitrary user data to be passed to callback (probably an MsimMessage *).
- *
- * @return The request/reply ID, used to link replies with requests, or -1.
- *          Put the rid in your request, 'rid' field.
- *
- * TODO: Make more generic and more specific:
- * 1) MSIM_USER_LOOKUP_CB - make it for PERSIST_REPLY, not just user lookup
- * 2) data - make it an MsimMessage?
- */
-guint
-msim_new_reply_callback(MsimSession *session, MSIM_USER_LOOKUP_CB cb,
-		gpointer data)
-{
-	guint rid;
-
-	rid = session->next_rid++;
-
-	g_hash_table_insert(session->user_lookup_cb, GUINT_TO_POINTER(rid), cb);
-	g_hash_table_insert(session->user_lookup_cb_data, GUINT_TO_POINTER(rid), data);
-
-	return rid;
-}
-
-/**
- * Return the icon name for a buddy and account.
- *
- * @param acct The account to find the icon for, or NULL for protocol icon.
- * @param buddy The buddy to find the icon for, or NULL for the account icon.
- *
- * @return The base icon name string.
- */
-static const gchar *
-msim_list_icon(PurpleAccount *acct, PurpleBuddy *buddy)
-{
-	/* Use a MySpace icon submitted by hbons at
-	 * http://developer.pidgin.im/wiki/MySpaceIM. */
-	return "myspace";
-}
-
-/**
- * Obtain the status text for a buddy.
- *
- * @param buddy The buddy to obtain status text for.
- *
- * @return Status text, or NULL if error. Caller g_free()'s.
- */
-static char *
-msim_status_text(PurpleBuddy *buddy)
-{
-	MsimUser *user;
-	const gchar *display_name = NULL, *headline = NULL;
-	PurpleAccount *account;
-
-	g_return_val_if_fail(buddy != NULL, NULL);
-
-	account = purple_buddy_get_account(buddy);
-
-	user = msim_get_user_from_buddy(buddy, FALSE);
-	if (user != NULL) {
-		/* Retrieve display name and/or headline, depending on user preference. */
-		if (purple_account_get_bool(account, "show_headline", TRUE)) {
-			headline = user->headline;
-		}
-
-		if (purple_account_get_bool(account, "show_display_name", FALSE)) {
-			display_name = user->display_name;
-		}
-	}
-
-	/* Return appropriate combination of display name and/or headline, or neither. */
-
-	if (display_name && headline) {
-		return g_strconcat(display_name, " ", headline, NULL);
-	} else if (display_name) {
-		return g_strdup(display_name);
-	} else if (headline) {
-		return g_strdup(headline);
-	}
-
-	return NULL;
-}
-
-/**
- * Obtain the tooltip text for a buddy.
- *
- * @param buddy Buddy to obtain tooltip text on.
- * @param user_info Variable modified to have the tooltip text.
- * @param full TRUE if should obtain full tooltip text.
- */
-static void
-msim_tooltip_text(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info,
-		gboolean full)
-{
-	MsimUser *user;
-
-	g_return_if_fail(buddy != NULL);
-	g_return_if_fail(user_info != NULL);
-
-	user = msim_get_user_from_buddy(buddy, TRUE);
-
-	if (PURPLE_BUDDY_IS_ONLINE(buddy)) {
-		MsimSession *session;
-		PurpleAccount *account = purple_buddy_get_account(buddy);
-		PurpleConnection *gc = purple_account_get_connection(account);
-
-		session = (MsimSession *)gc->proto_data;
-
-		/* TODO: if (full), do something different? */
-
-		/* TODO: request information? have to figure out how to do
-		 * the asynchronous lookup like oscar does (tooltip shows
-		 * 'retrieving...' if not yet available, then changes when it is).
-		 *
-		 * Right now, only show what we have on hand.
-		 */
-
-		/* Show abbreviated user info. */
-		msim_append_user_info(session, user_info, user, FALSE);
-	}
-}
-
-/**
- * Get possible user status types. Based on mockprpl.
- *
- * @return GList of status types.
- */
-static GList *
-msim_status_types(PurpleAccount *acct)
-{
-	GList *types;
-	PurpleStatusType *status;
-
-	purple_debug_info("myspace", "returning status types\n");
-
-	types = NULL;
-
-	/* Statuses are almost all the same. Define a macro to reduce code repetition. */
-#define _MSIM_ADD_NEW_STATUS(prim) status =                         \
-	purple_status_type_new_with_attrs(                          \
-	prim,   /* PurpleStatusPrimitive */                         \
-	NULL,   /* id - use default */                              \
-	NULL,   /* name - use default */                            \
-	TRUE,   /* saveable */                                      \
-	TRUE,   /* user_settable */                                 \
-	FALSE,  /* not independent */                               \
-	                                                            \
-	/* Attributes - each status can have a message. */          \
-	"message",                                                  \
-	_("Message"),                                               \
-	purple_value_new(PURPLE_TYPE_STRING),                       \
-	NULL);                                                      \
-	                                                            \
-	                                                            \
-	types = g_list_append(types, status)
-
-
-	_MSIM_ADD_NEW_STATUS(PURPLE_STATUS_AVAILABLE);
-	_MSIM_ADD_NEW_STATUS(PURPLE_STATUS_AWAY);
-	_MSIM_ADD_NEW_STATUS(PURPLE_STATUS_OFFLINE);
-	_MSIM_ADD_NEW_STATUS(PURPLE_STATUS_INVISIBLE);
-
-	/* Except tune status is different... */
-	status = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_TUNE,	/* primitive */
-			"tune",                 /* ID */
-			NULL,                   /* name - use default */
-			FALSE,                  /* saveable */
-			TRUE,                   /* should be user_settable some day */
-			TRUE,                   /* independent */
-
-			PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
-
-	types = g_list_append(types, status);
-
-	return types;
-}
-
-/*
- * TODO: This define is stolen from oscar.h.
- *       It's also in yahoo.h.
- *       It should be in libpurple/util.c
- */
-#define msim_put32(buf, data) ( \
-		(*((buf)) = (unsigned char)((data)>>24)&0xff), \
-		(*((buf)+1) = (unsigned char)((data)>>16)&0xff), \
-		(*((buf)+2) = (unsigned char)((data)>>8)&0xff), \
-		(*((buf)+3) = (unsigned char)(data)&0xff), \
-		4)
-
-/**
- * Compute the base64'd login challenge response based on username, password, nonce, and IPs.
- *
- * @param nonce The base64 encoded nonce ('nc') field from the server.
- * @param email User's email address (used as login name).
- * @param password User's cleartext password.
- * @param response_len Will be written with response length.
- *
- * @return Binary login challenge response, ready to send to the server.
- * Must be g_free()'d when finished. NULL if error.
- */
-static gchar *
-msim_compute_login_response(const gchar nonce[2 * NONCE_SIZE],
-		const gchar *email, const gchar *password, guint *response_len)
-{
-	PurpleCipherContext *key_context;
-	PurpleCipher *sha1;
-	PurpleCipherContext *rc4;
-
-	guchar hash_pw[HASH_SIZE];
-	guchar key[HASH_SIZE];
-	gchar *password_truncated, *password_utf16le, *password_utf8_lc;
-	GString *data;
-	guchar *data_out;
-	size_t data_out_len;
-	gsize conv_bytes_read, conv_bytes_written;
-	GError *conv_error;
-#ifdef MSIM_DEBUG_LOGIN_CHALLENGE
-	int i;
-#endif
-
-	g_return_val_if_fail(nonce != NULL, NULL);
-	g_return_val_if_fail(email != NULL, NULL);
-	g_return_val_if_fail(password != NULL, NULL);
-	g_return_val_if_fail(response_len != NULL, NULL);
-
-	/*
-	 * Truncate password to 10 characters.  Their "change password"
-	 * web page doesn't let you enter more than 10 characters, but you
-	 * can enter more than 10 when logging in on myspace.com and they
-	 * truncate it.
-	 */
-	password_truncated = g_strndup(password, 10);
-
-	/* Convert password to lowercase (required for passwords containing
-	 * uppercase characters). MySpace passwords are lowercase,
-	 * see ticket #2066. */
-	password_utf8_lc = g_utf8_strdown(password_truncated, -1);
-	g_free(password_truncated);
-
-	/* Convert ASCII password to UTF16 little endian */
-	purple_debug_info("msim", "converting password to UTF-16LE\n");
-	conv_error = NULL;
-	password_utf16le = g_convert(password_utf8_lc, -1, "UTF-16LE", "UTF-8",
-			&conv_bytes_read, &conv_bytes_written, &conv_error);
-	g_free(password_utf8_lc);
-
-	if (conv_error != NULL) {
-		purple_debug_error("msim",
-				"g_convert password UTF8->UTF16LE failed: %s",
-				conv_error->message);
-		g_error_free(conv_error);
-		return NULL;
-	}
-
-	/* Compute password hash */
-	purple_cipher_digest_region("sha1", (guchar *)password_utf16le,
-			conv_bytes_written, sizeof(hash_pw), hash_pw, NULL);
-	g_free(password_utf16le);
-
-#ifdef MSIM_DEBUG_LOGIN_CHALLENGE
-	purple_debug_info("msim", "pwhash = ");
-	for (i = 0; i < sizeof(hash_pw); i++)
-		purple_debug_info("msim", "%.2x ", hash_pw[i]);
-	purple_debug_info("msim", "\n");
-#endif
-
-	/* key = sha1(sha1(pw) + nonce2) */
-	sha1 = purple_ciphers_find_cipher("sha1");
-	key_context = purple_cipher_context_new(sha1, NULL);
-	purple_cipher_context_append(key_context, hash_pw, HASH_SIZE);
-	purple_cipher_context_append(key_context, (guchar *)(nonce + NONCE_SIZE), NONCE_SIZE);
-	purple_cipher_context_digest(key_context, sizeof(key), key, NULL);
-	purple_cipher_context_destroy(key_context);
-
-#ifdef MSIM_DEBUG_LOGIN_CHALLENGE
-	purple_debug_info("msim", "key = ");
-	for (i = 0; i < sizeof(key); i++) {
-		purple_debug_info("msim", "%.2x ", key[i]);
-	}
-	purple_debug_info("msim", "\n");
-#endif
-
-	rc4 = purple_cipher_context_new_by_name("rc4", NULL);
-
-	/* Note: 'key' variable is 0x14 bytes (from SHA-1 hash),
-	 * but only first 0x10 used for the RC4 key. */
-	purple_cipher_context_set_option(rc4, "key_len", (gpointer)0x10);
-	purple_cipher_context_set_key(rc4, key);
-
-	/* rc4 encrypt:
-	 * nonce1+email+IP list */
-
-	data = g_string_new(NULL);
-	g_string_append_len(data, nonce, NONCE_SIZE);
-
-	/* Include the null terminator */
-	g_string_append_len(data, email, strlen(email) + 1);
-
-	while (data->len % 4 != 0)
-		g_string_append_c(data, 0xfb);
-
-#ifdef SEND_OUR_IP_ADDRESSES
-	/* TODO: Obtain IPs of network interfaces instead of using this hardcoded value */
-	g_string_set_size(data, data->len + 4);
-	(void)msim_put32(data->str + data->len - 4, MSIM_LOGIN_IP_LIST_LEN);
-	g_string_append_len(data, MSIM_LOGIN_IP_LIST, MSIM_LOGIN_IP_LIST_LEN);
-#else
-	g_string_set_size(data, data->len + 4);
-	(void)msim_put32(data->str + data->len - 4, 0);
-#endif /* !SEND_OUR_IP_ADDRESSES */
-
-	data_out = g_new0(guchar, data->len);
-
-	purple_cipher_context_encrypt(rc4, (const guchar *)data->str,
-			data->len, data_out, &data_out_len);
-	purple_cipher_context_destroy(rc4);
-
-	if (data_out_len != data->len) {
-		purple_debug_info("msim", "msim_compute_login_response: "
-				"data length mismatch: %" G_GSIZE_FORMAT " != %"
-				G_GSIZE_FORMAT "\n", data_out_len, data->len);
-	}
-
-	g_string_free(data, TRUE);
-
-#ifdef MSIM_DEBUG_LOGIN_CHALLENGE
-	purple_debug_info("msim", "response=<%s>\n", data_out);
-#endif
-
-	*response_len = data_out_len;
-
-	return (gchar *)data_out;
-}
-
-/**
- * Process a login challenge, sending a response.
- *
- * @param session
- * @param msg Login challenge message.
- *
- * @return TRUE if successful, FALSE if not
- */
-static gboolean
-msim_login_challenge(MsimSession *session, MsimMessage *msg)
-{
-	PurpleAccount *account;
-	gchar *response;
-	guint response_len;
-	gchar *nc;
-	gsize nc_len;
-	gboolean ret;
-
-	g_return_val_if_fail(msg != NULL, FALSE);
-
-	g_return_val_if_fail(msim_msg_get_binary(msg, "nc", &nc, &nc_len), FALSE);
-
-	account = session->account;
-
-	g_return_val_if_fail(account != NULL, FALSE);
-
-	purple_connection_update_progress(session->gc, _("Reading challenge"), 1, 4);
-
-	purple_debug_info("msim", "nc is %" G_GSIZE_FORMAT
-			" bytes, decoded\n", nc_len);
-
-	if (nc_len != MSIM_AUTH_CHALLENGE_LENGTH) {
-		purple_debug_info("msim", "bad nc length: %" G_GSIZE_MODIFIER
-				"x != 0x%x\n", nc_len, MSIM_AUTH_CHALLENGE_LENGTH);
-		purple_connection_error_reason (session->gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("Unexpected challenge length from server"));
-		return FALSE;
-	}
-
-	purple_connection_update_progress(session->gc, _("Logging in"), 2, 4);
-
-	response_len = 0;
-	response = msim_compute_login_response(nc, account->username, account->password, &response_len);
-
-	g_free(nc);
-
-	ret = msim_send(session,
-			"login2", MSIM_TYPE_INTEGER, MSIM_AUTH_ALGORITHM,
-			/* This is actually user's email address. */
-			"username", MSIM_TYPE_STRING, g_strdup(account->username),
-			/* GString will be freed in msim_msg_free() in msim_send(). */
-			"response", MSIM_TYPE_BINARY, g_string_new_len(response, response_len),
-			"clientver", MSIM_TYPE_INTEGER, MSIM_CLIENT_VERSION,
-			"langid", MSIM_TYPE_INTEGER, MSIM_LANGUAGE_ID_ENGLISH,
-			"imlang", MSIM_TYPE_STRING, g_strdup(MSIM_LANGUAGE_NAME_ENGLISH),
-			"reconn", MSIM_TYPE_INTEGER, 0,
-			"status", MSIM_TYPE_INTEGER, 100,
-			"id", MSIM_TYPE_INTEGER, 1,
-			NULL);
-
-	g_free(response);
-
-	return ret;
-}
-
-/**
- * Process unrecognized information.
- *
- * @param session
- * @param msg An MsimMessage that was unrecognized, or NULL.
- * @param note Information on what was unrecognized, or NULL.
- */
-void
-msim_unrecognized(MsimSession *session, MsimMessage *msg, gchar *note)
-{
-	/* TODO: Some more context, outwardly equivalent to a backtrace,
-	 * for helping figure out what this msg is for. What was going on?
-	 * But not too much information so that a user
-	 * posting this dump reveals confidential information.
-	 */
-
-	/* TODO: dump unknown msgs to file, so user can send them to me
-	 * if they wish, to help add support for new messages (inspired
-	 * by Alexandr Shutko, who maintains OSCAR protocol documentation).
-	 *
-	 * Filed enhancement ticket for libpurple as #4688.
-	 */
-
-	purple_debug_info("msim", "Unrecognized data on account for %s\n",
-			(session && session->account && session->account->username) ?
-			session->account->username : "(NULL)");
-	if (note) {
-		purple_debug_info("msim", "(Note: %s)\n", note);
-	}
-
-	if (msg) {
-		msim_msg_dump("Unrecognized message dump: %s\n", msg);
-	}
-}
-
-/** Called when the session key arrives to check whether the user
- * has a username, and set one if desired. */
-static gboolean
-msim_is_username_set(MsimSession *session, MsimMessage *msg)
-{
-	g_return_val_if_fail(msg != NULL, FALSE);
-	g_return_val_if_fail(session->gc != NULL, FALSE);
-
-	session->sesskey = msim_msg_get_integer(msg, "sesskey");
-	purple_debug_info("msim", "SESSKEY=<%d>\n", session->sesskey);
-
-	/* What is proof? Used to be uid, but now is 52 base64'd bytes... */
-
-	/* Comes with: proof,profileid,userid,uniquenick -- all same values
-	 * some of the time, but can vary. This is our own user ID. */
-	session->userid = msim_msg_get_integer(msg, "userid");
-
-	/* Save uid to account so this account can be looked up by uid. */
-	purple_account_set_int(session->account, "uid", session->userid);
-
-	/* Not sure what profileid is used for. */
-	if (msim_msg_get_integer(msg, "profileid") != session->userid) {
-		msim_unrecognized(session, msg,
-				"Profile ID didn't match user ID, don't know why");
-	}
-
-	/* We now know are our own username, only after we're logged in..
-	 * which is weird, but happens because you login with your email
-	 * address and not username. Will be freed in msim_session_destroy(). */
-	session->username = msim_msg_get_string(msg, "uniquenick");
-
-	/* If user lacks a username, help them get one. */
-	if (msim_msg_get_integer(msg, "uniquenick") == session->userid) {
-		purple_debug_info("msim_is_username_set", "no username is set\n");
-		purple_request_yes_no(session->gc,
-			_("MySpaceIM - No Username Set"),
-			_("You appear to have no MySpace username."),
-			_("Would you like to set one now? (Note: THIS CANNOT BE CHANGED!)"),
-			0,
-			session->account,
-			NULL,
-			NULL,
-			session->gc,
-			G_CALLBACK(msim_set_username_cb),
-			G_CALLBACK(msim_do_not_set_username_cb));
-		purple_debug_info("msim_is_username_set","'username not set' alert prompted\n");
-		return FALSE;
-	}
-	return TRUE;
-}
-
-#ifdef MSIM_USE_KEEPALIVE
-/**
- * Check if the connection is still alive, based on last communication.
- */
-static gboolean
-msim_check_alive(gpointer data)
-{
-	MsimSession *session;
-	time_t delta;
-
-	session = (MsimSession *)data;
-
-	delta = time(NULL) - session->last_comm;
-
-	/* purple_debug_info("msim", "msim_check_alive: delta=%d\n", delta); */
-	if (delta >= MSIM_KEEPALIVE_INTERVAL) {
-		purple_debug_info("msim",
-				"msim_check_alive: %zu > interval of %d, presumed dead\n",
-				delta, MSIM_KEEPALIVE_INTERVAL);
-		purple_connection_error_reason(session->gc,
-				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-				_("Lost connection with server"));
-
-		return FALSE;
-	}
-
-	return TRUE;
-}
-#endif
-
-/**
- * Handle mail reply checks.
- */
-static void
-msim_check_inbox_cb(MsimSession *session, const MsimMessage *reply, gpointer data)
-{
-	MsimMessage *body;
-	guint i, n;
-	/* Information for each new inbox message type. */
-	static struct
-	{
-		const gchar *key;
-		guint bit;
-		const gchar *url;
-		const gchar *text;
-	} message_types[] = {
-		{ "Mail", MSIM_INBOX_MAIL, "http://messaging.myspace.com/index.cfm?fuseaction=mail.inbox", NULL },
-		{ "BlogComment", MSIM_INBOX_BLOG_COMMENT, "http://blog.myspace.com/index.cfm?fuseaction=blog", NULL },
-		{ "ProfileComment", MSIM_INBOX_PROFILE_COMMENT, "http://home.myspace.com/index.cfm?fuseaction=user", NULL },
-		{ "FriendRequest", MSIM_INBOX_FRIEND_REQUEST, "http://messaging.myspace.com/index.cfm?fuseaction=mail.friendRequests", NULL },
-		{ "PictureComment", MSIM_INBOX_PICTURE_COMMENT, "http://home.myspace.com/index.cfm?fuseaction=user", NULL }
-	};
-	const gchar *froms[G_N_ELEMENTS(message_types) + 1] = { "" },
-		*tos[G_N_ELEMENTS(message_types) + 1] = { "" },
-		*urls[G_N_ELEMENTS(message_types) + 1] = { "" },
-		*subjects[G_N_ELEMENTS(message_types) + 1] = { "" };
-
-	g_return_if_fail(reply != NULL);
-
-	/* Can't write _()'d strings in array initializers. Workaround. */
-	/* khc: then use N_() in the array initializer and use _() when they are
-	   used */
-	message_types[0].text = _("New mail messages");
-	message_types[1].text = _("New blog comments");
-	message_types[2].text = _("New profile comments");
-	message_types[3].text = _("New friend requests!");
-	message_types[4].text = _("New picture comments");
-
-	body = msim_msg_get_dictionary(reply, "body");
-
-	if (body == NULL)
-		return;
-
-	n = 0;
-
-	for (i = 0; i < G_N_ELEMENTS(message_types); ++i) {
-		const gchar *key;
-		guint bit;
-
-		key = message_types[i].key;
-		bit = message_types[i].bit;
-
-		if (msim_msg_get(body, key)) {
-			/* Notify only on when _changes_ from no mail -> has mail
-			 * (edge triggered) */
-			if (!(session->inbox_status & bit)) {
-				purple_debug_info("msim", "msim_check_inbox_cb: got %s, at %d\n",
-						key ? key : "(NULL)", n);
-
-				subjects[n] = message_types[i].text;
-				froms[n] = _("MySpace");
-				tos[n] = session->username;
-				/* TODO: append token, web challenge, so automatically logs in.
-				 * Would also need to free strings because they won't be static
-				 */
-				urls[n] = message_types[i].url;
-
-				++n;
-			} else {
-				purple_debug_info("msim",
-						"msim_check_inbox_cb: already notified of %s\n",
-						key ? key : "(NULL)");
-			}
-
-			session->inbox_status |= bit;
-		}
-	}
-
-	if (n) {
-		purple_debug_info("msim",
-				"msim_check_inbox_cb: notifying of %d\n", n);
-
-		/* TODO: free strings with callback _if_ change to dynamic (w/ token) */
-		purple_notify_emails(session->gc,         /* handle */
-				n,                        /* count */
-				TRUE,                     /* detailed */
-				subjects, froms, tos, urls,
-				NULL,                     /* PurpleNotifyCloseCallback cb */
-				NULL);                    /* gpointer user_data */
-
-	}
-
-	msim_msg_free(body);
-}
-
-/**
- * Send request to check if there is new mail.
- */
-static gboolean
-msim_check_inbox(gpointer data)
-{
-	MsimSession *session;
-
-	session = (MsimSession *)data;
-
-	purple_debug_info("msim", "msim_check_inbox: checking mail\n");
-	g_return_val_if_fail(msim_send(session,
-			"persist", MSIM_TYPE_INTEGER, 1,
-			"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-			"cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
-			"dsn", MSIM_TYPE_INTEGER, MG_CHECK_MAIL_DSN,
-			"lid", MSIM_TYPE_INTEGER, MG_CHECK_MAIL_LID,
-			"uid", MSIM_TYPE_INTEGER, session->userid,
-			"rid", MSIM_TYPE_INTEGER,
-				msim_new_reply_callback(session, msim_check_inbox_cb, NULL),
-			"body", MSIM_TYPE_STRING, g_strdup(""),
-			NULL), TRUE);
-
-	/* Always return true, so that we keep checking for mail. */
-	return TRUE;
-}
-
-/**
- * Add contact from server to buddy list, after looking up username.
- * Callback from msim_add_contact_from_server().
- *
- * @param data An MsimMessage * of the contact information. Will be freed.
- */
-static void
-msim_add_contact_from_server_cb(MsimSession *session, const MsimMessage *user_lookup_info, gpointer data)
-{
-	MsimMessage *contact_info, *user_lookup_info_body;
-	PurpleGroup *group;
-	PurpleBuddy *buddy;
-	MsimUser *user;
-	gchar *username, *group_name, *display_name;
-	guint uid, visibility;
-
-	contact_info = (MsimMessage *)data;
-	purple_debug_info("msim_add_contact_from_server_cb", "contact_info addr=%p\n", contact_info);
-	uid = msim_msg_get_integer(contact_info, "ContactID");
-
-	if (!user_lookup_info) {
-		username = g_strdup(msim_uid2username_from_blist(session->account, uid));
-		display_name = NULL;
-		g_return_if_fail(username != NULL);
-	} else {
-		user_lookup_info_body = msim_msg_get_dictionary(user_lookup_info, "body");
-		username = msim_msg_get_string(user_lookup_info_body, "UserName");
-		display_name = msim_msg_get_string(user_lookup_info_body, "DisplayName");
-		msim_msg_free(user_lookup_info_body);
-		g_return_if_fail(username != NULL);
-	}
-
-	purple_debug_info("msim_add_contact_from_server_cb",
-			"*** about to add/update username=%s\n", username);
-
-	/* 1. Creates a new group, or gets existing group if it exists (or so
-	 * the documentation claims). */
-	group_name = msim_msg_get_string(contact_info, "GroupName");
-	if (!group_name || (*group_name == '\0')) {
-		g_free(group_name);
-		group_name = g_strdup(_("IM Friends"));
-		purple_debug_info("myspace", "No GroupName specified, defaulting to '%s'.\n", group_name);
-	}
-	group = purple_find_group(group_name);
-	if (!group) {
-		group = purple_group_new(group_name);
-		/* Add group to beginning. See #2752. */
-		purple_blist_add_group(group, NULL);
-	}
-	g_free(group_name);
-
-	visibility = msim_msg_get_integer(contact_info, "Visibility");
-	if (visibility == 2) {
-		/* This buddy is blocked (and therefore not on our buddy list */
-		purple_privacy_deny_add(session->account, username, TRUE);
-		msim_msg_free(contact_info);
-		g_free(username);
-		g_free(display_name);
-		return;
-	}
-
-	/* 2. Get or create buddy */
-	buddy = purple_find_buddy(session->account, username);
-	if (!buddy) {
-		purple_debug_info("msim_add_contact_from_server_cb",
-				"creating new buddy: %s\n", username);
-		buddy = purple_buddy_new(session->account, username, NULL);
-	}
-
-	/* TODO: use 'Position' in contact_info to take into account where buddy is */
-	purple_blist_add_buddy(buddy, NULL, group, NULL /* insertion point */);
-
-	if (strtoul(username, NULL, 10) == uid) {
-		/*
-		 * This user has not set their username!  Set their server
-		 * alias to their display name so that we don't see a bunch
-		 * of numbers in the buddy list.
-		 */
-		if (display_name != NULL) {
-			purple_blist_node_set_string(PURPLE_BLIST_NODE(buddy), "DisplayName", display_name);
-			serv_got_alias(session->gc, username, display_name);
-		} else {
-			serv_got_alias(session->gc, username,
-					purple_blist_node_get_string(PURPLE_BLIST_NODE(buddy), "DisplayName"));
-		}
-	}
-	g_free(display_name);
-
-	/* 3. Update buddy information */
-	user = msim_get_user_from_buddy(buddy, TRUE);
-
-	user->id = uid;
-	/* Keep track of the user ID across sessions */
-	purple_blist_node_set_int(PURPLE_BLIST_NODE(buddy), "UserID", uid);
-
-	/* Stores a few fields in the MsimUser, relevant to the buddy itself.
-	 * AvatarURL, Headline, ContactID. */
-	msim_store_user_info(session, contact_info, NULL);
-
-	/* TODO: other fields, store in 'user' */
-	msim_msg_free(contact_info);
-
-	g_free(username);
-}
-
-/**
- * Add first ContactID in contact_info to buddy's list. Used to add
- * server-side buddies to client-side list.
- *
- * @return TRUE if added.
- */
-static gboolean
-msim_add_contact_from_server(MsimSession *session, MsimMessage *contact_info)
-{
-	guint uid;
-	const gchar *username;
-
-	uid = msim_msg_get_integer(contact_info, "ContactID");
-	g_return_val_if_fail(uid != 0, FALSE);
-
-	/* Lookup the username, since NickName and IMName is unreliable */
-	username = msim_uid2username_from_blist(session->account, uid);
-	if (!username) {
-		gchar *uid_str;
-
-		uid_str = g_strdup_printf("%d", uid);
-		purple_debug_info("msim_add_contact_from_server",
-				"contact_info addr=%p\n", contact_info);
-		msim_lookup_user(session, uid_str, msim_add_contact_from_server_cb, (gpointer)msim_msg_clone(contact_info));
-		g_free(uid_str);
-	} else {
-		msim_add_contact_from_server_cb(session, NULL, (gpointer)msim_msg_clone(contact_info));
-	}
-
-	/* Say that the contact was added, even if we're still looking up
-	 * their username. */
-	return TRUE;
-}
-
-/**
- * Called when contact list is received from server.
- */
-static void
-msim_got_contact_list(MsimSession *session, const MsimMessage *reply, gpointer user_data)
-{
-	MsimMessage *body, *body_node;
-	gchar *msg;
-	guint buddy_count;
-
-	body = msim_msg_get_dictionary(reply, "body");
-
-	buddy_count = 0;
-
-	for (body_node = body;
-		body_node != NULL;
-		body_node = msim_msg_get_next_element_node(body_node))
-	{
-		MsimMessageElement *elem;
-
-		elem = (MsimMessageElement *)body_node->data;
-
-		if (g_str_equal(elem->name, "ContactID"))
-		{
-			/* Will look for first contact in body_node */
-			if (msim_add_contact_from_server(session, body_node)) {
-				++buddy_count;
-			}
-		}
-	}
-
-	switch (GPOINTER_TO_UINT(user_data)) {
-		case MSIM_CONTACT_LIST_IMPORT_ALL_FRIENDS:
-		        msg = g_strdup_printf(ngettext("%d buddy was added or updated from the server (including buddies already on the server-side list)",
-						       "%d buddies were added or updated from the server (including buddies already on the server-side list)",
-						       buddy_count),
-					      buddy_count);
-			purple_notify_info(session->account, _("Add contacts from server"), msg, NULL);
-			g_free(msg);
-			break;
-
-		case MSIM_CONTACT_LIST_IMPORT_TOP_FRIENDS:
-			/* TODO */
-			break;
-
-		case MSIM_CONTACT_LIST_INITIAL_FRIENDS:
-			/* The session is now set up, ready to be connected. This emits the
-			 * signedOn signal, so clients can now do anything with msimprpl, and
-			 * we're ready for it (session key, userid, username all setup). */
-			purple_connection_update_progress(session->gc, _("Connected"), 3, 4);
-			purple_connection_set_state(session->gc, PURPLE_CONNECTED);
-			break;
-	}
-
-	msim_msg_free(body);
-}
-
-/**
- * Get contact list, calling msim_got_contact_list() with
- * what_to_do_after as user_data gpointer.
- *
- * @param what_to_do_after should be one of the MSIM_CONTACT_LIST_* #defines.
- */
-static gboolean
-msim_get_contact_list(MsimSession *session, int what_to_do_after)
-{
-	return msim_send(session,
-			"persist", MSIM_TYPE_INTEGER, 1,
-			"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-			"cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
-			"dsn", MSIM_TYPE_INTEGER, MG_LIST_ALL_CONTACTS_DSN,
-			"lid", MSIM_TYPE_INTEGER, MG_LIST_ALL_CONTACTS_LID,
-			"uid", MSIM_TYPE_INTEGER, session->userid,
-			"rid", MSIM_TYPE_INTEGER,
-				msim_new_reply_callback(session, msim_got_contact_list, GUINT_TO_POINTER(what_to_do_after)),
-			"body", MSIM_TYPE_STRING, g_strdup(""),
-			NULL);
-}
-
-/** Called after username is set, if necessary and we're open for business. */
-gboolean msim_we_are_logged_on(MsimSession *session)
-{
-	MsimMessage *body;
-
-	/* Set display name to username (otherwise will show email address) */
-	purple_connection_set_display_name(session->gc, session->username);
-
-	body = msim_msg_new(
-			"UserID", MSIM_TYPE_INTEGER, session->userid,
-			NULL);
-
-	/* Request IM info about ourself. */
-	msim_send(session,
-			"persist", MSIM_TYPE_INTEGER, 1,
-			"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-			"cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
-			"dsn", MSIM_TYPE_INTEGER, MG_OWN_MYSPACE_INFO_DSN,
-			"lid", MSIM_TYPE_INTEGER, MG_OWN_MYSPACE_INFO_LID,
-			"rid", MSIM_TYPE_INTEGER, session->next_rid++,
-			"UserID", MSIM_TYPE_INTEGER, session->userid,
-			"body", MSIM_TYPE_DICTIONARY, body,
-			NULL);
-
-	/* Request MySpace info about ourself. */
-	msim_send(session,
-			"persist", MSIM_TYPE_INTEGER, 1,
-			"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-			"cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
-			"dsn", MSIM_TYPE_INTEGER, MG_OWN_IM_INFO_DSN,
-			"lid", MSIM_TYPE_INTEGER, MG_OWN_IM_INFO_LID,
-			"rid", MSIM_TYPE_INTEGER, session->next_rid++,
-			"body", MSIM_TYPE_STRING, g_strdup(""),
-			NULL);
-
-	/* TODO: set options (persist cmd=514,dsn=1,lid=10) */
-	/* TODO: set blocklist */
-
-	/* Notify servers of our current status. */
-	purple_debug_info("msim", "msim_we_are_logged_on: notifying servers of status\n");
-	msim_set_status(session->account,
-			purple_account_get_active_status(session->account));
-
-	/* TODO: setinfo */
-	/*
-	body = msim_msg_new(
-		"TotalFriends", MSIM_TYPE_INTEGER, 666,
-		NULL);
-	msim_send(session,
-			"setinfo", MSIM_TYPE_BOOLEAN, TRUE,
-			"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-			"info", MSIM_TYPE_DICTIONARY, body,
-			NULL);
-			*/
-
-	/* Disable due to problems with timeouts. TODO: fix. */
-#ifdef MSIM_USE_KEEPALIVE
-	purple_timeout_add_seconds(MSIM_KEEPALIVE_INTERVAL_CHECK,
-			(GSourceFunc)msim_check_alive, session);
-#endif
-
-	/* Check mail if they want to. */
-	if (purple_account_get_check_mail(session->account)) {
-		session->inbox_handle = purple_timeout_add(MSIM_MAIL_INTERVAL_CHECK,
-				(GSourceFunc)msim_check_inbox, session);
-		msim_check_inbox(session);
-	}
-
-	msim_get_contact_list(session, MSIM_CONTACT_LIST_INITIAL_FRIENDS);
-
-	return TRUE;
-}
-
-/**
- * Record the client version in the buddy list, from an incoming message.
- */
-static gboolean
-msim_incoming_bm_record_cv(MsimSession *session, MsimMessage *msg)
-{
-	gchar *username, *cv;
-	gboolean ret;
-	MsimUser *user;
-
-	username = msim_msg_get_string(msg, "_username");
-	cv = msim_msg_get_string(msg, "cv");
-
-	g_return_val_if_fail(username != NULL, FALSE);
-	if (!cv) {
-		/* No client version to record, don't worry about it. */
-		g_free(username);
-		return FALSE;
-	}
-
-	user = msim_find_user(session, username);
-
-	if (user) {
-		user->client_cv = atol(cv);
-		ret = TRUE;
-	} else {
-		ret = FALSE;
-	}
-
-	g_free(username);
-	g_free(cv);
-
-	return ret;
-}
-
-#ifdef MSIM_SEND_CLIENT_VERSION
-/**
- * Send our client version to another unofficial client that understands it.
- */
-static gboolean
-msim_send_unofficial_client(MsimSession *session, gchar *username)
-{
-	gchar *our_info;
-	gboolean ret;
-
-	our_info = g_strdup_printf("Libpurple %d.%d.%d - msimprpl %s",
-			PURPLE_MAJOR_VERSION,
-			PURPLE_MINOR_VERSION,
-			PURPLE_MICRO_VERSION,
-			MSIM_PRPL_VERSION_STRING);
-
-	ret = msim_send_bm(session, username, our_info, MSIM_BM_UNOFFICIAL_CLIENT);
-
-	return ret;
-}
-#endif
-/**
- * Process incoming status mood messages.
- *
- * @param session
- * @param msg Status mood update message. Caller frees.
- *
- * @return TRUE if successful.
- */
-static gboolean
-msim_incoming_status_mood(MsimSession *session, MsimMessage *msg) {
-	/* TODO: I dont know too much about this yet,
-	 * so until I see how the official client handles
-	 * this and decide if libpurple should as well,
-	 * well just say we used it
-	 */
-	gchar *ss;
-	ss = msim_msg_get_string(msg, "msg");
-	purple_debug_info("msim", "Incoming Status Message: %s", ss ? ss : "(NULL)");
-	g_free(ss);
-	return TRUE;
-}
-
-/**
- * Process incoming status messages.
- *
- * @param session
- * @param msg Status update message. Caller frees.
- *
- * @return TRUE if successful.
- */
-static gboolean
-msim_incoming_status(MsimSession *session, MsimMessage *msg)
-{
-	MsimUser *user;
-	GList *list;
-	gchar *status_headline, *status_headline_escaped;
-	gint status_code, purple_status_code;
-	gchar *username;
-	gchar *unrecognized_msg;
-
-	g_return_val_if_fail(msg != NULL, FALSE);
-
-	/* Helpfully looked up by msim_incoming_resolve() for us. */
-	username = msim_msg_get_string(msg, "_username");
-	g_return_val_if_fail(username != NULL, FALSE);
-
-	{
-		gchar *ss;
-
-		ss = msim_msg_get_string(msg, "msg");
-		purple_debug_info("msim",
-				"msim_status: updating status for <%s> to <%s>\n",
-				username, ss ? ss : "(NULL)");
-		g_free(ss);
-	}
-
-	/* Example fields:
-	 *  |s|0|ss|Offline
-	 *  |s|1|ss|:-)|ls||ip|0|p|0
-	 */
-	list = msim_msg_get_list(msg, "msg");
-
-	status_code = msim_msg_get_integer_from_element(g_list_nth_data(list, MSIM_STATUS_ORDINAL_ONLINE));
-	purple_debug_info("msim", "msim_status: %s's status code = %d\n", username, status_code);
-	status_headline = msim_msg_get_string_from_element(g_list_nth_data(list, MSIM_STATUS_ORDINAL_HEADLINE));
-
-	/* Add buddy if not found.
-	 * TODO: Could this be responsible for #3444? */
-	user = msim_find_user(session, username);
-	if (!user) {
-		PurpleBuddy *buddy;
-
-		purple_debug_info("msim",
-				"msim_status: making new buddy for %s\n", username);
-		buddy = purple_buddy_new(session->account, username, NULL);
-		purple_blist_add_buddy(buddy, NULL, NULL, NULL);
-
-		user = msim_get_user_from_buddy(buddy, TRUE);
-		user->id = msim_msg_get_integer(msg, "f");
-
-		/* Keep track of the user ID across sessions */
-		purple_blist_node_set_int(PURPLE_BLIST_NODE(buddy), "UserID", user->id);
-
-		msim_store_user_info(session, msg, NULL);
-	} else {
-		purple_debug_info("msim", "msim_status: found buddy %s\n", username);
-	}
-
-	if (status_headline && strcmp(status_headline, "") != 0) {
-		/* The status headline is plaintext, but libpurple treats it as HTML,
-		 * so escape any HTML characters to their entity equivalents. */
-		status_headline_escaped = g_markup_escape_text(status_headline, -1);
-	} else {
-		status_headline_escaped = NULL;
-	}
-
-	g_free(status_headline);
-
-	/* don't copy; let the MsimUser own the headline, memory-wise */
-	g_free(user->headline);
-	user->headline = status_headline_escaped;
-
-	/* Set user status */
-	switch (status_code) {
-		case MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN:
-			purple_status_code = PURPLE_STATUS_OFFLINE;
-			break;
-
-		case MSIM_STATUS_CODE_ONLINE:
-			purple_status_code = PURPLE_STATUS_AVAILABLE;
-			break;
-
-		case MSIM_STATUS_CODE_AWAY:
-			purple_status_code = PURPLE_STATUS_AWAY;
-			break;
-
-		case MSIM_STATUS_CODE_IDLE:
-			/* Treat idle as an available status. */
-			purple_status_code = PURPLE_STATUS_AVAILABLE;
-			break;
-
-		default:
-			purple_debug_info("msim", "msim_incoming_status for %s, unknown status code %d, treating as available\n",
-						username, status_code);
-			purple_status_code = PURPLE_STATUS_AVAILABLE;
-
-			unrecognized_msg = g_strdup_printf("msim_incoming_status, unrecognized status code: %d\n",
-					status_code);
-			msim_unrecognized(session, NULL, unrecognized_msg);
-			g_free(unrecognized_msg);
-	}
-
-	purple_prpl_got_user_status(session->account, username, purple_primitive_get_id_from_type(purple_status_code), NULL);
-
-	if (status_code == MSIM_STATUS_CODE_IDLE) {
-		purple_debug_info("msim", "msim_status: got idle: %s\n", username);
-		purple_prpl_got_user_idle(session->account, username, TRUE, 0);
-	} else {
-		/* All other statuses indicate going back to non-idle. */
-		purple_prpl_got_user_idle(session->account, username, FALSE, 0);
-	}
-
-#ifdef MSIM_SEND_CLIENT_VERSION
-	if (status_code == MSIM_STATUS_CODE_ONLINE) {
-		/* Secretly whisper to unofficial clients our own version as they come online */
-		msim_send_unofficial_client(session, username);
-	}
-#endif
-
-	if (status_code != MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN) {
-		/* Get information when they come online.
-		 * TODO: periodically refresh?
-		 */
-		purple_debug_info("msim_incoming_status", "%s came online, looking up\n", username);
-		msim_lookup_user(session, username, NULL, NULL);
-	}
-
-	g_free(username);
-	msim_msg_list_free(list);
-
-	return TRUE;
-}
-
-/**
- * Handle an incoming instant message.
- *
- * @param session The session
- * @param msg Message from the server, containing 'f' (userid from) and 'msg'.
- *               Should also contain username in _username from preprocessing.
- *
- * @return TRUE if successful.
- */
-static gboolean
-msim_incoming_im(MsimSession *session, MsimMessage *msg, const gchar *username)
-{
-	gchar *msg_msim_markup, *msg_purple_markup;
-	gchar *userid;
-	time_t time_received;
-	PurpleConversation *conv;
-
-	/* I know this isn't really a string... but we need it to be one for
-	 * purple_find_conversation_with_account(). */
-	userid = msim_msg_get_string(msg, "f");
-
-	purple_debug_info("msim_incoming_im", "UserID is %s", userid);
-
-	if (msim_is_userid(username)) {
-		purple_debug_info("msim", "Ignoring message from spambot (%s) on account %s\n",
-				username, purple_account_get_username(session->account));
-		return FALSE;
-	}
-
-	/* See if a conversation with their UID already exists...*/
-	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, userid, session->account);
-	if (conv) {
-		/* Since the conversation exists... We need to normalize it */
-		purple_conversation_set_name(conv, username);
-	}
-
-	msg_msim_markup = msim_msg_get_string(msg, "msg");
-	g_return_val_if_fail(msg_msim_markup != NULL, FALSE);
-
-	msg_purple_markup = msim_markup_to_html(session, msg_msim_markup);
-	g_free(msg_msim_markup);
-
-	time_received = msim_msg_get_integer(msg, "date");
-	if (!time_received) {
-		purple_debug_info("msim_incoming_im", "date in message not set.\n");
-		time_received = time(NULL);
-	}
-
-	serv_got_im(session->gc, username, msg_purple_markup, PURPLE_MESSAGE_RECV, time_received);
-
-	g_free(msg_purple_markup);
-
-	return TRUE;
-}
-
-/**
- * Handle an incoming action message or an IM.
- *
- * @param session
- * @param msg
- *
- * @return TRUE if successful.
- */
-static gboolean
-msim_incoming_action_or_im(MsimSession *session, MsimMessage *msg)
-{
-	gchar *msg_text, *username;
-	gboolean rc;
-
-	g_return_val_if_fail(msg != NULL, FALSE);
-
-	msg_text = msim_msg_get_string(msg, "msg");
-	g_return_val_if_fail(msg_text != NULL, FALSE);
-
-	username = msim_msg_get_string(msg, "_username");
-	g_return_val_if_fail(username != NULL, FALSE);
-
-	purple_debug_info("msim",
-			"msim_incoming_action_or_im: action <%s> from <%s>\n",
-			msg_text, username);
-
-	if (g_str_equal(msg_text, "%typing%")) {
-		serv_got_typing(session->gc, username, 0, PURPLE_TYPING);
-		rc = TRUE;
-	} else if (g_str_equal(msg_text, "%stoptyping%")) {
-		serv_got_typing_stopped(session->gc, username);
-		rc = TRUE;
-	} else if (strstr(msg_text, "!!!ZAP_SEND!!!=RTE_BTN_ZAPS_")) {
-		rc = msim_incoming_zap(session, msg);
-	} else if (strstr(msg_text, "!!!GroupCount=")) {
-		/* TODO: support group chats. I think the number in msg_text has
-		 * something to do with the 'gid' field. */
-		purple_debug_info("msim",
-				"msim_incoming_action_or_im: "
-				"TODO: implement #4691, group chats: %s\n", msg_text);
-
-		rc = TRUE;
-	} else if (strstr(msg_text, "!!!Offline=")) {
-		/* TODO: support group chats. This one might mean a user
-		 * went offline or exited the chat. */
-		purple_debug_info("msim", "msim_incoming_action_or_im: "
-				"TODO: implement #4691, group chats: %s\n", msg_text);
-
-		rc = TRUE;
-	} else if (msim_msg_get_integer(msg, "aid") != 0) {
-		purple_debug_info("msim", "TODO: implement #4691, group chat from %d on %d: %s\n",
-				msim_msg_get_integer(msg, "aid"),
-				msim_msg_get_integer(msg, "f"),
-				msg_text);
-
-		rc = TRUE;
-	} else {
-		rc = msim_incoming_im(session, msg, username);
-	}
-
-	g_free(msg_text);
-	g_free(username);
-
-	return rc;
-}
-
-/**
- * Process an incoming media (message background?) message.
- */
-static gboolean
-msim_incoming_media(MsimSession *session, MsimMessage *msg)
-{
-	gchar *username, *text;
-
-	username = msim_msg_get_string(msg, "_username");
-	text = msim_msg_get_string(msg, "msg");
-
-	g_return_val_if_fail(username != NULL, FALSE);
-	g_return_val_if_fail(text != NULL, FALSE);
-
-	purple_debug_info("msim", "msim_incoming_media: from %s, got msg=%s\n", username, text);
-
-	/* Media messages are sent when the user opens a window to someone.
-	 * Tell libpurple they started typing and stopped typing, to inform the Psychic
-	 * Mode plugin so it too can open a window to the user. */
-	serv_got_typing(session->gc, username, 0, PURPLE_TYPING);
-	serv_got_typing_stopped(session->gc, username);
-
-	g_free(username);
-
-	return TRUE;
-}
-
-/**
- * Process an incoming "unofficial client" message. The plugin for
- * Miranda IM sends this message with the plugin information.
- */
-static gboolean
-msim_incoming_unofficial_client(MsimSession *session, MsimMessage *msg)
-{
-	MsimUser *user;
-	gchar *username, *client_info;
-
-	username = msim_msg_get_string(msg, "_username");
-	client_info = msim_msg_get_string(msg, "msg");
-
-	g_return_val_if_fail(username != NULL, FALSE);
-	g_return_val_if_fail(client_info != NULL, FALSE);
-
-	purple_debug_info("msim", "msim_incoming_unofficial_client: %s is using client %s\n",
-		username, client_info);
-
-	user = msim_find_user(session, username);
-
-	g_return_val_if_fail(user != NULL, FALSE);
-
-	if (user->client_info) {
-		g_free(user->client_info);
-	}
-	user->client_info = client_info;
-
-	g_free(username);
-	/* Do not free client_info - the MsimUser now owns it. */
-
-	return TRUE;
-}
-
-/**
- * Handle an incoming buddy message.
- */
-static gboolean
-msim_incoming_bm(MsimSession *session, MsimMessage *msg)
-{
-	guint bm;
-
-	bm = msim_msg_get_integer(msg, "bm");
-
-	msim_incoming_bm_record_cv(session, msg);
-
-	switch (bm) {
-		case MSIM_BM_STATUS:
-			return msim_incoming_status(session, msg);
-		case MSIM_BM_ACTION_OR_IM_DELAYABLE:
-		case MSIM_BM_ACTION_OR_IM_INSTANT:
-			return msim_incoming_action_or_im(session, msg);
-		case MSIM_BM_MEDIA:
-			return msim_incoming_media(session, msg);
-		case MSIM_BM_UNOFFICIAL_CLIENT:
-			return msim_incoming_unofficial_client(session, msg);
-		case MSIM_BM_STATUS_MOOD:
-			return msim_incoming_status_mood(session, msg);
-		default:
-			/*
-			 * Unknown message type!  We used to call
-			 *   msim_incoming_action_or_im(session, msg);
-			 * for these, but that doesn't help anything, and it means
-			 * we'll show broken gibberish if MySpace starts sending us
-			 * other message types.
-			 */
-			purple_debug_warning("myspace", "Received unknown imcoming "
-					"message, bm=%u\n", bm);
-			return TRUE;
-	}
-}
-
-/**
- * Process the initial server information from the server.
- */
-static gboolean
-msim_process_server_info(MsimSession *session, MsimMessage *msg)
-{
-	MsimMessage *body;
-
-	body = msim_msg_get_dictionary(msg, "body");
-	g_return_val_if_fail(body != NULL, FALSE);
-
-	/* Example body:
-AdUnitRefreshInterval=10.
-AlertPollInterval=360.
-AllowChatRoomEmoticonSharing=False.
-ChatRoomUserIDs=78744676;163733130;1300326231;123521495;142663391.
-CurClientVersion=673.
-EnableIMBrowse=True.
-EnableIMStuffAvatars=False.
-EnableIMStuffZaps=False.
-MaxAddAllFriends=100.
-MaxContacts=1000.
-MinClientVersion=594.
-MySpaceIM_ENGLISH=78744676.
-MySpaceNowTimer=720.
-PersistenceDataTimeout=900.
-UseWebChallenge=1.
-WebTicketGoHome=False
-
-	Anything useful? TODO: use what is useful, and use it.
-*/
-	purple_debug_info("msim_process_server_info",
-			"maximum contacts: %d\n",
-			msim_msg_get_integer(body, "MaxContacts"));
-
-	session->server_info = body;
-	/* session->server_info freed in msim_session_destroy */
-
-	return TRUE;
-}
-
-/**
- * Process a web challenge, used to login to the web site.
- */
-static gboolean
-msim_web_challenge(MsimSession *session, MsimMessage *msg)
-{
-	/* TODO: web challenge, store token. #2659. */
-	return FALSE;
-}
-
-/**
- * Process a persistance message reply from the server.
- *
- * @param session
- * @param msg Message reply from server.
- *
- * @return TRUE if successful.
- *
- * msim_lookup_user sets callback for here
- */
-static gboolean
-msim_process_reply(MsimSession *session, MsimMessage *msg)
-{
-	MSIM_USER_LOOKUP_CB cb;
-	gpointer data;
-	guint rid, cmd, dsn, lid;
-
-	g_return_val_if_fail(msg != NULL, FALSE);
-
-	msim_store_user_info(session, msg, NULL);
-
-	rid = msim_msg_get_integer(msg, "rid");
-	cmd = msim_msg_get_integer(msg, "cmd");
-	dsn = msim_msg_get_integer(msg, "dsn");
-	lid = msim_msg_get_integer(msg, "lid");
-
-	/* Unsolicited messages */
-	if (cmd == (guint)(MSIM_CMD_BIT_REPLY | MSIM_CMD_GET)) {
-		if (dsn == (guint)MG_SERVER_INFO_DSN && lid == (guint)MG_SERVER_INFO_LID) {
-			return msim_process_server_info(session, msg);
-		} else if (dsn == (guint)MG_WEB_CHALLENGE_DSN && lid == (guint)MG_WEB_CHALLENGE_LID) {
-			return msim_web_challenge(session, msg);
-		}
-	}
-
-	/* If a callback is registered for this userid lookup, call it. */
-	cb = g_hash_table_lookup(session->user_lookup_cb, GUINT_TO_POINTER(rid));
-	data = g_hash_table_lookup(session->user_lookup_cb_data, GUINT_TO_POINTER(rid));
-
-	if (cb) {
-		purple_debug_info("msim", "msim_process_reply: calling callback now\n");
-		/* Clone message, so that the callback 'cb' can use it (needs to free it also). */
-		cb(session, msg, data);
-		g_hash_table_remove(session->user_lookup_cb, GUINT_TO_POINTER(rid));
-		g_hash_table_remove(session->user_lookup_cb_data, GUINT_TO_POINTER(rid));
-	} else {
-		purple_debug_info("msim",
-				"msim_process_reply: no callback for rid %d\n", rid);
-	}
-
-	return TRUE;
-}
-
-/**
- * Handle an error from the server.
- *
- * @param session
- * @param msg The message.
- *
- * @return TRUE if successfully reported error.
- */
-static gboolean
-msim_error(MsimSession *session, MsimMessage *msg)
-{
-	gchar *errmsg, *full_errmsg;
-	guint err;
-
-	g_return_val_if_fail(msg != NULL, FALSE);
-
-	err = msim_msg_get_integer(msg, "err");
-	errmsg = msim_msg_get_string(msg, "errmsg");
-
-	full_errmsg = g_strdup_printf(_("Protocol error, code %d: %s"), err,
-			errmsg ? errmsg : "no 'errmsg' given");
-
-	g_free(errmsg);
-
-	purple_debug_info("msim", "msim_error (sesskey=%d): %s\n",
-			session->sesskey, full_errmsg);
-
-	/* Destroy session if fatal. */
-	if (msim_msg_get(msg, "fatal")) {
-		PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-		purple_debug_info("msim", "fatal error, closing\n");
-
-		switch (err) {
-			case MSIM_ERROR_INCORRECT_PASSWORD: /* Incorrect password */
-				reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
-				if (!purple_account_get_remember_password(session->account))
-					purple_account_set_password(session->account, NULL);
-#ifdef MSIM_MAX_PASSWORD_LENGTH
-				if (session->account->password && (strlen(session->account->password) > MSIM_MAX_PASSWORD_LENGTH)) {
-					gchar *suggestion;
-
-					suggestion = g_strdup_printf(_("%s Your password is "
-							"%zu characters, which is longer than the "
-							"maximum length of %d.  Please shorten your "
-							"password at http://profileedit.myspace.com/index.cfm?fuseaction=accountSettings.changePassword and try again."),
-							full_errmsg,
-							strlen(session->account->password),
-							MSIM_MAX_PASSWORD_LENGTH);
-
-					/* Replace full_errmsg. */
-					g_free(full_errmsg);
-					full_errmsg = suggestion;
-				} else {
-					g_free(full_errmsg);
-					full_errmsg = g_strdup(_("Incorrect username or password"));
-				}
-#endif
-				break;
-			case MSIM_ERROR_LOGGED_IN_ELSEWHERE: /* Logged in elsewhere */
-				reason = PURPLE_CONNECTION_ERROR_NAME_IN_USE;
-				if (!purple_account_get_remember_password(session->account))
-					purple_account_set_password(session->account, NULL);
-				break;
-		}
-		purple_connection_error_reason(session->gc, reason, full_errmsg);
-	} else {
-		purple_notify_error(session->account, _("MySpaceIM Error"), full_errmsg, NULL);
-	}
-
-	g_free(full_errmsg);
-
-	return TRUE;
-}
-
-/**
- * Process a message.
- *
- * @param session
- * @param msg A message from the server, ready for processing (possibly with resolved username information attached). Caller frees.
- *
- * @return TRUE if successful. FALSE if processing failed.
- */
-static gboolean
-msim_process(MsimSession *session, MsimMessage *msg)
-{
-	g_return_val_if_fail(session != NULL, FALSE);
-	g_return_val_if_fail(msg != NULL, FALSE);
-
-	if (msim_msg_get_integer(msg, "lc") == 1) {
-		return msim_login_challenge(session, msg);
-	} else if (msim_msg_get_integer(msg, "lc") == 2) {
-		/* return msim_we_are_logged_on(session, msg); */
-		if (msim_is_username_set(session, msg)) {
-			return msim_we_are_logged_on(session);
-		} else {
-			/* No username is set... We'll wait for the callbacks to do their work */
-			/* When they're all done, the last one will call msim_we_are_logged_on() and pick up where we left off */
-			return FALSE;
-		}
-	} else if (msim_msg_get(msg, "bm"))  {
-		return msim_incoming_bm(session, msg);
-	} else if (msim_msg_get(msg, "rid")) {
-		return msim_process_reply(session, msg);
-	} else if (msim_msg_get(msg, "error")) {
-		return msim_error(session, msg);
-	} else if (msim_msg_get(msg, "ka")) {
-		return TRUE;
-	} else {
-		msim_unrecognized(session, msg, "in msim_process");
-		return FALSE;
-	}
-}
-
-/**
- * After a uid is resolved to username, tag it with the username and submit for processing.
- *
- * @param session
- * @param userinfo Response messsage to resolving request.
- * @param data MsimMessage *, the message to attach information to.
- */
-static void
-msim_incoming_resolved(MsimSession *session, const MsimMessage *userinfo,
-		gpointer data)
-{
-	gchar *username;
-	MsimMessage *msg, *body;
-
-	g_return_if_fail(userinfo != NULL);
-
-	body = msim_msg_get_dictionary(userinfo, "body");
-	g_return_if_fail(body != NULL);
-
-	username = msim_msg_get_string(body, "UserName");
-	g_return_if_fail(username != NULL);
-	/* Note: username will be owned by 'msg' below. */
-
-	msg = (MsimMessage *)data;
-	g_return_if_fail(msg != NULL);
-
-	/* TODO: more elegant solution than below. attach whole message? */
-	/* Special elements name beginning with '_', we'll use internally within the
-	 * program (did not come directly from the wire). */
-	msg = msim_msg_append(msg, "_username", MSIM_TYPE_STRING, username); /* This makes 'msg' the owner of 'username' */
-
-	/* TODO: attach more useful information, like ImageURL */
-
-	msim_process(session, msg);
-
-	msim_msg_free(msg);
-	msim_msg_free(body);
-}
-
-/**
- * Preprocess incoming messages, resolving as needed, calling
- * msim_process() when ready to process.
- *
- * @param session
- * @param msg MsimMessage *, freed by caller.
- */
-static gboolean
-msim_preprocess_incoming(MsimSession *session, MsimMessage *msg)
-{
-	g_return_val_if_fail(msg != NULL, FALSE);
-
-	if (msim_msg_get(msg, "bm") && msim_msg_get(msg, "f")) {
-		guint uid;
-		const gchar *username;
-
-		/* 'f' = userid message is from, in buddy messages */
-		uid = msim_msg_get_integer(msg, "f");
-
-		username = msim_uid2username_from_blist(session->account, uid);
-
-		if (username) {
-			/* Know username already, use it. */
-			purple_debug_info("msim", "msim_preprocess_incoming: tagging with _username=%s\n",
-					username);
-			msg = msim_msg_append(msg, "_username", MSIM_TYPE_STRING, g_strdup(username));
-			return msim_process(session, msg);
-
-		} else {
-			gchar *from;
-
-			/* Send lookup request. */
-			/* XXX: where is msim_msg_get_string() freed? make _strdup and _nonstrdup. */
-			purple_debug_info("msim", "msim_incoming: sending lookup, setting up callback\n");
-			from = msim_msg_get_string(msg, "f");
-			msim_lookup_user(session, from, msim_incoming_resolved, msim_msg_clone(msg));
-			g_free(from);
-
-			/* indeterminate */
-			return TRUE;
-		}
-	} else {
-		/* Nothing to resolve - send directly to processing. */
-		return msim_process(session, msg);
-	}
-}
-
-/**
- * Callback when input available.
- *
- * @param gc_uncasted A PurpleConnection pointer.
- * @param source File descriptor.
- * @param cond PURPLE_INPUT_READ
- *
- * Reads the input, and calls msim_preprocess_incoming() to handle it.
- */
-static void
-msim_input_cb(gpointer gc_uncasted, gint source, PurpleInputCondition cond)
-{
-	PurpleConnection *gc;
-	MsimSession *session;
-	gchar *end;
-	int n;
-
-	g_return_if_fail(gc_uncasted != NULL);
-	g_return_if_fail(source >= 0);  /* Note: 0 is a valid fd */
-
-	gc = (PurpleConnection *)(gc_uncasted);
-	session = gc->proto_data;
-
-	/* libpurple/eventloop.h only defines these two */
-	if (cond != PURPLE_INPUT_READ && cond != PURPLE_INPUT_WRITE) {
-		purple_debug_info("msim_input_cb", "unknown condition=%d\n", cond);
-		purple_connection_error_reason (gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("Invalid input condition"));
-		return;
-	}
-
-	g_return_if_fail(cond == PURPLE_INPUT_READ);
-
-	/* Mark down that we got data, so we don't timeout. */
-	session->last_comm = time(NULL);
-
-	/* If approaching end of buffer, reallocate some more memory. */
-	if (session->rxsize < session->rxoff + MSIM_READ_BUF_SIZE) {
-		purple_debug_info("msim",
-			"msim_input_cb: %d-byte read buffer full, rxoff=%d, " "growing by %d bytes\n",
-			session->rxsize, session->rxoff, MSIM_READ_BUF_SIZE);
-			session->rxsize += MSIM_READ_BUF_SIZE;
-			session->rxbuf = g_realloc(session->rxbuf, session->rxsize);
-
-		return;
-	}
-
-	purple_debug_info("msim", "dynamic buffer at %d (max %d), reading up to %d\n",
-			session->rxoff, session->rxsize,
-			MSIM_READ_BUF_SIZE - session->rxoff - 1);
-
-	/* Read into buffer. On Win32, need recv() not read(). session->fd also holds
-	 * the file descriptor, but it sometimes differs from the 'source' parameter.
-	 */
-	n = recv(session->fd,
-		 session->rxbuf + session->rxoff,
-		 session->rxsize - session->rxoff - 1, 0);
-
-	if (n < 0) {
-		gchar *tmp;
-
-		if (errno == EAGAIN)
-			/* No worries */
-			return;
-
-		tmp = g_strdup_printf(_("Lost connection with server: %s"),
-				g_strerror(errno));
-		purple_connection_error_reason(gc,
-				PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-		g_free(tmp);
-		return;
-	} else if (n == 0) {
-		purple_connection_error_reason(gc,
-				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-				_("Server closed the connection"));
-		return;
-	}
-
-	/* Null terminate */
-	purple_debug_info("msim", "msim_input_cb: going to null terminate "
-			"at n=%d\n", n);
-	session->rxbuf[session->rxoff + n] = 0;
-
-#ifdef MSIM_CHECK_EMBEDDED_NULLS
-	/* Check for embedded NULs. I don't handle them, and they shouldn't occur. */
-	if (strlen(session->rxbuf + session->rxoff) != n) {
-		/* Occurs after login, but it is not a null byte. */
-		purple_debug_info("msim", "msim_input_cb: strlen=%d, but read %d bytes"
-				"--null byte encountered?\n",
-				strlen(session->rxbuf + session->rxoff), n);
-		/*purple_connection_error_reason (gc,
-				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-				"Invalid message - null byte on input"); */
-		return;
-	}
-#endif
-
-	session->rxoff += n;
-	purple_debug_info("msim", "msim_input_cb: read=%d\n", n);
-
-#ifdef MSIM_DEBUG_RXBUF
-	purple_debug_info("msim", "buf=<%s>\n", session->rxbuf);
-#endif
-
-	/* Look for \\final\\ end markers. If found, process message. */
-	while((end = strstr(session->rxbuf, MSIM_FINAL_STRING))) {
-		MsimMessage *msg;
-
-#ifdef MSIM_DEBUG_RXBUF
-		purple_debug_info("msim", "in loop: buf=<%s>\n", session->rxbuf);
-#endif
-		*end = 0;
-		msg = msim_parse(session->rxbuf);
-		if (!msg) {
-			purple_debug_info("msim", "msim_input_cb: couldn't parse rxbuf\n");
-			purple_connection_error_reason (gc,
-				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-				_("Unable to parse message"));
-			break;
-		} else {
-			/* Process message and then free it (processing function should
-			 * clone message if it wants to keep it afterwards.) */
-			if (!msim_preprocess_incoming(session, msg)) {
-				msim_msg_dump("msim_input_cb: preprocessing message failed on msg: %s\n", msg);
-			}
-			msim_msg_free(msg);
-		}
-
-		/* Move remaining part of buffer to beginning. */
-		session->rxoff -= strlen(session->rxbuf) + strlen(MSIM_FINAL_STRING);
-		memmove(session->rxbuf, end + strlen(MSIM_FINAL_STRING),
-				session->rxsize - (end + strlen(MSIM_FINAL_STRING) - session->rxbuf));
-
-		/* Clear end of buffer
-		 * memset(end, 0, MSIM_READ_BUF_SIZE - (end - session->rxbuf));
-		 */
-	}
-}
-
-/**
- * Callback when connected. Sets up input handlers.
- *
- * @param data A PurpleConnection pointer.
- * @param source File descriptor.
- * @param error_message
- */
-static void
-msim_connect_cb(gpointer data, gint source, const gchar *error_message)
-{
-	PurpleConnection *gc;
-	MsimSession *session;
-
-	g_return_if_fail(data != NULL);
-
-	gc = (PurpleConnection *)data;
-	session = (MsimSession *)gc->proto_data;
-
-	if (source < 0) {
-		gchar *tmp = g_strdup_printf(_("Unable to connect: %s"),
-				error_message);
-		purple_connection_error_reason (gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-			g_free(tmp);
-		return;
-	}
-
-	session->fd = source;
-
-	gc->inpa = purple_input_add(source, PURPLE_INPUT_READ, msim_input_cb, gc);
-}
-
-/**
- * Start logging in to the MSIM servers.
- *
- * @param acct Account information to use to login.
- */
-static void
-msim_login(PurpleAccount *acct)
-{
-	PurpleConnection *gc;
-	const gchar *host;
-	int port;
-
-	g_return_if_fail(acct != NULL);
-	g_return_if_fail(acct->username != NULL);
-
-	purple_debug_info("msim", "logging in %s\n", acct->username);
-
-	gc = purple_account_get_connection(acct);
-	gc->proto_data = msim_session_new(acct);
-	gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_URLDESC;
-
-	/*
-	 * Lets wipe out our local list of blocked buddies.  We'll get a
-	 * list of all blocked buddies from the server, and we shouldn't
-	 * have stuff in the local list that isn't on the server list.
-	 */
-	while (acct->deny != NULL)
-		purple_privacy_deny_remove(acct, acct->deny->data, TRUE);
-
-	/* 1. connect to server */
-	purple_connection_update_progress(gc, _("Connecting"),
-								  0,   /* which connection step this is */
-								  4);  /* total number of steps */
-
-	host = purple_account_get_string(acct, "server", MSIM_SERVER);
-	port = purple_account_get_int(acct, "port", MSIM_PORT);
-
-	/* From purple.sf.net/api:
-	 * """Note that this function name can be misleading--although it is called
-	 * "proxy connect," it is used for establishing any outgoing TCP connection,
-	 * whether through a proxy or not.""" */
-
-	/* Calls msim_connect_cb when connected. */
-	if (!purple_proxy_connect(gc, acct, host, port, msim_connect_cb, gc)) {
-		/* TODO: try other ports if in auto mode, then save
-		 * working port and try that first next time. */
-		purple_connection_error_reason (gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("Unable to connect"));
-		return;
-	}
-}
-
-static void
-msim_buddy_free(PurpleBuddy *buddy)
-{
-	msim_user_free(purple_buddy_get_protocol_data(buddy));
-	purple_buddy_set_protocol_data(buddy, NULL);
-}
-
-/**
- * Close the connection.
- *
- * @param gc The connection.
- */
-static void
-msim_close(PurpleConnection *gc)
-{
-	GSList *buddies;
-	MsimSession *session;
-
-	if (gc == NULL) {
-		return;
-	}
-
-	/*
-	 * Free our protocol-specific buddy data.  It almost seems like libpurple
-	 * should call our buddy_free prpl callback so that we don't need to do
-	 * this... but it doesn't, so we do.
-	 */
-	buddies = purple_find_buddies(purple_connection_get_account(gc), NULL);
-	while (buddies != NULL) {
-		msim_buddy_free(buddies->data);
-		buddies = g_slist_delete_link(buddies, buddies);
-	}
-
-	session = (MsimSession *)gc->proto_data;
-	if (session == NULL)
-		return;
-
-	gc->proto_data = NULL;
-
-	if (session->gc->inpa) {
-		purple_input_remove(session->gc->inpa);
-	}
-	if (session->fd >= 0) {
-		close(session->fd);
-		session->fd = -1;
-	}
-
-	msim_session_destroy(session);
-}
-
-/**
- * Schedule an IM to be sent once the user ID is looked up.
- *
- * @param gc Connection.
- * @param who A user id, email, or username to send the message to.
- * @param message Instant message text to send.
- * @param flags Flags.
- *
- * @return 1 if successful or postponed, -1 if failed
- *
- * Allows sending to a user by username, email address, or userid. If
- * a username or email address is given, the userid must be looked up.
- * This function does that by calling msim_postprocess_outgoing().
- */
-static int
-msim_send_im(PurpleConnection *gc, const gchar *who, const gchar *message,
-		PurpleMessageFlags flags)
-{
-	MsimSession *session;
-	gchar *message_msim;
-	int rc;
-
-	g_return_val_if_fail(gc != NULL, -1);
-	g_return_val_if_fail(who != NULL, -1);
-	g_return_val_if_fail(message != NULL, -1);
-
-	/* 'flags' has many options, not used here. */
-
-	session = (MsimSession *)gc->proto_data;
-
-	message_msim = html_to_msim_markup(session, message);
-
-	if (msim_send_bm(session, who, message_msim, MSIM_BM_ACTION_OR_IM_DELAYABLE)) {
-		/* Return 1 to have Purple show this IM as being sent, 0 to not. I always
-		 * return 1 even if the message could not be sent, since I don't know if
-		 * it has failed yet--because the IM is only sent after the userid is
-		 * retrieved from the server (which happens after this function returns).
-		 * If an error does occur, it should be logged to the IM window.
-		 */
-		rc = 1;
-	} else {
-		rc = -1;
-	}
-
-	g_free(message_msim);
-
-	return rc;
-}
-
-/**
- * Handle when our user starts or stops typing to another user.
- *
- * @param gc
- * @param name The buddy name to which our user is typing to
- * @param state PURPLE_TYPING, PURPLE_TYPED, PURPLE_NOT_TYPING
- *
- * @return 0
- */
-static unsigned int
-msim_send_typing(PurpleConnection *gc, const gchar *name,
-		PurpleTypingState state)
-{
-	const gchar *typing_str;
-	MsimSession *session;
-
-	g_return_val_if_fail(gc != NULL, 0);
-	g_return_val_if_fail(name != NULL, 0);
-
-	session = (MsimSession *)gc->proto_data;
-
-	switch (state) {
-		case PURPLE_TYPING:
-			typing_str = "%typing%";
-			break;
-
-		case PURPLE_TYPED:
-		case PURPLE_NOT_TYPING:
-		default:
-			typing_str = "%stoptyping%";
-			break;
-	}
-
-	purple_debug_info("msim", "msim_send_typing(%s): %d (%s)\n", name, state, typing_str);
-	msim_send_bm(session, name, typing_str, MSIM_BM_ACTION_OR_IM_INSTANT);
-	return 0;
-}
-
-/**
- * Callback for msim_get_info(), for when user info is received.
- */
-static void
-msim_get_info_cb(MsimSession *session, const MsimMessage *user_info_msg,
-		gpointer data)
-{
-	MsimMessage *msg;
-	gchar *username;
-	PurpleNotifyUserInfo *user_info;
-	MsimUser *user;
-
-	/* Get user{name,id} from msim_get_info, passed as an MsimMessage for
-	   orthogonality. */
-	msg = (MsimMessage *)data;
-	g_return_if_fail(msg != NULL);
-
-	username = msim_msg_get_string(msg, "user");
-	if (!username) {
-		purple_debug_info("msim", "msim_get_info_cb: no 'user' in msg\n");
-		return;
-	}
-
-	msim_msg_free(msg);
-	purple_debug_info("msim", "msim_get_info_cb: got for user: %s\n", username);
-
-	user = msim_find_user(session, username);
-
-	if (!user) {
-		/* User isn't on blist, create a temporary user to store info. */
-		user = g_new0(MsimUser, 1);
-		user->temporary_user = TRUE;
-	}
-
-	/* Update user structure with new information */
-	msim_store_user_info(session, user_info_msg, user);
-
-	user_info = purple_notify_user_info_new();
-
-	/* Append data from MsimUser to PurpleNotifyUserInfo for display, full */
-	msim_append_user_info(session, user_info, user, TRUE);
-
-	purple_notify_userinfo(session->gc, username, user_info, NULL, NULL);
-	purple_debug_info("msim", "msim_get_info_cb: username=%s\n", username);
-
-	purple_notify_user_info_destroy(user_info);
-
-	if (user->temporary_user)
-		msim_user_free(user);
-	g_free(username);
-}
-
-/**
- * Retrieve a user's profile.
- * @param username Username, user ID, or email address to lookup.
- */
-static void
-msim_get_info(PurpleConnection *gc, const gchar *username)
-{
-	MsimSession *session;
-	MsimUser *user;
-	gchar *user_to_lookup;
-	MsimMessage *user_msg;
-
-	g_return_if_fail(gc != NULL);
-	g_return_if_fail(username != NULL);
-
-	session = (MsimSession *)gc->proto_data;
-
-	/* Obtain uid of buddy. */
-	user = msim_find_user(session, username);
-
-	/* If is on buddy list, lookup by uid since it is faster. */
-	if (user && user->id) {
-		user_to_lookup = g_strdup_printf("%d", user->id);
-	} else {
-		/* Looking up buddy not on blist. Lookup by whatever user entered. */
-		user_to_lookup = g_strdup(username);
-	}
-
-	/* Pass the username to msim_get_info_cb(), because since we lookup
-	 * by userid, the userinfo message will only contain the uid (not
-	 * the username) but it would be useful to display the username too.
-	 */
-	user_msg = msim_msg_new(
-			"user", MSIM_TYPE_STRING, g_strdup(username),
-			NULL);
-	purple_debug_info("msim", "msim_get_info, setting up lookup, user=%s\n", username);
-
-	msim_lookup_user(session, user_to_lookup, msim_get_info_cb, user_msg);
-
-	g_free(user_to_lookup);
-}
-
-/**
- * Set status using an MSIM_STATUS_CODE_* value.
- * @param status_code An MSIM_STATUS_CODE_* value.
- * @param statstring Status string, must be a dynamic string (will be freed by msim_send).
- */
-static void
-msim_set_status_code(MsimSession *session, guint status_code, gchar *statstring)
-{
-	g_return_if_fail(statstring != NULL);
-
-	purple_debug_info("msim", "msim_set_status_code: going to set status to code=%d,str=%s\n",
-			status_code, statstring);
-
-	if (!msim_send(session,
-			"status", MSIM_TYPE_INTEGER, status_code,
-			"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-			"statstring", MSIM_TYPE_STRING, statstring,
-			"locstring", MSIM_TYPE_STRING, g_strdup(""),
-			NULL))
-	{
-		purple_debug_info("msim", "msim_set_status: failed to set status\n");
-	}
-}
-
-/**
- * Set your status - callback for when user manually sets it.
- */
-static void
-msim_set_status(PurpleAccount *account, PurpleStatus *status)
-{
-	PurpleStatusType *type;
-	PurplePresence *pres;
-	MsimSession *session;
-	guint status_code;
-	const gchar *message;
-	gchar *stripped;
-	gchar *unrecognized_msg;
-
-	session = (MsimSession *)account->gc->proto_data;
-
-	type = purple_status_get_type(status);
-	pres = purple_status_get_presence(status);
-
-	switch (purple_status_type_get_primitive(type)) {
-		case PURPLE_STATUS_AVAILABLE:
-			purple_debug_info("msim", "msim_set_status: available (%d->%d)\n", PURPLE_STATUS_AVAILABLE,
-					MSIM_STATUS_CODE_ONLINE);
-			status_code = MSIM_STATUS_CODE_ONLINE;
-			break;
-
-		case PURPLE_STATUS_INVISIBLE:
-			purple_debug_info("msim", "msim_set_status: invisible (%d->%d)\n", PURPLE_STATUS_INVISIBLE,
-					MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN);
-			status_code = MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN;
-			break;
-
-		case PURPLE_STATUS_AWAY:
-			purple_debug_info("msim", "msim_set_status: away (%d->%d)\n", PURPLE_STATUS_AWAY,
-					MSIM_STATUS_CODE_AWAY);
-			status_code = MSIM_STATUS_CODE_AWAY;
-			break;
-
-		default:
-			purple_debug_info("msim", "msim_set_status: unknown "
-					"status interpreting as online");
-			status_code = MSIM_STATUS_CODE_ONLINE;
-
-			unrecognized_msg = g_strdup_printf("msim_set_status, unrecognized status type: %d\n",
-					purple_status_type_get_primitive(type));
-			msim_unrecognized(session, NULL, unrecognized_msg);
-			g_free(unrecognized_msg);
-
-			break;
-	}
-
-	message = purple_status_get_attr_string(status, "message");
-
-	/* Status strings are plain text. */
-	if (message != NULL)
-		stripped = purple_markup_strip_html(message);
-	else
-		stripped = g_strdup("");
-
-	msim_set_status_code(session, status_code, stripped);
-
-	/* If we should be idle, set that status. Time is irrelevant here. */
-	if (purple_presence_is_idle(pres) && status_code != MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN)
-		msim_set_idle(account->gc, 1);
-}
-
-/**
- * Go idle.
- */
-static void
-msim_set_idle(PurpleConnection *gc, int time)
-{
-	MsimSession *session;
-	PurpleStatus *status;
-
-	g_return_if_fail(gc != NULL);
-
-	session = (MsimSession *)gc->proto_data;
-
-	status = purple_account_get_active_status(session->account);
-
-	if (time == 0) {
-		/* Going back from idle. In msim, idle is mutually exclusive
-		 * from the other states (you can only be away or idle, but not
-		 * both, for example), so by going non-idle I go back to what
-		 * libpurple says I should be.
-		 */
-		msim_set_status(session->account, status);
-	} else {
-		const gchar *message;
-		gchar *stripped;
-
-		/* Set the idle message to the status message from the real
-		 * current status.
-		 */
-		message = purple_status_get_attr_string(status, "message");
-		if (message != NULL)
-			stripped = purple_markup_strip_html(message);
-		else
-			stripped = g_strdup("");
-
-		/* msim doesn't support idle time, so just go idle */
-		msim_set_status_code(session, MSIM_STATUS_CODE_IDLE, stripped);
-	}
-}
-
-/**
- * @return TRUE if everything was ok, FALSE if something went awry.
- */
-static gboolean
-msim_update_blocklist_for_buddy(MsimSession *session, const char *name, gboolean allow, gboolean block)
-{
-	MsimMessage *msg;
-	GList *list;
-
-	list = NULL;
-	list = g_list_prepend(list, allow ? "a+" : "a-");
-	list = g_list_prepend(list, "<uid>");
-	list = g_list_prepend(list, block ? "b+" : "b-");
-	list = g_list_prepend(list, "<uid>");
-	list = g_list_reverse(list);
-
-	msg = msim_msg_new(
-			"blocklist", MSIM_TYPE_BOOLEAN, TRUE,
-			"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-			/* TODO: MsimMessage lists. Currently <uid> isn't replaced in lists. */
-			/* "idlist", MSIM_TYPE_STRING, g_strdup("a-|<uid>|b-|<uid>"), */
-			"idlist", MSIM_TYPE_LIST, list,
-			NULL);
-
-	if (!msim_postprocess_outgoing(session, msg, name, "idlist", NULL)) {
-		purple_debug_error("myspace",
-				"blocklist command failed for %s, allow=%d, block=%d\n",
-				name, allow, block);
-		msim_msg_free(msg);
-		return FALSE;
-	}
-
-	msim_msg_free(msg);
-
-	return TRUE;
-}
-
-/**
- * Add a buddy to user's buddy list.
- */
-static void
-msim_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
-{
-	MsimSession *session;
-	MsimMessage *msg;
-	MsimMessage *msg_persist;
-	MsimMessage *body;
-	const char *name, *gname;
-
-	session = (MsimSession *)gc->proto_data;
-	name = purple_buddy_get_name(buddy);
-	gname = group ? purple_group_get_name(group) : NULL;
-
-	if (msim_get_user_from_buddy(buddy, FALSE) != NULL)
-		return;
-
-	purple_debug_info("msim", "msim_add_buddy: want to add %s to %s\n",
-			name, gname ? gname : "(no group)");
-
-	msg = msim_msg_new(
-			"addbuddy", MSIM_TYPE_BOOLEAN, TRUE,
-			"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-			/* "newprofileid" will be inserted here with uid. */
-			"reason", MSIM_TYPE_STRING, g_strdup(""),
-			NULL);
-
-	if (!msim_postprocess_outgoing(session, msg, name, "newprofileid", "reason")) {
-		purple_notify_error(NULL, NULL, _("Failed to add buddy"), _("'addbuddy' command failed."));
-		msim_msg_free(msg);
-		return;
-	}
-	msim_msg_free(msg);
-
-	/* TODO: if addbuddy fails ('error' message is returned), delete added buddy from
-	 * buddy list since Purple adds it locally. */
-
-	body = msim_msg_new(
-			"ContactID", MSIM_TYPE_STRING, g_strdup("<uid>"),
-			"GroupName", MSIM_TYPE_STRING, g_strdup(gname),
-			"Position", MSIM_TYPE_INTEGER, 1000,
-			"Visibility", MSIM_TYPE_INTEGER, 1,
-			"NickName", MSIM_TYPE_STRING, g_strdup(""),
-			"NameSelect", MSIM_TYPE_INTEGER, 0,
-			NULL);
-
-	/* TODO: Update blocklist. */
-
-	msg_persist = msim_msg_new(
-		"persist", MSIM_TYPE_INTEGER, 1,
-		"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-		"cmd", MSIM_TYPE_INTEGER, MSIM_CMD_BIT_ACTION | MSIM_CMD_PUT,
-		"dsn", MSIM_TYPE_INTEGER, MC_CONTACT_INFO_DSN,
-		"uid", MSIM_TYPE_INTEGER, session->userid,
-		"lid", MSIM_TYPE_INTEGER, MC_CONTACT_INFO_LID,
-		/* TODO: Use msim_new_reply_callback to get rid. */
-		"rid", MSIM_TYPE_INTEGER, session->next_rid++,
-		"body", MSIM_TYPE_DICTIONARY, body,
-		NULL);
-
-	if (!msim_postprocess_outgoing(session, msg_persist, name, "body", NULL))
-	{
-		purple_notify_error(NULL, NULL, _("Failed to add buddy"), _("persist command failed"));
-		msim_msg_free(msg_persist);
-		return;
-	}
-	msim_msg_free(msg_persist);
-
-	/* Add to allow list, remove from block list */
-	msim_update_blocklist_for_buddy(session, name, TRUE, FALSE);
-}
-
-/**
- * Remove a buddy from the user's buddy list.
- */
-static void
-msim_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
-{
-	MsimSession *session;
-	MsimMessage *delbuddy_msg;
-	MsimMessage *persist_msg;
-	const char *name;
-
-	session = (MsimSession *)gc->proto_data;
-	name = purple_buddy_get_name(buddy);
-
-	delbuddy_msg = msim_msg_new(
-				"delbuddy", MSIM_TYPE_BOOLEAN, TRUE,
-				"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-				/* 'delprofileid' with uid will be inserted here. */
-				NULL);
-
-	if (!msim_postprocess_outgoing(session, delbuddy_msg, name, "delprofileid", NULL)) {
-		purple_notify_error(NULL, NULL, _("Failed to remove buddy"), _("'delbuddy' command failed"));
-		msim_msg_free(delbuddy_msg);
-		return;
-	}
-	msim_msg_free(delbuddy_msg);
-
-	persist_msg = msim_msg_new(
-			"persist", MSIM_TYPE_INTEGER, 1,
-			"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-			"cmd", MSIM_TYPE_INTEGER, MSIM_CMD_BIT_ACTION | MSIM_CMD_DELETE,
-			"dsn", MSIM_TYPE_INTEGER, MD_DELETE_BUDDY_DSN,
-			"lid", MSIM_TYPE_INTEGER, MD_DELETE_BUDDY_LID,
-			"uid", MSIM_TYPE_INTEGER, session->userid,
-			"rid", MSIM_TYPE_INTEGER, session->next_rid++,
-			/* <uid> will be replaced by postprocessing */
-			"body", MSIM_TYPE_STRING, g_strdup("ContactID=<uid>"),
-			NULL);
-
-	if (!msim_postprocess_outgoing(session, persist_msg, name, "body", NULL)) {
-		purple_notify_error(NULL, NULL, _("Failed to remove buddy"), _("persist command failed"));
-		msim_msg_free(persist_msg);
-		return;
-	}
-	msim_msg_free(persist_msg);
-
-	/*
-	 * Remove from our approve list and from our block list (this
-	 * doesn't seem like it would be necessary, but the official client
-	 * does it)
-	 */
-	if (!msim_update_blocklist_for_buddy(session, name, FALSE, FALSE)) {
-		purple_notify_error(NULL, NULL,
-				_("Failed to remove buddy"), _("blocklist command failed"));
-		return;
-	}
-	msim_buddy_free(buddy);
-}
-
-/**
- * Remove a buddy from the user's buddy list and add them to the block list.
- */
-static void
-msim_add_deny(PurpleConnection *gc, const char *name)
-{
-	MsimSession *session;
-	MsimMessage *msg, *body;
-
-	session = (MsimSession *)gc->proto_data;
-
-	/* Remove from buddy list */
-	msg = msim_msg_new(
-			"delbuddy", MSIM_TYPE_BOOLEAN, TRUE,
-			"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-			/* 'delprofileid' with uid will be inserted here. */
-			NULL);
-	if (!msim_postprocess_outgoing(session, msg, name, "delprofileid", NULL))
-		purple_debug_error("myspace", "delbuddy command failed\n");
-	msim_msg_free(msg);
-
-	/* Remove from our approve list and add to our block list */
-	msim_update_blocklist_for_buddy(session, name, FALSE, TRUE);
-
-	/*
-	 * Add the buddy to our list of blocked contacts, so we know they
-	 * are blocked if we log in with another client
-	 */
-	body = msim_msg_new(
-			"ContactID", MSIM_TYPE_STRING, g_strdup("<uid>"),
-			"Visibility", MSIM_TYPE_INTEGER, 2,
-			NULL);
-	msg = msim_msg_new(
-			"persist", MSIM_TYPE_INTEGER, 1,
-			"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-			"cmd", MSIM_TYPE_INTEGER, MSIM_CMD_BIT_ACTION | MSIM_CMD_PUT,
-			"dsn", MSIM_TYPE_INTEGER, MC_CONTACT_INFO_DSN,
-			"lid", MSIM_TYPE_INTEGER, MC_CONTACT_INFO_LID,
-			"rid", MSIM_TYPE_INTEGER, session->next_rid++,
-			"body", MSIM_TYPE_DICTIONARY, body,
-			NULL);
-	if (!msim_postprocess_outgoing(session, msg, name, "body", NULL))
-		purple_debug_error("myspace", "add to block list command failed\n");
-	msim_msg_free(msg);
-
-	/*
-	 * TODO: MySpace doesn't allow blocked buddies on our buddy list,
-	 *       do they?  If not then we need to remove the buddy from
-	 *       libpurple's buddy list.
-	 */
-}
-
-/**
- * Remove a buddy from the user's block list.
- */
-static void
-msim_rem_deny(PurpleConnection *gc, const char *name)
-{
-	MsimSession *session;
-	MsimMessage *msg, *body;
-
-	session = (MsimSession *)gc->proto_data;
-
-	/*
-	 * Remove from our list of blocked contacts, so we know they
-	 * are no longer blocked if we log in with another client
-	 */
-	body = msim_msg_new(
-			"ContactID", MSIM_TYPE_STRING, g_strdup("<uid>"),
-			NULL);
-	msg = msim_msg_new(
-			"persist", MSIM_TYPE_INTEGER, 1,
-			"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-			"cmd", MSIM_TYPE_INTEGER, MSIM_CMD_BIT_ACTION | MSIM_CMD_DELETE,
-			"dsn", MSIM_TYPE_INTEGER, MC_DELETE_CONTACT_INFO_DSN,
-			"lid", MSIM_TYPE_INTEGER, MC_DELETE_CONTACT_INFO_LID,
-			"rid", MSIM_TYPE_INTEGER, session->next_rid++,
-			"body", MSIM_TYPE_DICTIONARY, body,
-			NULL);
-	if (!msim_postprocess_outgoing(session, msg, name, "body", NULL))
-		purple_debug_error("myspace", "remove from block list command failed\n");
-	msim_msg_free(msg);
-
-	/* Remove from our approve list and our block list */
-	msim_update_blocklist_for_buddy(session, name, FALSE, FALSE);
-}
-
-/**
- * Returns a string of a username in canonical form. Basically removes all the
- * spaces, lowercases the string, and looks up user IDs to usernames.
- * Normalizing tom, TOM, Tom, and 6221 wil all return 'tom'.
- *
- * Borrowed this code from oscar_normalize. Added checking for
- * "if userid, get name before normalizing"
- */
-static const char *msim_normalize(const PurpleAccount *account, const char *str) {
-	static char normalized[BUF_LEN];
-	char *tmp1, *tmp2;
-	int i, j;
-	guint id;
-
-	g_return_val_if_fail(str != NULL, NULL);
-
-	if (msim_is_userid(str)) {
-		/* Have user ID, we need to get their username first :) */
-		const char *username;
-
-		/* If the account does not exist, we can't look up the user. */
-		if (!account || !account->gc)
-			return str;
-
-		id = atol(str);
-		username = msim_uid2username_from_blist((PurpleAccount *)account, id);
-		if (!username) {
-			/* Not in buddy list... scheisse... TODO: Manual Lookup! Bug #4631 */
-			/* Note: manual lookup using msim_lookup_user() is a problem inside
-			 * msim_normalize(), because msim_lookup_user() calls a callback function
-			 * when the user information has been looked up, but msim_normalize() expects
-			 * the result immediately. */
-			strncpy(normalized, str, BUF_LEN);
-		} else {
-			strncpy(normalized, username, BUF_LEN);
-		}
-	} else {
-		/* Have username. */
-		strncpy(normalized, str, BUF_LEN);
-	}
-
-	/* Strip spaces. */
-	for (i=0, j=0; normalized[j]; j++) {
-		if (normalized[j] != ' ')
-			normalized[i++] = normalized[j];
-	}
-	normalized[i] = '\0';
-
-	/* Lowercase and perform UTF-8 normalization. */
-	tmp1 = g_utf8_strdown(normalized, -1);
-	tmp2 = g_utf8_normalize(tmp1, -1, G_NORMALIZE_DEFAULT);
-	g_snprintf(normalized, sizeof(normalized), "%s", tmp2);
-	g_free(tmp2);
-	g_free(tmp1);
-
-	/* TODO: re-add caps and spacing back to what the user wanted.
-	 * User can format their own names, for example 'msimprpl' is shown
-	 * as 'MsIm PrPl' in the official client.
-	 *
-	 * TODO: file a ticket to add this enhancement.
-	 */
-
-	return normalized;
-}
-
-/**
- * Return whether the buddy can be messaged while offline.
- *
- * The protocol supports offline messages in just the same way as online
- * messages.
- */
-static gboolean
-msim_offline_message(const PurpleBuddy *buddy)
-{
-	return TRUE;
-}
-
-/**
- * Send raw data to the server, possibly with embedded NULs.
- *
- * Used in prpl_info struct, so that plugins can have the most possible
- * control of what is sent over the connection. Inside this prpl,
- * msim_send_raw() is used, since it sends NUL-terminated strings (easier).
- *
- * @param gc PurpleConnection
- * @param buf Buffer to send
- * @param total_bytes Size of buffer to send
- *
- * @return Bytes successfully sent, or -1 on error.
- */
-/*
- * TODO: This needs to do non-blocking writes and use a watcher to check
-  *      when the fd is available to be written to.
- */
-static int
-msim_send_really_raw(PurpleConnection *gc, const char *buf, int total_bytes)
-{
-	int total_bytes_sent;
-	MsimSession *session;
-
-	g_return_val_if_fail(gc != NULL, -1);
-	g_return_val_if_fail(buf != NULL, -1);
-	g_return_val_if_fail(total_bytes >= 0, -1);
-
-	session = (MsimSession *)gc->proto_data;
-
-	/* Loop until all data is sent, or a failure occurs. */
-	total_bytes_sent = 0;
-	do {
-		int bytes_sent;
-
-		bytes_sent = send(session->fd, buf + total_bytes_sent,
-				total_bytes - total_bytes_sent, 0);
-
-		if (bytes_sent < 0) {
-			purple_debug_info("msim", "msim_send_raw(%s): send() failed: %s\n",
-					buf, g_strerror(errno));
-			return total_bytes_sent;
-		}
-		total_bytes_sent += bytes_sent;
-
-	} while(total_bytes_sent < total_bytes);
-
-	return total_bytes_sent;
-}
-
-/**
- * Send raw data (given as a NUL-terminated string) to the server.
- *
- * @param session
- * @param msg The raw data to send, in a NUL-terminated string.
- *
- * @return TRUE if succeeded, FALSE if not.
- *
- */
-gboolean
-msim_send_raw(MsimSession *session, const gchar *msg)
-{
-	size_t len;
-
-	g_return_val_if_fail(msg != NULL, FALSE);
-
-	purple_debug_info("msim", "msim_send_raw: writing <%s>\n", msg);
-	len = strlen(msg);
-
-	return msim_send_really_raw(session->gc, msg, len) == (int)len;
-}
-
-static GHashTable *
-msim_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;
-}
-
-/**
- * Callbacks called by Purple, to access this plugin.
- */
-static PurplePluginProtocolInfo prpl_info = {
-	/* options */
-	  OPT_PROTO_USE_POINTSIZE        /* specify font size in sane point size */
-	| OPT_PROTO_MAIL_CHECK,
-
-	/* | OPT_PROTO_IM_IMAGE - TODO: direct images. */
-	NULL,              /* user_splits */
-	NULL,              /* protocol_options */
-	NO_BUDDY_ICONS,    /* icon_spec - TODO: eventually should add this */
-	msim_list_icon,    /* list_icon */
-	NULL,              /* list_emblems */
-	msim_status_text,  /* status_text */
-	msim_tooltip_text, /* tooltip_text */
-	msim_status_types, /* status_types */
-	msim_blist_node_menu,  /* blist_node_menu */
-	NULL,              /* chat_info */
-	NULL,              /* chat_info_defaults */
-	msim_login,        /* login */
-	msim_close,        /* close */
-	msim_send_im,      /* send_im */
-	NULL,              /* set_info */
-	msim_send_typing,  /* send_typing */
-	msim_get_info,     /* get_info */
-	msim_set_status,   /* set_status */
-	msim_set_idle,     /* set_idle */
-	NULL,              /* change_passwd */
-	msim_add_buddy,    /* add_buddy */
-	NULL,              /* add_buddies */
-	msim_remove_buddy, /* remove_buddy */
-	NULL,              /* remove_buddies */
-	NULL,              /* add_permit */
-	msim_add_deny,     /* add_deny */
-	NULL,              /* rem_permit */
-	msim_rem_deny,     /* rem_deny */
-	NULL,              /* set_permit_deny */
-	NULL,              /* join_chat */
-	NULL,              /* reject chat invite */
-	NULL,              /* get_chat_name */
-	NULL,              /* chat_invite */
-	NULL,              /* chat_leave */
-	NULL,              /* chat_whisper */
-	NULL,              /* chat_send */
-	NULL,              /* keepalive */
-	NULL,              /* register_user */
-	NULL,              /* get_cb_info */
-	NULL,              /* get_cb_away */
-	NULL,              /* alias_buddy */
-	NULL,              /* group_buddy */
-	NULL,              /* rename_group */
-	msim_buddy_free,   /* buddy_free */
-	NULL,              /* convo_closed */
-	msim_normalize,    /* normalize */
-	NULL,              /* set_buddy_icon */
-	NULL,              /* remove_group */
-	NULL,              /* get_cb_real_name */
-	NULL,              /* set_chat_topic */
-	NULL,              /* find_blist_chat */
-	NULL,              /* roomlist_get_list */
-	NULL,              /* roomlist_cancel */
-	NULL,              /* roomlist_expand_category */
-	NULL,              /* can_receive_file */
-	NULL,              /* send_file */
-	NULL,              /* new_xfer */
-	msim_offline_message,  /* offline_message */
-	NULL,              /* whiteboard_prpl_ops */
-	msim_send_really_raw,  /* send_raw */
-	NULL,                  /* roomlist_room_serialize */
-	NULL,                  /* unregister_user */
-	msim_send_attention,   /* send_attention */
-	msim_attention_types,  /* attention_types */
-	sizeof(PurplePluginProtocolInfo), /* struct_size */
-	msim_get_account_text_table,              /* get_account_text_table */
-	NULL,                   /* initiate_media */
-	NULL,                   /* get_media_caps */
-	NULL,                   /* get_moods */
-	NULL,                   /* set_public_alias */
-	NULL,                   /* get_public_alias */
-	NULL,                   /* add_buddy_with_invite */
-	NULL                    /* add_buddies_with_invite */
-};
-
-/**
- * Load the plugin.
- */
-static gboolean
-msim_load(PurplePlugin *plugin)
-{
-	/* If compiled to use RC4 from libpurple, check if it is really there. */
-	if (!purple_ciphers_find_cipher("rc4")) {
-		purple_debug_error("msim", "rc4 not in libpurple, but it is required - not loading MySpaceIM plugin!\n");
-		purple_notify_error(plugin, _("Missing Cipher"),
-				_("The RC4 cipher could not be found"),
-				_("Upgrade "
-					"to a libpurple with RC4 support (>= 2.0.1). MySpaceIM "
-					"plugin will not be loaded."));
-		return FALSE;
-	}
-	return TRUE;
-}
-
-/**
- * Called when friends have been imported to buddy list on server.
- */
-static void
-msim_import_friends_cb(MsimSession *session, const MsimMessage *reply, gpointer user_data)
-{
-	MsimMessage *body;
-	gchar *completed;
-
-	/* Check if the friends were imported successfully. */
-	body = msim_msg_get_dictionary(reply, "body");
-	g_return_if_fail(body != NULL);
-	completed = msim_msg_get_string(body, "Completed");
-	msim_msg_free(body);
-	g_return_if_fail(completed != NULL);
-	if (!g_str_equal(completed, "True"))
-	{
-		purple_debug_info("msim_import_friends_cb",
-				"failed to import friends: %s", completed);
-		purple_notify_error(session->account, _("Add friends from MySpace.com"),
-				_("Importing friends failed"), NULL);
-		g_free(completed);
-		return;
-	}
-	g_free(completed);
-
-	purple_debug_info("msim_import_friends_cb",
-			"added friends to server-side buddy list, requesting new contacts from server");
-
-	msim_get_contact_list(session, MSIM_CONTACT_LIST_IMPORT_ALL_FRIENDS);
-
-	/* TODO: show, X friends have been added */
-}
-
-/**
- * Import friends from myspace.com.
- */
-static void msim_import_friends(PurplePluginAction *action)
-{
-	PurpleConnection *gc;
-	MsimSession *session;
-	gchar *group_name;
-
-	gc = (PurpleConnection *)action->context;
-	session = (MsimSession *)gc->proto_data;
-
-	group_name = "MySpace Friends";
-
-	g_return_if_fail(msim_send(session,
-			"persist", MSIM_TYPE_INTEGER, 1,
-			"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-			"cmd", MSIM_TYPE_INTEGER, MSIM_CMD_PUT,
-			"dsn", MSIM_TYPE_INTEGER, MC_IMPORT_ALL_FRIENDS_DSN,
-			"lid", MSIM_TYPE_INTEGER, MC_IMPORT_ALL_FRIENDS_LID,
-			"uid", MSIM_TYPE_INTEGER, session->userid,
-			"rid", MSIM_TYPE_INTEGER,
-				msim_new_reply_callback(session, msim_import_friends_cb, NULL),
-			"body", MSIM_TYPE_STRING,
-				g_strdup_printf("GroupName=%s", group_name),
-			NULL));
-}
-
-/**
- * Actions menu for account.
- */
-static GList *
-msim_actions(PurplePlugin *plugin, gpointer context /* PurpleConnection* */)
-{
-	GList *menu;
-	PurplePluginAction *act;
-
-	menu = NULL;
-
-#if 0
-	/* TODO: find out how */
-	act = purple_plugin_action_new(_("Find people..."), msim_);
-	menu = g_list_append(menu, act);
-
-	act = purple_plugin_action_new(_("Change IM name..."), NULL);
-	menu = g_list_append(menu, act);
-#endif
-
-	act = purple_plugin_action_new(_("Add friends from MySpace.com"), msim_import_friends);
-	menu = g_list_append(menu, act);
-
-	return menu;
-}
-
-/**
- * Based on MSN's plugin info comments.
- */
-static PurplePluginInfo info = {
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                           /**< type           */
-	NULL,                                             /**< ui_requirement */
-	0,                                                /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                          /**< priority       */
-
-	"prpl-myspace",                                   /**< id             */
-	"MySpaceIM",                                      /**< name           */
-	MSIM_PRPL_VERSION_STRING,                         /**< version        */
-	                                                  /**  summary        */
-	"MySpaceIM Protocol Plugin",
-	                                                  /**  description    */
-	"MySpaceIM Protocol Plugin",
-	"Jeff Connelly <jeff2@soc.pidgin.im>",            /**< author         */
-	"http://developer.pidgin.im/wiki/MySpaceIM/",     /**< homepage       */
-
-	msim_load,                                        /**< load           */
-	NULL,                                             /**< unload         */
-	NULL,                                             /**< destroy        */
-	NULL,                                             /**< ui_info        */
-	&prpl_info,                                       /**< extra_info     */
-	NULL,                                             /**< prefs_info     */
-	msim_actions,                                     /**< msim_actions   */
-	NULL,                                             /**< reserved1      */
-	NULL,                                             /**< reserved2      */
-	NULL,                                             /**< reserved3      */
-	NULL                                              /**< reserved4      */
-};
-
-#ifdef MSIM_SELF_TEST
-/*
- * Test functions.
- * Used to test or try out the internal workings of msimprpl. If you're reading
- * this code for the first time, these functions can be instructive in learning
- * how msimprpl is architected.
- */
-
-/**
- * Test MsimMessage for basic functionality.
- */
-static int
-msim_test_msg(void)
-{
-	MsimMessage *msg, *msg_cloned, *msg2;
-	GList *list;
-	gchar *packed, *packed_expected, *packed_cloned;
-	guint failures;
-
-	failures = 0;
-
-	purple_debug_info("msim", "\n\nTesting MsimMessage\n");
-	msg = msim_msg_new(NULL);      /* Create a new, empty message. */
-
-	/* Append some new elements. */
-	msg = msim_msg_append(msg, "bx", MSIM_TYPE_BINARY, g_string_new_len("XXX", 3));
-	msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v1"));
-	msg = msim_msg_append(msg, "k1", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(42));
-	msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v43"));
-	msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v52/xxx\\yyy"));
-	msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v7"));
-	msim_msg_dump("msg debug str=%s\n", msg);
-	packed = msim_msg_pack(msg);
-
-	purple_debug_info("msim", "msg packed=%s\n", packed);
-
-	packed_expected = "\\bx\\WFhY\\k1\\v1\\k1\\42\\k1"
-		"\\v43\\k1\\v52/1xxx/2yyy\\k1\\v7\\final\\";
-
-	if (!g_str_equal(packed, packed_expected)) {
-		purple_debug_info("msim", "!!!(%d), msim_msg_pack not what expected: %s != %s\n",
-				++failures, packed, packed_expected);
-	}
-
-
-	msg_cloned = msim_msg_clone(msg);
-	packed_cloned = msim_msg_pack(msg_cloned);
-
-	purple_debug_info("msim", "msg cloned=%s\n", packed_cloned);
-	if (!g_str_equal(packed, packed_cloned)) {
-		purple_debug_info("msim", "!!!(%d), msim_msg_pack on cloned message not equal to original: %s != %s\n",
-				++failures, packed_cloned, packed);
-	}
-
-	g_free(packed);
-	g_free(packed_cloned);
-	msim_msg_free(msg_cloned);
-	msim_msg_free(msg);
-
-	/* Try some of the more advanced functionality */
-	list = NULL;
-
-	list = g_list_prepend(list, "item3");
-	list = g_list_prepend(list, "item2");
-	list = g_list_prepend(list, "item1");
-	list = g_list_prepend(list, "item0");
-
-	msg = msim_msg_new(NULL);
-	msg = msim_msg_append(msg, "string", MSIM_TYPE_STRING, g_strdup("string value"));
-	msg = msim_msg_append(msg, "raw", MSIM_TYPE_RAW, g_strdup("raw value"));
-	msg = msim_msg_append(msg, "integer", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(3140));
-	msg = msim_msg_append(msg, "boolean", MSIM_TYPE_BOOLEAN, GUINT_TO_POINTER(FALSE));
-	msg = msim_msg_append(msg, "list", MSIM_TYPE_LIST, list);
-
-	msim_msg_dump("msg with list=%s\n", msg);
-	purple_debug_info("msim", "msg with list packed=%s\n", msim_msg_pack(msg));
-
-	msg2 = msim_msg_new(NULL);
-	msg2 = msim_msg_append(msg2, "outer", MSIM_TYPE_STRING, g_strdup("outer value"));
-	msg2 = msim_msg_append(msg2, "body", MSIM_TYPE_DICTIONARY, msg);
-	msim_msg_dump("msg with dict=%s\n", msg2);      /* msg2 now 'owns' msg */
-	purple_debug_info("msim", "msg with dict packed=%s\n", msim_msg_pack(msg2));
-
-	msim_msg_free(msg2);
-
-	return failures;
-}
-
-/**
- * Test protocol-level escaping/unescaping.
- */
-static int
-msim_test_escaping(void)
-{
-	guint failures;
-	gchar *raw, *escaped, *unescaped, *expected;
-
-	failures = 0;
-
-	purple_debug_info("msim", "\n\nTesting escaping\n");
-
-	raw = "hello/world\\hello/world";
-
-	escaped = msim_escape(raw);
-	purple_debug_info("msim", "msim_test_escaping: raw=%s, escaped=%s\n", raw, escaped);
-	expected = "hello/1world/2hello/1world";
-	if (!g_str_equal(escaped, expected)) {
-		purple_debug_info("msim", "!!!(%d), msim_escape failed: %s != %s\n",
-				++failures, escaped, expected);
-	}
-
-
-	unescaped = msim_unescape(escaped);
-	g_free(escaped);
-	purple_debug_info("msim", "msim_test_escaping: unescaped=%s\n", unescaped);
-	if (!g_str_equal(raw, unescaped)) {
-		purple_debug_info("msim", "!!!(%d), msim_unescape failed: %s != %s\n",
-				++failures, raw, unescaped);
-	}
-
-	return failures;
-}
-
-static void
-msim_test_all(void)
-{
-	guint failures;
-
-	failures = 0;
-	failures += msim_test_msg();
-	failures += msim_test_escaping();
-
-	if (failures) {
-		purple_debug_info("msim", "msim_test_all HAD FAILURES: %d\n", failures);
-	} else {
-		purple_debug_info("msim", "msim_test_all - all tests passed!\n");
-	}
-	exit(0);
-}
-#endif
-
-#ifdef MSIM_CHECK_NEWER_VERSION
-/**
- * Callback for when a currentversion.txt has been downloaded.
- */
-static void
-msim_check_newer_version_cb(PurpleUtilFetchUrlData *url_data,
-		gpointer user_data,
-		const gchar *url_text,
-		gsize len,
-		const gchar *error_message)
-{
-	GKeyFile *keyfile;
-	GError *error;
-	GString *data;
-	gchar *newest_filever;
-
-	if (!url_text) {
-		purple_debug_info("msim_check_newer_version_cb",
-				"got error: %s\n", error_message);
-		return;
-	}
-
-	purple_debug_info("msim_check_newer_version_cb",
-			"url_text=%s\n", url_text ? url_text : "(NULL)");
-
-	/* Prepend [group] so that GKeyFile can parse it (requires a group). */
-	data = g_string_new(url_text);
-	purple_debug_info("msim", "data=%s\n", data->str
-			? data->str : "(NULL)");
-	data = g_string_prepend(data, "[group]\n");
-
-	purple_debug_info("msim", "data=%s\n", data->str
-			? data->str : "(NULL)");
-
-	/* url_text is variable=data\n...†*/
-
-	/* Check FILEVER, 1.0.716.0. 716 is build, MSIM_CLIENT_VERSION */
-	/* New (english) version can be downloaded from SETUPURL+SETUPFILE */
-
-	error = NULL;
-	keyfile = g_key_file_new();
-
-	/* Default list seperator is ;, but currentversion.txt doesn't have
-	 * these, so set to an unused character to avoid parsing problems. */
-	g_key_file_set_list_separator(keyfile, '\0');
-
-	g_key_file_load_from_data(keyfile, data->str, data->len,
-				G_KEY_FILE_NONE, &error);
-	g_string_free(data, TRUE);
-
-	if (error != NULL) {
-		purple_debug_info("msim_check_newer_version_cb",
-				"couldn't parse, error: %d %d %s\n",
-				error->domain, error->code, error->message);
-		g_error_free(error);
-		return;
-	}
-
-	gchar **ks;
-	guint n;
-	ks = g_key_file_get_keys(keyfile, "group", &n, NULL);
-	purple_debug_info("msim", "n=%d\n", n);
-	guint i;
-	for (i = 0; ks[i] != NULL; ++i)
-	{
-		purple_debug_info("msim", "%d=%s\n", i, ks[i]);
-	}
-
-	newest_filever = g_key_file_get_string(keyfile, "group",
-			"FILEVER", &error);
-
-	purple_debug_info("msim_check_newer_version_cb",
-			"newest filever: %s\n", newest_filever ?
-			newest_filever : "(NULL)");
-	if (error != NULL) {
-		purple_debug_info("msim_check_newer_version_cb",
-				"error: %d %d %s\n",
-				error->domain, error->code, error->message);
-		g_error_free(error);
-	}
-
-	g_key_file_free(keyfile);
-
-	exit(0);
-}
-#endif
-
-/**
- Handle a myim:addContact command, after username has been looked up.
- */
-static void
-msim_uri_handler_addContact_cb(MsimSession *session, MsimMessage *userinfo, gpointer data)
-{
-	MsimMessage *body;
-	gchar *username;
-
-	body = msim_msg_get_dictionary(userinfo, "body");
-	username = msim_msg_get_string(body, "UserName");
-	msim_msg_free(body);
-
-	if (!username) {
-		guint uid;
-
-		uid = msim_msg_get_integer(userinfo, "UserID");
-		g_return_if_fail(uid != 0);
-
-		username = g_strdup_printf("%d", uid);
-	}
-
-	purple_blist_request_add_buddy(session->account, username, _("Buddies"), NULL);
-
-	g_free(username);
-}
-
-/* TODO: move uid->username resolving to IM sending and buddy adding functions,
- * so that user can manually add or IM by userid and username automatically
- * looked up if possible? */
-
-/**
- * Handle a myim:sendIM URI command, after username has been looked up.
- */
-static void
-msim_uri_handler_sendIM_cb(MsimSession *session, MsimMessage *userinfo, gpointer data)
-{
-	PurpleConversation *conv;
-	MsimMessage *body;
-	gchar *username;
-
-	body = msim_msg_get_dictionary(userinfo, "body");
-	username = msim_msg_get_string(body, "UserName");
-	msim_msg_free(body);
-
-	if (!username) {
-		guint uid;
-
-		uid = msim_msg_get_integer(userinfo, "UserID");
-		g_return_if_fail(uid != 0);
-
-		username = g_strdup_printf("%d", uid);
-	}
-
-
-	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, username, session->account);
-	if (!conv)  {
-		purple_debug_info("msim_uri_handler", "creating new conversation for %s\n", username);
-		conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, session->account, username);
-	}
-
-	/* Just open the window so the user can send an IM. */
-	purple_conversation_present(conv);
-
-	g_free(username);
-}
-
-static gboolean
-msim_uri_handler(const gchar *proto, const gchar *cmd, GHashTable *params)
-{
-	PurpleAccount *account;
-	MsimSession *session;
-	GList *l;
-	gchar *uid_str, *cid_str;
-	guint uid, cid;
-
-	if (g_ascii_strcasecmp(proto, "myim"))
-		return FALSE;
-
-	/* Parameters are case-insensitive. */
-	uid_str = g_hash_table_lookup(params, "uid");
-	cid_str = g_hash_table_lookup(params, "cid");
-
-	uid = uid_str ? atol(uid_str) : 0;
-	cid = cid_str ? atol(cid_str) : 0;
-
-	/* Need a contact. */
-	g_return_val_if_fail(cid != 0, FALSE);
-
-	/* TODO: if auto=true, "Add all the people on this page to my IM List!", on
-	 * http://collect.myspace.com/index.cfm?fuseaction=im.friendslist. Don't need a cid. */
-
-	/* Convert numeric contact ID back to a string. Needed for looking up. Don't just
-	 * directly use cid directly from parameters, because it might not be numeric.
-	 * It is trivial to change this to allow cID to be a username, but that's not how
-	 * the official MySpaceIM client works, so don't provide that functionality. */
-	cid_str = g_strdup_printf("%d", cid);
-
-
-	/* Find our account with specified user id, or use first connected account if uid=0. */
-	account = NULL;
-	l = purple_accounts_get_all();
-	while (l) {
-		if (purple_account_is_connected(l->data) &&
-			(uid == 0 || purple_account_get_int(l->data, "uid", 0) == (int)uid)) {
-			account = l->data;
-			break;
-		}
-		l = l->next;
-	}
-
-	if (!account) {
-		purple_notify_error(NULL, _("myim URL handler"),
-				_("No suitable MySpaceIM account could be found to open this myim URL."),
-				_("Enable the proper MySpaceIM account and try again."));
-		g_free(cid_str);
-		return FALSE;
-	}
-
-	session = (MsimSession *)account->gc->proto_data;
-	g_return_val_if_fail(session != NULL, FALSE);
-
-	/* Lookup userid to username. TODO: push this down, to IM sending/contact
-	 * adding functions. */
-
-	/* myim:sendIM?uID=USERID&cID=CONTACTID */
-	if (!g_ascii_strcasecmp(cmd, "sendIM")) {
-		msim_lookup_user(session, cid_str, (MSIM_USER_LOOKUP_CB)msim_uri_handler_sendIM_cb, NULL);
-		g_free(cid_str);
-		return TRUE;
-
-	/* myim:addContact?uID=USERID&cID=CONTACTID */
-	} else if (!g_ascii_strcasecmp(cmd, "addContact")) {
-		msim_lookup_user(session, cid_str, (MSIM_USER_LOOKUP_CB)msim_uri_handler_addContact_cb, NULL);
-		g_free(cid_str);
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-/**
- * Initialize plugin.
- */
-static void
-init_plugin(PurplePlugin *plugin)
-{
-#ifdef MSIM_SELF_TEST
-	msim_test_all();
-	exit(0);
-#endif /* MSIM_SELF_TEST */
-
-	PurpleAccountOption *option;
-	static gboolean initialized = FALSE;
-
-#ifdef MSIM_CHECK_NEWER_VERSION
-	/* PROBLEM: MySpace's servers always return Content-Location, and
-	 * libpurple redirects to it, infinitely, even though it is the same
-	 * location we requested! */
-	purple_util_fetch_url("http://im.myspace.com/nsis/currentversion.txt",
-			FALSE, /* not full URL */
-			"MSIMAutoUpdateAgent", /* user agent */
-			TRUE,  /* use HTTP/1.1 */
-			msim_check_newer_version_cb, NULL);
-#endif
-
-	/* TODO: default to automatically try different ports. Make the user be
-	 * able to set the first port to try (like LastConnectedPort in Windows client).  */
-	option = purple_account_option_string_new(_("Connect server"), "server", MSIM_SERVER);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	option = purple_account_option_int_new(_("Connect port"), "port", MSIM_PORT);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-#ifdef MSIM_USER_WANTS_TO_CONFIGURE_STATUS_TEXT
-	option = purple_account_option_bool_new(_("Show display name in status text"), "show_display_name", TRUE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	option = purple_account_option_bool_new(_("Show headline in status text"), "show_headline", TRUE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-#endif
-
-#ifdef MSIM_USER_WANTS_TO_DISABLE_EMOTICONS
-	option = purple_account_option_bool_new(_("Send emoticons"), "emoticons", TRUE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-#endif
-
-#ifdef MSIM_USER_REALLY_CARES_ABOUT_PRECISE_FONT_SIZES
-	option = purple_account_option_int_new(_("Screen resolution (dots per inch)"), "dpi", MSIM_DEFAULT_DPI);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	option = purple_account_option_int_new(_("Base font size (points)"), "base_font_size", MSIM_BASE_FONT_POINT_SIZE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-#endif
-
-	/* Code below only runs once. Based on oscar.c's oscar_init(). */
-	if (initialized)
-		return;
-
-	initialized = TRUE;
-
-	purple_signal_connect(purple_get_core(), "uri-handler", &initialized,
-			PURPLE_CALLBACK(msim_uri_handler), NULL);
-}
-
-PURPLE_INIT_PLUGIN(myspace, init_plugin, info);
deleted file mode 100644
--- a/libpurple/protocols/myspace/myspace.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/* MySpaceIM Protocol Plugin, header file
- *
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- *
- * 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 _MYSPACE_MYSPACE_H
-#define _MYSPACE_MYSPACE_H
-
-#include "internal.h"
-
-/* Other includes */
-#include <string.h>
-#include <errno.h>/* for EAGAIN */
-#include <stdarg.h>
-#include <math.h>
-
-#include <glib.h>
-
-#ifdef _WIN32
-#include "win32dep.h"
-#else
-/* For recv() and send(); needed to match Win32 */
-#include <sys/types.h>
-#include <sys/socket.h>
-#endif
-
-#include "notify.h"
-#include "plugin.h"
-#include "accountopt.h"
-#include "version.h"
-#include "cipher.h"     /* for SHA-1 */
-#include "util.h"       /* for base64 */
-#include "debug.h"      /* for purple_debug_info */
-#include "request.h"    /* For dialogs used in setting the username */
-#include "xmlnode.h"
-#include "core.h"
-#include "conversation.h" /* For late normalization */
-
-/* MySpaceIM includes */
-#include "persist.h"
-#include "message.h"
-#include "session.h"
-#include "zap.h"
-#include "markup.h"
-#include "user.h"
-
-/* Conditional compilation options */
-/* Send third-party client version? (Recognized by us and Miranda's plugin) */
-/*#define MSIM_SEND_CLIENT_VERSION              */
-
-/* Debugging options */
-/* Low-level and rarely needed */
-/*#define MSIM_DEBUG_PARSE             */
-/*#define MSIM_DEBUG_LOGIN_CHALLENGE*/
-/*#define MSIM_DEBUG_RXBUF            */
-
-/* Encode unknown HTML tags from IM clients in messages as [tag], instead of
- * ignoring. Useful for debugging */
-/*#define MSIM_MARKUP_SHOW_UNKNOWN_TAGS  */
-
-/* Define to cause init_plugin() to run some tests and print
- * the results to the Purple debug log, then exit. Useful to
- * run with 'pidgin -d' to see the output. Don't define if
- * you want to actually use the plugin! */
-/*#define MSIM_SELF_TEST            */
-
-/* Constants */
-
-/* Maximum length of a password that is acceptable. This is the limit
- * on the official client (build 679) and on the 'new password' field at
- * http://settings.myspace.com/index.cfm?fuseaction=user.changepassword
- * (though curiously, not on the 'current password' field). */
-
-/* After login fails, if password is greater than this many characters,
- * warn user that it may be too long. */
-#define MSIM_MAX_PASSWORD_LENGTH    10
-
-/* Maximum length of usernames, when setting. */
-#define MSIM_MAX_USERNAME_LENGTH    25
-
-/* Build version of MySpaceIM to report to servers (1.0.xxx.0) */
-#define MSIM_CLIENT_VERSION         697
-
-/* Check for a newer official MySpaceIM client on startup?
- * (Mostly useful for developers) */
-/*#define MSIM_CHECK_NEWER_VERSION*/
-
-/* Language codes from http://www.microsoft.com/globaldev/reference/oslocversion.mspx */
-#define MSIM_LANGUAGE_ID_ENGLISH    1033
-#define MSIM_LANGUAGE_NAME_ENGLISH  "ENGLISH"
-
-/* msimprpl version string of this plugin */
-#define MSIM_PRPL_VERSION_STRING    "0.18"
-
-/* Default server */
-#define MSIM_SERVER                 "im.myspace.akadns.net"
-#define MSIM_PORT                   1863        /* TODO: alternate ports and automatic */
-
-/* Time between keepalives (seconds) - if no data within this time, is dead. */
-#define MSIM_KEEPALIVE_INTERVAL     (3 * 60)
-/*#define MSIM_USE_KEEPALIVE*/
-
-/* Time to check if alive (seconds) */
-#define MSIM_KEEPALIVE_INTERVAL_CHECK   30
-
-/* Time to check for new mail (milliseconds) */
-#define MSIM_MAIL_INTERVAL_CHECK    (60 * 1000)
-
-/* Constants */
-#define HASH_SIZE                   0x14        /**< Size of SHA-1 hash for login */
-#define NONCE_SIZE                  0x20        /**< Half of decoded 'nc' field */
-#define MSIM_READ_BUF_SIZE          (15 * 1024) /**< Receive buffer size */
-#define MSIM_FINAL_STRING           "\\final\\" /**< Message end marker */
-
-/* Messages */
-#define MSIM_BM_ACTION_OR_IM_DELAYABLE  1
-#define MSIM_BM_STATUS                  100
-#define MSIM_BM_ACTION_OR_IM_INSTANT    121
-#define MSIM_BM_MEDIA                   122
-#define MSIM_BM_PROFILE                 124
-#define MSIM_BM_STATUS_MOOD             126
-#define MSIM_BM_UNOFFICIAL_CLIENT       200
-
-/* Authentication algorithm for login2 */
-#define MSIM_AUTH_ALGORITHM         196610
-
-/* Recognized challenge length */
-#define MSIM_AUTH_CHALLENGE_LENGTH  0x40
-
-#ifdef SEND_OUR_IP_ADDRESSES
-/* TODO: obtain IPs of network interfaces from user's machine, instead of
- * hardcoding these values below (used in msim_compute_login_response).
- * This is not immediately
- * important because you can still connect and perform basic
- * functions of the protocol. There is also a high chance that the addreses
- * are RFC1918 private, so the servers couldn't do anything with them
- * anyways except make note of that fact. Probably important for any
- * kind of direct connection, or file transfer functionality.
- */
-
-#define MSIM_LOGIN_IP_LIST  "\x00\x00\x00\x00\x05\x7f\x00\x00\x01\x00\x00\x00\x00\x0a\x00\x00\x40\xc0\xa8\x58\x01\xc0\xa8\x3c\x01"
-#define MSIM_LOGIN_IP_LIST_LEN         25
-#endif /* SEND_OUR_IP_ADDRESSES */
-
-/* Indexes into status string (0|1|2|3|..., but 0 always empty) */
-#define MSIM_STATUS_ORDINAL_EMPTY       0
-#define MSIM_STATUS_ORDINAL_UNKNOWNs    1
-#define MSIM_STATUS_ORDINAL_ONLINE      2
-#define MSIM_STATUS_ORDINAL_UNKNOWNss   3
-#define MSIM_STATUS_ORDINAL_HEADLINE    4
-#define MSIM_STATUS_ORDINAL_UNKNOWNls   5
-#define MSIM_STATUS_ORDINAL_UNKNOWN     6
-#define MSIM_STATUS_ORDINAL_UNKNOWN1    7
-#define MSIM_STATUS_ORDINAL_UNKNOWNp    8
-#define MSIM_STATUS_ORDINAL_UNKNOWN2    9
-
-/* Status codes - states a buddy (or you!) can be in. */
-#define MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN    0
-#define MSIM_STATUS_CODE_ONLINE               1
-#define MSIM_STATUS_CODE_IDLE                 2
-#define MSIM_STATUS_CODE_AWAY                 5
-
-/* Inbox status bitfield values for MsimSession.inbox_status. */
-#define MSIM_INBOX_MAIL                 (1 << 0)
-#define MSIM_INBOX_BLOG_COMMENT         (1 << 1)
-#define MSIM_INBOX_PROFILE_COMMENT      (1 << 2)
-#define MSIM_INBOX_FRIEND_REQUEST       (1 << 3)
-#define MSIM_INBOX_PICTURE_COMMENT      (1 << 4)
-
-/* Codes for msim_got_contact_list(), to tell what to do afterwards. */
-#define MSIM_CONTACT_LIST_INITIAL_FRIENDS	0
-#define MSIM_CONTACT_LIST_IMPORT_ALL_FRIENDS	1
-#define MSIM_CONTACT_LIST_IMPORT_TOP_FRIENDS	2
-
-/* Error codes */
-#define MSIM_ERROR_INCORRECT_PASSWORD           260
-#define MSIM_ERROR_LOGGED_IN_ELSEWHERE          6
-
-/* Functions */
-gboolean msim_send_raw(MsimSession *session, const gchar *msg);
-
-gboolean msim_send_bm(MsimSession *session, const gchar *who, const gchar *text, int type);
-
-gboolean msim_we_are_logged_on(MsimSession *session);
-
-void msim_unrecognized(MsimSession *session, MsimMessage *msg, gchar *note);
-guint msim_new_reply_callback(MsimSession *session, MSIM_USER_LOOKUP_CB cb, gpointer data);
-
-#endif /* !_MYSPACE_MYSPACE_H */
deleted file mode 100644
--- a/libpurple/protocols/myspace/persist.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/* MySpaceIM Protocol Plugin, persist commands
- *
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- *
- * 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 _MYSPACE_PERSIST_H
-#define _MYSPACE_PERSIST_H
-
-/** Command codes */
-#define MSIM_CMD_GET               1
-#define MSIM_CMD_PUT               2
-#define MSIM_CMD_DELETE            3
-
-/** Command bit fields */
-#define MSIM_CMD_BIT_CODE          255        /*< Bits specifying command code */
-#define MSIM_CMD_BIT_REPLY         256        /**< 1=reply, 0=request */
-#define MSIM_CMD_BIT_ACTION        512        /**< 1=action, 0=information */
-#define MSIM_CMD_BIT_ERROR        1024        /**< 1=error, 0=normal */
-
-/** Macros to read cmd bitfield. */
-#define MSIM_CMD_GET_CODE(x)      (x & MSIM_CMD_BIT_CODE)
-#define MSIM_CMD_IS_REPLY(x)      (x & MSIM_CMD_BIT_REPLY)
-#define MSIM_CMD_IS_REQUEST(x)   !(x & MSIM_CMD_BIT_REPLY)
-#define MSIM_CMD_IS_ACTION(x)     (x & MSIM_CMD_BIT_ACTION)
-#define MSIM_CMD_IS_INFO(x)      !(x & MSIM_CMD_BIT_ACTION)
-#define MSIM_CMD_IS_ERROR(x)      (x & MSIM_CMD_BIT_ERROR)
-#define MSIM_CMD_IS_NORMAL(x)    !(x & MSIM_CMD_BIT_ERROR)
-
-/** Define a set of _DSN and _LID constants for a persistance request. */
-#define MSIM_PERSIST_DSN_LID(name,dsn,lid)             \
-    static const int name##_DSN = dsn;                 \
-    static const int name##_LID = lid;
-
-/* Can't do this, errors:
- *     persist.h:51:3: error: '#' is not followed by a macro parameter
- *  In file included from myspace.c:37:
- *  persist.h:56: error: expected ')' before numeric constant
- * So instead, I define const ints above.
-#define MSIM_PERSIST_DSN_LID(name,dsn,lid)             \
-	#define name##_DSN        dsn                  \
-	#define name##_LID        lid
-#endif
-*/
-
-/** Messages to Get information                dsn lid */
-MSIM_PERSIST_DSN_LID(MG_LIST_ALL_CONTACTS,         0, 1)
-MSIM_PERSIST_DSN_LID(MG_USER_INFO_BY_ID,           0, 2)
-MSIM_PERSIST_DSN_LID(MG_OWN_IM_INFO,               1, 4)
-MSIM_PERSIST_DSN_LID(MG_IM_INFO_BY_ID,             1, 17)
-MSIM_PERSIST_DSN_LID(MG_LIST_ALL_GROUPS,           2, 6)
-MSIM_PERSIST_DSN_LID(MG_MYSPACE_INFO_BY_ID,        4, 3)
-MSIM_PERSIST_DSN_LID(MG_OWN_MYSPACE_INFO,          4, 5)
-MSIM_PERSIST_DSN_LID(MG_MYSPACE_INFO_BY_STRING,    5, 7)
-MSIM_PERSIST_DSN_LID(MG_CHECK_MAIL,                7, 18)
-MSIM_PERSIST_DSN_LID(MG_WEB_CHALLENGE,            17, 26)
-MSIM_PERSIST_DSN_LID(MG_USER_SONG,                21, 28)
-MSIM_PERSIST_DSN_LID(MG_SERVER_INFO,             101, 20)
-
-/** Messages to Change/send information */
-MSIM_PERSIST_DSN_LID(MC_USER_PREFERENCES,          1, 10)
-MSIM_PERSIST_DSN_LID(MC_DELETE_CONTACT_INFO,       0, 8)
-MSIM_PERSIST_DSN_LID(MC_CONTACT_INFO,              0, 9)
-MSIM_PERSIST_DSN_LID(MC_SET_USERNAME,              9, 14)
-MSIM_PERSIST_DSN_LID(MC_IMPORT_ALL_FRIENDS,       14, 21)
-MSIM_PERSIST_DSN_LID(MC_INVITE,                   16, 25)
-
-/** Messages to Delete information */
-MSIM_PERSIST_DSN_LID(MD_DELETE_BUDDY,              0, 8)
-
-/** Error codes */
-#define MERR_PARSE                    1
-#define MERR_NOT_LOGGED_IN            2
-#define MERR_ANOTHER_LOGIN            6
-#define MERR_BAD_EMAIL                259
-#define MERR_BAD_PASSWORD             260
-#define MERR_BAD_UID_IN_PERSISTR      4352
-
-#endif /* !_MYSPACE_PERSIST_H */
deleted file mode 100644
--- a/libpurple/protocols/myspace/session.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/* MySpaceIM Protocol Plugin, session
- *
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- *
- * 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 "myspace.h"
-
-/* Session methods */
-
-/**
- * Create a new MSIM session.
- *
- * @param acct The account to create the session from.
- *
- * @return Pointer to a new session. Free with msim_session_destroy.
- */
-MsimSession *
-msim_session_new(PurpleAccount *acct)
-{
-	MsimSession *session;
-
-	g_return_val_if_fail(acct != NULL, NULL);
-
-	session = g_new0(MsimSession, 1);
-
-	session->magic = MSIM_SESSION_STRUCT_MAGIC;
-	session->account = acct;
-	session->gc = purple_account_get_connection(acct);
-	session->sesskey = 0;
-	session->userid = 0;
-	session->username = NULL;
-	session->fd = -1;
-
-	/* TODO: Remove. */
-	session->user_lookup_cb = g_hash_table_new_full(g_direct_hash,
-			g_direct_equal, NULL, NULL);  /* do NOT free function pointers! (values) */
-	session->user_lookup_cb_data = g_hash_table_new_full(g_direct_hash,
-			g_direct_equal, NULL, NULL);/* TODO: we don't know what the values are,
-											 they could be integers inside gpointers
-											 or strings, so I don't freed them.
-											 Figure this out, once free cache. */
-
-	/* Created in msim_process_server_info() */
-	session->server_info = NULL;
-
-	session->rxoff = 0;
-	session->rxsize = MSIM_READ_BUF_SIZE;
-	session->rxbuf = g_new0(gchar, session->rxsize);
-	session->next_rid = 1;
-	session->last_comm = time(NULL);
-	session->inbox_status = 0;
-	session->inbox_handle = 0;
-
-	return session;
-}
-
-/**
- * Free a session.
- *
- * @param session The session to destroy.
- */
-void
-msim_session_destroy(MsimSession *session)
-{
-	session->magic = -1;
-
-	g_free(session->rxbuf);
-	g_free(session->username);
-
-	/* TODO: Remove. */
-	g_hash_table_destroy(session->user_lookup_cb);
-	g_hash_table_destroy(session->user_lookup_cb_data);
-
-	if (session->server_info) {
-		msim_msg_free(session->server_info);
-	}
-
-	/* Stop checking the inbox at the end of the session. */
-	if (session->inbox_handle) {
-		purple_timeout_remove(session->inbox_handle);
-	}
-
-	g_free(session);
-}
deleted file mode 100644
--- a/libpurple/protocols/myspace/session.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* MySpaceIM Protocol Plugin, session
- *
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- *
- * 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 _MYSPACE_SESSION_H
-#define _MYSPACE_SESSION_H
-
-#include "account.h"
-
-/* Random number in every MsimSession, to ensure it is valid. */
-#define MSIM_SESSION_STRUCT_MAGIC       0xe4a6752b
-
-/* Everything needed to keep track of a session (proto_data field in PurpleConnection) */
-typedef struct _MsimSession
-{
-	guint magic;                        /**< MSIM_SESSION_STRUCT_MAGIC */
-	PurpleAccount *account;
-	PurpleConnection *gc;
-	guint sesskey;                      /**< Session key from server */
-	guint userid;                       /**< This user's numeric user ID */
-	gchar *username;                    /**< This user's unique username */
-	gboolean show_only_to_list;
-	int privacy_mode;                   /**< This is a bitmask */
-	int offline_message_mode;
-	gint fd;                            /**< File descriptor to/from server */
-
-	/* TODO: Remove. */
-	GHashTable *user_lookup_cb;         /**< Username -> userid lookup callback */
-	GHashTable *user_lookup_cb_data;    /**< Username -> userid lookup callback data */
-
-	MsimMessage *server_info;           /**< Parameters from server */
-
-	gchar *rxbuf;                       /**< Receive buffer */
-	guint rxoff;                        /**< Receive buffer offset */
-	guint rxsize;                       /**< Receive buffer size */
-	guint next_rid;                     /**< Next request/response ID */
-	time_t last_comm;                   /**< Time received last communication */
-	guint inbox_status;                 /**< Bit field of inbox notifications */
-	guint inbox_handle;                 /**< The handle for the mail check timer */
-} MsimSession;
-
-MsimSession *msim_session_new(PurpleAccount *acct);
-void msim_session_destroy(MsimSession *session);
-
-#endif /* !_MYSPACE_SESSION_H */
deleted file mode 100644
--- a/libpurple/protocols/myspace/user.c
+++ /dev/null
@@ -1,892 +0,0 @@
-/* MySpaceIM Protocol Plugin, header file
- *
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- *
- * 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 "myspace.h"
-
-static void msim_check_username_availability_cb(PurpleConnection *gc, const char *username_to_check);
-
-static char *msim_username_to_set;
-
-/**
- * Format the "now playing" indicator, showing the artist and song.
- *
- * @return Return a new string (must be g_free()'d), or NULL.
- */
-static gchar *
-msim_format_now_playing(const gchar *band, const gchar *song)
-{
-	if ((band && *band) || (song && *song)) {
-		return g_strdup_printf("%s - %s",
-			(band && *band) ? band : "Unknown Artist",
-			(song && *song) ? song : "Unknown Song");
-	} else {
-		return NULL;
-	}
-}
-
-/**
- * Get the MsimUser from a PurpleBuddy, optionally creating it if needed.
- */
-MsimUser *
-msim_get_user_from_buddy(PurpleBuddy *buddy, gboolean create)
-{
-	MsimUser *user;
-
-	if (!buddy) {
-		return NULL;
-	}
-
-	user = purple_buddy_get_protocol_data(buddy);
-	if (create && !user) {
-		PurpleBlistNode *node = PURPLE_BLIST_NODE(buddy);
-
-		/* No MsimUser for this buddy; make one. */
-
-		user = g_new0(MsimUser, 1);
-		user->buddy = buddy;
-		user->id = purple_blist_node_get_int(node, "UserID");
-		purple_buddy_set_protocol_data(buddy, user);
-	}
-
-	return user;
-}
-
-void msim_user_free(MsimUser *user)
-{
-	if (!user)
-		return;
-
-	if (user->url_data != NULL)
-		purple_util_fetch_url_cancel(user->url_data);
-
-	g_free(user->client_info);
-	g_free(user->gender);
-	g_free(user->location);
-	g_free(user->headline);
-	g_free(user->display_name);
-	g_free(user->username);
-	g_free(user->band_name);
-	g_free(user->song_name);
-	g_free(user->image_url);
-	g_free(user);
-}
-
-/**
- * Find and return an MsimUser * representing a user on the buddy list, or NULL.
- */
-MsimUser *
-msim_find_user(MsimSession *session, const gchar *username)
-{
-	PurpleBuddy *buddy;
-
-	buddy = purple_find_buddy(session->account, username);
-	if (!buddy) {
-		return NULL;
-	}
-
-	return msim_get_user_from_buddy(buddy, TRUE);
-}
-
-/**
- * Append user information to a PurpleNotifyUserInfo, given an MsimUser.
- * Used by msim_tooltip_text() and msim_get_info_cb() to show a user's profile.
- */
-void
-msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full)
-{
-	PurplePresence *presence;
-	gchar *str;
-	guint cv;
-
-	/* Useful to identify the account the tooltip refers to.
-	 *  Other prpls show this. */
-	if (user->username) {
-		purple_notify_user_info_add_pair(user_info, _("User"), user->username);
-	}
-
-	/* a/s/l...the vitals */
-	if (user->age) {
-		char age[16];
-		g_snprintf(age, sizeof(age), "%d", user->age);
-		purple_notify_user_info_add_pair(user_info, _("Age"), age);
-	}
-
-	if (user->gender && *user->gender) {
-		purple_notify_user_info_add_pair(user_info, _("Gender"), user->gender);
-	}
-
-	if (user->location && *user->location) {
-		purple_notify_user_info_add_pair(user_info, _("Location"), user->location);
-	}
-
-	/* Other information */
-	if (user->headline && *user->headline) {
-		purple_notify_user_info_add_pair(user_info, _("Headline"), user->headline);
-	}
-
-	if (user->buddy != NULL) {
-		presence = purple_buddy_get_presence(user->buddy);
-
-		if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
-			PurpleStatus *status;
-			const char *artist, *title;
-
-			status = purple_presence_get_status(presence, "tune");
-			title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
-			artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
-
-			str = msim_format_now_playing(artist, title);
-			if (str && *str) {
-				purple_notify_user_info_add_pair(user_info, _("Song"), str);
-			}
-			g_free(str);
-		}
-	}
-
-	/* Note: total friends only available if looked up by uid, not username. */
-	if (user->total_friends) {
-		char friends[16];
-		g_snprintf(friends, sizeof(friends), "%d", user->total_friends);
-		purple_notify_user_info_add_pair(user_info, _("Total Friends"), friends);
-	}
-
-	if (full) {
-		/* Client information */
-		char *client = NULL;
-
-		str = user->client_info;
-		cv = user->client_cv;
-
-		if (str && cv != 0) {
-			client = g_strdup_printf("%s (build %d)", str, cv);
-		} else if (str) {
-			client = g_strdup(str);
-		} else if (cv) {
-			client = g_strdup_printf("Build %d", cv);
-		}
-		if (client && *client)
-			purple_notify_user_info_add_pair(user_info, _("Client Version"), client);
-		g_free(client);
-	}
-
-	if (full && user->id) {
-		/* TODO: link to username, if available */
-		char *profile;
-		purple_notify_user_info_add_section_break(user_info);
-		if (user->buddy != NULL)
-			profile = g_strdup_printf("<a href=\"http://myspace.com/%s\">%s</a>",
-					purple_buddy_get_name(user->buddy), _("View web profile"));
-		else
-			profile = g_strdup_printf("<a href=\"http://myspace.com/%d\">%s</a>",
-					user->id, _("View web profile"));
-		purple_notify_user_info_add_pair(user_info, NULL, profile);
-		g_free(profile);
-	}
-}
-
-/**
- * Callback for when a buddy icon finished being downloaded.
- */
-static void
-msim_downloaded_buddy_icon(PurpleUtilFetchUrlData *url_data,
-		gpointer user_data,
-		const gchar *url_text,
-		gsize len,
-		const gchar *error_message)
-{
-	MsimUser *user = (MsimUser *)user_data;
-	const char *name = purple_buddy_get_name(user->buddy);
-	PurpleAccount *account;
-
-	user->url_data = NULL;
-
-	purple_debug_info("msim_downloaded_buddy_icon",
-			"Downloaded %" G_GSIZE_FORMAT " bytes\n", len);
-
-	if (!url_text) {
-		purple_debug_info("msim_downloaded_buddy_icon",
-				"failed to download icon for %s",
-				name);
-		return;
-	}
-
-	account = purple_buddy_get_account(user->buddy);
-	purple_buddy_icons_set_for_user(account, name,
-			g_memdup((gchar *)url_text, len), len,
-			/* Use URL itself as buddy icon "checksum" (TODO: ETag) */
-			user->image_url);		/* checksum */
-}
-
-/**
- * Set the currently playing song artist and or title.
- *
- * @param user User associated with the now playing information.
- *
- * @param new_artist New artist to set, or NULL/empty to not change artist.
- *
- * @param new_title New title to set, or NULL/empty to not change title.
- *
- * If new_artist and new_title are NULL/empty, deactivate PURPLE_STATUS_TUNE.
- *
- * This function is useful because it lets you set the artist or title
- * individually, which purple_prpl_got_user_status() doesn't do.
- */
-static void msim_set_artist_or_title(MsimUser *user, const char *new_artist, const char *new_title)
-{
-	PurplePresence *presence;
-	PurpleAccount *account;
-	const char *prev_artist, *prev_title;
-	const char *name;
-
-	if (user->buddy == NULL)
-		/* User not on buddy list so nothing to do */
-		return;
-
-	prev_artist = NULL;
-	prev_title = NULL;
-
-	if (new_artist && !*new_artist)
-		new_artist = NULL;
-	if (new_title && !*new_title)
-		new_title = NULL;
-
-	account = purple_buddy_get_account(user->buddy);
-	name = purple_buddy_get_name(user->buddy);
-
-	if (!new_artist && !new_title) {
-		purple_prpl_got_user_status_deactive(account, name, "tune");
-		return;
-	}
-
-	presence = purple_buddy_get_presence(user->buddy);
-
-	if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
-		PurpleStatus *status;
-
-		status = purple_presence_get_status(presence, "tune");
-		prev_title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
-		prev_artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
-	}
-
-	if (!new_artist)
-		new_artist = prev_artist;
-
-	if (!new_title)
-		new_title = prev_title;
-
-	purple_prpl_got_user_status(account, name, "tune",
-			PURPLE_TUNE_TITLE, new_title,
-			PURPLE_TUNE_ARTIST, new_artist,
-			NULL);
-}
-
-/**
- * Store a field of information about a buddy.
- *
- * @param key_str Key to store.
- * @param value_str Value string, either user takes ownership of this string
- *                  or it is freed if MsimUser doesn't store the string.
- * @param user User to store data in. Existing data will be replaced.
- */
-static void
-msim_store_user_info_each(const gchar *key_str, gchar *value_str, MsimUser *user)
-{
-	const char *name = user->buddy ? purple_buddy_get_name(user->buddy) : NULL;
-
-	if (g_str_equal(key_str, "UserID") || g_str_equal(key_str, "ContactID")) {
-		/* Save to buddy list, if it exists, for quick cached uid lookup with msim_uid2username_from_blist(). */
-		user->id = atol(value_str);
-		g_free(value_str);
-		if (user->buddy)
-		{
-			purple_debug_info("msim", "associating uid %s with username %s\n", key_str, name);
-			purple_blist_node_set_int(PURPLE_BLIST_NODE(user->buddy), "UserID", user->id);
-		}
-		/* Need to store in MsimUser, too? What if not on blist? */
-	} else if (g_str_equal(key_str, "Age")) {
-		user->age = atol(value_str);
-		g_free(value_str);
-	} else if (g_str_equal(key_str, "Gender")) {
-		g_free(user->gender);
-		user->gender = value_str;
-	} else if (g_str_equal(key_str, "Location")) {
-		g_free(user->location);
-		user->location = value_str;
-	} else if (g_str_equal(key_str, "TotalFriends")) {
-		user->total_friends = atol(value_str);
-		g_free(value_str);
-	} else if (g_str_equal(key_str, "DisplayName")) {
-		g_free(user->display_name);
-		user->display_name = value_str;
-	} else if (g_str_equal(key_str, "BandName")) {
-		msim_set_artist_or_title(user, value_str, NULL);
-		g_free(value_str);
-	} else if (g_str_equal(key_str, "SongName")) {
-		msim_set_artist_or_title(user, NULL, value_str);
-		g_free(value_str);
-	} else if (g_str_equal(key_str, "UserName") || g_str_equal(key_str, "IMName") || g_str_equal(key_str, "NickName")) {
-		/* Ignore because PurpleBuddy knows this already */
-		g_free(value_str);
-	} else if (g_str_equal(key_str, "ImageURL") || g_str_equal(key_str, "AvatarURL")) {
-		const gchar *previous_url;
-
-		if (user->temporary_user) {
-			/* This user will be destroyed soon; don't try to look up its image or avatar,
-			 * since that won't return immediately and we will end up accessing freed data.
-			 */
-			g_free(value_str);
-			return;
-		}
-
-		g_free(user->image_url);
-
-		user->image_url = value_str;
-
-		/* Instead of showing 'no photo' picture, show nothing. */
-		if (g_str_equal(user->image_url, "http://x.myspace.com/images/no_pic.gif"))
-		{
-			purple_buddy_icons_set_for_user(purple_buddy_get_account(user->buddy),
-				name, NULL, 0, NULL);
-			return;
-		}
-
-		/* TODO: use ETag for checksum */
-		previous_url = purple_buddy_icons_get_checksum_for_user(user->buddy);
-
-		/* Only download if URL changed */
-		if (!previous_url || !g_str_equal(previous_url, user->image_url)) {
-			if (user->url_data != NULL)
-				purple_util_fetch_url_cancel(user->url_data);
-			user->url_data = purple_util_fetch_url(user->image_url, TRUE, NULL, TRUE, msim_downloaded_buddy_icon, (gpointer)user);
-		}
-	} else if (g_str_equal(key_str, "LastImageUpdated")) {
-		/* TODO: use somewhere */
-		user->last_image_updated = atol(value_str);
-		g_free(value_str);
-	} else if (g_str_equal(key_str, "Headline")) {
-		g_free(user->headline);
-		user->headline = value_str;
-	} else {
-		/* TODO: other fields in MsimUser */
-		gchar *msg;
-
-		msg = g_strdup_printf("msim_store_user_info_each: unknown field %s=%s",
-				key_str, value_str);
-		g_free(value_str);
-
-		msim_unrecognized(NULL, NULL, msg);
-
-		g_free(msg);
-	}
-}
-
-/**
- * Save buddy information to the buddy list from a user info reply message.
- *
- * @param session
- * @param msg The user information reply, with any amount of information.
- * @param user The structure to save to, or NULL to save in PurpleBuddy->proto_data.
- *
- * Variable information is saved to the passed MsimUser structure. Permanent
- * information (UserID) is stored in the blist node of the buddy list (and
- * ends up in blist.xml, persisted to disk) if it exists.
- *
- * If the function has no buddy information, this function
- * is a no-op (and returns FALSE).
- */
-gboolean
-msim_store_user_info(MsimSession *session, const MsimMessage *msg, MsimUser *user)
-{
-	gchar *username;
-	MsimMessage *body, *body_node;
-
-	g_return_val_if_fail(msg != NULL, FALSE);
-
-	body = msim_msg_get_dictionary(msg, "body");
-	if (!body) {
-		return FALSE;
-	}
-
-	if (msim_msg_get_integer(msg, "dsn") == (guint)MG_OWN_IM_INFO_DSN &&
-		msim_msg_get_integer(msg, "lid") == (guint)MG_OWN_IM_INFO_LID)
-	{
-		/*
-		 * Some of this info will be available on the buddy list if the
-		 * user has themselves as their own buddy.
-		 *
-		 * Much of the info is already available in MsimSession,
-		 * stored in msim_we_are_logged_on().
-		 */
-		gchar *tmpstr;
-
-		tmpstr = msim_msg_get_string(body, "ShowOnlyToList");
-		if (tmpstr != NULL) {
-			session->show_only_to_list = g_str_equal(tmpstr, "True");
-			g_free(tmpstr);
-		}
-
-		session->privacy_mode = msim_msg_get_integer(body, "PrivacyMode");
-		session->offline_message_mode = msim_msg_get_integer(body, "OfflineMessageMode");
-
-		msim_send(session,
-				"blocklist", MSIM_TYPE_BOOLEAN, TRUE,
-				"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-				"idlist", MSIM_TYPE_STRING,
-						g_strdup_printf("w%d|c%d",
-								session->show_only_to_list ? 1 : 0,
-								session->privacy_mode & 1),
-				NULL);
-	} else if (msim_msg_get_integer(msg, "dsn") == (guint)MG_OWN_MYSPACE_INFO_DSN &&
-			msim_msg_get_integer(msg, "lid") == (guint)MG_OWN_MYSPACE_INFO_LID) {
-		/* TODO: same as above, but for MySpace info. */
-	}
-
-	username = msim_msg_get_string(body, "UserName");
-
-	if (!username) {
-		purple_debug_info("msim",
-			"msim_process_reply: not caching body, no UserName\n");
-		msim_msg_free(body);
-		g_free(username);
-		return FALSE;
-	}
-
-	/* Null user = find and store in PurpleBuddy's proto_data */
-	if (!user) {
-		user = msim_find_user(session, username);
-		if (!user) {
-			msim_msg_free(body);
-			g_free(username);
-			return FALSE;
-		}
-	}
-
-	/* TODO: make looping over MsimMessage's easier. */
-	for (body_node = body;
-		body_node != NULL;
-		body_node = msim_msg_get_next_element_node(body_node))
-	{
-		const gchar *key_str;
-		gchar *value_str;
-		MsimMessageElement *elem;
-
-		elem = (MsimMessageElement *)body_node->data;
-		key_str = elem->name;
-
-		value_str = msim_msg_get_string_from_element(elem);
-		msim_store_user_info_each(key_str, value_str, user);
-	}
-
-	msim_msg_free(body);
-	g_free(username);
-
-	return TRUE;
-}
-
-#if 0
-/**
- * Return whether a given username is syntactically valid.
- * Note: does not actually check that the user exists.
- */
-static gboolean
-msim_is_valid_username(const gchar *user)
-{
-	return !msim_is_userid(user) &&  /* Not all numeric */
-		strlen(user) <= MSIM_MAX_USERNAME_LENGTH
-		&& strspn(user, "0123456789"
-			"abcdefghijklmnopqrstuvwxyz"
-			"_"
-			"ABCDEFGHIJKLMNOPQRSTUVWXYZ") == strlen(user);
-}
-#endif
-
-/**
- * Check if a string is a userid (all numeric).
- *
- * @param user The user id, email, or name.
- *
- * @return TRUE if is userid, FALSE if not.
- */
-gboolean
-msim_is_userid(const gchar *user)
-{
-	g_return_val_if_fail(user != NULL, FALSE);
-
-	return strspn(user, "0123456789") == strlen(user);
-}
-
-/**
- * Check if a string is an email address (contains an @).
- *
- * @param user The user id, email, or name.
- *
- * @return TRUE if is an email, FALSE if not.
- *
- * This function is not intended to be used as a generic
- * means of validating email addresses, but to distinguish
- * between a user represented by an email address from
- * other forms of identification.
- */
-static gboolean
-msim_is_email(const gchar *user)
-{
-	g_return_val_if_fail(user != NULL, FALSE);
-
-	return strchr(user, '@') != NULL;
-}
-
-/**
- * Asynchronously lookup user information, calling callback when receive result.
- *
- * @param session
- * @param user The user id, email address, or username. Not freed.
- * @param cb Callback, called with user information when available.
- * @param data An arbitray data pointer passed to the callback.
- */
-/* TODO: change to not use callbacks */
-void
-msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data)
-{
-	MsimMessage *body;
-	gchar *field_name;
-	guint rid, dsn, lid;
-
-	g_return_if_fail(user != NULL);
-	/* Callback can be null to not call anything, just lookup & store information. */
-	/*g_return_if_fail(cb != NULL);*/
-
-	purple_debug_info("msim", "msim_lookup_userid: "
-			"asynchronously looking up <%s>\n", user);
-
-	/* Setup callback. Response will be associated with request using 'rid'. */
-	rid = msim_new_reply_callback(session, cb, data);
-
-	/* Send request */
-
-	if (msim_is_userid(user)) {
-		field_name = "UserID";
-		dsn = MG_MYSPACE_INFO_BY_ID_DSN;
-		lid = MG_MYSPACE_INFO_BY_ID_LID;
-	} else if (msim_is_email(user)) {
-		field_name = "Email";
-		dsn = MG_MYSPACE_INFO_BY_STRING_DSN;
-		lid = MG_MYSPACE_INFO_BY_STRING_LID;
-	} else {
-		field_name = "UserName";
-		dsn = MG_MYSPACE_INFO_BY_STRING_DSN;
-		lid = MG_MYSPACE_INFO_BY_STRING_LID;
-	}
-
-	body = msim_msg_new(
-			field_name, MSIM_TYPE_STRING, g_strdup(user),
-			NULL);
-
-	g_return_if_fail(msim_send(session,
-			"persist", MSIM_TYPE_INTEGER, 1,
-			"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-			"cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
-			"dsn", MSIM_TYPE_INTEGER, dsn,
-			"uid", MSIM_TYPE_INTEGER, session->userid,
-			"lid", MSIM_TYPE_INTEGER, lid,
-			"rid", MSIM_TYPE_INTEGER, rid,
-			"body", MSIM_TYPE_DICTIONARY, body,
-			NULL));
-}
-
-/**
- * Called after username is set.
- */
-static void msim_username_is_set_cb(MsimSession *session, const MsimMessage *userinfo, gpointer data)
-{
-	gchar *username;
-	const gchar *errmsg;
-	MsimMessage *body;
-
-	guint rid;
-	gint cmd,dsn,lid,code;
-	/* \persistr\\cmd\258\dsn\9\uid\204084363\lid\14\rid\369\body\UserName=TheAlbinoRhino1.Code=0\final\ */
-
-	purple_debug_info("msim","username_is_set made\n");
-
-	cmd = msim_msg_get_integer(userinfo, "cmd");
-	dsn = msim_msg_get_integer(userinfo, "dsn");
-#if 0
-	uid = msim_msg_get_integer(userinfo, "uid");
-#endif
-	lid = msim_msg_get_integer(userinfo, "lid");
-	body = msim_msg_get_dictionary(userinfo, "body");
-	errmsg = _("An error occurred while trying to set the username.  "
-			"Please try again, or visit http://editprofile.myspace.com/index.cfm?"
-			"fuseaction=profile.username to set your username.");
-
-	if (!body) {
-		purple_debug_info("msim_username_is_set_cb", "No body");
-		/* Error: No body! */
-		purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
-	}
-	username = msim_msg_get_string(body, "UserName");
-	code = msim_msg_get_integer(body,"Code");
-
-	msim_msg_free(body);
-
-	purple_debug_info("msim_username_is_set_cb",
-			"cmd = %d, dsn = %d, lid = %d, code = %d, username = %s\n",
-			cmd, dsn, lid, code, username);
-
-	if (cmd == (MSIM_CMD_BIT_REPLY | MSIM_CMD_PUT)
-			&& dsn == MC_SET_USERNAME_DSN
-			&& lid == MC_SET_USERNAME_LID)
-	{
-		purple_debug_info("msim_username_is_set_cb", "Proper cmd,dsn,lid for username_is_set!\n");
-		purple_debug_info("msim_username_is_set_cb", "Username Set with return code %d\n",code);
-		if (code == 0) {
-			/* Good! */
-			session->username = username;
-			msim_we_are_logged_on(session);
-		} else {
-			purple_debug_info("msim_username_is_set", "code is %d",code);
-			/* TODO: what to do here? */
-		}
-	} else if (cmd == (MSIM_CMD_BIT_REPLY | MSIM_CMD_GET)
-			&& dsn == MG_MYSPACE_INFO_BY_STRING_DSN
-			&& lid == MG_MYSPACE_INFO_BY_STRING_LID) {
-		/* Not quite done... ONE MORE STEP :) */
-		rid = msim_new_reply_callback(session, msim_username_is_set_cb, data);
-		body = msim_msg_new("UserName", MSIM_TYPE_STRING, g_strdup(username), NULL);
-		if (!msim_send(session, "persist", MSIM_TYPE_INTEGER, 1,
-					"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-					"cmd", MSIM_TYPE_INTEGER, MSIM_CMD_PUT,
-					"dsn", MSIM_TYPE_INTEGER, MC_SET_USERNAME_DSN,
-					"uid", MSIM_TYPE_INTEGER, session->userid,
-					"lid", MSIM_TYPE_INTEGER, MC_SET_USERNAME_LID,
-					"rid", MSIM_TYPE_INTEGER, rid,
-					"body", MSIM_TYPE_DICTIONARY, body,
-					NULL)) {
-			/* Error! */
-			/* Can't set... Disconnect */
-			purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
-		}
-
-	} else {
-		/* Error! */
-		purple_debug_info("msim","username_is_set Error: Invalid cmd/dsn/lid combination");
-		purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
-	}
-}
-
-/**
- * Asynchronously set new username, calling callback when receive result.
- *
- * @param session
- * @param username The username we're setting for ourselves. Not freed.
- * @param cb Callback, called with user information when available.
- * @param data An arbitray data pointer passed to the callback.
- */
-static void
-msim_set_username(MsimSession *session, const gchar *username,
-		MSIM_USER_LOOKUP_CB cb, gpointer data)
-{
-	MsimMessage *body;
-	guint rid;
-
-	g_return_if_fail(username != NULL);
-	g_return_if_fail(cb != NULL);
-
-	purple_debug_info("msim", "msim_set_username: "
-			"Setting username %s\n", username);
-
-	/* Setup callback. Response will be associated with request using 'rid'. */
-	rid = msim_new_reply_callback(session, cb, data);
-
-	/* TODO: I dont know if the ContactType is -/ALWAYS/- 1 */
-
-	body = msim_msg_new("UserName", MSIM_TYPE_STRING, g_strdup(username),NULL);
-/* \setinfo\\sesskey\469958979\info\Age=21.AvatarUrl=.BandName=.ContactType=1.DisplayName=Msim.Gender=M.ImageURL=http:/1/1x.myspace.com/1images/1no_pic.gif.LastLogin=128335268400000000.Location=US.ShowAvatar=False.SongName=.TotalFriends=1.UserName=msimprpl2\final\
-*/
-
-	/* Send request */
-	g_return_if_fail(msim_send(session,
-			 "setinfo", MSIM_TYPE_BOOLEAN, TRUE,
-			 "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-			 "info", MSIM_TYPE_DICTIONARY, body,
-			 NULL));
-	body = msim_msg_new("UserName", MSIM_TYPE_STRING, g_strdup(username),NULL);
-	g_return_if_fail(msim_send(session,
-			 "persist", MSIM_TYPE_INTEGER, 1,
-			 "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-			 "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
-			 "dsn", MSIM_TYPE_INTEGER, MG_MYSPACE_INFO_BY_STRING_DSN,
-			 "uid", MSIM_TYPE_INTEGER, session->userid,
-			 "lid", MSIM_TYPE_INTEGER, MG_MYSPACE_INFO_BY_STRING_LID,
-			 "rid", MSIM_TYPE_INTEGER, rid,
-			 "body", MSIM_TYPE_DICTIONARY, body,
-			 NULL));
-}
-
-/**
- * They've confirmed that username that was available, Lets make the call to set it
- */
-static void msim_set_username_confirmed_cb(PurpleConnection *gc)
-{
-	MsimMessage *user_msg;
-	MsimSession *session;
-
-	g_return_if_fail(gc != NULL);
-
-	session = (MsimSession *)gc->proto_data;
-
-	user_msg = msim_msg_new(
-			"user", MSIM_TYPE_STRING, g_strdup(msim_username_to_set),
-			NULL);
-
-	purple_debug_info("msim_set_username_confirmed_cb", "Setting username to %s\n", msim_username_to_set);
-
-	/* Sets our username... keep your fingers crossed :) */
-	msim_set_username(session, msim_username_to_set, msim_username_is_set_cb, user_msg);
-	g_free(msim_username_to_set);
-}
-
-/**
- * This is where we do a bit more than merely prompt the user.
- * Now we have some real data to tell us the state of their requested username
- * \persistr\\cmd\257\dsn\5\uid\204084363\lid\7\rid\367\body\UserName=TheAlbinoRhino1\final\
- */
-static void msim_username_is_available_cb(MsimSession *session, const MsimMessage *userinfo, gpointer data)
-{
-	MsimMessage *msg;
-	gchar *username;
-	MsimMessage *body;
-	gint userid;
-
-	purple_debug_info("msim_username_is_available_cb", "Look up username callback made\n");
-
-	msg = (MsimMessage *)data;
-	g_return_if_fail(msg != NULL);
-
-	username = msim_msg_get_string(msg, "user");
-	body = msim_msg_get_dictionary(userinfo, "body");
-
-	if (!body) {
-		purple_debug_info("msim_username_is_available_cb", "No body for %s?!\n", username);
-		purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-				_("An error occurred while trying to set the username.  "
-				"Please try again, or visit http://editprofile.myspace.com/index.cfm?"
-				"fuseaction=profile.username to set your username."));
-		return;
-	}
-
-	userid = msim_msg_get_integer(body, "UserID");
-
-	purple_debug_info("msim_username_is_available_cb", "Returned username is %s and userid is %d\n", username, userid);
-	msim_msg_free(body);
-	msim_msg_free(msg);
-
-	/* The response for a free username will ONLY have the UserName in it..
-	 * thus making UserID return 0 when we msg_get_integer it */
-	if (userid == 0) {
-		/* This username is currently unused */
-		purple_debug_info("msim_username_is_available_cb", "Username available. Prompting to Confirm.\n");
-		msim_username_to_set = g_strdup(username);
-		g_free(username);
-		purple_request_yes_no(session->gc,
-			_("MySpaceIM - Username Available"),
-			_("This username is available. Would you like to set it?"),
-			_("ONCE SET, THIS CANNOT BE CHANGED!"),
-			0,
-			session->account,
-			NULL,
-			NULL,
-			session->gc,
-			G_CALLBACK(msim_set_username_confirmed_cb),
-			G_CALLBACK(msim_do_not_set_username_cb));
-	} else {
-		/* Looks like its in use or we have an invalid response */
-		purple_debug_info("msim_username_is_available_cb", "Username unavaiable. Prompting for new entry.\n");
-		purple_request_input(session->gc, _("MySpaceIM - Please Set a Username"),
-			_("This username is unavailable."),
-				_("Please try another username:"),
-				"", FALSE, FALSE, NULL,
-				_("OK"), G_CALLBACK(msim_check_username_availability_cb),
-				_("Cancel"), G_CALLBACK(msim_do_not_set_username_cb),
-				session->account,
-				NULL,
-				NULL,
-				session->gc);
-	}
-}
-
-/**
- * Once they've submitted their desired new username,
- * check if it is available here.
- */
-static void msim_check_username_availability_cb(PurpleConnection *gc, const char *username_to_check)
-{
-	MsimMessage *user_msg;
-	MsimSession *session;
-
-	g_return_if_fail(gc != NULL);
-
-	session = (MsimSession *)gc->proto_data;
-
-	purple_debug_info("msim_check_username_availability_cb", "Checking username: %s\n", username_to_check);
-
-	user_msg = msim_msg_new(
-			"user", MSIM_TYPE_STRING, g_strdup(username_to_check),
-			NULL);
-
-	/* 25 characters: letters, numbers, underscores */
-	/* TODO: VERIFY ABOVE */
-
-	/* \persist\1\sesskey\288500516\cmd\1\dsn\5\uid\204084363\lid\7\rid\367\body\UserName=Jaywalker\final\ */
-	/* Official client uses a standard lookup... So do we! */
-	msim_lookup_user(session, username_to_check, msim_username_is_available_cb, user_msg);
-}
-
-/***
- * If they hit cancel or no at any point in the Setting Username process,
- * we come here.  Currently we're safe letting them get by without
- * setting it, unless we hear otherwise.  So for now give them a menu.
- * If this becomes an issue with the official client then boot them here.
- */
-void msim_do_not_set_username_cb(PurpleConnection *gc)
-{
-	purple_debug_info("msim", "Don't set username");
-
-	/* Protocol won't log in now without a username set.. Disconnect */
-	purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("No username set"));
-}
-
-/**
- * They've decided to set a username! Yay!
- */
-void msim_set_username_cb(PurpleConnection *gc)
-{
-	g_return_if_fail(gc != NULL);
-	purple_debug_info("msim","Set username\n");
-	purple_request_input(gc, _("MySpaceIM - Please Set a Username"),
-			_("Please enter a username to check its availability:"),
-			NULL,
-			"", FALSE, FALSE, NULL,
-			_("OK"), G_CALLBACK(msim_check_username_availability_cb),
-			_("Cancel"), G_CALLBACK(msim_do_not_set_username_cb),
-			purple_connection_get_account(gc),
-			NULL,
-			NULL,
-			gc);
-}
deleted file mode 100644
--- a/libpurple/protocols/myspace/user.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* MySpaceIM Protocol Plugin, header file
- *
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- *
- * 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 _MYSPACE_USER_H
-#define _MYSPACE_USER_H
-
-/* Hold ephemeral information about buddies, for proto_data of PurpleBuddy. */
-/* GHashTable? */
-typedef struct _MsimUser
-{
-	PurpleBuddy *buddy;
-	/* Note: id is also &buddy->node (set_blist_node_int), when buddy is non-NULL */
-	int id;
-	guint client_cv;
-	gchar *client_info;
-	guint age;
-	gchar *gender;
-	gchar *location;
-	guint total_friends;
-	gchar *headline;
-	gchar *display_name;
-	gchar *username;
-	gchar *band_name, *song_name;
-	gchar *image_url;
-	guint last_image_updated;
-	gboolean temporary_user;
-	PurpleUtilFetchUrlData *url_data;
-} MsimUser;
-
-/* Callback function pointer type for when a user's information is received,
- * initiated from a user lookup. */
-typedef void (*MSIM_USER_LOOKUP_CB)(MsimSession *session, const MsimMessage *userinfo, gpointer data);
-
-MsimUser *msim_get_user_from_buddy(PurpleBuddy *buddy, gboolean create);
-void msim_user_free(MsimUser *user);
-MsimUser *msim_find_user(MsimSession *session, const gchar *username);
-void msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full);
-gboolean msim_store_user_info(MsimSession *session, const MsimMessage *msg, MsimUser *user);
-gboolean msim_is_userid(const gchar *user);
-void msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data);
-void msim_set_username_cb(PurpleConnection *gc);
-void msim_do_not_set_username_cb(PurpleConnection *gc);
-
-#endif /* !_MYSPACE_USER_H */
deleted file mode 100644
--- a/libpurple/protocols/myspace/zap.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/* MySpaceIM Protocol Plugin - zap support
- *
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- *
- * 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 "myspace.h"
-#include "zap.h"
-
-/** Get zap types. */
-GList *
-msim_attention_types(PurpleAccount *acct)
-{
-	static GList *types = NULL;
-	PurpleAttentionType* attn;
-
-	if (!types) {
-#define _MSIM_ADD_NEW_ATTENTION(icn, ulname, nme, incoming, outgoing) \
-		attn = purple_attention_type_new(ulname, nme, incoming, outgoing); \
-		purple_attention_type_set_icon_name(attn, icn); \
-		types = g_list_append(types, attn);
-
-		/* TODO: icons for each zap */
-
-		/* Lots of comments for translators: */
-
-		/* Zap means "to strike suddenly and forcefully as if with a
-		 * projectile or weapon."  This term often has an electrical
-		 * connotation, for example, "he was zapped by electricity when
-		 * he put a fork in the toaster." */
-		_MSIM_ADD_NEW_ATTENTION(NULL, "Zap", _("Zap"), _("%s has zapped you!"),
-				_("Zapping %s..."));
-
-		/* Whack means "to hit or strike someone with a sharp blow" */
-		_MSIM_ADD_NEW_ATTENTION(NULL, "Whack", _("Whack"),
-				_("%s has whacked you!"), _("Whacking %s..."));
-
-		/* Torch means "to set on fire."  Don't worry, this doesn't
-		 * make a whole lot of sense in English, either.  Feel free
-		 * to translate it literally. */
-		_MSIM_ADD_NEW_ATTENTION(NULL, "Torch", _("Torch"),
-				_("%s has torched you!"), _("Torching %s..."));
-
-		/* Smooch means "to kiss someone, often enthusiastically" */
-		_MSIM_ADD_NEW_ATTENTION(NULL, "Smooch", _("Smooch"),
-				_("%s has smooched you!"), _("Smooching %s..."));
-
-		/* A hug is a display of affection; wrapping your arms around someone */
-		_MSIM_ADD_NEW_ATTENTION(NULL, "Hug", _("Hug"), _("%s has hugged you!"),
-				_("Hugging %s..."));
-
-		/* Slap means "to hit someone with an open/flat hand" */
-		_MSIM_ADD_NEW_ATTENTION(NULL, "Slap", _("Slap"),
-				_("%s has slapped you!"), _("Slapping %s..."));
-
-		/* Goose means "to pinch someone on their butt" */
-		_MSIM_ADD_NEW_ATTENTION(NULL, "Goose", _("Goose"),
-				_("%s has goosed you!"), _("Goosing %s..."));
-
-		/* A high-five is when two people's hands slap each other
-		 * in the air above their heads.  It is done to celebrate
-		 * something, often a victory, or to congratulate someone. */
-		_MSIM_ADD_NEW_ATTENTION(NULL, "High-five", _("High-five"),
-				_("%s has high-fived you!"), _("High-fiving %s..."));
-
-		/* We're not entirely sure what the MySpace people mean by
-		 * this... but we think it's the equivalent of "prank."  Or, for
-		 * someone to perform a mischievous trick or practical joke. */
-		_MSIM_ADD_NEW_ATTENTION(NULL, "Punk", _("Punk"),
-				_("%s has punk'd you!"), _("Punking %s..."));
-
-		/* Raspberry is a slang term for the vibrating sound made
-		 * when you stick your tongue out of your mouth with your
-		 * lips closed and blow.  It is typically done when
-		 * gloating or bragging.  Nowadays it's a pretty silly
-		 * gesture, so it does not carry a harsh negative
-		 * connotation.  It is generally used in a playful tone
-		 * with friends. */
-		_MSIM_ADD_NEW_ATTENTION(NULL, "Raspberry", _("Raspberry"),
-				_("%s has raspberried you!"), _("Raspberrying %s..."));
-	}
-
-	return types;
-}
-
-/** Send a zap to a user. */
-static gboolean
-msim_send_zap(MsimSession *session, const gchar *username, guint code)
-{
-	gchar *zap_string;
-	gboolean rc;
-
-	g_return_val_if_fail(session != NULL, FALSE);
-	g_return_val_if_fail(username != NULL, FALSE);
-
-	/* Construct and send the actual zap command. */
-	zap_string = g_strdup_printf("!!!ZAP_SEND!!!=RTE_BTN_ZAPS_%d", code);
-
-	if (!msim_send_bm(session, username, zap_string, MSIM_BM_ACTION_OR_IM_INSTANT)) {
-		purple_debug_info("msim_send_zap",
-				"msim_send_bm failed: zapping %s with %s\n",
-				username, zap_string);
-		rc = FALSE;
-	} else {
-		rc = TRUE;
-	}
-
-	g_free(zap_string);
-
-	return rc;
-}
-
-/** Send a zap */
-gboolean
-msim_send_attention(PurpleConnection *gc, const gchar *username, guint code)
-{
-	GList *types;
-	MsimSession *session;
-	PurpleAttentionType *attn;
-	PurpleBuddy *buddy;
-
-	session = (MsimSession *)gc->proto_data;
-
-	/* Look for this attention type, by the code index given. */
-	types = msim_attention_types(gc->account);
-	attn = (PurpleAttentionType *)g_list_nth_data(types, code);
-
-	if (!attn) {
-		purple_debug_info("msim_send_attention", "got invalid zap code %d\n", code);
-		return FALSE;
-	}
-
-	buddy = purple_find_buddy(session->account, username);
-	if (!buddy) {
-		return FALSE;
-	}
-
-	msim_send_zap(session, username, code);
-
-	return TRUE;
-}
-
-/** Zap someone. Callback from msim_blist_node_menu zap menu. */
-static void
-msim_send_zap_from_menu(PurpleBlistNode *node, gpointer zap_num_ptr)
-{
-	PurpleBuddy *buddy;
-	PurpleAccount *account;
-	PurpleConnection *gc;
-	MsimSession *session;
-	guint zap;
-
-	if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) {
-		/* Only know about buddies for now. */
-		return;
-	}
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *)node;
-
-	/* Find the session */
-	account = purple_buddy_get_account(buddy);
-	gc = purple_account_get_connection(account);
-	session = (MsimSession *)gc->proto_data;
-
-	zap = GPOINTER_TO_INT(zap_num_ptr);
-
-	purple_prpl_send_attention(session->gc, purple_buddy_get_name(buddy), zap);
-}
-
-/** Return menu, if any, for a buddy list node. */
-GList *
-msim_blist_node_menu(PurpleBlistNode *node)
-{
-	GList *menu, *zap_menu;
-	GList *types;
-	PurpleMenuAction *act;
-	guint i;
-
-	if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) {
-		/* Only know about buddies for now. */
-		return NULL;
-	}
-
-	zap_menu = NULL;
-
-	/* TODO: get rid of once is accessible directly in GUI */
-	types = msim_attention_types(NULL);
-	i = 0;
-	for (; types; types = g_list_next(types)) {
-		PurpleAttentionType *attn;
-
-		attn = (PurpleAttentionType *)types->data;
-
-		act = purple_menu_action_new(purple_attention_type_get_name(attn),
-				PURPLE_CALLBACK(msim_send_zap_from_menu), GUINT_TO_POINTER(i), NULL);
-		zap_menu = g_list_append(zap_menu, act);
-
-		++i;
-	}
-
-	act = purple_menu_action_new(_("Zap"), NULL, NULL, zap_menu);
-	menu = g_list_append(NULL, act);
-
-	return menu;
-}
-
-/** Process an incoming zap. */
-gboolean
-msim_incoming_zap(MsimSession *session, MsimMessage *msg)
-{
-	gchar *msg_text, *username;
-	gint zap;
-
-	msg_text = msim_msg_get_string(msg, "msg");
-	username = msim_msg_get_string(msg, "_username");
-
-	g_return_val_if_fail(msg_text != NULL, FALSE);
-	g_return_val_if_fail(username != NULL, FALSE);
-
-	g_return_val_if_fail(sscanf(msg_text, "!!!ZAP_SEND!!!=RTE_BTN_ZAPS_%d", &zap) == 1, FALSE);
-
-	zap = CLAMP(zap, 0, 9);
-
-	purple_prpl_got_attention(session->gc, username, zap);
-
-	g_free(msg_text);
-	g_free(username);
-
-	return TRUE;
-}
deleted file mode 100644
--- a/libpurple/protocols/myspace/zap.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* MySpaceIM Protocol Plugin - zap support
- *
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- *
- * 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 _MYSPACE_ZAP_H
-#define _MYSPACE_ZAP_H
-
-GList *msim_attention_types(PurpleAccount *acct);
-gboolean msim_send_attention(PurpleConnection *gc, const gchar *username, guint code);
-GList *msim_blist_node_menu(PurpleBlistNode *node);
-gboolean msim_incoming_zap(MsimSession *session, MsimMessage *msg);
-
-#endif /* !_MYSPACE_ZAP_H */
deleted file mode 100644
--- a/libpurple/protocols/yahoo/Makefile.in
+++ /dev/null
@@ -1,13 +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	= yahoo
-
-include $(srcdir)/../prpl.mk
-
-include $(srcdir)/../prpl-rules.mk
deleted file mode 100644
--- a/libpurple/protocols/yahoo/libyahoo.c
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * 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 <account.h>
-#include <core.h>
-
-#include "libymsg.h"
-#include "yahoochat.h"
-#include "yahoo_aliases.h"
-#include "yahoo_doodle.h"
-#include "yahoo_filexfer.h"
-#include "yahoo_picture.h"
-
-static PurplePlugin *my_protocol = NULL;
-
-static void yahoo_register_commands(void)
-{
-	purple_cmd_register("join", "s", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-	                  PURPLE_CMD_FLAG_PRPL_ONLY,
-	                  "prpl-yahoo", yahoopurple_cmd_chat_join,
-	                  _("join &lt;room&gt;:  Join a chat room on the Yahoo network"), NULL);
-	purple_cmd_register("list", "", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-	                  PURPLE_CMD_FLAG_PRPL_ONLY,
-	                  "prpl-yahoo", yahoopurple_cmd_chat_list,
-	                  _("list: List rooms on the Yahoo network"), NULL);
-	purple_cmd_register("buzz", "", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
-	                  "prpl-yahoo", yahoopurple_cmd_buzz,
-	                  _("buzz: Buzz a user to get their attention"), NULL);
-	purple_cmd_register("doodle", "", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
-	                  "prpl-yahoo", yahoo_doodle_purple_cmd_start,
-	                 _("doodle: Request user to start a Doodle session"), NULL);
-}
-
-static PurpleAccount *find_acct(const char *prpl, const char *acct_id)
-{
-	PurpleAccount *acct = NULL;
-
-	/* If we have a specific acct, use it */
-	if (acct_id) {
-		acct = purple_accounts_find(acct_id, prpl);
-		if (acct && !purple_account_is_connected(acct))
-			acct = NULL;
-	} else { /* Otherwise find an active account for the protocol */
-		GList *l = purple_accounts_get_all();
-		while (l) {
-			if (!strcmp(prpl, purple_account_get_protocol_id(l->data))
-					&& purple_account_is_connected(l->data)) {
-				acct = l->data;
-				break;
-			}
-			l = l->next;
-		}
-	}
-
-	return acct;
-}
-
-/* This may not be the best way to do this, but we find the first key w/o a value
- * and assume it is the buddy name */
-static void yahoo_find_uri_novalue_param(gpointer key, gpointer value, gpointer user_data)
-{
-	char **retval = user_data;
-
-	if (value == NULL && *retval == NULL) {
-		*retval = key;
-	}
-}
-
-static gboolean yahoo_uri_handler(const char *proto, const char *cmd, GHashTable *params)
-{
-	char *acct_id = g_hash_table_lookup(params, "account");
-	PurpleAccount *acct;
-
-	if (g_ascii_strcasecmp(proto, "ymsgr"))
-		return FALSE;
-
-	acct = find_acct(purple_plugin_get_id(my_protocol), acct_id);
-
-	if (!acct)
-		return FALSE;
-
-	/* ymsgr:SendIM?screename&m=The+Message */
-	if (!g_ascii_strcasecmp(cmd, "SendIM")) {
-		char *sname = NULL;
-		g_hash_table_foreach(params, yahoo_find_uri_novalue_param, &sname);
-		if (sname) {
-			char *message = g_hash_table_lookup(params, "m");
-
-			PurpleConversation *conv = purple_find_conversation_with_account(
-				PURPLE_CONV_TYPE_IM, sname, acct);
-			if (conv == NULL)
-				conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, sname);
-			purple_conversation_present(conv);
-
-			if (message) {
-				/* Spaces are encoded as '+' */
-				g_strdelimit(message, "+", ' ');
-				purple_conv_send_confirm(conv, message);
-			}
-		}
-		/* else
-			**If pidgindialogs_im() was in the core, we could use it here.
-			 * It is all purple_request_* based, but I'm not sure it really belongs in the core
-			pidgindialogs_im(); */
-
-		return TRUE;
-	}
-	/* ymsgr:Chat?roomname */
-	else if (!g_ascii_strcasecmp(cmd, "Chat")) {
-		char *rname = NULL;
-		g_hash_table_foreach(params, yahoo_find_uri_novalue_param, &rname);
-		if (rname) {
-			/* This is somewhat hacky, but the params aren't useful after this command */
-			g_hash_table_insert(params, g_strdup("room"), g_strdup(rname));
-			g_hash_table_insert(params, g_strdup("type"), g_strdup("Chat"));
-			serv_join_chat(purple_account_get_connection(acct), params);
-		}
-		/* else
-			** Same as above (except that this would have to be re-written using purple_request_*)
-			pidgin_blist_joinchat_show(); */
-
-		return TRUE;
-	}
-	/* ymsgr:AddFriend?name */
-	else if (!g_ascii_strcasecmp(cmd, "AddFriend")) {
-		char *name = NULL;
-		g_hash_table_foreach(params, yahoo_find_uri_novalue_param, &name);
-		purple_blist_request_add_buddy(acct, name, NULL, NULL);
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-static GHashTable *
-yahoo_get_account_text_table(PurpleAccount *account)
-{
-	GHashTable *table;
-	table = g_hash_table_new(g_str_hash, g_str_equal);
-	g_hash_table_insert(table, "login_label", (gpointer)_("Yahoo ID..."));
-	return table;
-}
-
-static gboolean yahoo_unload_plugin(PurplePlugin *plugin)
-{
-	yahoo_dest_colorht();
-
-	return TRUE;
-}
-
-static PurpleWhiteboardPrplOps yahoo_whiteboard_prpl_ops =
-{
-	yahoo_doodle_start,
-	yahoo_doodle_end,
-	yahoo_doodle_get_dimensions,
-	NULL,
-	yahoo_doodle_get_brush,
-	yahoo_doodle_set_brush,
-	yahoo_doodle_send_draw_list,
-	yahoo_doodle_clear,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static PurplePluginProtocolInfo prpl_info =
-{
-	OPT_PROTO_MAIL_CHECK | OPT_PROTO_CHAT_TOPIC,
-	NULL, /* user_splits */
-	NULL, /* protocol_options */
-	{"png,gif,jpeg", 96, 96, 96, 96, 0, PURPLE_ICON_SCALE_SEND},
-	yahoo_list_icon,
-	yahoo_list_emblem,
-	yahoo_status_text,
-	yahoo_tooltip_text,
-	yahoo_status_types,
-	yahoo_blist_node_menu,
-	yahoo_c_info,
-	yahoo_c_info_defaults,
-	yahoo_login,
-	yahoo_close,
-	yahoo_send_im,
-	NULL, /* set info */
-	yahoo_send_typing,
-	yahoo_get_info,
-	yahoo_set_status,
-	yahoo_set_idle,
-	NULL, /* change_passwd*/
-	yahoo_add_buddy,
-	NULL, /* add_buddies */
-	yahoo_remove_buddy,
-	NULL, /* remove_buddies */
-	NULL, /* add_permit */
-	yahoo_add_deny,
-	NULL, /* rem_permit */
-	yahoo_rem_deny,
-	yahoo_set_permit_deny,
-	yahoo_c_join,
-	NULL, /* reject chat invite */
-	yahoo_get_chat_name,
-	yahoo_c_invite,
-	yahoo_c_leave,
-	NULL, /* chat whisper */
-	yahoo_c_send,
-	yahoo_keepalive,
-	NULL, /* register_user */
-	NULL, /* get_cb_info */
-	NULL, /* get_cb_away */
-	yahoo_update_alias, /* alias_buddy */
-	yahoo_change_buddys_group,
-	yahoo_rename_group,
-	NULL, /* buddy_free */
-	NULL, /* convo_closed */
-	purple_normalize_nocase, /* normalize */
-	yahoo_set_buddy_icon,
-	NULL, /* void (*remove_group)(PurpleConnection *gc, const char *group);*/
-	NULL, /* char *(*get_cb_real_name)(PurpleConnection *gc, int id, const char *who); */
-	NULL, /* set_chat_topic */
-	NULL, /* find_blist_chat */
-	yahoo_roomlist_get_list,
-	yahoo_roomlist_cancel,
-	yahoo_roomlist_expand_category,
-	yahoo_can_receive_file, /* can_receive_file */
-	yahoo_send_file,
-	yahoo_new_xfer,
-	yahoo_offline_message, /* offline_message */
-	&yahoo_whiteboard_prpl_ops,
-	NULL, /* send_raw */
-	NULL, /* roomlist_room_serialize */
-	NULL, /* unregister_user */
-
-	yahoo_send_attention,
-	yahoo_attention_types,
-
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
-	yahoo_get_account_text_table,    /* get_account_text_table */
-	NULL, /* initiate_media */
-	NULL,  /* get_media_caps */
-	NULL,  /* get_moods */
-	NULL,  /* set_public_alias */
-	NULL,  /* get_public_alias */
-	NULL,  /* add_buddy_with_invite */
-	NULL   /* add_buddies_with_invite */
-};
-
-static PurplePluginInfo info =
-{
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                             /**< type           */
-	NULL,                                             /**< ui_requirement */
-	0,                                                /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                            /**< priority       */
-	"prpl-yahoo",                                     /**< id             */
-	"Yahoo",	                                      /**< name           */
-	DISPLAY_VERSION,                                  /**< version        */
-	                                                  /**  summary        */
-	N_("Yahoo! Protocol Plugin"),
-	                                                  /**  description    */
-	N_("Yahoo! Protocol Plugin"),
-	NULL,                                             /**< author         */
-	PURPLE_WEBSITE,                                     /**< homepage       */
-	NULL,                                             /**< load           */
-	yahoo_unload_plugin,                              /**< unload         */
-	NULL,                                             /**< destroy        */
-	NULL,                                             /**< ui_info        */
-	&prpl_info,                                       /**< extra_info     */
-	NULL,
-	yahoo_actions,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-gboolean purple_init_yahoojp_plugin(void);
-
-static void
-init_plugin(PurplePlugin *plugin)
-{
-	PurpleAccountOption *option;
-
-	option = purple_account_option_int_new(_("Pager port"), "port", YAHOO_PAGER_PORT);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	option = purple_account_option_string_new(_("File transfer server"), "xfer_host", YAHOO_XFER_HOST);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	option = purple_account_option_int_new(_("File transfer port"), "xfer_port", YAHOO_XFER_PORT);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	option = purple_account_option_string_new(_("Chat room locale"), "room_list_locale", YAHOO_ROOMLIST_LOCALE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	option = purple_account_option_string_new(_("Encoding"), "local_charset", "UTF-8");
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	option = purple_account_option_bool_new(_("Ignore conference and chatroom invitations"), "ignore_invites", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	option = purple_account_option_bool_new(_("Use account proxy for HTTP and HTTPS connections"), "proxy_ssl", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-#if 0
-	option = purple_account_option_string_new(_("Chat room list URL"), "room_list", YAHOO_ROOMLIST_URL);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-#endif
-
-	my_protocol = plugin;
-	yahoo_register_commands();
-	yahoo_init_colorht();
-
-	purple_signal_connect(purple_get_core(), "uri-handler", plugin,
-		PURPLE_CALLBACK(yahoo_uri_handler), NULL);
-	purple_init_yahoojp_plugin();
-}
-
-PURPLE_INIT_PLUGIN(yahoo, init_plugin, info);
deleted file mode 100644
--- a/libpurple/protocols/yahoo/libyahoojp.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * 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 PURPLE_STATIC_PRPL
-#define PURPLE_STATIC_PRPL
-#endif
-#include "internal.h"
-
-#include <account.h>
-
-#include "libymsg.h"
-#include "yahoochat.h"
-#include "yahoo_aliases.h"
-#include "yahoo_doodle.h"
-#include "yahoo_filexfer.h"
-#include "yahoo_picture.h"
-
-static void yahoojp_register_commands(void)
-{
-	purple_cmd_register("join", "s", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-	                  PURPLE_CMD_FLAG_PRPL_ONLY,
-	                  "prpl-yahoojp", yahoopurple_cmd_chat_join,
-	                  _("join &lt;room&gt;:  Join a chat room on the Yahoo network"), NULL);
-	purple_cmd_register("list", "", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-	                  PURPLE_CMD_FLAG_PRPL_ONLY,
-	                  "prpl-yahoojp", yahoopurple_cmd_chat_list,
-	                  _("list: List rooms on the Yahoo network"), NULL);
-	purple_cmd_register("buzz", "", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
-	                  "prpl-yahoojp", yahoopurple_cmd_buzz,
-	                  _("buzz: Buzz a user to get their attention"), NULL);
-	purple_cmd_register("doodle", "", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
-	                  "prpl-yahoojp", yahoo_doodle_purple_cmd_start,
-	                 _("doodle: Request user to start a Doodle session"), NULL);
-}
-
-static GHashTable *
-yahoojp_get_account_text_table(PurpleAccount *account)
-{
-	GHashTable *table;
-	table = g_hash_table_new(g_str_hash, g_str_equal);
-	g_hash_table_insert(table, "login_label", (gpointer)_("Yahoo JAPAN ID..."));
-	return table;
-}
-
-static gboolean yahoojp_unload_plugin(PurplePlugin *plugin)
-{
-	yahoo_dest_colorht();
-
-	return TRUE;
-}
-
-static PurpleWhiteboardPrplOps yahoo_whiteboard_prpl_ops =
-{
-	yahoo_doodle_start,
-	yahoo_doodle_end,
-	yahoo_doodle_get_dimensions,
-	NULL,
-	yahoo_doodle_get_brush,
-	yahoo_doodle_set_brush,
-	yahoo_doodle_send_draw_list,
-	yahoo_doodle_clear,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static PurplePluginProtocolInfo prpl_info =
-{
-	OPT_PROTO_MAIL_CHECK | OPT_PROTO_CHAT_TOPIC,
-	NULL, /* user_splits */
-	NULL, /* protocol_options */
-	{"png,gif,jpeg", 96, 96, 96, 96, 0, PURPLE_ICON_SCALE_SEND},
-	yahoo_list_icon,
-	yahoo_list_emblem,
-	yahoo_status_text,
-	yahoo_tooltip_text,
-	yahoo_status_types,
-	yahoo_blist_node_menu,
-	yahoo_c_info,
-	yahoo_c_info_defaults,
-	yahoo_login,
-	yahoo_close,
-	yahoo_send_im,
-	NULL, /* set info */
-	yahoo_send_typing,
-	yahoo_get_info,
-	yahoo_set_status,
-	yahoo_set_idle,
-	NULL, /* change_passwd*/
-	yahoo_add_buddy,
-	NULL, /* add_buddies */
-	yahoo_remove_buddy,
-	NULL, /* remove_buddies */
-	NULL, /* add_permit */
-	yahoo_add_deny,
-	NULL, /* rem_permit */
-	yahoo_rem_deny,
-	yahoo_set_permit_deny,
-	yahoo_c_join,
-	NULL, /* reject chat invite */
-	yahoo_get_chat_name,
-	yahoo_c_invite,
-	yahoo_c_leave,
-	NULL, /* chat whisper */
-	yahoo_c_send,
-	yahoo_keepalive,
-	NULL, /* register_user */
-	NULL, /* get_cb_info */
-	NULL, /* get_cb_away */
-	yahoo_update_alias, /* alias_buddy */
-	yahoo_change_buddys_group,
-	yahoo_rename_group,
-	NULL, /* buddy_free */
-	NULL, /* convo_closed */
-	purple_normalize_nocase, /* normalize */
-	yahoo_set_buddy_icon,
-	NULL, /* void (*remove_group)(PurpleConnection *gc, const char *group);*/
-	NULL, /* char *(*get_cb_real_name)(PurpleConnection *gc, int id, const char *who); */
-	NULL, /* set_chat_topic */
-	NULL, /* find_blist_chat */
-	yahoo_roomlist_get_list,
-	yahoo_roomlist_cancel,
-	yahoo_roomlist_expand_category,
-	NULL, /* can_receive_file */
-	yahoo_send_file,
-	yahoo_new_xfer,
-	yahoo_offline_message, /* offline_message */
-	&yahoo_whiteboard_prpl_ops,
-	NULL, /* send_raw */
-	NULL, /* roomlist_room_serialize */
-	NULL, /* unregister_user */
-
-	yahoo_send_attention,
-	yahoo_attention_types,
-
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
-	yahoojp_get_account_text_table,    /* get_account_text_table */
-	NULL, /* initiate_media */
-	NULL, /* get_media_caps */
-	NULL, /* get_moods */
-	NULL, /* set_public_alias */
-	NULL, /* get_public_alias */
-	NULL, /* add_buddy_with_invite */
-	NULL  /* add_buddies_with_invite */
-};
-
-static PurplePluginInfo info =
-{
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                             /**< type           */
-	NULL,                                             /**< ui_requirement */
-	0,                                                /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                            /**< priority       */
-	"prpl-yahoojp",                                     /**< id             */
-	"Yahoo JAPAN",	                                      /**< name           */
-	DISPLAY_VERSION,                                  /**< version        */
-	                                                  /**  summary        */
-	N_("Yahoo! JAPAN Protocol Plugin"),
-	                                                  /**  description    */
-	N_("Yahoo! JAPAN Protocol Plugin"),
-	NULL,                                             /**< author         */
-	PURPLE_WEBSITE,                                     /**< homepage       */
-	NULL,                                             /**< load           */
-	yahoojp_unload_plugin,                              /**< unload         */
-	NULL,                                             /**< destroy        */
-	NULL,                                             /**< ui_info        */
-	&prpl_info,                                       /**< extra_info     */
-	NULL,
-	yahoo_actions,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void
-init_plugin(PurplePlugin *plugin)
-{
-	PurpleAccountOption *option;
-
-	option = purple_account_option_int_new(_("Pager port"), "port", YAHOO_PAGER_PORT);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	option = purple_account_option_string_new(_("File transfer server"), "xfer_host", YAHOOJP_XFER_HOST);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	option = purple_account_option_int_new(_("File transfer port"), "xfer_port", YAHOO_XFER_PORT);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	option = purple_account_option_string_new(_("Chat room locale"), "room_list_locale", YAHOOJP_ROOMLIST_LOCALE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	option = purple_account_option_string_new(_("Encoding"), "local_charset", "UTF-8");
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	option = purple_account_option_bool_new(_("Ignore conference and chatroom invitations"), "ignore_invites", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	option = purple_account_option_bool_new(_("Use account proxy for HTTP and HTTPS connections"), "proxy_ssl", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-#if 0
-	option = purple_account_option_string_new(_("Chat room list URL"), "room_list", YAHOO_ROOMLIST_URL);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-#endif
-
-	yahoojp_register_commands();
-	yahoo_init_colorht();
-}
-
-PURPLE_INIT_PLUGIN(yahoojp, init_plugin, info);
-
deleted file mode 100644
--- a/libpurple/protocols/yahoo/libymsg.c
+++ /dev/null
@@ -1,5516 +0,0 @@
-/*
- * 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
- *
- */
-
-/*
- * Note: When handling the list of struct yahoo_pair's from an incoming
- * packet the value might not be UTF-8. You should either validate that
- * it is UTF-8 using g_utf8_validate() or use yahoo_string_decode().
- */
-
-#include "internal.h"
-
-#include "account.h"
-#include "accountopt.h"
-#include "blist.h"
-#include "cipher.h"
-#include "cmds.h"
-#include "core.h"
-#include "debug.h"
-#include "network.h"
-#include "notify.h"
-#include "privacy.h"
-#include "prpl.h"
-#include "proxy.h"
-#include "request.h"
-#include "server.h"
-#include "util.h"
-#include "version.h"
-#include "xmlnode.h"
-
-#include "libymsg.h"
-#include "yahoochat.h"
-#include "yahoo_aliases.h"
-#include "yahoo_doodle.h"
-#include "yahoo_filexfer.h"
-#include "yahoo_friend.h"
-#include "yahoo_packet.h"
-#include "yahoo_picture.h"
-#include "ycht.h"
-
-/* #define YAHOO_DEBUG */
-
-/* #define TRY_WEBMESSENGER_LOGIN 0 */
-
-/* One hour */
-#define PING_TIMEOUT 3600
-
-/* One minute */
-#define KEEPALIVE_TIMEOUT 60
-
-#ifdef TRY_WEBMESSENGER_LOGIN
-static void yahoo_login_page_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message);
-#endif /* TRY_WEBMESSENGER_LOGIN */
-
-static gboolean yahoo_is_japan(PurpleAccount *account)
-{
-	return purple_strequal(purple_account_get_protocol_id(account), "prpl-yahoojp");
-}
-
-static void yahoo_update_status(PurpleConnection *gc, const char *name, YahooFriend *f)
-{
-	char *status = NULL;
-
-	if (!gc || !name || !f || !purple_find_buddy(purple_connection_get_account(gc), name))
-		return;
-
-	switch (f->status) {
-	case YAHOO_STATUS_OFFLINE:
-		status = YAHOO_STATUS_TYPE_OFFLINE;
-		break;
-	case YAHOO_STATUS_AVAILABLE:
-		status = YAHOO_STATUS_TYPE_AVAILABLE;
-		break;
-	case YAHOO_STATUS_BRB:
-		status = YAHOO_STATUS_TYPE_BRB;
-		break;
-	case YAHOO_STATUS_BUSY:
-		status = YAHOO_STATUS_TYPE_BUSY;
-		break;
-	case YAHOO_STATUS_NOTATHOME:
-		status = YAHOO_STATUS_TYPE_NOTATHOME;
-		break;
-	case YAHOO_STATUS_NOTATDESK:
-		status = YAHOO_STATUS_TYPE_NOTATDESK;
-		break;
-	case YAHOO_STATUS_NOTINOFFICE:
-		status = YAHOO_STATUS_TYPE_NOTINOFFICE;
-		break;
-	case YAHOO_STATUS_ONPHONE:
-		status = YAHOO_STATUS_TYPE_ONPHONE;
-		break;
-	case YAHOO_STATUS_ONVACATION:
-		status = YAHOO_STATUS_TYPE_ONVACATION;
-		break;
-	case YAHOO_STATUS_OUTTOLUNCH:
-		status = YAHOO_STATUS_TYPE_OUTTOLUNCH;
-		break;
-	case YAHOO_STATUS_STEPPEDOUT:
-		status = YAHOO_STATUS_TYPE_STEPPEDOUT;
-		break;
-	case YAHOO_STATUS_INVISIBLE: /* this should never happen? */
-		status = YAHOO_STATUS_TYPE_INVISIBLE;
-		break;
-	case YAHOO_STATUS_CUSTOM:
-	case YAHOO_STATUS_IDLE:
-		if (!f->away)
-			status = YAHOO_STATUS_TYPE_AVAILABLE;
-		else
-			status = YAHOO_STATUS_TYPE_AWAY;
-		break;
-	default:
-		purple_debug_warning("yahoo", "Warning, unknown status %d\n", f->status);
-		break;
-	}
-
-	if (status) {
-		if (f->status == YAHOO_STATUS_CUSTOM)
-			purple_prpl_got_user_status(purple_connection_get_account(gc), name, status, "message",
-			                          yahoo_friend_get_status_message(f), NULL);
-		else
-			purple_prpl_got_user_status(purple_connection_get_account(gc), name, status, NULL);
-	}
-
-	if (f->idle != 0)
-		purple_prpl_got_user_idle(purple_connection_get_account(gc), name, TRUE, f->idle);
-	else
-		purple_prpl_got_user_idle(purple_connection_get_account(gc), name, FALSE, 0);
-
-	if (f->sms)
-		purple_prpl_got_user_status(purple_connection_get_account(gc), name, YAHOO_STATUS_TYPE_MOBILE, NULL);
-	else
-		purple_prpl_got_user_status_deactive(purple_connection_get_account(gc), name, YAHOO_STATUS_TYPE_MOBILE);
-}
-
-static void yahoo_process_status(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	PurpleAccount *account = purple_connection_get_account(gc);
-	GSList *l = pkt->hash;
-	YahooFriend *f = NULL;
-	char *name = NULL;
-	gboolean unicode = FALSE;
-	char *message = NULL;
-	YahooFederation fed = YAHOO_FEDERATION_NONE;
-	char *fedname = NULL;
-
-	if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) {
-		if (!purple_account_get_remember_password(account))
-			purple_account_set_password(account, NULL);
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NAME_IN_USE,
-			_("You have signed on from another location"));
-		return;
-	}
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 0: /* we won't actually do anything with this */
-		case 1: /* we won't actually do anything with this */
-			break;
-		case 8: /* how many online buddies we have */
-			break;
-		case 7: /* the current buddy */
-			/* update the previous buddy before changing the variables */
-			if (f) {
-				if (message)
-					yahoo_friend_set_status_message(f, yahoo_string_decode(gc, message, unicode));
-				if (name)
-					yahoo_update_status(gc, name, f);
-			}
-			name = message = NULL;
-			f = NULL;
-			if (pair->value && g_utf8_validate(pair->value, -1, NULL)) {
-				GSList *tmplist;
-
-				name = pair->value;
-
-				/* Look ahead to see if we have the federation info about the buddy */
-				for (tmplist = l->next; tmplist; tmplist = tmplist->next) {
-					struct yahoo_pair *p = tmplist->data;
-					if (p->key == 7)
-						break;
-					if (p->key == 241) {
-						fed = strtol(p->value, NULL, 10);
-						g_free(fedname);
-						switch (fed) {
-							case YAHOO_FEDERATION_MSN:
-								name = fedname = g_strconcat("msn/", name, NULL);
-								break;
-							case YAHOO_FEDERATION_OCS:
-								name = fedname = g_strconcat("ocs/", name, NULL);
-								break;
-							case YAHOO_FEDERATION_IBM:
-								name = fedname = g_strconcat("ibm/", name, NULL);
-								break;
-							case YAHOO_FEDERATION_NONE:
-							default:
-								fedname = NULL;
-								break;
-						}
-						break;
-					}
-				}
-				f = yahoo_friend_find_or_new(gc, name);
-				f->fed = fed;
-			}
-			break;
-		case 10: /* state */
-			if (!f)
-				break;
-
-			f->status = strtol(pair->value, NULL, 10);
-			if ((f->status >= YAHOO_STATUS_BRB) && (f->status <= YAHOO_STATUS_STEPPEDOUT))
-				f->away = 1;
-			else
-				f->away = 0;
-
-			if (f->status == YAHOO_STATUS_IDLE) {
-				/* Idle may have already been set in a more precise way in case 137 */
-				if (f->idle == 0)
-				{
-					if(pkt->service == YAHOO_SERVICE_STATUS_15)
-						f->idle = -1;
-					else
-						f->idle = time(NULL);
-				}
-			} else
-				f->idle = 0;
-
-			if (f->status != YAHOO_STATUS_CUSTOM)
-				yahoo_friend_set_status_message(f, NULL);
-
-			f->sms = 0;
-			break;
-		case 19: /* custom message */
-			if (f)
-				message = pair->value;
-			break;
-		case 11: /* this is the buddy's session id */
-			if (f)
-				f->session_id = strtol(pair->value, NULL, 10);
-			break;
-		case 17: /* in chat? */
-			break;
-		case 47: /* is custom status away or not? 2=idle*/
-			if (!f)
-				break;
-
-			/* I have no idea what it means when this is
-			 * set when someone's available, but it doesn't
-			 * mean idle. */
-			if (f->status == YAHOO_STATUS_AVAILABLE)
-				break;
-
-			f->away = strtol(pair->value, NULL, 10);
-			if (f->away == 2) {
-				/* Idle may have already been set in a more precise way in case 137 */
-				if (f->idle == 0)
-				{
-					if(pkt->service == YAHOO_SERVICE_STATUS_15)
-						f->idle = -1;
-					else
-						f->idle = time(NULL);
-				}
-			}
-
-			break;
-		case 138: /* when value is 1, either we're not idle, or we are but won't say how long */
-			if (!f)
-				break;
-
-			if( (strtol(pair->value, NULL, 10) == 1) && (f->idle) )
-				f->idle = -1;
-			break;
-		case 137: /* usually idle time in seconds, sometimes login time */
-			if (!f)
-				break;
-
-			if (f->status != YAHOO_STATUS_AVAILABLE)
-				f->idle = time(NULL) - strtol(pair->value, NULL, 10);
-			break;
-		case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */
-			if (strtol(pair->value, NULL, 10) == 0) {
-				if (f)
-					f->status = YAHOO_STATUS_OFFLINE;
-				if (name) {
-					purple_prpl_got_user_status(account, name, "offline", NULL);
-					purple_prpl_got_user_status_deactive(account, name, YAHOO_STATUS_TYPE_MOBILE);
-				}
-				break;
-			}
-			break;
-		case 60: /* SMS */
-			if (f) {
-				f->sms = strtol(pair->value, NULL, 10);
-				yahoo_update_status(gc, name, f);
-			}
-			break;
-		case 197: /* Avatars */
-		{
-			guchar *decoded;
-			char *tmp;
-			gsize len;
-
-			if (pair->value) {
-				decoded = purple_base64_decode(pair->value, &len);
-				if (decoded && len > 0) {
-					tmp = purple_str_binary_to_ascii(decoded, len);
-					purple_debug_info("yahoo", "Got key 197, value = %s\n", tmp);
-					g_free(tmp);
-				}
-				g_free(decoded);
-			}
-			break;
-		}
-		case 192: /* Pictures, aka Buddy Icons, checksum */
-		{
-			/* FIXME: Please, if you know this protocol,
-			 * FIXME: fix up the strtol() stuff if possible. */
-			int cksum = strtol(pair->value, NULL, 10);
-			const char *locksum = NULL;
-			PurpleBuddy *b;
-
-			if (!name)
-				break;
-
-			b = purple_find_buddy(gc->account, name);
-
-			if (!cksum || (cksum == -1)) {
-				if (f)
-					yahoo_friend_set_buddy_icon_need_request(f, TRUE);
-				purple_buddy_icons_set_for_user(gc->account, name, NULL, 0, NULL);
-				break;
-			}
-
-			if (!f)
-				break;
-
-			yahoo_friend_set_buddy_icon_need_request(f, FALSE);
-			if (b) {
-				locksum = purple_buddy_icons_get_checksum_for_user(b);
-				if (!locksum || (cksum != strtol(locksum, NULL, 10)))
-					yahoo_send_picture_request(gc, name);
-			}
-
-			break;
-		}
-		case 16: /* Custom error message */
-			{
-				char *tmp = yahoo_string_decode(gc, pair->value, TRUE);
-				purple_notify_error(gc, NULL, tmp, NULL);
-				g_free(tmp);
-			}
-			break;
-		case 97: /* Unicode status message */
-			unicode = !strcmp(pair->value, "1");
-			break;
-		case 244: /* client version number. Yahoo Client Detection */
-			if(f && strtol(pair->value, NULL, 10))
-				f->version_id = strtol(pair->value, NULL, 10);
-			break;
-		case 241: /* Federated network buddy belongs to */
-			break;  /* We process this when get '7' */
-		default:
-			purple_debug_warning("yahoo",
-					   "Unknown status key %d\n", pair->key);
-			break;
-		}
-
-		l = l->next;
-	}
-
-	if (f) {
-		if (pkt->service == YAHOO_SERVICE_LOGOFF)
-			f->status = YAHOO_STATUS_OFFLINE;
-		if (message)
-			yahoo_friend_set_status_message(f, yahoo_string_decode(gc, message, unicode));
-
-		if (name) /* update the last buddy */
-			yahoo_update_status(gc, name, f);
-	}
-
-	g_free(fedname);
-}
-
-static void yahoo_do_group_check(PurpleAccount *account, GHashTable *ht, const char *name, const char *group)
-{
-	PurpleBuddy *b;
-	PurpleGroup *g;
-	GSList *list, *i;
-	gboolean onlist = FALSE;
-	char *oname = NULL;
-
-	if (g_hash_table_lookup_extended(ht, name, (gpointer *)&oname, (gpointer *)&list))
-		g_hash_table_steal(ht, oname);
-	else
-		list = purple_find_buddies(account, name);
-
-	for (i = list; i; i = i->next) {
-		b = i->data;
-		g = purple_buddy_get_group(b);
-		if (!purple_utf8_strcasecmp(group, purple_group_get_name(g))) {
-			purple_debug_misc("yahoo",
-				"Oh good, %s is in the right group (%s).\n", name, group);
-			list = g_slist_delete_link(list, i);
-			onlist = TRUE;
-			break;
-		}
-	}
-
-	if (!onlist) {
-		purple_debug_misc("yahoo",
-			"Uhoh, %s isn't on the list (or not in this group), adding him to group %s.\n", name, group);
-		if (!(g = purple_find_group(group))) {
-			g = purple_group_new(group);
-			purple_blist_add_group(g, NULL);
-		}
-		b = purple_buddy_new(account, name, NULL);
-		purple_blist_add_buddy(b, NULL, g, NULL);
-	}
-
-	if (list) {
-		if (!oname)
-			oname = g_strdup(name);
-		g_hash_table_insert(ht, oname, list);
-	} else
-		g_free(oname);
-}
-
-static void yahoo_do_group_cleanup(gpointer key, gpointer value, gpointer user_data)
-{
-	char *name = key;
-	GSList *list = value, *i;
-	PurpleBuddy *b;
-	PurpleGroup *g;
-
-	for (i = list; i; i = i->next) {
-		b = i->data;
-		g = purple_buddy_get_group(b);
-		purple_debug_misc("yahoo", "Deleting Buddy %s from group %s.\n", name,
-				purple_group_get_name(g));
-		purple_blist_remove_buddy(b);
-	}
-}
-
-static char *_getcookie(char *rawcookie)
-{
-	char *cookie = NULL;
-	char *tmpcookie;
-	char *cookieend;
-
-	if (strlen(rawcookie) < 2)
-		return NULL;
-	tmpcookie = g_strdup(rawcookie+2);
-	cookieend = strchr(tmpcookie, ';');
-
-	if (cookieend)
-		*cookieend = '\0';
-
-	cookie = g_strdup(tmpcookie);
-	g_free(tmpcookie);
-
-	return cookie;
-}
-
-static void yahoo_process_cookie(YahooData *yd, char *c)
-{
-	if (c[0] == 'Y') {
-		if (yd->cookie_y)
-			g_free(yd->cookie_y);
-		yd->cookie_y = _getcookie(c);
-	} else if (c[0] == 'T') {
-		if (yd->cookie_t)
-			g_free(yd->cookie_t);
-		yd->cookie_t = _getcookie(c);
-	} else
-		purple_debug_info("yahoo", "Unrecognized cookie '%c'\n", c[0]);
-	yd->cookies = g_slist_prepend(yd->cookies, g_strdup(c));
-}
-
-static void yahoo_process_list_15(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	GSList *l = pkt->hash;
-
-	PurpleAccount *account = purple_connection_get_account(gc);
-	YahooData *yd = gc->proto_data;
-	GHashTable *ht;
-	char *norm_bud = NULL;
-	char *temp = NULL;
-	YahooFriend *f = NULL; /* It's your friends. They're going to want you to share your StarBursts. */
-	                       /* But what if you had no friends? */
-	YahooFederation fed = YAHOO_FEDERATION_NONE;
-	int stealth = 0;
-
-	ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_slist_free);
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-		l = l->next;
-
-		switch (pair->key) {
-		case 302:
-			/* This is always 318 before a group, 319 before the first s/n in a group, 320 before any ignored s/n.
-			 * It is not sent for s/n's in a group after the first.
-			 * All ignored s/n's are listed last, so when we see a 320 we clear the group and begin marking the
-			 * s/n's as ignored.  It is always followed by an identical 300 key.
-			 */
-			if (pair->value && !strcmp(pair->value, "320")) {
-				/* No longer in any group; this indicates the start of the ignore list. */
-				g_free(yd->current_list15_grp);
-				yd->current_list15_grp = NULL;
-			}
-
-			break;
-		case 301: /* This is 319 before all s/n's in a group after the first. It is followed by an identical 300. */
-			if(temp != NULL) {
-				switch (fed) {
-					case YAHOO_FEDERATION_MSN:
-						norm_bud = g_strconcat("msn/", temp, NULL);
-						break;
-					case YAHOO_FEDERATION_OCS:
-						norm_bud = g_strconcat("ocs/", temp, NULL);
-						break;
-					case YAHOO_FEDERATION_IBM:
-						norm_bud = g_strconcat("ibm/", temp, NULL);
-						break;
-					case YAHOO_FEDERATION_PBX:
-						norm_bud = g_strconcat("pbx/", temp, NULL);
-						break;
-					case YAHOO_FEDERATION_NONE:
-						norm_bud = g_strdup(temp);
-						break;
-				}
-				if (yd->current_list15_grp) {
-					/* This buddy is in a group */
-					f = yahoo_friend_find_or_new(gc, norm_bud);
-					if (!purple_find_buddy(account, norm_bud)) {
-						PurpleBuddy *b;
-						PurpleGroup *g;
-						if (!(g = purple_find_group(yd->current_list15_grp))) {
-							g = purple_group_new(yd->current_list15_grp);
-							purple_blist_add_group(g, NULL);
-						}
-						b = purple_buddy_new(account, norm_bud, NULL);
-						purple_blist_add_buddy(b, NULL, g, NULL);
-					}
-					yahoo_do_group_check(account, ht, norm_bud, yd->current_list15_grp);
-					if(fed) {
-						f->fed = fed;
-						purple_debug_info("yahoo", "Setting federation to %d\n", f->fed);
-					}
-					if(stealth == 2)
-						f->presence = YAHOO_PRESENCE_PERM_OFFLINE;
-
-					/* set p2p status not connected and no p2p packet sent */
-					if(fed == YAHOO_FEDERATION_NONE) {
-						yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED);
-						f->p2p_packet_sent = 0;
-					} else
-						yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_DO_NOT_CONNECT);
-				} else {
-					/* This buddy is on the ignore list (and therefore in no group) */
-					purple_debug_info("yahoo", "%s adding %s to the deny list because of the ignore list / no group was found\n",account->username, norm_bud);
-					purple_privacy_deny_add(account, norm_bud, 1);
-				}
-
-				g_free(norm_bud);
-				norm_bud=NULL;
-				fed = YAHOO_FEDERATION_NONE;
-				stealth = 0;
-				g_free(temp);
-				temp = NULL;
-			}
-			break;
-		case 300: /* This is 318 before a group, 319 before any s/n in a group, and 320 before any ignored s/n. */
-			break;
-		case 65: /* This is the group */
-			g_free(yd->current_list15_grp);
-			yd->current_list15_grp = yahoo_string_decode(gc, pair->value, FALSE);
-			break;
-		case 7: /* buddy's s/n */
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				g_free(temp);
-				temp = g_strdup(purple_normalize(account, pair->value));
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_list_15 "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 241: /* user on federated network */
-			fed = strtol(pair->value, NULL, 10);
-			break;
-		case 59: /* somebody told cookies come here too, but im not sure */
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				yahoo_process_cookie(yd, pair->value);
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_list_15 "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 317: /* Stealth Setting */
-			stealth = strtol(pair->value, NULL, 10);
-			break;
-		/* case 242: */ /* this seems related to 241 */
-			/* break; */
-		}
-	}
-
-	g_hash_table_foreach(ht, yahoo_do_group_cleanup, NULL);
-
-	/* The reporter of ticket #9745 determined that we weren't retrieving the
-	 * aliases during buddy list retrieval, so we never updated aliases that
-	 * changed while we were signed off. */
-	yahoo_fetch_aliases(gc);
-
-	/* Now that we have processed the buddy list, we can say yahoo has connected */
-	purple_connection_set_display_name(gc, purple_normalize(account, purple_account_get_username(account)));
-	yd->logged_in = TRUE;
-	purple_debug_info("yahoo","Authentication: Connection established\n");
-	purple_connection_set_state(gc, PURPLE_CONNECTED);
-	if (yd->picture_upload_todo) {
-		yahoo_buddy_icon_upload(gc, yd->picture_upload_todo);
-		yd->picture_upload_todo = NULL;
-	}
-	yahoo_set_status(account, purple_account_get_active_status(account));
-
-	g_hash_table_destroy(ht);
-	g_free(temp);
-}
-
-static void yahoo_process_list(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	GSList *l = pkt->hash;
-	gboolean got_serv_list = FALSE;
-	YahooFriend *f = NULL;
-	PurpleAccount *account = purple_connection_get_account(gc);
-	YahooData *yd = gc->proto_data;
-	GHashTable *ht;
-
-	char **lines;
-	char **split;
-	char **buddies;
-	char **tmp, **bud, *norm_bud;
-	char *grp = NULL;
-
-	if (pkt->id)
-		yd->session_id = pkt->id;
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-		l = l->next;
-
-		switch (pair->key) {
-		case 87:
-			if (!yd->tmp_serv_blist)
-				yd->tmp_serv_blist = g_string_new(pair->value);
-			else
-				g_string_append(yd->tmp_serv_blist, pair->value);
-			break;
-		case 88:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				if (!yd->tmp_serv_ilist)
-					yd->tmp_serv_ilist = g_string_new(pair->value);
-				else
-					g_string_append(yd->tmp_serv_ilist, pair->value);
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_list "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 89:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				yd->profiles = g_strsplit(pair->value, ",", -1);
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_list "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 59: /* cookies, yum */
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				yahoo_process_cookie(yd, pair->value);
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_list "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case YAHOO_SERVICE_PRESENCE_PERM:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				if (!yd->tmp_serv_plist)
-					yd->tmp_serv_plist = g_string_new(pair->value);
-				else
-					g_string_append(yd->tmp_serv_plist, pair->value);
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_list "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		}
-	}
-
-	if (pkt->status != 0)
-		return;
-
-	if (yd->tmp_serv_blist) {
-		ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_slist_free);
-
-		lines = g_strsplit(yd->tmp_serv_blist->str, "\n", -1);
-		for (tmp = lines; *tmp; tmp++) {
-			split = g_strsplit(*tmp, ":", 2);
-			if (!split)
-				continue;
-			if (!split[0] || !split[1]) {
-				g_strfreev(split);
-				continue;
-			}
-			grp = yahoo_string_decode(gc, split[0], FALSE);
-			buddies = g_strsplit(split[1], ",", -1);
-			for (bud = buddies; bud && *bud; bud++) {
-				if (!g_utf8_validate(*bud, -1, NULL)) {
-					purple_debug_warning("yahoo", "yahoo_process_list "
-							"got non-UTF-8 string for bud\n");
-					continue;
-				}
-
-				norm_bud = g_strdup(purple_normalize(account, *bud));
-				f = yahoo_friend_find_or_new(gc, norm_bud);
-
-				if (!purple_find_buddy(account, norm_bud)) {
-					PurpleBuddy *b;
-					PurpleGroup *g;
-					if (!(g = purple_find_group(grp))) {
-						g = purple_group_new(grp);
-						purple_blist_add_group(g, NULL);
-					}
-					b = purple_buddy_new(account, norm_bud, NULL);
-					purple_blist_add_buddy(b, NULL, g, NULL);
-				}
-
-				yahoo_do_group_check(account, ht, norm_bud, grp);
-				/* set p2p status not connected and no p2p packet sent */
-				yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED);
-				f->p2p_packet_sent = 0;
-
-				g_free(norm_bud);
-			}
-			g_strfreev(buddies);
-			g_strfreev(split);
-			g_free(grp);
-		}
-		g_strfreev(lines);
-
-		g_string_free(yd->tmp_serv_blist, TRUE);
-		yd->tmp_serv_blist = NULL;
-		g_hash_table_foreach(ht, yahoo_do_group_cleanup, NULL);
-		g_hash_table_destroy(ht);
-	}
-
-	if (yd->tmp_serv_ilist) {
-		buddies = g_strsplit(yd->tmp_serv_ilist->str, ",", -1);
-		for (bud = buddies; bud && *bud; bud++) {
-			/* The server is already ignoring the user */
-			got_serv_list = TRUE;
-			purple_privacy_deny_add(account, *bud, 1);
-		}
-		g_strfreev(buddies);
-
-		g_string_free(yd->tmp_serv_ilist, TRUE);
-		yd->tmp_serv_ilist = NULL;
-	}
-
-	if (got_serv_list &&
-		((account->perm_deny != PURPLE_PRIVACY_ALLOW_BUDDYLIST) &&
-		(account->perm_deny != PURPLE_PRIVACY_DENY_ALL) &&
-		(account->perm_deny != PURPLE_PRIVACY_ALLOW_USERS)))
-	{
-		account->perm_deny = PURPLE_PRIVACY_DENY_USERS;
-		purple_debug_info("yahoo", "%s privacy defaulting to PURPLE_PRIVACY_DENY_USERS.\n",
-				account->username);
-	}
-
-	if (yd->tmp_serv_plist) {
-		buddies = g_strsplit(yd->tmp_serv_plist->str, ",", -1);
-		for (bud = buddies; bud && *bud; bud++) {
-			f = yahoo_friend_find(gc, *bud);
-			if (f) {
-				purple_debug_info("yahoo", "%s setting presence for %s to PERM_OFFLINE\n",
-						account->username, *bud);
-				f->presence = YAHOO_PRESENCE_PERM_OFFLINE;
-			}
-		}
-		g_strfreev(buddies);
-		g_string_free(yd->tmp_serv_plist, TRUE);
-		yd->tmp_serv_plist = NULL;
-
-	}
-	/* Now that we've got the list, request aliases */
-	yahoo_fetch_aliases(gc);
-}
-
-/* pkt_type is YAHOO_PKT_TYPE_SERVER if pkt arrives from yahoo server, YAHOO_PKT_TYPE_P2P if pkt arrives through p2p */
-static void yahoo_process_notify(PurpleConnection *gc, struct yahoo_packet *pkt, yahoo_pkt_type pkt_type)
-{
-	PurpleAccount *account;
-	char *msg = NULL;
-	char *from = NULL;
-	char *stat = NULL;
-	char *game = NULL;
-	YahooFriend *f = NULL;
-	GSList *l = pkt->hash;
-	gint val_11 = 0;
-	YahooData *yd = gc->proto_data;
-	YahooFederation fed = YAHOO_FEDERATION_NONE;
-
-	account = purple_connection_get_account(gc);
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-		if (pair->key == 4 || pair->key == 1) {
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				from = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_notify "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-		}
-		if (pair->key == 49)
-			msg = pair->value;
-		if (pair->key == 13)
-			stat = pair->value;
-		if (pair->key == 14) {
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				game = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_notify "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-		}
-		if (pair->key == 11)
-			val_11 = strtol(pair->value, NULL, 10);
-		if (pair->key == 241)
-			fed = strtol(pair->value, NULL, 10);
-		l = l->next;
-	}
-
-	if (!from || !msg)
-		return;
-
-	/* disconnect the peer if connected through p2p and sends wrong value for session id */
-	if( (pkt_type == YAHOO_PKT_TYPE_P2P) && (val_11 != yd->session_id) ) {
-		purple_debug_warning("yahoo","p2p: %s sent us notify with wrong session id. Disconnecting p2p connection to peer\n", from);
-		/* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */
-		g_hash_table_remove(yd->peers, from);
-		return;
-	}
-
-	if (!g_ascii_strncasecmp(msg, "TYPING", strlen("TYPING"))
-		&& (purple_privacy_check(account, from)))
-	{
-		char *fed_from = from;
-		switch (fed) {
-			case YAHOO_FEDERATION_MSN:
-				fed_from = g_strconcat("msn/", from, NULL);
-				break;
-			case YAHOO_FEDERATION_OCS:
-				fed_from = g_strconcat("ocs/", from, NULL);
-				break;
-			case YAHOO_FEDERATION_IBM:
-				fed_from = g_strconcat("ibm/", from, NULL);
-				break;
-			case YAHOO_FEDERATION_PBX:
-				fed_from = g_strconcat("pbx/", from, NULL);
-				break;
-			case YAHOO_FEDERATION_NONE:
-			default:
-				break;
-		}
-
-		if (stat && *stat == '1')
-			serv_got_typing(gc, fed_from, 0, PURPLE_TYPING);
-		else
-			serv_got_typing_stopped(gc, fed_from);
-
-		if (fed_from != from)
-			g_free(fed_from);
-
-	} else if (!g_ascii_strncasecmp(msg, "GAME", strlen("GAME"))) {
-		PurpleBuddy *bud = purple_find_buddy(account, from);
-
-		if (!bud) {
-			purple_debug_warning("yahoo",
-					   "%s is playing a game, and doesn't want you to know.\n", from);
-		}
-
-		f = yahoo_friend_find(gc, from);
-		if (!f)
-			return; /* if they're not on the list, don't bother */
-
-		yahoo_friend_set_game(f, NULL);
-
-		if (stat && *stat == '1') {
-			yahoo_friend_set_game(f, game);
-			if (bud)
-				yahoo_update_status(gc, from, f);
-		}
-	} else if (!g_ascii_strncasecmp(msg, "WEBCAMINVITE", strlen("WEBCAMINVITE"))) {
-		PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, account);
-		char *buf = g_strdup_printf(_("%s has sent you a webcam invite, which is not yet supported."), from);
-		purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NOTIFY, time(NULL));
-		g_free(buf);
-	}
-}
-
-
-struct _yahoo_im {
-	char *from;
-	char *active_id;
-	int time;
-	int utf8;
-	int buddy_icon;
-	char *id;
-	char *msg;
-	YahooFederation fed;
-	char *fed_from;
-};
-
-static void yahoo_process_sms_message(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	PurpleAccount *account;
-	GSList *l = pkt->hash;
-	struct _yahoo_im *sms = NULL;
-	YahooData *yd;
-	char *server_msg = NULL;
-	char *m;
-
-	yd = gc->proto_data;
-	account = purple_connection_get_account(gc);
-
-	while (l != NULL) {
-		struct yahoo_pair *pair = l->data;
-		if (pair->key == 4) {
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				sms = g_new0(struct _yahoo_im, 1);
-				sms->from = g_strdup_printf("+%s", pair->value);
-				sms->time = time(NULL);
-				sms->utf8 = TRUE;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_sms_message "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-		}
-		if (pair->key == 14) {
-			if (sms)
-				sms->msg = pair->value;
-		}
-		if (pair->key == 68)
-			if(sms)
-				g_hash_table_insert(yd->sms_carrier, g_strdup(sms->from), g_strdup(pair->value));
-		if (pair->key == 16) {
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				server_msg = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_sms_message "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-		}
-		l = l->next;
-	}
-
-	if(!sms) {
-		purple_debug_info("yahoo", "Received a malformed SMS packet!\n");
-		return;
-	}
-
-	if ((int)pkt->status < 0)
-		pkt->status = YAHOO_STATUS_DISCONNECTED;
-	if (pkt->status == YAHOO_STATUS_DISCONNECTED) {
-		if (server_msg) {
-			PurpleConversation *c;
-			c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms->from, account);
-			if (c == NULL)
-				c = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sms->from);
-			purple_conversation_write(c, NULL, server_msg, PURPLE_MESSAGE_SYSTEM, time(NULL));
-		}
-		else
-			purple_notify_error(gc, NULL, _("Your SMS was not delivered"), NULL);
-
-		g_free(sms->from);
-		g_free(sms);
-		return ;
-	}
-
-	if (!sms->from || !sms->msg) {
-		g_free(sms);
-		return;
-	}
-
-	m = yahoo_string_decode(gc, sms->msg, sms->utf8);
-	serv_got_im(gc, sms->from, m, 0, sms->time);
-
-	g_free(m);
-	g_free(sms->from);
-	g_free(sms);
-}
-
-/* pkt_type is YAHOO_PKT_TYPE_SERVER if pkt arrives from yahoo server, YAHOO_PKT_TYPE_P2P if pkt arrives through p2p */
-static void yahoo_process_message(PurpleConnection *gc, struct yahoo_packet *pkt, yahoo_pkt_type pkt_type)
-{
-	PurpleAccount *account;
-	YahooData *yd = gc->proto_data;
-	GSList *l = pkt->hash;
-	GSList *list = NULL;
-	struct _yahoo_im *im = NULL;
-
-	account = purple_connection_get_account(gc);
-
-	if (pkt->status <= 1 || pkt->status == 5 || pkt->status == YAHOO_STATUS_OFFLINE) {
-	/* messages are received with status YAHOO_STATUS_OFFLINE in case of p2p */
-		while (l != NULL) {
-			struct yahoo_pair *pair = l->data;
-			if (pair->key == 4 || pair->key == 1) {
-				if (g_utf8_validate(pair->value, -1, NULL)) {
-					im = g_new0(struct _yahoo_im, 1);
-					list = g_slist_append(list, im);
-					im->from = pair->value;
-					im->time = time(NULL);
-					im->utf8 = TRUE;
-					im->fed = YAHOO_FEDERATION_NONE;
-					im->fed_from = g_strdup(im->from);
-				} else {
-					purple_debug_warning("yahoo", "yahoo_process_message "
-							"got non-UTF-8 string for key %d\n", pair->key);
-				}
-			}
-			if (im && pair->key == 5)
-				im->active_id = pair->value;
-			if (pair->key == 97)
-				if (im)
-					im->utf8 = strtol(pair->value, NULL, 10);
-			if (pair->key == 15)
-				if (im)
-					im->time = strtol(pair->value, NULL, 10);
-			if (pair->key == 206)
-				if (im)
-					im->buddy_icon = strtol(pair->value, NULL, 10);
-			if (pair->key == 14) {
-				if (im)
-					im->msg = pair->value;
-			}
-			if (im && pair->key == 241) {
-				im->fed = strtol(pair->value, NULL, 10);
-				g_free(im->fed_from);
-				switch (im->fed) {
-					case YAHOO_FEDERATION_MSN:
-						im->fed_from = g_strconcat("msn/",im->from, NULL);
-						break;
-					case YAHOO_FEDERATION_OCS:
-						im->fed_from = g_strconcat("ocs/",im->from, NULL);
-						break;
-					case YAHOO_FEDERATION_IBM:
-						im->fed_from = g_strconcat("ibm/",im->from, NULL);
-						break;
-					case YAHOO_FEDERATION_PBX:
-						im->fed_from = g_strconcat("pbx/",im->from, NULL);
-						break;
-					case YAHOO_FEDERATION_NONE:
-					default:
-						im->fed_from = g_strdup(im->from);
-						break;
-				}
-				purple_debug_info("yahoo", "Message from federated (%d) buddy %s.\n", im->fed, im->fed_from);
-
-			}
-			/* peer session id */
-			if (im && (pair->key == 11)) {
-				/* disconnect the peer if connected through p2p and sends wrong value for session id */
-				if( (im->fed == YAHOO_FEDERATION_NONE) && (pkt_type == YAHOO_PKT_TYPE_P2P)
-						&& (yd->session_id != strtol(pair->value, NULL, 10)) )
-				{
-					purple_debug_warning("yahoo","p2p: %s sent us message with wrong session id. Disconnecting p2p connection to peer\n", im->fed_from);
-					/* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */
-					g_hash_table_remove(yd->peers, im->fed_from);
-					g_free(im->fed_from);
-					g_free(im);
-					return; /* Not sure whether we should process remaining IMs in this packet */
-				}
-			}
-			/* IMV key */
-			if (im && pair->key == 63 && g_utf8_validate(pair->value, -1, NULL))
-			{
-				/* Check for the Doodle IMV, no IMvironment for federated buddies */
-				if (im->from != NULL && im->fed == YAHOO_FEDERATION_NONE)
-				{
-					g_hash_table_replace(yd->imvironments, g_strdup(im->from), g_strdup(pair->value));
-
-					if (strstr(pair->value, "doodle;") != NULL)
-					{
-						PurpleWhiteboard *wb;
-
-						if (!purple_privacy_check(account, im->from)) {
-							purple_debug_info("yahoo", "Doodle request from %s dropped.\n",
-												im->from);
-							g_free(im->fed_from);
-							g_free(im);
-							return;
-						}
-						/* I'm not sure the following ever happens -DAA */
-						wb = purple_whiteboard_get_session(account, im->from);
-
-						/* If a Doodle session doesn't exist between this user */
-						if(wb == NULL)
-						{
-							doodle_session *ds;
-							wb = purple_whiteboard_create(account, im->from,
-											DOODLE_STATE_REQUESTED);
-							ds = wb->proto_data;
-							ds->imv_key = g_strdup(pair->value);
-
-							yahoo_doodle_command_send_request(gc, im->from, pair->value);
-							yahoo_doodle_command_send_ready(gc, im->from, pair->value);
-						}
-					}
-				}
-			}
-			if (pair->key == 429)
-				if (im)
-					im->id = pair->value;
-			l = l->next;
-		}
-	} else if (pkt->status == 2) {
-		purple_notify_error(gc, NULL,
-		                  _("Your Yahoo! message did not get sent."), NULL);
-	}
-
-	for (l = list; l; l = l->next) {
-		YahooFriend *f;
-		char *m, *m2;
-		im = l->data;
-
-		if (!im->fed_from || !im->msg) {
-			g_free(im->fed_from);
-			g_free(im);
-			continue;
-		}
-
-		if (!purple_privacy_check(account, im->fed_from)) {
-			purple_debug_info("yahoo", "Message from %s dropped.\n", im->fed_from);
-			return;
-		}
-
-		/*
-		 * TODO: Is there anything else we should check when determining whether
-		 *       we should send an acknowledgement?
-		 */
-		if (im->id != NULL) {
-			/* Send acknowledgement.  If we don't do this then the official
-			 * Yahoo Messenger client for Windows will send us the same
-			 * message 7 seconds later as an offline message.  This is true
-			 * for at least version 9.0.0.2162 on Windows XP. */
-			struct yahoo_packet *pkt2;
-			pkt2 = yahoo_packet_new(YAHOO_SERVICE_MESSAGE_ACK,
-					YAHOO_STATUS_AVAILABLE, pkt->id);
-			yahoo_packet_hash(pkt2, "ssisii",
-					1, im->active_id,  /* May not always be the connection's display name */
-					5, im->from,
-					302, 430,
-					430, im->id,
-					303, 430,
-					450, 0);
-			yahoo_packet_send_and_free(pkt2, yd);
-		}
-
-		m = yahoo_string_decode(gc, im->msg, im->utf8);
-		/* This may actually not be necessary, but it appears
-		 * that at least at one point some clients were sending
-		 * "\r\n" as line delimiters, so we want to avoid double
-		 * lines. */
-		m2 = purple_strreplace(m, "\r\n", "\n");
-		g_free(m);
-		m = m2;
-		purple_util_chrreplace(m, '\r', '\n');
-		if (!strcmp(m, "<ding>")) {
-			char *username;
-
-			username = g_markup_escape_text(im->fed_from, -1);
-			purple_prpl_got_attention(gc, username, YAHOO_BUZZ);
-			g_free(username);