Merge with irc-len-fix-bp release-2.x.y

Thu, 06 Oct 2016 10:05:06 -0400

author
Daniel Atallah <datallah@pidgin.im>
date
Thu, 06 Oct 2016 10:05:06 -0400
branch
release-2.x.y
changeset 38112
7c7fbce30c75
parent 38111
f3b280edb8f5 (diff)
parent 38093
2f11753ccd3a (current diff)
child 38113
a696332798b9

Merge with irc-len-fix-bp

--- a/.hgignore	Wed Oct 05 22:15:51 2016 -0500
+++ b/.hgignore	Thu Oct 06 10:05:06 2016 -0400
@@ -1,3 +1,6 @@
+syntax: glob
+.DS_Store
+
 syntax: regexp
 (.*/)?TAGS$
 (.*/)?\.svn
--- a/ChangeLog	Wed Oct 05 22:15:51 2016 -0500
+++ b/ChangeLog	Thu Oct 06 10:05:06 2016 -0400
@@ -1,6 +1,41 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
-version 2.11.0 (06/21/16):
+version 2.12.0 (??/??/????):
+	libpurple:
+	* Removed the MSN protocol plugin. It has been unusable and dormant for some
+	  time. MSNP18 has been discontinued and the protocol plugin would require a 
+	  large update to start working again. See: http://ismsndeadyet.com/ The
+	  third-party Pidgin SkypeWeb plugin, however, should provide enough
+	  functionality as a replacement if people still want to use MSN:
+	  https://github.com/EionRobb/skype4pidgin/tree/master/skypeweb
+	* Removed Mxit protocol plugin. The service was closed at the end of
+	  September 2016. See
+	  https://pidgin.im/pipermail/devel/2016-September/024078.htm
+	* Removed the MySpaceIM protocol plugin. The service has been defunct for a
+	  long time. (#15356)
+	* Remove the Yahoo! protocol plugin. Yahoo has completely
+	  reimplemented their protocol, so this version is no longer operable as
+	  of August 5th, 2016:
+	  https://yahoo.tumblr.com/post/145715934739/q2-2016-progress-report-on-our-product
+	  A new protocol plugin has been written to support the new protocol.
+	  It can be found here: https://github.com/EionRobb/funyahoo-plusplus
+	  This also removes support for Yahoo! Japan. According to
+	  http://messenger.yahoo.co.jp/ the service ended March 26th, 2014.
+	* Remove the Facebook (XMPP) account option. According to
+	  https://developers.facebook.com/docs/chat the XMPP Chat API service
+	  ended April 30th, 2015. A new protocol plugin has been written,
+	  using a different method, to support Facebook. It can be found at
+	  https://github.com/dequis/purple-facebook/wiki
+
+	General
+	* Replaced instances of d.pidgin.im with developer.pidgin.im and updated the
+	  urls to use https. (#17036)
+
+	IRC
+	* Fixed issue of messages being silently cut off at 500 characters. Large
+	  messages are now split into parts and sent one by one. (#4753)
+
+version 2.11.0 (06/21/2016):
 	General:
 	* 2.10.12 was accidentally released with new additions to the API and
 	  should have been released as 2.11.0.  Unfortunately, we did not catch
@@ -23,14 +58,14 @@
 	  don't support rich text
 	* Fix a potential crash while exiting pidgin
 
-	AIM:
-	* Add support for the newer kerberos-based authentication of AIM 8.x
-
 	Windows-Specific Changes:
 	* Use getaddrinfo for DNS to enable IPv6 (#1075)
 	* Updates to dependencies:
 		* NSS 3.24 and NSPR 4.12.
 
+	AIM:
+	* Add support for the newer kerberos-based authentication of AIM 8.x
+
 	Bonjour
 	* Fixed building on Mac OSX (Patrick Cloke) (#16883)
 
@@ -75,7 +110,7 @@
 	* Fix a remote out-of-bounds read.  Discovered by Yves Younan of Cisco
 	  Talos.  (TALOS-CAN-0143)
 
-version 2.10.12 (12/31/15):
+version 2.10.12 (12/31/2015):
 	General:
 	* purple-url-handler now works with Python 3.x (Daniƫl van Eeden)
 	* Fixed an issue where transient startup statuses could be deleted
@@ -96,7 +131,7 @@
 	Gadu-Gadu:
 	* Updated internal libgadu to version 1.12.1.
 
-version 2.10.11 (11/23/14):
+version 2.10.11 (11/23/2014):
 	General:
 	* Fix handling of Self-Signed SSL/TLS Certificates when using the NSS
 	  plugin (#16412)
@@ -114,7 +149,7 @@
 	* Fail early when buddy list is unavailable instead of wasting bandwidth
 	  endlessly re-trying.
 
-version 2.10.10 (10/22/14):
+version 2.10.10 (10/22/2014):
 	General:
 	* Check the basic constraints extension when validating SSL/TLS
 	  certificates. This fixes a security hole that allowed a malicious
--- a/README	Wed Oct 05 22:15:51 2016 -0500
+++ b/README	Thu Oct 06 10:05:06 2016 -0400
@@ -4,7 +4,7 @@
 
 libpurple is a library intended to be used by programmers seeking
 to write an IM client that connects to many IM networks.  It supports
-AIM, ICQ, XMPP, MSN and Yahoo!, among others.
+AIM, ICQ, and XMPP, among others.
 
 Pidgin is a graphical IM client written in C which uses the GTK+
 toolkit.
--- a/configure.ac	Wed Oct 05 22:15:51 2016 -0500
+++ b/configure.ac	Thu Oct 06 10:05:06 2016 -0400
@@ -1189,7 +1189,7 @@
 fi
 
 if test "x$STATIC_PRPLS" = "xall" ; then
-	STATIC_PRPLS="bonjour gg irc jabber msn myspace mxit novell oscar sametime silc simple yahoo zephyr"
+	STATIC_PRPLS="bonjour gg irc jabber novell oscar sametime silc simple zephyr"
 fi
 if test "x$have_meanwhile" != "xyes" ; then
 	STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/sametime//'`
@@ -1209,19 +1209,13 @@
 load_proto=
 for i in $STATIC_PRPLS ; do
 	dnl Ugly special case for "libsilcpurple.la":
-	dnl ... and Ugly special case for multi-protocol oscar and yahoo
+	dnl ... and Ugly special case for multi-protocol oscar
 	if test \( "x$i" = "xoscar" -o "x$i" = "xaim" -o "x$i" = "xicq" \) -a "x$static_oscar" != "xyes"; then
 		STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/oscar/liboscar.la"
 		extern_init="$extern_init extern gboolean purple_init_aim_plugin();"
 		extern_init="$extern_init extern gboolean purple_init_icq_plugin();"
 		load_proto="$load_proto purple_init_aim_plugin();"
 		load_proto="$load_proto purple_init_icq_plugin();"
-	elif test "x$i" = "xyahoo"; then
-		STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/yahoo/libymsg.la"
-		extern_init="$extern_init extern gboolean purple_init_yahoo_plugin();"
-		extern_init="$extern_init extern gboolean purple_init_yahoojp_plugin();"
-		load_proto="$load_proto purple_init_yahoo_plugin();"
-		load_proto="$load_proto purple_init_yahoojp_plugin();"
 	else
 		if test "x$i" = "xsilc"; then
 			STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib${i}purple.la"
@@ -1238,9 +1232,6 @@
 		gg)			static_gg=yes ;;
 		irc)		static_irc=yes ;;
 		jabber)		static_jabber=yes ;;
-		msn)		static_msn=yes ;;
-		myspace)	static_myspace=yes ;;
-		mxit)		static_mxit=yes ;;
 		novell)		static_novell=yes ;;
 		oscar)		static_oscar=yes ;;
 		aim)		static_oscar=yes ;;
@@ -1249,7 +1240,6 @@
 		silc)		static_silc=yes ;;
 		silc10)		static_silc=yes ;;
 		simple)		static_simple=yes ;;
-		yahoo)		static_yahoo=yes ;;
 		zephyr)		static_zephyr=yes ;;
 		*)			echo "Invalid static protocol $i!!" ; exit 1 ;;
 	esac
@@ -1258,15 +1248,11 @@
 AM_CONDITIONAL(STATIC_GG, test "x$static_gg" = "xyes")
 AM_CONDITIONAL(STATIC_IRC, test "x$static_irc" = "xyes")
 AM_CONDITIONAL(STATIC_JABBER, test "x$static_jabber" = "xyes")
-AM_CONDITIONAL(STATIC_MSN, test "x$static_msn" = "xyes")
-AM_CONDITIONAL(STATIC_MYSPACE, test "x$static_myspace" = "xyes")
-AM_CONDITIONAL(STATIC_MXIT, test "x$static_mxit" = "xyes")
 AM_CONDITIONAL(STATIC_NOVELL, test "x$static_novell" = "xyes")
 AM_CONDITIONAL(STATIC_OSCAR, test "x$static_oscar" = "xyes")
 AM_CONDITIONAL(STATIC_SAMETIME, test "x$static_sametime" = "xyes" -a "x$have_meanwhile" = "xyes")
 AM_CONDITIONAL(STATIC_SILC, test "x$static_silc" = "xyes" -a "x$have_silc" = "xyes")
 AM_CONDITIONAL(STATIC_SIMPLE, test "x$static_simple" = "xyes")
-AM_CONDITIONAL(STATIC_YAHOO, test "x$static_yahoo" = "xyes")
 AM_CONDITIONAL(STATIC_ZEPHYR, test "x$static_zephyr" = "xyes")
 AC_SUBST(STATIC_LINK_LIBS)
 AC_DEFINE_UNQUOTED(STATIC_PROTO_INIT, $extern_init static void static_proto_init(void) { $load_proto },
@@ -1274,7 +1260,7 @@
 
 AC_ARG_WITH(dynamic_prpls, [AC_HELP_STRING([--with-dynamic-prpls], [specify which protocols to build dynamically])], [DYNAMIC_PRPLS=`echo $withval | $sedpath 's/,/ /g'`])
 if test "x$DYNAMIC_PRPLS" = "xall" ; then
-	DYNAMIC_PRPLS="bonjour gg irc jabber msn myspace mxit novell oscar sametime silc simple yahoo zephyr"
+	DYNAMIC_PRPLS="bonjour gg irc jabber novell oscar sametime silc simple zephyr"
 fi
 if test "x$have_meanwhile" != "xyes"; then
 	DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/sametime//'`
@@ -1295,9 +1281,6 @@
 		gg)			dynamic_gg=yes ;;
 		irc)		dynamic_irc=yes ;;
 		jabber)		dynamic_jabber=yes ;;
-		msn)		dynamic_msn=yes ;;
-		myspace)	dynamic_myspace=yes ;;
-		mxit)		dynamic_mxit=yes ;;
 		novell)		dynamic_novell=yes ;;
 		null)		dynamic_null=yes ;;
 		oscar)		dynamic_oscar=yes ;;
@@ -1307,7 +1290,6 @@
 		silc)		dynamic_silc=yes ;;
 		silc10)		dynamic_silc=yes ;;
 		simple)		dynamic_simple=yes ;;
-		yahoo)		dynamic_yahoo=yes ;;
 		zephyr)		dynamic_zephyr=yes ;;
 		*)			echo "Invalid dynamic protocol $i!!" ; exit 1 ;;
 	esac
@@ -1794,7 +1776,7 @@
 	[enable_nss="$enableval"],
 	[enable_nss="yes"])
 
-msg_ssl="None. MSN, Yahoo!, Novell Groupwise and Google Talk will not work without GnuTLS or NSS. OpenSSL is NOT usable!"
+msg_ssl="None. Novell Groupwise and Google Talk will not work without GnuTLS or NSS. OpenSSL is NOT usable!"
 looked_for_gnutls="no"
 dnl #
 dnl # Check for GnuTLS if it's specified.
@@ -2205,19 +2187,19 @@
 	AC_MSG_ERROR([
 Neither GnuTLS or NSS SSL development headers found.
 Use --disable-nss --disable-gnutls if you do not need SSL support.
-MSN, Yahoo!, Novell Groupwise and Google Talk will not work without GnuTLS or NSS. OpenSSL is NOT usable!
+Novell Groupwise and Google Talk will not work without GnuTLS or NSS. OpenSSL is NOT usable!
 ])
 elif test "x$looked_for_gnutls" = "xyes" -a "x$force_deps" = "xyes" ; then
 	AC_MSG_ERROR([
 GnuTLS SSL development headers not found.
 Use --disable-gnutls if you do not need SSL support.
-MSN, Yahoo!, Novell Groupwise and Google Talk will not work without SSL support.
+Novell Groupwise and Google Talk will not work without SSL support.
 ])
 elif test "x$looked_for_nss" = "xyes" -a "x$force_deps" = "xyes" ; then
 	AC_MSG_ERROR([
 NSS SSL development headers not found.
 Use --disable-nss if you do not need SSL support.
-MSN, Yahoo!, Novell Groupwise and Google Talk will not work without SSL support.
+Novell Groupwise and Google Talk will not work without SSL support.
 ])
 fi
 
@@ -2662,9 +2644,6 @@
 		   libpurple/protocols/gg/Makefile
 		   libpurple/protocols/irc/Makefile
 		   libpurple/protocols/jabber/Makefile
-		   libpurple/protocols/msn/Makefile
-		   libpurple/protocols/myspace/Makefile
-		   libpurple/protocols/mxit/Makefile
 		   libpurple/protocols/novell/Makefile
 		   libpurple/protocols/null/Makefile
 		   libpurple/protocols/oscar/Makefile
@@ -2672,7 +2651,6 @@
 		   libpurple/protocols/silc/Makefile
 		   libpurple/protocols/silc10/Makefile
 		   libpurple/protocols/simple/Makefile
-		   libpurple/protocols/yahoo/Makefile
 		   libpurple/protocols/zephyr/Makefile
 		   libpurple/tests/Makefile
 		   libpurple/purple.h
--- a/doc/TCL-HOWTO.dox	Wed Oct 05 22:15:51 2016 -0500
+++ b/doc/TCL-HOWTO.dox	Thu Oct 06 10:05:06 2016 -0400
@@ -124,7 +124,7 @@
   (default) returns all accounts, while the @c -online option returns
   only those accounts which are online.
 
-  The @c protocol subcommand returns the protocol ID (e.g. "prpl-msn")
+  The @c protocol subcommand returns the protocol ID (e.g. "prpl-aim")
   for the given account.
 
   The @c username subcommand returns the username for the account
--- a/doc/finch.1.in	Wed Oct 05 22:15:51 2016 -0500
+++ b/doc/finch.1.in	Thu Oct 06 10:05:06 2016 -0400
@@ -30,11 +30,10 @@
 .SH DESCRIPTION
 .PP
 \fBfinch\fR is a console-based modular messaging client based on libpurple
-which is capable of connecting to AIM, MSN, Yahoo!, XMPP, ICQ, IRC, SILC,
+which is capable of connecting to AIM, XMPP, ICQ, IRC, SILC,
 Novell GroupWise, Lotus Sametime, Zephyr, Gadu-Gadu, and QQ all at once. It has
 many common features found in other clients, as well as many unique features.
-Finch is not endorsed by or affiliated with America Online, ICQ, Microsoft, or
-Yahoo.
+Finch is not endorsed by or affiliated with America Online, ICQ, or Microsoft.
 
 .SH OPTIONS
 The following options are provided by \fBfinch\fR using the standard GNU
--- a/doc/pidgin.1.in	Wed Oct 05 22:15:51 2016 -0500
+++ b/doc/pidgin.1.in	Thu Oct 06 10:05:06 2016 -0400
@@ -29,11 +29,10 @@
 .SH DESCRIPTION
 .PP
 \fBpidgin\fR is a graphical modular messaging client based on libpurple
-which is capable of connecting to AIM, MSN, Yahoo!, XMPP, ICQ, IRC, SILC,
+which is capable of connecting to AIM, XMPP, ICQ, IRC, SILC,
 Novell GroupWise, Lotus Sametime, Zephyr, Gadu-Gadu, and QQ all at once. It has
 many common features found in other clients, as well as many unique features.
-Pidgin is not endorsed by or affiliated with America Online, ICQ, Microsoft, or
-Yahoo.
+Pidgin is not endorsed by or affiliated with America Online, ICQ, or Microsoft.
 .PP
 Pidgin can be extended by plugins written in multiple programming languages and
 controlled through DBus or \fBpurple-remote\fR.
@@ -93,7 +92,7 @@
 other protocols, aliases are saved only locally.
 .TP
 .B Protocol
-A messaging service.  AIM, XMPP, MSN, Zephyr, etc. are protocols.  Others may
+A messaging service.  AIM, XMPP, Zephyr, etc. are protocols.  Others may
 call these "service types," "account types," "services," and so on.
 
 .SH BUDDY LIST
--- a/libpurple/account.c	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/account.c	Thu Oct 06 10:05:06 2016 -0400
@@ -535,35 +535,6 @@
  * Reading from disk                                                 *
  *********************************************************************/
 static void
-migrate_yahoo_japan(PurpleAccount *account)
-{
-	/* detect a Yahoo! JAPAN account that existed prior to 2.6.0 and convert it
-	 * to use the new prpl-yahoojp.  Also remove the account-specific settings
-	 * we no longer need */
-
-	if(purple_strequal(purple_account_get_protocol_id(account), "prpl-yahoo")) {
-		if(purple_account_get_bool(account, "yahoojp", FALSE)) {
-			const char *serverjp = purple_account_get_string(account, "serverjp", NULL);
-			const char *xferjp_host = purple_account_get_string(account, "xferjp_host", NULL);
-
-			g_return_if_fail(serverjp != NULL);
-			g_return_if_fail(xferjp_host != NULL);
-
-			purple_account_set_string(account, "server", serverjp);
-			purple_account_set_string(account, "xfer_host", xferjp_host);
-
-			purple_account_set_protocol_id(account, "prpl-yahoojp");
-		}
-
-		/* these should always be nuked */
-		purple_account_remove_setting(account, "yahoojp");
-		purple_account_remove_setting(account, "serverjp");
-		purple_account_remove_setting(account, "xferjp_host");
-
-	}
-}
-
-static void
 migrate_icq_server(PurpleAccount *account)
 {
 	/* Migrate the login server setting for ICQ accounts.  See
@@ -668,9 +639,6 @@
 	}
 
 	/* we do this here because we need access to account settings to determine
-	 * if we can/should migrate an old Yahoo! JAPAN account */
-	migrate_yahoo_japan(account);
-	/* we do this here because we need access to account settings to determine
 	 * if we can/should migrate an ICQ account's server setting */
 	migrate_icq_server(account);
 	/* we do this here because we need to do it before the user views the
--- a/libpurple/account.h	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/account.h	Thu Oct 06 10:05:06 2016 -0400
@@ -192,7 +192,7 @@
 	/*
 	 * TODO: Supplementing the next two linked lists with hash tables
 	 * should help performance a lot when these lists are long.  This
-	 * matters quite a bit for protocols like MSN, where all your
+	 * matters quite a bit for protocols, where all your
 	 * buddies are added to your permit list.  Currently we have to
 	 * iterate through the entire list if we want to check if someone
 	 * is permitted or denied.  We should do this for 3.0.0.
--- a/libpurple/blist.h	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/blist.h	Thu Oct 06 10:05:06 2016 -0400
@@ -139,7 +139,7 @@
 	PurpleBlistNode node;                     /**< The node that this buddy inherits from */
 	char *name;                             /**< The name of the buddy. */
 	char *alias;                            /**< The user-set alias of the buddy */
-	char *server_alias;                     /**< The server-specified alias of the buddy.  (i.e. MSN "Friendly Names") */
+	char *server_alias;                     /**< The server-specified alias of the buddy */
 	void *proto_data;                       /**< This allows the prpl to associate whatever data it wants with a buddy */
 	PurpleBuddyIcon *icon;                    /**< The buddy icon. */
 	PurpleAccount *account;					/**< the account this buddy belongs to */
--- a/libpurple/buddyicon.c	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/buddyicon.c	Thu Oct 06 10:05:06 2016 -0400
@@ -1095,23 +1095,6 @@
 				purple_blist_node_set_string(node, "icon_checksum", hash);
 				purple_blist_node_remove_setting(node, "avatar_hash");
 			}
-			else
-			{
-				PurpleAccount *account = purple_buddy_get_account((PurpleBuddy *)node);
-				const char *prpl_id = purple_account_get_protocol_id(account);
-
-				if (g_str_equal(prpl_id, "prpl-yahoo") || g_str_equal(prpl_id, "prpl-yahoojp"))
-				{
-					int checksum = purple_blist_node_get_int(node, "icon_checksum");
-					if (checksum != 0)
-					{
-						char *checksum_str = g_strdup_printf("%i", checksum);
-						purple_blist_node_remove_setting(node, "icon_checksum");
-						purple_blist_node_set_string(node, "icon_checksum", checksum_str);
-						g_free(checksum_str);
-					}
-				}
-			}
 		}
 	}
 	else
--- a/libpurple/cmds.h	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/cmds.h	Thu Oct 06 10:05:06 2016 -0400
@@ -170,7 +170,7 @@
  *          order for the command to ever actually be called.
  * @param prpl_id If the #PURPLE_CMD_FLAG_PRPL_ONLY flag is set, this is the id
  *                of the prpl to which the command applies (such as
- *                <tt>"prpl-msn"</tt>). If the flag is not set, this parameter
+ *                <tt>"prpl-aim"</tt>). If the flag is not set, this parameter
  *                is ignored; pass @c NULL (or a humourous string of your
  *                choice!).
  * @param func This is the function to call when someone enters this command.
--- a/libpurple/conversation.c	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/conversation.c	Thu Oct 06 10:05:06 2016 -0400
@@ -351,7 +351,7 @@
 		}
 
 		/*
-		 * This hack is necessary because some prpls (MSN) have unnamed chats
+		 * This hack is necessary because some prpls have unnamed chats
 		 * that all use the same name.  A PurpleConversation for one of those
 		 * is only ever re-used if the user has left, so calls to
 		 * purple_conversation_new need to fall-through to creating a new
--- a/libpurple/conversation.h	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/conversation.h	Thu Oct 06 10:05:06 2016 -0400
@@ -884,9 +884,8 @@
 
 /**
  * Sets the quiet-time when no PURPLE_TYPING messages will be sent.
- * Few protocols need this (maybe only MSN).  If the user is still
- * typing after this quiet-period, then another PURPLE_TYPING message
- * will be sent.
+ * Few protocols need this.  If the user is still typing after this
+ * quiet-period, then another PURPLE_TYPING message will be sent.
  *
  * @param im  The IM.
  * @param val The number of seconds to wait before allowing another
--- a/libpurple/data/gconf/purple.schemas.in	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/data/gconf/purple.schemas.in	Thu Oct 06 10:05:06 2016 -0400
@@ -138,40 +138,6 @@
     </schema>
 
     <schema>
-      <key>/schemas/desktop/gnome/url-handlers/msnim/enabled</key>
-      <applyto>/desktop/gnome/url-handlers/msnim/enabled</applyto>
-      <owner>purple</owner>
-      <type>bool</type>
-      <default>true</default>
-      <locale name="C">
-        <short>Whether the specified command should handle "msnim" URLs</short>
-        <long>True if the command specified in the "command" key should handle "msnim" URLs.</long>
-      </locale>
-    </schema>
-    <schema>
-      <key>/schemas/desktop/gnome/url-handlers/msnim/command</key>
-      <applyto>/desktop/gnome/url-handlers/msnim/command</applyto>
-      <owner>purple</owner>
-      <type>string</type>
-      <default>purple-url-handler "%s"</default>
-      <locale name="C">
-        <short>The handler for "msnim" URLs</short>
-        <long>The command used to handle "msnim" URLs, if enabled.</long>
-      </locale>
-    </schema>
-    <schema>
-      <key>/schemas/desktop/gnome/url-handlers/msnim/needs_terminal</key>
-      <applyto>/desktop/gnome/url-handlers/msnim/needs_terminal</applyto>
-      <owner>purple</owner>
-      <type>bool</type>
-      <default>false</default>
-      <locale name="C">
-        <short>Run the command in a terminal</short>
-        <long>True if the command used to handle this type of URL should be run in a terminal.</long>
-      </locale>
-    </schema>
-
-    <schema>
       <key>/schemas/desktop/gnome/url-handlers/sip/enabled</key>
       <applyto>/desktop/gnome/url-handlers/sip/enabled</applyto>
       <owner>purple</owner>
@@ -238,39 +204,5 @@
         <long>True if the command used to handle this type of URL should be run in a terminal.</long>
       </locale>
     </schema>
-
-    <schema>
-      <key>/schemas/desktop/gnome/url-handlers/ymsgr/enabled</key>
-      <applyto>/desktop/gnome/url-handlers/ymsgr/enabled</applyto>
-      <owner>purple</owner>
-      <type>bool</type>
-      <default>true</default>
-      <locale name="C">
-        <short>Whether the specified command should handle "ymsgr" URLs</short>
-        <long>True if the command specified in the "command" key should handle "ymsgr" URLs.</long>
-      </locale>
-    </schema>
-    <schema>
-      <key>/schemas/desktop/gnome/url-handlers/ymsgr/command</key>
-      <applyto>/desktop/gnome/url-handlers/ymsgr/command</applyto>
-      <owner>purple</owner>
-      <type>string</type>
-      <default>purple-url-handler "%s"</default>
-      <locale name="C">
-        <short>The handler for "ymsgr" URLs</short>
-        <long>The command used to handle "ymsgr" URLs, if enabled.</long>
-      </locale>
-    </schema>
-    <schema>
-      <key>/schemas/desktop/gnome/url-handlers/ymsgr/needs_terminal</key>
-      <applyto>/desktop/gnome/url-handlers/ymsgr/needs_terminal</applyto>
-      <owner>purple</owner>
-      <type>bool</type>
-      <default>false</default>
-      <locale name="C">
-        <short>Run the command in a terminal</short>
-        <long>True if the command used to handle this type of URL should be run in a terminal.</long>
-      </locale>
-    </schema>
   </schemalist>
 </gconfschemafile>
--- a/libpurple/plugins/psychic.c	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/plugins/psychic.c	Thu Oct 06 10:05:06 2016 -0400
@@ -21,7 +21,7 @@
 #define PLUGIN_SUMMARY  N_("Psychic mode for incoming conversation")
 #define PLUGIN_DESC     N_("Causes conversation windows to appear as other" \
 			   " users begin to message you.  This works for" \
-			   " AIM, ICQ, XMPP, Sametime, and Yahoo!")
+			   " AIM, ICQ, XMPP, and Sametime")
 #define PLUGIN_AUTHOR   "Christopher O'Brien <siege@preoccupied.net>"
 
 
--- a/libpurple/protocols/Makefile.am	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/protocols/Makefile.am	Thu Oct 06 10:05:06 2016 -0400
@@ -1,5 +1,5 @@
 EXTRA_DIST = Makefile.mingw
 
-DIST_SUBDIRS = bonjour gg irc jabber msn myspace mxit novell null oscar sametime silc silc10 simple yahoo zephyr
+DIST_SUBDIRS = bonjour gg irc jabber novell null oscar sametime silc silc10 simple zephyr
 
 SUBDIRS = $(DYNAMIC_PRPLS) $(STATIC_PRPLS)
--- a/libpurple/protocols/Makefile.mingw	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/protocols/Makefile.mingw	Thu Oct 06 10:05:06 2016 -0400
@@ -8,7 +8,7 @@
 PIDGIN_TREE_TOP := ../..
 include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
 
-SUBDIRS = gg irc jabber msn mxit novell null oscar sametime silc simple yahoo bonjour myspace
+SUBDIRS = gg irc jabber novell null oscar sametime silc simple bonjour
 
 .PHONY: all install clean
 
--- a/libpurple/protocols/jabber/Makefile.am	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/protocols/jabber/Makefile.am	Thu Oct 06 10:05:06 2016 -0400
@@ -27,8 +27,6 @@
 			  data.h \
 			  disco.c \
 			  disco.h \
-			  facebook_roster.c \
-			  facebook_roster.h \
 			  google/gmail.c \
 			  google/gmail.h \
 			  google/google.c \
--- a/libpurple/protocols/jabber/Makefile.mingw	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/protocols/jabber/Makefile.mingw	Thu Oct 06 10:05:06 2016 -0400
@@ -55,7 +55,6 @@
 			chat.c \
 			data.c \
 			disco.c \
-			facebook_roster.c \
 			google/gmail.c \
 			google/google.c \
 			google/google_presence.c \
--- a/libpurple/protocols/jabber/facebook_roster.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +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 "facebook_roster.h"
-
-#include "roster.h"
-
-#include "internal.h"
-
-void
-jabber_facebook_roster_cleanup(JabberStream *js, xmlnode *query)
-{
-	PurpleAccount *account = purple_connection_get_account(js->gc);
-	xmlnode *item;
-	GSList *local_buddies;
-	GHashTable *remove_buddies;
-	GHashTableIter it;
-	PurpleBuddy *buddy;
-	const gchar *jid;
-
-	if (js->facebook_roster_cleanup_performed)
-		return;
-	js->facebook_roster_cleanup_performed = TRUE;
-
-	/* mark all local buddies as "to be removed" */
-	remove_buddies = g_hash_table_new_full(g_str_hash, g_str_equal,
-		g_free, NULL);
-	local_buddies = purple_find_buddies(account, NULL);
-	for (; local_buddies; local_buddies = g_slist_delete_link(
-		local_buddies, local_buddies))
-	{
-		buddy = local_buddies->data;
-
-		g_hash_table_insert(remove_buddies, g_strdup(jabber_normalize(
-			account, purple_buddy_get_name(buddy))), buddy);
-	}
-
-	/* un-mark all remote buddies */
-	for (item = xmlnode_get_child(query, "item"); item;
-		item = xmlnode_get_next_twin(item))
-	{
-		jid = xmlnode_get_attrib(item, "jid");
-
-		g_hash_table_remove(remove_buddies,
-			jabber_normalize(account, jid));
-	}
-
-	/* remove all not-remote buddies */
-	g_hash_table_iter_init(&it, remove_buddies);
-	while (g_hash_table_iter_next(&it, (gpointer*)&jid, (gpointer*)&buddy)) {
-		const gchar *alias = purple_buddy_get_local_buddy_alias(buddy);
-		item = xmlnode_new_child(query, "item");
-		xmlnode_set_namespace(item, xmlnode_get_namespace(query));
-		xmlnode_set_attrib(item, "jid", jid);
-		xmlnode_set_attrib(item, "subscription", "remove");
-		if (alias)
-			xmlnode_set_attrib(item, "name", alias);
-	}
-
-	g_hash_table_destroy(remove_buddies);
-}
-
-gboolean
-jabber_facebook_roster_incoming(JabberStream *js, xmlnode *item)
-{
-	PurpleAccount *account = purple_connection_get_account(js->gc);
-	const gchar *jid, *subscription;
-	gchar *jid_norm;
-	PurpleBuddy *buddy;
-	PurpleGroup *buddy_group;
-	xmlnode *group;
-	const gchar *alias;
-
-	subscription = xmlnode_get_attrib(item, "subscription");
-
-	/* Skip entries added with jabber_facebook_roster_cleanup */
-	if (g_strcmp0(subscription, "remove") == 0)
-		return TRUE;
-
-	jid = xmlnode_get_attrib(item, "jid");
-	jid_norm = g_strdup(jabber_normalize(account, jid));
-	buddy = purple_find_buddy(account, jid);
-	g_free(jid_norm);
-
-	/* Facebook forces "Facebook Friends" group */
-	while ((group = xmlnode_get_child(item, "group")) != NULL)
-		xmlnode_free(group);
-	group = xmlnode_new_child(item, "group");
-	xmlnode_set_namespace(group, xmlnode_get_namespace(item));
-
-	/* We don't have that buddy on the list, add him to the default group */
-	if (!buddy) {
-		xmlnode_insert_data(group,
-			JABBER_ROSTER_DEFAULT_GROUP, -1);
-		return TRUE;
-	}
-
-	/* Facebook forces buddy real name as alias */
-	alias = purple_buddy_get_local_buddy_alias(buddy);
-	if (alias)
-		xmlnode_set_attrib(item, "name", alias);
-
-	/* Add buddy to his group */
-	buddy_group = purple_buddy_get_group(buddy);
-	if (g_strcmp0(purple_group_get_name(buddy_group), _("Buddies")) == 0)
-		buddy_group = NULL;
-	if (buddy_group) {
-		xmlnode_insert_data(group,
-			purple_group_get_name(buddy_group), -1);
-	} else {
-		xmlnode_insert_data(group,
-			JABBER_ROSTER_DEFAULT_GROUP, -1);
-	}
-
-	return TRUE;
-}
--- a/libpurple/protocols/jabber/facebook_roster.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +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_XMPP_FACEBOOK_ROSTER_H_
-#define PURPLE_XMPP_FACEBOOK_ROSTER_H_
-
-#include "jabber.h"
-
-/* removes deleted buddies from the list */
-void
-jabber_facebook_roster_cleanup(JabberStream *js, xmlnode *query);
-
-/* ignores facebook roster quirks */
-gboolean
-jabber_facebook_roster_incoming(JabberStream *js, xmlnode *item);
-
-#endif /* PURPLE_XMPP_FACEBOOK_ROSTER_H_ */
--- a/libpurple/protocols/jabber/jabber.c	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/protocols/jabber/jabber.c	Thu Oct 06 10:05:06 2016 -0400
@@ -934,12 +934,6 @@
 	js->gc = gc;
 	js->fd = -1;
 
-	if (g_strcmp0("prpl-facebook-xmpp",
-		purple_account_get_protocol_id(account)) == 0)
-	{
-		js->server_caps |= JABBER_CAP_FACEBOOK;
-	}
-
 	user = g_strdup(purple_account_get_username(account));
 	/* jabber_id_new doesn't accept "user@domain/" as valid */
 	slash = strchr(user, '/');
--- a/libpurple/protocols/jabber/jabber.h	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/protocols/jabber/jabber.h	Thu Oct 06 10:05:06 2016 -0400
@@ -49,8 +49,6 @@
 	JABBER_CAP_ITEMS          = 1 << 14,
 	JABBER_CAP_ROSTER_VERSIONING = 1 << 15,
 
-	JABBER_CAP_FACEBOOK       = 1 << 16,
-
 	JABBER_CAP_RETRIEVED      = 1 << 31
 } JabberCapabilities;
 
@@ -284,9 +282,6 @@
 	gchar *google_relay_host;
 	GList *google_relay_requests; /* the HTTP requests to get */
 												/* relay info */
-
-	/* facebook quirks */
-	gboolean facebook_roster_cleanup_performed;
 };
 
 typedef gboolean (JabberFeatureEnabled)(JabberStream *js, const gchar *namespace);
--- a/libpurple/protocols/jabber/libxmpp.c	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/protocols/jabber/libxmpp.c	Thu Oct 06 10:05:06 2016 -0400
@@ -315,8 +315,9 @@
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
 						  option);
 
-	/* this should probably be part of global smiley theme settings later on,
-	  shared with MSN */
+	/* this should probably be part of global smiley theme settings
+	 * later on
+	 */
 	option = purple_account_option_bool_new(_("Show Custom Smileys"),
 		"custom_smileys", TRUE);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
--- a/libpurple/protocols/jabber/roster.c	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/protocols/jabber/roster.c	Thu Oct 06 10:05:06 2016 -0400
@@ -27,7 +27,6 @@
 
 #include "buddy.h"
 #include "chat.h"
-#include "facebook_roster.h"
 #include "google/google.h"
 #include "google/google_roster.h"
 #include "presence.h"
@@ -212,18 +211,11 @@
 
 	js->currently_parsing_roster_push = TRUE;
 
-	if (js->server_caps & JABBER_CAP_FACEBOOK)
-		jabber_facebook_roster_cleanup(js, query);
-
 	for(item = xmlnode_get_child(query, "item"); item; item = xmlnode_get_next_twin(item))
 	{
 		const char *jid, *name, *subscription, *ask;
 		JabberBuddy *jb;
 
-		if (js->server_caps & JABBER_CAP_FACEBOOK)
-			if (!jabber_facebook_roster_incoming(js, item))
-				continue;
-
 		subscription = xmlnode_get_attrib(item, "subscription");
 		jid = xmlnode_get_attrib(item, "jid");
 		name = xmlnode_get_attrib(item, "name");
--- a/libpurple/protocols/msn/Makefile.am	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-EXTRA_DIST = \
-	directconn.c \
-	directconn.h \
-	Makefile.mingw
-
-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
-
-MSNSOURCES = \
-	cmdproc.c \
-	cmdproc.h \
-	command.c \
-	command.h \
-	contact.c\
-	contact.h\
-	directconn.c \
-	directconn.h \
-	error.c \
-	error.h \
-	group.c \
-	group.h \
-	history.c \
-	history.h \
-	httpconn.c \
-	httpconn.h \
-	msg.c \
-	msg.h \
-	msn.c \
-	msn.h \
-	nexus.c \
-	nexus.h \
-	notification.c \
-	notification.h \
-	object.c \
-	object.h \
-	oim.c\
-	oim.h\
-	p2p.c \
-	p2p.h \
-	page.c \
-	page.h \
-	servconn.c \
-	servconn.h \
-	session.c \
-	session.h \
-	slp.c \
-	slp.h \
-	slpcall.c \
-	slpcall.h \
-	slplink.c \
-	slplink.h \
-	slpmsg.c \
-	slpmsg.h \
-	slpmsg_part.c \
-	slpmsg_part.h \
-	soap.c \
-	soap.h \
-	state.c \
-	state.h \
-	sbconn.c \
-	sbconn.h \
-	switchboard.c \
-	switchboard.h \
-	table.c \
-	table.h \
-	tlv.c \
-	tlv.h \
-	transaction.c \
-	transaction.h \
-	user.c \
-	user.h \
-	userlist.c \
-	userlist.h \
-	xfer.c \
-	xfer.h \
-	msnutils.c \
-	msnutils.h
-
-AM_CFLAGS = $(st)
-
-libmsn_la_LDFLAGS = -module -avoid-version
-
-if STATIC_MSN
-
-st = -DPURPLE_STATIC_PRPL
-noinst_LTLIBRARIES = libmsn.la
-libmsn_la_SOURCES  = $(MSNSOURCES)
-libmsn_la_CFLAGS   = $(AM_CFLAGS)
-
-else
-
-st =
-pkg_LTLIBRARIES   = libmsn.la
-libmsn_la_SOURCES = $(MSNSOURCES)
-libmsn_la_LIBADD  = $(GLIB_LIBS)
-
-endif
-
-AM_CPPFLAGS = \
-	-I$(top_srcdir)/libpurple \
-	-I$(top_builddir)/libpurple \
-	$(GLIB_CFLAGS) \
-	$(DEBUG_CFLAGS)
--- a/libpurple/protocols/msn/Makefile.mingw	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-#
-# Makefile.mingw
-#
-# Description: Makefile for win32 (mingw) version of libmsn
-#
-
-PIDGIN_TREE_TOP := ../../..
-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
-
-TARGET = libmsn
-TYPE = PLUGIN
-
-# Static or Plugin...
-ifeq ($(TYPE),STATIC)
-  DEFINES += -DSTATIC
-  DLL_INSTALL_DIR =	$(PURPLE_INSTALL_DIR)
-else
-ifeq ($(TYPE),PLUGIN)
-  DLL_INSTALL_DIR =	$(PURPLE_INSTALL_PLUGINS_DIR)
-endif
-endif
-
-##
-## INCLUDE PATHS
-##
-INCLUDE_PATHS +=	-I. \
-			-I$(GTK_TOP)/include \
-			-I$(GTK_TOP)/include/glib-2.0 \
-			-I$(GTK_TOP)/lib/glib-2.0/include \
-			-I$(PURPLE_TOP) \
-			-I$(PURPLE_TOP)/win32 \
-			-I$(PIDGIN_TREE_TOP)
-
-LIB_PATHS +=		-L$(GTK_TOP)/lib \
-			-L$(PURPLE_TOP)
-
-##
-##  SOURCES, OBJECTS
-##
-C_SRC =			cmdproc.c \
-			command.c \
-			contact.c\
-			directconn.c \
-			error.c \
-			group.c \
-			history.c \
-			httpconn.c \
-			msg.c \
-			msn.c \
-			nexus.c \
-			notification.c \
-			object.c \
-			oim.c\
-			p2p.c \
-			page.c \
-			servconn.c \
-			session.c \
-			slp.c \
-			slpcall.c \
-			slplink.c \
-			slpmsg.c \
-			slpmsg_part.c \
-			soap.c\
-			state.c \
-			sbconn.c \
-			switchboard.c \
-			table.c \
-			tlv.c \
-			transaction.c \
-			user.c \
-			userlist.c \
-			xfer.c \
-			msnutils.c
-
-OBJECTS = $(C_SRC:%.c=%.o)
-
-##
-## LIBRARIES
-##
-LIBS =	\
-			-lglib-2.0 \
-			-lintl \
-			-lws2_32 \
-			-lpurple
-
-include $(PIDGIN_COMMON_RULES)
-
-##
-## TARGET DEFINITIONS
-##
-.PHONY: all install clean
-
-all: $(TARGET).dll
-
-install: all $(DLL_INSTALL_DIR)
-	cp $(TARGET).dll $(DLL_INSTALL_DIR)
-
-$(OBJECTS): $(PURPLE_CONFIG_H)
-
-$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-	$(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
-
-##
-## CLEAN RULES
-##
-clean:
-	rm -f $(OBJECTS)
-	rm -f $(TARGET).dll
-
-include $(PIDGIN_COMMON_TARGETS)
--- a/libpurple/protocols/msn/cmdproc.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,339 +0,0 @@
-/**
- * @file cmdproc.c MSN command processor functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-
-#include "cmdproc.h"
-#include "error.h"
-
-MsnCmdProc *
-msn_cmdproc_new(MsnSession *session)
-{
-	MsnCmdProc *cmdproc;
-
-	cmdproc = g_new0(MsnCmdProc, 1);
-
-	cmdproc->session = session;
-	cmdproc->txqueue = g_queue_new();
-	cmdproc->history = msn_history_new();
-
-	cmdproc->multiparts = g_hash_table_new_full(g_str_hash, g_str_equal,
-	                                            NULL, (GDestroyNotify)msn_message_unref);
-
-	return cmdproc;
-}
-
-void
-msn_cmdproc_destroy(MsnCmdProc *cmdproc)
-{
-	MsnTransaction *trans;
-
-	while ((trans = g_queue_pop_head(cmdproc->txqueue)) != NULL)
-		msn_transaction_destroy(trans);
-
-	g_queue_free(cmdproc->txqueue);
-
-	msn_history_destroy(cmdproc->history);
-
-	if (cmdproc->last_cmd != NULL)
-		msn_command_unref(cmdproc->last_cmd);
-
-	g_hash_table_destroy(cmdproc->multiparts);
-
-	g_free(cmdproc);
-}
-
-void
-msn_cmdproc_process_queue(MsnCmdProc *cmdproc)
-{
-	MsnTransaction *trans;
-
-	while ((trans = g_queue_pop_head(cmdproc->txqueue)) != NULL)
-		msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-void
-msn_cmdproc_queue_trans(MsnCmdProc *cmdproc, MsnTransaction *trans)
-{
-	g_return_if_fail(cmdproc != NULL);
-	g_return_if_fail(trans   != NULL);
-
-	g_queue_push_tail(cmdproc->txqueue, trans);
-}
-
-static void
-show_debug_cmd(MsnCmdProc *cmdproc, gboolean incoming, const char *command)
-{
-	MsnServConn *servconn;
-	const char *names[] = { "NS", "SB" };
-	char *show;
-	char tmp;
-	size_t len;
-
-	servconn = cmdproc->servconn;
-	len = strlen(command);
-	show = g_strdup(command);
-
-	tmp = (incoming) ? 'S' : 'C';
-
-	if ((show[len - 1] == '\n') && (show[len - 2] == '\r'))
-	{
-		show[len - 2] = '\0';
-	}
-
-	purple_debug_misc("msn", "%c: %s %03d: %s\n", tmp,
-					names[servconn->type], servconn->num, show);
-
-	g_free(show);
-}
-
-gboolean
-msn_cmdproc_send_trans(MsnCmdProc *cmdproc, MsnTransaction *trans)
-{
-	MsnServConn *servconn;
-	char *data;
-	size_t len;
-	gboolean ret;
-
-	g_return_val_if_fail(cmdproc != NULL, TRUE);
-	g_return_val_if_fail(trans != NULL, TRUE);
-
-	servconn = cmdproc->servconn;
-
-	if (!servconn->connected) {
-		msn_transaction_destroy(trans);
-		return FALSE;
-	}
-
-	if (trans->saveable)
-		msn_history_add(cmdproc->history, trans);
-
-	data = msn_transaction_to_string(trans);
-
-	len = strlen(data);
-
-	show_debug_cmd(cmdproc, FALSE, data);
-
-	if (trans->callbacks == NULL)
-		trans->callbacks = g_hash_table_lookup(cmdproc->cbs_table->cmds,
-											   trans->command);
-
-	if (trans->payload != NULL)
-	{
-		data = g_realloc(data, len + trans->payload_len);
-		memcpy(data + len, trans->payload, trans->payload_len);
-		len += trans->payload_len;
-
-		/*
-		 * We're done with trans->payload.  Free it so that the memory
-		 * doesn't sit around in cmdproc->history.
-		 */
-		g_free(trans->payload);
-		trans->payload = NULL;
-		trans->payload_len = 0;
-	}
-
-	ret = msn_servconn_write(servconn, data, len) != -1;
-
-	if (!trans->saveable)
-		msn_transaction_destroy(trans);
-	g_free(data);
-	return ret;
-}
-
-void
-msn_cmdproc_process_payload(MsnCmdProc *cmdproc, char *payload,
-							int payload_len)
-{
-	MsnCommand *last;
-
-	g_return_if_fail(cmdproc != NULL);
-
-	last = cmdproc->last_cmd;
-	last->payload = g_memdup(payload, payload_len);
-	last->payload_len = payload_len;
-
-	if (last->payload_cb != NULL)
-		last->payload_cb(cmdproc, last, payload, payload_len);
-}
-
-void
-msn_cmdproc_process_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	MsnMsgTypeCb cb;
-	const char *message_id = NULL;
-
-	/* Multi-part messages */
-	message_id = msn_message_get_header_value(msg, "Message-ID");
-	if (message_id != NULL) {
-		/* This is the first in a series of chunks */
-
-		const char *chunk_text = msn_message_get_header_value(msg, "Chunks");
-		guint chunk;
-		if (chunk_text != NULL) {
-			chunk = strtol(chunk_text, NULL, 10);
-			/* 1024 chunks of ~1300 bytes is ~1MB, which seems OK to prevent
-			   some random client causing pidgin to hog a ton of memory.
-			   Probably should figure out the maximum that the official client
-			   actually supports, though. */
-			if (chunk > 0 && chunk < 1024) {
-				msg->total_chunks = chunk;
-				msg->received_chunks = 1;
-				g_hash_table_insert(cmdproc->multiparts, (gpointer)message_id, msn_message_ref(msg));
-				purple_debug_info("msn", "Received chunked message, message_id: '%s', total chunks: %d\n",
-				                  message_id, chunk);
-			} else {
-				purple_debug_error("msn", "MessageId '%s' has too many chunks: %d\n", message_id, chunk);
-			}
-			return;
-		} else {
-			chunk_text = msn_message_get_header_value(msg, "Chunk");
-			if (chunk_text != NULL) {
-				/* This is one chunk in a series of chunks */
-
-				MsnMessage *first = g_hash_table_lookup(cmdproc->multiparts, message_id);
-				chunk = strtol(chunk_text, NULL, 10);
-				if (first != NULL) {
-					if (first->received_chunks != chunk) {
-						/*
-						 * We received an out of order chunk number (i.e. not the
-						 * next one in the sequence).  Not sure if this can happen
-						 * legitimately, but we definitely don't handle it right
-						 * now.
-						 */
-						g_hash_table_remove(cmdproc->multiparts, message_id);
-						return;
-					}
-
-					/* Chunk is from 1 to total-1 (doesn't count first one) */
-					purple_debug_info("msn", "Received chunk %d of %d, message_id: '%s'\n",
-							chunk + 1, first->total_chunks, message_id);
-					first->body = g_realloc(first->body, first->body_len + msg->body_len);
-					memcpy(first->body + first->body_len, msg->body, msg->body_len);
-					first->body_len += msg->body_len;
-					first->received_chunks++;
-					if (first->received_chunks != first->total_chunks)
-						/* We're waiting for more chunks */
-						return;
-
-					/*
-					 * We have all the chunks for this message, great!  Send
-					 * it along... The caller takes care of freeing the old one.
-					 */
-					msg = first;
-				} else {
-					purple_debug_error("msn",
-					                   "Unable to find first chunk of message_id '%s' to correspond with chunk %d.\n",
-					                   message_id, chunk + 1);
-				}
-			} else {
-				purple_debug_error("msn", "Received MessageId '%s' with no chunk number!\n", message_id);
-			}
-		}
-	}
-
-	if (msn_message_get_content_type(msg) == NULL)
-	{
-		purple_debug_misc("msn", "failed to find message content\n");
-		return;
-	}
-
-	cb = g_hash_table_lookup(cmdproc->cbs_table->msgs,
-							 msn_message_get_content_type(msg));
-
-	if (cb != NULL)
-		cb(cmdproc, msg);
-	else
-		purple_debug_warning("msn", "Unhandled content-type '%s'\n",
-						   msn_message_get_content_type(msg));
-
-	if (message_id != NULL)
-		g_hash_table_remove(cmdproc->multiparts, message_id);
-}
-
-void
-msn_cmdproc_process_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnTransCb cb = NULL;
-	MsnTransaction *trans = NULL;
-
-	if (cmd->trId)
-		cmd->trans = trans = msn_history_find(cmdproc->history, cmd->trId);
-
-	if (trans != NULL)
-		if (trans->timer) {
-			purple_timeout_remove(trans->timer);
-			trans->timer = 0;
-		}
-
-	if (g_ascii_isdigit(cmd->command[0]) && trans != NULL)
-	{
-		MsnErrorCb error_cb;
-		int error;
-
-		error = atoi(cmd->command);
-
-		error_cb = trans->error_cb;
-		if (error_cb == NULL)
-			error_cb = g_hash_table_lookup(cmdproc->cbs_table->errors, trans->command);
-
-		if (error_cb != NULL)
-			error_cb(cmdproc, trans, error);
-		else
-			msn_error_handle(cmdproc->session, error);
-
-		return;
-	}
-
-	cb = g_hash_table_lookup(cmdproc->cbs_table->async, cmd->command);
-
-	if (cb == NULL && trans != NULL && trans->callbacks != NULL)
-		cb = g_hash_table_lookup(trans->callbacks, cmd->command);
-
-	if (cb == NULL)
-		cb = g_hash_table_lookup(cmdproc->cbs_table->fallback, cmd->command);
-
-	if (cb != NULL)
-		cb(cmdproc, cmd);
-	else
-		purple_debug_warning("msn", "Unhandled command '%s'\n",
-						   cmd->command);
-
-	if (trans != NULL && trans->pendent_cmd != NULL)
-		msn_transaction_unqueue_cmd(trans, cmdproc);
-}
-
-void
-msn_cmdproc_process_cmd_text(MsnCmdProc *cmdproc, const char *command)
-{
-	show_debug_cmd(cmdproc, TRUE, command);
-
-	if (cmdproc->last_cmd != NULL)
-		msn_command_unref(cmdproc->last_cmd);
-
-	cmdproc->last_cmd = msn_command_from_string(command);
-
-	msn_cmdproc_process_cmd(cmdproc, cmdproc->last_cmd);
-}
--- a/libpurple/protocols/msn/cmdproc.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/**
- * @file cmdproc.h MSN command processor functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_CMDPROC_H
-#define MSN_CMDPROC_H
-
-typedef struct _MsnCmdProc MsnCmdProc;
-
-#include "command.h"
-#include "history.h"
-#include "servconn.h"
-#include "session.h"
-#include "table.h"
-
-struct _MsnCmdProc
-{
-	MsnSession *session;
-	MsnServConn *servconn;
-
-	GQueue *txqueue;
-
-	MsnCommand *last_cmd;
-
-	MsnTable *cbs_table;
-
-	MsnHistory *history;
-
-	GHashTable *multiparts; /**< Multi-part message ID's */
-
-	void *data; /**< Extra data, like the switchboard. */
-};
-
-/**
- * Creates a MsnCmdProc structure.
- *
- * @param session 	The session to associate with.
- *
- * @return A new MsnCmdProc structure.
- */
-MsnCmdProc *msn_cmdproc_new(MsnSession *session);
-
-/**
- * Destroys an MsnCmdProc.
- *
- * @param cmdproc 	The object structure.
- */
-void msn_cmdproc_destroy(MsnCmdProc *cmdproc);
-
-/**
- * Process the queued transactions.
- *
- * @param cmdproc 	The MsnCmdProc.
- */
-void msn_cmdproc_process_queue(MsnCmdProc *cmdproc);
-
-/**
- * Sends transaction using this servconn.
- *
- * @param cmdproc 	The MsnCmdProc to be used.
- * @param trans 	The MsnTransaction to be sent.
- */
-gboolean msn_cmdproc_send_trans(MsnCmdProc *cmdproc, MsnTransaction *trans);
-
-/**
- * Add a transaction to the queue to be processed latter.
- *
- * @param cmdproc 	The MsnCmdProc in which the transaction will be queued.
- * @param trans 	The MsnTransaction to be queued.
- */
-void msn_cmdproc_queue_trans(MsnCmdProc *cmdproc,
-							 MsnTransaction *trans);
-
-void msn_cmdproc_process_msg(MsnCmdProc *cmdproc,
-							 MsnMessage *msg);
-void msn_cmdproc_process_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd);
-void msn_cmdproc_process_cmd_text(MsnCmdProc *cmdproc, const char *command);
-void msn_cmdproc_process_payload(MsnCmdProc *cmdproc,
-								 char *payload, int payload_len);
-
-#endif /* MSN_CMDPROC_H */
--- a/libpurple/protocols/msn/command.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/**
- * @file command.c MSN command functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#include "internal.h"
-
-#include "command.h"
-
-static gboolean
-is_num(const char *str)
-{
-	const char *c;
-	for (c = str; *c; c++) {
-		if (!(g_ascii_isdigit(*c)))
-			return FALSE;
-	}
-
-	return TRUE;
-}
-
-MsnCommand *
-msn_command_from_string(const char *string)
-{
-	MsnCommand *cmd;
-	char *param_start;
-
-	g_return_val_if_fail(string != NULL, NULL);
-
-	cmd = g_new0(MsnCommand, 1);
-	cmd->command = g_strdup(string);
-	param_start = strchr(cmd->command, ' ');
-
-	if (param_start)
-	{
-		*param_start++ = '\0';
-		cmd->params = g_strsplit_set(param_start, " ", 0);
-	}
-
-	if (cmd->params != NULL)
-	{
-		guint c;
-
-		for (c = 0; cmd->params[c] && cmd->params[c][0]; c++);
-		cmd->param_count = c;
-
-		if (cmd->param_count) {
-			char *param = cmd->params[0];
-			cmd->trId = is_num(param) ? atoi(param) : 0;
-		} else {
-			cmd->trId = 0;
-		}
-	}
-	else
-	{
-		cmd->trId = 0;
-	}
-
-	msn_command_ref(cmd);
-
-	return cmd;
-}
-
-static void
-msn_command_destroy(MsnCommand *cmd)
-{
-	g_free(cmd->payload);
-	g_free(cmd->command);
-	g_strfreev(cmd->params);
-	g_free(cmd);
-}
-
-MsnCommand *
-msn_command_ref(MsnCommand *cmd)
-{
-	g_return_val_if_fail(cmd != NULL, NULL);
-
-	cmd->ref_count++;
-	return cmd;
-}
-
-void
-msn_command_unref(MsnCommand *cmd)
-{
-	g_return_if_fail(cmd != NULL);
-	g_return_if_fail(cmd->ref_count > 0);
-
-	cmd->ref_count--;
-
-	if (cmd->ref_count == 0)
-	{
-		msn_command_destroy(cmd);
-	}
-}
-
--- a/libpurple/protocols/msn/command.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/**
- * @file command.h MSN command functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_COMMAND_H
-#define MSN_COMMAND_H
-
-typedef struct _MsnCommand MsnCommand;
-
-#include "cmdproc.h"
-#include "transaction.h"
-
-typedef void (*MsnPayloadCb)(MsnCmdProc *cmdproc, MsnCommand *cmd,
-							 char *payload, size_t len);
-
-/**
- * A received command.
- */
-struct _MsnCommand
-{
-	unsigned int trId;
-
-	char *command;
-	char **params;
-	guint param_count;
-
-	guint ref_count;
-
-	MsnTransaction *trans;
-
-	char *payload;
-	size_t payload_len;
-
-	MsnPayloadCb payload_cb;
-	void *payload_cbdata;
-};
-
-/**
- * Create a command object from the incoming string and ref it.
- *
- * @param string 	The incoming string.
- *
- * @return 			A MsnCommand object.
- */
-MsnCommand *msn_command_from_string(const char *string);
-
-/**
- * Increment the ref count.
- *
- * @param cmd 	The MsnCommand to be ref.
- *
- * @return 		The ref command.
- */
-MsnCommand *msn_command_ref(MsnCommand *cmd);
-
-/**
- * Decrement the ref count. If the count goes to 0, destroy it.
- *
- * @param cmd	The MsnCommand to be unref.
- *
- */
-void msn_command_unref(MsnCommand *cmd);
-
-#endif /* MSN_COMMAND_H */
-
--- a/libpurple/protocols/msn/contact.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2048 +0,0 @@
-/**
- * @file contact.c
- * 	get MSN contacts via SOAP request
- *	created by MaYuan<mayuan2006@gmail.com>
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-
-#include "contact.h"
-#include "xmlnode.h"
-#include "group.h"
-#include "msnutils.h"
-#include "soap.h"
-#include "nexus.h"
-#include "user.h"
-
-const char *MsnSoapPartnerScenarioText[] =
-{
-	"Initial",
-	"ContactSave",
-	"MessengerPendingList",
-	"ContactMsgrAPI",
-	"BlockUnblock",
-	"Timer"
-};
-
-const char *MsnMemberRole[] =
-{
-	"Forward",
-	"Allow",
-	"Block",
-	"Reverse",
-	"Pending"
-};
-
-typedef struct {
-	MsnSession *session;
-	MsnSoapPartnerScenario which;
-} GetContactListCbData;
-
-MsnCallbackState *
-msn_callback_state_new(MsnSession *session)
-{
-	MsnCallbackState *state = g_new0(MsnCallbackState, 1);
-
-	state->session = session;
-
-	return state;
-}
-
-MsnCallbackState *
-msn_callback_state_dup(MsnCallbackState *state)
-{
-	MsnCallbackState *new_state = g_new0(MsnCallbackState, 1);
-
-	new_state->session = state->session;
-	new_state->who = g_strdup(state->who);
-	new_state->uid = g_strdup(state->uid);
-	new_state->old_group_name = g_strdup(state->old_group_name);
-	new_state->new_group_name = g_strdup(state->new_group_name);
-	new_state->guid = g_strdup(state->guid);
-	/* The rest should be made new */
-
-	return new_state;
-}
-
-void
-msn_callback_state_free(MsnCallbackState *state)
-{
-	if (state == NULL)
-		return;
-
-	g_free(state->who);
-	g_free(state->uid);
-	g_free(state->old_group_name);
-	g_free(state->new_group_name);
-	g_free(state->guid);
-	if (state->body)
-		xmlnode_free(state->body);
-
-	g_free(state);
-}
-
-void
-msn_callback_state_set_who(MsnCallbackState *state, const gchar *who)
-{
-	g_return_if_fail(state != NULL);
-
-	g_free(state->who);
-	state->who = g_strdup(who);
-}
-
-void
-msn_callback_state_set_uid(MsnCallbackState *state, const gchar *uid)
-{
-	g_return_if_fail(state != NULL);
-
-	g_free(state->uid);
-	state->uid = g_strdup(uid);
-}
-
-void
-msn_callback_state_set_old_group_name(MsnCallbackState *state, const gchar *old_group_name)
-{
-	g_return_if_fail(state != NULL);
-
-	g_free(state->old_group_name);
-	state->old_group_name = g_strdup(old_group_name);
-}
-
-void
-msn_callback_state_set_new_group_name(MsnCallbackState *state, const gchar *new_group_name)
-{
-	g_return_if_fail(state != NULL);
-
-	g_free(state->new_group_name);
-	state->new_group_name = g_strdup(new_group_name);
-}
-
-void
-msn_callback_state_set_guid(MsnCallbackState *state, const gchar *guid)
-{
-	g_return_if_fail(state != NULL);
-
-	g_free(state->guid);
-	state->guid = g_strdup(guid);
-}
-
-
-void
-msn_callback_state_set_list_id(MsnCallbackState *state, MsnListId list_id)
-{
-	g_return_if_fail(state != NULL);
-
-	state->list_id = list_id;
-}
-
-void
-msn_callback_state_set_action(MsnCallbackState *state, MsnCallbackAction action)
-{
-	g_return_if_fail(state != NULL);
-
-	state->action |= action;
-}
-
-/***************************************************************
- * General SOAP handling
- ***************************************************************/
-
-static const char *
-msn_contact_operation_str(MsnCallbackAction action)
-{
-	/* Make sure this is large enough when adding more */
-	static char buf[BUF_LEN];
-	buf[0] = '\0';
-
-	if (action & MSN_ADD_BUDDY)
-		strcat(buf, "Adding Buddy,");
-	if (action & MSN_MOVE_BUDDY)
-		strcat(buf, "Moving Buddy,");
-	if (action & MSN_ACCEPTED_BUDDY)
-		strcat(buf, "Accepted Buddy,");
-	if (action & MSN_DENIED_BUDDY)
-		strcat(buf, "Denied Buddy,");
-	if (action & MSN_ADD_GROUP)
-		strcat(buf, "Adding Group,");
-	if (action & MSN_DEL_GROUP)
-		strcat(buf, "Deleting Group,");
-	if (action & MSN_RENAME_GROUP)
-		strcat(buf, "Renaming Group,");
-	if (action & MSN_UPDATE_INFO)
-		strcat(buf, "Updating Contact Info,");
-	if (action & MSN_ANNOTATE_USER)
-		strcat(buf, "Annotating Contact,");
-
-	return buf;
-}
-
-static gboolean msn_contact_request(MsnCallbackState *state);
-
-static void
-msn_contact_request_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = data;
-	xmlnode *fault;
-	char *faultcode_str;
-	xmlnode *cachekey;
-	char *changed;
-
-	if (resp == NULL) {
-		purple_debug_error("msn",
-		                   "Operation {%s} failed. No response received from server.\n",
-		                   msn_contact_operation_str(state->action));
-		msn_session_set_error(state->session, MSN_ERROR_BAD_BLIST, NULL);
-		msn_callback_state_free(state);
-		return;
-	}
-
- 	/* Update CacheKey if necessary */
- 	cachekey = xmlnode_get_child(resp->xml, "Header/ServiceHeader/CacheKeyChanged");
- 	if (cachekey != NULL) {
- 		changed = xmlnode_get_data(cachekey);
- 		if (changed && !strcmp(changed, "true")) {
- 			cachekey = xmlnode_get_child(resp->xml, "Header/ServiceHeader/CacheKey");
- 			g_free(state->session->abch_cachekey);
- 			state->session->abch_cachekey = xmlnode_get_data(cachekey);
- 			purple_debug_info("msn", "Updated CacheKey for %s to '%s'.\n",
- 			                  purple_account_get_username(state->session->account),
- 			                  state->session->abch_cachekey);
- 		}
- 		g_free(changed);
- 	}
-
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-
-	if (fault == NULL) {
-		/* No errors */
-		if (state->cb)
-			state->cb(req, resp, data);
-		msn_callback_state_free(state);
-		return;
-	}
-
-	faultcode_str = xmlnode_get_data(xmlnode_get_child(fault, "faultcode"));
-
-	if (faultcode_str && g_str_equal(faultcode_str, "q0:BadContextToken")) {
-		purple_debug_info("msn",
-		                  "Contact Operation {%s} failed because of bad token."
-		                  " Updating token now and retrying operation.\n",
-		                  msn_contact_operation_str(state->action));
-		/* Token has expired, so renew it, and try again later */
-		msn_nexus_update_token(state->session->nexus, MSN_AUTH_CONTACTS,
-		                       (GSourceFunc)msn_contact_request, data);
-	}
-	else
-	{
-		if (state->cb) {
-			state->cb(req, resp, data);
-		} else {
-			/* We don't know how to respond to this faultcode, so log it */
-			char *str = xmlnode_to_str(fault, NULL);
-			purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-			                   msn_contact_operation_str(state->action), str);
-			g_free(str);
-		}
-		msn_callback_state_free(state);
-	}
-
-	g_free(faultcode_str);
-}
-
-static gboolean
-msn_contact_request(MsnCallbackState *state)
-{
-	xmlnode *cachekey = xmlnode_get_child(state->body,
-	                                      "Header/ABApplicationHeader/CacheKey");
-	if (cachekey != NULL)
-		xmlnode_free(cachekey);
-	if (state->session->abch_cachekey != NULL) {
-		cachekey = xmlnode_new_child(xmlnode_get_child(state->body, "Header/ABApplicationHeader"), "CacheKey");
-		xmlnode_insert_data(cachekey, state->session->abch_cachekey, -1);
-	}
-	if (state->token == NULL)
-		state->token = xmlnode_get_child(state->body,
-			"Header/ABAuthHeader/TicketToken");
-	/* delete old & replace with new token */
-	xmlnode_free(state->token->child);
-	xmlnode_insert_data(state->token,
-		msn_nexus_get_token_str(state->session->nexus, MSN_AUTH_CONTACTS), -1);
-	msn_soap_message_send(state->session,
-		msn_soap_message_new(state->post_action, xmlnode_copy(state->body)),
-		MSN_CONTACT_SERVER, state->post_url, FALSE,
-		msn_contact_request_cb, state);
-	return FALSE;
-}
-
-/***************************************************************
- * Address Book and Membership List Operations
- ***************************************************************/
-
-/*get MSN member role utility*/
-static MsnListId
-msn_get_memberrole(const char *role)
-{
-	g_return_val_if_fail(role != NULL, 0);
-
-	if (!strcmp(role,"Allow")) {
-		return MSN_LIST_AL;
-	} else if (!strcmp(role,"Block")) {
-		return MSN_LIST_BL;
-	} else if (!strcmp(role,"Reverse")) {
-		return MSN_LIST_RL;
-	} else if (!strcmp(role,"Pending")) {
-		return MSN_LIST_PL;
-	}
-	return 0;
-}
-
-/* Create the AddressBook in the server, if we don't have one */
-static void
-msn_create_address_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
-{
-	MsnCallbackState *state = data;
-	if (resp && xmlnode_get_child(resp->xml, "Body/Fault") == NULL) {
-		purple_debug_info("msn", "Address Book successfully created!\n");
-		msn_get_address_book(state->session, MSN_PS_INITIAL, NULL, NULL);
-	} else {
-		purple_debug_info("msn", "Address Book creation failed!\n");
-	}
-}
-
-static void
-msn_create_address_book(MsnSession *session)
-{
-	gchar *body;
-	MsnCallbackState *state;
-
-	g_return_if_fail(session != NULL);
-	g_return_if_fail(session->user != NULL);
-	g_return_if_fail(session->user->passport != NULL);
-
-	purple_debug_info("msn", "Creating an Address Book.\n");
-
-	body = g_strdup_printf(MSN_ADD_ADDRESSBOOK_TEMPLATE,
-	                       session->user->passport);
-
-	state = msn_callback_state_new(session);
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_ADD_ADDRESSBOOK_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_create_address_cb;
-	msn_contact_request(state);
-
-	g_free(body);
-}
-
-static void
-msn_parse_each_member(MsnSession *session, xmlnode *member, const char *node,
-	MsnListId list)
-{
-	char *passport;
-	char *type;
-	char *member_id;
-	MsnUser *user;
-	xmlnode *annotation;
-	guint nid = MSN_NETWORK_UNKNOWN;
-	char *invite = NULL;
-
-	passport = xmlnode_get_data(xmlnode_get_child(member, node));
-	if (!msn_email_is_valid(passport)) {
-		g_free(passport);
-		return;
-	}
-
-	type = xmlnode_get_data(xmlnode_get_child(member, "Type"));
-	member_id = xmlnode_get_data(xmlnode_get_child(member, "MembershipId"));
-
-	user = msn_userlist_find_add_user(session->userlist, passport, NULL);
-
-	for (annotation = xmlnode_get_child(member, "Annotations/Annotation");
-	     annotation;
-	     annotation = xmlnode_get_next_twin(annotation)) {
-		char *name = xmlnode_get_data(xmlnode_get_child(annotation, "Name"));
-		char *value = xmlnode_get_data(xmlnode_get_child(annotation, "Value"));
-		if (name && value) {
-			if (!strcmp(name, "MSN.IM.BuddyType")) {
-				nid = strtoul(value, NULL, 10);
-			}
-			else if (!strcmp(name, "MSN.IM.InviteMessage")) {
-				invite = value;
-				value = NULL;
-			}
-		}
-		g_free(name);
-		g_free(value);
-	}
-
-	/* For EmailMembers, the network must be found in the annotations, above.
-	   Otherwise, PassportMembers are on the Passport network. */
-	if (!strcmp(node, "PassportName"))
-		nid = MSN_NETWORK_PASSPORT;
-
-	purple_debug_info("msn", "CL: %s name: %s, Type: %s, MembershipID: %s, NetworkID: %u\n",
-		node, passport, type, member_id == NULL ? "(null)" : member_id, nid);
-
-	msn_user_set_network(user, nid);
-	msn_user_set_invite_message(user, invite);
-
-	if (list == MSN_LIST_PL && member_id) {
-		user->member_id_on_pending_list = atoi(member_id);
-	}
-
-	msn_got_lst_user(session, user, 1 << list, NULL);
-
-	g_free(passport);
-	g_free(type);
-	g_free(member_id);
-	g_free(invite);
-}
-
-static void
-msn_parse_each_service(MsnSession *session, xmlnode *service)
-{
-	xmlnode *type;
-
-	if ((type = xmlnode_get_child(service, "Info/Handle/Type"))) {
-		char *type_str = xmlnode_get_data(type);
-
-		if (g_str_equal(type_str, "Profile")) {
-			/* Process Windows Live 'Messenger Roaming Identity' */
-		} else if (g_str_equal(type_str, "Messenger")) {
-			xmlnode *lastchange = xmlnode_get_child(service, "LastChange");
-			char *lastchange_str = xmlnode_get_data(lastchange);
-			xmlnode *membership;
-
-			purple_debug_info("msn", "CL last change: %s\n", lastchange_str);
-			purple_account_set_string(session->account,	"CLLastChange",
-				lastchange_str);
-
-			for (membership = xmlnode_get_child(service,
-					"Memberships/Membership");
-				 membership; membership = xmlnode_get_next_twin(membership)) {
-
-				xmlnode *role = xmlnode_get_child(membership, "MemberRole");
-				char *role_str = xmlnode_get_data(role);
-				MsnListId list = msn_get_memberrole(role_str);
-				xmlnode *member;
-
-				purple_debug_info("msn", "CL MemberRole role: %s, list: %d\n",
-					role_str, list);
-
-				for (member = xmlnode_get_child(membership, "Members/Member");
-					 member; member = xmlnode_get_next_twin(member)) {
-					const char *member_type = xmlnode_get_attrib(member, "type");
-					if (g_str_equal(member_type, "PassportMember")) {
-						msn_parse_each_member(session, member, "PassportName",
-							list);
-					} else if (g_str_equal(member_type, "PhoneMember")) {
-
-					} else if (g_str_equal(member_type, "EmailMember")) {
-						msn_parse_each_member(session, member, "Email",	list);
-					}
-				}
-
-				g_free(role_str);
-			}
-
-			g_free(lastchange_str);
-		}
-
-		g_free(type_str);
-	}
-}
-
-/*parse contact list*/
-static gboolean
-msn_parse_contact_list(MsnSession *session, xmlnode *node)
-{
-	xmlnode *fault, *faultnode;
-
-	/* we may get a response if our cache data is too old:
-	 *
-	 * <faultstring>Need to do full sync. Can't sync deltas Client
-	 * has too old a copy for us to do a delta sync</faultstring>
-	 *
-	 * this is not handled yet
-	 */
-	if ((fault = xmlnode_get_child(node, "Body/Fault"))) {
-		if ((faultnode = xmlnode_get_child(fault, "detail/errorcode"))) {
-			char *errorcode = xmlnode_get_data(faultnode);
-
-			if (g_str_equal(errorcode, "ABDoesNotExist")) {
-				msn_create_address_book(session);
-				g_free(errorcode);
-				return FALSE;
-			}
-
-			g_free(errorcode);
-		}
-
-		if ((faultnode = xmlnode_get_child(fault, "faultstring"))) {
-			char *faultstring = xmlnode_get_data(faultnode);
-			purple_debug_info("msn", "Retrieving contact list failed: %s\n",
-				faultstring);
-			msn_session_set_error(session, MSN_ERROR_BAD_BLIST, faultstring);
-			g_free(faultstring);
-		} else {
-			msn_session_set_error(session, MSN_ERROR_BAD_BLIST, NULL);
-		}
-		return FALSE;
-	} else {
-		xmlnode *service;
-
-		for (service = xmlnode_get_child(node, "Body/FindMembershipResponse/"
-				"FindMembershipResult/Services/Service");
-			 service; service = xmlnode_get_next_twin(service)) {
-			msn_parse_each_service(session, service);
-		}
-		return TRUE;
-	}
-}
-
-static void
-msn_get_contact_list_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = data;
-	MsnSession *session = state->session;
-
-	g_return_if_fail(session != NULL);
-
-	if (resp != NULL) {
-#ifdef MSN_PARTIAL_LISTS
-		const char *abLastChange;
-		const char *dynamicItemLastChange;
-#endif
-
-		purple_debug_misc("msn", "Got the contact list!\n");
-
-		if (msn_parse_contact_list(session, resp->xml)) {
-#ifdef MSN_PARTIAL_LISTS
-			abLastChange = purple_account_get_string(session->account,
-				"ablastChange", NULL);
-			dynamicItemLastChange = purple_account_get_string(session->account,
-				"DynamicItemLastChanged", NULL);
-#endif
-
-			if (state->partner_scenario == MSN_PS_INITIAL) {
-#ifdef MSN_PARTIAL_LISTS
-				/* XXX: this should be enabled when we can correctly do partial
-				   syncs with the server. Currently we need to retrieve the whole
-				   list to detect sync issues */
-				msn_get_address_book(session, MSN_PS_INITIAL, abLastChange, dynamicItemLastChange);
-#else
-				msn_get_address_book(session, MSN_PS_INITIAL, NULL, NULL);
-#endif
-			}
-		}
-	}
-}
-
-/*SOAP  get contact list*/
-void
-msn_get_contact_list(MsnSession *session,
-	const MsnSoapPartnerScenario partner_scenario, const char *update_time)
-{
-	gchar *body = NULL;
-	gchar *update_str = NULL;
-	MsnCallbackState *state;
-	const gchar *partner_scenario_str = MsnSoapPartnerScenarioText[partner_scenario];
-
-	purple_debug_misc("msn", "Getting Contact List.\n");
-
-	if (update_time != NULL) {
-		purple_debug_info("msn", "CL Last update time: %s\n", update_time);
-		update_str = g_strdup_printf(MSN_GET_CONTACT_UPDATE_XML, update_time);
-	}
-
-	body = g_strdup_printf(MSN_GET_CONTACT_TEMPLATE, partner_scenario_str,
-	                       update_str ? update_str : "");
-
-	state = msn_callback_state_new(session);
-	state->partner_scenario = partner_scenario;
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_GET_CONTACT_SOAP_ACTION;
-	state->post_url = MSN_GET_CONTACT_POST_URL;
-	state->cb = msn_get_contact_list_cb;
-	msn_contact_request(state);
-
-	g_free(update_str);
-	g_free(body);
-}
-
-static void
-msn_parse_addressbook_groups(MsnSession *session, xmlnode *node)
-{
-	xmlnode *group;
-
-	purple_debug_info("msn", "msn_parse_addressbook_groups()\n");
-
-	for(group = xmlnode_get_child(node, "Group"); group;
-					group = xmlnode_get_next_twin(group)){
-		xmlnode *groupId, *groupInfo, *groupname;
-		char *group_id = NULL, *group_name = NULL;
-
-		if ((groupId = xmlnode_get_child(group, "groupId")))
-			group_id = xmlnode_get_data(groupId);
-		if ((groupInfo = xmlnode_get_child(group, "groupInfo")) && (groupname = xmlnode_get_child(groupInfo, "name")))
-			group_name = xmlnode_get_data(groupname);
-
-		if (group_id == NULL) {
-			/* Group of ungroupped buddies */
-			g_free(group_name);
-			continue;
-		}
-
-		msn_group_new(session->userlist, group_id, group_name);
-
-		purple_debug_info("msn", "AB group_id: %s, name: %s\n", group_id, group_name ? group_name : "(null)");
-		if ((purple_find_group(group_name)) == NULL) {
-			PurpleGroup *g = purple_group_new(group_name);
-			purple_blist_add_group(g, NULL);
-		}
-		g_free(group_id);
-		g_free(group_name);
-	}
-}
-
-static gboolean
-msn_parse_addressbook_mobile(xmlnode *contactInfo, char **inout_mobile_number)
-{
-	xmlnode *phones;
-	char *mobile_number = NULL;
-	gboolean mobile = FALSE;
-
-	*inout_mobile_number = NULL;
-
-	if ((phones = xmlnode_get_child(contactInfo, "phones"))) {
-		xmlnode *contact_phone;
-		char *phone_type = NULL;
-
-		for (contact_phone = xmlnode_get_child(phones, "ContactPhone");
-			 contact_phone;
-			 contact_phone = xmlnode_get_next_twin(contact_phone)) {
-			xmlnode *contact_phone_type;
-
-			if (!(contact_phone_type =
-					xmlnode_get_child(contact_phone, "contactPhoneType")))
-				continue;
-
-			phone_type = xmlnode_get_data(contact_phone_type);
-
-			if (phone_type && !strcmp(phone_type, "ContactPhoneMobile")) {
-				xmlnode *number;
-
-				if ((number = xmlnode_get_child(contact_phone, "number"))) {
-					xmlnode *messenger_enabled;
-					char *is_messenger_enabled = NULL;
-
-					g_free(mobile_number);
-					mobile_number = xmlnode_get_data(number);
-
-					if (mobile_number &&
-							(messenger_enabled = xmlnode_get_child(contact_phone, "isMessengerEnabled"))
-							&& (is_messenger_enabled = xmlnode_get_data(messenger_enabled))
-							&& !strcmp(is_messenger_enabled, "true"))
-						mobile = TRUE;
-
-					g_free(is_messenger_enabled);
-				}
-			}
-
-			g_free(phone_type);
-		}
-	}
-
-	*inout_mobile_number = mobile_number;
-	return mobile;
-}
-
-static void
-msn_parse_addressbook_contacts(MsnSession *session, xmlnode *node)
-{
-	xmlnode *contactNode;
-	char *passport = NULL, *Name = NULL, *uid = NULL, *type = NULL, *mobile_number = NULL, *alias = NULL;
-	gboolean mobile = FALSE;
-	PurpleConnection *pc = purple_account_get_connection(session->account);
-
-	for(contactNode = xmlnode_get_child(node, "Contact"); contactNode;
-				contactNode = xmlnode_get_next_twin(contactNode)) {
-		xmlnode *contactId, *contactInfo, *contactType, *passportName, *displayName, *guid, *groupIds;
-		xmlnode *annotation;
-		MsnUser *user;
-
-		g_free(passport);
-		g_free(Name);
-		g_free(uid);
-		g_free(type);
-		g_free(mobile_number);
-		g_free(alias);
-		passport = Name = uid = type = mobile_number = alias = NULL;
-		mobile = FALSE;
-
-		if (!(contactId = xmlnode_get_child(contactNode,"contactId"))
-				|| !(contactInfo = xmlnode_get_child(contactNode, "contactInfo"))
-				|| !(contactType = xmlnode_get_child(contactInfo, "contactType")))
-			continue;
-
-		uid = xmlnode_get_data(contactId);
-		type = xmlnode_get_data(contactType);
-
-		/* Find out our settings */
-		if (type && !strcmp(type, "Me")) {
-			/* setup the Display Name */
-			if (purple_connection_get_display_name(pc) == NULL) {
-				char *friendly = NULL;
-				if ((displayName = xmlnode_get_child(contactInfo, "displayName")))
-					friendly = xmlnode_get_data(displayName);
-				purple_connection_set_display_name(pc,
-					friendly ? purple_url_decode(friendly) : NULL);
-				g_free(friendly);
-			}
-
-			for (annotation = xmlnode_get_child(contactInfo, "annotations/Annotation");
-			     annotation;
-			     annotation = xmlnode_get_next_twin(annotation)) {
-				char *name, *value;
-				name = xmlnode_get_data(xmlnode_get_child(annotation, "Name"));
-				value = xmlnode_get_data(xmlnode_get_child(annotation, "Value"));
-				if (name && g_str_equal(name, "MSN.IM.MPOP")) {
-					if (!value || atoi(value) != 0)
-						session->enable_mpop = TRUE;
-					else
-						session->enable_mpop = FALSE;
-				}
-				g_free(name);
-				g_free(value);
-			}
-
-			continue; /* Not adding own account as buddy to buddylist */
-		}
-
-		passportName = xmlnode_get_child(contactInfo, "passportName");
-		if (passportName == NULL) {
-			xmlnode *emailsNode, *contactEmailNode, *emailNode;
-			xmlnode *messengerEnabledNode;
-			char *msnEnabled;
-
-			/*TODO: add it to the non-instant Messenger group and recognize as email Membership*/
-			/* Yahoo/Federated User? */
-			emailsNode = xmlnode_get_child(contactInfo, "emails");
-			if (emailsNode == NULL) {
-				/*TODO:  need to support the Mobile type*/
-				continue;
-			}
-			for (contactEmailNode = xmlnode_get_child(emailsNode, "ContactEmail");
-			     contactEmailNode;
-			     contactEmailNode = xmlnode_get_next_twin(contactEmailNode)) {
-				if ((messengerEnabledNode = xmlnode_get_child(contactEmailNode, "isMessengerEnabled"))) {
-
-					msnEnabled = xmlnode_get_data(messengerEnabledNode);
-
-					if (msnEnabled && !strcmp(msnEnabled, "true")) {
-						if ((emailNode = xmlnode_get_child(contactEmailNode, "email")))
-							passport = xmlnode_get_data(emailNode);
-
-						/* Messenger enabled, Get the Passport*/
-						purple_debug_info("msn", "AB Yahoo/Federated User %s\n", passport ? passport : "(null)");
-						g_free(msnEnabled);
-						break;
-					}
-
-					g_free(msnEnabled);
-				}
-			}
-		} else {
-			xmlnode *messenger_user;
-			/* ignore non-messenger contacts */
-			if ((messenger_user = xmlnode_get_child(contactInfo, "isMessengerUser"))) {
-				char *is_messenger_user = xmlnode_get_data(messenger_user);
-
-				if (is_messenger_user && !strcmp(is_messenger_user, "false")) {
-					g_free(is_messenger_user);
-					continue;
-				}
-
-				g_free(is_messenger_user);
-			}
-
-			passport = xmlnode_get_data(passportName);
-		}
-
-		/* Couldn't find anything */
-		if (passport == NULL)
-			continue;
-
-		if (!msn_email_is_valid(passport))
-			continue;
-
-		if ((displayName = xmlnode_get_child(contactInfo, "displayName")))
-			Name = xmlnode_get_data(displayName);
-		else
-			Name = g_strdup(passport);
-
-		for (annotation = xmlnode_get_child(contactInfo, "annotations/Annotation");
-		     annotation;
-		     annotation = xmlnode_get_next_twin(annotation)) {
-			char *name;
-			name = xmlnode_get_data(xmlnode_get_child(annotation, "Name"));
-			if (!name)
-				continue;
-			if (!strcmp(name, "AB.NickName"))
-				alias = xmlnode_get_data(xmlnode_get_child(annotation, "Value"));
-			else if (!strcmp(name, "MSN.IM.HasSharedFolder"))
-				; /* Do nothing yet... */
-			else if (!strcmp(name, "AB.Spouse"))
-				; /* Do nothing yet... */
-			else if (!strcmp(name, "MSN.Mobile.ContactId"))
-				; /* Do nothing yet... */
-			else
-				purple_debug_info("msn",
-				                  "Unknown AB contact annotation: %s\n", name);
-			g_free(name);
-		}
-
-		mobile = msn_parse_addressbook_mobile(contactInfo, &mobile_number);
-
-		purple_debug_misc("msn", "AB passport:{%s} uid:{%s} display:{%s} alias: {%s} mobile:{%s} mobile number:{%s}\n",
-			passport, uid ? uid : "(null)", Name ? Name : "(null)", alias ? alias : "(null)",
-			mobile ? "true" : "false", mobile_number ? mobile_number : "(null)");
-
-		user = msn_userlist_find_add_user(session->userlist, passport, Name);
-		msn_user_set_uid(user, uid);
-		msn_user_set_mobile_phone(user, mobile_number);
-
-		groupIds = xmlnode_get_child(contactInfo, "groupIds");
-		if (groupIds) {
-			for (guid = xmlnode_get_child(groupIds, "guid"); guid;
-							guid = xmlnode_get_next_twin(guid)) {
-				char *group_id = xmlnode_get_data(guid);
-				msn_user_add_group_id(user, group_id);
-				purple_debug_misc("msn", "AB guid:%s\n", group_id ? group_id : "(null)");
-				g_free(group_id);
-			}
-		} else {
-			purple_debug_info("msn", "User not in any groups, adding to default group.\n");
-			/*not in any group,Then set default group*/
-			msn_user_add_group_id(user, MSN_INDIVIDUALS_GROUP_ID);
-		}
-
-		msn_got_lst_user(session, user, MSN_LIST_FL_OP, NULL);
-
-		if (mobile && user)
-		{
-			user->mobile = TRUE;
-			purple_prpl_got_user_status(session->account, user->passport, "mobile", NULL);
-			purple_prpl_got_user_status(session->account, user->passport, "available", NULL);
-		}
-		if (alias)
-			purple_serv_got_private_alias(pc, passport, alias);
-	}
-
-	g_free(passport);
-	g_free(Name);
-	g_free(uid);
-	g_free(type);
-	g_free(mobile_number);
-	g_free(alias);
-}
-
-static void
-msn_parse_addressbook_circles(MsnSession *session, xmlnode *node)
-{
-	xmlnode *ticket;
-
-	/* TODO: Parse groups */
-
-	ticket = xmlnode_get_child(node, "CircleTicket");
-	if (ticket) {
-		char *data = xmlnode_get_data(ticket);
-		msn_notification_send_circle_auth(session, data);
-		g_free(data);
-	}
-}
-
-static gboolean
-msn_parse_addressbook(MsnSession *session, xmlnode *node)
-{
-	xmlnode *result;
-	xmlnode *groups;
-	xmlnode *contacts;
-	xmlnode *abNode;
-	xmlnode *circleNode;
-	xmlnode *fault;
-
-	if ((fault = xmlnode_get_child(node, "Body/Fault"))) {
-		xmlnode *faultnode;
-
-		if ((faultnode = xmlnode_get_child(fault, "faultstring"))) {
-			gchar *faultstring = xmlnode_get_data(faultnode);
-			purple_debug_info("msn", "AB Faultstring: %s\n", faultstring);
-			g_free(faultstring);
-		}
-
-		if ((faultnode = xmlnode_get_child(fault, "detail/errorcode"))) {
-			gchar *errorcode = xmlnode_get_data(faultnode);
-
-			purple_debug_info("msn", "AB Error Code: %s\n", errorcode);
-
-			if (g_str_equal(errorcode, "ABDoesNotExist")) {
-				g_free(errorcode);
-				return TRUE;
-			}
-			g_free(errorcode);
-		}
-
-		return FALSE;
-	}
-
-	result = xmlnode_get_child(node, "Body/ABFindContactsPagedResponse/ABFindContactsPagedResult");
-	if (result == NULL) {
-		purple_debug_misc("msn", "Received no address book update\n");
-		return TRUE;
-	}
-
-	/* I don't see this "groups" tag documented on msnpiki, need to find out
-	   if they are really there, and update msnpiki */
-	/*Process Group List*/
-	groups = xmlnode_get_child(result, "Groups");
-	if (groups != NULL) {
-		msn_parse_addressbook_groups(session, groups);
-	}
-
-	/* Add an "Other Contacts" group for buddies who aren't in a group */
-	msn_group_new(session->userlist, MSN_INDIVIDUALS_GROUP_ID,
-				  MSN_INDIVIDUALS_GROUP_NAME);
-	purple_debug_misc("msn", "AB group_id:%s name:%s\n",
-					  MSN_INDIVIDUALS_GROUP_ID, MSN_INDIVIDUALS_GROUP_NAME);
-	if ((purple_find_group(MSN_INDIVIDUALS_GROUP_NAME)) == NULL){
-		PurpleGroup *g = purple_group_new(MSN_INDIVIDUALS_GROUP_NAME);
-		purple_blist_add_group(g, NULL);
-	}
-
-	/* Add a "Non-IM Contacts" group */
-	msn_group_new(session->userlist, MSN_NON_IM_GROUP_ID, MSN_NON_IM_GROUP_NAME);
-	purple_debug_misc("msn", "AB group_id:%s name:%s\n", MSN_NON_IM_GROUP_ID, MSN_NON_IM_GROUP_NAME);
-	if ((purple_find_group(MSN_NON_IM_GROUP_NAME)) == NULL) {
-		PurpleGroup *g = purple_group_new(MSN_NON_IM_GROUP_NAME);
-		purple_blist_add_group(g, NULL);
-	}
-
-	/*Process contact List*/
-	purple_debug_info("msn", "Process contact list...\n");
-	contacts = xmlnode_get_child(result, "Contacts");
-	if (contacts != NULL) {
-		msn_parse_addressbook_contacts(session, contacts);
-	}
-
-	abNode = xmlnode_get_child(result, "Ab");
-	if (abNode != NULL) {
-		xmlnode *node2;
-		char *tmp = NULL;
-
-		if ((node2 = xmlnode_get_child(abNode, "lastChange")))
-			tmp = xmlnode_get_data(node2);
-		purple_debug_info("msn", "AB lastchanged Time:{%s}\n", tmp ? tmp : "(null)");
-		purple_account_set_string(session->account, "ablastChange", tmp);
-
-		g_free(tmp); tmp = NULL;
-		if ((node2 = xmlnode_get_child(abNode, "DynamicItemLastChanged")))
-			tmp = xmlnode_get_data(node2);
-		purple_debug_info("msn", "AB DynamicItemLastChanged :{%s}\n", tmp ? tmp : "(null)");
-		purple_account_set_string(session->account, "DynamicItemLastChanged", tmp);
-		g_free(tmp);
-	}
-
-	circleNode = xmlnode_get_child(result, "CircleResult");
-	if (circleNode != NULL) {
-		msn_parse_addressbook_circles(session, circleNode);
-	}
-
-	return TRUE;
-}
-
-static void
-msn_get_address_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
-{
-	MsnCallbackState *state = data;
-	MsnSession *session = state->session;
-
-	g_return_if_fail(session != NULL);
-
-	purple_debug_misc("msn", "Got the Address Book!\n");
-
-	if (msn_parse_addressbook(session, resp->xml)) {
-		msn_send_privacy(session->account->gc);
-		msn_notification_dump_contact(session);
-	} else {
-		/* This is making us loop infinitely when we fail to parse the
-		  address book, disable for now (we should re-enable when we
-		  send timestamps)
-		*/
-		/*
-		msn_get_address_book(session, NULL, NULL);
-		*/
-		msn_session_set_error(session, MSN_ERROR_BAD_BLIST, NULL);
-	}
-}
-
-/*get the address book*/
-void
-msn_get_address_book(MsnSession *session,
-	MsnSoapPartnerScenario partner_scenario, const char *LastChanged,
-	const char *dynamicItemLastChange)
-{
-	char *body, *update_str = NULL;
-	MsnCallbackState *state;
-
-	purple_debug_misc("msn", "Getting Address Book\n");
-
-	/*build SOAP and POST it*/
-	if (dynamicItemLastChange != NULL)
-		update_str = g_strdup_printf(MSN_GET_ADDRESS_UPDATE_XML, dynamicItemLastChange);
-	else if (LastChanged != NULL)
-		update_str = g_strdup_printf(MSN_GET_ADDRESS_UPDATE_XML, LastChanged);
-
-	body = g_strdup_printf(MSN_GET_ADDRESS_TEMPLATE,
-		MsnSoapPartnerScenarioText[partner_scenario],
-		update_str ? update_str : "");
-
-	state = msn_callback_state_new(session);
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_GET_ADDRESS_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_get_address_cb;
-	msn_contact_request(state);
-
-	g_free(update_str);
-	g_free(body);
-}
-
-/***************************************************************
- * Contact Operations
- ***************************************************************/
-
-static void
-msn_add_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = data;
-	MsnSession *session = state->session;
-
-	MsnUserList *userlist;
-	MsnUser *user;
-	xmlnode *guid;
-
-	xmlnode *fault;
-
-	g_return_if_fail(session != NULL);
-	userlist = session->userlist;
-
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-	if (fault != NULL) {
-		char *errorcode = xmlnode_get_data(xmlnode_get_child(fault, "detail/errorcode"));
-		if (errorcode && !strcmp(errorcode, "EmailDomainIsFederated")) {
-			/* Do something special! */
-			purple_debug_error("msn", "Contact is from a federated domain, but don't know what to do yet!\n");
-
-		} else if (errorcode && !strcmp(errorcode, "InvalidPassportUser")) {
-			PurpleBuddy *buddy = purple_find_buddy(session->account, state->who);
-			char *str = g_strdup_printf(_("Unable to add \"%s\"."), state->who);
-			purple_notify_error(state->session, _("Buddy Add error"), str,
-			                    _("The username specified does not exist."));
-			g_free(str);
-			msn_userlist_rem_buddy(userlist, state->who);
-			if (buddy != NULL)
-				purple_blist_remove_buddy(buddy);
-
-		} else {
-			/* We don't know how to respond to this faultcode, so log it */
-			char *fault_str = xmlnode_to_str(fault, NULL);
-			if (fault_str != NULL) {
-				purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-				                   msn_contact_operation_str(state->action), fault_str);
-				g_free(fault_str);
-			}
-		}
-		return;
-	}
-
-	purple_debug_info("msn", "Contact added successfully\n");
-
-	msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_AL);
-	msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_FL);
-
-	user = msn_userlist_find_add_user(userlist, state->who, state->who);
-	msn_user_add_group_id(user, state->guid);
-
-	guid = xmlnode_get_child(resp->xml,
-		"Body/ABContactAddResponse/ABContactAddResult/guid");
-	if (guid != NULL) {
-		char *uid = xmlnode_get_data(guid);
-		msn_user_set_uid(user, uid);
-		purple_debug_info("msn", "Set %s guid to %s.\n", state->who, uid);
-		g_free(uid);
-	}
-}
-
-/* add a Contact in MSN_INDIVIDUALS_GROUP */
-void
-msn_add_contact(MsnSession *session, MsnCallbackState *state, const char *passport)
-{
-	MsnUser *user;
-	gchar *body = NULL;
-	gchar *contact_xml = NULL;
-
-	purple_debug_info("msn", "Adding contact %s to contact list\n", passport);
-
-	user = msn_userlist_find_user(session->userlist, passport);
-	if (user == NULL) {
-		purple_debug_warning("msn", "Unable to retrieve user %s from the userlist!\n", passport);
-		return; /* guess this never happened! */
-	}
-
-	if (user->networkid != MSN_NETWORK_PASSPORT) {
-		contact_xml = g_strdup_printf(MSN_CONTACT_EMAIL_XML,
-		                              user->networkid == MSN_NETWORK_YAHOO ?
-		                                  "Messenger2" :
-		                                  "Messenger3",
-		                              passport, 0);
-	} else {
-		contact_xml = g_strdup_printf(MSN_CONTACT_XML, passport);
-	}
-	body = g_strdup_printf(MSN_ADD_CONTACT_TEMPLATE, contact_xml);
-
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_CONTACT_ADD_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_add_contact_read_cb;
-	msn_contact_request(state);
-
-	g_free(contact_xml);
-	g_free(body);
-}
-
-static void
-msn_add_contact_to_group_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = data;
-	MsnSession *session = state->session;
-	MsnUserList *userlist;
-	xmlnode *fault;
-
-	g_return_if_fail(session != NULL);
-	userlist = session->userlist;
-
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-	if (fault != NULL) {
-		char *errorcode = xmlnode_get_data(xmlnode_get_child(fault, "detail/errorcode"));
-		if (errorcode && !strcmp(errorcode, "EmailDomainIsFederated")) {
-			/* Do something special! */
-			purple_debug_error("msn", "Contact is from a federated domain, but don't know what to do yet!\n");
-
-		} else if (errorcode && !strcmp(errorcode, "InvalidPassportUser")) {
-			PurpleBuddy *buddy = purple_find_buddy(session->account, state->who);
-			char *str = g_strdup_printf(_("Unable to add \"%s\"."), state->who);
-			purple_notify_error(session, _("Buddy Add error"), str,
-			                    _("The username specified does not exist."));
-			g_free(str);
-			msn_userlist_rem_buddy(userlist, state->who);
-			if (buddy != NULL)
-				purple_blist_remove_buddy(buddy);
-
-		} else {
-			/* We don't know how to respond to this faultcode, so log it */
-			char *fault_str = xmlnode_to_str(fault, NULL);
-			if (fault_str != NULL) {
-				purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-				                   msn_contact_operation_str(state->action), fault_str);
-				g_free(fault_str);
-			}
-		}
-		return;
-	}
-
-	if (msn_userlist_add_buddy_to_group(userlist, state->who,
-			state->new_group_name)) {
-		purple_debug_info("msn", "Contact %s added to group %s successfully!\n", state->who, state->new_group_name);
-	} else {
-		purple_debug_info("msn", "Contact %s added to group %s successfully on server, but failed in the local list\n", state->who, state->new_group_name);
-	}
-
-	if (state->action & MSN_ADD_BUDDY) {
-		MsnUser *user = msn_userlist_find_user(userlist, state->who);
-		xmlnode *guid = xmlnode_get_child(resp->xml,
-			"Body/ABGroupContactAddResponse/ABGroupContactAddResult/guid");
-
-		if (guid != NULL) {
-			char *uid = xmlnode_get_data(guid);
-			msn_user_set_uid(user, uid);
-			purple_debug_info("msn", "Set %s guid to %s.\n", state->who, uid);
-			g_free(uid);
-		}
-
-		msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_AL);
-		msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_FL);
-
-		if (msn_user_is_in_list(user, MSN_LIST_PL)) {
-			msn_del_contact_from_list(state->session, NULL, state->who, MSN_LIST_PL);
-			return;
-		}
-	}
-
-	if (state->action & MSN_MOVE_BUDDY) {
-		msn_del_contact_from_group(state->session, state->who, state->old_group_name);
-	}
-}
-
-void
-msn_add_contact_to_group(MsnSession *session, MsnCallbackState *state,
-			 const char *passport, const char *groupId)
-{
-	MsnUserList *userlist;
-	MsnUser *user;
-	gchar *body = NULL, *contact_xml, *invite;
-
-	g_return_if_fail(passport != NULL);
-	g_return_if_fail(groupId != NULL);
-
-	g_return_if_fail(session != NULL);
-
-	userlist = session->userlist;
-
-	if (!strcmp(groupId, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(groupId, MSN_NON_IM_GROUP_ID)) {
-
-		user = msn_userlist_find_add_user(userlist, passport, passport);
-
-		if (state->action & MSN_ADD_BUDDY) {
-			msn_add_contact(session, state, passport);
-			return;
-		}
-
-		if (state->action & MSN_MOVE_BUDDY) {
-			msn_user_add_group_id(user, groupId);
-			msn_del_contact_from_group(session, passport, state->old_group_name);
-		}
-
-		return;
-	}
-
-	purple_debug_info("msn", "Adding user %s to group %s\n", passport,
-			  msn_userlist_find_group_name(userlist, groupId));
-
-	user = msn_userlist_find_user(userlist, passport);
-	if (user == NULL) {
-		purple_debug_warning("msn", "Unable to retrieve user %s from the userlist!\n", passport);
-		msn_callback_state_free(state);
-		return; /* guess this never happened! */
-	}
-
-	if (user->uid != NULL) {
-		contact_xml = g_strdup_printf(MSN_CONTACT_ID_XML, user->uid);
-	} else if (user->networkid != MSN_NETWORK_PASSPORT) {
-		contact_xml = g_strdup_printf(MSN_CONTACT_EMAIL_XML,
-		                              user->networkid == MSN_NETWORK_YAHOO ?
-		                                  "Messenger2" :
-		                                  "Messenger3",
-		                              passport, 0);
-	} else {
-		contact_xml = g_strdup_printf(MSN_CONTACT_XML, passport);
-	}
-
-	if (user->invite_message) {
-		char *tmp;
-		body = g_markup_escape_text(user->invite_message, -1);
-
-		/* Ignore the cast, we treat it as const anyway. */
-		tmp = (char *)purple_connection_get_display_name(session->account->gc);
-		tmp = tmp ? g_markup_escape_text(tmp, -1) : g_strdup("");
-
-		invite = g_strdup_printf(MSN_CONTACT_INVITE_MESSAGE_XML, body, tmp);
-
-		g_free(body);
-		g_free(tmp);
-
-		/* We can free this now */
-		g_free(user->invite_message);
-		user->invite_message = NULL;
-
-	} else {
-		invite = g_strdup("");
-	}
-
-	body = g_strdup_printf(MSN_ADD_CONTACT_GROUP_TEMPLATE, groupId, contact_xml, invite);
-
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_ADD_CONTACT_GROUP_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_add_contact_to_group_read_cb;
-	msn_contact_request(state);
-
-	g_free(invite);
-	g_free(contact_xml);
-	g_free(body);
-}
-
-static void
-msn_delete_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = data;
-	MsnUserList *userlist = state->session->userlist;
-	MsnUser *user = msn_userlist_find_user_with_id(userlist, state->uid);
-	xmlnode *fault;
-
-	/* We don't know how to respond to this faultcode, so log it */
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-	if (fault != NULL) {
-		char *fault_str = xmlnode_to_str(fault, NULL);
-		purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-		                   msn_contact_operation_str(state->action), fault_str);
-		g_free(fault_str);
-		return;
-	}
-
-	purple_debug_info("msn", "Delete contact successful\n");
-
-	if (user != NULL) {
-		msn_userlist_remove_user(userlist, user);
-	}
-}
-
-/*delete a Contact*/
-void
-msn_delete_contact(MsnSession *session, MsnUser *user)
-{
-	gchar *body = NULL;
-	gchar *contact_id_xml = NULL ;
-	MsnCallbackState *state;
-
-	if (user->uid != NULL) {
-		contact_id_xml = g_strdup_printf(MSN_CONTACT_ID_XML, user->uid);
-		purple_debug_info("msn", "Deleting contact with contactId: %s\n", user->uid);
-	} else {
-		purple_debug_info("msn", "Unable to delete contact %s without a ContactId\n", user->passport);
-		return;
-	}
-
-	state = msn_callback_state_new(session);
-	msn_callback_state_set_uid(state, user->uid);
-
-	/* build SOAP request */
-	body = g_strdup_printf(MSN_DEL_CONTACT_TEMPLATE, contact_id_xml);
-
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_CONTACT_DEL_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_delete_contact_read_cb;
-	msn_contact_request(state);
-
-	g_free(contact_id_xml);
-	g_free(body);
-}
-
-static void
-msn_del_contact_from_group_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = data;
-	xmlnode *fault;
-
-	/* We don't know how to respond to this faultcode, so log it */
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-	if (fault != NULL) {
-		char *fault_str = xmlnode_to_str(fault, NULL);
-		purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-		                   msn_contact_operation_str(state->action), fault_str);
-		g_free(fault_str);
-		return;
-	}
-
-	if (msn_userlist_rem_buddy_from_group(state->session->userlist,
-			state->who, state->old_group_name)) {
-		purple_debug_info("msn", "Contact %s deleted successfully from group %s\n", state->who, state->old_group_name);
-	} else {
-		purple_debug_info("msn", "Contact %s deleted successfully from group %s in the server, but failed in the local list\n", state->who, state->old_group_name);
-	}
-}
-
-void
-msn_del_contact_from_group(MsnSession *session, const char *passport, const char *group_name)
-{
-	MsnUserList * userlist;
-	MsnUser *user;
-	MsnCallbackState *state;
-	gchar *body, *contact_id_xml;
-	const gchar *groupId;
-
-	g_return_if_fail(passport != NULL);
-	g_return_if_fail(group_name != NULL);
-	g_return_if_fail(session != NULL);
-
-	userlist = session->userlist;
-
-	groupId = msn_userlist_find_group_id(userlist, group_name);
-	if (groupId != NULL) {
-		purple_debug_info("msn", "Deleting user %s from group %s\n", passport, group_name);
-	} else {
-		purple_debug_warning("msn", "Unable to retrieve group id from group %s !\n", group_name);
-		return;
-	}
-
-	user = msn_userlist_find_user(userlist, passport);
-
-	if (user == NULL) {
-		purple_debug_warning("msn", "Unable to retrieve user from passport %s!\n", passport);
-		return;
-	}
-
-	if ( !strcmp(groupId, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(groupId, MSN_NON_IM_GROUP_ID)) {
-		msn_user_remove_group_id(user, groupId);
-		return;
-	}
-
-	state = msn_callback_state_new(session);
-	msn_callback_state_set_who(state, passport);
-	msn_callback_state_set_guid(state, groupId);
-	msn_callback_state_set_old_group_name(state, group_name);
-
-	if (user->uid != NULL)
-		contact_id_xml = g_strdup_printf(MSN_CONTACT_ID_XML, user->uid);
-	else
-		contact_id_xml = g_strdup_printf(MSN_CONTACT_XML, passport);
-	body = g_strdup_printf(MSN_CONTACT_DEL_GROUP_TEMPLATE, contact_id_xml, groupId);
-
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_CONTACT_DEL_GROUP_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_del_contact_from_group_read_cb;
-	msn_contact_request(state);
-
-	g_free(contact_id_xml);
-	g_free(body);
-}
-
-
-static void
-msn_update_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = (MsnCallbackState *)data;
-	xmlnode *fault;
-
-	/* We don't know how to respond to this faultcode, so log it */
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-	if (fault != NULL) {
-		char *fault_str = xmlnode_to_str(fault, NULL);
-		purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-		                   msn_contact_operation_str(state->action), fault_str);
-		g_free(fault_str);
-		return;
-	}
-
-	purple_debug_info("msn", "Contact updated successfully\n");
-}
-
-/* Update a contact's info */
-void
-msn_update_contact(MsnSession *session, const char *passport, MsnContactUpdateType type, const char* value)
-{
-	MsnCallbackState *state;
-	xmlnode *contact;
-	xmlnode *contact_info;
-	xmlnode *changes;
-	MsnUser *user = NULL;
-
-	purple_debug_info("msn", "Update contact information for %s with new %s: %s\n",
-		passport ? passport : "(null)",
-		type == MSN_UPDATE_DISPLAY ? "display name" : "alias",
-		value ? value : "(null)");
-	g_return_if_fail(passport != NULL);
-
-	if (strcmp(passport, "Me") != 0) {
-		user = msn_userlist_find_user(session->userlist, passport);
-		if (!user)
-			return;
-	}
-
-	contact_info = xmlnode_new("contactInfo");
-	changes = xmlnode_new("propertiesChanged");
-
-	switch (type) {
-		xmlnode *annotations;
-		xmlnode *display;
-		xmlnode *a, *n, *v;
-		case MSN_UPDATE_DISPLAY:
-			display = xmlnode_new_child(contact_info, "displayName");
-			xmlnode_insert_data(display, value, -1);
-			xmlnode_insert_data(changes, "DisplayName", -1);
-			break;
-
-		case MSN_UPDATE_ALIAS:
-			annotations = xmlnode_new_child(contact_info, "annotations");
-			xmlnode_insert_data(changes, "Annotation ", -1);
-
-			a = xmlnode_new_child(annotations, "Annotation");
-			n = xmlnode_new_child(a, "Name");
-			xmlnode_insert_data(n, "AB.NickName", -1);
-			v = xmlnode_new_child(a, "Value");
-			xmlnode_insert_data(v, value, -1);
-			break;
-
-		default:
-			g_return_if_reached();
-	}
-
-	state = msn_callback_state_new(session);
-
-	state->body = xmlnode_from_str(MSN_CONTACT_UPDATE_TEMPLATE, -1);
-	state->action = MSN_UPDATE_INFO;
-	state->post_action = MSN_CONTACT_UPDATE_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_update_contact_read_cb;
-
-	contact = xmlnode_get_child(state->body, "Body/ABContactUpdate/contacts/Contact");
-	xmlnode_insert_child(contact, contact_info);
-	xmlnode_insert_child(contact, changes);
-
-	xmlnode_insert_data(xmlnode_get_child(state->body,
-	                                      "Header/ABApplicationHeader/PartnerScenario"),
-	                    MsnSoapPartnerScenarioText[MSN_PS_SAVE_CONTACT], -1);
-
-	if (user) {
-		xmlnode *contactId = xmlnode_new_child(contact, "contactId");
-		msn_callback_state_set_uid(state, user->uid);
-		xmlnode_insert_data(contactId, state->uid, -1);
-	} else {
-		xmlnode *contactType = xmlnode_new_child(contact_info, "contactType");
-		xmlnode_insert_data(contactType, "Me", -1);
-	}
-
-	msn_contact_request(state);
-}
-
-static void
-msn_annotate_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = (MsnCallbackState *)data;
-	xmlnode *fault;
-
-	/* We don't know how to respond to this faultcode, so log it */
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-	if (fault != NULL) {
-		char *fault_str = xmlnode_to_str(fault, NULL);
-		purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-		                   msn_contact_operation_str(state->action), fault_str);
-		g_free(fault_str);
-		return;
-	}
-
-	purple_debug_info("msn", "Contact annotated successfully\n");
-}
-
-/* Update a contact's annotations */
-void
-msn_annotate_contact(MsnSession *session, const char *passport, ...)
-{
-	va_list params;
-	MsnCallbackState *state;
-	xmlnode *contact;
-	xmlnode *contact_info;
-	xmlnode *annotations;
-	MsnUser *user = NULL;
-
-	g_return_if_fail(passport != NULL);
-
-	if (strcmp(passport, "Me") != 0) {
-		user = msn_userlist_find_user(session->userlist, passport);
-		if (!user)
-			return;
-	}
-
-	contact_info = xmlnode_new("contactInfo");
-	annotations = xmlnode_new_child(contact_info, "annotations");
-
-	va_start(params, passport);
-	while (TRUE) {
-		const char *name;
-		const char *value;
-		xmlnode *a, *n, *v;
-
-		name = va_arg(params, const char *);
-		if (!name)
-			break;
-
-		value = va_arg(params, const char *);
-		if (!value)
-			break;
-
-		a = xmlnode_new_child(annotations, "Annotation");
-		n = xmlnode_new_child(a, "Name");
-		xmlnode_insert_data(n, name, -1);
-		v = xmlnode_new_child(a, "Value");
-		xmlnode_insert_data(v, value, -1);
-	}
-	va_end(params);
-
-	state = msn_callback_state_new(session);
-
-	state->body = xmlnode_from_str(MSN_CONTACT_ANNOTATE_TEMPLATE, -1);
-	state->action = MSN_ANNOTATE_USER;
-	state->post_action = MSN_CONTACT_ANNOTATE_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_annotate_contact_read_cb;
-
-	xmlnode_insert_data(xmlnode_get_child(state->body,
-	                                      "Header/ABApplicationHeader/PartnerScenario"),
-	                    MsnSoapPartnerScenarioText[MSN_PS_SAVE_CONTACT], -1);
-
-	contact = xmlnode_get_child(state->body, "Body/ABContactUpdate/contacts/Contact");
-	xmlnode_insert_child(contact, contact_info);
-
-	if (user) {
-		xmlnode *contactId = xmlnode_new_child(contact, "contactId");
-		msn_callback_state_set_uid(state, user->uid);
-		xmlnode_insert_data(contactId, state->uid, -1);
-	} else {
-		xmlnode *contactType = xmlnode_new_child(contact_info, "contactType");
-		xmlnode_insert_data(contactType, "Me", -1);
-	}
-
-	msn_contact_request(state);
-}
-
-static void
-msn_del_contact_from_list_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = data;
-	MsnSession *session = state->session;
-	xmlnode *fault;
-
-	/* We don't know how to respond to this faultcode, so log it */
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-	if (fault != NULL) {
-		char *fault_str = xmlnode_to_str(fault, NULL);
-		purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-		                   msn_contact_operation_str(state->action), fault_str);
-		g_free(fault_str);
-		return;
-	}
-
-	purple_debug_info("msn", "Contact %s deleted successfully from %s list on server!\n", state->who, MsnMemberRole[state->list_id]);
-
-	if (state->list_id == MSN_LIST_PL) {
-		MsnUser *user = msn_userlist_find_user(session->userlist, state->who);
-		MsnCallbackState *new_state = msn_callback_state_dup(state);
-
-		if (user != NULL)
-			msn_user_unset_op(user, MSN_LIST_PL_OP);
-
-		msn_add_contact_to_list(session, new_state, state->who, MSN_LIST_RL);
-		return;
-	} else if (state->list_id == MSN_LIST_AL) {
-		purple_privacy_permit_remove(session->account, state->who, TRUE);
-		msn_add_contact_to_list(session, NULL, state->who, MSN_LIST_BL);
-	} else if (state->list_id == MSN_LIST_BL) {
-		purple_privacy_deny_remove(session->account, state->who, TRUE);
-		msn_add_contact_to_list(session, NULL, state->who, MSN_LIST_AL);
-	}
-
-}
-
-void
-msn_del_contact_from_list(MsnSession *session, MsnCallbackState *state,
-			  const gchar *passport, const MsnListId list)
-{
-	gchar *body = NULL, *member = NULL;
-	MsnSoapPartnerScenario partner_scenario;
-	MsnUser *user;
-
-	g_return_if_fail(session != NULL);
-	g_return_if_fail(session->userlist != NULL);
-	g_return_if_fail(passport != NULL);
-	g_return_if_fail(list < 5);
-
-	purple_debug_info("msn", "Deleting contact %s from %s list\n", passport, MsnMemberRole[list]);
-
-	if (state == NULL) {
-		state = msn_callback_state_new(session);
-	}
-	msn_callback_state_set_list_id(state, list);
-	msn_callback_state_set_who(state, passport);
-
-	user = msn_userlist_find_user(session->userlist, passport);
-	g_return_if_fail(user != NULL);
-
-	if (list == MSN_LIST_PL) {
-		partner_scenario = MSN_PS_CONTACT_API;
-		if (user->networkid != MSN_NETWORK_PASSPORT)
-			member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML,
-			                         "EmailMember", "Email",
-			                         user->member_id_on_pending_list);
-		else
-			member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML,
-			                         "PassportMember", "Passport",
-			                         user->member_id_on_pending_list);
-	} else {
-		/* list == MSN_LIST_AL || list == MSN_LIST_BL */
-		partner_scenario = MSN_PS_BLOCK_UNBLOCK;
-		if (user && user->networkid != MSN_NETWORK_PASSPORT)
-			member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
-			                         "EmailMember", "Email",
-			                         "Email", passport, "Email");
-		else
-			member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
-			                         "PassportMember", "Passport",
-			                         "PassportName", passport, "PassportName");
-	}
-
-	body = g_strdup_printf(MSN_CONTACT_DELETE_FROM_LIST_TEMPLATE,
-		MsnSoapPartnerScenarioText[partner_scenario],
-		MsnMemberRole[list], member);
-
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_DELETE_MEMBER_FROM_LIST_SOAP_ACTION;
-	state->post_url = MSN_SHARE_POST_URL;
-	state->cb = msn_del_contact_from_list_read_cb;
-	msn_contact_request(state);
-
-	g_free(member);
-	g_free(body);
-}
-
-static void
-msn_add_contact_to_list_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-	gpointer data)
-{
-	MsnCallbackState *state = data;
-	xmlnode *fault;
-
-	/* We don't know how to respond to this faultcode, so log it */
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-	if (fault != NULL) {
-		char *fault_str = xmlnode_to_str(fault, NULL);
-		purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-		                   msn_contact_operation_str(state->action), fault_str);
-		g_free(fault_str);
-		return;
-	}
-
-	g_return_if_fail(state->session != NULL);
-
-	purple_debug_info("msn", "Contact %s added successfully to %s list on server!\n", state->who, MsnMemberRole[state->list_id]);
-
-	if (state->list_id == MSN_LIST_RL) {
-		MsnUser *user = msn_userlist_find_user(state->session->userlist, state->who);
-
-		if (user != NULL) {
-			msn_user_set_op(user, MSN_LIST_RL_OP);
-		}
-
-		if (state->action & MSN_DENIED_BUDDY) {
-			msn_add_contact_to_list(state->session, NULL, state->who, MSN_LIST_BL);
-		} else if (state->list_id == MSN_LIST_AL) {
-			purple_privacy_permit_add(state->session->account, state->who, TRUE);
-		} else if (state->list_id == MSN_LIST_BL) {
-			purple_privacy_deny_add(state->session->account, state->who, TRUE);
-		}
-	}
-}
-
-void
-msn_add_contact_to_list(MsnSession *session, MsnCallbackState *state,
-			const gchar *passport, const MsnListId list)
-{
-	gchar *body = NULL, *member = NULL;
-	MsnSoapPartnerScenario partner_scenario;
-	MsnUser *user;
-
-	g_return_if_fail(session != NULL);
-	g_return_if_fail(passport != NULL);
-	g_return_if_fail(list < 5);
-
-	purple_debug_info("msn", "Adding contact %s to %s list\n", passport, MsnMemberRole[list]);
-
-	if (state == NULL) {
-		state = msn_callback_state_new(session);
-	}
-	msn_callback_state_set_list_id(state, list);
-	msn_callback_state_set_who(state, passport);
-
-	user = msn_userlist_find_user(session->userlist, passport);
-
-	partner_scenario = (list == MSN_LIST_RL) ? MSN_PS_CONTACT_API : MSN_PS_BLOCK_UNBLOCK;
-	if (user && user->networkid != MSN_NETWORK_PASSPORT)
-		member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
-		                         "EmailMember", "Email",
-		                         "Email", state->who, "Email");
-	else
-		member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
-		                         "PassportMember", "Passport",
-		                         "PassportName", state->who, "PassportName");
-
-	body = g_strdup_printf(MSN_CONTACT_ADD_TO_LIST_TEMPLATE,
-		MsnSoapPartnerScenarioText[partner_scenario],
-		MsnMemberRole[list], member);
-
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_ADD_MEMBER_TO_LIST_SOAP_ACTION;
-	state->post_url = MSN_SHARE_POST_URL;
-	state->cb = msn_add_contact_to_list_read_cb;
-	msn_contact_request(state);
-
-	g_free(member);
-	g_free(body);
-}
-
-#if 0
-static void
-msn_gleams_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
-{
-	purple_debug_info("msn", "Gleams read done\n");
-}
-
-/*get the gleams info*/
-void
-msn_get_gleams(MsnSession *session)
-{
-	MsnSoapReq *soap_request;
-
-	purple_debug_info("msn", "msn get gleams info...\n");
-
-	state = msn_callback_state_new(session);
-	state->body = xmlnode_from_str(MSN_GLEAMS_TEMPLATE, -1);
-	state->post_action = MSN_GET_GLEAMS_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_gleams_read_cb;
-	msn_contact_request(state);
-}
-#endif
-
-
-/***************************************************************
- * Group Operations
- ***************************************************************/
-
-static void
-msn_group_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
-{
-	MsnCallbackState *state = data;
-	MsnSession *session;
-	MsnUserList *userlist;
-	xmlnode *fault;
-
-	/* We don't know how to respond to this faultcode, so log it */
-	fault = xmlnode_get_child(resp->xml, "Body/Fault");
-	if (fault != NULL) {
-		char *fault_str = xmlnode_to_str(fault, NULL);
-		purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-		                   msn_contact_operation_str(state->action), fault_str);
-		g_free(fault_str);
-		return;
-	}
-
-	purple_debug_info("msn", "Group request successful.\n");
-
-	g_return_if_fail(state->session != NULL);
-	g_return_if_fail(state->session->userlist != NULL);
-
-	session = state->session;
-	userlist = session->userlist;
-
-	if (state->action & MSN_RENAME_GROUP) {
-		msn_userlist_rename_group_id(session->userlist,
-					     state->guid,
-					     state->new_group_name);
-	}
-
-	if (state->action & MSN_ADD_GROUP) {
-		/* the response is taken from
-		   http://telepathy.freedesktop.org/wiki/Pymsn/MSNP/ContactListActions
-		   should copy it to msnpiki some day */
-		xmlnode *guid_node = xmlnode_get_child(resp->xml,
-			"Body/ABGroupAddResponse/ABGroupAddResult/guid");
-
-		if (guid_node) {
-			char *guid = xmlnode_get_data(guid_node);
-
-			/* create and add the new group to the userlist */
-			purple_debug_info("msn", "Adding group %s with guid = %s to the userlist\n", state->new_group_name, guid);
-			msn_group_new(session->userlist, guid, state->new_group_name);
-
-			if (state->action & MSN_ADD_BUDDY) {
-				msn_userlist_add_buddy(session->userlist,
-					state->who,
-					state->new_group_name);
-			} else if (state->action & MSN_MOVE_BUDDY) {
-				/* This will be freed when the add contact callback fires */
-				MsnCallbackState *new_state = msn_callback_state_dup(state);
-				msn_add_contact_to_group(session, new_state, state->who, guid);
-				g_free(guid);
-				return;
-			}
-			g_free(guid);
-		} else {
-			purple_debug_info("msn", "Adding group %s failed\n",
-				state->new_group_name);
-		}
-	}
-
-	if (state->action & MSN_DEL_GROUP) {
-		GList *l;
-
-		msn_userlist_remove_group_id(session->userlist, state->guid);
-		for (l = userlist->users; l != NULL; l = l->next) {
-			msn_user_remove_group_id( (MsnUser *)l->data, state->guid);
-		}
-	}
-}
-
-/* add group */
-void
-msn_add_group(MsnSession *session, MsnCallbackState *state, const char* group_name)
-{
-	char *body = NULL;
-	char *escaped_group_name = NULL;
-
-	g_return_if_fail(session != NULL);
-	g_return_if_fail(group_name != NULL);
-
-	purple_debug_info("msn", "Adding group %s to contact list.\n", group_name);
-
-	if (state == NULL) {
-		state = msn_callback_state_new(session);
-	}
-
-	msn_callback_state_set_action(state, MSN_ADD_GROUP);
-	msn_callback_state_set_new_group_name(state, group_name);
-
-	/* escape group name's html special chars so it can safely be sent
-	* in a XML SOAP request
-	*/
-	escaped_group_name = g_markup_escape_text(group_name, -1);
-	body = g_strdup_printf(MSN_GROUP_ADD_TEMPLATE, escaped_group_name);
-
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_GROUP_ADD_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_group_read_cb;
-	msn_contact_request(state);
-
-	g_free(escaped_group_name);
-	g_free(body);
-}
-
-/* delete group */
-void
-msn_del_group(MsnSession *session, const gchar *group_name)
-{
-	MsnCallbackState *state;
-	char *body = NULL;
-	const gchar *guid;
-
-	g_return_if_fail(session != NULL);
-
-	g_return_if_fail(group_name != NULL);
-	purple_debug_info("msn", "Deleting group %s from contact list\n", group_name);
-
-	guid = msn_userlist_find_group_id(session->userlist, group_name);
-
-	/* if group uid we need to del is NULL,
-	*  we need to delete nothing
-	*/
-	if (guid == NULL) {
-		purple_debug_info("msn", "Group %s guid not found, returning.\n", group_name);
-		return;
-	}
-
-	if ( !strcmp(guid, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(guid, MSN_NON_IM_GROUP_ID) ) {
-		/* XXX add back PurpleGroup since it isn't really removed in the server? */
-		return;
-	}
-
-	state = msn_callback_state_new(session);
-	msn_callback_state_set_action(state, MSN_DEL_GROUP);
-	msn_callback_state_set_guid(state, guid);
-
-	body = g_strdup_printf(MSN_GROUP_DEL_TEMPLATE, guid);
-
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_GROUP_DEL_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_group_read_cb;
-	msn_contact_request(state);
-
-	g_free(body);
-}
-
-/* rename group */
-void
-msn_contact_rename_group(MsnSession *session, const char *old_group_name, const char *new_group_name)
-{
-	gchar *body = NULL;
-	const gchar * guid;
-	MsnCallbackState *state;
-	char *escaped_group_name;
-
-	g_return_if_fail(session != NULL);
-	g_return_if_fail(session->userlist != NULL);
-	g_return_if_fail(old_group_name != NULL);
-	g_return_if_fail(new_group_name != NULL);
-
-	purple_debug_info("msn", "Renaming group %s to %s.\n", old_group_name, new_group_name);
-
-	guid = msn_userlist_find_group_id(session->userlist, old_group_name);
-	if (guid == NULL)
-		return;
-
-	state = msn_callback_state_new(session);
-	msn_callback_state_set_guid(state, guid);
-	msn_callback_state_set_new_group_name(state, new_group_name);
-
-	if ( !strcmp(guid, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(guid, MSN_NON_IM_GROUP_ID) ) {
-		MsnCallbackState *new_state = msn_callback_state_dup(state);
-		msn_add_group(session, new_state, new_group_name);
-		/* XXX move every buddy there (we probably need to fix concurrent SOAP reqs first) */
-	}
-
-	msn_callback_state_set_action(state, MSN_RENAME_GROUP);
-
-	escaped_group_name = g_markup_escape_text(new_group_name, -1);
-	body = g_strdup_printf(MSN_GROUP_RENAME_TEMPLATE, guid, escaped_group_name);
-
-	state->body = xmlnode_from_str(body, -1);
-	state->post_action = MSN_GROUP_RENAME_SOAP_ACTION;
-	state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-	state->cb = msn_group_read_cb;
-	msn_contact_request(state);
-
-	g_free(escaped_group_name);
-	g_free(body);
-}
-
--- a/libpurple/protocols/msn/contact.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,747 +0,0 @@
-/**
- * @file contact.h			Header file for contact.c
- *	Author
- * 		MaYuan<mayuan2006@gmail.com>
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA
- */
-#ifndef MSN_CONTACT_H
-#define MSN_CONTACT_H
-
-typedef struct _MsnCallbackState MsnCallbackState;
-
-typedef enum
-{
-	MSN_ADD_BUDDY       = 0x01,
-	MSN_MOVE_BUDDY      = 0x02,
-	MSN_ACCEPTED_BUDDY  = 0x04,
-	MSN_DENIED_BUDDY    = 0x08,
-	MSN_ADD_GROUP       = 0x10,
-	MSN_DEL_GROUP       = 0x20,
-	MSN_RENAME_GROUP    = 0x40,
-	MSN_UPDATE_INFO     = 0x80,
-	MSN_ANNOTATE_USER   = 0x100
-} MsnCallbackAction;
-
-typedef enum
-{
-	MSN_UPDATE_DISPLAY,	/* Real display name */
-	MSN_UPDATE_ALIAS,	/* Aliased display name */
-	MSN_UPDATE_COMMENT
-} MsnContactUpdateType;
-
-typedef enum
-{
-	MSN_PS_INITIAL,
-	MSN_PS_SAVE_CONTACT,
-	MSN_PS_PENDING_LIST,
-	MSN_PS_CONTACT_API,
-	MSN_PS_BLOCK_UNBLOCK,
-	MSN_PS_TIMER
-} MsnSoapPartnerScenario;
-
-#include "session.h"
-#include "soap.h"
-
-/* Thanks to TReKiE on the #pidgin channel for this new ID. */
-#define MSN_APPLICATION_ID "F6D2794D-501F-443A-ADBE-8F1490FF30FD"
-
-#define MSN_CONTACT_SERVER	"local-bay.contacts.msn.com"
-
-/* Get Contact List */
-
-#define MSN_GET_CONTACT_POST_URL	"/abservice/SharingService.asmx"
-#define MSN_GET_CONTACT_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/FindMembership"
-
-#define MSN_GET_CONTACT_UPDATE_XML \
-	"<View>Full</View>"\
-	"<deltasOnly>true</deltasOnly>"\
-	"<lastChange>%s</lastChange>"
-
-#define MSN_GET_CONTACT_TEMPLATE	"<?xml version='1.0' encoding='utf-8'?>"\
-"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
-	"<soap:Header xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId xmlns=\"http://www.msn.com/webservices/AddressBook\">" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration xmlns=\"http://www.msn.com/webservices/AddressBook\">false</IsMigration>"\
-			"<PartnerScenario xmlns=\"http://www.msn.com/webservices/AddressBook\">%s</PartnerScenario>"\
-		 "</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest xmlns=\"http://www.msn.com/webservices/AddressBook\">false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
-		"<FindMembership xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<serviceFilter xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-				"<Types xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-					"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Messenger</ServiceType>"\
-					"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Invitation</ServiceType>"\
-					"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">SocialNetwork</ServiceType>"\
-					"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Space</ServiceType>"\
-					"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Profile</ServiceType>"\
-				"</Types>"\
-			"</serviceFilter>"\
-			"%s"\
-		"</FindMembership>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/************************************************
- * Address Book SOAP
- * *********************************************/
-
-#define MSN_ADDRESS_BOOK_POST_URL	"/abservice/abservice.asmx"
-
-/* Create AddressBook template */
-#define MSN_ADD_ADDRESSBOOK_SOAP_ACTION     "http://www.msn.com/webservices/AddressBook/ABAdd"
-
-#define MSN_ADD_ADDRESSBOOK_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>Initial</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abInfo>"\
-				"<name/>"\
-				"<ownerPuid>0</ownerPuid>"\
-				"<ownerEmail>%s</ownerEmail>"\
-				"<fDefault>true</fDefault>"\
-			"</abInfo>"\
-		"</ABAdd>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/* Get AddressBook */
-#define MSN_GET_ADDRESS_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABFindContactsPaged"
-#define MSN_GET_ADDRESS_FULL_TIME	"0001-01-01T00:00:00.0000000-08:00"
-#define MSN_GET_ADDRESS_UPDATE_XML \
-	"<filterOptions>"\
-		"<deltasOnly>true</deltasOnly>"\
-		"<lastChange>%s</lastChange>"\
-	"</filterOptions>"
-
-#define MSN_GET_GLEAM_UPDATE_XML \
-	"%s"\
-	"<dynamicItemView>Gleam</dynamicItemView>"\
-	"<dynamicItemLastChange>%s</dynamicItemLastChange>"
-
-#define MSN_GET_ADDRESS_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>%s</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABFindContactsPaged xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abView>Full</abView>"\
-			"<extendedContent>AB AllGroups CircleResult</extendedContent>"\
-			"%s"\
-		"</ABFindContactsPaged>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-
-/*Gleams SOAP request template*/
-#define MSN_GET_GLEAMS_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABFindAll"
-#define MSN_GLEAMS_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>Initial</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABFindAll xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<abView>Full</abView>"\
-			"<dynamicItemView>Gleam</dynamicItemView>"\
-			"<dynamicItemLastChange>0001-01-01T00:00:00.0000000-08:00</dynamicItemLastChange>"\
-		"</ABFindAll>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-
-/*******************************************************
- * Contact Management SOAP actions
- *******************************************************/
-
-/* Add a new contact */
-#define MSN_CONTACT_ADD_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABContactAdd"
-#define MSN_CONTACT_LIVE_PENDING_XML \
-	"<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-		"<contactInfo>"\
-			"<contactType>LivePending</contactType>"\
-			"<passportName>%s</passportName>"\
-			"<isMessengerUser>true</isMessengerUser>"\
-		"</contactInfo>"\
-	"</Contact>"
-
-#define MSN_CONTACT_XML	\
-	"<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-		"<contactInfo>"\
-			"<passportName>%s</passportName>"\
-			"<isSmtp>false</isSmtp>"\
-			"<isMessengerUser>true</isMessengerUser>"\
-		"</contactInfo>"\
-	"</Contact>"
-
-#define MSN_CONTACT_DISPLAYNAME_XML	\
-	"<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-		"<contactInfo>"\
-			"<displayName>%s</displayName>"\
-			"<passportName>%s</passportName>"\
-			"<isMessengerUser>true</isMessengerUser>"\
-		"</contactInfo>"\
-	"</Contact>"
-
-#define MSN_CONTACT_ID_XML \
-	"<Contact>"\
-		"<contactId>%s</contactId>"\
-	"</Contact>"
-
-#define MSN_CONTACT_EMAIL_XML \
-	"<Contact>"\
-		"<contactInfo>"\
-			"<emails>"\
-				"<ContactEmail>"\
-					"<contactEmailType>%s</contactEmailType>"\
-					"<email>%s</email>"\
-					"<isMessengerEnabled>true</isMessengerEnabled>"\
-					"<Capability>%d</Capability>"\
-					"<MessengerEnabledExternally>false</MessengerEnabledExternally>"\
-					"<propertiesChanged/>"\
-				"</ContactEmail>"\
-			"</emails>"\
-		"</contactInfo>"\
-	"</Contact>"
-
-#define MSN_CONTACT_INVITE_MESSAGE_XML \
-	"<MessengerMemberInfo>"\
-		"<PendingAnnotations>"\
-			"<Annotation>"\
-				"<Name>MSN.IM.InviteMessage</Name>"\
-				"<Value>%s</Value>"\
-			"</Annotation>"\
-		"</PendingAnnotations>"\
-		"<DisplayName>%s</DisplayName>"\
-	"</MessengerMemberInfo>"
-
-#define MSN_ADD_CONTACT_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>ContactSave</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABContactAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<contacts>%s</contacts>"\
-			"<options>"\
-				"<EnableAllowListManagement>true</EnableAllowListManagement>"\
-			"</options>"\
-		"</ABContactAdd>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/* Add a contact to a group */
-#define MSN_ADD_CONTACT_GROUP_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABGroupContactAdd"
-#define MSN_ADD_CONTACT_GROUP_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>ContactSave</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABGroupContactAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<groupFilter>"\
-				"<groupIds>"\
-					"<guid>%s</guid>"\
-				"</groupIds>"\
-			"</groupFilter>"\
-			"<contacts>%s</contacts>"\
-			"<groupContactAddOptions>"\
-				"<fGenerateMissingQuickName>true</fGenerateMissingQuickName>"\
-				"<EnableAllowListManagement>true</EnableAllowListManagement>"\
-			"</groupContactAddOptions>"\
-			"%s"\
-		"</ABGroupContactAdd>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/* Delete a contact from the Contact List */
-#define MSN_CONTACT_DEL_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABContactDelete"
-#define MSN_DEL_CONTACT_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>Timer</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABContactDelete xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<contacts>%s</contacts>"\
-		"</ABContactDelete>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/* Remove a contact from a group */
-#define MSN_CONTACT_DEL_GROUP_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABGroupContactDelete"
-#define MSN_CONTACT_DEL_GROUP_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>Timer</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABGroupContactDelete xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<contacts>%s</contacts>"\
-			"<groupFilter>"\
-				"<groupIds>"\
-					"<guid>%s</guid>"\
-				"</groupIds>"\
-			"</groupFilter>"\
-		"</ABGroupContactDelete>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-
-/* Update Contact Information */
-#define MSN_CONTACT_UPDATE_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABContactUpdate"
-#define MSN_CONTACT_UPDATE_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario></PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABContactUpdate xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<contacts>"\
-				"<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-					""\
-				"</Contact>"\
-			"</contacts>"\
-		"</ABContactUpdate>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/* Update Contact Annotations */
-#define MSN_CONTACT_ANNOTATE_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABContactUpdate"
-#define MSN_CONTACT_ANNOTATE_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario></PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABContactUpdate xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<contacts>"\
-				"<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-					"<propertiesChanged>Annotation</propertiesChanged>"\
-				"</Contact>"\
-			"</contacts>"\
-		"</ABContactUpdate>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/*******************************************************
- * Add/Delete contact from lists SOAP actions
- *******************************************************/
-
-/* block means delete from allow list and add contact to block list */
-#define MSN_SHARE_POST_URL		"/abservice/SharingService.asmx"
-
-#define MSN_ADD_MEMBER_TO_LIST_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/AddMember"
-#define MSN_DELETE_MEMBER_FROM_LIST_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/DeleteMember"
-
-#define MSN_MEMBER_PASSPORT_XML	\
-	"<Member xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"%s\">"\
-		"<Type>%s</Type>"\
-		"<State>Accepted</State>"\
-		"<%s>%s</%s>"\
-	"</Member>"
-
-#define MSN_MEMBER_MEMBERSHIPID_XML	\
-	"<Member xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"%s\">"\
-		"<Type>%s</Type>"\
-		"<MembershipId>%u</MembershipId>"\
-		"<State>Accepted</State>"\
-	"</Member>"
-
-/* first delete contact from allow list */
-
-#define MSN_CONTACT_DELETE_FROM_LIST_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>%s</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<DeleteMember xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<serviceHandle>"\
-				"<Id>0</Id>"\
-				"<Type>Messenger</Type>"\
-				"<ForeignId></ForeignId>"\
-			"</serviceHandle>"\
-			"<memberships>"\
-				"<Membership>"\
-					"<MemberRole>%s</MemberRole>"\
-					"<Members>"\
-						"%s"\
-					"</Members>"\
-				"</Membership>"\
-			"</memberships>"\
-		"</DeleteMember>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-#define MSN_CONTACT_ADD_TO_LIST_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>%s</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<AddMember xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<serviceHandle>"\
-				"<Id>0</Id>"\
-				"<Type>Messenger</Type>"\
-				"<ForeignId></ForeignId>"\
-			"</serviceHandle>"\
-			"<memberships>"\
-				"<Membership>"\
-					"<MemberRole>%s</MemberRole>"\
-					"<Members>"\
-						"%s"\
-					"</Members>"\
-				"</Membership>"\
-			"</memberships>"\
-		"</AddMember>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-
-
-/*******************************************************
- * Group management SOAP actions
- *******************************************************/
-
-/* add a group */
-#define MSN_GROUP_ADD_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABGroupAdd"
-#define MSN_GROUP_ADD_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>GroupSave</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABGroupAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<groupAddOptions>"\
-				"<fRenameOnMsgrConflict>false</fRenameOnMsgrConflict>"\
-			"</groupAddOptions>"\
-			"<groupInfo>"\
-				"<GroupInfo>"\
-					"<name>%s</name>"\
-					"<groupType>C8529CE2-6EAD-434d-881F-341E17DB3FF8</groupType>"\
-					"<fMessenger>false</fMessenger>"\
-					"<annotations>"\
-						"<Annotation>"\
-							"<Name>MSN.IM.Display</Name>"\
-							"<Value>1</Value>"\
-						"</Annotation>"\
-					"</annotations>"\
-				"</GroupInfo>"\
-			"</groupInfo>"\
-		"</ABGroupAdd>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/* delete a group */
-#define MSN_GROUP_DEL_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABGroupDelete"
-#define MSN_GROUP_DEL_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>Timer</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABGroupDelete xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<groupFilter>"\
-				"<groupIds>"\
-					"<guid>%s</guid>"\
-				"</groupIds>"\
-			"</groupFilter>"\
-		"</ABGroupDelete>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/* change a group's name */
-#define MSN_GROUP_RENAME_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABGroupUpdate"
-#define MSN_GROUP_RENAME_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-	"<soap:Header>"\
-		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-			"<IsMigration>false</IsMigration>"\
-			"<PartnerScenario>Timer</PartnerScenario>"\
-		"</ABApplicationHeader>"\
-		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
-			"<TicketToken>EMPTY</TicketToken>"\
-		"</ABAuthHeader>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<ABGroupUpdate xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
-			"<groups>"\
-				"<Group>"\
-					"<groupId>%s</groupId>"\
-					"<groupInfo>"\
-						"<name>%s</name>"\
-					"</groupInfo>"\
-					"<propertiesChanged>GroupName </propertiesChanged>"\
-				"</Group>"\
-			"</groups>"\
-		"</ABGroupUpdate>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-struct _MsnCallbackState
-{
-	gchar * who;
-	gchar * uid;
-	gchar * old_group_name;
-	gchar * new_group_name;
-	gchar * guid;
-	MsnListId list_id;
-	MsnCallbackAction action;
-	MsnSession *session;
-	xmlnode *body;
-	xmlnode *token;
-	const gchar *post_action;
-	const gchar *post_url;
-	MsnSoapCallback cb;
-	/* For msn_get_contact_list only */
-	MsnSoapPartnerScenario partner_scenario;
-};
-
-/************************************************
- * function prototype
- ************************************************/
-MsnCallbackState * msn_callback_state_new(MsnSession *session);
-MsnCallbackState * msn_callback_state_dup(MsnCallbackState *state);
-void msn_callback_state_free(MsnCallbackState *state);
-void msn_callback_state_set_who(MsnCallbackState *state, const gchar *who);
-void msn_callback_state_set_uid(MsnCallbackState *state, const gchar *uid);
-void msn_callback_state_set_old_group_name(MsnCallbackState *state,
-					   const gchar *old_group_name);
-void msn_callback_state_set_new_group_name(MsnCallbackState *state,
-					   const gchar *new_group_name);
-void msn_callback_state_set_guid(MsnCallbackState *state, const gchar *guid);
-void msn_callback_state_set_list_id(MsnCallbackState *state, MsnListId list_id);
-void msn_callback_state_set_action(MsnCallbackState *state,
-				   MsnCallbackAction action);
-
-void msn_get_contact_list(MsnSession *session,
-			  const MsnSoapPartnerScenario partner_scenario,
-			  const char *update);
-void msn_get_address_book(MsnSession *session,
-			  const MsnSoapPartnerScenario partner_scenario,
-			  const char * update, const char * gupdate);
-
-/* contact SOAP operations */
-void msn_update_contact(MsnSession *session, const char *passport, MsnContactUpdateType type, const char* value);
-
-void msn_annotate_contact(MsnSession *session, const char *passport, ...) G_GNUC_NULL_TERMINATED;
-
-void msn_add_contact(MsnSession *session, MsnCallbackState *state,
-		     const char *passport);
-void msn_delete_contact(MsnSession *session, MsnUser *user);
-
-void msn_add_contact_to_group(MsnSession *session, MsnCallbackState *state,
-			      const char *passport, const char *groupId);
-void msn_del_contact_from_group(MsnSession *session, const char *passport,
-				const char *group_name);
-/* group operations */
-void msn_add_group(MsnSession *session, MsnCallbackState *state,
-					const char* group_name);
-void msn_del_group(MsnSession *session, const gchar *group_name);
-void msn_contact_rename_group(MsnSession *session, const char *old_group_name,
-						   const char *new_group_name);
-
-/* lists operations */
-void msn_add_contact_to_list(MsnSession *session, MsnCallbackState *state,
-			     const gchar *passport, const MsnListId list);
-void msn_del_contact_from_list(MsnSession *session, MsnCallbackState *state,
-			       const gchar *passport, const MsnListId list);
-
-#endif /* MSN_CONTACT_H */
--- a/libpurple/protocols/msn/directconn.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,958 +0,0 @@
-/**
- * @file directconn.c MSN direct connection functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "cipher.h"
-#include "debug.h"
-
-#include "msn.h"
-#include "msnutils.h"
-#include "directconn.h"
-
-#include "slp.h"
-#include "slpmsg.h"
-#include "p2p.h"
-
-#define DC_MAX_BODY_SIZE      8*1024
-#define DC_MAX_PACKET_SIZE    (P2P_PACKET_HEADER_SIZE + DC_MAX_BODY_SIZE)
-
-static void
-msn_dc_calculate_nonce_hash(MsnDirectConnNonceType type,
-                            const guchar *nonce, gsize nonce_len, gchar nonce_hash[37])
-{
-	guchar digest[20];
-
-	if (type == DC_NONCE_SHA1) {
-		PurpleCipher *cipher = purple_ciphers_find_cipher("sha1");
-		PurpleCipherContext *context = purple_cipher_context_new(cipher, NULL);
-		purple_cipher_context_append(context, nonce, nonce_len);
-		purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
-		purple_cipher_context_destroy(context);
-	} else if (type == DC_NONCE_PLAIN) {
-		memcpy(digest, nonce, nonce_len);
-	} else {
-		nonce_hash[0] = '\0';
-		g_return_if_reached();
-	}
-
-	g_sprintf(nonce_hash,
-	          "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
-
-	          digest[3],
-	          digest[2],
-	          digest[1],
-	          digest[0],
-
-	          digest[5],
-	          digest[4],
-
-	          digest[7],
-	          digest[6],
-
-	          digest[8],
-	          digest[9],
-
-	          digest[10],
-	          digest[11],
-	          digest[12],
-	          digest[13],
-	          digest[14],
-	          digest[15]
-	);
-}
-
-static void
-msn_dc_generate_nonce(MsnDirectConn *dc)
-{
-	guint32 *nonce;
-	int i;
-
-	nonce = (guint32 *)&dc->nonce;
-	for (i = 0; i < 4; i++)
-		nonce[i] = rand();
-
-	msn_dc_calculate_nonce_hash(dc->nonce_type, dc->nonce, sizeof(dc->nonce), dc->nonce_hash);
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "DC %p generated nonce %s\n", dc, dc->nonce_hash);
-}
-
-static MsnDirectConnPacket *
-msn_dc_new_packet(guint32 length)
-{
-	MsnDirectConnPacket	*p;
-
-	p = g_new0(MsnDirectConnPacket, 1);
-	p->length = length;
-	p->data = g_malloc(length);
-
-	return p;
-}
-
-static void
-msn_dc_destroy_packet(MsnDirectConnPacket *p)
-{
-	g_free(p->data);
-
-	if (p->part)
-		msn_slpmsgpart_unref(p->part);
-
-	g_free(p);
-}
-
-MsnDirectConn *
-msn_dc_new(MsnSlpCall *slpcall)
-{
-	MsnDirectConn *dc;
-
-	g_return_val_if_fail(slpcall != NULL, NULL);
-
-	dc = g_new0(MsnDirectConn, 1);
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "msn_dc_new %p\n", dc);
-
-	dc->slplink = slpcall->slplink;
-	dc->slpcall = slpcall;
-
-	if (dc->slplink->dc != NULL)
-		purple_debug_warning("msn", "msn_dc_new: slplink already has an allocated DC!\n");
-
-	dc->slplink->dc = dc;
-
-	dc->msg_body = NULL;
-	dc->prev_ack = NULL;
-	dc->listen_data = NULL;
-	dc->connect_data = NULL;
-	dc->listenfd = -1;
-	dc->listenfd_handle = 0;
-	dc->connect_timeout_handle = 0;
-	dc->fd = -1;
-	dc->recv_handle = 0;
-	dc->send_handle = 0;
-	dc->state = DC_STATE_CLOSED;
-	dc->in_buffer = NULL;
-	dc->out_queue = g_queue_new();
-	dc->msg_pos = -1;
-	dc->send_connection_info_msg_cb = NULL;
-	dc->ext_ip = NULL;
-	dc->timeout_handle = 0;
-	dc->progress = FALSE;
-	/*dc->num_calls = 1;*/
-
-	/* TODO: Probably should set this based on buddy caps */
-	dc->nonce_type = DC_NONCE_PLAIN;
-	msn_dc_generate_nonce(dc);
-
-	return dc;
-}
-
-void
-msn_dc_destroy(MsnDirectConn *dc)
-{
-	MsnSlpLink *slplink;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "msn_dc_destroy %p\n", dc);
-
-	g_return_if_fail(dc != NULL);
-
-	if (dc->slpcall != NULL)
-		dc->slpcall->wait_for_socket = FALSE;
-
-	slplink = dc->slplink;
-	if (slplink) {
-		slplink->dc = NULL;
-		if (slplink->swboard == NULL)
-			msn_slplink_unref(slplink);
-	}
-
-	g_free(dc->msg_body);
-
-	if (dc->prev_ack) {
-		msn_slpmsg_destroy(dc->prev_ack);
-	}
-
-	if (dc->listen_data != NULL) {
-		purple_network_listen_cancel(dc->listen_data);
-	}
-
-	if (dc->connect_data != NULL) {
-		purple_proxy_connect_cancel(dc->connect_data);
-	}
-
-	if (dc->listenfd != -1) {
-		purple_network_remove_port_mapping(dc->listenfd);
-		close(dc->listenfd);
-	}
-
-	if (dc->listenfd_handle != 0) {
-		purple_input_remove(dc->listenfd_handle);
-	}
-
-	if (dc->connect_timeout_handle != 0) {
-		purple_timeout_remove(dc->connect_timeout_handle);
-	}
-
-	if (dc->fd != -1) {
-		close(dc->fd);
-	}
-
-	if (dc->send_handle != 0) {
-		purple_input_remove(dc->send_handle);
-	}
-
-	if (dc->recv_handle != 0) {
-		purple_input_remove(dc->recv_handle);
-	}
-
-	g_free(dc->in_buffer);
-
-	if (dc->out_queue != NULL) {
-		while (!g_queue_is_empty(dc->out_queue))
-			msn_dc_destroy_packet( g_queue_pop_head(dc->out_queue) );
-
-		g_queue_free(dc->out_queue);
-	}
-
-	g_free(dc->ext_ip);
-
-	if (dc->timeout_handle != 0) {
-		purple_timeout_remove(dc->timeout_handle);
-	}
-
-	g_free(dc);
-}
-
-/*
-void
-msn_dc_ref(MsnDirectConn *dc)
-{
-	g_return_if_fail(dc != NULL);
-
-	dc->num_calls++;
-}
-
-void
-msn_dc_unref(MsnDirectConn *dc)
-{
-	g_return_if_fail(dc != NULL);
-
-
-	if (dc->num_calls > 0) {
-		dc->num_calls--;
-	}
-}
-*/
-
-void
-msn_dc_send_invite(MsnDirectConn *dc)
-{
-	MsnSlpCall    *slpcall;
-	MsnSlpMessage *msg;
-	gchar *header;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "msn_dc_send_invite %p\n", dc);
-
-	g_return_if_fail(dc != NULL);
-
-	slpcall = dc->slpcall;
-	g_return_if_fail(slpcall != NULL);
-
-	header = g_strdup_printf(
-		"INVITE MSNMSGR:%s MSNSLP/1.0",
-		slpcall->slplink->remote_user
-	);
-
-	msg = msn_slpmsg_sip_new(
-		slpcall,
-		0,
-		header,
-		slpcall->branch,
-		"application/x-msnmsgr-transrespbody",
-		dc->msg_body
-	);
-	msg->info = "DC INVITE";
-	msg->text_body = TRUE;
-	g_free(header);
-	g_free(dc->msg_body);
-	dc->msg_body = NULL;
-
-	msn_slplink_queue_slpmsg(slpcall->slplink, msg);
-}
-
-void
-msn_dc_send_ok(MsnDirectConn *dc)
-{
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "msn_dc_send_ok %p\n", dc);
-
-	g_return_if_fail(dc != NULL);
-
-	msn_slp_send_ok(dc->slpcall, dc->slpcall->branch,
-		"application/x-msnmsgr-transrespbody", dc->msg_body);
-	g_free(dc->msg_body);
-	dc->msg_body = NULL;
-
-	msn_slplink_send_slpmsg(dc->slpcall->slplink, dc->prev_ack);
-	msn_slpmsg_destroy(dc->prev_ack);
-	dc->prev_ack = NULL;
-	msn_slplink_send_queued_slpmsgs(dc->slpcall->slplink);
-}
-
-void
-msn_dc_fallback_to_sb(MsnDirectConn *dc)
-{
-	MsnSlpLink *slplink;
-	MsnSlpCall *slpcall;
-	GQueue *queue = NULL;
-
-	purple_debug_info("msn", "msn_dc_fallback_to_sb %p\n", dc);
-
-	g_return_if_fail(dc != NULL);
-
-	slpcall = dc->slpcall;
-	slplink = msn_slplink_ref(dc->slplink);
-	if (slpcall && !g_queue_is_empty(dc->out_queue)) {
-		queue = dc->out_queue;
-		dc->out_queue = NULL;
-	}
-
-	msn_dc_destroy(dc);
-
-	if (slpcall) {
-		msn_slpcall_session_init(slpcall);
-		if (queue) {
-			while (!g_queue_is_empty(queue)) {
-				MsnDirectConnPacket *p = g_queue_pop_head(queue);
-				msn_slplink_send_msgpart(slplink, (MsnSlpMessage*)p->part->ack_data);
-				msn_dc_destroy_packet(p);
-			}
-			g_queue_free(queue);
-		}
-	}
-	msn_slplink_unref(slplink);
-}
-
-static void
-msn_dc_send_cb(gpointer data, gint fd, PurpleInputCondition cond)
-{
-	MsnDirectConn *dc = data;
-	MsnDirectConnPacket *p;
-	int bytes_to_send;
-	int bytes_sent;
-
-	g_return_if_fail(dc != NULL);
-	g_return_if_fail(fd != -1);
-
-	if (g_queue_is_empty(dc->out_queue)) {
-		if (dc->send_handle != 0) {
-			purple_input_remove(dc->send_handle);
-			dc->send_handle = 0;
-		}
-		return;
-	}
-
-	p = g_queue_peek_head(dc->out_queue);
-
-	if (dc->msg_pos < 0) {
-		/* First we send the length of the packet */
-		guint32 len = GUINT32_TO_LE(p->length);
-		bytes_sent = send(fd, &len, 4, 0);
-		if (bytes_sent < 0) {
-			if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-				return;
-
-			purple_debug_warning("msn", "msn_dc_send_cb: send error\n");
-			msn_dc_destroy(dc);
-			return;
-		}
-		dc->msg_pos = 0;
-	}
-
-	bytes_to_send = p->length - dc->msg_pos;
-	bytes_sent = send(fd, p->data + dc->msg_pos, bytes_to_send, 0);
-	if (bytes_sent < 0) {
-		if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-			return;
-
-		purple_debug_warning("msn", "msn_dc_send_cb: send error\n");
-		msn_dc_destroy(dc);
-		return;
-	}
-
-	dc->progress = TRUE;
-
-	dc->msg_pos += bytes_sent;
-	if ((guint32)dc->msg_pos == p->length) {
-		if (p->sent_cb != NULL)
-			p->sent_cb(p);
-
-		g_queue_pop_head(dc->out_queue);
-		msn_dc_destroy_packet(p);
-
-		dc->msg_pos = -1;
-	}
-}
-
-static void
-msn_dc_enqueue_packet(MsnDirectConn *dc, MsnDirectConnPacket *p)
-{
-	gboolean was_empty;
-
-	was_empty = g_queue_is_empty(dc->out_queue);
-	g_queue_push_tail(dc->out_queue, p);
-
-	if (was_empty && dc->send_handle == 0) {
-		dc->send_handle = purple_input_add(dc->fd, PURPLE_INPUT_WRITE, msn_dc_send_cb, dc);
-		msn_dc_send_cb(dc, dc->fd, PURPLE_INPUT_WRITE);
-	}
-}
-
-static void
-msn_dc_send_foo(MsnDirectConn *dc)
-{
-	MsnDirectConnPacket	*p;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "msn_dc_send_foo %p\n", dc);
-
-	p = msn_dc_new_packet(4);
-
-	memcpy(p->data, "foo\0", 4);
-
-	msn_dc_enqueue_packet(dc, p);
-}
-
-#if 0 /* We don't actually need this */
-typedef struct {
-	guint32 null;
-	guint32 id;
-	guint32 null[5];
-	guint32 flags;
-	guint8  nonce[16];
-} MsnDirectConnNoncePacket;
-#endif
-#define DC_NONCE_PACKET_SIZE (8 * 4 + 16)
-#define DC_NONCE_PACKET_NONCE (8 * 4)
-
-static void
-msn_dc_send_handshake(MsnDirectConn *dc)
-{
-	MsnDirectConnPacket *p;
-	gchar *h;
-
-	p = msn_dc_new_packet(DC_NONCE_PACKET_SIZE);
-	h = (gchar *)p->data;
-
-	msn_push32le(h, 0); /* NUL */
-
-	msn_push32le(h, dc->slpcall->slplink->slp_seq_id++);
-
-	/* More NUL stuff */
-	msn_push64le(h, 0);
-	msn_push64le(h, 0);
-	msn_push32le(h, 0);
-
-	/* Flags */
-	msn_push32le(h, P2P_DC_HANDSHAKE);
-
-	/* The real Nonce, yay! */
-	memcpy(h, dc->nonce, 16);
-
-	msn_dc_enqueue_packet(dc, p);
-}
-
-static gboolean
-msn_dc_verify_handshake(MsnDirectConn *dc, guint32 packet_length)
-{
-	guchar nonce[16];
-	gchar  nonce_hash[37];
-
-	if (packet_length != DC_NONCE_PACKET_SIZE)
-		return FALSE;
-
-	memcpy(nonce, dc->in_buffer + 4 + DC_NONCE_PACKET_NONCE, sizeof(nonce));
-
-	if (dc->nonce_type == DC_NONCE_PLAIN) {
-		if (memcmp(dc->nonce, nonce, sizeof(nonce)) == 0) {
-			purple_debug_info("msn",
-					"Nonce from buddy request and nonce from DC attempt match, "
-					"allowing direct connection\n");
-			return TRUE;
-		} else {
-			purple_debug_warning("msn",
-					"Nonce from buddy request and nonce from DC attempt "
-					"don't match, ignoring direct connection\n");
-			return FALSE;
-		}
-
-	} else if (dc->nonce_type == DC_NONCE_SHA1) {
-		msn_dc_calculate_nonce_hash(dc->nonce_type, nonce, sizeof(nonce), nonce_hash);
-
-		if (g_str_equal(dc->remote_nonce, nonce_hash)) {
-			purple_debug_info("msn",
-					"Received nonce %s from buddy request "
-					"and calculated nonce %s from DC attempt. "
-					"Nonces match, allowing direct connection\n",
-					dc->remote_nonce, nonce_hash);
-			return TRUE;
-		} else {
-			purple_debug_warning("msn",
-					"Received nonce %s from buddy request "
-					"and calculated nonce %s from DC attempt. "
-					"Nonces don't match, ignoring direct connection\n",
-					dc->remote_nonce, nonce_hash);
-			return FALSE;
-		}
-	} else
-		return FALSE;
-}
-
-static void
-msn_dc_send_packet_cb(MsnDirectConnPacket *p)
-{
-	if (p->part != NULL && p->part->ack_cb != NULL)
-		p->part->ack_cb(p->part, p->part->ack_data);
-}
-
-void
-msn_dc_enqueue_part(MsnDirectConn *dc, MsnSlpMessagePart *part)
-{
-	MsnDirectConnPacket *p;
-	size_t length;
-
-	p = msn_dc_new_packet(0);
-	p->data = (guchar *)msn_slpmsgpart_serialize(part, &length);
-	p->length = length - P2P_PACKET_FOOTER_SIZE; /* DC doesn't need footer? */
-
-	p->sent_cb = msn_dc_send_packet_cb;
-	p->part = msn_slpmsgpart_ref(part);
-
-	msn_dc_enqueue_packet(dc, p);
-}
-
-static int
-msn_dc_process_packet(MsnDirectConn *dc, guint32 packet_length)
-{
-	MsnSlpMessagePart *part;
-
-	g_return_val_if_fail(dc != NULL, DC_PROCESS_ERROR);
-
-	switch (dc->state) {
-	case DC_STATE_CLOSED:
-		break;
-
-	case DC_STATE_FOO:
-		/* FOO message is always 4 bytes long */
-		if (packet_length != 4 || memcmp(dc->in_buffer, "\4\0\0\0foo", 8) != 0)
-			return DC_PROCESS_FALLBACK;
-
-		dc->state = DC_STATE_HANDSHAKE;
-		break;
-
-	case DC_STATE_HANDSHAKE:
-		if (!msn_dc_verify_handshake(dc, packet_length))
-			return DC_PROCESS_FALLBACK;
-
-		msn_dc_send_handshake(dc);
-		dc->state = DC_STATE_ESTABLISHED;
-
-		msn_slpcall_session_init(dc->slpcall);
-		dc->slpcall = NULL;
-		break;
-
-	case DC_STATE_HANDSHAKE_REPLY:
-		if (!msn_dc_verify_handshake(dc, packet_length))
-			return DC_PROCESS_FALLBACK;
-
-		dc->state = DC_STATE_ESTABLISHED;
-
-		msn_slpcall_session_init(dc->slpcall);
-		dc->slpcall = NULL;
-		break;
-
-	case DC_STATE_ESTABLISHED:
-		if (packet_length) {
-			MsnP2PVersion p2p;
-			p2p = msn_slplink_get_p2p_version(dc->slplink);
-			part = msn_slpmsgpart_new_from_data(p2p, dc->in_buffer + 4, packet_length);
-			if (part) {
-				msn_slplink_process_msg(dc->slplink, part);
-				msn_slpmsgpart_unref(part);
-			}
-		}
-
-		/*
-		if (dc->num_calls == 0) {
-			msn_dc_destroy(dc);
-
-			return DC_PROCESS_CLOSE;
-		}
-		*/
-		break;
-	}
-
-	return DC_PROCESS_OK;
-}
-
-static void
-msn_dc_recv_cb(gpointer data, gint fd, PurpleInputCondition cond)
-{
-	MsnDirectConn *dc;
-	int free_buf_space;
-	int bytes_received;
-	guint32 packet_length;
-
-	g_return_if_fail(data != NULL);
-	g_return_if_fail(fd != -1);
-
-	dc = data;
-	free_buf_space = dc->in_size - dc->in_pos;
-
-	bytes_received = recv(fd, dc->in_buffer + dc->in_pos, free_buf_space, 0);
-	if (bytes_received < 0) {
-		if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-			return;
-
-		purple_debug_warning("msn", "msn_dc_recv_cb: recv error\n");
-
-		if(dc->state != DC_STATE_ESTABLISHED)
-			msn_dc_fallback_to_sb(dc);
-		else
-			msn_dc_destroy(dc);
-		return;
-
-	} else if (bytes_received == 0) {
-		/* EOF. Remote side closed connection. */
-		purple_debug_info("msn", "msn_dc_recv_cb: recv EOF\n");
-
-		if(dc->state != DC_STATE_ESTABLISHED)
-			msn_dc_fallback_to_sb(dc);
-		else
-			msn_dc_destroy(dc);
-		return;
-	}
-
-	dc->progress = TRUE;
-
-	dc->in_pos += bytes_received;
-
-	/* Wait for packet length */
-	while (dc->in_pos >= 4) {
-		packet_length = GUINT32_FROM_LE(*((guint32*)dc->in_buffer));
-
-		if (packet_length > DC_MAX_PACKET_SIZE) {
-			/* Oversized packet */
-			purple_debug_warning("msn", "msn_dc_recv_cb: oversized packet received\n");
-			return;
-		}
-
-		/* Wait for the whole packet to arrive */
-		if ((guint32)dc->in_pos < 4 + packet_length)
-			return;
-
-		switch (msn_dc_process_packet(dc, packet_length)) {
-		case DC_PROCESS_CLOSE:
-			return;
-
-		case DC_PROCESS_FALLBACK:
-			purple_debug_warning("msn", "msn_dc_recv_cb: packet processing error, fall back to SB\n");
-			msn_dc_fallback_to_sb(dc);
-			return;
-
-		}
-
-		if ((guint32)dc->in_pos > packet_length + 4) {
-			g_memmove(dc->in_buffer, dc->in_buffer + 4 + packet_length, dc->in_pos - packet_length - 4);
-		}
-
-		dc->in_pos -= packet_length + 4;
-	}
-}
-
-static gboolean
-msn_dc_timeout(gpointer data)
-{
-	MsnDirectConn *dc = data;
-
-	g_return_val_if_fail(dc != NULL, FALSE);
-
-	if (dc->progress) {
-		dc->progress = FALSE;
-		return TRUE;
-	} else {
-		dc->timeout_handle = 0;
-		msn_dc_destroy(dc);
-		return FALSE;
-	}
-}
-
-static void
-msn_dc_init(MsnDirectConn *dc)
-{
-	g_return_if_fail(dc != NULL);
-
-	dc->in_size = DC_MAX_PACKET_SIZE + 4;
-	dc->in_pos = 0;
-	dc->in_buffer = g_malloc(dc->in_size);
-
-	dc->recv_handle = purple_input_add(dc->fd, PURPLE_INPUT_READ, msn_dc_recv_cb, dc);
-	dc->send_handle = purple_input_add(dc->fd, PURPLE_INPUT_WRITE, msn_dc_send_cb, dc);
-
-	dc->timeout_handle = purple_timeout_add_seconds(DC_TIMEOUT, msn_dc_timeout, dc);
-}
-
-void
-msn_dc_connected_to_peer_cb(gpointer data, gint fd, const gchar *error_msg)
-{
-	MsnDirectConn *dc = data;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "msn_dc_connected_to_peer_cb %p\n", dc);
-
-	g_return_if_fail(dc != NULL);
-
-	dc->connect_data = NULL;
-	purple_timeout_remove(dc->connect_timeout_handle);
-	dc->connect_timeout_handle = 0;
-
-	dc->fd = fd;
-	if (dc->fd != -1) {
-		msn_dc_init(dc);
-		msn_dc_send_foo(dc);
-		msn_dc_send_handshake(dc);
-		dc->state = DC_STATE_HANDSHAKE_REPLY;
-	}
-}
-
-/*
- * This callback will be called when we're the server
- * and nobody has connected us in DC_INCOMING_TIMEOUT seconds
- */
-static gboolean
-msn_dc_incoming_connection_timeout_cb(gpointer data) {
-	MsnDirectConn *dc = data;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "msn_dc_incoming_connection_timeout_cb %p\n", dc);
-
-	g_return_val_if_fail(dc != NULL, FALSE);
-
-	if (dc->listen_data != NULL) {
-		purple_network_listen_cancel(dc->listen_data);
-		dc->listen_data = NULL;
-	}
-
-	if (dc->listenfd_handle != 0) {
-		purple_input_remove(dc->listenfd_handle);
-		dc->listenfd_handle = 0;
-	}
-
-	if (dc->listenfd != -1) {
-		purple_network_remove_port_mapping(dc->listenfd);
-		close(dc->listenfd);
-		dc->listenfd = -1;
-	}
-
-	dc->connect_timeout_handle = 0;
-	msn_dc_fallback_to_sb(dc);
-
-	return FALSE;
-}
-
-/*
- * This callback will be called when we're unable to connect to
- * the remote host in DC_OUTGOING_TIMEOUT seconds.
- */
-gboolean
-msn_dc_outgoing_connection_timeout_cb(gpointer data)
-{
-	MsnDirectConn *dc = data;
-
-	purple_debug_info("msn", "msn_dc_outgoing_connection_timeout_cb %p\n", dc);
-
-	g_return_val_if_fail(dc != NULL, FALSE);
-
-	dc->connect_timeout_handle = 0;
-
-	if (dc->connect_data != NULL) {
-		purple_proxy_connect_cancel(dc->connect_data);
-		dc->connect_data = NULL;
-	}
-
-	if (dc->ext_ip && dc->ext_port) {
-		/* Try external IP/port if available. */
-		dc->connect_data = purple_proxy_connect(
-			NULL,
-			dc->slpcall->slplink->session->account,
-			dc->ext_ip,
-			dc->ext_port,
-			msn_dc_connected_to_peer_cb,
-			dc
-		);
-
-		g_free(dc->ext_ip);
-		dc->ext_ip = NULL;
-
-		if (dc->connect_data) {
-			dc->connect_timeout_handle = purple_timeout_add_seconds(
-				DC_OUTGOING_TIMEOUT,
-				msn_dc_outgoing_connection_timeout_cb,
-				dc
-			);
-		} else {
-			/*
-			 * Connection failed
-			 * Fall back to SB transfer
-			 */
-			msn_dc_outgoing_connection_timeout_cb(dc);
-		}
-
-	} else {
-		/*
-		 * Both internal and external connection attempts failed.
-		 * Fall back to SB transfer.
-		 */
-		msn_dc_fallback_to_sb(dc);
-	}
-
-	return FALSE;
-}
-
-/*
- * This callback will be called when we're the server
- * and somebody has connected to us in DC_INCOMING_TIMEOUT seconds.
- */
-static void
-msn_dc_incoming_connection_cb(gpointer data, gint listenfd, PurpleInputCondition cond)
-{
-	MsnDirectConn *dc = data;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "msn_dc_incoming_connection_cb %p\n", dc);
-
-	g_return_if_fail(dc != NULL);
-
-	if (dc->connect_timeout_handle != 0) {
-		purple_timeout_remove(dc->connect_timeout_handle);
-		dc->connect_timeout_handle = 0;
-	}
-
-	if (dc->listenfd_handle != 0) {
-		purple_input_remove(dc->listenfd_handle);
-		dc->listenfd_handle = 0;
-	}
-
-	dc->fd = accept(listenfd, NULL, 0);
-
-	purple_network_remove_port_mapping(dc->listenfd);
-	close(dc->listenfd);
-	dc->listenfd = -1;
-
-	if (dc->fd != -1) {
-		msn_dc_init(dc);
-		dc->state = DC_STATE_FOO;
-	}
-}
-
-void
-msn_dc_listen_socket_created_cb(int listenfd, gpointer data)
-{
-	MsnDirectConn *dc = data;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "msn_dc_listen_socket_created_cb %p\n", dc);
-
-	g_return_if_fail(dc != NULL);
-
-	dc->listen_data = NULL;
-
-	if (listenfd != -1) {
-		const char *ext_ip;
-		const char *int_ip;
-		int port;
-
-		ext_ip = purple_network_get_my_ip(listenfd);
-		int_ip = purple_network_get_local_system_ip(listenfd);
-		port = purple_network_get_port_from_fd(listenfd);
-
-		dc->listenfd = listenfd;
-		dc->listenfd_handle = purple_input_add(
-			listenfd,
-			PURPLE_INPUT_READ,
-			msn_dc_incoming_connection_cb,
-			dc
-		);
-		dc->connect_timeout_handle = purple_timeout_add_seconds(
-			DC_INCOMING_TIMEOUT,
-			msn_dc_incoming_connection_timeout_cb,
-			dc
-		);
-
-		if (strcmp(int_ip, ext_ip) != 0) {
-			dc->msg_body = g_strdup_printf(
-				"Bridge: TCPv1\r\n"
-				"Listening: true\r\n"
-				"%sNonce: {%s}\r\n"
-				"IPv4External-Addrs: %s\r\n"
-				"IPv4External-Port: %d\r\n"
-				"IPv4Internal-Addrs: %s\r\n"
-				"IPv4Internal-Port: %d\r\n"
-				"\r\n",
-
-				dc->nonce_type != DC_NONCE_PLAIN ? "Hashed-" : "",
-				dc->nonce_hash,
-				ext_ip,
-				port,
-				int_ip,
-				port
-			);
-
-		} else {
-			dc->msg_body = g_strdup_printf(
-				"Bridge: TCPv1\r\n"
-				"Listening: true\r\n"
-				"%sNonce: {%s}\r\n"
-				"IPv4External-Addrs: %s\r\n"
-				"IPv4External-Port: %d\r\n"
-				"\r\n",
-
-				dc->nonce_type != DC_NONCE_PLAIN ? "Hashed-" : "",
-				dc->nonce_hash,
-				ext_ip,
-				port
-			);
-		}
-
-		if (dc->slpcall->wait_for_socket) {
-			if (dc->send_connection_info_msg_cb != NULL)
-				dc->send_connection_info_msg_cb(dc);
-
-			dc->slpcall->wait_for_socket = FALSE;
-		}
-	}
-}
-
--- a/libpurple/protocols/msn/directconn.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +0,0 @@
-/**
- * @file directconn.h MSN direct connection functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_DIRECTCONN_H
-#define MSN_DIRECTCONN_H
-
-typedef struct _MsnDirectConn MsnDirectConn;
-
-#include "network.h"
-#include "proxy.h"
-#include "circbuffer.h"
-
-#include "slp.h"
-#include "slplink.h"
-#include "slpmsg.h"
-#include "slpmsg_part.h"
-#include "p2p.h"
-
-#define MSN_DCCONN_MAX_SIZE 1352
-
-typedef enum
-{
-	DC_STATE_CLOSED,            /*< No socket opened yet */
-	DC_STATE_FOO,               /*< Waiting for FOO message */
-	DC_STATE_HANDSHAKE,         /*< Waiting for handshake message */
-	DC_STATE_HANDSHAKE_REPLY,   /*< Waiting for handshake reply message */
-	DC_STATE_ESTABLISHED        /*< Handshake complete */
-} MsnDirectConnState;
-
-typedef enum
-{
-	DC_PROCESS_OK = 0,
-	DC_PROCESS_ERROR,
-	DC_PROCESS_FALLBACK,
-	DC_PROCESS_CLOSE
-
-} MsnDirectConnProcessResult;
-
-typedef enum
-{
-	DC_NONCE_UNKNOWN,	/**< Invalid scheme */
-	DC_NONCE_PLAIN,     /**< No hashing */
-	DC_NONCE_SHA1       /**< First 16 bytes of SHA1 of nonce */
-
-} MsnDirectConnNonceType;
-
-typedef struct _MsnDirectConnPacket MsnDirectConnPacket;
-
-struct _MsnDirectConnPacket {
-	guint32     length;
-	guchar      *data;
-
-	void        (*sent_cb)(struct _MsnDirectConnPacket*);
-	MsnSlpMessagePart *part;
-};
-
-struct _MsnDirectConn
-{
-	MsnDirectConnState  state;      /**< Direct connection status */
-	MsnSlpLink          *slplink;   /**< The slplink using this direct connection */
-	MsnSlpCall          *slpcall;   /**< The slpcall which initiated the direct connection */
-	char                *msg_body;  /**< The body of message sent by send_connection_info_msg_cb */
-	MsnSlpMessage       *prev_ack;  /**< The saved SLP ACK message */
-
-	MsnDirectConnNonceType nonce_type;         /**< The type of nonce hashing */
-	guchar                 nonce[16];          /**< The nonce used for handshake */
-	gchar                  nonce_hash[37];     /**< The hash of nonce */
-	gchar                  remote_nonce[37];   /**< The remote side's nonce */
-
-	PurpleNetworkListenData *listen_data;           /**< The pending socket creation request */
-	PurpleProxyConnectData  *connect_data;          /**< The pending connection attempt */
-	int                     listenfd;               /**< The socket we're listening for incoming connections */
-	guint                   listenfd_handle;        /**< The timeout handle for incoming connection */
-	guint                   connect_timeout_handle; /**< The timeout handle for outgoing connection */
-
-	int     fd;             /**< The direct connection socket */
-	guint   recv_handle;    /**< The incoming data callback handle */
-	guint   send_handle;    /**< The outgoing data callback handle */
-
-	gchar   *in_buffer; /**< The receive buffer */
-	int     in_size;    /**< The receive buffer size */
-	int     in_pos;     /**< The first free position in receive buffer */
-	GQueue  *out_queue; /**< The outgoing packet queue */
-	int     msg_pos;    /**< The position of next byte to be sent in the actual packet */
-
-	/** The callback used for sending information to the peer about the opened socket */
-	void (*send_connection_info_msg_cb)(MsnDirectConn *);
-
-	gchar   *ext_ip;    /**< Our external IP address */
-	int     ext_port;   /**< Our external port */
-
-	guint       timeout_handle;
-	gboolean    progress;
-
-	/*int   num_calls;*/  /**< The number of slpcalls using this direct connection */
-};
-
-/* Outgoing attempt */
-#define DC_OUTGOING_TIMEOUT (5)
-/* Time for internal + external connection attempts */
-#define DC_INCOMING_TIMEOUT (DC_OUTGOING_TIMEOUT * 3)
-/* Timeout for lack of activity */
-#define DC_TIMEOUT          (60)
-
-/*
- * Queues an MSN message to be sent via direct connection.
- */
-void
-msn_dc_enqueue_part(MsnDirectConn *dc, MsnSlpMessagePart *part);
-
-/*
- * Creates, initializes, and returns a new MsnDirectConn structure.
- */
-MsnDirectConn *
-msn_dc_new(MsnSlpCall *slpcall);
-
-/*
- * Destroys an MsnDirectConn structure. Frees every buffer allocated earlier
- * restores saved callbacks, etc.
- */
-void
-msn_dc_destroy(MsnDirectConn *dc);
-
-/*
- * Fallback to switchboard connection. Used when neither side is able to
- * create a listening socket.
- */
-void
-msn_dc_fallback_to_sb(MsnDirectConn *dc);
-
-/*
- * Increases the slpcall counter in DC. The direct connection remains open
- * until all slpcalls using it are destroyed.
- */
-void
-msn_dc_ref(MsnDirectConn *dc);
-
-/*
- * Decrease the slpcall counter in DC. The direct connection remains open
- * until all slpcalls using it are destroyed.
- */
-void
-msn_dc_unref(MsnDirectConn *dc);
-
-/*
- * Sends a direct connect INVITE message on the associated slplink
- * with the corresponding connection type and information.
- */
-void
-msn_dc_send_invite(MsnDirectConn *dc);
-
-/*
- * Sends a direct connect OK message as a response to an INVITE received earliaer
- * on the corresponding slplink.
- */
-void
-msn_dc_send_ok(MsnDirectConn *dc);
-
-/*
- * This callback will be called when we're successfully connected to
- * the remote host.
- */
-void
-msn_dc_connected_to_peer_cb(gpointer data, gint fd, const gchar *error_msg);
-
-/*
- * This callback will be called when we're unable to connect to
- * the remote host in DC_CONNECT_TIMEOUT seconds.
- */
-gboolean
-msn_dc_outgoing_connection_timeout_cb(gpointer data);
-
-/*
- * This callback will be called when the listening socket is successfully
- * created and its parameters (IP/port) are available.
- */
-void
-msn_dc_listen_socket_created_cb(int listenfd, gpointer data);
-
-#endif /* MSN_DIRECTCONN_H */
--- a/libpurple/protocols/msn/error.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,384 +0,0 @@
-/**
- * @file error.c Error functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-/* Masca: can we get rid of the sync issue dialog? */
-#include "request.h"
-
-#include "error.h"
-
-typedef struct
-{
-	MsnSession *session;
-	char *who;
-	char *group;
-	gboolean add;
-
-} MsnAddRemData;
-
-const char *
-msn_error_get_text(unsigned int type, gboolean *debug)
-{
-	static char msg[256];
-	const char *result;
-	*debug = FALSE;
-
-	switch (type) {
-		case 0:
-			result = _("Unable to parse message");
-			*debug = TRUE;
-			break;
-		case 200:
-			result = _("Syntax Error (probably a client bug)");
-			*debug = TRUE;
-			break;
-		case 201:
-			result = _("Invalid email address");
-			break;
-		case 205:
-			result = _("User does not exist");
-			break;
-		case 206:
-			result = _("Fully qualified domain name missing");
-			break;
-		case 207:
-			result = _("Already logged in");
-			break;
-		case 208:
-			result = _("Invalid username");
-			break;
-		case 209:
-			result = _("Invalid friendly name");
-			break;
-		case 210:
-			result = _("List full");
-			break;
-		case 215:
-			result = _("Already there");
-			*debug = TRUE;
-			break;
-		case 216:
-			result = _("Not on list");
-			break;
-		case 217:
-			result = _("User is offline");
-			break;
-		case 218:
-			result = _("Already in the mode");
-			*debug = TRUE;
-			break;
-		case 219:
-			result = _("Already in opposite list");
-			*debug = TRUE;
-			break;
-		case 223:
-			result = _("Too many groups");
-			break;
-		case 224:
-			result = _("Invalid group");
-			break;
-		case 225:
-			result = _("User not in group");
-			break;
-		case 229:
-			result = _("Group name too long");
-			break;
-		case 230:
-			result = _("Cannot remove group zero");
-			*debug = TRUE;
-			break;
-		case 231:
-			result = _("Tried to add a user to a group that doesn't exist");
-			break;
-		case 280:
-			result = _("Switchboard failed");
-			*debug = TRUE;
-			break;
-		case 281:
-			result = _("Notify transfer failed");
-			*debug = TRUE;
-			break;
-
-		case 300:
-			result = _("Required fields missing");
-			*debug = TRUE;
-			break;
-		case 301:
-			result = _("Too many hits to a FND");
-			*debug = TRUE;
-			break;
-		case 302:
-			result = _("Not logged in");
-			break;
-
-		case 500:
-			result = _("Service temporarily unavailable");
-			break;
-		case 501:
-			result = _("Database server error");
-			*debug = TRUE;
-			break;
-		case 502:
-			result = _("Command disabled");
-			*debug = TRUE;
-			break;
-		case 510:
-			result = _("File operation error");
-			*debug = TRUE;
-			break;
-		case 520:
-			result = _("Memory allocation error");
-			*debug = TRUE;
-			break;
-		case 540:
-			result = _("Wrong CHL value sent to server");
-			*debug = TRUE;
-			break;
-
-		case 600:
-			result = _("Server busy");
-			break;
-		case 601:
-			result = _("Server unavailable");
-			break;
-		case 602:
-			result = _("Peer notification server down");
-			*debug = TRUE;
-			break;
-		case 603:
-			result = _("Database connect error");
-			*debug = TRUE;
-			break;
-		case 604:
-			result = _("Server is going down (abandon ship)");
-			break;
-		case 605:
-			result = _("Server unavailable");
-			break;
-
-		case 707:
-			result = _("Error creating connection");
-			*debug = TRUE;
-			break;
-		case 710:
-			result = _("CVR parameters are either unknown or not allowed");
-			*debug = TRUE;
-			break;
-		case 711:
-			result = _("Unable to write");
-			break;
-		case 712:
-			result = _("Session overload");
-			*debug = TRUE;
-			break;
-		case 713:
-			result = _("User is too active");
-			break;
-		case 714:
-			result = _("Too many sessions");
-			break;
-		case 715:
-			result = _("Passport not verified");
-			break;
-		case 717:
-			result = _("Bad friend file");
-			*debug = TRUE;
-			break;
-		case 731:
-			result = _("Not expected");
-			*debug = TRUE;
-			break;
-
-		case 800:
-			result = _("Friendly name is changing too rapidly");
-			break;
-
-		case 910:
-		case 912:
-		case 918:
-		case 919:
-		case 921:
-		case 922:
-			result = _("Server too busy");
-			break;
-		case 911:
-		case 917:
-			result = _("Authentication failed");
-			break;
-		case 913:
-			result = _("Not allowed when offline");
-			break;
-		case 914:
-		case 915:
-		case 916:
-			result = _("Server unavailable");
-			break;
-		case 920:
-			result = _("Not accepting new users");
-			break;
-		case 923:
-			result = _("Kids Passport without parental consent");
-			break;
-		case 924:
-			result = _("Passport account not yet verified");
-			break;
-		case 927:
-			result = _("Passport account suspended");
-			break;
-		case 928:
-			result = _("Bad ticket");
-			*debug = TRUE;
-			break;
-
-		default:
-			g_snprintf(msg, sizeof(msg),
-			           _("Unknown Error Code %d"), type);
-			*debug = TRUE;
-			result = msg;
-			break;
-	}
-
-	return result;
-}
-
-void
-msn_error_handle(MsnSession *session, unsigned int type)
-{
-	char *buf;
-	gboolean debug;
-
-	buf = g_strdup_printf(_("MSN Error: %s\n"),
-	                      msn_error_get_text(type, &debug));
-	if (debug)
-		purple_debug_warning("msn", "error %d: %s\n", type, buf);
-	else
-		purple_notify_error(session->account->gc, NULL, buf, NULL);
-	g_free(buf);
-}
-
-/* Remove the buddy referenced by the MsnAddRemData before the serverside list
- * is changed.  If the buddy will be added, he'll be added back; if he will be
- * removed, he won't be. */
-/* Actually with our MSNP14 code that isn't true yet, he won't be added back :(
- * */
-static void
-msn_complete_sync_issue(MsnAddRemData *data)
-{
-	PurpleBuddy *buddy;
-	PurpleGroup *group = NULL;
-
-	if (data->group != NULL)
-		group = purple_find_group(data->group);
-
-	if (group != NULL)
-		buddy = purple_find_buddy_in_group(data->session->account, data->who, group);
-	else
-		buddy = purple_find_buddy(data->session->account, data->who);
-
-	if (buddy != NULL)
-		purple_blist_remove_buddy(buddy);
-}
-
-
-static void
-msn_add_cb(MsnAddRemData *data)
-{
-#if 0
-	/* this *should* be necessary !! */
-	msn_complete_sync_issue(data);
-#endif
-	MsnUserList *userlist = data->session->userlist;
-
-	msn_userlist_add_buddy(userlist, data->who, data->group);
-
-	g_free(data->group);
-	g_free(data->who);
-	g_free(data);
-}
-
-static void
-msn_rem_cb(MsnAddRemData *data)
-{
-	MsnUserList *userlist = data->session->userlist;
-	msn_complete_sync_issue(data);
-
-
-	if (data->group == NULL) {
-		msn_userlist_rem_buddy_from_list(userlist, data->who, MSN_LIST_FL);
-	} else {
-		g_free(data->group);
-	}
-
-	g_free(data->who);
-	g_free(data);
-}
-
-void
-msn_error_sync_issue(MsnSession *session, const char *passport,
-					const char *group_name)
-{
-	PurpleConnection *gc;
-	PurpleAccount *account;
-	MsnAddRemData *data;
-	char *msg, *reason;
-
-	account = session->account;
-	gc = purple_account_get_connection(account);
-
-	data          = g_new0(MsnAddRemData, 1);
-	data->who     = g_strdup(passport);
-	data->group   = g_strdup(group_name);
-	data->session = session;
-
-	msg = g_strdup_printf(_("Buddy list synchronization issue in %s (%s)"),
-						  purple_account_get_username(account),
-						  purple_account_get_protocol_name(account));
-
-	if (group_name != NULL)
-	{
-		reason = g_strdup_printf(_("%s on the local list is "
-								   "inside the group \"%s\" but not on "
-								   "the server list. "
-								   "Do you want this buddy to be added?"),
-								 passport, group_name);
-	}
-	else
-	{
-		reason = g_strdup_printf(_("%s is on the local list but "
-								   "not on the server list. "
-								   "Do you want this buddy to be added?"),
-								 passport);
-	}
-
-	purple_request_action(gc, NULL, msg, reason, PURPLE_DEFAULT_ACTION_NONE,
-						account, data->who, NULL,
-						data, 2,
-						_("Yes"), G_CALLBACK(msn_add_cb),
-						_("No"), G_CALLBACK(msn_rem_cb));
-
-	g_free(reason);
-	g_free(msg);
-}
-
--- a/libpurple/protocols/msn/error.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/**
- * @file error.h Error functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_ERROR_H
-#define MSN_ERROR_H
-
-#include "session.h"
-
-/**
- * Returns the string representation of an error type.
- *
- * @param type The error type.
- * @param debug Whether this should be treated as a debug log message or a user-visible error
- *
- * @return The string representation of the error type.
- */
-const char *msn_error_get_text(unsigned int type, gboolean *debug);
-
-/**
- * Handles an error.
- *
- * @param session The current session.
- * @param type    The error type.
- */
-void msn_error_handle(MsnSession *session, unsigned int type);
-
-/**
- * Show the sync issue in a dialog using request api
- *
- * @param sesion 		MsnSession associated to this error.
- * @param passport 		The passport associated with the error.
- * @param group_name 	The group in the buddy is suppoused to be
- */
-void msn_error_sync_issue(MsnSession *session, const char *passport,
-						 const char *group_name);
-
-#endif /* MSN_ERROR_H */
--- a/libpurple/protocols/msn/group.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/**
- * @file group.c Group functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#include "msn.h"
-#include "group.h"
-
-MsnGroup *
-msn_group_new(MsnUserList *userlist, const char *id, const char *name)
-{
-	MsnGroup *group;
-
-	g_return_val_if_fail(id != NULL,      NULL);
-	g_return_val_if_fail(name != NULL, NULL);
-
-	group = g_new0(MsnGroup, 1);
-
-	msn_userlist_add_group(userlist, group);
-
-	group->id      = g_strdup(id);
-	group->name    = g_strdup(name);
-
-	return group;
-}
-
-void
-msn_group_destroy(MsnGroup *group)
-{
-	g_return_if_fail(group != NULL);
-
-	g_free(group->id);
-	g_free(group->name);
-	g_free(group);
-}
-
-void
-msn_group_set_id(MsnGroup *group, const char *id)
-{
-	g_return_if_fail(group != NULL);
-	g_return_if_fail(id != NULL);
-
-	g_free(group->id);
-	group->id = g_strdup(id);
-}
-
-void
-msn_group_set_name(MsnGroup *group, const char *name)
-{
-	g_return_if_fail(group != NULL);
-	g_return_if_fail(name  != NULL);
-
-	g_free(group->name);
-	group->name = g_strdup(name);
-}
-
-char*
-msn_group_get_id(const MsnGroup *group)
-{
-	g_return_val_if_fail(group != NULL, NULL);
-
-	return group->id;
-}
-
-const char *
-msn_group_get_name(const MsnGroup *group)
-{
-	g_return_val_if_fail(group != NULL, NULL);
-
-	return group->name;
-}
--- a/libpurple/protocols/msn/group.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/**
- * @file group.h Group functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_GROUP_H
-#define MSN_GROUP_H
-
-typedef struct _MsnGroup  MsnGroup;
-
-#include "internal.h"
-
-#include "session.h"
-#include "user.h"
-#include "userlist.h"
-
-#define MSN_INDIVIDUALS_GROUP_ID	"1983"
-#define MSN_INDIVIDUALS_GROUP_NAME	_("Other Contacts")
-
-#define MSN_NON_IM_GROUP_ID		"email"
-#define MSN_NON_IM_GROUP_NAME	_("Non-IM Contacts")
-
-/**
- * A group.
- */
-struct _MsnGroup
-{
-	MsnSession *session;    /**< The MSN session.           */
-
-	char *id;                 /**< The group ID.              */
-	char *name;             /**< The name of the group.     */
-};
-
-/**************************************************************************
- ** @name Group API                                                       *
- **************************************************************************/
-/*@{*/
-
-/**
- * Creates a new group structure.
- *
- * @param session The MSN session.
- * @param id      The group ID.
- * @param name    The name of the group.
- *
- * @return A new group structure.
- */
-MsnGroup *msn_group_new(MsnUserList *userlist, const char *id, const char *name);
-
-/**
- * Destroys a group structure.
- *
- * @param group The group to destroy.
- */
-void msn_group_destroy(MsnGroup *group);
-
-/**
- * Sets the ID for a group.
- *
- * @param group The group.
- * @param id    The ID.
- */
-void msn_group_set_id(MsnGroup *group, const char *id);
-
-/**
- * Sets the name for a group.
- *
- * @param group The group.
- * @param name  The name.
- */
-void msn_group_set_name(MsnGroup *group, const char *name);
-
-/**
- * Returns the ID for a group.
- *
- * @param group The group.
- *
- * @return The ID.
- */
-char* msn_group_get_id(const MsnGroup *group);
-
-/**
- * Returns the name for a group.
- *
- * @param group The group.
- *
- * @return The name.
- */
-const char *msn_group_get_name(const MsnGroup *group);
-
-#endif /* MSN_GROUP_H */
--- a/libpurple/protocols/msn/history.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/**
- * @file history.c MSN history functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#include "msn.h"
-#include "history.h"
-
-MsnHistory *
-msn_history_new(void)
-{
-	MsnHistory *history = g_new0(MsnHistory, 1);
-
-	history->trId = 1;
-
-	history->queue = g_queue_new();
-
-	return history;
-}
-
-void
-msn_history_destroy(MsnHistory *history)
-{
-	MsnTransaction *trans;
-
-	while ((trans = g_queue_pop_head(history->queue)) != NULL)
-		msn_transaction_destroy(trans);
-
-	g_queue_free(history->queue);
-	g_free(history);
-}
-
-MsnTransaction *
-msn_history_find(MsnHistory *history, unsigned int trId)
-{
-	MsnTransaction *trans;
-	GList *list;
-
-	for (list = history->queue->head; list != NULL; list = list->next)
-	{
-		trans = list->data;
-		if (trans->trId == trId)
-			return trans;
-	}
-
-	return NULL;
-}
-
-void
-msn_history_add(MsnHistory *history, MsnTransaction *trans)
-{
-	GQueue *queue;
-	gsize max_elems;
-
-	g_return_if_fail(history != NULL);
-	g_return_if_fail(trans   != NULL);
-
-	queue = history->queue;
-
-	trans->trId = history->trId++;
-
-	g_queue_push_tail(queue, trans);
-
-	if (trans->cmdproc->servconn->type == MSN_SERVCONN_NS)
-		max_elems = MSN_NS_HIST_ELEMS;
-	else
-		max_elems = MSN_SB_HIST_ELEMS;
-
-	if (queue->length > max_elems)
-	{
-		trans = g_queue_pop_head(queue);
-		msn_transaction_destroy(trans);
-	}
-}
-
--- a/libpurple/protocols/msn/history.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/**
- * @file history.h MSN history functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_HISTORY_H
-#define MSN_HISTORY_H
-
-#include "internal.h"
-
-typedef struct _MsnHistory MsnHistory;
-
-#include "transaction.h"
-
-#define MSN_NS_HIST_ELEMS 0x300
-#define MSN_SB_HIST_ELEMS 0x30
-
-/**
- * The history.
- */
-struct _MsnHistory
-{
-	GQueue *queue;
-	unsigned int trId;
-};
-
-MsnHistory *msn_history_new(void);
-void msn_history_destroy(MsnHistory *history);
-MsnTransaction *msn_history_find(MsnHistory *history, unsigned int triId);
-void msn_history_add(MsnHistory *history, MsnTransaction *trans);
-
-#endif /* MSN_HISTORY_H */
--- a/libpurple/protocols/msn/httpconn.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,739 +0,0 @@
-/**
- * @file httpconn.c HTTP connection method
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#include "msn.h"
-#include "debug.h"
-#include "httpconn.h"
-
-typedef struct
-{
-	MsnHttpConn *httpconn;
-	char *body;
-	size_t body_len;
-} MsnHttpQueueData;
-
-static void
-msn_httpconn_process_queue(MsnHttpConn *httpconn)
-{
-	httpconn->waiting_response = FALSE;
-
-	if (httpconn->queue != NULL)
-	{
-		MsnHttpQueueData *queue_data;
-
-		queue_data = (MsnHttpQueueData *)httpconn->queue->data;
-
-		httpconn->queue = g_list_remove(httpconn->queue, queue_data);
-
-		msn_httpconn_write(queue_data->httpconn,
-						   queue_data->body,
-						   queue_data->body_len);
-
-		g_free(queue_data->body);
-		g_free(queue_data);
-	}
-}
-
-static gboolean
-msn_httpconn_parse_data(MsnHttpConn *httpconn, const char *buf,
-						size_t size, char **ret_buf, size_t *ret_size,
-						gboolean *error)
-{
-	const char *s, *c;
-	char *header, *body;
-	const char *body_start;
-	char *tmp;
-	size_t body_len = 0;
-
-	g_return_val_if_fail(httpconn != NULL, FALSE);
-	g_return_val_if_fail(buf      != NULL, FALSE);
-	g_return_val_if_fail(size      > 0,    FALSE);
-	g_return_val_if_fail(ret_buf  != NULL, FALSE);
-	g_return_val_if_fail(ret_size != NULL, FALSE);
-	g_return_val_if_fail(error    != NULL, FALSE);
-
-#if 0
-	purple_debug_info("msn", "HTTP: parsing data {%s}\n", buf);
-#endif
-
-	/* Healthy defaults. */
-	body = NULL;
-
-	*ret_buf  = NULL;
-	*ret_size = 0;
-	*error    = FALSE;
-
-	/* First, some tests to see if we have a full block of stuff. */
-	if (((strncmp(buf, "HTTP/1.1 200 OK\r\n", 17) != 0) &&
-		 (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) != 0)) &&
-		((strncmp(buf, "HTTP/1.0 200 OK\r\n", 17) != 0) &&
-		 (strncmp(buf, "HTTP/1.0 100 Continue\r\n", 23) != 0)))
-	{
-		*error = TRUE;
-
-		return FALSE;
-	}
-
-	if (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) == 0)
-	{
-		if ((s = strstr(buf, "\r\n\r\n")) == NULL)
-			return FALSE;
-
-		s += 4;
-
-		if (*s == '\0')
-		{
-			*ret_buf = g_strdup("");
-			*ret_size = 0;
-
-			msn_httpconn_process_queue(httpconn);
-
-			return TRUE;
-		}
-
-		size -= (s - buf);
-		buf = s;
-	}
-
-	if ((s = strstr(buf, "\r\n\r\n")) == NULL)
-		/* Need to wait for the full HTTP header to arrive */
-		return FALSE;
-
-	s += 4; /* Skip \r\n\r\n */
-	header = g_strndup(buf, s - buf);
-	body_start = s;
-	body_len = size - (body_start - buf);
-
-	if ((s = purple_strcasestr(header, "Content-Length: ")) != NULL)
-	{
-		size_t tmp_len;
-
-		s += strlen("Content-Length: ");
-
-		if ((c = strchr(s, '\r')) == NULL)
-		{
-			g_free(header);
-
-			return FALSE;
-		}
-
-		tmp = g_strndup(s, c - s);
-		tmp_len = atoi(tmp);
-		g_free(tmp);
-
-		if (body_len != tmp_len)
-		{
-			/* Need to wait for the full packet to arrive */
-
-			g_free(header);
-
-#if 0
-			purple_debug_warning("msn",
-							   "body length (%d) != content length (%d)\n",
-							   body_len, tmp_len);
-#endif
-
-			return FALSE;
-		}
-	}
-
-	body = g_malloc(body_len + 1);
-	memcpy(body, body_start, body_len);
-	body[body_len] = '\0';
-
-	if (purple_debug_is_verbose())
-		purple_debug_misc("msn", "Incoming HTTP buffer (header): {%s}\n",
-		                  header);
-
-	/* Now we should be able to process the data. */
-	if ((s = purple_strcasestr(header, "X-MSN-Messenger: ")) != NULL)
-	{
-		gchar *full_session_id = NULL, *gw_ip = NULL, *session_action = NULL;
-		char *t, *session_id;
-		char **elems, **cur, **tokens;
-
-		full_session_id = gw_ip = session_action = NULL;
-
-		s += strlen("X-MSN-Messenger: ");
-
-		if ((c = strchr(s, '\r')) == NULL)
-		{
-			msn_session_set_error(httpconn->session,
-								  MSN_ERROR_HTTP_MALFORMED, NULL);
-			purple_debug_error("msn", "Malformed X-MSN-Messenger field.\n{%s}\n",
-							 buf);
-
-			g_free(header);
-			g_free(body);
-			return FALSE;
-		}
-
-		tmp = g_strndup(s, c - s);
-
-		elems = g_strsplit(tmp, "; ", 0);
-
-		for (cur = elems; *cur != NULL; cur++)
-		{
-			tokens = g_strsplit(*cur, "=", 2);
-
-			if (strcmp(tokens[0], "SessionID") == 0) {
-				g_free(full_session_id);
-				full_session_id = tokens[1];
-			} else if (strcmp(tokens[0], "GW-IP") == 0) {
-				g_free(gw_ip);
-				gw_ip = tokens[1];
-			} else if (strcmp(tokens[0], "Session") == 0) {
-				g_free(session_action);
-				session_action = tokens[1];
-			} else
-				g_free(tokens[1]);
-
-			g_free(tokens[0]);
-			/* Don't free each of the tokens, only the array. */
-			g_free(tokens);
-		}
-
-		g_strfreev(elems);
-
-		g_free(tmp);
-
-		t = full_session_id ? strchr(full_session_id, '.') : NULL;
-		if (t != NULL)
-			session_id = g_strndup(full_session_id, t - full_session_id);
-		else {
-			purple_debug_error("msn", "Malformed full_session_id[%s]\n",
-					   full_session_id ? full_session_id : NULL);
-			session_id = g_strdup(full_session_id);
-		}
-
-		if (session_action == NULL || strcmp(session_action, "close") != 0)
-		{
-			g_free(httpconn->full_session_id);
-			httpconn->full_session_id = full_session_id;
-
-			g_free(httpconn->session_id);
-			httpconn->session_id = session_id;
-
-			g_free(httpconn->host);
-			httpconn->host = gw_ip;
-		}
-		else
-		{
-			/* I'll be honest, I don't fully understand all this, but this
-			 * causes crashes, Stu. */
-#if 0
-			MsnServConn *servconn;
-
-			/* It's going to die. */
-			/* poor thing */
-
-			servconn = httpconn->servconn;
-
-			if (servconn != NULL)
-				servconn->wasted = TRUE;
-#endif
-
-			g_free(full_session_id);
-			g_free(session_id);
-			g_free(gw_ip);
-		}
-
-		g_free(session_action);
-	}
-
-	g_free(header);
-
-	*ret_buf  = body;
-	*ret_size = body_len;
-
-	msn_httpconn_process_queue(httpconn);
-
-	return TRUE;
-}
-
-static void
-read_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
-	MsnHttpConn *httpconn;
-	MsnServConn *servconn;
-	char buf[MSN_BUF_LEN];
-	gssize len;
-	char *result_msg = NULL;
-	size_t result_len = 0;
-	gboolean error = FALSE;
-
-	httpconn = data;
-	servconn = httpconn->servconn;
-
-	if (servconn->type == MSN_SERVCONN_NS)
-		servconn->session->account->gc->last_received = time(NULL);
-
-	len = read(httpconn->fd, buf, sizeof(buf) - 1);
-	if (len < 0 && errno == EAGAIN)
-		return;
-	if (len <= 0) {
-		purple_debug_error("msn", "HTTP: servconn %03d read error, "
-			"len: %" G_GSSIZE_FORMAT ", errno: %d, error: %s\n",
-			servconn->num, len, error, g_strerror(errno));
-		msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ, NULL);
-
-		return;
-	}
-
-	buf[len] = '\0';
-
-	httpconn->rx_buf = g_realloc(httpconn->rx_buf, len + httpconn->rx_len + 1);
-	memcpy(httpconn->rx_buf + httpconn->rx_len, buf, len + 1);
-	httpconn->rx_len += len;
-
-	if (!msn_httpconn_parse_data(httpconn, httpconn->rx_buf, httpconn->rx_len,
-								 &result_msg, &result_len, &error))
-	{
-		/* Either we must wait for more input, or something went wrong */
-		if (error)
-			msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ, NULL);
-
-		return;
-	}
-
-	if (error)
-	{
-		purple_debug_error("msn", "HTTP: Special error\n");
-		msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ, NULL);
-
-		return;
-	}
-
-	g_free(httpconn->rx_buf);
-	httpconn->rx_buf = NULL;
-	httpconn->rx_len = 0;
-
-	if (result_len == 0)
-	{
-		/* Nothing to do here */
-#if 0
-		purple_debug_info("msn", "HTTP: nothing to do here\n");
-#endif
-		g_free(result_msg);
-		return;
-	}
-
-	g_free(servconn->rx_buf);
-	servconn->rx_buf = result_msg;
-	servconn->rx_len = result_len;
-
-	msn_servconn_process_data(servconn);
-}
-
-static void
-httpconn_write_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
-	MsnHttpConn *httpconn;
-	gssize ret;
-	int writelen;
-
-	httpconn = data;
-	writelen = purple_circ_buffer_get_max_read(httpconn->tx_buf);
-
-	if (writelen == 0)
-	{
-		purple_input_remove(httpconn->tx_handler);
-		httpconn->tx_handler = 0;
-		return;
-	}
-
-	ret = write(httpconn->fd, httpconn->tx_buf->outptr, writelen);
-	if (ret <= 0)
-	{
-		if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-			/* No worries */
-			return;
-
-		/* Error! */
-		msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_WRITE, NULL);
-		return;
-	}
-
-	purple_circ_buffer_mark_read(httpconn->tx_buf, ret);
-
-	/* TODO: I don't think these 2 lines are needed.  Remove them? */
-	if (ret == writelen)
-		httpconn_write_cb(data, source, cond);
-}
-
-static gboolean
-write_raw(MsnHttpConn *httpconn, const char *data, size_t data_len)
-{
-	gssize res; /* result of the write operation */
-
-	if (httpconn->tx_handler == 0)
-		res = write(httpconn->fd, data, data_len);
-	else
-	{
-		res = -1;
-		errno = EAGAIN;
-	}
-
-	if ((res <= 0) && ((errno != EAGAIN) && (errno != EWOULDBLOCK)))
-	{
-		msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_WRITE, NULL);
-		return FALSE;
-	}
-
-	if (res < 0 || (size_t)res < data_len)
-	{
-		if (res < 0)
-			res = 0;
-		if (httpconn->tx_handler == 0 && httpconn->fd)
-			httpconn->tx_handler = purple_input_add(httpconn->fd,
-				PURPLE_INPUT_WRITE, httpconn_write_cb, httpconn);
-		purple_circ_buffer_append(httpconn->tx_buf, data + res,
-			data_len - res);
-	}
-
-	return TRUE;
-}
-
-static char *
-msn_httpconn_proxy_auth(MsnHttpConn *httpconn)
-{
-	PurpleAccount *account;
-	PurpleProxyInfo *gpi;
-	const char *username, *password;
-	char *auth = NULL;
-
-	account = httpconn->session->account;
-
-	gpi = purple_proxy_get_setup(account);
-
-	if (gpi == NULL || !(purple_proxy_info_get_type(gpi) == PURPLE_PROXY_HTTP ||
-						 purple_proxy_info_get_type(gpi) == PURPLE_PROXY_USE_ENVVAR))
-		return NULL;
-
-	username = purple_proxy_info_get_username(gpi);
-	password = purple_proxy_info_get_password(gpi);
-
-	if (username != NULL) {
-		char *tmp;
-		auth = g_strdup_printf("%s:%s", username, password ? password : "");
-		tmp = purple_base64_encode((const guchar *)auth, strlen(auth));
-		g_free(auth);
-		auth = g_strdup_printf("Proxy-Authorization: Basic %s\r\n", tmp);
-		g_free(tmp);
-	}
-
-	return auth;
-}
-
-static gboolean
-msn_httpconn_poll(gpointer data)
-{
-	MsnHttpConn *httpconn;
-	char *header;
-	char *auth;
-
-	httpconn = data;
-
-	g_return_val_if_fail(httpconn != NULL, FALSE);
-
-	if ((httpconn->host == NULL) || (httpconn->full_session_id == NULL))
-	{
-		/* There's no need to poll if the session is not fully established */
-		return TRUE;
-	}
-
-	if (httpconn->waiting_response)
-	{
-		/* There's no need to poll if we're already waiting for a response */
-		return TRUE;
-	}
-
-	auth = msn_httpconn_proxy_auth(httpconn);
-
-	header = g_strdup_printf(
-		"POST http://%s/gateway/gateway.dll?Action=poll&SessionID=%s HTTP/1.1\r\n"
-		"Accept: */*\r\n"
-		"Accept-Language: en-us\r\n"
-		"User-Agent: MSMSGS\r\n"
-		"Host: %s\r\n"
-		"Proxy-Connection: Keep-Alive\r\n"
-		"%s" /* Proxy auth */
-		"Connection: Keep-Alive\r\n"
-		"Pragma: no-cache\r\n"
-		"Content-Type: application/x-msn-messenger\r\n"
-		"Content-Length: 0\r\n\r\n",
-		httpconn->host,
-		httpconn->full_session_id,
-		httpconn->host,
-		auth ? auth : "");
-
-	g_free(auth);
-
-	if (write_raw(httpconn, header, strlen(header)))
-		httpconn->waiting_response = TRUE;
-
-	g_free(header);
-
-	return TRUE;
-}
-
-gssize
-msn_httpconn_write(MsnHttpConn *httpconn, const char *body, size_t body_len)
-{
-	char *params;
-	char *data;
-	int header_len;
-	char *auth;
-	const char *server_types[] = { "NS", "SB" };
-	const char *server_type;
-	char *host;
-	MsnServConn *servconn;
-
-	/* TODO: remove http data from servconn */
-
-	g_return_val_if_fail(httpconn != NULL, 0);
-	g_return_val_if_fail(body != NULL, 0);
-	g_return_val_if_fail(body_len > 0, 0);
-
-	servconn = httpconn->servconn;
-
-	if (httpconn->waiting_response)
-	{
-		MsnHttpQueueData *queue_data = g_new0(MsnHttpQueueData, 1);
-
-		queue_data->httpconn = httpconn;
-		queue_data->body     = g_memdup(body, body_len);
-		queue_data->body_len = body_len;
-
-		httpconn->queue = g_list_append(httpconn->queue, queue_data);
-
-		return body_len;
-	}
-
-	server_type = server_types[servconn->type];
-
-	if (httpconn->virgin)
-	{
-		/* QuLogic: This doesn't look right to me, but it still seems to work */
-		host = MSN_HTTPCONN_SERVER;
-
-		/* The first time servconn->host is the host we should connect to. */
-		params = g_strdup_printf("Action=open&Server=%s&IP=%s",
-								 server_type,
-								 servconn->host);
-		httpconn->virgin = FALSE;
-	}
-	else
-	{
-		/* The rest of the times servconn->host is the gateway host. */
-		host = httpconn->host;
-
-		if (host == NULL || httpconn->full_session_id == NULL)
-		{
-			purple_debug_warning("msn", "Attempted HTTP write before session is established\n");
-			return -1;
-		}
-
-		params = g_strdup_printf("SessionID=%s",
-			httpconn->full_session_id);
-	}
-
-	auth = msn_httpconn_proxy_auth(httpconn);
-
-	data = g_strdup_printf(
-		"POST http://%s/gateway/gateway.dll?%s HTTP/1.1\r\n"
-		"Accept: */*\r\n"
-		"Accept-Language: en-us\r\n"
-		"User-Agent: MSMSGS\r\n"
-		"Host: %s\r\n"
-		"Proxy-Connection: Keep-Alive\r\n"
-		"%s" /* Proxy auth */
-		"Connection: Keep-Alive\r\n"
-		"Pragma: no-cache\r\n"
-		"Content-Type: application/x-msn-messenger\r\n"
-		"Content-Length: %d\r\n\r\n",
-		host,
-		params,
-		host,
-		auth ? auth : "",
-		(int) body_len);
-
-	g_free(params);
-
-	g_free(auth);
-
-	header_len = strlen(data);
-	data = g_realloc(data, header_len + body_len);
-	memcpy(data + header_len, body, body_len);
-
-	if (write_raw(httpconn, data, header_len + body_len))
-		httpconn->waiting_response = TRUE;
-
-	g_free(data);
-
-	return body_len;
-}
-
-MsnHttpConn *
-msn_httpconn_new(MsnServConn *servconn)
-{
-	MsnHttpConn *httpconn;
-
-	g_return_val_if_fail(servconn != NULL, NULL);
-
-	httpconn = g_new0(MsnHttpConn, 1);
-
-	purple_debug_info("msn", "new httpconn (%p)\n", httpconn);
-
-	/* TODO: Remove this */
-	httpconn->session = servconn->session;
-
-	httpconn->servconn = servconn;
-
-	httpconn->tx_buf = purple_circ_buffer_new(MSN_BUF_LEN);
-	httpconn->tx_handler = 0;
-
-	httpconn->fd = -1;
-
-	return httpconn;
-}
-
-void
-msn_httpconn_destroy(MsnHttpConn *httpconn)
-{
-	g_return_if_fail(httpconn != NULL);
-
-	purple_debug_info("msn", "destroy httpconn (%p)\n", httpconn);
-
-	if (httpconn->connected)
-		msn_httpconn_disconnect(httpconn);
-
-	g_free(httpconn->full_session_id);
-
-	g_free(httpconn->session_id);
-
-	g_free(httpconn->host);
-
-	while (httpconn->queue != NULL) {
-		MsnHttpQueueData *queue_data;
-
-		queue_data = (MsnHttpQueueData *) httpconn->queue->data;
-
-		httpconn->queue = g_list_delete_link(httpconn->queue, httpconn->queue);
-
-		g_free(queue_data->body);
-		g_free(queue_data);
-	}
-
-	purple_circ_buffer_destroy(httpconn->tx_buf);
-	if (httpconn->tx_handler > 0)
-		purple_input_remove(httpconn->tx_handler);
-
-	g_free(httpconn);
-}
-
-static void
-connect_cb(gpointer data, gint source, const gchar *error_message)
-{
-	MsnHttpConn *httpconn;
-
-	httpconn = data;
-	httpconn->connect_data = NULL;
-	httpconn->fd = source;
-
-	if (source >= 0)
-	{
-		httpconn->inpa = purple_input_add(httpconn->fd, PURPLE_INPUT_READ,
-			read_cb, data);
-
-		httpconn->timer = purple_timeout_add_seconds(2, msn_httpconn_poll, httpconn);
-
-		msn_httpconn_process_queue(httpconn);
-	}
-	else
-	{
-		purple_debug_error("msn", "HTTP: Connection error: %s\n",
-		                   error_message ? error_message : "(null)");
-		msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_CONNECT, error_message);
-	}
-}
-
-gboolean
-msn_httpconn_connect(MsnHttpConn *httpconn, const char *host, int port)
-{
-	g_return_val_if_fail(httpconn != NULL, FALSE);
-	g_return_val_if_fail(host     != NULL, FALSE);
-	g_return_val_if_fail(port      > 0,    FALSE);
-
-	if (httpconn->connected)
-		msn_httpconn_disconnect(httpconn);
-
-	httpconn->connect_data = purple_proxy_connect(NULL, httpconn->session->account,
-		host, 80, connect_cb, httpconn);
-
-	if (httpconn->connect_data != NULL)
-	{
-		httpconn->waiting_response = TRUE;
-		httpconn->connected = TRUE;
-	}
-
-	return httpconn->connected;
-}
-
-void
-msn_httpconn_disconnect(MsnHttpConn *httpconn)
-{
-	g_return_if_fail(httpconn != NULL);
-
-	if (!httpconn->connected)
-		return;
-
-	if (httpconn->connect_data != NULL)
-	{
-		purple_proxy_connect_cancel(httpconn->connect_data);
-		httpconn->connect_data = NULL;
-	}
-
-	if (httpconn->timer)
-	{
-		purple_timeout_remove(httpconn->timer);
-		httpconn->timer = 0;
-	}
-
-	if (httpconn->inpa > 0)
-	{
-		purple_input_remove(httpconn->inpa);
-		httpconn->inpa = 0;
-	}
-
-	close(httpconn->fd);
-	httpconn->fd = -1;
-
-	g_free(httpconn->rx_buf);
-	httpconn->rx_buf = NULL;
-	httpconn->rx_len = 0;
-
-	httpconn->connected = FALSE;
-
-	/* msn_servconn_disconnect(httpconn->servconn); */
-}
--- a/libpurple/protocols/msn/httpconn.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/**
- * @file httpconn.h HTTP connection
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_HTTPCONN_H
-#define MSN_HTTPCONN_H
-
-typedef struct _MsnHttpConn MsnHttpConn;
-
-#include "circbuffer.h"
-#include "servconn.h"
-#include "session.h"
-
-/**
- * An HTTP Connection.
- */
-struct _MsnHttpConn
-{
-	MsnSession *session; /**< The MSN Session. */
-	MsnServConn *servconn; /**< The connection object. */
-
-	PurpleProxyConnectData *connect_data;
-
-	char *full_session_id; /**< The full session id. */
-	char *session_id; /**< The trimmed session id. */
-
-	int timer; /**< The timer for polling. */
-
-	gboolean waiting_response; /**< The flag that states if we are waiting
-								 a response from the server. */
-	gboolean connected;        /**< The flag that states if the connection is on. */
-	gboolean virgin;           /**< The flag that states if this connection
-								 should specify the host (not gateway) to
-								 connect to. */
-
-	char *host; /**< The HTTP gateway host. */
-	GList *queue; /**< The queue of data chunks to write. */
-
-	int fd; /**< The connection's file descriptor. */
-	guint inpa; /**< The connection's input handler. */
-
-	char *rx_buf; /**< The receive buffer. */
-	int rx_len; /**< The receive buffer length. */
-
-	PurpleCircBuffer *tx_buf;
-	guint tx_handler;
-};
-
-/**
- * Creates a new HTTP connection object.
- *
- * @param servconn The connection object.
- *
- * @return The new object.
- */
-MsnHttpConn *msn_httpconn_new(MsnServConn *servconn);
-
-/**
- * Destroys an HTTP connection object.
- *
- * @param httpconn The HTTP connection object.
- */
-void msn_httpconn_destroy(MsnHttpConn *httpconn);
-
-/**
- * Writes a chunk of data to the HTTP connection.
- *
- * @param servconn    The server connection.
- * @param data        The data to write.
- * @param data_len    The size of the data to write.
- *
- * @return The number of bytes written.
- */
-gssize msn_httpconn_write(MsnHttpConn *httpconn, const char *data, size_t data_len);
-
-/**
- * Connects the HTTP connection object to a host.
- *
- * @param httpconn The HTTP connection object.
- * @param host The host to connect to.
- * @param port The port to connect to.
- */
-gboolean msn_httpconn_connect(MsnHttpConn *httpconn,
-							  const char *host, int port);
-
-/**
- * Disconnects the HTTP connection object.
- *
- * @param httpconn The HTTP connection object.
- */
-void msn_httpconn_disconnect(MsnHttpConn *httpconn);
-
-#endif /* MSN_HTTPCONN_H */
--- a/libpurple/protocols/msn/msg.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1217 +0,0 @@
-/**
- * @file msg.c Message functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-
-#include "msn.h"
-#include "msg.h"
-#include "msnutils.h"
-#include "slpmsg.h"
-#include "slpmsg_part.h"
-
-MsnMessage *
-msn_message_new(MsnMsgType type)
-{
-	MsnMessage *msg;
-
-	msg = g_new0(MsnMessage, 1);
-	msg->type = type;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "message new (%p)(%d)\n", msg, type);
-
-	msg->header_table = g_hash_table_new_full(g_str_hash, g_str_equal,
-											g_free, g_free);
-
-	msn_message_ref(msg);
-
-	return msg;
-}
-
-/**
- * Destroys a message.
- *
- * @param msg The message to destroy.
- */
-static void
-msn_message_destroy(MsnMessage *msg)
-{
-	g_return_if_fail(msg != NULL);
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "message destroy (%p)\n", msg);
-
-	g_free(msg->remote_user);
-	g_free(msg->body);
-	g_free(msg->content_type);
-	g_free(msg->charset);
-
-	g_hash_table_destroy(msg->header_table);
-	g_list_free(msg->header_list);
-	if (msg->part)
-		msn_slpmsgpart_unref(msg->part);
-
-	g_free(msg);
-}
-
-MsnMessage *
-msn_message_ref(MsnMessage *msg)
-{
-	g_return_val_if_fail(msg != NULL, NULL);
-
-	msg->ref_count++;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "message ref (%p)[%u]\n", msg, msg->ref_count);
-
-	return msg;
-}
-
-void
-msn_message_unref(MsnMessage *msg)
-{
-	g_return_if_fail(msg != NULL);
-	g_return_if_fail(msg->ref_count > 0);
-
-	msg->ref_count--;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "message unref (%p)[%u]\n", msg, msg->ref_count);
-
-	if (msg->ref_count == 0)
-		msn_message_destroy(msg);
-}
-
-MsnMessage *
-msn_message_new_plain(const char *message)
-{
-	MsnMessage *msg;
-	char *message_cr;
-
-	msg = msn_message_new(MSN_MSG_TEXT);
-	msg->retries = 1;
-	msn_message_set_header(msg, "User-Agent", PACKAGE_NAME "/" VERSION);
-	msn_message_set_content_type(msg, "text/plain");
-	msn_message_set_charset(msg, "UTF-8");
-	msn_message_set_flag(msg, 'A');
-	msn_message_set_header(msg, "X-MMS-IM-Format",
-						 "FN=Segoe%20UI; EF=; CO=0; CS=1;PF=0");
-
-	message_cr = purple_str_add_cr(message);
-	msn_message_set_bin_data(msg, message_cr, strlen(message_cr));
-	g_free(message_cr);
-
-	return msg;
-}
-
-MsnMessage *
-msn_message_new_msnslp(void)
-{
-	MsnMessage *msg;
-
-	msg = msn_message_new(MSN_MSG_SLP);
-
-	msn_message_set_header(msg, "User-Agent", NULL);
-
-	msn_message_set_flag(msg, 'D');
-	msn_message_set_content_type(msg, "application/x-msnmsgrp2p");
-
-	return msg;
-}
-
-MsnMessage *
-msn_message_new_nudge(void)
-{
-	MsnMessage *msg;
-
-	msg = msn_message_new(MSN_MSG_NUDGE);
-	msn_message_set_content_type(msg, "text/x-msnmsgr-datacast");
-	msn_message_set_flag(msg, 'N');
-	msn_message_set_bin_data(msg, "ID: 1\r\n", 7);
-
-	return msg;
-}
-
-void
-msn_message_parse_payload(MsnMessage *msg,
-						  const char *payload, size_t payload_len,
-						  const char *line_dem,const char *body_dem)
-{
-	char *tmp_base, *tmp;
-	const char *content_type;
-	char *end;
-	char **elems, **cur, **tokens;
-
-	g_return_if_fail(payload != NULL);
-	tmp_base = tmp = g_malloc(payload_len + 1);
-	memcpy(tmp_base, payload, payload_len);
-	tmp_base[payload_len] = '\0';
-
-	/* Find the end of the headers */
-	end = strstr(tmp, body_dem);
-	/* TODO? some clients use \r delimiters instead of \r\n, the official client
-	 * doesn't send such messages, but does handle receiving them. We'll just
-	 * avoid crashing for now */
-	if (end == NULL) {
-		g_free(tmp_base);
-		g_return_if_reached();
-	}
-
-	/* NUL-terminate the end of the headers - it'll get skipped over below */
-	*end = '\0';
-
-	/* Split the headers and parse each one */
-	elems = g_strsplit(tmp, line_dem, 0);
-	for (cur = elems; *cur != NULL; cur++)
-	{
-		const char *key, *value;
-
-		/* If this line starts with whitespace, it's been folded from the
-		   previous line and won't have ':'. */
-		if ((**cur == ' ') || (**cur == '\t')) {
-			tokens = g_strsplit(g_strchug(*cur), "=\"", 2);
-			key = tokens[0];
-			value = tokens[1];
-
-			/* The only one I care about is 'boundary' (which is folded from
-			   the key 'Content-Type'), so only process that. */
-			if (!strcmp(key, "boundary") && value) {
-				char *end = strchr(value, '\"');
-				if (end) {
-					*end = '\0';
-					msn_message_set_header(msg, key, value);
-				}
-			}
-
-			g_strfreev(tokens);
-			continue;
-		}
-
-		tokens = g_strsplit(*cur, ": ", 2);
-
-		key = tokens[0];
-		value = tokens[1];
-
-		if (!strcmp(key, "MIME-Version"))
-		{
-			/* Ignore MIME-Version header */
-		}
-		else if (!strcmp(key, "Content-Type"))
-		{
-			char *charset, *c;
-
-			if (value && (c = strchr(value, ';')) != NULL)
-			{
-				if ((charset = strchr(c, '=')) != NULL)
-				{
-					charset++;
-					msn_message_set_charset(msg, charset);
-				}
-
-				*c = '\0';
-			}
-
-			msn_message_set_content_type(msg, value);
-		}
-		else
-		{
-			msn_message_set_header(msg, key, value);
-		}
-
-		g_strfreev(tokens);
-	}
-	g_strfreev(elems);
-
-	/* Proceed to the end of the "\r\n\r\n" */
-	tmp = end + strlen(body_dem);
-
-	/* Now we *should* be at the body. */
-	content_type = msn_message_get_content_type(msg);
-
-	if (payload_len - (tmp - tmp_base) > 0) {
-		msg->body_len = payload_len - (tmp - tmp_base);
-		g_free(msg->body);
-		msg->body = g_malloc(msg->body_len + 1);
-		memcpy(msg->body, tmp, msg->body_len);
-		msg->body[msg->body_len] = '\0';
-	}
-
-	if (msg->body && content_type && purple_str_has_prefix(content_type, "text/")) {
-		char *body = NULL;
-
-		if (msg->charset == NULL || g_str_equal(msg->charset, "UTF-8")) {
-			/* Charset is UTF-8 */
-			if (!g_utf8_validate(msg->body, msg->body_len, NULL)) {
-				purple_debug_warning("msn", "Message contains invalid "
-						"UTF-8. Attempting to salvage.\n");
-				body = purple_utf8_salvage(msg->body);
-				payload_len = strlen(body);
-			}
-		} else {
-			/* Charset is something other than UTF-8 */
-			GError *err = NULL;
-			body = g_convert(msg->body, msg->body_len, "UTF-8",
-					msg->charset, NULL, &payload_len, &err);
-			if (!body || err) {
-				purple_debug_warning("msn", "Unable to convert message from "
-						"%s to UTF-8: %s\n", msg->charset,
-						err ? err->message : "Unknown error");
-				if (err)
-					g_error_free(err);
-
-				/* Fallback to ISO-8859-1 */
-				g_free(body);
-				body = g_convert(msg->body, msg->body_len, "UTF-8",
-						"ISO-8859-1", NULL, &payload_len, NULL);
-				if (!body) {
-					g_free(msg->body);
-					msg->body = NULL;
-					msg->body_len = 0;
-				}
-			}
-		}
-
-		if (body) {
-			g_free(msg->body);
-			msg->body = body;
-			msg->body_len = payload_len;
-			msn_message_set_charset(msg, "UTF-8");
-		}
-	}
-
-	g_free(tmp_base);
-}
-
-MsnMessage *
-msn_message_new_from_cmd(MsnSession *session, MsnCommand *cmd)
-{
-	MsnMessage *msg;
-
-	g_return_val_if_fail(cmd != NULL, NULL);
-
-	msg = msn_message_new(MSN_MSG_UNKNOWN);
-
-	msg->remote_user = g_strdup(cmd->params[0]);
-	/* msg->size = atoi(cmd->params[2]); */
-	msg->cmd = cmd;
-
-	return msg;
-}
-
-char *
-msn_message_gen_payload(MsnMessage *msg, size_t *ret_size)
-{
-	GList *l;
-	char *n, *base, *end;
-	int len;
-	size_t body_len = 0;
-	const void *body;
-
-	g_return_val_if_fail(msg != NULL, NULL);
-
-	len = MSN_BUF_LEN;
-
-	base = n = end = g_malloc(len + 1);
-	end += len;
-
-	/* Standard header. */
-	if (msg->charset == NULL)
-	{
-		g_snprintf(n, len,
-				   "MIME-Version: 1.0\r\n"
-				   "Content-Type: %s\r\n",
-				   msg->content_type);
-	}
-	else
-	{
-		g_snprintf(n, len,
-				   "MIME-Version: 1.0\r\n"
-				   "Content-Type: %s; charset=%s\r\n",
-				   msg->content_type, msg->charset);
-	}
-
-	n += strlen(n);
-
-	for (l = msg->header_list; l != NULL; l = l->next)
-	{
-		const char *key;
-		const char *value;
-
-		key = l->data;
-		value = msn_message_get_header_value(msg, key);
-
-		g_snprintf(n, end - n, "%s: %s\r\n", key, value);
-		n += strlen(n);
-	}
-
-	if ((end - n) > 2)
-		n += g_strlcpy(n, "\r\n", end - n);
-
-	body = msn_message_get_bin_data(msg, &body_len);
-
-	if (body != NULL && (end - n) > (gssize)body_len)
-	{
-		memcpy(n, body, body_len);
-		n += body_len;
-		*n = '\0';
-	}
-
-	if (ret_size != NULL)
-	{
-		*ret_size = n - base;
-
-		if (*ret_size > 1664)
-			*ret_size = 1664;
-	}
-
-	return base;
-}
-
-void
-msn_message_set_flag(MsnMessage *msg, char flag)
-{
-	g_return_if_fail(msg != NULL);
-	g_return_if_fail(flag != 0);
-
-	msg->flag = flag;
-}
-
-char
-msn_message_get_flag(const MsnMessage *msg)
-{
-	g_return_val_if_fail(msg != NULL, 0);
-
-	return msg->flag;
-}
-
-void
-msn_message_set_bin_data(MsnMessage *msg, const void *data, size_t len)
-{
-	g_return_if_fail(msg != NULL);
-
-	/* There is no need to waste memory on data we cannot send anyway */
-	if (len > 1664)
-		len = 1664;
-
-	if (msg->body != NULL)
-		g_free(msg->body);
-
-	if (data != NULL && len > 0)
-	{
-		msg->body = g_malloc(len + 1);
-		memcpy(msg->body, data, len);
-		msg->body[len] = '\0';
-		msg->body_len = len;
-	}
-	else
-	{
-		msg->body = NULL;
-		msg->body_len = 0;
-	}
-}
-
-const void *
-msn_message_get_bin_data(const MsnMessage *msg, size_t *len)
-{
-	g_return_val_if_fail(msg != NULL, NULL);
-
-	if (len)
-		*len = msg->body_len;
-
-	return msg->body;
-}
-
-void
-msn_message_set_content_type(MsnMessage *msg, const char *type)
-{
-	g_return_if_fail(msg != NULL);
-
-	g_free(msg->content_type);
-	msg->content_type = g_strdup(type);
-}
-
-const char *
-msn_message_get_content_type(const MsnMessage *msg)
-{
-	g_return_val_if_fail(msg != NULL, NULL);
-
-	return msg->content_type;
-}
-
-void
-msn_message_set_charset(MsnMessage *msg, const char *charset)
-{
-	g_return_if_fail(msg != NULL);
-
-	g_free(msg->charset);
-	msg->charset = g_strdup(charset);
-}
-
-const char *
-msn_message_get_charset(const MsnMessage *msg)
-{
-	g_return_val_if_fail(msg != NULL, NULL);
-
-	return msg->charset;
-}
-
-void
-msn_message_set_header(MsnMessage *msg, const char *name, const char *value)
-{
-	const char *temp;
-	char *new_name;
-
-	g_return_if_fail(msg != NULL);
-	g_return_if_fail(name != NULL);
-
-	temp = msn_message_get_header_value(msg, name);
-
-	if (value == NULL)
-	{
-		if (temp != NULL)
-		{
-			GList *l;
-
-			for (l = msg->header_list; l != NULL; l = l->next)
-			{
-				if (!g_ascii_strcasecmp(l->data, name))
-				{
-					msg->header_list = g_list_remove(msg->header_list, l->data);
-
-					break;
-				}
-			}
-
-			g_hash_table_remove(msg->header_table, name);
-		}
-
-		return;
-	}
-
-	new_name = g_strdup(name);
-
-	g_hash_table_insert(msg->header_table, new_name, g_strdup(value));
-
-	if (temp == NULL)
-		msg->header_list = g_list_append(msg->header_list, new_name);
-}
-
-const char *
-msn_message_get_header_value(const MsnMessage *msg, const char *name)
-{
-	g_return_val_if_fail(msg != NULL, NULL);
-	g_return_val_if_fail(name != NULL, NULL);
-
-	return g_hash_table_lookup(msg->header_table, name);
-}
-
-GHashTable *
-msn_message_get_hashtable_from_body(const MsnMessage *msg)
-{
-	GHashTable *table;
-	size_t body_len;
-	const char *body;
-	char **elems, **cur, **tokens, *body_str;
-
-	g_return_val_if_fail(msg != NULL, NULL);
-
-	table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-
-	body = msn_message_get_bin_data(msg, &body_len);
-
-	g_return_val_if_fail(body != NULL, NULL);
-
-	body_str = g_strndup(body, body_len);
-	elems = g_strsplit(body_str, "\r\n", 0);
-	g_free(body_str);
-
-	for (cur = elems; *cur != NULL; cur++)
-	{
-		if (**cur == '\0')
-			break;
-
-		tokens = g_strsplit(*cur, ": ", 2);
-
-		if (tokens[0] != NULL && tokens[1] != NULL) {
-			g_hash_table_insert(table, tokens[0], tokens[1]);
-			g_free(tokens);
-		} else
-			g_strfreev(tokens);
-	}
-
-	g_strfreev(elems);
-
-	return table;
-}
-
-char *
-msn_message_to_string(MsnMessage *msg)
-{
-	size_t body_len;
-	const char *body;
-
-	g_return_val_if_fail(msg != NULL, NULL);
-	g_return_val_if_fail(msg->type == MSN_MSG_TEXT, NULL);
-
-	body = msn_message_get_bin_data(msg, &body_len);
-
-	return g_strndup(body, body_len);
-}
-
-void
-msn_message_show_readable(MsnMessage *msg, const char *info,
-						  gboolean text_body)
-{
-	GString *str;
-	size_t body_len;
-	const char *body;
-	GList *l;
-
-	g_return_if_fail(msg != NULL);
-
-	str = g_string_new(NULL);
-
-	/* Standard header. */
-	if (msg->charset == NULL)
-	{
-		g_string_append_printf(str,
-				   "MIME-Version: 1.0\r\n"
-				   "Content-Type: %s\r\n",
-				   msg->content_type);
-	}
-	else
-	{
-		g_string_append_printf(str,
-				   "MIME-Version: 1.0\r\n"
-				   "Content-Type: %s; charset=%s\r\n",
-				   msg->content_type, msg->charset);
-	}
-
-	for (l = msg->header_list; l; l = l->next)
-	{
-		char *key;
-		const char *value;
-
-		key = l->data;
-		value = msn_message_get_header_value(msg, key);
-
-		g_string_append_printf(str, "%s: %s\r\n", key, value);
-	}
-
-	g_string_append(str, "\r\n");
-
-	body = msn_message_get_bin_data(msg, &body_len);
-
-	if (body != NULL)
-	{
-		if (msg->type == MSN_MSG_TEXT)
-		{
-			g_string_append_len(str, body, body_len);
-			g_string_append(str, "\r\n");
-		}
-		else
-		{
-			size_t i;
-			for (i = 0; i < body_len; i++, body++)
-			{
-				g_string_append_printf(str, "%02x ", (unsigned char)*body);
-				if (i % 16 == 0 && i != 0)
-					g_string_append_c(str, '\n');
-			}
-			g_string_append_c(str, '\n');
-		}
-	}
-
-	purple_debug_info("msn", "Message %s:\n{%s}\n", info, str->str);
-
-	g_string_free(str, TRUE);
-}
-
-/**************************************************************************
- * Message Handlers
- **************************************************************************/
-void
-msn_plain_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	PurpleConnection *gc;
-	const char *body;
-	char *body_enc;
-	char *body_final;
-	size_t body_len;
-	const char *passport;
-	const char *value;
-
-	gc = cmdproc->session->account->gc;
-
-	body = msn_message_get_bin_data(msg, &body_len);
-	body_enc = g_markup_escape_text(body, body_len);
-
-	passport = msg->remote_user;
-
-	if (!strcmp(passport, "messenger@microsoft.com") &&
-		strstr(body, "immediate security update"))
-	{
-		return;
-	}
-
-#if 0
-	if ((value = msn_message_get_header_value(msg, "User-Agent")) != NULL)
-	{
-		purple_debug_misc("msn", "User-Agent = '%s'\n", value);
-	}
-#endif
-
-	if ((value = msn_message_get_header_value(msg, "X-MMS-IM-Format")) != NULL)
-	{
-		char *pre, *post;
-
-		msn_parse_format(value, &pre, &post);
-
-		body_final = g_strdup_printf("%s%s%s", pre ? pre : "",
-									 body_enc ? body_enc : "", post ? post : "");
-
-		g_free(pre);
-		g_free(post);
-		g_free(body_enc);
-	}
-	else
-	{
-		body_final = body_enc;
-	}
-
-	if (cmdproc->servconn->type == MSN_SERVCONN_SB) {
-		MsnSwitchBoard *swboard = cmdproc->data;
-
-		swboard->flag |= MSN_SB_FLAG_IM;
-
-		if (swboard->current_users > 1 ||
-			((swboard->conv != NULL) &&
-			 purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
-		{
-			/* If current_users is always ok as it should then there is no need to
-			 * check if this is a chat. */
-			if (swboard->current_users <= 1)
-				purple_debug_misc("msn", "plain_msg: current_users(%d)\n",
-								swboard->current_users);
-
-			serv_got_chat_in(gc, swboard->chat_id, passport, 0, body_final,
-							 time(NULL));
-			if (swboard->conv == NULL)
-			{
-				swboard->conv = purple_find_chat(gc, swboard->chat_id);
-				swboard->flag |= MSN_SB_FLAG_IM;
-			}
-		}
-		else if (!g_str_equal(passport, purple_account_get_username(gc->account)))
-		{
-			/* Don't im ourselves ... */
-			serv_got_im(gc, passport, body_final, 0, time(NULL));
-			if (swboard->conv == NULL)
-			{
-				swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
-										passport, purple_connection_get_account(gc));
-				swboard->flag |= MSN_SB_FLAG_IM;
-			}
-		}
-
-	} else {
-		serv_got_im(gc, passport, body_final, 0, time(NULL));
-	}
-
-	g_free(body_final);
-}
-
-void
-msn_control_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	PurpleConnection *gc;
-	char *passport;
-
-	gc = cmdproc->session->account->gc;
-	passport = msg->remote_user;
-
-	if (msn_message_get_header_value(msg, "TypingUser") == NULL)
-		return;
-
-	if (cmdproc->servconn->type == MSN_SERVCONN_SB) {
-		MsnSwitchBoard *swboard = cmdproc->data;
-
-		if (swboard->current_users == 1)
-		{
-			serv_got_typing(gc, passport, MSN_TYPING_RECV_TIMEOUT,
-							PURPLE_TYPING);
-		}
-
-	} else {
-		serv_got_typing(gc, passport, MSN_TYPING_RECV_TIMEOUT,
-						PURPLE_TYPING);
-	}
-}
-
-static void
-datacast_inform_user(MsnSwitchBoard *swboard, const char *who,
-                     const char *msg, const char *filename)
-{
-	char *username, *str;
-	PurpleAccount *account;
-	PurpleBuddy *b;
-	PurpleConnection *pc;
-	gboolean chat;
-
-	account = swboard->session->account;
-	pc = purple_account_get_connection(account);
-
-	if ((b = purple_find_buddy(account, who)) != NULL)
-		username = g_markup_escape_text(purple_buddy_get_alias(b), -1);
-	else
-		username = g_markup_escape_text(who, -1);
-	str = g_strdup_printf(msg, username, filename);
-	g_free(username);
-
-	swboard->flag |= MSN_SB_FLAG_IM;
-	if (swboard->current_users > 1)
-		chat = TRUE;
-	else
-		chat = FALSE;
-
-	if (swboard->conv == NULL) {
-		if (chat)
-			swboard->conv = purple_find_chat(account->gc, swboard->chat_id);
-		else {
-			swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
-									who, account);
-			if (swboard->conv == NULL)
-				swboard->conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, who);
-		}
-	}
-
-	if (chat)
-		serv_got_chat_in(pc,
-		                 purple_conv_chat_get_id(PURPLE_CONV_CHAT(swboard->conv)),
-		                 who, PURPLE_MESSAGE_RECV|PURPLE_MESSAGE_SYSTEM, str,
-		                 time(NULL));
-	else
-		serv_got_im(pc, who, str, PURPLE_MESSAGE_RECV|PURPLE_MESSAGE_SYSTEM,
-		            time(NULL));
-	g_free(str);
-
-}
-
-/* TODO: Make these not be such duplicates of each other */
-static void
-got_wink_cb(MsnSlpCall *slpcall, const guchar *data, gsize size)
-{
-	FILE *f = NULL;
-	char *path = NULL;
-	const char *who = slpcall->slplink->remote_user;
-	purple_debug_info("msn", "Received wink from %s\n", who);
-
-	if ((f = purple_mkstemp(&path, TRUE)) &&
-	    (fwrite(data, 1, size, f) == size)) {
-		datacast_inform_user(slpcall->slplink->swboard,
-		                     who,
-		                     _("%s sent a wink. <a href='msn-wink://%s'>Click here to play it</a>"),
-		                     path);
-	} else {
-		purple_debug_error("msn", "Couldn\'t create temp file to store wink\n");
-		datacast_inform_user(slpcall->slplink->swboard,
-		                     who,
-		                     _("%s sent a wink, but it could not be saved"),
-		                     NULL);
-	}
-	if (f)
-		fclose(f);
-	g_free(path);
-}
-
-static void
-got_voiceclip_cb(MsnSlpCall *slpcall, const guchar *data, gsize size)
-{
-	FILE *f = NULL;
-	char *path = NULL;
-	const char *who = slpcall->slplink->remote_user;
-	purple_debug_info("msn", "Received voice clip from %s\n", who);
-
-	if ((f = purple_mkstemp(&path, TRUE)) &&
-	    (fwrite(data, 1, size, f) == size)) {
-		datacast_inform_user(slpcall->slplink->swboard,
-		                     who,
-		                     _("%s sent a voice clip. <a href='audio://%s'>Click here to play it</a>"),
-		                     path);
-	} else {
-		purple_debug_error("msn", "Couldn\'t create temp file to store sound\n");
-		datacast_inform_user(slpcall->slplink->swboard,
-		                     who,
-		                     _("%s sent a voice clip, but it could not be saved"),
-		                     NULL);
-	}
-	if (f)
-		fclose(f);
-	g_free(path);
-}
-
-void
-msn_p2p_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	MsnSession *session;
-	MsnSlpLink *slplink;
-	MsnP2PVersion p2p;
-
-	session = cmdproc->servconn->session;
-	slplink = msn_session_get_slplink(session, msg->remote_user);
-
-	if (slplink->swboard == NULL)
-	{
-		/*
-		 * We will need swboard in order to change its flags.  If its
-		 * NULL, something has probably gone wrong earlier on.  I
-		 * didn't want to do this, but MSN 7 is somehow causing us
-		 * to crash here, I couldn't reproduce it to debug more,
-		 * and people are reporting bugs. Hopefully this doesn't
-		 * cause more crashes. Stu.
-		 */
-		if (cmdproc->data == NULL)
-			g_warning("msn_p2p_msg cmdproc->data was NULL\n");
-		else {
-			slplink->swboard = (MsnSwitchBoard *)cmdproc->data;
-			slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink);
-		}
-	}
-
-	p2p = msn_slplink_get_p2p_version(slplink);
-	msg->part = msn_slpmsgpart_new_from_data(p2p, msg->body, msg->body_len);
-
-	if (msg->part)
-		msn_slplink_process_msg(slplink, msg->part);
-	else
-		purple_debug_warning("msn", "P2P message failed to parse.\n");
-}
-
-static void
-got_emoticon(MsnSlpCall *slpcall,
-			 const guchar *data, gsize size)
-{
-	PurpleConversation *conv;
-	MsnSwitchBoard *swboard;
-
-	swboard = slpcall->slplink->swboard;
-	conv = swboard->conv;
-
-	if (conv) {
-		/* FIXME: it would be better if we wrote the data as we received it
-		   instead of all at once, calling write multiple times and
-		   close once at the very end
-		 */
-		purple_conv_custom_smiley_write(conv, slpcall->data_info, data, size);
-		purple_conv_custom_smiley_close(conv, slpcall->data_info );
-	}
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "Got smiley: %s\n", slpcall->data_info);
-}
-
-void msn_emoticon_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	MsnSession *session;
-	MsnSlpLink *slplink;
-	MsnSwitchBoard *swboard;
-	MsnObject *obj;
-	char **tokens;
-	char *smile, *body_str;
-	const char *body, *who, *sha1;
-	guint tok;
-	size_t body_len;
-
-	PurpleConversation *conv;
-
-	session = cmdproc->servconn->session;
-
-	if (!purple_account_get_bool(session->account, "custom_smileys", TRUE))
-		return;
-
-	swboard = cmdproc->data;
-	conv = swboard->conv;
-
-	body = msn_message_get_bin_data(msg, &body_len);
-	if (!body || !body_len)
-		return;
-	body_str = g_strndup(body, body_len);
-
-	/* MSN Messenger 7 may send more than one MSNObject in a single message...
-	 * Maybe 10 tokens is a reasonable max value. */
-	tokens = g_strsplit(body_str, "\t", 10);
-
-	g_free(body_str);
-
-	for (tok = 0; tok < 9; tok += 2) {
-		if (tokens[tok] == NULL || tokens[tok + 1] == NULL) {
-			break;
-		}
-
-		smile = tokens[tok];
-		obj = msn_object_new_from_string(purple_url_decode(tokens[tok + 1]));
-
-		if (obj == NULL)
-			break;
-
-		who = msn_object_get_creator(obj);
-		sha1 = msn_object_get_sha1(obj);
-
-		slplink = msn_session_get_slplink(session, who);
-		if (slplink->swboard != swboard) {
-			if (slplink->swboard != NULL)
-				/*
-				 * Apparently we're using a different switchboard now or
-				 * something?  I don't know if this is normal, but it
-				 * definitely happens.  So make sure the old switchboard
-				 * doesn't still have a reference to us.
-				 */
-				slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink);
-			slplink->swboard = swboard;
-			slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink);
-		}
-
-		/* If the conversation doesn't exist then this is a custom smiley
-		 * used in the first message in a MSN conversation: we need to create
-		 * the conversation now, otherwise the custom smiley won't be shown.
-		 * This happens because every GtkIMHtml has its own smiley tree: if
-		 * the conversation doesn't exist then we cannot associate the new
-		 * smiley with its GtkIMHtml widget. */
-		if (!conv) {
-			conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, session->account, who);
-		}
-
-		if (purple_conv_custom_smiley_add(conv, smile, "sha1", sha1, TRUE)) {
-			msn_slplink_request_object(slplink, smile, got_emoticon, NULL, obj);
-		}
-
-		msn_object_destroy(obj);
-		obj =   NULL;
-		who =   NULL;
-		sha1 = NULL;
-	}
-	g_strfreev(tokens);
-}
-
-void
-msn_datacast_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	GHashTable *body;
-	const char *id;
-	body = msn_message_get_hashtable_from_body(msg);
-
-	id = g_hash_table_lookup(body, "ID");
-
-	if (!strcmp(id, "1")) {
-		/* Nudge */
-		PurpleAccount *account;
-		const char *user;
-
-		account = cmdproc->session->account;
-		user = msg->remote_user;
-
-		if (cmdproc->servconn->type == MSN_SERVCONN_SB) {
-			MsnSwitchBoard *swboard = cmdproc->data;
-			if (swboard->current_users > 1 ||
-				((swboard->conv != NULL) &&
-				 purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
-				purple_prpl_got_attention_in_chat(account->gc, swboard->chat_id, user, MSN_NUDGE);
-
-			else
-				purple_prpl_got_attention(account->gc, user, MSN_NUDGE);
-		} else {
-			purple_prpl_got_attention(account->gc, user, MSN_NUDGE);
-		}
-
-	} else if (!strcmp(id, "2")) {
-		/* Wink */
-		MsnSession *session;
-		MsnSlpLink *slplink;
-		MsnObject *obj;
-		const char *who;
-		const char *data;
-
-		session = cmdproc->session;
-
-		data = g_hash_table_lookup(body, "Data");
-		obj = msn_object_new_from_string(data);
-		who = msn_object_get_creator(obj);
-
-		slplink = msn_session_get_slplink(session, who);
-		msn_slplink_request_object(slplink, data, got_wink_cb, NULL, obj);
-
-		msn_object_destroy(obj);
-
-
-	} else if (!strcmp(id, "3")) {
-		/* Voiceclip */
-		MsnSession *session;
-		MsnSlpLink *slplink;
-		MsnObject *obj;
-		const char *who;
-		const char *data;
-
-		session = cmdproc->session;
-
-		data = g_hash_table_lookup(body, "Data");
-		obj = msn_object_new_from_string(data);
-		who = msn_object_get_creator(obj);
-
-		slplink = msn_session_get_slplink(session, who);
-		msn_slplink_request_object(slplink, data, got_voiceclip_cb, NULL, obj);
-
-		msn_object_destroy(obj);
-
-	} else if (!strcmp(id, "4")) {
-		/* Action */
-
-	} else {
-		purple_debug_warning("msn", "Got unknown datacast with ID %s.\n", id);
-	}
-
-	g_hash_table_destroy(body);
-}
-
-void
-msn_invite_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	GHashTable *body;
-	const gchar *command;
-	const gchar *cookie;
-	gboolean accepted = FALSE;
-
-	g_return_if_fail(cmdproc != NULL);
-	g_return_if_fail(msg != NULL);
-
-	body = msn_message_get_hashtable_from_body(msg);
-
-	if (body == NULL) {
-		purple_debug_warning("msn",
-				"Unable to parse invite msg body.\n");
-		return;
-	}
-
-	/*
-	 * GUID is NOT always present but Invitation-Command and Invitation-Cookie
-	 * are mandatory.
-	 */
-	command = g_hash_table_lookup(body, "Invitation-Command");
-	cookie = g_hash_table_lookup(body, "Invitation-Cookie");
-
-	if (command == NULL || cookie == NULL) {
-		purple_debug_warning("msn",
-			"Invalid invitation message: either Invitation-Command "
-			"or Invitation-Cookie is missing or invalid.\n"
-		);
-		return;
-
-	} else if (!strcmp(command, "INVITE")) {
-		const gchar	*guid = g_hash_table_lookup(body, "Application-GUID");
-
-		if (guid == NULL) {
-			purple_debug_warning("msn",
-			                     "Invite msg missing Application-GUID.\n");
-
-			accepted = TRUE;
-
-		} else if (!strcmp(guid, MSN_FT_GUID)) {
-
-		} else if (!strcmp(guid, "{02D3C01F-BF30-4825-A83A-DE7AF41648AA}")) {
-			purple_debug_info("msn", "Computer call\n");
-
-			if (cmdproc->session) {
-				PurpleConversation *conv = NULL;
-				gchar *from = msg->remote_user;
-				gchar *buf = NULL;
-
-				if (from)
-					conv = purple_find_conversation_with_account(
-							PURPLE_CONV_TYPE_IM, from,
-							cmdproc->session->account);
-				if (conv)
-					buf = g_strdup_printf(
-							_("%s sent you a voice chat "
-							"invite, which is not yet "
-							"supported."), from);
-				if (buf) {
-					purple_conversation_write(conv, NULL, buf,
-							PURPLE_MESSAGE_SYSTEM |
-							PURPLE_MESSAGE_NOTIFY,
-							time(NULL));
-					g_free(buf);
-				}
-			}
-		} else {
-			const gchar *application = g_hash_table_lookup(body, "Application-Name");
-			purple_debug_warning("msn", "Unhandled invite msg with GUID %s: %s.\n",
-			                     guid, application ? application : "(null)");
-		}
-
-		if (!accepted) {
-			MsnSwitchBoard *swboard = cmdproc->data;
-			char *text;
-			MsnMessage *cancel;
-
-			cancel = msn_message_new(MSN_MSG_TEXT);
-			msn_message_set_content_type(cancel, "text/x-msmsgsinvite");
-			msn_message_set_charset(cancel, "UTF-8");
-			msn_message_set_flag(cancel, 'U');
-
-			text = g_strdup_printf("Invitation-Command: CANCEL\r\n"
-			                       "Invitation-Cookie: %s\r\n"
-			                       "Cancel-Code: REJECT_NOT_INSTALLED\r\n",
-			                       cookie);
-			msn_message_set_bin_data(cancel, text, strlen(text));
-			g_free(text);
-
-			msn_switchboard_send_msg(swboard, cancel, TRUE);
-			msn_message_unref(cancel);
-		}
-
-	} else if (!strcmp(command, "CANCEL")) {
-		const gchar *code = g_hash_table_lookup(body, "Cancel-Code");
-		purple_debug_info("msn", "MSMSGS invitation cancelled: %s.\n",
-		                  code ? code : "no reason given");
-
-	} else {
-		/*
-		 * Some other already established invitation session.
-		 * Can be retrieved by Invitation-Cookie.
-		 */
-	}
-
-	g_hash_table_destroy(body);
-}
-
-/* Only called from chats. Handwritten messages for IMs come as a SLP message */
-void
-msn_handwritten_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	const char *body;
-	size_t body_len;
-
-	body = msn_message_get_bin_data(msg, &body_len);
-	msn_switchboard_show_ink(cmdproc->data, msg->remote_user, body);
-}
-
--- a/libpurple/protocols/msn/msg.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,325 +0,0 @@
-/**
- * @file msg.h Message functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_MSG_H
-#define MSN_MSG_H
-
-typedef struct _MsnMessage MsnMessage;
-
-/*
-typedef enum
-{
-	MSN_MSG_NORMAL,
-	MSN_MSG_SLP_SB,
-	MSN_MSG_SLP_DC
-} MsnMsgType;
-*/
-
-typedef enum
-{
-	MSN_MSG_UNKNOWN,
-	MSN_MSG_TEXT,
-	MSN_MSG_TYPING,
-	MSN_MSG_CAPS,
-	MSN_MSG_SLP,
-	MSN_MSG_NUDGE
-} MsnMsgType;
-
-typedef enum
-{
-	MSN_MSG_ERROR_NONE, /**< No error. */
-	MSN_MSG_ERROR_TIMEOUT, /**< The message timedout. */
-	MSN_MSG_ERROR_NAK, /**< The message could not be sent. */
-	MSN_MSG_ERROR_SB, /**< The error comes from the switchboard. */
-	MSN_MSG_ERROR_UNKNOWN /**< An unknown error occurred. */
-} MsnMsgErrorType;
-
-#include "command.h"
-#include "session.h"
-#include "transaction.h"
-#include "user.h"
-#include "slpmsg.h"
-#include "slpmsg_part.h"
-
-typedef void (*MsnMsgCb)(MsnMessage *, void *data);
-
-#define MSG_BODY_DEM	"\r\n\r\n"
-#define MSG_LINE_DEM	"\r\n"
-
-#define MSG_OIM_BODY_DEM	"\n\n"
-#define MSG_OIM_LINE_DEM	"\n"
-
-/**
- * A message.
- */
-struct _MsnMessage
-{
-	guint ref_count;        /**< The reference count.       */
-
-	MsnMsgType type;
-
-	MsnSlpMessagePart *part;
-
-	char *remote_user;
-	char flag;
-
-	char *content_type;
-	char *charset;
-	char *body;
-	gsize body_len;
-	guint total_chunks;     /**< How many chunks in this multi-part message */
-	guint received_chunks;  /**< How many chunks we've received so far */
-
-	GHashTable *header_table;
-	GList *header_list;
-
-	gboolean ack_ref;           /**< A flag that states if this message has
-								  been ref'ed for using it in a callback. */
-
-	MsnCommand *cmd;
-
-	MsnMsgCb ack_cb; /**< The callback to call when we receive an ACK of this
-					   message. */
-	MsnMsgCb nak_cb; /**< The callback to call when we receive a NAK of this
-					   message. */
-	void *ack_data; /**< The data used by callbacks. */
-
-	guint32 retries;
-};
-
-/**
- * Creates a new, empty message.
- *
- * @return A new message.
- */
-MsnMessage *msn_message_new(MsnMsgType type);
-
-/**
- * Creates a new, empty MSNSLP message.
- *
- * @return A new MSNSLP message.
- */
-MsnMessage *msn_message_new_msnslp(void);
-
-/**
- * Creates a new nudge message.
- *
- * @return A new nudge message.
- */
-MsnMessage *msn_message_new_nudge(void);
-
-/**
- * Creates a new plain message.
- *
- * @return A new plain message.
- */
-MsnMessage *msn_message_new_plain(const char *message);
-
-/**
- * Creates a new message based off a command.
- *
- * @param session The MSN session.
- * @param cmd     The command.
- *
- * @return The new message.
- */
-MsnMessage *msn_message_new_from_cmd(MsnSession *session, MsnCommand *cmd);
-
-/**
- * Parses the payload of a message.
- *
- * @param msg         The message.
- * @param payload     The payload.
- * @param payload_len The length of the payload.
- */
-void msn_message_parse_payload(MsnMessage *msg, const char *payload,
-							   size_t payload_len,
-						  const char *line_dem,const char *body_dem);
-
-/**
- * Increments the reference count on a message.
- *
- * @param msg The message.
- *
- * @return @a msg
- */
-MsnMessage *msn_message_ref(MsnMessage *msg);
-
-/**
- * Decrements the reference count on a message.
- *
- * This will destroy the structure if the count hits 0.
- *
- * @param msg The message.
- *
- * @return @a msg, or @c NULL if the new count is 0.
- */
-void msn_message_unref(MsnMessage *msg);
-
-/**
- * Generates the payload data of a message.
- *
- * @param msg      The message.
- * @param ret_size The returned size of the payload.
- *
- * @return The payload data of the message.
- */
-char *msn_message_gen_payload(MsnMessage *msg, size_t *ret_size);
-
-/**
- * Sets the flag for an outgoing message.
- *
- * @param msg  The message.
- * @param flag The flag.
- */
-void msn_message_set_flag(MsnMessage *msg, char flag);
-
-/**
- * Returns the flag for an outgoing message.
- *
- * @param msg The message.
- *
- * @return The flag.
- */
-char msn_message_get_flag(const MsnMessage *msg);
-
-/**
- * Sets the binary content of the message.
- *
- * @param msg  The message.
- * @param data The binary data.
- * @param len  The length of the data.
- */
-void msn_message_set_bin_data(MsnMessage *msg, const void *data, size_t len);
-
-/**
- * Returns the binary content of the message.
- *
- * @param msg The message.
- * @param len The returned length of the data.
- *
- * @return The binary data.
- */
-const void *msn_message_get_bin_data(const MsnMessage *msg, size_t *len);
-
-/**
- * Sets the content type in a message.
- *
- * @param msg  The message.
- * @param type The content-type.
- */
-void msn_message_set_content_type(MsnMessage *msg, const char *type);
-
-/**
- * Returns the content type in a message.
- *
- * @param msg The message.
- *
- * @return The content-type.
- */
-const char *msn_message_get_content_type(const MsnMessage *msg);
-
-/**
- * Sets the charset in a message.
- *
- * @param msg     The message.
- * @param charset The charset.
- */
-void msn_message_set_charset(MsnMessage *msg, const char *charset);
-
-/**
- * Returns the charset in a message.
- *
- * @param msg The message.
- *
- * @return The charset.
- */
-const char *msn_message_get_charset(const MsnMessage *msg);
-
-/**
- * Sets a header in a message.
- *
- * @param msg    The message.
- * @param header The header name.
- * @param value  The header value.
- */
-void msn_message_set_header(MsnMessage *msg, const char *name,
-						  const char *value);
-
-/**
- * Returns the value of a header from a message.
- *
- * @param msg    The message.
- * @param header The header value.
- *
- * @return The value, or @c NULL if not found.
- */
-const char *msn_message_get_header_value(const MsnMessage *msg, const char *name);
-
-/**
- * Parses the body and returns it in the form of a hashtable.
- *
- * @param msg The message.
- *
- * @return The resulting hashtable.
- */
-GHashTable *msn_message_get_hashtable_from_body(const MsnMessage *msg);
-
-void msn_message_show_readable(MsnMessage *msg, const char *info,
-							   gboolean text_body);
-
-char *msn_message_to_string(MsnMessage *msg);
-
-void msn_plain_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
-
-void msn_control_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
-
-/**
- * Processes peer to peer messages.
- *
- * @param cmdproc The command processor.
- * @param msg     The message.
- */
-void msn_p2p_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
-
-/**
- * Processes emoticon messages.
- *
- * @param cmdproc The command processor.
- * @param msg     The message.
- */
-void msn_emoticon_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
-
-void msn_datacast_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
-
-/**
- * Processes INVITE messages.
- *
- * @param cmdproc The command processor.
- * @param msg     The message.
- */
-void msn_invite_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
-
-void msn_handwritten_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
-
-#endif /* MSN_MSG_H */
--- a/libpurple/protocols/msn/msn.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3069 +0,0 @@
-/**
- * @file msn.c The MSN protocol plugin
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#define PHOTO_SUPPORT 1
-
-#include "internal.h"
-
-#include "debug.h"
-#include "request.h"
-
-#include "accountopt.h"
-#include "contact.h"
-#include "msg.h"
-#include "page.h"
-#include "pluginpref.h"
-#include "prefs.h"
-#include "session.h"
-#include "smiley.h"
-#include "state.h"
-#include "util.h"
-#include "cmds.h"
-#include "core.h"
-#include "prpl.h"
-#include "msnutils.h"
-#include "version.h"
-
-#include "error.h"
-#include "msg.h"
-#include "switchboard.h"
-#include "notification.h"
-#include "slplink.h"
-
-#if PHOTO_SUPPORT
-#define MAX_HTTP_BUDDYICON_BYTES (200 * 1024)
-#include "imgstore.h"
-#endif
-
-typedef struct
-{
-	PurpleConnection *gc;
-	const char *passport;
-
-} MsnMobileData;
-
-typedef struct
-{
-	PurpleConnection *gc;
-	char *name;
-
-} MsnGetInfoData;
-
-typedef struct
-{
-	MsnGetInfoData *info_data;
-	char *stripped;
-	char *url_buffer;
-	PurpleNotifyUserInfo *user_info;
-	char *photo_url_text;
-
-} MsnGetInfoStepTwoData;
-
-typedef struct
-{
-	PurpleConnection *gc;
-	const char *who;
-	char *msg;
-	PurpleMessageFlags flags;
-	time_t when;
-} MsnIMData;
-
-typedef struct
-{
-	char *smile;
-	PurpleSmiley *ps;
-	MsnObject *obj;
-} MsnEmoticon;
-
-static const char *
-msn_normalize(const PurpleAccount *account, const char *str)
-{
-	static char buf[BUF_LEN];
-	char *tmp;
-
-	g_return_val_if_fail(str != NULL, NULL);
-
-	tmp = g_strchomp(g_utf8_strdown(str, -1));
-	g_snprintf(buf, sizeof(buf), "%s%s", tmp,
-			   (strchr(tmp, '@') ? "" : "@hotmail.com"));
-	g_free(tmp);
-
-	return buf;
-}
-
-static gboolean
-msn_send_attention(PurpleConnection *gc, const char *username, guint type)
-{
-	MsnMessage *msg;
-	MsnSession *session;
-	MsnSwitchBoard *swboard;
-
-	msg = msn_message_new_nudge();
-	session = gc->proto_data;
-	swboard = msn_session_get_swboard(session, username, MSN_SB_FLAG_IM);
-
-	msn_switchboard_send_msg(swboard, msg, TRUE);
-	msn_message_unref(msg);
-
-	return TRUE;
-}
-
-static GList *
-msn_attention_types(PurpleAccount *account)
-{
-	static GList *list = NULL;
-
-	if (!list) {
-		list = g_list_append(list, purple_attention_type_new("Nudge", _("Nudge"),
-				_("%s has nudged you!"), _("Nudging %s...")));
-	}
-
-	return list;
-}
-
-static GHashTable *
-msn_get_account_text_table(PurpleAccount *unused)
-{
-	GHashTable *table;
-
-	table = g_hash_table_new(g_str_hash, g_str_equal);
-
-	g_hash_table_insert(table, "login_label", (gpointer)_("Email Address..."));
-
-	return table;
-}
-
-static PurpleCmdRet
-msn_cmd_nudge(PurpleConversation *conv, const gchar *cmd, gchar **args, gchar **error, void *data)
-{
-	PurpleAccount *account = purple_conversation_get_account(conv);
-	PurpleConnection *gc = purple_account_get_connection(account);
-	const gchar *username;
-
-	username = purple_conversation_get_name(conv);
-
-	purple_prpl_send_attention(gc, username, MSN_NUDGE);
-
-	return PURPLE_CMD_RET_OK;
-}
-
-struct public_alias_closure
-{
-	PurpleAccount *account;
-	gpointer success_cb;
-	gpointer failure_cb;
-};
-
-static gboolean
-set_public_alias_length_error(gpointer data)
-{
-	struct public_alias_closure *closure = data;
-	PurpleSetPublicAliasFailureCallback failure_cb = closure->failure_cb;
-
-	failure_cb(closure->account, _("Your new MSN friendly name is too long."));
-	g_free(closure);
-
-	return FALSE;
-}
-
-static void
-prp_success_cb(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	const char *type, *friendlyname;
-	struct public_alias_closure *closure;
-
-	g_return_if_fail(cmd->param_count >= 3);
-	type = cmd->params[1];
-	g_return_if_fail(!strcmp(type, "MFN"));
-
-	closure = cmd->trans->data;
-	friendlyname = purple_url_decode(cmd->params[2]);
-
-	msn_update_contact(cmdproc->session, "Me", MSN_UPDATE_DISPLAY, friendlyname);
-
-	purple_connection_set_display_name(
-		purple_account_get_connection(closure->account),
-		friendlyname);
-	purple_account_set_string(closure->account, "display-name", friendlyname);
-
-	if (closure->success_cb) {
-		PurpleSetPublicAliasSuccessCallback success_cb = closure->success_cb;
-		success_cb(closure->account, friendlyname);
-	}
-}
-
-static void
-prp_error_cb(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
-{
-	struct public_alias_closure *closure = trans->data;
-	PurpleSetPublicAliasFailureCallback failure_cb = closure->failure_cb;
-	gboolean debug;
-	const char *error_text;
-
-	error_text = msn_error_get_text(error, &debug);
-	failure_cb(closure->account, error_text);
-}
-
-static void
-prp_timeout_cb(MsnCmdProc *cmdproc, MsnTransaction *trans)
-{
-	struct public_alias_closure *closure = trans->data;
-	PurpleSetPublicAliasFailureCallback failure_cb = closure->failure_cb;
-	failure_cb(closure->account, _("Connection Timeout"));
-}
-
-void
-msn_set_public_alias(PurpleConnection *pc, const char *alias,
-                     PurpleSetPublicAliasSuccessCallback success_cb,
-                     PurpleSetPublicAliasFailureCallback failure_cb)
-{
-	MsnCmdProc *cmdproc;
-	MsnSession *session;
-	MsnTransaction *trans;
-	PurpleAccount *account;
-	char real_alias[BUDDY_ALIAS_MAXLEN + 1];
-	struct public_alias_closure *closure;
-
-	session = purple_connection_get_protocol_data(pc);
-	cmdproc = session->notification->cmdproc;
-	account = purple_connection_get_account(pc);
-
-	if (alias && *alias) {
-		if (!msn_encode_spaces(alias, real_alias, BUDDY_ALIAS_MAXLEN + 1)) {
-			if (failure_cb) {
-				struct public_alias_closure *closure =
-					g_new0(struct public_alias_closure, 1);
-				closure->account = account;
-				closure->failure_cb = failure_cb;
-				purple_timeout_add(0, set_public_alias_length_error, closure);
-			} else {
-				purple_notify_error(pc, NULL,
-				                    _("Your new MSN friendly name is too long."),
-				                    NULL);
-			}
-			return;
-		}
-
-		if (real_alias[0] == '\0')
-			g_strlcpy(real_alias, purple_account_get_username(account), sizeof(real_alias));
-	} else
-		g_strlcpy(real_alias, purple_account_get_username(account), sizeof(real_alias));
-
-	closure = g_new0(struct public_alias_closure, 1);
-	closure->account = account;
-	closure->success_cb = success_cb;
-	closure->failure_cb = failure_cb;
-
-	trans = msn_transaction_new(cmdproc, "PRP", "MFN %s", real_alias);
-	msn_transaction_set_data(trans, closure);
-	msn_transaction_set_data_free(trans, g_free);
-	msn_transaction_add_cb(trans, "PRP", prp_success_cb);
-	if (failure_cb) {
-		msn_transaction_set_error_cb(trans, prp_error_cb);
-		msn_transaction_set_timeout_cb(trans, prp_timeout_cb);
-	}
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-static gboolean
-get_public_alias_cb(gpointer data)
-{
-	struct public_alias_closure *closure = data;
-	PurpleGetPublicAliasSuccessCallback success_cb = closure->success_cb;
-	const char *alias;
-
-	alias = purple_account_get_string(closure->account, "display-name",
-	                                  purple_account_get_username(closure->account));
-	success_cb(closure->account, alias);
-	g_free(closure);
-
-	return FALSE;
-}
-
-static void
-msn_get_public_alias(PurpleConnection *pc,
-                     PurpleGetPublicAliasSuccessCallback success_cb,
-                     PurpleGetPublicAliasFailureCallback failure_cb)
-{
-	struct public_alias_closure *closure = g_new0(struct public_alias_closure, 1);
-	PurpleAccount *account = purple_connection_get_account(pc);
-
-	closure->account = account;
-	closure->success_cb = success_cb;
-	purple_timeout_add(0, get_public_alias_cb, closure);
-}
-
-static void
-msn_act_id(PurpleConnection *gc, const char *entry)
-{
-	msn_set_public_alias(gc, entry, NULL, NULL);
-}
-
-static void
-msn_set_prp(PurpleConnection *gc, const char *type, const char *entry)
-{
-	MsnCmdProc *cmdproc;
-	MsnSession *session;
-	MsnTransaction *trans;
-
-	session = gc->proto_data;
-	cmdproc = session->notification->cmdproc;
-
-	if (entry == NULL || *entry == '\0')
-	{
-		trans = msn_transaction_new(cmdproc, "PRP", "%s", type);
-	}
-	else
-	{
-		trans = msn_transaction_new(cmdproc, "PRP", "%s %s", type,
-						 purple_url_encode(entry));
-	}
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-static void
-msn_set_home_phone_cb(PurpleConnection *gc, const char *entry)
-{
-	msn_set_prp(gc, "PHH", entry);
-}
-
-static void
-msn_set_work_phone_cb(PurpleConnection *gc, const char *entry)
-{
-	msn_set_prp(gc, "PHW", entry);
-}
-
-static void
-msn_set_mobile_phone_cb(PurpleConnection *gc, const char *entry)
-{
-	msn_set_prp(gc, "PHM", entry);
-}
-
-static void
-enable_msn_pages_cb(PurpleConnection *gc)
-{
-	msn_set_prp(gc, "MOB", "Y");
-}
-
-static void
-disable_msn_pages_cb(PurpleConnection *gc)
-{
-	msn_set_prp(gc, "MOB", "N");
-}
-
-static void
-send_to_mobile(PurpleConnection *gc, const char *who, const char *entry)
-{
-	MsnTransaction *trans;
-	MsnSession *session;
-	MsnCmdProc *cmdproc;
-	MsnPage *page;
-	MsnMessage *msg;
-	MsnUser *user;
-	char *payload = NULL;
-	const char *mobile_number = NULL;
-	gsize payload_len;
-
-	session = gc->proto_data;
-	cmdproc = session->notification->cmdproc;
-
-	page = msn_page_new();
-	msn_page_set_body(page, entry);
-
-	payload = msn_page_gen_payload(page, &payload_len);
-
-	if ((user = msn_userlist_find_user(session->userlist, who)) &&
-		(mobile_number = msn_user_get_mobile_phone(user)) &&
-		mobile_number[0] == '+') {
-		/* if msn_user_get_mobile_phone() has a + in front, it's a number
-		   that from the buddy's contact card */
-		trans = msn_transaction_new(cmdproc, "PGD", "tel:%s 1 %" G_GSIZE_FORMAT,
-			mobile_number, payload_len);
-	} else {
-		/* otherwise we send to whatever phone number the buddy registered
-		   with msn */
-		trans = msn_transaction_new(cmdproc, "PGD", "%s 1 %" G_GSIZE_FORMAT,
-			who, payload_len);
-	}
-
-	msn_transaction_set_payload(trans, payload, payload_len);
-	g_free(payload);
-
-	msg = msn_message_new_plain(entry);
-	msn_transaction_set_data(trans, msg);
-
-	msn_page_destroy(page);
-
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-static void
-send_to_mobile_cb(MsnMobileData *data, const char *entry)
-{
-	send_to_mobile(data->gc, data->passport, entry);
-	g_free(data);
-}
-
-static void
-close_mobile_page_cb(MsnMobileData *data, const char *entry)
-{
-	g_free(data);
-}
-
-/* -- */
-
-static void
-msn_show_set_friendly_name(PurplePluginAction *action)
-{
-	PurpleConnection *gc;
-	PurpleAccount *account;
-	char *tmp;
-
-	gc = (PurpleConnection *) action->context;
-	account = purple_connection_get_account(gc);
-
-	tmp = g_strdup_printf(_("Set friendly name for %s."),
-	                      purple_account_get_username(account));
-	purple_request_input(gc, _("Set Friendly Name"), tmp,
-					   _("This is the name that other MSN buddies will "
-						 "see you as."),
-					   purple_connection_get_display_name(gc), FALSE, FALSE, NULL,
-					   _("OK"), G_CALLBACK(msn_act_id),
-					   _("Cancel"), NULL,
-					   account, NULL, NULL,
-					   gc);
-	g_free(tmp);
-}
-
-typedef struct MsnLocationData {
-	PurpleAccount *account;
-	MsnSession *session;
-	PurpleRequestFieldGroup *group;
-} MsnLocationData;
-
-static void
-update_endpoint_cb(MsnLocationData *data, PurpleRequestFields *fields)
-{
-	PurpleAccount *account;
-	MsnSession *session;
-	const char *old_name;
-	const char *name;
-	GList *others;
-
-	session = data->session;
-	account = data->account;
-
-	/* Update the current location's name */
-	old_name = purple_account_get_string(account, "endpoint-name", NULL);
-	name = purple_request_fields_get_string(fields, "endpoint-name");
-	if (!g_str_equal(old_name, name)) {
-		purple_account_set_string(account, "endpoint-name", name);
-		msn_notification_send_uux_private_endpointdata(session);
-	}
-
-	/* Sign out other locations */
-	for (others = purple_request_field_group_get_fields(data->group);
-	     others;
-	     others = g_list_next(others)) {
-		PurpleRequestField *field = others->data;
-		if (purple_request_field_get_type(field) != PURPLE_REQUEST_FIELD_BOOLEAN)
-			continue;
-		if (purple_request_field_bool_get_value(field)) {
-			const char *id = purple_request_field_get_id(field);
-			char *user;
-			purple_debug_info("msn", "Disconnecting Endpoint %s\n", id);
-
-			user = g_strdup_printf("%s;%s", purple_account_get_username(account), id);
-			msn_notification_send_uun(session, user, MSN_UNIFIED_NOTIFICATION_MPOP, "goawyplzthxbye");
-			g_free(user);
-		}
-	}
-
-	g_free(data);
-}
-
-static void
-msn_show_locations(PurplePluginAction *action)
-{
-	PurpleConnection *pc;
-	PurpleAccount *account;
-	MsnSession *session;
-	PurpleRequestFields *fields;
-	PurpleRequestFieldGroup *group;
-	PurpleRequestField *field;
-	gboolean have_other_endpoints;
-	GSList *l;
-	MsnLocationData *data;
-
-	pc = (PurpleConnection *)action->context;
-	account = purple_connection_get_account(pc);
-	session = purple_connection_get_protocol_data(pc);
-
-	fields = purple_request_fields_new();
-
-	group = purple_request_field_group_new(_("This Location"));
-	purple_request_fields_add_group(fields, group);
-	field = purple_request_field_label_new("endpoint-label", _("This is the name that identifies this location"));
-	purple_request_field_group_add_field(group, field);
-	field = purple_request_field_string_new("endpoint-name",
-	                                        _("Name"),
-	                                        purple_account_get_string(account, "endpoint-name", NULL),
-	                                        FALSE);
-	purple_request_field_set_required(field, TRUE);
-	purple_request_field_group_add_field(group, field);
-
-	group = purple_request_field_group_new(_("Other Locations"));
-	purple_request_fields_add_group(fields, group);
-
-	have_other_endpoints = FALSE;
-	for (l = session->user->endpoints; l; l = l->next) {
-		MsnUserEndpoint *ep = l->data;
-
-		if (ep->id[0] != '\0' && strncasecmp(ep->id + 1, session->guid, 36) == 0)
-			/* Don't add myself to the list */
-			continue;
-
-		if (!have_other_endpoints) {
-			/* We do in fact have an endpoint other than ourselves... let's
-			   add a label */
-			field = purple_request_field_label_new("others-label",
-					_("You can sign out from other locations here"));
-			purple_request_field_group_add_field(group, field);
-		}
-
-		have_other_endpoints = TRUE;
-		field = purple_request_field_bool_new(ep->id, ep->name, FALSE);
-		purple_request_field_group_add_field(group, field);
-	}
-	if (!have_other_endpoints) {
-		/* TODO: Due to limitations in our current request field API, the
-		   following string will show up with a trailing colon.  This should
-		   be fixed either by adding an "include_colon" boolean, or creating
-		   a separate purple_request_field_label_new_without_colon function,
-		   or by never automatically adding the colon and requiring that
-		   callers add the colon themselves. */
-		field = purple_request_field_label_new("others-label", _("You are not signed in from any other locations."));
-		purple_request_field_group_add_field(group, field);
-	}
-
-	data = g_new0(MsnLocationData, 1);
-	data->account = account;
-	data->session = session;
-	data->group = group;
-
-	purple_request_fields(pc, NULL, NULL, NULL,
-	                      fields,
-	                      _("OK"), G_CALLBACK(update_endpoint_cb),
-	                      _("Cancel"), G_CALLBACK(g_free),
-	                      account, NULL, NULL,
-	                      data);
-}
-
-static void
-enable_mpop_cb(PurpleConnection *pc)
-{
-	MsnSession *session = purple_connection_get_protocol_data(pc);
-
-	purple_debug_info("msn", "Enabling MPOP\n");
-
-	session->enable_mpop = TRUE;
-	msn_annotate_contact(session, "Me", "MSN.IM.MPOP", "1", NULL);
-
-	purple_prpl_got_account_actions(purple_connection_get_account(pc));
-}
-
-static void
-disable_mpop_cb(PurpleConnection *pc)
-{
-	PurpleAccount *account = purple_connection_get_account(pc);
-	MsnSession *session = purple_connection_get_protocol_data(pc);
-	GSList *l;
-
-	purple_debug_info("msn", "Disabling MPOP\n");
-
-	session->enable_mpop = FALSE;
-	msn_annotate_contact(session, "Me", "MSN.IM.MPOP", "0", NULL);
-
-	for (l = session->user->endpoints; l; l = l->next) {
-		MsnUserEndpoint *ep = l->data;
-		char *user;
-
-		if (ep->id[0] != '\0' && strncasecmp(ep->id + 1, session->guid, 36) == 0)
-			/* Don't kick myself */
-			continue;
-
-		purple_debug_info("msn", "Disconnecting Endpoint %s\n", ep->id);
-
-		user = g_strdup_printf("%s;%s", purple_account_get_username(account), ep->id);
-		msn_notification_send_uun(session, user, MSN_UNIFIED_NOTIFICATION_MPOP, "goawyplzthxbye");
-		g_free(user);
-	}
-
-	purple_prpl_got_account_actions(account);
-}
-
-static void
-msn_show_set_mpop(PurplePluginAction *action)
-{
-	PurpleConnection *pc;
-
-	pc = (PurpleConnection *)action->context;
-
-	purple_request_action(pc, NULL, _("Allow multiple logins?"),
-						_("Do you want to allow or disallow connecting from "
-						  "multiple locations simultaneously?"),
-						PURPLE_DEFAULT_ACTION_NONE,
-						purple_connection_get_account(pc), NULL, NULL,
-						pc, 3,
-						_("Allow"), G_CALLBACK(enable_mpop_cb),
-						_("Disallow"), G_CALLBACK(disable_mpop_cb),
-						_("Cancel"), NULL);
-}
-
-static void
-msn_show_set_home_phone(PurplePluginAction *action)
-{
-	PurpleConnection *gc;
-	MsnSession *session;
-
-	gc = (PurpleConnection *) action->context;
-	session = gc->proto_data;
-
-	purple_request_input(gc, NULL, _("Set your home phone number."), NULL,
-					   msn_user_get_home_phone(session->user), FALSE, FALSE, NULL,
-					   _("OK"), G_CALLBACK(msn_set_home_phone_cb),
-					   _("Cancel"), NULL,
-					   purple_connection_get_account(gc), NULL, NULL,
-					   gc);
-}
-
-static void
-msn_show_set_work_phone(PurplePluginAction *action)
-{
-	PurpleConnection *gc;
-	MsnSession *session;
-
-	gc = (PurpleConnection *) action->context;
-	session = gc->proto_data;
-
-	purple_request_input(gc, NULL, _("Set your work phone number."), NULL,
-					   msn_user_get_work_phone(session->user), FALSE, FALSE, NULL,
-					   _("OK"), G_CALLBACK(msn_set_work_phone_cb),
-					   _("Cancel"), NULL,
-					   purple_connection_get_account(gc), NULL, NULL,
-					   gc);
-}
-
-static void
-msn_show_set_mobile_phone(PurplePluginAction *action)
-{
-	PurpleConnection *gc;
-	MsnSession *session;
-
-	gc = (PurpleConnection *) action->context;
-	session = gc->proto_data;
-
-	purple_request_input(gc, NULL, _("Set your mobile phone number."), NULL,
-					   msn_user_get_mobile_phone(session->user), FALSE, FALSE, NULL,
-					   _("OK"), G_CALLBACK(msn_set_mobile_phone_cb),
-					   _("Cancel"), NULL,
-					   purple_connection_get_account(gc), NULL, NULL,
-					   gc);
-}
-
-static void
-msn_show_set_mobile_pages(PurplePluginAction *action)
-{
-	PurpleConnection *gc;
-
-	gc = (PurpleConnection *) action->context;
-
-	purple_request_action(gc, NULL, _("Allow MSN Mobile pages?"),
-						_("Do you want to allow or disallow people on "
-						  "your buddy list to send you MSN Mobile pages "
-						  "to your cell phone or other mobile device?"),
-						PURPLE_DEFAULT_ACTION_NONE,
-						purple_connection_get_account(gc), NULL, NULL,
-						gc, 3,
-						_("Allow"), G_CALLBACK(enable_msn_pages_cb),
-						_("Disallow"), G_CALLBACK(disable_msn_pages_cb),
-						_("Cancel"), NULL);
-}
-
-/* QuLogic: Disabled until confirmed correct. */
-#if 0
-static void
-msn_show_blocked_text(PurplePluginAction *action)
-{
-	PurpleConnection *pc = (PurpleConnection *) action->context;
-	MsnSession *session;
-	char *title;
-
-	session = pc->proto_data;
-
-	title = g_strdup_printf(_("Blocked Text for %s"), session->account->username);
-	if (session->blocked_text == NULL) {
-		purple_notify_formatted(pc, title, title, NULL, _("No text is blocked for this account."), NULL, NULL);
-	} else {
-		char *blocked_text;
-		blocked_text = g_strdup_printf(_("MSN servers are currently blocking the following regular expressions:<br/>%s"),
-		                               session->blocked_text);
-
-		purple_notify_formatted(pc, title, title, NULL, blocked_text, NULL, NULL);
-		g_free(blocked_text);
-	}
-	g_free(title);
-}
-#endif
-
-static void
-msn_show_hotmail_inbox(PurplePluginAction *action)
-{
-	PurpleConnection *gc;
-	MsnSession *session;
-
-	gc = (PurpleConnection *) action->context;
-	session = gc->proto_data;
-
-	if (!session->passport_info.email_enabled) {
-		purple_notify_error(gc, NULL,
-						  _("This account does not have email enabled."), NULL);
-		return;
-	}
-
-	/** apparently the correct value is 777, use 750 as a failsafe */
-	if ((session->passport_info.mail_url == NULL)
-		|| (time (NULL) - session->passport_info.mail_timestamp >= 750)) {
-		MsnTransaction *trans;
-		MsnCmdProc *cmdproc;
-
-		cmdproc = session->notification->cmdproc;
-
-		trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
-		msn_transaction_set_data(trans, GUINT_TO_POINTER(TRUE));
-
-		msn_cmdproc_send_trans(cmdproc, trans);
-
-	} else
-		purple_notify_uri(gc, session->passport_info.mail_url);
-}
-
-static void
-show_send_to_mobile_cb(PurpleBlistNode *node, gpointer ignored)
-{
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-	MsnMobileData *data;
-	PurpleAccount *account;
-	const char *name;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *) node;
-	account = purple_buddy_get_account(buddy);
-	gc = purple_account_get_connection(account);
-	name = purple_buddy_get_name(buddy);
-
-	data = g_new0(MsnMobileData, 1);
-	data->gc = gc;
-	data->passport = name;
-
-	purple_request_input(gc, NULL, _("Send a mobile message."), NULL,
-					   NULL, TRUE, FALSE, NULL,
-					   _("Page"), G_CALLBACK(send_to_mobile_cb),
-					   _("Close"), G_CALLBACK(close_mobile_page_cb),
-					   account, name, NULL,
-					   data);
-}
-
-static gboolean
-msn_offline_message(const PurpleBuddy *buddy) {
-	return TRUE;
-}
-
-void
-msn_send_privacy(PurpleConnection *gc)
-{
-	PurpleAccount *account;
-	MsnSession *session;
-	MsnCmdProc *cmdproc;
-	MsnTransaction *trans;
-
-	account = purple_connection_get_account(gc);
-	session = gc->proto_data;
-	cmdproc = session->notification->cmdproc;
-
-	if (account->perm_deny == PURPLE_PRIVACY_ALLOW_ALL ||
-	    account->perm_deny == PURPLE_PRIVACY_DENY_USERS)
-		trans = msn_transaction_new(cmdproc, "BLP", "%s", "AL");
-	else
-		trans = msn_transaction_new(cmdproc, "BLP", "%s", "BL");
-
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-static void
-initiate_chat_cb(PurpleBlistNode *node, gpointer data)
-{
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-	PurpleAccount *account;
-
-	MsnSession *session;
-	MsnSwitchBoard *swboard;
-
-	const char *alias;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *) node;
-	account = purple_buddy_get_account(buddy);
-	gc = purple_account_get_connection(account);
-
-	session = gc->proto_data;
-
-	swboard = msn_switchboard_new(session);
-	msn_switchboard_request(swboard);
-	msn_switchboard_request_add_user(swboard, purple_buddy_get_name(buddy));
-
-	/* TODO: This might move somewhere else, after USR might be */
-	swboard->chat_id = msn_switchboard_get_chat_id();
-	swboard->conv = serv_got_joined_chat(gc, swboard->chat_id, "MSN Chat");
-	swboard->flag = MSN_SB_FLAG_IM;
-
-	/* Local alias > Display name > Username */
-	if ((alias = purple_account_get_alias(account)) == NULL)
-		if ((alias = purple_connection_get_display_name(gc)) == NULL)
-			alias = purple_account_get_username(account);
-
-	purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv),
-	                          alias, NULL, PURPLE_CBFLAGS_NONE, TRUE);
-}
-
-static void
-t_msn_xfer_init(PurpleXfer *xfer)
-{
-	msn_request_ft(xfer);
-}
-
-static void
-t_msn_xfer_cancel_send(PurpleXfer *xfer)
-{
-	MsnSlpLink *slplink = xfer->data;
-	msn_slplink_unref(slplink);
-}
-
-static PurpleXfer*
-msn_new_xfer(PurpleConnection *gc, const char *who)
-{
-	MsnSession *session;
-	PurpleXfer *xfer;
-
-	session = gc->proto_data;
-
-	xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who);
-
-	g_return_val_if_fail(xfer != NULL, NULL);
-
-	xfer->data = msn_slplink_ref(msn_session_get_slplink(session, who));
-
-	purple_xfer_set_init_fnc(xfer, t_msn_xfer_init);
-	purple_xfer_set_cancel_send_fnc(xfer, t_msn_xfer_cancel_send);
-
-	return xfer;
-}
-
-static void
-msn_send_file(PurpleConnection *gc, const char *who, const char *file)
-{
-	PurpleXfer *xfer = msn_new_xfer(gc, who);
-
-	if (file)
-		purple_xfer_request_accepted(xfer, file);
-	else
-		purple_xfer_request(xfer);
-}
-
-static gboolean
-msn_can_receive_file(PurpleConnection *gc, const char *who)
-{
-	PurpleAccount *account;
-	gchar *normal;
-	gboolean ret;
-
-	account = purple_connection_get_account(gc);
-
-	normal = g_strdup(msn_normalize(account, purple_account_get_username(account)));
-	ret = strcmp(normal, msn_normalize(account, who));
-	g_free(normal);
-
-	if (ret) {
-		MsnSession *session = gc->proto_data;
-		if (session) {
-			MsnUser *user = msn_userlist_find_user(session->userlist, who);
-			if (user) {
-				/* Include these too: MSN_CAP_MOBILE_ON|MSN_CAP_WEB_WATCH ? */
-				if ((user->clientid & MSN_CAP_VIA_WEBIM) ||
-						user->networkid == MSN_NETWORK_YAHOO)
-					ret = FALSE;
-				else
-					ret = TRUE;
-			}
-		} else
-			ret = FALSE;
-	}
-
-	return ret;
-}
-
-/**************************************************************************
- * Protocol Plugin ops
- **************************************************************************/
-
-static const char *
-msn_list_icon(PurpleAccount *a, PurpleBuddy *b)
-{
-	return "msn";
-}
-
-static const char *
-msn_list_emblems(PurpleBuddy *b)
-{
-	MsnUser *user = purple_buddy_get_protocol_data(b);
-
-	if (user != NULL) {
-		if (user->clientid & MSN_CAP_BOT)
-			return "bot";
-		if (user->clientid & MSN_CAP_VIA_MOBILE)
-			return "mobile";
-#if 0
-		/* XXX: Since we don't support this, there's no point in showing it just yet */
-		if (user->clientid & MSN_CAP_SCHANNEL)
-			return "secure";
-#endif
-		if (user->clientid & MSN_CAP_VIA_WEBIM)
-			return "external";
-		if (user->networkid == MSN_NETWORK_YAHOO)
-			return "yahoo";
-	}
-
-	return NULL;
-}
-
-/*
- * Set the User status text
- */
-static char *
-msn_status_text(PurpleBuddy *buddy)
-{
-	PurplePresence *presence;
-	PurpleStatus *status;
-	const char *msg;
-
-	presence = purple_buddy_get_presence(buddy);
-	status = purple_presence_get_active_status(presence);
-
-	/* Official client says media takes precedence over message */
-	/* I say message take precedence over media! Plus prpl-jabber agrees
-	   too */
-	msg = purple_status_get_attr_string(status, "message");
-	if (msg && *msg)
-		return g_markup_escape_text(msg, -1);
-
-	if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
-		const char *title, *game, *office;
-		char *media, *esc;
-		status = purple_presence_get_status(presence, "tune");
-		title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
-
-		game = purple_status_get_attr_string(status, "game");
-		office = purple_status_get_attr_string(status, "office");
-
-		if (title && *title) {
-			const char *artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
-			const char *album = purple_status_get_attr_string(status, PURPLE_TUNE_ALBUM);
-			media = purple_util_format_song_info(title, artist, album, NULL);
-			return media;
-		}
-		else if (game && *game)
-			media = g_strdup_printf("Playing %s", game);
-		else if (office && *office)
-			media = g_strdup_printf("Editing %s", office);
-		else
-			return NULL;
-		esc = g_markup_escape_text(media, -1);
-		g_free(media);
-		return esc;
-	}
-
-	return NULL;
-}
-
-static void
-msn_tooltip_text(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, gboolean full)
-{
-	MsnUser *user;
-	PurplePresence *presence = purple_buddy_get_presence(buddy);
-	PurpleStatus *status = purple_presence_get_active_status(presence);
-
-	user = purple_buddy_get_protocol_data(buddy);
-
-	if (purple_presence_is_online(presence))
-	{
-		const char *psm, *name;
-		const char *mediatype = NULL;
-		char *currentmedia = NULL;
-
-		psm = purple_status_get_attr_string(status, "message");
-		if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
-			PurpleStatus *tune = purple_presence_get_status(presence, "tune");
-			const char *title = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE);
-			const char *game = purple_status_get_attr_string(tune, "game");
-			const char *office = purple_status_get_attr_string(tune, "office");
-			if (title && *title) {
-				const char *artist = purple_status_get_attr_string(tune, PURPLE_TUNE_ARTIST);
-				const char *album = purple_status_get_attr_string(tune, PURPLE_TUNE_ALBUM);
-				mediatype = _("Now Listening");
-				currentmedia = purple_util_format_song_info(title, artist, album, NULL);
-			} else if (game && *game) {
-				mediatype = _("Playing a game");
-				currentmedia = g_strdup(game);
-			} else if (office && *office) {
-				mediatype = _("Working");
-				currentmedia = g_strdup(office);
-			}
-		}
-
-		if (!purple_status_is_available(status)) {
-			name = purple_status_get_name(status);
-		} else {
-			name = NULL;
-		}
-
-		if (name != NULL && *name) {
-			char *tmp2;
-
-			tmp2 = g_markup_escape_text(name, -1);
-			if (purple_presence_is_idle(presence)) {
-				char *idle;
-				char *tmp3;
-				/* Never know what those translations might end up like... */
-				idle = g_markup_escape_text(_("Idle"), -1);
-				tmp3 = g_strdup_printf("%s/%s", tmp2, idle);
-				g_free(idle);
-				g_free(tmp2);
-				tmp2 = tmp3;
-			}
-
-			if (psm != NULL && *psm) {
-				purple_notify_user_info_add_pair_plaintext(user_info, tmp2, psm);
-			} else {
-				purple_notify_user_info_add_pair(user_info, _("Status"), tmp2);
-			}
-
-			g_free(tmp2);
-		} else {
-			if (psm != NULL && *psm) {
-				if (purple_presence_is_idle(presence)) {
-					purple_notify_user_info_add_pair_plaintext(user_info, _("Idle"), psm);
-				} else {
-					purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), psm);
-				}
-			} else {
-				if (purple_presence_is_idle(presence)) {
-					purple_notify_user_info_add_pair(user_info, _("Status"),
-						_("Idle"));
-				} else {
-					purple_notify_user_info_add_pair(user_info, _("Status"),
-						purple_status_get_name(status));
-				}
-			}
-		}
-
-		if (currentmedia) {
-			purple_notify_user_info_add_pair(user_info, mediatype, currentmedia);
-			g_free(currentmedia);
-		}
-	}
-
-	/* XXX: This is being shown in non-full tooltips because the
-	 * XXX: blocked icon overlay isn't always accurate for MSN.
-	 * XXX: This can die as soon as purple_privacy_check() knows that
-	 * XXX: this prpl always honors both the allow and deny lists. */
-	/* While the above comment may be strictly correct (the privacy API needs
-	 * rewriteing), purple_privacy_check() is going to be more accurate at
-	 * indicating whether a particular buddy is going to be able to message
-	 * you, which is the important information that this is trying to convey.
-	 */
-	if (full && user)
-	{
-		const char *phone;
-
-		purple_notify_user_info_add_pair(user_info, _("Has you"),
-									   ((user->list_op & (1 << MSN_LIST_RL)) ? _("Yes") : _("No")));
-
-		purple_notify_user_info_add_pair(user_info, _("Blocked"),
-									   ((user->list_op & (1 << MSN_LIST_BL)) ? _("Yes") : _("No")));
-
-		phone = msn_user_get_home_phone(user);
-		if (phone != NULL)
-			purple_notify_user_info_add_pair(user_info, _("Home Phone Number"), phone);
-
-		phone = msn_user_get_work_phone(user);
-		if (phone != NULL)
-			purple_notify_user_info_add_pair(user_info, _("Work Phone Number"), phone);
-
-		phone = msn_user_get_mobile_phone(user);
-		if (phone != NULL)
-			purple_notify_user_info_add_pair(user_info, _("Mobile Phone Number"), phone);
-	}
-}
-
-static GList *
-msn_status_types(PurpleAccount *account)
-{
-	PurpleStatusType *status;
-	GList *types = NULL;
-
-	status = purple_status_type_new_with_attrs(
-				PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE, TRUE, FALSE,
-				"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-				NULL);
-	types = g_list_append(types, status);
-
-	status = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_AWAY, NULL, NULL, TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
-	types = g_list_append(types, status);
-
-	status = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_AWAY, "brb", _("Be Right Back"), TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
-	types = g_list_append(types, status);
-
-	status = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_UNAVAILABLE, "busy", _("Busy"), TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
-	types = g_list_append(types, status);
-	status = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_UNAVAILABLE, "phone", _("On the Phone"), TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
-	types = g_list_append(types, status);
-	status = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_AWAY, "lunch", _("Out to Lunch"), TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
-	types = g_list_append(types, status);
-
-	status = purple_status_type_new_full(PURPLE_STATUS_INVISIBLE,
-			NULL, NULL, TRUE, TRUE, FALSE);
-	types = g_list_append(types, status);
-
-	status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE,
-			NULL, NULL, TRUE, TRUE, FALSE);
-	types = g_list_append(types, status);
-
-	status = purple_status_type_new_full(PURPLE_STATUS_MOBILE,
-			"mobile", NULL, FALSE, FALSE, TRUE);
-	types = g_list_append(types, status);
-
-	status = purple_status_type_new_with_attrs(PURPLE_STATUS_TUNE,
-			"tune", NULL, FALSE, TRUE, TRUE,
-			PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING),
-			"game", _("Game Title"), purple_value_new(PURPLE_TYPE_STRING),
-			"office", _("Office Title"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
-	types = g_list_append(types, status);
-
-	return types;
-}
-
-static GList *
-msn_actions(PurplePlugin *plugin, gpointer context)
-{
-	PurpleConnection *gc;
-	MsnSession *session;
-	GList *m = NULL;
-	PurplePluginAction *act;
-
-	gc = (PurpleConnection *) context;
-	session = gc->proto_data;
-
-	act = purple_plugin_action_new(_("Set Friendly Name..."),
-								 msn_show_set_friendly_name);
-	m = g_list_append(m, act);
-	m = g_list_append(m, NULL);
-
-	if (session->enable_mpop)
-	{
-		act = purple_plugin_action_new(_("View Locations..."),
-		                               msn_show_locations);
-		m = g_list_append(m, act);
-		m = g_list_append(m, NULL);
-	}
-
-	act = purple_plugin_action_new(_("Set Home Phone Number..."),
-								 msn_show_set_home_phone);
-	m = g_list_append(m, act);
-
-	act = purple_plugin_action_new(_("Set Work Phone Number..."),
-			msn_show_set_work_phone);
-	m = g_list_append(m, act);
-
-	act = purple_plugin_action_new(_("Set Mobile Phone Number..."),
-			msn_show_set_mobile_phone);
-	m = g_list_append(m, act);
-	m = g_list_append(m, NULL);
-
-#if 0
-	act = purple_plugin_action_new(_("Enable/Disable Mobile Devices..."),
-			msn_show_set_mobile_support);
-	m = g_list_append(m, act);
-#endif
-
-	act = purple_plugin_action_new(_("Allow/Disallow Multiple Logins..."),
-			msn_show_set_mpop);
-	m = g_list_append(m, act);
-
-	act = purple_plugin_action_new(_("Allow/Disallow Mobile Pages..."),
-			msn_show_set_mobile_pages);
-	m = g_list_append(m, act);
-
-/* QuLogic: Disabled until confirmed correct. */
-#if 0
-	m = g_list_append(m, NULL);
-	act = purple_plugin_action_new(_("View Blocked Text..."),
-			msn_show_blocked_text);
-	m = g_list_append(m, act);
-#endif
-
-	m = g_list_append(m, NULL);
-	act = purple_plugin_action_new(_("Open Hotmail Inbox"),
-			msn_show_hotmail_inbox);
-	m = g_list_append(m, act);
-
-	return m;
-}
-
-static GList *
-msn_buddy_menu(PurpleBuddy *buddy)
-{
-	MsnUser *user;
-
-	GList *m = NULL;
-	PurpleMenuAction *act;
-
-	g_return_val_if_fail(buddy != NULL, NULL);
-
-	user = purple_buddy_get_protocol_data(buddy);
-
-	if (user != NULL)
-	{
-		if (user->mobile)
-		{
-			act = purple_menu_action_new(_("Send to Mobile"),
-			                           PURPLE_CALLBACK(show_send_to_mobile_cb),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		}
-	}
-
-	if (g_ascii_strcasecmp(purple_buddy_get_name(buddy),
-				purple_account_get_username(purple_buddy_get_account(buddy))))
-	{
-		act = purple_menu_action_new(_("Initiate _Chat"),
-		                           PURPLE_CALLBACK(initiate_chat_cb),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-	}
-
-	return m;
-}
-
-static GList *
-msn_blist_node_menu(PurpleBlistNode *node)
-{
-	if(PURPLE_BLIST_NODE_IS_BUDDY(node))
-	{
-		return msn_buddy_menu((PurpleBuddy *) node);
-	}
-	else
-	{
-		return NULL;
-	}
-}
-
-static void
-msn_login(PurpleAccount *account)
-{
-	PurpleConnection *gc;
-	MsnSession *session;
-	const char *username;
-	const char *host;
-	gboolean http_method = FALSE;
-	int port;
-
-	gc = purple_account_get_connection(account);
-
-	if (!purple_ssl_is_supported())
-	{
-		purple_connection_error_reason(gc,
-			PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
-			_("SSL support is needed for MSN. Please install a supported "
-			  "SSL library."));
-		return;
-	}
-
-	http_method = purple_account_get_bool(account, "http_method", FALSE);
-
-	if (http_method)
-		host = purple_account_get_string(account, "http_method_server", MSN_HTTPCONN_SERVER);
-	else
-		host = purple_account_get_string(account, "server", MSN_SERVER);
-	port = purple_account_get_int(account, "port", MSN_PORT);
-
-	session = msn_session_new(account);
-
-	gc->proto_data = session;
-	gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_FORMATTING_WBFO | PURPLE_CONNECTION_NO_BGCOLOR |
-		PURPLE_CONNECTION_NO_FONTSIZE | PURPLE_CONNECTION_NO_URLDESC | PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY;
-
-	msn_session_set_login_step(session, MSN_LOGIN_STEP_START);
-
-	/* Hmm, I don't like this. */
-	/* XXX shx: Me neither */
-	username = msn_normalize(account, purple_account_get_username(account));
-
-	if (strcmp(username, purple_account_get_username(account)))
-		purple_account_set_username(account, username);
-
-	username = purple_account_get_string(account, "display-name", NULL);
-	purple_connection_set_display_name(gc, username);
-
-	if (purple_account_get_string(account, "endpoint-name", NULL) == NULL) {
-		GHashTable *ui_info = purple_core_get_ui_info();
-		const gchar *ui_name = ui_info ? g_hash_table_lookup(ui_info, "name") : NULL;
-		purple_account_set_string(account, "endpoint-name",
-				ui_name && *ui_name ? ui_name : PACKAGE_NAME);
-	}
-
-	if (!msn_session_connect(session, host, port, http_method))
-		purple_connection_error_reason(gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("Unable to connect"));
-}
-
-static void
-msn_close(PurpleConnection *gc)
-{
-	MsnSession *session;
-
-	session = gc->proto_data;
-
-	g_return_if_fail(session != NULL);
-
-	msn_session_destroy(session);
-
-	gc->proto_data = NULL;
-}
-
-static gboolean
-msn_send_me_im(gpointer data)
-{
-	MsnIMData *imdata = data;
-	serv_got_im(imdata->gc, imdata->who, imdata->msg, imdata->flags, imdata->when);
-	g_free(imdata->msg);
-	g_free(imdata);
-	return FALSE;
-}
-
-static GString*
-msn_msg_emoticon_add(GString *current, MsnEmoticon *emoticon)
-{
-	MsnObject *obj;
-	char *strobj;
-
-	if (emoticon == NULL)
-		return current;
-
-	obj = emoticon->obj;
-
-	if (!obj)
-		return current;
-
-	strobj = msn_object_to_string(obj);
-
-	if (current)
-		g_string_append_printf(current, "\t%s\t%s", emoticon->smile, strobj);
-	else {
-		current = g_string_new("");
-		g_string_printf(current, "%s\t%s", emoticon->smile, strobj);
-	}
-
-	g_free(strobj);
-
-	return current;
-}
-
-static void
-msn_send_emoticons(MsnSwitchBoard *swboard, GString *body)
-{
-	MsnMessage *msg;
-
-	g_return_if_fail(body != NULL);
-
-	msg = msn_message_new(MSN_MSG_SLP);
-	msn_message_set_content_type(msg, "text/x-mms-emoticon");
-	msn_message_set_flag(msg, 'N');
-	msn_message_set_bin_data(msg, body->str, body->len);
-
-	msn_switchboard_send_msg(swboard, msg, TRUE);
-	msn_message_unref(msg);
-}
-
-static void msn_emoticon_destroy(MsnEmoticon *emoticon)
-{
-	if (emoticon->obj)
-		msn_object_destroy(emoticon->obj);
-	g_free(emoticon->smile);
-	g_free(emoticon);
-}
-
-static GSList* msn_msg_grab_emoticons(const char *msg, const char *username)
-{
-	GSList *list;
-	GList *smileys;
-	PurpleSmiley *smiley;
-	PurpleStoredImage *img;
-	char *ptr;
-	MsnEmoticon *emoticon;
-	int length;
-
-	list = NULL;
-	smileys = purple_smileys_get_all();
-	length = strlen(msg);
-
-	for (; smileys; smileys = g_list_delete_link(smileys, smileys)) {
-		smiley = smileys->data;
-
-		ptr = g_strstr_len(msg, length, purple_smiley_get_shortcut(smiley));
-
-		if (!ptr)
-			continue;
-
-		img = purple_smiley_get_stored_image(smiley);
-
-		emoticon = g_new0(MsnEmoticon, 1);
-		emoticon->smile = g_strdup(purple_smiley_get_shortcut(smiley));
-		emoticon->ps = smiley;
-		emoticon->obj = msn_object_new_from_image(img,
-				purple_imgstore_get_filename(img),
-				username, MSN_OBJECT_EMOTICON);
-
-		purple_imgstore_unref(img);
-		list = g_slist_prepend(list, emoticon);
-	}
-
-	return list;
-}
-
-void
-msn_send_im_message(MsnSession *session, MsnMessage *msg)
-{
-	MsnEmoticon *smile;
-	GSList *smileys;
-	GString *emoticons = NULL;
-	const char *username = purple_account_get_username(session->account);
-	MsnSwitchBoard *swboard = msn_session_get_swboard(session, msg->remote_user, MSN_SB_FLAG_IM);
-
-	smileys = msn_msg_grab_emoticons(msg->body, username);
-	while (smileys) {
-		smile = (MsnEmoticon *)smileys->data;
-		emoticons = msn_msg_emoticon_add(emoticons, smile);
-		msn_emoticon_destroy(smile);
-		smileys = g_slist_delete_link(smileys, smileys);
-	}
-
-	if (emoticons) {
-		msn_send_emoticons(swboard, emoticons);
-		g_string_free(emoticons, TRUE);
-	}
-
-	msn_switchboard_send_msg(swboard, msg, TRUE);
-}
-
-static int
-msn_send_im(PurpleConnection *gc, const char *who, const char *message,
-			PurpleMessageFlags flags)
-{
-	PurpleAccount *account;
-	PurpleBuddy *buddy = purple_find_buddy(gc->account, who);
-	MsnSession *session;
-	MsnSwitchBoard *swboard;
-	MsnMessage *msg;
-	char *msgformat;
-	char *msgtext;
-	size_t msglen;
-	const char *username;
-
-	purple_debug_info("msn", "send IM {%s} to %s\n", message, who);
-	account = purple_connection_get_account(gc);
-	username = purple_account_get_username(account);
-
-	session = gc->proto_data;
-	swboard = msn_session_find_swboard(session, who);
-
-	if (!strncmp("tel:+", who, 5)) {
-		char *text = purple_markup_strip_html(message);
-		send_to_mobile(gc, who, text);
-		g_free(text);
-		return 1;
-	}
-
-	if (buddy) {
-		PurplePresence *p = purple_buddy_get_presence(buddy);
-		if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_MOBILE)) {
-			char *text = purple_markup_strip_html(message);
-			send_to_mobile(gc, who, text);
-			g_free(text);
-			return 1;
-		}
-	}
-
-	msn_import_html(message, &msgformat, &msgtext);
-	msglen = strlen(msgtext);
-	if (msglen == 0) {
-		/* Stuff like <hr> will be ignored. Don't send an empty message
-		   if that's all there is. */
-		g_free(msgtext);
-		g_free(msgformat);
-
-		return 0;
-	}
-
-	if (msglen + strlen(msgformat) + strlen(VERSION) > 1564)
-	{
-		g_free(msgformat);
-		g_free(msgtext);
-
-		return -E2BIG;
-	}
-
-	msg = msn_message_new_plain(msgtext);
-	msg->remote_user = g_strdup(who);
-	msn_message_set_header(msg, "X-MMS-IM-Format", msgformat);
-
-	g_free(msgformat);
-	g_free(msgtext);
-
-	if (g_ascii_strcasecmp(who, username))
-	{
-		if (flags & PURPLE_MESSAGE_AUTO_RESP) {
-			msn_message_set_flag(msg, 'U');
-		}
-
-		if (msn_user_is_yahoo(account, who) || !(msn_user_is_online(account, who) || swboard != NULL)) {
-			/*we send the online and offline Message to Yahoo User via UBM*/
-			purple_debug_info("msn", "send to offline or Yahoo user\n");
-			msn_notification_send_uum(session, msg);
-		} else {
-			purple_debug_info("msn", "send via switchboard\n");
-			msn_send_im_message(session, msg);
-		}
-	}
-	else
-	{
-		char *body_str, *body_enc, *pre, *post;
-		const char *format;
-		MsnIMData *imdata = g_new0(MsnIMData, 1);
-		/*
-		 * In MSN, you can't send messages to yourself, so
-		 * we'll fake like we received it ;)
-		 */
-		body_str = msn_message_to_string(msg);
-		body_enc = g_markup_escape_text(body_str, -1);
-		g_free(body_str);
-
-		format = msn_message_get_header_value(msg, "X-MMS-IM-Format");
-		msn_parse_format(format, &pre, &post);
-		body_str = g_strdup_printf("%s%s%s", pre ? pre :  "",
-								   body_enc ? body_enc : "", post ? post : "");
-		g_free(body_enc);
-		g_free(pre);
-		g_free(post);
-
-		serv_got_typing_stopped(gc, who);
-		imdata->gc = gc;
-		imdata->who = who;
-		imdata->msg = body_str;
-		imdata->flags = flags & ~PURPLE_MESSAGE_SEND;
-		imdata->when = time(NULL);
-		purple_timeout_add(0, msn_send_me_im, imdata);
-	}
-
-	msn_message_unref(msg);
-
-	return 1;
-}
-
-static unsigned int
-msn_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state)
-{
-	PurpleAccount *account;
-	MsnSession *session;
-	MsnSwitchBoard *swboard;
-	MsnMessage *msg;
-
-	account = purple_connection_get_account(gc);
-	session = gc->proto_data;
-
-	/*
-	 * TODO: I feel like this should be "if (state != PURPLE_TYPING)"
-	 *       but this is how it was before, and I don't want to break
-	 *       anything. --KingAnt
-	 */
-	if (state == PURPLE_NOT_TYPING)
-		return 0;
-
-	if (!g_ascii_strcasecmp(who, purple_account_get_username(account)))
-	{
-		/* We'll just fake it, since we're sending to ourself. */
-		serv_got_typing(gc, who, MSN_TYPING_RECV_TIMEOUT, PURPLE_TYPING);
-
-		return MSN_TYPING_SEND_TIMEOUT;
-	}
-
-	swboard = msn_session_find_swboard(session, who);
-
-	if (swboard == NULL || !msn_switchboard_can_send(swboard))
-		return 0;
-
-	swboard->flag |= MSN_SB_FLAG_IM;
-
-	msg = msn_message_new(MSN_MSG_TYPING);
-	msn_message_set_content_type(msg, "text/x-msmsgscontrol");
-	msn_message_set_flag(msg, 'U');
-	msn_message_set_header(msg, "TypingUser",
-						 purple_account_get_username(account));
-	msn_message_set_bin_data(msg, "\r\n", 2);
-
-	msn_switchboard_send_msg(swboard, msg, FALSE);
-
-	msn_message_unref(msg);
-
-	return MSN_TYPING_SEND_TIMEOUT;
-}
-
-static void
-msn_set_status(PurpleAccount *account, PurpleStatus *status)
-{
-	PurpleConnection *gc;
-	MsnSession *session;
-
-	gc = purple_account_get_connection(account);
-
-	if (gc != NULL)
-	{
-		session = gc->proto_data;
-		msn_change_status(session);
-	}
-}
-
-static void
-msn_set_idle(PurpleConnection *gc, int idle)
-{
-	MsnSession *session;
-
-	session = gc->proto_data;
-
-	msn_change_status(session);
-}
-
-/*
- * Actually adds a buddy once we have the response from FQY
- */
-static void
-add_pending_buddy(MsnSession *session,
-                  const char *who,
-                  MsnNetwork network,
-                  MsnUser *user)
-{
-	char *group;
-	MsnUserList *userlist;
-	MsnUser *user2;
-
-	g_return_if_fail(user != NULL);
-
-	if (network == MSN_NETWORK_UNKNOWN) {
-		purple_debug_error("msn", "Network in FQY response was unknown.  "
-				"Assuming %s is a passport user and adding anyway.\n", who);
-		network = MSN_NETWORK_PASSPORT;
-	}
-
-	group = msn_user_remove_pending_group(user);
-
-	userlist = session->userlist;
-	user2 = msn_userlist_find_user(userlist, who);
-	if (user2 != NULL) {
-		/* User already in userlist, so just update it. */
-		msn_user_unref(user);
-		user = user2;
-	} else {
-		msn_userlist_add_user(userlist, user);
-		msn_user_unref(user);
-	}
-
-	msn_user_set_network(user, network);
-	msn_userlist_add_buddy(userlist, who, group);
-
-	g_free(group);
-}
-
-static void
-msn_add_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group, const char *message)
-{
-	PurpleAccount *account;
-	const char *bname, *gname;
-	MsnSession *session;
-	MsnUserList *userlist;
-	MsnUser *user;
-
-	account = purple_connection_get_account(pc);
-	session = purple_connection_get_protocol_data(pc);
-	bname = purple_buddy_get_name(buddy);
-
-	if (!session->logged_in)
-	{
-		purple_debug_error("msn", "msn_add_buddy called before connected\n");
-
-		return;
-	}
-
-	/* XXX - Would group ever be NULL here?  I don't think so...
-	 * shx: Yes it should; MSN handles non-grouped buddies, and this is only
-	 * internal.
-	 * KingAnt: But PurpleBuddys must always exist inside PurpleGroups, so
-	 * won't group always be non-NULL here?
-	 */
-	bname = msn_normalize(account, bname);
-	gname = group ? purple_group_get_name(group) : NULL;
-	purple_debug_info("msn", "Add user:%s to group:%s\n",
-	                  bname, gname ? gname : "(null)");
-
-	if (!msn_email_is_valid(bname)) {
-		gchar *buf;
-		buf = g_strdup_printf(_("Unable to add the buddy %s because the username is invalid.  Usernames must be valid email addresses."), bname);
-		if (!purple_conv_present_error(bname, account, buf))
-			purple_notify_error(pc, NULL, _("Unable to Add"), buf);
-		g_free(buf);
-
-		/* Remove from local list */
-		purple_blist_remove_buddy(buddy);
-
-		return;
-	}
-
-	/* Make sure name is normalized */
-	purple_blist_rename_buddy(buddy, bname);
-
-	userlist = session->userlist;
-	user = msn_userlist_find_user(userlist, bname);
-	if (user && user->authorized) {
-		message = NULL;
-	}
-	if ((user != NULL) && (user->networkid != MSN_NETWORK_UNKNOWN)) {
-		/* We already know this buddy and their network. This function knows
-		   what to do with users already in the list and stuff... */
-		msn_user_set_invite_message(user, message);
-		msn_userlist_add_buddy(userlist, bname, gname);
-	} else {
-		char **tokens;
-		char *fqy;
-		/* We need to check the network for this buddy first */
-		user = msn_user_new(userlist, bname, NULL);
-		msn_user_set_invite_message(user, message);
-		msn_user_set_pending_group(user, gname);
-		msn_user_set_network(user, MSN_NETWORK_UNKNOWN);
-		/* Should probably re-use the msn_add_contact_xml function here */
-		tokens = g_strsplit(bname, "@", 2);
-		fqy = g_strdup_printf("<ml><d n=\"%s\"><c n=\"%s\"/></d></ml>",
-		                      tokens[1],
-		                      tokens[0]);
-		/* TODO: I think user will leak if we disconnect before receiving
-		         a response to this FQY request */
-		msn_notification_send_fqy(session, fqy, strlen(fqy),
-		                          (MsnFqyCb)add_pending_buddy, user);
-		g_free(fqy);
-		g_strfreev(tokens);
-	}
-}
-
-static void
-msn_rem_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
-{
-	MsnSession *session;
-	MsnUserList *userlist;
-
-	session = gc->proto_data;
-	userlist = session->userlist;
-
-	if (!session->logged_in)
-		return;
-
-	/* XXX - Does buddy->name need to be msn_normalize'd here?  --KingAnt */
-	msn_userlist_rem_buddy(userlist, purple_buddy_get_name(buddy));
-}
-
-static void
-msn_add_permit(PurpleConnection *gc, const char *who)
-{
-	MsnSession *session;
-	MsnUserList *userlist;
-	MsnUser *user;
-
-	session = gc->proto_data;
-	userlist = session->userlist;
-	user = msn_userlist_find_user(userlist, who);
-
-	if (!session->logged_in)
-		return;
-
-	if (user != NULL && user->list_op & MSN_LIST_BL_OP) {
-		msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_BL);
-
-		/* delete contact from Block list and add it to Allow in the callback */
-		msn_del_contact_from_list(session, NULL, who, MSN_LIST_BL);
-	} else {
-		/* just add the contact to Allow list */
-		msn_add_contact_to_list(session, NULL, who, MSN_LIST_AL);
-	}
-
-
-	msn_userlist_add_buddy_to_list(userlist, who, MSN_LIST_AL);
-}
-
-static void
-msn_add_deny(PurpleConnection *gc, const char *who)
-{
-	MsnSession *session;
-	MsnUserList *userlist;
-	MsnUser *user;
-
-	session = gc->proto_data;
-	userlist = session->userlist;
-	user = msn_userlist_find_user(userlist, who);
-
-	if (!session->logged_in)
-		return;
-
-	if (user != NULL && user->list_op & MSN_LIST_AL_OP) {
-		msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_AL);
-
-		/* delete contact from Allow list and add it to Block in the callback */
-		msn_del_contact_from_list(session, NULL, who, MSN_LIST_AL);
-	} else {
-		/* just add the contact to Block list */
-		msn_add_contact_to_list(session, NULL, who, MSN_LIST_BL);
-	}
-
-	msn_userlist_add_buddy_to_list(userlist, who, MSN_LIST_BL);
-}
-
-static void
-msn_rem_permit(PurpleConnection *gc, const char *who)
-{
-	MsnSession *session;
-	MsnUserList *userlist;
-	MsnUser *user;
-
-	session = gc->proto_data;
-	userlist = session->userlist;
-
-	if (!session->logged_in)
-		return;
-
-	user = msn_userlist_find_user(userlist, who);
-
-	msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_AL);
-
-	msn_del_contact_from_list(session, NULL, who, MSN_LIST_AL);
-
-	if (user != NULL && user->list_op & MSN_LIST_RL_OP)
-		msn_userlist_add_buddy_to_list(userlist, who, MSN_LIST_BL);
-}
-
-static void
-msn_rem_deny(PurpleConnection *gc, const char *who)
-{
-	MsnSession *session;
-	MsnUserList *userlist;
-	MsnUser *user;
-
-	session = gc->proto_data;
-	userlist = session->userlist;
-
-	if (!session->logged_in)
-		return;
-
-	user = msn_userlist_find_user(userlist, who);
-
-	msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_BL);
-
-	msn_del_contact_from_list(session, NULL, who, MSN_LIST_BL);
-
-	if (user != NULL && user->list_op & MSN_LIST_RL_OP)
-		msn_userlist_add_buddy_to_list(userlist, who, MSN_LIST_AL);
-}
-
-static void
-msn_set_permit_deny(PurpleConnection *gc)
-{
-	msn_send_privacy(gc);
-}
-
-static void
-msn_chat_invite(PurpleConnection *gc, int id, const char *msg,
-				const char *who)
-{
-	MsnSession *session;
-	MsnSwitchBoard *swboard;
-
-	session = gc->proto_data;
-
-	swboard = msn_session_find_swboard_with_id(session, id);
-
-	if (swboard == NULL)
-	{
-		/* if we have no switchboard, everyone else left the chat already */
-		swboard = msn_switchboard_new(session);
-		msn_switchboard_request(swboard);
-		swboard->chat_id = id;
-		swboard->conv = purple_find_chat(gc, id);
-	}
-
-	swboard->flag |= MSN_SB_FLAG_IM;
-
-	msn_switchboard_request_add_user(swboard, who);
-}
-
-static void
-msn_chat_leave(PurpleConnection *gc, int id)
-{
-	MsnSession *session;
-	MsnSwitchBoard *swboard;
-	PurpleConversation *conv;
-
-	session = gc->proto_data;
-
-	swboard = msn_session_find_swboard_with_id(session, id);
-
-	/* if swboard is NULL we were the only person left anyway */
-	if (swboard == NULL)
-		return;
-
-	conv = swboard->conv;
-
-	msn_switchboard_release(swboard, MSN_SB_FLAG_IM);
-
-	/* If other switchboards managed to associate themselves with this
-	 * conv, make sure they know it's gone! */
-	if (conv != NULL)
-	{
-		while ((swboard = msn_session_find_swboard_with_conv(session, conv)) != NULL)
-			swboard->conv = NULL;
-	}
-}
-
-static int
-msn_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags)
-{
-	PurpleAccount *account;
-	MsnSession *session;
-	const char *username;
-	MsnSwitchBoard *swboard;
-	MsnMessage *msg;
-	char *msgformat;
-	char *msgtext;
-	size_t msglen;
-	MsnEmoticon *smile;
-	GSList *smileys;
-	GString *emoticons = NULL;
-
-	account = purple_connection_get_account(gc);
-	session = gc->proto_data;
-	username = purple_account_get_username(account);
-	swboard = msn_session_find_swboard_with_id(session, id);
-
-	if (swboard == NULL)
-		return -EINVAL;
-
-	if (!swboard->ready)
-		return 0;
-
-	swboard->flag |= MSN_SB_FLAG_IM;
-
-	msn_import_html(message, &msgformat, &msgtext);
-	msglen = strlen(msgtext);
-
-	if ((msglen == 0) || (msglen + strlen(msgformat) + strlen(VERSION) > 1564))
-	{
-		g_free(msgformat);
-		g_free(msgtext);
-
-		return -E2BIG;
-	}
-
-	msg = msn_message_new_plain(msgtext);
-	msn_message_set_header(msg, "X-MMS-IM-Format", msgformat);
-
-	smileys = msn_msg_grab_emoticons(msg->body, username);
-	while (smileys) {
-		smile = (MsnEmoticon *)smileys->data;
-		emoticons = msn_msg_emoticon_add(emoticons, smile);
-		if (purple_conv_custom_smiley_add(swboard->conv, smile->smile,
-		                                  "sha1", purple_smiley_get_checksum(smile->ps),
-		                                  FALSE)) {
-			gconstpointer data;
-			size_t len;
-			data = purple_smiley_get_data(smile->ps, &len);
-			purple_conv_custom_smiley_write(swboard->conv, smile->smile, data, len);
-			purple_conv_custom_smiley_close(swboard->conv, smile->smile);
-		}
-		msn_emoticon_destroy(smile);
-		smileys = g_slist_delete_link(smileys, smileys);
-	}
-
-	if (emoticons) {
-		msn_send_emoticons(swboard, emoticons);
-		g_string_free(emoticons, TRUE);
-	}
-
-	msn_switchboard_send_msg(swboard, msg, FALSE);
-	msn_message_unref(msg);
-
-	g_free(msgformat);
-	g_free(msgtext);
-
-	serv_got_chat_in(gc, id, purple_account_get_username(account), flags,
-					 message, time(NULL));
-
-	return 0;
-}
-
-static void
-msn_keepalive(PurpleConnection *gc)
-{
-	MsnSession *session;
-	MsnTransaction *trans;
-
-	session = gc->proto_data;
-
-	if (!session->http_method)
-	{
-		MsnCmdProc *cmdproc;
-
-		cmdproc = session->notification->cmdproc;
-
-		trans = msn_transaction_new(cmdproc, "PNG", NULL);
-		msn_transaction_set_saveable(trans, FALSE);
-		msn_cmdproc_send_trans(cmdproc, trans);
-	}
-}
-
-static void msn_alias_buddy(PurpleConnection *pc, const char *name, const char *alias)
-{
-	MsnSession *session;
-
-	session = pc->proto_data;
-
-	msn_update_contact(session, name, MSN_UPDATE_ALIAS, alias);
-}
-
-static void
-msn_group_buddy(PurpleConnection *gc, const char *who,
-				const char *old_group_name, const char *new_group_name)
-{
-	MsnSession *session;
-	MsnUserList *userlist;
-
-	session = gc->proto_data;
-	userlist = session->userlist;
-
-	msn_userlist_move_buddy(userlist, who, old_group_name, new_group_name);
-}
-
-static void
-msn_rename_group(PurpleConnection *gc, const char *old_name,
-				 PurpleGroup *group, GList *moved_buddies)
-{
-	MsnSession *session;
-	const char *gname;
-
-	session = gc->proto_data;
-
-	g_return_if_fail(session != NULL);
-	g_return_if_fail(session->userlist != NULL);
-
-	gname = purple_group_get_name(group);
-	if (msn_userlist_find_group_with_name(session->userlist, old_name) != NULL)
-	{
-		msn_contact_rename_group(session, old_name, gname);
-	}
-	else
-	{
-		/* not found */
-		msn_add_group(session, NULL, gname);
-	}
-}
-
-static void
-msn_convo_closed(PurpleConnection *gc, const char *who)
-{
-	MsnSession *session;
-	MsnSwitchBoard *swboard;
-	PurpleConversation *conv;
-
-	session = gc->proto_data;
-
-	swboard = msn_session_find_swboard(session, who);
-
-	/*
-	 * Don't perform an assertion here. If swboard is NULL, then the
-	 * switchboard was either closed by the other party, or the person
-	 * is talking to himself.
-	 */
-	if (swboard == NULL)
-		return;
-
-	conv = swboard->conv;
-
-	/* If we release the switchboard here, it may still have messages
-	   pending ACK which would result in incorrect unsent message errors.
-	   Just let it timeout... This is *so* going to screw with people who
-	   use dumb clients that report "User has closed the conversation window" */
-	/* msn_switchboard_release(swboard, MSN_SB_FLAG_IM); */
-	swboard->conv = NULL;
-
-	/* If other switchboards managed to associate themselves with this
-	 * conv, make sure they know it's gone! */
-	if (conv != NULL)
-	{
-		while ((swboard = msn_session_find_swboard_with_conv(session, conv)) != NULL)
-			swboard->conv = NULL;
-	}
-}
-
-static void
-msn_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img)
-{
-	MsnSession *session;
-	MsnUser *user;
-
-	session = gc->proto_data;
-	user = session->user;
-
-	msn_user_set_buddy_icon(user, img);
-
-	msn_change_status(session);
-}
-
-static void
-msn_remove_group(PurpleConnection *gc, PurpleGroup *group)
-{
-	MsnSession *session;
-	const char *gname;
-
-	session = gc->proto_data;
-	gname = purple_group_get_name(group);
-
-	purple_debug_info("msn", "Remove group %s\n", gname);
-	/*we can't delete the default group*/
-	if(!strcmp(gname, MSN_INDIVIDUALS_GROUP_NAME)||
-		!strcmp(gname, MSN_NON_IM_GROUP_NAME))
-	{
-		purple_debug_info("msn", "This group can't be removed, returning.\n");
-		return ;
-	}
-
-	msn_del_group(session, gname);
-}
-
-/**
- * Extract info text from info_data and add it to user_info
- */
-static gboolean
-msn_tooltip_extract_info_text(PurpleNotifyUserInfo *user_info, MsnGetInfoData *info_data)
-{
-	PurpleBuddy *b;
-
-	b = purple_find_buddy(purple_connection_get_account(info_data->gc),
-						info_data->name);
-
-	if (b)
-	{
-		char *tmp;
-		const char *alias;
-
-		alias = purple_buddy_get_local_buddy_alias(b);
-		if (alias && alias[0])
-		{
-			purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), alias);
-		}
-
-		if ((alias = purple_buddy_get_server_alias(b)) != NULL)
-		{
-			char *nicktext = g_markup_escape_text(alias, -1);
-			tmp = g_strdup_printf("<font sml=\"msn\">%s</font>", nicktext);
-			purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp);
-			g_free(tmp);
-			g_free(nicktext);
-		}
-
-		/* Add the tooltip information */
-		msn_tooltip_text(b, user_info, TRUE);
-
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-#if PHOTO_SUPPORT
-
-static char *
-msn_get_photo_url(const char *url_text)
-{
-	char *p, *q;
-
-	if ((p = strstr(url_text, PHOTO_URL)) != NULL)
-	{
-		p += strlen(PHOTO_URL);
-	}
-	if (p && (strncmp(p, "http://", strlen("http://")) == 0) && ((q = strchr(p, '"')) != NULL))
-			return g_strndup(p, q - p);
-
-	return NULL;
-}
-
-static void msn_got_photo(PurpleUtilFetchUrlData *url_data, gpointer data,
-		const gchar *url_text, gsize len, const gchar *error_message);
-
-#endif
-
-#if 0
-static char *msn_info_date_reformat(const char *field, size_t len)
-{
-	char *tmp = g_strndup(field, len);
-	time_t t = purple_str_to_time(tmp, FALSE, NULL, NULL, NULL);
-
-	g_free(tmp);
-	return g_strdup(purple_date_format_short(localtime(&t)));
-}
-#endif
-
-#define MSN_GOT_INFO_GET_FIELD(a, b) \
-	found = purple_markup_extract_info_field(stripped, stripped_len, user_info, \
-			"\n" a ":", 0, "\n", 0, "Undisclosed", b, 0, NULL, NULL); \
-	if (found) \
-		sect_info = TRUE;
-
-#define MSN_GOT_INFO_GET_FIELD_NO_SEARCH(a, b) \
-	found = purple_markup_extract_info_field(stripped, stripped_len, user_info, \
-			"\n" a ":", 0, "\n", 0, "Undisclosed", b, 0, NULL, msn_info_strip_search_link); \
-	if (found) \
-		sect_info = TRUE;
-
-static char *
-msn_info_strip_search_link(const char *field, size_t len)
-{
-	const char *c;
-	if ((c = strstr(field, " (http://")) == NULL)
-		return g_strndup(field, len);
-	return g_strndup(field, c - field);
-}
-
-static void
-msn_got_info(PurpleUtilFetchUrlData *url_data, gpointer data,
-		const gchar *url_text, size_t len, const gchar *error_message)
-{
-	MsnGetInfoData *info_data = (MsnGetInfoData *)data;
-	MsnSession *session;
-	PurpleNotifyUserInfo *user_info;
-	char *stripped, *p, *q, *tmp;
-	char *user_url = NULL;
-	gboolean found;
-	gboolean has_tooltip_text = FALSE;
-	gboolean has_info = FALSE;
-	gboolean sect_info = FALSE;
-	gboolean has_contact_info = FALSE;
-	char *url_buffer;
-	int stripped_len;
-#if PHOTO_SUPPORT
-	char *photo_url_text = NULL;
-	MsnGetInfoStepTwoData *info2_data = NULL;
-#endif
-
-	purple_debug_info("msn", "In msn_got_info,url_text:{%s}\n",url_text);
-
-	session = purple_connection_get_protocol_data(info_data->gc);
-	session->url_datas = g_slist_remove(session->url_datas, url_data);
-
-	user_info = purple_notify_user_info_new();
-	has_tooltip_text = msn_tooltip_extract_info_text(user_info, info_data);
-
-	if (error_message != NULL || url_text == NULL || strcmp(url_text, "") == 0)
-	{
-		purple_notify_user_info_add_pair(user_info,
-				_("Error retrieving profile"), NULL);
-
-		purple_notify_userinfo(info_data->gc, info_data->name, user_info, NULL, NULL);
-		purple_notify_user_info_destroy(user_info);
-
-		g_free(info_data->name);
-		g_free(info_data);
-		return;
-	}
-
-	url_buffer = g_strdup(url_text);
-
-	/* If they have a homepage link, MSN masks it such that we need to
-	 * fetch the url out before purple_markup_strip_html() nukes it */
-	/* I don't think this works with the new spaces profiles - Stu 3/2/06 */
-	if ((p = strstr(url_text,
-			"Take a look at my </font><A class=viewDesc title=\"")) != NULL)
-	{
-		p += 50;
-
-		if ((q = strchr(p, '"')) != NULL)
-			user_url = g_strndup(p, q - p);
-	}
-
-	/*
-	 * purple_markup_strip_html() doesn't strip out character entities like &nbsp;
-	 * and &#183;
-	 */
-	while ((p = strstr(url_buffer, "&nbsp;")) != NULL)
-	{
-		*p = ' '; /* Turn &nbsp;'s into ordinary blanks */
-		p += 1;
-		memmove(p, p + 5, strlen(p + 5));
-		url_buffer[strlen(url_buffer) - 5] = '\0';
-	}
-
-	while ((p = strstr(url_buffer, "&#183;")) != NULL)
-	{
-		memmove(p, p + 6, strlen(p + 6));
-		url_buffer[strlen(url_buffer) - 6] = '\0';
-	}
-
-	/* Nuke the nasty \r's that just get in the way */
-	purple_str_strip_char(url_buffer, '\r');
-
-	/* MSN always puts in &#39; for apostrophes...replace them */
-	while ((p = strstr(url_buffer, "&#39;")) != NULL)
-	{
-		*p = '\'';
-		memmove(p + 1, p + 5, strlen(p + 5));
-		url_buffer[strlen(url_buffer) - 4] = '\0';
-	}
-
-	/* Nuke the html, it's easier than trying to parse the horrid stuff */
-	stripped = purple_markup_strip_html(url_buffer);
-	stripped_len = strlen(stripped);
-
-	purple_debug_misc("msn", "stripped = %p\n", stripped);
-	purple_debug_misc("msn", "url_buffer = %p\n", url_buffer);
-
-	/* General section header */
-	if (has_tooltip_text)
-		purple_notify_user_info_add_section_break(user_info);
-
-	purple_notify_user_info_add_section_header(user_info, _("General"));
-
-	/* Extract their Name and put it in */
-	MSN_GOT_INFO_GET_FIELD("Name", _("Name"));
-
-	/* General */
-	MSN_GOT_INFO_GET_FIELD("Nickname", _("Nickname"));
-	MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Age", _("Age"));
-	MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Gender", _("Gender"));
-	MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Occupation", _("Occupation"));
-	MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Location", _("Location"));
-
-	/* Extract their Interests and put it in */
-	found = purple_markup_extract_info_field(stripped, stripped_len, user_info,
-			"\nInterests\t", 0, " (/default.aspx?page=searchresults", 0,
-			"Undisclosed", _("Hobbies and Interests") /* _("Interests") */,
-			0, NULL, NULL);
-
-	if (found)
-		sect_info = TRUE;
-
-	MSN_GOT_INFO_GET_FIELD("More about me", _("A Little About Me"));
-
-	if (sect_info)
-	{
-		has_info = TRUE;
-		sect_info = FALSE;
-	}
-    else
-    {
-		/* Remove the section header */
-		purple_notify_user_info_remove_last_item(user_info);
-		if (has_tooltip_text)
-			purple_notify_user_info_remove_last_item(user_info);
-	}
-
-	/* Social */
-	purple_notify_user_info_add_section_break(user_info);
-	purple_notify_user_info_add_section_header(user_info, _("Social"));
-
-	MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Marital status", _("Marital Status"));
-	MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Interested in", _("Interests"));
-	MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Pets", _("Pets"));
-	MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Hometown", _("Hometown"));
-	MSN_GOT_INFO_GET_FIELD("Places lived", _("Places Lived"));
-	MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Fashion", _("Fashion"));
-	MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Humor", _("Humor"));
-	MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Music", _("Music"));
-	MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Favorite quote", _("Favorite Quote"));
-
-	if (sect_info)
-	{
-		has_info = TRUE;
-		sect_info = FALSE;
-	}
-    else
-    {
-		/* Remove the section header */
-		purple_notify_user_info_remove_last_item(user_info);
-		purple_notify_user_info_remove_last_item(user_info);
-	}
-
-	/* Contact Info */
-	/* Personal */
-	purple_notify_user_info_add_section_break(user_info);
-	purple_notify_user_info_add_section_header(user_info, _("Contact Info"));
-	purple_notify_user_info_add_section_header(user_info, _("Personal"));
-
-	MSN_GOT_INFO_GET_FIELD("Name", _("Name"));
-	MSN_GOT_INFO_GET_FIELD("Significant other", _("Significant Other"));
-	MSN_GOT_INFO_GET_FIELD("Home phone", _("Home Phone"));
-	MSN_GOT_INFO_GET_FIELD("Home phone 2", _("Home Phone 2"));
-	MSN_GOT_INFO_GET_FIELD("Home address", _("Home Address"));
-	MSN_GOT_INFO_GET_FIELD("Personal Mobile", _("Personal Mobile"));
-	MSN_GOT_INFO_GET_FIELD("Home fax", _("Home Fax"));
-	MSN_GOT_INFO_GET_FIELD("Personal email", _("Personal Email"));
-	MSN_GOT_INFO_GET_FIELD("Personal IM", _("Personal IM"));
-	MSN_GOT_INFO_GET_FIELD("Birthday", _("Birthday"));
-	MSN_GOT_INFO_GET_FIELD("Anniversary", _("Anniversary"));
-	MSN_GOT_INFO_GET_FIELD("Notes", _("Notes"));
-
-	if (sect_info)
-	{
-		has_info = TRUE;
-		sect_info = FALSE;
-		has_contact_info = TRUE;
-	}
-    else
-    {
-		/* Remove the section header */
-		purple_notify_user_info_remove_last_item(user_info);
-	}
-
-	/* Business */
-	purple_notify_user_info_add_section_header(user_info, _("Work"));
-	MSN_GOT_INFO_GET_FIELD("Name", _("Name"));
-	MSN_GOT_INFO_GET_FIELD("Job title", _("Job Title"));
-	MSN_GOT_INFO_GET_FIELD("Company", _("Company"));
-	MSN_GOT_INFO_GET_FIELD("Department", _("Department"));
-	MSN_GOT_INFO_GET_FIELD("Profession", _("Profession"));
-	MSN_GOT_INFO_GET_FIELD("Work phone 1", _("Work Phone"));
-	MSN_GOT_INFO_GET_FIELD("Work phone 2", _("Work Phone 2"));
-	MSN_GOT_INFO_GET_FIELD("Work address", _("Work Address"));
-	MSN_GOT_INFO_GET_FIELD("Work mobile", _("Work Mobile"));
-	MSN_GOT_INFO_GET_FIELD("Work pager", _("Work Pager"));
-	MSN_GOT_INFO_GET_FIELD("Work fax", _("Work Fax"));
-	MSN_GOT_INFO_GET_FIELD("Work email", _("Work Email"));
-	MSN_GOT_INFO_GET_FIELD("Work IM", _("Work IM"));
-	MSN_GOT_INFO_GET_FIELD("Start date", _("Start Date"));
-	MSN_GOT_INFO_GET_FIELD("Notes", _("Notes"));
-
-	if (sect_info)
-	{
-		has_info = TRUE;
-		sect_info = FALSE;
-		has_contact_info = TRUE;
-	}
-    else
-    {
-		/* Remove the section header */
-		purple_notify_user_info_remove_last_item(user_info);
-	}
-
-	if (!has_contact_info)
-	{
-		/* Remove the Contact Info section header */
-		purple_notify_user_info_remove_last_item(user_info);
-	}
-
-#if 0 /* these probably don't show up any more */
-	/*
-	 * The fields, 'A Little About Me', 'Favorite Things', 'Hobbies
-	 * and Interests', 'Favorite Quote', and 'My Homepage' may or may
-	 * not appear, in any combination. However, they do appear in
-	 * certain order, so we can successively search to pin down the
-	 * distinct values.
-	 */
-
-	/* Check if they have A Little About Me */
-	found = purple_markup_extract_info_field(stripped, stripped_len, s,
-			" A Little About Me \n\n", 0, "Favorite Things", '\n', NULL,
-			_("A Little About Me"), 0, NULL, NULL);
-
-	if (!found)
-	{
-		found = purple_markup_extract_info_field(stripped, stripped_len, s,
-				" A Little About Me \n\n", 0, "Hobbies and Interests", '\n',
-				NULL, _("A Little About Me"), 0, NULL, NULL);
-	}
-
-	if (!found)
-	{
-		found = purple_markup_extract_info_field(stripped, stripped_len, s,
-				" A Little About Me \n\n", 0, "Favorite Quote", '\n', NULL,
-				_("A Little About Me"), 0, NULL, NULL);
-	}
-
-	if (!found)
-	{
-		found = purple_markup_extract_info_field(stripped, stripped_len, s,
-				" A Little About Me \n\n", 0, "My Homepage \n\nTake a look",
-				'\n',
-				NULL, _("A Little About Me"), 0, NULL, NULL);
-	}
-
-	if (!found)
-	{
-		purple_markup_extract_info_field(stripped, stripped_len, s,
-				" A Little About Me \n\n", 0, "last updated", '\n', NULL,
-				_("A Little About Me"), 0, NULL, NULL);
-	}
-
-	if (found)
-		has_info = TRUE;
-
-	/* Check if they have Favorite Things */
-	found = purple_markup_extract_info_field(stripped, stripped_len, s,
-			" Favorite Things \n\n", 0, "Hobbies and Interests", '\n', NULL,
-			_("Favorite Things"), 0, NULL, NULL);
-
-	if (!found)
-	{
-		found = purple_markup_extract_info_field(stripped, stripped_len, s,
-				" Favorite Things \n\n", 0, "Favorite Quote", '\n', NULL,
-				_("Favorite Things"), 0, NULL, NULL);
-	}
-
-	if (!found)
-	{
-		found = purple_markup_extract_info_field(stripped, stripped_len, s,
-				" Favorite Things \n\n", 0, "My Homepage \n\nTake a look", '\n',
-				NULL, _("Favorite Things"), 0, NULL, NULL);
-	}
-
-	if (!found)
-	{
-		purple_markup_extract_info_field(stripped, stripped_len, s,
-				" Favorite Things \n\n", 0, "last updated", '\n', NULL,
-				_("Favorite Things"), 0, NULL, NULL);
-	}
-
-	if (found)
-		has_info = TRUE;
-
-	/* Check if they have Hobbies and Interests */
-	found = purple_markup_extract_info_field(stripped, stripped_len, s,
-			" Hobbies and Interests \n\n", 0, "Favorite Quote", '\n', NULL,
-			_("Hobbies and Interests"), 0, NULL, NULL);
-
-	if (!found)
-	{
-		found = purple_markup_extract_info_field(stripped, stripped_len, s,
-				" Hobbies and Interests \n\n", 0, "My Homepage \n\nTake a look",
-				'\n', NULL, _("Hobbies and Interests"), 0, NULL, NULL);
-	}
-
-	if (!found)
-	{
-		purple_markup_extract_info_field(stripped, stripped_len, s,
-				" Hobbies and Interests \n\n", 0, "last updated", '\n', NULL,
-				_("Hobbies and Interests"), 0, NULL, NULL);
-	}
-
-	if (found)
-		has_info = TRUE;
-
-	/* Check if they have Favorite Quote */
-	found = purple_markup_extract_info_field(stripped, stripped_len, s,
-			"Favorite Quote \n\n", 0, "My Homepage \n\nTake a look", '\n', NULL,
-			_("Favorite Quote"), 0, NULL, NULL);
-
-	if (!found)
-	{
-		purple_markup_extract_info_field(stripped, stripped_len, s,
-				"Favorite Quote \n\n", 0, "last updated", '\n', NULL,
-				_("Favorite Quote"), 0, NULL, NULL);
-	}
-
-	if (found)
-		has_info = TRUE;
-
-	/* Extract the last updated date and put it in */
-	found = purple_markup_extract_info_field(stripped, stripped_len, s,
-			" last updated:", 1, "\n", 0, NULL, _("Last Updated"), 0,
-			NULL, msn_info_date_reformat);
-
-	if (found)
-		has_info = TRUE;
-#endif
-
-	/* If we were able to fetch a homepage url earlier, stick it in there */
-	if (user_url != NULL)
-	{
-		tmp = g_strdup_printf("<a href=\"%s\">%s</a>", user_url, user_url);
-		purple_notify_user_info_add_pair(user_info, _("Homepage"), tmp);
-		g_free(tmp);
-		g_free(user_url);
-
-		has_info = TRUE;
-	}
-
-	if (!has_info)
-	{
-		/* MSN doesn't actually distinguish between "unknown member" and
-		 * a known member with an empty profile. Try to explain this fact.
-		 * Note that if we have a nonempty tooltip_text, we know the user
-		 * exists.
-		 */
-		/* This doesn't work with the new spaces profiles - Stu 3/2/06
-		char *p = strstr(url_buffer, "Unknown Member </TITLE>");
-		 * This might not work for long either ... */
-		/* Nope, it failed some time before 5/2/07 :(
-		char *p = strstr(url_buffer, "form id=\"SpacesSearch\" name=\"SpacesSearch\"");
-		 * Let's see how long this one holds out for ... */
-		char *p = strstr(url_buffer, "<form id=\"profile_form\" name=\"profile_form\" action=\"http&#58;&#47;&#47;spaces.live.com&#47;profile.aspx&#63;cid&#61;0\"");
-		PurpleBuddy *b = purple_find_buddy
-				(purple_connection_get_account(info_data->gc), info_data->name);
-		purple_notify_user_info_add_pair(user_info,
-				_("Error retrieving profile"), NULL);
-		purple_notify_user_info_add_pair(user_info, NULL,
-				((p && b) ? _("The user has not created a public profile.") :
-					(p ? _("MSN reported not being able to find the user's profile. "
-							"This either means that the user does not exist, "
-							"or that the user exists "
-							"but has not created a public profile.") :
-						_("Could not find "	/* This should never happen */
-							"any information in the user's profile. "
-							"The user most likely does not exist."))));
-	}
-
-	/* put a link to the actual profile URL */
-	purple_notify_user_info_add_section_break(user_info);
-	tmp = g_strdup_printf("<a href=\"%s%s\">%s</a>",
-			PROFILE_URL, info_data->name, _("View web profile"));
-	purple_notify_user_info_add_pair(user_info, NULL, tmp);
-	g_free(tmp);
-
-#if PHOTO_SUPPORT
-	/* Find the URL to the photo; must be before the marshalling [Bug 994207] */
-	photo_url_text = msn_get_photo_url(url_text);
-	purple_debug_info("msn", "photo url:{%s}\n", photo_url_text ? photo_url_text : "(null)");
-
-	/* Marshall the existing state */
-	info2_data = g_new0(MsnGetInfoStepTwoData, 1);
-	info2_data->info_data = info_data;
-	info2_data->stripped = stripped;
-	info2_data->url_buffer = url_buffer;
-	info2_data->user_info = user_info;
-	info2_data->photo_url_text = photo_url_text;
-
-	/* Try to put the photo in there too, if there's one */
-	if (photo_url_text)
-	{
-		url_data = purple_util_fetch_url_len(photo_url_text, FALSE, NULL, FALSE,
-		                                     MAX_HTTP_BUDDYICON_BYTES,
-		                                     msn_got_photo, info2_data);
-		session->url_datas = g_slist_prepend(session->url_datas, url_data);
-	}
-	else
-	{
-		/* Finish the Get Info and show the user something */
-		msn_got_photo(NULL, info2_data, NULL, 0, NULL);
-	}
-}
-
-static void
-msn_got_photo(PurpleUtilFetchUrlData *url_data, gpointer user_data,
-		const gchar *url_text, gsize len, const gchar *error_message)
-{
-	MsnGetInfoStepTwoData *info2_data = (MsnGetInfoStepTwoData *)user_data;
-	int id = -1;
-
-	/* Unmarshall the saved state */
-	MsnGetInfoData *info_data = info2_data->info_data;
-	char *stripped = info2_data->stripped;
-	char *url_buffer = info2_data->url_buffer;
-	PurpleNotifyUserInfo *user_info = info2_data->user_info;
-	char *photo_url_text = info2_data->photo_url_text;
-
-	if (url_data) {
-		MsnSession *session = purple_connection_get_protocol_data(info_data->gc);
-		session->url_datas = g_slist_remove(session->url_datas, url_data);
-	}
-
-	if (url_text && error_message)
-	{
-		purple_debug_warning("msn", "invalid connection. ignoring buddy photo info.\n");
-		g_free(stripped);
-		g_free(url_buffer);
-		purple_notify_user_info_destroy(user_info);
-		g_free(info_data->name);
-		g_free(info_data);
-		g_free(photo_url_text);
-		g_free(info2_data);
-
-		return;
-	}
-
-	/* Try to put the photo in there too, if there's one and is readable */
-	if (url_text && len != 0)
-	{
-		if (strstr(url_text, "400 Bad Request")
-			|| strstr(url_text, "403 Forbidden")
-			|| strstr(url_text, "404 Not Found"))
-		{
-
-			purple_debug_info("msn", "Error getting %s: %s\n",
-					photo_url_text, url_text);
-		}
-		else
-		{
-			char buf[1024];
-			purple_debug_info("msn", "%s is %" G_GSIZE_FORMAT " bytes\n", photo_url_text, len);
-			id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL);
-			g_snprintf(buf, sizeof(buf), "<img id=\"%d\"><br>", id);
-			purple_notify_user_info_prepend_pair(user_info, NULL, buf);
-		}
-	}
-
-	/* We continue here from msn_got_info, as if nothing has happened */
-#endif
-	purple_notify_userinfo(info_data->gc, info_data->name, user_info, NULL, NULL);
-
-	g_free(stripped);
-	g_free(url_buffer);
-	purple_notify_user_info_destroy(user_info);
-	g_free(info_data->name);
-	g_free(info_data);
-#if PHOTO_SUPPORT
-	g_free(photo_url_text);
-	g_free(info2_data);
-	if (id != -1)
-		purple_imgstore_unref_by_id(id);
-#endif
-}
-
-static void
-msn_get_info(PurpleConnection *gc, const char *name)
-{
-	MsnSession *session = purple_connection_get_protocol_data(gc);
-	MsnGetInfoData *data;
-	char *url;
-	PurpleUtilFetchUrlData *url_data;
-
-	data       = g_new0(MsnGetInfoData, 1);
-	data->gc   = gc;
-	data->name = g_strdup(name);
-
-	url = g_strdup_printf("%s%s", PROFILE_URL, name);
-
-	url_data = purple_util_fetch_url(url, FALSE,
-	                                 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
-	                                 TRUE, msn_got_info, data);
-	session->url_datas = g_slist_prepend(session->url_datas, url_data);
-
-	g_free(url);
-}
-
-static gboolean msn_load(PurplePlugin *plugin)
-{
-	msn_notification_init();
-	msn_switchboard_init();
-
-	return TRUE;
-}
-
-static gboolean msn_unload(PurplePlugin *plugin)
-{
-	msn_notification_end();
-	msn_switchboard_end();
-
-	return TRUE;
-}
-
-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;
-}
-
-static gboolean msn_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, "msnim"))
-		return FALSE;
-
-	acct = find_acct("prpl-msn", acct_id);
-
-	if (!acct)
-		return FALSE;
-
-	/* msnim:chat?contact=user@domain.tld */
-	if (!g_ascii_strcasecmp(cmd, "Chat")) {
-		char *sname = g_hash_table_lookup(params, "contact");
-		if (sname) {
-			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);
-		}
-		/*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;
-	}
-	/* msnim:add?contact=user@domain.tld */
-	else if (!g_ascii_strcasecmp(cmd, "Add")) {
-		char *name = g_hash_table_lookup(params, "contact");
-		purple_blist_request_add_buddy(acct, name, NULL, NULL);
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-
-static PurplePluginProtocolInfo prpl_info =
-{
-	OPT_PROTO_MAIL_CHECK|OPT_PROTO_INVITE_MESSAGE,
-	NULL,                               /* user_splits */
-	NULL,                               /* protocol_options */
-	{"png,gif", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_SEND},   /* icon_spec */
-	msn_list_icon,                      /* list_icon */
-	msn_list_emblems,                   /* list_emblems */
-	msn_status_text,                    /* status_text */
-	msn_tooltip_text,                   /* tooltip_text */
-	msn_status_types,                   /* away_states */
-	msn_blist_node_menu,                /* blist_node_menu */
-	NULL,                               /* chat_info */
-	NULL,                               /* chat_info_defaults */
-	msn_login,                          /* login */
-	msn_close,                          /* close */
-	msn_send_im,                        /* send_im */
-	NULL,                               /* set_info */
-	msn_send_typing,                    /* send_typing */
-	msn_get_info,                       /* get_info */
-	msn_set_status,                     /* set_away */
-	msn_set_idle,                       /* set_idle */
-	NULL,                               /* change_passwd */
-	NULL,                               /* add_buddy */
-	NULL,                               /* add_buddies */
-	msn_rem_buddy,                      /* remove_buddy */
-	NULL,                               /* remove_buddies */
-	msn_add_permit,                     /* add_permit */
-	msn_add_deny,                       /* add_deny */
-	msn_rem_permit,                     /* rem_permit */
-	msn_rem_deny,                       /* rem_deny */
-	msn_set_permit_deny,                /* set_permit_deny */
-	NULL,                               /* join_chat */
-	NULL,                               /* reject chat invite */
-	NULL,                               /* get_chat_name */
-	msn_chat_invite,                    /* chat_invite */
-	msn_chat_leave,                     /* chat_leave */
-	NULL,                               /* chat_whisper */
-	msn_chat_send,                      /* chat_send */
-	msn_keepalive,                      /* keepalive */
-	NULL,                               /* register_user */
-	NULL,                               /* get_cb_info */
-	NULL,                               /* get_cb_away */
-	msn_alias_buddy,                    /* alias_buddy */
-	msn_group_buddy,                    /* group_buddy */
-	msn_rename_group,                   /* rename_group */
-	NULL,                               /* buddy_free */
-	msn_convo_closed,                   /* convo_closed */
-	msn_normalize,                      /* normalize */
-	msn_set_buddy_icon,                 /* set_buddy_icon */
-	msn_remove_group,                   /* 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 */
-	msn_can_receive_file,               /* can_receive_file */
-	msn_send_file,                      /* send_file */
-	msn_new_xfer,                       /* new_xfer */
-	msn_offline_message,                /* offline_message */
-	NULL,                               /* whiteboard_prpl_ops */
-	NULL,                               /* send_raw */
-	NULL,                               /* roomlist_room_serialize */
-	NULL,                               /* unregister_user */
-	msn_send_attention,                 /* send_attention */
-	msn_attention_types,                /* attention_types */
-	sizeof(PurplePluginProtocolInfo),	/* struct_size */
-	msn_get_account_text_table,         /* get_account_text_table */
-	NULL,                               /* initiate_media */
-	NULL,                               /* get_media_caps */
-	NULL,                               /* get_moods */
-	msn_set_public_alias,               /* set_public_alias */
-	msn_get_public_alias,               /* get_public_alias */
-	msn_add_buddy,                      /* 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-msn",                                       /**< id             */
-	"MSN",                                            /**< name           */
-	DISPLAY_VERSION,                                  /**< version        */
-	N_("Windows Live Messenger Protocol Plugin"),     /**< summary        */
-	N_("Windows Live Messenger Protocol Plugin"),     /**< description    */
-	NULL,                                             /**< author         */
-	PURPLE_WEBSITE,                                   /**< homepage       */
-
-	msn_load,                                         /**< load           */
-	msn_unload,                                       /**< unload         */
-	NULL,                                             /**< destroy        */
-
-	NULL,                                             /**< ui_info        */
-	&prpl_info,                                       /**< extra_info     */
-	NULL,                                             /**< prefs_info     */
-	msn_actions,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void
-init_plugin(PurplePlugin *plugin)
-{
-	PurpleAccountOption *option;
-
-	option = purple_account_option_string_new(_("Server"), "server",
-											MSN_SERVER);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-											   option);
-
-	option = purple_account_option_int_new(_("Port"), "port", MSN_PORT);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-											   option);
-
-	option = purple_account_option_bool_new(_("Use HTTP Method"),
-										  "http_method", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-											   option);
-
-	option = purple_account_option_string_new(_("HTTP Method Server"),
-										  "http_method_server", MSN_HTTPCONN_SERVER);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-											   option);
-
-	option = purple_account_option_bool_new(_("Show custom smileys"),
-										  "custom_smileys", TRUE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-											   option);
-
-	option = purple_account_option_bool_new(_("Allow direct connections"),
-										  "direct_connect", TRUE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-											   option);
-
-	option = purple_account_option_bool_new(_("Allow connecting from multiple locations"),
-										  "mpop", TRUE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-											   option);
-
-	purple_cmd_register("nudge", "", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
-	                 "prpl-msn", msn_cmd_nudge,
-	                  _("nudge: nudge a user to get their attention"), NULL);
-
-	purple_prefs_remove("/plugins/prpl/msn");
-
-	purple_signal_connect(purple_get_core(), "uri-handler", plugin,
-		PURPLE_CALLBACK(msn_uri_handler), NULL);
-}
-
-PURPLE_INIT_PLUGIN(msn, init_plugin, info);
--- a/libpurple/protocols/msn/msn.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,158 +0,0 @@
-/**
- * @file msn.h The MSN protocol plugin
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_H
-#define MSN_H
-
-typedef enum
-{
-	MSN_CAP_VIA_MOBILE    = 0x0000001,
-	MSN_CAP_VIA_TEXAS     = 0x0000002,
-	MSN_CAP_INK_GIF       = 0x0000004,
-	MSN_CAP_INK_ISF       = 0x0000008,
-	MSN_CAP_VIDEO_CHAT    = 0x0000010,
-	MSN_CAP_PACKET        = 0x0000020,
-	MSN_CAP_MOBILE_ON     = 0x0000040,
-	MSN_CAP_WEB_WATCH     = 0x0000080,
-	MSN_CAP_ACTIVITIES    = 0x0000100,
-	MSN_CAP_VIA_WEBIM     = 0x0000200,
-	MSN_CAP_MOBILE_DEV    = 0x0000400,
-	MSN_CAP_VIA_FEDERATED = 0x0000800,
-	MSN_CAP_SPACE         = 0x0001000,
-	MSN_CAP_MCE           = 0x0002000,
-	MSN_CAP_DIRECTIM      = 0x0004000,
-	MSN_CAP_WINKS         = 0x0008000,
-	MSN_CAP_SEARCH        = 0x0010000,
-	MSN_CAP_BOT           = 0x0020000,
-	MSN_CAP_VOICEIM       = 0x0040000,
-	MSN_CAP_SCHANNEL      = 0x0080000,
-	MSN_CAP_SIP_INVITE    = 0x0100000,
-	MSN_CAP_MULTI_VV      = 0x0200000,
-	MSN_CAP_SDRIVE        = 0x0400000,
-	MSN_CAP_PAGEMODE_MSG  = 0x080000,
-	MSN_CAP_ONECARE       = 0x1000000,
-	MSN_CAP_P2P_TURN      = 0x2000000,
-	MSN_CAP_P2P_BOOTSTRAP_VIA_UUN = 0x4000000,
-	MSN_CAP_ALIASED       = 0x8000000
-} MsnClientCaps;
-
-typedef enum
-{
-	MSN_EXT_CAP_SMS_ONLY            = 0x1,
-	MSN_EXT_CAP_VOICE_OVER_MSNP     = 0x2,
-	MSN_EXT_CAP_UUCP_SIP            = 0x4,
-	MSN_EXT_CAP_APP_MSGS            = 0x8,
-	MSN_EXT_CAP_RTC_VIDEO           = 0x10,
-	MSN_EXT_CAP_P2PV2               = 0x20,
-	MSN_EXT_CAP_AUTH_WEBIM          = 0x40,
-	MSN_EXT_CAP_1ON1_VIA_GROUP      = 0x80,
-	MSN_EXT_CAP_OFFLINEIM           = 0x100,
-	MSN_EXT_CAP_SHARING_VIDEO       = 0x200,
-	MSN_EXT_CAP_NUDGE               = 0x400,
-	MSN_EXT_CAP_CIRCLE_VOICEIM      = 0x800,
-	MSN_EXT_CAP_SHARING             = 0x1000,
-	MSN_EXT_CAP_P2P_MIXER_RELAY     = 0x8000,
-	MSN_EXT_CAP_CONV_WINDOW_FT      = 0x20000,
-	MSN_EXT_CAP_VIDEO_16x9          = 0x40000,
-	MSN_EXT_CAP_P2P_ENVELOPE        = 0x80000,
-	MSN_EXT_CAP_YAHOOIM_DISABLE     = 0x400000,
-	MSN_EXT_CAP_SIP_TUNNELv2        = 0x800000,
-	MSN_EXT_CAP_VOICE_CLIP_WMA      = 0x1000000,
-	MSN_EXT_CAP_VOICE_CLIP_CIRCLEIM = 0x2000000,
-	MSN_EXT_CAP_SOCIAL_NEWS         = 0x4000000,
-	MSN_EXT_CAP_CUSTOM_SMILEY       = 0x8000000,
-	MSN_EXT_CAP_UTF8_MOODS          = 0x10000000,
-	MSN_EXT_CAP_FTURN               = 0x20000000,
-	MSN_EXT_CAP_P4_ACTIVITY         = 0x40000000,
-	MSN_EXT_CAP_MUC                 = 0x80000000
-} MsnClientExtCaps;
-
-typedef enum
-{
-	MSN_CLIENT_VER_5_0  = 0x00,
-	MSN_CLIENT_VER_6_0  = 0x10,	/* MSNC1 */
-	MSN_CLIENT_VER_6_1  = 0x20,	/* MSNC2 */
-	MSN_CLIENT_VER_6_2  = 0x30,	/* MSNC3 */
-	MSN_CLIENT_VER_7_0  = 0x40,	/* MSNC4 */
-	MSN_CLIENT_VER_7_5  = 0x50,	/* MSNC5 */
-	MSN_CLIENT_VER_8_0  = 0x60,	/* MSNC6 */
-	MSN_CLIENT_VER_8_1  = 0x70,	/* MSNC7 */
-	MSN_CLIENT_VER_8_5  = 0x80,	/* MSNC8 */
-	MSN_CLIENT_VER_9_0  = 0x90,	/* MSNC9 */
-	MSN_CLIENT_VER_14_0 = 0xA0,	/* MSNC10 */
-	MSN_CLIENT_VER_15_0 = 0xB0	/* MSNC11 */
-} MsnClientVerId;
-
-#include "internal.h"
-
-#include "session.h"
-
-#include "msg.h"
-
-#define MSN_BUF_LEN 8192
-
-/* Windows Live Messenger Server*/
-#define MSN_SERVER "messenger.hotmail.com"
-#define MSN_HTTPCONN_SERVER "gateway.messenger.hotmail.com"
-#define MSN_PORT 1863
-#define WLM_PROT_VER		18
-
-#define WLM_MAX_PROTOCOL	18
-#define WLM_MIN_PROTOCOL	18
-
-#define MSN_TYPING_RECV_TIMEOUT 6
-#define MSN_TYPING_SEND_TIMEOUT	4
-
-#define PROFILE_URL "http://spaces.live.com/profile.aspx?mem="
-#define PHOTO_URL	" contactparams:photopreauthurl=\""
-
-#define BUDDY_ALIAS_MAXLEN 387
-
-#define MSN_CAM_GUID "4BD96FC0-AB17-4425-A14A-439185962DC8"
-#define MSN_CAM_REQUEST_GUID "1C9AA97E-9C05-4583-A3BD-908A196F1E92"
-#define MSN_FT_GUID "5D3E02AB-6190-11D3-BBBB-00C04F795683"
-#define MSN_OBJ_GUID "A4268EEC-FEC5-49E5-95C3-F126696BDBF6"
-
-#define MSN_CLIENTINFO \
-	"Client-Name: Purple/" VERSION "\r\n" \
-	"Chat-Logging: Y\r\n"
-
-/* Index into attention_types */
-#define MSN_NUDGE 0
-
-#define MSN_CLIENT_ID_VERSION      MSN_CLIENT_VER_9_0
-#define MSN_CLIENT_ID_CAPABILITIES (MSN_CAP_PACKET|MSN_CAP_INK_GIF|MSN_CAP_VOICEIM)
-#define MSN_CLIENT_ID_EXT_CAPS     (0)
-
-#define MSN_CLIENT_ID \
-	((MSN_CLIENT_ID_VERSION    << 24) | \
-	 (MSN_CLIENT_ID_CAPABILITIES))
-
-void
-msn_set_public_alias(PurpleConnection *gc, const char *alias,
-                     PurpleSetPublicAliasSuccessCallback success_cb,
-                     PurpleSetPublicAliasFailureCallback failure_cb);
-void msn_send_privacy(PurpleConnection *gc);
-void msn_send_im_message(MsnSession *session, MsnMessage *msg);
-
-#endif /* MSN_H */
--- a/libpurple/protocols/msn/msnutils.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,719 +0,0 @@
-/**
- * @file msnutils.c Utility functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-
-#include "msn.h"
-#include "msnutils.h"
-
-#include "cipher.h"
-
-/**************************************************************************
- * Util
- **************************************************************************/
-char *
-rand_guid(void)
-{
-	return g_strdup_printf("%4X%4X-%4X-%4X-%4X-%4X%4X%4X",
-			rand() % 0xAAFF + 0x1111,
-			rand() % 0xAAFF + 0x1111,
-			rand() % 0xAAFF + 0x1111,
-			rand() % 0xAAFF + 0x1111,
-			rand() % 0xAAFF + 0x1111,
-			rand() % 0xAAFF + 0x1111,
-			rand() % 0xAAFF + 0x1111,
-			rand() % 0xAAFF + 0x1111);
-}
-
-void
-msn_parse_format(const char *mime, char **pre_ret, char **post_ret)
-{
-	char *cur;
-	GString *pre  = g_string_new(NULL);
-	GString *post = g_string_new(NULL);
-	unsigned int colors[3];
-
-	if (pre_ret  != NULL) *pre_ret  = NULL;
-	if (post_ret != NULL) *post_ret = NULL;
-
-	cur = strstr(mime, "FN=");
-
-	if (cur && (*(cur = cur + 3) != ';'))
-	{
-		pre = g_string_append(pre, "<FONT FACE=\"");
-
-		while (*cur && *cur != ';')
-		{
-			pre = g_string_append_c(pre, *cur);
-			cur++;
-		}
-
-		pre = g_string_append(pre, "\">");
-		post = g_string_prepend(post, "</FONT>");
-	}
-
-	cur = strstr(mime, "EF=");
-
-	if (cur && (*(cur = cur + 3) != ';'))
-	{
-		while (*cur && *cur != ';')
-		{
-			pre = g_string_append_c(pre, '<');
-			pre = g_string_append_c(pre, *cur);
-			pre = g_string_append_c(pre, '>');
-			post = g_string_prepend_c(post, '>');
-			post = g_string_prepend_c(post, *cur);
-			post = g_string_prepend_c(post, '/');
-			post = g_string_prepend_c(post, '<');
-			cur++;
-		}
-	}
-
-	cur = strstr(mime, "CO=");
-
-	if (cur && (*(cur = cur + 3) != ';'))
-	{
-		int i;
-
-		i = sscanf(cur, "%02x%02x%02x;", &colors[0], &colors[1], &colors[2]);
-
-		if (i > 0)
-		{
-			char tag[64];
-
-			if (i == 1)
-			{
-				colors[1] = 0;
-				colors[2] = 0;
-			}
-			else if (i == 2)
-			{
-				unsigned int temp = colors[0];
-
-				colors[0] = colors[1];
-				colors[1] = temp;
-				colors[2] = 0;
-			}
-			else if (i == 3)
-			{
-				unsigned int temp = colors[2];
-
-				colors[2] = colors[0];
-				colors[0] = temp;
-			}
-
-			g_snprintf(tag, sizeof(tag),
-				"<FONT COLOR=\"#%02x%02x%02x\">",
-				colors[0] & 0xFF, colors[1] & 0xFF,
-				colors[2] & 0xFF);
-
-			pre = g_string_append(pre, tag);
-			post = g_string_prepend(post, "</FONT>");
-		}
-	}
-
-	cur = strstr(mime, "RL=");
-
-	if (cur && (*(cur = cur + 3) != ';'))
-	{
-		if (*cur == '1')
-		{
-			/* RTL text was received */
-			pre = g_string_append(pre, "<SPAN style=\"direction:rtl;text-align:right;\">");
-			post = g_string_prepend(post, "</SPAN>");
-		}
-	}
-
-	cur = g_strdup(purple_url_decode(pre->str));
-	g_string_free(pre, TRUE);
-
-	if (pre_ret != NULL)
-		*pre_ret = cur;
-	else
-		g_free(cur);
-
-	cur = g_strdup(purple_url_decode(post->str));
-	g_string_free(post, TRUE);
-
-	if (post_ret != NULL)
-		*post_ret = cur;
-	else
-		g_free(cur);
-}
-
-/*encode the str to RFC2047 style
- * Currently only support the UTF-8 and base64 encode
- */
-char *
-msn_encode_mime(const char *str)
-{
-	gchar *base64, *retval;
-
-	g_return_val_if_fail(str != NULL, NULL);
-
-	base64 = purple_base64_encode((guchar *)str, strlen(str));
-	retval = g_strdup_printf("=?utf-8?B?%s?=", base64);
-	g_free(base64);
-
-	return retval;
-}
-
-/*
- * We need this because we're only supposed to encode spaces in the font
- * names. purple_url_encode() isn't acceptable.
- */
-gboolean
-msn_encode_spaces(const char *str, char *buf, size_t len)
-{
-	char *nonspace = buf;
-
-	while (isspace(*str))
-		str++;
-
-	for (; *str && len > 1; str++) {
-		if (*str == '%') {
-			if (len < 4)
-				break;
-			*buf++ = '%';
-			*buf++ = '2';
-			*buf++ = '5';
-			len -= 3;
-			nonspace = buf;
-		} else if (*str == ' ') {
-			if (len < 4)
-				break;
-			*buf++ = '%';
-			*buf++ = '2';
-			*buf++ = '0';
-			len -= 3;
-		} else {
-			*buf++ = *str;
-			len--;
-			nonspace = buf;
-		}
-	}
-
-	*nonspace = '\0';
-
-	return (*str == '\0');
-}
-
-/*
- * Taken from the zephyr plugin.
- * This parses HTML formatting (put out by one of the gtkimhtml widgets
- * and converts it to msn formatting. It doesn't deal with the tag closing,
- * but gtkimhtml widgets give valid html.
- * It currently deals properly with <b>, <u>, <i>, <font face=...>,
- * <font color=...>, <span dir=...>, <span style="direction: ...">.
- * It ignores <font back=...> and <font size=...>
- */
-void
-msn_import_html(const char *html, char **attributes, char **message)
-{
-	int len, retcount = 0;
-	const char *c;
-	char *msg;
-	char *fontface = NULL;
-	char fontface_encoded[BUF_LEN];
-	char fonteffect[5];
-	char fontcolor[7];
-	char direction = '0';
-
-	gboolean has_bold = FALSE;
-	gboolean has_italic = FALSE;
-	gboolean has_underline = FALSE;
-	gboolean has_strikethrough = FALSE;
-
-	g_return_if_fail(html       != NULL);
-	g_return_if_fail(attributes != NULL);
-	g_return_if_fail(message    != NULL);
-
-	len = strlen(html);
-	msg = g_malloc0(len + 1);
-
-	memset(fontcolor, 0, sizeof(fontcolor));
-	strcat(fontcolor, "0");
-	memset(fonteffect, 0, sizeof(fonteffect));
-
-	for (c = html; *c != '\0';)
-	{
-		if (*c == '<')
-		{
-			if (!g_ascii_strncasecmp(c + 1, "br>", 3))
-			{
-				msg[retcount++] = '\r';
-				msg[retcount++] = '\n';
-				c += 4;
-			}
-			else if (!g_ascii_strncasecmp(c + 1, "i>", 2))
-			{
-				if (!has_italic)
-				{
-					strcat(fonteffect, "I");
-					has_italic = TRUE;
-				}
-				c += 3;
-			}
-			else if (!g_ascii_strncasecmp(c + 1, "b>", 2))
-			{
-				if (!has_bold)
-				{
-					strcat(fonteffect, "B");
-					has_bold = TRUE;
-				}
-				c += 3;
-			}
-			else if (!g_ascii_strncasecmp(c + 1, "u>", 2))
-			{
-				if (!has_underline)
-				{
-					strcat(fonteffect, "U");
-					has_underline = TRUE;
-				}
-				c += 3;
-			}
-			else if (!g_ascii_strncasecmp(c + 1, "s>", 2))
-			{
-				if (!has_strikethrough)
-				{
-					strcat(fonteffect, "S");
-					has_strikethrough = TRUE;
-				}
-				c += 3;
-			}
-			else if (!g_ascii_strncasecmp(c + 1, "a href=\"", 8))
-			{
-				c += 9;
-
-				if (!g_ascii_strncasecmp(c, "mailto:", 7))
-					c += 7;
-
-				while ((*c != '\0') && g_ascii_strncasecmp(c, "\">", 2))
-					msg[retcount++] = *c++;
-
-				if (*c != '\0')
-					c += 2;
-
-				/* ignore descriptive string */
-				while ((*c != '\0') && g_ascii_strncasecmp(c, "</a>", 4))
-					c++;
-
-				if (*c != '\0')
-					c += 4;
-			}
-			else if (!g_ascii_strncasecmp(c + 1, "span", 4))
-			{
-				/* Bi-directional text support using CSS properties in span tags */
-				c += 5;
-
-				while (*c != '\0' && *c != '>')
-				{
-					while (*c == ' ')
-						c++;
-					if (!g_ascii_strncasecmp(c, "dir=\"rtl\"", 9))
-					{
-						c += 9;
-						direction = '1';
-					}
-					else if (!g_ascii_strncasecmp(c, "style=\"", 7))
-					{
-						/* Parse inline CSS attributes */
-						char *attributes;
-						int attr_len = 0;
-						c += 7;
-						while (*(c + attr_len) != '\0' && *(c + attr_len) != '"')
-							attr_len++;
-						if (*(c + attr_len) == '"')
-						{
-							char *attr_dir;
-							attributes = g_strndup(c, attr_len);
-							attr_dir = purple_markup_get_css_property(attributes, "direction");
-							if (attr_dir && (!g_ascii_strncasecmp(attr_dir, "RTL", 3)))
-								direction = '1';
-							g_free(attr_dir);
-							g_free(attributes);
-						}
-
-					}
-					else
-					{
-						c++;
-					}
-				}
-				if (*c == '>')
-					c++;
-			}
-			else if (!g_ascii_strncasecmp(c + 1, "font", 4))
-			{
-				c += 5;
-
-				while ((*c != '\0') && !g_ascii_strncasecmp(c, " ", 1))
-					c++;
-
-				if (!g_ascii_strncasecmp(c, "color=\"#", 7))
-				{
-					c += 8;
-
-					fontcolor[0] = *(c + 4);
-					fontcolor[1] = *(c + 5);
-					fontcolor[2] = *(c + 2);
-					fontcolor[3] = *(c + 3);
-					fontcolor[4] = *c;
-					fontcolor[5] = *(c + 1);
-
-					c += 8;
-				}
-				else if (!g_ascii_strncasecmp(c, "face=\"", 6))
-				{
-					const char *end = NULL;
-					const char *comma = NULL;
-					unsigned int namelen = 0;
-
-					c += 6;
-					end = strchr(c, '\"');
-					comma = strchr(c, ',');
-
-					if (comma == NULL || comma > end)
-						namelen = (unsigned int)(end - c);
-					else
-						namelen = (unsigned int)(comma - c);
-
-					fontface = g_strndup(c, namelen);
-					c = end + 2;
-				}
-				else
-				{
-					/* Drop all unrecognized/misparsed font tags */
-					while ((*c != '\0') && g_ascii_strncasecmp(c, "\">", 2))
-						c++;
-
-					if (*c != '\0')
-						c += 2;
-				}
-			}
-			else
-			{
-				while ((*c != '\0') && (*c != '>'))
-					c++;
-				if (*c != '\0')
-					c++;
-			}
-		}
-		else if (*c == '&')
-		{
-			if (!g_ascii_strncasecmp(c, "&lt;", 4))
-			{
-				msg[retcount++] = '<';
-				c += 4;
-			}
-			else if (!g_ascii_strncasecmp(c, "&gt;", 4))
-			{
-				msg[retcount++] = '>';
-				c += 4;
-			}
-			else if (!g_ascii_strncasecmp(c, "&nbsp;", 6))
-			{
-				msg[retcount++] = ' ';
-				c += 6;
-			}
-			else if (!g_ascii_strncasecmp(c, "&quot;", 6))
-			{
-				msg[retcount++] = '"';
-				c += 6;
-			}
-			else if (!g_ascii_strncasecmp(c, "&amp;", 5))
-			{
-				msg[retcount++] = '&';
-				c += 5;
-			}
-			else if (!g_ascii_strncasecmp(c, "&apos;", 6))
-			{
-				msg[retcount++] = '\'';
-				c += 6;
-			}
-			else
-				msg[retcount++] = *c++;
-		}
-		else
-			msg[retcount++] = *c++;
-	}
-
-	if (fontface == NULL)
-		fontface = g_strdup("Segoe UI");
-
-	msn_encode_spaces(fontface, fontface_encoded, BUF_LEN);
-	*attributes = g_strdup_printf("FN=%s; EF=%s; CO=%s; PF=0; RL=%c",
-								  fontface_encoded,
-								  fonteffect, fontcolor, direction);
-	*message = msg;
-
-	g_free(fontface);
-}
-
-void
-msn_parse_socket(const char *str, char **ret_host, int *ret_port)
-{
-	char *host;
-	char *c;
-	int port;
-
-	host = g_strdup(str);
-
-	if ((c = strchr(host, ':')) != NULL) {
-		*c = '\0';
-		port = atoi(c + 1);
-	} else {
-		port = 1863;
-	}
-
-	*ret_host = host;
-	*ret_port = port;
-}
-
-void
-msn_parse_user(const char *str, char **ret_user, int *ret_network)
-{
-	char **tokens;
-
-	tokens = g_strsplit(str, ":", 2);
-
-	*ret_network = atoi(tokens[0]);
-	*ret_user = tokens[1];
-
-	g_free(tokens[0]);
-	/* tokens[1] is returned */
-	g_free(tokens);
-}
-
-gboolean
-msn_email_is_valid(const char *passport)
-{
-	if (purple_email_is_valid(passport)) {
-		/* Special characters aren't allowed in domains, so only go to '@' */
-		while (*passport != '@') {
-			if (*passport == '/')
-				return FALSE;
-			else if (*passport == '?')
-				return FALSE;
-			else if (*passport == '=')
-				return FALSE;
-			/* MSN also doesn't like colons, but that's checked already */
-
-			passport++;
-		}
-
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-/***************************************************************************
- * MSN Challenge Computing Function
- ***************************************************************************/
-
-/*
- * Handle MSN Challenge computation
- * This algorithm references
- *  http://imfreedom.org/wiki/index.php/MSN:NS/Challenges
- */
-#define BUFSIZE	256
-void
-msn_handle_chl(char *input, char *output)
-{
-	PurpleCipher *cipher;
-	PurpleCipherContext *context;
-	const guchar productKey[] = MSNP15_WLM_PRODUCT_KEY;
-	const guchar productID[]  = MSNP15_WLM_PRODUCT_ID;
-	const char hexChars[]     = "0123456789abcdef";
-	char buf[BUFSIZE];
-	unsigned char md5Hash[16];
-	unsigned char *newHash;
-	unsigned int *md5Parts;
-	unsigned int *chlStringParts;
-	unsigned int newHashParts[5];
-
-	long long nHigh = 0, nLow = 0;
-
-	int len;
-	int i;
-
-	/* Create the MD5 hash by using Purple MD5 algorithm */
-	cipher = purple_ciphers_find_cipher("md5");
-	context = purple_cipher_context_new(cipher, NULL);
-
-	purple_cipher_context_append(context, (guchar *)input, strlen(input));
-	purple_cipher_context_append(context, productKey, sizeof(productKey) - 1);
-	purple_cipher_context_digest(context, sizeof(md5Hash), md5Hash, NULL);
-	purple_cipher_context_destroy(context);
-
-	/* Split it into four integers */
-	md5Parts = (unsigned int *)md5Hash;
-	for (i = 0; i < 4; i++) {
-		/* adjust endianess */
-		md5Parts[i] = GUINT_TO_LE(md5Parts[i]);
-
-		/* & each integer with 0x7FFFFFFF          */
-		/* and save one unmodified array for later */
-		newHashParts[i] = md5Parts[i];
-		md5Parts[i] &= 0x7FFFFFFF;
-	}
-
-	/* make a new string and pad with '0' to length that's a multiple of 8 */
-	snprintf(buf, BUFSIZE - 5, "%s%s", input, productID);
-	len = strlen(buf);
-	if ((len % 8) != 0) {
-		int fix = 8 - (len % 8);
-		strncpy(&buf[len], "00000000", fix);
-		buf[len + fix] = '\0';
-		len += fix;
-	}
-
-	/* split into integers */
-	chlStringParts = (unsigned int *)buf;
-
-	/* this is magic */
-	for (i = 0; i < (len / 4); i += 2) {
-		long long temp;
-
-		chlStringParts[i] = GUINT_TO_LE(chlStringParts[i]);
-		chlStringParts[i + 1] = GUINT_TO_LE(chlStringParts[i + 1]);
-
-		temp = (0x0E79A9C1 * (long long)chlStringParts[i]) % 0x7FFFFFFF;
-		temp = (md5Parts[0] * (temp + nLow) + md5Parts[1]) % 0x7FFFFFFF;
-		nHigh += temp;
-
-		temp = ((long long)chlStringParts[i + 1] + temp) % 0x7FFFFFFF;
-		nLow = (md5Parts[2] * temp + md5Parts[3]) % 0x7FFFFFFF;
-		nHigh += nLow;
-	}
-	nLow = (nLow + md5Parts[1]) % 0x7FFFFFFF;
-	nHigh = (nHigh + md5Parts[3]) % 0x7FFFFFFF;
-
-	newHashParts[0] ^= nLow;
-	newHashParts[1] ^= nHigh;
-	newHashParts[2] ^= nLow;
-	newHashParts[3] ^= nHigh;
-
-	/* adjust endianness */
-	for(i = 0; i < 4; i++)
-		newHashParts[i] = GUINT_TO_LE(newHashParts[i]);
-
-	/* make a string of the parts */
-	newHash = (unsigned char *)newHashParts;
-
-	/* convert to hexadecimal */
-	for (i = 0; i < 16; i++)
-	{
-		output[i * 2] = hexChars[(newHash[i] >> 4) & 0xF];
-		output[(i * 2) + 1] = hexChars[newHash[i] & 0xF];
-	}
-
-	output[32] = '\0';
-}
-
-guint8
-msn_read8(const char *buf)
-{
-	return (guint8)buf[0];
-}
-
-guint16
-msn_read16le(const char *buf)
-{
-	return GUINT16_FROM_LE(*(guint16 *)buf);
-}
-
-guint16
-msn_read16be(const char *buf)
-{
-	return GUINT16_FROM_BE(*(guint16 *)buf);
-}
-
-guint32
-msn_read32le(const char *buf)
-{
-	return GUINT32_FROM_LE(*(guint32 *)buf);
-}
-
-guint32
-msn_read32be(const char *buf)
-{
-	return GUINT32_FROM_BE(*(guint32 *)buf);
-}
-
-guint64
-msn_read64le(const char *buf)
-{
-	return GUINT64_FROM_LE(*(guint64 *)buf);
-}
-
-guint64
-msn_read64be(const char *buf)
-{
-	return GUINT64_FROM_BE(*(guint64 *)buf);
-}
-
-void
-msn_write8(char *buf, guint8 data)
-{
-	*(guint8 *)buf = data;
-}
-
-void
-msn_write16le(char *buf, guint16 data)
-{
-	*(guint16 *)buf = GUINT16_TO_LE(data);
-}
-
-void
-msn_write16be(char *buf, guint16 data)
-{
-	*(guint16 *)buf = GUINT16_TO_BE(data);
-}
-
-void
-msn_write32le(char *buf, guint32 data)
-{
-	*(guint32 *)buf = GUINT32_TO_LE(data);
-}
-
-void
-msn_write32be(char *buf, guint32 data)
-{
-	*(guint32 *)buf = GUINT32_TO_BE(data);
-}
-
-void
-msn_write64le(char *buf, guint64 data)
-{
-	*(guint64 *)buf = GUINT64_TO_LE(data);
-}
-
-void
-msn_write64be(char *buf, guint64 data)
-{
-	*(guint64 *)buf = GUINT64_TO_BE(data);
-}
-
--- a/libpurple/protocols/msn/msnutils.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,244 +0,0 @@
-/**
- * @file msnutils.h Utility functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_UTILS_H
-#define MSN_UTILS_H
-
-/*encode the str to RFC2047 style*/
-char *msn_encode_mime(const char *str);
-
-/**
- * Generate the Random GUID
- */
-char *rand_guid(void);
-
-/**
- * Encodes the spaces in a string
- *
- * @param str The string to be encoded.
- * @param buf The buffer to hold the encoded string.
- * @param len The maximum length (including NUL) to put in @buf.
- *
- * @return Whether @str was able to fit in @buf.
- */
-gboolean
-msn_encode_spaces(const char *str, char *buf, size_t len);
-
-/**
- * Parses the MSN message formatting into a format compatible with Purple.
- *
- * @param mime     The mime header with the formatting.
- * @param pre_ret  The returned prefix string.
- * @param post_ret The returned postfix string.
- *
- * @return The new message.
- */
-void msn_parse_format(const char *mime, char **pre_ret, char **post_ret);
-
-/**
- * Parses the Purple message formatting (html) into the MSN format.
- *
- * @param html			The html message to format.
- * @param attributes	The returned attributes string.
- * @param message		The returned message string.
- *
- * @return The new message.
- */
-void msn_import_html(const char *html, char **attributes, char **message);
-
-/**
- * Parses a socket string.
- *
- * @param str		A host:port string.
- * @param ret_host 	Return string value of the host.
- * @param ret_port	Return integer value of the port.
- */
-void msn_parse_socket(const char *str, char **ret_host, int *ret_port);
-
-/**
- * Parses a user name
- *
- * @param str         A network:username string.
- * @param ret_user    Return of the user's passport.
- * @param ret_network Return of the user's network.
- */
-void msn_parse_user(const char *str, char **ret_user, int *ret_network);
-
-/**
- * Verify if the email is a vaild passport.
- *
- * @param passport 	The email
- *
- * @return True if it is a valid passport, else FALSE
- */
-gboolean msn_email_is_valid(const char *passport);
-
-/**
- * Handle MSN Challenge Computation
- * This algorithm references
- * http://imfreedom.org/wiki/index.php/MSN:NS/Challenges
- *
- * @param input 	Challenge input.
- * @param output 	Callenge output.
- */
-void msn_handle_chl(char *input, char *output);
-
-/**
- * Read a byte from a buffer
- *
- * @param buf Pointer to buffer.
- *
- * @return 8-bit byte
- */
-guint8 msn_read8(const char *buf);
-
-/**
- * Read a little-endian short from a buffer
- *
- * @param buf Pointer to buffer.
- *
- * @return 16-bit short
- */
-guint16 msn_read16le(const char *buf);
-
-/**
- * Read a big-endian short from a buffer
- *
- * @param buf Pointer to buffer.
- *
- * @return 16-bit short
- */
-guint16 msn_read16be(const char *buf);
-
-/**
- * Read a little-endian int from a buffer
- *
- * @param buf Pointer to buffer.
- *
- * @return 32-bit int
- */
-guint32 msn_read32le(const char *buf);
-
-/**
- * Read a big-endian int from a buffer
- *
- * @param buf Pointer to buffer.
- *
- * @return 32-bit int
- */
-guint32 msn_read32be(const char *buf);
-
-/**
- * Read a little-endian long from a buffer
- *
- * @param buf Pointer to buffer.
- *
- * @return 64-bit long
- */
-guint64 msn_read64le(const char *buf);
-
-/**
- * Read a big-endian long from a buffer
- *
- * @param buf Pointer to buffer.
- *
- * @return 64-bit long
- */
-guint64 msn_read64be(const char *buf);
-
-/**
- * Write a byte to a buffer
- *
- * @param buf  Pointer to buffer.
- * @param data 8-bit byte.
- */
-void msn_write8(char *buf, guint8 data);
-
-/**
- * Write a little-endian short to a buffer
- *
- * @param buf  Pointer to buffer.
- * @param data short.
- */
-void msn_write16le(char *buf, guint16 data);
-
-/**
- * Write a big-endian short to a buffer
- *
- * @param buf  Pointer to buffer.
- * @param data short.
- */
-void msn_write16be(char *buf, guint16 data);
-
-/**
- * Write a little-endian int to a buffer
- *
- * @param buf  Pointer to buffer.
- * @param data int.
- */
-void msn_write32le(char *buf, guint32 data);
-
-/**
- * Write a big-endian int to a buffer
- *
- * @param buf  Pointer to buffer.
- * @param data int.
- */
-void msn_write32be(char *buf, guint32 data);
-
-/**
- * Write a little-endian long to a buffer
- *
- * @param buf  Pointer to buffer.
- * @param data long.
- */
-void msn_write64le(char *buf, guint64 data);
-
-/**
- * Write a big-endian long to a buffer
- *
- * @param buf  Pointer to buffer.
- * @param data short
- */
-void msn_write64be(char *buf, guint64 data);
-
-/**
- * Same as above, but these increment the buf pointer.
- */
-#define msn_pop8(buf)    msn_read8((buf+=1)-1)
-#define msn_pop16le(buf) msn_read16le((buf+=2)-2)
-#define msn_pop16be(buf) msn_read16be((buf+=2)-2)
-#define msn_pop32le(buf) msn_read32le((buf+=4)-4)
-#define msn_pop32be(buf) msn_read32be((buf+=4)-4)
-#define msn_pop64le(buf) msn_read64le((buf+=8)-8)
-#define msn_pop64be(buf) msn_read64be((buf+=8)-8)
-#define msn_push8(buf, data)    msn_write8(buf, data),    buf+=1
-#define msn_push16le(buf, data) msn_write16le(buf, data), buf+=2
-#define msn_push16be(buf, data) msn_write16be(buf, data), buf+=2
-#define msn_push32le(buf, data) msn_write32le(buf, data), buf+=4
-#define msn_push32be(buf, data) msn_write32be(buf, data), buf+=4
-#define msn_push64le(buf, data) msn_write64le(buf, data), buf+=8
-#define msn_push64be(buf, data) msn_write64be(buf, data), buf+=8
-
-#endif /* MSN_UTILS_H */
-
--- a/libpurple/protocols/msn/nexus.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,670 +0,0 @@
-/**
- * @file nexus.c MSN Nexus functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "cipher.h"
-#include "debug.h"
-
-#include "msnutils.h"
-#include "soap.h"
-#include "nexus.h"
-#include "notification.h"
-
-/**************************************************************************
- * Valid Ticket Tokens
- **************************************************************************/
-
-#define SSO_VALID_TICKET_DOMAIN 0
-#define SSO_VALID_TICKET_POLICY 1
-static char *ticket_domains[][2] = {
-	/* http://msnpiki.msnfanatic.com/index.php/MSNP15:SSO */
-	/* {"Domain", "Policy Ref URI"}, Purpose */
-	{"messengerclear.live.com", NULL},       /* Authentication for messenger. */
-	{"messenger.msn.com", "?id=507"},        /* Authentication for receiving OIMs. */
-	{"contacts.msn.com", "MBI"},             /* Authentication for the Contact server. */
-	{"messengersecure.live.com", "MBI_SSL"}, /* Authentication for sending OIMs. */
-	{"storage.live.com", "MBI"},             /* Storage REST API */
-	{"sup.live.com", "MBI"},                 /* What's New service */
-};
-
-/**************************************************************************
- * Main
- **************************************************************************/
-
-MsnNexus *
-msn_nexus_new(MsnSession *session)
-{
-	MsnNexus *nexus;
-	gsize i;
-
-	nexus = g_new0(MsnNexus, 1);
-	nexus->session = session;
-
-	nexus->token_len = sizeof(ticket_domains) / sizeof(char *[2]);
-	nexus->tokens = g_new0(MsnTicketToken, nexus->token_len);
-
-	for (i = 0; i < nexus->token_len; i++)
-		nexus->tokens[i].token = g_hash_table_new_full(g_str_hash, g_str_equal,
-		                                               g_free, g_free);
-
-	return nexus;
-}
-
-void
-msn_nexus_destroy(MsnNexus *nexus)
-{
-	gsize i;
-	for (i = 0; i < nexus->token_len; i++) {
-		g_hash_table_destroy(nexus->tokens[i].token);
-		g_free(nexus->tokens[i].secret);
-		g_slist_free(nexus->tokens[i].updates);
-	}
-
-	g_free(nexus->tokens);
-	g_free(nexus->policy);
-	g_free(nexus->nonce);
-	g_free(nexus->cipher);
-	g_free(nexus->secret);
-	g_free(nexus);
-}
-
-/**************************************************************************
- * RPS/SSO Authentication
- **************************************************************************/
-
-static char *
-rps_create_key(const char *key, int key_len, const char *data, size_t data_len)
-{
-	const guchar magic[] = "WS-SecureConversation";
-	const int magic_len = sizeof(magic) - 1;
-
-	PurpleCipherContext *hmac;
-	guchar hash1[20], hash2[20], hash3[20], hash4[20];
-	char *result;
-
-	hmac = purple_cipher_context_new_by_name("hmac", NULL);
-
-	purple_cipher_context_set_option(hmac, "hash", "sha1");
-	purple_cipher_context_set_key_with_len(hmac, (guchar *)key, key_len);
-	purple_cipher_context_append(hmac, magic, magic_len);
-	purple_cipher_context_append(hmac, (guchar *)data, data_len);
-	purple_cipher_context_digest(hmac, sizeof(hash1), hash1, NULL);
-
-	purple_cipher_context_reset(hmac, NULL);
-	purple_cipher_context_set_option(hmac, "hash", "sha1");
-	purple_cipher_context_set_key_with_len(hmac, (guchar *)key, key_len);
-	purple_cipher_context_append(hmac, hash1, 20);
-	purple_cipher_context_append(hmac, magic, magic_len);
-	purple_cipher_context_append(hmac, (guchar *)data, data_len);
-	purple_cipher_context_digest(hmac, sizeof(hash2), hash2, NULL);
-
-	purple_cipher_context_reset(hmac, NULL);
-	purple_cipher_context_set_option(hmac, "hash", "sha1");
-	purple_cipher_context_set_key_with_len(hmac, (guchar *)key, key_len);
-	purple_cipher_context_append(hmac, hash1, 20);
-	purple_cipher_context_digest(hmac, sizeof(hash3), hash3, NULL);
-
-	purple_cipher_context_reset(hmac, NULL);
-	purple_cipher_context_set_option(hmac, "hash", "sha1");
-	purple_cipher_context_set_key_with_len(hmac, (guchar *)key, key_len);
-	purple_cipher_context_append(hmac, hash3, sizeof(hash3));
-	purple_cipher_context_append(hmac, magic, magic_len);
-	purple_cipher_context_append(hmac, (guchar *)data, data_len);
-	purple_cipher_context_digest(hmac, sizeof(hash4), hash4, NULL);
-
-	purple_cipher_context_destroy(hmac);
-
-	result = g_malloc(24);
-	memcpy(result, hash2, sizeof(hash2));
-	memcpy(result + sizeof(hash2), hash4, 4);
-
-	return result;
-}
-
-static char *
-des3_cbc(const char *key, const char *iv, const char *data, int len, gboolean decrypt)
-{
-	PurpleCipherContext *des3;
-	char *out;
-	size_t outlen;
-
-	des3 = purple_cipher_context_new_by_name("des3", NULL);
-	purple_cipher_context_set_key(des3, (guchar *)key);
-	purple_cipher_context_set_batch_mode(des3, PURPLE_CIPHER_BATCH_MODE_CBC);
-	purple_cipher_context_set_iv(des3, (guchar *)iv, 8);
-
-	out = g_malloc(len);
-	if (decrypt)
-		purple_cipher_context_decrypt(des3, (guchar *)data, len, (guchar *)out, &outlen);
-	else
-		purple_cipher_context_encrypt(des3, (guchar *)data, len, (guchar *)out, &outlen);
-
-	purple_cipher_context_destroy(des3);
-
-	return out;
-}
-
-#define MSN_USER_KEY_SIZE (7*4 + 8 + 20 + 72)
-#define CRYPT_MODE_CBC 1
-#define CIPHER_TRIPLE_DES 0x6603
-#define HASH_SHA1 0x8004
-static char *
-msn_rps_encrypt(MsnNexus *nexus)
-{
-	char usr_key_base[MSN_USER_KEY_SIZE], *usr_key;
-	const char magic1[] = "SESSION KEY HASH";
-	const char magic2[] = "SESSION KEY ENCRYPTION";
-	PurpleCipherContext *hmac;
-	size_t len;
-	guchar *hash;
-	char *key1, *key2, *key3;
-	gsize key1_len;
-	const char *iv;
-	char *nonce_fixed;
-	char *cipher;
-	char *response;
-
-	usr_key = &usr_key_base[0];
-	/* Header */
-	msn_push32le(usr_key, 28);                  /* Header size */
-	msn_push32le(usr_key, CRYPT_MODE_CBC);      /* Crypt mode */
-	msn_push32le(usr_key, CIPHER_TRIPLE_DES);   /* Cipher type */
-	msn_push32le(usr_key, HASH_SHA1);           /* Hash type */
-	msn_push32le(usr_key, 8);                   /* IV size */
-	msn_push32le(usr_key, 20);                  /* Hash size */
-	msn_push32le(usr_key, 72);                  /* Cipher size */
-	/* Data */
-	iv = usr_key;
-	msn_push32le(usr_key, rand());
-	msn_push32le(usr_key, rand());
-	hash = (guchar *)usr_key;
-	usr_key += 20;  /* Remaining is cipher data */
-
-	key1 = (char *)purple_base64_decode((const char *)nexus->tokens[MSN_AUTH_MESSENGER].secret, &key1_len);
-	key2 = rps_create_key(key1, key1_len, magic1, sizeof(magic1) - 1);
-	key3 = rps_create_key(key1, key1_len, magic2, sizeof(magic2) - 1);
-
-	len = strlen(nexus->nonce);
-	hmac = purple_cipher_context_new_by_name("hmac", NULL);
-	purple_cipher_context_set_option(hmac, "hash", "sha1");
-	purple_cipher_context_set_key_with_len(hmac, (guchar *)key2, 24);
-	purple_cipher_context_append(hmac, (guchar *)nexus->nonce, len);
-	purple_cipher_context_digest(hmac, 20, hash, NULL);
-	purple_cipher_context_destroy(hmac);
-
-	/* We need to pad this to 72 bytes, apparently */
-	nonce_fixed = g_malloc(len + 8);
-	memcpy(nonce_fixed, nexus->nonce, len);
-	memset(nonce_fixed + len, 0x08, 8);
-	cipher = des3_cbc(key3, iv, nonce_fixed, len + 8, FALSE);
-	g_free(nonce_fixed);
-
-	memcpy(usr_key, cipher, 72);
-
-	g_free(key1);
-	g_free(key2);
-	g_free(key3);
-	g_free(cipher);
-
-	response = purple_base64_encode((guchar *)usr_key_base, MSN_USER_KEY_SIZE);
-
-	return response;
-}
-
-/**************************************************************************
- * Login
- **************************************************************************/
-
-/* Used to specify which token to update when only doing single updates */
-typedef struct _MsnNexusUpdateData MsnNexusUpdateData;
-struct _MsnNexusUpdateData {
-	MsnNexus *nexus;
-	int id;
-};
-
-typedef struct _MsnNexusUpdateCallback MsnNexusUpdateCallback;
-struct _MsnNexusUpdateCallback {
-	GSourceFunc cb;
-	gpointer data;
-};
-
-static gboolean
-nexus_parse_token(MsnNexus *nexus, int id, xmlnode *node)
-{
-	char *token_str, *expiry_str;
-	const char *id_str;
-	char **elems, **cur, **tokens;
-	xmlnode *token = xmlnode_get_child(node, "RequestedSecurityToken/BinarySecurityToken");
-	xmlnode *secret = xmlnode_get_child(node, "RequestedProofToken/BinarySecret");
-	xmlnode *expires = xmlnode_get_child(node, "LifeTime/Expires");
-
-	if (!token)
-		return FALSE;
-
-	/* Use the ID that the server sent us */
-	if (id == -1) {
-		id_str = xmlnode_get_attrib(token, "Id");
-		if (id_str == NULL)
-			return FALSE;
-
-		id = atol(id_str + 7) - 1;	/* 'Compact#' or 'PPToken#' */
-		if (id < 0 || (gsize)id >= nexus->token_len)
-			return FALSE;	/* Where did this come from? */
-	}
-
-	token_str = xmlnode_get_data(token);
-	if (token_str == NULL)
-		return FALSE;
-
-	g_hash_table_remove_all(nexus->tokens[id].token);
-
-	elems = g_strsplit(token_str, "&", 0);
-
-	for (cur = elems; *cur != NULL; cur++) {
-		tokens = g_strsplit(*cur, "=", 2);
-		g_hash_table_insert(nexus->tokens[id].token, tokens[0], tokens[1]);
-		/* Don't free each of the tokens, only the array. */
-		g_free(tokens);
-	}
-	g_strfreev(elems);
-	g_free(token_str);
-
-	if (secret)
-		nexus->tokens[id].secret = xmlnode_get_data(secret);
-	else
-		nexus->tokens[id].secret = NULL;
-
-	/* Yay for MS using ISO-8601 */
-	expiry_str = xmlnode_get_data(expires);
-	nexus->tokens[id].expiry = purple_str_to_time(expiry_str,
-		FALSE, NULL, NULL, NULL);
-	g_free(expiry_str);
-
-	purple_debug_info("msn", "Updated ticket for domain '%s', expires at %" G_GINT64_FORMAT ".\n",
-	                  ticket_domains[id][SSO_VALID_TICKET_DOMAIN],
-	                  (gint64)nexus->tokens[id].expiry);
-	return TRUE;
-}
-
-static gboolean
-nexus_parse_collection(MsnNexus *nexus, int id, xmlnode *collection)
-{
-	xmlnode *node;
-	gboolean result;
-
-	node = xmlnode_get_child(collection, "RequestSecurityTokenResponse");
-
-	if (!node)
-		return FALSE;
-
-	result = TRUE;
-	for (; node && result; node = node->next) {
-		xmlnode *endpoint = xmlnode_get_child(node, "AppliesTo/EndpointReference/Address");
-		char *address = xmlnode_get_data(endpoint);
-
-		if (g_str_equal(address, "http://Passport.NET/tb")) {
-			/* This node contains the stuff for updating tokens. */
-			char *data;
-			xmlnode *cipher = xmlnode_get_child(node, "RequestedSecurityToken/EncryptedData/CipherData/CipherValue");
-			xmlnode *secret = xmlnode_get_child(node, "RequestedProofToken/BinarySecret");
-
-			g_free(nexus->cipher);
-			nexus->cipher = xmlnode_get_data(cipher);
-			data = xmlnode_get_data(secret);
-			g_free(nexus->secret);
-			nexus->secret = (char *)purple_base64_decode(data, NULL);
-			g_free(data);
-
-		} else {
-			result = nexus_parse_token(nexus, id, node);
-		}
-		g_free(address);
-	}
-
-	return result;
-}
-
-static void
-nexus_got_response_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
-{
-	MsnNexus *nexus = data;
-	MsnSession *session = nexus->session;
-	const char *ticket;
-	char *response;
-
-	if (resp == NULL) {
-		msn_session_set_error(session, MSN_ERROR_SERVCONN, _("Windows Live ID authentication:Unable to connect"));
-		return;
-	}
-
-	if (!nexus_parse_collection(nexus, -1,
-	                            xmlnode_get_child(resp->xml,
-	                                              "Body/RequestSecurityTokenResponseCollection"))) {
-		msn_session_set_error(session, MSN_ERROR_SERVCONN, _("Windows Live ID authentication:Invalid response"));
-		return;
-	}
-
-	ticket = msn_nexus_get_token_str(nexus, MSN_AUTH_MESSENGER);
-	response = msn_rps_encrypt(nexus);
-	msn_got_login_params(session, ticket, response);
-	g_free(response);
-}
-
-/*when connect, do the SOAP Style windows Live ID authentication */
-void
-msn_nexus_connect(MsnNexus *nexus)
-{
-	MsnSession *session = nexus->session;
-	const char *username;
-	const char *password;
-	char *password_xml;
-	GString *domains;
-	char *request;
-	gsize i;
-
-	MsnSoapMessage *soap;
-
-	purple_debug_info("msn", "Starting Windows Live ID authentication\n");
-	msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE);
-
-	username = purple_account_get_username(session->account);
-	password = purple_connection_get_password(session->account->gc);
-	if (g_utf8_strlen(password, -1) > 16) {
-		/* max byte size for 16 utf8 characters is 64 + 1 for the null */
-		gchar truncated[65];
-		g_utf8_strncpy(truncated, password, 16);
-		password_xml = g_markup_escape_text(truncated, -1);
-	} else {
-		password_xml = g_markup_escape_text(password, -1);
-	}
-
-	purple_debug_info("msn", "Logging on %s, with policy '%s', nonce '%s'\n",
-	                  username, nexus->policy, nexus->nonce);
-
-	domains = g_string_new(NULL);
-	for (i = 0; i < nexus->token_len; i++) {
-		g_string_append_printf(domains, MSN_SSO_RST_TEMPLATE,
-		                       (int)i+1,
-		                       ticket_domains[i][SSO_VALID_TICKET_DOMAIN],
-		                       ticket_domains[i][SSO_VALID_TICKET_POLICY] != NULL ?
-		                           ticket_domains[i][SSO_VALID_TICKET_POLICY] :
-		                           nexus->policy);
-	}
-
-	request = g_strdup_printf(MSN_SSO_TEMPLATE, username, password_xml, domains->str);
-	g_free(password_xml);
-	g_string_free(domains, TRUE);
-
-	soap = msn_soap_message_new(NULL, xmlnode_from_str(request, -1));
-	g_free(request);
-	msn_soap_message_send(session, soap, MSN_SSO_SERVER, SSO_POST_URL, TRUE,
-	                      nexus_got_response_cb, nexus);
-}
-
-static void
-nexus_got_update_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
-{
-	MsnNexusUpdateData *ud = data;
-	MsnNexus *nexus = ud->nexus;
-	char iv[8] = {0,0,0,0,0,0,0,0};
-	xmlnode *enckey;
-	char *tmp;
-	char *nonce;
-	gsize len;
-	char *key;
-	GSList *updates;
-
-#if 0
-	char *decrypted_pp;
-#endif
-	char *decrypted_data;
-
-	if (resp == NULL)
-		return;
-
-	purple_debug_info("msn", "Got Update Response for %s.\n", ticket_domains[ud->id][SSO_VALID_TICKET_DOMAIN]);
-
-	enckey = xmlnode_get_child(resp->xml, "Header/Security/DerivedKeyToken");
-	while (enckey) {
-		if (g_str_equal(xmlnode_get_attrib(enckey, "Id"), "EncKey"))
-			break;
-		enckey = xmlnode_get_next_twin(enckey);
-	}
-	if (!enckey) {
-		purple_debug_error("msn", "Invalid response in token update.\n");
-		return;
-	}
-
-	tmp = xmlnode_get_data(xmlnode_get_child(enckey, "Nonce"));
-	nonce = (char *)purple_base64_decode(tmp, &len);
-	key = rps_create_key(nexus->secret, 24, nonce, len);
-	g_free(tmp);
-	g_free(nonce);
-
-#if 0
-	/* Don't know what this is for yet */
-	tmp = xmlnode_get_data(xmlnode_get_child(resp->xml,
-		"Header/EncryptedPP/EncryptedData/CipherData/CipherValue"));
-	if (tmp) {
-		decrypted_pp = des3_cbc(key, iv, tmp, len, TRUE);
-		g_free(tmp);
-		purple_debug_info("msn", "Got Response Header EncryptedPP: %s\n", decrypted_pp);
-		g_free(decrypted_pp);
-	}
-#endif
-
-	tmp = xmlnode_get_data(xmlnode_get_child(resp->xml,
-		"Body/EncryptedData/CipherData/CipherValue"));
-	if (tmp) {
-		char *unescaped;
-		xmlnode *rstresponse;
-
-		unescaped = (char *)purple_base64_decode(tmp, &len);
-		g_free(tmp);
-
-		decrypted_data = des3_cbc(key, iv, unescaped, len, TRUE);
-		g_free(unescaped);
-		purple_debug_info("msn", "Got Response Body EncryptedData: %s\n", decrypted_data);
-
-		rstresponse = xmlnode_from_str(decrypted_data, -1);
-		if (g_str_equal(rstresponse->name, "RequestSecurityTokenResponse"))
-			nexus_parse_token(nexus, ud->id, rstresponse);
-		else
-			nexus_parse_collection(nexus, ud->id, rstresponse);
-		g_free(decrypted_data);
-	}
-
-	updates = nexus->tokens[ud->id].updates;
-	nexus->tokens[ud->id].updates = NULL;
-	while (updates != NULL) {
-		MsnNexusUpdateCallback *update = updates->data;
-		if (update->cb)
-			purple_timeout_add(0, update->cb, update->data);
-		g_free(update);
-		updates = g_slist_delete_link(updates, updates);
-	}
-
-	g_free(ud);
-	g_free(key);
-}
-
-void
-msn_nexus_update_token(MsnNexus *nexus, int id, GSourceFunc cb, gpointer data)
-{
-	MsnSession *session = nexus->session;
-	MsnNexusUpdateData *ud;
-	MsnNexusUpdateCallback *update;
-	PurpleCipherContext *sha1;
-	PurpleCipherContext *hmac;
-
-	char *key;
-
-	guchar digest[20];
-
-	struct tm *tm;
-	time_t now;
-	char *now_str;
-	char *timestamp;
-	char *timestamp_b64;
-
-	char *domain;
-	char *domain_b64;
-
-	char *signedinfo;
-	gint32 nonce[6];
-	int i;
-	char *nonce_b64;
-	char *signature_b64;
-	guchar signature[20];
-
-	char *request;
-	MsnSoapMessage *soap;
-
-	update = g_new0(MsnNexusUpdateCallback, 1);
-	update->cb = cb;
-	update->data = data;
-
-	if (nexus->tokens[id].updates != NULL) {
-		/* Update already in progress. Just add to list and return. */
-		purple_debug_info("msn",
-		                  "Ticket update for user '%s' on domain '%s' in progress. Adding request to queue.\n",
-		                  purple_account_get_username(session->account),
-		                  ticket_domains[id][SSO_VALID_TICKET_DOMAIN]);
-		nexus->tokens[id].updates = g_slist_prepend(nexus->tokens[id].updates,
-		                                            update);
-		return;
-	} else {
-		purple_debug_info("msn",
-		                  "Updating ticket for user '%s' on domain '%s'\n",
-		                  purple_account_get_username(session->account),
-		                  ticket_domains[id][SSO_VALID_TICKET_DOMAIN]);
-		nexus->tokens[id].updates = g_slist_prepend(nexus->tokens[id].updates,
-		                                            update);
-	}
-
-	ud = g_new0(MsnNexusUpdateData, 1);
-	ud->nexus = nexus;
-	ud->id = id;
-
-	sha1 = purple_cipher_context_new_by_name("sha1", NULL);
-
-	domain = g_strdup_printf(MSN_SSO_RST_TEMPLATE,
-	                         id,
-	                         ticket_domains[id][SSO_VALID_TICKET_DOMAIN],
-	                         ticket_domains[id][SSO_VALID_TICKET_POLICY] != NULL ?
-	                             ticket_domains[id][SSO_VALID_TICKET_POLICY] :
-	                             nexus->policy);
-	purple_cipher_context_append(sha1, (guchar *)domain, strlen(domain));
-	purple_cipher_context_digest(sha1, 20, digest, NULL);
-	domain_b64 = purple_base64_encode(digest, 20);
-
-	now = time(NULL);
-	tm = gmtime(&now);
-	now_str = g_strdup(purple_utf8_strftime("%Y-%m-%dT%H:%M:%SZ", tm));
-	now += 5*60;
-	tm = gmtime(&now);
-	timestamp = g_strdup_printf(MSN_SSO_TIMESTAMP_TEMPLATE,
-	                            now_str,
-	                            purple_utf8_strftime("%Y-%m-%dT%H:%M:%SZ", tm));
-	purple_cipher_context_reset(sha1, NULL);
-	purple_cipher_context_append(sha1, (guchar *)timestamp, strlen(timestamp));
-	purple_cipher_context_digest(sha1, 20, digest, NULL);
-	timestamp_b64 = purple_base64_encode(digest, 20);
-	g_free(now_str);
-
-	purple_cipher_context_destroy(sha1);
-
-	signedinfo = g_strdup_printf(MSN_SSO_SIGNEDINFO_TEMPLATE,
-	                             id,
-	                             domain_b64,
-	                             timestamp_b64);
-
-	for (i = 0; i < 6; i++)
-		nonce[i] = rand();
-	nonce_b64 = purple_base64_encode((guchar *)&nonce, sizeof(nonce));
-
-	key = rps_create_key(nexus->secret, 24, (char *)nonce, sizeof(nonce));
-	hmac = purple_cipher_context_new_by_name("hmac", NULL);
-	purple_cipher_context_set_option(hmac, "hash", "sha1");
-	purple_cipher_context_set_key_with_len(hmac, (guchar *)key, 24);
-	purple_cipher_context_append(hmac, (guchar *)signedinfo, strlen(signedinfo));
-	purple_cipher_context_digest(hmac, 20, signature, NULL);
-	purple_cipher_context_destroy(hmac);
-	signature_b64 = purple_base64_encode(signature, 20);
-
-	request = g_strdup_printf(MSN_SSO_TOKEN_UPDATE_TEMPLATE,
-	                          nexus->cipher,
-	                          nonce_b64,
-	                          timestamp,
-	                          signedinfo,
-	                          signature_b64,
-	                          domain);
-
-	g_free(nonce_b64);
-	g_free(domain_b64);
-	g_free(timestamp_b64);
-	g_free(timestamp);
-	g_free(key);
-	g_free(signature_b64);
-	g_free(signedinfo);
-	g_free(domain);
-
-	soap = msn_soap_message_new(NULL, xmlnode_from_str(request, -1));
-	g_free(request);
-	msn_soap_message_send(session, soap, MSN_SSO_SERVER, SSO_POST_URL, TRUE,
-	                      nexus_got_update_cb, ud);
-}
-
-GHashTable *
-msn_nexus_get_token(MsnNexus *nexus, MsnAuthDomains id)
-{
-	g_return_val_if_fail(nexus != NULL, NULL);
-	g_return_val_if_fail(id < nexus->token_len, NULL);
-
-	return nexus->tokens[id].token;
-}
-
-const char *
-msn_nexus_get_token_str(MsnNexus *nexus, MsnAuthDomains id)
-{
-	static char buf[1024];
-	GHashTable *token = msn_nexus_get_token(nexus, id);
-	const char *msn_t;
-	const char *msn_p;
-	gint ret;
-
-	g_return_val_if_fail(token != NULL, NULL);
-
-	msn_t = g_hash_table_lookup(token, "t");
-	msn_p = g_hash_table_lookup(token, "p");
-
-	g_return_val_if_fail(msn_t != NULL, NULL);
-	g_return_val_if_fail(msn_p != NULL, NULL);
-
-	ret = g_snprintf(buf, sizeof(buf) - 1, "t=%s&p=%s", msn_t, msn_p);
-	g_return_val_if_fail(ret != -1, NULL);
-
-	return buf;
-}
-
--- a/libpurple/protocols/msn/nexus.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +0,0 @@
-/**
- * @file nexus.h MSN Nexus functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_NEXUS_H
-#define MSN_NEXUS_H
-
-#include "internal.h"
-
-typedef struct _MsnNexus MsnNexus;
-typedef struct _MsnTicketToken MsnTicketToken;
-
-/* Index into ticket_tokens in nexus.c Keep updated! */
-typedef enum
-{
-	MSN_AUTH_MESSENGER     = 0,
-	MSN_AUTH_MESSENGER_WEB = 1,
-	MSN_AUTH_CONTACTS      = 2,
-	MSN_AUTH_LIVE_SECURE   = 3,
-	MSN_AUTH_STORAGE       = 4,
-	MSN_AUTH_WHATSNEW      = 5
-} MsnAuthDomains;
-
-#define MSN_SSO_SERVER	"login.live.com"
-#define SSO_POST_URL	"/RST.srf"
-
-#define MSN_SSO_RST_TEMPLATE \
-"<wst:RequestSecurityToken xmlns=\"http://schemas.xmlsoap.org/ws/2004/04/trust\" Id=\"RST%d\">"\
-	"<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\
-	"<wsp:AppliesTo xmlns=\"http://schemas.xmlsoap.org/ws/2002/12/policy\">"\
-		"<wsa:EndpointReference xmlns=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">"\
-			"<wsa:Address>%s</wsa:Address>"\
-		"</wsa:EndpointReference>"\
-	"</wsp:AppliesTo>"\
-	"<wsse:PolicyReference xmlns=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" URI=\"%s\"></wsse:PolicyReference>"\
-"</wst:RequestSecurityToken>"
-
-#define MSN_SSO_TEMPLATE "<?xml version='1.0' encoding='utf-8'?>"\
-"<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\""\
-	" xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\""\
-	" xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\""\
-	" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\""\
-	" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\""\
-	" xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\""\
-	" xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\">"\
-	"<Header>"\
-		"<ps:AuthInfo"\
-			" xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\""\
-			" Id=\"PPAuthInfo\">"\
-			"<ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp>"\
-			"<ps:BinaryVersion>4</ps:BinaryVersion>"\
-			"<ps:UIVersion>1</ps:UIVersion>"\
-			"<ps:Cookies></ps:Cookies>"\
-			"<ps:RequestParams>AQAAAAIAAABsYwQAAAAxMDMz</ps:RequestParams>"\
-		"</ps:AuthInfo>"\
-		"<wsse:Security>"\
-			"<wsse:UsernameToken Id=\"user\">"\
-				"<wsse:Username>%s</wsse:Username>"\
-				"<wsse:Password>%s</wsse:Password>"\
-			"</wsse:UsernameToken>"\
-		"</wsse:Security>"\
-	"</Header>"\
-	"<Body>"\
-		"<ps:RequestMultipleSecurityTokens"\
-			" xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\""\
-			" Id=\"RSTS\">"\
-			"<wst:RequestSecurityToken Id=\"RST0\">"\
-				"<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\
-				"<wsp:AppliesTo>"\
-					"<wsa:EndpointReference>"\
-						"<wsa:Address>http://Passport.NET/tb</wsa:Address>"\
-					"</wsa:EndpointReference>"\
-				"</wsp:AppliesTo>"\
-			"</wst:RequestSecurityToken>"\
-			"%s"	/* Other RSTn tokens */\
-		"</ps:RequestMultipleSecurityTokens>"\
-	"</Body>"\
-"</Envelope>"
-
-#define MSN_SSO_AUTHINFO_TEMPLATE \
-"<ps:AuthInfo xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"PPAuthInfo\">"\
-	"<ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp>"\
-	"<ps:BinaryVersion>4</ps:BinaryVersion>"\
-	"<ps:UIVersion>1</ps:UIVersion>"\
-	"<ps:Cookies></ps:Cookies>"\
-	"<ps:RequestParams>AQAAAAIAAABsYwQAAAA0MTA1</ps:RequestParams>"\
-"</ps:AuthInfo>"
-/* Not sure what's editable here, so I'll just hard-code the SHA1 hash */
-#define MSN_SSO_AUTHINFO_SHA1_BASE64 "d2IeTF4DAkPEa/tVETHznsivEpc="
-
-#define MSN_SSO_TIMESTAMP_TEMPLATE \
-"<wsu:Timestamp xmlns=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" Id=\"Timestamp\">"\
-	"<wsu:Created>%s</wsu:Created>"\
-	"<wsu:Expires>%s</wsu:Expires>"\
-"</wsu:Timestamp>"
-
-#define MSN_SSO_SIGNEDINFO_TEMPLATE \
-"<SignedInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\">"\
-	"<CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></CanonicalizationMethod>"\
-	"<SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#hmac-sha1\"></SignatureMethod>"\
-	"<Reference URI=\"#RST%d\">"\
-		"<Transforms>"\
-			"<Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform>"\
-		"</Transforms>"\
-		"<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod>"\
-		"<DigestValue>%s</DigestValue>"\
-	"</Reference>"\
-	"<Reference URI=\"#Timestamp\">"\
-		"<Transforms>"\
-			"<Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform>"\
-		"</Transforms>"\
-		"<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod>"\
-		"<DigestValue>%s</DigestValue>"\
-	"</Reference>"\
-	"<Reference URI=\"#PPAuthInfo\">"\
-		"<Transforms>"\
-			"<Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform>"\
-		"</Transforms>"\
-		"<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod>"\
-		"<DigestValue>" MSN_SSO_AUTHINFO_SHA1_BASE64 "</DigestValue>"\
-	"</Reference>"\
-"</SignedInfo>"
-
-#define MSN_SSO_TOKEN_UPDATE_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<Envelope"\
-	" xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-	" xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\""\
-	" xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\""\
-	" xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\""\
-	" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\""\
-	" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\""\
-	" xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\""\
-	" xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\">"\
-	"<Header>"\
-		MSN_SSO_AUTHINFO_TEMPLATE /* ps:AuthInfo */ \
-		"<wsse:Security>"\
-			"<EncryptedData xmlns=\"http://www.w3.org/2001/04/xmlenc#\" Id=\"BinaryDAToken0\" Type=\"http://www.w3.org/2001/04/xmlenc#Element\">"\
-				"<EncryptionMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#tripledes-cbc\"></EncryptionMethod>"\
-				"<ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">"\
-					"<ds:KeyName>http://Passport.NET/STS</ds:KeyName>"\
-				"</ds:KeyInfo>"\
-				"<CipherData>"\
-					"<CipherValue>%s</CipherValue>"\
-				"</CipherData>"\
-			"</EncryptedData>"\
-			"<wssc:DerivedKeyToken Id=\"SignKey\">"\
-				"<wsse:RequestedTokenReference>"\
-					"<wsse:KeyIdentifier ValueType=\"http://docs.oasis-open.org/wss/2004/XX/oasis-2004XX-wss-saml-token-profile-1.0#SAMLAssertionID\" />"\
-					"<wsse:Reference URI=\"#BinaryDAToken0\" />"\
-				"</wsse:RequestedTokenReference>"\
-				"<wssc:Nonce>%s</wssc:Nonce>"\
-			"</wssc:DerivedKeyToken>"\
-			"%s" /* wsu:Timestamp */\
-			"<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\">"\
-				"%s" /* SignedInfo */\
-				"<SignatureValue>%s</SignatureValue>"\
-				"<KeyInfo>"\
-					"<wsse:SecurityTokenReference>"\
-						"<wsse:Reference URI=\"#SignKey\" />"\
-					"</wsse:SecurityTokenReference>"\
-				"</KeyInfo>"\
-			"</Signature>"\
-		"</wsse:Security>"\
-	"</Header>"\
-	"<Body>"\
-		"%s" /* wst:RequestSecurityToken */ \
-	"</Body>"\
-"</Envelope>"
-
-struct _MsnTicketToken {
-	GHashTable *token;
-	char *secret;
-	time_t expiry;
-	GSList *updates;
-};
-
-struct _MsnNexus
-{
-	MsnSession *session;
-
-	/* From server via USR command */
-	char *policy;
-	char *nonce;
-
-	/* From server via SOAP stuff */
-	char *cipher;
-	char *secret;
-	MsnTicketToken *tokens;
-	gsize token_len;
-};
-
-void msn_nexus_connect(MsnNexus *nexus);
-MsnNexus *msn_nexus_new(MsnSession *session);
-void msn_nexus_destroy(MsnNexus *nexus);
-GHashTable *msn_nexus_get_token(MsnNexus *nexus, MsnAuthDomains id);
-const char *msn_nexus_get_token_str(MsnNexus *nexus, MsnAuthDomains id);
-void msn_nexus_update_token(MsnNexus *nexus, int id, GSourceFunc cb, gpointer data);
-
-#endif /* MSN_NEXUS_H */
--- a/libpurple/protocols/msn/notification.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2480 +0,0 @@
-/**
- * @file notification.c Notification server functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "cipher.h"
-#include "core.h"
-#include "debug.h"
-
-#include "notification.h"
-
-#include "contact.h"
-#include "error.h"
-#include "msnutils.h"
-#include "state.h"
-#include "userlist.h"
-
-static MsnTable *cbs_table;
-
-/**************************************************************************
- * Main
- **************************************************************************/
-
-static void
-destroy_cb(MsnServConn *servconn)
-{
-	MsnNotification *notification;
-
-	notification = servconn->cmdproc->data;
-	g_return_if_fail(notification != NULL);
-
-	msn_notification_destroy(notification);
-}
-
-MsnNotification *
-msn_notification_new(MsnSession *session)
-{
-	MsnNotification *notification;
-	MsnServConn *servconn;
-
-	g_return_val_if_fail(session != NULL, NULL);
-
-	notification = g_new0(MsnNotification, 1);
-
-	notification->session = session;
-	notification->servconn = servconn = msn_servconn_new(session, MSN_SERVCONN_NS);
-	msn_servconn_set_destroy_cb(servconn, destroy_cb);
-
-	notification->cmdproc = servconn->cmdproc;
-	notification->cmdproc->data = notification;
-	notification->cmdproc->cbs_table = cbs_table;
-
-	return notification;
-}
-
-void
-msn_notification_destroy(MsnNotification *notification)
-{
-	notification->cmdproc->data = NULL;
-
-	msn_servconn_set_destroy_cb(notification->servconn, NULL);
-
-	msn_servconn_destroy(notification->servconn);
-
-	g_free(notification);
-}
-
-/**************************************************************************
- * Connect
- **************************************************************************/
-
-static void
-connect_cb(MsnServConn *servconn)
-{
-	MsnCmdProc *cmdproc;
-	MsnSession *session;
-	MsnTransaction *trans;
-	GString *vers;
-	const char *ver_str;
-	int i;
-
-	g_return_if_fail(servconn != NULL);
-
-	cmdproc = servconn->cmdproc;
-	session = servconn->session;
-
-	vers = g_string_new("");
-
-	for (i = WLM_MAX_PROTOCOL; i >= WLM_MIN_PROTOCOL; i--)
-		g_string_append_printf(vers, " MSNP%d", i);
-
-	g_string_append(vers, " CVR0");
-
-	if (session->login_step == MSN_LOGIN_STEP_START)
-		msn_session_set_login_step(session, MSN_LOGIN_STEP_HANDSHAKE);
-	else
-		msn_session_set_login_step(session, MSN_LOGIN_STEP_HANDSHAKE2);
-
-	/* Skip the initial space */
-	ver_str = (vers->str + 1);
-	trans = msn_transaction_new(cmdproc, "VER", "%s", ver_str);
-	msn_cmdproc_send_trans(cmdproc, trans);
-
-	g_string_free(vers, TRUE);
-}
-
-gboolean
-msn_notification_connect(MsnNotification *notification, const char *host, int port)
-{
-	MsnServConn *servconn;
-
-	g_return_val_if_fail(notification != NULL, FALSE);
-
-	servconn = notification->servconn;
-
-	msn_servconn_set_connect_cb(servconn, connect_cb);
-	notification->in_use = msn_servconn_connect(servconn, host, port, TRUE);
-
-	return notification->in_use;
-}
-
-void
-msn_notification_disconnect(MsnNotification *notification)
-{
-	g_return_if_fail(notification != NULL);
-	g_return_if_fail(notification->in_use);
-
-	msn_servconn_disconnect(notification->servconn);
-
-	notification->in_use = FALSE;
-}
-
-/**************************************************************************
- * Login
- **************************************************************************/
-
-void
-msn_got_login_params(MsnSession *session, const char *ticket, const char *response)
-{
-	MsnCmdProc *cmdproc;
-	MsnTransaction *trans;
-
-	cmdproc = session->notification->cmdproc;
-
-	msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_END);
-
-	trans = msn_transaction_new(cmdproc, "USR", "SSO S %s %s %s", ticket, response, session->guid);
-
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-static void
-cvr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	PurpleAccount *account;
-	MsnTransaction *trans;
-
-	account = cmdproc->session->account;
-
-	trans = msn_transaction_new(cmdproc, "USR", "SSO I %s", purple_account_get_username(account));
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-static void
-usr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnSession *session = cmdproc->session;
-
-	if (!g_ascii_strcasecmp(cmd->params[1], "OK"))
-	{
-		/* authenticate OK */
-		msn_session_set_login_step(session, MSN_LOGIN_STEP_SYN);
-	}
-	else if (!g_ascii_strcasecmp(cmd->params[1], "SSO"))
-	{
-		/* RPS authentication */
-
-		if (session->nexus)
-			msn_nexus_destroy(session->nexus);
-
-		session->nexus = msn_nexus_new(session);
-
-		session->nexus->policy = g_strdup(cmd->params[3]);
-		session->nexus->nonce = g_strdup(cmd->params[4]);
-
-		msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_START);
-
-		msn_nexus_connect(session->nexus);
-	}
-}
-
-static void
-usr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
-{
-	MsnErrorType msnerr = 0;
-
-	switch (error)
-	{
-		case 500:
-		case 601:
-		case 910:
-		case 921:
-			msnerr = MSN_ERROR_SERV_UNAVAILABLE;
-			break;
-		case 911:
-			msnerr = MSN_ERROR_AUTH;
-			break;
-		default:
-			return;
-			break;
-	}
-
-	msn_session_set_error(cmdproc->session, msnerr, NULL);
-}
-
-static void
-ver_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnSession *session;
-	MsnTransaction *trans;
-	PurpleAccount *account;
-	gboolean protocol_supported = FALSE;
-	guint proto_ver;
-	size_t i;
-
-	session = cmdproc->session;
-	account = session->account;
-
-	session->protocol_ver = 0;
-	for (i = 1; i < cmd->param_count; i++)
-	{
-		if (sscanf(cmd->params[i], "MSNP%d", &proto_ver) == 1) {
-			if (proto_ver >= WLM_MIN_PROTOCOL
-			 && proto_ver <= WLM_MAX_PROTOCOL
-			 && proto_ver > session->protocol_ver) {
-				protocol_supported = TRUE;
-				session->protocol_ver = proto_ver;
-			}
-		}
-	}
-
-	if (!protocol_supported)
-	{
-		msn_session_set_error(session, MSN_ERROR_UNSUPPORTED_PROTOCOL,
-							  NULL);
-		return;
-	}
-
-	purple_debug_info("msn", "Negotiated protocol version %d with the server.\n", session->protocol_ver);
-
-	/*
-	 * Windows Live Messenger 8.5
-	 * Notice :CVR String discriminate!
-	 * reference of http://www.microsoft.com/globaldev/reference/oslocversion.mspx
-	 * to see the Local ID
-	 */
-	trans = msn_transaction_new(cmdproc, "CVR",
-					"0x0409 winnt 5.1 i386 MSNMSGR 8.5.1302 BC01 %s",
-					 purple_account_get_username(account));
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-/**************************************************************************
- * Log out
- **************************************************************************/
-
-static void
-out_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	if (cmd->param_count == 0)
-		msn_session_set_error(cmdproc->session, -1, NULL);
-	else if (!g_ascii_strcasecmp(cmd->params[0], "OTH"))
-		msn_session_set_error(cmdproc->session, MSN_ERROR_SIGN_OTHER,
-							  NULL);
-	else if (!g_ascii_strcasecmp(cmd->params[0], "SSD"))
-		msn_session_set_error(cmdproc->session, MSN_ERROR_SERV_DOWN, NULL);
-}
-
-void
-msn_notification_close(MsnNotification *notification)
-{
-	MsnTransaction *trans;
-
-	g_return_if_fail(notification != NULL);
-
-	if (!notification->in_use)
-		return;
-
-	trans = msn_transaction_new(notification->cmdproc, "OUT", NULL);
-	msn_transaction_set_saveable(trans, FALSE);
-	msn_cmdproc_send_trans(notification->cmdproc, trans);
-
-	msn_notification_disconnect(notification);
-}
-
-/**************************************************************************
- * Messages
- **************************************************************************/
-
-static void
-msg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
-			 size_t len)
-{
-	MsnMessage *msg;
-
-	msg = msn_message_new_from_cmd(cmdproc->session, cmd);
-
-	msn_message_parse_payload(msg, payload, len, MSG_LINE_DEM, MSG_BODY_DEM);
-	if (purple_debug_is_verbose())
-		msn_message_show_readable(msg, "Notification", TRUE);
-
-	msn_cmdproc_process_msg(cmdproc, msg);
-
-	msn_message_unref(msg);
-}
-
-static void
-msg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	purple_debug_info("msn", "Processing MSG... \n");
-
-	/* NOTE: cmd is not always cmdproc->last_cmd, sometimes cmd is a queued
-	 * command and we are processing it */
-	if (cmd->payload == NULL) {
-		cmdproc->last_cmd->payload_cb = msg_cmd_post;
-		cmd->payload_len = atoi(cmd->params[2]);
-	} else {
-		g_return_if_fail(cmd->payload_cb != NULL);
-
-#if 0 /* glib on win32 doesn't correctly support precision modifiers for a string */
-		purple_debug_info("msn", "MSG payload:{%.*s}\n", (guint)cmd->payload_len, cmd->payload);
-#endif
-		cmd->payload_cb(cmdproc, cmd, cmd->payload, cmd->payload_len);
-	}
-}
-
-/*send Message to Yahoo Messenger*/
-void
-msn_notification_send_uum(MsnSession *session, MsnMessage *msg)
-{
-	MsnCmdProc *cmdproc;
-	MsnTransaction *trans;
-	char *payload;
-	gsize payload_len;
-	int type;
-	MsnUser *user;
-	int network;
-
-	g_return_if_fail(msg != NULL);
-
-	cmdproc = session->notification->cmdproc;
-
-	payload = msn_message_gen_payload(msg, &payload_len);
-	type = msg->type;
-	user = msn_userlist_find_user(session->userlist, msg->remote_user);
-	if (user)
-		network = msn_user_get_network(user);
-	else
-		network = MSN_NETWORK_PASSPORT;
-
-	purple_debug_info("msn",
-		"send UUM, payload{%s}, strlen:%" G_GSIZE_FORMAT ", len:%" G_GSIZE_FORMAT "\n",
-		payload, strlen(payload), payload_len);
-
-	trans = msn_transaction_new(cmdproc, "UUM", "%s %d %d %" G_GSIZE_FORMAT,
-		msg->remote_user, network, type, payload_len);
-	msn_transaction_set_payload(trans, payload, strlen(payload));
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-/*Yahoo msg process*/
-static void
-ubm_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	purple_debug_info("msn", "Processing UBM... \n");
-
-	/* NOTE: cmd is not always cmdproc->last_cmd, sometimes cmd is a queued
-	 * command and we are processing it */
-	if (cmd->payload == NULL) {
-		cmdproc->last_cmd->payload_cb = msg_cmd_post;
-		cmd->payload_len = atoi(cmd->params[5]);
-	} else {
-		g_return_if_fail(cmd->payload_cb != NULL);
-
-		purple_debug_info("msn", "UBM payload:{%.*s}\n", (guint)(cmd->payload_len), cmd->payload);
-		msg_cmd_post(cmdproc, cmd, cmd->payload, cmd->payload_len);
-	}
-}
-
-/**************************************************************************
- * Challenges
- *  we use MD5 to caculate the Challenges
- **************************************************************************/
-static void
-chl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnTransaction *trans;
-	char buf[33];
-
-	msn_handle_chl(cmd->params[1], buf);
-	trans = msn_transaction_new(cmdproc, "QRY", "%s 32", MSNP15_WLM_PRODUCT_ID);
-
-	msn_transaction_set_payload(trans, buf, 32);
-
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-/**************************************************************************
- * Buddy Lists
- **************************************************************************/
-
-typedef struct MsnFqyCbData {
-	MsnFqyCb cb;
-	gpointer data;
-} MsnFqyCbData;
-
-/* add contact to xmlnode */
-static void
-msn_add_contact_xml(xmlnode *mlNode, const char *passport, MsnListOp list_op, MsnNetwork networkId)
-{
-	xmlnode *d_node,*c_node;
-	char **tokens;
-	const char *email,*domain;
-	char fmt_str[3];
-
-	g_return_if_fail(passport != NULL);
-
-	purple_debug_info("msn", "Passport: %s, type: %d\n", passport, networkId);
-	tokens = g_strsplit(passport, "@", 2);
-	email = tokens[0];
-	domain = tokens[1];
-
-	if (email == NULL || domain == NULL) {
-		purple_debug_error("msn", "Invalid passport (%s) specified to add to contact xml.\n", passport);
-		g_strfreev(tokens);
-		g_return_if_reached();
-	}
-
-	/*find a domain Node*/
-	for (d_node = xmlnode_get_child(mlNode, "d"); d_node;
-	     d_node = xmlnode_get_next_twin(d_node)) {
-		const char *attr = xmlnode_get_attrib(d_node,"n");
-		if (attr == NULL)
-			continue;
-		if (!strcmp(attr, domain))
-			break;
-	}
-
-	if (d_node == NULL) {
-		/*domain not found, create a new domain Node*/
-		purple_debug_info("msn", "Didn't find existing domain node, adding one.\n");
-		d_node = xmlnode_new("d");
-		xmlnode_set_attrib(d_node, "n", domain);
-		xmlnode_insert_child(mlNode, d_node);
-	}
-
-	/*create contact node*/
-	c_node = xmlnode_new("c");
-	xmlnode_set_attrib(c_node, "n", email);
-
-	if (list_op != 0) {
-		purple_debug_info("msn", "list_op: %d\n", list_op);
-		g_snprintf(fmt_str, sizeof(fmt_str), "%d", list_op);
-		xmlnode_set_attrib(c_node, "l", fmt_str);
-	}
-
-	if (networkId != MSN_NETWORK_UNKNOWN) {
-		g_snprintf(fmt_str, sizeof(fmt_str), "%d", networkId);
-		/*mobile*/
-		/*type_str = g_strdup_printf("4");*/
-		xmlnode_set_attrib(c_node, "t", fmt_str);
-	}
-
-	xmlnode_insert_child(d_node, c_node);
-
-	g_strfreev(tokens);
-}
-
-static void
-msn_notification_post_adl(MsnCmdProc *cmdproc, const char *payload, int payload_len)
-{
-	MsnTransaction *trans;
-	purple_debug_info("msn", "Sending ADL with payload: %s\n", payload);
-	trans = msn_transaction_new(cmdproc, "ADL", "%i", payload_len);
-	msn_transaction_set_payload(trans, payload, payload_len);
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-static void
-msn_notification_post_rml(MsnCmdProc *cmdproc, const char *payload, int payload_len)
-{
-	MsnTransaction *trans;
-	purple_debug_info("msn", "Sending RML with payload: %s\n", payload);
-	trans = msn_transaction_new(cmdproc, "RML", "%i", payload_len);
-	msn_transaction_set_payload(trans, payload, payload_len);
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-void
-msn_notification_send_fqy(MsnSession *session,
-                          const char *payload, int payload_len,
-                          MsnFqyCb cb,
-                          gpointer cb_data)
-{
-	MsnTransaction *trans;
-	MsnCmdProc *cmdproc;
-	MsnFqyCbData *data;
-
-	cmdproc = session->notification->cmdproc;
-
-	data = g_new(MsnFqyCbData, 1);
-	data->cb = cb;
-	data->data = cb_data;
-
-	trans = msn_transaction_new(cmdproc, "FQY", "%d", payload_len);
-	msn_transaction_set_payload(trans, payload, payload_len);
-	msn_transaction_set_data(trans, data);
-	msn_transaction_set_data_free(trans, g_free);
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-static void
-update_contact_network(MsnSession *session, const char *passport, MsnNetwork network, gpointer unused)
-{
-	MsnUser *user;
-
-	if (network == MSN_NETWORK_UNKNOWN)
-	{
-		purple_debug_warning("msn",
-		                     "Ignoring user %s about which server knows nothing.\n",
-		                     passport);
-		/* Decrement the count for unknown results so that we'll continue login.
-		   Also, need to finish the login process here as well, because ADL OK
-		   will not be called. */
-		if (purple_debug_is_verbose())
-			purple_debug_info("msn", "ADL/FQY count is %d\n", session->adl_fqy);
-		if (--session->adl_fqy == 0)
-			msn_session_finish_login(session);
-		return;
-	}
-
-	/* TODO: Also figure out how to update membership lists */
-	user = msn_userlist_find_user(session->userlist, passport);
-	if (user) {
-		xmlnode *adl_node;
-		char *payload;
-		int payload_len;
-
-		msn_user_set_network(user, network);
-
-		adl_node = xmlnode_new("ml");
-		xmlnode_set_attrib(adl_node, "l", "1");
-		msn_add_contact_xml(adl_node, passport,
-		                    user->list_op & MSN_LIST_OP_MASK, network);
-		payload = xmlnode_to_str(adl_node, &payload_len);
-		msn_notification_post_adl(session->notification->cmdproc, payload, payload_len);
-		g_free(payload);
-		xmlnode_free(adl_node);
-	} else {
-		purple_debug_error("msn",
-		                   "Got FQY update for unknown user %s on network %d.\n",
-		                   passport, network);
-	}
-}
-
-/*dump contact info to NS*/
-void
-msn_notification_dump_contact(MsnSession *session)
-{
-	MsnUser *user;
-	GList *l;
-	xmlnode *adl_node;
-	xmlnode *fqy_node;
-	char *payload;
-	int payload_len;
-	int adl_count = 0;
-	int fqy_count = 0;
-	PurpleConnection *pc;
-	const char *display_name;
-
-	adl_node = xmlnode_new("ml");
-	adl_node->child = NULL;
-	xmlnode_set_attrib(adl_node, "l", "1");
-	fqy_node = xmlnode_new("ml");
-
-	/*get the userlist*/
-	for (l = session->userlist->users; l != NULL; l = l->next) {
-		user = l->data;
-
-		/* skip RL & PL during initial dump */
-		if (!(user->list_op & MSN_LIST_OP_MASK))
-			continue;
-
-		if (user->passport && !strcmp(user->passport, "messenger@microsoft.com"))
-			continue;
-
-		if ((user->list_op & MSN_LIST_OP_MASK & ~MSN_LIST_FL_OP)
-		 == (MSN_LIST_AL_OP | MSN_LIST_BL_OP)) {
-			/* The server will complain if we send it a user on both the
-			   Allow and Block lists. So assume they're on the Block list
-			   and remove them from the Allow list in the membership lists to
-			   stop this from happening again. */
-			purple_debug_warning("msn",
-			                     "User %s is on both Allow and Block list; "
-			                     "removing from Allow list.\n",
-			                     user->passport);
-			msn_user_unset_op(user, MSN_LIST_AL_OP);
-		}
-
-		if (user->networkid != MSN_NETWORK_UNKNOWN) {
-			if ((user->list_op & (MSN_LIST_OP_MASK | MSN_LIST_PL_OP)) == MSN_LIST_FL_OP) {
-				purple_debug_warning("msn",
-				                     "User %s is on neither Allow nor Block list, "
-				                     "and not Pending addition; "
-				                     "adding to Allow list.\n",
-				                     user->passport);
-				msn_user_set_op(user, MSN_LIST_AL_OP);
-			}
-
-			msn_add_contact_xml(adl_node, user->passport,
-			                    user->list_op & MSN_LIST_OP_MASK,
-			                    user->networkid);
-
-			/* each ADL command may contain up to 150 contacts */
-			if (++adl_count % 150 == 0) {
-				payload = xmlnode_to_str(adl_node, &payload_len);
-
-				/* ADL's are returned all-together */
-				session->adl_fqy++;
-				if (purple_debug_is_verbose())
-					purple_debug_info("msn", "Posting ADL, count is %d\n",
-					                  session->adl_fqy);
-
-				msn_notification_post_adl(session->notification->cmdproc,
-					payload, payload_len);
-
-				g_free(payload);
-				xmlnode_free(adl_node);
-
-				adl_node = xmlnode_new("ml");
-				adl_node->child = NULL;
-				xmlnode_set_attrib(adl_node, "l", "1");
-			}
-		} else {
-			/* FQY's are returned one-at-a-time */
-			session->adl_fqy++;
-			if (purple_debug_is_verbose())
-				purple_debug_info("msn", "Adding FQY address, count is %d\n",
-				                  session->adl_fqy);
-
-			msn_add_contact_xml(fqy_node, user->passport, 0, user->networkid);
-
-			/* each FQY command may contain up to 150 contacts, probably */
-			if (++fqy_count % 150 == 0) {
-				payload = xmlnode_to_str(fqy_node, &payload_len);
-
-				msn_notification_send_fqy(session, payload, payload_len,
-				                          update_contact_network, NULL);
-
-				g_free(payload);
-				xmlnode_free(fqy_node);
-				fqy_node = xmlnode_new("ml");
-			}
-		}
-	}
-
-	/* Send the rest, or just an empty one to let the server set us online */
-	if (adl_count == 0 || adl_count % 150 != 0) {
-		payload = xmlnode_to_str(adl_node, &payload_len);
-
-		/* ADL's are returned all-together */
-		session->adl_fqy++;
-		if (purple_debug_is_verbose())
-			purple_debug_info("msn", "Posting ADL, count is %d\n",
-			                  session->adl_fqy);
-
-		msn_notification_post_adl(session->notification->cmdproc, payload, payload_len);
-
-		g_free(payload);
-	}
-
-	if (fqy_count % 150 != 0) {
-		payload = xmlnode_to_str(fqy_node, &payload_len);
-
-		msn_notification_send_fqy(session, payload, payload_len,
-		                          update_contact_network, NULL);
-
-		g_free(payload);
-	}
-
-	xmlnode_free(adl_node);
-	xmlnode_free(fqy_node);
-
-	msn_session_activate_login_timeout(session);
-
-	pc = purple_account_get_connection(session->account);
-	display_name = purple_connection_get_display_name(pc);
-	if (display_name
-	    && strcmp(display_name,
-		      purple_account_get_username(session->account))) {
-		msn_set_public_alias(pc, display_name, NULL, NULL);
-	}
-
-}
-
-static void
-blp_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-}
-
-static void
-adl_cmd_parse(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
-		                         size_t len)
-{
-	xmlnode *root, *domain_node;
-
-	purple_debug_misc("msn", "Parsing received ADL XML data\n");
-
-	g_return_if_fail(payload != NULL);
-
-	root = xmlnode_from_str(payload, (gssize) len);
-
-	if (root == NULL) {
-		purple_debug_info("msn", "Invalid XML in ADL!\n");
-		return;
-	}
-	for (domain_node = xmlnode_get_child(root, "d");
-	     domain_node;
-	     domain_node = xmlnode_get_next_twin(domain_node)) {
-		xmlnode *contact_node = NULL;
-
-		for (contact_node = xmlnode_get_child(domain_node, "c");
-		     contact_node;
-		     contact_node = xmlnode_get_next_twin(contact_node)) {
-			const gchar *list;
-			gint list_op = 0;
-
-			list = xmlnode_get_attrib(contact_node, "l");
-			if (list != NULL) {
-				list_op = atoi(list);
-			}
-
-			if (list_op & MSN_LIST_RL_OP) {
-				/* someone is adding us */
-				msn_get_contact_list(cmdproc->session, MSN_PS_PENDING_LIST, NULL);
-			}
-		}
-	}
-
-	xmlnode_free(root);
-}
-
-static void
-adl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnSession *session;
-
-	g_return_if_fail(cmdproc != NULL);
-	g_return_if_fail(cmdproc->session != NULL);
-	g_return_if_fail(cmdproc->last_cmd != NULL);
-	g_return_if_fail(cmd != NULL);
-
-	session = cmdproc->session;
-
-	if (!strcmp(cmd->params[1], "OK")) {
-		/* ADL ack */
-		if (purple_debug_is_verbose())
-			purple_debug_info("msn", "ADL ACK, count is %d\n",
-			                  session->adl_fqy);
-		if (--session->adl_fqy == 0)
-			msn_session_finish_login(session);
-	} else {
-		cmdproc->last_cmd->payload_cb = adl_cmd_parse;
-		cmd->payload_len = atoi(cmd->params[1]);
-	}
-
-	return;
-}
-
-static void
-adl_error_parse(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
-{
-	MsnSession *session;
-	PurpleAccount *account;
-	PurpleConnection *gc;
-	int error = GPOINTER_TO_INT(cmd->payload_cbdata);
-
-	session = cmdproc->session;
-	account = session->account;
-	gc = purple_account_get_connection(account);
-
-	if (error == 241) {
-		/* khc: some googling suggests that error 241 means the buddy is somehow
-		   in the local list, but not the server list, and that we should add
-		   those buddies to the addressbook. For now I will just notify the user
-		   about the raw payload, because I am lazy */
-		xmlnode *adl = xmlnode_from_str(payload, len);
-		GString *emails = g_string_new(NULL);
-
-		xmlnode *domain = xmlnode_get_child(adl, "d");
-		while (domain) {
-			const char *domain_str = xmlnode_get_attrib(domain, "n");
-			xmlnode *contact = xmlnode_get_child(domain, "c");
-			while (contact) {
-				g_string_append_printf(emails, "%s@%s\n",
-					xmlnode_get_attrib(contact, "n"), domain_str);
-				contact = xmlnode_get_next_twin(contact);
-			}
-			domain = xmlnode_get_next_twin(domain);
-		}
-
-		purple_notify_error(gc, NULL,
-			_("The following users are missing from your addressbook"),
-			emails->str);
-		g_string_free(emails, TRUE);
-		xmlnode_free(adl);
-	}
-	else
-	{
-		char *adl = g_strndup(payload, len);
-		char *reason = g_strdup_printf(_("Unknown error (%d): %s"),
-			error, adl);
-		g_free(adl);
-
-		purple_notify_error(gc, NULL, _("Unable to add user"), reason);
-		g_free(reason);
-	}
-}
-
-static void
-adl_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
-{
-	MsnSession *session;
-	PurpleAccount *account;
-	PurpleConnection *gc;
-	MsnCommand *cmd = cmdproc->last_cmd;
-
-	session = cmdproc->session;
-	account = session->account;
-	gc = purple_account_get_connection(account);
-
-	purple_debug_error("msn", "ADL error\n");
-	if (cmd->param_count > 1) {
-		cmd->payload_cb = adl_error_parse;
-		cmd->payload_len = atoi(cmd->params[1]);
-		cmd->payload_cbdata = GINT_TO_POINTER(error);
-	} else {
-		char *reason = g_strdup_printf(_("Unknown error (%d)"), error);
-		purple_notify_error(gc, NULL, _("Unable to add user"), reason);
-		g_free(reason);
-	}
-}
-
-static void
-rml_error_parse(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
-{
-	MsnSession *session;
-	PurpleAccount *account;
-	PurpleConnection *gc;
-	char *adl, *reason;
-	int error = GPOINTER_TO_INT(cmd->payload_cbdata);
-
-	session = cmdproc->session;
-	account = session->account;
-	gc = purple_account_get_connection(account);
-
-	adl = g_strndup(payload, len);
-	reason = g_strdup_printf(_("Unknown error (%d): %s"),
-		error, adl);
-	g_free(adl);
-
-	purple_notify_error(gc, NULL, _("Unable to remove user"), reason);
-	g_free(reason);
-}
-
-static void
-rml_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
-{
-	MsnSession *session;
-	PurpleAccount *account;
-	PurpleConnection *gc;
-	MsnCommand *cmd = cmdproc->last_cmd;
-
-	session = cmdproc->session;
-	account = session->account;
-	gc = purple_account_get_connection(account);
-
-	purple_debug_error("msn", "RML error\n");
-	if (cmd->param_count > 1) {
-		cmd->payload_cb = rml_error_parse;
-		cmd->payload_len = atoi(cmd->params[1]);
-		cmd->payload_cbdata = GINT_TO_POINTER(error);
-	} else {
-		char *reason = g_strdup_printf(_("Unknown error (%d)"), error);
-		purple_notify_error(gc, NULL, _("Unable to remove user"), reason);
-		g_free(reason);
-	}
-}
-
-static void
-fqy_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
-			 size_t len)
-{
-	MsnSession *session;
-	xmlnode *ml, *d, *c;
-	const char *domain;
-	const char *local;
-	const char *type;
-	char *passport;
-	MsnNetwork network = MSN_NETWORK_PASSPORT;
-
-	session = cmdproc->session;
-
-	/* FQY response:
-	    <ml><d n="domain.com"><c n="local-node" t="network" /></d></ml> */
-	ml = xmlnode_from_str(payload, len);
-	for (d = xmlnode_get_child(ml, "d");
-	     d != NULL;
-	     d = xmlnode_get_next_twin(d)) {
-		domain = xmlnode_get_attrib(d, "n");
-		for (c = xmlnode_get_child(d, "c");
-		     c != NULL;
-		     c = xmlnode_get_next_twin(c)) {
-			local = xmlnode_get_attrib(c, "n");
-			type = xmlnode_get_attrib(c, "t");
-
-			passport = g_strdup_printf("%s@%s", local, domain);
-
-			if (g_ascii_isdigit(cmd->command[0]))
-				network = MSN_NETWORK_UNKNOWN;
-			else if (type != NULL)
-				network = (MsnNetwork)strtoul(type, NULL, 10);
-
-			purple_debug_info("msn", "FQY response says %s is from network %d\n",
-			                  passport, network);
-			if (cmd->trans->data) {
-				MsnFqyCbData *fqy_data = cmd->trans->data;
-				fqy_data->cb(session, passport, network, fqy_data->data);
-				/* Don't free fqy_data yet since the server responds to FQY multiple times.
-				   It will be freed when cmd->trans is freed. */
-			}
-
-			g_free(passport);
-		}
-	}
-
-	xmlnode_free(ml);
-}
-
-static void
-fqy_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
-{
-	MsnCommand *cmd = cmdproc->last_cmd;
-
-	purple_debug_warning("msn", "FQY error %d\n", error);
-	if (cmd->param_count > 1) {
-		cmd->payload_cb = fqy_cmd_post;
-		cmd->payload_len = atoi(cmd->params[1]);
-		cmd->payload_cbdata = GINT_TO_POINTER(error);
-	}
-#if 0
-	/* If the server didn't send us a corresponding email address for this
-	   FQY error, it's probably going to disconnect us. So it isn't necessary
-	   to tell the handler about it. */
-	else if (trans->data)
-		((MsnFqyCb)trans->data)(session, NULL, MSN_NETWORK_UNKNOWN, NULL);
-#endif
-}
-
-static void
-fqy_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	purple_debug_info("msn", "Process FQY\n");
-	cmdproc->last_cmd->payload_cb = fqy_cmd_post;
-	cmd->payload_len = atoi(cmd->params[1]);
-}
-
-static void
-rml_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
-			 size_t len)
-{
-	if (payload != NULL)
-		purple_debug_info("msn", "Received RML:\n%s\n", payload);
-}
-
-static void
-rml_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	purple_debug_info("msn", "Process RML\n");
-	cmd->payload_len = atoi(cmd->params[1]);
-	cmdproc->last_cmd->payload_cb = rml_cmd_post;
-}
-
-static void
-qng_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	/* TODO: Call PNG after the timeout specified. */
-}
-
-
-static void
-fln_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnUser *user;
-	char *passport;
-	int networkid;
-
-	/* Tell libpurple that the user has signed off */
-	msn_parse_user(cmd->params[0], &passport, &networkid);
-	user = msn_userlist_find_user(cmdproc->session->userlist, passport);
-	msn_user_set_state(user, NULL);
-	msn_user_update(user);
-
-	g_free(passport);
-}
-
-static void
-iln_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnSession *session;
-	MsnUser *user;
-	MsnObject *msnobj = NULL;
-	unsigned long clientid, extcaps;
-	char *extcap_str;
-	int networkid = 0;
-	const char *state, *passport;
-	char *friendly;
-
-	session = cmdproc->session;
-
-	state    = cmd->params[1];
-	passport = cmd->params[2];
-
-	user = msn_userlist_find_user(session->userlist, passport);
-	if (user == NULL)
-		/* Where'd this come from? */
-		return;
-
-	if (cmd->param_count == 8) {
-		/* Yahoo! Buddy, looks like */
-		networkid = atoi(cmd->params[3]);
-		friendly = g_strdup(purple_url_decode(cmd->params[4]));
-		clientid = strtoul(cmd->params[5], &extcap_str, 10);
-		if (extcap_str && *extcap_str)
-			extcaps = strtoul(extcap_str+1, NULL, 10);
-		else
-			extcaps = 0;
-
-		/* cmd->params[7] seems to be a URL to a Yahoo! icon:
-				https://sec.yimg.com/i/us/nt/b/purpley.1.0.png
-		   ... and it's purple, HAH!
-		*/
-	} else if (cmd->param_count == 7) {
-		/* MSNP14+ with Display Picture object */
-		networkid = atoi(cmd->params[3]);
-		friendly = g_strdup(purple_url_decode(cmd->params[4]));
-		clientid = strtoul(cmd->params[5], &extcap_str, 10);
-		if (extcap_str && *extcap_str)
-			extcaps = strtoul(extcap_str+1, NULL, 10);
-		else
-			extcaps = 0;
-		msnobj = msn_object_new_from_string(purple_url_decode(cmd->params[6]));
-	} else if (cmd->param_count == 6) {
-		/* Yes, this is 5. The friendly name could start with a number,
-		   but the display picture object can't... */
-		if (isdigit(cmd->params[5][0])) {
-			/* MSNP14 without Display Picture object */
-			networkid = atoi(cmd->params[3]);
-			friendly = g_strdup(purple_url_decode(cmd->params[4]));
-			clientid = strtoul(cmd->params[5], &extcap_str, 10);
-			if (extcap_str && *extcap_str)
-				extcaps = strtoul(extcap_str+1, NULL, 10);
-			else
-				extcaps = 0;
-		} else {
-			/* MSNP8+ with Display Picture object */
-			friendly = g_strdup(purple_url_decode(cmd->params[3]));
-			clientid = strtoul(cmd->params[4], &extcap_str, 10);
-			if (extcap_str && *extcap_str)
-				extcaps = strtoul(extcap_str+1, NULL, 10);
-			else
-				extcaps = 0;
-			msnobj = msn_object_new_from_string(purple_url_decode(cmd->params[5]));
-		}
-	} else if (cmd->param_count == 5) {
-		/* MSNP8+ without Display Picture object */
-		friendly = g_strdup(purple_url_decode(cmd->params[3]));
-		clientid = strtoul(cmd->params[4], &extcap_str, 10);
-		if (extcap_str && *extcap_str)
-			extcaps = strtoul(extcap_str+1, NULL, 10);
-		else
-			extcaps = 0;
-	} else {
-		purple_debug_warning("msn", "Received ILN with unknown number of parameters.\n");
-		return;
-	}
-
-	if (msn_user_set_friendly_name(user, friendly)) {
-		msn_update_contact(session, passport, MSN_UPDATE_DISPLAY, friendly);
-	}
-	g_free(friendly);
-
-	msn_user_set_object(user, msnobj);
-
-	user->mobile = (clientid & MSN_CAP_MOBILE_ON) || (user->extinfo && user->extinfo->phone_mobile && user->extinfo->phone_mobile[0] == '+');
-	msn_user_set_clientid(user, clientid);
-	msn_user_set_extcaps(user, extcaps);
-	msn_user_set_network(user, networkid);
-
-	msn_user_set_state(user, state);
-	msn_user_update(user);
-}
-
-static void
-ipg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
-{
-	PurpleConnection *gc;
-	MsnUserList *userlist;
-	const char *who = NULL;
-	char *text = NULL;
-	const char *id = NULL;
-	xmlnode *payloadNode, *from, *msg, *textNode;
-
-	purple_debug_misc("msn", "Incoming Page: {%s}\n", payload);
-
-	userlist = cmdproc->session->userlist;
-	gc = purple_account_get_connection(cmdproc->session->account);
-
-	/* payload looks like this:
-	   <?xml version="1.0"?>
-	   <NOTIFICATION id="0" siteid="111100400" siteurl="http://mobile.msn.com/">
-	     <TO name="passport@example.com">
-	       <VIA agent="mobile"/>
-	     </TO>
-	     <FROM name="tel:+XXXXXXXXXXX"/>
-		 <MSG pri="1" id="1">
-		   <CAT Id="110110001"/>
-		   <ACTION url="2wayIM.asp"/>
-		   <SUBSCR url="2wayIM.asp"/>
-		   <BODY lcid="1033">
-		     <TEXT>Message was here</TEXT>
-		   </BODY>
-		 </MSG>
-	   </NOTIFICATION>
-	*/
-
-	/* This is the payload if your message was too long:
-	   <NOTIFICATION id="TrID" siteid="111100400" siteurl="http://mobile.msn.com/">
-	     <TO name="passport@example.com">
-	       <VIA agent="mobile"/>
-	     </TO>
-	     <FROM name="tel:+XXXXXXXXXXX"/>
-	     <MSG pri="1" id="407">
-	       <CAT Id="110110001"/>
-	       <ACTION url="2wayIM.asp"/>
-	       <SUBSCR url="2wayIM.asp"/>
-	       <BODY lcid="1033">
-	         <TEXT></TEXT>
-	       </BODY>
-	     </MSG>
-	   </NOTIFICATION>
-	*/
-
-	payloadNode = xmlnode_from_str(payload, len);
-	if (!payloadNode)
-		return;
-
-	if (!(from = xmlnode_get_child(payloadNode, "FROM")) ||
-		!(msg = xmlnode_get_child(payloadNode, "MSG")) ||
-		!(textNode = xmlnode_get_child(msg, "BODY/TEXT"))) {
-		xmlnode_free(payloadNode);
-		return;
-	}
-
-	who = xmlnode_get_attrib(from, "name");
-	if (!who) return;
-
-	text = xmlnode_get_data(textNode);
-
-	/* Match number to user's mobile number, FROM is a phone number if the
-	   other side page you using your phone number */
-	if (!strncmp(who, "tel:+", 5)) {
-		MsnUser *user =
-			msn_userlist_find_user_with_mobile_phone(userlist, who + 4);
-
-		if (user && user->passport)
-			who = user->passport;
-	}
-
-	id = xmlnode_get_attrib(msg, "id");
-
-	if (id && strcmp(id, "1")) {
-		PurpleConversation *conv
-			= purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY,
-			                                        who, gc->account);
-		if (conv != NULL) {
-			const char *error;
-			if (!strcmp(id, "407"))
-				error = _("Mobile message was not sent because it was too long.");
-			else
-				error = _("Mobile message was not sent because an unknown error occurred.");
-
-			purple_conversation_write(conv, NULL, error,
-			                          PURPLE_MESSAGE_ERROR, time(NULL));
-
-			if ((id = xmlnode_get_attrib(payloadNode, "id")) != NULL) {
-				unsigned int trId = atol(id);
-				MsnTransaction *trans;
-
-				trans = msn_history_find(cmdproc->history, trId);
-				if (trans) {
-					MsnMessage *msg = (MsnMessage *)trans->data;
-
-					if (msg) {
-						char *body_str = msn_message_to_string(msg);
-						char *body_enc = g_markup_escape_text(body_str, -1);
-
-						purple_conversation_write(conv, NULL, body_enc,
-					                          	PURPLE_MESSAGE_RAW, time(NULL));
-
-						g_free(body_str);
-						g_free(body_enc);
-						msn_message_unref(msg);
-						trans->data = NULL;
-					}
-				}
-			}
-		}
-	} else {
-		serv_got_im(gc, who, text, 0, time(NULL));
-	}
-
-	g_free(text);
-	xmlnode_free(payloadNode);
-}
-
-static void
-ipg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	cmd->payload_len = atoi(cmd->params[0]);
-	cmdproc->last_cmd->payload_cb = ipg_cmd_post;
-}
-
-static void
-nln_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnSession *session;
-	MsnUser *user;
-	MsnObject *msnobj;
-	unsigned long clientid, extcaps;
-	char *extcap_str;
-	char *passport;
-	int networkid;
-	const char *state, *friendly;
-
-	session = cmdproc->session;
-
-	state = cmd->params[0];
-	msn_parse_user(cmd->params[1], &passport, &networkid);
-	friendly = purple_url_decode(cmd->params[2]);
-
-	user = msn_userlist_find_user(session->userlist, passport);
-	if (user == NULL) return;
-
-	if (msn_user_set_friendly_name(user, friendly) && user != session->user)
-	{
-		msn_update_contact(session, passport, MSN_UPDATE_DISPLAY, friendly);
-	}
-
-	if (cmd->param_count == 5)
-	{
-		msnobj = msn_object_new_from_string(purple_url_decode(cmd->params[4]));
-		msn_user_set_object(user, msnobj);
-	}
-	else
-	{
-		msn_user_set_object(user, NULL);
-	}
-
-	clientid = strtoul(cmd->params[3], &extcap_str, 10);
-	if (extcap_str && *extcap_str)
-		extcaps = strtoul(extcap_str+1, NULL, 10);
-	else
-		extcaps = 0;
-
-	user->mobile = (clientid & MSN_CAP_MOBILE_ON) || (user->extinfo && user->extinfo->phone_mobile && user->extinfo->phone_mobile[0] == '+');
-
-	msn_user_set_clientid(user, clientid);
-	msn_user_set_extcaps(user, extcaps);
-	msn_user_set_network(user, networkid);
-
-	msn_user_set_state(user, state);
-	msn_user_update(user);
-
-	g_free(passport);
-}
-
-#if 0
-static void
-chg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	char *state = cmd->params[1];
-	int state_id = 0;
-
-	if (!strcmp(state, "NLN"))
-		state_id = MSN_ONLINE;
-	else if (!strcmp(state, "BSY"))
-		state_id = MSN_BUSY;
-	else if (!strcmp(state, "IDL"))
-		state_id = MSN_IDLE;
-	else if (!strcmp(state, "BRB"))
-		state_id = MSN_BRB;
-	else if (!strcmp(state, "AWY"))
-		state_id = MSN_AWAY;
-	else if (!strcmp(state, "PHN"))
-		state_id = MSN_PHONE;
-	else if (!strcmp(state, "LUN"))
-		state_id = MSN_LUNCH;
-	else if (!strcmp(state, "HDN"))
-		state_id = MSN_HIDDEN;
-
-	cmdproc->session->state = state_id;
-}
-#endif
-
-
-static void
-not_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
-{
-#if 0
-	MSN_SET_PARAMS("NOT %d\r\n%s", cmdproc->servconn->payload, payload);
-	purple_debug_misc("msn", "Notification: {%s}\n", payload);
-#endif
-}
-
-static void
-not_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	cmd->payload_len = atoi(cmd->params[0]);
-	cmdproc->last_cmd->payload_cb = not_cmd_post;
-}
-
-static void
-prp_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnSession *session = cmdproc->session;
-	const char *type, *value;
-
-	g_return_if_fail(cmd->param_count >= 3);
-
-	type = cmd->params[2];
-
-	if (cmd->param_count == 4)
-	{
-		value = cmd->params[3];
-		if (!strcmp(type, "PHH"))
-			msn_user_set_home_phone(session->user, purple_url_decode(value));
-		else if (!strcmp(type, "PHW"))
-			msn_user_set_work_phone(session->user, purple_url_decode(value));
-		else if (!strcmp(type, "PHM"))
-			msn_user_set_mobile_phone(session->user, purple_url_decode(value));
-	}
-	else
-	{
-		if (!strcmp(type, "PHH"))
-			msn_user_set_home_phone(session->user, NULL);
-		else if (!strcmp(type, "PHW"))
-			msn_user_set_work_phone(session->user, NULL);
-		else if (!strcmp(type, "PHM"))
-			msn_user_set_mobile_phone(session->user, NULL);
-	}
-}
-
-/**************************************************************************
- * Misc commands
- **************************************************************************/
-
-static void
-url_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnSession *session;
-	PurpleConnection *gc;
-	PurpleAccount *account;
-	const char *rru;
-	const char *url;
-	PurpleCipherContext *cipher;
-	gchar creds[33];
-	char *buf;
-
-	gulong tmp_timestamp;
-
-	session = cmdproc->session;
-	account = session->account;
-	gc = account->gc;
-
-	rru = cmd->params[1];
-	url = cmd->params[2];
-
-	session->passport_info.mail_timestamp = time(NULL);
-	tmp_timestamp = session->passport_info.mail_timestamp - session->passport_info.sl;
-
-	buf = g_strdup_printf("%s%lu%s",
-	                      session->passport_info.mspauth ? session->passport_info.mspauth : "BOGUS",
-	                      tmp_timestamp,
-	                      purple_connection_get_password(gc));
-
-	cipher = purple_cipher_context_new_by_name("md5", NULL);
-	purple_cipher_context_append(cipher, (const guchar *)buf, strlen(buf));
-	purple_cipher_context_digest_to_str(cipher, sizeof(creds), creds, NULL);
-	purple_cipher_context_destroy(cipher);
-	g_free(buf);
-
-	g_free(session->passport_info.mail_url);
-	session->passport_info.mail_url =
-		g_strdup_printf("%s&auth=%s&creds=%s&sl=%ld&username=%s&mode=ttl&sid=%s&id=2&rru=%s&svc=mail&js=yes",
-		                url,
-		                session->passport_info.mspauth ? purple_url_encode(session->passport_info.mspauth) : "BOGUS",
-		                creds,
-		                tmp_timestamp,
-		                msn_user_get_passport(session->user),
-		                session->passport_info.sid,
-		                rru);
-
-	/* The user wants to check his or her email */
-	if (cmd->trans && cmd->trans->data)
-		purple_notify_uri(purple_account_get_connection(account), session->passport_info.mail_url);
-}
-/**************************************************************************
- * Switchboards
- **************************************************************************/
-
-static void
-rng_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnSession *session;
-	MsnSwitchBoard *swboard;
-	const char *session_id;
-	char *host;
-	int port;
-
-	session = cmdproc->session;
-	session_id = cmd->params[0];
-
-	msn_parse_socket(cmd->params[1], &host, &port);
-
-	if (session->http_method)
-		port = 80;
-
-	swboard = msn_switchboard_new(session);
-
-	msn_switchboard_set_invited(swboard, TRUE);
-	msn_switchboard_set_session_id(swboard, session_id);
-	msn_switchboard_set_auth_key(swboard, cmd->params[3]);
-	swboard->im_user = g_strdup(cmd->params[4]);
-	/* msn_switchboard_add_user(swboard, cmd->params[4]); */
-
-	if (!msn_switchboard_connect(swboard, host, port))
-		msn_switchboard_destroy(swboard);
-
-	g_free(host);
-}
-
-static void
-xfr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	char *host;
-	int port;
-
-	if (strcmp(cmd->params[1], "SB") && strcmp(cmd->params[1], "NS"))
-	{
-		/* Maybe we can have a generic bad command error. */
-		purple_debug_error("msn", "Bad XFR command (%s)\n", cmd->params[1]);
-		return;
-	}
-
-	msn_parse_socket(cmd->params[2], &host, &port);
-
-	if (!strcmp(cmd->params[1], "SB"))
-	{
-		purple_debug_error("msn", "This shouldn't be handled here.\n");
-	}
-	else if (!strcmp(cmd->params[1], "NS"))
-	{
-		MsnSession *session;
-
-		session = cmdproc->session;
-
-		msn_session_set_login_step(session, MSN_LOGIN_STEP_TRANSFER);
-
-		msn_notification_connect(session->notification, host, port);
-	}
-
-	g_free(host);
-}
-
-static void
-gcf_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
-			 size_t len)
-{
-/* QuLogic: Disabled until confirmed correct. */
-#if 0
-	xmlnode *root;
-	xmlnode *policy;
-
-	g_return_if_fail(cmd->payload != NULL);
-
-	if ( (root = xmlnode_from_str(cmd->payload, cmd->payload_len)) == NULL)
-	{
-		purple_debug_error("msn", "Unable to parse GCF payload into a XML tree\n");
-		return;
-	}
-
-
-	g_free(cmdproc->session->blocked_text);
-	cmdproc->session->blocked_text = NULL;
-
-	/* We need a get_child with attrib... */
-	policy = xmlnode_get_child(root, "Policy");
-	while (policy) {
-		if (g_str_equal(xmlnode_get_attrib(policy, "type"), "SHIELDS"))
-			break;
-		policy = xmlnode_get_next_twin(policy);
-	}
-
-	if (policy) {
-		GString *blocked = g_string_new(NULL);
-		xmlnode *imtext = xmlnode_get_child(policy,
-		                                    "config/block/regexp/imtext");
-		while (imtext) {
-			const char *value = xmlnode_get_attrib(imtext, "value");
-			g_string_append_printf(blocked, "%s<br/>\n",
-			                       purple_base64_decode(value, NULL));
-			imtext = xmlnode_get_next_twin(imtext);
-		}
-
-		cmdproc->session->blocked_text = g_string_free(blocked, FALSE);
-	}
-
-	xmlnode_free(root);
-#endif
-}
-
-static void
-gcf_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	purple_debug_info("msn", "Processing GCF command\n");
-
-	cmdproc->last_cmd->payload_cb  = gcf_cmd_post;
-	cmd->payload_len = atoi(cmd->params[1]);
-}
-
-static void
-sbs_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	purple_debug_info("msn", "Processing SBS... \n");
-	/*get the payload content*/
-}
-
-static void
-parse_user_endpoints(MsnUser *user, xmlnode *payloadNode)
-{
-	MsnSession *session;
-	xmlnode *epNode, *capsNode;
-	MsnUserEndpoint data;
-	const char *id;
-	char *caps, *tmp;
-	gboolean is_me;
-
-	purple_debug_info("msn", "Get EndpointData\n");
-
-	session = user->userlist->session;
-	is_me = (user == session->user);
-
-	msn_user_clear_endpoints(user);
-	for (epNode = xmlnode_get_child(payloadNode, "EndpointData");
-	     epNode;
-	     epNode = xmlnode_get_next_twin(epNode)) {
-		id = xmlnode_get_attrib(epNode, "id");
-		capsNode = xmlnode_get_child(epNode, "Capabilities");
-
-		/* Disconnect others, if MPOP is disabled */
-		if (is_me
-		 && !session->enable_mpop
-		 && strncasecmp(id + 1, session->guid, 36) != 0) {
-			purple_debug_info("msn", "Disconnecting Endpoint %s\n", id);
-
-			tmp = g_strdup_printf("%s;%s", user->passport, id);
-			msn_notification_send_uun(session, tmp, MSN_UNIFIED_NOTIFICATION_MPOP, "goawyplzthxbye");
-			g_free(tmp);
-		} else {
-			if (capsNode != NULL) {
-				caps = xmlnode_get_data(capsNode);
-
-				data.clientid = strtoul(caps, &tmp, 10);
-				if (tmp && *tmp)
-					data.extcaps = strtoul(tmp + 1, NULL, 10);
-				else
-					data.extcaps = 0;
-
-				g_free(caps);
-			} else {
-				data.clientid = 0;
-				data.extcaps = 0;
-			}
-
-			msn_user_set_endpoint_data(user, id, &data);
-		}
-	}
-
-	if (is_me && session->enable_mpop) {
-		for (epNode = xmlnode_get_child(payloadNode, "PrivateEndpointData");
-		     epNode;
-		     epNode = xmlnode_get_next_twin(epNode)) {
-			MsnUserEndpoint *ep;
-			xmlnode *nameNode, *clientNode;
-
-			/*	<PrivateEndpointData id='{GUID}'>
-					<EpName>Endpoint Name</EpName>
-					<Idle>true/false</Idle>
-					<ClientType>1</ClientType>
-					<State>NLN</State>
-				</PrivateEndpointData>
-			*/
-			id = xmlnode_get_attrib(epNode, "id");
-			ep = msn_user_get_endpoint_data(user, id);
-
-			if (ep != NULL) {
-				nameNode = xmlnode_get_child(epNode, "EpName");
-				if (nameNode != NULL) {
-					g_free(ep->name);
-					ep->name = xmlnode_get_data(nameNode);
-				}
-
-				clientNode = xmlnode_get_child(epNode, "ClientType");
-				if (clientNode != NULL) {
-					tmp = xmlnode_get_data(clientNode);
-					ep->type = strtoul(tmp, NULL, 10);
-					g_free(tmp);
-				}
-			}
-		}
-	}
-}
-
-static void parse_currentmedia(MsnUser *user, const char *cmedia)
-{
-	char **cmedia_array;
-	int strings = 0;
-
-	if (!cmedia || cmedia[0] == '\0') {
-		purple_debug_info("msn", "No currentmedia string\n");
-		return;
-	}
-
-	purple_debug_info("msn", "Parsing currentmedia string: \"%s\"\n", cmedia);
-
-	cmedia_array = g_strsplit(cmedia, "\\0", 0);
-
-	/*
-	 * 0: Application
-	 * 1: 'Music'/'Games'/'Office'
-	 * 2: '1' if enabled, '0' if not
-	 * 3: Format (eg. {0} by {1})
-	 * 4: Title
-	 * If 'Music':
-	 *  5: Artist
-	 *  6: Album
-	 *  7: ?
-	 */
-	strings  = g_strv_length(cmedia_array);
-
-	if (strings >= 4 && !strcmp(cmedia_array[2], "1")) {
-		if (user->extinfo == NULL)
-			user->extinfo = g_new0(MsnUserExtendedInfo, 1);
-		else {
-			g_free(user->extinfo->media_album);
-			g_free(user->extinfo->media_artist);
-			g_free(user->extinfo->media_title);
-		}
-
-		if (!strcmp(cmedia_array[1], "Music"))
-			user->extinfo->media_type = CURRENT_MEDIA_MUSIC;
-		else if (!strcmp(cmedia_array[1], "Games"))
-			user->extinfo->media_type = CURRENT_MEDIA_GAMES;
-		else if (!strcmp(cmedia_array[1], "Office"))
-			user->extinfo->media_type = CURRENT_MEDIA_OFFICE;
-		else
-			user->extinfo->media_type = CURRENT_MEDIA_UNKNOWN;
-
-		user->extinfo->media_title = g_strdup(cmedia_array[strings == 4 ? 3 : 4]);
-		user->extinfo->media_artist = strings > 5 ? g_strdup(cmedia_array[5]) : NULL;
-		user->extinfo->media_album = strings > 6 ? g_strdup(cmedia_array[6]) : NULL;
-	}
-
-	g_strfreev(cmedia_array);
-}
-
-/*
- * Get the UBX's PSM info
- * Post it to the User status
- * Thanks for Chris <ukdrizzle@yahoo.co.uk>'s code
- */
-static void
-ubx_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
-			 size_t len)
-{
-	MsnSession *session;
-	MsnUser *user;
-	char *passport;
-	int network;
-	xmlnode *payloadNode;
-	char *psm_str, *str;
-
-	session = cmdproc->session;
-
-	msn_parse_user(cmd->params[0], &passport, &network);
-	user = msn_userlist_find_user(session->userlist, passport);
-
-	if (user == NULL) {
-		str = g_strndup(payload, len);
-		purple_debug_info("msn", "unknown user %s, payload is %s\n",
-			passport, str);
-		g_free(passport);
-		g_free(str);
-		return;
-	}
-
-	g_free(passport);
-
-	/* Free any existing media info for this user */
-	if (user->extinfo) {
-		g_free(user->extinfo->media_album);
-		g_free(user->extinfo->media_artist);
-		g_free(user->extinfo->media_title);
-		user->extinfo->media_album = NULL;
-		user->extinfo->media_artist = NULL;
-		user->extinfo->media_title = NULL;
-		user->extinfo->media_type = CURRENT_MEDIA_UNKNOWN;
-	}
-
-	if (len != 0) {
-		payloadNode = xmlnode_from_str(payload, len);
-		if (!payloadNode) {
-			purple_debug_error("msn", "UBX XML parse Error!\n");
-
-			msn_user_set_statusline(user, NULL);
-
-			msn_user_update(user);
-			return;
-		}
-
-		psm_str = msn_get_psm(payloadNode);
-		msn_user_set_statusline(user, psm_str);
-		g_free(psm_str);
-
-		str = msn_get_currentmedia(payloadNode);
-		parse_currentmedia(user, str);
-		g_free(str);
-
-		parse_user_endpoints(user, payloadNode);
-
-		xmlnode_free(payloadNode);
-
-	} else {
-		msn_user_set_statusline(user, NULL);
-	}
-
-	msn_user_update(user);
-}
-
-static void
-ubx_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	purple_debug_misc("msn", "UBX received.\n");
-	cmdproc->last_cmd->payload_cb  = ubx_cmd_post;
-	cmd->payload_len = atoi(cmd->params[1]);
-}
-
-static void
-uux_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
-			 size_t len)
-{
-	/* Do Nothing, right now. */
-	if (payload != NULL)
-		purple_debug_info("msn", "UUX payload:\n%s\n", payload);
-}
-
-static void
-uux_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	purple_debug_misc("msn", "UUX received.\n");
-	cmdproc->last_cmd->payload_cb = uux_cmd_post;
-	cmd->payload_len = atoi(cmd->params[1]);
-}
-
-void
-msn_notification_send_uux(MsnSession *session, const char *payload)
-{
-	MsnTransaction *trans;
-	MsnCmdProc *cmdproc;
-	size_t len = strlen(payload);
-
-	cmdproc = session->notification->cmdproc;
-	purple_debug_misc("msn", "Sending UUX command with payload: %s\n", payload);
-	trans = msn_transaction_new(cmdproc, "UUX", "%" G_GSIZE_FORMAT, len);
-	msn_transaction_set_payload(trans, payload, len);
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-void msn_notification_send_uux_endpointdata(MsnSession *session)
-{
-	xmlnode *epDataNode;
-	xmlnode *capNode;
-	char *caps;
-	char *payload;
-	int length;
-
-	epDataNode = xmlnode_new("EndpointData");
-
-	capNode = xmlnode_new_child(epDataNode, "Capabilities");
-	caps = g_strdup_printf("%d:%02d", MSN_CLIENT_ID_CAPABILITIES, MSN_CLIENT_ID_EXT_CAPS);
-	xmlnode_insert_data(capNode, caps, -1);
-	g_free(caps);
-
-	payload = xmlnode_to_str(epDataNode, &length);
-
-	msn_notification_send_uux(session, payload);
-
-	xmlnode_free(epDataNode);
-	g_free(payload);
-}
-
-void msn_notification_send_uux_private_endpointdata(MsnSession *session)
-{
-	xmlnode *private;
-	const char *name;
-	xmlnode *epname;
-	xmlnode *idle;
-	GHashTable *ui_info;
-	const gchar *ui_type;
-	xmlnode *client_type;
-	xmlnode *state;
-	char *payload;
-	int length;
-
-	private = xmlnode_new("PrivateEndpointData");
-
-	name = purple_account_get_string(session->account, "endpoint-name", NULL);
-	epname = xmlnode_new_child(private, "EpName");
-	xmlnode_insert_data(epname, name, -1);
-
-	idle = xmlnode_new_child(private, "Idle");
-	xmlnode_insert_data(idle, "false", -1);
-
-	/* ClientType info (from amsn guys):
-		0: None
-		1: Computer
-		2: Website
-		3: Mobile / none
-		4: Xbox / phone /mobile
-		9: MsnGroup
-		32: Email member, currently Yahoo!
-	*/
-	client_type = xmlnode_new_child(private, "ClientType");
-	ui_info = purple_core_get_ui_info();
-	ui_type = ui_info ? g_hash_table_lookup(ui_info, "client_type") : NULL;
-	if (ui_type) {
-		if (strcmp(ui_type, "pc") == 0)
-			xmlnode_insert_data(client_type, "1", -1);
-		else if (strcmp(ui_type, "web") == 0)
-			xmlnode_insert_data(client_type, "2", -1);
-		else if (strcmp(ui_type, "phone") == 0)
-			xmlnode_insert_data(client_type, "3", -1);
-		else if (strcmp(ui_type, "handheld") == 0)
-			xmlnode_insert_data(client_type, "3", -1);
-		else
-			xmlnode_insert_data(client_type, "1", -1);
-	}
-	else
-		xmlnode_insert_data(client_type, "1", -1);
-
-	state = xmlnode_new_child(private, "State");
-	xmlnode_insert_data(state, msn_state_get_text(msn_state_from_account(session->account)), -1);
-
-	payload = xmlnode_to_str(private, &length);
-
-	msn_notification_send_uux(session, payload);
-
-	xmlnode_free(private);
-	g_free(payload);
-}
-
-static void
-ubn_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
-			 size_t len)
-{
-	/* Do Nothing, right now. */
-	if (payload != NULL)
-		purple_debug_info("msn", "UBN payload:\n%s\n", payload);
-}
-
-static void
-ubn_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	purple_debug_misc("msn", "UBN received from %s.\n", cmd->params[0]);
-	cmdproc->last_cmd->payload_cb  = ubn_cmd_post;
-	cmd->payload_len = atoi(cmd->params[2]);
-}
-
-static void
-uun_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
-			 size_t len)
-{
-	/* Do Nothing, right now. */
-	if (payload != NULL)
-		purple_debug_info("msn", "UUN payload:\n%s\n", payload);
-}
-
-static void
-uun_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	if (strcmp(cmd->params[1], "OK") != 0) {
-		purple_debug_misc("msn", "UUN received.\n");
-		cmdproc->last_cmd->payload_cb = uun_cmd_post;
-		cmd->payload_len = atoi(cmd->params[1]);
-	}
-	else
-		purple_debug_misc("msn", "UUN OK received.\n");
-}
-
-void
-msn_notification_send_uun(MsnSession *session, const char *user,
-                          MsnUnifiedNotificationType type, const char *payload)
-{
-	MsnTransaction *trans;
-	MsnCmdProc *cmdproc;
-	size_t len = strlen(payload);
-
-	cmdproc = session->notification->cmdproc;
-	purple_debug_misc("msn", "Sending UUN command %d to %s with payload: %s\n",
-	                  type, user, payload);
-	trans = msn_transaction_new(cmdproc, "UUN", "%s %d %" G_GSIZE_FORMAT,
-	                            user, type, len);
-	msn_transaction_set_payload(trans, payload, len);
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-void
-msn_notification_send_circle_auth(MsnSession *session, const char *ticket)
-{
-	MsnTransaction *trans;
-	MsnCmdProc *cmdproc;
-	char *encoded;
-
-	cmdproc = session->notification->cmdproc;
-
-	encoded = purple_base64_encode((guchar *)ticket, strlen(ticket));
-	trans = msn_transaction_new(cmdproc, "USR", "SHA A %s", encoded);
-	msn_cmdproc_send_trans(cmdproc, trans);
-
-	g_free(encoded);
-}
-
-/**************************************************************************
- * Message Types
- **************************************************************************/
-
-static void
-profile_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	MsnSession *session;
-	const char *value;
-#ifdef MSN_PARTIAL_LISTS
-	const char *clLastChange;
-#endif
-
-	session = cmdproc->session;
-
-	if (strcmp(msg->remote_user, "Hotmail"))
-		/* This isn't an official message. */
-		return;
-
-	if ((value = msn_message_get_header_value(msg, "sid")) != NULL)
-	{
-		g_free(session->passport_info.sid);
-		session->passport_info.sid = g_strdup(value);
-	}
-
-	if ((value = msn_message_get_header_value(msg, "MSPAuth")) != NULL)
-	{
-		g_free(session->passport_info.mspauth);
-		session->passport_info.mspauth = g_strdup(value);
-	}
-
-	if ((value = msn_message_get_header_value(msg, "ClientIP")) != NULL)
-	{
-		g_free(session->passport_info.client_ip);
-		session->passport_info.client_ip = g_strdup(value);
-	}
-
-	if ((value = msn_message_get_header_value(msg, "ClientPort")) != NULL)
-	{
-		session->passport_info.client_port = ntohs(atoi(value));
-	}
-
-	if ((value = msn_message_get_header_value(msg, "LoginTime")) != NULL)
-		session->passport_info.sl = atol(value);
-
-	if ((value = msn_message_get_header_value(msg, "EmailEnabled")) != NULL)
-		session->passport_info.email_enabled = (gboolean)atol(value);
-
-#ifdef MSN_PARTIAL_LISTS
-	/*starting retrieve the contact list*/
-	clLastChange = purple_account_get_string(session->account, "CLLastChange", NULL);
-	/* msn_userlist_load defeats all attempts at trying to detect blist sync issues */
-	msn_userlist_load(session);
-	msn_get_contact_list(session, MSN_PS_INITIAL, clLastChange);
-#else
-	/* always get the full list? */
-	msn_get_contact_list(session, MSN_PS_INITIAL, NULL);
-#endif
-}
-
-static void
-initial_email_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	MsnSession *session;
-	PurpleConnection *gc;
-	GHashTable *table;
-	const char *unread;
-
-	session = cmdproc->session;
-	gc = session->account->gc;
-
-	if (strcmp(msg->remote_user, "Hotmail"))
-		/* This isn't an official message. */
-		return;
-
-	if (session->passport_info.mail_url == NULL)
-	{
-		MsnTransaction *trans;
-		trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
-		msn_transaction_queue_cmd(trans, msg->cmd);
-
-		msn_cmdproc_send_trans(cmdproc, trans);
-
-		return;
-	}
-
-	if (!purple_account_get_check_mail(session->account))
-		return;
-
-	table = msn_message_get_hashtable_from_body(msg);
-
-	unread = g_hash_table_lookup(table, "Inbox-Unread");
-
-	if (unread != NULL)
-	{
-		int count = atoi(unread);
-
-		if (count > 0)
-		{
-			const char *passports[2] = { msn_user_get_passport(session->user) };
-			const char *urls[2] = { session->passport_info.mail_url };
-
-			purple_notify_emails(gc, count, FALSE, NULL, NULL,
-							   passports, urls, NULL, NULL);
-		}
-	}
-
-	g_hash_table_destroy(table);
-}
-
-/*offline Message notification process*/
-static void
-initial_mdata_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	MsnSession *session;
-	PurpleConnection *gc;
-	GHashTable *table;
-	const char *mdata, *unread;
-
-	session = cmdproc->session;
-	gc = session->account->gc;
-
-	if (strcmp(msg->remote_user, "Hotmail"))
-		/* This isn't an official message. */
-		return;
-
-	table = msn_message_get_hashtable_from_body(msg);
-
-	mdata = g_hash_table_lookup(table, "Mail-Data");
-
-	if (mdata != NULL)
-		msn_parse_oim_msg(session->oim, mdata);
-
-	if (g_hash_table_lookup(table, "Inbox-URL") == NULL)
-	{
-		g_hash_table_destroy(table);
-		return;
-	}
-
-	if (session->passport_info.mail_url == NULL)
-	{
-		MsnTransaction *trans;
-		trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
-		msn_transaction_queue_cmd(trans, msg->cmd);
-
-		msn_cmdproc_send_trans(cmdproc, trans);
-
-		g_hash_table_destroy(table);
-		return;
-	}
-
-	if (!purple_account_get_check_mail(session->account))
-	{
-		g_hash_table_destroy(table);
-		return;
-	}
-
-	unread = g_hash_table_lookup(table, "Inbox-Unread");
-
-	if (unread != NULL)
-	{
-		int count = atoi(unread);
-
-		if (count > 0)
-		{
-			const char *passports[2] = { msn_user_get_passport(session->user) };
-			const char *urls[2] = { session->passport_info.mail_url };
-
-			purple_notify_emails(gc, count, FALSE, NULL, NULL,
-							   passports, urls, NULL, NULL);
-		}
-	}
-
-	g_hash_table_destroy(table);
-}
-
-/*offline Message Notification*/
-static void
-delete_oim_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	purple_debug_misc("msn", "Delete OIM message.\n");
-}
-
-static void
-email_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	MsnSession *session;
-	PurpleConnection *gc;
-	GHashTable *table;
-	char *from, *subject, *tmp;
-
-	session = cmdproc->session;
-	gc = session->account->gc;
-
-	if (strcmp(msg->remote_user, "Hotmail"))
-		/* This isn't an official message. */
-		return;
-
-	if (session->passport_info.mail_url == NULL)
-	{
-		MsnTransaction *trans;
-		trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
-		msn_transaction_queue_cmd(trans, msg->cmd);
-
-		msn_cmdproc_send_trans(cmdproc, trans);
-
-		return;
-	}
-
-	if (!purple_account_get_check_mail(session->account))
-		return;
-
-	table = msn_message_get_hashtable_from_body(msg);
-
-	from = subject = NULL;
-
-	tmp = g_hash_table_lookup(table, "From");
-	if (tmp != NULL)
-		from = purple_mime_decode_field(tmp);
-
-	tmp = g_hash_table_lookup(table, "Subject");
-	if (tmp != NULL)
-		subject = purple_mime_decode_field(tmp);
-
-	purple_notify_email(gc,
-					  (subject != NULL ? subject : ""),
-					  (from != NULL ?  from : ""),
-					  msn_user_get_passport(session->user),
-					  session->passport_info.mail_url, NULL, NULL);
-
-	g_free(from);
-	g_free(subject);
-
-	g_hash_table_destroy(table);
-}
-
-static void
-system_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	GHashTable *table;
-	const char *type_s;
-
-	if (strcmp(msg->remote_user, "Hotmail"))
-		/* This isn't an official message. */
-		return;
-
-	table = msn_message_get_hashtable_from_body(msg);
-
-	if ((type_s = g_hash_table_lookup(table, "Type")) != NULL)
-	{
-		int type = atoi(type_s);
-		char buf[MSN_BUF_LEN] = "";
-		int minutes;
-
-		switch (type)
-		{
-			case 1:
-				minutes = atoi(g_hash_table_lookup(table, "Arg1"));
-				g_snprintf(buf, sizeof(buf), dngettext(PACKAGE,
-							"The MSN server will shut down for maintenance "
-							"in %d minute. You will automatically be "
-							"signed out at that time.  Please finish any "
-							"conversations in progress.\n\nAfter the "
-							"maintenance has been completed, you will be "
-							"able to successfully sign in.",
-							"The MSN server will shut down for maintenance "
-							"in %d minutes. You will automatically be "
-							"signed out at that time.  Please finish any "
-							"conversations in progress.\n\nAfter the "
-							"maintenance has been completed, you will be "
-							"able to successfully sign in.", minutes),
-						minutes);
-			default:
-				break;
-		}
-
-		if (*buf != '\0')
-			purple_notify_info(cmdproc->session->account->gc, NULL, buf, NULL);
-	}
-
-	g_hash_table_destroy(table);
-}
-
-/**************************************************************************
- * Dispatch server list management
- **************************************************************************/
-typedef struct MsnAddRemoveListData {
-	MsnCmdProc *cmdproc;
-	MsnUser *user;
-	MsnListOp list_op;
-	gboolean add;
-} MsnAddRemoveListData;
-
-static void
-modify_unknown_buddy_on_list(MsnSession *session, const char *passport,
-                             MsnNetwork network, gpointer data)
-{
-	MsnAddRemoveListData *addrem = data;
-	MsnCmdProc *cmdproc;
-	xmlnode *node;
-	char *payload;
-	int payload_len;
-
-	cmdproc = addrem->cmdproc;
-
-	/* Update user first */
-	msn_user_set_network(addrem->user, network);
-
-	node = xmlnode_new("ml");
-	node->child = NULL;
-
-	msn_add_contact_xml(node, passport, addrem->list_op, network);
-
-	payload = xmlnode_to_str(node, &payload_len);
-	xmlnode_free(node);
-
-	if (addrem->add)
-		msn_notification_post_adl(cmdproc, payload, payload_len);
-	else
-		msn_notification_post_rml(cmdproc, payload, payload_len);
-
-	g_free(payload);
-	g_free(addrem);
-}
-
-void
-msn_notification_add_buddy_to_list(MsnNotification *notification, MsnListId list_id,
-							  MsnUser *user)
-{
-	MsnAddRemoveListData *addrem;
-	MsnCmdProc *cmdproc;
-	MsnListOp list_op = 1 << list_id;
-	xmlnode *adl_node;
-	char *payload;
-	int payload_len;
-
-	cmdproc = notification->servconn->cmdproc;
-
-	adl_node = xmlnode_new("ml");
-	adl_node->child = NULL;
-
-	msn_add_contact_xml(adl_node, user->passport, list_op, user->networkid);
-
-	payload = xmlnode_to_str(adl_node, &payload_len);
-	xmlnode_free(adl_node);
-
-	if (user->networkid != MSN_NETWORK_UNKNOWN) {
-		msn_notification_post_adl(cmdproc, payload, payload_len);
-
-	} else {
-		addrem = g_new(MsnAddRemoveListData, 1);
-		addrem->cmdproc = cmdproc;
-		addrem->user = user;
-		addrem->list_op = list_op;
-		addrem->add = TRUE;
-
-		msn_notification_send_fqy(notification->session, payload, payload_len,
-		                          modify_unknown_buddy_on_list, addrem);
-	}
-
-	g_free(payload);
-}
-
-void
-msn_notification_rem_buddy_from_list(MsnNotification *notification, MsnListId list_id,
-						   MsnUser *user)
-{
-	MsnAddRemoveListData *addrem;
-	MsnCmdProc *cmdproc;
-	MsnListOp list_op = 1 << list_id;
-	xmlnode *rml_node;
-	char *payload;
-	int payload_len;
-
-	cmdproc = notification->servconn->cmdproc;
-
-	rml_node = xmlnode_new("ml");
-	rml_node->child = NULL;
-
-	msn_add_contact_xml(rml_node, user->passport, list_op, user->networkid);
-
-	payload = xmlnode_to_str(rml_node, &payload_len);
-	xmlnode_free(rml_node);
-
-	if (user->networkid != MSN_NETWORK_UNKNOWN) {
-		msn_notification_post_rml(cmdproc, payload, payload_len);
-
-	} else {
-		addrem = g_new(MsnAddRemoveListData, 1);
-		addrem->cmdproc = cmdproc;
-		addrem->user = user;
-		addrem->list_op = list_op;
-		addrem->add = FALSE;
-
-		msn_notification_send_fqy(notification->session, payload, payload_len,
-		                          modify_unknown_buddy_on_list, addrem);
-	}
-
-	g_free(payload);
-}
-
-/**************************************************************************
- * Init
- **************************************************************************/
-void
-msn_notification_init(void)
-{
-	cbs_table = msn_table_new();
-
-	/* Synchronous */
-	msn_table_add_cmd(cbs_table, "CHG", "CHG", NULL);
-	msn_table_add_cmd(cbs_table, "CHG", "ILN", iln_cmd);
-	msn_table_add_cmd(cbs_table, "ADL", "ILN", iln_cmd);
-	msn_table_add_cmd(cbs_table, "USR", "USR", usr_cmd);
-	msn_table_add_cmd(cbs_table, "USR", "XFR", xfr_cmd);
-	msn_table_add_cmd(cbs_table, "USR", "GCF", gcf_cmd);
-	msn_table_add_cmd(cbs_table, "CVR", "CVR", cvr_cmd);
-	msn_table_add_cmd(cbs_table, "VER", "VER", ver_cmd);
-	msn_table_add_cmd(cbs_table, "PRP", "PRP", prp_cmd);
-	msn_table_add_cmd(cbs_table, "BLP", "BLP", blp_cmd);
-	msn_table_add_cmd(cbs_table, "XFR", "XFR", xfr_cmd);
-
-	/* Asynchronous */
-	msn_table_add_cmd(cbs_table, NULL, "IPG", ipg_cmd);
-	msn_table_add_cmd(cbs_table, NULL, "MSG", msg_cmd);
-	msn_table_add_cmd(cbs_table, NULL, "UBM", ubm_cmd);
-	msn_table_add_cmd(cbs_table, NULL, "GCF", gcf_cmd);
-	msn_table_add_cmd(cbs_table, NULL, "SBS", sbs_cmd);
-	msn_table_add_cmd(cbs_table, NULL, "NOT", not_cmd);
-
-	msn_table_add_cmd(cbs_table, NULL, "CHL", chl_cmd);
-	msn_table_add_cmd(cbs_table, NULL, "RML", rml_cmd);
-	msn_table_add_cmd(cbs_table, NULL, "ADL", adl_cmd);
-	msn_table_add_cmd(cbs_table, NULL, "FQY", fqy_cmd);
-
-	msn_table_add_cmd(cbs_table, NULL, "QRY", NULL);
-	msn_table_add_cmd(cbs_table, NULL, "QNG", qng_cmd);
-	msn_table_add_cmd(cbs_table, NULL, "FLN", fln_cmd);
-	msn_table_add_cmd(cbs_table, NULL, "NLN", nln_cmd);
-	msn_table_add_cmd(cbs_table, NULL, "ILN", iln_cmd);
-	msn_table_add_cmd(cbs_table, NULL, "OUT", out_cmd);
-	msn_table_add_cmd(cbs_table, NULL, "RNG", rng_cmd);
-
-	msn_table_add_cmd(cbs_table, NULL, "UBX", ubx_cmd);
-	msn_table_add_cmd(cbs_table, NULL, "UUX", uux_cmd);
-
-	msn_table_add_cmd(cbs_table, NULL, "UBN", ubn_cmd);
-	msn_table_add_cmd(cbs_table, NULL, "UUN", uun_cmd);
-
-	msn_table_add_cmd(cbs_table, NULL, "URL", url_cmd);
-
-	msn_table_add_cmd(cbs_table, "fallback", "XFR", xfr_cmd);
-
-	msn_table_add_error(cbs_table, "ADL", adl_error);
-	msn_table_add_error(cbs_table, "RML", rml_error);
-	msn_table_add_error(cbs_table, "FQY", fqy_error);
-	msn_table_add_error(cbs_table, "USR", usr_error);
-
-	msn_table_add_msg_type(cbs_table,
-						   "text/x-msmsgsprofile",
-						   profile_msg);
-	/*initial OIM notification*/
-	msn_table_add_msg_type(cbs_table,
-							"text/x-msmsgsinitialmdatanotification",
-							initial_mdata_msg);
-	/*OIM notification when user online*/
-	msn_table_add_msg_type(cbs_table,
-							"text/x-msmsgsoimnotification",
-							initial_mdata_msg);
-	msn_table_add_msg_type(cbs_table,
-						   "text/x-msmsgsinitialemailnotification",
-						   initial_email_msg);
-	msn_table_add_msg_type(cbs_table,
-						   "text/x-msmsgsemailnotification",
-						   email_msg);
-	/*delete an offline Message notification*/
-	msn_table_add_msg_type(cbs_table,
-							"text/x-msmsgsactivemailnotification",
-						   delete_oim_msg);
-	msn_table_add_msg_type(cbs_table,
-						   "application/x-msmsgssystemmessage",
-						   system_msg);
-	/* generic message handlers */
-	msn_table_add_msg_type(cbs_table, "text/plain",
-						   msn_plain_msg);
-	msn_table_add_msg_type(cbs_table, "text/x-msmsgscontrol",
-						   msn_control_msg);
-	msn_table_add_msg_type(cbs_table, "text/x-msnmsgr-datacast",
-						   msn_datacast_msg);
-}
-
-void
-msn_notification_end(void)
-{
-	msn_table_destroy(cbs_table);
-}
-
--- a/libpurple/protocols/msn/notification.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/**
- * @file notification.h Notification server functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_NOTIFICATION_H
-#define MSN_NOTIFICATION_H
-
-typedef struct _MsnNotification MsnNotification;
-
-/* MSN protocol challenge info */
-
-/* MSNP18 challenge: WLM Version 2009 (Build 14.0.8089.726) */
-#define MSNP18_WLM_PRODUCT_KEY "C1BX{V4W}Q3*10SM"
-#define MSNP18_WLM_PRODUCT_ID "PROD0120PW!CCV9@"
-
-/* MSNP15 challenge: WLM 8.5.1288.816 */
-#define MSNP15_WLM_PRODUCT_KEY "ILTXC!4IXB5FB*PX"
-#define MSNP15_WLM_PRODUCT_ID "PROD0119GSJUC$18"
-
-/* MSNP13 challenge */
-#define MSNP13_WLM_PRODUCT_KEY	"O4BG@C7BWLYQX?5G"
-#define MSNP13_WLM_PRODUCT_ID	"PROD01065C%ZFN6F"
-
-#define MSNP10_PRODUCT_KEY		"VT6PX?UQTM4WM%YR"
-#define MSNP10_PRODUCT_ID		"PROD0038W!61ZTF9"
-
-#include "cmdproc.h"
-#include "msg.h"
-#include "session.h"
-#include "servconn.h"
-#include "state.h"
-#include "user.h"
-#include "userlist.h"
-
-struct _MsnNotification
-{
-	MsnSession *session;
-
-	/**
-	 * This is a convenience pointer that always points to
-	 * servconn->cmdproc
-	 */
-	MsnCmdProc *cmdproc;
-	MsnServConn *servconn;
-
-	gboolean in_use;
-};
-
-typedef void (*MsnFqyCb)(MsnSession *session, const char *passport, MsnNetwork network, gpointer data);
-
-/* Type used for msn_notification_send_uun */
-typedef enum {
-	MSN_UNIFIED_NOTIFICATION_SHARED_FOLDERS = 1,
-	MSN_UNIFIED_NOTIFICATION_UNKNOWN1 = 2,
-	MSN_UNIFIED_NOTIFICATION_P2P = 3,
-	MSN_UNIFIED_NOTIFICATION_MPOP = 4
-
-} MsnUnifiedNotificationType;
-
-void msn_notification_end(void);
-void msn_notification_init(void);
-
-void msn_notification_add_buddy_to_list(MsnNotification *notification,
-					MsnListId list_id, MsnUser *user);
-void msn_notification_rem_buddy_from_list(MsnNotification *notification,
-					  MsnListId list_id, MsnUser *user);
-
-void msn_notification_send_fqy(MsnSession *session,
-                               const char *payload, int payload_len,
-                               MsnFqyCb cb, gpointer cb_data);
-
-MsnNotification *msn_notification_new(MsnSession *session);
-void msn_notification_destroy(MsnNotification *notification);
-gboolean msn_notification_connect(MsnNotification *notification,
-				  const char *host, int port);
-void msn_notification_disconnect(MsnNotification *notification);
-void msn_notification_dump_contact(MsnSession *session);
-
-void msn_notification_send_uum(MsnSession *session, MsnMessage *msg);
-
-void msn_notification_send_uux(MsnSession *session, const char *payload);
-
-void msn_notification_send_uux_endpointdata(MsnSession *session);
-
-void msn_notification_send_uux_private_endpointdata(MsnSession *session);
-
-void msn_notification_send_uun(MsnSession *session,
-                               const char *user,
-                               MsnUnifiedNotificationType type,
-                               const char *payload);
-
-void msn_notification_send_circle_auth(MsnSession *session, const char *ticket);
-
-/**
- * Closes a notification.
- *
- * It's first closed, and then disconnected.
- *
- * @param notification The notification object to close.
- */
-void msn_notification_close(MsnNotification *notification);
-
-void msn_got_login_params(MsnSession *session, const char *ticket, const char *response);
-
-#endif /* MSN_NOTIFICATION_H */
--- a/libpurple/protocols/msn/object.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,459 +0,0 @@
-/**
- * @file object.c MSNObject API
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "msn.h"
-#include "object.h"
-#include "debug.h"
-/* Sha1 stuff */
-#include "cipher.h"
-/* Base64 stuff */
-#include "util.h"
-
-#define GET_STRING_TAG(field, id) \
-	if ((tag = strstr(str, id "=\"")) != NULL) \
-	{ \
-		tag += strlen(id "=\""); \
-		c = strchr(tag, '"'); \
-		if (c != NULL) \
-		{ \
-			if (obj->field != NULL) \
-				g_free(obj->field); \
-			obj->field = g_strndup(tag, c - tag); \
-		} \
-	}
-
-#define GET_INT_TAG(field, id) \
-	if ((tag = strstr(str, id "=\"")) != NULL) \
-	{ \
-		char buf[16]; \
-		size_t offset; \
-		tag += strlen(id "=\""); \
-		c = strchr(tag, '"'); \
-		if (c != NULL) \
-		{ \
-			memset(buf, 0, sizeof(buf)); \
-			offset = c - tag; \
-			if (offset >= sizeof(buf)) \
-				offset = sizeof(buf) - 1; \
-			strncpy(buf, tag, offset); \
-			obj->field = atoi(buf); \
-		} \
-	}
-
-static GList *local_objs;
-
-MsnObject *
-msn_object_new(void)
-{
-	MsnObject *obj;
-
-	obj = g_new0(MsnObject, 1);
-
-	msn_object_set_type(obj, MSN_OBJECT_UNKNOWN);
-	msn_object_set_friendly(obj, "AAA=");
-
-	return obj;
-}
-
-MsnObject *
-msn_object_new_from_string(const char *str)
-{
-	MsnObject *obj;
-	char *tag, *c;
-
-	g_return_val_if_fail(str != NULL, NULL);
-
-	if (strncmp(str, "<msnobj ", 8))
-		return NULL;
-
-	obj = msn_object_new();
-
-	GET_STRING_TAG(creator,  "Creator");
-	GET_INT_TAG(size,        "Size");
-	GET_INT_TAG(type,        "Type");
-	GET_STRING_TAG(location, "Location");
-	GET_STRING_TAG(friendly, "Friendly");
-	GET_STRING_TAG(sha1d,    "SHA1D");
-	GET_STRING_TAG(sha1c,    "SHA1C");
-	GET_STRING_TAG(url,      "Url");
-	GET_STRING_TAG(url1,     "Url1");
-
-	/* If we are missing any of the required elements then discard the object */
-	if (obj->creator == NULL || obj->size == 0 || obj->type == 0
-	 || obj->sha1d == NULL) {
-		purple_debug_error("msn", "Discarding invalid msnobj: '%s'\n", str);
-		msn_object_destroy(obj);
-		return NULL;
-	}
-
-	if (obj->location == NULL || obj->friendly == NULL) {
-		/* Location/friendly are required for non-buddyicon objects */
-		if (obj->type != MSN_OBJECT_USERTILE) {
-			purple_debug_error("msn", "Discarding invalid msnobj: '%s'\n", str);
-			msn_object_destroy(obj);
-			return NULL;
-		/* Buddy icon object can contain Url/Url1 instead */
-		} else if (obj->url == NULL || obj->url1 == NULL) {
-			purple_debug_error("msn", "Discarding invalid msnobj: '%s'\n", str);
-			msn_object_destroy(obj);
-			return NULL;
-		}
-	}
-
-	return obj;
-}
-
-MsnObject*
-msn_object_new_from_image(PurpleStoredImage *img, const char *location,
-		const char *creator, MsnObjectType type)
-{
-	MsnObject *msnobj;
-
-	PurpleCipherContext *ctx;
-	char *buf;
-	gconstpointer data;
-	size_t size;
-	char *base64;
-	unsigned char digest[20];
-
-	msnobj = NULL;
-
-	if (img == NULL)
-		return msnobj;
-
-	size = purple_imgstore_get_size(img);
-	data = purple_imgstore_get_data(img);
-
-	/* New object */
-	msnobj = msn_object_new();
-	msn_object_set_local(msnobj);
-	msn_object_set_type(msnobj, type);
-	msn_object_set_location(msnobj, location);
-	msn_object_set_creator(msnobj, creator);
-
-	msn_object_set_image(msnobj, img);
-
-	/* Compute the SHA1D field. */
-	memset(digest, 0, sizeof(digest));
-
-	ctx = purple_cipher_context_new_by_name("sha1", NULL);
-	purple_cipher_context_append(ctx, data, size);
-	purple_cipher_context_digest(ctx, sizeof(digest), digest, NULL);
-
-	base64 = purple_base64_encode(digest, sizeof(digest));
-	msn_object_set_sha1d(msnobj, base64);
-	g_free(base64);
-
-	msn_object_set_size(msnobj, size);
-
-	/* Compute the SHA1C field. */
-	buf = g_strdup_printf(
-		"Creator%sSize%dType%dLocation%sFriendly%sSHA1D%s",
-		msn_object_get_creator(msnobj),
-		msn_object_get_size(msnobj),
-		msn_object_get_type(msnobj),
-		msn_object_get_location(msnobj),
-		msn_object_get_friendly(msnobj),
-		msn_object_get_sha1d(msnobj));
-
-	memset(digest, 0, sizeof(digest));
-
-	purple_cipher_context_reset(ctx, NULL);
-	purple_cipher_context_append(ctx, (const guchar *)buf, strlen(buf));
-	purple_cipher_context_digest(ctx, sizeof(digest), digest, NULL);
-	purple_cipher_context_destroy(ctx);
-	g_free(buf);
-
-	base64 = purple_base64_encode(digest, sizeof(digest));
-	msn_object_set_sha1c(msnobj, base64);
-	g_free(base64);
-
-	return msnobj;
-}
-
-void
-msn_object_destroy(MsnObject *obj)
-{
-	g_return_if_fail(obj != NULL);
-
-	g_free(obj->creator);
-	g_free(obj->location);
-	g_free(obj->friendly);
-	g_free(obj->sha1d);
-	g_free(obj->sha1c);
-	g_free(obj->url);
-	g_free(obj->url1);
-
-	purple_imgstore_unref(obj->img);
-
-	if (obj->local)
-		local_objs = g_list_remove(local_objs, obj);
-
-	g_free(obj);
-}
-
-char *
-msn_object_to_string(const MsnObject *obj)
-{
-	char *str;
-	const char *sha1c;
-
-	g_return_val_if_fail(obj != NULL, NULL);
-
-	sha1c = msn_object_get_sha1c(obj);
-
-	str = g_strdup_printf("<msnobj Creator=\"%s\" Size=\"%d\" Type=\"%d\" "
-						  "Location=\"%s\" Friendly=\"%s\" SHA1D=\"%s\""
-						  "%s%s%s/>",
-						  msn_object_get_creator(obj),
-						  msn_object_get_size(obj),
-						  msn_object_get_type(obj),
-						  msn_object_get_location(obj),
-						  msn_object_get_friendly(obj),
-						  msn_object_get_sha1d(obj),
-						  sha1c ? " SHA1C=\"" : "",
-						  sha1c ? sha1c : "",
-						  sha1c ? "\"" : "");
-
-	return str;
-}
-
-void
-msn_object_set_creator(MsnObject *obj, const char *creator)
-{
-	g_return_if_fail(obj != NULL);
-
-	g_free(obj->creator);
-	obj->creator = g_strdup(creator);
-}
-
-void
-msn_object_set_size(MsnObject *obj, int size)
-{
-	g_return_if_fail(obj != NULL);
-
-	obj->size = size;
-}
-
-void
-msn_object_set_type(MsnObject *obj, MsnObjectType type)
-{
-	g_return_if_fail(obj != NULL);
-
-	obj->type = type;
-}
-
-void
-msn_object_set_location(MsnObject *obj, const char *location)
-{
-	g_return_if_fail(obj != NULL);
-
-	g_free(obj->location);
-	obj->location = g_strdup(location);
-}
-
-void
-msn_object_set_friendly(MsnObject *obj, const char *friendly)
-{
-	g_return_if_fail(obj != NULL);
-
-	g_free(obj->friendly);
-	obj->friendly = g_strdup(friendly);
-}
-
-void
-msn_object_set_sha1d(MsnObject *obj, const char *sha1d)
-{
-	g_return_if_fail(obj != NULL);
-
-	g_free(obj->sha1d);
-	obj->sha1d = g_strdup(sha1d);
-}
-
-void
-msn_object_set_sha1c(MsnObject *obj, const char *sha1c)
-{
-	g_return_if_fail(obj != NULL);
-
-	g_free(obj->sha1c);
-	obj->sha1c = g_strdup(sha1c);
-}
-
-void
-msn_object_set_url(MsnObject *obj, const char *url)
-{
-	g_return_if_fail(obj != NULL);
-
-	g_free(obj->url);
-	obj->url = g_strdup(url);
-}
-
-void
-msn_object_set_url1(MsnObject *obj, const char *url)
-{
-	g_return_if_fail(obj != NULL);
-
-	g_free(obj->url1);
-	obj->url1 = g_strdup(url);
-}
-
-const char *
-msn_object_get_creator(const MsnObject *obj)
-{
-	g_return_val_if_fail(obj != NULL, NULL);
-
-	return obj->creator;
-}
-
-int
-msn_object_get_size(const MsnObject *obj)
-{
-	g_return_val_if_fail(obj != NULL, 0);
-
-	return obj->size;
-}
-
-MsnObjectType
-msn_object_get_type(const MsnObject *obj)
-{
-	g_return_val_if_fail(obj != NULL, MSN_OBJECT_UNKNOWN);
-
-	return obj->type;
-}
-
-const char *
-msn_object_get_location(const MsnObject *obj)
-{
-	g_return_val_if_fail(obj != NULL, NULL);
-
-	return obj->location;
-}
-
-const char *
-msn_object_get_friendly(const MsnObject *obj)
-{
-	g_return_val_if_fail(obj != NULL, NULL);
-
-	return obj->friendly;
-}
-
-const char *
-msn_object_get_sha1d(const MsnObject *obj)
-{
-	g_return_val_if_fail(obj != NULL, NULL);
-
-	return obj->sha1d;
-}
-
-const char *
-msn_object_get_sha1c(const MsnObject *obj)
-{
-	g_return_val_if_fail(obj != NULL, NULL);
-
-	return obj->sha1c;
-}
-
-const char *
-msn_object_get_sha1(const MsnObject *obj)
-{
-	g_return_val_if_fail(obj != NULL, NULL);
-
-	if(obj->sha1c != NULL) {
-		return obj->sha1c;
-	} else {
-		return obj->sha1d;
-	}
-}
-
-const char *
-msn_object_get_url(const MsnObject *obj)
-{
-	g_return_val_if_fail(obj != NULL, NULL);
-
-	return obj->url;
-}
-
-const char *
-msn_object_get_url1(const MsnObject *obj)
-{
-	g_return_val_if_fail(obj != NULL, NULL);
-
-	return obj->url1;
-}
-
-MsnObject *
-msn_object_find_local(const char *sha1)
-{
-	GList *l;
-
-	g_return_val_if_fail(sha1 != NULL, NULL);
-
-	for (l = local_objs; l != NULL; l = l->next)
-	{
-		MsnObject *local_obj = l->data;
-
-		if (!strcmp(msn_object_get_sha1(local_obj), sha1))
-			return local_obj;
-	}
-
-	return NULL;
-
-}
-
-void
-msn_object_set_local(MsnObject *obj)
-{
-	g_return_if_fail(obj != NULL);
-
-	obj->local = TRUE;
-
-	local_objs = g_list_append(local_objs, obj);
-}
-
-void
-msn_object_set_image(MsnObject *obj, PurpleStoredImage *img)
-{
-	g_return_if_fail(obj != NULL);
-	g_return_if_fail(img != NULL);
-
-	/* obj->local = TRUE; */
-
-	purple_imgstore_unref(obj->img);
-	obj->img = purple_imgstore_ref(img);
-}
-
-PurpleStoredImage *
-msn_object_get_image(const MsnObject *obj)
-{
-	MsnObject *local_obj;
-
-	g_return_val_if_fail(obj != NULL, NULL);
-
-	local_obj = msn_object_find_local(msn_object_get_sha1(obj));
-
-	if (local_obj != NULL)
-		return local_obj->img;
-
-	return NULL;
-}
--- a/libpurple/protocols/msn/object.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,276 +0,0 @@
-/**
- * @file object.h MSNObject API
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_OBJECT_H
-#define MSN_OBJECT_H
-
-typedef enum
-{
-	MSN_OBJECT_UNKNOWN    = -1, /**< Unknown object        */
-	MSN_OBJECT_RESERVED1  =  1, /**< Reserved              */
-	MSN_OBJECT_EMOTICON   =  2, /**< Custom Emoticon       */
-	MSN_OBJECT_USERTILE   =  3, /**< UserTile (buddy icon) */
-	MSN_OBJECT_RESERVED2  =  4, /**< Reserved              */
-	MSN_OBJECT_BACKGROUND =  5  /**< Background            */
-} MsnObjectType;
-
-#include "internal.h"
-
-#include "imgstore.h"
-
-typedef struct
-{
-	gboolean local;
-
-	char *creator;
-	int size;
-	MsnObjectType type;
-	PurpleStoredImage *img;
-	char *location;
-	char *friendly;
-	char *sha1d;
-	char *sha1c;
-	char *url;
-	char *url1;
-} MsnObject;
-
-/**
- * Creates a MsnObject structure.
- *
- * @return A new MsnObject structure.
- */
-MsnObject *msn_object_new(void);
-
-/**
- * Creates a MsnObject structure from a string.
- *
- * @param str The string.
- *
- * @return The new MsnObject structure.
- */
-MsnObject *msn_object_new_from_string(const char *str);
-
-/**
- * Creates a MsnObject structure from a stored image
- *
- * @param img		The image associated to object
- * @param location	The object location as stored in MsnObject
- * @param creator	The creator of the object
- * @param type		The type of the object
- *
- * @return A new MsnObject structure
- */
-MsnObject *msn_object_new_from_image(PurpleStoredImage *img,
-		const char *location, const char *creator, MsnObjectType type);
-
-/**
- * Destroys an MsnObject structure.
- *
- * @param obj The object structure.
- */
-void msn_object_destroy(MsnObject *obj);
-
-/**
- * Outputs a string representation of an MsnObject.
- *
- * @param obj The object.
- *
- * @return The string representation. This must be freed.
- */
-char *msn_object_to_string(const MsnObject *obj);
-
-/**
- * Sets the creator field in a MsnObject.
- *
- * @param creator The creator value.
- */
-void msn_object_set_creator(MsnObject *obj, const char *creator);
-
-/**
- * Sets the size field in a MsnObject.
- *
- * @param size The size value.
- */
-void msn_object_set_size(MsnObject *obj, int size);
-
-/**
- * Sets the type field in a MsnObject.
- *
- * @param type The type value.
- */
-void msn_object_set_type(MsnObject *obj, MsnObjectType type);
-
-/**
- * Sets the location field in a MsnObject.
- *
- * @param location The location value.
- */
-void msn_object_set_location(MsnObject *obj, const char *location);
-
-/**
- * Sets the friendly name field in a MsnObject.
- *
- * @param friendly The friendly name value.
- */
-void msn_object_set_friendly(MsnObject *obj, const char *friendly);
-
-/**
- * Sets the SHA1D field in a MsnObject.
- *
- * @param sha1d The sha1d value.
- */
-void msn_object_set_sha1d(MsnObject *obj, const char *sha1d);
-
-/**
- * Sets the SHA1C field in a MsnObject.
- *
- * @param sha1c The sha1c value.
- */
-void msn_object_set_sha1c(MsnObject *obj, const char *sha1c);
-
-/**
- * Associates an image with a MsnObject.
- *
- * @param obj The object.
- * @param img The image to associate.
- */
-void msn_object_set_image(MsnObject *obj, PurpleStoredImage *img);
-
-/**
- * Sets the url field in a MsnObject.
- *
- * @param url The url value.
- */
-void msn_object_set_url(MsnObject *obj, const char *url);
-
-/**
- * Sets the url1 field in a MsnObject.
- *
- * @param url1 The url1 value.
- */
-void msn_object_set_url1(MsnObject *obj, const char *url);
-
-/**
- * Returns a MsnObject's creator value.
- *
- * @param obj The object.
- *
- * @return The creator value.
- */
-const char *msn_object_get_creator(const MsnObject *obj);
-
-/**
- * Returns a MsnObject's size value.
- *
- * @param obj The object.
- *
- * @return The size value.
- */
-int msn_object_get_size(const MsnObject *obj);
-
-/**
- * Returns a MsnObject's type.
- *
- * @param obj The object.
- *
- * @return The object type.
- */
-MsnObjectType msn_object_get_type(const MsnObject *obj);
-
-/**
- * Returns a MsnObject's location value.
- *
- * @param obj The object.
- *
- * @return The location value.
- */
-const char *msn_object_get_location(const MsnObject *obj);
-
-/**
- * Returns a MsnObject's friendly name value.
- *
- * @param obj The object.
- *
- * @return The friendly name value.
- */
-const char *msn_object_get_friendly(const MsnObject *obj);
-
-/**
- * Returns a MsnObject's SHA1D value.
- *
- * @param obj The object.
- *
- * @return The SHA1D value.
- */
-const char *msn_object_get_sha1d(const MsnObject *obj);
-
-/**
- * Returns a MsnObject's SHA1C value.
- *
- * @param obj The object.
- *
- * @return The SHA1C value.
- */
-const char *msn_object_get_sha1c(const MsnObject *obj);
-
-/**
- * Returns a MsnObject's SHA1C value if it exists, otherwise SHA1D.
- *
- * @param obj The object.
- *
- * @return The SHA1C value.
- */
-const char *msn_object_get_sha1(const MsnObject *obj);
-
-/**
- * Returns the image associated with the MsnObject.
- *
- * @param obj The object.
- *
- * @return The associated image.
- */
-PurpleStoredImage *msn_object_get_image(const MsnObject *obj);
-
-/**
- * Returns a MsnObject's url value.
- *
- * @param obj The object.
- *
- * @return The url value.
- */
-const char *msn_object_get_url(const MsnObject *obj);
-
-/**
- * Returns a MsnObject's url1 value.
- *
- * @param obj The object.
- *
- * @return The url1 value.
- */
-const char *msn_object_get_url1(const MsnObject *obj);
-
-MsnObject * msn_object_find_local(const char *sha1);
-
-void msn_object_set_local(MsnObject *obj);
-
-#endif /* MSN_OBJECT_H */
--- a/libpurple/protocols/msn/oim.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,886 +0,0 @@
-/**
- * @file oim.c
- * 	get and send MSN offline Instant Message via SOAP request
- *	Author
- * 		MaYuan<mayuan2006@gmail.com>
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-
-#include "soap.h"
-#include "oim.h"
-#include "msnutils.h"
-
-typedef struct _MsnOimSendReq {
-	char *from_member;
-	char *friendname;
-	char *to_member;
-	char *oim_msg;
-} MsnOimSendReq;
-
-typedef struct {
-	MsnOim *oim;
-	char *msg_id;
-} MsnOimRecvData;
-
-/*Local Function Prototype*/
-static void msn_parse_oim_xml(MsnOim *oim, xmlnode *node);
-static void msn_oim_free_send_req(MsnOimSendReq *req);
-static void msn_oim_recv_data_free(MsnOimRecvData *data);
-static void msn_oim_post_single_get_msg(MsnOim *oim, MsnOimRecvData *data);
-
-/*new a OIM object*/
-MsnOim *
-msn_oim_new(MsnSession *session)
-{
-	MsnOim *oim;
-
-	oim = g_new0(MsnOim, 1);
-	oim->session = session;
-	oim->oim_list = NULL;
-	oim->run_id = rand_guid();
-	oim->challenge = NULL;
-	oim->send_queue = g_queue_new();
-	oim->send_seq = 1;
-	return oim;
-}
-
-/*destroy the oim object*/
-void
-msn_oim_destroy(MsnOim *oim)
-{
-	MsnOimSendReq *request;
-
-	purple_debug_info("msn", "destroy the OIM %p\n", oim);
-	g_free(oim->run_id);
-	g_free(oim->challenge);
-
-	while ((request = g_queue_pop_head(oim->send_queue)) != NULL)
-		msn_oim_free_send_req(request);
-	g_queue_free(oim->send_queue);
-
-	while (oim->oim_list != NULL)
-		msn_oim_recv_data_free((MsnOimRecvData *)oim->oim_list->data);
-
-	g_free(oim);
-}
-
-static MsnOimSendReq *
-msn_oim_new_send_req(const char *from_member, const char*friendname,
-	const char* to_member, const char *msg)
-{
-	MsnOimSendReq *request;
-
-	request = g_new0(MsnOimSendReq, 1);
-	request->from_member	= g_strdup(from_member);
-	request->friendname		= g_strdup(friendname);
-	request->to_member		= g_strdup(to_member);
-	request->oim_msg		= g_strdup(msg);
-	return request;
-}
-
-static void
-msn_oim_free_send_req(MsnOimSendReq *req)
-{
-	g_return_if_fail(req != NULL);
-
-	g_free(req->from_member);
-	g_free(req->friendname);
-	g_free(req->to_member);
-	g_free(req->oim_msg);
-
-	g_free(req);
-}
-
-static MsnOimRecvData *
-msn_oim_recv_data_new(MsnOim *oim, char *msg_id)
-{
-	MsnOimRecvData *data;
-
-	data = g_new0(MsnOimRecvData, 1);
-	data->oim = oim;
-	data->msg_id = msg_id;
-
-	oim->oim_list = g_list_append(oim->oim_list, data);
-
-	return data;
-}
-
-/* Probably only good for g_list_find_custom */
-static gint
-msn_recv_data_equal(MsnOimRecvData *a, const char *msg_id)
-{
-	return strcmp(a->msg_id, msg_id);
-}
-
-static void
-msn_oim_recv_data_free(MsnOimRecvData *data)
-{
-	data->oim->oim_list = g_list_remove(data->oim->oim_list, data);
-	g_free(data->msg_id);
-
-	g_free(data);
-}
-
-/****************************************
- * Manage OIM Tokens
- ****************************************/
-typedef struct _MsnOimRequestData {
-	MsnOim *oim;
-	gboolean send;
-	const char *action;
-	const char *host;
-	const char *url;
-	xmlnode *body;
-	MsnSoapCallback cb;
-	gpointer cb_data;
-} MsnOimRequestData;
-
-static gboolean msn_oim_request_helper(MsnOimRequestData *data);
-
-static void
-msn_oim_request_cb(MsnSoapMessage *request, MsnSoapMessage *response,
-	gpointer req_data)
-{
-	MsnOimRequestData *data = (MsnOimRequestData *)req_data;
-	xmlnode *fault = NULL;
-	xmlnode *faultcode = NULL;
-
-	if (response != NULL)
-		fault = xmlnode_get_child(response->xml, "Body/Fault");
-
-	if (fault && (faultcode = xmlnode_get_child(fault, "faultcode"))) {
-		gchar *faultcode_str = xmlnode_get_data(faultcode);
-		gboolean need_token_update = FALSE;
-
-		if (faultcode_str) {
-			if (g_str_equal(faultcode_str, "q0:BadContextToken") ||
-				g_str_equal(faultcode_str, "AuthenticationFailed") ||
-				g_str_equal(faultcode_str, "s:AuthenticationFailed"))
-				need_token_update = TRUE;
-			else if (g_str_equal(faultcode_str, "q0:AuthenticationFailed") &&
-				xmlnode_get_child(fault, "detail/RequiredAuthPolicy") != NULL)
-				need_token_update = TRUE;
-		}
-
-		if (need_token_update) {
-			purple_debug_warning("msn", "OIM Request Error, Updating token now.\n");
-			msn_nexus_update_token(data->oim->session->nexus,
-				data->send ? MSN_AUTH_LIVE_SECURE : MSN_AUTH_MESSENGER_WEB,
-				(GSourceFunc)msn_oim_request_helper, data);
-			g_free(faultcode_str);
-			return;
-
-		}
-
-		g_free(faultcode_str);
-	}
-
-	if (data->cb)
-		data->cb(request, response, data->cb_data);
-	xmlnode_free(data->body);
-	g_free(data);
-}
-
-static gboolean
-msn_oim_request_helper(MsnOimRequestData *data)
-{
-	MsnSession *session = data->oim->session;
-
-	if (data->send) {
-		/* The Sending of OIM's uses a different token for some reason. */
-		xmlnode *ticket;
-		ticket = xmlnode_get_child(data->body, "Header/Ticket");
-		xmlnode_set_attrib(ticket, "passport",
-			msn_nexus_get_token_str(session->nexus, MSN_AUTH_LIVE_SECURE));
-	}
-	else
-	{
-		xmlnode *passport;
-		xmlnode *xml_t;
-		xmlnode *xml_p;
-		GHashTable *token;
-		const char *msn_t;
-		const char *msn_p;
-
-		token = msn_nexus_get_token(session->nexus, MSN_AUTH_MESSENGER_WEB);
-		g_return_val_if_fail(token != NULL, FALSE);
-
-		msn_t = g_hash_table_lookup(token, "t");
-		msn_p = g_hash_table_lookup(token, "p");
-
-		g_return_val_if_fail(msn_t != NULL, FALSE);
-		g_return_val_if_fail(msn_p != NULL, FALSE);
-
-		passport = xmlnode_get_child(data->body, "Header/PassportCookie");
-		xml_t = xmlnode_get_child(passport, "t");
-		xml_p = xmlnode_get_child(passport, "p");
-
-		/* frees old token text, or the 'EMPTY' text if first time */
-		xmlnode_free(xml_t->child);
-		xmlnode_free(xml_p->child);
-
-		xmlnode_insert_data(xml_t, msn_t, -1);
-		xmlnode_insert_data(xml_p, msn_p, -1);
-	}
-
-	msn_soap_message_send(session,
-		msn_soap_message_new(data->action, xmlnode_copy(data->body)),
-		data->host, data->url, FALSE,
-		msn_oim_request_cb, data);
-
-	return FALSE;
-}
-
-
-static void
-msn_oim_make_request(MsnOim *oim, gboolean send, const char *action,
-	const char *host, const char *url, xmlnode *body, MsnSoapCallback cb,
-	gpointer cb_data)
-{
-	MsnOimRequestData *data = g_new0(MsnOimRequestData, 1);
-	data->oim = oim;
-	data->send = send;
-	data->action = action;
-	data->host = host;
-	data->url = url;
-	data->body = body;
-	data->cb = cb;
-	data->cb_data = cb_data;
-
-	msn_oim_request_helper(data);
-}
-
-/****************************************
- * OIM GetMetadata request
- * **************************************/
-static void
-msn_oim_get_metadata_cb(MsnSoapMessage *request, MsnSoapMessage *response,
-	gpointer data)
-{
-	MsnOim *oim = data;
-
-	if (response) {
-		msn_parse_oim_xml(oim,
-			xmlnode_get_child(response->xml, "Body/GetMetadataResponse/MD"));
-	}
-}
-
-/* Post to get the OIM Metadata */
-static void
-msn_oim_get_metadata(MsnOim *oim)
-{
-	msn_oim_make_request(oim, FALSE, MSN_OIM_GET_METADATA_ACTION,
-		MSN_OIM_RETRIEVE_HOST, MSN_OIM_RETRIEVE_URL,
-		xmlnode_from_str(MSN_OIM_GET_METADATA_TEMPLATE, -1),
-		msn_oim_get_metadata_cb, oim);
-}
-
-/****************************************
- * OIM send SOAP request
- * **************************************/
-/*encode the message to OIM Message Format*/
-static gchar *
-msn_oim_msg_to_str(MsnOim *oim, const char *body)
-{
-	GString *oim_body;
-	char *oim_base64;
-	char *c;
-	int len;
-	size_t base64_len;
-
-	purple_debug_info("msn", "Encoding OIM Message...\n");
-	len = strlen(body);
-	c = oim_base64 = purple_base64_encode((const guchar *)body, len);
-	base64_len = strlen(oim_base64);
-	purple_debug_info("msn", "Encoded base64 body:{%s}\n", oim_base64);
-
-	oim_body = g_string_new(NULL);
-	g_string_printf(oim_body, MSN_OIM_MSG_TEMPLATE,
-		oim->run_id, oim->send_seq);
-
-#define OIM_LINE_LEN 76
-	while (base64_len > OIM_LINE_LEN) {
-		g_string_append_len(oim_body, c, OIM_LINE_LEN);
-		g_string_append_c(oim_body, '\n');
-		c += OIM_LINE_LEN;
-		base64_len -= OIM_LINE_LEN;
-	}
-#undef OIM_LINE_LEN
-
-	g_string_append(oim_body, c);
-
-	g_free(oim_base64);
-
-	return g_string_free(oim_body, FALSE);
-}
-
-/*
- * Process the send return SOAP string
- * If got SOAP Fault,get the lock key,and resend it.
- */
-static void
-msn_oim_send_read_cb(MsnSoapMessage *request, MsnSoapMessage *response,
-	gpointer data)
-{
-	MsnOim *oim = data;
-	MsnOimSendReq *msg = g_queue_pop_head(oim->send_queue);
-
-	g_return_if_fail(msg != NULL);
-
-	if (response == NULL) {
-		purple_debug_info("msn", "cannot send OIM: %s\n", msg->oim_msg);
-	} else {
-		xmlnode	*faultNode = xmlnode_get_child(response->xml, "Body/Fault");
-
-		if (faultNode == NULL) {
-			/*Send OK! return*/
-			purple_debug_info("msn", "sent OIM: %s\n", msg->oim_msg);
-		} else {
-			xmlnode *faultcode = xmlnode_get_child(faultNode, "faultcode");
-
-			if (faultcode) {
-				char *faultcode_str = xmlnode_get_data(faultcode);
-
-				if (faultcode_str && g_str_equal(faultcode_str, "q0:AuthenticationFailed")) {
-					xmlnode *challengeNode = xmlnode_get_child(faultNode,
-						"detail/LockKeyChallenge");
-					char *challenge = NULL;
-
-					if (challengeNode == NULL || (challenge = xmlnode_get_data(challengeNode)) == NULL) {
-						if (oim->challenge) {
-							g_free(oim->challenge);
-							oim->challenge = NULL;
-
-							purple_debug_info("msn", "Resending OIM: %s\n",
-								msg->oim_msg);
-							g_queue_push_head(oim->send_queue, msg);
-							msn_oim_send_msg(oim);
-							msg = NULL;
-						} else {
-							purple_debug_info("msn",
-								"Can't find lock key for OIM: %s\n",
-								msg->oim_msg);
-						}
-					} else {
-						char buf[33];
-
-						msn_handle_chl(challenge, buf);
-
-						g_free(oim->challenge);
-						oim->challenge = g_strndup(buf, sizeof(buf));
-						g_free(challenge);
-						purple_debug_info("msn", "Found lockkey:{%s}\n", oim->challenge);
-
-						/*repost the send*/
-						purple_debug_info("msn", "Resending OIM: %s\n", msg->oim_msg);
-						g_queue_push_head(oim->send_queue, msg);
-						msn_oim_send_msg(oim);
-						msg = NULL;
-					}
-				} else {
-					/* Report the error */
-					const char *str_reason = NULL;
-
-					if (faultcode_str) {
-						if (g_str_equal(faultcode_str, "q0:SystemUnavailable")) {
-							str_reason = _("Message was not sent because the system is "
-							               "unavailable. This normally happens when the "
-							               "user is blocked or does not exist.");
-						} else if (g_str_equal(faultcode_str, "q0:SenderThrottleLimitExceeded")) {
-							str_reason = _("Message was not sent because messages "
-							               "are being sent too quickly.");
-						} else if (g_str_equal(faultcode_str, "q0:InvalidContent")) {
-							str_reason = _("Message was not sent because an unknown "
-							               "encoding error occurred.");
-						}
-					}
-
-					if (str_reason == NULL) {
-						str_reason = _("Message was not sent because an unknown "
-						               "error occurred.");
-					}
-
-					msn_session_report_user(oim->session, msg->to_member,
-						str_reason, PURPLE_MESSAGE_ERROR);
-					msn_session_report_user(oim->session, msg->to_member,
-						msg->oim_msg, PURPLE_MESSAGE_RAW);
-				}
-
-				g_free(faultcode_str);
-			}
-		}
-	}
-
-	if (msg)
-		msn_oim_free_send_req(msg);
-}
-
-void
-msn_oim_prep_send_msg_info(MsnOim *oim, const char *membername,
-						   const char* friendname, const char *tomember,
-						   const char * msg)
-{
-	g_return_if_fail(oim != NULL);
-
-	g_queue_push_tail(oim->send_queue,
-		msn_oim_new_send_req(membername, friendname, tomember, msg));
-}
-
-/*post send single message request to oim server*/
-void
-msn_oim_send_msg(MsnOim *oim)
-{
-	MsnOimSendReq *oim_request;
-	char *soap_body;
-	char *msg_body;
-
-	g_return_if_fail(oim != NULL);
-	oim_request = g_queue_peek_head(oim->send_queue);
-	g_return_if_fail(oim_request != NULL);
-
-	purple_debug_info("msn", "Sending OIM: %s\n", oim_request->oim_msg);
-
-	/* if we got the challenge lock key, we compute it
-	 * else we go for the SOAP fault and resend it.
-	 */
-	if (oim->challenge == NULL){
-		purple_debug_info("msn", "No lock key challenge, waiting for SOAP Fault and Resend\n");
-	}
-
-	msg_body = msn_oim_msg_to_str(oim, oim_request->oim_msg);
-	soap_body = g_strdup_printf(MSN_OIM_SEND_TEMPLATE,
-					oim_request->from_member,
-					oim_request->friendname,
-					oim_request->to_member,
-					MSNP15_WLM_PRODUCT_ID,
-					oim->challenge ? oim->challenge : "",
-					oim->send_seq,
-					msg_body);
-
-	msn_oim_make_request(oim, TRUE, MSN_OIM_SEND_SOAP_ACTION, MSN_OIM_SEND_HOST,
-		MSN_OIM_SEND_URL, xmlnode_from_str(soap_body, -1), msn_oim_send_read_cb,
-		oim);
-
-	/*increase the offline Sequence control*/
-	if (oim->challenge != NULL) {
-		oim->send_seq++;
-	}
-
-	g_free(msg_body);
-	g_free(soap_body);
-}
-
-/****************************************
- * OIM delete SOAP request
- * **************************************/
-static void
-msn_oim_delete_read_cb(MsnSoapMessage *request, MsnSoapMessage *response,
-	gpointer data)
-{
-	MsnOimRecvData *rdata = data;
-
-	if (response && xmlnode_get_child(response->xml, "Body/Fault") == NULL)
-		purple_debug_info("msn", "Delete OIM success\n");
-	else
-		purple_debug_info("msn", "Delete OIM failed\n");
-
-	msn_oim_recv_data_free(rdata);
-}
-
-/*Post to get the Offline Instant Message*/
-static void
-msn_oim_post_delete_msg(MsnOimRecvData *rdata)
-{
-	MsnOim *oim = rdata->oim;
-	char *msgid = rdata->msg_id;
-	char *soap_body;
-
-	purple_debug_info("msn", "Delete single OIM Message {%s}\n",msgid);
-
-	soap_body = g_strdup_printf(MSN_OIM_DEL_TEMPLATE, msgid);
-
-	msn_oim_make_request(oim, FALSE, MSN_OIM_DEL_SOAP_ACTION, MSN_OIM_RETRIEVE_HOST,
-		MSN_OIM_RETRIEVE_URL, xmlnode_from_str(soap_body, -1), msn_oim_delete_read_cb, rdata);
-
-	g_free(soap_body);
-}
-
-/****************************************
- * OIM get SOAP request
- * **************************************/
-/* like purple_str_to_time, but different. The format of the timestamp
- * is like this: 5 Sep 2007 21:42:12 -0700 */
-static time_t
-msn_oim_parse_timestamp(const char *timestamp)
-{
-	char month_str[4], tz_str[6];
-	char *tz_ptr = tz_str;
-	static const char *months[] = {
-		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL
-	};
-	time_t tval = 0;
-	struct tm t;
-	memset(&t, 0, sizeof(t));
-
-	time(&tval);
-	localtime_r(&tval, &t);
-
-	if (sscanf(timestamp, "%02d %03s %04d %02d:%02d:%02d %05s",
-					&t.tm_mday, month_str, &t.tm_year,
-					&t.tm_hour, &t.tm_min, &t.tm_sec, tz_str) == 7) {
-		gboolean offset_positive = TRUE;
-		int tzhrs;
-		int tzmins;
-
-		for (t.tm_mon = 0;
-			 months[t.tm_mon] != NULL &&
-				 strcmp(months[t.tm_mon], month_str) != 0; t.tm_mon++);
-		if (months[t.tm_mon] != NULL) {
-			if (*tz_str == '-') {
-				offset_positive = FALSE;
-				tz_ptr++;
-			} else if (*tz_str == '+') {
-				tz_ptr++;
-			}
-
-			if (sscanf(tz_ptr, "%02d%02d", &tzhrs, &tzmins) == 2) {
-				time_t tzoff = tzhrs * 60 * 60 + tzmins * 60;
-#ifdef _WIN32
-				long sys_tzoff;
-#endif
-
-				if (offset_positive)
-					tzoff *= -1;
-
-				t.tm_year -= 1900;
-
-#ifdef _WIN32
-				if ((sys_tzoff = wpurple_get_tz_offset()) != -1)
-					tzoff += sys_tzoff;
-#else
-#ifdef HAVE_TM_GMTOFF
-				tzoff += t.tm_gmtoff;
-#else
-#	ifdef HAVE_TIMEZONE
-				tzset();    /* making sure */
-				tzoff -= timezone;
-#	endif
-#endif
-#endif /* _WIN32 */
-
-				return mktime(&t) + tzoff;
-			}
-		}
-	}
-
-	purple_debug_info("msn", "Can't parse timestamp %s\n", timestamp);
-	return tval;
-}
-
-/*Post the Offline Instant Message to User Conversation*/
-static void
-msn_oim_report_to_user(MsnOimRecvData *rdata, const char *msg_str)
-{
-	MsnMessage *message;
-	const char *date;
-	const char *from;
-	const char *boundary;
-	char *decode_msg = NULL, *clean_msg = NULL;
-	gsize body_len;
-	char **tokens;
-	char *passport = NULL;
-	time_t stamp;
-	const char *charset = NULL;
-
-	message = msn_message_new(MSN_MSG_UNKNOWN);
-
-	msn_message_parse_payload(message, msg_str, strlen(msg_str),
-	                          MSG_OIM_LINE_DEM, MSG_OIM_BODY_DEM);
-	purple_debug_info("msn", "oim body:{%s}\n", message->body);
-
-	boundary = msn_message_get_header_value(message, "boundary");
-
-	if (boundary != NULL) {
-		char *bounds;
-		char **part;
-
-		bounds = g_strdup_printf("--%s" MSG_OIM_LINE_DEM, boundary);
-		tokens = g_strsplit(message->body, bounds, 0);
-
-		/* tokens+1 to skip the "This is a multipart message..." text */
-		for (part = tokens+1; *part != NULL; part++) {
-			MsnMessage *multipart;
-			const char *type;
-			multipart = msn_message_new(MSN_MSG_UNKNOWN);
-			msn_message_parse_payload(multipart, *part, strlen(*part),
-			                          MSG_OIM_LINE_DEM, MSG_OIM_BODY_DEM);
-
-			type = msn_message_get_content_type(multipart);
-			if (type && !strcmp(type, "text/plain")) {
-				decode_msg = (char *)purple_base64_decode(multipart->body, &body_len);
-				charset = msn_message_get_charset(multipart);
-
-				msn_message_unref(multipart);
-				break;
-			}
-			msn_message_unref(multipart);
-		}
-
-		g_strfreev(tokens);
-		g_free(bounds);
-
-		if (decode_msg == NULL) {
-			purple_debug_error("msn", "Couldn't find text/plain OIM message.\n");
-			msn_message_unref(message);
-			return;
-		}
-	} else {
-		decode_msg = (char *)purple_base64_decode(message->body, &body_len);
-		charset = msn_message_get_charset(message);
-	}
-
-	if (charset && !((g_ascii_strncasecmp(charset, "UTF-8", 5) == 0) || (g_ascii_strncasecmp(charset, "UTF8", 4) == 0))) {
-		clean_msg = g_convert(decode_msg, body_len, "UTF-8", charset, NULL, NULL, NULL);
-
-		if (!clean_msg) {
-			char *clean = purple_utf8_salvage(decode_msg);
-
-			purple_debug_error("msn", "Failed to convert charset from %s to UTF-8 for OIM message: %s\n", charset, clean);
-
-			clean_msg = g_strdup_printf(_("%s (There was an error receiving this message. "
-			                              "Converting the encoding from %s to UTF-8 failed.)"),
-			                            clean, charset);
-			g_free(clean);
-		}
-
-		g_free(decode_msg);
-
-	} else if (!g_utf8_validate(decode_msg, body_len, NULL)) {
-		char *clean = purple_utf8_salvage(decode_msg);
-
-		purple_debug_error("msn", "Received an OIM message that is not UTF-8,"
-		                          " and no encoding specified: %s\n", clean);
-
-		if (charset) {
-			clean_msg = g_strdup_printf(_("%s (There was an error receiving this message."
-			                              " The charset was %s, but it was not valid UTF-8.)"),
-			                            clean, charset);
-		} else {
-			clean_msg = g_strdup_printf(_("%s (There was an error receiving this message."
-			                              " The charset was missing, but it was not valid UTF-8.)"),
-			                            clean);
-		}
-
-		g_free(clean);
-		g_free(decode_msg);
-
-	} else {
-		clean_msg = decode_msg;
-	}
-
-	from = msn_message_get_header_value(message, "X-OIM-originatingSource");
-
-	/* Match number to user's mobile number, FROM is a phone number
-	   if the other side pages you using your phone number */
-	if (from && !strncmp(from, "tel:+", 5)) {
-		MsnUser *user =	msn_userlist_find_user_with_mobile_phone(
-				rdata->oim->session->userlist, from + 4);
-
-		if (user && user->passport)
-			passport = g_strdup(user->passport);
-	}
-
-	if (passport == NULL) {
-		char *start, *end;
-
-		from = msn_message_get_header_value(message, "From");
-
-		tokens = g_strsplit(from, " ", 2);
-		if (tokens[1] != NULL)
-			from = (const char *)tokens[1];
-
-		start = strchr(from, '<');
-		if (start != NULL) {
-			start++;
-			end = strchr(from, '>');
-			if (end != NULL)
-				passport = g_strndup(start, end - start);
-		}
-		if (passport == NULL)
-			passport = g_strdup(_("Unknown"));
-
-		g_strfreev(tokens);
-	}
-
-	date = msn_message_get_header_value(message, "Date");
-	stamp = msn_oim_parse_timestamp(date);
-	purple_debug_info("msn", "oim Date:{%s},passport{%s}\n",
-	                  date, passport);
-
-	serv_got_im(purple_account_get_connection(rdata->oim->session->account), passport, clean_msg, 0,
-	            stamp);
-
-	/*Now get the oim message ID from the oim_list.
-	 * and append to read list to prepare for deleting the Offline Message when sign out
-	 */
-	msn_oim_post_delete_msg(rdata);
-
-	g_free(passport);
-	g_free(clean_msg);
-	msn_message_unref(message);
-}
-
-/* Parse the XML data,
- * prepare to report the OIM to user
- */
-static void
-msn_oim_get_read_cb(MsnSoapMessage *request, MsnSoapMessage *response,
-	gpointer data)
-{
-	MsnOimRecvData *rdata = data;
-
-	if (response != NULL) {
-		xmlnode *msg_node = xmlnode_get_child(response->xml,
-			"Body/GetMessageResponse/GetMessageResult");
-
-		if (msg_node) {
-			char *msg_str = xmlnode_get_data(msg_node);
-			msn_oim_report_to_user(rdata, msg_str);
-			g_free(msg_str);
-		} else {
-			char *str = xmlnode_to_str(response->xml, NULL);
-			purple_debug_info("msn", "Unknown OIM response: %s\n", str);
-			g_free(str);
-			msn_oim_recv_data_free(rdata);
-		}
-	} else {
-		purple_debug_info("msn", "Failed to get OIM\n");
-		msn_oim_recv_data_free(rdata);
-	}
-
-}
-
-/* parse the oim XML data
- * and post it to the soap server to get the Offline Message
- * */
-void
-msn_parse_oim_msg(MsnOim *oim,const char *xmlmsg)
-{
-	xmlnode *node;
-
-	purple_debug_info("msn", "%s\n", xmlmsg);
-
-	if (!strcmp(xmlmsg, "too-large")) {
-		/* Too many OIM's to send via NS, so we need to request them via SOAP. */
-		msn_oim_get_metadata(oim);
-	} else {
-		node = xmlnode_from_str(xmlmsg, -1);
-		msn_parse_oim_xml(oim, node);
-		xmlnode_free(node);
-	}
-}
-
-static void
-msn_parse_oim_xml(MsnOim *oim, xmlnode *node)
-{
-	xmlnode *mNode;
-	xmlnode *iu_node;
-	MsnSession *session = oim->session;
-
-	g_return_if_fail(node != NULL);
-
-	if (strcmp(node->name, "MD") != 0) {
-		char *xmlmsg = xmlnode_to_str(node, NULL);
-		purple_debug_info("msn", "WTF is this? %s\n", xmlmsg);
-		g_free(xmlmsg);
-		return;
-	}
-
-	iu_node = xmlnode_get_child(node, "E/IU");
-
-	if (iu_node != NULL && purple_account_get_check_mail(session->account))
-	{
-		char *unread = xmlnode_get_data(iu_node);
-		const char *passports[2] = { msn_user_get_passport(session->user) };
-		const char *urls[2] = { session->passport_info.mail_url };
-		int count;
-
-		/* XXX/khc: pretty sure this is wrong */
-		if (unread && (count = atoi(unread)) > 0)
-			purple_notify_emails(session->account->gc, count, FALSE, NULL,
-				NULL, passports, urls, NULL, NULL);
-		g_free(unread);
-	}
-
-	for(mNode = xmlnode_get_child(node, "M"); mNode;
-					mNode = xmlnode_get_next_twin(mNode)){
-		char *passport, *msgid, *nickname, *rtime = NULL;
-		xmlnode *e_node, *i_node, *n_node, *rt_node;
-
-		e_node = xmlnode_get_child(mNode, "E");
-		passport = xmlnode_get_data(e_node);
-
-		i_node = xmlnode_get_child(mNode, "I");
-		msgid = xmlnode_get_data(i_node);
-
-		n_node = xmlnode_get_child(mNode, "N");
-		nickname = xmlnode_get_data(n_node);
-
-		rt_node = xmlnode_get_child(mNode, "RT");
-		if (rt_node != NULL) {
-			rtime = xmlnode_get_data(rt_node);
-		}
-/*		purple_debug_info("msn", "E:{%s},I:{%s},rTime:{%s}\n",passport,msgid,rTime); */
-
-		if (!g_list_find_custom(oim->oim_list, msgid, (GCompareFunc)msn_recv_data_equal)) {
-			MsnOimRecvData *data = msn_oim_recv_data_new(oim, msgid);
-			msn_oim_post_single_get_msg(oim, data);
-			msgid = NULL;
-		}
-
-		g_free(passport);
-		g_free(msgid);
-		g_free(rtime);
-		g_free(nickname);
-	}
-}
-
-/*Post to get the Offline Instant Message*/
-static void
-msn_oim_post_single_get_msg(MsnOim *oim, MsnOimRecvData *data)
-{
-	char *soap_body;
-
-	purple_debug_info("msn", "Get single OIM Message\n");
-
-	soap_body = g_strdup_printf(MSN_OIM_GET_TEMPLATE, data->msg_id);
-
-	msn_oim_make_request(oim, FALSE, MSN_OIM_GET_SOAP_ACTION, MSN_OIM_RETRIEVE_HOST,
-		MSN_OIM_RETRIEVE_URL, xmlnode_from_str(soap_body, -1), msn_oim_get_read_cb,
-		data);
-
-	g_free(soap_body);
-}
-
--- a/libpurple/protocols/msn/oim.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +0,0 @@
-/**
- * @file oim.h			Header file for oim.c
- *	Author
- *		MaYuan<mayuan2006@gmail.com>
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA
- */
-#ifndef MSN_OIM_H
-#define MSN_OIM_H
-
-typedef struct _MsnOim MsnOim;
-
-/* OIM Retrieval Info */
-#define MSN_OIM_RETRIEVE_HOST	"rsi.hotmail.com"
-#define MSN_OIM_RETRIEVE_URL	"/rsi/rsi.asmx"
-
-/* OIM GetMetadata SOAP Template */
-#define MSN_OIM_GET_METADATA_ACTION "http://www.hotmail.msn.com/ws/2004/09/oim/rsi/GetMetadata"
-
-#define MSN_OIM_GET_METADATA_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
-	"<soap:Header>"\
-		"<PassportCookie xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\
-			"<t>EMPTY</t>"\
-			"<p>EMPTY</p>"\
-		"</PassportCookie>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<GetMetadata xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\" />"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/*OIM GetMessage SOAP Template*/
-#define MSN_OIM_GET_SOAP_ACTION	"http://www.hotmail.msn.com/ws/2004/09/oim/rsi/GetMessage"
-
-#define MSN_OIM_GET_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
-	"<soap:Header>"\
-		"<PassportCookie xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\
-			"<t>EMPTY</t>"\
-			"<p>EMPTY</p>"\
-		"</PassportCookie>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<GetMessage xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\
-			"<messageId>%s</messageId>"\
-			"<alsoMarkAsRead>false</alsoMarkAsRead>"\
-		"</GetMessage>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/*OIM DeleteMessages SOAP Template*/
-#define MSN_OIM_DEL_SOAP_ACTION	"http://www.hotmail.msn.com/ws/2004/09/oim/rsi/DeleteMessages"
-
-#define MSN_OIM_DEL_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
-	"<soap:Header>"\
-		"<PassportCookie xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\
-			"<t>EMPTY</t>"\
-			"<p>EMPTY</p>"\
-		"</PassportCookie>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<DeleteMessages xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\
-			"<messageIds>"\
-				"<messageId>%s</messageId>"\
-			"</messageIds>"\
-		"</DeleteMessages>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-/*OIM Send SOAP Template*/
-#define MSN_OIM_MSG_TEMPLATE "MIME-Version: 1.0\n"\
-	"Content-Type: text/plain; charset=UTF-8\n"\
-	"Content-Transfer-Encoding: base64\n"\
-	"X-OIM-Message-Type: OfflineMessage\n"\
-	"X-OIM-Run-Id: {%s}\n"\
-	"X-OIM-Sequence-Num: %d\n\n"
-
-#define MSN_OIM_SEND_HOST	"ows.messenger.msn.com"
-#define MSN_OIM_SEND_URL	"/OimWS/oim.asmx"
-#define MSN_OIM_SEND_SOAP_ACTION	"http://messenger.live.com/ws/2006/09/oim/Store2"
-#define MSN_OIM_SEND_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
-"<soap:Envelope"\
-	" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-	" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-	" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
-	"<soap:Header>"\
-		"<From"\
-			" memberName=\"%s\""\
-			" friendlyName=\"%s\""\
-			" xml:lang=\"en-US\""\
-			" proxy=\"MSNMSGR\""\
-			" xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\""\
-			" msnpVer=\"MSNP15\""\
-			" buildVer=\"8.5.1288\"/>"\
-		"<To memberName=\"%s\" xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\"/>"\
-		"<Ticket passport=\"EMPTY\" appid=\"%s\" lockkey=\"%s\" xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\"/>"\
-		"<Sequence xmlns=\"http://schemas.xmlsoap.org/ws/2003/03/rm\">"\
-			"<Identifier xmlns=\"http://schemas.xmlsoap.org/ws/2002/07/utility\">http://messenger.msn.com</Identifier>"\
-			"<MessageNumber>%d</MessageNumber>"\
-		"</Sequence>"\
-	"</soap:Header>"\
-	"<soap:Body>"\
-		"<MessageType xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\">text</MessageType>"\
-		"<Content xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\">%s</Content>"\
-	"</soap:Body>"\
-"</soap:Envelope>"
-
-struct _MsnOim
-{
-	MsnSession *session;
-
-	GList * oim_list;
-
-	char *challenge;
-	char *run_id;
-	gint send_seq;
-	GQueue *send_queue;
-};
-
-/****************************************************
- * function prototype
- * **************************************************/
-MsnOim * msn_oim_new(MsnSession *session);
-void msn_oim_destroy(MsnOim *oim);
-
-void msn_parse_oim_msg(MsnOim *oim,const char *xmlmsg);
-
-/*Send OIM Message*/
-void msn_oim_prep_send_msg_info(MsnOim *oim, const char *membername,
-								const char *friendname, const char *tomember,
-								const char * msg);
-
-void msn_oim_send_msg(MsnOim *oim);
-
-#endif/* MSN_OIM_H*/
--- a/libpurple/protocols/msn/p2p.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,872 +0,0 @@
-/**
- * @file p2p.c MSN P2P functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-
-#include "p2p.h"
-#include "tlv.h"
-#include "msnutils.h"
-
-MsnP2PInfo *
-msn_p2p_info_new(MsnP2PVersion version)
-{
-	MsnP2PInfo *info = g_new0(MsnP2PInfo, 1);
-	info->version = version;
-
-	switch (version) {
-		case MSN_P2P_VERSION_ONE:
-		case MSN_P2P_VERSION_TWO:
-			/* Nothing to do */
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", version);
-			g_free(info);
-			info = NULL;
-	}
-
-	return info;
-}
-
-MsnP2PInfo *
-msn_p2p_info_dup(MsnP2PInfo *info)
-{
-	MsnP2PInfo *new_info = g_new0(MsnP2PInfo, 1);
-
-	new_info->version = info->version;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			*new_info = *info;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			*new_info = *info;
-			new_info->header.v2.header_tlv = msn_tlvlist_copy(info->header.v2.header_tlv);
-			new_info->header.v2.data_tlv = msn_tlvlist_copy(info->header.v2.data_tlv);
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-			g_free(new_info);
-			new_info = NULL;
-	}
-
-	return new_info;
-}
-
-void
-msn_p2p_info_free(MsnP2PInfo *info)
-{
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			/* Nothing to do! */
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			msn_tlvlist_free(info->header.v2.header_tlv);
-			msn_tlvlist_free(info->header.v2.data_tlv);
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	g_free(info);
-}
-
-size_t
-msn_p2p_header_from_wire(MsnP2PInfo *info, const char *wire, size_t max_len)
-{
-	size_t len = 0;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE: {
-			MsnP2PHeader *header = &info->header.v1;
-
-			if (max_len < P2P_PACKET_HEADER_SIZE) {
-				/* Invalid packet length */
-				len = 0;
-				break;
-			}
-
-			header->session_id = msn_pop32le(wire);
-			header->id         = msn_pop32le(wire);
-			header->offset     = msn_pop64le(wire);
-			header->total_size = msn_pop64le(wire);
-			header->length     = msn_pop32le(wire);
-			header->flags      = msn_pop32le(wire);
-			header->ack_id     = msn_pop32le(wire);
-			header->ack_sub_id = msn_pop32le(wire);
-			header->ack_size   = msn_pop64le(wire);
-
-			len = P2P_PACKET_HEADER_SIZE;
-			break;
-		}
-
-		case MSN_P2P_VERSION_TWO: {
-			MsnP2Pv2Header *header = &info->header.v2;
-
-			header->header_len = msn_pop8(wire);
-			header->opcode = msn_pop8(wire);
-			header->message_len = msn_pop16be(wire);
-			header->base_id = msn_pop32be(wire);
-			if ((gsize)header->header_len + header->message_len +
-				P2P_PACKET_FOOTER_SIZE > max_len)
-			{
-				/* Invalid header and data length */
-				len = 0;
-				break;
-			}
-
-			if (header->header_len > 8) {
-				header->header_tlv = msn_tlvlist_read(wire, header->header_len - 8);
-				wire += header->header_len - 8;
-			}
-
-			if (header->message_len > 0) {
-				/* Parse Data packet */
-
-				header->data_header_len = msn_pop8(wire);
-				if (header->data_header_len > header->message_len) {
-					/* Invalid data header length */
-					len = 0;
-					break;
-				}
-				header->data_tf = msn_pop8(wire);
-				header->package_number = msn_pop16be(wire);
-				header->session_id = msn_pop32be(wire);
-
-				if (header->data_header_len > 8) {
-					header->data_tlv = msn_tlvlist_read(wire, header->data_header_len - 8);
-					wire += header->data_header_len - 8;
-				}
-			}
-
-			len = header->header_len + header->message_len;
-
-			break;
-		}
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return len;
-}
-
-char *
-msn_p2p_header_to_wire(MsnP2PInfo *info, size_t *len)
-{
-	char *wire = NULL;
-	char *tmp;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE: {
-			MsnP2PHeader *header = &info->header.v1;
-			tmp = wire = g_new(char, P2P_PACKET_HEADER_SIZE);
-
-			msn_push32le(tmp, header->session_id);
-			msn_push32le(tmp, header->id);
-			msn_push64le(tmp, header->offset);
-			msn_push64le(tmp, header->total_size);
-			msn_push32le(tmp, header->length);
-			msn_push32le(tmp, header->flags);
-			msn_push32le(tmp, header->ack_id);
-			msn_push32le(tmp, header->ack_sub_id);
-			msn_push64le(tmp, header->ack_size);
-
-			if (len)
-				*len = P2P_PACKET_HEADER_SIZE;
-
-			break;
-		}
-
-		case MSN_P2P_VERSION_TWO: {
-			MsnP2Pv2Header *header = &info->header.v2;
-			char *header_wire = NULL;
-			char *data_header_wire = NULL;
-
-			if (header->header_tlv != NULL)
-				header_wire = msn_tlvlist_write(header->header_tlv, &header->header_len);
-			else
-				header->header_len = 0;
-
-			if (header->data_tlv != NULL)
-				data_header_wire = msn_tlvlist_write(header->data_tlv, &header->data_header_len);
-			else
-				header->data_header_len = 0;
-
-			tmp = wire = g_new(char, 16 + header->header_len + header->data_header_len);
-
-			msn_push8(tmp, header->header_len + 8);
-			msn_push8(tmp, header->opcode);
-			msn_push16be(tmp, header->data_header_len + 8 + header->message_len);
-			msn_push32be(tmp, header->base_id);
-
-			if (header_wire != NULL) {
-				memcpy(tmp, header_wire, header->header_len);
-				tmp += header->header_len;
-			}
-
-			msn_push8(tmp, header->data_header_len + 8);
-			msn_push8(tmp, header->data_tf);
-			msn_push16be(tmp, header->package_number);
-			msn_push32be(tmp, header->session_id);
-
-			if (data_header_wire != NULL) {
-				memcpy(tmp, data_header_wire, header->data_header_len);
-				tmp += header->data_header_len;
-			}
-
-			if (len)
-				*len = header->header_len + header->data_header_len + 16;
-
-			break;
-		}
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return wire;
-}
-
-size_t
-msn_p2p_footer_from_wire(MsnP2PInfo *info, const char *wire)
-{
-	MsnP2PFooter *footer;
-
-	footer = &info->footer;
-
-	footer->value = msn_pop32be(wire);
-
-	return P2P_PACKET_FOOTER_SIZE;
-}
-
-char *
-msn_p2p_footer_to_wire(MsnP2PInfo *info, size_t *len)
-{
-	MsnP2PFooter *footer;
-	char *wire;
-	char *tmp;
-
-	footer = &info->footer;
-	tmp = wire = g_new(char, P2P_PACKET_FOOTER_SIZE);
-
-	msn_push32be(tmp, footer->value);
-
-	if (len)
-		*len = P2P_PACKET_FOOTER_SIZE;
-
-	return wire;
-}
-
-void
-msn_p2p_info_to_string(MsnP2PInfo *info, GString *str)
-{
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE: {
-			MsnP2PHeader *header = &info->header.v1;
-			g_string_append_printf(str, "Session ID: %u\r\n", header->session_id);
-			g_string_append_printf(str, "ID:         %u\r\n", header->id);
-			g_string_append_printf(str, "Offset:     %" G_GUINT64_FORMAT "\r\n", header->offset);
-			g_string_append_printf(str, "Total size: %" G_GUINT64_FORMAT "\r\n", header->total_size);
-			g_string_append_printf(str, "Length:     %u\r\n", header->length);
-			g_string_append_printf(str, "Flags:      0x%x\r\n", header->flags);
-			g_string_append_printf(str, "ACK ID:     %u\r\n", header->ack_id);
-			g_string_append_printf(str, "SUB ID:     %u\r\n", header->ack_sub_id);
-			g_string_append_printf(str, "ACK Size:   %" G_GUINT64_FORMAT "\r\n", header->ack_size);
-
-			break;
-		}
-
-		case MSN_P2P_VERSION_TWO:
-			/* Nothing to do! */
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	g_string_append_printf(str, "Footer:     0x%08X\r\n", info->footer.value);
-}
-
-gboolean
-msn_p2p_msg_is_data(const MsnP2PInfo *info)
-{
-	gboolean data = FALSE;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE: {
-			guint32 flags = info->header.v1.flags;
-			data = (flags == P2P_MSN_OBJ_DATA ||
-			        flags == (P2P_WLM2009_COMP | P2P_MSN_OBJ_DATA) ||
-			        flags == P2P_FILE_DATA);
-			break;
-		}
-
-		case MSN_P2P_VERSION_TWO:
-			data = info->header.v2.message_len > 0;
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return data;
-}
-
-gboolean
-msn_p2p_info_is_valid(MsnP2PInfo *info)
-{
-	gboolean valid = FALSE;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			valid = info->header.v1.total_size >= info->header.v1.length;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			/* Nothing to do! */
-			valid = TRUE;
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return valid;
-}
-
-gboolean
-msn_p2p_info_is_first(MsnP2PInfo *info)
-{
-	gboolean first = FALSE;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			first = info->header.v1.offset == 0;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			/* Nothing to do! */
-			first = info->header.v2.data_tf & TF_FIRST;
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return first;
-}
-
-gboolean
-msn_p2p_info_is_final(MsnP2PInfo *info)
-{
-	gboolean final = FALSE;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			final = info->header.v1.offset + info->header.v1.length >= info->header.v1.total_size;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			final = msn_tlv_gettlv(info->header.v2.data_tlv, P2P_DATA_TLV_REMAINING, 1) == NULL;
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return final;
-}
-
-void
-msn_p2p_info_create_ack(MsnP2PInfo *old_info, MsnP2PInfo *new_info)
-{
-	switch (old_info->version) {
-		case MSN_P2P_VERSION_ONE: {
-			MsnP2PHeader *old = &old_info->header.v1;
-			MsnP2PHeader *new = &new_info->header.v1;
-
-			new->session_id = old->session_id;
-			new->flags = P2P_ACK;
-			new->ack_id = old->id;
-			new->ack_sub_id = old->ack_id;
-			new->ack_size = old->total_size;
-			break;
-		}
-
-		case MSN_P2P_VERSION_TWO: {
-			MsnP2Pv2Header *old = &old_info->header.v2;
-			MsnP2Pv2Header *new = &new_info->header.v2;
-
-			msn_tlvlist_add_32(&new->header_tlv, P2P_HEADER_TLV_TYPE_ACK, old->base_id + old->message_len);
-			new->opcode = P2P_OPCODE_NONE;
-
-			if (old->message_len > 0) {
-				if (!msn_tlv_gettlv(old->header_tlv, P2P_HEADER_TLV_TYPE_ACK, 1)) {
-					if (old->opcode & P2P_OPCODE_SYN) {
-						msn_tlv_t *ack_tlv;
-						new->opcode |= P2P_OPCODE_RAK;
-						
-						ack_tlv = msn_tlv_gettlv(old->header_tlv, P2P_HEADER_TLV_TYPE_PEER_INFO, 1);
-						if (ack_tlv) {
-							msn_tlvlist_add_tlv(&new->header_tlv, ack_tlv);
-							new->opcode |= P2P_OPCODE_SYN;
-						}
-					}
-				}
-			}
-			break;
-		}
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", old_info->version);
-	}
-}
-
-gboolean
-msn_p2p_info_require_ack(MsnP2PInfo *info)
-{
-	gboolean ret = FALSE;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE: {
-			guint32 flags = msn_p2p_info_get_flags(info);
-
-			ret = flags == P2P_NO_FLAG || flags == P2P_WLM2009_COMP ||
-			      msn_p2p_msg_is_data(info);
-			break;
-		}
-
-		case MSN_P2P_VERSION_TWO:
-			ret = (info->header.v2.opcode & P2P_OPCODE_RAK) > 0;
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return ret;
-}
-
-gboolean
-msn_p2p_info_is_ack(MsnP2PInfo *info)
-{
-	gboolean ret = FALSE;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE: {
-			ret = msn_p2p_info_get_flags(info) == P2P_ACK;
-			break;
-		}
-
-		case MSN_P2P_VERSION_TWO:
-			ret = msn_tlv_gettlv(info->header.v2.header_tlv, P2P_HEADER_TLV_TYPE_ACK, 1) != NULL;
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return ret;
-}
-
-void
-msn_p2p_info_init_first(MsnP2PInfo *info, MsnP2PInfo *old_info)
-{
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			info->header.v1.session_id = old_info->header.v1.session_id;
-			info->header.v1.flags = old_info->header.v1.flags;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			info->header.v2.data_tf = TF_FIRST;
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-}
-
-guint32
-msn_p2p_info_get_session_id(MsnP2PInfo *info)
-{
-	guint32 session_id = 0;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			session_id = info->header.v1.session_id;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			session_id = info->header.v2.session_id;
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return session_id;
-}
-
-guint32
-msn_p2p_info_get_id(MsnP2PInfo *info)
-{
-	guint32 id = 0;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			id = info->header.v1.id;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			id = info->header.v2.base_id;
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return id;
-}
-
-guint64
-msn_p2p_info_get_offset(MsnP2PInfo *info)
-{
-	guint64 offset = 0;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			offset = info->header.v1.offset;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			/* Nothing to do! */
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return offset;
-}
-
-guint64
-msn_p2p_info_get_total_size(MsnP2PInfo *info)
-{
-	guint64 total_size = 0;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			total_size = info->header.v1.total_size;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			/* Nothing to do! */
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return total_size;
-}
-
-guint32
-msn_p2p_info_get_length(MsnP2PInfo *info)
-{
-	guint32 length = 0;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			length = info->header.v1.length;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			/* Nothing to do! */
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return length;
-}
-
-guint32
-msn_p2p_info_get_flags(MsnP2PInfo *info)
-{
-	guint32 flags = 0;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			flags = info->header.v1.flags;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			flags = info->header.v2.data_tf;
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return flags;
-}
-
-guint32
-msn_p2p_info_get_ack_id(MsnP2PInfo *info)
-{
-	guint32 ack_id = 0;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			ack_id = info->header.v1.ack_id;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			/* Nothing to do! */
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return ack_id;
-}
-
-guint32
-msn_p2p_info_get_ack_sub_id(MsnP2PInfo *info)
-{
-	guint32 ack_sub_id = 0;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			ack_sub_id = info->header.v1.ack_sub_id;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			/* Nothing to do! */
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return ack_sub_id;
-}
-
-guint64
-msn_p2p_info_get_ack_size(MsnP2PInfo *info)
-{
-	guint64 ack_size = 0;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			ack_size = info->header.v1.ack_size;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			/* Nothing to do! */
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return ack_size;
-}
-
-guint32
-msn_p2p_info_get_app_id(MsnP2PInfo *info)
-{
-	return info->footer.value;
-}
-
-void
-msn_p2p_info_set_session_id(MsnP2PInfo *info, guint32 session_id)
-{
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			info->header.v1.session_id = session_id;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			info->header.v2.session_id = session_id;
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-}
-
-void
-msn_p2p_info_set_id(MsnP2PInfo *info, guint32 id)
-{
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			info->header.v1.id = id;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			info->header.v2.base_id = id;
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-}
-
-void
-msn_p2p_info_set_offset(MsnP2PInfo *info, guint64 offset)
-{
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			info->header.v1.offset = offset;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			/* Nothing to do! */
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-}
-
-void
-msn_p2p_info_set_total_size(MsnP2PInfo *info, guint64 total_size)
-{
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			info->header.v1.total_size = total_size;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			/* Nothing to do! */
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-}
-
-void
-msn_p2p_info_set_length(MsnP2PInfo *info, guint32 length)
-{
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			info->header.v1.length = length;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			/* Nothing to do! */
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-}
-
-void
-msn_p2p_info_set_flags(MsnP2PInfo *info, guint32 flags)
-{
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			info->header.v1.flags = flags;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			info->header.v2.data_tf = flags;
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-}
-
-void
-msn_p2p_info_set_ack_id(MsnP2PInfo *info, guint32 ack_id)
-{
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			info->header.v1.ack_id = ack_id;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			/* Nothing to do! */
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-}
-
-void
-msn_p2p_info_set_ack_sub_id(MsnP2PInfo *info, guint32 ack_sub_id)
-{
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			info->header.v1.ack_sub_id = ack_sub_id;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			/* Nothing to do! */
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-}
-
-void
-msn_p2p_info_set_ack_size(MsnP2PInfo *info, guint64 ack_size)
-{
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			info->header.v1.ack_size = ack_size;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			/* Nothing to do! */
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-}
-
-void
-msn_p2p_info_set_app_id(MsnP2PInfo *info, guint32 app_id)
-{
-	info->footer.value = app_id;
-}
-
--- a/libpurple/protocols/msn/p2p.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,264 +0,0 @@
-/**
- * @file p2p.h MSN P2P functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#ifndef MSN_P2P_H
-#define MSN_P2P_H
-
-typedef struct {
-	guint32 session_id;
-	guint32 id;
-	/**
-	 * In a MsnSlpMessage:
-	 * For outgoing messages this is the number of bytes from buffer that
-	 * have already been sent out.  For incoming messages this is the
-	 * number of bytes that have been written to buffer.
-	 */
-	guint64 offset;
-	guint64 total_size;
-	guint32 length;
-	guint32 flags;
-	guint32 ack_id;
-	guint32 ack_sub_id;
-	guint64 ack_size;
-/*	guint8  body[1]; */
-} MsnP2PHeader;
-#define P2P_PACKET_HEADER_SIZE (6 * 4 + 3 * 8)
-
-typedef struct {
-	guint8  header_len;
-	guint8  opcode;
-	guint16 message_len;
-	guint32 base_id;
-	GSList *header_tlv;
-	guint8  data_header_len;
-	guint8  data_tf;
-	guint16 package_number;
-	guint32 session_id;
-	GSList *data_tlv;
-/*	guint8  body[1]; */
-} MsnP2Pv2Header;
-
-typedef struct {
-	guint16 protocol_version;
-	guint16 implementation_id;
-	guint16 version;
-	guint16 reserved;
-	guint32 caps;
-} P2PPeerInfo;
-
-typedef enum
-{
-	TF_FIRST    = 0x01,     /**< The first package. */
-	TF_MSNOBJ   = 0x04,     /**< Payload contains binary data for MsnObject. */
-	TF_FILE     = 0x06      /**< Payload contains binary data. */
-} TF;
-
-typedef enum
-{
-	P2P_HEADER_TLV_TYPE_PEER_INFO  = 0x01, /**< Client peer info */
-	P2P_HEADER_TLV_TYPE_ACK        = 0x02, /**< ACK */
-	P2P_HEADER_TLV_TYPE_NAK        = 0x03  /**< NAK */
-} P2PHeaderTLVType;
-
-typedef enum
-{
-	P2P_DATA_TLV_REMAINING  = 0x01, /**< Indicates the remaining data to transfer.*/
-} P2PDataTLVType;
-
-typedef enum
-{
-	P2P_PI_PVER     = 0x0200,
-	P2P_PI_IMP_ID   = 0,
-	P2P_PI_VER      = 0x0e00,
-	P2P_PI_RES      = 0,
-	P2P_PI_CAPS     = 0x0000010f
-} P2PPeerInfoVal;
-
-typedef struct
-{
-	guint32 value;
-} MsnP2PFooter;
-#define P2P_PACKET_FOOTER_SIZE (1 * 4)
-
-typedef enum
-{
-	MSN_P2P_VERSION_ONE = 0,
-	MSN_P2P_VERSION_TWO = 1,
-} MsnP2PVersion;
-
-typedef struct {
-	MsnP2PVersion version;
-	union {
-		MsnP2PHeader v1;
-		MsnP2Pv2Header v2;
-	} header;
-	MsnP2PFooter footer;
-} MsnP2PInfo;
-
-typedef enum
-{
-	P2P_NO_FLAG         = 0x0,        /**< No flags specified */
-	P2P_OUT_OF_ORDER    = 0x1,        /**< Chunk out-of-order */
-	P2P_ACK             = 0x2,        /**< Acknowledgement */
-	P2P_PENDING_INVITE  = 0x4,        /**< There is a pending invite */
-	P2P_BINARY_ERROR    = 0x8,        /**< Error on the binary level */
-	P2P_FILE            = 0x10,       /**< File */
-	P2P_MSN_OBJ_DATA    = 0x20,       /**< MsnObject data */
-	P2P_CLOSE           = 0x40,       /**< Close session */
-	P2P_TLP_ERROR       = 0x80,       /**< Error at transport layer protocol */
-	P2P_DC_HANDSHAKE    = 0x100,      /**< Direct Handshake */
-	P2P_WLM2009_COMP    = 0x1000000,  /**< Compatibility with WLM 2009 */
-	P2P_FILE_DATA       = 0x1000030   /**< File transfer data */
-} MsnP2PHeaderFlag;
-/* Info From:
- * http://msnpiki.msnfanatic.com/index.php/MSNC:P2Pv1_Headers#Flags
- * http://trac.kmess.org/changeset/ba04d0c825769d23370511031c47f6be75fe9b86
- * #7180
- */
-
-typedef enum
-{
-	P2P_APPID_SESSION   = 0x0,        /**< Negotiating session */
-	P2P_APPID_OBJ       = 0x1,        /**< MsnObject (Display or Emoticon) */
-	P2P_APPID_FILE      = 0x2,        /**< File transfer */
-	P2P_APPID_EMOTE     = 0xB,        /**< CustomEmoticon */
-	P2P_APPID_DISPLAY   = 0xC         /**< Display Image */
-} MsnP2PAppId;
-
-typedef enum
-{
-	P2P_OPCODE_NONE = 0x00,
-	P2P_OPCODE_SYN  = 0x01,
-	P2P_OPCODE_RAK  = 0x02
-} MsnP2Pv2OpCode;
-
-MsnP2PInfo *
-msn_p2p_info_new(MsnP2PVersion version);
-
-MsnP2PInfo *
-msn_p2p_info_dup(MsnP2PInfo *info);
-
-void
-msn_p2p_info_free(MsnP2PInfo *info);
-
-size_t
-msn_p2p_header_from_wire(MsnP2PInfo *info, const char *wire, size_t max_len);
-
-char *
-msn_p2p_header_to_wire(MsnP2PInfo *info, size_t *len);
-
-size_t
-msn_p2p_footer_from_wire(MsnP2PInfo *info, const char *wire);
-
-char *
-msn_p2p_footer_to_wire(MsnP2PInfo *info, size_t *len);
-
-void
-msn_p2p_info_to_string(MsnP2PInfo *info, GString *str);
-
-gboolean
-msn_p2p_msg_is_data(const MsnP2PInfo *info);
-
-gboolean
-msn_p2p_info_is_valid(MsnP2PInfo *info);
-
-gboolean
-msn_p2p_info_is_first(MsnP2PInfo *info);
-
-gboolean
-msn_p2p_info_is_final(MsnP2PInfo *info);
-
-void
-msn_p2p_info_create_ack(MsnP2PInfo *old_info, MsnP2PInfo *new_info);
-
-gboolean
-msn_p2p_info_require_ack(MsnP2PInfo *info);
-
-gboolean
-msn_p2p_info_is_ack(MsnP2PInfo *info);
-
-void
-msn_p2p_info_init_first(MsnP2PInfo *new_info, MsnP2PInfo *old_info);
-
-guint32
-msn_p2p_info_get_session_id(MsnP2PInfo *info);
-
-guint32
-msn_p2p_info_get_id(MsnP2PInfo *info);
-
-guint64
-msn_p2p_info_get_offset(MsnP2PInfo *info);
-
-guint64
-msn_p2p_info_get_total_size(MsnP2PInfo *info);
-
-guint32
-msn_p2p_info_get_length(MsnP2PInfo *info);
-
-guint32
-msn_p2p_info_get_flags(MsnP2PInfo *info);
-
-guint32
-msn_p2p_info_get_ack_id(MsnP2PInfo *info);
-
-guint32
-msn_p2p_info_get_ack_sub_id(MsnP2PInfo *info);
-
-guint64
-msn_p2p_info_get_ack_size(MsnP2PInfo *info);
-
-guint32
-msn_p2p_info_get_app_id(MsnP2PInfo *info);
-
-void
-msn_p2p_info_set_session_id(MsnP2PInfo *info, guint32 session_id);
-
-void
-msn_p2p_info_set_id(MsnP2PInfo *info, guint32 id);
-
-void
-msn_p2p_info_set_offset(MsnP2PInfo *info, guint64 offset);
-
-void
-msn_p2p_info_set_total_size(MsnP2PInfo *info, guint64 total_size);
-
-void
-msn_p2p_info_set_length(MsnP2PInfo *info, guint32 length);
-
-void
-msn_p2p_info_set_flags(MsnP2PInfo *info, guint32 flags);
-
-void
-msn_p2p_info_set_ack_id(MsnP2PInfo *info, guint32 ack_id);
-
-void
-msn_p2p_info_set_ack_sub_id(MsnP2PInfo *info, guint32 ack_sub_id);
-
-void
-msn_p2p_info_set_ack_size(MsnP2PInfo *info, guint64 ack_size);
-
-void
-msn_p2p_info_set_app_id(MsnP2PInfo *info, guint32 app_id);
-
-#endif /* MSN_P2P_H */
--- a/libpurple/protocols/msn/page.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/**
- * @file page.c Paging functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#include "msn.h"
-#include "page.h"
-
-MsnPage *
-msn_page_new(void)
-{
-	MsnPage *page;
-
-	page = g_new0(MsnPage, 1);
-
-	return page;
-}
-
-void
-msn_page_destroy(MsnPage *page)
-{
-	g_return_if_fail(page != NULL);
-
-	g_free(page->body);
-	g_free(page->from_location);
-	g_free(page->from_phone);
-
-	g_free(page);
-}
-
-char *
-msn_page_gen_payload(const MsnPage *page, size_t *ret_size)
-{
-	char *str;
-	char *body;
-
-	g_return_val_if_fail(page != NULL, NULL);
-
-	body = g_markup_escape_text(msn_page_get_body(page), -1);
-	str = g_strdup_printf(
-			"<TEXT xml:space=\"preserve\" enc=\"utf-8\">%s</TEXT>",
-			body);
-	g_free(body);
-
-	if (ret_size != NULL)
-		*ret_size = strlen(str);
-
-	return str;
-}
-
-void
-msn_page_set_body(MsnPage *page, const char *body)
-{
-	g_return_if_fail(page != NULL);
-	g_return_if_fail(body != NULL);
-
-	g_free(page->body);
-	page->body = g_strdup(body);
-}
-
-const char *
-msn_page_get_body(const MsnPage *page)
-{
-	g_return_val_if_fail(page != NULL, NULL);
-
-	return page->body;
-}
--- a/libpurple/protocols/msn/page.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/**
- * @file page.h Paging functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_PAGE_H
-#define MSN_PAGE_H
-
-typedef struct _MsnPage MsnPage;
-
-#include "session.h"
-
-/**
- * A page.
- */
-struct _MsnPage
-{
-	char *from_location;
-	char *from_phone;
-
-	char *body;
-};
-
-/**
- * Creates a new, empty page.
- *
- * @return A new page.
- */
-MsnPage *msn_page_new(void);
-
-/**
- * Destroys a page.
- */
-void msn_page_destroy(MsnPage *page);
-
-/**
- * Generates the payload data of a page.
- *
- * @param page     The page.
- * @param ret_size The returned size of the payload.
- *
- * @return The payload data of a page.
- */
-char *msn_page_gen_payload(const MsnPage *page, size_t *ret_size);
-
-/**
- * Sets the body of a page.
- *
- * @param page  The page.
- * @param body The body of the page.
- */
-void msn_page_set_body(MsnPage *page, const char *body);
-
-/**
- * Returns the body of the page.
- *
- * @param page The page.
- *
- * @return The body of the page.
- */
-const char *msn_page_get_body(const MsnPage *page);
-
-#endif /* MSN_PAGE_H */
--- a/libpurple/protocols/msn/sbconn.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +0,0 @@
-/**
- * @file sbconn.c MSN Switchboard Connection
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-
-#include "msg.h"
-#include "sbconn.h"
-
-void msn_sbconn_send_part(MsnSlpLink *slplink, MsnSlpMessagePart *part)
-{
-	MsnMessage *msg;
-	const char *passport;
-	char *data;
-	size_t size;
-
-	msg = msn_message_new_msnslp();
-
-	passport = purple_normalize(slplink->session->account, slplink->remote_user);
-	msn_message_set_header(msg, "P2P-Dest", passport);
-
-	msg->part = msn_slpmsgpart_ref(part);
-	data = msn_slpmsgpart_serialize(part, &size);
-	msn_message_set_bin_data(msg, data, size);
-	g_free(data);
-
-	if (slplink->swboard == NULL)
-	{
-		slplink->swboard = msn_session_get_swboard(slplink->session,
-				slplink->remote_user, MSN_SB_FLAG_FT);
-
-		g_return_if_fail(slplink->swboard != NULL);
-
-		/* If swboard is destroyed we will be too */
-		slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink);
-	}
-
-	msn_switchboard_send_msg(slplink->swboard, msg, TRUE);
-	msn_message_unref(msg);
-}
-
-/** Called when a message times out. */
-static void
-msg_timeout(MsnCmdProc *cmdproc, MsnTransaction *trans)
-{
-	MsnMessage *msg;
-
-	msg = trans->data;
-
-	msg_error_helper(cmdproc, msg, MSN_MSG_ERROR_TIMEOUT);
-}
-
-static void
-release_msg(MsnSwitchBoard *swboard, MsnMessage *msg)
-{
-	MsnCmdProc *cmdproc;
-	MsnTransaction *trans;
-	char *payload;
-	gsize payload_len;
-	char flag;
-
-	g_return_if_fail(swboard != NULL);
-	g_return_if_fail(msg     != NULL);
-
-	cmdproc = swboard->cmdproc;
-
-	payload = msn_message_gen_payload(msg, &payload_len);
-
-	if (purple_debug_is_verbose()) {
-		purple_debug_info("msn", "SB length:{%" G_GSIZE_FORMAT "}\n", payload_len);
-		msn_message_show_readable(msg, "SB SEND", FALSE);
-	}
-
-	flag = msn_message_get_flag(msg);
-	trans = msn_transaction_new(cmdproc, "MSG", "%c %" G_GSIZE_FORMAT,
-								flag, payload_len);
-
-	/* Data for callbacks */
-	msn_transaction_set_data(trans, msg);
-
-	if (flag != 'U') {
-		if (msg->type == MSN_MSG_TEXT)
-		{
-			msg->ack_ref = TRUE;
-			msn_message_ref(msg);
-			swboard->ack_list = g_list_append(swboard->ack_list, msg);
-			msn_transaction_set_timeout_cb(trans, msg_timeout);
-		}
-		else if (msg->type == MSN_MSG_SLP)
-		{
-			msg->ack_ref = TRUE;
-			msn_message_ref(msg);
-			swboard->ack_list = g_list_append(swboard->ack_list, msg);
-			msn_transaction_set_timeout_cb(trans, msg_timeout);
-#if 0
-			if (msg->ack_cb != NULL)
-			{
-				msn_transaction_add_cb(trans, "ACK", msg_ack);
-				msn_transaction_add_cb(trans, "NAK", msg_nak);
-			}
-#endif
-		}
-	}
-
-	trans->payload = payload;
-	trans->payload_len = payload_len;
-
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-static void
-queue_msg(MsnSwitchBoard *swboard, MsnMessage *msg)
-{
-	g_return_if_fail(swboard != NULL);
-	g_return_if_fail(msg     != NULL);
-
-	purple_debug_info("msn", "Appending message to queue.\n");
-
-	g_queue_push_tail(swboard->msg_queue, msg);
-
-	msn_message_ref(msg);
-}
-
-void
-msn_sbconn_process_queue(MsnSwitchBoard *swboard)
-{
-	MsnMessage *msg;
-
-	g_return_if_fail(swboard != NULL);
-
-	purple_debug_info("msn", "Processing queue\n");
-
-	while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL)
-	{
-		purple_debug_info("msn", "Sending message\n");
-		release_msg(swboard, msg);
-		msn_message_unref(msg);
-	}
-}
-
-void
-msn_switchboard_send_msg(MsnSwitchBoard *swboard, MsnMessage *msg,
-						 gboolean queue)
-{
-	g_return_if_fail(swboard != NULL);
-	g_return_if_fail(msg     != NULL);
-
-	purple_debug_info("msn", "switchboard send msg..\n");
-	if (msn_switchboard_can_send(swboard))
-		release_msg(swboard, msg);
-	else if (queue)
-		queue_msg(swboard, msg);
-}
--- a/libpurple/protocols/msn/sbconn.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/**
- * @file sbconn.h MSN Switchboard Connection
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#ifndef MSN_SBCONN_H
-#define MSN_SBCONN_H
-
-#include "msg.h"
-#include "slplink.h"
-
-#define MSN_SBCONN_MAX_SIZE 1202
-
-void msn_sbconn_send_part(MsnSlpLink *slplink, MsnSlpMessagePart *part);
-
-void msn_switchboard_send_msg(MsnSwitchBoard *swboard, MsnMessage *msg,
-						 gboolean queue);
-
-void
-msn_sbconn_process_queue(MsnSwitchBoard *swboard);
-
-#endif /* MSN_SBCONN_H */
--- a/libpurple/protocols/msn/servconn.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,608 +0,0 @@
-/**
- * @file servconn.c Server connection functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#include "internal.h"
-#include "debug.h"
-
-#include "servconn.h"
-#include "error.h"
-
-static void read_cb(gpointer data, gint source, PurpleInputCondition cond);
-static void servconn_timeout_renew(MsnServConn *servconn);
-
-/**************************************************************************
- * Main
- **************************************************************************/
-
-MsnServConn *
-msn_servconn_new(MsnSession *session, MsnServConnType type)
-{
-	MsnServConn *servconn;
-
-	g_return_val_if_fail(session != NULL, NULL);
-
-	servconn = g_new0(MsnServConn, 1);
-
-	servconn->type = type;
-
-	servconn->session = session;
-	servconn->cmdproc = msn_cmdproc_new(session);
-	servconn->cmdproc->servconn = servconn;
-
-	servconn->httpconn = msn_httpconn_new(servconn);
-
-	servconn->num = session->servconns_count++;
-
-	servconn->tx_buf = purple_circ_buffer_new(MSN_BUF_LEN);
-	servconn->tx_handler = 0;
-	servconn->timeout_sec = 0;
-	servconn->timeout_handle = 0;
-
-	servconn->fd = -1;
-
-	return servconn;
-}
-
-void
-msn_servconn_destroy(MsnServConn *servconn)
-{
-	g_return_if_fail(servconn != NULL);
-
-	if (servconn->processing)
-	{
-		servconn->wasted = TRUE;
-		return;
-	}
-
-	msn_servconn_disconnect(servconn);
-
-	if (servconn->destroy_cb)
-		servconn->destroy_cb(servconn);
-
-	if (servconn->httpconn != NULL)
-		msn_httpconn_destroy(servconn->httpconn);
-
-	g_free(servconn->host);
-
-	purple_circ_buffer_destroy(servconn->tx_buf);
-	if (servconn->tx_handler > 0)
-		purple_input_remove(servconn->tx_handler);
-	if (servconn->timeout_handle > 0)
-		purple_timeout_remove(servconn->timeout_handle);
-
-	msn_cmdproc_destroy(servconn->cmdproc);
-	g_free(servconn);
-}
-
-void
-msn_servconn_set_connect_cb(MsnServConn *servconn,
-							void (*connect_cb)(MsnServConn *))
-{
-	g_return_if_fail(servconn != NULL);
-	servconn->connect_cb = connect_cb;
-}
-
-void
-msn_servconn_set_disconnect_cb(MsnServConn *servconn,
-							   void (*disconnect_cb)(MsnServConn *))
-{
-	g_return_if_fail(servconn != NULL);
-
-	servconn->disconnect_cb = disconnect_cb;
-}
-
-void
-msn_servconn_set_destroy_cb(MsnServConn *servconn,
-							void (*destroy_cb)(MsnServConn *))
-{
-	g_return_if_fail(servconn != NULL);
-
-	servconn->destroy_cb = destroy_cb;
-}
-
-/**************************************************************************
- * Utility
- **************************************************************************/
-
-void
-msn_servconn_got_error(MsnServConn *servconn, MsnServConnError error,
-                       const char *reason)
-{
-	MsnSession *session = servconn->session;
-	MsnServConnType type = servconn->type;
-
-	const char *names[] = { "Notification", "Switchboard" };
-	const char *name;
-
-	name = names[type];
-
-	if (reason == NULL) {
-		switch (error)
-		{
-			case MSN_SERVCONN_ERROR_CONNECT:
-				reason = _("Unable to connect"); break;
-			case MSN_SERVCONN_ERROR_WRITE:
-				reason = _("Writing error"); break;
-			case MSN_SERVCONN_ERROR_READ:
-				reason = _("Reading error"); break;
-			default:
-				reason = _("Unknown error"); break;
-		}
-	}
-
-	purple_debug_error("msn", "Connection error from %s server (%s): %s\n",
-					 name, servconn->host, reason);
-
-	if (type == MSN_SERVCONN_SB)
-	{
-		MsnSwitchBoard *swboard;
-		swboard = servconn->cmdproc->data;
-		if (swboard != NULL)
-			swboard->error = MSN_SB_ERROR_CONNECTION;
-	}
-
-	/* servconn->disconnect_cb may destroy servconn, so don't use it again */
-	msn_servconn_disconnect(servconn);
-
-	if (type == MSN_SERVCONN_NS)
-	{
-		char *tmp = g_strdup_printf(_("Connection error from %s server:\n%s"),
-		                            name, reason);
-		msn_session_set_error(session, MSN_ERROR_SERVCONN, tmp);
-		g_free(tmp);
-	}
-}
-
-/**************************************************************************
- * Connect
- **************************************************************************/
-
-static void
-connect_cb(gpointer data, gint source, const char *error_message)
-{
-	MsnServConn *servconn;
-
-	servconn = data;
-	servconn->connect_data = NULL;
-
-	servconn->fd = source;
-
-	if (source >= 0)
-	{
-		servconn->connected = TRUE;
-
-		/* Someone wants to know we connected. */
-		servconn->connect_cb(servconn);
-		servconn->inpa = purple_input_add(servconn->fd, PURPLE_INPUT_READ,
-			read_cb, data);
-		servconn_timeout_renew(servconn);
-	}
-	else
-	{
-		purple_debug_error("msn", "Connection error: %s\n", error_message);
-		msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_CONNECT, error_message);
-	}
-}
-
-gboolean
-msn_servconn_connect(MsnServConn *servconn, const char *host, int port, gboolean force)
-{
-	MsnSession *session;
-
-	g_return_val_if_fail(servconn != NULL, FALSE);
-	g_return_val_if_fail(host     != NULL, FALSE);
-	g_return_val_if_fail(port      > 0,    FALSE);
-
-	session = servconn->session;
-
-	if (servconn->connected)
-		msn_servconn_disconnect(servconn);
-
-	g_free(servconn->host);
-	servconn->host = g_strdup(host);
-
-	if (session->http_method)
-	{
-		/* HTTP Connection. */
-
-		if (!servconn->httpconn->connected || force)
-			if (!msn_httpconn_connect(servconn->httpconn, host, port))
-				return FALSE;
-
-		servconn->connected = TRUE;
-		servconn->httpconn->virgin = TRUE;
-		servconn_timeout_renew(servconn);
-
-		/* Someone wants to know we connected. */
-		servconn->connect_cb(servconn);
-
-		return TRUE;
-	}
-
-	servconn->connect_data = purple_proxy_connect(NULL, session->account,
-			host, port, connect_cb, servconn);
-
-	return (servconn->connect_data != NULL);
-}
-
-void
-msn_servconn_disconnect(MsnServConn *servconn)
-{
-	g_return_if_fail(servconn != NULL);
-
-	if (servconn->connect_data != NULL)
-	{
-		purple_proxy_connect_cancel(servconn->connect_data);
-		servconn->connect_data = NULL;
-	}
-
-	if (!servconn->connected)
-	{
-		/* We could not connect. */
-		if (servconn->disconnect_cb != NULL)
-			servconn->disconnect_cb(servconn);
-
-		return;
-	}
-
-	if (servconn->session->http_method)
-	{
-		/* Fake disconnection. */
-		if (servconn->disconnect_cb != NULL)
-			servconn->disconnect_cb(servconn);
-
-		return;
-	}
-
-	if (servconn->inpa > 0)
-	{
-		purple_input_remove(servconn->inpa);
-		servconn->inpa = 0;
-	}
-
-	if (servconn->timeout_handle > 0)
-	{
-		purple_timeout_remove(servconn->timeout_handle);
-		servconn->timeout_handle = 0;
-	}
-
-	close(servconn->fd);
-
-	servconn->rx_buf = NULL;
-	servconn->rx_len = 0;
-	servconn->payload_len = 0;
-
-	servconn->connected = FALSE;
-
-	if (servconn->disconnect_cb != NULL)
-		servconn->disconnect_cb(servconn);
-}
-
-static gboolean
-servconn_idle_timeout_cb(MsnServConn *servconn)
-{
-	servconn->timeout_handle = 0;
-	msn_servconn_disconnect(servconn);
-	return FALSE;
-}
-
-static void
-servconn_timeout_renew(MsnServConn *servconn)
-{
-	if (servconn->timeout_handle) {
-		purple_timeout_remove(servconn->timeout_handle);
-		servconn->timeout_handle = 0;
-	}
-
-	if (servconn->connected && servconn->timeout_sec) {
-		servconn->timeout_handle = purple_timeout_add_seconds(
-			servconn->timeout_sec, (GSourceFunc)servconn_idle_timeout_cb, servconn);
-	}
-}
-
-void
-msn_servconn_set_idle_timeout(MsnServConn *servconn, guint seconds)
-{
-	servconn->timeout_sec = seconds;
-	if (servconn->connected)
-		servconn_timeout_renew(servconn);
-}
-
-static void
-servconn_write_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
-	MsnServConn *servconn = data;
-	gssize ret;
-	int writelen;
-
-	writelen = purple_circ_buffer_get_max_read(servconn->tx_buf);
-
-	if (writelen == 0) {
-		purple_input_remove(servconn->tx_handler);
-		servconn->tx_handler = 0;
-		return;
-	}
-
-	ret = write(servconn->fd, servconn->tx_buf->outptr, writelen);
-
-	if (ret < 0 && errno == EAGAIN)
-		return;
-	else if (ret <= 0) {
-		msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_WRITE, NULL);
-		return;
-	}
-
-	purple_circ_buffer_mark_read(servconn->tx_buf, ret);
-	servconn_timeout_renew(servconn);
-}
-
-gssize
-msn_servconn_write(MsnServConn *servconn, const char *buf, size_t len)
-{
-	gssize ret = 0;
-
-	g_return_val_if_fail(servconn != NULL, 0);
-
-	if (!servconn->session->http_method)
-	{
-		if (servconn->tx_handler == 0) {
-			switch (servconn->type)
-			{
-				case MSN_SERVCONN_NS:
-				case MSN_SERVCONN_SB:
-					ret = write(servconn->fd, buf, len);
-					break;
-#if 0
-				case MSN_SERVCONN_DC:
-					ret = write(servconn->fd, &buf, sizeof(len));
-					ret = write(servconn->fd, buf, len);
-					break;
-#endif
-				default:
-					ret = write(servconn->fd, buf, len);
-					break;
-			}
-		} else {
-			ret = -1;
-			errno = EAGAIN;
-		}
-
-		if (ret < 0 && errno == EAGAIN)
-			ret = 0;
-		if (ret >= 0 && (size_t)ret < len) {
-			if (servconn->tx_handler == 0)
-				servconn->tx_handler = purple_input_add(
-					servconn->fd, PURPLE_INPUT_WRITE,
-					servconn_write_cb, servconn);
-			purple_circ_buffer_append(servconn->tx_buf, buf + ret,
-				len - ret);
-		}
-	}
-	else
-	{
-		ret = msn_httpconn_write(servconn->httpconn, buf, len);
-	}
-
-	if (ret == -1)
-	{
-		msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_WRITE, NULL);
-	}
-
-	servconn_timeout_renew(servconn);
-	return ret;
-}
-
-static void
-read_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
-	MsnServConn *servconn;
-	char buf[MSN_BUF_LEN];
-	gssize len;
-
-	servconn = data;
-
-	if (servconn->type == MSN_SERVCONN_NS)
-		servconn->session->account->gc->last_received = time(NULL);
-
-	len = read(servconn->fd, buf, sizeof(buf) - 1);
-	if (len < 0 && errno == EAGAIN)
-		return;
-	if (len <= 0) {
-		purple_debug_error("msn", "servconn %03d read error, "
-			"len: %" G_GSSIZE_FORMAT ", errno: %d, error: %s\n",
-			servconn->num, len, errno, g_strerror(errno));
-		msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ, NULL);
-
-		return;
-	}
-
-	buf[len] = '\0';
-
-	servconn->rx_buf = g_realloc(servconn->rx_buf, len + servconn->rx_len + 1);
-	memcpy(servconn->rx_buf + servconn->rx_len, buf, len + 1);
-	servconn->rx_len += len;
-
-	servconn = msn_servconn_process_data(servconn);
-	if (servconn)
-		servconn_timeout_renew(servconn);
-}
-
-MsnServConn *msn_servconn_process_data(MsnServConn *servconn)
-{
-	char *cur, *end, *old_rx_buf;
-	int cur_len;
-
-	end = old_rx_buf = servconn->rx_buf;
-
-	servconn->processing = TRUE;
-
-	do
-	{
-		cur = end;
-
-		if (servconn->payload_len)
-		{
-			if (servconn->rx_len < 0
-				|| servconn->payload_len > (gsize)servconn->rx_len)
-				/* The payload is still not complete. */
-				break;
-
-			cur_len = servconn->payload_len;
-			end += cur_len;
-		}
-		else
-		{
-			end = strstr(cur, "\r\n");
-
-			if (end == NULL)
-				/* The command is still not complete. */
-				break;
-
-			*end = '\0';
-			end += 2;
-			cur_len = end - cur;
-		}
-
-		servconn->rx_len -= cur_len;
-
-		if (servconn->payload_len)
-		{
-			msn_cmdproc_process_payload(servconn->cmdproc, cur, cur_len);
-			servconn->payload_len = 0;
-		}
-		else
-		{
-			msn_cmdproc_process_cmd_text(servconn->cmdproc, cur);
-			servconn->payload_len = servconn->cmdproc->last_cmd->payload_len;
-		}
-	} while (servconn->connected && !servconn->wasted && servconn->rx_len > 0);
-
-	if (servconn->connected && !servconn->wasted)
-	{
-		if (servconn->rx_len > 0)
-			servconn->rx_buf = g_memdup(cur, servconn->rx_len);
-		else
-			servconn->rx_buf = NULL;
-	}
-
-	servconn->processing = FALSE;
-
-	if (servconn->wasted) {
-		msn_servconn_destroy(servconn);
-		servconn = NULL;
-	}
-
-	g_free(old_rx_buf);
-	return servconn;
-}
-
-#if 0
-static int
-create_listener(int port)
-{
-	int fd;
-	int flags;
-	const int on = 1;
-
-#if 0
-	struct addrinfo hints;
-	struct addrinfo *c, *res;
-	char port_str[5];
-
-	snprintf(port_str, sizeof(port_str), "%d", port);
-
-	memset(&hints, 0, sizeof(hints));
-
-	hints.ai_flags = AI_PASSIVE;
-	hints.ai_family = AF_UNSPEC;
-	hints.ai_socktype = SOCK_STREAM;
-
-	if (getaddrinfo(NULL, port_str, &hints, &res) != 0)
-	{
-		purple_debug_error("msn", "Could not get address info: %s.\n",
-						 port_str);
-		return -1;
-	}
-
-	for (c = res; c != NULL; c = c->ai_next)
-	{
-		fd = socket(c->ai_family, c->ai_socktype, c->ai_protocol);
-
-		if (fd < 0)
-			continue;
-
-		setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-
-		if (bind(fd, c->ai_addr, c->ai_addrlen) == 0)
-			break;
-
-		close(fd);
-	}
-
-	if (c == NULL)
-	{
-		purple_debug_error("msn", "Could not find socket: %s.\n", port_str);
-		return -1;
-	}
-
-	freeaddrinfo(res);
-#else
-	struct sockaddr_in sockin;
-
-	fd = socket(AF_INET, SOCK_STREAM, 0);
-
-	if (fd < 0)
-		return -1;
-
-	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) != 0)
-	{
-		close(fd);
-		return -1;
-	}
-
-	memset(&sockin, 0, sizeof(struct sockaddr_in));
-	sockin.sin_family = AF_INET;
-	sockin.sin_port = htons(port);
-
-	if (bind(fd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0)
-	{
-		close(fd);
-		return -1;
-	}
-#endif
-
-	if (listen (fd, 4) != 0)
-	{
-		close (fd);
-		return -1;
-	}
-
-	flags = fcntl(fd, F_GETFL);
-	fcntl(fd, F_SETFL, flags | O_NONBLOCK);
-#ifndef _WIN32
-	fcntl(fd, F_SETFD, FD_CLOEXEC);
-#endif
-
-	return fd;
-}
-#endif
--- a/libpurple/protocols/msn/servconn.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,193 +0,0 @@
-/**
- * @file servconn.h Server connection functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_SERVCONN_H
-#define MSN_SERVCONN_H
-
-typedef struct _MsnServConn MsnServConn;
-
-/**
- * Connection error types.
- */
-typedef enum
-{
-	MSN_SERVCONN_ERROR_NONE,
-	MSN_SERVCONN_ERROR_CONNECT,
-	MSN_SERVCONN_ERROR_WRITE,
-	MSN_SERVCONN_ERROR_READ
-} MsnServConnError;
-
-/**
- * Connection types.
- */
-typedef enum
-{
-	MSN_SERVCONN_NS,
-	MSN_SERVCONN_SB
-} MsnServConnType;
-
-#include "internal.h"
-#include "proxy.h"
-
-#include "cmdproc.h"
-#include "httpconn.h"
-#include "session.h"
-
-/**
- * A Connection.
- */
-struct _MsnServConn
-{
-	MsnServConnType type; /**< The type of this connection. */
-	MsnSession *session;  /**< The MSN session of this connection. */
-	MsnCmdProc *cmdproc;  /**< The command processor of this connection. */
-
-	PurpleProxyConnectData *connect_data;
-
-	gboolean connected;   /**< A flag that states if it's connected. */
-	gboolean processing;  /**< A flag that states if something is working
-							with this connection. */
-	gboolean wasted;      /**< A flag that states if it should be destroyed. */
-
-	char *host; /**< The host this connection is connected or should be
-				  connected to. */
-	int num; /**< A number id of this connection. */
-
-	MsnHttpConn *httpconn; /**< The HTTP connection this connection should use. */
-
-	int fd; /**< The connection's file descriptor. */
-	int inpa; /**< The connection's input handler. */
-
-	char *rx_buf; /**< The receive buffer. */
-	int rx_len; /**< The receive buffer lenght. */
-
-	size_t payload_len; /**< The length of the payload.
-						  It's only set when we've received a command that
-						  has a payload. */
-
-	PurpleCircBuffer *tx_buf;
-	guint tx_handler;
-	guint timeout_sec;
-	guint timeout_handle;
-
-	void (*connect_cb)(MsnServConn *); /**< The callback to call when connecting. */
-	void (*disconnect_cb)(MsnServConn *); /**< The callback to call when disconnecting. */
-	void (*destroy_cb)(MsnServConn *); /**< The callback to call when destroying. */
-};
-
-/**
- * Creates a new connection object.
- *
- * @param session The session.
- * @param type The type of the connection.
- */
-MsnServConn *msn_servconn_new(MsnSession *session, MsnServConnType type);
-
-/**
- * Destroys a connection object.
- *
- * @param servconn The connection.
- */
-void msn_servconn_destroy(MsnServConn *servconn);
-
-/**
- * Connects to a host.
- *
- * @param servconn The connection.
- * @param host The host.
- * @param port The port.
- * @param force Force this servconn to connect to a new server.
- */
-gboolean msn_servconn_connect(MsnServConn *servconn, const char *host, int port,
-                              gboolean force);
-
-/**
- * Disconnects.
- *
- * @param servconn The connection.
- */
-void msn_servconn_disconnect(MsnServConn *servconn);
-
-/**
- * Sets the connect callback.
- *
- * @param servconn The servconn.
- * @param connect_cb The connect callback.
- */
-void msn_servconn_set_connect_cb(MsnServConn *servconn,
-								 void (*connect_cb)(MsnServConn *));
-/**
- * Sets the disconnect callback.
- *
- * @param servconn The servconn.
- * @param disconnect_cb The disconnect callback.
- */
-void msn_servconn_set_disconnect_cb(MsnServConn *servconn,
-									void (*disconnect_cb)(MsnServConn *));
-/**
- * Sets the destroy callback.
- *
- * @param servconn The servconn that's being destroyed.
- * @param destroy_cb The destroy callback.
- */
-void msn_servconn_set_destroy_cb(MsnServConn *servconn,
-								 void (*destroy_cb)(MsnServConn *));
-
-/**
- * Writes a chunck of data to the servconn.
- *
- * @param servconn The servconn.
- * @param buf The data to write.
- * @param size The size of the data.
- */
-gssize msn_servconn_write(MsnServConn *servconn, const char *buf,
-						  size_t size);
-
-/**
- * Function to call whenever an error related to a switchboard occurs.
- *
- * @param servconn The servconn.
- * @param error The error that happened.
- */
-void msn_servconn_got_error(MsnServConn *servconn, MsnServConnError error,
-                            const char *reason);
-
-/**
- * Process the data in servconn->rx_buf.  This is called after reading
- * data from the socket.
- *
- * @param servconn The servconn.
- *
- * @return @c NULL if servconn was destroyed, 'servconn' otherwise.
- */
-MsnServConn *msn_servconn_process_data(MsnServConn *servconn);
-
-/**
- * Set a idle timeout fot this servconn
- *
- * @param servconn The servconn
- * @param seconds The idle timeout in seconds
- */
-void msn_servconn_set_idle_timeout(MsnServConn *servconn, guint seconds);
-
-#endif /* MSN_SERVCONN_H */
--- a/libpurple/protocols/msn/session.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,500 +0,0 @@
-/**
- * @file session.c MSN session functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-
-#include "error.h"
-#include "msnutils.h"
-#include "session.h"
-#include "notification.h"
-#include "oim.h"
-
-MsnSession *
-msn_session_new(PurpleAccount *account)
-{
-	MsnSession *session;
-
-	g_return_val_if_fail(account != NULL, NULL);
-
-	session = g_new0(MsnSession, 1);
-
-	session->account = account;
-	session->notification = msn_notification_new(session);
-	session->userlist = msn_userlist_new(session);
-
-	session->user = msn_user_new(session->userlist,
-								 purple_account_get_username(account), NULL);
-	msn_userlist_add_user(session->userlist, session->user);
-	session->oim = msn_oim_new(session);
-
-	session->protocol_ver = 0;
-	session->enable_mpop = TRUE; /* Default only */
-
-	session->guid = rand_guid();
-
-	return session;
-}
-
-void
-msn_session_destroy(MsnSession *session)
-{
-	g_return_if_fail(session != NULL);
-
-	session->destroying = TRUE;
-
-	while (session->url_datas) {
-		purple_util_fetch_url_cancel(session->url_datas->data);
-		session->url_datas = g_slist_delete_link(session->url_datas, session->url_datas);
-	}
-
-	if (session->connected)
-		msn_session_disconnect(session);
-
-	if (session->soap_cleanup_handle)
-		purple_timeout_remove(session->soap_cleanup_handle);
-
-	if (session->soap_table != NULL)
-		g_hash_table_destroy(session->soap_table);
-
-	while (session->slplinks != NULL)
-		msn_slplink_unref(session->slplinks->data);
-
-	while (session->switches != NULL)
-		msn_switchboard_destroy(session->switches->data);
-
-	if (session->oim != NULL)
-		msn_oim_destroy(session->oim);
-
-	if (session->nexus != NULL)
-		msn_nexus_destroy(session->nexus);
-
-	if (session->user != NULL)
-		msn_user_unref(session->user);
-
-	if (session->notification != NULL)
-		msn_notification_destroy(session->notification);
-
-	msn_userlist_destroy(session->userlist);
-
-	g_free(session->psm);
-	g_free(session->guid);
-	g_free(session->abch_cachekey);
-#if 0
-	g_free(session->blocked_text);
-#endif
-
-	g_free(session->passport_info.sid);
-	g_free(session->passport_info.mspauth);
-	g_free(session->passport_info.client_ip);
-	g_free(session->passport_info.mail_url);
-
-	g_free(session);
-}
-
-gboolean
-msn_session_connect(MsnSession *session, const char *host, int port,
-					gboolean http_method)
-{
-	g_return_val_if_fail(session != NULL, FALSE);
-	g_return_val_if_fail(!session->connected, TRUE);
-
-	session->connected = TRUE;
-	session->http_method = http_method;
-
-	if (session->notification == NULL)
-	{
-		purple_debug_error("msn", "This shouldn't happen\n");
-		g_return_val_if_reached(FALSE);
-	}
-
-	return msn_notification_connect(session->notification, host, port);
-}
-
-void
-msn_session_disconnect(MsnSession *session)
-{
-	g_return_if_fail(session != NULL);
-
-	if (!session->connected)
-		return;
-
-	if (session->login_timeout) {
-		purple_timeout_remove(session->login_timeout);
-		session->login_timeout = 0;
-	}
-
-	session->connected = FALSE;
-
-	while (session->switches != NULL)
-		msn_switchboard_close(session->switches->data);
-
-	if (session->notification != NULL)
-		msn_notification_close(session->notification);
-}
-
-/* TODO: This must go away when conversation is redesigned */
-MsnSwitchBoard *
-msn_session_find_swboard(MsnSession *session, const char *username)
-{
-	GList *l;
-
-	g_return_val_if_fail(session  != NULL, NULL);
-	g_return_val_if_fail(username != NULL, NULL);
-
-	for (l = session->switches; l != NULL; l = l->next)
-	{
-		MsnSwitchBoard *swboard;
-
-		swboard = l->data;
-
-		if ((swboard->im_user != NULL) && !strcmp(username, swboard->im_user))
-			return swboard;
-	}
-
-	return NULL;
-}
-
-static PurpleConversation *
-msn_session_get_conv(MsnSession *session,const char *passport)
-{
-	PurpleAccount *account;
-	PurpleConversation * conv;
-
-	g_return_val_if_fail(session != NULL, NULL);
-	account = session->account;
-
-	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
-									passport, account);
-	if(conv == NULL){
-		conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, passport);
-	}
-	return conv;
-}
-
-/* put Message to User Conversation
- *
- * 	passport - the one want to talk to you
- */
-void
-msn_session_report_user(MsnSession *session,const char *passport,const char *msg,PurpleMessageFlags flags)
-{
-	PurpleConversation * conv;
-
-	if ((conv = msn_session_get_conv(session,passport)) != NULL){
-		purple_conversation_write(conv, NULL, msg, flags, time(NULL));
-	}
-}
-
-MsnSwitchBoard *
-msn_session_find_swboard_with_conv(MsnSession *session, PurpleConversation *conv)
-{
-	GList *l;
-
-	g_return_val_if_fail(session  != NULL, NULL);
-	g_return_val_if_fail(conv != NULL, NULL);
-
-	for (l = session->switches; l != NULL; l = l->next)
-	{
-		MsnSwitchBoard *swboard;
-
-		swboard = l->data;
-
-		if (swboard->conv == conv)
-			return swboard;
-	}
-
-	return NULL;
-}
-
-MsnSwitchBoard *
-msn_session_find_swboard_with_id(const MsnSession *session, int chat_id)
-{
-	GList *l;
-
-	g_return_val_if_fail(session != NULL, NULL);
-	g_return_val_if_fail(chat_id >= 0,    NULL);
-
-	for (l = session->switches; l != NULL; l = l->next)
-	{
-		MsnSwitchBoard *swboard;
-
-		swboard = l->data;
-
-		if (swboard->chat_id == chat_id)
-			return swboard;
-	}
-
-	return NULL;
-}
-
-MsnSwitchBoard *
-msn_session_get_swboard(MsnSession *session, const char *username,
-						MsnSBFlag flag)
-{
-	MsnSwitchBoard *swboard;
-
-	g_return_val_if_fail(session != NULL, NULL);
-
-	swboard = msn_session_find_swboard(session, username);
-
-	if (swboard == NULL)
-	{
-		swboard = msn_switchboard_new(session);
-		swboard->im_user = g_strdup(username);
-		if (msn_switchboard_request(swboard))
-			msn_switchboard_request_add_user(swboard, username);
-		else
-			return NULL;
-	}
-
-	swboard->flag |= flag;
-
-	return swboard;
-}
-
-static gboolean
-msn_login_timeout_cb(gpointer data)
-{
-	MsnSession *session = data;
-	/* This forces the login process to finish, even though we haven't heard
-	   a response for our FQY requests yet. We'll at least end up online to the
-	   people we've already added. The rest will follow later. */
-	msn_session_finish_login(session);
-	session->login_timeout = 0;
-	return FALSE;
-}
-
-void
-msn_session_activate_login_timeout(MsnSession *session)
-{
-	if (!session->logged_in && session->connected) {
-		if (session->login_timeout)
-			purple_timeout_remove(session->login_timeout);
-		session->login_timeout =
-			purple_timeout_add_seconds(MSN_LOGIN_FQY_TIMEOUT,
-			                           msn_login_timeout_cb, session);
-	}
-}
-
-static void
-msn_session_sync_users(MsnSession *session)
-{
-	PurpleConnection *gc = purple_account_get_connection(session->account);
-	GList *to_remove = NULL;
-	GSList *buddies;
-
-	g_return_if_fail(gc != NULL);
-
-	/* The core used to use msn_add_buddy to add all buddies before
-	 * being logged in. This no longer happens, so we manually iterate
-	 * over the whole buddy list to identify sync issues.
-	 */
-	for (buddies = purple_find_buddies(session->account, NULL); buddies;
-			buddies = g_slist_delete_link(buddies, buddies)) {
-		PurpleBuddy *buddy = buddies->data;
-		const gchar *buddy_name = purple_buddy_get_name(buddy);
-		const gchar *group_name = purple_group_get_name(purple_buddy_get_group(buddy));
-		MsnUser *remote_user;
-		gboolean found = FALSE;
-
-		remote_user = msn_userlist_find_user(session->userlist, buddy_name);
-		if (remote_user && remote_user->list_op & MSN_LIST_FL_OP) {
-			GList *l;
-			for (l = remote_user->group_ids; l; l = l->next) {
-				const char *name = msn_userlist_find_group_name(remote_user->userlist, l->data);
-				if (name && !g_ascii_strcasecmp(group_name, name)) {
-					found = TRUE;
-					break;
-				}
-			}
-
-			/* We don't care if they're in a different group, as long as they're on the
-			 * list somewhere. If we check for the group, we cause pain, agony and
-			 * suffering for people who decide to re-arrange their buddy list elsewhere.
-			 */
-			if (!found) {
-				if ((remote_user == NULL) || !(remote_user->list_op & MSN_LIST_FL_OP)) {
-					/* The user is not on the server list */
-					msn_error_sync_issue(session, buddy_name, group_name);
-				} else {
-					/* The user is not in that group on the server list */
-					to_remove = g_list_prepend(to_remove, buddy);
-				}
-			}
-		}
-	}
-
-	if (to_remove != NULL) {
-		g_list_foreach(to_remove, (GFunc)purple_blist_remove_buddy, NULL);
-		g_list_free(to_remove);
-	}
-}
-
-void
-msn_session_set_error(MsnSession *session, MsnErrorType error,
-					  const char *info)
-{
-	PurpleConnection *gc;
-	PurpleConnectionError reason;
-	char *msg;
-
-	if (session->destroying)
-		return;
-
-	gc = purple_account_get_connection(session->account);
-
-	switch (error)
-	{
-		case MSN_ERROR_SERVCONN:
-			reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-			msg = g_strdup(info);
-			break;
-		case MSN_ERROR_UNSUPPORTED_PROTOCOL:
-			reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-			msg = g_strdup(_("Our protocol is not supported by the "
-							 "server"));
-			break;
-		case MSN_ERROR_HTTP_MALFORMED:
-			reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-			msg = g_strdup(_("Error parsing HTTP"));
-			break;
-		case MSN_ERROR_SIGN_OTHER:
-			reason = PURPLE_CONNECTION_ERROR_NAME_IN_USE;
-			msg = g_strdup(_("You have signed on from another location"));
-			if (!purple_account_get_remember_password(session->account))
-				purple_account_set_password(session->account, NULL);
-			break;
-		case MSN_ERROR_SERV_UNAVAILABLE:
-			reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-			msg = g_strdup(_("The MSN servers are temporarily "
-							 "unavailable. Please wait and try "
-							 "again."));
-			break;
-		case MSN_ERROR_SERV_DOWN:
-			reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-			msg = g_strdup(_("The MSN servers are going down "
-							 "temporarily"));
-			break;
-		case MSN_ERROR_AUTH:
-			reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
-			msg = g_strdup_printf(_("Unable to authenticate: %s"),
-								  (info == NULL ) ?
-								  _("Unknown error") : info);
-			/* Clear the password if it isn't being saved */
-			if (!purple_account_get_remember_password(session->account))
-				purple_account_set_password(session->account, NULL);
-			break;
-		case MSN_ERROR_BAD_BLIST:
-			reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-			msg = g_strdup_printf(_("Your MSN buddy list is temporarily "
-			                        "unavailable: %s"),
-			                      (info == NULL) ? _("Unknown error") : info);
-			break;
-		default:
-			reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-			msg = g_strdup(_("Unknown error"));
-			break;
-	}
-
-	msn_session_disconnect(session);
-
-	purple_connection_error_reason(gc, reason, msg);
-
-	g_free(msg);
-}
-
-static const char *
-get_login_step_text(MsnSession *session)
-{
-	const char *steps_text[] = {
-		_("Connecting"),
-		_("Handshaking"),
-		_("Transferring"),
-		_("Handshaking"),
-		_("Starting authentication"),
-		_("Getting cookie"),
-		_("Authenticating"),
-		_("Sending cookie"),
-		_("Retrieving buddy list")
-	};
-
-	return steps_text[session->login_step];
-}
-
-void
-msn_session_set_login_step(MsnSession *session, MsnLoginStep step)
-{
-	PurpleConnection *gc;
-
-	/* Prevent the connection progress going backwards, eg. if we get
-	 * transferred several times during login */
-	if (session->login_step >= step)
-		return;
-
-	/* If we're already logged in, we're probably here because of a
-	 * mid-session XFR from the notification server, so we don't want to
-	 * popup the connection progress dialog */
-	if (session->logged_in)
-		return;
-
-	gc = session->account->gc;
-
-	session->login_step = step;
-
-	purple_connection_update_progress(gc, get_login_step_text(session), step,
-									MSN_LOGIN_STEPS);
-}
-
-void
-msn_session_finish_login(MsnSession *session)
-{
-	PurpleAccount *account;
-	PurpleConnection *gc;
-	PurpleStoredImage *img;
-
-	if (!session->logged_in) {
-		account = session->account;
-		gc = purple_account_get_connection(account);
-
-		img = purple_buddy_icons_find_account_icon(session->account);
-		/* TODO: Do we really want to call this if img is NULL? */
-		msn_user_set_buddy_icon(session->user, img);
-		if (img != NULL)
-			purple_imgstore_unref(img);
-
-		session->logged_in = TRUE;
-		purple_connection_set_state(gc, PURPLE_CONNECTED);
-
-		/* Sync users */
-		msn_session_sync_users(session);
-	}
-
-	/* TODO: Send this when updating status instead? */
-	msn_notification_send_uux_endpointdata(session);
-	msn_notification_send_uux_private_endpointdata(session);
-
-	msn_change_status(session);
-}
-
--- a/libpurple/protocols/msn/session.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,245 +0,0 @@
-/**
- * @file session.h MSN session functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_SESSION_H
-#define MSN_SESSION_H
-
-typedef struct _MsnSession MsnSession;
-
-/**
- * Types of errors.
- */
-typedef enum
-{
-	MSN_ERROR_SERVCONN,
-	MSN_ERROR_UNSUPPORTED_PROTOCOL,
-	MSN_ERROR_HTTP_MALFORMED,
-	MSN_ERROR_AUTH,
-	MSN_ERROR_BAD_BLIST,
-	MSN_ERROR_SIGN_OTHER,
-	MSN_ERROR_SERV_DOWN,
-	MSN_ERROR_SERV_UNAVAILABLE
-} MsnErrorType;
-
-/**
- * Login steps.
- */
-typedef enum
-{
-	MSN_LOGIN_STEP_START,
-	MSN_LOGIN_STEP_HANDSHAKE,
-	MSN_LOGIN_STEP_TRANSFER,
-	MSN_LOGIN_STEP_HANDSHAKE2,
-	MSN_LOGIN_STEP_AUTH_START,
-	MSN_LOGIN_STEP_GET_COOKIE,
-	MSN_LOGIN_STEP_AUTH_END,
-	MSN_LOGIN_STEP_SYN,
-	MSN_LOGIN_STEP_END
-} MsnLoginStep;
-
-#define MSN_LOGIN_STEPS MSN_LOGIN_STEP_END
-
-#define MSN_LOGIN_FQY_TIMEOUT 30
-
-#define MSN_LOGIN_FQY_TIMEOUT 30
-
-#include "nexus.h"
-#include "notification.h"
-#include "oim.h"
-#include "switchboard.h"
-#include "user.h"
-#include "userlist.h"
-
-struct _MsnSession
-{
-	PurpleAccount *account;
-	MsnUser *user;
-
-	guint protocol_ver;
-
-	MsnLoginStep login_step; /**< The current step in the login process. */
-
-	gboolean connected:1;
-	gboolean logged_in:1; /**< A temporal flag to ignore local buddy list adds. */
-	gboolean destroying:1; /**< A flag that states if the session is being destroyed. */
-	gboolean http_method:1;
-	gboolean enable_mpop:1; /**< Use Multiple Points of Presence? */
-	int      adl_fqy; /**< A count of ADL/FQY so status is only changed once. */
-	guint    login_timeout; /**< Timeout to force status change if ADL/FQY fail. */
-
-	MsnNotification *notification;
-	MsnNexus        *nexus;
-	MsnOim          *oim;
-	MsnUserList     *userlist;
-	char            *abch_cachekey;
-
-	int servconns_count; /**< The count of server connections. */
-	GList *switches; /**< The list of all the switchboards. */
-	GList *slplinks; /**< The list of all the slplinks. */
-
-	/*psm info*/
-	char *psm;
-
-#if 0
-	char *blocked_text;
-#endif
-
-	struct
-	{
-		char *sid;
-		char *mspauth;
-		unsigned long sl;
-		char *client_ip;
-		int client_port;
-		char *mail_url;
-		gulong mail_timestamp;
-		gboolean email_enabled;
-	} passport_info;
-
-	GHashTable *soap_table;
-	guint soap_cleanup_handle;
-	char *guid;
-
-	GSList *url_datas; /**< PurpleUtilFetchUrlData to be cancelled on exit */
-};
-
-/**
- * Creates an MSN session.
- *
- * @param account The account.
- *
- * @return The new MSN session.
- */
-MsnSession *msn_session_new(PurpleAccount *account);
-
-/**
- * Destroys an MSN session.
- *
- * @param session The MSN session to destroy.
- */
-void msn_session_destroy(MsnSession *session);
-
-/**
- * Connects to and initiates an MSN session.
- *
- * @param session     The MSN session.
- * @param host        The dispatch server host.
- * @param port        The dispatch server port.
- * @param http_method Whether to use or not http_method.
- *
- * @return @c TRUE on success, @c FALSE on failure.
- */
-gboolean msn_session_connect(MsnSession *session,
-							 const char *host, int port,
-							 gboolean http_method);
-
-/**
- * Disconnects from an MSN session.
- *
- * @param session The MSN session.
- */
-void msn_session_disconnect(MsnSession *session);
-
- /**
- * Finds a switchboard with the given username.
- *
- * @param session The MSN session.
- * @param username The username to search for.
- *
- * @return The switchboard, if found.
- */
-MsnSwitchBoard *msn_session_find_swboard(MsnSession *session,
-										 const char *username);
-
- /**
- * Finds a switchboard with the given conversation.
- *
- * @param session The MSN session.
- * @param conv    The conversation to search for.
- *
- * @return The switchboard, if found.
- */
-MsnSwitchBoard *msn_session_find_swboard_with_conv(MsnSession *session,
-												   PurpleConversation *conv);
-/**
- * Finds a switchboard with the given chat ID.
- *
- * @param session The MSN session.
- * @param chat_id The chat ID to search for.
- *
- * @return The switchboard, if found.
- */
-MsnSwitchBoard *msn_session_find_swboard_with_id(const MsnSession *session,
-												 int chat_id);
-
-/**
- * Returns a switchboard to communicate with certain username.
- *
- * @param session The MSN session.
- * @param username The username to search for.
- * @param flag The flag of the switchboard
- *
- * @return The switchboard.
- */
-MsnSwitchBoard *msn_session_get_swboard(MsnSession *session,
-										const char *username, MsnSBFlag flag);
-
-/**
- * Sets an error for the MSN session.
- *
- * @param session The MSN session.
- * @param error The error.
- * @param info Extra information.
- */
-void msn_session_set_error(MsnSession *session, MsnErrorType error,
-						   const char *info);
-
-/**
- * Starts a timeout to initiate finishing login. Sometimes the server ignores
- * our FQY requests, so this forces ourselves online eventually.
- *
- * @param session The MSN session.
- */
-void
-msn_session_activate_login_timeout(MsnSession *session);
-
-/**
- * Sets the current step in the login process.
- *
- * @param session The MSN session.
- * @param step The current step.
- */
-void msn_session_set_login_step(MsnSession *session, MsnLoginStep step);
-
-/**
- * Finish the login proccess.
- *
- * @param session The MSN session.
- */
-void msn_session_finish_login(MsnSession *session);
-
-/*post message to User*/
-void msn_session_report_user(MsnSession *session,const char *passport,
-							const char *msg,PurpleMessageFlags flags);
-
-#endif /* MSN_SESSION_H */
--- a/libpurple/protocols/msn/slp.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,396 +0,0 @@
-/**
- * @file msnslp.c MSNSLP support
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-
-#include "slp.h"
-#include "slpcall.h"
-#include "slpmsg.h"
-#include "msnutils.h"
-
-#include "object.h"
-#include "user.h"
-#include "sbconn.h"
-#include "directconn.h"
-#include "p2p.h"
-#include "xfer.h"
-
-/* seconds to delay between sending buddy icon requests to the server. */
-#define BUDDY_ICON_DELAY 20
-
-typedef struct {
-	MsnSession *session;
-	const char *remote_user;
-	const char *sha1;
-} MsnFetchUserDisplayData;
-
-/**************************************************************************
- * SLP Control
- **************************************************************************/
-
-void
-msn_slp_send_ok(MsnSlpCall *slpcall, const char *branch,
-		const char *type, const char *content)
-{
-	MsnSlpLink *slplink;
-	MsnSlpMessage *slpmsg;
-
-	slplink = slpcall->slplink;
-
-	/* 200 OK */
-	slpmsg = msn_slpmsg_sip_new(slpcall, 1,
-								"MSNSLP/1.0 200 OK",
-								branch, type, content);
-
-	slpmsg->info = "SLP 200 OK";
-	slpmsg->text_body = TRUE;
-
-	msn_slplink_queue_slpmsg(slplink, slpmsg);
-}
-
-void
-msn_slp_send_decline(MsnSlpCall *slpcall, const char *branch,
-			 const char *type, const char *content)
-{
-	MsnSlpLink *slplink;
-	MsnSlpMessage *slpmsg;
-
-	slplink = slpcall->slplink;
-
-	/* 603 Decline */
-	slpmsg = msn_slpmsg_sip_new(slpcall, 1,
-								"MSNSLP/1.0 603 Decline",
-								branch, type, content);
-
-	slpmsg->info = "SLP 603 Decline";
-	slpmsg->text_body = TRUE;
-
-	msn_slplink_queue_slpmsg(slplink, slpmsg);
-}
-
-/**************************************************************************
- * Msg Callbacks
- **************************************************************************/
-
-/*
- * Called on a timeout from end_user_display(). Frees a buddy icon window slow and dequeues the next
- * buddy icon request if there is one.
- */
-static gboolean
-msn_release_buddy_icon_request_timeout(gpointer data)
-{
-	MsnUserList *userlist = (MsnUserList *)data;
-
-	/* Free one window slot */
-	userlist->buddy_icon_window++;
-
-	/* Clear the tag for our former request timer */
-	userlist->buddy_icon_request_timer = 0;
-
-	msn_release_buddy_icon_request(userlist);
-
-	return FALSE;
-}
-
-static void
-got_user_display(MsnSlpCall *slpcall,
-				 const guchar *data, gsize size)
-{
-	const char *info;
-	PurpleAccount *account;
-
-	g_return_if_fail(slpcall != NULL);
-
-	info = slpcall->data_info;
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "Got User Display: %s\n", slpcall->slplink->remote_user);
-
-	account = slpcall->slplink->session->account;
-
-	purple_buddy_icons_set_for_user(account, slpcall->slplink->remote_user,
-								  g_memdup(data, size), size, info);
-}
-
-static void
-end_user_display(MsnSlpCall *slpcall, MsnSession *session)
-{
-	MsnUserList *userlist;
-
-	g_return_if_fail(session != NULL);
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "End User Display\n");
-
-	userlist = session->userlist;
-
-	/* If the session is being destroyed we better stop doing anything. */
-	if (session->destroying)
-		return;
-
-	/* Delay before freeing a buddy icon window slot and requesting the next icon, if appropriate.
-	 * If we don't delay, we'll rapidly hit the MSN equivalent of AIM's rate limiting; the server will
-	 * send us an error 800 like so:
-	 *
-	 * C: NS 000: XFR 21 SB
-	 * S: NS 000: 800 21
-	 */
-	if (userlist->buddy_icon_request_timer) {
-		/* Free the window slot used by this previous request */
-		userlist->buddy_icon_window++;
-
-		/* Clear our pending timeout */
-		purple_timeout_remove(userlist->buddy_icon_request_timer);
-	}
-
-	/* Wait BUDDY_ICON_DELAY s before freeing our window slot and requesting the next icon. */
-	userlist->buddy_icon_request_timer = purple_timeout_add_seconds(BUDDY_ICON_DELAY,
-														  msn_release_buddy_icon_request_timeout, userlist);
-}
-
-static void
-fetched_user_display(PurpleUtilFetchUrlData *url_data, gpointer user_data,
-	const gchar *url_text, gsize len, const gchar *error_message)
-{
-	MsnFetchUserDisplayData *data = user_data;
-	MsnSession *session = data->session;
-
-	session->url_datas = g_slist_remove(session->url_datas, url_data);
-
-	if (url_text) {
-		purple_buddy_icons_set_for_user(session->account, data->remote_user,
-		                                g_memdup(url_text, len), len,
-		                                data->sha1);
-	}
-
-	end_user_display(NULL, session);
-
-	g_free(user_data);
-}
-
-static void
-request_own_user_display(MsnUser *user)
-{
-	PurpleAccount *account;
-	MsnSession *session;
-	MsnObject *my_obj = NULL;
-	gconstpointer data = NULL;
-	const char *info = NULL;
-	size_t len = 0;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "Requesting our own user display\n");
-
-	session = user->userlist->session;
-	account = session->account;
-	my_obj = msn_user_get_object(user);
-
-	if (my_obj != NULL) {
-		PurpleStoredImage *img = msn_object_get_image(my_obj);
-		data = purple_imgstore_get_data(img);
-		len = purple_imgstore_get_size(img);
-		info = msn_object_get_sha1(my_obj);
-	}
-
-	purple_buddy_icons_set_for_user(account, user->passport, g_memdup(data, len), len, info);
-
-	/* Free one window slot */
-	session->userlist->buddy_icon_window++;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "msn_request_user_display(): buddy_icon_window++ yields =%d\n",
-				session->userlist->buddy_icon_window);
-
-	msn_release_buddy_icon_request(session->userlist);
-}
-
-void
-msn_request_user_display(MsnUser *user)
-{
-	PurpleAccount *account;
-	MsnSession *session;
-	MsnSlpLink *slplink;
-	MsnObject *obj;
-	const char *info;
-
-	session = user->userlist->session;
-	account = session->account;
-
-	slplink = msn_session_get_slplink(session, user->passport);
-
-	obj = msn_user_get_object(user);
-
-	info = msn_object_get_sha1(obj);
-
-	if (g_ascii_strcasecmp(user->passport,
-						   purple_account_get_username(account)))
-	{
-		const char *url = msn_object_get_url1(obj);
-		if (url) {
-			MsnFetchUserDisplayData *data = g_new0(MsnFetchUserDisplayData, 1);
-			PurpleUtilFetchUrlData *url_data;
-			data->session = session;
-			data->remote_user = user->passport;
-			data->sha1 = info;
-			url_data = purple_util_fetch_url_len(url, TRUE, NULL, TRUE, 200*1024,
-			                                     fetched_user_display, data);
-			session->url_datas = g_slist_prepend(session->url_datas, url_data);
-		} else {
-			msn_slplink_request_object(slplink, info, got_user_display,
-			                           end_user_display, obj);
-		}
-	}
-	else
-		request_own_user_display(user);
-}
-
-static void
-send_file_cb(MsnSlpCall *slpcall)
-{
-	MsnSlpMessage *slpmsg;
-	PurpleXfer *xfer;
-
-	xfer = (PurpleXfer *)slpcall->xfer;
-	if (purple_xfer_get_status(xfer) >= PURPLE_XFER_STATUS_STARTED)
-		return;
-
-	purple_xfer_ref(xfer);
-	purple_xfer_start(xfer, -1, NULL, 0);
-	if (purple_xfer_get_status(xfer) != PURPLE_XFER_STATUS_STARTED) {
-		purple_xfer_unref(xfer);
-		return;
-	}
-	purple_xfer_unref(xfer);
-
-	slpmsg = msn_slpmsg_file_new(slpcall, purple_xfer_get_size(xfer));
-
-	msn_slplink_send_slpmsg(slpcall->slplink, slpmsg);
-}
-
-static gchar *
-gen_context(PurpleXfer *xfer, const char *file_name, const char *file_path)
-{
-	gsize size = 0;
-	MsnFileContext context;
-	gchar *u8 = NULL;
-	gchar *ret;
-	gunichar2 *uni = NULL;
-	glong currentChar = 0;
-	glong len = 0;
-	const char *preview;
-	gsize preview_len;
-
-	size = purple_xfer_get_size(xfer);
-
-	purple_xfer_prepare_thumbnail(xfer, "png");
-
-	if (!file_name) {
-		gchar *basename = g_path_get_basename(file_path);
-		u8 = purple_utf8_try_convert(basename);
-		g_free(basename);
-		file_name = u8;
-	}
-
-	uni = g_utf8_to_utf16(file_name, -1, NULL, &len, NULL);
-
-	if (u8) {
-		g_free(u8);
-		file_name = NULL;
-		u8 = NULL;
-	}
-
-	preview = purple_xfer_get_thumbnail(xfer, &preview_len);
-
-	context.length = MSN_FILE_CONTEXT_SIZE;
-	context.version = 2; /* V.3 contains additional unnecessary data */
-	context.file_size = size;
-	if (preview)
-		context.type = 0;
-	else
-		context.type = 1;
-
-	len = MIN(len, MAX_FILE_NAME_LEN);
-	for (currentChar = 0; currentChar < len; currentChar++) {
-		context.file_name[currentChar] = GUINT16_TO_LE(uni[currentChar]);
-	}
-	memset(&context.file_name[currentChar], 0x00, (MAX_FILE_NAME_LEN - currentChar) * 2);
-
-	memset(&context.unknown1, 0, sizeof(context.unknown1));
-	context.unknown2 = 0xffffffff;
-
-	/* Mind the cast, as in, don't free it after! */
-	context.preview = (char *)preview;
-	context.preview_len = preview_len;
-
-	u8 = msn_file_context_to_wire(&context);
-	ret = purple_base64_encode((const guchar *)u8, MSN_FILE_CONTEXT_SIZE + preview_len);
-
-	g_free(uni);
-	g_free(u8);
-
-	return ret;
-}
-
-void
-msn_request_ft(PurpleXfer *xfer)
-{
-	MsnSlpCall *slpcall;
-	MsnSlpLink *slplink;
-	char *context;
-	const char *fn;
-	const char *fp;
-
-	fn = purple_xfer_get_filename(xfer);
-	fp = purple_xfer_get_local_filename(xfer);
-
-	slplink = xfer->data;
-
-	g_return_if_fail(slplink != NULL);
-	g_return_if_fail(fp != NULL);
-
-	slpcall = msn_slpcall_new(slplink);
-	msn_slpcall_init(slpcall, MSN_SLPCALL_DC);
-
-	slpcall->session_init_cb = send_file_cb;
-	slpcall->end_cb = msn_xfer_end_cb;
-	slpcall->cb = msn_xfer_completed_cb;
-	slpcall->xfer = xfer;
-	purple_xfer_ref(slpcall->xfer);
-
-	slpcall->pending = TRUE;
-
-	purple_xfer_set_cancel_send_fnc(xfer, msn_xfer_cancel);
-	purple_xfer_set_read_fnc(xfer, msn_xfer_read);
-	purple_xfer_set_write_fnc(xfer, msn_xfer_write);
-
-	xfer->data = slpcall;
-
-	context = gen_context(xfer, fn, fp);
-
-	msn_slpcall_invite(slpcall, MSN_FT_GUID, P2P_APPID_FILE, context);
-	msn_slplink_unref(slplink);
-
-	g_free(context);
-}
-
--- a/libpurple/protocols/msn/slp.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/**
- * @file slp.h MSNSLP support
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_SLP_H
-#define MSN_SLP_H
-
-#include "internal.h"
-#include "ft.h"
-
-#include "session.h"
-#include "slpcall.h"
-#include "slplink.h"
-#include "user.h"
-
-void
-msn_slp_send_ok(MsnSlpCall *slpcall, const char *branch,
-		const char *type, const char *content);
-
-void
-msn_slp_send_decline(MsnSlpCall *slpcall, const char *branch,
-			 const char *type, const char *content);
-
-
-void send_bye(MsnSlpCall *slpcall, const char *type);
-
-
-void msn_request_user_display(MsnUser *user);
-
-void msn_request_ft(PurpleXfer *xfer);
-
-#endif /* MSN_SLP_H */
--- a/libpurple/protocols/msn/slpcall.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1157 +0,0 @@
-/**
- * @file slpcall.c SLP Call Functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-#include "smiley.h"
-
-#include "msnutils.h"
-#include "slpcall.h"
-
-#include "slp.h"
-#include "p2p.h"
-#include "xfer.h"
-
-/**************************************************************************
- * Main
- **************************************************************************/
-
-static gboolean
-msn_slpcall_timeout(gpointer data)
-{
-	MsnSlpCall *slpcall;
-
-	slpcall = data;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "slpcall_timeout: slpcall(%p)\n", slpcall);
-
-	if (!slpcall->pending && !slpcall->progress)
-	{
-		msn_slpcall_destroy(slpcall);
-		return TRUE;
-	}
-
-	slpcall->progress = FALSE;
-
-	return TRUE;
-}
-
-MsnSlpCall *
-msn_slpcall_new(MsnSlpLink *slplink)
-{
-	MsnSlpCall *slpcall;
-
-	g_return_val_if_fail(slplink != NULL, NULL);
-
-	slpcall = g_new0(MsnSlpCall, 1);
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "slpcall_new: slpcall(%p)\n", slpcall);
-
-	slpcall->slplink = slplink;
-
-	msn_slplink_add_slpcall(slplink, slpcall);
-
-	slpcall->timer = purple_timeout_add_seconds(MSN_SLPCALL_TIMEOUT, msn_slpcall_timeout, slpcall);
-
-	return slpcall;
-}
-
-void
-msn_slpcall_destroy(MsnSlpCall *slpcall)
-{
-	GList *e;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "slpcall_destroy: slpcall(%p)\n", slpcall);
-
-	g_return_if_fail(slpcall != NULL);
-
-	if (slpcall->timer)
-		purple_timeout_remove(slpcall->timer);
-
-	for (e = slpcall->slplink->slp_msgs; e != NULL; )
-	{
-		MsnSlpMessage *slpmsg = e->data;
-		e = e->next;
-
-		if (purple_debug_is_verbose())
-			purple_debug_info("msn", "slpcall_destroy: trying slpmsg(%p)\n",
-			                  slpmsg);
-
-		if (slpmsg->slpcall == slpcall)
-		{
-			msn_slpmsg_destroy(slpmsg);
-		}
-	}
-
-	if (slpcall->end_cb != NULL)
-		slpcall->end_cb(slpcall, slpcall->slplink->session);
-
-	if (slpcall->xfer != NULL) {
-		if (purple_xfer_get_type(slpcall->xfer) == PURPLE_XFER_RECEIVE)
-			g_byte_array_free(slpcall->u.incoming_data, TRUE);
-		slpcall->xfer->data = NULL;
-		purple_xfer_unref(slpcall->xfer);
-	}
-
-
-	msn_slplink_remove_slpcall(slpcall->slplink, slpcall);
-
-	g_free(slpcall->id);
-	g_free(slpcall->branch);
-	g_free(slpcall->data_info);
-
-	g_free(slpcall);
-}
-
-void
-msn_slpcall_init(MsnSlpCall *slpcall, MsnSlpCallType type)
-{
-	slpcall->session_id = rand() % 0xFFFFFF00 + 4;
-	slpcall->id = rand_guid();
-	slpcall->type = type;
-}
-
-void
-msn_slpcall_session_init(MsnSlpCall *slpcall)
-{
-	if (slpcall->session_init_cb)
-		slpcall->session_init_cb(slpcall);
-
-	slpcall->started = TRUE;
-}
-
-void
-msn_slpcall_invite(MsnSlpCall *slpcall, const char *euf_guid,
-					MsnP2PAppId app_id, const char *context)
-{
-	MsnSlpLink *slplink;
-	MsnSlpMessage *slpmsg;
-	char *header;
-	char *content;
-
-	g_return_if_fail(slpcall != NULL);
-	g_return_if_fail(context != NULL);
-
-	slplink = slpcall->slplink;
-
-	slpcall->branch = rand_guid();
-
-	content = g_strdup_printf(
-		"EUF-GUID: {%s}\r\n"
-		"SessionID: %lu\r\n"
-		"AppID: %d\r\n"
-		"Context: %s\r\n\r\n",
-		euf_guid,
-		slpcall->session_id,
-		app_id,
-		context);
-
-	header = g_strdup_printf("INVITE MSNMSGR:%s MSNSLP/1.0",
-							 slplink->remote_user);
-
-	slpmsg = msn_slpmsg_sip_new(slpcall, 0, header, slpcall->branch,
-								"application/x-msnmsgr-sessionreqbody", content);
-
-	slpmsg->info = "SLP INVITE";
-	slpmsg->text_body = TRUE;
-
-	msn_slplink_send_slpmsg(slplink, slpmsg);
-
-	g_free(header);
-	g_free(content);
-}
-
-void
-msn_slpcall_close(MsnSlpCall *slpcall)
-{
-	g_return_if_fail(slpcall != NULL);
-	g_return_if_fail(slpcall->slplink != NULL);
-
-	send_bye(slpcall, "application/x-msnmsgr-sessionclosebody");
-	msn_slplink_send_queued_slpmsgs(slpcall->slplink);
-	msn_slpcall_destroy(slpcall);
-}
-
-/*****************************************************************************
- * Parse received SLP messages
- ****************************************************************************/
-
-/**************************************************************************
- *** Util
- **************************************************************************/
-
-static char *
-get_token(const char *str, const char *start, const char *end)
-{
-	const char *c, *c2;
-
-	if ((c = strstr(str, start)) == NULL)
-		return NULL;
-
-	c += strlen(start);
-
-	if (end != NULL)
-	{
-		if ((c2 = strstr(c, end)) == NULL)
-			return NULL;
-
-		return g_strndup(c, c2 - c);
-	}
-	else
-	{
-		/* This has to be changed */
-		return g_strdup(c);
-	}
-
-}
-
-/* XXX: this could be improved if we tracked custom smileys
- * per-protocol, per-account, per-session or (ideally) per-conversation
- */
-static PurpleStoredImage *
-find_valid_emoticon(PurpleAccount *account, const char *path)
-{
-	GList *smileys;
-
-	if (!purple_account_get_bool(account, "custom_smileys", TRUE))
-		return NULL;
-
-	smileys = purple_smileys_get_all();
-
-	for (; smileys; smileys = g_list_delete_link(smileys, smileys)) {
-		PurpleSmiley *smiley;
-		PurpleStoredImage *img;
-
-		smiley = smileys->data;
-		img = purple_smiley_get_stored_image(smiley);
-
-		if (purple_strequal(path, purple_imgstore_get_filename(img))) {
-			g_list_free(smileys);
-			return img;
-		}
-
-		purple_imgstore_unref(img);
-	}
-
-	purple_debug_error("msn", "Received illegal request for file %s\n", path);
-	return NULL;
-}
-
-static char *
-parse_dc_nonce(const char *content, MsnDirectConnNonceType *ntype)
-{
-	char *nonce;
-
-	*ntype = DC_NONCE_UNKNOWN;
-
-	nonce = get_token(content, "Hashed-Nonce: {", "}\r\n");
-	if (nonce) {
-		*ntype = DC_NONCE_SHA1;
-	} else {
-		guint32 n1, n6;
-		guint16 n2, n3, n4, n5;
-		nonce = get_token(content, "Nonce: {", "}\r\n");
-		if (nonce
-		 && sscanf(nonce, "%08x-%04hx-%04hx-%04hx-%04hx%08x",
-		           &n1, &n2, &n3, &n4, &n5, &n6) == 6) {
-			*ntype = DC_NONCE_PLAIN;
-			g_free(nonce);
-			nonce = g_malloc(16);
-			*(guint32 *)(nonce +  0) = GUINT32_TO_LE(n1);
-			*(guint16 *)(nonce +  4) = GUINT16_TO_LE(n2);
-			*(guint16 *)(nonce +  6) = GUINT16_TO_LE(n3);
-			*(guint16 *)(nonce +  8) = GUINT16_TO_BE(n4);
-			*(guint16 *)(nonce + 10) = GUINT16_TO_BE(n5);
-			*(guint32 *)(nonce + 12) = GUINT32_TO_BE(n6);
-		} else {
-			/* Invalid nonce, so ignore request */
-			g_free(nonce);
-			nonce = NULL;
-		}
-	}
-
-	return nonce;
-}
-
-static void
-msn_slp_process_transresp(MsnSlpCall *slpcall, const char *content)
-{
-	/* A direct connection negotiation response */
-	char *bridge;
-	char *nonce;
-	char *listening;
-	MsnDirectConn *dc = slpcall->slplink->dc;
-	MsnDirectConnNonceType ntype;
-
-	purple_debug_info("msn", "process_transresp\n");
-
-	/* Direct connections are disabled. */
-	if (!purple_account_get_bool(slpcall->slplink->session->account, "direct_connect", TRUE))
-		return;
-
-	g_return_if_fail(dc != NULL);
-	g_return_if_fail(dc->state == DC_STATE_CLOSED);
-
-	bridge = get_token(content, "Bridge: ", "\r\n");
-	nonce = parse_dc_nonce(content, &ntype);
-	listening = get_token(content, "Listening: ", "\r\n");
-	if (listening && bridge && !strcmp(bridge, "TCPv1")) {
-		/* Ok, the client supports direct TCP connection */
-
-		/* We always need this. */
-		if (ntype == DC_NONCE_SHA1) {
-			strncpy(dc->remote_nonce, nonce, 36);
-			dc->remote_nonce[36] = '\0';
-		}
-
-		if (!strcasecmp(listening, "false")) {
-			if (dc->listen_data != NULL) {
-				/*
-				 * We'll listen for incoming connections but
-				 * the listening socket isn't ready yet so we cannot
-				 * send the INVITE packet now. Put the slpcall into waiting mode
-				 * and let the callback send the invite.
-				 */
-				slpcall->wait_for_socket = TRUE;
-
-			} else if (dc->listenfd != -1) {
-				/* The listening socket is ready. Send the INVITE here. */
-				msn_dc_send_invite(dc);
-
-			} else {
-				/* We weren't able to create a listener either. Use SB. */
-				msn_dc_fallback_to_sb(dc);
-			}
-
-		} else {
-			/*
-			 * We should connect to the client so parse
-			 * IP/port from response.
-			 */
-			char *ip, *port_str;
-			int port = 0;
-
-			if (ntype == DC_NONCE_PLAIN) {
-				/* Only needed for listening side. */
-				memcpy(dc->nonce, nonce, 16);
-			}
-
-			/* Cancel any listen attempts because we don't need them. */
-			if (dc->listenfd_handle != 0) {
-				purple_input_remove(dc->listenfd_handle);
-				dc->listenfd_handle = 0;
-			}
-			if (dc->connect_timeout_handle != 0) {
-				purple_timeout_remove(dc->connect_timeout_handle);
-				dc->connect_timeout_handle = 0;
-			}
-			if (dc->listenfd != -1) {
-				purple_network_remove_port_mapping(dc->listenfd);
-				close(dc->listenfd);
-				dc->listenfd = -1;
-			}
-			if (dc->listen_data != NULL) {
-				purple_network_listen_cancel(dc->listen_data);
-				dc->listen_data = NULL;
-			}
-
-			/* Save external IP/port for later use. We'll try local connection first. */
-			dc->ext_ip = get_token(content, "IPv4External-Addrs: ", "\r\n");
-			port_str = get_token(content, "IPv4External-Port: ", "\r\n");
-			if (port_str) {
-				dc->ext_port = atoi(port_str);
-				g_free(port_str);
-			}
-
-			ip = get_token(content, "IPv4Internal-Addrs: ", "\r\n");
-			port_str = get_token(content, "IPv4Internal-Port: ", "\r\n");
-			if (port_str) {
-				port = atoi(port_str);
-				g_free(port_str);
-			}
-
-			if (ip && port) {
-				/* Try internal address first */
-				dc->connect_data = purple_proxy_connect(
-					NULL,
-					slpcall->slplink->session->account,
-					ip,
-					port,
-					msn_dc_connected_to_peer_cb,
-					dc
-				);
-
-				if (dc->connect_data) {
-					/* Add connect timeout handle */
-					dc->connect_timeout_handle = purple_timeout_add_seconds(
-						DC_OUTGOING_TIMEOUT,
-						msn_dc_outgoing_connection_timeout_cb,
-						dc
-					);
-				} else {
-					/*
-					 * Connection failed
-					 * Try external IP/port (if specified)
-					 */
-					msn_dc_outgoing_connection_timeout_cb(dc);
-				}
-
-			} else {
-				/*
-				 * Omitted or invalid internal IP address / port
-				 * Try external IP/port (if specified)
-				 */
-				msn_dc_outgoing_connection_timeout_cb(dc);
-			}
-
-			g_free(ip);
-		}
-
-	} else {
-		/*
-		 * Invalid direct connect invitation or
-		 * TCP connection is not supported
-		 */
-	}
-
-	g_free(listening);
-	g_free(nonce);
-	g_free(bridge);
-
-	return;
-}
-
-static void
-got_sessionreq(MsnSlpCall *slpcall, const char *branch,
-			   const char *euf_guid, const char *context)
-{
-	gboolean accepted = FALSE;
-
-	if (!strcmp(euf_guid, MSN_OBJ_GUID))
-	{
-		/* Emoticon or UserDisplay */
-		char *content;
-		gsize len;
-		MsnSlpLink *slplink;
-		MsnSlpMessage *slpmsg;
-		MsnObject *obj;
-		char *msnobj_data;
-		PurpleStoredImage *img = NULL;
-		int type;
-
-		/* Send Ok */
-		content = g_strdup_printf("SessionID: %lu\r\n\r\n",
-								  slpcall->session_id);
-
-		msn_slp_send_ok(slpcall, branch, "application/x-msnmsgr-sessionreqbody",
-				content);
-
-		g_free(content);
-
-		slplink = slpcall->slplink;
-
-		msnobj_data = (char *)purple_base64_decode(context, &len);
-		obj = msn_object_new_from_string(msnobj_data);
-		type = msn_object_get_type(obj);
-		g_free(msnobj_data);
-		if (type == MSN_OBJECT_EMOTICON) {
-			img = find_valid_emoticon(slplink->session->account, obj->location);
-		} else if (type == MSN_OBJECT_USERTILE) {
-			img = msn_object_get_image(obj);
-			if (img)
-				purple_imgstore_ref(img);
-		}
-		msn_object_destroy(obj);
-
-		if (img != NULL) {
-			/* DATA PREP */
-			slpmsg = msn_slpmsg_dataprep_new(slpcall);
-			msn_slplink_queue_slpmsg(slplink, slpmsg);
-
-			/* DATA */
-			slpmsg = msn_slpmsg_obj_new(slpcall, img);
-			msn_slplink_queue_slpmsg(slplink, slpmsg);
-			purple_imgstore_unref(img);
-
-			accepted = TRUE;
-
-		} else {
-			purple_debug_error("msn", "Wrong object.\n");
-		}
-	}
-
-	else if (!strcmp(euf_guid, MSN_FT_GUID))
-	{
-		/* File Transfer */
-		PurpleAccount *account;
-		PurpleXfer *xfer;
-		MsnFileContext *file_context;
-		char *buf;
-		gsize bin_len;
-		guint32 file_size;
-		char *file_name;
-
-		account = slpcall->slplink->session->account;
-
-		slpcall->end_cb = msn_xfer_end_cb;
-		slpcall->branch = g_strdup(branch);
-
-		slpcall->pending = TRUE;
-
-		xfer = purple_xfer_new(account, PURPLE_XFER_RECEIVE,
-							 slpcall->slplink->remote_user);
-
-		buf = (char *)purple_base64_decode(context, &bin_len);
-		file_context = msn_file_context_from_wire(buf, bin_len);
-
-		if (file_context != NULL) {
-			file_size = file_context->file_size;
-
-			file_name = g_convert((const gchar *)&file_context->file_name,
-			                      MAX_FILE_NAME_LEN * 2,
-			                      "UTF-8", "UTF-16LE",
-			                      NULL, NULL, NULL);
-
-			purple_xfer_set_filename(xfer, file_name ? file_name : "");
-			g_free(file_name);
-			purple_xfer_set_size(xfer, file_size);
-			purple_xfer_set_init_fnc(xfer, msn_xfer_init);
-			purple_xfer_set_request_denied_fnc(xfer, msn_xfer_cancel);
-			purple_xfer_set_cancel_recv_fnc(xfer, msn_xfer_cancel);
-			purple_xfer_set_read_fnc(xfer, msn_xfer_read);
-			purple_xfer_set_write_fnc(xfer, msn_xfer_write);
-
-			slpcall->u.incoming_data = g_byte_array_new();
-
-			slpcall->xfer = xfer;
-			purple_xfer_ref(slpcall->xfer);
-
-			xfer->data = slpcall;
-
-			if (file_context->preview) {
-				purple_xfer_set_thumbnail(xfer, file_context->preview,
-				                          file_context->preview_len,
-				    					  "image/png");
-				g_free(file_context->preview);
-			}
-
-			purple_xfer_request(xfer);
-		}
-		g_free(file_context);
-		g_free(buf);
-
-		accepted = TRUE;
-
-	} else if (!strcmp(euf_guid, MSN_CAM_REQUEST_GUID)) {
-		purple_debug_info("msn", "Cam request.\n");
-		if (slpcall->slplink && slpcall->slplink->session) {
-			PurpleConversation *conv;
-			gchar *from = slpcall->slplink->remote_user;
-			conv = purple_find_conversation_with_account(
-					PURPLE_CONV_TYPE_IM, from,
-					slpcall->slplink->session->account);
-			if (conv) {
-				char *buf;
-				buf = g_strdup_printf(
-						_("%s requests to view your "
-						"webcam, but this request is "
-						"not yet supported."), from);
-				purple_conversation_write(conv, NULL, buf,
-						PURPLE_MESSAGE_SYSTEM |
-						PURPLE_MESSAGE_NOTIFY,
-						time(NULL));
-				g_free(buf);
-			}
-		}
-
-	} else if (!strcmp(euf_guid, MSN_CAM_GUID)) {
-		purple_debug_info("msn", "Cam invite.\n");
-		if (slpcall->slplink && slpcall->slplink->session) {
-			PurpleConversation *conv;
-			gchar *from = slpcall->slplink->remote_user;
-			conv = purple_find_conversation_with_account(
-					PURPLE_CONV_TYPE_IM, from,
-					slpcall->slplink->session->account);
-			if (conv) {
-				char *buf;
-				buf = g_strdup_printf(
-						_("%s invited you to view his/her webcam, but "
-						"this is not yet supported."), from);
-				purple_conversation_write(conv, NULL, buf,
-						PURPLE_MESSAGE_SYSTEM |
-						PURPLE_MESSAGE_NOTIFY,
-						time(NULL));
-				g_free(buf);
-			}
-		}
-
-	} else
-		purple_debug_warning("msn", "SLP SessionReq with unknown EUF-GUID: %s\n", euf_guid);
-
-	if (!accepted) {
-		char *content = g_strdup_printf("SessionID: %lu\r\n\r\n",
-		                                slpcall->session_id);
-		msn_slp_send_decline(slpcall, branch, "application/x-msnmsgr-sessionreqbody", content);
-		g_free(content);
-	}
-}
-
-void
-send_bye(MsnSlpCall *slpcall, const char *type)
-{
-	MsnSlpLink *slplink;
-	PurpleAccount *account;
-	MsnSlpMessage *slpmsg;
-	char *header;
-
-	slplink = slpcall->slplink;
-
-	g_return_if_fail(slplink != NULL);
-
-	account = slplink->session->account;
-
-	header = g_strdup_printf("BYE MSNMSGR:%s MSNSLP/1.0",
-							 purple_account_get_username(account));
-
-	slpmsg = msn_slpmsg_sip_new(slpcall, 0, header,
-								"A0D624A6-6C0C-4283-A9E0-BC97B4B46D32",
-								type,
-								"\r\n");
-	g_free(header);
-
-	slpmsg->info = "SLP BYE";
-	slpmsg->text_body = TRUE;
-
-	msn_slplink_queue_slpmsg(slplink, slpmsg);
-}
-
-static void
-got_invite(MsnSlpCall *slpcall,
-		   const char *branch, const char *type, const char *content)
-{
-	MsnSlpLink *slplink;
-
-	slplink = slpcall->slplink;
-
-	if (!strcmp(type, "application/x-msnmsgr-sessionreqbody"))
-	{
-		char *euf_guid, *context;
-		char *temp;
-
-		euf_guid = get_token(content, "EUF-GUID: {", "}\r\n");
-
-		temp = get_token(content, "SessionID: ", "\r\n");
-		if (temp != NULL)
-			slpcall->session_id = atoi(temp);
-		g_free(temp);
-
-		temp = get_token(content, "AppID: ", "\r\n");
-		if (temp != NULL)
-			slpcall->app_id = atoi(temp);
-		g_free(temp);
-
-		context = get_token(content, "Context: ", "\r\n");
-
-		if (context != NULL)
-			got_sessionreq(slpcall, branch, euf_guid, context);
-
-		g_free(context);
-		g_free(euf_guid);
-	}
-	else if (!strcmp(type, "application/x-msnmsgr-transreqbody"))
-	{
-		/* A direct connection negotiation request */
-		char *bridges;
-		char *nonce;
-		MsnDirectConnNonceType ntype;
-
-		purple_debug_info("msn", "got_invite: transreqbody received\n");
-
-		/* Direct connections may be disabled. */
-		if (!purple_account_get_bool(slplink->session->account, "direct_connect", TRUE)) {
-			msn_slp_send_ok(slpcall, branch,
-				"application/x-msnmsgr-transrespbody",
-				"Bridge: TCPv1\r\n"
-				"Listening: false\r\n"
-				"Nonce: {00000000-0000-0000-0000-000000000000}\r\n"
-				"\r\n");
-			msn_slpcall_session_init(slpcall);
-
-			return;
-		}
-
-		/* Don't do anything if we already have a direct connection */
-		if (slplink->dc != NULL)
-			return;
-
-		bridges = get_token(content, "Bridges: ", "\r\n");
-		nonce = parse_dc_nonce(content, &ntype);
-		if (bridges && strstr(bridges, "TCPv1") != NULL) {
-			/*
-			 * Ok, the client supports direct TCP connection
-			 * Try to create a listening port
-			 */
-			MsnDirectConn *dc;
-
-			dc = msn_dc_new(slpcall);
-			if (ntype == DC_NONCE_PLAIN) {
-				/* There is only one nonce for plain auth. */
-				dc->nonce_type = ntype;
-				memcpy(dc->nonce, nonce, 16);
-			} else if (ntype == DC_NONCE_SHA1) {
-				/* Each side has a nonce in SHA1 auth. */
-				dc->nonce_type = ntype;
-				strncpy(dc->remote_nonce, nonce, 36);
-				dc->remote_nonce[36] = '\0';
-			}
-
-			dc->listen_data = purple_network_listen_range(
-				0, 0,
-				SOCK_STREAM,
-				msn_dc_listen_socket_created_cb,
-				dc
-			);
-
-			if (dc->listen_data == NULL) {
-				/* Listen socket creation failed */
-
-				purple_debug_info("msn", "got_invite: listening failed\n");
-
-				if (dc->nonce_type != DC_NONCE_PLAIN)
-					msn_slp_send_ok(slpcall, branch,
-						"application/x-msnmsgr-transrespbody",
-						"Bridge: TCPv1\r\n"
-						"Listening: false\r\n"
-						"Hashed-Nonce: {00000000-0000-0000-0000-000000000000}\r\n"
-						"\r\n");
-				else
-					msn_slp_send_ok(slpcall, branch,
-						"application/x-msnmsgr-transrespbody",
-						"Bridge: TCPv1\r\n"
-						"Listening: false\r\n"
-						"Nonce: {00000000-0000-0000-0000-000000000000}\r\n"
-						"\r\n");
-
-			} else {
-				/*
-				 * Listen socket created successfully.
-				 * Don't send anything here because we don't know the parameters
-				 * of the created socket yet. msn_dc_send_ok will be called from
-				 * the callback function: dc_listen_socket_created_cb
-				 */
-				purple_debug_info("msn", "got_invite: listening socket created\n");
-
-				dc->send_connection_info_msg_cb = msn_dc_send_ok;
-				slpcall->wait_for_socket = TRUE;
-			}
-
-		} else {
-			/*
-			 * Invalid direct connect invitation or
-			 * TCP connection is not supported.
-			 */
-		}
-
-		g_free(nonce);
-		g_free(bridges);
-	}
-	else if (!strcmp(type, "application/x-msnmsgr-transrespbody"))
-	{
-		/* A direct connection negotiation response */
-		msn_slp_process_transresp(slpcall, content);
-	}
-}
-
-static void
-got_ok(MsnSlpCall *slpcall,
-	   const char *type, const char *content)
-{
-	g_return_if_fail(slpcall != NULL);
-	g_return_if_fail(type    != NULL);
-
-	if (!strcmp(type, "application/x-msnmsgr-sessionreqbody"))
-	{
-		char *content;
-		char *header;
-		char *nonce = NULL;
-		MsnSession *session = slpcall->slplink->session;
-		MsnSlpMessage *msg;
-		MsnDirectConn *dc;
-		MsnUser *user;
-
-		if (!purple_account_get_bool(session->account, "direct_connect", TRUE)) {
-			/* Don't attempt a direct connection if disabled. */
-			msn_slpcall_session_init(slpcall);
-			return;
-		}
-
-		if (slpcall->slplink->dc != NULL) {
-			/* If we already have an established direct connection
-			 * then just start the transfer.
-			 */
-			msn_slpcall_session_init(slpcall);
-			return;
-		}
-
-		user = msn_userlist_find_user(session->userlist,
-		                              slpcall->slplink->remote_user);
-		if (!user || !(user->clientid & 0xF0000000))	{
-			/* Just start a normal SB transfer. */
-			msn_slpcall_session_init(slpcall);
-			return;
-		}
-
-		/* Try direct file transfer by sending a second INVITE */
-		dc = msn_dc_new(slpcall);
-		g_free(slpcall->branch);
-		slpcall->branch = rand_guid();
-
-		dc->listen_data = purple_network_listen_range(
-			0, 0,
-			SOCK_STREAM,
-			msn_dc_listen_socket_created_cb,
-			dc
-		);
-
-		header = g_strdup_printf(
-			"INVITE MSNMSGR:%s MSNSLP/1.0",
-			slpcall->slplink->remote_user
-		);
-
-		if (dc->nonce_type == DC_NONCE_SHA1)
-			nonce = g_strdup_printf("Hashed-Nonce: {%s}\r\n", dc->nonce_hash);
-
-		if (dc->listen_data == NULL) {
-			/* Listen socket creation failed */
-			purple_debug_info("msn", "got_ok: listening failed\n");
-
-			content = g_strdup_printf(
-				"Bridges: TCPv1\r\n"
-				"NetID: %u\r\n"
-				"Conn-Type: IP-Restrict-NAT\r\n"
-				"UPnPNat: false\r\n"
-				"ICF: false\r\n"
-				"%s"
-				"\r\n",
-
-				rand() % G_MAXUINT32,
-				nonce ? nonce : ""
-			);
-
-		} else {
-			/* Listen socket created successfully. */
-			purple_debug_info("msn", "got_ok: listening socket created\n");
-
-			content = g_strdup_printf(
-				"Bridges: TCPv1\r\n"
-				"NetID: 0\r\n"
-				"Conn-Type: Direct-Connect\r\n"
-				"UPnPNat: false\r\n"
-				"ICF: false\r\n"
-				"%s"
-				"\r\n",
-
-				nonce ? nonce : ""
-			);
-		}
-
-		msg = msn_slpmsg_sip_new(
-			slpcall,
-			0,
-			header,
-			slpcall->branch,
-			"application/x-msnmsgr-transreqbody",
-			content
-		);
-		msg->info = "DC INVITE";
-		msg->text_body = TRUE;
-		g_free(nonce);
-		g_free(header);
-		g_free(content);
-
-		msn_slplink_queue_slpmsg(slpcall->slplink, msg);
-	}
-	else if (!strcmp(type, "application/x-msnmsgr-transreqbody"))
-	{
-		/* Do we get this? */
-		purple_debug_info("msn", "OK with transreqbody\n");
-	}
-	else if (!strcmp(type, "application/x-msnmsgr-transrespbody"))
-	{
-		msn_slp_process_transresp(slpcall, content);
-	}
-}
-
-static void
-got_error(MsnSlpCall *slpcall,
-          const char *error, const char *type, const char *content)
-{
-	/* It's not valid. Kill this off. */
-	purple_debug_error("msn", "Received non-OK result: %s\n",
-	                   error ? error : "Unknown");
-
-	if (type && !strcmp(type, "application/x-msnmsgr-transreqbody")) {
-		MsnDirectConn *dc = slpcall->slplink->dc;
-		if (dc) {
-			msn_dc_fallback_to_sb(dc);
-			return;
-		}
-	}
-
-	slpcall->wasted = TRUE;
-}
-
-static MsnSlpCall *
-msn_slp_sip_recv(MsnSlpLink *slplink, const char *body)
-{
-	MsnSlpCall *slpcall;
-
-	if (body == NULL)
-	{
-		purple_debug_warning("msn", "received bogus message\n");
-		return NULL;
-	}
-
-	if (!strncmp(body, "INVITE", strlen("INVITE")))
-	{
-		/* This is an INVITE request */
-		char *branch;
-		char *call_id;
-		char *content;
-		char *content_type;
-
-		/* From: <msnmsgr:buddy@hotmail.com> */
-#if 0
-		slpcall->remote_user = get_token(body, "From: <msnmsgr:", ">\r\n");
-#endif
-
-		branch = get_token(body, ";branch={", "}");
-
-		call_id = get_token(body, "Call-ID: {", "}");
-
-#if 0
-		long content_len = -1;
-
-		temp = get_token(body, "Content-Length: ", "\r\n");
-		if (temp != NULL)
-			content_len = atoi(temp);
-		g_free(temp);
-#endif
-		content_type = get_token(body, "Content-Type: ", "\r\n");
-
-		content = get_token(body, "\r\n\r\n", NULL);
-
-		slpcall = NULL;
-		if (branch && call_id)
-		{
-			slpcall = msn_slplink_find_slp_call(slplink, call_id);
-			if (slpcall)
-			{
-				g_free(slpcall->branch);
-				slpcall->branch = g_strdup(branch);
-				got_invite(slpcall, branch, content_type, content);
-			}
-			else if (content_type && content)
-			{
-				slpcall = msn_slpcall_new(slplink);
-				slpcall->id = g_strdup(call_id);
-				got_invite(slpcall, branch, content_type, content);
-			}
-		}
-
-		g_free(call_id);
-		g_free(branch);
-		g_free(content_type);
-		g_free(content);
-	}
-	else if (!strncmp(body, "MSNSLP/1.0 ", strlen("MSNSLP/1.0 ")))
-	{
-		/* This is a response */
-		char *content;
-		char *content_type;
-		/* Make sure this is "OK" */
-		const char *status = body + strlen("MSNSLP/1.0 ");
-		char *call_id;
-
-		call_id = get_token(body, "Call-ID: {", "}");
-		slpcall = msn_slplink_find_slp_call(slplink, call_id);
-		g_free(call_id);
-
-		g_return_val_if_fail(slpcall != NULL, NULL);
-
-		content_type = get_token(body, "Content-Type: ", "\r\n");
-
-		content = get_token(body, "\r\n\r\n", NULL);
-
-		if (strncmp(status, "200 OK", 6))
-		{
-			char *error = NULL;
-			const char *c;
-
-			/* Eww */
-			if ((c = strchr(status, '\r')) || (c = strchr(status, '\n')) ||
-				(c = strchr(status, '\0')))
-			{
-				size_t len = c - status;
-				error = g_strndup(status, len);
-			}
-
-			got_error(slpcall, error, content_type, content);
-			g_free(error);
-
-		} else {
-			/* Everything's just dandy */
-			got_ok(slpcall, content_type, content);
-		}
-
-		g_free(content_type);
-		g_free(content);
-	}
-	else if (!strncmp(body, "BYE", strlen("BYE")))
-	{
-		/* This is a BYE request */
-		char *call_id;
-
-		call_id = get_token(body, "Call-ID: {", "}");
-		slpcall = msn_slplink_find_slp_call(slplink, call_id);
-		g_free(call_id);
-
-		if (slpcall != NULL)
-			slpcall->wasted = TRUE;
-
-		/* msn_slpcall_destroy(slpcall); */
-	}
-	else
-		slpcall = NULL;
-
-	return slpcall;
-}
-
-MsnSlpCall *
-msn_slp_process_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
-{
-	MsnSlpCall *slpcall;
-	const guchar *body;
-	gsize body_len;
-	guint32 session_id;
-	guint32 flags;
-
-	slpcall = NULL;
-	body = slpmsg->buffer;
-	body_len = msn_p2p_info_get_offset(slpmsg->p2p_info);
-
-	session_id = msn_p2p_info_get_session_id(slpmsg->p2p_info);
-	flags = msn_p2p_info_get_flags(slpmsg->p2p_info);
-
-	if (flags == P2P_NO_FLAG || flags == P2P_WLM2009_COMP)
-	{
-		char *body_str;
-
-		if (session_id == 64)
-		{
-			/* This is for handwritten messages (Ink) */
-			GError *error = NULL;
-			gsize bytes_read, bytes_written;
-
-			body_str = g_convert((const gchar *)body, body_len / 2,
-			                     "UTF-8", "UTF-16LE",
-			                     &bytes_read, &bytes_written, &error);
-			body_len -= bytes_read + 2;
-			body += bytes_read + 2;
-			if (body_str == NULL
-			 || body_len <= 0
-			 || strstr(body_str, "image/gif") == NULL)
-			{
-				if (error != NULL) {
-					purple_debug_error("msn",
-					                   "Unable to convert Ink header from UTF-16 to UTF-8: %s\n",
-					                   error->message);
-					g_error_free(error);
-				}
-				else
-					purple_debug_error("msn",
-					                   "Received Ink in unknown format\n");
-				g_free(body_str);
-				return NULL;
-			}
-			g_free(body_str);
-
-			body_str = g_convert((const gchar *)body, body_len / 2,
-			                     "UTF-8", "UTF-16LE",
-			                     &bytes_read, &bytes_written, &error);
-			if (!body_str)
-			{
-				if (error != NULL) {
-					purple_debug_error("msn",
-					                   "Unable to convert Ink body from UTF-16 to UTF-8: %s\n",
-					                   error->message);
-					g_error_free(error);
-				}
-				else
-					purple_debug_error("msn",
-					                   "Received Ink in unknown format\n");
-				return NULL;
-			}
-
-			msn_switchboard_show_ink(slpmsg->slplink->swboard,
-			                         slplink->remote_user,
-			                         body_str);
-		}
-		else
-		{
-			body_str = g_strndup((const char *)body, body_len);
-			slpcall = msn_slp_sip_recv(slplink, body_str);
-		}
-		g_free(body_str);
-	}
-	 else if (msn_p2p_msg_is_data(slpmsg->p2p_info))
-	{
-		slpcall = msn_slplink_find_slp_call_with_session_id(slplink, session_id);
-
-		if (slpcall != NULL)
-		{
-			if (slpcall->timer) {
-				purple_timeout_remove(slpcall->timer);
-				slpcall->timer = 0;
-			}
-
-			if (slpcall->cb)
-				slpcall->cb(slpcall, body, body_len);
-
-			slpcall->wasted = TRUE;
-		}
-	}
-	else if (msn_p2p_info_is_ack(slpmsg->p2p_info))
-	{
-		/* Acknowledgement of previous message. Don't do anything currently. */
-	}
-	else
-		purple_debug_warning("msn", "Unprocessed SLP message with flags 0x%04x\n",
-		                     flags);
-
-	return slpcall;
-}
--- a/libpurple/protocols/msn/slpcall.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-/**
- * @file slpcall.h SLP Call functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_SLPCALL_H
-#define MSN_SLPCALL_H
-
-typedef struct _MsnSlpCall MsnSlpCall;
-
-typedef enum
-{
-	MSN_SLPCALL_ANY,
-	MSN_SLPCALL_DC
-} MsnSlpCallType;
-
-#include "internal.h"
-
-#include "slplink.h"
-
-/* The official client seems to timeout slp calls after 5 minutes */
-#define MSN_SLPCALL_TIMEOUT 300
-
-struct _MsnSlpCall
-{
-	/* Our parent slplink */
-	MsnSlpLink *slplink;
-
-	MsnSlpCallType type;
-
-	/* Call-ID */
-	char *id;
-	char *branch;
-
-	long session_id;
-	long app_id;
-
-	gboolean pending; /**< A flag that states if we should wait for this
-						slpcall to start and do not time out. */
-	gboolean progress; /**< A flag that states if there has been progress since
-						 the last time out. */
-	gboolean wasted; /**< A flag that states if this slpcall is going to be
-					   destroyed. */
-	gboolean started; /**< A flag that states if this slpcall's session has
-						been initiated. */
-
-	gboolean wait_for_socket;
-
-	void (*progress_cb)(MsnSlpCall *slpcall,
-						gsize total_length, gsize len);
-	void (*session_init_cb)(MsnSlpCall *slpcall);
-
-	/* Can be checksum, or smile */
-	char *data_info;
-
-	PurpleXfer *xfer;
-	union {
-		GByteArray *incoming_data;
-		struct {
-			gsize len;
-			const guchar *data;
-		} outgoing;
-	} u;
-	MsnSlpMessage *xfer_msg; /* A dirty hack */
-
-	MsnSlpCb cb;
-	void (*end_cb)(MsnSlpCall *slpcall, MsnSession *session);
-
-	guint timer;
-};
-
-MsnSlpCall *msn_slpcall_new(MsnSlpLink *slplink);
-void msn_slpcall_init(MsnSlpCall *slpcall, MsnSlpCallType type);
-void msn_slpcall_session_init(MsnSlpCall *slpcall);
-void msn_slpcall_destroy(MsnSlpCall *slpcall);
-void msn_slpcall_invite(MsnSlpCall *slpcall, const char *euf_guid,
-						 MsnP2PAppId app_id, const char *context);
-void msn_slpcall_close(MsnSlpCall *slpcall);
-
-#endif /* MSN_SLPCALL_H */
--- a/libpurple/protocols/msn/slplink.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,646 +0,0 @@
-/**
- * @file slplink.c MSNSLP Link support
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-
-#include "msn.h"
-#include "slplink.h"
-#include "slpmsg_part.h"
-
-#include "sbconn.h"
-#include "switchboard.h"
-#include "slp.h"
-#include "p2p.h"
-
-#ifdef MSN_DEBUG_SLP_FILES
-static int m_sc = 0;
-static int m_rc = 0;
-
-static void
-debug_part_to_file(MsnSlpMessage *msg, gboolean send)
-{
-	char *tmp;
-	char *dir;
-	char *data;
-	int c;
-	gsize data_size;
-
-	dir = send ? "send" : "recv";
-	c = send ? m_sc++ : m_rc++;
-	tmp = g_strdup_printf("%s/msntest/%s/%03d", purple_user_dir(), dir, c);
-	data = msn_slpmsg_serialize(msg, &data_size);
-	if (!purple_util_write_data_to_file_absolute(tmp, data, data_size))
-	{
-		purple_debug_error("msn", "could not save debug file\n");
-	}
-	g_free(tmp);
-}
-#endif
-
-/**************************************************************************
- * Main
- **************************************************************************/
-
-static MsnSlpLink *
-msn_slplink_new(MsnSession *session, const char *username)
-{
-	MsnSlpLink *slplink;
-
-	g_return_val_if_fail(session != NULL, NULL);
-
-	slplink = g_new0(MsnSlpLink, 1);
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "slplink_new: slplink(%p)\n", slplink);
-
-	slplink->session = session;
-	slplink->slp_seq_id = rand() % 0xFFFFFF00 + 4;
-
-	slplink->remote_user = g_strdup(username);
-	slplink->p2p_version = MSN_P2P_VERSION_ONE;
-
-	slplink->slp_msg_queue = g_queue_new();
-
-	session->slplinks =
-		g_list_append(session->slplinks, slplink);
-
-	return msn_slplink_ref(slplink);
-}
-
-static void
-msn_slplink_destroy(MsnSlpLink *slplink)
-{
-	MsnSession *session;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "slplink_destroy: slplink(%p)\n", slplink);
-
-	if (slplink->swboard != NULL) {
-		slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink);
-		slplink->swboard = NULL;
-	}
-
-	session = slplink->session;
-
-	if (slplink->dc != NULL) {
-		slplink->dc->slplink = NULL;
-		msn_dc_destroy(slplink->dc);
-		slplink->dc = NULL;
-	}
-
-	while (slplink->slp_calls != NULL)
-		msn_slpcall_destroy(slplink->slp_calls->data);
-
-	g_queue_free(slplink->slp_msg_queue);
-
-	session->slplinks =
-		g_list_remove(session->slplinks, slplink);
-
-	g_free(slplink->remote_user);
-
-	g_free(slplink);
-}
-
-MsnSlpLink *
-msn_slplink_ref(MsnSlpLink *slplink)
-{
-	g_return_val_if_fail(slplink != NULL, NULL);
-
-	slplink->refs++;
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "slplink ref (%p)[%d]\n", slplink, slplink->refs);
-
-	return slplink;
-}
-
-void
-msn_slplink_unref(MsnSlpLink *slplink)
-{
-	g_return_if_fail(slplink != NULL);
-
-	slplink->refs--;
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "slplink unref (%p)[%d]\n", slplink, slplink->refs);
-
-	if (slplink->refs == 0)
-		msn_slplink_destroy(slplink);
-}
-
-MsnSlpLink *
-msn_session_find_slplink(MsnSession *session, const char *who)
-{
-	GList *l;
-
-	for (l = session->slplinks; l != NULL; l = l->next)
-	{
-		MsnSlpLink *slplink;
-
-		slplink = l->data;
-
-		if (!strcmp(slplink->remote_user, who))
-			return slplink;
-	}
-
-	return NULL;
-}
-
-MsnSlpLink *
-msn_session_get_slplink(MsnSession *session, const char *username)
-{
-	MsnSlpLink *slplink;
-
-	g_return_val_if_fail(session != NULL, NULL);
-	g_return_val_if_fail(username != NULL, NULL);
-
-	slplink = msn_session_find_slplink(session, username);
-
-	if (slplink == NULL)
-		slplink = msn_slplink_new(session, username);
-
-	return slplink;
-}
-
-void
-msn_slplink_add_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall)
-{
-	if (slplink->swboard != NULL)
-		slplink->swboard->flag |= MSN_SB_FLAG_FT;
-
-	slplink->slp_calls = g_list_append(slplink->slp_calls, slpcall);
-
-	/*
-	if (slplink->dc != NULL && slplink->dc->state == DC_STATE_ESTABLISHED)
-		msn_dc_ref(slplink->dc);
-	*/
-}
-
-void
-msn_slplink_remove_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall)
-{
-	/*
-	if (slplink->dc != NULL && slplink->dc->state == DC_STATE_ESTABLISHED)
-		msn_dc_unref(slplink->dc);
-	*/
-
-	slplink->slp_calls = g_list_remove(slplink->slp_calls, slpcall);
-
-	/* The slplink has no slpcalls in it, release it from MSN_SB_FLAG_FT.
-	 * If nothing else is using it then this might cause swboard to be
-	 * destroyed. */
-	if (slplink->slp_calls == NULL && slplink->swboard != NULL) {
-		slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink);
-		msn_switchboard_release(slplink->swboard, MSN_SB_FLAG_FT);
-		slplink->swboard = NULL;
-	}
-
-	if (slplink->dc != NULL) {
-		if ((slplink->dc->state != DC_STATE_ESTABLISHED && slplink->dc->slpcall == slpcall)
-		 || (slplink->slp_calls == NULL)) {
-			/* The DC is not established and its corresponding slpcall is dead,
-			 * or the slplink has no slpcalls in it and no longer needs the DC.
-			 */
-			slplink->dc->slplink = NULL;
-			msn_dc_destroy(slplink->dc);
-			slplink->dc = NULL;
-		}
-	}
-}
-
-MsnSlpCall *
-msn_slplink_find_slp_call(MsnSlpLink *slplink, const char *id)
-{
-	GList *l;
-	MsnSlpCall *slpcall;
-
-	if (!id)
-		return NULL;
-
-	for (l = slplink->slp_calls; l != NULL; l = l->next)
-	{
-		slpcall = l->data;
-
-		if (slpcall->id && !strcmp(slpcall->id, id))
-			return slpcall;
-	}
-
-	return NULL;
-}
-
-MsnSlpCall *
-msn_slplink_find_slp_call_with_session_id(MsnSlpLink *slplink, long id)
-{
-	GList *l;
-	MsnSlpCall *slpcall;
-
-	for (l = slplink->slp_calls; l != NULL; l = l->next)
-	{
-		slpcall = l->data;
-
-		if (slpcall->session_id == id)
-			return slpcall;
-	}
-
-	return NULL;
-}
-
-MsnP2PVersion
-msn_slplink_get_p2p_version(MsnSlpLink *slplink)
-{
-	return slplink->p2p_version;
-}
-
-static void
-msn_slplink_send_part(MsnSlpLink *slplink, MsnSlpMessagePart *part)
-{
-	if (slplink->dc != NULL && slplink->dc->state == DC_STATE_ESTABLISHED)
-	{
-		msn_dc_enqueue_part(slplink->dc, part);
-	}
-	else
-	{
-		msn_sbconn_send_part(slplink, part);
-	}
-}
-
-void
-msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
-{
-	MsnSlpMessagePart *part;
-	MsnP2PInfo *info;
-	gsize real_size;
-	size_t len = 0;
-	guint64 offset;
-
-	/* Maybe we will want to create a new msg for this slpmsg instead of
-	 * reusing the same one all the time. */
-	info = slpmsg->p2p_info;
-	part = msn_slpmsgpart_new(msn_p2p_info_dup(info));
-	part->ack_data = slpmsg;
-
-	real_size = msn_p2p_info_is_ack(info) ? 0 : slpmsg->size;
-
-	offset = msn_p2p_info_get_offset(info);
-	if (offset < real_size)
-	{
-		if (slpmsg->slpcall && slpmsg->slpcall->xfer && purple_xfer_get_type(slpmsg->slpcall->xfer) == PURPLE_XFER_SEND &&
-				purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED)
-		{
-			len = MIN(MSN_SBCONN_MAX_SIZE, slpmsg->slpcall->u.outgoing.len);
-			msn_slpmsgpart_set_bin_data(part, slpmsg->slpcall->u.outgoing.data, len);
-		}
-		else
-		{
-			len = slpmsg->size - offset;
-
-			if (len > MSN_SBCONN_MAX_SIZE)
-				len = MSN_SBCONN_MAX_SIZE;
-
-			msn_slpmsgpart_set_bin_data(part, slpmsg->buffer + offset, len);
-		}
-
-		msn_p2p_info_set_length(slpmsg->p2p_info, len);
-	}
-
-#if 0
-	/* TODO: port this function to SlpMessageParts */
-	if (purple_debug_is_verbose())
-		msn_message_show_readable(msg, slpmsg->info, slpmsg->text_body);
-#endif
-
-#ifdef MSN_DEBUG_SLP_FILES
-	debug_part_to_file(slpmsg, TRUE);
-#endif
-
-	slpmsg->parts = g_list_append(slpmsg->parts, part);
-	msn_slplink_send_part(slplink, part);
-
-
-	if (msn_p2p_msg_is_data(info) && slpmsg->slpcall != NULL)
-	{
-		slpmsg->slpcall->progress = TRUE;
-
-		if (slpmsg->slpcall->progress_cb != NULL)
-		{
-			slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size,
-										 len);
-		}
-	}
-
-	/* slpmsg->offset += len; */
-}
-
-static void
-msn_slplink_release_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
-{
-	MsnP2PInfo *info;
-	guint32 flags;
-
-	info = slpmsg->p2p_info;
-
-	flags = msn_p2p_info_get_flags(info);
-	if (flags == P2P_NO_FLAG)
-	{
-		msn_p2p_info_set_ack_id(info, rand() % 0xFFFFFF00);
-	}
-	else if (msn_p2p_msg_is_data(info))
-	{
-		MsnSlpCall *slpcall;
-		slpcall = slpmsg->slpcall;
-
-		g_return_if_fail(slpcall != NULL);
-		msn_p2p_info_set_session_id(info, slpcall->session_id);
-		msn_p2p_info_set_app_id(info, slpcall->app_id);
-		msn_p2p_info_set_ack_id(info, rand() % 0xFFFFFF00);
-	}
-
-	msn_p2p_info_set_id(info, slpmsg->id);
-
-	msn_p2p_info_set_total_size(info, slpmsg->size);
-
-	msn_slplink_send_msgpart(slplink, slpmsg);
-}
-
-void
-msn_slplink_queue_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
-{
-	g_return_if_fail(slpmsg != NULL);
-
-	slpmsg->id = slplink->slp_seq_id++;
-
-	g_queue_push_tail(slplink->slp_msg_queue, slpmsg);
-}
-
-void
-msn_slplink_send_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
-{
-	slpmsg->id = slplink->slp_seq_id++;
-
-	msn_slplink_release_slpmsg(slplink, slpmsg);
-}
-
-void
-msn_slplink_send_queued_slpmsgs(MsnSlpLink *slplink)
-{
-	MsnSlpMessage *slpmsg;
-
-	/* Send the queued msgs in the order they were created */
-	while ((slpmsg = g_queue_pop_head(slplink->slp_msg_queue)) != NULL)
-	{
-		msn_slplink_release_slpmsg(slplink, slpmsg);
-	}
-}
-
-static void
-msn_slplink_send_ack(MsnSlpLink *slplink, MsnP2PInfo *info)
-{
-	MsnSlpMessage *slpmsg = msn_slpmsg_ack_new(slplink, info);
-
-	msn_slplink_send_slpmsg(slplink, slpmsg);
-	msn_slpmsg_destroy(slpmsg);
-}
-
-static MsnSlpMessage *
-msn_slplink_message_find(MsnSlpLink *slplink, guint32 session_id, long id)
-{
-	GList *e;
-
-	for (e = slplink->slp_msgs; e != NULL; e = e->next)
-	{
-		MsnSlpMessage *slpmsg = e->data;
-
-		if ((msn_p2p_info_get_session_id(slpmsg->p2p_info) == session_id) && (slpmsg->id == id))
-			return slpmsg;
-	}
-
-	return NULL;
-}
-
-static MsnSlpMessage *
-init_first_msg(MsnSlpLink *slplink, MsnP2PInfo *info)
-{
-	MsnSlpMessage *slpmsg;
-	guint32 session_id;
-
-	slpmsg = msn_slpmsg_new(slplink, NULL);
-	slpmsg->id = msn_p2p_info_get_id(info);
-	session_id = msn_p2p_info_get_session_id(info);
-	slpmsg->size = msn_p2p_info_get_total_size(info);
-	msn_p2p_info_init_first(slpmsg->p2p_info, info);
-
-	if (session_id)
-	{
-		slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, session_id);
-		if (slpmsg->slpcall != NULL)
-		{
-			if (msn_p2p_msg_is_data(info))
-			{
-				PurpleXfer *xfer = slpmsg->slpcall->xfer;
-				if (xfer != NULL)
-				{
-					slpmsg->ft = TRUE;
-					slpmsg->slpcall->xfer_msg = slpmsg;
-
-					purple_xfer_ref(xfer);
-					purple_xfer_start(xfer,	-1, NULL, 0);
-
-					if (xfer->data == NULL) {
-						purple_xfer_unref(xfer);
-						msn_slpmsg_destroy(slpmsg);
-						g_return_val_if_reached(NULL);
-					} else {
-						purple_xfer_unref(xfer);
-					}
-				}
-			}
-		}
-	}
-	if (!slpmsg->ft && slpmsg->size)
-	{
-		slpmsg->buffer = g_try_malloc(slpmsg->size);
-		if (slpmsg->buffer == NULL)
-		{
-			purple_debug_error("msn", "Failed to allocate buffer for slpmsg\n");
-			msn_slpmsg_destroy(slpmsg);
-			return NULL;
-		}
-	}
-
-	return slpmsg;
-}
-
-static void
-process_complete_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg, MsnP2PInfo *info)
-{
-	MsnSlpCall *slpcall;
-
-	slpcall = msn_slp_process_msg(slplink, slpmsg);
-
-	if (slpcall == NULL) {
-		msn_slpmsg_destroy(slpmsg);
-		return;
-	}
-
-	purple_debug_info("msn", "msn_slplink_process_msg: slpmsg complete\n");
-
-	if (msn_p2p_info_require_ack(slpmsg->p2p_info))
-	{
-		/* Release all the messages and send the ACK */
-
-		if (slpcall->wait_for_socket) {
-			/*
-			 * Save ack for later because we have to send
-			 * a 200 OK message to the previous direct connect
-			 * invitation before ACK but the listening socket isn't
-			 * created yet.
-			 */
-			purple_debug_info("msn", "msn_slplink_process_msg: save ACK\n");
-
-			slpcall->slplink->dc->prev_ack = msn_slpmsg_ack_new(slplink, info);
-		} else if (!slpcall->wasted) {
-			purple_debug_info("msn", "msn_slplink_process_msg: send ACK\n");
-
-			msn_slplink_send_ack(slplink, info);
-			msn_slplink_send_queued_slpmsgs(slplink);
-		}
-	}
-
-	msn_slpmsg_destroy(slpmsg);
-
-	if (!slpcall->wait_for_socket && slpcall->wasted)
-		msn_slpcall_destroy(slpcall);
-}
-
-static void
-slpmsg_add_part(MsnSlpMessage *slpmsg, MsnSlpMessagePart *part)
-{
-	if (slpmsg->ft) {
-		slpmsg->slpcall->u.incoming_data =
-				g_byte_array_append(slpmsg->slpcall->u.incoming_data, (const guchar *)part->buffer, part->size);
-		purple_xfer_prpl_ready(slpmsg->slpcall->xfer);
-	}
-	else if (slpmsg->size && slpmsg->buffer) {
-		guint64 offset = msn_p2p_info_get_offset(part->info);
-		if (G_MAXSIZE - part->size < offset
-				|| (offset + part->size) > slpmsg->size
-				|| msn_p2p_info_get_offset(slpmsg->p2p_info) != offset) {
-			purple_debug_error("msn",
-				"Oversized slpmsg - msgsize=%" G_GSIZE_FORMAT " offset=%" G_GUINT64_FORMAT " len=%" G_GSIZE_FORMAT "\n",
-				(gsize)slpmsg->size, offset, (gsize)part->size);
-			g_return_if_reached();
-		} else {
-			memcpy(slpmsg->buffer + offset, part->buffer, part->size);
-			msn_p2p_info_set_offset(slpmsg->p2p_info, offset + part->size);
-		}
-	}
-}
-
-void
-msn_slplink_process_msg(MsnSlpLink *slplink, MsnSlpMessagePart *part)
-{
-	MsnSlpMessage *slpmsg;
-	MsnP2PInfo *info;
-
-	info = part->info;
-
-	if (!msn_p2p_info_is_valid(info))
-	{
-		/* We seem to have received a bad header */
-		purple_debug_warning("msn", "Total size listed in SLP binary header "
-				"was less than length of this particular message.  This "
-				"should not happen.  Dropping message.\n");
-		return;
-	}
-
-	if (msn_p2p_info_is_first(info))
-		slpmsg = init_first_msg(slplink, info);
-	else {
-		guint32 session_id, id;
-		session_id = msn_p2p_info_get_session_id(info);
-		id = msn_p2p_info_get_id(info);
-		slpmsg = msn_slplink_message_find(slplink, session_id, id);
-		if (slpmsg == NULL)
-		{
-			/* Probably the transfer was cancelled */
-			purple_debug_error("msn", "Couldn't find slpmsg\n");
-			return;
-		}
-	}
-
-	slpmsg_add_part(slpmsg, part);
-
-	if (msn_p2p_msg_is_data(slpmsg->p2p_info) && slpmsg->slpcall != NULL)
-	{
-		slpmsg->slpcall->progress = TRUE;
-
-		if (slpmsg->slpcall->progress_cb != NULL)
-		{
-			slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size,
-										 part->size);
-		}
-	}
-
-#if 0
-	if (slpmsg->buffer == NULL)
-		return;
-#endif
-
-	/* All the pieces of the slpmsg have been received */
-	if (msn_p2p_info_is_final(info))
-		process_complete_msg(slplink, slpmsg, info);
-
-	/* NOTE: The slpmsg will be destroyed in process_complete_msg or left in
-	   the slplink until fully received. Don't free it here!
-	 */
-}
-
-void
-msn_slplink_request_object(MsnSlpLink *slplink,
-						   const char *info,
-						   MsnSlpCb cb,
-						   MsnSlpEndCb end_cb,
-						   const MsnObject *obj)
-{
-	MsnSlpCall *slpcall;
-	char *msnobj_data;
-	char *msnobj_base64;
-
-	g_return_if_fail(slplink != NULL);
-	g_return_if_fail(obj     != NULL);
-
-	msnobj_data = msn_object_to_string(obj);
-	msnobj_base64 = purple_base64_encode((const guchar *)msnobj_data, strlen(msnobj_data));
-	g_free(msnobj_data);
-
-	slpcall = msn_slpcall_new(slplink);
-	msn_slpcall_init(slpcall, MSN_SLPCALL_ANY);
-
-	slpcall->data_info = g_strdup(info);
-	slpcall->cb = cb;
-	slpcall->end_cb = end_cb;
-
-	msn_slpcall_invite(slpcall, MSN_OBJ_GUID, P2P_APPID_OBJ, msnobj_base64);
-
-	g_free(msnobj_base64);
-}
--- a/libpurple/protocols/msn/slplink.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-/**
- * @file slplink.h MSNSLP Link support
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_SLPLINK_H
-#define MSN_SLPLINK_H
-
-typedef struct _MsnSlpLink MsnSlpLink;
-
-#include "directconn.h"
-#include "session.h"
-#include "slpcall.h"
-#include "slpmsg.h"
-#include "switchboard.h"
-
-typedef void (*MsnSlpCb)(MsnSlpCall *slpcall,
-						 const guchar *data, gsize size);
-typedef void (*MsnSlpEndCb)(MsnSlpCall *slpcall, MsnSession *session);
-
-struct _MsnSlpLink
-{
-	MsnSession *session;
-	MsnSwitchBoard *swboard;
-	MsnDirectConn *dc;
-
-	guint refs;
-
-	char *remote_user;
-	MsnP2PVersion p2p_version;
-
-	int slp_seq_id;
-
-	GList *slp_calls;
-	GList *slp_msgs;
-
-	GQueue *slp_msg_queue;
-};
-
-MsnSlpLink *msn_slplink_ref(MsnSlpLink *slplink);
-void msn_slplink_unref(MsnSlpLink *slplink);
-
-/**
- * @return An MsnSlpLink for the given user, or NULL if there is no
- *         existing MsnSlpLink.
- */
-MsnSlpLink *msn_session_find_slplink(MsnSession *session,
-									 const char *who);
-
-/**
- * @return An MsnSlpLink for the given user.  One will be created if
- *         it does not already exist.
- */
-MsnSlpLink *msn_session_get_slplink(MsnSession *session, const char *username);
-
-void msn_slplink_add_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall);
-void msn_slplink_remove_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall);
-MsnSlpCall *msn_slplink_find_slp_call(MsnSlpLink *slplink,
-									  const char *id);
-MsnSlpCall *msn_slplink_find_slp_call_with_session_id(MsnSlpLink *slplink, long id);
-MsnP2PVersion msn_slplink_get_p2p_version(MsnSlpLink *slplink);
-
-void msn_slplink_queue_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg);
-void msn_slplink_send_slpmsg(MsnSlpLink *slplink,
-							 MsnSlpMessage *slpmsg);
-void msn_slplink_send_queued_slpmsgs(MsnSlpLink *slplink);
-void msn_slplink_process_msg(MsnSlpLink *slplink, MsnSlpMessagePart *part);
-
-/* Only exported for msn_xfer_write */
-void msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg);
-
-void msn_slplink_request_object(MsnSlpLink *slplink,
-								const char *info,
-								MsnSlpCb cb,
-								MsnSlpEndCb end_cb,
-								const MsnObject *obj);
-
-MsnSlpCall *msn_slp_process_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg);
-
-#endif /* MSN_SLPLINK_H */
--- a/libpurple/protocols/msn/slpmsg.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,309 +0,0 @@
-/**
- * @file slpmsg.c SLP Message functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-
-#include "slpmsg.h"
-#include "slpmsg_part.h"
-#include "slplink.h"
-
-/**************************************************************************
- * SLP Message
- **************************************************************************/
-
-MsnSlpMessage *
-msn_slpmsg_new(MsnSlpLink *slplink, MsnSlpCall *slpcall)
-{
-	MsnSlpMessage *slpmsg;
-	MsnP2PVersion p2p;
-
-	g_return_val_if_fail(slplink != NULL, NULL);
-
-	slpmsg = g_new0(MsnSlpMessage, 1);
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "slpmsg new (%p)\n", slpmsg);
-
-	msn_slpmsg_set_slplink(slpmsg, slplink);
-	slpmsg->slpcall = slpcall;
-
-	p2p = msn_slplink_get_p2p_version(slplink);
-	slpmsg->p2p_info = msn_p2p_info_new(p2p);
-
-	return slpmsg;
-}
-
-void
-msn_slpmsg_destroy(MsnSlpMessage *slpmsg)
-{
-	MsnSlpLink *slplink;
-	GList *cur;
-
-	g_return_if_fail(slpmsg != NULL);
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "slpmsg destroy (%p)\n", slpmsg);
-
-	slplink = slpmsg->slplink;
-
-	purple_imgstore_unref(slpmsg->img);
-
-	/* We don't want to free the data of the PurpleStoredImage,
-	 * but to avoid code duplication, it's sharing buffer. */
-	if (slpmsg->img == NULL)
-		g_free(slpmsg->buffer);
-
-	for (cur = slpmsg->parts; cur != NULL; cur = g_list_delete_link(cur, cur))
-	{
-		/* Something is pointing to this slpmsg, so we should remove that
-		 * pointer to prevent a crash. */
-		/* Ex: a user goes offline and after that we receive an ACK */
-
-		MsnSlpMessagePart *part = cur->data;
-
-		part->ack_cb = NULL;
-		part->nak_cb = NULL;
-		part->ack_data = NULL;
-		msn_slpmsgpart_unref(part);
-	}
-
-	slplink->slp_msgs = g_list_remove(slplink->slp_msgs, slpmsg);
-
-	msn_p2p_info_free(slpmsg->p2p_info);
-
-	g_free(slpmsg);
-}
-
-void
-msn_slpmsg_set_slplink(MsnSlpMessage *slpmsg, MsnSlpLink *slplink)
-{
-	g_return_if_fail(slplink != NULL);
-
-	slpmsg->slplink = slplink;
-
-	slplink->slp_msgs =
-		g_list_append(slplink->slp_msgs, slpmsg);
-}
-
-void
-msn_slpmsg_set_body(MsnSlpMessage *slpmsg, const char *body,
-						 long long size)
-{
-	/* We can only have one data source at a time. */
-	g_return_if_fail(slpmsg->buffer == NULL);
-	g_return_if_fail(slpmsg->img == NULL);
-	g_return_if_fail(slpmsg->ft == FALSE);
-
-	if (body != NULL)
-		slpmsg->buffer = g_memdup(body, size);
-	else
-		slpmsg->buffer = g_new0(guchar, size);
-
-	slpmsg->size = size;
-}
-
-void
-msn_slpmsg_set_image(MsnSlpMessage *slpmsg, PurpleStoredImage *img)
-{
-	/* We can only have one data source at a time. */
-	g_return_if_fail(slpmsg->buffer == NULL);
-	g_return_if_fail(slpmsg->img == NULL);
-	g_return_if_fail(slpmsg->ft == FALSE);
-
-	slpmsg->img = purple_imgstore_ref(img);
-	slpmsg->buffer = (guchar *)purple_imgstore_get_data(img);
-	slpmsg->size = purple_imgstore_get_size(img);
-}
-
-
-MsnSlpMessage *
-msn_slpmsg_sip_new(MsnSlpCall *slpcall, int cseq,
-				   const char *header, const char *branch,
-				   const char *content_type, const char *content)
-{
-	MsnSlpLink *slplink;
-	PurpleAccount *account;
-	MsnSlpMessage *slpmsg;
-	char *body;
-	gsize body_len;
-	gsize content_len;
-
-	g_return_val_if_fail(slpcall != NULL, NULL);
-	g_return_val_if_fail(header  != NULL, NULL);
-
-	slplink = slpcall->slplink;
-	account = slplink->session->account;
-
-	/* Let's remember that "content" should end with a 0x00 */
-
-	content_len = (content != NULL) ? strlen(content) + 1 : 0;
-
-	body = g_strdup_printf(
-		"%s\r\n"
-		"To: <msnmsgr:%s>\r\n"
-		"From: <msnmsgr:%s>\r\n"
-		"Via: MSNSLP/1.0/TLP ;branch={%s}\r\n"
-		"CSeq: %d\r\n"
-		"Call-ID: {%s}\r\n"
-		"Max-Forwards: 0\r\n"
-		"Content-Type: %s\r\n"
-		"Content-Length: %" G_GSIZE_FORMAT "\r\n"
-		"\r\n",
-		header,
-		slplink->remote_user,
-		purple_account_get_username(account),
-		branch,
-		cseq,
-		slpcall->id,
-		content_type,
-		content_len);
-
-	body_len = strlen(body);
-
-	if (content_len > 0)
-	{
-		body_len += content_len;
-		body = g_realloc(body, body_len);
-		g_strlcat(body, content, body_len);
-	}
-
-	slpmsg = msn_slpmsg_new(slplink, slpcall);
-	msn_slpmsg_set_body(slpmsg, body, body_len);
-
-	g_free(body);
-
-	return slpmsg;
-}
-
-MsnSlpMessage *msn_slpmsg_ack_new(MsnSlpLink *slplink, MsnP2PInfo *ack_info)
-{
-	MsnSlpMessage *slpmsg;
-	MsnP2PInfo *new_info;
-
-	slpmsg = msn_slpmsg_new(slplink, NULL);
-
-	new_info = slpmsg->p2p_info;
-	msn_p2p_info_create_ack(ack_info, new_info);
-	slpmsg->size = msn_p2p_info_get_total_size(ack_info);
-	slpmsg->info = "SLP ACK";
-
-	return slpmsg;
-}
-
-MsnSlpMessage *msn_slpmsg_obj_new(MsnSlpCall *slpcall, PurpleStoredImage *img)
-{
-	MsnSlpMessage *slpmsg;
-
-	slpmsg = msn_slpmsg_new(slpcall->slplink, slpcall);
-	msn_p2p_info_set_flags(slpmsg->p2p_info, P2P_MSN_OBJ_DATA);
-	slpmsg->info = "SLP DATA";
-
-	msn_slpmsg_set_image(slpmsg, img);
-
-	return slpmsg;
-}
-
-MsnSlpMessage *msn_slpmsg_dataprep_new(MsnSlpCall *slpcall)
-{
-	MsnSlpMessage *slpmsg;
-
-	slpmsg = msn_slpmsg_new(slpcall->slplink, slpcall);
-
-	msn_p2p_info_set_session_id(slpmsg->p2p_info, slpcall->session_id);
-	msn_slpmsg_set_body(slpmsg, NULL, 4);
-	slpmsg->info = "SLP DATA PREP";
-
-	return slpmsg;
-
-}
-
-MsnSlpMessage *msn_slpmsg_file_new(MsnSlpCall *slpcall, size_t size)
-{
-	MsnSlpMessage *slpmsg;
-
-	slpmsg = msn_slpmsg_new(slpcall->slplink, slpcall);
-
-	msn_p2p_info_set_flags(slpmsg->p2p_info, P2P_FILE_DATA);
-	slpmsg->info = "SLP FILE";
-	slpmsg->size = size;
-
-	return slpmsg;
-}
-
-char *msn_slpmsg_serialize(MsnSlpMessage *slpmsg, size_t *ret_size)
-{
-	char *header;
-	char *footer;
-	char *base;
-	char *tmp;
-	size_t header_size, footer_size;
-
-	header = msn_p2p_header_to_wire(slpmsg->p2p_info, &header_size);
-	footer = msn_p2p_footer_to_wire(slpmsg->p2p_info, &footer_size);
-
-	base = g_malloc(header_size + slpmsg->size + footer_size);
-	tmp = base;
-
-	/* Copy header */
-	memcpy(tmp, header, header_size);
-	tmp += header_size;
-
-	/* Copy body */
-	memcpy(tmp, slpmsg->buffer, slpmsg->size);
-	tmp += slpmsg->size;
-
-	/* Copy footer */
-	memcpy(tmp, footer, footer_size);
-	tmp += footer_size;
-
-	*ret_size = tmp - base;
-
-	g_free(header);
-	g_free(footer);
-
-	return base;
-}
-
-void msn_slpmsg_show_readable(MsnSlpMessage *slpmsg)
-{
-	GString *str;
-
-	str = g_string_new(NULL);
-
-	msn_p2p_info_to_string(slpmsg->p2p_info, str);
-
-	if (purple_debug_is_verbose() && slpmsg->buffer != NULL) {
-		g_string_append_len(str, (gchar*)slpmsg->buffer, slpmsg->size);
-
-		if (slpmsg->buffer[slpmsg->size - 1] == '\0') {
-			str->len--;
-			g_string_append(str, " 0x00");
-		}
-		g_string_append(str, "\r\n");
-
-	}
-
-	purple_debug_info("msn", "SlpMessage %s:\n{%s}\n", slpmsg->info, str->str);
-}
--- a/libpurple/protocols/msn/slpmsg.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/**
- * @file slpmsg.h SLP Message functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef _MSN_SLPMSG_H_
-#define _MSN_SLPMSG_H_
-
-typedef struct _MsnSlpMessage MsnSlpMessage;
-
-#include "imgstore.h"
-
-#include "slpcall.h"
-#include "slplink.h"
-#include "session.h"
-#include "p2p.h"
-
-#include "slp.h"
-
-/**
- * A SLP Message  This contains everything that we will need to send a SLP
- * Message even if has to be sent in several parts.
- */
-struct _MsnSlpMessage
-{
-	MsnSlpCall *slpcall; /**< The slpcall to which this slp message belongs (if applicable). */
-	MsnSlpLink *slplink; /**< The slplink through which this slp message is being sent. */
-	MsnSession *session;
-
-	MsnP2PInfo *p2p_info;
-
-	long id;
-
-	gboolean ft;
-	PurpleStoredImage *img;
-	guchar *buffer;
-
-	/**
-	 * This is the size of buffer, unless this is an outgoing file transfer,
-	 * in which case this is the size of the file.
-	 */
-	gsize size;
-
-	GList *parts; /**< A list with the SlpMsgParts */
-
-	const char *info;
-	gboolean text_body;
-};
-
-/**
- * Creates a new slp message
- *
- * @param slplink The slplink through which this slp message will be sent.
- * If it's set to NULL, it is a temporary SlpMessage.
- * @return The created slp message.
- */
-MsnSlpMessage *msn_slpmsg_new(MsnSlpLink *slplink, MsnSlpCall *slpcall);
-
-/**
- * Destroys a slp message
- *
- * @param slpmsg The slp message to destory.
- */
-void msn_slpmsg_destroy(MsnSlpMessage *slpmsg);
-
-/**
- * Relate this SlpMessage with an existing SlpLink
- *
- * @param slplink 	The SlpLink that will send this message.
- */
-void msn_slpmsg_set_slplink(MsnSlpMessage *slpmsg, MsnSlpLink *slplink);
-
-void msn_slpmsg_set_body(MsnSlpMessage *slpmsg, const char *body,
-						 long long size);
-void msn_slpmsg_set_image(MsnSlpMessage *slpmsg, PurpleStoredImage *img);
-MsnSlpMessage * msn_slpmsg_sip_new(MsnSlpCall *slpcall, int cseq,
-								   const char *header,
-								   const char *branch,
-								   const char *content_type,
-								   const char *content);
-
-/**
- * Create a new SLP Ack message
- *
- * @param header the value of the header in this slpmsg.
- *
- * @return A new SlpMessage with ACK headers
- */
-MsnSlpMessage *msn_slpmsg_ack_new(MsnSlpLink *slplink, MsnP2PInfo *info);
-
-/**
- * Create a new SLP message for MsnObject data.
- *
- * @param slpcall 	The slpcall that manages this message.
- * @param img 		The image to be sent in this message.
- *
- * @return A new SlpMessage with MsnObject info.
- */
-MsnSlpMessage *msn_slpmsg_obj_new(MsnSlpCall *slpcall, PurpleStoredImage *img);
-
-/**
- * Create a new SLP message for data preparation.
- *
- * @param slpcall 	The slpcall that manages this message.
- *
- * @return A new SlpMessage with data preparation info.
- */
-MsnSlpMessage *msn_slpmsg_dataprep_new(MsnSlpCall *slpcall);
-
-/**
- * Create a new SLP message for File transfer.
- *
- * @param slpcall 	The slpcall that manages this message.
- * @param size 		The size of the file being transsmited.
- *
- * @return A new SlpMessage with the file transfer info.
- */
-MsnSlpMessage *msn_slpmsg_file_new(MsnSlpCall *slpcall, size_t size);
-
-/**
- * Serialize the MsnSlpMessage in a way it can be used to be transmited
- *
- * @param slpmsg 	The MsnSlpMessage.
- * @param ret_size 	The size of the buffer cointaining the message.
- *
- * @return a buffer with the serialized data.
- */
-char *msn_slpmsg_serialize(MsnSlpMessage *slpmsg, size_t *ret_size);
-
-void msn_slpmsg_show_readable(MsnSlpMessage *slpmsg);
-
-#endif /* _MSN_SLPMSG_H_ */
--- a/libpurple/protocols/msn/slpmsg_part.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,232 +0,0 @@
-/**
- * @file slpmsg_part.c MSNSLP Parts
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-
-#include "slpmsg.h"
-#include "slpmsg_part.h"
-
-MsnSlpMessagePart *msn_slpmsgpart_new(MsnP2PInfo *info)
-{
-	MsnSlpMessagePart *part;
-
-	part = g_new0(MsnSlpMessagePart, 1);
-
-	part->info = info;
-
-	part->ack_cb = msn_slpmsgpart_ack;
-	part->nak_cb = msn_slpmsgpart_nak;
-
-	return msn_slpmsgpart_ref(part);
-}
-
-MsnSlpMessagePart *
-msn_slpmsgpart_new_from_data(MsnP2PVersion p2p, const char *data, size_t data_len)
-{
-	MsnSlpMessagePart *part;
-	MsnP2PInfo *info;
-	size_t len;
-	int body_len;
-
-	info = msn_p2p_info_new(p2p);
-
-	/* Extract the binary SLP header */
-	len = msn_p2p_header_from_wire(info, data, data_len);
-	if (len == 0) {
-		msn_p2p_info_free(info);
-		return NULL;
-	}
-	data += len;
-	part = msn_slpmsgpart_new(info);
-
-	/* Extract the body */
-	body_len = data_len - len - P2P_PACKET_FOOTER_SIZE;
-	/* msg->body_len = msg->msnslp_header.length; */
-
-	if (body_len > 0) {
-		part->size = body_len;
-		part->buffer = g_malloc(body_len);
-		memcpy(part->buffer, data, body_len);
-		data += body_len;
-	}
-
-	/* Extract the footer */
-	if (body_len >= 0)
-		msn_p2p_footer_from_wire(part->info, data);
-
-	return part;
-}
-
-static void msn_slpmsgpart_destroy(MsnSlpMessagePart *part)
-{
-	g_free(part->info);
-	g_free(part->buffer);
-
-	g_free(part);
-
-}
-
-MsnSlpMessagePart *msn_slpmsgpart_ref(MsnSlpMessagePart *part)
-{
-	g_return_val_if_fail(part != NULL, NULL);
-	part->ref_count++;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "part ref (%p)[%u]\n", part, part->ref_count);
-
-	return part;
-}
-
-void msn_slpmsgpart_unref(MsnSlpMessagePart *part)
-{
-	g_return_if_fail(part != NULL);
-	g_return_if_fail(part->ref_count > 0);
-
-	part->ref_count--;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "part unref (%p)[%u]\n", part, part->ref_count);
-
-	if (part->ref_count == 0) {
-		msn_slpmsgpart_destroy(part);
-	}
-}
-
-void msn_slpmsgpart_set_bin_data(MsnSlpMessagePart *part, const void *data, size_t len)
-{
-	g_return_if_fail(part != NULL);
-
-	g_free(part->buffer);
-
-	if (data != NULL && len > 0) {
-		part->buffer = g_malloc(len + 1);
-		memcpy(part->buffer, data, len);
-		part->buffer[len] = '\0';
-		part->size = len;
-	} else {
-		part->buffer = NULL;
-		part->size = 0;
-	}
-
-}
-
-char *msn_slpmsgpart_serialize(MsnSlpMessagePart *part, size_t *ret_size)
-{
-	char *header;
-	char *footer;
-	char *base;
-	char *tmp;
-	size_t header_size, footer_size;
-
-	header = msn_p2p_header_to_wire(part->info, &header_size);
-	footer = msn_p2p_footer_to_wire(part->info, &footer_size);
-
-	base = g_malloc(header_size + part->size + footer_size);
-	tmp = base;
-
-	/* Copy header */
-	memcpy(tmp, header, header_size);
-	tmp += header_size;
-
-	/* Copy body */
-	memcpy(tmp, part->buffer, part->size);
-	tmp += part->size;
-
-	/* Copy footer */
-	memcpy(tmp, footer, footer_size);
-	tmp += footer_size;
-
-	*ret_size = tmp - base;
-
-	g_free(header);
-	g_free(footer);
-
-	return base;
-}
-
-/* We have received the message ack */
-void
-msn_slpmsgpart_ack(MsnSlpMessagePart *part, void *data)
-{
-	MsnSlpMessage *slpmsg;
-	guint64 offset;
-	gsize real_size;
-
-	slpmsg = data;
-
-	real_size = msn_p2p_info_is_ack(slpmsg->p2p_info) ? 0 : slpmsg->size;
-
-	offset = msn_p2p_info_get_offset(slpmsg->p2p_info);
-	offset += msn_p2p_info_get_length(part->info);
-	msn_p2p_info_set_offset(slpmsg->p2p_info, offset);
-
-	slpmsg->parts = g_list_remove(slpmsg->parts, part);
-	msn_slpmsgpart_unref(part);
-
-	if (offset < real_size)
-	{
-		if (slpmsg->slpcall->xfer && purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED)
-		{
-			slpmsg->slpcall->xfer_msg = slpmsg;
-			purple_xfer_prpl_ready(slpmsg->slpcall->xfer);
-		}
-		else
-			msn_slplink_send_msgpart(slpmsg->slplink, slpmsg);
-	}
-	else
-	{
-		/* The whole message has been sent */
-		if (msn_p2p_msg_is_data(slpmsg->p2p_info))
-		{
-			if (slpmsg->slpcall != NULL)
-			{
-				if (slpmsg->slpcall->cb)
-					slpmsg->slpcall->cb(slpmsg->slpcall,
-						NULL, 0);
-			}
-		}
-	}
-}
-
-/* We have received the message nak. */
-void
-msn_slpmsgpart_nak(MsnSlpMessagePart *part, void *data)
-{
-	MsnSlpMessage *slpmsg;
-
-	slpmsg = data;
-
-	msn_slplink_send_msgpart(slpmsg->slplink, slpmsg);
-
-	slpmsg->parts = g_list_remove(slpmsg->parts, part);
-	msn_slpmsgpart_unref(part);
-}
-
-void
-msn_slpmsgpart_to_string(MsnSlpMessagePart *part, GString *str)
-{
-	msn_p2p_info_to_string(part->info, str);
-}
-
--- a/libpurple/protocols/msn/slpmsg_part.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/**
- * @file slpmsg_part.h MSNSLP Parts
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#ifndef MSN_SLPMSG_PART_H
-#define MSN_SLPMSG_PART_H
-
-#include "p2p.h"
-
-typedef struct _MsnSlpMessagePart MsnSlpMessagePart;
-typedef void (*MsnSlpPartCb)(MsnSlpMessagePart *part, void *data);
-
-struct _MsnSlpMessagePart
-{
-	guint ref_count;
-
-	MsnP2PInfo *info;
-
-	MsnSlpPartCb ack_cb;
-	MsnSlpPartCb nak_cb;
-	void *ack_data;
-
-	guchar *buffer;
-	size_t size;
-};
-
-MsnSlpMessagePart *msn_slpmsgpart_new(MsnP2PInfo *info);
-
-MsnSlpMessagePart *msn_slpmsgpart_new_from_data(MsnP2PVersion p2p, const char *data, size_t data_len);
-
-MsnSlpMessagePart *msn_slpmsgpart_ref(MsnSlpMessagePart *part);
-
-void msn_slpmsgpart_unref(MsnSlpMessagePart *part);
-
-void msn_slpmsgpart_set_bin_data(MsnSlpMessagePart *part, const void *data, size_t len);
-
-char *msn_slpmsgpart_serialize(MsnSlpMessagePart *part, size_t *ret_size);
-
-void msn_slpmsgpart_ack(MsnSlpMessagePart *part, void *data);
-
-void msn_slpmsgpart_nak(MsnSlpMessagePart *part, void *data);
-
-void msn_slpmsgpart_to_string(MsnSlpMessagePart *part, GString *str);
-
-#endif /* MSN_SLPMSG_PART_H */
-
--- a/libpurple/protocols/msn/soap.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,688 +0,0 @@
-/**
- * @file soap.c
- * Functions relating to SOAP connections.
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA
- */
-
-#include "internal.h"
-
-#include "soap.h"
-
-#include "session.h"
-
-#include "debug.h"
-#include "xmlnode.h"
-
-#include <glib.h>
-#if !defined(_WIN32) || !defined(_WINERROR_)
-#include <error.h>
-#endif
-
-#define SOAP_TIMEOUT (5 * 60)
-
-typedef struct _MsnSoapRequest {
-	char *path;
-	MsnSoapMessage *message;
-	gboolean secure;
-	MsnSoapCallback cb;
-	gpointer cb_data;
-} MsnSoapRequest;
-
-typedef struct _MsnSoapConnection {
-	MsnSession *session;
-	char *host;
-
-	time_t last_used;
-	PurpleSslConnection *ssl;
-	gboolean connected;
-
-	guint event_handle;
-	guint run_timer;
-	GString *buf;
-	gsize handled_len;
-	gsize body_len;
-	int response_code;
-	gboolean headers_done;
-	gboolean close_when_done;
-
-	MsnSoapMessage *message;
-
-	GQueue *queue;
-	MsnSoapRequest *current_request;
-} MsnSoapConnection;
-
-static gboolean msn_soap_connection_run(gpointer data);
-
-static MsnSoapConnection *
-msn_soap_connection_new(MsnSession *session, const char *host)
-{
-	MsnSoapConnection *conn = g_new0(MsnSoapConnection, 1);
-	conn->session = session;
-	conn->host = g_strdup(host);
-	conn->queue = g_queue_new();
-	return conn;
-}
-
-static void
-msn_soap_message_destroy(MsnSoapMessage *message)
-{
-	g_slist_foreach(message->headers, (GFunc)g_free, NULL);
-	g_slist_free(message->headers);
-	g_free(message->action);
-	if (message->xml)
-		xmlnode_free(message->xml);
-	g_free(message);
-}
-
-static void
-msn_soap_request_destroy(MsnSoapRequest *req, gboolean keep_message)
-{
-	g_free(req->path);
-	if (!keep_message)
-		msn_soap_message_destroy(req->message);
-	g_free(req);
-}
-
-static void
-msn_soap_connection_sanitize(MsnSoapConnection *conn, gboolean disconnect)
-{
-	if (conn->event_handle) {
-		purple_input_remove(conn->event_handle);
-		conn->event_handle = 0;
-	}
-
-	if (conn->run_timer) {
-		purple_timeout_remove(conn->run_timer);
-		conn->run_timer = 0;
-	}
-
-	if (conn->message) {
-		msn_soap_message_destroy(conn->message);
-		conn->message = NULL;
-	}
-
-	if (conn->buf) {
-		g_string_free(conn->buf, TRUE);
-		conn->buf = NULL;
-	}
-
-	if (conn->ssl && (disconnect || conn->close_when_done)) {
-		purple_ssl_close(conn->ssl);
-		conn->ssl = NULL;
-	}
-
-	if (conn->current_request) {
-		msn_soap_request_destroy(conn->current_request, FALSE);
-		conn->current_request = NULL;
-	}
-}
-
-static void
-msn_soap_connection_destroy_foreach_cb(gpointer item, gpointer data)
-{
-	MsnSoapRequest *req = item;
-
-	req->cb(req->message, NULL, req->cb_data);
-
-	msn_soap_request_destroy(req, FALSE);
-}
-
-static void
-msn_soap_connection_destroy(MsnSoapConnection *conn)
-{
-	if (conn->current_request) {
-		MsnSoapRequest *req = conn->current_request;
-		conn->current_request = NULL;
-		msn_soap_connection_destroy_foreach_cb(req, conn);
-	}
-
-	msn_soap_connection_sanitize(conn, TRUE);
-	g_queue_foreach(conn->queue, msn_soap_connection_destroy_foreach_cb, conn);
-	g_queue_free(conn->queue);
-
-	g_free(conn->host);
-	g_free(conn);
-}
-
-static gboolean
-msn_soap_cleanup_each(gpointer key, gpointer value, gpointer data)
-{
-	MsnSoapConnection *conn = value;
-	time_t *t = data;
-
-	if ((*t - conn->last_used) > SOAP_TIMEOUT * 2) {
-		purple_debug_info("soap", "cleaning up soap conn %p\n", conn);
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-static gboolean
-msn_soap_cleanup_for_session(gpointer data)
-{
-	MsnSession *sess = data;
-	time_t t = time(NULL);
-
-	purple_debug_info("soap", "session cleanup timeout\n");
-
-	if (sess->soap_table) {
-		g_hash_table_foreach_remove(sess->soap_table, msn_soap_cleanup_each,
-			&t);
-
-		if (g_hash_table_size(sess->soap_table) != 0)
-			return TRUE;
-	}
-
-	sess->soap_cleanup_handle = 0;
-	return FALSE;
-}
-
-static MsnSoapConnection *
-msn_soap_get_connection(MsnSession *session, const char *host)
-{
-	MsnSoapConnection *conn = NULL;
-
-	if (session->soap_table) {
-		conn = g_hash_table_lookup(session->soap_table, host);
-	} else {
-		session->soap_table = g_hash_table_new_full(g_str_hash, g_str_equal,
-			NULL, (GDestroyNotify)msn_soap_connection_destroy);
-	}
-
-	if (session->soap_cleanup_handle == 0)
-		session->soap_cleanup_handle = purple_timeout_add_seconds(SOAP_TIMEOUT,
-			msn_soap_cleanup_for_session, session);
-
-	if (conn == NULL) {
-		conn = msn_soap_connection_new(session, host);
-		g_hash_table_insert(session->soap_table, conn->host, conn);
-	}
-
-	conn->last_used = time(NULL);
-
-	return conn;
-}
-
-static void
-msn_soap_connection_handle_next(MsnSoapConnection *conn)
-{
-	msn_soap_connection_sanitize(conn, FALSE);
-
-	conn->run_timer = purple_timeout_add(0, msn_soap_connection_run, conn);
-}
-
-static void
-msn_soap_message_send_internal(MsnSession *session, MsnSoapMessage *message,
-	const char *host, const char *path, gboolean secure,
-	MsnSoapCallback cb, gpointer cb_data, gboolean first)
-{
-	MsnSoapConnection *conn = msn_soap_get_connection(session, host);
-	MsnSoapRequest *req = g_new0(MsnSoapRequest, 1);
-
-	req->path = g_strdup(path);
-	req->message = message;
-	req->secure = secure;
-	req->cb = cb;
-	req->cb_data = cb_data;
-
-	if (first) {
-		g_queue_push_head(conn->queue, req);
-	} else {
-		g_queue_push_tail(conn->queue, req);
-	}
-
-	if (conn->run_timer == 0)
-		conn->run_timer = purple_timeout_add(0, msn_soap_connection_run,
-			conn);
-}
-
-void
-msn_soap_message_send(MsnSession *session, MsnSoapMessage *message,
-	const char *host, const char *path, gboolean secure,
-	MsnSoapCallback cb, gpointer cb_data)
-{
-	g_return_if_fail(message != NULL);
-	g_return_if_fail(cb != NULL);
-
-	msn_soap_message_send_internal(session, message, host, path, secure,
-		cb, cb_data, FALSE);
-}
-
-static gboolean
-msn_soap_handle_redirect(MsnSoapConnection *conn, const char *url)
-{
-	char *host;
-	char *path;
-
-	if (purple_url_parse(url, &host, NULL, &path, NULL, NULL)) {
-		MsnSoapRequest *req = conn->current_request;
-		conn->current_request = NULL;
-
-		msn_soap_message_send_internal(conn->session, req->message, host, path,
-			req->secure, req->cb, req->cb_data, TRUE);
-
-		msn_soap_request_destroy(req, TRUE);
-
-		g_free(host);
-		g_free(path);
-
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-static gboolean
-msn_soap_handle_body(MsnSoapConnection *conn, MsnSoapMessage *response)
-{
-	xmlnode *body = xmlnode_get_child(response->xml, "Body");
-	xmlnode *fault = xmlnode_get_child(response->xml, "Fault");
-
-	if (fault) {
-		xmlnode *faultcode = xmlnode_get_child(fault, "faultcode");
-
-		if (faultcode != NULL) {
-			char *faultdata = xmlnode_get_data(faultcode);
-
-			if (faultdata && g_str_equal(faultdata, "psf:Redirect")) {
-				xmlnode *url = xmlnode_get_child(fault, "redirectUrl");
-
-				if (url) {
-					char *urldata = xmlnode_get_data(url);
-					if (urldata)
-						msn_soap_handle_redirect(conn, urldata);
-					g_free(urldata);
-				}
-
-				g_free(faultdata);
-				msn_soap_message_destroy(response);
-				return TRUE;
-			} else if (faultdata && g_str_equal(faultdata, "wsse:FailedAuthentication")) {
-				xmlnode *reason = xmlnode_get_child(fault, "faultstring");
-				char *reasondata = NULL;
-
-				if (reason)
-					reasondata = xmlnode_get_data(reason);
-
-				msn_soap_connection_sanitize(conn, TRUE);
-				msn_session_set_error(conn->session, MSN_ERROR_AUTH,
-					reasondata);
-
-				g_free(reasondata);
-				g_free(faultdata);
-				msn_soap_message_destroy(response);
-				return FALSE;
-			}
-
-			g_free(faultdata);
-		}
-	}
-
-	if (fault || body) {
-		if (conn->current_request) {
-			MsnSoapRequest *request = conn->current_request;
-			conn->current_request = NULL;
-			request->cb(request->message, response,
-				request->cb_data);
-			msn_soap_request_destroy(request, FALSE);
-		}
-		msn_soap_message_destroy(response);
-	}
-
-	return TRUE;
-}
-
-static void
-msn_soap_message_add_header(MsnSoapMessage *message,
-		const char *name, const char *value)
-{
-	char *header = g_strdup_printf("%s: %s\r\n", name, value);
-
-	message->headers = g_slist_prepend(message->headers, header);
-}
-
-static void
-msn_soap_process(MsnSoapConnection *conn)
-{
-	gboolean handled = FALSE;
-	char *cursor;
-	char *linebreak;
-
-	cursor = conn->buf->str + conn->handled_len;
-
-	if (!conn->headers_done) {
-		while ((linebreak = strstr(cursor, "\r\n"))	!= NULL) {
-			conn->handled_len = linebreak - conn->buf->str + 2;
-
-			if (conn->response_code == 0) {
-				if (sscanf(cursor, "HTTP/1.1 %d", &conn->response_code) != 1) {
-					/* something horribly wrong */
-					purple_ssl_close(conn->ssl);
-					conn->ssl = NULL;
-					handled = TRUE;
-					break;
-				} else if (conn->response_code == 503 && conn->session->login_step < MSN_LOGIN_STEP_END) {
-					msn_soap_connection_sanitize(conn, TRUE);
-					msn_session_set_error(conn->session, MSN_ERROR_SERV_UNAVAILABLE, NULL);
-					return;
-				}
-			} else if (cursor == linebreak) {
-				/* blank line */
-				conn->headers_done = TRUE;
-				cursor = conn->buf->str + conn->handled_len;
-				break;
-			} else {
-				char *line = g_strndup(cursor, linebreak - cursor);
-				char *sep = strstr(line, ": ");
-				char *key = line;
-				char *value;
-
-				if (sep == NULL) {
-					purple_debug_info("soap", "ignoring malformed line: %s\n", line);
-					g_free(line);
-					goto loop_end;
-				}
-
-				value = sep + 2;
-				*sep = '\0';
-				msn_soap_message_add_header(conn->message, key, value);
-
-				if ((conn->response_code == 301 || conn->response_code == 300)
-					&& strcmp(key, "Location") == 0) {
-
-					msn_soap_handle_redirect(conn, value);
-
-					handled = TRUE;
-					g_free(line);
-					break;
-				} else if (conn->response_code == 401 &&
-					strcmp(key, "WWW-Authenticate") == 0) {
-					char *error = strstr(value, "cbtxt=");
-
-					if (error) {
-						error += strlen("cbtxt=");
-					}
-
-					msn_soap_connection_sanitize(conn, TRUE);
-					msn_session_set_error(conn->session, MSN_ERROR_AUTH,
-						error ? purple_url_decode(error) : NULL);
-
-					g_free(line);
-					return;
-				} else if (strcmp(key, "Content-Length") == 0) {
-					if (sscanf(value, "%" G_GSIZE_FORMAT, &(conn->body_len)) != 1)
-						purple_debug_error("soap", "Unable to parse Content-Length\n");
-				} else if (strcmp(key, "Connection") == 0) {
-					if (strcmp(value, "close") == 0) {
-						conn->close_when_done = TRUE;
-					}
-				}
-				g_free(line);
-			}
-
-		loop_end:
-			cursor = conn->buf->str + conn->handled_len;
-		}
-	}
-
-	if (!handled && conn->headers_done) {
-		if (conn->buf->len - conn->handled_len >=
-			conn->body_len) {
-			xmlnode *node = xmlnode_from_str(cursor, conn->body_len);
-
-			if (node == NULL) {
-				purple_debug_info("soap", "Malformed SOAP response: %s\n",
-					cursor);
-			} else {
-				MsnSoapMessage *message = conn->message;
-				conn->message = NULL;
-				message->xml = node;
-
-				if (!msn_soap_handle_body(conn, message)) {
-					return;
-				}
-			}
-
-			msn_soap_connection_handle_next(conn);
-		}
-
-		return;
-	}
-
-	if (handled) {
-		msn_soap_connection_handle_next(conn);
-	}
-}
-
-static void
-msn_soap_read_cb(gpointer data, gint fd, PurpleInputCondition cond)
-{
-	MsnSoapConnection *conn = data;
-	int count = 0, cnt, perrno;
-	/* This buffer needs to be larger than any packets received from
-		login.live.com or Adium will fail to receive the packet
-		(something weird with the login.live.com server). With NSS it works
-		fine, so I believe it's some bug with OS X */
-	char buf[16 * 1024];
-	gsize cursor;
-
-	if (conn->message == NULL) {
-		conn->message = msn_soap_message_new(NULL, NULL);
-	}
-
-	if (conn->buf == NULL) {
-		conn->buf = g_string_new_len(buf, 0);
-	}
-
-	cursor = conn->buf->len;
-	while ((cnt = purple_ssl_read(conn->ssl, buf, sizeof(buf))) > 0) {
-		purple_debug_info("soap", "read %d bytes\n", cnt);
-		count += cnt;
-		g_string_append_len(conn->buf, buf, cnt);
-	}
-
-	perrno = errno;
-	if (cnt < 0 && perrno != EAGAIN)
-		purple_debug_info("soap", "read: %s\n", g_strerror(perrno));
-
-	if (conn->current_request && conn->current_request->secure &&
-		!purple_debug_is_unsafe())
-		purple_debug_misc("soap", "Received secure request.\n");
-	else if (count != 0)
-		purple_debug_misc("soap", "current %s\n", conn->buf->str + cursor);
-
-	/* && count is necessary for Adium, on OS X the last read always
-	   return an error, so we want to proceed anyway. See #5212 for
-	   discussion on this and the above buffer size issues */
-	if(cnt < 0 && errno == EAGAIN && count == 0)
-		return;
-
-	/* msn_soap_process could alter errno */
-	msn_soap_process(conn);
-
-	if ((cnt < 0 && perrno != EAGAIN) || cnt == 0) {
-		/* It's possible msn_soap_process closed the ssl connection */
-		if (conn->ssl) {
-			purple_ssl_close(conn->ssl);
-			conn->ssl = NULL;
-			msn_soap_connection_handle_next(conn);
-		}
-	}
-}
-
-static gboolean
-msn_soap_write_cb_internal(gpointer data, gint fd, PurpleInputCondition cond,
-		gboolean initial)
-{
-	MsnSoapConnection *conn = data;
-	int written;
-
-	if (cond != PURPLE_INPUT_WRITE)
-		return TRUE;
-
-	written = purple_ssl_write(conn->ssl, conn->buf->str + conn->handled_len,
-		conn->buf->len - conn->handled_len);
-
-	if (written < 0 && errno == EAGAIN)
-		return TRUE;
-	else if (written <= 0) {
-		purple_ssl_close(conn->ssl);
-		conn->ssl = NULL;
-		if (!initial)
-			msn_soap_connection_handle_next(conn);
-		return FALSE;
-	}
-
-	conn->handled_len += written;
-
-	if (conn->handled_len < conn->buf->len)
-		return TRUE;
-
-	/* we are done! */
-	g_string_free(conn->buf, TRUE);
-	conn->buf = NULL;
-	conn->handled_len = 0;
-	conn->body_len = 0;
-	conn->response_code = 0;
-	conn->headers_done = FALSE;
-	conn->close_when_done = FALSE;
-
-	purple_input_remove(conn->event_handle);
-	conn->event_handle = purple_input_add(conn->ssl->fd, PURPLE_INPUT_READ,
-		msn_soap_read_cb, conn);
-	return TRUE;
-}
-
-static void
-msn_soap_write_cb(gpointer data, gint fd, PurpleInputCondition cond)
-{
-	msn_soap_write_cb_internal(data, fd, cond, FALSE);
-}
-
-static void
-msn_soap_error_cb(PurpleSslConnection *ssl, PurpleSslErrorType error,
-		gpointer data)
-{
-	MsnSoapConnection *conn = data;
-
-	/* sslconn already frees the connection in case of error */
-	conn->ssl = NULL;
-
-	g_hash_table_remove(conn->session->soap_table, conn->host);
-}
-
-static void
-msn_soap_connected_cb(gpointer data, PurpleSslConnection *ssl,
-		PurpleInputCondition cond)
-{
-	MsnSoapConnection *conn = data;
-
-	conn->connected = TRUE;
-
-	if (conn->run_timer == 0)
-		conn->run_timer = purple_timeout_add(0, msn_soap_connection_run, conn);
-}
-
-MsnSoapMessage *
-msn_soap_message_new(const char *action, xmlnode *xml)
-{
-	MsnSoapMessage *message = g_new0(MsnSoapMessage, 1);
-
-	message->action = g_strdup(action);
-	message->xml = xml;
-
-	return message;
-}
-
-static gboolean
-msn_soap_connection_run(gpointer data)
-{
-	MsnSoapConnection *conn = data;
-	MsnSoapRequest *req = g_queue_peek_head(conn->queue);
-
-	conn->run_timer = 0;
-
-	if (req) {
-		if (conn->ssl == NULL) {
-			conn->ssl = purple_ssl_connect(conn->session->account, conn->host,
-				443, msn_soap_connected_cb, msn_soap_error_cb, conn);
-		} else if (conn->connected) {
-			int len = -1;
-			char *body = xmlnode_to_str(req->message->xml, &len);
-			GSList *iter;
-
-			g_queue_pop_head(conn->queue);
-
-			conn->buf = g_string_new("");
-
-			g_string_append_printf(conn->buf,
-				"POST /%s HTTP/1.1\r\n"
-				"SOAPAction: %s\r\n"
-				"Content-Type:text/xml; charset=utf-8\r\n"
-				"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n"
-				"Accept: */*\r\n"
-				"Host: %s\r\n"
-				"Content-Length: %d\r\n"
-				"Connection: Keep-Alive\r\n"
-				"Cache-Control: no-cache\r\n",
-				req->path, req->message->action ? req->message->action : "",
-				conn->host, len);
-
-			for (iter = req->message->headers; iter; iter = iter->next) {
-				g_string_append(conn->buf, (char *)iter->data);
-				g_string_append(conn->buf, "\r\n");
-			}
-
-			g_string_append(conn->buf, "\r\n");
-			g_string_append(conn->buf, body);
-
-			if (req->secure && !purple_debug_is_unsafe())
-				purple_debug_misc("soap", "Sending secure request.\n");
-			else
-				purple_debug_misc("soap", "%s\n", conn->buf->str);
-
-			conn->handled_len = 0;
-			conn->current_request = req;
-
-			if (conn->event_handle)
-				purple_input_remove(conn->event_handle);
-			conn->event_handle = purple_input_add(conn->ssl->fd,
-				PURPLE_INPUT_WRITE, msn_soap_write_cb, conn);
-			if (!msn_soap_write_cb_internal(conn, conn->ssl->fd, PURPLE_INPUT_WRITE, TRUE)) {
-				/* Not connected => reconnect and retry */
-				purple_debug_info("soap", "not connected, reconnecting\n");
-
-				conn->connected = FALSE;
-				conn->current_request = NULL;
-				msn_soap_connection_sanitize(conn, FALSE);
-
-				g_queue_push_head(conn->queue, req);
-				conn->run_timer = purple_timeout_add(0, msn_soap_connection_run, conn);
-			}
-
-			g_free(body);
-		}
-	}
-
-	return FALSE;
-}
--- a/libpurple/protocols/msn/soap.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/**
- * @file soap.h
- * 	header file for SOAP connection related process
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA
- */
-#ifndef MSN_SOAP_H
-#define MSN_SOAP_H
-
-typedef struct _MsnSoapMessage MsnSoapMessage;
-
-#include <glib.h>
-
-#include "xmlnode.h"
-
-#include "session.h"
-#include "sslconn.h"
-
-typedef void (*MsnSoapCallback)(MsnSoapMessage *request,
-	MsnSoapMessage *response, gpointer cb_data);
-
-struct _MsnSoapMessage {
-	char *action;
-	xmlnode *xml;
-	GSList *headers;
-};
-
-MsnSoapMessage *msn_soap_message_new(const char *action, xmlnode *xml);
-
-void msn_soap_message_send(MsnSession *session, MsnSoapMessage *message,
-	const char *host, const char *path, gboolean secure,
-	MsnSoapCallback cb, gpointer cb_data);
-
-#endif /* MSN_SOAP_H */
--- a/libpurple/protocols/msn/state.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,315 +0,0 @@
-/**
- * @file state.c State functions and definitions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-
-#include "core.h"
-
-#include "notification.h"
-#include "state.h"
-
-static const char *away_text[] =
-{
-	N_("Available"),
-	N_("Available"),
-	N_("Busy"),
-	N_("Idle"),
-	N_("Be Right Back"),
-	N_("Away From Computer"),
-	N_("On The Phone"),
-	N_("Out To Lunch"),
-	N_("Available"),
-	N_("Available")
-};
-
-/*
- * WLM media PSM info build prcedure
- *
- * Result can like:
- *	<CurrentMedia>\0Music\01\0{0} - {1}\0Song Title\0Song Artist\0Song Album\0\0</CurrentMedia>\
- *	<CurrentMedia>\0Games\01\0Playing {0}\0Game Name\0</CurrentMedia>\
- *	<CurrentMedia>\0Office\01\0Office Message\0Office App Name\0</CurrentMedia>"
- */
-static char *
-msn_build_psm(const char *psmstr,const char *mediastr, const char *guidstr, guint protocol_ver)
-{
-	xmlnode *dataNode,*psmNode,*mediaNode,*guidNode;
-	char *result;
-	int length;
-
-	dataNode = xmlnode_new("Data");
-
-	psmNode = xmlnode_new("PSM");
-	if(psmstr != NULL){
-		xmlnode_insert_data(psmNode, psmstr, -1);
-	}
-	xmlnode_insert_child(dataNode, psmNode);
-
-	mediaNode = xmlnode_new("CurrentMedia");
-	if(mediastr != NULL){
-		xmlnode_insert_data(mediaNode, mediastr, -1);
-	}
-	xmlnode_insert_child(dataNode, mediaNode);
-
-	guidNode = xmlnode_new("MachineGuid");
-	if(guidstr != NULL){
-		xmlnode_insert_data(guidNode, guidstr, -1);
-	}
-	xmlnode_insert_child(dataNode, guidNode);
-
-	if (protocol_ver >= 16) {
-		/* TODO: What is this for? */
-		xmlnode *ddpNode = xmlnode_new("DDP");
-		xmlnode_insert_child(dataNode, ddpNode);
-	}
-
-	result = xmlnode_to_str(dataNode, &length);
-	xmlnode_free(dataNode);
-	return result;
-}
-
-/* get the CurrentMedia info from the XML node */
-char *
-msn_get_currentmedia(xmlnode *payloadNode)
-{
-	xmlnode *currentmediaNode;
-	char *currentmedia;
-
-	purple_debug_info("msn", "Get CurrentMedia\n");
-	currentmediaNode = xmlnode_get_child(payloadNode, "CurrentMedia");
-	if (currentmediaNode == NULL) {
-		purple_debug_info("msn", "No CurrentMedia Node\n");
-		return NULL;
-	}
-	currentmedia = xmlnode_get_data(currentmediaNode);
-
-	return currentmedia;
-}
-
-/* Get the PSM info from the XML node */
-char *
-msn_get_psm(xmlnode *payloadNode)
-{
-	xmlnode *psmNode;
-	char *psm;
-
-	purple_debug_info("msn", "msn get PSM\n");
-	psmNode = xmlnode_get_child(payloadNode, "PSM");
-	if (psmNode == NULL) {
-		purple_debug_info("msn", "No PSM status Node\n");
-		return NULL;
-	}
-	psm = xmlnode_get_data(psmNode);
-
-	return psm;
-}
-
-static char *
-create_media_string(PurplePresence *presence)
-{
-	const char *title, *game, *office;
-	char *ret;
-	PurpleStatus *status = purple_presence_get_status(presence, "tune");
-	if (!status || !purple_status_is_active(status))
-		return NULL;
-
-	title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
-	game = purple_status_get_attr_string(status, "game");
-	office = purple_status_get_attr_string(status, "office");
-
-	if (title && *title) {
-		const char *artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
-		const char *album = purple_status_get_attr_string(status, PURPLE_TUNE_ALBUM);
-		ret = g_strdup_printf("WMP\\0Music\\01\\0{0}%s%s\\0%s\\0%s\\0%s\\0",
-		                      artist ? " - {1}" : "",
-		                      album ? " ({2})" : "",
-		                      title,
-		                      artist ? artist : "",
-		                      album ? album : "");
-	}
-	else if (game && *game)
-		ret = g_strdup_printf("\\0Games\\01\\0Playing {0}\\0%s\\0", game);
-	else if (office && *office)
-		ret = g_strdup_printf("\\0Office\\01\\0Editing {0}\\0%s\\0", office);
-	else
-		ret = NULL;
-
-	return ret;
-}
-
-/* set the MSN's PSM info,Currently Read from the status Line
- * Thanks for Cris Code
- */
-static void
-msn_set_psm(MsnSession *session)
-{
-	PurpleAccount *account;
-	PurplePresence *presence;
-	PurpleStatus *status;
-	char *payload;
-	const char *statusline;
-	gchar *statusline_stripped, *media = NULL;
-
-	g_return_if_fail(session != NULL);
-	g_return_if_fail(session->notification != NULL);
-
-	account = session->account;
-
-	/* Get the PSM string from Purple's Status Line */
-	presence = purple_account_get_presence(account);
-	status = purple_presence_get_active_status(presence);
-	statusline = purple_status_get_attr_string(status, "message");
-
-	/* MSN expects plain text, not HTML */
-	statusline_stripped = purple_markup_strip_html(statusline);
-	media = create_media_string(presence);
-	g_free(session->psm);
-	session->psm = msn_build_psm(statusline_stripped, media, session->guid, session->protocol_ver);
-
-	payload = session->psm;
-
-	msn_notification_send_uux(session, payload);
-
-	g_free(statusline_stripped);
-	g_free(media);
-}
-
-void
-msn_change_status(MsnSession *session)
-{
-	PurpleAccount *account;
-	MsnCmdProc *cmdproc;
-	MsnTransaction *trans;
-	MsnUser *user;
-	MsnObject *msnobj;
-	const char *state_text;
-	GHashTable *ui_info = purple_core_get_ui_info();
-	MsnClientCaps caps = MSN_CLIENT_ID;
-
-	g_return_if_fail(session != NULL);
-	g_return_if_fail(session->notification != NULL);
-
-	/* set client caps based on what the UI tells us it is... */
-	if (ui_info) {
-		const gchar *client_type = g_hash_table_lookup(ui_info, "client_type");
-		if (client_type) {
-			if (strcmp(client_type, "phone") == 0 ||
-				strcmp(client_type, "handheld") == 0) {
-				caps |= MSN_CAP_VIA_MOBILE;
-			} else if (strcmp(client_type, "web") == 0) {
-				caps |= MSN_CAP_VIA_WEBIM;
-			} else if (strcmp(client_type, "bot") == 0) {
-				caps |= MSN_CAP_BOT;
-			}
-			/* MSN doesn't a "console" type...
-			 What, they have no ncurses UI? :-) */
-		}
-	}
-
-	account = session->account;
-	cmdproc = session->notification->cmdproc;
-	user = session->user;
-	state_text = msn_state_get_text(msn_state_from_account(account));
-
-	/* If we're not logged in yet, don't send the status to the server,
-	 * it will be sent when login completes
-	 */
-	if (!session->logged_in)
-		return;
-
-	msn_set_psm(session);
-
-	msnobj = msn_user_get_object(user);
-
-	if (msnobj == NULL)
-	{
-		trans = msn_transaction_new(cmdproc, "CHG", "%s %u:%02u 0", state_text,
-		                            caps, MSN_CLIENT_ID_EXT_CAPS);
-	}
-	else
-	{
-		char *msnobj_str;
-
-		msnobj_str = msn_object_to_string(msnobj);
-
-		trans = msn_transaction_new(cmdproc, "CHG", "%s %u:%02u %s", state_text,
-		                            caps, MSN_CLIENT_ID_EXT_CAPS,
-		                            purple_url_encode(msnobj_str));
-
-		g_free(msnobj_str);
-	}
-
-	msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-const char *
-msn_away_get_text(MsnAwayType type)
-{
-	g_return_val_if_fail(type <= MSN_HIDDEN, NULL);
-
-	return _(away_text[type]);
-}
-
-const char *
-msn_state_get_text(MsnAwayType state)
-{
-	static char *status_text[] =
-	{ "NLN", "NLN", "BSY", "IDL", "BRB", "AWY", "PHN", "LUN", "HDN", "HDN" };
-
-	return status_text[state];
-}
-
-MsnAwayType
-msn_state_from_account(PurpleAccount *account)
-{
-	MsnAwayType msnstatus;
-	PurplePresence *presence;
-	PurpleStatus *status;
-	const char *status_id;
-
-	presence = purple_account_get_presence(account);
-	status = purple_presence_get_active_status(presence);
-	status_id = purple_status_get_id(status);
-
-	if (!strcmp(status_id, "away"))
-		msnstatus = MSN_AWAY;
-	else if (!strcmp(status_id, "brb"))
-		msnstatus = MSN_BRB;
-	else if (!strcmp(status_id, "busy"))
-		msnstatus = MSN_BUSY;
-	else if (!strcmp(status_id, "phone"))
-		msnstatus = MSN_PHONE;
-	else if (!strcmp(status_id, "lunch"))
-		msnstatus = MSN_LUNCH;
-	else if (!strcmp(status_id, "invisible"))
-		msnstatus = MSN_HIDDEN;
-	else
-		msnstatus = MSN_ONLINE;
-
-	if ((msnstatus == MSN_ONLINE) && purple_presence_is_idle(presence))
-		msnstatus = MSN_IDLE;
-
-	return msnstatus;
-}
--- a/libpurple/protocols/msn/state.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/**
- * @file state.h State functions and definitions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_STATE_H
-#define MSN_STATE_H
-
-/**
- * Away types.
- */
-typedef enum
-{
-	MSN_ONLINE  = 1,
-	MSN_BUSY    = 2,
-	MSN_IDLE    = 3,
-	MSN_BRB     = 4,
-	MSN_AWAY    = 5,
-	MSN_PHONE   = 6,
-	MSN_LUNCH   = 7,
-	MSN_OFFLINE = 8,
-	MSN_HIDDEN  = 9
-} MsnAwayType;
-
-/**
- * Changes the status of the user.
- *
- * @param session The MSN session.
- */
-void msn_change_status(MsnSession *session);
-
-/**
- * Returns the string representation of an away type.
- *
- * @param type The away type.
- *
- * @return The string representation of the away type.
- */
-const char *msn_away_get_text(MsnAwayType type);
-
-const char *msn_state_get_text(MsnAwayType state);
-
-/* Get the CurrentMedia info from the XML node */
-char *msn_get_currentmedia(xmlnode *payloadNode);
-
-/* Get the PSM info from the XML node */
-char *msn_get_psm(xmlnode *payloadNode);
-
-MsnAwayType msn_state_from_account(PurpleAccount *account);
-
-#endif /* MSN_STATE_H */
--- a/libpurple/protocols/msn/switchboard.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1197 +0,0 @@
-/**
- * @file switchboard.c MSN switchboard functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-
-#include "msnutils.h"
-#include "switchboard.h"
-#include "sbconn.h"
-#include "slplink.h"
-#include "user.h"
-#include "userlist.h"
-
-static MsnTable *cbs_table;
-
-/**************************************************************************
- * Main
- **************************************************************************/
-
-MsnSwitchBoard *
-msn_switchboard_new(MsnSession *session)
-{
-	MsnSwitchBoard *swboard;
-
-	g_return_val_if_fail(session != NULL, NULL);
-
-	swboard = g_new0(MsnSwitchBoard, 1);
-
-	swboard->session = session;
-	swboard->servconn = msn_servconn_new(session, MSN_SERVCONN_SB);
-	msn_servconn_set_idle_timeout(swboard->servconn, 60);
-	swboard->cmdproc = swboard->servconn->cmdproc;
-
-	swboard->msg_queue = g_queue_new();
-	swboard->empty = TRUE;
-
-	swboard->cmdproc->data = swboard;
-	swboard->cmdproc->cbs_table = cbs_table;
-
-	session->switches = g_list_prepend(session->switches, swboard);
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "switchboard new: swboard(%p)\n", swboard);
-
-	return swboard;
-}
-
-void
-msn_switchboard_destroy(MsnSwitchBoard *swboard)
-{
-	MsnSession *session;
-	MsnMessage *msg;
-	GList *l;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "switchboard destroy: swboard(%p)\n", swboard);
-
-	g_return_if_fail(swboard != NULL);
-
-	if (swboard->destroying)
-		return;
-
-	swboard->destroying = TRUE;
-
-	if (swboard->reconn_timeout_h > 0)
-		purple_timeout_remove(swboard->reconn_timeout_h);
-
-	/* If it linked us is because its looking for trouble */
-	while (swboard->slplinks != NULL) {
-		MsnSlpLink *slplink = swboard->slplinks->data;
-
-		swboard->slplinks = g_list_remove(swboard->slplinks, slplink);
-
-		/* Destroy only those slplinks which use the switchboard */
-		if (slplink->dc == NULL)
-			msn_slplink_unref(slplink);
-		else {
-			swboard->slplinks = g_list_remove(swboard->slplinks, slplink);
-			slplink->swboard = NULL;
-		}
-	}
-
-	/* Destroy the message queue */
-	while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL)
-	{
-		if (swboard->error != MSN_SB_ERROR_NONE)
-		{
-			/* The messages could not be sent due to a switchboard error */
-			msg_error_helper(swboard->cmdproc, msg,
-							 MSN_MSG_ERROR_SB);
-		}
-		msn_message_unref(msg);
-	}
-
-	g_queue_free(swboard->msg_queue);
-
-	/* msg_error_helper will both remove the msg from ack_list and
-	   unref it, so we don't need to do either here */
-	while ((l = swboard->ack_list) != NULL)
-		msg_error_helper(swboard->cmdproc, l->data, MSN_MSG_ERROR_SB);
-
-	g_free(swboard->im_user);
-	g_free(swboard->auth_key);
-	g_free(swboard->session_id);
-
-	for (; swboard->users; swboard->users = g_list_delete_link(swboard->users, swboard->users))
-		msn_user_unref(swboard->users->data);
-
-	session = swboard->session;
-	session->switches = g_list_remove(session->switches, swboard);
-
-	for (l = session->slplinks; l; l = l->next) {
-		MsnSlpLink *slplink = l->data;
-		if (slplink->swboard == swboard) slplink->swboard = NULL;
-	}
-
-#if 0
-	/* This should never happen or we are in trouble. */
-	if (swboard->servconn != NULL)
-		msn_servconn_destroy(swboard->servconn);
-#endif
-
-	swboard->cmdproc->data = NULL;
-
-	msn_servconn_set_disconnect_cb(swboard->servconn, NULL);
-
-	msn_servconn_destroy(swboard->servconn);
-
-	g_free(swboard);
-}
-
-void
-msn_switchboard_set_auth_key(MsnSwitchBoard *swboard, const char *key)
-{
-	g_return_if_fail(swboard != NULL);
-	g_return_if_fail(key != NULL);
-
-	swboard->auth_key = g_strdup(key);
-}
-
-const char *
-msn_switchboard_get_auth_key(MsnSwitchBoard *swboard)
-{
-	g_return_val_if_fail(swboard != NULL, NULL);
-
-	return swboard->auth_key;
-}
-
-void
-msn_switchboard_set_session_id(MsnSwitchBoard *swboard, const char *id)
-{
-	g_return_if_fail(swboard != NULL);
-	g_return_if_fail(id != NULL);
-
-	g_free(swboard->session_id);
-	swboard->session_id = g_strdup(id);
-}
-
-const char *
-msn_switchboard_get_session_id(MsnSwitchBoard *swboard)
-{
-	g_return_val_if_fail(swboard != NULL, NULL);
-
-	return swboard->session_id;
-}
-
-int
-msn_switchboard_get_chat_id(void)
-{
-	static int chat_id = 1;
-
-	return chat_id++;
-}
-
-void
-msn_switchboard_set_invited(MsnSwitchBoard *swboard, gboolean invited)
-{
-	g_return_if_fail(swboard != NULL);
-
-	swboard->invited = invited;
-}
-
-gboolean
-msn_switchboard_is_invited(MsnSwitchBoard *swboard)
-{
-	g_return_val_if_fail(swboard != NULL, FALSE);
-
-	return swboard->invited;
-}
-
-/**************************************************************************
- * Utility
- **************************************************************************/
-
-static void
-send_clientcaps(MsnSwitchBoard *swboard)
-{
-	MsnMessage *msg;
-
-	msg = msn_message_new(MSN_MSG_CAPS);
-	msn_message_set_content_type(msg, "text/x-clientcaps");
-	msn_message_set_flag(msg, 'U');
-	msn_message_set_bin_data(msg, MSN_CLIENTINFO, strlen(MSN_CLIENTINFO));
-
-	msn_switchboard_send_msg(swboard, msg, TRUE);
-
-	msn_message_unref(msg);
-}
-
-static void
-msn_switchboard_add_user(MsnSwitchBoard *swboard, const char *user)
-{
-	MsnCmdProc *cmdproc;
-	PurpleAccount *account;
-	MsnUserList *userlist;
-	MsnUser *msnuser;
-	char *semicolon;
-	char *passport;
-
-	g_return_if_fail(swboard != NULL);
-
-	cmdproc = swboard->cmdproc;
-	account = cmdproc->session->account;
-
-	semicolon = strchr(user, ';');
-	/* We don't really care about the machine ID. */
-	if (semicolon)
-		passport = g_strndup(user, semicolon - user);
-	else
-		passport = g_strdup(user);
-
-	userlist = swboard->session->userlist;
-	msnuser = msn_userlist_find_user(userlist, passport);
-
-	/* Don't add multiple endpoints to the conversation. */
-	if (g_list_find_custom(swboard->users, passport, (GCompareFunc)msn_user_passport_cmp)) {
-		g_free(passport);
-		return;
-	}
-
-	/* Don't add ourselves either... */
-	if (g_str_equal(passport, purple_account_get_username(account))) {
-		g_free(passport);
-		return;
-	}
-
-	if (!msnuser) {
-		purple_debug_info("msn","User %s is not on our list.\n", passport);
-		msnuser = msn_user_new(userlist, passport, NULL);
-	} else
-		msn_user_ref(msnuser);
-
-	g_free(passport);
-
-	swboard->users = g_list_prepend(swboard->users, msnuser);
-	swboard->current_users++;
-	swboard->empty = FALSE;
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "user=[%s], total=%d\n",
-		                  user, swboard->current_users);
-
-	if (!(swboard->flag & MSN_SB_FLAG_IM) && (swboard->conv != NULL))
-	{
-		/* This is a helper switchboard. */
-		purple_debug_error("msn", "switchboard_add_user: conv != NULL\n");
-		return;
-	}
-
-	if ((swboard->conv != NULL) &&
-		(purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
-	{
-		purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv), msnuser->passport, NULL,
-								PURPLE_CBFLAGS_NONE, TRUE);
-		msn_servconn_set_idle_timeout(swboard->servconn, 0);
-	}
-	else if (swboard->current_users > 1)
-	{
-		msn_servconn_set_idle_timeout(swboard->servconn, 0);
-		if (swboard->conv == NULL ||
-			purple_conversation_get_type(swboard->conv) != PURPLE_CONV_TYPE_CHAT)
-		{
-			GList *l;
-
-#if 0
-			/* this is bad - it causes msn_switchboard_close to be called on the
-			 * switchboard we're in the middle of using :( */
-			if (swboard->conv != NULL)
-				purple_conversation_destroy(swboard->conv);
-#endif
-
-			swboard->chat_id = msn_switchboard_get_chat_id();
-			swboard->flag |= MSN_SB_FLAG_IM;
-			swboard->conv = serv_got_joined_chat(account->gc,
-												 swboard->chat_id,
-												 "MSN Chat");
-
-			for (l = swboard->users; l != NULL; l = l->next)
-			{
-				const char *tmp_user;
-
-				tmp_user = ((MsnUser*)l->data)->passport;
-
-				purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv),
-										tmp_user, NULL, PURPLE_CBFLAGS_NONE, TRUE);
-			}
-
-			purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv),
-									purple_account_get_username(account),
-									NULL, PURPLE_CBFLAGS_NONE, TRUE);
-
-			g_free(swboard->im_user);
-			swboard->im_user = NULL;
-		}
-	}
-	else if (swboard->conv == NULL)
-	{
-		swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
-															msnuser->passport, account);
-	}
-	else
-	{
-		purple_debug_warning("msn", "switchboard_add_user: This should not happen!\n");
-	}
-}
-
-static PurpleConversation *
-msn_switchboard_get_conv(MsnSwitchBoard *swboard)
-{
-	PurpleAccount *account;
-
-	g_return_val_if_fail(swboard != NULL, NULL);
-
-	if (swboard->conv != NULL)
-		return swboard->conv;
-
-	purple_debug_error("msn", "Switchboard with unassigned conversation\n");
-
-	account = swboard->session->account;
-
-	return (swboard->conv = purple_conversation_new(PURPLE_CONV_TYPE_IM,
-												  account, swboard->im_user));
-}
-
-static void
-msn_switchboard_report_user(MsnSwitchBoard *swboard, PurpleMessageFlags flags, const char *msg)
-{
-	PurpleConversation *conv;
-
-	g_return_if_fail(swboard != NULL);
-	g_return_if_fail(msg != NULL);
-
-	if ((conv = msn_switchboard_get_conv(swboard)) != NULL)
-	{
-		purple_conversation_write(conv, NULL, msg, flags, time(NULL));
-	}
-}
-
-static void
-swboard_error_helper(MsnSwitchBoard *swboard, int reason, const char *passport)
-{
-	g_return_if_fail(swboard != NULL);
-
-	purple_debug_warning("msn", "Error: Unable to call the user %s for reason %i\n",
-					   passport ? passport : "(null)", reason);
-
-	/* TODO: if current_users > 0, this is probably a chat and an invite failed,
-	 * we should report that in the chat or something */
-	if (swboard->current_users == 0)
-	{
-		swboard->error = reason;
-		msn_switchboard_close(swboard);
-	}
-}
-
-static void
-cal_error_helper(MsnTransaction *trans, int reason)
-{
-	MsnSwitchBoard *swboard;
-	const char *passport;
-	char **params;
-
-	params = g_strsplit(trans->params, " ", 0);
-
-	passport = params[0];
-
-	swboard = trans->data;
-
-	purple_debug_warning("msn", "cal_error_helper: command %s failed for reason %i\n",trans->command,reason);
-
-	swboard_error_helper(swboard, reason, passport);
-
-	g_strfreev(params);
-}
-
-static gboolean
-msg_resend_cb(gpointer data)
-{
-	MsnSwitchBoard *swboard = data;
-
-	purple_debug_info("msn", "unqueuing unsent message to %s\n", swboard->im_user);
-
-	if (msn_switchboard_request(swboard)) {
-		msn_switchboard_request_add_user(swboard, swboard->im_user);
-		swboard->reconn_timeout_h = 0;
-	}
-	return FALSE;
-}
-
-void
-msg_error_helper(MsnCmdProc *cmdproc, MsnMessage *msg, MsnMsgErrorType error)
-{
-	MsnSwitchBoard *swboard;
-
-	g_return_if_fail(cmdproc != NULL);
-	g_return_if_fail(msg     != NULL);
-
-	if ((error != MSN_MSG_ERROR_SB) && (msg->nak_cb != NULL))
-		msg->nak_cb(msg, msg->ack_data);
-
-	swboard = cmdproc->data;
-
-	/* This is not good, and should be fixed somewhere else. */
-	g_return_if_fail(swboard != NULL);
-
-	if (msg->type == MSN_MSG_TEXT)
-	{
-		const char *format, *str_reason;
-		char *body_str, *body_enc, *pre, *post;
-
-#if 0
-		if (swboard->conv == NULL)
-		{
-			if (msg->ack_ref)
-				msn_message_unref(msg);
-
-			return;
-		}
-#endif
-
-		if (error == MSN_MSG_ERROR_TIMEOUT)
-		{
-			str_reason = _("Message may have not been sent "
-						   "because a timeout occurred:");
-		}
-		else if (error == MSN_MSG_ERROR_SB)
-		{
-			MsnSession *session = swboard->session;
-
-			if (!session->destroying && msg->retries &&	swboard->im_user &&
-				(swboard->error == MSN_SB_ERROR_CONNECTION ||
-					swboard->error == MSN_SB_ERROR_UNKNOWN)) {
-				MsnSwitchBoard *new_sw = msn_session_find_swboard(session,
-					swboard->im_user);
-
-				if (new_sw == NULL || new_sw->reconn_timeout_h == 0) {
-					new_sw = msn_switchboard_new(session);
-					new_sw->im_user = g_strdup(swboard->im_user);
-					new_sw->reconn_timeout_h = purple_timeout_add_seconds(3, msg_resend_cb, new_sw);
-					new_sw->flag |= MSN_SB_FLAG_IM;
-				}
-
-				body_str = msn_message_to_string(msg);
-				body_enc = g_markup_escape_text(body_str, -1);
-				g_free(body_str);
-
-				purple_debug_info("msn", "queuing unsent message to %s: %s\n",
-					swboard->im_user, body_enc);
-				g_free(body_enc);
-				msn_send_im_message(session, msg);
-				msg->retries--;
-
-				return;
-			}
-
-			switch (swboard->error)
-			{
-				case MSN_SB_ERROR_OFFLINE:
-					str_reason = _("Message could not be sent, "
-								   "not allowed while invisible:");
-					break;
-				case MSN_SB_ERROR_USER_OFFLINE:
-					str_reason = _("Message could not be sent "
-								   "because the user is offline:");
-					break;
-				case MSN_SB_ERROR_CONNECTION:
-					str_reason = _("Message could not be sent "
-								   "because a connection error occurred:");
-					break;
-				case MSN_SB_ERROR_TOO_FAST:
-					str_reason = _("Message could not be sent "
-								   "because we are sending too quickly:");
-					break;
-				case MSN_SB_ERROR_AUTHFAILED:
-					str_reason = _("Message could not be sent "
-								   "because we were unable to establish a "
-								   "session with the server. This is "
-								   "likely a server problem, try again in "
-								   "a few minutes:");
-					break;
-				default:
-					str_reason = _("Message could not be sent "
-								   "because an error with "
-								   "the switchboard occurred:");
-					break;
-			}
-		}
-		else
-		{
-			str_reason = _("Message may have not been sent "
-						   "because an unknown error occurred:");
-		}
-
-		body_str = msn_message_to_string(msg);
-		body_enc = g_markup_escape_text(body_str, -1);
-		g_free(body_str);
-
-		format = msn_message_get_header_value(msg, "X-MMS-IM-Format");
-		msn_parse_format(format, &pre, &post);
-		body_str = g_strdup_printf("%s%s%s", pre ? pre : "",
-								   body_enc ? body_enc : "", post ? post : "");
-		g_free(body_enc);
-		g_free(pre);
-		g_free(post);
-
-		msn_switchboard_report_user(swboard, PURPLE_MESSAGE_ERROR,
-									str_reason);
-		msn_switchboard_report_user(swboard, PURPLE_MESSAGE_RAW,
-									body_str);
-
-		g_free(body_str);
-	}
-
-	/* If a timeout occures we will want the msg around just in case we
-	 * receive the ACK after the timeout. */
-	if (msg->ack_ref && error != MSN_MSG_ERROR_TIMEOUT)
-	{
-		swboard->ack_list = g_list_remove(swboard->ack_list, msg);
-		msn_message_unref(msg);
-	}
-}
-
-/**************************************************************************
- * Message Stuff
- **************************************************************************/
-
-/** Called when we receive an error of a message. */
-static void
-msg_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
-{
-	msg_error_helper(cmdproc, trans->data, MSN_MSG_ERROR_UNKNOWN);
-}
-
-gboolean
-msn_switchboard_can_send(MsnSwitchBoard *swboard)
-{
-	g_return_val_if_fail(swboard != NULL, FALSE);
-
-	if (swboard->empty || !g_queue_is_empty(swboard->msg_queue))
-		return FALSE;
-
-	return TRUE;
-}
-
-/**************************************************************************
- * Switchboard Commands
- **************************************************************************/
-
-static void
-ans_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnSwitchBoard *swboard;
-
-	swboard = cmdproc->data;
-	swboard->ready = TRUE;
-}
-
-static void
-bye_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnSwitchBoard *swboard;
-	const char *user;
-
-	swboard = cmdproc->data;
-	user = cmd->params[0];
-
-	/* cmdproc->data is set to NULL when the switchboard is destroyed;
-	 * we may get a bye shortly thereafter. */
-	g_return_if_fail(swboard != NULL);
-
-	if (!(swboard->flag & MSN_SB_FLAG_IM) && (swboard->conv != NULL))
-		purple_debug_error("msn", "bye_cmd: helper bug\n");
-
-	if (swboard->conv == NULL)
-	{
-		/* This is a helper switchboard */
-		msn_switchboard_destroy(swboard);
-	}
-	else if ((swboard->current_users > 1) ||
-			 (purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
-	{
-		GList *passport;
-		/* This is a switchboard used for a chat */
-		purple_conv_chat_remove_user(PURPLE_CONV_CHAT(swboard->conv), user, NULL);
-
-		passport = g_list_find_custom(swboard->users, user, (GCompareFunc)strcmp);
-		if (passport)
-			g_free(passport->data);
-		else
-			purple_debug_warning("msn", "Can't find user %s in the switchboard\n", user);
-		swboard->users = g_list_delete_link(swboard->users, passport);
-		swboard->current_users--;
-		if (swboard->current_users == 0)
-			msn_switchboard_destroy(swboard);
-	}
-	else
-	{
-		/* This is a switchboard used for a im session */
-		msn_switchboard_destroy(swboard);
-	}
-}
-
-static void
-iro_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnSwitchBoard *swboard;
-
-	swboard = cmdproc->data;
-
-	swboard->total_users = atoi(cmd->params[2]);
-
-	msn_switchboard_add_user(swboard, cmd->params[3]);
-}
-
-static void
-joi_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnSession *session;
-	MsnSwitchBoard *swboard;
-	const char *passport;
-
-	passport = cmd->params[0];
-
-	session = cmdproc->session;
-	swboard = cmdproc->data;
-
-	msn_switchboard_add_user(swboard, passport);
-
-	msn_sbconn_process_queue(swboard);
-
-	if (!session->http_method)
-		send_clientcaps(swboard);
-
-	if (swboard->closed)
-		msn_switchboard_close(swboard);
-}
-
-static void
-msg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
-{
-	MsnMessage *msg;
-
-	msg = msn_message_new_from_cmd(cmdproc->session, cmd);
-
-	msn_message_parse_payload(msg, payload, len,
-					MSG_LINE_DEM,MSG_BODY_DEM);
-	if (purple_debug_is_verbose())
-		msn_message_show_readable(msg, "SB RECV", FALSE);
-
-	g_free (msg->remote_user);
-	msg->remote_user = g_strdup(cmd->params[0]);
-
-	msn_cmdproc_process_msg(cmdproc, msg);
-
-	msn_message_unref(msg);
-}
-
-static void
-msg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	cmd->payload_len = atoi(cmd->params[2]);
-	cmdproc->last_cmd->payload_cb = msg_cmd_post;
-}
-
-static void
-ubm_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	purple_debug_misc("msn", "get UBM...\n");
-	cmd->payload_len = atoi(cmd->params[5]);
-	cmdproc->last_cmd->payload_cb = msg_cmd_post;
-}
-
-static void
-nak_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnMessage *msg;
-
-	msg = cmd->trans->data;
-	g_return_if_fail(msg != NULL);
-
-	msg_error_helper(cmdproc, msg, MSN_MSG_ERROR_NAK);
-	cmd->trans->data = NULL;
-}
-
-static void
-ack_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnSwitchBoard *swboard;
-	MsnMessage *msg;
-
-	msg = cmd->trans->data;
-
-	if (msg->part && msg->part->ack_cb != NULL)
-		msg->part->ack_cb(msg->part, msg->part->ack_data);
-
-	swboard = cmdproc->data;
-	if (swboard)
-		swboard->ack_list = g_list_remove(swboard->ack_list, msg);
-	msn_message_unref(msg);
-	cmd->trans->data = NULL;
-}
-
-static void
-out_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	PurpleConnection *gc;
-	MsnSwitchBoard *swboard;
-
-	gc = cmdproc->session->account->gc;
-	swboard = cmdproc->data;
-
-	if (swboard->current_users > 1)
-		serv_got_chat_left(gc, swboard->chat_id);
-
-	msn_switchboard_disconnect(swboard);
-}
-
-static void
-usr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnSwitchBoard *swboard;
-
-	swboard = cmdproc->data;
-
-#if 0
-	GList *l;
-
-	for (l = swboard->users; l != NULL; l = l->next)
-	{
-		const char *user;
-		user = l->data;
-
-		msn_cmdproc_send(cmdproc, "CAL", "%s", user);
-	}
-#endif
-
-	swboard->ready = TRUE;
-	msn_cmdproc_process_queue(cmdproc);
-}
-
-/**************************************************************************
- * Message Handlers
- **************************************************************************/
-static void
-clientcaps_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-#if 0
-	MsnSession *session;
-	MsnSwitchBoard *swboard;
-	MsnUser *user;
-	GHashTable *clientcaps;
-	const char *value;
-
-	char *passport = msg->sender;
-
-	session = cmdproc->session;
-	swboard = cmdproc->servconn->swboard;
-
-	clientcaps = msn_message_get_hashtable_from_body(msg);
-#endif
-}
-
-void
-msn_switchboard_show_ink(MsnSwitchBoard *swboard, const char *passport,
-                         const char *data)
-{
-	PurpleConnection *gc;
-	guchar *image_data;
-	size_t image_len;
-	int imgid;
-	char *image_msg;
-
-	if (!purple_str_has_prefix(data, "base64:"))
-	{
-		purple_debug_error("msn", "Ignoring Ink not in Base64 format.\n");
-		return;
-	}
-
-	gc = purple_account_get_connection(swboard->session->account);
-
-	data += sizeof("base64:") - 1;
-	image_data = purple_base64_decode(data, &image_len);
-	if (!image_data || !image_len)
-	{
-		purple_debug_error("msn", "Unable to decode Ink from Base64 format.\n");
-		return;
-	}
-
-	imgid = purple_imgstore_add_with_id(image_data, image_len, NULL);
-	image_msg = g_strdup_printf("<IMG ID='%d'>", imgid);
-
-	if (swboard->current_users > 1 ||
-		((swboard->conv != NULL) &&
-		 purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
-		serv_got_chat_in(gc, swboard->chat_id, passport, 0, image_msg,
-						 time(NULL));
-	else
-		serv_got_im(gc, passport, image_msg, 0, time(NULL));
-
-	purple_imgstore_unref_by_id(imgid);
-	g_free(image_msg);
-}
-
-/**************************************************************************
- * Connect stuff
- **************************************************************************/
-static void
-ans_usr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error);
-
-static void
-connect_cb(MsnServConn *servconn)
-{
-	MsnSwitchBoard *swboard;
-	MsnTransaction *trans;
-	MsnCmdProc *cmdproc;
-	PurpleAccount *account;
-	char *username;
-
-	cmdproc = servconn->cmdproc;
-	g_return_if_fail(cmdproc != NULL);
-
-	account = cmdproc->session->account;
-	swboard = cmdproc->data;
-	g_return_if_fail(swboard != NULL);
-
-	username = g_strdup_printf("%s;{%s}",
-	                           purple_account_get_username(account),
-	                           servconn->session->guid);
-
-	if (msn_switchboard_is_invited(swboard))
-	{
-		swboard->empty = FALSE;
-
-		trans = msn_transaction_new(cmdproc, "ANS", "%s %s %s",
-									username,
-									swboard->auth_key, swboard->session_id);
-	}
-	else
-	{
-		trans = msn_transaction_new(cmdproc, "USR", "%s %s",
-									username,
-									swboard->auth_key);
-	}
-
-	msn_transaction_set_error_cb(trans, ans_usr_error);
-	msn_transaction_set_data(trans, swboard);
-	msn_cmdproc_send_trans(cmdproc, trans);
-
-	g_free(username);
-}
-
-static void
-ans_usr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
-{
-	MsnSwitchBoard *swboard;
-	char **params;
-	char *passport;
-	int reason = MSN_SB_ERROR_UNKNOWN;
-
-	if (error == 911)
-	{
-		reason = MSN_SB_ERROR_AUTHFAILED;
-	}
-
-	purple_debug_warning("msn", "ans_usr_error: command %s gave error %i\n", trans->command, error);
-
-	params = g_strsplit(trans->params, " ", 0);
-	passport = params[0];
-	swboard = trans->data;
-
-	swboard_error_helper(swboard, reason, passport);
-
-	g_strfreev(params);
-}
-
-static void
-disconnect_cb(MsnServConn *servconn)
-{
-	MsnSwitchBoard *swboard;
-
-	swboard = servconn->cmdproc->data;
-	g_return_if_fail(swboard != NULL);
-
-	msn_servconn_set_disconnect_cb(swboard->servconn, NULL);
-
-	msn_switchboard_destroy(swboard);
-}
-
-gboolean
-msn_switchboard_connect(MsnSwitchBoard *swboard, const char *host, int port)
-{
-	g_return_val_if_fail(swboard != NULL, FALSE);
-
-	msn_servconn_set_connect_cb(swboard->servconn, connect_cb);
-	msn_servconn_set_disconnect_cb(swboard->servconn, disconnect_cb);
-
-	return msn_servconn_connect(swboard->servconn, host, port, FALSE);
-}
-
-void
-msn_switchboard_disconnect(MsnSwitchBoard *swboard)
-{
-	g_return_if_fail(swboard != NULL);
-
-	msn_servconn_disconnect(swboard->servconn);
-}
-
-/**************************************************************************
- * Call stuff
- **************************************************************************/
-static void
-got_cal(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-#if 0
-	MsnSwitchBoard *swboard;
-	const char *user;
-
-	swboard = cmdproc->data;
-
-	user = cmd->params[0];
-
-	msn_switchboard_add_user(swboard, user);
-#endif
-}
-
-static void
-cal_timeout(MsnCmdProc *cmdproc, MsnTransaction *trans)
-{
-	purple_debug_warning("msn", "cal_timeout: command %s timed out\n", trans->command);
-
-	cal_error_helper(trans, MSN_SB_ERROR_UNKNOWN);
-}
-
-static void
-cal_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
-{
-	int reason = MSN_SB_ERROR_UNKNOWN;
-	MsnMessage *msg;
-	MsnSwitchBoard *swboard = trans->data;
-
-	if (error == 215)
-	{
-		purple_debug_info("msn", "Invited user already in switchboard\n");
-		return;
-	}
-	else if (error == 217)
-	{
-		reason = MSN_SB_ERROR_USER_OFFLINE;
-	}
-
-	purple_debug_warning("msn", "cal_error: command %s gave error %i\n", trans->command, error);
-
-	while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL){
-		purple_debug_warning("msn", "Unable to send msg: {%s}\n", msg->body);
-		/* The messages could not be sent due to a switchboard error */
-		swboard->error = MSN_SB_ERROR_USER_OFFLINE;
-		msg_error_helper(swboard->cmdproc, msg,
-							 MSN_MSG_ERROR_SB);
-	}
-	cal_error_helper(trans, reason);
-}
-
-void
-msn_switchboard_request_add_user(MsnSwitchBoard *swboard, const char *user)
-{
-	MsnTransaction *trans;
-	MsnCmdProc *cmdproc;
-
-	g_return_if_fail(swboard != NULL);
-
-	cmdproc = swboard->cmdproc;
-
-	trans = msn_transaction_new(cmdproc, "CAL", "%s", user);
-	/* this doesn't do anything, but users seem to think that
-	 * 'Unhandled command' is some kind of error, so we don't report it */
-	msn_transaction_add_cb(trans, "CAL", got_cal);
-
-	msn_transaction_set_data(trans, swboard);
-	msn_transaction_set_timeout_cb(trans, cal_timeout);
-
-	if (swboard->ready)
-		msn_cmdproc_send_trans(cmdproc, trans);
-	else
-		msn_cmdproc_queue_trans(cmdproc, trans);
-}
-
-/**************************************************************************
- * Create & Transfer stuff
- **************************************************************************/
-
-static void
-got_swboard(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-	MsnSwitchBoard *swboard;
-	char *host;
-	int port;
-	swboard = cmd->trans->data;
-
-	if (g_list_find(cmdproc->session->switches, swboard) == NULL)
-		/* The conversation window was closed. */
-		return;
-
-	purple_debug_info("msn", "Switchboard:auth:{%s} socket:{%s}\n", cmd->params[4], cmd->params[2]);
-	msn_switchboard_set_auth_key(swboard, cmd->params[4]);
-
-	msn_parse_socket(cmd->params[2], &host, &port);
-
-	if (!msn_switchboard_connect(swboard, host, port))
-		msn_switchboard_destroy(swboard);
-
-	g_free(host);
-}
-
-static void
-xfr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
-{
-	MsnSwitchBoard *swboard;
-	int reason = MSN_SB_ERROR_UNKNOWN;
-
-	if (error == 913)
-		reason = MSN_SB_ERROR_OFFLINE;
-	else if (error == 800)
-		reason = MSN_SB_ERROR_TOO_FAST;
-
-	swboard = trans->data;
-
-	purple_debug_info("msn",
-		"xfr_error %i for %s: trans %p, command %s, reason %i\n",
-		error, (swboard->im_user ? swboard->im_user : "(null)"), trans,
-		(trans->command ? trans->command : "(null)"), reason);
-
-	swboard_error_helper(swboard, reason, swboard->im_user);
-}
-
-gboolean
-msn_switchboard_request(MsnSwitchBoard *swboard)
-{
-	MsnCmdProc *cmdproc;
-	MsnTransaction *trans;
-
-	g_return_val_if_fail(swboard != NULL, FALSE);
-
-	cmdproc = swboard->session->notification->cmdproc;
-
-	trans = msn_transaction_new(cmdproc, "XFR", "%s", "SB");
-	msn_transaction_add_cb(trans, "XFR", got_swboard);
-
-	msn_transaction_set_data(trans, swboard);
-	msn_transaction_set_error_cb(trans, xfr_error);
-
-	return msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-void
-msn_switchboard_close(MsnSwitchBoard *swboard)
-{
-	g_return_if_fail(swboard != NULL);
-
-	if (swboard->error != MSN_SB_ERROR_NONE)
-	{
-		msn_switchboard_destroy(swboard);
-	}
-	else if (g_queue_is_empty(swboard->msg_queue) ||
-			 !swboard->session->connected)
-	{
-		MsnCmdProc *cmdproc;
-		MsnTransaction *trans;
-		cmdproc = swboard->cmdproc;
-		trans = msn_transaction_new(cmdproc, "OUT", NULL);
-		msn_transaction_set_saveable(trans, FALSE);
-		msn_cmdproc_send_trans(cmdproc, trans);
-
-		msn_switchboard_destroy(swboard);
-	}
-	else
-	{
-		swboard->closed = TRUE;
-	}
-}
-
-void
-msn_switchboard_release(MsnSwitchBoard *swboard, MsnSBFlag flag)
-{
-	g_return_if_fail(swboard != NULL);
-
-	swboard->flag &= ~flag;
-
-	if (flag == MSN_SB_FLAG_IM)
-		/* Forget any conversation that used to be associated with this
-		 * swboard. */
-		swboard->conv = NULL;
-
-	if (swboard->flag == 0)
-		/* Nothing else is using this switchboard, so close it */
-		msn_switchboard_close(swboard);
-}
-
-/**************************************************************************
- * Init stuff
- **************************************************************************/
-
-void
-msn_switchboard_init(void)
-{
-	cbs_table = msn_table_new();
-
-	msn_table_add_cmd(cbs_table, "ANS", "ANS", ans_cmd);
-	msn_table_add_cmd(cbs_table, "ANS", "IRO", iro_cmd);
-
-	msn_table_add_cmd(cbs_table, "MSG", "ACK", ack_cmd);
-	msn_table_add_cmd(cbs_table, "MSG", "NAK", nak_cmd);
-
-	msn_table_add_cmd(cbs_table, "USR", "USR", usr_cmd);
-
-	msn_table_add_cmd(cbs_table, NULL, "MSG", msg_cmd);
-	msn_table_add_cmd(cbs_table, NULL, "UBM", ubm_cmd);
-	msn_table_add_cmd(cbs_table, NULL, "JOI", joi_cmd);
-	msn_table_add_cmd(cbs_table, NULL, "BYE", bye_cmd);
-	msn_table_add_cmd(cbs_table, NULL, "OUT", out_cmd);
-
-#if 0
-	/* They might skip the history */
-	msn_table_add_cmd(cbs_table, NULL, "ACK", NULL);
-#endif
-
-	msn_table_add_error(cbs_table, "MSG", msg_error);
-	msn_table_add_error(cbs_table, "CAL", cal_error);
-
-	/* Register the message type callbacks. */
-	msn_table_add_msg_type(cbs_table, "text/plain",
-						   msn_plain_msg);
-	msn_table_add_msg_type(cbs_table, "text/x-msmsgscontrol",
-						   msn_control_msg);
-	msn_table_add_msg_type(cbs_table, "text/x-clientcaps",
-						   clientcaps_msg);
-	msn_table_add_msg_type(cbs_table, "text/x-clientinfo",
-						   clientcaps_msg);
-	msn_table_add_msg_type(cbs_table, "application/x-msnmsgrp2p",
-						   msn_p2p_msg);
-	msn_table_add_msg_type(cbs_table, "text/x-mms-emoticon",
-						   msn_emoticon_msg);
-	msn_table_add_msg_type(cbs_table, "text/x-mms-animemoticon",
-	                       msn_emoticon_msg);
-	msn_table_add_msg_type(cbs_table, "text/x-msnmsgr-datacast",
-						   msn_datacast_msg);
-	msn_table_add_msg_type(cbs_table, "text/x-msmsgsinvite",
-						   msn_invite_msg);
-	msn_table_add_msg_type(cbs_table, "image/gif",
-						   msn_handwritten_msg);
-}
-
-void
-msn_switchboard_end(void)
-{
-	msn_table_destroy(cbs_table);
-}
--- a/libpurple/protocols/msn/switchboard.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,266 +0,0 @@
-/**
- * @file switchboard.h MSN switchboard functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_SWITCHBOARD_H
-#define MSN_SWITCHBOARD_H
-
-typedef struct _MsnSwitchBoard MsnSwitchBoard;
-
-/**
- * A switchboard error.
- */
-typedef enum
-{
-	MSN_SB_ERROR_NONE, /**< No error. */
-	MSN_SB_ERROR_CAL, /**< The user could not join (answer the call). */
-	MSN_SB_ERROR_OFFLINE, /**< The account is offline. */
-	MSN_SB_ERROR_USER_OFFLINE, /**< The user to call is offline. */
-	MSN_SB_ERROR_CONNECTION, /**< There was a connection error. */
-	MSN_SB_ERROR_TOO_FAST, /**< We are sending too fast */
-	MSN_SB_ERROR_AUTHFAILED, /**< Authentication failed joining the switchboard session */
-	MSN_SB_ERROR_UNKNOWN /**< An unknown error occurred. */
-} MsnSBErrorType;
-
-/**
- * A switchboard flag.
- */
-typedef enum
-{
-	MSN_SB_FLAG_IM = 0x01, /**< This switchboard is being used for a conversation. */
-	MSN_SB_FLAG_FT = 0x02  /**< This switchboard is being used for file transfer. */
-} MsnSBFlag;
-
-#include "cmdproc.h"
-#include "msg.h"
-#include "servconn.h"
-#include "session.h"
-
-/**
- * A switchboard.
- *
- * A place where a bunch of users send messages to the rest of the users.
- */
-struct _MsnSwitchBoard
-{
-	MsnSession *session;   /**< Our parent session. */
-	MsnServConn *servconn; /**< The physical connection for this switchboard. */
-	MsnCmdProc *cmdproc;   /**< Convenience variable for servconn->cmdproc. */
-	char *im_user;
-
-	MsnSBFlag flag;
-	char *auth_key;
-	char *session_id;
-
-	PurpleConversation *conv; /**< The conversation that displays the
-							  messages of this switchboard, or @c NULL if
-							  this is a helper switchboard. */
-
-	gboolean empty;			/**< A flag that states if the swithcboard has no
-							  users in it. */
-	gboolean invited;		/**< A flag that states if we were invited to the
-							  switchboard. */
-	gboolean ready;			/**< A flag that states if this switchboard is
-							  ready to be used. */
-	gboolean closed;		/**< A flag that states if the switchboard has
-							  been closed by the user. */
-	gboolean destroying;	/**< A flag that states if the switchboard is
-							  alredy on the process of destruction. */
-
-	int current_users;
-	int total_users;
-	GList *users;
-
-	int chat_id;
-
-	GQueue *msg_queue; /**< Queue of messages to send. */
-	GList *ack_list; /**< List of messages waiting for an ack. */
-
-	MsnSBErrorType error; /**< The error that occurred in this switchboard
-							(if applicable). */
-	GList *slplinks; /**< The list of slplinks that are using this switchboard. */
-	guint reconn_timeout_h;
-};
-
-/**
- * Initialize the variables for switchboard creation.
- */
-void msn_switchboard_init(void);
-
-/**
- * Destroy the variables for switchboard creation.
- */
-void msn_switchboard_end(void);
-
-/**
- * Creates a new switchboard.
- *
- * @param session The MSN session.
- *
- * @return The new switchboard.
- */
-MsnSwitchBoard *msn_switchboard_new(MsnSession *session);
-
-/**
- * Destroys a switchboard.
- *
- * @param swboard The switchboard to destroy.
- */
-void msn_switchboard_destroy(MsnSwitchBoard *swboard);
-
-/**
- * Sets the auth key the switchboard must use when connecting.
- *
- * @param swboard The switchboard.
- * @param key     The auth key.
- */
-void msn_switchboard_set_auth_key(MsnSwitchBoard *swboard, const char *key);
-
-/**
- * Returns the auth key the switchboard must use when connecting.
- *
- * @param swboard The switchboard.
- *
- * @return The auth key.
- */
-const char *msn_switchboard_get_auth_key(MsnSwitchBoard *swboard);
-
-/**
- * Sets the session ID the switchboard must use when connecting.
- *
- * @param swboard The switchboard.
- * @param id      The session ID.
- */
-void msn_switchboard_set_session_id(MsnSwitchBoard *swboard, const char *id);
-
-/**
- * Returns the session ID the switchboard must use when connecting.
- *
- * @param swboard The switchboard.
- *
- * @return The session ID.
- */
-const char *msn_switchboard_get_session_id(MsnSwitchBoard *swboard);
-
-/**
- * Returns the next chat ID for use by a switchboard.
- *
- * @return The chat ID.
- */
-int msn_switchboard_get_chat_id(void);
-
-/**
- * Sets whether or not we were invited to this switchboard.
- *
- * @param swboard The switchboard.
- * @param invite  @c TRUE if invited, @c FALSE otherwise.
- */
-void msn_switchboard_set_invited(MsnSwitchBoard *swboard, gboolean invited);
-
-/**
- * Returns whether or not we were invited to this switchboard.
- *
- * @param swboard The switchboard.
- *
- * @return @c TRUE if invited, @c FALSE otherwise.
- */
-gboolean msn_switchboard_is_invited(MsnSwitchBoard *swboard);
-
-/**
- * Connects to a switchboard.
- *
- * @param swboard The switchboard.
- * @param host    The switchboard server host.
- * @param port    The switcbharod server port.
- *
- * @return @c TRUE if able to connect, or @c FALSE otherwise.
- */
-gboolean msn_switchboard_connect(MsnSwitchBoard *swboard,
-								 const char *host, int port);
-
-/**
- * Disconnects from a switchboard.
- *
- * @param swboard The switchboard to disconnect from.
- */
-void msn_switchboard_disconnect(MsnSwitchBoard *swboard);
-
-/**
- * Closes the switchboard.
- *
- * Called when a conversation is closed.
- *
- * @param swboard The switchboard to close.
- */
-void msn_switchboard_close(MsnSwitchBoard *swboard);
-
-/**
- * Release a switchboard from a certain function.
- *
- * @param swboard The switchboard to release.
- * @param flag The flag that states the function.
- */
-void msn_switchboard_release(MsnSwitchBoard *swboard, MsnSBFlag flag);
-
-/**
- * Returns whether or not we currently can send a message through this
- * switchboard.
- *
- * @param swboard The switchboard.
- *
- * @return @c TRUE if a message can be sent, @c FALSE otherwise.
- */
-gboolean msn_switchboard_can_send(MsnSwitchBoard *swboard);
-
-/**
- * Sends a message through this switchboard.
- *
- * @param swboard The switchboard.
- * @param msg The message.
- * @param queue A flag that states if we want this message to be queued (in
- * the case it cannot currently be sent).
- *
- * @return @c TRUE if a message can be sent, @c FALSE otherwise.
- */
-void msn_switchboard_send_msg(MsnSwitchBoard *swboard, MsnMessage *msg,
-							  gboolean queue);
-
-void
-msg_error_helper(MsnCmdProc *cmdproc, MsnMessage *msg, MsnMsgErrorType error);
-
-gboolean msn_switchboard_chat_leave(MsnSwitchBoard *swboard);
-gboolean msn_switchboard_chat_invite(MsnSwitchBoard *swboard, const char *who);
-
-gboolean msn_switchboard_request(MsnSwitchBoard *swboard);
-void msn_switchboard_request_add_user(MsnSwitchBoard *swboard, const char *user);
-
-/**
- * Shows an ink message from this switchboard.
- *
- * @param swboard  The switchboard.
- * @param passport The user that sent the ink.
- * @param data     The ink data.
- */
-void msn_switchboard_show_ink(MsnSwitchBoard *swboard, const char *passport,
-                              const char *data);
-
-#endif /* MSN_SWITCHBOARD_H */
--- a/libpurple/protocols/msn/table.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-/**
- * @file table.c MSN helper structure
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#include "msn.h"
-#include "table.h"
-
-static void
-null_cmd_cb(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-}
-
-static void
-null_error_cb(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
-{
-}
-
-MsnTable *
-msn_table_new()
-{
-	MsnTable *table;
-
-	table = g_new0(MsnTable, 1);
-
-	table->cmds = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify)g_hash_table_destroy);
-	table->msgs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
-	table->errors = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
-
-	table->async = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
-	table->fallback = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
-
-	return table;
-}
-
-void
-msn_table_destroy(MsnTable *table)
-{
-	g_return_if_fail(table != NULL);
-
-	g_hash_table_destroy(table->cmds);
-	g_hash_table_destroy(table->msgs);
-	g_hash_table_destroy(table->errors);
-
-	g_hash_table_destroy(table->async);
-	g_hash_table_destroy(table->fallback);
-
-	g_free(table);
-}
-
-void
-msn_table_add_cmd(MsnTable *table,
-				  char *command, char *answer, MsnTransCb cb)
-{
-	GHashTable *cbs;
-
-	g_return_if_fail(table  != NULL);
-	g_return_if_fail(answer != NULL);
-
-	cbs = NULL;
-
-	if (command == NULL)
-	{
-		cbs = table->async;
-	}
-	else if (strcmp(command, "fallback") == 0)
-	{
-		cbs = table->fallback;
-	}
-	else
-	{
-		cbs = g_hash_table_lookup(table->cmds, command);
-
-		if (cbs == NULL)
-		{
-			cbs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
-			g_hash_table_insert(table->cmds, command, cbs);
-		}
-	}
-
-	if (cb == NULL)
-		cb = null_cmd_cb;
-
-	g_hash_table_insert(cbs, answer, cb);
-}
-
-void
-msn_table_add_error(MsnTable *table,
-					char *answer, MsnErrorCb cb)
-{
-	g_return_if_fail(table  != NULL);
-	g_return_if_fail(answer != NULL);
-
-	if (cb == NULL)
-		cb = null_error_cb;
-
-	g_hash_table_insert(table->errors, answer, cb);
-}
-
-void
-msn_table_add_msg_type(MsnTable *table,
-					   char *type, MsnMsgTypeCb cb)
-{
-	g_return_if_fail(table != NULL);
-	g_return_if_fail(type  != NULL);
-	g_return_if_fail(cb    != NULL);
-
-#if 0
-	if (cb == NULL)
-		cb = null_msg_cb;
-#endif
-
-	g_hash_table_insert(table->msgs, type, cb);
-}
--- a/libpurple/protocols/msn/table.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/**
- * @file table.h MSN helper structure
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_TABLE_H
-#define MSN_TABLE_H
-
-typedef struct _MsnTable MsnTable;
-
-#include "cmdproc.h"
-#include "transaction.h"
-#include "msg.h"
-
-typedef void (*MsnMsgTypeCb)(MsnCmdProc *cmdproc, MsnMessage *msg);
-
-struct _MsnTable
-{
-	GHashTable *cmds; 		/**< Callbacks that manage command response. */
-	GHashTable *msgs; 		/**< Callbacks that manage incoming messages. */
-	GHashTable *errors; 	/**< Callbacks that manage command errors. */
-
-	GHashTable *async; 		/**< Callbacks that manage incoming asyncronous messages. */
-	/* TODO: Does this one is really needed? */
-	GHashTable *fallback; 	/**< Fallback callback. */
-};
-
-/**
- * Create a new instance of a MsnTable which map commands, errors and messages
- * with callbacks that will handle it.
- *
- * @return A new MsnTable.
- */
-MsnTable *msn_table_new(void);
-
-/**
- * Destroy a MsnTable.
- *
- * @param table The MsnTable to be destroyed.
- */
-void msn_table_destroy(MsnTable *table);
-
-/**
- * Relate an incomming command from server with a callback able to handle
- * the event.
- *
- * @param table 	The MsnTable.
- * @param command 	If NULL this add an incoming asyncronous command set in answer.
- * 					Else, the command sent.
- * @param answer 	The server answer to 'command'. If 'command' is NULL,
- * 					the asyncronous command sent by the server.
- * @param cb 		Callback to handle this event.
- */
-void msn_table_add_cmd(MsnTable *table, char *command, char *answer,
-					   MsnTransCb cb);
-
-/**
- * Set a callback to handle incoming command errors.
- *
- * @param table 	The MsnTable.
- * @param answer 	Incoming command with error.
- * @param cb 		Callback to handle this error.
- */
-void msn_table_add_error(MsnTable *table, char *answer, MsnErrorCb cb);
-
-/**
- * Relate a message Content-type with a callback able to handle it.
- *
- * @param table 	The MsnTable.
- * @param type 		The Message Content-Type.
- * @param cb 		Callback to handle this Content-type.
- */
-void msn_table_add_msg_type(MsnTable *table, char *type, MsnMsgTypeCb cb);
-
-#endif /* MSN_TABLE_H */
--- a/libpurple/protocols/msn/tlv.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,458 +0,0 @@
-/**
- * @file tlv.c MSN TLV functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "tlv.h"
-#include "msnutils.h"
-
-static msn_tlv_t *
-createtlv(guint8 type, guint8 length, guint8 *value)
-{
-	msn_tlv_t *ret;
-
-	ret = g_new(msn_tlv_t, 1);
-	ret->type = type;
-	ret->length = length;
-	ret->value = value;
-
-	return ret;
-}
-
-static void
-freetlv(msn_tlv_t *oldtlv)
-{
-	g_free(oldtlv->value);
-	g_free(oldtlv);
-}
-
-GSList *
-msn_tlvlist_read(const char *bs, size_t bs_len)
-{
-	GSList *list = NULL;
-
-	while (bs_len > 0) {
-		guint8 type, length;
-		msn_tlv_t *tlv;
-
-		if (bs_len == 3 && *bs == 0) {
-			/* Padding to multiple of 4 */
-			break;
-		} else if (bs_len == 2 && *bs == 0) {
-			/* Padding to multiple of 4 */
-			break;
-		} else if (bs_len == 1) {
-			if (*bs == 0) {
-				/* Padding to multiple of 4 */
-				break;
-			} else {
-				/* TLV is not small enough to fit here */
-				msn_tlvlist_free(list);
-				return NULL;
-			}
-		}
-
-		type = msn_pop8(bs);
-		length = msn_pop8(bs);
-		bs_len -= 2;
-
-		if (length > bs_len) {
-			msn_tlvlist_free(list);
-			return NULL;
-		}
-
-		tlv = createtlv(type, length, NULL);
-		if (length > 0) {
-			tlv->value = g_memdup(bs, length);
-			if (!tlv->value) {
-				freetlv(tlv);
-				msn_tlvlist_free(list);
-				return NULL;
-			}
-		}
-
-		bs_len -= length;
-		bs += length;
-
-		list = g_slist_prepend(list, tlv);
-	}
-
-	return g_slist_reverse(list);
-}
-
-GSList *
-msn_tlvlist_copy(GSList *orig)
-{
-	GSList *new = NULL;
-	msn_tlv_t *tlv;
-
-	while (orig != NULL) {
-		tlv = orig->data;
-		msn_tlvlist_add_raw(&new, tlv->type, tlv->length, (const char *)tlv->value);
-		orig = orig->next;
-	}
-
-	return new;
-}
-
-gboolean
-msn_tlvlist_equal(GSList *one, GSList *two)
-{
-	while (one && two) {
-		msn_tlv_t *a = one->data;
-		msn_tlv_t *b = two->data;
-
-		if (a->type != b->type)
-			return FALSE;
-		else if (a->length != b->length)
-			return FALSE;
-		else if (!a->value && b->value)
-			return FALSE;
-		else if (a->value && !b->value)
-			return FALSE;
-		else if (a->value && b->value && memcmp(a->value, b->value, a->length) != 0)
-			return FALSE;
-
-		one = one->next;
-		two = two->next;
-	}
-
-	return one == two;
-}
-
-void
-msn_tlvlist_free(GSList *list)
-{
-	while (list != NULL) {
-		freetlv(list->data);
-		list = g_slist_delete_link(list, list);
-	}
-}
-
-int
-msn_tlvlist_count(GSList *list)
-{
-	return g_slist_length(list);
-}
-
-size_t
-msn_tlvlist_size(GSList *list)
-{
-	int size;
-
-	if (list == NULL)
-		return 0;
-
-	for (size = 0; list; list = list->next)
-		size += (2 + ((msn_tlv_t *)list->data)->length);
-
-	return size;
-}
-
-int
-msn_tlvlist_add_raw(GSList **list, const guint8 type, const guint8 length, const char *value)
-{
-	msn_tlv_t *tlv;
-
-	if (list == NULL)
-		return 0;
-
-	tlv = createtlv(type, length, NULL);
-	if (length > 0)
-		tlv->value = g_memdup(value, length);
-
-	*list = g_slist_append(*list, tlv);
-
-	return tlv->length;
-}
-
-int
-msn_tlvlist_add_8(GSList **list, const guint8 type, const guint8 value)
-{
-	char v8[1];
-
-	msn_write8(v8, value);
-
-	return msn_tlvlist_add_raw(list, type, 1, v8);
-}
-
-int
-msn_tlvlist_add_16(GSList **list, const guint8 type, const guint16 value)
-{
-	char v16[2];
-
-	msn_write16be(v16, value);
-
-	return msn_tlvlist_add_raw(list, type, 2, v16);
-}
-
-int
-msn_tlvlist_add_32(GSList **list, const guint8 type, const guint32 value)
-{
-	char v32[4];
-
-	msn_write32be(v32, value);
-
-	return msn_tlvlist_add_raw(list, type, 4, v32);
-}
-
-int
-msn_tlvlist_add_str(GSList **list, const guint8 type, const char *value)
-{
-	return msn_tlvlist_add_raw(list, type, strlen(value), value);
-}
-
-int
-msn_tlvlist_add_empty(GSList **list, const guint8 type)
-{
-	return msn_tlvlist_add_raw(list, type, 0, NULL);
-}
-
-int
-msn_tlvlist_add_tlv(GSList **list, const msn_tlv_t *tlv)
-{
-	return msn_tlvlist_add_raw(list, tlv->type, tlv->length, (const char *)tlv->value);
-}
-
-int
-msn_tlvlist_replace_raw(GSList **list, const guint8 type, const guint8 length, const char *value)
-{
-	GSList *cur;
-	msn_tlv_t *tlv;
-
-	if (list == NULL)
-		return 0;
-
-	for (cur = *list; cur != NULL; cur = cur->next) {
-		tlv = cur->data;
-		if (tlv->type == type)
-			break;
-	}
-
-	if (cur == NULL)
-		/* TLV does not exist, so add a new one */
-		return msn_tlvlist_add_raw(list, type, length, value);
-
-	g_free(tlv->value);
-	tlv->length = length;
-	if (length > 0) {
-		tlv->value = g_memdup(value, length);
-	} else
-		tlv->value = NULL;
-
-	return length;
-}
-
-int
-msn_tlvlist_replace_str(GSList **list, const guint8 type, const char *str)
-{
-	return msn_tlvlist_replace_raw(list, type, strlen(str), str);
-}
-
-int
-msn_tlvlist_replace_empty(GSList **list, const guint8 type)
-{
-	return msn_tlvlist_replace_raw(list, type, 0, NULL);
-}
-
-int
-msn_tlvlist_replace_8(GSList **list, const guint8 type, const guint8 value)
-{
-	char v8[1];
-
-	msn_write8(v8, value);
-
-	return msn_tlvlist_replace_raw(list, type, 1, v8);
-}
-
-int
-msn_tlvlist_replace_32(GSList **list, const guint8 type, const guint32 value)
-{
-	char v32[4];
-
-	msn_write32be(v32, value);
-
-	return msn_tlvlist_replace_raw(list, type, 4, v32);
-}
-
-int
-msn_tlvlist_replace_tlv(GSList **list, const msn_tlv_t *tlv)
-{
-	return msn_tlvlist_replace_raw(list, tlv->type, tlv->length, (const char *)tlv->value);
-}
-
-void
-msn_tlvlist_remove(GSList **list, const guint8 type)
-{
-	GSList *cur, *next;
-	msn_tlv_t *tlv;
-
-	if (list == NULL || *list == NULL)
-		return;
-
-	cur = *list;
-	while (cur != NULL) {
-		tlv = cur->data;
-		next = cur->next;
-
-		if (tlv->type == type) {
-			/* Delete this TLV */
-			*list = g_slist_delete_link(*list, cur);
-			g_free(tlv->value);
-			g_free(tlv);
-		}
-
-		cur = next;
-	}
-}
-
-char *
-msn_tlvlist_write(GSList *list, guint8 *out_len)
-{
-	char *buf;
-	char *tmp;
-	size_t bytes_left;
-	size_t total_len;
-
-	tmp = buf = g_malloc(256);
-	bytes_left = total_len = 256;
-
-	for (; list; list = g_slist_next(list)) {
-		msn_tlv_t *tlv = (msn_tlv_t *)list->data;
-
-		if (G_UNLIKELY((gsize)tlv->length + 2 > bytes_left)) {
-			buf = g_realloc(buf, total_len + 256);
-			bytes_left += 256;
-			total_len += 256;
-			tmp = buf + (total_len - bytes_left);
-		}
-
-		msn_push8(tmp, tlv->type);
-		msn_push8(tmp, tlv->length);
-		memcpy(tmp, tlv->value, tlv->length);
-		tmp += tlv->length;
-
-		bytes_left -= (tlv->length + 2);
-	}
-
-	/* Align length to multiple of 4 */
-	total_len = total_len - bytes_left;
-	bytes_left = 4 - total_len % 4;
-	if (bytes_left != 4)
-		memset(tmp, 0, bytes_left);
-	else
-		bytes_left = 0;
-
-	*out_len = total_len + bytes_left;
-
-	return buf;
-}
-
-msn_tlv_t *
-msn_tlv_gettlv(GSList *list, const guint8 type, const int nth)
-{
-	msn_tlv_t *tlv;
-	int i;
-
-	for (i = 0; list != NULL; list = list->next) {
-		tlv = list->data;
-		if (tlv->type == type)
-			i++;
-		if (i >= nth)
-			return tlv;
-	}
-
-	return NULL;
-}
-
-int
-msn_tlv_getlength(GSList *list, const guint8 type, const int nth)
-{
-	msn_tlv_t *tlv;
-
-	tlv = msn_tlv_gettlv(list, type, nth);
-	if (tlv == NULL)
-		return -1;
-
-	return tlv->length;
-}
-
-char *
-msn_tlv_getvalue_as_string(msn_tlv_t *tlv)
-{
-	char *ret;
-
-	ret = g_malloc(tlv->length + 1);
-	memcpy(ret, tlv->value, tlv->length);
-	ret[tlv->length] = '\0';
-
-	return ret;
-}
-
-char *
-msn_tlv_getstr(GSList *list, const guint8 type, const int nth)
-{
-	msn_tlv_t *tlv;
-
-	tlv = msn_tlv_gettlv(list, type, nth);
-	if (tlv == NULL)
-		return NULL;
-
-	return msn_tlv_getvalue_as_string(tlv);
-}
-
-guint8
-msn_tlv_get8(GSList *list, const guint8 type, const int nth)
-{
-	msn_tlv_t *tlv;
-
-	tlv = msn_tlv_gettlv(list, type, nth);
-	if (tlv == NULL)
-		return 0; /* erm */
-
-	return msn_read8((const char *)tlv->value);
-}
-
-guint16
-msn_tlv_get16(GSList *list, const guint8 type, const int nth)
-{
-	msn_tlv_t *tlv;
-
-	tlv = msn_tlv_gettlv(list, type, nth);
-	if (tlv == NULL)
-		return 0; /* erm */
-
-	return msn_read16be((const char *)tlv->value);
-}
-
-guint32
-msn_tlv_get32(GSList *list, const guint8 type, const int nth)
-{
-	msn_tlv_t *tlv;
-
-	tlv = msn_tlv_gettlv(list, type, nth);
-	if (tlv == NULL)
-		return 0; /* erm */
-
-	return msn_read32be((const char *)tlv->value);
-}
-
--- a/libpurple/protocols/msn/tlv.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/**
- * @file tlv.h MSN TLV functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#ifndef MSN_TLV_H
-#define MSN_TLV_H
-
-#include "msn.h"
-
-/* TLV structure */
-typedef struct msn_tlv_s
-{
-	guint8 type;
-	guint8 length;
-	guint8 *value;
-} msn_tlv_t;
-
-/* TLV handling functions */
-char *msn_tlv_getvalue_as_string(msn_tlv_t *tlv);
-
-msn_tlv_t *msn_tlv_gettlv(GSList *list, const guint8 type, const int nth);
-int msn_tlv_getlength(GSList *list, const guint8 type, const int nth);
-char *msn_tlv_getstr(GSList *list, const guint8 type, const int nth);
-guint8 msn_tlv_get8(GSList *list, const guint8 type, const int nth);
-guint16 msn_tlv_get16(GSList *list, const guint8 type, const int nth);
-guint32 msn_tlv_get32(GSList *list, const guint8 type, const int nth);
-
-/* TLV list handling functions */
-GSList *msn_tlvlist_read(const char *bs, size_t bs_len);
-GSList *msn_tlvlist_copy(GSList *orig);
-
-int msn_tlvlist_count(GSList *list);
-size_t msn_tlvlist_size(GSList *list);
-gboolean msn_tlvlist_equal(GSList *one, GSList *two);
-char *msn_tlvlist_write(GSList *list, guint8 *out_len);
-void msn_tlvlist_free(GSList *list);
-
-int msn_tlvlist_add_raw(GSList **list, const guint8 type, const guint8 length, const char *value);
-int msn_tlvlist_add_empty(GSList **list, const guint8 type);
-int msn_tlvlist_add_8(GSList **list, const guint8 type, const guint8 value);
-int msn_tlvlist_add_16(GSList **list, const guint8 type, const guint16 value);
-int msn_tlvlist_add_32(GSList **list, const guint8 type, const guint32 value);
-int msn_tlvlist_add_str(GSList **list, const guint8 type, const char *value);
-int msn_tlvlist_add_tlv(GSList **list, const msn_tlv_t *tlv);
-
-int msn_tlvlist_replace_raw(GSList **list, const guint8 type, const guint8 lenth, const char *value);
-int msn_tlvlist_replace_str(GSList **list, const guint8 type, const char *str);
-int msn_tlvlist_replace_empty(GSList **list, const guint8 type);
-int msn_tlvlist_replace_8(GSList **list, const guint8 type, const guint8 value);
-int msn_tlvlist_replace_16(GSList **list, const guint8 type, const guint16 value);
-int msn_tlvlist_replace_32(GSList **list, const guint8 type, const guint32 value);
-int msn_tlvlist_replace_tlv(GSList **list, const msn_tlv_t *tlv);
-
-void msn_tlvlist_remove(GSList **list, const guint8 type);
-
-#endif /* MSN_TLV_H */
-
--- a/libpurple/protocols/msn/transaction.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,247 +0,0 @@
-/**
- * @file transaction.c MSN transaction functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-
-#include "msn.h"
-#include "transaction.h"
-
-MsnTransaction *
-msn_transaction_new(MsnCmdProc *cmdproc, const char *command,
-					const char *format, ...)
-{
-	MsnTransaction *trans;
-	va_list arg;
-
-	g_return_val_if_fail(command != NULL, NULL);
-
-	trans = g_new0(MsnTransaction, 1);
-
-	trans->cmdproc = cmdproc;
-	trans->command = g_strdup(command);
-	trans->saveable = TRUE;
-
-	if (format != NULL)
-	{
-		va_start(arg, format);
-		trans->params = g_strdup_vprintf(format, arg);
-		va_end(arg);
-	}
-
-	/* trans->queue = g_queue_new(); */
-
-	return trans;
-}
-
-void
-msn_transaction_destroy(MsnTransaction *trans)
-{
-	g_return_if_fail(trans != NULL);
-
-	g_free(trans->command);
-	g_free(trans->params);
-	g_free(trans->payload);
-
-	if (trans->data_free)
-		trans->data_free(trans->data);
-
-#if 0
-	if (trans->pendent_cmd != NULL)
-		msn_message_unref(trans->pendent_msg);
-#endif
-
-#if 0
-	MsnTransaction *elem;
-	if (trans->queue != NULL)
-	{
-		while ((elem = g_queue_pop_head(trans->queue)) != NULL)
-			msn_transaction_destroy(elem);
-
-		g_queue_free(trans->queue);
-	}
-#endif
-
-	if (trans->callbacks != NULL && trans->has_custom_callbacks)
-		g_hash_table_destroy(trans->callbacks);
-
-	if (trans->timer)
-		purple_timeout_remove(trans->timer);
-
-	g_free(trans);
-}
-
-char *
-msn_transaction_to_string(MsnTransaction *trans)
-{
-	char *str;
-
-	g_return_val_if_fail(trans != NULL, FALSE);
-
-	if (trans->params != NULL)
-		str = g_strdup_printf("%s %u %s\r\n", trans->command, trans->trId, trans->params);
-	else if (trans->saveable)
-		str = g_strdup_printf("%s %u\r\n", trans->command, trans->trId);
-	else
-		str = g_strdup_printf("%s\r\n", trans->command);
-
-	return str;
-}
-
-void
-msn_transaction_queue_cmd(MsnTransaction *trans, MsnCommand *cmd)
-{
-	purple_debug_info("msn", "queueing command.\n");
-	trans->pendent_cmd = cmd;
-	msn_command_ref(cmd);
-}
-
-void
-msn_transaction_unqueue_cmd(MsnTransaction *trans, MsnCmdProc *cmdproc)
-{
-	MsnCommand *cmd;
-
-	if (!cmdproc->servconn->connected)
-		return;
-
-	purple_debug_info("msn", "unqueueing command.\n");
-	cmd = trans->pendent_cmd;
-
-	g_return_if_fail(cmd != NULL);
-
-	msn_cmdproc_process_cmd(cmdproc, cmd);
-	msn_command_unref(cmd);
-
-	trans->pendent_cmd = NULL;
-}
-
-#if 0
-void
-msn_transaction_queue(MsnTransaction *trans, MsnTransaction *elem)
-{
-	if (trans->queue == NULL)
-		trans->queue = g_queue_new();
-
-	g_queue_push_tail(trans->queue, elem);
-}
-
-void
-msn_transaction_unqueue(MsnTransaction *trans, MsnCmdProc *cmdproc)
-{
-	MsnTransaction *elem;
-
-	while ((elem = g_queue_pop_head(trans->queue)) != NULL)
-		msn_cmdproc_send_trans(cmdproc, elem);
-}
-#endif
-
-void
-msn_transaction_set_payload(MsnTransaction *trans,
-							const char *payload, gsize payload_len)
-{
-	g_return_if_fail(trans   != NULL);
-	g_return_if_fail(payload != NULL);
-
-	trans->payload = g_strdup(payload);
-	trans->payload_len = payload_len ? payload_len : strlen(trans->payload);
-}
-
-void
-msn_transaction_set_data(MsnTransaction *trans, void *data)
-{
-	g_return_if_fail(trans != NULL);
-
-	trans->data = data;
-}
-
-void msn_transaction_set_data_free(MsnTransaction *trans, GDestroyNotify fn)
-{
-	g_return_if_fail(trans != NULL);
-	trans->data_free = fn;
-}
-
-void
-msn_transaction_set_saveable(MsnTransaction  *trans, gboolean saveable)
-{
-	g_return_if_fail(trans != NULL);
-
-	trans->saveable = saveable;
-}
-
-void
-msn_transaction_add_cb(MsnTransaction *trans, char *answer,
-					   MsnTransCb cb)
-{
-	g_return_if_fail(trans  != NULL);
-	g_return_if_fail(answer != NULL);
-
-	if (trans->callbacks == NULL)
-	{
-		trans->has_custom_callbacks = TRUE;
-		trans->callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
-												 NULL);
-	}
-	else if (trans->has_custom_callbacks != TRUE)
-		g_return_if_reached ();
-
-	g_hash_table_insert(trans->callbacks, answer, cb);
-}
-
-static gboolean
-transaction_timeout(gpointer data)
-{
-	MsnTransaction *trans;
-
-	trans = data;
-	g_return_val_if_fail(trans != NULL, FALSE);
-
-#if 0
-	purple_debug_info("msn", "timed out: %s %d %s\n", trans->command, trans->trId, trans->params);
-#endif
-
-	trans->timer = 0;
-
-	if (trans->timeout_cb != NULL)
-		trans->timeout_cb(trans->cmdproc, trans);
-
-	return FALSE;
-}
-
-void
-msn_transaction_set_timeout_cb(MsnTransaction *trans, MsnTimeoutCb cb)
-{
-	if (trans->timer)
-	{
-		purple_debug_error("msn", "This shouldn't be happening\n");
-		purple_timeout_remove(trans->timer);
-	}
-	trans->timeout_cb = cb;
-	trans->timer = purple_timeout_add_seconds(60, transaction_timeout, trans);
-}
-
-void
-msn_transaction_set_error_cb(MsnTransaction *trans, MsnErrorCb cb)
-{
-	trans->error_cb = cb;
-}
--- a/libpurple/protocols/msn/transaction.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/**
- * @file transaction.h MSN transaction functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_TRANSACTION_H
-#define MSN_TRANSACTION_H
-
-#include "internal.h"
-
-typedef struct _MsnTransaction MsnTransaction;
-
-#include "cmdproc.h"
-#include "command.h"
-
-typedef void (*MsnTransCb)(MsnCmdProc *cmdproc, MsnCommand *cmd);
-typedef void (*MsnTimeoutCb)(MsnCmdProc *cmdproc, MsnTransaction *trans);
-typedef void (*MsnErrorCb)(MsnCmdProc *cmdproc, MsnTransaction *trans,
-						   int error);
-
-/**
- * A transaction. A sending command that will initiate the transaction.
- */
-struct _MsnTransaction
-{
-	MsnCmdProc *cmdproc;
-
-	gboolean saveable;	/**< Whether to save this transaction in the history */
-	unsigned int trId;	/**< The ID of this transaction, if it's being saved */
-
-	char *command;
-	char *params;
-
-	guint timer;
-
-	void *data; /**< The data to be used on the different callbacks. */
-	GDestroyNotify data_free;  /**< The function to free 'data', or @c NULL */
-
-	GHashTable *callbacks;
-	gboolean has_custom_callbacks;
-	MsnErrorCb error_cb;
-	MsnTimeoutCb timeout_cb;
-
-	char *payload;
-	size_t payload_len;
-
-	GQueue *queue;
-	MsnCommand *pendent_cmd; /**< The command that is waiting for the result of
-							   this transaction. */
-};
-
-MsnTransaction *msn_transaction_new(MsnCmdProc *cmdproc, const char *command,
-	const char *format, ...) G_GNUC_PRINTF(3, 4);
-void msn_transaction_destroy(MsnTransaction *trans);
-
-char *msn_transaction_to_string(MsnTransaction *trans);
-void msn_transaction_queue_cmd(MsnTransaction *trans, MsnCommand *cmd);
-void msn_transaction_unqueue_cmd(MsnTransaction *trans, MsnCmdProc *cmdproc);
-void msn_transaction_set_payload(MsnTransaction *trans,
-								 const char *payload, gsize payload_len);
-void msn_transaction_set_data(MsnTransaction *trans, void *data);
-void msn_transaction_set_data_free(MsnTransaction *trans, GDestroyNotify fn);
-void msn_transaction_set_saveable(MsnTransaction  *trans, gboolean saveable);
-void msn_transaction_add_cb(MsnTransaction *trans, char *answer,
-							MsnTransCb cb);
-void msn_transaction_set_error_cb(MsnTransaction *trans, MsnErrorCb cb);
-void msn_transaction_set_timeout_cb(MsnTransaction *trans, MsnTimeoutCb cb);
-
-#endif /* MSN_TRANSACTION_H */
--- a/libpurple/protocols/msn/user.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,801 +0,0 @@
-/**
- * @file user.c User functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-#include "util.h"
-
-#include "user.h"
-#include "slp.h"
-
-static void free_user_endpoint(MsnUserEndpoint *data)
-{
-	g_free(data->id);
-	g_free(data->name);
-	g_free(data);
-}
-
-/*new a user object*/
-MsnUser *
-msn_user_new(MsnUserList *userlist, const char *passport,
-			 const char *friendly_name)
-{
-	MsnUser *user;
-
-	user = g_new0(MsnUser, 1);
-
-	user->userlist = userlist;
-
-	msn_user_set_passport(user, passport);
-	msn_user_set_friendly_name(user, friendly_name);
-
-	return msn_user_ref(user);
-}
-
-/*destroy a user object*/
-static void
-msn_user_destroy(MsnUser *user)
-{
-	while (user->endpoints != NULL) {
-		free_user_endpoint(user->endpoints->data);
-		user->endpoints = g_slist_delete_link(user->endpoints, user->endpoints);
-	}
-
-	if (user->clientcaps != NULL)
-		g_hash_table_destroy(user->clientcaps);
-
-	if (user->group_ids != NULL)
-	{
-		GList *l;
-		for (l = user->group_ids; l != NULL; l = l->next)
-		{
-			g_free(l->data);
-		}
-		g_list_free(user->group_ids);
-	}
-
-	if (user->msnobj != NULL)
-		msn_object_destroy(user->msnobj);
-
-	g_free(user->passport);
-	g_free(user->friendly_name);
-	g_free(user->uid);
-	if (user->extinfo) {
-		g_free(user->extinfo->media_album);
-		g_free(user->extinfo->media_artist);
-		g_free(user->extinfo->media_title);
-		g_free(user->extinfo->phone_home);
-		g_free(user->extinfo->phone_mobile);
-		g_free(user->extinfo->phone_work);
-		g_free(user->extinfo);
-	}
-	g_free(user->statusline);
-	g_free(user->invite_message);
-
-	g_free(user);
-}
-
-MsnUser *
-msn_user_ref(MsnUser *user)
-{
-	g_return_val_if_fail(user != NULL, NULL);
-
-	user->refcount++;
-
-	return user;
-}
-
-void
-msn_user_unref(MsnUser *user)
-{
-	g_return_if_fail(user != NULL);
-
-	user->refcount--;
-
-	if(user->refcount == 0)
-		msn_user_destroy(user);
-}
-
-void
-msn_user_update(MsnUser *user)
-{
-	PurpleAccount *account;
-	gboolean offline;
-
-	g_return_if_fail(user != NULL);
-
-	account = user->userlist->session->account;
-
-	offline = (user->status == NULL);
-
-	if (!offline) {
-		purple_prpl_got_user_status(account, user->passport, user->status,
-				"message", user->statusline, NULL);
-	} else {
-		if (user->mobile) {
-			purple_prpl_got_user_status(account, user->passport, "mobile", NULL);
-			purple_prpl_got_user_status(account, user->passport, "available", NULL);
-		} else {
-			purple_prpl_got_user_status(account, user->passport, "offline", NULL);
-		}
-	}
-
-	if (!offline || !user->mobile) {
-		purple_prpl_got_user_status_deactive(account, user->passport, "mobile");
-	}
-
-	if (!offline && user->extinfo && user->extinfo->media_type != CURRENT_MEDIA_UNKNOWN) {
-		if (user->extinfo->media_type == CURRENT_MEDIA_MUSIC) {
-			purple_prpl_got_user_status(account, user->passport, "tune",
-			                            PURPLE_TUNE_ARTIST, user->extinfo->media_artist,
-			                            PURPLE_TUNE_ALBUM, user->extinfo->media_album,
-			                            PURPLE_TUNE_TITLE, user->extinfo->media_title,
-			                            NULL);
-		} else if (user->extinfo->media_type == CURRENT_MEDIA_GAMES) {
-			purple_prpl_got_user_status(account, user->passport, "tune",
-			                            "game", user->extinfo->media_title,
-			                            NULL);
-		} else if (user->extinfo->media_type == CURRENT_MEDIA_OFFICE) {
-			purple_prpl_got_user_status(account, user->passport, "tune",
-			                            "office", user->extinfo->media_title,
-			                            NULL);
-		} else {
-			purple_debug_warning("msn", "Got CurrentMedia with unknown type %d.\n",
-			                     user->extinfo->media_type);
-		}
-	} else {
-		purple_prpl_got_user_status_deactive(account, user->passport, "tune");
-	}
-
-	if (user->idle)
-		purple_prpl_got_user_idle(account, user->passport, TRUE, -1);
-	else
-		purple_prpl_got_user_idle(account, user->passport, FALSE, 0);
-}
-
-void
-msn_user_set_state(MsnUser *user, const char *state)
-{
-	const char *status;
-
-	g_return_if_fail(user != NULL);
-
-	if (state == NULL) {
-		user->status = NULL;
-		return;
-	}
-
-	if (!g_ascii_strcasecmp(state, "BSY"))
-		status = "busy";
-	else if (!g_ascii_strcasecmp(state, "BRB"))
-		status = "brb";
-	else if (!g_ascii_strcasecmp(state, "AWY"))
-		status = "away";
-	else if (!g_ascii_strcasecmp(state, "PHN"))
-		status = "phone";
-	else if (!g_ascii_strcasecmp(state, "LUN"))
-		status = "lunch";
-	else if (!g_ascii_strcasecmp(state, "HDN"))
-		status = NULL;
-	else
-		status = "available";
-
-	if (!g_ascii_strcasecmp(state, "IDL"))
-		user->idle = TRUE;
-	else
-		user->idle = FALSE;
-
-	user->status = status;
-}
-
-void
-msn_user_set_passport(MsnUser *user, const char *passport)
-{
-	g_return_if_fail(user != NULL);
-
-	g_free(user->passport);
-	user->passport = g_strdup(passport);
-}
-
-gboolean
-msn_user_set_friendly_name(MsnUser *user, const char *name)
-{
-	g_return_val_if_fail(user != NULL, FALSE);
-
-	if (!name)
-		return FALSE;
-
-	if (user->friendly_name && (!strcmp(user->friendly_name, name) ||
-				!strcmp(user->passport, name)))
-		return FALSE;
-
-	g_free(user->friendly_name);
-	user->friendly_name = g_strdup(name);
-
-	serv_got_alias(purple_account_get_connection(user->userlist->session->account),
-			user->passport, name);
-	return TRUE;
-}
-
-void
-msn_user_set_statusline(MsnUser *user, const char *statusline)
-{
-	g_return_if_fail(user != NULL);
-
-	g_free(user->statusline);
-	user->statusline = g_strdup(statusline);
-}
-
-void
-msn_user_set_uid(MsnUser *user, const char *uid)
-{
-	g_return_if_fail(user != NULL);
-
-	g_free(user->uid);
-	user->uid = g_strdup(uid);
-}
-
-void
-msn_user_set_endpoint_data(MsnUser *user, const char *input, MsnUserEndpoint *newep)
-{
-	MsnUserEndpoint *ep;
-	char *endpoint;
-	GSList *l;
-
-	g_return_if_fail(user != NULL);
-	g_return_if_fail(input != NULL);
-
-	endpoint = g_ascii_strdown(input, -1);
-
-	for (l = user->endpoints; l; l = l->next) {
-		ep = l->data;
-		if (g_str_equal(ep->id, endpoint)) {
-			/* We have info about this endpoint! */
-
-			g_free(endpoint);
-
-			if (newep == NULL) {
-				/* Delete it and exit */
-				user->endpoints = g_slist_delete_link(user->endpoints, l);
-				free_user_endpoint(ep);
-				return;
-			}
-
-			/* Break out of our loop and update it */
-			break;
-		}
-	}
-	if (l == NULL) {
-		/* Need to add a new endpoint */
-		ep = g_new0(MsnUserEndpoint, 1);
-		ep->id = endpoint;
-		user->endpoints = g_slist_prepend(user->endpoints, ep);
-	}
-
-	ep->clientid = newep->clientid;
-	ep->extcaps = newep->extcaps;
-}
-
-void
-msn_user_clear_endpoints(MsnUser *user)
-{
-	MsnUserEndpoint *ep;
-	GSList *l;
-
-	g_return_if_fail(user != NULL);
-
-	for (l = user->endpoints; l; l = g_slist_delete_link(l, l)) {
-		ep = l->data;
-		free_user_endpoint(ep);
-	}
-
-	user->endpoints = NULL;
-}
-
-void
-msn_user_set_op(MsnUser *user, MsnListOp list_op)
-{
-	g_return_if_fail(user != NULL);
-
-	user->list_op |= list_op;
-}
-
-void
-msn_user_unset_op(MsnUser *user, MsnListOp list_op)
-{
-	g_return_if_fail(user != NULL);
-
-	user->list_op &= ~list_op;
-}
-
-void
-msn_user_set_buddy_icon(MsnUser *user, PurpleStoredImage *img)
-{
-	MsnObject *msnobj;
-
-	g_return_if_fail(user != NULL);
-
-	msnobj = msn_object_new_from_image(img, "TFR2C2.tmp",
-			user->passport, MSN_OBJECT_USERTILE);
-
-	if (!msnobj)
-		purple_debug_error("msn", "Unable to open buddy icon from %s!\n", user->passport);
-
-	msn_user_set_object(user, msnobj);
-}
-
-/*add group id to User object*/
-void
-msn_user_add_group_id(MsnUser *user, const char* group_id)
-{
-	MsnUserList *userlist;
-	PurpleAccount *account;
-	PurpleBuddy *b;
-	PurpleGroup *g;
-	const char *passport;
-	const char *group_name;
-
-	g_return_if_fail(user != NULL);
-	g_return_if_fail(group_id != NULL);
-
-	user->group_ids = g_list_append(user->group_ids, g_strdup(group_id));
-
-	userlist = user->userlist;
-	account = userlist->session->account;
-	passport = msn_user_get_passport(user);
-
-	group_name = msn_userlist_find_group_name(userlist, group_id);
-
-	purple_debug_info("msn", "User: group id:%s,name:%s,user:%s\n", group_id, group_name, passport);
-
-	g = purple_find_group(group_name);
-
-	if ((group_id == NULL) && (g == NULL))
-	{
-		g = purple_group_new(group_name);
-		purple_blist_add_group(g, NULL);
-	}
-
-	b = purple_find_buddy_in_group(account, passport, g);
-	if (b == NULL)
-	{
-		b = purple_buddy_new(account, passport, NULL);
-		purple_blist_add_buddy(b, NULL, g, NULL);
-	}
-	purple_buddy_set_protocol_data(b, user);
-	/*Update the blist Node info*/
-}
-
-/*check if the msn user is online*/
-gboolean
-msn_user_is_online(PurpleAccount *account, const char *name)
-{
-	PurpleBuddy *buddy;
-
-	buddy = purple_find_buddy(account, name);
-	return PURPLE_BUDDY_IS_ONLINE(buddy);
-}
-
-gboolean
-msn_user_is_yahoo(PurpleAccount *account, const char *name)
-{
-	MsnSession *session = NULL;
-	MsnUser *user;
-	PurpleConnection *gc;
-
-	gc = purple_account_get_connection(account);
-	if (gc != NULL)
-		session = gc->proto_data;
-
-	if ((session != NULL) && (user = msn_userlist_find_user(session->userlist, name)) != NULL)
-	{
-		return (user->networkid == MSN_NETWORK_YAHOO);
-	}
-	return (strstr(name,"@yahoo.") != NULL);
-}
-
-void
-msn_user_remove_group_id(MsnUser *user, const char *id)
-{
-	GList *l;
-
-	g_return_if_fail(user != NULL);
-	g_return_if_fail(id != NULL);
-
-	l = g_list_find_custom(user->group_ids, id, (GCompareFunc)strcmp);
-
-	if (l == NULL)
-		return;
-
-	g_free(l->data);
-	user->group_ids = g_list_delete_link(user->group_ids, l);
-}
-
-void
-msn_user_set_pending_group(MsnUser *user, const char *group)
-{
-	user->pending_group = g_strdup(group);
-}
-
-char *
-msn_user_remove_pending_group(MsnUser *user)
-{
-	char *group = user->pending_group;
-	user->pending_group = NULL;
-	return group;
-}
-
-void
-msn_user_set_home_phone(MsnUser *user, const char *number)
-{
-	g_return_if_fail(user != NULL);
-
-	if (!number && !user->extinfo)
-		return;
-
-	if (user->extinfo)
-		g_free(user->extinfo->phone_home);
-	else
-		user->extinfo = g_new0(MsnUserExtendedInfo, 1);
-
-	user->extinfo->phone_home = g_strdup(number);
-}
-
-void
-msn_user_set_work_phone(MsnUser *user, const char *number)
-{
-	g_return_if_fail(user != NULL);
-
-	if (!number && !user->extinfo)
-		return;
-
-	if (user->extinfo)
-		g_free(user->extinfo->phone_work);
-	else
-		user->extinfo = g_new0(MsnUserExtendedInfo, 1);
-
-	user->extinfo->phone_work = g_strdup(number);
-}
-
-void
-msn_user_set_mobile_phone(MsnUser *user, const char *number)
-{
-	g_return_if_fail(user != NULL);
-
-	if (!number && !user->extinfo)
-		return;
-
-	if (user->extinfo)
-		g_free(user->extinfo->phone_mobile);
-	else
-		user->extinfo = g_new0(MsnUserExtendedInfo, 1);
-
-	user->extinfo->phone_mobile = g_strdup(number);
-}
-
-void
-msn_user_set_clientid(MsnUser *user, guint clientid)
-{
-	g_return_if_fail(user != NULL);
-
-	user->clientid = clientid;
-}
-
-void
-msn_user_set_extcaps(MsnUser *user, guint extcaps)
-{
-	g_return_if_fail(user != NULL);
-
-	user->extcaps = extcaps;
-}
-
-void
-msn_user_set_network(MsnUser *user, MsnNetwork network)
-{
-	g_return_if_fail(user != NULL);
-
-	user->networkid = network;
-}
-
-static gboolean
-buddy_icon_cached(PurpleConnection *gc, MsnObject *obj)
-{
-	PurpleAccount *account;
-	PurpleBuddy *buddy;
-	const char *old;
-	const char *new;
-
-	g_return_val_if_fail(obj != NULL, FALSE);
-
-	account = purple_connection_get_account(gc);
-
-	buddy = purple_find_buddy(account, msn_object_get_creator(obj));
-	if (buddy == NULL)
-		return FALSE;
-
-	old = purple_buddy_icons_get_checksum_for_user(buddy);
-	new = msn_object_get_sha1(obj);
-
-	if (new == NULL)
-		return FALSE;
-
-	/* If the old and new checksums are the same, and the file actually exists,
-	 * then return TRUE */
-	if (old != NULL && !strcmp(old, new))
-		return TRUE;
-
-	return FALSE;
-}
-
-static void
-queue_buddy_icon_request(MsnUser *user)
-{
-	PurpleAccount *account;
-	MsnObject *obj;
-	GQueue *queue;
-
-	g_return_if_fail(user != NULL);
-
-	account = user->userlist->session->account;
-
-	obj = msn_user_get_object(user);
-
-	if (obj == NULL) {
-		purple_buddy_icons_set_for_user(account, user->passport, NULL, 0, NULL);
-		return;
-	}
-
-	if (!buddy_icon_cached(account->gc, obj)) {
-		MsnUserList *userlist;
-
-		userlist = user->userlist;
-		queue = userlist->buddy_icon_requests;
-
-		if (purple_debug_is_verbose())
-			purple_debug_info("msn", "Queueing buddy icon request for %s (buddy_icon_window = %i)\n",
-			                  user->passport, userlist->buddy_icon_window);
-
-		g_queue_push_tail(queue, user);
-
-		if (userlist->buddy_icon_window > 0)
-			msn_release_buddy_icon_request(userlist);
-	}
-}
-
-void
-msn_user_set_object(MsnUser *user, MsnObject *obj)
-{
-	g_return_if_fail(user != NULL);
-
-	if (user->msnobj != NULL && !msn_object_find_local(msn_object_get_sha1(obj)))
-		msn_object_destroy(user->msnobj);
-
-	user->msnobj = obj;
-
-	if (user->list_op & MSN_LIST_FL_OP)
-		queue_buddy_icon_request(user);
-}
-
-void
-msn_user_set_client_caps(MsnUser *user, GHashTable *info)
-{
-	g_return_if_fail(user != NULL);
-	g_return_if_fail(info != NULL);
-
-	if (user->clientcaps != NULL)
-		g_hash_table_destroy(user->clientcaps);
-
-	user->clientcaps = info;
-}
-
-void
-msn_user_set_invite_message(MsnUser *user, const char *message)
-{
-	g_return_if_fail(user != NULL);
-
-	g_free(user->invite_message);
-	user->invite_message = g_strdup(message);
-}
-
-const char *
-msn_user_get_passport(const MsnUser *user)
-{
-	g_return_val_if_fail(user != NULL, NULL);
-
-	return user->passport;
-}
-
-const char *
-msn_user_get_friendly_name(const MsnUser *user)
-{
-	g_return_val_if_fail(user != NULL, NULL);
-
-	return user->friendly_name;
-}
-
-const char *
-msn_user_get_home_phone(const MsnUser *user)
-{
-	g_return_val_if_fail(user != NULL, NULL);
-
-	return user->extinfo ? user->extinfo->phone_home : NULL;
-}
-
-const char *
-msn_user_get_work_phone(const MsnUser *user)
-{
-	g_return_val_if_fail(user != NULL, NULL);
-
-	return user->extinfo ? user->extinfo->phone_work : NULL;
-}
-
-const char *
-msn_user_get_mobile_phone(const MsnUser *user)
-{
-	g_return_val_if_fail(user != NULL, NULL);
-
-	return user->extinfo ? user->extinfo->phone_mobile : NULL;
-}
-
-guint
-msn_user_get_clientid(const MsnUser *user)
-{
-	g_return_val_if_fail(user != NULL, 0);
-
-	return user->clientid;
-}
-
-guint
-msn_user_get_extcaps(const MsnUser *user)
-{
-	g_return_val_if_fail(user != NULL, 0);
-
-	return user->extcaps;
-}
-
-MsnUserEndpoint *
-msn_user_get_endpoint_data(MsnUser *user, const char *input)
-{
-	char *endpoint;
-	GSList *l;
-	MsnUserEndpoint *ep;
-
-	g_return_val_if_fail(user != NULL, NULL);
-	g_return_val_if_fail(input != NULL, NULL);
-
-	endpoint = g_ascii_strdown(input, -1);
-
-	for (l = user->endpoints; l; l = l->next) {
-		ep = l->data;
-		if (g_str_equal(ep->id, endpoint)) {
-			g_free(endpoint);
-			return ep;
-		}
-	}
-
-	g_free(endpoint);
-
-	return NULL;
-}
-
-MsnNetwork
-msn_user_get_network(const MsnUser *user)
-{
-	g_return_val_if_fail(user != NULL, MSN_NETWORK_UNKNOWN);
-
-	return user->networkid;
-}
-
-MsnObject *
-msn_user_get_object(const MsnUser *user)
-{
-	g_return_val_if_fail(user != NULL, NULL);
-
-	return user->msnobj;
-}
-
-GHashTable *
-msn_user_get_client_caps(const MsnUser *user)
-{
-	g_return_val_if_fail(user != NULL, NULL);
-
-	return user->clientcaps;
-}
-
-const char *
-msn_user_get_invite_message(const MsnUser *user)
-{
-	g_return_val_if_fail(user != NULL, NULL);
-
-	return user->invite_message;
-}
-
-gboolean
-msn_user_is_capable(MsnUser *user, char *endpoint, guint capability, guint extcap)
-{
-	g_return_val_if_fail(user != NULL, FALSE);
-
-	if (endpoint != NULL) {
-		MsnUserEndpoint *ep = msn_user_get_endpoint_data(user, endpoint);
-		if (ep != NULL)
-			return (ep->clientid & capability) && (ep->extcaps & extcap);
-		else
-			return FALSE;
-	}
-
-	return (user->clientid & capability) && (user->extcaps & extcap);
-}
-
-/**************************************************************************
- * Utility functions
- **************************************************************************/
-
-int
-msn_user_passport_cmp(MsnUser *user, const char *passport)
-{
-	const char *str;
-	char *pass;
-	int result;
-
-	str = purple_normalize_nocase(NULL, msn_user_get_passport(user));
-	pass = g_strdup(str);
-
-#if GLIB_CHECK_VERSION(2,16,0)
-	result = g_strcmp0(pass, purple_normalize_nocase(NULL, passport));
-#else
-	str = purple_normalize_nocase(NULL, passport);
-	if (!pass)
-		result = -(pass != str);
-	else if (!str)
-		result = pass != str;
-	else
-		result = strcmp(pass, str);
-#endif /* GLIB < 2.16.0 */
-
-	g_free(pass);
-
-	return result;
-}
-
-gboolean
-msn_user_is_in_group(MsnUser *user, const char * group_id)
-{
-	if (user == NULL)
-		return FALSE;
-
-	if (group_id == NULL)
-		return FALSE;
-
-	return (g_list_find_custom(user->group_ids, group_id, (GCompareFunc)strcmp)) != NULL;
-}
-
-gboolean
-msn_user_is_in_list(MsnUser *user, MsnListId list_id)
-{
-	if (user == NULL)
-		return FALSE;
-
-	return (user->list_op & (1 << list_id));
-}
-
--- a/libpurple/protocols/msn/user.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,533 +0,0 @@
-/**
- * @file user.h User functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_USER_H
-#define MSN_USER_H
-
-typedef struct _MsnUser  MsnUser;
-
-typedef enum
-{
-	MSN_NETWORK_UNKNOWN      = 0,
-	MSN_NETWORK_PASSPORT     = 1,
-	MSN_NETWORK_COMMUNICATOR = 2,
-	MSN_NETWORK_MOBILE       = 4,
-	MSN_NETWORK_MNI          = 8,
-	MSN_NETWORK_CIRCLE       = 9,
-	MSN_NETWORK_TEMP_GROUP   = 10,
-	MSN_NETWORK_CID          = 11,
-	MSN_NETWORK_CONNECT      = 13,
-	MSN_NETWORK_REMOTE       = 14,
-	MSN_NETWORK_SMTP         = 16,
-	MSN_NETWORK_YAHOO        = 32
-} MsnNetwork;
-
-/**
- * Current media.
- */
-typedef enum
-{
-	CURRENT_MEDIA_UNKNOWN,
-	CURRENT_MEDIA_MUSIC,
-	CURRENT_MEDIA_GAMES,
-	CURRENT_MEDIA_OFFICE
-} CurrentMediaType;
-
-#include "object.h"
-#include "session.h"
-#include "userlist.h"
-
-/**
- * Contains optional info about a user that is fairly uncommon.  We
- * put this info in in a separate struct to save memory because we
- * allocate an MsnUser struct for each buddy, but we generally only
- * need this information for a small percentage of our buddies
- * (usually less than 1%).  Putting it in a separate struct makes
- * MsnUser smaller by the size of a few pointers.
- */
-typedef struct _MsnUserExtendedInfo
-{
-	CurrentMediaType media_type; /**< Type of the user's current media.   */
-	char *media_title;  /**< Title of the user's current media.  */
-	char *media_artist; /**< Artist of the user's current media. */
-	char *media_album;  /**< Album of the user's current media.  */
-
-	char *phone_home;   /**< E.T. uses this.                     */
-	char *phone_work;   /**< Work phone number.                  */
-	char *phone_mobile; /**< Mobile phone number.                */
-} MsnUserExtendedInfo;
-
-/**
- * A user.
- */
-struct _MsnUser
-{
-	MsnUserList *userlist;
-
-	guint8 refcount;        /**< The reference count of this object */
-
-	char *passport;         /**< The passport account.          */
-	char *friendly_name;    /**< The friendly name.             */
-
-	char *uid;              /*< User ID                         */
-	GSList *endpoints;      /*< Endpoint-specific data          */
-
-	const char *status;     /**< The state of the user.         */
-	char *statusline;       /**< The state of the user.         */
-
-	gboolean idle;          /**< The idle state of the user.    */
-
-	MsnUserExtendedInfo *extinfo; /**< Extended info for the user. */
-
-	gboolean authorized;    /**< Authorized to add this user.   */
-	gboolean mobile;        /**< Signed up with MSN Mobile.     */
-
-	GList *group_ids;       /**< The group IDs.                 */
-	char *pending_group;    /**< A pending group to add.        */
-
-	MsnObject *msnobj;      /**< The user's MSN Object.         */
-
-	GHashTable *clientcaps; /**< The client's capabilities.     */
-
-	guint clientid;         /**< The client's ID                */
-	guint extcaps;			/**< The client's extended capabilities */
-
-	MsnNetwork networkid;   /**< The user's network             */
-
-	MsnListOp list_op;      /**< Which lists the user is in     */
-
-	/**
-	 * The membershipId for this buddy on our pending list.  Sent by
-	 * the contact's server
-	 */
-	guint member_id_on_pending_list;
-
-	char *invite_message;   /**< Invite message of user request */
-};
-
-/**
- * A specific user endpoint.
- */
-typedef struct MsnUserEndpoint {
-	char *id;               /**< The client's endpoint ID          */
-	char *name;             /**< The client's endpoint's name      */
-	int type;               /**< The client's endpoint type        */
-	guint clientid;         /**< The client's ID                   */
-	guint extcaps;          /**< The client's extended capabilites */
-
-} MsnUserEndpoint;
-
-/**************************************************************************
- ** @name User API                                                        *
- **************************************************************************/
-/*@{*/
-
-/**
- * Creates a new user structure.
- *
- * @param session      The MSN session.
- * @param passport     The initial passport.
- * @param stored_name  The initial stored name.
- *
- * @return A new user structure.  It will have a reference count of 1.
- */
-MsnUser *msn_user_new(MsnUserList *userlist, const char *passport,
-					  const char *friendly_name);
-
-/**
- * Increment the reference count.
- *
- * @param user 	The user.
- *
- * @return 		user.
- */
-MsnUser *msn_user_ref(MsnUser *user);
-
-/**
- * Decrement the reference count.  When the count reaches 0 the object is
- * automatically freed.
- *
- * @param user 	The user
- */
-void msn_user_unref(MsnUser *user);
-
-/**
- * Updates the user.
- *
- * Communicates with the core to update the ui, etc.
- *
- * @param user The user to update.
- */
-void msn_user_update(MsnUser *user);
-
- /**
-  *  Sets the new statusline of user.
-  *
-  *  @param user The user.
-  *  @param state The statusline string.
-  */
-void msn_user_set_statusline(MsnUser *user, const char *statusline);
-
-/**
- * Sets the new state of user.
- *
- * @param user The user.
- * @param state The state string.
- */
-void msn_user_set_state(MsnUser *user, const char *state);
-
-/**
- * Sets the passport account for a user.
- *
- * @param user     The user.
- * @param passport The passport account.
- */
-void msn_user_set_passport(MsnUser *user, const char *passport);
-
-/**
- * Sets the friendly name for a user.
- *
- * @param user The user.
- * @param name The friendly name.
- *
- * @returns TRUE is name actually changed, FALSE otherwise.
- */
-gboolean msn_user_set_friendly_name(MsnUser *user, const char *name);
-
-/**
- * Sets the buddy icon for a local user.
- *
- * @param user     The user.
- * @param img      The buddy icon image
- */
-void msn_user_set_buddy_icon(MsnUser *user, PurpleStoredImage *img);
-
-/**
- * Sets the group ID list for a user.
- *
- * @param user The user.
- * @param ids  The group ID list.
- */
-void msn_user_set_group_ids(MsnUser *user, GList *ids);
-
-/**
- * Adds the group ID for a user.
- *
- * @param user The user.
- * @param id   The group ID.
- */
-void msn_user_add_group_id(MsnUser *user, const char * id);
-
-/**
- * Removes the group ID from a user.
- *
- * @param user The user.
- * @param id   The group ID.
- */
-void msn_user_remove_group_id(MsnUser *user, const char * id);
-
-/**
- * Sets the pending group for a user.
- *
- * @param user  The user.
- * @param group The group name.
- */
-void msn_user_set_pending_group(MsnUser *user, const char *group);
-
-/**
- * Removes the pending group from a user.
- *
- * @param user The user.
- *
- * @return Returns the pending group name.
- */
-char *msn_user_remove_pending_group(MsnUser *user);
-
-/**
- * Sets the home phone number for a user.
- *
- * @param user   The user.
- * @param number The home phone number.
- */
-void msn_user_set_home_phone(MsnUser *user, const char *number);
-
-/**
- * Sets the work phone number for a user.
- *
- * @param user   The user.
- * @param number The work phone number.
- */
-void msn_user_set_work_phone(MsnUser *user, const char *number);
-
-void msn_user_set_uid(MsnUser *user, const char *uid);
-
-/**
- * Sets endpoint data for a user.
- *
- * @param user     The user.
- * @param endpoint The endpoint.
- * @param data     The endpoint data.
- */
-void
-msn_user_set_endpoint_data(MsnUser *user, const char *endpoint, MsnUserEndpoint *data);
-
-/**
- * Clears all endpoint data for a user.
- *
- * @param user     The user.
- */
-void
-msn_user_clear_endpoints(MsnUser *user);
-
-/**
- * Sets the client id for a user.
- *
- * @param user     The user.
- * @param clientid The client id.
- */
-void msn_user_set_clientid(MsnUser *user, guint clientid);
-
-/**
- * Sets the client id for a user.
- *
- * @param user     The user.
- * @param extcaps  The client's extended capabilities.
- */
-void msn_user_set_extcaps(MsnUser *user, guint extcaps);
-
-/**
- * Sets the network id for a user.
- *
- * @param user    The user.
- * @param network The network id.
- */
-void msn_user_set_network(MsnUser *user, MsnNetwork network);
-
-/**
- * Sets the mobile phone number for a user.
- *
- * @param user   The user.
- * @param number The mobile phone number.
- */
-void msn_user_set_mobile_phone(MsnUser *user, const char *number);
-
-/**
- * Sets the MSNObject for a user.
- *
- * @param user The user.
- * @param obj  The MSNObject.
- */
-void msn_user_set_object(MsnUser *user, MsnObject *obj);
-
-/**
- * Sets the client information for a user.
- *
- * @param user The user.
- * @param info The client information.
- */
-void msn_user_set_client_caps(MsnUser *user, GHashTable *info);
-
-/**
- * Sets the invite message for a user.
- *
- * @param user    The user.
- * @param message The invite message for a user.
- */
-void msn_user_set_invite_message(MsnUser *user, const char *message);
-
-
-/**
- * Returns the passport account for a user.
- *
- * @param user The user.
- *
- * @return The passport account.
- */
-const char *msn_user_get_passport(const MsnUser *user);
-
-/**
- * Returns the friendly name for a user.
- *
- * @param user The user.
- *
- * @return The friendly name.
- */
-const char *msn_user_get_friendly_name(const MsnUser *user);
-
-/**
- * Returns the home phone number for a user.
- *
- * @param user The user.
- *
- * @return The user's home phone number.
- */
-const char *msn_user_get_home_phone(const MsnUser *user);
-
-/**
- * Returns the work phone number for a user.
- *
- * @param user The user.
- *
- * @return The user's work phone number.
- */
-const char *msn_user_get_work_phone(const MsnUser *user);
-
-/**
- * Returns the mobile phone number for a user.
- *
- * @param user The user.
- *
- * @return The user's mobile phone number.
- */
-const char *msn_user_get_mobile_phone(const MsnUser *user);
-
-/**
- * Gets endpoint data for a user.
- *
- * @param user     The user.
- * @param endpoint The endpoint.
- *
- * @return The user's endpoint data.
- */
-MsnUserEndpoint *
-msn_user_get_endpoint_data(MsnUser *user, const char *endpoint);
-
-/**
- * Returns the client id for a user.
- *
- * @param user    The user.
- *
- * @return The user's client id.
- */
-guint msn_user_get_clientid(const MsnUser *user);
-
-/**
- * Returns the extended capabilities for a user.
- *
- * @param user    The user.
- *
- * @return The user's extended capabilities.
- */
-guint msn_user_get_extcaps(const MsnUser *user);
-
-/**************************************************************************
- * Utility functions
- **************************************************************************/
-
-
-/**
- * Check if the user is part of the group.
- *
- * @param user 		The user we are asking group membership.
- * @param group_id 	The group where the user may be in.
- *
- * @return TRUE if user is part of the group. Otherwise, FALSE.
- */
-gboolean msn_user_is_in_group(MsnUser *user, const char * group_id);
-
-/**
- * Check if user is on list.
- *
- * @param user 		The user we are asking list membership.
- * @param list_id 	The list where the user may be in.
- *
- * @return TRUE if the user is on the list, else FALSE.
- */
-gboolean msn_user_is_in_list(MsnUser *user, MsnListId list_id);
-/**
- * Returns the network id for a user.
- *
- * @param user    The user.
- *
- * @return The user's network id.
- */
-MsnNetwork msn_user_get_network(const MsnUser *user);
-
-/**
- * Returns the MSNObject for a user.
- *
- * @param user The user.
- *
- * @return The MSNObject.
- */
-MsnObject *msn_user_get_object(const MsnUser *user);
-
-/**
- * Returns the client information for a user.
- *
- * @param user The user.
- *
- * @return The client information.
- */
-GHashTable *msn_user_get_client_caps(const MsnUser *user);
-
-/**
- * Returns the invite message for a user.
- *
- * @param user The user.
- *
- * @return The user's invite message.
- */
-const char *msn_user_get_invite_message(const MsnUser *user);
-
-/**
- * check to see if user is online
- */
-gboolean msn_user_is_online(PurpleAccount *account, const char *name);
-
-/**
- * check to see if user is Yahoo User
- */
-gboolean msn_user_is_yahoo(PurpleAccount *account, const char *name);
-
-void msn_user_set_op(MsnUser *user, MsnListOp list_op);
-void msn_user_unset_op(MsnUser *user, MsnListOp list_op);
-
-/**
- * Compare the given passport with the one of the user
- *
- * @param user 	User to compare.
- * @oaran passport 	Passport to compare.
- *
- * @return Zero if the passport match with the one of the user, otherwise
- * a positive integer if the user passport is greather than the one given
- * and a negative integer if it is less.
- */
-int msn_user_passport_cmp(MsnUser *user, const char *passport);
-
-/**
- * Checks whether a user is capable of some task.
- *
- * @param user       The user.
- * @param endpoint   The endpoint. Can be @NULL to check overall capabilities.
- * @param capability The capability (including client version).
- * @param extcap     The extended capability.
- *
- * @return Whether the user supports the capability.
- */
-gboolean
-msn_user_is_capable(MsnUser *user, char *endpoint, guint capability, guint extcap);
-
-/*@}*/
-
-#endif /* MSN_USER_H */
--- a/libpurple/protocols/msn/userlist.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,759 +0,0 @@
-/**
- * @file userlist.c MSN user list support
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-#include "request.h"
-
-#include "msn.h"
-#include "msnutils.h"
-#include "userlist.h"
-
-#include "contact.h"
-
-const char *lists[] = { "FL", "AL", "BL", "RL" };
-
-typedef struct
-{
-	PurpleConnection *gc;
-	char *who;
-	char *friendly;
-
-} MsnPermitAdd;
-
-/**************************************************************************
- * Callbacks
- **************************************************************************/
-static void
-msn_accept_add_cb(gpointer data)
-{
-	MsnPermitAdd *pa = data;
-
-	purple_debug_misc("msn", "Accepted the new buddy: %s\n", pa->who);
-
-	if (PURPLE_CONNECTION_IS_VALID(pa->gc))
-	{
-		MsnSession *session = pa->gc->proto_data;
-		MsnUserList *userlist = session->userlist;
-		PurpleAccount *account = purple_connection_get_account(pa->gc);
-
-		msn_userlist_add_buddy_to_list(userlist, pa->who, MSN_LIST_AL);
-		purple_privacy_deny_remove(account, pa->who, TRUE);
-		purple_privacy_permit_add(account, pa->who, TRUE);
-
-		msn_del_contact_from_list(session, NULL, pa->who, MSN_LIST_PL);
-	}
-
-	g_free(pa->who);
-	g_free(pa->friendly);
-	g_free(pa);
-}
-
-static void
-msn_cancel_add_cb(gpointer data)
-{
-	MsnPermitAdd *pa = data;
-
-	purple_debug_misc("msn", "Denied the new buddy: %s\n", pa->who);
-
-	if (PURPLE_CONNECTION_IS_VALID(pa->gc))
-	{
-		MsnSession *session = pa->gc->proto_data;
-		MsnUserList *userlist = session->userlist;
-		MsnCallbackState *state = msn_callback_state_new(session);
-
-		msn_callback_state_set_action(state, MSN_DENIED_BUDDY);
-
-		msn_userlist_add_buddy_to_list(userlist, pa->who, MSN_LIST_BL);
-		msn_del_contact_from_list(session, state, pa->who, MSN_LIST_PL);
-	}
-
-	g_free(pa->who);
-	g_free(pa->friendly);
-	g_free(pa);
-}
-
-static void
-got_new_entry(PurpleConnection *gc, const char *passport, const char *friendly, const char *message)
-{
-	PurpleAccount *acct;
-	MsnPermitAdd *pa;
-
-	pa = g_new0(MsnPermitAdd, 1);
-	pa->who = g_strdup(passport);
-	pa->friendly = g_strdup(friendly);
-	pa->gc = gc;
-
-	acct = purple_connection_get_account(gc);
-	purple_account_request_authorization(acct, passport, NULL, friendly, message,
-										 purple_find_buddy(acct, passport) != NULL,
-										 msn_accept_add_cb, msn_cancel_add_cb, pa);
-
-}
-
-/**************************************************************************
- * Server functions
- **************************************************************************/
-
-void
-msn_got_lst_user(MsnSession *session, MsnUser *user,
-				 MsnListOp list_op, GSList *group_ids)
-{
-	PurpleConnection *gc;
-	PurpleAccount *account;
-	const char *passport;
-	const char *store;
-	const char *message;
-
-	account = session->account;
-	gc = purple_account_get_connection(account);
-
-	passport = msn_user_get_passport(user);
-	store = msn_user_get_friendly_name(user);
-	message = msn_user_get_invite_message(user);
-
-	msn_user_set_op(user, list_op);
-
-	if (list_op & MSN_LIST_FL_OP)
-	{
-		GSList *c;
-		for (c = group_ids; c != NULL; c = g_slist_next(c))
-		{
-			char *group_id = c->data;
-			msn_user_add_group_id(user, group_id);
-		}
-
-		/* FIXME: It might be a real alias */
-		/* Umm, what? This might fix bug #1385130 */
-		serv_got_alias(gc, passport, store);
-	}
-
-	if (list_op & MSN_LIST_AL_OP)
-	{
-		/* These are users who are allowed to see our status. */
-		purple_privacy_deny_remove(account, passport, TRUE);
-		purple_privacy_permit_add(account, passport, TRUE);
-	}
-
-	if (list_op & MSN_LIST_BL_OP)
-	{
-		/* These are users who are not allowed to see our status. */
-		purple_privacy_permit_remove(account, passport, TRUE);
-		purple_privacy_deny_add(account, passport, TRUE);
-	}
-
-	if (list_op & MSN_LIST_RL_OP)
-	{
-		/* These are users who have us on their buddy list. */
-		/*
-		 * TODO: What is store name set to when this happens?
-		 *       For one of my accounts "something@hotmail.com"
-		 *       the store name was "something."  Maybe we
-		 *       should use the friendly name, instead? --KingAnt
-		 */
-
-		if (!(list_op & (MSN_LIST_AL_OP | MSN_LIST_BL_OP)))
-		{
-/*			got_new_entry(gc, passport, store, NULL); */
-		}
-	}
-
-	if (list_op & MSN_LIST_PL_OP)
-	{
-		user->authorized = TRUE;
-		got_new_entry(gc, passport, store, message);
-	}
-}
-
-/**************************************************************************
- * UserList functions
- **************************************************************************/
-
-MsnUserList*
-msn_userlist_new(MsnSession *session)
-{
-	MsnUserList *userlist;
-
-	userlist = g_new0(MsnUserList, 1);
-
-	userlist->session = session;
-	userlist->buddy_icon_requests = g_queue_new();
-
-	/* buddy_icon_window is the number of allowed simultaneous buddy icon requests.
-	 * XXX With smarter rate limiting code, we could allow more at once... 5 was the limit set when
-	 * we weren't retrieiving any more than 5 per MSN session. */
-	userlist->buddy_icon_window = 1;
-
-	return userlist;
-}
-
-void
-msn_userlist_destroy(MsnUserList *userlist)
-{
-	GList *l;
-
-	/*destroy userlist*/
-	for (l = userlist->users; l != NULL; l = l->next)
-	{
-		msn_user_unref(l->data);
-	}
-	g_list_free(userlist->users);
-
-	/*destroy group list*/
-	for (l = userlist->groups; l != NULL; l = l->next)
-	{
-		msn_group_destroy(l->data);
-	}
-	g_list_free(userlist->groups);
-
-	g_queue_free(userlist->buddy_icon_requests);
-
-	if (userlist->buddy_icon_request_timer)
-		purple_timeout_remove(userlist->buddy_icon_request_timer);
-
-	g_free(userlist);
-}
-
-MsnUser *
-msn_userlist_find_add_user(MsnUserList *userlist, const char *passport, const char *friendly_name)
-{
-	MsnUser *user;
-
-	user = msn_userlist_find_user(userlist, passport);
-	if (user == NULL)
-	{
-		user = msn_user_new(userlist, passport, friendly_name);
-		msn_userlist_add_user(userlist, user);
-		msn_user_unref(user);
-	} else {
-		msn_user_set_friendly_name(user, friendly_name);
-	}
-	return user;
-}
-
-void
-msn_userlist_add_user(MsnUserList *userlist, MsnUser *user)
-{
-	msn_user_ref(user);
-	userlist->users = g_list_prepend(userlist->users, user);
-}
-
-void
-msn_userlist_remove_user(MsnUserList *userlist, MsnUser *user)
-{
-	userlist->users = g_list_remove(userlist->users, user);
-	g_queue_remove(userlist->buddy_icon_requests, user);
-	msn_user_unref(user);
-}
-
-MsnUser *
-msn_userlist_find_user(MsnUserList *userlist, const char *passport)
-{
-	GList *l;
-
-	g_return_val_if_fail(passport != NULL, NULL);
-
-	for (l = userlist->users; l != NULL; l = l->next)
-	{
-		MsnUser *user = (MsnUser *)l->data;
-
-		g_return_val_if_fail(user->passport != NULL, NULL);
-
-		if (!g_ascii_strcasecmp(passport, user->passport)){
-			return user;
-		}
-	}
-
-	return NULL;
-}
-
-MsnUser *
-msn_userlist_find_user_with_id(MsnUserList *userlist, const char *uid)
-{
-	GList *l;
-
-	g_return_val_if_fail(uid != NULL, NULL);
-
-	for (l = userlist->users; l != NULL; l = l->next) {
-		MsnUser *user = (MsnUser *)l->data;
-
-		if (user->uid == NULL) {
-			continue;
-		}
-
-		if ( !g_ascii_strcasecmp(uid, user->uid) ) {
-			return user;
-		}
-	}
-
-	return NULL;
-}
-
-MsnUser *
-msn_userlist_find_user_with_mobile_phone(MsnUserList *userlist, const char *number)
-{
-	GList *l;
-
-	g_return_val_if_fail(number != NULL, NULL);
-
-	for (l = userlist->users; l != NULL; l = l->next) {
-		MsnUser *user = (MsnUser *)l->data;
-		const char *user_number = msn_user_get_mobile_phone(user);
-
-		if (user_number && !g_ascii_strcasecmp(number, user_number))
-			return user;
-	}
-
-	return NULL;
-}
-
-void
-msn_userlist_add_group(MsnUserList *userlist, MsnGroup *group)
-{
-	userlist->groups = g_list_append(userlist->groups, group);
-}
-
-void
-msn_userlist_remove_group(MsnUserList *userlist, MsnGroup *group)
-{
-	userlist->groups = g_list_remove(userlist->groups, group);
-}
-
-MsnGroup *
-msn_userlist_find_group_with_id(MsnUserList *userlist, const char * id)
-{
-	GList *l;
-
-	g_return_val_if_fail(userlist != NULL, NULL);
-	g_return_val_if_fail(id       != NULL, NULL);
-
-	for (l = userlist->groups; l != NULL; l = l->next)
-	{
-		MsnGroup *group = l->data;
-
-		if (!g_ascii_strcasecmp(group->id,id))
-			return group;
-	}
-
-	return NULL;
-}
-
-MsnGroup *
-msn_userlist_find_group_with_name(MsnUserList *userlist, const char *name)
-{
-	GList *l;
-
-	g_return_val_if_fail(userlist != NULL, NULL);
-	g_return_val_if_fail(name     != NULL, NULL);
-
-	for (l = userlist->groups; l != NULL; l = l->next)
-	{
-		MsnGroup *group = l->data;
-
-		if ((group->name != NULL) && !g_ascii_strcasecmp(name, group->name))
-			return group;
-	}
-
-	return NULL;
-}
-
-const char *
-msn_userlist_find_group_id(MsnUserList *userlist, const char *group_name)
-{
-	MsnGroup *group;
-
-	group = msn_userlist_find_group_with_name(userlist, group_name);
-
-	if (group != NULL)
-		return msn_group_get_id(group);
-	else
-		return NULL;
-}
-
-const char *
-msn_userlist_find_group_name(MsnUserList *userlist, const char * group_id)
-{
-	MsnGroup *group;
-
-	group = msn_userlist_find_group_with_id(userlist, group_id);
-
-	if (group != NULL)
-		return msn_group_get_name(group);
-	else
-		return NULL;
-}
-
-void
-msn_userlist_rename_group_id(MsnUserList *userlist, const char * group_id,
-							 const char *new_name)
-{
-	MsnGroup *group;
-
-	group = msn_userlist_find_group_with_id(userlist, group_id);
-
-	if (group != NULL)
-		msn_group_set_name(group, new_name);
-}
-
-void
-msn_userlist_remove_group_id(MsnUserList *userlist, const char * group_id)
-{
-	MsnGroup *group;
-
-	group = msn_userlist_find_group_with_id(userlist, group_id);
-
-	if (group != NULL)
-	{
-		msn_userlist_remove_group(userlist, group);
-		msn_group_destroy(group);
-	}
-}
-
-typedef struct {
-	MsnSession *session;
-	char *uid;
-} MsnUserlistABData;
-
-static void
-userlist_ab_delete_cb(void *data, int choice)
-{
-	MsnUserlistABData *ab = (MsnUserlistABData *)data;
-
-	/* msn_delete_contact(ab->session, ab->uid, (gboolean)choice); */
-
-	g_free(ab->uid);
-	g_free(ab);
-}
-
-void
-msn_userlist_rem_buddy(MsnUserList *userlist, const char *who)
-{
-	MsnUser *user = NULL;
-
-	g_return_if_fail(userlist != NULL);
-	g_return_if_fail(userlist->session != NULL);
-	g_return_if_fail(who != NULL);
-
-	user = msn_userlist_find_user(userlist, who);
-
-	msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_FL);
-
-	/* delete the contact from address book via soap action */
-	if (user != NULL) {
-		if (0 /*not ready yet*/ && userlist->session->passport_info.email_enabled) {
-			MsnUserlistABData *ab = g_new0(MsnUserlistABData, 1);
-			ab->session = userlist->session;
-			ab->uid = g_strdup(user->uid); /* Not necessary? */
-			purple_request_yes_no(userlist->session->account,
-				_("Delete Buddy from Address Book?"),
-				_("Do you want to delete this buddy from your address book as well?"),
-				user->passport, 0, userlist->session->account, user->passport,
-				NULL, ab,
-				G_CALLBACK(userlist_ab_delete_cb), G_CALLBACK(userlist_ab_delete_cb));
-		} else
-			msn_delete_contact(userlist->session, user);
-	}
-}
-
-void
-msn_userlist_rem_buddy_from_list(MsnUserList *userlist, const char *who,
-				 MsnListId list_id)
-{
-	MsnUser *user;
-	const gchar *list;
-	MsnListOp list_op = 1 << list_id;
-
-	user = msn_userlist_find_user(userlist, who);
-
-	g_return_if_fail(user != NULL);
-
-	if ( !msn_user_is_in_list(user, list_id)) {
-		list = lists[list_id];
-		purple_debug_info("msn", "User %s is not in list %s, not removing.\n", who, list);
-		return;
-	}
-
-	msn_user_unset_op(user, list_op);
-
-	msn_notification_rem_buddy_from_list(userlist->session->notification, list_id, user);
-}
-
-/*add buddy*/
-void
-msn_userlist_add_buddy(MsnUserList *userlist, const char *who, const char *group_name)
-{
-	MsnUser *user;
-	MsnCallbackState *state = NULL;
-	const char *group_id = NULL, *new_group_name;
-
-	new_group_name = group_name == NULL ? MSN_INDIVIDUALS_GROUP_NAME : group_name;
-
-	g_return_if_fail(userlist != NULL);
-	g_return_if_fail(userlist->session != NULL);
-
-	purple_debug_info("msn", "Add user: %s to group: %s\n", who, new_group_name);
-
-	if (!msn_email_is_valid(who))
-	{
-		/* only notify the user about problems adding to the friends list
-		 * maybe we should do something else for other lists, but it probably
-		 * won't cause too many problems if we just ignore it */
-
-		char *str = g_strdup_printf(_("Unable to add \"%s\"."), who);
-
-		purple_notify_error(NULL, NULL, str,
-				  _("The username specified is invalid."));
-		g_free(str);
-
-		return;
-	}
-
-	state = msn_callback_state_new(userlist->session);
-	msn_callback_state_set_who(state, who);
-	msn_callback_state_set_new_group_name(state, new_group_name);
-
-	group_id = msn_userlist_find_group_id(userlist, new_group_name);
-
-	if (group_id == NULL)
-	{
-		/* Whoa, we must add that group first. */
-		purple_debug_info("msn", "Adding user %s to a new group, creating group %s first\n", who, new_group_name);
-
-		msn_callback_state_set_action(state, MSN_ADD_BUDDY);
-
-		msn_add_group(userlist->session, state, new_group_name);
-		return;
-	} else {
-		msn_callback_state_set_guid(state, group_id);
-	}
-
-	/* XXX: adding user here may not be correct (should add them in the
- 	 * ACK to the ADL command), but for now we need to make sure they exist
-	 * early enough that the ILN command doesn't screw us up */
-
-	user = msn_userlist_find_add_user(userlist, who, who);
-
-	if ( msn_user_is_in_list(user, MSN_LIST_FL) ) {
-
-		purple_debug_info("msn", "User %s already exists\n", who);
-
-		msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_BL);
-
-		if (msn_user_is_in_group(user, group_id)) {
-			purple_debug_info("msn", "User %s is already in group %s, returning\n", who, new_group_name);
-			msn_callback_state_free(state);
-			return;
-		}
-	}
-
-	purple_debug_info("msn", "Adding user: %s to group id: %s\n", who, group_id);
-
-	msn_callback_state_set_action(state, MSN_ADD_BUDDY);
-
-	/* Add contact in the Contact server with a SOAP request and if
-	   successful, send ADL with MSN_LIST_AL and MSN_LIST_FL and a FQY */
-	msn_add_contact_to_group(userlist->session, state, who, group_id);
-}
-
-void
-msn_userlist_add_buddy_to_list(MsnUserList *userlist, const char *who,
-							MsnListId list_id)
-{
-	MsnUser *user = NULL;
-	const gchar *list;
-	MsnListOp list_op = 1 << list_id;
-
-	g_return_if_fail(userlist != NULL);
-
-	user = msn_userlist_find_add_user(userlist, who, who);
-
-	/* First we're going to check if it's already there. */
-	if (msn_user_is_in_list(user, list_id))
-	{
-		list = lists[list_id];
-		purple_debug_info("msn", "User '%s' is already in list: %s\n", who, list);
-		return;
-	}
-
-	/* XXX: see XXX above, this should really be done when we get the response from
-		the server */
-
-	msn_user_set_op(user, list_op);
-
-	msn_notification_add_buddy_to_list(userlist->session->notification, list_id, user);
-}
-
-gboolean
-msn_userlist_add_buddy_to_group(MsnUserList *userlist, const char *who,
-				const char *group_name)
-{
-	MsnUser *user;
-	gchar * group_id;
-
-	g_return_val_if_fail(userlist != NULL, FALSE);
-	g_return_val_if_fail(group_name != NULL, FALSE);
-	g_return_val_if_fail(who != NULL, FALSE);
-
-	purple_debug_info("msn", "Adding buddy with passport %s to group %s\n", who, group_name);
-
-	if ( (group_id = (gchar *)msn_userlist_find_group_id(userlist, group_name)) == NULL) {
-		purple_debug_error("msn", "Group %s has no guid!\n", group_name);
-		return FALSE;
-	}
-
-	if ( (user = msn_userlist_find_user(userlist, who)) == NULL) {
-		purple_debug_error("msn", "User %s not found!\n", who);
-		return FALSE;
-	}
-
-	msn_user_add_group_id(user, group_id);
-
-	return TRUE;
-}
-
-
-gboolean
-msn_userlist_rem_buddy_from_group(MsnUserList *userlist, const char *who,
-				const char *group_name)
-{
-	const gchar * group_id;
-	MsnUser *user;
-
-	g_return_val_if_fail(userlist != NULL, FALSE);
-	g_return_val_if_fail(group_name != NULL, FALSE);
-	g_return_val_if_fail(who != NULL, FALSE);
-
-	purple_debug_info("msn", "Removing buddy with passport %s from group %s\n", who, group_name);
-
-	if ( (group_id = msn_userlist_find_group_id(userlist, group_name)) == NULL) {
-		purple_debug_error("msn", "Group %s has no guid!\n", group_name);
-		return FALSE;
-	}
-
-	if ( (user = msn_userlist_find_user(userlist, who)) == NULL) {
-		purple_debug_error("msn", "User %s not found!\n", who);
-		return FALSE;
-	}
-
-	msn_user_remove_group_id(user, group_id);
-
-	return TRUE;
-}
-
-void
-msn_userlist_move_buddy(MsnUserList *userlist, const char *who,
-			const char *old_group_name, const char *new_group_name)
-{
-	const char *new_group_id;
-	MsnCallbackState *state;
-
-	g_return_if_fail(userlist != NULL);
-	g_return_if_fail(userlist->session != NULL);
-
-	state = msn_callback_state_new(userlist->session);
-	msn_callback_state_set_who(state, who);
-	msn_callback_state_set_action(state, MSN_MOVE_BUDDY);
-	msn_callback_state_set_old_group_name(state, old_group_name);
-	msn_callback_state_set_new_group_name(state, new_group_name);
-
-	new_group_id = msn_userlist_find_group_id(userlist, new_group_name);
-
-	if (new_group_id == NULL)
-	{
-		msn_add_group(userlist->session, state, new_group_name);
-		return;
-	}
-
-	/* add the contact to the new group, and remove it from the old one in
-	 * the callback
-	*/
-	msn_add_contact_to_group(userlist->session, state, who, new_group_id);
-}
-
-void
-msn_release_buddy_icon_request(MsnUserList *userlist)
-{
-	MsnUser *user;
-
-	g_return_if_fail(userlist != NULL);
-
-	if (purple_debug_is_verbose())
-		purple_debug_info("msn", "Releasing buddy icon request\n");
-
-	if (userlist->buddy_icon_window > 0) {
-		GQueue *queue;
-
-		queue = userlist->buddy_icon_requests;
-
-		if (g_queue_is_empty(userlist->buddy_icon_requests))
-			return;
-
-		user = g_queue_pop_head(queue);
-
-		userlist->buddy_icon_window--;
-
-		msn_request_user_display(user);
-
-		if (purple_debug_is_verbose())
-			purple_debug_info("msn",
-			                  "msn_release_buddy_icon_request(): buddy_icon_window-- yields =%d\n",
-			                  userlist->buddy_icon_window);
-	}
-}
-
-/*load userlist from the Blist file cache*/
-void
-msn_userlist_load(MsnSession *session)
-{
-	PurpleAccount *account = session->account;
-	PurpleConnection *gc = purple_account_get_connection(account);
-	GSList *l;
-	MsnUser * user;
-
-	g_return_if_fail(gc != NULL);
-
-	for (l = purple_find_buddies(account, NULL); l != NULL;
-			l = g_slist_delete_link(l, l)) {
-		PurpleBuddy *buddy = l->data;
-
-		user = msn_userlist_find_add_user(session->userlist,
-			purple_buddy_get_name(buddy), NULL);
-		purple_buddy_set_protocol_data(buddy, user);
-		msn_user_set_op(user, MSN_LIST_FL_OP);
-	}
-	for (l = session->account->permit; l != NULL; l = l->next)
-	{
-		user = msn_userlist_find_add_user(session->userlist,
-						(char *)l->data,NULL);
-		msn_user_set_op(user, MSN_LIST_AL_OP);
-	}
-	for (l = session->account->deny; l != NULL; l = l->next)
-	{
-		user = msn_userlist_find_add_user(session->userlist,
-						(char *)l->data,NULL);
-		msn_user_set_op(user, MSN_LIST_BL_OP);
-	}
-
-}
-
--- a/libpurple/protocols/msn/userlist.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/**
- * @file userlist.h MSN user list support
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef MSN_USERLIST_H
-#define MSN_USERLIST_H
-
-typedef struct _MsnUserList MsnUserList;
-
-typedef enum
-{
-	MSN_LIST_FL, /**< Forward list */
-	MSN_LIST_AL, /**< Allow list */
-	MSN_LIST_BL, /**< Block list */
-	MSN_LIST_RL, /**< Reverse list */
-	MSN_LIST_PL  /**< Pending list */
-} MsnListId;
-
-typedef enum
-{
-	MSN_LIST_FL_OP = 0x01,
-	MSN_LIST_AL_OP = 0x02,
-	MSN_LIST_BL_OP = 0x04,
-	MSN_LIST_RL_OP = 0x08,
-	MSN_LIST_PL_OP = 0x10
-} MsnListOp;
-#define MSN_LIST_OP_MASK	0x07
-
-#include "group.h"
-#include "msn.h"
-#include "user.h"
-
-struct _MsnUserList
-{
-	MsnSession *session;
-
-	GList *users; /* Contains MsnUsers */
-	GList *groups; /* Contains MsnGroups */
-
-	GQueue *buddy_icon_requests;
-	int buddy_icon_window;
-	guint buddy_icon_request_timer;
-
-};
-
-void msn_got_lst_user(MsnSession *session, MsnUser *user,
-					  MsnListOp list_op, GSList *group_ids);
-
-MsnUserList *msn_userlist_new(MsnSession *session);
-void msn_userlist_destroy(MsnUserList *userlist);
-
-void msn_userlist_add_user(MsnUserList *userlist, MsnUser *user);
-void msn_userlist_remove_user(MsnUserList *userlist, MsnUser *user);
-
-MsnUser * msn_userlist_find_user(MsnUserList *userlist, const char *passport);
-MsnUser * msn_userlist_find_add_user(MsnUserList *userlist,
-				const char *passport, const char *friendly_name);
-MsnUser * msn_userlist_find_user_with_id(MsnUserList *userlist, const char *uid);
-MsnUser * msn_userlist_find_user_with_mobile_phone(MsnUserList *userlist, const char *number);
-
-void msn_userlist_add_group(MsnUserList *userlist, MsnGroup *group);
-void msn_userlist_remove_group(MsnUserList *userlist, MsnGroup *group);
-MsnGroup *msn_userlist_find_group_with_id(MsnUserList *userlist, const char *id);
-MsnGroup *msn_userlist_find_group_with_name(MsnUserList *userlist, const char *name);
-const char * msn_userlist_find_group_id(MsnUserList *userlist,
-					const char *group_name);
-const char *msn_userlist_find_group_name(MsnUserList *userlist, const char *group_id);
-void msn_userlist_rename_group_id(MsnUserList *userlist, const char *group_id,
-				  const char *new_name);
-void msn_userlist_remove_group_id(MsnUserList *userlist, const char *group_id);
-
-void msn_userlist_rem_buddy(MsnUserList *userlist, const char *who);
-void msn_userlist_add_buddy(MsnUserList *userlist,
-			    const char *who, const char *group_name);
-void msn_userlist_move_buddy(MsnUserList *userlist, const char *who,
-						    const char *old_group_name,
-						    const char *new_group_name);
-
-gboolean msn_userlist_add_buddy_to_group(MsnUserList *userlist, const char *who,
-					 const char *group_name);
-gboolean msn_userlist_rem_buddy_from_group(MsnUserList *userlist,
-					   const char *who,
-					   const char *group_name);
-
-void msn_userlist_add_buddy_to_list(MsnUserList *userlist, const char *who,
-				    MsnListId list_id);
-void msn_userlist_rem_buddy_from_list(MsnUserList *userlist, const char *who,
-				      MsnListId list_id);
-void msn_release_buddy_icon_request(MsnUserList *userlist);
-
-void msn_userlist_load(MsnSession *session);
-
-#endif /* MSN_USERLIST_H */
--- a/libpurple/protocols/msn/xfer.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,235 +0,0 @@
-/**
- * @file xfer.c MSN File Transfer functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-
-#include "msnutils.h"
-#include "sbconn.h"
-#include "xfer.h"
-
-/**************************************************************************
- * Xfer
- **************************************************************************/
-
-void
-msn_xfer_init(PurpleXfer *xfer)
-{
-	MsnSlpCall *slpcall;
-	/* MsnSlpLink *slplink; */
-	char *content;
-
-	purple_debug_info("msn", "xfer_init\n");
-
-	slpcall = xfer->data;
-
-	/* Send Ok */
-	content = g_strdup_printf("SessionID: %lu\r\n\r\n",
-							  slpcall->session_id);
-
-	msn_slp_send_ok(slpcall, slpcall->branch, "application/x-msnmsgr-sessionreqbody",
-			content);
-
-	g_free(content);
-	msn_slplink_send_queued_slpmsgs(slpcall->slplink);
-}
-
-void
-msn_xfer_cancel(PurpleXfer *xfer)
-{
-	MsnSlpCall *slpcall;
-	char *content;
-
-	g_return_if_fail(xfer != NULL);
-	g_return_if_fail(xfer->data != NULL);
-
-	slpcall = xfer->data;
-
-	if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL)
-	{
-		if (slpcall->started)
-		{
-			msn_slpcall_close(slpcall);
-		}
-		else
-		{
-			content = g_strdup_printf("SessionID: %lu\r\n\r\n",
-									slpcall->session_id);
-
-			msn_slp_send_decline(slpcall, slpcall->branch, "application/x-msnmsgr-sessionreqbody",
-						content);
-
-			g_free(content);
-			msn_slplink_send_queued_slpmsgs(slpcall->slplink);
-
-			if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND)
-				slpcall->wasted = TRUE;
-			else
-				msn_slpcall_destroy(slpcall);
-		}
-	}
-}
-
-gssize
-msn_xfer_write(const guchar *data, gsize len, PurpleXfer *xfer)
-{
-	MsnSlpCall *slpcall;
-
-	g_return_val_if_fail(xfer != NULL, -1);
-	g_return_val_if_fail(data != NULL, -1);
-	g_return_val_if_fail(len > 0, -1);
-
-	g_return_val_if_fail(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND, -1);
-
-	slpcall = xfer->data;
-	/* Not sure I trust it'll be there */
-	g_return_val_if_fail(slpcall != NULL, -1);
-
-	g_return_val_if_fail(slpcall->xfer_msg != NULL, -1);
-
-	slpcall->u.outgoing.len = len;
-	slpcall->u.outgoing.data = data;
-	msn_slplink_send_msgpart(slpcall->slplink, slpcall->xfer_msg);
-
-	return MIN(MSN_SBCONN_MAX_SIZE, len);
-}
-
-gssize
-msn_xfer_read(guchar **data, PurpleXfer *xfer)
-{
-	MsnSlpCall *slpcall;
-	gsize len;
-
-	g_return_val_if_fail(xfer != NULL, -1);
-	g_return_val_if_fail(data != NULL, -1);
-
-	g_return_val_if_fail(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE, -1);
-
-	slpcall = xfer->data;
-	/* Not sure I trust it'll be there */
-	g_return_val_if_fail(slpcall != NULL, -1);
-
-	/* Just pass up the whole GByteArray. We'll make another. */
-	*data = slpcall->u.incoming_data->data;
-	len = slpcall->u.incoming_data->len;
-
-	g_byte_array_free(slpcall->u.incoming_data, FALSE);
-	slpcall->u.incoming_data = g_byte_array_new();
-
-	return len;
-}
-
-void
-msn_xfer_end_cb(MsnSlpCall *slpcall, MsnSession *session)
-{
-	if ((purple_xfer_get_status(slpcall->xfer) != PURPLE_XFER_STATUS_DONE) &&
-		(purple_xfer_get_status(slpcall->xfer) != PURPLE_XFER_STATUS_CANCEL_REMOTE) &&
-		(purple_xfer_get_status(slpcall->xfer) != PURPLE_XFER_STATUS_CANCEL_LOCAL))
-	{
-		purple_xfer_cancel_remote(slpcall->xfer);
-	}
-}
-
-void
-msn_xfer_completed_cb(MsnSlpCall *slpcall, const guchar *body,
-					  gsize size)
-{
-	PurpleXfer *xfer = slpcall->xfer;
-
-	purple_xfer_set_completed(xfer, TRUE);
-	purple_xfer_end(xfer);
-}
-
-gchar *
-msn_file_context_to_wire(MsnFileContext *context)
-{
-	gchar *ret, *tmp;
-
-	tmp = ret = g_new(gchar, MSN_FILE_CONTEXT_SIZE + context->preview_len + 1);
-
-	msn_push32le(tmp, context->length);
-	msn_push32le(tmp, context->version);
-	msn_push64le(tmp, context->file_size);
-	msn_push32le(tmp, context->type);
-	memcpy(tmp, context->file_name, MAX_FILE_NAME_LEN * 2);
-	tmp += MAX_FILE_NAME_LEN * 2;
-	memcpy(tmp, context->unknown1, sizeof(context->unknown1));
-	tmp += sizeof(context->unknown1);
-	msn_push32le(tmp, context->unknown2);
-	if (context->preview) {
-		memcpy(tmp, context->preview, context->preview_len);
-	}
-	tmp[context->preview_len] = '\0';
-
-	return ret;
-}
-
-MsnFileContext *
-msn_file_context_from_wire(const char *buf, gsize len)
-{
-	MsnFileContext *context;
-
-	if (!buf || len < MSN_FILE_CONTEXT_SIZE)
-		return NULL;
-
-	context = g_new(MsnFileContext, 1);
-
-	context->length = msn_pop32le(buf);
-	context->version = msn_pop32le(buf);
-	if (context->version == 2) {
-		/* The length field is broken for this version. No check. */
-		context->length = MSN_FILE_CONTEXT_SIZE;
-	} else if (context->version == 3) {
-		if (context->length != MSN_FILE_CONTEXT_SIZE + 63) {
-			g_free(context);
-			return NULL;
-		} else if (len < MSN_FILE_CONTEXT_SIZE + 63) {
-			g_free(context);
-			return NULL;
-		}
-	} else {
-		purple_debug_warning("msn", "Received MsnFileContext with unknown version: %d\n", context->version);
-		g_free(context);
-		return NULL;
-	}
-
-	context->file_size = msn_pop64le(buf);
-	context->type = msn_pop32le(buf);
-	memcpy(context->file_name, buf, MAX_FILE_NAME_LEN * 2);
-	buf += MAX_FILE_NAME_LEN * 2;
-	memcpy(context->unknown1, buf, sizeof(context->unknown1));
-	buf += sizeof(context->unknown1);
-	context->unknown2 = msn_pop32le(buf);
-
-	if (context->type == 0 && len > context->length) {
-		context->preview_len = len - context->length;
-		context->preview = g_memdup(buf, context->preview_len);
-	} else {
-		context->preview_len = 0;
-		context->preview = NULL;
-	}
-
-	return context;
-}
-
--- a/libpurple/protocols/msn/xfer.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/**
- * @file xfer.h MSN File Transfer functions
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#ifndef MSN_XFER_H
-#define MSN_XFER_H
-
-#include "slpcall.h"
-
-#define MAX_FILE_NAME_LEN 260 /* MAX_PATH in Windows */
-
-/**
- * The context data for a file transfer request
- */
-typedef struct
-{
-	guint32   length;       /*< Length of header */
-	guint32   version;      /*< MSN version */
-	guint64   file_size;    /*< Size of file */
-	guint32   type;         /*< Transfer type */
-	gunichar2 file_name[MAX_FILE_NAME_LEN]; /*< Self-explanatory */
-	gchar     unknown1[30]; /*< Used somehow for background sharing */
-	guint32   unknown2;     /*< Possibly for background sharing as well */
-	gchar     *preview;     /*< File preview data, 96x96 PNG */
-	gsize     preview_len;
-} MsnFileContext;
-
-#define MSN_FILE_CONTEXT_SIZE (4*4 + 1*8 + 2*MAX_FILE_NAME_LEN + 30)
-
-void msn_xfer_init(PurpleXfer *xfer);
-void msn_xfer_cancel(PurpleXfer *xfer);
-
-gssize msn_xfer_write(const guchar *data, gsize len, PurpleXfer *xfer);
-gssize msn_xfer_read(guchar **data, PurpleXfer *xfer);
-
-void msn_xfer_completed_cb(MsnSlpCall *slpcall,
-						   const guchar *body, gsize size);
-void msn_xfer_end_cb(MsnSlpCall *slpcall, MsnSession *session);
-
-gchar *
-msn_file_context_to_wire(MsnFileContext *context);
-
-MsnFileContext *
-msn_file_context_from_wire(const char *buf, gsize len);
-
-#endif /* MSN_XFER_H */
-
--- a/libpurple/protocols/mxit/Makefile.am	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-EXTRA_DIST = \
-	Makefile.mingw
-
-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
-
-MXITSOURCES = \
-	actions.c \
-	actions.h \
-	aes.c \
-	aes.h \
-	chunk.c \
-	chunk.h \
-	cipher.c \
-	cipher.h \
-	filexfer.c \
-	filexfer.h \
-	formcmds.c \
-	formcmds.h \
-	http.c \
-	http.h \
-	login.c \
-	login.h \
-	markup.c \
-	markup.h \
-	multimx.c \
-	multimx.h \
-	mxit.c \
-	mxit.h \
-	profile.c \
-	profile.h \
-	protocol.c \
-	protocol.h \
-	roster.c \
-	roster.h \
-	splashscreen.c \
-	splashscreen.h
-
-
-AM_CFLAGS = $(st)
-
-libmxit_la_LDFLAGS = -module -avoid-version
-
-if STATIC_MXIT
-
-st = -DPURPLE_STATIC_PRPL
-noinst_LTLIBRARIES = libmxit.la
-libmxit_la_SOURCES  = $(MXITSOURCES)
-libmxit_la_CFLAGS   = $(AM_CFLAGS)
-
-else
-
-st =
-pkg_LTLIBRARIES   = libmxit.la
-libmxit_la_SOURCES = $(MXITSOURCES)
-libmxit_la_LIBADD  = $(GLIB_LIBS)
-
-endif
-
-AM_CPPFLAGS = \
-	-I$(top_srcdir)/libpurple \
-	-I$(top_builddir)/libpurple \
-	$(GLIB_CFLAGS) \
-	$(DEBUG_CFLAGS)
--- a/libpurple/protocols/mxit/Makefile.mingw	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-#
-# Makefile.mingw
-#
-# Description: Makefile for win32 (mingw) version of libmxit
-#
-
-PIDGIN_TREE_TOP := ../../..
-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
-
-TARGET = libmxit
-TYPE = PLUGIN
-
-# Static or Plugin...
-ifeq ($(TYPE),STATIC)
-  DEFINES += -DSTATIC
-  DLL_INSTALL_DIR =	$(PURPLE_INSTALL_DIR)
-else
-ifeq ($(TYPE),PLUGIN)
-  DLL_INSTALL_DIR =	$(PURPLE_INSTALL_PLUGINS_DIR)
-endif
-endif
-
-##
-## INCLUDE PATHS
-##
-INCLUDE_PATHS +=	-I. \
-			-I$(GTK_TOP)/include \
-			-I$(GTK_TOP)/include/glib-2.0 \
-			-I$(GTK_TOP)/lib/glib-2.0/include \
-			-I$(PURPLE_TOP) \
-			-I$(PURPLE_TOP)/win32 \
-			-I$(PIDGIN_TREE_TOP)
-
-LIB_PATHS +=		-L$(GTK_TOP)/lib \
-			-L$(PURPLE_TOP)
-
-##
-##  SOURCES, OBJECTS
-##
-C_SRC =			actions.c \
-			aes.c \
-			chunk.c \
-			cipher.c \
-			filexfer.c \
-			formcmds.c \
-			http.c \
-			login.c \
-			markup.c \
-			multimx.c \
-			mxit.c \
-			profile.c \
-			protocol.c \
-			roster.c \
-			splashscreen.c
-
-OBJECTS = $(C_SRC:%.c=%.o)
-
-##
-## LIBRARIES
-##
-LIBS =	\
-			-lglib-2.0 \
-			-lintl \
-			-lws2_32 \
-			-lpurple
-
-include $(PIDGIN_COMMON_RULES)
-
-##
-## TARGET DEFINITIONS
-##
-.PHONY: all install clean
-
-all: $(TARGET).dll
-
-install: all $(DLL_INSTALL_DIR)
-	cp $(TARGET).dll $(DLL_INSTALL_DIR)
-
-$(OBJECTS): $(PURPLE_CONFIG_H)
-
-$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-	$(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
-
-##
-## CLEAN RULES
-##
-clean:
-	rm -f $(OBJECTS)
-	rm -f $(TARGET).dll
-
-include $(PIDGIN_COMMON_TARGETS)
--- a/libpurple/protocols/mxit/actions.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,545 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *					-- handle MXit plugin actions --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include	"internal.h"
-#include	"debug.h"
-#include	"request.h"
-
-#include	"protocol.h"
-#include	"mxit.h"
-#include	"roster.h"
-#include	"actions.h"
-#include	"splashscreen.h"
-#include	"cipher.h"
-#include	"profile.h"
-
-
-/*------------------------------------------------------------------------
- * The user has selected to change their profile.
- *
- *  @param gc		The connection object
- *  @param fields	The fields from the request pop-up
- */
-static void mxit_profile_cb( PurpleConnection* gc, PurpleRequestFields* fields )
-{
-	struct MXitSession*		session	= purple_connection_get_protocol_data( gc );
-	PurpleRequestField*		field	= NULL;
-	const char*				name	= NULL;
-	const char*				bday	= NULL;
-	const char*				err		= NULL;
-	GList*					entry	= NULL;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_profile_cb\n" );
-
-	if ( !PURPLE_CONNECTION_IS_VALID( gc ) ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "Unable to update profile; account offline.\n" );
-		return;
-	}
-
-	/* validate name */
-	name = purple_request_fields_get_string( fields, "name" );
-	if ( ( !name ) || ( strlen( name ) < 3 ) ) {
-		err = _( "The Display Name you entered is invalid." );
-		goto out;
-	}
-
-	/* validate birthdate */
-	bday = purple_request_fields_get_string( fields, "bday" );
-	if ( ( !bday ) || ( strlen( bday ) < 10 ) || ( !validateDate( bday ) ) ) {
-		err = _( "The birthday you entered is invalid. The correct format is: 'YYYY-MM-DD'." );
-		goto out;
-	}
-
-out:
-	if ( !err ) {
-		struct MXitProfile*	profile		= session->profile;
-		GString*			attributes	= g_string_sized_new( 128 );
-		char				attrib[512];
-		unsigned int		acount		= 0;
-
-
-		/* update name */
-		g_strlcpy( profile->nickname, name, sizeof( profile->nickname ) );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_FULLNAME, CP_PROFILE_TYPE_UTF8, profile->nickname );
-		g_string_append( attributes, attrib );
-		acount++;
-
-		/* update birthday */
-		g_strlcpy( profile->birthday, bday, sizeof( profile->birthday ) );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_BIRTHDATE, CP_PROFILE_TYPE_UTF8, profile->birthday );
-		g_string_append( attributes, attrib );
-		acount++;
-
-		/* update gender */
-		profile->male = ( purple_request_fields_get_choice( fields, "male" ) != 0 );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_GENDER, CP_PROFILE_TYPE_BOOL, ( profile->male ) ? "1" : "0" );
-		g_string_append( attributes, attrib );
-		acount++;
-
-		/* update title */
-		name = purple_request_fields_get_string( fields, "title" );
-		if ( !name )
-			profile->title[0] = '\0';
-		else
-			g_strlcpy( profile->title, name, sizeof( profile->title ) );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_TITLE, CP_PROFILE_TYPE_UTF8, profile->title );
-		g_string_append( attributes, attrib );
-		acount++;
-
-		/* update firstname */
-		name = purple_request_fields_get_string( fields, "firstname" );
-		if ( !name )
-			profile->firstname[0] = '\0';
-		else
-			g_strlcpy( profile->firstname, name, sizeof( profile->firstname ) );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_FIRSTNAME, CP_PROFILE_TYPE_UTF8, profile->firstname );
-		g_string_append( attributes, attrib );
-		acount++;
-
-		/* update lastname */
-		name = purple_request_fields_get_string( fields, "lastname" );
-		if ( !name )
-			profile->lastname[0] = '\0';
-		else
-			g_strlcpy( profile->lastname, name, sizeof( profile->lastname ) );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_LASTNAME, CP_PROFILE_TYPE_UTF8, profile->lastname );
-		g_string_append( attributes, attrib );
-		acount++;
-
-		/* update email address */
-		name = purple_request_fields_get_string( fields, "email" );
-		if ( !name )
-			profile->email[0] = '\0';
-		else
-			g_strlcpy( profile->email, name, sizeof( profile->email ) );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_EMAIL, CP_PROFILE_TYPE_UTF8, profile->email );
-		g_string_append( attributes, attrib );
-		acount++;
-
-		/* update mobile number */
-		name = purple_request_fields_get_string( fields, "mobilenumber" );
-		if ( !name )
-			profile->mobilenr[0] = '\0';
-		else
-			g_strlcpy( profile->mobilenr, name, sizeof( profile->mobilenr ) );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_MOBILENR, CP_PROFILE_TYPE_UTF8, profile->mobilenr );
-		g_string_append( attributes, attrib );
-		acount++;
-
-		/* update about me */
-		name = purple_request_fields_get_string( fields, "aboutme" );
-		if ( !name )
-			profile->aboutme[0] = '\0';
-		else
-			g_strlcpy( profile->aboutme, name, sizeof( profile->aboutme ) );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_ABOUTME, CP_PROFILE_TYPE_UTF8, profile->aboutme );
-		g_string_append( attributes, attrib );
-		acount++;
-
-		/* update where am i */
-		name = purple_request_fields_get_string( fields, "whereami" );
-		if ( !name )
-			profile->whereami[0] = '\0';
-		else
-			g_strlcpy( profile->whereami, name, sizeof( profile->whereami ) );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_WHEREAMI, CP_PROFILE_TYPE_UTF8, profile->whereami );
-		g_string_append( attributes, attrib );
-		acount++;
-
-		/* relationship status */
-		field = purple_request_fields_get_field( fields, "relationship" );
-		entry = g_list_first( purple_request_field_list_get_selected( field ) );
-		profile->relationship = atoi( purple_request_field_list_get_data( field, entry->data ) );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%i", CP_PROFILE_RELATIONSHIP, CP_PROFILE_TYPE_SHORT, profile->relationship );
-		g_string_append( attributes, attrib );
-		acount++;
-
-		/* update flags */
-		field = purple_request_fields_get_field( fields, "searchable" );
-		if ( purple_request_field_bool_get_value( field ) )		/* is searchable -> clear not-searchable flag */
-			profile->flags &= ~CP_PROF_NOT_SEARCHABLE;
-		else
-			profile->flags |= CP_PROF_NOT_SEARCHABLE;
-		field = purple_request_fields_get_field( fields, "suggestable" );
-		if ( purple_request_field_bool_get_value( field ) )		/* is suggestable -> clear not-suggestable flag */
-			profile->flags &= ~CP_PROF_NOT_SUGGESTABLE;
-		else
-			profile->flags |= CP_PROF_NOT_SUGGESTABLE;
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%" G_GINT64_FORMAT, CP_PROFILE_FLAGS, CP_PROFILE_TYPE_LONG, profile->flags);
-		g_string_append( attributes, attrib );
-		acount++;
-
-		/* send the profile update to MXit */
-		mxit_send_extprofile_update( session, NULL, acount, attributes->str );
-		g_string_free( attributes, TRUE );
-	}
-	else {
-		/* show error to user */
-		mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Profile Update Error" ), err );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Display and update the user's profile.
- *
- *  @param action	The action object
- */
-static void mxit_profile_action( PurplePluginAction* action )
-{
-	PurpleConnection*			gc		= (PurpleConnection*) action->context;
-	struct MXitSession*			session	= purple_connection_get_protocol_data( gc );
-	struct MXitProfile*			profile	= session->profile;
-
-	PurpleRequestFields*		fields	= NULL;
-	PurpleRequestField*			field	= NULL;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_profile_action\n" );
-
-	/* ensure that we actually have the user's profile information */
-	if ( !profile ) {
-		/* no profile information yet, so we cannot update */
-		mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Profile" ), _( "Your profile information is not yet retrieved. Please try again later." ) );
-		return;
-	}
-
-	fields = purple_request_fields_new();
-
-	/* Public information - what other users can see */
-	{
-		PurpleRequestFieldGroup* public_group = purple_request_field_group_new( "Public information" );
-
-		/* display name */
-		field = purple_request_field_string_new( "name", _( "Display Name" ), profile->nickname, FALSE );
-		purple_request_field_group_add_field( public_group, field );
-
-		/* birthday */
-		field = purple_request_field_string_new( "bday", _( "Birthday" ), profile->birthday, FALSE );
-		purple_request_field_group_add_field( public_group, field );
-		if ( profile->flags & CP_PROF_DOBLOCKED )
-			purple_request_field_string_set_editable( field, FALSE );
-
-		/* gender */
-		field = purple_request_field_choice_new( "male", _( "Gender" ), ( profile->male ) ? 1 : 0 );
-		purple_request_field_choice_add( field, _( "Female" ) );		/* 0 */
-		purple_request_field_choice_add( field, _( "Male" ) );			/* 1 */
-		purple_request_field_group_add_field( public_group, field );
-
-		/* first name */
-		field = purple_request_field_string_new( "firstname", _( "First Name" ), profile->firstname, FALSE );
-		purple_request_field_group_add_field( public_group, field );
-
-		/* last name */
-		field = purple_request_field_string_new( "lastname", _( "Last Name" ), profile->lastname, FALSE );
-		purple_request_field_group_add_field( public_group, field );
-
-		/* about me */
-		field = purple_request_field_string_new( "aboutme", _( "About Me" ), profile->aboutme, FALSE);
-		purple_request_field_group_add_field( public_group, field );
-
-		/* where I live */
-		field = purple_request_field_string_new( "whereami", _( "Where I Live" ), profile->whereami, FALSE);
-		purple_request_field_group_add_field( public_group, field );
-
-		/* relationship status */
-		field = purple_request_field_list_new( "relationship", _( "Relationship Status" ) );
-		purple_request_field_list_set_multi_select( field, FALSE );
-		purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_UNKNOWN ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_UNKNOWN ) );
-		purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_DONTSAY ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_DONTSAY ) );
-		purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_SINGLE ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_SINGLE ) );
-		purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_INVOLVED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_INVOLVED ) );
-		purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_ENGAGED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_ENGAGED ) );
-		purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_MARRIED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_MARRIED ) );
-		purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_COMPLICATED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_COMPLICATED ) );
-		purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_WIDOWED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_WIDOWED ) );
-		purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_SEPARATED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_SEPARATED ) );
-		purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_DIVORCED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_DIVORCED ) );
-		purple_request_field_list_add_selected( field, mxit_relationship_to_name( profile->relationship ) );
-		purple_request_field_group_add_field( public_group, field );
-
-		purple_request_fields_add_group( fields, public_group );
-	}
-
-	/* Private information - what only MXit can see */
-	{
-		PurpleRequestFieldGroup* private_group = purple_request_field_group_new( "Private information" );
-
-		/* title */
-		field = purple_request_field_string_new( "title", _( "Title" ), profile->title, FALSE );
-		purple_request_field_group_add_field( private_group, field );
-
-		/* email */
-		field = purple_request_field_string_new( "email", _( "Email" ), profile->email, FALSE );
-		purple_request_field_group_add_field( private_group, field );
-
-		/* mobile number */
-		field = purple_request_field_string_new( "mobilenumber", _( "Mobile Number" ), profile->mobilenr, FALSE );
-		purple_request_field_group_add_field( private_group, field );
-
-		/* is searchable */
-		field = purple_request_field_bool_new( "searchable", _( "Can be searched" ), ( ( profile->flags & CP_PROF_NOT_SEARCHABLE ) == 0) );
-		purple_request_field_group_add_field( private_group, field );
-
-		/* is suggestable */
-		field = purple_request_field_bool_new( "suggestable", _( "Can be suggested" ), ( ( profile->flags & CP_PROF_NOT_SUGGESTABLE ) == 0 ) );
-		purple_request_field_group_add_field( private_group, field );
-
-		purple_request_fields_add_group( fields, private_group );
-	}
-
-	/* (reference: "libpurple/request.h") */
-	purple_request_fields( gc, _( "Profile" ), _( "Update your MXit Profile" ), NULL, fields, _( "Set" ),
-			G_CALLBACK( mxit_profile_cb ), _( "Cancel" ), NULL, purple_connection_get_account( gc ), NULL, NULL, gc );
-}
-
-
-/*------------------------------------------------------------------------
- * The user has selected to change their PIN.
- *
- *  @param gc		The connection object
- *  @param fields	The fields from the request pop-up
- */
-static void mxit_change_pin_cb( PurpleConnection* gc, PurpleRequestFields* fields )
-{
-	struct MXitSession*		session	= purple_connection_get_protocol_data( gc );
-	const char*				pin		= NULL;
-	const char*				pin2	= NULL;
-	const char*				err		= NULL;
-	int						len;
-	int						i;
-
-	if ( !PURPLE_CONNECTION_IS_VALID( gc ) ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "Unable to update PIN; account offline.\n" );
-		return;
-	}
-
-	/* validate pin */
-	pin = purple_request_fields_get_string( fields, "pin" );
-	if ( !pin ) {
-		err = _( "The PIN you entered is invalid." );
-		goto out;
-	}
-	len = strlen( pin );
-	if ( ( len < 4 ) || ( len > 10 ) ) {
-		err = _( "The PIN you entered has an invalid length [4-10]." );
-		goto out;
-	}
-	for ( i = 0; i < len; i++ ) {
-		if ( !g_ascii_isdigit( pin[i] ) ) {
-			err = _( "The PIN is invalid. It should only consist of digits [0-9]." );
-			goto out;
-		}
-	}
-	pin2 = purple_request_fields_get_string( fields, "pin2" );
-	if ( ( !pin2 ) || ( strcmp( pin, pin2 ) != 0 ) ) {
-		err = _( "The two PINs you entered do not match." );
-		goto out;
-	}
-
-out:
-	if ( !err ) {
-		/* update PIN in account */
-		purple_account_set_password( session->acc, pin );
-
-		/* update session object */
-		g_free( session->encpwd );
-		session->encpwd = mxit_encrypt_password( session );
-
-		/* send the update request to MXit */
-		mxit_send_extprofile_update( session, session->encpwd, 0, NULL );
-	}
-	else {
-		/* show error to user */
-		mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "PIN Update Error" ), err );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Enable the user to change their PIN.
- *
- *  @param action	The action object
- */
-static void mxit_change_pin_action( PurplePluginAction* action )
-{
-	PurpleConnection*			gc		= (PurpleConnection*) action->context;
-	struct MXitSession*			session	= purple_connection_get_protocol_data( gc );
-
-	PurpleRequestFields*		fields	= NULL;
-	PurpleRequestFieldGroup*	group	= NULL;
-	PurpleRequestField*			field	= NULL;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_change_pin_action\n" );
-
-	fields = purple_request_fields_new();
-	group = purple_request_field_group_new( NULL );
-	purple_request_fields_add_group( fields, group );
-
-	/* pin */
-	field = purple_request_field_string_new( "pin", _( "PIN" ), purple_account_get_password( session->acc ), FALSE );
-	purple_request_field_string_set_masked( field, TRUE );
-	purple_request_field_group_add_field( group, field );
-
-	/* verify pin */
-	field = purple_request_field_string_new( "pin2", _( "Verify PIN" ), purple_account_get_password( session->acc ), FALSE );
-	purple_request_field_string_set_masked( field, TRUE );
-	purple_request_field_group_add_field( group, field );
-
-	/* (reference: "libpurple/request.h") */
-	purple_request_fields( gc, _( "Change PIN" ), _( "Change MXit PIN" ), NULL, fields, _( "Set" ),
-			G_CALLBACK( mxit_change_pin_cb ), _( "Cancel" ), NULL, purple_connection_get_account( gc ), NULL, NULL, gc );
-}
-
-
-/*------------------------------------------------------------------------
- * Display the current splash-screen, or a notification pop-up if one is not available.
- *
- *  @param action	The action object
- */
-static void mxit_splash_action( PurplePluginAction* action )
-{
-	PurpleConnection*		gc		= (PurpleConnection*) action->context;
-	struct MXitSession*		session	= purple_connection_get_protocol_data( gc );
-
-	if ( splash_current( session ) != NULL )
-		splash_display( session );
-	else
-		mxit_popup( PURPLE_NOTIFY_MSG_INFO, _( "View Splash" ), _( "There is no splash-screen currently available" ) );
-}
-
-
-/*------------------------------------------------------------------------
- * Display info about the plugin.
- *
- *  @param action	The action object
- */
-static void mxit_about_action( PurplePluginAction* action )
-{
-	char	version[256];
-
-	g_snprintf( version, sizeof( version ),
-											"MXit Client Protocol v%i.%i\n\n"
-											"Author:\nPieter Loubser\n\n"
-											"Contributors:\nAndrew Victor\n\n"
-											"Testers:\nBraeme Le Roux\n\n",
-											( MXIT_CP_PROTO_VESION / 10 ), ( MXIT_CP_PROTO_VESION % 10 ) );
-
-	mxit_popup( PURPLE_NOTIFY_MSG_INFO, _( "About" ), version );
-}
-
-
-/*------------------------------------------------------------------------
- * Request list of suggested friends.
- *
- *  @param action	The action object
- */
-static void mxit_suggested_friends_action( PurplePluginAction* action )
-{
-	PurpleConnection*		gc				= (PurpleConnection*) action->context;
-	struct MXitSession*		session			= purple_connection_get_protocol_data( gc );
-	const char*				profilelist[]	= {
-				CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_FIRSTNAME,
-				CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_STATUS, CP_PROFILE_AVATAR,
-				CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME };
-
-	mxit_send_suggest_friends( session, MXIT_SEARCHRESULTS_MAX, ARRAY_SIZE( profilelist ), profilelist );
-}
-
-
-/*------------------------------------------------------------------------
- * Perform contact search.
- *
- *  @param action	The action object
- */
-static void mxit_user_search_cb( PurpleConnection *gc, const char *input )
-{
-	struct MXitSession*		session			= purple_connection_get_protocol_data( gc );
-	const char*				profilelist[]	= {
-				CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_FIRSTNAME,
-				CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_STATUS, CP_PROFILE_AVATAR,
-				CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME };
-
-	mxit_send_suggest_search( session, MXIT_SEARCHRESULTS_MAX, input, ARRAY_SIZE( profilelist ), profilelist );
-}
-
-
-/*------------------------------------------------------------------------
- * Display the search input form.
- *
- *  @param action	The action object
- */
-static void mxit_user_search_action( PurplePluginAction* action )
-{
-	PurpleConnection*		gc				= (PurpleConnection*) action->context;
-
-	purple_request_input( gc, _( "Search for user" ),
-		_( "Search for a MXit contact" ),
-		_( "Type search information" ),
-		NULL, FALSE, FALSE, NULL,
-		_( "_Search" ), G_CALLBACK( mxit_user_search_cb ),
-		_( "_Cancel" ), NULL,
-		purple_connection_get_account( gc ), NULL, NULL,
-		gc );
-}
-
-
-/*------------------------------------------------------------------------
- * Associate actions with the MXit plugin.
- *
- *  @param plugin	The MXit protocol plugin
- *  @param context	The connection context (if available)
- *  @return			The list of plugin actions
- */
-GList* mxit_actions( PurplePlugin* plugin, gpointer context )
-{
-	PurplePluginAction*		action	= NULL;
-	GList*					m		= NULL;
-
-	/* display / change profile */
-	action = purple_plugin_action_new( _( "Change Profile..." ), mxit_profile_action );
-	m = g_list_append( m, action );
-
-	/* change PIN */
-	action = purple_plugin_action_new( _( "Change PIN..." ), mxit_change_pin_action );
-	m = g_list_append( m, action );
-
-	/* suggested friends */
-	action = purple_plugin_action_new( _( "Suggested friends..." ), mxit_suggested_friends_action );
-	m = g_list_append( m, action );
-
-	/* search for contacts */
-	action = purple_plugin_action_new( _( "Search for contacts..." ), mxit_user_search_action );
-	m = g_list_append( m, action );
-
-	/* display splash-screen */
-	action = purple_plugin_action_new( _( "View Splash..." ), mxit_splash_action );
-	m = g_list_append( m, action );
-
-	/* display plugin version */
-	action = purple_plugin_action_new( _( "About..." ), mxit_about_action );
-	m = g_list_append( m, action );
-
-	return m;
-}
--- a/libpurple/protocols/mxit/actions.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *					-- handle MXit plugin actions --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * 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		_MXIT_ACTIONS_H_
-#define		_MXIT_ACTIONS_H_
-
-
-/* callbacks */
-GList* mxit_actions( PurplePlugin* plugin, gpointer context );
-
-
-#endif		/* _MXIT_ACTIONS_H_ */
--- a/libpurple/protocols/mxit/aes.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,405 +0,0 @@
-
-// advanced encryption standard
-// author: karl malbrain, malbrain@yahoo.com
-
-/*
-This work, including the source code, documentation
-and related data, is placed into the public domain.
-
-The orginal author is Karl Malbrain.
-
-THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
-OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
-MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
-ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
-RESULTING FROM THE USE, MODIFICATION, OR
-REDISTRIBUTION OF THIS SOFTWARE.
-*/
-
-#include <string.h>
-#include <memory.h>
-
-#include "aes.h"
-
-// AES only supports Nb=4
-#define Nb 4			// number of columns in the state & expanded key
-
-#define Nk 4			// number of columns in a key
-#define Nr 10			// number of rounds in encryption
-
-static uchar Sbox[256] = {		// forward s-box
-0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
-0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
-0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
-0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
-0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
-0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
-0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
-0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
-0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
-0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
-0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
-0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
-0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
-0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
-0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
-0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};
-
-static uchar InvSbox[256] = {	// inverse s-box
-0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
-0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
-0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
-0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
-0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
-0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
-0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
-0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
-0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
-0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
-0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
-0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
-0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
-0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
-0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
-0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d};
-
-// combined Xtimes2[Sbox[]]
-static uchar Xtime2Sbox[256] = {
-0xc6, 0xf8, 0xee, 0xf6, 0xff, 0xd6, 0xde, 0x91, 0x60, 0x02, 0xce, 0x56, 0xe7, 0xb5, 0x4d, 0xec, 
-0x8f, 0x1f, 0x89, 0xfa, 0xef, 0xb2, 0x8e, 0xfb, 0x41, 0xb3, 0x5f, 0x45, 0x23, 0x53, 0xe4, 0x9b, 
-0x75, 0xe1, 0x3d, 0x4c, 0x6c, 0x7e, 0xf5, 0x83, 0x68, 0x51, 0xd1, 0xf9, 0xe2, 0xab, 0x62, 0x2a, 
-0x08, 0x95, 0x46, 0x9d, 0x30, 0x37, 0x0a, 0x2f, 0x0e, 0x24, 0x1b, 0xdf, 0xcd, 0x4e, 0x7f, 0xea, 
-0x12, 0x1d, 0x58, 0x34, 0x36, 0xdc, 0xb4, 0x5b, 0xa4, 0x76, 0xb7, 0x7d, 0x52, 0xdd, 0x5e, 0x13, 
-0xa6, 0xb9, 0x00, 0xc1, 0x40, 0xe3, 0x79, 0xb6, 0xd4, 0x8d, 0x67, 0x72, 0x94, 0x98, 0xb0, 0x85, 
-0xbb, 0xc5, 0x4f, 0xed, 0x86, 0x9a, 0x66, 0x11, 0x8a, 0xe9, 0x04, 0xfe, 0xa0, 0x78, 0x25, 0x4b, 
-0xa2, 0x5d, 0x80, 0x05, 0x3f, 0x21, 0x70, 0xf1, 0x63, 0x77, 0xaf, 0x42, 0x20, 0xe5, 0xfd, 0xbf, 
-0x81, 0x18, 0x26, 0xc3, 0xbe, 0x35, 0x88, 0x2e, 0x93, 0x55, 0xfc, 0x7a, 0xc8, 0xba, 0x32, 0xe6, 
-0xc0, 0x19, 0x9e, 0xa3, 0x44, 0x54, 0x3b, 0x0b, 0x8c, 0xc7, 0x6b, 0x28, 0xa7, 0xbc, 0x16, 0xad, 
-0xdb, 0x64, 0x74, 0x14, 0x92, 0x0c, 0x48, 0xb8, 0x9f, 0xbd, 0x43, 0xc4, 0x39, 0x31, 0xd3, 0xf2, 
-0xd5, 0x8b, 0x6e, 0xda, 0x01, 0xb1, 0x9c, 0x49, 0xd8, 0xac, 0xf3, 0xcf, 0xca, 0xf4, 0x47, 0x10, 
-0x6f, 0xf0, 0x4a, 0x5c, 0x38, 0x57, 0x73, 0x97, 0xcb, 0xa1, 0xe8, 0x3e, 0x96, 0x61, 0x0d, 0x0f, 
-0xe0, 0x7c, 0x71, 0xcc, 0x90, 0x06, 0xf7, 0x1c, 0xc2, 0x6a, 0xae, 0x69, 0x17, 0x99, 0x3a, 0x27, 
-0xd9, 0xeb, 0x2b, 0x22, 0xd2, 0xa9, 0x07, 0x33, 0x2d, 0x3c, 0x15, 0xc9, 0x87, 0xaa, 0x50, 0xa5, 
-0x03, 0x59, 0x09, 0x1a, 0x65, 0xd7, 0x84, 0xd0, 0x82, 0x29, 0x5a, 0x1e, 0x7b, 0xa8, 0x6d, 0x2c 
-};
-
-// combined Xtimes3[Sbox[]]
-static uchar Xtime3Sbox[256] = {
-0xa5, 0x84, 0x99, 0x8d, 0x0d, 0xbd, 0xb1, 0x54, 0x50, 0x03, 0xa9, 0x7d, 0x19, 0x62, 0xe6, 0x9a, 
-0x45, 0x9d, 0x40, 0x87, 0x15, 0xeb, 0xc9, 0x0b, 0xec, 0x67, 0xfd, 0xea, 0xbf, 0xf7, 0x96, 0x5b, 
-0xc2, 0x1c, 0xae, 0x6a, 0x5a, 0x41, 0x02, 0x4f, 0x5c, 0xf4, 0x34, 0x08, 0x93, 0x73, 0x53, 0x3f, 
-0x0c, 0x52, 0x65, 0x5e, 0x28, 0xa1, 0x0f, 0xb5, 0x09, 0x36, 0x9b, 0x3d, 0x26, 0x69, 0xcd, 0x9f, 
-0x1b, 0x9e, 0x74, 0x2e, 0x2d, 0xb2, 0xee, 0xfb, 0xf6, 0x4d, 0x61, 0xce, 0x7b, 0x3e, 0x71, 0x97, 
-0xf5, 0x68, 0x00, 0x2c, 0x60, 0x1f, 0xc8, 0xed, 0xbe, 0x46, 0xd9, 0x4b, 0xde, 0xd4, 0xe8, 0x4a, 
-0x6b, 0x2a, 0xe5, 0x16, 0xc5, 0xd7, 0x55, 0x94, 0xcf, 0x10, 0x06, 0x81, 0xf0, 0x44, 0xba, 0xe3, 
-0xf3, 0xfe, 0xc0, 0x8a, 0xad, 0xbc, 0x48, 0x04, 0xdf, 0xc1, 0x75, 0x63, 0x30, 0x1a, 0x0e, 0x6d, 
-0x4c, 0x14, 0x35, 0x2f, 0xe1, 0xa2, 0xcc, 0x39, 0x57, 0xf2, 0x82, 0x47, 0xac, 0xe7, 0x2b, 0x95, 
-0xa0, 0x98, 0xd1, 0x7f, 0x66, 0x7e, 0xab, 0x83, 0xca, 0x29, 0xd3, 0x3c, 0x79, 0xe2, 0x1d, 0x76, 
-0x3b, 0x56, 0x4e, 0x1e, 0xdb, 0x0a, 0x6c, 0xe4, 0x5d, 0x6e, 0xef, 0xa6, 0xa8, 0xa4, 0x37, 0x8b, 
-0x32, 0x43, 0x59, 0xb7, 0x8c, 0x64, 0xd2, 0xe0, 0xb4, 0xfa, 0x07, 0x25, 0xaf, 0x8e, 0xe9, 0x18, 
-0xd5, 0x88, 0x6f, 0x72, 0x24, 0xf1, 0xc7, 0x51, 0x23, 0x7c, 0x9c, 0x21, 0xdd, 0xdc, 0x86, 0x85, 
-0x90, 0x42, 0xc4, 0xaa, 0xd8, 0x05, 0x01, 0x12, 0xa3, 0x5f, 0xf9, 0xd0, 0x91, 0x58, 0x27, 0xb9, 
-0x38, 0x13, 0xb3, 0x33, 0xbb, 0x70, 0x89, 0xa7, 0xb6, 0x22, 0x92, 0x20, 0x49, 0xff, 0x78, 0x7a, 
-0x8f, 0xf8, 0x80, 0x17, 0xda, 0x31, 0xc6, 0xb8, 0xc3, 0xb0, 0x77, 0x11, 0xcb, 0xfc, 0xd6, 0x3a 
-};
-
-// modular multiplication tables
-// based on:
-
-// Xtime2[x] = (x & 0x80 ? 0x1b : 0) ^ (x + x)
-// Xtime3[x] = x^Xtime2[x];
-
-#if	0
-static uchar Xtime2[256] = {
-0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 
-0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 
-0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 
-0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, 
-0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, 
-0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, 
-0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, 
-0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, 
-0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, 
-0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25, 
-0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, 
-0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, 
-0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85, 
-0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, 
-0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, 
-0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5}; 
-#endif
-
-static uchar Xtime9[256] = {
-0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, 
-0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, 
-0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, 
-0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc, 
-0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, 
-0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91, 
-0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a, 
-0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, 
-0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b, 
-0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b, 
-0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, 
-0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, 
-0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed, 
-0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, 
-0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6, 
-0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46};
-
-static uchar XtimeB[256] = {
-0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, 
-0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, 
-0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12, 
-0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2, 
-0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, 
-0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f, 
-0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4, 
-0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, 
-0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e, 
-0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e, 
-0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, 
-0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55, 
-0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, 
-0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, 
-0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13, 
-0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3}; 
-
-static uchar XtimeD[256] = {
-0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, 
-0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, 
-0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0, 
-0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20, 
-0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, 
-0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, 
-0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d, 
-0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, 
-0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, 
-0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, 
-0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, 
-0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa, 
-0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc, 
-0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, 
-0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47, 
-0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97}; 
-
-static uchar XtimeE[256] = {
-0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, 
-0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, 
-0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81, 
-0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61, 
-0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, 
-0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, 
-0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c, 
-0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, 
-0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, 
-0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb, 
-0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, 
-0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, 
-0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6, 
-0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, 
-0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, 
-0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d}; 
-
-// exchanges columns in each of 4 rows
-// row0 - unchanged, row1- shifted left 1, 
-// row2 - shifted left 2 and row3 - shifted left 3
-static void ShiftRows (uchar *state)
-{
-uchar tmp;
-
-	// just substitute row 0
-	state[0] = Sbox[state[0]], state[4] = Sbox[state[4]];
-	state[8] = Sbox[state[8]], state[12] = Sbox[state[12]];
-
-	// rotate row 1
-	tmp = Sbox[state[1]], state[1] = Sbox[state[5]];
-	state[5] = Sbox[state[9]], state[9] = Sbox[state[13]], state[13] = tmp;
-
-	// rotate row 2
-	tmp = Sbox[state[2]], state[2] = Sbox[state[10]], state[10] = tmp;
-	tmp = Sbox[state[6]], state[6] = Sbox[state[14]], state[14] = tmp;
-
-	// rotate row 3
-	tmp = Sbox[state[15]], state[15] = Sbox[state[11]];
-	state[11] = Sbox[state[7]], state[7] = Sbox[state[3]], state[3] = tmp;
-}
-
-// restores columns in each of 4 rows
-// row0 - unchanged, row1- shifted right 1, 
-// row2 - shifted right 2 and row3 - shifted right 3
-static void InvShiftRows (uchar *state)
-{
-uchar tmp;
-
-	// restore row 0
-	state[0] = InvSbox[state[0]], state[4] = InvSbox[state[4]];
-	state[8] = InvSbox[state[8]], state[12] = InvSbox[state[12]];
-
-	// restore row 1
-	tmp = InvSbox[state[13]], state[13] = InvSbox[state[9]];
-	state[9] = InvSbox[state[5]], state[5] = InvSbox[state[1]], state[1] = tmp;
-
-	// restore row 2
-	tmp = InvSbox[state[2]], state[2] = InvSbox[state[10]], state[10] = tmp;
-	tmp = InvSbox[state[6]], state[6] = InvSbox[state[14]], state[14] = tmp;
-
-	// restore row 3
-	tmp = InvSbox[state[3]], state[3] = InvSbox[state[7]];
-	state[7] = InvSbox[state[11]], state[11] = InvSbox[state[15]], state[15] = tmp;
-}
-
-// recombine and mix each row in a column
-static void MixSubColumns (uchar *state)
-{
-uchar tmp[4 * Nb];
-
-	// mixing column 0
-	tmp[0] = Xtime2Sbox[state[0]] ^ Xtime3Sbox[state[5]] ^ Sbox[state[10]] ^ Sbox[state[15]];
-	tmp[1] = Sbox[state[0]] ^ Xtime2Sbox[state[5]] ^ Xtime3Sbox[state[10]] ^ Sbox[state[15]];
-	tmp[2] = Sbox[state[0]] ^ Sbox[state[5]] ^ Xtime2Sbox[state[10]] ^ Xtime3Sbox[state[15]];
-	tmp[3] = Xtime3Sbox[state[0]] ^ Sbox[state[5]] ^ Sbox[state[10]] ^ Xtime2Sbox[state[15]];
-
-	// mixing column 1
-	tmp[4] = Xtime2Sbox[state[4]] ^ Xtime3Sbox[state[9]] ^ Sbox[state[14]] ^ Sbox[state[3]];
-	tmp[5] = Sbox[state[4]] ^ Xtime2Sbox[state[9]] ^ Xtime3Sbox[state[14]] ^ Sbox[state[3]];
-	tmp[6] = Sbox[state[4]] ^ Sbox[state[9]] ^ Xtime2Sbox[state[14]] ^ Xtime3Sbox[state[3]];
-	tmp[7] = Xtime3Sbox[state[4]] ^ Sbox[state[9]] ^ Sbox[state[14]] ^ Xtime2Sbox[state[3]];
-
-	// mixing column 2
-	tmp[8] = Xtime2Sbox[state[8]] ^ Xtime3Sbox[state[13]] ^ Sbox[state[2]] ^ Sbox[state[7]];
-	tmp[9] = Sbox[state[8]] ^ Xtime2Sbox[state[13]] ^ Xtime3Sbox[state[2]] ^ Sbox[state[7]];
-	tmp[10]  = Sbox[state[8]] ^ Sbox[state[13]] ^ Xtime2Sbox[state[2]] ^ Xtime3Sbox[state[7]];
-	tmp[11]  = Xtime3Sbox[state[8]] ^ Sbox[state[13]] ^ Sbox[state[2]] ^ Xtime2Sbox[state[7]];
-
-	// mixing column 3
-	tmp[12] = Xtime2Sbox[state[12]] ^ Xtime3Sbox[state[1]] ^ Sbox[state[6]] ^ Sbox[state[11]];
-	tmp[13] = Sbox[state[12]] ^ Xtime2Sbox[state[1]] ^ Xtime3Sbox[state[6]] ^ Sbox[state[11]];
-	tmp[14] = Sbox[state[12]] ^ Sbox[state[1]] ^ Xtime2Sbox[state[6]] ^ Xtime3Sbox[state[11]];
-	tmp[15] = Xtime3Sbox[state[12]] ^ Sbox[state[1]] ^ Sbox[state[6]] ^ Xtime2Sbox[state[11]];
-
-	memcpy (state, tmp, sizeof(tmp));
-}
-
-// restore and un-mix each row in a column
-static void InvMixSubColumns (uchar *state)
-{
-uchar tmp[4 * Nb];
-int i;
-
-	// restore column 0
-	tmp[0] = XtimeE[state[0]] ^ XtimeB[state[1]] ^ XtimeD[state[2]] ^ Xtime9[state[3]];
-	tmp[5] = Xtime9[state[0]] ^ XtimeE[state[1]] ^ XtimeB[state[2]] ^ XtimeD[state[3]];
-	tmp[10] = XtimeD[state[0]] ^ Xtime9[state[1]] ^ XtimeE[state[2]] ^ XtimeB[state[3]];
-	tmp[15] = XtimeB[state[0]] ^ XtimeD[state[1]] ^ Xtime9[state[2]] ^ XtimeE[state[3]];
-
-	// restore column 1
-	tmp[4] = XtimeE[state[4]] ^ XtimeB[state[5]] ^ XtimeD[state[6]] ^ Xtime9[state[7]];
-	tmp[9] = Xtime9[state[4]] ^ XtimeE[state[5]] ^ XtimeB[state[6]] ^ XtimeD[state[7]];
-	tmp[14] = XtimeD[state[4]] ^ Xtime9[state[5]] ^ XtimeE[state[6]] ^ XtimeB[state[7]];
-	tmp[3] = XtimeB[state[4]] ^ XtimeD[state[5]] ^ Xtime9[state[6]] ^ XtimeE[state[7]];
-
-	// restore column 2
-	tmp[8] = XtimeE[state[8]] ^ XtimeB[state[9]] ^ XtimeD[state[10]] ^ Xtime9[state[11]];
-	tmp[13] = Xtime9[state[8]] ^ XtimeE[state[9]] ^ XtimeB[state[10]] ^ XtimeD[state[11]];
-	tmp[2]  = XtimeD[state[8]] ^ Xtime9[state[9]] ^ XtimeE[state[10]] ^ XtimeB[state[11]];
-	tmp[7]  = XtimeB[state[8]] ^ XtimeD[state[9]] ^ Xtime9[state[10]] ^ XtimeE[state[11]];
-
-	// restore column 3
-	tmp[12] = XtimeE[state[12]] ^ XtimeB[state[13]] ^ XtimeD[state[14]] ^ Xtime9[state[15]];
-	tmp[1] = Xtime9[state[12]] ^ XtimeE[state[13]] ^ XtimeB[state[14]] ^ XtimeD[state[15]];
-	tmp[6] = XtimeD[state[12]] ^ Xtime9[state[13]] ^ XtimeE[state[14]] ^ XtimeB[state[15]];
-	tmp[11] = XtimeB[state[12]] ^ XtimeD[state[13]] ^ Xtime9[state[14]] ^ XtimeE[state[15]];
-
-	for( i=0; i < 4 * Nb; i++ )
-		state[i] = InvSbox[tmp[i]];
-}
-
-// encrypt/decrypt columns of the key
-// n.b. you can replace this with
-//      byte-wise xor if you wish.
-
-static void AddRoundKey (unsigned *state, unsigned *key)
-{
-int idx;
-
-	for( idx = 0; idx < 4; idx++ )
-		state[idx] ^= key[idx];
-}
-
-static uchar Rcon[11] = {
-0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
-
-// produce Nb bytes for each round
-void ExpandKey (uchar *key, uchar *expkey)
-{
-uchar tmp0, tmp1, tmp2, tmp3, tmp4;
-unsigned idx;
-
-	memcpy (expkey, key, Nk * 4);
-
-	for( idx = Nk; idx < Nb * (Nr + 1); idx++ ) {
-		tmp0 = expkey[4*idx - 4];
-		tmp1 = expkey[4*idx - 3];
-		tmp2 = expkey[4*idx - 2];
-		tmp3 = expkey[4*idx - 1];
-		if( !(idx % Nk) ) {
-			tmp4 = tmp3;
-			tmp3 = Sbox[tmp0];
-			tmp0 = Sbox[tmp1] ^ Rcon[idx/Nk];
-			tmp1 = Sbox[tmp2];
-			tmp2 = Sbox[tmp4];
-		} else if( Nk > 6 && idx % Nk == 4 ) {
-			tmp0 = Sbox[tmp0];
-			tmp1 = Sbox[tmp1];
-			tmp2 = Sbox[tmp2];
-			tmp3 = Sbox[tmp3];
-		}
-
-		expkey[4*idx+0] = expkey[4*idx - 4*Nk + 0] ^ tmp0;
-		expkey[4*idx+1] = expkey[4*idx - 4*Nk + 1] ^ tmp1;
-		expkey[4*idx+2] = expkey[4*idx - 4*Nk + 2] ^ tmp2;
-		expkey[4*idx+3] = expkey[4*idx - 4*Nk + 3] ^ tmp3;
-	}
-}
-
-// encrypt one 128 bit block
-void Encrypt (uchar *in, uchar *expkey, uchar *out)
-{
-uchar state[Nb * 4];
-unsigned round;
-
-	memcpy (state, in, Nb * 4);
-	AddRoundKey ((unsigned *)state, (unsigned *)expkey);
-
-	for( round = 1; round < Nr + 1; round++ ) {
-		if( round < Nr )
-			MixSubColumns (state);
-		else
-			ShiftRows (state);
-
-		AddRoundKey ((unsigned *)state, (unsigned *)expkey + round * Nb);
-	}
-
-	memcpy (out, state, sizeof(state));
-}
-
-void Decrypt (uchar *in, uchar *expkey, uchar *out)
-{
-uchar state[Nb * 4];
-unsigned round;
-
-	memcpy (state, in, sizeof(state));
-
-	AddRoundKey ((unsigned *)state, (unsigned *)expkey + Nr * Nb);
-	InvShiftRows(state);
-
-	for( round = Nr; round--; )
-	{
-		AddRoundKey ((unsigned *)state, (unsigned *)expkey + round * Nb);
-		if( round )
-			InvMixSubColumns (state);
-	} 
-
-	memcpy (out, state, sizeof(state));
-}
--- a/libpurple/protocols/mxit/aes.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-// advanced encryption standard
-// author: karl malbrain, malbrain@yahoo.com
-
-/*
-This work, including the source code, documentation
-and related data, is placed into the public domain.
-
-The orginal author is Karl Malbrain.
-
-THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
-OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
-MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
-ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
-RESULTING FROM THE USE, MODIFICATION, OR
-REDISTRIBUTION OF THIS SOFTWARE.
-*/
-
-
-#ifndef		AES_MALBRAIN
-#define		AES_MALBRAIN
-
-
-// AES only supports Nb=4
-#define Nb 4			// number of columns in the state & expanded key
-
-#define Nk 4			// number of columns in a key
-#define Nr 10			// number of rounds in encryption
-
-
-typedef unsigned char uchar;
-
-
-void ExpandKey (uchar *key, uchar *expkey);
-void Encrypt (uchar *in, uchar *expkey, uchar *out);
-void Decrypt (uchar *in, uchar *expkey, uchar *out);
-
-
-#endif		/* AES_MALBRAIN */
-
--- a/libpurple/protocols/mxit/chunk.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,768 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *			-- handle chunked data (multimedia messages) --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include	"internal.h"
-#include	"debug.h"
-
-#include	"protocol.h"
-#include	"mxit.h"
-#include	"chunk.h"
-#include	"filexfer.h"
-
-
-/*========================================================================================================================
- * Data-Type encoding
- */
-
-#if	0
-#include	<byteswap.h>
-#if (__BYTE_ORDER == __BIG_ENDIAN)
-#define SWAP_64(x)  (x)
-#else
-#define SWAP_64(x)  bswap_64(x)
-#endif
-#endif
-
-/*------------------------------------------------------------------------
- * Encode a single byte in the chunked data.
- *
- *  @param chunkdata		The chunked-data buffer
- *  @param value			The byte
- *  @return					The number of bytes added.
- */
-static int add_int8( char* chunkdata, char value )
-{
-	*chunkdata = value;
-
-	return sizeof( char );
-}
-
-/*------------------------------------------------------------------------
- * Encode a 16-bit value in the chunked data.
- *
- *  @param chunkdata		The chunked-data buffer
- *  @param value			The 16-bit value
- *  @return					The number of bytes added.
- */
-static int add_int16( char* chunkdata, short value )
-{
-	value = htons( value );		/* network byte-order */
-	memcpy( chunkdata, &value, sizeof( short ) );
-
-	return sizeof( short );
-}
-
-/*------------------------------------------------------------------------
- * Encode a 32-bit value in the chunked data.
- *
- *  @param chunkdata		The chunked-data buffer
- *  @param value			The 32-bit value
- *  @return					The number of bytes added.
- */
-static int add_int32( char* chunkdata, int value )
-{
-	value = htonl( value );		/* network byte-order */
-	memcpy( chunkdata, &value, sizeof( int ) );
-
-	return sizeof( int );
-}
-
-#if	0
-/*------------------------------------------------------------------------
- * Encode a 64-bit value in the chunked data.
- *
- *  @param chunkdata		The chunked-data buffer
- *  @param value			The 64-bit value
- *  @return					The number of bytes added.
- */
-static int add_int64( char* chunkdata, int64_t value )
-{
-	value = SWAP_64( value );	/* network byte-order */
-	memcpy( chunkdata, &value, sizeof( int64_t ) );
-
-	return sizeof( int64_t );
-}
-#endif
-
-/*------------------------------------------------------------------------
- * Encode a block of data in the chunked data.
- *
- *  @param chunkdata		The chunked-data buffer
- *  @param data				The data to add
- *  @param datalen			The length of the data to add
- *  @return					The number of bytes added.
- */
-static int add_data( char* chunkdata, const char* data, int datalen )
-{
-	memcpy( chunkdata, data, datalen );
-
-	return datalen;
-}
-
-/*------------------------------------------------------------------------
- * Encode a string as UTF-8 in the chunked data.
- *
- *  @param chunkdata		The chunked-data buffer
- *  @param str				The string to encode
- *  @return					The number of bytes in the string
- */
-static int add_utf8_string( char* chunkdata, const char* str )
-{
-	int		pos		= 0;
-	size_t	len		= strlen( str );
-
-	/* utf8 string length [2 bytes] */
-	pos += add_int16( &chunkdata[pos], len );
-
-	/* utf8 string */
-	pos += add_data( &chunkdata[pos], str, len );
-
-	return pos;
-}
-
-
-/*========================================================================================================================
- * Data-Type decoding
- */
-
-/*------------------------------------------------------------------------
- * Extract a single byte from the chunked data.
- *
- *  @param chunkdata		The chunked-data buffer
- *  @param chunklen			The amount of data available in the buffer.
- *  @param value			The byte
- *  @return					The number of bytes extracted.
- */
-static int get_int8( const char* chunkdata, size_t chunklen, char* value )
-{
-	if ( chunklen < sizeof( char ) )
-		return 0;
-
-	*value = *chunkdata;
-
-	return sizeof( char );
-}
-
-/*------------------------------------------------------------------------
- * Extract a 16-bit value from the chunked data.
- *
- *  @param chunkdata		The chunked-data buffer
- *  @param chunklen			The amount of data available in the buffer.
- *  @param value			The 16-bit value
- *  @return					The number of bytes extracted
- */
-static int get_int16( const char* chunkdata, size_t chunklen, unsigned short* value )
-{
-	if ( chunklen < sizeof( short ) )
-		return 0;
-
-	*value = ntohs( *( (const short*) chunkdata ) );	/* host byte-order */
-
-	return sizeof( short );
-}
-
-/*------------------------------------------------------------------------
- * Extract a 32-bit value from the chunked data.
- *
- *  @param chunkdata		The chunked-data buffer
- *  @param chunklen			The amount of data available in the buffer.
- *  @param value			The 32-bit value
- *  @return					The number of bytes extracted
- */
-static int get_int32( const char* chunkdata, size_t chunklen, unsigned int* value )
-{
-	if ( chunklen < sizeof( int ) )
-		return 0;
-
-	*value = ntohl( *( (const int*) chunkdata ) );	/* host byte-order */
-
-	return sizeof( int );
-}
-
-#if	0
-/*------------------------------------------------------------------------
- * Extract a 64-bit value from the chunked data.
- *
- *  @param chunkdata		The chunked-data buffer
- *  @param chunklen			The amount of data available in the buffer.
- *  @param value			The 64-bit value
- *  @return					The number of bytes extracted
- */
-static int get_int64( const char* chunkdata, size_t chunklen, int64_t* value )
-{
-	if ( chunklen < sizeof( int64_t ) )
-		return 0;
-
-	*value = SWAP_64( *( (const int64_t*) chunkdata ) );	/* host byte-order */
-
-	return sizeof( int64_t );
-}
-#endif
-
-/*------------------------------------------------------------------------
- * Copy a block of data from the chunked data.
- *
- *  @param chunkdata		The chunked-data buffer
- *  @param chunklen			The amount of data available in the buffer.
- *  @param dest				Where to store the extract data
- *  @param datalen			The length of the data to extract
- *  @return					The number of bytes extracted
- */
-static int get_data( const char* chunkdata, size_t chunklen, char* dest, size_t datalen )
-{
-	if ( chunklen < datalen )
-		return 0;
-
-	memcpy( dest, chunkdata, datalen );
-
-	return datalen;
-}
-
-/*------------------------------------------------------------------------
- * Extract a UTF-8 encoded string from the chunked data.
- *
- *  @param chunkdata		The chunked-data buffer
- *  @param chunklen			The amount of data available in the buffer.
- *  @param str				A pointer to extracted string.  Must be g_free()'d.
- *  @param maxstrlen		Maximum size of destination buffer.
- *  @return					The number of bytes consumed
- */
-static int get_utf8_string( const char* chunkdata, size_t chunklen, char* str, size_t maxstrlen )
-{
-	size_t			pos = 0;
-	unsigned short	len = 0;
-	size_t			skip = 0;
-
-	/* string length [2 bytes] */
-	pos += get_int16( &chunkdata[pos], chunklen - pos, &len );
-
-	if ( ( len + pos ) > chunklen ) {
-		/* string length is longer than chunk size */
-		return 0;
-	}
-	else if ( len > maxstrlen ) {
-		/* possible buffer overflow */
-		purple_debug_error( MXIT_PLUGIN_ID, "Buffer overflow detected (get_utf8_string)\n" );
-		skip = len - maxstrlen;
-		len = maxstrlen;
-	}
-
-	/* string data */
-	pos += get_data( &chunkdata[pos], chunklen - pos, str, len );
-	str[len] = '\0';		/* terminate string */
-
-	return pos + skip;
-}
-
-
-/*========================================================================================================================
- * Chunked Data encoding
- */
-
-/*------------------------------------------------------------------------
- * Encode a "reject file" chunk.  (Chunk type 7)
- *
- *  @param chunkdata		Chunked-data buffer
- *  @param fileid			A unique ID that identifies this file
- *  @return					The number of bytes encoded in the buffer
- */
-size_t mxit_chunk_create_reject( char* chunkdata, const char* fileid )
-{
-	size_t	pos		= 0;
-
-	/* file id [8 bytes] */
-	pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN );
-
-	/* rejection reason [1 byte] */
-	pos += add_int8( &chunkdata[pos], REJECT_BY_USER );
-
-	/* rejection description [UTF-8 (optional)] */
-	pos += add_utf8_string( &chunkdata[pos], "" );
-
-	return pos;
-}
-
-
-/*------------------------------------------------------------------------
- * Encode a "get file" request chunk.  (Chunk type 8)
- *
- *  @param chunkdata		Chunked-data buffer
- *  @param fileid			A unique ID that identifies this file
- *  @param filesize			The number of bytes to retrieve
- *  @param offset			The start offset in the file
- *  @return					The number of bytes encoded in the buffer
- */
-size_t mxit_chunk_create_get( char* chunkdata, const char* fileid, size_t filesize, size_t offset )
-{
-	size_t	pos		= 0;
-
-	/* file id [8 bytes] */
-	pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN );
-
-	/* offset [4 bytes] */
-	pos += add_int32( &chunkdata[pos], offset );
-
-	/* length [4 bytes] */
-	pos += add_int32( &chunkdata[pos], filesize );
-
-	return pos;
-}
-
-
-/*------------------------------------------------------------------------
- * Encode a "received file" chunk.  (Chunk type 9)
- *
- *  @param chunkdata		Chunked-data buffer
- *  @param fileid			A unique ID that identifies this file
- *  @param status			The status of the file transfer (see chunk.h)
- *  @return					The number of bytes encoded in the buffer
- */
-size_t mxit_chunk_create_received( char* chunkdata, const char* fileid, unsigned char status )
-{
-	size_t	pos		= 0;
-
-	/* file id [8 bytes] */
-	pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN );
-
-	/* status [1 byte] */
-	pos += add_int8( &chunkdata[pos], status );
-
-	return pos;
-}
-
-
-/*------------------------------------------------------------------------
- * Encode a "send file direct" chunk.  (Chunk type 10)
- *
- *  @param chunkdata		Chunked-data buffer
- *  @param username			The username of the recipient
- *  @param filename			The name of the file being sent
- *  @param data				The file contents
- *  @param datalen			The size of the file contents
- *  @return					The number of bytes encoded in the buffer
- */
-size_t mxit_chunk_create_senddirect( char* chunkdata, const char* username, const char* filename, const unsigned char* data, size_t datalen )
-{
-	size_t		pos		= 0;
-	const char*	mime	= NULL;
-
-	/* data length [4 bytes] */
-	pos += add_int32( &chunkdata[pos], datalen );
-
-	/* number of username(s) [2 bytes] */
-	pos += add_int16( &chunkdata[pos], 1 );
-
-	/* username(s) [UTF-8] */
-	pos += add_utf8_string( &chunkdata[pos], username );
-
-	/* filename [UTF-8] */
-	pos += add_utf8_string( &chunkdata[pos], filename );
-
-	/* file mime type [UTF-8] */
-	mime = file_mime_type( filename, (const char*) data, datalen );
-	pos += add_utf8_string( &chunkdata[pos], mime );
-
-	/* human readable description [UTF-8 (optional)] */
-	pos += add_utf8_string( &chunkdata[pos], "" );
-
-	/* crc [4 bytes] (0 = optional) */
-	pos += add_int32( &chunkdata[pos], 0 );
-
-	/* the actual file data */
-	pos += add_data( &chunkdata[pos], (const char *) data, datalen );
-
-	return pos;
-}
-
-
-/*------------------------------------------------------------------------
- * Encode a "set avatar" chunk.  (Chunk type 13)
- *
- *  @param chunkdata		Chunked-data buffer
- *  @param data				The avatar data
- *  @param datalen			The size of the avatar data
- *  @return					The number of bytes encoded in the buffer
- */
-size_t mxit_chunk_create_set_avatar( char* chunkdata, const unsigned char* data, size_t datalen )
-{
-	char	fileid[MXIT_CHUNK_FILEID_LEN];
-	size_t	pos = 0;
-
-	/* id [8 bytes] */
-	memset( &fileid, 0, sizeof( fileid ) );		/* set to 0 for file upload */
-	pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN );
-
-	/* size [4 bytes] */
-	pos += add_int32( &chunkdata[pos], datalen );
-
-	/* crc [4 bytes] (0 = optional) */
-	pos += add_int32( &chunkdata[pos], 0 );
-
-	/* the actual file data */
-	pos += add_data( &chunkdata[pos], (const char *) data, datalen );
-
-	return pos;
-}
-
-
-/*------------------------------------------------------------------------
- * Encode a "get avatar" chunk.  (Chunk type 14)
- *
- *  @param chunkdata		Chunked-data buffer
- *  @param mxitId			The username who's avatar to download
- *  @param avatarId			The Id of the avatar image (as string)
- *  @return					The number of bytes encoded in the buffer
- */
-size_t mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const char* avatarId )
-{
-	size_t	pos = 0;
-
-	/* number of avatars [4 bytes] */
-	pos += add_int32( &chunkdata[pos], 1 );
-
-	/* username [UTF-8] */
-	pos += add_utf8_string( &chunkdata[pos], mxitId );
-
-	/* avatar id [UTF-8] */
-	pos += add_utf8_string( &chunkdata[pos], avatarId );
-
-	/* avatar format [UTF-8] */
-	pos += add_utf8_string( &chunkdata[pos], MXIT_AVATAR_TYPE );
-
-	/* avatar bit depth [1 byte] */
-	pos += add_int8( &chunkdata[pos], MXIT_AVATAR_BITDEPT );
-
-	/* number of sizes [2 bytes] */
-	pos += add_int16( &chunkdata[pos], 1 );
-
-	/* image size [4 bytes] */
-	pos += add_int32( &chunkdata[pos], MXIT_AVATAR_SIZE );
-
-	return pos;
-}
-
-
-/*========================================================================================================================
- * Chunked Data decoding
- */
-
-/*------------------------------------------------------------------------
- * Parse a received "offer file" chunk.  (Chunk 6)
- *
- *  @param chunkdata		Chunked data buffer
- *  @param datalen			The length of the chunked data
- *  @param offer			Decoded offerfile information
- *  @return					TRUE if successfully parsed, otherwise FALSE
- */
-gboolean mxit_chunk_parse_offer( char* chunkdata, size_t datalen, struct offerfile_chunk* offer )
-{
-	size_t pos = 0;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_offer (%zu bytes)\n", datalen );
-
-	memset( offer, 0, sizeof( struct offerfile_chunk ) );
-
-	/* id [8 bytes] */
-	pos += get_data( &chunkdata[pos], datalen - pos, offer->fileid, 8);
-
-	/* from username [UTF-8] */
-	pos += get_utf8_string( &chunkdata[pos], datalen - pos, offer->username, sizeof( offer->username ) );
-	mxit_strip_domain( offer->username );
-
-	/* file size [4 bytes] */
-	pos += get_int32( &chunkdata[pos], datalen - pos, &(offer->filesize) );
-
-	/* filename [UTF-8] */
-	pos += get_utf8_string( &chunkdata[pos], datalen - pos, offer->filename, sizeof( offer->filename ) );
-
-	/* mime type [UTF-8] */
-	pos += get_utf8_string( &chunkdata[pos], datalen - pos, offer->mimetype, sizeof( offer->mimetype ) );
-
-	/* timestamp [8 bytes] */
-	/* not used by libPurple */
-
-	/* file description [UTF-8] */
-	/* not used by libPurple */
-
-	/* file alternative [UTF-8] */
-	/* not used by libPurple */
-
-	/* flags [4 bytes] */
-	/* not used by libPurple */
-
-	return TRUE;
-}
-
-
-/*------------------------------------------------------------------------
- * Parse a received "get file" response chunk.  (Chunk 8)
- *
- *  @param chunkdata		Chunked data buffer
- *  @param datalen			The length of the chunked data
- *  @param offer			Decoded getfile information
- *  @return					TRUE if successfully parsed, otherwise FALSE
- */
-gboolean mxit_chunk_parse_get( char* chunkdata, size_t datalen, struct getfile_chunk* getfile )
-{
-	size_t pos = 0;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_file (%zu bytes)\n", datalen );
-
-	memset( getfile, 0, sizeof( struct getfile_chunk ) );
-
-	/* ensure that the chunk size is atleast the minimum size for a "get file" chunk */
-	if ( datalen < 20 )
-		return FALSE;
-
-	/* id [8 bytes] */
-	pos += get_data( &chunkdata[pos], datalen - pos, getfile->fileid, 8 );
-
-	/* offset [4 bytes] */
-	pos += get_int32( &chunkdata[pos], datalen - pos, &(getfile->offset) );
-
-	/* file length [4 bytes] */
-	pos += get_int32( &chunkdata[pos], datalen - pos, &(getfile->length) );
-
-	/* crc [4 bytes] */
-	pos += get_int32( &chunkdata[pos], datalen - pos, &(getfile->crc) );
-
-	/* check length does not exceed chunked data length */
-	if ( getfile->length > datalen - pos )
-		return FALSE;
-
-	/* file data */
-	if ( getfile->length > 0 )
-		getfile->data = &chunkdata[pos];
-
-	return TRUE;
-}
-
-
-/*------------------------------------------------------------------------
- * Parse a received splash screen chunk.  (Chunk 2)
- *
- *  @param chunkdata		Chunked data buffer
- *  @param datalen			The length of the chunked data
- *  @param splash			Decoded splash image information
- *  @return					TRUE if successfully parsed, otherwise FALSE
- */
-gboolean mxit_chunk_parse_splash( char* chunkdata, size_t datalen, struct splash_chunk* splash )
-{
-	size_t pos = 0;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_splash (%zu bytes)\n", datalen );
-
-	memset( splash, 0, sizeof( struct splash_chunk ) );
-
-	/* ensure that the chunk size is atleast the minimum size for a "splash screen" chunk */
-	if ( datalen < 6 )
-		return FALSE;
-
-	/* anchor [1 byte] */
-	pos += get_int8( &chunkdata[pos], datalen - pos, &(splash->anchor) );
-
-	/* time to show [1 byte] */
-	pos += get_int8( &chunkdata[pos], datalen - pos, &(splash->showtime) );
-
-	/* background color [4 bytes] */
-	pos += get_int32( &chunkdata[pos], datalen - pos, &(splash->bgcolor) );
-
-	/* file data */
-	if ( pos < datalen )
-		splash->data = &chunkdata[pos];
-
-	/* data length */
-	splash->datalen = datalen - pos;
-
-	return TRUE;
-}
-
-
-/*------------------------------------------------------------------------
- * Parse a received "custom resource" chunk.  (Chunk 1)
- *
- *  @param chunkdata		Chunked data buffer
- *  @param datalen			The length of the chunked data
- *  @param offer			Decoded custom resource
- *  @return					TRUE if successfully parsed, otherwise FALSE
- */
-gboolean mxit_chunk_parse_cr( char* chunkdata, size_t datalen, struct cr_chunk* cr )
-{
-	size_t			pos			= 0;
-	unsigned int	chunkslen	= 0;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_cr (%zu bytes)\n", datalen );
-
-	memset( cr, 0, sizeof( struct cr_chunk ) );
-
-	/* id [UTF-8] */
-	pos += get_utf8_string( &chunkdata[pos], datalen - pos, cr->id, sizeof( cr->id ) );
-
-	/* handle [UTF-8] */
-	pos += get_utf8_string( &chunkdata[pos], datalen - pos, cr->handle, sizeof( cr->handle ) );
-
-	/* operation [1 byte] */
-	pos += get_int8( &chunkdata[pos], datalen - pos, &(cr->operation) );
-
-	/* total length of all the chunks that are included [4 bytes] */
-	pos += get_int32( &chunkdata[pos], datalen - pos, &chunkslen );
-
-	/* ensure the chunks size does not exceed the data size */
-	if ( pos + chunkslen > datalen )
-		return FALSE;
-
-	/* parse the resource chunks */
-	while ( chunkslen >= MXIT_CHUNK_HEADER_SIZE ) {
-		gchar*	chunk		= &chunkdata[pos];
-		guint32	chunksize	= chunk_length( chunk );
-
-		/* check chunk size against length of received data */
-		if ( pos + MXIT_CHUNK_HEADER_SIZE + chunksize > datalen )
-			return FALSE;
-
-		switch ( chunk_type( chunk ) ) {
-			case CP_CHUNK_SPLASH :			/* splash image */
-				{
-					struct splash_chunk* splash = g_new0( struct splash_chunk, 1 );
-
-					if ( mxit_chunk_parse_splash( chunk_data( chunk ), chunksize, splash ) )
-						cr->resources = g_list_append( cr->resources, splash );
-					else
-						g_free( splash );
-					break;
-				}
-			case CP_CHUNK_CLICK :			/* splash click */
-				{
-					struct splash_click_chunk* click = g_new0( struct splash_click_chunk, 1 );
-
-					cr->resources = g_list_append( cr->resources, click );
-					break;
-				}
-			default:
-				purple_debug_info( MXIT_PLUGIN_ID, "Unsupported custom resource chunk received (%i)\n", chunk_type( chunk) );
-		}
-
-		/* skip over data to next resource chunk */
-		pos += MXIT_CHUNK_HEADER_SIZE + chunksize;
-		chunkslen -= ( MXIT_CHUNK_HEADER_SIZE + chunksize );
-	}
-
-	return TRUE;
-}
-
-
-/*------------------------------------------------------------------------
- * Parse a received "send file direct" response chunk.  (Chunk 10)
- *
- *  @param chunkdata		Chunked data buffer
- *  @param datalen			The length of the chunked data
- *  @param sendfile			Decoded sendfile information
- *  @return					TRUE if successfully parsed, otherwise FALSE
- */
-gboolean mxit_chunk_parse_sendfile( char* chunkdata, size_t datalen, struct sendfile_chunk* sendfile )
-{
-	size_t			pos		= 0;
-	unsigned short	entries	= 0;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_sendfile (%zu bytes)\n", datalen );
-
-	memset( sendfile, 0, sizeof( struct sendfile_chunk ) );
-
-	/* number of entries [2 bytes] */
-	pos += get_int16( &chunkdata[pos], datalen - pos, &entries );
-
-	if ( entries < 1 )		/* no data */
-		return FALSE;
-
-	/* contactAddress [UTF-8 string] */
-	pos += get_utf8_string( &chunkdata[pos], datalen - pos, sendfile->username, sizeof( sendfile->username ) );
-
-	/* status [4 bytes] */
-	pos += get_int32( &chunkdata[pos], datalen - pos, &(sendfile->status) );
-
-	/* status message [UTF-8 string] */
-	pos += get_utf8_string( &chunkdata[pos], datalen - pos, sendfile->statusmsg, sizeof( sendfile->statusmsg ) );
-
-	return TRUE;
-}
-
-
-/*------------------------------------------------------------------------
- * Parse a received "get avatar" response chunk.  (Chunk 14)
- *
- *  @param chunkdata		Chunked data buffer
- *  @param datalen			The length of the chunked data
- *  @param avatar			Decoded avatar information
- *  @return					TRUE if successfully parsed, otherwise FALSE
- */
-gboolean mxit_chunk_parse_get_avatar( char* chunkdata, size_t datalen, struct getavatar_chunk* avatar )
-{
-	size_t			pos			= 0;
-	unsigned int	numfiles	= 0;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_get_avatar (%zu bytes)\n", datalen );
-
-	memset( avatar, 0, sizeof( struct getavatar_chunk ) );
-
-	/* number of files [4 bytes] */
-	pos += get_int32( &chunkdata[pos], datalen - pos, &numfiles );
-
-	if ( numfiles < 1 )		/* no data */
-		return FALSE;
-
-	/* mxitId [UTF-8 string] */
-	pos += get_utf8_string( &chunkdata[pos], datalen - pos, avatar->mxitid, sizeof( avatar->mxitid ) );
-
-	/* avatar id [UTF-8 string] */
-	pos += get_utf8_string( &chunkdata[pos], datalen - pos, avatar->avatarid, sizeof( avatar->avatarid ) );
-
-	/* format [UTF-8 string] */
-	pos += get_utf8_string( &chunkdata[pos], datalen - pos, avatar->format, sizeof( avatar->format ) );
-
-	/* bit depth [1 byte] */
-	pos += get_int8( &chunkdata[pos], datalen - pos, &(avatar->bitdepth) );
-
-	/* crc [4 bytes] */
-	pos += get_int32( &chunkdata[pos], datalen - pos, &(avatar->crc) );
-
-	/* width [4 bytes] */
-	pos += get_int32( &chunkdata[pos], datalen - pos, &(avatar->width) );
-
-	/* height [4 bytes] */
-	pos += get_int32( &chunkdata[pos], datalen - pos, &(avatar->height) );
-
-	/* file length [4 bytes] */
-	pos += get_int32( &chunkdata[pos], datalen - pos, &(avatar->length) );
-
-	/* check length does not exceed chunked data length */
-	if ( avatar->length > datalen - pos )
-		return FALSE;
-
-	/* file data */
-	if ( avatar->length > 0 )
-		avatar->data = &chunkdata[pos];
-
-	return TRUE;
-}
--- a/libpurple/protocols/mxit/chunk.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,193 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *			-- handle chunked data (multimedia messages) --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * 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		_MXIT_CHUNK_H_
-#define		_MXIT_CHUNK_H_
-
-
-#include	"roster.h"
-
-
-#define		MXIT_CHUNK_FILEID_LEN		8			/* bytes */
-#define		MXIT_CHUNK_HEADER_SIZE		5			/* type (1 byte) + length (4 bytes) */
-
-
-/* Multimedia chunk types */
-#define		CP_CHUNK_NONE				0x00		/* (0) no chunk */
-#define		CP_CHUNK_CUSTOM				0x01		/* (1) custom resource */
-#define		CP_CHUNK_SPLASH				0x02		/* (2) splash image */
-#define		CP_CHUNK_CLICK				0x03		/* (3) splash click through */
-#define		CP_CHUNK_OFFER				0x06		/* (6) offer file */
-#define		CP_CHUNK_REJECT				0x07		/* (7) reject file */
-#define		CP_CHUNK_GET				0x08		/* (8) get file */
-#define		CP_CHUNK_RECEIVED			0x09		/* (9) received file */
-#define		CP_CHUNK_DIRECT_SND			0x0A		/* (10) send file direct */
-#define		CP_CHUNK_DIRECT_FWD			0x0B		/* (11) forward file direct */
-#define		CP_CHUNK_SKIN				0x0C		/* (12) MXit client skin */
-#define		CP_CHUNK_SET_AVATAR			0x0D		/* (13) set avatar */
-#define		CP_CHUNK_GET_AVATAR			0x0E		/* (14) get avatar */
-#define		CP_CHUNK_END				0x7E		/* (126) end */
-#define		CP_CHUNK_EXT				0x7F		/* (127) extended type */
-
-
-/* Custom Resource operations */
-#define		CR_OP_UPDATE				0
-#define		CR_OP_REMOVE				1
-
-/* File Received status */
-#define		RECV_STATUS_SUCCESS			0
-#define		RECV_STATUS_PARSE_FAIL		1
-#define		RECV_STATUS_CANNOT_OPEN		8
-#define		RECV_STATUS_BAD_CRC			9
-#define		RECV_STATUS_BAD_ID			10
-
-/* File Reject status */
-#define		REJECT_BY_USER				1
-#define		REJECT_FILETYPE				2
-#define		REJECT_NO_RESOURCES			3
-#define		REJECT_BAD_RECIPIENT		4
-
-/*
- * Chunk header manipulation functions
- */
-static inline guint chunk_type( gchar* chunkheader )
-{
-	return *chunkheader;
-}
-
-static inline void set_chunk_type( gchar* chunkheader, guint type )
-{
-	*chunkheader = type;
-}
-
-static inline guint32 chunk_length( gchar* chunkheader )
-{
-	guint32 length = *( (const guint32*) &chunkheader[1] );
-	return ntohl( length );
-}
-
-static inline void set_chunk_length( gchar* chunkheader, guint32 size )
-{
-	size = htonl( size );
-	memcpy( &chunkheader[1], &size, sizeof( guint32 ) );
-}
-
-static inline gchar* chunk_data( gchar* chunkheader )
-{
-	return &chunkheader[MXIT_CHUNK_HEADER_SIZE];
-}
-
-/*
- * Offer File chunk (6).
- */
-struct offerfile_chunk {
-	char			fileid[MXIT_CHUNK_FILEID_LEN];
-	char			username[MXIT_CP_MAX_JID_LEN + 1];
-	unsigned int	filesize;
-	char			filename[FILENAME_MAX];
-	char			mimetype[64];
-};
-
-/*
- * Get File chunk (8) response.
- */
-struct getfile_chunk {
-	char			fileid[MXIT_CHUNK_FILEID_LEN];
-	unsigned int	offset;
-	unsigned int	length;
-	unsigned int	crc;
-	char*			data;
-};
-
-/*
- * Custom Resource chunk (1).
- */
-struct cr_chunk {
-	char	id[64];
-	char	handle[64];
-	char	operation;
-	GList*	resources;
-};
-
-/*
- * Splash Image chunk (2)
- */
-struct splash_chunk {
-	char			anchor;
-	char			showtime;
-	unsigned int	bgcolor;
-	char*			data;
-	unsigned int	datalen;
-};
-
-/*
- * Splash Click Through chunk (3)
- */
-struct splash_click_chunk {
-	char	reserved[1];
-};
-
-/*
- * Get Avatar chunk (14) response.
- */
-struct getavatar_chunk {
-	char			mxitid[50];
-	char			avatarid[64];
-	char			format[16];
-	char			bitdepth;
-	unsigned int	crc;
-	unsigned int	width;
-	unsigned int	height;
-	unsigned int	length;
-	char*			data;
-};
-
-/*
- * Send File Direct chunk (10) response.
- */
-struct sendfile_chunk {
-	char			username[MXIT_CP_MAX_JID_LEN + 1];
-	unsigned int	status;
-	char			statusmsg[1024];
-};
-
-/* Encode chunk */
-size_t mxit_chunk_create_senddirect( char* chunkdata, const char* username, const char* filename, const unsigned char* data, size_t datalen );
-size_t mxit_chunk_create_reject( char* chunkdata, const char* fileid );
-size_t mxit_chunk_create_get( char* chunkdata, const char* fileid, size_t filesize, size_t offset );
-size_t mxit_chunk_create_received( char* chunkdata, const char* fileid, unsigned char status );
-size_t mxit_chunk_create_set_avatar( char* chunkdata, const unsigned char* data, size_t datalen );
-size_t mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const char* avatarId );
-
-/* Decode chunk */
-gboolean mxit_chunk_parse_offer( char* chunkdata, size_t datalen, struct offerfile_chunk* offer );
-gboolean mxit_chunk_parse_get( char* chunkdata, size_t datalen, struct getfile_chunk* getfile );
-gboolean mxit_chunk_parse_cr( char* chunkdata, size_t datalen, struct cr_chunk* cr );
-gboolean mxit_chunk_parse_sendfile( char* chunkdata, size_t datalen, struct sendfile_chunk* sendfile );
-gboolean mxit_chunk_parse_get_avatar( char* chunkdata, size_t datalen, struct getavatar_chunk* avatar );
-gboolean mxit_chunk_parse_splash( char* chunkdata, size_t datalen, struct splash_chunk* splash );
-
-#endif		/* _MXIT_CHUNK_H_ */
-
--- a/libpurple/protocols/mxit/cipher.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,245 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *						-- encryption --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include	"internal.h"
-#include	"debug.h"
-
-#include	"mxit.h"
-#include	"cipher.h"
-#include	"aes.h"
-
-
-/* encryption */
-#define		INITIAL_KEY		"6170383452343567"
-#define		SECRET_HEADER	"<mxit/>"
-#define		ENCRYPT_HEADER	"<mxitencrypted ver=\"5.2\"/>"
-
-
-/*------------------------------------------------------------------------
- * Add ISO10126 Padding to the data.
- *
- *  @param data		The data to pad.
- */
-static void padding_add( GString* data )
-{
-	unsigned int blocks = ( data->len / 16 ) + 1;
-	unsigned int padding = ( blocks * 16 ) - data->len;
-
-	g_string_set_size( data, blocks * 16 );
-	data->str[data->len - 1] = padding;
-}
-
-
-/*------------------------------------------------------------------------
- * Remove ISO10126 Padding from the data.
- *
- *  @param data		The data from which to remove padding.
- */
-static void padding_remove( GString* data )
-{
-	unsigned int padding;
-
-	if ( data->len == 0 )
-		return;
-
-	padding = data->str[data->len - 1];
-	g_string_truncate( data, data->len - padding );
-}
-
-
-/*------------------------------------------------------------------------
- * Generate the Transport-Layer crypto key.
- *  (Note: this function is not-thread safe)
- *
- *  @param session	The MXit Session object
- *	@return			The transport-layer crypto key.
- */
-static char* transport_layer_key( struct MXitSession* session )
-{
-	static char	key[16 + 1];
-	const char*	password		= purple_account_get_password( session->acc );
-	int			passlen			= strlen( password );
-
-	/* initialize with initial key */
-	g_strlcpy( key, INITIAL_KEY, sizeof( key ) );
-
-	/* client key (8 bytes) */
-	memcpy( key, session->clientkey, strlen( session->clientkey ) );
-
-	/* add last 8 characters of the PIN (no padding if less characters) */
-	if ( passlen <= 8 )
-		memcpy( key + 8, password, passlen );
-	else
-		memcpy( key + 8, password + ( passlen - 8 ), 8 );
-
-	return key;
-}
-
-
-/*------------------------------------------------------------------------
- * Encrypt the user's cleartext password using the AES 128-bit (ECB)
- *  encryption algorithm.
- *
- *  @param session	The MXit session object
- *  @return			The encrypted & encoded password.  Must be g_free'd when no longer needed.
- */
-char* mxit_encrypt_password( struct MXitSession* session )
-{
-	char			key[16 + 1];
-	char			exkey[512];
-	GString*		pass			= NULL;
-	GString*		encrypted		= NULL;
-	char*			base64;
-	unsigned int	i;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_encrypt_password\n" );
-
-	/* build the AES encryption key */
-	g_strlcpy( key, INITIAL_KEY, sizeof( key ) );
-	memcpy( key, session->clientkey, strlen( session->clientkey ) );
-	ExpandKey( (unsigned char*) key, (unsigned char*) exkey );
-
-	/* build the secret data to be encrypted: SECRET_HEADER + password */
-	pass = g_string_new( SECRET_HEADER );
-	g_string_append( pass, purple_account_get_password( session->acc) );
-	padding_add( pass );		/* add ISO10126 padding */
-
-	/* now encrypt the secret. we encrypt each block separately (ECB mode) */
-	encrypted = g_string_sized_new( pass->len );
-	for ( i = 0; i < pass->len; i += 16 ) {
-		char	block[16];
-
-		Encrypt( (unsigned char*) pass->str + i, (unsigned char*) exkey, (unsigned char*) block );
-		g_string_append_len( encrypted, block, 16 );
-	}
-
-	/* now base64 encode the encrypted password */
-	base64 = purple_base64_encode( (unsigned char*) encrypted->str, encrypted->len );
-	g_string_free( encrypted, TRUE );
-
-	g_string_free( pass, TRUE );
-
-	return base64;
-}
-
-
-/*------------------------------------------------------------------------
- * Decrypt a message using transport-layer encryption.
- *
- *  @param session	The MXit session object
- *	@param message	The encrypted message data (is base64-encoded).
- *  @return			The decrypted message.  Must be g_free'd when no longer needed.
- */
-char* mxit_decrypt_message( struct MXitSession* session, char* message )
-{
-	guchar*			raw_message;
-	gsize			raw_len;
-	char			exkey[512];
-	GString*		decoded		= NULL;
-	unsigned int	i;
-
-	/* remove optional header: <mxitencrypted ver="5.2"/> */
-	if ( strncmp( message, ENCRYPT_HEADER, strlen( ENCRYPT_HEADER ) ) == 0 )
-		message += strlen( ENCRYPT_HEADER );
-
-	/* base64 decode the message */
-	raw_message = purple_base64_decode( message, &raw_len );
-
-	/* AES-encrypted data is always blocks of 16 bytes */
-	if ( ( raw_len == 0 ) || ( raw_len % 16 != 0 ) )
-		return NULL;
-
-	/* build the AES key */
-	ExpandKey( (unsigned char*) transport_layer_key( session ), (unsigned char*) exkey );
-
-	/* AES decrypt each block */
-	decoded = g_string_sized_new( raw_len );
-	for ( i = 0; i < raw_len; i += 16 ) {
-		char	block[16];
-
-		Decrypt( (unsigned char*) raw_message + i, (unsigned char*) exkey, (unsigned char*) block );
-		g_string_append_len( decoded, block, 16 );
-	}
-	g_free( raw_message );
-
-	/* check that the decrypted message starts with header: <mxit/> */
-	if ( strncmp( decoded->str, SECRET_HEADER, strlen( SECRET_HEADER ) != 0 ) ) {
-		g_string_free( decoded, TRUE );
-		return NULL;			/* message could not be decrypted */
-	}
-
-	/* remove ISO10126 padding */
-	padding_remove( decoded );
-
-	/* remove encryption header */
-	g_string_erase( decoded, 0, strlen( SECRET_HEADER ) );
-
-	return g_string_free( decoded, FALSE );
-}
-
-
-/*------------------------------------------------------------------------
- * Encrypt a message using transport-layer encryption.
- *
- *  @param session	The MXit session object
- *	@param message	The message data.
- *  @return			The encrypted message.  Must be g_free'd when no longer needed.
- */
-char* mxit_encrypt_message( struct MXitSession* session, char* message )
-{
-	GString*		raw_message	= NULL;
-	char			exkey[512];
-	GString*		encoded		= NULL;
-	gchar*			base64;
-	unsigned int	i;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "encrypt message: '%s'\n", message );
-
-	/* append encryption header to message data */
-	raw_message = g_string_new( SECRET_HEADER );
-	g_string_append( raw_message, message );
-	padding_add( raw_message );		/* add ISO10126 padding */
-
-	/* build the AES key */
-	ExpandKey( (unsigned char*) transport_layer_key( session ), (unsigned char*) exkey );
-
-	/* AES encrypt each block */
-	encoded = g_string_sized_new( raw_message->len );
-	for ( i = 0; i < raw_message->len; i += 16 ) {
-		char	block[16];
-
-		Encrypt( (unsigned char*) raw_message->str + i, (unsigned char*) exkey, (unsigned char*) block );
-		g_string_append_len( encoded, block, 16 );
-	}
-	g_string_free( raw_message, TRUE );
-
-	/* base64 encode the encrypted message */
-	base64 = purple_base64_encode( (unsigned char *) encoded->str, encoded->len );
-	g_string_free( encoded, TRUE );
-
-	purple_debug_info( MXIT_PLUGIN_ID, "encrypted message: '%s'\n", base64 );
-
-	return base64;
-}
--- a/libpurple/protocols/mxit/cipher.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *						-- encryption --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * 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		_MXIT_CIPHER_H_
-#define		_MXIT_CIPHER_H_
-
-
-struct MXitSession;
-
-
-char* mxit_encrypt_password( struct MXitSession* session );
-
-char* mxit_decrypt_message( struct MXitSession* session, char* message );
-char* mxit_encrypt_message( struct MXitSession* session, char* message );
-
-#endif		/* _MXIT_CIPHER_H_ */
--- a/libpurple/protocols/mxit/filexfer.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,463 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *			-- file transfers (sending and receiving)  --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include	"internal.h"
-#include	"debug.h"
-
-#include	"protocol.h"
-#include	"mxit.h"
-#include	"chunk.h"
-#include	"filexfer.h"
-
-
-#define		MIME_TYPE_OCTETSTREAM		"application/octet-stream"
-
-
-/* supported file mime types */
-static struct mime_type {
-	const char*		magic;
-	const short		magic_len;
-	const char*		mime;
-} const mime_types[] = {
-					/*	magic									length	mime					*/
-	/* images */	{	"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A",		8,		"image/png"				},		/* image png */
-					{	"\xFF\xD8",								2,		"image/jpeg"			},		/* image jpeg */
-					{	"\x3C\x3F\x78\x6D\x6C",					5,		"image/svg+xml"			},		/* image SVGansi */
-					{	"\xEF\xBB\xBF",							3,		"image/svg+xml"			},		/* image SVGutf */
-					{	"\xEF\xBB\xBF",							3,		"image/svg+xml"			},		/* image SVGZ */
-	/* mxit */		{	"\x4d\x58\x4d",							3,		"application/mxit-msgs"	},		/* mxit message */
-					{	"\x4d\x58\x44\x01",						4,		"application/mxit-mood" },		/* mxit mood */
-					{	"\x4d\x58\x45\x01",						4,		"application/mxit-emo"	},		/* mxit emoticon */
-					{	"\x4d\x58\x46\x01",						4,		"application/mxit-emof"	},		/* mxit emoticon frame */
-					{	"\x4d\x58\x53\x01",						4,		"application/mxit-skin"	},		/* mxit skin */
-	/* audio */		{	"\x4d\x54\x68\x64",						4,		"audio/midi"			},		/* audio midi */
-					{	"\x52\x49\x46\x46",						4,		"audio/wav"				},		/* audio wav */
-					{	"\xFF\xF1",								2,		"audio/aac"				},		/* audio aac1 */
-					{	"\xFF\xF9",								2,		"audio/aac"				},		/* audio aac2 */
-					{	"\xFF",									1,		"audio/mp3"				},		/* audio mp3 */
-					{	"\x23\x21\x41\x4D\x52\x0A",				6,		"audio/amr"				},		/* audio AMR */
-					{	"\x23\x21\x41\x4D\x52\x2D\x57\x42",		8,		"audio/amr-wb"			},		/* audio AMR WB */
-					{	"\x00\x00\x00",							3,		"audio/mp4"				},		/* audio mp4 */
-					{	"\x2E\x73\x6E\x64",						4,		"audio/au"				}		/* audio AU */
-};
-
-
-/*------------------------------------------------------------------------
- * Return the MIME type matching the data file.
- *
- *  @param filename		The name of file
- *  @param buf			The data
- *  @param buflen		The length of the data
- *  @return				A MIME type string
- */
-const char* file_mime_type( const char* filename, const char* buf, int buflen )
-{
-	unsigned int	i;
-
-	/* check for matching magic headers */
-	for ( i = 0; i < ARRAY_SIZE( mime_types ); i++ ) {
-
-		if ( buflen < mime_types[i].magic_len )	/* data is shorter than size of magic */
-			continue;
-
-		if ( memcmp( buf, mime_types[i].magic, mime_types[i].magic_len ) == 0 )
-			return mime_types[i].mime;
-	}
-
-	/* we did not find the MIME type, so return the default (application/octet-stream) */
-	return MIME_TYPE_OCTETSTREAM;
-}
-
-
-/*------------------------------------------------------------------------
- * Cleanup and deallocate a MXit file transfer object
- *
- *  @param xfer			The file transfer object
- */
-static void mxit_xfer_free( PurpleXfer* xfer )
-{
-	struct mxitxfer*	mx		= (struct mxitxfer*) xfer->data;;
-
-	if ( mx ) {
-		g_free( mx );
-		xfer->data = NULL;
-	}
-}
-
-
-/*========================================================================================================================
- * File Transfer callbacks
- */
-
-/*------------------------------------------------------------------------
- * Initialise a new file transfer.
- *
- *  @param xfer			The file transfer object
- */
-static void mxit_xfer_init( PurpleXfer* xfer )
-{
-	struct mxitxfer*	mx	= (struct mxitxfer*) xfer->data;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_init\n" );
-
-	if ( purple_xfer_get_type( xfer ) == PURPLE_XFER_SEND ) {
-		/* we are trying to send a file to MXit */
-
-		if ( purple_xfer_get_size( xfer ) > CP_MAX_FILESIZE ) {
-			/* the file is too big */
-			purple_xfer_error( purple_xfer_get_type( xfer ), purple_xfer_get_account( xfer ), purple_xfer_get_remote_user( xfer ), _( "The file you are trying to send is too large!" ) );
-			purple_xfer_cancel_local( xfer );
-			return;
-		}
-
-		/* start the file transfer */
-		purple_xfer_start( xfer, -1, NULL, 0 );
-	}
-	else {
-		/*
-		 * we have just accepted a file transfer request from MXit.  send a confirmation
-		 * to the MXit server so that can send us the file
-		 */
-		mxit_send_file_accept( mx->session, mx->fileid, purple_xfer_get_size( xfer ), 0 );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Start the file transfer.
- *
- *  @param xfer			The file transfer object
- */
-static void mxit_xfer_start( PurpleXfer* xfer )
-{
-	goffset			filesize;
-	unsigned char*	buffer;
-	int				wrote;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_start\n" );
-
-	if ( purple_xfer_get_type( xfer ) == PURPLE_XFER_SEND ) {
-		/*
-		 * the user wants to send a file to one of his contacts. we need to create
-		 * a buffer and copy the file data into memory and then we can send it to
-		 * the contact. we will send the whole file with one go.
-		 */
-		filesize = purple_xfer_get_bytes_remaining( xfer );
-		buffer = g_malloc( filesize );
-
-		if (fread(buffer, filesize, 1, xfer->dest_fp) == 1) {
-			/* send data */
-			wrote = purple_xfer_write( xfer, buffer, filesize );
-			if ( wrote > 0 )
-				purple_xfer_set_bytes_sent( xfer, wrote );
-		} else {
-			/* file read error */
-			purple_xfer_error( purple_xfer_get_type( xfer ), purple_xfer_get_account( xfer ), purple_xfer_get_remote_user( xfer ), _( "Unable to access the local file" ) );
-			purple_xfer_cancel_local( xfer );
-		}
-
-		/* free the buffer */
-		g_free( buffer );
-		buffer = NULL;
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * The file transfer has ended.
- *
- *  @param xfer			The file transfer object
- */
-static void mxit_xfer_end( PurpleXfer* xfer )
-{
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_end\n" );
-
-	/* deallocate object */
-	mxit_xfer_free( xfer );
-}
-
-
-/*------------------------------------------------------------------------
- * The file transfer (to a user) has been cancelled.
- *
- *  @param xfer			The file transfer object
- */
-static void mxit_xfer_cancel_send( PurpleXfer* xfer )
-{
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_cancel_send\n" );
-
-	/* deallocate object */
-	mxit_xfer_free( xfer );
-}
-
-
-/*------------------------------------------------------------------------
- * Send the file data.
- *
- *  @param buffer		The data to sent
- *  @param size			The length of the data to send
- *  @param xfer			The file transfer object
- *  @return				The amount of data actually sent
- */
-static gssize mxit_xfer_write( const guchar* buffer, size_t size, PurpleXfer* xfer )
-{
-	struct mxitxfer*	mx	= (struct mxitxfer*) xfer->data;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_write\n" );
-
-	if ( !mx ) {
-		purple_debug_warning( MXIT_PLUGIN_ID, "mxit_xfer_write: invalid internal mxit xfer data\n" );
-		return -1;
-	}
-	else if ( purple_xfer_get_type( xfer ) != PURPLE_XFER_SEND ) {
-		purple_debug_warning( MXIT_PLUGIN_ID, "mxit_xfer_write: wrong xfer type received\n" );
-		return -1;
-	}
-
-	/* create and send the packet to MXit */
-	mxit_send_file( mx->session, purple_xfer_get_remote_user( xfer ), purple_xfer_get_filename( xfer ), buffer, size );
-
-	/* the transfer is complete */
-	purple_xfer_set_completed( xfer, TRUE );
-
-	return size;
-}
-
-
-/*------------------------------------------------------------------------
- * The user has rejected a file offer from MXit.
- *
- *  @param xfer			The file transfer object
- */
-static void mxit_xfer_request_denied( PurpleXfer* xfer )
-{
-	struct mxitxfer*	mx		= (struct mxitxfer*) xfer->data;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_request_denied\n" );
-
-	/* send file reject packet to MXit server */
-	mxit_send_file_reject( mx->session, mx->fileid );
-
-	/* deallocate object */
-	mxit_xfer_free( xfer );
-}
-
-
-/*------------------------------------------------------------------------
- * The file transfer (from MXit) has been cancelled.
- */
-static void mxit_xfer_cancel_recv( PurpleXfer* xfer )
-{
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_cancel_recv\n" );
-
-	/* deallocate object */
-	mxit_xfer_free( xfer );
-}
-
-
-/*========================================================================================================================
- * Callbacks from libPurple
- */
-
-/*------------------------------------------------------------------------
- * Indicate if file transfers are supported to this contact.
- * For MXit file transfers are always supported.
- *
- *  @param gc			The connection object
- *  @param who			The username of the contact
- *  @return				TRUE if file transfers are supported
- */
-gboolean mxit_xfer_enabled( PurpleConnection* gc, const char* who )
-{
-	return TRUE;
-}
-
-
-/*------------------------------------------------------------------------
- * Create and initialize a new file transfer to a contact.
- *
- *  @param gc			The connection object
- *  @param who			The username of the recipient
- */
-PurpleXfer* mxit_xfer_new( PurpleConnection* gc, const char* who )
-{
-	struct MXitSession*	session	= purple_connection_get_protocol_data( gc );
-	PurpleXfer*			xfer	= NULL;
-	struct mxitxfer*	mx		= NULL;
-
-	/* (reference: "libpurple/ft.h") */
-	xfer = purple_xfer_new( session->acc, PURPLE_XFER_SEND, who );
-
-	/* create file info and attach it to the file transfer */
-	mx = g_new0( struct mxitxfer, 1 );
-	mx->session = session;
-	xfer->data = mx;
-
-	/* configure callbacks (reference: "libpurple/ft.h") */
-	purple_xfer_set_init_fnc( xfer, mxit_xfer_init );
-	purple_xfer_set_start_fnc( xfer, mxit_xfer_start );
-	purple_xfer_set_end_fnc( xfer, mxit_xfer_end );
-	purple_xfer_set_cancel_send_fnc( xfer, mxit_xfer_cancel_send );
-	purple_xfer_set_write_fnc( xfer, mxit_xfer_write );
-
-	return xfer;
-}
-
-
-/*------------------------------------------------------------------------
- * The user has initiated a file transfer to a contact.
- *
- *  @param gc			The connection object
- *  @param who			The username of the contact
- *  @param filename		The filename (is NULL if request has not been accepted yet)
- */
-void mxit_xfer_tx( PurpleConnection* gc, const char* who, const char* filename )
-{
-	PurpleXfer	*xfer	= mxit_xfer_new( gc, who );
-
-	if ( filename )
-		purple_xfer_request_accepted( xfer, filename );
-	else
-		purple_xfer_request( xfer );
-}
-
-
-/*========================================================================================================================
- * Calls from the MXit Protocol layer
- */
-
-/*------------------------------------------------------------------------
- * A file transfer offer has been received from the MXit server.
- *
- *  @param session		The MXit session object
- *  @param usermame		The username of the sender
- *  @param filename		The name of the file being offered
- *  @param filesize		The size of the file being offered
- *  @param fileid		A unique ID that identifies this file
- */
-void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, const char* filename, unsigned int filesize, const char* fileid )
-{
-	PurpleXfer*			xfer	= NULL;
-	struct mxitxfer*	mx		= NULL;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "File Offer: file=%s, from=%s, size=%i\n", filename, username, filesize );
-
-	xfer = purple_xfer_new( session->acc, PURPLE_XFER_RECEIVE, username );
-	if ( xfer ) {
-		/* create a new mxit xfer struct for internal use */
-		mx = g_new0( struct mxitxfer, 1 );
-		mx->session = session;
-		memcpy( mx->fileid, fileid, MXIT_CHUNK_FILEID_LEN );
-		xfer->data = mx;
-
-		purple_xfer_set_filename( xfer, filename );
-		if ( filesize > 0 )
-			purple_xfer_set_size( xfer, filesize );
-
-		/* register file transfer callback functions */
-		purple_xfer_set_init_fnc( xfer, mxit_xfer_init );
-		purple_xfer_set_request_denied_fnc( xfer, mxit_xfer_request_denied );
-		purple_xfer_set_cancel_recv_fnc( xfer, mxit_xfer_cancel_recv );
-		purple_xfer_set_end_fnc( xfer, mxit_xfer_end );
-
-		/* give the request to the user to accept/deny */
-		purple_xfer_request( xfer );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Return the libPurple file-transfer object associated with a MXit transfer
- *
- *  @param session		The MXit session object
- *  @param fileid		A unique ID that identifies this file
- */
-static PurpleXfer* find_mxit_xfer( struct MXitSession* session, const char* fileid )
-{
-	GList*		item	= NULL;
-	PurpleXfer*	xfer	= NULL;
-
-	item = purple_xfers_get_all();		/* list of all active transfers */
-	while ( item ) {
-		xfer = item->data;
-
-		if ( purple_xfer_get_account( xfer ) == session->acc ) {
-			/* transfer is associated with this MXit account */
-			struct mxitxfer* mx	= xfer->data;
-
-			/* does the fileid match? */
-			if ( ( mx ) && ( memcmp( mx->fileid, fileid, MXIT_CHUNK_FILEID_LEN ) == 0 ) )
-				break;
-		}
-
-		item = g_list_next( item );
-	}
-
-	if ( item )
-		return item->data;
-	else
-		return NULL;
-}
-
-/*------------------------------------------------------------------------
- * A file has been received from the MXit server.
- *
- *  @param session		The	MXit session object
- *  @param fileid		A unique ID that identifies this file
- *  @param data			The file data
- *  @param datalen		The size of the data
- */
-void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, unsigned int datalen )
-{
-	PurpleXfer*			xfer	= NULL;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_rx_file: (size=%i)\n", datalen );
-
-	/* find the file-transfer object */
-	xfer = find_mxit_xfer( session, fileid );
-	if ( xfer ) {
-		/* this is the transfer we have been looking for */
-		purple_xfer_ref( xfer );
-		purple_xfer_start( xfer, -1, NULL, 0 );
-
-		if ( fwrite( data, datalen, 1, xfer->dest_fp ) > 0 ) {
-			purple_xfer_unref( xfer );
-			purple_xfer_set_completed( xfer, TRUE );
-			purple_xfer_end( xfer );
-
-			/* inform MXit that file was successfully received */
-			mxit_send_file_received( session, fileid, RECV_STATUS_SUCCESS );
-		}
-		else {
-			/* file write error */
-			purple_xfer_error( purple_xfer_get_type( xfer ), purple_xfer_get_account( xfer ), purple_xfer_get_remote_user( xfer ), _( "Unable to save the file" ) );
-			purple_xfer_cancel_local( xfer );
-		}
-	}
-	else {
-		/* file transfer not found */
-		mxit_send_file_received( session, fileid, RECV_STATUS_BAD_ID );
-	}
-}
--- a/libpurple/protocols/mxit/filexfer.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *			-- file transfers (sending and receiving)  --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * 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		_MXIT_FILEXFER_H_
-#define		_MXIT_FILEXFER_H_
-
-
-/*
- * a MXit file transfer
- */
-struct mxitxfer {
-	struct MXitSession*		session;
-	char					fileid[MXIT_CHUNK_FILEID_LEN];
-};
-
-const char* file_mime_type( const char* filename, const char* buf, int buflen );
-
-/* libPurple callbacks */
-gboolean mxit_xfer_enabled( PurpleConnection* gc, const char* who );
-void mxit_xfer_tx( PurpleConnection* gc, const char* who, const char* filename );
-PurpleXfer* mxit_xfer_new( PurpleConnection* gc, const char* who );
-
-/* MXit Protocol callbacks */
-void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, const char* filename, unsigned int filesize, const char* fileid );
-void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, unsigned int datalen );
-
-
-#endif		/* _MXIT_FILEXFER_H_ */
--- a/libpurple/protocols/mxit/formcmds.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,638 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *					-- MXit Forms & Commands --
- *
- *				Andrew Victor	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-
-#include "internal.h"
-#include "debug.h"
-
-#include "protocol.h"
-#include "mxit.h"
-#include "markup.h"
-#include "formcmds.h"
-
-#undef MXIT_DEBUG_COMMANDS
-
-/*
- * the MXit Command identifiers
- */
-typedef enum
-{
-	MXIT_CMD_UNKNOWN = 0,		/* Unknown command */
-	MXIT_CMD_CLEAR,				/* Clear (clear) */
-	MXIT_CMD_SENDSMS,			/* Send SMS (sendsms) */
-	MXIT_CMD_REPLY,				/* Reply (reply) */
-	MXIT_CMD_PLATREQ,			/* Platform Request (platreq) */
-	MXIT_CMD_SELECTCONTACT,		/* Select Contact (selc) */
-	MXIT_CMD_IMAGE,				/* Inline image (img) */
-	MXIT_CMD_SCREENCONFIG,		/* Chat-screen config (csc) */
-	MXIT_CMD_SCREENINFO,		/* Chat-screen info (csi) */
-	MXIT_CMD_IMAGESTRIP,		/* Image Strip (is) */
-	MXIT_CMD_TABLE				/* Table (tbl) */
-} MXitCommandType;
-
-/* Chat-screen behaviours (bhvr) */
-#define SCREEN_NO_HEADINGS		0x01
-#define SCREEN_FULLSCREEN		0x02
-#define SCREEN_AUTOCLEAR		0x04
-#define SCREEN_NO_AUDIO			0x08
-#define SCREEN_NO_MSGPREFIX		0x10
-#define SCREEN_NOTIFY			0x20
-#define SCREEN_PROGRESSBAR		0x40
-
-
-/*
- * object for an inline image request with an URL
- */
-struct ii_url_request
-{
-	struct RXMsgData*	mx;
-	char*				url;
-};
-
-
-/*------------------------------------------------------------------------
- * Callback function invoked when an inline image request to a web site completes.
- *
- *  @param url_data
- *  @param user_data		The Markup message object
- *  @param url_text			The data returned from the WAP site
- *  @param len				The length of the data returned
- *  @param error_message	Descriptive error message
- */
-static void mxit_cb_ii_returned(PurpleUtilFetchUrlData* url_data, gpointer user_data, const gchar* url_text, gsize len, const gchar* error_message)
-{
-	struct ii_url_request*	iireq		= (struct ii_url_request*) user_data;
-	int*					intptr		= NULL;
-	int						id;
-
-#ifdef	MXIT_DEBUG_COMMANDS
-	purple_debug_info(MXIT_PLUGIN_ID, "Inline Image returned from %s\n", iireq->url);
-#endif
-
-	if (!url_text) {
-		/* no reply from the WAP site */
-		purple_debug_error(MXIT_PLUGIN_ID, "Error downloading Inline Image from %s.\n", iireq->url);
-		goto done;
-	}
-
-	/* lets first see if we don't have the inline image already in cache */
-	if (g_hash_table_lookup(iireq->mx->session->iimages, iireq->url)) {
-		/* inline image found in the cache, so we just ignore this reply */
-		goto done;
-	}
-
-	/* we now have the inline image, store a copy in the imagestore */
-	id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL);
-
-	/* map the inline image id to purple image id */
-	intptr = g_malloc(sizeof(int));
-	*intptr = id;
-	g_hash_table_insert(iireq->mx->session->iimages, iireq->url, intptr);
-
-	iireq->mx->flags |= PURPLE_MESSAGE_IMAGES;
-
-done:
-	iireq->mx->img_count--;
-	if ((iireq->mx->img_count == 0) && (iireq->mx->converted)) {
-		/*
-		 * this was the last outstanding emoticon for this message,
-		 * so we can now display it to the user.
-		 */
-		mxit_show_message(iireq->mx);
-	}
-
-	g_free(iireq);
-}
-
-
-/*------------------------------------------------------------------------
- * Return the command identifier of this MXit Command.
- *
- *  @param cmd			The MXit command <key,value> map
- *  @return				The MXit command identifier
- */
-static MXitCommandType command_type(GHashTable* hash)
-{
-	char* op;
-	char* type;
-
-	op = g_hash_table_lookup(hash, "op");
-	if (op) {
-		if ( strcmp(op, "cmd") == 0 ) {
-			type = g_hash_table_lookup(hash, "type");
-			if (type == NULL)								/* no command provided */
-				return MXIT_CMD_UNKNOWN;
-			else if (strcmp(type, "clear") == 0)			/* clear */
-				return MXIT_CMD_CLEAR;
-			else if (strcmp(type, "sendsms") == 0)			/* send an SMS */
-				return MXIT_CMD_SENDSMS;
-			else if (strcmp(type, "reply") == 0)			/* list of options */
-				return MXIT_CMD_REPLY;
-			else if (strcmp(type, "platreq") == 0)			/* platform request */
-				return MXIT_CMD_PLATREQ;
-			else if (strcmp(type, "selc") == 0)				/* select contact */
-				return MXIT_CMD_SELECTCONTACT;
-		}
-		else if (strcmp(op, "img") == 0)					/* inline image */
-			return MXIT_CMD_IMAGE;
-		else if (strcmp(op, "csc") == 0)					/* chat-screen config */
-			return MXIT_CMD_SCREENCONFIG;
-		else if (strcmp(op, "csi") == 0)					/* chat-screen info */
-			return MXIT_CMD_SCREENINFO;
-		else if (strcmp(op, "is") == 0)						/* image-strip */
-			return MXIT_CMD_IMAGESTRIP;
-		else if (strcmp(op, "tbl") == 0)					/* table */
-			return MXIT_CMD_TABLE;
-	}
-
-	return MXIT_CMD_UNKNOWN;
-}
-
-
-/*------------------------------------------------------------------------
- * Tokenize a MXit Command string into a <key,value> map.
- *
- *  @param cmd			The MXit command string
- *  @return				The <key,value> hash-map, or NULL on error.
- */
-static GHashTable* command_tokenize(char* cmd)
-{
-	GHashTable* hash	= NULL;
-	gchar**		parts;
-	int			i		= 0;
-
-#ifdef MXIT_DEBUG_COMMANDS
-	purple_debug_info(MXIT_PLUGIN_ID, "command: '%s'\n", cmd);
-#endif
-
-	/* explode the command into parts */
-	parts = g_strsplit(cmd, "|", 0);
-
-	hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-
-	/* now break part into a key & value */
-	while (parts[i] != NULL) {
-		char* value;
-
-		value = strchr(parts[i], '=');		/* find start of value */
-		if (value != NULL) {
-			*value = '\0';
-			value++;
-		}
-
-#ifdef MXIT_DEBUG_COMMANDS
-		purple_debug_info(MXIT_PLUGIN_ID, "  key='%s' value='%s'\n", parts[i], value);
-#endif
-
-		g_hash_table_insert(hash, g_strdup(parts[i]), g_strdup(value));
-
-		i++;
-	}
-
-	g_strfreev(parts);
-
-	return hash;
-}
-
-
-/*------------------------------------------------------------------------
- * Process a Clear MXit command.
- *  [::op=cmd|type=clear|clearmsgscreen=true|auto=true|id=12345:]
- *
- *  @param session		The MXit session object
- *  @param from			The sender of the message.
- *  @param hash			The MXit command <key,value> map
- */
-static void command_clear(struct MXitSession* session, const char* from, GHashTable* hash)
-{
-	PurpleConversation *conv;
-	char* clearmsgscreen;
-
-	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, session->acc);
-	if (conv == NULL) {
-		purple_debug_error(MXIT_PLUGIN_ID, _( "Conversation with '%s' not found\n" ), from);
-		return;
-	}
-
-	clearmsgscreen = g_hash_table_lookup(hash, "clearmsgscreen");
-	if ( (clearmsgscreen) && (strcmp(clearmsgscreen, "true") == 0) ) {
-		/* this is a command to clear the chat screen */
-		purple_conversation_clear_message_history(conv);
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Process a Reply MXit command.
- *  [::op=cmd|type=reply|replymsg=back|selmsg=b) Back|displaymsg=Processing|id=12345:]
- *  [::op=cmd|nm=rep|type=reply|replymsg=back|selmsg=b) Back|displaymsg=Processing|id=12345:]
- *
- *  @param mx			The received message data object
- *  @param hash			The MXit command <key,value> map
- */
-static void command_reply(struct RXMsgData* mx, GHashTable* hash)
-{
-	char* replymsg;
-	char* selmsg;
-	char* nm;
-
-	selmsg = g_hash_table_lookup(hash, "selmsg");			/* selection message */
-	replymsg = g_hash_table_lookup(hash, "replymsg");		/* reply message */
-	nm = g_hash_table_lookup(hash, "nm");					/* name parameter */
-
-	if ((selmsg == NULL) || (replymsg == NULL))
-		return;		/* these parameters are required */
-
-	if (nm) {		/* indicates response must be a structured response */
-		gchar*	seltext = g_markup_escape_text(purple_url_decode(selmsg), -1);
-		gchar*	replycmd = g_strdup_printf("type=reply|nm=%s|res=%s|err=0", nm, purple_url_decode(replymsg));
-
-		mxit_add_html_link( mx, replycmd, TRUE, seltext );
-
-		g_free(seltext);
-		g_free(replycmd);
-	}
-	else {
-		gchar*	seltext = g_markup_escape_text(purple_url_decode(selmsg), -1);
-
-		mxit_add_html_link( mx, purple_url_decode(replymsg), FALSE, seltext );
-
-		g_free(seltext);
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Process a PlatformRequest MXit command.
- *  [::op=cmd|type=platreq|selmsg=Upgrade MXit|dest=http%3a//m.mxit.com|id=12345:]
- *
- *  @param hash			The MXit command <key,value> map
- *  @param msg			The message to display (as generated so far)
- */
-static void command_platformreq(GHashTable* hash, GString* msg)
-{
-	gchar*	text	= NULL;
-	char*	selmsg;
-	char*	dest;
-
-	selmsg = g_hash_table_lookup(hash, "selmsg");			/* find the selection message */
-	if (selmsg && (strlen(selmsg) > 0)) {
-		text = g_markup_escape_text(purple_url_decode(selmsg), -1);
-	}
-
-	dest = g_hash_table_lookup(hash, "dest");				/* find the destination */
-	if (dest) {
-		g_string_append_printf(msg, "<a href=\"%s\">%s</a>", purple_url_decode(dest), (text) ? text : _( "Download" ));		/* add link to display message */
-	}
-
-	if (text)
-		g_free(text);
-}
-
-
-/*------------------------------------------------------------------------
- * Process an inline image MXit command.
- *  [::op=img|dat=ASDF23408asdflkj2309flkjsadf%3d%3d|algn=1|w=120|h=12|t=100|replymsg=text:]
- *
- *  @param mx			The received message data object
- *  @param hash			The MXit command <key,value> map
- *  @param msg			The message to display (as generated so far)
- */
-static void command_image(struct RXMsgData* mx, GHashTable* hash, GString* msg)
-{
-	const char*	img;
-	const char*	reply;
-	guchar*		rawimg;
-	gsize		rawimglen;
-	int			imgid;
-
-	img = g_hash_table_lookup(hash, "dat");
-	if (img) {
-		rawimg = purple_base64_decode(img, &rawimglen);
-		//purple_util_write_data_to_file_absolute("/tmp/mxitinline.png", (char*) rawimg, rawimglen);
-		imgid = purple_imgstore_add_with_id(rawimg, rawimglen, NULL);
-		g_string_append_printf(msg, "<img id=\"%i\">", imgid);
-		mx->flags |= PURPLE_MESSAGE_IMAGES;
-	}
-	else {
-		img = g_hash_table_lookup(hash, "src");
-		if (img) {
-			struct ii_url_request*	iireq;
-
-			iireq = g_new0(struct ii_url_request,1);
-			iireq->url = g_strdup(purple_url_decode(img));
-			iireq->mx = mx;
-
-			g_string_append_printf(msg, "%s%s>", MXIT_II_TAG, iireq->url);
-			mx->got_img = TRUE;
-
-			/* lets first see if we don't have the inline image already in cache */
-			if (g_hash_table_lookup(mx->session->iimages, iireq->url)) {
-				/* inline image found in the cache, so we do not have to request it from the web */
-				g_free(iireq);
-			}
-			else {
-				/* send the request for the inline image */
-				purple_debug_info(MXIT_PLUGIN_ID, "sending request for inline image '%s'\n", iireq->url);
-
-				/* request the image (reference: "libpurple/util.h") */
-				purple_util_fetch_url_request(iireq->url, TRUE, NULL, TRUE, NULL, FALSE, mxit_cb_ii_returned, iireq);
-				mx->img_count++;
-			}
-		}
-	}
-
-	/* if this is a clickable image, show a click link */
-	reply = g_hash_table_lookup(hash, "replymsg");
-	if (reply) {
-		g_string_append_printf(msg, "\n");
-		mxit_add_html_link(mx, purple_url_decode(reply), FALSE, _( "click here" ));
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Process an Imagestrip MXit command.
- *  [::op=is|nm=status|dat=iVBORw0KGgoAAAA%3d%3d|v=63398792426788|fw=8|fh=8|layer=0:]
- *
- *  @param from			The sender of the message.
- *  @param hash			The MXit command <key,value> map
- */
-static void command_imagestrip(struct MXitSession* session, const char* from, GHashTable* hash)
-{
-	const char* name;
-	const char* validator;
-	const char* tmp;
-	int width, height, layer;
-
-	purple_debug_info(MXIT_PLUGIN_ID, "ImageStrip received from %s\n", from);
-
-	/* image strip name */
-	name = g_hash_table_lookup(hash, "nm");
-
-	/* validator */
-	validator = g_hash_table_lookup(hash, "v");
-
-	if (!name || !validator)
-		return;
-
-	/* image data */
-	tmp = g_hash_table_lookup(hash, "dat");
-	if (tmp) {
-		guchar*		rawimg;
-		gsize		rawimglen;
-		char*		dir;
-		char*		escfrom;
-		char*		escname;
-		char*		escvalidator;
-		char*		filename;
-
-		/* base64 decode the image data */
-		rawimg = purple_base64_decode(tmp, &rawimglen);
-		if (!rawimg)
-			return;
-
-		/* save it to a file */
-		dir = g_build_filename(purple_user_dir(), "mxit", "imagestrips", NULL);
-		purple_build_dir(dir, S_IRUSR | S_IWUSR | S_IXUSR);		/* ensure directory exists */
-
-		escfrom = g_strdup(purple_escape_filename(from));
-		escname = g_strdup(purple_escape_filename(name));
-		escvalidator = g_strdup(purple_escape_filename(validator));
-		filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s-%s-%s.png", dir, escfrom, escname, escvalidator);
-
-		purple_util_write_data_to_file_absolute(filename, (char*) rawimg, rawimglen);
-
-		g_free(dir);
-		g_free(escfrom);
-		g_free(escname);
-		g_free(escvalidator);
-		g_free(filename);
-	}
-
-	tmp = g_hash_table_lookup(hash, "fw");
-	width = (tmp ? atoi(tmp) : 0);
-
-	tmp = g_hash_table_lookup(hash, "fh");
-	height = (tmp ? atoi(tmp) : 0);
-
-	tmp = g_hash_table_lookup(hash, "layer");
-	layer = (tmp ? atoi(tmp) : 0);
-
-	purple_debug_info(MXIT_PLUGIN_ID, "ImageStrip %s from %s: [w=%i h=%i l=%i validator=%s]\n", name, from, width, height, layer, validator);
-}
-
-
-/*------------------------------------------------------------------------
- * Process a Chat-Screen-Info MXit command.
- *  [::op=csi:]
- *
- *  @param session		The MXit session object
- *  @param from			The sender of the message.
- */
-static void command_screeninfo(struct MXitSession* session, const char* from)
-{
-	char* response;
-
-	purple_debug_info(MXIT_PLUGIN_ID, "Chat Screen Info received from %s\n", from);
-
-	// TODO: Determine width, height, colors of chat-screen.
-
-	response = g_strdup_printf("::type=csi|res=bhvr,0;w,%i;h,%i;col,0.ffffffff,29.ff000000:", 300, 400);
-
-	/* send response back to MXit */
-    mxit_send_message( session, from, response, FALSE, TRUE );
-
-	g_free(response);
-}
-
-
-/*------------------------------------------------------------------------
- * Process a Chat-Screen-Configure MXit command.
- *  [::op=csc|bhvr=|menu=<menu>|col=<colors>:]
- *  where:
- *   menu ::= <menuitem> { ";" <menuitem> }
- *     menuitem ::= { type "," <text> "," <name> "," <meta> }
- *   colors ::= <color> { ";" <color> }
- *     color ::= <colorid> "," <ARGB hex color>
- *
- *  @param session		The MXit session object
- *  @param from			The sender of the message.
- *  @param hash			The MXit command <key,value> map
- */
-static void command_screenconfig(struct MXitSession* session, const char* from, GHashTable* hash)
-{
-	const char* tmp;
-
-	purple_debug_info(MXIT_PLUGIN_ID, "Chat Screen Configure received from %s\n", from);
-
-	/* Behaviour */
-	tmp = g_hash_table_lookup(hash, "bhvr");
-	if (tmp) {
-		purple_debug_info(MXIT_PLUGIN_ID, "  behaviour = %s\n", tmp);
-		// TODO: Re-configure conversation screen.
-	}
-
-	/* Menu */
-	tmp = g_hash_table_lookup(hash, "menu");
-	if (tmp) {
-		purple_debug_info(MXIT_PLUGIN_ID, "  menu = %s\n", tmp);
-		// TODO: Implement conversation-specific sub-menu.
-	}
-
-	/* Colours */
-	tmp = g_hash_table_lookup(hash, "col");
-	if (tmp) {
-		purple_debug_info(MXIT_PLUGIN_ID, "  colours = %s\n", tmp);
-		// TODO: Re-configuration conversation colors.
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Process a Table Markup MXit command.
- *
- *  @param mx			The received message data object
- *  @param hash			The MXit command <key,value> map
- */
-static void command_table(struct RXMsgData* mx, GHashTable* hash)
-{
-	const char* tmp;
-	const char* name;
-	int mode;
-	unsigned int nr_columns = 0, nr_rows = 0;
-	gchar** coldata;
-	unsigned int i, j;
-
-	/* table name */
-	name = g_hash_table_lookup(hash, "nm");
-	if (!name)
-		return;
-
-	/* number of columns */
-	tmp = g_hash_table_lookup(hash, "col");
-	nr_columns = (tmp ? atoi(tmp) : 0);
-
-	/* number of rows */
-	tmp = g_hash_table_lookup(hash, "row");
-	nr_rows = (tmp ? atoi(tmp) : 0);
-
-	/* mode */
-	tmp = g_hash_table_lookup(hash, "mode");
-	mode = (tmp ? atoi(tmp) : 0);
-
-	/* table data */
-	tmp = g_hash_table_lookup(hash, "d");
-	if (!tmp)
-		tmp = "";
-
-	coldata = g_strsplit(tmp, "~", 0);			/* split into entries for each row & column */
-
-	if (g_strv_length(coldata) != (nr_rows * nr_columns)) {
-		purple_debug_info(MXIT_PLUGIN_ID, "Invalid table data: cols=%i rows=%i\n", nr_columns, nr_rows);
-		g_strfreev(coldata);
-		return;
-	}
-
-	purple_debug_info(MXIT_PLUGIN_ID, "Table %s from %s: [cols=%i rows=%i mode=%i]\n", name, mx->from, nr_columns, nr_rows, mode);
-
-	for (i = 0; i < nr_rows; i++) {
-		for (j = 0; j < nr_columns; j++) {
-			purple_debug_info(MXIT_PLUGIN_ID, " Row %i Column %i = %s\n", i, j, coldata[i*nr_columns + j]);
-		}
-	}
-
-	g_strfreev(coldata);
-}
-
-
-/*------------------------------------------------------------------------
- * Process a received MXit Command message.
- *
- *  @param mx				The received message data object
- *  @param message			The message text
- *  @return					The length of the command
- */
-int mxit_parse_command(struct RXMsgData* mx, char* message)
-{
-	GHashTable* hash	= NULL;
-	char*		start;
-	char*		end;
-
-	/* ensure that this is really a command */
-	if ( ( message[0] != ':' ) || ( message[1] != ':' ) ) {
-		/* this is not a command */
-		return 0;
-	}
-
-	start = message + 2;
-	end = strstr(start, ":");
-	if (end) {
-		/* end of a command found */
-		*end = '\0';		/* terminate command string */
-
-		hash = command_tokenize(start);			/* break into <key,value> pairs */
-		if (hash) {
-			MXitCommandType type = command_type(hash);
-
-			switch (type) {
-				case MXIT_CMD_CLEAR :
-					command_clear(mx->session, mx->from, hash);
-					break;
-				case MXIT_CMD_REPLY :
-					command_reply(mx, hash);
-					break;
-				case MXIT_CMD_PLATREQ :
-					command_platformreq(hash, mx->msg);
-					break;
-				case MXIT_CMD_IMAGE :
-					command_image(mx, hash, mx->msg);
-					break;
-				case MXIT_CMD_SCREENCONFIG :
-					command_screenconfig(mx->session, mx->from, hash);
-					break;
-				case MXIT_CMD_SCREENINFO :
-					command_screeninfo(mx->session, mx->from);
-					break;
-				case MXIT_CMD_IMAGESTRIP :
-					command_imagestrip(mx->session, mx->from, hash);
-					break;
-				case MXIT_CMD_TABLE :
-					command_table(mx, hash);
-					break;
-				default :
-					/* command unknown, or not currently supported */
-					break;
-			}
-			g_hash_table_destroy(hash);
-		}
-		*end = ':';
-
-		return end - message;
-	}
-	else {
-		return 0;
-	}
-}
--- a/libpurple/protocols/mxit/formcmds.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *					-- MXit Forms & Commands --
- *
- *				Andrew Victor	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * 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		_MXIT_FORMCMDS_H_
-#define		_MXIT_FORMCMDS_H_
-
-#include	"protocol.h"
-
-int mxit_parse_command(struct RXMsgData* mx, char* message);
-
-#endif		/* _MXIT_FORMCMDS_H_ */
--- a/libpurple/protocols/mxit/http.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,344 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *			-- MXit client protocol implementation --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include	"internal.h"
-#include	"debug.h"
-
-#include	"mxit.h"
-#include	"protocol.h"
-#include	"http.h"
-
-
-/* HTTP constants */
-#define		HTTP_11_200_OK		"HTTP/1.1 200 OK\r\n"
-#define		HTTP_11_100_CONT	"HTTP/1.1 100 Continue\r\n"
-#define		HTTP_11_SEPERATOR	"\r\n\r\n"
-#define		HTTP_CONTENT_LEN	"Content-Length: "
-
-
-/* define to enable HTTP debugging */
-#define		DEBUG_HTTP
-
-
-/*------------------------------------------------------------------------
- * This will freeup the memory used by a HTTP request structure
- *
- *	@param req		The HTTP structure's resources should be freed up
- */
-static void free_http_request( struct http_request* req )
-{
-	g_free( req->host );
-	g_free( req->data );
-	g_free( req );
-}
-
-
-/*------------------------------------------------------------------------
- * Write the request to the HTTP server.
- *
- *  @param fd			The file descriptor
- *  @param pktdata		The packet data
- *  @param pktlen		The length of the packet data
- *  @return				Return -1 on error, otherwise 0
- */
-static int mxit_http_raw_write( int fd, const char* pktdata, size_t pktlen )
-{
-	size_t	written;
-	int		res;
-
-	written = 0;
-	while ( written < pktlen ) {
-		res = write( fd, &pktdata[written], pktlen - written );
-		if ( res <= 0 ) {
-			/* error on socket */
-			if ( errno == EAGAIN )
-				continue;
-
-			purple_debug_error( MXIT_PLUGIN_ID, "Error while writing packet to HTTP server (%i)\n", res );
-			return -1;
-		}
-		written += res;
-	}
-
-	return 0;
-}
-
-
-/*------------------------------------------------------------------------
- * Callback when data is received from the HTTP server.
- *
- *  @param user_data		The MXit session object
- *  @param source			The file-descriptor on which data was received
- *  @param cond				Condition which caused the callback (PURPLE_INPUT_READ)
- */
-static void mxit_cb_http_read( gpointer user_data, gint source, PurpleInputCondition cond )
-{
-	struct MXitSession*	session		= (struct MXitSession*) user_data;
-	char				buf[256];
-	unsigned int		buflen;
-	char*				body;
-	unsigned int		bodylen;
-	char*				ch;
-	int					len;
-	char*				tmp;
-	int					res;
-#if 0
-	char*				next;
-#endif
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_http_read\n" );
-
-	if ( session->rx_state == RX_STATE_RLEN ) {
-		/* we are reading in the HTTP headers */
-
-		/* copy partial headers if we have any part saved */
-		memcpy( buf, session->rx_dbuf, session->rx_i );
-		buflen = session->rx_i;
-
-		/* read bytes from the socket */
-		len = read( session->fd, buf + buflen, sizeof( buf ) - ( buflen + 1 ) );
-		if ( len <= 0 ) {
-			/* connection has been terminated, or error occurred */
-			goto done;
-		}
-		buf[buflen+len] = '\0';
-
-#if 0
-nextpacket:
-#endif
-
-#ifdef	DEBUG_HTTP
-		purple_debug_info( MXIT_PLUGIN_ID, "HTTP POST READ 1: (%i)\n", len );
-		dump_bytes( session, buf + buflen, len );
-#endif
-
-		/* see if we have all the HTTP headers yet */
-		ch = strstr( buf, HTTP_11_SEPERATOR );
-		if ( !ch ) {
-			/* we need to wait for more input, so save what we have */
-			session->rx_i = buflen + len;
-			memcpy( session->rx_dbuf, buf, session->rx_i );
-			return;
-		}
-		buflen += len;
-
-		/* we have the header's end now skip over the http separator to get the body offset */
-		ch += strlen( HTTP_11_SEPERATOR );
-		*(ch - 1) = '\0';
-		body = ch;
-
-		res = buflen - ( ch - buf );
-		if ( res > 0 ) {
-			/* we read more bytes than just the header so copy it over */
-			memcpy( session->rx_dbuf, ch, res );
-			session->rx_i = res;
-		}
-		else {
-			session->rx_i = 0;
-		}
-
-		/* test for a good response */
-		if ( ( strncmp( buf, HTTP_11_200_OK, strlen( HTTP_11_200_OK ) ) != 0 ) && ( strncmp( buf, HTTP_11_100_CONT, strlen( HTTP_11_100_CONT ) ) != 0 ) ) {
-			/* bad result */
-			purple_debug_error( MXIT_PLUGIN_ID, "HTTP error: %s\n", ch );
-			goto done;
-		}
-
-		/* find the content-length */
-		ch = (char*) purple_strcasestr( buf, HTTP_CONTENT_LEN );
-		if ( !ch ) {
-			/* bad request. it does not contain a content-length header */
-			purple_debug_error( MXIT_PLUGIN_ID, "HTTP reply received without content-length header (ignoring packet)\n" );
-			goto done;
-		}
-
-		/* parse the content-length */
-		ch += strlen( HTTP_CONTENT_LEN );
-		tmp = strchr( ch, '\r' );
-		if ( !tmp ) {
-			purple_debug_error( MXIT_PLUGIN_ID, "Received bad HTTP reply packet (ignoring packet)\n" );
-			goto done;
-		}
-		tmp = g_strndup( ch, tmp - ch );
-		bodylen = strtoul( tmp, NULL, 10 );
-		g_free( tmp );
-		tmp = NULL;
-
-		if ( buflen + bodylen >= CP_MAX_PACKET ) {
-			/* this packet is way to big */
-			goto done;
-		}
-		else if ( buflen > ( ( body - buf ) + bodylen ) ) {
-			/* we have a second packet here */
-#if 0
-			next = body + bodylen;
-#endif
-			session->rx_res = 0;
-		}
-		else {
-			session->rx_res = bodylen - session->rx_i;
-		}
-
-		if ( session->rx_res == 0 ) {
-			/* we have read all the data */
-			session->rx_i = bodylen;
-			session->rx_state = RX_STATE_PROC;
-		}
-		else {
-			/* there is still some data outstanding */
-			session->rx_state = RX_STATE_DATA;
-		}
-	}
-	else if ( session->rx_state == RX_STATE_DATA ) {
-		/* we are reading the HTTP content (body) */
-
-		/* read bytes from the socket */
-		len = read( session->fd, &session->rx_dbuf[session->rx_i], session->rx_res );
-		if ( len <= 0 ) {
-			/* connection has been terminated, or error occurred */
-			goto done;
-		}
-
-#ifdef	DEBUG_HTTP
-		purple_debug_info( MXIT_PLUGIN_ID, "HTTP POST READ 2: (%i)\n", len );
-		dump_bytes( session, &session->rx_dbuf[session->rx_i], len );
-#endif
-		session->rx_i += len;
-		session->rx_res -= len;
-
-		if ( session->rx_res == 0 ) {
-			/* ok, so now we have read in the whole packet */
-			session->rx_state = RX_STATE_PROC;
-		}
-	}
-
-	if ( session->rx_state == RX_STATE_PROC ) {
-		mxit_parse_packet( session );
-
-#if	0
-		if ( next ) {
-			/* there is another packet of which we read some data */
-
-			/* reset input */
-			session->rx_state = RX_STATE_RLEN;
-			session->rx_lbuf[0] = '\0';
-			session->rx_i = 0;
-			session->rx_res = 0;
-
-			/* move read data */
-			len = next - buf;
-			buflen = len;
-			memcpy( buf, next, len );
-			goto nextpacket;
-		}
-#endif
-
-		/* we are done */
-		goto done;
-	}
-
-	return;
-done:
-	close( session->fd );
-	purple_input_remove( session->http_handler );
-	session->http_handler = 0;
-}
-
-
-/*------------------------------------------------------------------------
- * Callback invoked once the connection has been established to the HTTP server,
- * or on connection failure.
- *
- *  @param user_data		The MXit session object
- *  @param source			The file-descriptor associated with the connection
- *  @param error_message	Message explaining why the connection failed
- */
-static void mxit_cb_http_connect( gpointer user_data, gint source, const gchar* error_message )
-{
-	struct http_request*	req	= (struct http_request*) user_data;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_http_connect\n" );
-
-	/* source is the file descriptor of the new connection */
-	if ( source < 0 ) {
-		purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_http_connect failed: %s\n", error_message );
-		purple_connection_error( req->session->con, _( "Unable to connect to the MXit HTTP server. Please check your server settings." ) );
-		return;
-	}
-
-	/* we now have an open and active TCP connection to the mxit server */
-	req->session->fd = source;
-
-	/* reset the receive buffer */
-	req->session->rx_state = RX_STATE_RLEN;
-	req->session->rx_lbuf[0] = '\0';
-	req->session->rx_i = 0;
-	req->session->rx_res = 0;
-
-	/* start listening on the open connection for messages from the server (reference: "libpurple/eventloop.h") */
-	req->session->http_handler = purple_input_add( req->session->fd, PURPLE_INPUT_READ, mxit_cb_http_read, req->session );
-
-	/* actually send the request to the HTTP server */
-	mxit_http_raw_write( req->session->fd, req->data, req->datalen );
-
-	/* free up resources */
-	free_http_request( req );
-	req = NULL;
-}
-
-
-/*------------------------------------------------------------------------
- * Create HTTP connection for sending a HTTP request
- *
- *	@param session		The MXit session object
- *	@param host			The server name to connect to
- *	@param port			The port number to connect to
- *	@param header		The HTTP header.
- *	@param data			The HTTP request data.
- *	@param datalen		The HTTP request data length
- */
-void mxit_http_send_request( struct MXitSession* session, char* host, int port, gchar* header, const char* data, size_t datalen )
-{
-	PurpleProxyConnectData*		con	= NULL;
-	struct http_request*		req;
-	size_t						headerlen = strlen( header );
-
-	/* build the http request */
-	req = g_new0( struct http_request, 1 );
-	req->session = session;
-	req->host = host;
-	req->port = port;
-	req->data = g_malloc0( headerlen + datalen );
-	memcpy( req->data, header, headerlen );
-	memcpy( req->data + headerlen, data, datalen );
-	req->datalen = headerlen + datalen;
-
-	/* open connection to the HTTP server */
-	con = purple_proxy_connect( NULL, session->acc, host, port, mxit_cb_http_connect, req );
-	if ( !con ) {
-		purple_connection_error_reason( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Unable to connect" ) );
-	}
-}
-
--- a/libpurple/protocols/mxit/http.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *			-- MXit client protocol implementation --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * 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		_MXIT_HTTP_H_
-#define		_MXIT_HTTP_H_
-
-
-
-struct http_request
-{
-	struct MXitSession*		session;
-	char*					host;
-	int						port;
-	char*					data;
-	size_t					datalen;
-};
-
-
-void mxit_http_send_request( struct MXitSession* session, char* host, int port, gchar* header, const char* data, size_t datalen );
-
-
-
-#endif		/* _MXIT_HTTP_H_ */
-
--- a/libpurple/protocols/mxit/login.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,821 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *				-- MXit user login functionality --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include	"internal.h"
-#include	"debug.h"
-#include	"request.h"
-#include	"version.h"
-
-#include	"protocol.h"
-#include	"mxit.h"
-#include	"cipher.h"
-#include	"login.h"
-#include	"profile.h"
-
-/* requesting captcha size */
-#define		MXIT_CAPTCHA_HEIGHT		50
-#define		MXIT_CAPTCHA_WIDTH		150
-
-
-/* prototypes */
-static void mxit_register_view( struct MXitSession* session );
-static void get_clientinfo( struct MXitSession* session );
-
-
-/*------------------------------------------------------------------------
- * Create a new mxit session object
- *
- * @return The MXit session object
- */
-static struct MXitSession* mxit_create_object( PurpleAccount* account )
-{
-	PurpleConnection*	con			= purple_account_get_connection( account );
-	struct MXitSession*	session		= NULL;
-
-	/* currently the wapsite does not handle a '+' in front of the username (mxitid) so we just strip it */
-	{
-		const char* username	= purple_account_get_username( account );
-
-		if ( username[0] == '+' ) {
-			char* fixed = g_strdup( &username[1] );
-			purple_account_set_username( account, fixed );
-			g_free( fixed );
-		}
-	}
-
-	session = g_new0( struct MXitSession, 1 );
-	session->con = con;
-	session->acc = account;
-
-	/* configure the connection (reference: "libpurple/connection.h") */
-	purple_connection_set_protocol_data( con, session );
-	con->flags |= PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC | PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_SUPPORT_MOODS;
-
-	/* configure the session (reference: "libpurple/account.h") */
-	g_strlcpy( session->server, purple_account_get_string( account, MXIT_CONFIG_SERVER_ADDR, DEFAULT_SERVER ), sizeof( session->server ) );
-	g_strlcpy( session->http_server, purple_account_get_string( account, MXIT_CONFIG_HTTPSERVER, DEFAULT_HTTP_SERVER ), sizeof( session->http_server ) );
-	session->port = purple_account_get_int( account, MXIT_CONFIG_SERVER_PORT, DEFAULT_PORT );
-	g_strlcpy( session->distcode, purple_account_get_string( account, MXIT_CONFIG_DISTCODE, "" ), sizeof( session->distcode ) );
-	g_strlcpy( session->clientkey, purple_account_get_string( account, MXIT_CONFIG_CLIENTKEY, "" ), sizeof( session->clientkey ) );
-	g_strlcpy( session->dialcode, purple_account_get_string( account, MXIT_CONFIG_DIALCODE, "" ), sizeof( session->dialcode ) );
-	session->http = purple_account_get_bool( account, MXIT_CONFIG_USE_HTTP, FALSE );
-	session->iimages = g_hash_table_new( g_str_hash, g_str_equal );
-	session->rx_state = RX_STATE_RLEN;
-	session->http_interval = MXIT_HTTP_POLL_MIN;
-	session->http_last_poll = mxit_now_milli();
-
-	return session;
-}
-
-
-/*------------------------------------------------------------------------
- * We now have a connection established with MXit, so we can start the
- * login procedure
- *
- * @param session	The MXit session object
- */
-static void mxit_connected( struct MXitSession* session )
-{
-	int			state;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_connected\n" );
-
-	session->flags |= MXIT_FLAG_CONNECTED;
-	purple_connection_update_progress( session->con, _( "Logging In..." ), 2, 4 );
-
-	/* create a timer to send a ping packet if the connection is idle */
-	session->last_tx = mxit_now_milli();
-
-	/* encrypt the user password */
-	session->encpwd = mxit_encrypt_password( session );
-
-	state = purple_account_get_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
-	if ( state == MXIT_STATE_LOGIN ) {
-		/* create and send login packet */
-		mxit_send_login( session );
-	}
-	else {
-		if ( !session->profile ) {
-			/* we have lost the session profile, so ask the user to enter it again */
-			mxit_register_view( session );
-		}
-		else {
-			/* create and send the register packet */
-			mxit_send_register( session );
-		}
-	}
-
-	/* enable signals */
-	mxit_enable_signals( session );
-
-#ifdef		MXIT_LINK_CLICK
-	/* register for uri click notification */
-	mxit_register_uri_handler();
-#endif
-
-	/* start the polling if this is a HTTP connection */
-	if ( session->http ) {
-		session->http_timer_id = purple_timeout_add_seconds( 2, mxit_manage_polling, session );
-	}
-
-	/* This timer might already exist if we're registering a new account */
-	if ( session->q_slow_timer_id == 0 ) {
-		/* start the tx queue manager timer */
-		session->q_slow_timer_id = purple_timeout_add_seconds( 2, mxit_manage_queue_slow, session );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Callback invoked once the connection has been established to the MXit server,
- * or on connection failure.
- *
- *  @param user_data		The MXit session object
- *  @param source			The file-descriptor associated with the connection
- *  @param error_message	Message explaining why the connection failed
- */
-static void mxit_cb_connect( gpointer user_data, gint source, const gchar* error_message )
-{
-	struct MXitSession*	session		= (struct MXitSession*) user_data;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_connect\n" );
-
-	/* source is the file descriptor of the new connection */
-	if ( source < 0 ) {
-		purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_connect failed: %s\n", error_message );
-		purple_connection_error( session->con, _( "Unable to connect to the MXit server. Please check your server settings." ) );
-		return;
-	}
-
-	/* we now have an open and active TCP connection to the mxit server */
-	session->fd = source;
-
-	/* start listening on the open connection for messages from the server (reference: "libpurple/eventloop.h") */
-	session->con->inpa = purple_input_add( session->fd, PURPLE_INPUT_READ, mxit_cb_rx, session );
-
-	mxit_connected( session );
-}
-
-
-/*------------------------------------------------------------------------
- * Attempt to establish a connection to the MXit server.
- *
- *  @param session			The MXit session object
- */
-static void mxit_login_connect( struct MXitSession* session )
-{
-	PurpleProxyConnectData*		data	= NULL;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_login_connect\n" );
-
-	purple_connection_update_progress( session->con, _( "Connecting..." ), 1, 4 );
-
-	/*
-	 * at this stage we have all the user's information we require
-	 * for logging into MXit. we will now create a new connection to
-	 * a MXit server.
-	 */
-
-	if ( !session->http ) {
-		/* socket connection */
-		data = purple_proxy_connect( session->con, session->acc, session->server, session->port, mxit_cb_connect, session );
-		if ( !data ) {
-			purple_connection_error( session->con, _( "Unable to connect to the MXit server. Please check your server settings." ) );
-			return;
-		}
-	}
-	else {
-		/* http connection */
-		mxit_connected( session );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Register a new account with MXit
- *
- * @param gc		The connection object
- * @param fields	This is the fields filled-in by the user
- */
-static void mxit_cb_register_ok( PurpleConnection *gc, PurpleRequestFields *fields )
-{
-	struct MXitSession*		session		= purple_connection_get_protocol_data( gc );
-	struct MXitProfile*		profile		= session->profile;
-	const char*				str;
-	const char*				pin;
-	const char*				err			= NULL;
-	int						len;
-	int						i;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_register_ok\n" );
-
-	if ( !PURPLE_CONNECTION_IS_VALID( gc ) ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "Unable to register; account offline.\n" );
-		return;
-	}
-
-	/* nickname */
-	str = purple_request_fields_get_string( fields, "nickname" );
-	if ( ( !str ) || ( strlen( str ) < 3 ) ) {
-		err = _( "The Display Name you entered is too short." );
-		goto out;
-	}
-	g_strlcpy( profile->nickname, str, sizeof( profile->nickname ) );
-
-	/* birthdate */
-	str = purple_request_fields_get_string( fields, "bday" );
-	if ( ( !str ) || ( strlen( str ) < 10 ) || ( !validateDate( str ) ) ) {
-		err = _( "The birthday you entered is invalid. The correct format is: 'YYYY-MM-DD'." );
-		goto out;
-	}
-	g_strlcpy( profile->birthday, str, sizeof( profile->birthday ) );
-
-	/* gender */
-	profile->male = ( purple_request_fields_get_choice( fields, "male" ) != 0 );
-
-	/* pin */
-	pin = purple_request_fields_get_string( fields, "pin" );
-	if ( !pin ) {
-		err = _( "The PIN you entered is invalid." );
-		goto out;
-	}
-	len = strlen( pin );
-	if ( ( len < 7 ) || ( len > 10 ) ) {
-		err = _( "The PIN you entered has an invalid length [7-10]." );
-		goto out;
-	}
-	for ( i = 0; i < len; i++ ) {
-		if ( !g_ascii_isdigit( pin[i] ) ) {
-			err = _( "The PIN is invalid. It should only consist of digits [0-9]." );
-			goto out;
-		}
-	}
-	str = purple_request_fields_get_string( fields, "pin2" );
-	if ( ( !str ) || ( strcmp( pin, str ) != 0 ) ) {
-		err = _( "The two PINs you entered do not match." );
-		goto out;
-	}
-	g_strlcpy( profile->pin, pin, sizeof( profile->pin ) );
-
-out:
-	if ( !err ) {
-		purple_account_set_password( session->acc, session->profile->pin );
-		mxit_login_connect( session );
-	}
-	else {
-		/* show error to user */
-		mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Registration Error" ), err );
-		mxit_register_view( session );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Register a new account with MXit
- *
- * @param gc		The connection object
- * @param fields	This is the fields filled-in by the user
- */
-static void mxit_cb_register_cancel( PurpleConnection *gc, PurpleRequestFields *fields )
-{
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_register_cancel\n" );
-
-	/* disconnect */
-	purple_account_disconnect( purple_connection_get_account( gc ) );
-}
-
-
-/*------------------------------------------------------------------------
- * Show a window to the user so that he can enter his information
- *
- *  @param session		The MXit session object
- */
-static void mxit_register_view( struct MXitSession* session )
-{
-	struct MXitProfile*			profile;
-	PurpleRequestFields*		fields;
-	PurpleRequestFieldGroup*	group;
-	PurpleRequestField*			field;
-
-	if ( !session->profile ) {
-		/* we need to create a profile object here */
-		session->profile = g_new0( struct MXitProfile, 1 );
-	}
-	profile = session->profile;
-
-	fields = purple_request_fields_new();
-	group = purple_request_field_group_new( NULL );
-	purple_request_fields_add_group( fields, group );
-
-	/* mxit login name */
-	field = purple_request_field_string_new( "loginname", _( "MXit ID" ), purple_account_get_username( session->acc ), FALSE );
-	purple_request_field_string_set_editable( field, FALSE );
-	purple_request_field_group_add_field( group, field );
-
-	/* nick name (required) */
-	field = purple_request_field_string_new( "nickname", _( "Display Name" ), profile->nickname, FALSE );
-	purple_request_field_set_required( field, TRUE );
-	purple_request_field_group_add_field( group, field );
-
-	/* birthday (required) */
-	field = purple_request_field_string_new( "bday", _( "Birthday" ), profile->birthday, FALSE );
-	purple_request_field_string_set_default_value( field, "YYYY-MM-DD" );
-	purple_request_field_set_required( field, TRUE );
-	purple_request_field_group_add_field( group, field );
-
-	/* gender */
-	field = purple_request_field_choice_new( "male", _( "Gender" ), ( profile->male ) ? 1 : 0 );
-	purple_request_field_choice_add( field, _( "Female" ) );		/* 0 */
-	purple_request_field_choice_add( field, _( "Male" ) );			/* 1 */
-	purple_request_field_group_add_field( group, field );
-
-	/* pin (required) */
-	field = purple_request_field_string_new( "pin", _( "PIN" ), profile->pin, FALSE );
-	purple_request_field_string_set_masked( field, TRUE );
-	purple_request_field_set_required( field, TRUE );
-	purple_request_field_group_add_field( group, field );
-	field = purple_request_field_string_new( "pin2", _( "Verify PIN" ), "", FALSE );
-	purple_request_field_string_set_masked( field, TRUE );
-	purple_request_field_set_required( field, TRUE );
-	purple_request_field_group_add_field( group, field );
-
-	/* show the form to the user to complete */
-	purple_request_fields( session->con, _( "Register New MXit Account" ), _( "Register New MXit Account" ), _( "Please fill in the following fields:" ), fields, _( "OK" ), G_CALLBACK( mxit_cb_register_ok ), _( "Cancel" ), G_CALLBACK( mxit_cb_register_cancel ), session->acc, NULL, NULL, session->con );
-}
-
-
-/*------------------------------------------------------------------------
- * Callback function invoked once the Authorization information has been submitted
- * to the MXit WAP site.
- *
- *  @param url_data			libPurple internal object (see purple_util_fetch_url_request)
- *  @param user_data		The MXit session object
- *  @param url_text			The data returned from the WAP site
- *  @param len				The length of the data returned
- *  @param error_message	Descriptive error message
- */
-static void mxit_cb_clientinfo2( PurpleUtilFetchUrlData* url_data, gpointer user_data, const gchar* url_text, gsize len, const gchar* error_message )
-{
-	struct MXitSession*		session		= (struct MXitSession*) user_data;
-	gchar**					parts;
-	gchar**					host;
-	int						state;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_clientinfo_cb2\n" );
-
-#ifdef	DEBUG_PROTOCOL
-	purple_debug_info( MXIT_PLUGIN_ID, "HTTP RESPONSE: '%s'\n", url_text );
-#endif
-
-	/* remove request from the async outstanding calls list */
-	session->async_calls = g_slist_remove( session->async_calls, url_data );
-
-	if ( !url_text ) {
-		/* no reply from the WAP site */
-		purple_connection_error( session->con, _( "Error contacting the MXit WAP site. Please try again later." ) );
-		return;
-	}
-
-	/* explode the response from the WAP site into an array */
-	parts = g_strsplit( url_text, ";", 15 );
-
-	if ( !parts ) {
-		/* wapserver error */
-		purple_connection_error( session->con, _( "MXit is currently unable to process the request. Please try again later." ) );
-		return;
-	}
-
-	/* check wapsite return code */
-	switch ( parts[0][0] ) {
-			case '0' :
-				/* valid reply! */
-				break;
-			case '1' :
-				purple_connection_error( session->con, _( "Wrong security code entered. Please try again later." ) );
-				return;
-			case '2' :
-				purple_connection_error( session->con, _( "Your session has expired. Please try again later." ) );
-				return;
-			case '5' :
-				purple_connection_error( session->con, _( "Invalid country selected. Please try again." ) );
-				return;
-			case '6' :
-				purple_connection_error( session->con, _( "The MXit ID you entered is not registered. Please register first." ) );
-				return;
-			case '7' :
-				purple_connection_error( session->con, _( "The MXit ID you entered is already registered. Please choose another." ) );
-				/* this user's account already exists, so we need to change the registration login flag to be login */
-				purple_account_set_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
-				return;
-			case '3' :
-			case '4' :
-			default :
-				purple_connection_error( session->con, _( "Internal error. Please try again later." ) );
-				return;
-	}
-
-	/* now parse and split the distribution code and the client key */
-	g_strlcpy( session->distcode, &parts[1][2], 36 + 1 );
-	g_strlcpy( session->clientkey, &parts[1][38], 8 + 1 );
-
-	/* get the dial code for the client */
-	g_strlcpy( session->dialcode, parts[4], sizeof( session->dialcode ) );
-
-	/* parse the proxy server address and port number */
-	host = g_strsplit( parts[2], ":", 4 );
-	g_strlcpy( session->server, &host[1][2], sizeof( session->server ) );
-	session->port = atoi( &host[2][0] );
-
-	/* parse the http proxy server address and port number */
-	g_strlcpy( session->http_server, parts[3], sizeof( session->http_server ) );
-
-	purple_debug_info( MXIT_PLUGIN_ID, "distcode='%s', clientkey='%s', dialcode='%s'\n", session->distcode, session->clientkey, session->dialcode );
-	purple_debug_info( MXIT_PLUGIN_ID, "sock_server='%s', http_server='%s', port='%i', cc='%s'\n", session->server, session->http_server, session->port, parts[11] );
-
-	/* save the information (reference: "libpurple/account.h") */
-	purple_account_set_string( session->acc, MXIT_CONFIG_DISTCODE, session->distcode );
-	purple_account_set_string( session->acc, MXIT_CONFIG_CLIENTKEY, session->clientkey );
-	purple_account_set_string( session->acc, MXIT_CONFIG_DIALCODE, session->dialcode );
-	purple_account_set_string( session->acc, MXIT_CONFIG_SERVER_ADDR, session->server );
-	purple_account_set_int( session->acc, MXIT_CONFIG_SERVER_PORT, session->port );
-	purple_account_set_string( session->acc, MXIT_CONFIG_HTTPSERVER, session->http_server );
-
-	/* update the state */
-	state = purple_account_get_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
-	if ( state == MXIT_STATE_REGISTER1 )
-		purple_account_set_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_REGISTER2 );
-
-	/* freeup the memory */
-	g_strfreev( host );
-	g_strfreev( parts );
-
-	if ( state == MXIT_STATE_LOGIN ) {
-		/* now we can continue with the login process */
-		mxit_login_connect( session );
-	}
-	else {
-		/* the user is registering so we need to get more information from him/her first to complete the process */
-		mxit_register_view( session );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Free up the data associated with the Authorization process.
- *
- *  @param data			The data object to free
- */
-static void free_logindata( struct login_data* data )
-{
-	if ( !data )
-		return;
-
-	/* free up the login resources */
-	g_free( data->wapserver );
-	g_free( data->sessionid );
-	g_free( data->captcha );
-	g_free( data->cc );
-	g_free( data->locale );
-	g_free( data );
-}
-
-
-/*------------------------------------------------------------------------
- * This function is called when the user accepts the Authorization form.
- *
- *  @param gc				The connection object
- *  @param fields			The list of fields in the accepted form
- */
-static void mxit_cb_captcha_ok( PurpleConnection* gc, PurpleRequestFields* fields )
-{
-	struct MXitSession*		session	= purple_connection_get_protocol_data( gc );
-	PurpleUtilFetchUrlData*	url_data;
-	PurpleRequestField*		field;
-	const char*				captcha_resp;
-	GList*					entries;
-	GList*					entry;
-	char*					url;
-	int						state;
-
-	/* get the captcha response */
-	captcha_resp = purple_request_fields_get_string( fields, "code" );
-	if ( ( captcha_resp == NULL ) || ( captcha_resp[0] == '\0' ) ) {
-		/* the user did not fill in the captcha */
-		mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Error" ), _( "You did not enter the security code" ) );
-		free_logindata( session->logindata );
-		purple_account_disconnect( session->acc );
-		return;
-	}
-
-	/* get chosen country */
-	field = purple_request_fields_get_field( fields, "country" );
-	entries = purple_request_field_list_get_selected( field );
-	entry = g_list_first( entries );
-	session->logindata->cc = purple_request_field_list_get_data( field, entry->data );
-	purple_account_set_string( session->acc, MXIT_CONFIG_COUNTRYCODE, session->logindata->cc );
-
-	/* get chosen language */
-	field = purple_request_fields_get_field( fields, "locale" );
-	entries = purple_request_field_list_get_selected( field );
-	entry = g_list_first( entries );
-	session->logindata->locale = purple_request_field_list_get_data( field, entry->data );
-	purple_account_set_string( session->acc, MXIT_CONFIG_LOCALE, session->logindata->locale );
-
-#ifdef	DEBUG_PROTOCOL
-	purple_debug_info( MXIT_PLUGIN_ID, "cc='%s', locale='%s', captcha='%s'\n", session->logindata->cc, session->logindata->locale, captcha_resp );
-#endif
-
-	/* get state */
-	state = purple_account_get_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
-
-	url = g_strdup_printf( "%s?type=getpid&sessionid=%s&login=%s&ver=%i.%i.%i&clientid=%s&cat=%s&chalresp=%s&cc=%s&loc=%s&path=%i&brand=%s&model=%s&h=%i&w=%i&ts=%li",
-			session->logindata->wapserver,
-			session->logindata->sessionid,
-			purple_url_encode( purple_account_get_username( session->acc ) ),
-			PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION,
-			MXIT_CLIENT_ID,
-			MXIT_CP_ARCH,
-			captcha_resp,
-			session->logindata->cc,
-			session->logindata->locale,
-			( state == MXIT_STATE_REGISTER1 ) ? 0 : 1,
-			MXIT_CP_PLATFORM,
-			MXIT_CP_OS,
-			MXIT_CAPTCHA_HEIGHT,
-			MXIT_CAPTCHA_WIDTH,
-			time( NULL )
-	);
-	url_data = purple_util_fetch_url_request( url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, mxit_cb_clientinfo2, session );
-	if ( url_data )
-		session->async_calls = g_slist_prepend( session->async_calls, url_data );
-
-#ifdef	DEBUG_PROTOCOL
-	purple_debug_info( MXIT_PLUGIN_ID, "HTTP REQUEST: '%s'\n", url );
-#endif
-	g_free( url );
-
-	/* free up the login resources */
-	free_logindata( session->logindata );
-}
-
-
-/*------------------------------------------------------------------------
- * This function is called when the user cancels the Authorization form.
- *
- *  @param gc				The connection object
- *  @param fields			The list of fields in the cancelled form
- */
-static void mxit_cb_captcha_cancel( PurpleConnection* gc, PurpleRequestFields* fields )
-{
-	struct MXitSession*		session	= purple_connection_get_protocol_data( gc );
-
-	/* free up the login resources */
-	free_logindata( session->logindata );
-
-	/* we cannot continue, so we disconnect this account */
-	purple_account_disconnect( session->acc );
-}
-
-
-/*------------------------------------------------------------------------
- * Callback function invoked once the client information has been retrieved from
- * the MXit WAP site.  Display page where user can select their authorization information.
- *
- *  @param url_data			libPurple internal object (see purple_util_fetch_url_request)
- *  @param user_data		The MXit session object
- *  @param url_text			The data returned from the WAP site
- *  @param len				The length of the data returned
- *  @param error_message	Descriptive error message
- */
-static void mxit_cb_clientinfo1( PurpleUtilFetchUrlData* url_data, gpointer user_data, const gchar* url_text, gsize len, const gchar* error_message )
-{
-	struct MXitSession*			session		= (struct MXitSession*) user_data;
-	struct login_data*			logindata;
-	PurpleRequestFields*		fields;
-	PurpleRequestFieldGroup*	group		= NULL;
-	PurpleRequestField*			field		= NULL;
-	gchar**						parts;
-	gchar**						countries;
-	gchar**						locales;
-	int							i;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_clientinfo_cb1\n" );
-
-#ifdef	DEBUG_PROTOCOL
-	purple_debug_info( MXIT_PLUGIN_ID, "RESPONSE: %s\n", url_text );
-#endif
-
-	/* remove request from the async outstanding calls list */
-	session->async_calls = g_slist_remove( session->async_calls, url_data );
-
-	if ( !url_text ) {
-		/* no reply from the WAP site */
-		purple_connection_error( session->con, _( "Error contacting the MXit WAP site. Please try again later." ) );
-		return;
-	}
-
-	/* explode the response from the WAP site into an array */
-	parts = g_strsplit( url_text, ";", 15 );
-
-	if ( ( !parts ) || ( parts[0][0] != '0' ) ) {
-		/* server could not find the user */
-		purple_connection_error( session->con, _( "MXit is currently unable to process the request. Please try again later." ) );
-		return;
-	}
-
-	/* save received settings */
-	logindata = g_new0( struct login_data, 1 );
-	logindata->wapserver = g_strdup( parts[1] );
-	logindata->sessionid = g_strdup( parts[2] );
-	session->logindata = logindata;
-
-	/* now generate the popup requesting the user for action */
-
-	fields = purple_request_fields_new();
-	group = purple_request_field_group_new( NULL );
-	purple_request_fields_add_group( fields, group );
-
-	/* add the captcha */
-	logindata->captcha = purple_base64_decode( parts[3], &logindata->captcha_size );
-	field = purple_request_field_image_new( "captcha", _( "Security Code" ), (gchar*) logindata->captcha, logindata->captcha_size );
-	purple_request_field_group_add_field( group, field );
-
-	/* ask for input (required) */
-	field = purple_request_field_string_new( "code", _( "Enter Security Code" ), NULL, FALSE );
-	purple_request_field_set_required( field, TRUE );
-	purple_request_field_group_add_field( group, field );
-
-	/* choose your country, but be careful, we already know your IP! ;-) */
-	countries = g_strsplit( parts[4], ",", 500 );
-	field = purple_request_field_list_new( "country", _( "Your Country" ) );
-	purple_request_field_list_set_multi_select( field, FALSE );
-	for ( i = 0; countries[i]; i++ ) {
-		gchar**		country;
-
-		country = g_strsplit( countries[i], "|", 2 );
-		if ( !country ) {
-			/* oops, this is not good, time to bail */
-			break;
-		}
-		purple_request_field_list_add( field, country[1], g_strdup( country[0] ) );
-		if ( strcmp( country[1], parts[6] ) == 0 ) {
-			/* based on the user's IP, this is his current country code, so we default to it */
-			purple_request_field_list_add_selected( field, country[1] );
-		}
-		g_strfreev( country );
-	}
-	purple_request_field_group_add_field( group, field );
-
-	/* choose your language */
-	locales = g_strsplit( parts[5], ",", 200 );
-	field = purple_request_field_list_new( "locale", _( "Your Language" ) );
-	purple_request_field_list_set_multi_select( field, FALSE );
-	for ( i = 0; locales[i]; i++ ) {
-		gchar**		locale;
-
-		locale = g_strsplit( locales[i], "|", 2 );
-		if ( !locale ) {
-			/* oops, this is not good, time to bail */
-			break;
-		}
-		purple_request_field_list_add( field, locale[1], g_strdup( locale[0] ) );
-		g_strfreev( locale );
-	}
-	purple_request_field_list_add_selected( field, "English" );
-	purple_request_field_group_add_field( group, field );
-
-	/* display the form to the user and wait for his/her input */
-	purple_request_fields( session->con, "MXit", _( "MXit Authorization" ), _( "MXit account validation" ), fields,
-			_( "Continue" ), G_CALLBACK( mxit_cb_captcha_ok ), _( "Cancel" ), G_CALLBACK( mxit_cb_captcha_cancel ), session->acc, NULL, NULL, session->con );
-
-	/* freeup the memory */
-	g_strfreev( parts );
-}
-
-
-/*------------------------------------------------------------------------
- * Initiate a request for the client information (distribution code, client key, etc)
- *  required for logging in from the MXit WAP site.
- *
- *  @param session		The MXit session object
- */
-static void get_clientinfo( struct MXitSession* session )
-{
-	PurpleUtilFetchUrlData*	url_data;
-	const char*				wapserver;
-	char*					url;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "get_clientinfo\n" );
-
-	purple_connection_update_progress( session->con, _( "Retrieving User Information..." ), 0, 4 );
-
-	/* get the WAP site as was configured by the user in the advanced settings */
-	wapserver = purple_account_get_string( session->acc, MXIT_CONFIG_WAPSERVER, DEFAULT_WAPSITE );
-
-	/* reference: "libpurple/util.h" */
-	url = g_strdup_printf( "%s/res/?type=challenge&getcountries=true&getlanguage=true&getimage=true&h=%i&w=%i&ts=%li", wapserver, MXIT_CAPTCHA_HEIGHT, MXIT_CAPTCHA_WIDTH, time( NULL ) );
-	url_data = purple_util_fetch_url_request( url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, mxit_cb_clientinfo1, session );
-	if ( url_data )
-		session->async_calls = g_slist_prepend( session->async_calls, url_data );
-
-#ifdef	DEBUG_PROTOCOL
-	purple_debug_info( MXIT_PLUGIN_ID, "HTTP REQUEST: '%s'\n", url );
-#endif
-	g_free( url );
-}
-
-
-/*------------------------------------------------------------------------
- * Log the user into MXit.
- *
- *  @param account		The account object
- */
-void mxit_login( PurpleAccount* account )
-{
-	struct MXitSession*		session		= NULL;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_login\n" );
-
-	/* create and save a new mxit session */
-	session = mxit_create_object( account );
-
-	/*
-	 * before we can login we need to have a valid distribution code and client key for authentication.
-	 * if we don't have any info saved from a previous login, we need to get it from the MXit WAP site.
-	 * we do cache it, so this step is only done on the very first login for each account.
-	 */
-	if ( strlen( session->distcode ) == 0 ) {
-		/* this must be the very first login, so we need to retrieve the user information */
-		get_clientinfo( session );
-	}
-	else {
-		/* we can continue with the login */
-		mxit_login_connect( session );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Perform a reconnect to the MXit server, and maintain same session object.
- *
- *  @param account		The account object
- */
-void mxit_reconnect( struct MXitSession* session )
-{
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_reconnect\n" );
-
-	/* remove the input cb function */
-	if ( session->con->inpa ) {
-		purple_input_remove( session->con->inpa );
-		session->con->inpa = 0;
-	}
-
-	/* close existing connection */
-	session->flags &= ~MXIT_FLAG_CONNECTED;
-	purple_proxy_connect_cancel_with_handle( session->con );
-
-	/* perform the re-connect */
-	mxit_login_connect( session );
-}
-
-
-/*------------------------------------------------------------------------
- * Register a new account with MXit
- *
- * @param acc		The account object
- */
-void mxit_register( PurpleAccount* account )
-{
-	struct MXitSession*		session		= NULL;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_register\n" );
-
-	/* create and save a new mxit session */
-	session = mxit_create_object( account );
-	purple_account_set_int( account, MXIT_CONFIG_STATE, MXIT_STATE_REGISTER1 );
-
-	get_clientinfo( session );
-}
-
--- a/libpurple/protocols/mxit/login.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *				-- MXit user login functionality --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * 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		_MXIT_LOGIN_H_
-#define		_MXIT_LOGIN_H_
-
-
-struct login_data {
-	char*		wapserver;			/* direct WAP server for postback */
-	char*		sessionid;			/* unique session id */
-	guchar*		captcha;			/* actual captcha (PNG) */
-	gsize		captcha_size;		/* captcha size */
-	char*		cc;					/* country code */
-	char*		locale;				/* locale (language) */
-};
-
-
-void mxit_login( PurpleAccount* account );
-void mxit_register( PurpleAccount* account );
-void mxit_reconnect( struct MXitSession* session );
-
-
-#endif		/* _MXIT_LOGIN_H_ */
--- a/libpurple/protocols/mxit/markup.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1264 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *			-- convert between MXit and libPurple markup --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include	"internal.h"
-#include	"debug.h"
-
-#include	"protocol.h"
-#include	"mxit.h"
-#include	"markup.h"
-#include	"chunk.h"
-#include	"formcmds.h"
-#include	"roster.h"
-
-
-/* define this to enable emoticon (markup) debugging */
-#undef		MXIT_DEBUG_EMO
-/* define this to enable markup conversion debugging */
-#undef		MXIT_DEBUG_MARKUP
-
-
-#define		MXIT_FRAME_MAGIC		"MXF\x01"			/* mxit emoticon magic number */
-#define		MXIT_MAX_EMO_ID			16					/* maximum emoticon ID length */
-#define		COLORCODE_LEN			6					/* colour code ID length */
-
-
-/* HTML tag types */
-#define		MXIT_TAG_COLOR			0x01				/* font color tag */
-#define		MXIT_TAG_SIZE			0x02				/* font size tag */
-#define		MXIT_MAX_MSG_TAGS		90					/* maximum tags per message (pigdin hack work around) */
-
-/*
- * a HTML tag object
- */
-struct tag {
-	char	type;
-	char*	value;
-};
-
-
-#define		MXIT_VIBE_MSG_COLOR			"#9933FF"
-#define		MXIT_FAREWELL_MSG_COLOR		"#949494"
-
-
-/* vibes */
-static const char*	vibes[] = {
-	/* 0 */		N_( "Cool Vibrations" ),
-	/* 1 */		N_( "Purple Rain" ),
-	/* 2 */		N_( "Polite" ),
-	/* 3 */		N_( "Rock n Roll" ),
-	/* 4 */		N_( "Summer Slumber" ),
-	/* 5 */		N_( "Electric Razor" ),
-	/* 6 */		N_( "S.O.S" ),
-	/* 7 */		N_( "Jack Hammer" ),
-	/* 8 */		N_( "Bumble Bee" ),
-	/* 9 */		N_( "Ripple" )
-};
-
-
-
-#ifdef	MXIT_DEBUG_EMO
-/*------------------------------------------------------------------------
- * Dump a byte buffer as hexadecimal to the console for debugging purposes.
- *
- *  @param buf				The data to dump
- *  @param len				The length of the data
- */
-static void hex_dump( const gchar* buf, int len )
-{
-	char		msg[256];
-	int			pos;
-	int			i;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "Dumping data (%i bytes)\n", len );
-
-	memset( msg, 0x00, sizeof( msg ) );
-	pos = 0;
-
-	for ( i = 0; i < len; i++ ) {
-
-		if ( pos == 0 )
-			pos += sprintf( &msg[pos], "%04i:  ", i );
-
-		pos += sprintf( &msg[pos], "0x%02X ", buf[i] );
-
-		if ( i % 16 == 15 ) {
-			pos += sprintf( &msg[pos], "\n" );
-			purple_debug_info( MXIT_PLUGIN_ID, "%s", msg );
-			pos = 0;
-		}
-		else if ( i % 16 == 7 )
-			pos += sprintf( &msg[pos], " " );
-	}
-
-	if ( pos > 0 ) {
-		pos += sprintf( &msg[pos], "\n" );
-		purple_debug_info( MXIT_PLUGIN_ID, "%s", msg );
-		pos = 0;
-	}
-}
-#endif
-
-
-/*------------------------------------------------------------------------
- * Adds a link to a message
- *
- *  @param mx				The Markup message object
- *	@param replydata		This is the what will be returned when the link gets clicked
- *	@param isStructured		Indicates that the reply is a structured reply
- *	@param displaytext		This is the text for the link which will be displayed in the UI
- */
-void mxit_add_html_link( struct RXMsgData* mx, const char* replydata, gboolean isStructured, const char* displaytext )
-{
-#ifdef	MXIT_LINK_CLICK
-	gchar*	link	= NULL;
-	gchar*	link64	= NULL;
-
-	/*
-	 * The link content is encoded as follows:
-	 *  MXIT_LINK_KEY | ACCOUNT_USER | ACCOUNT_PROTO | REPLY_TO | REPLY_FORMAT | REPLY_DATA
-	 */
-	link = g_strdup_printf( "%s|%s|%s|%s|%i|%s",
-			MXIT_LINK_KEY,
-			purple_account_get_username( mx->session->acc ),
-			purple_account_get_protocol_id( mx->session->acc ),
-			mx->from,
-			isStructured ? 1 : 0,
-			replydata );
-	link64 = purple_base64_encode( (const unsigned char*) link, strlen( link ) );
-
-	g_string_append_printf( mx->msg, "<a href=\"%s%s\">%s</a>", MXIT_LINK_PREFIX, link64, displaytext );
-
-	g_free( link64 );
-	g_free( link );
-#else
-	g_string_append_printf( mx->msg, "<b>%s</b>", replydata );
-#endif
-}
-
-
-/*------------------------------------------------------------------------
- * Extract an ASN.1 formatted length field from the data.
- *
- *  @param data				The source data
- *  @param data_len			Length of data
- *  @param size				The extracted length
- *  @return					The number of bytes extracted
- */
-static unsigned int asn_getlength( const gchar* data, gsize data_len, int* size )
-{
-	unsigned int	len		= 0;
-	unsigned char	bytes;
-	unsigned char	byte;
-	int				i;
-
-	if ( data_len < 1 ) {
-		/* missing first byte! */
-		return -1;
-	}
-
-	/* first byte specifies the number of bytes in the length */
-	bytes = ( data[0] & ~0x80 );
-	if ( bytes > sizeof( unsigned int ) ) {
-		/* file too big! */
-		return -1;
-	}
-	data++;
-
-	if ( data_len - 1 < bytes ) {
-		/* missing length! */
-		return -1;
-	}
-
-	/* parse out the actual length */
-	for ( i = 0; i < bytes; i++ ) {
-		byte = data[i];
-		len <<= 8;
-		len += byte;
-	}
-
-	*size = len;
-	return bytes + 1;
-}
-
-
-/*------------------------------------------------------------------------
- * Extract an ASN.1 formatted UTF-8 string field from the data.
- *
- *  @param data				The source data
- *  @param data_len			Length of data
- *  @param type				Expected type of string
- *  @param utf8				The extracted string.  Must be deallocated by caller.
- *  @return					The number of bytes extracted
- */
-static int asn_getUtf8( const gchar* data, gsize data_len, gchar type, char** utf8 )
-{
-	unsigned int len;
-	gchar *out_str;
-
-	if ( data_len < 2 ) {
-		/* missing type or length! */
-		return -1;
-	}
-
-	/* validate the field type [1 byte] */
-	if ( data[0] != type ) {
-		/* this is not a utf-8 string! */
-		purple_debug_error( MXIT_PLUGIN_ID, "Invalid UTF-8 encoded string in ASN data (got 0x%02X, expected 0x%02X)\n", data[0], type );
-		return -1;
-	}
-
-	len = (guint8)data[1]; /* length field [1 byte] */
-	if ( data_len - 2 < len ) {
-		/* not enough bytes left in data! */
-		return -1;
-	}
-
-	out_str = g_malloc(len + 1);
-	memcpy(out_str, &data[2], len); /* data field */
-	out_str[len] = '\0';
-
-	*utf8 = out_str;
-
-	return ( len + 2 );
-}
-
-
-/*------------------------------------------------------------------------
- * Free data associated with a Markup message object.
- *
- *  @param mx				The Markup message object
- */
-static void free_markupdata( struct RXMsgData* mx )
-{
-	if ( mx ) {
-		if ( mx->msg )
-			g_string_free( mx->msg, TRUE );
-		if ( mx->from )
-			g_free( mx->from );
-		g_free( mx );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Split the message into smaller messages and send them one at a time
- * to pidgin to be displayed on the UI
- *
- *  @param mx				The received message object
- */
-static void mxit_show_split_message( struct RXMsgData* mx )
-{
-	GString*		msg		= NULL;
-	char*			ch		= NULL;
-	unsigned int	pos		= 0;
-	unsigned int	start	= 0;
-	unsigned int	l_nl	= 0;
-	unsigned int	l_sp	= 0;
-	unsigned int	l_gt	= 0;
-	unsigned int	stop	= 0;
-	int				tags	= 0;
-	gboolean		intag	= FALSE;
-
-	/*
-	 * awful hack to work around the awful hack in pidgin to work around GtkIMHtml's
-	 * inefficient rendering of messages with lots of formatting changes.
-	 * (reference: see the function pidgin_conv_write_conv() in gtkconv.c) the issue
-	 * is that when you have more than 100 '<' characters in the message passed to
-	 * pidgin, none of the markup (including links) are rendered and thus just dump
-	 * all the text as is to the conversation window. this message dump is very
-	 * confusing and makes it totally unusable. to work around this we will count
-	 * the amount of tags and if its more than the pidgin threshold, we will just
-	 * break the message up into smaller parts and send them separately to pidgin.
-	 * to the user it will look like multiple messages, but at least he will be able
-	 * to use and understand it.
-	 */
-
-	ch = mx->msg->str;
-	pos = start;
-	while ( ch[pos] ) {
-
-		if ( ch[pos] == '<' ) {
-			tags++;
-			intag = TRUE;
-		}
-		else if ( ch[pos] == '\n' ) {
-			l_nl = pos;
-		}
-		else if ( ch[pos] == '>' ) {
-			l_gt = pos;
-			intag = FALSE;
-		}
-		else if ( ch[pos] == ' ' ) {
-			/* ignore spaces inside tags */
-			if ( !intag )
-				l_sp = pos;
-		}
-		else if ( ( ch[pos] == 'w' ) && ( pos + 4 < mx->msg->len ) && ( memcmp( &ch[pos], "www.", 4 ) == 0 ) ) {
-			tags += 2;
-		}
-		else if ( ( ch[pos] == 'h' ) && ( pos + 8 < mx->msg->len ) && ( memcmp( &ch[pos], "http://", 7 ) == 0 ) ) {
-			tags += 2;
-		}
-
-		if ( tags > MXIT_MAX_MSG_TAGS ) {
-			/* we have reached the maximum amount of tags pidgin (gtk) can handle per message.
-			   so its time to send what we have and then start building a new message */
-
-			/* now find the right place to break the message */
-			if ( l_nl > start ) {
-				/* break at last '\n' char */
-				stop = l_nl;
-				ch[stop] = '\0';
-				msg = g_string_new( &ch[start] );
-				ch[stop] = '\n';
-			}
-			else if ( l_sp > start ) {
-				/* break at last ' ' char */
-				stop = l_sp;
-				ch[stop] = '\0';
-				msg = g_string_new( &ch[start] );
-				ch[stop] = ' ';
-			}
-			else {
-				/* break at the last '>' char */
-				char t;
-				stop = l_gt + 1;
-				t = ch[stop];
-				ch[stop] = '\0';
-				msg = g_string_new( &ch[start] );
-				ch[stop] = t;
-				stop--;
-			}
-
-			/* push message to pidgin */
-			serv_got_im( mx->session->con, mx->from, msg->str, mx->flags, mx->timestamp );
-			g_string_free( msg, TRUE );
-			msg = NULL;
-
-			/* next part need this flag set */
-			mx->flags |= PURPLE_MESSAGE_RAW;
-
-			tags = 0;
-			start = stop + 1;
-			pos = start;
-		}
-		else
-			pos++;
-	}
-
-	if ( start != pos ) {
-		/* send the last part of the message */
-
-		/* build the string */
-		ch[pos] = '\0';
-		msg = g_string_new( &ch[start] );
-		ch[pos] = '\n';
-
-		/* push message to pidgin */
-		serv_got_im( mx->session->con, mx->from, msg->str, mx->flags, mx->timestamp );
-		g_string_free( msg, TRUE );
-		msg = NULL;
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Insert custom emoticons and inline images into the message (if there
- * are any), then give the message to the UI to display to the user.
- *
- *  @param mx				The received message object
- */
-void mxit_show_message( struct RXMsgData* mx )
-{
-	char*				pos;
-	int					start;
-	unsigned int		end;
-	int					emo_ofs;
-	char*				ii;
-	char				tag[64];
-	int*				img_id;
-
-	if ( mx->got_img ) {
-		/* search and replace all emoticon tags with proper image tags */
-
-		while ( ( pos = strstr( mx->msg->str, MXIT_II_TAG ) ) != NULL ) {
-			start = pos - mx->msg->str;					/* offset at which MXIT_II_TAG starts */
-			emo_ofs = start + strlen( MXIT_II_TAG );	/* offset at which EMO's ID starts */
-			end = emo_ofs + 1;							/* offset at which MXIT_II_TAG ends */
-
-			while ( ( end < mx->msg->len ) && ( mx->msg->str[end] != '>' ) )
-				end++;
-
-			if ( end == mx->msg->len )			/* end of emoticon tag not found */
-				break;
-
-			ii = g_strndup( &mx->msg->str[emo_ofs], end - emo_ofs );
-
-			/* remove inline image tag */
-			g_string_erase( mx->msg, start, ( end - start ) + 1 );
-
-			/* find the image entry */
-			img_id = (int*) g_hash_table_lookup( mx->session->iimages, ii );
-			if ( !img_id ) {
-				/* inline image not found, so we will just skip it */
-				purple_debug_error( MXIT_PLUGIN_ID, "inline image NOT found (%s)\n", ii );
-			}
-			else {
-				/* insert img tag */
-				g_snprintf( tag, sizeof( tag ), "<img id=\"%i\">", *img_id );
-				g_string_insert( mx->msg, start, tag );
-			}
-
-			g_free( ii );
-		}
-	}
-
-#ifdef MXIT_DEBUG_MARKUP
-	purple_debug_info( MXIT_PLUGIN_ID, "Markup RX (converted): '%s'\n", mx->msg->str );
-#endif
-
-	if ( mx->processed ) {
-		/* this message has already been taken care of, so just ignore it here */
-	}
-	else if ( mx->chatid < 0 ) {
-		/* normal chat message */
-		mxit_show_split_message( mx );
-	}
-	else {
-		/* this is a multimx message */
-		serv_got_chat_in( mx->session->con, mx->chatid, mx->from, mx->flags, mx->msg->str, mx->timestamp);
-	}
-
-	/* freeup resource */
-	free_markupdata( mx );
-}
-
-
-/*------------------------------------------------------------------------
- * Extract the custom emoticon ID from the message.
- *
- *  @param message			The input data
- *  @param emid				The extracted emoticon ID
- */
-static void parse_emoticon_str( const char* message, char* emid )
-{
-	int		i;
-
-	for ( i = 0; ( message[i] != '\0' && message[i] != '}' && i < MXIT_MAX_EMO_ID ); i++ ) {
-		emid[i] = message[i];
-	}
-
-	if ( message[i] == '\0' ) {
-		/* end of message reached, ignore the tag */
-		emid[0] = '\0';
-	}
-	else if ( i == MXIT_MAX_EMO_ID ) {
-		/* invalid tag length, ignore the tag */
-		emid[0] = '\0';
-	}
-	else
-		emid[i] = '\0';
-}
-
-
-/*------------------------------------------------------------------------
- * Callback function invoked when a custom emoticon request to the WAP site completes.
- *
- *  @param url_data
- *  @param user_data		The Markup message object
- *  @param url_text			The data returned from the WAP site
- *  @param len				The length of the data returned
- *  @param error_message	Descriptive error message
- */
-static void emoticon_returned( PurpleUtilFetchUrlData* url_data, gpointer user_data, const gchar* url_text, gsize len, const gchar* error_message )
-{
-	struct RXMsgData*	mx			= (struct RXMsgData*) user_data;
-	const gchar*		data		= url_text;
-	unsigned int		pos			= 0;
-	int					id;
-	char*				str;
-	int					em_size		= 0;
-	char*				em_data		= NULL;
-	char*				em_id		= NULL;
-	int*				intptr		= NULL;
-	int					res;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "emoticon_returned\n" );
-
-	/* remove request from the async outstanding calls list */
-	mx->session->async_calls = g_slist_remove( mx->session->async_calls, url_data );
-
-	if ( !url_text ) {
-		/* no reply from the WAP site */
-		purple_debug_error( MXIT_PLUGIN_ID, "Error contacting the MXit WAP site. Please try again later (emoticon).\n" );
-		goto done;
-	}
-
-#ifdef	MXIT_DEBUG_EMO
-	hex_dump( data, len );
-#endif
-
-	/* validate that the returned data starts with the magic constant that indicates it is a custom emoticon */
-	if ( len - pos < strlen( MXIT_FRAME_MAGIC ) || memcmp( MXIT_FRAME_MAGIC, &data[pos], strlen( MXIT_FRAME_MAGIC ) ) != 0 ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad magic)\n" );
-		goto done;
-	}
-	pos += strlen( MXIT_FRAME_MAGIC );
-
-	/* validate the image frame desc byte */
-	if ( data[pos] != '\x6F' ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad frame desc)\n" );
-		goto done;
-	}
-	pos++;
-
-	/* get the frame image data length */
-	res = asn_getlength( &data[pos], len - pos, &em_size );
-	if ( res <= 0 ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad frame length)\n" );
-		goto done;
-	}
-	pos += res;
-#ifdef	MXIT_DEBUG_EMO
-	purple_debug_info( MXIT_PLUGIN_ID, "read the length '%i'\n", em_size );
-#endif
-
-	/* utf-8 (emoticon name) */
-	res = asn_getUtf8( &data[pos], len - pos, 0x0C, &str );
-	if ( res <= 0 ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad name string)\n" );
-		goto done;
-	}
-	pos += res;
-#ifdef	MXIT_DEBUG_EMO
-	purple_debug_info( MXIT_PLUGIN_ID, "read the string '%s'\n", str );
-#endif
-	g_free( str );
-	str = NULL;
-
-	/* utf-8 (emoticon shortcut) */
-	res = asn_getUtf8( &data[pos], len - pos, 0x81, &str );
-	if ( res <= 0 ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad shortcut string)\n" );
-		goto done;
-	}
-	pos += res;
-#ifdef	MXIT_DEBUG_EMO
-	purple_debug_info( MXIT_PLUGIN_ID, "read the string '%s'\n", str );
-#endif
-	em_id = str;
-
-	/* validate the image data type */
-	if ( len - pos < 1 || data[pos] != '\x82' ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad data type)\n" );
-		g_free( em_id );
-		goto done;
-	}
-	pos++;
-
-	/* get the data length */
-	res = asn_getlength( &data[pos], len - pos, &em_size );
-	if ( res <= 0 ) {
-		/* bad frame length */
-		purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad data length)\n" );
-		g_free( em_id );
-		goto done;
-	}
-	pos += res;
-#ifdef	MXIT_DEBUG_EMO
-	purple_debug_info( MXIT_PLUGIN_ID, "read the length '%i'\n", em_size );
-#endif
-
-	if ( len - pos < (gsize)em_size ) {
-		/* not enough bytes left in data! */
-		purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (data length too long)\n");
-		g_free( em_id );
-		goto done;
-	}
-
-	/* strip the mxit markup tags from the emoticon id (eg, .{XY} -> XY) */
-	if ( ( em_id[0] == '.' ) && ( em_id[1] == '{' ) ) {
-		char	emo[MXIT_MAX_EMO_ID + 1];
-
-		parse_emoticon_str( &em_id[2], emo );
-		strcpy( em_id, emo );
-	}
-
-	if ( g_hash_table_lookup( mx->session->iimages, em_id ) ) {
-		/* emoticon found in the table, so ignore this one */
-		g_free( em_id );
-		goto done;
-	}
-
-	/* make a copy of the data */
-	em_data = g_malloc( em_size );
-	memcpy( em_data, &data[pos], em_size );
-
-	/* we now have the emoticon, store it in the imagestore */
-	id = purple_imgstore_add_with_id( em_data, em_size, NULL );
-
-	/* map the mxit emoticon id to purple image id */
-	intptr = g_malloc( sizeof( int ) );
-	*intptr = id;
-	g_hash_table_insert( mx->session->iimages, em_id, intptr );
-
-	mx->flags |= PURPLE_MESSAGE_IMAGES;
-done:
-	mx->img_count--;
-	if ( ( mx->img_count == 0 ) && ( mx->converted ) ) {
-		/*
-		 * this was the last outstanding emoticon for this message,
-		 * so we can now display it to the user.
-		 */
-		mxit_show_message( mx );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Send a request to the MXit WAP site to download the specified emoticon.
- *
- *  @param mx				The Markup message object
- *  @param id				The ID for the emoticon
- */
-static void emoticon_request( struct RXMsgData* mx, const char* id )
-{
-	PurpleUtilFetchUrlData*	url_data;
-	const char*				wapserver;
-	char*					url;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "sending request for emoticon '%s'\n", id );
-
-	wapserver = purple_account_get_string( mx->session->acc, MXIT_CONFIG_WAPSERVER, DEFAULT_WAPSITE );
-
-	/* reference: "libpurple/util.h" */
-	url = g_strdup_printf( "%s/res/?type=emo&mlh=%i&sc=%s&ts=%li", wapserver, MXIT_EMOTICON_SIZE, id, time( NULL ) );
-	url_data = purple_util_fetch_url_request( url, TRUE, NULL, TRUE, NULL, FALSE, emoticon_returned, mx );
-	if ( url_data )
-		mx->session->async_calls = g_slist_prepend( mx->session->async_calls, url_data );
-
-	g_free( url );
-}
-
-
-/*------------------------------------------------------------------------
- * Parse a Vibe command.
- *
- *  @param mx				The Markup message object
- *  @param message			The message text (which contains the vibe)
- *  @return id				The length of the message to skip
- */
-static int mxit_parse_vibe( struct RXMsgData* mx, const char* message )
-{
-	unsigned int	vibeid;
-
-	vibeid = message[2] - '0';
-
-	purple_debug_info( MXIT_PLUGIN_ID, "Vibe received (%i)\n", vibeid );
-
-	if ( vibeid > ( ARRAY_SIZE( vibes ) - 1 ) ) {
-		purple_debug_warning( MXIT_PLUGIN_ID, "Unsupported vibe received (%i)\n", vibeid );
-		/* unsupported vibe */
-		return 0;
-	}
-
-	g_string_append_printf( mx->msg, "<font color=\"%s\"><i>%s Vibe...</i></font>", MXIT_VIBE_MSG_COLOR, _( vibes[vibeid] ) );
-	return 2;
-}
-
-
-/*------------------------------------------------------------------------
- * Extract the nickname from a chatroom message and display it nicely in
- * libPurple-style (HTML) markup.
- *
- *  @param mx				The received message data object
- *  @param message			The message text
- *  @return					The length of the message to skip
- */
-static int mxit_extract_chatroom_nick( struct RXMsgData* mx, char* message, int len, int msgflags )
-{
-	int		i;
-
-	if ( message[0] == '<' ) {
-		/*
-		 * The message MIGHT contains an embedded nickname.  But we can't
-		 * be sure unless we find the end-of-nickname sequence: (>\n)
-		 * Search for it....
-		 */
-		gboolean	found	= FALSE;
-
-		for ( i = 1; i < len; i++ ) {
-			if ( ( message[i] == '\n' ) && ( message[i-1] == '>' ) ) {
-				found = TRUE;
-				message[i-1] = '\0';	/* loose the '>' */
-				i++;					/* and skip the new-line */
-				break;
-			}
-		}
-
-		if ( found ) {
-			gchar*		nickname;
-
-			/*
-			 * The message definitely had an embedded nickname - generate a marked-up
-			 * message to be displayed.
-			 */
-			nickname = g_markup_escape_text( &message[1], -1 );
-
-			/* Remove any MXit escaping from nickname ("\X" --> "X") */
-			if ( msgflags & CP_MSG_MARKUP ) {
-				int	nicklen = strlen( nickname );
-				int	j, k;
-
-				for ( j = 0, k = 0; j < nicklen; j++ ) {
-					if ( nickname[j] == '\\' )
-						j++;
-
-					nickname[k] = nickname[j];
-					k++;
-				}
-
-				nickname[k] = '\0';		/* terminate string */
-			}
-
-			/* add nickname within some BOLD markup to the new converted message */
-			g_string_append_printf( mx->msg, "<b>%s:</b> ", nickname );
-
-			/* free up the resources */
-			g_free( nickname );
-
-			return i;
-		}
-	}
-
-	return 0;
-}
-
-
-
-/*------------------------------------------------------------------------
- * Convert a message containing MXit protocol markup to libPurple-style (HTML) markup.
- *
- *  @param mx				The received message data object
- *  @param message			The message text
- *  @param len				The length of the message
- */
-void mxit_parse_markup( struct RXMsgData* mx, char* message, int len, short msgtype, int msgflags )
-{
-	char		tmpstr1[128];
-	char*		ch;
-	int			i			= 0;
-
-	/* tags */
-	gboolean	tag_bold	= FALSE;
-	gboolean	tag_under	= FALSE;
-	gboolean	tag_italic	= FALSE;
-	int			font_size	= 0;
-
-#ifdef MXIT_DEBUG_MARKUP
-	purple_debug_info( MXIT_PLUGIN_ID, "Markup RX (original): '%s'\n", message );
-#endif
-
-
-	/*
-	 * supported MXit markup:
-	 * '*'			bold
-	 * '_'			underline
-	 * '/'			italics
-	 * '$'			highlight text
-	 * '.+' 		inc font size
-	 * '.-'			dec font size
-	 * '#XXXXXX'	foreground color
-	 * '.{XX}'		custom emoticon
-	 * '\'			escape the following character
-	 * '::'			MXit commands
-	 */
-
-
-	if ( is_mxit_chatroom_contact( mx->session, mx->from ) ) {
-		/* chatroom message, so we need to extract and skip the sender's nickname
-		 * which is embedded inside the message */
-		i = mxit_extract_chatroom_nick( mx, message, len, msgflags );
-	}
-
-	/* run through the message and check for custom emoticons and markup */
-	for ( ; i < len; i++ ) {
-		switch ( message[i] ) {
-
-
-			/* mxit markup parsing */
-			case '*' :
-					if ( !( msgflags & CP_MSG_MARKUP ) ) {
-						g_string_append_c( mx->msg, message[i] );
-						break;
-					}
-
-					/* bold markup */
-					if ( !tag_bold )
-						g_string_append( mx->msg, "<b>" );
-					else
-						g_string_append( mx->msg, "</b>" );
-					tag_bold = !tag_bold;
-					break;
-			case '_' :
-					if ( !( msgflags & CP_MSG_MARKUP ) ) {
-						g_string_append_c( mx->msg, message[i] );
-						break;
-					}
-
-					/* underscore markup */
-					if ( !tag_under )
-						g_string_append( mx->msg, "<u>" );
-					else
-						g_string_append( mx->msg, "</u>" );
-					tag_under = !tag_under;
-					break;
-			case '/' :
-					if ( !( msgflags & CP_MSG_MARKUP ) ) {
-						g_string_append_c( mx->msg, message[i] );
-						break;
-					}
-
-					/* italics markup */
-					if ( !tag_italic )
-						g_string_append( mx->msg, "<i>" );
-					else
-						g_string_append( mx->msg, "</i>" );
-					tag_italic = !tag_italic;
-					break;
-			case '$' :
-					if ( !( msgflags & CP_MSG_MARKUP ) ) {
-						g_string_append_c( mx->msg, message[i] );
-						break;
-					}
-					else if ( i + 1 >= len ) {
-						/* message too short for complete link */
-						g_string_append_c( mx->msg, '$' );
-						break;
-					}
-
-					/* find the end tag */
-					ch = strstr( &message[i + 1], "$" );
-					if ( ch ) {
-						/* end found */
-						*ch = '\0';
-						mxit_add_html_link( mx, &message[i + 1], FALSE, &message[i + 1] );
-						*ch = '$';
-						i += ( ch - &message[i + 1] ) + 1;
-					}
-					else {
-						g_string_append_c( mx->msg, message[i] );
-					}
-					/* highlight text */
-					break;
-			case '#' :
-					if ( !( msgflags & CP_MSG_MARKUP ) ) {
-						g_string_append_c( mx->msg, message[i] );
-						break;
-					}
-					else if ( i + COLORCODE_LEN >= len ) {
-						/* message too short for complete colour code */
-						g_string_append_c( mx->msg, '#' );
-						break;
-					}
-
-					/* foreground (text) color */
-					memcpy( tmpstr1, &message[i + 1], COLORCODE_LEN );
-					tmpstr1[ COLORCODE_LEN ] = '\0';			/* terminate string */
-					if ( strcmp( tmpstr1, "??????" ) == 0 ) {
-						/* need to reset the font */
-						g_string_append( mx->msg, "</font>" );
-						i += COLORCODE_LEN;
-					}
-					else if ( strspn( tmpstr1, "0123456789abcdefABCDEF") == COLORCODE_LEN ) {
-						/* definitely a numeric colour code */
-						g_string_append_printf( mx->msg, "<font color=\"#%s\">", tmpstr1 );
-						i += COLORCODE_LEN;
-					}
-					else {
-						/* not valid colour markup */
-						g_string_append_c( mx->msg, '#' );
-					}
-					break;
-			case '.' :
-					if ( i + 1 >= len ) {
-						/* message too short */
-						g_string_append_c( mx->msg, '.' );
-						break;
-					}
-
-					if ( ( msgflags & CP_MSG_EMOTICON ) && ( message[i+1] == '{' ) ) {
-						/* custom emoticon */
-						if ( i + 2 >= len ) {
-							/* message too short */
-							g_string_append_c( mx->msg, '.' );
-							break;
-						}
-
-						parse_emoticon_str( &message[i+2], tmpstr1 );
-						if ( tmpstr1[0] != '\0' ) {
-							mx->got_img = TRUE;
-
-							if ( g_hash_table_lookup( mx->session->iimages, tmpstr1 ) ) {
-								/* emoticon found in the cache, so we do not have to request it from the WAPsite */
-							}
-							else {
-								/* request emoticon from the WAPsite */
-								mx->img_count++;
-								emoticon_request( mx, tmpstr1 );
-							}
-
-							g_string_append_printf( mx->msg, MXIT_II_TAG"%s>", tmpstr1 );
-							i += strlen( tmpstr1 ) + 2;
-						}
-						else
-							g_string_append_c( mx->msg, '.' );
-					}
-					else if ( ( msgflags & CP_MSG_MARKUP ) && ( message[i+1] == '+' ) ) {
-						/* increment text size */
-						font_size++;
-						g_string_append_printf( mx->msg, "<font size=\"%+i\">", font_size );
-						i++;
-					}
-					else if ( ( msgflags & CP_MSG_MARKUP ) && ( message[i+1] == '-' ) ) {
-						/* decrement text size */
-						font_size--;
-						g_string_append_printf( mx->msg, "<font size=\"%+i\">", font_size );
-						i++;
-					}
-					else
-						g_string_append_c( mx->msg, '.' );
-
-					break;
-			case '\\' :
-					if ( i + 1 >= len ) {
-						/* message too short for an escaped character */
-						g_string_append_c( mx->msg, '\\' );
-					}
-					else {
-						/* ignore the next character, because its been escaped */
-						g_string_append_c( mx->msg, message[i + 1] );
-						i++;
-					}
-					break;
-
-
-			/* command parsing */
-			case ':' :
-					if ( i + 1 >= len ) {
-						/* message too short */
-						g_string_append_c( mx->msg, ':' );
-						break;
-					}
-
-					if ( message[i+1] == '@' ) {
-						/* this is a vibe! */
-						int		size;
-
-						if ( i + 2 >= len ) {
-							/* message too short */
-							g_string_append_c( mx->msg, message[i] );
-							break;
-						}
-
-						size = mxit_parse_vibe( mx, &message[i] );
-						if ( size == 0 )
-							g_string_append_c( mx->msg, message[i] );
-						else
-							i += size;
-					}
-					else if ( msgtype != CP_MSGTYPE_COMMAND ) {
-						/* this is not a command message */
-						g_string_append_c( mx->msg, message[i] );
-					}
-					else if ( message[i+1] == ':' ) {
-						/* parse out the command */
-						int		size;
-
-						size = mxit_parse_command( mx, &message[i] );
-						if ( size == 0 )
-							g_string_append_c( mx->msg, ':' );
-						else
-							i += size;
-					}
-					else {
-						g_string_append_c( mx->msg, ':' );
-					}
-					break;
-
-
-			/* these aren't MXit markup, but are interpreted by libPurple */
-			case '<' :
-					g_string_append( mx->msg, "&lt;" );
-					break;
-			case '>' :
-					g_string_append( mx->msg, "&gt;" );
-					break;
-			case '&' :
-					g_string_append( mx->msg, "&amp;" );
-					break;
-			case '"' :
-					g_string_append( mx->msg, "&quot;" );
-					break;
-
-			default :
-					/* text */
-					g_string_append_c( mx->msg, message[i] );
-					break;
-		}
-	}
-
-	if ( msgflags & CP_MSG_FAREWELL ) {
-		/* this is a farewell message */
-		g_string_prepend( mx->msg, "<font color=\""MXIT_FAREWELL_MSG_COLOR"\"><i>" );
-		g_string_append( mx->msg, "</i></font>" );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Insert an inline image command.
- *
- *  @param mx				The message text as processed so far.
- *  @oaram id				The imgstore ID of the inline image.
- */
-static void inline_image_add( GString* mx, int id )
-{
-	PurpleStoredImage *image;
-	gconstpointer img_data;
-	gsize img_size;
-	gchar* enc;
-
-	image = purple_imgstore_find_by_id( id );
-	if ( image == NULL )
-		return;
-
-	img_data = purple_imgstore_get_data( image );
-	img_size = purple_imgstore_get_size( image );
-
-	enc = purple_base64_encode( img_data, img_size );
-
-	g_string_append( mx, "::op=img|dat=" );
-	g_string_append( mx, enc );
-	g_string_append_c( mx, ':' );
-
-	g_free( enc );
-}
-
-
-/*------------------------------------------------------------------------
- * Convert libpurple (HTML) markup to MXit protocol markup (for sending to MXit).
- * Any MXit markup codes in the original message also need to be escaped.
- *
- *  @param message			The message text containing libPurple (HTML) markup
- *  @return					The message text containing MXit markup
- */
-char* mxit_convert_markup_tx( const char* message, int* msgtype )
-{
-	GString*			mx;
-	struct tag*			tag;
-	GList*				entry;
-	GList*				tagstack	= NULL;
-	char*				reply;
-	int					len			= strlen ( message );
-	int					i;
-
-#ifdef MXIT_DEBUG_MARKUP
-	purple_debug_info( MXIT_PLUGIN_ID, "Markup TX (original): '%s'\n", message );
-#endif
-
-	/*
-	 * libPurple uses the following HTML markup codes:
-	 *   Bold:			<b>...</b>
-	 *   Italics:		<i>...</i>
-	 *   Underline:		<u>...</u>
-	 *   Strikethrough:	<s>...</s>					(NO MXIT SUPPORT)
-	 *   Font size:		<font size="">...</font>
-	 *   Font type:		<font face="">...</font>	(NO MXIT SUPPORT)
-	 *   Font colour:	<font color=#">...</font>
-	 *   Links:			<a href="">...</a>
-	 *   Newline:		<br>
-	 *   Inline image:  <IMG ID="">
-	 * The following characters are also encoded:
-	 *   &amp;  &quot;  &lt;  &gt;
-	 */
-
-	/* new message data */
-	mx = g_string_sized_new( len );
-
-	/* run through the message and check for HTML markup */
-	for ( i = 0; i < len; i++ ) {
-
-		switch ( message[i] ) {
-			case '<' :
-				if ( purple_str_has_prefix( &message[i], "<b>" ) || purple_str_has_prefix( &message[i], "</b>" ) ) {
-					/* bold */
-					g_string_append_c( mx, '*' );
-				}
-				else if ( purple_str_has_prefix( &message[i], "<i>" ) || purple_str_has_prefix( &message[i], "</i>" ) ) {
-					/* italics */
-					g_string_append_c( mx, '/' );
-				}
-				else if ( purple_str_has_prefix( &message[i], "<u>" ) || purple_str_has_prefix( &message[i], "</u>" ) ) {
-					/* underline */
-					g_string_append_c( mx, '_' );
-				}
-				else if ( purple_str_has_prefix( &message[i], "<br>" ) ) {
-					/* newline */
-					g_string_append_c( mx, '\n' );
-				}
-				else if ( purple_str_has_prefix( &message[i], "<font size=" ) ) {
-					/* font size */
-					int fontsize;
-
-					tag = g_new0( struct tag, 1 );
-					tag->type = MXIT_TAG_SIZE;
-					tagstack = g_list_prepend( tagstack, tag );
-					// TODO: implement size control
-					if ( sscanf( &message[i+12], "%i", &fontsize ) ) {
-						purple_debug_info( MXIT_PLUGIN_ID, "Font size set to %i\n", fontsize );
-					}
-				}
-				else if ( purple_str_has_prefix( &message[i], "<font color=" ) ) {
-					/* font colour */
-					char color[8];
-
-					/* ensure we have the complete tag: <font color="#123456"> */
-					if ( i + 20 < len ) {
-						tag = g_new0( struct tag, 1 );
-						tag->type = MXIT_TAG_COLOR;
-						tagstack = g_list_append( tagstack, tag );
-
-						memset( color, 0x00, sizeof( color ) );
-						memcpy( color, &message[i + 13], 7 );
-						g_string_append( mx, color );
-					}
-				}
-				else if ( purple_str_has_prefix( &message[i], "</font>" ) ) {
-					/* end of font tag */
-					entry = g_list_last( tagstack );
-					if ( entry ) {
-						tag = entry->data;
-						if ( tag->type == MXIT_TAG_COLOR ) {
-							/* font color reset */
-							g_string_append( mx, "#??????" );
-						}
-						else if ( tag->type == MXIT_TAG_SIZE ) {
-							/* font size */
-							// TODO: implement size control
-						}
-						tagstack = g_list_remove( tagstack, tag );
-						g_free( tag );
-					}
-				}
-				else if ( purple_str_has_prefix( &message[i], "<IMG ID=" ) ) {
-					/* inline image */
-					int imgid;
-
-					if ( sscanf( &message[i+9], "%i", &imgid ) ) {
-						inline_image_add( mx, imgid );
-						*msgtype = CP_MSGTYPE_COMMAND;		/* inline image must be sent as a MXit command */
-					}
-				}
-
-				/* skip to end of tag ('>') */
-				for ( i++; ( i < len ) && ( message[i] != '>' ) ; i++ );
-
-				break;
-
-			case '*' :	/* MXit bold */
-			case '_' :	/* MXit underline */
-			case '/' :	/* MXit italic */
-			case '#' :	/* MXit font color */
-			case '$' :	/* MXit highlight text */
-			case '\\' :	/* MXit escape backslash */
-				g_string_append( mx, "\\" );				/* escape character */
-				g_string_append_c( mx, message[i] );		/* character to escape */
-				break;
-
-			case '.' : /* might be a MXit font size change, or custom emoticon */
-				if ( i + 1 < len ) {
-					if ( ( message[i+1] == '+' ) || ( message[i+1] == '-' ) )
-						g_string_append( mx, "\\." );		/* escape "." */
-					else
-						g_string_append_c( mx, '.' );
-				}
-				else
-					g_string_append_c( mx, '.' );
-				break;
-
-			default:
-				g_string_append_c( mx, message[i] );
-				break;
-		}
-	}
-
-	/* unescape HTML entities to their literal characters (reference: "libpurple/utils.h") */
-	reply = purple_unescape_html( mx->str );
-
-	g_string_free( mx, TRUE );
-
-#ifdef MXIT_DEBUG_MARKUP
-	purple_debug_info( MXIT_PLUGIN_ID, "Markup TX (converted): '%s'\n", reply );
-#endif
-
-	return reply;
-}
-
-
-/*------------------------------------------------------------------------
- * Free an emoticon entry.
- *
- *  @param key				MXit emoticon ID
- *  @param value			Imagestore ID for emoticon
- *  @param user_data		NULL (unused)
- *  @return					TRUE
- */
-static gboolean emoticon_entry_free( gpointer key, gpointer value, gpointer user_data )
-{
-	int* imgid = value;
-
-	/* key is a string */
-	g_free( key );
-
-	/* value is 'id' in imagestore */
-	purple_imgstore_unref_by_id( *imgid );
-	g_free( value );
-
-	return TRUE;
-}
-
-
-/*------------------------------------------------------------------------
- * Free all entries in the emoticon cache.
- *
- *  @param session			The MXit session object
- */
-void mxit_free_emoticon_cache( struct MXitSession* session )
-{
-	g_hash_table_foreach_remove( session->iimages, emoticon_entry_free, NULL );
-	g_hash_table_destroy ( session->iimages );
-}
--- a/libpurple/protocols/mxit/markup.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *			-- convert between MXit and libPurple markup --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * 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		_MXIT_MARKUP_H_
-#define		_MXIT_MARKUP_H_
-
-#define		MXIT_II_TAG				"<MXII="			/* inline image placeholder string */
-
-
-void mxit_parse_markup( struct RXMsgData* mx, char* message, int len, short msgtype, int msgflags );
-char* mxit_convert_markup_tx( const char* message, int* msgtype );
-void mxit_add_html_link( struct RXMsgData* mx, const char* replydata, gboolean isStructured, const char* displaytext );
-void mxit_show_message( struct RXMsgData* mx );
-
-void mxit_free_emoticon_cache( struct MXitSession* session );
-
-
-#endif		/* _MXIT_MARKUP_H_ */
--- a/libpurple/protocols/mxit/multimx.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,648 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *						-- MultiMx GroupChat --
- *
- *				Andrew Victor	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-
-#include "protocol.h"
-#include "mxit.h"
-#include "multimx.h"
-#include "markup.h"
-
-
-#if 0
-static void multimx_dump(struct multimx* multimx)
-{
-	purple_debug_info(MXIT_PLUGIN_ID, "MultiMX:\n");
-	purple_debug_info(MXIT_PLUGIN_ID, "  Chat ID: %i\n", multimx->chatid);
-	purple_debug_info(MXIT_PLUGIN_ID, "  Username: %s\n", multimx->roomid);
-	purple_debug_info(MXIT_PLUGIN_ID, "  Alias: %s\n", multimx->roomname);
-	purple_debug_info(MXIT_PLUGIN_ID, "  State: %i\n", multimx->state);
-}
-#endif
-
-
-/*------------------------------------------------------------------------
- * Find a MultiMx session based on libpurple chatID.
- *
- *  @param session		The MXit session object
- *  @param id			The libpurple group-chat ID
- *  @return				The MultiMX room object (or NULL if not found)
- */
-static struct multimx* find_room_by_id(struct MXitSession* session, int id)
-{
-	GList* x = session->rooms;
-
-	while (x != NULL) {
-		struct multimx* multimx = (struct multimx *) x->data;
-
-		if (multimx->chatid == id)
-			return multimx;
-
-		x = g_list_next(x);
-	}
-
-	return NULL;
-}
-
-
-/*------------------------------------------------------------------------
- * Find a MultiMx session based on Alias
- *
- *  @param session		The MXit session object
- *  @param roomname		The UI room-name
- *  @return				The MultiMX room object (or NULL if not found)
- */
-static struct multimx* find_room_by_alias(struct MXitSession* session, const char* roomname)
-{
-	GList* x = session->rooms;
-
-	while (x != NULL) {
-		struct multimx* multimx = (struct multimx *) x->data;
-
-		if (!strcmp(multimx->roomname, roomname))
-			return multimx;
-
-		x = g_list_next(x);
-	}
-
-	return NULL;
-}
-
-
-/*------------------------------------------------------------------------
- * Find a MultiMx session based on Username (MXit RoomId)
- *
- *  @param session		The MXit session object
- *  @param username		The MXit RoomID (MultiMX contact username)
- *  @return				The MultiMX room object (or NULL if not found)
- */
-static struct multimx* find_room_by_username(struct MXitSession* session, const char* username)
-{
-	GList* x = session->rooms;
-
-	while (x != NULL) {
-		struct multimx* multimx = (struct multimx *) x->data;
-
-		if (!strcmp(multimx->roomid, username))
-			return multimx;
-
-		x = g_list_next(x);
-	}
-
-	return NULL;
-}
-
-
-/*------------------------------------------------------------------------
- * Create a GroupChat room, and add to list of rooms.
- *
- *  @param session		The MXit session object
- *  @param roomid		The MXit RoomID (MultiMX contact username)
- *  @param roomname		The UI room-name
- *  @param state		The initial state of the room (see multimx.h)
- *  @return				The MultiMX room object
- */
-static struct multimx* room_create(struct MXitSession* session, const char* roomid, const char* roomname, short state)
-{
-	struct multimx* multimx = NULL;
-	static int groupchatID = 1;
-
-	purple_debug_info(MXIT_PLUGIN_ID, "Groupchat create - roomid='%s' roomname='%s'\n", roomid, roomname);
-
-	/* Create a new GroupChat */
-	multimx = g_new0(struct multimx, 1);
-
-	/* Initialize groupchat */
-	g_strlcpy(multimx->roomid, roomid, sizeof(multimx->roomid));
-	g_strlcpy(multimx->roomname, roomname, sizeof(multimx->roomname));
-	multimx->chatid = groupchatID++;
-	multimx->state = state;
-
-	/* determine our nickname (from profile) */
-	if (session->profile && (session->profile->nickname[0] != '\0'))
-		multimx->nickname = g_strdup(session->profile->nickname);
-
-	/* Add to GroupChat list */
-	session->rooms = g_list_append(session->rooms, multimx);
-
-	return multimx;
-}
-
-
-/*------------------------------------------------------------------------
- * Free the Groupchat room.
- *
- *  @param session		The MXit session object
- *  @param multimx		The MultiMX room object to deallocate
- */
-static void room_remove(struct MXitSession* session, struct multimx* multimx)
-{
-	/* Remove from GroupChat list */
-	session->rooms = g_list_remove(session->rooms, multimx);
-
-	/* free nickname */
-	if (multimx->nickname)
-		g_free(multimx->nickname);
-
-	/* Deallocate it */
-	g_free (multimx);
-	multimx = NULL;
-}
-
-
-/*------------------------------------------------------------------------
- * Another user has join the GroupChat, add them to the member-list.
- *
- *  @param convo		The Conversation object
- *  @param nickname		The nickname of the user who joined the room
- */
-static void member_added(PurpleConversation* convo, const char* nickname)
-{
-	purple_debug_info(MXIT_PLUGIN_ID, "member_added: '%s'\n", nickname);
-
-	purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo), nickname, NULL, PURPLE_CBFLAGS_NONE, TRUE);
-}
-
-
-/*------------------------------------------------------------------------
- * Another user has left the GroupChat, remove them from the member-list.
- *
- *  @param convo		The Conversation object
- *  @param nickname		The nickname of the user who left the room
- */
-static void member_removed(PurpleConversation* convo, const char* nickname)
-{
-	purple_debug_info(MXIT_PLUGIN_ID, "member_removed: '%s'\n", nickname);
-
-	purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), nickname, NULL);
-}
-
-
-/*------------------------------------------------------------------------
- * A user was kicked from the GroupChat, remove them from the member-list.
- *
- *  @param convo		The Conversation object
- *  @param nickname		The nickname of the user who was kicked
- */
-static void member_kicked(PurpleConversation* convo, const char* nickname)
-{
-	purple_debug_info(MXIT_PLUGIN_ID, "member_kicked: '%s'\n", nickname);
-
-	purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), nickname, _("was kicked"));
-}
-
-
-/*------------------------------------------------------------------------
- * You were kicked from the GroupChat.
- *
- *  @param convo		The Conversation object
- *  @param session		The MXit session object
- *  @param multimx		The MultiMX room object
- */
-static void you_kicked(PurpleConversation* convo, struct MXitSession* session, struct multimx* multimx)
-{
-	purple_debug_info(MXIT_PLUGIN_ID, "you_kicked\n");
-
-	purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "MXit", _("You have been kicked from this MultiMX."), PURPLE_MESSAGE_SYSTEM, time(NULL));
-	purple_conv_chat_clear_users(PURPLE_CONV_CHAT(convo));
-	serv_got_chat_left(session->con, multimx->chatid);
-}
-
-
-/*------------------------------------------------------------------------
- * Update the full GroupChat member list.
- *
- *  @param convo		The Conversation object
- *  @param data			The nicknames of the users in the room (separated by \n)
- */
-static void member_update(PurpleConversation* convo, char* data)
-{
-	gchar** userlist;
-	int i = 0;
-
-	purple_debug_info(MXIT_PLUGIN_ID, "member_update: '%s'\n", data);
-
-	/* Clear list */
-	purple_conv_chat_clear_users(PURPLE_CONV_CHAT(convo));
-
-	/* Add each member */
-	data = g_strstrip(data);				/* string leading & trailing whitespace */
-	userlist = g_strsplit(data, "\n", 0);	/* tokenize string */
-	while (userlist[i] != NULL) {
-		purple_debug_info(MXIT_PLUGIN_ID, "member_update - adding: '%s'\n", userlist[i]);
-		purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo), userlist[i], NULL, PURPLE_CBFLAGS_NONE, FALSE);
-		i++;
-	}
-	g_strfreev(userlist);
-}
-
-
-/* -------------------------------------------------------------------------------------------------
- * Calls from MXit Protocol layer
- * ------------------------------------------------------------------------------------------------- */
-
-/*------------------------------------------------------------------------
- * Received a Subscription Request to a MultiMX room.
- *
- *  @param session		The MXit session object
- *  @param contact		The invited MultiMX room's contact information
- *  @param creator		The nickname of the room's creator / invitor
- */
-void multimx_invite(struct MXitSession* session, struct contact* contact, const char* creator)
-{
-	GHashTable *components;
-
-	purple_debug_info(MXIT_PLUGIN_ID, "Groupchat invite to '%s' (roomid='%s') by '%s'\n", contact->alias, contact->username, creator);
-
-	/* Check if the room already exists (ie, already joined or invite pending) */
-	if (find_room_by_username(session, contact->username) != NULL)
-		return;
-
-	/* Create a new room */
-	room_create(session, contact->username, contact->alias, STATE_INVITED);
-
-	components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-	g_hash_table_insert(components, g_strdup("room"), g_strdup(contact->alias));
-
-	/* Call libpurple - will trigger either 'mxit_chat_join' or 'mxit_chat_reject' */
-	serv_got_chat_invite(session->con, contact->alias, creator, NULL, components);
-}
-
-
-/*------------------------------------------------------------------------
- * MultiMX room has been added to the roster.
- *
- *  @param session		The MXit session object
- *  @param contact		The MultiMX room's contact information
- */
-void multimx_created(struct MXitSession* session, struct contact* contact)
-{
-	PurpleConnection *gc = session->con;
-	struct multimx* multimx = NULL;
-
-	purple_debug_info(MXIT_PLUGIN_ID, "Groupchat '%s' created as '%s'\n", contact->alias, contact->username);
-
-	/* Find matching MultiMX group */
-	multimx = find_room_by_username(session, contact->username);
-	if (multimx == NULL) {
-		multimx = room_create(session, contact->username, contact->alias, TRUE);
-	}
-	else if (multimx->state == STATE_INVITED) {
-		/* After successfully accepting an invitation */
-		multimx->state = STATE_JOINED;
-	}
-
-	/* Call libpurple - will trigger 'mxit_chat_join' */
-	serv_got_joined_chat(gc, multimx->chatid, multimx->roomname);
-
-	/* Send ".list" command to GroupChat server to retrieve current member-list */
-	mxit_send_message(session, multimx->roomid, ".list", FALSE, FALSE);
-}
-
-
-/*------------------------------------------------------------------------
- * Is this username a MultiMX contact?
- *
- *  @param session		The MXit session object
- *  @param username		The username of the contact
- *  @return				TRUE if this contacts matches the RoomID of a MultiMX room.
- */
-gboolean is_multimx_contact(struct MXitSession* session, const char* username)
-{
-	/* Check for username in list of open rooms */
-	return (find_room_by_username(session, username) != NULL);
-}
-
-
-/*------------------------------------------------------------------------
- * Received a message from a MultiMX room.
- *
- */
-void multimx_message_received(struct RXMsgData* mx, char* msg, int msglen, short msgtype, int msgflags)
-{
-	struct multimx* multimx = NULL;
-
-	purple_debug_info(MXIT_PLUGIN_ID, "Groupchat message received: %s\n", msg);
-
-	/* Find matching multimx group */
-	multimx = find_room_by_username(mx->session, mx->from);
-	if (multimx == NULL) {
-		purple_debug_error(MXIT_PLUGIN_ID, "Groupchat '%s' not found\n", mx->from);
-		return;
-	}
-
-	/* Determine if system message or a message from a contact */
-	if (msg[0] == '<') {
-		/* Message contains embedded nickname - must be from contact */
-		unsigned int i;
-
-		for (i = 1; i < strlen(msg); i++) {		/* search for end of nickname */
-			if ((msg[i] == '>') && (msg[i+1] == '\n')) {
-				msg[i] = '\0';
-				g_free(mx->from);
-				mx->from = g_strdup(&msg[1]);
-				msg = &msg[i+2];		/* skip '>' and newline */
-				break;
-			}
-		}
-
-		/* now do markup processing on the message */
-		mx->chatid = multimx->chatid;
-		mxit_parse_markup(mx, msg, strlen(msg), msgtype, msgflags);
-	}
-	else {
-		/* Must be a service message */
-		char* ofs;
-
-		PurpleConversation* convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, multimx->roomname, mx->session->acc);
-		if (convo == NULL) {
-			purple_debug_error(MXIT_PLUGIN_ID, "Conversation '%s' not found\n", multimx->roomname);
-			return;
-		}
-
-		/* Determine if somebody has joined or left - update member-list */
-		if ((ofs = strstr(msg, " has joined")) != NULL) {
-			/* Somebody has joined */
-			*ofs = '\0';
-			member_added(convo, msg);
-			mx->processed = TRUE;
-		}
-		else if ((ofs = strstr(msg, " has left")) != NULL) {
-			/* Somebody has left */
-			*ofs = '\0';
-			member_removed(convo, msg);
-			mx->processed = TRUE;
-		}
-		else if ((ofs = strstr(msg, " has been kicked")) != NULL) {
-			/* Somebody has been kicked */
-			*ofs = '\0';
-			member_kicked(convo, msg);
-			mx->processed = TRUE;
-		}
-		else if (strcmp(msg, "You have been kicked.") == 0) {
-			/* You have been kicked */
-			you_kicked(convo, mx->session, multimx);
-			mx->processed = TRUE;
-		}
-		else if (g_str_has_prefix(msg, "The following users are in this MultiMx:") == TRUE) {
-			member_update(convo, msg + strlen("The following users are in this MultiMx:") + 1);
-			mx->processed = TRUE;
-		}
-		else {
-			/* Display server message in chat window */
-			serv_got_chat_in(mx->session->con, multimx->chatid, "MXit", PURPLE_MESSAGE_SYSTEM, msg, mx->timestamp);
-			mx->processed = TRUE;
-		}
-	}
-}
-
-
-
-/* -------------------------------------------------------------------------------------------------
- * Callbacks from libpurple
- * ------------------------------------------------------------------------------------------------- */
-
-/*------------------------------------------------------------------------
- * User has selected "Add Chat" from the main menu.
- *
- *  @param gc			The connection object
- *  @return				A list of chat configuration values
- */
-GList* mxit_chat_info(PurpleConnection *gc)
-{
-	GList *m = NULL;
-	struct proto_chat_entry *pce;
-
-	/* Configuration option: Room Name */
-	pce = g_new0(struct proto_chat_entry, 1);
-	pce->label = _( "_Room Name:" );
-	pce->identifier = "room";
-	pce->required = TRUE;
-	m = g_list_append(m, pce);
-
-	return m;
-}
-
-
-/*------------------------------------------------------------------------
- * User has joined a chatroom, either because they are creating it or they
- * accepted an invite.
- *
- *  @param gc			The connection object
- *  @param components	The list of chat configuration values
- */
-void mxit_chat_join(PurpleConnection *gc, GHashTable *components)
-{
-	struct MXitSession* session = purple_connection_get_protocol_data(gc);
-	const char* roomname = NULL;
-	struct multimx* multimx = NULL;
-
-	purple_debug_info(MXIT_PLUGIN_ID, "mxit_chat_join\n");
-
-	/* Determine if groupchat already exists */
-	roomname = g_hash_table_lookup(components, "room");
-	multimx = find_room_by_alias(session, roomname);
-
-	if (multimx != NULL) {
-		/* The room information already exists */
-
-		if (multimx->state == STATE_INVITED) {
-			/* Invite is pending */
-			purple_debug_info(MXIT_PLUGIN_ID, "Groupchat %i accept sent\n", multimx->chatid);
-
-			/* Send Subscription Accept to MXit */
-			mxit_send_allow_sub(session, multimx->roomid, multimx->roomname);
-		}
-		else {
-			/* Join existing room */
-			purple_debug_info(MXIT_PLUGIN_ID, "Groupchat %i rejoined\n", multimx->chatid);
-
-			serv_got_joined_chat(gc, multimx->chatid, multimx->roomname);
-		}
-	}
-	else {
-		/* Send Groupchat Create to MXit */
-		mxit_send_groupchat_create(session, roomname, 0, NULL);
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * User has rejected an invite to join a MultiMX room.
- *
- *  @param gc			The connection object
- *  @param components	The list of chat configuration values
- */
-void mxit_chat_reject(PurpleConnection *gc, GHashTable* components)
-{
-	struct MXitSession* session = purple_connection_get_protocol_data(gc);
-	const char* roomname = NULL;
-	struct multimx* multimx = NULL;
-
-	purple_debug_info(MXIT_PLUGIN_ID, "mxit_chat_reject\n");
-
-	roomname = g_hash_table_lookup(components, "room");
-	multimx = find_room_by_alias(session, roomname);
-	if (multimx == NULL) {
-		purple_debug_error(MXIT_PLUGIN_ID, "Groupchat '%s' not found\n", roomname);
-		return;
-	}
-
-	/* Send Subscription Reject to MXit */
-	mxit_send_deny_sub(session, multimx->roomid, NULL);
-
-	/* Remove from our list of rooms */
-	room_remove(session, multimx);
-}
-
-
-/*------------------------------------------------------------------------
- * Return name of chatroom (on mouse hover)
- *
- *  @param components	The list of chat configuration values.
- *  @return				The name of the chat room
- */
-char* mxit_chat_name(GHashTable *components)
-{
-	return g_strdup(g_hash_table_lookup(components, "room"));
-}
-
-
-/*------------------------------------------------------------------------
- * User has selected to invite somebody to a chatroom.
- *
- *  @param gc			The connection object
- *  @param id			The chat room ID
- *  @param msg			The invitation message entered by the user
- *  @param name			The username of the person to invite
- */
-void mxit_chat_invite(PurpleConnection *gc, int id, const char *msg, const char *username)
-{
-	struct MXitSession* session = purple_connection_get_protocol_data(gc);
-	struct multimx* multimx = NULL;
-	PurpleBuddy* buddy;
-	PurpleConversation *convo;
-	char* tmp;
-
-	purple_debug_info(MXIT_PLUGIN_ID, "Groupchat invite to '%s'\n", username);
-
-	/* Find matching MultiMX group */
-	multimx = find_room_by_id(session, id);
-	if (multimx == NULL) {
-		purple_debug_error(MXIT_PLUGIN_ID, "Could not find groupchat %i\n", id);
-		return;
-	}
-
-	/* Send invite to MXit */
-	mxit_send_groupchat_invite(session, multimx->roomid, 1, &username);
-
-	/* Find the buddy information for this contact (reference: "libpurple/blist.h") */
-	buddy = purple_find_buddy(session->acc, username);
-	if (!buddy) {
-		purple_debug_warning(MXIT_PLUGIN_ID, "mxit_chat_invite: unable to find the buddy '%s'\n", username);
-		return;
-	}
-
-	convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, multimx->roomname, session->acc);
-	if (convo == NULL) {
-		purple_debug_error(MXIT_PLUGIN_ID, "Conversation '%s' not found\n", multimx->roomname);
-		return;
-	}
-
-	/* Display system message in chat window */
-	tmp = g_strdup_printf("%s: %s", _("You have invited"), purple_buddy_get_alias(buddy));
-	purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "MXit", tmp, PURPLE_MESSAGE_SYSTEM, time(NULL));
-	g_free(tmp);
-}
-
-
-/*------------------------------------------------------------------------
- * User as closed the chat window, and the chatroom is not marked as persistent.
- *
- *  @param gc			The connection object
- *  @param id			The chat room ID
- */
-void mxit_chat_leave(PurpleConnection *gc, int id)
-{
-	struct MXitSession* session = purple_connection_get_protocol_data(gc);
-	struct multimx* multimx = NULL;
-
-	purple_debug_info(MXIT_PLUGIN_ID, "Groupchat %i leave\n", id);
-
-	/* Find matching multimx group */
-	multimx = find_room_by_id(session, id);
-	if (multimx == NULL) {
-		purple_debug_error(MXIT_PLUGIN_ID, "Could not find groupchat %i\n", id);
-		return;
-	}
-
-	/* Send Remove Groupchat to MXit */
-	mxit_send_remove(session, multimx->roomid);
-
-	/* Remove from our list of rooms */
-	room_remove(session, multimx);
-}
-
-
-/*------------------------------------------------------------------------
- * User has entered a message in a chatroom window, send it to the MXit server.
- *
- *  @param gc			The connection object
- *  @param id			The chat room ID
- *  @param message		The sent message data
- *  @param flags		The message flags
- *  @return				Indicates success / failure
- */
-int mxit_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags)
-{
-	struct MXitSession* session = purple_connection_get_protocol_data(gc);
-	struct multimx* multimx = NULL;
-	const char* nickname;
-
-	purple_debug_info(MXIT_PLUGIN_ID, "Groupchat %i message send: '%s'\n", id, message);
-
-	/* Find matching MultiMX group */
-	multimx = find_room_by_id(session, id);
-	if (multimx == NULL) {
-		purple_debug_error(MXIT_PLUGIN_ID, "Could not find groupchat %i\n", id);
-		return -1;
-	}
-
-	/* Send packet to MXit */
-	mxit_send_message(session, multimx->roomid, message, TRUE, FALSE);
-
-	/* Determine our nickname to display */
-	if (multimx->nickname)
-		nickname = multimx->nickname;
-	else
-		nickname = purple_account_get_alias(purple_connection_get_account(gc));		/* local alias */
-
-	/* Display message in chat window */
-	serv_got_chat_in(gc, id, nickname, flags, message, time(NULL));
-
-	return 0;
-}
-
--- a/libpurple/protocols/mxit/multimx.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *						-- MultiMx GroupChat --
- *
- *				Andrew Victor	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * 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		_MXIT_MULTIMX_H_
-#define		_MXIT_MULTIMX_H_
-
-#include	"roster.h"
-
-
-/* GroupChat Room state */
-#define		STATE_CREATOR	0
-#define		STATE_INVITED	1
-#define		STATE_JOINED	2
-
-/*
- * a MultiMX room
- */
-struct multimx {
-	char	roomname[MXIT_CP_MAX_ALIAS_LEN];	/* name of the room */
-	char	roomid[MXIT_CP_MAX_JID_LEN];		/* internal JID for room */
-	int		chatid;								/* libpurple chat ID */
-	char*	nickname;							/* our nickname in the room */
-	short	state;								/* state */
-};
-
-
-/*
- * Received a Subscription Request to a MultiMX room.
- */
-void multimx_invite(struct MXitSession* session, struct contact* contact, const char* creator);
-
-/*
- * MultiMX room has been added to the roster.
- */
-void multimx_created(struct MXitSession* session, struct contact* contact);
-
-/*
- * Is this username a MultiMX contact?
- */
-gboolean is_multimx_contact(struct MXitSession* session, const char* username);
-
-/*
- * Received a message from a MultiMX room.
- */
-void multimx_message_received(struct RXMsgData* mx, char* message, int len, short msgtype, int msgflags);
-
-/*
- * User has selected "Add Chat" from the main menu.
- */
-GList* mxit_chat_info(PurpleConnection *gc);
-
-/*
- * User has joined a chatroom, either because they are creating it or they accepted an invite.
- */
-void mxit_chat_join(PurpleConnection *gc, GHashTable *data);
-
-/*
- * User has rejected an invite to join a MultiMX room.
- */
-void mxit_chat_reject(PurpleConnection *gc, GHashTable* components);
-
-/*
- * Return name of chatroom (on mouse hover)
- */
-char* mxit_chat_name(GHashTable *data);
-
-/*
- * User has selected to invite somebody to a chatroom.
- */
-void mxit_chat_invite(PurpleConnection *gc, int id, const char *msg, const char *name);
-
-/*
- * User as closed the chat window, and the chatroom is not marked as persistent.
- */
-void mxit_chat_leave(PurpleConnection *gc, int id);
-
-/*
- * User has entered a message in a chatroom window, send it to the MXit server.
- */
-int mxit_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags);
-
-
-#endif		/* _MXIT_MULTIMX_H_ */
--- a/libpurple/protocols/mxit/mxit.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,862 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *					--  MXit libPurple plugin API --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include	"internal.h"
-#include	"debug.h"
-#include	"accountopt.h"
-#include	"version.h"
-
-#include	"mxit.h"
-#include	"protocol.h"
-#include	"login.h"
-#include	"roster.h"
-#include	"chunk.h"
-#include	"filexfer.h"
-#include	"actions.h"
-#include	"multimx.h"
-
-
-#ifdef	MXIT_LINK_CLICK
-
-
-/* pidgin callback function pointers for URI click interception */
-static void *(*mxit_pidgin_uri_cb)(const char *uri);
-static PurpleNotifyUiOps* mxit_nots_override_original;
-static PurpleNotifyUiOps mxit_nots_override;
-static int not_link_ref_count = 0;
-
-
-/*------------------------------------------------------------------------
- * Handle an URI clicked on the UI
- *
- * @param link	the link name which has been clicked
- */
-static void* mxit_link_click( const char* link64 )
-{
-	PurpleAccount*		account;
-	PurpleConnection*	gc;
-	gchar**				parts		= NULL;
-	gchar*				link		= NULL;
-	gsize				len;
-	gboolean			is_command	= FALSE;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_link_click (%s)\n", link64 );
-
-	if ( g_ascii_strncasecmp( link64, MXIT_LINK_PREFIX, strlen( MXIT_LINK_PREFIX ) ) != 0 ) {
-		/* this is not for us */
-		goto skip;
-	}
-
-	/* decode the base64 payload */
-	link = (gchar*) purple_base64_decode( link64 + strlen( MXIT_LINK_PREFIX ), &len );
-	purple_debug_info( MXIT_PLUGIN_ID, "Clicked Link: '%s'\n", link );
-
-	parts = g_strsplit( link, "|", 6 );
-
-	/* check if this is a valid mxit link */
-	if ( ( !parts ) || ( !parts[0] ) || ( !parts[1] ) || ( !parts[2] ) || ( !parts[3] ) || ( !parts[4] ) || ( !parts[5] ) ) {
-		/* this is not for us */
-		goto skip;
-	}
-	else if ( g_ascii_strcasecmp( parts[0], MXIT_LINK_KEY ) != 0 ) {
-		/* this is not for us */
-		goto skip;
-	}
-
-	/* find the account */
-	account = purple_accounts_find( parts[1], parts[2] );
-	if ( !account )
-		goto skip;
-	gc = purple_account_get_connection( account );
-	if ( !gc )
-		goto skip;
-
-	/* determine if it's a command-response to send */
-	is_command = ( atoi( parts[4] ) == 1 );
-
-	/* send click message back to MXit */
-	mxit_send_message( purple_connection_get_protocol_data( gc ), parts[3], parts[5], FALSE, is_command );
-
-	g_free( link );
-	link = NULL;
-	g_strfreev( parts );
-	parts = NULL;
-
-	return (void*) link64;
-
-skip:
-	/* this is not an internal mxit link */
-
-	if ( link )
-		g_free( link );
-	link = NULL;
-
-	if ( parts )
-		g_strfreev( parts );
-	parts = NULL;
-
-	if ( mxit_pidgin_uri_cb )
-		return mxit_pidgin_uri_cb( link64 );
-	else
-		return (void*) link64;
-}
-
-
-/*------------------------------------------------------------------------
- * Register MXit to receive URI click notifications from the UI
- */
-void mxit_register_uri_handler( void )
-{
-	not_link_ref_count++;
-	if ( not_link_ref_count == 1 ) {
-		/* make copy of notifications */
-		mxit_nots_override_original = purple_notify_get_ui_ops();
-		memcpy( &mxit_nots_override, mxit_nots_override_original, sizeof( PurpleNotifyUiOps ) );
-
-		/* save previously configured callback function pointer */
-		mxit_pidgin_uri_cb = mxit_nots_override.notify_uri;
-
-		/* override the URI function call with MXit's own one */
-		mxit_nots_override.notify_uri = mxit_link_click;
-		purple_notify_set_ui_ops( &mxit_nots_override );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Unregister MXit from receiving URI click notifications from the UI
- */
-static void mxit_unregister_uri_handler()
-{
-	not_link_ref_count--;
-	if ( not_link_ref_count == 0 ) {
-		/* restore the notifications to its original state */
-		purple_notify_set_ui_ops( mxit_nots_override_original );
-	}
-}
-
-#endif
-
-
-/*------------------------------------------------------------------------
- * This gets called when a new chat conversation is opened by the user
- *
- *  @param conv				The conversation object
- *  @param session			The MXit session object
- */
-static void mxit_cb_chat_created( PurpleConversation* conv, struct MXitSession* session )
-{
-	PurpleConnection*	gc;
-	struct contact*		contact;
-	PurpleBuddy*		buddy;
-	const char*			who;
-	char*				tmp;
-
-	gc = purple_conversation_get_gc( conv );
-	if ( session->con != gc ) {
-		/* not our conversation */
-		return;
-	}
-	else if ( purple_conversation_get_type( conv ) != PURPLE_CONV_TYPE_IM ) {
-		/* wrong type of conversation */
-		return;
-	}
-
-	/* get the contact name */
-	who = purple_conversation_get_name( conv );
-	if ( !who )
-		return;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "Conversation started with '%s'\n", who );
-
-	/* find the buddy object */
-	buddy = purple_find_buddy( session->acc, who );
-	if ( !buddy )
-		return;
-
-	contact = purple_buddy_get_protocol_data( buddy );
-	if ( !contact )
-		return;
-
-	/* we ignore all conversations with which we have chatted with in this session */
-	if ( find_active_chat( session->active_chats, who ) )
-		return;
-
-	/* determine if this buddy is a MXit service */
-	switch ( contact->type ) {
-		case MXIT_TYPE_BOT :
-		case MXIT_TYPE_CHATROOM :
-		case MXIT_TYPE_GALLERY :
-		case MXIT_TYPE_INFO :
-				tmp = g_strdup_printf("<font color=\"#999999\">%s</font>\n", _( "Loading menu..." ));
-				serv_got_im( session->con, who, tmp, PURPLE_MESSAGE_NOTIFY, time( NULL ) );
-				g_free( tmp );
-				mxit_send_message( session, who, " ", FALSE, FALSE );
-		default :
-				break;
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Enable some signals to handled by our plugin
- *
- *  @param session			The MXit session object
- */
-void mxit_enable_signals( struct MXitSession* session )
-{
-	/* enable the signal when a new conversation is opened by the user */
-	purple_signal_connect_priority( purple_conversations_get_handle(), "conversation-created", session, PURPLE_CALLBACK( mxit_cb_chat_created ),
-			session, PURPLE_SIGNAL_PRIORITY_HIGHEST );
-}
-
-
-/*------------------------------------------------------------------------
- * Disable some signals handled by our plugin
- *
- *  @param session			The MXit session object
- */
-static void mxit_disable_signals( struct MXitSession* session )
-{
-	/* disable the signal when a new conversation is opened by the user */
-	purple_signal_disconnect( purple_conversations_get_handle(), "conversation-created", session, PURPLE_CALLBACK( mxit_cb_chat_created ) );
-}
-
-
-/*------------------------------------------------------------------------
- * Return the base icon name.
- *
- *  @param account	The MXit account object
- *  @param buddy	The buddy
- *  @return			The icon name (excluding extension)
- */
-static const char* mxit_list_icon( PurpleAccount* account, PurpleBuddy* buddy )
-{
-	return "mxit";
-}
-
-
-/*------------------------------------------------------------------------
- * Return the emblem icon name.
- *
- *  @param buddy	The buddy
- *  @return			The icon name (excluding extension)
- */
-static const char* mxit_list_emblem( PurpleBuddy* buddy )
-{
-	struct contact*	contact = purple_buddy_get_protocol_data( buddy );
-
-	if ( !contact )
-		return NULL;
-
-	/* subscription state is Pending, Rejected or Deleted */
-	if ( contact->subtype != MXIT_SUBTYPE_BOTH )
-		return "not-authorized";
-
-	switch ( contact-> type ) {
-		case MXIT_TYPE_JABBER :			/* external contacts via MXit */
-		case MXIT_TYPE_MSN :
-		case MXIT_TYPE_YAHOO :
-		case MXIT_TYPE_ICQ :
-		case MXIT_TYPE_AIM :
-		case MXIT_TYPE_QQ :
-		case MXIT_TYPE_WV :
-			return "external";
-
-		case MXIT_TYPE_BOT :			/* MXit services */
-		case MXIT_TYPE_GALLERY :
-		case MXIT_TYPE_INFO :
-			return "bot";
-
-		case MXIT_TYPE_CHATROOM :		/* MXit group chat services */
-		case MXIT_TYPE_MULTIMX :
-		default:
-			return NULL;
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Return short string representing buddy's status for display on buddy list.
- * Returns status message (if one is set), or otherwise the mood.
- *
- *  @param buddy	The buddy.
- *  @return			The status text
- */
-char* mxit_status_text( PurpleBuddy* buddy )
-{
-	char* text = NULL;
-	struct contact*	contact = purple_buddy_get_protocol_data( buddy );
-
-	if ( !contact )
-		return NULL;
-
-	if ( contact->statusMsg )							/* status message */
-		text = g_strdup( contact-> statusMsg );
-	else if ( contact->mood != MXIT_MOOD_NONE )			/* mood */
-		text = g_strdup( mxit_convert_mood_to_name( contact->mood ) );
-
-	return text;
-}
-
-
-/*------------------------------------------------------------------------
- * Return UI tooltip information for a buddy when hovering in buddy list.
- *
- *  @param buddy	The buddy
- *  @param info		The tooltip info being returned
- *  @param full		Return full or summarized information
- */
-static void mxit_tooltip( PurpleBuddy* buddy, PurpleNotifyUserInfo* info, gboolean full )
-{
-	struct contact*	contact = purple_buddy_get_protocol_data( buddy );
-
-	if ( !contact )
-		return;
-
-	/* status (reference: "libpurple/notify.h") */
-	if ( contact->presence != MXIT_PRESENCE_OFFLINE )
-		purple_notify_user_info_add_pair( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) );
-
-	/* status message */
-	if ( contact->statusMsg )
-		purple_notify_user_info_add_pair( info, _( "Status Message" ), contact->statusMsg );
-
-	/* mood */
-	if ( contact->mood != MXIT_MOOD_NONE )
-		purple_notify_user_info_add_pair( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) );
-
-	/* subscription type */
-	if ( contact->subtype != 0 )
-		purple_notify_user_info_add_pair( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) );
-
-	/* rejection message */
-	if ( ( contact->subtype == MXIT_SUBTYPE_REJECTED ) && ( contact->msg != NULL ) )
-		purple_notify_user_info_add_pair( info, _( "Rejection Message" ), contact->msg );
-}
-
-
-/*------------------------------------------------------------------------
- * Initiate the logout sequence, close the connection and clear the session data.
- *
- *  @param gc	The connection object
- */
-static void mxit_close( PurpleConnection* gc )
-{
-	struct MXitSession*	session	= purple_connection_get_protocol_data( gc );
-
-	/* disable signals */
-	mxit_disable_signals( session );
-
-	/* close the connection */
-	mxit_close_connection( session );
-
-#ifdef		MXIT_LINK_CLICK
-	/* unregister for uri click notification */
-	mxit_unregister_uri_handler();
-#endif
-
-	purple_debug_info( MXIT_PLUGIN_ID, "Releasing the session object..\n" );
-
-	/* free the session memory */
-	g_free( session );
-	session = NULL;
-}
-
-
-/*------------------------------------------------------------------------
- * Send a message to a contact
- *
- *  @param gc		The connection object
- *  @param who		The username of the recipient
- *  @param message	The message text
- *  @param flags	Message flags (defined in conversation.h)
- *  @return			Positive value (success, and echo to conversation window)
-					Zero (success, no echo)
-					Negative value (error)
- */
-static int mxit_send_im( PurpleConnection* gc, const char* who, const char* message, PurpleMessageFlags flags )
-{
-	purple_debug_info( MXIT_PLUGIN_ID, "Sending message '%s' to buddy '%s'\n", message, who );
-
-	mxit_send_message( purple_connection_get_protocol_data( gc ), who, message, TRUE, FALSE );
-
-	return 1;		/* echo to conversation window */
-}
-
-
-/*------------------------------------------------------------------------
- * The user changed their current presence state.
- *
- *  @param account	The MXit account object
- *  @param status	The new status (libPurple status type)
- */
-static void mxit_set_status( PurpleAccount* account, PurpleStatus* status )
-{
-	struct MXitSession*		session =	purple_connection_get_protocol_data( purple_account_get_connection( account ) );
-	const char*				statusid;
-	int						presence;
-	char*					statusmsg1;
-	char*					statusmsg2;
-
-	/* Handle mood changes */
-	if ( purple_status_type_get_primitive( purple_status_get_type( status ) ) == PURPLE_STATUS_MOOD ) {
-		const char* moodid = purple_status_get_attr_string( status, PURPLE_MOOD_NAME );
-		int mood;
-
-		/* convert the purple mood to a mxit mood */
-		mood = mxit_convert_mood( moodid );
-		if ( mood < 0 ) {
-			/* error, mood not found */
-			purple_debug_info( MXIT_PLUGIN_ID, "Mood status NOT found! (id = %s)\n", moodid );
-			return;
-		}
-
-		/* update mood state */
-		mxit_send_mood( session, mood );
-		return;
-	}
-
-	/* get the status id (reference: "libpurple/status.h") */
-	statusid = purple_status_get_id( status );
-
-	/* convert the purple status to a mxit status */
-	presence = mxit_convert_presence( statusid );
-	if ( presence < 0 ) {
-		/* error, status not found */
-		purple_debug_info( MXIT_PLUGIN_ID, "Presence status NOT found! (id = %s)\n", statusid );
-		return;
-	}
-
-	statusmsg1 = purple_markup_strip_html( purple_status_get_attr_string( status, "message" ) );
-	statusmsg2 = g_strndup( statusmsg1, CP_MAX_STATUS_MSG );
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_status: '%s'\n", statusmsg2 );
-
-	/* update presence state */
-	mxit_send_presence( session, presence, statusmsg2 );
-
-	g_free( statusmsg1 );
-	g_free( statusmsg2 );
-}
-
-
-/*------------------------------------------------------------------------
- * MXit supports messages to offline contacts.
- *
- *  @param buddy	The buddy
- */
-static gboolean mxit_offline_message( const PurpleBuddy *buddy )
-{
-	return TRUE;
-}
-
-
-/*------------------------------------------------------------------------
- * Free the resources used to store a buddy.
- *
- *  @param buddy	The buddy
- */
-static void mxit_free_buddy( PurpleBuddy* buddy )
-{
-	struct contact*		contact;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_free_buddy\n" );
-
-	contact = purple_buddy_get_protocol_data( buddy );
-	if ( contact ) {
-		if ( contact->statusMsg )
-			g_free( contact->statusMsg );
-		if ( contact->avatarId )
-			g_free( contact->avatarId );
-		if ( contact->msg )
-			g_free( contact->msg );
-		g_free( contact );
-	}
-
-	purple_buddy_set_protocol_data( buddy, NULL );
-}
-
-
-/*------------------------------------------------------------------------
- * Periodic task called every KEEPALIVE_INTERVAL (30 sec) to to maintain
- * idle connections, timeouts and the transmission queue to the MXit server.
- *
- *  @param gc		The connection object
- */
-static void mxit_keepalive( PurpleConnection *gc )
-{
-	struct MXitSession*	session	= purple_connection_get_protocol_data( gc );
-
-	/* if not logged in, there is nothing to do */
-	if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) )
-		return;
-
-	/* pinging is only for socket connections (HTTP does polling) */
-	if ( session->http )
-		return;
-
-	if ( session->last_tx <= ( mxit_now_milli() - ( MXIT_PING_INTERVAL * 1000 ) ) ) {
-		/*
-		 * this connection has been idle for too long, better ping
-		 * the server before it kills our connection.
-		 */
-		mxit_send_ping( session );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Set or clear our Buddy icon.
- *
- *  @param gc		The connection object
- *  @param img		The buddy icon data
- */
-static void mxit_set_buddy_icon( PurpleConnection *gc, PurpleStoredImage *img )
-{
-	struct MXitSession*	session	= purple_connection_get_protocol_data( gc );
-
-	if ( img == NULL )
-		mxit_set_avatar( session, NULL, 0 );
-	else
-		mxit_set_avatar( session, purple_imgstore_get_data( img ), purple_imgstore_get_size( img ) );
-}
-
-
-/*------------------------------------------------------------------------
- * Request profile information for another MXit contact.
- *
- *  @param gc		The connection object
- *  @param who		The username of the contact.
- */
-static void mxit_get_info( PurpleConnection *gc, const char *who )
-{
-	PurpleBuddy*			buddy;
-	struct contact*			contact;
-	struct MXitSession*		session			= purple_connection_get_protocol_data( gc );
-	const char*				profilelist[]	= { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME,
-												CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_LASTSEEN,
-												CP_PROFILE_STATUS, CP_PROFILE_AVATAR, CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME, CP_PROFILE_RELATIONSHIP };
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_info: '%s'\n", who );
-
-	/* find the buddy information for this contact (reference: "libpurple/blist.h") */
-	buddy = purple_find_buddy( session->acc, who );
-	if ( buddy ) {
-		/* user is in our contact-list, so it's not an invite */
-		contact = purple_buddy_get_protocol_data( buddy );
-		if ( !contact )
-			return;
-
-		/* only MXit users have profiles */
-		if ( contact->type != MXIT_TYPE_MXIT ) {
-			mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "No profile available" ), _( "This contact does not have a profile." ) );
-			return;
-		}
-	}
-
-	/* send profile request */
-	mxit_send_extprofile_request( session, who, ARRAY_SIZE( profilelist ), profilelist );
-}
-
-
-/*------------------------------------------------------------------------
- * Return a list of labels to be used by Pidgin for assisting the user.
- */
-static GHashTable* mxit_get_text_table( PurpleAccount* acc )
-{
-	GHashTable* table;
-
-	table = g_hash_table_new( g_str_hash, g_str_equal );
-
-	g_hash_table_insert( table, "login_label", (gpointer)_( "Your MXit ID..." ) );
-
-	return table;
-}
-
-
-/*------------------------------------------------------------------------
- * Re-Invite was selected from the buddy-list menu.
- *
- *  @param node		The entry in the buddy list.
- *  @param ignored	(not used)
- */
-static void mxit_reinvite( PurpleBlistNode *node, gpointer ignored )
-{
-	PurpleBuddy*		buddy		= (PurpleBuddy *) node;
-	PurpleConnection*	gc			= purple_account_get_connection( purple_buddy_get_account( buddy ) );
-	struct MXitSession*	session		= purple_connection_get_protocol_data( gc );
-	struct contact*		contact;
-
-	contact = purple_buddy_get_protocol_data( (PurpleBuddy*) node );
-	if ( !contact )
-		return;
-
-	/* send a new invite */
-	mxit_send_invite( session, contact->username, TRUE, contact->alias, contact->groupname, NULL );
-}
-
-
-/*------------------------------------------------------------------------
- * Buddy-list menu.
- *
- *  @param node		The entry in the buddy list.
- */
-static GList* mxit_blist_menu( PurpleBlistNode *node )
-{
-	PurpleBuddy*		buddy;
-	struct contact*		contact;
-	GList*				m = NULL;
-	PurpleMenuAction*	act;
-
-	if ( !PURPLE_BLIST_NODE_IS_BUDDY( node ) )
-		return NULL;
-
-	buddy = (PurpleBuddy *) node;
-	contact = purple_buddy_get_protocol_data( buddy );
-	if ( !contact )
-		return NULL;
-
-	if ( ( contact->subtype == MXIT_SUBTYPE_DELETED ) || ( contact->subtype == MXIT_SUBTYPE_REJECTED ) || ( contact->subtype == MXIT_SUBTYPE_NONE ) ) {
-		/* contact is in Deleted, Rejected or None state */
-		act = purple_menu_action_new( _( "Re-Invite" ), PURPLE_CALLBACK( mxit_reinvite ), NULL, NULL );
-		m = g_list_append( m, act );
-	}
-
-	return m;
-}
-
-
-/*------------------------------------------------------------------------
- * Return Chat-room default settings.
- *
- *  @return		Chat defaults list
- */
-static GHashTable *mxit_chat_info_defaults( PurpleConnection *gc, const char *chat_name )
-{
-    return g_hash_table_new_full( g_str_hash, g_str_equal, NULL, g_free );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a typing indicator event.
- *
- *  @param gc		The connection object
- *  @param name		The username of the contact
- *  @param state	The typing state to be reported.
- */
-static unsigned int mxit_send_typing( PurpleConnection *gc, const char *name, PurpleTypingState state )
-{
-	PurpleAccount*		account		= purple_connection_get_account( gc );
-	struct MXitSession*	session		= purple_connection_get_protocol_data( gc );
-	PurpleBuddy*		buddy;
-	struct contact*		contact;
-	gchar*				messageId	= NULL;
-
-	/* find the buddy information for this contact (reference: "libpurple/blist.h") */
-	buddy = purple_find_buddy( account, name );
-	if ( !buddy ) {
-		purple_debug_warning( MXIT_PLUGIN_ID, "mxit_send_typing: unable to find the buddy '%s'\n", name );
-		return 0;
-	}
-
-	contact = purple_buddy_get_protocol_data( buddy );
-	if ( !contact )
-		return 0;
-
-	/* does this contact support and want typing notification? */
-	if ( ! ( contact->capabilities & MXIT_PFLAG_TYPING ) )
-		return 0;
-
-	messageId = purple_uuid_random();		/* generate a unique message id */
-
-	switch ( state ) {
-		case PURPLE_TYPING :		/* currently typing */
-			mxit_send_msgevent( session, name, messageId, CP_MSGEVENT_TYPING );
-			break;
-
-		case PURPLE_TYPED :			/* stopped typing */
-		case PURPLE_NOT_TYPING :	/* not typing / erased all text */
-			mxit_send_msgevent( session, name, messageId, CP_MSGEVENT_STOPPED );
-			break;
-
-		default:
-			break;
-	}
-
-	g_free( messageId );
-
-	return 0;
-}
-
-
-/*========================================================================================================================*/
-
-static PurplePluginProtocolInfo proto_info = {
-	OPT_PROTO_REGISTER_NOSCREENNAME | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE,			/* options */
-	NULL,					/* user_splits */
-	NULL,					/* protocol_options */
-	{						/* icon_spec */
-		"png,jpeg,bmp",										/* supported formats */
-		32, 32,												/* min width & height */
-		800, 800,											/* max width & height */
-		CP_MAX_FILESIZE,									/* max filesize */
-		PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY	/* scaling rules */
-	},
-	mxit_list_icon,			/* list_icon */
-	mxit_list_emblem,		/* list_emblem */
-	mxit_status_text,		/* status_text */
-	mxit_tooltip,			/* tooltip_text */
-	mxit_status_types,		/* status types				[roster.c] */
-	mxit_blist_menu,		/* blist_node_menu */
-	mxit_chat_info,			/* chat_info				[multimx.c] */
-	mxit_chat_info_defaults,/* chat_info_defaults */
-	mxit_login,				/* login					[login.c] */
-	mxit_close,				/* close */
-	mxit_send_im,			/* send_im */
-	NULL,					/* set_info */
-	mxit_send_typing,		/* send_typing */
-	mxit_get_info,			/* get_info */
-	mxit_set_status,		/* set_status */
-	NULL,					/* set_idle */
-	NULL,					/* change_passwd */
-	NULL,					/* add_buddy				[roster.c] */
-	NULL,					/* add_buddies */
-	mxit_remove_buddy,		/* remove_buddy				[roster.c] */
-	NULL,					/* remove_buddies */
-	NULL,					/* add_permit */
-	NULL,					/* add_deny */
-	NULL,					/* rem_permit */
-	NULL,					/* rem_deny */
-	NULL,					/* set_permit_deny */
-	mxit_chat_join,			/* join_chat				[multimx.c] */
-	mxit_chat_reject,		/* reject chat invite		[multimx.c] */
-	mxit_chat_name,			/* get_chat_name			[multimx.c] */
-	mxit_chat_invite,		/* chat_invite				[multimx.c] */
-	mxit_chat_leave,		/* chat_leave				[multimx.c] */
-	NULL,					/* chat_whisper */
-	mxit_chat_send,			/* chat_send				[multimx.c] */
-	mxit_keepalive,			/* keepalive */
-	mxit_register,			/* register_user */
-	NULL,					/* get_cb_info */
-	NULL,					/* get_cb_away */
-	mxit_buddy_alias,		/* alias_buddy				[roster.c] */
-	mxit_buddy_group,		/* group_buddy				[roster.c] */
-	mxit_rename_group,		/* rename_group				[roster.c] */
-	mxit_free_buddy,		/* buddy_free */
-	NULL,					/* convo_closed */
-	NULL,					/* normalize */
-	mxit_set_buddy_icon,	/* set_buddy_icon */
-	NULL,					/* remove_group */			// TODO: Add function to move all contacts out of this group (cmd=30 - 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 */
-	mxit_xfer_enabled,		/* can_receive_file			[filexfer.c] */
-	mxit_xfer_tx,			/* send_file				[filexfer.c */
-	mxit_xfer_new,			/* new_xfer					[filexfer.c] */
-	mxit_offline_message,	/* offline_message */
-	NULL,					/* whiteboard_prpl_ops */
-	NULL,					/* send_raw */
-	NULL,					/* roomlist_room_serialize */
-	NULL,					/* unregister_user */
-	NULL,					/* send_attention */
-	NULL,					/* attention_types */
-	sizeof( PurplePluginProtocolInfo ),		/* struct_size */
-	mxit_get_text_table,	/* get_account_text_table */
-	NULL,					/* initiate_media */
-	NULL,					/* get_media_caps */
-	mxit_get_moods,			/* get_moods */
-	NULL,					/* set_public_alias */
-	NULL,					/* get_public_alias */
-	mxit_add_buddy,			/* add_buddy_with_invite */
-	NULL					/* add_buddies_with_invite */
-};
-
-
-static PurplePluginInfo plugin_info = {
-	PURPLE_PLUGIN_MAGIC,								/* purple magic, this must always be PURPLE_PLUGIN_MAGIC */
-	PURPLE_MAJOR_VERSION,								/* libpurple version */
-	PURPLE_MINOR_VERSION,								/* libpurple version */
-	PURPLE_PLUGIN_PROTOCOL,								/* plugin type (connecting to another network) */
-	NULL,												/* UI requirement (NULL for core plugin) */
-	0,													/* plugin flags (zero is default) */
-	NULL,												/* plugin dependencies (set this value to NULL no matter what) */
-	PURPLE_PRIORITY_DEFAULT,							/* libpurple priority */
-
-	MXIT_PLUGIN_ID,										/* plugin id (must be unique) */
-	MXIT_PLUGIN_NAME,									/* plugin name (this will be displayed in the UI) */
-	DISPLAY_VERSION,									/* version of the plugin */
-
-	MXIT_PLUGIN_SUMMARY,								/* short summary of the plugin */
-	MXIT_PLUGIN_DESC,									/* description of the plugin (can be long) */
-	MXIT_PLUGIN_EMAIL,									/* plugin author name and email address */
-	MXIT_PLUGIN_WWW,									/* plugin website (to find new versions and reporting of bugs) */
-
-	NULL,												/* function pointer for loading the plugin */
-	NULL,												/* function pointer for unloading the plugin */
-	NULL,												/* function pointer for destroying the plugin */
-
-	NULL,												/* pointer to an UI-specific struct */
-	&proto_info,										/* pointer to either a PurplePluginLoaderInfo or PurplePluginProtocolInfo struct */
-	NULL,												/* pointer to a PurplePluginUiInfo struct */
-	mxit_actions,										/* function pointer where you can define plugin-actions */
-
-	/* padding */
-	NULL,												/* pointer reserved for future use */
-	NULL,												/* pointer reserved for future use */
-	NULL,												/* pointer reserved for future use */
-	NULL												/* pointer reserved for future use */
-};
-
-
-/*------------------------------------------------------------------------
- * Initialising the MXit plugin.
- *
- *  @param plugin	The plugin object
- */
-static void init_plugin( PurplePlugin* plugin )
-{
-	PurpleAccountOption*	option;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "Loading MXit libPurple plugin...\n" );
-
-	/* Configuration options */
-
-	/* WAP server (reference: "libpurple/accountopt.h") */
-	option = purple_account_option_string_new( _( "WAP Server" ), MXIT_CONFIG_WAPSERVER, DEFAULT_WAPSITE );
-	proto_info.protocol_options = g_list_append( proto_info.protocol_options, option );
-
-	option = purple_account_option_bool_new( _( "Connect via HTTP" ), MXIT_CONFIG_USE_HTTP, FALSE );
-	proto_info.protocol_options = g_list_append( proto_info.protocol_options, option );
-
-	option = purple_account_option_bool_new( _( "Enable splash-screen popup" ), MXIT_CONFIG_SPLASHPOPUP, FALSE );
-	proto_info.protocol_options = g_list_append( proto_info.protocol_options, option );
-}
-
-PURPLE_INIT_PLUGIN( mxit, init_plugin, plugin_info );
-
--- a/libpurple/protocols/mxit/mxit.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,196 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *					--  MXit libPurple plugin API --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * 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		_MXIT_H_
-#define		_MXIT_H_
-
-
-#include "internal.h"
-
-
-#if defined( __APPLE__ )
-/* apple architecture */
-#ifndef HOST_NAME_MAX
-#define		HOST_NAME_MAX				512
-#endif
-#elif defined( _WIN32 )
-/* windows architecture */
-#ifndef HOST_NAME_MAX
-#define		HOST_NAME_MAX				512
-#endif
-#include	"libc_interface.h"
-#elif defined( __linux__ )
-/* linux architecture */
-#include	<net/if.h>
-#include	<sys/ioctl.h>
-#include	<sys/socket.h>
-#include	<netinet/in.h>
-#include	<arpa/inet.h>
-#else
-/* other architecture */
-#ifndef HOST_NAME_MAX
-#define		HOST_NAME_MAX				512
-#endif
-#endif
-
-
-#include	"protocol.h"
-#include	"profile.h"
-
-
-/* Plugin details */
-#define		MXIT_PLUGIN_ID				"prpl-loubserp-mxit"
-#define		MXIT_PLUGIN_NAME			"MXit"
-#define		MXIT_PLUGIN_EMAIL			"Pieter Loubser <libpurple@mxit.com>"
-#define		MXIT_PLUGIN_WWW				"http://www.mxit.com"
-#define		MXIT_PLUGIN_SUMMARY			"MXit Protocol Plugin"
-#define		MXIT_PLUGIN_DESC			"MXit"
-
-#define		MXIT_HTTP_USERAGENT			"libpurple-"DISPLAY_VERSION
-
-
-/* default connection settings */
-#define		DEFAULT_SERVER				"stream.mxit.co.za"
-#define		DEFAULT_PORT				9119
-#define		DEFAULT_WAPSITE				"http://www.mxit.com"
-#define		DEFAULT_HTTP_SERVER			"http://int.poll.mxit.com:80/mxit"
-
-
-/* Purple account configuration variable names */
-#define		MXIT_CONFIG_STATE			"state"
-#define		MXIT_CONFIG_WAPSERVER		"wap_server"
-#define		MXIT_CONFIG_DISTCODE		"distcode"
-#define		MXIT_CONFIG_CLIENTKEY		"clientkey"
-#define		MXIT_CONFIG_DIALCODE		"dialcode"
-#define		MXIT_CONFIG_SERVER_ADDR		"server"
-#define		MXIT_CONFIG_SERVER_PORT		"port"
-#define		MXIT_CONFIG_HTTPSERVER		"httpserver"
-#define		MXIT_CONFIG_SPLASHID		"splashid"
-#define		MXIT_CONFIG_SPLASHCLICK		"splashclick"
-#define		MXIT_CONFIG_SPLASHPOPUP		"splashpopup"
-#define		MXIT_CONFIG_COUNTRYCODE		"cc"
-#define		MXIT_CONFIG_LOCALE			"locale"
-#define		MXIT_CONFIG_USE_HTTP		"use_http"
-
-
-/* account states */
-#define		MXIT_STATE_LOGIN			0x00
-#define		MXIT_STATE_REGISTER1		0x01
-#define		MXIT_STATE_REGISTER2		0x02
-
-
-/* Client session flags */
-#define		MXIT_FLAG_CONNECTED			0x01		/* established connection to the server */
-#define		MXIT_FLAG_LOGGEDIN			0x02		/* user currently logged in */
-#define		MXIT_FLAG_FIRSTROSTER		0x04		/* set to true once the first roster update has been received and processed */
-
-
-/* Maximum number of search results */
-#define		MXIT_SEARCHRESULTS_MAX		30
-
-
-/* define this to enable the link clicking support */
-#define		MXIT_LINK_CLICK
-
-#ifdef		MXIT_LINK_CLICK
-#define		MXIT_LINK_PREFIX			"gopher://"
-#define		MXIT_LINK_KEY				"MXIT"
-#endif
-
-
-#define		ARRAY_SIZE( x )				( sizeof( x ) / sizeof( x[0] ) )
-
-
-/*
- * data structure containing all MXit session information
- */
-struct MXitSession {
-	/* socket connection */
-	char				server[HOST_NAME_MAX];		/* MXit server name to connect to */
-	int					port;						/* MXit server port to connect on */
-	int					fd;							/* connection file descriptor */
-
-	/* http connection */
-	gboolean			http;						/* connect to MXit via HTTP and not by socket */
-	char				http_server[HOST_NAME_MAX];	/* MXit HTTP server */
-	unsigned int		http_sesid;					/* HTTP session id */
-	unsigned int		http_seqno;					/* HTTP request sequence number */
-	guint				http_timer_id;				/* timer resource id (pidgin) */
-	int					http_interval;				/* poll inverval */
-	gint64				http_last_poll;				/* the last time a poll has been sent */
-	guint				http_handler;				/* HTTP connection handler */
-
-	/* client */
-	struct login_data*	logindata;
-	char*				encpwd;						/* encrypted password */
-	char				distcode[64];				/* distribution code */
-	char				clientkey[16];				/* client key */
-	char				dialcode[8];				/* dialing code */
-	short				flags;						/* client session flags (see above) */
-
-	/* personal (profile) */
-	struct MXitProfile*	profile;					/* user's profile information */
-	char*				uid;						/* the user's UID */
-
-	/* libpurple */
-	PurpleAccount*		acc;						/* pointer to the libpurple internal account struct */
-	PurpleConnection*	con;						/* pointer to the libpurple internal connection struct */
-
-	/* transmit */
-	struct tx_queue		queue;						/* transmit packet queue (FIFO mode) */
-	gint64				last_tx;					/* timestamp of last packet sent */
-	int					outack;						/* outstanding ack packet */
-	guint				q_slow_timer_id;			/* timer handle for slow tx queue */
-	guint				q_fast_timer_id;			/* timer handle for fast tx queue */
-	GSList*				async_calls;				/* list of current outstanding async calls */
-
-	/* receive */
-	char				rx_lbuf[16];				/* receive byte buffer (socket packet length) */
-	char				rx_dbuf[CP_MAX_PACKET];		/* receive byte buffer (raw data) */
-	unsigned int		rx_i;						/* receive buffer current index */
-	int					rx_res;						/* amount of bytes still outstanding for the current packet */
-	char				rx_state;					/* current receiver state */
-	gint64				last_rx;					/* timestamp of last packet received */
-	GList*				active_chats;				/* list of all our contacts we received messages from (active chats) */
-	GList*				invites;					/* list of all the invites that we have received */
-
-	/* groupchat */
-	GList*				rooms;						/* active groupchat rooms */
-
-	/* inline images */
-	GHashTable*			iimages;					/* table which maps inline images (including emoticons) to purple's imgstore id's */
-};
-
-
-char* mxit_status_text( PurpleBuddy* buddy );
-void mxit_enable_signals( struct MXitSession* session );
-
-#ifdef	MXIT_LINK_CLICK
-void mxit_register_uri_handler( void );
-#endif
-
-
-#endif		/* _MXIT_H_ */
-
--- a/libpurple/protocols/mxit/profile.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,365 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *					-- user profile's --
- *
- *				Andrew Victor	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * 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		_XOPEN_SOURCE	1
-#include	<time.h>
-
-#include	"internal.h"
-
-#include	"mxit.h"
-#include	"profile.h"
-#include	"roster.h"
-
-
-/*------------------------------------------------------------------------
- * Return the MXit Relationship status as a string.
- *
- * @param id		The Relationship status value (see profile.h)
- * @return			The relationship status as a text string.
- */
-const char* mxit_relationship_to_name( short id )
-{
-	switch ( id ) {
-		case MXIT_RELATIONSHIP_UNKNOWN :
-			return _( "Unknown" );
-		case MXIT_RELATIONSHIP_DONTSAY :
-			return _( "Don't want to say" );
-		case MXIT_RELATIONSHIP_SINGLE :
-			return _( "Single" );
-		case MXIT_RELATIONSHIP_INVOLVED :
-			return _( "In a relationship" );
-		case MXIT_RELATIONSHIP_ENGAGED :
-			return _( "Engaged" );
-		case MXIT_RELATIONSHIP_MARRIED :
-			return _( "Married" );
-		case MXIT_RELATIONSHIP_COMPLICATED :
-			return _( "It's complicated" );
-		case MXIT_RELATIONSHIP_WIDOWED :
-			return _( "Widowed" );
-		case MXIT_RELATIONSHIP_SEPARATED :
-			return _( "Separated" );
-		case MXIT_RELATIONSHIP_DIVORCED :
-			return _( "Divorced" );
-		default :
-			return "";
-	}
-}
-
-/*------------------------------------------------------------------------
- * Returns true if it is a valid date.
- *
- * @param bday		Date-of-Birth string (YYYY-MM-DD)
- * @return			TRUE if valid, else FALSE
- */
-gboolean validateDate( const char* bday )
-{
-	struct tm*	tm;
-	time_t		t;
-	int			cur_year;
-	int			max_days[13]	= { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-	char		date[16];
-	int			year;
-	int			month;
-	int			day;
-
-	/* validate length */
-	if ( strlen( bday ) != 10 ) {
-		return FALSE;
-	}
-
-	/* validate the format */
-	if (	( !isdigit( bday[0] ) ) || ( !isdigit( bday[1] ) ) || ( !isdigit( bday[2] ) ) || ( !isdigit( bday[3] ) ) ||		/* year */
-			( bday[4] != '-' ) ||
-			( !isdigit( bday[5] ) ) || ( !isdigit( bday[6] ) ) ||															/* month */
-			( bday[7] != '-' ) ||
-			( !isdigit( bday[8] ) ) || ( !isdigit( bday[9] ) ) ) { 															/* day */
-		return FALSE;
-	}
-
-	/* convert */
-	t = time( NULL );
-	tm = gmtime( &t );
-	cur_year = tm->tm_year + 1900;
-	memcpy( date, bday, 10 );
-	date[4] = '\0';
-	date[7] = '\0';
-	date[10] = '\0';
-	year = atoi( &date[0] );
-	month = atoi( &date[5] );
-	day = atoi( &date[8] );
-
-	/* validate month */
-	if ( ( month < 1 ) || ( month > 12 ) ) {
-		return FALSE;
-	}
-
-	/* validate day */
-	if ( ( day < 1 ) || ( day > max_days[month] ) ) {
-		return FALSE;
-	}
-
-	/* validate year */
-	if ( ( year < ( cur_year - 100 ) ) || ( year >= cur_year ) ) {
-		/* you are either tooo old or tooo young to join mxit... sorry */
-		return FALSE;
-	}
-
-	/* special case leap-year */
-	if ( ( year % 4 != 0 ) && ( month == 2 ) && ( day == 29 ) ) {
-		/* cannot have 29 days in February in non leap-years! */
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-
-/*------------------------------------------------------------------------
- * Calculate an Age from the date-of-birth.
- *
- * @param date		Date-of-Birth string (YYYY-MM-DD)
- * @return			The age
- */
-static int calculateAge( const char* date )
-{
-	time_t t;
-	struct tm now, bdate;
-	int age;
-
-	if ( ( !date ) || ( strlen( date ) == 0 ) )
-		return 0;
-
-	/* current time */
-	t = time( NULL );
-	localtime_r( &t, &now );
-
-	/* decode hdate */
-	memset( &bdate, 0, sizeof( struct tm ) );
-	purple_str_to_time( date, FALSE, &bdate, NULL, NULL );
-
-	/* calculate difference */
-	age = now.tm_year - bdate.tm_year;
-	if ( now.tm_mon < bdate.tm_mon )		/* is before month of birth */
-		age--;
-	else if ( ( now.tm_mon == bdate.tm_mon ) && ( now.tm_mday < bdate.tm_mday ) )	/* before birthday in current month */
-		age--;
-
-	return age;
-}
-
-
-/*------------------------------------------------------------------------
- * Returns timestamp field in date & time format (DD-MM-YYYY HH:MM:SS)
- *
- * @param msecs		The timestamps (milliseconds since epoch)
- * @return			Date & Time in a display'able format.
- */
-static const char* datetime( gint64 msecs )
-{
-	time_t secs = msecs / 1000;
-
-	struct tm t;
-	localtime_r( &secs, &t );
-
-	return purple_utf8_strftime( "%d-%m-%Y %H:%M:%S", &t );
-}
-
-
-/*------------------------------------------------------------------------
- * Display the profile information.
- *
- * @param session		The MXit session object
- * @param username		The username who's profile information this is
- * @param profile		The profile
- */
-void mxit_show_profile( struct MXitSession* session, const char* username, struct MXitProfile* profile )
-{
-	PurpleNotifyUserInfo*	info		= purple_notify_user_info_new();
-	struct contact*			contact		= NULL;
-	PurpleBuddy*			buddy;
-	gchar*					tmp			= NULL;
-
-	buddy = purple_find_buddy( session->acc, username );
-	if ( buddy ) {
-		purple_notify_user_info_add_pair( info, _( "Alias" ), purple_buddy_get_alias( buddy ) );
-		purple_notify_user_info_add_section_break( info );
-		contact = purple_buddy_get_protocol_data( buddy );
-	}
-
-	purple_notify_user_info_add_pair( info, _( "Display Name" ), profile->nickname );
-
-	tmp = g_strdup_printf("%s (%i)", profile->birthday, calculateAge( profile->birthday ) );
-	purple_notify_user_info_add_pair( info, _( "Birthday" ), tmp );
-	g_free( tmp );
-
-	purple_notify_user_info_add_pair( info, _( "Gender" ), profile->male ? _( "Male" ) : _( "Female" ) );
-
-	/* optional information */
-	purple_notify_user_info_add_pair( info, _( "First Name" ), profile->firstname );
-	purple_notify_user_info_add_pair( info, _( "Last Name" ), profile->lastname );
-	purple_notify_user_info_add_pair( info, _( "Country" ), profile->regcountry );
-
-	if ( strlen( profile->aboutme ) > 0 )
-		purple_notify_user_info_add_pair( info, _( "About Me" ), profile->aboutme );
-	if ( strlen( profile->whereami ) > 0 )
-		purple_notify_user_info_add_pair( info, _( "Where I Live" ), profile->whereami );
-
-	purple_notify_user_info_add_pair_plaintext( info, _( "Relationship Status" ), mxit_relationship_to_name( profile->relationship ) );
-
-	purple_notify_user_info_add_section_break( info );
-
-	if ( contact ) {
-		/* presence */
-		purple_notify_user_info_add_pair( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) );
-
-		/* last online */
-		if ( contact->presence == MXIT_PRESENCE_OFFLINE )
-			purple_notify_user_info_add_pair( info, _( "Last Online" ), ( profile->lastonline == 0 ) ? _( "Unknown" ) : datetime( profile->lastonline ) );
-
-		/* mood */
-		if ( contact->mood != MXIT_MOOD_NONE )
-			purple_notify_user_info_add_pair( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) );
-		else
-			purple_notify_user_info_add_pair( info, _( "Mood" ), _( "None" ) );
-
-		/* status message */
-		if ( contact->statusMsg )
-			purple_notify_user_info_add_pair( info, _( "Status Message" ), contact->statusMsg );
-
-		/* subscription type */
-		purple_notify_user_info_add_pair( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) );
-	}
-	else {
-		/* this is an invite */
-		contact = get_mxit_invite_contact( session, username );
-		if ( contact ) {
-			/* invite found */
-
-			if ( contact->msg )
-				purple_notify_user_info_add_pair( info, _( "Invite Message" ), contact->msg );
-
-			if ( contact->imgid ) {
-				/* this invite has a avatar */
-				char* img_text;
-				img_text = g_strdup_printf( "<img id='%d'>", contact->imgid );
-				purple_notify_user_info_add_pair( info, _( "Photo" ), img_text );
-				g_free( img_text );
-			}
-
-			if ( contact->statusMsg )
-				purple_notify_user_info_add_pair( info, _( "Status Message" ), contact->statusMsg );
-		}
-	}
-
-	purple_notify_userinfo( session->con, username, info, NULL, NULL );
-	purple_notify_user_info_destroy( info );
-}
-
-
-/*------------------------------------------------------------------------
- * Display the profiles of search results.
- *
- * @param gc			The connection object
- * @param row			The selected row from search-results
- * @param user_data		NULL (unused)
- */
-static void mxit_search_results_add_cb( PurpleConnection *gc, GList *row, gpointer user_data )
-{
-	/* display add buddy dialog */
-	purple_blist_request_add_buddy( purple_connection_get_account( gc ), g_list_nth_data( row, 0 ), NULL, g_list_nth_data( row, 1 ) );
-}
-
-
-/*------------------------------------------------------------------------
- * Display the profiles of search results.
- *
- * @param session		The MXit session object
- * @param searchType	The type of search (CP_SUGGEST_*)
- * @param maxResults	The maximum number of results
- * @param entries		The list of profile entries
- */
-void mxit_show_search_results( struct MXitSession* session, int searchType, int maxResults, GList* entries )
-{
-	PurpleNotifySearchResults*	results;
-	PurpleNotifySearchColumn*	column;
-	gchar*						text;
-
-	if ( !entries ) {
-		mxit_popup( PURPLE_NOTIFY_MSG_INFO, _( "No results" ), _( "No contacts found." ) );
-		return;
-	}
-
-	results = purple_notify_searchresults_new();
-	if ( !results )
-		return;
-
-	/* define columns */
-	column = purple_notify_searchresults_column_new( _( "UserId" ) );
-	purple_notify_searchresults_column_add( results, column );
-	column = purple_notify_searchresults_column_new( _( "Display Name" ) );
-	purple_notify_searchresults_column_add( results, column );
-	column = purple_notify_searchresults_column_new( _( "First Name" ) );
-	purple_notify_searchresults_column_add( results, column );
-	column = purple_notify_searchresults_column_new( _( "Last Name" ) );
-	purple_notify_searchresults_column_add( results, column );
-	column = purple_notify_searchresults_column_new( _( "Gender" ) );
-	purple_notify_searchresults_column_add( results, column );
-	column = purple_notify_searchresults_column_new( _( "Age" ) );
-	purple_notify_searchresults_column_add( results, column );
-	column = purple_notify_searchresults_column_new( _( "Where I live" ) );
-	purple_notify_searchresults_column_add( results, column );
-
-	while ( entries != NULL ) {
-		struct MXitProfile* profile	= ( struct MXitProfile *) entries->data;
-		GList*	row;
-		gchar* tmp = purple_base64_encode( (unsigned char *) profile->userid, strlen( profile->userid ) );
-
-		/* column values */
-		row = g_list_append( NULL, g_strdup_printf( "#%s", tmp ) );
-		row = g_list_append( row, g_strdup( profile->nickname ) );
-		row = g_list_append( row, g_strdup( profile->firstname ) );
-		row = g_list_append( row, g_strdup( profile->lastname ) );
-		row = g_list_append( row, g_strdup( profile->male ? "Male" : "Female" ) );
-		row = g_list_append( row, g_strdup_printf( "%i", calculateAge( profile->birthday ) ) );
-		row = g_list_append( row, g_strdup( profile->whereami ) );
-
-		purple_notify_searchresults_row_add( results, row );
-		entries = g_list_next( entries );
-
-		g_free( tmp );
-	}
-
-	/* button */
-	purple_notify_searchresults_button_add( results, PURPLE_NOTIFY_BUTTON_INVITE, mxit_search_results_add_cb );
-
-	if ( searchType == CP_SUGGEST_FRIENDS )
-		text = g_strdup_printf( dngettext( PACKAGE, "You have %i suggested friend.", "You have %i suggested friends.", maxResults ), maxResults );
-	else
-		text = g_strdup_printf( dngettext( PACKAGE, "We found %i contact that matches your search.", "We found %i contacts that match your search.", maxResults ), maxResults );
-
-	purple_notify_searchresults( session->con, NULL, text, NULL, results, NULL, NULL );
-
-	g_free( text );
-}
--- a/libpurple/protocols/mxit/profile.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *					-- user profile's --
- *
- *				Andrew Victor	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * 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		_MXIT_PROFILE_H_
-#define		_MXIT_PROFILE_H_
-
-
-/* MXit relationship status types */
-#define MXIT_RELATIONSHIP_UNKNOWN		0
-#define MXIT_RELATIONSHIP_DONTSAY		1
-#define MXIT_RELATIONSHIP_SINGLE		2
-#define MXIT_RELATIONSHIP_INVOLVED		3
-#define MXIT_RELATIONSHIP_ENGAGED		4
-#define MXIT_RELATIONSHIP_MARRIED		5
-#define MXIT_RELATIONSHIP_COMPLICATED	6
-#define MXIT_RELATIONSHIP_WIDOWED		7
-#define MXIT_RELATIONSHIP_SEPARATED		8
-#define MXIT_RELATIONSHIP_DIVORCED		9
-
-struct MXitProfile {
-	/* required */
-	char		loginname[64];						/* name user uses to log into MXit with (aka 'mxitid') */
-	char		userid[51];							/* internal UserId (only in search results) */
-	char		nickname[101];						/* user's own display name (aka 'display name', aka 'fullname', aka 'alias') in MXit */
-	char		birthday[16];						/* user's birthday "YYYY-MM-DD" */
-	gboolean	male;								/* true if the user's gender is male (otherwise female) */
-	char		pin[16];							/* user's password */
-
-	/* optional */
-	char		title[21];							/* user's title */
-	char		firstname[51];						/* user's first name */
-	char		lastname[51];						/* user's last name (aka 'surname') */
-	char		email[201];							/* user's email address */
-	char		mobilenr[21];						/* user's mobile number */
-	char		regcountry[3];						/* user's registered country code */
-	char		whereami[51];						/* where am I / where I live */
-	char		aboutme[513];						/* about me */
-	int			relationship;						/* relationship status */
-
-	gint64		flags;								/* user's profile flags */
-	gint64		lastonline;							/* user's last-online timestamp */
-};
-
-struct MXitSession;
-void mxit_show_profile( struct MXitSession* session, const char* username, struct MXitProfile* profile );
-void mxit_show_search_results( struct MXitSession* session, int searchType, int maxResults, GList* entries );
-const char* mxit_relationship_to_name( short id );
-
-gboolean validateDate( const char* bday );
-
-
-#endif		/* _MXIT_PROFILE_H_ */
--- a/libpurple/protocols/mxit/protocol.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3008 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *			-- MXit client protocol implementation --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include	"internal.h"
-#include	"debug.h"
-#include	"version.h"
-
-#include	"protocol.h"
-#include	"mxit.h"
-#include	"roster.h"
-#include	"chunk.h"
-#include	"filexfer.h"
-#include	"markup.h"
-#include	"multimx.h"
-#include	"splashscreen.h"
-#include	"login.h"
-#include	"formcmds.h"
-#include	"http.h"
-#include	"cipher.h"
-
-
-#define		MXIT_MS_OFFSET		3
-
-/* configure the right record terminator char to use */
-#define		CP_REC_TERM			( ( session->http ) ? CP_HTTP_REC_TERM : CP_SOCK_REC_TERM )
-
-
-/*------------------------------------------------------------------------
- * return the current timestamp in milliseconds
- */
-gint64 mxit_now_milli( void )
-{
-	GTimeVal	now;
-
-	g_get_current_time( &now );
-
-	return ( ( now.tv_sec * 1000 ) + ( now.tv_usec / 1000 ) );
-}
-
-
-/*------------------------------------------------------------------------
- * Display a notification popup message to the user.
- *
- *  @param type			The type of notification:
- *		- info:		PURPLE_NOTIFY_MSG_INFO
- *		- warning:	PURPLE_NOTIFY_MSG_WARNING
- *		- error:	PURPLE_NOTIFY_MSG_ERROR
- *  @param heading		Heading text
- *  @param message		Message text
- */
-void mxit_popup( int type, const char* heading, const char* message )
-{
-	/* (reference: "libpurple/notify.h") */
-	purple_notify_message( NULL, type, _( MXIT_POPUP_WIN_NAME ), heading, message, NULL, NULL );
-}
-
-
-/*------------------------------------------------------------------------
- * For compatibility with legacy clients, all usernames are sent from MXit with a domain
- *  appended.  For MXit contacts, this domain is set to "@m".  This function strips
- *  those fake domains.
- *
- *  @param username		The username of the contact
- */
-void mxit_strip_domain( char* username )
-{
-	if ( g_str_has_suffix( username, "@m" ) )
-		username[ strlen( username ) - 2 ] = '\0';
-}
-
-
-/*------------------------------------------------------------------------
- * Dump a byte buffer to the console for debugging purposes.
- *
- *  @param buf			The data
- *  @param len			The data length
- */
-void dump_bytes( struct MXitSession* session, const char* buf, int len )
-{
-	char*	msg	= g_malloc0( len + 1 );
-	int		i;
-
-	for ( i = 0; i < len; i++ ) {
-		char ch	= buf[i];
-
-		if ( ch == CP_REC_TERM )		/* record terminator */
-			msg[i] = '!';
-		else if ( ch == CP_FLD_TERM )	/* field terminator */
-			msg[i] = '^';
-		else if ( ch == CP_PKT_TERM )	/* packet terminator */
-			msg[i] = '@';
-		else if ( ( ch < 0x20 ) || ( ch > 0x7E ) )		/* non-printable character */
-			msg[i] = '_';
-		else
-			msg[i] = ch;
-	}
-
-	purple_debug_info( MXIT_PLUGIN_ID, "DUMP: '%s'\n", msg );
-
-	g_free( msg );
-}
-
-
-/*------------------------------------------------------------------------
- * Determine if we have an active chat with a specific contact
- *
- *  @param session		The MXit session object
- *  @param who			The contact name
- *  @return				Return true if we have an active chat with the contact
- */
-gboolean find_active_chat( const GList* chats, const char* who )
-{
-	const GList*	list	= chats;
-	const char*		chat	= NULL;
-
-	while ( list ) {
-		chat = (const char*) list->data;
-
-		if ( strcmp( chat, who ) == 0 )
-			return TRUE;
-
-		list = g_list_next( list );
-	}
-
-	return FALSE;
-}
-
-
-/*------------------------------------------------------------------------
- * scnprintf
- *
- *	@param string		The destination buffer.
- *	@param size			The maximum size of the destination buffer.
- * 	@param format		The format string
- *	@param ...			The parameters to the format string.
- *	@return				The number of characters actually stored in the buffer.
- */
-static int scnprintf( gchar* string, size_t size, const char *format, ... )
-{
-	va_list args;
-	guint i;
-
-	va_start( args, format );
-	i = g_vsnprintf( string, size, format, args );
-	va_end( args );
-
-	if ( i < size )
-		return i;
-	else if ( size > 0 )		/* destination buffer too short - return number of characters actually inserted */
-		return size - 1;
-	else
-		return 0;
-}
-
-
-
-/*========================================================================================================================
- * Low-level Packet transmission
- */
-
-/*------------------------------------------------------------------------
- * Remove next packet from transmission queue.
- *
- *  @param session		The MXit session object
- *  @return				The next packet for transmission (or NULL)
- */
-static struct tx_packet* pop_tx_packet( struct MXitSession* session )
-{
-	struct tx_packet*	packet	= NULL;
-
-	if ( session->queue.count > 0 ) {
-		/* dequeue the next packet */
-		packet = session->queue.packets[session->queue.rd_i];
-		session->queue.packets[session->queue.rd_i] = NULL;
-		session->queue.rd_i = ( session->queue.rd_i + 1 ) % MAX_QUEUE_SIZE;
-		session->queue.count--;
-	}
-
-	return packet;
-}
-
-
-/*------------------------------------------------------------------------
- * Add packet to transmission queue.
- *
- *  @param session		The MXit session object
- *  @param packet		The packet to transmit
- *  @return				Return TRUE if packet was enqueue, or FALSE if queue is full.
- */
-static gboolean push_tx_packet( struct MXitSession* session, struct tx_packet* packet )
-{
-	if ( session->queue.count < MAX_QUEUE_SIZE ) {
-		/* enqueue packet */
-		session->queue.packets[session->queue.wr_i] = packet;
-		session->queue.wr_i = ( session->queue.wr_i + 1 ) % MAX_QUEUE_SIZE;
-		session->queue.count++;
-		return TRUE;
-	}
-	else
-		return FALSE;		/* queue is full */
-}
-
-
-/*------------------------------------------------------------------------
- * Deallocate transmission packet.
- *
- *  @param packet		The packet to deallocate.
- */
-static void free_tx_packet( struct tx_packet* packet )
-{
-	g_free( packet->data );
-	g_free( packet );
-	packet = NULL;
-}
-
-
-/*------------------------------------------------------------------------
- * Flush all the packets from the tx queue and release the resources.
- *
- *  @param session		The MXit session object
- */
-static void flush_queue( struct MXitSession* session )
-{
-	struct tx_packet*	packet;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "flushing the tx queue\n" );
-
-	while ( (packet = pop_tx_packet( session ) ) != NULL )
-		free_tx_packet( packet );
-}
-
-
-/*------------------------------------------------------------------------
- * TX Step 3: Write the packet data to the TCP connection.
- *
- *  @param fd			The file descriptor
- *  @param pktdata		The packet data
- *  @param pktlen		The length of the packet data
- *  @return				Return -1 on error, otherwise 0
- */
-static int mxit_write_sock_packet( int fd, const char* pktdata, int pktlen )
-{
-	int		written;
-	int		res;
-
-	written = 0;
-	while ( written < pktlen ) {
-		res = write( fd, &pktdata[written], pktlen - written );
-		if ( res <= 0 ) {
-			/* error on socket */
-			if ( errno == EAGAIN )
-				continue;
-
-			purple_debug_error( MXIT_PLUGIN_ID, "Error while writing packet to MXit server (%i)\n", res );
-			return -1;
-		}
-		written += res;
-	}
-
-	return 0;
-}
-
-
-/*------------------------------------------------------------------------
- * Callback called for handling a HTTP GET response
- *
- *  @param url_data			libPurple internal object (see purple_util_fetch_url_request)
- *  @param user_data		The MXit session object
- *  @param url_text			The data returned (could be NULL if error)
- *  @param len				The length of the data returned (0 if error)
- *  @param error_message	Descriptive error message
- */
-static void mxit_cb_http_rx( PurpleUtilFetchUrlData* url_data, gpointer user_data, const gchar* url_text, gsize len, const gchar* error_message )
-{
-	struct MXitSession*		session		= (struct MXitSession*) user_data;
-
-	/* clear outstanding request */
-	session->async_calls = g_slist_remove( session->async_calls, url_data );
-
-	if ( ( !url_text ) || ( len == 0 ) ) {
-		/* error with request */
-		purple_debug_error( MXIT_PLUGIN_ID, "HTTP response error (%s)\n", error_message );
-		return;
-	}
-
-	/* convert the HTTP result */
-	memcpy( session->rx_dbuf, url_text, len );
-	session->rx_i = len;
-
-	mxit_parse_packet( session );
-}
-
-
-/*------------------------------------------------------------------------
- * TX Step 3: Write the packet data to the HTTP connection (GET style).
- *
- *  @param session		The MXit session object
- *  @param pktdata		The packet data
- *  @param pktlen		The length of the packet data
- *  @return				Return -1 on error, otherwise 0
- */
-static void mxit_write_http_get( struct MXitSession* session, struct tx_packet* packet )
-{
-	PurpleUtilFetchUrlData*	url_data;
-	char*		part	= NULL;
-	char*		url		= NULL;
-
-	if ( packet->datalen > 0 ) {
-		char*	tmp		= NULL;
-
-		tmp = g_strndup( packet->data, packet->datalen );
-		part = g_strdup( purple_url_encode( tmp ) );
-		g_free( tmp );
-	}
-
-	url = g_strdup_printf( "%s?%s%s", session->http_server, purple_url_encode( packet->header ), ( !part ) ? "" : part );
-
-#ifdef	DEBUG_PROTOCOL
-	purple_debug_info( MXIT_PLUGIN_ID, "HTTP GET: '%s'\n", url );
-#endif
-
-	/* send the HTTP request */
-	url_data = purple_util_fetch_url_request( url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, mxit_cb_http_rx, session );
-	if ( url_data )
-		session->async_calls = g_slist_prepend( session->async_calls, url_data );
-
-	g_free( url );
-	if ( part )
-		g_free( part );
-}
-
-
-/*------------------------------------------------------------------------
- * TX Step 3: Write the packet data to the HTTP connection (POST style).
- *
- *  @param session		The MXit session object
- *  @param pktdata		The packet data
- *  @param pktlen		The length of the packet data
- *  @return				Return -1 on error, otherwise 0
- */
-static void mxit_write_http_post( struct MXitSession* session, struct tx_packet* packet )
-{
-	char*		host_name;
-	int			host_port;
-	gboolean	ok;
-	gchar*		httpheader;
-
-	/* extract the HTTP host name and host port number to connect to */
-	ok = purple_url_parse( session->http_server, &host_name, &host_port, NULL, NULL, NULL );
-	if ( !ok ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "HTTP POST error: (host name '%s' not valid)\n", session->http_server );
-	}
-
-	/* strip off the last '&' from the header */
-	packet->header[packet->headerlen - 1] = '\0';
-	packet->headerlen--;
-
-	/* build the HTTP request header */
-	httpheader = g_strdup_printf(
-					"POST %s?%s HTTP/1.1\r\n"
-					"User-Agent: " MXIT_HTTP_USERAGENT "\r\n"
-					"Content-Type: application/octet-stream\r\n"
-					"Host: %s\r\n"
-					"Content-Length: %d\r\n"
-					"\r\n",
-					session->http_server,
-					purple_url_encode( packet->header ),
-					host_name,
-					packet->datalen - MXIT_MS_OFFSET
-	);
-
-#ifdef	DEBUG_PROTOCOL
-	purple_debug_info( MXIT_PLUGIN_ID, "HTTP POST:\n" );
-	dump_bytes( session, httpheader, strlen( httpheader ) );
-	dump_bytes( session, packet->data + MXIT_MS_OFFSET, packet->datalen - MXIT_MS_OFFSET );
-#endif
-
-	/* send the request to the HTTP server */
-	mxit_http_send_request( session, host_name, host_port, httpheader, packet->data + MXIT_MS_OFFSET, packet->datalen - MXIT_MS_OFFSET );
-
-	/* cleanup */
-	g_free( httpheader );
-}
-
-
-/*------------------------------------------------------------------------
- * TX Step 2: Handle the transmission of the packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param packet		The packet to transmit
- */
-static void mxit_send_packet( struct MXitSession* session, struct tx_packet* packet )
-{
-	int		res;
-
-	if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) {
-		/* we are not connected so ignore all packets to be send */
-		purple_debug_error( MXIT_PLUGIN_ID, "Dropping TX packet (we are not connected)\n" );
-		return;
-	}
-
-	purple_debug_info( MXIT_PLUGIN_ID, "Packet send CMD:%i (%i)\n", packet->cmd, packet->headerlen + packet->datalen );
-#ifdef	DEBUG_PROTOCOL
-	dump_bytes( session, packet->header, packet->headerlen );
-	dump_bytes( session, packet->data, packet->datalen );
-#endif
-
-	if ( !session->http ) {
-		/* socket connection */
-		char		data[packet->datalen + packet->headerlen];
-		int			datalen;
-
-		/* create raw data buffer */
-		memcpy( data, packet->header, packet->headerlen );
-		memcpy( data + packet->headerlen, packet->data, packet->datalen );
-		datalen = packet->headerlen + packet->datalen;
-
-		res = mxit_write_sock_packet( session->fd, data, datalen );
-		if ( res < 0 ) {
-			/* we must have lost the connection, so terminate it so that we can reconnect */
-			purple_connection_error( session->con, _( "We have lost the connection to MXit. Please reconnect." ) );
-		}
-	}
-	else {
-		/* http connection */
-
-		if ( packet->cmd == CP_CMD_MEDIA ) {
-			/* multimedia packets must be send with a HTTP POST */
-			mxit_write_http_post( session, packet );
-		}
-		else {
-			mxit_write_http_get( session, packet );
-		}
-	}
-
-	/* update the timestamp of the last-transmitted packet */
-	session->last_tx = mxit_now_milli();
-
-	/*
-	 * we need to remember that we are still waiting for the ACK from
-	 * the server on this request
-	 */
-	session->outack = packet->cmd;
-
-	/* free up the packet resources */
-	free_tx_packet( packet );
-}
-
-
-/*------------------------------------------------------------------------
- * TX Step 1: Create a new Tx packet and queue it for sending.
- *
- *  @param session		The MXit session object
- *  @param data			The packet data (payload)
- *  @param datalen		The length of the packet data
- *  @param cmd			The MXit command for this packet
- */
-static void mxit_queue_packet( struct MXitSession* session, const char* data, int datalen, int cmd )
-{
-	struct tx_packet*	packet;
-	char				header[256];
-	int					hlen;
-
-	/* create a packet for sending */
-	packet = g_new0( struct tx_packet, 1 );
-	packet->data = g_malloc0( datalen );
-	packet->cmd = cmd;
-	packet->headerlen = 0;
-
-	/* create generic packet header */
-	hlen = scnprintf( header, sizeof( header ), "id=%s%c", purple_account_get_username( session->acc ), CP_REC_TERM );	/* client mxitid */
-
-	if ( session->http ) {
-		/* http connection only */
-		hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "s=" );
-		if ( session->http_sesid > 0 ) {
-			hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_sesid, CP_FLD_TERM );	/* http session id */
-		}
-		session->http_seqno++;
-		hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_seqno, CP_REC_TERM );		/* http request sequence id */
-	}
-
-	hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "cm=%i%c", cmd, CP_REC_TERM ); 						/* packet command */
-
-	if ( !session->http ) {
-		/* socket connection only */
-		packet->headerlen = scnprintf( packet->header, sizeof( packet->header ), "ln=%i%c", ( datalen + hlen ), CP_REC_TERM );		/* packet length */
-	}
-
-	/* copy the header to packet */
-	memcpy( packet->header + packet->headerlen, header, hlen );
-	packet->headerlen += hlen;
-
-	/* copy payload to packet */
-	if ( datalen > 0 )
-		memcpy( packet->data, data, datalen );
-	packet->datalen = datalen;
-
-
-	/* shortcut */
-	if ( ( session->queue.count == 0 ) && ( session->outack == 0 ) ) {
-		/* the queue is empty and there are no outstanding acks so we can write it directly */
-		mxit_send_packet( session, packet );
-	}
-	else {
-		/* we need to queue this packet */
-
-		if ( ( packet->cmd == CP_CMD_PING ) || ( packet->cmd == CP_CMD_POLL ) ) {
-			/* we do NOT queue HTTP poll nor socket ping packets */
-			free_tx_packet( packet );
-			return;
-		}
-
-		purple_debug_info( MXIT_PLUGIN_ID, "queueing packet for later sending cmd=%i\n", cmd );
-		if ( !push_tx_packet( session, packet ) ) {
-			/* packet could not be queued for transmission */
-			mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Message Send Error" ), _( "Unable to process your request at this time" ) );
-			free_tx_packet( packet );
-		}
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Manage the packet send queue (send next packet, timeout's, etc).
- *
- *  @param session		The MXit session object
- */
-static void mxit_manage_queue( struct MXitSession* session )
-{
-	struct tx_packet*	packet		= NULL;
-	gint64				now			= mxit_now_milli();
-
-	if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) {
-		/* we are not connected, so ignore the queue */
-		return;
-	}
-	else if ( session->outack > 0 ) {
-		/* we are still waiting for an outstanding ACK from the MXit server */
-		if ( session->last_tx <= mxit_now_milli() - ( MXIT_ACK_TIMEOUT * 1000 ) ) {
-			/* ack timeout! so we close the connection here */
-			purple_debug_info( MXIT_PLUGIN_ID, "mxit_manage_queue: Timeout awaiting ACK for command '%i'\n", session->outack );
-			purple_connection_error( session->con, _( "Timeout while waiting for a response from the MXit server." ) );
-		}
-		return;
-	}
-
-	/*
-	 * the mxit server has flood detection and it prevents you from sending messages to fast.
-	 * this is a self defense mechanism, a very annoying feature. so the client must ensure that
-	 * it does not send messages too fast otherwise mxit will ignore the user for 30 seconds.
-	 * this is what we are trying to avoid here..
-	 */
-	if ( session->q_fast_timer_id == 0 ) {
-		/* the fast timer has not been set yet */
-		if ( session->last_tx > ( now - MXIT_TX_DELAY ) ) {
-			/* we need to wait a little before sending the next packet, so schedule a wakeup call */
-			gint64 tdiff = now - ( session->last_tx );
-			guint delay = ( MXIT_TX_DELAY - tdiff ) + 9;
-			if ( delay <= 0 )
-				delay = MXIT_TX_DELAY;
-			session->q_fast_timer_id = purple_timeout_add( delay, mxit_manage_queue_fast, session );
-		}
-		else {
-			/* get the next packet from the queue to send */
-			packet = pop_tx_packet( session );
-			if ( packet != NULL ) {
-				/* there was a packet waiting to be sent to the server, now is the time to do something about it */
-
-				/* send the packet to MXit server */
-				mxit_send_packet( session, packet );
-			}
-		}
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Slow callback to manage the packet send queue.
- *
- *  @param session		The MXit session object
- */
-gboolean mxit_manage_queue_slow( gpointer user_data )
-{
-	struct MXitSession* session		= (struct MXitSession*) user_data;
-
-	mxit_manage_queue( session );
-
-	/* continue running */
-	return TRUE;
-}
-
-
-/*------------------------------------------------------------------------
- * Fast callback to manage the packet send queue.
- *
- *  @param session		The MXit session object
- */
-gboolean mxit_manage_queue_fast( gpointer user_data )
-{
-	struct MXitSession* session		= (struct MXitSession*) user_data;
-
-	session->q_fast_timer_id = 0;
-	mxit_manage_queue( session );
-
-	/* stop running */
-	return FALSE;
-}
-
-
-/*------------------------------------------------------------------------
- * Callback to manage HTTP server polling (HTTP connections ONLY)
- *
- *  @param session		The MXit session object
- */
-gboolean mxit_manage_polling( gpointer user_data )
-{
-	struct MXitSession* session		= (struct MXitSession*) user_data;
-	gboolean			poll		= FALSE;
-	gint64				now			= mxit_now_milli();
-	gint64				rxdiff;
-
-	if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) ) {
-		/* we only poll if we are actually logged in */
-		return TRUE;
-	}
-
-	/* calculate the time differences */
-	rxdiff = now - session->last_rx;
-
-	if ( rxdiff < MXIT_HTTP_POLL_MIN ) {
-		/* we received some reply a few moments ago, so reset the poll interval */
-		session->http_interval = MXIT_HTTP_POLL_MIN;
-	}
-	else if ( session->http_last_poll < ( now - session->http_interval ) ) {
-		/* time to poll again */
-		poll = TRUE;
-
-		/* back-off some more with the polling */
-		session->http_interval = session->http_interval + ( session->http_interval / 2 );
-		if ( session->http_interval > MXIT_HTTP_POLL_MAX )
-			session->http_interval = MXIT_HTTP_POLL_MAX;
-	}
-
-	/* debugging */
-	//purple_debug_info( MXIT_PLUGIN_ID, "POLL TIMER: %i (%i)\n", session->http_interval, rxdiff );
-
-	if ( poll ) {
-		/* send poll request */
-		session->http_last_poll = mxit_now_milli();
-		mxit_send_poll( session );
-	}
-
-	return TRUE;
-}
-
-
-/*========================================================================================================================
- * Send MXit operations.
- */
-
-/*------------------------------------------------------------------------
- * Send a ping/keepalive packet to MXit server.
- *
- *  @param session		The MXit session object
- */
-void mxit_send_ping( struct MXitSession* session )
-{
-	/* queue packet for transmission */
-	mxit_queue_packet( session, NULL, 0, CP_CMD_PING );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a poll request to the HTTP server (HTTP connections ONLY).
- *
- *  @param session		The MXit session object
- */
-void mxit_send_poll( struct MXitSession* session )
-{
-	/* queue packet for transmission */
-	mxit_queue_packet( session, NULL, 0, CP_CMD_POLL );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a logout packet to the MXit server.
- *
- *  @param session		The MXit session object
- */
-void mxit_send_logout( struct MXitSession* session )
-{
-	/* queue packet for transmission */
-	mxit_queue_packet( session, NULL, 0, CP_CMD_LOGOUT );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a register packet to the MXit server.
- *
- *  @param session		The MXit session object
- */
-void mxit_send_register( struct MXitSession* session )
-{
-	struct MXitProfile*	profile		= session->profile;
-	const char*			locale;
-	char				data[CP_MAX_PACKET];
-	int					datalen;
-	char*				clientVersion;
-	unsigned int		features	= MXIT_CP_FEATURES;
-
-	locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE );
-
-	/* generate client version string (eg, P-2.7.10-Y-PURPLE) */
-	clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM );
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ),
-								"ms=%s%c%s%c%i%c%s%c"		/* "ms"=password\1version\1maxreplyLen\1name\1 */
-								"%s%c%i%c%s%c%s%c"			/* dateOfBirth\1gender\1location\1capabilities\1 */
-								"%s%c%i%c%s%c%s"			/* dc\1features\1dialingcode\1locale */
-								"%c%i%c%i",					/* \1protocolVer\1lastRosterUpdate */
-								session->encpwd, CP_FLD_TERM, clientVersion, CP_FLD_TERM, CP_MAX_FILESIZE, CP_FLD_TERM, profile->nickname, CP_FLD_TERM,
-								profile->birthday, CP_FLD_TERM, ( profile->male ) ? 1 : 0, CP_FLD_TERM, MXIT_DEFAULT_LOC, CP_FLD_TERM, MXIT_CP_CAP, CP_FLD_TERM,
-								session->distcode, CP_FLD_TERM, features, CP_FLD_TERM, session->dialcode, CP_FLD_TERM, locale,
-								CP_FLD_TERM, MXIT_CP_PROTO_VESION, CP_FLD_TERM, 0
-	);
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_REGISTER );
-
-	g_free( clientVersion );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a login packet to the MXit server.
- *
- *  @param session		The MXit session object
- */
-void mxit_send_login( struct MXitSession* session )
-{
-	const char*		splashId;
-	const char*		locale;
-	char			data[CP_MAX_PACKET];
-	int				datalen;
-	char*			clientVersion;
-	unsigned int	features	= MXIT_CP_FEATURES;
-
-	locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE );
-
-	/* generate client version string (eg, P-2.7.10-Y-PURPLE) */
-	clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM );
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ),
-								"ms=%s%c%s%c%i%c"			/* "ms"=password\1version\1getContacts\1 */
-								"%s%c%s%c%i%c"				/* capabilities\1dc\1features\1 */
-								"%s%c%s%c"					/* dialingcode\1locale\1 */
-								"%i%c%i%c%i",				/* maxReplyLen\1protocolVer\1lastRosterUpdate */
-								session->encpwd, CP_FLD_TERM, clientVersion, CP_FLD_TERM, 1, CP_FLD_TERM,
-								MXIT_CP_CAP, CP_FLD_TERM, session->distcode, CP_FLD_TERM, features, CP_FLD_TERM,
-								session->dialcode, CP_FLD_TERM, locale, CP_FLD_TERM,
-								CP_MAX_FILESIZE, CP_FLD_TERM, MXIT_CP_PROTO_VESION, CP_FLD_TERM, 0
-	);
-
-	/* include "custom resource" information */
-	splashId = splash_current( session );
-	if ( splashId != NULL )
-		datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%ccr=%s", CP_REC_TERM, splashId );
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_LOGIN );
-
-	g_free( clientVersion );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a chat message packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param to			The username of the recipient
- *  @param msg			The message text
- */
-void mxit_send_message( struct MXitSession* session, const char* to, const char* msg, gboolean parse_markup, gboolean is_command )
-{
-	char		data[CP_MAX_PACKET];
-	char*		markuped_msg;
-	int			datalen;
-	int			msgtype = ( is_command ? CP_MSGTYPE_COMMAND : CP_MSGTYPE_NORMAL );
-
-	/* first we need to convert the markup from libPurple to MXit format */
-	if ( parse_markup )
-		markuped_msg = mxit_convert_markup_tx( msg, &msgtype );
-	else
-		markuped_msg = g_strdup( msg );
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ),
-								"ms=%s%c%s%c%i%c%i",		/* "ms"=jid\1msg\1type\1flags */
-								to, CP_FLD_TERM, markuped_msg, CP_FLD_TERM, msgtype, CP_FLD_TERM, CP_MSG_MARKUP | CP_MSG_EMOTICON
-	);
-
-	/* free the resources */
-	g_free( markuped_msg );
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_TX_MSG );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a extended profile request packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param username		Username who's profile is being requested (NULL = our own)
- *  @param nr_attribs	Number of attributes being requested
- *  @param attribute	The names of the attributes
- */
-void mxit_send_extprofile_request( struct MXitSession* session, const char* username, unsigned int nr_attrib, const char* attribute[] )
-{
-	char			data[CP_MAX_PACKET];
-	int				datalen;
-	unsigned int	i;
-
-	datalen = scnprintf( data, sizeof( data ),
-								"ms=%s%c%i",		/* "ms="mxitid\1nr_attributes */
-								( username ? username : "" ), CP_FLD_TERM, nr_attrib
-	);
-
-	/* add attributes */
-	for ( i = 0; i < nr_attrib; i++ )
-		datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_GET );
-}
-
-
-/*------------------------------------------------------------------------
- * Send an update profile packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param password		The new password to be used for logging in (optional)
- *	@param nr_attrib	The number of attributes
- *	@param attributes	String containing the attribute-name, attribute-type and value (seperated by '\01')
- */
-void mxit_send_extprofile_update( struct MXitSession* session, const char* password, unsigned int nr_attrib, const char* attributes )
-{
-	char			data[CP_MAX_PACKET];
-	gchar**			parts					= NULL;
-	int				datalen;
-	unsigned int	i;
-
-	if ( attributes )
-		parts = g_strsplit( attributes, "\01", 1 + ( nr_attrib * 3 ) );
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ),
-								"ms=%s%c%i",	/* "ms"=password\1nr_attibutes  */
-								( password ) ? password : "", CP_FLD_TERM, nr_attrib
-	);
-
-	/* add attributes */
-	for ( i = 1; i < nr_attrib * 3; i+=3 ) {
-		if ( parts == NULL || parts[i] == NULL || parts[i + 1] == NULL || parts[i + 2] == NULL ) {
-			purple_debug_error( MXIT_PLUGIN_ID, "Invalid profile update attributes = '%s' - nbr=%u\n", attributes, nr_attrib );
-			g_strfreev( parts );
-			return;
-		}
-		datalen += scnprintf( data + datalen, sizeof( data ) - datalen,
-								"%c%s%c%s%c%s",		/* \1name\1type\1value  */
-								CP_FLD_TERM, parts[i], CP_FLD_TERM, parts[i + 1], CP_FLD_TERM, parts[i + 2] );
-	}
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_SET );
-
-	/* freeup the memory */
-	g_strfreev( parts );
-}
-
-
-/*------------------------------------------------------------------------
- * Send packet to request list of suggested friends.
- *
- *  @param session		The MXit session object
- *  @param max			Maximum number of results to return
- *  @param nr_attribs	Number of attributes being requested
- *  @param attribute	The names of the attributes
- */
-void mxit_send_suggest_friends( struct MXitSession* session, int max, unsigned int nr_attrib, const char* attribute[] )
-{
-	char			data[CP_MAX_PACKET];
-	int				datalen;
-	unsigned int	i;
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ),
-								"ms=%i%c%s%c%i%c%i%c%i",	/* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */
-								CP_SUGGEST_FRIENDS, CP_FLD_TERM, "", CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib );
-
-	/* add attributes */
-	for ( i = 0; i < nr_attrib; i++ )
-		datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
-}
-
-
-/*------------------------------------------------------------------------
- * Send packet to perform a search for users.
- *
- *  @param session		The MXit session object
- *  @param max			Maximum number of results to return
- *  @param text			The search text
- *  @param nr_attribs	Number of attributes being requested
- *  @param attribute	The names of the attributes
- */
-void mxit_send_suggest_search( struct MXitSession* session, int max, const char* text, unsigned int nr_attrib, const char* attribute[] )
-{
-	char			data[CP_MAX_PACKET];
-	int				datalen;
-	unsigned int	i;
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ),
-								"ms=%i%c%s%c%i%c%i%c%i",	/* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */
-								CP_SUGGEST_SEARCH, CP_FLD_TERM, text, CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib );
-
-	/* add attributes */
-	for ( i = 0; i < nr_attrib; i++ )
-		datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a presence update packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param presence		The presence (as per MXit types)
- *  @param statusmsg	The status message (can be NULL)
- */
-void mxit_send_presence( struct MXitSession* session, int presence, const char* statusmsg )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ),
-								"ms=%i%c",					/* "ms"=show\1status */
-								presence, CP_FLD_TERM
-	);
-
-	/* append status message (if one is set) */
-	if ( statusmsg )
-		datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%s", statusmsg );
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_STATUS );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a mood update packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param mood			The mood (as per MXit types)
- */
-void mxit_send_mood( struct MXitSession* session, int mood )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ),
-								"ms=%i",	/* "ms"=mood */
-								mood
-	);
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_MOOD );
-}
-
-
-/*------------------------------------------------------------------------
- * Send an invite contact packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param username		The username of the contact being invited
- *  @param mxitid		Indicates the username is a MXitId.
- *  @param alias		Our alias for the contact
- *  @param groupname	Group in which contact should be stored.
- *  @param message		Invite message
- */
-void mxit_send_invite( struct MXitSession* session, const char* username, gboolean mxitid, const char* alias, const char* groupname, const char* message )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ),
-								"ms=%s%c%s%c%s%c%i%c%s%c%i",	/* "ms"=group \1 username \1 alias \1 type \1 msg \1 isuserid */
-								groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias,
-								CP_FLD_TERM, MXIT_TYPE_MXIT, CP_FLD_TERM,
-								( message ? message : "" ), CP_FLD_TERM,
-								( mxitid ? 0 : 1 )
-	);
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_INVITE );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a remove contact packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param username		The username of the contact being removed
- */
-void mxit_send_remove( struct MXitSession* session, const char* username )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ),
-								"ms=%s",	/* "ms"=username */
-								username
-	);
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_REMOVE );
-}
-
-
-/*------------------------------------------------------------------------
- * Send an accept subscription (invite) packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param username		The username of the contact being accepted
- *  @param alias		Our alias for the contact
- */
-void mxit_send_allow_sub( struct MXitSession* session, const char* username, const char* alias )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ),
-								"ms=%s%c%s%c%s",	/* "ms"=username\1group\1alias */
-								username, CP_FLD_TERM, "", CP_FLD_TERM, alias
-	);
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_ALLOW );
-}
-
-
-/*------------------------------------------------------------------------
- * Send an deny subscription (invite) packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param username		The username of the contact being denied
- *  @param reason		The message describing the reason for the rejection (can be NULL).
- */
-void mxit_send_deny_sub( struct MXitSession* session, const char* username, const char* reason )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ),
-								"ms=%s",	/* "ms"=username */
-								username
-	);
-
-	/* append reason (if one is set) */
-	if ( reason )
-		datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, reason );
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_DENY );
-}
-
-
-/*------------------------------------------------------------------------
- * Send an update contact packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param username		The username of the contact being denied
- *  @param alias		Our alias for the contact
- *  @param groupname	Group in which contact should be stored.
- */
-void mxit_send_update_contact( struct MXitSession* session, const char* username, const char* alias, const char* groupname )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ),
-								"ms=%s%c%s%c%s",	/* "ms"=groupname\1username\1alias */
-								groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias
-	);
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_UPDATE );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a splash-screen click event packet.
- *
- *  @param session		The MXit session object
- *  @param splashid		The identifier of the splash-screen
- */
-void mxit_send_splashclick( struct MXitSession* session, const char* splashid )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ),
-								"ms=%s",	/* "ms"=splashId */
-								splashid
-	);
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_SPLASHCLICK );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a message event packet.
- *
- *  @param session		The MXit session object
- *  @param to           The username of the original sender (ie, recipient of the event)
- *  @param id			The identifier of the event (received in message)
- *  @param event		Identified the type of event
- */
-void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_msgevent: to=%s id=%s event=%i\n", to, id, event );
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ),
-								"ms=%s%c%s%c%i",		/* "ms"=contactAddress \1 id \1 event */
-								to, CP_FLD_TERM, id, CP_FLD_TERM, event
-	);
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_MSGEVENT );
-}
-
-
-/*------------------------------------------------------------------------
- * Send packet to create a MultiMX room.
- *
- *  @param session		The MXit session object
- *  @param groupname	Name of the room to create
- *  @param nr_usernames	Number of users in initial invite
- *  @param usernames	The usernames of the users in the initial invite
- */
-void mxit_send_groupchat_create( struct MXitSession* session, const char* groupname, int nr_usernames, const char* usernames[] )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-	int			i;
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ),
-								"ms=%s%c%i",	/* "ms"=roomname\1nr_jids\1jid0\1..\1jidN */
-								groupname, CP_FLD_TERM, nr_usernames
-	);
-
-	/* add usernames */
-	for ( i = 0; i < nr_usernames; i++ )
-		datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_CREATE );
-}
-
-
-/*------------------------------------------------------------------------
- * Send packet to invite users to existing MultiMX room.
- *
- *  @param session		The MXit session object
- *  @param roomid		The unique RoomID for the MultiMx room.
- *  @param nr_usernames	Number of users being invited
- *  @param usernames	The usernames of the users being invited
- */
-void mxit_send_groupchat_invite( struct MXitSession* session, const char* roomid, int nr_usernames, const char* usernames[] )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-	int			i;
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ),
-								"ms=%s%c%i",	/* "ms"=roomid\1nr_jids\1jid0\1..\1jidN */
-								roomid, CP_FLD_TERM, nr_usernames
-	);
-
-	/* add usernames */
-	for ( i = 0; i < nr_usernames; i++ )
-		datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_INVITE );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a "send file direct" multimedia packet.
- *
- *  @param session		The MXit session object
- *  @param username		The username of the recipient
- *  @param filename		The name of the file being sent
- *  @param buf			The content of the file
- *  @param buflen		The length of the file contents
- */
-void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, size_t buflen )
-{
-	char				data[CP_MAX_PACKET];
-	int					datalen		= 0;
-	gchar*				chunk;
-	size_t				chunksize;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %zu bytes to user '%s'\n", filename, buflen, username );
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ), "ms=" );
-
-	/* map chunk header over data buffer */
-	chunk = &data[datalen];
-
-	/* encode chunk */
-	chunksize = mxit_chunk_create_senddirect( chunk_data( chunk ), username, filename, buf, buflen );
-	set_chunk_type( chunk, CP_CHUNK_DIRECT_SND );
-	set_chunk_length( chunk, chunksize );
-	datalen += MXIT_CHUNK_HEADER_SIZE + chunksize;
-
-	/* send the byte stream to the mxit server */
-	mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a "reject file" multimedia packet.
- *
- *  @param session		The MXit session object
- *  @param fileid		A unique ID that identifies this file
- */
-void mxit_send_file_reject( struct MXitSession* session, const char* fileid )
-{
-	char				data[CP_MAX_PACKET];
-	int					datalen		= 0;
-	gchar*				chunk;
-	size_t				chunksize;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_reject\n" );
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ), "ms=" );
-
-	/* map chunk header over data buffer */
-	chunk = &data[datalen];
-
-	/* encode chunk */
-	chunksize = mxit_chunk_create_reject( chunk_data( chunk ), fileid );
-	set_chunk_type( chunk, CP_CHUNK_REJECT );
-	set_chunk_length( chunk, chunksize );
-	datalen += MXIT_CHUNK_HEADER_SIZE + chunksize;
-
-	/* send the byte stream to the mxit server */
-	mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a "get file" multimedia packet.
- *
- *  @param session		The MXit session object
- *  @param fileid		A unique ID that identifies this file
- *  @param filesize		The number of bytes to retrieve
- *  @param offset		Offset in file at which to start retrieving
- */
-void mxit_send_file_accept( struct MXitSession* session, const char* fileid, size_t filesize, size_t offset )
-{
-	char				data[CP_MAX_PACKET];
-	int					datalen		= 0;
-	gchar*				chunk;
-	size_t				chunksize;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_accept\n" );
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ), "ms=" );
-
-	/* map chunk header over data buffer */
-	chunk = &data[datalen];
-
-	/* encode chunk */
-	chunksize = mxit_chunk_create_get( chunk_data(chunk), fileid, filesize, offset );
-	set_chunk_type( chunk, CP_CHUNK_GET );
-	set_chunk_length( chunk, chunksize );
-	datalen += MXIT_CHUNK_HEADER_SIZE + chunksize;
-
-	/* send the byte stream to the mxit server */
-	mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a "received file" multimedia packet.
- *
- *  @param session		The MXit session object
- *  @param status		The status of the file-transfer
- */
-void mxit_send_file_received( struct MXitSession* session, const char* fileid, short status )
-{
-	char				data[CP_MAX_PACKET];
-	int					datalen		= 0;
-	gchar*				chunk;
-	size_t				chunksize;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_received\n" );
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ), "ms=" );
-
-	/* map chunk header over data buffer */
-	chunk = &data[datalen];
-
-	/* encode chunk */
-	chunksize = mxit_chunk_create_received( chunk_data(chunk), fileid, status );
-	set_chunk_type( chunk, CP_CHUNK_RECEIVED );
-	set_chunk_length( chunk, chunksize );
-	datalen += MXIT_CHUNK_HEADER_SIZE + chunksize;
-
-	/* send the byte stream to the mxit server */
-	mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a "set avatar" multimedia packet.
- *
- *  @param session		The MXit session object
- *  @param data			The avatar data
- *  @param buflen		The length of the avatar data
- */
-void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, size_t avatarlen )
-{
-	char				data[CP_MAX_PACKET];
-	int					datalen		= 0;
-	gchar*				chunk;
-	size_t				chunksize;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %zu bytes\n", avatarlen );
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ), "ms=" );
-
-	/* map chunk header over data buffer */
-	chunk = &data[datalen];
-
-	/* encode chunk */
-	chunksize = mxit_chunk_create_set_avatar( chunk_data(chunk), avatar, avatarlen );
-	set_chunk_type( chunk, CP_CHUNK_SET_AVATAR );
-	set_chunk_length( chunk, chunksize );
-	datalen += MXIT_CHUNK_HEADER_SIZE + chunksize;
-
-	/* send the byte stream to the mxit server */
-	mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a "get avatar" multimedia packet.
- *
- *  @param session		The MXit session object
- *  @param mxitId		The username who's avatar to request
- *  @param avatarId		The id of the avatar image (as string)
- *  @param data			The avatar data
- *  @param buflen		The length of the avatar data
- */
-void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const char* avatarId )
-{
-	char				data[CP_MAX_PACKET];
-	int					datalen		= 0;
-	gchar*				chunk;
-	size_t				chunksize;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_avatar: %s\n", mxitId );
-
-	/* convert the packet to a byte stream */
-	datalen = scnprintf( data, sizeof( data ), "ms=" );
-
-	/* map chunk header over data buffer */
-	chunk = &data[datalen];
-
-	/* encode chunk */
-	chunksize = mxit_chunk_create_get_avatar( chunk_data(chunk), mxitId, avatarId );
-	set_chunk_type( chunk, CP_CHUNK_GET_AVATAR );
-	set_chunk_length( chunk, chunksize );
-	datalen += MXIT_CHUNK_HEADER_SIZE + chunksize;
-
-	/* send the byte stream to the mxit server */
-	mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
-}
-
-
-/*------------------------------------------------------------------------
- * Process a login message packet.
- *
- *  @param session		The MXit session object
- *  @param records		The packet's data records
- *  @param rcount		The number of data records
- */
-static void mxit_parse_cmd_login( struct MXitSession* session, struct record** records, int rcount )
-{
-	PurpleStatus*	status;
-	int				presence;
-	const char*		statusmsg;
-	const char*		profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME,
-									CP_PROFILE_TITLE, CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_EMAIL,
-									CP_PROFILE_MOBILENR, CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME, CP_PROFILE_RELATIONSHIP, CP_PROFILE_FLAGS };
-
-	purple_account_set_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
-
-	/* we were not yet logged in so we need to complete the login sequence here */
-	session->flags |= MXIT_FLAG_LOGGEDIN;
-	purple_connection_update_progress( session->con, _( "Successfully Logged In..." ), 3, 4 );
-	purple_connection_set_state( session->con, PURPLE_CONNECTED );
-
-	/* save extra info if this is a HTTP connection */
-	if ( session->http ) {
-		/* save the http server to use for this session */
-		g_strlcpy( session->http_server, records[1]->fields[3]->data, sizeof( session->http_server ) );
-
-		/* save the session id */
-		session->http_sesid = atoi( records[0]->fields[0]->data );
-	}
-
-	/* extract UserId (from protocol 5.9) */
-	if ( records[1]->fcount >= 9 )
-		session->uid = g_strdup( records[1]->fields[8]->data );
-
-	/* display the current splash-screen */
-	if ( splash_popup_enabled( session ) )
-		splash_display( session );
-
-	/* update presence status */
-	status = purple_account_get_active_status( session->acc );
-	presence = mxit_convert_presence( purple_status_get_id( status ) );
-	statusmsg = purple_status_get_attr_string( status, "message" );
-
-	if ( ( presence != MXIT_PRESENCE_ONLINE ) || ( statusmsg ) ) {
-		/* when logging into MXit, your default presence is online. but with the UI, one can change
-		 * the presence to whatever. in the case where its changed to a different presence setting
-		 * we need to send an update to the server, otherwise the user's presence will be out of
-		 * sync between the UI and MXit.
-		 */
-		char* statusmsg1 = purple_markup_strip_html( statusmsg );
-		char* statusmsg2 = g_strndup( statusmsg1, CP_MAX_STATUS_MSG );
-
-		mxit_send_presence( session, presence, statusmsg2 );
-
-		g_free( statusmsg1 );
-		g_free( statusmsg2 );
-	}
-
-	/* retrieve our MXit profile */
-	mxit_send_extprofile_request( session, NULL, ARRAY_SIZE( profilelist ), profilelist );
-}
-
-
-/*------------------------------------------------------------------------
- * Process a received message packet.
- *
- *  @param session		The MXit session object
- *  @param records		The packet's data records
- *  @param rcount		The number of data records
- */
-static void mxit_parse_cmd_message( struct MXitSession* session, struct record** records, int rcount )
-{
-	struct RXMsgData*	mx			= NULL;
-	char*				message		= NULL;
-	char*				sender		= NULL;
-	int					msglen		= 0;
-	int					msgflags	= 0;
-	int					msgtype		= 0;
-
-	if ( ( rcount == 1 ) || ( records[0]->fcount < 2 ) || ( records[1]->fcount == 0 ) || ( records[1]->fields[0]->len == 0 ) ) {
-		/* packet contains no message or an empty message */
-		return;
-	}
-
-	message = records[1]->fields[0]->data;
-	msglen = strlen( message );
-
-	/* strip off dummy domain */
-	sender = records[0]->fields[0]->data;
-	mxit_strip_domain( sender );
-
-#ifdef	DEBUG_PROTOCOL
-	purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", sender );
-#endif
-
-	/* decode message flags (if any) */
-	if ( records[0]->fcount >= 5 )
-		msgflags = atoi( records[0]->fields[4]->data );
-	msgtype = atoi( records[0]->fields[2]->data );
-
-	if ( msgflags & CP_MSG_PWD_ENCRYPTED ) {
-		/* this is a password encrypted message. we do not currently support those so ignore it */
-		PurpleBuddy*	buddy;
-		const char*		name;
-		char			msg[128];
-
-		buddy = purple_find_buddy( session->acc, sender );
-		if ( buddy )
-			name = purple_buddy_get_alias( buddy );
-		else
-			name = sender;
-		g_snprintf( msg, sizeof( msg ), _( "%s sent you an encrypted message, but it is not supported on this client." ), name );
-		mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Error" ), msg );
-		return;
-	}
-	else if ( msgflags & CP_MSG_TL_ENCRYPTED ) {
-		/* this is a transport-layer encrypted message. */
-		message = mxit_decrypt_message( session, message );
-		if ( !message ) {
-			/* could not be decrypted */
-			serv_got_im( session->con, sender, _( "An encrypted message was received which could not be decrypted." ), PURPLE_MESSAGE_ERROR, time( NULL ) );
-			return;
-		}
-	}
-
-	if ( msgflags & CP_MSG_NOTIFY_DELIVERY ) {
-		/* delivery notification is requested */
-		if ( records[0]->fcount >= 4 )
-			mxit_send_msgevent( session, sender, records[0]->fields[3]->data, CP_MSGEVENT_DELIVERED );
-	}
-
-	/* create and initialise new markup struct */
-	mx = g_new0( struct RXMsgData, 1 );
-	mx->msg = g_string_sized_new( msglen );
-	mx->session = session;
-	mx->from = g_strdup( sender );
-	mx->timestamp = atoi( records[0]->fields[1]->data );
-	mx->got_img = FALSE;
-	mx->chatid = -1;
-	mx->img_count = 0;
-
-	/* update list of active chats */
-	if ( !find_active_chat( session->active_chats, mx->from ) ) {
-		session->active_chats = g_list_append( session->active_chats, g_strdup( mx->from ) );
-	}
-
-	if ( is_multimx_contact( session, mx->from ) ) {
-		/* this is a MultiMx chatroom message */
-		multimx_message_received( mx, message, msglen, msgtype, msgflags );
-	}
-	else {
-		mxit_parse_markup( mx, message, msglen, msgtype, msgflags );
-	}
-
-	/* we are now done parsing the message */
-	mx->converted = TRUE;
-	if ( mx->img_count == 0 ) {
-		/* we have all the data we need for this message to be displayed now. */
-		mxit_show_message( mx );
-	}
-	else {
-		/* this means there are still images outstanding for this message and
-		 * still need to wait for them before we can display the message.
-		 * so the image received callback function will eventually display
-		 * the message. */
-	}
-
-	/* cleanup */
-	if ( msgflags & CP_MSG_TL_ENCRYPTED )
-		g_free( message );
-}
-
-
-/*------------------------------------------------------------------------
- * Process a received subscription request packet.
- *
- *  @param session		The MXit session object
- *  @param records		The packet's data records
- *  @param rcount		The number of data records
- */
-static void mxit_parse_cmd_new_sub( struct MXitSession* session, struct record** records, int rcount )
-{
-	struct contact*		contact;
-	struct record*		rec;
-	int					i;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_new_sub (%i recs)\n", rcount );
-
-	for ( i = 0; i < rcount; i++ ) {
-		rec = records[i];
-
-		if ( rec->fcount < 4 ) {
-			purple_debug_error( MXIT_PLUGIN_ID, "BAD SUBSCRIPTION RECORD! %i fields\n", rec->fcount );
-			break;
-		}
-
-		/* build up a new contact info struct */
-		contact = g_new0( struct contact, 1 );
-
-		g_strlcpy( contact->username, rec->fields[0]->data, sizeof( contact->username ) );
-		mxit_strip_domain( contact->username );				/* remove dummy domain */
-		g_strlcpy( contact->alias, rec->fields[1]->data, sizeof( contact->alias ) );
-		contact->type = atoi( rec->fields[2]->data );
-
-		if ( rec->fcount >= 5 ) {
-			/* there is a personal invite message attached */
-			if ( ( rec->fields[4]->data ) && ( strlen( rec->fields[4]->data ) > 0 ) )
-				contact->msg = strdup( rec->fields[4]->data );
-		}
-
-		/* handle the subscription */
-		if ( contact-> type == MXIT_TYPE_MULTIMX ) {		/* subscription to a MultiMX room */
-			char* creator = NULL;
-
-			if ( rec->fcount >= 6 )
-				creator = rec->fields[5]->data;
-
-			multimx_invite( session, contact, creator );
-		}
-		else
-			mxit_new_subscription( session, contact );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Parse the received presence value, and ensure that it is supported.
- *
- *  @param value		The received presence value.
- *  @return				A valid presence value.
- */
-static short mxit_parse_presence( const char* value )
-{
-	short presence = atoi( value );
-
-	/* ensure that the presence value is valid */
-	switch ( presence ) {
-		case MXIT_PRESENCE_OFFLINE :
-		case MXIT_PRESENCE_ONLINE :
-		case MXIT_PRESENCE_AWAY :
-		case MXIT_PRESENCE_DND :
-			return presence;
-
-		default :
-			return MXIT_PRESENCE_ONLINE;
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Parse the received mood value, and ensure that it is supported.
- *
- *  @param value		The received mood value.
- *  @return				A valid mood value.
- */
-static short mxit_parse_mood( const char* value )
-{
-	short mood = atoi( value );
-
-	/* ensure that the mood value is valid */
-	if ( ( mood >= MXIT_MOOD_NONE ) && ( mood <= MXIT_MOOD_STRESSED ) )
-		return mood;
-
-	return MXIT_MOOD_NONE;
-}
-
-
-/*------------------------------------------------------------------------
- * Process a received contact update packet.
- *
- *  @param session		The MXit session object
- *  @param records		The packet's data records
- *  @param rcount		The number of data records
- */
-static void mxit_parse_cmd_contact( struct MXitSession* session, struct record** records, int rcount )
-{
-	struct contact*		contact	= NULL;
-	struct record*		rec;
-	int					i;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_contact (%i recs)\n", rcount );
-
-	for ( i = 0; i < rcount; i++ ) {
-		rec = records[i];
-
-		if ( rec->fcount < 6 ) {
-			purple_debug_error( MXIT_PLUGIN_ID, "BAD CONTACT RECORD! %i fields\n", rec->fcount );
-			break;
-		}
-
-		/* build up a new contact info struct */
-		contact = g_new0( struct contact, 1 );
-
-		g_strlcpy( contact->groupname, rec->fields[0]->data, sizeof( contact->groupname ) );
-		g_strlcpy( contact->username, rec->fields[1]->data, sizeof( contact->username ) );
-		mxit_strip_domain( contact->username );				/* remove dummy domain */
-		g_strlcpy( contact->alias, rec->fields[2]->data, sizeof( contact->alias ) );
-
-		contact->presence = mxit_parse_presence( rec->fields[3]->data );
-		contact->type = atoi( rec->fields[4]->data );
-		contact->mood = mxit_parse_mood( rec->fields[5]->data );
-
-		if ( rec->fcount > 6 ) {
-			/* added in protocol 5.9 - flags & subtype */
-			contact->flags = atoi( rec->fields[6]->data );
-			contact->subtype = rec->fields[7]->data[0];
-		}
-		if ( rec->fcount > 8 ) {
-			/* added in protocol 6.0 - reject message */
-			contact->msg = g_strdup( rec->fields[8]->data );
-		}
-
-		/* add the contact to the buddy list */
-		if ( contact-> type == MXIT_TYPE_MULTIMX )			/* contact is a MultiMX room */
-			multimx_created( session, contact );
-		else
-			mxit_update_contact( session, contact );
-	}
-
-	if ( !( session->flags & MXIT_FLAG_FIRSTROSTER ) ) {
-		session->flags |= MXIT_FLAG_FIRSTROSTER;
-		mxit_update_blist( session );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Process a received presence update packet.
- *
- *  @param session		The MXit session object
- *  @param records		The packet's data records
- *  @param rcount		The number of data records
- */
-static void mxit_parse_cmd_presence( struct MXitSession* session, struct record** records, int rcount )
-{
-	int					i;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_presence (%i recs)\n", rcount );
-
-	for ( i = 0; i < rcount; i++ ) {
-		struct record*	rec		= records[i];
-		int				flags	= 0;
-
-		if ( rec->fcount < 6 ) {
-			purple_debug_error( MXIT_PLUGIN_ID, "BAD PRESENCE RECORD! %i fields\n", rec->fcount );
-			break;
-		}
-
-		/*
-		 * The format of the record is:
-		 * contactAddressN \1 presenceN \1 moodN \1 customMoodN \1 statusMsgN \1 avatarIdN [ \1 flagsN ]
-		 */
-		mxit_strip_domain( rec->fields[0]->data );		/* contactAddress */
-
-		if ( rec->fcount >= 7 )		/* flags field is included */
-			flags = atoi( rec->fields[6]->data );
-
-		mxit_update_buddy_presence( session, rec->fields[0]->data, mxit_parse_presence( rec->fields[1]->data ), mxit_parse_mood( rec->fields[2]->data ),
-				rec->fields[3]->data, rec->fields[4]->data, flags );
-		mxit_update_buddy_avatar( session, rec->fields[0]->data, rec->fields[5]->data );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Process a received extended profile packet.
- *
- *  @param session		The MXit session object
- *  @param records		The packet's data records
- *  @param rcount		The number of data records
- */
-static void mxit_parse_cmd_extprofile( struct MXitSession* session, struct record** records, int rcount )
-{
-	const char*				mxitId		= records[0]->fields[0]->data;
-	struct MXitProfile*		profile		= NULL;
-	int						count;
-	int						i;
-	const char*				avatarId	= NULL;
-	char*					statusMsg	= NULL;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_extprofile: profile for '%s'\n", mxitId );
-
-	if ( ( records[0]->fields[0]->len == 0 ) || ( session->uid && ( strcmp( session->uid, records[0]->fields[0]->data ) == 0 ) ) ) {
-		/* No UserId or Our UserId provided, so this must be our own profile information */
-		if ( session->profile == NULL )
-			session->profile = g_new0( struct MXitProfile, 1 );
-		profile = session->profile;
-	}
-	else {
-		/* is a buddy's profile */
-		profile = g_new0( struct MXitProfile, 1 );
-	}
-
-	/* set the count for attributes */
-	count = atoi( records[0]->fields[1]->data );
-
-	/* ensure the packet has the correct number of fields */
-	if ( records[0]->fcount < ( 2 + ( count * 3 ) ) ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "Insufficient number of fields in extprofile response. fields=%i records=%i", records[0]->fcount, count );
-		return;
-	}
-
-	for ( i = 0; i < count; i++ ) {
-		char* fname;
-		char* fvalue;
-		char* fstatus;
-		int f = ( i * 3 ) + 2;
-
-		fname = records[0]->fields[f]->data;		/* field name */
-		fvalue = records[0]->fields[f + 1]->data;	/* field value */
-		fstatus = records[0]->fields[f + 2]->data;	/* field status */
-
-		/* first check the status on the returned attribute */
-		if ( fstatus[0] != '0' ) {
-			/* error: attribute requested was NOT found */
-			purple_debug_error( MXIT_PLUGIN_ID, "Bad profile status on attribute '%s' \n", fname );
-			continue;
-		}
-
-		if ( strcmp( CP_PROFILE_BIRTHDATE, fname ) == 0 ) {
-			/* birthdate */
-			if ( records[0]->fields[f + 1]->len > 10 ) {
-				fvalue[10] = '\0';
-				records[0]->fields[f + 1]->len = 10;
-			}
-			memcpy( profile->birthday, fvalue, records[0]->fields[f + 1]->len );
-		}
-		else if ( strcmp( CP_PROFILE_GENDER, fname ) == 0 ) {
-			/* gender */
-			profile->male = ( fvalue[0] == '1' );
-		}
-		else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) {
-			/* nickname */
-			g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) );
-		}
-		else if ( strcmp( CP_PROFILE_STATUS, fname ) == 0 ) {
-			/* status message - just keep a reference to the value */
-			statusMsg = g_markup_escape_text( fvalue, -1 );
-		}
-		else if ( strcmp( CP_PROFILE_AVATAR, fname ) == 0 ) {
-			/* avatar id - just keep a reference to the value */
-			avatarId = fvalue;
-		}
-		else if ( strcmp( CP_PROFILE_TITLE, fname ) == 0 ) {
-			/* title */
-			g_strlcpy( profile->title, fvalue, sizeof( profile->title ) );
-		}
-		else if ( strcmp( CP_PROFILE_FIRSTNAME, fname ) == 0 ) {
-			/* first name */
-			g_strlcpy( profile->firstname, fvalue, sizeof( profile->firstname ) );
-		}
-		else if ( strcmp( CP_PROFILE_LASTNAME, fname ) == 0 ) {
-			/* last name */
-			g_strlcpy( profile->lastname, fvalue, sizeof( profile->lastname ) );
-		}
-		else if ( strcmp( CP_PROFILE_EMAIL, fname ) == 0 ) {
-			/* email address */
-			g_strlcpy( profile->email, fvalue, sizeof( profile->email ) );
-		}
-		else if ( strcmp( CP_PROFILE_MOBILENR, fname ) == 0 ) {
-			/* mobile number */
-			g_strlcpy( profile->mobilenr, fvalue, sizeof( profile->mobilenr ) );
-		}
-		else if ( strcmp( CP_PROFILE_REGCOUNTRY, fname ) == 0 ) {
-			/* registered country */
-			g_strlcpy( profile->regcountry, fvalue, sizeof( profile->regcountry ) );
-		}
-		else if ( strcmp( CP_PROFILE_FLAGS, fname ) == 0 ) {
-			/* profile flags */
-			profile->flags = g_ascii_strtoll( fvalue, NULL, 10 );
-		}
-		else if ( strcmp( CP_PROFILE_LASTSEEN, fname ) == 0 ) {
-			/* last seen online */
-			profile->lastonline = g_ascii_strtoll( fvalue, NULL, 10 );
-		}
-		else if ( strcmp( CP_PROFILE_WHEREAMI, fname ) == 0 ) {
-			/* where am I */
-			g_strlcpy( profile->whereami, fvalue, sizeof( profile->whereami ) );
-		}
-		else if ( strcmp( CP_PROFILE_ABOUTME, fname ) == 0) {
-			/* about me */
-			g_strlcpy( profile->aboutme, fvalue, sizeof( profile->aboutme ) );
-		}
-		else if ( strcmp( CP_PROFILE_RELATIONSHIP, fname ) == 0) {
-			/* relatinship status */
-			profile->relationship = strtol( fvalue, NULL, 10 );
-		}
-		else {
-			/* invalid profile attribute */
-			purple_debug_error( MXIT_PLUGIN_ID, "Invalid profile attribute received '%s' \n", fname );
-		}
-	}
-
-	if ( profile != session->profile ) {
-		/* not our own profile */
-		struct contact*		contact		= NULL;
-
-		contact = get_mxit_invite_contact( session, mxitId );
-		if ( contact ) {
-			/* this is an invite, so update its profile info */
-			if ( ( statusMsg ) && ( strlen( statusMsg ) > 0 ) ) {
-				/* update the status message */
-				if ( contact->statusMsg )
-					g_free( contact->statusMsg );
-				contact->statusMsg = strdup( statusMsg );
-			}
-			else
-				contact->statusMsg = NULL;
-			if ( contact->profile )
-				g_free( contact->profile );
-			contact->profile = profile;
-			if ( ( avatarId ) && ( strlen( avatarId ) > 0 ) ) {
-				/* avatar must be requested for this invite before we can display it */
-				mxit_get_avatar( session, mxitId, avatarId );
-				if ( contact->avatarId )
-					g_free( contact->avatarId );
-				contact->avatarId = strdup( avatarId );
-			}
-			else {
-				/* display what we have */
-				contact->avatarId = NULL;
-				mxit_show_profile( session, mxitId, profile );
-			}
-		}
-		else {
-			/* this is a contact */
-			if ( avatarId )
-				mxit_update_buddy_avatar( session, mxitId, avatarId );
-
-			if ( ( statusMsg ) && ( strlen( statusMsg ) > 0 ) ) {
-				/* update the status message */
-				PurpleBuddy*		buddy	= NULL;
-
-				buddy = purple_find_buddy( session->acc, mxitId );
-				if ( buddy ) {
-					contact = purple_buddy_get_protocol_data( buddy );
-					if ( contact ) {
-						if ( contact->statusMsg )
-							g_free( contact->statusMsg );
-						contact->statusMsg = strdup( statusMsg );
-					}
-				}
-			}
-
-			/* show the profile */
-			mxit_show_profile( session, mxitId, profile );
-			g_free( profile );
-		}
-	}
-
-	g_free( statusMsg );
-}
-
-
-/*------------------------------------------------------------------------
- * Process a received suggest-contacts packet.
- *
- *  @param session		The MXit session object
- *  @param records		The packet's data records
- *  @param rcount		The number of data records
- */
-static void mxit_parse_cmd_suggestcontacts( struct MXitSession* session, struct record** records, int rcount )
-{
-	GList* entries = NULL;
-	int searchType;
-	int maxResults;
-	int count;
-	int i;
-
-	/*
-	 * searchType \1 numSuggestions \1 total \1 numAttributes \1 name0 \1 name1 \1 ... \1 nameN \0
-	 * userid \1 contactType \1 value0 \1 value1 ... valueN \0
-	 * ...
-	 * userid \1 contactType \1 value0 \1 value1 ... valueN
-	 */
-
-	/* ensure that record[0] contacts the minumum number of fields */
-	if ( records[0]->fcount < 4 ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "Insufficient number of fields in suggest contacts response. fields=%i", records[0]->fcount );
-		return;
-	}
-
-	/* the type of results */
-	searchType = atoi( records[0]->fields[0]->data );
-
-	/* the maximum number of results */
-	maxResults = atoi( records[0]->fields[2]->data );
-
-	/* set the count for attributes */
-	count = atoi( records[0]->fields[3]->data );
-
-	/* ensure that record[0] contains the specified number of attributes */
-	if ( records[0]->fcount < ( 4 + count ) ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "Insufficient number of fields in suggest contacts response. fields=%i attributes=%i", records[0]->fcount, count );
-		return;
-	}
-
-	for ( i = 1; i < rcount; i ++ ) {
-		struct record*		rec		= records[i];
-		struct MXitProfile*	profile	= g_new0( struct MXitProfile, 1 );
-		int j;
-
-		/* ensure that each result contains the specified number of attributes */
-		if ( rec->fcount != ( 2 + count ) ) {
-			purple_debug_error( MXIT_PLUGIN_ID, "Insufficient number of fields in suggest contacts response. fields=%i attributes=%i", rec->fcount, count );
-			g_free( profile );
-			continue;
-		}
-
-		g_strlcpy( profile->userid, rec->fields[0]->data, sizeof( profile->userid ) );
-		// TODO: ContactType - User or Service
-
-		for ( j = 0; j < count; j++ ) {
-			char* fname;
-			char* fvalue = "";
-
-			fname = records[0]->fields[4 + j]->data;		/* field name */
-			if ( records[i]->fcount > ( 2 + j ) )
-				fvalue = records[i]->fields[2 + j]->data;	/* field value */
-
-			purple_debug_info( MXIT_PLUGIN_ID, " %s: field='%s' value='%s'\n", profile->userid, fname, fvalue );
-
-			if ( strcmp( CP_PROFILE_BIRTHDATE, fname ) == 0 ) {
-				/* birthdate */
-				g_strlcpy( profile->birthday, fvalue, sizeof( profile->birthday ) );
-			}
-			else if ( strcmp( CP_PROFILE_FIRSTNAME, fname ) == 0 ) {
-				/* first name */
-				g_strlcpy( profile->firstname, fvalue, sizeof( profile->firstname ) );
-			}
-			else if ( strcmp( CP_PROFILE_LASTNAME, fname ) == 0 ) {
-				/* last name */
-				g_strlcpy( profile->lastname, fvalue, sizeof( profile->lastname ) );
-			}
-			else if ( strcmp( CP_PROFILE_GENDER, fname ) == 0 ) {
-				/* gender */
-				profile->male = ( fvalue[0] == '1' );
-			}
-			else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) {
-				/* nickname */
-				g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) );
-			}
-			else if ( strcmp( CP_PROFILE_WHEREAMI, fname ) == 0 ) {
-				/* where am I */
-				g_strlcpy( profile->whereami, fvalue, sizeof( profile->whereami ) );
-			}
-			/* ignore other attibutes */
-		}
-
-		entries = g_list_append( entries, profile );
-	}
-
-	/* display */
-	mxit_show_search_results( session, searchType, maxResults, entries );
-
-	/* cleanup */
-	g_list_foreach( entries, (GFunc)g_free, NULL );
-}
-
-/*------------------------------------------------------------------------
- * Process a received message event packet.
- *
- *  @param session		The MXit session object
- *  @param records		The packet's data records
- *  @param rcount		The number of data records
- */
-static void mxit_parse_cmd_msgevent( struct MXitSession* session, struct record** records, int rcount )
-{
-	int event;
-
-	/*
-	 * contactAddress \1 dateTime \1 id \1 event
-	 */
-
-	/* strip off dummy domain */
-	mxit_strip_domain( records[0]->fields[0]->data );
-
-	event = atoi( records[0]->fields[3]->data );
-
-	switch ( event ) {
-		case CP_MSGEVENT_TYPING :							/* user is typing */
-		case CP_MSGEVENT_ANGRY :							/* user is typing angrily */
-			serv_got_typing( session->con, records[0]->fields[0]->data, 0, PURPLE_TYPING );
-			break;
-
-		case CP_MSGEVENT_STOPPED :							/* user has stopped typing */
-			serv_got_typing_stopped( session->con, records[0]->fields[0]->data );
-			break;
-
-		case CP_MSGEVENT_ERASING :							/* user is erasing text */
-		case CP_MSGEVENT_DELIVERED :						/* message was delivered */
-		case CP_MSGEVENT_DISPLAYED :						/* message was viewed */
-			/* these are currently not supported by libPurple */
-			break;
-
-		default:
-			purple_debug_error( MXIT_PLUGIN_ID, "Unknown message event received (%i)\n", event );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Process a received multimedia packet.
- *
- *  @param session		The MXit session object
- *  @param records		The packet's data records
- *  @param rcount		The number of data records
- */
-static void mxit_parse_cmd_media( struct MXitSession* session, struct record** records, int rcount )
-{
-	guint	chunktype;
-	guint32	chunksize;
-	gchar*	chunkdata;
-
-	/* received packet is too short to even contain a chunk header */
-	if ( records[0]->fields[0]->len < MXIT_CHUNK_HEADER_SIZE )
-		return;
-
-	/* decode the chunk header */
-	chunktype = chunk_type( records[0]->fields[0]->data );
-	chunksize = chunk_length( records[0]->fields[0]->data );
-	chunkdata = chunk_data( records[0]->fields[0]->data );
-
-	/* check chunk size against length of received data */
-	if ( MXIT_CHUNK_HEADER_SIZE + chunksize > records[0]->fields[0]->len )
-		return;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_media (%i records) (%i type) (%i bytes)\n", rcount, chunktype, chunksize );
-
-	/* supported chunked data types */
-	switch ( chunktype ) {
-		case CP_CHUNK_CUSTOM :				/* custom resource */
-			{
-				struct cr_chunk chunk;
-
-				/* decode the chunked data */
-				if ( mxit_chunk_parse_cr( chunkdata, chunksize, &chunk ) ) {
-
-					purple_debug_info( MXIT_PLUGIN_ID, "chunk info id=%s handle=%s op=%i\n", chunk.id, chunk.handle, chunk.operation );
-
-					/* this is a splash-screen operation */
-					if ( strcmp( chunk.handle, HANDLE_SPLASH2 ) == 0 ) {
-						if ( chunk.operation == CR_OP_UPDATE ) {		/* update the splash-screen */
-							struct splash_chunk *splash = chunk.resources->data;			// TODO: Fix - assuming 1st resource is splash
-							gboolean clickable = ( g_list_length( chunk.resources ) > 1 );	// TODO: Fix - if 2 resources, then is clickable
-
-							if ( splash != NULL )
-								splash_update( session, chunk.id, splash->data, splash->datalen, clickable );
-						}
-						else if ( chunk.operation == CR_OP_REMOVE )		/* remove the splash-screen */
-							splash_remove( session );
-					}
-
-					/* cleanup custom resources */
-					g_list_foreach( chunk.resources, (GFunc)g_free, NULL );
-				}
-			}
-			break;
-
-		case CP_CHUNK_OFFER :				/* file offer */
-			{
-				struct offerfile_chunk chunk;
-
-				/* decode the chunked data */
-				if ( mxit_chunk_parse_offer( chunkdata, chunksize, &chunk ) ) {
-					/* process the offer */
-					mxit_xfer_rx_offer( session, chunk.username, chunk.filename, chunk.filesize, chunk.fileid );
-				}
-			}
-			break;
-
-		case CP_CHUNK_GET :					/* get file response */
-			{
-				struct getfile_chunk chunk;
-
-				/* decode the chunked data */
-				if ( mxit_chunk_parse_get( chunkdata, chunksize, &chunk ) ) {
-					/* process the getfile */
-					mxit_xfer_rx_file( session, chunk.fileid, chunk.data, chunk.length );
-				}
-			}
-			break;
-
-		case CP_CHUNK_GET_AVATAR :			/* get avatars */
-			{
-				struct getavatar_chunk chunk;
-				struct contact* contact = NULL;
-
-				/* decode the chunked data */
-				if ( mxit_chunk_parse_get_avatar( chunkdata, chunksize, &chunk ) ) {
-					/* update avatar image */
-					purple_debug_info( MXIT_PLUGIN_ID, "updating avatar for contact '%s'\n", chunk.mxitid );
-
-					contact = get_mxit_invite_contact( session, chunk.mxitid );
-					if ( contact ) {
-						/* this is an invite (add image to the internal image store) */
-						contact->imgid = purple_imgstore_add_with_id( g_memdup( chunk.data, chunk.length ), chunk.length, NULL );
-						/* show the profile */
-						mxit_show_profile( session, chunk.mxitid, contact->profile );
-					}
-					else {
-						/* this is a contact's avatar, so update it */
-						purple_buddy_icons_set_for_user( session->acc, chunk.mxitid, g_memdup( chunk.data, chunk.length ), chunk.length, chunk.avatarid );
-					}
-				}
-			}
-			break;
-
-		case CP_CHUNK_SET_AVATAR :
-			/* this is a reply packet to a set avatar request. no action is required */
-			break;
-
-		case CP_CHUNK_REJECT :
-			/* this is a reply packet to a reject file request. no action is required */
-			break;
-
-		case CP_CHUNK_DIRECT_SND :
-			/* this is a ack for a file send. */
-			{
-				struct sendfile_chunk chunk;
-
-				if ( mxit_chunk_parse_sendfile( chunkdata, chunksize, &chunk ) ) {
-					purple_debug_info( MXIT_PLUGIN_ID, "file-send send to '%s' [status=%i message='%s']\n", chunk.username, chunk.status, chunk.statusmsg );
-
-					if ( chunk.status != 0 )	/* not success */
-						mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "File Send Failed" ), chunk.statusmsg );
-				}
-			}
-			break;
-
-		case CP_CHUNK_RECEIVED :
-			/* this is a ack for a file received. no action is required */
-			break;
-
-		default :
-			purple_debug_error( MXIT_PLUGIN_ID, "Unsupported chunked data packet type received (%i)\n", chunktype );
-			break;
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Handle a redirect sent from the MXit server.
- *
- *  @param session		The MXit session object
- *  @param url			The redirect information
- */
-static void mxit_perform_redirect( struct MXitSession* session, const char* url )
-{
-	gchar**		parts;
-	gchar**		host;
-	int			type;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_perform_redirect: %s\n", url );
-
-	/* tokenize the URL string */
-	parts = g_strsplit( url, ";", 0 );
-
-	/* Part 1: protocol://host:port */
-	host = g_strsplit( parts[0], ":", 4 );
-	if ( strcmp( host[0], "socket" ) == 0 ) {
-		/* redirect to a MXit socket proxy */
-		g_strlcpy( session->server, &host[1][2], sizeof( session->server ) );
-		session->port = atoi( host[2] );
-	}
-	else {
-		purple_connection_error( session->con, _( "Cannot perform redirect using the specified protocol" ) );
-		goto redirect_fail;
-	}
-
-	/* Part 2: type of redirect */
-	type = atoi( parts[1] );
-	if ( type == CP_REDIRECT_PERMANENT ) {
-		/* permanent redirect, so save new MXit server and port */
-		purple_account_set_string( session->acc, MXIT_CONFIG_SERVER_ADDR, session->server );
-		purple_account_set_int( session->acc, MXIT_CONFIG_SERVER_PORT, session->port );
-	}
-
-	/* Part 3: message (optional) */
-	if ( parts[2] != NULL )
-		purple_connection_notice( session->con, parts[2] );
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_perform_redirect: %s redirect to %s:%i\n",
-			( type == CP_REDIRECT_PERMANENT ) ? "Permanent" : "Temporary", session->server, session->port );
-
-	/* perform the re-connect to the new MXit server */
-	mxit_reconnect( session );
-
-redirect_fail:
-	g_strfreev( parts );
-	g_strfreev( host );
-}
-
-
-/*------------------------------------------------------------------------
- * Process a success response received from the MXit server.
- *
- *  @param session		The MXit session object
- *  @param packet		The received packet
- */
-static int process_success_response( struct MXitSession* session, struct rx_packet* packet )
-{
-	/* ignore ping/poll packets */
-	if ( ( packet->cmd != CP_CMD_PING ) && ( packet->cmd != CP_CMD_POLL ) )
-		session->last_rx = mxit_now_milli();
-
-	/*
-	 * when we pass the packet records to the next level for parsing
-	 * we minus 3 records because 1) the first record is the packet
-	 * type 2) packet reply status 3) the last record is bogus
-	 */
-
-	/* packet command */
-	switch ( packet->cmd ) {
-
-		case CP_CMD_REGISTER :
-				/* fall through, when registeration successful, MXit will auto login */
-		case CP_CMD_LOGIN :
-				/* login response */
-				if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) ) {
-					mxit_parse_cmd_login( session, &packet->records[2], packet->rcount - 3 );
-				}
-				break;
-
-		case CP_CMD_LOGOUT :
-				/* logout response */
-				session->flags &= ~MXIT_FLAG_LOGGEDIN;
-				purple_account_disconnect( session->acc );
-
-				/* note:
-				 * we do not prompt the user here for a reconnect, because this could be the user
-				 * logging in with his phone. so we just disconnect the account otherwise
-				 * mxit will start to bounce between the phone and pidgin. also could be a valid
-				 * disconnect selected by the user.
-				 */
-				return -1;
-
-		case CP_CMD_CONTACT :
-				/* contact update */
-				mxit_parse_cmd_contact( session, &packet->records[2], packet->rcount - 3 );
-				break;
-
-		case CP_CMD_PRESENCE :
-				/* presence update */
-				mxit_parse_cmd_presence( session, &packet->records[2], packet->rcount - 3 );
-				break;
-
-		case CP_CMD_RX_MSG :
-				/* incoming message (no bogus record) */
-				mxit_parse_cmd_message( session, &packet->records[2], packet->rcount - 2 );
-				break;
-
-		case CP_CMD_NEW_SUB :
-				/* new subscription request */
-				mxit_parse_cmd_new_sub( session, &packet->records[2], packet->rcount - 3 );
-				break;
-
-		case CP_CMD_MEDIA :
-				/* multi-media message */
-				mxit_parse_cmd_media( session, &packet->records[2], packet->rcount - 2 );
-				break;
-
-		case CP_CMD_EXTPROFILE_GET :
-				/* profile update */
-				mxit_parse_cmd_extprofile( session, &packet->records[2], packet->rcount - 2 );
-				break;
-
-		case CP_CMD_SUGGESTCONTACTS :
-				/* suggest contacts */
-				mxit_parse_cmd_suggestcontacts( session, &packet->records[2], packet->rcount - 2 );
-				break;
-
-		case CP_CMD_GOT_MSGEVENT :
-				/* received message event */
-				mxit_parse_cmd_msgevent( session, &packet->records[2], packet->rcount - 2 );
-				break;
-
-		case CP_CMD_MOOD :
-				/* mood update */
-		case CP_CMD_UPDATE :
-				/* update contact information */
-		case CP_CMD_ALLOW :
-				/* allow subscription ack */
-		case CP_CMD_DENY :
-				/* deny subscription ack */
-		case CP_CMD_INVITE :
-				/* invite contact ack */
-		case CP_CMD_REMOVE :
-				/* remove contact ack */
-		case CP_CMD_TX_MSG :
-				/* outgoing message ack */
-		case CP_CMD_STATUS :
-				/* presence update ack */
-		case CP_CMD_GRPCHAT_CREATE :
-				/* create groupchat */
-		case CP_CMD_GRPCHAT_INVITE :
-				/* groupchat invite */
-		case CP_CMD_PING :
-				/* ping reply */
-		case CP_CMD_POLL :
-				/* HTTP poll reply */
-		case CP_CMD_EXTPROFILE_SET :
-				/* profile update */
-				// TODO: Protocol 6.2 indicates status for each attribute, and current value.
-		case CP_CMD_SPLASHCLICK :
-				/* splash-screen clickthrough */
-		case CP_CMD_MSGEVENT :
-				/* event message */
-				break;
-
-		default :
-			/* unknown packet */
-			purple_debug_error( MXIT_PLUGIN_ID, "Received unknown client packet (cmd = %i)\n", packet->cmd );
-	}
-
-	return 0;
-}
-
-
-/*------------------------------------------------------------------------
- * Process an error response received from the MXit server.
- *
- *  @param session		The MXit session object
- *  @param packet		The received packet
- */
-static int process_error_response( struct MXitSession* session, struct rx_packet* packet )
-{
-	char			errmsg[256];
-	const char*		errdesc;
-
-	/* set the error description to be shown to the user */
-	if ( packet->errmsg )
-		errdesc = packet->errmsg;
-	else
-		errdesc = _( "An internal MXit server error occurred." );
-
-	purple_debug_info( MXIT_PLUGIN_ID, "Error Reply %i:%s\n", packet->errcode, errdesc );
-
-	if ( packet->errcode == MXIT_ERRCODE_LOGGEDOUT ) {
-		/* we are not currently logged in, so we need to reconnect */
-		purple_connection_error( session->con, _( errdesc ) );
-	}
-
-	/* packet command */
-	switch ( packet->cmd ) {
-
-		case CP_CMD_REGISTER :
-		case CP_CMD_LOGIN :
-				if ( packet->errcode == MXIT_ERRCODE_REDIRECT ) {
-					mxit_perform_redirect( session, packet->errmsg );
-					return 0;
-				}
-				else {
-					g_snprintf( errmsg, sizeof( errmsg ), _( "Login error: %s (%i)" ), errdesc, packet->errcode );
-					purple_connection_error( session->con, errmsg );
-					return -1;
-				}
-		case CP_CMD_LOGOUT :
-				g_snprintf( errmsg, sizeof( errmsg ), _( "Logout error: %s (%i)" ), errdesc, packet->errcode );
-				purple_connection_error_reason( session->con, PURPLE_CONNECTION_ERROR_NAME_IN_USE, _( errmsg ) );
-				return -1;
-		case CP_CMD_CONTACT :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_RX_MSG :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_TX_MSG :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Sending Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_STATUS :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Status Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_MOOD :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Mood Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_KICK :
-				/*
-				 * the MXit server sends this packet if we were idle for too long.
-				 * to stop the server from closing this connection we need to resend
-				 * the login packet.
-				 */
-				mxit_send_login( session );
-				break;
-		case CP_CMD_INVITE :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Invitation Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_REMOVE :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Removal Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_ALLOW :
-		case CP_CMD_DENY :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Subscription Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_UPDATE :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Update Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_MEDIA :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "File Transfer Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_GRPCHAT_CREATE :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Cannot create MultiMx room" ), _( errdesc ) );
-				break;
-		case CP_CMD_GRPCHAT_INVITE :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "MultiMx Invitation Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_EXTPROFILE_GET :
-		case CP_CMD_EXTPROFILE_SET :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Profile Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_SPLASHCLICK :
-		case CP_CMD_MSGEVENT :
-				/* ignore error */
-				break;
-		case CP_CMD_PING :
-		case CP_CMD_POLL :
-				break;
-		default :
-				mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Error" ), _( errdesc ) );
-				break;
-	}
-
-	return 0;
-}
-
-
-/*========================================================================================================================
- * Low-level Packet receive
- */
-
-#ifdef	DEBUG_PROTOCOL
-/*------------------------------------------------------------------------
- * Dump a received packet structure.
- *
- *  @param p			The received packet
- */
-static void dump_packet( struct rx_packet* p )
-{
-	struct record*		r	= NULL;
-	struct field*		f	= NULL;
-	int					i;
-	int					j;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "PACKET DUMP: (%i records)\n", p->rcount );
-
-	for ( i = 0; i < p->rcount; i++ ) {
-		r = p->records[i];
-		purple_debug_info( MXIT_PLUGIN_ID, "RECORD: (%i fields)\n", r->fcount );
-
-		for ( j = 0; j < r->fcount; j++ ) {
-			f = r->fields[j];
-			purple_debug_info( MXIT_PLUGIN_ID, "\tFIELD: (len=%zu) '%s' \n", f->len, f->data );
-		}
-	}
-}
-#endif
-
-
-/*------------------------------------------------------------------------
- * Free up memory used by a packet structure.
- *
- *  @param p			The received packet
- */
-static void free_rx_packet( struct rx_packet* p )
-{
-	struct record*		r	= NULL;
-	struct field*		f	= NULL;
-	int					i;
-	int					j;
-
-	for ( i = 0; i < p->rcount; i++ ) {
-		r = p->records[i];
-
-		for ( j = 0; j < r->fcount; j++ ) {
-			g_free( f );
-		}
-		g_free( r->fields );
-		g_free( r );
-	}
-	g_free( p->records );
-}
-
-
-/*------------------------------------------------------------------------
- * Add a new field to a record.
- *
- *  @param r			Parent record object
- *  @return				The newly created field
- */
-static struct field* add_field( struct record* r )
-{
-	struct field*	field;
-
-	field = g_new0( struct field, 1 );
-
-	r->fields = g_realloc( r->fields, sizeof( struct field* ) * ( r->fcount + 1 ) );
-	r->fields[r->fcount] = field;
-	r->fcount++;
-
-	return field;
-}
-
-
-/*------------------------------------------------------------------------
- * Add a new record to a packet.
- *
- *  @param p			The packet object
- *  @return				The newly created record
- */
-static struct record* add_record( struct rx_packet* p )
-{
-	struct record*	rec;
-
-	rec = g_new0( struct record, 1 );
-
-	p->records = g_realloc( p->records, sizeof( struct record* ) * ( p->rcount + 1 ) );
-	p->records[p->rcount] = rec;
-	p->rcount++;
-
-	return rec;
-}
-
-
-/*------------------------------------------------------------------------
- * Parse the received byte stream into a proper client protocol packet.
- *
- *  @param session		The MXit session object
- *  @return				Success (0) or Failure (!0)
- */
-int mxit_parse_packet( struct MXitSession* session )
-{
-	struct rx_packet	packet;
-	struct record*		rec;
-	struct field*		field;
-	gboolean			pbreak;
-	unsigned int		i;
-	int					res	= 0;
-
-#ifdef	DEBUG_PROTOCOL
-	purple_debug_info( MXIT_PLUGIN_ID, "Received packet (%i bytes)\n", session->rx_i );
-	dump_bytes( session, session->rx_dbuf, session->rx_i );
-#endif
-
-	i = 0;
-	while ( i < session->rx_i ) {
-
-		/* create first record and field */
-		rec = NULL;
-		field = NULL;
-		memset( &packet, 0x00, sizeof( struct rx_packet ) );
-		rec = add_record( &packet );
-		pbreak = FALSE;
-
-		/* break up the received packet into fields and records for easy parsing */
-		while ( ( i < session->rx_i ) && ( !pbreak ) ) {
-
-			switch ( session->rx_dbuf[i] ) {
-				case CP_SOCK_REC_TERM :
-						/* new record */
-						if ( packet.rcount == 1 ) {
-							/* packet command */
-							if ( packet.records[0]->fcount > 0 )
-								packet.cmd = atoi( packet.records[0]->fields[0]->data );
-						}
-						else if ( packet.rcount == 2 ) {
-							/* special case: binary multimedia packets should not be parsed here */
-							if ( packet.cmd == CP_CMD_MEDIA ) {
-								/* add the chunked to new record */
-								rec = add_record( &packet );
-								field = add_field( rec );
-								field->data = &session->rx_dbuf[i + 1];
-								field->len = session->rx_i - i;
-								/* now skip the binary data */
-								res = chunk_length( field->data );
-								/* determine if we have more packets */
-								if ( res + 6 + i < session->rx_i ) {
-									/* we have more than one packet in this stream */
-									i += res + 6;
-									pbreak = TRUE;
-								}
-								else {
-									i = session->rx_i;
-								}
-							}
-						}
-						else if ( !field ) {
-							field = add_field( rec );
-							field->data = &session->rx_dbuf[i];
-						}
-						session->rx_dbuf[i] = '\0';
-						rec = add_record( &packet );
-						field = NULL;
-
-						break;
-				case CP_FLD_TERM :
-						/* new field */
-						session->rx_dbuf[i] = '\0';
-						if ( !field ) {
-							field = add_field( rec );
-							field->data = &session->rx_dbuf[i];
-						}
-						field = NULL;
-						break;
-				case CP_PKT_TERM :
-						/* packet is done! */
-						session->rx_dbuf[i] = '\0';
-						pbreak = TRUE;
-						break;
-				default :
-						/* skip non special characters */
-						if ( !field ) {
-							field = add_field( rec );
-							field->data = &session->rx_dbuf[i];
-						}
-						field->len++;
-						break;
-			}
-
-			i++;
-		}
-
-		if ( packet.rcount < 2 ) {
-			/* bad packet */
-			purple_connection_error( session->con, _( "Invalid packet received from MXit." ) );
-			free_rx_packet( &packet );
-			continue;
-		}
-
-		session->rx_dbuf[session->rx_i] = '\0';
-		packet.errcode = atoi( packet.records[1]->fields[0]->data );
-
-		purple_debug_info( MXIT_PLUGIN_ID, "Packet received CMD:%i (%i)\n", packet.cmd, packet.errcode );
-#ifdef	DEBUG_PROTOCOL
-		/* debug */
-		dump_packet( &packet );
-#endif
-
-		/* reset the out ack */
-		if ( session->outack == packet.cmd ) {
-			/* outstanding ack received from mxit server */
-			session->outack = 0;
-		}
-
-		/* check packet status */
-		if ( packet.errcode != MXIT_ERRCODE_SUCCESS ) {
-			/* error reply! */
-			if ( ( packet.records[1]->fcount > 1 ) && ( packet.records[1]->fields[1]->data ) )
-				packet.errmsg = packet.records[1]->fields[1]->data;
-			else
-				packet.errmsg = NULL;
-
-			res = process_error_response( session, &packet );
-		}
-		else {
-			/* success reply! */
-			res = process_success_response( session, &packet );
-		}
-
-		/* free up the packet resources */
-		free_rx_packet( &packet );
-	}
-
-	if ( session->outack == 0 )
-			mxit_manage_queue( session );
-
-	return res;
-}
-
-
-/*------------------------------------------------------------------------
- * Callback when data is received from the MXit server.
- *
- *  @param user_data		The MXit session object
- *  @param source			The file-descriptor on which data was received
- *  @param cond				Condition which caused the callback (PURPLE_INPUT_READ)
- */
-void mxit_cb_rx( gpointer user_data, gint source, PurpleInputCondition cond )
-{
-	struct MXitSession*	session		= (struct MXitSession*) user_data;
-	char				ch;
-	int					res;
-	int					len;
-
-	if ( session->rx_state == RX_STATE_RLEN ) {
-		/* we are reading in the packet length */
-		len = read( session->fd, &ch, 1 );
-		if ( len < 0 ) {
-			/* connection error */
-			purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x01)" ) );
-			return;
-		}
-		else if ( len == 0 ) {
-			/* connection closed */
-			purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x02)" ) );
-			return;
-		}
-		else {
-			/* byte read */
-			if ( ch == CP_REC_TERM ) {
-				/* the end of the length record found */
-				session->rx_lbuf[session->rx_i] = '\0';
-				session->rx_res = atoi( &session->rx_lbuf[3] );
-				if ( ( session->rx_res <= 0 ) || ( session->rx_res > CP_MAX_PACKET ) ) {
-					purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x03)" ) );
-					return;
-				}
-				session->rx_state = RX_STATE_DATA;
-				session->rx_i = 0;
-			}
-			else {
-				/* still part of the packet length record */
-				session->rx_lbuf[session->rx_i] = ch;
-				session->rx_i++;
-				if ( session->rx_i >= sizeof( session->rx_lbuf ) ) {
-					/* malformed packet length record (too long) */
-					purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x04)" ) );
-					return;
-				}
-			}
-		}
-	}
-	else if ( session->rx_state == RX_STATE_DATA ) {
-		/* we are reading in the packet data */
-		len = read( session->fd, &session->rx_dbuf[session->rx_i], session->rx_res );
-		if ( len < 0 ) {
-			/* connection error */
-			purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x05)" ) );
-			return;
-		}
-		else if ( len == 0 ) {
-			/* connection closed */
-			purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x06)" ) );
-			return;
-		}
-		else {
-			/* data read */
-			session->rx_i += len;
-			session->rx_res -= len;
-
-			if ( session->rx_res == 0 ) {
-				/* ok, so now we have read in the whole packet */
-				session->rx_state = RX_STATE_PROC;
-			}
-		}
-	}
-
-	if ( session->rx_state == RX_STATE_PROC ) {
-		/* we have a full packet, which we now need to process */
-		res = mxit_parse_packet( session );
-
-		if ( res == 0 ) {
-			/* we are still logged in */
-			session->rx_state = RX_STATE_RLEN;
-			session->rx_res = 0;
-			session->rx_i = 0;
-		}
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Log the user off MXit and close the connection
- *
- *  @param session		The MXit session object
- */
-void mxit_close_connection( struct MXitSession* session )
-{
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_close_connection\n" );
-
-	if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) {
-		/* we are already closed */
-		return;
-	}
-	else if ( session->flags & MXIT_FLAG_LOGGEDIN ) {
-		/* we are currently logged in so we need to send a logout packet */
-		if ( !session->http ) {
-			mxit_send_logout( session );
-		}
-		session->flags &= ~MXIT_FLAG_LOGGEDIN;
-	}
-	session->flags &= ~MXIT_FLAG_CONNECTED;
-
-	/* cancel all outstanding async calls */
-	while ( session->async_calls ) {
-		purple_util_fetch_url_cancel( session->async_calls->data );
-		session->async_calls = g_slist_delete_link( session->async_calls, session->async_calls );
-	}
-
-	/* remove the input cb function */
-	if ( session->con->inpa ) {
-		purple_input_remove( session->con->inpa );
-		session->con->inpa = 0;
-	}
-
-	/* remove HTTP poll timer */
-	if ( session->http_timer_id > 0 )
-		purple_timeout_remove( session->http_timer_id );
-
-	/* remove slow queue manager timer */
-	if ( session->q_slow_timer_id > 0 )
-		purple_timeout_remove( session->q_slow_timer_id );
-
-	/* remove fast queue manager timer */
-	if ( session->q_fast_timer_id > 0 )
-		purple_timeout_remove( session->q_fast_timer_id );
-
-	/* remove all groupchat rooms */
-	while ( session->rooms != NULL ) {
-		struct multimx* multimx = (struct multimx *) session->rooms->data;
-
-		session->rooms = g_list_remove( session->rooms, multimx );
-
-		free( multimx );
-	}
-	g_list_free( session->rooms );
-	session->rooms = NULL;
-
-	/* remove all rx chats names */
-	while ( session->active_chats != NULL ) {
-		char* chat = (char*) session->active_chats->data;
-
-		session->active_chats = g_list_remove( session->active_chats, chat );
-
-		g_free( chat );
-	}
-	g_list_free( session->active_chats );
-	session->active_chats = NULL;
-
-	/* clear the internal invites */
-	while ( session->invites != NULL ) {
-		struct contact* contact = (struct contact*) session->invites->data;
-
-		session->invites = g_list_remove( session->invites, contact );
-
-		if ( contact->msg )
-			g_free( contact->msg );
-		if ( contact->statusMsg )
-			g_free( contact->statusMsg );
-		if ( contact->profile )
-			g_free( contact->profile );
-		g_free( contact );
-	}
-	g_list_free( session->invites );
-	session->invites = NULL;
-
-	/* free profile information */
-	if ( session->profile )
-		free( session->profile );
-
-	/* free custom emoticons */
-	mxit_free_emoticon_cache( session );
-
-	/* free allocated memory */
-	if ( session->uid )
-		g_free( session->uid );
-	g_free( session->encpwd );
-	session->encpwd = NULL;
-
-	/* flush all the commands still in the queue */
-	flush_queue( session );
-}
-
--- a/libpurple/protocols/mxit/protocol.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,352 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *			-- MXit client protocol implementation --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * 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		_MXIT_PROTO_H_
-#define		_MXIT_PROTO_H_
-
-
-/* Client protocol constants */
-#define		CP_SOCK_REC_TERM		'\x00'				/* socket record terminator */
-#define		CP_HTTP_REC_TERM		'\x26'				/* http record terminator '&' */
-#define		CP_FLD_TERM				'\x01'				/* field terminator */
-#define		CP_PKT_TERM				'\x02'				/* packet terminator */
-
-
-#define		CP_MAX_PACKET			( 1 * 1000 * 1000 )	/* maximum client protocol packet size (1 MB) */
-#define		CP_MAX_FILESIZE			( CP_MAX_PACKET - 1000 )	/* maximum file size (reserve some space for packet headers) */
-#define		MXIT_EMOTICON_SIZE		18					/* icon size for custom emoticons */
-#define		CP_MAX_STATUS_MSG		250					/* maximum status message length (in characters) */
-
-/* Avatars */
-#define		MXIT_AVATAR_SIZE		96					/* default avatar image size 96x96 */
-#define		MXIT_AVATAR_TYPE		"PNG"				/* request avatars in this file type (only a suggestion) */
-#define		MXIT_AVATAR_BITDEPT		24					/* request avatars with this bit depth (only a suggestion) */
-
-/* Protocol error codes */
-#define		MXIT_ERRCODE_SUCCESS	0
-#define		MXIT_ERRCODE_REDIRECT	16
-#define		MXIT_ERRCODE_LOGGEDOUT	42
-
-/* MXit client features */
-#define		MXIT_CF_NONE			0x000000
-#define		MXIT_CF_FORMS			0x000001
-#define		MXIT_CF_FILE_TRANSFER	0x000002
-#define		MXIT_CF_CAMERA			0x000004
-#define		MXIT_CF_COMMANDS		0x000008
-#define		MXIT_CF_SMS				0x000010
-#define		MXIT_CF_FILE_ACCESS		0x000020
-#define		MXIT_CF_MIDP2			0x000040
-#define		MXIT_CF_SKINS			0x000080
-#define		MXIT_CF_AUDIO			0x000100
-#define		MXIT_CF_ENCRYPTION		0x000200
-#define		MXIT_CF_VOICE_REC		0x000400
-#define		MXIT_CF_VECTOR_GFX		0x000800
-#define		MXIT_CF_IMAGES			0x001000
-#define		MXIT_CF_MARKUP			0x002000
-#define		MXIT_CF_VIBES			0x004000
-#define		MXIT_CF_SELECT_CONTACT	0x008000
-#define		MXIT_CF_CUSTOM_EMO		0x010000
-#define		MXIT_CF_ALERT_PROFILES	0x020000
-#define		MXIT_CF_EXT_MARKUP		0x040000
-#define		MXIT_CF_PLAIN_PWD		0x080000
-#define		MXIT_CF_NO_GATEWAYS		0x100000
-#define		MXIT_CF_NO_AVATARS		0x200000
-#define		MXIT_CF_GAMING			0x400000
-#define		MXIT_CF_GAMING_UPDATE	0x800000
-#define		MXIT_CF_VOICE			0x1000000
-#define		MXIT_CF_VIDEO			0x2000000
-#define		MXIT_CF_TOUCHSCREEN		0x4000000
-#define		MXIT_CF_SVC_CONNECTION	0x8000000
-#define		MXIT_CF_MXML			0x10000000
-#define		MXIT_CF_TYPING_NOTIFY	0x20000000
-
-/* Client features supported by this implementation */
-#define		MXIT_CP_FEATURES		( MXIT_CF_FILE_TRANSFER | MXIT_CF_FILE_ACCESS | MXIT_CF_AUDIO | MXIT_CF_MARKUP | MXIT_CF_EXT_MARKUP | MXIT_CF_NO_GATEWAYS | MXIT_CF_IMAGES | MXIT_CF_COMMANDS | MXIT_CF_VIBES | MXIT_CF_MIDP2 | MXIT_CF_TYPING_NOTIFY )
-
-
-#define		MXIT_PING_INTERVAL		( 5 * 60 )				/* ping the server after X seconds of being idle (5 minutes) */
-#define		MXIT_ACK_TIMEOUT		( 30 )					/* timeout after waiting X seconds for an ack from the server (30 seconds) */
-#define		MXIT_TX_DELAY			( 100 )					/* delay between sending consecutive packets (100 ms) */
-
-/* MXit client version */
-#define		MXIT_CP_DISTCODE		'P'						/* client distribution code (magic, do not touch!) */
-#define		MXIT_CP_ARCH			"Y"						/* client architecture series (Y not for Yoda but for PC-client) */
-#define		MXIT_CLIENT_ID			"LP"					/* client ID as specified by MXit */
-#define		MXIT_CP_PLATFORM		"PURPLE"				/* client platform */
-#define		MXIT_CP_PROTO_VESION	63						/* client protocol version */
-
-/* set operating system name */
-#if defined( __APPLE__ )
-#define		MXIT_CP_OS				"apple"
-#elif defined( _WIN32 )
-#define		MXIT_CP_OS				"windows"
-#elif defined( __linux__ )
-#define		MXIT_CP_OS				"linux"
-#else
-#define		MXIT_CP_OS				"unknown"
-#endif
-
-/* Client capabilities */
-#define		MXIT_CP_CAP				"utf8=true;cid="MXIT_CLIENT_ID
-
-/* Client settings */
-#define		MAX_QUEUE_SIZE			( 1 << 5 )				/* tx queue size (32 packets) */
-#define		MXIT_POPUP_WIN_NAME		"MXit Notification"		/* popup window name */
-#define		MXIT_DEFAULT_LOCALE		"en"					/* default locale setting */
-#define		MXIT_DEFAULT_LOC		"planetpurple"			/* the default location for registration */
-
-/* Client protocol commands */
-#define		CP_CMD_LOGIN			0x0001					/* (1) login */
-#define		CP_CMD_LOGOUT			0x0002					/* (2) logout */
-#define		CP_CMD_CONTACT			0x0003					/* (3) get contacts */
-#define		CP_CMD_UPDATE			0x0005					/* (5) update contact information */
-#define		CP_CMD_INVITE			0x0006					/* (6) subscribe to new contact */
-#define		CP_CMD_PRESENCE			0x0007					/* (7) get presence */
-#define		CP_CMD_REMOVE			0x0008					/* (8) remove contact */
-#define		CP_CMD_RX_MSG			0x0009					/* (9) get new messages */
-#define		CP_CMD_TX_MSG			0x000A					/* (10) send new message */
-#define		CP_CMD_REGISTER			0x000B					/* (11) register */
-//#define	CP_CMD_PROFILE_SET		0x000C					/* (12) set profile (DEPRECATED see CP_CMD_EXTPROFILE_SET) */
-#define		CP_CMD_SUGGESTCONTACTS	0x000D					/* (13) suggest contacts */
-#define		CP_CMD_POLL				0x0011					/* (17) poll the HTTP server for an update */
-//#define	CP_CMD_PROFILE_GET		0x001A					/* (26) get profile (DEPRECATED see CP_CMD_EXTPROFILE_GET) */
-#define		CP_CMD_MEDIA			0x001B					/* (27) get multimedia message */
-#define		CP_CMD_SPLASHCLICK		0x001F					/* (31) splash-screen clickthrough */
-#define		CP_CMD_STATUS			0x0020					/* (32) set shown presence & status */
-#define		CP_CMD_MSGEVENT			0x0023					/* (35) Raise message event */
-#define		CP_CMD_GOT_MSGEVENT		0x0024					/* (36) Get message event */
-#define		CP_CMD_MOOD				0x0029					/* (41) set mood */
-#define		CP_CMD_KICK				0x002B					/* (43) login kick */
-#define		CP_CMD_GRPCHAT_CREATE	0x002C					/* (44) create new groupchat */
-#define		CP_CMD_GRPCHAT_INVITE	0x002D					/* (45) add new groupchat member */
-#define		CP_CMD_NEW_SUB			0x0033					/* (51) get new subscription */
-#define		CP_CMD_ALLOW			0x0034					/* (52) allow subscription */
-#define		CP_CMD_DENY				0x0037					/* (55) deny subscription */
-#define		CP_CMD_EXTPROFILE_GET	0x0039					/* (57) get extended profile */
-#define		CP_CMD_EXTPROFILE_SET	0x003A					/* (58) set extended profile */
-#define		CP_CMD_PING				0x03E8					/* (1000) ping (keepalive) */
-
-/* HTTP connection */
-#define		MXIT_HTTP_POLL_MIN		7						/* minimum time between HTTP polls (seconds) */
-#define		MXIT_HTTP_POLL_MAX		( 10 * 60 )				/* maximum time between HTTP polls (seconds) */
-
-/* receiver states */
-#define		RX_STATE_RLEN			0x01					/* reading packet length section */
-#define		RX_STATE_DATA			0x02					/* reading packet data section */
-#define		RX_STATE_PROC			0x03					/* process read data */
-
-/* message flags */
-#define		CP_MSG_NOTIFY_DELIVERY	0x0002					/* request delivery notification */
-#define		CP_MSG_NOTIFY_READ		0x0004					/* request read notification */
-#define		CP_MSG_PWD_ENCRYPTED	0x0010					/* message is password encrypted */
-#define		CP_MSG_TL_ENCRYPTED		0x0020					/* message is transport encrypted */
-#define		CP_MSG_RPLY_PWD_ENCRYPT	0x0040					/* reply should be password encrypted */
-#define		CP_MSG_RPLY_TL_ENCRYPT	0x0080					/* reply should be transport encrypted */
-#define		CP_MSG_MARKUP			0x0200					/* message may contain markup */
-#define		CP_MSG_EMOTICON			0x0400					/* message may contain custom emoticons */
-#define		CP_MSG_FAREWELL			0x0800					/* this is a farewell message */
-
-/* redirect types */
-#define		CP_REDIRECT_PERMANENT	1						/* permanent redirect */
-#define		CP_REDIRECT_TEMPORARY	2						/* temporary redirect */
-
-/* message tx types */
-#define		CP_MSGTYPE_NORMAL		0x01					/* normal message */
-#define		CP_MSGTYPE_CHAT			0x02					/* chat message */
-#define		CP_MSGTYPE_HEADLINE		0x03					/* headline message */
-#define		CP_MSGTYPE_ERROR		0x04					/* error message */
-#define		CP_MSGTYPE_GROUPCHAT	0x05					/* groupchat message */
-#define		CP_MSGTYPE_FORM			0x06					/* mxit custom form */
-#define		CP_MSGTYPE_COMMAND		0x07					/* mxit command */
-
-/* message event types */
-#define		CP_MSGEVENT_DELIVERED	0x02					/* message was delivered */
-#define		CP_MSGEVENT_DISPLAYED	0x04					/* message was viewed */
-#define		CP_MSGEVENT_TYPING		0x10					/* user is typing */
-#define		CP_MSGEVENT_STOPPED		0x20					/* user has stopped typing */
-#define		CP_MSGEVENT_ANGRY		0x40					/* user is typing angrily */
-#define		CP_MSGEVENT_ERASING		0x80					/* user is erasing text */
-
-/* extended profile attribute fields */
-#define		CP_PROFILE_BIRTHDATE	"birthdate"				/* Birthdate (String - ISO 8601 format) */
-#define		CP_PROFILE_GENDER		"gender"				/* Gender (Boolean - 0=female, 1=male) */
-// #define		CP_PROFILE_HIDENUMBER	"hidenumber"			/* Hide Number (Boolean - 0=false, 1=true) (DEPRECATED) */
-#define		CP_PROFILE_FULLNAME		"fullname"				/* Fullname (UTF8 String) */
-#define		CP_PROFILE_STATUS		"statusmsg"				/* Status Message (UTF8 String) */
-#define		CP_PROFILE_PREVSTATUS	"prevstatusmsgs"		/* Previous Status Messages (UTF8 String) */
-#define		CP_PROFILE_AVATAR		"avatarid"				/* Avatar ID (String) */
-#define		CP_PROFILE_MODIFIED		"lastmodified"			/* Last-Modified timestamp */
-#define		CP_PROFILE_TITLE		"title"					/* Title (UTF8 String) */
-#define		CP_PROFILE_FIRSTNAME	"firstname"				/* First name (UTF8 String) */
-#define		CP_PROFILE_LASTNAME		"lastname"				/* Last name (UTF8 String) */
-#define		CP_PROFILE_EMAIL		"email"					/* Email address (UTF8 String) */
-#define		CP_PROFILE_MOBILENR		"mobilenumber"			/* Mobile Number (UTF8 String) */
-#define		CP_PROFILE_REGCOUNTRY	"registeredcountry"		/* Registered Country Code (UTF8 String) */
-#define		CP_PROFILE_FLAGS		"flags"					/* Profile flags (Bitset) */
-#define		CP_PROFILE_LASTSEEN		"lastseen"				/* Last-Online timestamp */
-#define		CP_PROFILE_WHEREAMI		"whereami"				/* Where am I / Where I live */
-#define		CP_PROFILE_ABOUTME		"aboutme"				/* About me */
-#define		CP_PROFILE_RELATIONSHIP	"relationship"			/* Relationship Status */
-
-/* extended profile field types */
-#define		CP_PROFILE_TYPE_BOOL	0x02					/* boolean (0 or 1) */
-#define		CP_PROFILE_TYPE_SHORT	0x04					/* short (16-bit) */
-#define		CP_PROFILE_TYPE_INT		0x05					/* integer (32-bit) */
-#define		CP_PROFILE_TYPE_LONG	0x06					/* long (64-bit) */
-#define		CP_PROFILE_TYPE_UTF8	0x0A					/* UTF8 string */
-#define		CP_PROFILE_TYPE_DATE	0x0B					/* date-time (ISO 8601 format) */
-
-/* profile flags */
-#define		CP_PROF_NOT_SEARCHABLE	0x02					/* user cannot be searched for */
-#define		CP_PROF_NOT_SUGGESTABLE	0x08					/* user cannot be suggested as friend */
-#define		CP_PROF_DOBLOCKED		0x40					/* date-of-birth cannot be changed */
-
-/* suggestion types */
-#define		CP_SUGGEST_ADDRESSBOOK	0						/* address book search */
-#define		CP_SUGGEST_FRIENDS		1						/* suggested friends */
-#define		CP_SUGGEST_SEARCH		2						/* free-text search */
-#define		CP_SUGGEST_MXITID		3						/* MXitId search */
-
-/* define this to enable protocol debugging (very verbose logging) */
-#define		DEBUG_PROTOCOL
-
-
-/* ======================================================================================= */
-
-struct MXitSession;
-
-/*------------------------------------------*/
-
-struct field {
-	char*				data;
-	size_t				len;
-};
-
-struct record {
-	struct field**		fields;
-	int					fcount;
-};
-
-struct rx_packet {
-	int					cmd;
-	int					errcode;
-	char*				errmsg;
-	struct record**		records;
-	int					rcount;
-};
-
-struct tx_packet {
-	int					cmd;
-	char				header[256];
-	int					headerlen;
-	char*				data;
-	int					datalen;
-};
-
-/*------------------------------------------*/
-
-
-/*
- * A received message data object
- */
-struct RXMsgData {
-	struct MXitSession*		session;					/* MXit session object */
-	char*					from;						/* the sender's name */
-	time_t					timestamp;					/* time at which the message was sent */
-	GString*				msg;						/* newly created message converted to libPurple formatting */
-	gboolean				got_img;					/* flag to say if this message got any images/emoticons embedded */
-	short					img_count;					/* the amount of images/emoticons still outstanding for the message */
-	int						chatid;						/* multimx chatroom id */
-	int						flags;						/* libPurple conversation flags */
-	gboolean				converted;					/* true if the message has been completely parsed and converted to libPurple markup */
-	gboolean				processed;					/* the message has been processed completely and should be freed up */
-};
-
-
-
-/*
- * The packet transmission queue.
- */
-struct tx_queue {
-	struct tx_packet*	packets[MAX_QUEUE_SIZE];		/* array of packet pointers */
-	int					count;							/* number of packets queued */
-	int					rd_i;							/* queue current read index (queue offset for reading a packet) */
-	int					wr_i;							/* queue current write index (queue offset for adding new packet) */
-};
-
-
-/* ======================================================================================= */
-
-void mxit_popup( int type, const char* heading, const char* message );
-void mxit_strip_domain( char* username );
-gboolean find_active_chat( const GList* chats, const char* who );
-
-void mxit_cb_rx( gpointer data, gint source, PurpleInputCondition cond );
-gboolean mxit_manage_queue_slow( gpointer user_data );
-gboolean mxit_manage_queue_fast( gpointer user_data );
-gboolean mxit_manage_polling( gpointer user_data );
-
-void mxit_send_register( struct MXitSession* session );
-void mxit_send_login( struct MXitSession* session );
-void mxit_send_logout( struct MXitSession* session );
-void mxit_send_ping( struct MXitSession* session );
-void mxit_send_poll( struct MXitSession* session );
-
-void mxit_send_presence( struct MXitSession* session, int presence, const char* statusmsg );
-void mxit_send_mood( struct MXitSession* session, int mood );
-void mxit_send_message( struct MXitSession* session, const char* to, const char* msg, gboolean parse_markup, gboolean is_command );
-
-void mxit_send_extprofile_update( struct MXitSession* session, const char* password, unsigned int nr_attrib, const char* attributes );
-void mxit_send_extprofile_request( struct MXitSession* session, const char* username, unsigned int nr_attrib, const char* attribute[] );
-
-void mxit_send_suggest_friends( struct MXitSession* session, int max, unsigned int nr_attrib, const char* attribute[] );
-void mxit_send_suggest_search( struct MXitSession* session, int max, const char* text, unsigned int nr_attrib, const char* attribute[] );
-
-void mxit_send_invite( struct MXitSession* session, const char* username, gboolean mxitid, const char* alias, const char* groupname, const char* message );
-void mxit_send_remove( struct MXitSession* session, const char* username );
-void mxit_send_allow_sub( struct MXitSession* session, const char* username, const char* alias );
-void mxit_send_deny_sub( struct MXitSession* session, const char* username, const char* reason );
-void mxit_send_update_contact( struct MXitSession* session, const char* username, const char* alias, const char* groupname );
-void mxit_send_splashclick( struct MXitSession* session, const char* splashid );
-void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event);
-
-void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, size_t buflen );
-void mxit_send_file_reject( struct MXitSession* session, const char* fileid );
-void mxit_send_file_accept( struct MXitSession* session, const char* fileid, size_t filesize, size_t offset );
-void mxit_send_file_received( struct MXitSession* session, const char* fileid, short status );
-void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, size_t avatarlen );
-void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const char* avatarId );
-
-void mxit_send_groupchat_create( struct MXitSession* session, const char* groupname, int nr_usernames, const char* usernames[] );
-void mxit_send_groupchat_invite( struct MXitSession* session, const char* roomid, int nr_usernames, const char* usernames[] );
-
-int mxit_parse_packet( struct MXitSession* session );
-void dump_bytes( struct MXitSession* session, const char* buf, int len );
-void mxit_close_connection( struct MXitSession* session );
-gint64 mxit_now_milli( void );
-
-
-#endif		/* _MXIT_PROTO_H_ */
-
--- a/libpurple/protocols/mxit/roster.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,900 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *			-- user roster management (mxit contacts) --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include	"internal.h"
-#include	"debug.h"
-
-#include	"protocol.h"
-#include	"mxit.h"
-#include	"roster.h"
-
-
-struct contact_invite {
-	struct MXitSession*		session;		/* MXit session object */
-	struct contact*			contact;		/* The contact performing the invite */
-};
-
-
-/*========================================================================================================================
- * Presence / Status
- */
-
-/* statuses (reference: libpurple/status.h) */
-static struct status
-{
-	PurpleStatusPrimitive	primitive;
-	int						mxit;
-	const char*				id;
-	const char*				name;
-} const mxit_statuses[] = {
-		/*	primitive,						no,							id,			name					*/
-		{	PURPLE_STATUS_OFFLINE,			MXIT_PRESENCE_OFFLINE,		"offline",	N_( "Offline" )			},	/* 0 */
-		{	PURPLE_STATUS_AVAILABLE,		MXIT_PRESENCE_ONLINE,		"online",	N_( "Available" )		},	/* 1 */
-		{	PURPLE_STATUS_AWAY,				MXIT_PRESENCE_AWAY,			"away",		N_( "Away" )			},	/* 2 */
-		{	PURPLE_STATUS_AVAILABLE,		MXIT_PRESENCE_AVAILABLE,	"chat",		N_( "Chatty" )			},	/* 3 */
-		{	PURPLE_STATUS_UNAVAILABLE,		MXIT_PRESENCE_DND,			"dnd",		N_( "Do Not Disturb" )	}	/* 4 */
-};
-
-
-/*------------------------------------------------------------------------
- * Return list of supported statuses. (see status.h)
- *
- *  @param account	The MXit account object
- *  @return			List of PurpleStatusType
- */
-GList* mxit_status_types( PurpleAccount* account )
-{
-	GList*				statuslist	= NULL;
-	PurpleStatusType*	type;
-	unsigned int		i;
-
-	for ( i = 0; i < ARRAY_SIZE( mxit_statuses ); i++ ) {
-		const struct status* status = &mxit_statuses[i];
-
-		/* add mxit status (reference: "libpurple/status.h") */
-		type = purple_status_type_new_with_attrs( status->primitive, status->id, _( status->name ), TRUE, TRUE, FALSE,
-					"message", _( "Message" ), purple_value_new( PURPLE_TYPE_STRING ),
-					NULL );
-
-		statuslist = g_list_append( statuslist, type );
-	}
-
-	/* add Mood option */
-	type = purple_status_type_new_with_attrs( PURPLE_STATUS_MOOD, "mood", NULL, FALSE, TRUE, TRUE,
-		PURPLE_MOOD_NAME, _( "Mood Name" ), purple_value_new( PURPLE_TYPE_STRING ),
-		NULL );
-	statuslist = g_list_append( statuslist, type );
-
-	return statuslist;
-}
-
-
-/*------------------------------------------------------------------------
- * Returns the MXit presence code, given the unique status ID.
- *
- *  @param id		The status ID
- *  @return			The MXit presence code
- */
-int mxit_convert_presence( const char* id )
-{
-	unsigned int	i;
-
-	for ( i = 0; i < ARRAY_SIZE( mxit_statuses ); i++ ) {
-		if ( strcmp( mxit_statuses[i].id, id ) == 0 )	/* status found! */
-			return mxit_statuses[i].mxit;
-	}
-
-	return -1;
-}
-
-
-/*------------------------------------------------------------------------
- * Returns the MXit presence as a string, given the MXit presence ID.
- *
- *  @param no		The MXit presence I (see above)
- *  @return			The presence as a text string
- */
-const char* mxit_convert_presence_to_name( short no )
-{
-	unsigned int	i;
-
-	for ( i = 0; i < ARRAY_SIZE( mxit_statuses ); i++ ) {
-		if ( mxit_statuses[i].mxit == no )				/* status found! */
-			return _( mxit_statuses[i].name );
-	}
-
-	return "";
-}
-
-
-/*========================================================================================================================
- * Moods
- */
-
-/* moods (reference: libpurple/status.h) */
-static PurpleMood mxit_moods[] = {
-	{ "angry",		N_( "Angry" ),		NULL },
-	{ "excited",	N_( "Excited" ),	NULL },
-	{ "grumpy",		N_( "Grumpy" ),		NULL },
-	{ "happy",		N_( "Happy" ),		NULL },
-	{ "in_love",	N_( "In love" ),	NULL },
-	{ "invincible",	N_( "Invincible" ),	NULL },
-	{ "sad",		N_( "Sad" ),		NULL },
-	{ "hot",		N_( "Hot" ),		NULL },
-	{ "sick",		N_( "Sick" ),		NULL },
-	{ "sleepy",		N_( "Sleepy" ),		NULL },
-	{ "bored",		N_( "Bored" ),		NULL },
-	{ "cold",		N_( "Cold" ),		NULL },
-	{ "confused",	N_( "Confused" ),	NULL },
-	{ "hungry",		N_( "Hungry" ),		NULL },
-	{ "stressed",	N_( "Stressed" ),	NULL },
-	/* Mark the last record. */
-	{ NULL, NULL, NULL }
-};
-
-
-/*------------------------------------------------------------------------
- * Returns the MXit mood code, given the unique mood ID.
- *
- *  @param id		The mood ID
- *  @return			The MXit mood code
- */
-int mxit_convert_mood( const char* id )
-{
-	unsigned int	i;
-
-	/* Mood is being unset */
-	if ( id == NULL )
-		return MXIT_MOOD_NONE;
-
-	for ( i = 0; i < ARRAY_SIZE( mxit_moods ) - 1; i++ ) {
-		if ( strcmp( mxit_moods[i].mood, id ) == 0 )	/* mood found! */
-			return i + 1;		/* because MXIT_MOOD_NONE is 0 */
-	}
-
-	return -1;
-}
-
-
-/*------------------------------------------------------------------------
- * Return the list of MXit-supported moods.
- *
- *  @param account	The MXit account object
- */
-PurpleMood* mxit_get_moods( PurpleAccount *account )
-{
-	return mxit_moods;
-}
-
-
-/*------------------------------------------------------------------------
- * Returns the MXit mood as a string, given the MXit mood's ID.
- *
- *  @param id		The MXit mood ID (see roster.h)
- *  @return			The mood as a text string
- */
-const char* mxit_convert_mood_to_name( short id )
-{
-	switch ( id ) {
-		case MXIT_MOOD_ANGRY :
-				return _( "Angry" );
-		case MXIT_MOOD_EXCITED :
-				return _( "Excited" );
-		case MXIT_MOOD_GRUMPY :
-				return _( "Grumpy" );
-		case MXIT_MOOD_HAPPY :
-				return _( "Happy" );
-		case MXIT_MOOD_INLOVE :
-				return _( "In Love" );
-		case MXIT_MOOD_INVINCIBLE :
-				return _( "Invincible" );
-		case MXIT_MOOD_SAD :
-				return _( "Sad" );
-		case MXIT_MOOD_HOT :
-				return _( "Hot" );
-		case MXIT_MOOD_SICK :
-				return _( "Sick" );
-		case MXIT_MOOD_SLEEPY :
-				return _( "Sleepy" );
-		case MXIT_MOOD_BORED :
-				return _( "Bored" );
-		case MXIT_MOOD_COLD :
-				return _( "Cold" );
-		case MXIT_MOOD_CONFUSED :
-				return _( "Confused" );
-		case MXIT_MOOD_HUNGRY :
-				return _( "Hungry" );
-		case MXIT_MOOD_STRESSED :
-				return _( "Stressed" );
-		case MXIT_MOOD_NONE :
-		default :
-				return "";
-	}
-}
-
-
-/*========================================================================================================================
- * Subscription Types
- */
-
-/*------------------------------------------------------------------------
- * Returns a Contact subscription type as a string.
- *
- *  @param subtype	The subscription type
- *  @return			The subscription type as a text string
- */
-const char* mxit_convert_subtype_to_name( short subtype )
-{
-	switch ( subtype ) {
-		case MXIT_SUBTYPE_BOTH :
-				return _( "Both" );
-		case MXIT_SUBTYPE_PENDING :
-				return _( "Pending" );
-		case MXIT_SUBTYPE_ASK :
-				return _( "Invited" );
-		case MXIT_SUBTYPE_REJECTED :
-				return _( "Rejected" );
-		case MXIT_SUBTYPE_DELETED :
-				return _( "Deleted" );
-		case MXIT_SUBTYPE_NONE :
-				return _( "None" );
-		default :
-				return "";
-	}
-}
-
-
-/*========================================================================================================================
- * Calls from the MXit Protocol layer
- */
-
-#if	0
-/*------------------------------------------------------------------------
- * Dump a contact's info the the debug console.
- *
- *  @param contact		The contact
- */
-static void dump_contact( struct contact* contact )
-{
-	purple_debug_info( MXIT_PLUGIN_ID, "CONTACT: name='%s', alias='%s', group='%s', type='%i', presence='%i', mood='%i'\n",
-						contact->username, contact->alias, contact->groupname, contact->type, contact->presence, contact->mood );
-}
-#endif
-
-
-#if	0
-/*------------------------------------------------------------------------
- * Move a buddy from one group to another
- *
- * @param buddy		the buddy to move between groups
- * @param group		the new group to move the buddy to
- */
-static PurpleBuddy* mxit_update_buddy_group( struct MXitSession* session, PurpleBuddy* buddy, PurpleGroup* group )
-{
-	PurpleGroup*		current_group	= purple_buddy_get_group( buddy );
-
-	/* make sure the groups actually differs */
-	if ( strcmp( current_group->name, group->name ) != 0 ) {
-		/* groupnames does not match, so we need to make the update */
-
-		struct contact*		contact		= purple_buddy_get_protocol_data( buddy );
-		PurpleBuddy*		newbuddy	= NULL;
-
-		purple_debug_info( MXIT_PLUGIN_ID, "Moving '%s' from group '%s' to '%s'\n", buddy->alias, current_group->name, group->name );
-
-		/*
-		 * XXX: libPurple does not currently provide an API to change or rename the group name
-		 * for a specific buddy. One option is to remove the buddy from the list and re-adding
-		 * him in the new group, but by doing that makes the buddy go offline and then online
-		 * again. This is really not ideal and very irritating, but how else then?
-		 */
-
-		/* create new buddy, and transfer 'contact' data */
-		newbuddy = purple_buddy_new( session->acc, buddy->name, buddy->alias );
-		purple_buddy_set_protocol_data( newbuddy, contact );
-		purple_buddy_set_protocol_data( buddy, NULL );
-
-		/* remove the buddy */
-		purple_blist_remove_buddy( buddy );
-
-		/* add buddy */
-		purple_blist_add_buddy( newbuddy, NULL, group, NULL );
-
-		/* now re-instate his presence again */
-		if ( contact ) {
-
-			/* update the buddy's status (reference: "libpurple/prpl.h") */
-			if ( contact->statusMsg )
-				purple_prpl_got_user_status( session->acc, newbuddy->name, mxit_statuses[contact->presence].id, "message", contact->statusMsg, NULL );
-			else
-				purple_prpl_got_user_status( session->acc, newbuddy->name, mxit_statuses[contact->presence].id, NULL );
-
-			/* update the buddy's mood */
-			if ( contact->mood == MXIT_MOOD_NONE )
-				purple_prpl_got_user_status_deactive( session->acc, newbuddy->name, "mood" );
-			else
-				purple_prpl_got_user_status( session->acc, newbuddy->name, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL );
-
-			/* update avatar */
-			if ( contact->avatarId ) {
-				mxit_get_avatar( session, newbuddy->name, contact->avatarId );
-				g_free( contact->avatarId );
-				contact->avatarId = NULL;
-			}
-		}
-
-		return newbuddy;
-	}
-	else
-		return buddy;
-}
-#endif
-
-
-/*------------------------------------------------------------------------
- * A contact update packet was received from the MXit server, so update the buddy's
- * information.
- *
- *  @param session		The MXit session object
- *  @param contact		The contact
- */
-void mxit_update_contact( struct MXitSession* session, struct contact* contact )
-{
-	PurpleBuddy*		buddy	= NULL;
-	PurpleGroup*		group	= NULL;
-	const char*			id		= NULL;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_update_contact: user='%s' alias='%s' group='%s'\n", contact->username, contact->alias, contact->groupname );
-
-	/*
-	 * libPurple requires all contacts to be in a group.
-	 * So if this MXit contact isn't in a group, pretend it is.
-	 */
-	if ( *contact->groupname == '\0' ) {
-		g_strlcpy( contact->groupname, MXIT_DEFAULT_GROUP, sizeof( contact->groupname ) );
-	}
-
-	/* find or create a group for this contact */
-	group = purple_find_group( contact->groupname );
-	if ( !group )
-		group = purple_group_new( contact->groupname );
-
-	/* see if the buddy is not in the group already */
-	buddy = purple_find_buddy_in_group( session->acc, contact->username, group );
-	if ( !buddy ) {
-		/* buddy not found in the group */
-
-		/* lets try finding him in all groups */
-		buddy = purple_find_buddy( session->acc, contact->username );
-		if ( buddy ) {
-			/* ok, so we found him in another group. to switch him between groups we must delete him and add him again. */
-			purple_blist_remove_buddy( buddy );
-			buddy = NULL;
-		}
-
-		/* create new buddy */
-		buddy = purple_buddy_new( session->acc, contact->username, contact->alias );
-		purple_buddy_set_protocol_data( buddy, contact );
-
-		/* add new buddy to list */
-		purple_blist_add_buddy( buddy, NULL, group, NULL );
-	}
-	else {
-		/* buddy was found in the group */
-
-		gpointer data = NULL;
-
-		/* now update the buddy's alias */
-		purple_blist_alias_buddy( buddy, contact->alias );
-
-		/* replace the buddy's contact struct */
-		if ( ( data = purple_buddy_get_protocol_data( buddy ) ) )
-			free( data );
-		purple_buddy_set_protocol_data( buddy, contact );
-	}
-
-	/* load buddy's avatar id */
-	id = purple_buddy_icons_get_checksum_for_user( buddy );
-	if ( id )
-		contact->avatarId = g_strdup( id );
-	else
-		contact->avatarId = NULL;
-
-	/* update the buddy's status (reference: "libpurple/prpl.h") */
-	purple_prpl_got_user_status( session->acc, contact->username, mxit_statuses[contact->presence].id, NULL );
-
-	/* update the buddy's mood */
-	if ( contact->mood == MXIT_MOOD_NONE )
-		purple_prpl_got_user_status_deactive( session->acc, contact->username, "mood" );
-	else
-		purple_prpl_got_user_status( session->acc, contact->username, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL );
-}
-
-
-/*------------------------------------------------------------------------
- * A presence update packet was received from the MXit server, so update the buddy's
- * information.
- *
- *  @param session		The MXit session object
- *  @param username		The contact which presence to update
- *  @param presence		The new presence state for the contact
- *  @param mood			The new mood for the contact
- *  @param customMood	The custom mood identifier
- *  @param statusMsg	This is the contact's status message
- *  @param flags		The contact's presence flags.
- */
-void mxit_update_buddy_presence( struct MXitSession* session, const char* username, short presence, short mood, const char* customMood, const char* statusMsg, int flags )
-{
-	PurpleBuddy*		buddy	= NULL;
-	struct contact*		contact	= NULL;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_update_buddy_presence: user='%s' presence=%i mood=%i customMood='%s' statusMsg='%s'\n",
-		username, presence, mood, customMood, statusMsg );
-
-	if ( ( presence < MXIT_PRESENCE_OFFLINE ) || ( presence > MXIT_PRESENCE_DND ) ) {
-		purple_debug_info( MXIT_PLUGIN_ID, "mxit_update_buddy_presence: invalid presence state %i\n", presence );
-		return;		/* ignore packet */
-	}
-
-	/* find the buddy information for this contact (reference: "libpurple/blist.h") */
-	buddy = purple_find_buddy( session->acc, username );
-	if ( !buddy ) {
-		purple_debug_warning( MXIT_PLUGIN_ID, "mxit_update_buddy_presence: unable to find the buddy '%s'\n", username );
-		return;
-	}
-
-	contact = purple_buddy_get_protocol_data( buddy );
-	if ( !contact )
-		return;
-
-	contact->presence = presence;
-	contact->mood = mood;
-	contact->capabilities = flags;
-
-	g_strlcpy( contact->customMood, customMood, sizeof( contact->customMood ) );
-	// TODO: Download custom mood frame.
-
-	/* update status message */
-	if ( contact->statusMsg ) {
-		g_free( contact->statusMsg );
-		contact->statusMsg = NULL;
-	}
-	if ( ( statusMsg ) && ( statusMsg[0] != '\0' ) )
-		contact->statusMsg = g_markup_escape_text( statusMsg, -1 );
-
-	/* update the buddy's status (reference: "libpurple/prpl.h") */
-	if ( contact->statusMsg )
-		purple_prpl_got_user_status( session->acc, username, mxit_statuses[contact->presence].id, "message", contact->statusMsg, NULL );
-	else
-		purple_prpl_got_user_status( session->acc, username, mxit_statuses[contact->presence].id, NULL );
-
-	/* update the buddy's mood */
-	if ( contact->mood == MXIT_MOOD_NONE )
-		purple_prpl_got_user_status_deactive( session->acc, username, "mood" );
-	else
-		purple_prpl_got_user_status( session->acc, username, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL );
-}
-
-
-/*------------------------------------------------------------------------
- * Update the buddy's avatar.
- * Either a presence update packet was received from the MXit server, or a profile response.
- *
- *  @param session		The MXit session object
- *  @param username		The contact which presence to update
- *  @param avatarId		This is the contact's avatar id
- */
-void mxit_update_buddy_avatar( struct MXitSession* session, const char* username, const char* avatarId )
-{
-	PurpleBuddy*		buddy	= NULL;
-	struct contact*		contact	= NULL;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_update_buddy_avatar: user='%s' avatar='%s'\n", username, avatarId );
-
-	/* find the buddy information for this contact (reference: "libpurple/blist.h") */
-	buddy = purple_find_buddy( session->acc, username );
-	if ( !buddy ) {
-		purple_debug_warning( MXIT_PLUGIN_ID, "mxit_update_buddy_presence: unable to find the buddy '%s'\n", username );
-		return;
-	}
-
-	contact = purple_buddy_get_protocol_data( buddy );
-	if ( !contact )
-		return;
-
-	if ( ( contact->avatarId ) && ( g_ascii_strcasecmp( contact->avatarId, avatarId ) == 0 ) ) {
-		/*  avatar has not changed - do nothing */
-	}
-	else if ( avatarId[0] != '\0' ) {		/* avatar has changed */
-		if ( contact->avatarId )
-			g_free( contact->avatarId );
-		contact->avatarId = g_strdup( avatarId );
-
-		/* Send request to download new avatar image */
-		mxit_get_avatar( session, username, avatarId );
-	}
-	else		/* clear current avatar */
-		purple_buddy_icons_set_for_user( session->acc, username, NULL, 0, NULL );
-}
-
-
-/*------------------------------------------------------------------------
- * update the blist cached by libPurple. We need to do this to keep
- * libPurple and MXit's rosters in sync with each other.
- *
- * @param session		The MXit session object
- */
-void mxit_update_blist( struct MXitSession* session )
-{
-	PurpleBuddy*	buddy	= NULL;
-	GSList*			list	= NULL;
-	unsigned int	i;
-
-	/* remove all buddies we did not receive a roster update for.
-	 * these contacts must have been removed from another client */
-	list = purple_find_buddies( session->acc, NULL );
-
-	for ( i = 0; i < g_slist_length( list ); i++ ) {
-		buddy = g_slist_nth_data( list, i );
-
-		if ( !purple_buddy_get_protocol_data( buddy ) ) {
-			const gchar* alias = purple_buddy_get_alias( buddy );
-			const gchar* name = purple_buddy_get_name( buddy );
-
-			/* this buddy should be removed, because we did not receive him in our roster update from MXit */
-			purple_debug_info( MXIT_PLUGIN_ID, "Removed 'old' buddy from the blist '%s' (%s)\n", alias, name );
-			purple_blist_remove_buddy( buddy );
-		}
-	}
-
-	/* tell the UI to update the blist */
-	purple_blist_add_account( session->acc );
-}
-
-
-/*------------------------------------------------------------------------
- * The user authorized an invite (subscription request).
- *
- *  @param user_data	Object associated with the invite
- */
-static void mxit_cb_buddy_auth( gpointer user_data )
-{
-	struct contact_invite*	invite	= (struct contact_invite*) user_data;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_buddy_auth '%s'\n", invite->contact->username );
-
-	/* send a allow subscription packet to MXit */
-	mxit_send_allow_sub( invite->session, invite->contact->username, invite->contact->alias );
-
-	/* remove the invite from our internal invites list */
-	invite->session->invites = g_list_remove( invite->session->invites, invite->contact );
-
-	/* freeup invite object */
-	if ( invite->contact->msg )
-		g_free( invite->contact->msg );
-	if ( invite->contact->statusMsg )
-		g_free( invite->contact->statusMsg );
-	if ( invite->contact->profile )
-		g_free( invite->contact->profile );
-	g_free( invite->contact );
-	g_free( invite );
-}
-
-
-/*------------------------------------------------------------------------
- * The user rejected an invite (subscription request).
- *
- *  @param user_data	Object associated with the invite
- */
-static void mxit_cb_buddy_deny( gpointer user_data )
-{
-	struct contact_invite*	invite	= (struct contact_invite*) user_data;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_buddy_deny '%s'\n", invite->contact->username );
-
-	/* send a deny subscription packet to MXit */
-	mxit_send_deny_sub( invite->session, invite->contact->username, NULL );
-
-	/* remove the invite from our internal invites list */
-	invite->session->invites = g_list_remove( invite->session->invites, invite->contact );
-
-	/* freeup invite object */
-	if ( invite->contact->msg )
-		g_free( invite->contact->msg );
-	if ( invite->contact->statusMsg )
-		g_free( invite->contact->statusMsg );
-	if ( invite->contact->profile )
-		g_free( invite->contact->profile );
-	g_free( invite->contact );
-	g_free( invite );
-}
-
-
-/*------------------------------------------------------------------------
- * A new subscription request packet was received from the MXit server.
- * Prompt user to accept or reject it.
- *
- *  @param session		The MXit session object
- *  @param contact		The contact performing the invite
- */
-void mxit_new_subscription( struct MXitSession* session, struct contact* contact )
-{
-	struct contact_invite*	invite;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_new_subscription from '%s' (%s)\n", contact->username, contact->alias );
-
-	invite = g_new0( struct contact_invite, 1 );
-	invite->session = session;
-	invite->contact = contact;
-
-	/* add the invite to our internal invites list */
-	invite->session->invites = g_list_append( invite->session->invites, invite->contact );
-
-	/* (reference: "libpurple/account.h") */
-	purple_account_request_authorization( session->acc, contact->username, NULL, contact->alias, contact->msg, FALSE, mxit_cb_buddy_auth, mxit_cb_buddy_deny, invite );
-}
-
-
-/*------------------------------------------------------------------------
- * Return the contact object for a mxit invite
- *
- *  @param session		The MXit session object
- *  @param username		The username of the contact
- *  @return				The contact object for the inviting user
- */
-struct contact* get_mxit_invite_contact( struct MXitSession* session, const char* username )
-{
-	struct contact*		con		= NULL;
-	struct contact*		match	= NULL;
-	unsigned int		i;
-
-	/* run through all the invites and try and find the match */
-	for ( i = 0; i < g_list_length( session->invites ); i++ ) {
-		con = g_list_nth_data( session->invites, i );
-		if ( strcmp( con->username, username ) == 0 ) {
-			/* invite found */
-			match = con;
-			break;
-		}
-	}
-
-	return match;
-}
-
-
-/*------------------------------------------------------------------------
- * Return TRUE if this is a MXit Chatroom contact.
- *
- *  @param session		The MXit session object
- *  @param username		The username of the contact
- */
-gboolean is_mxit_chatroom_contact( struct MXitSession* session, const char* username )
-{
-	PurpleBuddy*		buddy;
-	struct contact*		contact	= NULL;
-
-	/* find the buddy */
-	buddy = purple_find_buddy( session->acc, username );
-	if ( !buddy ) {
-		purple_debug_warning( MXIT_PLUGIN_ID, "is_mxit_chatroom_contact: unable to find the buddy '%s'\n", username );
-		return FALSE;
-	}
-
-	contact = purple_buddy_get_protocol_data( buddy );
-	if ( !contact )
-		return FALSE;
-
-	return ( contact->type == MXIT_TYPE_CHATROOM );
-}
-
-
-/*========================================================================================================================
- * Callbacks from libpurple
- */
-
-/*------------------------------------------------------------------------
- * The user has added a buddy to the list, so send an invite request.
- *
- *  @param gc		The connection object
- *  @param buddy	The new buddy
- *  @param group	The group of the new buddy
- *  @param message	The invite message
- */
-void mxit_add_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group, const char* message )
-{
-	struct MXitSession*	session	= purple_connection_get_protocol_data( gc );
-	GSList*				list	= NULL;
-	PurpleBuddy*		mxbuddy	= NULL;
-	unsigned int		i;
-	const gchar *		buddy_name = purple_buddy_get_name( buddy );
-	const gchar *		buddy_alias = purple_buddy_get_alias( buddy );
-	const gchar *		group_name = purple_group_get_name( group );
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_add_buddy '%s' (group='%s')\n", buddy_name, group_name );
-
-	list = purple_find_buddies( session->acc, buddy_name );
-	if ( g_slist_length( list ) == 1 ) {
-		purple_debug_info( MXIT_PLUGIN_ID, "mxit_add_buddy (scenario 1) (list:%i)\n", g_slist_length( list ) );
-		/*
-		 * we only send an invite to MXit when the user is not already inside our
-		 * blist.  this is done because purple does an add_buddy() call when
-		 * you accept an invite.  so in that case the user is already
-		 * in our blist and ready to be chatted to.
-		 */
-
-		if ( buddy_name[0] == '#' ) {
-			gchar *tmp = (gchar*) purple_base64_decode( buddy_name + 1, NULL );
-			if ( tmp ) {
-				mxit_send_invite( session, tmp, FALSE, buddy_alias, group_name, message );
-				g_free( tmp );
-			}
-		}
-		else
-			mxit_send_invite( session, buddy_name, TRUE, buddy_alias, group_name, message );
-	}
-	else {
-		purple_debug_info( MXIT_PLUGIN_ID, "mxit_add_buddy (scenario 2) (list:%i)\n", g_slist_length( list ) );
-		/*
-		 * we already have the buddy in our list, so we will only update
-		 * his information here and not send another invite message
-		 */
-
-		/* find the correct buddy */
-		for ( i = 0; i < g_slist_length( list ); i++ ) {
-			mxbuddy = g_slist_nth_data( list, i );
-
-			if ( purple_buddy_get_protocol_data( mxbuddy ) != NULL ) {
-				/* this is our REAL MXit buddy! */
-
-				/* now update the buddy's alias */
-				purple_blist_alias_buddy( mxbuddy, buddy_alias );
-
-				/* now update the buddy's group */
-//				mxbuddy = mxit_update_buddy_group( session, mxbuddy, group );
-
-				/* send the update to the MXit server */
-				mxit_send_update_contact( session, purple_buddy_get_name( mxbuddy ), purple_buddy_get_alias( mxbuddy ), group_name );
-			}
-		}
-	}
-
-	/*
-	 * we remove the buddy here from the buddy list because the MXit server
-	 * will send us a proper contact update packet if this succeeds.  now
-	 * we do not have to worry about error handling in case of adding an
-	 * invalid contact.  so the user will still see the contact as offline
-	 * until he eventually accepts the invite.
-	 */
-	purple_blist_remove_buddy( buddy );
-
-	g_slist_free( list );
-}
-
-
-/*------------------------------------------------------------------------
- * The user has removed a buddy from the list.
- *
- *  @param gc		The connection object
- *  @param buddy	The buddy being removed
- *  @param group	The group the buddy was in
- */
-void mxit_remove_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group )
-{
-	struct MXitSession*	session	= purple_connection_get_protocol_data( gc );
-	const gchar *		buddy_name = purple_buddy_get_name( buddy );
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_remove_buddy '%s'\n", buddy_name );
-
-	mxit_send_remove( session, buddy_name );
-}
-
-
-/*------------------------------------------------------------------------
- * The user changed the buddy's alias.
- *
- *  @param gc		The connection object
- *  @param who		The username of the buddy
- *  @param alias	The new alias
- */
-void mxit_buddy_alias( PurpleConnection* gc, const char* who, const char* alias )
-{
-	struct MXitSession*	session	= purple_connection_get_protocol_data( gc );
-	PurpleBuddy*		buddy	= NULL;
-	PurpleGroup*		group	= NULL;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_buddy_alias '%s' to '%s\n", who, alias );
-
-	/* find the buddy */
-	buddy = purple_find_buddy( session->acc, who );
-	if ( !buddy ) {
-		purple_debug_warning( MXIT_PLUGIN_ID, "mxit_buddy_alias: unable to find the buddy '%s'\n", who );
-		return;
-	}
-
-	/* find buddy group */
-	group = purple_buddy_get_group( buddy );
-	if ( !group ) {
-		purple_debug_warning( MXIT_PLUGIN_ID, "mxit_buddy_alias: unable to find the group for buddy '%s'\n", who );
-		return;
-	}
-
-	mxit_send_update_contact( session, who, alias, purple_group_get_name( group ) );
-}
-
-
-/*------------------------------------------------------------------------
- * The user changed the group for a single buddy.
- *
- *  @param gc			The connection object
- *  @param who			The username of the buddy
- *  @param old_group	The old group's name
- *  @param new_group	The new group's name
- */
-void mxit_buddy_group( PurpleConnection* gc, const char* who, const char* old_group, const char* new_group )
-{
-	struct MXitSession*	session	= purple_connection_get_protocol_data( gc );
-	PurpleBuddy*		buddy	= NULL;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_buddy_group from '%s' to '%s'\n", old_group, new_group );
-
-	/* find the buddy */
-	buddy = purple_find_buddy( session->acc, who );
-	if ( !buddy ) {
-		purple_debug_warning( MXIT_PLUGIN_ID, "mxit_buddy_group: unable to find the buddy '%s'\n", who );
-		return;
-	}
-
-	mxit_send_update_contact( session, who, purple_buddy_get_alias( buddy ), new_group );
-}
-
-
-/*------------------------------------------------------------------------
- * The user has selected to rename a group, so update all contacts in that
- * group.
- *
- *  @param gc				The connection object
- *  @param old_name			The old group name
- *  @param group			The updated group object
- *  @param moved_buddies	The buddies affected by the rename
- */
-void mxit_rename_group( PurpleConnection* gc, const char* old_name, PurpleGroup* group, GList* moved_buddies )
-{
-	struct MXitSession*	session	= purple_connection_get_protocol_data( gc );
-	PurpleBuddy*		buddy	= NULL;
-	GList*				item	= NULL;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_rename_group from '%s' to '%s\n", old_name, purple_group_get_name( group ) );
-
-	//  TODO: Might be more efficient to use the "rename group" command (cmd=29).
-
-	/* loop through all the contacts in the group and send updates */
-	item = moved_buddies;
-	while ( item ) {
-		buddy = item->data;
-		mxit_send_update_contact( session, purple_buddy_get_name( buddy ), purple_buddy_get_alias( buddy ), purple_group_get_name( group ) );
-		item = g_list_next( item );
-	}
-}
-
--- a/libpurple/protocols/mxit/roster.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *			-- user roster management (mxit contacts) --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * 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		_MXIT_ROSTER_H_
-#define		_MXIT_ROSTER_H_
-
-
-/* MXit contact presence states */
-#define		MXIT_PRESENCE_OFFLINE		0x00
-#define		MXIT_PRESENCE_ONLINE		0x01
-#define		MXIT_PRESENCE_AWAY			0x02
-#define		MXIT_PRESENCE_AVAILABLE		0x03
-#define		MXIT_PRESENCE_DND			0x04
-
-
-/* MXit contact types */
-#define		MXIT_TYPE_MXIT				0x00
-#define		MXIT_TYPE_JABBER			0x01
-#define		MXIT_TYPE_MSN				0x02
-#define		MXIT_TYPE_YAHOO				0x03
-#define		MXIT_TYPE_ICQ				0x04
-#define		MXIT_TYPE_AIM				0x05
-#define		MXIT_TYPE_QQ				0x06
-#define		MXIT_TYPE_WV				0x07
-#define		MXIT_TYPE_BOT				0x08
-#define		MXIT_TYPE_CHATROOM			0x09
-#define		MXIT_TYPE_SMS				0x0A
-#define		MXIT_TYPE_GROUP				0x0B
-#define		MXIT_TYPE_GALLERY			0x0C
-#define		MXIT_TYPE_INFO				0x0D
-#define		MXIT_TYPE_MULTIMX			0x0E
-#define		MXIT_TYPE_HYBRID			0x0F
-
-
-/* MXit contact moods */
-#define		MXIT_MOOD_NONE				0x00
-#define		MXIT_MOOD_ANGRY				0x01
-#define		MXIT_MOOD_EXCITED			0x02
-#define		MXIT_MOOD_GRUMPY			0x03
-#define		MXIT_MOOD_HAPPY				0x04
-#define		MXIT_MOOD_INLOVE			0x05
-#define		MXIT_MOOD_INVINCIBLE		0x06
-#define		MXIT_MOOD_SAD				0x07
-#define		MXIT_MOOD_HOT				0x08
-#define		MXIT_MOOD_SICK				0x09
-#define		MXIT_MOOD_SLEEPY			0x0A
-#define		MXIT_MOOD_BORED				0x0B
-#define		MXIT_MOOD_COLD				0x0C
-#define		MXIT_MOOD_CONFUSED			0x0D
-#define		MXIT_MOOD_HUNGRY			0x0E
-#define		MXIT_MOOD_STRESSED			0x0F
-
-
-/* MXit contact flags */
-//#define		MXIT_CFLAG_HIDDEN			0x02		/* (DEPRECATED) */
-#define		MXIT_CFLAG_GATEWAY			0x04
-#define		MXIT_CFLAG_FOCUS_SEND_BLANK	0x20000
-
-
-/* MXit presence flags */
-#define		MXIT_PFLAG_VOICE			0x1
-#define		MXIT_PFLAG_VIDEO			0x2
-#define		MXIT_PFLAG_TYPING			0x4
-
-
-/* Subscription types */
-#define		MXIT_SUBTYPE_BOTH			'B'
-#define		MXIT_SUBTYPE_PENDING		'P'
-#define		MXIT_SUBTYPE_ASK			'A'
-#define		MXIT_SUBTYPE_REJECTED		'R'
-#define		MXIT_SUBTYPE_DELETED		'D'
-#define		MXIT_SUBTYPE_NONE			'N'
-
-
-/* client protocol constants */
-#define		MXIT_CP_MAX_JID_LEN			64
-#define		MXIT_CP_MAX_GROUP_LEN		32
-#define		MXIT_CP_MAX_ALIAS_LEN		100
-
-#define		MXIT_DEFAULT_GROUP			"MXit"
-
-
-/*
- * a MXit contact
- */
-struct contact {
-	char		username[MXIT_CP_MAX_JID_LEN+1];	/* unique contact name (with domain) */
-	char		alias[MXIT_CP_MAX_ALIAS_LEN+1];		/* contact alias (what will be seen) */
-	char		groupname[MXIT_CP_MAX_GROUP_LEN+1];	/* contact group name */
-
-	short		type;								/* contact type */
-	short		mood;								/* contact current mood */
-	int			flags;								/* contact flags */
-	short		presence;							/* presence state */
-	int			capabilities;						/* contact capabilities */
-	short		subtype;							/* subscription type */
-
-	char*		msg;								/* invite/rejection message */
-
-	char		customMood[16];						/* custom mood */
-	char*		statusMsg;							/* status message */
-	char*		avatarId;							/* avatarId */
-
-	/* invites only */
-	void*		profile;							/* user's profile (if available) */
-	int			imgid;								/* avatar image id in the imgstore */
-};
-
-/* Presence / Status */
-GList* mxit_status_types( PurpleAccount* account );
-int mxit_convert_presence( const char* id );
-const char* mxit_convert_presence_to_name( short no );
-const char* mxit_convert_subtype_to_name( short subtype );
-
-/* Moods */
-int mxit_convert_mood( const char* id );
-const char* mxit_convert_mood_to_name( short id );
-
-/* MXit Protocol callbacks */
-void mxit_update_contact( struct MXitSession* session, struct contact* contact );
-void mxit_update_buddy_presence( struct MXitSession* session, const char* username, short presence, short mood, const char* customMood, const char* statusMsg, int flags );
-void mxit_update_buddy_avatar( struct MXitSession* session, const char* username, const char* avatarId );
-void mxit_new_subscription( struct MXitSession* session, struct contact* contact );
-void mxit_update_blist( struct MXitSession* session );
-gboolean is_mxit_chatroom_contact( struct MXitSession* session, const char* username );
-struct contact* get_mxit_invite_contact( struct MXitSession* session, const char* username );
-
-/* libPurple callbacks */
-void mxit_add_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group, const char* message );
-void mxit_remove_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group );
-void mxit_buddy_alias( PurpleConnection* gc, const char* who, const char* alias );
-void mxit_buddy_group( PurpleConnection* gc, const char* who, const char* old_group, const char* new_group );
-void mxit_rename_group( PurpleConnection* gc, const char* old_name, PurpleGroup* group, GList* moved_buddies );
-PurpleMood* mxit_get_moods( PurpleAccount *account );
-
-
-#endif		/* _MXIT_ROSTER_H_ */
--- a/libpurple/protocols/mxit/splashscreen.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,222 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *						-- splash screens --
- *
- *				Andrew Victor	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "debug.h"
-#include "imgstore.h"
-#include "request.h"
-
-#include "protocol.h"
-#include "mxit.h"
-#include "splashscreen.h"
-
-
-/*------------------------------------------------------------------------
- * Return the ID of the current splash-screen.
- *
- *  @param session		The MXit session object
- *  @return				The ID of the splash-screen (or NULL if no splash-screen)
- */
-const char* splash_current(struct MXitSession* session)
-{
-	const char* splashId = purple_account_get_string(session->acc, MXIT_CONFIG_SPLASHID, NULL);
-
-	if ((splashId != NULL) && (*splashId != '\0')) {
-		purple_debug_info(MXIT_PLUGIN_ID, "Current splashId: '%s'\n", splashId);
-		return splashId;
-	}
-	else
-		return NULL;
-}
-
-
-/*------------------------------------------------------------------------
- * Indicate if splash-screen popups are enabled.
- *
- *  @param session		The MXit session object
- *  @return				TRUE if the popup is enabled.
- */
-gboolean splash_popup_enabled(struct MXitSession* session)
-{
-	return purple_account_get_bool(session->acc, MXIT_CONFIG_SPLASHPOPUP, DEFAULT_SPLASH_POPUP);
-}
-
-
-/*------------------------------------------------------------------------
- * Return if the current splash-screen is clickable.
- *
- *  @param session		The MXit session object
- *  @return				TRUE or FALSE
- */
-static gboolean splash_clickable(struct MXitSession* session)
-{
-	return purple_account_get_bool(session->acc, MXIT_CONFIG_SPLASHCLICK, FALSE);
-}
-
-
-/*------------------------------------------------------------------------
- * Remove the stored splash-screen (if it exists).
- *
- *  @param session		The MXit session object
- */
-void splash_remove(struct MXitSession* session)
-{
-	const char* splashId = NULL;
-	char* filename;
-
-	/* Get current splash ID */
-	splashId = splash_current(session);
-
-	if (splashId != NULL) {
-		purple_debug_info(MXIT_PLUGIN_ID, "Removing splashId: '%s'\n", splashId);
-
-		/* Delete stored splash image */
-		filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "mxit" G_DIR_SEPARATOR_S "%s.png", purple_user_dir(), purple_escape_filename(splashId));
-		g_unlink(filename);
-		g_free(filename);
-
-		/* Clear current splash ID from settings */
-		purple_account_set_string(session->acc, MXIT_CONFIG_SPLASHID, "");
-		purple_account_set_bool(session->acc, MXIT_CONFIG_SPLASHCLICK, FALSE);
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Save a new splash-screen for later display.
- *
- *  @param session		The MXit session object
- *  @param splashID		The ID of the splash-screen
- *  @param data			Splash-screen image data (PNG format)
- *  @param datalen		Splash-screen image data size
- */
-void splash_update(struct MXitSession* session, const char* splashId, const char* data, unsigned int datalen, gboolean clickable)
-{
-	char* dir;
-	char* filename;
-
-	/* Remove the current splash-screen */
-	splash_remove(session);
-
-	/* Save the new splash image */
-	dir = g_strdup_printf("%s" G_DIR_SEPARATOR_S "mxit", purple_user_dir());
-	purple_build_dir(dir, S_IRUSR | S_IWUSR | S_IXUSR);		/* ensure directory exists */
-
-	filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s.png", dir, purple_escape_filename(splashId));
-	if (purple_util_write_data_to_file_absolute(filename, data, datalen)) {
-		/* Store new splash-screen ID to settings */
-		purple_account_set_string(session->acc, MXIT_CONFIG_SPLASHID, splashId);
-		purple_account_set_bool(session->acc, MXIT_CONFIG_SPLASHCLICK, clickable );
-	}
-
-	g_free(dir);
-	g_free(filename);
-}
-
-
-/*------------------------------------------------------------------------
- * The user has clicked OK on the Splash request form.
- *
- *  @param gc			The connection object
- *  @param fields		The list of fields in the accepted form
- */
-static void splash_click_ok(PurpleConnection* gc, PurpleRequestFields* fields)
-{
-	struct MXitSession*	session	= purple_connection_get_protocol_data(gc);
-	const char* splashId;
-
-	/* Get current splash ID */
-	splashId = splash_current(session);
-	if (splashId == NULL)		/* no splash-screen */
-		return;
-
-	/* if is clickable, then send click event */
-	if (splash_clickable(session))
-		mxit_send_splashclick(session, splashId);
-}
-
-
-/*------------------------------------------------------------------------
- * Display the current splash-screen.
- *
- *  @param session		The MXit session object
- */
-void splash_display(struct MXitSession* session)
-{
-	const char* splashId = NULL;
-	char* filename;
-	gchar* imgdata;
-	gsize imglen;
-	int imgid = -1;
-
-	/* Get current splash ID */
-	splashId = splash_current(session);
-	if (splashId == NULL)		/* no splash-screen */
-		return;
-
-	purple_debug_info(MXIT_PLUGIN_ID, "Display Splash: '%s'\n", splashId);
-
-	/* Load splash-screen image from file */
-	filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "mxit" G_DIR_SEPARATOR_S "%s.png", purple_user_dir(), purple_escape_filename(splashId));
-	if (g_file_get_contents(filename, &imgdata, &imglen, NULL)) {
-		char buf[128];
-
-		/* Add splash-image to imagestore */
-		imgid = purple_imgstore_add_with_id(g_memdup(imgdata, imglen), imglen, NULL);
-
-		/* Generate and display message */
-		g_snprintf(buf, sizeof(buf), "<img id=\"%d\">", imgid);
-
-		/* Open a request-type popup to display the image */
-		{
-			PurpleRequestFields*		fields;
-			PurpleRequestFieldGroup*	group;
-			PurpleRequestField*			field;
-
-			fields = purple_request_fields_new();
-			group = purple_request_field_group_new(NULL);
-			purple_request_fields_add_group(fields, group);
-
-			field = purple_request_field_image_new("splash", "", imgdata, imglen);		/* add splash image */
-			purple_request_field_group_add_field(group, field);
-
-			if (splash_clickable(session)) {
-				purple_request_fields(session->con, _("MXit Advertising"), NULL, NULL, fields,
-					_("More Information"), G_CALLBACK(splash_click_ok), _("Close"), NULL, session->acc, NULL, NULL, session->con);
-			}
-			else {
-				purple_request_fields(session->con, _("MXit Advertising"), NULL, NULL, fields,
-					_("Continue"), G_CALLBACK(splash_click_ok), _("Close"), NULL, session->acc, NULL, NULL, session->con);
-			}
-		}
-
-		/* Release reference to image */
-		purple_imgstore_unref_by_id(imgid);
-
-		g_free(imgdata);
-	}
-
-	g_free(filename);
-}
--- a/libpurple/protocols/mxit/splashscreen.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *						-- splash screens --
- *
- *				Andrew Victor	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * 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		_MXIT_SPLASHSCREEN_H_
-#define		_MXIT_SPLASHSCREEN_H_
-
-#define		HANDLE_SPLASH1		"plas1.png"
-#define		HANDLE_SPLASH2		"plas2.png"
-
-#define		DEFAULT_SPLASH_POPUP	FALSE		/* disabled by default */
-
-/*
- * Return the ID of the current splash-screen.
- */
-const char* splash_current(struct MXitSession* session);
-
-/*
- * Indicate if splash-screen popups are enabled.
- */
-gboolean splash_popup_enabled(struct MXitSession* session);
-
-/*
- * Save a new splash-screen.
- */
-void splash_update(struct MXitSession* session, const char* splashId, const char* data, unsigned int datalen, gboolean clickable);
-
-/*
- * Remove the stored splash-screen (if it exists).
- */
-void splash_remove(struct MXitSession* session);
-
-/*
- * Display the current splash-screen.
- */
-void splash_display(struct MXitSession* session);
-
-#endif		/* _MXIT_SPLASHSCREEN_H_ */
--- a/libpurple/protocols/myspace/Makefile.am	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-EXTRA_DIST = \
-	Makefile.mingw
-
-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
-
-MSIMSOURCES = markup.c \
-	  markup.h \
-	  message.c \
-	  message.h \
-	  myspace.c \
-	  myspace.h \
-	  persist.h \
-	  session.c \
-	  session.h \
-	  user.c \
-	  user.h \
-	  zap.c \
-	  zap.h
-
-AM_CFLAGS = $(st)
-
-libmyspace_la_LDFLAGS = -module -avoid-version
-
-if STATIC_MYSPACE
-
-st = -DPURPLE_STATIC_PRPL
-noinst_LTLIBRARIES    = libmyspace.la
-libmyspace_la_SOURCES = $(MSIMSOURCES)
-libmyspace_la_CFLAGS  = $(AM_CFLAGS)
-
-else
-
-st =
-pkg_LTLIBRARIES       = libmyspace.la
-libmyspace_la_SOURCES = $(MSIMSOURCES)
-libmyspace_la_LIBADD  = $(GLIB_LIBS)
-
-endif
-
-AM_CPPFLAGS = \
-	-I$(top_srcdir)/libpurple \
-	-I$(top_builddir)/libpurple \
-	$(GLIB_CFLAGS) \
-	$(DEBUG_CFLAGS)
--- a/libpurple/protocols/myspace/Makefile.mingw	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-#
-# Makefile.mingw
-#
-# Description: Makefile for win32 (mingw) version of libmyspace
-#
-
-PIDGIN_TREE_TOP := ../../..
-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
-
-TARGET = libmyspace
-TYPE = PLUGIN
-
-# Static or Plugin...
-ifeq ($(TYPE),STATIC)
-  DEFINES += -DSTATIC
-  DLL_INSTALL_DIR =	$(PURPLE_INSTALL_DIR)
-else
-ifeq ($(TYPE),PLUGIN)
-  DLL_INSTALL_DIR =	$(PURPLE_INSTALL_PLUGINS_DIR)
-endif
-endif
-
-##
-## INCLUDE PATHS
-##
-INCLUDE_PATHS +=	-I. \
-			-I$(GTK_TOP)/include \
-			-I$(GTK_TOP)/include/glib-2.0 \
-			-I$(GTK_TOP)/lib/glib-2.0/include \
-			-I$(PURPLE_TOP) \
-			-I$(PURPLE_TOP)/win32 \
-			-I$(PIDGIN_TREE_TOP)
-
-LIB_PATHS =		-L$(GTK_TOP)/lib \
-			-L$(PURPLE_TOP)
-
-##
-##  SOURCES, OBJECTS
-##
-C_SRC =			myspace.c message.c zap.c session.c markup.c user.c
-
-OBJECTS = $(C_SRC:%.c=%.o)
-
-##
-## LIBRARIES
-##
-LIBS =	\
-			-lglib-2.0 \
-			-lws2_32 \
-			-lintl \
-			-lpurple
-
-include $(PIDGIN_COMMON_RULES)
-
-##
-## TARGET DEFINITIONS
-##
-.PHONY: all install clean
-
-all: $(TARGET).dll
-
-install: all $(DLL_INSTALL_DIR)
-	cp $(TARGET).dll $(DLL_INSTALL_DIR)
-
-$(OBJECTS): $(PURPLE_CONFIG_H)
-
-##
-## BUILD DLL
-##
-$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-	$(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
-
-##
-## CLEAN RULES
-##
-
-clean:
-	rm -f $(OBJECTS)
-	rm -f $(TARGET).dll
-
-include $(PIDGIN_COMMON_TARGETS)
--- a/libpurple/protocols/myspace/README	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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
--- a/libpurple/protocols/myspace/markup.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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;
-}
--- a/libpurple/protocols/myspace/markup.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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 */
--- a/libpurple/protocols/myspace/message.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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);
-}
--- a/libpurple/protocols/myspace/message.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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 */
--- a/libpurple/protocols/myspace/myspace.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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);
--- a/libpurple/protocols/myspace/myspace.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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 */
--- a/libpurple/protocols/myspace/persist.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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 */
--- a/libpurple/protocols/myspace/session.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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);
-}
--- a/libpurple/protocols/myspace/session.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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 */
--- a/libpurple/protocols/myspace/user.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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);
-}
--- a/libpurple/protocols/myspace/user.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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 */
--- a/libpurple/protocols/myspace/zap.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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;
-}
--- a/libpurple/protocols/myspace/zap.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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 */
--- a/libpurple/protocols/yahoo/Makefile.am	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-EXTRA_DIST = \
-	Makefile.mingw
-
-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
-
-YAHOOSOURCES = \
-	libymsg.c \
-	libymsg.h \
-	util.c \
-	yahoochat.h \
-	yahoochat.c \
-	yahoo_aliases.c \
-	yahoo_aliases.h \
-	yahoo_doodle.h \
-	yahoo_doodle.c \
-	yahoo_filexfer.h \
-	yahoo_filexfer.c \
-	yahoo_friend.h \
-	yahoo_friend.c \
-	yahoo_packet.h \
-	yahoo_packet.c \
-	yahoo_picture.c \
-	yahoo_picture.h \
-	yahoo_profile.c \
-	ycht.c \
-	ycht.h
-
-AM_CFLAGS = $(st)
-
-libyahoo_la_LDFLAGS = -module -avoid-version
-libyahoojp_la_LDFLAGS = -module -avoid-version
-
-if STATIC_YAHOO
-
-st = -DPURPLE_STATIC_PRPL
-noinst_LTLIBRARIES  = libymsg.la
-libymsg_la_SOURCES = $(YAHOOSOURCES) libyahoo.c libyahoojp.c
-libymsg_la_CFLAGS  = $(AM_CFLAGS)
-
-else
-
-st =
-pkg_LTLIBRARIES     = libymsg.la libyahoo.la libyahoojp.la
-
-libymsg_la_SOURCES = $(YAHOOSOURCES)
-libymsg_la_LIBADD  = $(GLIB_LIBS)
-
-libyahoo_la_SOURCES = libyahoo.c
-libyahoo_la_LIBADD = libymsg.la
-
-libyahoojp_la_SOURCES = libyahoojp.c
-libyahoojp_la_LIBADD = libymsg.la
-
-endif
-
-AM_CPPFLAGS = \
-	-I$(top_srcdir)/libpurple \
-	-I$(top_builddir)/libpurple \
-	$(GLIB_CFLAGS) \
-	$(DEBUG_CFLAGS)
--- a/libpurple/protocols/yahoo/Makefile.mingw	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-#
-# Makefile.mingw
-#
-# Description: Makefile for win32 (mingw) version of libyahoo
-#
-
-PIDGIN_TREE_TOP := ../../..
-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
-
-TARGET = libymsg
-YAHOO_TARGET = libyahoo
-YAHOOJP_TARGET = libyahoojp
-TYPE = PLUGIN
-
-# Static or Plugin...
-ifeq ($(TYPE),STATIC)
-  DEFINES += -DSTATIC
-  DLL_INSTALL_DIR =	$(PURPLE_INSTALL_DIR)
-else
-ifeq ($(TYPE),PLUGIN)
-  DLL_INSTALL_DIR =	$(PURPLE_INSTALL_PLUGINS_DIR)
-endif
-endif
-
-##
-## INCLUDE PATHS
-##
-INCLUDE_PATHS +=	-I. \
-			-I$(GTK_TOP)/include \
-			-I$(GTK_TOP)/include/glib-2.0 \
-			-I$(GTK_TOP)/lib/glib-2.0/include \
-			-I$(PURPLE_TOP) \
-			-I$(PURPLE_TOP)/win32 \
-			-I$(PIDGIN_TREE_TOP)
-
-LIB_PATHS +=		-L. \
-			-L$(GTK_TOP)/lib \
-			-L$(PURPLE_TOP)
-
-##
-##  SOURCES, OBJECTS
-##
-C_SRC =			util.c \
-			libymsg.c \
-			yahoochat.c \
-			yahoo_aliases.c \
-			yahoo_doodle.c \
-			yahoo_filexfer.c \
-			yahoo_friend.c \
-			yahoo_packet.c \
-			yahoo_picture.c \
-			yahoo_profile.c \
-			ycht.c
-
-OBJECTS = $(C_SRC:%.c=%.o)
-
-YAHOO_C_SRC = libyahoo.c
-YAHOO_OBJECTS = $(YAHOO_C_SRC:%.c=%.o)
-
-YAHOOJP_C_SRC = libyahoojp.c
-YAHOOJP_OBJECTS = $(YAHOOJP_C_SRC:%.c=%.o)
-
-##
-## LIBRARIES
-##
-LIBS =			\
-			-lglib-2.0 \
-			-lws2_32 \
-			-lintl \
-			-lpurple
-
-include $(PIDGIN_COMMON_RULES)
-
-##
-## TARGET DEFINITIONS
-##
-
-.PHONY: all install clean
-
-all: $(TARGET).dll $(YAHOO_TARGET).dll $(YAHOOJP_TARGET).dll
-
-install: all $(DLL_INSTALL_DIR)
-	cp $(YAHOO_TARGET).dll $(YAHOOJP_TARGET).dll $(DLL_INSTALL_DIR)
-	cp $(TARGET).dll $(PURPLE_INSTALL_DIR)
-
-$(OBJECTS): $(PURPLE_CONFIG_H)
-
-$(TARGET).dll.a $(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-	$(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--output-def,$(TARGET).def,--out-implib,$(TARGET).dll.a -o $(TARGET).dll
-
-$(YAHOO_TARGET).dll: $(TARGET).dll.a $(YAHOO_OBJECTS)
-	$(CC) -shared $(YAHOO_OBJECTS) $(LIB_PATHS) $(LIBS) -lymsg $(DLL_LD_FLAGS) -o $(YAHOO_TARGET).dll
-
-$(YAHOOJP_TARGET).dll: $(TARGET).dll.a $(YAHOOJP_OBJECTS)
-	$(CC) -shared $(YAHOOJP_OBJECTS) $(LIB_PATHS) $(LIBS) -lymsg $(DLL_LD_FLAGS) -o $(YAHOOJP_TARGET).dll
-
-##
-## CLEAN RULES
-##
-clean:
-	rm -f $(OBJECTS) $(TARGET).dll $(TARGET).dll.a
-	rm -f $(YAHOO_OBJECTS) $(YAHOO_TARGET).dll
-	rm -f $(YAHOOJP_OBJECTS) $(YAHOOJP_TARGET).dll
-
-include $(PIDGIN_COMMON_TARGETS)
--- a/libpurple/protocols/yahoo/libyahoo.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,348 +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
-};
-
-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_PLUGIN(yahoo, init_plugin, info);
--- a/libpurple/protocols/yahoo/libyahoojp.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +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 "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);
-
--- a/libpurple/protocols/yahoo/libymsg.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5513 +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);
-			g_free(m);
-			g_free(im->fed_from);
-			g_free(im);
-			continue;
-		}
-
-		m2 = yahoo_codes_to_html(m);
-		g_free(m);
-
-		serv_got_im(gc, im->fed_from, m2, 0, im->time);
-		g_free(m2);
-
-		/* Official clients don't share buddy images with federated buddies */
-		if (im->fed == YAHOO_FEDERATION_NONE) {
-			if ((f = yahoo_friend_find(gc, im->from)) && im->buddy_icon == 2) {
-				if (yahoo_friend_get_buddy_icon_need_request(f)) {
-					yahoo_send_picture_request(gc, im->from);
-					yahoo_friend_set_buddy_icon_need_request(f, FALSE);
-				}
-			}
-		}
-
-		g_free(im->fed_from);
-		g_free(im);
-	}
-
-	g_slist_free(list);
-}
-
-static void yahoo_process_sysmessage(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	GSList *l = pkt->hash;
-	char *prim, *me = NULL, *msg = NULL;
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-
-		if (pair->key == 5) {
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				me = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_sysmessage "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-		}
-		if (pair->key == 14) {
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				msg = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_sysmessage "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-		}
-
-		l = l->next;
-	}
-
-	if (!msg || !g_utf8_validate(msg, -1, NULL))
-		return;
-
-	prim = g_strdup_printf(_("Yahoo! system message for %s:"),
-	                       me?me:purple_connection_get_display_name(gc));
-	purple_notify_info(NULL, NULL, prim, msg);
-	g_free(prim);
-}
-
-struct yahoo_add_request {
-	PurpleConnection *gc;
-	char *id;
-	char *who;
-	YahooFederation fed;
-};
-
-static void
-yahoo_buddy_add_authorize_cb(gpointer data)
-{
-	struct yahoo_add_request *add_req = data;
-	struct yahoo_packet *pkt;
-	YahooData *yd = add_req->gc->proto_data;
-	const char *who = add_req->who;
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	if (add_req->fed) {
-		who += 4;
-		yahoo_packet_hash(pkt, "ssiii",
-						  1, add_req->id,
-						  5, who,
-						  241, add_req->fed,
-						  13, 1,
-						  334, 0);
-	}
-	else {
-		yahoo_packet_hash(pkt, "ssii",
-						  1, add_req->id,
-						  5, who,
-						  13, 1,
-						  334, 0);
-	}
-
-	yahoo_packet_send_and_free(pkt, yd);
-
-	g_free(add_req->id);
-	g_free(add_req->who);
-	g_free(add_req);
-}
-
-static void
-yahoo_buddy_add_deny_cb(struct yahoo_add_request *add_req, const char *msg)
-{
-	YahooData *yd = add_req->gc->proto_data;
-	struct yahoo_packet *pkt;
-	char *encoded_msg = NULL;
-	const char *who = add_req->who;
-
-	if (msg && *msg)
-		encoded_msg = yahoo_string_encode(add_req->gc, msg, NULL);
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15,
-			YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	if (add_req->fed) {
-		who += 4; /* Skip fed identifier (msn|ocs|ibm)/' */
-		yahoo_packet_hash(pkt, "ssiiiis",
-						  1, add_req->id,
-						  5, who,
-						  241, add_req->fed,
-						  13, 2,
-						  334, 0,
-						  97, 1,
-						  14, encoded_msg ? encoded_msg : "");
-	}
-	else {
-		yahoo_packet_hash(pkt, "ssiiis",
-						  1, add_req->id,
-						  5, who,
-						  13, 2,
-						  334, 0,
-						  97, 1,
-						  14, encoded_msg ? encoded_msg : "");
-	}
-
-
-	yahoo_packet_send_and_free(pkt, yd);
-
-	g_free(encoded_msg);
-
-	g_free(add_req->id);
-	g_free(add_req->who);
-	g_free(add_req);
-}
-
-static void
-yahoo_buddy_add_deny_noreason_cb(struct yahoo_add_request *add_req, const char*msg)
-{
-	yahoo_buddy_add_deny_cb(add_req, NULL);
-}
-
-static void
-yahoo_buddy_add_deny_reason_cb(gpointer data) {
-	struct yahoo_add_request *add_req = data;
-	purple_request_input(add_req->gc, NULL, _("Authorization denied message:"),
-			NULL, _("No reason given."), TRUE, FALSE, NULL,
-			_("OK"), G_CALLBACK(yahoo_buddy_add_deny_cb),
-			_("Cancel"), G_CALLBACK(yahoo_buddy_add_deny_noreason_cb),
-			purple_connection_get_account(add_req->gc), add_req->who, NULL,
-			add_req);
-}
-
-static void yahoo_buddy_denied_our_add(PurpleConnection *gc, const char *who, const char *reason)
-{
-	char *notify_msg;
-	YahooData *yd = gc->proto_data;
-
-	if (who == NULL)
-		return;
-
-	if (reason != NULL) {
-		char *msg2 = yahoo_string_decode(gc, reason, FALSE);
-		notify_msg = g_strdup_printf(_("%s has (retroactively) denied your request to add them to your list for the following reason: %s."), who, msg2);
-		g_free(msg2);
-	} else
-		notify_msg = g_strdup_printf(_("%s has (retroactively) denied your request to add them to your list."), who);
-
-	purple_notify_info(gc, NULL, _("Add buddy rejected"), notify_msg);
-	g_free(notify_msg);
-
-	g_hash_table_remove(yd->friends, who);
-	purple_prpl_got_user_status(purple_connection_get_account(gc), who, "offline", NULL); /* FIXME: make this set not on list status instead */
-	/* TODO: Shouldn't we remove the buddy from our local list? */
-}
-
-static void yahoo_buddy_auth_req_15(PurpleConnection *gc, struct yahoo_packet *pkt) {
-	PurpleAccount *account;
-	GSList *l = pkt->hash;
-	const char *msg = NULL;
-
-	account = purple_connection_get_account(gc);
-
-	/* Buddy authorized/declined our addition */
-	if (pkt->status == 1) {
-		char *temp = NULL;
-		char *who = NULL;
-		int response = 0;
-		YahooFederation fed = YAHOO_FEDERATION_NONE;
-
-		while (l) {
-			struct yahoo_pair *pair = l->data;
-
-			switch (pair->key) {
-			case 4:
-				if (g_utf8_validate(pair->value, -1, NULL)) {
-					temp = pair->value;
-				} else {
-					purple_debug_warning("yahoo", "yahoo_buddy_auth_req_15 "
-							"got non-UTF-8 string for key %d\n", pair->key);
-				}
-				break;
-			case 13:
-				response = strtol(pair->value, NULL, 10);
-				break;
-			case 14:
-				msg = pair->value;
-				break;
-			case 241:
-				fed = strtol(pair->value, NULL, 10);
-				break;
-			}
-			l = l->next;
-		}
-
-		switch (fed) {
-			case YAHOO_FEDERATION_MSN:
-				who = g_strconcat("msn/", temp, NULL);
-				break;
-			case YAHOO_FEDERATION_OCS:
-				who = g_strconcat("ocs/", temp, NULL);
-				break;
-			case YAHOO_FEDERATION_IBM:
-				who = g_strconcat("ibm/", temp, NULL);
-				break;
-			case YAHOO_FEDERATION_NONE:
-			default:
-				who = g_strdup(temp);
-				break;
-		}
-
-		if (response == 1) /* Authorized */
-			purple_debug_info("yahoo", "Received authorization from buddy '%s'.\n", who ? who : "(Unknown Buddy)");
-		else if (response == 2) { /* Declined */
-			purple_debug_info("yahoo", "Received authorization decline from buddy '%s'.\n", who ? who : "(Unknown Buddy)");
-			yahoo_buddy_denied_our_add(gc, who, msg);
-		} else
-			purple_debug_error("yahoo", "Received unknown authorization response of %d from buddy '%s'.\n", response, who ? who : "(Unknown Buddy)");
-	g_free(who);
-	}
-	/* Buddy requested authorization to add us. */
-	else if (pkt->status == 3) {
-		struct yahoo_add_request *add_req;
-		const char *firstname = NULL, *lastname = NULL;
-		char *temp = NULL;
-
-		add_req = g_new0(struct yahoo_add_request, 1);
-		add_req->gc = gc;
-		add_req->fed = YAHOO_FEDERATION_NONE;
-
-		while (l) {
-			struct yahoo_pair *pair = l->data;
-
-			switch (pair->key) {
-			case 4:
-				if (g_utf8_validate(pair->value, -1, NULL)) {
-					temp = pair->value;
-				} else {
-					purple_debug_warning("yahoo", "yahoo_buddy_auth_req_15 "
-							"got non-UTF-8 string for key %d\n", pair->key);
-				}
-				break;
-			case 5:
-				if (g_utf8_validate(pair->value, -1, NULL)) {
-					add_req->id = g_strdup(pair->value);
-				} else {
-					purple_debug_warning("yahoo", "yahoo_buddy_auth_req_15 "
-							"got non-UTF-8 string for key %d\n", pair->key);
-				}
-				break;
-			case 14:
-				msg = pair->value;
-				break;
-			case 216:
-				if (g_utf8_validate(pair->value, -1, NULL)) {
-					firstname = pair->value;
-				} else {
-					purple_debug_warning("yahoo", "yahoo_buddy_auth_req_15 "
-							"got non-UTF-8 string for key %d\n", pair->key);
-				}
-				break;
-			case 241:
-				add_req->fed = strtol(pair->value, NULL, 10);
-				break;
-			case 254:
-				if (g_utf8_validate(pair->value, -1, NULL)) {
-					lastname = pair->value;
-				} else {
-					purple_debug_warning("yahoo", "yahoo_buddy_auth_req_15 "
-							"got non-UTF-8 string for key %d\n", pair->key);
-				}
-				break;
-
-			}
-			l = l->next;
-		}
-		switch (add_req->fed) {
-			case YAHOO_FEDERATION_MSN:
-				add_req->who = g_strconcat("msn/", temp, NULL);
-				break;
-			case YAHOO_FEDERATION_OCS:
-				add_req->who = g_strconcat("ocs/", temp, NULL);
-				break;
-			case YAHOO_FEDERATION_IBM:
-				add_req->who = g_strconcat("ibm/", temp, NULL);
-				break;
-			case YAHOO_FEDERATION_NONE:
-			default:
-				add_req->who = g_strdup(temp);
-				break;
-		}
-
-		if (add_req->id && add_req->who) {
-			char *alias = NULL, *dec_msg = NULL;
-
-			if (!purple_privacy_check(account, add_req->who))
-			{
-				purple_debug_misc("yahoo", "Auth. request from %s dropped and automatically denied due to privacy settings!\n",
-						  add_req->who);
-				yahoo_buddy_add_deny_cb(add_req, NULL);
-				return;
-			}
-
-			if (msg)
-				dec_msg = yahoo_string_decode(gc, msg, FALSE);
-
-			if (firstname && lastname)
-				alias = g_strdup_printf("%s %s", firstname, lastname);
-			else if (firstname)
-				alias = g_strdup(firstname);
-			else if (lastname)
-				alias = g_strdup(lastname);
-
-			/* DONE! this is almost exactly the same as what MSN does,
-			 * this should probably be moved to the core.
-			 */
-			 purple_account_request_authorization(account, add_req->who, add_req->id,
-					alias, dec_msg,
-					purple_find_buddy(account, add_req->who) != NULL,
-					yahoo_buddy_add_authorize_cb,
-					yahoo_buddy_add_deny_reason_cb,
-					add_req);
-			g_free(alias);
-			g_free(dec_msg);
-		} else {
-			g_free(add_req->id);
-			g_free(add_req->who);
-			g_free(add_req);
-		}
-	} else {
-		purple_debug_error("yahoo", "Received authorization of unknown status (%d).\n", pkt->status);
-	}
-}
-
-/* I don't think this happens anymore in Version 15 */
-static void yahoo_buddy_added_us(PurpleConnection *gc, struct yahoo_packet *pkt) {
-	PurpleAccount *account;
-	struct yahoo_add_request *add_req;
-	char *msg = NULL;
-	GSList *l = pkt->hash;
-
-	account = purple_connection_get_account(gc);
-
-	add_req = g_new0(struct yahoo_add_request, 1);
-	add_req->gc = gc;
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 1:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				add_req->id = g_strdup(pair->value);
-			} else {
-					purple_debug_warning("yahoo", "yahoo_buddy_added_us "
-							"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 3:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				add_req->who = g_strdup(pair->value);
-			} else {
-					purple_debug_warning("yahoo", "yahoo_buddy_added_us "
-							"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 15: /* time, for when they add us and we're offline */
-			break;
-		case 14:
-			msg = pair->value;
-			break;
-		}
-		l = l->next;
-	}
-
-	if (add_req->id && add_req->who) {
-		char *dec_msg = NULL;
-
-		if (!purple_privacy_check(account, add_req->who)) {
-			purple_debug_misc("yahoo", "Auth. request from %s dropped and automatically denied due to privacy settings!\n",
-					  add_req->who);
-			yahoo_buddy_add_deny_cb(add_req, NULL);
-			return;
-		}
-
-		if (msg)
-			dec_msg = yahoo_string_decode(gc, msg, FALSE);
-
-		/* DONE! this is almost exactly the same as what MSN does,
-		 * this should probably be moved to the core.
-		 */
-		 purple_account_request_authorization(account, add_req->who, add_req->id,
-				NULL, dec_msg,
-				purple_find_buddy(account,add_req->who) != NULL,
-						yahoo_buddy_add_authorize_cb,
-						yahoo_buddy_add_deny_reason_cb, add_req);
-		g_free(dec_msg);
-	} else {
-		g_free(add_req->id);
-		g_free(add_req->who);
-		g_free(add_req);
-	}
-}
-
-/* I have no idea if this every gets called in version 15 */
-static void yahoo_buddy_denied_our_add_old(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	char *who = NULL;
-	char *msg = NULL;
-	GSList *l = pkt->hash;
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 3:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				who = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_buddy_denied_our_add_old "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 14:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				msg = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_buddy_denied_our_add_old "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		}
-		l = l->next;
-	}
-
-	yahoo_buddy_denied_our_add(gc, who, msg);
-}
-
-static void yahoo_process_contact(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	switch (pkt->status) {
-	case 1:
-		yahoo_process_status(gc, pkt);
-		return;
-	case 3:
-		yahoo_buddy_added_us(gc, pkt);
-		break;
-	case 7:
-		yahoo_buddy_denied_our_add_old(gc, pkt);
-		break;
-	default:
-		break;
-	}
-}
-
-#define OUT_CHARSET "utf-8"
-
-static char *yahoo_decode(const char *text)
-{
-	char *converted = NULL;
-	char *n, *new;
-	const char *end, *p;
-	int i, k;
-
-	n = new = g_malloc(strlen (text) + 1);
-	end = text + strlen(text);
-
-	for (p = text; p < end; p++, n++) {
-		if (*p == '\\') {
-			if (p[1] >= '0' && p[1] <= '7') {
-				p += 1;
-				for (i = 0, k = 0; k < 3; k += 1) {
-					char c = p[k];
-					if (c < '0' || c > '7') break;
-					i *= 8;
-					i += c - '0';
-				}
-				*n = i;
-				p += k - 1;
-			} else { /* bug 959248 */
-				/* If we see a \ not followed by an octal number,
-				 * it means that it is actually a \\ with one \
-				 * already eaten by some unknown function.
-				 * This is arguably broken.
-				 *
-				 * I think wing is wrong here, there is no function
-				 * called that I see that could have done it. I guess
-				 * it is just really sending single \'s. That's yahoo
-				 * for you.
-				 */
-				*n = *p;
-			}
-		}
-		else
-			*n = *p;
-	}
-
-	*n = '\0';
-
-	if (strstr(text, "\033$B"))
-		converted = g_convert(new, n - new, OUT_CHARSET, "iso-2022-jp", NULL, NULL, NULL);
-	if (!converted)
-		converted = g_convert(new, n - new, OUT_CHARSET, "iso-8859-1", NULL, NULL, NULL);
-	g_free(new);
-
-	return converted;
-}
-
-static void yahoo_process_mail(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	PurpleAccount *account = purple_connection_get_account(gc);
-	YahooData *yd = gc->proto_data;
-	const char *who = NULL;
-	const char *email = NULL;
-	const char *subj = NULL;
-	const char *yahoo_mail_url = (yd->jp? YAHOOJP_MAIL_URL: YAHOO_MAIL_URL);
-	int count = 0;
-	GSList *l = pkt->hash;
-
-	if (!purple_account_get_check_mail(account))
-		return;
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-		if (pair->key == 9)
-			count = strtol(pair->value, NULL, 10);
-		else if (pair->key == 43) {
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				who = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_mail "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-		} else if (pair->key == 42) {
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				email = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_mail "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-		} else if (pair->key == 18) {
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				subj = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_mail "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-		}
-		l = l->next;
-	}
-
-	if (who && subj && email && *email) {
-		char *dec_who = yahoo_decode(who);
-		char *dec_subj = yahoo_decode(subj);
-		char *from = g_strdup_printf("%s (%s)", dec_who, email);
-
-		purple_notify_email(gc, dec_subj, from, purple_account_get_username(account),
-						  yahoo_mail_url, NULL, NULL);
-
-		g_free(dec_who);
-		g_free(dec_subj);
-		g_free(from);
-	} else if (count > 0) {
-		const char *tos[2] = { purple_account_get_username(account) };
-		const char *urls[2] = { yahoo_mail_url };
-
-		purple_notify_emails(gc, count, FALSE, NULL, NULL, tos, urls,
-						   NULL, NULL);
-	}
-}
-
-/* We use this structure once while we authenticate */
-struct yahoo_auth_data
-{
-	PurpleConnection *gc;
-	char *seed;
-};
-
-/* This is the y64 alphabet... it's like base64, but has a . and a _ */
-static const char base64digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._";
-
-/* This is taken from Sylpheed by Hiroyuki Yamamoto. We have our own tobase64 function
- * in util.c, but it is different from the one yahoo uses */
-static void to_y64(char *out, const unsigned char *in, gsize inlen)
-     /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
-{
-	for (; inlen >= 3; inlen -= 3)
-		{
-			*out++ = base64digits[in[0] >> 2];
-			*out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
-			*out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
-			*out++ = base64digits[in[2] & 0x3f];
-			in += 3;
-		}
-	if (inlen > 0)
-		{
-			unsigned char fragment;
-
-			*out++ = base64digits[in[0] >> 2];
-			fragment = (in[0] << 4) & 0x30;
-			if (inlen > 1)
-				fragment |= in[1] >> 4;
-			*out++ = base64digits[fragment];
-			*out++ = (inlen < 2) ? '-' : base64digits[(in[1] << 2) & 0x3c];
-			*out++ = '-';
-		}
-	*out = '\0';
-}
-
-static void yahoo_auth16_stage3(PurpleConnection *gc, const char *crypt)
-{
-	YahooData *yd = gc->proto_data;
-	PurpleAccount *account = purple_connection_get_account(gc);
-	const char *name = purple_normalize(account, purple_account_get_username(account));
-	PurpleCipher *md5_cipher;
-	PurpleCipherContext *md5_ctx;
-	guchar md5_digest[16];
-	gchar base64_string[25];
-	struct yahoo_packet *pkt;
-
-	purple_debug_info("yahoo","Authentication: In yahoo_auth16_stage3\n");
-
-	g_return_if_fail(crypt != NULL);
-
-	md5_cipher = purple_ciphers_find_cipher("md5");
-	md5_ctx = purple_cipher_context_new(md5_cipher, NULL);
-	purple_cipher_context_append(md5_ctx, (guchar *)crypt, strlen(crypt));
-	purple_cipher_context_digest(md5_ctx, sizeof(md5_digest), md5_digest, NULL);
-
-	to_y64(base64_string, md5_digest, 16);
-
-	purple_debug_info("yahoo", "yahoo status: %d\n", yd->current_status);
-	pkt = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, yd->current_status, yd->session_id);
-
-	if(yd->cookie_b) { /* send B cookie if we have it */
-		yahoo_packet_hash(pkt, "ssssssssss",
-					1, name,
-					0, name,
-					277, yd->cookie_y,
-					278, yd->cookie_t,
-					307, base64_string,
-					244, yd->jp ? YAHOOJP_CLIENT_VERSION_ID : YAHOO_CLIENT_VERSION_ID,
-					2, name,
-					2, "1",
-					59, yd->cookie_b,
-					98, purple_account_get_string(account, "room_list_locale", yd->jp ? "jp" : "us"),
-					135, yd->jp ? YAHOOJP_CLIENT_VERSION : YAHOO_CLIENT_VERSION);
-	} else { /* don't try to send an empty B cookie - the server will be mad */
-		yahoo_packet_hash(pkt, "sssssssss",
-					1, name,
-					0, name,
-					277, yd->cookie_y,
-					278, yd->cookie_t,
-					307, base64_string,
-					244, yd->jp ? YAHOOJP_CLIENT_VERSION_ID : YAHOO_CLIENT_VERSION_ID,
-					2, name,
-					2, "1",
-					98, purple_account_get_string(account, "room_list_locale", yd->jp ? "jp" : "us"),
-					135, yd->jp ? YAHOOJP_CLIENT_VERSION : YAHOO_CLIENT_VERSION);
-	}
-
-	if (yd->picture_checksum)
-		yahoo_packet_hash_int(pkt, 192, yd->picture_checksum);
-	yahoo_packet_send_and_free(pkt, yd);
-
-	purple_cipher_context_destroy(md5_ctx);
-}
-
-static gchar *yahoo_auth16_get_cookie_b(gchar *headers)
-{
-	gchar **splits = g_strsplit(headers, "\r\n", -1);
-	gchar *tmp = NULL, *tmp2 = NULL, *sem = NULL;
-	int elements = g_strv_length(splits), i;
-
-	if(elements > 1) {
-		for(i = 0; i < elements; i++) {
-			if(g_ascii_strncasecmp(splits[i], "Set-Cookie: B=", 14) == 0) {
-				tmp = &splits[i][14];
-				sem = strchr(tmp, ';');
-
-				if (sem != NULL) {
-					tmp2 = g_strndup(tmp, sem - tmp);
-					purple_debug_info("yahoo", "Got needed part of B cookie: %s\n",
-							tmp2 ? tmp2 : "(null)");
-					break;
-				}
-			}
-		}
-	}
-
-	g_strfreev(splits);
-	return tmp2;
-}
-
-static void yahoo_auth16_stage2(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *ret_data, size_t len, const gchar *error_message)
-{
-	struct yahoo_auth_data *auth_data = user_data;
-	PurpleConnection *gc = auth_data->gc;
-	YahooData *yd = purple_connection_get_protocol_data(gc);
-
-	purple_debug_info("yahoo","Authentication: In yahoo_auth16_stage2\n");
-
-	yd->url_datas = g_slist_remove(yd->url_datas, url_data);
-
-	if (error_message != NULL) {
-		purple_debug_error("yahoo", "Login Failed, unable to retrieve stage 2 url: %s\n", error_message);
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message);
-		g_free(auth_data->seed);
-		g_free(auth_data);
-		return;
-	}
-	else if (len > 0 && ret_data && *ret_data) {
-		gchar **splits = g_strsplit(ret_data, "\r\n\r\n", -1), **split_data = NULL;
-		int totalelements = 0;
-		int response_no = -1;
-		char *crumb = NULL;
-		char *crypt = NULL;
-
-		if(g_strv_length(splits) > 1) {
-			yd->cookie_b = yahoo_auth16_get_cookie_b(splits[0]);
-			split_data = g_strsplit(splits[1], "\r\n", -1);
-			totalelements = g_strv_length(split_data);
-		}
-
-		if (totalelements >= 4) {
-			int i;
-
-			for(i = 0; i < totalelements; i++) {
-				/* I'm not exactly a fan of the magic numbers, but it's obvious,
-				 * so no sense in wasting a bajillion vars or calls to strlen */
-
-				if(g_ascii_isdigit(split_data[i][0])) {
-					/* if the current line and the next line both start with numbers,
-					 * the current line is the length of the body, so skip.  If not,
-					 * then the current line is the response code from the login process. */
-					if(!g_ascii_isdigit(split_data[i + 1][0])) {
-						response_no = strtol(split_data[i], NULL, 10);
-						purple_debug_info("yahoo", "Got auth16 stage 2 response code: %d\n",
-								response_no);
-					}
-				} else if(strncmp(split_data[i], "crumb=", 6) == 0) {
-					crumb = g_strdup(&split_data[i][6]);
-
-					if(purple_debug_is_unsafe())
-						purple_debug_info("yahoo", "Got crumb: %s\n", crumb);
-
-				} else if(strncmp(split_data[i], "Y=", 2) == 0) {
-					yd->cookie_y = g_strdup(&split_data[i][2]);
-
-					if(purple_debug_is_unsafe())
-						purple_debug_info("yahoo", "Got Y cookie: %s\n", yd->cookie_y);
-
-				} else if(strncmp(split_data[i], "T=", 2) == 0) {
-					yd->cookie_t = g_strdup(&split_data[i][2]);
-
-					if(purple_debug_is_unsafe())
-						purple_debug_info("yahoo", "Got T cookie: %s\n", yd->cookie_t);
-				}
-			}
-		}
-
-		g_strfreev(splits);
-		g_strfreev(split_data);
-
-		if (crumb == NULL)
-			response_no = -1;
-
-		if(response_no != 0) {
-			/* Some error in the login process */
-			PurpleConnectionError error;
-			char *error_reason = NULL;
-
-			switch(response_no) {
-				case -1:
-					/* Some error in the received stream */
-					error_reason = g_strdup(_("Received invalid data"));
-					error = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-					break;
-				case 100:
-					/* Unknown error */
-					error_reason = g_strdup(_("Unknown error"));
-					error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
-					break;
-				default:
-					/* if we have everything we need, why not try to login irrespective of response */
-					if((crumb != NULL) && (yd->cookie_y != NULL) && (yd->cookie_t != NULL)) {
-#if 0
-						try_login_on_error = TRUE;
-#endif
-						break;
-					}
-					error_reason = g_strdup(_("Unknown error"));
-					error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
-					break;
-			}
-			if(error_reason) {
-				purple_debug_error("yahoo", "Authentication error: %s. "
-				                   "Code %d\n", error_reason, response_no);
-				purple_connection_error_reason(gc, error, error_reason);
-				g_free(error_reason);
-				g_free(auth_data->seed);
-				g_free(auth_data);
-				return;
-			}
-		}
-
-		crypt = g_strconcat(crumb, auth_data->seed, NULL);
-		yahoo_auth16_stage3(gc, crypt);
-		g_free(crypt);
-		g_free(crumb);
-	}
-	g_free(auth_data->seed);
-	g_free(auth_data);
-}
-
-static void yahoo_auth16_stage1_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *ret_data, size_t len, const gchar *error_message)
-{
-	struct yahoo_auth_data *auth_data = user_data;
-	PurpleConnection *gc = auth_data->gc;
-	YahooData *yd = purple_connection_get_protocol_data(gc);
-
-	purple_debug_info("yahoo","Authentication: In yahoo_auth16_stage1_cb\n");
-
-	yd->url_datas = g_slist_remove(yd->url_datas, url_data);
-
-	if (error_message != NULL) {
-		purple_debug_error("yahoo", "Login Failed, unable to retrieve login url: %s\n", error_message);
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message);
-		g_free(auth_data->seed);
-		g_free(auth_data);
-		return;
-	}
-	else if (len > 0 && ret_data && *ret_data) {
-		PurpleAccount *account = purple_connection_get_account(gc);
-		gchar **split_data = g_strsplit(ret_data, "\r\n", -1);
-		int totalelements = 0;
-		int response_no = -1;
-		char *token = NULL;
-
-		totalelements = g_strv_length(split_data);
-
-		if(totalelements == 1) { /* Received an error code */
-			response_no = strtol(split_data[0], NULL, 10);
-		} else if(totalelements == 2 || totalelements == 3 ) { /* received valid data */
-			response_no = strtol(split_data[0], NULL, 10);
-			token = g_strdup(split_data[1] + strlen("ymsgr="));
-		} else { /* It looks like a transparent proxy has returned a document we don't want */
-			response_no = -1;
-		}
-
-		g_strfreev(split_data);
-
-		if(response_no != 0) {
-			/* Some error in the login process */
-			PurpleConnectionError error;
-			char *error_reason;
-
-			switch(response_no) {
-				case -1:
-					/* Some error in the received stream */
-					error_reason = g_strdup(_("Received invalid data"));
-					error = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-					break;
-				case 1212:
-					/* Password incorrect */
-					/* Set password to NULL. Avoids account locking. Brings dialog to enter password if clicked on Re-enable account */
-					if (!purple_account_get_remember_password(account))
-						purple_account_set_password(account, NULL);
-					error_reason = g_strdup(_("Incorrect password"));
-					error = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
-					break;
-				case 1213:
-					/* security lock from too many failed login attempts */
-					error_reason = g_strdup(_("Account locked: Too many failed login "
-								"attempts.  Logging into the Yahoo! website may fix this."));
-					error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
-					break;
-				case 1235:
-					/* the username does not exist */
-					error_reason = g_strdup(_("Username does not exist"));
-					error = PURPLE_CONNECTION_ERROR_INVALID_USERNAME;
-					break;
-				case 1214:
-					/* indicates a lock of some description */
-					error_reason = g_strdup(_("Account locked: Unknown reason.  Logging "
-								"into the Yahoo! website may fix this."));
-					error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
-					break;
-				case 1236:
-					/* indicates a lock due to logging in too frequently */
-					error_reason = g_strdup(_("Account locked: You have been logging in too "
-								"frequently.  Wait a few minutes before trying to connect "
-								"again.  Logging into the Yahoo! website may help."));
-					error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
-					break;
-				case 100:
-					/* username or password missing */
-					error_reason = g_strdup(_("Username or password missing"));
-					error = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
-					break;
-				default:
-					/* Unknown error! */
-					error_reason = g_strdup_printf(_("Unknown error (%d)"), response_no);
-					error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
-					break;
-			}
-			purple_debug_error("yahoo", "Authentication error: %s. Code %d\n",
-			                   error_reason, response_no);
-			purple_connection_error_reason(gc, error, error_reason);
-			g_free(error_reason);
-			g_free(auth_data->seed);
-			g_free(auth_data);
-			g_free(token);
-		}
-		else {
-			/* OK to login, correct information provided */
-			PurpleUtilFetchUrlData *url_data = NULL;
-			char *url = NULL;
-			gboolean yahoojp = yahoo_is_japan(account);
-			gboolean proxy_ssl = purple_account_get_bool(account, "proxy_ssl", FALSE);
-
-			url = g_strdup_printf(yahoojp ? YAHOOJP_LOGIN_URL : YAHOO_LOGIN_URL, token);
-			url_data = purple_util_fetch_url_request_len_with_account(
-					proxy_ssl ? account : NULL, url, TRUE, YAHOO_CLIENT_USERAGENT,
-					TRUE, NULL, TRUE, -1, yahoo_auth16_stage2, auth_data);
-			if (url_data)
-				yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
-			g_free(url);
-			g_free(token);
-		}
-	}
-}
-
-static void yahoo_auth16_stage1(PurpleConnection *gc, const char *seed)
-{
-	YahooData *yd = purple_connection_get_protocol_data(gc);
-	PurpleAccount *account = purple_connection_get_account(gc);
-	PurpleUtilFetchUrlData *url_data = NULL;
-	struct yahoo_auth_data *auth_data = NULL;
-	char *url = NULL;
-	char *encoded_username;
-	char *encoded_password;
-	gboolean yahoojp = yahoo_is_japan(account);
-	gboolean proxy_ssl = purple_account_get_bool(account, "proxy_ssl", FALSE);
-
-	purple_debug_info("yahoo", "Authentication: In yahoo_auth16_stage1\n");
-
-	if(!purple_ssl_is_supported()) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("SSL support unavailable"));
-		return;
-	}
-
-	auth_data = g_new0(struct yahoo_auth_data, 1);
-	auth_data->gc = gc;
-	auth_data->seed = g_strdup(seed);
-
-	encoded_username = g_strdup(purple_url_encode(purple_account_get_username(purple_connection_get_account(gc))));
-	encoded_password = g_strdup(purple_url_encode(purple_connection_get_password(gc)));
-	url = g_strdup_printf(yahoojp ? YAHOOJP_TOKEN_URL : YAHOO_TOKEN_URL,
-			encoded_username, encoded_password, purple_url_encode(seed));
-	g_free(encoded_password);
-	g_free(encoded_username);
-
-	url_data = purple_util_fetch_url_request_len_with_account(
-			proxy_ssl ? account : NULL, url, TRUE,
-			YAHOO_CLIENT_USERAGENT, TRUE, NULL, FALSE, -1,
-			yahoo_auth16_stage1_cb, auth_data);
-	if (url_data)
-		yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
-
-	g_free(url);
-}
-
-static void yahoo_process_auth(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	char *seed = NULL;
-	GSList *l = pkt->hash;
-	int m = 0;
-	gchar *buf;
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-		/* (pair->key == 1) -> sn */
-		if (pair->key == 94) {
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				seed = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_auth "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-		} else if (pair->key == 13) {
-			m = atoi(pair->value);
-		}
-		l = l->next;
-	}
-
-	if (seed) {
-		switch (m) {
-		case 0:
-			/* used to be for really old auth routine, dont support now */
-		case 1:
-		case 2: /* Yahoo ver 16 authentication */
-			yahoo_auth16_stage1(gc, seed);
-			break;
-		default:
-			{
-				GHashTable *ui_info = purple_core_get_ui_info();
-
-				buf = g_strdup_printf(_("The Yahoo server has requested the use of an unrecognized "
-							"authentication method.  You will probably not be able "
-							"to successfully sign on to Yahoo.  Check %s for updates."),
-							((ui_info && g_hash_table_lookup(ui_info, "website")) ? (char *)g_hash_table_lookup(ui_info, "website") : PURPLE_WEBSITE));
-				purple_notify_error(gc, "", _("Failed Yahoo! Authentication"),
-							buf);
-				g_free(buf);
-				yahoo_auth16_stage1(gc, seed); /* Can't hurt to try it anyway. */
-				break;
-			}
-		}
-	}
-}
-
-static void ignore_buddy(PurpleBuddy *buddy) {
-	PurpleGroup *group;
-	PurpleAccount *account;
-	gchar *name;
-
-	if (!buddy)
-		return;
-
-	group = purple_buddy_get_group(buddy);
-	name = g_strdup(purple_buddy_get_name(buddy));
-	account = purple_buddy_get_account(buddy);
-
-	purple_debug_info("yahoo", "blist: Removing '%s' from buddy list.\n", name);
-	purple_account_remove_buddy(account, buddy, group);
-	purple_blist_remove_buddy(buddy);
-
-	serv_add_deny(purple_account_get_connection(account), name);
-
-	g_free(name);
-}
-
-static void keep_buddy(PurpleBuddy *b)
-{
-	purple_privacy_deny_remove(purple_buddy_get_account(b),
-			purple_buddy_get_name(b), 1);
-}
-
-static void yahoo_process_ignore(PurpleConnection *gc, struct yahoo_packet *pkt) {
-	PurpleBuddy *b;
-	GSList *l;
-	gchar *who = NULL;
-	gchar buf[BUF_LONG];
-	gboolean ignore = TRUE;
-	gint status = 0;
-
-	for (l = pkt->hash; l; l = l->next) {
-		struct yahoo_pair *pair = l->data;
-		switch (pair->key) {
-		case 0:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				who = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_ignore "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		/* 1 -> me */
-		case 13:
-			/* 1 == ignore, 2 == unignore */
-			ignore = (strtol(pair->value, NULL, 10) == 1);
-			break;
-		case 66:
-			status = strtol(pair->value, NULL, 10);
-			break;
-		default:
-			break;
-		}
-	}
-
-	/*
-	 * status
-	 * 0  - ok
-	 * 2  - already in ignore list, could not add
-	 * 3  - not in ignore list, could not delete
-	 * 12 - is a buddy, could not add (and possibly also a not-in-ignore list condition?)
-	 */
-	switch (status) {
-		case 12:
-			purple_debug_info("yahoo", "Server reported \"is a buddy\" for %s while %s",
-							  who, (ignore ? "ignoring" : "unignoring"));
-
-			if (ignore) {
-				b = purple_find_buddy(gc->account, who);
-				g_snprintf(buf, sizeof(buf), _("You have tried to ignore %s, but the "
-											   "user is on your buddy list.  Clicking \"Yes\" "
-											   "will remove and ignore the buddy."), who);
-				purple_request_yes_no(gc, NULL, _("Ignore buddy?"), buf, 0,
-									  gc->account, who, NULL,
-									  b,
-									  G_CALLBACK(ignore_buddy),
-									  G_CALLBACK(keep_buddy));
-				break;
-			}
-		case 2:
-			purple_debug_info("yahoo", "Server reported that %s is already in the ignore list.\n",
-							  who);
-			break;
-		case 3:
-			purple_debug_info("yahoo", "Server reported that %s is not in the ignore list; could not delete\n",
-							  who);
-		case 0:
-		default:
-			break;
-	}
-}
-
-static void yahoo_process_authresp(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-#ifdef TRY_WEBMESSENGER_LOGIN
-	YahooData *yd = gc->proto_data;
-#endif /* TRY_WEBMESSENGER_LOGIN */
-	GSList *l = pkt->hash;
-	int err = 0;
-	char *msg;
-	char *url = NULL;
-	char *fullmsg;
-	PurpleAccount *account = gc->account;
-	PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-
-		if (pair->key == 66)
-			err = strtol(pair->value, NULL, 10);
-		else if (pair->key == 20) {
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				url = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_authresp "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-		}
-
-		l = l->next;
-	}
-
-	switch (err) {
-	case 0:
-		msg = g_strdup(_("Unknown error"));
-		reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-		break;
-	case 3:
-		msg = g_strdup(_("Username does not exist"));
-		reason = PURPLE_CONNECTION_ERROR_INVALID_USERNAME;
-		break;
-	case 13:
-#ifdef TRY_WEBMESSENGER_LOGIN
-		if (!yd->wm) {
-			PurpleUtilFetchUrlData *url_data;
-			yd->wm = TRUE;
-			if (yd->fd >= 0)
-				close(yd->fd);
-			if (gc->inpa)
-				purple_input_remove(gc->inpa);
-			url_data = purple_util_fetch_url(WEBMESSENGER_URL, TRUE,
-					"Purple/" VERSION, FALSE, yahoo_login_page_cb, gc);
-			if (url_data != NULL)
-				yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
-			return;
-		}
-#endif /* TRY_WEBMESSENGER_LOGIN */
-		if (!purple_account_get_remember_password(account))
-			purple_account_set_password(account, NULL);
-
-		msg = g_strdup(_("Invalid username or password"));
-		reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
-		break;
-	case 14:
-		msg = g_strdup(_("Your account has been locked due to too many failed login attempts."
-					"  Please try logging into the Yahoo! website."));
-		reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
-		break;
-	case 52:
-		/* See #9660. As much as we know, reconnecting shouldn't hurt */
-		purple_debug_info("yahoo", "Got error 52, Set to autoreconnect\n");
-		msg = g_strdup(_("Unknown error 52.  Reconnecting should fix this."));
-		reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-		break;
-	case 1013:
-		msg = g_strdup(_("Error 1013: The username you have entered is invalid."
-					"  The most common cause of this error is entering your email"
-					" address instead of your Yahoo! ID."));
-		reason = PURPLE_CONNECTION_ERROR_INVALID_USERNAME;
-		break;
-	default:
-		msg = g_strdup_printf(_("Unknown error number %d. Logging into the Yahoo! website may fix this."), err);
-	}
-
-	if (url)
-		fullmsg = g_strdup_printf("%s\n%s", msg, url);
-	else
-		fullmsg = g_strdup(msg);
-
-	purple_connection_error_reason(gc, reason, fullmsg);
-	g_free(msg);
-	g_free(fullmsg);
-}
-
-static void yahoo_process_addbuddy(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	int err = 0;
-	char *who = NULL;
-	char *temp = NULL;
-	char *group = NULL;
-	char *decoded_group;
-	char *buf;
-	YahooFriend *f;
-	GSList *l = pkt->hash;
-	YahooData *yd = gc->proto_data;
-	YahooFederation fed = YAHOO_FEDERATION_NONE;
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 66:
-			err = strtol(pair->value, NULL, 10);
-			break;
-		case 7:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				temp = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_addbuddy "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 65:
-			group = pair->value;
-			break;
-		case 241:
-			fed = strtol(pair->value, NULL, 10);
-			break;
-		}
-
-		l = l->next;
-	}
-
-	if (!temp)
-		return;
-	if (!group)
-		group = "";
-
-	switch (fed) {
-		case YAHOO_FEDERATION_MSN:
-			who = g_strconcat("msn/", temp, NULL);
-			break;
-		case YAHOO_FEDERATION_OCS:
-			who = g_strconcat("ocs/", temp, NULL);
-			break;
-		case YAHOO_FEDERATION_IBM:
-			who = g_strconcat("ibm/", temp, NULL);
-			break;
-		case YAHOO_FEDERATION_NONE:
-		default:
-			who = g_strdup(temp);
-			break;
-	}
-
-	if (!err || (err == 2)) { /* 0 = ok, 2 = already on serv list */
-		f = yahoo_friend_find_or_new(gc, who);
-		yahoo_update_status(gc, who, f);
-		f->fed = fed;
-
-		if( !g_hash_table_lookup(yd->peers, who) ) {
-			/* we are not connected as client, so set friend to not connected */
-			if(fed)
-				yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_DO_NOT_CONNECT);
-			else	{
-				yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED);
-				f->p2p_packet_sent = 0;
-			}
-		}
-		else	/* we are already connected. set friend to YAHOO_P2PSTATUS_WE_ARE_CLIENT */
-			yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_WE_ARE_CLIENT);
-		g_free(who);
-		return;
-	}
-
-	decoded_group = yahoo_string_decode(gc, group, FALSE);
-	buf = g_strdup_printf(_("Unable to add buddy %s to group %s to the server list on account %s."),
-				who, decoded_group, purple_connection_get_display_name(gc));
-	if (!purple_conv_present_error(who, purple_connection_get_account(gc), buf))
-		purple_notify_error(gc, NULL, _("Unable to add buddy to server list"), buf);
-	g_free(buf);
-	g_free(decoded_group);
-	g_free(who);
-}
-
-/* write pkt to the source */
-static void yahoo_p2p_write_pkt(gint source, struct yahoo_packet *pkt)
-{
-	size_t pkt_len;
-	gssize written;
-	guchar *raw_packet;
-
-	/*build the raw packet and send it to the host*/
-	pkt_len = yahoo_packet_build(pkt, 0, 0, 0, &raw_packet);
-	written = write(source, raw_packet, pkt_len);
-	if (written < 0 || (gsize)written != pkt_len)
-		purple_debug_warning("yahoo","p2p: couldn't write to the source\n");
-	g_free(raw_packet);
-}
-
-static void yahoo_p2p_keepalive_cb(gpointer key, gpointer value, gpointer user_data)
-{
-	struct yahoo_p2p_data *p2p_data = value;
-	PurpleConnection *gc = user_data;
-	struct yahoo_packet *pkt_to_send;
-	PurpleAccount *account;
-	YahooData *yd = gc->proto_data;
-
-	account = purple_connection_get_account(gc);
-
-	pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash(pkt_to_send, "ssisi",
-		4, purple_normalize(account, purple_account_get_username(account)),
-		5, p2p_data->host_username,
-		241, 0,		/* Protocol identifier */
-		49, "PEERTOPEER",
-		13, 7);
-	yahoo_p2p_write_pkt(p2p_data->source, pkt_to_send);
-
-	yahoo_packet_free(pkt_to_send);
-}
-
-static gboolean yahoo_p2p_keepalive(gpointer data)
-{
-	PurpleConnection *gc = data;
-	YahooData *yd = gc->proto_data;
-
-	g_hash_table_foreach(yd->peers, yahoo_p2p_keepalive_cb, gc);
-
-	return TRUE;
-}
-
-/* destroy p2p_data associated with a peer and close p2p connection.
- * g_hash_table_remove() calls this function to destroy p2p_data associated with the peer,
- * call g_hash_table_remove() instead of this fucntion if peer has an entry in the table */
-static void yahoo_p2p_disconnect_destroy_data(gpointer data)
-{
-	struct yahoo_p2p_data *p2p_data;
-	YahooFriend *f;
-
-	if(!(p2p_data = data))
-		return ;
-
-	/* If friend, set him not connected */
-	f = yahoo_friend_find(p2p_data->gc, p2p_data->host_username);
-	if (f)
-		yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED);
-
-	if(p2p_data->source >= 0)
-		close(p2p_data->source);
-	if (p2p_data->input_event > 0)
-		purple_input_remove(p2p_data->input_event);
-	g_free(p2p_data->host_ip);
-	g_free(p2p_data->host_username);
-	g_free(p2p_data);
-}
-
-/* exchange of initial p2pfilexfer packets, service type YAHOO_SERVICE_P2PFILEXFER */
-static void yahoo_p2p_process_p2pfilexfer(gpointer data, gint source, struct yahoo_packet *pkt)
-{
-	struct yahoo_p2p_data *p2p_data;
-	char *who = NULL;
-	GSList *l = pkt->hash;
-	struct yahoo_packet *pkt_to_send;
-	PurpleAccount *account;
-	int val_13_to_send = 0;
-	YahooData *yd;
-	YahooFriend *f;
-
-	if(!(p2p_data = data))
-		return ;
-
-	yd = p2p_data->gc->proto_data;
-
-	/* lets see whats in the packet */
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 4:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				who = pair->value;
-				if(strncmp(who, p2p_data->host_username, strlen(p2p_data->host_username)) != 0) {
-					/* from whom are we receiving the packets ?? */
-					purple_debug_warning("yahoo","p2p: received data from wrong user\n");
-					return;
-				}
-			} else {
-				purple_debug_warning("yahoo", "yahoo_p2p_process_p2pfilexfer "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 13:
-			p2p_data->val_13 = strtol(pair->value, NULL, 10);	/* Value should be 5-7 */
-			break;
-		/* case 5, 49 look laters, no use right now */
-		}
-		l = l->next;
-	}
-
-	account = purple_connection_get_account(p2p_data->gc);
-
-	/* key_13: sort of a counter.
-	 * WHEN WE ARE CLIENT: yahoo server sends val_13 = 0, we send to peer val_13 = 1, receive back val_13 = 5,
-	 * we send val_13=6, receive val_13=7, we send val_13=7, HALT. Keep sending val_13 = 7 as keep alive.
-	 * WHEN WE ARE SERVER: we send val_13 = 0 to yahoo server, peer sends us val_13 = 1, we send val_13 = 5,
-	 * receive val_13 = 6, send val_13 = 7, receive val_13 = 7. HALT. Keep sending val_13 = 7 as keep alive. */
-
-	switch(p2p_data->val_13) {
-		case 1 : val_13_to_send = 5; break;
-		case 5 : val_13_to_send = 6; break;
-		case 6 : val_13_to_send = 7; break;
-		case 7 : if( g_hash_table_lookup(yd->peers, p2p_data->host_username) )
-				return;
-			 val_13_to_send = 7; break;
-		default: purple_debug_warning("yahoo","p2p:Unknown value for key 13\n");
-			 return;
-		}
-
-	/* Build the yahoo packet */
-	pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash(pkt_to_send, "ssisi",
-		4, purple_normalize(account, purple_account_get_username(account)),
-		5, p2p_data->host_username,
-		241, 0,		/* Protocol identifier */
-		49, "PEERTOPEER",
-		13, val_13_to_send);
-
-	/* build the raw packet and send it to the host */
-	yahoo_p2p_write_pkt(source, pkt_to_send);
-	yahoo_packet_free(pkt_to_send);
-
-	if( val_13_to_send == 7 )
-		if( !g_hash_table_lookup(yd->peers, p2p_data->host_username) ) {
-			g_hash_table_insert(yd->peers, g_strdup(p2p_data->host_username), p2p_data);
-			/* If the peer is a friend, set him connected */
-			f = yahoo_friend_find(p2p_data->gc, p2p_data->host_username);
-			if (f) {
-				if(p2p_data->connection_type == YAHOO_P2P_WE_ARE_SERVER) {
-					p2p_data->session_id = f->session_id;
-					yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_WE_ARE_SERVER);
-				}
-				else
-					yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_WE_ARE_CLIENT);
-			}
-		}
-}
-
-/* callback function associated with receiving of data, not considering receipt of multiple YMSG packets in a single TCP packet */
-static void yahoo_p2p_read_pkt_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
-	guchar buf[1024];	/* is it safe to assume a fixed array length of 1024 ?? */
-	int len;
-	int pos = 0;
-	int pktlen;
-	struct yahoo_packet *pkt;
-	guchar *start;
-	struct yahoo_p2p_data *p2p_data;
-	YahooData *yd;
-
-	if(!(p2p_data = data))
-		return ;
-	yd = p2p_data->gc->proto_data;
-
-	len = read(source, buf, sizeof(buf));
-	if ((len < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
-		return ; /* No Worries*/
-	else if (len <= 0)
-	{
-		purple_debug_warning("yahoo","p2p: Error in connection, or host disconnected\n");
-		/* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */
-		if( g_hash_table_lookup(yd->peers, p2p_data->host_username) )
-			g_hash_table_remove(yd->peers,p2p_data->host_username);
-		else
-			yahoo_p2p_disconnect_destroy_data(data);
-		return;
-	}
-
-	/* TODO: It looks like there's a bug here (and above) where an incorrect
-	 * assumtion is being made that the buffer will be added to when this
-	 * is next called, but that's not really the case! */
-	if(len < YAHOO_PACKET_HDRLEN)
-		return;
-
-	if(strncmp((char *)buf, "YMSG", 4) != 0) {
-		/* Not a YMSG packet */
-		purple_debug_warning("yahoo", "p2p: Got something other than YMSG packet\n");
-
-		start = (guchar *) g_strstr_len((char *) buf + 1, len - 1 ,"YMSG");
-		if (start == NULL) {
-			/* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */
-			if (g_hash_table_lookup(yd->peers, p2p_data->host_username))
-				g_hash_table_remove(yd->peers, p2p_data->host_username);
-			else
-				yahoo_p2p_disconnect_destroy_data(data);
-			return;
-		}
-		purple_debug_warning("yahoo","p2p: Got something other than YMSG packet\n");
-
-		len -= (start - buf);
-		g_memmove(buf, start, len);
-	}
-
-	pos += 4;	/* YMSG */
-	pos += 2;
-	pos += 2;
-
-	pktlen = yahoo_get16(buf + pos); pos += 2;
-	if (len < (YAHOO_PACKET_HDRLEN + pktlen)) {
-		purple_debug_error("yahoo", "p2p: packet length(%d) > buffer length(%d)\n",
-				pktlen, (len - pos)); 
-		/* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */
-		if (g_hash_table_lookup(yd->peers, p2p_data->host_username))
-			g_hash_table_remove(yd->peers, p2p_data->host_username);
-		else
-			yahoo_p2p_disconnect_destroy_data(data);
-		return;
-	} else
-		purple_debug_misc("yahoo", "p2p: %d bytes to read\n", pktlen);
-
-	pkt = yahoo_packet_new(0, 0, 0);
-	pkt->service = yahoo_get16(buf + pos); pos += 2;
-	pkt->status = yahoo_get32(buf + pos); pos += 4;
-	pkt->id = yahoo_get32(buf + pos); pos += 4;
-
-	purple_debug_misc("yahoo", "p2p: Yahoo Service: 0x%02x Status: %d\n",pkt->service, pkt->status);
-	yahoo_packet_read(pkt, buf + pos, pktlen);
-
-	/* packet processing */
-	switch(pkt->service) {
-		case YAHOO_SERVICE_P2PFILEXFER:
-			yahoo_p2p_process_p2pfilexfer(data, source, pkt);
-			break;
-		case YAHOO_SERVICE_MESSAGE:
-			yahoo_process_message(p2p_data->gc, pkt, YAHOO_PKT_TYPE_P2P);
-			break;
-		case YAHOO_SERVICE_NOTIFY:
-			yahoo_process_notify(p2p_data->gc, pkt, YAHOO_PKT_TYPE_P2P);
-			break;
-		default:
-			purple_debug_warning("yahoo","p2p: p2p service %d Unhandled\n",pkt->service);
-	}
-
-	yahoo_packet_free(pkt);
-}
-
-static void yahoo_p2p_server_send_connected_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
-	int acceptfd;
-	struct yahoo_p2p_data *p2p_data;
-	YahooData *yd;
-
-	if(!(p2p_data = data))
-		return ;
-	yd = p2p_data->gc->proto_data;
-
-	acceptfd = accept(source, NULL, 0);
-	if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
-		return;
-	else if(acceptfd == -1) {
-		purple_debug_warning("yahoo","yahoo_p2p_server_send_connected_cb: accept: %s\n", g_strerror(errno));
-		yahoo_p2p_disconnect_destroy_data(data);
-		return;
-	}
-
-	/* remove timeout */
-	if (yd->yahoo_p2p_server_timeout_handle) {
-		purple_timeout_remove(yd->yahoo_p2p_server_timeout_handle);
-		yd->yahoo_p2p_server_timeout_handle = 0;
-	}
-
-	/* remove watcher and close p2p server */
-	if (yd->yahoo_p2p_server_watcher) {
-		purple_input_remove(yd->yahoo_p2p_server_watcher);
-		yd->yahoo_p2p_server_watcher = 0;
-	}
-	if (yd->yahoo_local_p2p_server_fd >= 0) {
-		close(yd->yahoo_local_p2p_server_fd);
-		yd->yahoo_local_p2p_server_fd = -1;
-	}
-
-	/* Add an Input Read event to the file descriptor */
-	p2p_data->input_event = purple_input_add(acceptfd, PURPLE_INPUT_READ, yahoo_p2p_read_pkt_cb, data);
-	p2p_data->source = acceptfd;
-}
-
-static gboolean yahoo_cancel_p2p_server_listen_cb(gpointer data)
-{
-	struct yahoo_p2p_data *p2p_data;
-	YahooData *yd;
-
-	if(!(p2p_data = data))
-		return FALSE;
-
-	yd = p2p_data->gc->proto_data;
-
-	purple_debug_warning("yahoo","yahoo p2p server timeout, peer failed to connect\n");
-	yahoo_p2p_disconnect_destroy_data(data);
-	purple_input_remove(yd->yahoo_p2p_server_watcher);
-	yd->yahoo_p2p_server_watcher = 0;
-	close(yd->yahoo_local_p2p_server_fd);
-	yd->yahoo_local_p2p_server_fd = -1;
-	yd->yahoo_p2p_server_timeout_handle = 0;
-
-	return FALSE;
-}
-
-static void yahoo_p2p_server_listen_cb(int listenfd, gpointer data)
-{
-	struct yahoo_p2p_data *p2p_data;
-	YahooData *yd;
-
-	if(!(p2p_data = data))
-		return ;
-
-	yd = p2p_data->gc->proto_data;
-	yd->listen_data = NULL;
-
-	if(listenfd == -1) {
-		purple_debug_warning("yahoo","p2p: error starting p2p server\n");
-		yahoo_p2p_disconnect_destroy_data(data);
-		return;
-	}
-
-	/* Add an Input Read event to the file descriptor */
-	yd->yahoo_local_p2p_server_fd = listenfd;
-	yd->yahoo_p2p_server_watcher = purple_input_add(listenfd, PURPLE_INPUT_READ, yahoo_p2p_server_send_connected_cb,data);
-
-	/* add timeout */
-	yd->yahoo_p2p_server_timeout_handle = purple_timeout_add_seconds(YAHOO_P2P_SERVER_TIMEOUT, yahoo_cancel_p2p_server_listen_cb, data);
-}
-
-/* send p2p pkt containing our encoded ip, asking peer to connect to us */
-void yahoo_send_p2p_pkt(PurpleConnection *gc, const char *who, int val_13)
-{
-	const char *public_ip;
-	guint32 temp[4];
-	guint32 ip;
-	char temp_str[100];
-	gchar *base64_ip = NULL;
-	YahooFriend *f;
-	struct yahoo_packet *pkt;
-	PurpleAccount *account;
-	YahooData *yd = gc->proto_data;
-	struct yahoo_p2p_data *p2p_data;
-	const char *norm_username;
-
-	f = yahoo_friend_find(gc, who);
-	account = purple_connection_get_account(gc);
-
-	/* Do not send invitation if already listening for other connection */
-	if(yd->yahoo_local_p2p_server_fd >= 0)
-		return;
-
-	/* One shouldn't try to connect to self */
-	if( strcmp(purple_normalize(account, purple_account_get_username(account)), who) == 0)
-		return;
-
-	/* send packet to only those friends who arent p2p connected and to whom we havent already sent. Do not send if this condition doesn't hold good */
-	if( !( f && (yahoo_friend_get_p2p_status(f) == YAHOO_P2PSTATUS_NOT_CONNECTED) && (f->p2p_packet_sent == 0)) )
-		return;
-
-	/* Dont send p2p packet to buddies of other protocols */
-	if(f->fed)
-		return;
-
-	/* Finally, don't try to connect to buddies not online or on sms */
-	if( (f->status == YAHOO_STATUS_OFFLINE) || f->sms )
-		return;
-
-	public_ip = purple_network_get_public_ip();
-	if( (sscanf(public_ip, "%u.%u.%u.%u", &temp[0], &temp[1], &temp[2], &temp[3])) !=4 )
-		return ;
-
-	ip = (temp[3] << 24) | (temp[2] <<16) | (temp[1] << 8) | temp[0];
-	sprintf(temp_str, "%d", ip);
-	base64_ip = purple_base64_encode( (guchar *)temp_str, strlen(temp_str) );
-
-	norm_username = purple_normalize(account, purple_account_get_username(account));
-	pkt = yahoo_packet_new(YAHOO_SERVICE_PEERTOPEER, YAHOO_STATUS_AVAILABLE, 0);
-	yahoo_packet_hash(pkt, "sssissis",
-		1, norm_username,
-		4, norm_username,
-		12, base64_ip,	/* base64 encode ip */
-		61, 0,		/* To-do : figure out what is 61 for?? */
-		2, "",
-		5, who,
-		13, val_13,
-		49, "PEERTOPEER");
-	yahoo_packet_send_and_free(pkt, yd);
-
-	f->p2p_packet_sent = 1;	/* set p2p_packet_sent to sent */
-
-	p2p_data = g_new0(struct yahoo_p2p_data, 1);
-
-	p2p_data->gc = gc;
-	p2p_data->host_ip = NULL;
-	p2p_data->host_username = g_strdup(who);
-	p2p_data->val_13 = val_13;
-	p2p_data->connection_type = YAHOO_P2P_WE_ARE_SERVER;
-	p2p_data->source = -1;
-
-	/* FIXME: If the port is already used, purple_network_listener returns NULL and old listener won't be canceled
-	 * in yahoo_close function. */
-	if (yd->listen_data)
-		purple_debug_warning("yahoo","p2p: Failed to create p2p server - server already exists\n");
-	else {
-		yd->listen_data = purple_network_listen(YAHOO_PAGER_PORT_P2P, SOCK_STREAM, yahoo_p2p_server_listen_cb, p2p_data);
-		if (yd->listen_data == NULL)
-			purple_debug_warning("yahoo","p2p: Failed to created p2p server\n");
-	}
-
-	g_free(base64_ip);
-}
-
-/* function called when connection to p2p host is setup */
-static void yahoo_p2p_init_cb(gpointer data, gint source, const gchar *error_message)
-{
-	struct yahoo_p2p_data *p2p_data;
-	struct yahoo_packet *pkt_to_send;
-	PurpleAccount *account;
-	YahooData *yd;
-
-	p2p_data = data;
-	yd = p2p_data->gc->proto_data;
-
-	if(error_message != NULL) {
-		purple_debug_warning("yahoo","p2p: %s\n",error_message);
-		yahoo_send_p2p_pkt(p2p_data->gc, p2p_data->host_username, 2);/* send p2p init packet with val_13=2 */
-
-		yahoo_p2p_disconnect_destroy_data(p2p_data);
-		return;
-	}
-
-	/* Add an Input Read event to the file descriptor */
-	p2p_data->input_event = purple_input_add(source, PURPLE_INPUT_READ, yahoo_p2p_read_pkt_cb, data);
-	p2p_data->source = source;
-
-	account = purple_connection_get_account(p2p_data->gc);
-
-	/* Build the yahoo packet */
-	pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash(pkt_to_send, "ssisi",
-		4, purple_normalize(account, purple_account_get_username(account)),
-		5, p2p_data->host_username,
-		241, 0,		/* Protocol identifier */
-		49, "PEERTOPEER",
-		13, 1);		/* we receive key13= 0 or 2, we send key13=1 */
-
-	yahoo_p2p_write_pkt(source, pkt_to_send);	/* build raw packet and send */
-	yahoo_packet_free(pkt_to_send);
-}
-
-static void yahoo_process_p2p(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	GSList *l = pkt->hash;
-	char *who = NULL;
-	char *base64 = NULL;
-	guchar *decoded;
-	gsize len;
-	gint val_13 = 0;
-	gint val_11 = 0;
-	PurpleAccount *account;
-	YahooFriend *f;
-
-	/* if status is not YAHOO_STATUS_BRB or YAHOO_STATUS_P2P, the packet bounced back,
-	 * so it contains our own ip */
-	if(pkt->status != YAHOO_STATUS_BRB && pkt->status != YAHOO_STATUS_P2P)
-		return ;
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 5:
-			/* our identity */
-			break;
-		case 4:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				who = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_p2p "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 1:
-			/* who again, the master identity this time? */
-			break;
-		case 12:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				base64 = pair->value;
-				/* so, this is an ip address. in base64. decoded it's in ascii.
-				   after strtol, it's in reversed byte order. Who thought this up?*/
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_p2p "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 13:
-			val_13 = strtol(pair->value, NULL, 10);
-			break;
-		case 11:
-			val_11 = strtol(pair->value, NULL, 10);		/* session id of peer */
-			if( (f = yahoo_friend_find(gc, who)) )
-				f->session_id = val_11;
-			break;
-		/*
-			TODO: figure these out
-			yahoo: Key: 61          Value: 0
-			yahoo: Key: 2   Value:
-			yahoo: Key: 13          Value: 0	packet count ??
-			yahoo: Key: 49          Value: PEERTOPEER
-			yahoo: Key: 140         Value: 1
-		*/
-
-		}
-
-		l = l->next;
-	}
-
-	if (base64) {
-		guint32 ip;
-		YahooFriend *f;
-		char *host_ip, *tmp;
-		struct yahoo_p2p_data *p2p_data;
-
-		decoded = purple_base64_decode(base64, &len);
-		if (decoded == NULL) {
-			purple_debug_info("yahoo","p2p: Unable to decode base64 IP (%s) \n", base64);
-			return;
-		}
-		tmp = purple_str_binary_to_ascii(decoded, len);
-		purple_debug_info("yahoo", "Got P2P service packet (from server): who = %s, ip = %s\n", who, tmp);
-		g_free(tmp);
-
-		ip = strtol((gchar *)decoded, NULL, 10);
-		g_free(decoded);
-		host_ip = g_strdup_printf("%u.%u.%u.%u", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff,
-		                       (ip >> 24) & 0xff);
-		f = yahoo_friend_find(gc, who);
-		if (f)
-			yahoo_friend_set_ip(f, host_ip);
-		purple_debug_info("yahoo", "IP : %s\n", host_ip);
-
-		account = purple_connection_get_account(gc);
-
-		if(val_11==0) {
-			if(!f)
-				return;
-			else
-				val_11 = f->session_id;
-		}
-
-		p2p_data = g_new0(struct yahoo_p2p_data, 1);
-		p2p_data->host_username = g_strdup(who);
-		p2p_data->val_13 = val_13;
-		p2p_data->session_id = val_11;
-		p2p_data->host_ip = host_ip;
-		p2p_data->gc = gc;
-		p2p_data->connection_type = YAHOO_P2P_WE_ARE_CLIENT;
-		p2p_data->source = -1;
-
-		/* connect to host */
-		if((purple_proxy_connect(gc, account, host_ip, YAHOO_PAGER_PORT_P2P, yahoo_p2p_init_cb, p2p_data))==NULL) {
-			purple_debug_info("yahoo","p2p: Connection to %s failed\n", host_ip);
-			g_free(p2p_data->host_ip);
-			g_free(p2p_data->host_username);
-			g_free(p2p_data);
-		}
-	}
-}
-
-static void yahoo_process_audible(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	PurpleAccount *account;
-	char *who = NULL, *msg = NULL, *id = NULL;
-	GSList *l = pkt->hash;
-
-	account = purple_connection_get_account(gc);
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 4:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				who = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_audible "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 5:
-			/* us */
-			break;
-		case 230:
-			/* the audible, in foo.locale.bar.baz format
-			   eg: base.tw.smiley.smiley43 */
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				id = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_audible "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 231:
-			/* the text of the audible */
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				msg = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_audible "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 232:
-			/* SHA-1 hash of audible SWF file (eg: 4e8691499d9c0fb8374478ff9720f4a9ea4a4915) */
-			break;
-		}
-
-		l = l->next;
-	}
-
-	if (!msg)
-		msg = id;
-	if (!who || !msg)
-		return;
-	if (!g_utf8_validate(msg, -1, NULL)) {
-		purple_debug_misc("yahoo", "Warning, nonutf8 audible, ignoring!\n");
-		return;
-	}
-	if (!purple_privacy_check(account, who)) {
-		purple_debug_misc("yahoo", "Audible message from %s for %s dropped!\n",
-				purple_account_get_username(account), who);
-		return;
-	}
-	if (id) {
-		/* "http://l.yimg.com/pu/dl/aud/"+locale+"/"+id+".swf" */
-		char **audible_locale = g_strsplit(id, ".", 0);
-		char *buf = g_strdup_printf(_("[ Audible %s/%s/%s.swf ] %s"), YAHOO_AUDIBLE_URL, audible_locale[1], id, msg);
-		g_strfreev(audible_locale);
-
-		serv_got_im(gc, who, buf, 0, time(NULL));
-		g_free(buf);
-	} else
-		serv_got_im(gc, who, msg, 0, time(NULL));
-}
-
-static void yahoo_packet_process(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	switch (pkt->service) {
-	case YAHOO_SERVICE_LOGON:
-	case YAHOO_SERVICE_LOGOFF:
-	case YAHOO_SERVICE_ISAWAY:
-	case YAHOO_SERVICE_ISBACK:
-	case YAHOO_SERVICE_GAMELOGON:
-	case YAHOO_SERVICE_GAMELOGOFF:
-	case YAHOO_SERVICE_CHATLOGON:
-	case YAHOO_SERVICE_CHATLOGOFF:
-	case YAHOO_SERVICE_Y6_STATUS_UPDATE:
-	case YAHOO_SERVICE_STATUS_15:
-		yahoo_process_status(gc, pkt);
-		break;
-	case YAHOO_SERVICE_NOTIFY:
-		yahoo_process_notify(gc, pkt, YAHOO_PKT_TYPE_SERVER);
-		break;
-	case YAHOO_SERVICE_MESSAGE:
-	case YAHOO_SERVICE_GAMEMSG:
-	case YAHOO_SERVICE_CHATMSG:
-		yahoo_process_message(gc, pkt, YAHOO_PKT_TYPE_SERVER);
-		break;
-	case YAHOO_SERVICE_SYSMESSAGE:
-		yahoo_process_sysmessage(gc, pkt);
-			break;
-	case YAHOO_SERVICE_NEWMAIL:
-		yahoo_process_mail(gc, pkt);
-		break;
-	case YAHOO_SERVICE_NEWCONTACT:
-		yahoo_process_contact(gc, pkt);
-		break;
-	case YAHOO_SERVICE_AUTHRESP:
-		yahoo_process_authresp(gc, pkt);
-		break;
-	case YAHOO_SERVICE_LIST:
-		yahoo_process_list(gc, pkt);
-		break;
-	case YAHOO_SERVICE_LIST_15:
-		yahoo_process_list_15(gc, pkt);
-		break;
-	case YAHOO_SERVICE_AUTH:
-		yahoo_process_auth(gc, pkt);
-		break;
-	case YAHOO_SERVICE_AUTH_REQ_15:
-		yahoo_buddy_auth_req_15(gc, pkt);
-		break;
-	case YAHOO_SERVICE_ADDBUDDY:
-		yahoo_process_addbuddy(gc, pkt);
-		break;
-	case YAHOO_SERVICE_IGNORECONTACT:
-		yahoo_process_ignore(gc, pkt);
-		break;
-	case YAHOO_SERVICE_CONFINVITE:
-	case YAHOO_SERVICE_CONFADDINVITE:
-		yahoo_process_conference_invite(gc, pkt);
-		break;
-	case YAHOO_SERVICE_CONFDECLINE:
-		yahoo_process_conference_decline(gc, pkt);
-		break;
-	case YAHOO_SERVICE_CONFLOGON:
-		yahoo_process_conference_logon(gc, pkt);
-		break;
-	case YAHOO_SERVICE_CONFLOGOFF:
-		yahoo_process_conference_logoff(gc, pkt);
-		break;
-	case YAHOO_SERVICE_CONFMSG:
-		yahoo_process_conference_message(gc, pkt);
-		break;
-	case YAHOO_SERVICE_CHATONLINE:
-		yahoo_process_chat_online(gc, pkt);
-		break;
-	case YAHOO_SERVICE_CHATLOGOUT:
-		yahoo_process_chat_logout(gc, pkt);
-		break;
-	case YAHOO_SERVICE_CHATGOTO:
-		yahoo_process_chat_goto(gc, pkt);
-		break;
-	case YAHOO_SERVICE_CHATJOIN:
-		yahoo_process_chat_join(gc, pkt);
-		break;
-	case YAHOO_SERVICE_CHATLEAVE: /* XXX is this right? */
-	case YAHOO_SERVICE_CHATEXIT:
-		yahoo_process_chat_exit(gc, pkt);
-		break;
-	case YAHOO_SERVICE_CHATINVITE: /* XXX never seen this one, might not do it right */
-	case YAHOO_SERVICE_CHATADDINVITE:
-		yahoo_process_chat_addinvite(gc, pkt);
-		break;
-	case YAHOO_SERVICE_COMMENT:
-		yahoo_process_chat_message(gc, pkt);
-		break;
-	case YAHOO_SERVICE_PRESENCE_PERM:
-	case YAHOO_SERVICE_PRESENCE_SESSION:
-		yahoo_process_presence(gc, pkt);
-		break;
-	case YAHOO_SERVICE_P2PFILEXFER:
-		/* This case had no break and continued; thus keeping it this way.*/
-		yahoo_process_p2p(gc, pkt);	/* P2PFILEXFER handled the same way as process_p2p */
-		yahoo_process_p2pfilexfer(gc, pkt);	/* redundant ??, need to have a break now */
-	case YAHOO_SERVICE_FILETRANSFER:
-		yahoo_process_filetransfer(gc, pkt);
-		break;
-	case YAHOO_SERVICE_PEERTOPEER:
-		yahoo_process_p2p(gc, pkt);
-		break;
-	case YAHOO_SERVICE_PICTURE:
-		yahoo_process_picture(gc, pkt);
-		break;
-	case YAHOO_SERVICE_PICTURE_CHECKSUM:
-		yahoo_process_picture_checksum(gc, pkt);
-		break;
-	case YAHOO_SERVICE_PICTURE_UPLOAD:
-		yahoo_process_picture_upload(gc, pkt);
-		break;
-	case YAHOO_SERVICE_PICTURE_UPDATE:
-	case YAHOO_SERVICE_AVATAR_UPDATE:
-		yahoo_process_avatar_update(gc, pkt);
-		break;
-	case YAHOO_SERVICE_AUDIBLE:
-		yahoo_process_audible(gc, pkt);
-		break;
-	case YAHOO_SERVICE_CONTACT_DETAILS:
-		yahoo_process_contact_details(gc, pkt);
-		break;
-	case YAHOO_SERVICE_FILETRANS_15:
-		yahoo_process_filetrans_15(gc, pkt);
-		break;
-	case YAHOO_SERVICE_FILETRANS_INFO_15:
-		yahoo_process_filetrans_info_15(gc, pkt);
-		break;
-	case YAHOO_SERVICE_FILETRANS_ACC_15:
-		yahoo_process_filetrans_acc_15(gc, pkt);
-		break;
-	case YAHOO_SERVICE_SMS_MSG:
-		yahoo_process_sms_message(gc, pkt);
-		break;
-
-	default:
-		purple_debug_error("yahoo", "Unhandled service 0x%02x\n", pkt->service);
-		break;
-	}
-}
-
-static void yahoo_pending(gpointer data, gint source, PurpleInputCondition cond)
-{
-	PurpleConnection *gc = data;
-	YahooData *yd = gc->proto_data;
-	char buf[1024];
-	int len;
-
-	len = read(yd->fd, buf, sizeof(buf));
-
-	if (len < 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 (len == 0) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-				_("Server closed the connection"));
-		return;
-	}
-	gc->last_received = time(NULL);
-	yd->rxqueue = g_realloc(yd->rxqueue, len + yd->rxlen);
-	memcpy(yd->rxqueue + yd->rxlen, buf, len);
-	yd->rxlen += len;
-
-	while (1) {
-		struct yahoo_packet *pkt;
-		int pos = 0;
-		int pktlen;
-
-		if (yd->rxlen < YAHOO_PACKET_HDRLEN)
-			return;
-
-		if (strncmp((char *)yd->rxqueue, "YMSG", MIN(4, yd->rxlen)) != 0) {
-			/* HEY! This isn't even a YMSG packet. What
-			 * are you trying to pull? */
-			guchar *start;
-
-			purple_debug_warning("yahoo", "Error in YMSG stream, got something not a YMSG packet!\n");
-
-			start = memchr(yd->rxqueue + 1, 'Y', yd->rxlen - 1);
-			if (start) {
-				g_memmove(yd->rxqueue, start, yd->rxlen - (start - yd->rxqueue));
-				yd->rxlen -= start - yd->rxqueue;
-				continue;
-			} else {
-				g_free(yd->rxqueue);
-				yd->rxqueue = NULL;
-				yd->rxlen = 0;
-				return;
-			}
-		}
-
-		pos += 4; /* YMSG */
-		pos += 2;
-		pos += 2;
-
-		pktlen = yahoo_get16(yd->rxqueue + pos); pos += 2;
-		purple_debug_misc("yahoo", "%d bytes to read, rxlen is %d\n", pktlen, yd->rxlen);
-
-		if (yd->rxlen < (YAHOO_PACKET_HDRLEN + pktlen))
-			return;
-
-		yahoo_packet_dump(yd->rxqueue, YAHOO_PACKET_HDRLEN + pktlen);
-
-		pkt = yahoo_packet_new(0, 0, 0);
-
-		pkt->service = yahoo_get16(yd->rxqueue + pos); pos += 2;
-		pkt->status = yahoo_get32(yd->rxqueue + pos); pos += 4;
-		purple_debug_misc("yahoo", "Yahoo Service: 0x%02x Status: %d\n",
-				   pkt->service, pkt->status);
-		pkt->id = yahoo_get32(yd->rxqueue + pos); pos += 4;
-
-		yahoo_packet_read(pkt, yd->rxqueue + pos, pktlen);
-
-		yd->rxlen -= YAHOO_PACKET_HDRLEN + pktlen;
-		if (yd->rxlen) {
-			guchar *tmp = g_memdup(yd->rxqueue + YAHOO_PACKET_HDRLEN + pktlen, yd->rxlen);
-			g_free(yd->rxqueue);
-			yd->rxqueue = tmp;
-		} else {
-			g_free(yd->rxqueue);
-			yd->rxqueue = NULL;
-		}
-
-		yahoo_packet_process(gc, pkt);
-
-		yahoo_packet_free(pkt);
-	}
-}
-
-static void yahoo_got_connected(gpointer data, gint source, const gchar *error_message)
-{
-	PurpleConnection *gc = data;
-	YahooData *yd;
-	struct yahoo_packet *pkt;
-
-	if (source < 0) {
-		gchar *tmp;
-		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;
-	}
-
-	yd = gc->proto_data;
-	yd->fd = source;
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, yd->current_status, yd->session_id);
-
-	yahoo_packet_hash_str(pkt, 1, purple_normalize(gc->account, purple_account_get_username(purple_connection_get_account(gc))));
-	yahoo_packet_send_and_free(pkt, yd);
-
-	gc->inpa = purple_input_add(yd->fd, PURPLE_INPUT_READ, yahoo_pending, gc);
-}
-
-#ifdef TRY_WEBMESSENGER_LOGIN
-static void yahoo_got_web_connected(gpointer data, gint source, const gchar *error_message)
-{
-	PurpleConnection *gc = data;
-	YahooData *yd;
-	struct yahoo_packet *pkt;
-
-	if (source < 0) {
-		gchar *tmp;
-		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;
-	}
-
-	yd = gc->proto_data;
-	yd->fd = source;
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_WEBLOGIN, YAHOO_STATUS_WEBLOGIN, yd->session_id);
-
-	yahoo_packet_hash(pkt, "sss", 0,
-	                  purple_normalize(gc->account, purple_account_get_username(purple_connection_get_account(gc))),
-	                  1, purple_normalize(gc->account, purple_account_get_username(purple_connection_get_account(gc))),
-	                  6, yd->auth);
-	yahoo_packet_send_and_free(pkt, yd);
-
-	g_free(yd->auth);
-	gc->inpa = purple_input_add(yd->fd, PURPLE_INPUT_READ, yahoo_pending, gc);
-}
-
-static void yahoo_web_pending(gpointer data, gint source, PurpleInputCondition cond)
-{
-	PurpleConnection *gc = data;
-	PurpleAccount *account = purple_connection_get_account(gc);
-	YahooData *yd = gc->proto_data;
-	char bufread[2048], *i = bufread, *buf = bufread;
-	int len;
-	GString *s;
-
-	len = read(source, bufread, sizeof(bufread) - 1);
-
-	if (len < 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 (len == 0) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-				_("Server closed the connection"));
-		return;
-	}
-
-	if (yd->rxlen > 0 || !g_strstr_len(buf, len, "\r\n\r\n")) {
-		yd->rxqueue = g_realloc(yd->rxqueue, yd->rxlen + len + 1);
-		memcpy(yd->rxqueue + yd->rxlen, buf, len);
-		yd->rxlen += len;
-		i = buf = (char *)yd->rxqueue;
-		len = yd->rxlen;
-	}
-	buf[len] = '\0';
-
-	if ((strncmp(buf, "HTTP/1.0 302", strlen("HTTP/1.0 302")) &&
-			  strncmp(buf, "HTTP/1.1 302", strlen("HTTP/1.1 302")))) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("Received unexpected HTTP response from server"));
-		purple_debug_misc("yahoo", "Unexpected HTTP response: %s\n", buf);
-		return;
-	}
-
-	s = g_string_sized_new(len);
-
-	while ((i = strstr(i, "Set-Cookie: "))) {
-
-		i += strlen("Set-Cookie: ");
-		for (;*i != ';' && *i != '\0'; i++)
-			g_string_append_c(s, *i);
-
-		g_string_append(s, "; ");
-		/* Should these cookies be included too when trying for xfer?
-		 * It seems to work without these
-		 */
-	}
-
-	yd->auth = g_string_free(s, FALSE);
-	purple_input_remove(gc->inpa);
-	close(source);
-	g_free(yd->rxqueue);
-	yd->rxqueue = NULL;
-	yd->rxlen = 0;
-	/* Now we have our cookies to login with.  I'll go get the milk. */
-	if (purple_proxy_connect(gc, account, "wcs2.msg.dcn.yahoo.com",
-	                         purple_account_get_int(account, "port", YAHOO_PAGER_PORT),
-	                         yahoo_got_web_connected, gc) == NULL) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-		                               _("Unable to connect"));
-		return;
-	}
-}
-
-static void yahoo_got_cookies_send_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
-	PurpleConnection *gc;
-	YahooData *yd;
-	int written, remaining;
-
-	gc = data;
-	yd = gc->proto_data;
-
-	remaining = strlen(yd->auth) - yd->auth_written;
-	written = write(source, yd->auth + yd->auth_written, remaining);
-
-	if (written < 0 && errno == EAGAIN)
-		written = 0;
-	else if (written <= 0) {
-		gchar *tmp;
-		g_free(yd->auth);
-		yd->auth = NULL;
-		if (gc->inpa)
-			purple_input_remove(gc->inpa);
-		gc->inpa = 0;
-		tmp = g_strdup_printf(_("Lost connection with %s: %s"),
-				"login.yahoo.com:80", g_strerror(errno));
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-		g_free(tmp);
-		return;
-	}
-
-	if (written < remaining) {
-		yd->auth_written += written;
-		return;
-	}
-
-	g_free(yd->auth);
-	yd->auth = NULL;
-	yd->auth_written = 0;
-	purple_input_remove(gc->inpa);
-	gc->inpa = purple_input_add(source, PURPLE_INPUT_READ, yahoo_web_pending, gc);
-}
-
-static void yahoo_got_cookies(gpointer data, gint source, const gchar *error_message)
-{
-	PurpleConnection *gc = data;
-
-	if (source < 0) {
-		gchar *tmp;
-		tmp = g_strdup_printf(_("Unable to establish a connection with %s: %s"),
-				"login.yahoo.com:80", error_message);
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-		g_free(tmp);
-		return;
-	}
-
-	if (gc->inpa == 0)
-	{
-		gc->inpa = purple_input_add(source, PURPLE_INPUT_WRITE,
-			yahoo_got_cookies_send_cb, gc);
-		yahoo_got_cookies_send_cb(gc, source, PURPLE_INPUT_WRITE);
-	}
-}
-
-static void yahoo_login_page_hash_iter(const char *key, const char *val, GString *url)
-{
-	if (!strcmp(key, "passwd") || !strcmp(key, "login"))
-		return;
-	g_string_append_c(url, '&');
-	g_string_append(url, key);
-	g_string_append_c(url, '=');
-	if (!strcmp(key, ".save") || !strcmp(key, ".js"))
-		g_string_append_c(url, '1');
-	else if (!strcmp(key, ".challenge"))
-		g_string_append(url, val);
-	else
-		g_string_append(url, purple_url_encode(val));
-}
-
-static GHashTable *yahoo_login_page_hash(const char *buf, size_t len)
-{
-	GHashTable *hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-	const char *c = buf;
-	char *d;
-	char name[64], value[64];
-	int count;
-	int input_len = strlen("<input ");
-	int name_len = strlen("name=\"");
-	int value_len = strlen("value=\"");
-	while ((len > ((c - buf) + input_len))
-			&& (c = strstr(c, "<input "))) {
-		if (!(c = g_strstr_len(c, len - (c - buf), "name=\"")))
-			continue;
-		c += name_len;
-		count = sizeof(name)-1;
-		for (d = name; (len > ((c - buf) + 1)) && *c!='"'
-				&& count; c++, d++, count--)
-			*d = *c;
-		*d = '\0';
-		count = sizeof(value)-1;
-		if (!(d = g_strstr_len(c, len - (c - buf), "value=\"")))
-			continue;
-		d += value_len;
-		if (strchr(c, '>') < d)
-			break;
-		for (c = d, d = value; (len > ((c - buf) + 1))
-				&& *c!='"' && count; c++, d++, count--)
-			*d = *c;
-		*d = '\0';
-		g_hash_table_insert(hash, g_strdup(name), g_strdup(value));
-	}
-	return hash;
-}
-
-static void
-yahoo_login_page_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
-		const gchar *url_text, size_t len, const gchar *error_message)
-{
-	PurpleConnection *gc = (PurpleConnection *)user_data;
-	PurpleAccount *account = purple_connection_get_account(gc);
-	YahooData *yd = gc->proto_data;
-	const char *sn = purple_account_get_username(account);
-	const char *pass = purple_connection_get_password(gc);
-	GHashTable *hash = yahoo_login_page_hash(url_text, len);
-	GString *url = g_string_new("GET http://login.yahoo.com/config/login?login=");
-	char md5[33], *hashp = md5, *chal;
-	int i;
-	PurpleCipher *cipher;
-	PurpleCipherContext *context;
-	guchar digest[16];
-
-	yd->url_datas = g_slist_remove(yd->url_datas, url_data);
-
-	if (error_message != NULL)
-	{
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-		                               error_message);
-		return;
-	}
-
-	url = g_string_append(url, sn);
-	url = g_string_append(url, "&passwd=");
-
-	cipher = purple_ciphers_find_cipher("md5");
-	context = purple_cipher_context_new(cipher, NULL);
-
-	purple_cipher_context_append(context, (const guchar *)pass, strlen(pass));
-	purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
-	for (i = 0; i < 16; ++i) {
-		g_snprintf(hashp, 3, "%02x", digest[i]);
-		hashp += 2;
-	}
-
-	chal = g_strconcat(md5, g_hash_table_lookup(hash, ".challenge"), NULL);
-	purple_cipher_context_reset(context, NULL);
-	purple_cipher_context_append(context, (const guchar *)chal, strlen(chal));
-	purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
-	hashp = md5;
-	for (i = 0; i < 16; ++i) {
-		g_snprintf(hashp, 3, "%02x", digest[i]);
-		hashp += 2;
-	}
-	/*
-	 * I dunno why this is here and commented out.. but in case it's needed
-	 * I updated it..
-
-	purple_cipher_context_reset(context, NULL);
-	purple_cipher_context_append(context, md5, strlen(md5));
-	purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
-	hashp = md5;
-	for (i = 0; i < 16; ++i) {
-		g_snprintf(hashp, 3, "%02x", digest[i]);
-		hashp += 2;
-	}
-	*/
-	g_free(chal);
-
-	url = g_string_append(url, md5);
-	g_hash_table_foreach(hash, (GHFunc)yahoo_login_page_hash_iter, url);
-
-	url = g_string_append(url, "&.hash=1&.md5=1 HTTP/1.1\r\n"
-			      "Host: login.yahoo.com\r\n\r\n");
-	g_hash_table_destroy(hash);
-	yd->auth = g_string_free(url, FALSE);
-	if (purple_proxy_connect(gc, account, "login.yahoo.com", 80, yahoo_got_cookies, gc) == NULL) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-		                               _("Unable to connect"));
-		return;
-	}
-
-	purple_cipher_context_destroy(context);
-}
-#endif /* TRY_WEBMESSENGER_LOGIN */
-
-static void yahoo_picture_check(PurpleAccount *account)
-{
-	PurpleConnection *gc = purple_account_get_connection(account);
-	PurpleStoredImage *img = purple_buddy_icons_find_account_icon(account);
-
-	yahoo_set_buddy_icon(gc, img);
-	purple_imgstore_unref(img);
-}
-
-static int get_yahoo_status_from_purple_status(PurpleStatus *status)
-{
-	PurplePresence *presence;
-	const char *status_id;
-	const char *msg;
-
-	presence = purple_status_get_presence(status);
-	status_id = purple_status_get_id(status);
-	msg = purple_status_get_attr_string(status, "message");
-
-	if ((msg != NULL) && (*msg != '\0')) {
-		return YAHOO_STATUS_CUSTOM;
-	} else if (!strcmp(status_id, YAHOO_STATUS_TYPE_AVAILABLE)) {
-		return YAHOO_STATUS_AVAILABLE;
-	} else if (!strcmp(status_id, YAHOO_STATUS_TYPE_BRB)) {
-		return YAHOO_STATUS_BRB;
-	} else if (!strcmp(status_id, YAHOO_STATUS_TYPE_BUSY)) {
-		return YAHOO_STATUS_BUSY;
-	} else if (!strcmp(status_id, YAHOO_STATUS_TYPE_NOTATHOME)) {
-		return YAHOO_STATUS_NOTATHOME;
-	} else if (!strcmp(status_id, YAHOO_STATUS_TYPE_NOTATDESK)) {
-		return YAHOO_STATUS_NOTATDESK;
-	} else if (!strcmp(status_id, YAHOO_STATUS_TYPE_NOTINOFFICE)) {
-		return YAHOO_STATUS_NOTINOFFICE;
-	} else if (!strcmp(status_id, YAHOO_STATUS_TYPE_ONPHONE)) {
-		return YAHOO_STATUS_ONPHONE;
-	} else if (!strcmp(status_id, YAHOO_STATUS_TYPE_ONVACATION)) {
-		return YAHOO_STATUS_ONVACATION;
-	} else if (!strcmp(status_id, YAHOO_STATUS_TYPE_OUTTOLUNCH)) {
-		return YAHOO_STATUS_OUTTOLUNCH;
-	} else if (!strcmp(status_id, YAHOO_STATUS_TYPE_STEPPEDOUT)) {
-		return YAHOO_STATUS_STEPPEDOUT;
-	} else if (!strcmp(status_id, YAHOO_STATUS_TYPE_INVISIBLE)) {
-		return YAHOO_STATUS_INVISIBLE;
-	} else if (!strcmp(status_id, YAHOO_STATUS_TYPE_AWAY)) {
-		return YAHOO_STATUS_CUSTOM;
-	} else if (purple_presence_is_idle(presence)) {
-		return YAHOO_STATUS_IDLE;
-	} else {
-		purple_debug_error("yahoo", "Unexpected PurpleStatus!\n");
-		return YAHOO_STATUS_AVAILABLE;
-	}
-}
-
-static void yahoo_got_pager_server(PurpleUtilFetchUrlData *url_data,
-		gpointer user_data, const gchar *url_text, gsize len, const gchar *error_message)
-{
-	YahooData *yd = user_data;
-	PurpleConnection *gc = yd->gc;
-	PurpleAccount *a = purple_connection_get_account(gc);
-	gchar **strings = NULL, *cs_server = NULL;
-	int port = purple_account_get_int(a, "port", YAHOO_PAGER_PORT);
-	int stringslen = 0;
-
-	yd->url_datas = g_slist_remove(yd->url_datas, url_data);
-
-	if(error_message != NULL || len == 0) {
-		purple_debug_error("yahoo", "Unable to retrieve server info. %"
-				G_GSIZE_FORMAT " bytes retrieved with error message: %s\n", len,
-				error_message ? error_message : "(null)");
-
-		if(yahoo_is_japan(a)) { /* We don't know fallback hosts for Yahoo Japan :( */
-			purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-					_("Unable to connect: The server returned an empty response."));
-		} else {
-				if(purple_proxy_connect(gc, a, YAHOO_PAGER_HOST_FALLBACK, port,
-							yahoo_got_connected, gc) == NULL) {
-					purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-							_("Unable to connect"));
-				}
-		}
-	} else {
-		strings = g_strsplit(url_text, "\r\n", -1);
-
-		if((stringslen = g_strv_length(strings)) > 1) {
-			int i;
-
-			for(i = 0; i < stringslen; i++) {
-				if(g_ascii_strncasecmp(strings[i], "COLO_CAPACITY=", 14) == 0) {
-					purple_debug_info("yahoo", "Got COLO Capacity: %s\n", &(strings[i][14]));
-				} else if(g_ascii_strncasecmp(strings[i], "CS_IP_ADDRESS=", 14) == 0) {
-					cs_server = g_strdup(&strings[i][14]);
-					purple_debug_info("yahoo", "Got CS IP address: %s\n", cs_server);
-				}
-			}
-		}
-
-		if(cs_server) { /* got an address; get on with connecting */
-			if(purple_proxy_connect(gc, a, cs_server, port, yahoo_got_connected, gc) == NULL)
-				purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-								_("Unable to connect"));
-		} else {
-			purple_debug_error("yahoo", "No CS address retrieved!  Server "
-					"response:\n%s\n", url_text ? url_text : "(null)");
-
-			if(yahoo_is_japan(a)) { /* We don't know fallback hosts for Yahoo Japan :( */
-				purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-						_("Unable to connect: The server's response did not contain "
-							"the necessary information"));
-			} else
-				if(purple_proxy_connect(gc, a, YAHOO_PAGER_HOST_FALLBACK, port,
-							yahoo_got_connected, gc) == NULL) {
-					purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-							_("Unable to connect"));
-				}
-		}
-	}
-
-	g_strfreev(strings);
-	g_free(cs_server);
-}
-
-void yahoo_login(PurpleAccount *account) {
-	PurpleConnection *gc = purple_account_get_connection(account);
-	YahooData *yd = gc->proto_data = g_new0(YahooData, 1);
-	PurpleStatus *status = purple_account_get_active_status(account);
-	gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
-	gboolean proxy_ssl = purple_account_get_bool(account, "proxy_ssl", FALSE);
-	PurpleUtilFetchUrlData *url_data;
-
-	gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC;
-
-	purple_connection_update_progress(gc, _("Connecting"), 1, 2);
-
-	purple_connection_set_display_name(gc, purple_account_get_username(account));
-
-	yd->gc = gc;
-	yd->jp = yahoo_is_japan(account);
-	yd->yahoo_local_p2p_server_fd = -1;
-	yd->fd = -1;
-	yd->txhandler = 0;
-	/* TODO: Is there a good grow size for the buffer? */
-	yd->txbuf = purple_circ_buffer_new(0);
-	yd->friends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_friend_free);
-	yd->imvironments = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-	yd->xfer_peer_idstring_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
-	yd->peers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
-					yahoo_p2p_disconnect_destroy_data);
-	yd->sms_carrier = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-	yd->yahoo_p2p_timer = purple_timeout_add_seconds(YAHOO_P2P_KEEPALIVE_SECS,
-					yahoo_p2p_keepalive, gc);
-	yd->confs = NULL;
-	yd->conf_id = 2;
-	yd->last_keepalive = yd->last_ping = time(NULL);
-
-	yd->current_status = get_yahoo_status_from_purple_status(status);
-
-	yahoo_picture_check(account);
-
-	/* Get the pager server.  Actually start connecting in the callback since we
-	 * must have the contents of the HTTP response to proceed. */
-	url_data = purple_util_fetch_url_request_len_with_account(
-			proxy_ssl ? purple_connection_get_account(gc) : NULL,
-			yd->jp ? YAHOOJP_PAGER_HOST_REQ_URL : YAHOO_PAGER_HOST_REQ_URL,
-			use_whole_url ? TRUE : FALSE,
-			YAHOO_CLIENT_USERAGENT, FALSE, NULL, FALSE, -1,
-			yahoo_got_pager_server, yd);
-	if (url_data)
-		yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
-
-	return;
-}
-
-void yahoo_close(PurpleConnection *gc) {
-	YahooData *yd = (YahooData *)gc->proto_data;
-	GSList *l;
-
-	if (gc->inpa)
-		purple_input_remove(gc->inpa);
-
-	while (yd->url_datas) {
-		purple_util_fetch_url_cancel(yd->url_datas->data);
-		yd->url_datas = g_slist_delete_link(yd->url_datas, yd->url_datas);
-	}
-
-	for (l = yd->confs; l; l = l->next) {
-		PurpleConversation *conv = l->data;
-
-		yahoo_conf_leave(yd, purple_conversation_get_name(conv),
-		                 purple_connection_get_display_name(gc),
-				 purple_conv_chat_get_users(PURPLE_CONV_CHAT(conv)));
-	}
-	g_slist_free(yd->confs);
-
-	for (l = yd->cookies; l; l = l->next) {
-		g_free(l->data);
-		l->data=NULL;
-	}
-	g_slist_free(yd->cookies);
-
-	yd->chat_online = FALSE;
-	if (yd->in_chat)
-		yahoo_c_leave(gc, 1); /* 1 = YAHOO_CHAT_ID */
-
-	purple_timeout_remove(yd->yahoo_p2p_timer);
-	if(yd->yahoo_p2p_server_timeout_handle != 0) {
-		purple_timeout_remove(yd->yahoo_p2p_server_timeout_handle);
-		yd->yahoo_p2p_server_timeout_handle = 0;
-	}
-
-	/* close p2p server if it is waiting for a peer to connect */
-	if (yd->yahoo_p2p_server_watcher) {
-		purple_input_remove(yd->yahoo_p2p_server_watcher);
-		yd->yahoo_p2p_server_watcher = 0;
-	}
-	if (yd->yahoo_local_p2p_server_fd >= 0) {
-		close(yd->yahoo_local_p2p_server_fd);
-		yd->yahoo_local_p2p_server_fd = -1;
-	}
-
-	g_hash_table_destroy(yd->sms_carrier);
-	g_hash_table_destroy(yd->peers);
-	g_hash_table_destroy(yd->friends);
-	g_hash_table_destroy(yd->imvironments);
-	g_hash_table_destroy(yd->xfer_peer_idstring_map);
-	g_free(yd->chat_name);
-
-	g_free(yd->cookie_y);
-	g_free(yd->cookie_t);
-	g_free(yd->cookie_b);
-
-	if (yd->txhandler)
-		purple_input_remove(yd->txhandler);
-
-	purple_circ_buffer_destroy(yd->txbuf);
-
-	if (yd->fd >= 0)
-		close(yd->fd);
-
-	g_free(yd->rxqueue);
-	yd->rxlen = 0;
-	g_free(yd->picture_url);
-
-	if (yd->buddy_icon_connect_data)
-		purple_proxy_connect_cancel(yd->buddy_icon_connect_data);
-	if (yd->picture_upload_todo)
-		yahoo_buddy_icon_upload_data_free(yd->picture_upload_todo);
-	if (yd->ycht)
-		ycht_connection_close(yd->ycht);
-	if (yd->listen_data != NULL)
-		purple_network_listen_cancel(yd->listen_data);
-
-	g_free(yd->pending_chat_room);
-	g_free(yd->pending_chat_id);
-	g_free(yd->pending_chat_topic);
-	g_free(yd->pending_chat_goto);
-	g_strfreev(yd->profiles);
-
-	yahoo_personal_details_reset(&yd->ypd, TRUE);
-
-	g_free(yd->current_list15_grp);
-
-	g_free(yd);
-	gc->proto_data = NULL;
-}
-
-const char *yahoo_list_icon(PurpleAccount *a, PurpleBuddy *b)
-{
-	return "yahoo";
-}
-
-const char *yahoo_list_emblem(PurpleBuddy *b)
-{
-	PurpleAccount *account;
-	PurpleConnection *gc;
-	YahooFriend *f;
-	PurplePresence *presence;
-
-	if (!b || !(account = purple_buddy_get_account(b)) ||
-			!(gc = purple_account_get_connection(account)) ||
-			!gc->proto_data)
-		return NULL;
-
-	f = yahoo_friend_find(gc, purple_buddy_get_name(b));
-	if (!f) {
-		return "not-authorized";
-	}
-
-	presence = purple_buddy_get_presence(b);
-
-	if (purple_presence_is_online(presence)) {
-		if (yahoo_friend_get_game(f))
-			return "game";
-
-		if (f->fed)
-			return "external";
-	}
-	return NULL;
-}
-
-static const char *yahoo_get_status_string(enum yahoo_status a)
-{
-	switch (a) {
-	case YAHOO_STATUS_BRB:
-		return _("Be Right Back");
-	case YAHOO_STATUS_BUSY:
-		return _("Busy");
-	case YAHOO_STATUS_NOTATHOME:
-		return _("Not at Home");
-	case YAHOO_STATUS_NOTATDESK:
-		return _("Not at Desk");
-	case YAHOO_STATUS_NOTINOFFICE:
-		return _("Not in Office");
-	case YAHOO_STATUS_ONPHONE:
-		return _("On the Phone");
-	case YAHOO_STATUS_ONVACATION:
-		return _("On Vacation");
-	case YAHOO_STATUS_OUTTOLUNCH:
-		return _("Out to Lunch");
-	case YAHOO_STATUS_STEPPEDOUT:
-		return _("Stepped Out");
-	case YAHOO_STATUS_INVISIBLE:
-		return _("Invisible");
-	case YAHOO_STATUS_IDLE:
-		return _("Idle");
-	case YAHOO_STATUS_OFFLINE:
-		return _("Offline");
-	default:
-		return _("Available");
-	}
-}
-
-static void yahoo_initiate_conference(PurpleBlistNode *node, gpointer data) {
-
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-
-	GHashTable *components;
-	YahooData *yd;
-	int id;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-	yd = gc->proto_data;
-	id = yd->conf_id;
-
-	components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-	g_hash_table_replace(components, g_strdup("room"),
-		g_strdup_printf("%s-%d", purple_connection_get_display_name(gc), id));
-	g_hash_table_replace(components, g_strdup("topic"), g_strdup("Join my conference..."));
-	g_hash_table_replace(components, g_strdup("type"), g_strdup("Conference"));
-	yahoo_c_join(gc, components);
-	g_hash_table_destroy(components);
-
-	yahoo_c_invite(gc, id, "Join my conference...", purple_buddy_get_name(buddy));
-}
-
-static void yahoo_presence_settings(PurpleBlistNode *node, gpointer data) {
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-	int presence_val = GPOINTER_TO_INT(data);
-
-	buddy = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-
-	yahoo_friend_update_presence(gc, purple_buddy_get_name(buddy), presence_val);
-}
-
-static void yahoo_game(PurpleBlistNode *node, gpointer data) {
-
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-
-	const char *game;
-	char *game2;
-	char *t;
-	char url[256];
-	YahooFriend *f;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-
-	f = yahoo_friend_find(gc, purple_buddy_get_name(buddy));
-	if (!f)
-		return;
-
-	game = yahoo_friend_get_game(f);
-	if (!game)
-		return;
-
-	t = game2 = g_strdup(strstr(game, "ante?room="));
-	while (*t && *t != '\t')
-		t++;
-	*t = 0;
-	g_snprintf(url, sizeof url, "http://games.yahoo.com/games/%s", game2);
-	purple_notify_uri(gc, url);
-	g_free(game2);
-}
-
-char *yahoo_status_text(PurpleBuddy *b)
-{
-	YahooFriend *f = NULL;
-	const char *msg;
-	char *msg2;
-	PurpleAccount *account;
-	PurpleConnection *gc;
-
-	account = purple_buddy_get_account(b);
-	gc = purple_account_get_connection(account);
-	if (!gc || !purple_connection_get_protocol_data(gc))
-		return NULL;
-
-	f = yahoo_friend_find(gc, purple_buddy_get_name(b));
-	if (!f)
-		return g_strdup(_("Not on server list"));
-
-	switch (f->status) {
-	case YAHOO_STATUS_AVAILABLE:
-		return NULL;
-	case YAHOO_STATUS_IDLE:
-		if (f->idle == -1)
-			return g_strdup(yahoo_get_status_string(f->status));
-		return NULL;
-	case YAHOO_STATUS_CUSTOM:
-		if (!(msg = yahoo_friend_get_status_message(f)))
-			return NULL;
-		msg2 = g_markup_escape_text(msg, strlen(msg));
-		purple_util_chrreplace(msg2, '\n', ' ');
-		return msg2;
-
-	default:
-		return g_strdup(yahoo_get_status_string(f->status));
-	}
-}
-
-void yahoo_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full)
-{
-	YahooFriend *f;
-	char *status = NULL;
-	const char *presence = NULL;
-	PurpleAccount *account;
-
-	account = purple_buddy_get_account(b);
-	f = yahoo_friend_find(purple_account_get_connection(account), purple_buddy_get_name(b));
-	if (!f)
-		status = g_strdup_printf("\n%s", _("Not on server list"));
-	else {
-		switch (f->status) {
-		case YAHOO_STATUS_CUSTOM:
-			if (!yahoo_friend_get_status_message(f))
-				return;
-			status = g_strdup(yahoo_friend_get_status_message(f));
-			break;
-		case YAHOO_STATUS_OFFLINE:
-			break;
-		default:
-			status = g_strdup(yahoo_get_status_string(f->status));
-			break;
-		}
-
-		switch (f->presence) {
-			case YAHOO_PRESENCE_ONLINE:
-				presence = _("Appear Online");
-				break;
-			case YAHOO_PRESENCE_PERM_OFFLINE:
-				presence = _("Appear Permanently Offline");
-				break;
-			case YAHOO_PRESENCE_DEFAULT:
-				break;
-			default:
-				purple_debug_error("yahoo", "Unknown presence in yahoo_tooltip_text\n");
-				break;
-		}
-	}
-
-	if (status != NULL) {
-		purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), status);
-		g_free(status);
-	}
-
-	if (presence != NULL)
-		purple_notify_user_info_add_pair_plaintext(user_info, _("Presence"), presence);
-
-	if (f && full) {
-		YahooPersonalDetails *ypd = &f->ypd;
-		int i;
-		struct {
-			char *id;
-			char *text;
-			char *value;
-		} yfields[] = {
-			{"hp", N_("Home Phone Number"), ypd->phone.home},
-			{"wp", N_("Work Phone Number"), ypd->phone.work},
-			{"mo", N_("Mobile Phone Number"), ypd->phone.mobile},
-			{NULL, NULL, NULL}
-		};
-		for (i = 0; yfields[i].id; i++) {
-			if (!yfields[i].value || !*yfields[i].value)
-				continue;
-			purple_notify_user_info_add_pair(user_info, _(yfields[i].text), yfields[i].value);
-		}
-	}
-}
-
-static void yahoo_addbuddyfrommenu_cb(PurpleBlistNode *node, gpointer data)
-{
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-
-	yahoo_add_buddy(gc, buddy, NULL);
-}
-
-
-static void yahoo_chat_goto_menu(PurpleBlistNode *node, gpointer data)
-{
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-
-	yahoo_chat_goto(gc, purple_buddy_get_name(buddy));
-}
-
-static GList *build_presence_submenu(YahooFriend *f, PurpleConnection *gc) {
-	GList *m = NULL;
-	PurpleMenuAction *act;
-	YahooData *yd = (YahooData *) gc->proto_data;
-
-	if (yd->current_status == YAHOO_STATUS_INVISIBLE) {
-		if (f->presence != YAHOO_PRESENCE_ONLINE) {
-			act = purple_menu_action_new(_("Appear Online"),
-			                           PURPLE_CALLBACK(yahoo_presence_settings),
-			                           GINT_TO_POINTER(YAHOO_PRESENCE_ONLINE),
-			                           NULL);
-			m = g_list_append(m, act);
-		} else if (f->presence != YAHOO_PRESENCE_DEFAULT) {
-			act = purple_menu_action_new(_("Appear Offline"),
-			                           PURPLE_CALLBACK(yahoo_presence_settings),
-			                           GINT_TO_POINTER(YAHOO_PRESENCE_DEFAULT),
-			                           NULL);
-			m = g_list_append(m, act);
-		}
-	}
-
-	if (f->presence == YAHOO_PRESENCE_PERM_OFFLINE) {
-		act = purple_menu_action_new(_("Don't Appear Permanently Offline"),
-		                           PURPLE_CALLBACK(yahoo_presence_settings),
-		                           GINT_TO_POINTER(YAHOO_PRESENCE_DEFAULT),
-		                           NULL);
-		m = g_list_append(m, act);
-	} else {
-		act = purple_menu_action_new(_("Appear Permanently Offline"),
-		                           PURPLE_CALLBACK(yahoo_presence_settings),
-		                           GINT_TO_POINTER(YAHOO_PRESENCE_PERM_OFFLINE),
-		                           NULL);
-		m = g_list_append(m, act);
-	}
-
-	return m;
-}
-
-static void yahoo_doodle_blist_node(PurpleBlistNode *node, gpointer data)
-{
-	PurpleBuddy *b = (PurpleBuddy *)node;
-	PurpleAccount *account = purple_buddy_get_account(b);
-	PurpleConnection *gc = purple_account_get_connection(account);
-
-	yahoo_doodle_initiate(gc, purple_buddy_get_name(b));
-}
-
-static void
-yahoo_userinfo_blist_node(PurpleBlistNode *node, gpointer data)
-{
-	PurpleBuddy *b = (PurpleBuddy *)node;
-	PurpleAccount *account = purple_buddy_get_account(b);
-	PurpleConnection *gc = purple_account_get_connection(account);
-
-	yahoo_set_userinfo_for_buddy(gc, b);
-}
-
-static GList *yahoo_buddy_menu(PurpleBuddy *buddy)
-{
-	GList *m = NULL;
-	PurpleMenuAction *act;
-
-	PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-	YahooData *yd = gc->proto_data;
-	static char buf2[1024];
-	YahooFriend *f;
-
-	f = yahoo_friend_find(gc, purple_buddy_get_name(buddy));
-
-	if (!f && !yd->wm) {
-		act = purple_menu_action_new(_("Add Buddy"),
-		                           PURPLE_CALLBACK(yahoo_addbuddyfrommenu_cb),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-
-		return m;
-
-	}
-
-	if (f && f->status != YAHOO_STATUS_OFFLINE && f->fed == YAHOO_FEDERATION_NONE) {
-		if (!yd->wm) {
-			act = purple_menu_action_new(_("Join in Chat"),
-			                           PURPLE_CALLBACK(yahoo_chat_goto_menu),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		}
-
-		act = purple_menu_action_new(_("Initiate Conference"),
-		                           PURPLE_CALLBACK(yahoo_initiate_conference),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-
-		if (yahoo_friend_get_game(f)) {
-			const char *game = yahoo_friend_get_game(f);
-			char *room;
-			char *t;
-
-			if ((room = strstr(game, "&follow="))) {/* skip ahead to the url */
-				while (*room && *room != '\t')          /* skip to the tab */
-					room++;
-				t = room++;                             /* room as now at the name */
-				while (*t != '\n')
-					t++;                            /* replace the \n with a space */
-				*t = ' ';
-				g_snprintf(buf2, sizeof buf2, "%s", room);
-
-				act = purple_menu_action_new(buf2,
-				                           PURPLE_CALLBACK(yahoo_game),
-				                           NULL, NULL);
-				m = g_list_append(m, act);
-			}
-		}
-	}
-
-	if (f) {
-		act = purple_menu_action_new(_("Presence Settings"), NULL, NULL,
-		                           build_presence_submenu(f, gc));
-		m = g_list_append(m, act);
-
-		if (f->fed == YAHOO_FEDERATION_NONE) {
-			act = purple_menu_action_new(_("Start Doodling"),
-					PURPLE_CALLBACK(yahoo_doodle_blist_node),
-					NULL, NULL);
-			m = g_list_append(m, act);
-		}
-
-		act = purple_menu_action_new(_("Set User Info..."),
-		                           PURPLE_CALLBACK(yahoo_userinfo_blist_node),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-	}
-
-	return m;
-}
-
-GList *yahoo_blist_node_menu(PurpleBlistNode *node)
-{
-	if(PURPLE_BLIST_NODE_IS_BUDDY(node)) {
-		return yahoo_buddy_menu((PurpleBuddy *) node);
-	} else {
-		return NULL;
-	}
-}
-
-static void yahoo_act_id(PurpleConnection *gc, PurpleRequestFields *fields)
-{
-	YahooData *yd = gc->proto_data;
-	const char *name = yd->profiles[purple_request_fields_get_choice(fields, "id")];
-
-	struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_IDACT, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash_str(pkt, 3, name);
-	yahoo_packet_send_and_free(pkt, yd);
-
-	purple_connection_set_display_name(gc, name);
-}
-
-static void
-yahoo_get_inbox_token_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
-		const gchar *token, size_t len, const gchar *error_message)
-{
-	PurpleConnection *gc = user_data;
-	gboolean set_cookie = FALSE;
-	gchar *url;
-	YahooData *yd = gc->proto_data;
-
-	g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc));
-
-	yd->url_datas = g_slist_remove(yd->url_datas, url_data);
-
-	if (error_message != NULL)
-		purple_debug_error("yahoo", "Requesting mail login token failed: %s\n", error_message);
-	else if (len > 0 && token && *token) {
-	 	/* Should we not be hardcoding the rd url? */
-		url = g_strdup_printf(
-			"http://login.yahoo.com/config/reset_cookies_token?"
-			".token=%s"
-			"&.done=http://us.rd.yahoo.com/messenger/client/%%3fhttp://mail.yahoo.com/",
-			token);
-		set_cookie = TRUE;
-	}
-
-	if (!set_cookie) {
-		purple_debug_error("yahoo", "No mail login token; forwarding to login screen.\n");
-		url = g_strdup(yd->jp ? YAHOOJP_MAIL_URL : YAHOO_MAIL_URL);
-	}
-
-	/* Open the mailbox with the parsed url data */
-	purple_notify_uri(gc, url);
-
-	g_free(url);
-}
-
-
-static void yahoo_show_inbox(PurplePluginAction *action)
-{
-	/* Setup a cookie that can be used by the browser */
-	/* XXX I have no idea how this will work with Yahoo! Japan. */
-
-	PurpleConnection *gc = action->context;
-	YahooData *yd = gc->proto_data;
-
-	PurpleUtilFetchUrlData *url_data;
-	const char* base_url = "http://login.yahoo.com";
-	/* use whole URL if using HTTP Proxy */
-	gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
-	gchar *request = g_strdup_printf(
-		"POST %s/config/cookie_token HTTP/1.0\r\n"
-		"Cookie: T=%s; path=/; domain=.yahoo.com; Y=%s;\r\n"
-		"User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
-		"Host: login.yahoo.com\r\n"
-		"Content-Length: 0\r\n\r\n",
-		use_whole_url ? base_url : "",
-		yd->cookie_t, yd->cookie_y);
-
-	url_data = purple_util_fetch_url_request_len_with_account(
-			purple_connection_get_account(gc), base_url, use_whole_url,
-			YAHOO_CLIENT_USERAGENT, TRUE, request, FALSE, -1,
-			yahoo_get_inbox_token_cb, gc);
-
-	g_free(request);
-
-	if (url_data != NULL)
-		yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
-	else {
-		const char *yahoo_mail_url = (yd->jp ? YAHOOJP_MAIL_URL : YAHOO_MAIL_URL);
-		purple_debug_error("yahoo",
-				   "Unable to request mail login token; forwarding to login screen.");
-		purple_notify_uri(gc, yahoo_mail_url);
-	}
-}
-
-static void
-yahoo_set_userinfo_fn(PurplePluginAction *action)
-{
-	yahoo_set_userinfo(action->context);
-}
-
-static void yahoo_show_act_id(PurplePluginAction *action)
-{
-	PurpleRequestFields *fields;
-	PurpleRequestFieldGroup *group;
-	PurpleRequestField *field;
-	PurpleConnection *gc = (PurpleConnection *) action->context;
-	YahooData *yd = purple_connection_get_protocol_data(gc);
-	const char *name = purple_connection_get_display_name(gc);
-	int iter;
-
-	fields = purple_request_fields_new();
-	group = purple_request_field_group_new(NULL);
-	purple_request_fields_add_group(fields, group);
-	field = purple_request_field_choice_new("id", _("Activate which ID?"), 0);
-	purple_request_field_group_add_field(group, field);
-
-	for (iter = 0; yd->profiles[iter]; iter++) {
-		purple_request_field_choice_add(field, yd->profiles[iter]);
-		if (purple_strequal(yd->profiles[iter], name))
-			purple_request_field_choice_set_default_value(field, iter);
-	}
-
-	purple_request_fields(gc, NULL, _("Select the ID you want to activate"), NULL,
-					   fields,
-					   _("OK"), G_CALLBACK(yahoo_act_id),
-					   _("Cancel"), NULL,
-					   purple_connection_get_account(gc), NULL, NULL,
-					   gc);
-}
-
-static void yahoo_show_chat_goto(PurplePluginAction *action)
-{
-	PurpleConnection *gc = (PurpleConnection *) action->context;
-	purple_request_input(gc, NULL, _("Join whom in chat?"), NULL,
-					   "", FALSE, FALSE, NULL,
-					   _("OK"), G_CALLBACK(yahoo_chat_goto),
-					   _("Cancel"), NULL,
-					   purple_connection_get_account(gc), NULL, NULL,
-					   gc);
-}
-
-GList *yahoo_actions(PurplePlugin *plugin, gpointer context) {
-	GList *m = NULL;
-	PurplePluginAction *act;
-
-	act = purple_plugin_action_new(_("Set User Info..."),
-			yahoo_set_userinfo_fn);
-	m = g_list_append(m, act);
-
-	act = purple_plugin_action_new(_("Activate ID..."),
-			yahoo_show_act_id);
-	m = g_list_append(m, act);
-
-	act = purple_plugin_action_new(_("Join User in Chat..."),
-			yahoo_show_chat_goto);
-	m = g_list_append(m, act);
-
-	m = g_list_append(m, NULL);
-	act = purple_plugin_action_new(_("Open Inbox"),
-			yahoo_show_inbox);
-	m = g_list_append(m, act);
-
-	return m;
-}
-
-struct yahoo_sms_carrier_cb_data	{
-	PurpleConnection *gc;
-	char *who;
-	char *what;
-};
-
-static void yahoo_get_sms_carrier_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
-		const gchar *webdata, size_t len, const gchar *error_message)
-{
-	struct yahoo_sms_carrier_cb_data *sms_cb_data = user_data;
-	PurpleConnection *gc = sms_cb_data->gc;
-	YahooData *yd = gc->proto_data;
-	char *status = NULL;
-	char *carrier = NULL;
-	PurpleAccount *account = purple_connection_get_account(gc);
-	PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms_cb_data->who, account);
-
-	yd->url_datas = g_slist_remove(yd->url_datas, url_data);
-
-	if (error_message != NULL) {
-		purple_conversation_write(conv, NULL, _("Can't send SMS. Unable to obtain mobile carrier."), PURPLE_MESSAGE_SYSTEM, time(NULL));
-
-		g_free(sms_cb_data->who);
-		g_free(sms_cb_data->what);
-		g_free(sms_cb_data);
-		return ;
-	}
-	else if (len > 0 && webdata && *webdata) {
-		xmlnode *validate_data_root = xmlnode_from_str(webdata, -1);
-		xmlnode *validate_data_child = xmlnode_get_child(validate_data_root, "mobile_no");
-		const char *mobile_no = xmlnode_get_attrib(validate_data_child, "msisdn");
-
-		validate_data_root = xmlnode_copy(validate_data_child);
-		validate_data_child = xmlnode_get_child(validate_data_root, "status");
-		status = xmlnode_get_data(validate_data_child);
-
-		validate_data_child = xmlnode_get_child(validate_data_root, "carrier");
-		carrier = xmlnode_get_data(validate_data_child);
-
-		purple_debug_info("yahoo", "SMS validate data: %s\n", webdata);
-
-		if (status && g_str_equal(status, "Valid")) {
-			g_hash_table_insert(yd->sms_carrier,
-					g_strdup_printf("+%s", mobile_no), g_strdup(carrier));
-			yahoo_send_im(sms_cb_data->gc, sms_cb_data->who,
-					sms_cb_data->what, PURPLE_MESSAGE_SEND);
-		} else {
-			g_hash_table_insert(yd->sms_carrier,
-					g_strdup_printf("+%s", mobile_no), g_strdup("Unknown"));
-			purple_conversation_write(conv, NULL,
-					_("Can't send SMS. Unknown mobile carrier."),
-					PURPLE_MESSAGE_SYSTEM, time(NULL));
-		}
-
-		xmlnode_free(validate_data_child);
-		xmlnode_free(validate_data_root);
-		g_free(sms_cb_data->who);
-		g_free(sms_cb_data->what);
-		g_free(sms_cb_data);
-		g_free(status);
-		g_free(carrier);
-	}
-}
-
-static void yahoo_get_sms_carrier(PurpleConnection *gc, gpointer data)
-{
-	YahooData *yd = gc->proto_data;
-	PurpleUtilFetchUrlData *url_data;
-	struct yahoo_sms_carrier_cb_data *sms_cb_data;
-	char *validate_request_str = NULL;
-	char *request = NULL;
-	gboolean use_whole_url = FALSE;
-	xmlnode *validate_request_root = NULL;
-	xmlnode *validate_request_child = NULL;
-
-	if(!(sms_cb_data = data))
-		return;
-
-	validate_request_root = xmlnode_new("validate");
-	xmlnode_set_attrib(validate_request_root, "intl", "us");
-	xmlnode_set_attrib(validate_request_root, "version", YAHOO_CLIENT_VERSION);
-	xmlnode_set_attrib(validate_request_root, "qos", "0");
-
-	validate_request_child = xmlnode_new_child(validate_request_root, "mobile_no");
-	xmlnode_set_attrib(validate_request_child, "msisdn", sms_cb_data->who + 1);
-
-	validate_request_str = xmlnode_to_str(validate_request_root, NULL);
-
-	xmlnode_free(validate_request_child);
-	xmlnode_free(validate_request_root);
-
-	request = g_strdup_printf(
-		"POST /mobileno?intl=us&version=%s HTTP/1.1\r\n"
-		"Cookie: T=%s; path=/; domain=.yahoo.com; Y=%s; path=/; domain=.yahoo.com;\r\n"
-		"User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
-		"Host: validate.msg.yahoo.com\r\n"
-		"Content-Length: %" G_GSIZE_FORMAT "\r\n"
-		"Cache-Control: no-cache\r\n\r\n%s",
-		YAHOO_CLIENT_VERSION, yd->cookie_t, yd->cookie_y, strlen(validate_request_str), validate_request_str);
-
-	/* use whole URL if using HTTP Proxy */
-	if ((gc->account->proxy_info) && (gc->account->proxy_info->type == PURPLE_PROXY_HTTP))
-	    use_whole_url = TRUE;
-
-	url_data = purple_util_fetch_url_request_len_with_account(
-			purple_connection_get_account(gc), YAHOO_SMS_CARRIER_URL, use_whole_url,
-			YAHOO_CLIENT_USERAGENT, TRUE, request, FALSE, -1,
-			yahoo_get_sms_carrier_cb, data);
-
-	g_free(request);
-	g_free(validate_request_str);
-
-	if (url_data)
-		yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
-	else {
-		PurpleAccount *account = purple_connection_get_account(gc);
-		PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms_cb_data->who, account);
-		purple_conversation_write(conv, NULL, _("Can't send SMS. Unable to obtain mobile carrier."), PURPLE_MESSAGE_SYSTEM, time(NULL));
-		g_free(sms_cb_data->who);
-		g_free(sms_cb_data->what);
-		g_free(sms_cb_data);
-	}
-}
-
-int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags)
-{
-	YahooData *yd = gc->proto_data;
-	struct yahoo_packet *pkt = NULL;
-	char *msg = yahoo_html_to_codes(what);
-	char *msg2;
-	gboolean utf8 = TRUE;
-	PurpleWhiteboard *wb;
-	int ret = 1;
-	const char *fed_who;
-	gsize lenb = 0;
-	glong lenc = 0;
-	struct yahoo_p2p_data *p2p_data;
-	YahooFederation fed = YAHOO_FEDERATION_NONE;
-	msg2 = yahoo_string_encode(gc, msg, &utf8);
-
-	if(msg2) {
-		lenb = strlen(msg2);
-		lenc = g_utf8_strlen(msg2, -1);
-
-		if(lenb > YAHOO_MAX_MESSAGE_LENGTH_BYTES || lenc > YAHOO_MAX_MESSAGE_LENGTH_CHARS) {
-			purple_debug_info("yahoo", "Message too big.  Length is %" G_GSIZE_FORMAT
-					" bytes, %ld characters.  Max is %d bytes, %d chars."
-					"  Message is '%s'.\n", lenb, lenc, YAHOO_MAX_MESSAGE_LENGTH_BYTES,
-					YAHOO_MAX_MESSAGE_LENGTH_CHARS, msg2);
-			g_free(msg);
-			g_free(msg2);
-			return -E2BIG;
-		}
-	}
-
-	fed = yahoo_get_federation_from_name(who);
-
-	if (who[0] == '+') {
-		/* we have an sms to be sent */
-		gchar *carrier = NULL;
-		const char *alias = NULL;
-		PurpleAccount *account = purple_connection_get_account(gc);
-		PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, account);
-
-		carrier = g_hash_table_lookup(yd->sms_carrier, who);
-		if (!carrier) {
-			struct yahoo_sms_carrier_cb_data *sms_cb_data;
-			sms_cb_data = g_malloc(sizeof(struct yahoo_sms_carrier_cb_data));
-			sms_cb_data->gc = gc;
-			sms_cb_data->who = g_strdup(who);
-			sms_cb_data->what = g_strdup(what);
-
-			purple_conversation_write(conv, NULL, _("Getting mobile carrier to send the SMS."), PURPLE_MESSAGE_SYSTEM, time(NULL));
-
-			yahoo_get_sms_carrier(gc, sms_cb_data);
-
-			g_free(msg);
-			g_free(msg2);
-			return ret;
-		}
-		else if( strcmp(carrier,"Unknown") == 0 ) {
-			purple_conversation_write(conv, NULL, _("Can't send SMS. Unknown mobile carrier."), PURPLE_MESSAGE_SYSTEM, time(NULL));
-
-			g_free(msg);
-			g_free(msg2);
-			return -1;
-		}
-
-		alias = purple_account_get_alias(account);
-		pkt = yahoo_packet_new(YAHOO_SERVICE_SMS_MSG, YAHOO_STATUS_AVAILABLE, yd->session_id);
-		yahoo_packet_hash(pkt, "sssss",
-			1, purple_connection_get_display_name(gc),
-			69, alias,
-			5, who + 1,
-			68, carrier,
-			14, msg2);
-		yahoo_packet_send_and_free(pkt, yd);
-
-		g_free(msg);
-		g_free(msg2);
-
-		return ret;
-	}
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE, yd->session_id);
-	fed_who = who;
-	switch (fed) {
-		case YAHOO_FEDERATION_MSN:
-		case YAHOO_FEDERATION_OCS:
-		case YAHOO_FEDERATION_IBM:
-		case YAHOO_FEDERATION_PBX:
-			fed_who += 4;
-			break;
-		case YAHOO_FEDERATION_NONE:
-		default:
-			break;
-	}
-	yahoo_packet_hash(pkt, "ss", 1, purple_connection_get_display_name(gc), 5, fed_who);
-	if (fed)
-		yahoo_packet_hash_int(pkt, 241, fed);
-
-	if (utf8)
-		yahoo_packet_hash_str(pkt, 97, "1");
-	yahoo_packet_hash_str(pkt, 14, msg2);
-
-	/*
-	 * IMVironment.
-	 *
-	 * If this message is to a user who is also Doodling with the local user,
-	 * format the chat packet with the correct IMV information (thanks Yahoo!)
-	 *
-	 * Otherwise attempt to use the same IMVironment as the remote user,
-	 * just so that we don't inadvertantly reset their IMVironment back
-	 * to nothing.
-	 *
-	 * If they have not set an IMVironment, then use the default.
-	 */
-	wb = purple_whiteboard_get_session(gc->account, who);
-	if (wb)
-		yahoo_packet_hash_str(pkt, 63, DOODLE_IMV_KEY);
-	else
-	{
-		const char *imv;
-		imv = g_hash_table_lookup(yd->imvironments, who);
-		if (imv != NULL)
-			yahoo_packet_hash_str(pkt, 63, imv);
-		else
-			yahoo_packet_hash_str(pkt, 63, ";0");
-	}
-
-	yahoo_packet_hash_str(pkt,   64, "0"); /* no idea */
-	yahoo_packet_hash_str(pkt, 1002, "1"); /* no idea, Yahoo 6 or later only it seems */
-	if (!yd->picture_url)
-		yahoo_packet_hash_str(pkt, 206, "0"); /* 0 = no picture, 2 = picture, maybe 1 = avatar? */
-	else
-		yahoo_packet_hash_str(pkt, 206, "2");
-
-	/* We may need to not send any packets over 2000 bytes, but I'm not sure yet. */
-	if ((YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt)) <= 2000) {
-		/* if p2p link exists, send through it. To-do: key 15, time value to be sent in case of p2p */
-		if( (p2p_data = g_hash_table_lookup(yd->peers, who)) && !fed) {
-			yahoo_packet_hash_int(pkt, 11, p2p_data->session_id);
-			yahoo_p2p_write_pkt(p2p_data->source, pkt);
-		}
-		else	{
-			yahoo_packet_send(pkt, yd);
-			if(!fed)
-				yahoo_send_p2p_pkt(gc, who, 0);		/* send p2p packet, with val_13=0 */
-		}
-	}
-	else
-		ret = -E2BIG;
-
-	yahoo_packet_free(pkt);
-
-	g_free(msg);
-	g_free(msg2);
-
-	return ret;
-}
-
-unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state)
-{
-	YahooData *yd = gc->proto_data;
-	struct yahoo_p2p_data *p2p_data;
-	YahooFederation fed = YAHOO_FEDERATION_NONE;
-	struct yahoo_packet *pkt = NULL;
-
-	fed = yahoo_get_federation_from_name(who);
-
-	/* Don't do anything if sms is being typed */
-	if( strncmp(who, "+", 1) == 0 )
-		return 0;
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YAHOO_STATUS_TYPING, yd->session_id);
-
-	/* check to see if p2p link exists, send through it */
-	if( (p2p_data = g_hash_table_lookup(yd->peers, who)) && !fed) {
-		yahoo_packet_hash(pkt, "sssssis", 49, "TYPING", 1, purple_connection_get_display_name(gc),
-	                  14, " ", 13, state == PURPLE_TYPING ? "1" : "0",
-	                  5, who, 11, p2p_data->session_id, 1002, "1");	/* To-do: key 15 to be sent in case of p2p */
-		yahoo_p2p_write_pkt(p2p_data->source, pkt);
-		yahoo_packet_free(pkt);
-	}
-	else	{	/* send through yahoo server */
-
-		const char *fed_who = who;
-		switch (fed) {
-			case YAHOO_FEDERATION_MSN:
-			case YAHOO_FEDERATION_OCS:
-			case YAHOO_FEDERATION_IBM:
-			case YAHOO_FEDERATION_PBX:
-				fed_who += 4;
-				break;
-			case YAHOO_FEDERATION_NONE:
-			default:
-				break;
-		}
-
-		yahoo_packet_hash(pkt, "ssssss", 49, "TYPING", 1, purple_connection_get_display_name(gc),
-                  14, " ", 13, state == PURPLE_TYPING ? "1" : "0",
-                  5, fed_who, 1002, "1");
-        if (fed)
-        	yahoo_packet_hash_int(pkt, 241, fed);
-		yahoo_packet_send_and_free(pkt, yd);
-	}
-
-	return 0;
-}
-
-static void yahoo_session_presence_remove(gpointer key, gpointer value, gpointer data)
-{
-	YahooFriend *f = value;
-	if (f && f->presence == YAHOO_PRESENCE_ONLINE)
-		f->presence = YAHOO_PRESENCE_DEFAULT;
-}
-
-void yahoo_set_status(PurpleAccount *account, PurpleStatus *status)
-{
-	PurpleConnection *gc;
-	PurplePresence *presence;
-	YahooData *yd;
-	struct yahoo_packet *pkt;
-	int old_status;
-	const char *msg = NULL;
-	char *tmp = NULL;
-	char *conv_msg = NULL;
-	gboolean utf8 = TRUE;
-
-	if (!purple_status_is_active(status))
-		return;
-
-	gc = purple_account_get_connection(account);
-	presence = purple_status_get_presence(status);
-	yd = (YahooData *)gc->proto_data;
-	old_status = yd->current_status;
-
-	yd->current_status = get_yahoo_status_from_purple_status(status);
-
-	if (yd->current_status == YAHOO_STATUS_CUSTOM)
-	{
-		msg = purple_status_get_attr_string(status, "message");
-
-		if (purple_status_is_available(status)) {
-			tmp = yahoo_string_encode(gc, msg, &utf8);
-			conv_msg = purple_markup_strip_html(tmp);
-			g_free(tmp);
-		} else {
-			if ((msg == NULL) || (*msg == '\0'))
-				msg = _("Away");
-			tmp = yahoo_string_encode(gc, msg, &utf8);
-			conv_msg = purple_markup_strip_html(tmp);
-			g_free(tmp);
-		}
-	}
-
-	if (yd->current_status == YAHOO_STATUS_INVISIBLE) {
-		pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBLE_TOGGLE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-		yahoo_packet_hash_str(pkt, 13, "2");
-		yahoo_packet_send_and_free(pkt, yd);
-
-		return;
-	}
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash_int(pkt, 10, yd->current_status);
-
-	if (yd->current_status == YAHOO_STATUS_CUSTOM) {
-		yahoo_packet_hash_str(pkt, 97, utf8 ? "1" : 0);
-		yahoo_packet_hash_str(pkt, 19, conv_msg);
-	} else {
-		yahoo_packet_hash_str(pkt, 19, "");
-	}
-
-	g_free(conv_msg);
-
-	if (purple_presence_is_idle(presence))
-		yahoo_packet_hash_str(pkt, 47, "2");
-	else	{
-		if (!purple_status_is_available(status))
-			yahoo_packet_hash_str(pkt, 47, "1");
-		else
-			yahoo_packet_hash_str(pkt, 47, "0");
-	}
-
-	yahoo_packet_send_and_free(pkt, yd);
-
-	if (old_status == YAHOO_STATUS_INVISIBLE) {
-		pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBLE_TOGGLE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-		yahoo_packet_hash_str(pkt, 13, "1");
-		yahoo_packet_send_and_free(pkt, yd);
-
-		/* Any per-session presence settings are removed */
-		g_hash_table_foreach(yd->friends, yahoo_session_presence_remove, NULL);
-
-	}
-}
-
-void yahoo_set_idle(PurpleConnection *gc, int idle)
-{
-	YahooData *yd = gc->proto_data;
-	struct yahoo_packet *pkt = NULL;
-	char *msg = NULL, *msg2 = NULL;
-	PurpleStatus *status = NULL;
-	gboolean invisible = FALSE;
-
-	if (idle && yd->current_status != YAHOO_STATUS_CUSTOM)
-		yd->current_status = YAHOO_STATUS_IDLE;
-	else if (!idle && yd->current_status == YAHOO_STATUS_IDLE) {
-		status = purple_presence_get_active_status(purple_account_get_presence(purple_connection_get_account(gc)));
-		yd->current_status = get_yahoo_status_from_purple_status(status);
-	}
-
-	invisible = (yd->current_status == YAHOO_STATUS_INVISIBLE);
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	if (!idle && invisible)
-		yahoo_packet_hash_int(pkt, 10, YAHOO_STATUS_AVAILABLE);
-	else
-		yahoo_packet_hash_int(pkt, 10, yd->current_status);
-
-	if (yd->current_status == YAHOO_STATUS_CUSTOM) {
-		const char *tmp;
-		if (status == NULL)
-			status = purple_presence_get_active_status(purple_account_get_presence(purple_connection_get_account(gc)));
-		tmp = purple_status_get_attr_string(status, "message");
-		if (tmp != NULL) {
-			gboolean utf8 = TRUE;
-			msg = yahoo_string_encode(gc, tmp, &utf8);
-			msg2 = purple_markup_strip_html(msg);
-			yahoo_packet_hash_str(pkt, 97, utf8 ? "1" : 0);
-			yahoo_packet_hash_str(pkt, 19, msg2);
-		} else {
-			/* get_yahoo_status_from_purple_status() returns YAHOO_STATUS_CUSTOM for
-			 * the generic away state (YAHOO_STATUS_TYPE_AWAY) with no message */
-			yahoo_packet_hash_str(pkt, 19, _("Away"));
-		}
-	} else {
-		yahoo_packet_hash_str(pkt, 19, "");
-	}
-
-	if (idle)
-		yahoo_packet_hash_str(pkt, 47, "2");
-	else if (yd->current_status == YAHOO_STATUS_CUSTOM &&
-			!purple_status_is_available(status))
-		/* We are still unavailable in this case.
-		 * Make sure Yahoo knows that */
-		yahoo_packet_hash_str(pkt, 47, "1");
-
-	yahoo_packet_send_and_free(pkt, yd);
-
-	g_free(msg);
-	g_free(msg2);
-}
-
-GList *yahoo_status_types(PurpleAccount *account)
-{
-	PurpleStatusType *type;
-	GList *types = NULL;
-
-	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, YAHOO_STATUS_TYPE_AVAILABLE,
-	                                       NULL, TRUE, TRUE, FALSE,
-	                                       "message", _("Message"),
-	                                       purple_value_new(PURPLE_TYPE_STRING), NULL);
-	types = g_list_append(types, type);
-
-	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_AWAY,
-	                                       NULL, TRUE, TRUE, FALSE,
-	                                       "message", _("Message"),
-	                                       purple_value_new(PURPLE_TYPE_STRING), NULL);
-	types = g_list_append(types, type);
-
-	type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_BRB, _("Be Right Back"), TRUE);
-	types = g_list_append(types, type);
-
-	type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE, YAHOO_STATUS_TYPE_BUSY,
-	                                       _("Busy"), TRUE, TRUE, FALSE,
-	                                       "message", _("Message"),
-	                                       purple_value_new(PURPLE_TYPE_STRING), NULL);
-	types = g_list_append(types, type);
-
-	type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_NOTATHOME, _("Not at Home"), TRUE);
-	types = g_list_append(types, type);
-
-	type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_NOTATDESK, _("Not at Desk"), TRUE);
-	types = g_list_append(types, type);
-
-	type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_NOTINOFFICE, _("Not in Office"), TRUE);
-	types = g_list_append(types, type);
-
-	type = purple_status_type_new(PURPLE_STATUS_UNAVAILABLE, YAHOO_STATUS_TYPE_ONPHONE, _("On the Phone"), TRUE);
-	types = g_list_append(types, type);
-
-	type = purple_status_type_new(PURPLE_STATUS_EXTENDED_AWAY, YAHOO_STATUS_TYPE_ONVACATION, _("On Vacation"), TRUE);
-	types = g_list_append(types, type);
-
-	type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_OUTTOLUNCH, _("Out to Lunch"), TRUE);
-	types = g_list_append(types, type);
-
-	type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_STEPPEDOUT, _("Stepped Out"), TRUE);
-	types = g_list_append(types, type);
-
-
-	type = purple_status_type_new(PURPLE_STATUS_INVISIBLE, YAHOO_STATUS_TYPE_INVISIBLE, NULL, TRUE);
-	types = g_list_append(types, type);
-
-	type = purple_status_type_new(PURPLE_STATUS_OFFLINE, YAHOO_STATUS_TYPE_OFFLINE, NULL, TRUE);
-	types = g_list_append(types, type);
-
-	type = purple_status_type_new_full(PURPLE_STATUS_MOBILE, YAHOO_STATUS_TYPE_MOBILE, NULL, FALSE, FALSE, TRUE);
-	types = g_list_append(types, type);
-
-	return types;
-}
-
-void yahoo_keepalive(PurpleConnection *gc)
-{
-	struct yahoo_packet *pkt;
-	YahooData *yd = gc->proto_data;
-	time_t now = time(NULL);
-
-	/* We're only allowed to send a ping once an hour or the servers will boot us */
-	if ((now - yd->last_ping) >= PING_TIMEOUT) {
-		yd->last_ping = now;
-
-		/* The native client will only send PING or CHATPING */
-		if (yd->chat_online) {
-			if (yd->wm) {
-				ycht_chat_send_keepalive(yd->ycht);
-			} else {
-				pkt = yahoo_packet_new(YAHOO_SERVICE_CHATPING, YAHOO_STATUS_AVAILABLE, yd->session_id);
-				yahoo_packet_hash_str(pkt, 109, purple_connection_get_display_name(gc));
-				yahoo_packet_send_and_free(pkt, yd);
-			}
-		} else {
-			pkt = yahoo_packet_new(YAHOO_SERVICE_PING, YAHOO_STATUS_AVAILABLE, yd->session_id);
-			yahoo_packet_send_and_free(pkt, yd);
-		}
-	}
-
-	if ((now - yd->last_keepalive) >= KEEPALIVE_TIMEOUT) {
-		yd->last_keepalive = now;
-		pkt = yahoo_packet_new(YAHOO_SERVICE_KEEPALIVE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-		yahoo_packet_hash_str(pkt, 0, purple_connection_get_display_name(gc));
-		yahoo_packet_send_and_free(pkt, yd);
-	}
-
-}
-
-void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g)
-{
-	YahooData *yd = (YahooData *)gc->proto_data;
-	struct yahoo_packet *pkt;
-	const char *group = NULL;
-	char *group2;
-	const char *bname;
-	const char *fed_bname;
-	YahooFederation fed = YAHOO_FEDERATION_NONE;
-
-	if (!yd->logged_in)
-		return;
-
-	fed_bname = bname = purple_buddy_get_name(buddy);
-	if (!purple_privacy_check(purple_connection_get_account(gc), bname))
-		return;
-
-	fed = yahoo_get_federation_from_name(bname);
-	if (fed != YAHOO_FEDERATION_NONE)
-		fed_bname += 4;
-
-	g = purple_buddy_get_group(buddy);
-	if (g)
-		group = purple_group_get_name(g);
-	else
-		group = "Buddies";
-
-	group2 = yahoo_string_encode(gc, group, NULL);
-	pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	if (fed) {
-		yahoo_packet_hash(pkt, "sssssssisss",
-						  14, "",
-						  65, group2,
-						  97, "1",
-						  1, purple_connection_get_display_name(gc),
-						  302, "319",
-						  300, "319",
-						  7, fed_bname,
-						  241, fed,
-						  334, "0",
-						  301, "319",
-						  303, "319"
-		);
-	}
-	else {
-		yahoo_packet_hash(pkt, "ssssssssss",
-						  14, "",
-						  65, group2,
-						  97, "1",
-						  1, purple_connection_get_display_name(gc),
-						  302, "319",
-						  300, "319",
-						  7, fed_bname,
-						  334, "0",
-						  301, "319",
-						  303, "319"
-		);
-	}
-
-	yahoo_packet_send_and_free(pkt, yd);
-	g_free(group2);
-}
-
-void yahoo_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
-{
-	YahooData *yd = (YahooData *)gc->proto_data;
-	struct yahoo_packet *pkt;
-	GSList *buddies, *l;
-	PurpleGroup *g;
-	gboolean remove = TRUE;
-	char *cg;
-	const char *bname, *gname;
-	YahooFriend *f = NULL;
-	YahooFederation fed = YAHOO_FEDERATION_NONE;
-
-	bname = purple_buddy_get_name(buddy);
-	f = yahoo_friend_find(gc, bname);
-	if (!f)
-		return;
-	fed = f->fed;
-
-	gname = purple_group_get_name(group);
-	buddies = purple_find_buddies(purple_connection_get_account(gc), bname);
-	for (l = buddies; l; l = l->next) {
-		g = purple_buddy_get_group(l->data);
-		if (purple_utf8_strcasecmp(gname, purple_group_get_name(g))) {
-			remove = FALSE;
-			break;
-		}
-	}
-
-	g_slist_free(buddies);
-
-	if (remove) {
-		g_hash_table_remove(yd->friends, bname);
-		f = NULL; /* f no longer valid - Just making it clear */
-	}
-
-	cg = yahoo_string_encode(gc, gname, NULL);
-	pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	switch (fed) {
-		case YAHOO_FEDERATION_MSN:
-		case YAHOO_FEDERATION_OCS:
-		case YAHOO_FEDERATION_IBM:
-			bname += 4;
-			break;
-		case YAHOO_FEDERATION_NONE:
-		default:
-			break;
-	}
-
-	yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc),
-	                  7, bname, 65, cg);
-	if (fed)
-		yahoo_packet_hash_int(pkt, 241, fed);
-	yahoo_packet_send_and_free(pkt, yd);
-	g_free(cg);
-}
-
-void yahoo_add_deny(PurpleConnection *gc, const char *who) {
-	YahooData *yd = (YahooData *)gc->proto_data;
-	struct yahoo_packet *pkt;
-	YahooFederation fed = YAHOO_FEDERATION_NONE;
-
-	if (!yd->logged_in)
-		return;
-
-	if (!who || who[0] == '\0')
-		return;
-
-	fed = yahoo_get_federation_from_name(who);
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	if(fed)
-		yahoo_packet_hash(pkt, "ssis", 1, purple_connection_get_display_name(gc), 7, who+4, 241, fed, 13, "1");
-	else
-		yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), 7, who, 13, "1");
-
-	yahoo_packet_send_and_free(pkt, yd);
-}
-
-void yahoo_rem_deny(PurpleConnection *gc, const char *who) {
-	YahooData *yd = (YahooData *)gc->proto_data;
-	struct yahoo_packet *pkt;
-	YahooFederation fed = YAHOO_FEDERATION_NONE;
-
-	if (!yd->logged_in)
-		return;
-
-	if (!who || who[0] == '\0')
-		return;
-	fed = yahoo_get_federation_from_name(who);
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	if(fed)
-		yahoo_packet_hash(pkt, "ssis", 1, purple_connection_get_display_name(gc), 7, who+4, 241, fed, 13, "2");
-	else
-		yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), 7, who, 13, "2");
-
-	yahoo_packet_send_and_free(pkt, yd);
-}
-
-void yahoo_set_permit_deny(PurpleConnection *gc)
-{
-	PurpleAccount *account;
-	GSList *deny;
-
-	account = purple_connection_get_account(gc);
-
-	switch (account->perm_deny)
-	{
-		case PURPLE_PRIVACY_ALLOW_ALL:
-			for (deny = account->deny; deny; deny = deny->next)
-				yahoo_rem_deny(gc, deny->data);
-			break;
-
-		case PURPLE_PRIVACY_ALLOW_BUDDYLIST:
-		case PURPLE_PRIVACY_ALLOW_USERS:
-		case PURPLE_PRIVACY_DENY_USERS:
-		case PURPLE_PRIVACY_DENY_ALL:
-			for (deny = account->deny; deny; deny = deny->next)
-				yahoo_add_deny(gc, deny->data);
-			break;
-	}
-}
-
-void yahoo_change_buddys_group(PurpleConnection *gc, const char *who,
-				   const char *old_group, const char *new_group)
-{
-	YahooData *yd = gc->proto_data;
-	struct yahoo_packet *pkt;
-	char *gpn, *gpo;
-	YahooFriend *f = yahoo_friend_find(gc, who);
-	const char *temp = NULL;
-
-	/* Step 0:  If they aren't on the server list anyway,
-	 *          don't bother letting the server know.
-	 */
-	if (!f)
-		return;
-
-	if(f->fed) {
-		temp = who+4;
-	} else
-		temp = who;
-
-	/* If old and new are the same, we would probably
-	 * end up deleting the buddy, which would be bad.
-	 * This might happen because of the charset conversation.
-	 */
-	gpn = yahoo_string_encode(gc, new_group, NULL);
-	gpo = yahoo_string_encode(gc, old_group, NULL);
-	if (!strcmp(gpn, gpo)) {
-		g_free(gpn);
-		g_free(gpo);
-		return;
-	}
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CHGRP_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	if(f->fed)
-		yahoo_packet_hash(pkt, "ssssissss", 1, purple_connection_get_display_name(gc),
-	                  302, "240", 300, "240", 7, temp, 241, f->fed, 224, gpo, 264, gpn, 301,
-	                  "240", 303, "240");
-	else
-		yahoo_packet_hash(pkt, "ssssssss", 1, purple_connection_get_display_name(gc),
-	                  302, "240", 300, "240", 7, temp, 224, gpo, 264, gpn, 301,
-	                  "240", 303, "240");
-	yahoo_packet_send_and_free(pkt, yd);
-
-	g_free(gpn);
-	g_free(gpo);
-}
-
-void yahoo_rename_group(PurpleConnection *gc, const char *old_name,
-							   PurpleGroup *group, GList *moved_buddies)
-{
-	YahooData *yd = gc->proto_data;
-	struct yahoo_packet *pkt;
-	char *gpn, *gpo;
-
-	gpn = yahoo_string_encode(gc, purple_group_get_name(group), NULL);
-	gpo = yahoo_string_encode(gc, old_name, NULL);
-	if (!strcmp(gpn, gpo)) {
-		g_free(gpn);
-		g_free(gpo);
-		return;
-	}
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_GROUPRENAME, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc),
-	                  65, gpo, 67, gpn);
-	yahoo_packet_send_and_free(pkt, yd);
-	g_free(gpn);
-	g_free(gpo);
-}
-
-/********************************* Commands **********************************/
-
-PurpleCmdRet
-yahoopurple_cmd_buzz(PurpleConversation *c, const gchar *cmd, gchar **args, gchar **error, void *data) {
-	PurpleAccount *account = purple_conversation_get_account(c);
-
-	if (*args && args[0])
-		return PURPLE_CMD_RET_FAILED;
-
-	purple_prpl_send_attention(account->gc, c->name, YAHOO_BUZZ);
-
-	return PURPLE_CMD_RET_OK;
-}
-
-PurpleCmdRet
-yahoopurple_cmd_chat_join(PurpleConversation *conv, const char *cmd,
-                        char **args, char **error, void *data)
-{
-	GHashTable *comp;
-	PurpleConnection *gc;
-
-	if (!args || !args[0])
-		return PURPLE_CMD_RET_FAILED;
-
-	gc = purple_conversation_get_gc(conv);
-	purple_debug_info("yahoo", "Trying to join %s \n", args[0]);
-
-	comp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-	g_hash_table_replace(comp, g_strdup("room"), g_ascii_strdown(args[0], -1));
-	g_hash_table_replace(comp, g_strdup("type"), g_strdup("Chat"));
-
-	yahoo_c_join(gc, comp);
-
-	g_hash_table_destroy(comp);
-	return PURPLE_CMD_RET_OK;
-}
-
-PurpleCmdRet
-yahoopurple_cmd_chat_list(PurpleConversation *conv, const char *cmd,
-                        char **args, char **error, void *data)
-{
-	PurpleAccount *account = purple_conversation_get_account(conv);
-	if (*args && args[0])
-		return PURPLE_CMD_RET_FAILED;
-	purple_roomlist_show_with_account(account);
-	return PURPLE_CMD_RET_OK;
-}
-
-gboolean yahoo_offline_message(const PurpleBuddy *buddy)
-{
-	return TRUE;
-}
-
-gboolean yahoo_send_attention(PurpleConnection *gc, const char *username, guint type)
-{
-	PurpleConversation *c;
-
-	c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
-			username, gc->account);
-
-	g_return_val_if_fail(c != NULL, FALSE);
-
-	purple_debug_info("yahoo", "Sending <ding> on account %s to buddy %s.\n",
-			username, c->name);
-	purple_conv_im_send_with_flags(PURPLE_CONV_IM(c), "<ding>", PURPLE_MESSAGE_INVISIBLE);
-
-	return TRUE;
-}
-
-GList *yahoo_attention_types(PurpleAccount *account)
-{
-	static GList *list = NULL;
-
-	if (!list) {
-		/* Yahoo only supports one attention command: the 'buzz'. */
-		/* This is index number YAHOO_BUZZ. */
-		list = g_list_append(list, purple_attention_type_new("Buzz", _("Buzz"),
-				_("%s has buzzed you!"), _("Buzzing %s...")));
-	}
-
-	return list;
-}
-
--- a/libpurple/protocols/yahoo/libymsg.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,402 +0,0 @@
-/**
- * @file libymsg.h The Yahoo! and Yahoo! JAPAN Protocol Plugins
- *
- * 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 _LIBYMSG_H_
-#define _LIBYMSG_H_
-
-#include "circbuffer.h"
-#include "cmds.h"
-#include "prpl.h"
-#include "network.h"
-
-#define YAHOO_PAGER_HOST_REQ_URL "http://vcs2.msg.yahoo.com/capacity"
-#define YAHOO_PAGER_HOST_FALLBACK "scsa.msg.yahoo.com"
-#define YAHOO_PAGER_PORT 5050
-#define YAHOO_PAGER_PORT_P2P 5101
-#define YAHOO_LOGIN_URL "https://login.yahoo.com/config/pwtoken_login?src=ymsgr&ts=&token=%s"
-#define YAHOO_TOKEN_URL "https://login.yahoo.com/config/pwtoken_get?src=ymsgr&ts=&login=%s&passwd=%s&chal=%s"
-#define YAHOO_P2P_KEEPALIVE_SECS 300
-#define YAHOO_P2P_SERVER_TIMEOUT 10
-#define YAHOO_PROFILE_URL "http://profiles.yahoo.com/"
-#define YAHOO_MAIL_URL "http://rd.yahoo.com/messenger/client/?http://mail.yahoo.com/"
-#define YAHOO_XFER_HOST "filetransfer.msg.yahoo.com"
-#define YAHOO_XFER_PORT 80
-#define YAHOO_XFER_RELAY_HOST "relay.msg.yahoo.com"
-#define YAHOO_XFER_RELAY_PORT 80
-#define YAHOO_ROOMLIST_URL "http://insider.msg.yahoo.com/ycontent/"
-#define YAHOO_ROOMLIST_LOCALE "us"
-
-/* Yahoo! JAPAN stuff */
-#define YAHOOJP_PAGER_HOST_REQ_URL "http://cs1.yahoo.co.jp/capacity"
-#define YAHOOJP_TOKEN_URL "https://login.yahoo.co.jp/config/pwtoken_get?src=ymsgr&ts=&login=%s&passwd=%s&chal=%s"
-#define YAHOOJP_LOGIN_URL "https://login.yahoo.co.jp/config/pwtoken_login?src=ymsgr&ts=&token=%s"
-#define YAHOOJP_PROFILE_URL "http://profiles.yahoo.co.jp/"
-#define YAHOOJP_MAIL_URL "http://mail.yahoo.co.jp/"
-#define YAHOOJP_XFER_HOST "filetransfer.msg.yahoo.co.jp"
-#define YAHOOJP_WEBCAM_HOST "wc.yahoo.co.jp"
-/* not sure, must test: */
-#define YAHOOJP_XFER_RELAY_HOST "relay.msg.yahoo.co.jp"
-#define YAHOOJP_XFER_RELAY_PORT 80
-#define YAHOOJP_ROOMLIST_URL "http://insider.msg.yahoo.co.jp/ycontent/"
-#define YAHOOJP_ROOMLIST_LOCALE "ja"
-
-#define YAHOO_AUDIBLE_URL "http://l.yimg.com/pu/dl/aud"
-
-#define WEBMESSENGER_URL "http://login.yahoo.com/config/login?.src=pg"
-
-#define YAHOO_SMS_CARRIER_URL "http://validate.msg.yahoo.com"
-
-#define YAHOO_USERINFO_URL "http://address.yahoo.com/yab/us?v=XM&sync=1&tags=short&useutf8=1&noclear=1&legenc=codepage-1252"
-#define YAHOOJP_USERINFO_URL "http://address.yahoo.co.jp/yab/jp?v=XM&sync=1&tags=short&useutf8=1&noclear=1&legenc=codepage-1252"
-
-#define YAHOO_PICURL_SETTING "picture_url"
-#define YAHOO_PICCKSUM_SETTING "picture_checksum"
-#define YAHOO_PICEXPIRE_SETTING "picture_expire"
-
-#define YAHOO_STATUS_TYPE_OFFLINE "offline"
-#define YAHOO_STATUS_TYPE_AVAILABLE "available"
-#define YAHOO_STATUS_TYPE_BRB "brb"
-#define YAHOO_STATUS_TYPE_BUSY "busy"
-#define YAHOO_STATUS_TYPE_NOTATHOME "notathome"
-#define YAHOO_STATUS_TYPE_NOTATDESK "notatdesk"
-#define YAHOO_STATUS_TYPE_NOTINOFFICE "notinoffice"
-#define YAHOO_STATUS_TYPE_ONPHONE "onphone"
-#define YAHOO_STATUS_TYPE_ONVACATION "onvacation"
-#define YAHOO_STATUS_TYPE_OUTTOLUNCH "outtolunch"
-#define YAHOO_STATUS_TYPE_STEPPEDOUT "steppedout"
-#define YAHOO_STATUS_TYPE_AWAY "away"
-#define YAHOO_STATUS_TYPE_INVISIBLE "invisible"
-#define YAHOO_STATUS_TYPE_MOBILE "mobile"
-
-#define YAHOO_CLIENT_VERSION_ID "4194239"
-#define YAHOO_CLIENT_VERSION "9.0.0.2162"
-
-#define YAHOOJP_CLIENT_VERSION_ID "4186047"
-#define YAHOOJP_CLIENT_VERSION "9.0.0.1727"
-
-#define YAHOO_CLIENT_USERAGENT "Mozilla/5.0"
-#define YAHOO_CLIENT_USERAGENT_ALIAS "Mozilla/4.0 (compatible; MSIE 5.5)"
-
-/* Index into attention types list. */
-#define YAHOO_BUZZ 0
-
-typedef enum {
-	YAHOO_PKT_TYPE_SERVER = 0,
-	YAHOO_PKT_TYPE_P2P
-} yahoo_pkt_type;
-
-typedef enum {
-	YAHOO_P2P_WE_ARE_CLIENT =0,
-	YAHOO_P2P_WE_ARE_SERVER
-} yahoo_p2p_connection_type;
-
-enum yahoo_status {
-	YAHOO_STATUS_AVAILABLE = 0,
-	YAHOO_STATUS_BRB,
-	YAHOO_STATUS_BUSY,
-	YAHOO_STATUS_NOTATHOME,
-	YAHOO_STATUS_NOTATDESK,
-	YAHOO_STATUS_NOTINOFFICE,
-	YAHOO_STATUS_ONPHONE,
-	YAHOO_STATUS_ONVACATION,
-	YAHOO_STATUS_OUTTOLUNCH,
-	YAHOO_STATUS_STEPPEDOUT,
-	YAHOO_STATUS_P2P = 11,
-	YAHOO_STATUS_INVISIBLE = 12,
-	YAHOO_STATUS_CUSTOM = 99,
-	YAHOO_STATUS_IDLE = 999,
-	YAHOO_STATUS_WEBLOGIN = 0x5a55aa55,
-	YAHOO_STATUS_OFFLINE = 0x5a55aa56, /* don't ask */
-	YAHOO_STATUS_TYPING = 0x16,
-	YAHOO_STATUS_DISCONNECTED = -1 /* 0xffffffff; in ymsg 15. doesnt mean the normal sense of 'disconnected' */
-};
-
-/*
- * Yahoo federated networks.  Key 241 in ymsg.
- * If it doesn't exist, it is on Yahoo's netowrk.
- * It if does exist, send to another IM network.
- */
-
-typedef enum {
-	YAHOO_FEDERATION_NONE = 0, /* No federation - Yahoo! network */
-	YAHOO_FEDERATION_OCS = 1,  /* LCS or OCS private networks */
-	YAHOO_FEDERATION_MSN = 2,  /* MSN or Windows Live network */
-	YAHOO_FEDERATION_IBM = 9,  /* IBM/Sametime network */
-	YAHOO_FEDERATION_PBX = 100 /* Yahoo! Pingbox service */
-} YahooFederation;
-
-
-struct yahoo_buddy_icon_upload_data {
-	PurpleConnection *gc;
-	GString *str;
-	char *filename;
-	int pos;
-	int fd;
-	guint watcher;
-};
-
-struct yahoo_p2p_data	{
-	PurpleConnection *gc;
-	char *host_ip;
-	char *host_username;
-	int val_13;
-	guint input_event;
-	gint source;
-	int session_id;
-	yahoo_p2p_connection_type connection_type;
-};
-
-struct _YchtConn;
-
-typedef struct _YahooPersonalDetails {
-	char *id;
-
-	struct {
-		char *first;
-		char *last;
-		char *middle;
-		char *nick;
-	} names;
-
-	struct {
-		char *work;
-		char *home;
-		char *mobile;
-	} phone;
-} YahooPersonalDetails;
-
-typedef struct {
-	PurpleConnection *gc;
-	int fd;
-	guchar *rxqueue;
-	int rxlen;
-	PurpleCircBuffer *txbuf;
-	guint txhandler;
-	GHashTable *friends;
-
-	char **profiles;  /* Multiple profiles can be associated with an account */
-	YahooPersonalDetails ypd;
-
-	/**
-	 * This is used to keep track of the IMVironment chosen
-	 * by people you talk to.  We don't do very much with
-	 * this right now... but at least now if the remote user
-	 * selects an IMVironment we won't reset it back to the
-	 * default of nothing.
-	 */
-	GHashTable *imvironments;
-
-	int current_status;
-	gboolean logged_in;
-	GString *tmp_serv_blist, *tmp_serv_ilist, *tmp_serv_plist;
-	GSList *confs;
-	unsigned int conf_id; /* just a counter */
-	gboolean chat_online;
-	gboolean in_chat;
-	char *chat_name;
-	char *pending_chat_room;
-	char *pending_chat_id;
-	char *pending_chat_topic;
-	char *pending_chat_goto;
-	char *auth;
-	gsize auth_written;
-	char *cookie_y;
-	char *cookie_t;
-	char *cookie_b;
-	int session_id;
-	gboolean jp;
-	gboolean wm; /* connected w/ web messenger method */
-	/* picture aka buddy icon stuff */
-	char *picture_url;
-	int picture_checksum;
-
-	/* ew. we have to check the icon before we connect,
-	 * but can't upload it til we're connected. */
-	struct yahoo_buddy_icon_upload_data *picture_upload_todo;
-	PurpleProxyConnectData *buddy_icon_connect_data;
-
-	struct _YchtConn *ycht;
-
-	/**
-	 * This linked list contains PurpleUtilFetchUrlData structs
-	 * for when we lookup people profile or photo information.
-	 */
-	GSList *url_datas;
-	GHashTable *xfer_peer_idstring_map;/* Hey, i dont know, but putting this HashTable next to friends gives a run time fault... */
-	GSList *cookies;/* contains all cookies, including _y and _t */
-	PurpleNetworkListenData *listen_data;
-
-	/**
-	 * We may receive a list15 in multiple packets with no prior warning as to how many we'll be getting;
-	 * the server expects us to keep track of the group for which it is sending us contact names.
-	 */
-	char *current_list15_grp;
-	time_t last_ping;
-	time_t last_keepalive;
-	GHashTable *peers;	/* information about p2p data */
-	int yahoo_p2p_timer;
-	int yahoo_local_p2p_server_fd;
-	int yahoo_p2p_server_watcher;
-	GHashTable *sms_carrier;	/* sms carrier data */
-	guint yahoo_p2p_server_timeout_handle;
-} YahooData;
-
-#define YAHOO_MAX_STATUS_MESSAGE_LENGTH (255)
-
-/*
- * Current Maximum Length for Instant Messages
- *
- * This was found by experiment.
- *
- * The YMSG protocol allows a message of up to 948 bytes, but the official client
- * limits to 800 characters.  According to experiments I conducted, it seems that
- * the discrepancy is to allow some leeway for messages with mixed single- and
- * multi-byte characters, as I was able to send messages of 840 and 932 bytes
- * by using some multibyte characters (some random Chinese or Japanese characters,
- * to be precise). - rekkanoryo
- */
-#define YAHOO_MAX_MESSAGE_LENGTH_BYTES 948
-#define YAHOO_MAX_MESSAGE_LENGTH_CHARS 800
-
-/* sometimes i wish prpls could #include things from other prpls. then i could just
- * use the routines from libfaim and not have to admit to knowing how they work. */
-#define yahoo_put16(buf, data) ( \
-		(*(buf) = (unsigned char)((data)>>8)&0xff), \
-		(*((buf)+1) = (unsigned char)(data)&0xff),  \
-		2)
-#define yahoo_get16(buf) ((((*(buf))<<8)&0xff00) + ((*((buf)+1)) & 0xff))
-#define yahoo_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)
-#define yahoo_get32(buf) ((((*(buf))<<24)&0xff000000) + \
-		(((*((buf)+1))<<16)&0x00ff0000) + \
-		(((*((buf)+2))<< 8)&0x0000ff00) + \
-		(((*((buf)+3)    )&0x000000ff)))
-
-/* util.c */
-void yahoo_init_colorht(void);
-void yahoo_dest_colorht(void);
-char *yahoo_codes_to_html(const char *x);
-
-/**
- * This function takes a normal HTML message and converts it to the message
- * format used by Yahoo, which uses a frankensteinish combination of ANSI
- * escape codes and broken HTML.
- *
- * It results in slightly different output than would be sent by official
- * Yahoo clients.  The two main differences are:
- *
- * 1. We always close all tags, whereas official Yahoo clients leave tags
- *    dangling open at the end of each message (and the client treats them
- *    as closed).
- * 2. We always close inner tags first before closing outter tags.
- *
- * For example, if you want to send this message:
- *   <b> bold <i> bolditalic </i></b><i> italic </i>
- * Official Yahoo clients would send:
- *   ESC[1m bold ESC[2m bolditalic ESC[x1m italic
- * But we will send:
- *   ESC[1m bold ESC[2m bolditalic ESC[x2mESC[x1mESC[2m italic ESC[x2m
- */
-char *yahoo_html_to_codes(const char *src);
-
-gboolean
-yahoo_account_use_http_proxy(PurpleConnection *conn);
-
-/**
- * Encode some text to send to the yahoo server.
- *
- * @param gc The connection handle.
- * @param str The null terminated utf8 string to encode.
- * @param utf8 If not @c NULL, whether utf8 is okay or not.
- *             Even if it is okay, we may not use it. If we
- *             used it, we set this to @c TRUE, else to
- *             @c FALSE. If @c NULL, false is assumed, and
- *             it is not dereferenced.
- * @return The g_malloced string in the appropriate encoding.
- */
-char *yahoo_string_encode(PurpleConnection *gc, const char *str, gboolean *utf8);
-
-/**
- * Decode some text received from the server.
- *
- * @param gc The gc handle.
- * @param str The null terminated string to decode.
- * @param utf8 Did the server tell us it was supposed to be utf8?
- * @return The decoded, utf-8 string, which must be g_free()'d.
- */
-char *yahoo_string_decode(PurpleConnection *gc, const char *str, gboolean utf8);
-
-char *yahoo_convert_to_numeric(const char *str);
-
-YahooFederation yahoo_get_federation_from_name(const char *who);
-
-/* yahoo_profile.c */
-void yahoo_get_info(PurpleConnection *gc, const char *name);
-
-/* libymsg.h  - these functions were formerly static but need not to be for the
- * new two-prpl model. */
-const char *yahoo_list_icon(PurpleAccount *a, PurpleBuddy *b);
-const char *yahoo_list_emblem(PurpleBuddy *b);
-char *yahoo_status_text(PurpleBuddy *b);
-void yahoo_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full);
-GList *yahoo_status_types(PurpleAccount *account);
-GList *yahoo_blist_node_menu(PurpleBlistNode *node);
-void yahoo_login(PurpleAccount *account);
-void yahoo_close(PurpleConnection *gc);
-int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags);
-unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state);
-void yahoo_set_status(PurpleAccount *account, PurpleStatus *status);
-void yahoo_set_idle(PurpleConnection *gc, int idle);
-void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g);
-void yahoo_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group);
-void yahoo_add_deny(PurpleConnection *gc, const char *who);
-void yahoo_rem_deny(PurpleConnection *gc, const char *who);
-void yahoo_set_permit_deny(PurpleConnection *gc);
-void yahoo_keepalive(PurpleConnection *gc);
-void yahoo_change_buddys_group(PurpleConnection *gc, const char *who, const char *old_group, const char *new_group);
-void yahoo_rename_group(PurpleConnection *gc, const char *old_name, PurpleGroup *group, GList *moved_buddies);
-gboolean yahoo_offline_message(const PurpleBuddy *buddy);
-gboolean yahoo_send_attention(PurpleConnection *gc, const char *username, guint type);
-GList *yahoo_attention_types(PurpleAccount *account);
-
-GList *yahoo_actions(PurplePlugin *plugin, gpointer context);
-void yahoopurple_register_commands(void);
-
-PurpleCmdRet yahoopurple_cmd_buzz(PurpleConversation *c, const gchar *cmd, gchar **args, gchar **error, void *data);
-PurpleCmdRet yahoopurple_cmd_chat_join(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data);
-PurpleCmdRet yahoopurple_cmd_chat_list(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data);
-/* needed for xfer, thought theyd be useful for other enhancements later on
-   Returns list of cookies stored in yahoo_data formatted as a single null terminated string
-   returned value must be g_freed
-*/
-gchar* yahoo_get_cookies(PurpleConnection *gc);
-
-/* send p2p pkt containing our encoded ip, asking peer to connect to us */
-void yahoo_send_p2p_pkt(PurpleConnection *gc, const char *who, int val_13);
-
-#endif /* _LIBYMSG_H_ */
--- a/libpurple/protocols/yahoo/util.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,986 +0,0 @@
-/*
- * purple
- *
- * Some code copyright 2003 Tim Ringenbach <omarvo@hotmail.com>
- * (marv on irc.freenode.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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#include "debug.h"
-#include "internal.h"
-#include "prpl.h"
-
-#include "libymsg.h"
-
-#include <string.h>
-
-gboolean
-yahoo_account_use_http_proxy(PurpleConnection *pc)
-{
-	PurpleAccount *account = purple_connection_get_account(pc);
-	PurpleProxyInfo *ppi = NULL;
-	PurpleProxyType type = PURPLE_PROXY_NONE;
-	gboolean proxy_ssl = purple_account_get_bool(account, "proxy_ssl", FALSE);
-
-	if(proxy_ssl)
-		ppi = purple_proxy_get_setup(account);
-	else
-		ppi = purple_proxy_get_setup(NULL);
-
-	type = purple_proxy_info_get_type(ppi);
-
-	return (type == PURPLE_PROXY_HTTP || type == PURPLE_PROXY_USE_ENVVAR);
-}
-
-/*
- * Returns cookies formatted as a null terminated string for the given connection.
- * Must g_free return value.
- *
- * TODO:will work, but must test for strict correctness
- */
-gchar* yahoo_get_cookies(PurpleConnection *gc)
-{
-	gchar *ans = NULL;
-	gchar *cur;
-	char firstflag = 1;
-	gchar *t1,*t2,*t3;
-	GSList *tmp;
-	GSList *cookies;
-	cookies = ((YahooData*)(gc->proto_data))->cookies;
-	tmp = cookies;
-	while(tmp)
-	{
-		cur = tmp->data;
-		t1 = ans;
-		t2 = g_strrstr(cur, ";expires=");
-		if(t2 == NULL)
-			t2 = g_strrstr(cur, "; expires=");
-		if(t2 == NULL)
-		{
-			if(firstflag)
-				ans = g_strdup_printf("%c=%s", cur[0], cur+2);
-			else
-				ans = g_strdup_printf("%s; %c=%s", t1, cur[0], cur+2);
-		}
-		else
-		{
-			t3 = strstr(t2+1, ";");
-			if(t3 != NULL)
-			{
-				t2[0] = '\0';
-
-				if(firstflag)
-					ans = g_strdup_printf("%c=%s%s", cur[0], cur+2, t3);
-				else
-					ans = g_strdup_printf("%s; %c=%s%s", t1, cur[0], cur+2, t3);
-
-				t2[0] = ';';
-			}
-			else
-			{
-				t2[0] = '\0';
-
-				if(firstflag)
-					ans = g_strdup_printf("%c=%s", cur[0], cur+2);
-				else
-					ans = g_strdup_printf("%s; %c=%s", t1, cur[0], cur+2);
-
-				t2[0] = ';';
-			}
-		}
-		if(firstflag)
-			firstflag = 0;
-		else
-			g_free(t1);
-		tmp = g_slist_next(tmp);
-	}
-	return ans;
-}
-
-/**
- * Encode some text to send to the yahoo server.
- *
- * @param gc The connection handle.
- * @param str The null terminated utf8 string to encode.
- * @param utf8 If not @c NULL, whether utf8 is okay or not.
- *             Even if it is okay, we may not use it. If we
- *             used it, we set this to @c TRUE, else to
- *             @c FALSE. If @c NULL, false is assumed, and
- *             it is not dereferenced.
- * @return The g_malloced string in the appropriate encoding.
- */
-char *yahoo_string_encode(PurpleConnection *gc, const char *str, gboolean *utf8)
-{
-	YahooData *yd = gc->proto_data;
-	char *ret;
-	const char *to_codeset;
-	GError *error = NULL;
-
-	if (yd->jp)
-		return g_strdup(str);
-
-	if (utf8 && *utf8) /* FIXME: maybe don't use utf8 if it'll fit in latin1 */
-		return g_strdup(str);
-
-	to_codeset = purple_account_get_string(purple_connection_get_account(gc), "local_charset",  "ISO-8859-1");
-	ret = g_convert_with_fallback(str, -1, to_codeset, "UTF-8", "?", NULL, NULL, &error);
-	if (!ret) {
-		if (error) {
-			purple_debug_error("yahoo", "Could not convert %s from UTF-8 to "
-					"%s: %d - %s\n", str ? str : "(null)", to_codeset,
-					error->code,
-					error->message ? error->message : "(null)");
-			g_error_free(error);
-		} else {
-			purple_debug_error("yahoo", "Could not convert %s from UTF-8 to "
-					"%s: unkown error\n", str ? str : "(null)", to_codeset);
-		}
-		return g_strdup("");
-	}
-
-	return ret;
-}
-
-/**
- * Decode some text received from the server.
- *
- * @param gc The gc handle.
- * @param str The null terminated string to decode.
- * @param utf8 Did the server tell us it was supposed to be utf8?
- * @return The decoded, utf-8 string, which must be g_free()'d.
- */
-char *yahoo_string_decode(PurpleConnection *gc, const char *str, gboolean utf8)
-{
-	YahooData *yd = gc->proto_data;
-	char *ret;
-	const char *from_codeset;
-	GError *error = NULL;
-
-	if (utf8) {
-		if (g_utf8_validate(str, -1, NULL))
-			return g_strdup(str);
-		purple_debug_warning("yahoo", "Server told us a string was supposed "
-				"to be UTF-8, but it was not. Will try another encoding.\n");
-	}
-
-	if (yd->jp)
-		from_codeset = "SHIFT_JIS";
-	else
-		from_codeset = purple_account_get_string(purple_connection_get_account(gc), "local_charset",  "ISO-8859-1");
-
-	ret = g_convert_with_fallback(str, -1, "UTF-8", from_codeset, NULL, NULL, NULL, &error);
-	if (!ret) {
-		if (error) {
-			purple_debug_error("yahoo", "Could not convert %s from %s to "
-					"UTF-8: %d - %s\n", str ? str : "(null)", from_codeset,
-					error->code, error->message ? error->message : "(null)");
-			g_error_free(error);
-		} else {
-			purple_debug_error("yahoo", "Could not convert %s from %s to "
-					"UTF-8: unkown error\n", str ? str : "(null)",
-					from_codeset);
-		}
-		return g_strdup("");
-	}
-
-	return ret;
-}
-
-char *yahoo_convert_to_numeric(const char *str)
-{
-	GString *gstr = NULL;
-	const unsigned char *p;
-
-	gstr = g_string_sized_new(strlen(str) * 6 + 1);
-
-	for (p = (unsigned char *)str; *p; p++) {
-		g_string_append_printf(gstr, "&#%u;", *p);
-	}
-
-	return g_string_free(gstr, FALSE);
-}
-
-/*
- * The values in this hash table should probably be lowercase, since that's
- * what xhtml expects.  Also because yahoo_codes_to_html() does
- * case-sensitive comparisons.
- *
- * I found these on some website but i don't know that they actually
- * work (or are supposed to work). I didn't implement them yet.
- *
- * [0;30m ---black
- * [1;37m ---white
- * [0;37m ---tan
- * [0;38m ---light black
- * [1;39m ---dark blue
- * [0;32m ---green
- * [0;33m ---yellow
- * [0;35m ---pink
- * [1;35m ---purple
- * [1;30m ---light blue
- * [0;31m ---red
- * [0;34m ---blue
- * [0;36m ---aqua
- * (shift+comma)lyellow(shift+period) ---light yellow
- * (shift+comma)lgreen(shift+period) ---light green
- * [2;30m <--white out
- */
-
-static GHashTable *esc_codes_ht = NULL;
-static GHashTable *tags_ht = NULL;
-
-void yahoo_init_colorht()
-{
-	if (esc_codes_ht != NULL)
-		/* Hash table has already been initialized */
-		return;
-
-	/* Key is the escape code string.  Value is the HTML that should be
-	 * inserted in place of the escape code. */
-	esc_codes_ht = g_hash_table_new(g_str_hash, g_str_equal);
-
-	/* Key is the name of the HTML tag, for example "font" or "/font"
-	 * value is the HTML that should be inserted in place of the old tag */
-	tags_ht = g_hash_table_new(g_str_hash, g_str_equal);
-
-	/* the numbers in comments are what gyach uses, but i think they're incorrect */
-#ifdef USE_CSS_FORMATTING
-	g_hash_table_insert(esc_codes_ht, "30", "<span style=\"color: #000000\">"); /* black */
-	g_hash_table_insert(esc_codes_ht, "31", "<span style=\"color: #0000FF\">"); /* blue */
-	g_hash_table_insert(esc_codes_ht, "32", "<span style=\"color: #008080\">"); /* cyan */      /* 00b2b2 */
-	g_hash_table_insert(esc_codes_ht, "33", "<span style=\"color: #808080\">"); /* gray */      /* 808080 */
-	g_hash_table_insert(esc_codes_ht, "34", "<span style=\"color: #008000\">"); /* green */     /* 00c200 */
-	g_hash_table_insert(esc_codes_ht, "35", "<span style=\"color: #FF0080\">"); /* pink */      /* ffafaf */
-	g_hash_table_insert(esc_codes_ht, "36", "<span style=\"color: #800080\">"); /* purple */    /* b200b2 */
-	g_hash_table_insert(esc_codes_ht, "37", "<span style=\"color: #FF8000\">"); /* orange */    /* ffff00 */
-	g_hash_table_insert(esc_codes_ht, "38", "<span style=\"color: #FF0000\">"); /* red */
-	g_hash_table_insert(esc_codes_ht, "39", "<span style=\"color: #808000\">"); /* olive */     /* 546b50 */
-#else
-	g_hash_table_insert(esc_codes_ht, "30", "<font color=\"#000000\">"); /* black */
-	g_hash_table_insert(esc_codes_ht, "31", "<font color=\"#0000FF\">"); /* blue */
-	g_hash_table_insert(esc_codes_ht, "32", "<font color=\"#008080\">"); /* cyan */      /* 00b2b2 */
-	g_hash_table_insert(esc_codes_ht, "33", "<font color=\"#808080\">"); /* gray */      /* 808080 */
-	g_hash_table_insert(esc_codes_ht, "34", "<font color=\"#008000\">"); /* green */     /* 00c200 */
-	g_hash_table_insert(esc_codes_ht, "35", "<font color=\"#FF0080\">"); /* pink */      /* ffafaf */
-	g_hash_table_insert(esc_codes_ht, "36", "<font color=\"#800080\">"); /* purple */    /* b200b2 */
-	g_hash_table_insert(esc_codes_ht, "37", "<font color=\"#FF8000\">"); /* orange */    /* ffff00 */
-	g_hash_table_insert(esc_codes_ht, "38", "<font color=\"#FF0000\">"); /* red */
-	g_hash_table_insert(esc_codes_ht, "39", "<font color=\"#808000\">"); /* olive */     /* 546b50 */
-#endif /* !USE_CSS_FORMATTING */
-
-	g_hash_table_insert(esc_codes_ht,  "1",  "<b>");
-	g_hash_table_insert(esc_codes_ht, "x1", "</b>");
-	g_hash_table_insert(esc_codes_ht,  "2",  "<i>");
-	g_hash_table_insert(esc_codes_ht, "x2", "</i>");
-	g_hash_table_insert(esc_codes_ht,  "4",  "<u>");
-	g_hash_table_insert(esc_codes_ht, "x4", "</u>");
-
-	/* these just tell us the text they surround is supposed
-	 * to be a link. purple figures that out on its own so we
-	 * just ignore it.
-	 */
-	g_hash_table_insert(esc_codes_ht, "l", ""); /* link start */
-	g_hash_table_insert(esc_codes_ht, "xl", ""); /* link end */
-
-#ifdef USE_CSS_FORMATTING
-	g_hash_table_insert(tags_ht, "black",  "<span style=\"color: #000000\">");
-	g_hash_table_insert(tags_ht, "blue",   "<span style=\"color: #0000FF\">");
-	g_hash_table_insert(tags_ht, "cyan",   "<span style=\"color: #008284\">");
-	g_hash_table_insert(tags_ht, "gray",   "<span style=\"color: #848284\">");
-	g_hash_table_insert(tags_ht, "green",  "<span style=\"color: #008200\">");
-	g_hash_table_insert(tags_ht, "pink",   "<span style=\"color: #FF0084\">");
-	g_hash_table_insert(tags_ht, "purple", "<span style=\"color: #840084\">");
-	g_hash_table_insert(tags_ht, "orange", "<span style=\"color: #FF8000\">");
-	g_hash_table_insert(tags_ht, "red",    "<span style=\"color: #FF0000\">");
-	g_hash_table_insert(tags_ht, "yellow", "<span style=\"color: #848200\">");
-
-	g_hash_table_insert(tags_ht, "/black",  "</span>");
-	g_hash_table_insert(tags_ht, "/blue",   "</span>");
-	g_hash_table_insert(tags_ht, "/cyan",   "</span>");
-	g_hash_table_insert(tags_ht, "/gray",   "</span>");
-	g_hash_table_insert(tags_ht, "/green",  "</span>");
-	g_hash_table_insert(tags_ht, "/pink",   "</span>");
-	g_hash_table_insert(tags_ht, "/purple", "</span>");
-	g_hash_table_insert(tags_ht, "/orange", "</span>");
-	g_hash_table_insert(tags_ht, "/red",    "</span>");
-	g_hash_table_insert(tags_ht, "/yellow", "</span>");
-#else
-	g_hash_table_insert(tags_ht, "black",  "<font color=\"#000000\">");
-	g_hash_table_insert(tags_ht, "blue",   "<font color=\"#0000FF\">");
-	g_hash_table_insert(tags_ht, "cyan",   "<font color=\"#008284\">");
-	g_hash_table_insert(tags_ht, "gray",   "<font color=\"#848284\">");
-	g_hash_table_insert(tags_ht, "green",  "<font color=\"#008200\">");
-	g_hash_table_insert(tags_ht, "pink",   "<font color=\"#FF0084\">");
-	g_hash_table_insert(tags_ht, "purple", "<font color=\"#840084\">");
-	g_hash_table_insert(tags_ht, "orange", "<font color=\"#FF8000\">");
-	g_hash_table_insert(tags_ht, "red",    "<font color=\"#FF0000\">");
-	g_hash_table_insert(tags_ht, "yellow", "<font color=\"#848200\">");
-
-	g_hash_table_insert(tags_ht, "/black",  "</font>");
-	g_hash_table_insert(tags_ht, "/blue",   "</font>");
-	g_hash_table_insert(tags_ht, "/cyan",   "</font>");
-	g_hash_table_insert(tags_ht, "/gray",   "</font>");
-	g_hash_table_insert(tags_ht, "/green",  "</font>");
-	g_hash_table_insert(tags_ht, "/pink",   "</font>");
-	g_hash_table_insert(tags_ht, "/purple", "</font>");
-	g_hash_table_insert(tags_ht, "/orange", "</font>");
-	g_hash_table_insert(tags_ht, "/red",    "</font>");
-	g_hash_table_insert(tags_ht, "/yellow", "</font>");
-#endif /* !USE_CSS_FORMATTING */
-
-	/* We don't support these tags, so discard them */
-	g_hash_table_insert(tags_ht, "alt", "");
-	g_hash_table_insert(tags_ht, "fade", "");
-	g_hash_table_insert(tags_ht, "snd", "");
-	g_hash_table_insert(tags_ht, "/alt", "");
-	g_hash_table_insert(tags_ht, "/fade", "");
-
-	/* Official clients don't seem to send b, i or u tags.  They use
-	 * the escape codes listed above.  Official clients definitely send
-	 * font tags, though.  I wonder if we can remove the opening and
-	 * closing b, i and u tags from here? */
-	g_hash_table_insert(tags_ht, "b", "<b>");
-	g_hash_table_insert(tags_ht, "i", "<i>");
-	g_hash_table_insert(tags_ht, "u", "<u>");
-	g_hash_table_insert(tags_ht, "font", "<font>");
-
-	g_hash_table_insert(tags_ht, "/b", "</b>");
-	g_hash_table_insert(tags_ht, "/i", "</i>");
-	g_hash_table_insert(tags_ht, "/u", "</u>");
-	g_hash_table_insert(tags_ht, "/font", "</font>");
-}
-
-void yahoo_dest_colorht()
-{
-	if (esc_codes_ht == NULL)
-		/* Hash table has already been destroyed */
-		return;
-
-	g_hash_table_destroy(esc_codes_ht);
-	esc_codes_ht = NULL;
-	g_hash_table_destroy(tags_ht);
-	tags_ht = NULL;
-}
-
-#ifndef USE_CSS_FORMATTING
-static int point_to_html(int x)
-{
-	if (x < 9)
-		return 1;
-	if (x < 11)
-		return 2;
-	if (x < 13)
-		return 3;
-	if (x < 17)
-		return 4;
-	if (x < 25)
-		return 5;
-	if (x < 35)
-		return 6;
-	return 7;
-}
-#endif /* !USE_CSS_FORMATTING */
-
-static void append_attrs_datalist_foreach_cb(GQuark key_id, gpointer data, gpointer user_data)
-{
-	const char *key;
-	const char *value;
-	xmlnode *cur;
-
-	key = g_quark_to_string(key_id);
-	value = data;
-	cur = user_data;
-
-	xmlnode_set_attrib(cur, key, value);
-}
-
-/**
- * @param cur A pointer to the position in the XML tree that we're
- *        currently building.  This will be modified when opening a tag
- *        or closing an existing tag.
- */
-static void yahoo_codes_to_html_add_tag(xmlnode **cur, const char *tag, gboolean is_closing_tag, const gchar *tag_name, gboolean is_font_tag)
-{
-	if (is_closing_tag) {
-		xmlnode *tmp;
-		GSList *dangling_tags = NULL;
-
-		/* Move up the DOM until we find the opening tag */
-		for (tmp = *cur; tmp != NULL; tmp = xmlnode_get_parent(tmp)) {
-			/* Add one to tag_name when doing this comparison because it starts with a / */
-			if (g_str_equal(tmp->name, tag_name + 1))
-				/* Found */
-				break;
-			dangling_tags = g_slist_prepend(dangling_tags, tmp);
-		}
-		if (tmp == NULL) {
-			/* This is a closing tag with no opening tag.  Useless. */
-			purple_debug_error("yahoo", "Ignoring unmatched tag %s", tag);
-			g_slist_free(dangling_tags);
-			return;
-		}
-
-		/* Move our current position up, now that we've closed a tag */
-		*cur = xmlnode_get_parent(tmp);
-
-		/* Re-open any tags that were nested below the tag we just closed */
-		while (dangling_tags != NULL) {
-			tmp = dangling_tags->data;
-			dangling_tags = g_slist_delete_link(dangling_tags, dangling_tags);
-
-			/* Create a copy of this tag+attributes (but not child tags or
-			 * data) at our new location */
-			*cur = xmlnode_new_child(*cur, tmp->name);
-			for (tmp = tmp->child; tmp != NULL; tmp = tmp->next)
-				if (tmp->type == XMLNODE_TYPE_ATTRIB)
-					xmlnode_set_attrib_full(*cur, tmp->name,
-							tmp->xmlns, tmp->prefix, tmp->data);
-		}
-	} else {
-		const char *start;
-		const char *end;
-		GData *attributes;
-		char *fontsize = NULL;
-
-		if (!purple_markup_find_tag(tag_name, tag, &start, &end, &attributes))
-			g_return_if_reached();
-		*cur = xmlnode_new_child(*cur, tag_name);
-
-		if (is_font_tag) {
-			/* Special case for the font size attribute */
-			fontsize = g_strdup(g_datalist_get_data(&attributes, "size"));
-			if (fontsize != NULL)
-				g_datalist_remove_data(&attributes, "size");
-		}
-
-		/* Add all font tag attributes */
-		g_datalist_foreach(&attributes, append_attrs_datalist_foreach_cb, *cur);
-		g_datalist_clear(&attributes);
-
-		if (fontsize != NULL) {
-#ifdef USE_CSS_FORMATTING
-			/*
-			 * The Yahoo font size value is given in pt, even though the HTML
-			 * standard for <font size="x"> treats the size as a number on a
-			 * scale between 1 and 7.  So we insert the font size as a CSS
-			 * style on a span tag.
-			 */
-			gchar *tmp = g_strdup_printf("font-size: %spt", fontsize);
-			*cur = xmlnode_new_child(*cur, "span");
-			xmlnode_set_attrib(*cur, "style", tmp);
-			g_free(tmp);
-#else
-			/*
-			 * The Yahoo font size value is given in pt, even though the HTML
-			 * standard for <font size="x"> treats the size as a number on a
-			 * scale between 1 and 7.  So we convert it to an appropriate
-			 * value.  This loses precision, which is why CSS formatting is
-			 * preferred.  The "absz" attribute remains here for backward
-			 * compatibility with UIs that might use it, but it is totally
-			 * not standard at all.
-			 */
-			int size, htmlsize;
-			gchar tmp[11];
-			size = strtol(fontsize, NULL, 10);
-			htmlsize = point_to_html(size);
-			sprintf(tmp, "%u", htmlsize);
-			xmlnode_set_attrib(*cur, "size", tmp);
-			xmlnode_set_attrib(*cur, "absz", fontsize);
-#endif /* !USE_CSS_FORMATTING */
-			g_free(fontsize);
-		}
-	}
-}
-
-/**
- * Similar to purple_markup_get_tag_name(), but works with closing tags.
- *
- * @return The lowercase name of the tag.  If this is a closing tag then
- *         this value starts with a forward slash.  The caller must free
- *         this string with g_free.
- */
-static gchar *yahoo_markup_get_tag_name(const char *tag, gboolean *is_closing_tag)
-{
-	size_t len;
-
-	*is_closing_tag = (tag[1] == '/');
-	if (*is_closing_tag)
-		len = strcspn(tag + 1, "> ");
-	else
-		len = strcspn(tag + 1, "> /");
-
-	return g_utf8_strdown(tag + 1, len);
-}
-
-/*
- * Yahoo! messages generally aren't well-formed.  Their markup is
- * more of a flow from start to finish rather than a hierarchy from
- * outer to inner.  They tend to open tags and close them only when
- * necessary.
- *
- * Example: <font size="8">size 8 <font size="16">size 16 <font size="8">size 8 again
- *
- * But we want to send well-formed HTML to the core, so we step through
- * the input string and build an xmlnode tree containing sanitized HTML.
- */
-char *yahoo_codes_to_html(const char *x)
-{
-	size_t x_len;
-	xmlnode *html, *cur;
-	GString *cdata = g_string_new(NULL);
-	guint i, j;
-	gboolean no_more_gt_brackets = FALSE;
-	const char *match;
-	gchar *xmlstr1, *xmlstr2, *esc;
-
-	x_len = strlen(x);
-	html = xmlnode_new("html");
-
-	cur = html;
-	for (i = 0; i < x_len; i++) {
-		if ((x[i] == 0x1b) && (x[i+1] == '[')) {
-			/* This escape sequence signifies the beginning of some
-			 * text formatting code */
-			j = i + 1;
-
-			while (j++ < x_len) {
-				gchar *code;
-
-				if (x[j] != 'm')
-					/* Keep looking for the end of this sequence */
-					continue;
-
-				/* We've reached the end of the formatting sequence, yay */
-
-				/* Append any character data that belongs in the current node */
-				if (cdata->len > 0) {
-					xmlnode_insert_data(cur, cdata->str, cdata->len);
-					g_string_truncate(cdata, 0);
-				}
-
-				code = g_strndup(x + i + 2, j - i - 2);
-				if (code[0] == '#') {
-#ifdef USE_CSS_FORMATTING
-					gchar *tmp = g_strdup_printf("color: %s", code);
-					cur = xmlnode_new_child(cur, "span");
-					xmlnode_set_attrib(cur, "style", tmp);
-					g_free(tmp);
-#else
-					cur = xmlnode_new_child(cur, "font");
-					xmlnode_set_attrib(cur, "color", code);
-#endif /* !USE_CSS_FORMATTING */
-
-				} else if ((match = g_hash_table_lookup(esc_codes_ht, code))) {
-					/* Some tags are in the hash table only because we
-					 * want to ignore them */
-					if (match[0] != '\0') {
-						gboolean is_closing_tag;
-						gchar *tag_name;
-						tag_name = yahoo_markup_get_tag_name(match, &is_closing_tag);
-						yahoo_codes_to_html_add_tag(&cur, match, is_closing_tag, tag_name, FALSE);
-						g_free(tag_name);
-					}
-
-				} else {
-					purple_debug_error("yahoo",
-						"Ignoring unknown ansi code 'ESC[%sm'.\n", code);
-				}
-
-				g_free(code);
-				i = j;
-				break;
-			}
-
-		} else if (x[i] == '<' && !no_more_gt_brackets) {
-			/* The start of an HTML tag */
-			j = i;
-
-			while (j++ < x_len) {
-				gchar *tag;
-				gboolean is_closing_tag;
-				gchar *tag_name;
-
-				if (x[j] != '>') {
-					if (x[j] == '"') {
-						/* We're inside a quoted attribute value. Skip to the end */
-						j++;
-						while (j != x_len && x[j] != '"')
-							j++;
-					} else if (x[j] == '\'') {
-						/* We're inside a quoted attribute value. Skip to the end */
-						j++;
-						while (j != x_len && x[j] != '\'')
-							j++;
-					}
-					if (j != x_len)
-						/* Keep looking for the end of this tag */
-						continue;
-
-					/* This < has no corresponding > */
-					g_string_append_c(cdata, x[i]);
-					no_more_gt_brackets = TRUE;
-					break;
-				}
-
-				tag = g_strndup(x + i, j - i + 1);
-				tag_name = yahoo_markup_get_tag_name(tag, &is_closing_tag);
-
-				match = g_hash_table_lookup(tags_ht, tag_name);
-				if (match == NULL) {
-					/* Unknown tag.  The user probably typed a less-than sign */
-					g_string_append_c(cdata, x[i]);
-					g_free(tag);
-					g_free(tag_name);
-					break;
-				}
-
-				/* Some tags are in the hash table only because we
-				 * want to ignore them */
-				if (match[0] != '\0') {
-					/* Append any character data that belongs in the current node */
-					if (cdata->len > 0) {
-						xmlnode_insert_data(cur, cdata->str, cdata->len);
-						g_string_truncate(cdata, 0);
-					}
-					if (g_str_equal(tag_name, "font"))
-						/* Font tags are a special case.  We don't
-						 * necessarily want to replace the whole thing--
-						 * we just want to fix the size attribute. */
-						yahoo_codes_to_html_add_tag(&cur, tag, is_closing_tag, tag_name, TRUE);
-					else
-						yahoo_codes_to_html_add_tag(&cur, match, is_closing_tag, tag_name, FALSE);
-				}
-
-				i = j;
-				g_free(tag);
-				g_free(tag_name);
-				break;
-			}
-
-		} else {
-			g_string_append_c(cdata, x[i]);
-		}
-	}
-
-	/* Append any remaining character data */
-	if (cdata->len > 0)
-		xmlnode_insert_data(cur, cdata->str, cdata->len);
-	g_string_free(cdata, TRUE);
-
-	/* Serialize our HTML */
-	xmlstr1 = xmlnode_to_str(html, NULL);
-	xmlnode_free(html);
-
-	/* Strip off the outter HTML node */
-	/* This probably isn't necessary, especially if we made the outter HTML
-	 * node an empty span.  But the HTML is simpler this way. */
-	if (!purple_strequal(xmlstr1, "<html/>"))
-		xmlstr2 = g_strndup(xmlstr1 + 6, strlen(xmlstr1) - 13);
-	else
-		xmlstr2 = g_strdup("");
-	g_free(xmlstr1);
-
-	esc = g_strescape(x, NULL);
-	purple_debug_misc("yahoo", "yahoo_codes_to_html(%s)=%s\n", esc, xmlstr2);
-	g_free(esc);
-
-	return xmlstr2;
-}
-
-/* borrowed from gtkimhtml */
-#define MAX_FONT_SIZE 7
-#define POINT_SIZE(x) (_point_sizes [MIN ((x > 0 ? x : 1), MAX_FONT_SIZE) - 1])
-static const gint _point_sizes [] = { 8, 10, 12, 14, 20, 30, 40 };
-
-typedef struct
-{
-	gboolean bold;
-	gboolean italic;
-	gboolean underline;
-	gboolean in_link;
-	int font_size;
-	char *font_face;
-	char *font_color;
-} CurrentMsgState;
-
-static void yahoo_htc_list_cleanup(GSList *l)
-{
-	while (l != NULL) {
-		g_free(l->data);
-		l = g_slist_delete_link(l, l);
-	}
-}
-
-static void parse_font_tag(GString *dest, const char *tag_name, const char *tag,
-				GSList **colors, GSList **tags)
-{
-	const char *start;
-	const char *end;
-	GData *attributes;
-	const char *attribute;
-	gboolean needendtag;
-	GString *tmp;
-
-	if (!purple_markup_find_tag(tag_name, tag, &start, &end, &attributes))
-		g_return_if_reached();
-
-	needendtag = FALSE;
-	tmp = g_string_new(NULL);
-
-	attribute = g_datalist_get_data(&attributes, "color");
-	if (attribute != NULL) {
-		g_string_append(tmp, *colors ? (*colors)->data : "\033[#000000m");
-		g_string_append_printf(dest, "\033[%sm", attribute);
-		*colors = g_slist_prepend(*colors,
-				g_strdup_printf("\033[%sm", attribute));
-	} else {
-		/* We need to add a value to the colors stack even if we're not
-		 * setting a color because we ALWAYS pop exactly 1 element from
-		 * this stack for every </font> tag.  If we don't add anything
-		 * then we'll pop something that we shouldn't when we hit this
-		 * corresponding </font>. */
-		*colors = g_slist_prepend(*colors,
-				*colors ? g_strdup((*colors)->data) : g_strdup("\033[#000000m"));
-	}
-
-	attribute = g_datalist_get_data(&attributes, "face");
-	if (attribute != NULL) {
-		needendtag = TRUE;
-		g_string_append(dest, "<font ");
-		g_string_append_printf(dest, "face=\"%s\" ", attribute);
-	}
-
-	attribute = g_datalist_get_data(&attributes, "size");
-	if (attribute != NULL) {
-		if (!needendtag) {
-			needendtag = TRUE;
-			g_string_append(dest, "<font ");
-		}
-
-		g_string_append_printf(dest, "size=\"%d\" ",
-				POINT_SIZE(strtol(attribute, NULL, 10)));
-	}
-
-	if (needendtag) {
-		dest->str[dest->len-1] = '>';
-		*tags = g_slist_prepend(*tags, g_strdup("</font>"));
-		g_string_free(tmp, TRUE);
-	} else {
-		*tags = g_slist_prepend(*tags, tmp->str);
-		g_string_free(tmp, FALSE);
-	}
-
-	g_datalist_clear(&attributes);
-}
-
-char *yahoo_html_to_codes(const char *src)
-{
-	GSList *colors = NULL;
-
-	/**
-	 * A stack of char*s where each char* is the string that should be
-	 * appended to dest in order to close all the tags that were opened
-	 * by a <font> tag.
-	 */
-	GSList *tags = NULL;
-
-	size_t src_len;
-	guint i, j;
-	GString *dest;
-	char *esc;
-	gboolean no_more_gt_brackets = FALSE;
-	gchar *tag, *tag_name;
-	gboolean is_closing_tag;
-	CurrentMsgState current_state;
-
-	memset(&current_state, 0, sizeof(current_state));
-
-	src_len = strlen(src);
-	dest = g_string_sized_new(src_len);
-
-	for (i = 0; i < src_len; i++) {
-		if (src[i] == '<' && !no_more_gt_brackets) {
-			/* The start of an HTML tag  */
-			j = i;
-
-			while (j++ < src_len) {
-				if (src[j] != '>') {
-					if (src[j] == '"') {
-						/* We're inside a quoted attribute value. Skip to the end */
-						j++;
-						while (j != src_len && src[j] != '"')
-							j++;
-					} else if (src[j] == '\'') {
-						/* We're inside a quoted attribute value. Skip to the end */
-						j++;
-						while (j != src_len && src[j] != '\'')
-							j++;
-					}
-					if (j != src_len)
-						/* Keep looking for the end of this tag */
-						continue;
-
-					/* This < has no corresponding > */
-					g_string_append_c(dest, src[i]);
-					no_more_gt_brackets = TRUE;
-					break;
-				}
-
-				tag = g_strndup(src + i, j - i + 1);
-				tag_name = yahoo_markup_get_tag_name(tag, &is_closing_tag);
-
-				if (g_str_equal(tag_name, "a")) {
-					const char *start;
-					const char *end;
-					GData *attributes;
-					const char *attribute;
-
-					/*
-					 * TODO: Ideally we would replace this:
-					 * <a href="http://pidgin.im/">Pidgin</a>
-					 * with this:
-					 * Pidgin (http://pidgin.im/)
-					 *
-					 * Currently we drop the text within the <a> tag and
-					 * just show the URL.  Doing it the fancy way is
-					 * complicated when dealing with HTML tags within the
-					 * <a> tag.
-					 */
-
-					/* Append the URL */
-					if (!purple_markup_find_tag(tag_name,
-						tag, &start, &end, &attributes))
-					{
-						g_warn_if_reached();
-						i = j;
-						g_free(tag);
-						g_free(tag_name);
-						break;
-					}
-
-					attribute = g_datalist_get_data(&attributes, "href");
-					if (attribute != NULL) {
-						if (purple_str_has_prefix(attribute, "mailto:"))
-							attribute += 7;
-						g_string_append(dest, attribute);
-					}
-					g_datalist_clear(&attributes);
-
-					/* Skip past the closing </a> tag */
-					end = purple_strcasestr(src + j, "</a>");
-					if (end != NULL)
-						j = end - src + 3;
-
-				} else if (g_str_equal(tag_name, "font")) {
-					parse_font_tag(dest, tag_name, tag, &colors, &tags);
-				} else if (g_str_equal(tag_name, "b")) {
-					g_string_append(dest, "\033[1m");
-					current_state.bold = TRUE;
-				} else if (g_str_equal(tag_name, "/b")) {
-					if (current_state.bold) {
-						g_string_append(dest, "\033[x1m");
-						current_state.bold = FALSE;
-					}
-				} else if (g_str_equal(tag_name, "i")) {
-					current_state.italic = TRUE;
-					g_string_append(dest, "\033[2m");
-				} else if (g_str_equal(tag_name, "/i")) {
-					if (current_state.italic) {
-						g_string_append(dest, "\033[x2m");
-						current_state.italic = FALSE;
-					}
-				} else if (g_str_equal(tag_name, "u")) {
-					current_state.underline = TRUE;
-					g_string_append(dest, "\033[4m");
-				} else if (g_str_equal(tag_name, "/u")) {
-					if (current_state.underline) {
-						g_string_append(dest, "\033[x4m");
-						current_state.underline = FALSE;
-					}
-				} else if (g_str_equal(tag_name, "/a")) {
-					/* Do nothing */
-				} else if (g_str_equal(tag_name, "br")) {
-					g_string_append_c(dest, '\n');
-				} else if (g_str_equal(tag_name, "/font")) {
-					if (tags != NULL) {
-						char *etag = tags->data;
-						tags = g_slist_delete_link(tags, tags);
-						g_string_append(dest, etag);
-						if (colors != NULL) {
-							g_free(colors->data);
-							colors = g_slist_delete_link(colors, colors);
-						}
-						g_free(etag);
-					}
-				} else if (g_str_equal(tag_name, "span") || g_str_equal(tag_name, "/span")) {
-					/* Do nothing */
-				} else {
-					/* We don't know what the tag is. Send it unmodified. */
-					g_string_append(dest, tag);
-				}
-
-				i = j;
-				g_free(tag);
-				g_free(tag_name);
-				break;
-			}
-
-		} else {
-			const char *entity;
-			int length;
-
-			entity = purple_markup_unescape_entity(src + i, &length);
-			if (entity != NULL) {
-				/* src[i] is the start of an HTML entity */
-				g_string_append(dest, entity);
-				i += length - 1;
-			} else
-				/* src[i] is a normal character */
-				g_string_append_c(dest, src[i]);
-		}
-	}
-
-	esc = g_strescape(dest->str, NULL);
-	purple_debug_misc("yahoo", "yahoo_html_to_codes(%s)=%s\n", src, esc);
-	g_free(esc);
-
-	yahoo_htc_list_cleanup(colors);
-	yahoo_htc_list_cleanup(tags);
-
-	return g_string_free(dest, FALSE);
-}
-
-YahooFederation yahoo_get_federation_from_name(const char *who)
-{
-	YahooFederation fed = YAHOO_FEDERATION_NONE;
-	if (who[3] == '/') {
-		if (!g_ascii_strncasecmp(who, "msn", 3))
-			fed = YAHOO_FEDERATION_MSN;
-		else if (!g_ascii_strncasecmp(who, "ocs", 3))
-			fed = YAHOO_FEDERATION_OCS;
-		else if (!g_ascii_strncasecmp(who, "ibm", 3))
-			fed = YAHOO_FEDERATION_IBM;
-		else if (!g_ascii_strncasecmp(who, "pbx", 3))
-			fed = YAHOO_FEDERATION_PBX;
-	}
-	return fed;
-}
-
--- a/libpurple/protocols/yahoo/yahoo_aliases.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,729 +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 "accountopt.h"
-#include "blist.h"
-#include "debug.h"
-#include "util.h"
-#include "request.h"
-#include "version.h"
-#include "libymsg.h"
-#include "yahoo_aliases.h"
-#include "yahoo_friend.h"
-#include "yahoo_packet.h"
-
-/* I hate hardcoding this stuff, but Yahoo never sends us anything to use.  Someone in the know may be able to tweak this URL */
-#define YAHOO_ALIAS_FETCH_URL "http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us&diffs=1&t=0&tags=short&rt=0&prog-ver=" YAHOO_CLIENT_VERSION "&useutf8=1&legenc=codepage-1252"
-#define YAHOO_ALIAS_UPDATE_URL "http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us&sync=1&tags=short&noclear=1&useutf8=1&legenc=codepage-1252"
-#define YAHOOJP_ALIAS_FETCH_URL "http://address.yahoo.co.jp/yab/jp?v=XM&prog=ymsgr&.intl=jp&diffs=1&t=0&tags=short&rt=0&prog-ver=" YAHOOJP_CLIENT_VERSION
-#define YAHOOJP_ALIAS_UPDATE_URL "http://address.yahoo.co.jp/yab/jp?v=XM&prog=ymsgr&.intl=jp&sync=1&tags=short&noclear=1"
-
-void yahoo_update_alias(PurpleConnection *gc, const char *who, const char *alias);
-
-/**
- * Stuff we want passed to the callback function
- */
-struct callback_data {
-	PurpleConnection *gc;
-	gchar *id;
-	gchar *who;
-};
-
-void yahoo_personal_details_reset(YahooPersonalDetails *ypd, gboolean all)
-{
-	if (all)
-		g_free(ypd->id);
-	g_free(ypd->names.first);
-	g_free(ypd->names.last);
-	g_free(ypd->names.middle);
-	g_free(ypd->names.nick);
-	g_free(ypd->phone.work);
-	g_free(ypd->phone.home);
-	g_free(ypd->phone.mobile);
-}
-
-/**************************************************************************
- * Alias Fetch Functions
- **************************************************************************/
-
-static void
-yahoo_fetch_aliases_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message)
-{
-	PurpleConnection *gc = user_data;
-	YahooData *yd = gc->proto_data;
-
-	yd->url_datas = g_slist_remove(yd->url_datas, url_data);
-
-	if (len == 0) {
-		purple_debug_info("yahoo", "No Aliases to process.%s%s\n",
-						  error_message ? " Error:" : "", error_message ? error_message : "");
-	} else {
-		gchar *full_name, *nick_name;
-		const char *yid, *id, *fn, *ln, *nn, *alias, *mn;
-		const char *hp, *wp, *mo;
-		YahooFriend *f;
-		PurpleBuddy *b;
-		xmlnode *item, *contacts;
-		PurpleAccount *account;
-
-		account = purple_connection_get_account(gc);
-		/* Put our web response into a xmlnode for easy management */
-		contacts = xmlnode_from_str(url_text, -1);
-
-		if (contacts == NULL) {
-			purple_debug_error("yahoo", "Badly formed Alias XML\n");
-			return;
-		}
-		purple_debug_info("yahoo", "Fetched %" G_GSIZE_FORMAT
-				" bytes of alias data\n", len);
-
-		/* Loop around and around and around until we have gone through all the received aliases  */
-		for(item = xmlnode_get_child(contacts, "ct"); item; item = xmlnode_get_next_twin(item)) {
-			/* Yahoo replies with two types of contact (ct) record, we are only interested in the alias ones */
-			if ((yid = xmlnode_get_attrib(item, "yi"))) {
-				YahooPersonalDetails *ypd = NULL;
-				/* Grab all the bits of information we can */
-				fn = xmlnode_get_attrib(item, "fn");
-				ln = xmlnode_get_attrib(item, "ln");
-				nn = xmlnode_get_attrib(item, "nn");
-				mn = xmlnode_get_attrib(item, "mn");
-				id = xmlnode_get_attrib(item, "id");
-
-				hp = xmlnode_get_attrib(item, "hp");
-				wp = xmlnode_get_attrib(item, "wp");
-				mo = xmlnode_get_attrib(item, "mo");
-
-				full_name = nick_name = NULL;
-				alias = NULL;
-
-				/* Yahoo stores first and last names separately, lets put them together into a full name */
-				if (yd->jp)
-					full_name = g_strstrip(g_strdup_printf("%s %s", (ln != NULL ? ln : "") , (fn != NULL ? fn : "")));
-				else
-					full_name = g_strstrip(g_strdup_printf("%s %s", (fn != NULL ? fn : "") , (ln != NULL ? ln : "")));
-				nick_name = (nn != NULL ? g_strstrip(g_strdup(nn)) : NULL);
-
-				if (nick_name != NULL)
-					alias = nick_name;   /* If we have a nickname from Yahoo, let's use it */
-				else if (strlen(full_name) != 0)
-					alias = full_name;  /* If no Yahoo nickname, we can use the full_name created above */
-
-				/*  Find the local buddy that matches */
-				f = yahoo_friend_find(gc, yid);
-				b = purple_find_buddy(account, yid);
-
-				/*  If we don't find a matching buddy, ignore the alias !!  */
-				if (f != NULL && b != NULL) {
-					const char *buddy_alias = purple_buddy_get_alias(b);
-					yahoo_friend_set_alias_id(f, id);
-
-					/* Finally, if we received an alias, we better update the buddy list */
-					if (alias != NULL) {
-						serv_got_alias(gc, yid, alias);
-						purple_debug_info("yahoo", "Fetched alias '%s' (%s)\n", alias, id);
-					} else if (buddy_alias && *buddy_alias && !g_str_equal(buddy_alias, yid)) {
-					/* Or if we have an alias that Yahoo doesn't, send it up */
-						yahoo_update_alias(gc, yid, buddy_alias);
-						purple_debug_info("yahoo", "Sent updated alias '%s'\n", buddy_alias);
-					}
-				}
-
-				if (f != NULL)
-					ypd = &f->ypd;
-				else {
-					/* May be the alias is for the account? */
-					const char *yidn = purple_normalize(account, yid);
-					if (purple_strequal(yidn, purple_connection_get_display_name(gc))) {
-						ypd = &yd->ypd;
-					}
-				}
-
-				if (ypd) {
-					yahoo_personal_details_reset(ypd, TRUE);
-					ypd->id = g_strdup(id);
-					ypd->names.first = g_strdup(fn);
-					ypd->names.middle = g_strdup(mn);
-					ypd->names.last = g_strdup(ln);
-					ypd->names.nick = g_strdup(nn);
-
-					ypd->phone.work = g_strdup(wp);
-					ypd->phone.home = g_strdup(hp);
-					ypd->phone.mobile = g_strdup(mo);
-				}
-
-				g_free(full_name);
-				g_free(nick_name);
-			}
-		}
-		xmlnode_free(contacts);
-	}
-}
-
-void
-yahoo_fetch_aliases(PurpleConnection *gc)
-{
-	YahooData *yd = gc->proto_data;
-	const char *url;
-	gchar *request, *webpage, *webaddress;
-	PurpleUtilFetchUrlData *url_data;
-
-	/* use whole URL if using HTTP Proxy */
-	gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
-
-	/*  Build all the info to make the web request */
-	url = yd->jp ? YAHOOJP_ALIAS_FETCH_URL : YAHOO_ALIAS_FETCH_URL;
-	purple_url_parse(url, &webaddress, NULL, &webpage, NULL, NULL);
-	request = g_strdup_printf("GET %s%s/%s HTTP/1.1\r\n"
-				 "User-Agent: " YAHOO_CLIENT_USERAGENT_ALIAS "\r\n"
-				 "Cookie: T=%s; Y=%s\r\n"
-				 "Host: %s\r\n"
-				 "Cache-Control: no-cache\r\n\r\n",
-				  use_whole_url ? "http://" : "", use_whole_url ? webaddress : "", webpage,
-				  yd->cookie_t, yd->cookie_y,
-				  webaddress);
-
-	/* We have a URL and some header information, let's connect and get some aliases  */
-	url_data = purple_util_fetch_url_request_len_with_account(purple_connection_get_account(gc),
-				url, use_whole_url, NULL, TRUE, request, FALSE, -1,
-				yahoo_fetch_aliases_cb, gc);
-	if (url_data != NULL)
-		yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
-
-	g_free(webaddress);
-	g_free(webpage);
-	g_free(request);
-}
-
-/**************************************************************************
- * Alias Update Functions
- **************************************************************************/
-
-static void
-yahoo_update_alias_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message)
-{
-	xmlnode *node, *result;
-	struct callback_data *cb = user_data;
-	PurpleConnection *gc = cb->gc;
-	YahooData *yd;
-
-	yd = gc->proto_data;
-	yd->url_datas = g_slist_remove(yd->url_datas, url_data);
-
-	if (len == 0 || error_message != NULL) {
-		purple_debug_info("yahoo", "Error updating alias for %s: %s\n",
-				  cb->who,
-				  error_message ? error_message : "");
-		g_free(cb->who);
-		g_free(cb->id);
-		g_free(cb);
-		return;
-	}
-
-	result = xmlnode_from_str(url_text, -1);
-
-	if (result == NULL) {
-		purple_debug_error("yahoo", "Alias update for %s failed: Badly formed response\n",
-				   cb->who);
-		g_free(cb->who);
-		g_free(cb->id);
-		g_free(cb);
-		return;
-	}
-
-	if ((node = xmlnode_get_child(result, "ct"))) {
-		if (cb->id == NULL) {
-			const char *new_id = xmlnode_get_attrib(node, "id");
-			if (new_id != NULL) {
-				/* We now have an addressbook id for the friend; we should save it */
-				YahooFriend *f = yahoo_friend_find(cb->gc, cb->who);
-
-				purple_debug_info("yahoo", "Alias creation for %s succeeded\n", cb->who);
-
-				if (f)
-					yahoo_friend_set_alias_id(f, new_id);
-				else
-					purple_debug_error("yahoo", "Missing YahooFriend. Unable to store new addressbook id.\n");
-			} else
-				purple_debug_error("yahoo", "Missing new addressbook id in add response for %s (weird).\n",
-						   cb->who);
-		} else {
-			if (g_ascii_strncasecmp(xmlnode_get_attrib(node, "id"), cb->id, strlen(cb->id))==0)
-				purple_debug_info("yahoo", "Alias update for %s succeeded\n", cb->who);
-			else
-				purple_debug_error("yahoo", "Alias update for %s failed (Contact record return mismatch)\n",
-						   cb->who);
-		}
-	} else
-		purple_debug_info("yahoo", "Alias update for %s failed (No contact record returned)\n", cb->who);
-
-	g_free(cb->who);
-	g_free(cb->id);
-	g_free(cb);
-	xmlnode_free(result);
-}
-
-void
-yahoo_update_alias(PurpleConnection *gc, const char *who, const char *alias)
-{
-	YahooData *yd;
-	const char *url;
-	gchar *content, *request, *webpage, *webaddress;
-	struct callback_data *cb;
-	PurpleUtilFetchUrlData *url_data;
-	YahooFriend *f;
-	/* use whole URL if using HTTP Proxy */
-	gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
-
-	g_return_if_fail(who != NULL);
-	g_return_if_fail(gc != NULL);
-
-	if (alias == NULL)
-		alias = "";
-
-	f = yahoo_friend_find(gc, who);
-	if (f == NULL) {
-		purple_debug_error("yahoo", "Missing YahooFriend. Unable to set server alias.\n");
-		return;
-	}
-
-	yd = gc->proto_data;
-
-	/* Using callback_data so I have access to gc in the callback function */
-	cb = g_new0(struct callback_data, 1);
-	cb->who = g_strdup(who);
-	cb->id = g_strdup(yahoo_friend_get_alias_id(f));
-	cb->gc = gc;
-
-	/*  Build all the info to make the web request */
-	url = yd->jp ? YAHOOJP_ALIAS_UPDATE_URL: YAHOO_ALIAS_UPDATE_URL;
-	purple_url_parse(url, &webaddress, NULL, &webpage, NULL, NULL);
-
-	if (cb->id == NULL) {
-		/* No id for this buddy, so create an address book entry */
-		purple_debug_info("yahoo", "Creating '%s' as new alias for user '%s'\n", alias, who);
-
-		if (yd->jp) {
-			gchar *alias_jp = g_convert(alias, -1, "EUC-JP", "UTF-8", NULL, NULL, NULL);
-			gchar *converted_alias_jp = yahoo_convert_to_numeric(alias_jp);
-			content = g_strdup_printf("<ab k=\"%s\" cc=\"9\">\n"
-						  "<ct a=\"1\" yi='%s' nn='%s' />\n</ab>\r\n",
-						  purple_account_get_username(gc->account),
-						  who, converted_alias_jp);
-			g_free(converted_alias_jp);
-			g_free(alias_jp);
-		} else {
-			gchar *escaped_alias = g_markup_escape_text(alias, -1);
-			content = g_strdup_printf("<?xml version=\"1.0\" encoding=\"utf-8\"?><ab k=\"%s\" cc=\"9\">\n"
-						  "<ct a=\"1\" yi='%s' nn='%s' />\n</ab>\r\n",
-						  purple_account_get_username(gc->account),
-						  who, escaped_alias);
-			g_free(escaped_alias);
-		}
-	} else {
-		purple_debug_info("yahoo", "Updating '%s' as new alias for user '%s'\n", alias, who);
-
-		if (yd->jp) {
-			gchar *alias_jp = g_convert(alias, -1, "EUC-JP", "UTF-8", NULL, NULL, NULL);
-			gchar *converted_alias_jp = yahoo_convert_to_numeric(alias_jp);
-			content = g_strdup_printf("<ab k=\"%s\" cc=\"1\">\n"
-						  "<ct e=\"1\"  yi='%s' id='%s' nn='%s' pr='0' />\n</ab>\r\n",
-						  purple_account_get_username(gc->account),
-						  who, cb->id, converted_alias_jp);
-			g_free(converted_alias_jp);
-			g_free(alias_jp);
-		} else {
-			gchar *escaped_alias = g_markup_escape_text(alias, -1);
-			content = g_strdup_printf("<?xml version=\"1.0\" encoding=\"utf-8\"?><ab k=\"%s\" cc=\"1\">\n"
-						  "<ct e=\"1\"  yi='%s' id='%s' nn='%s' pr='0' />\n</ab>\r\n",
-						  purple_account_get_username(gc->account),
-						  who, cb->id, escaped_alias);
-			g_free(escaped_alias);
-		}
-	}
-
-	request = g_strdup_printf("POST %s%s/%s HTTP/1.1\r\n"
-				  "User-Agent: " YAHOO_CLIENT_USERAGENT_ALIAS "\r\n"
-				  "Cookie: T=%s; Y=%s\r\n"
-				  "Host: %s\r\n"
-				  "Content-Length: %" G_GSIZE_FORMAT "\r\n"
-				  "Cache-Control: no-cache\r\n\r\n"
-				  "%s",
-				  use_whole_url ? "http://" : "", use_whole_url ? webaddress : "", webpage,
-				  yd->cookie_t, yd->cookie_y,
-				  webaddress,
-				  strlen(content),
-				  content);
-
-	/* We have a URL and some header information, let's connect and update the alias  */
-	url_data = purple_util_fetch_url_request_len_with_account(
-			purple_connection_get_account(gc), url, use_whole_url, NULL, TRUE,
-			request, FALSE, -1, yahoo_update_alias_cb, cb);
-	if (url_data != NULL)
-		yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
-
-	g_free(webpage);
-	g_free(webaddress);
-	g_free(content);
-	g_free(request);
-}
-
-
-/**************************************************************************
- * User Info Update Functions
- **************************************************************************/
-
-#if 0
-/* This block of code can be used to send our contact details to
- * everyone in the buddylist. But with the official messenger,
- * doing this pops a conversation window at the receiver's end,
- * which is stupid, and thus not really surprising. */
-
-struct yahoo_userinfo {
-	YahooData *yd;
-	char *xml;
-};
-
-static void
-yahoo_send_userinfo_to_user(struct yahoo_userinfo *yui, const char *who)
-{
-	struct yahoo_packet *pkt;
-	PurpleConnection *gc;
-
-	gc = yui->yd->gc;
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CONTACT_DETAILS, 0, 0);
-	yahoo_packet_hash(pkt, "siisis",
-			1, purple_connection_get_display_name(gc),
-			13, 1,    /* This creates a conversation window in the official client */
-			302, 5,
-			5, who,
-			303, 5,
-			280, yui->xml);
-	yahoo_packet_send_and_free(pkt, yui->yd);
-}
-
-static void
-yahoo_send_userinfo_foreach(gpointer key, gpointer value, gpointer data)
-{
-	const char *who = key;
-	YahooFriend *f = value;
-
-	if (f->status != YAHOO_STATUS_OFFLINE) {
-		yahoo_send_userinfo_to_user(data, who);
-	}
-}
-
-static void
-yahoo_sent_userinfo_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message)
-{
-	struct yahoo_userinfo *yui = user_data;
-	yahoo_fetch_aliases_cb(url_data, yui->yd->gc, url_text, len, error_message);
-	g_hash_table_foreach(yui->yd->friends, yahoo_send_userinfo_foreach, yui);
-	g_free(yui->xml);
-	g_free(yui);
-}
-#endif
-
-static void
-yahoo_set_userinfo_cb(PurpleConnection *gc, PurpleRequestFields *fields)
-{
-	xmlnode *node = xmlnode_new("ab");
-	xmlnode *ct = xmlnode_new_child(node, "ct");
-	YahooData *yd = purple_connection_get_protocol_data(gc);
-	PurpleAccount *account;
-	PurpleUtilFetchUrlData *url_data;
-	char *webaddress, *webpage;
-	char *request, *content;
-	int len;
-	int i;
-	char * yfields[] = { "fn", "ln", "nn", "mn", "hp", "wp", "mo", NULL };
-
-	account = purple_connection_get_account(gc);
-
-	xmlnode_set_attrib(node, "k", purple_connection_get_display_name(gc));
-	xmlnode_set_attrib(node, "cc", "1");		/* XXX: ? */
-
-	xmlnode_set_attrib(ct, "e", "1");
-	xmlnode_set_attrib(ct, "yi", purple_request_fields_get_string(fields, "yname"));
-	xmlnode_set_attrib(ct, "id", purple_request_fields_get_string(fields, "yid"));
-	xmlnode_set_attrib(ct, "pr", "0");
-
-	for (i = 0; yfields[i]; i++) {
-		const char *v = purple_request_fields_get_string(fields, yfields[i]);
-		xmlnode_set_attrib(ct, yfields[i], v ? v : "");
-	}
-
-	content = xmlnode_to_formatted_str(node, &len);
-	xmlnode_free(node);
-	purple_url_parse(yd->jp ? YAHOOJP_USERINFO_URL : YAHOO_USERINFO_URL, &webaddress, NULL, &webpage, NULL, NULL);
-
-	request = g_strdup_printf("POST %s HTTP/1.1\r\n"
-				  "User-Agent: " YAHOO_CLIENT_USERAGENT_ALIAS "\r\n"
-				  "Cookie: T=%s; path=/; domain=.yahoo.com; Y=%s;\r\n"
-				  "Host: %s\r\n"
-				  "Content-Length: %d\r\n"
-				  "Cache-Control: no-cache\r\n\r\n"
-				  "%s\r\n\r\n",
-				  webpage,
-				  yd->cookie_t, yd->cookie_y,
-				  webaddress,
-				  len + 4,
-				  content);
-
-#if 0
-	{
-		/* This is if we wanted to send our contact details to everyone
-		 * in the buddylist. But this cannot be done now, because in the
-		 * official messenger, doing this pops a conversation window at
-		 * the receiver's end, which is stupid, and thus not really
-		 * surprising. */
-		struct yahoo_userinfo *ui = g_new(struct yahoo_userinfo, 1);
-		node = xmlnode_new("contact");
-
-		for (i = 0; yfields[i]; i++) {
-			const char *v = purple_request_fields_get_string(fields, yfields[i]);
-			if (v) {
-				xmlnode *nd = xmlnode_new_child(node, yfields[i]);
-				xmlnode_insert_data(nd, v, -1);
-			}
-		}
-
-		ui->yd = yd;
-		ui->xml = xmlnode_to_str(node, NULL);
-		xmlnode_free(node);
-	}
-#endif
-
-	url_data = purple_util_fetch_url_request_len_with_account(account, webaddress, FALSE,
-			YAHOO_CLIENT_USERAGENT_ALIAS, TRUE, request, FALSE, -1,
-			yahoo_fetch_aliases_cb, gc);
-	if (url_data != NULL)
-		yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
-
-	g_free(webaddress);
-	g_free(webpage);
-	g_free(content);
-	g_free(request);
-}
-
-static PurpleRequestFields *
-request_fields_from_personal_details(YahooPersonalDetails *ypd, const char *id)
-{
-	PurpleRequestFields *fields;
-	PurpleRequestFieldGroup *group;
-	PurpleRequestField *field;
-	int i;
-	struct {
-		char *id;
-		char *text;
-		char *value;
-	} yfields[] = {
-		{"fn", N_("First Name"), ypd->names.first},
-		{"ln", N_("Last Name"), ypd->names.last},
-		{"nn", N_("Nickname"), ypd->names.nick},
-		{"mn", N_("Middle Name"), ypd->names.middle},
-		{"hp", N_("Home Phone Number"), ypd->phone.home},
-		{"wp", N_("Work Phone Number"), ypd->phone.work},
-		{"mo", N_("Mobile Phone Number"), ypd->phone.mobile},
-		{NULL, NULL, NULL}
-	};
-
-	fields = purple_request_fields_new();
-	group = purple_request_field_group_new(NULL);
-	purple_request_fields_add_group(fields, group);
-
-	field = purple_request_field_string_new("yname", "", id, FALSE);
-	purple_request_field_set_visible(field, FALSE);
-	purple_request_field_group_add_field(group, field);
-
-	field = purple_request_field_string_new("yid", "", ypd->id, FALSE);
-	purple_request_field_set_visible(field, FALSE);
-	purple_request_field_group_add_field(group, field);
-
-	for (i = 0; yfields[i].id; i++) {
-		field = purple_request_field_string_new(yfields[i].id, _(yfields[i].text),
-				yfields[i].value, FALSE);
-		purple_request_field_group_add_field(group, field);
-	}
-
-	return fields;
-}
-
-void yahoo_set_userinfo_for_buddy(PurpleConnection *gc, PurpleBuddy *buddy)
-{
-	PurpleRequestFields *fields;
-	YahooFriend *f;
-	const char *name;
-
-	name = purple_buddy_get_name(buddy);
-	f = yahoo_friend_find(gc, name);
-	if (!f)
-		return;
-
-	fields = request_fields_from_personal_details(&f->ypd, name);
-	purple_request_fields(gc, NULL, _("Set User Info"), NULL, fields,
-			_("OK"), G_CALLBACK(yahoo_set_userinfo_cb),
-			_("Cancel"), NULL,
-			purple_connection_get_account(gc), NULL, NULL, gc);
-}
-
-void yahoo_set_userinfo(PurpleConnection *gc)
-{
-	YahooData *yd = purple_connection_get_protocol_data(gc);
-	PurpleRequestFields *fields = request_fields_from_personal_details(&yd->ypd,
-					purple_connection_get_display_name(gc));
-	purple_request_fields(gc, NULL, _("Set User Info"), NULL, fields,
-			_("OK"), G_CALLBACK(yahoo_set_userinfo_cb),
-			_("Cancel"), NULL,
-			purple_connection_get_account(gc), NULL, NULL, gc);
-}
-
-static gboolean
-parse_contact_details(YahooData *yd, const char *who, const char *xml)
-{
-	xmlnode *node, *nd;
-	YahooFriend *f;
-	char *yid;
-
-	node = xmlnode_from_str(xml, -1);
-	if (!node) {
-		purple_debug_info("yahoo", "Received malformed XML for contact details from '%s':\n%s\n",
-				who, xml);
-		return FALSE;
-	}
-
-	nd = xmlnode_get_child(node, "yi");
-	if (!nd || !(yid = xmlnode_get_data(nd))) {
-		xmlnode_free(node);
-		return FALSE;
-	}
-
-	if (!purple_strequal(yid, who)) {
-		/* The user may not want to set the contact details about folks in the buddylist
-		   to what some random dude might have sent. So it would be good if we popped
-		   up a prompt requiring the user to confirm the details before we set them.
-		   However, someone could send details about hundreds of users at the same time,
-		   which would make things really bad. So for now, until we have a better way of
-		   dealing with this, ignore this details. */
-		purple_debug_info("yahoo", "Ignoring contact details sent by %s about %s\n",
-				who, yid);
-		g_free(yid);
-		xmlnode_free(node);
-		return FALSE;
-	}
-
-	f = yahoo_friend_find(yd->gc, yid);
-	if (!f) {
-		g_free(yid);
-		xmlnode_free(node);
-		return FALSE;
-	} else {
-		int i;
-		YahooPersonalDetails *ypd = &f->ypd;
-		char *alias = NULL;
-		struct {
-			char *id;
-			char **field;
-		} details[] = {
-			{"fn", &ypd->names.first},
-			{"mn", &ypd->names.middle},
-			{"ln", &ypd->names.last},
-			{"nn", &ypd->names.nick},
-			{"wp", &ypd->phone.work},
-			{"hp", &ypd->phone.home},
-			{"mo", &ypd->phone.mobile},
-			{NULL, NULL}
-		};
-
-		yahoo_personal_details_reset(ypd, FALSE);
-
-		for (i = 0; details[i].id; i++) {
-			nd = xmlnode_get_child(node, details[i].id);
-			*details[i].field = nd ? xmlnode_get_data(nd) : NULL;
-		}
-
-		if (ypd->names.nick)
-			alias = ypd->names.nick;
-		else if (ypd->names.first || ypd->names.last) {
-			alias = g_strstrip(g_strdup_printf("%s %s",
-						ypd->names.first ? ypd->names.first : "",
-						ypd->names.last ? ypd->names.last : ""));
-		}
-
-		if (alias) {
-			serv_got_alias(yd->gc, yid, alias);
-			if (alias != ypd->names.nick)
-				g_free(alias);
-		}
-	}
-
-	xmlnode_free(node);
-	g_free(yid);
-	return TRUE;
-}
-
-/* I don't think this happens for MSN buddies. -- sad */
-void yahoo_process_contact_details(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	GSList *l = pkt->hash;
-	const char *who = NULL, *xml = NULL;
-	YahooData *yd = purple_connection_get_protocol_data(gc);
-
-	for (; l; l = l->next) {
-		struct yahoo_pair *pair = l->data;
-		switch (pair->key) {
-			case 4:
-				if (g_utf8_validate(pair->value, -1, NULL)) {
-					/* This is the person who sent us the details.
-					   But not necessarily about himself. */
-					who = pair->value;
-				} else {
-					purple_debug_warning("yahoo", "yahoo_process_contact_details "
-							"got non-UTF-8 string for key %d\n", pair->key);
-				}
-				break;
-			case 5:
-				break;
-			case 13:
-				/* This is '1' if 'who' is sending the contact details about herself,
-				   '0' if 'who' is sending the contact details she has about buddies
-				   in her list. However, in all cases, the xml in key 280 always seems
-				   to contain the yid of the person, so we may as well ignore this field
-				   and look into the xml instead to see who the information is about. */
-				break;
-			case 280:
-				if (g_utf8_validate(pair->value, -1, NULL)) {
-					xml = pair->value;
-					parse_contact_details(yd, who, xml);
-				} else {
-					purple_debug_warning("yahoo", "yahoo_process_contact_details "
-							"got non-UTF-8 string for key %d\n", pair->key);
-				}
-				break;
-		}
-	}
-}
-
--- a/libpurple/protocols/yahoo/yahoo_aliases.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +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 "accountopt.h"
-#include "blist.h"
-#include "debug.h"
-#include "util.h"
-#include "version.h"
-#include "libymsg.h"
-#include "yahoo_packet.h"
-
-void yahoo_update_alias(PurpleConnection *gc, const char *who, const char *alias);
-void yahoo_fetch_aliases(PurpleConnection *gc);
-void yahoo_set_userinfo(PurpleConnection *gc);
-void yahoo_set_userinfo_for_buddy(PurpleConnection *gc, PurpleBuddy *buddy);
-void yahoo_personal_details_reset(YahooPersonalDetails *ypd, gboolean all);
-void yahoo_process_contact_details(PurpleConnection *gc, struct yahoo_packet *pkt);
--- a/libpurple/protocols/yahoo/yahoo_doodle.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,609 +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
- *
- */
-
-/******************************************************************************
- * INCLUDES
- *****************************************************************************/
-#include "internal.h"
-
-#include "account.h"
-#include "accountopt.h"
-#include "blist.h"
-#include "cipher.h"
-#include "cmds.h"
-#include "debug.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 "libymsg.h"
-#include "yahoo_packet.h"
-#include "yahoo_friend.h"
-#include "yahoochat.h"
-#include "ycht.h"
-#include "yahoo_filexfer.h"
-#include "yahoo_picture.h"
-
-#include "whiteboard.h"
-#include "yahoo_doodle.h"
-
-/******************************************************************************
- * Globals
- *****************************************************************************/
-#if 0
-const int DefaultColorRGB24[] =
-{
-	DOODLE_COLOR_RED,
-	DOODLE_COLOR_ORANGE,
-	DOODLE_COLOR_YELLOW,
-	DOODLE_COLOR_GREEN,
-	DOODLE_COLOR_CYAN,
-	DOODLE_COLOR_BLUE,
-	DOODLE_COLOR_VIOLET,
-	DOODLE_COLOR_PURPLE,
-	DOODLE_COLOR_TAN,
-	DOODLE_COLOR_BROWN,
-	DOODLE_COLOR_BLACK,
-	DOODLE_COLOR_GREY,
-	DOODLE_COLOR_WHITE
-};
-#endif
-
-/******************************************************************************
- * Functions
- *****************************************************************************/
-PurpleCmdRet yahoo_doodle_purple_cmd_start(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data)
-{
-	PurpleAccount *account;
-	PurpleConnection *gc;
-	const gchar *name;
-
-	if(*args && args[0])
-		return PURPLE_CMD_RET_FAILED;
-
-	account = purple_conversation_get_account(conv);
-	gc = purple_account_get_connection(account);
-	name = purple_conversation_get_name(conv);
-	yahoo_doodle_initiate(gc, name);
-
-	/* Write a local message to this conversation showing that a request for a
-	 * Doodle session has been made
-	 */
-	purple_conv_im_write(PURPLE_CONV_IM(conv), "", _("Sent Doodle request."),
-					   PURPLE_MESSAGE_NICK | PURPLE_MESSAGE_RECV, time(NULL));
-
-	return PURPLE_CMD_RET_OK;
-}
-
-void yahoo_doodle_initiate(PurpleConnection *gc, const char *name)
-{
-	PurpleAccount *account;
-	char *to = (char*)name;
-
-	g_return_if_fail(gc);
-	g_return_if_fail(name);
-
-	account = purple_connection_get_account(gc);
-
-	if(purple_whiteboard_get_session(account, to) == NULL)
-	{
-		/* Insert this 'session' in the list.  At this point, it's only a
-		 * requested session.
-		 */
-		purple_whiteboard_create(account, to, DOODLE_STATE_REQUESTING);
-	}
-
-	/* NOTE Perhaps some careful handling of remote assumed established
-	 * sessions
-	 */
-
-	yahoo_doodle_command_send_ready(gc, to, DOODLE_IMV_KEY);
-	yahoo_doodle_command_send_request(gc, to, DOODLE_IMV_KEY);
-
-}
-
-static void yahoo_doodle_command_got_request(PurpleConnection *gc, const char *from, const char *imv_key)
-{
-	PurpleAccount *account;
-	PurpleWhiteboard *wb;
-
-	purple_debug_info("yahoo", "doodle: Got Request (%s)\n", from);
-
-	account = purple_connection_get_account(gc);
-
-	/* Only handle this if local client requested Doodle session (else local
-	 * client would have sent one)
-	 */
-	wb = purple_whiteboard_get_session(account, from);
-
-	/* If a session with the remote user doesn't exist */
-	if(wb == NULL)
-	{
-		doodle_session *ds;
-		/* Ask user if they wish to accept the request for a doodle session */
-		/* TODO Ask local user to start Doodle session with remote user */
-		/* NOTE This if/else statement won't work right--must use dialog
-		 * results
-		 */
-
-		/* char dialog_message[64];
-		g_sprintf(dialog_message, "%s is requesting to start a Doodle session with you.", from);
-
-		purple_notify_message(NULL, PURPLE_NOTIFY_MSG_INFO, "Doodle",
-		dialog_message, NULL, NULL, NULL);
-		*/
-
-		wb = purple_whiteboard_create(account, from, DOODLE_STATE_REQUESTED);
-		ds = wb->proto_data;
-		ds->imv_key = g_strdup(imv_key);
-
-		yahoo_doodle_command_send_ready(gc, from, imv_key);
-	}
-
-	/* TODO Might be required to clear the canvas of an existing doodle
-	 * session at this point
-	 */
-}
-
-static void yahoo_doodle_command_got_ready(PurpleConnection *gc, const char *from, const char *imv_key)
-{
-	PurpleAccount *account;
-	PurpleWhiteboard *wb;
-
-	purple_debug_info("yahoo", "doodle: Got Ready(%s)\n", from);
-
-	account = purple_connection_get_account(gc);
-
-	/* Only handle this if local client requested Doodle session (else local
-	 * client would have sent one)
-	 */
-	wb = purple_whiteboard_get_session(account, from);
-
-	if(wb == NULL)
-		return;
-
-	if(wb->state == DOODLE_STATE_REQUESTING)
-	{
-		doodle_session *ds = wb->proto_data;
-		purple_whiteboard_start(wb);
-
-		wb->state = DOODLE_STATE_ESTABLISHED;
-
-		yahoo_doodle_command_send_confirm(gc, from, imv_key);
-		/* Let's steal the imv_key and reuse it */
-		g_free(ds->imv_key);
-		ds->imv_key = g_strdup(imv_key);
-	}
-	else if(wb->state == DOODLE_STATE_ESTABLISHED)
-	{
-		/* TODO Ask whether to save picture too */
-		purple_whiteboard_clear(wb);
-	}
-
-	/* NOTE Not sure about this... I am trying to handle if the remote user
-	 * already thinks we're in a session with them (when their chat message
-	 * contains the doodle imv key)
-	 */
-	else if(wb->state == DOODLE_STATE_REQUESTED)
-	{
-		/* purple_whiteboard_start(wb); */
-		yahoo_doodle_command_send_ready(gc, from, imv_key);
-	}
-}
-
-static void yahoo_doodle_command_got_draw(PurpleConnection *gc, const char *from, const char *message)
-{
-	PurpleAccount *account;
-	PurpleWhiteboard *wb;
-	char **tokens;
-	int i;
-	GList *d_list = NULL; /* a local list of drawing info */
-
-	g_return_if_fail(message != NULL);
-
-	purple_debug_info("yahoo", "doodle: Got Draw (%s)\n", from);
-	purple_debug_info("yahoo", "doodle: Draw message: %s\n", message);
-
-	account = purple_connection_get_account(gc);
-
-	/* Only handle this if local client requested Doodle session (else local
-	 * client would have sent one)
-	 */
-	wb = purple_whiteboard_get_session(account, from);
-
-	if(wb == NULL)
-		return;
-
-	/* TODO Functionalize
-	 * Convert drawing packet message to an integer list
-	 */
-
-	/* Check to see if the message begans and ends with quotes */
-	if((message[0] != '\"') || (message[strlen(message) - 1] != '\"'))
-		return;
-
-	/* Ignore the inital quotation mark. */
-	message += 1;
-
-	tokens = g_strsplit(message, ",", 0);
-
-	/* Traverse and extract all integers divided by commas */
-	for (i = 0; tokens[i] != NULL; i++)
-	{
-		int last = strlen(tokens[i]) - 1;
-		if (tokens[i][last] == '"')
-			tokens[i][last] = '\0';
-
-		d_list = g_list_prepend(d_list, GINT_TO_POINTER(atoi(tokens[i])));
-	}
-	d_list = g_list_reverse(d_list);
-
-	g_strfreev(tokens);
-
-	yahoo_doodle_draw_stroke(wb, d_list);
-
-	/* goodle_doodle_session_set_canvas_as_icon(ds); */
-
-	g_list_free(d_list);
-}
-
-
-static void yahoo_doodle_command_got_clear(PurpleConnection *gc, const char *from)
-{
-	PurpleAccount *account;
-	PurpleWhiteboard *wb;
-
-	purple_debug_info("yahoo", "doodle: Got Clear (%s)\n", from);
-
-	account = purple_connection_get_account(gc);
-
-	/* Only handle this if local client requested Doodle session (else local
-	 * client would have sent one)
-	 */
-	wb = purple_whiteboard_get_session(account, from);
-
-	if(wb == NULL)
-		return;
-
-	if(wb->state == DOODLE_STATE_ESTABLISHED)
-	{
-		/* TODO Ask user whether to save the image before clearing it */
-
-		purple_whiteboard_clear(wb);
-	}
-}
-
-
-static void
-yahoo_doodle_command_got_extra(PurpleConnection *gc, const char *from, const char *message, const char *imv_key)
-{
-	purple_debug_info("yahoo", "doodle: Got Extra (%s)\n", from);
-
-	/* I do not like these 'extra' features, so I'll only handle them in one
-	 * way, which is returning them with the command/packet to turn them off
-	 */
-	yahoo_doodle_command_send_extra(gc, from, DOODLE_EXTRA_NONE, imv_key);
-}
-
-static void yahoo_doodle_command_got_confirm(PurpleConnection *gc, const char *from)
-{
-	PurpleAccount *account;
-	PurpleWhiteboard *wb;
-
-	purple_debug_info("yahoo", "doodle: Got Confirm (%s)\n", from);
-
-	/* Get the doodle session */
-	account = purple_connection_get_account(gc);
-
-	/* Only handle this if local client requested Doodle session (else local
-	 * client would have sent one)
-	 */
-	wb = purple_whiteboard_get_session(account, from);
-
-	if(wb == NULL)
-		return;
-
-	/* TODO Combine the following IF's? */
-
-	/* Check if we requested a doodle session */
-	/*if(wb->state == DOODLE_STATE_REQUESTING)
-	{
-		wb->state = DOODLE_STATE_ESTABLISHED;
-
-		purple_whiteboard_start(wb);
-
-		yahoo_doodle_command_send_confirm(gc, from);
-	}*/
-
-	/* Check if we accepted a request for a doodle session */
-	if(wb->state == DOODLE_STATE_REQUESTED)
-	{
-		wb->state = DOODLE_STATE_ESTABLISHED;
-
-		purple_whiteboard_start(wb);
-	}
-}
-
-void yahoo_doodle_command_got_shutdown(PurpleConnection *gc, const char *from)
-{
-	PurpleAccount *account;
-	PurpleWhiteboard *wb;
-
-	g_return_if_fail(from != NULL);
-
-	purple_debug_info("yahoo", "doodle: Got Shutdown (%s)\n", from);
-
-	account = purple_connection_get_account(gc);
-
-	/* Only handle this if local client requested Doodle session (else local
-	 * client would have sent one)
-	 */
-	wb = purple_whiteboard_get_session(account, from);
-
-	if(wb == NULL)
-		return;
-
-	/* TODO Ask if user wants to save picture before the session is closed */
-
-	wb->state = DOODLE_STATE_CANCELLED;
-	purple_whiteboard_destroy(wb);
-}
-
-static void yahoo_doodle_command_send_generic(const char *type,
-											  PurpleConnection *gc,
-											  const char *to,
-											  const char *message,
-											  int command,
-											  const char *imv,
-											  const char *sixtyfour)
-{
-	YahooData *yd;
-	struct yahoo_packet *pkt;
-
-	purple_debug_info("yahoo", "doodle: Sent %s (%s)\n", type, to);
-
-	yd = gc->proto_data;
-
-	/* Make and send an acknowledge (ready) Doodle packet */
-	pkt = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash_str(pkt, 49,  "IMVIRONMENT");
-	yahoo_packet_hash_str(pkt, 1,    purple_account_get_username(gc->account));
-	yahoo_packet_hash_str(pkt, 14,   message);
-	yahoo_packet_hash_int(pkt, 13,   command);
-	yahoo_packet_hash_str(pkt, 5,    to);
-	yahoo_packet_hash_str(pkt, 63,   imv ? imv : DOODLE_IMV_KEY);
-	yahoo_packet_hash_str(pkt, 64,   sixtyfour);
-	yahoo_packet_hash_str(pkt, 1002, "1");
-
-	yahoo_packet_send_and_free(pkt, yd);
-}
-
-void yahoo_doodle_command_send_ready(PurpleConnection *gc, const char *to, const char *imv_key)
-{
-	yahoo_doodle_command_send_generic("Ready", gc, to, "1", DOODLE_CMD_READY, imv_key, "1");
-}
-
-void yahoo_doodle_command_send_request(PurpleConnection *gc, const char *to, const char *imv_key)
-{
-	yahoo_doodle_command_send_generic("Request", gc, to, "", DOODLE_CMD_REQUEST, imv_key, "0");
-}
-
-void yahoo_doodle_command_send_draw(PurpleConnection *gc, const char *to, const char *message, const char *imv_key)
-{
-	yahoo_doodle_command_send_generic("Draw", gc, to, message, DOODLE_CMD_DRAW, imv_key, "1");
-}
-
-void yahoo_doodle_command_send_clear(PurpleConnection *gc, const char *to, const char *imv_key)
-{
-	yahoo_doodle_command_send_generic("Clear", gc, to, " ", DOODLE_CMD_CLEAR, imv_key, "1");
-}
-
-void yahoo_doodle_command_send_extra(PurpleConnection *gc, const char *to, const char *message, const char *imv_key)
-{
-	yahoo_doodle_command_send_generic("Extra", gc, to, message, DOODLE_CMD_EXTRA, imv_key, "1");
-}
-
-void yahoo_doodle_command_send_confirm(PurpleConnection *gc, const char *to, const char *imv_key)
-{
-	yahoo_doodle_command_send_generic("Confirm", gc, to, "1", DOODLE_CMD_CONFIRM, imv_key, "1");
-}
-
-void yahoo_doodle_command_send_shutdown(PurpleConnection *gc, const char *to)
-{
-	yahoo_doodle_command_send_generic("Shutdown", gc, to, "", DOODLE_CMD_SHUTDOWN, ";0", "0");
-}
-
-void yahoo_doodle_start(PurpleWhiteboard *wb)
-{
-	doodle_session *ds = g_new0(doodle_session, 1);
-
-	/* purple_debug_debug("yahoo", "doodle: yahoo_doodle_start()\n"); */
-
-	/* Set default brush size and color */
-	ds->brush_size  = DOODLE_BRUSH_SMALL;
-	ds->brush_color = DOODLE_COLOR_RED;
-
-	wb->proto_data = ds;
-}
-
-void yahoo_doodle_end(PurpleWhiteboard *wb)
-{
-	PurpleConnection *gc = purple_account_get_connection(wb->account);
-	doodle_session *ds = wb->proto_data;
-
-	/* g_debug_debug("yahoo", "doodle: yahoo_doodle_end()\n"); */
-
-	if (gc && wb->state != DOODLE_STATE_CANCELLED)
-		yahoo_doodle_command_send_shutdown(gc, wb->who);
-
-	g_free(ds->imv_key);
-	g_free(wb->proto_data);
-}
-
-void yahoo_doodle_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height)
-{
-	/* standard Doodle canvases are of one size:  368x256 */
-	*width = DOODLE_CANVAS_WIDTH;
-	*height = DOODLE_CANVAS_HEIGHT;
-}
-
-static char *yahoo_doodle_build_draw_string(doodle_session *ds, GList *draw_list)
-{
-	GString *message;
-
-	g_return_val_if_fail(draw_list != NULL, NULL);
-
-	message = g_string_new("");
-	g_string_printf(message, "\"%d,%d", ds->brush_color, ds->brush_size);
-
-	for(; draw_list != NULL; draw_list = draw_list->next)
-	{
-		g_string_append_printf(message, ",%d", GPOINTER_TO_INT(draw_list->data));
-	}
-	g_string_append_c(message, '"');
-
-	return g_string_free(message, FALSE);
-}
-
-void yahoo_doodle_send_draw_list(PurpleWhiteboard *wb, GList *draw_list)
-{
-	doodle_session *ds = wb->proto_data;
-	char *message;
-
-	g_return_if_fail(draw_list != NULL);
-
-	message = yahoo_doodle_build_draw_string(ds, draw_list);
-	yahoo_doodle_command_send_draw(wb->account->gc, wb->who, message, ds->imv_key);
-	g_free(message);
-}
-
-void yahoo_doodle_clear(PurpleWhiteboard *wb)
-{
-	doodle_session *ds = wb->proto_data;
-	yahoo_doodle_command_send_clear(wb->account->gc, wb->who, ds->imv_key);
-}
-
-
-/* Traverse through the list and draw the points and lines */
-void yahoo_doodle_draw_stroke(PurpleWhiteboard *wb, GList *draw_list)
-{
-	int brush_color;
-	int brush_size;
-	int x;
-	int y;
-
-	g_return_if_fail(draw_list != NULL);
-
-	brush_color = GPOINTER_TO_INT(draw_list->data);
-	draw_list = draw_list->next;
-	g_return_if_fail(draw_list != NULL);
-
-	brush_size = GPOINTER_TO_INT(draw_list->data);
-	draw_list = draw_list->next;
-	g_return_if_fail(draw_list != NULL);
-
-	x = GPOINTER_TO_INT(draw_list->data);
-	draw_list = draw_list->next;
-	g_return_if_fail(draw_list != NULL);
-
-	y = GPOINTER_TO_INT(draw_list->data);
-	draw_list = draw_list->next;
-	g_return_if_fail(draw_list != NULL);
-
-	/*
-	purple_debug_debug("yahoo", "doodle: Drawing: color=%d, size=%d, (%d,%d)\n", brush_color, brush_size, x, y);
-	*/
-
-	while(draw_list != NULL && draw_list->next != NULL)
-	{
-		int dx = GPOINTER_TO_INT(draw_list->data);
-		int dy = GPOINTER_TO_INT(draw_list->next->data);
-
-		purple_whiteboard_draw_line(wb,
-								  x, y,
-								  x + dx, y + dy,
-								  brush_color, brush_size);
-
-		x += dx;
-		y += dy;
-
-		draw_list = draw_list->next->next;
-	}
-}
-
-void yahoo_doodle_get_brush(const PurpleWhiteboard *wb, int *size, int *color)
-{
-	doodle_session *ds = wb->proto_data;
-	*size = ds->brush_size;
-	*color = ds->brush_color;
-}
-
-void yahoo_doodle_set_brush(PurpleWhiteboard *wb, int size, int color)
-{
-	doodle_session *ds = wb->proto_data;
-	ds->brush_size = size;
-	ds->brush_color = color;
-
-	/* Notify the core about the changes */
-	purple_whiteboard_set_brush(wb, size, color);
-}
-
-void yahoo_doodle_process(PurpleConnection *gc, const char *me, const char *from,
-						  const char *command, const char *message, const char *imv_key)
-{
-	if(!command)
-		return;
-
-	/* Now check to see what sort of Doodle message it is */
-	switch(atoi(command))
-	{
-		case DOODLE_CMD_REQUEST:
-			yahoo_doodle_command_got_request(gc, from, imv_key);
-			break;
-
-		case DOODLE_CMD_READY:
-			yahoo_doodle_command_got_ready(gc, from, imv_key);
-			break;
-
-		case DOODLE_CMD_CLEAR:
-			yahoo_doodle_command_got_clear(gc, from);
-			break;
-
-		case DOODLE_CMD_DRAW:
-			yahoo_doodle_command_got_draw(gc, from, message);
-			break;
-
-		case DOODLE_CMD_EXTRA:
-			yahoo_doodle_command_got_extra(gc, from, message, imv_key);
-			break;
-
-		case DOODLE_CMD_CONFIRM:
-			yahoo_doodle_command_got_confirm(gc, from);
-			break;
-	}
-}
--- a/libpurple/protocols/yahoo/yahoo_doodle.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/**
- * @file yahoo_doodle.h The Yahoo! protocol plugin Doodle IMVironment object
- *
- * 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 _YAHOO_DOODLE_H_
-#define _YAHOO_DOODLE_H_
-
-/******************************************************************************
- * Includes
- *****************************************************************************/
-#include "whiteboard.h"
-#include "cmds.h"
-
-#define DOODLE_IMV_KEY "doodle;106"
-
-/******************************************************************************
- * Defines
- *****************************************************************************/
-/* Doodle communication commands */
-/* TODO: Should be an enum. */
-#define DOODLE_CMD_REQUEST	0
-#define DOODLE_CMD_CLEAR	1
-#define DOODLE_CMD_DRAW		2
-#define DOODLE_CMD_EXTRA	3
-#define DOODLE_CMD_READY	4
-#define DOODLE_CMD_CONFIRM	5
-/* Doodle communication command for shutting down (also 0) */
-#define DOODLE_CMD_SHUTDOWN 0
-
-#define DOODLE_EXTRA_NONE      "\"1\""
-#define DOODLE_EXTRA_TICTACTOE "\"3\""
-#define DOODLE_EXTRA_DOTS      "\"2\""
-
-/* Doodle session states */
-/* TODO: Should be an enum. */
-#define DOODLE_STATE_REQUESTING  0
-#define DOODLE_STATE_REQUESTED   1
-#define DOODLE_STATE_ESTABLISHED 2
-#define DOODLE_STATE_CANCELLED    3
-
-/* Doodle canvas dimensions */
-#define DOODLE_CANVAS_WIDTH  368
-#define DOODLE_CANVAS_HEIGHT 256
-
-/* Doodle color codes (most likely RGB) */
-/* TODO: Should be an enum and sorted by color name. */
-#define	DOODLE_COLOR_RED    13369344
-#define	DOODLE_COLOR_ORANGE 16737792
-#define	DOODLE_COLOR_YELLOW 15658496
-#define	DOODLE_COLOR_GREEN     52224
-#define	DOODLE_COLOR_CYAN      52428
-#define	DOODLE_COLOR_BLUE        204
-#define	DOODLE_COLOR_VIOLET  5381277
-#define	DOODLE_COLOR_PURPLE 13369548
-#define	DOODLE_COLOR_TAN    12093547
-#define	DOODLE_COLOR_BROWN   5256485
-#define	DOODLE_COLOR_BLACK         0
-#define	DOODLE_COLOR_GREY   11184810
-#define	DOODLE_COLOR_WHITE  16777215
-
-#define PALETTE_NUM_OF_COLORS 12
-
-/* Doodle brush sizes (most likely variable) */
-#define DOODLE_BRUSH_SMALL   2
-#define DOODLE_BRUSH_MEDIUM  5
-#define DOODLE_BRUSH_LARGE  10
-
-#define DOODLE_MAX_BRUSH_MOTIONS 100
-
-/******************************************************************************
- * Datatypes
- *****************************************************************************/
-typedef struct _doodle_session
-{
-	int brush_size;  /* Size of drawing brush */
-	int brush_color; /* Color of drawing brush */
-	gchar *imv_key;
-} doodle_session;
-
-/******************************************************************************
- * API
- *****************************************************************************/
-
-PurpleCmdRet yahoo_doodle_purple_cmd_start(PurpleConversation *conv, const char *cmd, char **args,
-									   char **error, void *data);
-
-void yahoo_doodle_process(PurpleConnection *gc, const char *me, const char *from,
-						  const char *command, const char *message, const char *imv_key);
-void yahoo_doodle_initiate(PurpleConnection *gc, const char *to);
-
-void yahoo_doodle_command_got_shutdown(PurpleConnection *gc, const char *from);
-
-void yahoo_doodle_command_send_request(PurpleConnection *gc, const char *to, const char *imv_key);
-void yahoo_doodle_command_send_ready(PurpleConnection *gc, const char *to, const char *imv_key);
-void yahoo_doodle_command_send_draw(PurpleConnection *gc, const char *to, const char *message, const char *imv_key);
-void yahoo_doodle_command_send_clear(PurpleConnection *gc, const char *to, const char *imv_key);
-void yahoo_doodle_command_send_extra(PurpleConnection *gc, const char *to, const char *message, const char *imv_key);
-void yahoo_doodle_command_send_confirm(PurpleConnection *gc, const char *to, const char *imv_key);
-void yahoo_doodle_command_send_shutdown(PurpleConnection *gc, const char *to);
-
-void yahoo_doodle_start(PurpleWhiteboard *wb);
-void yahoo_doodle_end(PurpleWhiteboard *wb);
-void yahoo_doodle_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height);
-void yahoo_doodle_send_draw_list(PurpleWhiteboard *wb, GList *draw_list);
-void yahoo_doodle_clear(PurpleWhiteboard *wb);
-
-void yahoo_doodle_draw_stroke(PurpleWhiteboard *wb, GList *draw_list);
-void yahoo_doodle_get_brush(const PurpleWhiteboard *wb, int *size, int *color);
-void yahoo_doodle_set_brush(PurpleWhiteboard *wb, int size, int color);
-
-#endif /* _YAHOO_DOODLE_H_ */
--- a/libpurple/protocols/yahoo/yahoo_filexfer.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2048 +0,0 @@
-/*
- * @file yahoo_filexfer.c Yahoo Filetransfer
- *
- * 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 "dnsquery.h"
-
-#include "prpl.h"
-#include "util.h"
-#include "debug.h"
-#include "network.h"
-#include "notify.h"
-#include "proxy.h"
-#include "ft.h"
-#include "libymsg.h"
-#include "yahoo_packet.h"
-#include "yahoo_filexfer.h"
-#include "yahoo_doodle.h"
-#include "yahoo_friend.h"
-
-struct yahoo_xfer_data {
-	gchar *host;
-	gchar *path;
-	int port;
-	PurpleConnection *gc;
-	long expires;
-	gboolean started;
-	gchar *txbuf;
-	gsize txbuflen;
-	gsize txbuf_written;
-	guint tx_handler;
-	gchar *rxqueue;
-	guint rxlen;
-	gchar *xfer_peer_idstring;
-	gchar *xfer_idstring_for_relay;
-	int version; /* 0 for old, 15 for Y7(YMSG 15) */
-	int info_val_249;
-
-	enum {
-		STARTED = 0,
-		HEAD_REQUESTED,
-		HEAD_REPLY_RECEIVED,
-		TRANSFER_PHASE,
-		ACCEPTED,
-		P2P_HEAD_REQUESTED,
-		P2P_HEAD_REPLIED,
-		P2P_GET_REQUESTED
-	} status_15;
-
-	/* contains all filenames, in case of multiple transfers, with the first
-	 * one in the list being the current file's name (ymsg15) */
-	GSList *filename_list;
-	GSList *size_list; /* corresponds to filename_list, with size as **STRING** */
-	gboolean firstoflist;
-	gchar *xfer_url;	/* url of the file, used when we are p2p server */
-	int yahoo_local_p2p_ft_server_fd;
-	int yahoo_local_p2p_ft_server_port;
-	int yahoo_p2p_ft_server_watcher;
-	int input_event;
-};
-
-static void yahoo_xfer_data_free(struct yahoo_xfer_data *xd)
-{
-	PurpleConnection *gc;
-	YahooData *yd;
-	PurpleXfer *xfer;
-	GSList *l;
-
-	gc = xd->gc;
-	yd = gc->proto_data;
-
-	/* remove entry from map */
-	if(xd->xfer_peer_idstring) {
-		xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xd->xfer_peer_idstring);
-		if(xfer)
-			g_hash_table_remove(yd->xfer_peer_idstring_map, xd->xfer_peer_idstring);
-	}
-
-	/* empty file & filesize list */
-	for (l = xd->filename_list; l; l = l->next) {
-		g_free(l->data);
-		l->data=NULL;
-	}
-	for (l = xd->size_list; l; l = l->next) {
-		g_free(l->data);
-		l->data=NULL;
-	}
-	g_slist_free(xd->filename_list);
-	g_slist_free(xd->size_list);
-
-	g_free(xd->host);
-	g_free(xd->path);
-	g_free(xd->txbuf);
-	g_free(xd->xfer_peer_idstring);
-	g_free(xd->xfer_idstring_for_relay);
-	if (xd->tx_handler)
-		purple_input_remove(xd->tx_handler);
-	g_free(xd);
-}
-
-static void yahoo_receivefile_send_cb(gpointer data, gint source, PurpleInputCondition condition)
-{
-	PurpleXfer *xfer;
-	struct yahoo_xfer_data *xd;
-	int remaining, written;
-
-	xfer = data;
-	xd = xfer->data;
-
-	remaining = xd->txbuflen - xd->txbuf_written;
-	written = write(xfer->fd, xd->txbuf + xd->txbuf_written, remaining);
-
-	if (written < 0 && errno == EAGAIN)
-		written = 0;
-	else if (written <= 0) {
-		purple_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno);
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	if (written < remaining) {
-		xd->txbuf_written += written;
-		return;
-	}
-
-	purple_input_remove(xd->tx_handler);
-	xd->tx_handler = 0;
-	g_free(xd->txbuf);
-	xd->txbuf = NULL;
-	xd->txbuflen = 0;
-
-	purple_xfer_start(xfer, source, NULL, 0);
-
-}
-
-static void yahoo_receivefile_connected(gpointer data, gint source, const gchar *error_message)
-{
-	PurpleXfer *xfer;
-	struct yahoo_xfer_data *xd;
-
-	purple_debug_info("yahoo", "in yahoo_receivefile_connected\n");
-
-	if (!(xfer = data))
-		return;
-	if (!(xd = xfer->data))
-		return;
-	if ((source < 0) || (xd->path == NULL) || (xd->host == NULL)) {
-		purple_xfer_error(PURPLE_XFER_RECEIVE, purple_xfer_get_account(xfer),
-				xfer->who, _("Unable to connect."));
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	xfer->fd = source;
-
-	/* The first time we get here, assemble the tx buffer */
-	if (xd->txbuflen == 0) {
-		xd->txbuf = g_strdup_printf("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n",
-			      xd->path, xd->host);
-		xd->txbuflen = strlen(xd->txbuf);
-		xd->txbuf_written = 0;
-	}
-
-	if (!xd->tx_handler)
-	{
-		xd->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE,
-			yahoo_receivefile_send_cb, xfer);
-		yahoo_receivefile_send_cb(xfer, source, PURPLE_INPUT_WRITE);
-	}
-}
-
-static void yahoo_sendfile_send_cb(gpointer data, gint source, PurpleInputCondition condition)
-{
-	PurpleXfer *xfer;
-	struct yahoo_xfer_data *xd;
-	int written, remaining;
-
-	xfer = data;
-	xd = xfer->data;
-
-	remaining = xd->txbuflen - xd->txbuf_written;
-	written = write(xfer->fd, xd->txbuf + xd->txbuf_written, remaining);
-
-	if (written < 0 && errno == EAGAIN)
-		written = 0;
-	else if (written <= 0) {
-		purple_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno);
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	if (written < remaining) {
-		xd->txbuf_written += written;
-		return;
-	}
-
-	purple_input_remove(xd->tx_handler);
-	xd->tx_handler = 0;
-	g_free(xd->txbuf);
-	xd->txbuf = NULL;
-	xd->txbuflen = 0;
-
-	purple_xfer_start(xfer, source, NULL, 0);
-}
-
-static void yahoo_sendfile_connected(gpointer data, gint source, const gchar *error_message)
-{
-	PurpleXfer *xfer;
-	struct yahoo_xfer_data *xd;
-	struct yahoo_packet *pkt;
-	gchar *size, *filename, *encoded_filename, *header;
-	guchar *pkt_buf;
-	const char *host;
-	int port;
-	size_t content_length, header_len, pkt_buf_len;
-	PurpleConnection *gc;
-	PurpleAccount *account;
-	YahooData *yd;
-
-	purple_debug_info("yahoo", "in yahoo_sendfile_connected\n");
-
-	if (!(xfer = data))
-		return;
-	if (!(xd = xfer->data))
-		return;
-
-	if (source < 0) {
-		purple_xfer_error(PURPLE_XFER_RECEIVE, purple_xfer_get_account(xfer),
-				xfer->who, _("Unable to connect."));
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	xfer->fd = source;
-
-	/* Assemble the tx buffer */
-	gc = xd->gc;
-	account = purple_connection_get_account(gc);
-	yd = gc->proto_data;
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANSFER,
-		YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	size = g_strdup_printf("%" G_GSIZE_FORMAT, purple_xfer_get_size(xfer));
-	filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
-	encoded_filename = yahoo_string_encode(gc, filename, NULL);
-
-	yahoo_packet_hash(pkt, "sssss", 0, purple_connection_get_display_name(gc),
-	  5, xfer->who, 14, "", 27, encoded_filename, 28, size);
-	g_free(size);
-	g_free(encoded_filename);
-	g_free(filename);
-
-	content_length = YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt);
-
-	pkt_buf_len = yahoo_packet_build(pkt, 4, FALSE, yd->jp, &pkt_buf);
-	yahoo_packet_free(pkt);
-
-	host = purple_account_get_string(account, "xfer_host", YAHOO_XFER_HOST);
-	port = purple_account_get_int(account, "xfer_port", YAHOO_XFER_PORT);
-	header = g_strdup_printf(
-		"POST http://%s:%d/notifyft HTTP/1.0\r\n"
-		"Content-length: %" G_GSIZE_FORMAT "\r\n"
-		"Host: %s:%d\r\n"
-		"Cookie: Y=%s; T=%s\r\n"
-		"\r\n",
-		host, port, content_length + 4 + purple_xfer_get_size(xfer),
-		host, port, yd->cookie_y, yd->cookie_t);
-
-	header_len = strlen(header);
-
-	xd->txbuflen = header_len + pkt_buf_len + 4;
-	xd->txbuf = g_malloc(xd->txbuflen);
-
-	memcpy(xd->txbuf, header, header_len);
-	g_free(header);
-	memcpy(xd->txbuf + header_len, pkt_buf, pkt_buf_len);
-	g_free(pkt_buf);
-	memcpy(xd->txbuf + header_len + pkt_buf_len, "29\xc0\x80", 4);
-
-	xd->txbuf_written = 0;
-
-	if (xd->tx_handler == 0)
-	{
-		xd->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE,
-										yahoo_sendfile_send_cb, xfer);
-		yahoo_sendfile_send_cb(xfer, source, PURPLE_INPUT_WRITE);
-	}
-}
-
-static void yahoo_xfer_init(PurpleXfer *xfer)
-{
-	struct yahoo_xfer_data *xfer_data;
-	PurpleConnection *gc;
-	PurpleAccount *account;
-	YahooData *yd;
-
-	xfer_data = xfer->data;
-	gc = xfer_data->gc;
-	yd = gc->proto_data;
-	account = purple_connection_get_account(gc);
-
-	if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
-		if (yd->jp) {
-			if (purple_proxy_connect(gc, account, purple_account_get_string(account, "xferjp_host",  YAHOOJP_XFER_HOST),
-			                       purple_account_get_int(account, "xfer_port", YAHOO_XFER_PORT),
-			                       yahoo_sendfile_connected, xfer) == NULL)
-			{
-				purple_notify_error(gc, NULL, _("File Transfer Failed"),
-				                _("Unable to establish file descriptor."));
-				purple_xfer_cancel_remote(xfer);
-			}
-		} else {
-			if (purple_proxy_connect(gc, account, purple_account_get_string(account, "xfer_host",  YAHOO_XFER_HOST),
-			                       purple_account_get_int(account, "xfer_port", YAHOO_XFER_PORT),
-			                       yahoo_sendfile_connected, xfer) == NULL)
-			{
-				purple_notify_error(gc, NULL, _("File Transfer Failed"),
-				                _("Unable to establish file descriptor."));
-				purple_xfer_cancel_remote(xfer);
-			}
-		}
-	} else {
-		xfer->fd = -1;
-		if (purple_proxy_connect(gc, account, xfer_data->host, xfer_data->port,
-		                              yahoo_receivefile_connected, xfer) == NULL) {
-			purple_notify_error(gc, NULL, _("File Transfer Failed"),
-			             _("Unable to establish file descriptor."));
-			purple_xfer_cancel_remote(xfer);
-		}
-	}
-}
-
-static void yahoo_xfer_init_15(PurpleXfer *xfer)
-{
-	struct yahoo_xfer_data *xfer_data;
-	PurpleConnection *gc;
-	PurpleAccount *account;
-	YahooData *yd;
-	struct yahoo_packet *pkt;
-
-	xfer_data = xfer->data;
-	gc = xfer_data->gc;
-	yd = gc->proto_data;
-	account = purple_connection_get_account(gc);
-
-	if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND)	{
-		gchar *filename;
-		filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
-		pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
-							   YAHOO_STATUS_AVAILABLE,
-							   yd->session_id);
-		yahoo_packet_hash(pkt, "sssiiiisiii",
-			1, purple_normalize(account, purple_account_get_username(account)),
-			5, xfer->who,
-			265, xfer_data->xfer_peer_idstring,
-			222, 1,
-			266, 1,
-			302, 268,
-			300, 268,
-			27,  filename,
-			28,  xfer->size,
-			301, 268,
-			303, 268);
-		g_free(filename);
-	} else {
-		if(xfer_data->firstoflist == TRUE) {
-			pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
-				YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-			yahoo_packet_hash(pkt, "sssi",
-				1, purple_normalize(account, purple_account_get_username(account)),
-				5, xfer->who,
-				265, xfer_data->xfer_peer_idstring,
-				222, 3);
-		} else {
-			pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15,
-				YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-			yahoo_packet_hash(pkt, "sssi",
-				1, purple_normalize(account, purple_account_get_username(account)),
-				5, xfer->who,
-				265, xfer_data->xfer_peer_idstring,
-				271, 1);
-		}
-	}
-	yahoo_packet_send_and_free(pkt, yd);
-}
-
-static void yahoo_xfer_start(PurpleXfer *xfer)
-{
-	/* We don't need to do anything here, do we? */
-}
-
-static guint calculate_length(const gchar *l, size_t len)
-{
-	size_t i;
-
-	for (i = 0; i < len; i++) {
-		if (!g_ascii_isdigit(l[i]))
-			continue;
-		return strtol(l + i, NULL, 10);
-	}
-	return 0;
-}
-
-static gssize yahoo_xfer_read(guchar **buffer, PurpleXfer *xfer)
-{
-	gchar buf[4096];
-	gssize len;
-	gchar *start = NULL;
-	gchar *length;
-	gchar *end;
-	int filelen;
-	struct yahoo_xfer_data *xd = xfer->data;
-
-	if (purple_xfer_get_type(xfer) != PURPLE_XFER_RECEIVE) {
-		return 0;
-	}
-
-	len = read(xfer->fd, buf, sizeof(buf));
-
-	if (len <= 0) {
-		if ((purple_xfer_get_size(xfer) > 0) &&
-		    (purple_xfer_get_bytes_sent(xfer) >= purple_xfer_get_size(xfer))) {
-			purple_xfer_set_completed(xfer, TRUE);
-			return 0;
-		} else
-			return -1;
-	}
-
-	if (!xd->started) {
-		xd->rxqueue = g_realloc(xd->rxqueue, len + xd->rxlen);
-		memcpy(xd->rxqueue + xd->rxlen, buf, len);
-		xd->rxlen += len;
-
-		length = g_strstr_len(xd->rxqueue, len, "Content-length:");
-		/* some proxies re-write this header, changing the capitalization :(
-		 * technically that's allowed since headers are case-insensitive
-		 * [RFC 2616, section 4.2] */
-		if (length == NULL)
-			length = g_strstr_len(xd->rxqueue, len, "Content-Length:");
-		if (length) {
-			end = g_strstr_len(length, length - xd->rxqueue, "\r\n");
-			if (!end)
-				return 0;
-			if ((filelen = calculate_length(length, len - (length - xd->rxqueue))))
-				purple_xfer_set_size(xfer, filelen);
-		}
-		start = g_strstr_len(xd->rxqueue, len, "\r\n\r\n");
-		if (start)
-			start += 4;
-		if (!start || start > (xd->rxqueue + len))
-			return 0;
-		xd->started = TRUE;
-
-		len -= (start - xd->rxqueue);
-
-		*buffer = g_malloc(len);
-		memcpy(*buffer, start, len);
-		g_free(xd->rxqueue);
-		xd->rxqueue = NULL;
-		xd->rxlen = 0;
-	} else {
-		*buffer = g_malloc(len);
-		memcpy(*buffer, buf, len);
-	}
-
-	return len;
-}
-
-static gssize yahoo_xfer_write(const guchar *buffer, size_t size, PurpleXfer *xfer)
-{
-	gssize len;
-	struct yahoo_xfer_data *xd = xfer->data;
-
-	if (!xd)
-		return -1;
-
-	if (purple_xfer_get_type(xfer) != PURPLE_XFER_SEND) {
-		return -1;
-	}
-
-	len = write(xfer->fd, buffer, size);
-
-	if (len == -1) {
-		if (purple_xfer_get_bytes_sent(xfer) >= purple_xfer_get_size(xfer))
-			purple_xfer_set_completed(xfer, TRUE);
-		if ((errno != EAGAIN) && (errno != EINTR))
-			return -1;
-		return 0;
-	}
-
-	return len;
-}
-
-static void yahoo_xfer_cancel_send(PurpleXfer *xfer)
-{
-	struct yahoo_xfer_data *xfer_data;
-
-	xfer_data = xfer->data;
-
-	if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL && xfer_data->version == 15)
-	{
-		PurpleConnection *gc;
-		PurpleAccount *account;
-		YahooData *yd;
-		struct yahoo_packet *pkt;
-
-		gc = xfer_data->gc;
-		yd = gc->proto_data;
-		account = purple_connection_get_account(gc);
-		if(xfer_data->xfer_idstring_for_relay) /* hack to see if file trans acc/info packet has been received */
-		{
-			pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15,
-								   YAHOO_STATUS_DISCONNECTED,
-								   yd->session_id);
-			yahoo_packet_hash(pkt, "sssi",
-				1, purple_normalize(account, purple_account_get_username(account)),
-				5, xfer->who,
-				265, xfer_data->xfer_peer_idstring,
-				66, -1);
-		}
-		else
-		{
-			pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
-								   YAHOO_STATUS_AVAILABLE,
-								   yd->session_id);
-			yahoo_packet_hash(pkt, "sssi",
-				1, purple_normalize(account, purple_account_get_username(account)),
-				5, xfer->who,
-				265, xfer_data->xfer_peer_idstring,
-				222, 2);
-		}
-		yahoo_packet_send_and_free(pkt, yd);
-	}
-
-
-	if (xfer_data)
-		yahoo_xfer_data_free(xfer_data);
-	xfer->data = NULL;
-}
-
-static void yahoo_xfer_cancel_recv(PurpleXfer *xfer)
-{
-	struct yahoo_xfer_data *xfer_data;
-
-	xfer_data = xfer->data;
-
-	if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL && xfer_data->version == 15)
-	{
-
-		PurpleConnection *gc;
-		PurpleAccount *account;
-		YahooData *yd;
-		struct yahoo_packet *pkt;
-
-		gc = xfer_data->gc;
-		yd = gc->proto_data;
-		account = purple_connection_get_account(gc);
-		if(!xfer_data->xfer_idstring_for_relay) /* hack to see if file trans acc/info packet has been received */
-		{
-			pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
-								   YAHOO_STATUS_AVAILABLE,
-								   yd->session_id);
-			yahoo_packet_hash(pkt, "sssi",
-				1, purple_normalize(account, purple_account_get_username(account)),
-				5, xfer->who,
-				265, xfer_data->xfer_peer_idstring,
-				222, 4);
-		}
-		else
-		{
-			pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
-								   YAHOO_STATUS_DISCONNECTED,
-								   yd->session_id);
-			yahoo_packet_hash(pkt, "sssi",
-				1, purple_normalize(account, purple_account_get_username(account)),
-				5, xfer->who,
-				265, xfer_data->xfer_peer_idstring,
-				66, -1);
-		}
-		yahoo_packet_send_and_free(pkt, yd);
-	}
-
-	if (xfer_data)
-		yahoo_xfer_data_free(xfer_data);
-	xfer->data = NULL;
-}
-
-/* Send HTTP OK after receiving file */
-static void yahoo_p2p_ft_server_send_OK(PurpleXfer *xfer)
-{
-	char *tx = NULL;
-	int written;
-
-	tx = g_strdup_printf("HTTP/1.1 200 OK\r\nContent-Length: 0\r\nContent-Type: application/octet-stream\r\nConnection: close\r\n\r\n");
-	written = write(xfer->fd, tx, strlen(tx));
-
-	if (written < 0 && errno == EAGAIN)
-		written = 0;
-	else if (written <= 0)
-		purple_debug_info("yahoo", "p2p filetransfer: Unable to write HTTP OK");
-
-	/* close connection */
-	close(xfer->fd);
-	xfer->fd = -1;
-	g_free(tx);
-}
-
-static void yahoo_xfer_end(PurpleXfer *xfer_old)
-{
-	struct yahoo_xfer_data *xfer_data;
-	PurpleXfer *xfer = NULL;
-	PurpleConnection *gc;
-	YahooData *yd;
-
-	xfer_data = xfer_old->data;
-	if(xfer_data && xfer_data->version == 15
-	   && purple_xfer_get_type(xfer_old) == PURPLE_XFER_RECEIVE
-	   && xfer_data->filename_list) {
-
-		/* Send HTTP OK in case of p2p transfer, when we act as server */
-		if((xfer_data->xfer_url != NULL) && (xfer_old->fd >=0) && (purple_xfer_get_status(xfer_old) == PURPLE_XFER_STATUS_DONE))
-			yahoo_p2p_ft_server_send_OK(xfer_old);
-
-		/* removing top of filename & size list completely */
-		g_free( xfer_data->filename_list->data );
-		g_free( xfer_data->size_list->data );
-
-		xfer_data->filename_list->data = NULL;
-		xfer_data->size_list->data = NULL;
-
-		xfer_data->filename_list = g_slist_delete_link(xfer_data->filename_list, xfer_data->filename_list);
-		xfer_data->size_list = g_slist_delete_link(xfer_data->size_list, xfer_data->size_list);
-
-		/* if there are still more files */
-		if(xfer_data->filename_list)
-		{
-			gchar* filename;
-			long filesize;
-
-			filename = xfer_data->filename_list->data;
-			filesize = atol( xfer_data->size_list->data );
-
-			gc = xfer_data->gc;
-			yd = gc->proto_data;
-
-			/* setting up xfer_data for next file's tranfer */
-			g_free(xfer_data->host);
-			g_free(xfer_data->path);
-			g_free(xfer_data->txbuf);
-			g_free(xfer_data->rxqueue);
-			g_free(xfer_data->xfer_idstring_for_relay);
-			if (xfer_data->tx_handler)
-				purple_input_remove(xfer_data->tx_handler);
-			xfer_data->host = NULL;
-			xfer_data->host = NULL;
-			xfer_data->port = 0;
-			xfer_data->expires = 0;
-			xfer_data->started = FALSE;
-			xfer_data->txbuf = NULL;
-			xfer_data->txbuflen = 0;
-			xfer_data->txbuf_written = 0;
-			xfer_data->tx_handler = 0;
-			xfer_data->rxqueue = NULL;
-			xfer_data->rxlen = 0;
-			xfer_data->xfer_idstring_for_relay = NULL;
-			xfer_data->info_val_249 = 0;
-			xfer_data->status_15 = STARTED;
-			xfer_data->firstoflist = FALSE;
-
-			/* Dereference xfer_data from old xfer */
-			xfer_old->data = NULL;
-
-			/* Build the file transfer handle. */
-			xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, xfer_old->who);
-
-
-			if (xfer) {
-				/* Set the info about the incoming file. */
-				char *utf8_filename = yahoo_string_decode(gc, filename, TRUE);
-				purple_xfer_set_filename(xfer, utf8_filename);
-				g_free(utf8_filename);
-				purple_xfer_set_size(xfer, filesize);
-
-				xfer->data = xfer_data;
-
-				/* Setup our I/O op functions */
-				purple_xfer_set_init_fnc(xfer,        yahoo_xfer_init_15);
-				purple_xfer_set_start_fnc(xfer,       yahoo_xfer_start);
-				purple_xfer_set_end_fnc(xfer,         yahoo_xfer_end);
-				purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send);
-				purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv);
-				purple_xfer_set_read_fnc(xfer,        yahoo_xfer_read);
-				purple_xfer_set_write_fnc(xfer,       yahoo_xfer_write);
-				purple_xfer_set_request_denied_fnc(xfer,yahoo_xfer_cancel_recv);
-
-				/* update map to current xfer */
-				g_hash_table_remove(yd->xfer_peer_idstring_map, xfer_data->xfer_peer_idstring);
-				g_hash_table_insert(yd->xfer_peer_idstring_map, xfer_data->xfer_peer_idstring, xfer);
-
-				/* Now perform the request */
-				purple_xfer_request(xfer);
-			}
-			return;
-		}
-	}
-	if (xfer_data)
-		yahoo_xfer_data_free(xfer_data);
-	xfer_old->data = NULL;
-
-}
-
-void yahoo_process_p2pfilexfer(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	GSList *l = pkt->hash;
-
-	char *me      = NULL;
-	char *from    = NULL;
-	char *service = NULL;
-	char *message = NULL;
-	char *command = NULL;
-	char *imv     = NULL;
-
-	/* Get all the necessary values from this new packet */
-	while(l != NULL)
-	{
-		struct yahoo_pair *pair = l->data;
-
-		switch(pair->key) {
-		case 5:         /* Get who the packet is for */
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				me = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_p2pfilexfer "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 4:         /* Get who the packet is from */
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				from = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_p2pfilexfer "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 49:        /* Get the type of service */
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				service = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_p2pfilexfer "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 14:        /* Get the 'message' of the packet */
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				message = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_p2pfilexfer "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 13:        /* Get the command associated with this packet */
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				command = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_p2pfilexfer "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 63:        /* IMVironment name and version */
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				imv = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_p2pfilexfer "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 64:        /* Not sure, but it does vary with initialization of Doodle */
-			break;
-		}
-
-		l = l->next;
-	}
-
-	/* If this packet is an IMVIRONMENT, handle it accordingly */
-	if(service != NULL && imv != NULL && !strcmp(service, "IMVIRONMENT"))
-	{
-		/* Check for a Doodle packet and handle it accordingly */
-		if(strstr(imv, "doodle;") != NULL)
-			yahoo_doodle_process(gc, me, from, command, message, imv);
-
-		/* If an IMVIRONMENT packet comes without a specific imviroment name */
-		if(!strcmp(imv, ";0"))
-		{
-			/* It is unfortunately time to close all IMVironments with the remote client */
-			yahoo_doodle_command_got_shutdown(gc, from);
-		}
-	}
-}
-
-void yahoo_process_filetransfer(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	char *from = NULL;
-	char *msg = NULL;
-	char *url = NULL;
-	char *imv = NULL;
-	PurpleXfer *xfer;
-	YahooData *yd;
-	struct yahoo_xfer_data *xfer_data;
-	char *service = NULL;
-	char *filename = NULL;
-	unsigned long filesize = 0L;
-	GSList *l;
-
-	yd = gc->proto_data;
-
-	for (l = pkt->hash; l; l = l->next) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 4:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				from = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_filetransfer "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 5: /* to */
-			break;
-		case 14:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				msg = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_filetransfer "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 20:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				url = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_filetransfer "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 38: /* expires */
-			break;
-		case 27:
-			filename = pair->value;
-			break;
-		case 28:
-			filesize = atol(pair->value);
-			break;
-		case 49:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				service = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_filetransfer "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 63:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				imv = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_filetransfer "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		}
-	}
-
-	/*
-	 * The remote user has changed their IMVironment.  We
-	 * record it for later use.
-	 */
-	if (from && imv && service && (strcmp("IMVIRONMENT", service) == 0)) {
-		g_hash_table_replace(yd->imvironments, g_strdup(from), g_strdup(imv));
-		return;
-	}
-
-	if (pkt->service == YAHOO_SERVICE_P2PFILEXFER) {
-		if (service && (strcmp("FILEXFER", service) != 0)) {
-			purple_debug_misc("yahoo", "unhandled service 0x%02x\n", pkt->service);
-			return;
-		}
-	}
-
-	if (msg) {
-		char *tmp;
-		tmp = strchr(msg, '\006');
-		if (tmp)
-			*tmp = '\0';
-	}
-
-	if (!url || !from)
-		return;
-
-	/* Setup the Yahoo-specific file transfer data */
-	xfer_data = g_new0(struct yahoo_xfer_data, 1);
-	xfer_data->gc = gc;
-	if (!purple_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL)) {
-		g_free(xfer_data);
-		return;
-	}
-
-	purple_debug_misc("yahoo_filexfer", "Host is %s, port is %d, path is %s, and the full url was %s.\n",
-	                xfer_data->host, xfer_data->port, xfer_data->path, url);
-
-	/* Build the file transfer handle. */
-	xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, from);
-	if (xfer == NULL) {
-		g_free(xfer_data);
-		g_return_if_reached();
-	}
-
-	xfer->data = xfer_data;
-
-	/* Set the info about the incoming file. */
-	if (filename) {
-		char *utf8_filename = yahoo_string_decode(gc, filename, TRUE);
-		purple_xfer_set_filename(xfer, utf8_filename);
-		g_free(utf8_filename);
-	} else {
-		gchar *start, *end;
-		start = g_strrstr(xfer_data->path, "/");
-		if (start)
-			start++;
-		end = g_strrstr(xfer_data->path, "?");
-		if (start && *start && end) {
-			char *utf8_filename;
-			filename = g_strndup(start, end - start);
-			utf8_filename = yahoo_string_decode(gc, filename, TRUE);
-			g_free(filename);
-			purple_xfer_set_filename(xfer, utf8_filename);
-			g_free(utf8_filename);
-			filename = NULL;
-		}
-	}
-
-	purple_xfer_set_size(xfer, filesize);
-
-	/* Setup our I/O op functions */
-	purple_xfer_set_init_fnc(xfer,        yahoo_xfer_init);
-	purple_xfer_set_start_fnc(xfer,       yahoo_xfer_start);
-	purple_xfer_set_end_fnc(xfer,         yahoo_xfer_end);
-	purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send);
-	purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv);
-	purple_xfer_set_read_fnc(xfer,        yahoo_xfer_read);
-	purple_xfer_set_write_fnc(xfer,       yahoo_xfer_write);
-
-	/* Now perform the request */
-	purple_xfer_request(xfer);
-}
-
-PurpleXfer *yahoo_new_xfer(PurpleConnection *gc, const char *who)
-{
-	PurpleXfer *xfer;
-	struct yahoo_xfer_data *xfer_data;
-
-	g_return_val_if_fail(who != NULL, NULL);
-
-	xfer_data = g_new0(struct yahoo_xfer_data, 1);
-	xfer_data->gc = gc;
-
-	/* Build the file transfer handle. */
-	xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who);
-	if (xfer == NULL)
-	{
-		g_free(xfer_data);
-		g_return_val_if_reached(NULL);
-	}
-
-	xfer->data = xfer_data;
-
-	/* Setup our I/O op functions */
-	purple_xfer_set_init_fnc(xfer,        yahoo_xfer_init);
-	purple_xfer_set_start_fnc(xfer,       yahoo_xfer_start);
-	purple_xfer_set_end_fnc(xfer,         yahoo_xfer_end);
-	purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send);
-	purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv);
-	purple_xfer_set_read_fnc(xfer,        yahoo_xfer_read);
-	purple_xfer_set_write_fnc(xfer,       yahoo_xfer_write);
-
-	return xfer;
-}
-
-static gchar* yahoo_xfer_new_xfer_id(void)
-{
-	gchar *ans;
-	int i,j;
-	ans = g_strnfill(24, ' ');
-	ans[23] = '$';
-	ans[22] = '$';
-	for(i = 0; i < 22; i++)
-	{
-		j = g_random_int_range (0,61);
-		if(j < 26)
-			ans[i] = j + 'a';
-		else if(j < 52)
-			ans[i] = j - 26 + 'A';
-		else
-			ans[i] = j - 52 + '0';
-	}
-	return ans;
-}
-
-static void yahoo_xfer_dns_connected_15(GSList *hosts, gpointer data, const char *error_message)
-{
-	PurpleXfer *xfer;
-	struct yahoo_xfer_data *xd;
-	struct sockaddr_in *addr;
-	struct yahoo_packet *pkt;
-	unsigned long actaddr;
-	unsigned char a,b,c,d;
-	PurpleConnection *gc;
-	PurpleAccount *account;
-	YahooData *yd;
-	gchar *url;
-	gchar *filename;
-
-	if (!(xfer = data))
-		return;
-	if (!(xd = xfer->data))
-		return;
-	gc = xd->gc;
-	account = purple_connection_get_account(gc);
-	yd = gc->proto_data;
-
-	if(!hosts)
-	{
-		purple_debug_error("yahoo", "Unable to find an IP address for relay.msg.yahoo.com\n");
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	/* Discard the length... */
-	hosts = g_slist_remove(hosts, hosts->data);
-	if(!hosts)
-	{
-		purple_debug_error("yahoo", "Unable to find an IP address for relay.msg.yahoo.com\n");
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	/* TODO:actually, u must try with addr no.1 , if its not working addr no.2 ..... */
-	addr = hosts->data;
-	actaddr = addr->sin_addr.s_addr;
-	d = actaddr & 0xff;
-	actaddr >>= 8;
-	c = actaddr & 0xff;
-	actaddr >>= 8;
-	b = actaddr & 0xff;
-	actaddr >>= 8;
-	a = actaddr & 0xff;
-	if(yd->jp)
-		xd->port = YAHOOJP_XFER_RELAY_PORT;
-	else
-		xd->port = YAHOO_XFER_RELAY_PORT;
-
-	url = g_strdup_printf("%u.%u.%u.%u", d, c, b, a);
-
-	/* Free the address... */
-	g_free(hosts->data);
-	hosts = g_slist_remove(hosts, hosts->data);
-	addr = NULL;
-	while (hosts != NULL)
-	{
-		/* Discard the length... */
-		hosts = g_slist_remove(hosts, hosts->data);
-		/* Free the address... */
-		g_free(hosts->data);
-		hosts = g_slist_remove(hosts, hosts->data);
-	}
-
-	if (!purple_url_parse(url, &(xd->host), &(xd->port), &(xd->path), NULL, NULL)) {
-		purple_xfer_cancel_remote(xfer);
-		g_free(url);
-		return;
-	}
-	g_free(url);
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
-
-	yahoo_packet_hash(pkt, "ssssis",
-		1, purple_normalize(account, purple_account_get_username(account)),
-		5, xfer->who,
-		265, xd->xfer_peer_idstring,
-		27,  filename,
-		249, 3,
-		250, xd->host);
-
-	g_free(filename);
-	yahoo_packet_send_and_free(pkt, yd);
-}
-
-gboolean yahoo_can_receive_file(PurpleConnection *gc, const char *who)
-{
-	if (!who || yahoo_get_federation_from_name(who) != YAHOO_FEDERATION_NONE)
-		return FALSE;
-	return TRUE;
-}
-
-void yahoo_send_file(PurpleConnection *gc, const char *who, const char *file)
-{
-	struct yahoo_xfer_data *xfer_data;
-	YahooData *yd = gc->proto_data;
-	PurpleXfer *xfer = yahoo_new_xfer(gc, who);
-
-	g_return_if_fail(xfer != NULL);
-
-	/* if we don't have a p2p connection, try establishing it now */
-	if( !g_hash_table_lookup(yd->peers, who) )
-		yahoo_send_p2p_pkt(gc, who, 0);
-
-	xfer_data = xfer->data;
-	xfer_data->status_15 = STARTED;
-	purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15);
-	xfer_data->version = 15;
-	xfer_data->xfer_peer_idstring = yahoo_xfer_new_xfer_id();
-	g_hash_table_insert(yd->xfer_peer_idstring_map, xfer_data->xfer_peer_idstring, xfer);
-
-	/* Now perform the request */
-	if (file)
-		purple_xfer_request_accepted(xfer, file);
-	else
-		purple_xfer_request(xfer);
-}
-
-static void yahoo_p2p_ft_server_listen_cb(int listenfd, gpointer data);	/* using this in yahoo_xfer_send_cb_15 */
-static void yahoo_xfer_connected_15(gpointer data, gint source, const gchar *error_message);/* using this in recv_cb */
-
-static void yahoo_xfer_recv_cb_15(gpointer data, gint source, PurpleInputCondition condition)
-{
-	PurpleXfer *xfer;
-	struct yahoo_xfer_data *xd;
-	int did;
-	gchar* buf;
-	gchar* t;
-	PurpleAccount *account;
-	PurpleConnection *gc;
-
-	xfer = data;
-	xd = xfer->data;
-	account = purple_connection_get_account(xd->gc);
-	gc = xd->gc;
-
-	buf=g_strnfill(1000, 0);
-	while((did = read(source, buf, 998)) > 0)
-	{
-		xd->txbuflen += did;
-		buf[did] = '\0';
-		t = xd->txbuf;
-		xd->txbuf = g_strconcat(t,buf,NULL);
-		g_free(t);
-	}
-	g_free(buf);
-
-	if (did < 0 && errno == EAGAIN)
-		return;
-	else if (did < 0) {
-		purple_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno);
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	purple_input_remove(xd->tx_handler);
-	xd->tx_handler = 0;
-	xd->txbuflen = 0;
-
-	if(xd->status_15 == HEAD_REQUESTED) {
-		xd->status_15 = HEAD_REPLY_RECEIVED;
-		close(source);/* Is this required? */
-		g_free(xd->txbuf);
-		xd->txbuf = NULL;
-		if (purple_proxy_connect(gc, account, xd->host, xd->port, yahoo_xfer_connected_15, xfer) == NULL)
-		{
-			purple_notify_error(gc, NULL, _("File Transfer Failed"),
-				_("Unable to establish file descriptor."));
-			purple_xfer_cancel_remote(xfer);
-		}
-	} else {
-		purple_debug_error("yahoo","Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n",
-						   purple_xfer_get_type(xfer),
-						   xd->status_15);
-		return;
-	}
-}
-
-static void yahoo_xfer_send_cb_15(gpointer data, gint source, PurpleInputCondition condition)
-{
-	PurpleXfer *xfer;
-	struct yahoo_xfer_data *xd;
-	int remaining, written;
-
-	xfer = data;
-	xd = xfer->data;
-	remaining = xd->txbuflen - xd->txbuf_written;
-	written = write(source, xd->txbuf + xd->txbuf_written, remaining);
-
-	if (written < 0 && errno == EAGAIN)
-		written = 0;
-	else if (written <= 0) {
-		purple_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno);
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	if (written < remaining) {
-		xd->txbuf_written += written;
-		return;
-	}
-
-	purple_input_remove(xd->tx_handler);
-	xd->tx_handler = 0;
-	g_free(xd->txbuf);
-	xd->txbuf = NULL;
-	xd->txbuflen = 0;
-	xd->txbuf_written = 0;
-
-	if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == STARTED)
-	{
-		xd->status_15 = HEAD_REQUESTED;
-		xd->tx_handler = purple_input_add(source, PURPLE_INPUT_READ, yahoo_xfer_recv_cb_15, xfer);
-		yahoo_xfer_recv_cb_15(xfer, source, PURPLE_INPUT_READ);
-	}
-	else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == HEAD_REPLY_RECEIVED)
-	{
-		xd->status_15 = TRANSFER_PHASE;
-		xfer->fd = source;
-		purple_xfer_start(xfer, source, NULL, 0);
-	}
-	else if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && (xd->status_15 == ACCEPTED || xd->status_15 == P2P_GET_REQUESTED) )
-	{
-		xd->status_15 = TRANSFER_PHASE;
-		xfer->fd = source;
-		/* Remove Read event */
-		purple_input_remove(xd->input_event);
-		xd->input_event = 0;
-		purple_xfer_start(xfer, source, NULL, 0);
-	}
-	else if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && xd->status_15 == P2P_HEAD_REQUESTED)
-	{
-		xd->status_15 = P2P_HEAD_REPLIED;
-		/* Remove Read event and close descriptor */
-		purple_input_remove(xd->input_event);
-		xd->input_event = 0;
-		close(source);
-		xfer->fd = -1;
-		/* start local server, listen for connections */
-		purple_network_listen(xd->yahoo_local_p2p_ft_server_port, SOCK_STREAM, yahoo_p2p_ft_server_listen_cb, xfer);
-	}
-	else
-	{
-		purple_debug_error("yahoo", "Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n", purple_xfer_get_type(xfer), xd->status_15);
-		return;
-	}
-}
-
-static void yahoo_xfer_connected_15(gpointer data, gint source, const gchar *error_message)
-{
-	PurpleXfer *xfer;
-	struct yahoo_xfer_data *xd;
-	PurpleAccount *account;
-	PurpleConnection *gc;
-
-	if (!(xfer = data))
-		return;
-	if (!(xd = xfer->data))
-		return;
-	gc = xd->gc;
-	account = purple_connection_get_account(gc);
-	if ((source < 0) || (xd->path == NULL) || (xd->host == NULL)) {
-		purple_xfer_error(PURPLE_XFER_RECEIVE, purple_xfer_get_account(xfer),
-			xfer->who, _("Unable to connect."));
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-	/* The first time we get here, assemble the tx buffer */
-	if (xd->txbuflen == 0)
-	{
-		gchar* cookies;
-		YahooData *yd = gc->proto_data;
-
-		/* cookies = yahoo_get_cookies(gc);
-		 * This doesn't seem to be working. The function is returning NULL, which yahoo servers don't like
-		 * For now let us not use this function */
-
-		cookies = g_strdup_printf("Y=%s; T=%s", yd->cookie_y, yd->cookie_t);
-
-		if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && xd->status_15 == ACCEPTED)
-		{
-			if(xd->info_val_249 == 2)
-				{
-				/* sending file via p2p, we are connected as client */
-				xd->txbuf = g_strdup_printf("POST /%s HTTP/1.1\r\n"
-						"User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
-						"Host: %s\r\n"
-						"Content-Length: %ld\r\n"
-						"Cache-Control: no-cache\r\n\r\n",
-										xd->path,
-										xd->host,
-										(long int)xfer->size);	/* to do, add Referer */
-				}
-			else
-				{
-				/* sending file via relaying */
-				xd->txbuf = g_strdup_printf("POST /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n"
-						"Cookie:%s\r\n"
-						"User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
-						"Host: %s\r\n"
-						"Content-Length: %ld\r\n"
-						"Cache-Control: no-cache\r\n\r\n",
-										purple_url_encode(xd->xfer_idstring_for_relay),
-										purple_normalize(account, purple_account_get_username(account)),
-										xfer->who,
-										cookies,
-										xd->host,
-										(long int)xfer->size);
-				}
-		}
-		else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == STARTED)
-		{
-			if(xd->info_val_249 == 1)
-				{
-				/* receiving file via p2p, connected as client */
-				xd->txbuf = g_strdup_printf("HEAD /%s HTTP/1.1\r\n"
-						"Accept: */*\r\n"
-						"User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
-						"Host: %s\r\n"
-						"Content-Length: 0\r\n"
-						"Cache-Control: no-cache\r\n\r\n",
-						xd->path,xd->host);
-			}
-			else
-				{
-				/* receiving file via relaying */
-				xd->txbuf = g_strdup_printf("HEAD /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n"
-						"Accept: */*\r\n"
-						"Cookie: %s\r\n"
-						"User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
-						"Host: %s\r\n"
-						"Content-Length: 0\r\n"
-						"Cache-Control: no-cache\r\n\r\n",
-										purple_url_encode(xd->xfer_idstring_for_relay),
-										purple_normalize(account, purple_account_get_username(account)),
-										xfer->who,
-										cookies,
-										xd->host);
-			}
-		}
-		else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == HEAD_REPLY_RECEIVED)
-		{
-			if(xd->info_val_249 == 1)
-				{
-				/* receiving file via p2p, connected as client */
-				xd->txbuf = g_strdup_printf("GET /%s HTTP/1.1\r\n"
-						"User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
-						"Host: %s\r\n"
-						"Connection: Keep-Alive\r\n\r\n",
-						xd->path, xd->host);
-			}
-			else
-				{
-				/* receiving file via relaying */
-				xd->txbuf = g_strdup_printf("GET /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n"
-						"Cookie: %s\r\n"
-						"User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
-						"Host: %s\r\n"
-						"Connection: Keep-Alive\r\n\r\n",
-										purple_url_encode(xd->xfer_idstring_for_relay),
-										purple_normalize(account, purple_account_get_username(account)),
-										xfer->who,
-										cookies,
-										xd->host);
-			}
-		}
-		else
-		{
-			purple_debug_error("yahoo", "Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n", purple_xfer_get_type(xfer), xd->status_15);
-			g_free(cookies);
-			return;
-		}
-		xd->txbuflen = strlen(xd->txbuf);
-		xd->txbuf_written = 0;
-		g_free(cookies);
-	}
-
-	if (!xd->tx_handler)
-	{
-		xd->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE,
-			yahoo_xfer_send_cb_15, xfer);
-		yahoo_xfer_send_cb_15(xfer, source, PURPLE_INPUT_WRITE);
-	}
-}
-
-static void yahoo_p2p_ft_POST_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
-	PurpleXfer *xfer;
-	struct yahoo_xfer_data *xd;
-
-	xfer = data;
-	if (!(xd = xfer->data))	{
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	purple_input_remove(xd->input_event);
-	xd->status_15 = TRANSFER_PHASE;
-	xfer->fd = source;
-	purple_xfer_start(xfer, source, NULL, 0);
-}
-
-static void yahoo_p2p_ft_HEAD_GET_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
-	PurpleXfer *xfer;
-	struct yahoo_xfer_data *xd;
-	guchar buf[1024];
-	int len;
-	char *url_head;
-	char *url_get;
-	time_t unix_time;
-	char *time_str;
-
-	xfer = data;
-	if (!(xd = xfer->data))	{
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	len = read(source, buf, sizeof(buf));
-	if ((len < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
-		return ; /* No Worries*/
-	else if (len <= 0)	{
-		purple_debug_warning("yahoo","p2p-ft: Error in connection, or host disconnected\n");
-		purple_input_remove(xd->input_event);
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	url_head = g_strdup_printf("HEAD %s", xd->xfer_url);
-	url_get = g_strdup_printf("GET %s", xd->xfer_url);
-
-	if( strncmp(url_head, (char *)buf, strlen(url_head)) == 0 )
-		xd->status_15 = P2P_HEAD_REQUESTED;
-	else if( strncmp(url_get, (char *)buf, strlen(url_get)) == 0 )
-		xd->status_15 = P2P_GET_REQUESTED;
-	else	{
-		purple_debug_warning("yahoo","p2p-ft: Wrong HEAD/GET request from peer, disconnecting host\n");
-		purple_input_remove(xd->input_event);
-		purple_xfer_cancel_remote(xfer);
-		g_free(url_head);
-		return;
-	}
-
-	unix_time = time(NULL);
-	time_str = ctime(&unix_time);
-	time_str[strlen(time_str) - 1] = '\0';
-
-	if (xd->txbuflen == 0)	{
-		xd->txbuf = g_strdup_printf("HTTP/1.0 200 OK\r\n"
-		                            "Date: %s GMT\r\n"
-		                            "Server: Y!/1.0\r\n"
-		                            "MIME-version: 1.0\r\n"
-		                            "Last-modified: %s GMT\r\n"
-		                            "Content-length: %" G_GSIZE_FORMAT "\r\n\r\n",
-		                            time_str, time_str, xfer->size);
-		xd->txbuflen = strlen(xd->txbuf);
-		xd->txbuf_written = 0;
-	}
-
-	if (!xd->tx_handler)	{
-		xd->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE, yahoo_xfer_send_cb_15, xfer);
-		yahoo_xfer_send_cb_15(xfer, source, PURPLE_INPUT_WRITE);
-	}
-
-	g_free(url_head);
-	g_free(url_get);
-}
-
-static void yahoo_p2p_ft_server_send_connected_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
-	int acceptfd;
-	PurpleXfer *xfer;
-	struct yahoo_xfer_data *xd;
-
-	xfer = data;
-	if (!(xd = xfer->data))	{
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	acceptfd = accept(source, NULL, 0);
-	if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
-		return;
-	else if(acceptfd == -1) {
-		purple_debug_warning("yahoo","yahoo_p2p_server_send_connected_cb: accept: %s\n", g_strerror(errno));
-		purple_xfer_cancel_remote(xfer);
-		/* remove watcher and close p2p ft server */
-		purple_input_remove(xd->yahoo_p2p_ft_server_watcher);
-		close(xd->yahoo_local_p2p_ft_server_fd);
-		return;
-	}
-
-	/* remove watcher and close p2p ft server */
-	purple_input_remove(xd->yahoo_p2p_ft_server_watcher);
-	close(xd->yahoo_local_p2p_ft_server_fd);
-
-	/* Add an Input Read event to the file descriptor */
-	xfer->fd = acceptfd;
-	if(xfer->type == PURPLE_XFER_RECEIVE)
-		xd->input_event = purple_input_add(acceptfd, PURPLE_INPUT_READ, yahoo_p2p_ft_POST_cb, data);
-	else
-		xd->input_event = purple_input_add(acceptfd, PURPLE_INPUT_READ, yahoo_p2p_ft_HEAD_GET_cb, data);
-}
-
-static void yahoo_p2p_ft_server_listen_cb(int listenfd, gpointer data)
-{
-	PurpleXfer *xfer;
-	struct yahoo_xfer_data *xd;
-	struct yahoo_packet *pkt;
-	PurpleAccount *account;
-	YahooData *yd;
-	gchar *filename;
-	const char *local_ip;
-	gchar *url_to_send = NULL;
-	char *filename_without_spaces = NULL;
-
-	xfer = data;
-	if (!(xd = xfer->data) || (listenfd == -1))	{
-		purple_debug_warning("yahoo","p2p: error starting server for p2p file transfer\n");
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	if( (xfer->type == PURPLE_XFER_RECEIVE) || (xd->status_15 != P2P_HEAD_REPLIED) )	{
-		yd = xd->gc->proto_data;
-		account = purple_connection_get_account(xd->gc);
-		local_ip = purple_network_get_my_ip(listenfd);
-		xd->yahoo_local_p2p_ft_server_port = purple_network_get_port_from_fd(listenfd);
-
-		filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
-		filename_without_spaces = g_strdup(filename);
-		purple_util_chrreplace(filename_without_spaces, ' ', '+');
-		xd->xfer_url = g_strdup_printf("/Messenger.%s.%d000%s?AppID=Messenger&UserID=%s&K=lc9lu2u89gz1llmplwksajkjx", xfer->who, (int)time(NULL), filename_without_spaces, xfer->who);
-		url_to_send = g_strdup_printf("http://%s:%d%s", local_ip, xd->yahoo_local_p2p_ft_server_port, xd->xfer_url);
-
-		if(xfer->type == PURPLE_XFER_RECEIVE)	{
-			xd->info_val_249 = 2;	/* 249=2: we are p2p server, and receiving file */
-			pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15,
-				YAHOO_STATUS_AVAILABLE, yd->session_id);
-			yahoo_packet_hash(pkt, "ssssis",
-				1, purple_normalize(account, purple_account_get_username(account)),
-				5, xfer->who,
-				265, xd->xfer_peer_idstring,
-				27, xfer->filename,
-				249, 2,
-				250, url_to_send);
-		}
-		else	{
-			xd->info_val_249 = 1;	/* 249=1: we are p2p server, and sending file */
-			pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
-			yahoo_packet_hash(pkt, "ssssis",
-				1, purple_normalize(account, purple_account_get_username(account)),
-				5, xfer->who,
-				265, xd->xfer_peer_idstring,
-				27,  filename,
-				249, 1,
-				250, url_to_send);
-		}
-
-		yahoo_packet_send_and_free(pkt, yd);
-
-		g_free(filename);
-		g_free(url_to_send);
-		g_free(filename_without_spaces);
-	}
-
-	/* Add an Input Read event to the file descriptor */
-	xd->yahoo_local_p2p_ft_server_fd = listenfd;
-	xd->yahoo_p2p_ft_server_watcher = purple_input_add(listenfd, PURPLE_INPUT_READ, yahoo_p2p_ft_server_send_connected_cb, data);
-}
-
-/* send (p2p) file transfer information */
-static void yahoo_p2p_client_send_ft_info(PurpleConnection *gc, PurpleXfer *xfer)
-{
-	struct yahoo_xfer_data *xd;
-	struct yahoo_packet *pkt;
-	PurpleAccount *account;
-	YahooData *yd;
-	gchar *filename;
-	struct yahoo_p2p_data *p2p_data;
-
-	if (!(xd = xfer->data))
-		return;
-
-	account = purple_connection_get_account(gc);
-	yd = gc->proto_data;
-
-	p2p_data = g_hash_table_lookup(yd->peers, xfer->who);
-	if( p2p_data->connection_type == YAHOO_P2P_WE_ARE_SERVER )
-		if(purple_network_listen_range(0, 0, SOCK_STREAM, yahoo_p2p_ft_server_listen_cb, xfer))
-			return;
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
-
-	yahoo_packet_hash(pkt, "ssssi",
-		1, purple_normalize(account, purple_account_get_username(account)),
-		5, xfer->who,
-		265, xd->xfer_peer_idstring,
-		27,  filename,
-		249, 2);	/* 249=2: we are p2p client */
-	xd->info_val_249 = 2;
-	yahoo_packet_send_and_free(pkt, yd);
-
-	g_free(filename);
-}
-
-void yahoo_process_filetrans_15(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	char *from = NULL;
-	char *imv = NULL;
-	long val_222 = 0L;
-	PurpleXfer *xfer;
-	YahooData *yd;
-	struct yahoo_xfer_data *xfer_data;
-	char *service = NULL;
-	char *filename = NULL;
-	char *xfer_peer_idstring = NULL;
-	char *utf8_filename;
-	unsigned long filesize = 0L;
-	GSList *l;
-	GSList *filename_list = NULL;
-	GSList *size_list = NULL;
-	int nooffiles = 0;
-
-	yd = gc->proto_data;
-
-	for (l = pkt->hash; l; l = l->next) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 4:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				from = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_filetrans_15 "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 5: /* to */
-			break;
-		case 265:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				xfer_peer_idstring = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_filetrans_15 "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 27:
-			filename_list = g_slist_prepend(filename_list, g_strdup(pair->value));
-			nooffiles++;
-			break;
-		case 28:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				size_list = g_slist_prepend(size_list, g_strdup(pair->value));
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_filetrans_15 "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 222:
-			val_222 = atol(pair->value);
-			/* 1=send, 2=cancel, 3=accept, 4=reject */
-			break;
-
-		/* check for p2p and imviron .... not sure it comes by this service packet. Since it was bundled with filexfer in old ymsg version, still keeping it. */
-		case 49:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				service = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_filetrans_15 "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 63:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				imv = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_filetrans_15 "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		/* end check */
-
-		}
-	}
-	if(!xfer_peer_idstring)
-		return;
-
-	if(val_222 == 2 || val_222 == 4)
-	{
-		xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map,
-								   xfer_peer_idstring);
-		if(!xfer) return;
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-	if(val_222 == 3)
-	{
-		PurpleAccount *account;
-		xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map,
-								   xfer_peer_idstring);
-		if(!xfer)
-			return;
-		/*
-		*	In the file trans info packet that we must reply with, we are
-		*	supposed to mention the ip address...
-		*	purple connect does not give me a way of finding the ip address...
-		*	so, purple dnsquery is used... but retries, trying with next ip
-		*	address etc. is not implemented..TODO
-		*/
-
-		/* To send through p2p */
-		if( g_hash_table_lookup(yd->peers, from) )	{
-			/* send p2p file transfer information */
-			yahoo_p2p_client_send_ft_info(gc, xfer);
-			return;
-		}
-
-		account = purple_connection_get_account(gc);
-		if (yd->jp)
-		{
-			purple_dnsquery_a_account(account, YAHOOJP_XFER_RELAY_HOST,
-							YAHOOJP_XFER_RELAY_PORT,
-							yahoo_xfer_dns_connected_15, xfer);
-		}
-		else
-		{
-			purple_dnsquery_a_account(account, YAHOO_XFER_RELAY_HOST,
-							YAHOO_XFER_RELAY_PORT,
-							yahoo_xfer_dns_connected_15, xfer);
-		}
-		return;
-	}
-
-	/* processing for p2p and imviron .... not sure it comes by this service packet. Since it was bundled with filexfer in old ymsg version, still keeping it. */
-	/*
-	* The remote user has changed their IMVironment.  We
-	* record it for later use.
-	*/
-	if (from && imv && service && (strcmp("IMVIRONMENT", service) == 0)) {
-		g_hash_table_replace(yd->imvironments, g_strdup(from), g_strdup(imv));
-		return;
-	}
-
-	if (pkt->service == YAHOO_SERVICE_P2PFILEXFER) {
-		if (service && (strcmp("FILEXFER", service) != 0)) {
-			purple_debug_misc("yahoo", "unhandled service 0x%02x\n", pkt->service);
-			return;
-		}
-	}
-	/* end processing */
-
-	if(!filename_list)
-		return;
-	/* have to change list into order in which client at other end sends */
-	filename_list = g_slist_reverse(filename_list);
-	size_list = g_slist_reverse(size_list);
-	filename = filename_list->data;
-	filesize = atol(size_list->data);
-
-	if(!from) return;
-	xfer_data = g_new0(struct yahoo_xfer_data, 1);
-	xfer_data->version = 15;
-	xfer_data->firstoflist = TRUE;
-	xfer_data->gc = gc;
-	xfer_data->xfer_peer_idstring = g_strdup(xfer_peer_idstring);
-	xfer_data->filename_list = filename_list;
-	xfer_data->size_list = size_list;
-
-	/* Build the file transfer handle. */
-	xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, from);
-	if (xfer == NULL)
-	{
-		g_free(xfer_data);
-		g_return_if_reached();
-	}
-
-	xfer->message = NULL;
-
-	/* Set the info about the incoming file. */
-	utf8_filename = yahoo_string_decode(gc, filename, TRUE);
-	purple_xfer_set_filename(xfer, utf8_filename);
-	g_free(utf8_filename);
-	purple_xfer_set_size(xfer, filesize);
-
-	xfer->data = xfer_data;
-
-	/* Setup our I/O op functions */
-	purple_xfer_set_init_fnc(xfer,        yahoo_xfer_init_15);
-	purple_xfer_set_start_fnc(xfer,       yahoo_xfer_start);
-	purple_xfer_set_end_fnc(xfer,         yahoo_xfer_end);
-	purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send);
-	purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv);
-	purple_xfer_set_read_fnc(xfer,        yahoo_xfer_read);
-	purple_xfer_set_write_fnc(xfer,       yahoo_xfer_write);
-	purple_xfer_set_request_denied_fnc(xfer,yahoo_xfer_cancel_recv);
-
-	g_hash_table_insert(yd->xfer_peer_idstring_map,
-						xfer_data->xfer_peer_idstring,
-						xfer);
-
-	if(nooffiles > 1) {
-		gchar* message;
-		message = g_strdup_printf(_("%s is trying to send you a group of %d files.\n"), xfer->who, nooffiles);
-		purple_xfer_conversation_write(xfer, message, FALSE);
-		g_free(message);
-	}
-	/* Now perform the request */
-	purple_xfer_request(xfer);
-}
-
-void yahoo_process_filetrans_info_15(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	char *url = NULL;
-	long val_249 = 0;
-	long val_66 = 0;
-	PurpleXfer *xfer;
-	YahooData *yd;
-	struct yahoo_xfer_data *xfer_data;
-	char *xfer_peer_idstring = NULL;
-	char *xfer_idstring_for_relay = NULL;
-	GSList *l;
-	struct yahoo_packet *pkt_to_send;
-	struct yahoo_p2p_data *p2p_data;
-
-	yd = gc->proto_data;
-
-	for (l = pkt->hash; l; l = l->next) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 4: /* from */
-			break;
-		case 5: /* to */
-			break;
-		case 265:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				xfer_peer_idstring = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_filetrans_info_15 "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 27: /* filename */
-			break;
-		case 66:
-			val_66 = strtol(pair->value, NULL, 10);
-			break;
-		case 249:
-			val_249 = strtol(pair->value, NULL, 10);
-			/* 249 has value 1 or 2 when doing p2p transfer and value 3 when relaying through yahoo server */
-			break;
-		case 250:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				url = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_filetrans_info_15 "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 251:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				xfer_idstring_for_relay = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_filetrans_info_15 "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		}
-	}
-
-	if(!xfer_peer_idstring)
-		return;
-
-	xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xfer_peer_idstring);
-
-	if(!xfer) return;
-
-	if(val_66==-1)
-	{
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	xfer_data = xfer->data;
-
-	xfer_data->info_val_249 = val_249;
-	xfer_data->xfer_idstring_for_relay = g_strdup(xfer_idstring_for_relay);
-	if(val_249 == 1 || val_249 == 3) {
-		PurpleAccount *account;
-		if (!purple_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL)) {
-			purple_xfer_cancel_remote(xfer);
-			return;
-		}
-
-		account = purple_connection_get_account(xfer_data->gc);
-
-		pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15,
-			YAHOO_STATUS_AVAILABLE, yd->session_id);
-		yahoo_packet_hash(pkt_to_send, "ssssis",
-			1, purple_normalize(account, purple_account_get_username(account)),
-			5, xfer->who,
-			265, xfer_data->xfer_peer_idstring,
-			27, xfer->filename,
-			249, xfer_data->info_val_249,
-			251, xfer_data->xfer_idstring_for_relay);
-
-		yahoo_packet_send_and_free(pkt_to_send, yd);
-
-		if (purple_proxy_connect(gc, account, xfer_data->host, xfer_data->port,
-			yahoo_xfer_connected_15, xfer) == NULL) {
-			purple_notify_error(gc, NULL, _("File Transfer Failed"),
-				_("Unable to establish file descriptor."));
-			purple_xfer_cancel_remote(xfer);
-		}
-	}
-	else if(val_249 == 2)	{
-		p2p_data = g_hash_table_lookup(yd->peers, xfer->who);
-		if( !( p2p_data && (p2p_data->connection_type == YAHOO_P2P_WE_ARE_SERVER) ) )	{
-			purple_xfer_cancel_remote(xfer);
-			return;
-		}
-		if(!purple_network_listen_range(0, 0, SOCK_STREAM, yahoo_p2p_ft_server_listen_cb, xfer)) {
-			purple_xfer_cancel_remote(xfer);
-			return;
-		}
-	}
-}
-
-/* TODO: Check filename etc. No probs till some hacker comes in the way */
-void yahoo_process_filetrans_acc_15(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	gchar *xfer_peer_idstring = NULL;
-	gchar *xfer_idstring_for_relay = NULL;
-	PurpleXfer *xfer;
-	YahooData *yd;
-	struct yahoo_xfer_data *xfer_data;
-	GSList *l;
-	PurpleAccount *account;
-	long val_66 = 0;
-	gchar *url = NULL;
-	int val_249 = 0;
-
-	yd = gc->proto_data;
-	for (l = pkt->hash; l; l = l->next) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 251:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				xfer_idstring_for_relay = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_filetrans_acc_15 "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 265:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				xfer_peer_idstring = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_filetrans_acc_15 "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 66:
-			val_66 = atol(pair->value);
-			break;
-		case 249:
-			val_249 = atol(pair->value);
-			break;
-		case 250:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				/* we get a p2p url here when sending file, connected as client */
-				url = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_filetrans_acc_15 "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		}
-	}
-
-	xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xfer_peer_idstring);
-	if(!xfer) return;
-
-	if(val_66 == -1 || ( (!(xfer_idstring_for_relay)) && (val_249 != 2) ))
-	{
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	if( (val_249 == 2) && (!(url)) )
-	{
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	xfer_data = xfer->data;
-	if(url)
-		purple_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL);
-
-	xfer_data->xfer_idstring_for_relay = g_strdup(xfer_idstring_for_relay);
-	xfer_data->status_15 = ACCEPTED;
-	account = purple_connection_get_account(gc);
-
-	if (purple_proxy_connect(gc, account, xfer_data->host, xfer_data->port,
-		yahoo_xfer_connected_15, xfer) == NULL)
-	{
-		purple_notify_error(gc, NULL, _("File Transfer Failed"),_("Unable to connect"));
-			purple_xfer_cancel_remote(xfer);
-	}
-}
--- a/libpurple/protocols/yahoo/yahoo_filexfer.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +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 _YAHOO_FILEXFER_H_
-#define _YAHOO_FILEXFER_H_
-
-#include "ft.h"
-
-/**
- * Process ymsg events, particular IMViroments like Doodle
- */
-void yahoo_process_p2pfilexfer( PurpleConnection *gc, struct yahoo_packet *pkt );
-
-/**
- * Process ymsg file receive invites.
- */
-void yahoo_process_filetransfer(PurpleConnection *gc, struct yahoo_packet *pkt);
-
-/**
- * Create a new PurpleXfer
- *
- * @param gc The PurpleConnection handle.
- * @param who Who will we be sending it to?
- */
-PurpleXfer *yahoo_new_xfer(PurpleConnection *gc, const char *who);
-
-/**
- * Returns TRUE if the buddy can receive file, FALSE otherwise.
- * Federated users cannot receive files. So this will return FALSE only
- * for them.
- *
- * @param gc The connection
- * @param who The name of the remote user
- *
- * @return TRUE or FALSE
- */
-gboolean yahoo_can_receive_file(PurpleConnection *gc, const char *who);
-
-/**
- * Send a file.
- *
- * @param gc The PurpleConnection handle.
- * @param who Who are we sending it to?
- * @param file What file? If NULL, user will choose after this call.
- */
-void yahoo_send_file(PurpleConnection *gc, const char *who, const char *file);
-
-void yahoo_process_filetrans_15(PurpleConnection *gc, struct yahoo_packet *pkt);
-void yahoo_process_filetrans_info_15(PurpleConnection *gc, struct yahoo_packet *pkt);
-void yahoo_process_filetrans_acc_15(PurpleConnection *gc, struct yahoo_packet *pkt);
-
-#endif
--- a/libpurple/protocols/yahoo/yahoo_friend.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,330 +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 "prpl.h"
-#include "util.h"
-#include "debug.h"
-
-#include "yahoo_friend.h"
-#include "yahoo_aliases.h"
-
-static YahooFriend *yahoo_friend_new(void)
-{
-	YahooFriend *ret;
-
-	ret = g_new0(YahooFriend, 1);
-	ret->status = YAHOO_STATUS_OFFLINE;
-	ret->presence = YAHOO_PRESENCE_DEFAULT;
-
-	return ret;
-}
-
-YahooFriend *yahoo_friend_find(PurpleConnection *gc, const char *name)
-{
-	YahooData *yd;
-	const char *norm;
-
-	g_return_val_if_fail(gc != NULL, NULL);
-	g_return_val_if_fail(gc->proto_data != NULL, NULL);
-
-	yd = gc->proto_data;
-	norm = purple_normalize(purple_connection_get_account(gc), name);
-
-	return g_hash_table_lookup(yd->friends, norm);
-}
-
-YahooFriend *yahoo_friend_find_or_new(PurpleConnection *gc, const char *name)
-{
-	YahooFriend *f;
-	YahooData *yd;
-	const char *norm;
-
-	g_return_val_if_fail(gc != NULL, NULL);
-	g_return_val_if_fail(gc->proto_data != NULL, NULL);
-
-	yd = gc->proto_data;
-	norm = purple_normalize(purple_connection_get_account(gc), name);
-
-	f = g_hash_table_lookup(yd->friends, norm);
-	if (!f) {
-		f = yahoo_friend_new();
-		g_hash_table_insert(yd->friends, g_strdup(norm), f);
-	}
-
-	return f;
-}
-
-void yahoo_friend_set_ip(YahooFriend *f, const char *ip)
-{
-	g_free(f->ip);
-	f->ip = g_strdup(ip);
-}
-
-const char *yahoo_friend_get_ip(YahooFriend *f)
-{
-	return f->ip;
-}
-
-void yahoo_friend_set_game(YahooFriend *f, const char *game)
-{
-	g_free(f->game);
-
-	if (game)
-		f->game = g_strdup(game);
-	else
-		f->game = NULL;
-}
-
-const char *yahoo_friend_get_game(YahooFriend *f)
-{
-	return f->game;
-}
-
-void yahoo_friend_set_status_message(YahooFriend *f, char *msg)
-{
-	g_free(f->msg);
-
-	f->msg = msg;
-}
-
-const char *yahoo_friend_get_status_message(YahooFriend *f)
-{
-	return f->msg;
-}
-
-void yahoo_friend_set_buddy_icon_need_request(YahooFriend *f, gboolean needs)
-{
-	f->bicon_sent_request = !needs;
-}
-
-gboolean yahoo_friend_get_buddy_icon_need_request(YahooFriend *f)
-{
-	return !f->bicon_sent_request;
-}
-
-void yahoo_friend_set_alias_id(YahooFriend *f, const char *alias_id)
-{
-	g_free(f->ypd.id);
-	f->ypd.id = g_strdup(alias_id);
-}
-
-const char *yahoo_friend_get_alias_id(YahooFriend *f)
-{
-	return f->ypd.id;
-}
-
-void yahoo_friend_free(gpointer p)
-{
-	YahooFriend *f = p;
-	g_free(f->msg);
-	g_free(f->game);
-	g_free(f->ip);
-	yahoo_personal_details_reset(&f->ypd, TRUE);
-	g_free(f);
-}
-
-void yahoo_process_presence(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	GSList *l = pkt->hash;
-	YahooFriend *f;
-	char *temp = NULL;
-	char *who = NULL;
-	int value = 0;
-	YahooFederation fed = YAHOO_FEDERATION_NONE;
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-			case 7:
-				if (g_utf8_validate(pair->value, -1, NULL)) {
-					temp = pair->value;
-				} else {
-					purple_debug_warning("yahoo", "yahoo_process_presence "
-							"got non-UTF-8 string for key %d\n", pair->key);
-				}
-				break;
-			case 31:
-				value = strtol(pair->value, NULL, 10);
-				break;
-			case 241:
-				fed = strtol(pair->value, NULL, 10);
-				break;
-		}
-
-		l = l->next;
-	}
-
-	if (value != 1 && value != 2) {
-		purple_debug_error("yahoo", "Received unknown value for presence key: %d\n", value);
-		return;
-	}
-
-	switch (fed) {
-		case YAHOO_FEDERATION_MSN:
-			who = g_strconcat("msn/", temp, NULL);
-			break;
-		case YAHOO_FEDERATION_OCS:
-			who = g_strconcat("ocs/", temp, NULL);
-			break;
-		case YAHOO_FEDERATION_IBM:
-			who = g_strconcat("ibm/", temp, NULL);
-			break;
-		case YAHOO_FEDERATION_PBX:
-			who = g_strconcat("pbx/", temp, NULL);
-			break;
-		case YAHOO_FEDERATION_NONE:
-			who = g_strdup(temp);
-			break;
-	}
-	g_return_if_fail(who != NULL);
-
-	f = yahoo_friend_find(gc, who);
-	if (!f)	{
-		g_free(who);
-		return;
-	}
-
-	if (pkt->service == YAHOO_SERVICE_PRESENCE_PERM) {
-		purple_debug_info("yahoo", "Setting permanent presence for %s to %d.\n", who, (value == 1));
-		/* If setting from perm offline to online when in invisible status,
-		 * this has already been taken care of (when the temp status changed) */
-		if (value == 2 && f->presence == YAHOO_PRESENCE_ONLINE) {
-		} else {
-			if (value == 1) /* Setting Perm offline */
-				f->presence = YAHOO_PRESENCE_PERM_OFFLINE;
-			else
-				f->presence = YAHOO_PRESENCE_DEFAULT;
-		}
-	} else {
-		purple_debug_info("yahoo", "Setting session presence for %s to %d.\n", who, (value == 1));
-		if (value == 1)
-			f->presence = YAHOO_PRESENCE_ONLINE;
-		else
-			f->presence = YAHOO_PRESENCE_DEFAULT;
-	}
-	g_free(who);
-}
-
-void yahoo_friend_update_presence(PurpleConnection *gc, const char *name,
-		YahooPresenceVisibility presence)
-{
-	YahooData *yd = gc->proto_data;
-	struct yahoo_packet *pkt = NULL;
-	YahooFriend *f;
-	const char *thirtyone, *thirteen;
-	int service = -1;
-	const char *temp = NULL;
-
-	if (!yd->logged_in)
-		return;
-
-	f = yahoo_friend_find(gc, name);
-	if (!f)
-		return;
-
-	if(f->fed != YAHOO_FEDERATION_NONE)
-		temp = name+4;
-	else
-		temp = name;
-
-	/* No need to change the value if it is already correct */
-	if (f->presence == presence) {
-		purple_debug_info("yahoo", "Not setting presence because there are no changes.\n");
-		return;
-	}
-
-	if (presence == YAHOO_PRESENCE_PERM_OFFLINE) {
-		service = YAHOO_SERVICE_PRESENCE_PERM;
-		thirtyone = "1";
-		thirteen = "2";
-	} else if (presence == YAHOO_PRESENCE_DEFAULT) {
-		if (f->presence == YAHOO_PRESENCE_PERM_OFFLINE) {
-			service = YAHOO_SERVICE_PRESENCE_PERM;
-			thirtyone = "2";
-			thirteen = "2";
-		} else if (yd->current_status == YAHOO_STATUS_INVISIBLE) {
-			service = YAHOO_SERVICE_PRESENCE_SESSION;
-			thirtyone = "2";
-			thirteen = "1";
-		}
-	} else if (presence == YAHOO_PRESENCE_ONLINE) {
-		if (f->presence == YAHOO_PRESENCE_PERM_OFFLINE) {
-			pkt = yahoo_packet_new(YAHOO_SERVICE_PRESENCE_PERM,
-					YAHOO_STATUS_AVAILABLE, yd->session_id);
-			if(f->fed)
-				yahoo_packet_hash(pkt, "ssssssiss",
-					1, purple_connection_get_display_name(gc),
-					31, "2", 13, "2",
-					302, "319", 300, "319",
-					7, temp, 241, f->fed,
-					301, "319", 303, "319");
-			else
-				yahoo_packet_hash(pkt, "ssssssss",
-					1, purple_connection_get_display_name(gc),
-					31, "2", 13, "2",
-					302, "319", 300, "319",
-					7, temp,
-					301, "319", 303, "319");
-
-			yahoo_packet_send_and_free(pkt, yd);
-		}
-
-		service = YAHOO_SERVICE_PRESENCE_SESSION;
-		thirtyone = "1";
-		thirteen = "1";
-	}
-
-	if (service > 0) {
-		pkt = yahoo_packet_new(service,
-				YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-		if(f->fed)
-			yahoo_packet_hash(pkt, "ssssssiss",
-				1, purple_connection_get_display_name(gc),
-				31, thirtyone, 13, thirteen,
-				302, "319", 300, "319",
-				7, temp, 241, f->fed,
-				301, "319", 303, "319");
-		else
-			yahoo_packet_hash(pkt, "ssssssss",
-				1, purple_connection_get_display_name(gc),
-				31, thirtyone, 13, thirteen,
-				302, "319", 300, "319",
-				7, temp,
-				301, "319", 303, "319");
-
-		yahoo_packet_send_and_free(pkt, yd);
-	}
-}
-
-void yahoo_friend_set_p2p_status(YahooFriend *f, YahooP2PStatus p2p_status)
-{
-	f->p2p_status = p2p_status;
-}
-
-YahooP2PStatus yahoo_friend_get_p2p_status(YahooFriend *f)
-{
-	return f->p2p_status;
-}
--- a/libpurple/protocols/yahoo/yahoo_friend.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/**
- * @file yahoo_friend.h The Yahoo! protocol plugin YahooFriend object
- *
- * 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 _YAHOO_FRIEND_H_
-#define _YAHOO_FRIEND_H_
-
-#include "libymsg.h"
-#include "yahoo_packet.h"
-
-typedef enum {
-	YAHOO_PRESENCE_DEFAULT = 0,
-	YAHOO_PRESENCE_ONLINE,
-	YAHOO_PRESENCE_PERM_OFFLINE
-} YahooPresenceVisibility;
-
-typedef enum {
-	YAHOO_P2PSTATUS_NOT_CONNECTED = 0,
-	YAHOO_P2PSTATUS_DO_NOT_CONNECT,
-	YAHOO_P2PSTATUS_WE_ARE_SERVER,
-	YAHOO_P2PSTATUS_WE_ARE_CLIENT
-} YahooP2PStatus;
-
-
-/* these are called friends instead of buddies mainly so I can use variables
- * named f and not confuse them with variables named b
- */
-typedef struct _YahooFriend {
-	enum yahoo_status status;
-	gchar *msg;
-	gchar *game;
-	int idle;
-	int away;
-	gboolean sms;
-	gchar *ip;
-	gboolean bicon_sent_request;
-	YahooPresenceVisibility presence;
-	YahooFederation fed;
-	long int version_id;
-	YahooPersonalDetails ypd;
-	YahooP2PStatus p2p_status;
-	gboolean p2p_packet_sent;	/* 0:not sent, 1=sent */
-	gint session_id;	/* session id of friend */
-} YahooFriend;
-
-YahooFriend *yahoo_friend_find(PurpleConnection *gc, const char *name);
-YahooFriend *yahoo_friend_find_or_new(PurpleConnection *gc, const char *name);
-
-void yahoo_friend_set_ip(YahooFriend *f, const char *ip);
-const char *yahoo_friend_get_ip(YahooFriend *f);
-
-void yahoo_friend_set_game(YahooFriend *f, const char *game);
-const char *yahoo_friend_get_game(YahooFriend *f);
-
-void yahoo_friend_set_status_message(YahooFriend *f, char *msg);
-const char *yahoo_friend_get_status_message(YahooFriend *f);
-
-void yahoo_friend_set_alias_id(YahooFriend *f, const char *alias_id);
-const char *yahoo_friend_get_alias_id(YahooFriend *f);
-
-void yahoo_friend_set_buddy_icon_need_request(YahooFriend *f, gboolean needs);
-gboolean yahoo_friend_get_buddy_icon_need_request(YahooFriend *f);
-
-void yahoo_friend_free(gpointer p);
-
-void yahoo_process_presence(PurpleConnection *gc, struct yahoo_packet *pkt);
-void yahoo_friend_update_presence(PurpleConnection *gc, const char *name,
-		YahooPresenceVisibility presence);
-
-void yahoo_friend_set_p2p_status(YahooFriend *f, YahooP2PStatus p2p_status);
-YahooP2PStatus yahoo_friend_get_p2p_status(YahooFriend *f);
-
-#endif /* _YAHOO_FRIEND_H_ */
--- a/libpurple/protocols/yahoo/yahoo_packet.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,403 +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 "debug.h"
-
-#include "libymsg.h"
-#include "yahoo_packet.h"
-
-struct yahoo_packet *yahoo_packet_new(enum yahoo_service service, enum yahoo_status status, int id)
-{
-	struct yahoo_packet *pkt = g_new0(struct yahoo_packet, 1);
-
-	pkt->service = service;
-	pkt->status = status;
-	pkt->id = id;
-
-	return pkt;
-}
-
-void yahoo_packet_hash_str(struct yahoo_packet *pkt, int key, const char *value)
-{
-	struct yahoo_pair *pair;
-
-	g_return_if_fail(value != NULL);
-
-	pair = g_new0(struct yahoo_pair, 1);
-	pair->key = key;
-	pair->value = g_strdup(value);
-	pkt->hash = g_slist_prepend(pkt->hash, pair);
-}
-
-void yahoo_packet_hash_int(struct yahoo_packet *pkt, int key, int value)
-{
-	struct yahoo_pair *pair;
-
-	pair = g_new0(struct yahoo_pair, 1);
-	pair->key = key;
-	pair->value = g_strdup_printf("%d", value);
-	pkt->hash = g_slist_prepend(pkt->hash, pair);
-}
-
-void yahoo_packet_hash(struct yahoo_packet *pkt, const char *fmt, ...)
-{
-	char *strval;
-	int key, intval;
-	const char *cur;
-	va_list ap;
-
-	va_start(ap, fmt);
-	for (cur = fmt; *cur; cur++) {
-		key = va_arg(ap, int);
-		switch (*cur) {
-		case 'i':
-			intval = va_arg(ap, int);
-			yahoo_packet_hash_int(pkt, key, intval);
-			break;
-		case 's':
-			strval = va_arg(ap, char *);
-			yahoo_packet_hash_str(pkt, key, strval);
-			break;
-		default:
-			purple_debug_error("yahoo", "Invalid format character '%c'\n", *cur);
-			break;
-		}
-	}
-	va_end(ap);
-}
-
-size_t yahoo_packet_length(struct yahoo_packet *pkt)
-{
-	GSList *l;
-
-	size_t len = 0;
-
-	l = pkt->hash;
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-		int tmp = pair->key;
-		do {
-			tmp /= 10;
-			len++;
-		} while (tmp);
-		len += 2;
-		len += strlen(pair->value);
-		len += 2;
-		l = l->next;
-	}
-
-	return len;
-}
-
-/*
- * 'len' is the value given to us by the server that is supposed to
- * be the length of 'data'.  But apparently there's a time when this
- * length is incorrect.  Christopher Layne thinks it might be a bug
- * in their server code.
- *
- * The following information is from Christopher:
- *
- * It sometimes happens when Yahoo! sends a packet continuation within
- * chat.  Sometimes when joining a large chatroom the initial
- * SERVICE_CHATJOIN packet will be so large that it will need to be
- * split into multiple packets.  That's fine, except that the length
- * of the second packet is wrong.  The packet has the same length as
- * the first packet, and the length given in the header is the same,
- * however the actual data in the packet is shorter than this length.
- * So half of the packet contains good, valid data, and then the rest
- * of the packet is junk.  Luckily there is a null terminator after
- * the valid data and before the invalid data.
- *
- * What does all this mean?  It means that we parse through the data
- * pulling out key/value pairs until we've parsed 'len' bytes, or until
- * we run into a null terminator, whichever comes first.
- */
-void yahoo_packet_read(struct yahoo_packet *pkt, const guchar *data, int len)
-{
-	int pos = 0;
-	char key[64];
-	const guchar *delimiter;
-	gboolean accept;
-	guint x;
-	struct yahoo_pair *pair;
-
-	while (pos + 1 < len)
-	{
-		if (data[pos] == '\0')
-			break;
-
-		pair = g_new0(struct yahoo_pair, 1);
-
-		x = 0;
-		while (pos + 1 < len) {
-			if (data[pos] == 0xc0 && data[pos + 1] == 0x80)
-				break;
-			if (x >= sizeof(key)-1) {
-				x++;
-				pos++;
-				continue;
-			}
-			key[x++] = data[pos++];
-		}
-		if (x >= sizeof(key)-1) {
-			x = 0;
-		}
-		key[x] = 0;
-		pos += 2;
-		pair->key = strtol(key, NULL, 10);
-		accept = x; /* if x is 0 there was no key, so don't accept it */
-
-		if (pos + 1 > len) {
-			/* Malformed packet! (Truncated--garbage or something) */
-			accept = FALSE;
-		}
-
-		if (accept) {
-			delimiter = (const guchar *)g_strstr_len((const char *)&data[pos], len - pos, "\xc0\x80");
-			if (delimiter == NULL)
-			{
-				/* Malformed packet! (It doesn't end in 0xc0 0x80) */
-				g_free(pair);
-				pos = len;
-				continue;
-			}
-			x = delimiter - data;
-			pair->value = g_strndup((const gchar *)&data[pos], x - pos);
-			pos = x;
-			pkt->hash = g_slist_prepend(pkt->hash, pair);
-
-			if (purple_debug_is_verbose() || g_getenv("PURPLE_YAHOO_DEBUG")) {
-				char *esc;
-				esc = g_strescape(pair->value, NULL);
-				purple_debug_misc("yahoo", "Key: %d  \tValue: %s\n", pair->key, esc);
-				g_free(esc);
-			}
-		} else {
-			g_free(pair);
-		}
-		pos += 2;
-
-		if (pos + 1 > len) break;
-
-		/* Skip over garbage we've noticed in the mail notifications */
-		if (data[0] == '9' && data[pos] == 0x01)
-			pos++;
-	}
-
-	/*
-	 * Originally this function used g_slist_append().  I changed
-	 * it to use g_slist_prepend() for improved performance.
-	 * Ideally the Yahoo! PRPL code would be indifferent to the
-	 * order of the key/value pairs, but I don't know if this is
-	 * the case for all incoming messages.  To be on the safe side
-	 * we reverse the list.
-	 */
-	pkt->hash = g_slist_reverse(pkt->hash);
-}
-
-void yahoo_packet_write(struct yahoo_packet *pkt, guchar *data)
-{
-	GSList *l;
-	int pos = 0;
-
-	/* This is only called from one place, and the list is
-	 * always backwards */
-
-	l = pkt->hash = g_slist_reverse(pkt->hash);
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-		gchar buf[100];
-
-		g_snprintf(buf, sizeof(buf), "%d", pair->key);
-		strcpy((char *)&data[pos], buf);
-		pos += strlen(buf);
-		data[pos++] = 0xc0;
-		data[pos++] = 0x80;
-
-		strcpy((char *)&data[pos], pair->value);
-		pos += strlen(pair->value);
-		data[pos++] = 0xc0;
-		data[pos++] = 0x80;
-
-		l = l->next;
-	}
-}
-
-void yahoo_packet_dump(guchar *data, int len)
-{
-#ifdef YAHOO_DEBUG
-	int i;
-
-	purple_debug_misc("yahoo", "");
-
-	for (i = 0; i + 1 < len; i += 2) {
-		if ((i % 16 == 0) && i) {
-			purple_debug_misc(NULL, "\n");
-			purple_debug_misc("yahoo", "");
-		}
-
-		purple_debug_misc(NULL, "%02x%02x ", data[i], data[i + 1]);
-	}
-	if (i < len)
-		purple_debug_misc(NULL, "%02x", data[i]);
-
-	purple_debug_misc(NULL, "\n");
-	purple_debug_misc("yahoo", "");
-
-	for (i = 0; i < len; i++) {
-		if ((i % 16 == 0) && i) {
-			purple_debug_misc(NULL, "\n");
-			purple_debug_misc("yahoo", "");
-		}
-
-		if (g_ascii_isprint(data[i]))
-			purple_debug_misc(NULL, "%c ", data[i]);
-		else
-			purple_debug_misc(NULL, ". ");
-	}
-
-	purple_debug_misc(NULL, "\n");
-#endif /* YAHOO_DEBUG */
-}
-
-static void
-yahoo_packet_send_can_write(gpointer data, gint source, PurpleInputCondition cond)
-{
-	YahooData *yd = data;
-	int ret, writelen;
-
-	writelen = purple_circ_buffer_get_max_read(yd->txbuf);
-
-	if (writelen == 0) {
-		purple_input_remove(yd->txhandler);
-		yd->txhandler = 0;
-		return;
-	}
-
-	ret = write(yd->fd, yd->txbuf->outptr, writelen);
-
-	if (ret < 0 && errno == EAGAIN)
-		return;
-	else if (ret < 0) {
-		/* TODO: what to do here - do we really have to disconnect? */
-		purple_connection_error_reason(yd->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-		                               _("Write Error"));
-		return;
-	}
-
-	purple_circ_buffer_mark_read(yd->txbuf, ret);
-}
-
-
-size_t yahoo_packet_build(struct yahoo_packet *pkt, int pad, gboolean wm,
-			 gboolean jp, guchar **buf)
-{
-	size_t pktlen = yahoo_packet_length(pkt);
-	size_t len = YAHOO_PACKET_HDRLEN + pktlen;
-	guchar *data;
-	int pos = 0;
-
-	data = g_malloc0(len + 1);
-
-	memcpy(data + pos, "YMSG", 4); pos += 4;
-
-	if (wm)
-		pos += yahoo_put16(data + pos, YAHOO_WEBMESSENGER_PROTO_VER);
-	else if (jp)
-		pos += yahoo_put16(data + pos, YAHOO_PROTO_VER_JAPAN);
-	else
-		pos += yahoo_put16(data + pos, YAHOO_PROTO_VER);
-	pos += yahoo_put16(data + pos, 0x0000);
-	pos += yahoo_put16(data + pos, pktlen + pad);
-	pos += yahoo_put16(data + pos, pkt->service);
-	pos += yahoo_put32(data + pos, pkt->status);
-	pos += yahoo_put32(data + pos, pkt->id);
-
-	yahoo_packet_write(pkt, data + pos);
-
-	*buf = data;
-
-	return len;
-}
-
-int yahoo_packet_send(struct yahoo_packet *pkt, YahooData *yd)
-{
-	size_t len;
-	gssize ret;
-	guchar *data;
-
-	if (yd->fd < 0)
-		return -1;
-
-	len = yahoo_packet_build(pkt, 0, yd->wm, yd->jp, &data);
-
-	yahoo_packet_dump(data, len);
-	if (yd->txhandler == 0)
-		ret = write(yd->fd, data, len);
-	else {
-		ret = -1;
-		errno = EAGAIN;
-	}
-
-	if (ret < 0 && errno == EAGAIN)
-		ret = 0;
-	else if (ret <= 0) {
-		purple_debug_warning("yahoo", "Only wrote %" G_GSSIZE_FORMAT
-				" of %" G_GSIZE_FORMAT " bytes!\n", ret, len);
-		g_free(data);
-		return ret;
-	}
-
-	if ((gsize)ret < len) {
-		if (yd->txhandler == 0)
-			yd->txhandler = purple_input_add(yd->fd, PURPLE_INPUT_WRITE,
-				yahoo_packet_send_can_write, yd);
-		purple_circ_buffer_append(yd->txbuf, data + ret, len - ret);
-	}
-
-	g_free(data);
-
-	return ret;
-}
-
-int yahoo_packet_send_and_free(struct yahoo_packet *pkt, YahooData *yd)
-{
-	int ret;
-
-	ret = yahoo_packet_send(pkt, yd);
-	yahoo_packet_free(pkt);
-	return ret;
-}
-
-void yahoo_packet_free(struct yahoo_packet *pkt)
-{
-	while (pkt->hash) {
-		struct yahoo_pair *pair = pkt->hash->data;
-		g_free(pair->value);
-		g_free(pair);
-		pkt->hash = g_slist_delete_link(pkt->hash, pkt->hash);
-	}
-	g_free(pkt);
-}
--- a/libpurple/protocols/yahoo/yahoo_packet.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/**
- * @file yahoo_packet.h The Yahoo! protocol plugin
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#ifndef _YAHOO_PACKET_H_
-#define _YAHOO_PACKET_H_
-
-enum yahoo_service { /* these are easier to see in hex */
-	YAHOO_SERVICE_LOGON = 1,
-	YAHOO_SERVICE_LOGOFF,
-	YAHOO_SERVICE_ISAWAY,
-	YAHOO_SERVICE_ISBACK,
-	YAHOO_SERVICE_IDLE, /* 5 (placemarker) */
-	YAHOO_SERVICE_MESSAGE,
-	YAHOO_SERVICE_IDACT,
-	YAHOO_SERVICE_IDDEACT,
-	YAHOO_SERVICE_MAILSTAT,
-	YAHOO_SERVICE_USERSTAT, /* 0xa */
-	YAHOO_SERVICE_NEWMAIL,
-	YAHOO_SERVICE_CHATINVITE,
-	YAHOO_SERVICE_CALENDAR,
-	YAHOO_SERVICE_NEWPERSONALMAIL,
-	YAHOO_SERVICE_NEWCONTACT,
-	YAHOO_SERVICE_ADDIDENT, /* 0x10 */
-	YAHOO_SERVICE_ADDIGNORE,
-	YAHOO_SERVICE_PING,
-	YAHOO_SERVICE_GOTGROUPRENAME,
-	YAHOO_SERVICE_SYSMESSAGE = 0x14,
-	YAHOO_SERVICE_SKINNAME = 0x15,
-	YAHOO_SERVICE_PASSTHROUGH2 = 0x16,
-	YAHOO_SERVICE_CONFINVITE = 0x18,
-	YAHOO_SERVICE_CONFLOGON,
-	YAHOO_SERVICE_CONFDECLINE,
-	YAHOO_SERVICE_CONFLOGOFF,
-	YAHOO_SERVICE_CONFADDINVITE,
-	YAHOO_SERVICE_CONFMSG,
-	YAHOO_SERVICE_CHATLOGON,
-	YAHOO_SERVICE_CHATLOGOFF,
-	YAHOO_SERVICE_CHATMSG = 0x20,
-	YAHOO_SERVICE_GAMELOGON = 0x28,
-	YAHOO_SERVICE_GAMELOGOFF,
-	YAHOO_SERVICE_GAMEMSG = 0x2a,
-	YAHOO_SERVICE_FILETRANSFER = 0x46,
-	YAHOO_SERVICE_VOICECHAT = 0x4A,
-	YAHOO_SERVICE_NOTIFY = 0x4B,
-	YAHOO_SERVICE_VERIFY,
-	YAHOO_SERVICE_P2PFILEXFER,
-	YAHOO_SERVICE_PEERTOPEER = 0x4F,
-	YAHOO_SERVICE_WEBCAM,
-	YAHOO_SERVICE_AUTHRESP = 0x54,
-	YAHOO_SERVICE_LIST = 0x55,
-	YAHOO_SERVICE_AUTH = 0x57,
-	YAHOO_SERVICE_AUTHBUDDY = 0x6d,
-	YAHOO_SERVICE_ADDBUDDY = 0x83,
-	YAHOO_SERVICE_REMBUDDY = 0x84,
-	YAHOO_SERVICE_IGNORECONTACT,    /* > 1, 7, 13 < 1, 66, 13, 0*/
-	YAHOO_SERVICE_REJECTCONTACT,
-	YAHOO_SERVICE_GROUPRENAME = 0x89, /* > 1, 65(new), 66(0), 67(old) */
-	YAHOO_SERVICE_KEEPALIVE = 0x8A,
-	YAHOO_SERVICE_CHATONLINE = 0x96, /* > 109(id), 1, 6(abcde) < 0,1*/
-	YAHOO_SERVICE_CHATGOTO,
-	YAHOO_SERVICE_CHATJOIN, /* > 1 104-room 129-1600326591 62-2 */
-	YAHOO_SERVICE_CHATLEAVE,
-	YAHOO_SERVICE_CHATEXIT = 0x9b,
-	YAHOO_SERVICE_CHATADDINVITE = 0x9d,
-	YAHOO_SERVICE_CHATLOGOUT = 0xa0,
-	YAHOO_SERVICE_CHATPING,
-	YAHOO_SERVICE_COMMENT = 0xa8,
-	YAHOO_SERVICE_PRESENCE_PERM = 0xb9,
-	YAHOO_SERVICE_PRESENCE_SESSION = 0xba,
-	YAHOO_SERVICE_AVATAR = 0xbc,
-	YAHOO_SERVICE_PICTURE_CHECKSUM = 0xbd,
-	YAHOO_SERVICE_PICTURE = 0xbe,
-	YAHOO_SERVICE_PICTURE_UPDATE = 0xc1,
-	YAHOO_SERVICE_PICTURE_UPLOAD = 0xc2,
-	YAHOO_SERVICE_Y6_VISIBLE_TOGGLE = 0xc5,
-	YAHOO_SERVICE_Y6_STATUS_UPDATE = 0xc6,
-	YAHOO_SERVICE_AVATAR_UPDATE = 0xc7,
-	YAHOO_SERVICE_VERIFY_ID_EXISTS = 0xc8,
-	YAHOO_SERVICE_AUDIBLE = 0xd0,
-	YAHOO_SERVICE_CONTACT_DETAILS = 0xd3,
-	/* YAHOO_SERVICE_CHAT_SESSION = 0xd4,?? Reports start of chat session, gets an id from server */
-	YAHOO_SERVICE_AUTH_REQ_15 = 0xd6,
-	YAHOO_SERVICE_FILETRANS_15 = 0xdc,
-	YAHOO_SERVICE_FILETRANS_INFO_15 = 0xdd,
-	YAHOO_SERVICE_FILETRANS_ACC_15 = 0xde,
-	/* photo sharing services ?? - 0xd2, 0xd7, 0xd8, 0xda */
-	YAHOO_SERVICE_CHGRP_15 = 0xe7,
-	YAHOO_SERVICE_STATUS_15 = 0xf0,
-	YAHOO_SERVICE_LIST_15 = 0xf1,
-	YAHOO_SERVICE_MESSAGE_ACK = 0xfb,
-	YAHOO_SERVICE_WEBLOGIN = 0x0226,
-	YAHOO_SERVICE_SMS_MSG = 0x02ea
-	/* YAHOO_SERVICE_DISCONNECT = 0x07d1 Server forces us to disconnect. Is sent with TCP FIN flag set */
-};
-
-struct yahoo_pair {
-	int key;
-	char *value;
-};
-
-struct yahoo_packet {
-	guint16 service;
-	gint32 status;
-	guint32 id;
-	GSList *hash;
-};
-
-#define YAHOO_WEBMESSENGER_PROTO_VER 0x0065
-#define YAHOO_PROTO_VER 0x0010
-#define YAHOO_PROTO_VER_JAPAN 0x0010
-
-#define YAHOO_PACKET_HDRLEN (4 + 2 + 2 + 2 + 2 + 4 + 4)
-
-struct yahoo_packet *yahoo_packet_new(enum yahoo_service service,
-				      enum yahoo_status status, int id);
-void yahoo_packet_hash(struct yahoo_packet *pkt, const char *fmt, ...);
-void yahoo_packet_hash_str(struct yahoo_packet *pkt, int key, const char *value);
-void yahoo_packet_hash_int(struct yahoo_packet *pkt, int key, int value);
-int yahoo_packet_send(struct yahoo_packet *pkt, YahooData *yd);
-int yahoo_packet_send_and_free(struct yahoo_packet *pkt, YahooData *yd);
-size_t yahoo_packet_build(struct yahoo_packet *pkt, int pad, gboolean wm, gboolean jp,
-guchar **buf);
-void yahoo_packet_read(struct yahoo_packet *pkt, const guchar *data, int len);
-void yahoo_packet_write(struct yahoo_packet *pkt, guchar *data);
-void yahoo_packet_dump(guchar *data, int len);
-size_t yahoo_packet_length(struct yahoo_packet *pkt);
-void yahoo_packet_free(struct yahoo_packet *pkt);
-
-#endif /* _YAHOO_PACKET_H_ */
--- a/libpurple/protocols/yahoo/yahoo_picture.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,611 +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 "accountopt.h"
-#include "blist.h"
-#include "debug.h"
-#include "privacy.h"
-#include "prpl.h"
-#include "proxy.h"
-#include "util.h"
-
-#include "libymsg.h"
-#include "yahoo_packet.h"
-#include "yahoo_friend.h"
-#include "yahoo_picture.h"
-
-
-struct yahoo_fetch_picture_data {
-	PurpleConnection *gc;
-	char *who;
-	int checksum;
-};
-
-static void
-yahoo_fetch_picture_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
-		const gchar *pic_data, size_t len, const gchar *error_message)
-{
-	struct yahoo_fetch_picture_data *d;
-	YahooData *yd;
-
-	d = user_data;
-	yd = d->gc->proto_data;
-	yd->url_datas = g_slist_remove(yd->url_datas, url_data);
-
-	if (error_message != NULL) {
-		purple_debug_error("yahoo", "Fetching buddy icon failed: %s\n", error_message);
-	} else if (len == 0) {
-		purple_debug_error("yahoo", "Fetched an icon with length 0.  Strange.\n");
-	} else {
-		char *checksum = g_strdup_printf("%i", d->checksum);
-		purple_buddy_icons_set_for_user(purple_connection_get_account(d->gc), d->who, g_memdup(pic_data, len), len, checksum);
-		g_free(checksum);
-	}
-
-	g_free(d->who);
-	g_free(d);
-}
-
-void yahoo_process_picture(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	YahooData *yd;
-	GSList *l = pkt->hash;
-	char *who = NULL;
-	gboolean got_icon_info = FALSE, send_icon_info = FALSE;
-	char *url = NULL;
-	int checksum = 0;
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 1:
-		case 4:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				who = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_picture "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 5: /* us */
-			break;
-		case 13: {
-				int tmp;
-				tmp = strtol(pair->value, NULL, 10);
-				if (tmp == 1) {
-					send_icon_info = TRUE;
-				} else if (tmp == 2) {
-					got_icon_info = TRUE;
-				}
-				break;
-			}
-		case 20:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				url = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_picture "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 192:
-			checksum = strtol(pair->value, NULL, 10);
-			break;
-		}
-
-		l = l->next;
-	}
-
-	if (!who)
-		return;
-
-	if (!purple_privacy_check(purple_connection_get_account(gc), who)) {
-		purple_debug_info("yahoo", "Picture packet from %s dropped.\n", who);
-		return;
-	}
-
-	/* Yahoo IM 6 spits out 0.png as the URL if the buddy icon is not set */
-	if (who && got_icon_info && url && !g_ascii_strncasecmp(url, "http://", 7)) {
-		/* TODO: make this work p2p, try p2p before the url */
-		PurpleUtilFetchUrlData *url_data;
-		struct yahoo_fetch_picture_data *data;
-		/* use whole URL if using HTTP Proxy */
-		gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
-
-		data = g_new0(struct yahoo_fetch_picture_data, 1);
-		data->gc = gc;
-		data->who = g_strdup(who);
-		data->checksum = checksum;
-		/* TODO: Does this need to be MSIE 5.0? */
-		url_data = purple_util_fetch_url(url, use_whole_url,
-				"Mozilla/4.0 (compatible; MSIE 5.5)", FALSE,
-				yahoo_fetch_picture_cb, data);
-		if (url_data != NULL) {
-			yd = gc->proto_data;
-			yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
-		}
-	} else if (who && send_icon_info) {
-		yahoo_send_picture_info(gc, who);
-	}
-}
-
-void yahoo_process_picture_checksum(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	GSList *l = pkt->hash;
-	char *who = NULL;
-	int checksum = 0;
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 4:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				who = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_picture_checksum "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 5:
-			/* us */
-			break;
-		case 192:
-			checksum = strtol(pair->value, NULL, 10);
-			break;
-		}
-		l = l->next;
-	}
-
-	if (who) {
-		PurpleBuddy *b = purple_find_buddy(gc->account, who);
-		const char *locksum = NULL;
-
-		/* FIXME: Cleanup this strtol() stuff if possible. */
-		if (b) {
-			locksum = purple_buddy_icons_get_checksum_for_user(b);
-			if (!locksum || (checksum != strtol(locksum, NULL, 10)))
-				yahoo_send_picture_request(gc, who);
-		}
-	}
-}
-
-void yahoo_process_picture_upload(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	PurpleAccount *account = purple_connection_get_account(gc);
-	YahooData *yd = gc->proto_data;
-	GSList *l = pkt->hash;
-	char *url = NULL;
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 5:
-			/* us */
-			break;
-		case 27:
-			/* filename on our computer. */
-			break;
-		case 20: /* url at yahoo */
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				url = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_picture_upload "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-		case 38: /* timestamp */
-			break;
-		}
-		l = l->next;
-	}
-
-	if (url) {
-		g_free(yd->picture_url);
-		yd->picture_url = g_strdup(url);
-		purple_account_set_string(account, YAHOO_PICURL_SETTING, url);
-		purple_account_set_int(account, YAHOO_PICCKSUM_SETTING, yd->picture_checksum);
-		yahoo_send_picture_checksum(gc);
-		yahoo_send_picture_update(gc, 2);
-	}
-}
-
-void yahoo_process_avatar_update(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	GSList *l = pkt->hash;
-	char *who = NULL;
-	int avatar = 0;
-
-	while (l) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 4:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				who = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_avatar_upload "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 5:
-			/* us */
-			break;
-		case 206:   /* Older versions. Still needed? */
-		case 213:   /* Newer versions */
-			/*
-			 * 0 - No icon or avatar
-			 * 1 - Using an avatar
-			 * 2 - Using an icon
-			 */
-			avatar = strtol(pair->value, NULL, 10);
-			break;
-		}
-		l = l->next;
-	}
-
-	if (who) {
-		if (avatar == 2)
-			yahoo_send_picture_request(gc, who);
-		else if ((avatar == 0) || (avatar == 1)) {
-			YahooFriend *f;
-			purple_buddy_icons_set_for_user(gc->account, who, NULL, 0, NULL);
-			if ((f = yahoo_friend_find(gc, who)))
-				yahoo_friend_set_buddy_icon_need_request(f, TRUE);
-			purple_debug_misc("yahoo", "Setting user %s's icon to NULL.\n", who);
-		}
-	}
-}
-
-void yahoo_send_picture_info(PurpleConnection *gc, const char *who)
-{
-	YahooData *yd = gc->proto_data;
-	struct yahoo_packet *pkt;
-
-	if (!yd->picture_url) {
-		purple_debug_warning("yahoo", "Attempted to send picture info without a picture\n");
-		return;
-	}
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash(pkt, "ssssi", 1, purple_connection_get_display_name(gc),
-	                  5, who,
-	                  13, "2", 20, yd->picture_url, 192, yd->picture_checksum);
-	yahoo_packet_send_and_free(pkt, yd);
-}
-
-void yahoo_send_picture_request(PurpleConnection *gc, const char *who)
-{
-	YahooData *yd = gc->proto_data;
-	struct yahoo_packet *pkt;
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash_str(pkt, 1, purple_connection_get_display_name(gc)); /* me */
-	yahoo_packet_hash_str(pkt, 5, who); /* the other guy */
-	yahoo_packet_hash_str(pkt, 13, "1"); /* 1 = request, 2 = reply */
-	yahoo_packet_send_and_free(pkt, yd);
-}
-
-void yahoo_send_picture_checksum(PurpleConnection *gc)
-{
-	YahooData *yd = gc->proto_data;
-	struct yahoo_packet *pkt;
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_CHECKSUM, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash(pkt, "ssi", 1, purple_connection_get_display_name(gc),
-			  212, "1", 192, yd->picture_checksum);
-	yahoo_packet_send_and_free(pkt, yd);
-}
-
-void yahoo_send_picture_update_to_user(PurpleConnection *gc, const char *who, int type)
-{
-	YahooData *yd = gc->proto_data;
-	struct yahoo_packet *pkt;
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_AVATAR_UPDATE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash(pkt, "si", 3, who, 213, type);
-	yahoo_packet_send_and_free(pkt, yd);
-}
-
-struct yspufe {
-	PurpleConnection *gc;
-	int type;
-};
-
-static void yahoo_send_picture_update_foreach(gpointer key, gpointer value, gpointer data)
-{
-	const char *who = key;
-	YahooFriend *f = value;
-	struct yspufe *d = data;
-
-	if (f->status != YAHOO_STATUS_OFFLINE)
-		yahoo_send_picture_update_to_user(d->gc, who, d->type);
-}
-
-void yahoo_send_picture_update(PurpleConnection *gc, int type)
-{
-	YahooData *yd = gc->proto_data;
-	struct yspufe data;
-
-	data.gc = gc;
-	data.type = type;
-
-	g_hash_table_foreach(yd->friends, yahoo_send_picture_update_foreach, &data);
-}
-
-void yahoo_buddy_icon_upload_data_free(struct yahoo_buddy_icon_upload_data *d)
-{
-	purple_debug_misc("yahoo", "In yahoo_buddy_icon_upload_data_free()\n");
-
-	if (d->str)
-		g_string_free(d->str, TRUE);
-	g_free(d->filename);
-	if (d->watcher)
-		purple_input_remove(d->watcher);
-	if (d->fd != -1)
-		close(d->fd);
-	g_free(d);
-}
-
-/* we couldn't care less about the server's response, but yahoo gets grumpy if we close before it sends it */
-static void yahoo_buddy_icon_upload_reading(gpointer data, gint source, PurpleInputCondition condition)
-{
-	struct yahoo_buddy_icon_upload_data *d = data;
-	PurpleConnection *gc = d->gc;
-	char buf[1024];
-	int ret;
-
-	if (!PURPLE_CONNECTION_IS_VALID(gc)) {
-		yahoo_buddy_icon_upload_data_free(d);
-		return;
-	}
-
-	ret = read(d->fd, buf, sizeof(buf));
-
-	if (ret < 0 && errno == EAGAIN)
-		return;
-	else if (ret <= 0) {
-		/* There are other problems if d->str->len overflows, so shut up the
-		 * warning on 64-bit. */
-		purple_debug_info("yahoo", "Buddy icon upload response (%" G_GSIZE_FORMAT ") bytes (> ~400 indicates failure):\n%.*s\n",
-			d->str->len, (guint)d->str->len, d->str->str);
-
-		yahoo_buddy_icon_upload_data_free(d);
-		return;
-	}
-
-	g_string_append_len(d->str, buf, ret);
-}
-
-static void yahoo_buddy_icon_upload_pending(gpointer data, gint source, PurpleInputCondition condition)
-{
-	struct yahoo_buddy_icon_upload_data *d = data;
-	PurpleConnection *gc = d->gc;
-	gssize wrote;
-
-	if (!PURPLE_CONNECTION_IS_VALID(gc)) {
-		yahoo_buddy_icon_upload_data_free(d);
-		return;
-	}
-
-	wrote = write(d->fd, d->str->str + d->pos, d->str->len - d->pos);
-	if (wrote < 0 && errno == EAGAIN)
-		return;
-	if (wrote <= 0) {
-		purple_debug_info("yahoo", "Error uploading buddy icon.\n");
-		yahoo_buddy_icon_upload_data_free(d);
-		return;
-	}
-	d->pos += wrote;
-	if ((size_t)d->pos >= d->str->len) {
-		purple_debug_misc("yahoo", "Finished uploading buddy icon.\n");
-		purple_input_remove(d->watcher);
-		/* Clean out the sent buffer and reuse it to read the result */
-		g_string_free(d->str, TRUE);
-		d->str = g_string_new("");
-		d->watcher = purple_input_add(d->fd, PURPLE_INPUT_READ, yahoo_buddy_icon_upload_reading, d);
-	}
-}
-
-static void yahoo_buddy_icon_upload_connected(gpointer data, gint source, const gchar *error_message)
-{
-	struct yahoo_buddy_icon_upload_data *d = data;
-	struct yahoo_packet *pkt;
-	gchar *tmp, *header;
-	guchar *pkt_buf;
-	const char *host;
-	int port;
-	gsize pkt_buf_len;
-	PurpleConnection *gc = d->gc;
-	PurpleAccount *account;
-	YahooData *yd;
-	/* use whole URL if using HTTP Proxy */
-	gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
-
-	account = purple_connection_get_account(gc);
-	yd = gc->proto_data;
-
-	/* Buddy icon connect is now complete; clear the PurpleProxyConnectData */
-	yd->buddy_icon_connect_data = NULL;
-
-	if (source < 0) {
-		purple_debug_error("yahoo", "Buddy icon upload failed: %s\n", error_message);
-		yahoo_buddy_icon_upload_data_free(d);
-		return;
-	}
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPLOAD, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	tmp = g_strdup_printf("%" G_GSIZE_FORMAT, d->str->len);
-	/* 1 = me, 38 = expire time(?), 0 = me, 28 = size, 27 = filename, 14 = NULL, 29 = data */
-	yahoo_packet_hash_str(pkt, 1, purple_connection_get_display_name(gc));
-	yahoo_packet_hash_str(pkt, 38, "604800"); /* time til expire */
-	purple_account_set_int(account, YAHOO_PICEXPIRE_SETTING, time(NULL) + 604800);
-	yahoo_packet_hash_str(pkt, 0, purple_connection_get_display_name(gc));
-	yahoo_packet_hash_str(pkt, 28, tmp);
-	g_free(tmp);
-	yahoo_packet_hash_str(pkt, 27, d->filename);
-	yahoo_packet_hash_str(pkt, 14, "");
-	/* 4 padding for the 29 key name */
-	pkt_buf_len = yahoo_packet_build(pkt, 4, FALSE, yd->jp, &pkt_buf);
-	yahoo_packet_free(pkt);
-
-	/* header + packet + "29" + 0xc0 + 0x80) + pictureblob */
-
-	host = purple_account_get_string(account, "xfer_host", yd->jp? YAHOOJP_XFER_HOST : YAHOO_XFER_HOST);
-	port = purple_account_get_int(account, "xfer_port", YAHOO_XFER_PORT);
-	tmp = g_strdup_printf("%s:%d", host, port);
-	header = g_strdup_printf("POST %s%s/notifyft HTTP/1.1\r\n"
-		"User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
-		"Cookie: T=%s; Y=%s\r\n"
-		"Host: %s\r\n"
-		"Content-Length: %" G_GSIZE_FORMAT "\r\n"
-		"Cache-Control: no-cache\r\n\r\n",
-		use_whole_url ? "http://" : "", use_whole_url ? tmp : "",
-		yd->cookie_t, yd->cookie_y,
-		tmp,
-		pkt_buf_len + 4 + d->str->len);
-	g_free(tmp);
-
-	/* There's no magic here, we just need to prepend in reverse order */
-	g_string_prepend(d->str, "29\xc0\x80");
-
-	g_string_prepend_len(d->str, (char *)pkt_buf, pkt_buf_len);
-	g_free(pkt_buf);
-
-	g_string_prepend(d->str, header);
-	g_free(header);
-
-	/* There are other problems if we're uploading over 4GB of data */
-	purple_debug_info("yahoo", "Buddy icon upload data:\n%.*s\n", (guint)d->str->len, d->str->str);
-
-	d->fd = source;
-	d->watcher = purple_input_add(d->fd, PURPLE_INPUT_WRITE, yahoo_buddy_icon_upload_pending, d);
-
-	yahoo_buddy_icon_upload_pending(d, d->fd, PURPLE_INPUT_WRITE);
-}
-
-void yahoo_buddy_icon_upload(PurpleConnection *gc, struct yahoo_buddy_icon_upload_data *d)
-{
-	PurpleAccount *account = purple_connection_get_account(gc);
-	YahooData *yd = gc->proto_data;
-
-	if (yd->buddy_icon_connect_data != NULL) {
-		/* Cancel any in-progress buddy icon upload */
-		purple_proxy_connect_cancel(yd->buddy_icon_connect_data);
-		yd->buddy_icon_connect_data = NULL;
-	}
-
-	yd->buddy_icon_connect_data = purple_proxy_connect(NULL, account,
-			purple_account_get_string(account, "xfer_host",
-				yd->jp? YAHOOJP_XFER_HOST : YAHOO_XFER_HOST),
-			purple_account_get_int(account, "xfer_port", YAHOO_XFER_PORT),
-			yahoo_buddy_icon_upload_connected, d);
-
-	if (yd->buddy_icon_connect_data == NULL)
-	{
-		purple_debug_error("yahoo", "Uploading our buddy icon failed to connect.\n");
-		yahoo_buddy_icon_upload_data_free(d);
-	}
-}
-
-static int yahoo_buddy_icon_calculate_checksum(const guchar *data, gsize len)
-{
-	/* This code is borrowed from Kopete, which seems to be managing to calculate
-	   checksums in such a manner that Yahoo!'s servers are happy */
-
-	const guchar *p = data;
-	int checksum = 0, g, i = len;
-
-	while(i--) {
-		checksum = (checksum << 4) + *p++;
-
-		if((g = (checksum & 0xf0000000)) != 0)
-			checksum ^= g >> 23;
-
-		checksum &= ~g;
-	}
-
-	purple_debug_misc("yahoo", "Calculated buddy icon checksum: %d\n", checksum);
-
-	return checksum;
-}
-
-void yahoo_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img)
-{
-	YahooData *yd = gc->proto_data;
-	PurpleAccount *account = gc->account;
-
-	if (img == NULL) {
-		g_free(yd->picture_url);
-		yd->picture_url = NULL;
-
-		/* TODO: don't we have to clear it on the server too?! */
-
-		purple_account_set_string(account, YAHOO_PICURL_SETTING, NULL);
-		purple_account_set_int(account, YAHOO_PICCKSUM_SETTING, 0);
-		purple_account_set_int(account, YAHOO_PICEXPIRE_SETTING, 0);
-		if (yd->logged_in)
-			/* Tell everyone we ain't got one no more */
-			yahoo_send_picture_update(gc, 0);
-
-	} else {
-		gconstpointer data = purple_imgstore_get_data(img);
-		size_t len = purple_imgstore_get_size(img);
-		GString *s = g_string_new_len(data, len);
-		struct yahoo_buddy_icon_upload_data *d;
-		int oldcksum = purple_account_get_int(account, YAHOO_PICCKSUM_SETTING, 0);
-		int expire = purple_account_get_int(account, YAHOO_PICEXPIRE_SETTING, 0);
-		const char *oldurl = purple_account_get_string(account, YAHOO_PICURL_SETTING, NULL);
-
-		yd->picture_checksum = yahoo_buddy_icon_calculate_checksum(data, len);
-
-		if ((yd->picture_checksum == oldcksum) &&
-			(expire > (time(NULL) + 60*60*24)) && oldurl)
-		{
-			purple_debug_misc("yahoo", "buddy icon is up to date. Not reuploading.\n");
-			g_string_free(s, TRUE);
-			g_free(yd->picture_url);
-			yd->picture_url = g_strdup(oldurl);
-			return;
-		}
-
-		/* We use this solely for sending a filename to the server */
-		d = g_new0(struct yahoo_buddy_icon_upload_data, 1);
-		d->gc = gc;
-		d->str = s;
-		d->fd = -1;
-		d->filename = g_strdup(purple_imgstore_get_filename(img));
-
-		if (!yd->logged_in) {
-			yd->picture_upload_todo = d;
-			return;
-		}
-
-		yahoo_buddy_icon_upload(gc, d);
-
-	}
-}
--- a/libpurple/protocols/yahoo/yahoo_picture.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +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 _YAHOO_PICTURE_H_
-#define _YAHOO_PICTURE_H_
-
-void yahoo_send_picture_request(PurpleConnection *gc, const char *who);
-void yahoo_send_picture_info(PurpleConnection *gc, const char *who);
-void yahoo_send_picture_checksum(PurpleConnection *gc);
-void yahoo_send_picture_update(PurpleConnection *gc, int type);
-void yahoo_send_picture_update_to_user(PurpleConnection *gc, const char *who, int type);
-
-void yahoo_process_picture(PurpleConnection *gc, struct yahoo_packet *pkt);
-void yahoo_process_picture_checksum(PurpleConnection *gc, struct yahoo_packet *pkt);
-void yahoo_process_picture_upload(PurpleConnection *gc, struct yahoo_packet *pkt);
-
-void yahoo_process_avatar_update(PurpleConnection *gc, struct yahoo_packet *pkt);
-
-void yahoo_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img);
-void yahoo_buddy_icon_upload(PurpleConnection *gc, struct yahoo_buddy_icon_upload_data *d);
-void yahoo_buddy_icon_upload_data_free(struct yahoo_buddy_icon_upload_data *d);
-
-#endif /* _YAHOO_PICTURE_H_ */
--- a/libpurple/protocols/yahoo/yahoo_profile.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1282 +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
- *
- */
-
-#define PHOTO_SUPPORT 1
-
-#include "internal.h"
-#include "debug.h"
-#include "notify.h"
-#include "util.h"
-#if PHOTO_SUPPORT
-#include "imgstore.h"
-#endif /* PHOTO_SUPPORT */
-
-#include "libymsg.h"
-#include "yahoo_friend.h"
-
-typedef struct {
-	PurpleConnection *gc;
-	char *name;
-} YahooGetInfoData;
-
-typedef enum profile_lang_id {
-	XX, DA, DE, EL,
-	EN, EN_GB,
-	ES_AR, ES_ES, ES_MX, ES_US,
-	FR_CA, FR_FR,
-	IT, JA, KO, NO, PT, SV,
-	ZH_CN, ZH_HK, ZH_TW, ZH_US, PT_BR
-} profile_lang_id_t;
-
-typedef struct profile_lang_node {
-	profile_lang_id_t lang;
-	char *last_updated_string;
-	char *det;
-} profile_lang_node_t;
-
-typedef struct profile_strings_node {
-	profile_lang_id_t lang;
-	char *lang_string;                   /* Only to make debugging output saner */
-	char *charset;
-	char *yahoo_id_string;
-	char *private_string;
-	char *no_answer_string;
-	char *my_email_string;
-	char *realname_string;
-	char *location_string;
-	char *age_string;
-	char *maritalstatus_string;
-	char *gender_string;
-	char *occupation_string;
-	char *hobbies_string;
-	char *latest_news_string;
-	char *favorite_quote_string;
-	char *links_string;
-	char *no_home_page_specified_string;
-	char *home_page_string;
-	char *no_cool_link_specified_string;
-	char *cool_link_1_string;
-	char *cool_link_2_string;
-	char *cool_link_3_string;
-	char *dummy;
-} profile_strings_node_t;
-
-typedef enum profile_state {
-	PROFILE_STATE_DEFAULT,
-	PROFILE_STATE_NOT_FOUND,
-	PROFILE_STATE_UNKNOWN_LANGUAGE
-} profile_state_t;
-
-typedef struct {
-	YahooGetInfoData *info_data;
-	PurpleNotifyUserInfo *user_info;
-	char *url_buffer;
-	char *photo_url_text;
-	char *profile_url_text;
-	const profile_strings_node_t *strings;
-	const char *last_updated_string;
-	const char *title;
-	profile_state_t profile_state;
-} YahooGetInfoStepTwoData;
-
-/* Strings to determine the profile "language" (more accurately "locale").
- * Strings in this list must be in the original charset in the profile.
- * The "Last Updated" string is used, but sometimes is not sufficient to
- * distinguish 2 locales with this (e.g., ES_ES from ES_US, or FR_CA from
- * FR_FR, or EL from EN_GB), in which case a second string is added and
- * such special cases must be placed before the more general case.
- */
-static const profile_lang_node_t profile_langs[] = {
-	{ DA,    "Opdateret sidste gang&nbsp;",                          NULL },
-	{ DE,    "Letzter Update&nbsp;",                                 NULL },
-	{ EL,    "Last Updated:",              "http://gr.profiles.yahoo.com" },
-	{ EN_GB, "Last Update&nbsp;",                      "Favourite Quote" },
-	{ EN,    "Last Update:",                                        NULL },
-	{ EN,    "Last Update&nbsp;",                                   NULL },
-	{ ES_AR, "\332ltima actualizaci\363n&nbsp;",                     NULL },
-	{ ES_ES, "Actualizada el&nbsp;",       "http://es.profiles.yahoo.com" },
-	{ ES_MX, "Actualizada el &nbsp;",      "http://mx.profiles.yahoo.com" },
-	{ ES_US, "Actualizada el &nbsp;",                                NULL },
-	{ FR_CA, "Derni\xe8re mise \xe0 jour", "http://cf.profiles.yahoo.com" },
-	{ FR_FR, "Derni\xe8re mise \xe0 jour",                           NULL },
-	{ IT,    "Ultimo aggiornamento:",                                NULL },
-	{ JA,    "\xba\xc7\xbd\xaa\xb9\xb9\xbf\xb7\xc6\xfc\xa1\xa7",     NULL },
-	{ KO,    "\xb0\xbb\xbd\xc5\x20\xb3\xaf\xc2\xa5&nbsp;",           NULL },
-	{ NO,    "Sist oppdatert&nbsp;",                                 NULL },
-	{ PT,    "\332ltima atualiza\347\343o&nbsp;",                    NULL },
-	{ PT_BR, "\332ltima atualiza\347\343o:",                         NULL },
-	{ SV,    "Senast uppdaterad&nbsp;",                              NULL },
-	{ ZH_CN, "\xd7\xee\xba\xf3\xd0\xde\xb8\xc4\xc8\xd5\xc6\xda",     NULL },
-	{ ZH_HK, "\xb3\xcc\xaa\xf1\xa7\xf3\xb7\x73\xae\xc9\xb6\xa1",     NULL },
-	{ ZH_US, "\xb3\xcc\xab\xe1\xad\xd7\xa7\xef\xa4\xe9\xb4\xc1", "http://chinese.profiles.yahoo.com" },
-	{ ZH_TW, "\xb3\xcc\xab\xe1\xad\xd7\xa7\xef\xa4\xe9\xb4\xc1",     NULL },
-	{ XX,     NULL,                                                  NULL }
-};
-
-/* Strings in this list must be in UTF-8; &nbsp;'s should be specified as spaces. */
-static const profile_strings_node_t profile_strings[] = {
-	{ DA, "da", "ISO-8859-1",
-		"Yahoo! ID:",
-		"Privat",
-		"Intet svar",
-		"Min Email",
-		"Rigtige navn:",
-		"Opholdssted:",
-		"Alder:",
-		"Ɔgteskabelig status:",
-		"KĆøn:",
-		"Erhverv:",
-		"Hobbyer:",
-		"Sidste nyt:",
-		"Favoritcitat",
-		"Links",
-		"Ingen hjemmeside specificeret",
-		"Forside:",
-		"Intet cool link specificeret",
-		"Cool link 1:",
-		"Cool link 2:",
-		"Cool link 3:",
-		NULL
-	},
-	{ DE, "de", "ISO-8859-1",
-		"Yahoo!-ID:",
-		"Privat",
-		"Keine Antwort",
-		"Meine E-Mail",
-		"Realer Name:",
-		"Ort:",
-		"Alter:",
-		"Familienstand:",
-		"Geschlecht:",
-		"Beruf:",
-		"Hobbys:",
-		"Neuste Nachrichten:",
-		"Mein Lieblingsspruch",
-		"Links",
-		"Keine Homepage angegeben",
-		"Homepage:",
-		"Keinen coolen Link angegeben",
-		"Cooler Link 1:",
-		"Cooler Link 2:",
-		"Cooler Link 3:",
-		NULL
-	},
-	{ EL, "el", "ISO-8859-7", /* EL is identical to EN, except no_answer_string */
-		"Yahoo! ID:",
-		"Private",
-		"Καμία Ī±Ļ€Ī¬Ī½Ļ„Ī·ĻƒĪ·",
-		"My Email",
-		"Real Name:",
-		"Location:",
-		"Age:",
-		"Marital Status:",
-		"Gender:",
-		"Occupation:",
-		"Hobbies:",
-		"Latest News",
-		"Favorite Quote",
-		"Links",
-		"No home page specified",
-		"Home Page:",
-		"No cool link specified",
-		"Cool Link 1:",
-		"Cool Link 2:",
-		"Cool Link 3:",
-		NULL
-	},
-	{ EN, "en", "ISO-8859-1",
-		"Yahoo! ID:",
-		"Private",
-		"No Answer",
-		"My Email:",
-		"Real Name:",
-		"Location:",
-		"Age:",
-		"Marital Status:",
-		"Sex:",
-		"Occupation:",
-		"Hobbies",
-		"Latest News",
-		"Favorite Quote",
-		"Links",
-		"No home page specified",
-		"Home Page:",
-		"No cool link specified",
-		"Cool Link 1",
-		"Cool Link 2",
-		"Cool Link 3",
-		NULL
-	},
-	{ EN_GB, "en_GB", "ISO-8859-1", /* Same as EN except spelling of "Favourite" */
-		"Yahoo! ID:",
-		"Private",
-		"No Answer",
-		"My Email:",
-		"Real Name:",
-		"Location:",
-		"Age:",
-		"Marital Status:",
-		"Sex:",
-		"Occupation:",
-		"Hobbies",
-		"Latest News",
-		"Favourite Quote",
-		"Links",
-		"No home page specified",
-		"Home Page:",
-		"No cool link specified",
-		"Cool Link 1",
-		"Cool Link 2",
-		"Cool Link 3",
-		NULL
-	},
-	{ ES_AR, "es_AR", "ISO-8859-1",
-		"Usuario de Yahoo!:",
-		"Privado",
-		"No introdujiste una respuesta",
-		"Mi dirección de correo electrónico",
-		"Nombre real:",
-		"Ubicación:",
-		"Edad:",
-		"Estado civil:",
-		"Sexo:",
-		"Ocupación:",
-		"Pasatiempos:",
-		"Últimas noticias:",
-		"Tu cita favorita",
-		"Enlaces",
-		"Ninguna pƔgina de inicio especificada",
-		"PƔgina de inicio:",
-		"NingĆŗn enlace preferido",
-		"Enlace genial 1:",
-		"Enlace genial 2:",
-		"Enlace genial 3:",
-		NULL
-	},
-	{ ES_ES, "es_ES", "ISO-8859-1",
-		"ID de Yahoo!:",
-		"Privado",
-		"Sin respuesta",
-		"Mi correo-e",
-		"Nombre verdadero:",
-		"Lugar:",
-		"Edad:",
-		"Estado civil:",
-		"Sexo:",
-		"Ocupación:",
-		"Aficiones:",
-		"Ultimas Noticias:",
-		"Tu cita Favorita",
-		"Enlace",
-		"Ninguna pƔgina personal especificada",
-		"PƔgina de Inicio:",
-		"NingĆŗn enlace preferido",
-		"Enlaces Preferidos 1:",
-		"Enlaces Preferidos 2:",
-		"Enlaces Preferidos 3:",
-		NULL
-	},
-	{ ES_MX, "es_MX", "ISO-8859-1",
-		"ID de Yahoo!:",
-		"Privado",
-		"Sin responder",
-		"Mi Dirección de correo-e",
-		"Nombre real:",
-		"Ubicación:",
-		"Edad:",
-		"Estado civil:",
-		"Sexo:",
-		"Ocupación:",
-		"Pasatiempos:",
-		"Ultimas Noticias:",
-		"Su cita favorita",
-		"Enlaces",
-		"Ninguna PƔgina predefinida",
-		"PƔgina web:",
-		"NingĆŗn Enlace preferido",
-		"Enlaces Preferidos 1:",
-		"Enlaces Preferidos 2:",
-		"Enlaces Preferidos 3:",
-		NULL
-	},
-	{ ES_US, "es_US", "ISO-8859-1",
-		"ID de Yahoo!:",
-		"Privado",
-		"No introdujo una respuesta",
-		"Mi Dirección de correo-e",
-		"Nombre real:",
-		"Localidad:",
-		"Edad:",
-		"Estado civil:",
-		"Sexo:",
-		"Ocupación:",
-		"Pasatiempos:",
-		"Ultimas Noticias:",
-		"Su cita Favorita",
-		"Enlaces",
-		"Ninguna PƔgina de inicio predefinida",
-		"PƔgina de inicio:",
-		"NingĆŗn Enlace preferido",
-		"Enlaces Preferidos 1:",
-		"Enlaces Preferidos 2:",
-		"Enlaces Preferidos 3:",
-		NULL
-	},
-	{ FR_CA, "fr_CA", "ISO-8859-1",
-		"Compte Yahoo!:",
-		"PrivƩ",
-		"Sans rƩponse",
-		"Mon courriel",
-		"Nom rƩel:",
-		"Lieu:",
-		"Ƃge:",
-		"Ɖtat civil:",
-		"Sexe:",
-		"Profession:",
-		"Passe-temps:",
-		"ActualitƩs:",
-		"Citation prƩfƩrƩe",
-		"Liens",
-		"Pas de mention d'une page personnelle",
-		"Page personnelle:",
-		"Pas de mention d'un lien favori",
-		"Lien prƩfƩrƩ 1:",
-		"Lien prƩfƩrƩ 2:",
-		"Lien prƩfƩrƩ 3:",
-		NULL
-	},
-	{ FR_FR, "fr_FR", "ISO-8859-1",
-		"Compte Yahoo!:",
-		"PrivƩ",
-		"Sans rƩponse",
-		"Mon E-mail",
-		"Nom rƩel:",
-		"Lieu:",
-		"Ƃge:",
-		"Situation de famille:",
-		"Sexe:",
-		"Profession:",
-		"Centres d'intérêts:",
-		"ActualitƩs:",
-		"Citation prƩfƩrƩe",
-		"Liens",
-		"Pas de mention d'une page perso",
-		"Page perso:",
-		"Pas de mention d'un lien favori",
-		"Lien prƩfƩrƩ 1:",
-		"Lien prƩfƩrƩ 2:",
-		"Lien prƩfƩrƩ 3:",
-		NULL
-	},
-	{ IT, "it", "ISO-8859-1",
-		"Yahoo! ID:",
-		"Non pubblica",
-		"Nessuna risposta",
-		"La mia e-mail:",
-		"Nome vero:",
-		"LocalitĆ :",
-		"EtĆ :",
-		"Stato civile:",
-		"Sesso:",
-		"Occupazione:",
-		"Hobby",
-		"Ultime notizie",
-		"Citazione preferita",
-		"Link",
-		"Nessuna home page specificata",
-		"Inizio:",
-		"Nessun link specificato",
-		"Cool Link 1",
-		"Cool Link 2",
-		"Cool Link 3",
-		NULL
-	},
-	{ JA, "ja", "EUC-JP",
-		"Yahoo! JAPAN ID:",
-		"非公開",
-		"ē„”å›žē­”",
-		"ピール:",
-		"åå‰ļ¼š",
-		"ä½ę‰€ļ¼š",
-		"幓齢:",
-		"未婚/ę—¢å©šļ¼š",
-		"ę€§åˆ„ļ¼š",
-		"職愭:",
-		"č¶£å‘³ļ¼š",
-		"ęœ€čæ‘ć®å‡ŗę„äŗ‹ļ¼š",
-		NULL,
-#if 0
-		"ćŠć™ć™ć‚ć‚µć‚¤ćƒˆ",
-#else
-		"自己PR", /* "Self description" comes before "Links" for yahoo.co.jp */
-#endif
-		NULL,
-		NULL,
-		NULL,
-		"ćŠć™ć™ć‚ć‚µć‚¤ćƒˆ1:",
-		"ćŠć™ć™ć‚ć‚µć‚¤ćƒˆ2:",
-		"ćŠć™ć™ć‚ć‚µć‚¤ćƒˆ3:",
-		NULL
-	},
-	{ KO, "ko", "EUC-KR",
-		"야후! ID:",
-		"ė¹„ź³µź°œ",
-		"ė¹„ź³µź°œ",
-		"My Email",
-		"실명:",
-		"거주지:",
-		"ė‚˜ģ“:",
-		"결혼 여부:",
-		"성별:",
-		"직업:",
-		"취미:",
-		"ģžźø° ģ†Œź°œ:",
-		"ģ¢‹ģ•„ķ•˜ėŠ” ėŖ…ģ–ø",
-		"링크",
-		"ķ™ˆķŽ˜ģ“ģ§€ė„¼ ģ§€ģ •ķ•˜ģ§€ ģ•Šģ•˜ģŠµė‹ˆė‹¤.",
-		"ķ™ˆķŽ˜ģ“ģ§€:",
-		"ģ¶”ģ²œ ģ‚¬ģ“ķŠøź°€ ģ—†ģŠµė‹ˆė‹¤.",
-		"ģ¶”ģ²œ ģ‚¬ģ“ķŠø 1:",
-		"ģ¶”ģ²œ ģ‚¬ģ“ķŠø 2:",
-		"ģ¶”ģ²œ ģ‚¬ģ“ķŠø 3:",
-		NULL
-	},
-	{ NO, "no", "ISO-8859-1",
-		"Yahoo! ID:",
-		"Privat",
-		"Ikke noe svar",
-		"Min e-post",
-		"Virkelig navn:",
-		"Sted:",
-		"Alder:",
-		"Sivilstatus:",
-		"KjĆønn:",
-		"Yrke:",
-		"Hobbyer:",
-		"Siste nytt:",
-		"Yndlingssitat",
-		"Lenker",
-		"Ingen hjemmeside angitt",
-		"Hjemmeside:",
-		"No cool link specified",
-		"Bra lenke 1:",
-		"Bra lenke 2:",
-		"Bra lenke 3:",
-		NULL
-	},
-	{ PT, "pt", "ISO-8859-1",
-		"ID Yahoo!:",
-		"Particular",
-		"Sem resposta",
-		"Meu e-mail",
-		"Nome verdadeiro:",
-		"Local:",
-		"Idade:",
-		"Estado civil:",
-		"Sexo:",
-		"Ocupação:",
-		"Hobbies:",
-		"Últimas notícias:",
-		"Frase favorita",
-		"Links",
-		"Nenhuma pƔgina pessoal especificada",
-		"PƔgina pessoal:",
-		"Nenhum site legal especificado",
-		"Site legal 1:",
-		"Site legal 2:",
-		"Site legal 3:",
-		NULL
-	},
-	{ PT_BR, "pt_br", "ISO-8859-1",
-		"ID Yahoo!:",
-		"Particular",
-		"Sem resposta",
-		"Meu e-mail",
-		"Nome verdadeiro:",
-		"Localização:",
-		"Idade:",
-		"Estado civil:",
-		"Sexo:",
-		"Ocupação:",
-		"Pasatiempos:",
-		"Últimas novidades:",
-		"Frase preferida:",
-		"Links",
-		"Nenhuma home page especificada",
-		"PƔgina Web:",
-		"Nenhum site legal especificado",
-		"Link legal 1",
-		"Link legal 2",
-		"Link legal 3",
-		NULL
-	},
-	{ SV, "sv", "ISO-8859-1",
-		"Yahoo!-ID:",
-		"Privat",
-		"Inget svar",
-		"Min mail",
-		"Riktigt namn:",
-		"Plats:",
-		"ƅlder:",
-		"CivilstƄnd:",
-		"Kƶn:",
-		"Yrke:",
-		"Hobby:",
-		"Senaste nytt:",
-		"Favoritcitat",
-		"LƤnkar",
-		"Ingen hemsida specificerad",
-		"Hemsida:",
-		"Ingen cool lƤnk specificerad",
-		"Coola lƤnkar 1:",
-		"Coola lƤnkar 2:",
-		"Coola lƤnkar 3:",
-		NULL
-	},
-	{ ZH_CN, "zh_CN", "GB2312",
-		"Yahoo! ID:",
-		"ę²”ęœ‰ęä¾›",
-		"ę²”ęœ‰å›žē­”",
-		"äøŖäŗŗē”µé‚®åœ°å€",
-		"ēœŸå®žå§“å:",
-		"ę‰€åœØåœ°ē‚¹:",
-		"幓龄:",
-		"å©šå§»ēŠ¶å†µ:",
-		"ę€§åˆ«:",
-		"职业:",
-		"äøšä½™ēˆ±å„½:",
-		"个人近况:",
-		"å–œę¬¢ēš„å¼•čØ€",
-		"é“¾ęŽ„",
-		"ę²”ęœ‰äøŖäŗŗäø»é”µ",
-		"个人主锵:",
-		"ę²”ęœ‰ęŽØčē½‘ē«™é“¾ęŽ„",
-		"ęŽØčē½‘ē«™é“¾ęŽ„ 1:",
-		"ęŽØčē½‘ē«™é“¾ęŽ„ 2:",
-		"ęŽØčē½‘ē«™é“¾ęŽ„ 3:",
-		NULL
-	},
-	{ ZH_HK, "zh_HK", "Big5",
-		"Yahoo! ID:",
-		"ē§äŗŗēš„",
-		"ę²’ęœ‰å›žē­”",
-		"電子俔箱",
-		"ēœŸåÆ¦å§“å:",
-		"地點:",
-		"幓齔:",
-		"å©šå§»ē‹€ę³:",
-		"ę€§åˆ„:",
-		"職ꄭ:",
-		"嗜儽:",
-		"ęœ€ę–°ę¶ˆęÆ:",
-		"ęœ€å–œę„›ēš„č‚”ē„Øå«åƒ¹", /* [sic] Yahoo!'s translators don't check context */
-		"連結",
-		"ę²’ęœ‰ę³Øę˜Žå€‹äŗŗē¶²é ", /* [sic] */
-		"個人網頁:",
-		"ę²’ęœ‰ę³Øę˜Ž Cool 連結", /* [sic] */
-		"Cool 連結 1:", /* TODO */
-		"Cool 連結 2:", /* TODO */
-		"Cool 連結 3:", /* TODO */
-		NULL
-	},
-	{ ZH_TW, "zh_TW", "Big5",
-		"åø³ 號:",
-		"ę²’ęœ‰ęä¾›",
-		"ę²’ęœ‰å›žę‡‰",
-		"電子俔箱",
-		"姓名:",
-		"地點:",
-		"幓齔:",
-		"å©šå§»ē‹€ę…‹:",
-		"ę€§åˆ„:",
-		"職ꄭ:",
-		"興趣:",
-		"個人近況:",
-		"å–œę­”ēš„åå„",
-		"連結",
-		"ę²’ęœ‰å€‹äŗŗē¶²é ",
-		"個人網頁:",
-		"ę²’ęœ‰ęŽØč–¦ē¶²ē«™é€£ēµ",
-		"ęŽØč–¦ē¶²ē«™é€£ēµ 1:",
-		"ęŽØč–¦ē¶²ē«™é€£ēµ 2:",
-		"ęŽØč–¦ē¶²ē«™é€£ēµ 3:",
-		NULL
-	},
-	{ ZH_US, "zh_US", "Big5", /* ZH_US is like ZH_TW, but also a bit like ZH_HK */
-		"Yahoo! ID:",
-		"ę²’ęœ‰ęä¾›",
-		"ę²’ęœ‰å›žē­”",
-		"個人Email地址",
-		"ēœŸåÆ¦å§“å:",
-		"地點:",
-		"幓齔:",
-		"å©šå§»ē‹€ę…‹:",
-		"ę€§åˆ„:",
-		"職ꄭ:",
-		"嗜儽:",
-		"個人近況:",
-		"å–œę­”ēš„åå„",
-		"連結",
-		"ę²’ęœ‰å€‹äŗŗē¶²é ",
-		"個人網頁:",
-		"ę²’ęœ‰ęŽØč–¦ē¶²ē«™é€£ēµ",
-		"ęŽØč–¦ē¶²ē«™é€£ēµ 1:", /* TODO */
-		"ęŽØč–¦ē¶²ē«™é€£ēµ 2:", /* TODO */
-		"ęŽØč–¦ē¶²ē«™é€£ēµ 3:", /* TODO */
-		NULL
-	},
-	{ XX, NULL, NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL
-	},
-};
-
-static char *yahoo_info_date_reformat(const char *field, size_t len)
-{
-	char *tmp = g_strndup(field, len);
-	time_t t = purple_str_to_time(tmp, FALSE, NULL, NULL, NULL);
-
-	g_free(tmp);
-	return g_strdup(purple_date_format_short(localtime(&t)));
-}
-
-static char *yahoo_remove_nonbreaking_spaces(char *str)
-{
-	char *p;
-	while ((p = strstr(str, "&nbsp;")) != NULL) {
-		*p = ' '; /* Turn &nbsp;'s into ordinary blanks */
-		p += 1;
-		memmove(p, p + 5, strlen(p + 5));
-		str[strlen(str) - 5] = '\0';
-	}
-	return str;
-}
-
-static void yahoo_extract_user_info_text(PurpleNotifyUserInfo *user_info, YahooGetInfoData *info_data) {
-	PurpleBuddy *b;
-	YahooFriend *f;
-
-	b = purple_find_buddy(purple_connection_get_account(info_data->gc),
-			info_data->name);
-
-	if (b) {
-		const char *balias = purple_buddy_get_local_buddy_alias(b);
-		if(balias && balias[0]) {
-			purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), balias);
-		}
-		#if 0
-		if (b->idle > 0) {
-			char *idletime = purple_str_seconds_to_string(time(NULL) - b->idle);
-			purple_notify_user_info_add_pair_plaintext(user_info, _("Idle"), idletime);
-			g_free(idletime);
-		}
-		#endif
-
-		/* Add the normal tooltip pairs */
-		yahoo_tooltip_text(b, user_info, TRUE);
-
-		if ((f = yahoo_friend_find(info_data->gc, purple_buddy_get_name(b)))) {
-			const char *ip;
-			if ((ip = yahoo_friend_get_ip(f)))
-				purple_notify_user_info_add_pair_plaintext(user_info, _("IP Address"), ip);
-		}
-	}
-}
-
-#if PHOTO_SUPPORT
-
-static char *yahoo_get_photo_url(const char *url_text, const char *name) {
-	GString *s = g_string_sized_new(strlen(name) + 8);
-	char *p;
-	char *it = NULL;
-
-	/*g_string_printf(s, " alt=\"%s\">", name);*/
-	/* Y! newformat */
-	g_string_printf(s, " alt=%s>", name);
-	p = strstr(url_text, s->str);
-
-	if (p) {
-		/* Search backwards for "http://". This is stupid, but it works. */
-		for (; !it && p > url_text; p -= 1) {
-			/*if (strncmp(p, "\"http://", 8) == 0) {*/
-			/* Y! newformat*/
-			if (strncmp(p, "=http://", 8) == 0) {
-				char *q;
-				p += 1; /* skip only the ' ' */
-				q = strchr(p, ' ');
-				if (q) {
-					g_free(it);
-					it = g_strndup(p, q - p);
-				}
-			}
-		}
-	}
-
-	g_string_free(s, TRUE);
-	return it;
-}
-
-static void
-yahoo_got_photo(PurpleUtilFetchUrlData *url_data, gpointer data,
-		const gchar *url_text, size_t len, const gchar *error_message);
-
-#endif /* PHOTO_SUPPORT */
-
-static void yahoo_got_info(PurpleUtilFetchUrlData *url_data, gpointer user_data,
-		const gchar *url_text, size_t len, const gchar *error_message)
-{
-	YahooGetInfoData *info_data = (YahooGetInfoData *)user_data;
-	PurpleNotifyUserInfo *user_info;
-	char *p;
-#if PHOTO_SUPPORT
-	YahooGetInfoStepTwoData *info2_data;
-	char *photo_url_text = NULL;
-#else
-	gboolean found = FALSE;
-	char *stripped;
-	int stripped_len;
-	char *last_updated_utf8_string = NULL;
-#endif /* !PHOTO_SUPPORT */
-	const char *last_updated_string = NULL;
-	char *url_buffer;
-	GString *s;
-	char *tmp;
-	char *profile_url_text = NULL;
-	int lang, strid;
-	YahooData *yd;
-	const profile_strings_node_t *strings = NULL;
-	const char *title;
-	profile_state_t profile_state = PROFILE_STATE_DEFAULT;
-
-	purple_debug_info("yahoo", "In yahoo_got_info\n");
-
-	yd = info_data->gc->proto_data;
-	yd->url_datas = g_slist_remove(yd->url_datas, url_data);
-
-	user_info = purple_notify_user_info_new();
-
-	title = yd->jp ? _("Yahoo! Japan Profile") :
-					 _("Yahoo! Profile");
-
-	/* Get the tooltip info string */
-	yahoo_extract_user_info_text(user_info, info_data);
-
-	/* We failed to grab the profile URL.  This is not expected to actually
-	 * happen except under unusual error conditions, as Yahoo is observed
-	 * to send back HTML, with a 200 status code.
-	 */
-	if (error_message != NULL || url_text == NULL || strcmp(url_text, "") == 0) {
-		purple_notify_user_info_add_pair(user_info, _("Error retrieving profile"), NULL);
-		purple_notify_userinfo(info_data->gc, info_data->name,
-			user_info, NULL, NULL);
-		purple_notify_user_info_destroy(user_info);
-		g_free(profile_url_text);
-		g_free(info_data->name);
-		g_free(info_data);
-		return;
-	}
-
-	/* Construct the correct profile URL */
-	s = g_string_sized_new(80); /* wild guess */
-	g_string_printf(s, "%s%s", (yd->jp? YAHOOJP_PROFILE_URL: YAHOO_PROFILE_URL),
-		info_data->name);
-	profile_url_text = g_string_free(s, FALSE);
-	s = NULL;
-
-	/* We don't yet support the multiple link level of the warning page for
-	 * 'adult' profiles, not to mention the fact that yahoo wants you to be
-	 * logged in (on the website) to be able to view an 'adult' profile.  For
-	 * now, just tell them that we can't help them, and provide a link to the
-	 * profile if they want to do the web browser thing.
-	 */
-	p = strstr(url_text, "Adult Profiles Warning Message");
-	if (!p) {
-		p = strstr(url_text, "Adult Content Warning"); /* TITLE element */
-	}
-	if (p) {
-		tmp = g_strdup_printf("<b>%s</b><br><br>"
-							  "%s<br><a href=\"%s\">%s</a>",
-						_("Sorry, profiles marked as containing adult content "
-						"are not supported at this time."),
-						 _("If you wish to view this profile, "
-						"you will need to visit this link in your web browser:"),
-						 profile_url_text, profile_url_text);
-		purple_notify_user_info_add_pair(user_info, NULL, tmp);
-		g_free(tmp);
-
-		purple_notify_userinfo(info_data->gc, info_data->name,
-				user_info, NULL, NULL);
-
-		g_free(profile_url_text);
-		purple_notify_user_info_destroy(user_info);
-		g_free(info_data->name);
-		g_free(info_data);
-		return;
-	}
-
-	/* Check whether the profile is written in a supported language */
-	for (lang = 0;; lang += 1) {
-		last_updated_string = profile_langs[lang].last_updated_string;
-		if (!last_updated_string)
-			break;
-
-		p = strstr(url_text, last_updated_string);
-
-		if (p) {
-			if (profile_langs[lang].det && !strstr(url_text, profile_langs[lang].det))
-				p = NULL;
-			else
-				break;
-		}
-	}
-
-	if (p) {
-		for (strid = 0; profile_strings[strid].lang != XX; strid += 1) {
-			if (profile_strings[strid].lang == profile_langs[lang].lang) break;
-		}
-		strings = profile_strings + strid;
-		purple_debug_info("yahoo", "detected profile lang = %s (%d)\n", profile_strings[strid].lang_string, lang);
-	}
-
-	/* Every user may choose his/her own profile language, and this language
-	 * has nothing to do with the preferences of the user which looks at the
-	 * profile. We try to support all languages, but nothing is guaranteed.
-	 * If we cannot determine the language, it means either (1) the profile
-	 * is written in an unsupported language, (2) our language support is
-	 * out of date, or (3) the user is not found, or (4) Y! have changed their
-	 * webpage layout
-	 */
-	if (!p || strings->lang == XX) {
-		if (!strstr(url_text, "Yahoo! Member Directory - User not found")
-				&& !strstr(url_text, "was not found on this server.")
-				&& !strstr(url_text, "\xb8\xf8\xb3\xab\xa5\xd7\xa5\xed\xa5\xd5\xa5\xa3\xa1\xbc\xa5\xeb\xa4\xac\xb8\xab\xa4\xc4\xa4\xab\xa4\xea\xa4\xde\xa4\xbb\xa4\xf3")) {
-			profile_state = PROFILE_STATE_UNKNOWN_LANGUAGE;
-		} else {
-			profile_state = PROFILE_STATE_NOT_FOUND;
-		}
-	}
-
-#if PHOTO_SUPPORT
-	photo_url_text = yahoo_get_photo_url(url_text, info_data->name);
-#endif /* PHOTO_SUPPORT */
-
-	url_buffer = g_strdup(url_text);
-
-	/*
-	 * purple_markup_strip_html() doesn't strip out character entities like &nbsp;
-	 * and &#183;
-	*/
-	yahoo_remove_nonbreaking_spaces(url_buffer);
-#if 1
-	while ((p = strstr(url_buffer, "&#183;")) != NULL) {
-		memmove(p, p + 6, strlen(p + 6));
-		url_buffer[strlen(url_buffer) - 6] = '\0';
-	}
-#endif
-
-	/* nuke the nasty \r's */
-	purple_str_strip_char(url_buffer, '\r');
-
-#if PHOTO_SUPPORT
-	/* Marshall the existing state */
-	info2_data = g_malloc(sizeof(YahooGetInfoStepTwoData));
-	info2_data->info_data = info_data;
-	info2_data->url_buffer = url_buffer;
-	info2_data->photo_url_text = photo_url_text;
-	info2_data->profile_url_text = profile_url_text;
-	info2_data->strings = strings;
-	info2_data->last_updated_string = last_updated_string;
-	info2_data->title = title;
-	info2_data->profile_state = profile_state;
-	info2_data->user_info = user_info;
-
-	/* Try to put the photo in there too, if there's one */
-	if (photo_url_text) {
-		PurpleUtilFetchUrlData *url_data;
-		/* use whole URL if using HTTP Proxy */
-		gboolean use_whole_url = yahoo_account_use_http_proxy(info_data->gc);
-
-		/* User-uploaded photos use a different server that requires the Host
-		 * header, but Yahoo Japan will use the "chunked" content encoding if
-		 * we specify HTTP 1.1. So we have to specify 1.0 & fix purple_util_fetch_url
-		 */
-		url_data = purple_util_fetch_url(photo_url_text, use_whole_url, NULL,
-				FALSE, yahoo_got_photo, info2_data);
-		if (url_data != NULL)
-			yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
-	} else {
-		/* Emulate a callback */
-		yahoo_got_photo(NULL, info2_data, NULL, 0, NULL);
-	}
-}
-
-static void
-yahoo_got_photo(PurpleUtilFetchUrlData *url_data, gpointer data,
-		const gchar *url_text, size_t len, const gchar *error_message)
-{
-	YahooGetInfoStepTwoData *info2_data = (YahooGetInfoStepTwoData *)data;
-	YahooData *yd;
-	gboolean found = FALSE;
-	int id = -1;
-
-	/* Temporary variables */
-	char *p = NULL;
-	char *stripped;
-	int stripped_len;
-	char *last_updated_utf8_string = NULL;
-	char *tmp;
-
-	/* Unmarshall the saved state */
-	YahooGetInfoData *info_data = info2_data->info_data;
-	char *url_buffer = info2_data->url_buffer;
-	PurpleNotifyUserInfo *user_info = info2_data->user_info;
-	char *photo_url_text = info2_data->photo_url_text;
-	char *profile_url_text = info2_data->profile_url_text;
-	const profile_strings_node_t *strings = info2_data->strings;
-	const char *last_updated_string = info2_data->last_updated_string;
-	profile_state_t profile_state = info2_data->profile_state;
-
-	/* We continue here from yahoo_got_info, as if nothing has happened */
-#endif /* PHOTO_SUPPORT */
-
-	/* Jun 29 05 Bleeter: Y! changed their profile pages. Terminators now seem to be */
-	/* </dd> and not \n. The prpl's need to be audited before it can be moved */
-	/* in to purple_markup_strip_html*/
-	char *fudged_buffer;
-
-	yd = info_data->gc->proto_data;
-	yd->url_datas = g_slist_remove(yd->url_datas, url_data);
-
-	fudged_buffer = purple_strcasereplace(url_buffer, "</dd>", "</dd><br>");
-	/* nuke the html, it's easier than trying to parse the horrid stuff */
-	stripped = purple_markup_strip_html(fudged_buffer);
-	stripped_len = strlen(stripped);
-
-	purple_debug_misc("yahoo", "stripped = %p\n", stripped);
-	purple_debug_misc("yahoo", "url_buffer = %p\n", url_buffer);
-
-	/* convert to utf8 */
-	if (strings && strings->charset) {
-		p = g_convert(stripped, -1, "utf-8", strings->charset,
-				NULL, NULL, NULL);
-		if (!p) {
-			p = g_locale_to_utf8(stripped, -1, NULL, NULL, NULL);
-			if (!p) {
-				p = g_convert(stripped, -1, "utf-8", "windows-1252",
-						NULL, NULL, NULL);
-			}
-		}
-		if (p) {
-			g_free(stripped);
-			stripped = purple_utf8_ncr_decode(p);
-			stripped_len = strlen(stripped);
-			g_free(p);
-		}
-	}
-	p = NULL;
-
-	/* "Last updated" should also be converted to utf8 and with &nbsp; killed */
-	if (strings && strings->charset) {
-		last_updated_utf8_string = g_convert(last_updated_string, -1, "utf-8",
-				strings->charset, NULL, NULL, NULL);
-		yahoo_remove_nonbreaking_spaces(last_updated_utf8_string);
-
-		purple_debug_misc("yahoo", "after utf8 conversion: stripped = (%s)\n", stripped);
-	}
-
-	if (strings && profile_state == PROFILE_STATE_DEFAULT) {
-#if 0
-	/* extract their Yahoo! ID and put it in. Don't bother marking has_info as
-	 * true, since the Yahoo! ID will always be there */
-	if (!purple_markup_extract_info_field(stripped, stripped_len, user_info,
-			strings->yahoo_id_string, (yd->jp ? 2 : 10), "\n", 0,
-			NULL, _("Yahoo! ID"), 0, NULL, NULL))
-		;
-#endif
-
-#if PHOTO_SUPPORT
-	/* Try to put the photo in there too, if there's one and is readable */
-	if (url_text && len != 0) {
-		if (strstr(url_text, "400 Bad Request")
-				|| strstr(url_text, "403 Forbidden")
-				|| strstr(url_text, "404 Not Found")) {
-
-			purple_debug_info("yahoo", "Error getting %s: %s\n",
-					photo_url_text, url_text);
-		} else {
-			purple_debug_info("yahoo", "%s is %" G_GSIZE_FORMAT
-					" bytes\n", photo_url_text, len);
-			id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL);
-
-			tmp = g_strdup_printf("<img id=\"%d\"><br>", id);
-			purple_notify_user_info_add_pair(user_info, NULL, tmp);
-			g_free(tmp);
-		}
-	}
-#endif /* PHOTO_SUPPORT */
-
-	/* extract their Email address and put it in */
-	found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-			strings->my_email_string, (yd->jp ? 4 : 1), " ", 0,
-			strings->private_string, _("Email"), 0, NULL, NULL);
-
-	/* extract the Nickname if it exists */
-	found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-			"Nickname:", 1, "\n", '\n',
-			NULL, _("Nickname"), 0, NULL, NULL);
-
-	/* extract their RealName and put it in */
-	found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-			strings->realname_string, (yd->jp ? 3 : 1), "\n", '\n',
-			NULL, _("Real Name"), 0, NULL, NULL);
-
-	/* extract their Location and put it in */
-	found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-			strings->location_string, (yd->jp ? 4 : 2), "\n", '\n',
-			NULL, _("Location"), 0, NULL, NULL);
-
-	/* extract their Age and put it in */
-	found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-			strings->age_string, (yd->jp ? 2 : 3), "\n", '\n',
-			NULL, _("Age"), 0, NULL, NULL);
-
-	/* extract their MaritalStatus and put it in */
-	found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-			strings->maritalstatus_string, (yd->jp ? 2 : 3), "\n", '\n',
-			strings->no_answer_string, _("Marital Status"), 0, NULL, NULL);
-
-	/* extract their Gender and put it in */
-	found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-			strings->gender_string, (yd->jp ? 2 : 3), "\n", '\n',
-			strings->no_answer_string, _("Gender"), 0, NULL, NULL);
-
-	/* extract their Occupation and put it in */
-	found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-			strings->occupation_string, 2, "\n", '\n',
-			NULL, _("Occupation"), 0, NULL, NULL);
-
-	/* Hobbies, Latest News, and Favorite Quote are a bit different, since
-	 * the values can contain embedded newlines... but any or all of them
-	 * can also not appear.  The way we delimit them is to successively
-	 * look for the next one that _could_ appear, and if all else fails,
-	 * we end the section by looking for the 'Links' heading, which is the
-	 * next thing to follow this bunch.  (For Yahoo Japan, we check for
-	 * the "Description" ("Self PR") heading instead of "Links".)
-	 */
-
-	if (!purple_markup_extract_info_field(stripped, stripped_len, user_info,
-			strings->hobbies_string, (yd->jp ? 3 : 1), strings->latest_news_string,
-			'\n', "\n", _("Hobbies"), 0, NULL, NULL))
-	{
-		if (!purple_markup_extract_info_field(stripped, stripped_len, user_info,
-				strings->hobbies_string, 1, strings->favorite_quote_string,
-				'\n', "\n", _("Hobbies"), 0, NULL, NULL))
-		{
-			found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-					strings->hobbies_string, 1, strings->links_string,
-					'\n', "\n", _("Hobbies"), 0, NULL, NULL);
-		}
-		else
-			found = TRUE;
-	}
-	else
-		found = TRUE;
-
-	if (!purple_markup_extract_info_field(stripped, stripped_len, user_info,
-			strings->latest_news_string, 1, strings->favorite_quote_string,
-			'\n', "\n", _("Latest News"), 0, NULL, NULL))
-	{
-		found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-				strings->latest_news_string, (yd->jp ? 2 : 1), strings->links_string,
-				'\n', "\n", _("Latest News"), 0, NULL, NULL);
-	}
-	else
-		found = TRUE;
-
-	found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-			strings->favorite_quote_string, 1, strings->links_string,
-			'\n', "\n", _("Favorite Quote"), 0, NULL, NULL);
-
-	/* Home Page will either be "No home page specified",
-	 * or "Home Page: " and a link.
-	 * For Yahoo! Japan, if there is no home page specified,
-	 * neither "No home page specified" nor "Home Page:" is shown.
-	 */
-	if (strings->home_page_string) {
-		p = !strings->no_home_page_specified_string? NULL:
-			strstr(stripped, strings->no_home_page_specified_string);
-		if(!p)
-		{
-			found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-					strings->home_page_string, 1, "\n", 0, NULL,
-					_("Home Page"), 1, NULL, NULL);
-		}
-	}
-
-	/* Cool Link {1,2,3} is also different.  If "No cool link specified"
-	 * exists, then we have none.  If we have one however, we'll need to
-	 * check and see if we have a second one.  If we have a second one,
-	 * we have to check to see if we have a third one.
-	 */
-	p = !strings->no_cool_link_specified_string? NULL:
-		strstr(stripped,strings->no_cool_link_specified_string);
-	if (!p)
-	{
-		if (purple_markup_extract_info_field(stripped, stripped_len, user_info,
-				strings->cool_link_1_string, 1, "\n", 0, NULL,
-				_("Cool Link 1"), 1, NULL, NULL))
-		{
-			found = TRUE;
-			if (purple_markup_extract_info_field(stripped, stripped_len, user_info,
-					strings->cool_link_2_string, 1, "\n", 0, NULL,
-					_("Cool Link 2"), 1, NULL, NULL))
-			{
-				purple_markup_extract_info_field(stripped, stripped_len, user_info,
-						strings->cool_link_3_string, 1, "\n", 0, NULL,
-						_("Cool Link 3"), 1, NULL, NULL);
-			}
-		}
-	}
-
-	if (last_updated_utf8_string != NULL) {
-		/* see if Member Since is there, and if so, extract it. */
-		found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-				"Member Since:", 1, last_updated_utf8_string,
-				'\n', NULL, _("Member Since"), 0, NULL, yahoo_info_date_reformat);
-
-		/* extract the Last Updated date and put it in */
-		found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-				last_updated_utf8_string, (yd->jp ? 2 : 1), (yd->jp ? "\n" : " "), (yd->jp ? 0 : '\n'), NULL,
-				_("Last Update"), 0, NULL, (yd->jp ? NULL : yahoo_info_date_reformat));
-	}
-	} /* if (profile_state == PROFILE_STATE_DEFAULT) */
-
-	if(!found)
-	{
-		const gchar *str;
-
-		purple_notify_user_info_add_section_break(user_info);
-		purple_notify_user_info_add_pair(user_info,
-				_("Error retrieving profile"), NULL);
-
-		if (profile_state == PROFILE_STATE_UNKNOWN_LANGUAGE) {
-			str = _("This profile is in a language "
-					  "or format that is not supported at this time.");
-
-		} else if (profile_state == PROFILE_STATE_NOT_FOUND) {
-			PurpleBuddy *b = purple_find_buddy
-					(purple_connection_get_account(info_data->gc),
-							info_data->name);
-			YahooFriend *f = NULL;
-			if (b) {
-				/* Someone on the buddy list can be "not on server list",
-				 * in which case the user may or may not actually exist.
-				 * Hence this extra step.
-				 */
-				PurpleAccount *account = purple_buddy_get_account(b);
-				f = yahoo_friend_find(purple_account_get_connection(account),
-						purple_buddy_get_name(b));
-			}
-			str = f ? _("Could not retrieve the user's profile. "
-					  "This most likely is a temporary server-side problem. "
-					  "Please try again later.") :
-					_("Could not retrieve the user's profile. "
-					  "This most likely means that the user does not exist; "
-					  "however, Yahoo! sometimes does fail to find a user's "
-					  "profile. If you know that the user exists, "
-					  "please try again later.");
-		} else {
-			str = _("The user's profile is empty.");
-		}
-
-		purple_notify_user_info_add_pair(user_info, NULL, str);
-	}
-
-	/* put a link to the actual profile URL */
-	purple_notify_user_info_add_section_break(user_info);
-	tmp = g_strdup_printf("<a href=\"%s\">%s</a>",
-			profile_url_text, _("View web profile"));
-	purple_notify_user_info_add_pair(user_info, NULL, tmp);
-	g_free(tmp);
-
-	g_free(stripped);
-
-	/* show it to the user */
-	purple_notify_userinfo(info_data->gc, info_data->name,
-						  user_info, NULL, NULL);
-	purple_notify_user_info_destroy(user_info);
-
-	g_free(last_updated_utf8_string);
-	g_free(url_buffer);
-	g_free(fudged_buffer);
-	g_free(profile_url_text);
-	g_free(info_data->name);
-	g_free(info_data);
-
-#if PHOTO_SUPPORT
-	g_free(photo_url_text);
-	g_free(info2_data);
-	if (id != -1)
-		purple_imgstore_unref_by_id(id);
-#endif /* PHOTO_SUPPORT */
-}
-
-void yahoo_get_info(PurpleConnection *gc, const char *name)
-{
-	YahooData *yd = gc->proto_data;
-	YahooGetInfoData *data;
-	char *url;
-	PurpleUtilFetchUrlData *url_data;
-
-	data       = g_new0(YahooGetInfoData, 1);
-	data->gc   = gc;
-	data->name = g_strdup(name);
-
-	url = g_strdup_printf("%s%s",
-			(yd->jp ? YAHOOJP_PROFILE_URL : YAHOO_PROFILE_URL), name);
-
-	url_data = purple_util_fetch_url(url, TRUE, NULL, FALSE, yahoo_got_info, data);
-	if (url_data != NULL)
-		yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
-
-	g_free(url);
-}
--- a/libpurple/protocols/yahoo/yahoochat.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1684 +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.
- *
- * Some code copyright 2003 Tim Ringenbach <omarvo@hotmail.com>
- * (marv on irc.freenode.net)
- * Some code borrowed from libyahoo2, copyright (C) 2002, Philip
- * S Tellis <philip . tellis AT gmx . 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
- *
- */
-
-#include "internal.h"
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#include "debug.h"
-#include "privacy.h"
-#include "prpl.h"
-
-#include "conversation.h"
-#include "notify.h"
-#include "util.h"
-
-#include "libymsg.h"
-#include "yahoo_packet.h"
-#include "yahoochat.h"
-#include "ycht.h"
-
-#define YAHOO_CHAT_ID (1)
-
-/* prototype(s) */
-static void yahoo_chat_leave(PurpleConnection *gc, const char *room, const char *dn, gboolean logout);
-
-/* special function to log us on to the yahoo chat service */
-static void yahoo_chat_online(PurpleConnection *gc)
-{
-	YahooData *yd = gc->proto_data;
-	struct yahoo_packet *pkt;
-	const char *rll;
-
-	if (yd->wm) {
-		ycht_connection_open(gc);
-		return;
-	}
-
-	rll = purple_account_get_string(purple_connection_get_account(gc),
-								  "room_list_locale", YAHOO_ROOMLIST_LOCALE);
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CHATONLINE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash(pkt, "sssss",
-					  109, purple_connection_get_display_name(gc),
-					  1, purple_connection_get_display_name(gc),
-					  6, "abcde",
-					/* I'm not sure this is the correct way to set this. */
-					  98, rll,
-					  135, yd->jp ? YAHOO_CLIENT_VERSION : YAHOOJP_CLIENT_VERSION);
-	yahoo_packet_send_and_free(pkt, yd);
-}
-
-/* this is slow, and different from the purple_* version in that it (hopefully) won't add a user twice */
-void yahoo_chat_add_users(PurpleConvChat *chat, GList *newusers)
-{
-	GList *i;
-
-	for (i = newusers; i; i = i->next) {
-		if (purple_conv_chat_find_user(chat, i->data))
-			continue;
-		purple_conv_chat_add_user(chat, i->data, NULL, PURPLE_CBFLAGS_NONE, TRUE);
-	}
-}
-
-void yahoo_chat_add_user(PurpleConvChat *chat, const char *user, const char *reason)
-{
-	if (purple_conv_chat_find_user(chat, user))
-		return;
-
-	purple_conv_chat_add_user(chat, user, reason, PURPLE_CBFLAGS_NONE, TRUE);
-}
-
-static PurpleConversation *yahoo_find_conference(PurpleConnection *gc, const char *name)
-{
-	YahooData *yd;
-	GSList *l;
-
-	yd = gc->proto_data;
-
-	for (l = yd->confs; l; l = l->next) {
-		PurpleConversation *c = l->data;
-		if (!purple_utf8_strcasecmp(purple_conversation_get_name(c), name))
-			return c;
-	}
-	return NULL;
-}
-
-
-void yahoo_process_conference_invite(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	PurpleAccount *account;
-	GSList *l;
-	char *room = NULL;
-	char *who = NULL;
-	char *msg = NULL;
-	GString *members = NULL;
-	GHashTable *components;
-
-	if ( (pkt->status == 2) || (pkt->status == 11) )
-		return; /* Status is 11 when we are being notified about invitation being sent to someone else */
-
-	account = purple_connection_get_account(gc);
-
-	for (l = pkt->hash; l; l = l->next) {
-		struct yahoo_pair *pair = l->data;
-		if (pair->key == 57)
-		{
-			room = yahoo_string_decode(gc, pair->value, FALSE);
-			if (yahoo_find_conference(gc, room) != NULL)
-			{
-				/* Looks like we got invited to an already open conference. */
-				/* Laters: Should we accept this conference rather than ignoring the invitation ? */
-				purple_debug_info("yahoo","Ignoring invitation for an already existing chat, room:%s\n",room);
-				g_free(room);
-				return;
-			}
-		}
-	}
-
-	members = g_string_sized_new(512);
-
-	for (l = pkt->hash; l; l = l->next) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 1: /* us, but we already know who we are */
-			break;
-		case 57:
-			g_free(room);
-			room = yahoo_string_decode(gc, pair->value, FALSE);
-			break;
-		case 50: /* inviter */
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				who = pair->value;
-				g_string_append_printf(members, "%s\n", who);
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_conference_invite "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 51: /* This user is being invited to the conference. Comes with status = 11, so we wont reach here */
-			break;
-		case 52: /* Invited users. Assuming us invited, since we got this packet */
-			break; /* break needed, or else we add the users to the conference before they accept the invitation */
-		case 53: /* members who have already joined the conference */
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				g_string_append_printf(members, "%s\n", pair->value);
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_conference_invite "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 58:
-			g_free(msg);
-			msg = yahoo_string_decode(gc, pair->value, FALSE);
-			break;
-		case 13: /* ? */
-			break;
-		}
-	}
-
-	if (!room) {
-		g_string_free(members, TRUE);
-		g_free(msg);
-		return;
-	}
-
-	if (!purple_privacy_check(account, who) ||
-			(purple_account_get_bool(account, "ignore_invites", FALSE)))
-	{
-		purple_debug_info("yahoo",
-		    "Invite to conference %s from %s has been dropped.\n", room, who);
-		g_free(room);
-		g_free(msg);
-		g_string_free(members, TRUE);
-		return;
-	}
-
-	components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-	g_hash_table_replace(components, g_strdup("room"), room);
-	if (msg)
-		g_hash_table_replace(components, g_strdup("topic"), msg);
-	g_hash_table_replace(components, g_strdup("type"), g_strdup("Conference"));
-	g_hash_table_replace(components, g_strdup("members"), g_string_free(members, FALSE));
-	serv_got_chat_invite(gc, room, who, msg, components);
-
-}
-
-void yahoo_process_conference_decline(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	GSList *l;
-	char *room = NULL;
-	char *who = NULL;
-	char *msg = NULL;
-	PurpleConversation *c = NULL;
-	int utf8 = 0;
-
-	for (l = pkt->hash; l; l = l->next) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 57:
-			g_free(room);
-			room = yahoo_string_decode(gc, pair->value, FALSE);
-			break;
-		case 54:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				who = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_conference_decline "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 14:
-			g_free(msg);
-			msg = yahoo_string_decode(gc, pair->value, FALSE);
-			break;
-		case 97:
-			utf8 = strtol(pair->value, NULL, 10);
-			break;
-		}
-	}
-	if (!purple_privacy_check(purple_connection_get_account(gc), who))
-	{
-		g_free(room);
-		g_free(msg);
-		return;
-	}
-
-	if (who && room) {
-		/* make sure we're in the room before we process a decline message for it */
-		if((c = yahoo_find_conference(gc, room))) {
-			char *tmp = NULL, *msg_tmp = NULL;
-			if(msg)
-			{
-				msg_tmp = yahoo_string_decode(gc, msg, utf8);
-				msg = yahoo_codes_to_html(msg_tmp);
-				serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(c)), who, 0, msg, time(NULL));
-				g_free(msg_tmp);
-				g_free(msg);
-			}
-
-			tmp = g_strdup_printf(_("%s has declined to join."), who);
-			purple_conversation_write(c, NULL, tmp, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, time(NULL));
-
-			g_free(tmp);
-		}
-
-		g_free(room);
-	}
-}
-
-void yahoo_process_conference_logon(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	GSList *l;
-	char *room = NULL;
-	char *who = NULL;
-	PurpleConversation *c;
-
-	for (l = pkt->hash; l; l = l->next) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 57:
-			g_free(room);
-			room = yahoo_string_decode(gc, pair->value, FALSE);
-			break;
-		case 53:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				who = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_conference_logon "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		}
-	}
-
-	if (who && room) {
-		c = yahoo_find_conference(gc, room);
-		if (c)
-		{	/* Prevent duplicate users in the chat */
-			if( !purple_conv_chat_find_user(PURPLE_CONV_CHAT(c), who) )
-				yahoo_chat_add_user(PURPLE_CONV_CHAT(c), who, NULL);
-		}
-		g_free(room);
-	}
-}
-
-void yahoo_process_conference_logoff(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	GSList *l;
-	char *room = NULL;
-	char *who = NULL;
-	PurpleConversation *c;
-
-	for (l = pkt->hash; l; l = l->next) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 57:
-			g_free(room);
-			room = yahoo_string_decode(gc, pair->value, FALSE);
-			break;
-		case 56:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				who = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_conference_logoff "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		}
-	}
-
-	if (who && room) {
-		c = yahoo_find_conference(gc, room);
-		if (c)
-			purple_conv_chat_remove_user(PURPLE_CONV_CHAT(c), who, NULL);
-		g_free(room);
-	}
-}
-
-void yahoo_process_conference_message(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	GSList *l;
-	char *room = NULL;
-	char *who = NULL;
-	char *msg = NULL;
-	int utf8 = 0;
-	PurpleConversation *c;
-
-	for (l = pkt->hash; l; l = l->next) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 57:
-			g_free(room);
-			room = yahoo_string_decode(gc, pair->value, FALSE);
-			break;
-		case 3:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				who = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_conference_message "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 14:
-			msg = pair->value;
-			break;
-		case 97:
-			utf8 = strtol(pair->value, NULL, 10);
-			break;
-		}
-	}
-
-	if (room && who && msg) {
-		char *msg2;
-
-		c = yahoo_find_conference(gc, room);
-		if (!c) {
-			g_free(room);
-			return;
-		}
-
-		msg2 = yahoo_string_decode(gc, msg, utf8);
-		msg = yahoo_codes_to_html(msg2);
-		serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(c)), who, 0, msg, time(NULL));
-		g_free(msg);
-		g_free(msg2);
-	}
-
-	g_free(room);
-}
-
-static void yahoo_chat_join(PurpleConnection *gc, const char *dn, const char *room, const char *topic, const char *id)
-{
-	YahooData *yd = gc->proto_data;
-	struct yahoo_packet *pkt;
-	char *room2;
-	gboolean utf8 = TRUE;
-
-	if (yd->wm) {
-		g_return_if_fail(yd->ycht != NULL);
-		ycht_chat_join(yd->ycht, room);
-		return;
-	}
-
-	/* apparently room names are always utf8, or else always not utf8,
-	 * so we don't have to actually pass the flag in the packet. Or something. */
-	room2 = yahoo_string_encode(gc, room, &utf8);
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CHATJOIN, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash(pkt, "ssss",
-						1, purple_connection_get_display_name(gc),
-						104, room2,
-						62, "2",
-						129, id ? id : "0");
-	yahoo_packet_send_and_free(pkt, yd);
-	g_free(room2);
-}
-
-/* this is a confirmation of yahoo_chat_online(); */
-void yahoo_process_chat_online(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	YahooData *yd = (YahooData *) gc->proto_data;
-
-	if (pkt->status == 1) {
-		yd->chat_online = TRUE;
-
-		/* We need to goto a user in chat */
-		if (yd->pending_chat_goto) {
-			struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_CHATGOTO, YAHOO_STATUS_AVAILABLE, yd->session_id);
-			yahoo_packet_hash(pkt, "sss",
-				109, yd->pending_chat_goto,
-				1, purple_connection_get_display_name(gc),
-				62, "2");
-			yahoo_packet_send_and_free(pkt, yd);
-		} else if (yd->pending_chat_room) {
-			yahoo_chat_join(gc, purple_connection_get_display_name(gc), yd->pending_chat_room,
-				yd->pending_chat_topic, yd->pending_chat_id);
-		}
-
-		g_free(yd->pending_chat_room);
-		yd->pending_chat_room = NULL;
-		g_free(yd->pending_chat_id);
-		yd->pending_chat_id = NULL;
-		g_free(yd->pending_chat_topic);
-		yd->pending_chat_topic = NULL;
-		g_free(yd->pending_chat_goto);
-		yd->pending_chat_goto = NULL;
-	}
-}
-
-/* this is basicly the opposite of chat_online */
-void yahoo_process_chat_logout(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	YahooData *yd = (YahooData *) gc->proto_data;
-	GSList *l;
-
-	for (l = pkt->hash; l; l = l->next) {
-		struct yahoo_pair *pair = l->data;
-
-		if (pair->key == 1)
-			if (g_ascii_strcasecmp(pair->value,
-					purple_connection_get_display_name(gc)))
-				return;
-	}
-
-	if (pkt->status == 1) {
-		yd->chat_online = FALSE;
-		g_free(yd->pending_chat_room);
-		yd->pending_chat_room = NULL;
-		g_free(yd->pending_chat_id);
-		yd->pending_chat_id = NULL;
-		g_free(yd->pending_chat_topic);
-		yd->pending_chat_topic = NULL;
-		g_free(yd->pending_chat_goto);
-		yd->pending_chat_goto = NULL;
-		if (yd->in_chat)
-			yahoo_c_leave(gc, YAHOO_CHAT_ID);
-	}
-}
-
-void yahoo_process_chat_join(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	PurpleAccount *account = purple_connection_get_account(gc);
-	YahooData *yd = (YahooData *) gc->proto_data;
-	PurpleConversation *c = NULL;
-	GSList *l;
-	GList *members = NULL;
-	GList *roomies = NULL;
-	char *room = NULL;
-	char *topic = NULL;
-
-	if (pkt->status == -1) {
-		/* We can't join */
-		struct yahoo_pair *pair = pkt->hash->data;
-		gchar const *failed_to_join = _("Failed to join chat");
-		switch (atoi(pair->value)) {
-			case 0xFFFFFFFA: /* -6 */
-				purple_notify_error(gc, NULL, failed_to_join, _("Unknown room"));
-				break;
-			case 0xFFFFFFF1: /* -15 */
-				purple_notify_error(gc, NULL, failed_to_join, _("Maybe the room is full"));
-				break;
-			case 0xFFFFFFDD: /* -35 */
-				purple_notify_error(gc, NULL, failed_to_join, _("Not available"));
-				break;
-			default:
-				purple_notify_error(gc, NULL, failed_to_join,
-						_("Unknown error. You may need to logout and wait five minutes before being able to rejoin a chatroom"));
-		}
-		return;
-	}
-
-	for (l = pkt->hash; l; l = l->next) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-
-		case 104:
-			g_free(room);
-			room = yahoo_string_decode(gc, pair->value, TRUE);
-			break;
-		case 105:
-			g_free(topic);
-			topic = yahoo_string_decode(gc, pair->value, TRUE);
-			break;
-		case 128: /* some id */
-			break;
-		case 108: /* number of joiners */
-			break;
-		case 129: /* some other id */
-			break;
-		case 130: /* some base64 or hash or something */
-			break;
-		case 126: /* some negative number */
-			break;
-		case 13: /* this is 1. maybe its the type of room? (normal, user created, private, etc?) */
-			break;
-		case 61: /*this looks similar to 130 */
-			break;
-
-		/* the previous section was just room info. this next section is
-		   info about individual room members, (including us) */
-
-		case 109: /* the yahoo id */
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				members = g_list_append(members, pair->value);
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_chat_join "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 110: /* age */
-			break;
-		case 141: /* nickname */
-			break;
-		case 142: /* location */
-			break;
-		case 113: /* bitmask */
-			break;
-		}
-	}
-
-	if (room && yd->chat_name && purple_utf8_strcasecmp(room, yd->chat_name))
-		yahoo_chat_leave(gc, room,
-				purple_connection_get_display_name(gc), FALSE);
-
-	c = purple_find_chat(gc, YAHOO_CHAT_ID);
-
-	if (room && (!c || purple_conv_chat_has_left(PURPLE_CONV_CHAT(c))) &&
-	    members && (members->next ||
-	     !g_ascii_strcasecmp(members->data, purple_connection_get_display_name(gc)))) {
-		GList *l;
-		GList *flags = NULL;
-		for (l = members; l; l = l->next)
-			flags = g_list_prepend(flags, GINT_TO_POINTER(PURPLE_CBFLAGS_NONE));
-		if (c && purple_conv_chat_has_left(PURPLE_CONV_CHAT(c))) {
-			/* this might be a hack, but oh well, it should nicely */
-			char *tmpmsg;
-
-			purple_conversation_set_name(c, room);
-
-			c = serv_got_joined_chat(gc, YAHOO_CHAT_ID, room);
-			if (topic) {
-				purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic);
-				/* Also print the topic to the backlog so that the captcha link is clickable */
-				purple_conv_chat_write(PURPLE_CONV_CHAT(c), "", topic, PURPLE_MESSAGE_SYSTEM, time(NULL));
-			}
-			yd->in_chat = 1;
-			yd->chat_name = g_strdup(room);
-			purple_conv_chat_add_users(PURPLE_CONV_CHAT(c), members, NULL, flags, FALSE);
-
-			tmpmsg = g_strdup_printf(_("You are now chatting in %s."), room);
-			purple_conv_chat_write(PURPLE_CONV_CHAT(c), "", tmpmsg, PURPLE_MESSAGE_SYSTEM, time(NULL));
-			g_free(tmpmsg);
-		} else {
-			c = serv_got_joined_chat(gc, YAHOO_CHAT_ID, room);
-			if (topic) {
-				purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic);
-				/* Also print the topic to the backlog so that the captcha link is clickable */
-				purple_conv_chat_write(PURPLE_CONV_CHAT(c), "", topic, PURPLE_MESSAGE_SYSTEM, time(NULL));
-			}
-			yd->in_chat = 1;
-			yd->chat_name = g_strdup(room);
-			purple_conv_chat_add_users(PURPLE_CONV_CHAT(c), members, NULL, flags, FALSE);
-		}
-		g_list_free(flags);
-	} else if (c) {
-		if (topic) {
-			const char *cur_topic = purple_conv_chat_get_topic(PURPLE_CONV_CHAT(c));
-			if (cur_topic == NULL || strcmp(cur_topic, topic) != 0)
-				purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic);
-		}
-		yahoo_chat_add_users(PURPLE_CONV_CHAT(c), members);
-	}
-
-	if (account->deny && c) {
-		PurpleConversationUiOps *ops = purple_conversation_get_ui_ops(c);
-		for (l = account->deny; l != NULL; l = l->next) {
-			for (roomies = members; roomies; roomies = roomies->next) {
-				if (!purple_utf8_strcasecmp((char *)l->data, roomies->data)) {
-					purple_debug_info("yahoo", "Ignoring room member %s in room %s\n" , (char *)roomies->data, room ? room : "");
-					purple_conv_chat_ignore(PURPLE_CONV_CHAT(c),roomies->data);
-					ops->chat_update_user(c, roomies->data);
-				}
-			}
-		}
-	}
-	g_list_free(roomies);
-	g_list_free(members);
-	g_free(room);
-	g_free(topic);
-}
-
-void yahoo_process_chat_exit(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	char *who = NULL;
-	char *room = NULL;
-	GSList *l;
-
-	for (l = pkt->hash; l; l = l->next) {
-		struct yahoo_pair *pair = l->data;
-
-		if (pair->key == 104) {
-			g_free(room);
-			room = yahoo_string_decode(gc, pair->value, TRUE);
-		}
-		if (pair->key == 109) {
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				who = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_chat_exit "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-		}
-	}
-
-	if (who && room) {
-		PurpleConversation *c = purple_find_chat(gc, YAHOO_CHAT_ID);
-		if (c && !purple_utf8_strcasecmp(purple_conversation_get_name(c), room))
-			purple_conv_chat_remove_user(PURPLE_CONV_CHAT(c), who, NULL);
-
-	}
-	g_free(room);
-}
-
-void yahoo_process_chat_message(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	char *room = NULL, *who = NULL, *msg = NULL, *msg2;
-	int msgtype = 1, utf8 = 1; /* default to utf8 */
-	PurpleConversation *c = NULL;
-	GSList *l;
-
-	for (l = pkt->hash; l; l = l->next) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-
-		case 97:
-			utf8 = strtol(pair->value, NULL, 10);
-			break;
-		case 104:
-			g_free(room);
-			room = yahoo_string_decode(gc, pair->value, TRUE);
-			break;
-		case 109:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				who = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_chat_message "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 117:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				msg = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_chat_message "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 124:
-			msgtype = strtol(pair->value, NULL, 10);
-			break;
-		}
-	}
-
-	c = purple_find_chat(gc, YAHOO_CHAT_ID);
-	if (!who || !c) {
-		if (room)
-			g_free(room);
-		/* we still get messages after we part, funny that */
-		return;
-	}
-
-	if (!msg) {
-		purple_debug_misc("yahoo", "Got a message packet with no message.\nThis probably means something important, but we're ignoring it.\n");
-		return;
-	}
-	msg2 = yahoo_string_decode(gc, msg, utf8);
-	msg = yahoo_codes_to_html(msg2);
-	g_free(msg2);
-
-	if (msgtype == 2 || msgtype == 3) {
-		char *tmp;
-		tmp = g_strdup_printf("/me %s", msg);
-		g_free(msg);
-		msg = tmp;
-	}
-
-	serv_got_chat_in(gc, YAHOO_CHAT_ID, who, 0, msg, time(NULL));
-	g_free(msg);
-	g_free(room);
-}
-
-void yahoo_process_chat_addinvite(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	PurpleAccount *account;
-	GSList *l;
-	char *room = NULL;
-	char *msg = NULL;
-	char *who = NULL;
-
-	account = purple_connection_get_account(gc);
-
-	for (l = pkt->hash; l; l = l->next) {
-		struct yahoo_pair *pair = l->data;
-
-		switch (pair->key) {
-		case 104:
-			g_free(room);
-			room = yahoo_string_decode(gc, pair->value, TRUE);
-			break;
-		case 129: /* room id? */
-			break;
-		case 126: /* ??? */
-			break;
-		case 117:
-			g_free(msg);
-			msg = yahoo_string_decode(gc, pair->value, FALSE);
-			break;
-		case 119:
-			if (g_utf8_validate(pair->value, -1, NULL)) {
-				who = pair->value;
-			} else {
-				purple_debug_warning("yahoo", "yahoo_process_chat_addinvite "
-						"got non-UTF-8 string for key %d\n", pair->key);
-			}
-			break;
-		case 118: /* us */
-			break;
-		}
-	}
-
-	if (room && who) {
-		GHashTable *components;
-
-		if (!purple_privacy_check(account, who) ||
-				(purple_account_get_bool(account, "ignore_invites", FALSE)))
-		{
-			purple_debug_info("yahoo", "Invite to room %s from %s has been dropped.\n", room, who);
-			g_free(room);
-			g_free(msg);
-			return;
-		}
-
-		components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-		g_hash_table_replace(components, g_strdup("room"), g_strdup(room));
-		serv_got_chat_invite(gc, room, who, msg, components);
-	}
-
-	g_free(room);
-	g_free(msg);
-}
-
-void yahoo_process_chat_goto(PurpleConnection *gc, struct yahoo_packet *pkt)
-{
-	if (pkt->status == -1)
-		purple_notify_error(gc, NULL, _("Failed to join buddy in chat"),
-						_("Maybe they're not in a chat?"));
-}
-
-/*
- * Functions dealing with conferences
- * I think conference names are always ascii.
- */
-
-void yahoo_conf_leave(YahooData *yd, const char *room, const char *dn, GList *who)
-{
-	struct yahoo_packet *pkt;
-	GList *w;
-
-	purple_debug_misc("yahoo", "leaving conference %s\n", room);
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGOFF, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	yahoo_packet_hash_str(pkt, 1, dn);
-	for (w = who; w; w = w->next) {
-		const char *name = purple_conv_chat_cb_get_name(w->data);
-		yahoo_packet_hash_str(pkt, 3, name);
-	}
-
-	yahoo_packet_hash_str(pkt, 57, room);
-	yahoo_packet_send_and_free(pkt, yd);
-}
-
-static int yahoo_conf_send(PurpleConnection *gc, const char *dn, const char *room,
-							GList *members, const char *what)
-{
-	YahooData *yd = gc->proto_data;
-	struct yahoo_packet *pkt;
-	GList *who;
-	char *msg, *msg2;
-	int utf8 = 1;
-
-	msg = yahoo_html_to_codes(what);
-	msg2 = yahoo_string_encode(gc, msg, &utf8);
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CONFMSG, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	yahoo_packet_hash_str(pkt, 1, dn);
-	for (who = members; who; who = who->next) {
-		const char *name = purple_conv_chat_cb_get_name(who->data);
-		yahoo_packet_hash_str(pkt, 53, name);
-	}
-	yahoo_packet_hash(pkt, "ss", 57, room, 14, msg2);
-	if (utf8)
-		yahoo_packet_hash_str(pkt, 97, "1"); /* utf-8 */
-
-	yahoo_packet_send_and_free(pkt, yd);
-	g_free(msg);
-	g_free(msg2);
-
-	return 0;
-}
-
-static void yahoo_conf_join(YahooData *yd, PurpleConversation *c, const char *dn, const char *room,
-						const char *topic, const char *members)
-{
-	struct yahoo_packet *pkt;
-	char **memarr = NULL;
-	int i;
-
-	if (members)
-		memarr = g_strsplit(members, "\n", 0);
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGON, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	yahoo_packet_hash(pkt, "sss", 1, dn, 3, dn, 57, room);
-	if (memarr) {
-		for(i = 0 ; memarr[i]; i++) {
-			if (!strcmp(memarr[i], "") || !strcmp(memarr[i], dn))
-					continue;
-			yahoo_packet_hash_str(pkt, 3, memarr[i]);
-			purple_conv_chat_add_user(PURPLE_CONV_CHAT(c), memarr[i], NULL, PURPLE_CBFLAGS_NONE, TRUE);
-		}
-	}
-	yahoo_packet_send_and_free(pkt, yd);
-
-	if (memarr)
-		g_strfreev(memarr);
-}
-
-static void yahoo_conf_invite(PurpleConnection *gc, PurpleConversation *c,
-		const char *dn, const char *buddy, const char *room, const char *msg)
-{
-	YahooData *yd = gc->proto_data;
-	struct yahoo_packet *pkt;
-	GList *members;
-	char *msg2 = NULL;
-
-	if (msg)
-		msg2 = yahoo_string_encode(gc, msg, NULL);
-
-	members = purple_conv_chat_get_users(PURPLE_CONV_CHAT(c));
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CONFADDINVITE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	yahoo_packet_hash(pkt, "sssss", 1, dn, 51, buddy, 57, room, 58, msg?msg2:"", 13, "0");
-	for(; members; members = members->next) {
-		const char *name = purple_conv_chat_cb_get_name(members->data);
-		if (!strcmp(name, dn))
-			continue;
-		yahoo_packet_hash(pkt, "ss", 52, name, 53, name);
-	}
-
-	yahoo_packet_send_and_free(pkt, yd);
-	g_free(msg2);
-}
-
-/*
- * Functions dealing with chats
- */
-
-static void yahoo_chat_leave(PurpleConnection *gc, const char *room, const char *dn, gboolean logout)
-{
-	YahooData *yd = gc->proto_data;
-	struct yahoo_packet *pkt;
-
-	char *eroom;
-	gboolean utf8 = 1;
-
-	if (yd->wm) {
-		g_return_if_fail(yd->ycht != NULL);
-
-		ycht_chat_leave(yd->ycht, room, logout);
-		return;
-	}
-
-	eroom = yahoo_string_encode(gc, room, &utf8);
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CHATEXIT, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash(pkt, "sss", 104, eroom, 109, dn, 108, "1");
-	yahoo_packet_hash_str(pkt, 112, "0"); /* what does this one mean? */
-	yahoo_packet_send_and_free(pkt, yd);
-
-	yd->in_chat = 0;
-	if (yd->chat_name) {
-		g_free(yd->chat_name);
-		yd->chat_name = NULL;
-	}
-
-	if (purple_find_chat(gc, YAHOO_CHAT_ID) != NULL)
-		serv_got_chat_left(gc, YAHOO_CHAT_ID);
-
-	if (!logout)
-		return;
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CHATLOGOUT,
-			YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash_str(pkt, 1, dn);
-	yahoo_packet_send_and_free(pkt, yd);
-
-	yd->chat_online = FALSE;
-	g_free(yd->pending_chat_room);
-	yd->pending_chat_room = NULL;
-	g_free(yd->pending_chat_id);
-	yd->pending_chat_id = NULL;
-	g_free(yd->pending_chat_topic);
-	yd->pending_chat_topic = NULL;
-	g_free(yd->pending_chat_goto);
-	yd->pending_chat_goto = NULL;
-	g_free(eroom);
-}
-
-static int yahoo_chat_send(PurpleConnection *gc, const char *dn, const char *room, const char *what, PurpleMessageFlags flags)
-{
-	YahooData *yd = gc->proto_data;
-	struct yahoo_packet *pkt;
-	int me = 0;
-	char *msg1, *msg2, *room2;
-	gboolean utf8 = TRUE;
-
-	if (yd->wm) {
-		g_return_val_if_fail(yd->ycht != NULL, 1);
-
-		return ycht_chat_send(yd->ycht, room, what);
-	}
-
-	msg1 = g_strdup(what);
-
-	if (purple_message_meify(msg1, -1))
-		me = 1;
-
-	msg2 = yahoo_html_to_codes(msg1);
-	g_free(msg1);
-	msg1 = yahoo_string_encode(gc, msg2, &utf8);
-	g_free(msg2);
-	room2 = yahoo_string_encode(gc, room, NULL);
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_COMMENT, YAHOO_STATUS_AVAILABLE, yd->session_id);
-
-	yahoo_packet_hash(pkt, "sss", 1, dn, 104, room2, 117, msg1);
-	if (me)
-		yahoo_packet_hash_str(pkt, 124, "2");
-	else
-		yahoo_packet_hash_str(pkt, 124, "1");
-	/* fixme: what about /think? (124=3) */
-	if (utf8)
-		yahoo_packet_hash_str(pkt, 97, "1");
-
-	yahoo_packet_send_and_free(pkt, yd);
-	g_free(msg1);
-	g_free(room2);
-
-	return 0;
-}
-
-
-static void yahoo_chat_invite(PurpleConnection *gc, const char *dn, const char *buddy,
-							const char *room, const char *msg)
-{
-	YahooData *yd = gc->proto_data;
-	struct yahoo_packet *pkt;
-	char *room2, *msg2 = NULL;
-	gboolean utf8 = TRUE;
-
-	if (yd->wm) {
-		g_return_if_fail(yd->ycht != NULL);
-		ycht_chat_send_invite(yd->ycht, room, buddy, msg);
-		return;
-	}
-
-	room2 = yahoo_string_encode(gc, room, &utf8);
-	if (msg)
-		msg2 = yahoo_string_encode(gc, msg, NULL);
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CHATADDINVITE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash(pkt, "sssss", 1, dn, 118, buddy, 104, room2, 117, (msg2?msg2:""), 129, "0");
-	yahoo_packet_send_and_free(pkt, yd);
-
-	g_free(room2);
-	g_free(msg2);
-}
-
-void yahoo_chat_goto(PurpleConnection *gc, const char *name)
-{
-	YahooData *yd;
-	struct yahoo_packet *pkt;
-
-	yd = gc->proto_data;
-
-	if (yd->wm) {
-		g_return_if_fail(yd->ycht != NULL);
-		ycht_chat_goto_user(yd->ycht, name);
-		return;
-	}
-
-	if (!yd->chat_online) {
-		yahoo_chat_online(gc);
-		g_free(yd->pending_chat_room);
-		yd->pending_chat_room = NULL;
-		g_free(yd->pending_chat_id);
-		yd->pending_chat_id = NULL;
-		g_free(yd->pending_chat_topic);
-		yd->pending_chat_topic = NULL;
-		g_free(yd->pending_chat_goto);
-		yd->pending_chat_goto = g_strdup(name);
-		return;
-	}
-
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CHATGOTO, YAHOO_STATUS_AVAILABLE, yd->session_id);
-	yahoo_packet_hash(pkt, "sss", 109, name, 1, purple_connection_get_display_name(gc), 62, "2");
-	yahoo_packet_send_and_free(pkt, yd);
-}
-/*
- * These are the functions registered with the core
- * which get called for both chats and conferences.
- */
-
-void yahoo_c_leave(PurpleConnection *gc, int id)
-{
-	YahooData *yd = (YahooData *) gc->proto_data;
-	PurpleConversation *c;
-
-	if (!yd)
-		return;
-
-	c = purple_find_chat(gc, id);
-	if (!c)
-		return;
-
-	if (id != YAHOO_CHAT_ID) {
-		yahoo_conf_leave(yd, purple_conversation_get_name(c),
-			purple_connection_get_display_name(gc), purple_conv_chat_get_users(PURPLE_CONV_CHAT(c)));
-			yd->confs = g_slist_remove(yd->confs, c);
-	} else {
-		yahoo_chat_leave(gc, purple_conversation_get_name(c), purple_connection_get_display_name(gc), TRUE);
-	}
-
-	serv_got_chat_left(gc, id);
-}
-
-int yahoo_c_send(PurpleConnection *gc, int id, const char *what, PurpleMessageFlags flags)
-{
-	PurpleConversation *c;
-	int ret;
-	YahooData *yd;
-
-	yd = (YahooData *) gc->proto_data;
-	if (!yd)
-		return -1;
-
-	c = purple_find_chat(gc, id);
-	if (!c)
-		return -1;
-
-	if (id != YAHOO_CHAT_ID) {
-		ret = yahoo_conf_send(gc, purple_connection_get_display_name(gc),
-				purple_conversation_get_name(c), purple_conv_chat_get_users(PURPLE_CONV_CHAT(c)), what);
-	} else {
-		ret = yahoo_chat_send(gc, purple_connection_get_display_name(gc),
-						purple_conversation_get_name(c), what, flags);
-		if (!ret)
-			serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(c)),
-					purple_connection_get_display_name(gc), flags, what, time(NULL));
-	}
-	return ret;
-}
-
-GList *yahoo_c_info(PurpleConnection *gc)
-{
-	GList *m = NULL;
-	struct proto_chat_entry *pce;
-
-	pce = g_new0(struct proto_chat_entry, 1);
-	pce->label = _("_Room:");
-	pce->identifier = "room";
-	pce->required = TRUE;
-	m = g_list_append(m, pce);
-
-	return m;
-}
-
-GHashTable *yahoo_c_info_defaults(PurpleConnection *gc, const char *chat_name)
-{
-	GHashTable *defaults;
-
-	defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
-
-	if (chat_name != NULL)
-		g_hash_table_insert(defaults, "room", g_strdup(chat_name));
-
-	return defaults;
-}
-
-char *yahoo_get_chat_name(GHashTable *data)
-{
-	return g_strdup(g_hash_table_lookup(data, "room"));
-}
-
-void yahoo_c_join(PurpleConnection *gc, GHashTable *data)
-{
-	YahooData *yd;
-	char *room, *topic, *type;
-	PurpleConversation *c;
-
-	yd = (YahooData *) gc->proto_data;
-	if (!yd)
-		return;
-
-	room = g_hash_table_lookup(data, "room");
-	if (!room)
-		return;
-
-	topic = g_hash_table_lookup(data, "topic");
-	if (!topic)
-		topic = "";
-
-	if ((type = g_hash_table_lookup(data, "type")) && !strcmp(type, "Conference")) {
-		int id;
-		const char *members = g_hash_table_lookup(data, "members");
-		id = yd->conf_id++;
-		c = serv_got_joined_chat(gc, id, room);
-		yd->confs = g_slist_prepend(yd->confs, c);
-		purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), purple_connection_get_display_name(gc), topic);
-		yahoo_conf_join(yd, c, purple_connection_get_display_name(gc), room, topic, members);
-		return;
-	} else {
-		const char *id;
-		/*if (yd->in_chat)
-			yahoo_chat_leave(gc, room,
-					purple_connection_get_display_name(gc),
-					FALSE);*/
-
-		id = g_hash_table_lookup(data, "id");
-
-		if (!yd->chat_online) {
-			yahoo_chat_online(gc);
-			g_free(yd->pending_chat_room);
-			yd->pending_chat_room = g_strdup(room);
-			g_free(yd->pending_chat_id);
-			yd->pending_chat_id = g_strdup(id);
-			g_free(yd->pending_chat_topic);
-			yd->pending_chat_topic = g_strdup(topic);
-			g_free(yd->pending_chat_goto);
-			yd->pending_chat_goto = NULL;
-		} else {
-			yahoo_chat_join(gc, purple_connection_get_display_name(gc), room, topic, id);
-		}
-		return;
-	}
-}
-
-void yahoo_c_invite(PurpleConnection *gc, int id, const char *msg, const char *name)
-{
-	PurpleConversation *c;
-
-	c = purple_find_chat(gc, id);
-	if (!c || !c->name)
-		return;
-
-	if (id != YAHOO_CHAT_ID) {
-		yahoo_conf_invite(gc, c, purple_connection_get_display_name(gc), name,
-							purple_conversation_get_name(c), msg);
-	} else {
-		yahoo_chat_invite(gc, purple_connection_get_display_name(gc), name,
-							purple_conversation_get_name(c), msg);
-	}
-}
-
-struct yahoo_roomlist {
-	int fd;
-	int inpa;
-	gchar *txbuf;
-	gsize tx_written;
-	guchar *rxqueue;
-	int rxlen;
-	gboolean started;
-	char *path;
-	char *host;
-	PurpleRoomlist *list;
-	PurpleRoomlistRoom *cat;
-	PurpleRoomlistRoom *ucat;
-	GMarkupParseContext *parse;
-};
-
-static void yahoo_roomlist_destroy(struct yahoo_roomlist *yrl)
-{
-	if (yrl->inpa)
-		purple_input_remove(yrl->inpa);
-	g_free(yrl->txbuf);
-	g_free(yrl->rxqueue);
-	g_free(yrl->path);
-	g_free(yrl->host);
-	if (yrl->parse)
-		g_markup_parse_context_free(yrl->parse);
-	g_free(yrl);
-}
-
-enum yahoo_room_type {
-	yrt_yahoo,
-	yrt_user
-};
-
-struct yahoo_chatxml_state {
-	PurpleRoomlist *list;
-	struct yahoo_roomlist *yrl;
-	GQueue *q;
-	struct {
-		enum yahoo_room_type type;
-		char *name;
-		char *topic;
-		char *id;
-		int users, voices, webcams;
-	} room;
-};
-
-struct yahoo_lobby {
-	int count, users, voices, webcams;
-};
-
-static struct yahoo_chatxml_state *yahoo_chatxml_state_new(PurpleRoomlist *list, struct yahoo_roomlist *yrl)
-{
-	struct yahoo_chatxml_state *s;
-
-	s = g_new0(struct yahoo_chatxml_state, 1);
-	s->list = list;
-	s->yrl = yrl;
-	s->q = g_queue_new();
-
-	return s;
-}
-
-static void yahoo_chatxml_state_destroy(struct yahoo_chatxml_state *s)
-{
-	g_queue_free(s->q);
-	g_free(s->room.name);
-	g_free(s->room.topic);
-	g_free(s->room.id);
-	g_free(s);
-}
-
-static void yahoo_chatlist_start_element(GMarkupParseContext *context,
-                                  const gchar *ename, const gchar **anames,
-                                  const gchar **avalues, gpointer user_data,
-                                  GError **error)
-{
-	struct yahoo_chatxml_state *s = user_data;
-	PurpleRoomlist *list = s->list;
-	PurpleRoomlistRoom *r;
-	PurpleRoomlistRoom *parent;
-	int i;
-
-	if (!strcmp(ename, "category")) {
-		const gchar *name = NULL, *id = NULL;
-
-		for (i = 0; anames[i]; i++) {
-			if (!strcmp(anames[i], "id"))
-				id = avalues[i];
-			if (!strcmp(anames[i], "name"))
-				name = avalues[i];
-		}
-		if (!name || !id)
-			return;
-
-		parent = g_queue_peek_head(s->q);
-		r = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_CATEGORY, name, parent);
-		purple_roomlist_room_add_field(list, r, (gpointer)name);
-		purple_roomlist_room_add_field(list, r, (gpointer)id);
-		purple_roomlist_room_add(list, r);
-		g_queue_push_head(s->q, r);
-	} else if (!strcmp(ename, "room")) {
-		s->room.users = s->room.voices = s->room.webcams = 0;
-
-		for (i = 0; anames[i]; i++) {
-			if (!strcmp(anames[i], "id")) {
-				g_free(s->room.id);
-				s->room.id = g_strdup(avalues[i]);
-			} else if (!strcmp(anames[i], "name")) {
-				g_free(s->room.name);
-				s->room.name = g_strdup(avalues[i]);
-			} else if (!strcmp(anames[i], "topic")) {
-				g_free(s->room.topic);
-				s->room.topic = g_strdup(avalues[i]);
-			} else if (!strcmp(anames[i], "type")) {
-				if (!strcmp("yahoo", avalues[i]))
-					s->room.type = yrt_yahoo;
-				else
-					s->room.type = yrt_user;
-			}
-		}
-
-	} else if (!strcmp(ename, "lobby")) {
-		struct yahoo_lobby *lob = g_new0(struct yahoo_lobby, 1);
-
-		for (i = 0; anames[i]; i++) {
-			if (!strcmp(anames[i], "count")) {
-				lob->count = strtol(avalues[i], NULL, 10);
-			} else if (!strcmp(anames[i], "users")) {
-				s->room.users += lob->users = strtol(avalues[i], NULL, 10);
-			} else if (!strcmp(anames[i], "voices")) {
-				s->room.voices += lob->voices = strtol(avalues[i], NULL, 10);
-			} else if (!strcmp(anames[i], "webcams")) {
-				s->room.webcams += lob->webcams = strtol(avalues[i], NULL, 10);
-			}
-		}
-		g_queue_push_head(s->q, lob);
-	}
-}
-
-static void yahoo_chatlist_end_element(GMarkupParseContext *context, const gchar *ename,
-                                       gpointer user_data, GError **error)
-{
-	struct yahoo_chatxml_state *s = user_data;
-
-	if (!strcmp(ename, "category")) {
-		g_queue_pop_head(s->q);
-	} else if (!strcmp(ename, "room")) {
-		struct yahoo_lobby *lob;
-		PurpleRoomlistRoom *r, *l;
-
-		if (s->room.type == yrt_yahoo)
-			r = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_CATEGORY|PURPLE_ROOMLIST_ROOMTYPE_ROOM,
-		                                   s->room.name, s->yrl->cat);
-		else
-			r = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_CATEGORY|PURPLE_ROOMLIST_ROOMTYPE_ROOM,
-		                                   s->room.name, s->yrl->ucat);
-
-		purple_roomlist_room_add_field(s->list, r, s->room.name);
-		purple_roomlist_room_add_field(s->list, r, s->room.id);
-		purple_roomlist_room_add_field(s->list, r, GINT_TO_POINTER(s->room.users));
-		purple_roomlist_room_add_field(s->list, r, GINT_TO_POINTER(s->room.voices));
-		purple_roomlist_room_add_field(s->list, r, GINT_TO_POINTER(s->room.webcams));
-		purple_roomlist_room_add_field(s->list, r, s->room.topic);
-		purple_roomlist_room_add(s->list, r);
-
-		while ((lob = g_queue_pop_head(s->q))) {
-			char *name = g_strdup_printf("%s:%d", s->room.name, lob->count);
-			l = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, name, r);
-
-			purple_roomlist_room_add_field(s->list, l, name);
-			purple_roomlist_room_add_field(s->list, l, s->room.id);
-			purple_roomlist_room_add_field(s->list, l, GINT_TO_POINTER(lob->users));
-			purple_roomlist_room_add_field(s->list, l, GINT_TO_POINTER(lob->voices));
-			purple_roomlist_room_add_field(s->list, l, GINT_TO_POINTER(lob->webcams));
-			purple_roomlist_room_add_field(s->list, l, s->room.topic);
-			purple_roomlist_room_add(s->list, l);
-
-			g_free(name);
-			g_free(lob);
-		}
-	}
-}
-
-static GMarkupParser parser = {
-	yahoo_chatlist_start_element,
-	yahoo_chatlist_end_element,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void yahoo_roomlist_cleanup(PurpleRoomlist *list, struct yahoo_roomlist *yrl)
-{
-	purple_roomlist_set_in_progress(list, FALSE);
-
-	if (yrl) {
-		list->proto_data = g_list_remove(list->proto_data, yrl);
-		yahoo_roomlist_destroy(yrl);
-	}
-
-	purple_roomlist_unref(list);
-}
-
-static void yahoo_roomlist_pending(gpointer data, gint source, PurpleInputCondition cond)
-{
-	struct yahoo_roomlist *yrl = data;
-	PurpleRoomlist *list = yrl->list;
-	char buf[1024];
-	int len;
-	guchar *start;
-	struct yahoo_chatxml_state *s;
-
-	len = read(yrl->fd, buf, sizeof(buf));
-
-	if (len < 0 && errno == EAGAIN)
-		return;
-
-	if (len <= 0) {
-		if (yrl->parse)
-			g_markup_parse_context_end_parse(yrl->parse, NULL);
-		yahoo_roomlist_cleanup(list, yrl);
-		return;
-	}
-
-	yrl->rxqueue = g_realloc(yrl->rxqueue, len + yrl->rxlen);
-	memcpy(yrl->rxqueue + yrl->rxlen, buf, len);
-	yrl->rxlen += len;
-
-	if (!yrl->started) {
-		yrl->started = TRUE;
-		start = (guchar *)g_strstr_len((char *)yrl->rxqueue, yrl->rxlen, "\r\n\r\n");
-		if (!start || (start - yrl->rxqueue + 4) >= yrl->rxlen)
-			return;
-		start += 4;
-	} else {
-		start = yrl->rxqueue;
-	}
-
-	if (yrl->parse == NULL) {
-		s = yahoo_chatxml_state_new(list, yrl);
-		yrl->parse = g_markup_parse_context_new(&parser, 0, s,
-		             (GDestroyNotify)yahoo_chatxml_state_destroy);
-	}
-
-	if (!g_markup_parse_context_parse(yrl->parse, (char *)start, (yrl->rxlen - (start - yrl->rxqueue)), NULL)) {
-
-		yahoo_roomlist_cleanup(list, yrl);
-		return;
-	}
-
-	yrl->rxlen = 0;
-}
-
-static void yahoo_roomlist_send_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
-	struct yahoo_roomlist *yrl;
-	PurpleRoomlist *list;
-	int written, remaining;
-
-	yrl = data;
-	list = yrl->list;
-
-	remaining = strlen(yrl->txbuf) - yrl->tx_written;
-	written = write(yrl->fd, yrl->txbuf + yrl->tx_written, remaining);
-
-	if (written < 0 && errno == EAGAIN)
-		written = 0;
-	else if (written <= 0) {
-		purple_input_remove(yrl->inpa);
-		yrl->inpa = 0;
-		g_free(yrl->txbuf);
-		yrl->txbuf = NULL;
-		purple_notify_error(purple_account_get_connection(list->account), NULL, _("Unable to connect"), _("Fetching the room list failed."));
-		yahoo_roomlist_cleanup(list, yrl);
-		return;
-	}
-
-	if (written < remaining) {
-		yrl->tx_written += written;
-		return;
-	}
-
-	g_free(yrl->txbuf);
-	yrl->txbuf = NULL;
-
-	purple_input_remove(yrl->inpa);
-	yrl->inpa = purple_input_add(yrl->fd, PURPLE_INPUT_READ,
-							   yahoo_roomlist_pending, yrl);
-
-}
-
-static void yahoo_roomlist_got_connected(gpointer data, gint source, const gchar *error_message)
-{
-	struct yahoo_roomlist *yrl = data;
-	PurpleRoomlist *list = yrl->list;
-	YahooData *yd = purple_account_get_connection(list->account)->proto_data;
-
-	if (source < 0) {
-		purple_notify_error(purple_account_get_connection(list->account), NULL, _("Unable to connect"), _("Fetching the room list failed."));
-		yahoo_roomlist_cleanup(list, yrl);
-		return;
-	}
-
-	yrl->fd = source;
-
-	yrl->txbuf = g_strdup_printf(
-		"GET http://%s/%s HTTP/1.0\r\n"
-		"Host: %s\r\n"
-		"Cookie: Y=%s; T=%s\r\n\r\n",
-		yrl->host, yrl->path, yrl->host, yd->cookie_y,
-		yd->cookie_t);
-
-
-	yrl->inpa = purple_input_add(yrl->fd, PURPLE_INPUT_WRITE,
-							   yahoo_roomlist_send_cb, yrl);
-	yahoo_roomlist_send_cb(yrl, yrl->fd, PURPLE_INPUT_WRITE);
-}
-
-PurpleRoomlist *yahoo_roomlist_get_list(PurpleConnection *gc)
-{
-	PurpleAccount *account;
-	PurpleRoomlist *rl;
-	PurpleRoomlistField *f;
-	GList *fields = NULL;
-	struct yahoo_roomlist *yrl;
-	const char *rll, *rlurl;
-	char *url;
-
-	account = purple_connection_get_account(gc);
-
-	/* for Yahoo Japan, it appears there is only one valid URL and locale */
-	if(purple_account_get_bool(account, "yahoojp", FALSE)) {
-		rll = YAHOOJP_ROOMLIST_LOCALE;
-		rlurl = YAHOOJP_ROOMLIST_URL;
-	}
-	else { /* but for the rest of the world that isn't the case */
-		rll = purple_account_get_string(account, "room_list_locale", YAHOO_ROOMLIST_LOCALE);
-		rlurl = purple_account_get_string(account, "room_list", YAHOO_ROOMLIST_URL);
-	}
-
-	url = g_strdup_printf("%s?chatcat=0&intl=%s", rlurl, rll);
-
-	yrl = g_new0(struct yahoo_roomlist, 1);
-	rl = purple_roomlist_new(account);
-	yrl->list = rl;
-
-	purple_url_parse(url, &(yrl->host), NULL, &(yrl->path), NULL, NULL);
-	g_free(url);
-
-	f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", "room", TRUE);
-	fields = g_list_append(fields, f);
-
-	f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", "id", TRUE);
-	fields = g_list_append(fields, f);
-
-	f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_INT, _("Users"), "users", FALSE);
-	fields = g_list_append(fields, f);
-
-	f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_INT, _("Voices"), "voices", FALSE);
-	fields = g_list_append(fields, f);
-
-	f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_INT, _("Webcams"), "webcams", FALSE);
-	fields = g_list_append(fields, f);
-
-	f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, _("Topic"), "topic", FALSE);
-	fields = g_list_append(fields, f);
-
-	purple_roomlist_set_fields(rl, fields);
-
-	if (purple_proxy_connect(gc, account, yrl->host, 80,
-	                       yahoo_roomlist_got_connected, yrl) == NULL)
-	{
-		purple_notify_error(gc, NULL, _("Connection problem"), _("Unable to fetch room list."));
-		yahoo_roomlist_cleanup(rl, yrl);
-		return NULL;
-	}
-
-	rl->proto_data = g_list_append(rl->proto_data, yrl);
-
-	purple_roomlist_set_in_progress(rl, TRUE);
-	return rl;
-}
-
-void yahoo_roomlist_cancel(PurpleRoomlist *list)
-{
-	GList *l, *k;
-
-	k = l = list->proto_data;
-	list->proto_data = NULL;
-
-	purple_roomlist_set_in_progress(list, FALSE);
-
-	for (; l; l = l->next) {
-		yahoo_roomlist_destroy(l->data);
-		purple_roomlist_unref(list);
-	}
-	g_list_free(k);
-}
-
-void yahoo_roomlist_expand_category(PurpleRoomlist *list, PurpleRoomlistRoom *category)
-{
-	struct yahoo_roomlist *yrl;
-	char *url;
-	char *id;
-	const char *rll;
-
-	if (category->type != PURPLE_ROOMLIST_ROOMTYPE_CATEGORY)
-		return;
-
-	if (!(id = g_list_nth_data(category->fields, 1))) {
-		purple_roomlist_set_in_progress(list, FALSE);
-		return;
-	}
-
-	rll = purple_account_get_string(list->account, "room_list_locale",
-								  YAHOO_ROOMLIST_LOCALE);
-
-	if (rll != NULL && *rll != '\0') {
-		url = g_strdup_printf("%s?chatroom_%s=0&intl=%s",
-	       purple_account_get_string(list->account,"room_list",
-	       YAHOO_ROOMLIST_URL), id, rll);
-	} else {
-		url = g_strdup_printf("%s?chatroom_%s=0",
-	       purple_account_get_string(list->account,"room_list",
-	       YAHOO_ROOMLIST_URL), id);
-	}
-
-	yrl = g_new0(struct yahoo_roomlist, 1);
-	yrl->list = list;
-	yrl->cat = category;
-	list->proto_data = g_list_append(list->proto_data, yrl);
-
-	purple_url_parse(url, &(yrl->host), NULL, &(yrl->path), NULL, NULL);
-	g_free(url);
-
-	yrl->ucat = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_CATEGORY, _("User Rooms"), yrl->cat);
-	purple_roomlist_room_add(list, yrl->ucat);
-
-	if (purple_proxy_connect(purple_account_get_connection(list->account),
-			list->account, yrl->host, 80,
-			yahoo_roomlist_got_connected, yrl) == NULL)
-	{
-		purple_notify_error(purple_account_get_connection(list->account),
-		                  NULL, _("Connection problem"), _("Unable to fetch room list."));
-		purple_roomlist_ref(list);
-		yahoo_roomlist_cleanup(list, yrl);
-		return;
-	}
-
-	purple_roomlist_set_in_progress(list, TRUE);
-	purple_roomlist_ref(list);
-}
--- a/libpurple/protocols/yahoo/yahoochat.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/**
- * @file yahoochat.h The Yahoo! protocol plugin, chat and conference stuff
- *
- * 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 _YAHOOCHAT_H_
-#define _YAHOOCHAT_H_
-
-#include "roomlist.h"
-#include "yahoo_packet.h"
-
-void yahoo_process_conference_invite(PurpleConnection *gc, struct yahoo_packet *pkt);
-void yahoo_process_conference_decline(PurpleConnection *gc, struct yahoo_packet *pkt);
-void yahoo_process_conference_logon(PurpleConnection *gc, struct yahoo_packet *pkt);
-void yahoo_process_conference_logoff(PurpleConnection *gc, struct yahoo_packet *pkt);
-void yahoo_process_conference_message(PurpleConnection *gc, struct yahoo_packet *pkt);
-
-void yahoo_process_chat_online(PurpleConnection *gc, struct yahoo_packet *pkt);
-void yahoo_process_chat_logout(PurpleConnection *gc, struct yahoo_packet *pkt);
-void yahoo_process_chat_join(PurpleConnection *gc, struct yahoo_packet *pkt);
-void yahoo_process_chat_exit(PurpleConnection *gc, struct yahoo_packet *pkt);
-void yahoo_process_chat_message(PurpleConnection *gc, struct yahoo_packet *pkt);
-void yahoo_process_chat_addinvite(PurpleConnection *gc, struct yahoo_packet *pkt);
-void yahoo_process_chat_goto(PurpleConnection *gc, struct yahoo_packet *pkt);
-
-void yahoo_c_leave(PurpleConnection *gc, int id);
-int yahoo_c_send(PurpleConnection *gc, int id, const char *what, PurpleMessageFlags flags);
-GList *yahoo_c_info(PurpleConnection *gc);
-GHashTable *yahoo_c_info_defaults(PurpleConnection *gc, const char *chat_name);
-void yahoo_c_join(PurpleConnection *gc, GHashTable *data);
-char *yahoo_get_chat_name(GHashTable *data);
-void yahoo_c_invite(PurpleConnection *gc, int id, const char *msg, const char *name);
-
-void yahoo_conf_leave(YahooData *yd, const char *room, const char *dn, GList *who);
-
-void yahoo_chat_goto(PurpleConnection *gc, const char *name);
-
-/* room listing functions */
-PurpleRoomlist *yahoo_roomlist_get_list(PurpleConnection *gc);
-void yahoo_roomlist_cancel(PurpleRoomlist *list);
-void yahoo_roomlist_expand_category(PurpleRoomlist *list, PurpleRoomlistRoom *category);
-
-/* util */
-void yahoo_chat_add_users(PurpleConvChat *chat, GList *newusers);
-void yahoo_chat_add_user(PurpleConvChat *chat, const char *user, const char *reason);
-
-#endif /* _YAHOO_CHAT_H_ */
--- a/libpurple/protocols/yahoo/ycht.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,658 +0,0 @@
-/**
- * @file ycht.c The Yahoo! protocol plugin, YCHT protocol stuff.
- *
- * purple
- *
- * Copyright (C) 2004 Timothy Ringenbach <omarvo@hotmail.com>
- * Liberal amounts of code borrowed from the rest of the Yahoo! prpl.
- *
- * 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 "prpl.h"
-#include "notify.h"
-#include "account.h"
-#include "proxy.h"
-#include "debug.h"
-#include "conversation.h"
-#include "util.h"
-
-#include "libymsg.h"
-#include "yahoo_packet.h"
-#include "ycht.h"
-#include "yahoochat.h"
-
-/*
- * dword: YCHT
- * dword: 0x000000AE
- * dword: service
- * word:  status
- * word:  size
- */
-#define YAHOO_CHAT_ID (1)
-/************************************************************************************
- * Functions to process various kinds of packets.
- ************************************************************************************/
-static void ycht_process_login(YchtConn *ycht, YchtPkt *pkt)
-{
-	PurpleConnection *gc = ycht->gc;
-	YahooData *yd = gc->proto_data;
-
-	if (ycht->logged_in)
-		return;
-
-	yd->chat_online = TRUE;
-	ycht->logged_in = TRUE;
-
-	if (ycht->room)
-		ycht_chat_join(ycht, ycht->room);
-}
-
-static void ycht_process_logout(YchtConn *ycht, YchtPkt *pkt)
-{
-	PurpleConnection *gc = ycht->gc;
-	YahooData *yd = gc->proto_data;
-
-	yd->chat_online = FALSE;
-	ycht->logged_in = FALSE;
-}
-
-static void ycht_process_chatjoin(YchtConn *ycht, YchtPkt *pkt)
-{
-	char *room, *topic;
-	PurpleConnection *gc = ycht->gc;
-	PurpleConversation *c = NULL;
-	gboolean new_room = FALSE;
-	char **members;
-	int i;
-
-	room = g_list_nth_data(pkt->data, 0);
-	topic = g_list_nth_data(pkt->data, 1);
-	if (!g_list_nth_data(pkt->data, 4))
-		return;
-	if (!room)
-		return;
-
-	members = g_strsplit(g_list_nth_data(pkt->data, 4), "\001", 0);
-	for (i = 0; members[i]; i++) {
-		char *tmp = strchr(members[i], '\002');
-		if (tmp)
-			*tmp = '\0';
-	}
-
-	if (g_list_length(pkt->data) > 5)
-		new_room = TRUE;
-
-	if (new_room && ycht->changing_rooms) {
-		serv_got_chat_left(gc, YAHOO_CHAT_ID);
-		ycht->changing_rooms = FALSE;
-		c = serv_got_joined_chat(gc, YAHOO_CHAT_ID, room);
-	} else {
-		c = purple_find_chat(gc, YAHOO_CHAT_ID);
-	}
-
-	if (topic)
-		purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic);
-
-	for (i = 0; members[i]; i++) {
-		if (new_room) {
-			/*if (!strcmp(members[i], purple_connection_get_display_name(ycht->gc)))
-				continue;*/
-			purple_conv_chat_add_user(PURPLE_CONV_CHAT(c), members[i], NULL, PURPLE_CBFLAGS_NONE, TRUE);
-		} else {
-			yahoo_chat_add_user(PURPLE_CONV_CHAT(c), members[i], NULL);
-		}
-	}
-
-	g_strfreev(members);
-}
-
-static void ycht_process_chatpart(YchtConn *ycht, YchtPkt *pkt)
-{
-	char *room, *who;
-
-	room = g_list_nth_data(pkt->data, 0);
-	who = g_list_nth_data(pkt->data, 1);
-
-	if (who && room) {
-		PurpleConversation *c = purple_find_chat(ycht->gc, YAHOO_CHAT_ID);
-		if (c && !purple_utf8_strcasecmp(purple_conversation_get_name(c), room))
-			purple_conv_chat_remove_user(PURPLE_CONV_CHAT(c), who, NULL);
-
-	}
-}
-
-static void ycht_progress_chatmsg(YchtConn *ycht, YchtPkt *pkt)
-{
-	char *who, *what, *msg;
-	PurpleConversation *c;
-	PurpleConnection *gc = ycht->gc;
-
-	who = g_list_nth_data(pkt->data, 1);
-	what = g_list_nth_data(pkt->data, 2);
-
-	if (!who || !what)
-		return;
-
-	c = purple_find_chat(gc, YAHOO_CHAT_ID);
-	if (!c)
-		return;
-
-	msg = yahoo_string_decode(gc, what, 1);
-	what = yahoo_codes_to_html(msg);
-	g_free(msg);
-
-	if (pkt->service == YCHT_SERVICE_CHATMSG_EMOTE) {
-		char *tmp = g_strdup_printf("/me %s", what);
-		g_free(what);
-		what = tmp;
-	}
-
-	serv_got_chat_in(gc, YAHOO_CHAT_ID, who, 0, what, time(NULL));
-	g_free(what);
-}
-
-static void ycht_progress_online_friends(YchtConn *ycht, YchtPkt *pkt)
-{
-#if 0
-	PurpleConnection *gc = ycht->gc;
-	YahooData *yd = gc->proto_data;
-
-	if (ycht->logged_in)
-		return;
-
-	yd->chat_online = TRUE;
-	ycht->logged_in = TRUE;
-
-	if (ycht->room)
-		ycht_chat_join(ycht, ycht->room);
-#endif
-}
-
-/*****************************************************************************
- * Functions dealing with YCHT packets and their contents directly.
- *****************************************************************************/
-static void ycht_packet_dump(const guchar *data, int len)
-{
-#ifdef YAHOO_YCHT_DEBUG
-	int i;
-
-	purple_debug_misc("yahoo", "");
-
-	for (i = 0; i + 1 < len; i += 2) {
-		if ((i % 16 == 0) && i) {
-			purple_debug_misc(NULL, "\n");
-			purple_debug_misc("yahoo", "");
-		}
-
-		purple_debug_misc(NULL, "%02hhx%02hhx ", data[i], data[i + 1]);
-	}
-	if (i < len)
-		purple_debug_misc(NULL, "%02hhx", data[i]);
-
-	purple_debug_misc(NULL, "\n");
-	purple_debug_misc("yahoo", "");
-
-	for (i = 0; i < len; i++) {
-		if ((i % 16 == 0) && i) {
-			purple_debug_misc(NULL, "\n");
-			purple_debug_misc("yahoo", "");
-		}
-
-		if (g_ascii_isprint(data[i]))
-			purple_debug_misc(NULL, "%c ", data[i]);
-		else
-			purple_debug_misc(NULL, ". ");
-	}
-
-	purple_debug_misc(NULL, "\n");
-#endif /* YAHOO_YCHT_DEBUG */
-}
-
-static YchtPkt *ycht_packet_new(guint version, guint service, int status)
-{
-	YchtPkt *ret;
-
-	ret = g_new0(YchtPkt, 1);
-
-	ret->version = version;
-	ret->service = service;
-	ret->status = status;
-
-	return ret;
-}
-
-static void ycht_packet_append(YchtPkt *pkt, const char *str)
-{
-	g_return_if_fail(pkt != NULL);
-	g_return_if_fail(str != NULL);
-
-	pkt->data = g_list_append(pkt->data, g_strdup(str));
-}
-
-static int ycht_packet_length(YchtPkt *pkt)
-{
-	int ret;
-	GList *l;
-
-	ret = YCHT_HEADER_LEN;
-
-	for (l = pkt->data; l; l = l->next) {
-		ret += strlen(l->data);
-		if (l->next)
-			ret += strlen(YCHT_SEP);
-	}
-
-	return ret;
-}
-
-static void ycht_packet_send_write_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
-	YchtConn *ycht = data;
-	int ret, writelen;
-
-	writelen = purple_circ_buffer_get_max_read(ycht->txbuf);
-
-	if (writelen == 0) {
-		purple_input_remove(ycht->tx_handler);
-		ycht->tx_handler = 0;
-		return;
-	}
-
-	ret = write(ycht->fd, ycht->txbuf->outptr, writelen);
-
-	if (ret < 0 && errno == EAGAIN)
-		return;
-	else if (ret <= 0) {
-		/* TODO: error handling */
-/*
-		gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
-				g_strerror(errno));
-		purple_connection_error_reason(purple_account_get_connection(irc->account),
-			      PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-		g_free(tmp);
-*/
-		return;
-	}
-
-	purple_circ_buffer_mark_read(ycht->txbuf, ret);
-
-}
-
-static void ycht_packet_send(YchtConn *ycht, YchtPkt *pkt)
-{
-	int len, pos, written;
-	char *buf;
-	GList *l;
-
-	g_return_if_fail(ycht != NULL);
-	g_return_if_fail(pkt != NULL);
-	g_return_if_fail(ycht->fd != -1);
-
-	pos = 0;
-	len = ycht_packet_length(pkt);
-	buf = g_malloc(len);
-
-	memcpy(buf + pos, "YCHT", 4); pos += 4;
-	pos += yahoo_put32(buf + pos, pkt->version);
-	pos += yahoo_put32(buf + pos, pkt->service);
-	pos += yahoo_put16(buf + pos, pkt->status);
-	pos += yahoo_put16(buf + pos, len - YCHT_HEADER_LEN);
-
-	for (l = pkt->data; l; l = l->next) {
-		int slen = strlen(l->data);
-		memcpy(buf + pos, l->data, slen); pos += slen;
-
-		if (l->next) {
-			memcpy(buf + pos, YCHT_SEP, strlen(YCHT_SEP));
-			pos += strlen(YCHT_SEP);
-		}
-	}
-
-	if (!ycht->tx_handler)
-		written = write(ycht->fd, buf, len);
-	else {
-		written = -1;
-		errno = EAGAIN;
-	}
-
-	if (written < 0 && errno == EAGAIN)
-		written = 0;
-	else if (written <= 0) {
-		/* TODO: Error handling (was none before NBIO changes) */
-		written = 0;
-	}
-
-	if (written < len) {
-		if (!ycht->tx_handler)
-			ycht->tx_handler = purple_input_add(ycht->fd,
-				PURPLE_INPUT_WRITE, ycht_packet_send_write_cb,
-				ycht);
-		purple_circ_buffer_append(ycht->txbuf, buf + written,
-			len - written);
-	}
-
-	g_free(buf);
-}
-
-static void ycht_packet_read(YchtPkt *pkt, const char *buf, int len)
-{
-	const char *pos = buf;
-	const char *needle;
-	char *tmp, *tmp2;
-	int i = 0;
-
-	while (len > 0 && (needle = g_strstr_len(pos, len, YCHT_SEP))) {
-		tmp = g_strndup(pos, needle - pos);
-		pkt->data = g_list_append(pkt->data, tmp);
-		len -= needle - pos + strlen(YCHT_SEP);
-		pos = needle + strlen(YCHT_SEP);
-		tmp2 = g_strescape(tmp, NULL);
-		purple_debug_misc("yahoo", "Data[%d]:\t%s\n", i++, tmp2);
-		g_free(tmp2);
-	}
-
-	if (len) {
-		tmp = g_strndup(pos, len);
-		pkt->data = g_list_append(pkt->data, tmp);
-		tmp2 = g_strescape(tmp, NULL);
-		purple_debug_misc("yahoo", "Data[%d]:\t%s\n", i, tmp2);
-		g_free(tmp2);
-	};
-
-	purple_debug_misc("yahoo", "--==End of incoming YCHT packet==--\n");
-}
-
-static void ycht_packet_process(YchtConn *ycht, YchtPkt *pkt)
-{
-	if (pkt->data && !strncmp(pkt->data->data, "*** Danger Will Robinson!!!", strlen("*** Danger Will Robinson!!!")))
-		return;
-
-	switch (pkt->service) {
-	case YCHT_SERVICE_LOGIN:
-		ycht_process_login(ycht, pkt);
-		break;
-	case YCHT_SERVICE_LOGOUT:
-		ycht_process_logout(ycht, pkt);
-		break;
-	case YCHT_SERVICE_CHATJOIN:
-		ycht_process_chatjoin(ycht, pkt);
-		break;
-	case YCHT_SERVICE_CHATPART:
-		ycht_process_chatpart(ycht, pkt);
-		break;
-	case YCHT_SERVICE_CHATMSG:
-	case YCHT_SERVICE_CHATMSG_EMOTE:
-		ycht_progress_chatmsg(ycht, pkt);
-		break;
-	case YCHT_SERVICE_ONLINE_FRIENDS:
-		ycht_progress_online_friends(ycht, pkt);
-		break;
-	default:
-		purple_debug_warning("yahoo", "YCHT: warning, unhandled service 0x%02x\n", pkt->service);
-	}
-}
-
-static void ycht_packet_free(YchtPkt *pkt)
-{
-	GList *l;
-
-	g_return_if_fail(pkt != NULL);
-
-	for (l = pkt->data; l; l = l->next)
-		g_free(l->data);
-	g_list_free(pkt->data);
-	g_free(pkt);
-}
-
-/************************************************************************************
- * Functions dealing with connecting and disconnecting and reading data into YchtPkt
- * structs, and all that stuff.
- ************************************************************************************/
-
-void ycht_connection_close(YchtConn *ycht)
-{
-	YahooData *yd = ycht->gc->proto_data;
-
-	if (yd) {
-		yd->ycht = NULL;
-		yd->chat_online = FALSE;
-	}
-
-	if (ycht->fd > 0)
-		close(ycht->fd);
-	if (ycht->inpa)
-		purple_input_remove(ycht->inpa);
-
-	if (ycht->tx_handler)
-		purple_input_remove(ycht->tx_handler);
-
-	purple_circ_buffer_destroy(ycht->txbuf);
-
-	g_free(ycht->rxqueue);
-
-	g_free(ycht);
-}
-
-static void ycht_connection_error(YchtConn *ycht, const gchar *error)
-{
-
-	purple_notify_info(ycht->gc, NULL, _("Connection problem with the YCHT server"), error);
-	ycht_connection_close(ycht);
-}
-
-static void ycht_pending(gpointer data, gint source, PurpleInputCondition cond)
-{
-	YchtConn *ycht = data;
-	char buf[1024];
-	int len;
-
-	len = read(ycht->fd, buf, sizeof(buf));
-
-	if (len < 0) {
-		gchar *tmp;
-
-		if (errno == EAGAIN)
-			/* No worries */
-			return;
-
-		tmp = g_strdup_printf(_("Lost connection with server: %s"),
-				g_strerror(errno));
-		ycht_connection_error(ycht, tmp);
-		g_free(tmp);
-		return;
-	} else if (len == 0) {
-		ycht_connection_error(ycht, _("Server closed the connection"));
-		return;
-	}
-
-	ycht->rxqueue = g_realloc(ycht->rxqueue, len + ycht->rxlen);
-	memcpy(ycht->rxqueue + ycht->rxlen, buf, len);
-	ycht->rxlen += len;
-
-	while (1) {
-		YchtPkt *pkt;
-		int pos = 0;
-		guint pktlen;
-		guint service;
-		guint version;
-		gint status;
-
-		if (ycht->rxlen < YCHT_HEADER_LEN)
-			return;
-
-		if (strncmp("YCHT", (char *)ycht->rxqueue, 4) != 0)
-			purple_debug_error("yahoo", "YCHT: protocol error.\n");
-
-		pos += 4; /* YCHT */
-
-		version = yahoo_get32(ycht->rxqueue + pos); pos += 4;
-		service = yahoo_get32(ycht->rxqueue + pos); pos += 4;
-		status = yahoo_get16(ycht->rxqueue + pos); pos += 2;
-		pktlen  = yahoo_get16(ycht->rxqueue + pos); pos += 2;
-		purple_debug_misc("yahoo", "ycht: %d bytes to read, rxlen is %d\n",
-				pktlen, ycht->rxlen);
-
-		if (ycht->rxlen < (YCHT_HEADER_LEN + pktlen))
-			return;
-
-		purple_debug_misc("yahoo", "--==Incoming YCHT packet==--\n");
-		purple_debug_misc("yahoo", "YCHT Service: 0x%02x Version: 0x%02x Status: 0x%02x\n",
-				service, version, status);
-		ycht_packet_dump(ycht->rxqueue, YCHT_HEADER_LEN + pktlen);
-
-		pkt = ycht_packet_new(version, service, status);
-		ycht_packet_read(pkt, (char *)ycht->rxqueue + pos, pktlen);
-
-		ycht->rxlen -= YCHT_HEADER_LEN + pktlen;
-		if (ycht->rxlen) {
-			guchar *tmp = g_memdup(ycht->rxqueue + YCHT_HEADER_LEN + pktlen, ycht->rxlen);
-			g_free(ycht->rxqueue);
-			ycht->rxqueue = tmp;
-		} else {
-			g_free(ycht->rxqueue);
-			ycht->rxqueue = NULL;
-		}
-
-		ycht_packet_process(ycht, pkt);
-
-		ycht_packet_free(pkt);
-	}
-}
-
-static void ycht_got_connected(gpointer data, gint source, const gchar *error_message)
-{
-	YchtConn *ycht = data;
-	PurpleConnection *gc = ycht->gc;
-	YahooData *yd = gc->proto_data;
-	YchtPkt *pkt;
-	char *buf;
-
-	if (source < 0) {
-		ycht_connection_error(ycht, _("Unable to connect"));
-		return;
-	}
-
-	ycht->fd = source;
-
-	pkt = ycht_packet_new(YCHT_VERSION, YCHT_SERVICE_LOGIN, 0);
-
-	buf = g_strdup_printf("%s\001Y=%s; T=%s", purple_connection_get_display_name(gc), yd->cookie_y, yd->cookie_t);
-	ycht_packet_append(pkt, buf);
-	g_free(buf);
-
-	ycht_packet_send(ycht, pkt);
-
-	ycht_packet_free(pkt);
-
-	ycht->inpa = purple_input_add(ycht->fd, PURPLE_INPUT_READ, ycht_pending, ycht);
-}
-
-void ycht_connection_open(PurpleConnection *gc)
-{
-	YchtConn *ycht;
-	YahooData *yd = gc->proto_data;
-	PurpleAccount *account = purple_connection_get_account(gc);
-
-	ycht = g_new0(YchtConn, 1);
-	ycht->gc = gc;
-	ycht->fd = -1;
-
-	yd->ycht = ycht;
-
-	if (purple_proxy_connect(gc, account,
-	                       purple_account_get_string(account, "ycht-server",  YAHOO_YCHT_HOST),
-	                       purple_account_get_int(account, "ycht-port", YAHOO_YCHT_PORT),
-	                       ycht_got_connected, ycht) == NULL)
-	{
-		ycht_connection_error(ycht, _("Unable to connect"));
-		return;
-	}
-}
-
-/*******************************************************************************************
- * These are functions called because the user did something.
- *******************************************************************************************/
-
-void ycht_chat_join(YchtConn *ycht, const char *room)
-{
-	YchtPkt *pkt;
-	char *tmp;
-
-	tmp = g_strdup(room);
-	g_free(ycht->room);
-	ycht->room = tmp;
-
-	if (!ycht->logged_in)
-		return;
-
-	ycht->changing_rooms = TRUE;
-	pkt = ycht_packet_new(YCHT_VERSION, YCHT_SERVICE_CHATJOIN, 0);
-	ycht_packet_append(pkt, ycht->room);
-	ycht_packet_send(ycht, pkt);
-	ycht_packet_free(pkt);
-}
-
-int ycht_chat_send(YchtConn *ycht, const char *room, const char *what)
-{
-	YchtPkt *pkt;
-	char *msg1, *msg2, *buf;
-
-	if (strcmp(room, ycht->room))
-		purple_debug_warning("yahoo", "uhoh, sending to the wrong room!\n");
-
-	pkt = ycht_packet_new(YCHT_VERSION, YCHT_SERVICE_CHATMSG, 0);
-
-	msg1 = yahoo_html_to_codes(what);
-	msg2 = yahoo_string_encode(ycht->gc, msg1, NULL);
-	g_free(msg1);
-
-	buf = g_strdup_printf("%s\001%s", ycht->room, msg2);
-	ycht_packet_append(pkt, buf);
-	g_free(msg2);
-	g_free(buf);
-
-	ycht_packet_send(ycht, pkt);
-	ycht_packet_free(pkt);
-	return 1;
-}
-
-void ycht_chat_leave(YchtConn *ycht, const char *room, gboolean logout)
-{
-	if (logout)
-		ycht_connection_close(ycht);
-}
-
-void ycht_chat_send_invite(YchtConn *ycht, const char *room, const char *buddy, const char *msg)
-{
-}
-
-void ycht_chat_goto_user(YchtConn *ycht, const char *name)
-{
-}
-
-void ycht_chat_send_keepalive(YchtConn *ycht)
-{
-	YchtPkt *pkt;
-
-	pkt = ycht_packet_new(YCHT_VERSION, YCHT_SERVICE_PING, 0);
-	ycht_packet_send(ycht, pkt);
-	ycht_packet_free(pkt);
-}
--- a/libpurple/protocols/yahoo/ycht.h	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/**
- * @file ycht.h The Yahoo! protocol plugin, YCHT protocol stuff.
- *
- * purple
- *
- * Copyright (C) 2004 Timothy Ringenbach <omarvo@hotmail.com>
- *
- * 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_YCHT_H_
-#define _PURPLE_YCHT_H_
-
-/* #define YAHOO_YCHT_DEBUG */
-
-#define YAHOO_YCHT_HOST "jcs3.chat.dcn.yahoo.com"
-#define YAHOO_YCHT_PORT 8002
-
-#define YCHT_VERSION (0xae)
-#define YCHT_HEADER_LEN (0x10)
-
-typedef enum {
-	YCHT_SERVICE_LOGIN = 0x01,
-	YCHT_SERVICE_LOGOUT = 0x02,
-	YCHT_SERVICE_CHATJOIN = 0x11,
-	YCHT_SERVICE_CHATPART = 0x12,
-	YCHT_SERVICE_CHATMSG = 0x41,
-	YCHT_SERVICE_CHATMSG_EMOTE = 0x43,
-	YCHT_SERVICE_PING = 0x62,
-	YCHT_SERVICE_ONLINE_FRIENDS = 0x68
-} ycht_service;
-/*
-yahoo: YCHT Service: 0x11 Version: 0x100
-yahoo: Data[0]: Linux, FreeBSD, Solaris:1
-yahoo: Data[1]: Questions, problems and discussions about all flavors of Unix.
-yahoo: Data[2]:
-yahoo: Data[3]: 0
-yahoo: Data[4]: sgooki888\0020\002 \0022769036\00258936\002
-yahoo: --==End of incoming YCHT packet==--
-
-yahoo: --==Incoming YCHT packet==--
-yahoo: YCHT Service: 0x12 Version: 0x100
-yahoo: Data[0]: Linux, FreeBSD, Solaris:1
-yahoo: Data[1]: cccc4cccc
-yahoo: --==End of incoming YCHT packet==--
-
-*/
-#define YCHT_SEP "\xc0\x80"
-
-typedef struct _YchtConn {
-	PurpleConnection *gc;
-	gchar *room;
-	int room_id;
-	gint fd;
-	gint inpa;
-	gboolean logged_in;
-	gboolean changing_rooms;
-	guchar *rxqueue;
-	guint rxlen;
-	PurpleCircBuffer *txbuf;
-	guint tx_handler;
-} YchtConn;
-
-typedef struct {
-	guint version;
-	guint service;
-	gint status;
-	GList *data;
-} YchtPkt;
-
-void ycht_connection_open(PurpleConnection *gc);
-void ycht_connection_close(YchtConn *ycht);
-
-void ycht_chat_join(YchtConn *ycht, const char *room);
-int ycht_chat_send(YchtConn *ycht, const char *room, const char *what);
-void ycht_chat_leave(YchtConn *ycht, const char *room, gboolean logout);
-void ycht_chat_send_invite(YchtConn *ycht, const char *room, const char *buddy, const char *msg);
-void ycht_chat_goto_user(YchtConn *ycht, const char *name);
-void ycht_chat_send_keepalive(YchtConn *ycht);
-
-#endif /* _PURPLE_YCHT_H_ */
--- a/libpurple/prpl.c	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/prpl.c	Thu Oct 06 10:05:06 2016 -0400
@@ -634,8 +634,7 @@
 	 * but may be used in the future.
 	 */
 	if (g_strcmp0(id, "prpl-xmpp") == 0 ||
-		g_strcmp0(id, "prpl-gtalk") == 0 ||
-		g_strcmp0(id, "prpl-facebook-xmpp") == 0)
+		g_strcmp0(id, "prpl-gtalk") == 0)
 	{
 		id = "prpl-jabber";
 	}
--- a/libpurple/prpl.h	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/prpl.h	Thu Oct 06 10:05:06 2016 -0400
@@ -162,7 +162,7 @@
 	/**
 	 * Notify on new mail.
 	 *
-	 * MSN and Yahoo notify you when you have new mail.
+	 * If a protocol notifies you when you have new mail.
 	 */
 	OPT_PROTO_MAIL_CHECK = 0x00000020,
 
@@ -921,8 +921,8 @@
  * @param gc The connection to send the message on.
  * @param who Whose attention to request.
  * @param type_code An index into the prpl's attention_types list determining the type
- *        of the attention request command to send. 0 if prpl only defines one
- *        (for example, Yahoo and MSN), but some protocols define more (MySpaceIM).
+ *        of the attention request command to send. 0 if prpl only defines one,
+ *        but protocols are allowed to define more.
  *
  * Note that you can't send arbitrary PurpleAttentionType's, because there is
  * only a fixed set of attention commands.
--- a/libpurple/purple-url-handler	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/purple-url-handler	Thu Oct 06 10:05:06 2016 -0400
@@ -224,34 +224,6 @@
                 channel = "#" + channel
             gochat(account, {"server": server, "channel": channel, "password": params.get("key", "")}, params.get("msg"))
 
-def msnim(uri):
-    protocol = "prpl-msn"
-    match = re.match(r"^msnim:([^?]*)(\?(.*))", uri)
-    if not match:
-        print("Invalid msnim URI: %s" % uri)
-        return
-
-    command = unquote_plus(match.group(1))
-    paramstring = match.group(3)
-    params = {}
-    if paramstring:
-        for param in paramstring.split("&"):
-            key, value = extendlist(param.split("=", 1), 2, "")
-            params[key] = unquote_plus(value)
-    screenname = params.get("contact", "")
-
-    account = findaccount(protocol)
-
-    if command.lower() == "chat":
-        goim(account, screenname)
-    elif command.lower() == "add":
-        addbuddy(account, screenname)
-
-def myim(uri):
-        protocol = "prpl-myspace"
-        print "TODO: send uri: ", uri
-        assert False, "Not implemented"
-
 def sip(uri):
     protocol = "prpl-simple"
     match = re.match(r"^sip:(.*)", uri)
@@ -328,31 +300,6 @@
         # XXX V&V prompt to establish call
         goim(account, jid)
 
-def ymsgr(uri):
-    protocol = "prpl-yahoo"
-    match = re.match(r"^ymsgr:([^?]*)(\?([^&]*)(&(.*))?)", uri)
-    if not match:
-        print("Invalid ymsgr URI: %s" % uri)
-        return
-
-    command = unquote_plus(match.group(1))
-    screenname = unquote_plus(match.group(3))
-    paramstring = match.group(5)
-    params = {}
-    if paramstring:
-        for param in paramstring.split("&"):
-            key, value = extendlist(param.split("=", 1), 2, "")
-            params[key] = unquote_plus(value)
-
-    account = findaccount(protocol)
-
-    if command.lower() == "sendim":
-        goim(account, screenname, params.get("m"))
-    elif command.lower() == "chat":
-        gochat(account, {"room": screenname})
-    elif command.lower() == "addfriend":
-        addbuddy(account, screenname)
-
 
 def main(argv=sys.argv):
     if len(argv) != 2 or argv[1] == "--help" or argv[1] == "-h":
@@ -376,18 +323,12 @@
             icq(uri)
         elif type == "irc":
             irc(uri)
-        elif type == "msnim":
-            msnim(uri)
-        elif type == "myim":
-            myim(uri)
         elif type == "sip":
             sip(uri)
         elif type == "xmpp":
             xmpp(uri)
         elif type == "gtalk":
             gtalk(uri)
-        elif type == "ymsgr":
-            ymsgr(uri)
         else:
             print("Unknown protocol: %s" % type)
     except dbus.DBusException as e:
--- a/libpurple/server.h	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/server.h	Thu Oct 06 10:05:06 2016 -0400
@@ -68,8 +68,8 @@
  * @param gc The connection to send the message on.
  * @param who Whose attention to request.
  * @param type_code An index into the prpl's attention_types list determining the type
- * 	of the attention request command to send. 0 if prpl only defines one
- * 	(for example, Yahoo and MSN), but some protocols define more (MySpaceIM).
+ * 	of the attention request command to send. 0 if prpl only defines one,
+ * 	but protocols are allowed to define more.
  *
  * Note that you can't send arbitrary PurpleAttentionType's, because there is
  * only a fixed set of attention commands.
--- a/libpurple/tests/Makefile.am	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/tests/Makefile.am	Thu Oct 06 10:05:06 2016 -0400
@@ -15,7 +15,6 @@
 		test_jabber_jutil.c \
 		test_jabber_scram.c \
 		test_oscar_util.c \
-		test_yahoo_util.c \
 		test_util.c \
 		test_xmlnode.c \
 		$(top_builddir)/libpurple/util.h
@@ -32,7 +31,6 @@
 check_libpurple_LDADD=\
 		$(top_builddir)/libpurple/protocols/jabber/libjabber.la \
 		$(top_builddir)/libpurple/protocols/oscar/liboscar.la \
-		$(top_builddir)/libpurple/protocols/yahoo/libymsg.la \
 		$(top_builddir)/libpurple/libpurple.la \
         @CHECK_LIBS@ \
 		$(GLIB_LIBS)
--- a/libpurple/tests/check_libpurple.c	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/tests/check_libpurple.c	Thu Oct 06 10:05:06 2016 -0400
@@ -92,7 +92,6 @@
 	srunner_add_suite(sr, jabber_jutil_suite());
 	srunner_add_suite(sr, jabber_scram_suite());
 	srunner_add_suite(sr, oscar_util_suite());
-	srunner_add_suite(sr, yahoo_util_suite());
 	srunner_add_suite(sr, util_suite());
 	srunner_add_suite(sr, xmlnode_suite());
 
--- a/libpurple/tests/test_yahoo_util.c	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,214 +0,0 @@
-#include <string.h>
-
-#include "tests.h"
-#include "../protocols/yahoo/libymsg.h"
-
-static void setup_codes_to_html(void)
-{
-	yahoo_init_colorht();
-}
-
-static void teardown_codes_to_html(void)
-{
-	yahoo_dest_colorht();
-}
-
-START_TEST(test_codes_to_html)
-{
-	assert_string_equal_free("",
-			yahoo_codes_to_html(""));
-	assert_string_equal_free("",
-			yahoo_codes_to_html("\x1B[12345m"));
-	assert_string_equal_free("plain",
-			yahoo_codes_to_html("plain"));
-	assert_string_equal_free("unknown  ansi code",
-			yahoo_codes_to_html("unknown \x1B[12345m ansi code"));
-	assert_string_equal_free("plain &lt;peanut&gt;",
-			yahoo_codes_to_html("plain <peanut>"));
-	assert_string_equal_free("plain &lt;peanut",
-			yahoo_codes_to_html("plain <peanut"));
-	assert_string_equal_free("plain&gt; peanut",
-			yahoo_codes_to_html("plain> peanut"));
-	assert_string_equal_free("<font face='inva&gt;lid'>test</font>",
-			yahoo_codes_to_html("<font face='inva>lid'>test"));
-	assert_string_equal_free("&lt;font face=&apos;inva&gt;lid",
-			yahoo_codes_to_html("<font face='inva>lid"));
-
-	/* bold/italic/underline */
-	assert_string_equal_free("<b>bold</b>",
-			yahoo_codes_to_html("\x1B[1mbold"));
-	assert_string_equal_free("<i>italic</i>",
-			yahoo_codes_to_html("\x1B[2mitalic"));
-	assert_string_equal_free("<u>underline</u>",
-			yahoo_codes_to_html("\x1B[4munderline"));
-	assert_string_equal_free("no markup",
-			yahoo_codes_to_html("no\x1B[x4m markup"));
-	assert_string_equal_free("<b>bold</b> <i>italic</i> <u>underline</u>",
-			yahoo_codes_to_html("\x1B[1mbold\x1B[x1m \x1B[2mitalic\x1B[x2m \x1B[4munderline"));
-	assert_string_equal_free("<b>bold <i>bolditalic</i></b><i> italic</i>",
-			yahoo_codes_to_html("\x1B[1mbold \x1B[2mbolditalic\x1B[x1m italic"));
-	assert_string_equal_free("<b>bold <i>bolditalic</i></b><i> <u>italicunderline</u></i>",
-			yahoo_codes_to_html("\x1B[1mbold \x1B[2mbolditalic\x1B[x1m \x1B[4mitalicunderline"));
-	assert_string_equal_free("<b>bold <i>bolditalic <u>bolditalicunderline</u></i><u> boldunderline</u></b>",
-			yahoo_codes_to_html("\x1B[1mbold \x1B[2mbolditalic \x1B[4mbolditalicunderline\x1B[x2m boldunderline"));
-	assert_string_equal_free("<b>bold <i>bolditalic <u>bolditalicunderline</u></i></b><i><u> italicunderline</u></i>",
-			yahoo_codes_to_html("\x1B[1mbold \x1B[2mbolditalic \x1B[4mbolditalicunderline\x1B[x1m italicunderline"));
-
-	/* link */
-	assert_string_equal_free("http://pidgin.im/",
-			yahoo_codes_to_html("\x1B[lmhttp://pidgin.im/\x1B[xlm"));
-
-#ifdef USE_CSS_FORMATTING
-	/* font color */
-	assert_string_equal_free("<span style='color: #0000FF'>blue</span>",
-			yahoo_codes_to_html("\x1B[31mblue"));
-	assert_string_equal_free("<span style='color: #70ea15'>custom color</span>",
-			yahoo_codes_to_html("\x1B[#70ea15mcustom color"));
-
-	/* font face */
-	assert_string_equal_free("<font face='Georgia'>test</font>",
-			yahoo_codes_to_html("<font face='Georgia'>test</font>"));
-
-	/* font size */
-	assert_string_equal_free("<font><span style='font-size: 15pt'>test</span></font>",
-			yahoo_codes_to_html("<font size='15'>test"));
-	assert_string_equal_free("<font><span style='font-size: 32pt'>size 32</span></font>",
-			yahoo_codes_to_html("<font size='32'>size 32"));
-
-	/* combinations */
-	assert_string_equal_free("<font face='Georgia'><span style='font-size: 32pt'>test</span></font>",
-			yahoo_codes_to_html("<font face='Georgia' size='32'>test"));
-	assert_string_equal_free("<span style='color: #FF0080'><font><span style='font-size: 15pt'>test</span></font></span>",
-			yahoo_codes_to_html("\x1B[35m<font size='15'>test"));
-#else
-	/* font color */
-	assert_string_equal_free("<font color='#0000FF'>blue</font>",
-			yahoo_codes_to_html("\x1B[31mblue"));
-	assert_string_equal_free("<font color='#70ea15'>custom color</font>",
-			yahoo_codes_to_html("\x1B[#70ea15mcustom color"));
-	assert_string_equal_free("test",
-			yahoo_codes_to_html("<ALT #ff0000,#00ff00,#0000ff>test</ALT>"));
-
-	/* font face */
-	assert_string_equal_free("<font face='Georgia'>test</font>",
-			yahoo_codes_to_html("<font face='Georgia'>test"));
-
-	/* font size */
-	assert_string_equal_free("<font size='4' absz='15'>test</font>",
-			yahoo_codes_to_html("<font size='15'>test"));
-	assert_string_equal_free("<font size='6' absz='32'>size 32</font>",
-			yahoo_codes_to_html("<font size='32'>size 32"));
-
-	/* combinations */
-	assert_string_equal_free("<font face='Georgia' size='6' absz='32'>test</font>",
-			yahoo_codes_to_html("<font face='Georgia' size='32'>test"));
-	assert_string_equal_free("<font color='#FF0080'><font size='4' absz='15'>test</font></font>",
-			yahoo_codes_to_html("\x1B[35m<font size='15'>test"));
-	assert_string_equal_free(":&lt;",
-			yahoo_codes_to_html("<FADE #ff0000,#00ff00,#0000ff>:<</FADE>"));
-#endif /* !USE_CSS_FORMATTING */
-}
-END_TEST
-
-START_TEST(test_html_to_codes)
-{
-	assert_string_equal_free("plain",
-			yahoo_html_to_codes("plain"));
-	assert_string_equal_free("plain <peanut>",
-			yahoo_html_to_codes("plain &lt;peanut&gt;"));
-	assert_string_equal_free("plain <peanut",
-			yahoo_html_to_codes("plain &lt;peanut"));
-	assert_string_equal_free("plain> peanut",
-			yahoo_html_to_codes("plain&gt; peanut"));
-	assert_string_equal_free("plain >",
-			yahoo_html_to_codes("plain &gt;"));
-	assert_string_equal_free("plain > ",
-			yahoo_html_to_codes("plain &gt; "));
-	assert_string_equal_free("plain <",
-			yahoo_html_to_codes("plain &lt;"));
-	assert_string_equal_free("plain < ",
-			yahoo_html_to_codes("plain &lt; "));
-	assert_string_equal_free("plain &lt",
-			yahoo_html_to_codes("plain &lt"));
-	assert_string_equal_free("plain &",
-			yahoo_html_to_codes("plain &amp;"));
-
-	/* bold/italic/underline */
-	assert_string_equal_free("\x1B[1mbold\x1B[x1m",
-			yahoo_html_to_codes("<b>bold</b>"));
-	assert_string_equal_free("\x1B[2mitalic\x1B[x2m",
-			yahoo_html_to_codes("<i>italic</i>"));
-	assert_string_equal_free("\x1B[4munderline\x1B[x4m",
-			yahoo_html_to_codes("<u>underline</u>"));
-	assert_string_equal_free("no markup",
-			yahoo_html_to_codes("no</u> markup"));
-	assert_string_equal_free("\x1B[1mbold\x1B[x1m \x1B[2mitalic\x1B[x2m \x1B[4munderline\x1B[x4m",
-			yahoo_html_to_codes("<b>bold</b> <i>italic</i> <u>underline</u>"));
-	assert_string_equal_free("\x1B[1mbold \x1B[2mbolditalic\x1B[x2m\x1B[x1m\x1B[2m italic\x1B[x2m",
-			yahoo_html_to_codes("<b>bold <i>bolditalic</i></b><i> italic</i>"));
-	assert_string_equal_free("\x1B[1mbold \x1B[2mbolditalic\x1B[x2m\x1B[x1m\x1B[2m \x1B[4mitalicunderline\x1B[x4m\x1B[x2m",
-			yahoo_html_to_codes("<b>bold <i>bolditalic</i></b><i> <u>italicunderline</u></i>"));
-
-	/* link */
-	assert_string_equal_free("http://pidgin.im/",
-			yahoo_html_to_codes("<A HREF=\"http://pidgin.im/\">http://pidgin.im/</A>"));
-	assert_string_equal_free("mark@example.com",
-			yahoo_html_to_codes("<A HREF=\"mailto:mark@example.com\">mark@example.com</A>"));
-#if 0
-	assert_string_equal_free("Pidgin (http://pidgin.im/)",
-			yahoo_html_to_codes("<A HREF=\"http://pidgin.im/\">Pidgin</A>"));
-#endif
-
-	/* font nothing */
-	assert_string_equal_free("nothing",
-			yahoo_html_to_codes("<font>nothing</font>"));
-
-	/* font color */
-	assert_string_equal_free("\x1B[#E71414mred\x1B[#000000m",
-			yahoo_html_to_codes("<font color=\"#E71414\">red</font>"));
-	assert_string_equal_free("\x1B[#FF0000mred\x1B[#000000m \x1B[#0000FFmblue\x1B[#000000m black",
-			yahoo_html_to_codes("<font color=\"#FF0000\">red</font> <font color=\"#0000FF\">blue</font> black"));
-
-	/* font size */
-	assert_string_equal_free("<font size=\"10\">test</font>",
-			yahoo_html_to_codes("<font size=\"2\">test</font>"));
-	assert_string_equal_free("<font size=\"30\">test</font>",
-			yahoo_html_to_codes("<font size=\"6\">test</font>"));
-
-	/* combinations */
-	assert_string_equal_free("\x1B[#FF0000m<font size=\"8\">redsmall</font> rednormal\x1B[#000000m",
-			yahoo_html_to_codes("<font color=\"#FF0000\"><font size=\"1\">redsmall</font> rednormal</font>"));
-
-	assert_string_equal_free("\x1B[#FF0000m<font size=\"8\">redsmall</font> \x1B[#00FF00mgreennormal\x1B[#FF0000m rednormal\x1B[#000000m",
-			yahoo_html_to_codes("<font color=\"#FF0000\"><font size=\"1\">redsmall</font> <font color=\"#00FF00\">greennormal</font> rednormal</font>"));
-
-	assert_string_equal_free("\x1B[1mbold \x1B[#FF0000mred <font face=\"Comic Sans MS\" size=\"20\">larger \x1B[#000000mbacktoblack <font size=\"12\">normalsize</font>\x1B[#FF0000m</font>\x1B[#000000m\x1B[x1m",
-			yahoo_html_to_codes("<b>bold <font color=\"#FF0000\">red <font face=\"Comic Sans MS\" size=\"5\">larger <font color=\"#000000\">backtoblack <font size=\"3\">normalsize</font></font></font></font></b>"));
-
-	/* buzz/unknown tags */
-	assert_string_equal_free("<ding>",
-			yahoo_html_to_codes("<ding>"));
-	assert_string_equal_free("Unknown <tags>",
-			yahoo_html_to_codes("Unknown <tags>"));
-}
-END_TEST
-
-Suite *
-yahoo_util_suite(void)
-{
-	Suite *s;
-	TCase *tc;
-
-	s = suite_create("Yahoo Utility Functions");
-
-	tc = tcase_create("Convert IM from network format to HTML");
-	tcase_add_unchecked_fixture(tc, setup_codes_to_html, teardown_codes_to_html);
-	tcase_add_test(tc, test_codes_to_html);
-	suite_add_tcase(s, tc);
-
-	tc = tcase_create("Convert IM from HTML to network format");
-	tcase_add_test(tc, test_html_to_codes);
-	suite_add_tcase(s, tc);
-
-	return s;
-}
--- a/libpurple/tests/tests.h	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/tests/tests.h	Thu Oct 06 10:05:06 2016 -0400
@@ -14,7 +14,6 @@
 Suite * jabber_jutil_suite(void);
 Suite * jabber_scram_suite(void);
 Suite * oscar_util_suite(void);
-Suite * yahoo_util_suite(void);
 Suite * util_suite(void);
 Suite * xmlnode_suite(void);
 
--- a/libpurple/util.c	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/util.c	Thu Oct 06 10:05:06 2016 -0400
@@ -1882,7 +1882,6 @@
  * - \n should be converted to a normal space
  * - in addition to <br>, <p> and <div> etc. should also be converted into \n
  * - We want to turn </td>#whitespace<td> sequences into a single tab
- * - We want to turn <td> into a single tab (for msn profile "parsing")
  * - We want to turn </tr>#whitespace<tr> sequences into a single \n
  * - <script>...</script> and <style>...</style> should be completely removed
  */
--- a/libpurple/util.h	Wed Oct 05 22:15:51 2016 -0500
+++ b/libpurple/util.h	Thu Oct 06 10:05:06 2016 -0400
@@ -456,8 +456,8 @@
 /**
  * Extracts a field of data from HTML.
  *
- * This is a scary function. See protocols/msn/msn.c and
- * protocols/yahoo/yahoo_profile.c for example usage.
+ * This is a scary function. It used to be used for MSN and Yahoo prpls,
+ * but since those prpls have been removed, this is now deprecated.
  *
  * @param str            The string to parse.
  * @param len            The size of str.
--- a/pidgin.apspec.in	Wed Oct 05 22:15:51 2016 -0500
+++ b/pidgin.apspec.in	Thu Oct 06 10:05:06 2016 -0400
@@ -14,7 +14,7 @@
 
 [Description]
 Pidgin allows you to talk to anyone using a variety of messaging protocols,
-including AIM (Oscar and TOC), ICQ, IRC, Yahoo!, MSN Messenger, XMPP,
+including AIM (Oscar and TOC), ICQ, IRC, XMPP,
 Gadu-Gadu, and Zephyr. These protocols are implemented using a
 modular, easy to use design. To use a protocol, just add an account using the
 account editor.
@@ -23,7 +23,7 @@
 features, such as perl scripting, TCL scripting and C plugins.
 
 Pidgin is NOT affiliated with or endorsed by America Online, Inc., Microsoft
-Corporation, Yahoo! Inc., or ICQ Inc.
+Corporation, or ICQ Inc.
 
 [BuildPrepare]
 APBUILD_STATIC="Xss startup-notification-1" prepareBuild --enable-nss --enable-gnutls --enable-binreloc --disable-perl --disable-tcl --disable-gtktest --disable-glibtest --disable-vv  --disable-fortify
--- a/pidgin.spec.in	Wed Oct 05 22:15:51 2016 -0500
+++ b/pidgin.spec.in	Thu Oct 06 10:05:06 2016 -0400
@@ -161,7 +161,7 @@
 
 %description
 Pidgin allows you to talk to anyone using a variety of messaging
-protocols including AIM, MSN, Yahoo!, XMPP, Bonjour, Gadu-Gadu,
+protocols including AIM, XMPP, Bonjour, Gadu-Gadu,
 ICQ, IRC, Novell Groupwise, QQ, Lotus Sametime, SILC, Simple and
 Zephyr.  These protocols are implemented using a modular, easy to
 use design.  To use a protocol, just add an account using the
@@ -171,7 +171,7 @@
 unique features, such as perl scripting, TCL scripting and C plugins.
 
 Pidgin is not affiliated with or endorsed by America Online, Inc.,
-Microsoft Corporation, Yahoo! Inc., or ICQ Inc.
+Microsoft Corporation, or ICQ Inc.
 
 %description devel
 The pidgin-devel package contains the header files, developer
@@ -182,8 +182,8 @@
 libpurple contains the core IM support for IM clients such as Pidgin
 and Finch.
 
-libpurple supports a variety of messaging protocols including AIM, MSN,
-Yahoo!, XMPP, Bonjour, Gadu-Gadu, ICQ, IRC, Novell Groupwise, QQ,
+libpurple supports a variety of messaging protocols including AIM,
+XMPP, Bonjour, Gadu-Gadu, ICQ, IRC, Novell Groupwise, QQ,
 Lotus Sametime, SILC, Simple and Zephyr.
 
 %description -n libpurple-devel
--- a/pidgin/data/pidgin.appdata.xml.in	Wed Oct 05 22:15:51 2016 -0500
+++ b/pidgin/data/pidgin.appdata.xml.in	Thu Oct 06 10:05:06 2016 -0400
@@ -13,8 +13,8 @@
       chat networks simultaneously.
     </_p>
     <_p>
-      This means that you can be chatting with friends on MSN, talking to a
-      friend on Google Talk, and sitting in a Yahoo chat room all at the same
+      This means that you can be chatting with friends on AIM, talking to a
+      friend on Google Talk, and sitting in an IRC chat room all at the same
       time.
     </_p>
   </description>
--- a/pidgin/data/pidgin.desktop.in.in	Wed Oct 05 22:15:51 2016 -0500
+++ b/pidgin/data/pidgin.desktop.in.in	Thu Oct 06 10:05:06 2016 -0400
@@ -1,7 +1,7 @@
 [Desktop Entry]
 _Name=Pidgin Internet Messenger
 _GenericName=Internet Messenger
-_Comment=Chat over IM.  Supports AIM, Google Talk, Jabber/XMPP, MSN, Yahoo and more
+_Comment=Chat over IM.  Supports AIM, Google Talk, Jabber/XMPP, and more
 Exec=pidgin
 Icon=pidgin
 StartupNotify=true
--- a/pidgin/gtkaccount.c	Wed Oct 05 22:15:51 2016 -0500
+++ b/pidgin/gtkaccount.c	Thu Oct 06 10:05:06 2016 -0400
@@ -577,10 +577,6 @@
 			!strcmp(purple_account_user_split_get_text(split), _("Domain")))
 			value = "gmail.com";
 
-		if (value == NULL && g_object_get_data(G_OBJECT(item), "fakefacebook") &&
-			!strcmp(purple_account_user_split_get_text(split), _("Domain")))
-			value = "chat.facebook.com";
-
 		if (value != NULL)
 			gtk_entry_set_text(GTK_ENTRY(entry), value);
 	}
@@ -776,7 +772,7 @@
 {
 	PurpleAccountOption *option;
 	PurpleAccount *account;
-	GtkWidget *vbox, *check, *entry, *combo, *menu, *item;
+	GtkWidget *vbox, *check, *entry, *combo;
 	GList *list, *node;
 	gint i, idx, int_value;
 	GtkListStore *model;
@@ -815,9 +811,6 @@
 			gtk_label_new_with_mnemonic(_("Ad_vanced")), 1);
 	gtk_widget_show(vbox);
 
-	menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(dialog->protocol_menu));
-	item = gtk_menu_get_active(GTK_MENU(menu));
-
 	for (l = dialog->prpl_info->protocol_options; l != NULL; l = l->next)
 	{
 		option = (PurpleAccountOption *)l->data;
@@ -932,10 +925,6 @@
 				model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
 				opt_entry->widget = combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
 
-				if (g_object_get_data(G_OBJECT(item), "fakefacebook") &&
-					!strcmp(opt_entry->setting, "connection_security"))
-					str_value = "opportunistic_tls";
-
 				/* Loop through list of PurpleKeyValuePair items */
 				for (node = list; node != NULL; node = node->next) {
 					if (node->data != NULL) {
--- a/pidgin/gtkblist.c	Wed Oct 05 22:15:51 2016 -0500
+++ b/pidgin/gtkblist.c	Thu Oct 06 10:05:06 2016 -0400
@@ -2130,8 +2130,6 @@
 	char *alias    = NULL;
 	GList *aims    = NULL;
 	GList *icqs    = NULL;
-	GList *yahoos  = NULL;
-	GList *msns    = NULL;
 	GList *jabbers = NULL;
 
 	s = temp_vcard = g_strdup(vcard);
@@ -2171,7 +2169,6 @@
 		if (!strcmp(field, "FN"))
 			alias = g_strdup(value);
 		else if (!strcmp(field, "X-AIM") || !strcmp(field, "X-ICQ") ||
-				 !strcmp(field, "X-YAHOO") || !strcmp(field, "X-MSN") ||
 				 !strcmp(field, "X-JABBER"))
 		{
 			char **values = g_strsplit(value, ":", 0);
@@ -2183,10 +2180,6 @@
 					aims = g_list_append(aims, g_strdup(*im));
 				else if (!strcmp(field, "X-ICQ"))
 					icqs = g_list_append(icqs, g_strdup(*im));
-				else if (!strcmp(field, "X-YAHOO"))
-					yahoos = g_list_append(yahoos, g_strdup(*im));
-				else if (!strcmp(field, "X-MSN"))
-					msns = g_list_append(msns, g_strdup(*im));
 				else if (!strcmp(field, "X-JABBER"))
 					jabbers = g_list_append(jabbers, g_strdup(*im));
 			}
@@ -2197,8 +2190,7 @@
 
 	g_free(temp_vcard);
 
-	if (aims == NULL && icqs == NULL && yahoos == NULL &&
-		msns == NULL && jabbers == NULL)
+	if (aims == NULL && icqs == NULL && jabbers == NULL)
 	{
 		g_free(alias);
 
@@ -2207,8 +2199,6 @@
 
 	add_buddies_from_vcard("prpl-aim",    group, aims,    alias);
 	add_buddies_from_vcard("prpl-icq",    group, icqs,    alias);
-	add_buddies_from_vcard("prpl-yahoo",  group, yahoos,  alias);
-	add_buddies_from_vcard("prpl-msn",    group, msns,    alias);
 	add_buddies_from_vcard("prpl-jabber", group, jabbers, alias);
 
 	g_free(alias);
@@ -3796,7 +3786,7 @@
 
 		/* Nickname/Server Alias */
 		/* I'd like to only show this if there's a contact or buddy
-		 * alias, but many people on MSN set long nicknames, which
+		 * alias, but people often set long nicknames, which
 		 * get ellipsized, so the only way to see the whole thing is
 		 * to look at the tooltip. */
 		if (full && b->server_alias != NULL && b->server_alias[0] != '\0')
@@ -4022,14 +4012,12 @@
 
 	tune = purple_presence_get_status(p, "tune");
 	if (tune && purple_status_is_active(tune)) {
-		/* Only in MSN.
-		 * TODO: Replace "Tune" with generalized "Media" in 3.0. */
+		/* TODO: Replace "Tune" with generalized "Media" in 3.0. */
 		if (purple_status_get_attr_string(tune, "game") != NULL) {
 			path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "game.png", NULL);
 			return _pidgin_blist_get_cached_emblem(path);
 		}
-		/* Only in MSN.
-		 * TODO: Replace "Tune" with generalized "Media" in 3.0. */
+		/* TODO: Replace "Tune" with generalized "Media" in 3.0. */
 		if (purple_status_get_attr_string(tune, "office") != NULL) {
 			path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "office.png", NULL);
 			return _pidgin_blist_get_cached_emblem(path);
--- a/pidgin/gtkutils.c	Wed Oct 05 22:15:51 2016 -0500
+++ b/pidgin/gtkutils.c	Thu Oct 06 10:05:06 2016 -0400
@@ -677,7 +677,7 @@
 	GdkPixbuf *pixbuf = NULL;
 	GtkSizeGroup *sg;
 	GList *p;
-	const char *gtalk_name = NULL, *facebook_name = NULL;
+	const char *gtalk_name = NULL;
 	int i;
 
 	aop_menu = g_malloc0(sizeof(AopMenu));
@@ -688,7 +688,6 @@
 
 	if (purple_find_prpl("prpl-jabber")) {
 		gtalk_name = _("Google Talk");
-		facebook_name = _("Facebook (XMPP)");
 	}
 
 	for (p = purple_plugins_get_protocols(), i = 0;
@@ -720,29 +719,6 @@
 			i++;
 		}
 
-		if (facebook_name && strcmp(facebook_name, plugin->info->name) < 0) {
-			char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
-			                                  "16", "facebook.png", NULL);
-			GtkWidget *item;
-
-			pixbuf = pidgin_pixbuf_new_from_file(filename);
-			g_free(filename);
-
-			gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
-				item = aop_menu_item_new(sg, pixbuf, facebook_name, "prpl-jabber", "protocol"));
-			g_object_set_data(G_OBJECT(item), "fakefacebook", GINT_TO_POINTER(1));
-
-			if (pixbuf)
-				g_object_unref(pixbuf);
-
-			/* libpurple3 compatibility */
-			if (g_strcmp0(default_proto_id, "prpl-facebook-xmpp") == 0)
-				aop_menu->default_item = i;
-
-			facebook_name = NULL;
-			i++;
-		}
-
 		pixbuf = pidgin_create_prpl_icon_from_prpl(plugin, PIDGIN_PRPL_ICON_SMALL, NULL);
 
 		gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
--- a/pidgin/gtkwhiteboard.h	Wed Oct 05 22:15:51 2016 -0500
+++ b/pidgin/gtkwhiteboard.h	Thu Oct 06 10:05:06 2016 -0400
@@ -37,8 +37,6 @@
 #define BRUSH_STATE_DOWN    1
 #define BRUSH_STATE_MOTION  2
 
-/* XXX: This seems duplicated with the Yahoo! Doodle prpl code.
- * XXX: How should they work together? */
 #define PALETTE_NUM_COLORS  7
 
 /**
--- a/pidgin/pixmaps/Makefile.am	Wed Oct 05 22:15:51 2016 -0500
+++ b/pidgin/pixmaps/Makefile.am	Thu Oct 06 10:05:06 2016 -0400
@@ -166,10 +166,6 @@
 		emotes/default/24/scalable/mobile.svg \
 		emotes/default/24/scalable/monkey.svg \
 		emotes/default/24/scalable/moon.svg \
-		emotes/default/24/scalable/msn-away.svg \
-		emotes/default/24/scalable/msn-busy.svg \
-		emotes/default/24/scalable/msn_online.svg \
-		emotes/default/24/scalable/msn.svg \
 		emotes/default/24/scalable/musical-note.svg \
 		emotes/default/24/scalable/peace.svg \
 		emotes/default/24/scalable/phone.svg \
@@ -213,10 +209,8 @@
 		protocols/16/scalable/irc.svg \
 		protocols/16/scalable/jabber.svg \
 		protocols/16/scalable/meanwhile.svg \
-		protocols/16/scalable/msn.svg \
 		protocols/16/scalable/silc.svg \
 		protocols/16/scalable/simple.svg \
-		protocols/16/scalable/yahoo.svg \
 		protocols/16/scalable/zephyr.svg
 
 PROTOCOLS_16 = \
@@ -230,12 +224,8 @@
 		protocols/16/irc.png \
 		protocols/16/jabber.png \
 		protocols/16/meanwhile.png \
-		protocols/16/msn.png \
-		protocols/16/mxit.png \
-		protocols/16/myspace.png \
 		protocols/16/silc.png \
 		protocols/16/simple.png \
-		protocols/16/yahoo.png \
 		protocols/16/zephyr.png
 
 ICONS_16_SCALABLE = \
@@ -268,10 +258,8 @@
 		protocols/22/scalable/irc.svg \
 		protocols/22/scalable/jabber.svg \
 		protocols/22/scalable/meanwhile.svg \
-		protocols/22/scalable/msn.svg \
 		protocols/22/scalable/silc.svg \
 		protocols/22/scalable/simple.svg \
-		protocols/22/scalable/yahoo.svg \
 		protocols/22/scalable/zephyr.svg
 
 PROTOCOLS_22 = \
@@ -285,12 +273,8 @@
 		protocols/22/irc.png \
 		protocols/22/jabber.png \
 		protocols/22/meanwhile.png \
-		protocols/22/msn.png \
-		protocols/22/mxit.png \
-		protocols/22/myspace.png \
 		protocols/22/silc.png \
 		protocols/22/simple.png \
-		protocols/22/yahoo.png \
 		protocols/22/zephyr.png
 
 PROTOCOLS_48 = \
@@ -303,12 +287,8 @@
 		protocols/48/irc.png \
 		protocols/48/jabber.png \
 		protocols/48/meanwhile.png \
-		protocols/48/msn.png \
-		protocols/48/mxit.png \
-		protocols/48/myspace.png \
 		protocols/48/silc.png \
 		protocols/48/simple.png \
-		protocols/48/yahoo.png \
 		protocols/48/zephyr.png
 
 PROTOCOLS_SCALABLE = \
@@ -321,11 +301,8 @@
 		protocols/scalable/irc.svg \
 		protocols/scalable/jabber.svg \
 		protocols/scalable/meanwhile.svg \
-		protocols/scalable/msn.svg \
-		protocols/scalable/mxit.svg \
 		protocols/scalable/silc.svg \
 		protocols/scalable/simple.svg \
-		protocols/scalable/yahoo.svg \
 		protocols/scalable/zephyr.svg
 
 STATUS_11 = \
--- a/pidgin/pixmaps/emotes/default/24/Makefile.am	Wed Oct 05 22:15:51 2016 -0500
+++ b/pidgin/pixmaps/emotes/default/24/Makefile.am	Thu Oct 06 10:05:06 2016 -0400
@@ -113,10 +113,6 @@
     monkey.png \
     moon.png \
     mrgreen.png \
-    msn-away.png \
-    msn-busy.png \
-    msn_online.png \
-    msn.png \
     musical-note.png \
     music.png \
     nervous.png \
--- a/pidgin/pixmaps/emotes/default/24/default.theme.in	Wed Oct 05 22:15:51 2016 -0500
+++ b/pidgin/pixmaps/emotes/default/24/default.theme.in	Thu Oct 06 10:05:06 2016 -0400
@@ -100,95 +100,6 @@
 ! cyclops.png       O-)     o-)
 
 
-# Following Windows Live Messenger 8.1
-[MSN]
-happy.png           :)      :-)
-excited.png         :D      :d      :-D     :-d
-wink.png            ;)      ;-)
-shocked.png         :-O     :-o     :O      :o
-tongue.png          :-P     :P      :-p     :p
-glasses-cool.png    (H)     (h)
-angry.png           :@      :-@
-embarrassed.png     :$      :-$
-confused.png        :S      :s      :-S     :-s
-sad.png             :(      :-(
-crying.png          :'(
-neutral.png         :|      :-|
-devil.png           (6)
-angel.png           (A)     (a)
-in_love.png         (L)     (l)
-love-over.png       (U)     (u)
-msn.png             (M)     (m)
-cat.png             (@)
-dog.png             (&)
-moon.png            (S)
-star.png            (*)
-film.png            (~)
-musical-note.png    (8)
-mail.png            (E)     (e)
-rose.png            (F)     (f)
-rose-dead.png       (W)     (w)
-clock.png           (O)     (o)
-kiss.png            (K)     (k)
-present.png         (G)     (g)
-cake.png            (^)
-camera.png          (P)     (p)
-lamp.png            (I)     (i)
-coffee.png          (C)     (c)
-phone.png           (T)     (t)
-hug-left.png        ({)
-hug-right.png       (})
-beer.png            (B)     (b)
-drink.png           (D)     (d)
-boy.png             (Z)     (z)
-girl.png            (X)     (x)
-good.png            (Y)     (y)
-bad.png             (N)     (n)
-vampire.png         :[      :-[
-goat.png            (nah)
-sun.png             (#)
-rainbow.png         (R)     (r)
-quiet.png           :-#
-teeth.png           8o|
-glasses-nerdy.png   8-|
-sarcastic.png       ^o)
-secret.png          :-*
-sick.png            +o(
-snail.png           (sn)
-turtle.png          (tu)
-plate.png           (pl)
-bowl.png            (||)
-pizza.png           (pi)
-soccerball.png      (so)
-car.png             (au)
-airplane.png        (ap)
-umbrella.png        (um)
-island.png          (ip)
-computer.png        (co)
-mobile.png          (mp)
-brb.png             (brb)
-rain.png            (st)
-highfive.png        (h5)
-coins.png           (mo)
-sheep.png           (bah)
-dont-know.png       :^)
-thinking.png        *-)
-thunder.png         (li)
-party.png           <:o)
-eyeroll.png         8-)
-sleepy.png          |-) 
-bunny.png           ('.')
-! skywalker.png     C:-)    c:-)    C:)     c:)
-! monkey.png        :-(|)   :(|)    8-|)
-! cyclops.png       O-)     o-)
-
-# Hidden MSN emotes
-cigarette.png      	(ci)    (CI)
-handcuffs.png       (%)
-console.png			(xx)    (XX)
-fingers-crossed.png	(yn)    (YN)
-
-
 # Following QQ 2006
 [QQ]
 shocked.png         /:O      /jy       /surprised
@@ -324,266 +235,3 @@
 ! skywalker.png     C:-)    c:-)    C:)     c:)
 ! monkey.png        :-(|)   :(|)    8-|)
 ! cyclops.png       O-)     o-)
-
-
-# Following Yahoo! Messenger 8.1
-[Yahoo]
-happy.png           :)      :-)
-question.png        :-/     :-\\
-shocked.png         :-O     :O      :-o     :o 
-devil.png           >:)
-angel.png           O:-)    o:-)    0:-)
-sick.png            :-&
-sleepy.png          (:|
-hypnotized.png      @-)
-on-the-phone.png    :)]
-sad.png             :(      :-(
-amorous.png         :x      :-x     :X      :-X
-angry.png           X-(     x-(     X(      x(
-crying.png          :((
-glasses-nerdy.png   :-B     :-b
-quiet.png           :-$
-drool.png           =P~     =p~
-lying.png           :^O     :^o
-call-me.png         :-c
-wink.png            ;)      ;-)
-embarrassed.png     :">
-mean.png            :->     :>
-laugh.png           :))     :-))
-bye.png             =;
-arrogant.png        [-(
-thinking.png        :-?
-waiting.png         :-w     :-W
-at-wits-end.png     ~x(     ~X(
-excited.png         :D      :-D     :d      :-d
-tongue.png          :-P     :P      :-p     :p
-glasses-cool.png    B-)     b-)
-neutral.png         :|      :-|
-sleeping.png        I-)     i-)     |-)
-clown.png           :o)     :O)
-doh.png             #-o     #-O
-weep.png            :-<
-go-away.png         :-h
-lashes.png          ;;)
-kiss.png            :-*     :*
-confused.png        :-S     :-s
-sarcastic.png       /:)
-eyeroll.png         8-|
-silly.png           8-}
-clap.png            =D>     =d>
-mad-tongue.png      >:P     >:p
-time-out.png        :-t     :-T
-hug-left.png        >:D<    >:d<
-love-over.png       =((
-hot.png             #:-S    #:-s
-rotfl.png           =)) :-j :-J 
-loser.png           L-)     l-)
-party.png           <:-P    <:-p
-nervous.png         :-SS	:-Ss	:-sS	:-ss
-cowboy.png          <):)
-desire.png          8->
-! skywalker.png     C:-)    c:-)    C:)     c:)
-! monkey.png        :-(|)   :(|)    8-|)
-! cyclops.png       O-)     o-)
-
-# Hidden Yahoo emotes
-alien.png           =:)     >-)
-beat-up.png         b-(     B-(
-chicken.png         ~:>
-coffee.png          ~o)     ~O)
-cow.png             3:-O    3:-o
-dance.png           \\:D/   \\:d/
-rose.png            @};-
-dont-know.png       :-L     :-l
-skeleton.png        8-X     8-x
-lamp.png            *-:)
-monkey.png          :(|)
-coins.png           $-)
-peace.png           :)>-
-pig.png             :@)
-pray.png            [-o<    [-O<
-pumpkin.png         (~~)
-shame.png           [-X     [-x
-flag.png            **==
-clover.png          %%-
-musical-note.png    :-"
-giggle.png          ;))
-worship.png         ^:)^
-star.png            (*)
-waving.png          >:/
-talktohand.png      :-@
-
-# Only available after activating the Yahoo! Fighter IMVironment
-male-fighter1.png   o->     O->
-male-fighter2.png   o=>     O=>
-female-fighter.png  o-+     O-+
-yin-yang.png        (%)
-
-# Following Yahoo! Messenger 8.1
-[Yahoo JAPAN]
-happy.png           :)      :-)
-question.png        :-/     :-\\
-shocked.png         :-O     :O      :-o     :o 
-devil.png           >:)
-angel.png           O:-)    o:-)    0:-)
-sick.png            :-&
-sleepy.png          (:|
-hypnotized.png      @-)
-on-the-phone.png    :)]
-sad.png             :(      :-(
-amorous.png         :x      :-x     :X      :-X
-angry.png           X-(     x-(     X(      x(
-crying.png          :((
-glasses-nerdy.png   :-B     :-b
-quiet.png           :-$
-drool.png           =P~     =p~
-lying.png           :^O     :^o
-call-me.png         :-c
-wink.png            ;)      ;-)
-embarrassed.png     :">
-mean.png            :->     :>
-laugh.png           :))     :-))
-bye.png             =;
-arrogant.png        [-(
-thinking.png        :-?
-waiting.png         :-w     :-W
-at-wits-end.png     ~x(     ~X(
-excited.png         :D      :-D     :d      :-d
-tongue.png          :-P     :P      :-p     :p
-glasses-cool.png    B-)     b-)
-neutral.png         :|      :-|
-sleeping.png        I-)     i-)     |-)
-clown.png           :o)     :O)
-doh.png             #-o     #-O
-weep.png            :-<
-go-away.png         :-h
-lashes.png          ;;)
-kiss.png            :-*     :*
-confused.png        :-S     :-s
-sarcastic.png       /:)
-eyeroll.png         8-|
-silly.png           8-}
-clap.png            =D>     =d>
-mad-tongue.png      >:P     >:p
-time-out.png        :-t     :-T
-hug-left.png        >:D<    >:d<
-love-over.png       =((
-hot.png             #:-S    #:-s
-rotfl.png           =)) :-j :-J 
-loser.png           L-)     l-)
-party.png           <:-P    <:-p
-nervous.png         :-SS       :-Ss    :-sS    :-ss
-cowboy.png          <):)
-desire.png          8->
-! skywalker.png     C:-)    c:-)    C:)     c:)
-! monkey.png        :-(|)  :(|)
-
-# Hidden Yahoo emotes
-alien.png           =:)     >-)
-beat-up.png         b-(     B-(
-chicken.png         ~:>
-coffee.png          ~o)     ~O)
-cow.png             3:-O    3:-o
-dance.png           \\:D/   \\:d/
-rose.png            @};-
-dont-know.png       :-L     :-l
-skeleton.png        8-X     8-x
-lamp.png            *-:)
-monkey.png          :(|)
-coins.png           $-)
-peace.png           :)>-
-pig.png             :@)
-pray.png            [-o<    [-O<
-pumpkin.png         (~~)
-shame.png           [-X     [-x
-flag.png            **==
-clover.png          %%-
-musical-note.png    :-"
-giggle.png          ;))
-worship.png         ^:)^
-star.png            (*)
-waving.png          >:/
-talktohand.png      :-@
-
-# Only available after activating the Yahoo! Fighter IMVironment
-male-fighter1.png   o->     O->
-male-fighter2.png   o=>     O=>
-female-fighter.png  o-+     O-+
-yin-yang.png        (%)
-
-
-# Following MySpaceIM Beta 1.0.697.0
-[MySpaceIM]
-excited.png  	    :D      :-D
-devil.png	    }:)
-confused.png	    :Z
-glasses-nerdy.png   B)
-bulgy-eyes.png	    %)
-freaked-out.png	    :E
-happy.png	    :)      :-)
-amorous.png	    :X
-laugh.png	    :))
-mohawk.png	    -:
-mad-tongue.png	    X(
-messed.png	    X)
-glasses-nerdy.png   Q)
-doh.png		    :G
-pirate.png	    P)
-shocked.png	    :O
-sidefrown.png	    :{
-sinister.png	    :B
-smirk.png	    :,
-neutral.png	    :|
-tongue.png	    :P      :p
-pissed-off.png	    B|
-wink.png	    ;-)     ;)
-sad.png		    :[
-kiss.png            :x
-! skywalker.png     C:-)    c:-)    C:)     c:)
-! monkey.png        :-(|)   :(|)    8-|)
-! cyclops.png       O-)     o-)
-
-
-# MXit standard emoticons
-[MXit]
-happy.png           :-)     :)
-sad.png             :-(     :(
-wink.png            ;-)     ;)
-excited.png         :-D     :D     :->      :>
-neutral.png         :-|     :|
-shocked.png         :-O     :O
-tongue.png          :-P     :P
-embarrassed.png     :-$     :$
-glasses-cool.png    8-)
-in_love.png         (H)
-rose.png            (F)
-### Added in v3.0
-boy.png             (m)
-girl.png            (f)
-star.png            (*)
-chilli.png          (c)
-kiss.png            (x)
-lamp.png            (i)
-pissed-off.png      :e      :-e
-shut-mouth.png      :-x     :x
-thunder.png         (z)
-coffee.png          (U)
-mrgreen.png         (G)
-### Added in v5.0
-sick.png            :o(
-excruciating.png    :-{     :{
-amorous.png         :-}     :}
-eyeroll.png         8-o     8o
-crying.png          :'(
-thinking.png        :-?     :?
-drool.png           :-~     :~
-sleeping.png        :-z     :z
-lying.png           :L)
-glasses-nerdy.png   8-|     8|
-pirate.png          P-)
-### Added in v5.9.7
-bored.png           :-[     :[
-cold.png            :-<     :<
-confused.png        :-,     :,
-hungry.png          :-C     :C
-stressed.png        :-s     :s
Binary file pidgin/pixmaps/emotes/default/24/msn-away.png has changed
Binary file pidgin/pixmaps/emotes/default/24/msn-busy.png has changed
Binary file pidgin/pixmaps/emotes/default/24/msn.png has changed
Binary file pidgin/pixmaps/emotes/default/24/msn_online.png has changed
--- a/pidgin/pixmaps/emotes/default/24/scalable/msn-away.svg	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,290 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="24"
-   height="24"
-   id="svg2"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   version="1.0"
-   sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/emotes/scalable"
-   sodipodi:docname="msn-away.svg"
-   inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/emotes/msn/todo/msn_away.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
-  <defs
-     id="defs4">
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2239"
-       id="linearGradient1357"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.371983,0,0,0.372254,10.53035,10.56553)"
-       x1="15.602553"
-       y1="1.5657365"
-       x2="15.522223"
-       y2="33.483475" />
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2239">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop2241" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop2243" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3816">
-      <stop
-         style="stop-color:#000000;stop-opacity:1;"
-         offset="0"
-         id="stop3818" />
-      <stop
-         style="stop-color:#000000;stop-opacity:0;"
-         offset="1"
-         id="stop3820" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3816"
-       id="radialGradient3822"
-       cx="31.112698"
-       cy="19.008621"
-       fx="31.112698"
-       fy="19.008621"
-       r="8.6620579"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2228">
-      <stop
-         style="stop-color:#f56600;stop-opacity:1;"
-         offset="0"
-         id="stop2230" />
-      <stop
-         style="stop-color:#f56600;stop-opacity:0;"
-         offset="1"
-         id="stop2232" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2219">
-      <stop
-         style="stop-color:#3465a4;stop-opacity:1;"
-         offset="0"
-         id="stop2221" />
-      <stop
-         style="stop-color:#3465a4;stop-opacity:0;"
-         offset="1"
-         id="stop2223" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2219"
-       id="linearGradient2251"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.747158,0,0,0.74873,0.374035,0.608489)"
-       x1="9.9973583"
-       y1="14.918511"
-       x2="14.069712"
-       y2="18.218639" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2228"
-       id="linearGradient1330"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.782765,0,0,0.747651,1.035995,0.614065)"
-       x1="20.998175"
-       y1="11.741063"
-       x2="17.999571"
-       y2="18.866741" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="24.007725"
-     inkscape:cx="20.034795"
-     inkscape:cy="11.236512"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     fill="#edd400"
-     showguides="true"
-     inkscape:guide-bbox="true"
-     inkscape:window-width="1268"
-     inkscape:window-height="971"
-     inkscape:window-x="6"
-     inkscape:window-y="21" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1">
-    <path
-       d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1  22.45064,19.008621 A 8.6620579 8.6620579 0 1 1  39.774755 19.008621 z"
-       sodipodi:ry="8.6620579"
-       sodipodi:rx="8.6620579"
-       sodipodi:cy="19.008621"
-       sodipodi:cx="31.112698"
-       id="path4318"
-       style="opacity:0.4;color:#000000;fill:url(#radialGradient3822);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       sodipodi:type="arc"
-       transform="matrix(1.044119,0,0,0.346338,-18.44114,13.41659)" />
-    <path
-       style="opacity:1;fill:#edd400;fill-opacity:1;stroke:#c4a000;stroke-width:1.00000083;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 18.436518,9.9127618 C 21.037357,10.673309 21.362289,19.501337 18.407881,19.501337 C 15.489266,19.501337 8.9905421,7.150538 18.436518,9.9127618 z "
-       id="rect2194"
-       sodipodi:nodetypes="czs" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.96520001"
-       inkscape:original="M 15.59375 9.53125 C 10.549483 10.044796 15.852462 19.5 18.40625 19.5 C 21.360658 19.5 21.038339 10.666797 18.4375 9.90625 C 17.256753 9.560972 16.31436 9.4578863 15.59375 9.53125 z "
-       xlink:href="#rect2194"
-       style="opacity:0.5;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.00000024;stroke-miterlimit:4;stroke-opacity:1"
-       id="path2259"
-       inkscape:href="#rect2194"
-       d="M 16,10.75 C 15.512126,10.798024 15.253534,10.920051 15.09375,11.0625 C 14.933966,11.204949 14.83864,11.380838 14.78125,11.6875 C 14.66647,12.300825 14.844054,13.385232 15.3125,14.46875 C 15.780946,15.552268 16.512913,16.653582 17.21875,17.4375 C 17.924587,18.221418 18.67699,18.5625 18.75,18.5625 C 18.89196,18.5625 18.968845,18.54667 19.09375,18.4375 C 19.218655,18.32833 19.365593,18.098064 19.5,17.78125 C 19.768815,17.147621 19.923112,16.154119 19.90625,15.125 C 19.889388,14.095881 19.705611,13.023656 19.40625,12.25 C 19.106889,11.476344 18.724904,11.117253 18.53125,11.0625 C 17.425208,10.749781 16.582845,10.692627 16,10.75 z " />
-    <path
-       style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000083;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 13.316085,20.509475 C 10.851196,20.509475 4.3258741,14.508937 9.3204332,11.066555 C 14.310647,7.6271659 15.818731,20.509475 13.316085,20.509475 z "
-       id="rect2201"
-       sodipodi:nodetypes="czz" />
-    <path
-       style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 10.99506,11.498797 C 10.735658,11.486846 10.370038,11.588319 9.8835883,11.932121 C 8.8737,12.645867 8.5374239,13.351301 8.4999186,14.121547 C 8.4624133,14.891791 8.7901654,15.780902 9.3391937,16.607457 C 9.8882225,17.43401 10.661309,18.195719 11.403357,18.728462 C 12.145404,19.261206 12.809412,19.500227 13.070994,19.500227 C 13.222335,19.500227 13.331682,19.0625 13.39947,18.682848 C 13.535046,17.923542 13.548476,16.808781 13.376787,15.695196 C 13.205098,14.58161 12.846108,13.444035 12.401414,12.661929 C 11.95672,11.879824 11.481565,11.52121 10.99506,11.498797 z "
-       id="path2254"
-       sodipodi:nodetypes="cssssssssc" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.99454969"
-       inkscape:original="M 19.8125 2.53125 C 16.600144 3.1011521 12.46875 9.9375003 12.46875 9.9375 L 14.46875 14.5 C 18.173566 14.5 20.656251 12.6875 20.65625 12.6875 C 20.65625 12.6875 24.40713 4.4120618 21.125 2.6875 C 20.718044 2.4736692 20.271408 2.4498354 19.8125 2.53125 z "
-       xlink:href="#rect1317"
-       style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       id="path2245"
-       inkscape:href="#rect1317"
-       d="M 20,3.5 C 18.995087,3.678281 17.104383,5.3426949 15.71875,7.0625 C 14.498278,8.5773128 13.796939,9.7027104 13.59375,10.03125 L 15.0625,13.375 C 17.799931,13.187054 19.57299,12.186552 19.84375,12 C 19.951969,11.755173 20.691026,10.13991 21.15625,8.125 C 21.405718,7.0445423 21.52736,5.9263632 21.4375,5.09375 C 21.34764,4.2611368 21.117806,3.8050199 20.65625,3.5625 C 20.487599,3.4738843 20.316754,3.4438049 20,3.5 z " />
-    <path
-       style="opacity:1;fill:url(#linearGradient2251);fill-opacity:1;stroke:#204a87;stroke-width:1.00000036;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 1.7306799,5.8222291 C 3.0741729,3.5659039 16.882213,13.11203 11.087148,14.375153 C 5.2996209,15.636634 0.40087698,8.0555627 1.7306799,5.8222291 z "
-       id="rect2197"
-       sodipodi:nodetypes="czz" />
-    <path
-       style="opacity:0.2;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 2.7390794,8.1722341 C 3.0496879,9.0060223 3.6590736,9.9821112 4.4574474,10.857929 C 6.0541952,12.609562 8.35926,13.89948 10.765977,13.389526 C 11.255672,13.285765 11.400406,13.151715 11.448617,13.081331 C 11.496824,13.010949 11.537361,12.912219 11.448617,12.641053 C 11.271127,12.098721 10.521911,11.132591 9.4713148,10.219525 C 8.4207206,9.3064602 7.0856043,8.3957283 5.8462653,7.7099423 C 4.6069262,7.0241566 3.3045923,6.5498939 2.7239802,6.4956482 C 2.4148401,6.4667656 2.428471,7.3384455 2.7390794,8.1722341 z "
-       id="path2249"
-       sodipodi:nodetypes="cssssssss" />
-    <path
-       style="opacity:1;fill:url(#linearGradient1330);fill-opacity:1;stroke:#ce5d00;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 12.478485,9.9508709 C 12.478485,9.9508709 17.866649,0.9861607 21.122294,2.6968071 C 24.404423,4.4213689 20.644961,12.673483 20.644961,12.673483 C 20.644961,12.673483 18.181394,14.512366 14.476578,14.512366 L 12.478485,9.9508709 z "
-       id="rect1317"
-       sodipodi:nodetypes="czccc" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.99298751"
-       inkscape:original="M 19.8125 2.53125 C 16.600144 3.1011521 12.46875 9.9375003 12.46875 9.9375 L 14.46875 14.5 C 18.173566 14.5 20.656251 12.6875 20.65625 12.6875 C 20.65625 12.6875 24.40713 4.4120618 21.125 2.6875 C 20.718044 2.4736692 20.271408 2.4498354 19.8125 2.53125 z "
-       xlink:href="#rect1317"
-       style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-       id="path1328"
-       inkscape:href="#rect1317"
-       d="M 20,3.5 C 18.994143,3.6784485 17.104459,5.3425998 15.71875,7.0625 C 14.49821,8.5773965 13.796948,9.7026949 13.59375,10.03125 L 15.0625,13.375 C 17.800353,13.18702 19.57294,12.186586 19.84375,12 C 19.951976,11.755161 20.690984,10.140091 21.15625,8.125 C 21.40574,7.0444453 21.527392,5.9266549 21.4375,5.09375 C 21.347608,4.2608451 21.11837,3.8053161 20.65625,3.5625 C 20.487225,3.4736876 20.316977,3.4437653 20,3.5 z " />
-    <path
-       sodipodi:type="arc"
-       style="opacity:1;fill:#75507b;fill-opacity:1;stroke:#5c3566;stroke-width:1.35211551;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path2192"
-       sodipodi:cx="13.4375"
-       sodipodi:cy="15.825892"
-       sodipodi:rx="0.8035714"
-       sodipodi:ry="5.1116071"
-       d="M 14.241071 15.825892 A 0.8035714 5.1116071 0 1 1  12.633929,15.825892 A 0.8035714 5.1116071 0 1 1  14.241071 15.825892 z"
-       transform="matrix(0.603448,-0.487879,0.280285,0.679821,0.46572,8.794406)" />
-    <image
-       id="image2210"
-       height="8"
-       width="8"
-       sodipodi:absref="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       xlink:href="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       x="-16"
-       y="14" />
-    <path
-       sodipodi:type="arc"
-       style="color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:#204a87;stroke-width:2.39076138px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       id="path1339"
-       sodipodi:cx="15.590227"
-       sodipodi:cy="16.57217"
-       sodipodi:rx="14.345175"
-       sodipodi:ry="14.345175"
-       d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1  1.2450523,16.57217 A 14.345175 14.345175 0 1 1  29.935402 16.57217 z"
-       transform="matrix(0.418279,0,0,0.41827,9.969451,9.594492)" />
-    <path
-       sodipodi:type="arc"
-       style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#204a87;stroke-width:3.58355522px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       id="path1341"
-       sodipodi:cx="15.590227"
-       sodipodi:cy="16.57217"
-       sodipodi:rx="14.345175"
-       sodipodi:ry="14.345175"
-       d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1  1.2450523,16.57217 A 14.345175 14.345175 0 1 1  29.935402 16.57217 z"
-       transform="matrix(0.27909,0,0,0.279013,12.14008,11.90447)" />
-    <path
-       sodipodi:type="arc"
-       style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#2e3436;stroke-width:14.28468895px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       id="path2216"
-       sodipodi:cx="15.590227"
-       sodipodi:cy="16.57217"
-       sodipodi:rx="14.345175"
-       sodipodi:ry="14.345175"
-       d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1  1.2450523,16.57217 A 14.345175 14.345175 0 1 1  29.935402 16.57217 z"
-       transform="matrix(7.000599e-2,0,0,7.000603e-2,15.40087,15.36409)" />
-    <path
-       style="opacity:0.5;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient1357);stroke-width:0.99999857px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       d="M 21.500001,16.521601 C 21.500001,19.293526 19.251968,21.543204 16.482071,21.543204 C 13.712174,21.543204 11.464141,19.293526 11.464141,16.521601 C 11.464141,13.749677 13.712174,11.499999 16.482071,11.499999 C 19.251968,11.499999 21.500001,13.749677 21.500001,16.521601 z "
-       id="path2220" />
-    <path
-       sodipodi:type="arc"
-       style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path1588"
-       sodipodi:cx="20.264311"
-       sodipodi:cy="14.476474"
-       sodipodi:rx="2.9448855"
-       sodipodi:ry="0.78724658"
-       d="M 23.209196 14.476474 A 2.9448855 0.78724658 0 1 1  17.319425,14.476474 A 2.9448855 0.78724658 0 1 1  23.209196 14.476474 z"
-       transform="matrix(-6.220304e-17,-0.509358,0.635129,5.747536e-7,7.296084,24.84778)" />
-    <path
-       sodipodi:type="arc"
-       style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path1362"
-       sodipodi:cx="20.264311"
-       sodipodi:cy="14.476474"
-       sodipodi:rx="2.9448855"
-       sodipodi:ry="0.78724658"
-       d="M 23.209196 14.476474 A 2.9448855 0.78724658 0 1 1  17.319425,14.476474 A 2.9448855 0.78724658 0 1 1  23.209196 14.476474 z"
-       transform="matrix(0.509357,-6.171994e-17,-5.747534e-7,0.63513,8.168748,7.331552)" />
-  </g>
-</svg>
--- a/pidgin/pixmaps/emotes/default/24/scalable/msn-busy.svg	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,287 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="24"
-   height="24"
-   id="svg2"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   version="1.0"
-   sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/emotes/scalable"
-   sodipodi:docname="msn-busy.svg"
-   inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/emotes/msn/todo/msn_occ.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
-  <defs
-     id="defs4">
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2239"
-       id="linearGradient2345"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.370788,0,0,0.370892,10.56557,10.55964)"
-       x1="15.535398"
-       y1="1.8014067"
-       x2="15.535398"
-       y2="48.674999" />
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2186">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop2188" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop2190" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2186"
-       id="linearGradient2343"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.525701,0,0,0.525844,10.18726,10.18624)"
-       x1="11.226587"
-       y1="-5.4832759"
-       x2="11.226587"
-       y2="17.697369" />
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2239">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop2241" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop2243" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3816">
-      <stop
-         style="stop-color:#000000;stop-opacity:1;"
-         offset="0"
-         id="stop3818" />
-      <stop
-         style="stop-color:#000000;stop-opacity:0;"
-         offset="1"
-         id="stop3820" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3816"
-       id="radialGradient3822"
-       cx="31.112698"
-       cy="19.008621"
-       fx="31.112698"
-       fy="19.008621"
-       r="8.6620579"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2228">
-      <stop
-         style="stop-color:#f56600;stop-opacity:1;"
-         offset="0"
-         id="stop2230" />
-      <stop
-         style="stop-color:#f56600;stop-opacity:0;"
-         offset="1"
-         id="stop2232" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2219">
-      <stop
-         style="stop-color:#3465a4;stop-opacity:1;"
-         offset="0"
-         id="stop2221" />
-      <stop
-         style="stop-color:#3465a4;stop-opacity:0;"
-         offset="1"
-         id="stop2223" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2219"
-       id="linearGradient2251"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.747158,0,0,0.74873,0.374035,0.608489)"
-       x1="9.9973583"
-       y1="14.918511"
-       x2="14.069712"
-       y2="18.218639" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2228"
-       id="linearGradient1330"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.782765,0,0,0.747651,1.035995,0.614065)"
-       x1="20.998175"
-       y1="11.741063"
-       x2="17.999571"
-       y2="18.866741" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="24.007725"
-     inkscape:cx="24.82492"
-     inkscape:cy="10.486753"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     fill="#edd400"
-     showguides="true"
-     inkscape:guide-bbox="true"
-     inkscape:window-width="1268"
-     inkscape:window-height="971"
-     inkscape:window-x="6"
-     inkscape:window-y="21" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1">
-    <path
-       d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1  22.45064,19.008621 A 8.6620579 8.6620579 0 1 1  39.774755 19.008621 z"
-       sodipodi:ry="8.6620579"
-       sodipodi:rx="8.6620579"
-       sodipodi:cy="19.008621"
-       sodipodi:cx="31.112698"
-       id="path4318"
-       style="opacity:0.4;color:#000000;fill:url(#radialGradient3822);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       sodipodi:type="arc"
-       transform="matrix(1.044119,0,0,0.346338,-18.44114,13.41659)" />
-    <path
-       style="opacity:1;fill:#edd400;fill-opacity:1;stroke:#c4a000;stroke-width:1.00000083;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 18.436518,9.9127618 C 21.037357,10.673309 21.362289,19.501337 18.407881,19.501337 C 15.489266,19.501337 8.9905421,7.150538 18.436518,9.9127618 z "
-       id="rect2194"
-       sodipodi:nodetypes="czs" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.96520001"
-       inkscape:original="M 15.59375 9.53125 C 10.549483 10.044796 15.852462 19.5 18.40625 19.5 C 21.360658 19.5 21.038339 10.666797 18.4375 9.90625 C 17.256753 9.560972 16.31436 9.4578863 15.59375 9.53125 z "
-       xlink:href="#rect2194"
-       style="opacity:0.5;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.00000024;stroke-miterlimit:4;stroke-opacity:1"
-       id="path2259"
-       inkscape:href="#rect2194"
-       d="M 16,10.75 C 15.512126,10.798024 15.253534,10.920051 15.09375,11.0625 C 14.933966,11.204949 14.83864,11.380838 14.78125,11.6875 C 14.66647,12.300825 14.844054,13.385232 15.3125,14.46875 C 15.780946,15.552268 16.512913,16.653582 17.21875,17.4375 C 17.924587,18.221418 18.67699,18.5625 18.75,18.5625 C 18.89196,18.5625 18.968845,18.54667 19.09375,18.4375 C 19.218655,18.32833 19.365593,18.098064 19.5,17.78125 C 19.768815,17.147621 19.923112,16.154119 19.90625,15.125 C 19.889388,14.095881 19.705611,13.023656 19.40625,12.25 C 19.106889,11.476344 18.724904,11.117253 18.53125,11.0625 C 17.425208,10.749781 16.582845,10.692627 16,10.75 z " />
-    <path
-       style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000083;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 13.316085,20.509475 C 10.851196,20.509475 4.3258741,14.508937 9.3204332,11.066555 C 14.310647,7.6271659 15.818731,20.509475 13.316085,20.509475 z "
-       id="rect2201"
-       sodipodi:nodetypes="czz" />
-    <path
-       style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 10.99506,11.498797 C 10.735658,11.486846 10.370038,11.588319 9.8835883,11.932121 C 8.8737,12.645867 8.5374239,13.351301 8.4999186,14.121547 C 8.4624133,14.891791 8.7901654,15.780902 9.3391937,16.607457 C 9.8882225,17.43401 10.661309,18.195719 11.403357,18.728462 C 12.145404,19.261206 12.809412,19.500227 13.070994,19.500227 C 13.222335,19.500227 13.331682,19.0625 13.39947,18.682848 C 13.535046,17.923542 13.548476,16.808781 13.376787,15.695196 C 13.205098,14.58161 12.846108,13.444035 12.401414,12.661929 C 11.95672,11.879824 11.481565,11.52121 10.99506,11.498797 z "
-       id="path2254"
-       sodipodi:nodetypes="cssssssssc" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.99454969"
-       inkscape:original="M 19.8125 2.53125 C 16.600144 3.1011521 12.46875 9.9375003 12.46875 9.9375 L 14.46875 14.5 C 18.173566 14.5 20.656251 12.6875 20.65625 12.6875 C 20.65625 12.6875 24.40713 4.4120618 21.125 2.6875 C 20.718044 2.4736692 20.271408 2.4498354 19.8125 2.53125 z "
-       xlink:href="#rect1317"
-       style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       id="path2245"
-       inkscape:href="#rect1317"
-       d="M 20,3.5 C 18.995087,3.678281 17.104383,5.3426949 15.71875,7.0625 C 14.498278,8.5773128 13.796939,9.7027104 13.59375,10.03125 L 15.0625,13.375 C 17.799931,13.187054 19.57299,12.186552 19.84375,12 C 19.951969,11.755173 20.691026,10.13991 21.15625,8.125 C 21.405718,7.0445423 21.52736,5.9263632 21.4375,5.09375 C 21.34764,4.2611368 21.117806,3.8050199 20.65625,3.5625 C 20.487599,3.4738843 20.316754,3.4438049 20,3.5 z " />
-    <path
-       style="opacity:1;fill:url(#linearGradient2251);fill-opacity:1;stroke:#204a87;stroke-width:1.00000036;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 1.7306799,5.8222291 C 3.0741729,3.5659039 16.882213,13.11203 11.087148,14.375153 C 5.2996209,15.636634 0.40087698,8.0555627 1.7306799,5.8222291 z "
-       id="rect2197"
-       sodipodi:nodetypes="czz" />
-    <path
-       style="opacity:0.2;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 2.7390794,8.1722341 C 3.0496879,9.0060223 3.6590736,9.9821112 4.4574474,10.857929 C 6.0541952,12.609562 8.35926,13.89948 10.765977,13.389526 C 11.255672,13.285765 11.400406,13.151715 11.448617,13.081331 C 11.496824,13.010949 11.537361,12.912219 11.448617,12.641053 C 11.271127,12.098721 10.521911,11.132591 9.4713148,10.219525 C 8.4207206,9.3064602 7.0856043,8.3957283 5.8462653,7.7099423 C 4.6069262,7.0241566 3.3045923,6.5498939 2.7239802,6.4956482 C 2.4148401,6.4667656 2.428471,7.3384455 2.7390794,8.1722341 z "
-       id="path2249"
-       sodipodi:nodetypes="cssssssss" />
-    <path
-       style="opacity:1;fill:url(#linearGradient1330);fill-opacity:1;stroke:#ce5d00;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 12.478485,9.9508709 C 12.478485,9.9508709 17.866649,0.9861607 21.122294,2.6968071 C 24.404423,4.4213689 20.644961,12.673483 20.644961,12.673483 C 20.644961,12.673483 18.181394,14.512366 14.476578,14.512366 L 12.478485,9.9508709 z "
-       id="rect1317"
-       sodipodi:nodetypes="czccc" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.99298751"
-       inkscape:original="M 19.8125 2.53125 C 16.600144 3.1011521 12.46875 9.9375003 12.46875 9.9375 L 14.46875 14.5 C 18.173566 14.5 20.656251 12.6875 20.65625 12.6875 C 20.65625 12.6875 24.40713 4.4120618 21.125 2.6875 C 20.718044 2.4736692 20.271408 2.4498354 19.8125 2.53125 z "
-       xlink:href="#rect1317"
-       style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-       id="path1328"
-       inkscape:href="#rect1317"
-       d="M 20,3.5 C 18.994143,3.6784485 17.104459,5.3425998 15.71875,7.0625 C 14.49821,8.5773965 13.796948,9.7026949 13.59375,10.03125 L 15.0625,13.375 C 17.800353,13.18702 19.57294,12.186586 19.84375,12 C 19.951976,11.755161 20.690984,10.140091 21.15625,8.125 C 21.40574,7.0444453 21.527392,5.9266549 21.4375,5.09375 C 21.347608,4.2608451 21.11837,3.8053161 20.65625,3.5625 C 20.487225,3.4736876 20.316977,3.4437653 20,3.5 z " />
-    <path
-       sodipodi:type="arc"
-       style="opacity:1;fill:#75507b;fill-opacity:1;stroke:#5c3566;stroke-width:1.35211551;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path2192"
-       sodipodi:cx="13.4375"
-       sodipodi:cy="15.825892"
-       sodipodi:rx="0.8035714"
-       sodipodi:ry="5.1116071"
-       d="M 14.241071 15.825892 A 0.8035714 5.1116071 0 1 1  12.633929,15.825892 A 0.8035714 5.1116071 0 1 1  14.241071 15.825892 z"
-       transform="matrix(0.603448,-0.487879,0.280285,0.679821,0.46572,8.794406)" />
-    <image
-       id="image2210"
-       height="8"
-       width="8"
-       sodipodi:absref="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       xlink:href="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       x="-16"
-       y="14" />
-    <path
-       sodipodi:type="arc"
-       style="color:#000000;fill:#ef2929;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36561811px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       id="path1311"
-       sodipodi:cx="15.590227"
-       sodipodi:cy="16.57217"
-       sodipodi:rx="14.345175"
-       sodipodi:ry="14.345175"
-       d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1  1.2450523,16.57217 A 14.345175 14.345175 0 1 1  29.935402 16.57217 z"
-       transform="matrix(0.428768,0,0,0.428768,9.892003,9.386493)" />
-    <path
-       sodipodi:type="arc"
-       style="color:#000000;fill:#ef2929;fill-opacity:1;fill-rule:evenodd;stroke:#a40000;stroke-width:2.39228702px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       id="path2325"
-       sodipodi:cx="15.590227"
-       sodipodi:cy="16.57217"
-       sodipodi:rx="14.345175"
-       sodipodi:ry="14.345175"
-       d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1  1.2450523,16.57217 A 14.345175 14.345175 0 1 1  29.935402 16.57217 z"
-       transform="matrix(0.418007,0,0,0.418014,9.979183,9.569085)" />
-    <path
-       style="opacity:0.6;color:#000000;fill:url(#linearGradient2343);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2345);stroke-width:0.99999946px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       d="M 21.5,16.493913 C 21.5,19.255693 19.259185,21.497138 16.498179,21.497138 C 13.737175,21.497138 11.496359,19.255693 11.496359,16.493913 C 11.496359,13.732133 13.737175,11.490689 16.498179,11.490689 C 19.259185,11.490689 21.5,13.732133 21.5,16.493913 z "
-       id="path2327" />
-    <path
-       style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#a40000;stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       d="M 20.496182,16.458239 C 20.496182,17.703608 20.024622,17.483447 16.462297,17.483447 C 12.933743,17.483447 12.495999,17.683305 12.495999,16.513032 C 12.495999,15.324498 13.508591,15.534349 16.49609,15.534349 C 19.461295,15.534349 20.496182,15.194605 20.496182,16.458239 z "
-       id="path2329"
-       sodipodi:nodetypes="czzzz" />
-  </g>
-</svg>
--- a/pidgin/pixmaps/emotes/default/24/scalable/msn.svg	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,398 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="24"
-   height="24"
-   id="svg2"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   version="1.0"
-   sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/emotes/scalable"
-   sodipodi:docname="msn.svg"
-   inkscape:export-filename="/home/hbons/Desktop/Pidgin objects refresh/msn.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
-  <defs
-     id="defs4">
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3365">
-      <stop
-         style="stop-color:#5c3566;stop-opacity:1;"
-         offset="0"
-         id="stop3367" />
-      <stop
-         style="stop-color:#8b509a;stop-opacity:1"
-         offset="1"
-         id="stop3369" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3351">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop3353" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop3355" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3343">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop3345" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop3347" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3335">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop3337" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop3339" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3327">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop3329" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop3331" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3319">
-      <stop
-         style="stop-color:#4e9a06;stop-opacity:1;"
-         offset="0"
-         id="stop3321" />
-      <stop
-         style="stop-color:#346703;stop-opacity:1"
-         offset="1"
-         id="stop3323" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3311">
-      <stop
-         style="stop-color:#c4a000;stop-opacity:1;"
-         offset="0"
-         id="stop3313" />
-      <stop
-         style="stop-color:#8d7300;stop-opacity:1"
-         offset="1"
-         id="stop3315" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3303">
-      <stop
-         style="stop-color:#275ba7;stop-opacity:1"
-         offset="0"
-         id="stop3305" />
-      <stop
-         style="stop-color:#193a6b;stop-opacity:1"
-         offset="1"
-         id="stop3307" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3295">
-      <stop
-         style="stop-color:#ce5d00;stop-opacity:1;"
-         offset="0"
-         id="stop3297" />
-      <stop
-         style="stop-color:#934200;stop-opacity:1"
-         offset="1"
-         id="stop3299" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2228">
-      <stop
-         style="stop-color:#f56600;stop-opacity:1;"
-         offset="0"
-         id="stop2230" />
-      <stop
-         style="stop-color:#f56600;stop-opacity:0;"
-         offset="1"
-         id="stop2232" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2219">
-      <stop
-         style="stop-color:#3465a4;stop-opacity:1;"
-         offset="0"
-         id="stop2221" />
-      <stop
-         style="stop-color:#3465a4;stop-opacity:0;"
-         offset="1"
-         id="stop2223" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2219"
-       id="linearGradient2251"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.7478375,0,0,0.74565,0.362245,0.6499215)"
-       x1="9.9973583"
-       y1="14.918511"
-       x2="14.069712"
-       y2="18.218639" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2228"
-       id="linearGradient1330"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.7836824,0,0,0.7456274,1.0441002,0.6393144)"
-       x1="20.998175"
-       y1="11.741063"
-       x2="17.999571"
-       y2="18.866741" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3295"
-       id="linearGradient3301"
-       x1="13.499517"
-       y1="5.7508841"
-       x2="19.822943"
-       y2="12.873591"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3303"
-       id="linearGradient3309"
-       x1="6.1233511"
-       y1="9.0836287"
-       x2="7.5831451"
-       y2="12.665809"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3311"
-       id="linearGradient3317"
-       x1="17.831778"
-       y1="15.212441"
-       x2="19.213747"
-       y2="18.711315"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3319"
-       id="linearGradient3325"
-       x1="11.485289"
-       y1="15.208427"
-       x2="11.709392"
-       y2="19.748632"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3327"
-       id="linearGradient3333"
-       x1="4.0816622"
-       y1="6.3746572"
-       x2="12.001054"
-       y2="14.330429"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3335"
-       id="linearGradient3341"
-       x1="17.539385"
-       y1="6.8022232"
-       x2="18.413244"
-       y2="13.875"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3343"
-       id="linearGradient3349"
-       x1="10.121327"
-       y1="15.499049"
-       x2="15.003057"
-       y2="20.74736"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3351"
-       id="linearGradient3357"
-       x1="17.87402"
-       y1="15.548746"
-       x2="19.074448"
-       y2="19.297539"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3365"
-       id="linearGradient3371"
-       x1="11.89096"
-       y1="10.121053"
-       x2="13.943691"
-       y2="15.952509"
-       gradientUnits="userSpaceOnUse" />
-    <filter
-       inkscape:collect="always"
-       id="filter3524"
-       x="-0.16498175"
-       width="1.3299635"
-       y="-0.25116625"
-       height="1.5023325">
-      <feGaussianBlur
-         inkscape:collect="always"
-         stdDeviation="0.58412235"
-         id="feGaussianBlur3526" />
-    </filter>
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="24.007725"
-     inkscape:cx="15.55707"
-     inkscape:cy="12.527763"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     fill="#edd400"
-     showguides="true"
-     inkscape:guide-bbox="true"
-     inkscape:window-width="1268"
-     inkscape:window-height="842"
-     inkscape:window-x="4"
-     inkscape:window-y="24"
-     inkscape:snap-nodes="false"
-     inkscape:snap-bbox="true"
-     objecttolerance="10"
-     gridtolerance="10">
-    <inkscape:grid
-       type="xygrid"
-       id="grid2523"
-       empspacing="5"
-       visible="true"
-       enabled="true" />
-  </sodipodi:namedview>
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1">
-    <path
-       transform="matrix(1.529904,0,0,0.8958107,-7.1225487,2.8886031)"
-       sodipodi:type="arc"
-       style="opacity:0.51;color:#000000;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;filter:url(#filter3524)"
-       id="path3373"
-       sodipodi:cx="14.786907"
-       sodipodi:cy="18.543423"
-       sodipodi:rx="4.2486324"
-       sodipodi:ry="2.7907684"
-       d="m 19.03554,18.543423 a 4.2486324,2.7907684 0 1 1 -8.4972649,0 4.2486324,2.7907684 0 1 1 8.4972649,0 z" />
-    <path
-       style="opacity:1;fill:#edd400;fill-opacity:1;stroke:url(#linearGradient3317);stroke-width:1.00000083000000006;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 18.434458,9.9114244 C 21.035297,10.671972 21.360229,19.5 18.405821,19.5 15.487206,19.5 8.9884822,7.1492006 18.434458,9.9114244 z"
-       id="rect2194"
-       sodipodi:nodetypes="czs" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.96520001"
-       inkscape:original="M 15.59375 9.53125 C 10.549483 10.044796 15.852462 19.5 18.40625 19.5 C 21.360658 19.5 21.038339 10.666797 18.4375 9.90625 C 17.256753 9.560972 16.31436 9.4578863 15.59375 9.53125 z "
-       xlink:href="#rect2194"
-       style="opacity:0.50000000000000000;fill:none;stroke:url(#linearGradient3357);stroke-width:1.00000024000000010;stroke-miterlimit:4;stroke-opacity:1"
-       id="path2259"
-       inkscape:href="#rect2194"
-       d="m 15.6875,10.5 c -0.473603,0.048216 -0.717991,0.167321 -0.875,0.3125 -0.157009,0.145179 -0.254582,0.333993 -0.3125,0.65625 -0.115836,0.644514 0.066506,1.762661 0.53125,2.875 0.464744,1.112339 1.177275,2.228538 1.875,3.03125 0.697725,0.802712 1.457149,1.15625 1.5,1.15625 0.128818,0 0.189747,-0.014042 0.3125,-0.125 0.122753,-0.110958 0.272186,-0.329464 0.40625,-0.65625 0.268128,-0.653572 0.422914,-1.695064 0.40625,-2.75 -0.016664,-1.054936 -0.202643,-2.142617 -0.5,-2.9375 -0.297357,-0.794883 -0.702716,-1.16837 -0.875,-1.21875 C 17.058619,10.522777 16.233116,10.444452 15.6875,10.5 z" />
-    <path
-       style="fill:#73d216;fill-opacity:1;stroke:url(#linearGradient3325);stroke-width:1.00000072000000007;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 13.312869,20.5 C 10.84934,20.5 4.3276171,14.515416 9.3194212,11.082187 14.306882,7.6519426 15.814134,20.5 13.312869,20.5 z"
-       id="rect2201"
-       sodipodi:nodetypes="czz" />
-    <path
-       style="opacity:0.50000000000000000;fill:none;fill-opacity:1;stroke:url(#linearGradient3349);stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 10.99506,11.498797 C 10.735658,11.486846 10.370038,11.588319 9.8835883,11.932121 C 8.8737,12.645867 8.5374239,13.351301 8.4999186,14.121547 C 8.4624133,14.891791 8.7901654,15.780902 9.3391937,16.607457 C 9.8882225,17.43401 10.661309,18.195719 11.403357,18.728462 C 12.145404,19.261206 12.809412,19.500227 13.070994,19.500227 C 13.222335,19.500227 13.331682,19.0625 13.39947,18.682848 C 13.535046,17.923542 13.548476,16.808781 13.376787,15.695196 C 13.205098,14.58161 12.846108,13.444035 12.401414,12.661929 C 11.95672,11.879824 11.481565,11.52121 10.99506,11.498797 z "
-       id="path2254"
-       sodipodi:nodetypes="cssssssssc" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.99454969"
-       inkscape:original="M 19.84375 2.53125 C 16.627629 3.0996097 12.5 9.9375001 12.5 9.9375 L 14.5 14.5 C 18.209158 14.5 20.4375 12.78125 20.4375 12.78125 C 20.4375 12.78125 24.442227 4.438644 21.15625 2.71875 C 20.748817 2.505498 20.303196 2.4500558 19.84375 2.53125 z "
-       xlink:href="#rect1317"
-       style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       id="path2245"
-       inkscape:href="#rect1317"
-       d="M 20,3.5 C 18.995087,3.678281 17.104383,5.3426949 15.71875,7.0625 C 14.498278,8.5773128 13.796939,9.7027104 13.59375,10.03125 L 15.0625,13.375 C 17.799931,13.187054 19.57299,12.186552 19.84375,12 C 19.951969,11.755173 20.691026,10.13991 21.15625,8.125 C 21.405718,7.0445423 21.52736,5.9263632 21.4375,5.09375 C 21.34764,4.2611368 21.117806,3.8050199 20.65625,3.5625 C 20.487599,3.4738843 20.316754,3.4438049 20,3.5 z " />
-    <path
-       style="opacity:1;fill:url(#linearGradient2251);fill-opacity:1;stroke:url(#linearGradient3309);stroke-width:1.00000036000000003;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 1.7201236,5.8422141 C 3.0648384,3.5951707 16.885436,13.102028 11.0851,14.359955 5.2923103,15.616246 0.38911136,8.0663605 1.7201236,5.8422141 z"
-       id="rect2197"
-       sodipodi:nodetypes="czz" />
-    <path
-       style="opacity:0.50000000000000000;fill:none;fill-opacity:1;stroke:url(#linearGradient3333);stroke-width:0.99999994000000003;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 2.7390794,8.1722341 C 3.0496879,9.0060223 3.6590736,9.9821112 4.4574474,10.857929 C 6.0541952,12.609562 8.35926,13.89948 10.765977,13.389526 C 11.255672,13.285765 11.400406,13.151715 11.448617,13.081331 C 11.496824,13.010949 11.537361,12.912219 11.448617,12.641053 C 11.271127,12.098721 10.521911,11.132591 9.4713148,10.219525 C 8.4207206,9.3064602 7.0856043,8.3957283 5.8462653,7.7099423 C 4.6069262,7.0241566 3.3045923,6.5498939 2.7239802,6.4956482 C 2.4148401,6.4667656 2.428471,7.3384455 2.7390794,8.1722341 z "
-       id="path2249"
-       sodipodi:nodetypes="cssssssss" />
-    <path
-       style="opacity:1;fill:url(#linearGradient1330);fill-opacity:1;stroke:url(#linearGradient3301);stroke-width:1.00000059999999991;stroke-miterlimit:4;stroke-opacity:1"
-       d="m 12.5,9.9508496 c 0,0 5.3944787,-8.9404465 8.6539392,-7.2344302 3.2859758,1.7198941 -0.72781076,10.074633 -0.72781076,10.074633 0,0 -2.2165346,1.7089461 -5.9256925,1.7089461 z"
-       id="rect1317"
-       sodipodi:nodetypes="czccc" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.99298751"
-       inkscape:original="M 19.84375 2.53125 C 16.627629 3.0996097 12.5 9.9375001 12.5 9.9375 L 14.5 14.5 C 18.209158 14.5 20.4375 12.78125 20.4375 12.78125 C 20.4375 12.78125 24.442227 4.438644 21.15625 2.71875 C 20.748817 2.505498 20.303196 2.4500558 19.84375 2.53125 z "
-       xlink:href="#rect1317"
-       style="opacity:0.50000000000000000;fill:none;fill-opacity:1;stroke:url(#linearGradient3341);stroke-width:1.00000059999999991;stroke-miterlimit:4;stroke-opacity:1"
-       id="path1328"
-       inkscape:href="#rect1317"
-       d="M 20,3.5 C 18.994143,3.6784485 17.104459,5.3425998 15.71875,7.0625 C 14.49821,8.5773965 13.796948,9.7026949 13.59375,10.03125 L 15.0625,13.375 C 17.800353,13.18702 19.57294,12.186586 19.84375,12 C 19.951976,11.755161 20.690984,10.140091 21.15625,8.125 C 21.40574,7.0444453 21.527392,5.9266549 21.4375,5.09375 C 21.347608,4.2608451 21.11837,3.8053161 20.65625,3.5625 C 20.487225,3.4736876 20.316977,3.4437653 20,3.5 z " />
-    <path
-       style="opacity:1;fill:url(#linearGradient3371);fill-opacity:1;stroke:none"
-       d="m 11.389657,9.0579863 c -0.414051,0.3722786 -0.352513,0.9865027 -0.277197,1.4838927 0.239773,1.364175 0.789435,2.64708 1.325924,3.915745 0.363289,0.814507 0.739494,1.646019 1.333013,2.322141 0.21439,0.294032 0.688179,0.394083 0.9256,0.076102 0.364704,-0.448044 0.240335,-1.068768 0.154354,-1.590251 C 14.606869,14.019691 14.107446,12.843211 13.623624,11.675334 13.252072,10.834687 12.875025,9.9742966 12.27693,9.2664664 12.071179,9.0077513 11.678175,8.7965612 11.389657,9.0579863 z"
-       id="path2192" />
-    <image
-       id="image2210"
-       height="8"
-       width="8"
-       sodipodi:absref="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       xlink:href="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       x="-16"
-       y="14" />
-  </g>
-</svg>
--- a/pidgin/pixmaps/emotes/default/24/scalable/msn_online.svg	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,275 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="24"
-   height="24"
-   id="svg2"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   version="1.0"
-   sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/emotes/scalable"
-   sodipodi:docname="msn_online.svg"
-   inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/msn2.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
-  <defs
-     id="defs4">
-    <linearGradient
-       id="linearGradient2851">
-      <stop
-         style="stop-color:#73d216;stop-opacity:1;"
-         offset="0"
-         id="stop2853" />
-      <stop
-         style="stop-color:#5ca911;stop-opacity:1;"
-         offset="1"
-         id="stop2855" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2851"
-       id="linearGradient2857"
-       x1="6.878005"
-       y1="11.789385"
-       x2="12.233074"
-       y2="27.77807"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3149">
-      <stop
-         style="stop-color:#eeeeec;stop-opacity:1;"
-         offset="0"
-         id="stop3151" />
-      <stop
-         style="stop-color:#eeeeec;stop-opacity:0;"
-         offset="1"
-         id="stop3153" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3149"
-       id="linearGradient2269"
-       gradientUnits="userSpaceOnUse"
-       x1="17.890068"
-       y1="8.0617304"
-       x2="17.890068"
-       y2="40.032413" />
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3816">
-      <stop
-         style="stop-color:#000000;stop-opacity:1;"
-         offset="0"
-         id="stop3818" />
-      <stop
-         style="stop-color:#000000;stop-opacity:0;"
-         offset="1"
-         id="stop3820" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3816"
-       id="radialGradient3822"
-       cx="31.112698"
-       cy="19.008621"
-       fx="31.112698"
-       fy="19.008621"
-       r="8.6620579"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2228">
-      <stop
-         style="stop-color:#f56600;stop-opacity:1;"
-         offset="0"
-         id="stop2230" />
-      <stop
-         style="stop-color:#f56600;stop-opacity:0;"
-         offset="1"
-         id="stop2232" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2219">
-      <stop
-         style="stop-color:#3465a4;stop-opacity:1;"
-         offset="0"
-         id="stop2221" />
-      <stop
-         style="stop-color:#3465a4;stop-opacity:0;"
-         offset="1"
-         id="stop2223" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2219"
-       id="linearGradient2251"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.747158,0,0,0.74873,0.374035,0.608489)"
-       x1="9.9973583"
-       y1="14.918511"
-       x2="14.069712"
-       y2="18.218639" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2228"
-       id="linearGradient1330"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.782765,0,0,0.747651,1.035995,0.614065)"
-       x1="20.998175"
-       y1="11.741063"
-       x2="17.999571"
-       y2="18.866741" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="24.007725"
-     inkscape:cx="24.82492"
-     inkscape:cy="10.486753"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     fill="#edd400"
-     showguides="true"
-     inkscape:guide-bbox="true"
-     inkscape:window-width="1268"
-     inkscape:window-height="971"
-     inkscape:window-x="6"
-     inkscape:window-y="21" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1">
-    <path
-       d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1  22.45064,19.008621 A 8.6620579 8.6620579 0 1 1  39.774755 19.008621 z"
-       sodipodi:ry="8.6620579"
-       sodipodi:rx="8.6620579"
-       sodipodi:cy="19.008621"
-       sodipodi:cx="31.112698"
-       id="path4318"
-       style="opacity:0.4;color:#000000;fill:url(#radialGradient3822);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       sodipodi:type="arc"
-       transform="matrix(1.044119,0,0,0.346338,-18.44114,13.41659)" />
-    <path
-       style="opacity:1;fill:#edd400;fill-opacity:1;stroke:#c4a000;stroke-width:1.00000083;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 18.436518,9.9127618 C 21.037357,10.673309 21.362289,19.501337 18.407881,19.501337 C 15.489266,19.501337 8.9905421,7.150538 18.436518,9.9127618 z "
-       id="rect2194"
-       sodipodi:nodetypes="czs" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.96520001"
-       inkscape:original="M 15.59375 9.53125 C 10.549483 10.044796 15.852462 19.5 18.40625 19.5 C 21.360658 19.5 21.038339 10.666797 18.4375 9.90625 C 17.256753 9.560972 16.31436 9.4578863 15.59375 9.53125 z "
-       xlink:href="#rect2194"
-       style="opacity:0.5;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.00000024;stroke-miterlimit:4;stroke-opacity:1"
-       id="path2259"
-       inkscape:href="#rect2194"
-       d="M 16,10.75 C 15.512126,10.798024 15.253534,10.920051 15.09375,11.0625 C 14.933966,11.204949 14.83864,11.380838 14.78125,11.6875 C 14.66647,12.300825 14.844054,13.385232 15.3125,14.46875 C 15.780946,15.552268 16.512913,16.653582 17.21875,17.4375 C 17.924587,18.221418 18.67699,18.5625 18.75,18.5625 C 18.89196,18.5625 18.968845,18.54667 19.09375,18.4375 C 19.218655,18.32833 19.365593,18.098064 19.5,17.78125 C 19.768815,17.147621 19.923112,16.154119 19.90625,15.125 C 19.889388,14.095881 19.705611,13.023656 19.40625,12.25 C 19.106889,11.476344 18.724904,11.117253 18.53125,11.0625 C 17.425208,10.749781 16.582845,10.692627 16,10.75 z " />
-    <path
-       style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000083;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 13.316085,20.509475 C 10.851196,20.509475 4.3258741,14.508937 9.3204332,11.066555 C 14.310647,7.6271659 15.818731,20.509475 13.316085,20.509475 z "
-       id="rect2201"
-       sodipodi:nodetypes="czz" />
-    <path
-       style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 10.99506,11.498797 C 10.735658,11.486846 10.370038,11.588319 9.8835883,11.932121 C 8.8737,12.645867 8.5374239,13.351301 8.4999186,14.121547 C 8.4624133,14.891791 8.7901654,15.780902 9.3391937,16.607457 C 9.8882225,17.43401 10.661309,18.195719 11.403357,18.728462 C 12.145404,19.261206 12.809412,19.500227 13.070994,19.500227 C 13.222335,19.500227 13.331682,19.0625 13.39947,18.682848 C 13.535046,17.923542 13.548476,16.808781 13.376787,15.695196 C 13.205098,14.58161 12.846108,13.444035 12.401414,12.661929 C 11.95672,11.879824 11.481565,11.52121 10.99506,11.498797 z "
-       id="path2254"
-       sodipodi:nodetypes="cssssssssc" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.99454969"
-       inkscape:original="M 19.8125 2.53125 C 16.600144 3.1011521 12.46875 9.9375003 12.46875 9.9375 L 14.46875 14.5 C 18.173566 14.5 20.656251 12.6875 20.65625 12.6875 C 20.65625 12.6875 24.40713 4.4120618 21.125 2.6875 C 20.718044 2.4736692 20.271408 2.4498354 19.8125 2.53125 z "
-       xlink:href="#rect1317"
-       style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       id="path2245"
-       inkscape:href="#rect1317"
-       d="M 20,3.5 C 18.995087,3.678281 17.104383,5.3426949 15.71875,7.0625 C 14.498278,8.5773128 13.796939,9.7027104 13.59375,10.03125 L 15.0625,13.375 C 17.799931,13.187054 19.57299,12.186552 19.84375,12 C 19.951969,11.755173 20.691026,10.13991 21.15625,8.125 C 21.405718,7.0445423 21.52736,5.9263632 21.4375,5.09375 C 21.34764,4.2611368 21.117806,3.8050199 20.65625,3.5625 C 20.487599,3.4738843 20.316754,3.4438049 20,3.5 z " />
-    <path
-       style="opacity:1;fill:url(#linearGradient2251);fill-opacity:1;stroke:#204a87;stroke-width:1.00000036;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 1.7306799,5.8222291 C 3.0741729,3.5659039 16.882213,13.11203 11.087148,14.375153 C 5.2996209,15.636634 0.40087698,8.0555627 1.7306799,5.8222291 z "
-       id="rect2197"
-       sodipodi:nodetypes="czz" />
-    <path
-       style="opacity:0.2;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 2.7390794,8.1722341 C 3.0496879,9.0060223 3.6590736,9.9821112 4.4574474,10.857929 C 6.0541952,12.609562 8.35926,13.89948 10.765977,13.389526 C 11.255672,13.285765 11.400406,13.151715 11.448617,13.081331 C 11.496824,13.010949 11.537361,12.912219 11.448617,12.641053 C 11.271127,12.098721 10.521911,11.132591 9.4713148,10.219525 C 8.4207206,9.3064602 7.0856043,8.3957283 5.8462653,7.7099423 C 4.6069262,7.0241566 3.3045923,6.5498939 2.7239802,6.4956482 C 2.4148401,6.4667656 2.428471,7.3384455 2.7390794,8.1722341 z "
-       id="path2249"
-       sodipodi:nodetypes="cssssssss" />
-    <path
-       style="opacity:1;fill:url(#linearGradient1330);fill-opacity:1;stroke:#ce5d00;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 12.478485,9.9508709 C 12.478485,9.9508709 17.866649,0.9861607 21.122294,2.6968071 C 24.404423,4.4213689 20.644961,12.673483 20.644961,12.673483 C 20.644961,12.673483 18.181394,14.512366 14.476578,14.512366 L 12.478485,9.9508709 z "
-       id="rect1317"
-       sodipodi:nodetypes="czccc" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.99298751"
-       inkscape:original="M 19.8125 2.53125 C 16.600144 3.1011521 12.46875 9.9375003 12.46875 9.9375 L 14.46875 14.5 C 18.173566 14.5 20.656251 12.6875 20.65625 12.6875 C 20.65625 12.6875 24.40713 4.4120618 21.125 2.6875 C 20.718044 2.4736692 20.271408 2.4498354 19.8125 2.53125 z "
-       xlink:href="#rect1317"
-       style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-       id="path1328"
-       inkscape:href="#rect1317"
-       d="M 20,3.5 C 18.994143,3.6784485 17.104459,5.3425998 15.71875,7.0625 C 14.49821,8.5773965 13.796948,9.7026949 13.59375,10.03125 L 15.0625,13.375 C 17.800353,13.18702 19.57294,12.186586 19.84375,12 C 19.951976,11.755161 20.690984,10.140091 21.15625,8.125 C 21.40574,7.0444453 21.527392,5.9266549 21.4375,5.09375 C 21.347608,4.2608451 21.11837,3.8053161 20.65625,3.5625 C 20.487225,3.4736876 20.316977,3.4437653 20,3.5 z " />
-    <path
-       sodipodi:type="arc"
-       style="opacity:1;fill:#75507b;fill-opacity:1;stroke:#5c3566;stroke-width:1.35211551;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path2192"
-       sodipodi:cx="13.4375"
-       sodipodi:cy="15.825892"
-       sodipodi:rx="0.8035714"
-       sodipodi:ry="5.1116071"
-       d="M 14.241071 15.825892 A 0.8035714 5.1116071 0 1 1  12.633929,15.825892 A 0.8035714 5.1116071 0 1 1  14.241071 15.825892 z"
-       transform="matrix(0.603448,-0.487879,0.280285,0.679821,0.46572,8.794406)" />
-    <image
-       id="image2210"
-       height="8"
-       width="8"
-       sodipodi:absref="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       xlink:href="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       x="-16"
-       y="14" />
-    <path
-       sodipodi:type="arc"
-       style="opacity:1;fill:url(#linearGradient2857);fill-opacity:1;fill-rule:evenodd;stroke:#418203;stroke-width:2.31977415;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path1460"
-       sodipodi:cx="17.890068"
-       sodipodi:cy="17.572527"
-       sodipodi:rx="13.932817"
-       sodipodi:ry="13.932817"
-       d="M 31.822886 17.572527 A 13.932817 13.932817 0 1 1  3.9572506,17.572527 A 13.932817 13.932817 0 1 1  31.822886 17.572527 z"
-       transform="matrix(0.431281,0,0,0.430872,8.790887,8.928459)" />
-    <path
-       sodipodi:type="arc"
-       style="opacity:0.5;fill:url(#linearGradient2269);fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.77727246;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path3145"
-       sodipodi:cx="17.890068"
-       sodipodi:cy="17.572527"
-       sodipodi:rx="13.932817"
-       sodipodi:ry="13.932817"
-       d="M 31.822886 17.572527 A 13.932817 13.932817 0 1 1  3.9572506,17.572527 A 13.932817 13.932817 0 1 1  31.822886 17.572527 z"
-       transform="matrix(0.360072,0,0,0.360059,10.05444,10.16875)" />
-  </g>
-</svg>
--- a/pidgin/pixmaps/emotes/small/16/small.theme.in	Wed Oct 05 22:15:51 2016 -0500
+++ b/pidgin/pixmaps/emotes/small/16/small.theme.in	Thu Oct 06 10:05:06 2016 -0400
@@ -72,52 +72,6 @@
 glasses-cool.png    8-)
 
 
-# Following Windows Live Messenger 8.1
-[MSN]
-happy.png           :)      :-)
-excited.png         :D      :d      :-D     :-d
-wink.png            ;)      ;-)
-shocked.png         :-O     :-o     :O      :o
-tongue.png          :-P     :P      :-p     :p
-glasses-cool.png    (H)     (h)
-angry.png           :@      :-@
-embarrassed.png     :$      :-$
-confused.png        :S      :s      :-S     :-s
-sad.png             :(      :-(
-crying.png          :'(
-neutral.png         :|      :-|
-devil.png           (6)
-angel.png           (A)     (a)
-in_love.png         (L)     (l)
-star.png            (*)
-musical-note.png    (8)
-rose.png            (F)     (f)
-kiss.png            (K)     (k)
-camera.png          (P)     (p)
-lamp.png            (I)     (i)
-coffee.png          (C)     (c)
-phone.png           (T)     (t)
-hug-left.png        ({)
-hug-right.png       (})
-beer.png            (B)     (b)
-boy.png             (Z)     (z)
-girl.png            (X)     (x)
-sarcastic.png       ^o)
-sick.png            +o(
-plate.png           (pl)
-mobile.png          (mp)
-dont-know.png       :^)
-thinking.png        *-)
-thunder.png         (li)
-party.png           <:o)
-eyeroll.png         8-)
-sleepy.png          |-) 
-
-# Hidden MSN emotes
-cigarette.png      	(ci)    (CI)
-console.png			(xx)    (XX)
-
-
 # Following QQ 2006
 [QQ]
 shocked.png         /:O      /jy       /surprised
@@ -179,143 +133,3 @@
 excited.png         :-D     :D
 glasses-cool.png    8-)
 amorous.png         *IN\ LOVE*
-
-
-# Following Yahoo! Messenger 8.1
-[Yahoo]
-happy.png           :)      :-)
-question.png        :-/     :-\\
-shocked.png         :-O     :O      :-o     :o 
-devil.png           >:)
-angel.png           O:-)    o:-)    0:-)
-sick.png            :-&
-sleepy.png          (:|
-sad.png             :(      :-(
-amorous.png         :x      :-x     :X      :-X
-angry.png           X-(     x-(     X(      x(
-crying.png          :((
-drool.png           =P~     =p~
-lying.png           :^O     :^o
-wink.png            ;)      ;-)
-embarrassed.png     :">
-mean.png            :->     :>
-thinking.png        :-?
-excited.png         :D      :-D     :d      :-d
-tongue.png          :-P     :P      :-p     :p
-glasses-cool.png    B-)     b-)
-neutral.png         :|      :-|
-sleeping.png        I-)     i-)     |-)
-kiss.png            :-*     :*
-confused.png        :-S     :-s
-sarcastic.png       /:)
-eyeroll.png         8-|
-hug-left.png        >:D<    >:d<
-hot.png             #:-S    #:-s
-party.png           <:-P    <:-p
-nervous.png         :-SS	:-Ss	:-sS	:-ss
-
-# Hidden Yahoo emotes
-coffee.png          ~o)     ~O)
-rose.png            @};-
-dont-know.png       :-L     :-l
-lamp.png            *-:)
-shame.png           [-X     [-x
-musical-note.png    :-"
-star.png            (*)
-
-# Following Yahoo! Messenger 8.1
-[Yahoo JAPAN]
-happy.png           :)      :-)
-question.png        :-/     :-\\
-shocked.png         :-O     :O      :-o     :o 
-devil.png           >:)
-angel.png           O:-)    o:-)    0:-)
-sick.png            :-&
-sleepy.png          (:|
-sad.png             :(      :-(
-amorous.png         :x      :-x     :X      :-X
-angry.png           X-(     x-(     X(      x(
-crying.png          :((
-wink.png            ;)      ;-)
-thinking.png        :-?
-excited.png         :D      :-D     :d      :-d
-tongue.png          :-P     :P      :-p     :p
-glasses-cool.png    B-)     b-)
-neutral.png         :|      :-|
-sleeping.png        I-)     i-)     |-)
-kiss.png            :-*     :*
-confused.png        :-S     :-s
-sarcastic.png       /:)
-eyeroll.png         8-|
-hug-left.png        >:D<    >:d<
-party.png           <:-P    <:-p
-
-# Hidden Yahoo emotes
-coffee.png          ~o)     ~O)
-rose.png            @};-
-dont-know.png       :-L     :-l
-lamp.png            *-:)
-shame.png           [-X     [-x
-musical-note.png    :-"
-star.png            (*)
-
-
-# Following MySpaceIM Beta 1.0.697.0
-[MySpaceIM]
-excited.png  	    :D      :-D
-devil.png	    }:)
-confused.png	    :Z
-happy.png	    :)      :-)
-amorous.png	    :X
-pirate.png	    P)
-shocked.png	    :O
-neutral.png	    :|
-tongue.png	    :P      :p
-pissed-off.png	    B|
-wink.png	    ;-)     ;)
-sad.png		    :[
-kiss.png            :x
-
-# MXit standard emoticons
-[MXit]
-happy.png           :-)     :)
-sad.png             :-(     :(
-wink.png            ;-)     ;)
-excited.png         :-D     :D     :->      :>
-neutral.png         :-|     :|
-shocked.png         :-O     :O
-tongue.png          :-P     :P
-embarrassed.png     :-$     :$
-glasses-cool.png    8-)
-in_love.png         (H)
-rose.png            (F)
-### Added in v3.0
-boy.png             (m)
-girl.png            (f)
-star.png            (*)
-chilli.png          (c)
-kiss.png            (x)
-lamp.png            (i)
-pissed-off.png      :e      :-e
-shut-mouth.png      :-x     :x
-thunder.png         (z)
-coffee.png          (U)
-mrgreen.png         (G)
-### Added in v5.0
-sick.png            :o(
-excruciating.png    :-{     :{
-amorous.png         :-}     :}
-eyeroll.png         8-o     8o
-crying.png          :'(
-thinking.png        :-?     :?
-drool.png           :-~     :~
-sleeping.png        :-z     :z
-lying.png           :L)
-glasses-nerdy.png   8-|     8|
-pirate.png          P-)
-### Added in v5.9.7
-bored.png           :-[     :[
-cold.png            :-<     :<
-confused.png        :-,     :,
-hungry.png          :-C     :C
-stressed.png        :-s     :s
Binary file pidgin/pixmaps/protocols/16/msn.png has changed
Binary file pidgin/pixmaps/protocols/16/mxit.png has changed
Binary file pidgin/pixmaps/protocols/16/myspace.png has changed
--- a/pidgin/pixmaps/protocols/16/scalable/msn.svg	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,352 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="16px"
-   height="16px"
-   id="svg4239"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/16/scalable"
-   sodipodi:docname="msn.svg"
-   inkscape:export-filename="/home/hbons/Bureaublad/msn.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
-  <defs
-     id="defs4241">
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient8709">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop8711" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop8713" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient8701">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop8703" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop8705" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient8693">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop8695" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop8697" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient8685">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop8687" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop8689" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient8677">
-      <stop
-         style="stop-color:#5c3566;stop-opacity:1;"
-         offset="0"
-         id="stop8679" />
-      <stop
-         style="stop-color:#874e96;stop-opacity:1"
-         offset="1"
-         id="stop8681" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient8660">
-      <stop
-         style="stop-color:#275ba6;stop-opacity:1"
-         offset="0"
-         id="stop8662" />
-      <stop
-         style="stop-color:#183765;stop-opacity:1"
-         offset="1"
-         id="stop8664" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient8652">
-      <stop
-         style="stop-color:#4e9a06;stop-opacity:1;"
-         offset="0"
-         id="stop8654" />
-      <stop
-         style="stop-color:#2f5f02;stop-opacity:1"
-         offset="1"
-         id="stop8656" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient8644">
-      <stop
-         style="stop-color:#c4a000;stop-opacity:1;"
-         offset="0"
-         id="stop8646" />
-      <stop
-         style="stop-color:#786300;stop-opacity:1"
-         offset="1"
-         id="stop8648" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient8636">
-      <stop
-         style="stop-color:#ce5d00;stop-opacity:1;"
-         offset="0"
-         id="stop8638" />
-      <stop
-         style="stop-color:#833b00;stop-opacity:1"
-         offset="1"
-         id="stop8640" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient2219"
-       inkscape:collect="always">
-      <stop
-         id="stop2221"
-         offset="0"
-         style="stop-color:#3465a4;stop-opacity:1;" />
-      <stop
-         id="stop2223"
-         offset="1"
-         style="stop-color:#3465a4;stop-opacity:0;" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient2228"
-       inkscape:collect="always">
-      <stop
-         id="stop2230"
-         offset="0"
-         style="stop-color:#f56600;stop-opacity:1;" />
-      <stop
-         id="stop2232"
-         offset="1"
-         style="stop-color:#f56600;stop-opacity:0;" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2228"
-       id="linearGradient4505"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.782765,0,0,0.747651,1.035995,0.614065)"
-       x1="20.007692"
-       y1="13.250565"
-       x2="18.727983"
-       y2="17.102213" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2219"
-       id="linearGradient4507"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.5438817,0,0,0.5799505,-0.3274572,-0.2722861)"
-       x1="10.200594"
-       y1="14.726058"
-       x2="13.252806"
-       y2="18.174761" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient8636"
-       id="linearGradient8642"
-       x1="16.397886"
-       y1="7.1729202"
-       x2="19.359613"
-       y2="12.699073"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient8644"
-       id="linearGradient8650"
-       x1="17.004478"
-       y1="15.059639"
-       x2="19.158651"
-       y2="19.232847"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.8565497,0,0,0.700607,-3.0651761,-0.162781)" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient8652"
-       id="linearGradient8658"
-       x1="11.425816"
-       y1="15.977947"
-       x2="13.070351"
-       y2="19.869415"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient8660"
-       id="linearGradient8666"
-       x1="1.1384629"
-       y1="4.3090925"
-       x2="6.360837"
-       y2="9.665041"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient8677"
-       id="linearGradient8683"
-       x1="9.734354"
-       y1="10.855804"
-       x2="8.227417"
-       y2="7.5956616"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient8685"
-       id="linearGradient8691"
-       x1="2.27721"
-       y1="6.7656131"
-       x2="10.084975"
-       y2="12.919206"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient8709"
-       id="linearGradient8733"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.789526,0,0,0.621298,-1.921384,0.986574)"
-       x1="18.850323"
-       y1="18.158928"
-       x2="17.372902"
-       y2="13.093926" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient8701"
-       id="linearGradient8742"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.599236,0,0,0.624815,0.408284,1.315959)"
-       x1="12.687945"
-       y1="18.895752"
-       x2="11.633714"
-       y2="15.440485" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient8693"
-       id="linearGradient8745"
-       gradientUnits="userSpaceOnUse"
-       x1="13.573946"
-       y1="3.1337965"
-       x2="11.223683"
-       y2="8.5642729" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="27.3287"
-     inkscape:cx="20.590777"
-     inkscape:cy="9.6812143"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     inkscape:grid-bbox="true"
-     inkscape:document-units="px"
-     inkscape:window-width="1430"
-     inkscape:window-height="837"
-     inkscape:window-x="254"
-     inkscape:window-y="427"
-     inkscape:snap-nodes="false"
-     inkscape:snap-bbox="true"
-     objecttolerance="10"
-     gridtolerance="10">
-    <inkscape:grid
-       type="xygrid"
-       id="grid7864"
-       visible="true"
-       enabled="true" />
-  </sodipodi:namedview>
-  <metadata
-     id="metadata4244">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     id="layer1"
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer">
-    <path
-       style="fill:#edd400;fill-opacity:1;stroke:url(#linearGradient8650);stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
-       d="M 12.726618,6.7821693 C 14.954366,7.315014 15.232686,13.499992 12.702089,13.499992 C 10.20215,13.499992 4.63567,4.846936 12.726618,6.7821693 z"
-       id="rect2194" />
-    <path
-       style="opacity:0.5;fill:none;fill-opacity:1;stroke:url(#linearGradient8733);stroke-width:1.00000119;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 10.464305,7.5102029 C 10.084666,7.5060849 9.6095224,7.6779929 9.5306688,8.0961333 C 9.4083085,8.8812767 9.7824927,9.6266355 10.172483,10.280772 C 10.718966,11.141573 11.429181,11.932478 12.346756,12.402887 C 12.624698,12.609701 12.991224,12.391706 13.128703,12.12186 C 13.685105,10.954392 13.588008,9.5514732 13.062635,8.3912413 C 12.867487,7.9910733 12.482071,7.658617 12.022113,7.639864 C 11.508321,7.5519031 10.987071,7.4717107 10.464305,7.5102029 z"
-       id="path2259" />
-    <path
-       transform="matrix(0.712542,0,0,0.698139,-0.834614,0.18154)"
-       style="fill:#73d216;fill-opacity:1;stroke:url(#linearGradient8658);stroke-width:1.41783130000000002;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 13.316085,20.509475 C 10.851196,20.509475 4.3258741,14.508937 9.3204332,11.066555 C 14.310647,7.6271659 15.818731,20.509475 13.316085,20.509475 z "
-       id="rect2201" />
-    <path
-       style="opacity:0.5;fill:none;fill-opacity:1;stroke:url(#linearGradient8742);stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 6.9969196,8.5005798 C 6.4095407,8.5652754 5.9363988,9.0353859 5.6504082,9.5247059 C 5.3128668,10.187546 5.6118436,10.924286 5.9818793,11.497377 C 6.4590192,12.279805 7.2102283,12.858859 7.9986562,13.300897 C 8.6344334,13.702713 8.4099456,12.64584 8.4957981,12.27224 C 8.4979791,11.096105 8.2902419,9.8546211 7.6065424,8.8720886 C 7.4570093,8.6818207 7.2484632,8.5134511 6.9969196,8.5005798 z"
-       id="path2254" />
-    <path
-       transform="matrix(0.720961,0,0,0.718898,-0.697672,-0.282723)"
-       style="opacity:0.25;fill:none;fill-opacity:1;stroke:white;stroke-width:1.389027;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 20,3.5 C 18.995087,3.678281 17.104383,5.3426949 15.71875,7.0625 C 14.498278,8.5773128 13.796939,9.7027104 13.59375,10.03125 L 15.0625,13.375 C 17.799931,13.187054 19.57299,12.186552 19.84375,12 C 19.951969,11.755173 20.691026,10.13991 21.15625,8.125 C 21.405718,7.0445423 21.52736,5.9263632 21.4375,5.09375 C 21.34764,4.2611368 21.117806,3.8050199 20.65625,3.5625 C 20.487599,3.4738843 20.316754,3.4438049 20,3.5 z "
-       id="path2245" />
-    <path
-       style="fill:url(#linearGradient4507);fill-opacity:1;stroke:url(#linearGradient8666);stroke-width:1.00000106999999994;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 0.66009074,3.7661675 C 1.638065,2.0184654 11.689407,9.4126942 7.470982,10.391083 C 3.2580442,11.368199 -0.30791802,5.4960608 0.66009074,3.7661675 z"
-       id="rect2197" />
-    <path
-       transform="matrix(0.666514,0,0,0.713565,-0.165619,-0.134566)"
-       style="opacity:0.50000000000000000;fill:none;fill-opacity:1;stroke:url(#linearGradient8691);stroke-width:1.45003652999999999;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 2.9037792,8.1978741 C 3.2143877,9.0316623 3.9610232,9.9051913 4.759397,10.781009 C 6.3561448,12.532642 8.35926,13.89948 10.765977,13.389526 C 11.255672,13.285765 11.400406,13.151715 11.448617,13.081331 C 11.496824,13.010949 11.537361,12.912219 11.448617,12.641053 C 11.271127,12.098721 10.247411,11.388991 9.1968152,10.475925 C 8.146221,9.5628599 6.8660046,8.7034079 5.6266656,8.0176219 C 4.3873265,7.3318362 3.3045923,6.5498939 2.7239802,6.4956482 C 2.4148401,6.4667656 2.5931708,7.3640855 2.9037792,8.1978741 z"
-       id="path2249"
-       sodipodi:nodetypes="csssssssc" />
-    <path
-       transform="matrix(0.700821,0,0,0.664862,-0.245183,-0.148725)"
-       style="fill:url(#linearGradient4505);fill-opacity:1;stroke:url(#linearGradient8642);stroke-width:1.46497786000000008;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 12.478485,9.9508709 C 12.478485,9.9508709 17.866649,0.9861607 21.122294,2.6968071 C 24.404423,4.4213689 20.644961,12.673483 20.644961,12.673483 C 20.644961,12.673483 18.181394,14.512366 14.476578,14.512366 L 12.478485,9.9508709 z "
-       id="rect1317" />
-    <path
-       style="opacity:0.50000000000000000;fill:none;fill-opacity:1;stroke:url(#linearGradient8745);stroke-width:1.00000059999999991;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 13.641543,2.6087804 C 13.042222,2.7550593 12.566354,3.1867157 12.108436,3.5768078 C 11.18133,4.4213418 10.408475,5.418624 9.6753778,6.4315252 C 9.7266839,7.073663 10.22649,7.8212816 10.524225,8.4451141 C 11.523392,8.3745467 12.537477,8.14589 13.395949,7.6120796 C 13.929097,6.4895545 14.279568,5.2829939 14.46967,4.0564994 C 14.517847,3.5935306 14.505216,3.0568259 14.178422,2.69122 C 14.015215,2.4959594 13.853389,2.5338947 13.641543,2.6087804 z"
-       id="path1328"
-       sodipodi:nodetypes="ccccccsc" />
-    <path
-       style="fill:url(#linearGradient8683);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 7.84375,6.0625 C 7.2204009,5.7746851 6.7868533,6.5768349 7.0386107,7.0974232 C 7.2879783,8.4863432 7.8061372,9.8184408 8.4250523,11.082033 C 8.6624096,11.493677 8.9604116,12.091198 9.5358102,11.967269 C 10.350721,11.726246 9.8989976,10.67735 9.7858357,10.097672 C 9.4218582,8.8029479 8.9711599,7.5041911 8.2319551,6.3726804 C 8.1261729,6.2440217 7.9975858,6.1299296 7.84375,6.0625 z"
-       id="path2192" />
-  </g>
-</svg>
--- a/pidgin/pixmaps/protocols/16/scalable/yahoo.svg	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,138 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="16px"
-   height="16px"
-   id="svg4248"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/16/scalable"
-   sodipodi:docname="yahoo.svg"
-   inkscape:export-filename="/home/hbons/Bureaublad/yahoo.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
-  <defs
-     id="defs4250">
-    <inkscape:perspective
-       sodipodi:type="inkscape:persp3d"
-       inkscape:vp_x="0 : 8 : 1"
-       inkscape:vp_y="0 : 1000 : 0"
-       inkscape:vp_z="16 : 8 : 1"
-       inkscape:persp3d-origin="8 : 5.3333333 : 1"
-       id="perspective17" />
-    <linearGradient
-       id="linearGradient4123"
-       inkscape:collect="always">
-      <stop
-         id="stop4125"
-         offset="0"
-         style="stop-color:#ff0000;stop-opacity:1;" />
-      <stop
-         id="stop4127"
-         offset="1"
-         style="stop-color:#ff0000;stop-opacity:0;" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4123"
-       id="linearGradient6737"
-       gradientUnits="userSpaceOnUse"
-       x1="20.181133"
-       y1="12.686874"
-       x2="20.181133"
-       y2="5.3694997" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4123"
-       id="linearGradient6739"
-       gradientUnits="userSpaceOnUse"
-       x1="10.378018"
-       y1="18.430471"
-       x2="5.8631868"
-       y2="-0.23792659"
-       gradientTransform="matrix(0.676847,0,0,0.662872,0.3362294,0.7829564)" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="36.060436"
-     inkscape:cx="15.360711"
-     inkscape:cy="8.3801083"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     inkscape:grid-bbox="true"
-     inkscape:document-units="px"
-     inkscape:window-width="1440"
-     inkscape:window-height="847"
-     inkscape:window-x="0"
-     inkscape:window-y="0"
-     inkscape:grid-points="false"
-     inkscape:guide-points="false"
-     gridtolerance="10"
-     inkscape:object-points="false"
-     inkscape:object-nodes="false"
-     objecttolerance="10"
-     inkscape:snap-bbox="true"
-     inkscape:snap-nodes="false">
-    <inkscape:grid
-       type="xygrid"
-       id="grid7857"
-       visible="true"
-       enabled="true" />
-  </sodipodi:namedview>
-  <metadata
-     id="metadata4253">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     id="layer1"
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer">
-    <path
-       style="fill:white;fill-opacity:1;stroke:none;stroke-width:1.49293232;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 0.24196135,4.148819 L 0.24910211,7.1529832 L 3.5563617,7.147764 L 7.6406917,12.763032 L 7.642012,14.664616 L 4.6774169,14.67713 L 4.6586789,17.695272 L 13.533193,17.684579 L 13.569765,14.669366 L 10.619662,14.679398 L 10.629019,12.755768 L 14.593143,8.6330885 L 16.51876,8.6465912 L 16.509766,5.6235735 L 12.050243,5.6188666 L 12.072495,7.7727612 L 10.847264,10.121315 L 8.9433829,10.071394 L 7.9521191,7.1118568 L 9.0229281,7.1259776 L 9.0246268,4.0988967 L 0.24196135,4.148819 z "
-       id="path6741"
-       sodipodi:nodetypes="cccccccccccccccccccccc"
-       transform="matrix(0.676847,0,0,0.662872,0.331396,0.782369)" />
-    <rect
-       style="opacity:0;fill:none;fill-opacity:1;stroke:#a40000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="rect3203"
-       width="0"
-       height="2.5118096"
-       x="6"
-       y="6.4881902"
-       transform="translate(-1.463597e-2,-4.995136)" />
-    <path
-       style="fill:url(#linearGradient6739);fill-opacity:1;stroke:#a40000;stroke-width:1.00000047999999997;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 6.5 3.5 L 0.5 3.53125 L 0.5 5.53125 L 2.75 5.53125 L 5.5 9.25 L 5.5 10.5 L 4.28125 10.5 C 3.3577546 10.5 3.5 11.5 3.5 11.5 L 3.5 12.5 L 6.5 12.5 L 9.5 12.5 L 9.5 11.21875 C 9.4999997 11.21875 9.4638896 10.5 8.71875 10.5 L 7.53125 10.5 L 7.53125 9.6875 L 10.21875 6.5 L 11.53125 6.5 L 11.5 4.5 L 8.5 4.5 L 8.5 5.8125 L 7.09375 7.5 L 6.65625 7.5 L 5.1875 5.5 L 6.5 5.5 L 6.5 3.5 z M 13.5 3.5 L 13.53125 9.9375 L 15.71875 3.5 L 13.5 3.5 z M 12.5 10.5 C 11.948 10.5 11.5 10.948002 11.5 11.5 C 11.5 12.051998 11.948 12.5 12.5 12.5 C 13.052 12.5 13.5 12.051998 13.5 11.5 C 13.5 10.948002 13.052001 10.5 12.5 10.5 z "
-       id="rect3219" />
-    <rect
-       style="fill:white;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="rect4115"
-       width="1"
-       height="1"
-       x="15"
-       y="12"
-       transform="matrix(0.672571,0,0,0.662714,0.148779,0.239809)" />
-  </g>
-</svg>
Binary file pidgin/pixmaps/protocols/16/yahoo.png has changed
Binary file pidgin/pixmaps/protocols/22/msn.png has changed
Binary file pidgin/pixmaps/protocols/22/mxit.png has changed
Binary file pidgin/pixmaps/protocols/22/myspace.png has changed
--- a/pidgin/pixmaps/protocols/22/scalable/msn.svg	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,223 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="24"
-   height="24"
-   id="svg2"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   version="1.0"
-   sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols"
-   sodipodi:docname="msn.svg"
-   inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/msn2.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
-  <defs
-     id="defs4">
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3816">
-      <stop
-         style="stop-color:#000000;stop-opacity:1;"
-         offset="0"
-         id="stop3818" />
-      <stop
-         style="stop-color:#000000;stop-opacity:0;"
-         offset="1"
-         id="stop3820" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3816"
-       id="radialGradient3822"
-       cx="31.112698"
-       cy="19.008621"
-       fx="31.112698"
-       fy="19.008621"
-       r="8.6620579"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2228">
-      <stop
-         style="stop-color:#f56600;stop-opacity:1;"
-         offset="0"
-         id="stop2230" />
-      <stop
-         style="stop-color:#f56600;stop-opacity:0;"
-         offset="1"
-         id="stop2232" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2219">
-      <stop
-         style="stop-color:#3465a4;stop-opacity:1;"
-         offset="0"
-         id="stop2221" />
-      <stop
-         style="stop-color:#3465a4;stop-opacity:0;"
-         offset="1"
-         id="stop2223" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2219"
-       id="linearGradient2251"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.747158,0,0,0.74873,0.374035,0.608489)"
-       x1="9.9973583"
-       y1="14.918511"
-       x2="14.069712"
-       y2="18.218639" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2228"
-       id="linearGradient1330"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.782765,0,0,0.747651,1.035995,0.614065)"
-       x1="20.998175"
-       y1="11.741063"
-       x2="17.999571"
-       y2="18.866741" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="29.556977"
-     inkscape:cx="19.409996"
-     inkscape:cy="10.944939"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     fill="#edd400"
-     showguides="true"
-     inkscape:guide-bbox="true"
-     inkscape:window-width="1268"
-     inkscape:window-height="971"
-     inkscape:window-x="6"
-     inkscape:window-y="21" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1">
-    <path
-       d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1  22.45064,19.008621 A 8.6620579 8.6620579 0 1 1  39.774755 19.008621 z"
-       sodipodi:ry="8.6620579"
-       sodipodi:rx="8.6620579"
-       sodipodi:cy="19.008621"
-       sodipodi:cx="31.112698"
-       id="path4318"
-       style="opacity:0.4;color:#000000;fill:url(#radialGradient3822);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       sodipodi:type="arc"
-       transform="matrix(1.044119,0,0,0.346338,-18.44114,13.41659)" />
-    <path
-       style="opacity:1;fill:#edd400;fill-opacity:1;stroke:#c4a000;stroke-width:1.00000083;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 18.436518,9.9127618 C 21.037357,10.673309 21.362289,19.501337 18.407881,19.501337 C 15.489266,19.501337 8.9905421,7.150538 18.436518,9.9127618 z "
-       id="rect2194"
-       sodipodi:nodetypes="czs" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.96520001"
-       inkscape:original="M 15.59375 9.53125 C 10.549483 10.044796 15.852462 19.5 18.40625 19.5 C 21.360658 19.5 21.038339 10.666797 18.4375 9.90625 C 17.256753 9.560972 16.31436 9.4578863 15.59375 9.53125 z "
-       xlink:href="#rect2194"
-       style="opacity:0.5;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.00000024;stroke-miterlimit:4;stroke-opacity:1"
-       id="path2259"
-       inkscape:href="#rect2194"
-       d="M 16,10.75 C 15.512126,10.798024 15.253534,10.920051 15.09375,11.0625 C 14.933966,11.204949 14.83864,11.380838 14.78125,11.6875 C 14.66647,12.300825 14.844054,13.385232 15.3125,14.46875 C 15.780946,15.552268 16.512913,16.653582 17.21875,17.4375 C 17.924587,18.221418 18.67699,18.5625 18.75,18.5625 C 18.89196,18.5625 18.968845,18.54667 19.09375,18.4375 C 19.218655,18.32833 19.365593,18.098064 19.5,17.78125 C 19.768815,17.147621 19.923112,16.154119 19.90625,15.125 C 19.889388,14.095881 19.705611,13.023656 19.40625,12.25 C 19.106889,11.476344 18.724904,11.117253 18.53125,11.0625 C 17.425208,10.749781 16.582845,10.692627 16,10.75 z " />
-    <path
-       style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000083;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 13.316085,20.509475 C 10.851196,20.509475 4.3258741,14.508937 9.3204332,11.066555 C 14.310647,7.6271659 15.818731,20.509475 13.316085,20.509475 z "
-       id="rect2201"
-       sodipodi:nodetypes="czz" />
-    <path
-       style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 10.99506,11.498797 C 10.735658,11.486846 10.370038,11.588319 9.8835883,11.932121 C 8.8737,12.645867 8.5374239,13.351301 8.4999186,14.121547 C 8.4624133,14.891791 8.7901654,15.780902 9.3391937,16.607457 C 9.8882225,17.43401 10.661309,18.195719 11.403357,18.728462 C 12.145404,19.261206 12.809412,19.500227 13.070994,19.500227 C 13.222335,19.500227 13.331682,19.0625 13.39947,18.682848 C 13.535046,17.923542 13.548476,16.808781 13.376787,15.695196 C 13.205098,14.58161 12.846108,13.444035 12.401414,12.661929 C 11.95672,11.879824 11.481565,11.52121 10.99506,11.498797 z "
-       id="path2254"
-       sodipodi:nodetypes="cssssssssc" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.99454969"
-       inkscape:original="M 19.8125 2.53125 C 16.600144 3.1011521 12.46875 9.9375003 12.46875 9.9375 L 14.46875 14.5 C 18.173566 14.5 20.656251 12.6875 20.65625 12.6875 C 20.65625 12.6875 24.40713 4.4120618 21.125 2.6875 C 20.718044 2.4736692 20.271408 2.4498354 19.8125 2.53125 z "
-       xlink:href="#rect1317"
-       style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       id="path2245"
-       inkscape:href="#rect1317"
-       d="M 20,3.5 C 18.995087,3.678281 17.104383,5.3426949 15.71875,7.0625 C 14.498278,8.5773128 13.796939,9.7027104 13.59375,10.03125 L 15.0625,13.375 C 17.799931,13.187054 19.57299,12.186552 19.84375,12 C 19.951969,11.755173 20.691026,10.13991 21.15625,8.125 C 21.405718,7.0445423 21.52736,5.9263632 21.4375,5.09375 C 21.34764,4.2611368 21.117806,3.8050199 20.65625,3.5625 C 20.487599,3.4738843 20.316754,3.4438049 20,3.5 z " />
-    <path
-       style="opacity:1;fill:url(#linearGradient2251);fill-opacity:1;stroke:#204a87;stroke-width:1.00000036;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 1.7306799,5.8222291 C 3.0741729,3.5659039 16.882213,13.11203 11.087148,14.375153 C 5.2996209,15.636634 0.40087698,8.0555627 1.7306799,5.8222291 z "
-       id="rect2197"
-       sodipodi:nodetypes="czz" />
-    <path
-       style="opacity:0.2;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 2.7390794,8.1722341 C 3.0496879,9.0060223 3.6590736,9.9821112 4.4574474,10.857929 C 6.0541952,12.609562 8.35926,13.89948 10.765977,13.389526 C 11.255672,13.285765 11.400406,13.151715 11.448617,13.081331 C 11.496824,13.010949 11.537361,12.912219 11.448617,12.641053 C 11.271127,12.098721 10.521911,11.132591 9.4713148,10.219525 C 8.4207206,9.3064602 7.0856043,8.3957283 5.8462653,7.7099423 C 4.6069262,7.0241566 3.3045923,6.5498939 2.7239802,6.4956482 C 2.4148401,6.4667656 2.428471,7.3384455 2.7390794,8.1722341 z "
-       id="path2249"
-       sodipodi:nodetypes="cssssssss" />
-    <path
-       style="opacity:1;fill:url(#linearGradient1330);fill-opacity:1;stroke:#ce5d00;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 12.478485,9.9508709 C 12.478485,9.9508709 17.866649,0.9861607 21.122294,2.6968071 C 24.404423,4.4213689 20.644961,12.673483 20.644961,12.673483 C 20.644961,12.673483 18.181394,14.512366 14.476578,14.512366 L 12.478485,9.9508709 z "
-       id="rect1317"
-       sodipodi:nodetypes="czccc" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.99298751"
-       inkscape:original="M 19.8125 2.53125 C 16.600144 3.1011521 12.46875 9.9375003 12.46875 9.9375 L 14.46875 14.5 C 18.173566 14.5 20.656251 12.6875 20.65625 12.6875 C 20.65625 12.6875 24.40713 4.4120618 21.125 2.6875 C 20.718044 2.4736692 20.271408 2.4498354 19.8125 2.53125 z "
-       xlink:href="#rect1317"
-       style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-       id="path1328"
-       inkscape:href="#rect1317"
-       d="M 20,3.5 C 18.994143,3.6784485 17.104459,5.3425998 15.71875,7.0625 C 14.49821,8.5773965 13.796948,9.7026949 13.59375,10.03125 L 15.0625,13.375 C 17.800353,13.18702 19.57294,12.186586 19.84375,12 C 19.951976,11.755161 20.690984,10.140091 21.15625,8.125 C 21.40574,7.0444453 21.527392,5.9266549 21.4375,5.09375 C 21.347608,4.2608451 21.11837,3.8053161 20.65625,3.5625 C 20.487225,3.4736876 20.316977,3.4437653 20,3.5 z " />
-    <path
-       sodipodi:type="arc"
-       style="opacity:1;fill:#75507b;fill-opacity:1;stroke:#5c3566;stroke-width:1.35211551;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path2192"
-       sodipodi:cx="13.4375"
-       sodipodi:cy="15.825892"
-       sodipodi:rx="0.8035714"
-       sodipodi:ry="5.1116071"
-       d="M 14.241071 15.825892 A 0.8035714 5.1116071 0 1 1  12.633929,15.825892 A 0.8035714 5.1116071 0 1 1  14.241071 15.825892 z"
-       transform="matrix(0.603448,-0.487879,0.280285,0.679821,0.46572,8.794406)" />
-    <image
-       id="image1314"
-       height="31.456791"
-       width="30.814816"
-       sodipodi:absref="/home/hbons/Desktop/MSN_groups_butterfly.gif"
-       xlink:href="/home/hbons/Desktop/MSN_groups_butterfly.gif"
-       x="-32"
-       y="-23.456791"
-       style="opacity:0.72727272" />
-    <image
-       id="image2210"
-       height="8"
-       width="8"
-       sodipodi:absref="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       xlink:href="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       x="-16"
-       y="14" />
-  </g>
-</svg>
--- a/pidgin/pixmaps/protocols/22/scalable/myspace.svg	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="24"
-   height="24"
-   id="svg2160"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   sodipodi:docname="myspace.svg"
-   sodipodi:docbase="/home/hbons/Desktop"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape"
-   sodipodi:modified="true"
-   version="1.0">
-  <defs
-     id="defs2162">
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3147">
-      <stop
-         style="stop-color:#eeeeec;stop-opacity:1;"
-         offset="0"
-         id="stop3149" />
-      <stop
-         style="stop-color:#eeeeec;stop-opacity:0;"
-         offset="1"
-         id="stop3151" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3147"
-       id="linearGradient3153"
-       x1="6.0203052"
-       y1="1.0398448"
-       x2="26.101271"
-       y2="25.83909"
-       gradientUnits="userSpaceOnUse" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="9.8994949"
-     inkscape:cx="31.349135"
-     inkscape:cy="11.3794"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     inkscape:grid-bbox="true"
-     inkscape:document-units="px"
-     inkscape:window-width="1440"
-     inkscape:window-height="847"
-     inkscape:window-x="3"
-     inkscape:window-y="25"
-     width="24px"
-     height="24px" />
-  <metadata
-     id="metadata2165">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     id="layer1"
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer">
-    <path
-       style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:#888a85;stroke-width:1.00000012;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 17 1.5 C 15.068 1.5 13.5 3.0680001 13.5 5 C 13.5 6.932 15.068 8.5 17 8.5 C 18.932 8.5 20.499999 6.932 20.5 5 C 20.5 3.068 18.931999 1.4999999 17 1.5 z M 10.5 2.5 C 8.8439999 2.5 7.5000001 3.8439999 7.5 5.5 C 7.5 7.1559999 8.8439997 8.4999996 10.5 8.5 C 9.395701 8.5527352 8.4448563 9.5454035 7.875 10.4375 C 7.830859 8.7148111 7.161553 7.5791344 5.6875 7.5 C 6.7035586 7.4052513 7.5 6.5406823 7.5 5.5 C 7.5 4.396 6.604 3.5 5.5 3.5 C 4.396 3.5 3.4999999 4.396 3.5 5.5 C 3.5 6.5828941 4.3626534 7.4666427 5.4375 7.5 C 4.352857 7.6401732 3.5000005 8.6243123 3.5 9.875 L 3.5 14.53125 L 7.5625 14.53125 L 7.5625 18.53125 L 12.5 18.53125 L 12.5 22.5 L 21.5 22.5 C 21.499867 19.408873 21.5 16.303843 21.5 13.21875 C 21.5 10.634939 19.434134 8.53125 16.875 8.53125 C 15.587036 8.5312503 14.40291 9.424387 13.5625 10.28125 C 13.046577 9.1148819 11.916283 8.5 10.59375 8.5 C 12.205095 8.4489386 13.5 7.1236737 13.5 5.5 C 13.5 3.8440001 12.156 2.5 10.5 2.5 z "
-       id="path3149" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-1.00878"
-       inkscape:original="M 17 1.5 C 15.068 1.5 13.5 3.0680001 13.5 5 C 13.5 6.932 15.068 8.5 17 8.5 C 18.932 8.5 20.499999 6.932 20.5 5 C 20.5 3.068 18.931999 1.4999999 17 1.5 z M 10.5 2.5 C 8.8439999 2.5 7.5000001 3.8439999 7.5 5.5 C 7.5 7.1559999 8.8439997 8.4999996 10.5 8.5 C 9.395701 8.5527352 8.4448563 9.5454035 7.875 10.4375 C 7.830859 8.7148111 7.161553 7.5791344 5.6875 7.5 C 6.7035586 7.4052513 7.5 6.5406823 7.5 5.5 C 7.5 4.396 6.604 3.5 5.5 3.5 C 4.396 3.5 3.4999999 4.396 3.5 5.5 C 3.5 6.5828941 4.3626534 7.4666427 5.4375 7.5 C 4.352857 7.6401732 3.5000005 8.6243123 3.5 9.875 L 3.5 14.53125 L 7.5625 14.53125 L 7.5625 18.53125 L 12.5 18.53125 L 12.5 22.5 L 21.5 22.5 C 21.499867 19.408873 21.5 16.303843 21.5 13.21875 C 21.5 10.634939 19.434134 8.53125 16.875 8.53125 C 15.587036 8.5312503 14.40291 9.424387 13.5625 10.28125 C 13.046577 9.1148819 11.916283 8.5 10.59375 8.5 C 12.205095 8.4489386 13.5 7.1236737 13.5 5.5 C 13.5 3.8440001 12.156 2.5 10.5 2.5 z "
-       style="opacity:1;fill:url(#linearGradient3153);fill-opacity:1.0;stroke:#ffffff;stroke-width:1.00000012;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path2174"
-       d="M 17,2.5 C 15.613813,2.5 14.5,3.6138135 14.5,5 C 14.5,6.3861867 15.613813,7.5 17,7.5 C 18.386187,7.5 19.499999,6.3861873 19.5,5 C 19.5,3.6138137 18.386185,2.4999999 17,2.5 z M 10.5,3.5 C 9.3898132,3.5 8.5000001,4.3898131 8.5,5.5 C 8.5,6.5997176 9.3733703,7.4835976 10.46875,7.5 C 10.499983,7.4985473 10.531267,7.4985473 10.5625,7.5 C 10.572807,7.4996734 10.583484,7.5004795 10.59375,7.5 C 11.655314,7.4504166 12.5,6.5769144 12.5,5.5 C 12.5,4.3898135 11.610187,3.5 10.5,3.5 z M 5.5,4.5 C 4.9418133,4.5 4.4999999,4.9418134 4.5,5.5 C 4.5,6.0471523 4.9293308,6.4832594 5.46875,6.5 C 5.4999831,6.4985473 5.5312669,6.4985473 5.5625,6.5 C 5.572916,6.4998387 5.583334,6.4998387 5.59375,6.5 C 6.0934659,6.4534009 6.5,6.0259981 6.5,5.5 C 6.5,4.9418133 6.0581867,4.5 5.5,4.5 z M 5.53125,8.5 C 4.98621,8.5848564 4.5000003,9.0959604 4.5,9.875 L 4.5,13.53125 L 7.5625,13.53125 C 8.1127746,13.536073 8.557677,13.980975 8.5625,14.53125 L 8.5625,17.53125 L 12.5,17.53125 C 13.050275,17.536073 13.495177,17.980975 13.5,18.53125 L 13.5,21.5 L 20.5,21.5 C 20.499928,18.739558 20.5,15.971417 20.5,13.21875 C 20.5,11.172647 18.881301,9.53125 16.875,9.53125 C 16.053394,9.5312502 15.035346,10.231141 14.28125,11 C 14.045303,11.244024 13.70246,11.353041 13.368907,11.290106 C 13.035354,11.227172 12.755806,11.000722 12.625,10.6875 C 12.280526,9.9087333 11.615906,9.5089368 10.625,9.5 C 10.614584,9.5001613 10.604166,9.5001613 10.59375,9.5 C 10.583334,9.5001613 10.572916,9.5001613 10.5625,9.5 C 10.033117,9.5252804 9.1973144,10.219569 8.71875,10.96875 C 8.4774641,11.327111 8.0347855,11.49207 7.6178253,11.378996 C 7.2008651,11.265922 6.9021772,10.899915 6.875,10.46875 C 6.8561284,9.7322475 6.6929787,9.2126452 6.5,8.9375 C 6.312535,8.6702161 6.1126513,8.5308317 5.65625,8.5 C 5.645834,8.5001613 5.635416,8.5001613 5.625,8.5 C 5.5937669,8.5014527 5.5624831,8.5014527 5.53125,8.5 L 5.53125,8.5 z " />
-  </g>
-</svg>
--- a/pidgin/pixmaps/protocols/22/scalable/yahoo.svg	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="24"
-   height="24"
-   id="svg1307"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   version="1.0"
-   sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/22/scalable"
-   sodipodi:docname="yahoo.svg"
-   inkscape:export-filename="/home/hbons/GUI/Tango/Gaim Refresh/protocols/22/yahoo.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
-  <defs
-     id="defs1309">
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3150">
-      <stop
-         style="stop-color:#2e3436;stop-opacity:1;"
-         offset="0"
-         id="stop3152" />
-      <stop
-         style="stop-color:#2e3436;stop-opacity:0;"
-         offset="1"
-         id="stop3154" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3150"
-       id="radialGradient3156"
-       cx="10.748654"
-       cy="10.457643"
-       fx="10.748654"
-       fy="10.457643"
-       r="6.6449099"
-       gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient4123">
-      <stop
-         style="stop-color:#ff0000;stop-opacity:1;"
-         offset="0"
-         id="stop4125" />
-      <stop
-         style="stop-color:#ff0000;stop-opacity:0;"
-         offset="1"
-         id="stop4127" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4123"
-       id="linearGradient4129"
-       x1="20.102123"
-       y1="10.489645"
-       x2="20.102123"
-       y2="3.0395992"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4123"
-       id="linearGradient4131"
-       x1="9.7634506"
-       y1="11.499014"
-       x2="9.7634506"
-       y2="0.12942761"
-       gradientUnits="userSpaceOnUse" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="29.290175"
-     inkscape:cx="18.292625"
-     inkscape:cy="12.739723"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     inkscape:grid-bbox="true"
-     inkscape:document-units="px"
-     fill="#a40000"
-     showguides="true"
-     inkscape:guide-bbox="true"
-     inkscape:window-width="1268"
-     inkscape:window-height="971"
-     inkscape:window-x="6"
-     inkscape:window-y="25" />
-  <metadata
-     id="metadata1312">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     id="layer1"
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer">
-    <rect
-       style="opacity:0;fill:none;fill-opacity:1;stroke:#a40000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="rect3203"
-       width="0"
-       height="2.5118096"
-       x="6"
-       y="6.4881902" />
-    <path
-       sodipodi:type="arc"
-       style="opacity:0.6;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path3140"
-       sodipodi:cx="10.748654"
-       sodipodi:cy="10.457643"
-       sodipodi:rx="6.6449099"
-       sodipodi:ry="2.3675451"
-       d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1  4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1  17.393564 10.457643 z"
-       transform="matrix(1.730648,0,0,1.300982,-7.102139,4.474929)" />
-    <path
-       style="opacity:1;fill:url(#linearGradient4131);fill-opacity:1.0;stroke:#a40000;stroke-width:0.99999958;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 0.49908419,5.4951356 L 0.49908419,7.5376225 L 3.3376273,7.5964463 L 8.515629,12.953307 L 8.515629,15.459996 L 5.4587364,15.459996 L 5.4587364,17.502482 L 13.56886,17.502482 L 13.56886,15.459996 L 10.463631,15.459996 L 10.463631,12.891414 L 14.972535,8.5279191 L 16.532174,8.5279191 L 16.532174,6.5473259 L 11.478943,6.5473259 L 11.478943,8.5279191 L 12.040413,8.5279191 L 9.8296564,10.446619 L 9.1979396,10.446619 L 5.9890137,7.5376225 L 9.5449908,7.5376225 L 9.5449908,5.4951356 L 0.49908419,5.4951356 z "
-       id="rect3219"
-       sodipodi:nodetypes="ccccccccccccccccccccccc" />
-    <path
-       sodipodi:type="arc"
-       style="opacity:1;fill:#ff0000;fill-opacity:1;stroke:#a40000;stroke-width:0.97808969;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path4110"
-       sodipodi:cx="16.860584"
-       sodipodi:cy="16.429377"
-       sodipodi:rx="1.3865612"
-       sodipodi:ry="1.5252173"
-       d="M 18.247145 16.429377 A 1.3865612 1.5252173 0 1 1  15.474023,16.429377 A 1.3865612 1.5252173 0 1 1  18.247145 16.429377 z"
-       transform="matrix(1.06013,0,0,0.986015,-0.904476,0.796501)" />
-    <path
-       style="fill:url(#linearGradient4129);fill-opacity:1.0;stroke:#a40000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 18.485372,6.4981503 L 22.514636,6.4981503 L 18.576821,12.500953 L 18.485372,6.4981503 z "
-       id="rect4112"
-       sodipodi:nodetypes="cccc" />
-  </g>
-</svg>
Binary file pidgin/pixmaps/protocols/22/yahoo.png has changed
Binary file pidgin/pixmaps/protocols/48/msn.png has changed
Binary file pidgin/pixmaps/protocols/48/mxit.png has changed
Binary file pidgin/pixmaps/protocols/48/myspace.png has changed
Binary file pidgin/pixmaps/protocols/48/yahoo.png has changed
--- a/pidgin/pixmaps/protocols/scalable/msn.svg	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="48"
-   height="48"
-   id="svg2"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   version="1.0"
-   sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/48"
-   sodipodi:docname="msn.svg"
-   inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/48/msn.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
-  <defs
-     id="defs4">
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3816">
-      <stop
-         style="stop-color:#000000;stop-opacity:1;"
-         offset="0"
-         id="stop3818" />
-      <stop
-         style="stop-color:#000000;stop-opacity:0;"
-         offset="1"
-         id="stop3820" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2228">
-      <stop
-         style="stop-color:#f56600;stop-opacity:1;"
-         offset="0"
-         id="stop2230" />
-      <stop
-         style="stop-color:#f56600;stop-opacity:0;"
-         offset="1"
-         id="stop2232" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2219">
-      <stop
-         style="stop-color:#3465a4;stop-opacity:1;"
-         offset="0"
-         id="stop2221" />
-      <stop
-         style="stop-color:#3465a4;stop-opacity:0;"
-         offset="1"
-         id="stop2223" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3816"
-       id="radialGradient1358"
-       gradientUnits="userSpaceOnUse"
-       cx="31.112698"
-       cy="19.008621"
-       fx="31.112698"
-       fy="19.008621"
-       r="8.6620579"
-       gradientTransform="matrix(1.904859,0,0,0.57723,-32.76529,27.09015)" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2219"
-       id="linearGradient1360"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1.427299,0,0,1.408267,0.332861,3.39912)"
-       x1="10.329217"
-       y1="14.96656"
-       x2="16.580788"
-       y2="20.092552" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2228"
-       id="linearGradient1362"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1.489007,0,0,1.428565,1.731241,3.002037)"
-       x1="20.998175"
-       y1="11.741063"
-       x2="18.544895"
-       y2="23.366545" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="14.778489"
-     inkscape:cx="32.469518"
-     inkscape:cy="22.977647"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     fill="#edd400"
-     showguides="true"
-     inkscape:guide-bbox="true"
-     inkscape:window-width="1268"
-     inkscape:window-height="971"
-     inkscape:window-x="6"
-     inkscape:window-y="21" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1">
-    <path
-       style="opacity:0.4;color:#000000;fill:url(#radialGradient1358);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       d="M 43.00001,38.062496 C 43.00001,40.822496 35.608012,43.062496 26.500013,43.062496 C 17.392013,43.062496 10.000014,40.822496 10.000014,38.062496 C 10.000014,35.302496 17.392013,33.062496 26.500013,33.062496 C 35.608012,33.062496 43.00001,35.302496 43.00001,38.062496 z "
-       id="path4318" />
-    <path
-       style="fill:#edd400;fill-opacity:1;stroke:#c4a000;stroke-width:1.00000083;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 34.662639,20.335823 C 39.495137,21.781376 40.098879,38.560591 34.609432,38.560591 C 29.18649,38.560591 17.111515,15.085731 34.662639,20.335823 z "
-       id="rect2194" />
-    <path
-       style="opacity:0.5;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.00000024;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 29.5,20.59375 C 28.488762,20.699063 27.850577,20.9863 27.40625,21.40625 C 26.961923,21.8262 26.695785,22.399576 26.5625,23.15625 C 26.295929,24.669599 26.724448,26.888006 27.625,29.09375 C 28.525552,31.299494 29.853318,33.518217 31.21875,35.125 C 32.584182,36.731783 34.047656,37.59375 34.625,37.59375 C 35.065414,37.59375 35.396266,37.452251 35.75,37.125 C 36.103734,36.797749 36.436723,36.267837 36.71875,35.5625 C 37.282805,34.151825 37.566795,32.092358 37.53125,30 C 37.495705,27.907642 37.16426,25.762788 36.5625,24.125 C 35.96074,22.487212 35.097603,21.497403 34.375,21.28125 C 32.261511,20.64904 30.658881,20.473061 29.5,20.59375 z "
-       id="path2259" />
-    <path
-       style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 24.98559,40.707419 C 20.31754,40.707419 7.959768,29.343494 17.418553,22.824249 C 26.869109,16.310672 29.725145,40.707419 24.98559,40.707419 z "
-       id="rect2201" />
-    <path
-       style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999911;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 20.429472,22.564494 C 19.813992,22.53919 18.946491,22.754031 17.792299,23.48193 C 15.396153,24.993077 14.598274,26.486625 14.509287,28.117394 C 14.420299,29.74816 15.197952,31.630592 16.500622,33.380577 C 17.803294,35.130559 19.637587,36.743254 21.398232,37.871181 C 23.158877,38.999109 24.734359,39.505165 25.355011,39.505165 C 25.714095,39.505165 25.973542,38.578409 26.134382,37.774606 C 26.456061,36.166999 26.487926,33.806821 26.080561,31.449134 C 25.673198,29.091442 24.821426,26.682961 23.766308,25.027083 C 22.711189,23.371206 21.583796,22.611947 20.429472,22.564494 z "
-       id="path2254" />
-    <path
-       style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 38.290982,9.1309894 C 35.842841,9.5672523 32.283411,12.929344 29.603482,16.28724 C 27.08796,19.439138 25.478582,22.11333 25.259732,22.47474 L 28.572232,30.03724 C 34.665525,29.832673 38.559865,27.128092 38.853482,26.91224 C 39.014293,26.551466 40.549044,23.055678 41.478482,19.03724 C 41.967713,16.922043 42.260097,14.730906 42.072232,12.97474 C 41.884367,11.218574 41.30548,10.015388 40.103482,9.3809894 C 39.532517,9.0796416 38.992058,9.0060564 38.290982,9.1309894 z "
-       id="path2245" />
-    <path
-       style="fill:url(#linearGradient1360);fill-opacity:1;stroke:#204a87;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 2.9244668,13.205506 C 5.4909473,8.9616426 31.868508,26.916697 20.798169,29.292473 C 9.7422309,31.665159 0.38413836,17.406122 2.9244668,13.205506 z "
-       id="rect2197" />
-    <path
-       style="opacity:0.2;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999905;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 4.0077208,17.150417 C 4.6613048,18.933996 5.9435775,21.021975 7.6235197,22.895457 C 10.983405,26.64242 15.833733,29.401717 20.89796,28.310863 C 21.928379,28.088904 22.232928,27.802155 22.334374,27.651594 C 22.435813,27.501039 22.52111,27.289844 22.334374,26.709786 C 21.960899,25.54967 20.384396,23.482994 18.173725,21.529832 C 15.963059,19.576669 13.153701,17.6285 10.545878,16.161517 C 7.9380537,14.694536 5.1976761,13.680027 3.975949,13.563989 C 3.3254548,13.502207 3.3541371,15.366838 4.0077208,17.150417 z "
-       id="path2249" />
-    <path
-       style="fill:url(#linearGradient1362);fill-opacity:1;stroke:#ce5d00;stroke-width:1.00000048;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 23.497613,20.84222 C 23.497613,20.84222 33.747199,3.7130144 39.940221,6.9816102 C 46.183621,10.276795 39.032218,26.044415 39.032218,26.044415 C 39.032218,26.044415 34.34592,29.558038 27.298467,29.558038 L 23.497613,20.84222 z "
-       id="rect1317" />
-    <path
-       style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 37.65625,7.5937494 C 35.207156,8.0301823 31.648755,11.392008 28.96875,14.75 C 26.453156,17.901987 24.843855,20.576081 24.625,20.9375 L 27.9375,28.5 C 34.029365,28.295478 37.922857,25.592475 38.21875,25.375 C 38.379566,25.014217 39.91427,21.518622 40.84375,17.5 C 41.333003,15.384706 41.625396,13.193957 41.4375,11.4375 C 41.249604,9.6810425 40.671312,8.4784456 39.46875,7.8437494 C 38.897466,7.5422332 38.357596,7.4687683 37.65625,7.5937494 z "
-       id="path1328" />
-    <path
-       style="fill:#75507b;fill-opacity:1;stroke:#5c3566;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 25.75715,25.780775 C 27.420525,29.605605 28.313593,33.06003 27.750608,33.491546 C 27.187623,33.923061 25.380722,31.169067 23.717348,27.344236 C 22.053974,23.519407 21.160905,20.064982 21.72389,19.633467 C 22.286875,19.201951 24.093776,21.955945 25.75715,25.780775 z "
-       id="path2192" />
-  </g>
-</svg>
--- a/pidgin/pixmaps/protocols/scalable/mxit.svg	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 width="48px" height="48px" viewBox="0 0 48 48" enable-background="new 0 0 48 48" xml:space="preserve">
-<g>
-	
-		<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-0.5654" y1="38.3721" x2="-1.3676" y2="-7.5858" gradientTransform="matrix(1 0 0 -1 24.9448 39.3594)">
-		<stop  offset="0" style="stop-color:#D67B43"/>
-		<stop  offset="0.2638" style="stop-color:#D16841"/>
-		<stop  offset="1" style="stop-color:#CB222B"/>
-	</linearGradient>
-	<path fill="url(#SVGID_1_)" d="M1,23.964c0,17.022,5.954,22.978,22.978,22.978s22.978-5.953,22.978-22.978
-		C46.956,7.315,41.254,1.259,25.077,1h-2.194C6.702,1.259,1,7.315,1,23.964"/>
-	<g>
-		<rect x="20.251" y="22.668" fill="#FFFFFF" width="6.656" height="12.984"/>
-		<path fill="#FFFFFF" d="M30.659,12.288h-20.03v5.796l0,0c0,0.003,0,0.007,0,0.011c0,0.478,0.387,0.864,0.865,0.864
-			c0.008,0,0.017-0.002,0.027-0.002c0,0.002,0,0.003,0.002,0.005h15.795c0,0,3.34,0,3.34,3.34v10.012
-			c0,1.947,1.39,3.338,3.336,3.338h3.331V18.714C37.156,12.291,30.659,12.288,30.659,12.288z"/>
-		<path fill="#FFFFFF" d="M10.629,32.314c0,1.949,1.391,3.338,3.337,3.338h3.322V22.657h-6.659V32.314z"/>
-	</g>
-</g>
-</svg>
--- a/pidgin/pixmaps/protocols/scalable/yahoo.svg	Wed Oct 05 22:15:51 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="48"
-   height="48"
-   id="svg1307"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   version="1.0"
-   sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/48"
-   sodipodi:docname="yahoo.svg"
-   inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/48/yahoo.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
-  <defs
-     id="defs1309">
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2211">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop2213" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop2215" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3150">
-      <stop
-         style="stop-color:#2e3436;stop-opacity:1;"
-         offset="0"
-         id="stop3152" />
-      <stop
-         style="stop-color:#2e3436;stop-opacity:0;"
-         offset="1"
-         id="stop3154" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3150"
-       id="radialGradient3156"
-       cx="10.748654"
-       cy="10.457643"
-       fx="10.748654"
-       fy="10.457643"
-       r="6.6449099"
-       gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient4123">
-      <stop
-         style="stop-color:#ff0000;stop-opacity:1;"
-         offset="0"
-         id="stop4125" />
-      <stop
-         style="stop-color:#ff0000;stop-opacity:0;"
-         offset="1"
-         id="stop4127" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4123"
-       id="linearGradient2206"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1.871443,0,0,1.871443,1.990827,1.339082)"
-       x1="9.7634506"
-       y1="11.499014"
-       x2="9.7634506"
-       y2="0.12942761" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2211"
-       id="linearGradient2217"
-       x1="36.249207"
-       y1="7.6495404"
-       x2="36.249207"
-       y2="23.063982"
-       gradientUnits="userSpaceOnUse" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="11.098901"
-     inkscape:cx="49.54817"
-     inkscape:cy="29.700698"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     inkscape:grid-bbox="true"
-     inkscape:document-units="px"
-     fill="#a40000"
-     showguides="true"
-     inkscape:guide-bbox="true"
-     inkscape:window-width="1268"
-     inkscape:window-height="971"
-     inkscape:window-x="6"
-     inkscape:window-y="21" />
-  <metadata
-     id="metadata1312">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     id="layer1"
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer">
-    <rect
-       style="opacity:0;fill:none;fill-opacity:1;stroke:#a40000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="rect3203"
-       width="0"
-       height="2.5118096"
-       x="6"
-       y="6.4881902" />
-    <path
-       sodipodi:type="arc"
-       style="opacity:0.6;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path3140"
-       sodipodi:cx="10.748654"
-       sodipodi:cy="10.457643"
-       sodipodi:rx="6.6449099"
-       sodipodi:ry="2.3675451"
-       d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1  4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1  17.393564 10.457643 z"
-       transform="matrix(3.163562,0,0,2.111892,-10.02562,12.91459)" />
-    <path
-       style="opacity:1;fill:#ff0000;fill-opacity:1;stroke:#a40000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 36.593752,13.5 L 36.750002,24.71875 L 44.125002,13.5 L 36.593752,13.5 z M 33.406252,30.34375 C 32.052922,30.519922 31.000003,31.724054 31.000002,33.15625 C 31.000002,34.70982 32.231505,35.96875 33.750002,35.96875 C 35.268499,35.96875 36.500002,34.70982 36.500002,33.15625 C 36.500002,31.60268 35.268499,30.343751 33.750002,30.34375 C 33.631369,30.34375 33.520941,30.32882 33.406252,30.34375 z "
-       id="path4110" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-1.0402364"
-       inkscape:original="M 36.59375 13.5 L 36.75 24.71875 L 44.125 13.5 L 36.59375 13.5 z M 33.40625 30.34375 C 32.052918 30.519922 31.000001 31.724054 31 33.15625 C 31 34.70982 32.231503 35.96875 33.75 35.96875 C 35.268495 35.96875 36.5 34.70982 36.5 33.15625 C 36.499998 31.60268 35.268497 30.343751 33.75 30.34375 C 33.631365 30.34375 33.520939 30.32882 33.40625 30.34375 z "
-       xlink:href="#path4110"
-       style="opacity:0.35;fill:url(#linearGradient2217);fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path2209"
-       inkscape:href="#path4110"
-       d="M 37.625,15.0625 L 37.71875,21.875 L 42.1875,15.0625 L 37.625,15.0625 z M 33.53125,31.90625 C 32.711111,32.013013 32.031251,32.765143 32.03125,33.6875 C 32.031249,34.691344 32.806451,35.46875 33.75,35.46875 C 34.693551,35.46875 35.46875,34.691346 35.46875,33.6875 C 35.468751,32.683656 34.69355,31.906251 33.75,31.90625 C 33.544091,31.90625 33.473148,31.913814 33.53125,31.90625 z " />
-    <path
-       style="opacity:1;fill:url(#linearGradient2206);fill-opacity:1;stroke:#a40000;stroke-width:0.99999976;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 2.6545432,11.532816 L 4.353345,15.445312 L 7.741467,15.555398 L 17.47685,25.310159 L 17.4318,31.506326 L 12.428056,31.384739 L 11.665952,34.499424 L 27.339128,34.54589 L 26.551973,31.519888 L 21.572919,31.603085 L 21.572919,25.191498 L 28.209096,17.523843 L 31.468823,17.433744 L 32.573193,13.532585 L 23.168883,13.473142 L 21.694773,17.410562 L 23.776066,17.4644 L 19.977012,20.889333 L 13.198929,15.445312 L 17.758833,15.445312 L 20.124034,11.577865 L 2.6545432,11.532816 z "
-       id="rect3219"
-       sodipodi:nodetypes="cccccccccccccccccccccc" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.98856229"
-       inkscape:original="M 2.65625 11.53125 L 4.34375 15.4375 L 7.75 15.5625 L 17.46875 25.3125 L 17.4375 31.5 L 12.4375 31.375 L 11.65625 34.5 L 27.34375 34.53125 L 26.5625 31.53125 L 21.5625 31.59375 L 21.5625 25.1875 L 28.21875 17.53125 L 31.46875 17.4375 L 32.5625 13.53125 L 23.15625 13.46875 L 21.6875 17.40625 L 23.78125 17.46875 L 19.96875 20.875 L 13.1875 15.4375 L 17.75 15.4375 L 20.125 11.5625 L 2.65625 11.53125 z "
-       xlink:href="#rect3219"
-       style="opacity:0.35;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999976;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path2204"
-       inkscape:href="#rect3219"
-       d="M 4.15625,13.0625 L 5,15 L 7.78125,15.09375 C 8.0317447,15.110809 8.266366,15.222533 8.4375,15.40625 L 18.15625,25.15625 C 18.347286,25.335037 18.45966,25.58226 18.46875,25.84375 L 18.4375,32.03125 C 18.44087,32.30297 18.33225,32.564099 18.137167,32.75327 C 17.942084,32.942442 17.677738,33.042977 17.40625,33.03125 L 13.21875,32.9375 L 12.9375,34.03125 L 26.0625,34.0625 L 25.78125,33.0625 L 21.5625,33.125 C 21.296354,33.12807 21.040212,33.0237 20.852006,32.835494 C 20.6638,32.647288 20.55943,32.391146 20.5625,32.125 L 20.5625,25.71875 C 20.562717,25.476777 20.651667,25.243286 20.8125,25.0625 L 27.46875,17.40625 C 27.649517,17.19593 27.910308,17.071204 28.1875,17.0625 L 30.71875,17 L 31.28125,15.0625 L 23.84375,15 L 23.125,16.96875 L 23.8125,17 C 24.228223,17.002399 24.598033,17.264612 24.737859,17.656122 C 24.877684,18.047632 24.757648,18.48479 24.4375,18.75 L 20.625,22.15625 C 20.263408,22.479557 19.720674,22.492795 19.34375,22.1875 L 12.5625,16.75 C 12.215365,16.491727 12.076498,16.037735 12.219751,15.629463 C 12.363005,15.221191 12.755094,14.953499 13.1875,14.96875 L 17.1875,14.96875 L 18.34375,13.09375 L 4.15625,13.0625 z " />
-  </g>
-</svg>
--- a/pidgin/plugins/disco/xmppdisco.c	Wed Oct 05 22:15:51 2016 -0500
+++ b/pidgin/plugins/disco/xmppdisco.c	Thu Oct 06 10:05:06 2016 -0400
@@ -252,7 +252,6 @@
 } disco_type_mappings[] = {
 	{ "gadu-gadu", "gadu-gadu" }, /* the prpl is prpl-gg, but list_icon returns "gadu-gadu" */
 	{ "sametime",  "meanwhile" },
-	{ "myspaceim", "myspace" },
 	{ "xmpp",      "jabber" }, /* prpl-jabber (mentioned in case the prpl is renamed so this line will match) */
 	{ NULL,        NULL }
 };
--- a/pidgin/plugins/gevolution/add_buddy_dialog.c	Wed Oct 05 22:15:51 2016 -0500
+++ b/pidgin/plugins/gevolution/add_buddy_dialog.c	Thu Oct 06 10:05:06 2016 -0400
@@ -288,21 +288,18 @@
 	{
 		EContact *contact = E_CONTACT(c->data);
 		const char *name;
-		GList *aims, *jabbers, *yahoos, *msns, *icqs, *novells, *ggs;
+		GList *aims, *jabbers, *icqs, *novells, *ggs;
 
 		name = e_contact_get_const(contact, E_CONTACT_FULL_NAME);
 
 		aims    = e_contact_get(contact, E_CONTACT_IM_AIM);
 		jabbers = e_contact_get(contact, E_CONTACT_IM_JABBER);
-		yahoos  = e_contact_get(contact, E_CONTACT_IM_YAHOO);
-		msns    = e_contact_get(contact, E_CONTACT_IM_MSN);
 		icqs    = e_contact_get(contact, E_CONTACT_IM_ICQ);
 		novells = e_contact_get(contact, E_CONTACT_IM_GROUPWISE);
 		ggs     = e_contact_get(contact, E_CONTACT_IM_GADUGADU);
 
-		if (aims == NULL && jabbers == NULL && yahoos == NULL &&
-			msns == NULL && icqs == NULL && novells == NULL &&
-			ggs == NULL)
+		if (aims == NULL && jabbers == NULL &&
+			icqs == NULL && novells == NULL && ggs == NULL)
 		{
 			GtkTreeIter iter;
 
@@ -317,8 +314,6 @@
 		{
 			add_ims(dialog, contact, name, aims,    "prpl-aim");
 			add_ims(dialog, contact, name, jabbers, "prpl-jabber");
-			add_ims(dialog, contact, name, yahoos,  "prpl-yahoo");
-			add_ims(dialog, contact, name, msns,    "prpl-msn");
 			add_ims(dialog, contact, name, icqs,    "prpl-icq");
 			add_ims(dialog, contact, name, novells, "prpl-novell");
 			add_ims(dialog, contact, name, ggs,     "prpl-gg");
@@ -367,7 +362,7 @@
 	{
 		EContact *contact = E_CONTACT(l->data);
 		const char *name;
-		GList *aims, *jabbers, *yahoos, *msns, *icqs, *novells, *ggs;
+		GList *aims, *jabbers, *icqs, *novells, *ggs;
 
 		name = e_contact_get_const(contact, E_CONTACT_FULL_NAME);
 
@@ -379,15 +374,12 @@
 
 		aims    = e_contact_get(contact, E_CONTACT_IM_AIM);
 		jabbers = e_contact_get(contact, E_CONTACT_IM_JABBER);
-		yahoos  = e_contact_get(contact, E_CONTACT_IM_YAHOO);
-		msns    = e_contact_get(contact, E_CONTACT_IM_MSN);
 		icqs    = e_contact_get(contact, E_CONTACT_IM_ICQ);
 		novells = e_contact_get(contact, E_CONTACT_IM_GROUPWISE);
 		ggs     = e_contact_get(contact, E_CONTACT_IM_GADUGADU);
 
-		if (aims == NULL && jabbers == NULL && yahoos == NULL &&
-			msns == NULL && icqs == NULL && novells == NULL &&
-			ggs == NULL)
+		if (aims == NULL && jabbers == NULL &&
+			icqs == NULL && novells == NULL && ggs == NULL)
 		{
 			GtkTreeIter iter;
 
@@ -402,8 +394,6 @@
 		{
 			add_ims(dialog, contact, name, aims,    "prpl-aim");
 			add_ims(dialog, contact, name, jabbers, "prpl-jabber");
-			add_ims(dialog, contact, name, yahoos,  "prpl-yahoo");
-			add_ims(dialog, contact, name, msns,    "prpl-msn");
 			add_ims(dialog, contact, name, icqs,    "prpl-icq");
 			add_ims(dialog, contact, name, novells, "prpl-novell");
 			add_ims(dialog, contact, name, ggs,     "prpl-gg");
--- a/pidgin/plugins/gevolution/gevo-util.c	Wed Oct 05 22:15:51 2016 -0500
+++ b/pidgin/plugins/gevolution/gevo-util.c	Thu Oct 06 10:05:06 2016 -0400
@@ -103,10 +103,6 @@
 		protocol_field = E_CONTACT_IM_AIM;
 	else if (!strcmp(protocol_id, "prpl-icq"))
 		protocol_field = E_CONTACT_IM_ICQ;
-	else if (!strcmp(protocol_id, "prpl-msn"))
-		protocol_field = E_CONTACT_IM_MSN;
-	else if (!strcmp(protocol_id, "prpl-yahoo"))
-		protocol_field = E_CONTACT_IM_YAHOO;
 	else if (!strcmp(protocol_id, "prpl-jabber"))
 		protocol_field = E_CONTACT_IM_JABBER;
 	else if (!strcmp(protocol_id, "prpl-novell"))
@@ -165,23 +161,5 @@
 		g_object_unref(contact);
 	}
 
-	if (mail == NULL)
-	{
-		PurpleAccount *account = purple_buddy_get_account(buddy);
-		const char *prpl_id = purple_account_get_protocol_id(account);
-
-		if (!strcmp(prpl_id, "prpl-msn"))
-		{
-			mail = g_strdup(purple_normalize(account,
-										   purple_buddy_get_name(buddy)));
-		}
-		else if (!strcmp(prpl_id, "prpl-yahoo"))
-		{
-			mail = g_strdup_printf("%s@yahoo.com",
-								   purple_normalize(account,
-												  purple_buddy_get_name(buddy)));
-		}
-	}
-
 	return mail;
 }
--- a/pidgin/plugins/gevolution/gevolution.c	Wed Oct 05 22:15:51 2016 -0500
+++ b/pidgin/plugins/gevolution/gevolution.c	Thu Oct 06 10:05:06 2016 -0400
@@ -121,8 +121,6 @@
 
 	update_ims_from_contact(contact, name, "prpl-aim",    E_CONTACT_IM_AIM);
 	update_ims_from_contact(contact, name, "prpl-jabber", E_CONTACT_IM_JABBER);
-	update_ims_from_contact(contact, name, "prpl-yahoo",  E_CONTACT_IM_YAHOO);
-	update_ims_from_contact(contact, name, "prpl-msn",    E_CONTACT_IM_MSN);
 	update_ims_from_contact(contact, name, "prpl-icq",    E_CONTACT_IM_ICQ);
 	update_ims_from_contact(contact, name, "prpl-novell", E_CONTACT_IM_GROUPWISE);
 	update_ims_from_contact(contact, name, "prpl-gg",     E_CONTACT_IM_GADUGADU);
--- a/pidgin/plugins/gevolution/new_person_dialog.c	Wed Oct 05 22:15:51 2016 -0500
+++ b/pidgin/plugins/gevolution/new_person_dialog.c	Thu Oct 06 10:05:06 2016 -0400
@@ -145,12 +145,8 @@
 			field = E_CONTACT_IM_AIM;
 		else if (!strcmp(im_service, "prpl-icq"))
 			field = E_CONTACT_IM_ICQ;
-		else if (!strcmp(im_service, "prpl-yahoo"))
-			field = E_CONTACT_IM_YAHOO;
 		else if (!strcmp(im_service, "prpl-jabber"))
 			field = E_CONTACT_IM_JABBER;
-		else if (!strcmp(im_service, "prpl-msn"))
-			field = E_CONTACT_IM_MSN;
 		else if (!strcmp(im_service, "prpl-novell"))
 			field = E_CONTACT_IM_GROUPWISE;
 		else if (!strcmp(im_service, "prpl-gg"))
--- a/pidgin/plugins/raw.c	Wed Oct 05 22:15:51 2016 -0500
+++ b/pidgin/plugins/raw.c	Thu Oct 06 10:05:06 2016 -0400
@@ -33,7 +33,6 @@
 #include "gtkutils.h"
 
 #include "protocols/jabber/jabber.h"
-#include "protocols/msn/session.h"
 
 #ifdef MAX
 # undef MAX
@@ -82,13 +81,6 @@
 		write(*a, txt, ntohs(len));
 		purple_debug(PURPLE_DEBUG_MISC, "raw", "TOC C: %s\n", txt);
 
-	} else if (strcmp(prpl_id, "prpl-msn") == 0) {
-		MsnSession *session = gc->proto_data;
-		char buf[strlen(txt) + 3];
-
-		g_snprintf(buf, sizeof(buf), "%s\r\n", txt);
-		msn_servconn_write(session->notification->servconn, buf, strlen(buf));
-
 	} else if (strcmp(prpl_id, "prpl-irc") == 0) {
 		write(*(int *)gc->proto_data, txt, strlen(txt));
 		write(*(int *)gc->proto_data, "\r\n", 2);
@@ -175,7 +167,7 @@
 	N_("Raw"),
 	DISPLAY_VERSION,
 	N_("Lets you send raw input to text-based protocols."),
-	N_("Lets you send raw input to text-based protocols (XMPP, MSN, IRC, "
+	N_("Lets you send raw input to text-based protocols (XMPP, IRC, "
 	   "TOC). Hit 'Enter' in the entry box to send. Watch the debug window."),
 	"Eric Warmenhoven <eric@warmenhoven.org>",
 	PURPLE_WEBSITE,
--- a/pidgin/win32/nsis/pidgin-installer.nsi	Wed Oct 05 22:15:51 2016 -0500
+++ b/pidgin/win32/nsis/pidgin-installer.nsi	Thu Oct 06 10:05:06 2016 -0400
@@ -388,9 +388,6 @@
 !macroend
 SectionGroup /e $(URIHANDLERSSECTIONTITLE) SecURIHandlers
   !insertmacro URI_SECTION "aim"
-  !insertmacro URI_SECTION "msnim"
-  !insertmacro URI_SECTION "myim"
-  !insertmacro URI_SECTION "ymsgr"
   !insertmacro URI_SECTION "xmpp"
 SectionGroupEnd
 
@@ -506,12 +503,6 @@
     ; I can't think of an easy way to maintain a list in a single place
     Push "aim"
     Call un.UnregisterURIHandler
-    Push "msnim"
-    Call un.UnregisterURIHandler
-    Push "myim"
-    Call un.UnregisterURIHandler
-    Push "ymsgr"
-    Call un.UnregisterURIHandler
     Push "xmpp"
     Call un.UnregisterURIHandler
 
@@ -564,17 +555,12 @@
     Delete "$INSTDIR\plugins\libgg.dll"
     Delete "$INSTDIR\plugins\libicq.dll"
     Delete "$INSTDIR\plugins\libirc.dll"
-    Delete "$INSTDIR\plugins\libmsn.dll"
-    Delete "$INSTDIR\plugins\libmxit.dll"
-    Delete "$INSTDIR\plugins\libmyspace.dll"
     Delete "$INSTDIR\plugins\libnapster.dll"
     Delete "$INSTDIR\plugins\libnovell.dll"
     Delete "$INSTDIR\plugins\libsametime.dll"
     Delete "$INSTDIR\plugins\libsilc.dll"
     Delete "$INSTDIR\plugins\libsimple.dll"
     Delete "$INSTDIR\plugins\libtoc.dll"
-    Delete "$INSTDIR\plugins\libyahoo.dll"
-    Delete "$INSTDIR\plugins\libyahoojp.dll"
     Delete "$INSTDIR\plugins\libxmpp.dll"
     Delete "$INSTDIR\plugins\log_reader.dll"
     Delete "$INSTDIR\plugins\markerline.dll"
--- a/po/POTFILES.in	Wed Oct 05 22:15:51 2016 -0500
+++ b/po/POTFILES.in	Thu Oct 06 10:05:06 2016 -0400
@@ -95,7 +95,6 @@
 libpurple/protocols/jabber/bosh.c
 libpurple/protocols/jabber/buddy.c
 libpurple/protocols/jabber/chat.c
-libpurple/protocols/jabber/facebook_roster.c
 libpurple/protocols/jabber/jabber.c
 libpurple/protocols/jabber/jutil.c
 libpurple/protocols/jabber/libxmpp.c
@@ -107,34 +106,6 @@
 libpurple/protocols/jabber/usermood.c
 libpurple/protocols/jabber/usernick.c
 libpurple/protocols/jabber/xdata.c
-libpurple/protocols/msn/contact.c
-libpurple/protocols/msn/error.c
-libpurple/protocols/msn/group.h
-libpurple/protocols/msn/msg.c
-libpurple/protocols/msn/msn.c
-libpurple/protocols/msn/nexus.c
-libpurple/protocols/msn/notification.c
-libpurple/protocols/msn/oim.c
-libpurple/protocols/msn/servconn.c
-libpurple/protocols/msn/session.c
-libpurple/protocols/msn/slp.c
-libpurple/protocols/msn/slpcall.c
-libpurple/protocols/msn/state.c
-libpurple/protocols/msn/switchboard.c
-libpurple/protocols/msn/userlist.c
-libpurple/protocols/mxit/actions.c
-libpurple/protocols/mxit/filexfer.c
-libpurple/protocols/mxit/http.c
-libpurple/protocols/mxit/login.c
-libpurple/protocols/mxit/multimx.c
-libpurple/protocols/mxit/mxit.c
-libpurple/protocols/mxit/profile.c
-libpurple/protocols/mxit/protocol.c
-libpurple/protocols/mxit/roster.c
-libpurple/protocols/mxit/splashscreen.c
-libpurple/protocols/myspace/myspace.c
-libpurple/protocols/myspace/user.c
-libpurple/protocols/myspace/zap.c
 libpurple/protocols/novell/nmuser.c
 libpurple/protocols/novell/novell.c
 libpurple/protocols/oscar/authorization.c
@@ -172,16 +143,6 @@
 libpurple/protocols/silc10/util.c
 libpurple/protocols/silc10/wb.c
 libpurple/protocols/simple/simple.c
-libpurple/protocols/yahoo/libyahoo.c
-libpurple/protocols/yahoo/libyahoojp.c
-libpurple/protocols/yahoo/libymsg.c
-libpurple/protocols/yahoo/yahoo_aliases.c
-libpurple/protocols/yahoo/yahoo_doodle.c
-libpurple/protocols/yahoo/yahoo_filexfer.c
-libpurple/protocols/yahoo/yahoo_packet.c
-libpurple/protocols/yahoo/yahoo_profile.c
-libpurple/protocols/yahoo/yahoochat.c
-libpurple/protocols/yahoo/ycht.c
 libpurple/protocols/zephyr/zephyr.c
 libpurple/proxy.c
 libpurple/prpl.c

mercurial