# HG changeset patch
# Node ID 39a060382150
# Parent  a3b862b8dcde
diff --git a/libpurple/meson.build b/libpurple/meson.build
--- a/libpurple/meson.build
+++ b/libpurple/meson.build
@@ -440,7 +440,6 @@
 
 subdir('tests')
 subdir('plugins')
-subdir('protocols')
 
 test(
 	'purple_license_headers',
diff --git a/libpurple/protocols/jabber/adhoccommands.h b/libpurple/protocols/jabber/adhoccommands.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/adhoccommands.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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_JABBER_ADHOCCOMMANDS_H
-#define PURPLE_JABBER_ADHOCCOMMANDS_H
-
-#include "jabber.h"
-
-/* Implementation of XEP-0050 */
-
-typedef struct {
-	char *jid;
-	char *node;
-	char *name;
-} JabberAdHocCommands;
-
-void jabber_adhoc_commands_free(JabberAdHocCommands *cmd);
-
-void jabber_adhoc_disco_result_cb(JabberStream *js, const char *from,
-                                  JabberIqType type, const char *id,
-                                  PurpleXmlNode *packet, gpointer data);
-
-void jabber_adhoc_execute_action(PurpleBlistNode *node, gpointer data);
-
-void jabber_adhoc_got_list(JabberStream *js, const char *from, PurpleXmlNode *query);
-
-void jabber_adhoc_server_get_list(JabberStream *js);
-
-void jabber_adhoc_init_server_commands(JabberStream *js, GList **m);
-
-#endif /* PURPLE_JABBER_ADHOCCOMMANDS_H */
diff --git a/libpurple/protocols/jabber/adhoccommands.c b/libpurple/protocols/jabber/adhoccommands.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/adhoccommands.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "adhoccommands.h"
-#include <string.h>
-#include "xdata.h"
-#include "iq.h"
-
-static void jabber_adhoc_execute(JabberStream *js, JabberAdHocCommands *cmd);
-
-void
-jabber_adhoc_commands_free(JabberAdHocCommands *cmd)
-{
-	g_return_if_fail(cmd != NULL);
-
-	g_free(cmd->jid);
-	g_free(cmd->node);
-	g_free(cmd->name);
-	g_free(cmd);
-}
-
-static void
-do_adhoc_ignoreme(G_GNUC_UNUSED JabberStream *js, ...) {
-	/* we don't have to do anything */
-}
-
-typedef struct {
-	char *sessionid;
-	char *who;
-	char *node;
-	GList *actionslist;
-} JabberAdHocActionInfo;
-
-static void
-jabber_adhoc_got_buddy_list(JabberStream *js, const char *from, PurpleXmlNode *query)
-{
-	JabberID *jid;
-	JabberBuddy *jb;
-	JabberBuddyResource *jbr = NULL;
-	PurpleXmlNode *item;
-
-	if ((jid = jabber_id_new(from))) {
-		if (jid->resource && (jb = jabber_buddy_find(js, from, TRUE)))
-			jbr = jabber_buddy_find_resource(jb, jid->resource);
-		jabber_id_free(jid);
-	}
-
-	if(!jbr)
-		return;
-
-	/* since the list we just received is complete, wipe the old one */
-	g_clear_list(&jbr->commands, (GDestroyNotify)jabber_adhoc_commands_free);
-
-	for(item = query->child; item; item = item->next) {
-		JabberAdHocCommands *cmd;
-		if(item->type != PURPLE_XMLNODE_TYPE_TAG)
-			continue;
-		if(!purple_strequal(item->name, "item"))
-			continue;
-		cmd = g_new0(JabberAdHocCommands, 1);
-
-		cmd->jid = g_strdup(purple_xmlnode_get_attrib(item,"jid"));
-		cmd->node = g_strdup(purple_xmlnode_get_attrib(item,"node"));
-		cmd->name = g_strdup(purple_xmlnode_get_attrib(item,"name"));
-
-		jbr->commands = g_list_append(jbr->commands,cmd);
-	}
-}
-
-void
-jabber_adhoc_disco_result_cb(JabberStream *js, const char *from,
-                             JabberIqType type, G_GNUC_UNUSED const char *id,
-                             PurpleXmlNode *packet, G_GNUC_UNUSED gpointer data)
-{
-	PurpleXmlNode *query;
-	const char *node;
-
-	if (type == JABBER_IQ_ERROR)
-		return;
-
-	query = purple_xmlnode_get_child_with_namespace(packet, "query", NS_DISCO_ITEMS);
-	if (!query)
-		return;
-	node = purple_xmlnode_get_attrib(query, "node");
-	if (!purple_strequal(node, "http://jabber.org/protocol/commands"))
-		return;
-
-	jabber_adhoc_got_buddy_list(js, from, query);
-}
-
-static void jabber_adhoc_parse(JabberStream *js, const char *from,
-                               JabberIqType type, const char *id,
-                               PurpleXmlNode *packet, gpointer data);
-
-static void do_adhoc_action_cb(JabberStream *js, PurpleXmlNode *result, const char *actionhandle, gpointer user_data) {
-	PurpleXmlNode *command;
-	JabberAdHocActionInfo *actionInfo = user_data;
-	JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET);
-	jabber_iq_set_callback(iq, jabber_adhoc_parse, NULL);
-
-	purple_xmlnode_set_attrib(iq->node, "to", actionInfo->who);
-	command = purple_xmlnode_new_child(iq->node,"command");
-	purple_xmlnode_set_namespace(command,"http://jabber.org/protocol/commands");
-	purple_xmlnode_set_attrib(command,"sessionid",actionInfo->sessionid);
-	purple_xmlnode_set_attrib(command,"node",actionInfo->node);
-
-	/* cancel is handled differently on ad-hoc commands than regular forms */
-	if (purple_strequal(purple_xmlnode_get_namespace(result), "jabber:x:data") &&
-			purple_strequal(purple_xmlnode_get_attrib(result, "type"), "cancel")) {
-		purple_xmlnode_set_attrib(command,"action","cancel");
-	} else {
-		if(actionhandle)
-			purple_xmlnode_set_attrib(command,"action",actionhandle);
-		purple_xmlnode_insert_child(command,result);
-	}
-
-	g_list_free_full(actionInfo->actionslist, g_free);
-	g_free(actionInfo->sessionid);
-	g_free(actionInfo->who);
-	g_free(actionInfo->node);
-
-	jabber_iq_send(iq);
-}
-
-static void
-jabber_adhoc_parse(JabberStream *js, const char *from, JabberIqType type,
-                   G_GNUC_UNUSED const char *id, PurpleXmlNode *packet,
-                   G_GNUC_UNUSED gpointer data)
-{
-	PurpleXmlNode *command = purple_xmlnode_get_child_with_namespace(packet, "command", "http://jabber.org/protocol/commands");
-	const char *status = purple_xmlnode_get_attrib(command,"status");
-	PurpleXmlNode *xdata = purple_xmlnode_get_child_with_namespace(command,"x","jabber:x:data");
-
-	if (type == JABBER_IQ_ERROR) {
-		char *msg = jabber_parse_error(js, packet, NULL);
-		if(!msg)
-			msg = g_strdup(_("Unknown Error"));
-
-		purple_notify_error(NULL, _("Ad-Hoc Command Failed"),
-			_("Ad-Hoc Command Failed"), msg,
-			purple_request_cpar_from_connection(js->gc));
-		g_free(msg);
-		return;
-	}
-
-	if(!status)
-		return;
-
-	if(purple_strequal(status,"completed")) {
-		/* display result */
-		PurpleXmlNode *note = purple_xmlnode_get_child(command,"note");
-
-		if(note) {
-			char *data = purple_xmlnode_get_data(note);
-			purple_notify_info(NULL, from, data, NULL,
-				purple_request_cpar_from_connection(js->gc));
-			g_free(data);
-		}
-
-		if(xdata)
-			jabber_x_data_request(js, xdata, (jabber_x_data_cb)do_adhoc_ignoreme, NULL);
-		return;
-	}
-	if(purple_strequal(status,"executing")) {
-		/* this command needs more steps */
-		PurpleXmlNode *actions, *action;
-		int actionindex = 0;
-		GList *actionslist = NULL;
-		JabberAdHocActionInfo *actionInfo;
-		if(!xdata)
-			return; /* shouldn't happen */
-
-		actions = purple_xmlnode_get_child(command,"actions");
-		if(!actions) {
-			JabberXDataAction *defaultaction = g_new0(JabberXDataAction, 1);
-			defaultaction->name = g_strdup(_("execute"));
-			defaultaction->handle = g_strdup("execute");
-			actionslist = g_list_append(actionslist, defaultaction);
-		} else {
-			const char *defaultactionhandle = purple_xmlnode_get_attrib(actions, "execute");
-			int index = 0;
-			for(action = actions->child; action; action = action->next, ++index) {
-				if(action->type == PURPLE_XMLNODE_TYPE_TAG) {
-					JabberXDataAction *newaction = g_new0(JabberXDataAction, 1);
-					newaction->name = g_strdup(_(action->name));
-					newaction->handle = g_strdup(action->name);
-					actionslist = g_list_append(actionslist, newaction);
-					if(defaultactionhandle && purple_strequal(defaultactionhandle, action->name))
-						actionindex = index;
-				}
-			}
-		}
-
-		actionInfo = g_new0(JabberAdHocActionInfo, 1);
-		actionInfo->sessionid = g_strdup(purple_xmlnode_get_attrib(command,"sessionid"));
-		actionInfo->who = g_strdup(from);
-		actionInfo->node = g_strdup(purple_xmlnode_get_attrib(command,"node"));
-		actionInfo->actionslist = actionslist;
-
-		jabber_x_data_request_with_actions(js,xdata,actionslist,actionindex,do_adhoc_action_cb,actionInfo);
-	}
-}
-
-void jabber_adhoc_execute_action(PurpleBlistNode *node, gpointer data) {
-	if (PURPLE_IS_BUDDY(node)) {
-		JabberAdHocCommands *cmd = data;
-		PurpleBuddy *buddy = (PurpleBuddy *) node;
-		PurpleAccount *account = purple_buddy_get_account(buddy);
-		PurpleConnection *gc = purple_account_get_connection(account);
-		JabberStream *js = purple_connection_get_protocol_data(gc);
-
-		jabber_adhoc_execute(js, cmd);
-	}
-}
-
-static void
-jabber_adhoc_got_server_list(JabberStream *js, G_GNUC_UNUSED const char *from,
-                             PurpleXmlNode *query)
-{
-	PurpleXmlNode *item;
-
-	if(!query)
-		return;
-
-	/* clean current list (just in case there is one) */
-	g_clear_list(&js->commands, (GDestroyNotify)jabber_adhoc_commands_free);
-
-	/* re-fill list */
-	for(item = query->child; item; item = item->next) {
-		JabberAdHocCommands *cmd;
-		if(item->type != PURPLE_XMLNODE_TYPE_TAG)
-			continue;
-		if(!purple_strequal(item->name, "item"))
-			continue;
-		cmd = g_new0(JabberAdHocCommands, 1);
-		cmd->jid = g_strdup(purple_xmlnode_get_attrib(item,"jid"));
-		cmd->node = g_strdup(purple_xmlnode_get_attrib(item,"node"));
-		cmd->name = g_strdup(purple_xmlnode_get_attrib(item,"name"));
-
-		js->commands = g_list_append(js->commands,cmd);
-	}
-
-	if (js->state == JABBER_STREAM_CONNECTED) {
-		PurpleProtocol *protocol = purple_connection_get_protocol(js->gc);
-
-		purple_protocol_actions_changed(PURPLE_PROTOCOL_ACTIONS(protocol),
-		                                purple_connection_get_account(js->gc));
-	}
-}
-
-static void
-jabber_adhoc_server_got_list_cb(JabberStream *js, const char *from,
-                                G_GNUC_UNUSED JabberIqType type,
-                                G_GNUC_UNUSED const char *id,
-                                PurpleXmlNode *packet,
-                                G_GNUC_UNUSED gpointer data)
-{
-	PurpleXmlNode *query = purple_xmlnode_get_child_with_namespace(packet, "query",
-			NS_DISCO_ITEMS);
-
-	jabber_adhoc_got_server_list(js, from, query);
-
-}
-
-void jabber_adhoc_got_list(JabberStream *js, const char *from, PurpleXmlNode *query)
-{
-	if (purple_strequal(from, js->user->domain)) {
-		jabber_adhoc_got_server_list(js, from, query);
-	} else {
-		jabber_adhoc_got_buddy_list(js, from, query);
-	}
-}
-
-void jabber_adhoc_server_get_list(JabberStream *js) {
-	JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_GET, NS_DISCO_ITEMS);
-	PurpleXmlNode *query = purple_xmlnode_get_child_with_namespace(iq->node, "query",
-			NS_DISCO_ITEMS);
-
-	purple_xmlnode_set_attrib(iq->node,"to",js->user->domain);
-	purple_xmlnode_set_attrib(query,"node","http://jabber.org/protocol/commands");
-
-	jabber_iq_set_callback(iq,jabber_adhoc_server_got_list_cb,NULL);
-	jabber_iq_send(iq);
-}
-
-static void
-jabber_adhoc_execute(JabberStream *js, JabberAdHocCommands *cmd) {
-	JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET);
-	PurpleXmlNode *command = purple_xmlnode_new_child(iq->node,"command");
-	purple_xmlnode_set_attrib(iq->node,"to",cmd->jid);
-	purple_xmlnode_set_namespace(command,"http://jabber.org/protocol/commands");
-	purple_xmlnode_set_attrib(command,"node",cmd->node);
-	purple_xmlnode_set_attrib(command,"action","execute");
-
-	jabber_iq_set_callback(iq,jabber_adhoc_parse,NULL);
-
-	jabber_iq_send(iq);
-}
-
-static void jabber_adhoc_server_execute(PurpleProtocolAction *action) {
-	JabberAdHocCommands *cmd = action->user_data;
-	if(cmd) {
-		PurpleConnection *gc = (PurpleConnection *) action->connection;
-		JabberStream *js = purple_connection_get_protocol_data(gc);
-
-		jabber_adhoc_execute(js, cmd);
-	}
-}
-
-void jabber_adhoc_init_server_commands(JabberStream *js, GList **m) {
-	GList *cmdlst;
-	JabberBuddy *jb;
-
-	/* also add commands for other clients connected to the same account on another resource */
-	char *accountname = g_strdup_printf("%s@%s", js->user->node, js->user->domain);
-	if((jb = jabber_buddy_find(js, accountname, TRUE))) {
-		GList *iter;
-		for(iter = jb->resources; iter; iter = g_list_next(iter)) {
-			JabberBuddyResource *jbr = iter->data;
-			GList *riter;
-			for(riter = jbr->commands; riter; riter = g_list_next(riter)) {
-				JabberAdHocCommands *cmd = riter->data;
-				char *cmdname = g_strdup_printf("%s (%s)",cmd->name,jbr->name);
-				PurpleProtocolAction *act = purple_protocol_action_new(cmdname, jabber_adhoc_server_execute);
-				act->user_data = cmd;
-				*m = g_list_append(*m, act);
-				g_free(cmdname);
-			}
-		}
-	}
-	g_free(accountname);
-
-	/* now add server commands */
-	for(cmdlst = js->commands; cmdlst; cmdlst = g_list_next(cmdlst)) {
-		JabberAdHocCommands *cmd = cmdlst->data;
-		PurpleProtocolAction *act = purple_protocol_action_new(cmd->name, jabber_adhoc_server_execute);
-		act->user_data = cmd;
-		*m = g_list_append(*m, act);
-	}
-}
diff --git a/libpurple/protocols/jabber/auth.h b/libpurple/protocols/jabber/auth.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/auth.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * @file auth.h Authentication routines
- *
- * 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_JABBER_AUTH_H
-#define PURPLE_JABBER_AUTH_H
-
-typedef struct _JabberSaslMech JabberSaslMech;
-
-#include <purple.h>
-
-#include "jabber.h"
-
-typedef enum {
-	JABBER_SASL_STATE_FAIL = -1,    /* Abort, Retry, Fail? */
-	JABBER_SASL_STATE_OK = 0,       /* Hooray! */
-	JABBER_SASL_STATE_CONTINUE = 1  /* More authentication required */
-} JabberSaslState;
-
-struct _JabberSaslMech {
-	gint8 priority; /* Higher priority will be tried before lower priority */
-	const gchar *name;
-	JabberSaslState (*start)(JabberStream *js, PurpleXmlNode *mechanisms, PurpleXmlNode **reply, char **msg);
-	JabberSaslState (*handle_challenge)(JabberStream *js, PurpleXmlNode *packet, PurpleXmlNode **reply, char **msg);
-	JabberSaslState (*handle_success)(JabberStream *js, PurpleXmlNode *packet, char **msg);
-	JabberSaslState (*handle_failure)(JabberStream *js, PurpleXmlNode *packet, PurpleXmlNode **reply, char **msg);
-	void (*dispose)(JabberStream *js);
-};
-
-void jabber_auth_start(JabberStream *js, PurpleXmlNode *packet);
-void jabber_auth_start_old(JabberStream *js);
-void jabber_auth_handle_challenge(JabberStream *js, PurpleXmlNode *packet);
-void jabber_auth_handle_success(JabberStream *js, PurpleXmlNode *packet);
-void jabber_auth_handle_failure(JabberStream *js, PurpleXmlNode *packet);
-
-JabberSaslMech *jabber_auth_get_plain_mech(void);
-JabberSaslMech *jabber_auth_get_digest_md5_mech(void);
-JabberSaslMech **jabber_auth_get_scram_mechs(gint *count);
-JabberSaslMech *jabber_auth_get_webex_token_mech(void);
-
-void jabber_auth_init(void);
-void jabber_auth_uninit(void);
-
-#endif /* PURPLE_JABBER_AUTH_H */
diff --git a/libpurple/protocols/jabber/auth.c b/libpurple/protocols/jabber/auth.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/auth.c
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "auth.h"
-#include "disco.h"
-#include "jabber.h"
-#include "jutil.h"
-#include "iq.h"
-
-static GSList *auth_mechs = NULL;
-
-static void auth_old_result_cb(JabberStream *js, const char *from,
-                               JabberIqType type, const char *id,
-                               PurpleXmlNode *packet, gpointer data);
-
-static void finish_plaintext_authentication(JabberStream *js)
-{
-	JabberIq *iq;
-	PurpleXmlNode *query, *x;
-
-	iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth");
-	query = purple_xmlnode_get_child(iq->node, "query");
-	x = purple_xmlnode_new_child(query, "username");
-	purple_xmlnode_insert_data(x, js->user->node, -1);
-	x = purple_xmlnode_new_child(query, "resource");
-	purple_xmlnode_insert_data(x, js->user->resource, -1);
-	x = purple_xmlnode_new_child(query, "password");
-	purple_xmlnode_insert_data(x, purple_connection_get_password(js->gc), -1);
-	jabber_iq_set_callback(iq, auth_old_result_cb, NULL);
-	jabber_iq_send(iq);
-}
-
-static void allow_plaintext_auth(PurpleAccount *account)
-{
-	PurpleConnection *gc;
-	JabberStream *js;
-
-	purple_account_set_bool(account, "auth_plain_in_clear", TRUE);
-
-	gc = purple_account_get_connection(account);
-	js = purple_connection_get_protocol_data(gc);
-
-	finish_plaintext_authentication(js);
-}
-
-static void disallow_plaintext_auth(PurpleAccount *account)
-{
-	purple_connection_error(purple_account_get_connection(account),
-		PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
-		_("Server requires plaintext authentication over an unencrypted stream"));
-}
-
-static void
-auth_old_pass_cb(PurpleConnection *gc, PurpleRequestPage *page) {
-	PurpleAccount *account;
-	JabberStream *js;
-	const char *entry;
-	gboolean remember;
-
-	/* TODO: the password prompt dialog doesn't get disposed if the account disconnects */
-	PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
-
-	account = purple_connection_get_account(gc);
-	js = purple_connection_get_protocol_data(gc);
-
-	entry = purple_request_page_get_string(page, "password");
-	remember = purple_request_page_get_bool(page, "remember");
-
-	if (!entry || !*entry)
-	{
-		purple_notify_error(account, NULL,
-			_("Password is required to sign on."), NULL,
-			purple_request_cpar_from_connection(gc));
-		return;
-	}
-
-	if(remember) {
-		PurpleCredentialManager *manager = NULL;
-
-		purple_account_set_remember_password(account, TRUE);
-
-		manager = purple_credential_manager_get_default();
-		purple_credential_manager_write_password_async(manager, account, entry,
-		                                               NULL, NULL, NULL);
-	}
-
-	/* Store the new password in our connection. */
-	purple_connection_set_password(gc, entry);
-
-	/* Restart our connection. */
-	jabber_auth_start_old(js);
-}
-
-static void
-auth_no_pass_cb(PurpleConnection *gc, G_GNUC_UNUSED PurpleRequestPage *page) {
-	/* TODO: the password prompt dialog doesn't get disposed if the account disconnects */
-	PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
-
-	/* Disable the account as the user has cancelled connecting */
-	purple_account_set_enabled(purple_connection_get_account(gc), FALSE);
-}
-
-static void
-auth_old_read_pass_cb(GObject *source, GAsyncResult *result, gpointer data) {
-	JabberStream *js = data;
-	PurpleCredentialManager *manager = PURPLE_CREDENTIAL_MANAGER(source);
-	GError *error = NULL;
-	char *password = NULL;
-
-	password = purple_credential_manager_read_password_finish(manager, result,
-	                                                          &error);
-	if(password == NULL || error != NULL) {
-		PurpleAccount *account = NULL;
-		const char *message = "unknown error";
-
-		if(error != NULL) {
-			message = error->message;
-		}
-
-		purple_debug_warning("jabber", "failed to read password from the "
-		                     "credential manager : %s", message);
-
-		g_clear_error(&error);
-
-		account = purple_connection_get_account(js->gc);
-		purple_account_request_password(account, G_CALLBACK(auth_old_pass_cb),
-		                                G_CALLBACK(auth_no_pass_cb),
-		                                js->gc);
-
-		return;
-	}
-
-	/* Save the password in the connection. */
-	purple_connection_set_password(js->gc, password);
-	purple_str_wipe(password);
-
-	/* Restart the authentication process. */
-	jabber_auth_start_old(js);
-}
-
-void
-jabber_auth_start(JabberStream *js, PurpleXmlNode *packet)
-{
-	GSList *mechanisms = NULL;
-	GSList *l;
-	PurpleXmlNode *response = NULL;
-	PurpleXmlNode *mechs, *mechnode;
-	JabberSaslState state;
-	char *msg = NULL;
-
-	mechs = purple_xmlnode_get_child(packet, "mechanisms");
-	if(!mechs) {
-		purple_connection_error(js->gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("Invalid response from server"));
-		return;
-	}
-
-	for(mechnode = purple_xmlnode_get_child(mechs, "mechanism"); mechnode;
-			mechnode = purple_xmlnode_get_next_twin(mechnode))
-	{
-		char *mech_name = purple_xmlnode_get_data(mechnode);
-
-		if (mech_name && *mech_name)
-			mechanisms = g_slist_prepend(mechanisms, mech_name);
-		else
-			g_free(mech_name);
-
-	}
-
-	for (l = auth_mechs; l; l = l->next) {
-		JabberSaslMech *possible = l->data;
-
-		/* Can we find this mechanism in the server's list? */
-		if (g_slist_find_custom(mechanisms, possible->name, (GCompareFunc)strcmp)) {
-			js->auth_mech = possible;
-			break;
-		}
-	}
-
-	g_slist_free_full(mechanisms, g_free);
-
-	if (js->auth_mech == NULL) {
-		/* Found no good mechanisms... */
-		purple_connection_error(js->gc,
-				PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
-				_("Server does not use any supported authentication method"));
-		return;
-	}
-
-	state = js->auth_mech->start(js, mechs, &response, &msg);
-	if (state == JABBER_SASL_STATE_FAIL) {
-		purple_connection_error(js->gc,
-				PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
-				msg ? msg : _("Unknown Error"));
-	} else if (response) {
-		jabber_send(js, response);
-		purple_xmlnode_free(response);
-	}
-
-	g_free(msg);
-}
-
-static void
-auth_old_result_cb(JabberStream *js, G_GNUC_UNUSED const char *from,
-                   JabberIqType type, G_GNUC_UNUSED const char *id,
-                   PurpleXmlNode *packet, G_GNUC_UNUSED gpointer data)
-{
-	if (type == JABBER_IQ_RESULT) {
-		jabber_stream_set_state(js, JABBER_STREAM_POST_AUTH);
-		jabber_disco_items_server(js);
-	} else {
-		PurpleAccount *account;
-		PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-		char *msg = jabber_parse_error(js, packet, &reason);
-		PurpleXmlNode *error;
-		const char *err_code;
-
-		account = purple_connection_get_account(js->gc);
-
-		/* FIXME: Why is this not in jabber_parse_error? */
-		if((error = purple_xmlnode_get_child(packet, "error")) &&
-					(err_code = purple_xmlnode_get_attrib(error, "code")) &&
-					purple_strequal(err_code, "401")) {
-			reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
-			/* Clear the password if it isn't being saved */
-			if(!purple_account_get_remember_password(account)) {
-				PurpleCredentialManager *manager = NULL;
-
-				manager = purple_credential_manager_get_default();
-
-				purple_credential_manager_clear_password_async(manager, account,
-				                                               NULL, NULL,
-				                                               NULL);
-			}
-		}
-
-		purple_connection_error(js->gc, reason, msg);
-		g_free(msg);
-	}
-}
-
-static void
-auth_old_cb(JabberStream *js, G_GNUC_UNUSED const char *from,
-            JabberIqType type, G_GNUC_UNUSED const char *id,
-            PurpleXmlNode *packet, G_GNUC_UNUSED gpointer data)
-{
-	JabberIq *iq;
-	PurpleXmlNode *query, *x;
-	const char *pw = purple_connection_get_password(js->gc);
-
-	if (type == JABBER_IQ_ERROR) {
-		PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-		char *msg = jabber_parse_error(js, packet, &reason);
-		purple_connection_error(js->gc, reason, msg);
-		g_free(msg);
-	} else if (type == JABBER_IQ_RESULT) {
-		query = purple_xmlnode_get_child(packet, "query");
-		if (js->stream_id && *js->stream_id &&
-				purple_xmlnode_get_child(query, "digest")) {
-			char *s, *hash;
-
-			iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth");
-			query = purple_xmlnode_get_child(iq->node, "query");
-			x = purple_xmlnode_new_child(query, "username");
-			purple_xmlnode_insert_data(x, js->user->node, -1);
-			x = purple_xmlnode_new_child(query, "resource");
-			purple_xmlnode_insert_data(x, js->user->resource, -1);
-
-			x = purple_xmlnode_new_child(query, "digest");
-			s = g_strdup_printf("%s%s", js->stream_id, pw);
-			hash = g_compute_checksum_for_string(G_CHECKSUM_SHA1,
-					s, -1);
-			purple_xmlnode_insert_data(x, hash, -1);
-			g_free(hash);
-			g_free(s);
-			jabber_iq_set_callback(iq, auth_old_result_cb, NULL);
-			jabber_iq_send(iq);
-		} else if ((x = purple_xmlnode_get_child(query, "crammd5"))) {
-			/* For future reference, this appears to be a custom OS X extension
-			 * to non-SASL authentication.
-			 */
-			const char *challenge;
-			gchar *digest;
-
-			/* Calculate the MHAC-MD5 digest */
-			challenge = purple_xmlnode_get_attrib(x, "challenge");
-			digest = g_compute_hmac_for_string(G_CHECKSUM_MD5,
-					(guchar *)pw, strlen(pw),
-					challenge, -1);
-
-			g_return_if_fail(digest != NULL);
-
-			/* Create the response query */
-			iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth");
-			query = purple_xmlnode_get_child(iq->node, "query");
-
-			x = purple_xmlnode_new_child(query, "username");
-			purple_xmlnode_insert_data(x, js->user->node, -1);
-			x = purple_xmlnode_new_child(query, "resource");
-			purple_xmlnode_insert_data(x, js->user->resource, -1);
-
-			x = purple_xmlnode_new_child(query, "crammd5");
-
-			purple_xmlnode_insert_data(x, digest, 32);
-			g_free(digest);
-
-			jabber_iq_set_callback(iq, auth_old_result_cb, NULL);
-			jabber_iq_send(iq);
-
-		} else if(purple_xmlnode_get_child(query, "password")) {
-			PurpleAccount *account = purple_connection_get_account(js->gc);
-			if(!jabber_stream_is_ssl(js) && !purple_account_get_bool(account,
-						"auth_plain_in_clear", FALSE))
-			{
-				PurpleContactInfo *info = PURPLE_CONTACT_INFO(account);
-				char *msg = g_strdup_printf(_("%s requires plaintext authentication over an unencrypted connection.  Allow this and continue authentication?"),
-				                            purple_contact_info_get_username(info));
-				purple_request_yes_no(js->gc, _("Plaintext Authentication"),
-						_("Plaintext Authentication"),
-						msg,
-						1,
-						purple_request_cpar_from_account(account),
-						account, allow_plaintext_auth,
-						disallow_plaintext_auth);
-				g_free(msg);
-				return;
-			}
-			finish_plaintext_authentication(js);
-		} else {
-			purple_connection_error(js->gc,
-				PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
-				_("Server does not use any supported authentication method"));
-			return;
-		}
-	}
-}
-
-void jabber_auth_start_old(JabberStream *js)
-{
-	PurpleAccount *account;
-	JabberIq *iq;
-	PurpleXmlNode *query, *username;
-
-	account = purple_connection_get_account(js->gc);
-
-	/*
-	 * We can end up here without encryption if the server doesn't support
-	 * <stream:features/> and we're not using old-style SSL.  If the user
-	 * is requiring SSL/TLS, we need to enforce it.
-	 */
-	if (!jabber_stream_is_ssl(js) &&
-			purple_strequal("require_tls",
-				purple_account_get_string(account, "connection_security", JABBER_DEFAULT_REQUIRE_TLS))) {
-		purple_connection_error(js->gc,
-			PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
-			_("You require encryption, but it is not available on this server."));
-		return;
-	}
-
-	/*
-	 * IQ Auth doesn't have support for resource binding, so we need to pick a
-	 * default resource so it will work properly.  jabberd14 throws an error and
-	 * iChat server just fails silently.
-	 */
-	if (!js->user->resource || *js->user->resource == '\0') {
-		g_free(js->user->resource);
-		js->user->resource = g_strdup("Home");
-	}
-
-	/* With Cyrus SASL, passwords are optional for this protocol. So, we need to
-	 * do our own password prompting here
-	 */
-
-	if (!purple_connection_get_password(js->gc)) {
-		PurpleCredentialManager *manager = NULL;
-
-		manager = purple_credential_manager_get_default();
-
-		purple_credential_manager_read_password_async(manager, account, NULL,
-		                                              auth_old_read_pass_cb,
-		                                              js);
-		return;
-	}
-	iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:auth");
-
-	query = purple_xmlnode_get_child(iq->node, "query");
-	username = purple_xmlnode_new_child(query, "username");
-	purple_xmlnode_insert_data(username, js->user->node, -1);
-
-	jabber_iq_set_callback(iq, auth_old_cb, NULL);
-
-	jabber_iq_send(iq);
-}
-
-void
-jabber_auth_handle_challenge(JabberStream *js, PurpleXmlNode *packet)
-{
-	const char *ns = purple_xmlnode_get_namespace(packet);
-
-	if (!purple_strequal(ns, NS_XMPP_SASL)) {
-		purple_connection_error(js->gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("Invalid response from server"));
-		return;
-	}
-
-	if (js->auth_mech && js->auth_mech->handle_challenge) {
-		PurpleXmlNode *response = NULL;
-		char *msg = NULL;
-		JabberSaslState state = js->auth_mech->handle_challenge(js, packet, &response, &msg);
-		if (state == JABBER_SASL_STATE_FAIL) {
-			purple_connection_error(js->gc,
-					PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
-					msg ? msg : _("Invalid challenge from server"));
-		} else if (response) {
-			jabber_send(js, response);
-			purple_xmlnode_free(response);
-		}
-
-		g_free(msg);
-	} else
-		purple_debug_warning("jabber", "Received unexpected (and unhandled) <challenge/>\n");
-}
-
-void jabber_auth_handle_success(JabberStream *js, PurpleXmlNode *packet)
-{
-	const char *ns = purple_xmlnode_get_namespace(packet);
-
-	if (!purple_strequal(ns, NS_XMPP_SASL)) {
-		purple_connection_error(js->gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("Invalid response from server"));
-		return;
-	}
-
-	if (js->auth_mech && js->auth_mech->handle_success) {
-		char *msg = NULL;
-		JabberSaslState state = js->auth_mech->handle_success(js, packet, &msg);
-
-		if (state == JABBER_SASL_STATE_FAIL) {
-			purple_connection_error(js->gc,
-					PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
-					msg ? msg : _("Invalid response from server"));
-			return;
-		} else if (state == JABBER_SASL_STATE_CONTINUE) {
-			purple_connection_error(js->gc,
-					PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
-					msg ? msg : _("Server thinks authentication is complete, but client does not"));
-			return;
-		}
-
-		g_free(msg);
-	}
-
-	/*
-	 * The stream will be reinitialized later in jabber_recv_cb_ssl() or
-	 * jabber_bosh_connection_send.
-	 */
-	js->reinit = TRUE;
-	jabber_stream_set_state(js, JABBER_STREAM_POST_AUTH);
-}
-
-void jabber_auth_handle_failure(JabberStream *js, PurpleXmlNode *packet)
-{
-	PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-	char *msg = NULL;
-
-	if (js->auth_mech && js->auth_mech->handle_failure) {
-		PurpleXmlNode *stanza = NULL;
-		JabberSaslState state = js->auth_mech->handle_failure(js, packet, &stanza, &msg);
-
-		if (state != JABBER_SASL_STATE_FAIL) {
-			if (stanza) {
-				jabber_send(js, stanza);
-				purple_xmlnode_free(stanza);
-			}
-
-			return;
-		}
-	}
-
-	if (!msg)
-		msg = jabber_parse_error(js, packet, &reason);
-
-	if (!msg) {
-		purple_connection_error(js->gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("Invalid response from server"));
-	} else {
-		purple_connection_error(js->gc, reason, msg);
-		g_free(msg);
-	}
-}
-
-static gint compare_mech(gconstpointer a, gconstpointer b)
-{
-	const JabberSaslMech *mech_a = a;
-	const JabberSaslMech *mech_b = b;
-
-	/* higher priority comes *before* lower priority in the list */
-	if (mech_a->priority > mech_b->priority)
-		return -1;
-	else if (mech_a->priority < mech_b->priority)
-		return 1;
-	/* This really shouldn't happen */
-	return 0;
-}
-
-static void
-jabber_auth_add_mech(JabberSaslMech *mech) {
-	auth_mechs = g_slist_insert_sorted(auth_mechs, mech, compare_mech);
-}
-
-void jabber_auth_init(void)
-{
-	JabberSaslMech **tmp;
-	gint count, i;
-
-	jabber_auth_add_mech(jabber_auth_get_plain_mech());
-	jabber_auth_add_mech(jabber_auth_get_digest_md5_mech());
-#ifdef HAVE_WEBEX_TOKEN
-	jabber_auth_add_mech(jabber_auth_get_webex_token_mech());
-#endif
-
-	tmp = jabber_auth_get_scram_mechs(&count);
-	for (i = 0; i < count; ++i)
-		jabber_auth_add_mech(tmp[i]);
-}
-
-void jabber_auth_uninit(void)
-{
-	g_clear_slist(&auth_mechs, NULL);
-}
diff --git a/libpurple/protocols/jabber/auth_digest_md5.h b/libpurple/protocols/jabber/auth_digest_md5.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/auth_digest_md5.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * @file auth_digest_md5.h Implementation of SASL DIGEST-MD5 authentication
- *
- * 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_JABBER_AUTH_DIGEST_MD5_H
-#define PURPLE_JABBER_AUTH_DIGEST_MD5_H
-
-#include "jabber.h"
-
-/*
- * Every function in this file is ONLY exposed for tests.
- * DO NOT USE ANYTHING HERE OR YOU WILL BE SENT TO THE PIT OF DESPAIR.
- */
-
-/*
- * Parse a DIGEST-MD5 challenge.
- */
-PURPLE_XMPP_EXTERN_FOR_TESTS
-GHashTable *jabber_auth_digest_md5_parse(const char *challenge);
-
-#endif /* PURPLE_JABBER_AUTH_DIGEST_MD5_H */
diff --git a/libpurple/protocols/jabber/auth_digest_md5.c b/libpurple/protocols/jabber/auth_digest_md5.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/auth_digest_md5.c
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "auth_digest_md5.h"
-#include "auth.h"
-#include "jabber.h"
-
-static JabberSaslState
-digest_md5_start(G_GNUC_UNUSED JabberStream *js,
-                 G_GNUC_UNUSED PurpleXmlNode *packet, PurpleXmlNode **response,
-                 G_GNUC_UNUSED char **error)
-{
-	PurpleXmlNode *auth = purple_xmlnode_new("auth");
-	purple_xmlnode_set_namespace(auth, NS_XMPP_SASL);
-	purple_xmlnode_set_attrib(auth, "mechanism", "DIGEST-MD5");
-
-	*response = auth;
-	return JABBER_SASL_STATE_CONTINUE;
-}
-
-/* Parts of this algorithm are inspired by stuff in libgsasl */
-GHashTable* jabber_auth_digest_md5_parse(const char *challenge)
-{
-	const char *token_start, *val_start, *val_end, *cur;
-	GHashTable *ret = g_hash_table_new_full(g_str_hash, g_str_equal,
-			g_free, g_free);
-
-	cur = challenge;
-	while(*cur != '\0') {
-		/* Find the end of the token */
-		gboolean in_quotes = FALSE;
-		char *name, *value = NULL;
-		token_start = cur;
-		while (*cur != '\0' && (in_quotes || *cur != ',')) {
-			if (*cur == '"')
-				in_quotes = !in_quotes;
-			cur++;
-		}
-
-		/* Find start of value.  */
-		val_start = strchr(token_start, '=');
-		if (val_start == NULL || val_start > cur)
-			val_start = cur;
-
-		if (token_start != val_start) {
-			name = g_strndup(token_start, val_start - token_start);
-
-			if (val_start != cur) {
-				val_start++;
-				while (val_start != cur && (*val_start == ' ' || *val_start == '\t'
-						|| *val_start == '\r' || *val_start == '\n'
-						|| *val_start == '"'))
-					val_start++;
-
-				val_end = cur;
-				while (val_end >= val_start && (*val_end == ' ' || *val_end == ',' || *val_end == '\t'
-						|| *val_end == '\r' || *val_end == '\n'
-						|| *val_end == '"'  || *val_end == '\0'))
-					val_end--;
-
-				if (val_end - val_start + 1 >= 0)
-					value = g_strndup(val_start, val_end - val_start + 1);
-			}
-
-			g_hash_table_replace(ret, name, value);
-		}
-
-		/* Find the start of the next token, if there is one */
-		if (*cur != '\0') {
-			cur++;
-			while (*cur == ' ' || *cur == ',' || *cur == '\t'
-					|| *cur == '\r' || *cur == '\n')
-				cur++;
-		}
-	}
-
-	return ret;
-}
-
-static char *
-generate_response_value(JabberID *jid, const char *passwd, const char *nonce,
-		const char *cnonce, const char *a2, const char *realm)
-{
-	GChecksum *hash;
-	gsize digest_len = 16;
-
-	gchar *a1, *convnode=NULL, *convpasswd = NULL, *ha1, *ha2, *kd, *x, *z;
-
-	if((convnode = g_convert(jid->node, -1, "iso-8859-1", "utf-8",
-					NULL, NULL, NULL)) == NULL) {
-		convnode = g_strdup(jid->node);
-	}
-	if(passwd && ((convpasswd = g_convert(passwd, -1, "iso-8859-1",
-						"utf-8", NULL, NULL, NULL)) == NULL)) {
-		convpasswd = g_strdup(passwd);
-	}
-
-	hash = g_checksum_new(G_CHECKSUM_MD5);
-
-	x = g_strdup_printf("%s:%s:%s", convnode, realm, convpasswd ? convpasswd : "");
-	g_checksum_update(hash, (const guchar *)x, -1);
-
-	a1 = g_strdup_printf("xxxxxxxxxxxxxxxx:%s:%s", nonce, cnonce);
-
-	g_checksum_get_digest(hash, (guint8 *)a1, &digest_len);
-	g_checksum_free(hash);
-
-	ha1 = g_compute_checksum_for_string(G_CHECKSUM_MD5, a1, -1);
-	ha2 = g_compute_checksum_for_string(G_CHECKSUM_MD5, a2, -1);
-
-	kd = g_strdup_printf("%s:%s:00000001:%s:auth:%s", ha1, nonce, cnonce, ha2);
-
-	z = g_compute_checksum_for_string(G_CHECKSUM_MD5, kd, -1);
-
-	g_free(convnode);
-	g_free(convpasswd);
-	g_free(x);
-	g_free(a1);
-	g_free(ha1);
-	g_free(ha2);
-	g_free(kd);
-
-	return z;
-}
-
-static JabberSaslState
-digest_md5_handle_challenge(JabberStream *js, PurpleXmlNode *packet,
-                            PurpleXmlNode **response, char **msg)
-{
-	PurpleXmlNode *reply = NULL;
-	char *enc_in = purple_xmlnode_get_data(packet);
-	char *dec_in;
-	char *enc_out;
-	gsize size = 0;
-	GHashTable *parts;
-	JabberSaslState state = JABBER_SASL_STATE_CONTINUE;
-
-	if (!enc_in) {
-		*msg = g_strdup(_("Invalid response from server"));
-		return JABBER_SASL_STATE_FAIL;
-	}
-
-	dec_in = (char *)g_base64_decode(enc_in, &size);
-	purple_debug_misc("jabber", "decoded challenge (%"
-			G_GSIZE_FORMAT "): %s\n",
-			size,
-			dec_in);
-
-	parts = jabber_auth_digest_md5_parse(dec_in);
-
-	if (g_hash_table_lookup(parts, "rspauth")) {
-		char *rspauth = g_hash_table_lookup(parts, "rspauth");
-		char *expected_rspauth = js->auth_mech_data;
-
-		if (rspauth && purple_strequal(rspauth, expected_rspauth)) {
-			reply = purple_xmlnode_new("response");
-			purple_xmlnode_set_namespace(reply, NS_XMPP_SASL);
-		} else {
-			*msg = g_strdup(_("Invalid challenge from server"));
-			state = JABBER_SASL_STATE_FAIL;
-		}
-		g_free(js->auth_mech_data);
-		js->auth_mech_data = NULL;
-	} else {
-		/* assemble a response, and send it */
-		/* see RFC 2831 */
-		char *realm;
-		char *nonce;
-
-		/* Make sure the auth string contains everything that should be there.
-		   This isn't everything in RFC2831, but it is what we need. */
-
-		nonce = g_hash_table_lookup(parts, "nonce");
-
-		/* we're actually supposed to prompt the user for a realm if
-		 * the server doesn't send one, but that really complicates things,
-		 * so i'm not gonna worry about it until is poses a problem to
-		 * someone, or I get really bored */
-		realm = g_hash_table_lookup(parts, "realm");
-		if(!realm)
-			realm = js->user->domain;
-
-		if (nonce == NULL || realm == NULL) {
-			*msg = g_strdup(_("Invalid challenge from server"));
-			state = JABBER_SASL_STATE_FAIL;
-		} else {
-			GString *response = g_string_new("");
-			char *a2;
-			char *auth_resp;
-			char *cnonce;
-
-			cnonce = g_strdup_printf("%x%u%x", g_random_int(), (int)time(NULL),
-					g_random_int());
-
-			a2 = g_strdup_printf("AUTHENTICATE:xmpp/%s", realm);
-			auth_resp = generate_response_value(js->user,
-					purple_connection_get_password(js->gc), nonce, cnonce, a2, realm);
-			g_free(a2);
-
-			a2 = g_strdup_printf(":xmpp/%s", realm);
-			js->auth_mech_data = generate_response_value(js->user,
-					purple_connection_get_password(js->gc), nonce, cnonce, a2, realm);
-			g_free(a2);
-
-			g_string_append_printf(response, "username=\"%s\"", js->user->node);
-			g_string_append_printf(response, ",realm=\"%s\"", realm);
-			g_string_append_printf(response, ",nonce=\"%s\"", nonce);
-			g_string_append_printf(response, ",cnonce=\"%s\"", cnonce);
-			g_string_append_printf(response, ",nc=00000001");
-			g_string_append_printf(response, ",qop=auth");
-			g_string_append_printf(response, ",digest-uri=\"xmpp/%s\"", realm);
-			g_string_append_printf(response, ",response=%s", auth_resp);
-			g_string_append_printf(response, ",charset=utf-8");
-
-			g_free(auth_resp);
-			g_free(cnonce);
-
-			enc_out = g_base64_encode((guchar *)response->str, response->len);
-
-			purple_debug_misc("jabber", "decoded response (%"
-					G_GSIZE_FORMAT "): %s\n",
-					response->len, response->str);
-
-			reply = purple_xmlnode_new("response");
-			purple_xmlnode_set_namespace(reply, NS_XMPP_SASL);
-			purple_xmlnode_insert_data(reply, enc_out, -1);
-
-			g_free(enc_out);
-
-			g_string_free(response, TRUE);
-		}
-	}
-
-	g_free(enc_in);
-	g_free(dec_in);
-	g_hash_table_destroy(parts);
-
-	*response = reply;
-	return state;
-}
-
-static void
-digest_md5_dispose(JabberStream *js)
-{
-	g_free(js->auth_mech_data);
-	js->auth_mech_data = NULL;
-}
-
-static JabberSaslMech digest_md5_mech = {
-	10, /* priority */
-	"DIGEST-MD5", /* name */
-	digest_md5_start,
-	digest_md5_handle_challenge,
-	NULL, /* handle_success */
-	NULL, /* handle_failure */
-	digest_md5_dispose,
-};
-
-JabberSaslMech *jabber_auth_get_digest_md5_mech(void)
-{
-	return &digest_md5_mech;
-}
diff --git a/libpurple/protocols/jabber/auth_plain.c b/libpurple/protocols/jabber/auth_plain.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/auth_plain.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "jabber.h"
-#include "auth.h"
-
-static PurpleXmlNode *finish_plaintext_authentication(JabberStream *js)
-{
-	PurpleXmlNode *auth;
-	GString *response;
-	gchar *enc_out;
-
-	auth = purple_xmlnode_new("auth");
-	purple_xmlnode_set_namespace(auth, NS_XMPP_SASL);
-
-	response = g_string_new("");
-	response = g_string_append_c(response, '\0');
-	response = g_string_append(response, js->user->node);
-	response = g_string_append_c(response, '\0');
-	response = g_string_append(response,
-			purple_connection_get_password(js->gc));
-
-	enc_out = g_base64_encode((guchar *)response->str, response->len);
-
-	purple_xmlnode_set_attrib(auth, "mechanism", "PLAIN");
-	purple_xmlnode_insert_data(auth, enc_out, -1);
-	g_free(enc_out);
-	g_string_free(response, TRUE);
-
-	return auth;
-}
-
-static void allow_plaintext_auth(PurpleAccount *account)
-{
-	PurpleConnection *gc = purple_account_get_connection(account);
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-	PurpleXmlNode *response;
-
-	purple_account_set_bool(account, "auth_plain_in_clear", TRUE);
-
-	response = finish_plaintext_authentication(js);
-	jabber_send(js, response);
-	purple_xmlnode_free(response);
-}
-
-static void disallow_plaintext_auth(PurpleAccount *account)
-{
-	purple_connection_error(purple_account_get_connection(account),
-		PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
-		_("Server requires plaintext authentication over an unencrypted stream"));
-}
-
-static JabberSaslState
-jabber_plain_start(JabberStream *js, G_GNUC_UNUSED PurpleXmlNode *packet,
-                   PurpleXmlNode **response, G_GNUC_UNUSED char **error)
-{
-	PurpleAccount *account = purple_connection_get_account(js->gc);
-	PurpleContactInfo *info = PURPLE_CONTACT_INFO(account);
-	char *msg;
-
-	if (jabber_stream_is_ssl(js) || purple_account_get_bool(account, "auth_plain_in_clear", FALSE)) {
-		*response = finish_plaintext_authentication(js);
-		return JABBER_SASL_STATE_OK;
-	}
-
-	msg = g_strdup_printf(_("%s requires plaintext authentication over an unencrypted connection.  Allow this and continue authentication?"),
-			purple_contact_info_get_username(info));
-	purple_request_yes_no(js->gc, _("Plaintext Authentication"),
-			_("Plaintext Authentication"),
-			msg,
-			1,
-			purple_request_cpar_from_account(account),
-			account, allow_plaintext_auth, disallow_plaintext_auth);
-	g_free(msg);
-	return JABBER_SASL_STATE_CONTINUE;
-}
-
-static JabberSaslMech plain_mech = {
-	0, /* priority */
-	"PLAIN", /* name */
-	jabber_plain_start,
-	NULL, /* handle_challenge */
-	NULL, /* handle_success */
-	NULL, /* handle_failure */
-	NULL  /* dispose */
-};
-
-JabberSaslMech *jabber_auth_get_plain_mech(void)
-{
-	return &plain_mech;
-}
diff --git a/libpurple/protocols/jabber/auth_scram.h b/libpurple/protocols/jabber/auth_scram.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/auth_scram.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * @file auth_scram.h Implementation of SASL-SCRAM authentication
- *
- * 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_JABBER_AUTH_SCRAM_H
-#define PURPLE_JABBER_AUTH_SCRAM_H
-
-/*
- * Every function in this file is ONLY exposed for tests.
- * DO NOT USE ANYTHING HERE OR YOU WILL BE SENT TO THE PIT OF DESPAIR.
- */
-
-/* Per-connection state stored between messages.
- * This is stored in js->auth_data_mech.
- */
-typedef struct {
-	const char *mech_substr;
-	GChecksumType type;
-} JabberScramHash;
-
-typedef struct {
-	const JabberScramHash *hash;
-	char *cnonce;
-	GString *auth_message;
-
-	GString *client_proof;
-	GString *server_signature;
-
-	gchar *password;
-	gboolean channel_binding;
-	int step;
-} JabberScramData;
-
-#include "auth.h"
-
-/**
- * Implements the Hi() function as described in the SASL-SCRAM I-D.
- *
- * @param hash The struct corresponding to the hash function to be used.
- * @param str  The string to perform the PBKDF2 operation on.
- * @param salt The salt.
- * @param iterations The number of iterations to perform.
- *
- * @returns A newly allocated string containing the result. The string is
- *          NOT null-terminated and its length is the length of the binary
- *          output of the hash function in-use.
- */
-PURPLE_XMPP_EXTERN_FOR_TESTS
-guchar *jabber_scram_hi(const JabberScramHash *hash, const GString *str,
-                        GString *salt, guint iterations);
-
-/**
- * Calculates the proofs as described in Section 3 of the SASL-SCRAM I-D.
- *
- * @param data A JabberScramData structure. hash and auth_message must be
- *             set. client_proof and server_signature will be set as a result
- *             of this function.
- * @param salt       The salt (as specified by the server)
- * @param iterations The number of iterations to perform.
- *
- * @returns TRUE if the proofs were successfully calculated. FALSE otherwise.
- */
-PURPLE_XMPP_EXTERN_FOR_TESTS
-gboolean jabber_scram_calc_proofs(JabberScramData *data, GString *salt,
-                                  guint iterations);
-
-/**
- * Feed the algorithm with the data from the server.
- */
-PURPLE_XMPP_EXTERN_FOR_TESTS
-gboolean jabber_scram_feed_parser(JabberScramData *data, gchar *in, gchar **out);
-
-/**
- * Clean up and destroy the data struct
- */
-PURPLE_XMPP_EXTERN_FOR_TESTS
-void jabber_scram_data_destroy(JabberScramData *data);
-
-#endif /* PURPLE_JABBER_AUTH_SCRAM_H */
diff --git a/libpurple/protocols/jabber/auth_scram.c b/libpurple/protocols/jabber/auth_scram.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/auth_scram.c
+++ /dev/null
@@ -1,598 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "auth.h"
-#include "auth_scram.h"
-
-static const JabberScramHash hashes[] = {
-	{ "-SHA-1", G_CHECKSUM_SHA1 },
-};
-
-static const JabberScramHash *mech_to_hash(const char *mech)
-{
-	gsize i;
-
-	g_return_val_if_fail(mech != NULL && *mech != '\0', NULL);
-
-	for (i = 0; i < G_N_ELEMENTS(hashes); ++i) {
-		if (strstr(mech, hashes[i].mech_substr))
-			return &(hashes[i]);
-	}
-
-	purple_debug_error("jabber", "Unknown SCRAM mechanism %s\n", mech);
-	g_return_val_if_reached(NULL);
-}
-
-guchar *jabber_scram_hi(const JabberScramHash *hash, const GString *str,
-                        GString *salt, guint iterations)
-{
-	GHmac *hmac;
-	gsize digest_len;
-	guchar *result;
-	guint i;
-	guchar *prev, *tmp;
-
-	g_return_val_if_fail(hash != NULL, NULL);
-	g_return_val_if_fail(str != NULL && str->len > 0, NULL);
-	g_return_val_if_fail(salt != NULL && salt->len > 0, NULL);
-	g_return_val_if_fail(iterations > 0, NULL);
-
-	digest_len = g_checksum_type_get_length(hash->type);
-	prev   = g_new0(guchar, digest_len);
-	tmp    = g_new0(guchar, digest_len);
-	result = g_new0(guchar, digest_len);
-
-	hmac = g_hmac_new(hash->type, (guchar *)str->str, str->len);
-
-	/* Append INT(1), a four-octet encoding of the integer 1, most significant
-	 * octet first. */
-	g_string_append_len(salt, "\0\0\0\1", 4);
-
-	/* Compute U0 */
-	g_hmac_update(hmac, (guchar *)salt->str, salt->len);
-	g_hmac_get_digest(hmac, result, &digest_len);
-	g_hmac_unref(hmac);
-
-	memcpy(prev, result, digest_len);
-
-	/* Compute U1...Ui */
-	for (i = 1; i < iterations; ++i) {
-		guint j;
-		hmac = g_hmac_new(hash->type, (guchar *)str->str, str->len);
-		g_hmac_update(hmac, prev, digest_len);
-		g_hmac_get_digest(hmac, tmp, &digest_len);
-		g_hmac_unref(hmac);
-
-		for (j = 0; j < digest_len; ++j)
-			result[j] ^= tmp[j];
-
-		memcpy(prev, tmp, digest_len);
-	}
-
-	g_free(tmp);
-	g_free(prev);
-	return result;
-}
-
-/*
- * Helper functions for doing the SCRAM calculations. The first argument
- * is the hash algorithm.  All buffers must be of the appropriate size
- * according to the JabberScramHash.
- *
- * "str" is a NULL-terminated string for jabber_scram_hmac().
- *
- * Needless to say, these are fragile.
- */
-static void
-jabber_scram_hmac(const JabberScramHash *hash, guchar *out, const guchar *key, const gchar *str)
-{
-	GHmac *hmac;
-	gsize digest_len = g_checksum_type_get_length(hash->type);
-
-	hmac = g_hmac_new(hash->type, key, digest_len);
-	g_hmac_update(hmac, (guchar *)str, -1);
-	g_hmac_get_digest(hmac, out, &digest_len);
-	g_hmac_unref(hmac);
-}
-
-static void
-jabber_scram_hash(const JabberScramHash *hash, guchar *out, const guchar *data)
-{
-	GChecksum *checksum;
-	gsize digest_len = g_checksum_type_get_length(hash->type);
-
-	checksum = g_checksum_new(hash->type);
-	g_checksum_update(checksum, data, digest_len);
-	g_checksum_get_digest(checksum, out, &digest_len);
-	g_checksum_free(checksum);
-}
-
-gboolean
-jabber_scram_calc_proofs(JabberScramData *data, GString *salt, guint iterations)
-{
-	guint hash_len = g_checksum_type_get_length(data->hash->type);
-	guint i;
-
-	GString *pass = g_string_new(data->password);
-
-	guchar *salted_password;
-	guchar *client_key, *stored_key, *client_signature, *server_key;
-
-	data->client_proof = g_string_sized_new(hash_len);
-	data->client_proof->len = hash_len;
-	data->server_signature = g_string_sized_new(hash_len);
-	data->server_signature->len = hash_len;
-
-	salted_password = jabber_scram_hi(data->hash, pass, salt, iterations);
-
-	memset(pass->str, 0, pass->allocated_len);
-	g_string_free(pass, TRUE);
-
-	if (!salted_password)
-		return FALSE;
-
-	client_key = g_new0(guchar, hash_len);
-	stored_key = g_new0(guchar, hash_len);
-	client_signature = g_new0(guchar, hash_len);
-	server_key = g_new0(guchar, hash_len);
-
-	/* client_key = HMAC(salted_password, "Client Key") */
-	jabber_scram_hmac(data->hash, client_key, salted_password, "Client Key");
-	/* server_key = HMAC(salted_password, "Server Key") */
-	jabber_scram_hmac(data->hash, server_key, salted_password, "Server Key");
-	g_free(salted_password);
-
-	/* stored_key = HASH(client_key) */
-	jabber_scram_hash(data->hash, stored_key, client_key);
-
-	/* client_signature = HMAC(stored_key, auth_message) */
-	jabber_scram_hmac(data->hash, client_signature, stored_key, data->auth_message->str);
-	/* server_signature = HMAC(server_key, auth_message) */
-	jabber_scram_hmac(data->hash, (guchar *)data->server_signature->str, server_key, data->auth_message->str);
-
-	/* client_proof = client_key XOR client_signature */
-	for (i = 0; i < hash_len; ++i)
-		data->client_proof->str[i] = client_key[i] ^ client_signature[i];
-
-	g_free(server_key);
-	g_free(client_signature);
-	g_free(stored_key);
-	g_free(client_key);
-
-	return TRUE;
-}
-
-static gboolean
-parse_server_step1(JabberScramData *data, const char *challenge,
-                   gchar **out_nonce, GString **out_salt, guint *out_iterations)
-{
-	char **tokens;
-	char *token, *decoded, *tmp;
-	gsize len;
-	char *nonce = NULL;
-	GString *salt = NULL;
-	guint iterations;
-
-	tokens = g_strsplit(challenge, ",", -1);
-	if (tokens == NULL)
-		return FALSE;
-
-	token = tokens[0];
-	if (token[0] != 'r' || token[1] != '=')
-		goto err;
-
-	/* Ensure that the first cnonce_len bytes of the nonce are the original
-	 * cnonce we sent to the server.
-	 */
-	if (0 != strncmp(data->cnonce, token + 2, strlen(data->cnonce)))
-		goto err;
-
-	nonce = g_strdup(token + 2);
-
-	/* The Salt, base64-encoded */
-	token = tokens[1];
-	if (token[0] != 's' || token[1] != '=')
-		goto err;
-
-	decoded = (gchar *)g_base64_decode(token + 2, &len);
-	if (!decoded || *decoded == '\0') {
-		g_free(decoded);
-		goto err;
-	}
-	salt = g_string_new_len(decoded, len);
-	g_free(decoded);
-
-	/* The iteration count */
-	token = tokens[2];
-	if (token[0] != 'i' || token[1] != '=' || token[2] == '\0')
-		goto err;
-
-	/* Validate the string */
-	for (tmp = token + 2; *tmp; ++tmp)
-		if (!g_ascii_isdigit(*tmp))
-			goto err;
-
-	iterations = strtoul(token + 2, NULL, 10);
-
-	g_strfreev(tokens);
-	*out_nonce = nonce;
-	*out_salt = salt;
-	*out_iterations = iterations;
-	return TRUE;
-
-err:
-	g_free(nonce);
-	if (salt)
-		g_string_free(salt, TRUE);
-	g_strfreev(tokens);
-	return FALSE;
-}
-
-static gboolean
-parse_server_step2(G_GNUC_UNUSED JabberScramData *data, const char *challenge,
-                   char **out_verifier)
-{
-	char **tokens;
-	char *token;
-
-	tokens = g_strsplit(challenge, ",", -1);
-	if (tokens == NULL)
-		return FALSE;
-
-	token = tokens[0];
-	if (token[0] != 'v' || token[1] != '=' || token[2] == '\0') {
-		g_strfreev(tokens);
-		return FALSE;
-	}
-
-	*out_verifier = g_strdup(token + 2);
-	g_strfreev(tokens);
-	return TRUE;
-}
-
-gboolean
-jabber_scram_feed_parser(JabberScramData *data, gchar *in, gchar **out)
-{
-	gboolean ret;
-
-	g_return_val_if_fail(data != NULL, FALSE);
-
-	g_string_append_c(data->auth_message, ',');
-	g_string_append(data->auth_message, in);
-
-	if (data->step == 1) {
-		gchar *nonce, *proof;
-		GString *salt;
-		guint iterations;
-
-		ret = parse_server_step1(data, in, &nonce, &salt, &iterations);
-		if (!ret)
-			return FALSE;
-
-		g_string_append_c(data->auth_message, ',');
-
-		/* "biws" is the base64 encoding of "n,,". I promise. */
-		g_string_append_printf(data->auth_message, "c=%s,r=%s", "biws", nonce);
-#ifdef CHANNEL_BINDING
-#error fix this
-#endif
-
-		ret = jabber_scram_calc_proofs(data, salt, iterations);
-
-		g_string_free(salt, TRUE);
-		salt = NULL;
-		if (!ret) {
-			g_free(nonce);
-			return FALSE;
-		}
-
-		proof = g_base64_encode((guchar *)data->client_proof->str, data->client_proof->len);
-		*out = g_strdup_printf("c=%s,r=%s,p=%s", "biws", nonce, proof);
-		g_free(nonce);
-		g_free(proof);
-	} else if (data->step == 2) {
-		gchar *server_sig, *enc_server_sig;
-		gsize len;
-
-		ret = parse_server_step2(data, in, &enc_server_sig);
-		if (!ret)
-			return FALSE;
-
-		server_sig = (gchar *)g_base64_decode(enc_server_sig, &len);
-		g_free(enc_server_sig);
-
-		if (server_sig == NULL || len != data->server_signature->len) {
-			g_free(server_sig);
-			return FALSE;
-		}
-
-		if (0 != memcmp(server_sig, data->server_signature->str, len)) {
-			g_free(server_sig);
-			return FALSE;
-		}
-		g_free(server_sig);
-
-		*out = NULL;
-	} else {
-		purple_debug_error("jabber", "SCRAM: There is no step %d\n", data->step);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-static gchar *escape_username(const gchar *in)
-{
-	gchar *tmp, *tmp2;
-
-	tmp = purple_strreplace(in, "=", "=3D");
-	tmp2 = purple_strreplace(tmp, ",", "=2C");
-	g_free(tmp);
-	return tmp2;
-}
-
-static JabberSaslState
-scram_start(JabberStream *js, G_GNUC_UNUSED PurpleXmlNode *mechanisms,
-            PurpleXmlNode **out, char **error)
-{
-	PurpleXmlNode *reply;
-	JabberScramData *data;
-	guint64 cnonce;
-#ifdef CHANNEL_BINDING
-	gboolean binding_supported = TRUE;
-#endif
-	gchar *dec_out, *enc_out;
-	gchar *prepped_node, *tmp;
-	gchar *prepped_pass;
-
-	prepped_node = jabber_saslprep(js->user->node);
-	if (!prepped_node) {
-		*error = g_strdup(_("Unable to canonicalize username"));
-		return JABBER_SASL_STATE_FAIL;
-	}
-
-	tmp = escape_username(prepped_node);
-	g_free(prepped_node);
-	prepped_node = tmp;
-
-	prepped_pass = jabber_saslprep(purple_connection_get_password(js->gc));
-	if (!prepped_pass) {
-		g_free(prepped_node);
-		*error = g_strdup(_("Unable to canonicalize password"));
-		return JABBER_SASL_STATE_FAIL;
-	}
-
-	data = js->auth_mech_data = g_new0(JabberScramData, 1);
-	data->hash = mech_to_hash(js->auth_mech->name);
-	data->password = prepped_pass;
-
-#ifdef CHANNEL_BINDING
-	if (strstr(js->auth_mech_name, "-PLUS"))
-		data->channel_binding = TRUE;
-#endif
-	cnonce = ((guint64)g_random_int() << 32) | g_random_int();
-	data->cnonce = g_base64_encode((guchar *)&cnonce, sizeof(cnonce));
-
-	data->auth_message = g_string_new(NULL);
-	g_string_printf(data->auth_message, "n=%s,r=%s",
-			prepped_node, data->cnonce);
-	g_free(prepped_node);
-
-	data->step = 1;
-
-	reply = purple_xmlnode_new("auth");
-	purple_xmlnode_set_namespace(reply, NS_XMPP_SASL);
-	purple_xmlnode_set_attrib(reply, "mechanism", js->auth_mech->name);
-
-	/* TODO: Channel binding */
-	dec_out = g_strdup_printf("%c,,%s", 'n', data->auth_message->str);
-	enc_out = g_base64_encode((guchar *)dec_out, strlen(dec_out));
-	purple_debug_misc("jabber", "initial SCRAM message '%s'\n", dec_out);
-
-	purple_xmlnode_insert_data(reply, enc_out, -1);
-
-	g_free(enc_out);
-	g_free(dec_out);
-
-	*out = reply;
-	return JABBER_SASL_STATE_CONTINUE;
-}
-
-static JabberSaslState
-scram_handle_challenge(JabberStream *js, PurpleXmlNode *challenge, PurpleXmlNode **out, char **error)
-{
-	JabberScramData *data = js->auth_mech_data;
-	PurpleXmlNode *reply;
-	gchar *enc_in, *dec_in = NULL;
-	gchar *enc_out = NULL, *dec_out = NULL;
-	gsize len;
-	JabberSaslState state = JABBER_SASL_STATE_FAIL;
-
-	enc_in = purple_xmlnode_get_data(challenge);
-	if (!enc_in || *enc_in == '\0') {
-		reply = purple_xmlnode_new("abort");
-		purple_xmlnode_set_namespace(reply, NS_XMPP_SASL);
-		data->step = -1;
-		*error = g_strdup(_("Invalid challenge from server"));
-		goto out;
-	}
-
-	dec_in = (gchar *)g_base64_decode(enc_in, &len);
-	if (!dec_in || len != strlen(dec_in)) {
-		/* Danger afoot; SCRAM shouldn't contain NUL bytes */
-		reply = purple_xmlnode_new("abort");
-		purple_xmlnode_set_namespace(reply, NS_XMPP_SASL);
-		data->step = -1;
-		*error = g_strdup(_("Malicious challenge from server"));
-		goto out;
-	}
-
-	purple_debug_misc("jabber", "decoded challenge: %s\n", dec_in);
-
-	if (!jabber_scram_feed_parser(data, dec_in, &dec_out)) {
-		reply = purple_xmlnode_new("abort");
-		purple_xmlnode_set_namespace(reply, NS_XMPP_SASL);
-		data->step = -1;
-		*error = g_strdup(_("Invalid challenge from server"));
-		goto out;
-	}
-
-	data->step += 1;
-
-	reply = purple_xmlnode_new("response");
-	purple_xmlnode_set_namespace(reply, NS_XMPP_SASL);
-
-	purple_debug_misc("jabber", "decoded response: %s\n", dec_out ? dec_out : "(null)");
-	if (dec_out) {
-		enc_out = g_base64_encode((guchar *)dec_out, strlen(dec_out));
-		purple_xmlnode_insert_data(reply, enc_out, -1);
-	}
-
-	state = JABBER_SASL_STATE_CONTINUE;
-
-out:
-	g_free(enc_in);
-	g_free(dec_in);
-	g_free(enc_out);
-	g_free(dec_out);
-
-	*out = reply;
-	return state;
-}
-
-static JabberSaslState
-scram_handle_success(JabberStream *js, PurpleXmlNode *packet, char **error)
-{
-	JabberScramData *data = js->auth_mech_data;
-	char *enc_in, *dec_in;
-	char *dec_out = NULL;
-	gsize len;
-
-	enc_in = purple_xmlnode_get_data(packet);
-	if (data->step != 3 && (!enc_in || *enc_in == '\0')) {
-		*error = g_strdup(_("Invalid challenge from server"));
-		g_free(enc_in);
-		return JABBER_SASL_STATE_FAIL;
-	}
-
-	if (data->step == 3) {
-		/*
-		 * If the server took the slow approach (sending the verifier
-		 * as a challenge/response pair), we get here.
-		 */
-		g_free(enc_in);
-		return JABBER_SASL_STATE_OK;
-	}
-
-	if (data->step != 2) {
-		*error = g_strdup(_("Unexpected response from server"));
-		g_free(enc_in);
-		return JABBER_SASL_STATE_FAIL;
-	}
-
-	dec_in = (gchar *)g_base64_decode(enc_in, &len);
-	g_free(enc_in);
-	if (!dec_in || len != strlen(dec_in)) {
-		/* Danger afoot; SCRAM shouldn't contain NUL bytes */
-		g_free(dec_in);
-		*error = g_strdup(_("Malicious challenge from server"));
-		return JABBER_SASL_STATE_FAIL;
-	}
-
-	purple_debug_misc("jabber", "decoded success: %s\n", dec_in);
-
-	if (!jabber_scram_feed_parser(data, dec_in, &dec_out) || dec_out != NULL) {
-		g_free(dec_in);
-		g_free(dec_out);
-		*error = g_strdup(_("Invalid challenge from server"));
-		return JABBER_SASL_STATE_FAIL;
-	}
-
-	g_free(dec_in);
-	/* Hooray */
-	return JABBER_SASL_STATE_OK;
-}
-
-void jabber_scram_data_destroy(JabberScramData *data)
-{
-	g_free(data->cnonce);
-	if (data->auth_message)
-		g_string_free(data->auth_message, TRUE);
-	if (data->client_proof)
-		g_string_free(data->client_proof, TRUE);
-	if (data->server_signature)
-		g_string_free(data->server_signature, TRUE);
-	if (data->password) {
-		memset(data->password, 0, strlen(data->password));
-		g_free(data->password);
-	}
-
-	g_free(data);
-}
-
-static void scram_dispose(JabberStream *js)
-{
-	if (js->auth_mech_data) {
-		jabber_scram_data_destroy(js->auth_mech_data);
-		js->auth_mech_data = NULL;
-	}
-}
-
-static JabberSaslMech scram_sha1_mech = {
-	50, /* priority */
-	"SCRAM-SHA-1", /* name */
-	scram_start,
-	scram_handle_challenge,
-	scram_handle_success,
-	NULL, /* handle_failure */
-	scram_dispose
-};
-
-#ifdef CHANNEL_BINDING
-/* With channel binding */
-static JabberSaslMech scram_sha1_plus_mech = {
-	scram_sha1_mech.priority + 1, /* priority */
-	"SCRAM-SHA-1-PLUS", /* name */
-	scram_start,
-	scram_handle_challenge,
-	scram_handle_success,
-	NULL, /* handle_failure */
-	scram_dispose
-};
-#endif
-
-JabberSaslMech **jabber_auth_get_scram_mechs(gint *count)
-{
-	static JabberSaslMech *mechs[] = {
-		&scram_sha1_mech,
-#ifdef CHANNEL_BINDING
-		&scram_sha1_plus_mech,
-#endif
-	};
-
-	*count = G_N_ELEMENTS(mechs);
-	return mechs;
-}
diff --git a/libpurple/protocols/jabber/auth_webex.c b/libpurple/protocols/jabber/auth_webex.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/auth_webex.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <purple.h>
-
-#include "jabber.h"
-#include "auth.h"
-
-static PurpleXmlNode *finish_webex_authentication(JabberStream *js)
-{
-	PurpleXmlNode *auth;
-
-	auth = purple_xmlnode_new("auth");
-	purple_xmlnode_set_namespace(auth, NS_XMPP_SASL);
-
-	purple_xmlnode_set_attrib(auth, "mechanism", "WEBEX-TOKEN");
-	purple_xmlnode_insert_data(auth, purple_connection_get_password(js->gc), -1);
-
-	return auth;
-}
-
-static JabberSaslState
-jabber_webex_start(JabberStream *js, G_GNUC_UNUSED PurpleXmlNode *packet,
-                   PurpleXmlNode **response, G_GNUC_UNUSED char **error)
-{
-	*response = finish_webex_authentication(js);
-	return JABBER_SASL_STATE_OK;
-}
-
-static JabberSaslMech webex_token_mech = {
-	101, /* priority */
-	"WEBEX-TOKEN", /* name */
-	jabber_webex_start,
-	NULL, /* handle_challenge */
-	NULL, /* handle_success */
-	NULL, /* handle_failure */
-	NULL  /* dispose */
-};
-
-JabberSaslMech *jabber_auth_get_webex_token_mech(void)
-{
-	return &webex_token_mech;
-}
diff --git a/libpurple/protocols/jabber/bosh.h b/libpurple/protocols/jabber/bosh.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/bosh.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * @file bosh.h Bidirectional-streams over Synchronous HTTP (BOSH)
- * (XEP-0124 and XEP-0206)
- *
- * 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_JABBER_BOSH_H
-#define PURPLE_JABBER_BOSH_H
-
-typedef struct _PurpleJabberBOSHConnection PurpleJabberBOSHConnection;
-
-#include "jabber.h"
-
-void
-jabber_bosh_init(void);
-
-void
-jabber_bosh_uninit(void);
-
-PurpleJabberBOSHConnection *
-jabber_bosh_connection_new(JabberStream *js, const gchar *url);
-
-void
-jabber_bosh_connection_destroy(PurpleJabberBOSHConnection *conn);
-
-gboolean
-jabber_bosh_connection_is_ssl(const PurpleJabberBOSHConnection *conn);
-
-void
-jabber_bosh_connection_send(PurpleJabberBOSHConnection *conn,
-	const gchar *data);
-
-void
-jabber_bosh_connection_send_keepalive(PurpleJabberBOSHConnection *conn);
-
-#endif /* PURPLE_JABBER_BOSH_H */
diff --git a/libpurple/protocols/jabber/bosh.c b/libpurple/protocols/jabber/bosh.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/bosh.c
+++ /dev/null
@@ -1,544 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include <libsoup/soup.h>
-
-#include "bosh.h"
-
-/*
-TODO: test, what happens, if the http server (BOSH server) doesn't support
-keep-alive (sends connection: close).
-*/
-
-#define JABBER_BOSH_SEND_DELAY 250
-
-#define JABBER_BOSH_TIMEOUT 10
-
-static gchar *jabber_bosh_useragent = NULL;
-
-struct _PurpleJabberBOSHConnection {
-	JabberStream *js;
-	SoupSession *payload_reqs;
-
-	gchar *url;
-	gboolean is_ssl;
-	gboolean is_terminating;
-
-	gchar *sid;
-	guint64 rid; /* Must be big enough to hold 2^53 - 1 */
-
-	GString *send_buff;
-	guint send_timer;
-};
-
-static SoupMessage *jabber_bosh_connection_http_request_new(
-        PurpleJabberBOSHConnection *conn, GString *data);
-static void
-jabber_bosh_connection_session_create(PurpleJabberBOSHConnection *conn);
-static void
-jabber_bosh_connection_send_now(PurpleJabberBOSHConnection *conn);
-
-void
-jabber_bosh_init(void)
-{
-	PurpleUi *ui = purple_core_get_ui();
-	const gchar *ui_name = NULL;
-	const gchar *ui_version = NULL;
-
-	if(PURPLE_IS_UI(ui)) {
-		ui_name = purple_ui_get_name(ui);
-		ui_version = purple_ui_get_version(ui);
-	}
-
-	if(ui_name) {
-		jabber_bosh_useragent = g_strdup_printf(
-			"%s%s%s (libpurple " VERSION ")", ui_name,
-			ui_version ? " " : "", ui_version ? ui_version : "");
-	} else {
-		jabber_bosh_useragent = g_strdup("libpurple " VERSION);
-	}
-}
-
-void jabber_bosh_uninit(void)
-{
-	g_clear_pointer(&jabber_bosh_useragent, g_free);
-}
-
-PurpleJabberBOSHConnection*
-jabber_bosh_connection_new(JabberStream *js, const gchar *url)
-{
-	PurpleJabberBOSHConnection *conn;
-	PurpleAccount *account;
-	GProxyResolver *resolver;
-	GError *error = NULL;
-	const gchar *scheme;
-
-	account = purple_connection_get_account(js->gc);
-	resolver = purple_proxy_get_proxy_resolver(account, &error);
-	if (resolver == NULL) {
-		purple_debug_error("jabber-bosh",
-		                   "Unable to get account proxy resolver: %s",
-		                   error->message);
-		g_error_free(error);
-		return NULL;
-	}
-
-	scheme = g_uri_peek_scheme(url);
-	if (scheme == NULL) {
-		purple_debug_error("jabber-bosh", "Unable to parse given BOSH URL: %s",
-		                   url);
-		g_object_unref(resolver);
-		return NULL;
-	}
-
-	conn = g_new0(PurpleJabberBOSHConnection, 1);
-	conn->payload_reqs = soup_session_new_with_options(
-	        "proxy-resolver", resolver,
-	        "timeout", JABBER_BOSH_TIMEOUT + 2,
-	        "user-agent", jabber_bosh_useragent,
-	        NULL);
-	conn->url = g_strdup(url);
-	conn->js = js;
-	conn->is_ssl = g_str_equal(scheme, "https");
-	conn->send_buff = g_string_new(NULL);
-
-	/*
-	 * Random 64-bit integer masked off by 2^52 - 1.
-	 *
-	 * This should produce a random integer in the range [0, 2^52). It's
-	 * unlikely we'll send enough packets in one session to overflow the
-	 * rid.
-	 */
-	conn->rid = (((guint64)g_random_int() << 32) | g_random_int());
-	conn->rid &= 0xFFFFFFFFFFFFFLL;
-
-	g_object_unref(resolver);
-
-	jabber_bosh_connection_session_create(conn);
-
-	return conn;
-}
-
-void
-jabber_bosh_connection_destroy(PurpleJabberBOSHConnection *conn)
-{
-	if (conn == NULL || conn->is_terminating)
-		return;
-	conn->is_terminating = TRUE;
-
-	if (conn->sid != NULL) {
-		purple_debug_info("jabber-bosh",
-			"Terminating a session for %p\n", conn);
-		jabber_bosh_connection_send_now(conn);
-	}
-
-	g_clear_handle_id(&conn->send_timer, g_source_remove);
-
-	soup_session_abort(conn->payload_reqs);
-
-	g_clear_object(&conn->payload_reqs);
-	g_string_free(conn->send_buff, TRUE);
-	conn->send_buff = NULL;
-
-	g_free(conn->sid);
-	conn->sid = NULL;
-	g_free(conn->url);
-	conn->url = NULL;
-
-	g_free(conn);
-}
-
-gboolean
-jabber_bosh_connection_is_ssl(const PurpleJabberBOSHConnection *conn)
-{
-	return conn->is_ssl;
-}
-
-static PurpleXmlNode *
-jabber_bosh_connection_parse(PurpleJabberBOSHConnection *conn,
-                             SoupMessage *msg, GBytes *response_body,
-                             GError *error)
-{
-	gconstpointer body = NULL;
-	gsize length = 0;
-	PurpleXmlNode *root;
-	const gchar *type;
-
-	g_return_val_if_fail(conn != NULL, NULL);
-	g_return_val_if_fail(msg != NULL, NULL);
-
-	if (conn->is_terminating || purple_account_is_disconnecting(
-		purple_connection_get_account(conn->js->gc)))
-	{
-		return NULL;
-	}
-
-	if(error != NULL ||
-	   !SOUP_STATUS_IS_SUCCESSFUL(soup_message_get_status(msg))) {
-		gchar *tmp = g_strdup_printf(
-		    _("Unable to connect: %s"),
-		    error ? error->message : soup_message_get_reason_phrase(msg));
-		purple_connection_error(conn->js->gc,
-		                        PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-		g_free(tmp);
-		return NULL;
-	}
-
-	body = g_bytes_get_data(response_body, &length);
-	root = purple_xmlnode_from_str(body, length);
-
-	type = purple_xmlnode_get_attrib(root, "type");
-	if (purple_strequal(type, "terminate")) {
-		purple_connection_error(conn->js->gc,
-			PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("The BOSH "
-			"connection manager terminated your session."));
-		purple_xmlnode_free(root);
-		return NULL;
-	}
-
-	return root;
-}
-
-static void
-jabber_bosh_connection_recv(GObject *source, GAsyncResult *result,
-                            gpointer data)
-{
-	SoupMessage *msg = data;
-	PurpleJabberBOSHConnection *bosh_conn = NULL;
-	GBytes *response_body = NULL;
-	GError *error = NULL;
-	PurpleXmlNode *node, *child;
-
-	response_body = soup_session_send_and_read_finish(SOUP_SESSION(source),
-	                                                  result, &error);
-	bosh_conn = g_object_get_data(G_OBJECT(msg), "bosh-connection");
-
-	if (response_body != NULL && purple_debug_is_verbose() &&
-	    purple_debug_is_unsafe())
-	{
-		const gchar *body = NULL;
-		gsize length = 0;
-
-		body = g_bytes_get_data(response_body, &length);
-		purple_debug_misc("jabber-bosh", "received: %.*s", (int)length, body);
-	}
-
-	node = jabber_bosh_connection_parse(bosh_conn, msg, response_body, error);
-	g_clear_pointer(&response_body, g_bytes_unref);
-	g_clear_error(&error);
-	g_clear_object(&msg);
-
-	if (node == NULL) {
-		return;
-	}
-
-	child = node->child;
-	while (child != NULL) {
-		/* jabber_process_packet might free child */
-		PurpleXmlNode *next = child->next;
-		const gchar *xmlns;
-
-		if (child->type != PURPLE_XMLNODE_TYPE_TAG) {
-			child = next;
-			continue;
-		}
-
-		/* Workaround for non-compliant servers that don't stamp
-		 * the right xmlns on these packets. See #11315.
-		 */
-		xmlns = purple_xmlnode_get_namespace(child);
-		if ((xmlns == NULL || purple_strequal(xmlns, NS_BOSH)) &&
-			(purple_strequal(child->name, "iq") ||
-			purple_strequal(child->name, "message") ||
-			purple_strequal(child->name, "presence")))
-		{
-			purple_xmlnode_set_namespace(child, NS_XMPP_CLIENT);
-		}
-
-		jabber_process_packet(bosh_conn->js, &child);
-
-		child = next;
-	}
-
-	jabber_bosh_connection_send(bosh_conn, NULL);
-}
-
-static void
-jabber_bosh_connection_send_now(PurpleJabberBOSHConnection *conn)
-{
-	SoupMessage *req;
-	GString *data;
-
-	g_return_if_fail(conn != NULL);
-
-	g_clear_handle_id(&conn->send_timer, g_source_remove);
-
-	if (conn->sid == NULL)
-		return;
-
-	data = g_string_new(NULL);
-
-	/* missing parameters: route, from, ack */
-	g_string_printf(data, "<body "
-		"rid='%" G_GUINT64_FORMAT "' "
-		"sid='%s' "
-		"xmlns='" NS_BOSH "' "
-		"xmlns:xmpp='" NS_XMPP_BOSH "' ",
-		++conn->rid, conn->sid);
-
-	if (conn->js->reinit && !conn->is_terminating) {
-		g_string_append(data, "xmpp:restart='true'/>");
-		conn->js->reinit = FALSE;
-	} else {
-		if (conn->is_terminating)
-			g_string_append(data, "type='terminate' ");
-		g_string_append_c(data, '>');
-		g_string_append_len(data, conn->send_buff->str,
-			conn->send_buff->len);
-		g_string_append(data, "</body>");
-		g_string_set_size(conn->send_buff, 0);
-	}
-
-	if (purple_debug_is_verbose() && purple_debug_is_unsafe())
-		purple_debug_misc("jabber-bosh", "sending: %s\n", data->str);
-
-	req = jabber_bosh_connection_http_request_new(conn, data);
-
-	if (conn->is_terminating) {
-		soup_session_send_async(conn->payload_reqs, req, G_PRIORITY_DEFAULT,
-		                        NULL, NULL, NULL);
-		g_free(conn->sid);
-		conn->sid = NULL;
-	} else {
-		g_object_set_data(G_OBJECT(req), "bosh-connection", conn);
-		soup_session_send_and_read_async(conn->payload_reqs, req,
-		                                 G_PRIORITY_DEFAULT, NULL,
-		                                 jabber_bosh_connection_recv, req);
-	}
-}
-
-static gboolean
-jabber_bosh_connection_send_delayed(gpointer _conn)
-{
-	PurpleJabberBOSHConnection *conn = _conn;
-
-	conn->send_timer = 0;
-	jabber_bosh_connection_send_now(conn);
-
-	return FALSE;
-}
-
-void
-jabber_bosh_connection_send(PurpleJabberBOSHConnection *conn,
-	const gchar *data)
-{
-	g_return_if_fail(conn != NULL);
-
-	if (data)
-		g_string_append(conn->send_buff, data);
-
-	if (conn->send_timer == 0) {
-		conn->send_timer = g_timeout_add(
-			JABBER_BOSH_SEND_DELAY,
-			jabber_bosh_connection_send_delayed, conn);
-	}
-}
-
-void
-jabber_bosh_connection_send_keepalive(PurpleJabberBOSHConnection *conn)
-{
-	g_return_if_fail(conn != NULL);
-
-	jabber_bosh_connection_send_now(conn);
-}
-
-static gboolean
-jabber_bosh_version_check(const gchar *version, int major_req, int minor_min)
-{
-	const gchar *dot;
-	int major, minor = 0;
-
-	if (version == NULL)
-		return FALSE;
-
-	major = atoi(version);
-	dot = strchr(version, '.');
-	if (dot)
-		minor = atoi(dot + 1);
-
-	if (major != major_req)
-		return FALSE;
-	if (minor < minor_min)
-		return FALSE;
-	return TRUE;
-}
-
-static void
-jabber_bosh_connection_session_created(GObject *source, GAsyncResult *result,
-                                       gpointer data)
-{
-	SoupMessage *msg = data;
-	PurpleJabberBOSHConnection *bosh_conn = NULL;
-	GBytes *response_body = NULL;
-	GError *error = NULL;
-	PurpleXmlNode *node, *features;
-	const gchar *sid, *ver, *inactivity_str;
-	int inactivity = 0;
-
-	response_body = soup_session_send_and_read_finish(SOUP_SESSION(source),
-	                                                  result, &error);
-	bosh_conn = g_object_get_data(G_OBJECT(msg), "bosh-connection");
-
-	if (response_body != NULL && purple_debug_is_verbose() &&
-	    purple_debug_is_unsafe())
-	{
-		const gchar *body = NULL;
-		gsize length = 0;
-
-		body = g_bytes_get_data(response_body, &length);
-		purple_debug_misc("jabber-bosh", "received (session creation): %.*s",
-		                  (int)length, body);
-	}
-
-	node = jabber_bosh_connection_parse(bosh_conn, msg, response_body, error);
-	g_clear_pointer(&response_body, g_bytes_unref);
-	g_clear_error(&error);
-	g_clear_object(&msg);
-
-	if (node == NULL) {
-		return;
-	}
-
-	sid = purple_xmlnode_get_attrib(node, "sid");
-	ver = purple_xmlnode_get_attrib(node, "ver");
-	inactivity_str = purple_xmlnode_get_attrib(node, "inactivity");
-	/* requests = purple_xmlnode_get_attrib(node, "requests"); */
-
-	if (!sid) {
-		purple_connection_error(bosh_conn->js->gc,
-			PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-			_("No BOSH session ID given"));
-		purple_xmlnode_free(node);
-		return;
-	}
-
-	if (ver == NULL) {
-		purple_debug_info("jabber-bosh", "Missing version in BOSH initiation\n");
-	} else if (!jabber_bosh_version_check(ver, 1, 6)) {
-		purple_debug_error("jabber-bosh",
-			"Unsupported BOSH version: %s\n", ver);
-		purple_connection_error(bosh_conn->js->gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("Unsupported version of BOSH protocol"));
-		purple_xmlnode_free(node);
-		return;
-	}
-
-	purple_debug_misc("jabber-bosh", "Session created for %p\n", bosh_conn);
-
-	bosh_conn->sid = g_strdup(sid);
-
-	if (inactivity_str)
-		inactivity = atoi(inactivity_str);
-	if (inactivity < 0 || inactivity > 3600) {
-		purple_debug_warning("jabber-bosh", "Ignoring invalid "
-			"inactivity value: %s\n", inactivity_str);
-		inactivity = 0;
-	}
-	if (inactivity > 0) {
-		inactivity -= 5; /* rounding */
-		if (inactivity <= 0)
-			inactivity = 1;
-		bosh_conn->js->max_inactivity = inactivity;
-		if (bosh_conn->js->inactivity_timer == 0) {
-			purple_debug_misc("jabber-bosh", "Starting inactivity "
-				"timer for %d secs (compensating for "
-				"rounding)\n", inactivity);
-			jabber_stream_restart_inactivity_timer(bosh_conn->js);
-		}
-	}
-
-	jabber_stream_set_state(bosh_conn->js, JABBER_STREAM_AUTHENTICATING);
-
-	/* FIXME: Depending on receiving features might break with some hosts */
-	features = purple_xmlnode_get_child(node, "features");
-	jabber_stream_features_parse(bosh_conn->js, features);
-
-	purple_xmlnode_free(node);
-
-	jabber_bosh_connection_send(bosh_conn, NULL);
-}
-
-static void
-jabber_bosh_connection_session_create(PurpleJabberBOSHConnection *conn)
-{
-	SoupMessage *req;
-	GString *data;
-
-	purple_debug_misc("jabber-bosh", "Requesting Session Create for %p\n",
-		conn);
-
-	data = g_string_new(NULL);
-
-	/* missing optional parameters: route, from, ack */
-	g_string_printf(data, "<body content='text/xml; charset=utf-8' "
-		"rid='%" G_GUINT64_FORMAT "' "
-		"to='%s' "
-		"xml:lang='en' "
-		"ver='1.10' "
-		"wait='%d' "
-		"hold='1' "
-		"xmlns='" NS_BOSH "' "
-		"xmpp:version='1.0' "
-		"xmlns:xmpp='urn:xmpp:xbosh' "
-		"/>",
-		++conn->rid, conn->js->user->domain, JABBER_BOSH_TIMEOUT);
-
-	req = jabber_bosh_connection_http_request_new(conn, data);
-	g_object_set_data(G_OBJECT(req), "bosh-connection", conn);
-	soup_session_send_and_read_async(conn->payload_reqs, req,
-	                                 G_PRIORITY_DEFAULT, NULL,
-	                                 jabber_bosh_connection_session_created,
-	                                 req);
-}
-
-static SoupMessage *
-jabber_bosh_connection_http_request_new(PurpleJabberBOSHConnection *conn,
-                                        GString *data)
-{
-	SoupMessage *req;
-	GBytes *body = NULL;
-
-	jabber_stream_restart_inactivity_timer(conn->js);
-
-	req = soup_message_new("POST", conn->url);
-	body = g_string_free_to_bytes(data);
-	soup_message_set_request_body_from_bytes(req, "text/xml; charset=utf-8",
-	                                         body);
-	g_bytes_unref(body);
-
-	return req;
-}
diff --git a/libpurple/protocols/jabber/buddy.h b/libpurple/protocols/jabber/buddy.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/buddy.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- * @file buddy.h Buddy handlers
- *
- * 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_JABBER_BUDDY_H
-#define PURPLE_JABBER_BUDDY_H
-
-typedef struct _JabberBuddy JabberBuddy;
-
-#include <purple.h>
-
-#include "jabber.h"
-#include "caps.h"
-#include "jutil.h"
-
-struct _JabberBuddy {
-	/**
-	 * A sorted list of resources in priority descending order.
-	 * This means that the first resource in the list is the
-	 * "most available" (see resource_compare_cb in buddy.c for
-	 * details).  Don't play with this yourself, let
-	 * jabber_buddy_track_resource and jabber_buddy_remove_resource do it.
-	 */
-	GList *resources;
-	char *error_msg;
-	enum {
-		JABBER_INVISIBLE_NONE   = 0,
-		JABBER_INVISIBLE_SERVER = 1 << 1,
-		JABBER_INVIS_BUDDY      = 1 << 2
-	} invisible;
-	enum {
-		JABBER_SUB_NONE    = 0,
-		JABBER_SUB_PENDING = 1 << 1,
-		JABBER_SUB_TO      = 1 << 2,
-		JABBER_SUB_FROM    = 1 << 3,
-		JABBER_SUB_BOTH    = (JABBER_SUB_TO | JABBER_SUB_FROM),
-		JABBER_SUB_REMOVE  = 1 << 4
-	} subscription;
-};
-
-typedef struct {
-	JabberBuddy *jb;
-	char *name;
-	int priority;
-	JabberBuddyState state;
-	char *status;
-	time_t idle;
-	JabberCapabilities capabilities;
-	char *thread_id;
-	enum {
-		JABBER_CHAT_STATES_UNKNOWN,
-		JABBER_CHAT_STATES_UNSUPPORTED,
-		JABBER_CHAT_STATES_SUPPORTED
-	} chat_states;
-	struct {
-		char *version;
-		char *name;
-		char *os;
-	} client;
-	GTimeZone *tz_off;
-	JabberCapsClientInfo *caps;
-	GList *commands;
-	gboolean commands_fetched;
-} JabberBuddyResource;
-
-void jabber_buddy_free(JabberBuddy *jb);
-JabberBuddy *jabber_buddy_find(JabberStream *js, const char *name,
-		gboolean create);
-JabberBuddyResource *jabber_buddy_find_resource(JabberBuddy *jb,
-		const char *resource);
-JabberBuddyResource *jabber_buddy_track_resource(JabberBuddy *jb, const char *resource,
-		int priority, JabberBuddyState state, const char *status);
-void jabber_buddy_remove_resource(JabberBuddy *jb, const char *resource);
-void jabber_buddy_get_info(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const char *who);
-
-GList *jabber_blist_node_menu(PurpleProtocolClient *client, PurpleBlistNode *node);
-
-void jabber_set_info(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const char *info);
-void jabber_setup_set_info(GSimpleAction *action, GVariant *parameter, gpointer data);
-void jabber_set_buddy_icon(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleImage *img);
-
-void jabber_buddy_remove_all_pending_buddy_info_requests(JabberStream *js);
-
-void jabber_vcard_fetch_mine(JabberStream *js);
-
-gboolean jabber_resource_know_capabilities(const JabberBuddyResource *jbr);
-gboolean jabber_resource_has_capability(const JabberBuddyResource *jbr,
-										const gchar *cap);
-
-const gchar *
-jabber_resource_get_identity_category_type(const JabberBuddyResource *jbr,
-	const gchar *category);
-
-#endif /* PURPLE_JABBER_BUDDY_H */
diff --git a/libpurple/protocols/jabber/buddy.c b/libpurple/protocols/jabber/buddy.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/buddy.c
+++ /dev/null
@@ -1,1957 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "glibcompat.h"
-
-#include "buddy.h"
-#include "chat.h"
-#include "jabber.h"
-#include "iq.h"
-#include "presence.h"
-#include "useravatar.h"
-#include "xdata.h"
-#include "pep.h"
-#include "adhoccommands.h"
-
-typedef struct {
-	long idle_seconds;
-} JabberBuddyInfoResource;
-
-typedef struct {
-	JabberStream *js;
-	JabberBuddy *jb;
-	char *jid;
-	GSList *ids;
-	GHashTable *resources;
-	guint timeout_handle;
-	GSList *vcard_images;
-	PurpleNotifyUserInfo *user_info;
-	long last_seconds;
-	gchar *last_message;
-} JabberBuddyInfo;
-
-static void
-jabber_buddy_resource_free(JabberBuddyResource *jbr)
-{
-	g_return_if_fail(jbr != NULL);
-
-	g_list_free_full(jbr->commands, (GDestroyNotify)jabber_adhoc_commands_free);
-	g_free(jbr->name);
-	g_free(jbr->status);
-	g_free(jbr->thread_id);
-	g_free(jbr->client.name);
-	g_free(jbr->client.version);
-	g_free(jbr->client.os);
-	g_clear_pointer(&jbr->tz_off, g_time_zone_unref);
-	g_free(jbr);
-}
-
-void jabber_buddy_free(JabberBuddy *jb)
-{
-	g_return_if_fail(jb != NULL);
-
-	g_free(jb->error_msg);
-	g_list_free_full(jb->resources, (GDestroyNotify)jabber_buddy_resource_free);
-
-	g_free(jb);
-}
-
-JabberBuddy *jabber_buddy_find(JabberStream *js, const char *name,
-		gboolean create)
-{
-	JabberBuddy *jb;
-	char *realname;
-
-	if (js->buddies == NULL)
-		return NULL;
-
-	if(!(realname = jabber_get_bare_jid(name)))
-		return NULL;
-
-	jb = g_hash_table_lookup(js->buddies, realname);
-
-	if(!jb && create) {
-		jb = g_new0(JabberBuddy, 1);
-		g_hash_table_insert(js->buddies, realname, jb);
-	} else
-		g_free(realname);
-
-	return jb;
-}
-
-/* Returns -1 if a is a higher priority resource than b, or is
- * "more available" than b.  0 if they're the same, and 1 if b is
- * higher priority/more available than a.
- */
-static gint resource_compare_cb(gconstpointer a, gconstpointer b)
-{
-	const JabberBuddyResource *jbra = a;
-	const JabberBuddyResource *jbrb = b;
-	JabberBuddyState state_a, state_b;
-
-	if (jbra->priority != jbrb->priority)
-		return jbra->priority > jbrb->priority ? -1 : 1;
-
-	/* Fold the states for easier comparison */
-	/* TODO: Differentiate online/chat and away/dnd? */
-	switch (jbra->state) {
-		case JABBER_BUDDY_STATE_ONLINE:
-		case JABBER_BUDDY_STATE_CHAT:
-			state_a = JABBER_BUDDY_STATE_ONLINE;
-			break;
-		case JABBER_BUDDY_STATE_AWAY:
-		case JABBER_BUDDY_STATE_DND:
-			state_a = JABBER_BUDDY_STATE_AWAY;
-			break;
-		case JABBER_BUDDY_STATE_XA:
-			state_a = JABBER_BUDDY_STATE_XA;
-			break;
-		case JABBER_BUDDY_STATE_UNAVAILABLE:
-			state_a = JABBER_BUDDY_STATE_UNAVAILABLE;
-			break;
-		default:
-			state_a = JABBER_BUDDY_STATE_UNKNOWN;
-			break;
-	}
-
-	switch (jbrb->state) {
-		case JABBER_BUDDY_STATE_ONLINE:
-		case JABBER_BUDDY_STATE_CHAT:
-			state_b = JABBER_BUDDY_STATE_ONLINE;
-			break;
-		case JABBER_BUDDY_STATE_AWAY:
-		case JABBER_BUDDY_STATE_DND:
-			state_b = JABBER_BUDDY_STATE_AWAY;
-			break;
-		case JABBER_BUDDY_STATE_XA:
-			state_b = JABBER_BUDDY_STATE_XA;
-			break;
-		case JABBER_BUDDY_STATE_UNAVAILABLE:
-			state_b = JABBER_BUDDY_STATE_UNAVAILABLE;
-			break;
-		default:
-			state_b = JABBER_BUDDY_STATE_UNKNOWN;
-			break;
-	}
-
-	if (state_a == state_b) {
-		if (jbra->idle == jbrb->idle)
-			return 0;
-		else if ((jbra->idle && !jbrb->idle) ||
-				(jbra->idle && jbrb->idle && jbra->idle < jbrb->idle))
-			return 1;
-		else
-			return -1;
-	}
-
-	if (state_a == JABBER_BUDDY_STATE_ONLINE)
-		return -1;
-	else if (state_a == JABBER_BUDDY_STATE_AWAY &&
-				(state_b == JABBER_BUDDY_STATE_XA ||
-				 state_b == JABBER_BUDDY_STATE_UNAVAILABLE ||
-				 state_b == JABBER_BUDDY_STATE_UNKNOWN))
-		return -1;
-	else if (state_a == JABBER_BUDDY_STATE_XA &&
-				(state_b == JABBER_BUDDY_STATE_UNAVAILABLE ||
-				 state_b == JABBER_BUDDY_STATE_UNKNOWN))
-		return -1;
-	else if (state_a == JABBER_BUDDY_STATE_UNAVAILABLE &&
-				state_b == JABBER_BUDDY_STATE_UNKNOWN)
-		return -1;
-
-	return 1;
-}
-
-JabberBuddyResource *jabber_buddy_find_resource(JabberBuddy *jb,
-		const char *resource)
-{
-	GList *l;
-
-	if (!jb)
-		return NULL;
-
-	if (resource == NULL)
-		return jb->resources ? jb->resources->data : NULL;
-
-	for (l = jb->resources; l; l = l->next)
-	{
-		JabberBuddyResource *jbr = l->data;
-		if (purple_strequal(resource, jbr->name))
-			return jbr;
-	}
-
-	return NULL;
-}
-
-JabberBuddyResource *jabber_buddy_track_resource(JabberBuddy *jb, const char *resource,
-		int priority, JabberBuddyState state, const char *status)
-{
-	/* TODO: Optimization: Only reinsert if priority+state changed */
-	JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, resource);
-	if (jbr) {
-		jb->resources = g_list_remove(jb->resources, jbr);
-	} else {
-		jbr = g_new0(JabberBuddyResource, 1);
-		jbr->jb = jb;
-		jbr->name = g_strdup(resource);
-		jbr->capabilities = JABBER_CAP_NONE;
-	}
-	jbr->priority = priority;
-	jbr->state = state;
-	g_free(jbr->status);
-	jbr->status = g_strdup(status);
-
-	jb->resources = g_list_insert_sorted(jb->resources, jbr,
-	                                     resource_compare_cb);
-	return jbr;
-}
-
-void jabber_buddy_remove_resource(JabberBuddy *jb, const char *resource)
-{
-	JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, resource);
-
-	if(!jbr)
-		return;
-
-	jbr->jb->resources = g_list_remove(jbr->jb->resources, jbr);
-	jabber_buddy_resource_free(jbr);
-}
-
-/*******
- * This is the old vCard stuff taken from the old prpl.  vCards, by definition
- * are a temporary thing until jabber can get its act together and come up
- * with a format for user information, hence the namespace of 'vcard-temp'
- *
- * Since I don't feel like putting that much work into something that's
- * _supposed_ to go away, i'm going to just copy the kludgy old code here,
- * and make it purdy when jabber comes up with a standards-track JEP to
- * replace vcard-temp
- *                                 --Nathan
- *******/
-
-/*---------------------------------------*/
-/* Jabber "set info" (vCard) support     */
-/*---------------------------------------*/
-
-/*
- * V-Card format:
- *
- *  <vCard prodid='' version='' xmlns=''>
- *    <FN></FN>
- *    <N>
- *	<FAMILY/>
- *	<GIVEN/>
- *    </N>
- *    <NICKNAME/>
- *    <URL/>
- *    <ADR>
- *	<STREET/>
- *	<EXTADD/>
- *	<LOCALITY/>
- *	<REGION/>
- *	<PCODE/>
- *	<COUNTRY/>
- *    </ADR>
- *    <TEL/>
- *    <EMAIL/>
- *    <ORG>
- *	<ORGNAME/>
- *	<ORGUNIT/>
- *    </ORG>
- *    <TITLE/>
- *    <ROLE/>
- *    <DESC/>
- *    <BDAY/>
- *  </vCard>
- *
- * See also:
- *
- *	http://docs.jabber.org/proto/html/vcard-temp.html
- *	http://www.vcard-xml.org/dtd/vCard-XML-v2-20010520.dtd
- */
-
-/*
- * Cross-reference user-friendly V-Card entry labels to vCard XML tags
- * and attributes.
- *
- * Order is (or should be) unimportant.  For example: we have no way of
- * knowing in what order real data will arrive.
- *
- * Format: Label, Pre-set text, "visible" flag, "editable" flag, XML tag
- *         name, XML tag's parent tag "path" (relative to vCard node).
- *
- *         List is terminated by a NULL label pointer.
- *
- *	   Entries with no label text, but with XML tag and parent tag
- *	   entries, are used by V-Card XML construction routines to
- *	   "automagically" construct the appropriate XML node tree.
- *
- * Thoughts on future direction/expansion
- *
- *	This is a "simple" vCard.
- *
- *	It is possible for nodes other than the "vCard" node to have
- *      attributes.  Should that prove necessary/desirable, add an
- *      "attributes" pointer to the vcard_template struct, create the
- *      necessary tag_attr structs, and add 'em to the vcard_dflt_data
- *      array.
- *
- *	The above changes will (obviously) require changes to the vCard
- *      construction routines.
- */
-
-struct vcard_template {
-	char *label;			/* label text pointer */
-	char *tag;			/* tag text */
-	char *ptag;			/* parent tag "path" text */
-} const vcard_template_data[] = {
-	{N_("Full Name"),          "FN",        NULL},
-	{N_("Family Name"),        "FAMILY",    "N"},
-	{N_("Given Name"),         "GIVEN",     "N"},
-	{N_("Nickname"),           "NICKNAME",  NULL},
-	{N_("URL"),                "URL",       NULL},
-	{N_("Street Address"),     "STREET",    "ADR"},
-	{N_("Extended Address"),   "EXTADD",    "ADR"},
-	{N_("Locality"),           "LOCALITY",  "ADR"},
-	{N_("Region"),             "REGION",    "ADR"},
-	{N_("Postal Code"),        "PCODE",     "ADR"},
-	{N_("Country"),            "CTRY",      "ADR"},
-	{N_("Telephone"),          "NUMBER",    "TEL"},
-	{N_("Email"),              "USERID",    "EMAIL"},
-	{N_("Organization Name"),  "ORGNAME",   "ORG"},
-	{N_("Organization Unit"),  "ORGUNIT",   "ORG"},
-	{N_("Job Title"),          "TITLE",     NULL},
-	{N_("Role"),               "ROLE",      NULL},
-	{N_("Birthday"),           "BDAY",      NULL},
-	{N_("Description"),        "DESC",      NULL},
-	{"",                       "N",         NULL},
-	{"",                       "ADR",       NULL},
-	{"",                       "ORG",       NULL},
-	{NULL,                     NULL,        NULL}
-};
-
-/*
- * The "vCard" tag's attribute list...
- */
-struct tag_attr {
-	char *attr;
-	char *value;
-} const vcard_tag_attr_list[] = {
-	{"prodid",   "-//HandGen//NONSGML vGen v1.0//EN"},
-	{"version",  "2.0",                             },
-	{"xmlns",    "vcard-temp",                      },
-	{NULL, NULL},
-};
-
-
-/*
- * Insert a tag node into an PurpleXmlNode tree, recursively inserting parent tag
- * nodes as necessary
- *
- * Returns pointer to inserted node
- *
- * Note to hackers: this code is designed to be re-entrant (it's recursive--it
- * calls itself), so don't put any "static"s in here!
- */
-static PurpleXmlNode *insert_tag_to_parent_tag(PurpleXmlNode *start, const char *parent_tag, const char *new_tag)
-{
-	PurpleXmlNode *x = NULL;
-
-	/*
-	 * If the parent tag wasn't specified, see if we can get it
-	 * from the vCard template struct.
-	 */
-	if(parent_tag == NULL) {
-		const struct vcard_template *vc_tp = vcard_template_data;
-
-		while(vc_tp->label != NULL) {
-			if(purple_strequal(vc_tp->tag, new_tag)) {
-				parent_tag = vc_tp->ptag;
-				break;
-			}
-			++vc_tp;
-		}
-	}
-
-	/*
-	 * If we have a parent tag...
-	 */
-	if(parent_tag != NULL ) {
-		/*
-		 * Try to get the parent node for a tag
-		 */
-		if((x = purple_xmlnode_get_child(start, parent_tag)) == NULL) {
-			/*
-			 * Descend?
-			 */
-			char *grand_parent = g_strdup(parent_tag);
-			char *parent;
-
-			if((parent = strrchr(grand_parent, '/')) != NULL) {
-				*(parent++) = '\0';
-				x = insert_tag_to_parent_tag(start, grand_parent, parent);
-			} else {
-				x = purple_xmlnode_new_child(start, grand_parent);
-			}
-			g_free(grand_parent);
-		} else {
-			/*
-			 * We found *something* to be the parent node.
-			 * Note: may be the "root" node!
-			 */
-			PurpleXmlNode *y;
-			if((y = purple_xmlnode_get_child(x, new_tag)) != NULL) {
-				return(y);
-			}
-		}
-	}
-
-	/*
-	 * insert the new tag into its parent node
-	 */
-	return(purple_xmlnode_new_child((x == NULL? start : x), new_tag));
-}
-
-/*
- * Send vCard info to Jabber server
- */
-void
-jabber_set_info(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
-                PurpleConnection *gc, const char *info)
-{
-	PurpleImage *img;
-	JabberIq *iq;
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-	PurpleXmlNode *vc_node;
-	const struct tag_attr *tag_attr;
-
-	/* if we haven't grabbed the remote vcard yet, we can't
-	 * assume that what we have here is correct */
-	if(!js->vcard_fetched) {
-		PurpleImage *image;
-		g_free(js->initial_avatar_hash);
-		image = purple_buddy_icons_find_account_icon(purple_connection_get_account(gc));
-		if (image != NULL) {
-			js->initial_avatar_hash = g_compute_checksum_for_data(
-				G_CHECKSUM_SHA1,
-				purple_image_get_data(image),
-				purple_image_get_data_size(image)
-			);
-			g_object_unref(image);
-		} else {
-			js->initial_avatar_hash = NULL;
-		}
-		return;
-	}
-
-	g_free(js->avatar_hash);
-	js->avatar_hash = NULL;
-
-	/*
-	 * Send only if there's actually any *information* to send
-	 */
-	vc_node = info ? purple_xmlnode_from_str(info, -1) : NULL;
-
-	if (vc_node && (!vc_node->name ||
-			g_ascii_strncasecmp(vc_node->name, "vCard", 5))) {
-		purple_xmlnode_free(vc_node);
-		vc_node = NULL;
-	}
-
-	if ((img = purple_buddy_icons_find_account_icon(purple_connection_get_account(gc)))) {
-		gconstpointer avatar_data;
-		gsize avatar_len;
-		PurpleXmlNode *photo, *binval, *type;
-		gchar *enc;
-
-		if(!vc_node) {
-			vc_node = purple_xmlnode_new("vCard");
-			for(tag_attr = vcard_tag_attr_list; tag_attr->attr != NULL; ++tag_attr)
-				purple_xmlnode_set_attrib(vc_node, tag_attr->attr, tag_attr->value);
-		}
-
-		avatar_data = purple_image_get_data(img);
-		avatar_len = purple_image_get_data_size(img);
-		/* Get rid of an old PHOTO if one exists.
-		 * TODO: This may want to be modified to remove all old PHOTO
-		 * children, at the moment some people have managed to get
-		 * multiple PHOTO entries in their vCard. */
-		if((photo = purple_xmlnode_get_child(vc_node, "PHOTO"))) {
-			purple_xmlnode_free(photo);
-		}
-		photo = purple_xmlnode_new_child(vc_node, "PHOTO");
-		type = purple_xmlnode_new_child(photo, "TYPE");
-		purple_xmlnode_insert_data(type, "image/png", -1);
-		binval = purple_xmlnode_new_child(photo, "BINVAL");
-		enc = g_base64_encode(avatar_data, avatar_len);
-
-		js->avatar_hash = g_compute_checksum_for_data(G_CHECKSUM_SHA1,
-			avatar_data, avatar_len);
-
-		purple_xmlnode_insert_data(binval, enc, -1);
-		g_free(enc);
-		g_object_unref(img);
-	} else if (vc_node) {
-		PurpleXmlNode *photo;
-		/* TODO: Remove all PHOTO children? (see above note) */
-		if ((photo = purple_xmlnode_get_child(vc_node, "PHOTO"))) {
-			purple_xmlnode_free(photo);
-		}
-	}
-
-	if (vc_node != NULL) {
-		iq = jabber_iq_new(js, JABBER_IQ_SET);
-		purple_xmlnode_insert_child(iq->node, vc_node);
-		jabber_iq_send(iq);
-
-		/* Send presence to update vcard-temp:x:update */
-		jabber_presence_send(js, FALSE);
-	}
-}
-
-void
-jabber_set_buddy_icon(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
-                      PurpleConnection *gc, PurpleImage *img)
-{
-	PurpleAccount *account = purple_connection_get_account(gc);
-
-	/* Publish the avatar as specified in XEP-0084 */
-	jabber_avatar_set(purple_connection_get_protocol_data(gc), img);
-	/* Set the image in our vCard */
-	jabber_set_info(NULL, gc, purple_account_get_user_info(account));
-
-	/* TODO: Fake image to ourselves, since a number of servers do not echo
-	 * back our presence to us. To do this without uselessly copying the data
-	 * of the image, we need purple_buddy_icons_set_for_user_image (i.e. takes
-	 * an existing icon/stored image). */
-}
-
-/*
- * This is the callback from the "ok clicked" for "set vCard"
- *
- * Sets the vCard with data from PurpleRequestFields.
- */
-static void
-jabber_format_info(PurpleConnection *gc, PurpleRequestPage *page) {
-	PurpleXmlNode *vc_node;
-	PurpleProtocol *protocol = NULL;
-	const char *text;
-	char *p;
-	const struct vcard_template *vc_tp;
-	const struct tag_attr *tag_attr;
-
-	vc_node = purple_xmlnode_new("vCard");
-
-	for(tag_attr = vcard_tag_attr_list; tag_attr->attr != NULL; ++tag_attr)
-		purple_xmlnode_set_attrib(vc_node, tag_attr->attr, tag_attr->value);
-
-	for (vc_tp = vcard_template_data; vc_tp->label != NULL; vc_tp++) {
-		if (*vc_tp->label == '\0')
-			continue;
-
-		text = purple_request_page_get_string(page, vc_tp->tag);
-
-		if(!purple_strempty(text)) {
-			PurpleXmlNode *xp;
-
-			purple_debug_info("jabber", "Setting %s to '%s'\n", vc_tp->tag, text);
-
-			if ((xp = insert_tag_to_parent_tag(vc_node,
-											   NULL, vc_tp->tag)) != NULL) {
-
-				purple_xmlnode_insert_data(xp, text, -1);
-			}
-		}
-	}
-
-	p = purple_xmlnode_to_str(vc_node, NULL);
-	purple_xmlnode_free(vc_node);
-
-	purple_account_set_user_info(purple_connection_get_account(gc), p);
-	protocol = purple_connection_get_protocol(gc);
-	if(PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER, set_info)) {
-		purple_protocol_server_set_info(PURPLE_PROTOCOL_SERVER(protocol),
-		                                gc, p);
-	}
-
-	g_free(p);
-}
-
-/*
- * This gets executed as the protocol action.
- *
- * Creates a new PurpleRequestFields struct, gets the XML-formatted user_info
- * string (if any) into GSLists for the (multi-entry) edit dialog and
- * calls the set_vcard dialog.
- */
-void
-jabber_setup_set_info(G_GNUC_UNUSED GSimpleAction *action, GVariant *parameter,
-                      G_GNUC_UNUSED gpointer data)
-{
-	const char *account_id = NULL;
-	PurpleAccountManager *manager = NULL;
-	PurpleAccount *account = NULL;
-	PurpleConnection *connection = NULL;
-	PurpleRequestPage *page;
-	PurpleRequestGroup *group;
-	PurpleRequestField *field;
-	const struct vcard_template *vc_tp;
-	const char *user_info;
-	char *cdata = NULL;
-	PurpleXmlNode *x_vc_data = NULL;
-
-	if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) {
-		g_critical("XMPP Set Info action parameter is of incorrect type %s",
-		           g_variant_get_type_string(parameter));
-	}
-
-	account_id = g_variant_get_string(parameter, NULL);
-	manager = purple_account_manager_get_default();
-	account = purple_account_manager_find_by_id(manager, account_id);
-	connection = purple_account_get_connection(account);
-
-	page = purple_request_page_new();
-	group = purple_request_group_new(NULL);
-	purple_request_page_add_group(page, group);
-
-	/*
-	 * Get existing, XML-formatted, user info
-	 */
-	if((user_info = purple_account_get_user_info(account)) != NULL) {
-		x_vc_data = purple_xmlnode_from_str(user_info, -1);
-	}
-
-	/*
-	 * Set up GSLists for edit with labels from "template," data from user info
-	 */
-	for(vc_tp = vcard_template_data; vc_tp->label != NULL; ++vc_tp) {
-		PurpleXmlNode *data_node;
-		if((vc_tp->label)[0] == '\0')
-			continue;
-
-		if (x_vc_data != NULL) {
-			if(vc_tp->ptag == NULL) {
-				data_node = purple_xmlnode_get_child(x_vc_data, vc_tp->tag);
-			} else {
-				gchar *tag = g_strdup_printf("%s/%s", vc_tp->ptag, vc_tp->tag);
-				data_node = purple_xmlnode_get_child(x_vc_data, tag);
-				g_free(tag);
-			}
-			if(data_node)
-				cdata = purple_xmlnode_get_data(data_node);
-		}
-
-		if(purple_strequal(vc_tp->tag, "DESC")) {
-			field = purple_request_field_string_new(vc_tp->tag,
-												  _(vc_tp->label), cdata,
-												  TRUE);
-		} else {
-			field = purple_request_field_string_new(vc_tp->tag,
-												  _(vc_tp->label), cdata,
-												  FALSE);
-		}
-
-		g_free(cdata);
-		cdata = NULL;
-
-		purple_request_group_add_field(group, field);
-	}
-
-	if(x_vc_data != NULL)
-		purple_xmlnode_free(x_vc_data);
-
-	purple_request_fields(connection, _("Edit XMPP vCard"),
-	                      _("Edit XMPP vCard"),
-	                      _("All items below are optional. Enter only the "
-	                        "information with which you feel comfortable."),
-	                      page,
-	                      _("Save"), G_CALLBACK(jabber_format_info),
-	                      _("Cancel"), NULL,
-	                      purple_request_cpar_from_connection(connection),
-	                      connection);
-
-	g_clear_object(&account);
-}
-
-/*---------------------------------------*/
-/* End Jabber "set info" (vCard) support */
-/*---------------------------------------*/
-
-/******
- * end of that ancient crap that needs to die
- ******/
-
-static void jabber_buddy_info_destroy(JabberBuddyInfo *jbi)
-{
-	/* Remove the timeout, which would otherwise trigger jabber_buddy_get_info_timeout() */
-	g_clear_handle_id(&jbi->timeout_handle, g_source_remove);
-
-	g_slist_free(jbi->ids);
-	g_free(jbi->jid);
-	g_hash_table_destroy(jbi->resources);
-	g_free(jbi->last_message);
-	purple_notify_user_info_destroy(jbi->user_info);
-	g_free(jbi);
-}
-
-static void
-add_jbr_info(JabberBuddyInfo *jbi, const char *resource,
-             JabberBuddyResource *jbr)
-{
-	JabberBuddyInfoResource *jbir;
-	PurpleNotifyUserInfo *user_info;
-
-	jbir = g_hash_table_lookup(jbi->resources, resource);
-	user_info = jbi->user_info;
-
-	if (jbr && jbr->client.name) {
-		char *tmp =
-			g_strdup_printf("%s%s%s", jbr->client.name,
-		                    (jbr->client.version ? " " : ""),
-		                    (jbr->client.version ? jbr->client.version : ""));
-		/* TODO: Check whether it's correct to call prepend_pair_html,
-		         or if we should be using prepend_pair_plaintext */
-		purple_notify_user_info_prepend_pair_html(user_info, _("Client"), tmp);
-		g_free(tmp);
-
-		if (jbr->client.os) {
-			/* TODO: Check whether it's correct to call prepend_pair_html,
-			         or if we should be using prepend_pair_plaintext */
-			purple_notify_user_info_prepend_pair_html(user_info, _("Operating System"), jbr->client.os);
-		}
-	}
-
-	if (jbr && jbr->tz_off != NULL) {
-		GDateTime *dt = NULL;
-		char *timestamp = NULL;
-
-		dt = g_date_time_new_now(jbr->tz_off);
-
-		timestamp = g_date_time_format(dt, "%X %:z");
-		g_date_time_unref(dt);
-
-		purple_notify_user_info_prepend_pair_plaintext(user_info, _("Local Time"), timestamp);
-		g_free(timestamp);
-	}
-
-	if (jbir && jbir->idle_seconds > 0) {
-		char *idle = purple_str_seconds_to_string(jbir->idle_seconds);
-		purple_notify_user_info_prepend_pair_plaintext(user_info, _("Idle"), idle);
-		g_free(idle);
-	}
-
-	if (jbr) {
-		char *purdy = NULL;
-		char *tmp;
-		char priority[12];
-		const char *status_name = jabber_buddy_state_get_name(jbr->state);
-
-		if (jbr->status) {
-			tmp = g_markup_escape_text(jbr->status, -1);
-			purdy = purple_strdup_withhtml(tmp);
-			g_free(tmp);
-
-			if (purple_strequal(status_name, purdy))
-				status_name = NULL;
-		}
-
-		tmp = g_strdup_printf("%s%s%s", (status_name ? status_name : ""),
-						((status_name && purdy) ? ": " : ""),
-						(purdy ? purdy : ""));
-		purple_notify_user_info_prepend_pair_html(user_info, _("Status"), tmp);
-
-		g_snprintf(priority, sizeof(priority), "%d", jbr->priority);
-		purple_notify_user_info_prepend_pair_plaintext(user_info, _("Priority"), priority);
-
-		g_free(tmp);
-		g_free(purdy);
-	} else {
-		purple_notify_user_info_prepend_pair_plaintext(user_info, _("Status"), _("Unknown"));
-	}
-}
-
-static void jabber_buddy_info_show_if_ready(JabberBuddyInfo *jbi)
-{
-	char *resource_name;
-	JabberBuddyResource *jbr;
-	GList *resources;
-	PurpleNotifyUserInfo *user_info;
-
-	/* not yet */
-	if (jbi->ids)
-		return;
-
-	user_info = jbi->user_info;
-	resource_name = jabber_get_resource(jbi->jid);
-
-	/* If we have one or more pairs from the vcard, put a section break above it */
-	if (g_queue_get_length(purple_notify_user_info_get_entries(user_info)))
-		purple_notify_user_info_prepend_section_break(user_info);
-
-	/* Add the information about the user's resource(s) */
-	if (resource_name) {
-		jbr = jabber_buddy_find_resource(jbi->jb, resource_name);
-		add_jbr_info(jbi, resource_name, jbr);
-	} else {
-		/* TODO: This is in priority-ascending order (lowest prio first), because
-		 * everything is prepended.  Is that ok? */
-		for (resources = jbi->jb->resources; resources; resources = resources->next) {
-			jbr = resources->data;
-
-			/* put a section break between resources, this is not needed if
-			 we are at the first, because one was already added for the vcard
-			 section */
-			if (resources != jbi->jb->resources)
-				purple_notify_user_info_prepend_section_break(user_info);
-
-			add_jbr_info(jbi, jbr->name, jbr);
-
-			if (jbr->name) {
-				/* TODO: Check whether it's correct to call prepend_pair_html,
-				         or if we should be using prepend_pair_plaintext */
-				purple_notify_user_info_prepend_pair_html(user_info, _("Resource"), jbr->name);
-			}
-		}
-	}
-
-	if (!jbi->jb->resources) {
-		/* the buddy is offline */
-		gboolean is_domain = jabber_jid_is_domain(jbi->jid);
-
-		if (jbi->last_seconds > 0) {
-			char *last = purple_str_seconds_to_string(jbi->last_seconds);
-			gchar *message = NULL;
-			const gchar *title = NULL;
-			if (is_domain) {
-				title = _("Uptime");
-				message = last;
-				last = NULL;
-			} else {
-				title = _("Logged Off");
-				message = g_strdup_printf(_("%s ago"), last);
-			}
-			purple_notify_user_info_prepend_pair_plaintext(user_info, title, message);
-			g_free(last);
-			g_free(message);
-		}
-
-		if (!is_domain) {
-			gchar *status =
-				g_strdup_printf("%s%s%s",	_("Offline"),
-				                jbi->last_message ? ": " : "",
-				                jbi->last_message ? jbi->last_message : "");
-			/* TODO: Check whether it's correct to call prepend_pair_html,
-			         or if we should be using prepend_pair_plaintext */
-			purple_notify_user_info_prepend_pair_html(user_info, _("Status"), status);
-			g_free(status);
-		}
-	}
-
-	g_free(resource_name);
-
-	purple_notify_userinfo(jbi->js->gc, jbi->jid, user_info, NULL, NULL);
-
-	g_slist_free_full(jbi->vcard_images, g_object_unref);
-
-	jbi->js->pending_buddy_info_requests = g_slist_remove(jbi->js->pending_buddy_info_requests, jbi);
-
-	jabber_buddy_info_destroy(jbi);
-}
-
-static void jabber_buddy_info_remove_id(JabberBuddyInfo *jbi, const char *id)
-{
-	GSList *l;
-	char *comp_id;
-
-	if(!id)
-		return;
-
-	l = g_slist_find_custom(jbi->ids, id, (GCompareFunc)g_strcmp0);
-	if(l) {
-		comp_id = l->data;
-		jbi->ids = g_slist_delete_link(jbi->ids, l);
-		g_free(comp_id);
-	}
-}
-
-static void
-jabber_vcard_save_mine(JabberStream *js, G_GNUC_UNUSED const char *from,
-                       JabberIqType type, G_GNUC_UNUSED const char *id,
-                       PurpleXmlNode *packet, G_GNUC_UNUSED gpointer data)
-{
-	PurpleXmlNode *vcard, *photo, *binval;
-	char *txt, *vcard_hash = NULL;
-	PurpleAccount *account;
-
-	if (type == JABBER_IQ_ERROR) {
-		PurpleXmlNode *error;
-		purple_debug_warning("jabber", "Server returned error while retrieving vCard\n");
-
-		error = purple_xmlnode_get_child(packet, "error");
-		if (!error || !purple_xmlnode_get_child(error, "item-not-found"))
-			return;
-	}
-
-	account = purple_connection_get_account(js->gc);
-
-	if((vcard = purple_xmlnode_get_child(packet, "vCard")) ||
-			(vcard = purple_xmlnode_get_child_with_namespace(packet, "query", "vcard-temp")))
-	{
-		txt = purple_xmlnode_to_str(vcard, NULL);
-		purple_account_set_user_info(account, txt);
-		g_free(txt);
-	} else {
-		/* if we have no vCard, then lets not overwrite what we might have locally */
-	}
-
-	js->vcard_fetched = TRUE;
-
-	if (vcard && (photo = purple_xmlnode_get_child(vcard, "PHOTO")) &&
-	             (binval = purple_xmlnode_get_child(photo, "BINVAL"))) {
-		gsize size;
-		char *bintext = purple_xmlnode_get_data(binval);
-		if (bintext) {
-			guchar *data = g_base64_decode(bintext, &size);
-			g_free(bintext);
-
-			if (data) {
-				vcard_hash = g_compute_checksum_for_data(
-					G_CHECKSUM_SHA1, data, size);
-				g_free(data);
-			}
-		}
-	}
-
-	/* Republish our vcard if the photo is different than the server's */
-	if (js->initial_avatar_hash && !purple_strequal(vcard_hash, js->initial_avatar_hash)) {
-		jabber_set_info(NULL, js->gc, purple_account_get_user_info(account));
-	} else if (vcard_hash) {
-		/* A photo is in the vCard. Advertise its hash */
-		js->avatar_hash = vcard_hash;
-		vcard_hash = NULL;
-
-		/* Send presence to update vcard-temp:x:update */
-		jabber_presence_send(js, FALSE);
-	}
-
-	g_free(vcard_hash);
-}
-
-void jabber_vcard_fetch_mine(JabberStream *js)
-{
-	JabberIq *iq = jabber_iq_new(js, JABBER_IQ_GET);
-
-	PurpleXmlNode *vcard = purple_xmlnode_new_child(iq->node, "vCard");
-	purple_xmlnode_set_namespace(vcard, "vcard-temp");
-	jabber_iq_set_callback(iq, jabber_vcard_save_mine, NULL);
-
-	jabber_iq_send(iq);
-}
-
-static void jabber_vcard_parse(JabberStream *js, const char *from,
-                               JabberIqType type, const char *id,
-                               PurpleXmlNode *packet, gpointer data)
-{
-	char *bare_jid;
-	char *text;
-	char *serverside_alias = NULL;
-	PurpleXmlNode *vcard;
-	PurpleAccount *account;
-	JabberBuddyInfo *jbi = data;
-	PurpleNotifyUserInfo *user_info;
-
-	g_return_if_fail(jbi != NULL);
-
-	jabber_buddy_info_remove_id(jbi, id);
-
-	if (type == JABBER_IQ_ERROR) {
-		purple_debug_info("jabber", "Got error response for vCard\n");
-		jabber_buddy_info_show_if_ready(jbi);
-		return;
-	}
-
-	user_info = jbi->user_info;
-	account = purple_connection_get_account(js->gc);
-
-	if(from == NULL) {
-		from = purple_contact_info_get_username(PURPLE_CONTACT_INFO(account));
-	}
-	bare_jid = jabber_get_bare_jid(from);
-
-	/* TODO: Is the query xmlns='vcard-temp' version of this still necessary? */
-	if((vcard = purple_xmlnode_get_child(packet, "vCard")) ||
-			(vcard = purple_xmlnode_get_child_with_namespace(packet, "query", "vcard-temp"))) {
-		PurpleXmlNode *child;
-		for(child = vcard->child; child; child = child->next)
-		{
-			PurpleXmlNode *child2;
-
-			if(child->type != PURPLE_XMLNODE_TYPE_TAG)
-				continue;
-
-			text = purple_xmlnode_get_data(child);
-			if(text && purple_strequal(child->name, "FN")) {
-				if (!serverside_alias)
-					serverside_alias = g_strdup(text);
-
-				purple_notify_user_info_add_pair_plaintext(user_info, _("Full Name"), text);
-			} else if(purple_strequal(child->name, "N")) {
-				for(child2 = child->child; child2; child2 = child2->next)
-				{
-					char *text2;
-
-					if(child2->type != PURPLE_XMLNODE_TYPE_TAG)
-						continue;
-
-					text2 = purple_xmlnode_get_data(child2);
-					if(text2 && purple_strequal(child2->name, "FAMILY")) {
-						purple_notify_user_info_add_pair_plaintext(user_info, _("Family Name"), text2);
-					} else if(text2 && purple_strequal(child2->name, "GIVEN")) {
-						purple_notify_user_info_add_pair_plaintext(user_info, _("Given Name"), text2);
-					} else if(text2 && purple_strequal(child2->name, "MIDDLE")) {
-						purple_notify_user_info_add_pair_plaintext(user_info, _("Middle Name"), text2);
-					}
-					g_free(text2);
-				}
-			} else if(text && purple_strequal(child->name, "NICKNAME")) {
-				/* Prefer the Nickcname to the Full Name as the serverside alias if it's not just part of the jid.
-				 * Ignore it if it's part of the jid. */
-				if (strstr(bare_jid, text) == NULL) {
-					g_free(serverside_alias);
-					serverside_alias = g_strdup(text);
-
-					purple_notify_user_info_add_pair_plaintext(user_info, _("Nickname"), text);
-				}
-			} else if(text && purple_strequal(child->name, "BDAY")) {
-				purple_notify_user_info_add_pair_plaintext(user_info, _("Birthday"), text);
-			} else if(purple_strequal(child->name, "ADR")) {
-				gboolean address_line_added = FALSE;
-
-				for(child2 = child->child; child2; child2 = child2->next)
-				{
-					char *text2;
-
-					if(child2->type != PURPLE_XMLNODE_TYPE_TAG)
-						continue;
-
-					text2 = purple_xmlnode_get_data(child2);
-					if (text2 == NULL)
-						continue;
-
-					/* We do this here so that it's not added if all the child
-					 * elements are empty. */
-					if (!address_line_added)
-					{
-						purple_notify_user_info_add_section_header(user_info, _("Address"));
-						address_line_added = TRUE;
-					}
-
-					if(purple_strequal(child2->name, "POBOX")) {
-						purple_notify_user_info_add_pair_plaintext(user_info, _("P.O. Box"), text2);
-					} else if (purple_strequal(child2->name, "EXTADD") || purple_strequal(child2->name, "EXTADR")) {
-						/*
-						 * EXTADD is correct, EXTADR is generated by other
-						 * clients. The next time someone reads this, remove
-						 * EXTADR.
-						 */
-						purple_notify_user_info_add_pair_plaintext(user_info, _("Extended Address"), text2);
-					} else if(purple_strequal(child2->name, "STREET")) {
-						purple_notify_user_info_add_pair_plaintext(user_info, _("Street Address"), text2);
-					} else if(purple_strequal(child2->name, "LOCALITY")) {
-						purple_notify_user_info_add_pair_plaintext(user_info, _("Locality"), text2);
-					} else if(purple_strequal(child2->name, "REGION")) {
-						purple_notify_user_info_add_pair_plaintext(user_info, _("Region"), text2);
-					} else if(purple_strequal(child2->name, "PCODE")) {
-						purple_notify_user_info_add_pair_plaintext(user_info, _("Postal Code"), text2);
-					} else if(purple_strequal(child2->name, "CTRY")
-								|| purple_strequal(child2->name, "COUNTRY")) {
-						purple_notify_user_info_add_pair_plaintext(user_info, _("Country"), text2);
-					}
-					g_free(text2);
-				}
-
-				if (address_line_added)
-					purple_notify_user_info_add_section_break(user_info);
-
-			} else if(purple_strequal(child->name, "TEL")) {
-				char *number;
-				if((child2 = purple_xmlnode_get_child(child, "NUMBER"))) {
-					/* show what kind of number it is */
-					number = purple_xmlnode_get_data(child2);
-					if(number) {
-						purple_notify_user_info_add_pair_plaintext(user_info, _("Telephone"), number);
-						g_free(number);
-					}
-				} else if((number = purple_xmlnode_get_data(child))) {
-					/* lots of clients (including purple) do this, but it's
-					 * out of spec */
-					purple_notify_user_info_add_pair_plaintext(user_info, _("Telephone"), number);
-					g_free(number);
-				}
-			} else if(purple_strequal(child->name, "EMAIL")) {
-				char *userid, *escaped;
-				if((child2 = purple_xmlnode_get_child(child, "USERID"))) {
-					/* show what kind of email it is */
-					userid = purple_xmlnode_get_data(child2);
-					if(userid) {
-						char *mailto;
-						escaped = g_markup_escape_text(userid, -1);
-						mailto = g_strdup_printf("<a href=\"mailto:%s\">%s</a>", escaped, escaped);
-						purple_notify_user_info_add_pair_html(user_info, _("Email"), mailto);
-
-						g_free(mailto);
-						g_free(escaped);
-						g_free(userid);
-					}
-				} else if((userid = purple_xmlnode_get_data(child))) {
-					/* lots of clients (including purple) do this, but it's
-					 * out of spec */
-					char *mailto;
-
-					escaped = g_markup_escape_text(userid, -1);
-					mailto = g_strdup_printf("<a href=\"mailto:%s\">%s</a>", escaped, escaped);
-					purple_notify_user_info_add_pair_html(user_info, _("Email"), mailto);
-
-					g_free(mailto);
-					g_free(escaped);
-					g_free(userid);
-				}
-			} else if(purple_strequal(child->name, "ORG")) {
-				for(child2 = child->child; child2; child2 = child2->next)
-				{
-					char *text2;
-
-					if(child2->type != PURPLE_XMLNODE_TYPE_TAG)
-						continue;
-
-					text2 = purple_xmlnode_get_data(child2);
-					if(text2 && purple_strequal(child2->name, "ORGNAME")) {
-						purple_notify_user_info_add_pair_plaintext(user_info, _("Organization Name"), text2);
-					} else if(text2 && purple_strequal(child2->name, "ORGUNIT")) {
-						purple_notify_user_info_add_pair_plaintext(user_info, _("Organization Unit"), text2);
-					}
-					g_free(text2);
-				}
-			} else if(text && purple_strequal(child->name, "TITLE")) {
-				purple_notify_user_info_add_pair_plaintext(user_info, _("Job Title"), text);
-			} else if(text && purple_strequal(child->name, "ROLE")) {
-				purple_notify_user_info_add_pair_plaintext(user_info, _("Role"), text);
-			} else if(text && purple_strequal(child->name, "DESC")) {
-				purple_notify_user_info_add_pair_plaintext(user_info, _("Description"), text);
-			} else if(purple_strequal(child->name, "PHOTO") ||
-					purple_strequal(child->name, "LOGO")) {
-				char *bintext = NULL;
-				PurpleXmlNode *binval;
-
-				if ((binval = purple_xmlnode_get_child(child, "BINVAL")) &&
-						(bintext = purple_xmlnode_get_data(binval))) {
-					gsize size;
-					guchar *data;
-					gboolean photo = purple_strequal(child->name, "PHOTO");
-
-					data = g_base64_decode(bintext, &size);
-					if (data) {
-						PurpleImage *img;
-						guint img_id;
-						char *img_text;
-						char *hash;
-
-						img = purple_image_new_from_data(data, size);
-						img_id = purple_image_store_add(img);
-
-						jbi->vcard_images = g_slist_prepend(jbi->vcard_images, img);
-						img_text = g_strdup_printf("<img src='"
-							PURPLE_IMAGE_STORE_PROTOCOL "%u'>", img_id);
-
-						purple_notify_user_info_add_pair_html(user_info, (photo ? _("Photo") : _("Logo")), img_text);
-
-						hash = g_compute_checksum_for_data(G_CHECKSUM_SHA1, data, size);
-						purple_buddy_icons_set_for_user(account, bare_jid, data, size, hash);
-						g_free(hash);
-						g_free(img_text);
-					}
-					g_free(bintext);
-				}
-			}
-			g_free(text);
-		}
-	}
-
-	if (serverside_alias) {
-		PurpleBuddy *b;
-		/* If we found a serverside alias, set it and tell the core */
-		purple_serv_got_alias(js->gc, bare_jid, serverside_alias);
-		b = purple_blist_find_buddy(account, bare_jid);
-		if (b) {
-			purple_blist_node_set_string((PurpleBlistNode*)b, "servernick", serverside_alias);
-		}
-
-		g_free(serverside_alias);
-	}
-
-	g_free(bare_jid);
-
-	jabber_buddy_info_show_if_ready(jbi);
-}
-
-static void jabber_buddy_info_resource_free(gpointer data)
-{
-	JabberBuddyInfoResource *jbri = data;
-	g_free(jbri);
-}
-
-static guint jbir_hash(gconstpointer v)
-{
-	if (v)
-		return g_str_hash(v);
-	else
-		return 0;
-}
-
-static gboolean jbir_equal(gconstpointer v1, gconstpointer v2)
-{
-	const gchar *resource_1 = v1;
-	const gchar *resource_2 = v2;
-
-	return purple_strequal(resource_1, resource_2);
-}
-
-static void
-jabber_version_parse(G_GNUC_UNUSED JabberStream *js, const char *from,
-                     JabberIqType type, const char *id, PurpleXmlNode *packet,
-                     gpointer data)
-{
-	JabberBuddyInfo *jbi = data;
-	PurpleXmlNode *query;
-	char *resource_name;
-
-	g_return_if_fail(jbi != NULL);
-
-	jabber_buddy_info_remove_id(jbi, id);
-
-	if(!from)
-		return;
-
-	resource_name = jabber_get_resource(from);
-
-	if(resource_name) {
-		if (type == JABBER_IQ_RESULT) {
-			if((query = purple_xmlnode_get_child(packet, "query"))) {
-				JabberBuddyResource *jbr = jabber_buddy_find_resource(jbi->jb, resource_name);
-				if(jbr) {
-					PurpleXmlNode *node;
-					if((node = purple_xmlnode_get_child(query, "name"))) {
-						jbr->client.name = purple_xmlnode_get_data(node);
-					}
-					if((node = purple_xmlnode_get_child(query, "version"))) {
-						jbr->client.version = purple_xmlnode_get_data(node);
-					}
-					if((node = purple_xmlnode_get_child(query, "os"))) {
-						jbr->client.os = purple_xmlnode_get_data(node);
-					}
-				}
-			}
-		}
-		g_free(resource_name);
-	}
-
-	jabber_buddy_info_show_if_ready(jbi);
-}
-
-static void jabber_last_parse(JabberStream *js, const char *from,
-                              JabberIqType type, const char *id,
-                              PurpleXmlNode *packet, gpointer data)
-{
-	JabberBuddyInfo *jbi = data;
-	PurpleXmlNode *query;
-	char *resource_name;
-	const char *seconds;
-
-	g_return_if_fail(jbi != NULL);
-
-	jabber_buddy_info_remove_id(jbi, id);
-
-	if(!from)
-		return;
-
-	resource_name = jabber_get_resource(from);
-
-	if(resource_name) {
-		if (type == JABBER_IQ_RESULT) {
-			if((query = purple_xmlnode_get_child(packet, "query"))) {
-				seconds = purple_xmlnode_get_attrib(query, "seconds");
-				if(seconds) {
-					char *end = NULL;
-					long sec = strtol(seconds, &end, 10);
-					JabberBuddy *jb = NULL;
-					char *resource = NULL;
-					char *buddy_name = NULL;
-					JabberBuddyResource *jbr = NULL;
-
-					if(end != seconds) {
-						JabberBuddyInfoResource *jbir = g_hash_table_lookup(jbi->resources, resource_name);
-						if(jbir) {
-							jbir->idle_seconds = sec;
-						}
-					}
-					/* Update the idle time of the buddy resource, if we got it.
-					 This will correct the value when a server doesn't mark
-					 delayed presence and we got the presence when signing on */
-					jb = jabber_buddy_find(js, from, FALSE);
-					if (jb) {
-						resource = jabber_get_resource(from);
-						buddy_name = jabber_get_bare_jid(from);
-						/* if the resource already has an idle time set, we
-						 must have gotten it originally from a presence. In
-						 this case we update it. Otherwise don't update it, to
-						 avoid setting an idle and not getting informed about
-						 the resource getting unidle */
-						if (resource && buddy_name) {
-							jbr = jabber_buddy_find_resource(jb, resource);
-							if (jbr) {
-								if (jbr->idle) {
-									if (sec) {
-										jbr->idle = time(NULL) - sec;
-									} else {
-										jbr->idle = 0;
-									}
-
-									if (jbr ==
-										jabber_buddy_find_resource(jb, NULL)) {
-										purple_protocol_got_user_idle(purple_connection_get_account(js->gc),
-											buddy_name, jbr->idle, jbr->idle);
-									}
-								}
-							}
-						}
-						g_free(resource);
-						g_free(buddy_name);
-					}
-				}
-			}
-		}
-		g_free(resource_name);
-	}
-
-	jabber_buddy_info_show_if_ready(jbi);
-}
-
-static void
-jabber_last_offline_parse(G_GNUC_UNUSED JabberStream *js,
-                          G_GNUC_UNUSED const char *from, JabberIqType type,
-                          const char *id, PurpleXmlNode *packet, gpointer data)
-{
-	JabberBuddyInfo *jbi = data;
-	PurpleXmlNode *query;
-	const char *seconds;
-
-	g_return_if_fail(jbi != NULL);
-
-	jabber_buddy_info_remove_id(jbi, id);
-
-	if (type == JABBER_IQ_RESULT) {
-		if((query = purple_xmlnode_get_child(packet, "query"))) {
-			seconds = purple_xmlnode_get_attrib(query, "seconds");
-			if(seconds) {
-				char *end = NULL;
-				long sec = strtol(seconds, &end, 10);
-				if(end != seconds) {
-					jbi->last_seconds = sec;
-				}
-			}
-			jbi->last_message = purple_xmlnode_get_data(query);
-		}
-	}
-
-	jabber_buddy_info_show_if_ready(jbi);
-}
-
-static void
-jabber_time_parse(G_GNUC_UNUSED JabberStream *js, const char *from,
-                  JabberIqType type, const char *id, PurpleXmlNode *packet,
-                  gpointer data)
-{
-	JabberBuddyInfo *jbi = data;
-	JabberBuddyResource *jbr;
-	char *resource_name;
-
-	g_return_if_fail(jbi != NULL);
-
-	jabber_buddy_info_remove_id(jbi, id);
-
-	if (!from)
-		return;
-
-	resource_name = jabber_get_resource(from);
-	jbr = resource_name ? jabber_buddy_find_resource(jbi->jb, resource_name) : NULL;
-	g_free(resource_name);
-	if (jbr) {
-		if (type == JABBER_IQ_RESULT) {
-			PurpleXmlNode *time = purple_xmlnode_get_child(packet, "time");
-			PurpleXmlNode *tzo = time ? purple_xmlnode_get_child(time, "tzo") : NULL;
-			char *tzo_data = tzo ? purple_xmlnode_get_data(tzo) : NULL;
-			if (tzo_data) {
-				char *c = tzo_data;
-				int hours, minutes;
-				if (tzo_data[0] == 'Z' && tzo_data[1] == '\0') {
-					jbr->tz_off = g_time_zone_new_offset(0);
-				} else {
-					gboolean offset_positive = (tzo_data[0] == '+');
-					/* [+-]HH:MM */
-					if (((*c == '+' || *c == '-') && (c = c + 1)) &&
-							sscanf(c, "%02d:%02d", &hours, &minutes) == 2)
-					{
-						gint32 tz_off = 60*60*hours + 60*minutes;
-						if (!offset_positive) {
-							tz_off *= -1;
-						}
-
-						jbr->tz_off = g_time_zone_new_offset(tz_off);
-
-					} else {
-						purple_debug_info("jabber", "Ignoring malformed timezone %s",
-						                  tzo_data);
-					}
-				}
-
-				g_free(tzo_data);
-			}
-		}
-	}
-
-	jabber_buddy_info_show_if_ready(jbi);
-}
-
-void jabber_buddy_remove_all_pending_buddy_info_requests(JabberStream *js)
-{
-	g_clear_slist(&js->pending_buddy_info_requests,
-	              (GDestroyNotify)jabber_buddy_info_destroy);
-}
-
-static gboolean jabber_buddy_get_info_timeout(gpointer data)
-{
-	JabberBuddyInfo *jbi = data;
-
-	/* remove the pending callbacks */
-	while(jbi->ids) {
-		char *id = jbi->ids->data;
-		jabber_iq_remove_callback_by_id(jbi->js, id);
-		jbi->ids = g_slist_delete_link(jbi->ids, jbi->ids);
-		g_free(id);
-	}
-
-	jbi->js->pending_buddy_info_requests = g_slist_remove(jbi->js->pending_buddy_info_requests, jbi);
-	jbi->timeout_handle = 0;
-
-	jabber_buddy_info_show_if_ready(jbi);
-
-	return FALSE;
-}
-
-static gboolean _client_is_blacklisted(JabberBuddyResource *jbr, const char *ns)
-{
-	/* can't be blacklisted if we don't know what you're running yet */
-	if(!jbr->client.name)
-		return FALSE;
-
-	if(purple_strequal(ns, NS_LAST_ACTIVITY)) {
-		if(purple_strequal(jbr->client.name, "Trillian")) {
-			/* verified by nwalp 2007/05/09 */
-			if(purple_strequal(jbr->client.version, "3.1.0.121") ||
-					/* verified by nwalp 2007/09/19 */
-					purple_strequal(jbr->client.version, "3.1.7.0")) {
-				return TRUE;
-			}
-		}
-	}
-
-	return FALSE;
-}
-
-static void
-dispatch_queries_for_resource(JabberStream *js, JabberBuddyInfo *jbi,
-                              gboolean is_bare_jid, const char *jid,
-                              JabberBuddyResource *jbr)
-{
-	JabberIq *iq;
-	JabberBuddyInfoResource *jbir;
-	char *full_jid = NULL;
-	const char *to;
-
-	if (is_bare_jid && jbr->name) {
-		full_jid = g_strdup_printf("%s/%s", jid, jbr->name);
-		to = full_jid;
-	} else
-		to = jid;
-
-	jbir = g_new0(JabberBuddyInfoResource, 1);
-	g_hash_table_insert(jbi->resources, g_strdup(jbr->name), jbir);
-
-	if(!jbr->client.name) {
-		iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:version");
-		purple_xmlnode_set_attrib(iq->node, "to", to);
-		jabber_iq_set_callback(iq, jabber_version_parse, jbi);
-		jbi->ids = g_slist_prepend(jbi->ids, g_strdup(iq->id));
-		jabber_iq_send(iq);
-	}
-
-	/* this is to fix the feeling of irritation I get when trying
-	 * to get info on a friend running Trillian, which doesn't
-	 * respond (with an error or otherwise) to jabber:iq:last
-	 * requests.  There are a number of Trillian users in my
-	 * office. */
-	if(!_client_is_blacklisted(jbr, NS_LAST_ACTIVITY)) {
-		iq = jabber_iq_new_query(js, JABBER_IQ_GET, NS_LAST_ACTIVITY);
-		purple_xmlnode_set_attrib(iq->node, "to", to);
-		jabber_iq_set_callback(iq, jabber_last_parse, jbi);
-		jbi->ids = g_slist_prepend(jbi->ids, g_strdup(iq->id));
-		jabber_iq_send(iq);
-	}
-
-	if (jbr->tz_off == NULL &&
-			(jbr->caps == NULL ||
-				jabber_resource_has_capability(jbr, NS_ENTITY_TIME))) {
-		PurpleXmlNode *child;
-		iq = jabber_iq_new(js, JABBER_IQ_GET);
-		purple_xmlnode_set_attrib(iq->node, "to", to);
-		child = purple_xmlnode_new_child(iq->node, "time");
-		purple_xmlnode_set_namespace(child, NS_ENTITY_TIME);
-		jabber_iq_set_callback(iq, jabber_time_parse, jbi);
-		jbi->ids = g_slist_prepend(jbi->ids, g_strdup(iq->id));
-		jabber_iq_send(iq);
-	}
-
-	g_free(full_jid);
-}
-
-static void jabber_buddy_get_info_for_jid(JabberStream *js, const char *jid)
-{
-	JabberIq *iq;
-	PurpleXmlNode *vcard;
-	GList *resources;
-	JabberBuddy *jb;
-	JabberBuddyInfo *jbi;
-	const char *slash;
-	gboolean is_bare_jid;
-
-	jb = jabber_buddy_find(js, jid, TRUE);
-
-	/* invalid JID */
-	if(!jb)
-		return;
-
-	slash = strchr(jid, '/');
-	is_bare_jid = (slash == NULL);
-
-	jbi = g_new0(JabberBuddyInfo, 1);
-	jbi->jid = g_strdup(jid);
-	jbi->js = js;
-	jbi->jb = jb;
-	jbi->resources = g_hash_table_new_full(jbir_hash, jbir_equal, g_free, jabber_buddy_info_resource_free);
-	jbi->user_info = purple_notify_user_info_new();
-
-	iq = jabber_iq_new(js, JABBER_IQ_GET);
-
-	purple_xmlnode_set_attrib(iq->node, "to", jid);
-	vcard = purple_xmlnode_new_child(iq->node, "vCard");
-	purple_xmlnode_set_namespace(vcard, "vcard-temp");
-
-	jabber_iq_set_callback(iq, jabber_vcard_parse, jbi);
-	jbi->ids = g_slist_prepend(jbi->ids, g_strdup(iq->id));
-
-	jabber_iq_send(iq);
-
-	if (is_bare_jid) {
-		if (jb->resources) {
-			for(resources = jb->resources; resources; resources = resources->next) {
-				JabberBuddyResource *jbr = resources->data;
-				dispatch_queries_for_resource(js, jbi, is_bare_jid, jid, jbr);
-			}
-		} else {
-			/* user is offline, send a jabber:iq:last to find out last time online */
-			iq = jabber_iq_new_query(js, JABBER_IQ_GET, NS_LAST_ACTIVITY);
-			purple_xmlnode_set_attrib(iq->node, "to", jid);
-			jabber_iq_set_callback(iq, jabber_last_offline_parse, jbi);
-			jbi->ids = g_slist_prepend(jbi->ids, g_strdup(iq->id));
-			jabber_iq_send(iq);
-		}
-	} else {
-		JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, slash + 1);
-		if (jbr)
-			dispatch_queries_for_resource(js, jbi, is_bare_jid, jid, jbr);
-		else
-			purple_debug_warning("jabber", "jabber_buddy_get_info_for_jid() "
-					"was passed JID %s, but there is no corresponding "
-					"JabberBuddyResource!\n", jid);
-	}
-
-	js->pending_buddy_info_requests = g_slist_prepend(js->pending_buddy_info_requests, jbi);
-	jbi->timeout_handle = g_timeout_add_seconds(30, jabber_buddy_get_info_timeout, jbi);
-}
-
-void
-jabber_buddy_get_info(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
-                      PurpleConnection *gc, const char *who)
-{
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-	JabberID *jid = jabber_id_new(who);
-
-	if (!jid)
-		return;
-
-	if (jid->node && jabber_chat_find(js, jid->node, jid->domain)) {
-		/* For a conversation, include the resource (indicates the user). */
-		jabber_buddy_get_info_for_jid(js, who);
-	} else {
-		char *bare_jid = jabber_get_bare_jid(who);
-		jabber_buddy_get_info_for_jid(js, bare_jid);
-		g_free(bare_jid);
-	}
-
-	jabber_id_free(jid);
-}
-
-static void jabber_buddy_set_invisibility(JabberStream *js, const char *who,
-		gboolean invisible)
-{
-	PurplePresence *gpresence;
-	PurpleAccount *account;
-	PurpleStatus *status;
-	JabberBuddy *jb = jabber_buddy_find(js, who, TRUE);
-	PurpleXmlNode *presence;
-	JabberBuddyState state;
-	char *msg;
-	int priority;
-
-	account   = purple_connection_get_account(js->gc);
-	gpresence = purple_account_get_presence(account);
-	status    = purple_presence_get_active_status(gpresence);
-
-	purple_status_to_jabber(status, &state, &msg, &priority);
-	presence = jabber_presence_create_js(js, state, msg, priority);
-
-	g_free(msg);
-
-	purple_xmlnode_set_attrib(presence, "to", who);
-	if(invisible) {
-		purple_xmlnode_set_attrib(presence, "type", "invisible");
-		jb->invisible |= JABBER_INVIS_BUDDY;
-	} else {
-		jb->invisible &= ~JABBER_INVIS_BUDDY;
-	}
-
-	jabber_send(js, presence);
-	purple_xmlnode_free(presence);
-}
-
-static void
-jabber_buddy_make_invisible(PurpleBlistNode *node, G_GNUC_UNUSED gpointer data)
-{
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-	JabberStream *js;
-
-	g_return_if_fail(PURPLE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-	js = purple_connection_get_protocol_data(gc);
-
-	jabber_buddy_set_invisibility(js, purple_buddy_get_name(buddy), TRUE);
-}
-
-static void
-jabber_buddy_make_visible(PurpleBlistNode *node, G_GNUC_UNUSED gpointer data)
-{
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-	JabberStream *js;
-
-	g_return_if_fail(PURPLE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-	js = purple_connection_get_protocol_data(gc);
-
-	jabber_buddy_set_invisibility(js, purple_buddy_get_name(buddy), FALSE);
-}
-
-static void cancel_presence_notification(gpointer data)
-{
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-	JabberStream *js;
-
-	buddy = data;
-	gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-	js = purple_connection_get_protocol_data(gc);
-
-	jabber_presence_subscription_set(js, purple_buddy_get_name(buddy), "unsubscribed");
-}
-
-static void
-jabber_buddy_cancel_presence_notification(PurpleBlistNode *node,
-                                          G_GNUC_UNUSED gpointer data)
-{
-	PurpleBuddy *buddy;
-	PurpleAccount *account;
-	PurpleConnection *gc;
-	const gchar *name;
-	char *msg;
-
-	g_return_if_fail(PURPLE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *) node;
-	name = purple_buddy_get_name(buddy);
-	account = purple_buddy_get_account(buddy);
-	gc = purple_account_get_connection(account);
-
-	msg = g_strdup_printf(_("%s will no longer be able to see your status "
-	                        "updates.  Do you want to continue?"), name);
-	purple_request_yes_no(gc, NULL, _("Cancel Presence Notification"),
-	                      msg, 0 /* Yes */, purple_request_cpar_from_account(account), buddy,
-	                      cancel_presence_notification, NULL /* Do nothing */);
-	g_free(msg);
-}
-
-static void
-jabber_buddy_rerequest_auth(PurpleBlistNode *node, G_GNUC_UNUSED gpointer data)
-{
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-	JabberStream *js;
-
-	g_return_if_fail(PURPLE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-	js = purple_connection_get_protocol_data(gc);
-
-	jabber_presence_subscription_set(js, purple_buddy_get_name(buddy), "subscribe");
-}
-
-static void
-jabber_buddy_unsubscribe(PurpleBlistNode *node, G_GNUC_UNUSED gpointer data)
-{
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-	JabberStream *js;
-
-	g_return_if_fail(PURPLE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-	js = purple_connection_get_protocol_data(gc);
-
-	jabber_presence_subscription_set(js, purple_buddy_get_name(buddy), "unsubscribe");
-}
-
-static void
-jabber_buddy_login(PurpleBlistNode *node, G_GNUC_UNUSED gpointer data)
-{
-	if(PURPLE_IS_BUDDY(node)) {
-		/* simply create a directed presence of the current status */
-		PurpleBuddy *buddy = (PurpleBuddy *) node;
-		PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-		JabberStream *js = purple_connection_get_protocol_data(gc);
-		PurpleAccount *account = purple_connection_get_account(gc);
-		PurplePresence *gpresence = purple_account_get_presence(account);
-		PurpleStatus *status = purple_presence_get_active_status(gpresence);
-		PurpleXmlNode *presence;
-		JabberBuddyState state;
-		char *msg;
-		int priority;
-
-		purple_status_to_jabber(status, &state, &msg, &priority);
-		presence = jabber_presence_create_js(js, state, msg, priority);
-
-		g_free(msg);
-
-		purple_xmlnode_set_attrib(presence, "to", purple_buddy_get_name(buddy));
-
-		jabber_send(js, presence);
-		purple_xmlnode_free(presence);
-	}
-}
-
-static void
-jabber_buddy_logout(PurpleBlistNode *node, G_GNUC_UNUSED gpointer data)
-{
-	if(PURPLE_IS_BUDDY(node)) {
-		/* simply create a directed unavailable presence */
-		PurpleBuddy *buddy = (PurpleBuddy *) node;
-		PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-		JabberStream *js = purple_connection_get_protocol_data(gc);
-		PurpleXmlNode *presence;
-
-		presence = jabber_presence_create_js(js, JABBER_BUDDY_STATE_UNAVAILABLE, NULL, 0);
-
-		purple_xmlnode_set_attrib(presence, "to", purple_buddy_get_name(buddy));
-
-		jabber_send(js, presence);
-		purple_xmlnode_free(presence);
-	}
-}
-
-static GList *jabber_buddy_menu(PurpleBuddy *buddy)
-{
-	PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-	const char *name = purple_buddy_get_name(buddy);
-	JabberBuddy *jb = jabber_buddy_find(js, name, TRUE);
-	GList *jbrs;
-
-	GList *m = NULL;
-	PurpleActionMenu *act;
-
-	if(!jb)
-		return m;
-
-	if (js->protocol_version.major == 0 && js->protocol_version.minor == 9 &&
-			jb != js->user_jb) {
-		if(jb->invisible & JABBER_INVIS_BUDDY) {
-			act = purple_action_menu_new(_("Un-hide From"),
-			                           G_CALLBACK(jabber_buddy_make_visible),
-			                           NULL, NULL);
-		} else {
-			act = purple_action_menu_new(_("Temporarily Hide From"),
-			                           G_CALLBACK(jabber_buddy_make_invisible),
-			                           NULL, NULL);
-		}
-		m = g_list_append(m, act);
-	}
-
-	if(jb->subscription & JABBER_SUB_FROM && jb != js->user_jb) {
-		act = purple_action_menu_new(_("Cancel Presence Notification"),
-		                           G_CALLBACK(jabber_buddy_cancel_presence_notification),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-	}
-
-	if(!(jb->subscription & JABBER_SUB_TO)) {
-		act = purple_action_menu_new(_("(Re-)Request authorization"),
-		                           G_CALLBACK(jabber_buddy_rerequest_auth),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-
-	} else if (jb != js->user_jb) {
-
-		/* shouldn't this just happen automatically when the buddy is
-		   removed? */
-		act = purple_action_menu_new(_("Unsubscribe"),
-		                           G_CALLBACK(jabber_buddy_unsubscribe),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-	}
-
-	/*
-	 * This if-condition implements parts of XEP-0100: Gateway Interaction
-	 *
-	 * According to stpeter, there is no way to know if a jid on the roster is a gateway without sending a disco#info.
-	 * However, since the gateway might appear offline to us, we cannot get that information. Therefore, I just assume
-	 * that gateways on the roster can be identified by having no '@' in their jid. This is a faily safe assumption, since
-	 * people don't tend to have a server or other service there.
-	 *
-	 * TODO: Use disco#info...
-	 */
-	if (strchr(name, '@') == NULL) {
-		act = purple_action_menu_new(_("Log In"),
-									 G_CALLBACK(jabber_buddy_login),
-									 NULL, NULL);
-		m = g_list_append(m, act);
-		act = purple_action_menu_new(_("Log Out"),
-									 G_CALLBACK(jabber_buddy_logout),
-									 NULL, NULL);
-		m = g_list_append(m, act);
-	}
-
-	/* add all ad hoc commands to the action menu */
-	for(jbrs = jb->resources; jbrs; jbrs = g_list_next(jbrs)) {
-		JabberBuddyResource *jbr = jbrs->data;
-		GList *commands;
-		if (!jbr->commands)
-			continue;
-		for(commands = jbr->commands; commands; commands = g_list_next(commands)) {
-			JabberAdHocCommands *cmd = commands->data;
-			act = purple_action_menu_new(cmd->name, G_CALLBACK(jabber_adhoc_execute_action), cmd, NULL);
-			m = g_list_append(m, act);
-		}
-	}
-
-	return m;
-}
-
-GList *
-jabber_blist_node_menu(G_GNUC_UNUSED PurpleProtocolClient *client,
-                       PurpleBlistNode *node)
-{
-	if(PURPLE_IS_BUDDY(node)) {
-		return jabber_buddy_menu((PurpleBuddy *) node);
-	} else {
-		return NULL;
-	}
-}
-
-gboolean
-jabber_resource_know_capabilities(const JabberBuddyResource *jbr)
-{
-	return jbr->caps != NULL;
-}
-
-gboolean
-jabber_resource_has_capability(const JabberBuddyResource *jbr, const gchar *cap)
-{
-	const GList *node = NULL;
-
-	if (jbr->caps == NULL) {
-		purple_debug_info("jabber",
-			"Unable to find caps: nothing known about buddy\n");
-		return FALSE;
-	}
-
-	node = g_list_find_custom(jbr->caps->features, cap, (GCompareFunc)strcmp);
-	return (node != NULL);
-}
-
-const gchar *
-jabber_resource_get_identity_category_type(const JabberBuddyResource *jbr,
-	const gchar *category)
-{
-	const GList *iter = NULL;
-
-	if (jbr->caps != NULL) {
-		for (iter = jbr->caps->identities ; iter ; iter = g_list_next(iter)) {
-			const JabberIdentity *identity =
-				(JabberIdentity *) iter->data;
-
-			if (purple_strequal(identity->category, category)) {
-				return identity->type;
-			}
-		}
-	}
-
-	return NULL;
-}
diff --git a/libpurple/protocols/jabber/caps.h b/libpurple/protocols/jabber/caps.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/caps.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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_JABBER_CAPS_H
-#define PURPLE_JABBER_CAPS_H
-
-typedef struct _JabberCapsClientInfo JabberCapsClientInfo;
-
-#include "jabber.h"
-
-/* Implementation of XEP-0115 - Entity Capabilities */
-
-typedef struct {
-	const char *node;
-	const char *ver;
-	const char *hash;
-} JabberCapsTuple;
-
-struct _JabberCapsClientInfo {
-	GList *identities; /* JabberIdentity */
-	GList *features; /* char * */
-	GList *forms; /* PurpleXmlNode * */
-
-	const JabberCapsTuple tuple;
-};
-
-typedef void (*jabber_caps_get_info_cb)(JabberCapsClientInfo *info, gpointer user_data);
-
-void jabber_caps_init(void);
-void jabber_caps_uninit(void);
-
-/**
- * Main entity capabilities function to get the capabilities of a contact.
- *
- * The callback will be called synchronously if we already have the
- * capabilities for the specified (node,ver,hash).
- */
-void jabber_caps_get_info(JabberStream *js, const char *who, const char *node,
-                          const char *ver, const char *hash,
-                          jabber_caps_get_info_cb cb,
-                          gpointer user_data);
-
-/**
- *	Takes a JabberCapsClientInfo pointer and returns the caps hash according to
- *	XEP-0115 Version 1.5.
- *
- *	@param info A JabberCapsClientInfo pointer.
- *	@param hash_type GChecksumType to be used. Either sha-1 or md5.
- *	@return		The base64 encoded SHA-1 hash; must be freed by caller
- */
-PURPLE_XMPP_EXTERN_FOR_TESTS
-gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info,
-                                  GChecksumType hash_type);
-
-/**
- *  Calculate SHA1 hash for own featureset.
- */
-void jabber_caps_calculate_own_hash(JabberStream *js);
-
-/** Get the current caps hash.
- * 	@ret hash
-**/
-const gchar* jabber_caps_get_own_hash(JabberStream *js);
-
-/**
- *  Broadcast a new calculated hash using a <presence> stanza.
- */
-void jabber_caps_broadcast_change(void);
-
-/**
- * Parse the <query/> element from an IQ stanza into a JabberCapsClientInfo
- * struct.
- *
- * Exposed for tests
- *
- * @param query The 'query' element from an IQ reply stanza.
- * @returns A JabberCapsClientInfo struct, or NULL on error
- */
-PURPLE_XMPP_EXTERN_FOR_TESTS
-JabberCapsClientInfo *jabber_caps_parse_client_info(PurpleXmlNode *query);
-
-/**
- * Release memory of a JabberCapsClientInfo struct
- * returned by jabber_caps_parse_client_info.
- *
- * Exposed for tests
- *
- * @param info The info object to free.
- */
-PURPLE_XMPP_EXTERN_FOR_TESTS
-void jabber_caps_client_info_destroy(JabberCapsClientInfo *info);
-
-#endif /* PURPLE_JABBER_CAPS_H */
diff --git a/libpurple/protocols/jabber/caps.c b/libpurple/protocols/jabber/caps.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/caps.c
+++ /dev/null
@@ -1,661 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "caps.h"
-#include "iq.h"
-#include "presence.h"
-#include "xdata.h"
-
-#define JABBER_CAPS_FILENAME "xmpp-caps.xml"
-
-typedef struct {
-	gchar *var;
-	GList *values;
-} JabberDataFormField;
-
-static GHashTable *capstable = NULL; /* JabberCapsTuple -> JabberCapsClientInfo */
-static guint       save_timer = 0;
-
-static guint jabber_caps_hash(gconstpointer data) {
-	const JabberCapsTuple *key = data;
-	guint nodehash = g_str_hash(key->node);
-	guint verhash  = g_str_hash(key->ver);
-	guint hashhash = g_str_hash(key->hash);
-	return nodehash ^ verhash ^ hashhash;
-}
-
-static gboolean jabber_caps_compare(gconstpointer v1, gconstpointer v2) {
-	const JabberCapsTuple *name1 = v1;
-	const JabberCapsTuple *name2 = v2;
-
-	return purple_strequal(name1->node, name2->node) &&
-	       purple_strequal(name1->ver, name2->ver) &&
-	       purple_strequal(name1->hash, name2->hash);
-}
-
-void
-jabber_caps_client_info_destroy(JabberCapsClientInfo *info)
-{
-	if (info == NULL)
-		return;
-
-	g_list_free_full(info->identities, (GDestroyNotify)jabber_identity_free);
-
-	g_list_free_full(info->features, g_free);
-
-	g_list_free_full(info->forms, (GDestroyNotify)purple_xmlnode_free);
-
-	g_free((char *)info->tuple.node);
-	g_free((char *)info->tuple.ver);
-	g_free((char *)info->tuple.hash);
-
-	g_free(info);
-}
-
-static void jabber_caps_store_client(gpointer key, gpointer value, gpointer user_data) {
-	const JabberCapsTuple *tuple = key;
-	const JabberCapsClientInfo *props = value;
-	PurpleXmlNode *root = user_data;
-	PurpleXmlNode *client = purple_xmlnode_new_child(root, "client");
-	GList *iter;
-
-	purple_xmlnode_set_attrib(client, "node", tuple->node);
-	purple_xmlnode_set_attrib(client, "ver", tuple->ver);
-	purple_xmlnode_set_attrib(client, "hash", tuple->hash);
-	for(iter = props->identities; iter; iter = g_list_next(iter)) {
-		JabberIdentity *id = iter->data;
-		PurpleXmlNode *identity = purple_xmlnode_new_child(client, "identity");
-		purple_xmlnode_set_attrib(identity, "category", id->category);
-		purple_xmlnode_set_attrib(identity, "type", id->type);
-		if (id->name)
-			purple_xmlnode_set_attrib(identity, "name", id->name);
-		if (id->lang)
-			purple_xmlnode_set_attrib(identity, "lang", id->lang);
-	}
-
-	for(iter = props->features; iter; iter = g_list_next(iter)) {
-		const char *feat = iter->data;
-		PurpleXmlNode *feature = purple_xmlnode_new_child(client, "feature");
-		purple_xmlnode_set_attrib(feature, "var", feat);
-	}
-
-	for(iter = props->forms; iter; iter = g_list_next(iter)) {
-		/* FIXME: See #7814 */
-		PurpleXmlNode *xdata = iter->data;
-		purple_xmlnode_insert_child(client, purple_xmlnode_copy(xdata));
-	}
-}
-
-static gboolean
-do_jabber_caps_store(G_GNUC_UNUSED gpointer data)
-{
-	char *str;
-	int length = 0;
-	PurpleXmlNode *root = purple_xmlnode_new("capabilities");
-
-	g_hash_table_foreach(capstable, jabber_caps_store_client, root);
-	str = purple_xmlnode_to_formatted_str(root, &length);
-	purple_xmlnode_free(root);
-	purple_util_write_data_to_cache_file(JABBER_CAPS_FILENAME, str, length);
-	g_free(str);
-
-	save_timer = 0;
-	return FALSE;
-}
-
-static void
-schedule_caps_save(void)
-{
-	if (save_timer == 0)
-		save_timer = g_timeout_add_seconds(5, do_jabber_caps_store, NULL);
-}
-
-static void
-jabber_caps_load(void)
-{
-	PurpleXmlNode *capsdata = purple_util_read_xml_from_cache_file(JABBER_CAPS_FILENAME, "XMPP capabilities cache");
-	PurpleXmlNode *client;
-
-	if(!capsdata)
-		return;
-
-	if (!purple_strequal(capsdata->name, "capabilities")) {
-		purple_xmlnode_free(capsdata);
-		return;
-	}
-
-	for (client = capsdata->child; client; client = client->next) {
-		if (client->type != PURPLE_XMLNODE_TYPE_TAG)
-			continue;
-		if (purple_strequal(client->name, "client")) {
-			JabberCapsClientInfo *value = g_new0(JabberCapsClientInfo, 1);
-			JabberCapsTuple *key = (JabberCapsTuple*)&value->tuple;
-			PurpleXmlNode *child;
-			key->node = g_strdup(purple_xmlnode_get_attrib(client,"node"));
-			key->ver  = g_strdup(purple_xmlnode_get_attrib(client,"ver"));
-			key->hash = g_strdup(purple_xmlnode_get_attrib(client,"hash"));
-
-			for (child = client->child; child; child = child->next) {
-				if (child->type != PURPLE_XMLNODE_TYPE_TAG)
-					continue;
-				if (purple_strequal(child->name, "feature")) {
-					const char *var = purple_xmlnode_get_attrib(child, "var");
-					if(!var)
-						continue;
-					value->features = g_list_append(value->features,g_strdup(var));
-				} else if (purple_strequal(child->name, "identity")) {
-					const char *category = purple_xmlnode_get_attrib(child, "category");
-					const char *type = purple_xmlnode_get_attrib(child, "type");
-					const char *name = purple_xmlnode_get_attrib(child, "name");
-					const char *lang = purple_xmlnode_get_attrib(child, "lang");
-					JabberIdentity *id;
-
-					if (!category || !type)
-						continue;
-
-					id = jabber_identity_new(category, type, lang, name);
-					value->identities = g_list_append(value->identities,id);
-				} else if (purple_strequal(child->name, "x")) {
-					/* TODO: See #7814 -- this might cause problems if anyone
-					 * ever actually specifies forms. In fact, for this to
-					 * work properly, that bug needs to be fixed in
-					 * purple_xmlnode_from_str, not the output version... */
-					value->forms = g_list_append(value->forms, purple_xmlnode_copy(child));
-				}
-			}
-
-			g_hash_table_replace(capstable, key, value);
-		}
-	}
-	purple_xmlnode_free(capsdata);
-}
-
-void jabber_caps_init(void)
-{
-	capstable = g_hash_table_new_full(jabber_caps_hash, jabber_caps_compare, NULL, (GDestroyNotify)jabber_caps_client_info_destroy);
-	jabber_caps_load();
-}
-
-void jabber_caps_uninit(void)
-{
-	if(save_timer != 0) {
-		g_clear_handle_id(&save_timer, g_source_remove);
-		do_jabber_caps_store(NULL);
-	}
-	g_clear_pointer(&capstable, g_hash_table_destroy);
-}
-
-typedef struct {
-	jabber_caps_get_info_cb cb;
-	gpointer cb_data;
-
-	char *who;
-	char *node;
-	char *ver;
-	char *hash;
-
-	JabberCapsClientInfo *info;
-} jabber_caps_cbplususerdata;
-
-static void
-cbplususerdata_destroy(jabber_caps_cbplususerdata *data)
-{
-	if (data == NULL)
-		return;
-
-	g_free(data->who);
-	g_free(data->node);
-	g_free(data->ver);
-	g_free(data->hash);
-
-	/* If we have info here, it's already in the capstable, so don't free it */
-
-	g_free(data);
-}
-
-static void
-jabber_caps_get_info_complete(jabber_caps_cbplususerdata *userdata)
-{
-	if (userdata->cb) {
-		userdata->cb(userdata->info, userdata->cb_data);
-		userdata->info = NULL;
-	}
-}
-
-static void
-jabber_caps_client_iqcb(G_GNUC_UNUSED JabberStream *js,
-                        G_GNUC_UNUSED const char *from, JabberIqType type,
-                        G_GNUC_UNUSED const char *id, PurpleXmlNode *packet,
-                        gpointer data)
-{
-	jabber_caps_cbplususerdata *userdata = data;
-	PurpleXmlNode *query = NULL;
-	JabberCapsClientInfo *info = NULL, *value;
-	JabberCapsTuple key;
-	gchar *hash = NULL;
-	GChecksumType hash_type;
-	gboolean supported_hash = TRUE;
-
-	query = purple_xmlnode_get_child_with_namespace(packet, "query",
-	                                                NS_DISCO_INFO);
-	if(query == NULL || type == JABBER_IQ_ERROR) {
-		userdata->cb(NULL, userdata->cb_data);
-		cbplususerdata_destroy(userdata);
-		return;
-	}
-
-	/* check hash */
-	info = jabber_caps_parse_client_info(query);
-
-	if(purple_strequal(userdata->hash, "sha-1")) {
-		hash_type = G_CHECKSUM_SHA1;
-	} else if(purple_strequal(userdata->hash, "md5")) {
-		hash_type = G_CHECKSUM_MD5;
-	} else {
-		supported_hash = FALSE;
-	}
-
-	if (supported_hash) {
-		hash = jabber_caps_calculate_hash(info, hash_type);
-	}
-
-	if (hash == NULL || !purple_strequal(hash, userdata->ver)) {
-		purple_debug_warning("jabber",
-		                     "Could not validate caps info from %s. "
-		                     "Expected %s, got %s",
-		                     purple_xmlnode_get_attrib(packet, "from"),
-		                     userdata->ver, hash ? hash : "(null)");
-
-		userdata->cb(NULL, userdata->cb_data);
-		jabber_caps_client_info_destroy(info);
-		cbplususerdata_destroy(userdata);
-		g_free(hash);
-		return;
-	}
-
-	g_free(hash);
-
-	key.node = userdata->node;
-	key.ver  = userdata->ver;
-	key.hash = userdata->hash;
-
-	/* Use the copy of this data already in the table if it exists or insert
-	 * a new one if we need to */
-	if ((value = g_hash_table_lookup(capstable, &key))) {
-		jabber_caps_client_info_destroy(info);
-		info = value;
-	} else {
-		JabberCapsTuple *n_key = NULL;
-
-		if (G_UNLIKELY(info == NULL)) {
-			g_warn_if_reached();
-			return;
-		}
-
-		n_key = (JabberCapsTuple *)&info->tuple;
-		n_key->node = userdata->node;
-		n_key->ver  = userdata->ver;
-		n_key->hash = userdata->hash;
-		userdata->node = userdata->ver = userdata->hash = NULL;
-
-		/* The capstable gets a reference */
-		g_hash_table_insert(capstable, n_key, info);
-		schedule_caps_save();
-	}
-
-	userdata->info = info;
-
-	jabber_caps_get_info_complete(userdata);
-
-	cbplususerdata_destroy(userdata);
-}
-
-void
-jabber_caps_get_info(JabberStream *js, const char *who, const char *node,
-                     const char *ver, const char *hash,
-                     jabber_caps_get_info_cb cb, gpointer user_data)
-{
-	JabberCapsClientInfo *info = NULL;
-	JabberCapsTuple key;
-	jabber_caps_cbplususerdata *userdata = NULL;
-	JabberIq *iq = NULL;
-	PurpleXmlNode *query = NULL;
-	char *nodever = NULL;
-
-	/* Using this in a read-only fashion, so the cast is OK */
-	key.node = (char *)node;
-	key.ver = (char *)ver;
-	key.hash = (char *)hash;
-
-	info = g_hash_table_lookup(capstable, &key);
-	if (info != NULL) {
-		/* We already have all the information we care about */
-		if (cb) {
-			cb(info, user_data);
-		}
-		return;
-	}
-
-	userdata = g_new0(jabber_caps_cbplususerdata, 1);
-	/* We start out with 0 references. Every query takes one */
-	userdata->cb = cb;
-	userdata->cb_data = user_data;
-	userdata->who = g_strdup(who);
-	userdata->node = g_strdup(node);
-	userdata->ver = g_strdup(ver);
-	userdata->hash = g_strdup(hash);
-
-	/* If we don't have the basic information about the client, we need to
-	 * fetch it. */
-	iq = jabber_iq_new_query(js, JABBER_IQ_GET, NS_DISCO_INFO);
-	query = purple_xmlnode_get_child_with_namespace(iq->node, "query",
-	                                                NS_DISCO_INFO);
-	nodever = g_strdup_printf("%s#%s", node, ver);
-	purple_xmlnode_set_attrib(query, "node", nodever);
-	g_free(nodever);
-	purple_xmlnode_set_attrib(iq->node, "to", who);
-
-	jabber_iq_set_callback(iq, jabber_caps_client_iqcb, userdata);
-	jabber_iq_send(iq);
-}
-
-static gint
-jabber_xdata_compare(gconstpointer a, gconstpointer b)
-{
-	const PurpleXmlNode *aformtypefield = a;
-	const PurpleXmlNode *bformtypefield = b;
-	char *aformtype;
-	char *bformtype;
-	int result;
-
-	aformtype = jabber_x_data_get_formtype(aformtypefield);
-	bformtype = jabber_x_data_get_formtype(bformtypefield);
-
-	result = strcmp(aformtype, bformtype);
-	g_free(aformtype);
-	g_free(bformtype);
-	return result;
-}
-
-JabberCapsClientInfo *jabber_caps_parse_client_info(PurpleXmlNode *query)
-{
-	PurpleXmlNode *child;
-	JabberCapsClientInfo *info;
-
-	if (!query || !purple_strequal(query->name, "query") ||
-			!purple_strequal(query->xmlns, NS_DISCO_INFO))
-		return NULL;
-
-	info = g_new0(JabberCapsClientInfo, 1);
-
-	for(child = query->child; child; child = child->next) {
-		if (child->type != PURPLE_XMLNODE_TYPE_TAG)
-			continue;
-		if (purple_strequal(child->name, "identity")) {
-			/* parse identity */
-			const char *category = purple_xmlnode_get_attrib(child, "category");
-			const char *type = purple_xmlnode_get_attrib(child, "type");
-			const char *name = purple_xmlnode_get_attrib(child, "name");
-			const char *lang = purple_xmlnode_get_attrib(child, "lang");
-			JabberIdentity *id;
-
-			if (!category || !type)
-				continue;
-
-			id = jabber_identity_new(category, type, lang, name);
-			info->identities = g_list_append(info->identities, id);
-		} else if (purple_strequal(child->name, "feature")) {
-			/* parse feature */
-			const char *var = purple_xmlnode_get_attrib(child, "var");
-			if (var)
-				info->features = g_list_prepend(info->features, g_strdup(var));
-		} else if (purple_strequal(child->name, "x")) {
-			if (purple_strequal(child->xmlns, "jabber:x:data")) {
-				/* x-data form */
-				PurpleXmlNode *dataform = purple_xmlnode_copy(child);
-				info->forms = g_list_append(info->forms, dataform);
-			}
-		}
-	}
-	return info;
-}
-
-static gint jabber_caps_xdata_field_compare(gconstpointer a, gconstpointer b)
-{
-	const JabberDataFormField *ac = a;
-	const JabberDataFormField *bc = b;
-
-	return strcmp(ac->var, bc->var);
-}
-
-static GList* jabber_caps_xdata_get_fields(const PurpleXmlNode *x)
-{
-	GList *fields = NULL;
-	PurpleXmlNode *field;
-
-	if (!x)
-		return NULL;
-
-	for (field = purple_xmlnode_get_child(x, "field"); field; field = purple_xmlnode_get_next_twin(field)) {
-		PurpleXmlNode *value;
-		JabberDataFormField *xdatafield = g_new0(JabberDataFormField, 1);
-		xdatafield->var = g_strdup(purple_xmlnode_get_attrib(field, "var"));
-
-		for (value = purple_xmlnode_get_child(field, "value"); value; value = purple_xmlnode_get_next_twin(value)) {
-			gchar *val = purple_xmlnode_get_data(value);
-			xdatafield->values = g_list_prepend(xdatafield->values, val);
-		}
-
-		xdatafield->values = g_list_sort(xdatafield->values, (GCompareFunc)strcmp);
-		fields = g_list_prepend(fields, xdatafield);
-	}
-
-	fields = g_list_sort(fields, jabber_caps_xdata_field_compare);
-	return fields;
-}
-
-static void
-append_escaped_string(GChecksum *hash, const gchar *str)
-{
-	g_return_if_fail(hash != NULL);
-
-	if (str && *str) {
-		char *tmp = g_markup_escape_text(str, -1);
-		g_checksum_update(hash, (const guchar *)tmp, -1);
-		g_free(tmp);
-	}
-
-	g_checksum_update(hash, (const guchar *)"<", -1);
-}
-
-gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info,
-	GChecksumType hash_type)
-{
-	GChecksum *hash;
-	GList *node;
-	guint8 *checksum;
-	gsize checksum_size;
-	gchar *ret;
-
-	if (!info)
-		return NULL;
-
-	/* sort identities, features and x-data forms */
-	info->identities = g_list_sort(info->identities, jabber_identity_compare);
-	info->features = g_list_sort(info->features, (GCompareFunc)strcmp);
-	info->forms = g_list_sort(info->forms, jabber_xdata_compare);
-
-	hash = g_checksum_new(hash_type);
-
-	if (hash == NULL) {
-		return NULL;
-	}
-
-	/* Add identities to the hash data */
-	for (node = info->identities; node; node = node->next) {
-		JabberIdentity *id = (JabberIdentity*)node->data;
-		char *category = g_markup_escape_text(id->category, -1);
-		char *type = g_markup_escape_text(id->type, -1);
-		char *lang = NULL;
-		char *name = NULL;
-		char *tmp;
-
-		if (id->lang)
-			lang = g_markup_escape_text(id->lang, -1);
-		if (id->name)
-			name = g_markup_escape_text(id->name, -1);
-
-		tmp = g_strconcat(category, "/", type, "/", lang ? lang : "",
-		                  "/", name ? name : "", "<", NULL);
-
-		g_checksum_update(hash, (const guchar *)tmp, -1);
-
-		g_free(tmp);
-		g_free(category);
-		g_free(type);
-		g_free(lang);
-		g_free(name);
-	}
-
-	/* concat features to the verification string */
-	for (node = info->features; node; node = node->next) {
-		append_escaped_string(hash, node->data);
-	}
-
-	/* concat x-data forms to the verification string */
-	for(node = info->forms; node; node = node->next) {
-		PurpleXmlNode *data = (PurpleXmlNode *)node->data;
-		gchar *formtype = jabber_x_data_get_formtype(data);
-		GList *fields = jabber_caps_xdata_get_fields(data);
-
-		/* append FORM_TYPE's field value to the verification string */
-		append_escaped_string(hash, formtype);
-		g_free(formtype);
-
-		while (fields) {
-			JabberDataFormField *field = (JabberDataFormField*)fields->data;
-
-			if (!purple_strequal(field->var, "FORM_TYPE")) {
-				/* Append the "var" attribute */
-				append_escaped_string(hash, field->var);
-				/* Append <value/> elements' cdata */
-				while (field->values) {
-					append_escaped_string(hash, field->values->data);
-					g_free(field->values->data);
-					field->values = g_list_delete_link(field->values,
-					                                   field->values);
-				}
-			} else {
-				g_list_free_full(field->values, g_free);
-			}
-
-			g_free(field->var);
-			g_free(field);
-
-			fields = g_list_delete_link(fields, fields);
-		}
-	}
-
-	checksum_size = g_checksum_type_get_length(hash_type);
-	checksum = g_new(guint8, checksum_size);
-
-	/* generate hash */
-	g_checksum_get_digest(hash, checksum, &checksum_size);
-
-	ret = g_base64_encode(checksum, checksum_size);
-	g_free(checksum);
-	g_checksum_free(hash);
-
-	return ret;
-}
-
-void jabber_caps_calculate_own_hash(JabberStream *js) {
-	JabberCapsClientInfo info;
-	GList *iter = NULL;
-	GList *features = NULL;
-
-	if (!jabber_identities && !jabber_features) {
-		/* This really shouldn't ever happen */
-		purple_debug_warning("jabber", "No features or identities, cannot calculate own caps hash.\n");
-		g_free(js->caps_hash);
-		js->caps_hash = NULL;
-		return;
-	}
-
-	/* build the currently-supported list of features */
-	if (jabber_features) {
-		for (iter = jabber_features; iter; iter = iter->next) {
-			JabberFeature *feat = iter->data;
-			if(!feat->is_enabled || feat->is_enabled(js, feat->namespace)) {
-				features = g_list_append(features, feat->namespace);
-			}
-		}
-	}
-
-	info.features = features;
-	/* TODO: This copy can go away, I think, since jabber_identities
-	 * is pre-sorted, so the sort in calculate_hash should be idempotent.
-	 * However, I want to test that. --darkrain
-	 */
-	info.identities = g_list_copy(jabber_identities);
-	info.forms = NULL;
-
-	g_free(js->caps_hash);
-	js->caps_hash = jabber_caps_calculate_hash(&info, G_CHECKSUM_SHA1);
-	g_list_free(info.identities);
-	g_list_free(info.features);
-}
-
-const gchar* jabber_caps_get_own_hash(JabberStream *js)
-{
-	if (!js->caps_hash)
-		jabber_caps_calculate_own_hash(js);
-
-	return js->caps_hash;
-}
-
-void
-jabber_caps_broadcast_change(void)
-{
-	PurpleAccountManager *manager = NULL;
-	GList *node, *accounts;
-
-	manager = purple_account_manager_get_default();
-	accounts = purple_account_manager_get_enabled(manager);
-
-	for (node = accounts; node; node = node->next) {
-		PurpleAccount *account = node->data;
-		const char *protocol_id = purple_account_get_protocol_id(account);
-		if (purple_strequal("prpl-jabber", protocol_id) && purple_account_is_connected(account)) {
-			PurpleConnection *gc = purple_account_get_connection(account);
-			jabber_presence_send(purple_connection_get_protocol_data(gc), TRUE);
-		}
-	}
-
-	g_list_free(accounts);
-}
-
diff --git a/libpurple/protocols/jabber/chat.h b/libpurple/protocols/jabber/chat.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/chat.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/**
- * @file chat.h Chat 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 PURPLE_JABBER_CHAT_H
-#define PURPLE_JABBER_CHAT_H
-
-#include <purple.h>
-
-#include "jabber.h"
-
-typedef struct {
-	char *handle;
-	char *jid;
-} JabberChatMember;
-
-
-typedef struct {
-	JabberStream *js;
-	char *room;
-	char *server;
-	char *handle;
-	GHashTable *components;
-	int id;
-	PurpleChatConversation *conv;
-	gboolean muc;
-	gboolean xhtml;
-	PurpleRequestType config_dialog_type;
-	void *config_dialog_handle;
-	GHashTable *members;
-	gboolean left;
-	GDateTime *joined;
-} JabberChat;
-
-GList *jabber_chat_info(PurpleProtocolChat *protocol_chat, PurpleConnection *connection);
-GHashTable *jabber_chat_info_defaults(PurpleConnection *gc, const char *chat_name);
-char *jabber_get_chat_name(PurpleProtocolChat *protocol_chat, GHashTable *data);
-
-void jabber_chat_join(PurpleConnection *gc, GHashTable *data);
-JabberChat *jabber_chat_find(JabberStream *js, const char *room,
-		const char *server);
-JabberChat *jabber_chat_find_by_id(JabberStream *js, int id);
-JabberChat *jabber_chat_find_by_conv(PurpleChatConversation *conv);
-void jabber_chat_destroy(JabberChat *chat);
-void jabber_chat_free(JabberChat *chat);
-gboolean jabber_chat_find_buddy(PurpleChatConversation *conv, const char *name);
-void jabber_chat_invite(PurpleConnection *gc, int id, const char *message,
-		const char *name);
-void jabber_chat_leave(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id);
-char *jabber_chat_user_real_name(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id, const char *who);
-void jabber_chat_request_room_configure(JabberChat *chat);
-void jabber_chat_create_instant_room(JabberChat *chat);
-void jabber_chat_register(JabberChat *chat);
-void jabber_chat_change_topic(JabberChat *chat, const char *topic);
-void jabber_chat_set_topic(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id, const char *topic);
-gboolean jabber_chat_change_nick(JabberChat *chat, const char *nick);
-void jabber_chat_part(JabberChat *chat, const char *msg);
-void jabber_chat_track_handle(JabberChat *chat, const char *handle,
-		const char *jid, const char *affiliation, const char *role);
-void jabber_chat_remove_handle(JabberChat *chat, const char *handle);
-gboolean jabber_chat_ban_user(JabberChat *chat, const char *who,
-		const char *why);
-gboolean jabber_chat_affiliate_user(JabberChat *chat, const char *who,
-		const char *affiliation);
-gboolean jabber_chat_affiliation_list(JabberChat *chat, const char *affiliation);
-gboolean jabber_chat_role_user(JabberChat *chat, const char *who,
-		const char *role, const char *why);
-gboolean jabber_chat_role_list(JabberChat *chat, const char *role);
-
-PurpleRoomlist *jabber_roomlist_get_list(PurpleProtocolRoomlist *protocol_roomlist, PurpleConnection *gc);
-void jabber_roomlist_cancel(PurpleProtocolRoomlist *protocol_roomlist, PurpleRoomlist *list);
-char *jabber_roomlist_room_serialize(PurpleProtocolRoomlist *protocol_roomlist, PurpleRoomlistRoom *room);
-
-void jabber_chat_disco_traffic(JabberChat *chat);
-
-#endif /* PURPLE_JABBER_CHAT_H */
diff --git a/libpurple/protocols/jabber/chat.c b/libpurple/protocols/jabber/chat.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/chat.c
+++ /dev/null
@@ -1,1225 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "chat.h"
-#include "iq.h"
-#include "message.h"
-#include "presence.h"
-#include "xdata.h"
-#include "data.h"
-
-GList *
-jabber_chat_info(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
-                 G_GNUC_UNUSED PurpleConnection *connection)
-{
-	GList *m = NULL;
-	PurpleProtocolChatEntry *pce;
-
-	pce = g_new0(PurpleProtocolChatEntry, 1);
-	pce->label = _("_Room");
-	pce->identifier = "room";
-	pce->required = TRUE;
-	m = g_list_append(m, pce);
-
-	pce = g_new0(PurpleProtocolChatEntry, 1);
-	pce->label = _("_Server");
-	pce->identifier = "server";
-	pce->required = TRUE;
-	m = g_list_append(m, pce);
-
-	pce = g_new0(PurpleProtocolChatEntry, 1);
-	pce->label = _("_Handle");
-	pce->identifier = "handle";
-	pce->required = TRUE;
-	m = g_list_append(m, pce);
-
-	pce = g_new0(PurpleProtocolChatEntry, 1);
-	pce->label = _("_Password");
-	pce->identifier = "password";
-	pce->secret = TRUE;
-	m = g_list_append(m, pce);
-
-	return m;
-}
-
-GHashTable *jabber_chat_info_defaults(PurpleConnection *gc, const char *chat_name)
-{
-	GHashTable *defaults;
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-
-	defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
-
-	g_hash_table_insert(defaults, "handle", g_strdup(js->user->node));
-
-	if (js->chat_servers)
-		g_hash_table_insert(defaults, "server", g_strdup(js->chat_servers->data));
-
-	if (chat_name != NULL) {
-		JabberID *jid = jabber_id_new(chat_name);
-		if(jid) {
-			g_hash_table_insert(defaults, "room", g_strdup(jid->node));
-			if(jid->domain)
-				g_hash_table_replace(defaults, "server", g_strdup(jid->domain));
-			if(jid->resource)
-				g_hash_table_replace(defaults, "handle", g_strdup(jid->resource));
-			jabber_id_free(jid);
-		}
-	}
-
-	return defaults;
-}
-
-JabberChat *jabber_chat_find(JabberStream *js, const char *room,
-		const char *server)
-{
-	JabberChat *chat = NULL;
-
-	g_return_val_if_fail(room != NULL, NULL);
-	g_return_val_if_fail(server != NULL, NULL);
-
-	if(NULL != js->chats)
-	{
-		char *room_jid = g_strdup_printf("%s@%s", room, server);
-
-		chat = g_hash_table_lookup(js->chats, room_jid);
-		g_free(room_jid);
-	}
-
-	return chat;
-}
-
-static gboolean
-find_by_id_cb(G_GNUC_UNUSED gpointer key, gpointer value, gpointer user_data)
-{
-	JabberChat *chat = value;
-
-	return chat->id == GPOINTER_TO_INT(user_data);
-}
-
-JabberChat *jabber_chat_find_by_id(JabberStream *js, int id)
-{
-	return g_hash_table_find(js->chats, find_by_id_cb, GINT_TO_POINTER(id));
-}
-
-JabberChat *jabber_chat_find_by_conv(PurpleChatConversation *conv)
-{
-	PurpleAccount *account = purple_conversation_get_account(PURPLE_CONVERSATION(conv));
-	PurpleConnection *gc = purple_account_get_connection(account);
-	JabberStream *js;
-	int id;
-	if (!gc)
-		return NULL;
-	js = purple_connection_get_protocol_data(gc);
-	id = purple_chat_conversation_get_id(conv);
-	return jabber_chat_find_by_id(js, id);
-}
-
-void jabber_chat_invite(PurpleConnection *gc, int id, const char *msg,
-		const char *name)
-{
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-	JabberChat *chat;
-	PurpleXmlNode *message, *body, *x, *invite;
-	char *room_jid;
-
-	chat = jabber_chat_find_by_id(js, id);
-	if(!chat)
-		return;
-
-	message = purple_xmlnode_new("message");
-
-	room_jid = g_strdup_printf("%s@%s", chat->room, chat->server);
-
-	if(chat->muc) {
-		purple_xmlnode_set_attrib(message, "to", room_jid);
-		x = purple_xmlnode_new_child(message, "x");
-		purple_xmlnode_set_namespace(x, "http://jabber.org/protocol/muc#user");
-		invite = purple_xmlnode_new_child(x, "invite");
-		purple_xmlnode_set_attrib(invite, "to", name);
-		if (msg) {
-			body = purple_xmlnode_new_child(invite, "reason");
-			purple_xmlnode_insert_data(body, msg, -1);
-		}
-	} else {
-		purple_xmlnode_set_attrib(message, "to", name);
-		/*
-		 * Putting the reason into the body was an 'undocumented protocol,
-		 * ...not part of "groupchat 1.0"'.
-		 * http://xmpp.org/extensions/attic/jep-0045-1.16.html#invite
-		 *
-		 * Left here for compatibility.
-		 */
-		if (msg) {
-			body = purple_xmlnode_new_child(message, "body");
-			purple_xmlnode_insert_data(body, msg, -1);
-		}
-
-		x = purple_xmlnode_new_child(message, "x");
-		purple_xmlnode_set_attrib(x, "jid", room_jid);
-
-		/* The better place for it! XEP-0249 style. */
-		if (msg)
-			purple_xmlnode_set_attrib(x, "reason", msg);
-		purple_xmlnode_set_namespace(x, "jabber:x:conference");
-	}
-
-	jabber_send(js, message);
-	purple_xmlnode_free(message);
-	g_free(room_jid);
-}
-
-void jabber_chat_member_free(JabberChatMember *jcm);
-
-gchar *
-jabber_get_chat_name(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
-                     GHashTable *data)
-{
-	char *room, *server, *chat_name = NULL;
-
-	room = g_hash_table_lookup(data, "room");
-	server = g_hash_table_lookup(data, "server");
-
-	if (room && server) {
-		chat_name = g_strdup_printf("%s@%s", room, server);
-	}
-	return chat_name;
-}
-
-static void insert_in_hash_table(gpointer key, gpointer value, gpointer user_data)
-{
-	GHashTable *hash_table = (GHashTable *)user_data;
-	g_hash_table_insert(hash_table, g_strdup(key), g_strdup(value));
-}
-
-static JabberChat *
-jabber_chat_new(JabberStream *js, const char *room, const char *server,
-                const char *handle, G_GNUC_UNUSED const char *password,
-                GHashTable *data)
-{
-	JabberChat *chat;
-	char *jid;
-
-	if (jabber_chat_find(js, room, server) != NULL)
-		return NULL;
-
-	chat = g_new0(JabberChat, 1);
-	chat->js = js;
-	chat->joined = 0;
-
-	chat->room = g_strdup(room);
-	chat->server = g_strdup(server);
-	chat->handle = g_strdup(handle);
-
-	/* Copy the data hash table to chat->components */
-	chat->components = g_hash_table_new_full(g_str_hash, g_str_equal,
-			g_free, g_free);
-	if (data == NULL) {
-		g_hash_table_insert(chat->components, g_strdup("handle"), g_strdup(handle));
-		g_hash_table_insert(chat->components, g_strdup("room"), g_strdup(room));
-		g_hash_table_insert(chat->components, g_strdup("server"), g_strdup(server));
-		/* g_hash_table_insert(chat->components, g_strdup("password"), g_strdup(server)); */
-	} else {
-		g_hash_table_foreach(data, insert_in_hash_table, chat->components);
-	}
-
-	chat->members = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
-			(GDestroyNotify)jabber_chat_member_free);
-
-	jid = g_strdup_printf("%s@%s", room, server);
-	g_hash_table_insert(js->chats, jid, chat);
-
-	return chat;
-}
-
-/*
- * jabber_join_chat:
- * @room: The room to join. This MUST be normalized already.
- * @server: The server the room is on. This MUST be normalized already.
- * @password: (nullable): The password (if required) to join the room.
- * @data: (nullable): The chat hash table. If NULL, it will be generated for
- *        current core<>protocol API interface.
- *
- * In-protocol function for joining a chat room. Doesn't require sticking goop
- * into a hash table.
- */
-static JabberChat *
-jabber_join_chat(JabberStream *js, const char *room, const char *server,
-                 const char *handle, const char *password, GHashTable *data)
-{
-	JabberChat *chat;
-
-	PurpleConnection *gc;
-	PurpleAccount *account;
-	PurpleStatus *status;
-
-	PurpleXmlNode *presence, *x;
-	JabberBuddyState state;
-	char *msg;
-	int priority;
-
-	char *jid;
-
-	chat = jabber_chat_new(js, room, server, handle, password, data);
-	if (chat == NULL)
-		return NULL;
-
-	gc = js->gc;
-	account = purple_connection_get_account(gc);
-	status = purple_account_get_active_status(account);
-	purple_status_to_jabber(status, &state, &msg, &priority);
-
-	presence = jabber_presence_create_js(js, state, msg, priority);
-	g_free(msg);
-
-	jid = g_strdup_printf("%s@%s/%s", room, server, handle);
-	purple_xmlnode_set_attrib(presence, "to", jid);
-	g_free(jid);
-
-	x = purple_xmlnode_new_child(presence, "x");
-	purple_xmlnode_set_namespace(x, "http://jabber.org/protocol/muc");
-
-	if (password && *password) {
-		PurpleXmlNode *p = purple_xmlnode_new_child(x, "password");
-		purple_xmlnode_insert_data(p, password, -1);
-	}
-
-	jabber_send(js, presence);
-	purple_xmlnode_free(presence);
-
-	return chat;
-}
-
-void jabber_chat_join(PurpleConnection *gc, GHashTable *data)
-{
-	char *room, *server, *handle, *passwd;
-	JabberID *jid;
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-	char *tmp;
-
-	room = g_hash_table_lookup(data, "room");
-	server = g_hash_table_lookup(data, "server");
-	handle = g_hash_table_lookup(data, "handle");
-	passwd = g_hash_table_lookup(data, "password");
-
-	if(!room || !server)
-		return;
-
-	if(!handle)
-		handle = js->user->node;
-
-	if(!jabber_nodeprep_validate(room)) {
-		char *buf = g_strdup_printf(_("%s is not a valid room name"), room);
-		purple_notify_error(gc, _("Invalid Room Name"), _("Invalid Room Name"),
-			buf, purple_request_cpar_from_connection(gc));
-		purple_serv_got_join_chat_failed(gc, data);
-		g_free(buf);
-		return;
-	} else if(!jabber_domain_validate(server)) {
-		char *buf = g_strdup_printf(_("%s is not a valid server name"), server);
-		purple_notify_error(gc, _("Invalid Server Name"),
-			_("Invalid Server Name"), buf,
-			purple_request_cpar_from_connection(gc));
-		purple_serv_got_join_chat_failed(gc, data);
-		g_free(buf);
-		return;
-	} else if(!jabber_resourceprep_validate(handle)) {
-		char *buf = g_strdup_printf(_("%s is not a valid room handle"), handle);
-		purple_notify_error(gc, _("Invalid Room Handle"),
-			_("Invalid Room Handle"), buf,
-			purple_request_cpar_from_connection(gc));
-		purple_serv_got_join_chat_failed(gc, data);
-		g_free(buf);
-		return;
-	}
-
-	/* Normalize the room and server parameters */
-	tmp = g_strdup_printf("%s@%s", room, server);
-	jid = jabber_id_new(tmp);
-	g_free(tmp);
-
-	if (jid == NULL) {
-		/* TODO: Error message */
-
-		g_return_if_reached();
-	}
-
-	/*
-	 * Now that we've done all that nice core-interface stuff, let's join
-	 * this room!
-	 */
-	jabber_join_chat(js, jid->node, jid->domain, handle, passwd, data);
-	jabber_id_free(jid);
-}
-
-void
-jabber_chat_leave(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
-                  PurpleConnection *gc, gint id)
-{
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-	JabberChat *chat = jabber_chat_find_by_id(js, id);
-
-	if(!chat)
-		return;
-
-	jabber_chat_part(chat, NULL);
-
-	chat->left = TRUE;
-}
-
-void jabber_chat_destroy(JabberChat *chat)
-{
-	JabberStream *js = chat->js;
-	char *room_jid = g_strdup_printf("%s@%s", chat->room, chat->server);
-
-	g_hash_table_remove(js->chats, room_jid);
-	g_free(room_jid);
-}
-
-void jabber_chat_free(JabberChat *chat)
-{
-	if(chat->config_dialog_handle)
-		purple_request_close(chat->config_dialog_type, chat->config_dialog_handle);
-
-	g_free(chat->room);
-	g_free(chat->server);
-	g_free(chat->handle);
-	g_hash_table_destroy(chat->members);
-	g_hash_table_destroy(chat->components);
-
-	g_clear_pointer(&chat->joined, g_date_time_unref);
-
-	g_free(chat);
-}
-
-gboolean jabber_chat_find_buddy(PurpleChatConversation *conv, const char *name)
-{
-	return purple_chat_conversation_has_user(conv, name);
-}
-
-gchar *
-jabber_chat_user_real_name(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
-                           PurpleConnection *gc, gint id, const gchar *who)
-{
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-	JabberChat *chat;
-	JabberChatMember *jcm;
-
-	chat = jabber_chat_find_by_id(js, id);
-
-	if(!chat)
-		return NULL;
-
-	jcm = g_hash_table_lookup(chat->members, who);
-	if (jcm != NULL && jcm->jid)
-		return g_strdup(jcm->jid);
-
-
-	return g_strdup_printf("%s@%s/%s", chat->room, chat->server, who);
-}
-
-static void jabber_chat_room_configure_x_data_cb(JabberStream *js, PurpleXmlNode *result, gpointer data)
-{
-	JabberChat *chat = data;
-	PurpleXmlNode *query;
-	JabberIq *iq;
-	char *to = g_strdup_printf("%s@%s", chat->room, chat->server);
-
-	iq = jabber_iq_new_query(js, JABBER_IQ_SET, "http://jabber.org/protocol/muc#owner");
-	purple_xmlnode_set_attrib(iq->node, "to", to);
-	g_free(to);
-
-	query = purple_xmlnode_get_child(iq->node, "query");
-
-	purple_xmlnode_insert_child(query, result);
-
-	jabber_iq_send(iq);
-}
-
-static void
-jabber_chat_room_configure_cb(JabberStream *js, const char *from,
-                              JabberIqType type, G_GNUC_UNUSED const char *id,
-                              PurpleXmlNode *packet,
-                              G_GNUC_UNUSED gpointer data)
-{
-	PurpleXmlNode *query, *x;
-	char *msg;
-	JabberChat *chat;
-	JabberID *jid;
-
-	if (!from)
-		return;
-
-	if (type == JABBER_IQ_RESULT) {
-		jid = jabber_id_new(from);
-
-		if(!jid)
-			return;
-
-		chat = jabber_chat_find(js, jid->node, jid->domain);
-		jabber_id_free(jid);
-
-		if(!chat)
-			return;
-
-		if(!(query = purple_xmlnode_get_child(packet, "query")))
-			return;
-
-		for(x = purple_xmlnode_get_child(query, "x"); x; x = purple_xmlnode_get_next_twin(x)) {
-			const char *xmlns;
-			if(!(xmlns = purple_xmlnode_get_namespace(x)))
-				continue;
-
-			if(purple_strequal(xmlns, "jabber:x:data")) {
-				chat->config_dialog_type = PURPLE_REQUEST_FIELDS;
-				chat->config_dialog_handle = jabber_x_data_request(js, x, jabber_chat_room_configure_x_data_cb, chat);
-				return;
-			}
-		}
-	} else if (type == JABBER_IQ_ERROR) {
-		char *msg = jabber_parse_error(js, packet, NULL);
-
-		purple_notify_error(js->gc, _("Configuration error"),
-			_("Configuration error"), msg,
-			purple_request_cpar_from_connection(js->gc));
-
-		g_free(msg);
-		return;
-	}
-
-	msg = g_strdup_printf("Unable to configure room %s", from);
-
-	purple_notify_info(js->gc, _("Unable to configure"),
-		_("Unable to configure"), msg,
-		purple_request_cpar_from_connection(js->gc));
-	g_free(msg);
-
-}
-
-void jabber_chat_request_room_configure(JabberChat *chat) {
-	JabberIq *iq;
-	char *room_jid;
-
-	if(!chat)
-		return;
-
-	chat->config_dialog_handle = NULL;
-
-	if(!chat->muc) {
-		purple_notify_error(chat->js->gc, _("Room Configuration Error"),
-			_("Room Configuration Error"),
-			_("This room is not capable of being configured"),
-			purple_request_cpar_from_connection(chat->js->gc));
-		return;
-	}
-
-	iq = jabber_iq_new_query(chat->js, JABBER_IQ_GET,
-			"http://jabber.org/protocol/muc#owner");
-	room_jid = g_strdup_printf("%s@%s", chat->room, chat->server);
-
-	purple_xmlnode_set_attrib(iq->node, "to", room_jid);
-
-	jabber_iq_set_callback(iq, jabber_chat_room_configure_cb, NULL);
-
-	jabber_iq_send(iq);
-
-	g_free(room_jid);
-}
-
-void jabber_chat_create_instant_room(JabberChat *chat) {
-	JabberIq *iq;
-	PurpleXmlNode *query, *x;
-	char *room_jid;
-
-	if(!chat)
-		return;
-
-	chat->config_dialog_handle = NULL;
-
-	iq = jabber_iq_new_query(chat->js, JABBER_IQ_SET,
-			"http://jabber.org/protocol/muc#owner");
-	query = purple_xmlnode_get_child(iq->node, "query");
-	x = purple_xmlnode_new_child(query, "x");
-	room_jid = g_strdup_printf("%s@%s", chat->room, chat->server);
-
-	purple_xmlnode_set_attrib(iq->node, "to", room_jid);
-	purple_xmlnode_set_namespace(x, "jabber:x:data");
-	purple_xmlnode_set_attrib(x, "type", "submit");
-
-	jabber_iq_send(iq);
-
-	g_free(room_jid);
-}
-
-static void
-jabber_chat_register_x_data_result_cb(JabberStream *js,
-                                      G_GNUC_UNUSED const char *from,
-                                      JabberIqType type,
-                                      G_GNUC_UNUSED const char *id,
-                                      PurpleXmlNode *packet,
-                                      G_GNUC_UNUSED gpointer data)
-{
-	if (type == JABBER_IQ_ERROR) {
-		char *msg = jabber_parse_error(js, packet, NULL);
-
-		purple_notify_error(js->gc, _("Registration error"),
-			_("Registration error"), msg,
-			purple_request_cpar_from_connection(js->gc));
-
-		g_free(msg);
-		return;
-	}
-}
-
-static void jabber_chat_register_x_data_cb(JabberStream *js, PurpleXmlNode *result, gpointer data)
-{
-	JabberChat *chat = data;
-	PurpleXmlNode *query;
-	JabberIq *iq;
-	char *to = g_strdup_printf("%s@%s", chat->room, chat->server);
-
-	iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:register");
-	purple_xmlnode_set_attrib(iq->node, "to", to);
-	g_free(to);
-
-	query = purple_xmlnode_get_child(iq->node, "query");
-
-	purple_xmlnode_insert_child(query, result);
-
-	jabber_iq_set_callback(iq, jabber_chat_register_x_data_result_cb, NULL);
-
-	jabber_iq_send(iq);
-}
-
-static void
-jabber_chat_register_cb(JabberStream *js, const char *from, JabberIqType type,
-                        G_GNUC_UNUSED const char *id, PurpleXmlNode *packet,
-                        G_GNUC_UNUSED gpointer data)
-{
-	PurpleXmlNode *query, *x;
-	char *msg;
-	JabberChat *chat;
-	JabberID *jid;
-
-	if (!from)
-		return;
-
-	if (type == JABBER_IQ_RESULT) {
-		jid = jabber_id_new(from);
-
-		if(!jid)
-			return;
-
-		chat = jabber_chat_find(js, jid->node, jid->domain);
-		jabber_id_free(jid);
-
-		if(!chat)
-			return;
-
-		if(!(query = purple_xmlnode_get_child(packet, "query")))
-			return;
-
-		for(x = purple_xmlnode_get_child(query, "x"); x; x = purple_xmlnode_get_next_twin(x)) {
-			const char *xmlns;
-
-			if(!(xmlns = purple_xmlnode_get_namespace(x)))
-				continue;
-
-			if(purple_strequal(xmlns, "jabber:x:data")) {
-				jabber_x_data_request(js, x, jabber_chat_register_x_data_cb, chat);
-				return;
-			}
-		}
-	} else if (type == JABBER_IQ_ERROR) {
-		char *msg = jabber_parse_error(js, packet, NULL);
-
-		purple_notify_error(js->gc, _("Registration error"),
-			_("Registration error"), msg,
-			purple_request_cpar_from_connection(js->gc));
-
-		g_free(msg);
-		return;
-	}
-
-	msg = g_strdup_printf("Unable to configure room %s", from);
-
-	purple_notify_info(js->gc, _("Unable to configure"), _("Unable to "
-		"configure"), msg, purple_request_cpar_from_connection(js->gc));
-	g_free(msg);
-
-}
-
-void jabber_chat_register(JabberChat *chat)
-{
-	JabberIq *iq;
-	char *room_jid;
-
-	if(!chat)
-		return;
-
-	room_jid = g_strdup_printf("%s@%s", chat->room, chat->server);
-
-	iq = jabber_iq_new_query(chat->js, JABBER_IQ_GET, "jabber:iq:register");
-	purple_xmlnode_set_attrib(iq->node, "to", room_jid);
-	g_free(room_jid);
-
-	jabber_iq_set_callback(iq, jabber_chat_register_cb, NULL);
-
-	jabber_iq_send(iq);
-}
-
-/* merge this with the function below when we get everyone on the same page wrt /commands */
-void jabber_chat_change_topic(JabberChat *chat, const char *topic)
-{
-	JabberMessage *jm;
-
-	jm = g_new0(JabberMessage, 1);
-	jm->js = chat->js;
-	jm->type = JABBER_MESSAGE_GROUPCHAT;
-	jm->to = g_strdup_printf("%s@%s", chat->room, chat->server);
-
-	if (topic && *topic)
-		jm->subject = g_strdup(topic);
-	else
-		jm->subject = g_strdup("");
-
-	jabber_message_send(jm);
-	jabber_message_free(jm);
-}
-
-void
-jabber_chat_set_topic(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
-                      PurpleConnection *gc, gint id, const gchar *topic)
-{
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-	JabberChat *chat = jabber_chat_find_by_id(js, id);
-
-	if(!chat)
-		return;
-
-	jabber_chat_change_topic(chat, topic);
-}
-
-
-gboolean jabber_chat_change_nick(JabberChat *chat, const char *nick)
-{
-	PurpleXmlNode *presence;
-	char *full_jid;
-	PurpleAccount *account;
-	PurpleStatus *status;
-	JabberBuddyState state;
-	char *msg;
-	int priority;
-
-	if(!chat->muc) {
-		purple_conversation_write_system_message(
-			PURPLE_CONVERSATION(chat->conv),
-			_("Nick changing not supported in non-MUC chatrooms"), 0);
-		return FALSE;
-	}
-
-	account = purple_connection_get_account(chat->js->gc);
-	status = purple_account_get_active_status(account);
-
-	purple_status_to_jabber(status, &state, &msg, &priority);
-
-	presence = jabber_presence_create_js(chat->js, state, msg, priority);
-	full_jid = g_strdup_printf("%s@%s/%s", chat->room, chat->server, nick);
-	purple_xmlnode_set_attrib(presence, "to", full_jid);
-	g_free(full_jid);
-	g_free(msg);
-
-	jabber_send(chat->js, presence);
-	purple_xmlnode_free(presence);
-
-	return TRUE;
-}
-
-void jabber_chat_part(JabberChat *chat, const char *msg)
-{
-	char *room_jid;
-	PurpleXmlNode *presence;
-
-	room_jid = g_strdup_printf("%s@%s/%s", chat->room, chat->server,
-			chat->handle);
-	presence = purple_xmlnode_new("presence");
-	purple_xmlnode_set_attrib(presence, "to", room_jid);
-	purple_xmlnode_set_attrib(presence, "type", "unavailable");
-	if(msg) {
-		PurpleXmlNode *status = purple_xmlnode_new_child(presence, "status");
-		purple_xmlnode_insert_data(status, msg, -1);
-	}
-	jabber_send(chat->js, presence);
-
-	purple_xmlnode_free(presence);
-	g_free(room_jid);
-}
-
-static void
-roomlist_disco_result_cb(JabberStream *js, G_GNUC_UNUSED const char *from,
-                         JabberIqType type, G_GNUC_UNUSED const char *id,
-                         PurpleXmlNode *packet, G_GNUC_UNUSED gpointer data)
-{
-	PurpleXmlNode *query;
-	PurpleXmlNode *item;
-
-	if(!js->roomlist)
-		return;
-
-	if (type == JABBER_IQ_ERROR) {
-		char *err = jabber_parse_error(js, packet, NULL);
-		purple_notify_error(js->gc, _("Error"),
-			_("Error retrieving room list"), err,
-			purple_request_cpar_from_connection(js->gc));
-		purple_roomlist_set_in_progress(js->roomlist, FALSE);
-		g_object_unref(js->roomlist);
-		js->roomlist = NULL;
-		g_free(err);
-		return;
-	}
-
-	if(!(query = purple_xmlnode_get_child(packet, "query"))) {
-		char *err = jabber_parse_error(js, packet, NULL);
-		purple_notify_error(js->gc, _("Error"),
-			_("Error retrieving room list"), err,
-			purple_request_cpar_from_connection(js->gc));
-		purple_roomlist_set_in_progress(js->roomlist, FALSE);
-		g_object_unref(js->roomlist);
-		js->roomlist = NULL;
-		g_free(err);
-		return;
-	}
-
-	for(item = purple_xmlnode_get_child(query, "item"); item;
-			item = purple_xmlnode_get_next_twin(item)) {
-		const char *name;
-		PurpleRoomlistRoom *room;
-		JabberID *jid;
-
-		if(!(jid = jabber_id_new(purple_xmlnode_get_attrib(item, "jid"))))
-			continue;
-		name = purple_xmlnode_get_attrib(item, "name");
-
-
-		room = purple_roomlist_room_new(jid->node, name);
-		purple_roomlist_room_add_field(room, "room", g_strdup(jid->node));
-		purple_roomlist_room_add_field(room, "server", g_strdup(jid->domain));
-		purple_roomlist_room_add(js->roomlist, room);
-		g_object_unref(room);
-
-		jabber_id_free(jid);
-	}
-	purple_roomlist_set_in_progress(js->roomlist, FALSE);
-	g_object_unref(js->roomlist);
-	js->roomlist = NULL;
-}
-
-static void
-roomlist_cancel_cb(JabberStream *js, G_GNUC_UNUSED const char *server) {
-	if(js->roomlist) {
-		purple_roomlist_set_in_progress(js->roomlist, FALSE);
-		g_object_unref(js->roomlist);
-		js->roomlist = NULL;
-	}
-}
-
-static void roomlist_ok_cb(JabberStream *js, const char *server)
-{
-	JabberIq *iq;
-
-	if(!js->roomlist)
-		return;
-
-	if(!server || !*server) {
-		purple_notify_error(js->gc, _("Invalid Server"),
-			_("Invalid Server"), NULL,
-			purple_request_cpar_from_connection(js->gc));
-		purple_roomlist_set_in_progress(js->roomlist, FALSE);
-		return;
-	}
-
-	purple_roomlist_set_in_progress(js->roomlist, TRUE);
-
-	iq = jabber_iq_new_query(js, JABBER_IQ_GET, NS_DISCO_ITEMS);
-
-	purple_xmlnode_set_attrib(iq->node, "to", server);
-
-	jabber_iq_set_callback(iq, roomlist_disco_result_cb, NULL);
-
-	jabber_iq_send(iq);
-}
-
-PurpleRoomlist *
-jabber_roomlist_get_list(G_GNUC_UNUSED PurpleProtocolRoomlist *protocol_roomlist,
-                         PurpleConnection *gc)
-{
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-
-	if(js->roomlist)
-		g_object_unref(js->roomlist);
-
-	js->roomlist = purple_roomlist_new(purple_connection_get_account(js->gc));
-
-	purple_request_input(gc, _("Enter a Conference Server"), _("Enter a Conference Server"),
-			_("Select a conference server to query"),
-			js->chat_servers ? js->chat_servers->data : NULL,
-			FALSE, FALSE, NULL,
-			_("Find Rooms"), G_CALLBACK(roomlist_ok_cb),
-			_("Cancel"), G_CALLBACK(roomlist_cancel_cb),
-			purple_request_cpar_from_connection(gc),
-			js);
-
-	return js->roomlist;
-}
-
-void
-jabber_roomlist_cancel(G_GNUC_UNUSED PurpleProtocolRoomlist *protocol_roomlist,
-                       PurpleRoomlist *list)
-{
-	PurpleAccount *account;
-	PurpleConnection *gc;
-	JabberStream *js;
-
-	account = purple_roomlist_get_account(list);
-	gc = purple_account_get_connection(account);
-	js = purple_connection_get_protocol_data(gc);
-
-	purple_roomlist_set_in_progress(list, FALSE);
-
-	if (js->roomlist == list) {
-		js->roomlist = NULL;
-		g_object_unref(list);
-	}
-}
-
-char *
-jabber_roomlist_room_serialize(G_GNUC_UNUSED PurpleProtocolRoomlist *protocol_roomlist,
-                               PurpleRoomlistRoom *room)
-{
-	const gchar *room_name = NULL, *server = NULL;
-
-	room_name = purple_roomlist_room_get_field(room, "room");
-	server = purple_roomlist_room_get_field(room, "server");
-
-	return g_strdup_printf("%s@%s", room_name, server);
-}
-
-void jabber_chat_member_free(JabberChatMember *jcm)
-{
-	g_free(jcm->handle);
-	g_free(jcm->jid);
-	g_free(jcm);
-}
-
-void
-jabber_chat_track_handle(JabberChat *chat, const char *handle, const char *jid,
-                         G_GNUC_UNUSED const char *affiliation,
-                         G_GNUC_UNUSED const char *role)
-{
-	JabberChatMember *jcm = g_new0(JabberChatMember, 1);
-
-	jcm->handle = g_strdup(handle);
-	jcm->jid = g_strdup(jid);
-
-	g_hash_table_replace(chat->members, jcm->handle, jcm);
-
-	/* XXX: keep track of role and affiliation */
-}
-
-void jabber_chat_remove_handle(JabberChat *chat, const char *handle)
-{
-	g_hash_table_remove(chat->members, handle);
-}
-
-gboolean jabber_chat_ban_user(JabberChat *chat, const char *who, const char *why)
-{
-	JabberChatMember *jcm;
-	const char *jid;
-	char *to;
-	JabberIq *iq;
-	PurpleXmlNode *query, *item, *reason;
-
-	jcm = g_hash_table_lookup(chat->members, who);
-	if (jcm && jcm->jid)
-		jid = jcm->jid;
-	else if (strchr(who, '@') != NULL)
-		jid = who;
-	else
-		return FALSE;
-
-	iq = jabber_iq_new_query(chat->js, JABBER_IQ_SET,
-			"http://jabber.org/protocol/muc#admin");
-
-	to = g_strdup_printf("%s@%s", chat->room, chat->server);
-	purple_xmlnode_set_attrib(iq->node, "to", to);
-	g_free(to);
-
-	query = purple_xmlnode_get_child(iq->node, "query");
-	item = purple_xmlnode_new_child(query, "item");
-	purple_xmlnode_set_attrib(item, "jid", jid);
-	purple_xmlnode_set_attrib(item, "affiliation", "outcast");
-	if(why) {
-		reason = purple_xmlnode_new_child(item, "reason");
-		purple_xmlnode_insert_data(reason, why, -1);
-	}
-
-	jabber_iq_send(iq);
-
-	return TRUE;
-}
-
-gboolean jabber_chat_affiliate_user(JabberChat *chat, const char *who, const char *affiliation)
-{
-	JabberChatMember *jcm;
-	const char *jid;
-	char *to;
-	JabberIq *iq;
-	PurpleXmlNode *query, *item;
-
-	jcm = g_hash_table_lookup(chat->members, who);
-	if (jcm && jcm->jid)
-		jid = jcm->jid;
-	else if (strchr(who, '@') != NULL)
-		jid = who;
-	else
-		return FALSE;
-
-	iq = jabber_iq_new_query(chat->js, JABBER_IQ_SET,
-			"http://jabber.org/protocol/muc#admin");
-
-	to = g_strdup_printf("%s@%s", chat->room, chat->server);
-	purple_xmlnode_set_attrib(iq->node, "to", to);
-	g_free(to);
-
-	query = purple_xmlnode_get_child(iq->node, "query");
-	item = purple_xmlnode_new_child(query, "item");
-	purple_xmlnode_set_attrib(item, "jid", jid);
-	purple_xmlnode_set_attrib(item, "affiliation", affiliation);
-
-	jabber_iq_send(iq);
-
-	return TRUE;
-}
-
-static void
-jabber_chat_affiliation_list_cb(JabberStream *js,
-                                G_GNUC_UNUSED const char *from,
-                                JabberIqType type,
-                                G_GNUC_UNUSED const char *id,
-                                PurpleXmlNode *packet, gpointer data)
-{
-	JabberChat *chat;
-	PurpleXmlNode *query, *item;
-	int chat_id = GPOINTER_TO_INT(data);
-	GString *buf;
-
-	if(!(chat = jabber_chat_find_by_id(js, chat_id)))
-		return;
-
-	if (type == JABBER_IQ_ERROR)
-		return;
-
-	if(!(query = purple_xmlnode_get_child(packet, "query")))
-		return;
-
-	buf = g_string_new(_("Affiliations:"));
-
-	item = purple_xmlnode_get_child(query, "item");
-	if (item) {
-		for( ; item; item = purple_xmlnode_get_next_twin(item)) {
-			const char *jid = purple_xmlnode_get_attrib(item, "jid");
-			const char *affiliation = purple_xmlnode_get_attrib(item, "affiliation");
-			if (jid && affiliation)
-				g_string_append_printf(buf, "\n%s %s", jid, affiliation);
-		}
-    } else {
-		buf = g_string_append_c(buf, '\n');
-		buf = g_string_append_len(buf, _("No users found"), -1);
-	}
-
-	purple_conversation_write_system_message(PURPLE_CONVERSATION(chat->conv),
-		buf->str, PURPLE_MESSAGE_NO_LOG);
-
-	g_string_free(buf, TRUE);
-}
-
-gboolean jabber_chat_affiliation_list(JabberChat *chat, const char *affiliation)
-{
-	JabberIq *iq;
-	char *room_jid;
-	PurpleXmlNode *query, *item;
-
-	iq = jabber_iq_new_query(chat->js, JABBER_IQ_GET,
-			"http://jabber.org/protocol/muc#admin");
-
-	room_jid = g_strdup_printf("%s@%s", chat->room, chat->server);
-	purple_xmlnode_set_attrib(iq->node, "to", room_jid);
-
-	query = purple_xmlnode_get_child(iq->node, "query");
-	item = purple_xmlnode_new_child(query, "item");
-	purple_xmlnode_set_attrib(item, "affiliation", affiliation);
-
-	jabber_iq_set_callback(iq, jabber_chat_affiliation_list_cb, GINT_TO_POINTER(chat->id));
-	jabber_iq_send(iq);
-
-	return TRUE;
-}
-
-gboolean jabber_chat_role_user(JabberChat *chat, const char *who,
-                               const char *role, const char *why)
-{
-	char *to;
-	JabberIq *iq;
-	PurpleXmlNode *query, *item;
-	JabberChatMember *jcm;
-
-	jcm = g_hash_table_lookup(chat->members, who);
-
-	if (!jcm || !jcm->handle)
-		return FALSE;
-
-	iq = jabber_iq_new_query(chat->js, JABBER_IQ_SET,
-	                         "http://jabber.org/protocol/muc#admin");
-
-	to = g_strdup_printf("%s@%s", chat->room, chat->server);
-	purple_xmlnode_set_attrib(iq->node, "to", to);
-	g_free(to);
-
-	query = purple_xmlnode_get_child(iq->node, "query");
-	item = purple_xmlnode_new_child(query, "item");
-	purple_xmlnode_set_attrib(item, "nick", jcm->handle);
-	purple_xmlnode_set_attrib(item, "role", role);
-	if (why) {
-		PurpleXmlNode *reason = purple_xmlnode_new_child(item, "reason");
-		purple_xmlnode_insert_data(reason, why, -1);
-	}
-
-	jabber_iq_send(iq);
-
-	return TRUE;
-}
-
-static void
-jabber_chat_role_list_cb(JabberStream *js, G_GNUC_UNUSED const char *from,
-                         JabberIqType type, G_GNUC_UNUSED const char *id,
-                         PurpleXmlNode *packet, gpointer data)
-{
-	JabberChat *chat;
-	PurpleXmlNode *query, *item;
-	int chat_id = GPOINTER_TO_INT(data);
-	GString *buf;
-
-	if(!(chat = jabber_chat_find_by_id(js, chat_id)))
-		return;
-
-	if (type == JABBER_IQ_ERROR)
-		return;
-
-	if(!(query = purple_xmlnode_get_child(packet, "query")))
-		return;
-
-	buf = g_string_new(_("Roles:"));
-
-	item = purple_xmlnode_get_child(query, "item");
-	if (item) {
-		for( ; item; item = purple_xmlnode_get_next_twin(item)) {
-			const char *jid  = purple_xmlnode_get_attrib(item, "jid");
-			const char *role = purple_xmlnode_get_attrib(item, "role");
-			if (jid && role)
-				g_string_append_printf(buf, "\n%s %s", jid, role);
-	    }
-	} else {
-		buf = g_string_append_c(buf, '\n');
-		buf = g_string_append_len(buf, _("No users found"), -1);
-	}
-
-	purple_conversation_write_system_message(PURPLE_CONVERSATION(chat->conv),
-		buf->str, PURPLE_MESSAGE_NO_LOG);
-
-	g_string_free(buf, TRUE);
-}
-
-gboolean jabber_chat_role_list(JabberChat *chat, const char *role)
-{
-	JabberIq *iq;
-	char *room_jid;
-	PurpleXmlNode *query, *item;
-
-	iq = jabber_iq_new_query(chat->js, JABBER_IQ_GET,
-			"http://jabber.org/protocol/muc#admin");
-
-	room_jid = g_strdup_printf("%s@%s", chat->room, chat->server);
-	purple_xmlnode_set_attrib(iq->node, "to", room_jid);
-
-	query = purple_xmlnode_get_child(iq->node, "query");
-	item = purple_xmlnode_new_child(query, "item");
-	purple_xmlnode_set_attrib(item, "role", role);
-
-	jabber_iq_set_callback(iq, jabber_chat_role_list_cb, GINT_TO_POINTER(chat->id));
-	jabber_iq_send(iq);
-
-	return TRUE;
-}
-
-static void
-jabber_chat_disco_traffic_cb(JabberStream *js, G_GNUC_UNUSED const char *from,
-                             G_GNUC_UNUSED JabberIqType type,
-                             G_GNUC_UNUSED const char *id,
-                             G_GNUC_UNUSED PurpleXmlNode *packet,
-                             gpointer data)
-{
-	JabberChat *chat;
-	int chat_id = GPOINTER_TO_INT(data);
-
-	if(!(chat = jabber_chat_find_by_id(js, chat_id)))
-		return;
-
-	/* defaults, in case the conference server doesn't
-	 * support this request */
-	chat->xhtml = TRUE;
-}
-
-void jabber_chat_disco_traffic(JabberChat *chat)
-{
-	JabberIq *iq;
-	PurpleXmlNode *query;
-	char *room_jid;
-
-	room_jid = g_strdup_printf("%s@%s", chat->room, chat->server);
-
-	iq = jabber_iq_new_query(chat->js, JABBER_IQ_GET, NS_DISCO_INFO);
-
-	purple_xmlnode_set_attrib(iq->node, "to", room_jid);
-
-	query = purple_xmlnode_get_child(iq->node, "query");
-
-	purple_xmlnode_set_attrib(query, "node", "http://jabber.org/protocol/muc#traffic");
-
-	jabber_iq_set_callback(iq, jabber_chat_disco_traffic_cb, GINT_TO_POINTER(chat->id));
-
-	jabber_iq_send(iq);
-
-	g_free(room_jid);
-}
diff --git a/libpurple/protocols/jabber/data.h b/libpurple/protocols/jabber/data.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/data.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * purple - Handling of XEP-0231: Bits of Binary.
- *
- * 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_JABBER_DATA_H
-#define PURPLE_JABBER_DATA_H
-
-#include <purple.h>
-
-#include "jabber.h"
-
-#include <glib.h>
-
-#define JABBER_DATA_MAX_SIZE 8192
-
-
-typedef struct {
-	char *cid;
-	char *type;
-	gsize size;
-	gpointer data;
-	gboolean ephemeral;
-} JabberData;
-
-typedef void (JabberDataRequestCallback)(JabberData *data, gchar *alt,
-    gpointer userdata);
-
-
-/* creates a JabberData instance from raw data */
-JabberData *jabber_data_create_from_data(gconstpointer data, gsize size,
-	const char *type, gboolean ephemeral, JabberStream *js);
-
-/* create a JabberData instance from an XML "data" element (as defined by
-  XEP 0231 */
-JabberData *jabber_data_create_from_xml(PurpleXmlNode *tag);
-
-/* destroy a JabberData instance, NOT to be used on data that has been
-	associated, since they get "owned" */
-void jabber_data_destroy(JabberData *data);
-
-const char *jabber_data_get_cid(const JabberData *data);
-const char *jabber_data_get_type(const JabberData *data);
-
-gsize jabber_data_get_size(const JabberData *data);
-gpointer jabber_data_get_data(const JabberData *data);
-
-/* returns the XML definition for the data element */
-PurpleXmlNode *jabber_data_get_xml_definition(const JabberData *data);
-
-/* returns an XHTML-IM "img" tag given a data instance */
-PurpleXmlNode *jabber_data_get_xhtml_im(const JabberData *data, const gchar *alt);
-
-void jabber_data_request(JabberStream *js, const gchar *cid, const gchar *who,
-    gchar *alt, gboolean ephemeral, JabberDataRequestCallback cb,
-    gpointer userdata);
-
-/* lookup functions */
-const JabberData *jabber_data_find_local_by_alt(const gchar *alt);
-const JabberData *jabber_data_find_local_by_cid(const gchar *cid);
-const JabberData *jabber_data_find_remote_by_cid(JabberStream *js,
-    const gchar *who, const gchar *cid);
-
-/* store data objects */
-void jabber_data_associate_local(JabberData *data, const gchar *alt);
-void jabber_data_associate_remote(JabberStream *js, const gchar *who,
-    JabberData *data);
-
-void jabber_data_init(void);
-void jabber_data_uninit(void);
-
-#endif /* PURPLE_JABBER_DATA_H */
diff --git a/libpurple/protocols/jabber/data.c b/libpurple/protocols/jabber/data.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/data.c
+++ /dev/null
@@ -1,474 +0,0 @@
-/*
- * purple - Handling of XEP-0231: Bits of Binary.
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <stdlib.h>
-#include <glib.h>
-#include <string.h>
-
-#include <purple.h>
-#include "libpurple/glibcompat.h"
-
-#include "data.h"
-#include "iq.h"
-
-static GHashTable *local_data_by_alt = NULL;
-static GHashTable *local_data_by_cid = NULL;
-static GHashTable *remote_data_by_cid = NULL;
-
-JabberData *
-jabber_data_create_from_data(gconstpointer rawdata, gsize size,
-                             const char *type, gboolean ephemeral,
-                             G_GNUC_UNUSED JabberStream *js)
-{
-	JabberData *data;
-	gchar *checksum;
-
-	g_return_val_if_fail(rawdata != NULL, NULL);
-	g_return_val_if_fail(size > 0, NULL);
-	g_return_val_if_fail(type != NULL, NULL);
-
-	checksum = g_compute_checksum_for_data(G_CHECKSUM_SHA1, rawdata, size);
-
-	data = g_new0(JabberData, 1);
-	data->cid = g_strdup_printf("sha1+%s@bob.xmpp.org", checksum);
-	data->type = g_strdup(type);
-	data->size = size;
-	data->ephemeral = ephemeral;
-	data->data = g_memdup2(rawdata, size);
-
-	g_free(checksum);
-	return data;
-}
-
-static void
-jabber_data_delete(gpointer cbdata)
-{
-	JabberData *data = cbdata;
-
-	g_free(data->cid);
-	g_free(data->type);
-	g_free(data->data);
-	g_free(data);
-}
-
-
-JabberData *
-jabber_data_create_from_xml(PurpleXmlNode *tag)
-{
-	JabberData *data;
-	gchar *raw_data = NULL;
-	const gchar *cid, *type;
-
-	g_return_val_if_fail(tag != NULL, NULL);
-
-	/* check if this is a "data" tag */
-	if (!purple_strequal(tag->name, "data")) {
-		purple_debug_error("jabber", "Invalid data element\n");
-		return NULL;
-	}
-
-	cid = purple_xmlnode_get_attrib(tag, "cid");
-	type = purple_xmlnode_get_attrib(tag, "type");
-
-	if (!cid || !type) {
-		purple_debug_error("jabber", "cid or type missing\n");
-		return NULL;
-	}
-
-	raw_data = purple_xmlnode_get_data(tag);
-
-	if (raw_data == NULL || *raw_data == '\0') {
-		purple_debug_error("jabber", "data element was empty");
-		g_free(raw_data);
-		return NULL;
-	}
-
-	data = g_new0(JabberData, 1);
-	data->data = g_base64_decode(raw_data, &data->size);
-	g_free(raw_data);
-
-	if (data->data == NULL) {
-		purple_debug_error("jabber", "Malformed base64 data\n");
-		g_free(data);
-		return NULL;
-	}
-
-	data->cid = g_strdup(cid);
-	data->type = g_strdup(type);
-
-	return data;
-}
-
-void
-jabber_data_destroy(JabberData *data)
-{
-	g_return_if_fail(data != NULL);
-
-	jabber_data_delete(data);
-}
-
-const char *
-jabber_data_get_cid(const JabberData *data)
-{
-	g_return_val_if_fail(data != NULL, NULL);
-
-	return data->cid;
-}
-
-
-const char *
-jabber_data_get_type(const JabberData *data)
-{
-	g_return_val_if_fail(data != NULL, NULL);
-
-	return data->type;
-}
-
-gsize
-jabber_data_get_size(const JabberData *data)
-{
-	g_return_val_if_fail(data != NULL, 0);
-
-	return data->size;
-}
-
-gpointer
-jabber_data_get_data(const JabberData *data)
-{
-	g_return_val_if_fail(data != NULL, NULL);
-
-	return data->data;
-}
-
-PurpleXmlNode *
-jabber_data_get_xml_definition(const JabberData *data)
-{
-	PurpleXmlNode *tag;
-	char *base64data;
-
-	g_return_val_if_fail(data != NULL, NULL);
-
-	tag = purple_xmlnode_new("data");
-	base64data = g_base64_encode(data->data, data->size);
-
-	purple_xmlnode_set_namespace(tag, NS_BOB);
-	purple_xmlnode_set_attrib(tag, "cid", data->cid);
-	purple_xmlnode_set_attrib(tag, "type", data->type);
-
-	purple_xmlnode_insert_data(tag, base64data, -1);
-
-	g_free(base64data);
-
-	return tag;
-}
-
-PurpleXmlNode *
-jabber_data_get_xhtml_im(const JabberData *data, const gchar *alt)
-{
-	PurpleXmlNode *img;
-	char *src;
-
-	g_return_val_if_fail(data != NULL, NULL);
-	g_return_val_if_fail(alt != NULL, NULL);
-
-	img = purple_xmlnode_new("img");
-	purple_xmlnode_set_attrib(img, "alt", alt);
-
-	src = g_strconcat("cid:", data->cid, NULL);
-	purple_xmlnode_set_attrib(img, "src", src);
-	g_free(src);
-
-	return img;
-}
-
-static PurpleXmlNode *
-jabber_data_get_xml_request(const gchar *cid)
-{
-	PurpleXmlNode *tag = purple_xmlnode_new("data");
-
-	purple_xmlnode_set_namespace(tag, NS_BOB);
-	purple_xmlnode_set_attrib(tag, "cid", cid);
-
-	return tag;
-}
-
-static gboolean
-jabber_data_has_valid_hash(const JabberData *data)
-{
-	const gchar *cid = jabber_data_get_cid(data);
-	gchar **cid_parts = g_strsplit(cid, "@", -1);
-	guint num_cid_parts = 0;
-	gboolean ret = FALSE;
-
-	if (cid_parts)
-		num_cid_parts = g_strv_length(cid_parts);
-
-	if (num_cid_parts == 2 && purple_strequal(cid_parts[1], "bob.xmpp.org")) {
-		gchar **sub_parts = g_strsplit(cid_parts[0], "+", -1);
-		guint num_sub_parts = 0;
-
-		if (sub_parts)
-			num_sub_parts = g_strv_length(sub_parts);
-
-		if (num_sub_parts == 2) {
-			const gchar *hash_algo = sub_parts[0];
-			const gchar *hash_value = sub_parts[1];
-			GChecksumType hash_type;
-			gboolean valid_hash_type = TRUE;
-
-			if (purple_strequal(hash_algo, "sha1"))
-				hash_type = G_CHECKSUM_SHA1;
-			else if (purple_strequal(hash_algo, "sha256"))
-				hash_type = G_CHECKSUM_SHA256;
-			else if (purple_strequal(hash_algo, "sha512"))
-				hash_type = G_CHECKSUM_SHA512;
-			else if (purple_strequal(hash_algo, "md5"))
-				hash_type = G_CHECKSUM_MD5;
-			else
-				valid_hash_type = FALSE;
-
-			if (valid_hash_type) {
-				gchar *digest = g_compute_checksum_for_data(
-					hash_type, jabber_data_get_data(data),
-					jabber_data_get_size(data));
-
-				ret = purple_strequal(digest, hash_value);
-
-				if (!ret)
-					purple_debug_warning("jabber", "Unable to validate BoB "
-					                     "hash; expecting %s, got %s\n",
-					                     cid, digest);
-
-				g_free(digest);
-			} else {
-				purple_debug_warning("jabber", "Unable to validate BoB hash; "
-				                     "unknown hash algorithm %s\n", hash_algo);
-			}
-		} else {
-			purple_debug_warning("jabber", "Malformed BoB CID\n");
-		}
-
-		g_strfreev(sub_parts);
-	}
-
-	g_strfreev(cid_parts);
-	return ret;
-}
-
-
-typedef struct {
-	gpointer userdata;
-	gchar *alt;
-	gboolean ephemeral;
-	JabberDataRequestCallback *cb;
-} JabberDataRequestData;
-
-static void
-jabber_data_request_cb(JabberStream *js, const char *from, JabberIqType type, 
-                       G_GNUC_UNUSED const char *id, PurpleXmlNode *packet,
-                       gpointer data)
-{
-	JabberDataRequestData *request_data = (JabberDataRequestData *) data;
-	gpointer userdata = request_data->userdata;
-	gchar *alt = request_data->alt;
-	gboolean ephemeral = request_data->ephemeral;
-	JabberDataRequestCallback *cb = request_data->cb;
-
-	PurpleXmlNode *data_element = purple_xmlnode_get_child(packet, "data");
-	PurpleXmlNode *item_not_found = purple_xmlnode_get_child(packet, "item-not-found");
-
-	/* did we get a data element as result? */
-	if (data_element && type == JABBER_IQ_RESULT) {
-		JabberData *data = jabber_data_create_from_xml(data_element);
-
-		if (data && !ephemeral) {
-			jabber_data_associate_remote(js, from, data);
-		}
-		cb(data, alt, userdata);
-	} else if (item_not_found) {
-		purple_debug_info("jabber",
-			"Responder didn't recognize requested data\n");
-		cb(NULL, alt, userdata);
-	} else {
-		purple_debug_warning("jabber", "Unknown response to data request\n");
-		cb(NULL, alt, userdata);
-	}
-
-	g_free(request_data);
-}
-
-void
-jabber_data_request(JabberStream *js, const gchar *cid, const gchar *who,
-    gchar *alt, gboolean ephemeral, JabberDataRequestCallback cb,
-    gpointer userdata)
-{
-	JabberIq *request;
-	PurpleXmlNode *data_request;
-	JabberDataRequestData *data;
-
-	g_return_if_fail(cid != NULL);
-	g_return_if_fail(who != NULL);
-	g_return_if_fail(alt != NULL);
-
-	request = jabber_iq_new(js, JABBER_IQ_GET);
-	data_request = jabber_data_get_xml_request(cid);
-	data = g_new0(JabberDataRequestData, 1);
-
-	data->userdata = userdata;
-	data->alt = alt;
-	data->ephemeral = ephemeral;
-	data->cb = cb;
-
-	purple_xmlnode_set_attrib(request->node, "to", who);
-	jabber_iq_set_callback(request, jabber_data_request_cb, data);
-	purple_xmlnode_insert_child(request->node, data_request);
-	jabber_iq_send(request);
-}
-
-const JabberData *
-jabber_data_find_local_by_alt(const gchar *alt)
-{
-	purple_debug_info("jabber", "looking up local data object with alt = %s\n", alt);
-	return g_hash_table_lookup(local_data_by_alt, alt);
-}
-
-const JabberData *
-jabber_data_find_local_by_cid(const gchar *cid)
-{
-	purple_debug_info("jabber", "lookup local data object with cid = %s\n", cid);
-	return g_hash_table_lookup(local_data_by_cid, cid);
-}
-
-const JabberData *
-jabber_data_find_remote_by_cid(JabberStream *js, const gchar *who,
-    const gchar *cid)
-{
-	const JabberData *data = g_hash_table_lookup(remote_data_by_cid, cid);
-	purple_debug_info("jabber", "lookup remote data object with cid = %s\n", cid);
-
-	if (data == NULL) {
-		gchar *jid_cid =
-			g_strdup_printf("%s@%s/%s%s%s", js->user->node, js->user->domain,
-			    js->user->resource, who, cid);
-		purple_debug_info("jabber",
-		    "didn't find BoB object by pure CID, try including JIDs: %s\n",
-		    jid_cid);
-		data = g_hash_table_lookup(remote_data_by_cid, jid_cid);
-		g_free(jid_cid);
-	}
-	return data;
-}
-
-void
-jabber_data_associate_local(JabberData *data, const gchar *alt)
-{
-	g_return_if_fail(data != NULL);
-
-	purple_debug_info("jabber", "associating local data object\n alt = %s, cid = %s\n",
-		alt , jabber_data_get_cid(data));
-	if (alt)
-		g_hash_table_insert(local_data_by_alt, g_strdup(alt), data);
-	g_hash_table_insert(local_data_by_cid, g_strdup(jabber_data_get_cid(data)),
-		data);
-}
-
-void
-jabber_data_associate_remote(JabberStream *js, const gchar *who, JabberData *data)
-{
-	gchar *cid;
-
-	g_return_if_fail(data != NULL);
-
-	if (jabber_data_has_valid_hash(data)) {
-		cid = g_strdup(jabber_data_get_cid(data));
-	} else {
-		cid = g_strdup_printf("%s@%s/%s%s%s", js->user->node, js->user->domain,
-		    js->user->resource, who, jabber_data_get_cid(data));
-	}
-
-	purple_debug_info("jabber", "associating remote BoB object with cid = %s\n",
-		cid);
-
-	g_hash_table_insert(remote_data_by_cid, cid, data);
-}
-
-/* Handles iq requests. */
-static void
-jabber_data_parse(JabberStream *js, const char *who,
-                  G_GNUC_UNUSED JabberIqType type, const char *id,
-                  PurpleXmlNode *data_node)
-{
-	JabberIq *result = NULL;
-	const char *cid = purple_xmlnode_get_attrib(data_node, "cid");
-	const JabberData *data = cid ? jabber_data_find_local_by_cid(cid) : NULL;
-
-	if (!data) {
-		PurpleXmlNode *item_not_found = purple_xmlnode_new("item-not-found");
-
-		result = jabber_iq_new(js, JABBER_IQ_ERROR);
-		if (who)
-			purple_xmlnode_set_attrib(result->node, "to", who);
-		purple_xmlnode_set_attrib(result->node, "id", id);
-		purple_xmlnode_insert_child(result->node, item_not_found);
-	} else {
-		result = jabber_iq_new(js, JABBER_IQ_RESULT);
-		if (who)
-			purple_xmlnode_set_attrib(result->node, "to", who);
-		purple_xmlnode_set_attrib(result->node, "id", id);
-		purple_xmlnode_insert_child(result->node,
-							 jabber_data_get_xml_definition(data));
-		/* if the data object is temporary, destroy it and remove the references
-		 to it */
-		if (data->ephemeral) {
-			g_hash_table_remove(local_data_by_cid, cid);
-		}
-	}
-	jabber_iq_send(result);
-}
-
-void
-jabber_data_init(void)
-{
-	if (purple_debug_is_verbose())
-		purple_debug_misc("jabber", "creating hash tables for data objects");
-	local_data_by_alt = g_hash_table_new_full(g_str_hash, g_str_equal,
-		g_free, NULL);
-	local_data_by_cid = g_hash_table_new_full(g_str_hash, g_str_equal,
-		g_free, jabber_data_delete);
-	remote_data_by_cid = g_hash_table_new_full(g_str_hash, g_str_equal,
-		g_free, jabber_data_delete);
-
-	jabber_iq_register_handler("data", NS_BOB, jabber_data_parse);
-}
-
-void
-jabber_data_uninit(void)
-{
-	if (purple_debug_is_verbose())
-		purple_debug_info("jabber", "destroying hash tables for data objects");
-	g_clear_pointer(&local_data_by_alt, g_hash_table_destroy);
-	g_clear_pointer(&local_data_by_cid, g_hash_table_destroy);
-	g_clear_pointer(&remote_data_by_cid, g_hash_table_destroy);
-}
diff --git a/libpurple/protocols/jabber/disco.h b/libpurple/protocols/jabber/disco.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/disco.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * @file disco.h Jabber Service Discovery
- *
- * 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_JABBER_DISCO_H
-#define PURPLE_JABBER_DISCO_H
-
-#include "jabber.h"
-
-typedef struct {
-	const char *jid;  /* MUST */
-	const char *node; /* SHOULD */
-	const char *name; /* MAY */
-} JabberDiscoItem;
-
-typedef void (JabberDiscoInfoCallback)(JabberStream *js, const char *who,
-		JabberCapabilities capabilities, gpointer data);
-
-typedef void (JabberDiscoItemsCallback)(JabberStream *js, const char *jid,
-		const char *node, GSList *items, gpointer data);
-
-void jabber_disco_info_parse(JabberStream *js, const char *from,
-                             JabberIqType type, const char *id, PurpleXmlNode *in_query);
-void jabber_disco_items_parse(JabberStream *js, const char *from,
-                              JabberIqType type, const char *id, PurpleXmlNode *query);
-
-void jabber_disco_items_server(JabberStream *js);
-
-void jabber_disco_info_do(JabberStream *js, const char *who,
-		JabberDiscoInfoCallback *callback, gpointer data);
-
-#endif /* PURPLE_JABBER_DISCO_H */
diff --git a/libpurple/protocols/jabber/disco.c b/libpurple/protocols/jabber/disco.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/disco.c
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
- * purple - Jabber Service Discovery
- *
- * 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 <purple.h>
-
-#include "adhoccommands.h"
-#include "buddy.h"
-#include "disco.h"
-#include "iq.h"
-#include "jabber.h"
-#include "jingle/jingle.h"
-#include "pep.h"
-#include "presence.h"
-#include "roster.h"
-#include "useravatar.h"
-
-struct _jabber_disco_info_cb_data {
-	gpointer data;
-	JabberDiscoInfoCallback *callback;
-};
-
-struct _jabber_disco_items_cb_data {
-	gpointer data;
-	JabberDiscoItemsCallback *callback;
-};
-
-#define SUPPORT_FEATURE(x) { \
-	feature = purple_xmlnode_new_child(query, "feature"); \
-	purple_xmlnode_set_attrib(feature, "var", x); \
-}
-
-static void
-jabber_disco_bytestream_server_cb(JabberStream *js, const char *from,
-                                  G_GNUC_UNUSED JabberIqType type,
-                                  G_GNUC_UNUSED const char *id,
-                                  PurpleXmlNode *packet, gpointer data)
-{
-	JabberBytestreamsStreamhost *sh = data;
-	PurpleXmlNode *query = purple_xmlnode_get_child_with_namespace(packet, "query",
-		NS_BYTESTREAMS);
-
-	if (from && purple_strequal(from, sh->jid) && query != NULL) {
-		PurpleXmlNode *sh_node = purple_xmlnode_get_child(query, "streamhost");
-		if (sh_node) {
-			const char *jid = purple_xmlnode_get_attrib(sh_node, "jid");
-			const char *port = purple_xmlnode_get_attrib(sh_node, "port");
-
-
-			if (jid == NULL || !purple_strequal(jid, from))
-				purple_debug_error("jabber", "Invalid jid(%s) for bytestream.\n",
-						   jid ? jid : "(null)");
-
-			sh->host = g_strdup(purple_xmlnode_get_attrib(sh_node, "host"));
-			sh->zeroconf = g_strdup(purple_xmlnode_get_attrib(sh_node, "zeroconf"));
-			if (port != NULL)
-				sh->port = atoi(port);
-		}
-	}
-
-	purple_debug_info("jabber", "Discovered bytestream proxy server: "
-			  "jid='%s' host='%s' port='%d' zeroconf='%s'\n",
-			   from ? from : "", sh->host ? sh->host : "",
-			   sh->port, sh->zeroconf ? sh->zeroconf : "");
-
-	/* TODO: When we support zeroconf proxies, fix this to handle them */
-	if (!(sh->jid && sh->host && sh->port > 0)) {
-		js->bs_proxies = g_list_remove(js->bs_proxies, sh);
-		jabber_bytestreams_streamhost_free(sh);
-	}
-}
-
-
-void jabber_disco_info_parse(JabberStream *js, const char *from,
-                             JabberIqType type, const char *id,
-                             PurpleXmlNode *in_query)
-{
-	if(type == JABBER_IQ_GET) {
-		PurpleXmlNode *query, *identity, *feature;
-		JabberIq *iq;
-		const char *node = purple_xmlnode_get_attrib(in_query, "node");
-		char *node_uri = NULL;
-
-		/* create custom caps node URI */
-		node_uri = g_strconcat(CAPS0115_NODE, "#", jabber_caps_get_own_hash(js), NULL);
-
-		iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, NS_DISCO_INFO);
-
-		jabber_iq_set_id(iq, id);
-
-		if (from)
-			purple_xmlnode_set_attrib(iq->node, "to", from);
-		query = purple_xmlnode_get_child(iq->node, "query");
-
-		if(node)
-			purple_xmlnode_set_attrib(query, "node", node);
-
-		if(!node || purple_strequal(node, node_uri)) {
-			GList *features, *identities;
-			for(identities = jabber_identities; identities; identities = identities->next) {
-				JabberIdentity *ident = (JabberIdentity*)identities->data;
-				identity = purple_xmlnode_new_child(query, "identity");
-				purple_xmlnode_set_attrib(identity, "category", ident->category);
-				purple_xmlnode_set_attrib(identity, "type", ident->type);
-				if (ident->lang)
-					purple_xmlnode_set_attrib(identity, "xml:lang", ident->lang);
-				if (ident->name)
-					purple_xmlnode_set_attrib(identity, "name", ident->name);
-			}
-			for(features = jabber_features; features; features = features->next) {
-				JabberFeature *feat = (JabberFeature*)features->data;
-				if (!feat->is_enabled || feat->is_enabled(js, feat->namespace)) {
-					feature = purple_xmlnode_new_child(query, "feature");
-					purple_xmlnode_set_attrib(feature, "var", feat->namespace);
-				}
-			}
-		} else {
-			PurpleXmlNode *error, *inf;
-
-			/* XXX: gross hack, implement jabber_iq_set_type or something */
-			purple_xmlnode_set_attrib(iq->node, "type", "error");
-			iq->type = JABBER_IQ_ERROR;
-
-			error = purple_xmlnode_new_child(query, "error");
-			purple_xmlnode_set_attrib(error, "code", "404");
-			purple_xmlnode_set_attrib(error, "type", "cancel");
-			inf = purple_xmlnode_new_child(error, "item-not-found");
-			purple_xmlnode_set_namespace(inf, NS_XMPP_STANZAS);
-		}
-		g_free(node_uri);
-		jabber_iq_send(iq);
-	} else if (type == JABBER_IQ_SET) {
-		/* wtf? seriously. wtf‽ */
-		JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR);
-		PurpleXmlNode *error, *bad_request;
-
-		/* Free the <query/> */
-		purple_xmlnode_free(purple_xmlnode_get_child(iq->node, "query"));
-		/* Add an error */
-		error = purple_xmlnode_new_child(iq->node, "error");
-		purple_xmlnode_set_attrib(error, "type", "modify");
-		bad_request = purple_xmlnode_new_child(error, "bad-request");
-		purple_xmlnode_set_namespace(bad_request, NS_XMPP_STANZAS);
-
-		jabber_iq_set_id(iq, id);
-		if (from)
-			purple_xmlnode_set_attrib(iq->node, "to", from);
-
-		jabber_iq_send(iq);
-	}
-}
-
-static void
-jabber_disco_info_cb(JabberStream *js, const char *from, JabberIqType type,
-                     G_GNUC_UNUSED const char *id, PurpleXmlNode *packet,
-                     gpointer data)
-{
-	struct _jabber_disco_info_cb_data *jdicd = data;
-	PurpleXmlNode *query;
-
-	query = purple_xmlnode_get_child_with_namespace(packet, "query", NS_DISCO_INFO);
-
-	if (type == JABBER_IQ_RESULT && query) {
-		PurpleXmlNode *child;
-		JabberID *jid;
-		JabberBuddy *jb;
-		JabberBuddyResource *jbr = NULL;
-		JabberCapabilities capabilities = JABBER_CAP_NONE;
-
-		if((jid = jabber_id_new(from))) {
-			if(jid->resource && (jb = jabber_buddy_find(js, from, TRUE)))
-				jbr = jabber_buddy_find_resource(jb, jid->resource);
-			jabber_id_free(jid);
-		}
-
-		if(jbr)
-			capabilities = jbr->capabilities;
-
-		for(child = query->child; child; child = child->next) {
-			if(child->type != PURPLE_XMLNODE_TYPE_TAG)
-				continue;
-
-			if(purple_strequal(child->name, "identity")) {
-				const char *category = purple_xmlnode_get_attrib(child, "category");
-				const char *type = purple_xmlnode_get_attrib(child, "type");
-				if(!category || !type)
-					continue;
-
-				if(purple_strequal(category, "conference") && purple_strequal(type, "text")) {
-					/* we found a groupchat or MUC server, add it to the list */
-					/* XXX: actually check for protocol/muc or gc-1.0 support */
-					js->chat_servers = g_list_prepend(js->chat_servers, g_strdup(from));
-				} else if(purple_strequal(category, "proxy") && purple_strequal(type, "bytestreams")) {
-					/* This is a bytestream proxy */
-					JabberIq *iq;
-					JabberBytestreamsStreamhost *sh;
-
-					purple_debug_info("jabber", "Found bytestream proxy server: %s\n", from);
-
-					sh = g_new0(JabberBytestreamsStreamhost, 1);
-					sh->jid = g_strdup(from);
-					js->bs_proxies = g_list_prepend(js->bs_proxies, sh);
-
-					iq = jabber_iq_new_query(js, JABBER_IQ_GET,
-							NS_BYTESTREAMS);
-					purple_xmlnode_set_attrib(iq->node, "to", sh->jid);
-					jabber_iq_set_callback(iq, jabber_disco_bytestream_server_cb, sh);
-					jabber_iq_send(iq);
-				}
-
-			} else if(purple_strequal(child->name, "feature")) {
-				const char *var = purple_xmlnode_get_attrib(child, "var");
-				if(!var)
-					continue;
-
-				if(purple_strequal(var, "http://jabber.org/protocol/si"))
-					capabilities |= JABBER_CAP_SI;
-				else if(purple_strequal(var, "http://jabber.org/protocol/si/profile/file-transfer"))
-					capabilities |= JABBER_CAP_SI_FILE_XFER;
-				else if(purple_strequal(var, NS_BYTESTREAMS))
-					capabilities |= JABBER_CAP_BYTESTREAMS;
-				else if(purple_strequal(var, "jabber:iq:search"))
-					capabilities |= JABBER_CAP_IQ_SEARCH;
-				else if(purple_strequal(var, "jabber:iq:register"))
-					capabilities |= JABBER_CAP_IQ_REGISTER;
-				else if(purple_strequal(var, NS_PING))
-					capabilities |= JABBER_CAP_PING;
-				else if(purple_strequal(var, NS_DISCO_ITEMS))
-					capabilities |= JABBER_CAP_ITEMS;
-				else if(purple_strequal(var, "http://jabber.org/protocol/commands")) {
-					capabilities |= JABBER_CAP_ADHOC;
-				}
-				else if(purple_strequal(var, NS_IBB)) {
-					purple_debug_info("jabber", "remote supports IBB\n");
-					capabilities |= JABBER_CAP_IBB;
-				}
-			}
-		}
-
-		js->chat_servers = g_list_reverse(js->chat_servers);
-
-		capabilities |= JABBER_CAP_RETRIEVED;
-
-		if(jbr)
-			jbr->capabilities = capabilities;
-
-		if (jdicd && jdicd->callback)
-			jdicd->callback(js, from, capabilities, jdicd->data);
-	} else { /* type == JABBER_IQ_ERROR or query == NULL */
-		JabberID *jid;
-		JabberBuddy *jb;
-		JabberBuddyResource *jbr = NULL;
-		JabberCapabilities capabilities = JABBER_CAP_NONE;
-
-		if((jid = jabber_id_new(from))) {
-			if(jid->resource && (jb = jabber_buddy_find(js, from, TRUE)))
-				jbr = jabber_buddy_find_resource(jb, jid->resource);
-			jabber_id_free(jid);
-		}
-
-		if(jbr)
-			capabilities = jbr->capabilities;
-
-		if (jdicd && jdicd->callback)
-			jdicd->callback(js, from, capabilities, jdicd->data);
-	}
-
-	g_free(jdicd);
-}
-
-void jabber_disco_items_parse(JabberStream *js, const char *from,
-                              JabberIqType type, const char *id,
-                              PurpleXmlNode *query)
-{
-	if(type == JABBER_IQ_GET) {
-		JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_RESULT,
-				NS_DISCO_ITEMS);
-
-		/* preserve node */
-		PurpleXmlNode *iq_query = purple_xmlnode_get_child(iq->node, "query");
-		const char *node = purple_xmlnode_get_attrib(query, "node");
-		if(node)
-			purple_xmlnode_set_attrib(iq_query,"node",node);
-
-		jabber_iq_set_id(iq, id);
-
-		if (from)
-			purple_xmlnode_set_attrib(iq->node, "to", from);
-		jabber_iq_send(iq);
-	}
-}
-
-static void
-jabber_disco_finish_server_info_result_cb(JabberStream *js)
-{
-	const char *ft_proxies;
-
-	/*
-	 * This *should* happen only if the server supports vcard-temp, but there
-	 * are apparently some servers that don't advertise it even though they
-	 * support it.
-	 */
-	jabber_vcard_fetch_mine(js);
-
-	if (js->pep)
-		jabber_avatar_fetch_mine(js);
-
-	/* Yes, please! */
-	jabber_roster_request(js);
-
-	if (js->server_caps & JABBER_CAP_ADHOC) {
-		/* The server supports ad-hoc commands, so let's request the list */
-		jabber_adhoc_server_get_list(js);
-	}
-
-	/* If the server supports blocking, request the block list */
-	if (js->server_caps & JABBER_CAP_BLOCKING) {
-		jabber_request_block_list(js);
-	}
-
-	/* If the server supports carbons, enable them! */
-	if(js->server_caps & JABBER_CAP_MESSAGE_CARBONS) {
-		JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET);
-		PurpleXmlNode *enable = purple_xmlnode_new_child(iq->node, "enable");
-
-		purple_xmlnode_set_namespace(enable, NS_MESSAGE_CARBONS);
-
-		jabber_iq_send(iq);
-	}
-
-	/* If there are manually specified bytestream proxies, query them */
-	ft_proxies = purple_account_get_string(purple_connection_get_account(js->gc), "ft_proxies", NULL);
-	if (ft_proxies) {
-		JabberIq *iq;
-		JabberBytestreamsStreamhost *sh;
-		int i;
-		char *tmp;
-		gchar **ft_proxy_list = g_strsplit(ft_proxies, ",", 0);
-
-		for(i = 0; ft_proxy_list[i]; i++) {
-			g_strstrip(ft_proxy_list[i]);
-			if(!(*ft_proxy_list[i]))
-				continue;
-
-			/* We used to allow specifying a port directly here; get rid of it */
-			if((tmp = strchr(ft_proxy_list[i], ':')))
-				*tmp = '\0';
-
-			sh = g_new0(JabberBytestreamsStreamhost, 1);
-			sh->jid = g_strdup(ft_proxy_list[i]);
-			js->bs_proxies = g_list_prepend(js->bs_proxies, sh);
-
-			iq = jabber_iq_new_query(js, JABBER_IQ_GET, NS_BYTESTREAMS);
-			purple_xmlnode_set_attrib(iq->node, "to", sh->jid);
-			jabber_iq_set_callback(iq, jabber_disco_bytestream_server_cb, sh);
-			jabber_iq_send(iq);
-		}
-
-		g_strfreev(ft_proxy_list);
-	}
-
-}
-
-static void
-jabber_disco_server_info_result_cb(JabberStream *js, const char *from,
-                                   JabberIqType type,
-                                   G_GNUC_UNUSED const char *id,
-                                   PurpleXmlNode *packet,
-                                   G_GNUC_UNUSED gpointer data)
-{
-	PurpleXmlNode *query, *child;
-
-	if (!from || !purple_strequal(from, js->user->domain)) {
-		jabber_disco_finish_server_info_result_cb(js);
-		return;
-	}
-
-	if (type == JABBER_IQ_ERROR) {
-		/* A common way to get here is for the server not to support xmlns http://jabber.org/protocol/disco#info */
-		jabber_disco_finish_server_info_result_cb(js);
-		return;
-	}
-
-	query = purple_xmlnode_get_child(packet, "query");
-
-	if (!query) {
-		jabber_disco_finish_server_info_result_cb(js);
-		return;
-	}
-
-	for (child = purple_xmlnode_get_child(query, "identity"); child;
-	     child = purple_xmlnode_get_next_twin(child)) {
-		const char *category, *type, *name;
-		category = purple_xmlnode_get_attrib(child, "category");
-		type = purple_xmlnode_get_attrib(child, "type");
-		if(purple_strequal(category, "pubsub") && purple_strequal(type, "pep")) {
-			js->pep = TRUE;
-		}
-		if (!purple_strequal(category, "server"))
-			continue;
-		if (!purple_strequal(type, "im"))
-			continue;
-
-		name = purple_xmlnode_get_attrib(child, "name");
-		if (!name)
-			continue;
-
-		g_free(js->server_name);
-		js->server_name = g_strdup(name);
-	}
-
-	for (child = purple_xmlnode_get_child(query, "feature"); child;
-	     child = purple_xmlnode_get_next_twin(child)) {
-		const char *var;
-		var = purple_xmlnode_get_attrib(child, "var");
-		if (!var)
-			continue;
-
-		if (purple_strequal("http://jabber.org/protocol/commands", var)) {
-			js->server_caps |= JABBER_CAP_ADHOC;
-		} else if (purple_strequal(NS_SIMPLE_BLOCKING, var)) {
-			js->server_caps |= JABBER_CAP_BLOCKING;
-		} else if (purple_strequal(NS_MESSAGE_CARBONS, var)) {
-			js->server_caps |= JABBER_CAP_MESSAGE_CARBONS;
-		}
-	}
-
-	jabber_disco_finish_server_info_result_cb(js);
-}
-
-static void
-jabber_disco_server_items_result_cb(JabberStream *js, const char *from,
-                                    JabberIqType type,
-                                    G_GNUC_UNUSED const char *id,
-                                    PurpleXmlNode *packet,
-                                    G_GNUC_UNUSED gpointer data)
-{
-	PurpleXmlNode *query, *child;
-
-	if (!from || !purple_strequal(from, js->user->domain))
-		return;
-
-	if (type == JABBER_IQ_ERROR)
-		return;
-
-	g_clear_list(&js->chat_servers, g_free);
-
-	query = purple_xmlnode_get_child(packet, "query");
-
-	for(child = purple_xmlnode_get_child(query, "item"); child;
-			child = purple_xmlnode_get_next_twin(child)) {
-		JabberIq *iq;
-		const char *jid;
-
-		if(!(jid = purple_xmlnode_get_attrib(child, "jid")))
-			continue;
-
-		/* we don't actually care about the specific nodes,
-		 * so we won't query them */
-		if(purple_xmlnode_get_attrib(child, "node") != NULL)
-			continue;
-
-		iq = jabber_iq_new_query(js, JABBER_IQ_GET, NS_DISCO_INFO);
-		purple_xmlnode_set_attrib(iq->node, "to", jid);
-		jabber_iq_set_callback(iq, jabber_disco_info_cb, NULL);
-		jabber_iq_send(iq);
-	}
-}
-
-void jabber_disco_items_server(JabberStream *js)
-{
-	JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_GET, NS_DISCO_ITEMS);
-
-	purple_xmlnode_set_attrib(iq->node, "to", js->user->domain);
-
-	jabber_iq_set_callback(iq, jabber_disco_server_items_result_cb, NULL);
-	jabber_iq_send(iq);
-
-	iq = jabber_iq_new_query(js, JABBER_IQ_GET, NS_DISCO_INFO);
-	purple_xmlnode_set_attrib(iq->node, "to", js->user->domain);
-	jabber_iq_set_callback(iq, jabber_disco_server_info_result_cb, NULL);
-	jabber_iq_send(iq);
-}
-
-void jabber_disco_info_do(JabberStream *js, const char *who, JabberDiscoInfoCallback *callback, gpointer data)
-{
-	JabberID *jid;
-	JabberBuddy *jb;
-	JabberBuddyResource *jbr = NULL;
-	struct _jabber_disco_info_cb_data *jdicd;
-	JabberIq *iq;
-
-	if((jid = jabber_id_new(who))) {
-		if(jid->resource && (jb = jabber_buddy_find(js, who, TRUE)))
-			jbr = jabber_buddy_find_resource(jb, jid->resource);
-		jabber_id_free(jid);
-	}
-
-	if(jbr && jbr->capabilities & JABBER_CAP_RETRIEVED) {
-		callback(js, who, jbr->capabilities, data);
-		return;
-	}
-
-	jdicd = g_new0(struct _jabber_disco_info_cb_data, 1);
-	jdicd->data = data;
-	jdicd->callback = callback;
-
-	iq = jabber_iq_new_query(js, JABBER_IQ_GET, NS_DISCO_INFO);
-	purple_xmlnode_set_attrib(iq->node, "to", who);
-
-	jabber_iq_set_callback(iq, jabber_disco_info_cb, jdicd);
-	jabber_iq_send(iq);
-}
-
diff --git a/libpurple/protocols/jabber/ibb.h b/libpurple/protocols/jabber/ibb.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/ibb.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * purple - Handling of XEP-0047: In-Band Bytestreams.
- *
- * 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_JABBER_IBB_H
-#define PURPLE_JABBER_IBB_H
-
-#include "jabber.h"
-#include "iq.h"
-
-typedef struct _JabberIBBSession JabberIBBSession;
-
-typedef void
-(JabberIBBDataCallback)(JabberIBBSession *, const gpointer data, gsize size);
-
-typedef void (JabberIBBOpenedCallback)(JabberIBBSession *);
-typedef void (JabberIBBClosedCallback)(JabberIBBSession *);
-typedef void (JabberIBBErrorCallback)(JabberIBBSession *);
-typedef void (JabberIBBSentCallback)(JabberIBBSession *);
-
-typedef gboolean (JabberIBBOpenHandler)(JabberStream *js, const char *from,
-                                        const char *id, PurpleXmlNode *open);
-
-typedef enum {
-	JABBER_IBB_SESSION_NOT_OPENED,
-	JABBER_IBB_SESSION_OPENED,
-	JABBER_IBB_SESSION_CLOSED,
-	JABBER_IBB_SESSION_ERROR
-} JabberIBBSessionState;
-
-struct _JabberIBBSession {
-	JabberStream *js;
-	gchar *who;
-	gchar *sid;
-	gchar *id;
-	guint16 send_seq;
-	guint16 recv_seq;
-	gsize block_size;
-
-	/* session state */
-	JabberIBBSessionState state;
-
-	/* user data (f.ex. a handle to a PurpleXfer) */
-	gpointer user_data;
-
-	/* callbacks */
-	JabberIBBOpenedCallback *opened_cb;
-	JabberIBBSentCallback *data_sent_cb;
-	JabberIBBClosedCallback *closed_cb;
-	/* callback for receiving data */
-	JabberIBBDataCallback *data_received_cb;
-	JabberIBBErrorCallback *error_cb;
-
-	/* store the last sent IQ (to permit cancel of callback) */
-	gchar *last_iq_id;
-};
-
-JabberIBBSession *jabber_ibb_session_create(JabberStream *js, const gchar *sid,
-	const gchar *who, gpointer user_data);
-JabberIBBSession *jabber_ibb_session_create_from_xmlnode(JabberStream *js,
-	const gchar *from, const gchar *id, PurpleXmlNode *open, gpointer user_data);
-
-void jabber_ibb_session_destroy(JabberIBBSession *sess);
-
-void jabber_ibb_session_set_opened_callback(JabberIBBSession *sess,
-	JabberIBBOpenedCallback *cb);
-void jabber_ibb_session_set_data_sent_callback(JabberIBBSession *sess,
-	JabberIBBSentCallback *cb);
-void jabber_ibb_session_set_closed_callback(JabberIBBSession *sess,
-	JabberIBBClosedCallback *cb);
-void jabber_ibb_session_set_data_received_callback(JabberIBBSession *sess,
-	JabberIBBDataCallback *cb);
-void jabber_ibb_session_set_error_callback(JabberIBBSession *sess,
-	JabberIBBErrorCallback *cb);
-
-void jabber_ibb_session_open(JabberIBBSession *sess);
-void jabber_ibb_session_close(JabberIBBSession *sess);
-void jabber_ibb_session_send_data(JabberIBBSession *sess, gconstpointer data,
-	gsize size);
-
-JabberIBBSessionState jabber_ibb_session_get_state(const JabberIBBSession *sess);
-
-gsize jabber_ibb_session_get_block_size(const JabberIBBSession *sess);
-
-/* get maximum size data block to send (in bytes)
- (before encoded to BASE64) */
-gsize jabber_ibb_session_get_max_data_size(const JabberIBBSession *sess);
-
-gpointer jabber_ibb_session_get_user_data(JabberIBBSession *sess);
-
-/* add a handler for open session */
-void jabber_ibb_register_open_handler(JabberIBBOpenHandler *cb);
-void jabber_ibb_unregister_open_handler(JabberIBBOpenHandler *cb);
-
-void jabber_ibb_init(void);
-void jabber_ibb_uninit(void);
-
-#endif /* PURPLE_JABBER_IBB_H */
diff --git a/libpurple/protocols/jabber/ibb.c b/libpurple/protocols/jabber/ibb.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/ibb.c
+++ /dev/null
@@ -1,514 +0,0 @@
-/*
- * purple - Handling of XEP-0047: In-Band Bytestreams.
- *
- * 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 <math.h>
-
-#include <purple.h>
-
-#include "ibb.h"
-
-#define JABBER_IBB_SESSION_DEFAULT_BLOCK_SIZE 4096
-
-static GHashTable *jabber_ibb_sessions = NULL;
-static GList *open_handlers = NULL;
-
-static JabberStream *jabber_ibb_session_get_js(JabberIBBSession *sess);
-
-JabberIBBSession *
-jabber_ibb_session_create(JabberStream *js, const gchar *sid, const gchar *who,
-	gpointer user_data)
-{
-	JabberIBBSession *sess = g_new0(JabberIBBSession, 1);
-	sess->js = js;
-	if (sid) {
-		sess->sid = g_strdup(sid);
-	} else {
-		sess->sid = jabber_get_next_id(js);
-	}
-	sess->who = g_strdup(who);
-	sess->block_size = JABBER_IBB_SESSION_DEFAULT_BLOCK_SIZE;
-	sess->state = JABBER_IBB_SESSION_NOT_OPENED;
-	sess->user_data = user_data;
-
-	g_hash_table_insert(jabber_ibb_sessions, sess->sid, sess);
-
-	return sess;
-}
-
-JabberIBBSession *
-jabber_ibb_session_create_from_xmlnode(JabberStream *js, const char *from,
-	const char *id, PurpleXmlNode *open, gpointer user_data)
-{
-	JabberIBBSession *sess = NULL;
-	const gchar *sid = purple_xmlnode_get_attrib(open, "sid");
-	const gchar *block_size = purple_xmlnode_get_attrib(open, "block-size");
-
-	if (!open) {
-		return NULL;
-	}
-
-	if (!sid || !block_size) {
-		purple_debug_error("jabber",
-			"IBB session open tag requires sid and block-size attributes\n");
-		return NULL;
-	}
-
-	sess = jabber_ibb_session_create(js, sid, from, user_data);
-	sess->id = g_strdup(id);
-	sess->block_size = atoi(block_size);
-	/* if we create a session from an incoming <open/> request, it means the
-	  session is immediately open... */
-	sess->state = JABBER_IBB_SESSION_OPENED;
-
-	return sess;
-}
-
-void
-jabber_ibb_session_destroy(JabberIBBSession *sess)
-{
-	purple_debug_info("jabber", "IBB: destroying session %p %s\n", sess,
-		sess->sid);
-
-	if (jabber_ibb_session_get_state(sess) == JABBER_IBB_SESSION_OPENED) {
-		jabber_ibb_session_close(sess);
-	}
-
-	if (sess->last_iq_id) {
-		purple_debug_info("jabber", "IBB: removing callback for <iq/> %s\n",
-			sess->last_iq_id);
-		jabber_iq_remove_callback_by_id(jabber_ibb_session_get_js(sess),
-			sess->last_iq_id);
-		g_free(sess->last_iq_id);
-		sess->last_iq_id = NULL;
-	}
-
-	g_hash_table_remove(jabber_ibb_sessions, sess->sid);
-	g_free(sess->id);
-	g_free(sess->sid);
-	g_free(sess->who);
-	g_free(sess);
-}
-
-static const gchar *
-jabber_ibb_session_get_sid(const JabberIBBSession *sess)
-{
-	return sess->sid;
-}
-
-static JabberStream *
-jabber_ibb_session_get_js(JabberIBBSession *sess)
-{
-	return sess->js;
-}
-
-static const gchar *
-jabber_ibb_session_get_who(const JabberIBBSession *sess)
-{
-	return sess->who;
-}
-
-static guint16
-jabber_ibb_session_get_send_seq(const JabberIBBSession *sess)
-{
-	return sess->send_seq;
-}
-
-static guint16
-jabber_ibb_session_get_recv_seq(const JabberIBBSession *sess)
-{
-	return sess->recv_seq;
-}
-
-JabberIBBSessionState
-jabber_ibb_session_get_state(const JabberIBBSession *sess)
-{
-	return sess->state;
-}
-
-gsize
-jabber_ibb_session_get_block_size(const JabberIBBSession *sess)
-{
-	return sess->block_size;
-}
-
-gsize
-jabber_ibb_session_get_max_data_size(const JabberIBBSession *sess)
-{
-	return (gsize) floor((sess->block_size - 2) * (float) 3 / 4);
-}
-
-gpointer
-jabber_ibb_session_get_user_data(JabberIBBSession *sess)
-{
-	return sess->user_data;
-}
-
-void
-jabber_ibb_session_set_opened_callback(JabberIBBSession *sess,
-	JabberIBBOpenedCallback *cb)
-{
-	sess->opened_cb = cb;
-}
-
-void
-jabber_ibb_session_set_data_sent_callback(JabberIBBSession *sess,
-	JabberIBBSentCallback *cb)
-{
-	sess->data_sent_cb = cb;
-}
-
-void
-jabber_ibb_session_set_closed_callback(JabberIBBSession *sess,
-	JabberIBBClosedCallback *cb)
-{
-	sess->closed_cb = cb;
-}
-
-void
-jabber_ibb_session_set_data_received_callback(JabberIBBSession *sess,
-	JabberIBBDataCallback *cb)
-{
-	sess->data_received_cb = cb;
-}
-
-void
-jabber_ibb_session_set_error_callback(JabberIBBSession *sess,
-	JabberIBBErrorCallback *cb)
-{
-	sess->error_cb = cb;
-}
-
-static void
-jabber_ibb_session_opened_cb(G_GNUC_UNUSED JabberStream *js,
-                             G_GNUC_UNUSED const char *from,
-                             JabberIqType type, G_GNUC_UNUSED const char *id,
-                             G_GNUC_UNUSED PurpleXmlNode *packet,
-                             gpointer data)
-{
-	JabberIBBSession *sess = (JabberIBBSession *) data;
-
-	if (type == JABBER_IQ_ERROR) {
-		sess->state = JABBER_IBB_SESSION_ERROR;
-	} else {
-		sess->state = JABBER_IBB_SESSION_OPENED;
-	}
-
-	if (sess->opened_cb) {
-		sess->opened_cb(sess);
-	}
-}
-
-void
-jabber_ibb_session_open(JabberIBBSession *sess)
-{
-	if (jabber_ibb_session_get_state(sess) != JABBER_IBB_SESSION_NOT_OPENED) {
-		purple_debug_error("jabber",
-			"jabber_ibb_session called on an already open stream\n");
-	} else {
-		JabberIq *set = jabber_iq_new(sess->js, JABBER_IQ_SET);
-		PurpleXmlNode *open = purple_xmlnode_new("open");
-		gchar block_size[10];
-
-		purple_xmlnode_set_attrib(set->node, "to", jabber_ibb_session_get_who(sess));
-		purple_xmlnode_set_namespace(open, NS_IBB);
-		purple_xmlnode_set_attrib(open, "sid", jabber_ibb_session_get_sid(sess));
-		g_snprintf(block_size, sizeof(block_size), "%" G_GSIZE_FORMAT,
-			jabber_ibb_session_get_block_size(sess));
-		purple_xmlnode_set_attrib(open, "block-size", block_size);
-		purple_xmlnode_insert_child(set->node, open);
-
-		jabber_iq_set_callback(set, jabber_ibb_session_opened_cb, sess);
-
-		jabber_iq_send(set);
-	}
-}
-
-void
-jabber_ibb_session_close(JabberIBBSession *sess)
-{
-	JabberIBBSessionState state = jabber_ibb_session_get_state(sess);
-
-	if (state != JABBER_IBB_SESSION_OPENED && state != JABBER_IBB_SESSION_ERROR) {
-		purple_debug_error("jabber",
-			"jabber_ibb_session_close called on a session that has not been"
-			"opened\n");
-	} else {
-		JabberIq *set = jabber_iq_new(jabber_ibb_session_get_js(sess),
-			JABBER_IQ_SET);
-		PurpleXmlNode *close = purple_xmlnode_new("close");
-
-		purple_xmlnode_set_attrib(set->node, "to", jabber_ibb_session_get_who(sess));
-		purple_xmlnode_set_namespace(close, NS_IBB);
-		purple_xmlnode_set_attrib(close, "sid", jabber_ibb_session_get_sid(sess));
-		purple_xmlnode_insert_child(set->node, close);
-		jabber_iq_send(set);
-		sess->state = JABBER_IBB_SESSION_CLOSED;
-	}
-}
-
-static void
-jabber_ibb_session_send_acknowledge_cb(G_GNUC_UNUSED JabberStream *js,
-                                       G_GNUC_UNUSED const char *from,
-                                       JabberIqType type,
-                                       G_GNUC_UNUSED const char *id,
-                                       G_GNUC_UNUSED PurpleXmlNode *packet,
-                                       gpointer data)
-{
-	JabberIBBSession *sess = (JabberIBBSession *) data;
-
-	if (sess) {
-		/* reset callback */
-		g_free(sess->last_iq_id);
-		sess->last_iq_id = NULL;
-
-		if (type == JABBER_IQ_ERROR) {
-			jabber_ibb_session_close(sess);
-			sess->state = JABBER_IBB_SESSION_ERROR;
-
-			if (sess->error_cb) {
-				sess->error_cb(sess);
-			}
-		} else {
-			if (sess->data_sent_cb) {
-				sess->data_sent_cb(sess);
-			}
-		}
-	} else {
-		/* the session has gone away, it was probably cancelled */
-		purple_debug_info("jabber",
-			"got response from send data, but IBB session is no longer active\n");
-	}
-}
-
-void
-jabber_ibb_session_send_data(JabberIBBSession *sess, gconstpointer data,
-                             gsize size)
-{
-	JabberIBBSessionState state = jabber_ibb_session_get_state(sess);
-
-	purple_debug_info("jabber", "sending data block of %" G_GSIZE_FORMAT " bytes on IBB stream\n",
-		size);
-
-	if (state != JABBER_IBB_SESSION_OPENED) {
-		purple_debug_error("jabber",
-			"trying to send data on a non-open IBB session\n");
-	} else if (size > jabber_ibb_session_get_max_data_size(sess)) {
-		purple_debug_error("jabber",
-			"trying to send a too large packet in the IBB session\n");
-	} else {
-		JabberIq *set = jabber_iq_new(jabber_ibb_session_get_js(sess),
-			JABBER_IQ_SET);
-		PurpleXmlNode *data_element = purple_xmlnode_new("data");
-		char *base64 = g_base64_encode(data, size);
-		char seq[10];
-		g_snprintf(seq, sizeof(seq), "%u", jabber_ibb_session_get_send_seq(sess));
-
-		purple_xmlnode_set_attrib(set->node, "to", jabber_ibb_session_get_who(sess));
-		purple_xmlnode_set_namespace(data_element, NS_IBB);
-		purple_xmlnode_set_attrib(data_element, "sid", jabber_ibb_session_get_sid(sess));
-		purple_xmlnode_set_attrib(data_element, "seq", seq);
-		purple_xmlnode_insert_data(data_element, base64, -1);
-
-		purple_xmlnode_insert_child(set->node, data_element);
-
-		purple_debug_info("jabber",
-			"IBB: setting send <iq/> callback for session %p %s\n", sess,
-			sess->sid);
-		jabber_iq_set_callback(set, jabber_ibb_session_send_acknowledge_cb, sess);
-		sess->last_iq_id = g_strdup(purple_xmlnode_get_attrib(set->node, "id"));
-		purple_debug_info("jabber", "IBB: set sess->last_iq_id: %s\n",
-			sess->last_iq_id);
-		jabber_iq_send(set);
-
-		g_free(base64);
-		(sess->send_seq)++;
-	}
-}
-
-static void
-jabber_ibb_send_error_response(JabberStream *js, const char *to, const char *id)
-{
-	JabberIq *result = jabber_iq_new(js, JABBER_IQ_ERROR);
-	PurpleXmlNode *error = purple_xmlnode_new("error");
-	PurpleXmlNode *item_not_found = purple_xmlnode_new("item-not-found");
-
-	purple_xmlnode_set_namespace(item_not_found, NS_XMPP_STANZAS);
-	purple_xmlnode_set_attrib(error, "code", "440");
-	purple_xmlnode_set_attrib(error, "type", "cancel");
-	jabber_iq_set_id(result, id);
-	purple_xmlnode_set_attrib(result->node, "to", to);
-	purple_xmlnode_insert_child(error, item_not_found);
-	purple_xmlnode_insert_child(result->node, error);
-
-	jabber_iq_send(result);
-}
-
-/* Handle incoming packet. */
-static void
-jabber_ibb_parse(JabberStream *js, const char *who,
-                 G_GNUC_UNUSED JabberIqType type, const char *id,
-                 PurpleXmlNode *child)
-{
-	const char *name = child->name;
-	gboolean data  = purple_strequal(name, "data");
-	gboolean close = purple_strequal(name, "close");
-	gboolean open  = purple_strequal(name, "open");
-	const gchar *sid = (data || close) ?
-		purple_xmlnode_get_attrib(child, "sid") : NULL;
-	JabberIBBSession *sess =
-		sid ? g_hash_table_lookup(jabber_ibb_sessions, sid) : NULL;
-
-	if (sess) {
-
-		if (!purple_strequal(who, jabber_ibb_session_get_who(sess))) {
-			/* the iq comes from a different JID than the remote JID of the
-			  session, ignore it */
-			purple_debug_error("jabber",
-				"Got IBB iq from wrong JID, ignoring\n");
-		} else if (data) {
-			const gchar *seq_attr = purple_xmlnode_get_attrib(child, "seq");
-			guint16 seq = (seq_attr ? atoi(seq_attr) : 0);
-
-			/* reject the data, and set the session in error if we get an
-			  out-of-order packet */
-			if (seq_attr && seq == jabber_ibb_session_get_recv_seq(sess)) {
-				/* sequence # is the expected... */
-				JabberIq *result = jabber_iq_new(js, JABBER_IQ_RESULT);
-
-				jabber_iq_set_id(result, id);
-				purple_xmlnode_set_attrib(result->node, "to", who);
-
-				if (sess->data_received_cb) {
-					gchar *base64 = purple_xmlnode_get_data(child);
-					gsize size;
-					gpointer rawdata = g_base64_decode(base64, &size);
-
-					g_free(base64);
-
-					if (rawdata) {
-						purple_debug_info("jabber",
-							"got %" G_GSIZE_FORMAT " bytes of data on IBB stream\n",
-							size);
-						/* we accept other clients to send up to block-size
-						 of _unencoded_ data, since there's been some confusions
-						 regarding the interpretation of this attribute
-						 (including previous versions of libpurple) */
-						if (size > jabber_ibb_session_get_block_size(sess)) {
-							purple_debug_error("jabber",
-								"IBB: received a too large packet\n");
-							if (sess->error_cb)
-								sess->error_cb(sess);
-							g_free(rawdata);
-							return;
-						} else {
-							purple_debug_info("jabber",
-								"calling IBB callback for received data\n");
-							sess->data_received_cb(sess, rawdata, size);
-						}
-						g_free(rawdata);
-					} else {
-						purple_debug_error("jabber",
-							"IBB: invalid BASE64 data received\n");
-						if (sess->error_cb)
-							sess->error_cb(sess);
-						return;
-
-					}
-				}
-
-				(sess->recv_seq)++;
-				jabber_iq_send(result);
-
-			} else {
-				purple_debug_error("jabber",
-					"Received an out-of-order/invalid IBB packet\n");
-				sess->state = JABBER_IBB_SESSION_ERROR;
-
-				if (sess->error_cb) {
-					sess->error_cb(sess);
-				}
-			}
-		} else if (close) {
-			sess->state = JABBER_IBB_SESSION_CLOSED;
-			purple_debug_info("jabber", "IBB: received close\n");
-
-			if (sess->closed_cb) {
-				purple_debug_info("jabber", "IBB: calling closed handler\n");
-				sess->closed_cb(sess);
-			}
-		}
-	} else if (open) {
-		JabberIq *result;
-		const GList *iterator;
-
-		/* run all open handlers registered until one returns true */
-		for (iterator = open_handlers ; iterator ;
-			 iterator = g_list_next(iterator)) {
-			JabberIBBOpenHandler *handler = iterator->data;
-
-			if (handler(js, who, id, child)) {
-				result = jabber_iq_new(js, JABBER_IQ_RESULT);
-				purple_xmlnode_set_attrib(result->node, "to", who);
-				jabber_iq_set_id(result, id);
-				jabber_iq_send(result);
-				return;
-			}
-		}
-		/* no open callback returned success, reject */
-		jabber_ibb_send_error_response(js, who, id);
-	} else {
-		/* send error reply */
-		jabber_ibb_send_error_response(js, who, id);
-	}
-}
-
-void
-jabber_ibb_register_open_handler(JabberIBBOpenHandler *cb)
-{
-	open_handlers = g_list_append(open_handlers, cb);
-}
-
-void
-jabber_ibb_unregister_open_handler(JabberIBBOpenHandler *cb)
-{
-	open_handlers = g_list_remove(open_handlers, cb);
-}
-
-void
-jabber_ibb_init(void)
-{
-	jabber_ibb_sessions = g_hash_table_new(g_str_hash, g_str_equal);
-
-	jabber_add_feature(NS_IBB, NULL);
-
-	jabber_iq_register_handler("close", NS_IBB, jabber_ibb_parse);
-	jabber_iq_register_handler("data", NS_IBB, jabber_ibb_parse);
-	jabber_iq_register_handler("open", NS_IBB, jabber_ibb_parse);
-}
-
-void
-jabber_ibb_uninit(void)
-{
-	g_clear_pointer(&jabber_ibb_sessions, g_hash_table_destroy);
-	g_clear_list(&open_handlers, NULL);
-}
diff --git a/libpurple/protocols/jabber/iq.h b/libpurple/protocols/jabber/iq.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/iq.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/**
- * @file iq.h JabberID handlers
- *
- * 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_JABBER_IQ_H
-#define PURPLE_JABBER_IQ_H
-
-#include <purple.h>
-
-typedef enum {
-	JABBER_IQ_SET,
-	JABBER_IQ_GET,
-	JABBER_IQ_RESULT,
-	JABBER_IQ_ERROR,
-	JABBER_IQ_NONE
-} JabberIqType;
-
-#include "jabber.h"
-
-typedef struct _JabberIq JabberIq;
-typedef struct _JabberIqCallbackData  JabberIqCallbackData;
-
-/**
- * A JabberIqHandler is called to process an incoming IQ stanza.
- * Handlers typically process unsolicited incoming GETs or SETs for their
- * registered namespace, but may be called to handle the results of a
- * GET or SET that we generated if no JabberIqCallback was generated
- * The handler may be called for the results of a GET or SET (RESULT or ERROR)
- * that we generated
- * if the generating function did not register a JabberIqCallback.
- *
- * @param js    The JabberStream object.
- * @param from  The remote entity (the from attribute on the <iq/> stanza)
- * @param type  The IQ type.
- * @param id    The IQ id (the id attribute on the <iq/> stanza)
- * @param child The child element of the <iq/> stanza that matches the name
- *              and namespace registered with jabber_iq_register_handler.
- *
- * @see jabber_iq_register_handler()
- * @see JabberIqCallback
- */
-typedef void (JabberIqHandler)(JabberStream *js, const char *from,
-                               JabberIqType type, const char *id,
-                               PurpleXmlNode *child);
-
-/**
- * A JabberIqCallback is called to process the results of a GET or SET that
- * we send to a remote entity. The callback is matched based on the id
- * of the incoming stanza (which matches the one on the initial stanza).
- *
- * @param js     The JabberStream object.
- * @param from   The remote entity (the from attribute on the <iq/> stanza)
- * @param type   The IQ type. The only possible values are JABBER_IQ_RESULT
- *               and JABBER_IQ_ERROR.
- * @param id     The IQ id (the id attribute on the <iq/> stanza)
- * @param packet The <iq/> stanza
- * @param data   The callback data passed to jabber_iq_set_callback()
- *
- * @see jabber_iq_set_callback()
- */
-typedef void (JabberIqCallback)(JabberStream *js, const char *from,
-                                JabberIqType type, const char *id,
-                                PurpleXmlNode *packet, gpointer data);
-
-struct _JabberIq {
-	JabberIqType type;
-	char *id;
-	PurpleXmlNode *node;
-
-	JabberIqCallback *callback;
-	gpointer callback_data;
-
-	JabberStream *js;
-};
-
-JabberIq *jabber_iq_new(JabberStream *js, JabberIqType type);
-JabberIq *jabber_iq_new_query(JabberStream *js, JabberIqType type,
-		const char *xmlns);
-
-void jabber_iq_parse(JabberStream *js, PurpleXmlNode *packet);
-
-void jabber_iq_callbackdata_free(JabberIqCallbackData *jcd);
-void jabber_iq_remove_callback_by_id(JabberStream *js, const char *id);
-void jabber_iq_set_callback(JabberIq *iq, JabberIqCallback *cb, gpointer data);
-void jabber_iq_set_id(JabberIq *iq, const char *id);
-
-void jabber_iq_send(JabberIq *iq);
-void jabber_iq_free(JabberIq *iq);
-
-void jabber_iq_init(void);
-void jabber_iq_uninit(void);
-
-void jabber_iq_register_handler(const char *node, const char *xmlns,
-                                JabberIqHandler *func);
-
-/* Connected to namespace-handler registration signals */
-void jabber_iq_signal_register(const gchar *node, const gchar *xmlns);
-void jabber_iq_signal_unregister(const gchar *node, const gchar *xmlns);
-
-#endif /* PURPLE_JABBER_IQ_H */
diff --git a/libpurple/protocols/jabber/iq.c b/libpurple/protocols/jabber/iq.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/iq.c
+++ /dev/null
@@ -1,562 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "buddy.h"
-#include "disco.h"
-#include "iq.h"
-#include "jingle/jingle.h"
-#include "oob.h"
-#include "roster.h"
-#include "si.h"
-#include "ping.h"
-#include "adhoccommands.h"
-#include "data.h"
-#include "ibb.h"
-
-static GHashTable *iq_handlers = NULL;
-static GHashTable *signal_iq_handlers = NULL;
-
-struct _JabberIqCallbackData {
-	JabberIqCallback *callback;
-	gpointer data;
-	JabberID *to;
-};
-
-void jabber_iq_callbackdata_free(JabberIqCallbackData *jcd)
-{
-	jabber_id_free(jcd->to);
-	g_free(jcd);
-}
-
-JabberIq *jabber_iq_new(JabberStream *js, JabberIqType type)
-{
-	JabberIq *iq;
-
-	iq = g_new0(JabberIq, 1);
-
-	iq->type = type;
-
-	iq->node = purple_xmlnode_new("iq");
-	switch(iq->type) {
-		case JABBER_IQ_SET:
-			purple_xmlnode_set_attrib(iq->node, "type", "set");
-			break;
-		case JABBER_IQ_GET:
-			purple_xmlnode_set_attrib(iq->node, "type", "get");
-			break;
-		case JABBER_IQ_ERROR:
-			purple_xmlnode_set_attrib(iq->node, "type", "error");
-			break;
-		case JABBER_IQ_RESULT:
-			purple_xmlnode_set_attrib(iq->node, "type", "result");
-			break;
-		case JABBER_IQ_NONE:
-			/* this shouldn't ever happen */
-			break;
-	}
-
-	iq->js = js;
-
-	if(type == JABBER_IQ_GET || type == JABBER_IQ_SET) {
-		iq->id = jabber_get_next_id(js);
-		purple_xmlnode_set_attrib(iq->node, "id", iq->id);
-	}
-
-	return iq;
-}
-
-JabberIq *jabber_iq_new_query(JabberStream *js, JabberIqType type,
-		const char *xmlns)
-{
-	JabberIq *iq = jabber_iq_new(js, type);
-	PurpleXmlNode *query;
-
-	query = purple_xmlnode_new_child(iq->node, "query");
-	purple_xmlnode_set_namespace(query, xmlns);
-
-	return iq;
-}
-
-void
-jabber_iq_set_callback(JabberIq *iq, JabberIqCallback *callback, gpointer data)
-{
-	iq->callback = callback;
-	iq->callback_data = data;
-}
-
-void jabber_iq_set_id(JabberIq *iq, const char *id)
-{
-	g_free(iq->id);
-
-	if(id) {
-		purple_xmlnode_set_attrib(iq->node, "id", id);
-		iq->id = g_strdup(id);
-	} else {
-		purple_xmlnode_remove_attrib(iq->node, "id");
-		iq->id = NULL;
-	}
-}
-
-void jabber_iq_send(JabberIq *iq)
-{
-	JabberIqCallbackData *jcd;
-	g_return_if_fail(iq != NULL);
-
-	jabber_send(iq->js, iq->node);
-
-	if(iq->id && iq->callback) {
-		jcd = g_new0(JabberIqCallbackData, 1);
-		jcd->callback = iq->callback;
-		jcd->data = iq->callback_data;
-		jcd->to = jabber_id_new(purple_xmlnode_get_attrib(iq->node, "to"));
-
-		g_hash_table_insert(iq->js->iq_callbacks, g_strdup(iq->id), jcd);
-	}
-
-	jabber_iq_free(iq);
-}
-
-void jabber_iq_free(JabberIq *iq)
-{
-	g_return_if_fail(iq != NULL);
-
-	g_free(iq->id);
-	purple_xmlnode_free(iq->node);
-	g_free(iq);
-}
-
-static void
-jabber_iq_last_parse(JabberStream *js, const char *from, JabberIqType type,
-                     const char *id, G_GNUC_UNUSED PurpleXmlNode *packet)
-{
-	JabberIq *iq;
-	PurpleXmlNode *query;
-	char *idle_time;
-
-	if(type == JABBER_IQ_GET) {
-		iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, NS_LAST_ACTIVITY);
-		jabber_iq_set_id(iq, id);
-		if (from)
-			purple_xmlnode_set_attrib(iq->node, "to", from);
-
-		query = purple_xmlnode_get_child(iq->node, "query");
-
-		idle_time =
-		        g_strdup_printf("%" G_GINT64_FORMAT,
-		                        (gint64)(js->idle ? time(NULL) - js->idle : 0));
-		purple_xmlnode_set_attrib(query, "seconds", idle_time);
-		g_free(idle_time);
-
-		jabber_iq_send(iq);
-	}
-}
-
-static void jabber_time_parse(JabberStream *js, const char *from,
-                              JabberIqType type, const char *id,
-                              PurpleXmlNode *child)
-{
-	JabberIq *iq;
-
-	if(type == JABBER_IQ_GET) {
-		PurpleXmlNode *tzo, *utc;
-		GDateTime *now, *now_utc;
-		gchar *date, *tz;
-
-		iq = jabber_iq_new(js, JABBER_IQ_RESULT);
-		jabber_iq_set_id(iq, id);
-		if (from)
-			purple_xmlnode_set_attrib(iq->node, "to", from);
-
-		child = purple_xmlnode_new_child(iq->node, child->name);
-		purple_xmlnode_set_namespace(child, NS_ENTITY_TIME);
-
-		/* <tzo>-06:00</tzo> */
-		now = g_date_time_new_now_local();
-		tz = g_date_time_format(now, "%:z");
-		tzo = purple_xmlnode_new_child(child, "tzo");
-		purple_xmlnode_insert_data(tzo, tz, -1);
-		g_free(tz);
-
-		/* <utc>2006-12-19T17:58:35Z</utc> */
-		now_utc = g_date_time_to_utc(now);
-		date = g_date_time_format(now_utc, "%FT%TZ");
-		utc = purple_xmlnode_new_child(child, "utc");
-		purple_xmlnode_insert_data(utc, date, -1);
-		g_free(date);
-
-		g_date_time_unref(now);
-		g_date_time_unref(now_utc);
-
-		jabber_iq_send(iq);
-	} else {
-		/* TODO: Errors */
-	}
-}
-
-static void
-jabber_iq_version_parse(JabberStream *js, const char *from, JabberIqType type,
-                        const char *id, G_GNUC_UNUSED PurpleXmlNode *packet)
-{
-	JabberIq *iq;
-	PurpleXmlNode *query;
-
-	if(type == JABBER_IQ_GET) {
-		PurpleUi *ui;
-		const char *ui_name = NULL, *ui_version = NULL;
-
-		iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:version");
-		if (from)
-			purple_xmlnode_set_attrib(iq->node, "to", from);
-		jabber_iq_set_id(iq, id);
-
-		query = purple_xmlnode_get_child(iq->node, "query");
-
-		ui = purple_core_get_ui();
-
-		if(PURPLE_IS_UI(ui)) {
-			ui_name = purple_ui_get_name(ui);
-			ui_version = purple_ui_get_version(ui);
-		}
-
-		if(NULL != ui_name && NULL != ui_version) {
-			char *version_complete = g_strdup_printf("%s (libpurple " VERSION ")", ui_version);
-			purple_xmlnode_insert_data(purple_xmlnode_new_child(query, "name"), ui_name, -1);
-			purple_xmlnode_insert_data(purple_xmlnode_new_child(query, "version"), version_complete, -1);
-			g_free(version_complete);
-		} else {
-			purple_xmlnode_insert_data(purple_xmlnode_new_child(query, "name"), "libpurple", -1);
-			purple_xmlnode_insert_data(purple_xmlnode_new_child(query, "version"), VERSION, -1);
-		}
-
-		jabber_iq_send(iq);
-	}
-}
-
-void jabber_iq_remove_callback_by_id(JabberStream *js, const char *id)
-{
-	g_hash_table_remove(js->iq_callbacks, id);
-}
-
-/**
- * Verify that the 'from' attribute of an IQ reply is a valid match for
- * a given IQ request. The expected behavior is outlined in section
- * 8.1.2.1 of the XMPP CORE spec (RFC 6120). We consider the reply to
- * be a valid match if any of the following is true:
- * - Request 'to' matches reply 'from' (including the case where
- *   neither are set).
- * - Request 'to' was my JID (bare or full) and reply 'from' is empty.
- * - Request 'to' was empty and reply 'from' is my JID. The spec says
- *   we should only allow bare JID, but we also allow full JID for
- *   compatibility with some servers.
- * - Request 'to' was empty and reply 'from' is server JID. Not allowed by
- *   any spec, but for compatibility with some servers.
- *
- * These rules should allow valid IQ replies while preventing spoofed
- * ones.
- *
- * For more discussion see the "Spoofing of iq ids and misbehaving
- * servers" email thread from January 2014 on the jdev and security
- * mailing lists. Also see https://developer.pidgin.im/ticket/15879
- *
- * @return TRUE if this reply is valid for the given request.
- */
-static gboolean does_reply_from_match_request_to(JabberStream *js, JabberID *to, JabberID *from)
-{
-	if (jabber_id_equal(to, from)) {
-		/* Request 'to' matches reply 'from' */
-		return TRUE;
-	}
-
-	if (!from && purple_strequal(to->node, js->user->node)
-			&& purple_strequal(to->domain, js->user->domain)) {
-		/* Request 'to' was my JID (bare or full) and reply 'from' is empty */
-		return TRUE;
-	}
-
-	if (!to && purple_strequal(from->domain, js->user->domain)) {
-		/* Request 'to' is empty and reply 'from' domain matches our domain */
-
-		if (!from->node && !from->resource) {
-			/* Reply 'from' is server bare JID */
-			return TRUE;
-		}
-
-		if (purple_strequal(from->node, js->user->node)
-				&& (!from->resource || purple_strequal(from->resource, js->user->resource))) {
-			/* Reply 'from' is my full or bare JID */
-			return TRUE;
-		}
-	}
-
-	return FALSE;
-}
-
-void jabber_iq_parse(JabberStream *js, PurpleXmlNode *packet)
-{
-	JabberIqCallbackData *jcd;
-	PurpleXmlNode *child, *error, *x;
-	const char *xmlns;
-	const char *iq_type, *id, *from;
-	JabberIqType type = JABBER_IQ_NONE;
-	gboolean signal_return;
-	JabberID *from_id;
-
-	from = purple_xmlnode_get_attrib(packet, "from");
-	id = purple_xmlnode_get_attrib(packet, "id");
-	iq_type = purple_xmlnode_get_attrib(packet, "type");
-
-	/*
-	 * Ensure the 'from' attribute is valid. No point in handling a stanza
-	 * of which we don't understand where it came from.
-	 */
-	from_id = jabber_id_new(from);
-
-	if (from && !from_id) {
-		purple_debug_error("jabber", "Received an iq with an invalid from: %s\n", from);
-		return;
-	}
-
-	/*
-	 * child will be either the first tag child or NULL if there is no child.
-	 * Historically, we used just the 'query' subchild, but newer XEPs use
-	 * differently named children. Grabbing the first child is (for the time
-	 * being) sufficient.
-	 */
-	for (child = packet->child; child; child = child->next) {
-		if (child->type == PURPLE_XMLNODE_TYPE_TAG)
-			break;
-	}
-
-	if (iq_type) {
-		if (purple_strequal(iq_type, "get"))
-			type = JABBER_IQ_GET;
-		else if (purple_strequal(iq_type, "set"))
-			type = JABBER_IQ_SET;
-		else if (purple_strequal(iq_type, "result"))
-			type = JABBER_IQ_RESULT;
-		else if (purple_strequal(iq_type, "error"))
-			type = JABBER_IQ_ERROR;
-	}
-
-	if (type == JABBER_IQ_NONE) {
-		purple_debug_error("jabber", "IQ with invalid type ('%s') - ignoring.\n",
-						   iq_type ? iq_type : "(null)");
-		jabber_id_free(from_id);
-		return;
-	}
-
-	/* All IQs must have an ID, so send an error for a set/get that doesn't */
-	if(!id || !*id) {
-
-		if(type == JABBER_IQ_SET || type == JABBER_IQ_GET) {
-			JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR);
-
-			purple_xmlnode_free(iq->node);
-			iq->node = purple_xmlnode_copy(packet);
-			if (from) {
-				purple_xmlnode_set_attrib(iq->node, "to", from);
-				purple_xmlnode_remove_attrib(iq->node, "from");
-			}
-
-			purple_xmlnode_set_attrib(iq->node, "type", "error");
-			/* This id is clearly not useful, but we must put something there for a valid stanza */
-			iq->id = jabber_get_next_id(js);
-			purple_xmlnode_set_attrib(iq->node, "id", iq->id);
-			error = purple_xmlnode_new_child(iq->node, "error");
-			purple_xmlnode_set_attrib(error, "type", "modify");
-			x = purple_xmlnode_new_child(error, "bad-request");
-			purple_xmlnode_set_namespace(x, NS_XMPP_STANZAS);
-
-			jabber_iq_send(iq);
-		} else
-			purple_debug_error("jabber", "IQ of type '%s' missing id - ignoring.\n",
-			                   iq_type);
-
-		jabber_id_free(from_id);
-		return;
-	}
-
-	signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_protocol(js->gc),
-			"jabber-receiving-iq", js->gc, iq_type, id, from, packet));
-	if (signal_return) {
-		jabber_id_free(from_id);
-		return;
-	}
-
-	/* First, lets see if a special callback got registered */
-	if(type == JABBER_IQ_RESULT || type == JABBER_IQ_ERROR) {
-		jcd = g_hash_table_lookup(js->iq_callbacks, id);
-		if (jcd) {
-			if (does_reply_from_match_request_to(js, jcd->to, from_id)) {
-				jcd->callback(js, from, type, id, packet, jcd->data);
-				jabber_iq_remove_callback_by_id(js, id);
-				jabber_id_free(from_id);
-				return;
-			} else {
-				char *expected_to;
-
-				if (jcd->to) {
-					expected_to = jabber_id_get_full_jid(jcd->to);
-				} else {
-					expected_to = jabber_id_get_bare_jid(js->user);
-				}
-
-				purple_debug_error("jabber", "Got a result iq with id %s from %s instead of expected %s!\n", id, from ? from : "(null)", expected_to);
-
-				g_free(expected_to);
-			}
-		}
-	}
-
-	/*
-	 * Apparently not, so let's see if we have a pre-defined handler
-	 * or if an outside plugin is interested.
-	 */
-	if(child && (xmlns = purple_xmlnode_get_namespace(child))) {
-		char *key = g_strdup_printf("%s %s", child->name, xmlns);
-		JabberIqHandler *jih = g_hash_table_lookup(iq_handlers, key);
-		int signal_ref = GPOINTER_TO_INT(g_hash_table_lookup(signal_iq_handlers, key));
-		g_free(key);
-
-		if (signal_ref > 0) {
-			signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_protocol(js->gc), "jabber-watched-iq",
-					js->gc, iq_type, id, from, child));
-			if (signal_return) {
-				jabber_id_free(from_id);
-				return;
-			}
-		}
-
-		if(jih) {
-			jih(js, from, type, id, child);
-			jabber_id_free(from_id);
-			return;
-		}
-	}
-
-	purple_debug_misc("jabber", "Unhandled IQ with id %s\n", id);
-
-	/* If we get here, send the default error reply mandated by XMPP-CORE */
-	if(type == JABBER_IQ_SET || type == JABBER_IQ_GET) {
-		JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR);
-
-		purple_xmlnode_free(iq->node);
-		iq->node = purple_xmlnode_copy(packet);
-		if (from) {
-			purple_xmlnode_set_attrib(iq->node, "to", from);
-			purple_xmlnode_remove_attrib(iq->node, "from");
-		}
-
-		purple_xmlnode_set_attrib(iq->node, "type", "error");
-		error = purple_xmlnode_new_child(iq->node, "error");
-		purple_xmlnode_set_attrib(error, "type", "cancel");
-		purple_xmlnode_set_attrib(error, "code", "501");
-		x = purple_xmlnode_new_child(error, "feature-not-implemented");
-		purple_xmlnode_set_namespace(x, NS_XMPP_STANZAS);
-
-		jabber_iq_send(iq);
-	}
-
-	jabber_id_free(from_id);
-}
-
-void jabber_iq_register_handler(const char *node, const char *xmlns, JabberIqHandler *handlerfunc)
-{
-	/*
-	 * This is valid because nodes nor namespaces cannot have spaces in them
-	 * (see http://www.w3.org/TR/2006/REC-xml-20060816/ and
-	 * http://www.w3.org/TR/REC-xml-names/)
-	 */
-	char *key = g_strdup_printf("%s %s", node, xmlns);
-	g_hash_table_replace(iq_handlers, key, handlerfunc);
-}
-
-void jabber_iq_signal_register(const gchar *node, const gchar *xmlns)
-{
-	gchar *key;
-	int ref;
-
-	g_return_if_fail(node != NULL && *node != '\0');
-	g_return_if_fail(xmlns != NULL && *xmlns != '\0');
-
-	key = g_strdup_printf("%s %s", node, xmlns);
-	ref = GPOINTER_TO_INT(g_hash_table_lookup(signal_iq_handlers, key));
-	if (ref == 0) {
-		g_hash_table_insert(signal_iq_handlers, key, GINT_TO_POINTER(1));
-	} else {
-		g_hash_table_insert(signal_iq_handlers, key, GINT_TO_POINTER(ref + 1));
-		g_free(key);
-	}
-}
-
-void jabber_iq_signal_unregister(const gchar *node, const gchar *xmlns)
-{
-	gchar *key;
-	int ref;
-
-	g_return_if_fail(node != NULL && *node != '\0');
-	g_return_if_fail(xmlns != NULL && *xmlns != '\0');
-
-	key = g_strdup_printf("%s %s", node, xmlns);
-	ref = GPOINTER_TO_INT(g_hash_table_lookup(signal_iq_handlers, key));
-
-	if (ref == 1) {
-		g_hash_table_remove(signal_iq_handlers, key);
-	} else if (ref > 1) {
-		g_hash_table_insert(signal_iq_handlers, key, GINT_TO_POINTER(ref - 1));
-	}
-
-	g_free(key);
-}
-
-void jabber_iq_init(void)
-{
-	iq_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
-	signal_iq_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
-
-	jabber_iq_register_handler("jingle", JINGLE, jingle_parse);
-	jabber_iq_register_handler("ping", NS_PING, jabber_ping_parse);
-	jabber_iq_register_handler("query", NS_BYTESTREAMS,
-			jabber_bytestreams_parse);
-	jabber_iq_register_handler("query", NS_DISCO_INFO, jabber_disco_info_parse);
-	jabber_iq_register_handler("query", NS_DISCO_ITEMS, jabber_disco_items_parse);
-	jabber_iq_register_handler("query", NS_LAST_ACTIVITY, jabber_iq_last_parse);
-	jabber_iq_register_handler("query", NS_OOB_IQ_DATA, jabber_oob_parse);
-	jabber_iq_register_handler("query", "jabber:iq:roster",
-			jabber_roster_parse);
-	jabber_iq_register_handler("query", "jabber:iq:version",
-			jabber_iq_version_parse);
-	jabber_iq_register_handler("block", NS_SIMPLE_BLOCKING, jabber_blocklist_parse_push);
-	jabber_iq_register_handler("unblock", NS_SIMPLE_BLOCKING, jabber_blocklist_parse_push);
-	jabber_iq_register_handler("time", NS_ENTITY_TIME, jabber_time_parse);
-
-}
-
-void jabber_iq_uninit(void)
-{
-	g_clear_pointer(&iq_handlers, g_hash_table_destroy);
-	g_clear_pointer(&signal_iq_handlers, g_hash_table_destroy);
-}
diff --git a/libpurple/protocols/jabber/jabber.h b/libpurple/protocols/jabber/jabber.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/jabber.h
+++ /dev/null
@@ -1,324 +0,0 @@
-/**
- * @file jabber.h
- *
- * 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_JABBER_JABBER_H
-#define PURPLE_JABBER_JABBER_H
-
-typedef enum {
-	JABBER_CAP_NONE           = 0,
-/*	JABBER_CAP_XHTML          = 1 << 0, */
-/*	JABBER_CAP_COMPOSING      = 1 << 1, */
-	JABBER_CAP_SI             = 1 << 2,
-	JABBER_CAP_SI_FILE_XFER   = 1 << 3,
-	JABBER_CAP_BYTESTREAMS    = 1 << 4,
-	JABBER_CAP_IBB            = 1 << 5,
-	JABBER_CAP_CHAT_STATES    = 1 << 6,
-	JABBER_CAP_IQ_SEARCH      = 1 << 7,
-	JABBER_CAP_IQ_REGISTER    = 1 << 8,
-
-	JABBER_CAP_PING           = 1 << 11,
-	JABBER_CAP_ADHOC          = 1 << 12,
-	JABBER_CAP_BLOCKING       = 1 << 13,
-
-	JABBER_CAP_ITEMS          = 1 << 14,
-	JABBER_CAP_ROSTER_VERSIONING = 1 << 15,
-
-	JABBER_CAP_MESSAGE_CARBONS = 1 << 19,
-
-	JABBER_CAP_RETRIEVED      = 1 << 31
-} JabberCapabilities;
-
-typedef struct _JabberStream JabberStream;
-
-#include <libxml/parser.h>
-#include <glib.h>
-#include <gmodule.h>
-#include <gio/gio.h>
-#include <libsoup/soup.h>
-
-#include <purple.h>
-
-#ifdef PURPLE_XMPP_COMPILATION
-#define PURPLE_XMPP_EXTERN_FOR_TESTS _PURPLE_EXPORT extern
-#else
-#define PURPLE_XMPP_EXTERN_FOR_TESTS _PURPLE_IMPORT extern
-#endif
-
-#include "namespaces.h"
-
-#include "auth.h"
-#include "iq.h"
-#include "jutil.h"
-#include "buddy.h"
-#include "bosh.h"
-
-#define CAPS0115_NODE "https://pidgin.im/"
-
-#define JABBER_TYPE_PROTOCOL (jabber_protocol_get_type())
-G_DECLARE_DERIVABLE_TYPE(JabberProtocol, jabber_protocol, JABBER, PROTOCOL,
-                         PurpleProtocol)
-
-#define JABBER_DEFAULT_REQUIRE_TLS    "require_starttls"
-
-/* Index into attention_types list */
-#define JABBER_BUZZ 0
-
-typedef enum {
-	JABBER_STREAM_OFFLINE,
-	JABBER_STREAM_CONNECTING,
-	JABBER_STREAM_INITIALIZING,
-	JABBER_STREAM_INITIALIZING_ENCRYPTION,
-	JABBER_STREAM_AUTHENTICATING,
-	JABBER_STREAM_POST_AUTH,
-	JABBER_STREAM_CONNECTED
-} JabberStreamState;
-
-struct _JabberProtocolClass {
-	PurpleProtocolClass parent_class;
-};
-
-struct _JabberStream
-{
-	guint inpa;
-
-	GCancellable *cancellable;
-
-	xmlParserCtxt *context;
-	PurpleXmlNode *current;
-
-	struct {
-		guint8 major;
-		guint8 minor;
-	} protocol_version;
-
-	JabberSaslMech *auth_mech;
-	gpointer auth_mech_data;
-
-	/**
-	 * The header from the opening <stream/> tag.  This being NULL is treated
-	 * as a special condition in the parsing code (signifying the next
-	 * stanza started is an opening stream tag), and its being missing on
-	 * the stream header is treated as a fatal error.
-	 */
-	char *stream_id;
-	JabberStreamState state;
-
-	GHashTable *buddies;
-
-	/*
-	 * This boolean was added to eliminate a heinous bug where we would
-	 * get into a loop with the server and move a buddy back and forth
-	 * from one group to another.
-	 *
-	 * The sequence goes something like this:
-	 * 1. Our resource and another resource both approve an authorization
-	 *    request at the exact same time.  We put the buddy in group A and
-	 *    the other resource put the buddy in group B.
-	 * 2. The server receives the roster add for group B and sends us a
-	 *    roster push.
-	 * 3. We receive this roster push and modify our local blist.  This
-	 *    triggers us to send a roster add for group B.
-	 * 4. The server receives our earlier roster add for group A and sends us a
-	 *    roster push.
-	 * 5. We receive this roster push and modify our local blist.  This
-	 *    triggers us to send a roster add for group A.
-	 * 6. The server receives our earlier roster add for group B and sends
-	 *    us a roster push.
-	 * (repeat steps 3 through 6 ad infinitum)
-	 *
-	 * This boolean is used to short-circuit the sending of a roster add
-	 * when we receive a roster push.
-	 *
-	 * See these bug reports:
-	 * https://trac.adium.im/ticket/8834
-	 * https://developer.pidgin.im/ticket/5484
-	 * https://developer.pidgin.im/ticket/6188
-	 */
-	gboolean currently_parsing_roster_push;
-
-	GHashTable *chats;
-	GList *chat_servers;
-	PurpleRoomlist *roomlist;
-
-	GHashTable *iq_callbacks;
-	int next_id;
-
-	GList *bs_proxies;
-	GList *oob_file_transfers;
-	GList *file_transfers;
-
-	time_t idle;
-	time_t old_idle;
-
-	JabberID *user;
-	JabberBuddy *user_jb;
-
-	PurpleConnection *gc;
-	GSocketClient *client;
-	GIOStream *stream;
-	GInputStream *input;
-	GOutputStream *output;
-
-	char *initial_avatar_hash;
-	char *avatar_hash;
-	GSList *pending_avatar_requests;
-
-	GSList *pending_buddy_info_requests;
-
-	gboolean reinit;
-
-	JabberCapabilities server_caps;
-	char *server_name;
-
-	char *serverFQDN;
-
-	gboolean vcard_fetched;
-
-	/* Entity Capabilities hash */
-	char *caps_hash;
-
-	/* does the local server support PEP? */
-	gboolean pep;
-
-	/* Is Buzz enabled? */
-	gboolean allowBuzz;
-
-	/* A list of JabberAdHocCommands supported by the server */
-	GList *commands;
-
-	/* last presence update to check for differences */
-	JabberBuddyState old_state;
-	char *old_msg;
-	int old_priority;
-	char *old_avatarhash;
-
-	char *certificate_CN;
-
-	/* A purple timeout tag for the keepalive */
-	guint keepalive_timeout;
-	guint max_inactivity;
-	guint inactivity_timer;
-	guint conn_close_timeout;
-
-	PurpleJabberBOSHConnection *bosh;
-
-	SoupSession *http_conns;
-
-	/* keep a hash table of JingleSessions */
-	GHashTable *sessions;
-};
-
-typedef gboolean (JabberFeatureEnabled)(JabberStream *js, const gchar *namespace);
-
-typedef struct
-{
-	gchar *namespace;
-	JabberFeatureEnabled *is_enabled;
-} JabberFeature;
-
-typedef struct
-{
-	gchar *category;
-	gchar *type;
-	gchar *name;
-	gchar *lang;
-} JabberIdentity;
-
-typedef struct {
-	char *jid;
-	char *host;
-	guint16 port;
-	char *zeroconf;
-} JabberBytestreamsStreamhost;
-
-/* what kind of additional features as returned from disco#info are supported? */
-extern GList *jabber_features;
-/* A sorted list of identities advertised.  Use jabber_add_identity to add
- * so it remains sorted.
- */
-extern GList *jabber_identities;
-
-/**
- * Returns the GType for the JabberProtocol object.
- */
-
-void jabber_stream_features_parse(JabberStream *js, PurpleXmlNode *packet);
-void jabber_process_packet(JabberStream *js, PurpleXmlNode **packet);
-void jabber_send(JabberStream *js, PurpleXmlNode *data);
-
-void jabber_stream_set_state(JabberStream *js, JabberStreamState state);
-
-char *jabber_get_next_id(JabberStream *js);
-
-/** Parse an error into a human-readable string and optionally a disconnect
- *  reason.
- *  @param js     the stream on which the error occurred.
- *  @param packet the error packet
- *  @param reason where to store the disconnection reason, or @c NULL if you
- *                don't care or you don't intend to close the connection.
- */
-char *jabber_parse_error(JabberStream *js, PurpleXmlNode *packet, PurpleConnectionError *reason);
-
-/**
- * Add a feature to the list of features advertised via disco#info.  If you
- * call this while accounts are connected, Bad Things(TM) will happen because
- * the Entity Caps hash will be out-of-date (which should be fixed :/)
- *
- * @param namespace The namespace of the feature
- * @param cb        A callback determining whether or not this feature
- *                  will advertised; may be NULL.
- */
-void jabber_add_feature(const gchar *namespace, JabberFeatureEnabled cb);
-
-JabberIdentity *jabber_identity_new(const gchar *category, const gchar *type, const gchar *lang, const gchar *name);
-void jabber_identity_free(JabberIdentity *id);
-
-/**
- * GCompareFunc for JabberIdentity structs.
- */
-gint jabber_identity_compare(gconstpointer a, gconstpointer b);
-
-void jabber_bytestreams_streamhost_free(JabberBytestreamsStreamhost *sh);
-
-/**
- * Returns true if this connection is over a secure (SSL) stream. Use this
- * instead of checking js->gsc because BOSH stores its PurpleSslConnection
- * members in its own data structure.
- */
-gboolean jabber_stream_is_ssl(JabberStream *js);
-
-/**
- * Restart the "we haven't sent anything in a while and should send
- * something or the server will kick us off" timer (obviously
- * called when sending something.  It's exposed for BOSH.)
- */
-void jabber_stream_restart_inactivity_timer(JabberStream *js);
-
-/** Protocol functions */
-void jabber_blocklist_parse_push(JabberStream *js, const char *from,
-                                 JabberIqType type, const char *id,
-                                 PurpleXmlNode *child);
-void jabber_request_block_list(JabberStream *js);
-
-#endif /* PURPLE_JABBER_JABBER_H */
diff --git a/libpurple/protocols/jabber/jabber.c b/libpurple/protocols/jabber/jabber.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/jabber.c
+++ /dev/null
@@ -1,3312 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <purpleconfig.h>
-
-#include <errno.h>
-
-#include <glib/gi18n-lib.h>
-
-#include <gplugin.h>
-#include <gplugin-native.h>
-
-#include <birb.h>
-
-#include <purple.h>
-
-#include "auth.h"
-#include "buddy.h"
-#include "caps.h"
-#include "chat.h"
-#include "data.h"
-#include "disco.h"
-#include "ibb.h"
-#include "iq.h"
-#include "jutil.h"
-#include "message.h"
-#include "parser.h"
-#include "presence.h"
-#include "jabber.h"
-#include "roster.h"
-#include "oob.h"
-#include "ping.h"
-#include "si.h"
-#include "xdata.h"
-#include "pep.h"
-#include "adhoccommands.h"
-#include "xmpp.h"
-
-#include "jingle/jingle.h"
-#include "jingle/content.h"
-#include "jingle/iceudp.h"
-#include "jingle/rawudp.h"
-#include "jingle/rtp.h"
-#include "jingle/session.h"
-
-#define PING_TIMEOUT 60
-/* Send a whitespace keepalive to the server if we haven't sent
- * anything in the last 120 seconds
- */
-#define DEFAULT_INACTIVITY_TIME 120
-
-GList *jabber_features = NULL;
-GList *jabber_identities = NULL;
-
-static PurpleProtocol *xmpp_protocol = NULL;
-
-static GHashTable *jabber_cmds = NULL; /* PurpleProtocol * => GSList of ids */
-
-static gint plugin_ref = 0;
-
-static void jabber_send_raw(PurpleProtocolServer *protocol_server, JabberStream *js, const gchar *data, gint len);
-static void jabber_remove_feature(const gchar *namespace);
-static gboolean jabber_initiate_media(PurpleProtocolMedia *media, PurpleAccount *account, const char *who, PurpleMediaSessionType type);
-static PurpleMediaCaps jabber_get_media_caps(PurpleProtocolMedia *media, PurpleAccount *account, const char *who);
-
-static void jabber_stream_init(JabberStream *js)
-{
-	char *open_stream;
-
-	g_free(js->stream_id);
-	js->stream_id = NULL;
-
-	open_stream = g_strdup_printf("<stream:stream to='%s' "
-				          "xmlns='" NS_XMPP_CLIENT "' "
-						  "xmlns:stream='" NS_XMPP_STREAMS "' "
-						  "version='1.0'>",
-						  js->user->domain);
-	/* setup the parser fresh for each stream */
-	jabber_parser_setup(js);
-	jabber_send_raw(NULL, js, open_stream, -1);
-	js->reinit = FALSE;
-	g_free(open_stream);
-}
-
-static void
-jabber_session_initialized_cb(JabberStream *js, G_GNUC_UNUSED const char *from,
-                              JabberIqType type, G_GNUC_UNUSED const char *id,
-                              G_GNUC_UNUSED PurpleXmlNode *packet,
-                              G_GNUC_UNUSED gpointer data)
-{
-	if (type == JABBER_IQ_RESULT) {
-		jabber_disco_items_server(js);
-	} else {
-		purple_connection_error(js->gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			("Error initializing session"));
-	}
-}
-
-static void jabber_session_init(JabberStream *js)
-{
-	JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET);
-	PurpleXmlNode *session;
-
-	jabber_iq_set_callback(iq, jabber_session_initialized_cb, NULL);
-
-	session = purple_xmlnode_new_child(iq->node, "session");
-	purple_xmlnode_set_namespace(session, NS_XMPP_SESSION);
-
-	jabber_iq_send(iq);
-}
-
-static void
-jabber_bind_result_cb(JabberStream *js, G_GNUC_UNUSED const char *from,
-                      JabberIqType type, G_GNUC_UNUSED const char *id,
-                      PurpleXmlNode *packet, G_GNUC_UNUSED gpointer data)
-{
-	PurpleXmlNode *bind;
-
-	if (type == JABBER_IQ_RESULT &&
-			(bind = purple_xmlnode_get_child_with_namespace(packet, "bind", NS_XMPP_BIND))) {
-		PurpleXmlNode *jid;
-		char *full_jid;
-		if((jid = purple_xmlnode_get_child(bind, "jid")) && (full_jid = purple_xmlnode_get_data(jid))) {
-			jabber_id_free(js->user);
-
-			js->user = jabber_id_new(full_jid);
-			if (js->user == NULL) {
-				purple_connection_error(js->gc,
-					PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-					_("Invalid response from server"));
-				g_free(full_jid);
-				return;
-			}
-
-			js->user_jb = jabber_buddy_find(js, full_jid, TRUE);
-			js->user_jb->subscription |= JABBER_SUB_BOTH;
-
-			purple_connection_set_display_name(js->gc, full_jid);
-
-			g_free(full_jid);
-		}
-	} else {
-		PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-		char *msg = jabber_parse_error(js, packet, &reason);
-		purple_connection_error(js->gc, reason, msg);
-		g_free(msg);
-
-		return;
-	}
-
-	jabber_session_init(js);
-}
-
-static char *
-jabber_prep_resource(char *input)
-{
-	const gchar *hostname = NULL, *dot = NULL;
-	gchar *result = NULL;
-
-	/* Empty resource == don't send any */
-	if (input == NULL || *input == '\0')
-		return NULL;
-
-	if (strstr(input, "__HOSTNAME__") == NULL)
-		return g_strdup(input);
-
-	/* Replace __HOSTNAME__ with hostname */
-	hostname = g_get_host_name();
-
-	/* We want only the short hostname, not the FQDN - this will prevent the
-	 * resource string from being unreasonably long on systems which stuff the
-	 * whole FQDN in the hostname */
-	if ((dot = strchr(hostname, '.')) != NULL) {
-		gchar *short_hostname = g_strndup(hostname, dot - hostname);
-		result = purple_strreplace(input, "__HOSTNAME__", short_hostname);
-		g_free(short_hostname);
-	} else {
-		result = purple_strreplace(input, "__HOSTNAME__", hostname);
-	}
-
-	return result;
-}
-
-static gboolean
-jabber_process_starttls(JabberStream *js, PurpleXmlNode *packet)
-{
-	PurpleAccount *account = NULL;
-	PurpleXmlNode *starttls = NULL;
-
-	/* It's a secure BOSH connection, just return FALSE and skip, without doing
-	 * anything extra. XEP-0206 (XMPP Over BOSH): The client SHOULD ignore any
-	 * Transport Layer Security (TLS) feature since BOSH channel encryption
-	 * SHOULD be negotiated at the HTTP layer.
-	 *
-	 * Note: we are already receiving STARTTLS at this point from a SSL/TLS BOSH
-	 * connection, so it is not necessary to check if SSL is supported.
-	 */
-	if (js->bosh && jabber_bosh_connection_is_ssl(js->bosh)) {
-		return FALSE;
-	}
-
-	/* Otherwise, it's a standard XMPP connection, or a HTTP (insecure) BOSH connection.
-	 * We request STARTTLS for standard XMPP connections, but we do nothing for insecure
-	 * BOSH connections, per XEP-0206. */
-	if(!js->bosh) {
-		jabber_send_raw(NULL, js,
-				"<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>", -1);
-		return TRUE;
-	}
-
-	/* It's an insecure standard XMPP connection, or an insecure BOSH connection, let's
-	 * ignore STARTTLS even it's required by the server to prevent disabling HTTP BOSH
-	 * entirely (sysadmin is responsible to provide HTTPS-only BOSH if security is required),
-	 * and emit errors if encryption is required by the user. */
-	starttls = purple_xmlnode_get_child(packet, "starttls");
-	if(!js->bosh && purple_xmlnode_get_child(starttls, "required")) {
-		purple_connection_error(js->gc,
-				PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
-				_("Server requires TLS/SSL, but no TLS/SSL support was found."));
-		return TRUE;
-	}
-
-	account = purple_connection_get_account(js->gc);
-	if (purple_strequal("require_tls", purple_account_get_string(account, "connection_security", JABBER_DEFAULT_REQUIRE_TLS))) {
-		purple_connection_error(js->gc,
-				PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
-				_("You require encryption, but no TLS/SSL support was found."));
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-void jabber_stream_features_parse(JabberStream *js, PurpleXmlNode *packet)
-{
-	PurpleAccount *account = purple_connection_get_account(js->gc);
-	const char *connection_security =
-		purple_account_get_string(account, "connection_security", JABBER_DEFAULT_REQUIRE_TLS);
-
-	if (purple_xmlnode_get_child(packet, "starttls")) {
-		if (jabber_process_starttls(js, packet)) {
-			jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING_ENCRYPTION);
-			return;
-		}
-	} else if (purple_strequal(connection_security, "require_tls") && !jabber_stream_is_ssl(js)) {
-		purple_connection_error(js->gc,
-			 PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
-			_("You require encryption, but it is not available on this server."));
-		return;
-	}
-
-	if(purple_xmlnode_get_child(packet, "mechanisms")) {
-		jabber_stream_set_state(js, JABBER_STREAM_AUTHENTICATING);
-		jabber_auth_start(js, packet);
-	} else if(purple_xmlnode_get_child(packet, "bind")) {
-		PurpleXmlNode *bind, *resource;
-		char *requested_resource;
-		JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET);
-		bind = purple_xmlnode_new_child(iq->node, "bind");
-		purple_xmlnode_set_namespace(bind, NS_XMPP_BIND);
-		requested_resource = jabber_prep_resource(js->user->resource);
-
-		if (requested_resource != NULL) {
-			resource = purple_xmlnode_new_child(bind, "resource");
-			purple_xmlnode_insert_data(resource, requested_resource, -1);
-			g_free(requested_resource);
-		}
-
-		jabber_iq_set_callback(iq, jabber_bind_result_cb, NULL);
-
-		jabber_iq_send(iq);
-	} else if (purple_xmlnode_get_child_with_namespace(packet, "ver", NS_ROSTER_VERSIONING)) {
-		js->server_caps |= JABBER_CAP_ROSTER_VERSIONING;
-	} else /* if(purple_xmlnode_get_child_with_namespace(packet, "auth")) */ {
-		/* If we get an empty stream:features packet, or we explicitly get
-		 * an auth feature with namespace http://jabber.org/features/iq-auth
-		 * we should revert back to iq:auth authentication, even though we're
-		 * connecting to an XMPP server.  */
-		jabber_stream_set_state(js, JABBER_STREAM_AUTHENTICATING);
-		jabber_auth_start_old(js);
-	}
-}
-
-static void jabber_stream_handle_error(JabberStream *js, PurpleXmlNode *packet)
-{
-	PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-	char *msg = jabber_parse_error(js, packet, &reason);
-
-	purple_connection_error(js->gc, reason, msg);
-
-	g_free(msg);
-}
-
-static void tls_init(JabberStream *js);
-
-void jabber_process_packet(JabberStream *js, PurpleXmlNode **packet)
-{
-	const char *name;
-	const char *xmlns;
-
-	purple_signal_emit(purple_connection_get_protocol(js->gc), "jabber-receiving-xmlnode", js->gc, packet);
-
-	/* if the signal leaves us with a null packet, we're done */
-	if(NULL == *packet)
-		return;
-
-	name = (*packet)->name;
-	xmlns = purple_xmlnode_get_namespace(*packet);
-
-	if (purple_strequal(name, "iq")) {
-		jabber_iq_parse(js, *packet);
-	} else if (purple_strequal(name, "presence")) {
-		jabber_presence_parse(js, *packet);
-	} else if (purple_strequal(name, "message")) {
-		jabber_message_parse(js, *packet);
-	} else if (purple_strequal(xmlns, NS_XMPP_STREAMS)) {
-		if (purple_strequal(name, "features"))
-			jabber_stream_features_parse(js, *packet);
-		else if (purple_strequal(name, "error"))
-			jabber_stream_handle_error(js, *packet);
-	} else if (purple_strequal(xmlns, NS_XMPP_SASL)) {
-		if (js->state != JABBER_STREAM_AUTHENTICATING)
-			purple_debug_warning("jabber", "Ignoring spurious SASL stanza %s\n", name);
-		else {
-			if (purple_strequal(name, "challenge"))
-				jabber_auth_handle_challenge(js, *packet);
-			else if (purple_strequal(name, "success"))
-				jabber_auth_handle_success(js, *packet);
-			else if (purple_strequal(name, "failure"))
-				jabber_auth_handle_failure(js, *packet);
-		}
-	} else if (purple_strequal(xmlns, NS_XMPP_TLS)) {
-		if (js->state != JABBER_STREAM_INITIALIZING_ENCRYPTION ||
-		    G_IS_TLS_CONNECTION(js->stream)) {
-			purple_debug_warning("jabber", "Ignoring spurious %s\n", name);
-		} else {
-			if (purple_strequal(name, "proceed"))
-				tls_init(js);
-			/* TODO: Handle <failure/>, I guess? */
-		}
-	} else {
-		purple_debug_warning("jabber", "Unknown packet: %s\n", name);
-	}
-}
-
-static void
-jabber_push_bytes_cb(GObject *source, GAsyncResult *res, gpointer data)
-{
-	BirbQueuedOutputStream *stream = BIRB_QUEUED_OUTPUT_STREAM(source);
-	JabberStream *js = data;
-	gboolean result;
-	GError *error = NULL;
-
-	result = birb_queued_output_stream_push_bytes_finish(stream, res, &error);
-
-	if (!result) {
-		birb_queued_output_stream_clear_queue(stream);
-
-		if (error->code != G_IO_ERROR_CANCELLED) {
-			g_prefix_error(&error, "%s", _("Lost connection with server: "));
-			purple_connection_take_error(js->gc, error);
-		} else {
-			g_error_free(error);
-		}
-	}
-}
-
-static gboolean do_jabber_send_raw(JabberStream *js, const char *data, int len)
-{
-	GBytes *output;
-	gboolean success = TRUE;
-
-	g_return_val_if_fail(len > 0, FALSE);
-
-	if (js->state == JABBER_STREAM_CONNECTED)
-		jabber_stream_restart_inactivity_timer(js);
-
-	output = g_bytes_new(data, len);
-	birb_queued_output_stream_push_bytes_async(
-	        BIRB_QUEUED_OUTPUT_STREAM(js->output), output, G_PRIORITY_DEFAULT,
-	        js->cancellable, jabber_push_bytes_cb, js);
-	g_bytes_unref(output);
-
-	return success;
-}
-
-static void
-jabber_send_raw(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
-                JabberStream *js, const char *data, gint len)
-{
-	PurpleConnection *gc;
-	PurpleAccount *account;
-
-	gc = js->gc;
-	account = purple_connection_get_account(gc);
-
-	g_return_if_fail(data != NULL);
-
-	/* because printing a tab to debug every minute gets old */
-	if (!purple_strequal(data, "\t")) {
-		const char *username;
-		char *text = NULL, *last_part = NULL, *tag_start = NULL;
-
-		/* Because debug logs with plaintext passwords make me sad */
-		if (!purple_debug_is_unsafe() && js->state != JABBER_STREAM_CONNECTED &&
-				/* Either <auth> or <query><password>... */
-				(((tag_start = strstr(data, "<auth ")) &&
-					strstr(data, "xmlns='" NS_XMPP_SASL "'")) ||
-				((tag_start = strstr(data, "<query ")) &&
-					strstr(data, "xmlns='jabber:iq:auth'>") &&
-					(tag_start = strstr(tag_start, "<password>"))))) {
-			char *data_start, *tag_end = strchr(tag_start, '>');
-			text = g_strdup(data);
-
-			/* Better to print out some wacky debugging than crash
-			 * due to a plugin sending bad xml */
-			if (tag_end == NULL)
-				tag_end = tag_start;
-
-			data_start = text + (tag_end - data) + 1;
-
-			last_part = strchr(data_start, '<');
-			*data_start = '\0';
-		}
-
-		username = purple_connection_get_display_name(gc);
-		if(username == NULL) {
-			PurpleContactInfo *info = PURPLE_CONTACT_INFO(account);
-			username = purple_contact_info_get_username(info);
-		}
-
-		purple_debug_misc("jabber", "Sending%s (%s): %s%s%s\n",
-				jabber_stream_is_ssl(js) ? " (ssl)" : "", username,
-				text ? text : data,
-				last_part ? "password removed" : "",
-				last_part ? last_part : "");
-
-		g_free(text);
-	}
-
-	purple_signal_emit(purple_connection_get_protocol(gc), "jabber-sending-text", gc, &data);
-	if (data == NULL)
-		return;
-
-	if (len == -1)
-		len = strlen(data);
-
-	if (js->bosh)
-		jabber_bosh_connection_send(js->bosh, data);
-	else
-		do_jabber_send_raw(js, data, len);
-}
-
-static gint
-jabber_protocol_send_raw(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
-                         PurpleConnection *gc, const gchar *buf, gint len)
-{
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-
-	g_return_val_if_fail(js != NULL, -1);
-	/* TODO: It's probably worthwhile to restrict this to when the account
-	 * state is CONNECTED, but I can /almost/ envision reasons for wanting
-	 * to do things during the connection process.
-	 */
-
-	jabber_send_raw(NULL, js, buf, len);
-	return (len < 0 ? (int)strlen(buf) : len);
-}
-
-static void
-jabber_send_signal_cb(PurpleConnection *pc, PurpleXmlNode **packet,
-                      G_GNUC_UNUSED gpointer unused)
-{
-	JabberStream *js;
-	char *txt;
-	int len;
-
-	if (NULL == packet)
-		return;
-
-	PURPLE_ASSERT_CONNECTION_IS_VALID(pc);
-
-	js = purple_connection_get_protocol_data(pc);
-
-	if (NULL == js)
-		return;
-
-	if (js->bosh)
-		if (purple_strequal((*packet)->name, "message") ||
-				purple_strequal((*packet)->name, "iq") ||
-				purple_strequal((*packet)->name, "presence"))
-			purple_xmlnode_set_namespace(*packet, NS_XMPP_CLIENT);
-	txt = purple_xmlnode_to_str(*packet, &len);
-	jabber_send_raw(NULL, js, txt, len);
-	g_free(txt);
-}
-
-void jabber_send(JabberStream *js, PurpleXmlNode *packet)
-{
-	purple_signal_emit(purple_connection_get_protocol(js->gc), "jabber-sending-xmlnode", js->gc, &packet);
-}
-
-static gboolean jabber_keepalive_timeout(PurpleConnection *gc)
-{
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-	purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-					_("Ping timed out"));
-	js->keepalive_timeout = 0;
-	return FALSE;
-}
-
-static void
-jabber_keepalive(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
-                 PurpleConnection *gc)
-{
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-
-	if (js->keepalive_timeout == 0) {
-		jabber_keepalive_ping(js);
-		js->keepalive_timeout = g_timeout_add_seconds(120,
-				G_SOURCE_FUNC(jabber_keepalive_timeout), gc);
-	}
-}
-
-static int
-jabber_get_keepalive_interval(G_GNUC_UNUSED PurpleProtocolServer *protocol_server)
-{
-	return PING_TIMEOUT;
-}
-
-static gboolean
-jabber_recv_cb(GObject *stream, gpointer data)
-{
-	PurpleConnection *gc = data;
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-	gssize len;
-	gchar buf[4096];
-	GError *error = NULL;
-
-	PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
-
-	do {
-		len = g_pollable_input_stream_read_nonblocking(
-		        G_POLLABLE_INPUT_STREAM(stream), buf, sizeof(buf) - 1,
-		        js->cancellable, &error);
-		if (len == 0) {
-			purple_connection_error(js->gc,
-			                        PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			                        _("Server closed the connection"));
-			js->inpa = 0;
-			return G_SOURCE_REMOVE;
-		} else if (len < 0) {
-			if (error->code == G_IO_ERROR_WOULD_BLOCK) {
-				g_error_free(error);
-				return G_SOURCE_CONTINUE;
-			} else if (error->code == G_IO_ERROR_CANCELLED) {
-				g_error_free(error);
-			} else {
-				g_prefix_error(&error, "%s",
-				               _("Lost connection with server: "));
-				purple_connection_take_error(js->gc, error);
-			}
-			js->inpa = 0;
-			return G_SOURCE_REMOVE;
-		}
-
-		purple_connection_update_last_received(gc);
-		buf[len] = '\0';
-		purple_debug_misc("jabber", "Recv (%" G_GSSIZE_FORMAT "): %s", len,
-		                  buf);
-		jabber_parser_process(js, buf, len);
-		if(js->reinit)
-			jabber_stream_init(js);
-	} while (len > 0);
-
-	return G_SOURCE_CONTINUE;
-}
-
-static void
-jabber_stream_connect_finish(JabberStream *js, GIOStream *stream)
-{
-	GSource *source;
-
-	js->stream = stream;
-	js->input = g_object_ref(g_io_stream_get_input_stream(js->stream));
-	js->output = birb_queued_output_stream_new(
-	        g_io_stream_get_output_stream(js->stream));
-
-	if (js->state == JABBER_STREAM_CONNECTING) {
-		jabber_send_raw(NULL, js, "<?xml version='1.0' ?>", -1);
-	}
-
-	jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING);
-	source = g_pollable_input_stream_create_source(
-	        G_POLLABLE_INPUT_STREAM(js->input), js->cancellable);
-	g_source_set_callback(source, G_SOURCE_FUNC(jabber_recv_cb), js->gc, NULL);
-	js->inpa = g_source_attach(source, NULL);
-	g_source_unref(source);
-}
-
-static void
-jabber_login_callback(GObject *source_object, GAsyncResult *res, gpointer data)
-{
-	GSocketClient *client = G_SOCKET_CLIENT(source_object);
-	JabberStream *js = data;
-	GSocketConnection *conn;
-	GIOStream *stream;
-	gboolean is_old_ssl = g_socket_client_get_tls(client);
-	GError *error = NULL;
-
-	conn = g_socket_client_connect_to_host_finish(client, res, &error);
-	if (conn == NULL) {
-		if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
-			g_error_free(error);
-			return;
-		} else if (is_old_ssl) {
-			/* Old-style SSL only makes a direct connection, or fails. */
-			purple_connection_take_error(js->gc, error);
-			return;
-		}
-		g_error_free(error);
-
-		purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-		                        _("Unable to connect"));
-
-		purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-		                        _("Unable to connect"));
-
-		return;
-	}
-
-	if (is_old_ssl) {
-		stream = G_IO_STREAM(g_tcp_wrapper_connection_get_base_io_stream(
-		        G_TCP_WRAPPER_CONNECTION(conn)));
-	} else {
-		stream = G_IO_STREAM(conn);
-	}
-
-	jabber_stream_connect_finish(js, stream);
-
-	if (is_old_ssl) {
-		/* Tell the app that we're doing encryption */
-		jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING_ENCRYPTION);
-	}
-}
-
-static void
-tls_handshake_cb(GObject *source_object, GAsyncResult *res, gpointer data)
-{
-	JabberStream *js = data;
-	GError *error = NULL;
-
-	if (!g_tls_connection_handshake_finish(G_TLS_CONNECTION(source_object), res,
-	                                       &error)) {
-		if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
-			/* Connection already closed/freed. Escape. */
-		} else if (g_error_matches(error, G_TLS_ERROR, G_TLS_ERROR_HANDSHAKE)) {
-			/* In Gio, a handshake error is because of the cert */
-			purple_connection_error(js->gc,
-			                        PURPLE_CONNECTION_ERROR_CERT_OTHER_ERROR,
-			                        _("SSL peer presented an invalid certificate"));
-		} else {
-			/* Report any other errors as handshake failing */
-			purple_connection_error(js->gc,
-			                        PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
-			                        _("SSL Handshake Failed"));
-		}
-
-		g_error_free(error);
-		return;
-	}
-
-	jabber_stream_connect_finish(js, js->stream);
-
-	/* Tell the app that we're doing encryption */
-	jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING_ENCRYPTION);
-}
-
-static void tls_init(JabberStream *js)
-{
-	GSocketConnectable *identity;
-	GIOStream *tls_conn;
-	GError *error = NULL;
-
-	g_clear_handle_id(&js->inpa, g_source_remove);
-	js->input = NULL;
-	g_filter_output_stream_set_close_base_stream(
-	        G_FILTER_OUTPUT_STREAM(js->output), FALSE);
-	g_output_stream_close(G_OUTPUT_STREAM(js->output), js->cancellable, NULL);
-	js->output = NULL;
-
-	identity = g_network_address_new(js->certificate_CN, 0);
-	tls_conn = g_tls_client_connection_new(js->stream, identity, &error);
-	g_object_unref(identity);
-
-	if (tls_conn == NULL) {
-		purple_debug_warning("jabber",
-		                     "Error creating TLS client connection: %s",
-		                     error->message);
-		g_clear_error(&error);
-		purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-		                        _("SSL Connection Failed"));
-		return;
-	}
-
-	g_clear_object(&js->stream);
-	js->stream = G_IO_STREAM(tls_conn);
-
-	g_tls_connection_handshake_async(G_TLS_CONNECTION(tls_conn),
-	                                 G_PRIORITY_DEFAULT, js->cancellable,
-	                                 tls_handshake_cb, js);
-}
-
-static void
-srv_resolved_cb(GObject *source_object, GAsyncResult *result, gpointer data)
-{
-	GSocketClient *client = G_SOCKET_CLIENT(source_object);
-	JabberStream *js = data;
-	GSocketConnection *conn;
-	GError *error = NULL;
-
-	conn = g_socket_client_connect_to_service_finish(client, result, &error);
-	if (error) {
-		if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
-			/* Do nothing; cancelled. */
-
-		} else if (g_error_matches(error, G_RESOLVER_ERROR,
-		                           G_RESOLVER_ERROR_NOT_FOUND)) {
-			/* If there was no response, then attempt fallback behaviour of XMPP
-			 * Core 3.2.2. */
-			purple_debug_warning(
-			        "jabber",
-			        "SRV lookup failed, proceeding with normal connection : %s",
-			        error->message);
-
-			g_socket_client_connect_to_host_async(
-			        js->client, js->user->domain,
-			        purple_account_get_int(
-			                purple_connection_get_account(js->gc), "port",
-			                5222),
-			        js->cancellable, jabber_login_callback, js);
-
-		} else {
-			/* If resolving failed or connecting failed, then just error out, as
-			 * in XMPP Core 3.2.1 step 8. */
-			purple_connection_g_error(js->gc, error);
-		}
-
-		g_error_free(error);
-		return;
-	}
-
-	jabber_stream_connect_finish(js, G_IO_STREAM(conn));
-}
-
-static JabberStream *
-jabber_stream_new(PurpleAccount *account)
-{
-	PurpleConnection *gc = purple_account_get_connection(account);
-	PurpleContactInfo *info = PURPLE_CONTACT_INFO(account);
-	GProxyResolver *resolver;
-	GError *error = NULL;
-	JabberStream *js;
-	PurplePresence *presence;
-	gchar *user;
-	gchar *slash;
-
-	resolver = purple_proxy_get_proxy_resolver(account, &error);
-	if (resolver == NULL) {
-		purple_debug_error("jabber", "Unable to get account proxy resolver: %s",
-		                   error->message);
-		g_error_free(error);
-		return NULL;
-	}
-
-	js = g_new0(JabberStream, 1);
-	purple_connection_set_protocol_data(gc, js);
-	js->gc = gc;
-	js->http_conns = soup_session_new_with_options("proxy-resolver", resolver,
-	                                               NULL);
-	g_object_unref(resolver);
-
-	/* we might want to expose this at some point */
-	js->cancellable = g_cancellable_new();
-
-	user = g_strdup(purple_contact_info_get_username(info));
-	/* jabber_id_new doesn't accept "user@domain/" as valid */
-	slash = strchr(user, '/');
-	if (slash && *(slash + 1) == '\0')
-		*slash = '\0';
-	js->user = jabber_id_new(user);
-
-	if (!js->user) {
-		purple_connection_error(gc,
-			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
-			_("Invalid XMPP ID"));
-		g_free(user);
-		/* Destroying the connection will free the JabberStream */
-		return NULL;
-	}
-
-	if (!js->user->node || *(js->user->node) == '\0') {
-		purple_connection_error(gc,
-			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
-			_("Invalid XMPP ID. Username portion must be set."));
-		g_free(user);
-		/* Destroying the connection will free the JabberStream */
-		return NULL;
-	}
-
-	if (!js->user->domain || *(js->user->domain) == '\0') {
-		purple_connection_error(gc,
-			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
-			_("Invalid XMPP ID. Domain must be set."));
-		g_free(user);
-		/* Destroying the connection will free the JabberStream */
-		return NULL;
-	}
-
-	js->buddies = g_hash_table_new_full(g_str_hash, g_str_equal,
-			g_free, (GDestroyNotify)jabber_buddy_free);
-
-	/* This is overridden during binding, but we need it here
-	 * in case the server only does legacy non-sasl auth!.
-	 */
-	purple_connection_set_display_name(gc, user);
-
-	js->user_jb = jabber_buddy_find(js, user, TRUE);
-	g_free(user);
-	if (!js->user_jb) {
-		/* This basically *can't* fail, but for good measure... */
-		purple_connection_error(gc,
-			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
-			_("Invalid XMPP ID"));
-		/* Destroying the connection will free the JabberStream */
-		g_return_val_if_reached(NULL);
-	}
-
-	js->user_jb->subscription |= JABBER_SUB_BOTH;
-
-	js->iq_callbacks = g_hash_table_new_full(g_str_hash, g_str_equal,
-			g_free, (GDestroyNotify)jabber_iq_callbackdata_free);
-	js->chats = g_hash_table_new_full(g_str_hash, g_str_equal,
-			g_free, (GDestroyNotify)jabber_chat_free);
-	js->next_id = g_random_int();
-	js->keepalive_timeout = 0;
-	js->max_inactivity = DEFAULT_INACTIVITY_TIME;
-	/* Set the default protocol version to 1.0. Overridden in parser.c. */
-	js->protocol_version.major = 1;
-	js->protocol_version.minor = 0;
-	js->sessions = NULL;
-
-	/* if we are idle, set idle-ness on the stream (this could happen if we get
-		disconnected and the reconnects while being idle. I don't think it makes
-		sense to do this when registering a new account... */
-	presence = purple_account_get_presence(account);
-	if (purple_presence_is_idle(presence)) {
-		GDateTime *idle = purple_presence_get_idle_time(presence);
-
-		js->idle = 0;
-		if(idle != NULL) {
-			js->idle = g_date_time_to_unix(idle);
-		}
-	}
-
-	return js;
-}
-
-static void
-jabber_stream_connect(JabberStream *js)
-{
-	PurpleConnection *gc = js->gc;
-	PurpleAccount *account = purple_connection_get_account(gc);
-	const char *connect_server = purple_account_get_string(account,
-			"connect_server", "");
-	const char *bosh_url = purple_account_get_string(account,
-			"bosh_url", "");
-	GError *error = NULL;
-
-	jabber_stream_set_state(js, JABBER_STREAM_CONNECTING);
-
-	/* If both BOSH and a Connect Server are specified, we prefer BOSH. I'm not
-	 * attached to that choice, though.
-	 */
-	if (*bosh_url) {
-		js->bosh = jabber_bosh_connection_new(js, bosh_url);
-		if (!js->bosh) {
-			purple_connection_error(gc,
-				PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
-				_("Malformed BOSH URL"));
-		}
-
-		return;
-	}
-
-	js->client = purple_gio_socket_client_new(account, &error);
-	if (js->client == NULL) {
-		purple_connection_take_error(gc, error);
-		return;
-	}
-
-	js->certificate_CN = g_strdup(connect_server[0] ? connect_server : js->user->domain);
-
-	/* if they've got old-ssl mode going, we probably want to ignore SRV lookups */
-	if (purple_strequal("old_ssl", purple_account_get_string(account, "connection_security", JABBER_DEFAULT_REQUIRE_TLS))) {
-		g_socket_client_set_tls(js->client, TRUE);
-		g_socket_client_connect_to_host_async(
-		        js->client, js->certificate_CN,
-		        purple_account_get_int(account, "port", 5223), js->cancellable,
-		        jabber_login_callback, js);
-		return;
-	}
-
-	/* no old-ssl, so if they've specified a connect server, we'll use that, otherwise we'll
-	 * invoke the magic of SRV lookups, to figure out host and port */
-	if(connect_server[0]) {
-		g_socket_client_connect_to_host_async(
-		        js->client, connect_server,
-		        purple_account_get_int(account, "port", 5222), js->cancellable,
-		        jabber_login_callback, js);
-	} else {
-		g_socket_client_connect_to_service_async(js->client, js->user->domain,
-		                                         "xmpp-client", js->cancellable,
-		                                         srv_resolved_cb, js);
-	}
-}
-
-static void
-jabber_login(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleAccount *account) {
-	PurpleConnection *gc = purple_account_get_connection(account);
-	JabberStream *js;
-	PurpleImage *image;
-
-	purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_HTML |
-		PURPLE_CONNECTION_FLAG_NO_IMAGES);
-	js = jabber_stream_new(account);
-	if (js == NULL)
-		return;
-
-	/* replace old default proxies with the new default: NULL
-	 * TODO: these can eventually be removed */
-	if (purple_strequal("proxy.jabber.org", purple_account_get_string(account, "ft_proxies", ""))
-			|| purple_strequal("proxy.eu.jabber.org", purple_account_get_string(account, "ft_proxies", "")))
-		purple_account_set_string(account, "ft_proxies", NULL);
-
-	/*
-	 * Calculate the avatar hash for our current image so we know (when we
-	 * fetch our vCard and PEP avatar) if we should send our avatar to the
-	 * server.
-	 */
-	image = purple_buddy_icons_find_account_icon(account);
-	if (image != NULL) {
-		js->initial_avatar_hash = g_compute_checksum_for_data(
-			G_CHECKSUM_SHA1,
-			purple_image_get_data(image),
-			purple_image_get_data_size(image)
-		);
-		g_object_unref(image);
-	}
-
-	jabber_stream_connect(js);
-}
-
-/* TODO: As Will pointed out in IRC, after being notified by the core to
- * shutdown, we should async. wait for the server to send us the stream
- * termination before destroying everything. That seems like it would require
- * changing the semantics of protocol's close(), so it's a good idea for 3.0.0.
- */
-static void
-jabber_close(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleConnection *gc) {
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-
-	/* Close all of the open Jingle sessions on this stream */
-	jingle_terminate_sessions(js);
-
-	if (js->bosh) {
-		jabber_bosh_connection_destroy(js->bosh);
-		js->bosh = NULL;
-	} else if (js->output != NULL) {
-		/* We should emit the stream termination message here
-		 * normally, but since we destroy the jabber stream just
-		 * after, it has no way to effectively go out on the
-		 * wire. Moreover, it causes a connection lost error in
-		 * the output queued stream that triggers an
-		 * heap-use-after-free error in jabber_push_bytes_cb().
-		 *
-		 * This case happens when disabling the jabber account
-		 * from the dialog box.
-		 *
-		 * jabber_send_raw(js, "</stream:stream>", -1);
-		 */
-		g_clear_handle_id(&js->inpa, g_source_remove);
-		purple_gio_graceful_close(js->stream, js->input,
-		                          G_OUTPUT_STREAM(js->output));
-	}
-
-	g_clear_object(&js->output);
-	g_clear_object(&js->input);
-	g_clear_object(&js->stream);
-
-	jabber_buddy_remove_all_pending_buddy_info_requests(js);
-
-	jabber_parser_free(js);
-
-	g_clear_pointer(&js->iq_callbacks, g_hash_table_destroy);
-	g_clear_pointer(&js->buddies, g_hash_table_destroy);
-	g_clear_pointer(&js->chats, g_hash_table_destroy);
-
-	g_list_free_full(js->chat_servers, g_free);
-
-	g_list_free_full(js->bs_proxies, (GDestroyNotify)jabber_bytestreams_streamhost_free);
-
-	if (js->http_conns) {
-		soup_session_abort(js->http_conns);
-		g_object_unref(js->http_conns);
-	}
-
-	g_free(js->stream_id);
-	g_clear_pointer(&js->user, jabber_id_free);
-	g_free(js->initial_avatar_hash);
-	g_free(js->avatar_hash);
-	g_free(js->caps_hash);
-
-	if (js->auth_mech && js->auth_mech->dispose)
-		js->auth_mech->dispose(js);
-	g_free(js->serverFQDN);
-	g_list_free_full(js->commands, (GDestroyNotify)jabber_adhoc_commands_free);
-	g_free(js->server_name);
-	g_free(js->certificate_CN);
-	g_free(js->old_msg);
-	g_free(js->old_avatarhash);
-
-	g_clear_handle_id(&js->keepalive_timeout, g_source_remove);
-	g_clear_handle_id(&js->inactivity_timer, g_source_remove);
-	g_clear_handle_id(&js->conn_close_timeout, g_source_remove);
-
-	g_cancellable_cancel(js->cancellable);
-	g_object_unref(js->cancellable);
-
-	g_free(js);
-
-	purple_connection_set_protocol_data(gc, NULL);
-}
-
-void jabber_stream_set_state(JabberStream *js, JabberStreamState state)
-{
-	js->state = state;
-	if(state == JABBER_STREAM_INITIALIZING) {
-		jabber_stream_init(js);
-	} else if(state == JABBER_STREAM_CONNECTED) {
-		/* Send initial presence */
-		jabber_presence_send(js, TRUE);
-		/* Start up the inactivity timer */
-		jabber_stream_restart_inactivity_timer(js);
-
-		purple_connection_set_state(js->gc, PURPLE_CONNECTION_STATE_CONNECTED);
-	}
-}
-
-char *jabber_get_next_id(JabberStream *js)
-{
-	return g_strdup_printf("purple%x", js->next_id++);
-}
-
-
-static void
-jabber_idle_set(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
-                PurpleConnection *gc, gint idle)
-{
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-
-	js->idle = idle ? time(NULL) - idle : idle;
-
-	/* send out an updated prescence */
-	purple_debug_info("jabber", "sending updated presence for idle\n");
-	jabber_presence_send(js, FALSE);
-}
-
-void
-jabber_blocklist_parse_push(G_GNUC_UNUSED JabberStream *js,
-                            G_GNUC_UNUSED const char *from,
-                            G_GNUC_UNUSED JabberIqType type,
-                            G_GNUC_UNUSED const char *id,
-                            G_GNUC_UNUSED PurpleXmlNode *child)
-{
-#if 0
-	JabberIq *result;
-	PurpleXmlNode *item;
-	PurpleAccount *account;
-	gboolean is_block;
-	GSList *deny;
-
-	if (!jabber_is_own_account(js, from)) {
-		PurpleXmlNode *error, *x;
-		result = jabber_iq_new(js, JABBER_IQ_ERROR);
-		purple_xmlnode_set_attrib(result->node, "id", id);
-		if (from)
-			purple_xmlnode_set_attrib(result->node, "to", from);
-
-		error = purple_xmlnode_new_child(result->node, "error");
-		purple_xmlnode_set_attrib(error, "type", "cancel");
-		x = purple_xmlnode_new_child(error, "not-allowed");
-		purple_xmlnode_set_namespace(x, NS_XMPP_STANZAS);
-
-		jabber_iq_send(result);
-		return;
-	}
-
-	account = purple_connection_get_account(js->gc);
-	is_block = purple_strequal(child->name, "block");
-
-	item = purple_xmlnode_get_child(child, "item");
-	if (!is_block && item == NULL) {
-		/* Unblock everyone */
-		purple_debug_info("jabber", "Received unblock push. Unblocking everyone.\n");
-
-		while ((deny = purple_account_privacy_get_denied(account)) != NULL) {
-			purple_account_privacy_deny_remove(account, deny->data, TRUE);
-		}
-	} else if (item == NULL) {
-		/* An empty <block/> is bogus */
-		PurpleXmlNode *error, *x;
-		result = jabber_iq_new(js, JABBER_IQ_ERROR);
-		purple_xmlnode_set_attrib(result->node, "id", id);
-
-		error = purple_xmlnode_new_child(result->node, "error");
-		purple_xmlnode_set_attrib(error, "type", "modify");
-		x = purple_xmlnode_new_child(error, "bad-request");
-		purple_xmlnode_set_namespace(x, NS_XMPP_STANZAS);
-
-		jabber_iq_send(result);
-		return;
-	} else {
-		for ( ; item; item = purple_xmlnode_get_next_twin(item)) {
-			const char *jid = purple_xmlnode_get_attrib(item, "jid");
-			if (jid == NULL || *jid == '\0')
-				continue;
-
-			if (is_block)
-				purple_account_privacy_deny_add(account, jid, TRUE);
-			else
-				purple_account_privacy_deny_remove(account, jid, TRUE);
-		}
-	}
-
-	result = jabber_iq_new(js, JABBER_IQ_RESULT);
-	purple_xmlnode_set_attrib(result->node, "id", id);
-	jabber_iq_send(result);
-#endif
-}
-
-#if 0
-static void jabber_blocklist_parse(JabberStream *js, const char *from,
-                                   JabberIqType type, const char *id,
-                                   PurpleXmlNode *packet, gpointer data)
-{
-	PurpleXmlNode *blocklist, *item;
-	PurpleAccount *account;
-	GSList *deny;
-
-	blocklist = purple_xmlnode_get_child_with_namespace(packet,
-			"blocklist", NS_SIMPLE_BLOCKING);
-	account = purple_connection_get_account(js->gc);
-
-	if (type == JABBER_IQ_ERROR || blocklist == NULL)
-		return;
-
-	/* This is the only privacy method supported by XEP-0191 */
-	purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_DENY_USERS);
-
-	/*
-	 * TODO: When account->deny is something more than a hash table, this can
-	 * be re-written to find the set intersection and difference.
-	 */
-	while ((deny = purple_account_privacy_get_denied(account)))
-		purple_account_privacy_deny_remove(account, deny->data, TRUE);
-
-	item = purple_xmlnode_get_child(blocklist, "item");
-	while (item != NULL) {
-		const char *jid = purple_xmlnode_get_attrib(item, "jid");
-		purple_account_privacy_deny_add(account, jid, TRUE);
-		item = purple_xmlnode_get_next_twin(item);
-	}
-}
-#endif
-
-void
-jabber_request_block_list(G_GNUC_UNUSED JabberStream *js)
-{
-#if 0
-	JabberIq *iq;
-	PurpleXmlNode *blocklist;
-
-	iq = jabber_iq_new(js, JABBER_IQ_GET);
-
-	blocklist = purple_xmlnode_new_child(iq->node, "blocklist");
-	purple_xmlnode_set_namespace(blocklist, NS_SIMPLE_BLOCKING);
-
-	jabber_iq_set_callback(iq, jabber_blocklist_parse, NULL);
-
-	jabber_iq_send(iq);
-#endif
-}
-
-#if 0
-static void
-jabber_add_deny(PurpleProtocolPrivacy *privacy, PurpleConnection *gc,
-                const char *who)
-{
-	JabberStream *js;
-	JabberIq *iq;
-	PurpleXmlNode *block, *item;
-
-	g_return_if_fail(who != NULL && *who != '\0');
-
-	js = purple_connection_get_protocol_data(gc);
-	if (js == NULL)
-		return;
-
-	if (!(js->server_caps & JABBER_CAP_BLOCKING))
-	{
-		purple_notify_error(NULL, _("Server doesn't support blocking"),
-			_("Server doesn't support blocking"), NULL,
-			purple_request_cpar_from_connection(gc));
-		return;
-	}
-
-	iq = jabber_iq_new(js, JABBER_IQ_SET);
-
-	block = purple_xmlnode_new_child(iq->node, "block");
-	purple_xmlnode_set_namespace(block, NS_SIMPLE_BLOCKING);
-
-	item = purple_xmlnode_new_child(block, "item");
-	purple_xmlnode_set_attrib(item, "jid", who);
-
-	jabber_iq_send(iq);
-}
-
-static void
-jabber_remove_deny(PurpleProtocolPrivacy *privacy, PurpleConnection *gc,
-                   const char *who)
-{
-	JabberStream *js;
-	JabberIq *iq;
-	PurpleXmlNode *unblock, *item;
-
-	g_return_if_fail(who != NULL && *who != '\0');
-
-	js = purple_connection_get_protocol_data(gc);
-	if (js == NULL)
-		return;
-
-	if (!(js->server_caps & JABBER_CAP_BLOCKING))
-		return;
-
-	iq = jabber_iq_new(js, JABBER_IQ_SET);
-
-	unblock = purple_xmlnode_new_child(iq->node, "unblock");
-	purple_xmlnode_set_namespace(unblock, NS_SIMPLE_BLOCKING);
-
-	item = purple_xmlnode_new_child(unblock, "item");
-	purple_xmlnode_set_attrib(item, "jid", who);
-
-	jabber_iq_send(iq);
-}
-#endif
-
-void jabber_add_feature(const char *namespace, JabberFeatureEnabled cb) {
-	JabberFeature *feat;
-
-	g_return_if_fail(namespace != NULL);
-
-	feat = g_new0(JabberFeature,1);
-	feat->namespace = g_strdup(namespace);
-	feat->is_enabled = cb;
-
-	/* try to remove just in case it already exists in the list */
-	jabber_remove_feature(namespace);
-
-	jabber_features = g_list_append(jabber_features, feat);
-}
-
-static void jabber_feature_free(JabberFeature *feature) {
-	g_return_if_fail(feature != NULL);
-
-	g_free(feature->namespace);
-	g_free(feature);
-}
-
-static void
-jabber_remove_feature(const char *namespace) {
-	GList *feature;
-	for(feature = jabber_features; feature; feature = feature->next) {
-		JabberFeature *feat = (JabberFeature*)feature->data;
-		if(purple_strequal(feat->namespace, namespace)) {
-			jabber_feature_free(feat);
-			jabber_features = g_list_delete_link(jabber_features, feature);
-			break;
-		}
-	}
-}
-
-gint
-jabber_identity_compare(gconstpointer a, gconstpointer b)
-{
-	const JabberIdentity *ac;
-	const JabberIdentity *bc;
-	gint cat_cmp;
-	gint typ_cmp;
-
-	ac = a;
-	bc = b;
-
-	cat_cmp = g_strcmp0(ac->category, bc->category);
-	if (cat_cmp != 0) {
-		return cat_cmp;
-	}
-
-	typ_cmp = g_strcmp0(ac->type, bc->type);
-	if (typ_cmp != 0) {
-		return typ_cmp;
-	}
-
-	return g_strcmp0(ac->lang, bc->lang);
-}
-
-JabberIdentity *jabber_identity_new(const gchar *category, const gchar *type,
-				    const gchar *lang, const gchar *name)
-{
-	JabberIdentity *id = g_new0(JabberIdentity, 1);
-	id->category = g_strdup(category);
-	id->type = g_strdup(type);
-	id->lang = g_strdup(lang);
-	id->name = g_strdup(name);
-	return id;
-}
-
-void jabber_identity_free(JabberIdentity *id)
-{
-	g_return_if_fail(id != NULL);
-
-	g_free(id->category);
-	g_free(id->type);
-	g_free(id->lang);
-	g_free(id->name);
-	g_free(id);
-}
-
-/*
- * jabber_add_identity:
- * @category: The category of the identity.
- * @type: The type of the identity.
- * @language: (nullable): The language localization of the name.
- * @name: The name of the identity.
- *
- * Adds an identity to this jabber library instance. For list of valid values
- * visit the website of the XMPP Registrar
- * (http://xmpp.org/registrar/disco-categories.html#client)
- *
- * Like with jabber_add_feature, if you call this while accounts are connected,
- * Bad Things will happen.
- */
-static void
-jabber_add_identity(const gchar *category, const gchar *type,
-                    const gchar *lang, const gchar *name)
-{
-	GList *identity;
-	JabberIdentity *ident;
-
-	/* both required according to XEP-0030 */
-	g_return_if_fail(category != NULL);
-	g_return_if_fail(type != NULL);
-
-	ident = jabber_identity_new(category, type, lang, name);
-
-	/* Check if this identity is already there... */
-	identity = g_list_find_custom(jabber_identities, ident, jabber_identity_compare);
-	if (identity != NULL) {
-		jabber_identity_free(ident);
-		return;
-	}
-
-	jabber_identities = g_list_insert_sorted(jabber_identities, ident,
-	                                         jabber_identity_compare);
-}
-
-void jabber_bytestreams_streamhost_free(JabberBytestreamsStreamhost *sh)
-{
-	g_return_if_fail(sh != NULL);
-
-	g_free(sh->jid);
-	g_free(sh->host);
-	g_free(sh->zeroconf);
-	g_free(sh);
-}
-
-gboolean jabber_stream_is_ssl(JabberStream *js)
-{
-	return (js->bosh && jabber_bosh_connection_is_ssl(js->bosh)) ||
-	       (!js->bosh && G_IS_TLS_CONNECTION(js->stream));
-}
-
-static gboolean
-inactivity_cb(gpointer data)
-{
-	JabberStream *js = data;
-
-	/* We want whatever is sent to set this.  It's okay because
-	 * the eventloop unsets it via the return FALSE.
-	 */
-	js->inactivity_timer = 0;
-
-	if (js->bosh) {
-		jabber_bosh_connection_send_keepalive(js->bosh);
-	} else {
-		jabber_send_raw(NULL, js, "\t", 1);
-	}
-
-	return FALSE;
-}
-
-void jabber_stream_restart_inactivity_timer(JabberStream *js)
-{
-	g_clear_handle_id(&js->inactivity_timer, g_source_remove);
-
-	g_return_if_fail(js->max_inactivity > 0);
-
-	js->inactivity_timer =
-		g_timeout_add_seconds(js->max_inactivity,
-		                           inactivity_cb, js);
-}
-
-static const char *
-jabber_list_emblem(G_GNUC_UNUSED PurpleProtocolClient *client, PurpleBuddy *b)
-{
-	JabberStream *js;
-	JabberBuddy *jb = NULL;
-	PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(b));
-
-	if(!gc)
-		return NULL;
-
-	js = purple_connection_get_protocol_data(gc);
-	if(js)
-		jb = jabber_buddy_find(js, purple_buddy_get_name(b), FALSE);
-
-	if(!PURPLE_BUDDY_IS_ONLINE(b)) {
-		if(jb && (jb->subscription & JABBER_SUB_PENDING ||
-					!(jb->subscription & JABBER_SUB_TO)))
-			return "not-authorized";
-	}
-
-	if (jb) {
-		JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, NULL);
-		if (jbr) {
-			const gchar *client_type =
-				jabber_resource_get_identity_category_type(jbr, "client");
-
-			if (client_type) {
-				if (purple_strequal(client_type, "phone")) {
-					return "mobile";
-				} else if (purple_strequal(client_type, "web")) {
-					return "external";
-				} else if (purple_strequal(client_type, "handheld")) {
-					return "hiptop";
-				} else if (purple_strequal(client_type, "bot")) {
-					return "bot";
-				}
-				/* the default value "pc" falls through and has no emblem */
-			}
-		}
-	}
-
-	return NULL;
-}
-
-static GList *
-jabber_status_types(G_GNUC_UNUSED PurpleProtocol *protocol,
-                    G_GNUC_UNUSED PurpleAccount *account)
-{
-	PurpleStatusType *type;
-	GList *types = NULL;
-	GValue *priority_value;
-	GValue *buzz_enabled;
-
-	priority_value = purple_value_new(G_TYPE_INT);
-	g_value_set_int(priority_value, 1);
-	buzz_enabled = purple_value_new(G_TYPE_BOOLEAN);
-	g_value_set_boolean(buzz_enabled, TRUE);
-	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
-			jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_ONLINE),
-			NULL, TRUE, TRUE, FALSE,
-			"priority", _("Priority"), priority_value,
-			"message", _("Message"), purple_value_new(G_TYPE_STRING),
-			"nick", _("Nickname"), purple_value_new(G_TYPE_STRING),
-			"buzz", _("Allow Buzz"), buzz_enabled,
-			NULL);
-	types = g_list_prepend(types, type);
-
-	priority_value = purple_value_new(G_TYPE_INT);
-	g_value_set_int(priority_value, 1);
-	buzz_enabled = purple_value_new(G_TYPE_BOOLEAN);
-	g_value_set_boolean(buzz_enabled, TRUE);
-	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
-			jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_CHAT),
-			_("Chatty"), TRUE, TRUE, FALSE,
-			"priority", _("Priority"), priority_value,
-			"message", _("Message"), purple_value_new(G_TYPE_STRING),
-			"nick", _("Nickname"), purple_value_new(G_TYPE_STRING),
-			"buzz", _("Allow Buzz"), buzz_enabled,
-			NULL);
-	types = g_list_prepend(types, type);
-
-	priority_value = purple_value_new(G_TYPE_INT);
-	g_value_set_int(priority_value, 0);
-	buzz_enabled = purple_value_new(G_TYPE_BOOLEAN);
-	g_value_set_boolean(buzz_enabled, TRUE);
-	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY,
-			jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_AWAY),
-			NULL, TRUE, TRUE, FALSE,
-			"priority", _("Priority"), priority_value,
-			"message", _("Message"), purple_value_new(G_TYPE_STRING),
-			"nick", _("Nickname"), purple_value_new(G_TYPE_STRING),
-			"buzz", _("Allow Buzz"), buzz_enabled,
-			NULL);
-	types = g_list_prepend(types, type);
-
-	priority_value = purple_value_new(G_TYPE_INT);
-	g_value_set_int(priority_value, 0);
-	buzz_enabled = purple_value_new(G_TYPE_BOOLEAN);
-	g_value_set_boolean(buzz_enabled, TRUE);
-	type = purple_status_type_new_with_attrs(PURPLE_STATUS_EXTENDED_AWAY,
-			jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_XA),
-			NULL, TRUE, TRUE, FALSE,
-			"priority", _("Priority"), priority_value,
-			"message", _("Message"), purple_value_new(G_TYPE_STRING),
-			"nick", _("Nickname"), purple_value_new(G_TYPE_STRING),
-			"buzz", _("Allow Buzz"), buzz_enabled,
-			NULL);
-	types = g_list_prepend(types, type);
-
-	priority_value = purple_value_new(G_TYPE_INT);
-	g_value_set_int(priority_value, 0);
-	type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE,
-			jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_DND),
-			_("Do Not Disturb"), TRUE, TRUE, FALSE,
-			"priority", _("Priority"), priority_value,
-			"message", _("Message"), purple_value_new(G_TYPE_STRING),
-			"nick", _("Nickname"), purple_value_new(G_TYPE_STRING),
-			NULL);
-	types = g_list_prepend(types, type);
-
-	/*
-	if(js->protocol_version == JABBER_PROTO_0_9)
-		"Invisible"
-	*/
-
-	type = purple_status_type_new_with_attrs(PURPLE_STATUS_OFFLINE,
-			jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_UNAVAILABLE),
-			NULL, TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(G_TYPE_STRING),
-			NULL);
-	types = g_list_prepend(types, type);
-
-	return g_list_reverse(types);
-}
-
-static void
-jabber_password_change_result_cb(JabberStream *js,
-                                 G_GNUC_UNUSED const char *from,
-                                 JabberIqType type,
-                                 G_GNUC_UNUSED const char *id,
-                                 PurpleXmlNode *packet, gpointer data)
-{
-	if (type == JABBER_IQ_RESULT) {
-		PurpleAccount *account = purple_connection_get_account(js->gc);
-		PurpleCredentialManager *manager = NULL;
-
-		purple_notify_info(js->gc, _("Password Changed"), _("Password "
-			"Changed"), _("Your password has been changed."),
-			purple_request_cpar_from_connection(js->gc));
-
-		manager = purple_credential_manager_get_default();
-		purple_credential_manager_write_password_async(manager, account,
-		                                               (const gchar *)data,
-		                                               NULL, NULL, NULL);
-	} else {
-		char *msg = jabber_parse_error(js, packet, NULL);
-
-		purple_notify_error(js->gc, _("Error changing password"),
-			_("Error changing password"), msg,
-			purple_request_cpar_from_connection(js->gc));
-		g_free(msg);
-	}
-
-	g_free(data);
-}
-
-static void
-jabber_password_change_cb(JabberStream *js, PurpleRequestPage *page) {
-	const char *p1, *p2;
-	JabberIq *iq;
-	PurpleXmlNode *query, *y;
-
-	p1 = purple_request_page_get_string(page, "password1");
-	p2 = purple_request_page_get_string(page, "password2");
-
-	if(!purple_strequal(p1, p2)) {
-		purple_notify_error(js->gc, NULL,
-			_("New passwords do not match."), NULL,
-			purple_request_cpar_from_connection(js->gc));
-		return;
-	}
-
-	iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:register");
-
-	purple_xmlnode_set_attrib(iq->node, "to", js->user->domain);
-
-	query = purple_xmlnode_get_child(iq->node, "query");
-
-	y = purple_xmlnode_new_child(query, "username");
-	purple_xmlnode_insert_data(y, js->user->node, -1);
-	y = purple_xmlnode_new_child(query, "password");
-	purple_xmlnode_insert_data(y, p1, -1);
-
-	jabber_iq_set_callback(iq, jabber_password_change_result_cb, g_strdup(p1));
-
-	jabber_iq_send(iq);
-}
-
-static void
-jabber_password_change(G_GNUC_UNUSED GSimpleAction *action, GVariant *parameter,
-                       G_GNUC_UNUSED gpointer data)
-{
-	const char *account_id = NULL;
-	PurpleAccountManager *manager = NULL;
-	PurpleAccount *account = NULL;
-	PurpleConnection *connection = NULL;
-	JabberStream *js = NULL;
-	PurpleRequestPage *page;
-	PurpleRequestGroup *group;
-	PurpleRequestField *field;
-
-	if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) {
-		g_critical("XMPP Change Password action parameter is of incorrect type %s",
-		           g_variant_get_type_string(parameter));
-	}
-
-	account_id = g_variant_get_string(parameter, NULL);
-	manager = purple_account_manager_get_default();
-	account = purple_account_manager_find_by_id(manager, account_id);
-	connection = purple_account_get_connection(account);
-	g_clear_object(&account);
-	js = purple_connection_get_protocol_data(connection);
-
-	page = purple_request_page_new();
-	group = purple_request_group_new(NULL);
-	purple_request_page_add_group(page, group);
-
-	field = purple_request_field_string_new("password1", _("Password"),
-			"", FALSE);
-	purple_request_field_string_set_masked(PURPLE_REQUEST_FIELD_STRING(field),
-	                                       TRUE);
-	purple_request_field_set_required(field, TRUE);
-	purple_request_group_add_field(group, field);
-
-	field = purple_request_field_string_new("password2", _("Password (again)"),
-			"", FALSE);
-	purple_request_field_string_set_masked(PURPLE_REQUEST_FIELD_STRING(field),
-	                                       TRUE);
-	purple_request_field_set_required(field, TRUE);
-	purple_request_group_add_field(group, field);
-
-	purple_request_fields(connection, _("Change XMPP Password"),
-	                      _("Change XMPP Password"),
-	                      _("Please enter your new password"),
-	                      page,
-	                      _("OK"), G_CALLBACK(jabber_password_change_cb),
-	                      _("Cancel"), NULL,
-	                      purple_request_cpar_from_connection(connection), js);
-}
-
-static const gchar *
-xmpp_protocol_actions_get_prefix(G_GNUC_UNUSED PurpleProtocolActions *actions)
-{
-	return "prpl-xmpp";
-}
-
-static GActionGroup *
-xmpp_protocol_actions_get_action_group(G_GNUC_UNUSED PurpleProtocolActions *actions,
-                                       PurpleConnection *connection)
-{
-	JabberStream *js = purple_connection_get_protocol_data(connection);
-	GSimpleActionGroup *group = NULL;
-	GActionEntry entries[] = {
-		{
-			.name = "set-user-info",
-			.activate = jabber_setup_set_info,
-			.parameter_type = "s",
-		},
-		{
-			.name = "change-password",
-			.activate = jabber_password_change,
-			.parameter_type = "s",
-		},
-	};
-	gsize nentries = G_N_ELEMENTS(entries);
-
-	group = g_simple_action_group_new();
-	g_action_map_add_action_entries(G_ACTION_MAP(group), entries, nentries,
-	                                NULL);
-
-	if(js->pep) {
-		jabber_pep_add_action_entries(group);
-	}
-
-#if 0
-	if(js->commands) {
-		jabber_adhoc_add_server_action_entries(js, group);
-	}
-#endif
-
-	return G_ACTION_GROUP(group);
-}
-
-static GMenu *
-xmpp_protocol_actions_get_menu(G_GNUC_UNUSED PurpleProtocolActions *actions,
-                               G_GNUC_UNUSED PurpleConnection *connection)
-{
-	GMenu *menu = NULL;
-	GMenuItem *item = NULL;
-
-	menu = g_menu_new();
-
-	item = g_menu_item_new(_("Set User Info..."), "prpl-xmpp.set-user-info");
-	g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s",
-	                          "account");
-	g_menu_append_item(menu, item);
-	g_object_unref(item);
-
-	item = g_menu_item_new(_("Change Password..."),
-	                       "prpl-xmpp.change-password");
-	g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s",
-	                          "account");
-	g_menu_append_item(menu, item);
-	g_object_unref(item);
-
-	jabber_pep_append_menu(menu);
-
-#if 0
-	if(js->commands) {
-		jabber_adhoc_append_server_menu(js, menu);
-	}
-#endif
-
-	return menu;
-}
-
-static PurpleChat *
-jabber_find_blist_chat(G_GNUC_UNUSED PurpleProtocolClient *client,
-                       PurpleAccount *account, const char *name)
-{
-	PurpleBlistNode *gnode, *cnode;
-	JabberID *jid;
-
-	if(!(jid = jabber_id_new(name)))
-		return NULL;
-
-	for (gnode = purple_blist_get_default_root(); gnode;
-	     gnode = purple_blist_node_get_sibling_next(gnode)) {
-		for(cnode = purple_blist_node_get_first_child(gnode);
-				cnode;
-				cnode = purple_blist_node_get_sibling_next(cnode)) {
-			PurpleChat *chat = (PurpleChat*)cnode;
-			const char *room, *server;
-			GHashTable *components;
-			if(!PURPLE_IS_CHAT(cnode))
-				continue;
-
-			if (purple_chat_get_account(chat) != account)
-				continue;
-
-			components = purple_chat_get_components(chat);
-			if(!(room = g_hash_table_lookup(components, "room")))
-				continue;
-			if(!(server = g_hash_table_lookup(components, "server")))
-				continue;
-
-			/* FIXME: Collate is wrong in a few cases here; this should be prepped */
-			if(jid->node && jid->domain &&
-					!g_utf8_collate(room, jid->node) && !g_utf8_collate(server, jid->domain)) {
-				jabber_id_free(jid);
-				return chat;
-			}
-		}
-	}
-	jabber_id_free(jid);
-	return NULL;
-}
-
-static void
-jabber_convo_closed(G_GNUC_UNUSED PurpleProtocolClient *client,
-                    PurpleConnection *gc, const char *who)
-{
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-	JabberID *jid;
-	JabberBuddy *jb;
-	JabberBuddyResource *jbr;
-
-	if(!(jid = jabber_id_new(who)))
-		return;
-
-	if((jb = jabber_buddy_find(js, who, TRUE)) &&
-			(jbr = jabber_buddy_find_resource(jb, jid->resource))) {
-		g_free(jbr->thread_id);
-		jbr->thread_id = NULL;
-	}
-
-	jabber_id_free(jid);
-}
-
-static const gchar *
-jabber_client_normalize(G_GNUC_UNUSED PurpleProtocolClient *client,
-                        PurpleAccount *account, const char *who)
-{
-	return jabber_normalize(account, who);
-}
-
-char *jabber_parse_error(JabberStream *js,
-                         PurpleXmlNode *packet,
-                         PurpleConnectionError *reason)
-{
-	PurpleXmlNode *error;
-	const char *code = NULL, *text = NULL;
-	const char *xmlns = purple_xmlnode_get_namespace(packet);
-	char *cdata = NULL;
-
-#define SET_REASON(x) \
-	if(reason != NULL) { *reason = x; }
-
-	if((error = purple_xmlnode_get_child(packet, "error"))) {
-		PurpleXmlNode *t = purple_xmlnode_get_child_with_namespace(error, "text", NS_XMPP_STANZAS);
-		if (t)
-			cdata = purple_xmlnode_get_data(t);
-
-		code = purple_xmlnode_get_attrib(error, "code");
-
-		/* Stanza errors */
-		if(purple_xmlnode_get_child(error, "bad-request")) {
-			text = _("Bad Request");
-		} else if(purple_xmlnode_get_child(error, "conflict")) {
-			SET_REASON(PURPLE_CONNECTION_ERROR_NAME_IN_USE);
-			text = _("Conflict");
-		} else if(purple_xmlnode_get_child(error, "feature-not-implemented")) {
-			text = _("Feature Not Implemented");
-		} else if(purple_xmlnode_get_child(error, "forbidden")) {
-			text = _("Forbidden");
-		} else if(purple_xmlnode_get_child(error, "gone")) {
-			text = _("Gone");
-		} else if(purple_xmlnode_get_child(error, "internal-server-error")) {
-			text = _("Internal Server Error");
-		} else if(purple_xmlnode_get_child(error, "item-not-found")) {
-			text = _("Item Not Found");
-		} else if(purple_xmlnode_get_child(error, "jid-malformed")) {
-			text = _("Malformed XMPP ID");
-		} else if(purple_xmlnode_get_child(error, "not-acceptable")) {
-			text = _("Not Acceptable");
-		} else if(purple_xmlnode_get_child(error, "not-allowed")) {
-			text = _("Not Allowed");
-		} else if(purple_xmlnode_get_child(error, "not-authorized")) {
-			text = _("Not Authorized");
-		} else if(purple_xmlnode_get_child(error, "payment-required")) {
-			text = _("Payment Required");
-		} else if(purple_xmlnode_get_child(error, "recipient-unavailable")) {
-			text = _("Recipient Unavailable");
-		} else if(purple_xmlnode_get_child(error, "redirect")) {
-			/* XXX */
-		} else if(purple_xmlnode_get_child(error, "registration-required")) {
-			text = _("Registration Required");
-		} else if(purple_xmlnode_get_child(error, "remote-server-not-found")) {
-			text = _("Remote Server Not Found");
-		} else if(purple_xmlnode_get_child(error, "remote-server-timeout")) {
-			text = _("Remote Server Timeout");
-		} else if(purple_xmlnode_get_child(error, "resource-constraint")) {
-			text = _("Server Overloaded");
-		} else if(purple_xmlnode_get_child(error, "service-unavailable")) {
-			text = _("Service Unavailable");
-		} else if(purple_xmlnode_get_child(error, "subscription-required")) {
-			text = _("Subscription Required");
-		} else if(purple_xmlnode_get_child(error, "unexpected-request")) {
-			text = _("Unexpected Request");
-		} else if(purple_xmlnode_get_child(error, "undefined-condition")) {
-			text = _("Unknown Error");
-		}
-	} else if(purple_strequal(xmlns, NS_XMPP_SASL)) {
-		/* Most common reason can be the default */
-		SET_REASON(PURPLE_CONNECTION_ERROR_NETWORK_ERROR);
-		if(purple_xmlnode_get_child(packet, "aborted")) {
-			text = _("Authorization Aborted");
-		} else if(purple_xmlnode_get_child(packet, "incorrect-encoding")) {
-			text = _("Incorrect encoding in authorization");
-		} else if(purple_xmlnode_get_child(packet, "invalid-authzid")) {
-			text = _("Invalid authzid");
-		} else if(purple_xmlnode_get_child(packet, "invalid-mechanism")) {
-			text = _("Invalid Authorization Mechanism");
-		} else if(purple_xmlnode_get_child(packet, "mechanism-too-weak")) {
-			SET_REASON(PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE);
-			text = _("Authorization mechanism too weak");
-		} else if(purple_xmlnode_get_child(packet, "not-authorized")) {
-			SET_REASON(PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED);
-			/* Clear the password if it isn't being saved */
-			if (!purple_account_get_remember_password(purple_connection_get_account(js->gc))) {
-				PurpleAccount *account = purple_connection_get_account(js->gc);
-				PurpleCredentialManager *manager = NULL;
-
-				manager = purple_credential_manager_get_default();
-				purple_credential_manager_clear_password_async(manager, account,
-				                                               NULL, NULL,
-				                                               NULL);
-			}
-			text = _("Not Authorized");
-		} else if(purple_xmlnode_get_child(packet, "temporary-auth-failure")) {
-			text = _("Temporary Authentication Failure");
-		} else {
-			SET_REASON(PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED);
-			text = _("Authentication Failure");
-		}
-	} else if(purple_strequal(packet->name, "stream:error") ||
-			 (purple_strequal(packet->name, "error") &&
-				purple_strequal(xmlns, NS_XMPP_STREAMS))) {
-		/* Most common reason as default: */
-		SET_REASON(PURPLE_CONNECTION_ERROR_NETWORK_ERROR);
-		if(purple_xmlnode_get_child(packet, "bad-format")) {
-			text = _("Bad Format");
-		} else if(purple_xmlnode_get_child(packet, "bad-namespace-prefix")) {
-			text = _("Bad Namespace Prefix");
-		} else if(purple_xmlnode_get_child(packet, "conflict")) {
-			SET_REASON(PURPLE_CONNECTION_ERROR_NAME_IN_USE);
-			text = _("Resource Conflict");
-		} else if(purple_xmlnode_get_child(packet, "connection-timeout")) {
-			text = _("Connection Timeout");
-		} else if(purple_xmlnode_get_child(packet, "host-gone")) {
-			text = _("Host Gone");
-		} else if(purple_xmlnode_get_child(packet, "host-unknown")) {
-			text = _("Host Unknown");
-		} else if(purple_xmlnode_get_child(packet, "improper-addressing")) {
-			text = _("Improper Addressing");
-		} else if(purple_xmlnode_get_child(packet, "internal-server-error")) {
-			text = _("Internal Server Error");
-		} else if(purple_xmlnode_get_child(packet, "invalid-id")) {
-			text = _("Invalid ID");
-		} else if(purple_xmlnode_get_child(packet, "invalid-namespace")) {
-			text = _("Invalid Namespace");
-		} else if(purple_xmlnode_get_child(packet, "invalid-xml")) {
-			text = _("Invalid XML");
-		} else if(purple_xmlnode_get_child(packet, "nonmatching-hosts")) {
-			text = _("Non-matching Hosts");
-		} else if(purple_xmlnode_get_child(packet, "not-authorized")) {
-			text = _("Not Authorized");
-		} else if(purple_xmlnode_get_child(packet, "policy-violation")) {
-			text = _("Policy Violation");
-		} else if(purple_xmlnode_get_child(packet, "remote-connection-failed")) {
-			text = _("Remote Connection Failed");
-		} else if(purple_xmlnode_get_child(packet, "resource-constraint")) {
-			text = _("Resource Constraint");
-		} else if(purple_xmlnode_get_child(packet, "restricted-xml")) {
-			text = _("Restricted XML");
-		} else if(purple_xmlnode_get_child(packet, "see-other-host")) {
-			text = _("See Other Host");
-		} else if(purple_xmlnode_get_child(packet, "system-shutdown")) {
-			text = _("System Shutdown");
-		} else if(purple_xmlnode_get_child(packet, "undefined-condition")) {
-			text = _("Undefined Condition");
-		} else if(purple_xmlnode_get_child(packet, "unsupported-encoding")) {
-			text = _("Unsupported Encoding");
-		} else if(purple_xmlnode_get_child(packet, "unsupported-stanza-type")) {
-			text = _("Unsupported Stanza Type");
-		} else if(purple_xmlnode_get_child(packet, "unsupported-version")) {
-			text = _("Unsupported Version");
-		} else if(purple_xmlnode_get_child(packet, "xml-not-well-formed")) {
-			text = _("XML Not Well Formed");
-		} else {
-			text = _("Stream Error");
-		}
-	}
-
-#undef SET_REASON
-
-	if(text || cdata) {
-		char *ret = g_strdup_printf("%s%s%s", code ? code : "",
-				code ? ": " : "", text ? text : cdata);
-		g_free(cdata);
-		return ret;
-	} else {
-		return NULL;
-	}
-}
-
-static PurpleCmdRet
-jabber_cmd_chat_config(PurpleConversation *conv, G_GNUC_UNUSED const char *cmd,
-                       G_GNUC_UNUSED char **args, G_GNUC_UNUSED char **error,
-                       G_GNUC_UNUSED gpointer data)
-{
-	JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv));
-
-	if (!chat)
-		return PURPLE_CMD_RET_FAILED;
-
-	jabber_chat_request_room_configure(chat);
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet
-jabber_cmd_chat_register(PurpleConversation *conv,
-                         G_GNUC_UNUSED const char *cmd,
-                         G_GNUC_UNUSED char **args, G_GNUC_UNUSED char **error,
-                         G_GNUC_UNUSED gpointer data)
-{
-	JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv));
-
-	if (!chat)
-		return PURPLE_CMD_RET_FAILED;
-
-	jabber_chat_register(chat);
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet
-jabber_cmd_chat_topic(PurpleConversation *conv, G_GNUC_UNUSED const char *cmd,
-                      char **args, G_GNUC_UNUSED char **error,
-                      G_GNUC_UNUSED gpointer data)
-{
-	JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv));
-
-	if (!chat)
-		return PURPLE_CMD_RET_FAILED;
-
-	if (args && args[0] && *args[0])
-		jabber_chat_change_topic(chat, args[0]);
-	else {
-		const char *cur = purple_chat_conversation_get_topic(PURPLE_CHAT_CONVERSATION(conv));
-		char *buf, *tmp, *tmp2;
-
-		if (cur) {
-			tmp = g_markup_escape_text(cur, -1);
-			tmp2 = purple_markup_linkify(tmp);
-			buf = g_strdup_printf(_("current topic is: %s"), tmp2);
-			g_free(tmp);
-			g_free(tmp2);
-		} else
-			buf = g_strdup(_("No topic is set"));
-		purple_conversation_write_system_message(conv, buf, PURPLE_MESSAGE_NO_LOG);
-		g_free(buf);
-	}
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet
-jabber_cmd_chat_nick(PurpleConversation *conv, G_GNUC_UNUSED const char *cmd,
-                     char **args, char **error, G_GNUC_UNUSED gpointer data)
-{
-	JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv));
-
-	if(!chat || !args || !args[0])
-		return PURPLE_CMD_RET_FAILED;
-
-	if (!jabber_resourceprep_validate(args[0])) {
-		*error = g_strdup(_("Invalid nickname"));
-		return PURPLE_CMD_RET_FAILED;
-	}
-
-	if (jabber_chat_change_nick(chat, args[0]))
-		return PURPLE_CMD_RET_OK;
-	else
-		return PURPLE_CMD_RET_FAILED;
-}
-
-static PurpleCmdRet
-jabber_cmd_chat_part(PurpleConversation *conv, G_GNUC_UNUSED const char *cmd,
-                     char **args, G_GNUC_UNUSED char **error,
-                     G_GNUC_UNUSED gpointer data)
-{
-	JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv));
-
-	if (!chat)
-		return PURPLE_CMD_RET_FAILED;
-
-	jabber_chat_part(chat, args ? args[0] : NULL);
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet
-jabber_cmd_chat_ban(PurpleConversation *conv, G_GNUC_UNUSED const char *cmd,
-                    char **args, char **error, G_GNUC_UNUSED gpointer data)
-{
-	JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv));
-
-	if(!chat || !args || !args[0])
-		return PURPLE_CMD_RET_FAILED;
-
-	if(!jabber_chat_ban_user(chat, args[0], args[1])) {
-		*error = g_strdup_printf(_("Unable to ban user %s"), args[0]);
-		return PURPLE_CMD_RET_FAILED;
-	}
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet
-jabber_cmd_chat_affiliate(PurpleConversation *conv,
-                          G_GNUC_UNUSED const char *cmd, char **args,
-                          char **error, G_GNUC_UNUSED gpointer data)
-{
-	JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv));
-
-	if (!chat || !args || !args[0])
-		return PURPLE_CMD_RET_FAILED;
-
-	if (!purple_strequal(args[0], "owner") &&
-	    !purple_strequal(args[0], "admin") &&
-	    !purple_strequal(args[0], "member") &&
-	    !purple_strequal(args[0], "outcast") &&
-	    !purple_strequal(args[0], "none")) {
-		*error = g_strdup_printf(_("Unknown affiliation: \"%s\""), args[0]);
-		return PURPLE_CMD_RET_FAILED;
-	}
-
-	if (args[1]) {
-		int i;
-		char **nicks = g_strsplit(args[1], " ", -1);
-
-		for (i = 0; nicks[i]; ++i)
-			if (!jabber_chat_affiliate_user(chat, nicks[i], args[0])) {
-				*error = g_strdup_printf(_("Unable to affiliate user %s as \"%s\""), nicks[i], args[0]);
-				g_strfreev(nicks);
-				return PURPLE_CMD_RET_FAILED;
-			}
-
-		g_strfreev(nicks);
-	} else {
-		jabber_chat_affiliation_list(chat, args[0]);
-	}
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet
-jabber_cmd_chat_role(PurpleConversation *conv, G_GNUC_UNUSED const char *cmd,
-                     char **args, char **error, G_GNUC_UNUSED gpointer data)
-{
-	JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv));
-
-	if (!chat || !args || !args[0])
-		return PURPLE_CMD_RET_FAILED;
-
-	if (!purple_strequal(args[0], "moderator") &&
-	    !purple_strequal(args[0], "participant") &&
-	    !purple_strequal(args[0], "visitor") &&
-	    !purple_strequal(args[0], "none")) {
-		*error = g_strdup_printf(_("Unknown role: \"%s\""), args[0]);
-		return PURPLE_CMD_RET_FAILED;
-	}
-
-	if (args[1]) {
-		int i;
-		char **nicks = g_strsplit(args[1], " ", -1);
-
-		for (i = 0; nicks[i]; i++)
-			if (!jabber_chat_role_user(chat, nicks[i], args[0], NULL)) {
-				*error = g_strdup_printf(_("Unable to set role \"%s\" for user: %s"),
-										 args[0], nicks[i]);
-				g_strfreev(nicks);
-				return PURPLE_CMD_RET_FAILED;
-			}
-
-		g_strfreev(nicks);
-	} else {
-		jabber_chat_role_list(chat, args[0]);
-	}
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet
-jabber_cmd_chat_invite(PurpleConversation *conv, G_GNUC_UNUSED const char *cmd,
-                       char **args, G_GNUC_UNUSED char **error,
-                       G_GNUC_UNUSED gpointer data)
-{
-	if(!args || !args[0])
-		return PURPLE_CMD_RET_FAILED;
-
-	jabber_chat_invite(purple_conversation_get_connection(conv),
-			purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv)), args[1] ? args[1] : "",
-			args[0]);
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet
-jabber_cmd_chat_join(PurpleConversation *conv, G_GNUC_UNUSED const char *cmd,
-                     char **args, char **error, G_GNUC_UNUSED gpointer data)
-{
-	JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv));
-	GHashTable *components;
-	JabberID *jid = NULL;
-	const char *room = NULL, *server = NULL, *handle = NULL;
-
-	if (!chat || !args || !args[0])
-		return PURPLE_CMD_RET_FAILED;
-
-	components = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
-
-	if (strchr(args[0], '@'))
-		jid = jabber_id_new(args[0]);
-	if (jid) {
-		room   = jid->node;
-		server = jid->domain;
-		handle = jid->resource ? jid->resource : chat->handle;
-	} else {
-		/* If jabber_id_new failed, the user may have just passed in
-		 * a room name.  For backward compatibility, handle that here.
-		 */
-		if (strchr(args[0], '@')) {
-			*error = g_strdup(_("Invalid XMPP ID"));
-			return PURPLE_CMD_RET_FAILED;
-		}
-
-		room   = args[0];
-		server = chat->server;
-		handle = chat->handle;
-	}
-
-	g_hash_table_insert(components, "room", (gpointer)room);
-	g_hash_table_insert(components, "server", (gpointer)server);
-	g_hash_table_insert(components, "handle", (gpointer)handle);
-
-	if (args[1])
-		g_hash_table_insert(components, "password", args[1]);
-
-	jabber_chat_join(purple_conversation_get_connection(conv), components);
-
-	g_hash_table_destroy(components);
-	jabber_id_free(jid);
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet
-jabber_cmd_chat_kick(PurpleConversation *conv, G_GNUC_UNUSED const char *cmd,
-                     char **args, char **error, G_GNUC_UNUSED void *data)
-{
-	JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv));
-
-	if(!chat || !args || !args[0])
-		return PURPLE_CMD_RET_FAILED;
-
-	if(!jabber_chat_role_user(chat, args[0], "none", args[1])) {
-		*error = g_strdup_printf(_("Unable to kick user %s"), args[0]);
-		return PURPLE_CMD_RET_FAILED;
-	}
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet
-jabber_cmd_chat_msg(PurpleConversation *conv, G_GNUC_UNUSED const char *cmd,
-                    char **args, G_GNUC_UNUSED char **error,
-                    G_GNUC_UNUSED void *data)
-{
-	PurpleAccount *account = NULL;
-	PurpleConnection *pc = NULL;
-	PurpleProtocol *prpl = NULL;
-	PurpleMessage *msg = NULL;
-	JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv));
-	char *who;
-	const gchar *me = NULL;
-
-	if (!chat)
-		return PURPLE_CMD_RET_FAILED;
-
-	account = purple_connection_get_account(pc);
-	me = purple_contact_info_get_name_for_display(PURPLE_CONTACT_INFO(account));
-
-	who = g_strdup_printf("%s@%s/%s", chat->room, chat->server, args[0]);
-	pc = purple_conversation_get_connection(conv);
-	prpl = purple_connection_get_protocol(pc);
-
-	msg = purple_message_new_outgoing(me, who, args[1], 0);
-
-	jabber_message_send_im(PURPLE_PROTOCOL_IM(prpl), pc, NULL, msg);
-
-	g_free(who);
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet
-jabber_cmd_ping(PurpleConversation *conv, G_GNUC_UNUSED const char *cmd,
-                char **args, char **error, G_GNUC_UNUSED void *data)
-{
-	PurpleAccount *account;
-	PurpleConnection *pc;
-
-	if(!args || !args[0])
-		return PURPLE_CMD_RET_FAILED;
-
-	account = purple_conversation_get_account(conv);
-	pc = purple_account_get_connection(account);
-
-	if(!jabber_ping_jid(purple_connection_get_protocol_data(pc), args[0])) {
-		*error = g_strdup_printf(_("Unable to ping user %s"), args[0]);
-		return PURPLE_CMD_RET_FAILED;
-	}
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static gboolean
-jabber_offline_message(G_GNUC_UNUSED PurpleProtocolClient *client,
-                       G_GNUC_UNUSED PurpleBuddy *buddy)
-{
-	return TRUE;
-}
-
-static gboolean
-jabber_audio_enabled(G_GNUC_UNUSED JabberStream *js,
-                     G_GNUC_UNUSED const char *namespace)
-{
-	PurpleMediaManager *manager = purple_media_manager_get();
-	PurpleMediaCaps caps = purple_media_manager_get_ui_caps(manager);
-
-	return (caps & (PURPLE_MEDIA_CAPS_AUDIO | PURPLE_MEDIA_CAPS_AUDIO_SINGLE_DIRECTION));
-}
-
-static gboolean
-jabber_video_enabled(G_GNUC_UNUSED JabberStream *js,
-                     G_GNUC_UNUSED const char *namespace)
-{
-	PurpleMediaManager *manager = purple_media_manager_get();
-	PurpleMediaCaps caps = purple_media_manager_get_ui_caps(manager);
-
-	return (caps & (PURPLE_MEDIA_CAPS_VIDEO | PURPLE_MEDIA_CAPS_VIDEO_SINGLE_DIRECTION));
-}
-
-typedef struct {
-	PurpleProtocolMedia *media;
-	PurpleAccount *account;
-	gchar *who;
-	PurpleMediaSessionType type;
-
-} JabberMediaRequest;
-
-static void
-jabber_media_cancel_cb(JabberMediaRequest *request,
-                       G_GNUC_UNUSED PurpleRequestPage *page)
-{
-	g_free(request->who);
-	g_free(request);
-}
-
-static void
-jabber_media_ok_cb(JabberMediaRequest *request, PurpleRequestPage *page) {
-	const gchar *selected = purple_request_page_get_choice(page, "resource");
-	gchar *who = g_strdup_printf("%s/%s", request->who, selected);
-	jabber_initiate_media(request->media, request->account, who, request->type);
-
-	g_free(who);
-	g_free(request->who);
-	g_free(request);
-}
-
-static gboolean
-jabber_initiate_media(PurpleProtocolMedia *media, PurpleAccount *account,
-                      const gchar *who, PurpleMediaSessionType type)
-{
-	PurpleConnection *gc = purple_account_get_connection(account);
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-	JabberBuddy *jb;
-	JabberBuddyResource *jbr = NULL;
-	char *resource = NULL;
-
-	if (!js) {
-		purple_debug_error("jabber",
-				"jabber_initiate_media: NULL stream\n");
-		return FALSE;
-	}
-
-	jb = jabber_buddy_find(js, who, FALSE);
-
-	if(!jb || !jb->resources ||
-			(((resource = jabber_get_resource(who)) != NULL)
-			 && (jbr = jabber_buddy_find_resource(jb, resource)) == NULL)) {
-		/* no resources online, we're trying to initiate with someone
-		 * whose presence we're not subscribed to, or
-		 * someone who is offline.  Let's inform the user */
-		char *msg;
-
-		if(!jb) {
-			msg = g_strdup_printf(_("Unable to initiate media with %s: invalid JID"), who);
-		} else if(jb->subscription & JABBER_SUB_TO && !jb->resources) {
-			msg = g_strdup_printf(_("Unable to initiate media with %s: user is not online"), who);
-		} else if(resource) {
-			msg = g_strdup_printf(_("Unable to initiate media with %s: resource is not online"), who);
-		} else {
-			msg = g_strdup_printf(_("Unable to initiate media with %s: not subscribed to user presence"), who);
-		}
-
-		purple_notify_error(account, _("Media Initiation Failed"),
-			_("Media Initiation Failed"), msg,
-			purple_request_cpar_from_connection(gc));
-		g_free(msg);
-		g_free(resource);
-		return FALSE;
-	} else if(jbr != NULL) {
-		/* they've specified a resource, no need to ask or
-		 * default or anything, just do it */
-
-		g_free(resource);
-
-		return jingle_rtp_initiate_media(js, who, type);
-	} else if(!jb->resources->next) {
-		/* only 1 resource online (probably our most common case)
-		 * so no need to ask who to initiate with */
-		gchar *name;
-		gboolean result;
-		jbr = jb->resources->data;
-		name = g_strdup_printf("%s/%s", who, jbr->name);
-		result = jabber_initiate_media(media, account, name, type);
-		g_free(name);
-		return result;
-	} else {
-		/* we've got multiple resources,
-		 * we need to pick one to initiate with */
-		GList *l;
-		char *msg;
-		PurpleRequestPage *page = NULL;
-		PurpleRequestField *field = NULL;
-		PurpleRequestFieldChoice *choice = NULL;
-		PurpleRequestGroup *group = NULL;
-		JabberMediaRequest *request;
-
-		field = purple_request_field_choice_new("resource", _("Resource"), 0);
-		choice = PURPLE_REQUEST_FIELD_CHOICE(field);
-		for(l = jb->resources; l; l = l->next)
-		{
-			JabberBuddyResource *ljbr = l->data;
-			PurpleMediaCaps caps;
-			gchar *name;
-			name = g_strdup_printf("%s/%s", who, ljbr->name);
-			caps = jabber_get_media_caps(media, account, name);
-			g_free(name);
-
-			if ((type & PURPLE_MEDIA_AUDIO) &&
-					(type & PURPLE_MEDIA_VIDEO)) {
-				if (caps & PURPLE_MEDIA_CAPS_AUDIO_VIDEO) {
-					jbr = ljbr;
-					purple_request_field_choice_add_full(choice, jbr->name,
-					                                     g_strdup(jbr->name),
-					                                     g_free);
-				}
-			} else if (type & (PURPLE_MEDIA_AUDIO) &&
-					(caps & PURPLE_MEDIA_CAPS_AUDIO)) {
-				jbr = ljbr;
-				purple_request_field_choice_add_full(choice, jbr->name,
-				                                     g_strdup(jbr->name),
-				                                     g_free);
-			}else if (type & (PURPLE_MEDIA_VIDEO) &&
-					(caps & PURPLE_MEDIA_CAPS_VIDEO)) {
-				jbr = ljbr;
-				purple_request_field_choice_add_full(choice, jbr->name,
-				                                     g_strdup(jbr->name),
-				                                     g_free);
-			}
-		}
-
-		if (jbr == NULL) {
-			purple_debug_error("jabber",
-					"No resources available\n");
-			return FALSE;
-		}
-
-		if(g_list_length(purple_request_field_choice_get_elements(choice)) <= 1) {
-			gchar *name;
-			gboolean result;
-			g_object_unref(field);
-			name = g_strdup_printf("%s/%s", who, jbr->name);
-			result = jabber_initiate_media(media, account, name, type);
-			g_free(name);
-			return result;
-		}
-
-		msg = g_strdup_printf(_("Please select the resource of %s with which you would like to start a media session."), who);
-		page = purple_request_page_new();
-		group =	purple_request_group_new(NULL);
-		request = g_new0(JabberMediaRequest, 1);
-		request->media = media;
-		request->account = account;
-		request->who = g_strdup(who);
-		request->type = type;
-
-		purple_request_group_add_field(group, field);
-		purple_request_page_add_group(page, group);
-		purple_request_fields(account, _("Select a Resource"), msg,
-				NULL, page, _("Initiate Media"),
-				G_CALLBACK(jabber_media_ok_cb), _("Cancel"),
-				G_CALLBACK(jabber_media_cancel_cb),
-				purple_request_cpar_from_account(account),
-				request);
-
-		g_free(msg);
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-static PurpleMediaCaps
-jabber_get_media_caps(G_GNUC_UNUSED PurpleProtocolMedia *media,
-                      PurpleAccount *account, const char *who)
-{
-	PurpleConnection *gc = purple_account_get_connection(account);
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-	JabberBuddy *jb;
-	JabberBuddyResource *jbr;
-	PurpleMediaCaps total = PURPLE_MEDIA_CAPS_NONE;
-	gchar *resource;
-	GList *specific = NULL, *l;
-
-	if (!js) {
-		purple_debug_info("jabber",
-				"jabber_can_do_media: NULL stream\n");
-		return FALSE;
-	}
-
-	jb = jabber_buddy_find(js, who, FALSE);
-
-	if (!jb || !jb->resources) {
-		/* no resources online, we're trying to get caps for someone
-		 * whose presence we're not subscribed to, or
-		 * someone who is offline. */
-		return total;
-
-	} else if ((resource = jabber_get_resource(who)) != NULL) {
-		/* they've specified a resource, no need to ask or
-		 * default or anything, just do it */
-		jbr = jabber_buddy_find_resource(jb, resource);
-		g_free(resource);
-
-		if (!jbr) {
-			purple_debug_error("jabber", "jabber_get_media_caps:"
-					" Can't find resource %s\n", who);
-			return total;
-		}
-
-		l = specific = g_list_prepend(specific, jbr);
-
-	} else {
-		/* we've got multiple resources, combine their caps */
-		l = jb->resources;
-	}
-
-	for (; l; l = l->next) {
-		PurpleMediaCaps caps = PURPLE_MEDIA_CAPS_NONE;
-		jbr = l->data;
-
-		if (jabber_resource_has_capability(jbr,
-				JINGLE_APP_RTP_SUPPORT_AUDIO))
-			caps |= PURPLE_MEDIA_CAPS_AUDIO_SINGLE_DIRECTION |
-					PURPLE_MEDIA_CAPS_AUDIO;
-		if (jabber_resource_has_capability(jbr,
-				JINGLE_APP_RTP_SUPPORT_VIDEO))
-			caps |= PURPLE_MEDIA_CAPS_VIDEO_SINGLE_DIRECTION |
-					PURPLE_MEDIA_CAPS_VIDEO;
-		if (caps & PURPLE_MEDIA_CAPS_AUDIO && caps &
-				PURPLE_MEDIA_CAPS_VIDEO)
-			caps |= PURPLE_MEDIA_CAPS_AUDIO_VIDEO;
-		if (caps != PURPLE_MEDIA_CAPS_NONE) {
-			if (!jabber_resource_has_capability(jbr,
-					JINGLE_TRANSPORT_ICEUDP) &&
-					!jabber_resource_has_capability(jbr,
-					JINGLE_TRANSPORT_RAWUDP)) {
-				purple_debug_info("jingle-rtp", "Buddy doesn't "
-						"support the same transport types\n");
-				caps = PURPLE_MEDIA_CAPS_NONE;
-			} else
-				caps |= PURPLE_MEDIA_CAPS_MODIFY_SESSION |
-						PURPLE_MEDIA_CAPS_CHANGE_DIRECTION;
-		}
-
-		total |= caps;
-	}
-
-	g_clear_list(&specific, NULL);
-
-	return total;
-}
-
-static gboolean
-jabber_can_receive_file(G_GNUC_UNUSED PurpleProtocolXfer *prplxfer,
-                        PurpleConnection *gc, const char *who)
-{
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-
-	if (js) {
-		JabberBuddy *jb = jabber_buddy_find(js, who, FALSE);
-		GList *iter;
-		gboolean has_resources_without_caps = FALSE;
-
-		/* if we didn't find a JabberBuddy, we don't have presence for this
-		 buddy, let's assume they can receive files, disco should tell us
-		 when actually trying */
-		if (jb == NULL)
-			return TRUE;
-
-		/* find out if there is any resources without caps */
-		for (iter = jb->resources; iter ; iter = g_list_next(iter)) {
-			JabberBuddyResource *jbr = (JabberBuddyResource *) iter->data;
-
-			if (!jabber_resource_know_capabilities(jbr)) {
-				has_resources_without_caps = TRUE;
-			}
-		}
-
-		if (has_resources_without_caps) {
-			/* there is at least one resource which we don't have caps for,
-			 let's assume they can receive files... */
-			return TRUE;
-		} else {
-			/* we have caps for all the resources, see if at least one has
-			 right caps */
-			for (iter = jb->resources; iter ; iter = g_list_next(iter)) {
-				JabberBuddyResource *jbr = (JabberBuddyResource *) iter->data;
-
-				if (jabber_resource_has_capability(jbr, NS_SI_FILE_TRANSFER)
-			    	&& (jabber_resource_has_capability(jbr,
-			    			NS_BYTESTREAMS)
-			        	|| jabber_resource_has_capability(jbr, NS_IBB))) {
-					return TRUE;
-				}
-			}
-			return FALSE;
-		}
-	} else {
-		return TRUE;
-	}
-}
-
-static void
-jabber_register_commands(PurpleProtocol *protocol)
-{
-	GSList *commands = NULL;
-	PurpleCmdId id;
-	const gchar *proto_id = purple_protocol_get_id(protocol);
-
-	id = purple_cmd_register("config", "", PURPLE_CMD_P_PROTOCOL,
-		PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, proto_id,
-		jabber_cmd_chat_config, _("config:  Configure a chat room."),
-		NULL);
-	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("configure", "", PURPLE_CMD_P_PROTOCOL,
-		PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, proto_id,
-		jabber_cmd_chat_config, _("configure:  Configure a chat room."),
-		NULL);
-	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("nick", "s", PURPLE_CMD_P_PROTOCOL,
-		PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, proto_id,
-		jabber_cmd_chat_nick, _("nick &lt;new nickname&gt;:  "
-		"Change your nickname."), NULL);
-	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("part", "s", PURPLE_CMD_P_PROTOCOL,
-		PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-		PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, proto_id, jabber_cmd_chat_part,
-		_("part [message]:  Leave the room."), NULL);
-	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("register", "", PURPLE_CMD_P_PROTOCOL,
-		PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, proto_id,
-		jabber_cmd_chat_register,
-		_("register:  Register with a chat room."), NULL);
-	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
-
-	/* XXX: there needs to be a core /topic cmd, methinks */
-	id = purple_cmd_register("topic", "s", PURPLE_CMD_P_PROTOCOL,
-		PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-		PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, proto_id, jabber_cmd_chat_topic,
-		_("topic [new topic]:  View or change the topic."), NULL);
-	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("ban", "ws", PURPLE_CMD_P_PROTOCOL,
-		PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-		PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, proto_id, jabber_cmd_chat_ban,
-		_("ban &lt;user&gt; [reason]:  Ban a user from the room."),
-		NULL);
-	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("affiliate", "ws", PURPLE_CMD_P_PROTOCOL,
-		PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-		PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, proto_id,
-		jabber_cmd_chat_affiliate, _("affiliate "
-		"&lt;owner|admin|member|outcast|none&gt; [nick1] [nick2] ...: "
-		"Get the users with an affiliation or set users' affiliation "
-		"with the room."), NULL);
-	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("role", "ws", PURPLE_CMD_P_PROTOCOL,
-		PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-		PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, proto_id, jabber_cmd_chat_role,
-		_("role &lt;moderator|participant|visitor|none&gt; [nick1] "
-		"[nick2] ...: Get the users with a role or set users' role "
-		"with the room."), NULL);
-	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("invite", "ws", PURPLE_CMD_P_PROTOCOL,
-		PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-		PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, proto_id, jabber_cmd_chat_invite,
-		_("invite &lt;user&gt; [message]:  Invite a user to the room."),
-		NULL);
-	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("join", "ws", PURPLE_CMD_P_PROTOCOL,
-		PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-		PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, proto_id, jabber_cmd_chat_join,
-		_("join: &lt;room[@server]&gt; [password]:  Join a chat."),
-		NULL);
-	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("kick", "ws", PURPLE_CMD_P_PROTOCOL,
-		PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-		PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, proto_id, jabber_cmd_chat_kick,
-		_("kick &lt;user&gt; [reason]:  Kick a user from the room."),
-		NULL);
-	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("msg", "ws", PURPLE_CMD_P_PROTOCOL,
-		PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, proto_id,
-		jabber_cmd_chat_msg, _("msg &lt;user&gt; &lt;message&gt;:  "
-		"Send a private message to another user."), NULL);
-	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("ping", "w", PURPLE_CMD_P_PROTOCOL,
-		PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM |
-		PURPLE_CMD_FLAG_PROTOCOL_ONLY, proto_id, jabber_cmd_ping,
-		_("ping &lt;jid&gt;:  Ping a user/component/server."), NULL);
-	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
-
-	g_hash_table_insert(jabber_cmds, protocol, commands);
-}
-
-static void cmds_free_func(gpointer value)
-{
-	GSList *commands = value;
-	g_slist_free_full(commands,
-	                  (GDestroyNotify)(GCallback)purple_cmd_unregister);
-}
-
-static void jabber_unregister_commands(PurpleProtocol *protocol)
-{
-	g_hash_table_remove(jabber_cmds, protocol);
-}
-
-static gboolean
-find_acct_cb(PurpleAccount *account, const gchar *protocol) {
-	const gchar *account_protocol_id = NULL;
-
-	account_protocol_id = purple_account_get_protocol_id(account);
-	return (purple_strequal(protocol, account_protocol_id) &&
-	        purple_account_is_connected(account));
-}
-
-static PurpleAccount *find_acct(const char *protocol, const char *acct_id)
-{
-	PurpleAccountManager *manager = NULL;
-	PurpleAccount *acct = NULL;
-
-	manager = purple_account_manager_get_default();
-
-	/* If we have a specific acct, use it */
-	if (acct_id) {
-		acct = purple_account_manager_find(manager, acct_id, protocol);
-		if (acct && !purple_account_is_connected(acct)) {
-			g_clear_object(&acct);
-		}
-	} else { /* Otherwise find an active account for the protocol */
-		acct = purple_account_manager_find_custom(manager,
-		                                          (GEqualFunc)find_acct_cb,
-		                                          protocol);
-	}
-
-	return acct;
-}
-
-static gboolean
-xmpp_uri_handler(const char *proto, const char *user, GHashTable *params,
-		gpointer user_data)
-{
-	PurpleProtocol *protocol = (PurpleProtocol *)user_data;
-	const gchar *acct_id = NULL;
-	PurpleAccount *acct;
-
-	g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), FALSE);
-
-	if (g_ascii_strcasecmp(proto, "xmpp"))
-		return FALSE;
-
-	if (params != NULL) {
-		acct_id = g_hash_table_lookup(params, "account");
-	}
-
-	acct = find_acct(XMPP_PROTOCOL_ID, acct_id);
-
-	if (!acct)
-		return FALSE;
-
-	/* xmpp:romeo@montague.net?message;subject=Test%20Message;body=Here%27s%20a%20test%20message */
-	/* params is NULL if the URI has no '?' (or anything after it) */
-	if (!params || g_hash_table_lookup_extended(params, "message", NULL, NULL)) {
-		if (user && *user) {
-			PurpleConversation *im = purple_im_conversation_new(acct, user);
-			const gchar *body = NULL;
-
-			purple_conversation_present(im);
-
-			if(params != NULL) {
-				body = g_hash_table_lookup(params, "body");
-			}
-
-			if(body && *body) {
-				purple_conversation_send_confirm(im, body);
-			}
-
-			g_clear_object(&acct);
-
-			return TRUE;
-		}
-	} else if (g_hash_table_lookup_extended(params, "roster", NULL, NULL)) {
-		char *name = g_hash_table_lookup(params, "name");
-		if (user && *user) {
-			purple_blist_request_add_buddy(acct, user, NULL, name);
-			g_clear_object(&acct);
-			return TRUE;
-		}
-	} else if (g_hash_table_lookup_extended(params, "join", NULL, NULL)) {
-		PurpleConnection *gc = purple_account_get_connection(acct);
-		if (user && *user) {
-			GHashTable *params = jabber_chat_info_defaults(gc, user);
-			jabber_chat_join(gc, params);
-		}
-		g_clear_object(&acct);
-		return TRUE;
-	}
-
-	g_clear_object(&acct);
-
-	return FALSE;
-}
-
-static void
-jabber_do_init(void)
-{
-	PurpleUi *ui = purple_core_get_ui();
-	const gchar *ui_type;
-	const gchar *type = "pc"; /* default client type, if unknown or
-								unspecified */
-	const gchar *ui_name = NULL;
-
-	jabber_cmds = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, cmds_free_func);
-
-	ui_type = ui ? purple_ui_get_client_type(ui) : NULL;
-	if (ui_type) {
-		if (purple_strequal(ui_type, "pc") ||
-			purple_strequal(ui_type, "console") ||
-			purple_strequal(ui_type, "phone") ||
-			purple_strequal(ui_type, "handheld") ||
-			purple_strequal(ui_type, "web") ||
-			purple_strequal(ui_type, "bot")) {
-			type = ui_type;
-		}
-	}
-
-	if (ui)
-		ui_name = purple_ui_get_name(ui);
-	if (ui_name == NULL)
-		ui_name = GETTEXT_PACKAGE;
-
-	jabber_add_identity("client", type, NULL, ui_name);
-
-	/* initialize jabber_features list */
-	jabber_add_feature(NS_LAST_ACTIVITY, NULL);
-	jabber_add_feature(NS_OOB_IQ_DATA, NULL);
-	jabber_add_feature(NS_ENTITY_TIME, NULL);
-	jabber_add_feature("jabber:iq:version", NULL);
-	jabber_add_feature("jabber:x:conference", NULL);
-	jabber_add_feature(NS_BYTESTREAMS, NULL);
-	jabber_add_feature("http://jabber.org/protocol/caps", NULL);
-	jabber_add_feature("http://jabber.org/protocol/chatstates", NULL);
-	jabber_add_feature(NS_DISCO_INFO, NULL);
-	jabber_add_feature(NS_DISCO_ITEMS, NULL);
-	jabber_add_feature(NS_IBB, NULL);
-	jabber_add_feature("http://jabber.org/protocol/muc", NULL);
-	jabber_add_feature("http://jabber.org/protocol/muc#user", NULL);
-	jabber_add_feature("http://jabber.org/protocol/si", NULL);
-	jabber_add_feature(NS_SI_FILE_TRANSFER, NULL);
-	jabber_add_feature(NS_XHTML_IM, NULL);
-	jabber_add_feature(NS_PING, NULL);
-
-	/* Bits Of Binary */
-	jabber_add_feature(NS_BOB, NULL);
-
-	/* Jingle features! */
-	jabber_add_feature(JINGLE, NULL);
-
-	jabber_add_feature(JINGLE_APP_RTP, NULL);
-	jabber_add_feature(JINGLE_APP_RTP_SUPPORT_AUDIO, jabber_audio_enabled);
-	jabber_add_feature(JINGLE_APP_RTP_SUPPORT_VIDEO, jabber_video_enabled);
-	jabber_add_feature(JINGLE_TRANSPORT_RAWUDP, NULL);
-	jabber_add_feature(JINGLE_TRANSPORT_ICEUDP, NULL);
-
-	g_signal_connect(G_OBJECT(purple_media_manager_get()), "ui-caps-changed",
-			G_CALLBACK(jabber_caps_broadcast_change), NULL);
-
-	/* reverse order of unload_plugin */
-	jabber_iq_init();
-	jabber_presence_init();
-	jabber_caps_init();
-	/* PEP things should be init via jabber_pep_init, not here */
-	jabber_pep_init();
-	jabber_data_init();
-	jabber_bosh_init();
-
-	/* TODO: Implement adding and retrieving own features via IPC API */
-
-	jabber_ibb_init();
-	jabber_si_init();
-
-	jabber_auth_init();
-}
-
-static void
-jabber_do_uninit(void)
-{
-	/* reverse order of jabber_do_init */
-	jabber_bosh_uninit();
-	jabber_data_uninit();
-	jabber_si_uninit();
-	jabber_ibb_uninit();
-	/* PEP things should be uninit via jabber_pep_uninit, not here */
-	jabber_pep_uninit();
-	jabber_caps_uninit();
-	jabber_presence_uninit();
-	jabber_iq_uninit();
-
-	g_signal_handlers_disconnect_by_func(purple_media_manager_get(),
-	                                     jabber_caps_broadcast_change, NULL);
-
-	jabber_auth_uninit();
-	g_clear_list(&jabber_features, (GDestroyNotify)jabber_feature_free);
-	g_clear_list(&jabber_identities, (GDestroyNotify)jabber_identity_free);
-
-	g_clear_pointer(&jabber_cmds, g_hash_table_destroy);
-}
-
-static void jabber_init_protocol(PurpleProtocol *protocol)
-{
-	++plugin_ref;
-
-	if (plugin_ref == 1)
-		jabber_do_init();
-
-	jabber_register_commands(protocol);
-
-	purple_signal_register(protocol, "jabber-register-namespace-watcher",
-			purple_marshal_VOID__POINTER_POINTER,
-			G_TYPE_NONE, 2,
-			G_TYPE_STRING,  /* node */
-			G_TYPE_STRING); /* namespace */
-
-	purple_signal_register(protocol, "jabber-unregister-namespace-watcher",
-			purple_marshal_VOID__POINTER_POINTER,
-			G_TYPE_NONE, 2,
-			G_TYPE_STRING,  /* node */
-			G_TYPE_STRING); /* namespace */
-
-	purple_signal_connect(protocol, "jabber-register-namespace-watcher",
-			protocol, G_CALLBACK(jabber_iq_signal_register), NULL);
-	purple_signal_connect(protocol, "jabber-unregister-namespace-watcher",
-			protocol, G_CALLBACK(jabber_iq_signal_unregister), NULL);
-
-
-	purple_signal_register(protocol, "jabber-receiving-xmlnode",
-			purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
-			PURPLE_TYPE_CONNECTION,
-			G_TYPE_POINTER); /* pointer to a PurpleXmlNode* */
-
-	purple_signal_register(protocol, "jabber-sending-xmlnode",
-			purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
-			PURPLE_TYPE_CONNECTION,
-			G_TYPE_POINTER); /* pointer to a PurpleXmlNode* */
-
-	/*
-	 * Do not remove this or the plugin will fail. Completely. You have been
-	 * warned!
-	 */
-	purple_signal_connect_priority(protocol, "jabber-sending-xmlnode",
-			protocol, G_CALLBACK(jabber_send_signal_cb),
-			NULL, PURPLE_SIGNAL_PRIORITY_HIGHEST);
-
-	purple_signal_register(protocol, "jabber-sending-text",
-			     purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
-			     PURPLE_TYPE_CONNECTION,
-			     G_TYPE_POINTER); /* pointer to a string */
-
-	purple_signal_register(protocol, "jabber-receiving-message",
-			purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER_POINTER,
-			G_TYPE_BOOLEAN, 6,
-			PURPLE_TYPE_CONNECTION,
-			G_TYPE_STRING, /* type */
-			G_TYPE_STRING, /* id */
-			G_TYPE_STRING, /* from */
-			G_TYPE_STRING, /* to */
-			PURPLE_TYPE_XMLNODE);
-
-	purple_signal_register(protocol, "jabber-receiving-iq",
-			purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER,
-			G_TYPE_BOOLEAN, 5,
-			PURPLE_TYPE_CONNECTION,
-			G_TYPE_STRING, /* type */
-			G_TYPE_STRING, /* id */
-			G_TYPE_STRING, /* from */
-			PURPLE_TYPE_XMLNODE);
-
-	purple_signal_register(protocol, "jabber-watched-iq",
-			purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER,
-			G_TYPE_BOOLEAN, 5,
-			PURPLE_TYPE_CONNECTION,
-			G_TYPE_STRING, /* type */
-			G_TYPE_STRING, /* id */
-			G_TYPE_STRING, /* from */
-			PURPLE_TYPE_XMLNODE); /* child */
-
-	purple_signal_register(protocol, "jabber-receiving-presence",
-			purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER,
-			G_TYPE_BOOLEAN, 4,
-			PURPLE_TYPE_CONNECTION,
-			G_TYPE_STRING, /* type */
-			G_TYPE_STRING, /* from */
-			PURPLE_TYPE_XMLNODE);
-}
-
-static void jabber_uninit_protocol(PurpleProtocol *protocol)
-{
-	g_return_if_fail(plugin_ref > 0);
-
-	purple_signals_unregister_by_instance(protocol);
-	jabber_unregister_commands(protocol);
-
-	--plugin_ref;
-	if (plugin_ref == 0)
-		jabber_do_uninit();
-}
-
-static PurpleBuddyIconSpec *
-jabber_protocol_get_buddy_icon_spec(G_GNUC_UNUSED PurpleProtocol *protocol) {
-	return purple_buddy_icon_spec_new("png",
-	                                  32, 32, 96, 96, 0,
-	                                  PURPLE_ICON_SCALE_SEND |
-	                                  PURPLE_ICON_SCALE_DISPLAY);
-}
-
-static void
-jabber_protocol_init(G_GNUC_UNUSED JabberProtocol *self) {
-}
-
-static void
-jabber_protocol_class_init(JabberProtocolClass *klass)
-{
-	PurpleProtocolClass *protocol_class = PURPLE_PROTOCOL_CLASS(klass);
-
-	protocol_class->get_buddy_icon_spec = jabber_protocol_get_buddy_icon_spec;
-
-	protocol_class->login = jabber_login;
-	protocol_class->close = jabber_close;
-	protocol_class->status_types = jabber_status_types;
-}
-
-static void
-jabber_protocol_class_finalize(G_GNUC_UNUSED JabberProtocolClass *klass)
-{
-}
-
-static void
-xmpp_protocol_actions_iface_init(PurpleProtocolActionsInterface *iface)
-{
-	iface->get_prefix = xmpp_protocol_actions_get_prefix;
-	iface->get_action_group = xmpp_protocol_actions_get_action_group;
-	iface->get_menu = xmpp_protocol_actions_get_menu;
-}
-
-static void
-jabber_protocol_client_iface_init(PurpleProtocolClientInterface *client_iface)
-{
-	client_iface->list_emblem     = jabber_list_emblem;
-	client_iface->blist_node_menu = jabber_blist_node_menu;
-	client_iface->convo_closed    = jabber_convo_closed;
-	client_iface->normalize       = jabber_client_normalize;
-	client_iface->find_blist_chat = jabber_find_blist_chat;
-	client_iface->offline_message = jabber_offline_message;
-}
-
-static void
-jabber_protocol_server_iface_init(PurpleProtocolServerInterface *server_iface)
-{
-	server_iface->set_info               = jabber_set_info;
-	server_iface->get_info               = jabber_buddy_get_info;
-	server_iface->set_status             = jabber_set_status;
-	server_iface->set_idle               = jabber_idle_set;
-	server_iface->add_buddy              = jabber_roster_add_buddy;
-	server_iface->remove_buddy           = jabber_roster_remove_buddy;
-	server_iface->keepalive              = jabber_keepalive;
-	server_iface->get_keepalive_interval = jabber_get_keepalive_interval;
-	server_iface->alias_buddy            = jabber_roster_alias_change;
-	server_iface->group_buddy            = jabber_roster_group_change;
-	server_iface->rename_group           = jabber_roster_group_rename;
-	server_iface->set_buddy_icon         = jabber_set_buddy_icon;
-	server_iface->send_raw               = jabber_protocol_send_raw;
-}
-
-static void
-jabber_protocol_im_iface_init(PurpleProtocolIMInterface *im_iface)
-{
-	im_iface->send        = jabber_message_send_im;
-	im_iface->send_typing = jabber_send_typing;
-}
-
-static GHashTable *
-jabber_protocol_chat_info_defaults(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
-                                   PurpleConnection *connection,
-                                   const gchar *name)
-{
-	return jabber_chat_info_defaults(connection, name);
-}
-
-static void
-jabber_protocol_chat_join(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
-                          PurpleConnection *connection, GHashTable *components)
-{
-	jabber_chat_join(connection, components);
-}
-
-static void
-jabber_protocol_chat_invite(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
-                            PurpleConnection *connection,  gint id,
-                            const gchar *message, const gchar *who)
-{
-	jabber_chat_invite(connection, id, message, who);
-}
-
-static void
-jabber_protocol_chat_iface_init(PurpleProtocolChatInterface *chat_iface)
-{
-	chat_iface->info               = jabber_chat_info;
-	chat_iface->info_defaults      = jabber_protocol_chat_info_defaults;
-	chat_iface->join               = jabber_protocol_chat_join;
-	chat_iface->get_name           = jabber_get_chat_name;
-	chat_iface->invite             = jabber_protocol_chat_invite;
-	chat_iface->leave              = jabber_chat_leave;
-	chat_iface->send               = jabber_message_send_chat;
-	chat_iface->get_user_real_name = jabber_chat_user_real_name;
-	chat_iface->set_topic          = jabber_chat_set_topic;
-}
-
-static void
-jabber_protocol_roomlist_iface_init(PurpleProtocolRoomlistInterface *roomlist_iface)
-{
-	roomlist_iface->get_list       = jabber_roomlist_get_list;
-	roomlist_iface->cancel         = jabber_roomlist_cancel;
-	roomlist_iface->room_serialize = jabber_roomlist_room_serialize;
-}
-
-static void
-jabber_protocol_media_iface_init(PurpleProtocolMediaInterface *media_iface)
-{
-	media_iface->initiate_session = jabber_initiate_media;
-	media_iface->get_caps         = jabber_get_media_caps;
-}
-
-static void
-jabber_protocol_xfer_iface_init(PurpleProtocolXferInterface *xfer_iface)
-{
-	xfer_iface->can_receive = jabber_can_receive_file;
-	xfer_iface->send_file   = jabber_si_xfer_send;
-	xfer_iface->new_xfer    = jabber_si_new_xfer;
-}
-
-G_DEFINE_DYNAMIC_TYPE_EXTENDED(
-	JabberProtocol,
-	jabber_protocol,
-	PURPLE_TYPE_PROTOCOL,
-	G_TYPE_FLAG_ABSTRACT,
-	G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_ACTIONS,
-	                              xmpp_protocol_actions_iface_init)
-	G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_CLIENT,
-	                              jabber_protocol_client_iface_init)
-	G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_SERVER,
-	                              jabber_protocol_server_iface_init)
-	G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_IM,
-	                              jabber_protocol_im_iface_init)
-	G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_CHAT,
-	                              jabber_protocol_chat_iface_init)
-	G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_ROOMLIST,
-	                              jabber_protocol_roomlist_iface_init)
-	G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_MEDIA,
-	                              jabber_protocol_media_iface_init)
-	G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_XFER,
-	                              jabber_protocol_xfer_iface_init))
-
-static GPluginPluginInfo *
-jabber_query(G_GNUC_UNUSED GError **error)
-{
-	return purple_plugin_info_new(
-		"id",           "prpl-xmpp",
-		"name",         "XMPP Protocols",
-		"version",      DISPLAY_VERSION,
-		"category",     N_("Protocol"),
-		"summary",      N_("XMPP Protocol Plugin"),
-		"description",  N_("XMPP Protocol Plugin"),
-		"website",      PURPLE_WEBSITE,
-		"abi-version",  PURPLE_ABI_VERSION,
-		"flags",        PURPLE_PLUGIN_INFO_FLAGS_INTERNAL |
-		                PURPLE_PLUGIN_INFO_FLAGS_AUTO_LOAD,
-		NULL
-	);
-}
-
-static gboolean
-jabber_load(GPluginPlugin *plugin, GError **error)
-{
-	PurpleProtocolManager *manager = purple_protocol_manager_get_default();
-
-	jingle_session_register(plugin);
-
-	jingle_transport_register(plugin);
-	jingle_iceudp_register(plugin);
-	jingle_rawudp_register(plugin);
-
-	jingle_content_register(plugin);
-	jingle_rtp_register(plugin);
-
-	jabber_protocol_register_type(G_TYPE_MODULE(plugin));
-
-	xmpp_protocol_register(plugin);
-
-	jabber_oob_xfer_register(G_TYPE_MODULE(plugin));
-	jabber_si_xfer_register(G_TYPE_MODULE(plugin));
-
-	xmpp_protocol = xmpp_protocol_new();
-	if(!purple_protocol_manager_register(manager, xmpp_protocol, error)) {
-		g_clear_object(&xmpp_protocol);
-
-		return FALSE;
-	}
-
-	purple_signal_connect(purple_get_core(), "uri-handler", xmpp_protocol,
-		G_CALLBACK(xmpp_uri_handler), xmpp_protocol);
-
-	jabber_init_protocol(xmpp_protocol);
-
-	return TRUE;
-}
-
-static gboolean
-jabber_unload(G_GNUC_UNUSED GPluginPlugin *plugin,
-              G_GNUC_UNUSED gboolean shutdown, GError **error)
-{
-	PurpleProtocolManager *manager = purple_protocol_manager_get_default();
-
-	if(!purple_protocol_manager_unregister(manager, xmpp_protocol, error)) {
-		return FALSE;
-	}
-
-	purple_signal_disconnect(purple_get_core(), "uri-handler",
-			xmpp_protocol, G_CALLBACK(xmpp_uri_handler));
-
-	jabber_uninit_protocol(xmpp_protocol);
-
-	g_clear_object(&xmpp_protocol);
-
-	return TRUE;
-}
-
-GPLUGIN_NATIVE_PLUGIN_DECLARE(jabber)
diff --git a/libpurple/protocols/jabber/jingle/content.h b/libpurple/protocols/jabber/jingle/content.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/jingle/content.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/**
- * @file content.h
- *
- * 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_JABBER_JINGLE_CONTENT_H
-#define PURPLE_JABBER_JINGLE_CONTENT_H
-
-
-#include "jabber.h"
-#include "jingle.h"
-#include "session.h"
-#include "transport.h"
-
-#include <glib.h>
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-#define JINGLE_TYPE_CONTENT  jingle_content_get_type()
-
-typedef struct _JingleContent JingleContent;
-
-/** The content class */
-struct _JingleContentClass
-{
-	GObjectClass parent_class;     /**< The parent class. */
-
-	PurpleXmlNode *(*to_xml) (JingleContent *content, PurpleXmlNode *jingle, JingleActionType action);
-	JingleContent *(*parse) (PurpleXmlNode *content);
-	void (*handle_action) (JingleContent *content, PurpleXmlNode *xmlcontent, JingleActionType action);
-	const gchar *description_type;
-};
-
-/**
- * Gets the content class's GType
- *
- * @return The content class's GType.
- */
-G_MODULE_EXPORT
-G_DECLARE_DERIVABLE_TYPE(JingleContent, jingle_content, JINGLE, CONTENT,
-		GObject)
-
-/**
- * Registers the JingleContent type in the type system.
- */
-void jingle_content_register(PurplePlugin *plugin);
-
-JingleContent *jingle_content_create(const gchar *type, const gchar *creator,
-		const gchar *disposition, const gchar *name,
-		const gchar *senders, JingleTransport *transport);
-
-JingleSession *jingle_content_get_session(JingleContent *content);
-const gchar *jingle_content_get_description_type(JingleContent *content);
-gchar *jingle_content_get_creator(JingleContent *content);
-gchar *jingle_content_get_disposition(JingleContent *content);
-gchar *jingle_content_get_name(JingleContent *content);
-gchar *jingle_content_get_senders(JingleContent *content);
-JingleTransport *jingle_content_get_transport(JingleContent *content);
-JingleTransport *jingle_content_get_pending_transport(JingleContent *content);
-
-void jingle_content_set_session(JingleContent *content, JingleSession *session);
-void jingle_content_set_pending_transport(JingleContent *content, JingleTransport *transport);
-void jingle_content_accept_transport(JingleContent *content);
-void jingle_content_remove_pending_transport(JingleContent *content);
-void jingle_content_modify(JingleContent *content, const gchar *senders);
-
-#define jingle_content_create_content_accept(session) \
-	jingle_session_to_packet(session, JINGLE_CONTENT_ACCEPT)
-#define jingle_content_create_content_add(session) \
-	jingle_session_to_packet(session, JINGLE_CONTENT_ADD)
-#define jingle_content_create_content_modify(session) \
-	jingle_session_to_packet(session, JINGLE_CONTENT_MODIFY)
-#define jingle_content_create_content_remove(session) \
-	jingle_session_to_packet(session, JINGLE_CONTENT_REMOVE)
-
-JingleContent *jingle_content_parse(PurpleXmlNode *content);
-PurpleXmlNode *jingle_content_to_xml(JingleContent *content, PurpleXmlNode *jingle, JingleActionType action);
-void jingle_content_handle_action(JingleContent *content, PurpleXmlNode *xmlcontent, JingleActionType action);
-
-G_END_DECLS
-
-#endif /* PURPLE_JABBER_JINGLE_CONTENT_H */
-
diff --git a/libpurple/protocols/jabber/jingle/content.c b/libpurple/protocols/jabber/jingle/content.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/jingle/content.c
+++ /dev/null
@@ -1,477 +0,0 @@
-/**
- * @file content.c
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "content.h"
-#include "jingle.h"
-
-#include <string.h>
-
-typedef struct
-{
-	JingleSession *session;
-	gchar *description_type;
-	gchar *creator;
-	gchar *disposition;
-	gchar *name;
-	gchar *senders;
-	JingleTransport *transport;
-	JingleTransport *pending_transport;
-} JingleContentPrivate;
-
-enum {
-	PROP_0,
-	PROP_SESSION,
-	PROP_CREATOR,
-	PROP_DISPOSITION,
-	PROP_NAME,
-	PROP_SENDERS,
-	PROP_TRANSPORT,
-	PROP_PENDING_TRANSPORT,
-	N_PROPERTIES,
-};
-
-static GParamSpec *properties[N_PROPERTIES] = {NULL, };
-
-G_DEFINE_DYNAMIC_TYPE_EXTENDED(
-	JingleContent,
-	jingle_content,
-	G_TYPE_OBJECT,
-	0,
-	G_ADD_PRIVATE_DYNAMIC(JingleContent)
-);
-
-/******************************************************************************
- * JingleContent Implementation
- *****************************************************************************/
-static JingleContent *
-jingle_content_parse_internal(PurpleXmlNode *content)
-{
-	PurpleXmlNode *description = purple_xmlnode_get_child(content, "description");
-	const gchar *type = purple_xmlnode_get_namespace(description);
-	const gchar *creator = purple_xmlnode_get_attrib(content, "creator");
-	const gchar *disposition = purple_xmlnode_get_attrib(content, "disposition");
-	const gchar *senders = purple_xmlnode_get_attrib(content, "senders");
-	const gchar *name = purple_xmlnode_get_attrib(content, "name");
-	JingleTransport *transport =
-			jingle_transport_parse(purple_xmlnode_get_child(content, "transport"));
-	if (transport == NULL)
-		return NULL;
-
-	if (senders == NULL)
-		senders = "both";
-
-	return jingle_content_create(type, creator, disposition, name, senders, transport);
-}
-
-static PurpleXmlNode *
-jingle_content_to_xml_internal(JingleContent *content, PurpleXmlNode *jingle, JingleActionType action)
-{
-	PurpleXmlNode *node = purple_xmlnode_new_child(jingle, "content");
-	gchar *creator = jingle_content_get_creator(content);
-	gchar *name = jingle_content_get_name(content);
-	gchar *senders = jingle_content_get_senders(content);
-	gchar *disposition = jingle_content_get_disposition(content);
-
-	purple_xmlnode_set_attrib(node, "creator", creator);
-	purple_xmlnode_set_attrib(node, "name", name);
-	purple_xmlnode_set_attrib(node, "senders", senders);
-	if (!purple_strequal("session", disposition))
-		purple_xmlnode_set_attrib(node, "disposition", disposition);
-
-	g_free(disposition);
-	g_free(senders);
-	g_free(name);
-	g_free(creator);
-
-	if (action != JINGLE_CONTENT_REMOVE) {
-		JingleTransport *transport;
-
-		if (action != JINGLE_TRANSPORT_ACCEPT &&
-				action != JINGLE_TRANSPORT_INFO &&
-				action != JINGLE_TRANSPORT_REJECT &&
-				action != JINGLE_TRANSPORT_REPLACE) {
-			PurpleXmlNode *description = purple_xmlnode_new_child(node, "description");
-
-			purple_xmlnode_set_namespace(description,
-					jingle_content_get_description_type(content));
-		}
-
-		if (action != JINGLE_TRANSPORT_REJECT && action == JINGLE_TRANSPORT_REPLACE)
-			transport = jingle_content_get_pending_transport(content);
-		else
-			transport = jingle_content_get_transport(content);
-
-		jingle_transport_to_xml(transport, node, action);
-		g_object_unref(transport);
-	}
-
-	return node;
-}
-
-/******************************************************************************
- * GObject Stuff
- *****************************************************************************/
-static void
-jingle_content_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
-	JingleContent *content = JINGLE_CONTENT(object);
-	JingleContentPrivate *priv = jingle_content_get_instance_private(content);
-
-	switch (prop_id) {
-		case PROP_SESSION:
-			priv->session = g_value_get_object(value);
-			break;
-		case PROP_CREATOR:
-			g_free(priv->creator);
-			priv->creator = g_value_dup_string(value);
-			break;
-		case PROP_DISPOSITION:
-			g_free(priv->disposition);
-			priv->disposition = g_value_dup_string(value);
-			break;
-		case PROP_NAME:
-			g_free(priv->name);
-			priv->name = g_value_dup_string(value);
-			break;
-		case PROP_SENDERS:
-			g_free(priv->senders);
-			priv->senders = g_value_dup_string(value);
-			break;
-		case PROP_TRANSPORT:
-			if (priv->transport)
-				g_object_unref(priv->transport);
-			priv->transport = g_value_get_object(value);
-			break;
-		case PROP_PENDING_TRANSPORT:
-			if (priv->pending_transport)
-				g_object_unref(priv->pending_transport);
-			priv->pending_transport = g_value_get_object(value);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
-static void
-jingle_content_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
-	JingleContent *content = JINGLE_CONTENT(object);
-	JingleContentPrivate *priv = jingle_content_get_instance_private(content);
-
-	switch (prop_id) {
-		case PROP_SESSION:
-			g_value_set_object(value, priv->session);
-			break;
-		case PROP_CREATOR:
-			g_value_set_string(value, priv->creator);
-			break;
-		case PROP_DISPOSITION:
-			g_value_set_string(value, priv->disposition);
-			break;
-		case PROP_NAME:
-			g_value_set_string(value, priv->name);
-			break;
-		case PROP_SENDERS:
-			g_value_set_string(value, priv->senders);
-			break;
-		case PROP_TRANSPORT:
-			g_value_set_object(value, priv->transport);
-			break;
-		case PROP_PENDING_TRANSPORT:
-			g_value_set_object(value, priv->pending_transport);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
-static void
-jingle_content_init(G_GNUC_UNUSED JingleContent *content)
-{
-}
-
-static void
-jingle_content_finalize (GObject *content)
-{
-	JingleContentPrivate *priv = jingle_content_get_instance_private(JINGLE_CONTENT(content));
-
-	purple_debug_info("jingle","jingle_content_finalize\n");
-
-	g_free(priv->description_type);
-	g_free(priv->creator);
-	g_free(priv->disposition);
-	g_free(priv->name);
-	g_free(priv->senders);
-	g_object_unref(priv->transport);
-	if (priv->pending_transport)
-		g_object_unref(priv->pending_transport);
-
-	G_OBJECT_CLASS(jingle_content_parent_class)->finalize(content);
-}
-
-
-static void
-jingle_content_class_finalize(G_GNUC_UNUSED JingleContentClass *klass)
-{
-}
-
-static void
-jingle_content_class_init (JingleContentClass *klass)
-{
-	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
-
-	obj_class->finalize = jingle_content_finalize;
-	obj_class->set_property = jingle_content_set_property;
-	obj_class->get_property = jingle_content_get_property;
-
-	klass->to_xml = jingle_content_to_xml_internal;
-	klass->parse = jingle_content_parse_internal;
-
-	properties[PROP_SESSION] = g_param_spec_object("session",
-			"Jingle Session",
-			"The jingle session parent of this content.",
-			JINGLE_TYPE_SESSION,
-			G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_CREATOR] = g_param_spec_string("creator",
-			"Creator",
-			"The participant that created this content.",
-			NULL,
-			G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_DISPOSITION] = g_param_spec_string("disposition",
-			"Disposition",
-			"The disposition of the content.",
-			NULL,
-			G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_NAME] = g_param_spec_string("name",
-			"Name",
-			"The name of this content.",
-			NULL,
-			G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_SENDERS] = g_param_spec_string("senders",
-			"Senders",
-			"The sender of this content.",
-			NULL,
-			G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_TRANSPORT] = g_param_spec_object("transport",
-			"transport",
-			"The transport of this content.",
-			JINGLE_TYPE_TRANSPORT,
-			G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_PENDING_TRANSPORT] = g_param_spec_object("pending-transport",
-			"Pending transport",
-			"The pending transport contained within this content",
-			JINGLE_TYPE_TRANSPORT,
-			G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
-}
-
-/******************************************************************************
- * Public API
- *****************************************************************************/
-void
-jingle_content_register(PurplePlugin *plugin)
-{
-	jingle_content_register_type(G_TYPE_MODULE(plugin));
-}
-
-JingleContent *
-jingle_content_create(const gchar *type, const gchar *creator,
-		const gchar *disposition, const gchar *name,
-		const gchar *senders, JingleTransport *transport)
-{
-
-
-	JingleContent *content = g_object_new(jingle_get_type(type),
-			"creator", creator,
-			"disposition", disposition != NULL ? disposition : "session",
-			"name", name,
-			"senders", senders != NULL ? senders : "both",
-			"transport", transport,
-			NULL);
-	return content;
-}
-
-JingleSession *jingle_content_get_session(JingleContent *content)
-{
-	JingleSession *session;
-	g_object_get(content, "session", &session, NULL);
-	return session;
-}
-
-const gchar *
-jingle_content_get_description_type(JingleContent *content)
-{
-	return JINGLE_CONTENT_GET_CLASS(content)->description_type;
-}
-
-gchar *
-jingle_content_get_creator(JingleContent *content)
-{
-	gchar *creator;
-	g_object_get(content, "creator", &creator, NULL);
-	return creator;
-}
-
-gchar *
-jingle_content_get_disposition(JingleContent *content)
-{
-	gchar *disposition;
-	g_object_get(content, "disposition", &disposition, NULL);
-	return disposition;
-}
-
-gchar *
-jingle_content_get_name(JingleContent *content)
-{
-	gchar *name;
-	g_object_get(content, "name", &name, NULL);
-	return name;
-}
-
-gchar *
-jingle_content_get_senders(JingleContent *content)
-{
-	gchar *senders;
-	g_object_get(content, "senders", &senders, NULL);
-	return senders;
-}
-
-JingleTransport *
-jingle_content_get_transport(JingleContent *content)
-{
-	JingleTransport *transport;
-	g_object_get(content, "transport", &transport, NULL);
-	return transport;
-}
-
-JingleTransport *
-jingle_content_get_pending_transport(JingleContent *content)
-{
-	JingleTransport *pending_transport;
-	g_object_get(content, "pending-transport", &pending_transport, NULL);
-	return pending_transport;
-}
-
-void
-jingle_content_set_session(JingleContent *content, JingleSession *session)
-{
-	g_return_if_fail(JINGLE_IS_CONTENT(content));
-	g_return_if_fail(JINGLE_IS_SESSION(session));
-	g_object_set(content, "session", session, NULL);
-}
-
-void
-jingle_content_set_pending_transport(JingleContent *content, JingleTransport *transport)
-{
-	g_object_set(content, "pending-transport", transport, NULL);
-}
-
-void
-jingle_content_accept_transport(JingleContent *content)
-{
-	JingleContentPrivate *priv = NULL;
-	GObject *obj;
-
-	g_return_if_fail(JINGLE_IS_CONTENT(content));
-
-	priv = jingle_content_get_instance_private(content);
-
-	if (priv->transport)
-		g_object_unref(priv->transport);
-
-	priv->transport = priv->pending_transport;
-	priv->pending_transport = NULL;
-
-	obj = G_OBJECT(content);
-	g_object_freeze_notify(obj);
-	g_object_notify_by_pspec(obj, properties[PROP_TRANSPORT]);
-	g_object_notify_by_pspec(obj, properties[PROP_PENDING_TRANSPORT]);
-	g_object_thaw_notify(obj);
-}
-
-void
-jingle_content_remove_pending_transport(JingleContent *content)
-{
-	JingleContentPrivate *priv = NULL;
-
-	g_return_if_fail(JINGLE_IS_CONTENT(content));
-
-	priv = jingle_content_get_instance_private(content);
-
-	if (priv->pending_transport) {
-		g_object_unref(priv->pending_transport);
-		priv->pending_transport = NULL;
-	}
-
-	g_object_notify_by_pspec(G_OBJECT(content), properties[PROP_PENDING_TRANSPORT]);
-}
-
-void
-jingle_content_modify(JingleContent *content, const gchar *senders)
-{
-	g_object_set(content, "senders", senders, NULL);
-}
-
-JingleContent *
-jingle_content_parse(PurpleXmlNode *content)
-{
-	const gchar *type = purple_xmlnode_get_namespace(purple_xmlnode_get_child(content, "description"));
-	GType jingle_type = jingle_get_type(type);
-
-	if (jingle_type != G_TYPE_NONE) {
-		return JINGLE_CONTENT_CLASS(g_type_class_ref(jingle_type))->parse(content);
-	} else {
-		return NULL;
-	}
-}
-
-PurpleXmlNode *
-jingle_content_to_xml(JingleContent *content, PurpleXmlNode *jingle, JingleActionType action)
-{
-	g_return_val_if_fail(content != NULL, NULL);
-	g_return_val_if_fail(JINGLE_IS_CONTENT(content), NULL);
-	return JINGLE_CONTENT_GET_CLASS(content)->to_xml(content, jingle, action);
-}
-
-void
-jingle_content_handle_action(JingleContent *content, PurpleXmlNode *xmlcontent, JingleActionType action)
-{
-	g_return_if_fail(content != NULL);
-	g_return_if_fail(JINGLE_IS_CONTENT(content));
-	JINGLE_CONTENT_GET_CLASS(content)->handle_action(content, xmlcontent, action);
-}
-
diff --git a/libpurple/protocols/jabber/jingle/iceudp.h b/libpurple/protocols/jabber/jingle/iceudp.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/jingle/iceudp.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * @file iceudp.h
- *
- * 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_JABBER_JINGLE_ICEUDP_H
-#define PURPLE_JABBER_JINGLE_ICEUDP_H
-
-#include <glib.h>
-#include <glib-object.h>
-
-#include "transport.h"
-
-G_BEGIN_DECLS
-
-#define JINGLE_TYPE_ICEUDP  jingle_iceudp_get_type()
-#define JINGLE_TYPE_ICEUDP_CANDIDATE  jingle_iceudp_candidate_get_type()
-
-/** @copydoc _JingleIceUdpCandidate */
-typedef struct _JingleIceUdpCandidate JingleIceUdpCandidate;
-
-struct _JingleIceUdpCandidate
-{
-	gchar *id;
-	guint component;
-	gchar *foundation;
-	guint generation;
-	gchar *ip;
-	guint network;
-	guint port;
-	guint priority;
-	gchar *protocol;
-	gchar *reladdr;
-	guint relport;
-	gchar *type;
-
-	gchar *username;
-	gchar *password;
-
-	gboolean rem_known;	/* TRUE if the remote side knows
-				 * about this candidate */
-};
-
-GType jingle_iceudp_candidate_get_type(void);
-
-/**
- * Gets the iceudp class's GType
- *
- * @return The iceudp class's GType.
- */
-G_MODULE_EXPORT
-G_DECLARE_FINAL_TYPE(JingleIceUdp, jingle_iceudp, JINGLE, ICEUDP,
-		JingleTransport)
-
-/**
- * Registers the JingleIceUdp type in the type system.
- */
-void jingle_iceudp_register(PurplePlugin *plugin);
-
-JingleIceUdpCandidate *jingle_iceudp_candidate_new(const gchar *id,
-		guint component, const gchar *foundation, guint generation,
-		const gchar *ip, guint network, guint port, guint priority,
-		const gchar *protocol, const gchar *type,
-		const gchar *username, const gchar *password);
-
-G_END_DECLS
-
-#endif /* PURPLE_JABBER_JINGLE_ICEUDP_H */
-
diff --git a/libpurple/protocols/jabber/jingle/iceudp.c b/libpurple/protocols/jabber/jingle/iceudp.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/jingle/iceudp.c
+++ /dev/null
@@ -1,499 +0,0 @@
-/**
- * @file iceudp.c
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "iceudp.h"
-#include "jingle.h"
-
-#include <string.h>
-
-struct _JingleIceUdp
-{
-	JingleTransport parent;
-};
-
-typedef struct
-{
-	GList *local_candidates;
-	GList *remote_candidates;
-} JingleIceUdpPrivate;
-
-enum {
-	PROP_0,
-	PROP_LOCAL_CANDIDATES,
-	PROP_REMOTE_CANDIDATES,
-	N_PROPERTIES,
-};
-
-static GParamSpec *properties[N_PROPERTIES] = {NULL, };
-
-G_DEFINE_DYNAMIC_TYPE_EXTENDED(
-	JingleIceUdp,
-	jingle_iceudp,
-	JINGLE_TYPE_TRANSPORT,
-	G_TYPE_FLAG_FINAL,
-	G_ADD_PRIVATE_DYNAMIC(JingleIceUdp)
-);
-
-/******************************************************************************
- * JingleIceUdp Transport Implementation
- *****************************************************************************/
-static void
-jingle_iceudp_add_local_candidate(JingleTransport *transport, const gchar *id, guint generation, PurpleMediaCandidate *candidate)
-{
-	JingleIceUdp *iceudp = JINGLE_ICEUDP(transport);
-	JingleIceUdpPrivate *priv = jingle_iceudp_get_instance_private(iceudp);
-	PurpleMediaCandidateType type;
-	gchar *ip;
-	gchar *username;
-	gchar *password;
-	gchar *foundation;
-	JingleIceUdpCandidate *iceudp_candidate;
-	GList *iter;
-
-	ip = purple_media_candidate_get_ip(candidate);
-	username = purple_media_candidate_get_username(candidate);
-	password = purple_media_candidate_get_password(candidate);
-	type = purple_media_candidate_get_candidate_type(candidate);
-	foundation = purple_media_candidate_get_foundation(candidate);
-
-	iceudp_candidate = jingle_iceudp_candidate_new(id,
-			purple_media_candidate_get_component_id(candidate),
-			foundation, generation, ip, 0,
-			purple_media_candidate_get_port(candidate),
-			purple_media_candidate_get_priority(candidate), "udp",
-			type == PURPLE_MEDIA_CANDIDATE_TYPE_HOST ? "host" :
-			type == PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX ? "srflx" :
-			type == PURPLE_MEDIA_CANDIDATE_TYPE_PRFLX ? "prflx" :
-			type == PURPLE_MEDIA_CANDIDATE_TYPE_RELAY ? "relay" :
-			"", username, password);
-	iceudp_candidate->reladdr = purple_media_candidate_get_base_ip(candidate);
-	iceudp_candidate->relport = purple_media_candidate_get_base_port(candidate);
-
-	g_free(password);
-	g_free(username);
-	g_free(foundation);
-	g_free(ip);
-
-	for (iter = priv->local_candidates; iter; iter = g_list_next(iter)) {
-		JingleIceUdpCandidate *c = iter->data;
-		if (purple_strequal(c->id, id)) {
-			generation = c->generation + 1;
-
-			g_boxed_free(JINGLE_TYPE_ICEUDP_CANDIDATE, c);
-			priv->local_candidates = g_list_delete_link(
-					priv->local_candidates, iter);
-
-			iceudp_candidate->generation = generation;
-
-			priv->local_candidates = g_list_append(
-					priv->local_candidates, iceudp_candidate);
-
-			g_object_notify_by_pspec(G_OBJECT(iceudp), properties[PROP_LOCAL_CANDIDATES]);
-
-			return;
-		}
-	}
-
-	priv->local_candidates = g_list_append(
-			priv->local_candidates, iceudp_candidate);
-
-	g_object_notify_by_pspec(G_OBJECT(iceudp), properties[PROP_LOCAL_CANDIDATES]);
-}
-
-static GList *
-jingle_iceudp_get_remote_candidates(JingleTransport *transport)
-{
-	JingleIceUdp *iceudp = JINGLE_ICEUDP(transport);
-	JingleIceUdpPrivate *priv = jingle_iceudp_get_instance_private(iceudp);
-	GList *candidates = priv->remote_candidates;
-	GList *ret = NULL;
-
-	for (; candidates; candidates = g_list_next(candidates)) {
-		JingleIceUdpCandidate *candidate = candidates->data;
-		PurpleMediaCandidate *new_candidate = purple_media_candidate_new(
-					candidate->foundation, candidate->component,
-					purple_strequal(candidate->type, "host") ?
-						PURPLE_MEDIA_CANDIDATE_TYPE_HOST :
-						purple_strequal(candidate->type, "srflx") ?
-							PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX :
-							purple_strequal(candidate->type, "prflx") ?
-								PURPLE_MEDIA_CANDIDATE_TYPE_PRFLX :
-								purple_strequal(candidate->type, "relay") ?
-									PURPLE_MEDIA_CANDIDATE_TYPE_RELAY : 0,
-					PURPLE_MEDIA_NETWORK_PROTOCOL_UDP,
-					candidate->ip, candidate->port);
-		g_object_set(new_candidate,
-		             "base-ip", candidate->reladdr,
-		             "base-port", candidate->relport,
-		             "username", candidate->username,
-		             "password", candidate->password,
-		             "priority", candidate->priority,
-		             NULL);
-		ret = g_list_append(ret, new_candidate);
-	}
-
-	return ret;
-}
-
-static JingleIceUdpCandidate *
-jingle_iceudp_get_remote_candidate_by_id(JingleIceUdp *iceudp,
-		const gchar *id)
-{
-	JingleIceUdpPrivate *priv = jingle_iceudp_get_instance_private(iceudp);
-	GList *iter = priv->remote_candidates;
-	for (; iter; iter = g_list_next(iter)) {
-		JingleIceUdpCandidate *candidate = iter->data;
-		if (purple_strequal(candidate->id, id)) {
-			return candidate;
-		}
-	}
-	return NULL;
-}
-
-static void
-jingle_iceudp_add_remote_candidate(JingleIceUdp *iceudp, JingleIceUdpCandidate *candidate)
-{
-	JingleIceUdpPrivate *priv = jingle_iceudp_get_instance_private(iceudp);
-	JingleIceUdpCandidate *iceudp_candidate =
-			jingle_iceudp_get_remote_candidate_by_id(iceudp,
-					candidate->id);
-	if (iceudp_candidate != NULL) {
-		priv->remote_candidates = g_list_remove(
-				priv->remote_candidates, iceudp_candidate);
-		g_boxed_free(JINGLE_TYPE_ICEUDP_CANDIDATE, iceudp_candidate);
-	}
-	priv->remote_candidates = g_list_append(priv->remote_candidates, candidate);
-
-	g_object_notify_by_pspec(G_OBJECT(iceudp), properties[PROP_REMOTE_CANDIDATES]);
-}
-
-static JingleTransport *
-jingle_iceudp_parse_internal(PurpleXmlNode *iceudp)
-{
-	JingleTransport *transport = JINGLE_TRANSPORT_CLASS(jingle_iceudp_parent_class)->parse(iceudp);
-	PurpleXmlNode *candidate = purple_xmlnode_get_child(iceudp, "candidate");
-	JingleIceUdpCandidate *iceudp_candidate = NULL;
-
-	const gchar *username = purple_xmlnode_get_attrib(iceudp, "ufrag");
-	const gchar *password = purple_xmlnode_get_attrib(iceudp, "pwd");
-
-	for (; candidate; candidate = purple_xmlnode_get_next_twin(candidate)) {
-		const gchar *relport = purple_xmlnode_get_attrib(candidate, "rel-port");
-		const gchar *component = purple_xmlnode_get_attrib(candidate, "component");
-		const gchar *foundation = purple_xmlnode_get_attrib(candidate, "foundation");
-		const gchar *generation = purple_xmlnode_get_attrib(candidate, "generation");
-		const gchar *id = purple_xmlnode_get_attrib(candidate, "id");
-		const gchar *ip = purple_xmlnode_get_attrib(candidate, "ip");
-		const gchar *network = purple_xmlnode_get_attrib(candidate, "network");
-		const gchar *port = purple_xmlnode_get_attrib(candidate, "port");
-		const gchar *priority = purple_xmlnode_get_attrib(candidate, "priority");
-		const gchar *protocol = purple_xmlnode_get_attrib(candidate, "protocol");
-		const gchar *type = purple_xmlnode_get_attrib(candidate, "type");
-
-		if (!component || !foundation || !generation || !id || !ip ||
-				!network || !port || !priority || !protocol || !type)
-			continue;
-
-		iceudp_candidate = jingle_iceudp_candidate_new(
-				id,
-				atoi(component),
-				foundation,
-				atoi(generation),
-				ip,
-				atoi(network),
-				atoi(port),
-				atoi(priority),
-				protocol,
-				type,
-				username, password);
-		iceudp_candidate->reladdr = g_strdup(
-				purple_xmlnode_get_attrib(candidate, "rel-addr"));
-		iceudp_candidate->relport =
-				relport != NULL ? atoi(relport) : 0;
-		iceudp_candidate->rem_known = TRUE;
-		jingle_iceudp_add_remote_candidate(JINGLE_ICEUDP(transport), iceudp_candidate);
-	}
-
-	return transport;
-}
-
-static PurpleXmlNode *
-jingle_iceudp_to_xml_internal(JingleTransport *transport, PurpleXmlNode *content, JingleActionType action)
-{
-	PurpleXmlNode *node = JINGLE_TRANSPORT_CLASS(jingle_iceudp_parent_class)->to_xml(transport, content, action);
-
-	if (action == JINGLE_SESSION_INITIATE ||
-			action == JINGLE_SESSION_ACCEPT ||
-			action == JINGLE_TRANSPORT_INFO ||
-			action == JINGLE_CONTENT_ADD ||
-			action == JINGLE_TRANSPORT_REPLACE) {
-		JingleIceUdpPrivate *priv = jingle_iceudp_get_instance_private(JINGLE_ICEUDP(transport));
-		GList *iter = priv->local_candidates;
-		gboolean used_candidate = FALSE;
-
-		for (; iter; iter = g_list_next(iter)) {
-			JingleIceUdpCandidate *candidate = iter->data;
-			PurpleXmlNode *xmltransport;
-			gchar *component, *generation, *network,
-					*port, *priority;
-
-			if (candidate->rem_known == TRUE)
-				continue;
-
-			used_candidate = TRUE;
-			candidate->rem_known = TRUE;
-
-			xmltransport = purple_xmlnode_new_child(node, "candidate");
-			component = g_strdup_printf("%d", candidate->component);
-			generation = g_strdup_printf("%d",
-					candidate->generation);
-			network = g_strdup_printf("%d", candidate->network);
-			port = g_strdup_printf("%d", candidate->port);
-			priority = g_strdup_printf("%d", candidate->priority);
-
-			purple_xmlnode_set_attrib(xmltransport, "component", component);
-			purple_xmlnode_set_attrib(xmltransport, "foundation", candidate->foundation);
-			purple_xmlnode_set_attrib(xmltransport, "generation", generation);
-			purple_xmlnode_set_attrib(xmltransport, "id", candidate->id);
-			purple_xmlnode_set_attrib(xmltransport, "ip", candidate->ip);
-			purple_xmlnode_set_attrib(xmltransport, "network", network);
-			purple_xmlnode_set_attrib(xmltransport, "port", port);
-			purple_xmlnode_set_attrib(xmltransport, "priority", priority);
-			purple_xmlnode_set_attrib(xmltransport, "protocol", candidate->protocol);
-
-			if (candidate->reladdr != NULL &&
-					(!purple_strequal(candidate->ip, candidate->reladdr) ||
-					(candidate->port != candidate->relport))) {
-				gchar *relport = g_strdup_printf("%d",
-						candidate->relport);
-				purple_xmlnode_set_attrib(xmltransport, "rel-addr",
-						candidate->reladdr);
-				purple_xmlnode_set_attrib(xmltransport, "rel-port",
-						relport);
-				g_free(relport);
-			}
-
-			purple_xmlnode_set_attrib(xmltransport, "type", candidate->type);
-
-			g_free(component);
-			g_free(generation);
-			g_free(network);
-			g_free(port);
-			g_free(priority);
-		}
-
-		if (used_candidate == TRUE) {
-			JingleIceUdpCandidate *candidate =
-					priv->local_candidates->data;
-			purple_xmlnode_set_attrib(node, "pwd", candidate->password);
-			purple_xmlnode_set_attrib(node, "ufrag", candidate->username);
-		}
-	}
-
-	return node;
-}
-
-/******************************************************************************
- * JingleIceUdp GObject Implementation
- *****************************************************************************/
-static void
-jingle_iceudp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
-	JingleIceUdp *iceudp = JINGLE_ICEUDP(object);
-	JingleIceUdpPrivate *priv = jingle_iceudp_get_instance_private(iceudp);
-
-	switch (prop_id) {
-		case PROP_LOCAL_CANDIDATES:
-			priv->local_candidates =
-					g_value_get_pointer(value);
-			break;
-		case PROP_REMOTE_CANDIDATES:
-			priv->remote_candidates =
-					g_value_get_pointer(value);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
-static void
-jingle_iceudp_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
-	JingleIceUdp *iceudp = JINGLE_ICEUDP(object);
-	JingleIceUdpPrivate *priv = jingle_iceudp_get_instance_private(iceudp);
-
-	switch (prop_id) {
-		case PROP_LOCAL_CANDIDATES:
-			g_value_set_pointer(value, priv->local_candidates);
-			break;
-		case PROP_REMOTE_CANDIDATES:
-			g_value_set_pointer(value, priv->remote_candidates);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
-static void
-jingle_iceudp_init(G_GNUC_UNUSED JingleIceUdp *iceudp)
-{
-}
-
-static void
-jingle_iceudp_candidate_free(JingleIceUdpCandidate *candidate);
-
-static void
-jingle_iceudp_finalize (GObject *object)
-{
-	JingleIceUdp *iceudp = JINGLE_ICEUDP(object);
-	JingleIceUdpPrivate *priv = jingle_iceudp_get_instance_private(iceudp);
-
-	purple_debug_info("jingle","jingle_iceudp_finalize\n");
-
-	g_list_free_full(priv->local_candidates,
-			(GDestroyNotify)jingle_iceudp_candidate_free);
-	g_list_free_full(priv->remote_candidates,
-			(GDestroyNotify)jingle_iceudp_candidate_free);
-
-	G_OBJECT_CLASS(jingle_iceudp_parent_class)->finalize(object);
-}
-
-static void
-jingle_iceudp_class_finalize(G_GNUC_UNUSED JingleIceUdpClass *klass)
-{
-}
-
-static void
-jingle_iceudp_class_init (JingleIceUdpClass *klass)
-{
-	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
-	JingleTransportClass *transport_class = JINGLE_TRANSPORT_CLASS(klass);
-
-	obj_class->finalize = jingle_iceudp_finalize;
-	obj_class->set_property = jingle_iceudp_set_property;
-	obj_class->get_property = jingle_iceudp_get_property;
-
-	transport_class->to_xml = jingle_iceudp_to_xml_internal;
-	transport_class->parse = jingle_iceudp_parse_internal;
-	transport_class->transport_type = JINGLE_TRANSPORT_ICEUDP;
-	transport_class->add_local_candidate = jingle_iceudp_add_local_candidate;
-	transport_class->get_remote_candidates = jingle_iceudp_get_remote_candidates;
-
-	properties[PROP_LOCAL_CANDIDATES] = g_param_spec_pointer("local-candidates",
-			"Local candidates",
-			"The local candidates for this transport.",
-			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_REMOTE_CANDIDATES] = g_param_spec_pointer("remote-candidates",
-			"Remote candidates",
-			"The remote candidates for this transport.",
-			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-	g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
-}
-
-/******************************************************************************
- * JingleIceUdpCandidate Boxed Implementation
- *****************************************************************************/
-static JingleIceUdpCandidate *
-jingle_iceudp_candidate_copy(JingleIceUdpCandidate *candidate)
-{
-	JingleIceUdpCandidate *new_candidate = g_new0(JingleIceUdpCandidate, 1);
-	new_candidate->id = g_strdup(candidate->id);
-	new_candidate->component = candidate->component;
-	new_candidate->foundation = g_strdup(candidate->foundation);
-	new_candidate->generation = candidate->generation;
-	new_candidate->ip = g_strdup(candidate->ip);
-	new_candidate->network = candidate->network;
-	new_candidate->port = candidate->port;
-	new_candidate->priority = candidate->priority;
-	new_candidate->protocol = g_strdup(candidate->protocol);
-	new_candidate->type = g_strdup(candidate->type);
-
-	new_candidate->username = g_strdup(candidate->username);
-	new_candidate->password = g_strdup(candidate->password);
-
-	new_candidate->rem_known = candidate->rem_known;
-
-	return new_candidate;
-}
-
-static void
-jingle_iceudp_candidate_free(JingleIceUdpCandidate *candidate)
-{
-	g_free(candidate->foundation);
-	g_free(candidate->id);
-	g_free(candidate->ip);
-	g_free(candidate->protocol);
-	g_free(candidate->reladdr);
-	g_free(candidate->type);
-
-	g_free(candidate->username);
-	g_free(candidate->password);
-	g_free(candidate);
-}
-
-G_DEFINE_BOXED_TYPE(JingleIceUdpCandidate, jingle_iceudp_candidate,
-		jingle_iceudp_candidate_copy, jingle_iceudp_candidate_free)
-
-/******************************************************************************
- * Public API
- *****************************************************************************/
-void
-jingle_iceudp_register(PurplePlugin *plugin) {
-	jingle_iceudp_register_type(G_TYPE_MODULE(plugin));
-}
-
-JingleIceUdpCandidate *
-jingle_iceudp_candidate_new(const gchar *id,
-		guint component, const gchar *foundation,
-		guint generation, const gchar *ip,
-		guint network, guint port, guint priority,
-		const gchar *protocol, const gchar *type,
-		const gchar *username, const gchar *password)
-{
-	JingleIceUdpCandidate *candidate = g_new0(JingleIceUdpCandidate, 1);
-	candidate->id = g_strdup(id);
-	candidate->component = component;
-	candidate->foundation = g_strdup(foundation);
-	candidate->generation = generation;
-	candidate->ip = g_strdup(ip);
-	candidate->network = network;
-	candidate->port = port;
-	candidate->priority = priority;
-	candidate->protocol = g_strdup(protocol);
-	candidate->type = g_strdup(type);
-
-	candidate->username = g_strdup(username);
-	candidate->password = g_strdup(password);
-
-	candidate->rem_known = FALSE;
-	return candidate;
-}
diff --git a/libpurple/protocols/jabber/jingle/jingle.h b/libpurple/protocols/jabber/jingle/jingle.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/jingle/jingle.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * @file jingle.h
- *
- * 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 Library 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 PURPLE_JABBER_JINGLE_H
-#define PURPLE_JABBER_JINGLE_H
-
-#include "jabber.h"
-
-#include <glib.h>
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-#define JINGLE "urn:xmpp:jingle:1"
-#define JINGLE_ERROR "urn:xmpp:jingle:errors:0"
-#define JINGLE_APP_FT "urn:xmpp:jingle:apps:file-transfer:1"
-#define JINGLE_APP_RTP "urn:xmpp:jingle:apps:rtp:1"
-#define JINGLE_APP_RTP_ERROR "urn:xmpp:jingle:apps:rtp:errors:1"
-#define JINGLE_APP_RTP_INFO "urn:xmpp:jingle:apps:rtp:info:1"
-#define JINGLE_APP_RTP_SUPPORT_AUDIO "urn:xmpp:jingle:apps:rtp:audio"
-#define JINGLE_APP_RTP_SUPPORT_VIDEO "urn:xmpp:jingle:apps:rtp:video"
-#define JINGLE_APP_XML "urn:xmpp:tmp:jingle:apps:xmlstream"
-#define JINGLE_DTMF "urn:xmpp:jingle:dtmf:0"
-#define JINGLE_TRANSPORT_S5B "urn:xmpp:jingle:transports:s5b:0"
-#define JINGLE_TRANSPORT_IBB "urn:xmpp:jingle:transports:ibb:0"
-#define JINGLE_TRANSPORT_ICEUDP "urn:xmpp:jingle:transports:ice-udp:1"
-#define JINGLE_TRANSPORT_RAWUDP "urn:xmpp:jingle:transports:raw-udp:1"
-
-typedef enum {
-	JINGLE_UNKNOWN_TYPE,
-	JINGLE_CONTENT_ACCEPT,
-	JINGLE_CONTENT_ADD,
-	JINGLE_CONTENT_MODIFY,
-	JINGLE_CONTENT_REJECT,
-	JINGLE_CONTENT_REMOVE,
-	JINGLE_DESCRIPTION_INFO,
-	JINGLE_SECURITY_INFO,
-	JINGLE_SESSION_ACCEPT,
-	JINGLE_SESSION_INFO,
-	JINGLE_SESSION_INITIATE,
-	JINGLE_SESSION_TERMINATE,
-	JINGLE_TRANSPORT_ACCEPT,
-	JINGLE_TRANSPORT_INFO,
-	JINGLE_TRANSPORT_REJECT,
-	JINGLE_TRANSPORT_REPLACE,
-} JingleActionType;
-
-const gchar *jingle_get_action_name(JingleActionType action);
-JingleActionType jingle_get_action_type(const gchar *action);
-
-GType jingle_get_type(const gchar *type);
-
-void jingle_parse(JabberStream *js, const char *from, JabberIqType type,
-                  const char *id, PurpleXmlNode *child);
-
-void jingle_terminate_sessions(JabberStream *js);
-
-/* create a parameter array given autoconfigured STUN (and later perhaps TURN). */
-GHashTable *jingle_get_params(JabberStream *js, const gchar *relay_ip,
-	guint relay_udp, guint relay_tcp, guint relay_ssltcp,
-	const gchar *relay_username, const gchar *relay_password);
-
-G_END_DECLS
-
-#endif /* PURPLE_JABBER_JINGLE_H */
diff --git a/libpurple/protocols/jabber/jingle/jingle.c b/libpurple/protocols/jabber/jingle/jingle.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/jingle/jingle.c
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * @file jingle.c
- *
- * purple - Jabber Protocol Plugin
- *
- * 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 <purple.h>
-
-#include "content.h"
-#include "jingle.h"
-#include "session.h"
-#include "iceudp.h"
-#include "rawudp.h"
-#include "rtp.h"
-
-#include <string.h>
-#include <gst/gst.h>
-
-GType
-jingle_get_type(const gchar *type)
-{
-	if (type == NULL)
-		return G_TYPE_NONE;
-
-	if (purple_strequal(type, JINGLE_TRANSPORT_RAWUDP))
-		return JINGLE_TYPE_RAWUDP;
-	else if (purple_strequal(type, JINGLE_TRANSPORT_ICEUDP))
-		return JINGLE_TYPE_ICEUDP;
-	else if (purple_strequal(type, JINGLE_APP_RTP))
-		return JINGLE_TYPE_RTP;
-	else
-		return G_TYPE_NONE;
-}
-
-static void
-jingle_handle_unknown_type(G_GNUC_UNUSED JingleSession *session,
-                           G_GNUC_UNUSED PurpleXmlNode *jingle)
-{
-	/* Send error */
-}
-
-static void
-jingle_handle_content_accept(JingleSession *session, PurpleXmlNode *jingle)
-{
-	PurpleXmlNode *content = purple_xmlnode_get_child(jingle, "content");
-	jabber_iq_send(jingle_session_create_ack(session, jingle));
-
-	for (; content; content = purple_xmlnode_get_next_twin(content)) {
-		const gchar *name = purple_xmlnode_get_attrib(content, "name");
-		const gchar *creator = purple_xmlnode_get_attrib(content, "creator");
-		jingle_session_accept_content(session, name, creator);
-		/* signal here */
-	}
-}
-
-static void
-jingle_handle_content_add(JingleSession *session, PurpleXmlNode *jingle)
-{
-	PurpleXmlNode *content = purple_xmlnode_get_child(jingle, "content");
-	jabber_iq_send(jingle_session_create_ack(session, jingle));
-
-	for (; content; content = purple_xmlnode_get_next_twin(content)) {
-		JingleContent *pending_content =
-				jingle_content_parse(content);
-		if (pending_content == NULL) {
-			purple_debug_error("jingle",
-					"Error parsing \"content-add\" content.\n");
-			jabber_iq_send(jingle_session_terminate_packet(session,
-				"unsupported-applications"));
-		} else {
-			jingle_session_add_pending_content(session,
-					pending_content);
-		}
-	}
-
-	/* XXX: signal here */
-}
-
-static void
-jingle_handle_content_modify(JingleSession *session, PurpleXmlNode *jingle)
-{
-	PurpleXmlNode *content = purple_xmlnode_get_child(jingle, "content");
-	jabber_iq_send(jingle_session_create_ack(session, jingle));
-
-	for (; content; content = purple_xmlnode_get_next_twin(content)) {
-		const gchar *name = purple_xmlnode_get_attrib(content, "name");
-		const gchar *creator = purple_xmlnode_get_attrib(content, "creator");
-		JingleContent *local_content = jingle_session_find_content(session, name, creator);
-
-		if (local_content != NULL) {
-			const gchar *senders = purple_xmlnode_get_attrib(content, "senders");
-			gchar *local_senders = jingle_content_get_senders(local_content);
-			if (!purple_strequal(senders, local_senders))
-				jingle_content_modify(local_content, senders);
-			g_free(local_senders);
-		} else {
-			purple_debug_error("jingle", "content_modify: unknown content\n");
-			jabber_iq_send(jingle_session_terminate_packet(session,
-				"unknown-applications"));
-		}
-	}
-}
-
-static void
-jingle_handle_content_reject(JingleSession *session, PurpleXmlNode *jingle)
-{
-	PurpleXmlNode *content = purple_xmlnode_get_child(jingle, "content");
-	jabber_iq_send(jingle_session_create_ack(session, jingle));
-
-	for (; content; content = purple_xmlnode_get_next_twin(content)) {
-		const gchar *name = purple_xmlnode_get_attrib(content, "name");
-		const gchar *creator = purple_xmlnode_get_attrib(content, "creator");
-		jingle_session_remove_pending_content(session, name, creator);
-		/* signal here */
-	}
-}
-
-static void
-jingle_handle_content_remove(JingleSession *session, PurpleXmlNode *jingle)
-{
-	PurpleXmlNode *content = purple_xmlnode_get_child(jingle, "content");
-
-	jabber_iq_send(jingle_session_create_ack(session, jingle));
-
-	for (; content; content = purple_xmlnode_get_next_twin(content)) {
-		const gchar *name = purple_xmlnode_get_attrib(content, "name");
-		const gchar *creator = purple_xmlnode_get_attrib(content, "creator");
-		jingle_session_remove_content(session, name, creator);
-	}
-}
-
-static void
-jingle_handle_description_info(JingleSession *session, PurpleXmlNode *jingle)
-{
-	PurpleXmlNode *content = purple_xmlnode_get_child(jingle, "content");
-
-	jabber_iq_send(jingle_session_create_ack(session, jingle));
-
-	jingle_session_accept_session(session);
-
-	for (; content; content = purple_xmlnode_get_next_twin(content)) {
-		const gchar *name = purple_xmlnode_get_attrib(content, "name");
-		const gchar *creator = purple_xmlnode_get_attrib(content, "creator");
-		JingleContent *parsed_content =
-				jingle_session_find_content(session, name, creator);
-		if (parsed_content == NULL) {
-			purple_debug_error("jingle", "Error parsing content\n");
-			jabber_iq_send(jingle_session_terminate_packet(session,
-				"unsupported-applications"));
-		} else {
-			jingle_content_handle_action(parsed_content, content,
-					JINGLE_DESCRIPTION_INFO);
-		}
-	}
-}
-
-static void
-jingle_handle_security_info(JingleSession *session, PurpleXmlNode *jingle)
-{
-	jabber_iq_send(jingle_session_create_ack(session, jingle));
-}
-
-static void
-jingle_handle_session_accept(JingleSession *session, PurpleXmlNode *jingle)
-{
-	PurpleXmlNode *content = purple_xmlnode_get_child(jingle, "content");
-
-	jabber_iq_send(jingle_session_create_ack(session, jingle));
-
-	jingle_session_accept_session(session);
-
-	for (; content; content = purple_xmlnode_get_next_twin(content)) {
-		const gchar *name = purple_xmlnode_get_attrib(content, "name");
-		const gchar *creator = purple_xmlnode_get_attrib(content, "creator");
-		JingleContent *parsed_content =
-				jingle_session_find_content(session, name, creator);
-		if (parsed_content == NULL) {
-			purple_debug_error("jingle", "Error parsing content\n");
-			jabber_iq_send(jingle_session_terminate_packet(session,
-				"unsupported-applications"));
-		} else {
-			jingle_content_handle_action(parsed_content, content,
-					JINGLE_SESSION_ACCEPT);
-		}
-	}
-}
-
-static void
-jingle_handle_session_info(JingleSession *session, PurpleXmlNode *jingle)
-{
-	jabber_iq_send(jingle_session_create_ack(session, jingle));
-	/* XXX: call signal */
-}
-
-static void
-jingle_handle_session_initiate(JingleSession *session, PurpleXmlNode *jingle)
-{
-	PurpleXmlNode *content = purple_xmlnode_get_child(jingle, "content");
-
-	for (; content; content = purple_xmlnode_get_next_twin(content)) {
-		JingleContent *parsed_content = jingle_content_parse(content);
-		if (parsed_content == NULL) {
-			purple_debug_error("jingle", "Error parsing content\n");
-			jabber_iq_send(jingle_session_terminate_packet(session,
-				"unsupported-applications"));
-		} else {
-			jingle_session_add_content(session, parsed_content);
-			/* since we don't have the possibility to enable
-			 * our local video after the video connection is
-			 * established, we ignore senders of type
-			 * 'initiator', and reply with senders of type
-			 * 'both' instead.
-			 */
-			jingle_content_modify(parsed_content, "both");
-			jingle_content_handle_action(parsed_content, content,
-					JINGLE_SESSION_INITIATE);
-		}
-	}
-
-	jabber_iq_send(jingle_session_create_ack(session, jingle));
-}
-
-static void
-jingle_handle_session_terminate(JingleSession *session, PurpleXmlNode *jingle)
-{
-	jabber_iq_send(jingle_session_create_ack(session, jingle));
-
-	jingle_session_handle_action(session, jingle,
-			JINGLE_SESSION_TERMINATE);
-	/* display reason? */
-	g_object_unref(session);
-}
-
-static void
-jingle_handle_transport_accept(JingleSession *session, PurpleXmlNode *jingle)
-{
-	PurpleXmlNode *content = purple_xmlnode_get_child(jingle, "content");
-
-	jabber_iq_send(jingle_session_create_ack(session, jingle));
-
-	for (; content; content = purple_xmlnode_get_next_twin(content)) {
-		const gchar *name = purple_xmlnode_get_attrib(content, "name");
-		const gchar *creator = purple_xmlnode_get_attrib(content, "creator");
-		JingleContent *content = jingle_session_find_content(session, name, creator);
-		jingle_content_accept_transport(content);
-	}
-}
-
-static void
-jingle_handle_transport_info(JingleSession *session, PurpleXmlNode *jingle)
-{
-	PurpleXmlNode *content = purple_xmlnode_get_child(jingle, "content");
-
-	jabber_iq_send(jingle_session_create_ack(session, jingle));
-
-	for (; content; content = purple_xmlnode_get_next_twin(content)) {
-		const gchar *name = purple_xmlnode_get_attrib(content, "name");
-		const gchar *creator = purple_xmlnode_get_attrib(content, "creator");
-		JingleContent *parsed_content =
-				jingle_session_find_content(session, name, creator);
-		if (parsed_content == NULL) {
-			purple_debug_error("jingle", "Error parsing content\n");
-			jabber_iq_send(jingle_session_terminate_packet(session,
-				"unsupported-applications"));
-		} else {
-			jingle_content_handle_action(parsed_content, content,
-					JINGLE_TRANSPORT_INFO);
-		}
-	}
-}
-
-static void
-jingle_handle_transport_reject(JingleSession *session, PurpleXmlNode *jingle)
-{
-	PurpleXmlNode *content = purple_xmlnode_get_child(jingle, "content");
-
-	jabber_iq_send(jingle_session_create_ack(session, jingle));
-
-	for (; content; content = purple_xmlnode_get_next_twin(content)) {
-		const gchar *name = purple_xmlnode_get_attrib(content, "name");
-		const gchar *creator = purple_xmlnode_get_attrib(content, "creator");
-		JingleContent *content = jingle_session_find_content(session, name, creator);
-		jingle_content_remove_pending_transport(content);
-	}
-}
-
-static void
-jingle_handle_transport_replace(JingleSession *session, PurpleXmlNode *jingle)
-{
-	PurpleXmlNode *content = purple_xmlnode_get_child(jingle, "content");
-
-	jabber_iq_send(jingle_session_create_ack(session, jingle));
-
-	for (; content; content = purple_xmlnode_get_next_twin(content)) {
-		const gchar *name = purple_xmlnode_get_attrib(content, "name");
-		const gchar *creator = purple_xmlnode_get_attrib(content, "creator");
-		PurpleXmlNode *xmltransport = purple_xmlnode_get_child(content, "transport");
-		JingleTransport *transport = jingle_transport_parse(xmltransport);
-		JingleContent *content = jingle_session_find_content(session, name, creator);
-
-		jingle_content_set_pending_transport(content, transport);
-	}
-}
-
-typedef struct {
-	const char *name;
-	void (*handler)(JingleSession*, PurpleXmlNode*);
-} JingleAction;
-
-static const JingleAction jingle_actions[] = {
-	{"unknown-type",	jingle_handle_unknown_type},
-	{"content-accept",	jingle_handle_content_accept},
-	{"content-add",		jingle_handle_content_add},
-	{"content-modify",	jingle_handle_content_modify},
-	{"content-reject",	jingle_handle_content_reject},
-	{"content-remove",	jingle_handle_content_remove},
-	{"description-info",	jingle_handle_description_info},
-	{"security-info",	jingle_handle_security_info},
-	{"session-accept",	jingle_handle_session_accept},
-	{"session-info",	jingle_handle_session_info},
-	{"session-initiate",	jingle_handle_session_initiate},
-	{"session-terminate",	jingle_handle_session_terminate},
-	{"transport-accept",	jingle_handle_transport_accept},
-	{"transport-info",	jingle_handle_transport_info},
-	{"transport-reject",	jingle_handle_transport_reject},
-	{"transport-replace",	jingle_handle_transport_replace},
-};
-
-const gchar *
-jingle_get_action_name(JingleActionType action)
-{
-	return jingle_actions[action].name;
-}
-
-JingleActionType
-jingle_get_action_type(const gchar *action)
-{
-	static const int num_actions =
-			sizeof(jingle_actions)/sizeof(JingleAction);
-	/* Start at 1 to skip the unknown-action type */
-	int i = 1;
-	for (; i < num_actions; ++i) {
-		if (purple_strequal(action, jingle_actions[i].name))
-			return i;
-	}
-	return JINGLE_UNKNOWN_TYPE;
-}
-
-void
-jingle_parse(JabberStream *js, const char *from, JabberIqType type,
-             G_GNUC_UNUSED const char *id, PurpleXmlNode *jingle)
-{
-	const gchar *action;
-	const gchar *sid;
-	JingleActionType action_type;
-	JingleSession *session;
-
-	if (type != JABBER_IQ_SET) {
-		/* TODO: send iq error here */
-		return;
-	}
-
-	if (!(action = purple_xmlnode_get_attrib(jingle, "action"))) {
-		/* TODO: send iq error here */
-		return;
-	}
-
-	action_type = jingle_get_action_type(action);
-
-	purple_debug_info("jabber", "got Jingle package action = %s\n",
-			  action);
-
-	if (!(sid = purple_xmlnode_get_attrib(jingle, "sid"))) {
-		/* send iq error here */
-		return;
-	}
-
-	if (!(session = jingle_session_find_by_sid(js, sid))
-			&& !purple_strequal(action, "session-initiate")) {
-		purple_debug_error("jingle", "jabber_jingle_session_parse couldn't find session\n");
-		/* send iq error here */
-		return;
-	}
-
-	if (action_type == JINGLE_SESSION_INITIATE) {
-		if (session) {
-			/* This should only happen if you start a session with yourself */
-			purple_debug_error("jingle", "Jingle session with "
-					"id={%s} already exists\n", sid);
-			/* send iq error */
-			return;
-		} else {
-			char *own_jid = g_strdup_printf("%s@%s/%s", js->user->node,
-					js->user->domain, js->user->resource);
-			session = jingle_session_create(js, sid, own_jid, from, FALSE);
-			g_free(own_jid);
-		}
-	}
-
-	jingle_actions[action_type].handler(session, jingle);
-}
-
-void
-jingle_terminate_sessions(JabberStream *js)
-{
-	if (js->sessions) {
-		GList *list = g_hash_table_get_values(js->sessions);
-		g_list_free_full(list, g_object_unref);
-		g_clear_pointer(&js->sessions, g_hash_table_unref);
-	}
-}
-
-static void
-jingle_create_relay_info(const gchar *ip, guint port, const gchar *username,
-	const gchar *password, const gchar *relay_type, GPtrArray *relay_info)
-{
-	GValue value;
-	GstStructure *turn_setup = gst_structure_new("relay-info",
-		"ip", G_TYPE_STRING, ip,
-		"port", G_TYPE_UINT, port,
-		"username", G_TYPE_STRING, username,
-		"password", G_TYPE_STRING, password,
-		"relay-type", G_TYPE_STRING, relay_type,
-		NULL);
-	purple_debug_info("jabber", "created gst_structure %p\n", turn_setup);
-	if (turn_setup) {
-		memset(&value, 0, sizeof(GValue));
-		g_value_init(&value, GST_TYPE_STRUCTURE);
-		gst_value_set_structure(&value, turn_setup);
-		g_ptr_array_add(relay_info, &value);
-		gst_structure_free(turn_setup);
-	}
-}
-
-static void
-jingle_param_free(GValue *value)
-{
-	g_value_unset(value);
-	g_free(value);
-}
-
-GHashTable *
-jingle_get_params(G_GNUC_UNUSED JabberStream *js, const gchar *relay_ip,
-                  guint relay_udp, guint relay_tcp, guint relay_ssltcp,
-                  const gchar *relay_username, const gchar *relay_password)
-{
-	GHashTable *params = NULL;
-	GValue *value = NULL;
-
-	if(relay_ip) {
-		GPtrArray *relay_info = g_ptr_array_new_full(1, (GDestroyNotify)gst_structure_free);
-
-		params = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify)jingle_param_free);
-
-		if (relay_udp) {
-			jingle_create_relay_info(relay_ip, relay_udp, relay_username,
-				relay_password, "udp", relay_info);
-		}
-		if (relay_tcp) {
-			jingle_create_relay_info(relay_ip, relay_tcp, relay_username,
-				relay_password, "tcp", relay_info);
-		}
-		if (relay_ssltcp) {
-			jingle_create_relay_info(relay_ip, relay_ssltcp, relay_username,
-				relay_password, "tls", relay_info);
-		}
-		value = g_new(GValue, 1);
-		g_value_init(value, G_TYPE_PTR_ARRAY);
-		g_value_take_boxed(value, relay_info);
-		g_hash_table_insert(params, "relay-info", value);
-	}
-
-	return params;
-}
diff --git a/libpurple/protocols/jabber/jingle/rawudp.h b/libpurple/protocols/jabber/jingle/rawudp.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/jingle/rawudp.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * @file rawudp.h
- *
- * 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_JABBER_JINGLE_RAWUDP_H
-#define PURPLE_JABBER_JINGLE_RAWUDP_H
-
-#include <glib.h>
-#include <glib-object.h>
-
-#include "transport.h"
-
-G_BEGIN_DECLS
-
-#define JINGLE_TYPE_RAWUDP  jingle_rawudp_get_type()
-#define JINGLE_TYPE_RAWUDP_CANDIDATE  jingle_rawudp_candidate_get_type()
-
-/** @copydoc _JingleRawUdpCandidate */
-typedef struct _JingleRawUdpCandidate JingleRawUdpCandidate;
-
-struct _JingleRawUdpCandidate
-{
-	guint generation;
-	guint component;
-	gchar *id;
-	gchar *ip;
-	guint port;
-
-	gboolean rem_known;	/* TRUE if the remote side knows
-				 * about this candidate */
-};
-
-GType jingle_rawudp_candidate_get_type(void);
-
-/**
- * Gets the rawudp class's GType
- *
- * @return The rawudp class's GType.
- */
-G_MODULE_EXPORT
-G_DECLARE_FINAL_TYPE(JingleRawUdp, jingle_rawudp, JINGLE, RAWUDP,
-		JingleTransport)
-
-/**
- * Registers the JingleRawUdp type in the type system.
- */
-void jingle_rawudp_register(PurplePlugin *plugin);
-
-JingleRawUdpCandidate *jingle_rawudp_candidate_new(const gchar *id,
-		guint generation, guint component, const gchar *ip, guint port);
-
-G_END_DECLS
-
-#endif /* PURPLE_JABBER_JINGLE_RAWUDP_H */
-
diff --git a/libpurple/protocols/jabber/jingle/rawudp.c b/libpurple/protocols/jabber/jingle/rawudp.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/jingle/rawudp.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/**
- * @file rawudp.c
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "rawudp.h"
-#include "jingle.h"
-
-#include <string.h>
-
-struct _JingleRawUdp
-{
-	JingleTransport parent;
-};
-
-typedef struct
-{
-	GList *local_candidates;
-	GList *remote_candidates;
-} JingleRawUdpPrivate;
-
-enum {
-	PROP_0,
-	PROP_LOCAL_CANDIDATES,
-	PROP_REMOTE_CANDIDATES,
-	N_PROPERTIES,
-};
-static GParamSpec *properties[N_PROPERTIES] = {NULL, };
-
-G_DEFINE_DYNAMIC_TYPE_EXTENDED(
-	JingleRawUdp,
-	jingle_rawudp,
-	JINGLE_TYPE_TRANSPORT,
-	G_TYPE_FLAG_FINAL,
-	G_ADD_PRIVATE_DYNAMIC(JingleRawUdp)
-);
-
-/******************************************************************************
- * JingleRawUdp Transport Implementation
- *****************************************************************************/
-static GList *
-jingle_rawudp_get_remote_candidates(JingleTransport *transport)
-{
-	JingleRawUdp *rawudp = JINGLE_RAWUDP(transport);
-	JingleRawUdpPrivate *priv = jingle_rawudp_get_instance_private(rawudp);
-	GList *candidates = priv->remote_candidates;
-	GList *ret = NULL;
-
-	for (; candidates; candidates = g_list_next(candidates)) {
-		JingleRawUdpCandidate *candidate = candidates->data;
-		ret = g_list_append(ret, purple_media_candidate_new("",
-					candidate->component,
-					PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX,
-					PURPLE_MEDIA_NETWORK_PROTOCOL_UDP,
-					candidate->ip, candidate->port));
-	}
-
-	return ret;
-}
-
-static JingleRawUdpCandidate *
-jingle_rawudp_get_remote_candidate_by_id(JingleRawUdp *rawudp, gchar *id)
-{
-	JingleRawUdpPrivate *priv = jingle_rawudp_get_instance_private(rawudp);
-
-	GList *iter = priv->remote_candidates;
-	for (; iter; iter = g_list_next(iter)) {
-		JingleRawUdpCandidate *candidate = iter->data;
-		if (purple_strequal(candidate->id, id)) {
-			return candidate;
-		}
-	}
-	return NULL;
-}
-
-static void
-jingle_rawudp_add_remote_candidate(JingleRawUdp *rawudp, JingleRawUdpCandidate *candidate)
-{
-	JingleRawUdpPrivate *priv = jingle_rawudp_get_instance_private(rawudp);
-	JingleRawUdpCandidate *rawudp_candidate =
-			jingle_rawudp_get_remote_candidate_by_id(rawudp, candidate->id);
-	if (rawudp_candidate != NULL) {
-		priv->remote_candidates = g_list_remove(
-				priv->remote_candidates, rawudp_candidate);
-		g_boxed_free(JINGLE_TYPE_RAWUDP_CANDIDATE, rawudp_candidate);
-	}
-	priv->remote_candidates = g_list_append(priv->remote_candidates, candidate);
-
-	g_object_notify_by_pspec(G_OBJECT(rawudp), properties[PROP_REMOTE_CANDIDATES]);
-}
-
-static PurpleXmlNode *
-jingle_rawudp_to_xml_internal(JingleTransport *transport, PurpleXmlNode *content, JingleActionType action)
-{
-	PurpleXmlNode *node = JINGLE_TRANSPORT_CLASS(jingle_rawudp_parent_class)->to_xml(transport, content, action);
-
-	if (action == JINGLE_SESSION_INITIATE ||
-			action == JINGLE_TRANSPORT_INFO ||
-			action == JINGLE_SESSION_ACCEPT) {
-		JingleRawUdpPrivate *priv = jingle_rawudp_get_instance_private(JINGLE_RAWUDP(transport));
-		GList *iter = priv->local_candidates;
-
-		for (; iter; iter = g_list_next(iter)) {
-			JingleRawUdpCandidate *candidate = iter->data;
-			PurpleXmlNode *xmltransport;
-			gchar *generation, *component, *port;
-
-			if (candidate->rem_known == TRUE)
-				continue;
-			candidate->rem_known = TRUE;
-
-			xmltransport = purple_xmlnode_new_child(node, "candidate");
-			generation = g_strdup_printf("%d", candidate->generation);
-			component = g_strdup_printf("%d", candidate->component);
-			port = g_strdup_printf("%d", candidate->port);
-
-			purple_xmlnode_set_attrib(xmltransport, "generation", generation);
-			purple_xmlnode_set_attrib(xmltransport, "component", component);
-			purple_xmlnode_set_attrib(xmltransport, "id", candidate->id);
-			purple_xmlnode_set_attrib(xmltransport, "ip", candidate->ip);
-			purple_xmlnode_set_attrib(xmltransport, "port", port);
-
-			g_free(port);
-			g_free(generation);
-		}
-	}
-
-	return node;
-}
-
-static JingleTransport *
-jingle_rawudp_parse_internal(PurpleXmlNode *rawudp)
-{
-	JingleTransport *transport = JINGLE_TRANSPORT_CLASS(jingle_rawudp_parent_class)->parse(rawudp);
-	JingleRawUdpPrivate *priv = jingle_rawudp_get_instance_private(JINGLE_RAWUDP(transport));
-	PurpleXmlNode *candidate = purple_xmlnode_get_child(rawudp, "candidate");
-	JingleRawUdpCandidate *rawudp_candidate = NULL;
-
-	for (; candidate; candidate = purple_xmlnode_get_next_twin(candidate)) {
-		const gchar *id = purple_xmlnode_get_attrib(candidate, "id");
-		const gchar *generation = purple_xmlnode_get_attrib(candidate, "generation");
-		const gchar *component = purple_xmlnode_get_attrib(candidate, "component");
-		const gchar *ip = purple_xmlnode_get_attrib(candidate, "ip");
-		const gchar *port = purple_xmlnode_get_attrib(candidate, "port");
-
-		if (!id || !generation || !component || !ip || !port)
-			continue;
-
-		rawudp_candidate = jingle_rawudp_candidate_new(
-				id,
-				atoi(generation),
-				atoi(component),
-				ip,
-				atoi(port));
-		rawudp_candidate->rem_known = TRUE;
-		jingle_rawudp_add_remote_candidate(JINGLE_RAWUDP(transport), rawudp_candidate);
-	}
-
-	if (rawudp_candidate != NULL &&
-			g_list_length(priv->remote_candidates) == 1) {
-		/* manufacture rtcp candidate */
-		rawudp_candidate = g_boxed_copy(JINGLE_TYPE_RAWUDP_CANDIDATE, rawudp_candidate);
-		rawudp_candidate->component = 2;
-		rawudp_candidate->port = rawudp_candidate->port + 1;
-		rawudp_candidate->rem_known = TRUE;
-		jingle_rawudp_add_remote_candidate(JINGLE_RAWUDP(transport), rawudp_candidate);
-	}
-
-	return transport;
-}
-
-static void
-jingle_rawudp_add_local_candidate(JingleTransport *transport, const gchar *id, guint generation, PurpleMediaCandidate *candidate)
-{
-	JingleRawUdp *rawudp = JINGLE_RAWUDP(transport);
-	JingleRawUdpPrivate *priv = jingle_rawudp_get_instance_private(rawudp);
-	gchar *ip;
-	JingleRawUdpCandidate *rawudp_candidate;
-	GList *iter;
-
-	ip = purple_media_candidate_get_ip(candidate);
-	rawudp_candidate = jingle_rawudp_candidate_new(id, generation,
-			purple_media_candidate_get_component_id(candidate),
-			ip, purple_media_candidate_get_port(candidate));
-	g_free(ip);
-
-	for (iter = priv->local_candidates; iter; iter = g_list_next(iter)) {
-		JingleRawUdpCandidate *c = iter->data;
-		if (purple_strequal(c->id, id)) {
-			generation = c->generation + 1;
-
-			g_boxed_free(JINGLE_TYPE_RAWUDP_CANDIDATE, c);
-			priv->local_candidates = g_list_delete_link(
-					priv->local_candidates, iter);
-
-			rawudp_candidate->generation = generation;
-
-			priv->local_candidates = g_list_append(
-					priv->local_candidates, rawudp_candidate);
-
-			g_object_notify_by_pspec(G_OBJECT(rawudp), properties[PROP_LOCAL_CANDIDATES]);
-
-			return;
-		}
-	}
-
-	priv->local_candidates = g_list_append(
-			priv->local_candidates, rawudp_candidate);
-
-	g_object_notify_by_pspec(G_OBJECT(rawudp), properties[PROP_LOCAL_CANDIDATES]);
-}
-
-/******************************************************************************
- * JingleRawUdp GObject Stuff
- *****************************************************************************/
-static void
-jingle_rawudp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
-	JingleRawUdp *rawudp = JINGLE_RAWUDP(object);
-	JingleRawUdpPrivate *priv = jingle_rawudp_get_instance_private(rawudp);
-
-	switch (prop_id) {
-		case PROP_LOCAL_CANDIDATES:
-			priv->local_candidates = g_value_get_pointer(value);
-			break;
-		case PROP_REMOTE_CANDIDATES:
-			priv->remote_candidates = g_value_get_pointer(value);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
-static void
-jingle_rawudp_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
-	JingleRawUdp *rawudp = JINGLE_RAWUDP(object);
-	JingleRawUdpPrivate *priv = jingle_rawudp_get_instance_private(rawudp);
-
-	switch (prop_id) {
-		case PROP_LOCAL_CANDIDATES:
-			g_value_set_pointer(value, priv->local_candidates);
-			break;
-		case PROP_REMOTE_CANDIDATES:
-			g_value_set_pointer(value, priv->remote_candidates);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
-static void
-jingle_rawudp_init(G_GNUC_UNUSED JingleRawUdp *rawudp)
-{
-}
-
-static void
-jingle_rawudp_finalize (GObject *rawudp)
-{
-/*	JingleRawUdpPrivate *priv = JINGLE_RAWUDP_GET_PRIVATE(rawudp); */
-	purple_debug_info("jingle","jingle_rawudp_finalize\n");
-
-	G_OBJECT_CLASS(jingle_rawudp_parent_class)->finalize(rawudp);
-}
-
-static void
-jingle_rawudp_class_finalize(G_GNUC_UNUSED JingleRawUdpClass *klass) {
-}
-
-static void
-jingle_rawudp_class_init (JingleRawUdpClass *klass)
-{
-	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
-	JingleTransportClass *transport_class = JINGLE_TRANSPORT_CLASS(klass);
-
-	obj_class->finalize = jingle_rawudp_finalize;
-	obj_class->set_property = jingle_rawudp_set_property;
-	obj_class->get_property = jingle_rawudp_get_property;
-
-	transport_class->to_xml = jingle_rawudp_to_xml_internal;
-	transport_class->parse = jingle_rawudp_parse_internal;
-	transport_class->transport_type = JINGLE_TRANSPORT_RAWUDP;
-	transport_class->add_local_candidate = jingle_rawudp_add_local_candidate;
-	transport_class->get_remote_candidates = jingle_rawudp_get_remote_candidates;
-
-	properties[PROP_LOCAL_CANDIDATES] = g_param_spec_pointer("local-candidates",
-			"Local candidates",
-			"The local candidates for this transport.",
-			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_REMOTE_CANDIDATES] = g_param_spec_pointer("remote-candidates",
-			"Remote candidates",
-			"The remote candidates for this transport.",
-			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-	g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
-}
-
-/******************************************************************************
- * JingleRawUdpCandidate Boxed Type
- *****************************************************************************/
-static JingleRawUdpCandidate *
-jingle_rawudp_candidate_copy(JingleRawUdpCandidate *candidate)
-{
-	JingleRawUdpCandidate *new_candidate = g_new0(JingleRawUdpCandidate, 1);
-	new_candidate->generation = candidate->generation;
-	new_candidate->component = candidate->component;
-	new_candidate->id = g_strdup(candidate->id);
-	new_candidate->ip = g_strdup(candidate->ip);
-	new_candidate->port = candidate->port;
-
-	new_candidate->rem_known = candidate->rem_known;
-	return new_candidate;
-}
-
-static void
-jingle_rawudp_candidate_free(JingleRawUdpCandidate *candidate)
-{
-	g_free(candidate->id);
-	g_free(candidate->ip);
-}
-
-G_DEFINE_BOXED_TYPE(JingleRawUdpCandidate, jingle_rawudp_candidate,
-		jingle_rawudp_candidate_copy, jingle_rawudp_candidate_free)
-
-/******************************************************************************
- * Public API
- *****************************************************************************/
-void
-jingle_rawudp_register(PurplePlugin *plugin) {
-	jingle_rawudp_register_type(G_TYPE_MODULE(plugin));
-}
-
-JingleRawUdpCandidate *
-jingle_rawudp_candidate_new(const gchar *id, guint generation, guint component, const gchar *ip, guint port)
-{
-	JingleRawUdpCandidate *candidate = g_new0(JingleRawUdpCandidate, 1);
-	candidate->generation = generation;
-	candidate->component = component;
-	candidate->id = g_strdup(id);
-	candidate->ip = g_strdup(ip);
-	candidate->port = port;
-
-	candidate->rem_known = FALSE;
-	return candidate;
-}
diff --git a/libpurple/protocols/jabber/jingle/rtp.h b/libpurple/protocols/jabber/jingle/rtp.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/jingle/rtp.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * @file rtp.h
- *
- * 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_JABBER_JINGLE_RTP_H
-#define PURPLE_JABBER_JINGLE_RTP_H
-
-#include <glib.h>
-#include <glib-object.h>
-
-#include <purple.h>
-
-#include "content.h"
-
-G_BEGIN_DECLS
-
-#define JINGLE_TYPE_RTP  jingle_rtp_get_type()
-
-/**
- * Gets the rtp class's GType
- *
- * @return The rtp class's GType.
- */
-G_MODULE_EXPORT
-G_DECLARE_FINAL_TYPE(JingleRtp, jingle_rtp, JINGLE, RTP, JingleContent)
-
-/**
- * Registers the JingleRtp type in the type system.
- */
-void jingle_rtp_register(PurplePlugin *plugin);
-
-gchar *jingle_rtp_get_media_type(JingleContent *content);
-gchar *jingle_rtp_get_ssrc(JingleContent *content);
-
-gboolean jingle_rtp_initiate_media(JabberStream *js,
-				   const gchar *who,
-				   PurpleMediaSessionType type);
-void jingle_rtp_terminate_session(JabberStream *js, const gchar *who);
-
-G_END_DECLS
-
-#endif /* PURPLE_JABBER_JINGLE_RTP_H */
-
diff --git a/libpurple/protocols/jabber/jingle/rtp.c b/libpurple/protocols/jabber/jingle/rtp.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/jingle/rtp.c
+++ /dev/null
@@ -1,933 +0,0 @@
-/**
- * @file rtp.c
- *
- * 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 <purpleconfig.h>
-
-#include <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "jabber.h"
-#include "jingle.h"
-#include "iceudp.h"
-#include "rawudp.h"
-#include "rtp.h"
-#include "session.h"
-
-#include <string.h>
-
-struct _JingleRtp
-{
-	JingleContent parent;
-};
-
-typedef struct
-{
-	gchar *media_type;
-	gchar *ssrc;
-} JingleRtpPrivate;
-
-static JingleContent *jingle_rtp_parse_internal(PurpleXmlNode *rtp);
-static PurpleXmlNode *jingle_rtp_to_xml_internal(JingleContent *rtp, PurpleXmlNode *content, JingleActionType action);
-static void jingle_rtp_handle_action_internal(JingleContent *content, PurpleXmlNode *jingle, JingleActionType action);
-
-static PurpleMedia *jingle_rtp_get_media(JingleSession *session);
-
-enum {
-	PROP_0,
-	PROP_MEDIA_TYPE,
-	PROP_SSRC,
-	N_PROPERTIES,
-};
-
-static GParamSpec *properties[N_PROPERTIES] = {NULL, };
-
-G_DEFINE_DYNAMIC_TYPE_EXTENDED(
-	JingleRtp,
-	jingle_rtp,
-	JINGLE_TYPE_CONTENT,
-	G_TYPE_FLAG_FINAL,
-	G_ADD_PRIVATE_DYNAMIC(JingleRtp)
-);
-
-/******************************************************************************
- * Helpers
- *****************************************************************************/
-static JingleTransport *
-jingle_rtp_candidates_to_transport(JingleSession *session, const gchar *type, guint generation, GList *candidates)
-{
-	JingleTransport *transport;
-
-	transport = jingle_transport_create(type);
-	if (!transport)
-		return NULL;
-
-	for (; candidates; candidates = g_list_next(candidates)) {
-		PurpleMediaCandidate *candidate = candidates->data;
-		if (purple_media_candidate_get_protocol(candidate) ==
-				PURPLE_MEDIA_NETWORK_PROTOCOL_UDP) {
-			gchar *id = jabber_get_next_id(jingle_session_get_js(session));
-			jingle_transport_add_local_candidate(transport, id, generation, candidate);
-			g_free(id);
-		}
-	}
-
-	return transport;
-}
-
-static void jingle_rtp_ready(JingleSession *session);
-
-static void
-jingle_rtp_candidates_prepared_cb(PurpleMedia *media,
-		gchar *sid, gchar *name, JingleSession *session)
-{
-	JingleContent *content = jingle_session_find_content(
-			session, sid, NULL);
-	JingleTransport *oldtransport, *transport;
-	GList *candidates;
-
-	purple_debug_info("jingle-rtp", "jingle_rtp_candidates_prepared_cb\n");
-
-	if (content == NULL) {
-		purple_debug_error("jingle-rtp",
-				"jingle_rtp_candidates_prepared_cb: "
-				"Can't find session %s\n", sid);
-		return;
-	}
-
-	oldtransport = jingle_content_get_transport(content);
-	candidates = purple_media_get_local_candidates(media, sid, name);
-	transport = jingle_rtp_candidates_to_transport(
-			session, jingle_transport_get_transport_type(oldtransport),
-			0, candidates);
-
-	purple_media_candidate_list_free(candidates);
-	g_object_unref(oldtransport);
-
-	jingle_content_set_pending_transport(content, transport);
-	jingle_content_accept_transport(content);
-
-	jingle_rtp_ready(session);
-}
-
-static void
-jingle_rtp_codecs_changed_cb(G_GNUC_UNUSED PurpleMedia *media, char *sid,
-                             JingleSession *session)
-{
-	purple_debug_info("jingle-rtp", "jingle_rtp_codecs_changed_cb: "
-			"session_id: %s jingle_session: %p\n", sid, session);
-	jingle_rtp_ready(session);
-}
-
-static void
-jingle_rtp_new_candidate_cb(G_GNUC_UNUSED PurpleMedia *media, char *sid,
-                            G_GNUC_UNUSED char *name,
-                            PurpleMediaCandidate *candidate,
-                            JingleSession *session)
-{
-	JingleContent *content = jingle_session_find_content(session, sid, NULL);
-	JingleTransport *transport;
-	gchar *id;
-
-	purple_debug_info("jingle-rtp", "jingle_rtp_new_candidate_cb\n");
-
-	if (content == NULL) {
-		purple_debug_error("jingle-rtp",
-				"jingle_rtp_new_candidate_cb: "
-				"Can't find session %s\n", sid);
-		return;
-	}
-
-	transport = jingle_content_get_transport(content);
-
-	id = jabber_get_next_id(jingle_session_get_js(session));
-	jingle_transport_add_local_candidate(transport, id, 1, candidate);
-	g_free(id);
-
-	g_object_unref(transport);
-
-	jabber_iq_send(jingle_session_to_packet(session, JINGLE_TRANSPORT_INFO));
-}
-
-static void
-jingle_rtp_initiate_ack_cb(G_GNUC_UNUSED JabberStream *js,
-                           G_GNUC_UNUSED const char *from, JabberIqType type,
-                           G_GNUC_UNUSED const char *id, PurpleXmlNode *packet,
-                           gpointer data)
-{
-	JingleSession *session = data;
-
-	if (type == JABBER_IQ_ERROR || purple_xmlnode_get_child(packet, "error")) {
-		purple_media_end(jingle_rtp_get_media(session), NULL, NULL);
-		g_object_unref(session);
-		return;
-	}
-}
-
-static void
-jingle_rtp_state_changed_cb(G_GNUC_UNUSED PurpleMedia *media,
-                            PurpleMediaState state, char *sid, char *name,
-                            G_GNUC_UNUSED JingleSession *session)
-{
-	purple_debug_info("jingle-rtp", "state-changed: state %d "
-			"id: %s name: %s\n", state, sid ? sid : "(null)",
-			name ? name : "(null)");
-}
-
-static void
-jingle_rtp_stream_info_cb(PurpleMedia *media, PurpleMediaInfoType type,
-                          char *sid, char *name, G_GNUC_UNUSED gboolean local,
-                          JingleSession *session)
-{
-	purple_debug_info("jingle-rtp", "stream-info: type %d "
-			"id: %s name: %s\n", type, sid ? sid : "(null)",
-			name ? name : "(null)");
-
-	g_return_if_fail(JINGLE_IS_SESSION(session));
-
-	if (type == PURPLE_MEDIA_INFO_HANGUP ||
-			type == PURPLE_MEDIA_INFO_REJECT) {
-		jabber_iq_send(jingle_session_terminate_packet(
-				session, type == PURPLE_MEDIA_INFO_HANGUP ?
-				"success" : "decline"));
-
-		g_signal_handlers_disconnect_by_func(media,
-		                                     jingle_rtp_state_changed_cb,
-		                                     session);
-		g_signal_handlers_disconnect_by_func(media,
-		                                     jingle_rtp_stream_info_cb,
-		                                     session);
-		g_signal_handlers_disconnect_by_func(media,
-		                                     jingle_rtp_new_candidate_cb,
-		                                     session);
-
-		g_object_unref(session);
-	/* The same signal is emitted *four* times in case of acceptance
-	 * by purple_media_stream_info() (stream acceptance, session
-	 * acceptance, participant acceptance, and conference acceptance).
-	 * We only react to the first one, where sid and name are given
-	 * non-null values.
-	 */
-	} else if (type == PURPLE_MEDIA_INFO_ACCEPT && sid && name &&
-			jingle_session_is_initiator(session) == FALSE) {
-
-		jingle_rtp_ready(session);
-	}
-}
-
-static void
-jingle_rtp_ready(JingleSession *session)
-{
-	PurpleMedia *media = jingle_rtp_get_media(session);
-
-	if (purple_media_candidates_prepared(media, NULL, NULL) &&
-			purple_media_codecs_ready(media, NULL) &&
-			(jingle_session_is_initiator(session) == TRUE ||
-			purple_media_accepted(media, NULL, NULL))) {
-		if (jingle_session_is_initiator(session)) {
-			JabberIq *iq = jingle_session_to_packet(
-					session, JINGLE_SESSION_INITIATE);
-			jabber_iq_set_callback(iq,
-					jingle_rtp_initiate_ack_cb, session);
-			jabber_iq_send(iq);
-		} else {
-			jabber_iq_send(jingle_session_to_packet(session,
-					JINGLE_SESSION_ACCEPT));
-		}
-
-		g_signal_handlers_disconnect_by_func(media,
-		                                     jingle_rtp_candidates_prepared_cb,
-		                                     session);
-		g_signal_handlers_disconnect_by_func(media,
-		                                     jingle_rtp_codecs_changed_cb,
-		                                     session);
-		g_signal_connect(media, "new-candidate",
-		                 G_CALLBACK(jingle_rtp_new_candidate_cb), session);
-	}
-}
-
-static PurpleMedia *
-jingle_rtp_create_media(JingleContent *content)
-{
-	JingleSession *session = jingle_content_get_session(content);
-	JabberStream *js = jingle_session_get_js(session);
-	gchar *remote_jid = jingle_session_get_remote_jid(session);
-
-	PurpleMedia *media = purple_media_manager_create_media(
-			purple_media_manager_get(),
-			purple_connection_get_account(js->gc),
-			"fsrtpconference", remote_jid,
-			jingle_session_is_initiator(session));
-	g_free(remote_jid);
-
-	if (!media) {
-		purple_debug_error("jingle-rtp", "Couldn't create media session\n");
-		return NULL;
-	}
-
-	purple_media_set_protocol_data(media, session);
-
-	/* connect callbacks */
-	g_signal_connect(G_OBJECT(media), "candidates-prepared",
-				 G_CALLBACK(jingle_rtp_candidates_prepared_cb), session);
-	g_signal_connect(G_OBJECT(media), "codecs-changed",
-				 G_CALLBACK(jingle_rtp_codecs_changed_cb), session);
-	g_signal_connect(G_OBJECT(media), "state-changed",
-				 G_CALLBACK(jingle_rtp_state_changed_cb), session);
-	g_signal_connect(G_OBJECT(media), "stream-info",
-			G_CALLBACK(jingle_rtp_stream_info_cb), session);
-
-	g_object_unref(session);
-	return media;
-}
-
-static gboolean
-jingle_rtp_init_media(JingleContent *content)
-{
-	JingleSession *session = jingle_content_get_session(content);
-	PurpleMedia *media = jingle_rtp_get_media(session);
-	gchar *creator;
-	gchar *media_type;
-	gchar *remote_jid;
-	gchar *senders;
-	gchar *name;
-	const gchar *transmitter;
-	gboolean is_audio;
-	gboolean is_creator;
-	PurpleMediaSessionType type;
-	JingleTransport *transport;
-	GHashTable *params = NULL;
-
-	/* maybe this create ought to just be in initiate and handle initiate */
-	if (media == NULL) {
-		media = jingle_rtp_create_media(content);
-
-		if (media == NULL)
-			return FALSE;
-	}
-
-	media_type = jingle_rtp_get_media_type(content);
-	if (media_type == NULL) {
-		g_object_unref(session);
-		return FALSE;
-	}
-
-	name = jingle_content_get_name(content);
-	remote_jid = jingle_session_get_remote_jid(session);
-	senders = jingle_content_get_senders(content);
-	transport = jingle_content_get_transport(content);
-
-	if (JINGLE_IS_RAWUDP(transport))
-		transmitter = "rawudp";
-	else if (JINGLE_IS_ICEUDP(transport))
-		transmitter = "nice";
-	else
-		transmitter = "notransmitter";
-	g_object_unref(transport);
-
-	is_audio = purple_strequal(media_type, "audio");
-
-	if (purple_strequal(senders, "both"))
-		type = is_audio ? PURPLE_MEDIA_AUDIO
-				: PURPLE_MEDIA_VIDEO;
-	else if (purple_strequal(senders, "initiator") ==
-			jingle_session_is_initiator(session))
-		type = is_audio ? PURPLE_MEDIA_SEND_AUDIO
-				: PURPLE_MEDIA_SEND_VIDEO;
-	else
-		type = is_audio ? PURPLE_MEDIA_RECV_AUDIO
-				: PURPLE_MEDIA_RECV_VIDEO;
-
-	params =
-		jingle_get_params(jingle_session_get_js(session), NULL, 0, 0, 0,
-			NULL, NULL);
-
-	creator = jingle_content_get_creator(content);
-	if (creator == NULL) {
-		g_free(name);
-		g_free(media_type);
-		g_free(remote_jid);
-		g_free(senders);
-		g_hash_table_destroy(params);
-		g_object_unref(session);
-		return FALSE;
-	}
-
-	if (purple_strequal(creator, "initiator"))
-		is_creator = jingle_session_is_initiator(session);
-	else
-		is_creator = !jingle_session_is_initiator(session);
-	g_free(creator);
-
-	if(!purple_media_add_stream(media, name, remote_jid,
-			type, is_creator, transmitter, params)) {
-		purple_media_end(media, NULL, NULL);
-		/* TODO: How much clean-up is necessary here? (does calling
-		         purple_media_end lead to cleaning up Jingle structs?) */
-		return FALSE;
-	}
-
-	g_free(name);
-	g_free(media_type);
-	g_free(remote_jid);
-	g_free(senders);
-	g_hash_table_destroy(params);
-	g_object_unref(session);
-
-	return TRUE;
-}
-
-static GList *
-jingle_rtp_parse_codecs(PurpleXmlNode *description)
-{
-	GList *codecs = NULL;
-	PurpleXmlNode *codec_element = NULL;
-	const char *encoding_name,*id, *clock_rate;
-	PurpleMediaCodec *codec;
-	const gchar *media = purple_xmlnode_get_attrib(description, "media");
-	PurpleMediaSessionType type;
-
-	if (media == NULL) {
-		purple_debug_warning("jingle-rtp", "missing media type\n");
-		return NULL;
-	}
-
-	if (purple_strequal(media, "video")) {
-		type = PURPLE_MEDIA_VIDEO;
-	} else if (purple_strequal(media, "audio")) {
-		type = PURPLE_MEDIA_AUDIO;
-	} else {
-		purple_debug_warning("jingle-rtp", "unknown media type: %s\n",
-				media);
-		return NULL;
-	}
-
-	for (codec_element = purple_xmlnode_get_child(description, "payload-type") ;
-		 codec_element ;
-		 codec_element = purple_xmlnode_get_next_twin(codec_element)) {
-		PurpleXmlNode *param;
-		gchar *codec_str;
-		encoding_name = purple_xmlnode_get_attrib(codec_element, "name");
-
-		id = purple_xmlnode_get_attrib(codec_element, "id");
-		clock_rate = purple_xmlnode_get_attrib(codec_element, "clockrate");
-
-		codec = purple_media_codec_new(atoi(id), encoding_name,
-				     type,
-				     clock_rate ? atoi(clock_rate) : 0);
-
-		for (param = purple_xmlnode_get_child(codec_element, "parameter");
-				param; param = purple_xmlnode_get_next_twin(param)) {
-			purple_media_codec_add_optional_parameter(codec,
-					purple_xmlnode_get_attrib(param, "name"),
-					purple_xmlnode_get_attrib(param, "value"));
-		}
-
-		codec_str = purple_media_codec_to_string(codec);
-		purple_debug_info("jingle-rtp", "received codec: %s\n", codec_str);
-		g_free(codec_str);
-
-		codecs = g_list_append(codecs, codec);
-	}
-	return codecs;
-}
-
-static void
-add_parameter_to_payload(PurpleKeyValuePair *mparam, PurpleXmlNode *payload)
-{
-	PurpleXmlNode *param = purple_xmlnode_new_child(payload, "parameter");
-	purple_xmlnode_set_attrib(param, "name", mparam->key);
-	purple_xmlnode_set_attrib(param, "value", mparam->value);
-}
-
-static void
-jingle_rtp_add_payload(gpointer codec, gpointer description)
-{
-	gchar *id, *name, *clockrate, *channels;
-	gchar *codec_str;
-	PurpleXmlNode *payload = purple_xmlnode_new_child(description, "payload-type");
-
-	id = g_strdup_printf("%d", purple_media_codec_get_id(codec));
-	name = purple_media_codec_get_encoding_name(codec);
-	clockrate = g_strdup_printf("%d", purple_media_codec_get_clock_rate(codec));
-	channels = g_strdup_printf("%d", purple_media_codec_get_channels(codec));
-
-	purple_xmlnode_set_attrib(payload, "name", name);
-	purple_xmlnode_set_attrib(payload, "id", id);
-	purple_xmlnode_set_attrib(payload, "clockrate", clockrate);
-	purple_xmlnode_set_attrib(payload, "channels", channels);
-
-	g_free(channels);
-	g_free(clockrate);
-	g_free(name);
-	g_free(id);
-
-	g_list_foreach(purple_media_codec_get_optional_parameters(codec),
-	               (GFunc)add_parameter_to_payload, payload);
-
-	codec_str = purple_media_codec_to_string(codec);
-	purple_debug_info("jingle", "adding codec: %s", codec_str);
-	g_free(codec_str);
-}
-
-/******************************************************************************
- * JingleContent Implementation
- *****************************************************************************/
-static PurpleXmlNode *
-jingle_rtp_to_xml_internal(JingleContent *rtp, PurpleXmlNode *content, JingleActionType action)
-{
-	PurpleXmlNode *node = JINGLE_CONTENT_CLASS(jingle_rtp_parent_class)->to_xml(rtp, content, action);
-	PurpleXmlNode *description = purple_xmlnode_get_child(node, "description");
-	if (description != NULL) {
-		JingleSession *session = jingle_content_get_session(rtp);
-		PurpleMedia *media = jingle_rtp_get_media(session);
-		gchar *media_type = jingle_rtp_get_media_type(rtp);
-		gchar *ssrc = jingle_rtp_get_ssrc(rtp);
-		gchar *name = jingle_content_get_name(rtp);
-		GList *codecs = purple_media_get_codecs(media, name);
-
-		purple_xmlnode_set_attrib(description, "media", media_type);
-
-		if (ssrc != NULL)
-			purple_xmlnode_set_attrib(description, "ssrc", ssrc);
-
-		g_free(media_type);
-		g_free(name);
-		g_object_unref(session);
-
-		g_list_foreach(codecs, jingle_rtp_add_payload, description);
-		purple_media_codec_list_free(codecs);
-	}
-	return node;
-}
-
-static JingleContent *
-jingle_rtp_parse_internal(PurpleXmlNode *rtp)
-{
-	JingleContent *content = JINGLE_CONTENT_CLASS(jingle_rtp_parent_class)->parse(rtp);
-	PurpleXmlNode *description = purple_xmlnode_get_child(rtp, "description");
-	const gchar *media_type = purple_xmlnode_get_attrib(description, "media");
-	const gchar *ssrc = purple_xmlnode_get_attrib(description, "ssrc");
-	purple_debug_info("jingle-rtp", "rtp parse\n");
-	g_object_set(content, "media-type", media_type, NULL);
-	if (ssrc != NULL)
-		g_object_set(content, "ssrc", ssrc, NULL);
-	return content;
-}
-
-static void
-jingle_rtp_handle_action_internal(JingleContent *content, PurpleXmlNode *xmlcontent, JingleActionType action)
-{
-	switch (action) {
-		case JINGLE_SESSION_ACCEPT:
-		case JINGLE_SESSION_INITIATE: {
-			JingleSession *session;
-			JingleTransport *transport;
-			PurpleXmlNode *description;
-			GList *candidates;
-			GList *codecs;
-			gchar *name;
-			gchar *remote_jid;
-			PurpleMedia *media;
-
-			session = jingle_content_get_session(content);
-
-			if (action == JINGLE_SESSION_INITIATE &&
-					!jingle_rtp_init_media(content)) {
-				/* XXX: send error */
-				jabber_iq_send(jingle_session_terminate_packet(
-						session, "general-error"));
-				g_object_unref(session);
-				break;
-			}
-
-			transport = jingle_transport_parse(
-					purple_xmlnode_get_child(xmlcontent, "transport"));
-			description = purple_xmlnode_get_child(xmlcontent, "description");
-			candidates = jingle_transport_get_remote_candidates(transport);
-			codecs = jingle_rtp_parse_codecs(description);
-			name = jingle_content_get_name(content);
-			remote_jid = jingle_session_get_remote_jid(session);
-
-			media = jingle_rtp_get_media(session);
-			purple_media_set_remote_codecs(media,
-					name, remote_jid, codecs);
-			purple_media_add_remote_candidates(media,
-					name, remote_jid, candidates);
-
-			if (action == JINGLE_SESSION_ACCEPT)
-				purple_media_stream_info(media,
-						PURPLE_MEDIA_INFO_ACCEPT,
-						name, remote_jid, FALSE);
-
-			g_free(remote_jid);
-			g_free(name);
-			g_object_unref(session);
-			g_object_unref(transport);
-			purple_media_candidate_list_free(candidates);
-			purple_media_codec_list_free(codecs);
-			break;
-		}
-		case JINGLE_SESSION_TERMINATE: {
-			JingleSession *session = jingle_content_get_session(content);
-			PurpleMedia *media = jingle_rtp_get_media(session);
-
-			if (media != NULL) {
-				purple_media_end(media, NULL, NULL);
-			}
-
-			g_object_unref(session);
-			break;
-		}
-		case JINGLE_TRANSPORT_INFO: {
-			JingleSession *session = jingle_content_get_session(content);
-			JingleTransport *transport = jingle_transport_parse(
-					purple_xmlnode_get_child(xmlcontent, "transport"));
-			GList *candidates = jingle_transport_get_remote_candidates(transport);
-			gchar *name = jingle_content_get_name(content);
-			gchar *remote_jid =
-					jingle_session_get_remote_jid(session);
-
-			purple_media_add_remote_candidates(
-					jingle_rtp_get_media(session),
-					name, remote_jid, candidates);
-
-			g_free(remote_jid);
-			g_free(name);
-			g_object_unref(session);
-			g_object_unref(transport);
-			purple_media_candidate_list_free(candidates);
-			break;
-		}
-		case JINGLE_DESCRIPTION_INFO: {
-			JingleSession *session =
-					jingle_content_get_session(content);
-			PurpleXmlNode *description = purple_xmlnode_get_child(
-					xmlcontent, "description");
-			GList *codecs, *iter, *iter2, *remote_codecs =
-					jingle_rtp_parse_codecs(description);
-			gchar *name = jingle_content_get_name(content);
-			gchar *remote_jid =
-					jingle_session_get_remote_jid(session);
-			PurpleMedia *media;
-
-			media = jingle_rtp_get_media(session);
-
-			/*
-			 * This may have problems if description-info is
-			 * received without the optional parameters for a
-			 * codec with configuration info (such as THEORA
-			 * or H264). The local configuration info may be
-			 * set for the remote codec.
-			 *
-			 * As of 2.6.3 there's no API to support getting
-			 * the remote codecs specifically, just the
-			 * intersection. Another option may be to cache
-			 * the remote codecs received in initiate/accept.
-			 */
-			codecs = purple_media_get_codecs(media, name);
-
-			for (iter = codecs; iter; iter = g_list_next(iter)) {
-				guint id;
-
-				id = purple_media_codec_get_id(iter->data);
-				iter2 = remote_codecs;
-
-				for (; iter2; iter2 = g_list_next(iter2)) {
-					if (purple_media_codec_get_id(
-							iter2->data) != id)
-						continue;
-
-					g_object_unref(iter->data);
-					iter->data = iter2->data;
-					remote_codecs = g_list_delete_link(
-							remote_codecs, iter2);
-					break;
-				}
-			}
-
-			codecs = g_list_concat(codecs, remote_codecs);
-
-			purple_media_set_remote_codecs(media,
-					name, remote_jid, codecs);
-
-			purple_media_codec_list_free (codecs);
-			g_free(remote_jid);
-			g_free(name);
-			g_object_unref(session);
-			break;
-		}
-		default:
-			break;
-	}
-}
-
-
-/******************************************************************************
- * GObject Stuff
- *****************************************************************************/
-static void
-jingle_rtp_init(G_GNUC_UNUSED JingleRtp *rtp)
-{
-}
-
-static void
-jingle_rtp_finalize (GObject *rtp)
-{
-	JingleRtpPrivate *priv = jingle_rtp_get_instance_private(JINGLE_RTP(rtp));
-	purple_debug_info("jingle-rtp","jingle_rtp_finalize\n");
-
-	g_free(priv->media_type);
-	g_free(priv->ssrc);
-
-	G_OBJECT_CLASS(jingle_rtp_parent_class)->finalize(rtp);
-}
-
-static void
-jingle_rtp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
-	JingleRtp *rtp = JINGLE_RTP(object);
-	JingleRtpPrivate *priv = jingle_rtp_get_instance_private(rtp);
-
-	switch (prop_id) {
-		case PROP_MEDIA_TYPE:
-			g_free(priv->media_type);
-			priv->media_type = g_value_dup_string(value);
-			break;
-		case PROP_SSRC:
-			g_free(priv->ssrc);
-			priv->ssrc = g_value_dup_string(value);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
-static void
-jingle_rtp_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
-	JingleRtp *rtp = JINGLE_RTP(object);
-	JingleRtpPrivate *priv = jingle_rtp_get_instance_private(rtp);
-
-	switch (prop_id) {
-		case PROP_MEDIA_TYPE:
-			g_value_set_string(value, priv->media_type);
-			break;
-		case PROP_SSRC:
-			g_value_set_string(value, priv->ssrc);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
-
-static void
-jingle_rtp_class_finalize(G_GNUC_UNUSED JingleRtpClass *klass) {
-}
-
-static void
-jingle_rtp_class_init (JingleRtpClass *klass)
-{
-	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
-	JingleContentClass *content_class = JINGLE_CONTENT_CLASS(klass);
-
-	obj_class->finalize = jingle_rtp_finalize;
-	obj_class->set_property = jingle_rtp_set_property;
-	obj_class->get_property = jingle_rtp_get_property;
-
-	content_class->to_xml = jingle_rtp_to_xml_internal;
-	content_class->parse = jingle_rtp_parse_internal;
-	content_class->description_type = JINGLE_APP_RTP;
-	content_class->handle_action = jingle_rtp_handle_action_internal;
-
-	properties[PROP_MEDIA_TYPE] = g_param_spec_string("media-type",
-			"Media Type",
-			"The media type (\"audio\" or \"video\") for this rtp session.",
-			NULL,
-			G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_SSRC] = g_param_spec_string("ssrc",
-			"ssrc",
-			"The ssrc for this rtp session.",
-			NULL,
-			G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
-}
-
-/******************************************************************************
- * Public API
- *****************************************************************************/
-void
-jingle_rtp_register(PurplePlugin *plugin) {
-	jingle_rtp_register_type(G_TYPE_MODULE(plugin));
-}
-
-gchar *
-jingle_rtp_get_media_type(JingleContent *content)
-{
-	gchar *media_type;
-	g_object_get(content, "media-type", &media_type, NULL);
-	return media_type;
-}
-
-gchar *
-jingle_rtp_get_ssrc(JingleContent *content)
-{
-	gchar *ssrc;
-	g_object_get(content, "ssrc", &ssrc, NULL);
-	return ssrc;
-}
-
-static PurpleMedia *
-jingle_rtp_get_media(JingleSession *session)
-{
-	JabberStream *js = jingle_session_get_js(session);
-	PurpleMedia *media = NULL;
-	GList *iter = purple_media_manager_get_media_by_account(
-			purple_media_manager_get(),
-			purple_connection_get_account(js->gc));
-
-	for (; iter; iter = g_list_delete_link(iter, iter)) {
-		JingleSession *media_session =
-				purple_media_get_protocol_data(iter->data);
-		if (media_session == session) {
-			media = iter->data;
-			break;
-		}
-	}
-	g_clear_list(&iter, NULL);
-
-	return media;
-}
-
-gboolean
-jingle_rtp_initiate_media(JabberStream *js, const gchar *who,
-		      PurpleMediaSessionType type)
-{
-	/* create content negotiation */
-	JingleSession *session;
-	JingleContent *content;
-	JingleTransport *transport;
-	JabberBuddy *jb;
-	JabberBuddyResource *jbr;
-	gboolean ret = FALSE;
-	const gchar *transport_type;
-
-	gchar *resource = NULL, *me = NULL, *sid = NULL;
-
-	/* construct JID to send to */
-	jb = jabber_buddy_find(js, who, FALSE);
-	if (!jb) {
-		purple_debug_error("jingle-rtp", "Could not find Jabber buddy\n");
-		goto out;
-	}
-
-	resource = jabber_get_resource(who);
-	jbr = jabber_buddy_find_resource(jb, resource);
-
-	if (!jbr) {
-		purple_debug_error("jingle-rtp", "Could not find buddy's resource - %s\n", resource);
-		goto out;
-	}
-
-	if (jabber_resource_has_capability(jbr, JINGLE_TRANSPORT_ICEUDP)) {
-		transport_type = JINGLE_TRANSPORT_ICEUDP;
-	} else if (jabber_resource_has_capability(jbr, JINGLE_TRANSPORT_RAWUDP)) {
-		transport_type = JINGLE_TRANSPORT_RAWUDP;
-	} else {
-		purple_debug_error("jingle-rtp", "Resource doesn't support "
-				"the same transport types\n");
-		goto out;
-	}
-
-	/* set ourselves as initiator */
-	me = g_strdup_printf("%s@%s/%s", js->user->node, js->user->domain, js->user->resource);
-
-	sid = jabber_get_next_id(js);
-	session = jingle_session_create(js, sid, me, who, TRUE);
-
-
-	if (type & PURPLE_MEDIA_AUDIO) {
-		JingleRtpPrivate *priv = NULL;
-
-		transport = jingle_transport_create(transport_type);
-		content = jingle_content_create(JINGLE_APP_RTP, "initiator",
-				"session", "audio-session", "both", transport);
-
-		priv = jingle_rtp_get_instance_private(JINGLE_RTP(content));
-
-		jingle_session_add_content(session, content);
-		priv->media_type = g_strdup("audio");
-		jingle_rtp_init_media(content);
-		g_object_notify_by_pspec(G_OBJECT(content), properties[PROP_MEDIA_TYPE]);
-	}
-	if (type & PURPLE_MEDIA_VIDEO) {
-		JingleRtpPrivate *priv = NULL;
-
-		transport = jingle_transport_create(transport_type);
-		content = jingle_content_create(JINGLE_APP_RTP, "initiator",
-				"session", "video-session", "both", transport);
-
-		priv = jingle_rtp_get_instance_private(JINGLE_RTP(content));
-
-		jingle_session_add_content(session, content);
-		priv->media_type = g_strdup("video");
-		jingle_rtp_init_media(content);
-		g_object_notify_by_pspec(G_OBJECT(content), properties[PROP_MEDIA_TYPE]);
-	}
-
-	if (jingle_rtp_get_media(session) == NULL) {
-		goto out;
-	}
-
-	ret = TRUE;
-
-out:
-	g_free(me);
-	g_free(resource);
-	g_free(sid);
-	return ret;
-}
-
-void
-jingle_rtp_terminate_session(JabberStream *js, const gchar *who)
-{
-	JingleSession *session;
-/* XXX: This may cause file transfers and xml sessions to stop as well */
-	session = jingle_session_find_by_jid(js, who);
-
-	if (session) {
-		PurpleMedia *media = jingle_rtp_get_media(session);
-		if (media) {
-			purple_debug_info("jingle-rtp", "hanging up media\n");
-			purple_media_stream_info(media,
-					PURPLE_MEDIA_INFO_HANGUP,
-					NULL, NULL, TRUE);
-		}
-	}
-}
diff --git a/libpurple/protocols/jabber/jingle/session.h b/libpurple/protocols/jabber/jingle/session.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/jingle/session.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
- * @file session.h
- *
- * 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_JABBER_JINGLE_SESSION_H
-#define PURPLE_JABBER_JINGLE_SESSION_H
-
-#include "iq.h"
-#include "jabber.h"
-
-#include <glib.h>
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-#define JINGLE_TYPE_SESSION  jingle_session_get_type()
-
-struct _JingleContent;
-
-/**
- * Gets the session class's GType
- *
- * @return The session class's GType.
- */
-G_MODULE_EXPORT
-G_DECLARE_FINAL_TYPE(JingleSession, jingle_session, JINGLE, SESSION, GObject)
-
-/**
- * Registers the JingleSession type in the type system.
- */
-void jingle_session_register(PurplePlugin *plugin);
-
-JingleSession *jingle_session_create(JabberStream *js, const gchar *sid,
-				     const gchar *local_jid, const gchar *remote_jid,
-				     gboolean is_initiator);
-JabberStream *jingle_session_get_js(JingleSession *session);
-gchar *jingle_session_get_sid(JingleSession *session);
-gchar *jingle_session_get_local_jid(JingleSession *session);
-gchar *jingle_session_get_remote_jid(JingleSession *session);
-gboolean jingle_session_is_initiator(JingleSession *session);
-gboolean jingle_session_get_state(JingleSession *session);
-
-GList *jingle_session_get_contents(JingleSession *session);
-GList *jingle_session_get_pending_contents(JingleSession *session);
-
-JingleSession *jingle_session_find_by_sid(JabberStream *js, const gchar *sid);
-JingleSession *jingle_session_find_by_jid(JabberStream *js, const gchar *jid);
-
-JabberIq *jingle_session_create_ack(JingleSession *session, const PurpleXmlNode *jingle);
-PurpleXmlNode *jingle_session_to_xml(JingleSession *session, PurpleXmlNode *parent, JingleActionType action);
-JabberIq *jingle_session_to_packet(JingleSession *session, JingleActionType action);
-
-void jingle_session_handle_action(JingleSession *session, PurpleXmlNode *jingle, JingleActionType action);
-
-struct _JingleContent *jingle_session_find_content(JingleSession *session,
-					const gchar *name, const gchar *creator);
-struct _JingleContent *jingle_session_find_pending_content(JingleSession *session,
-					const gchar *name, const gchar *creator);
-
-void jingle_session_add_content(JingleSession *session, struct _JingleContent* content);
-void jingle_session_remove_content(JingleSession *session, const gchar *name, const gchar *creator);
-void jingle_session_add_pending_content(JingleSession *session, struct _JingleContent* content);
-void jingle_session_remove_pending_content(JingleSession *session, const gchar *name, const gchar *creator);
-void jingle_session_accept_content(JingleSession *session, const gchar *name, const gchar *creator);
-void jingle_session_accept_session(JingleSession *session);
-JabberIq *jingle_session_terminate_packet(JingleSession *session, const gchar *reason);
-JabberIq *jingle_session_redirect_packet(JingleSession *session, const gchar *sid);
-
-G_END_DECLS
-
-#endif /* PURPLE_JABBER_JINGLE_SESSION_H */
-
diff --git a/libpurple/protocols/jabber/jingle/session.c b/libpurple/protocols/jabber/jingle/session.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/jingle/session.c
+++ /dev/null
@@ -1,685 +0,0 @@
-/**
- * @file session.c
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "content.h"
-#include "session.h"
-#include "jingle.h"
-
-#include <string.h>
-
-struct _JingleSession
-{
-	GObject parent;
-};
-
-typedef struct
-{
-	gchar *sid;
-	JabberStream *js;
-	gchar *remote_jid;
-	gchar *local_jid;
-	gboolean is_initiator;
-	gboolean state;
-	GList *contents;
-	GList *pending_contents;
-} JingleSessionPrivate;
-
-enum {
-	PROP_0,
-	PROP_SID,
-	PROP_JS,
-	PROP_REMOTE_JID,
-	PROP_LOCAL_JID,
-	PROP_IS_INITIATOR,
-	PROP_STATE,
-	PROP_CONTENTS,
-	PROP_PENDING_CONTENTS,
-	N_PROPERTIES,
-};
-
-static GParamSpec *properties[N_PROPERTIES] = {NULL, };
-
-G_DEFINE_DYNAMIC_TYPE_EXTENDED(
-	JingleSession,
-	jingle_session,
-	G_TYPE_OBJECT,
-	G_TYPE_FLAG_FINAL,
-	G_ADD_PRIVATE_DYNAMIC(JingleSession)
-);
-
-/******************************************************************************
- * Helpers
- *****************************************************************************/
-static gboolean
-find_by_jid_ghr(G_GNUC_UNUSED gpointer key, gpointer value, gpointer user_data)
-{
-	JingleSession *session = (JingleSession *)value;
-	const gchar *jid = user_data;
-	gboolean use_bare = strchr(jid, '/') == NULL;
-	gchar *remote_jid = jingle_session_get_remote_jid(session);
-	gchar *cmp_jid = use_bare ? jabber_get_bare_jid(remote_jid)
-				  : g_strdup(remote_jid);
-	g_free(remote_jid);
-	if (purple_strequal(jid, cmp_jid)) {
-		g_free(cmp_jid);
-		return TRUE;
-	}
-	g_free(cmp_jid);
-
-	return FALSE;
-}
-
-static PurpleXmlNode *
-jingle_add_jingle_packet(JingleSession *session,
-			 JabberIq *iq, JingleActionType action)
-{
-	PurpleXmlNode *jingle = iq ?
-			purple_xmlnode_new_child(iq->node, "jingle") :
-			purple_xmlnode_new("jingle");
-	gchar *local_jid = jingle_session_get_local_jid(session);
-	gchar *remote_jid = jingle_session_get_remote_jid(session);
-	gchar *sid = jingle_session_get_sid(session);
-
-	purple_xmlnode_set_namespace(jingle, JINGLE);
-	purple_xmlnode_set_attrib(jingle, "action", jingle_get_action_name(action));
-
-	if (jingle_session_is_initiator(session)) {
-		purple_xmlnode_set_attrib(jingle, "initiator", local_jid);
-		purple_xmlnode_set_attrib(jingle, "responder", remote_jid);
-	} else {
-		purple_xmlnode_set_attrib(jingle, "initiator", remote_jid);
-		purple_xmlnode_set_attrib(jingle, "responder", local_jid);
-	}
-
-	purple_xmlnode_set_attrib(jingle, "sid", sid);
-
-	g_free(local_jid);
-	g_free(remote_jid);
-	g_free(sid);
-
-	return jingle;
-}
-
-static JabberIq *
-jingle_create_iq(JingleSession *session)
-{
-	JabberStream *js = jingle_session_get_js(session);
-	JabberIq *result = jabber_iq_new(js, JABBER_IQ_SET);
-	gchar *from = jingle_session_get_local_jid(session);
-	gchar *to = jingle_session_get_remote_jid(session);
-
-	purple_xmlnode_set_attrib(result->node, "from", from);
-	purple_xmlnode_set_attrib(result->node, "to", to);
-
-	g_free(from);
-	g_free(to);
-	return result;
-}
-
-/******************************************************************************
- * GObject Implementation
- *****************************************************************************/
-static void
-jingle_session_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
-	JingleSession *session = JINGLE_SESSION(object);
-	JingleSessionPrivate *priv = jingle_session_get_instance_private(session);
-
-	switch (prop_id) {
-		case PROP_SID:
-			g_free(priv->sid);
-			priv->sid = g_value_dup_string(value);
-			break;
-		case PROP_JS:
-			priv->js = g_value_get_pointer(value);
-			break;
-		case PROP_REMOTE_JID:
-			g_free(priv->remote_jid);
-			priv->remote_jid = g_value_dup_string(value);
-			break;
-		case PROP_LOCAL_JID:
-			g_free(priv->local_jid);
-			priv->local_jid = g_value_dup_string(value);
-			break;
-		case PROP_IS_INITIATOR:
-			priv->is_initiator = g_value_get_boolean(value);
-			break;
-		case PROP_STATE:
-			priv->state = g_value_get_boolean(value);
-			break;
-		case PROP_CONTENTS:
-			priv->contents = g_value_get_pointer(value);
-			break;
-		case PROP_PENDING_CONTENTS:
-			priv->pending_contents = g_value_get_pointer(value);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
-static void
-jingle_session_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
-	JingleSession *session = JINGLE_SESSION(object);
-	JingleSessionPrivate *priv = jingle_session_get_instance_private(session);
-
-	switch (prop_id) {
-		case PROP_SID:
-			g_value_set_string(value, priv->sid);
-			break;
-		case PROP_JS:
-			g_value_set_pointer(value, priv->js);
-			break;
-		case PROP_REMOTE_JID:
-			g_value_set_string(value, priv->remote_jid);
-			break;
-		case PROP_LOCAL_JID:
-			g_value_set_string(value, priv->local_jid);
-			break;
-		case PROP_IS_INITIATOR:
-			g_value_set_boolean(value, priv->is_initiator);
-			break;
-		case PROP_STATE:
-			g_value_set_boolean(value, priv->state);
-			break;
-		case PROP_CONTENTS:
-			g_value_set_pointer(value, priv->contents);
-			break;
-		case PROP_PENDING_CONTENTS:
-			g_value_set_pointer(value, priv->pending_contents);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
-static void
-jingle_session_init(G_GNUC_UNUSED JingleSession *session)
-{
-}
-
-static void
-jingle_session_finalize (GObject *session)
-{
-	JingleSessionPrivate *priv = jingle_session_get_instance_private(JINGLE_SESSION(session));
-	purple_debug_info("jingle","jingle_session_finalize\n");
-
-	g_hash_table_remove(priv->js->sessions, priv->sid);
-
-	g_free(priv->sid);
-	g_free(priv->remote_jid);
-	g_free(priv->local_jid);
-
-	g_list_free_full(priv->contents, g_object_unref);
-	g_list_free_full(priv->pending_contents, g_object_unref);
-
-	G_OBJECT_CLASS(jingle_session_parent_class)->finalize(session);
-}
-
-static void
-jingle_session_class_finalize(G_GNUC_UNUSED JingleSessionClass *klass)
-{
-}
-
-static void
-jingle_session_class_init (JingleSessionClass *klass)
-{
-	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
-
-	obj_class->finalize = jingle_session_finalize;
-	obj_class->set_property = jingle_session_set_property;
-	obj_class->get_property = jingle_session_get_property;
-
-	properties[PROP_SID] = g_param_spec_string("sid",
-			"Session ID",
-			"The unique session ID of the Jingle Session.",
-			NULL,
-			G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_JS] = g_param_spec_pointer("js",
-			"JabberStream",
-			"The Jabber stream associated with this session.",
-			G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_REMOTE_JID] = g_param_spec_string("remote-jid",
-			"Remote JID",
-			"The JID of the remote participant.",
-			NULL,
-			G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_LOCAL_JID] = g_param_spec_string("local-jid",
-			"Local JID",
-			"The JID of the local participant.",
-			NULL,
-			G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_IS_INITIATOR] = g_param_spec_boolean("is-initiator",
-			"Is Initiator",
-			"Whether or not the local JID is the initiator of the session.",
-			FALSE,
-			G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_STATE] = g_param_spec_boolean("state",
-			"State",
-			"The state of the session (PENDING=FALSE, ACTIVE=TRUE).",
-			FALSE,
-			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_CONTENTS] = g_param_spec_pointer("contents",
-			"Contents",
-			"The active contents contained within this session",
-			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_PENDING_CONTENTS] = g_param_spec_pointer("pending-contents",
-			"Pending contents",
-			"The pending contents contained within this session",
-			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-	g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
-}
-
-/******************************************************************************
- * Public API
- *****************************************************************************/
-void
-jingle_session_register(PurplePlugin *plugin) {
-	jingle_session_register_type(G_TYPE_MODULE(plugin));
-}
-
-JingleSession *
-jingle_session_create(JabberStream *js, const gchar *sid,
-			const gchar *local_jid, const gchar *remote_jid,
-			gboolean is_initiator)
-{
-	JingleSession *session = g_object_new(jingle_session_get_type(),
-			"js", js,
-			"sid", sid,
-			"local-jid", local_jid,
-			"remote-jid", remote_jid,
-			"is_initiator", is_initiator,
-			NULL);
-
-	/* insert it into the hash table */
-	if (!js->sessions) {
-		purple_debug_info("jingle",
-				"Creating hash table for sessions\n");
-		js->sessions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
-	}
-	purple_debug_info("jingle",
-			"inserting session with key: %s into table\n", sid);
-	g_hash_table_insert(js->sessions, g_strdup(sid), session);
-
-	return session;
-}
-
-JabberStream *
-jingle_session_get_js(JingleSession *session)
-{
-	JabberStream *js;
-	g_object_get(session, "js", &js, NULL);
-	return js;
-}
-
-gchar *
-jingle_session_get_sid(JingleSession *session)
-{
-	gchar *sid;
-	g_object_get(session, "sid", &sid, NULL);
-	return sid;
-}
-
-gchar *
-jingle_session_get_local_jid(JingleSession *session)
-{
-	gchar *local_jid;
-	g_object_get(session, "local-jid", &local_jid, NULL);
-	return local_jid;
-}
-
-gchar *
-jingle_session_get_remote_jid(JingleSession *session)
-{
-	gchar *remote_jid;
-	g_object_get(session, "remote-jid", &remote_jid, NULL);
-	return remote_jid;
-}
-
-gboolean
-jingle_session_is_initiator(JingleSession *session)
-{
-	gboolean is_initiator;
-	g_object_get(session, "is-initiator", &is_initiator, NULL);
-	return is_initiator;
-}
-
-gboolean
-jingle_session_get_state(JingleSession *session)
-{
-	gboolean state;
-	g_object_get(session, "state", &state, NULL);
-	return state;
-}
-
-GList *
-jingle_session_get_contents(JingleSession *session)
-{
-	GList *contents;
-	g_object_get(session, "contents", &contents, NULL);
-	return contents;
-}
-
-GList *
-jingle_session_get_pending_contents(JingleSession *session)
-{
-	GList *pending_contents;
-	g_object_get(session, "pending-contents", &pending_contents, NULL);
-	return pending_contents;
-}
-
-JingleSession *
-jingle_session_find_by_sid(JabberStream *js, const gchar *sid)
-{
-	JingleSession *session = NULL;
-
-	if (js->sessions)
-		session = g_hash_table_lookup(js->sessions, sid);
-
-	purple_debug_info("jingle", "find_by_id %s\n", sid);
-	purple_debug_info("jingle", "lookup: %p\n", session);
-
-	return session;
-}
-
-JingleSession *
-jingle_session_find_by_jid(JabberStream *js, const gchar *jid)
-{
-	return js->sessions != NULL ?
-			g_hash_table_find(js->sessions,
-			find_by_jid_ghr, (gpointer)jid) : NULL;
-}
-
-JabberIq *
-jingle_session_create_ack(JingleSession *session, const PurpleXmlNode *jingle)
-{
-	JabberIq *result = jabber_iq_new(
-			jingle_session_get_js(session),
-			JABBER_IQ_RESULT);
-	PurpleXmlNode *packet = purple_xmlnode_get_parent(jingle);
-	jabber_iq_set_id(result, purple_xmlnode_get_attrib(packet, "id"));
-	purple_xmlnode_set_attrib(result->node, "from", purple_xmlnode_get_attrib(packet, "to"));
-	purple_xmlnode_set_attrib(result->node, "to", purple_xmlnode_get_attrib(packet, "from"));
-	return result;
-}
-
-PurpleXmlNode *
-jingle_session_to_xml(JingleSession *session, PurpleXmlNode *jingle, JingleActionType action)
-{
-	if (action != JINGLE_SESSION_INFO && action != JINGLE_SESSION_TERMINATE) {
-		GList *iter;
-		if (action == JINGLE_CONTENT_ACCEPT
-				|| action == JINGLE_CONTENT_ADD
-				|| action == JINGLE_CONTENT_REMOVE)
-			iter = jingle_session_get_pending_contents(session);
-		else
-			iter = jingle_session_get_contents(session);
-
-		for (; iter; iter = g_list_next(iter)) {
-			jingle_content_to_xml(iter->data, jingle, action);
-		}
-	}
-	return jingle;
-}
-
-JabberIq *
-jingle_session_to_packet(JingleSession *session, JingleActionType action)
-{
-	JabberIq *iq = jingle_create_iq(session);
-	PurpleXmlNode *jingle = jingle_add_jingle_packet(session, iq, action);
-	jingle_session_to_xml(session, jingle, action);
-	return iq;
-}
-
-void jingle_session_handle_action(JingleSession *session, PurpleXmlNode *jingle, JingleActionType action)
-{
-	GList *iter;
-	if (action == JINGLE_CONTENT_ADD || action == JINGLE_CONTENT_REMOVE)
-		iter = jingle_session_get_pending_contents(session);
-	else
-		iter = jingle_session_get_contents(session);
-
-	for (; iter; iter = g_list_next(iter)) {
-		jingle_content_handle_action(iter->data, jingle, action);
-	}
-}
-
-JingleContent *
-jingle_session_find_content(JingleSession *session, const gchar *name, const gchar *creator)
-{
-	JingleSessionPrivate *priv = NULL;
-	GList *iter;
-
-	g_return_val_if_fail(JINGLE_IS_SESSION(session), NULL);
-
-	if (name == NULL)
-		return NULL;
-
-	priv = jingle_session_get_instance_private(session);
-
-	iter = priv->contents;
-	for (; iter; iter = g_list_next(iter)) {
-		JingleContent *content = iter->data;
-		gchar *cname = jingle_content_get_name(content);
-		gboolean result = purple_strequal(name, cname);
-		g_free(cname);
-
-		if (creator != NULL) {
-			gchar *ccreator = jingle_content_get_creator(content);
-			result = (result && purple_strequal(creator, ccreator));
-			g_free(ccreator);
-		}
-
-		if (result == TRUE)
-			return content;
-	}
-	return NULL;
-}
-
-JingleContent *
-jingle_session_find_pending_content(JingleSession *session, const gchar *name, const gchar *creator)
-{
-	JingleSessionPrivate *priv = NULL;
-	GList *iter;
-
-	g_return_val_if_fail(JINGLE_IS_SESSION(session), NULL);
-
-	if (name == NULL)
-		return NULL;
-
-	priv = jingle_session_get_instance_private(session);
-
-	iter = priv->pending_contents;
-	for (; iter; iter = g_list_next(iter)) {
-		JingleContent *content = iter->data;
-		gchar *cname = jingle_content_get_name(content);
-		gboolean result = purple_strequal(name, cname);
-		g_free(cname);
-
-		if (creator != NULL) {
-			gchar *ccreator = jingle_content_get_creator(content);
-			result = (result && purple_strequal(creator, ccreator));
-			g_free(ccreator);
-		}
-
-		if (result == TRUE)
-			return content;
-	}
-	return NULL;
-}
-
-void
-jingle_session_add_content(JingleSession *session, JingleContent* content)
-{
-	JingleSessionPrivate *priv = NULL;
-
-	g_return_if_fail(JINGLE_IS_SESSION(session));
-
-	priv = jingle_session_get_instance_private(session);
-
-	priv->contents = g_list_append(priv->contents, content);
-	jingle_content_set_session(content, session);
-
-	g_object_notify_by_pspec(G_OBJECT(session), properties[PROP_CONTENTS]);
-}
-
-void
-jingle_session_remove_content(JingleSession *session, const gchar *name, const gchar *creator)
-{
-	JingleSessionPrivate *priv = NULL;
-	JingleContent *content = NULL;
-
-	g_return_if_fail(JINGLE_IS_SESSION(session));
-
-	priv = jingle_session_get_instance_private(session);
-	content = jingle_session_find_content(session, name, creator);
-
-	if (content) {
-		priv->contents = g_list_remove(priv->contents, content);
-		g_object_unref(content);
-
-		g_object_notify_by_pspec(G_OBJECT(session), properties[PROP_CONTENTS]);
-	}
-}
-
-void
-jingle_session_add_pending_content(JingleSession *session, JingleContent* content)
-{
-	JingleSessionPrivate *priv = NULL;
-
-	g_return_if_fail(JINGLE_IS_SESSION(session));
-
-	priv = jingle_session_get_instance_private(session);
-
-	priv->pending_contents = g_list_append(priv->pending_contents, content);
-	jingle_content_set_session(content, session);
-
-	g_object_notify_by_pspec(G_OBJECT(session), properties[PROP_PENDING_CONTENTS]);
-}
-
-void
-jingle_session_remove_pending_content(JingleSession *session, const gchar *name, const gchar *creator)
-{
-	JingleSessionPrivate *priv = NULL;
-	JingleContent *content = NULL;
-
-	g_return_if_fail(JINGLE_IS_SESSION(session));
-
-	priv = jingle_session_get_instance_private(session);
-	content = jingle_session_find_pending_content(session, name, creator);
-
-	if (content) {
-		priv->pending_contents = g_list_remove(priv->pending_contents, content);
-		g_object_unref(content);
-
-		g_object_notify_by_pspec(G_OBJECT(session), properties[PROP_PENDING_CONTENTS]);
-	}
-}
-
-void
-jingle_session_accept_content(JingleSession *session, const gchar *name, const gchar *creator)
-{
-	JingleContent *content = NULL;
-
-	g_return_if_fail(JINGLE_IS_SESSION(session));
-
-	content = jingle_session_find_pending_content(session, name, creator);
-	if (content) {
-		g_object_ref(content);
-		jingle_session_remove_pending_content(session, name, creator);
-		jingle_session_add_content(session, content);
-	}
-}
-
-void
-jingle_session_accept_session(JingleSession *session)
-{
-	JingleSessionPrivate *priv = NULL;
-
-	g_return_if_fail(JINGLE_IS_SESSION(session));
-
-	priv = jingle_session_get_instance_private(session);
-
-	priv->state = TRUE;
-
-	g_object_notify_by_pspec(G_OBJECT(session), properties[PROP_STATE]);
-}
-
-JabberIq *
-jingle_session_terminate_packet(JingleSession *session, const gchar *reason)
-{
-	JabberIq *iq = NULL;
-
-	g_return_val_if_fail(JINGLE_IS_SESSION(session), NULL);
-
-	iq = jingle_session_to_packet(session, JINGLE_SESSION_TERMINATE);
-
-	if (reason != NULL) {
-		PurpleXmlNode *reason_node;
-		PurpleXmlNode *jingle = purple_xmlnode_get_child(iq->node, "jingle");
-		reason_node = purple_xmlnode_new_child(jingle, "reason");
-		purple_xmlnode_new_child(reason_node, reason);
-	}
-
-	return iq;
-}
-
-JabberIq *
-jingle_session_redirect_packet(JingleSession *session, const gchar *sid)
-{
-	JabberIq *iq = NULL;
-	PurpleXmlNode *alt_session;
-
-	g_return_val_if_fail(JINGLE_IS_SESSION(session), NULL);
-
-	iq = jingle_session_terminate_packet(session, "alternative-session");
-
-	if (sid == NULL)
-		return iq;
-
-	alt_session = purple_xmlnode_get_child(iq->node,
-			"jingle/reason/alternative-session");
-
-	if (alt_session != NULL) {
-		PurpleXmlNode *sid_node = purple_xmlnode_new_child(alt_session, "sid");
-		purple_xmlnode_insert_data(sid_node, sid, -1);
-	}
-
-	return iq;
-}
diff --git a/libpurple/protocols/jabber/jingle/transport.h b/libpurple/protocols/jabber/jingle/transport.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/jingle/transport.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * @file transport.h
- *
- * 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_JABBER_JINGLE_TRANSPORT_H
-#define PURPLE_JABBER_JINGLE_TRANSPORT_H
-
-#include <glib.h>
-#include <glib-object.h>
-
-#include <purple.h>
-
-#include "jingle.h"
-
-G_BEGIN_DECLS
-
-#define JINGLE_TYPE_TRANSPORT  jingle_transport_get_type()
-
-typedef struct _JingleTransport JingleTransport;
-
-/** The transport class */
-struct _JingleTransportClass
-{
-	GObjectClass parent_class;     /**< The parent class. */
-
-	const gchar *transport_type;
-	PurpleXmlNode *(*to_xml) (JingleTransport *transport, PurpleXmlNode *content, JingleActionType action);
-	JingleTransport *(*parse) (PurpleXmlNode *transport);
-	void (*add_local_candidate) (JingleTransport *transport, const gchar *id, guint generation, PurpleMediaCandidate *candidate);
-	GList *(*get_remote_candidates) (JingleTransport *transport);
-};
-
-/**
- * Gets the transport class's GType
- *
- * @return The transport class's GType.
- */
-G_MODULE_EXPORT
-G_DECLARE_DERIVABLE_TYPE(JingleTransport, jingle_transport, JINGLE, TRANSPORT,
-		GObject)
-
-/**
- * Registers the JingleTransport type in the type system.
- */
-void jingle_transport_register(PurplePlugin *plugin);
-
-JingleTransport *jingle_transport_create(const gchar *type);
-const gchar *jingle_transport_get_transport_type(JingleTransport *transport);
-
-void jingle_transport_add_local_candidate(JingleTransport *transport, const gchar *id, guint generation, PurpleMediaCandidate *candidate);
-GList *jingle_transport_get_remote_candidates(JingleTransport *transport);
-
-JingleTransport *jingle_transport_parse(PurpleXmlNode *transport);
-PurpleXmlNode *jingle_transport_to_xml(JingleTransport *transport, PurpleXmlNode *content, JingleActionType action);
-
-G_END_DECLS
-
-#endif /* PURPLE_JABBER_JINGLE_TRANSPORT_H */
-
diff --git a/libpurple/protocols/jabber/jingle/transport.c b/libpurple/protocols/jabber/jingle/transport.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/jingle/transport.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/**
- * @file transport.c
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "transport.h"
-#include "jingle.h"
-
-#include <string.h>
-
-G_DEFINE_DYNAMIC_TYPE(JingleTransport, jingle_transport, G_TYPE_OBJECT);
-
-/******************************************************************************
- * Transport Implementation
- *****************************************************************************/
-static JingleTransport *
-jingle_transport_parse_internal(PurpleXmlNode *transport)
-{
-	const gchar *type = purple_xmlnode_get_namespace(transport);
-	return jingle_transport_create(type);
-}
-
-static void
-jingle_transport_add_local_candidate_internal(G_GNUC_UNUSED JingleTransport *transport,
-                                              G_GNUC_UNUSED const char *id,
-                                              G_GNUC_UNUSED guint generation,
-                                              G_GNUC_UNUSED PurpleMediaCandidate *candidate)
-{
-	/* Nothing to do */
-}
-
-static PurpleXmlNode *
-jingle_transport_to_xml_internal(JingleTransport *transport,
-                                 PurpleXmlNode *content,
-                                 G_GNUC_UNUSED JingleActionType action)
-{
-	PurpleXmlNode *node = purple_xmlnode_new_child(content, "transport");
-	purple_xmlnode_set_namespace(node, jingle_transport_get_transport_type(transport));
-	return node;
-}
-
-static GList *
-jingle_transport_get_remote_candidates_internal(G_GNUC_UNUSED JingleTransport *transport)
-{
-	return NULL;
-}
-
-/******************************************************************************
- * GObject Stuff
- *****************************************************************************/
-static void
-jingle_transport_init(G_GNUC_UNUSED JingleTransport *transport)
-{
-}
-
-static void
-jingle_transport_class_finalize(G_GNUC_UNUSED JingleTransportClass *klass)
-{
-}
-
-static void
-jingle_transport_class_init (JingleTransportClass *klass)
-{
-	klass->to_xml = jingle_transport_to_xml_internal;
-	klass->parse = jingle_transport_parse_internal;
-	klass->add_local_candidate = jingle_transport_add_local_candidate_internal;
-	klass->get_remote_candidates = jingle_transport_get_remote_candidates_internal;
-}
-
-/******************************************************************************
- * Public API
- *****************************************************************************/
-void
-jingle_transport_register(PurplePlugin *plugin) {
-	jingle_transport_register_type(G_TYPE_MODULE(plugin));
-}
-
-JingleTransport *
-jingle_transport_create(const gchar *type)
-{
-	return g_object_new(jingle_get_type(type), NULL);
-}
-
-const gchar *
-jingle_transport_get_transport_type(JingleTransport *transport)
-{
-	return JINGLE_TRANSPORT_GET_CLASS(transport)->transport_type;
-}
-
-void
-jingle_transport_add_local_candidate(JingleTransport *transport, const gchar *id,
-                                     guint generation, PurpleMediaCandidate *candidate)
-{
-	JINGLE_TRANSPORT_GET_CLASS(transport)->add_local_candidate(transport, id,
-	                                                           generation, candidate);
-}
-
-GList *
-jingle_transport_get_remote_candidates(JingleTransport *transport)
-{
-	return JINGLE_TRANSPORT_GET_CLASS(transport)->get_remote_candidates(transport);
-}
-
-JingleTransport *
-jingle_transport_parse(PurpleXmlNode *transport)
-{
-	const gchar *type_name = purple_xmlnode_get_namespace(transport);
-	GType type = jingle_get_type(type_name);
-	if (type == G_TYPE_NONE)
-		return NULL;
-
-	return JINGLE_TRANSPORT_CLASS(g_type_class_ref(type))->parse(transport);
-}
-
-PurpleXmlNode *
-jingle_transport_to_xml(JingleTransport *transport, PurpleXmlNode *content, JingleActionType action)
-{
-	g_return_val_if_fail(transport != NULL, NULL);
-	g_return_val_if_fail(JINGLE_IS_TRANSPORT(transport), NULL);
-	return JINGLE_TRANSPORT_GET_CLASS(transport)->to_xml(transport, content, action);
-}
diff --git a/libpurple/protocols/jabber/jutil.h b/libpurple/protocols/jabber/jutil.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/jutil.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
- * @file jutil.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 PURPLE_JABBER_JUTIL_H
-#define PURPLE_JABBER_JUTIL_H
-
-typedef struct {
-	char *node;
-	char *domain;
-	char *resource;
-} JabberID;
-
-typedef enum {
-	JABBER_BUDDY_STATE_UNKNOWN = -2,
-	JABBER_BUDDY_STATE_ERROR = -1,
-	JABBER_BUDDY_STATE_UNAVAILABLE = 0,
-	JABBER_BUDDY_STATE_ONLINE,
-	JABBER_BUDDY_STATE_CHAT,
-	JABBER_BUDDY_STATE_AWAY,
-	JABBER_BUDDY_STATE_XA,
-	JABBER_BUDDY_STATE_DND
-} JabberBuddyState;
-
-#include "jabber.h"
-
-PURPLE_XMPP_EXTERN_FOR_TESTS
-JabberID* jabber_id_new(const char *str);
-
-/**
- * Compare two JIDs for equality. In addition to the node and domain,
- * the resources of the two JIDs must also be equal (or both absent).
- */
-gboolean jabber_id_equal(const JabberID *jid1, const JabberID *jid2);
-
-PURPLE_XMPP_EXTERN_FOR_TESTS
-void jabber_id_free(JabberID *jid);
-
-PURPLE_XMPP_EXTERN_FOR_TESTS
-char *jabber_get_resource(const char *jid);
-PURPLE_XMPP_EXTERN_FOR_TESTS
-char *jabber_get_bare_jid(const char *jid);
-char *jabber_id_get_bare_jid(const JabberID *jid);
-char *jabber_id_get_full_jid(const JabberID *jid);
-
-gboolean jabber_jid_is_domain(const char *jid);
-
-PURPLE_XMPP_EXTERN_FOR_TESTS
-const char *jabber_normalize(const PurpleAccount *account, const char *in);
-
-/* Returns true if JID is the bare JID of our account. */
-gboolean jabber_is_own_account(JabberStream *js, const char *jid);
-
-PURPLE_XMPP_EXTERN_FOR_TESTS
-gboolean jabber_nodeprep_validate(const char *);
-gboolean jabber_domain_validate(const char *);
-gboolean jabber_resourceprep_validate(const char *);
-
-/**
- * Apply the SASLprep profile of stringprep to the string passed in.
- *
- * @returns A newly allocated string containing the normalized version
- *          of the input, or NULL if an error occurred (the string could
- *          not be normalized)
- */
-PURPLE_XMPP_EXTERN_FOR_TESTS
-char *jabber_saslprep(const char *);
-
-/* state -> readable name */
-const char *jabber_buddy_state_get_name(JabberBuddyState state);
-/* state -> core id */
-const char *jabber_buddy_state_get_status_id(JabberBuddyState state);
-/* state -> show attr (for presence stanza) */
-const char *jabber_buddy_state_get_show(JabberBuddyState state);
-/* core id -> state */
-JabberBuddyState jabber_buddy_status_id_get_state(const char *id);
-/* show attr (presence stanza) -> state */
-JabberBuddyState jabber_buddy_show_get_state(const char *id);
-
-#endif /* PURPLE_JABBER_JUTIL_H */
diff --git a/libpurple/protocols/jabber/jutil.c b/libpurple/protocols/jabber/jutil.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/jutil.c
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "chat.h"
-#include "presence.h"
-#include "jutil.h"
-
-#include <idna.h>
-#include <stringprep.h>
-static char idn_buffer[1024];
-
-static gboolean jabber_nodeprep(char *str, size_t buflen)
-{
-	return stringprep_xmpp_nodeprep(str, buflen) == STRINGPREP_OK;
-}
-
-static gboolean jabber_resourceprep(char *str, size_t buflen)
-{
-	return stringprep_xmpp_resourceprep(str, buflen) == STRINGPREP_OK;
-}
-
-static JabberID*
-jabber_idn_validate(const char *str, const char *at, const char *slash,
-                    const char *null)
-{
-	const char *node = NULL;
-	const char *domain = NULL;
-	const char *resource = NULL;
-	int node_len = 0;
-	int domain_len = 0;
-	int resource_len = 0;
-	char *out;
-	JabberID *jid;
-
-	/* Ensure no parts are > 1023 bytes */
-	if (at) {
-		node = str;
-		node_len = at - str;
-
-		domain = at + 1;
-		if (slash) {
-			domain_len = slash - (at + 1);
-			resource = slash + 1;
-			resource_len = null - (slash + 1);
-		} else {
-			domain_len = null - (at + 1);
-		}
-	} else {
-		domain = str;
-
-		if (slash) {
-			domain_len = slash - str;
-			resource = slash + 1;
-			resource_len = null - (slash + 1);
-		} else {
-			domain_len = null - str;
-		}
-	}
-
-	if (node && node_len > 1023)
-		return NULL;
-	if (domain_len > 1023)
-		return NULL;
-	if (resource && resource_len > 1023)
-		return NULL;
-
-	jid = g_new0(JabberID, 1);
-
-	if (node) {
-		strncpy(idn_buffer, node, node_len);
-		idn_buffer[node_len] = '\0';
-
-		if (!jabber_nodeprep(idn_buffer, sizeof(idn_buffer))) {
-			jabber_id_free(jid);
-			jid = NULL;
-			goto out;
-		}
-
-		jid->node = g_strdup(idn_buffer);
-	}
-
-	/* domain *must* be here */
-	strncpy(idn_buffer, domain, domain_len);
-	idn_buffer[domain_len] = '\0';
-	if (domain[0] == '[') { /* IPv6 address */
-		gboolean valid = FALSE;
-
-		if (domain_len > 2 && idn_buffer[domain_len - 1] == ']') {
-			GInetAddress *addr;
-			idn_buffer[domain_len - 1] = '\0';
-			addr = g_inet_address_new_from_string(idn_buffer + 1);
-			if (addr != NULL) {
-				valid = (g_inet_address_get_family(addr) ==
-				         G_SOCKET_FAMILY_IPV6);
-				g_object_unref(addr);
-			}
-		}
-
-		if (!valid) {
-			jabber_id_free(jid);
-			jid = NULL;
-			goto out;
-		}
-
-		jid->domain = g_strndup(domain, domain_len);
-	} else {
-		/* Apply nameprep */
-		if (stringprep_nameprep(idn_buffer, sizeof(idn_buffer)) != STRINGPREP_OK) {
-			jabber_id_free(jid);
-			jid = NULL;
-			goto out;
-		}
-
-		/* And now ToASCII */
-		if (idna_to_ascii_8z(idn_buffer, &out, IDNA_USE_STD3_ASCII_RULES) != IDNA_SUCCESS) {
-			jabber_id_free(jid);
-			jid = NULL;
-			goto out;
-		}
-
-		/* This *MUST* be freed using 'free', not 'g_free' */
-		free(out);
-		jid->domain = g_strdup(idn_buffer);
-	}
-
-	if (resource) {
-		strncpy(idn_buffer, resource, resource_len);
-		idn_buffer[resource_len] = '\0';
-
-		if (!jabber_resourceprep(idn_buffer, sizeof(idn_buffer))) {
-			jabber_id_free(jid);
-			jid = NULL;
-			goto out;
-		} else
-			jid->resource = g_strdup(idn_buffer);
-	}
-
-out:
-	return jid;
-}
-
-gboolean jabber_nodeprep_validate(const char *str)
-{
-	gboolean result;
-
-	if(!str)
-		return TRUE;
-
-	if(strlen(str) > 1023)
-		return FALSE;
-
-	strncpy(idn_buffer, str, sizeof(idn_buffer) - 1);
-	idn_buffer[sizeof(idn_buffer) - 1] = '\0';
-	result = jabber_nodeprep(idn_buffer, sizeof(idn_buffer));
-	return result;
-}
-
-gboolean jabber_domain_validate(const char *str)
-{
-	const char *c;
-	size_t len;
-
-	if(!str)
-		return TRUE;
-
-	len = strlen(str);
-	if (len > 1023)
-		return FALSE;
-
-	c = str;
-
-	if (*c == '[') {
-		/* Check if str is a valid IPv6 identifier */
-		GInetAddress *addr;
-		gboolean valid = FALSE;
-
-		if (len <= 2 || *(c + len - 1) != ']') {
-			return FALSE;
-		}
-
-		/* Ugly, but in-place */
-		*(gchar *)(c + len - 1) = '\0';
-		addr = g_inet_address_new_from_string(c + 1);
-		if (addr != NULL) {
-			valid = (g_inet_address_get_family(addr) == G_SOCKET_FAMILY_IPV6);
-			g_object_unref(addr);
-		}
-		*(gchar *)(c + len - 1) = ']';
-
-		return valid;
-	}
-
-	while(c && *c) {
-		gunichar ch = g_utf8_get_char(c);
-		/* The list of characters allowed in domain names is pretty small */
-		if ((ch <= 0x7F && !( (ch >= 'a' && ch <= 'z')
-				|| (ch >= '0' && ch <= '9')
-				|| (ch >= 'A' && ch <= 'Z')
-				|| ch == '.'
-				|| ch == '-' )) || (ch >= 0x80 && !g_unichar_isgraph(ch)))
-			return FALSE;
-
-		c = g_utf8_next_char(c);
-	}
-
-	return TRUE;
-}
-
-gboolean jabber_resourceprep_validate(const char *str)
-{
-	gboolean result;
-
-	if(!str)
-		return TRUE;
-
-	if(strlen(str) > 1023)
-		return FALSE;
-
-	strncpy(idn_buffer, str, sizeof(idn_buffer) - 1);
-	idn_buffer[sizeof(idn_buffer) - 1] = '\0';
-	result = jabber_resourceprep(idn_buffer, sizeof(idn_buffer));
-	return result;
-}
-
-char *jabber_saslprep(const char *in)
-{
-	char *out;
-
-	g_return_val_if_fail(in != NULL, NULL);
-	g_return_val_if_fail(strlen(in) <= sizeof(idn_buffer) - 1, NULL);
-
-	strncpy(idn_buffer, in, sizeof(idn_buffer) - 1);
-	idn_buffer[sizeof(idn_buffer) - 1] = '\0';
-
-	if (STRINGPREP_OK != stringprep(idn_buffer, sizeof(idn_buffer), 0,
-	                                stringprep_saslprep)) {
-		memset(idn_buffer, 0, sizeof(idn_buffer));
-		return NULL;
-	}
-
-	out = g_strdup(idn_buffer);
-	memset(idn_buffer, 0, sizeof(idn_buffer));
-	return out;
-}
-
-static JabberID*
-jabber_id_new_internal(const char *str, gboolean allow_terminating_slash)
-{
-	const char *at = NULL;
-	const char *slash = NULL;
-	const char *c;
-	gboolean needs_validation = FALSE;
-	JabberID *jid;
-
-	if (!str)
-		return NULL;
-
-	for (c = str; *c != '\0'; c++)
-	{
-		switch (*c) {
-			case '@':
-				if (!slash) {
-					if (at) {
-						/* Multiple @'s in the node/domain portion, not a valid JID! */
-						return NULL;
-					}
-					if (c == str) {
-						/* JIDs cannot start with @ */
-						return NULL;
-					}
-					if (c[1] == '\0') {
-						/* JIDs cannot end with @ */
-						return NULL;
-					}
-					at = c;
-				}
-				break;
-
-			case '/':
-				if (!slash) {
-					if (c == str) {
-						/* JIDs cannot start with / */
-						return NULL;
-					}
-					if (c[1] == '\0' && !allow_terminating_slash) {
-						/* JIDs cannot end with / */
-						return NULL;
-					}
-					slash = c;
-				}
-				break;
-
-			default:
-				/* characters allowed everywhere */
-				if ((*c >= 'a' && *c <= 'z')
-						|| (*c >= '0' && *c <= '9')
-						|| (*c >= 'A' && *c <= 'Z')
-						|| *c == '.' || *c == '-')
-					/* We're good */
-					break;
-
-				/*
-				 * Hmm, this character is a bit more exotic.  Better fall
-				 * back to using the more expensive UTF-8 compliant
-				 * stringprep functions.
-				 */
-				needs_validation = TRUE;
-				break;
-		}
-	}
-
-	if (!needs_validation) {
-		/* JID is made of only ASCII characters--just lowercase and return */
-		jid = g_new0(JabberID, 1);
-
-		if (at) {
-			jid->node = g_ascii_strdown(str, at - str);
-			if (slash) {
-				jid->domain = g_ascii_strdown(at + 1, slash - (at + 1));
-				if (*(slash + 1))
-					jid->resource = g_strdup(slash + 1);
-			} else {
-				jid->domain = g_ascii_strdown(at + 1, -1);
-			}
-		} else {
-			if (slash) {
-				jid->domain = g_ascii_strdown(str, slash - str);
-				if (*(slash + 1))
-					jid->resource = g_strdup(slash + 1);
-			} else {
-				jid->domain = g_ascii_strdown(str, -1);
-			}
-		}
-		return jid;
-	}
-
-	/*
-	 * If we get here, there are some non-ASCII chars in the string, so
-	 * we'll need to validate it, normalize, and finally do a full jabber
-	 * nodeprep on the jid.
-	 */
-
-	if (!g_utf8_validate(str, -1, NULL))
-		return NULL;
-
-	return jabber_idn_validate(str, at, slash, c /* points to the null */);
-}
-
-void
-jabber_id_free(JabberID *jid)
-{
-	if(jid) {
-		g_free(jid->node);
-		g_free(jid->domain);
-		g_free(jid->resource);
-		g_free(jid);
-	}
-}
-
-
-gboolean
-jabber_id_equal(const JabberID *jid1, const JabberID *jid2)
-{
-	if (!jid1 && !jid2) {
-		/* Both are null therefore equal */
-		return TRUE;
-	}
-
-	if (!jid1 || !jid2) {
-		/* One is null, other is non-null, therefore not equal */
-		return FALSE;
-	}
-
-	return purple_strequal(jid1->node, jid2->node) &&
-			purple_strequal(jid1->domain, jid2->domain) &&
-			purple_strequal(jid1->resource, jid2->resource);
-}
-
-char *jabber_get_resource(const char *in)
-{
-	JabberID *jid = jabber_id_new(in);
-	char *out;
-
-	if(!jid)
-		return NULL;
-
-	out = g_strdup(jid->resource);
-	jabber_id_free(jid);
-
-	return out;
-}
-
-char *
-jabber_get_bare_jid(const char *in)
-{
-	JabberID *jid = jabber_id_new(in);
-	char *out;
-
-	if (!jid)
-		return NULL;
-	out = jabber_id_get_bare_jid(jid);
-	jabber_id_free(jid);
-
-	return out;
-}
-
-char *
-jabber_id_get_bare_jid(const JabberID *jid)
-{
-	g_return_val_if_fail(jid != NULL, NULL);
-
-	return g_strconcat(jid->node ? jid->node : "",
-	                   jid->node ? "@" : "",
-	                   jid->domain,
-	                   NULL);
-}
-
-char *
-jabber_id_get_full_jid(const JabberID *jid)
-{
-	g_return_val_if_fail(jid != NULL, NULL);
-
-	return g_strconcat(jid->node ? jid->node : "",
-	                   jid->node ? "@" : "",
-	                   jid->domain,
-	                   jid->resource ? "/" : "",
-	                   jid->resource ? jid->resource : "",
-	                   NULL);
-}
-
-gboolean
-jabber_jid_is_domain(const char *jid)
-{
-	const char *c;
-
-	for (c = jid; *c; ++c) {
-		if (*c == '@' || *c == '/')
-			return FALSE;
-	}
-
-	return TRUE;
-}
-
-
-JabberID *
-jabber_id_new(const char *str)
-{
-	return jabber_id_new_internal(str, FALSE);
-}
-
-const char *jabber_normalize(const PurpleAccount *account, const char *in)
-{
-	PurpleConnection *gc = NULL;
-	JabberStream *js = NULL;
-	static char buf[3072]; /* maximum legal length of a jabber jid */
-	JabberID *jid;
-
-	if (account) {
-		gc = purple_account_get_connection((PurpleAccount *)account);
-	}
-	if (gc)
-		js = purple_connection_get_protocol_data(gc);
-
-	jid = jabber_id_new_internal(in, TRUE);
-	if(!jid)
-		return NULL;
-
-	if(js && jid->node && jid->resource &&
-			jabber_chat_find(js, jid->node, jid->domain))
-		g_snprintf(buf, sizeof(buf), "%s@%s/%s", jid->node, jid->domain,
-				jid->resource);
-	else
-		g_snprintf(buf, sizeof(buf), "%s%s%s", jid->node ? jid->node : "",
-				jid->node ? "@" : "", jid->domain);
-
-	jabber_id_free(jid);
-
-	return buf;
-}
-
-gboolean
-jabber_is_own_account(JabberStream *js, const char *str)
-{
-	JabberID *jid;
-	gboolean equal;
-
-	if (str == NULL)
-		return TRUE;
-
-	g_return_val_if_fail(*str != '\0', FALSE);
-
-	jid = jabber_id_new(str);
-	if (!jid)
-		return FALSE;
-
-	equal = (purple_strequal(jid->node, js->user->node) &&
-	         purple_strequal(jid->domain, js->user->domain) &&
-	         (jid->resource == NULL ||
-	             purple_strequal(jid->resource, js->user->resource)));
-	jabber_id_free(jid);
-	return equal;
-}
-
-static const struct {
-		const char *status_id; /* link to core */
-		const char *show; /* The show child's cdata in a presence stanza */
-		const char *readable; /* readable representation */
-		JabberBuddyState state;
-} jabber_statuses[] = {
-	{ "offline",       NULL,   N_("Offline"),        JABBER_BUDDY_STATE_UNAVAILABLE },
-	{ "available",     NULL,   N_("Available"),      JABBER_BUDDY_STATE_ONLINE},
-	{ "freeforchat",   "chat", N_("Chatty"),         JABBER_BUDDY_STATE_CHAT },
-	{ "away",          "away", N_("Away"),           JABBER_BUDDY_STATE_AWAY },
-	{ "extended_away", "xa",   N_("Extended Away"),  JABBER_BUDDY_STATE_XA },
-	{ "dnd",           "dnd",  N_("Do Not Disturb"), JABBER_BUDDY_STATE_DND },
-	{ "error",         NULL,   N_("Error"),          JABBER_BUDDY_STATE_ERROR }
-};
-
-const char *
-jabber_buddy_state_get_name(const JabberBuddyState state)
-{
-	gsize i;
-	for (i = 0; i < G_N_ELEMENTS(jabber_statuses); ++i)
-		if (jabber_statuses[i].state == state)
-			return _(jabber_statuses[i].readable);
-
-	return _("Unknown");
-}
-
-JabberBuddyState
-jabber_buddy_status_id_get_state(const char *id)
-{
-	gsize i;
-	if (!id)
-		return JABBER_BUDDY_STATE_UNKNOWN;
-
-	for (i = 0; i < G_N_ELEMENTS(jabber_statuses); ++i)
-		if (purple_strequal(id, jabber_statuses[i].status_id))
-			return jabber_statuses[i].state;
-
-	return JABBER_BUDDY_STATE_UNKNOWN;
-}
-
-JabberBuddyState jabber_buddy_show_get_state(const char *id)
-{
-	gsize i;
-
-	g_return_val_if_fail(id != NULL, JABBER_BUDDY_STATE_UNKNOWN);
-
-	for (i = 0; i < G_N_ELEMENTS(jabber_statuses); ++i)
-		if (jabber_statuses[i].show && purple_strequal(id, jabber_statuses[i].show))
-			return jabber_statuses[i].state;
-
-	purple_debug_warning("jabber", "Invalid value of presence <show/> "
-	                     "attribute: %s\n", id);
-	return JABBER_BUDDY_STATE_UNKNOWN;
-}
-
-const char *
-jabber_buddy_state_get_show(JabberBuddyState state)
-{
-	gsize i;
-	for (i = 0; i < G_N_ELEMENTS(jabber_statuses); ++i)
-		if (state == jabber_statuses[i].state)
-			return jabber_statuses[i].show;
-
-	return NULL;
-}
-
-const char *
-jabber_buddy_state_get_status_id(JabberBuddyState state)
-{
-	gsize i;
-	for (i = 0; i < G_N_ELEMENTS(jabber_statuses); ++i)
-		if (state == jabber_statuses[i].state)
-			return jabber_statuses[i].status_id;
-
-	return NULL;
-}
-
diff --git a/libpurple/protocols/jabber/meson.build b/libpurple/protocols/jabber/meson.build
deleted file mode 100644
--- a/libpurple/protocols/jabber/meson.build
+++ /dev/null
@@ -1,103 +0,0 @@
-#######################################################################
-# Check for Internationalized Domain Name support
-#######################################################################
-
-JABBER_SOURCES = [
-	'adhoccommands.c',
-	'adhoccommands.h',
-	'auth.c',
-	'auth.h',
-	'auth_digest_md5.c',
-	'auth_digest_md5.h',
-	'auth_plain.c',
-	'auth_scram.c',
-	'auth_scram.h',
-	'auth_webex.c',
-	'buddy.c',
-	'buddy.h',
-	'bosh.c',
-	'bosh.h',
-	'caps.c',
-	'caps.h',
-	'chat.c',
-	'chat.h',
-	'data.c',
-	'data.h',
-	'disco.c',
-	'disco.h',
-	'ibb.c',
-	'ibb.h',
-	'iq.c',
-	'iq.h',
-	'jabber.c',
-	'jabber.h',
-	'jingle/jingle.c',
-	'jingle/jingle.h',
-	'jingle/content.c',
-	'jingle/content.h',
-	'jingle/iceudp.c',
-	'jingle/iceudp.h',
-	'jingle/rawudp.c',
-	'jingle/rawudp.h',
-	'jingle/rtp.c',
-	'jingle/rtp.h',
-	'jingle/session.c',
-	'jingle/session.h',
-	'jingle/transport.c',
-	'jingle/transport.h',
-	'jutil.c',
-	'jutil.h',
-	'message.c',
-	'message.h',
-	'namespaces.h',
-	'oob.c',
-	'oob.h',
-	'parser.c',
-	'parser.h',
-	'pep.c',
-	'pep.h',
-	'ping.c',
-	'ping.h',
-	'presence.c',
-	'presence.h',
-	'roster.c',
-	'roster.h',
-	'si.c',
-	'si.h',
-	'useravatar.c',
-	'useravatar.h',
-	'usernick.c',
-	'usernick.h',
-	'xdata.c',
-	'xdata.h',
-	'xmpp.c',
-	'xmpp.h'
-]
-
-if IS_WIN32
-	jabber_link_args = ['-Wl,--export-all-symbols']
-else
-	jabber_link_args = []
-endif
-
-if DYNAMIC_JABBER
-	idn = dependency('libidn', version : '>= 0.0.0')
-
-	xmpp_resources = gnome.compile_resources('xmppresource',
-		'resources/xmpp.gresource.xml',
-		source_dir : 'resources',
-		c_name : 'xmpp')
-	JABBER_SOURCES += xmpp_resources
-
-	jabber_prpl = shared_library('jabber', JABBER_SOURCES,
-	    c_args : ['-DPURPLE_XMPP_COMPILATION', '-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="Purple-XMPP"'],
-	    gnu_symbol_visibility : 'hidden',
-	    link_args : jabber_link_args,
-	    dependencies : [birb_dep, gstreamer, idn, libxml, libpurple_dep, libsoup, glib, gio, math],
-	    install : true,
-	    install_dir : PURPLE_PLUGINDIR)
-
-	devenv.append('PURPLE_PLUGIN_PATH', meson.current_build_dir())
-
-	subdir('tests')
-endif
diff --git a/libpurple/protocols/jabber/message.h b/libpurple/protocols/jabber/message.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/message.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * @file message.h Message handlers
- *
- * 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_JABBER_MESSAGE_H
-#define PURPLE_JABBER_MESSAGE_H
-
-#include <purple.h>
-
-#include "jabber.h"
-
-typedef struct {
-	JabberStream *js;
-	enum {
-		JABBER_MESSAGE_NORMAL,
-		JABBER_MESSAGE_CHAT,
-		JABBER_MESSAGE_GROUPCHAT,
-		JABBER_MESSAGE_HEADLINE,
-		JABBER_MESSAGE_ERROR,
-		JABBER_MESSAGE_GROUPCHAT_INVITE,
-		JABBER_MESSAGE_EVENT,
-		JABBER_MESSAGE_OTHER
-	} type;
-	GDateTime *sent;
-	gboolean delayed;
-	gboolean forwarded;
-	gboolean outgoing;
-	char *id;
-	char *from;
-	char *to;
-	char *subject;
-	char *body;
-	char *xhtml;
-	char *password;
-	char *error;
-	char *thread_id;
-	enum {
-		JM_STATE_NONE,
-		JM_STATE_ACTIVE,
-		JM_STATE_COMPOSING,
-		JM_STATE_PAUSED,
-		JM_STATE_INACTIVE,
-		JM_STATE_GONE
-	} chat_state;
-	GList *etc;
-	GList *eventitems;
-} JabberMessage;
-
-void jabber_message_free(JabberMessage *jm);
-
-void jabber_message_send(JabberMessage *jm);
-
-void jabber_message_parse(JabberStream *js, PurpleXmlNode *packet);
-int jabber_message_send_im(PurpleProtocolIM *pim, PurpleConnection *gc, PurpleConversation *conversation, PurpleMessage *msg);
-int jabber_message_send_chat(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id, PurpleConversation *conversation, PurpleMessage *msg);
-
-unsigned int jabber_send_typing(PurpleProtocolIM *pim, PurpleConnection *gc, const char *who, PurpleIMTypingState state);
-
-#endif /* PURPLE_JABBER_MESSAGE_H */
diff --git a/libpurple/protocols/jabber/message.c b/libpurple/protocols/jabber/message.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/message.c
+++ /dev/null
@@ -1,1002 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "adhoccommands.h"
-#include "buddy.h"
-#include "chat.h"
-#include "data.h"
-#include "message.h"
-#include "pep.h"
-#include "iq.h"
-
-#include <string.h>
-
-static GString *jm_body_with_oob(JabberMessage *jm) {
-	GList *etc;
-	GString *body = g_string_new("");
-
-	if(jm->xhtml)
-		g_string_append(body, jm->xhtml);
-	else if(jm->body)
-		g_string_append(body, jm->body);
-
-	for(etc = jm->etc; etc; etc = etc->next) {
-		PurpleXmlNode *x = etc->data;
-		const char *xmlns = purple_xmlnode_get_namespace(x);
-		if(purple_strequal(xmlns, NS_OOB_X_DATA)) {
-			PurpleXmlNode *url, *desc;
-			char *urltxt, *desctxt;
-
-			url = purple_xmlnode_get_child(x, "url");
-			desc = purple_xmlnode_get_child(x, "desc");
-
-			if(!url)
-				continue;
-
-			urltxt = purple_xmlnode_get_data(url);
-			desctxt = desc ? purple_xmlnode_get_data(desc) : urltxt;
-
-			if(body->len && !purple_strequal(body->str, urltxt))
-				g_string_append_printf(body, "<br/><a href='%s'>%s</a>",
-						urltxt, desctxt);
-			else
-				g_string_printf(body, "<a href='%s'>%s</a>",
-						urltxt, desctxt);
-
-			g_free(urltxt);
-
-			if(desctxt != urltxt)
-				g_free(desctxt);
-		}
-	}
-
-	return body;
-}
-
-void jabber_message_free(JabberMessage *jm)
-{
-	g_free(jm->from);
-	g_free(jm->to);
-	g_free(jm->id);
-	g_free(jm->subject);
-	g_free(jm->body);
-	g_free(jm->xhtml);
-	g_free(jm->password);
-	g_free(jm->error);
-	g_free(jm->thread_id);
-	g_list_free(jm->etc);
-	g_list_free(jm->eventitems);
-
-	g_clear_pointer(&jm->sent, g_date_time_unref);
-
-	g_free(jm);
-}
-
-static void handle_chat(JabberMessage *jm)
-{
-	const gchar *contact = jm->outgoing ? jm->to : jm->from;
-	JabberID *jid = jabber_id_new(contact);
-
-	PurpleConnection *gc;
-	PurpleConversationManager *manager;
-	PurpleAccount *account;
-	PurpleMessageFlags flags = 0;
-	JabberBuddy *jb;
-	JabberBuddyResource *jbr;
-	GString *body;
-
-	if(!jid)
-		return;
-
-	manager = purple_conversation_manager_get_default();
-
-	gc = jm->js->gc;
-	account = purple_connection_get_account(gc);
-
-	jb = jabber_buddy_find(jm->js, contact, TRUE);
-	jbr = jabber_buddy_find_resource(jb, jid->resource);
-
-	if (jbr && jm->chat_state != JM_STATE_NONE)
-		jbr->chat_states = JABBER_CHAT_STATES_SUPPORTED;
-
-	switch(jm->chat_state) {
-		case JM_STATE_COMPOSING:
-			purple_serv_got_typing(gc, contact, 0, PURPLE_IM_TYPING);
-			break;
-		case JM_STATE_PAUSED:
-			purple_serv_got_typing(gc, contact, 0, PURPLE_IM_TYPED);
-			break;
-		case JM_STATE_GONE: {
-			PurpleConversation *im = NULL;
-
-			im = purple_conversation_manager_find_im(manager, account, contact);
-
-			if (im && jid->node && jid->domain) {
-				char buf[256];
-				PurpleBuddy *buddy;
-
-				g_snprintf(buf, sizeof(buf), "%s@%s", jid->node, jid->domain);
-
-				if ((buddy = purple_blist_find_buddy(account, buf))) {
-					const char *who;
-					char *escaped;
-
-					who = purple_buddy_get_alias(buddy);
-					escaped = g_markup_escape_text(who, -1);
-
-					g_snprintf(buf, sizeof(buf),
-					           _("%s has left the conversation."), escaped);
-					g_free(escaped);
-
-					/* At some point when we restructure PurpleConversation,
-					 * this should be able to be implemented by removing the
-					 * user from the conversation like we do with chats now. */
-					purple_conversation_write_system_message(im, buf, 0);
-				}
-			}
-			purple_serv_got_typing_stopped(gc, contact);
-			break;
-		}
-		default:
-			purple_serv_got_typing_stopped(gc, contact);
-	}
-
-	body = jm_body_with_oob(jm);
-
-	if(body && body->len) {
-		if (jid->resource) {
-			/*
-			 * We received a message from a specific resource, so
-			 * we probably want a reply to go to this specific
-			 * resource (i.e. bind/lock the conversation to this
-			 * resource).
-			 *
-			 * This works because purple_im_conversation_send gets the name
-			 * from purple_conversation_get_name()
-			 */
-			PurpleConversation *im;
-
-			im = purple_conversation_manager_find_im(manager, account, contact);
-			if (im && !purple_strequal(contact,
-					purple_conversation_get_name(im))) {
-				purple_debug_info("jabber", "Binding conversation to %s\n",
-				                  contact);
-				purple_conversation_set_name(im, contact);
-			}
-		}
-
-		if(jbr) {
-			/* Treat SUPPORTED as a terminal with no escape :) */
-			if (jbr->chat_states != JABBER_CHAT_STATES_SUPPORTED) {
-				if (jm->chat_state != JM_STATE_NONE)
-					jbr->chat_states = JABBER_CHAT_STATES_SUPPORTED;
-				else
-					jbr->chat_states = JABBER_CHAT_STATES_UNSUPPORTED;
-			}
-
-			g_free(jbr->thread_id);
-			jbr->thread_id = g_strdup(jm->thread_id);
-		}
-
-		if(jm->forwarded) {
-			flags |= PURPLE_MESSAGE_FORWARDED;
-		}
-		flags |= jm->outgoing ? PURPLE_MESSAGE_SEND : PURPLE_MESSAGE_RECV;
-
-		purple_serv_got_im(gc, contact, body->str, flags,
-		                   (time_t)g_date_time_to_unix(jm->sent));
-	}
-
-	jabber_id_free(jid);
-
-	if(body)
-		g_string_free(body, TRUE);
-}
-
-static void handle_headline(JabberMessage *jm)
-{
-	char *title;
-	GString *body;
-
-	if(!jm->xhtml && !jm->body)
-		return; /* ignore headlines without any content */
-
-	body = jm_body_with_oob(jm);
-	title = g_strdup_printf(_("Message from %s"), jm->from);
-
-	purple_notify_formatted(jm->js->gc, title, jm->subject ? jm->subject : title,
-			NULL, body->str, NULL, NULL);
-
-	g_free(title);
-	g_string_free(body, TRUE);
-}
-
-static void handle_groupchat(JabberMessage *jm)
-{
-	JabberID *jid = jabber_id_new(jm->from);
-	JabberChat *chat;
-	PurpleMessageFlags messageFlags = 0;
-
-	if(!jid)
-		return;
-
-	chat = jabber_chat_find(jm->js, jid->node, jid->domain);
-
-	if(!chat)
-		return;
-
-	if(jm->subject) {
-		/* TODO: use set_topic_full when we support contact info's. */
-		purple_conversation_set_topic(PURPLE_CONVERSATION(chat->conv),
-		                              jm->subject);
-		messageFlags |= PURPLE_MESSAGE_NO_LOG;
-		if(!jm->xhtml && !jm->body) {
-			char *msg, *tmp, *tmp2;
-			tmp = g_markup_escape_text(jm->subject, -1);
-			tmp2 = purple_markup_linkify(tmp);
-			if(jid->resource)
-				msg = g_strdup_printf(_("%s has set the topic to: %s"), jid->resource, tmp2);
-			else
-				msg = g_strdup_printf(_("The topic is: %s"), tmp2);
-			purple_conversation_write_system_message(PURPLE_CONVERSATION(chat->conv),
-				msg, messageFlags);
-			g_free(tmp);
-			g_free(tmp2);
-			g_free(msg);
-		}
-	}
-
-	if(jm->xhtml || jm->body) {
-		if(jid->resource) {
-			time_t sent = (time_t)g_date_time_to_unix(jm->sent);
-
-			purple_serv_got_chat_in(jm->js->gc, chat->id, jid->resource,
-							messageFlags | (jm->delayed ? PURPLE_MESSAGE_DELAYED : 0),
-							jm->xhtml ? jm->xhtml : jm->body, sent);
-		} else if(chat->muc) {
-			purple_conversation_write_system_message(
-				PURPLE_CONVERSATION(chat->conv),
-				jm->xhtml ? jm->xhtml : jm->body, messageFlags);
-		}
-	}
-
-	jabber_id_free(jid);
-}
-
-static void handle_groupchat_invite(JabberMessage *jm)
-{
-	GHashTable *components;
-	JabberID *jid = jabber_id_new(jm->to);
-
-	if(!jid)
-		return;
-
-	components = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
-
-	g_hash_table_replace(components, "room", g_strdup(jid->node));
-	g_hash_table_replace(components, "server", g_strdup(jid->domain));
-	g_hash_table_replace(components, "handle", g_strdup(jm->js->user->node));
-	g_hash_table_replace(components, "password", g_strdup(jm->password));
-
-	jabber_id_free(jid);
-	purple_serv_got_chat_invite(jm->js->gc, jm->to, jm->from, jm->body, components);
-}
-
-static void handle_error(JabberMessage *jm)
-{
-	char *buf;
-
-	if(!jm->body)
-		return;
-
-	buf = g_strdup_printf(_("Message delivery to %s failed: %s"),
-			jm->from, jm->error ? jm->error : "");
-
-	purple_notify_formatted(jm->js->gc, _("XMPP Message Error"), _("XMPP Message Error"), buf,
-			jm->xhtml ? jm->xhtml : jm->body, NULL, NULL);
-
-	g_free(buf);
-}
-
-static gchar *
-jabber_message_xml_to_string_strip_img_smileys(PurpleXmlNode *xhtml)
-{
-	gchar *markup = purple_xmlnode_to_str(xhtml, NULL);
-	int len = strlen(markup);
-	int pos = 0;
-	GString *out = g_string_new(NULL);
-
-	while (pos < len) {
-		/* this is a bit cludgy, maybe there is a better way to do this...
-		  we need to find all <img> tags within the XHTML and replace those
-			tags with the value of their "alt" attributes */
-		if (g_str_has_prefix(&(markup[pos]), "<img")) {
-			PurpleXmlNode *img = NULL;
-			int pos2 = pos;
-			const gchar *src;
-
-			for (; pos2 < len ; pos2++) {
-				if (g_str_has_prefix(&(markup[pos2]), "/>")) {
-					pos2 += 2;
-					break;
-				} else if (g_str_has_prefix(&(markup[pos2]), "</img>")) {
-					pos2 += 5;
-					break;
-				}
-			}
-
-			/* note, if the above loop didn't find the end of the <img> tag,
-			  it the parsed string will be until the end of the input string,
-			  in which case purple_xmlnode_from_str will bail out and return NULL,
-			  in this case the "if" statement below doesn't trigger and the
-			  text is copied unchanged */
-			img = purple_xmlnode_from_str(&(markup[pos]), pos2 - pos);
-			src = purple_xmlnode_get_attrib(img, "src");
-
-			if (g_str_has_prefix(src, "cid:")) {
-				const gchar *alt = purple_xmlnode_get_attrib(img, "alt");
-				/* if the "alt" attribute is empty, put the cid as smiley string */
-				if (alt && alt[0] != '\0') {
-					/* if the "alt" is the same as the CID, as Jabbim does,
-					 this prevents linkification... */
-					if (purple_email_is_valid(alt)) {
-						gchar *safe_alt = g_strdup_printf("smiley:%s", alt);
-						out = g_string_append(out, safe_alt);
-						g_free(safe_alt);
-					} else {
-						gchar *alt_escaped = g_markup_escape_text(alt, -1);
-						out = g_string_append(out, alt_escaped);
-						g_free(alt_escaped);
-					}
-				} else {
-					out = g_string_append(out, src);
-				}
-				pos += pos2 - pos;
-			} else {
-				out = g_string_append_c(out, markup[pos]);
-				pos++;
-			}
-
-			purple_xmlnode_free(img);
-
-		} else {
-			out = g_string_append_c(out, markup[pos]);
-			pos++;
-		}
-	}
-
-	g_free(markup);
-	return g_string_free(out, FALSE);
-}
-
-void jabber_message_parse(JabberStream *js, PurpleXmlNode *packet)
-{
-	JabberMessage *jm;
-	const char *id, *from, *to, *type;
-	PurpleXmlNode *child = NULL, *received = NULL;
-	gboolean signal_return;
-	gboolean delayed = FALSE, is_outgoing = FALSE, is_forwarded = FALSE;
-	GDateTime *timestamp = g_date_time_new_now_utc();
-
-	/* Check if we have a carbons received element from our own account. */
-	from = purple_xmlnode_get_attrib(packet, "from");
-	if(from != NULL && jabber_is_own_account(js, from)) {
-		PurpleXmlNode *forwarded = NULL;
-
-		/* We check if this is a received carbon first. */
-		received = purple_xmlnode_get_child_with_namespace(packet, "received",
-		                                                   NS_MESSAGE_CARBONS);
-		if(received != NULL) {
-			forwarded = purple_xmlnode_get_child_with_namespace(received,
-			                                                    "forwarded",
-			                                                    NS_FORWARD);
-		} else {
-			PurpleXmlNode *sent = NULL;
-
-			sent = purple_xmlnode_get_child_with_namespace(packet, "sent",
-			                                               NS_MESSAGE_CARBONS);
-			if(sent != NULL) {
-				forwarded = purple_xmlnode_get_child_with_namespace(sent,
-				                                                    "forwarded",
-				                                                    NS_FORWARD);
-				is_outgoing = TRUE;
-			}
-		}
-
-		if(forwarded != NULL) {
-			PurpleXmlNode *fwd_msg = NULL;
-
-			fwd_msg = purple_xmlnode_get_child_with_namespace(forwarded,
-			                                                  "message",
-			                                                  NS_XMPP_CLIENT);
-			if(fwd_msg != NULL) {
-				PurpleXmlNode *delay = NULL;
-
-				/* We have a forwarded message, so update the packet to point
-				 * to it directly.
-				 */
-				packet = fwd_msg;
-				is_forwarded = TRUE;
-
-				/* Now check if it was a delayed message and if so, grab the
-				 * timestamp that the server sent.
-				 */
-				delay = purple_xmlnode_get_child_with_namespace(forwarded,
-				                                                "delay",
-				                                                NS_DELAYED_DELIVERY);
-				if(delay != NULL) {
-					GDateTime *delayed_ts = NULL;
-					GTimeZone *tz = g_time_zone_new_utc();
-					const gchar *ts = purple_xmlnode_get_attrib(delay,
-					                                            "stamp");
-
-					delayed_ts = g_date_time_new_from_iso8601(ts, tz);
-					g_time_zone_unref(tz);
-
-					if(delayed_ts != NULL) {
-						delayed = TRUE;
-						g_date_time_unref(timestamp);
-						timestamp = delayed_ts;
-					}
-				}
-			}
-		}
-	}
-
-	/* If the message was forwarded, packet is now pointing to the forwarded
-	 * message.
-	 */
-	from = purple_xmlnode_get_attrib(packet, "from");
-	id = purple_xmlnode_get_attrib(packet, "id");
-	to = purple_xmlnode_get_attrib(packet, "to");
-	type = purple_xmlnode_get_attrib(packet, "type");
-
-	signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_protocol(js->gc),
-			"jabber-receiving-message", js->gc, type, id, from, to, packet));
-	if (signal_return)
-		return;
-
-	jm = g_new0(JabberMessage, 1);
-	jm->js = js;
-	jm->sent = timestamp;
-	jm->delayed = delayed;
-	jm->chat_state = JM_STATE_NONE;
-	jm->forwarded = is_forwarded;
-	jm->outgoing = is_outgoing;
-
-	if(type) {
-		if(purple_strequal(type, "normal"))
-			jm->type = JABBER_MESSAGE_NORMAL;
-		else if(purple_strequal(type, "chat"))
-			jm->type = JABBER_MESSAGE_CHAT;
-		else if(purple_strequal(type, "groupchat"))
-			jm->type = JABBER_MESSAGE_GROUPCHAT;
-		else if(purple_strequal(type, "headline"))
-			jm->type = JABBER_MESSAGE_HEADLINE;
-		else if(purple_strequal(type, "error"))
-			jm->type = JABBER_MESSAGE_ERROR;
-		else
-			jm->type = JABBER_MESSAGE_OTHER;
-	} else {
-		jm->type = JABBER_MESSAGE_NORMAL;
-	}
-
-	jm->from = g_strdup(from);
-	jm->to   = g_strdup(to);
-	jm->id   = g_strdup(id);
-
-	for(child = packet->child; child; child = child->next) {
-		const char *xmlns = purple_xmlnode_get_namespace(child);
-		if(child->type != PURPLE_XMLNODE_TYPE_TAG)
-			continue;
-
-		if(purple_strequal(child->name, "error")) {
-			const char *code = purple_xmlnode_get_attrib(child, "code");
-			char *code_txt = NULL;
-			char *text = purple_xmlnode_get_data(child);
-			if (!text) {
-				PurpleXmlNode *enclosed_text_node;
-
-				if ((enclosed_text_node = purple_xmlnode_get_child(child, "text")))
-					text = purple_xmlnode_get_data(enclosed_text_node);
-			}
-
-			if(code)
-				code_txt = g_strdup_printf(_("(Code %s)"), code);
-
-			if(!jm->error)
-				jm->error = g_strdup_printf("%s%s%s",
-						text ? text : "",
-						text && code_txt ? " " : "",
-						code_txt ? code_txt : "");
-
-			g_free(code_txt);
-			g_free(text);
-		} else if (xmlns == NULL) {
-			/* QuLogic: Not certain this is correct, but it would have happened
-			   with the previous code. */
-			if(purple_strequal(child->name, "x"))
-				jm->etc = g_list_append(jm->etc, child);
-			/* The following tests expect xmlns != NULL */
-			continue;
-		} else if(purple_strequal(child->name, "subject") && purple_strequal(xmlns, NS_XMPP_CLIENT)) {
-			if(!jm->subject) {
-				jm->subject = purple_xmlnode_get_data(child);
-				if(!jm->subject)
-					jm->subject = g_strdup("");
-			}
-		} else if(purple_strequal(child->name, "thread") && purple_strequal(xmlns, NS_XMPP_CLIENT)) {
-			if(!jm->thread_id)
-				jm->thread_id = purple_xmlnode_get_data(child);
-		} else if(purple_strequal(child->name, "body") && purple_strequal(xmlns, NS_XMPP_CLIENT)) {
-			if(!jm->body) {
-				char *msg = purple_xmlnode_get_data(child);
-				char *escaped = g_markup_escape_text(msg, -1);
-				jm->body = purple_strdup_withhtml(escaped);
-				g_free(escaped);
-				g_free(msg);
-			}
-		} else if(purple_strequal(child->name, "html") && purple_strequal(xmlns, NS_XHTML_IM)) {
-			if(!jm->xhtml && purple_xmlnode_get_child(child, "body")) {
-				char *c;
-				gchar *reformatted_xhtml;
-
-				purple_xmlnode_strip_prefixes(child);
-
-				/* reformat xhtml so that img tags with a "cid:" src gets
-				  translated to the bare text of the emoticon (the "alt" attrib) */
-				/* this is done also when custom smiley retrieval is turned off,
-				  this way the receiver always sees the shortcut instead */
-				reformatted_xhtml =
-					jabber_message_xml_to_string_strip_img_smileys(child);
-
-				jm->xhtml = reformatted_xhtml;
-
-			    /* Convert all newlines to whitespace. Technically, even regular, non-XML HTML is supposed to ignore newlines, but Pidgin has, as convention
-				 * treated \n as a newline for compatibility with other protocols
-				 */
-				for (c = jm->xhtml; *c != '\0'; c++) {
-					if (*c == '\n')
-						*c = ' ';
-				}
-			}
-		} else if(purple_strequal(child->name, "active") && purple_strequal(xmlns,"http://jabber.org/protocol/chatstates")) {
-			jm->chat_state = JM_STATE_ACTIVE;
-		} else if(purple_strequal(child->name, "composing") && purple_strequal(xmlns,"http://jabber.org/protocol/chatstates")) {
-			jm->chat_state = JM_STATE_COMPOSING;
-		} else if(purple_strequal(child->name, "paused") && purple_strequal(xmlns,"http://jabber.org/protocol/chatstates")) {
-			jm->chat_state = JM_STATE_PAUSED;
-		} else if(purple_strequal(child->name, "inactive") && purple_strequal(xmlns,"http://jabber.org/protocol/chatstates")) {
-			jm->chat_state = JM_STATE_INACTIVE;
-		} else if(purple_strequal(child->name, "gone") && purple_strequal(xmlns,"http://jabber.org/protocol/chatstates")) {
-			jm->chat_state = JM_STATE_GONE;
-		} else if(purple_strequal(child->name, "event") && purple_strequal(xmlns,"http://jabber.org/protocol/pubsub#event")) {
-			PurpleXmlNode *items;
-			jm->type = JABBER_MESSAGE_EVENT;
-			for(items = purple_xmlnode_get_child(child,"items"); items; items = items->next)
-				jm->eventitems = g_list_append(jm->eventitems, items);
-		} else if(purple_strequal(child->name, "delay") && purple_strequal(xmlns, NS_DELAYED_DELIVERY)) {
-			const char *stamp = purple_xmlnode_get_attrib(child, "stamp");
-			if(stamp != NULL) {
-				GDateTime *delayed_ts = NULL;
-				GTimeZone *tz = g_time_zone_new_utc();
-
-				delayed_ts = g_date_time_new_from_iso8601(stamp, tz);
-				g_time_zone_unref(tz);
-
-				if(delayed_ts != NULL) {
-					jm->delayed = TRUE;
-					g_date_time_unref(jm->sent);
-					jm->sent = delayed_ts;
-				}
-			}
-		} else if(purple_strequal(child->name, "x")) {
-			if(purple_strequal(xmlns, NS_DELAYED_DELIVERY_LEGACY)) {
-				const char *stamp = purple_xmlnode_get_attrib(child, "stamp");
-
-				if(stamp != NULL) {
-					GDateTime *delayed_ts = NULL;
-					GTimeZone *tz = g_time_zone_new_utc();
-
-					delayed_ts = g_date_time_new_from_iso8601(stamp, tz);
-					g_time_zone_unref(tz);
-
-					if(delayed_ts != NULL) {
-						jm->delayed = TRUE;
-						g_date_time_unref(jm->sent);
-						jm->sent = delayed_ts;
-					}
-				}
-			} else if(purple_strequal(xmlns, "jabber:x:conference") &&
-					jm->type != JABBER_MESSAGE_GROUPCHAT_INVITE &&
-					jm->type != JABBER_MESSAGE_ERROR) {
-				const char *jid = purple_xmlnode_get_attrib(child, "jid");
-				if(jid) {
-					const char *reason = purple_xmlnode_get_attrib(child, "reason");
-					const char *password = purple_xmlnode_get_attrib(child, "password");
-
-					jm->type = JABBER_MESSAGE_GROUPCHAT_INVITE;
-					g_free(jm->to);
-					jm->to = g_strdup(jid);
-
-					if (reason) {
-						g_free(jm->body);
-						jm->body = g_strdup(reason);
-					}
-
-					if (password) {
-						g_free(jm->password);
-						jm->password = g_strdup(password);
-					}
-				}
-			} else if(purple_strequal(xmlns, "http://jabber.org/protocol/muc#user") &&
-					jm->type != JABBER_MESSAGE_ERROR) {
-				PurpleXmlNode *invite = purple_xmlnode_get_child(child, "invite");
-				if(invite) {
-					PurpleXmlNode *reason, *password;
-					const char *jid = purple_xmlnode_get_attrib(invite, "from");
-					g_free(jm->to);
-					jm->to = jm->from;
-					jm->from = g_strdup(jid);
-					if((reason = purple_xmlnode_get_child(invite, "reason"))) {
-						g_free(jm->body);
-						jm->body = purple_xmlnode_get_data(reason);
-					}
-					if((password = purple_xmlnode_get_child(child, "password"))) {
-						g_free(jm->password);
-						jm->password = purple_xmlnode_get_data(password);
-					}
-
-					jm->type = JABBER_MESSAGE_GROUPCHAT_INVITE;
-				}
-			} else {
-				jm->etc = g_list_append(jm->etc, child);
-			}
-		} else if (purple_strequal(child->name, "query")) {
-			const char *node = purple_xmlnode_get_attrib(child, "node");
-			if (purple_strequal(xmlns, NS_DISCO_ITEMS)
-					&& purple_strequal(node, "http://jabber.org/protocol/commands")) {
-				jabber_adhoc_got_list(js, jm->from, child);
-			}
-		}
-	}
-
-	switch(jm->type) {
-		case JABBER_MESSAGE_OTHER:
-			purple_debug_info("jabber",
-					"Received message of unknown type: %s\n", type);
-			G_GNUC_FALLTHROUGH;
-		case JABBER_MESSAGE_NORMAL:
-		case JABBER_MESSAGE_CHAT:
-			handle_chat(jm);
-			break;
-		case JABBER_MESSAGE_HEADLINE:
-			handle_headline(jm);
-			break;
-		case JABBER_MESSAGE_GROUPCHAT:
-			handle_groupchat(jm);
-			break;
-		case JABBER_MESSAGE_GROUPCHAT_INVITE:
-			handle_groupchat_invite(jm);
-			break;
-		case JABBER_MESSAGE_EVENT:
-			jabber_handle_event(jm);
-			break;
-		case JABBER_MESSAGE_ERROR:
-			handle_error(jm);
-			break;
-	}
-	jabber_message_free(jm);
-}
-
-void jabber_message_send(JabberMessage *jm)
-{
-	PurpleXmlNode *message, *child;
-	const char *type = NULL;
-
-	message = purple_xmlnode_new("message");
-
-	switch(jm->type) {
-		case JABBER_MESSAGE_NORMAL:
-			type = "normal";
-			break;
-		case JABBER_MESSAGE_CHAT:
-		case JABBER_MESSAGE_GROUPCHAT_INVITE:
-			type = "chat";
-			break;
-		case JABBER_MESSAGE_HEADLINE:
-			type = "headline";
-			break;
-		case JABBER_MESSAGE_GROUPCHAT:
-			type = "groupchat";
-			break;
-		case JABBER_MESSAGE_ERROR:
-			type = "error";
-			break;
-		case JABBER_MESSAGE_OTHER:
-		default:
-			type = NULL;
-			break;
-	}
-
-	if(type)
-		purple_xmlnode_set_attrib(message, "type", type);
-
-	if (jm->id)
-		purple_xmlnode_set_attrib(message, "id", jm->id);
-
-	purple_xmlnode_set_attrib(message, "to", jm->to);
-
-	if(jm->thread_id) {
-		child = purple_xmlnode_new_child(message, "thread");
-		purple_xmlnode_insert_data(child, jm->thread_id, -1);
-	}
-
-	child = NULL;
-	switch(jm->chat_state)
-	{
-		case JM_STATE_ACTIVE:
-			child = purple_xmlnode_new_child(message, "active");
-			break;
-		case JM_STATE_COMPOSING:
-			child = purple_xmlnode_new_child(message, "composing");
-			break;
-		case JM_STATE_PAUSED:
-			child = purple_xmlnode_new_child(message, "paused");
-			break;
-		case JM_STATE_INACTIVE:
-			child = purple_xmlnode_new_child(message, "inactive");
-			break;
-		case JM_STATE_GONE:
-			child = purple_xmlnode_new_child(message, "gone");
-			break;
-		case JM_STATE_NONE:
-			/* yep, nothing */
-			break;
-	}
-	if(child)
-		purple_xmlnode_set_namespace(child, "http://jabber.org/protocol/chatstates");
-
-	if(jm->subject) {
-		child = purple_xmlnode_new_child(message, "subject");
-		purple_xmlnode_insert_data(child, jm->subject, -1);
-	}
-
-	if(jm->body) {
-		child = purple_xmlnode_new_child(message, "body");
-		purple_xmlnode_insert_data(child, jm->body, -1);
-	}
-
-	if(jm->xhtml) {
-		if ((child = purple_xmlnode_from_str(jm->xhtml, -1))) {
-			purple_xmlnode_insert_child(message, child);
-		} else {
-			purple_debug_error("jabber",
-					"XHTML translation/validation failed, returning: %s\n",
-					jm->xhtml);
-		}
-	}
-
-	jabber_send(jm->js, message);
-
-	purple_xmlnode_free(message);
-}
-
-/*
- * Compare the XHTML and plain strings passed in for "equality". Any HTML markup
- * other than <br/> (matches a newline) in the XHTML will cause this to return
- * FALSE.
- */
-static gboolean
-jabber_xhtml_plain_equal(const char *xhtml_escaped, const char *plain)
-{
-	int i = 0;
-	int j = 0;
-	gboolean ret;
-	char *xhtml = purple_unescape_html(xhtml_escaped);
-
-	while (xhtml[i] && plain[j]) {
-		if (xhtml[i] == plain[j]) {
-			i += 1;
-			j += 1;
-			continue;
-		}
-
-		if (plain[j] == '\n' && !strncmp(xhtml+i, "<br/>", 5)) {
-			i += 5;
-			j += 1;
-			continue;
-		}
-
-		g_free(xhtml);
-		return FALSE;
-	}
-
-	/* Are we at the end of both strings? */
-	ret = (xhtml[i] == plain[j]) && (xhtml[i] == '\0');
-	g_free(xhtml);
-	return ret;
-}
-
-int
-jabber_message_send_im(G_GNUC_UNUSED PurpleProtocolIM *pim,
-                       PurpleConnection *gc,
-                       G_GNUC_UNUSED PurpleConversation *conversation,
-                       PurpleMessage *msg)
-{
-	JabberMessage *jm;
-	JabberBuddy *jb;
-	JabberBuddyResource *jbr;
-	char *xhtml;
-	char *tmp;
-	char *resource;
-	const gchar *rcpt = purple_message_get_recipient(msg);
-
-	if (!rcpt || purple_message_is_empty(msg))
-		return 0;
-
-	resource = jabber_get_resource(rcpt);
-
-	jb = jabber_buddy_find(purple_connection_get_protocol_data(gc), rcpt, TRUE);
-	jbr = jabber_buddy_find_resource(jb, resource);
-
-	g_free(resource);
-
-	jm = g_new0(JabberMessage, 1);
-	jm->js = purple_connection_get_protocol_data(gc);
-	jm->type = JABBER_MESSAGE_CHAT;
-	jm->chat_state = JM_STATE_ACTIVE;
-	jm->to = g_strdup(rcpt);
-	jm->id = jabber_get_next_id(jm->js);
-
-	if(jbr) {
-		if(jbr->thread_id)
-			jm->thread_id = jbr->thread_id;
-
-		if (jbr->chat_states == JABBER_CHAT_STATES_UNSUPPORTED)
-			jm->chat_state = JM_STATE_NONE;
-		else {
-			/* if(JABBER_CHAT_STATES_UNKNOWN == jbr->chat_states)
-			   jbr->chat_states = JABBER_CHAT_STATES_UNSUPPORTED; */
-		}
-	}
-
-	tmp = purple_utf8_strip_unprintables(purple_message_get_contents(msg));
-	purple_markup_html_to_xhtml(tmp, &xhtml, &jm->body);
-	g_free(tmp);
-
-	/*
-	 * For backward compatibility with user expectations or for those not on
-	 * the user's roster, allow sending XHTML-IM markup.
-	 */
-	if (jbr == NULL || jbr->caps == NULL ||
-			jabber_resource_has_capability(jbr, NS_XHTML_IM)) {
-		if (!jabber_xhtml_plain_equal(xhtml, jm->body))
-			/* Wrap the message in <p/> for great interoperability justice. */
-			jm->xhtml = g_strdup_printf("<html xmlns='" NS_XHTML_IM "'><body xmlns='" NS_XHTML "'><p>%s</p></body></html>", xhtml);
-	}
-
-	g_free(xhtml);
-
-	jabber_message_send(jm);
-	jabber_message_free(jm);
-	return 1;
-}
-
-gint
-jabber_message_send_chat(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
-                         PurpleConnection *gc, gint id,
-                         G_GNUC_UNUSED PurpleConversation *conversation,
-                         PurpleMessage *msg)
-{
-	JabberChat *chat;
-	JabberMessage *jm;
-	JabberStream *js;
-	char *xhtml;
-	char *tmp;
-
-	if (!gc || purple_message_is_empty(msg))
-		return 0;
-
-	js = purple_connection_get_protocol_data(gc);
-	chat = jabber_chat_find_by_id(js, id);
-
-	if(!chat)
-		return 0;
-
-	jm = g_new0(JabberMessage, 1);
-	jm->js = purple_connection_get_protocol_data(gc);
-	jm->type = JABBER_MESSAGE_GROUPCHAT;
-	jm->to = g_strdup_printf("%s@%s", chat->room, chat->server);
-	jm->id = jabber_get_next_id(jm->js);
-
-	tmp = purple_utf8_strip_unprintables(purple_message_get_contents(msg));
-	purple_markup_html_to_xhtml(tmp, &xhtml, &jm->body);
-	g_free(tmp);
-
-	if (chat->xhtml && !jabber_xhtml_plain_equal(xhtml, jm->body))
-		/* Wrap the message in <p/> for greater interoperability justice. */
-		jm->xhtml = g_strdup_printf("<html xmlns='" NS_XHTML_IM "'><body xmlns='" NS_XHTML "'><p>%s</p></body></html>", xhtml);
-
-	g_free(xhtml);
-
-	jabber_message_send(jm);
-	jabber_message_free(jm);
-
-	return 1;
-}
-
-unsigned int
-jabber_send_typing(G_GNUC_UNUSED PurpleProtocolIM *pim, PurpleConnection *gc,
-                   const char *who, PurpleIMTypingState state)
-{
-	JabberStream *js;
-	JabberMessage *jm;
-	JabberBuddy *jb;
-	JabberBuddyResource *jbr;
-	char *resource;
-
-	js = purple_connection_get_protocol_data(gc);
-	jb = jabber_buddy_find(js, who, TRUE);
-	if (!jb)
-		return 0;
-
-	resource = jabber_get_resource(who);
-	jbr = jabber_buddy_find_resource(jb, resource);
-	g_free(resource);
-
-	/* We know this entity doesn't support chat states */
-	if (jbr && jbr->chat_states == JABBER_CHAT_STATES_UNSUPPORTED)
-		return 0;
-
-	/* *If* we don't have presence /and/ the buddy can't see our
-	 * presence, don't send typing notifications.
-	 */
-	if (!jbr && !(jb->subscription & JABBER_SUB_FROM))
-		return 0;
-
-	/* TODO: figure out threading */
-	jm = g_new0(JabberMessage, 1);
-	jm->js = js;
-	jm->type = JABBER_MESSAGE_CHAT;
-	jm->to = g_strdup(who);
-	jm->id = jabber_get_next_id(jm->js);
-
-	if(PURPLE_IM_TYPING == state)
-		jm->chat_state = JM_STATE_COMPOSING;
-	else if(PURPLE_IM_TYPED == state)
-		jm->chat_state = JM_STATE_PAUSED;
-	else
-		jm->chat_state = JM_STATE_ACTIVE;
-
-	/* if(JABBER_CHAT_STATES_UNKNOWN == jbr->chat_states)
-		jbr->chat_states = JABBER_CHAT_STATES_UNSUPPORTED; */
-
-	jabber_message_send(jm);
-	jabber_message_free(jm);
-
-	return 0;
-}
diff --git a/libpurple/protocols/jabber/namespaces.h b/libpurple/protocols/jabber/namespaces.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/namespaces.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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_JABBER_NAMESPACES_H
-#define PURPLE_JABBER_NAMESPACES_H
-
-#define NS_XMPP_BIND "urn:ietf:params:xml:ns:xmpp-bind"
-#define NS_XMPP_CLIENT "jabber:client"
-#define NS_XMPP_SASL "urn:ietf:params:xml:ns:xmpp-sasl"
-#define NS_XMPP_SESSION "urn:ietf:params:xml:ns:xmpp-session"
-#define NS_XMPP_STANZAS "urn:ietf:params:xml:ns:xmpp-stanzas"
-#define NS_XMPP_STREAMS "http://etherx.jabber.org/streams"
-#define NS_XMPP_TLS "urn:ietf:params:xml:ns:xmpp-tls"
-
-/* XEP-0012 Last Activity (and XEP-0256 Last Activity in Presence) */
-#define NS_LAST_ACTIVITY "jabber:iq:last"
-
-/* XEP-0030 Service Discovery */
-#define NS_DISCO_INFO "http://jabber.org/protocol/disco#info"
-#define NS_DISCO_ITEMS "http://jabber.org/protocol/disco#items"
-
-/* XEP-0047 IBB (In-band bytestreams) */
-#define NS_IBB "http://jabber.org/protocol/ibb"
-
-/* XEP-0065 SOCKS5 Bytestreams */
-#define NS_BYTESTREAMS "http://jabber.org/protocol/bytestreams"
-
-/* XEP-0066 Out of Band Data (OOB) */
-#define NS_OOB_IQ_DATA "jabber:iq:oob"
-#define NS_OOB_X_DATA  "jabber:x:oob"
-
-/* XEP-0071 XHTML-IM (rich-text messages) */
-#define NS_XHTML_IM "http://jabber.org/protocol/xhtml-im"
-#define NS_XHTML "http://www.w3.org/1999/xhtml"
-
-/* XEP-0084 v1.1 User Avatar */
-#define NS_AVATAR_1_1_DATA      "urn:xmpp:avatar:data"
-#define NS_AVATAR_1_1_METADATA  "urn:xmpp:avatar:metadata"
-
-/* XEP-0096 SI File Transfer */
-#define NS_SI_FILE_TRANSFER 	"http://jabber.org/protocol/si/profile/file-transfer"
-
-/* XEP-0124 Bidirectional-streams Over Synchronous HTTP (BOSH) */
-#define NS_BOSH "http://jabber.org/protocol/httpbind"
-
-/* XEP-0191 Simple Communications Blocking */
-#define NS_SIMPLE_BLOCKING "urn:xmpp:blocking"
-
-/* XEP-0199 Ping */
-#define NS_PING "urn:xmpp:ping"
-
-/* XEP-0202 Entity Time */
-#define NS_ENTITY_TIME "urn:xmpp:time"
-
-/* XEP-0203 Delayed Delivery (and legacy delayed delivery) */
-#define NS_DELAYED_DELIVERY "urn:xmpp:delay"
-#define NS_DELAYED_DELIVERY_LEGACY "jabber:x:delay"
-
-/* XEP-0206 XMPP over BOSH */
-#define NS_XMPP_BOSH "urn:xmpp:xbosh"
-
-/* XEP-0231 BoB (Bits of Binary) */
-#define NS_BOB "urn:xmpp:bob"
-
-/* XEP-0233 XMPP Server Registration for use with Kerberos V5 */
-#define NS_XMPP_SERVER_REGISTRATION "urn:xmpp:domain-based-name:1"
-
-/* XEP-0237 Roster Versioning */
-#define NS_ROSTER_VERSIONING "urn:xmpp:features:rosterver"
-
-/* XEP-0264 File Transfer Thumbnails (Thumbs) */
-#define NS_THUMBS "urn:xmpp:thumbs:0"
-
-/* XEP-0280 Message Carbons */
-#define NS_MESSAGE_CARBONS "urn:xmpp:carbons:2"
-
-/* XEP-0297 Stanza Forwarding */
-#define NS_FORWARD "urn:xmpp:forward:0"
-
-#endif /* PURPLE_JABBER_NAMESPACES_H */
diff --git a/libpurple/protocols/jabber/oob.h b/libpurple/protocols/jabber/oob.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/oob.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * @file oob.h out-of-band 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 PURPLE_JABBER_OOB_H
-#define PURPLE_JABBER_OOB_H
-
-#include "jabber.h"
-
-G_BEGIN_DECLS
-
-#define JABBER_TYPE_OOB_XFER (jabber_oob_xfer_get_type())
-G_DECLARE_FINAL_TYPE(JabberOOBXfer, jabber_oob_xfer, JABBER, OOB_XFER, PurpleXfer);
-
-void jabber_oob_parse(JabberStream *js, const char *from, JabberIqType type,
-                      const char *id, PurpleXmlNode *querynode);
-
-void jabber_oob_xfer_register(GTypeModule *module);
-
-G_END_DECLS
-
-#endif /* PURPLE_JABBER_OOB_H */
diff --git a/libpurple/protocols/jabber/oob.c b/libpurple/protocols/jabber/oob.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/oob.c
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <purple.h>
-
-#include "jabber.h"
-#include "iq.h"
-#include "oob.h"
-
-/* Number of bytes to read asynchronously per chunk. */
-#define JABBER_OOB_READ_SIZE (1024*1024)
-
-struct _JabberOOBXfer {
-	JabberStream *js;
-	gchar *iq_id;
-	gchar *url;
-	GCancellable *cancellable;
-	SoupMessage *msg;
-};
-
-G_DEFINE_DYNAMIC_TYPE_EXTENDED(JabberOOBXfer, jabber_oob_xfer,
-                               PURPLE_TYPE_XFER, G_TYPE_FLAG_FINAL, {})
-
-static void jabber_oob_xfer_xfer_init(PurpleXfer *xfer)
-{
-	purple_xfer_start(xfer, -1, NULL, 0);
-}
-
-static void jabber_oob_xfer_end(PurpleXfer *xfer)
-{
-	JabberOOBXfer *jox = JABBER_OOB_XFER(xfer);
-	JabberIq *iq;
-
-	iq = jabber_iq_new(jox->js, JABBER_IQ_RESULT);
-	purple_xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
-	jabber_iq_set_id(iq, jox->iq_id);
-
-	jabber_iq_send(iq);
-}
-
-static void
-jabber_oob_xfer_got_content_length(SoupMessage *msg, gpointer user_data)
-{
-	PurpleXfer *xfer = user_data;
-	SoupMessageHeaders *headers;
-	goffset total;
-
-	headers = soup_message_get_response_headers(msg);
-	total = soup_message_headers_get_content_length(headers);
-
-	purple_xfer_set_size(xfer, total);
-}
-
-static void
-jabber_oob_xfer_writer(GObject *source, GAsyncResult *result, gpointer data) {
-	GInputStream *input = G_INPUT_STREAM(source);
-	PurpleXfer *xfer = data;
-	JabberOOBXfer *jox = JABBER_OOB_XFER(xfer);
-	GBytes *bytes = NULL;
-	GError *error = NULL;
-	gpointer buffer = NULL;
-	gsize size = 0;
-
-	bytes = g_input_stream_read_bytes_finish(input, result, &error);
-	if(bytes == NULL || error != NULL) {
-		purple_debug_error("jabber", "Error reading OOB data: %s",
-		                   error ? error->message : "unknown error");
-		purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE);
-		purple_xfer_end(xfer);
-		g_clear_pointer(&bytes, g_bytes_unref);
-		g_clear_object(&input);
-		g_clear_error(&error);
-		jox->msg = NULL;
-		return;
-	}
-
-	buffer = g_bytes_unref_to_data(bytes, &size);
-
-	/* We've reached the end of the file. */
-	if(size == 0) {
-		purple_xfer_set_completed(xfer, TRUE);
-		purple_xfer_end(xfer);
-		g_clear_object(&input);
-		jox->msg = NULL;
-		return;
-	}
-
-	if (!purple_xfer_write_file(xfer, buffer, size)) {
-		purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_LOCAL);
-		purple_xfer_end(xfer);
-		g_clear_object(&input);
-		jox->msg = NULL;
-		return;
-	}
-
-	/* Asynchronously read the next chunk of data. */
-	g_input_stream_read_bytes_async(input, JABBER_OOB_READ_SIZE,
-	                                G_PRIORITY_DEFAULT, jox->cancellable,
-	                                jabber_oob_xfer_writer, xfer);
-}
-
-static void
-jabber_oob_xfer_send_cb(GObject *source, GAsyncResult *result, gpointer data) {
-	PurpleXfer *xfer = data;
-	JabberOOBXfer *jox = JABBER_OOB_XFER(xfer);
-	GInputStream *input = NULL;
-	GError *error = NULL;
-
-	if(!SOUP_STATUS_IS_SUCCESSFUL(soup_message_get_status(jox->msg))) {
-		purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE);
-		purple_xfer_end(xfer);
-		jox->msg = NULL;
-		return;
-	}
-
-	input = soup_session_send_finish(SOUP_SESSION(source), result, &error);
-	if(input == NULL || error != NULL) {
-		purple_debug_error("jabber", "Error sending OOB request: %s",
-		                   error ? error->message : "unknown error");
-		purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE);
-		purple_xfer_end(xfer);
-		g_clear_object(&input);
-		g_clear_error(&error);
-		jox->msg = NULL;
-		return;
-	}
-
-	/* Asynchronously read an initial chunk of data. */
-	g_input_stream_read_bytes_async(input, JABBER_OOB_READ_SIZE,
-	                                G_PRIORITY_DEFAULT, jox->cancellable,
-	                                jabber_oob_xfer_writer, xfer);
-}
-
-static void jabber_oob_xfer_start(PurpleXfer *xfer)
-{
-	SoupMessage *msg;
-	JabberOOBXfer *jox = JABBER_OOB_XFER(xfer);
-
-	msg = soup_message_new("GET", jox->url);
-	soup_message_add_header_handler(
-	        msg, "got-headers", "Content-Length",
-	        G_CALLBACK(jabber_oob_xfer_got_content_length), xfer);
-	soup_session_send_async(jox->js->http_conns, msg, G_PRIORITY_DEFAULT,
-	                        jox->cancellable, jabber_oob_xfer_send_cb, xfer);
-}
-
-static void jabber_oob_xfer_recv_error(PurpleXfer *xfer, const char *code) {
-	JabberOOBXfer *jox = JABBER_OOB_XFER(xfer);
-	JabberIq *iq;
-	PurpleXmlNode *y, *z;
-
-	iq = jabber_iq_new(jox->js, JABBER_IQ_ERROR);
-	purple_xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
-	jabber_iq_set_id(iq, jox->iq_id);
-	y = purple_xmlnode_new_child(iq->node, "error");
-	purple_xmlnode_set_attrib(y, "code", code);
-	if(purple_strequal(code, "406")) {
-		z = purple_xmlnode_new_child(y, "not-acceptable");
-		purple_xmlnode_set_attrib(y, "type", "modify");
-		purple_xmlnode_set_namespace(z, NS_XMPP_STANZAS);
-	} else if(purple_strequal(code, "404")) {
-		z = purple_xmlnode_new_child(y, "not-found");
-		purple_xmlnode_set_attrib(y, "type", "cancel");
-		purple_xmlnode_set_namespace(z, NS_XMPP_STANZAS);
-	}
-	jabber_iq_send(iq);
-}
-
-static void jabber_oob_xfer_recv_denied(PurpleXfer *xfer) {
-	jabber_oob_xfer_recv_error(xfer, "406");
-}
-
-static void jabber_oob_xfer_recv_cancelled(PurpleXfer *xfer) {
-	JabberOOBXfer *jox = JABBER_OOB_XFER(xfer);
-
-	g_cancellable_cancel(jox->cancellable);
-
-	jabber_oob_xfer_recv_error(xfer, "404");
-}
-
-void jabber_oob_parse(JabberStream *js, const char *from, JabberIqType type,
-	const char *id, PurpleXmlNode *querynode) {
-	JabberOOBXfer *jox;
-	const gchar *filename, *slash;
-	gchar *url;
-	PurpleXmlNode *urlnode;
-
-	if(type != JABBER_IQ_SET)
-		return;
-
-	if(!from)
-		return;
-
-	if(!(urlnode = purple_xmlnode_get_child(querynode, "url")))
-		return;
-
-	url = purple_xmlnode_get_data(urlnode);
-	if (!url)
-		return;
-
-	jox = g_object_new(
-		JABBER_TYPE_OOB_XFER,
-		"account", purple_connection_get_account(js->gc),
-		"type", PURPLE_XFER_TYPE_RECEIVE,
-		"remote-user", from,
-		NULL
-	);
-
-	jox->iq_id = g_strdup(id);
-	jox->js = js;
-	jox->url = url;
-
-	slash = strrchr(url, '/');
-	if (slash == NULL) {
-		filename = url;
-	} else {
-		filename = slash + 1;
-	}
-
-	purple_xfer_set_filename(PURPLE_XFER(jox), filename);
-
-	js->oob_file_transfers = g_list_append(js->oob_file_transfers, jox);
-
-	purple_xfer_request(PURPLE_XFER(jox));
-}
-
-static void
-jabber_oob_xfer_init(JabberOOBXfer *xfer) {
-	xfer->cancellable = g_cancellable_new();
-}
-
-static void
-jabber_oob_xfer_finalize(GObject *obj) {
-	JabberOOBXfer *jox = JABBER_OOB_XFER(obj);
-
-	jox->js->oob_file_transfers = g_list_remove(jox->js->oob_file_transfers,
-			jox);
-
-	g_free(jox->iq_id);
-	g_free(jox->url);
-	if(jox->cancellable != NULL) {
-		g_cancellable_cancel(jox->cancellable);
-	}
-	g_clear_object(&jox->cancellable);
-
-	G_OBJECT_CLASS(jabber_oob_xfer_parent_class)->finalize(obj);
-}
-
-static void
-jabber_oob_xfer_class_finalize(G_GNUC_UNUSED JabberOOBXferClass *klass) {
-}
-
-static void
-jabber_oob_xfer_class_init(JabberOOBXferClass *klass) {
-	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
-	PurpleXferClass *xfer_class = PURPLE_XFER_CLASS(klass);
-
-	obj_class->finalize = jabber_oob_xfer_finalize;
-
-	xfer_class->init = jabber_oob_xfer_xfer_init;
-	xfer_class->end = jabber_oob_xfer_end;
-	xfer_class->request_denied = jabber_oob_xfer_recv_denied;
-	xfer_class->cancel_recv = jabber_oob_xfer_recv_cancelled;
-	xfer_class->start = jabber_oob_xfer_start;
-}
-
-void
-jabber_oob_xfer_register(GTypeModule *module) {
-	jabber_oob_xfer_register_type(module);
-}
diff --git a/libpurple/protocols/jabber/parser.h b/libpurple/protocols/jabber/parser.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/parser.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * @file parser.h XML parser 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 PURPLE_JABBER_PARSER_H
-#define PURPLE_JABBER_PARSER_H
-
-#include "jabber.h"
-
-void jabber_parser_setup(JabberStream *js);
-void jabber_parser_free(JabberStream *js);
-void jabber_parser_process(JabberStream *js, const char *buf, int len);
-
-#endif /* PURPLE_JABBER_PARSER_H */
diff --git a/libpurple/protocols/jabber/parser.c b/libpurple/protocols/jabber/parser.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/parser.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * purple - Jabber XML parser stuff
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <libxml/parser.h>
-
-#include <purple.h>
-
-#include "jabber.h"
-#include "parser.h"
-
-static void
-jabber_parser_element_start_libxml(void *user_data,
-                                   const xmlChar *element_name,
-                                   const xmlChar *prefix,
-                                   const xmlChar *namespace, int nb_namespaces,
-                                   const xmlChar **namespaces,
-                                   int nb_attributes,
-                                   G_GNUC_UNUSED int nb_defaulted,
-                                   const xmlChar **attributes)
-{
-	JabberStream *js = user_data;
-	PurpleXmlNode *node;
-	int i, j;
-
-	if(!element_name) {
-		return;
-	} else if (js->stream_id == NULL) {
-		/* Sanity checking! */
-		if (0 != xmlStrcmp(element_name, (xmlChar *) "stream") ||
-				0 != xmlStrcmp(namespace, (xmlChar *) NS_XMPP_STREAMS)) {
-			/* We were expecting a <stream:stream/> opening stanza, but
-			 * didn't get it. Bad!
-			 */
-			purple_debug_error("jabber", "Expecting stream header, got %s with "
-			                   "xmlns %s\n", element_name, namespace);
-			purple_connection_error(js->gc,
-					PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
-					_("XMPP stream header missing"));
-			return;
-		}
-
-		js->protocol_version.major = 0;
-		js->protocol_version.minor = 9;
-
-		for (i = 0; i < nb_attributes * 5; i += 5) {
-			int attrib_len = attributes[i+4] - attributes[i+3];
-			char *attrib = g_strndup((gchar *)attributes[i+3], attrib_len);
-
-			if(!xmlStrcmp(attributes[i], (xmlChar*) "version")) {
-				const char *dot = strchr(attrib, '.');
-
-				js->protocol_version.major = atoi(attrib);
-				js->protocol_version.minor = dot ? atoi(dot + 1) : 0;
-
-				if (js->protocol_version.major > 1) {
-					/* TODO: Send <unsupported-version/> error */
-					purple_connection_error(js->gc,
-							PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
-							_("XMPP Version Mismatch"));
-					g_free(attrib);
-					return;
-				}
-
-				if (js->protocol_version.major == 0 && js->protocol_version.minor != 9) {
-					purple_debug_warning("jabber", "Treating version %s as 0.9 for backward "
-					                     "compatibility\n", attrib);
-				}
-				g_free(attrib);
-			} else if(!xmlStrcmp(attributes[i], (xmlChar*) "id")) {
-				g_free(js->stream_id);
-				js->stream_id = attrib;
-			} else {
-				g_free(attrib);
-			}
-		}
-
-		if (js->stream_id == NULL) {
-			/* Let's make up a placeholder stream ID, which we need to do
-			 * because we flag on it being NULL as a special case in this
-			 * parsing code.
-			 */
-			js->stream_id = g_strdup("");
-			purple_debug_info("jabber", "Server failed to specify a stream "
-			                  "ID (underspecified in rfc3920, but intended "
-			                  "to be a MUST; digest legacy auth may fail.\n");
-		}
-	} else {
-
-		if(js->current)
-			node = purple_xmlnode_new_child(js->current, (const char*) element_name);
-		else
-			node = purple_xmlnode_new((const char*) element_name);
-		purple_xmlnode_set_namespace(node, (const char*) namespace);
-		purple_xmlnode_set_prefix(node, (const char *)prefix);
-
-		if (nb_namespaces != 0) {
-			node->namespace_map = g_hash_table_new_full(
-				g_str_hash, g_str_equal, g_free, g_free);
-
-			for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
-				const char *key = (const char *)namespaces[j];
-				const char *val = (const char *)namespaces[j + 1];
-				g_hash_table_insert(node->namespace_map,
-					g_strdup(key ? key : ""), g_strdup(val ? val : ""));
-			}
-		}
-		for(i=0; i < nb_attributes * 5; i+=5) {
-			const char *name = (const char *)attributes[i];
-			const char *prefix = (const char *)attributes[i+1];
-			const char *attrib_ns = (const char *)attributes[i+2];
-			char *txt;
-			int attrib_len = attributes[i+4] - attributes[i+3];
-			char *attrib = g_strndup((gchar *)attributes[i+3], attrib_len);
-
-			txt = attrib;
-			attrib = purple_unescape_text(txt);
-			g_free(txt);
-			purple_xmlnode_set_attrib_full(node, name, attrib_ns, prefix, attrib);
-			g_free(attrib);
-		}
-
-		js->current = node;
-	}
-}
-
-static void
-jabber_parser_element_end_libxml(void *user_data, const xmlChar *element_name,
-                                 G_GNUC_UNUSED const xmlChar *prefix,
-                                 G_GNUC_UNUSED const xmlChar *namespace)
-{
-	JabberStream *js = user_data;
-
-	if(!js->current)
-		return;
-
-	if(js->current->parent) {
-		if(!xmlStrcmp((xmlChar*) js->current->name, element_name))
-			js->current = js->current->parent;
-	} else {
-		PurpleXmlNode *packet = js->current;
-		js->current = NULL;
-		jabber_process_packet(js, &packet);
-		if (packet != NULL)
-			purple_xmlnode_free(packet);
-	}
-}
-
-static void
-jabber_parser_element_text_libxml(void *user_data, const xmlChar *text, int text_len)
-{
-	JabberStream *js = user_data;
-
-	if(!js->current)
-		return;
-
-	if(!text || !text_len)
-		return;
-
-	purple_xmlnode_insert_data(js->current, (const char*) text, text_len);
-}
-
-static void
-jabber_parser_structured_error_handler(void *user_data, const xmlError *error)
-{
-	JabberStream *js = user_data;
-
-	if (error->level == XML_ERR_WARNING
-			&& purple_strequal(error->message, "xmlns: URI vcard-temp is not absolute\n"))
-		/*
-		 * This message happens when parsing vcards, and is normal, so don't
-		 * bother logging it because people scare easily.
-		 */
-		return;
-
-	if (error->level == XML_ERR_FATAL && error->code == XML_ERR_DOCUMENT_END)
-		/*
-		 * This is probably more annoying than the vcard-temp error; it occurs
-		 * because we disconnect in most cases without waiting for the receiving
-		 * </stream:stream> (limitations of libpurple)
-		 */
-		return;
-
-	purple_debug_error("jabber", "XML parser error for JabberStream %p: "
-								 "Domain %i, code %i, level %i: %s",
-					   js,
-					   error->domain, error->code, error->level,
-					   (error->message ? error->message : "(null)\n"));
-}
-
-static xmlSAXHandler jabber_parser_libxml = {
-	NULL,									/*internalSubset*/
-	NULL,									/*isStandalone*/
-	NULL,									/*hasInternalSubset*/
-	NULL,									/*hasExternalSubset*/
-	NULL,									/*resolveEntity*/
-	NULL,									/*getEntity*/
-	NULL,									/*entityDecl*/
-	NULL,									/*notationDecl*/
-	NULL,									/*attributeDecl*/
-	NULL,									/*elementDecl*/
-	NULL,									/*unparsedEntityDecl*/
-	NULL,									/*setDocumentLocator*/
-	NULL,									/*startDocument*/
-	NULL,									/*endDocument*/
-	NULL,									/*startElement*/
-	NULL,									/*endElement*/
-	NULL,									/*reference*/
-	jabber_parser_element_text_libxml,		/*characters*/
-	NULL,									/*ignorableWhitespace*/
-	NULL,									/*processingInstruction*/
-	NULL,									/*comment*/
-	NULL,									/*warning*/
-	NULL,									/*error*/
-	NULL,									/*fatalError*/
-	NULL,									/*getParameterEntity*/
-	NULL,									/*cdataBlock*/
-	NULL,									/*externalSubset*/
-	XML_SAX2_MAGIC,							/*initialized*/
-	NULL,									/*_private*/
-	jabber_parser_element_start_libxml,		/*startElementNs*/
-	jabber_parser_element_end_libxml,		/*endElementNs*/
-	(xmlStructuredErrorFunc)jabber_parser_structured_error_handler	/*serror*/
-};
-
-void
-jabber_parser_setup(JabberStream *js)
-{
-	/* This seems backwards, but it makes sense. The libxml code creates
-	 * the parser context when you try to use it (this way, it can figure
-	 * out the encoding at creation time. So, setting up the parser is
-	 * just a matter of destroying any current parser. */
-	jabber_parser_free(js);
-}
-
-void jabber_parser_free(JabberStream *js) {
-	if (js->context) {
-		xmlParseChunk(js->context, NULL,0,1);
-		xmlFreeParserCtxt(js->context);
-		js->context = NULL;
-	}
-}
-
-void jabber_parser_process(JabberStream *js, const char *buf, int len)
-{
-	int ret;
-
-	if (js->context == NULL) {
-		/* libxml inconsistently starts parsing on creating the
-		 * parser, so do a ParseChunk right afterwards to force it. */
-		js->context = xmlCreatePushParserCtxt(&jabber_parser_libxml, js, buf, len, NULL);
-		xmlParseChunk(js->context, "", 0, 0);
-	} else if ((ret = xmlParseChunk(js->context, buf, len, 0)) != XML_ERR_OK) {
-		const xmlError *err = xmlCtxtGetLastError(js->context);
-		/*
-		 * libxml2 uses a global setting to determine whether or not to store
-		 * warnings.  Other libraries may set this, which causes err to be
-		 * NULL. See #8136 for details.
-		 */
-		xmlErrorLevel level = XML_ERR_WARNING;
-
-		if (err)
-			level = err->level;
-
-		switch (level) {
-			case XML_ERR_NONE:
-				purple_debug_info("jabber", "xmlParseChunk returned info %i\n", ret);
-				break;
-			case XML_ERR_WARNING:
-				purple_debug_warning("jabber", "xmlParseChunk returned warning %i\n", ret);
-				break;
-			case XML_ERR_ERROR:
-				purple_debug_error("jabber", "xmlParseChunk returned error %i\n", ret);
-				break;
-			case XML_ERR_FATAL:
-				purple_debug_error("jabber", "xmlParseChunk returned fatal %i\n", ret);
-				purple_connection_error (js->gc,
-				                                PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-				                                _("XML Parse error"));
-				break;
-		}
-	}
-
-	if (js->protocol_version.major == 0 && js->protocol_version.minor == 9 &&
-			!purple_connection_get_error_info(js->gc) &&
-			(js->state == JABBER_STREAM_INITIALIZING ||
-			 js->state == JABBER_STREAM_INITIALIZING_ENCRYPTION)) {
-		/*
-		 * Legacy servers don't advertise features, so if we've just gotten
-		 * the opening <stream:stream> and there was no version, we need to
-		 * immediately start legacy IQ auth.
-		 */
-		jabber_stream_set_state(js, JABBER_STREAM_AUTHENTICATING);
-		jabber_auth_start_old(js);
-	}
-}
-
diff --git a/libpurple/protocols/jabber/pep.h b/libpurple/protocols/jabber/pep.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/pep.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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_JABBER_PEP_H
-#define PURPLE_JABBER_PEP_H
-
-#include "jabber.h"
-#include "message.h"
-#include "buddy.h"
-
-void jabber_pep_init(void);
-void jabber_pep_uninit(void);
-
-void jabber_pep_add_action_entries(GSimpleActionGroup *group);
-void jabber_pep_append_menu(GMenu *menu);
-
-/*
- * Callback for receiving PEP events.
- *
- * @parameter js	The JabberStream this item was received on
- * @parameter items	The &lt;items/>-tag with the &lt;item/>-children
- */
-typedef void (JabberPEPHandler)(JabberStream *js, const char *from, PurpleXmlNode *items);
-
-/*
- * Registers a callback for PEP events. Also automatically announces this receiving capability via disco#info.
- * Don't forget to use jabber_add_feature when supporting the sending of PEP events of this type.
- *
- * @parameter xmlns			The namespace for this event
- * @parameter handlerfunc	The callback to be used when receiving an event with this namespace
- */
-void jabber_pep_register_handler(const char *xmlns, JabberPEPHandler handlerfunc);
-
-/*
- * Request a specific item from another PEP node.
- *
- * @parameter js	The JabberStream that should be used
- * @parameter to	The target PEP node
- * @parameter node	The node name of the item that is requested
- * @parameter id	The item id of the requested item (may be NULL)
- * @parameter cb	The callback to be used when this item is received
- *
- * The items element passed to the callback will be NULL if any error occurred (like a permission error, node doesn't exist etc.)
- */
-void jabber_pep_request_item(JabberStream *js, const char *to, const char *node, const char *id, JabberPEPHandler cb);
-
-/*
- * Default callback that can be used for namespaces which should only be enabled when PEP is supported
- *
- * @parameter js		The JabberStream struct for this connection
- * @parameter namespace The namespace that's queried, ignored.
- *
- * @returns TRUE when PEP is enabled, FALSE otherwise
- */
-gboolean jabber_pep_namespace_only_when_pep_enabled_cb(JabberStream *js, const gchar *namespace);
-
-void jabber_handle_event(JabberMessage *jm);
-
-/*
- * Publishes PEP item(s)
- *
- * @parameter js	The JabberStream associated with the connection this event should be published
- * @parameter publish	The publish node. This could be for example &lt;publish node='http://jabber.org/protocol/tune'/> with an &lt;item/> as subnode
- */
-void jabber_pep_publish(JabberStream *js, PurpleXmlNode *publish);
-
-#endif /* PURPLE_JABBER_PEP_H */
diff --git a/libpurple/protocols/jabber/pep.c b/libpurple/protocols/jabber/pep.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/pep.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <glib/gi18n-lib.h>
-
-#include "pep.h"
-#include "iq.h"
-#include <string.h>
-#include "useravatar.h"
-#include "usernick.h"
-
-static GHashTable *pep_handlers = NULL;
-
-void jabber_pep_init(void) {
-	if(!pep_handlers) {
-		pep_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
-
-		/* register PEP handlers */
-		jabber_avatar_init();
-		jabber_nick_init();
-	}
-}
-
-void jabber_pep_uninit(void) {
-	/* any PEP handlers that need to clean things up go here. The standard
-	 * cleanup of removing the handler and feature are handled here and by
-	 * jabber_features_destroy() in jabber.c
-	 */
-	g_clear_pointer(&pep_handlers, g_hash_table_destroy);
-}
-
-void
-jabber_pep_add_action_entries(GSimpleActionGroup *group) {
-	jabber_nick_add_action_entries(group);
-}
-
-void
-jabber_pep_append_menu(GMenu *menu) {
-	/* register the PEP-specific actions */
-	jabber_nick_append_menu(menu);
-}
-
-void jabber_pep_register_handler(const char *xmlns, JabberPEPHandler handlerfunc) {
-	gchar *notifyns = g_strdup_printf("%s+notify", xmlns);
-	jabber_add_feature(notifyns, NULL); /* receiving PEPs is always supported */
-	g_free(notifyns);
-	g_hash_table_replace(pep_handlers, g_strdup(xmlns), handlerfunc);
-}
-
-static void
-do_pep_iq_request_item_callback(JabberStream *js, const char *from,
-                                JabberIqType type,
-                                G_GNUC_UNUSED const char *id,
-                                PurpleXmlNode *packet, gpointer data)
-{
-	PurpleXmlNode *pubsub;
-	PurpleXmlNode *items = NULL;
-	JabberPEPHandler *cb = data;
-
-	if (type == JABBER_IQ_RESULT) {
-		pubsub = purple_xmlnode_get_child_with_namespace(packet, "pubsub", "http://jabber.org/protocol/pubsub");
-		if(pubsub)
-			items = purple_xmlnode_get_child(pubsub, "items");
-	}
-
-	cb(js, from, items);
-}
-
-void jabber_pep_request_item(JabberStream *js, const char *to, const char *node, const char *id, JabberPEPHandler cb) {
-	JabberIq *iq = jabber_iq_new(js, JABBER_IQ_GET);
-	PurpleXmlNode *pubsub, *items;
-
-	if (to)
-		purple_xmlnode_set_attrib(iq->node, "to", to);
-
-	pubsub = purple_xmlnode_new_child(iq->node,"pubsub");
-	purple_xmlnode_set_namespace(pubsub, "http://jabber.org/protocol/pubsub");
-
-	items = purple_xmlnode_new_child(pubsub, "items");
-	purple_xmlnode_set_attrib(items,"node",node);
-
-	if (id) {
-		PurpleXmlNode *item = purple_xmlnode_new_child(items, "item");
-		purple_xmlnode_set_attrib(item, "id", id);
-	} else
-		/* Most recent item */
-		purple_xmlnode_set_attrib(items, "max_items", "1");
-
-	jabber_iq_set_callback(iq,do_pep_iq_request_item_callback,(gpointer)cb);
-
-	jabber_iq_send(iq);
-}
-
-gboolean
-jabber_pep_namespace_only_when_pep_enabled_cb(JabberStream *js,
-                                              G_GNUC_UNUSED const char *namespace)
-{
-	return js->pep;
-}
-
-void jabber_handle_event(JabberMessage *jm) {
-	/* this may be called even when the own server doesn't support pep! */
-	JabberPEPHandler *jph;
-	GList *itemslist;
-	char *jid;
-
-	if (jm->type != JABBER_MESSAGE_EVENT)
-		return;
-
-	jid = jabber_get_bare_jid(jm->from);
-
-	for(itemslist = jm->eventitems; itemslist; itemslist = itemslist->next) {
-		PurpleXmlNode *items = (PurpleXmlNode*)itemslist->data;
-		const char *nodename = purple_xmlnode_get_attrib(items,"node");
-
-		if(nodename && (jph = g_hash_table_lookup(pep_handlers, nodename)))
-			jph(jm->js, jid, items);
-	}
-
-	/* discard items we don't have a handler for */
-	g_free(jid);
-}
-
-void jabber_pep_publish(JabberStream *js, PurpleXmlNode *publish) {
-	JabberIq *iq;
-	PurpleXmlNode *pubsub;
-
-	if(js->pep != TRUE) {
-		/* ignore when there's no PEP support on the server */
-		purple_xmlnode_free(publish);
-		return;
-	}
-
-	iq = jabber_iq_new(js, JABBER_IQ_SET);
-
-	pubsub = purple_xmlnode_new("pubsub");
-	purple_xmlnode_set_namespace(pubsub, "http://jabber.org/protocol/pubsub");
-
-	purple_xmlnode_insert_child(pubsub, publish);
-
-	purple_xmlnode_insert_child(iq->node, pubsub);
-
-	jabber_iq_send(iq);
-}
diff --git a/libpurple/protocols/jabber/ping.h b/libpurple/protocols/jabber/ping.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/ping.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * @file ping.h ping 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 PURPLE_JABBER_PING_H
-#define PURPLE_JABBER_PING_H
-
-#include <purple.h>
-
-#include "jabber.h"
-#include "iq.h"
-
-void jabber_ping_parse(JabberStream *js, const char *from,
-                       JabberIqType, const char *id, PurpleXmlNode *child);
-gboolean jabber_ping_jid(JabberStream *js, const char *jid);
-void jabber_keepalive_ping(JabberStream *js);
-
-#endif /* PURPLE_JABBER_PING_H */
diff --git a/libpurple/protocols/jabber/ping.c b/libpurple/protocols/jabber/ping.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/ping.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <purple.h>
-
-#include "jabber.h"
-#include "ping.h"
-#include "iq.h"
-
-static void
-jabber_keepalive_pong_cb(JabberStream *js, G_GNUC_UNUSED const char *from,
-                         G_GNUC_UNUSED JabberIqType type,
-                         G_GNUC_UNUSED const char *id,
-                         G_GNUC_UNUSED PurpleXmlNode *packet,
-                         G_GNUC_UNUSED gpointer data)
-{
-	g_clear_handle_id(&js->keepalive_timeout, g_source_remove);
-}
-
-void
-jabber_ping_parse(JabberStream *js, const char *from, JabberIqType type,
-                  const char *id, G_GNUC_UNUSED PurpleXmlNode *ping)
-{
-	if (type == JABBER_IQ_GET) {
-		JabberIq *iq = jabber_iq_new(js, JABBER_IQ_RESULT);
-
-		if (from)
-			purple_xmlnode_set_attrib(iq->node, "to", from);
-		purple_xmlnode_set_attrib(iq->node, "id", id);
-
-		jabber_iq_send(iq);
-	} else if (type == JABBER_IQ_SET) {
-		/* XXX: error */
-	}
-}
-
-static void
-jabber_ping_result_cb(G_GNUC_UNUSED JabberStream *js,
-                      G_GNUC_UNUSED const char *from, JabberIqType type,
-                      G_GNUC_UNUSED const char *id,
-                      G_GNUC_UNUSED PurpleXmlNode *packet,
-                      G_GNUC_UNUSED gpointer data)
-{
-	if (type == JABBER_IQ_RESULT)
-		purple_debug_info("jabber", "PONG!\n");
-	else
-		purple_debug_info("jabber", "ping not supported\n");
-}
-
-void jabber_keepalive_ping(JabberStream *js)
-{
-	JabberIq *iq;
-	PurpleXmlNode *ping;
-
-	iq = jabber_iq_new(js, JABBER_IQ_GET);
-	ping = purple_xmlnode_new_child(iq->node, "ping");
-	purple_xmlnode_set_namespace(ping, NS_PING);
-
-	jabber_iq_set_callback(iq, jabber_keepalive_pong_cb, NULL);
-	jabber_iq_send(iq);
-}
-
-gboolean jabber_ping_jid(JabberStream *js, const char *jid)
-{
-	JabberIq *iq;
-	PurpleXmlNode *ping;
-
-	iq = jabber_iq_new(js, JABBER_IQ_GET);
-	if (jid)
-		purple_xmlnode_set_attrib(iq->node, "to", jid);
-
-	ping = purple_xmlnode_new_child(iq->node, "ping");
-	purple_xmlnode_set_namespace(ping, NS_PING);
-
-	jabber_iq_set_callback(iq, jabber_ping_result_cb, NULL);
-	jabber_iq_send(iq);
-
-	return TRUE;
-}
diff --git a/libpurple/protocols/jabber/presence.h b/libpurple/protocols/jabber/presence.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/presence.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
- * @file presence.h Presence
- *
- * 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_JABBER_PRESENCE_H
-#define PURPLE_JABBER_PRESENCE_H
-
-typedef enum {
-	JABBER_PRESENCE_ERROR = -2,
-	JABBER_PRESENCE_PROBE = -1,
-	JABBER_PRESENCE_AVAILABLE,
-	JABBER_PRESENCE_UNAVAILABLE,
-	JABBER_PRESENCE_SUBSCRIBE,
-	JABBER_PRESENCE_SUBSCRIBED,
-	JABBER_PRESENCE_UNSUBSCRIBE,
-	JABBER_PRESENCE_UNSUBSCRIBED
-} JabberPresenceType;
-
-typedef struct _JabberPresenceChatInfo JabberPresenceChatInfo;
-typedef struct _JabberPresence JabberPresence;
-
-#include <purple.h>
-
-#include "buddy.h"
-#include "chat.h"
-#include "jabber.h"
-#include "jutil.h"
-
-struct _JabberPresenceChatInfo {
-	GSList *codes;
-	PurpleXmlNode *item;
-};
-
-struct _JabberPresence {
-	JabberPresenceType type;
-	JabberID *jid_from;
-	const char *from;
-	const char *to;
-	const char *id;
-
-	JabberBuddy *jb;
-	JabberChat *chat;
-	JabberPresenceChatInfo chat_info;
-	PurpleXmlNode *caps; /* TODO: Temporary, see presence.c:parse_caps */
-
-	JabberBuddyState state;
-	gchar *status;
-	int priority;
-
-	char *vcard_avatar_hash;
-	char *nickname;
-
-	gboolean delayed;
-	GDateTime *sent;
-	int idle;
-	gboolean adjust_idle_for_delay;
-};
-
-void jabber_presence_init(void);
-void jabber_presence_uninit(void);
-
-void jabber_set_status(PurpleProtocolServer *protocol_server, PurpleAccount *account, PurpleStatus *status);
-
-/**
- *	Send a full presence stanza.
- *
- *	@param js       A JabberStream object.
- *	@param force    Force sending the presence stanza, irrespective of whether
- *	                the contents seem to have changed.
- */
-void jabber_presence_send(JabberStream *js, gboolean force);
-
-PurpleXmlNode *jabber_presence_create_js(JabberStream *js, JabberBuddyState state, const char *msg, int priority);
-void jabber_presence_parse(JabberStream *js, PurpleXmlNode *packet);
-void jabber_presence_subscription_set(JabberStream *js, const char *who,
-		const char *type);
-void jabber_presence_fake_to_self(JabberStream *js, PurpleStatus *status);
-void purple_status_to_jabber(PurpleStatus *status, JabberBuddyState *state, char **msg, int *priority);
-
-#endif /* PURPLE_JABBER_PRESENCE_H */
diff --git a/libpurple/protocols/jabber/presence.c b/libpurple/protocols/jabber/presence.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/presence.c
+++ /dev/null
@@ -1,1248 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "buddy.h"
-#include "chat.h"
-#include "presence.h"
-#include "iq.h"
-#include "jutil.h"
-#include "adhoccommands.h"
-
-static GHashTable *presence_handlers = NULL;
-
-static const struct {
-	const char *name;
-	JabberPresenceType type;
-} jabber_presence_types[] = {
-	{ "error", JABBER_PRESENCE_ERROR },
-	{ "probe", JABBER_PRESENCE_PROBE },
-	{ "unavailable", JABBER_PRESENCE_UNAVAILABLE },
-	{ "subscribe", JABBER_PRESENCE_SUBSCRIBE },
-	{ "subscribed", JABBER_PRESENCE_SUBSCRIBED },
-	{ "unsubscribe", JABBER_PRESENCE_UNSUBSCRIBE },
-	{ "unsubscribed", JABBER_PRESENCE_UNSUBSCRIBED }
-	/* { NULL, JABBER_PRESENCE_AVAILABLE } the default */
-};
-
-typedef void (JabberPresenceHandler)(JabberStream *js,
-                                     JabberPresence *presence,
-                                     PurpleXmlNode *child);
-
-static JabberPresenceType
-str_to_presence_type(const char *type)
-{
-	gsize i;
-
-	if (type == NULL)
-		return JABBER_PRESENCE_AVAILABLE;
-
-	for (i = 0; i < G_N_ELEMENTS(jabber_presence_types); ++i)
-		if (purple_strequal(type, jabber_presence_types[i].name))
-			return jabber_presence_types[i].type;
-
-	purple_debug_warning("jabber", "Unknown presence type '%s'\n", type);
-	return JABBER_PRESENCE_AVAILABLE;
-}
-
-static void
-chats_send_presence_foreach(G_GNUC_UNUSED gpointer key, gpointer val,
-                            gpointer user_data)
-{
-	JabberChat *chat = val;
-	PurpleXmlNode *presence = user_data;
-	char *chat_full_jid;
-
-	if(!chat->conv || chat->left)
-		return;
-
-	chat_full_jid = g_strdup_printf("%s@%s/%s", chat->room, chat->server,
-			chat->handle);
-
-	purple_xmlnode_set_attrib(presence, "to", chat_full_jid);
-	jabber_send(chat->js, presence);
-	g_free(chat_full_jid);
-}
-
-void jabber_presence_fake_to_self(JabberStream *js, PurpleStatus *status)
-{
-	PurpleAccount *account;
-	PurplePresence *presence;
-	JabberBuddy *jb;
-	JabberBuddyResource *jbr;
-	const char *username;
-	JabberBuddyState state;
-	char *msg;
-	int priority;
-
-	g_return_if_fail(js->user != NULL);
-
-	account = purple_connection_get_account(js->gc);
-	username = purple_connection_get_display_name(js->gc);
-	presence = purple_account_get_presence(account);
-	if (status == NULL)
-		status = purple_presence_get_active_status(presence);
-	purple_status_to_jabber(status, &state, &msg, &priority);
-
-	jb = js->user_jb;
-
-	if (state == JABBER_BUDDY_STATE_UNAVAILABLE ||
-			state == JABBER_BUDDY_STATE_UNKNOWN) {
-		jabber_buddy_remove_resource(jb, js->user->resource);
-	} else {
-		jbr = jabber_buddy_track_resource(jb, js->user->resource, priority,
-				state, msg);
-
-		jbr->idle = 0;
-		if(purple_presence_is_idle(presence)) {
-			GDateTime *idle_since = purple_presence_get_idle_time(presence);
-
-			if(idle_since != NULL) {
-				jbr->idle = g_date_time_to_unix(idle_since);
-			}
-		}
-	}
-
-	/*
-	 * While we need to track the status of this resource, the core
-	 * only cares if we're on our own buddy list.
-	 */
-	if (purple_blist_find_buddy(account, username)) {
-		jbr = jabber_buddy_find_resource(jb, NULL);
-		if (jbr) {
-			purple_protocol_got_user_status(account, username,
-					jabber_buddy_state_get_status_id(jbr->state),
-					"priority", jbr->priority,
-					jbr->status ? "message" : NULL, jbr->status,
-					NULL);
-			purple_protocol_got_user_idle(account, username, jbr->idle, jbr->idle);
-		} else {
-			purple_protocol_got_user_status(account, username, "offline",
-					msg ? "message" : NULL, msg,
-					NULL);
-		}
-	}
-	g_free(msg);
-}
-
-void
-jabber_set_status(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
-                  PurpleAccount *account, PurpleStatus *status)
-{
-	PurpleConnection *gc;
-	JabberStream *js;
-
-	if (!purple_account_is_connected(account))
-		return;
-
-	if (purple_status_is_exclusive(status) && !purple_status_is_active(status)) {
-		/* An exclusive status can't be deactivated. You should just
-		 * activate some other exclusive status. */
-		return;
-	}
-
-	gc = purple_account_get_connection(account);
-	js = purple_connection_get_protocol_data(gc);
-
-	jabber_presence_send(js, FALSE);
-}
-
-void jabber_presence_send(JabberStream *js, gboolean force)
-{
-	PurpleAccount *account;
-	PurpleXmlNode *presence, *x, *photo;
-	char *stripped = NULL;
-	JabberBuddyState state;
-	int priority;
-	gboolean allowBuzz;
-	PurplePresence *p;
-	PurpleStatus *status;
-
-	account = purple_connection_get_account(js->gc);
-	p = purple_account_get_presence(account);
-	status = purple_presence_get_active_status(p);
-
-	/* we don't want to send presence before we've gotten our roster */
-	if (js->state != JABBER_STREAM_CONNECTED) {
-		purple_debug_misc("jabber", "attempt to send presence before roster retrieved\n");
-		return;
-	}
-
-	purple_status_to_jabber(status, &state, &stripped, &priority);
-
-	/* check for buzz support */
-	allowBuzz = purple_status_get_attr_boolean(status,"buzz");
-	/* changing the buzz state has to trigger a re-broadcasting of the presence for caps */
-
-	/* check if there are any differences to the <presence> and send them in that case */
-	if (force || allowBuzz != js->allowBuzz || js->old_state != state ||
-		!purple_strequal(js->old_msg, stripped) || js->old_priority != priority ||
-		!purple_strequal(js->old_avatarhash, js->avatar_hash) || js->old_idle != js->idle) {
-		/* Need to update allowBuzz before creating the presence (with caps) */
-		js->allowBuzz = allowBuzz;
-
-		presence = jabber_presence_create_js(js, state, stripped, priority);
-
-		/* Per XEP-0153 4.1, we must always send the <x> */
-		x = purple_xmlnode_new_child(presence, "x");
-		purple_xmlnode_set_namespace(x, "vcard-temp:x:update");
-		/*
-		 * FIXME: Per XEP-0153 4.3.2 bullet 2, we must not publish our
-		 * image hash if another resource has logged in and updated the
-		 * vcard avatar. Requires changes in jabber_presence_parse.
-		 */
-		if (js->vcard_fetched) {
-			/* Always publish a <photo>; it's empty if we have no image. */
-			photo = purple_xmlnode_new_child(x, "photo");
-			if (js->avatar_hash)
-				purple_xmlnode_insert_data(photo, js->avatar_hash, -1);
-		}
-
-		jabber_send(js, presence);
-
-		g_hash_table_foreach(js->chats, chats_send_presence_foreach, presence);
-		purple_xmlnode_free(presence);
-
-		/* update old values */
-
-		g_free(js->old_msg);
-		g_free(js->old_avatarhash);
-		js->old_msg = g_strdup(stripped);
-		js->old_avatarhash = g_strdup(js->avatar_hash);
-		js->old_state = state;
-		js->old_priority = priority;
-		js->old_idle = js->idle;
-	}
-	g_free(stripped);
-
-#undef CHANGED
-
-	jabber_presence_fake_to_self(js, status);
-}
-
-PurpleXmlNode *jabber_presence_create_js(JabberStream *js, JabberBuddyState state, const char *msg, int priority)
-{
-	PurpleXmlNode *show, *status, *presence, *pri, *c;
-	const char *show_string = NULL;
-
-	g_return_val_if_fail(js !=NULL, NULL);
-
-	presence = purple_xmlnode_new("presence");
-
-	if(state == JABBER_BUDDY_STATE_UNAVAILABLE)
-		purple_xmlnode_set_attrib(presence, "type", "unavailable");
-	else if(state != JABBER_BUDDY_STATE_ONLINE &&
-			state != JABBER_BUDDY_STATE_UNKNOWN &&
-			state != JABBER_BUDDY_STATE_ERROR)
-		show_string = jabber_buddy_state_get_show(state);
-
-	if(show_string) {
-		show = purple_xmlnode_new_child(presence, "show");
-		purple_xmlnode_insert_data(show, show_string, -1);
-	}
-
-	if(msg) {
-		status = purple_xmlnode_new_child(presence, "status");
-		purple_xmlnode_insert_data(status, msg, -1);
-	}
-
-	if(priority) {
-		char *pstr = g_strdup_printf("%d", priority);
-		pri = purple_xmlnode_new_child(presence, "priority");
-		purple_xmlnode_insert_data(pri, pstr, -1);
-		g_free(pstr);
-	}
-
-	/* if we are idle and not offline, include idle */
-	if (js->idle && state != JABBER_BUDDY_STATE_UNAVAILABLE) {
-		PurpleXmlNode *query = purple_xmlnode_new_child(presence, "query");
-		gchar seconds[10];
-		g_snprintf(seconds, 10, "%d", (int) (time(NULL) - js->idle));
-
-		purple_xmlnode_set_namespace(query, NS_LAST_ACTIVITY);
-		purple_xmlnode_set_attrib(query, "seconds", seconds);
-	}
-
-	/* JEP-0115 */
-	/* calculate hash */
-	jabber_caps_calculate_own_hash(js);
-	/* create xml */
-	c = purple_xmlnode_new_child(presence, "c");
-	purple_xmlnode_set_namespace(c, "http://jabber.org/protocol/caps");
-	purple_xmlnode_set_attrib(c, "node", CAPS0115_NODE);
-	purple_xmlnode_set_attrib(c, "hash", "sha-1");
-	purple_xmlnode_set_attrib(c, "ver", jabber_caps_get_own_hash(js));
-
-	return presence;
-}
-
-struct _jabber_add_permit {
-	PurpleConnection *gc;
-	JabberStream *js;
-	char *who;
-};
-
-static void
-authorize_add_cb(G_GNUC_UNUSED PurpleAuthorizationRequest *request,
-                 gpointer data)
-{
-	struct _jabber_add_permit *jap = data;
-
-	PURPLE_ASSERT_CONNECTION_IS_VALID(jap->gc);
-
-	jabber_presence_subscription_set(purple_connection_get_protocol_data(jap->gc),
-		jap->who, "subscribed");
-
-	g_free(jap->who);
-	g_free(jap);
-}
-
-static void
-deny_add_cb(G_GNUC_UNUSED PurpleAuthorizationRequest *request,
-            G_GNUC_UNUSED const char *message, gpointer data)
-{
-	struct _jabber_add_permit *jap = data;
-
-	PURPLE_ASSERT_CONNECTION_IS_VALID(jap->gc);
-
-	jabber_presence_subscription_set(purple_connection_get_protocol_data(jap->gc),
-		jap->who, "unsubscribed");
-
-	g_free(jap->who);
-	g_free(jap);
-}
-
-static void
-jabber_vcard_parse_avatar(JabberStream *js, const char *from,
-                          G_GNUC_UNUSED JabberIqType type,
-                          G_GNUC_UNUSED const char *id, PurpleXmlNode *packet,
-                          G_GNUC_UNUSED gpointer data)
-{
-	JabberBuddy *jb = NULL;
-	PurpleXmlNode *vcard, *photo, *binval, *fn, *nick;
-	char *text;
-
-	if(!from)
-		return;
-
-	jb = jabber_buddy_find(js, from, TRUE);
-
-	js->pending_avatar_requests = g_slist_remove(js->pending_avatar_requests, jb);
-
-	if((vcard = purple_xmlnode_get_child(packet, "vCard")) ||
-			(vcard = purple_xmlnode_get_child_with_namespace(packet, "query", "vcard-temp"))) {
-		/* The logic here regarding the nickname and full name is copied from
-		 * buddy.c:jabber_vcard_parse. */
-		gchar *nickname = NULL;
-		if ((fn = purple_xmlnode_get_child(vcard, "FN")))
-			nickname = purple_xmlnode_get_data(fn);
-
-		if ((nick = purple_xmlnode_get_child(vcard, "NICKNAME"))) {
-			char *tmp = purple_xmlnode_get_data(nick);
-			char *bare_jid = jabber_get_bare_jid(from);
-			if (tmp && strstr(bare_jid, tmp) == NULL) {
-				g_free(nickname);
-				nickname = tmp;
-			} else
-				g_free(tmp);
-
-			g_free(bare_jid);
-		}
-
-		if (nickname) {
-			purple_serv_got_alias(js->gc, from, nickname);
-			g_free(nickname);
-		}
-
-		if ((photo = purple_xmlnode_get_child(vcard, "PHOTO"))) {
-			guchar *data = NULL;
-			gchar *hash = NULL;
-			gsize size = 0;
-
-			if ((binval = purple_xmlnode_get_child(photo, "BINVAL")) &&
-					(text = purple_xmlnode_get_data(binval))) {
-				data = g_base64_decode(text, &size);
-				g_free(text);
-
-				if (data) {
-					hash = g_compute_checksum_for_data(G_CHECKSUM_SHA1, data,
-					                                   size);
-				}
-			}
-
-			purple_buddy_icons_set_for_user(purple_connection_get_account(js->gc), from, data, size, hash);
-
-			g_free(hash);
-		}
-	}
-}
-
-typedef struct {
-	JabberStream *js;
-	JabberBuddy *jb;
-	char *from;
-} JabberPresenceCapabilities;
-
-static void
-jabber_presence_set_capabilities(JabberCapsClientInfo *info,
-                                 JabberPresenceCapabilities *userdata)
-{
-	JabberBuddyResource *jbr;
-	char *resource = strchr(userdata->from, '/');
-
-	if (resource)
-		resource += 1;
-
-	jbr = jabber_buddy_find_resource(userdata->jb, resource);
-	if (!jbr) {
-		g_free(userdata->from);
-		g_free(userdata);
-		return;
-	}
-
-	jbr->caps = info;
-
-	purple_protocol_got_media_caps(
-			purple_connection_get_account(userdata->js->gc),
-			userdata->from);
-	if (info == NULL)
-		goto out;
-
-	if (!jbr->commands_fetched && jabber_resource_has_capability(jbr, "http://jabber.org/protocol/commands")) {
-		JabberIq *iq = jabber_iq_new_query(userdata->js, JABBER_IQ_GET, NS_DISCO_ITEMS);
-		PurpleXmlNode *query = purple_xmlnode_get_child_with_namespace(iq->node, "query", NS_DISCO_ITEMS);
-		purple_xmlnode_set_attrib(iq->node, "to", userdata->from);
-		purple_xmlnode_set_attrib(query, "node", "http://jabber.org/protocol/commands");
-		jabber_iq_set_callback(iq, jabber_adhoc_disco_result_cb, NULL);
-		jabber_iq_send(iq);
-
-		jbr->commands_fetched = TRUE;
-	}
-
-out:
-	g_free(userdata->from);
-	g_free(userdata);
-}
-
-static gboolean
-handle_presence_chat(JabberStream *js, JabberPresence *presence, PurpleXmlNode *packet)
-{
-	static int i = 1;
-	PurpleChatUserFlags flags = PURPLE_CHAT_USER_NONE;
-	JabberChat *chat = presence->chat;
-
-	if (presence->state == JABBER_BUDDY_STATE_ERROR) {
-		char *title, *msg = jabber_parse_error(js, packet, NULL);
-
-		if (!chat->conv) {
-			title = g_strdup_printf(_("Error joining chat %s"), presence->from);
-			purple_serv_got_join_chat_failed(js->gc, chat->components);
-		} else {
-			title = g_strdup_printf(_("Error in chat %s"), presence->from);
-			if (g_hash_table_size(chat->members) == 0)
-				purple_serv_got_chat_left(js->gc, chat->id);
-		}
-		purple_notify_error(js->gc, title, title, msg,
-			purple_request_cpar_from_connection(js->gc));
-		g_free(title);
-		g_free(msg);
-
-		if (g_hash_table_size(chat->members) == 0)
-			/* Only destroy the chat if the error happened while joining */
-			jabber_chat_destroy(chat);
-		return FALSE;
-	}
-
-	if (presence->type == JABBER_PRESENCE_AVAILABLE) {
-		const char *jid = NULL;
-		const char *affiliation = NULL;
-		const char *role = NULL;
-		gboolean is_our_resource = FALSE; /* Is the presence about us? */
-		JabberBuddyResource *jbr;
-
-		/*
-		 * XEP-0045 mandates the presence to include a resource (which is
-		 * treated as the chat nick). Some non-compliant servers allow
-		 * joining without a nick.
-		 */
-		if (!presence->jid_from->resource)
-			return FALSE;
-
-		if (presence->chat_info.item) {
-			jid = purple_xmlnode_get_attrib(presence->chat_info.item, "jid");
-			affiliation = purple_xmlnode_get_attrib(presence->chat_info.item, "affiliation");
-			role = purple_xmlnode_get_attrib(presence->chat_info.item, "role");
-		}
-
-		if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(110)) ||
-				purple_strequal(presence->jid_from->resource, chat->handle) ||
-				purple_strequal(presence->to, jid))
-			is_our_resource = TRUE;
-
-		if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(201))) {
-			chat->config_dialog_type = PURPLE_REQUEST_ACTION;
-			chat->config_dialog_handle =
-				purple_request_action(js->gc,
-						_("Create New Room"),
-						_("Create New Room"),
-						_("You are creating a new room.  Would"
-							" you like to configure it, or"
-							" accept the default settings?"),
-						/* Default Action */ 1,
-						purple_request_cpar_from_conversation(PURPLE_CONVERSATION(chat->conv)),
-						chat, 2,
-						_("_Configure Room"), G_CALLBACK(jabber_chat_request_room_configure),
-						_("_Accept Defaults"), G_CALLBACK(jabber_chat_create_instant_room));
-		}
-
-		if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(210))) {
-			/* server rewrote room-nick */
-			g_free(chat->handle);
-			chat->handle = g_strdup(presence->jid_from->resource);
-		}
-
-		if (purple_strequal(affiliation, "owner"))
-			flags |= PURPLE_CHAT_USER_FOUNDER;
-		if (role) {
-			if (purple_strequal(role, "moderator"))
-				flags |= PURPLE_CHAT_USER_OP;
-			else if (purple_strequal(role, "participant"))
-				flags |= PURPLE_CHAT_USER_VOICE;
-		}
-
-		if(!chat->conv) {
-			PurpleConversation *conv;
-			char *room_jid = g_strdup_printf("%s@%s", presence->jid_from->node, presence->jid_from->domain);
-			chat->id = i++;
-			conv = purple_serv_got_joined_chat(js->gc, chat->id, room_jid);
-			chat->conv = PURPLE_CHAT_CONVERSATION(conv);
-			purple_chat_conversation_set_nick(chat->conv, chat->handle);
-
-			jabber_chat_disco_traffic(chat);
-			g_free(room_jid);
-		}
-
-		jbr = jabber_buddy_track_resource(presence->jb, presence->jid_from->resource, presence->priority, presence->state, presence->status);
-		jbr->commands_fetched = TRUE;
-
-		jabber_chat_track_handle(chat, presence->jid_from->resource, jid, affiliation, role);
-
-		if(!jabber_chat_find_buddy(chat->conv, presence->jid_from->resource)) {
-			gboolean new_arrival = FALSE;
-
-			if(chat->joined != NULL) {
-				gint newer = -1;
-
-				if(presence->sent != NULL) {
-					newer = g_date_time_compare(presence->sent, chat->joined);
-				}
-
-				if(!presence->delayed || newer > 0) {
-					new_arrival = TRUE;
-				}
-			}
-
-			purple_chat_conversation_add_user(chat->conv,
-			                                  presence->jid_from->resource,
-			                                  jid, flags, new_arrival);
-		} else {
-			purple_chat_user_set_flags(purple_chat_conversation_find_user(chat->conv, presence->jid_from->resource),
-					flags);
-		}
-
-		if (is_our_resource && chat->joined == NULL) {
-			chat->joined = g_date_time_new_now_utc();
-		}
-
-	} else if (presence->type == JABBER_PRESENCE_UNAVAILABLE) {
-		gboolean nick_change = FALSE;
-		gboolean kick = FALSE;
-		gboolean is_our_resource = FALSE; /* Is the presence about us? */
-
-		const char *jid = NULL;
-
-		/* If the chat nick is invalid, we haven't yet joined, or we've
-		 * already left (it was probably us leaving after we closed the
-		 * chat), we don't care.
-		 */
-		if (!presence->jid_from->resource || !chat->conv || chat->left) {
-			if (chat->left &&
-					presence->jid_from->resource && chat->handle && purple_strequal(presence->jid_from->resource, chat->handle))
-				jabber_chat_destroy(chat);
-			return FALSE;
-		}
-
-		is_our_resource = purple_strequal(presence->jid_from->resource, chat->handle);
-
-		jabber_buddy_remove_resource(presence->jb, presence->jid_from->resource);
-
-		if (presence->chat_info.item)
-			jid = purple_xmlnode_get_attrib(presence->chat_info.item, "jid");
-
-		if (chat->muc) {
-			if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(110))) {
-				is_our_resource = TRUE;
-				chat->joined = 0;
-			}
-
-			if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(301))) {
-				/* XXX: We got banned.  YAY! (No GIR, that's bad) */
-			}
-
-
-			if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(303))) {
-				const char *nick = NULL;
-				if (presence->chat_info.item)
-					nick = purple_xmlnode_get_attrib(presence->chat_info.item, "nick");
-
-				/* nick change */
-				if (!nick) {
-					purple_debug_warning("jabber", "Chat presence indicating a nick change, but no new nickname!\n");
-				} else {
-					nick_change = TRUE;
-
-					if (purple_strequal(presence->jid_from->resource, chat->handle)) {
-						/* Changing our own nickname */
-						g_free(chat->handle);
-						/* TODO: This should be resourceprep'd */
-						chat->handle = g_strdup(nick);
-					}
-
-					purple_chat_conversation_rename_user(chat->conv,
-					                             presence->jid_from->resource,
-					                             nick);
-					jabber_chat_remove_handle(chat,
-					                          presence->jid_from->resource);
-				}
-			}
-
-			if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(307))) {
-				/* Someone was kicked from the room */
-				const char *actor = NULL;
-				char *reason = NULL;
-				char *tmp;
-
-				kick = TRUE;
-
-				if (presence->chat_info.item) {
-					PurpleXmlNode *node;
-
-					node = purple_xmlnode_get_child(presence->chat_info.item, "actor");
-					if (node)
-						actor = purple_xmlnode_get_attrib(node, "jid");
-					node = purple_xmlnode_get_child(presence->chat_info.item, "reason");
-					if (node)
-						reason = purple_xmlnode_get_data(node);
-				}
-
-				if (reason == NULL)
-					reason = g_strdup(_("No reason"));
-
-				if (is_our_resource) {
-					if (actor)
-						tmp = g_strdup_printf(_("You have been kicked by %s: (%s)"),
-								actor, reason);
-					else
-						tmp = g_strdup_printf(_("You have been kicked: (%s)"),
-								reason);
-				} else {
-					if (actor)
-						tmp = g_strdup_printf(_("Kicked by %s (%s)"),
-								actor, reason);
-					else
-						tmp = g_strdup_printf(_("Kicked (%s)"),
-								reason);
-				}
-
-				g_free(presence->status);
-				presence->status = tmp;
-
-				g_free(reason);
-			}
-
-			if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(321))) {
-				/* XXX: removed due to an affiliation change */
-			}
-
-			if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(322))) {
-				/* XXX: removed because room is now members-only */
-			}
-
-			if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(332))) {
-				/* XXX: removed due to system shutdown */
-			}
-		}
-
-		/*
-		 * Possibly another connected resource of our JID (see XEP-0045
-		 * v1.24 section 7.1.10) being disconnected. Should be
-		 * distinguished by the item_jid.
-		 * Also possibly works around bits of an Openfire bug. See
-		 * #8319.
-		 */
-		if (is_our_resource && jid && !purple_strequal(presence->to, jid)) {
-			/* TODO: When the above is a loop, this needs to still act
-			 * sanely for all cases (this code is a little fragile). */
-			if (!kick && !nick_change)
-				/* Presumably, kicks and nick changes also affect us. */
-				is_our_resource = FALSE;
-		}
-
-		if(!nick_change) {
-			if (is_our_resource) {
-				if (kick) {
-					gchar *msg = g_strdup_printf("%s: %s",
-						presence->jid_from->resource,
-						presence->status);
-					purple_conversation_write_system_message(PURPLE_CONVERSATION(chat->conv), msg, 0);
-				}
-
-				purple_serv_got_chat_left(js->gc, chat->id);
-				jabber_chat_destroy(chat);
-			} else {
-				purple_chat_conversation_remove_user(chat->conv, presence->jid_from->resource,
-						presence->status);
-				jabber_chat_remove_handle(chat, presence->jid_from->resource);
-			}
-		}
-	}
-
-	return TRUE;
-}
-
-static gboolean
-handle_presence_contact(JabberStream *js, JabberPresence *presence)
-{
-	JabberBuddyResource *jbr;
-	PurpleAccount *account;
-	PurpleBuddy *b;
-	char *buddy_name;
-	PurpleConversation *im;
-	PurpleConversationManager *manager;
-
-	buddy_name = jabber_id_get_bare_jid(presence->jid_from);
-
-	account = purple_connection_get_account(js->gc);
-	b = purple_blist_find_buddy(account, buddy_name);
-
-	manager = purple_conversation_manager_get_default();
-	/*
-	 * Unbind/unlock from sending messages to a specific resource on
-	 * presence changes.  This is locked to a specific resource when
-	 * receiving a message (in message.c).
-	 */
-	im = purple_conversation_manager_find_im(manager, account, buddy_name);
-	if (im) {
-		purple_debug_info("jabber", "Changed conversation binding from %s to %s",
-				purple_conversation_get_name(im), buddy_name);
-		purple_conversation_set_name(im, buddy_name);
-	}
-
-	if (b == NULL) {
-		if (presence->jb != js->user_jb) {
-			PurpleContactInfo *info = PURPLE_CONTACT_INFO(account);
-			purple_debug_warning("jabber",
-			                     "Got presence for unknown buddy %s on account %s (%p)",
-			                     buddy_name,
-			                     purple_contact_info_get_username(info),
-			                     account);
-			g_free(buddy_name);
-			return FALSE;
-		} else {
-			/* this is a different resource of our own account. Resume even when this account isn't on our blist */
-		}
-	}
-
-	if (b && presence->vcard_avatar_hash) {
-		const char *ah = presence->vcard_avatar_hash[0] != '\0' ?
-				presence->vcard_avatar_hash : NULL;
-		const char *ah2 = purple_buddy_icons_get_checksum_for_user(b);
-		if (!purple_strequal(ah, ah2)) {
-			/* XXX this is a crappy way of trying to prevent
-			 * someone from spamming us with presence packets
-			 * and causing us to DoS ourselves...what we really
-			 * need is a queue system that can throttle itself,
-			 * but i'm too tired to write that right now */
-			if(!g_slist_find(js->pending_avatar_requests, presence->jb)) {
-				JabberIq *iq;
-				PurpleXmlNode *vcard;
-
-				js->pending_avatar_requests =
-					g_slist_prepend(js->pending_avatar_requests, presence->jb);
-
-				iq = jabber_iq_new(js, JABBER_IQ_GET);
-				purple_xmlnode_set_attrib(iq->node, "to", buddy_name);
-				vcard = purple_xmlnode_new_child(iq->node, "vCard");
-				purple_xmlnode_set_namespace(vcard, "vcard-temp");
-
-				jabber_iq_set_callback(iq, jabber_vcard_parse_avatar, NULL);
-				jabber_iq_send(iq);
-			}
-		}
-	}
-
-	if (presence->state == JABBER_BUDDY_STATE_ERROR ||
-			presence->type == JABBER_PRESENCE_UNAVAILABLE ||
-			presence->type == JABBER_PRESENCE_UNSUBSCRIBED) {
-		jabber_buddy_remove_resource(presence->jb, presence->jid_from->resource);
-	} else {
-		jbr = jabber_buddy_track_resource(presence->jb,
-				presence->jid_from->resource, presence->priority,
-				presence->state, presence->status);
-		jbr->idle = presence->idle ? time(NULL) - presence->idle : 0;
-	}
-
-	jbr = jabber_buddy_find_resource(presence->jb, NULL);
-	if (jbr) {
-		purple_protocol_got_user_status(account, buddy_name,
-				jabber_buddy_state_get_status_id(jbr->state),
-				"priority", jbr->priority,
-				"message", jbr->status,
-				NULL);
-		purple_protocol_got_user_idle(account, buddy_name,
-				jbr->idle, jbr->idle);
-		if (presence->nickname)
-			purple_serv_got_alias(js->gc, buddy_name, presence->nickname);
-	} else {
-		purple_protocol_got_user_status(account, buddy_name,
-				jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_UNAVAILABLE),
-				presence->status ? "message" : NULL, presence->status,
-				NULL);
-	}
-	g_free(buddy_name);
-
-	return TRUE;
-}
-
-void jabber_presence_parse(JabberStream *js, PurpleXmlNode *packet)
-{
-	const char *type;
-	JabberBuddyResource *jbr = NULL;
-	gboolean signal_return, ret;
-	JabberPresence presence;
-	PurpleXmlNode *child;
-
-	memset(&presence, 0, sizeof(presence));
-	/* defaults */
-	presence.state = JABBER_BUDDY_STATE_UNKNOWN;
-	presence.sent = g_date_time_new_now_utc();
-	/* interesting values */
-	presence.from = purple_xmlnode_get_attrib(packet, "from");
-	presence.to   = purple_xmlnode_get_attrib(packet, "to");
-	type = purple_xmlnode_get_attrib(packet, "type");
-	presence.type = str_to_presence_type(type);
-
-	presence.jb = jabber_buddy_find(js, presence.from, TRUE);
-	g_return_if_fail(presence.jb != NULL);
-
-	presence.jid_from = jabber_id_new(presence.from);
-	if (presence.jid_from == NULL) {
-		purple_debug_error("jabber", "Ignoring presence with malformed 'from' "
-		                   "JID: %s\n", presence.from);
-		return;
-	}
-
-	signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_protocol(js->gc),
-			"jabber-receiving-presence", js->gc, type, presence.from, packet));
-	if (signal_return) {
-		goto out;
-	}
-
-	if (presence.jid_from->node)
-		presence.chat = jabber_chat_find(js, presence.jid_from->node,
-		                                 presence.jid_from->domain);
-	g_free(presence.jb->error_msg);
-	presence.jb->error_msg = NULL;
-
-	if (presence.type == JABBER_PRESENCE_AVAILABLE) {
-		presence.state = JABBER_BUDDY_STATE_ONLINE;
-	} else if (presence.type == JABBER_PRESENCE_ERROR) {
-		/* TODO: Is this handled properly?  Should it be treated as per-jbr? */
-		char *msg = jabber_parse_error(js, packet, NULL);
-		presence.state = JABBER_BUDDY_STATE_ERROR;
-		presence.jb->error_msg = msg ? msg : g_strdup(_("Unknown Error in presence"));
-	} else if (presence.type == JABBER_PRESENCE_SUBSCRIBE) {
-		/* TODO: Move to handle_subscribe() (so nick is extracted by the
-		 * PresenceHandler */
-		struct _jabber_add_permit *jap = g_new0(struct _jabber_add_permit, 1);
-		gboolean onlist = FALSE;
-		PurpleAccount *account;
-		PurpleAuthorizationRequest *request = NULL;
-		PurpleNotification *notification = NULL;
-		PurpleNotificationManager *manager = NULL;
-		PurpleBuddy *buddy;
-		PurpleXmlNode *nick;
-
-		account = purple_connection_get_account(js->gc);
-		buddy = purple_blist_find_buddy(account, presence.from);
-		nick = purple_xmlnode_get_child_with_namespace(packet, "nick", "http://jabber.org/protocol/nick");
-		if (nick)
-			presence.nickname = purple_xmlnode_get_data(nick);
-
-		if (buddy) {
-			if ((presence.jb->subscription & (JABBER_SUB_TO | JABBER_SUB_PENDING)))
-				onlist = TRUE;
-		}
-
-		jap->gc = js->gc;
-		jap->who = g_strdup(presence.from);
-		jap->js = js;
-
-		request = purple_authorization_request_new(account, presence.from);
-		purple_authorization_request_set_alias(request, presence.nickname);
-		purple_authorization_request_set_add(request, !onlist);
-		g_signal_connect(request, "accepted", G_CALLBACK(authorize_add_cb),
-		                 jap);
-		g_signal_connect(request, "denied", G_CALLBACK(deny_add_cb), jap);
-
-		notification = purple_notification_new_from_authorization_request(request);
-		manager = purple_notification_manager_get_default();
-		purple_notification_manager_add(manager, notification);
-
-		g_object_unref(notification);
-
-		goto out;
-	} else if (presence.type == JABBER_PRESENCE_SUBSCRIBED) {
-		/* This case (someone has approved our subscribe request) is handled
-		 * by the roster push the server sends along with this.
-		 */
-		goto out;
-	} else if (presence.type == JABBER_PRESENCE_UNSUBSCRIBE) {
-		/* XXX I'm not sure this is the right way to handle this, it
-		 * might be better to add "unsubscribe" to the presence status
-		 * if lower down, but I'm not sure. */
-		/* they are unsubscribing from our presence, we don't care */
-		/* Well, maybe just a little, we might want/need to start
-		 * acknowledging this (and the others) at some point. */
-		goto out;
-	} else if (presence.type == JABBER_PRESENCE_PROBE) {
-		purple_debug_warning("jabber", "Ignoring presence probe\n");
-		goto out;
-	} else if (presence.type == JABBER_PRESENCE_UNAVAILABLE) {
-		presence.state = JABBER_BUDDY_STATE_UNAVAILABLE;
-	} else if (presence.type == JABBER_PRESENCE_UNSUBSCRIBED) {
-		presence.state = JABBER_BUDDY_STATE_UNKNOWN;
-	} else {
-		purple_debug_warning("jabber", "Ignoring presence with invalid type "
-		                     "'%s'\n", type);
-		goto out;
-	}
-
-	for (child = packet->child; child; child = child->next) {
-		const char *xmlns;
-		char *key;
-		JabberPresenceHandler *pih;
-		if (child->type != PURPLE_XMLNODE_TYPE_TAG)
-			continue;
-
-		xmlns = purple_xmlnode_get_namespace(child);
-		key = g_strdup_printf("%s %s", child->name, xmlns ? xmlns : "");
-		pih = g_hash_table_lookup(presence_handlers, key);
-		g_free(key);
-		if (pih)
-			pih(js, &presence, child);
-	}
-
-	if (presence.delayed && presence.idle && presence.adjust_idle_for_delay) {
-		GDateTime *now = g_date_time_new_now_utc();
-		GTimeSpan difference = 0;
-
-		difference = g_date_time_difference(now, presence.sent);
-
-		g_date_time_unref(now);
-
-		/* Delayed and idle, so update idle time */
-		presence.idle = presence.idle + (difference / G_TIME_SPAN_SECOND);
-	}
-
-	/* TODO: Handle tracking jb(r) here? */
-
-	if (presence.chat)
-		ret = handle_presence_chat(js, &presence, packet);
-	else
-		ret = handle_presence_contact(js, &presence);
-	if (!ret)
-		goto out;
-
-	if (presence.caps && presence.type == JABBER_PRESENCE_AVAILABLE) {
-		/* handle Entity Capabilities (XEP-0115) */
-		const char *node = purple_xmlnode_get_attrib(presence.caps, "node");
-		const char *ver  = purple_xmlnode_get_attrib(presence.caps, "ver");
-		const char *hash = purple_xmlnode_get_attrib(presence.caps, "hash");
-
-		/* v1.5 uses: node, ver, and hash. */
-		if(node != NULL && *node != '\0' &&
-		   ver != NULL && *ver != '\0' &&
-		   hash != NULL && *hash != '\0')
-		{
-			jbr = jabber_buddy_find_resource(presence.jb, presence.jid_from->resource);
-
-			/* Look it up if we don't already have all this information */
-			if(jbr == NULL || jbr->caps == NULL ||
-			   !purple_strequal(node, jbr->caps->tuple.node) ||
-			   !purple_strequal(ver, jbr->caps->tuple.ver) ||
-			   !purple_strequal(hash, jbr->caps->tuple.hash))
-			{
-				JabberPresenceCapabilities *userdata = g_new0(JabberPresenceCapabilities, 1);
-				userdata->js = js;
-				userdata->jb = presence.jb;
-				userdata->from = g_strdup(presence.from);
-				jabber_caps_get_info(js, presence.from, node, ver, hash,
-				    (jabber_caps_get_info_cb)jabber_presence_set_capabilities,
-				    userdata);
-			}
-		}
-	}
-
-out:
-	g_slist_free(presence.chat_info.codes);
-	g_free(presence.status);
-	g_free(presence.vcard_avatar_hash);
-	g_free(presence.nickname);
-	jabber_id_free(presence.jid_from);
-	g_clear_pointer(&presence.sent, g_date_time_unref);
-}
-
-void jabber_presence_subscription_set(JabberStream *js, const char *who, const char *type)
-{
-	PurpleXmlNode *presence = purple_xmlnode_new("presence");
-
-	purple_xmlnode_set_attrib(presence, "to", who);
-	purple_xmlnode_set_attrib(presence, "type", type);
-
-	jabber_send(js, presence);
-	purple_xmlnode_free(presence);
-}
-
-void purple_status_to_jabber(PurpleStatus *status, JabberBuddyState *state, char **msg, int *priority)
-{
-	const char *status_id = NULL;
-	const char *formatted_msg = NULL;
-
-	if(state) *state = JABBER_BUDDY_STATE_UNKNOWN;
-	if(msg) *msg = NULL;
-	if(priority) *priority = 0;
-
-	if(!status) {
-		if(state) *state = JABBER_BUDDY_STATE_UNAVAILABLE;
-	} else {
-		if(state) {
-			status_id = purple_status_get_id(status);
-			*state = jabber_buddy_status_id_get_state(status_id);
-		}
-
-		if(msg) {
-			formatted_msg = purple_status_get_attr_string(status, "message");
-
-			/* if the message is blank, then there really isn't a message */
-			if(formatted_msg && *formatted_msg)
-				*msg = purple_markup_strip_html(formatted_msg);
-		}
-
-		if(priority)
-			*priority = purple_status_get_attr_int(status, "priority");
-	}
-}
-
-/* Incoming presence handlers */
-static void
-parse_priority(G_GNUC_UNUSED JabberStream *js, JabberPresence *presence,
-               PurpleXmlNode *priority)
-{
-	char *p = purple_xmlnode_get_data(priority);
-
-	if (presence->priority != 0)
-		purple_debug_warning("jabber", "presence stanza received with multiple "
-		                     "priority children!?\n");
-
-	if (p) {
-		presence->priority = atoi(p);
-		g_free(p);
-	} else
-		purple_debug_warning("jabber", "Empty <priority/> in presence!\n");
-}
-
-static void
-parse_show(G_GNUC_UNUSED JabberStream *js, JabberPresence *presence,
-           PurpleXmlNode *show)
-{
-	char *cdata;
-
-	if (presence->type != JABBER_PRESENCE_AVAILABLE) {
-		purple_debug_warning("jabber", "<show/> present on presence, but "
-		                               "type is not default ('available')\n");
-		return;
-	}
-
-	cdata = purple_xmlnode_get_data(show);
-	if (cdata) {
-		presence->state = jabber_buddy_show_get_state(cdata);
-		g_free(cdata);
-	} else
-		purple_debug_warning("jabber", "<show/> present on presence, but "
-		                               "no contents!\n");
-}
-
-static void
-parse_status(G_GNUC_UNUSED JabberStream *js, JabberPresence *presence,
-             PurpleXmlNode *status)
-{
-	/* TODO: Check/track language attribute? */
-
-	g_free(presence->status);
-	presence->status = purple_xmlnode_get_data(status);
-}
-
-static void
-parse_delay(G_GNUC_UNUSED JabberStream *js, JabberPresence *presence,
-            PurpleXmlNode *delay)
-{
-	GTimeZone *tz = g_time_zone_new_utc();
-	const char *stamp = purple_xmlnode_get_attrib(delay, "stamp");
-
-	presence->delayed = TRUE;
-	presence->sent = g_date_time_new_from_iso8601(stamp, tz);
-
-	g_time_zone_unref(tz);
-}
-
-static void
-parse_idle(G_GNUC_UNUSED JabberStream *js, JabberPresence *presence,
-           PurpleXmlNode *query)
-{
-	const gchar *seconds = purple_xmlnode_get_attrib(query, "seconds");
-	if (seconds) {
-		presence->idle = atoi(seconds);
-		presence->adjust_idle_for_delay = TRUE;
-		if (presence->idle < 0) {
-			purple_debug_warning("jabber", "Received bogus idle time %s\n", seconds);
-			presence->idle = 0;
-		}
-	}
-}
-
-static void
-parse_caps(G_GNUC_UNUSED JabberStream *js, JabberPresence *presence,
-           PurpleXmlNode *c)
-{
-	/* TODO: Move the rest of the caps handling in here, after changing the
-	 * the "do we have details about this (node, ver) and exts" to not
-	 * require the jbr to be present (since that happens later).
-	 */
-	presence->caps = c;
-}
-
-static void
-parse_nickname(G_GNUC_UNUSED JabberStream *js, JabberPresence *presence,
-               PurpleXmlNode *nick)
-{
-	g_free(presence->nickname);
-	presence->nickname = purple_xmlnode_get_data(nick);
-}
-
-static void
-parse_vcard_avatar(G_GNUC_UNUSED JabberStream *js, JabberPresence *presence,
-                   PurpleXmlNode *x)
-{
-	PurpleXmlNode *photo = purple_xmlnode_get_child(x, "photo");
-
-	if (photo) {
-		char *hash_tmp = purple_xmlnode_get_data(photo);
-		g_free(presence->vcard_avatar_hash);
-		presence->vcard_avatar_hash =
-			hash_tmp ? hash_tmp : g_strdup("");
-	}
-}
-
-static void
-parse_muc_user(G_GNUC_UNUSED JabberStream *js, JabberPresence *presence,
-               PurpleXmlNode *x)
-{
-	PurpleXmlNode *status;
-
-	if (presence->chat == NULL) {
-		purple_debug_warning("jabber", "Ignoring MUC gloop on non-MUC presence\n");
-		return;
-	}
-
-	if (presence->chat->conv == NULL)
-		presence->chat->muc = TRUE;
-
-	for (status = purple_xmlnode_get_child(x, "status"); status;
-			status = purple_xmlnode_get_next_twin(status)) {
-		const char *code = purple_xmlnode_get_attrib(status, "code");
-		int val;
-		if (!code)
-			continue;
-
-		val = atoi(code);
-		if (val == 0 || val < 0) {
-			purple_debug_warning("jabber", "Ignoring bogus status code '%s'\n",
-			                               code);
-			continue;
-		}
-
-		presence->chat_info.codes = g_slist_prepend(presence->chat_info.codes, GINT_TO_POINTER(val));
-	}
-
-	presence->chat_info.item = purple_xmlnode_get_child(x, "item");
-}
-
-static void
-jabber_presence_register_handler(const char *node, const char *xmlns,
-                                 JabberPresenceHandler *handler)
-{
-	/*
-	 * This is valid because nodes nor namespaces cannot have spaces in them
-	 * (see http://www.w3.org/TR/2006/REC-xml-20060816/ and
-	 * http://www.w3.org/TR/REC-xml-names/)
-	 */
-	char *key = g_strdup_printf("%s %s", node, xmlns);
-	g_hash_table_replace(presence_handlers, key, handler);
-}
-
-void jabber_presence_init(void)
-{
-	presence_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
-
-	/* Core RFC things */
-	jabber_presence_register_handler("priority", "jabber:client", parse_priority);
-	jabber_presence_register_handler("show", "jabber:client", parse_show);
-	jabber_presence_register_handler("status", "jabber:client", parse_status);
-
-	/* XEPs */
-	jabber_presence_register_handler("c", "http://jabber.org/protocol/caps", parse_caps);
-	jabber_presence_register_handler("delay", NS_DELAYED_DELIVERY, parse_delay);
-	jabber_presence_register_handler("nick", "http://jabber.org/protocol/nick", parse_nickname);
-	jabber_presence_register_handler("query", NS_LAST_ACTIVITY, parse_idle);
-	jabber_presence_register_handler("x", NS_DELAYED_DELIVERY_LEGACY, parse_delay);
-	jabber_presence_register_handler("x", "http://jabber.org/protocol/muc#user", parse_muc_user);
-	jabber_presence_register_handler("x", "vcard-temp:x:update", parse_vcard_avatar);
-}
-
-void jabber_presence_uninit(void)
-{
-	g_clear_pointer(&presence_handlers , g_hash_table_destroy);
-}
diff --git a/libpurple/protocols/jabber/resources/icons/16x16/apps/im-jabber.png b/libpurple/protocols/jabber/resources/icons/16x16/apps/im-jabber.png
deleted file mode 100644
index 77a3f64135f09b9751129de09194f4848cd03d9e..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/libpurple/protocols/jabber/resources/icons/16x16/apps/scalable/im-jabber.svg b/libpurple/protocols/jabber/resources/icons/16x16/apps/scalable/im-jabber.svg
deleted file mode 100644
--- a/libpurple/protocols/jabber/resources/icons/16x16/apps/scalable/im-jabber.svg
+++ /dev/null
@@ -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="16"
-   height="16"
-   id="svg3302"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   sodipodi:docbase="/home/hbons/Desktop"
-   sodipodi:docname="jabber.svg"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape"
-   inkscape:export-filename="/home/hbons/Desktop/xmpp16.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90"
-   version="1.0">
-  <defs
-     id="defs3304">
-    <linearGradient
-       id="linearGradient2234"
-       inkscape:collect="always">
-      <stop
-         id="stop2236"
-         offset="0"
-         style="stop-color:#d9541e;stop-opacity:1" />
-      <stop
-         id="stop2238"
-         offset="1"
-         style="stop-color:#717311;stop-opacity:0;" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient2218"
-       inkscape:collect="always">
-      <stop
-         id="stop2220"
-         offset="0"
-         style="stop-color:#033e6f;stop-opacity:1" />
-      <stop
-         id="stop2222"
-         offset="1"
-         style="stop-color:#0f97cb;stop-opacity:1" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient2209"
-       inkscape:collect="always">
-      <stop
-         id="stop2211"
-         offset="0"
-         style="stop-color:#439638;stop-opacity:1" />
-      <stop
-         id="stop2213"
-         offset="1"
-         style="stop-color:#05757c;stop-opacity:0;" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3334">
-      <stop
-         style="stop-color:#f0a530;stop-opacity:1;"
-         offset="0"
-         id="stop3336" />
-      <stop
-         style="stop-color:#f0a530;stop-opacity:0;"
-         offset="1"
-         id="stop3338" />
-    </linearGradient>
-    <filter
-       inkscape:collect="always"
-       x="-0.49491513"
-       width="1.9898303"
-       y="-1.0582331"
-       height="3.1164663"
-       id="filter3871">
-      <feGaussianBlur
-         inkscape:collect="always"
-         stdDeviation="5.4785069"
-         id="feGaussianBlur3873" />
-    </filter>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2218"
-       id="linearGradient2244"
-       gradientUnits="userSpaceOnUse"
-       x1="5.0133924"
-       y1="12.455358"
-       x2="15.638392"
-       y2="30.098215"
-       gradientTransform="matrix(0.3406067,0,0,0.3698986,2.395e-3,-0.5863818)" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3334"
-       id="linearGradient2252"
-       gradientUnits="userSpaceOnUse"
-       x1="5.0133924"
-       y1="12.455358"
-       x2="15.638392"
-       y2="30.098215"
-       gradientTransform="matrix(-0.3406067,0,0,0.3698986,15.999925,-0.5863818)" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2209"
-       id="linearGradient2216"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.3406067,0,0,0.3754611,0.1185465,-0.6525396)"
-       x1="18.734463"
-       y1="21.519651"
-       x2="15.642859"
-       y2="23.876795" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2234"
-       id="linearGradient2231"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.3406067,0,0,0.3698986,2.025084e-2,-0.6190852)"
-       x1="30.893675"
-       y1="21.130915"
-       x2="37.48666"
-       y2="23.216526" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="28"
-     inkscape:cx="21.256159"
-     inkscape:cy="8.9295837"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     inkscape:grid-bbox="true"
-     inkscape:document-units="px"
-     inkscape:window-width="1434"
-     inkscape:window-height="823"
-     inkscape:window-x="3"
-     inkscape:window-y="43"
-     width="16px"
-     height="16px" />
-  <metadata
-     id="metadata3307">
-    <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:#0a6fa2;fill-opacity:1;stroke:#02396a;stroke-width:1.00000012;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 15.5,2.5000001 L 10.454106,2.5327029 C 10.454106,4.6682012 8.4691474,12.778185 3.1541859,14.341671 C 9.641668,14.341671 15.5,7.1171759 15.5,2.5000001 z "
-       id="path2228"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="fill:none;fill-opacity:1;stroke:url(#linearGradient2231);stroke-width:1.00000012;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 15.5,2.5062012 L 9.5791052,2.5000001 C 9.5791052,8.214349 8.5048611,12.745482 3.1899,14.308968 C 9.6773816,14.308968 15.5,7.123377 15.5,2.5062012 z "
-       id="path3388"
-       sodipodi:nodetypes="cccc" />
-    <path
-       sodipodi:type="arc"
-       style="opacity:0.29670332;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter3871)"
-       id="path3425"
-       sodipodi:cx="22.273863"
-       sodipodi:cy="36.736797"
-       sodipodi:rx="13.283506"
-       sodipodi:ry="6.2124381"
-       d="M 35.557369 36.736797 A 13.283506 6.2124381 0 1 1  8.9903564,36.736797 A 13.283506 6.2124381 0 1 1  35.557369 36.736797 z"
-       transform="matrix(0.3743374,0,0,0.1458475,-0.1571981,8.780618)" />
-    <path
-       style="fill:url(#linearGradient2252);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 14.997635,3.0728311 C 14.887455,4.1217876 13.42731,7.8391015 11.614614,10.013526 C 9.8225375,12.167186 7.1757566,13.602216 4.4938048,14.013055 C 6.5159292,13.016029 7.9668293,11.287886 8.900404,9.5049152 C 9.4616251,8.4330773 9.8347045,7.3512888 10.049952,6.3954548 C 10.244853,5.5299708 10.748164,3.6076606 10.677327,3.0472855 L 14.997635,3.0728311 z "
-       id="path3382"
-       sodipodi:nodetypes="cscsscc" />
-    <path
-       style="fill:#e96d1f;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 11.998273,3.0857646 L 9.853875,3.0746296 C 10.052724,5.704186 9.8431306,10.840842 5,13.99819 C 10.262132,13.127062 12.135446,6.14782 11.998273,3.0857646 z "
-       id="path3384"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 14.328472,3.5879657 C 13.402352,7.5116178 11.050991,9.896006 7.9932059,11.841578 C 9.4009194,9.3771388 10.613796,8.3204791 10.426187,3.617359 L 14.328472,3.5879657 z "
-       id="path3390"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="fill:#0a6fa2;fill-opacity:1;stroke:#02396a;stroke-width:1.00000012;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 0.50232,2.5000001 L 5.548214,2.5327029 C 5.548214,4.6682012 7.5331725,12.778185 12.848134,14.341671 C 6.3606519,14.341671 0.50232,7.1171759 0.50232,2.5000001 z "
-       id="path2230"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="fill:url(#linearGradient2244);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 1.0046854,3.0728311 C 1.025579,4.1606915 2.5750102,7.8391015 4.3877063,10.013526 C 6.1797822,12.167186 8.8265635,13.602216 11.508516,14.013055 C 9.4863905,13.01603 8.0354905,11.287886 7.1019159,9.5049152 C 6.5406948,8.4330773 6.1676154,7.3512888 5.9523683,6.3954548 C 5.7574673,5.5299709 5.2541559,3.6076606 5.3249925,3.0472854 L 1.0046854,3.0728311 z "
-       id="path2236"
-       sodipodi:nodetypes="cscsscc" />
-    <path
-       style="fill:#a0ce67;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 3.7118046,3.055775 L 6.0094407,3.1813771 C 5.9820727,4.0797021 5.9514165,10.838935 12,13.996284 C 5.4281278,13.125156 3.6296973,5.1178307 3.7118046,3.055775 z "
-       id="rect3326"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.00000012;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 1.6738483,3.5879662 C 2.5999681,7.5116186 4.9513289,9.8960072 8.0091145,11.841579 C 6.6014005,9.3771399 5.3885239,8.3204801 5.5761331,3.6173594 L 1.6738483,3.5879662 z "
-       id="path2240"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="fill:none;fill-opacity:1;stroke:url(#linearGradient2216);stroke-width:1.00000012;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 0.63632979,2.5000002 L 6.7242835,2.6127543 C 6.3286085,4.7177198 7.6493245,12.913003 12.964286,14.500001 C 6.4768045,14.500001 0.63632979,7.1866089 0.63632979,2.5000002 z "
-       id="path3352"
-       sodipodi:nodetypes="cccc" />
-  </g>
-</svg>
diff --git a/libpurple/protocols/jabber/resources/icons/22x22/apps/im-jabber.png b/libpurple/protocols/jabber/resources/icons/22x22/apps/im-jabber.png
deleted file mode 100644
index 99ec91040ae6eb7e8f70f9f04833c45745b7fd94..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/libpurple/protocols/jabber/resources/icons/22x22/apps/scalable/im-jabber.svg b/libpurple/protocols/jabber/resources/icons/22x22/apps/scalable/im-jabber.svg
deleted file mode 100644
--- a/libpurple/protocols/jabber/resources/icons/22x22/apps/scalable/im-jabber.svg
+++ /dev/null
@@ -1,251 +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="svg3302"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   sodipodi:docbase="/home/hbons/Desktop"
-   sodipodi:docname="jabber.svg"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape"
-   inkscape:export-filename="/home/hbons/Desktop/xmpp22.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90"
-   version="1.0">
-  <defs
-     id="defs3304">
-    <linearGradient
-       id="linearGradient2222"
-       inkscape:collect="always">
-      <stop
-         id="stop2224"
-         offset="0"
-         style="stop-color:#429538;stop-opacity:1" />
-      <stop
-         id="stop2226"
-         offset="1"
-         style="stop-color:#033e6f;stop-opacity:1" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient2214"
-       inkscape:collect="always">
-      <stop
-         id="stop2216"
-         offset="0"
-         style="stop-color:#033e6f;stop-opacity:1" />
-      <stop
-         id="stop2218"
-         offset="1"
-         style="stop-color:#14a9de;stop-opacity:1" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3417">
-      <stop
-         style="stop-color:#df5219;stop-opacity:1"
-         offset="0"
-         id="stop3419" />
-      <stop
-         style="stop-color:#034072;stop-opacity:1"
-         offset="1"
-         id="stop3421" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3334">
-      <stop
-         style="stop-color:#034072;stop-opacity:1"
-         offset="0"
-         id="stop3336" />
-      <stop
-         style="stop-color:#109cd3;stop-opacity:1"
-         offset="1"
-         id="stop3338" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3417"
-       id="linearGradient3423"
-       x1="31.736355"
-       y1="20.841261"
-       x2="35.292381"
-       y2="22.255474"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.4696897,0,0,0.4693264,1.1291183,0.5593256)" />
-    <filter
-       inkscape:collect="always"
-       x="-0.49491513"
-       width="1.9898303"
-       y="-1.0582331"
-       height="3.1164663"
-       id="filter3871">
-      <feGaussianBlur
-         inkscape:collect="always"
-         stdDeviation="5.4785069"
-         id="feGaussianBlur3873" />
-    </filter>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2222"
-       id="linearGradient2206"
-       gradientUnits="userSpaceOnUse"
-       x1="18.734463"
-       y1="21.519651"
-       x2="15.642859"
-       y2="23.876795"
-       gradientTransform="matrix(0.4696897,0,0,0.4693264,0.7859883,0.5593256)" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3334"
-       id="linearGradient2427"
-       gradientUnits="userSpaceOnUse"
-       x1="5.0133924"
-       y1="12.455358"
-       x2="15.638392"
-       y2="30.098215"
-       gradientTransform="matrix(-0.4731084,0,0,0.4693403,23.025142,0.6736289)" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2214"
-       id="linearGradient2429"
-       gradientUnits="userSpaceOnUse"
-       x1="5.0133924"
-       y1="12.455358"
-       x2="15.638392"
-       y2="30.098215"
-       gradientTransform="matrix(0.4731084,0,0,0.4693403,0.7795066,0.6736289)" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="14"
-     inkscape:cx="11.10389"
-     inkscape:cy="13.373032"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     inkscape:grid-bbox="true"
-     inkscape:document-units="px"
-     inkscape:window-width="1434"
-     inkscape:window-height="823"
-     inkscape:window-x="3"
-     inkscape:window-y="43"
-     inkscape:snap-bbox="true"
-     inkscape:snap-nodes="false"
-     objecttolerance="9"
-     gridtolerance="12">
-    <inkscape:grid
-       type="xygrid"
-       id="grid2421"
-       visible="true"
-       enabled="true" />
-  </sodipodi:namedview>
-  <metadata
-     id="metadata3307">
-    <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
-       sodipodi:type="arc"
-       style="opacity:0.29670332;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter3871)"
-       id="path3425"
-       sodipodi:cx="22.273863"
-       sodipodi:cy="36.736797"
-       sodipodi:rx="13.283506"
-       sodipodi:ry="6.2124381"
-       d="M 35.557369,36.736797 A 13.283506,6.2124381 0 1 1 8.9903564,36.736797 A 13.283506,6.2124381 0 1 1 35.557369,36.736797 z"
-       transform="matrix(0.5199608,0,0,0.1850564,0.5826339,12.558808)" />
-    <path
-       style="fill:#da6812;fill-opacity:1;stroke:#a24900;stroke-width:1.00000012;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 22.499999,4.5000001 L 14.975448,6.4912682 C 15.521075,9.1224749 12.829223,17.516252 5.5000001,19.499999 C 14.446104,19.499999 22.499999,10.35826 22.499999,4.5000001 z"
-       id="path3380"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="fill:url(#linearGradient2427);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 22.005002,4.971026 C 21.851961,7.7335015 19.92301,11.265451 16.933871,14.123162 C 14.261115,16.678402 10.768225,18.676617 7.0429489,19.197904 C 9.8517135,17.932843 11.867038,15.740114 13.163789,13.477819 C 13.943334,12.117834 14.259517,10.820984 14.558499,9.6081884 C 14.82922,8.5100321 14.983993,6.7178749 14.8856,6.0068516 L 22.005002,4.971026 z"
-       id="path3382"
-       sodipodi:nodetypes="cscsscc" />
-    <path
-       style="fill:#abbb25;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 18.868549,5.7525618 L 15.016096,6.7750535 C 15.049889,7.9148799 14.627471,15.172893 7.1591181,19.179048 C 15.27359,18.073731 18.969928,8.3689705 18.868549,5.7525618 z"
-       id="path3384"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="fill:none;fill-opacity:1;stroke:url(#linearGradient3423);stroke-width:1.00000024;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 22.499999,4.5000003 L 14.317055,5.5583642 C 14.862682,8.1895711 12.829223,17.516254 5.4999998,19.500001 C 14.446104,19.500001 22.499999,10.358261 22.499999,4.5000003 z"
-       id="path3388"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="fill:#df5219;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 19.203087,5.4052024 L 15.293888,5.9416777 C 15.327681,7.0815041 14.627471,15.172893 7.1591181,19.179048 C 15.27359,18.073731 19.304466,8.0216111 19.203087,5.4052024 z"
-       id="path3386"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="fill:#e96d1f;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 17.202112,5.6933762 L 14.951055,6.0174391 C 14.984849,7.1572655 14.688699,15.172893 7.2203467,19.179048 C 15.706546,17.068001 18.393936,6.9484519 17.202112,5.6933762 z"
-       id="path2228"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.00000012;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 21.5,5.5000001 C 21.259562,7.8476013 19.283758,10.890908 16.721197,13.322762 C 14.636171,15.301438 12.341463,16.82458 9.4999988,17.5 C 11.488026,16.319811 12.990581,14.640432 13.991693,12.906761 C 14.701922,11.676826 14.851876,10.636782 15.125188,9.5362725 C 15.351957,8.6231762 15.486367,7.0468868 15.426863,6.3988159 L 21.5,5.5000001 z"
-       id="path3390"
-       sodipodi:nodetypes="cscsscc" />
-    <path
-       style="fill:#da6812;fill-opacity:1;stroke:#a24900;stroke-width:1.00000012;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 1.5,4.5000001 L 9.0245518,6.4912682 C 8.4789251,9.1224749 11.170778,17.516252 18.499999,19.499999 C 9.5538954,19.499999 1.5,10.35826 1.5,4.5000001 z"
-       id="rect3321"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="fill:url(#linearGradient2429);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 1.7996466,4.971026 C 1.9526876,7.7335015 3.8816385,11.265451 6.8707772,14.123162 C 9.5435341,16.678402 13.036424,18.676617 16.7617,19.197904 C 13.952935,17.932843 11.937611,15.740114 10.64086,13.477819 C 9.8613144,12.117834 9.3431008,10.745223 9.044119,9.532427 C 8.7733983,8.4342707 8.9721786,6.8188901 9.0705719,6.1078667 L 1.7996466,4.971026 z"
-       id="path3332"
-       sodipodi:nodetypes="cscsscc" />
-    <path
-       style="fill:#08aec5;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 4.936101,5.7525618 L 8.7885541,6.7750535 C 8.7547609,7.9148799 9.1771789,15.172893 16.645531,19.179048 C 8.5310592,18.073731 4.8347205,8.3689705 4.936101,5.7525618 z"
-       id="rect3326"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="fill:#429538;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 4.6746077,5.4242622 L 8.9905846,5.9416777 C 8.9567914,7.0815041 9.1771789,15.172893 16.645531,19.179048 C 8.5310592,18.073731 4.4776451,8.3725446 4.6746077,5.4242622 z"
-       id="path3342"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="fill:#a0ce67;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 6.8152887,5.6933762 L 8.9905846,6.0679467 C 8.9567914,7.2077731 9.1771789,15.172893 16.645531,19.179048 C 8.1593314,17.068001 5.6948939,7.1270234 6.8152887,5.6933762 z"
-       id="path2220"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="fill:none;fill-opacity:1;stroke:url(#linearGradient2206);stroke-width:1.00000024;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 1.5000001,4.5000003 L 9.5252953,5.6445861 C 8.9796685,8.275793 11.170777,17.516254 18.5,19.500001 C 9.5538955,19.500001 1.5000001,10.358261 1.5000001,4.5000003 z"
-       id="path3352"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.00000012;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 2.6528401,5.6995163 C 3.1155917,8.0886161 4.8685432,11.14436 7.4405852,13.603314 C 9.0643917,15.155725 10.886287,16.515122 12.976833,17.423211 C 11.790214,16.318736 11.187637,15.199935 10.457851,13.926759 C 9.6473369,12.512747 9.1262733,11.255179 8.8124406,9.9821414 C 8.5924509,9.0897701 8.4306975,7.2046934 8.4453019,6.4949387 L 2.6528401,5.6995163 z"
-       id="path3366"
-       sodipodi:nodetypes="cscsscc" />
-  </g>
-</svg>
diff --git a/libpurple/protocols/jabber/resources/icons/48x48/apps/im-jabber.png b/libpurple/protocols/jabber/resources/icons/48x48/apps/im-jabber.png
deleted file mode 100644
index 8116334ffe9791673c3164c7ba63404d097209d5..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/libpurple/protocols/jabber/resources/icons/scalable/apps/im-jabber.svg b/libpurple/protocols/jabber/resources/icons/scalable/apps/im-jabber.svg
deleted file mode 100644
--- a/libpurple/protocols/jabber/resources/icons/scalable/apps/im-jabber.svg
+++ /dev/null
@@ -1,246 +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="48px"
-   height="48px"
-   id="svg3302"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   sodipodi:docbase="/home/hbons/Desktop"
-   sodipodi:docname="jabber.svg"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape"
-   inkscape:export-filename="/home/hbons/Desktop/xmpp.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90">
-  <defs
-     id="defs3304">
-    <linearGradient
-       id="linearGradient2222"
-       inkscape:collect="always">
-      <stop
-         id="stop2224"
-         offset="0"
-         style="stop-color:#429538;stop-opacity:1" />
-      <stop
-         id="stop2226"
-         offset="1"
-         style="stop-color:#033e6f;stop-opacity:1" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient2214"
-       inkscape:collect="always">
-      <stop
-         id="stop2216"
-         offset="0"
-         style="stop-color:#033e6f;stop-opacity:1" />
-      <stop
-         id="stop2218"
-         offset="1"
-         style="stop-color:#14a9de;stop-opacity:1" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3417">
-      <stop
-         style="stop-color:#df5219;stop-opacity:1"
-         offset="0"
-         id="stop3419" />
-      <stop
-         style="stop-color:#034072;stop-opacity:1"
-         offset="1"
-         id="stop3421" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3334">
-      <stop
-         style="stop-color:#034072;stop-opacity:1"
-         offset="0"
-         id="stop3336" />
-      <stop
-         style="stop-color:#109cd3;stop-opacity:1"
-         offset="1"
-         id="stop3338" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2214"
-       id="linearGradient3340"
-       x1="5.0133924"
-       y1="12.455358"
-       x2="15.638392"
-       y2="30.098215"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3334"
-       id="linearGradient3392"
-       gradientUnits="userSpaceOnUse"
-       x1="5.0133924"
-       y1="12.455358"
-       x2="15.638392"
-       y2="30.098215" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3417"
-       id="linearGradient3423"
-       x1="31.736355"
-       y1="20.841261"
-       x2="35.292381"
-       y2="22.255474"
-       gradientUnits="userSpaceOnUse" />
-    <filter
-       inkscape:collect="always"
-       x="-0.49491513"
-       width="1.9898303"
-       y="-1.0582332"
-       height="3.1164664"
-       id="filter3871">
-      <feGaussianBlur
-         inkscape:collect="always"
-         stdDeviation="5.4785069"
-         id="feGaussianBlur3873" />
-    </filter>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2222"
-       id="linearGradient2206"
-       gradientUnits="userSpaceOnUse"
-       x1="18.734463"
-       y1="21.519651"
-       x2="15.642859"
-       y2="23.876795" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="4.9497475"
-     inkscape:cx="81.961371"
-     inkscape:cy="4.928944"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     inkscape:grid-bbox="true"
-     inkscape:document-units="px"
-     inkscape:window-width="1434"
-     inkscape:window-height="823"
-     inkscape:window-x="3"
-     inkscape:window-y="43" />
-  <metadata
-     id="metadata3307">
-    <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
-       sodipodi:type="arc"
-       style="opacity:0.2967033;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter3871)"
-       id="path3425"
-       sodipodi:cx="22.273863"
-       sodipodi:cy="36.736797"
-       sodipodi:rx="13.283506"
-       sodipodi:ry="6.2124381"
-       d="M 35.557369 36.736797 A 13.283506 6.2124381 0 1 1  8.9903564,36.736797 A 13.283506 6.2124381 0 1 1  35.557369 36.736797 z"
-       transform="matrix(1.0990312,0,0,0.3942904,-0.4161261,25.323157)" />
-    <path
-       style="fill:#da6812;fill-opacity:1;stroke:#a24900;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 45.5,8.3964466 L 29.479739,12.639268 C 30.641414,18.245615 24.910285,36.130347 9.305892,40.357143 C 28.352732,40.357143 45.5,20.878719 45.5,8.3964466 z "
-       id="path3380"
-       sodipodi:nodetypes="cccc" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.56227452"
-       inkscape:original="M 1.53125 8.40625 C 1.53125 20.888522 18.671909 40.34375 37.71875 40.34375 C 22.114357 36.116954 16.369574 18.231347 17.53125 12.625 L 1.53125 8.40625 z "
-       style="fill:url(#linearGradient3392);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       id="path3382"
-       d="M 2.15625,9.15625 C 2.4797298,15.042119 6.5569158,22.567467 12.875,28.65625 C 18.524354,34.100573 25.907207,38.35807 33.78125,39.46875 C 27.844419,36.773348 23.584667,32.10141 20.84375,27.28125 C 19.19604,24.383597 18.100702,21.459043 17.46875,18.875 C 16.896533,16.535213 16.729528,14.546192 16.9375,13.03125 L 2.15625,9.15625 z "
-       transform="matrix(-1,0,0,1,47.020178,0)" />
-    <path
-       style="fill:#abbb25;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 38.234464,10.821428 L 30.091607,13 C 30.163035,15.428571 29.270178,30.892857 13.484463,39.428571 C 30.635869,37.073525 38.448749,16.396079 38.234464,10.821428 z "
-       id="path3384"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="fill:none;fill-opacity:1;stroke:url(#linearGradient3423);stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 45.5,8.3964466 L 29.479739,12.639268 C 30.641414,18.245615 24.910285,36.130347 9.305892,40.357143 C 28.352732,40.357143 45.5,20.878719 45.5,8.3964466 z "
-       id="path3388"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="fill:#df5219;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 38.941571,10.619397 L 30.091607,13 C 30.163035,15.428571 29.270178,30.892857 13.484463,39.428571 C 30.635869,37.073525 39.155856,16.194048 38.941571,10.619397 z "
-       id="path3386"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="fill:#e96d1f;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 34.3385,11.986693 L 30.221025,13 C 30.292453,15.428571 29.399596,30.892857 13.613881,39.428571 C 31.551001,34.930668 35.951771,13.823779 34.3385,11.986693 z "
-       id="path2228"
-       sodipodi:nodetypes="cccc" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-1.0305283"
-       inkscape:original="M 1.53125 8.40625 C 1.53125 20.888522 18.671909 40.34375 37.71875 40.34375 C 22.114357 36.116954 16.369574 18.231347 17.53125 12.625 L 1.53125 8.40625 z "
-       style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       id="path3390"
-       d="M 2.78125,9.8125 C 3.3466531,15.418621 7.1614784,22.50518 13.1875,28.3125 C 18.090567,33.03762 24.31812,36.855835 31,38.46875 C 26.325029,35.650434 22.791678,31.640043 20.4375,27.5 C 18.767353,24.562889 17.642711,21.596789 17,18.96875 C 16.46674,16.788257 16.328823,14.953857 16.46875,13.40625 L 2.78125,9.8125 z "
-       transform="matrix(-1,0,0,1,47.020178,0)" />
-    <path
-       style="fill:#da6812;fill-opacity:1;stroke:#a24900;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 1.5201775,8.3964466 L 17.540439,12.639268 C 16.378764,18.245615 22.109893,36.130347 37.714286,40.357143 C 18.667446,40.357143 1.5201775,20.878719 1.5201775,8.3964466 z "
-       id="rect3321"
-       sodipodi:nodetypes="cccc" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.56227452"
-       inkscape:original="M 1.53125 8.40625 C 1.53125 20.888522 18.671909 40.34375 37.71875 40.34375 C 22.114357 36.116954 16.369574 18.231347 17.53125 12.625 L 1.53125 8.40625 z "
-       style="fill:url(#linearGradient3340);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       id="path3332"
-       d="M 2.15625,9.15625 C 2.4797298,15.042119 6.5569158,22.567467 12.875,28.65625 C 18.524354,34.100573 25.907207,38.35807 33.78125,39.46875 C 27.844419,36.773348 23.584667,32.10141 20.84375,27.28125 C 19.19604,24.383597 18.100702,21.459043 17.46875,18.875 C 16.896533,16.535213 16.729528,14.546192 16.9375,13.03125 L 2.15625,9.15625 z " />
-    <path
-       style="fill:#08aec5;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 8.7857143,10.821428 L 16.928571,13 C 16.857143,15.428571 17.75,30.892857 33.535715,39.428571 C 16.384309,37.073525 8.5714286,16.396079 8.7857143,10.821428 z "
-       id="rect3326"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="fill:#429538;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 8.1796228,10.821428 L 16.928571,13 C 16.857143,15.428571 17.75,30.892857 33.535715,39.428571 C 16.384309,37.073525 7.7633066,17.103186 8.1796228,10.821428 z "
-       id="path3342"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="fill:#a0ce67;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 12.811096,11.986693 L 16.928571,13 C 16.857143,15.428571 17.75,30.892857 33.535715,39.428571 C 15.598595,34.930668 11.197825,13.823779 12.811096,11.986693 z "
-       id="path2220"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="fill:none;fill-opacity:1;stroke:url(#linearGradient2206);stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 1.5201775,8.3964466 L 17.540439,12.639268 C 16.378764,18.245615 22.109893,36.130347 37.714286,40.357143 C 18.667446,40.357143 1.5201775,20.878719 1.5201775,8.3964466 z "
-       id="path3352"
-       sodipodi:nodetypes="cccc" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-1.0305283"
-       inkscape:original="M 1.53125 8.40625 C 1.53125 20.888522 18.671909 40.34375 37.71875 40.34375 C 22.114357 36.116954 16.369574 18.231347 17.53125 12.625 L 1.53125 8.40625 z "
-       style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       id="path3366"
-       d="M 2.78125,9.8125 C 3.3466531,15.418621 7.1614784,22.50518 13.1875,28.3125 C 18.090567,33.03762 24.31812,36.855835 31,38.46875 C 26.325029,35.650434 22.791678,31.640043 20.4375,27.5 C 18.767353,24.562889 17.642711,21.596789 17,18.96875 C 16.46674,16.788257 16.328823,14.953857 16.46875,13.40625 L 2.78125,9.8125 z " />
-  </g>
-</svg>
diff --git a/libpurple/protocols/jabber/resources/xmpp.gresource.xml b/libpurple/protocols/jabber/resources/xmpp.gresource.xml
deleted file mode 100644
--- a/libpurple/protocols/jabber/resources/xmpp.gresource.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<gresources>
-  <gresource prefix="/im/pidgin/libpurple/xmpp">
-    <file>icons/16x16/apps/im-jabber.png</file>
-    <file>icons/16x16/apps/scalable/im-jabber.svg</file>
-    <file>icons/22x22/apps/im-jabber.png</file>
-    <file>icons/22x22/apps/scalable/im-jabber.svg</file>
-    <file>icons/48x48/apps/im-jabber.png</file>
-    <file>icons/scalable/apps/im-jabber.svg</file>
-  </gresource>
-</gresources>
diff --git a/libpurple/protocols/jabber/roster.h b/libpurple/protocols/jabber/roster.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/roster.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * @file roster.h Roster manipulation
- *
- * 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_JABBER_ROSTER_H
-#define PURPLE_JABBER_ROSTER_H
-
-/* it must *not* be localized */
-#define JABBER_ROSTER_DEFAULT_GROUP "Buddies"
-
-#include "jabber.h"
-
-void jabber_roster_request(JabberStream *js);
-
-void jabber_roster_parse(JabberStream *js, const char *from,
-                         JabberIqType type, const char *id, PurpleXmlNode *query);
-
-void jabber_roster_add_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleBuddy *buddy,
-		PurpleGroup *group, const gchar *message);
-void jabber_roster_alias_change(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const gchar *name,
-		const gchar *alias);
-void jabber_roster_group_change(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const gchar *name,
-		const gchar *old_group, const gchar *new_group);
-void jabber_roster_group_rename(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const gchar *old_name,
-		PurpleGroup *group, GList *moved_buddies);
-void jabber_roster_remove_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleBuddy *buddy,
-		PurpleGroup *group);
-
-#endif /* PURPLE_JABBER_ROSTER_H */
diff --git a/libpurple/protocols/jabber/roster.c b/libpurple/protocols/jabber/roster.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/roster.c
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <purple.h>
-
-#include "buddy.h"
-#include "chat.h"
-#include "presence.h"
-#include "roster.h"
-#include "iq.h"
-
-#include <string.h>
-
-static const gchar *jabber_roster_group_get_global_name(PurpleGroup *group);
-
-/* Take a list of strings and join them with a ", " separator */
-static gchar *roster_groups_join(GSList *list)
-{
-	GString *out = g_string_new(NULL);
-	for ( ; list; list = list->next) {
-		out = g_string_append(out, (const char *)list->data);
-		if (list->next)
-			out = g_string_append(out, ", ");
-	}
-
-	return g_string_free(out, FALSE);
-}
-
-static void
-roster_request_cb(JabberStream *js, const char *from, JabberIqType type,
-                  const char *id, PurpleXmlNode *packet,
-                  G_GNUC_UNUSED gpointer data)
-{
-	PurpleXmlNode *query;
-
-	if (type == JABBER_IQ_ERROR) {
-		/*
-		 * This shouldn't happen in any real circumstances and
-		 * likely constitutes a server-side misconfiguration (i.e.
-		 * explicitly not loading mod_roster...)
-		 */
-		purple_debug_error("jabber", "Error retrieving roster!?\n");
-		jabber_stream_set_state(js, JABBER_STREAM_CONNECTED);
-		return;
-	}
-
-	query = purple_xmlnode_get_child(packet, "query");
-	if (query == NULL) {
-		jabber_stream_set_state(js, JABBER_STREAM_CONNECTED);
-		return;
-	}
-
-	jabber_roster_parse(js, from, type, id, query);
-	jabber_stream_set_state(js, JABBER_STREAM_CONNECTED);
-}
-
-void jabber_roster_request(JabberStream *js)
-{
-	JabberIq *iq;
-
-	iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:roster");
-
-	jabber_iq_set_callback(iq, roster_request_cb, NULL);
-	jabber_iq_send(iq);
-}
-
-static void remove_purple_buddies(JabberStream *js, const char *jid)
-{
-	GSList *buddies;
-
-	buddies = purple_blist_find_buddies(purple_connection_get_account(js->gc), jid);
-
-	g_slist_free_full(buddies, (GDestroyNotify)purple_blist_remove_buddy);
-}
-
-static void add_purple_buddy_to_groups(JabberStream *js, const char *jid,
-		const char *alias, GSList *groups)
-{
-	GSList *buddies, *l;
-	PurpleAccount *account = purple_connection_get_account(js->gc);
-
-	buddies = purple_blist_find_buddies(purple_connection_get_account(js->gc), jid);
-
-	if(!groups) {
-		if(!buddies) {
-			groups = g_slist_append(groups, g_strdup(JABBER_ROSTER_DEFAULT_GROUP));
-		} else {
-			/* TODO: What should we do here? Removing the local buddies
-			 * is wrong, but so is letting the group state get out of sync with
-			 * the server.
-			 */
-			g_slist_free(buddies);
-			return;
-		}
-	}
-
-	while(buddies) {
-		PurpleBuddy *b = buddies->data;
-		PurpleGroup *g = purple_buddy_get_group(b);
-
-		buddies = g_slist_delete_link(buddies, buddies);
-
-		/* XMPP groups are case-sensitive, but libpurple groups are
-		 * case-insensitive. We treat a buddy in both "Friends" and "friends"
-		 * as only being in one group, but if we push changes about the buddy
-		 * to the server, the buddy will be dropped from one of the groups.
-		 * Not optimal, but better than the alternative, I think.
-		 */
-		l = g_slist_find_custom(groups, purple_group_get_name(g),
-			(GCompareFunc)purple_utf8_strcasecmp);
-		if (!l && g == purple_blist_get_default_group()) {
-			l = g_slist_find_custom(groups, JABBER_ROSTER_DEFAULT_GROUP,
-				(GCompareFunc)purple_utf8_strcasecmp);
-		}
-		if (!l && g == purple_blist_get_default_group()) {
-			l = g_slist_find_custom(groups,
-				_purple_blist_get_localized_default_group_name(),
-				(GCompareFunc)purple_utf8_strcasecmp);
-		}
-
-		if (l) {
-			/* The buddy is already on the local list. Update info. */
-			const char *servernick, *balias;
-
-			/* Previously stored serverside / buddy-supplied alias */
-			if((servernick = purple_blist_node_get_string((PurpleBlistNode*)b, "servernick")))
-				purple_serv_got_alias(js->gc, jid, servernick);
-
-			/* Alias from our roster retrieval */
-			balias = purple_buddy_get_local_alias(b);
-			if(alias && !purple_strequal(alias, balias))
-				purple_serv_got_private_alias(js->gc, jid, alias);
-			g_free(l->data);
-			groups = g_slist_delete_link(groups, l);
-		} else {
-			/* This buddy isn't in the group on the server anymore */
-			purple_debug_info("jabber", "jabber_roster_parse(): "
-				"Removing %s from group '%s' on the local list",
-				purple_buddy_get_name(b),
-				jabber_roster_group_get_global_name(g));
-			purple_blist_remove_buddy(b);
-		}
-	}
-
-	if (groups) {
-		char *tmp = roster_groups_join(groups);
-		purple_debug_info("jabber", "jabber_roster_parse(): Adding %s to "
-		                  "groups: %s\n", jid, tmp);
-		g_free(tmp);
-	}
-
-	while(groups) {
-		PurpleGroup *g = purple_blist_find_group(groups->data);
-		PurpleBuddy *b = purple_buddy_new(account, jid, alias);
-
-		if(!g) {
-			g = purple_group_new(groups->data);
-			purple_blist_add_group(g, NULL);
-		}
-
-		purple_blist_add_buddy(b, NULL, g, NULL);
-		purple_buddy_set_local_alias(b, alias);
-
-		g_free(groups->data);
-		groups = g_slist_delete_link(groups, groups);
-	}
-}
-
-void jabber_roster_parse(JabberStream *js, const char *from,
-                         JabberIqType type, const char *id, PurpleXmlNode *query)
-{
-	PurpleXmlNode *item, *group;
-
-	if (!jabber_is_own_account(js, from)) {
-		purple_debug_warning("jabber", "Received bogon roster push from %s\n",
-		                     from);
-		return;
-	}
-
-	js->currently_parsing_roster_push = TRUE;
-
-	for(item = purple_xmlnode_get_child(query, "item"); item; item = purple_xmlnode_get_next_twin(item))
-	{
-		const char *jid, *name, *subscription, *ask;
-		JabberBuddy *jb;
-
-		subscription = purple_xmlnode_get_attrib(item, "subscription");
-		jid = purple_xmlnode_get_attrib(item, "jid");
-		name = purple_xmlnode_get_attrib(item, "name");
-		ask = purple_xmlnode_get_attrib(item, "ask");
-
-		if(!jid)
-			continue;
-
-		if(!(jb = jabber_buddy_find(js, jid, TRUE)))
-			continue;
-
-		if(subscription) {
-			if (purple_strequal(subscription, "remove"))
-				jb->subscription = JABBER_SUB_REMOVE;
-			else if (jb == js->user_jb)
-				jb->subscription = JABBER_SUB_BOTH;
-			else if (purple_strequal(subscription, "none"))
-				jb->subscription = JABBER_SUB_NONE;
-			else if (purple_strequal(subscription, "to"))
-				jb->subscription = JABBER_SUB_TO;
-			else if (purple_strequal(subscription, "from"))
-				jb->subscription = JABBER_SUB_FROM;
-			else if (purple_strequal(subscription, "both"))
-				jb->subscription = JABBER_SUB_BOTH;
-		}
-
-		if(purple_strequal(ask, "subscribe"))
-			jb->subscription |= JABBER_SUB_PENDING;
-		else
-			jb->subscription &= ~JABBER_SUB_PENDING;
-
-		if(jb->subscription & JABBER_SUB_REMOVE) {
-			remove_purple_buddies(js, jid);
-		} else {
-			GSList *groups = NULL;
-
-			for(group = purple_xmlnode_get_child(item, "group"); group; group = purple_xmlnode_get_next_twin(group)) {
-				char *group_name = purple_xmlnode_get_data(group);
-
-				if (group_name == NULL || *group_name == '\0')
-					/* Changing this string?  Look in add_purple_buddy_to_groups */
-					group_name = g_strdup(JABBER_ROSTER_DEFAULT_GROUP);
-
-				/*
-				 * See the note in add_purple_buddy_to_groups; the core handles
-				 * names case-insensitively and this is required to not
-				 * end up with duplicates if a buddy is in, e.g.,
-				 * 'XMPP' and 'xmpp'
-				 */
-				if (g_slist_find_custom(groups, group_name, (GCompareFunc)purple_utf8_strcasecmp))
-					g_free(group_name);
-				else
-					groups = g_slist_prepend(groups, group_name);
-			}
-
-			add_purple_buddy_to_groups(js, jid, name, groups);
-			if (jb == js->user_jb)
-				jabber_presence_fake_to_self(js, NULL);
-		}
-	}
-
-	if (type == JABBER_IQ_SET) {
-		JabberIq *ack = jabber_iq_new(js, JABBER_IQ_RESULT);
-		jabber_iq_set_id(ack, id);
-		jabber_iq_send(ack);
-	}
-
-	js->currently_parsing_roster_push = FALSE;
-}
-
-/* jabber_roster_update frees the GSList* passed in */
-static void jabber_roster_update(JabberStream *js, const char *name,
-		GSList *groups)
-{
-	PurpleBuddy *b;
-	PurpleGroup *g;
-	GSList *l;
-	JabberIq *iq;
-	PurpleXmlNode *query, *item, *group;
-	const char *balias;
-
-	if (js->currently_parsing_roster_push)
-		return;
-
-	if(!(b = purple_blist_find_buddy(purple_connection_get_account(js->gc), name)))
-		return;
-
-	if (groups) {
-		char *tmp = roster_groups_join(groups);
-
-		purple_debug_info("jabber", "jabber_roster_update(%s): [Source: "
-		                  "groups]: groups: %s\n", name, tmp);
-		g_free(tmp);
-	} else {
-		GSList *buddies = purple_blist_find_buddies(purple_connection_get_account(js->gc), name);
-		char *tmp;
-
-		if(!buddies)
-			return;
-		while(buddies) {
-			b = buddies->data;
-			g = purple_buddy_get_group(b);
-			groups = g_slist_append(groups,
-				(char *)jabber_roster_group_get_global_name(g));
-			buddies = g_slist_delete_link(buddies, buddies);
-		}
-
-		tmp = roster_groups_join(groups);
-		purple_debug_info("jabber", "jabber_roster_update(%s): [Source: local blist]: groups: %s\n",
-		                  name, tmp);
-		g_free(tmp);
-	}
-
-	iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster");
-
-	query = purple_xmlnode_get_child(iq->node, "query");
-	item = purple_xmlnode_new_child(query, "item");
-
-	purple_xmlnode_set_attrib(item, "jid", name);
-
-	balias = purple_buddy_get_local_alias(b);
-	purple_xmlnode_set_attrib(item, "name", balias ? balias : "");
-
-	for(l = groups; l; l = l->next) {
-		group = purple_xmlnode_new_child(item, "group");
-		purple_xmlnode_insert_data(group, l->data, -1);
-	}
-
-	g_slist_free(groups);
-
-	jabber_iq_send(iq);
-}
-
-void
-jabber_roster_add_buddy(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
-                        PurpleConnection *gc, PurpleBuddy *buddy,
-                        G_GNUC_UNUSED PurpleGroup *group,
-                        G_GNUC_UNUSED const char *message)
-{
-	JabberStream *js = purple_connection_get_protocol_data(gc);
-	char *who;
-	JabberID *jid;
-	JabberBuddy *jb;
-	JabberBuddyResource *jbr;
-	const char *name;
-
-	/* If we haven't received the roster yet, ignore any adds */
-	if (js->state != JABBER_STREAM_CONNECTED)
-		return;
-
-	name = purple_buddy_get_name(buddy);
-	jid = jabber_id_new(name);
-	if (jid == NULL) {
-		/* TODO: Remove the buddy from the list? */
-		return;
-	}
-
-	/* Adding a chat room or a chat user to the roster is *not* supported. */
-	if (jid->node && jabber_chat_find(js, jid->node, jid->domain) != NULL) {
-		/*
-		 * This is the same thing Bonjour does. If it causes problems, move
-		 * it to an idle callback.
-		 */
-		purple_debug_warning("jabber", "Cowardly refusing to add a MUC user "
-		                     "to your buddy list and removing the buddy. "
-		                     "Buddies can only be added by real (non-MUC) "
-		                     "JID\n");
-		purple_blist_remove_buddy(buddy);
-		jabber_id_free(jid);
-		return;
-	}
-
-	who = jabber_id_get_bare_jid(jid);
-	if (jid->resource != NULL) {
-		/*
-		 * If the buddy name added contains a resource, strip that off and
-		 * rename the buddy.
-		 */
-		purple_buddy_set_name(buddy, who);
-	}
-
-	jb = jabber_buddy_find(js, who, FALSE);
-
-	purple_debug_info("jabber", "jabber_roster_add_buddy(): Adding %s\n", who);
-
-	jabber_roster_update(js, who, NULL);
-
-	if (jb == js->user_jb) {
-		jabber_presence_fake_to_self(js, NULL);
-	} else if(!jb || !(jb->subscription & JABBER_SUB_TO)) {
-		jabber_presence_subscription_set(js, who, "subscribe");
-	} else if((jbr =jabber_buddy_find_resource(jb, NULL))) {
-		purple_protocol_got_user_status(purple_connection_get_account(gc), who,
-				jabber_buddy_state_get_status_id(jbr->state),
-				"priority", jbr->priority, jbr->status ? "message" : NULL, jbr->status, NULL);
-	}
-
-	g_free(who);
-}
-
-void
-jabber_roster_alias_change(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
-                           PurpleConnection *gc, const gchar *name,
-                           const gchar *alias)
-{
-	PurpleBuddy *b = purple_blist_find_buddy(purple_connection_get_account(gc), name);
-
-	if(b != NULL) {
-		purple_buddy_set_local_alias(b, alias);
-
-		purple_debug_info("jabber", "jabber_roster_alias_change(): Aliased %s to %s\n",
-				name, alias ? alias : "(null)");
-
-		jabber_roster_update(purple_connection_get_protocol_data(gc), name, NULL);
-	}
-}
-
-void
-jabber_roster_group_change(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
-                           PurpleConnection *gc, const gchar *name,
-                           const gchar *old_group, const gchar *new_group)
-{
-	GSList *buddies, *groups = NULL;
-
-	if(!old_group || !new_group || purple_strequal(old_group, new_group))
-		return;
-
-	buddies = purple_blist_find_buddies(purple_connection_get_account(gc), name);
-	while(buddies) {
-		groups = g_slist_append(groups, (char*)new_group);
-		buddies = g_slist_delete_link(buddies, buddies);
-	}
-
-	purple_debug_info("jabber", "jabber_roster_group_change(): Moving %s from %s to %s\n",
-	                  name, old_group, new_group);
-
-	jabber_roster_update(purple_connection_get_protocol_data(gc), name, groups);
-}
-
-void
-jabber_roster_group_rename(PurpleProtocolServer *protocol_server,
-                           PurpleConnection *gc, const gchar *old_name,
-                           PurpleGroup *group, GList *moved_buddies)
-{
-	GList *l;
-	const char *gname = jabber_roster_group_get_global_name(group);
-
-	for(l = moved_buddies; l; l = l->next) {
-		PurpleBuddy *buddy = l->data;
-
-		jabber_roster_group_change(protocol_server, gc,
-		                           purple_buddy_get_name(buddy), old_name,
-		                           gname);
-	}
-}
-
-void
-jabber_roster_remove_buddy(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
-                           PurpleConnection *gc, PurpleBuddy *buddy,
-                           PurpleGroup *group)
-{
-	const char *name = purple_buddy_get_name(buddy);
-	GSList *buddies = purple_blist_find_buddies(purple_connection_get_account(gc), name);
-
-	buddies = g_slist_remove(buddies, buddy);
-	if(buddies != NULL) {
-		PurpleBuddy *tmpbuddy;
-		PurpleGroup *tmpgroup;
-		GSList *groups = NULL;
-
-		while(buddies) {
-			tmpbuddy = buddies->data;
-			tmpgroup = purple_buddy_get_group(tmpbuddy);
-			groups = g_slist_append(groups,
-				(char *)jabber_roster_group_get_global_name(tmpgroup));
-			buddies = g_slist_delete_link(buddies, buddies);
-		}
-
-		purple_debug_info("jabber", "jabber_roster_remove_buddy(): "
-			"Removing %s from %s", purple_buddy_get_name(buddy),
-			jabber_roster_group_get_global_name(group));
-
-		jabber_roster_update(purple_connection_get_protocol_data(gc), name, groups);
-	} else {
-		JabberIq *iq = jabber_iq_new_query(purple_connection_get_protocol_data(gc), JABBER_IQ_SET,
-				"jabber:iq:roster");
-		PurpleXmlNode *query = purple_xmlnode_get_child(iq->node, "query");
-		PurpleXmlNode *item = purple_xmlnode_new_child(query, "item");
-
-		purple_xmlnode_set_attrib(item, "jid", name);
-		purple_xmlnode_set_attrib(item, "subscription", "remove");
-
-		purple_debug_info("jabber", "jabber_roster_remove_buddy(): Removing %s\n",
-		                  purple_buddy_get_name(buddy));
-
-		jabber_iq_send(iq);
-	}
-}
-
-static const gchar *
-jabber_roster_group_get_global_name(PurpleGroup *group)
-{
-	const gchar *name = NULL;
-
-	if (group)
-		name = purple_group_get_name(group);
-
-	if (name == NULL)
-		name = JABBER_ROSTER_DEFAULT_GROUP;
-	else if (purple_strequal(name, PURPLE_BLIST_DEFAULT_GROUP_NAME))
-		name = JABBER_ROSTER_DEFAULT_GROUP;
-	else if (purple_strequal(name, _purple_blist_get_localized_default_group_name()))
-		name = JABBER_ROSTER_DEFAULT_GROUP;
-
-	return name;
-}
diff --git a/libpurple/protocols/jabber/si.h b/libpurple/protocols/jabber/si.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/si.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * @file si.h SI 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 PURPLE_JABBER_SI_H
-#define PURPLE_JABBER_SI_H
-
-#include <purple.h>
-
-#include "jabber.h"
-
-G_BEGIN_DECLS
-
-#define JABBER_TYPE_SI_XFER (jabber_si_xfer_get_type())
-G_DECLARE_FINAL_TYPE(JabberSIXfer, jabber_si_xfer, JABBER, SI_XFER, PurpleXfer);
-
-void jabber_bytestreams_parse(JabberStream *js, const char *from,
-                              JabberIqType type, const char *id, PurpleXmlNode *query);
-PurpleXfer *jabber_si_new_xfer(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *who);
-void jabber_si_xfer_send(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *who, const char *file);
-
-void jabber_si_xfer_register(GTypeModule *module);
-
-void jabber_si_init(void);
-void jabber_si_uninit(void);
-
-G_END_DECLS
-
-#endif /* PURPLE_JABBER_SI_H */
diff --git a/libpurple/protocols/jabber/si.c b/libpurple/protocols/jabber/si.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/si.c
+++ /dev/null
@@ -1,1909 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <purpleconfig.h>
-
-#include <errno.h>
-#include <sys/types.h>
-
-#include <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "buddy.h"
-#include "data.h"
-#include "disco.h"
-#include "jabber.h"
-#include "ibb.h"
-#include "iq.h"
-#include "si.h"
-
-#define STREAMHOST_CONNECT_TIMEOUT 5
-#define ENABLE_FT_THUMBNAILS 0
-
-struct _JabberSIXfer {
-	PurpleXfer parent;
-
-	JabberStream *js;
-
-	GCancellable *cancellable;
-	GSocketClient *client;
-	GSocketService *service;
-	guint connect_timeout;
-
-	gboolean accepted;
-
-	char *stream_id;
-	char *iq_id;
-
-	enum {
-		STREAM_METHOD_UNKNOWN     = 0,
-		STREAM_METHOD_BYTESTREAMS = 2 << 1,
-		STREAM_METHOD_IBB         = 2 << 2,
-		STREAM_METHOD_UNSUPPORTED = 2 << 30
-	} stream_method;
-
-	GList *streamhosts;
-
-	gchar *socks_buf;
-	GSocketConnection *local_streamhost_conn;
-
-	JabberIBBSession *ibb_session;
-	guint ibb_timeout_handle;
-	PurpleCircularBuffer *ibb_buffer;
-};
-
-G_DEFINE_DYNAMIC_TYPE_EXTENDED(JabberSIXfer, jabber_si_xfer, PURPLE_TYPE_XFER,
-                               G_TYPE_FLAG_FINAL, {})
-
-/* some forward declarations */
-static void jabber_si_xfer_ibb_send_init(JabberStream *js, PurpleXfer *xfer);
-
-static PurpleXfer*
-jabber_si_xfer_find(JabberStream *js, const char *sid, const char *from)
-{
-	GList *xfers;
-
-	if(!sid || !from)
-		return NULL;
-
-	for(xfers = js->file_transfers; xfers; xfers = xfers->next) {
-		PurpleXfer *xfer = xfers->data;
-		JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-		if(jsx->stream_id && purple_xfer_get_remote_user(xfer) &&
-				purple_strequal(jsx->stream_id, sid) && purple_strequal(purple_xfer_get_remote_user(xfer), from))
-			return xfer;
-	}
-
-	return NULL;
-}
-
-
-
-static void jabber_si_bytestreams_attempt_connect(PurpleXfer *xfer);
-
-static void
-jabber_si_bytestreams_try_next_streamhost(PurpleXfer *xfer,
-                                          const gchar *error_message)
-{
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	JabberBytestreamsStreamhost *streamhost = jsx->streamhosts->data;
-
-	purple_debug_warning(
-	        "jabber",
-	        "si connection failed, jid was %s, host was %s, error was %s",
-	        streamhost->jid, streamhost->host, error_message);
-	jsx->streamhosts = g_list_remove(jsx->streamhosts, streamhost);
-	jabber_bytestreams_streamhost_free(streamhost);
-	g_clear_object(&jsx->client);
-	jabber_si_bytestreams_attempt_connect(xfer);
-}
-
-static void
-jabber_si_bytestreams_connect_cb(GObject *source, GAsyncResult *result,
-                                 gpointer user_data)
-{
-	PurpleXfer *xfer = PURPLE_XFER(user_data);
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	GIOStream *stream = NULL;
-	GError *error = NULL;
-	GSocket *socket = NULL;
-	JabberIq *iq = NULL;
-	JabberBytestreamsStreamhost *streamhost = jsx->streamhosts->data;
-
-	stream = g_proxy_connect_finish(G_PROXY(source), result, &error);
-	if (stream == NULL) {
-		if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
-			purple_debug_error("jabber",
-			                   "Unable to connect to destination host: %s",
-			                   error->message);
-			jabber_si_bytestreams_try_next_streamhost(
-			        xfer, "Unable to connect to destination host.");
-		}
-
-		g_clear_error(&error);
-		return;
-	}
-
-	if (!G_IS_SOCKET_CONNECTION(stream)) {
-		purple_debug_error("jabber",
-		                   "GProxy didn't return a GSocketConnection.");
-		jabber_si_bytestreams_try_next_streamhost(
-		        xfer, "GProxy didn't return a GSocketConnection.");
-		g_object_unref(stream);
-		return;
-	}
-
-	/* unknown file transfer type is assumed to be RECEIVE */
-	if (purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_SEND) {
-		PurpleXmlNode *query, *activate;
-		iq = jabber_iq_new_query(jsx->js, JABBER_IQ_SET, NS_BYTESTREAMS);
-		purple_xmlnode_set_attrib(iq->node, "to", streamhost->jid);
-		query = purple_xmlnode_get_child(iq->node, "query");
-		purple_xmlnode_set_attrib(query, "sid", jsx->stream_id);
-		activate = purple_xmlnode_new_child(query, "activate");
-		purple_xmlnode_insert_data(activate, purple_xfer_get_remote_user(xfer), -1);
-
-		/* TODO: We need to wait for an activation result before starting */
-	} else {
-		PurpleXmlNode *query, *su;
-		iq = jabber_iq_new_query(jsx->js, JABBER_IQ_RESULT, NS_BYTESTREAMS);
-		purple_xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
-		jabber_iq_set_id(iq, jsx->iq_id);
-		query = purple_xmlnode_get_child(iq->node, "query");
-		su = purple_xmlnode_new_child(query, "streamhost-used");
-		purple_xmlnode_set_attrib(su, "jid", streamhost->jid);
-	}
-
-	jabber_iq_send(iq);
-
-	jsx->local_streamhost_conn = G_SOCKET_CONNECTION(stream);
-	socket = g_socket_connection_get_socket(jsx->local_streamhost_conn);
-	purple_xfer_start(xfer, g_socket_get_fd(socket), NULL, -1);
-}
-
-static void
-jabber_si_bytestreams_ibb_timeout_remove(JabberSIXfer *jsx)
-{
-	g_clear_handle_id(&jsx->ibb_timeout_handle, g_source_remove);
-}
-
-static gboolean
-jabber_si_bytestreams_ibb_timeout_cb(gpointer data)
-{
-	PurpleXfer *xfer = (PurpleXfer *) data;
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-
-	if (jsx && !jsx->ibb_session) {
-		purple_debug_info("jabber",
-			"jabber_si_bytestreams_ibb_timeout called and IBB session not set "
-			" up yet, cancel transfer");
-		jabber_si_bytestreams_ibb_timeout_remove(jsx);
-		purple_xfer_cancel_local(xfer);
-	}
-
-	return FALSE;
-}
-
-/* This is called when we connect to the SOCKS5 proxy server (through any
- * relevant account proxy)
- */
-static void
-jabber_si_bytestreams_socks5_connect_to_host_cb(GObject *source,
-                                                GAsyncResult *result,
-                                                gpointer user_data)
-{
-	PurpleXfer *xfer = PURPLE_XFER(user_data);
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	JabberID *dstjid;
-	const JabberID *from_jid, *to_jid;
-	GSocketConnection *conn;
-	GProxy *proxy;
-	GSocketAddress *addr;
-	GInetSocketAddress *inet_addr;
-	GSocketAddress *proxy_addr;
-	gchar *dstaddr, *hash_input;
-	GError *error = NULL;
-
-	conn = g_socket_client_connect_to_host_finish(G_SOCKET_CLIENT(source),
-	                                              result, &error);
-	if (conn == NULL) {
-		if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
-			purple_debug_error("jabber", "Unable to connect to SOCKS5 host: %s",
-			                   error->message);
-			jabber_si_bytestreams_try_next_streamhost(
-			        xfer, "Unable to connect to SOCKS5 host.");
-		}
-
-		g_clear_error(&error);
-		return;
-	}
-
-	proxy = g_proxy_get_default_for_protocol("socks5");
-	if (proxy == NULL) {
-		purple_debug_error("jabber", "SOCKS5 proxy backend missing.");
-		jabber_si_bytestreams_try_next_streamhost(
-		        xfer, "SOCKS5 proxy backend missing.");
-		g_object_unref(conn);
-		return;
-	}
-
-	addr = g_socket_connection_get_remote_address(conn, &error);
-	if (addr == NULL) {
-		purple_debug_error(
-		        "jabber",
-		        "Unable to retrieve SOCKS5 host address from connection: %s",
-		        error->message);
-		jabber_si_bytestreams_try_next_streamhost(
-		        xfer, "Unable to retrieve SOCKS5 host address from connection");
-		g_object_unref(conn);
-		g_object_unref(proxy);
-		g_clear_error(&error);
-		return;
-	}
-
-	dstjid = jabber_id_new(purple_xfer_get_remote_user(xfer));
-
-	/* unknown file transfer type is assumed to be RECEIVE */
-	if (purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_SEND) {
-		from_jid = jsx->js->user;
-		to_jid = dstjid;
-	} else {
-		from_jid = dstjid;
-		to_jid = jsx->js->user;
-	}
-
-	/* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */
-	hash_input = g_strdup_printf("%s%s@%s/%s%s@%s/%s", jsx->stream_id,
-	                             from_jid->node, from_jid->domain,
-	                             from_jid->resource, to_jid->node,
-	                             to_jid->domain, to_jid->resource);
-	dstaddr = g_compute_checksum_for_string(G_CHECKSUM_SHA1, hash_input, -1);
-	g_free(hash_input);
-	jabber_id_free(dstjid);
-
-	inet_addr = G_INET_SOCKET_ADDRESS(addr);
-
-	proxy_addr =
-	        g_proxy_address_new(g_inet_socket_address_get_address(inet_addr),
-	                            g_inet_socket_address_get_port(inet_addr),
-	                            "socks5", dstaddr, 0, NULL, NULL);
-	g_object_unref(inet_addr);
-
-	purple_debug_info("jabber", "Connecting to %s using SOCKS5 proxy", dstaddr);
-
-	g_proxy_connect_async(proxy, G_IO_STREAM(conn), G_PROXY_ADDRESS(proxy_addr),
-	                      jsx->cancellable, jabber_si_bytestreams_connect_cb,
-	                      user_data);
-
-	g_object_unref(proxy_addr);
-	g_object_unref(conn);
-	g_object_unref(proxy);
-	g_free(dstaddr);
-}
-
-static void
-jabber_si_bytestreams_attempt_connect(PurpleXfer *xfer)
-{
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	JabberBytestreamsStreamhost *streamhost;
-	JabberID *dstjid;
-
-	if(!jsx->streamhosts) {
-		JabberIq *iq = jabber_iq_new(jsx->js, JABBER_IQ_ERROR);
-		PurpleXmlNode *error, *inf;
-
-		if(jsx->iq_id)
-			jabber_iq_set_id(iq, jsx->iq_id);
-
-		purple_xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
-		error = purple_xmlnode_new_child(iq->node, "error");
-		purple_xmlnode_set_attrib(error, "code", "404");
-		purple_xmlnode_set_attrib(error, "type", "cancel");
-		inf = purple_xmlnode_new_child(error, "item-not-found");
-		purple_xmlnode_set_namespace(inf, NS_XMPP_STANZAS);
-
-		jabber_iq_send(iq);
-
-		/* if IBB is available, revert to that before giving up... */
-		if (jsx->stream_method & STREAM_METHOD_IBB) {
-			/* if we are the initializer, init IBB */
-			purple_debug_info("jabber",
-				"jabber_si_bytestreams_attempt_connect: "
-				"no streamhosts found, trying IBB\n");
-			if(jsx->stream_method & STREAM_METHOD_BYTESTREAMS) {
-				jsx->stream_method &= ~STREAM_METHOD_BYTESTREAMS;
-			}
-			/* if we are the sender, open an IBB session, but not if we already
-			  did it, since we could have received the error <iq/> from the
-			  receiver already... */
-			if (purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_SEND
-				&& !jsx->ibb_session) {
-				jabber_si_xfer_ibb_send_init(jsx->js, xfer);
-			} else {
-				/* setup a timeout to cancel waiting for IBB open */
-				jsx->ibb_timeout_handle = g_timeout_add_seconds(30,
-					jabber_si_bytestreams_ibb_timeout_cb, xfer);
-			}
-			/* if we are the receiver, just wait for IBB open, callback is
-			  already set up... */
-		} else {
-			purple_xfer_cancel_local(xfer);
-		}
-
-		return;
-	}
-
-	streamhost = jsx->streamhosts->data;
-	dstjid = jabber_id_new(purple_xfer_get_remote_user(xfer));
-
-	/* TODO: Deal with zeroconf */
-
-	if(dstjid != NULL && streamhost->host && streamhost->port > 0) {
-		GError *error = NULL;
-		PurpleAccount *account;
-
-		account = purple_connection_get_account(jsx->js->gc);
-		jsx->client = purple_gio_socket_client_new(account, &error);
-		if (jsx->client != NULL) {
-			if (purple_xfer_get_xfer_type(xfer) != PURPLE_XFER_TYPE_SEND) {
-				/* When selecting a streamhost, timeout after
-				 * STREAMHOST_CONNECT_TIMEOUT seconds, otherwise it takes
-				 * forever
-				 */
-				g_socket_client_set_timeout(jsx->client,
-				                            STREAMHOST_CONNECT_TIMEOUT);
-			}
-
-			purple_debug_info("jabber",
-			                  "Connecting to SOCKS5 streamhost proxy %s:%d",
-			                  streamhost->host, streamhost->port);
-
-			g_socket_client_connect_to_host_async(
-			        jsx->client, streamhost->host, streamhost->port,
-			        jsx->cancellable,
-			        jabber_si_bytestreams_socks5_connect_to_host_cb, xfer);
-		} else {
-			purple_debug_error(
-			        "jabber",
-			        "Failed to connect to SOCKS5 streamhost proxy: %s",
-			        error->message);
-			g_clear_error(&error);
-		}
-
-		jabber_id_free(dstjid);
-	}
-
-	if (jsx->client == NULL) {
-		jsx->streamhosts = g_list_remove(jsx->streamhosts, streamhost);
-		jabber_bytestreams_streamhost_free(streamhost);
-		jabber_si_bytestreams_attempt_connect(xfer);
-	}
-}
-
-void jabber_bytestreams_parse(JabberStream *js, const char *from,
-                              JabberIqType type, const char *id, PurpleXmlNode *query)
-{
-	PurpleXfer *xfer;
-	JabberSIXfer *jsx;
-	PurpleXmlNode *streamhost;
-	const char *sid;
-
-	if(type != JABBER_IQ_SET)
-		return;
-
-	if(!from)
-		return;
-
-	if(!(sid = purple_xmlnode_get_attrib(query, "sid")))
-		return;
-
-	if(!(xfer = jabber_si_xfer_find(js, sid, from)))
-		return;
-
-	jsx = JABBER_SI_XFER(xfer);
-
-	if(!jsx->accepted)
-		return;
-
-	g_free(jsx->iq_id);
-	jsx->iq_id = g_strdup(id);
-
-	for(streamhost = purple_xmlnode_get_child(query, "streamhost"); streamhost;
-			streamhost = purple_xmlnode_get_next_twin(streamhost)) {
-		const char *jid, *host = NULL, *port, *zeroconf;
-		int portnum = 0;
-
-		if((jid = purple_xmlnode_get_attrib(streamhost, "jid")) &&
-				((zeroconf = purple_xmlnode_get_attrib(streamhost, "zeroconf")) ||
-				((host = purple_xmlnode_get_attrib(streamhost, "host")) &&
-				(port = purple_xmlnode_get_attrib(streamhost, "port")) &&
-				(portnum = atoi(port))))) {
-			/* ignore 0.0.0.0 */
-			if(purple_strequal(host, "0.0.0.0") == FALSE) {
-				JabberBytestreamsStreamhost *sh = g_new0(JabberBytestreamsStreamhost, 1);
-				sh->jid = g_strdup(jid);
-				sh->host = g_strdup(host);
-				sh->port = portnum;
-				sh->zeroconf = g_strdup(zeroconf);
-
-				/* If there were a lot of these, it'd be worthwhile to prepend and reverse. */
-				jsx->streamhosts = g_list_append(jsx->streamhosts, sh);
-			}
-		}
-	}
-
-	jabber_si_bytestreams_attempt_connect(xfer);
-}
-
-static void
-jabber_si_xfer_bytestreams_send_write_response_cb(GObject *source,
-                                                  GAsyncResult *result,
-                                                  gpointer user_data)
-{
-	PurpleXfer *xfer = PURPLE_XFER(user_data);
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	gsize bytes_written = 0;
-	GError *error = NULL;
-
-	if (!g_output_stream_write_all_finish(G_OUTPUT_STREAM(source), result,
-	                                      &bytes_written, &error)) {
-		if (error->code != G_IO_ERROR_CANCELLED) {
-			purple_xfer_cancel_remote(xfer);
-		}
-		g_clear_error(&error);
-	} else {
-		/* Before actually starting sending the file, we need to wait until the
-		 * recipient sends the IQ result with <streamhost-used/>
-		 */
-		purple_debug_info("jabber",
-		                  "SOCKS5 connection negotiation completed. Waiting "
-		                  "for IQ result to start file transfer.");
-	}
-
-	g_clear_pointer(&jsx->socks_buf, g_free);
-}
-
-static void
-jabber_si_xfer_bytestreams_send_read_request_cb(GObject *source,
-                                                GAsyncResult *result,
-                                                gpointer user_data)
-{
-	PurpleXfer *xfer = PURPLE_XFER(user_data);
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	gsize bytes_read = 0;
-	GError *error = NULL;
-	GOutputStream *output = NULL;
-	gsize bufsize;
-	gchar *dstaddr, *hash;
-	gchar *host;
-
-	purple_debug_info("jabber",
-	                  "in jabber_si_xfer_bytestreams_send_read_request_cb");
-
-	if (!g_input_stream_read_all_finish(G_INPUT_STREAM(source), result,
-	                                    &bytes_read, &error)) {
-		if (error->code != G_IO_ERROR_CANCELLED) {
-			purple_xfer_cancel_remote(xfer);
-		}
-		g_clear_error(&error);
-		return;
-	}
-
-	dstaddr = g_strdup_printf("%s%s@%s/%s%s", jsx->stream_id,
-			jsx->js->user->node, jsx->js->user->domain,
-			jsx->js->user->resource, purple_xfer_get_remote_user(xfer));
-
-	/* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */
-	hash = g_compute_checksum_for_string(G_CHECKSUM_SHA1, dstaddr, -1);
-
-	if (strncmp(hash, jsx->socks_buf + 5, 40) || jsx->socks_buf[45] != 0x00 ||
-	    jsx->socks_buf[46] != 0x00) {
-		if (jsx->socks_buf[45] != 0x00 || jsx->socks_buf[46] != 0x00) {
-			purple_debug_error("jabber",
-			                   "Got SOCKS5 BS conn with the wrong DST.PORT "
-			                   "(must be 0 - got[0x%x,0x%x]).",
-			                   jsx->socks_buf[45], jsx->socks_buf[46]);
-		} else {
-			purple_debug_error("jabber",
-			                   "Got SOCKS5 BS conn with the wrong DST.ADDR "
-			                   "(expected '%s' - got '%.40s').",
-			                   hash, jsx->socks_buf + 5);
-		}
-		purple_xfer_cancel_remote(xfer);
-		g_free(hash);
-		g_free(dstaddr);
-		return;
-	}
-
-	g_free(hash);
-	g_free(dstaddr);
-
-	g_free(jsx->socks_buf);
-	host = purple_network_get_my_ip_from_gio(
-	        G_SOCKET_CONNECTION(jsx->js->stream));
-
-	bufsize = 5 + strlen(host) + 2;
-	jsx->socks_buf = g_malloc(bufsize);
-
-	jsx->socks_buf[0] = 0x05;
-	jsx->socks_buf[1] = 0x00;
-	jsx->socks_buf[2] = 0x00;
-	jsx->socks_buf[3] = 0x03;
-	jsx->socks_buf[4] = strlen(host);
-	memcpy(jsx->socks_buf + 5, host, strlen(host));
-	jsx->socks_buf[5 + strlen(host)] = 0x00;
-	jsx->socks_buf[6 + strlen(host)] = 0x00;
-
-	output = g_io_stream_get_output_stream(
-	        G_IO_STREAM(jsx->local_streamhost_conn));
-	g_output_stream_write_all_async(
-	        output, jsx->socks_buf, bufsize, G_PRIORITY_DEFAULT,
-	        jsx->cancellable, jabber_si_xfer_bytestreams_send_write_response_cb,
-	        xfer);
-
-	g_free(host);
-}
-
-static void
-jabber_si_xfer_bytestreams_send_read_request_header_cb(GObject *source,
-                                                       GAsyncResult *result,
-                                                       gpointer user_data)
-{
-	GInputStream *input = G_INPUT_STREAM(source);
-	PurpleXfer *xfer = PURPLE_XFER(user_data);
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	gsize bytes_read = 0;
-	GError *error = NULL;
-
-	purple_debug_info(
-	        "jabber",
-	        "in jabber_si_xfer_bytestreams_send_read_request_header_cb");
-
-	if (!g_input_stream_read_all_finish(input, result, &bytes_read, &error)) {
-		if (error->code != G_IO_ERROR_CANCELLED) {
-			purple_xfer_cancel_remote(xfer);
-		}
-		g_clear_error(&error);
-		return;
-	}
-
-	if (jsx->socks_buf[0] != 0x05 || jsx->socks_buf[1] != 0x01 ||
-	    jsx->socks_buf[3] != 0x03 || jsx->socks_buf[4] != 40) {
-		purple_debug_info(
-		        "jabber",
-		        "Invalid socks5 conn req. header[0x%x,0x%x,0x%x,0x%x,0x%x]",
-		        jsx->socks_buf[0], jsx->socks_buf[1], jsx->socks_buf[2],
-		        jsx->socks_buf[3], jsx->socks_buf[4]);
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	/* Read DST.ADDR and the following 2-byte port number. */
-	purple_debug_info("jabber", "reading %u bytes for DST.ADDR + port num",
-	                  jsx->socks_buf[4] + 2);
-	g_input_stream_read_all_async(
-	        input, jsx->socks_buf + 5, jsx->socks_buf[4] + 2,
-	        G_PRIORITY_DEFAULT, jsx->cancellable,
-	        jabber_si_xfer_bytestreams_send_read_request_cb, xfer);
-}
-
-static void
-jabber_si_xfer_bytestreams_send_write_method_cb(GObject *source,
-                                                GAsyncResult *result,
-                                                gpointer user_data)
-{
-	PurpleXfer *xfer = PURPLE_XFER(user_data);
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	gsize bytes_written = 0;
-	GError *error = NULL;
-
-	if (!g_output_stream_write_all_finish(G_OUTPUT_STREAM(source), result,
-	                                      &bytes_written, &error)) {
-		if (error->code != G_IO_ERROR_CANCELLED) {
-			purple_xfer_cancel_remote(xfer);
-		}
-		g_clear_pointer(&jsx->socks_buf, g_free);
-		g_clear_error(&error);
-		return;
-	}
-
-	/* If we sent a "Success", wait for a response, otherwise give up and cancel */
-	if (jsx->socks_buf[1] == 0x00) {
-		GInputStream *input = g_io_stream_get_input_stream(
-		        G_IO_STREAM(jsx->local_streamhost_conn));
-
-		g_free(jsx->socks_buf);
-		/* Request is: Version, Command, Reserved, Address type, Address length,
-		 * Address (up to 255), 2-byte port */
-		jsx->socks_buf = g_malloc(5 + 255 + 2);
-		g_input_stream_read_all_async(
-		        input, jsx->socks_buf, 5, G_PRIORITY_DEFAULT, jsx->cancellable,
-		        jabber_si_xfer_bytestreams_send_read_request_header_cb, xfer);
-	} else {
-		purple_xfer_cancel_remote(xfer);
-	}
-}
-
-static void
-jabber_si_xfer_bytestreams_send_read_methods_cb(GObject *source,
-                                                GAsyncResult *result,
-                                                gpointer user_data)
-{
-	PurpleXfer *xfer = PURPLE_XFER(user_data);
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	gsize bytes_read = 0;
-	GError *error = NULL;
-	GOutputStream *output;
-	gboolean valid_method_found = FALSE;
-	gint i;
-
-	purple_debug_info("jabber",
-	                  "in jabber_si_xfer_bytestreams_send_read_methods_cb");
-
-	if (!g_input_stream_read_all_finish(G_INPUT_STREAM(source), result,
-	                                    &bytes_read, &error)) {
-		if (error->code != G_IO_ERROR_CANCELLED) {
-			purple_xfer_cancel_remote(xfer);
-		}
-		g_clear_error(&error);
-		return;
-	}
-
-	purple_debug_info("jabber", "going to test %u different methods",
-	                  jsx->socks_buf[1]);
-
-	for (i = 0; i < jsx->socks_buf[1]; i++) {
-		purple_debug_info("jabber", "testing %u", jsx->socks_buf[i + 2]);
-		if (jsx->socks_buf[i + 2] == 0x00) {
-			valid_method_found = TRUE;
-			break;
-		}
-	}
-
-	g_free(jsx->socks_buf);
-	jsx->socks_buf = g_malloc(2);
-	jsx->socks_buf[0] = 0x05;
-	jsx->socks_buf[1] = valid_method_found ? 0x00 : 0xFF;
-	output = g_io_stream_get_output_stream(
-	        G_IO_STREAM(jsx->local_streamhost_conn));
-	g_output_stream_write_all_async(
-	        output, jsx->socks_buf, 2, G_PRIORITY_DEFAULT, jsx->cancellable,
-	        jabber_si_xfer_bytestreams_send_write_method_cb, xfer);
-}
-
-static void
-jabber_si_xfer_bytestreams_send_read_version_cb(GObject *source,
-                                                GAsyncResult *result,
-                                                gpointer user_data)
-{
-	GInputStream *input = G_INPUT_STREAM(source);
-	PurpleXfer *xfer = PURPLE_XFER(user_data);
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	gsize bytes_read = 0;
-	GError *error = NULL;
-
-	purple_debug_info("jabber",
-	                  "in jabber_si_xfer_bytestreams_send_read_version_cb");
-
-	/* Try to read the SOCKS5 header */
-	if (!g_input_stream_read_all_finish(input, result, &bytes_read, &error)) {
-		if (error->code != G_IO_ERROR_CANCELLED) {
-			purple_xfer_cancel_remote(xfer);
-		}
-		g_clear_error(&error);
-		return;
-	}
-
-	purple_debug_info("jabber", "checking to make sure we're socks FIVE");
-	if (jsx->socks_buf[0] != 0x05) {
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	/* Number of methods is given in second byte. */
-	purple_debug_info("jabber", "reading %u bytes for auth methods",
-	                  jsx->socks_buf[1]);
-	g_input_stream_read_all_async(
-	        input, jsx->socks_buf + 2, jsx->socks_buf[1], G_PRIORITY_DEFAULT,
-	        jsx->cancellable, jabber_si_xfer_bytestreams_send_read_methods_cb,
-	        xfer);
-}
-
-static gint
-jabber_si_compare_jid(gconstpointer a, gconstpointer b)
-{
-	const JabberBytestreamsStreamhost *sh = a;
-
-	if(!a)
-		return -1;
-
-	return strcmp(sh->jid, (char *)b);
-}
-
-static void
-jabber_si_xfer_bytestreams_send_connected_cb(G_GNUC_UNUSED GSocketService *service,
-                                             GSocketConnection *connection,
-                                             GObject *source_object,
-                                             G_GNUC_UNUSED gpointer data)
-{
-	PurpleXfer *xfer = PURPLE_XFER(source_object);
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	GInputStream *input = NULL;
-
-	purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_connected_cb\n");
-
-	jsx->local_streamhost_conn = g_object_ref(connection);
-	g_socket_service_stop(jsx->service);
-	g_clear_object(&jsx->service);
-
-	/* Initial message is: Version, Method count, up to 255 methods. */
-	jsx->socks_buf = g_malloc(2 + 255);
-	input = g_io_stream_get_input_stream(
-	        G_IO_STREAM(jsx->local_streamhost_conn));
-	g_input_stream_read_all_async(
-	        input, jsx->socks_buf, 2, G_PRIORITY_DEFAULT, jsx->cancellable,
-	        jabber_si_xfer_bytestreams_send_read_version_cb, xfer);
-}
-
-static void
-jabber_si_connect_proxy_cb(JabberStream *js, const char *from,
-                           JabberIqType type, G_GNUC_UNUSED const char *id,
-                           PurpleXmlNode *packet, gpointer data)
-{
-	PurpleXfer *xfer = data;
-	JabberSIXfer *jsx;
-	PurpleXmlNode *query, *streamhost_used;
-	const char *jid;
-	GList *matched;
-
-	/* TODO: This need to send errors if we don't see what we're looking for */
-
-	/* Make sure that the xfer is actually still valid and we're not just receiving an old iq response */
-	if (!g_list_find(js->file_transfers, xfer)) {
-		purple_debug_error("jabber", "Got bytestreams response for no longer existing xfer (%p)\n", xfer);
-		return;
-	}
-
-	jsx = JABBER_SI_XFER(xfer);
-
-	/* In the case of a direct file transfer, this is expected to return */
-	if(!jsx)
-		return;
-
-	if(type != JABBER_IQ_RESULT) {
-		purple_debug_info("jabber",
-			    "jabber_si_xfer_connect_proxy_cb: type = error\n");
-		/* if IBB is available, open IBB session */
-		purple_debug_info("jabber",
-			"jabber_si_xfer_connect_proxy_cb: got error, method: %d\n",
-			jsx->stream_method);
-		if (jsx->stream_method & STREAM_METHOD_IBB) {
-			/* if we previously tried bytestreams, we need to disable it. */
-			if(jsx->stream_method & STREAM_METHOD_BYTESTREAMS) {
-				jsx->stream_method &= ~STREAM_METHOD_BYTESTREAMS;
-			}
-
-			purple_debug_info("jabber", "IBB is possible, try it\n");
-			/* if we are the sender and haven't already opened an IBB
-			  session, do so now (we might already have failed to open
-			  the bytestream proxy ourselves when receiving this <iq/> */
-			if (purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_SEND
-				&& !jsx->ibb_session) {
-				jabber_si_xfer_ibb_send_init(js, xfer);
-			} else {
-				jsx->ibb_timeout_handle = g_timeout_add_seconds(30,
-					jabber_si_bytestreams_ibb_timeout_cb, xfer);
-			}
-			/* if we are receiver, just wait for IBB open stanza, callback
-			  is already set up */
-		} else {
-			purple_xfer_cancel_remote(xfer);
-		}
-		return;
-	}
-
-	if (!from)
-		return;
-
-	if(!(query = purple_xmlnode_get_child(packet, "query")))
-		return;
-
-	if(!(streamhost_used = purple_xmlnode_get_child(query, "streamhost-used")))
-		return;
-
-	if(!(jid = purple_xmlnode_get_attrib(streamhost_used, "jid")))
-		return;
-
-	purple_debug_info("jabber", "jabber_si_connect_proxy_cb() will be looking at jsx %p: jsx->streamhosts is %p and jid is %s\n",
-					  jsx, jsx->streamhosts, jid);
-
-	if(!(matched = g_list_find_custom(jsx->streamhosts, jid, jabber_si_compare_jid)))
-	{
-		gchar *my_jid = g_strdup_printf("%s@%s/%s", jsx->js->user->node,
-			jsx->js->user->domain, jsx->js->user->resource);
-		if (purple_strequal(jid, my_jid)) {
-			GSocket *sock = NULL;
-			gint fd = -1;
-			purple_debug_info("jabber", "Got local SOCKS5 streamhost-used.\n");
-			sock = g_socket_connection_get_socket(jsx->local_streamhost_conn);
-			fd = g_socket_get_fd(sock);
-			_purple_network_set_common_socket_flags(fd);
-			purple_xfer_start(xfer, fd, NULL, -1);
-		} else {
-			/* if available, try to revert to IBB... */
-			if (jsx->stream_method & STREAM_METHOD_IBB) {
-				if(jsx->stream_method & STREAM_METHOD_BYTESTREAMS) {
-					jsx->stream_method &= ~STREAM_METHOD_BYTESTREAMS;
-				}
-
-				purple_debug_info("jabber",
-					"jabber_si_connect_proxy_cb: trying to revert to IBB\n");
-				if (purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_SEND) {
-					jabber_si_xfer_ibb_send_init(jsx->js, xfer);
-				} else {
-					jsx->ibb_timeout_handle = g_timeout_add_seconds(30,
-						jabber_si_bytestreams_ibb_timeout_cb, xfer);
-				}
-				/* if we are the receiver, we are already set up...*/
-			} else {
-				purple_debug_info("jabber",
-					"streamhost-used does not match any proxy that was offered to target\n");
-				purple_xfer_cancel_local(xfer);
-			}
-		}
-		g_free(my_jid);
-		return;
-	}
-
-	/* Clean up the local streamhost - it isn't going to be used.*/
-	g_clear_object(&jsx->local_streamhost_conn);
-	if (jsx->service) {
-		g_socket_service_stop(jsx->service);
-		g_clear_object(&jsx->service);
-	}
-
-	jsx->streamhosts = g_list_remove_link(jsx->streamhosts, matched);
-	g_list_free_full(jsx->streamhosts, (GDestroyNotify)jabber_bytestreams_streamhost_free);
-
-	jsx->streamhosts = matched;
-
-	jabber_si_bytestreams_attempt_connect(xfer);
-}
-
-static void
-jabber_si_xfer_bytestreams_send_local_info(PurpleXfer *xfer, GList *local_ips)
-{
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	JabberIq *iq;
-	PurpleXmlNode *query, *streamhost;
-	char port[6];
-	GList *tmp;
-	JabberBytestreamsStreamhost *sh, *sh2;
-	int streamhost_count = 0;
-
-	iq = jabber_iq_new_query(jsx->js, JABBER_IQ_SET, NS_BYTESTREAMS);
-	purple_xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
-	query = purple_xmlnode_get_child(iq->node, "query");
-
-	purple_xmlnode_set_attrib(query, "sid", jsx->stream_id);
-
-	/* If we successfully started listening locally */
-	if (local_ips) {
-		gchar *jid;
-
-		jid = g_strdup_printf("%s@%s/%s", jsx->js->user->node,
-			jsx->js->user->domain, jsx->js->user->resource);
-		g_snprintf(port, sizeof(port), "%hu", purple_xfer_get_local_port(xfer));
-
-		/* Include the localhost's IPs (for in-network transfers) */
-		while (local_ips) {
-			gchar *local_ip = local_ips->data;
-			streamhost_count++;
-			streamhost = purple_xmlnode_new_child(query, "streamhost");
-			purple_xmlnode_set_attrib(streamhost, "jid", jid);
-			purple_xmlnode_set_attrib(streamhost, "host", local_ip);
-			purple_xmlnode_set_attrib(streamhost, "port", port);
-			g_free(local_ip);
-			local_ips = g_list_delete_link(local_ips, local_ips);
-		}
-
-		g_free(jid);
-	}
-
-	for (tmp = jsx->js->bs_proxies; tmp; tmp = tmp->next) {
-		sh = tmp->data;
-
-		/* TODO: deal with zeroconf proxies */
-
-		if (!sh->jid) {
-			continue;
-		} else if (!sh->host) {
-			continue;
-		} else if (sh->port <= 0) {
-			continue;
-		} else if (g_list_find_custom(jsx->streamhosts, sh->jid,
-		                              jabber_si_compare_jid) != NULL) {
-			continue;
-		}
-
-		streamhost_count++;
-		streamhost = purple_xmlnode_new_child(query, "streamhost");
-		purple_xmlnode_set_attrib(streamhost, "jid", sh->jid);
-		purple_xmlnode_set_attrib(streamhost, "host", sh->host);
-		g_snprintf(port, sizeof(port), "%hu", sh->port);
-		purple_xmlnode_set_attrib(streamhost, "port", port);
-
-		sh2 = g_new0(JabberBytestreamsStreamhost, 1);
-		sh2->jid = g_strdup(sh->jid);
-		sh2->host = g_strdup(sh->host);
-		/*sh2->zeroconf = g_strdup(sh->zeroconf);*/
-		sh2->port = sh->port;
-
-		jsx->streamhosts = g_list_prepend(jsx->streamhosts, sh2);
-	}
-
-	/* We have no way of transferring, cancel the transfer */
-	if (streamhost_count == 0) {
-		jabber_iq_free(iq);
-
-		/* if available, revert to IBB */
-		if (jsx->stream_method & STREAM_METHOD_IBB) {
-			if(jsx->stream_method & STREAM_METHOD_BYTESTREAMS) {
-				jsx->stream_method &= ~STREAM_METHOD_BYTESTREAMS;
-			}
-			purple_debug_info("jabber", "jabber_si_xfer_bytestreams_send_local_"
-			                            "info: trying to revert to IBB\n");
-			if (purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_SEND) {
-				/* if we are the sender, init the IBB session... */
-				jabber_si_xfer_ibb_send_init(jsx->js, xfer);
-			} else {
-				jsx->ibb_timeout_handle = g_timeout_add_seconds(30,
-					jabber_si_bytestreams_ibb_timeout_cb, xfer);
-			}
-			/* if we are the receiver, we should just wait... the IBB open
-			  handler has already been set up... */
-		} else {
-			/* We should probably notify the target,
-			  but this really shouldn't ever happen */
-			purple_xfer_cancel_local(xfer);
-		}
-
-		return;
-	}
-
-	jabber_iq_set_callback(iq, jabber_si_connect_proxy_cb, xfer);
-
-	jabber_iq_send(iq);
-}
-
-static void
-jabber_si_xfer_bytestreams_send_init(PurpleXfer *xfer)
-{
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	PurpleProxyType proxy_type;
-	GList *local_ips = NULL;
-
-	/* TODO: This should probably be done with an account option instead of
-	 *       piggy-backing on the TOR proxy type. */
-	proxy_type = purple_proxy_info_get_proxy_type(
-	        purple_proxy_get_setup(purple_connection_get_account(jsx->js->gc)));
-	if (proxy_type == PURPLE_PROXY_TYPE_TOR) {
-		purple_debug_info("jabber", "Skipping attempting local streamhost.\n");
-		jsx->service = NULL;
-	} else {
-		guint16 port = 0;
-		GError *error = NULL;
-		jsx->service = g_socket_service_new();
-		port = purple_socket_listener_add_any_inet_port(
-		        G_SOCKET_LISTENER(jsx->service), G_OBJECT(xfer), &error);
-		if (port != 0) {
-			purple_xfer_set_local_port(xfer, port);
-		} else {
-			purple_debug_error("jabber",
-			                   "Unable to create streamhost socket listener: "
-			                   "%s. Trying proxy instead.",
-			                   error->message);
-			g_error_free(error);
-			g_clear_object(&jsx->service);
-		}
-	}
-
-	if (jsx->service) {
-		gchar *public_ip;
-
-		/* Include the public IP (assuming there is a port mapped somehow) */
-		public_ip = purple_network_get_my_ip_from_gio(
-		        G_SOCKET_CONNECTION(jsx->js->stream));
-		if (!purple_strequal(public_ip, "0.0.0.0")) {
-			local_ips = g_list_append(local_ips, public_ip);
-		} else {
-			g_free(public_ip);
-		}
-
-		g_signal_connect(
-		        G_OBJECT(jsx->service), "incoming",
-		        G_CALLBACK(jabber_si_xfer_bytestreams_send_connected_cb), NULL);
-	}
-
-	jabber_si_xfer_bytestreams_send_local_info(xfer, local_ips);
-}
-
-static void
-jabber_si_xfer_ibb_error_cb(JabberIBBSession *sess)
-{
-	PurpleXfer *xfer = (PurpleXfer *) jabber_ibb_session_get_user_data(sess);
-
-	purple_debug_error("jabber", "an error occurred during IBB file transfer\n");
-	purple_xfer_cancel_remote(xfer);
-}
-
-static void
-jabber_si_xfer_ibb_closed_cb(JabberIBBSession *sess)
-{
-	PurpleXfer *xfer = (PurpleXfer *) jabber_ibb_session_get_user_data(sess);
-
-	purple_debug_info("jabber", "the remote user closed the transfer\n");
-	if (purple_xfer_get_bytes_remaining(xfer) > 0) {
-		purple_xfer_cancel_remote(xfer);
-	} else {
-		purple_xfer_set_completed(xfer, TRUE);
-		purple_xfer_end(xfer);
-	}
-}
-
-static void
-jabber_si_xfer_ibb_recv_data_cb(JabberIBBSession *sess, gpointer data,
-	gsize size)
-{
-	PurpleXfer *xfer = (PurpleXfer *) jabber_ibb_session_get_user_data(sess);
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-
-	if ((goffset)size <= purple_xfer_get_bytes_remaining(xfer)) {
-		purple_debug_info("jabber", "about to write %" G_GSIZE_FORMAT " bytes from IBB stream\n",
-			size);
-		purple_circular_buffer_append(jsx->ibb_buffer, data, size);
-		purple_xfer_protocol_ready(xfer);
-	} else {
-		/* trying to write past size of file transfers negotiated size,
-		  reject transfer to protect against malicious behaviour */
-		purple_debug_error("jabber",
-			"IBB file transfer send more data than expected\n");
-		purple_xfer_cancel_remote(xfer);
-	}
-
-}
-
-static gssize
-jabber_si_xfer_ibb_read(PurpleXfer *xfer, guchar **out_buffer, size_t buf_size)
-{
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	guchar *buffer;
-	gsize size;
-	gsize tmp;
-
-	if(jsx->stream_method & STREAM_METHOD_BYTESTREAMS) {
-		return PURPLE_XFER_CLASS(jabber_si_xfer_parent_class)->read(xfer, out_buffer, buf_size);
-	}
-
-	size = purple_circular_buffer_get_used(jsx->ibb_buffer);
-
-	*out_buffer = buffer = g_malloc(size);
-	while ((tmp = purple_circular_buffer_get_max_read(jsx->ibb_buffer))) {
-		const gchar *output = purple_circular_buffer_get_output(jsx->ibb_buffer);
-		memcpy(buffer, output, tmp);
-		buffer += tmp;
-		purple_circular_buffer_mark_read(jsx->ibb_buffer, tmp);
-	}
-
-	return size;
-}
-
-static gboolean
-jabber_si_xfer_ibb_open_cb(JabberStream *js, const char *who, const char *id,
-                           PurpleXmlNode *open)
-{
-	const gchar *sid = purple_xmlnode_get_attrib(open, "sid");
-	PurpleXfer *xfer = jabber_si_xfer_find(js, sid, who);
-
-	if (xfer) {
-		JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-		JabberIBBSession *sess =
-			jabber_ibb_session_create_from_xmlnode(js, who, id, open, xfer);
-
-		jabber_si_bytestreams_ibb_timeout_remove(jsx);
-
-		if (sess) {
-			/* setup callbacks here...*/
-			jabber_ibb_session_set_data_received_callback(sess,
-				jabber_si_xfer_ibb_recv_data_cb);
-			jabber_ibb_session_set_closed_callback(sess,
-				jabber_si_xfer_ibb_closed_cb);
-			jabber_ibb_session_set_error_callback(sess,
-				jabber_si_xfer_ibb_error_cb);
-
-			jsx->ibb_session = sess;
-			/* we handle up to block-size bytes of decoded data, to handle
-			 clients interpreting the block-size attribute as that
-			 (see also remark in ibb.c) */
-			jsx->ibb_buffer =
-				purple_circular_buffer_new(jabber_ibb_session_get_block_size(sess));
-
-			/* start the transfer */
-			purple_xfer_start(xfer, -1, NULL, 0);
-			return TRUE;
-		} else {
-			/* failed to create IBB session */
-			purple_debug_error("jabber", "failed to create IBB session\n");
-			purple_xfer_cancel_remote(xfer);
-			return FALSE;
-		}
-	} else {
-		/* we got an IBB <open/> for an unknown file transfer, pass along... */
-		purple_debug_info("jabber",
-			"IBB open did not match any SI file transfer\n");
-		return FALSE;
-	}
-}
-
-static gssize
-jabber_si_xfer_ibb_write(PurpleXfer *xfer, const guchar *buffer, size_t len)
-{
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	JabberIBBSession *sess = jsx->ibb_session;
-	gsize packet_size;
-
-	if(jsx->stream_method & STREAM_METHOD_BYTESTREAMS) {
-		purple_debug_error("jabber", "falling back to raw socket\n");
-		return PURPLE_XFER_CLASS(jabber_si_xfer_parent_class)->write(xfer, buffer, len);
-	}
-
-	packet_size = MIN(len, jabber_ibb_session_get_max_data_size(sess));
-
-	jabber_ibb_session_send_data(sess, buffer, packet_size);
-
-	return packet_size;
-}
-
-static void
-jabber_si_xfer_ibb_sent_cb(JabberIBBSession *sess)
-{
-	PurpleXfer *xfer = (PurpleXfer *) jabber_ibb_session_get_user_data(sess);
-	goffset remaining = purple_xfer_get_bytes_remaining(xfer);
-
-	if (remaining == 0) {
-		/* close the session */
-		jabber_ibb_session_close(sess);
-		purple_xfer_set_completed(xfer, TRUE);
-		purple_xfer_end(xfer);
-	} else {
-		/* send more... */
-		purple_xfer_protocol_ready(xfer);
-	}
-}
-
-static void
-jabber_si_xfer_ibb_opened_cb(JabberIBBSession *sess)
-{
-	PurpleXfer *xfer = (PurpleXfer *) jabber_ibb_session_get_user_data(sess);
-
-	if (jabber_ibb_session_get_state(sess) == JABBER_IBB_SESSION_OPENED) {
-		purple_xfer_start(xfer, -1, NULL, 0);
-		purple_xfer_protocol_ready(xfer);
-	} else {
-		/* error */
-		purple_xfer_end(xfer);
-	}
-}
-
-static void
-jabber_si_xfer_ibb_send_init(JabberStream *js, PurpleXfer *xfer)
-{
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-
-	jsx->ibb_session = jabber_ibb_session_create(js, jsx->stream_id,
-		purple_xfer_get_remote_user(xfer), xfer);
-
-	if (jsx->ibb_session) {
-		/* should set callbacks here... */
-		jabber_ibb_session_set_opened_callback(jsx->ibb_session,
-			jabber_si_xfer_ibb_opened_cb);
-		jabber_ibb_session_set_data_sent_callback(jsx->ibb_session,
-			jabber_si_xfer_ibb_sent_cb);
-		jabber_ibb_session_set_closed_callback(jsx->ibb_session,
-			jabber_si_xfer_ibb_closed_cb);
-		jabber_ibb_session_set_error_callback(jsx->ibb_session,
-			jabber_si_xfer_ibb_error_cb);
-
-		jsx->ibb_buffer =
-			purple_circular_buffer_new(jabber_ibb_session_get_max_data_size(jsx->ibb_session));
-
-		/* open the IBB session */
-		jabber_ibb_session_open(jsx->ibb_session);
-
-	} else {
-		/* failed to create IBB session */
-		purple_debug_error("jabber",
-			"failed to initiate IBB session for file transfer\n");
-		purple_xfer_cancel_local(xfer);
-	}
-}
-
-static void
-jabber_si_xfer_send_method_cb(JabberStream *js, G_GNUC_UNUSED const char *from,
-                              G_GNUC_UNUSED JabberIqType type,
-                              G_GNUC_UNUSED const char *id,
-                              PurpleXmlNode *packet, gpointer data)
-{
-	PurpleXfer *xfer = data;
-	PurpleXmlNode *si, *feature, *x, *field, *value;
-	gboolean found_method = FALSE;
-
-	if(!(si = purple_xmlnode_get_child_with_namespace(packet, "si", "http://jabber.org/protocol/si"))) {
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	if(!(feature = purple_xmlnode_get_child_with_namespace(si, "feature", "http://jabber.org/protocol/feature-neg"))) {
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	if(!(x = purple_xmlnode_get_child_with_namespace(feature, "x", "jabber:x:data"))) {
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	for(field = purple_xmlnode_get_child(x, "field"); field; field = purple_xmlnode_get_next_twin(field)) {
-		const char *var = purple_xmlnode_get_attrib(field, "var");
-		JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-
-		if(purple_strequal(var, "stream-method")) {
-			if((value = purple_xmlnode_get_child(field, "value"))) {
-				char *val = purple_xmlnode_get_data(value);
-				if(purple_strequal(val, NS_BYTESTREAMS)) {
-					jabber_si_xfer_bytestreams_send_init(xfer);
-					jsx->stream_method |= STREAM_METHOD_BYTESTREAMS;
-					found_method = TRUE;
-				} else if (purple_strequal(val, NS_IBB)) {
-					jsx->stream_method |= STREAM_METHOD_IBB;
-					if (!found_method) {
-						/* we haven't tried to init a bytestream session, yet
-						  start IBB right away... */
-						jabber_si_xfer_ibb_send_init(js, xfer);
-						found_method = TRUE;
-					}
-				}
-				g_free(val);
-			}
-		}
-	}
-
-	if (!found_method) {
-		purple_xfer_cancel_remote(xfer);
-	}
-
-}
-
-static void jabber_si_xfer_send_request(PurpleXfer *xfer)
-{
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	JabberIq *iq;
-	PurpleXmlNode *si, *file, *feature, *x, *field, *option, *value;
-	char buf[32];
-#if ENABLE_FT_THUMBNAILS
-	gconstpointer thumb;
-	gsize thumb_size;
-
-	purple_xfer_prepare_thumbnail(xfer, "jpeg,png");
-#endif
-	purple_xfer_set_filename(xfer, g_path_get_basename(purple_xfer_get_local_filename(xfer)));
-
-	iq = jabber_iq_new(jsx->js, JABBER_IQ_SET);
-	purple_xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
-	si = purple_xmlnode_new_child(iq->node, "si");
-	purple_xmlnode_set_namespace(si, "http://jabber.org/protocol/si");
-	jsx->stream_id = jabber_get_next_id(jsx->js);
-	purple_xmlnode_set_attrib(si, "id", jsx->stream_id);
-	purple_xmlnode_set_attrib(si, "profile", NS_SI_FILE_TRANSFER);
-
-	file = purple_xmlnode_new_child(si, "file");
-	purple_xmlnode_set_namespace(file, NS_SI_FILE_TRANSFER);
-	purple_xmlnode_set_attrib(file, "name", purple_xfer_get_filename(xfer));
-	g_snprintf(buf, sizeof(buf), "%" G_GOFFSET_FORMAT, purple_xfer_get_size(xfer));
-	purple_xmlnode_set_attrib(file, "size", buf);
-	/* maybe later we'll do hash and date attribs */
-
-#if ENABLE_FT_THUMBNAILS
-	/* add thumbnail, if appropriate */
-	if ((thumb = purple_xfer_get_thumbnail(xfer, &thumb_size))) {
-		const gchar *mimetype = purple_xfer_get_thumbnail_mimetype(xfer);
-		JabberData *thumbnail_data =
-			jabber_data_create_from_data(thumb, thumb_size,
-				mimetype, TRUE, jsx->js);
-		PurpleXmlNode *thumbnail = purple_xmlnode_new_child(file, "thumbnail");
-		purple_xmlnode_set_namespace(thumbnail, NS_THUMBS);
-		purple_xmlnode_set_attrib(thumbnail, "cid",
-			jabber_data_get_cid(thumbnail_data));
-		purple_xmlnode_set_attrib(thumbnail, "mime-type", mimetype);
-		/* cache data */
-		jabber_data_associate_local(thumbnail_data, NULL);
-	}
-#endif
-
-	feature = purple_xmlnode_new_child(si, "feature");
-	purple_xmlnode_set_namespace(feature, "http://jabber.org/protocol/feature-neg");
-	x = purple_xmlnode_new_child(feature, "x");
-	purple_xmlnode_set_namespace(x, "jabber:x:data");
-	purple_xmlnode_set_attrib(x, "type", "form");
-	field = purple_xmlnode_new_child(x, "field");
-	purple_xmlnode_set_attrib(field, "var", "stream-method");
-	purple_xmlnode_set_attrib(field, "type", "list-single");
-	/* maybe we should add an option to always skip bytestreams for people
-		behind troublesome firewalls */
-	option = purple_xmlnode_new_child(field, "option");
-	value = purple_xmlnode_new_child(option, "value");
-	purple_xmlnode_insert_data(value, NS_BYTESTREAMS, -1);
-	option = purple_xmlnode_new_child(field, "option");
-	value = purple_xmlnode_new_child(option, "value");
-	purple_xmlnode_insert_data(value, NS_IBB, -1);
-
-	jabber_iq_set_callback(iq, jabber_si_xfer_send_method_cb, xfer);
-
-	/* Store the IQ id so that we can cancel the callback */
-	g_free(jsx->iq_id);
-	jsx->iq_id = g_strdup(iq->id);
-
-	jabber_iq_send(iq);
-}
-
-/*
- * These four functions should only be called from the PurpleXfer functions
- * (typically purple_xfer_cancel_(remote|local), purple_xfer_end, or
- * purple_xfer_request_denied.
- */
-static void jabber_si_xfer_cancel_send(PurpleXfer *xfer)
-{
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-
-	/* if there is an IBB session active, send close on that */
-	if (jsx->ibb_session) {
-		jabber_ibb_session_close(jsx->ibb_session);
-	}
-	purple_debug_info("jabber", "in jabber_si_xfer_cancel_send\n");
-
-	g_cancellable_cancel(jsx->cancellable);
-}
-
-
-static void jabber_si_xfer_request_denied(PurpleXfer *xfer)
-{
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	JabberStream *js = jsx->js;
-
-	/*
-	 * TODO: It's probably an error if jsx->iq_id == NULL. g_return_if_fail
-	 * might be warranted.
-	 */
-	if (jsx->iq_id && !jsx->accepted) {
-		JabberIq *iq;
-		PurpleXmlNode *error, *child;
-		iq = jabber_iq_new(js, JABBER_IQ_ERROR);
-		purple_xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
-		jabber_iq_set_id(iq, jsx->iq_id);
-
-		error = purple_xmlnode_new_child(iq->node, "error");
-		purple_xmlnode_set_attrib(error, "type", "cancel");
-		child = purple_xmlnode_new_child(error, "forbidden");
-		purple_xmlnode_set_namespace(child, NS_XMPP_STANZAS);
-		child = purple_xmlnode_new_child(error, "text");
-		purple_xmlnode_set_namespace(child, NS_XMPP_STANZAS);
-		purple_xmlnode_insert_data(child, "Offer Declined", -1);
-
-		jabber_iq_send(iq);
-	}
-
-	purple_debug_info("jabber", "in jabber_si_xfer_request_denied\n");
-}
-
-
-static void jabber_si_xfer_cancel_recv(PurpleXfer *xfer)
-{
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	/* if there is an IBB session active, send close */
-	if (jsx->ibb_session) {
-		jabber_ibb_session_close(jsx->ibb_session);
-	}
-	purple_debug_info("jabber", "in jabber_si_xfer_cancel_recv\n");
-
-	g_cancellable_cancel(jsx->cancellable);
-}
-
-
-static void jabber_si_xfer_send_disco_cb(JabberStream *js, const char *who,
-		JabberCapabilities capabilities, gpointer data)
-{
-	PurpleXfer *xfer = PURPLE_XFER(data);
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-
-	if (capabilities & JABBER_CAP_IBB) {
-		purple_debug_info("jabber",
-			"jabber_si_xfer_send_disco_cb: remote JID supports IBB\n");
-		jsx->stream_method |= STREAM_METHOD_IBB;
-	}
-
-	if (capabilities & JABBER_CAP_SI_FILE_XFER) {
-		jabber_si_xfer_send_request(xfer);
-	} else {
-		char *msg = g_strdup_printf(_("Unable to send file to %s, user does not support file transfers"), who);
-		purple_notify_error(js->gc, _("File Send Failed"),
-			_("File Send Failed"), msg,
-			purple_request_cpar_from_connection(js->gc));
-		g_free(msg);
-		purple_xfer_cancel_local(xfer);
-	}
-}
-
-static void
-resource_select_cancel_cb(PurpleXfer *xfer,
-                          G_GNUC_UNUSED PurpleRequestPage *page)
-{
-	purple_xfer_cancel_local(xfer);
-}
-
-static void do_transfer_send(PurpleXfer *xfer, const char *resource)
-{
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	char **who_v = g_strsplit(purple_xfer_get_remote_user(xfer), "/", 2);
-	char *who;
-	JabberBuddy *jb;
-	JabberBuddyResource *jbr = NULL;
-
-	jb = jabber_buddy_find(jsx->js, who_v[0], FALSE);
-	if (jb) {
-		jbr = jabber_buddy_find_resource(jb, resource);
-	}
-
-	who = g_strdup_printf("%s/%s", who_v[0], resource);
-	g_strfreev(who_v);
-	purple_xfer_set_remote_user(xfer, who);
-
-	if (jbr && jabber_resource_know_capabilities(jbr)) {
-		char *msg;
-
-		if (jabber_resource_has_capability(jbr, NS_IBB))
-			jsx->stream_method |= STREAM_METHOD_IBB;
-		if (jabber_resource_has_capability(jbr, NS_SI_FILE_TRANSFER)) {
-			jabber_si_xfer_send_request(xfer);
-			g_free(who);
-			return;
-		}
-
-		msg = g_strdup_printf(_("Unable to send file to %s, user does not support file transfers"), who);
-		purple_notify_error(jsx->js->gc, _("File Send Failed"),
-			_("File Send Failed"), msg,
-			purple_request_cpar_from_connection(jsx->js->gc));
-		g_free(msg);
-		purple_xfer_cancel_local(xfer);
-	} else {
-		jabber_disco_info_do(jsx->js, who,
-				jabber_si_xfer_send_disco_cb, xfer);
-	}
-
-	g_free(who);
-}
-
-static void
-resource_select_ok_cb(PurpleXfer *xfer, PurpleRequestPage *page)
-{
-	const char *selected_label = purple_request_page_get_choice(page, "resource");
-
-	do_transfer_send(xfer, selected_label);
-}
-
-static void jabber_si_xfer_xfer_init(PurpleXfer *xfer)
-{
-	JabberSIXfer *jsx = JABBER_SI_XFER(xfer);
-	JabberIq *iq;
-	if(purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_SEND) {
-		JabberBuddy *jb;
-		JabberBuddyResource *jbr = NULL;
-		char *resource;
-		GList *resources = NULL;
-
-		if(NULL != (resource = jabber_get_resource(purple_xfer_get_remote_user(xfer)))) {
-			/* they've specified a resource, no need to ask or
-			 * default or anything, just do it */
-
-			do_transfer_send(xfer, resource);
-			g_free(resource);
-			return;
-		}
-
-		jb = jabber_buddy_find(jsx->js, purple_xfer_get_remote_user(xfer), TRUE);
-
-		if (jb) {
-			GList *l;
-
-			for (l = jb->resources ; l ; l = g_list_next(l)) {
-				jbr = l->data;
-
-				if (!jabber_resource_know_capabilities(jbr) ||
-				    (jabber_resource_has_capability(jbr, NS_SI_FILE_TRANSFER)
-				     && (jabber_resource_has_capability(jbr, NS_BYTESTREAMS)
-				         || jabber_resource_has_capability(jbr, NS_IBB)))) {
-					resources = g_list_append(resources, jbr);
-				}
-			}
-		}
-
-		if (!resources) {
-			/* no resources online, we're trying to send to someone
-			 * whose presence we're not subscribed to, or
-			 * someone who is offline.  Let's inform the user */
-			char *msg;
-
-			if(!jb) {
-				msg = g_strdup_printf(_("Unable to send file to %s, invalid JID"), purple_xfer_get_remote_user(xfer));
-			} else if(jb->subscription & JABBER_SUB_TO) {
-				msg = g_strdup_printf(_("Unable to send file to %s, user is not online"), purple_xfer_get_remote_user(xfer));
-			} else {
-				msg = g_strdup_printf(_("Unable to send file to %s, not subscribed to user presence"), purple_xfer_get_remote_user(xfer));
-			}
-
-			purple_notify_error(jsx->js->gc, _("File Send Failed"),
-				_("File Send Failed"), msg,
-				purple_request_cpar_from_connection(jsx->js->gc));
-			g_free(msg);
-		} else if (g_list_length(resources) == 1) {
-			/* only 1 resource online (probably our most common case)
-			 * so no need to ask who to send to */
-			jbr = resources->data;
-			do_transfer_send(xfer, jbr->name);
-		} else {
-			/* we've got multiple resources, we need to pick one to send to */
-			GList *l;
-			PurpleRequestPage *page = NULL;
-			PurpleRequestField *field = NULL;
-			PurpleRequestFieldChoice *choice = NULL;
-			PurpleRequestGroup *group = NULL;
-			char *msg = NULL;
-
-			field = purple_request_field_choice_new("resource", _("Resource"), 0);
-			choice = PURPLE_REQUEST_FIELD_CHOICE(field);
-			for(l = resources; l; l = l->next) {
-				jbr = l->data;
-				purple_request_field_choice_add_full(choice, jbr->name,
-				                                     g_strdup(jbr->name),
-				                                     g_free);
-			}
-
-			group = purple_request_group_new(NULL);
-			purple_request_group_add_field(group, field);
-
-			page = purple_request_page_new();
-			purple_request_page_add_group(page, group);
-
-			msg = g_strdup_printf(_("Please select the resource of %s to "
-			                        "which you would like to send a file"),
-			                      purple_xfer_get_remote_user(xfer));
-
-			purple_request_fields(jsx->js->gc, _("Select a Resource"), msg, NULL, page,
-					_("Send File"), G_CALLBACK(resource_select_ok_cb), _("Cancel"), G_CALLBACK(resource_select_cancel_cb),
-					purple_request_cpar_from_connection(jsx->js->gc), xfer);
-
-			g_free(msg);
-		}
-
-		g_list_free(resources);
-	} else {
-		PurpleXmlNode *si, *feature, *x, *field, *value;
-
-		iq = jabber_iq_new(jsx->js, JABBER_IQ_RESULT);
-		purple_xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
-		if(jsx->iq_id)
-			jabber_iq_set_id(iq, jsx->iq_id);
-		else
-			purple_debug_error("jabber", "Sending SI result with new IQ id.\n");
-
-		jsx->accepted = TRUE;
-
-		si = purple_xmlnode_new_child(iq->node, "si");
-		purple_xmlnode_set_namespace(si, "http://jabber.org/protocol/si");
-
-		feature = purple_xmlnode_new_child(si, "feature");
-		purple_xmlnode_set_namespace(feature, "http://jabber.org/protocol/feature-neg");
-
-		x = purple_xmlnode_new_child(feature, "x");
-		purple_xmlnode_set_namespace(x, "jabber:x:data");
-		purple_xmlnode_set_attrib(x, "type", "submit");
-		field = purple_xmlnode_new_child(x, "field");
-		purple_xmlnode_set_attrib(field, "var", "stream-method");
-
-		/* we should maybe "remember" if bytestreams has failed before (in the
-			same session) with this JID, and only present IBB as an option to
-			avoid unnecessary timeout */
-		/* maybe we should have an account option to always just try IBB
-			for people who know their firewalls are very restrictive */
-		if (jsx->stream_method & STREAM_METHOD_BYTESTREAMS) {
-			value = purple_xmlnode_new_child(field, "value");
-			purple_xmlnode_insert_data(value, NS_BYTESTREAMS, -1);
-		} else if(jsx->stream_method & STREAM_METHOD_IBB) {
-			value = purple_xmlnode_new_child(field, "value");
-			purple_xmlnode_insert_data(value, NS_IBB, -1);
-		}
-
-		jabber_iq_send(iq);
-	}
-}
-
-PurpleXfer *
-jabber_si_new_xfer(G_GNUC_UNUSED PurpleProtocolXfer *prplxfer,
-                   PurpleConnection *gc, const char *who)
-{
-	JabberStream *js;
-	JabberSIXfer *jsx;
-
-	js = purple_connection_get_protocol_data(gc);
-
-	jsx = g_object_new(
-		JABBER_TYPE_SI_XFER,
-		"account", purple_connection_get_account(gc),
-		"type", PURPLE_XFER_TYPE_SEND,
-		"remote-user", who,
-		NULL
-	);
-
-	jsx->js = js;
-	js->file_transfers = g_list_append(js->file_transfers, jsx);
-
-	return PURPLE_XFER(jsx);
-}
-
-void jabber_si_xfer_send(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *who, const char *file)
-{
-	PurpleXfer *xfer;
-
-	xfer = jabber_si_new_xfer(prplxfer, gc, who);
-
-	if (file)
-		purple_xfer_request_accepted(xfer, file);
-	else
-		purple_xfer_request(xfer);
-}
-
-#if ENABLE_FT_THUMBNAILS
-static void
-jabber_si_thumbnail_cb(JabberData *data, gchar *alt, gpointer userdata)
-{
-	PurpleXfer *xfer = (PurpleXfer *) userdata;
-
-	if (data) {
-		purple_xfer_set_thumbnail(xfer, jabber_data_get_data(data),
-			jabber_data_get_size(data), jabber_data_get_type(data));
-		/* data is ephemeral, get rid of now (the xfer re-owned the thumbnail */
-		jabber_data_destroy(data);
-	}
-
-	purple_xfer_request(xfer);
-}
-#endif
-
-static void
-jabber_si_parse(JabberStream *js, const char *from,
-                G_GNUC_UNUSED JabberIqType type, const char *id,
-                PurpleXmlNode *si)
-{
-	JabberSIXfer *jsx;
-	PurpleXmlNode *file, *feature, *x, *field, *option, *value;
-#if ENABLE_FT_THUMBNAILS
-	PurpleXmlNode *thumbnail;
-#endif
-	const char *stream_id, *filename, *filesize_c, *profile;
-	goffset filesize = 0;
-
-	if(!(profile = purple_xmlnode_get_attrib(si, "profile")) ||
-			!purple_strequal(profile, NS_SI_FILE_TRANSFER))
-		return;
-
-	if(!(stream_id = purple_xmlnode_get_attrib(si, "id")))
-		return;
-
-	if(!(file = purple_xmlnode_get_child(si, "file")))
-		return;
-
-	if(!(filename = purple_xmlnode_get_attrib(file, "name")))
-		return;
-
-	if((filesize_c = purple_xmlnode_get_attrib(file, "size")))
-		filesize = g_ascii_strtoull(filesize_c, NULL, 10);
-
-	if(!(feature = purple_xmlnode_get_child(si, "feature")))
-		return;
-
-	if(!(x = purple_xmlnode_get_child_with_namespace(feature, "x", "jabber:x:data")))
-		return;
-
-	if(!from)
-		return;
-
-	/* if they've already sent us this file transfer with the same damn id
-	 * then we're gonna ignore it, until I think of something better to do
-	 * with it */
-	if(jabber_si_xfer_find(js, stream_id, from) != NULL)
-		return;
-
-	jsx = g_object_new(
-		JABBER_TYPE_SI_XFER,
-		"account", purple_connection_get_account(js->gc),
-		"type", PURPLE_XFER_TYPE_RECEIVE,
-		"remote-user", from,
-		NULL
-	);
-
-	for(field = purple_xmlnode_get_child(x, "field"); field; field = purple_xmlnode_get_next_twin(field)) {
-		const char *var = purple_xmlnode_get_attrib(field, "var");
-		if(purple_strequal(var, "stream-method")) {
-			for(option = purple_xmlnode_get_child(field, "option"); option;
-					option = purple_xmlnode_get_next_twin(option)) {
-				if((value = purple_xmlnode_get_child(option, "value"))) {
-					char *val;
-					if((val = purple_xmlnode_get_data(value))) {
-						if(purple_strequal(val, NS_BYTESTREAMS)) {
-							jsx->stream_method |= STREAM_METHOD_BYTESTREAMS;
-						} else if(purple_strequal(val, NS_IBB)) {
-							jsx->stream_method |= STREAM_METHOD_IBB;
-						}
-						g_free(val);
-					}
-				}
-			}
-		}
-	}
-
-	if(jsx->stream_method == STREAM_METHOD_UNKNOWN) {
-		g_object_unref(jsx);
-		return;
-	}
-
-	jsx->js = js;
-	jsx->stream_id = g_strdup(stream_id);
-	jsx->iq_id = g_strdup(id);
-
-	purple_xfer_set_filename(PURPLE_XFER(jsx), filename);
-	if(filesize > 0) {
-		purple_xfer_set_size(PURPLE_XFER(jsx), filesize);
-	}
-
-	js->file_transfers = g_list_append(js->file_transfers, jsx);
-
-#if ENABLE_FT_THUMBNAILS
-	/* if there is a thumbnail, we should request it... */
-	if ((thumbnail = purple_xmlnode_get_child_with_namespace(file, "thumbnail",
-		NS_THUMBS))) {
-		const char *cid = purple_xmlnode_get_attrib(thumbnail, "cid");
-		if (cid) {
-			jabber_data_request(js, cid, purple_xfer_get_remote_user(PURPLE_XFER(jsx)),
-			    NULL, TRUE, jabber_si_thumbnail_cb, jsx);
-			return;
-		}
-	}
-#endif
-
-	purple_xfer_request(PURPLE_XFER(jsx));
-}
-
-/******************************************************************************
- * GObject Implementation
- *****************************************************************************/
-static void
-jabber_si_xfer_init(JabberSIXfer *jsx)
-{
-	jsx->ibb_session = NULL;
-	jsx->cancellable = g_cancellable_new();
-}
-
-static void
-jabber_si_xfer_finalize(GObject *obj) {
-	JabberSIXfer *jsx = JABBER_SI_XFER(obj);
-	JabberStream *js = jsx->js;
-
-	js->file_transfers = g_list_remove(js->file_transfers, jsx);
-
-	g_cancellable_cancel(jsx->cancellable);
-	g_clear_object(&jsx->cancellable);
-
-	g_clear_object(&jsx->client);
-	g_clear_object(&jsx->local_streamhost_conn);
-	if (jsx->service) {
-		g_socket_service_stop(jsx->service);
-	}
-	g_clear_object(&jsx->service);
-
-	if (jsx->iq_id != NULL) {
-		jabber_iq_remove_callback_by_id(js, jsx->iq_id);
-	}
-
-	g_clear_handle_id(&jsx->connect_timeout, g_source_remove);
-	g_clear_handle_id(&jsx->ibb_timeout_handle, g_source_remove);
-
-	g_list_free_full(jsx->streamhosts, (GDestroyNotify)jabber_bytestreams_streamhost_free);
-
-	if (jsx->ibb_session) {
-		purple_debug_info("jabber",
-			"jabber_si_xfer_free: destroying IBB session\n");
-		jabber_ibb_session_destroy(jsx->ibb_session);
-	}
-
-	if (jsx->ibb_buffer) {
-		g_object_unref(jsx->ibb_buffer);
-	}
-
-	purple_debug_info("jabber", "jabber_si_xfer_free(): freeing jsx %p\n", jsx);
-
-	g_free(jsx->stream_id);
-	g_free(jsx->iq_id);
-	g_free(jsx->socks_buf);
-
-	G_OBJECT_CLASS(jabber_si_xfer_parent_class)->finalize(obj);
-}
-
-static void
-jabber_si_xfer_class_finalize(G_GNUC_UNUSED JabberSIXferClass *klass) {
-}
-
-static void
-jabber_si_xfer_class_init(JabberSIXferClass *klass) {
-	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
-	PurpleXferClass *xfer_class = PURPLE_XFER_CLASS(klass);
-
-	obj_class->finalize = jabber_si_xfer_finalize;
-
-	xfer_class->init = jabber_si_xfer_xfer_init;
-	xfer_class->request_denied = jabber_si_xfer_request_denied;
-	xfer_class->cancel_send = jabber_si_xfer_cancel_send;
-	xfer_class->cancel_recv = jabber_si_xfer_cancel_recv;
-	xfer_class->read = jabber_si_xfer_ibb_read;
-	xfer_class->write = jabber_si_xfer_ibb_write;
-}
-
-/******************************************************************************
- * Public API
- *****************************************************************************/
-void
-jabber_si_xfer_register(GTypeModule *module) {
-	jabber_si_xfer_register_type(module);
-}
-
-void
-jabber_si_init(void) {
-	jabber_iq_register_handler("si", "http://jabber.org/protocol/si", jabber_si_parse);
-
-	jabber_ibb_register_open_handler(jabber_si_xfer_ibb_open_cb);
-}
-
-void
-jabber_si_uninit(void) {
-	jabber_ibb_unregister_open_handler(jabber_si_xfer_ibb_open_cb);
-}
diff --git a/libpurple/protocols/jabber/tests/meson.build b/libpurple/protocols/jabber/tests/meson.build
deleted file mode 100644
--- a/libpurple/protocols/jabber/tests/meson.build
+++ /dev/null
@@ -1,11 +0,0 @@
-foreach prog : ['caps', 'digest_md5', 'scram', 'jutil']
-	e = executable(
-	    f'test_jabber_@prog@', f'test_jabber_@prog@.c',
-	    link_with : [jabber_prpl],
-	    dependencies : [libxml, libpurple_dep, libsoup, glib])
-
-	jabberenv = environment()
-	jabberenv.set('XDG_CONFIG_DIR', meson.current_build_dir() / 'config')
-
-	test(f'jabber_@prog@', e, env: jabberenv)
-endforeach
diff --git a/libpurple/protocols/jabber/tests/test_jabber_caps.c b/libpurple/protocols/jabber/tests/test_jabber_caps.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/tests/test_jabber_caps.c
+++ /dev/null
@@ -1,60 +0,0 @@
-#include <glib.h>
-
-#include <purple.h>
-
-#include "protocols/jabber/caps.h"
-
-static void
-test_jabber_caps_parse_invalid_nodes(void) {
-	PurpleXmlNode *query;
-
-	g_assert_null(jabber_caps_parse_client_info(NULL));
-
-	/* Something other than a disco#info query */
-	query = purple_xmlnode_new("foo");
-	g_assert_null(jabber_caps_parse_client_info(query));
-	purple_xmlnode_free(query);
-
-	query = purple_xmlnode_new("query");
-	g_assert_null(jabber_caps_parse_client_info(query));
-
-	purple_xmlnode_set_namespace(query, "jabber:iq:last");
-	g_assert_null(jabber_caps_parse_client_info(query));
-	purple_xmlnode_free(query);
-}
-
-static void
-_test_jabber_caps_match(GChecksumType hash_type, const gchar *in, const gchar *expected) {
-	PurpleXmlNode *query = purple_xmlnode_from_str(in, -1);
-	JabberCapsClientInfo *info = jabber_caps_parse_client_info(query);
-	gchar *got = NULL;
-
-	got = jabber_caps_calculate_hash(info, hash_type);
-
-	g_assert_cmpstr(expected, ==, got);
-	g_free(got);
-	jabber_caps_client_info_destroy(info);
-	purple_xmlnode_free(query);
-}
-
-static void
-test_jabber_caps_calculate_from_xmlnode(void) {
-	_test_jabber_caps_match(
-		G_CHECKSUM_SHA1,
-		"<query xmlns='http://jabber.org/protocol/disco#info' node='http://tkabber.jabber.ru/#GNjxthSckUNvAIoCCJFttjl6VL8='><identity category='client' type='pc' name='Tkabber'/><x xmlns='jabber:x:data' type='result'><field var='FORM_TYPE' type='hidden'><value>urn:xmpp:dataforms:softwareinfo</value></field><field var='software'><value>Tkabber</value></field><field var='software_version'><value> ( 8.5.5 )</value></field><field var='os'><value>ATmega640-16AU</value></field><field var='os_version'><value/></field></x><feature var='games:board'/><feature var='http://jabber.org/protocol/activity'/><feature var='http://jabber.org/protocol/bytestreams'/><feature var='http://jabber.org/protocol/chatstates'/><feature var='http://jabber.org/protocol/commands'/><feature var='http://jabber.org/protocol/commands'/><feature var='http://jabber.org/protocol/disco#info'/><feature var='http://jabber.org/protocol/disco#items'/><feature var='http://jabber.org/protocol/feature-neg'/><feature var='http://jabber.org/protocol/geoloc'/><feature var='http://jabber.org/protocol/ibb'/><feature var='http://jabber.org/protocol/iqibb'/><feature var='http://jabber.org/protocol/muc'/><feature var='http://jabber.org/protocol/mute#ancestor'/><feature var='http://jabber.org/protocol/mute#editor'/><feature var='http://jabber.org/protocol/rosterx'/><feature var='http://jabber.org/protocol/si'/><feature var='http://jabber.org/protocol/si/profile/file-transfer'/><feature var='jabber:iq:avatar'/><feature var='jabber:iq:browse'/><feature var='jabber:iq:dtcp'/><feature var='jabber:iq:filexfer'/><feature var='jabber:iq:ibb'/><feature var='jabber:iq:inband'/><feature var='jabber:iq:jidlink'/><feature var='jabber:iq:last'/><feature var='jabber:iq:oob'/><feature var='jabber:iq:privacy'/><feature var='jabber:iq:time'/><feature var='jabber:iq:version'/><feature var='jabber:x:data'/><feature var='jabber:x:event'/><feature var='jabber:x:oob'/><feature var='urn:xmpp:ping'/><feature var='urn:xmpp:receipts'/><feature var='urn:xmpp:time'/></query>",
-		"sVNUrcvQ2ryBm4L+NRhXrRnd71c="
-	);
-}
-
-gint
-main(gint argc, gchar **argv) {
-	g_test_init(&argc, &argv, NULL);
-
-	g_test_add_func("/jabber/caps/parse invalid nodes",
-	                test_jabber_caps_parse_invalid_nodes);
-
-	g_test_add_func("/jabber/caps/calculate from xmlnode",
-	                test_jabber_caps_calculate_from_xmlnode);
-
-	return g_test_run();
-}
diff --git a/libpurple/protocols/jabber/tests/test_jabber_digest_md5.c b/libpurple/protocols/jabber/tests/test_jabber_digest_md5.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/tests/test_jabber_digest_md5.c
+++ /dev/null
@@ -1,51 +0,0 @@
-#include <glib.h>
-
-#include <purple.h>
-
-#include "protocols/jabber/auth_digest_md5.h"
-#include "protocols/jabber/jutil.h"
-
-static void
-test_jabber_digest_md5_parsing(void) {
-	GHashTable *table;
-	const gchar *value = NULL;
-
-	#define check_value(name, expected) G_STMT_START {\
-		value = g_hash_table_lookup(table, (name)); \
-		g_assert_nonnull(value); \
-		g_assert_cmpstr((expected), ==, value); \
-	} G_STMT_END
-
-	table = jabber_auth_digest_md5_parse("r=\"realm\",token=   \"   asdf\"");
-	check_value("r", "realm");
-	check_value("token", "asdf");
-	g_hash_table_destroy(table);
-
-	table = jabber_auth_digest_md5_parse("r=\"a\", token=   \"   asdf\"");
-	check_value("r", "a");
-	check_value("token", "asdf");
-	g_hash_table_destroy(table);
-
-	table = jabber_auth_digest_md5_parse("r=\"\", token=   \"   asdf\"");
-	check_value("r", "");
-	check_value("token", "asdf");
-	g_hash_table_destroy(table);
-
-	table = jabber_auth_digest_md5_parse("realm=\"somerealm\",nonce=\"OA6MG9tEQGm2hh\",qop=\"auth\",charset=utf-8,algorithm=md5-sess");
-	check_value("realm", "somerealm");
-	check_value("nonce", "OA6MG9tEQGm2hh");
-	check_value("qop", "auth");
-	check_value("charset", "utf-8");
-	check_value("algorithm", "md5-sess");
-	g_hash_table_destroy(table);
-}
-
-gint
-main(gint argc, gchar **argv) {
-	g_test_init(&argc, &argv, NULL);
-
-	g_test_add_func("/jabber/digest/md5/parsing",
-	                test_jabber_digest_md5_parsing);
-
-	return g_test_run();
-}
diff --git a/libpurple/protocols/jabber/tests/test_jabber_jutil.c b/libpurple/protocols/jabber/tests/test_jabber_jutil.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/tests/test_jabber_jutil.c
+++ /dev/null
@@ -1,290 +0,0 @@
-#include <glib.h>
-
-#include <purple.h>
-
-#include "protocols/jabber/jutil.h"
-
-PurpleTestStringData test_jabber_util_get_resource_exists_data[] = {
-        {"foo@bar/baz", "baz"},
-        {"bar/baz", "baz"},
-        {"foo@bar/baz/bat", "baz/bat"},
-        {"bar/baz/bat", "baz/bat"},
-        {NULL, NULL},
-};
-static void
-test_jabber_util_get_resource_exists(const PurpleTestStringData *data)
-{
-	char *resource;
-
-	resource = jabber_get_resource(data->input);
-	g_assert_cmpstr(data->output, ==, resource);
-	g_free(resource);
-}
-
-PurpleTestStringData test_jabber_util_get_resource_none_data[] = {
-        {"foo@bar", NULL},
-        {"bar", NULL},
-        {NULL, NULL},
-};
-static void
-test_jabber_util_get_resource_none(const PurpleTestStringData *data)
-{
-	g_assert_cmpstr(data->output, ==, jabber_get_resource(data->input));
-}
-
-PurpleTestStringData test_jabber_util_get_bare_jid_data[] = {
-        {"foo@bar", "foo@bar"},
-        {"foo@bar/baz", "foo@bar"},
-        {"bar", "bar"},
-        {"bar/baz", "bar"},
-        {NULL, NULL},
-};
-static void
-test_jabber_util_get_bare_jid(const PurpleTestStringData *data)
-{
-	char *bare_jid;
-
-	bare_jid = jabber_get_bare_jid(data->input);
-	g_assert_cmpstr(data->output, ==, bare_jid);
-	g_free(bare_jid);
-}
-
-static void
-test_jabber_util_nodeprep_validate(void) {
-	const gchar *data[] = {
-		"foo",
-		"%d",
-		"y\\z",
-		"a=",
-		"a,",
-		NULL,
-	};
-	gchar *longnode;
-	gint i;
-
-	for(i = 0; data[i]; i++) {
-		g_assert_true(jabber_nodeprep_validate(data[i]));
-	}
-
-	longnode = g_strnfill(1023, 'a');
-	g_assert_true(jabber_nodeprep_validate(longnode));
-	g_free(longnode);
-
-	longnode = g_strnfill(1024, 'a');
-	g_assert_false(jabber_nodeprep_validate(longnode));
-	g_free(longnode);
-}
-
-const gchar *test_jabber_util_nodeprep_validate_illegal_chars_data[] = {
-        "don't",
-        "m@ke",
-        "\"me\"",
-        "&ngry",
-        "c:",
-        "a/b",
-        "4>2",
-        "4<7",
-        NULL,
-};
-static void
-test_jabber_util_nodeprep_validate_illegal_chars(const gchar *data)
-{
-	g_assert_false(jabber_nodeprep_validate(data));
-}
-
-static void
-test_jabber_util_nodeprep_validate_too_long(void) {
-	gchar *longnode = g_strnfill(1024, 'a');
-
-	g_assert_false(jabber_nodeprep_validate(longnode));
-
-	g_free(longnode);
-}
-
-const gchar *test_jabber_util_jabber_id_new_valid_data[] = {
-        "gmail.com",
-        "gmail.com/Test",
-        "gmail.com/Test@",
-        "gmail.com/@",
-        "gmail.com/Test@alkjaweflkj",
-        "noone@example.com",
-        "noone@example.com/Test12345",
-        "noone@example.com/Test@12345",
-        "noone@example.com/Te/st@12@//345",
-        "わいど@conference.jabber.org",
-        "まりるーむ@conference.jabber.org",
-        "noone@example.com/まりるーむ",
-        "noone@example/stuff.org",
-        "noone@nödåtXäYZ.example",
-        "noone@nödåtXäYZ.example/まりるーむ",
-        "noone@わいど.org",
-        "noone@まつ.おおかみ.net",
-        "noone@310.0.42.230/s",
-        "noone@[::1]", /* IPv6 */
-        "noone@[3001:470:1f05:d58::2]",
-        "noone@[3001:470:1f05:d58::2]/foo",
-        "no=one@310.0.42.230",
-        "no,one@310.0.42.230",
-        NULL,
-};
-static void
-test_jabber_util_jabber_id_new_valid(const gchar *data)
-{
-	JabberID *jid = jabber_id_new(data);
-
-	g_assert_nonnull(jid);
-
-	jabber_id_free(jid);
-}
-
-const gchar *test_jabber_util_jabber_id_new_invalid_data[] = {
-        "@gmail.com",
-        "@@gmail.com",
-        "noone@@example.com/Test12345",
-        "no@one@example.com/Test12345",
-        "@example.com/Test@12345",
-        "/Test@12345",
-        "noone@",
-        "noone/",
-        "noone@gmail_stuff.org",
-        "noone@gmail[stuff.org",
-        "noone@gmail\\stuff.org",
-        "noone@[::1]124",
-        "noone@2[::1]124/as",
-        "noone@まつ.おおかみ/\x01",
-        /*
-         * RFC 3454 Section 6 reads, in part,
-         * "If a string contains any RandALCat character, the
-         *  string MUST NOT contain any LCat character."
-         * The character is U+066D (ARABIC FIVE POINTED STAR).
-         */
-        "foo@example.com/٭simplexe٭",
-        NULL,
-};
-static void
-test_jabber_util_jabber_id_new_invalid(const gchar *jid)
-{
-	g_assert_null(jabber_id_new(jid));
-}
-
-#define assert_jid_parts(expect_node, expect_domain, str) G_STMT_START { \
-	JabberID *jid = jabber_id_new(str); \
-	g_assert_nonnull(jid); \
-	g_assert_nonnull(jid->node); \
-	g_assert_nonnull(jid->domain); \
-	g_assert_null(jid->resource); \
-	g_assert_cmpstr(expect_node, ==, jid->node); \
-	g_assert_cmpstr(expect_domain, ==, jid->domain); \
-	jabber_id_free(jid); \
-} G_STMT_END
-
-
-static void
-test_jabber_util_jid_parts(void) {
-	/* Ensure that jabber_id_new is properly lowercasing node and domains */
-	assert_jid_parts("noone", "example.com", "NoOne@example.com");
-	assert_jid_parts("noone", "example.com", "noone@ExaMPle.CoM");
-
-	/* These case-mapping tests culled from examining RFC3454 B.2 */
-
-	/* Cyrillic capital EF (U+0424) maps to lowercase EF (U+0444) */
-	assert_jid_parts("ф", "example.com", "Ф@example.com");
-
-	/*
-	 * These character (U+A664 and U+A665) are not mapped to anything in
-	 * RFC3454 B.2. This first test *fails* when not using IDN because glib's
-	 * case-folding/utf8_strdown improperly (for XMPP) lowercases the character.
-	 *
-	 * This is known, but not (very?) likely to actually cause a problem, so
-	 * this test is commented out when using glib's functions.
-	 */
-	assert_jid_parts("Ꙥ", "example.com", "Ꙥ@example.com");
-	assert_jid_parts("ꙥ", "example.com", "ꙥ@example.com");
-
-	/* U+04E9 to U+04E9 */
-	assert_jid_parts("noone", "өexample.com", "noone@Өexample.com");
-}
-
-PurpleTestStringData test_jabber_util_jabber_normalize_data[] = {
-        {"NoOnE@ExAMplE.com", "noone@example.com"},
-        {"NoOnE@ExampLE.cOM/", "noone@example.com"},
-        {"NoONe@exAMPle.CoM/resource", "noone@example.com"},
-        {NULL, NULL},
-};
-static void
-test_jabber_util_jabber_normalize(const PurpleTestStringData *data)
-{
-	g_assert_cmpstr(data->output, ==, jabber_normalize(NULL, data->input));
-}
-
-gint
-main(gint argc, gchar **argv) {
-	gchar *test_name;
-	gint i;
-	g_test_init(&argc, &argv, NULL);
-	g_test_set_nonfatal_assertions();
-
-	for (i = 0; test_jabber_util_get_resource_exists_data[i].input; i++) {
-		test_name = g_strdup_printf("/jabber/util/get_resource/exists/%d", i);
-		g_test_add_data_func(
-		        test_name, &test_jabber_util_get_resource_exists_data[i],
-		        (GTestDataFunc)test_jabber_util_get_resource_exists);
-		g_free(test_name);
-	}
-	for (i = 0; test_jabber_util_get_resource_none_data[i].input; i++) {
-		test_name = g_strdup_printf("/jabber/util/get_resource/none/%d", i);
-		g_test_add_data_func(test_name,
-		                     &test_jabber_util_get_resource_none_data[i],
-		                     (GTestDataFunc)test_jabber_util_get_resource_none);
-		g_free(test_name);
-	}
-
-	for (i = 0; test_jabber_util_get_bare_jid_data[i].input; i++) {
-		test_name = g_strdup_printf("/jabber/util/get_bare_jid/%d", i);
-		g_test_add_data_func(test_name, &test_jabber_util_get_bare_jid_data[i],
-		                     (GTestDataFunc)test_jabber_util_get_bare_jid);
-		g_free(test_name);
-	}
-
-	g_test_add_func("/jabber/util/nodeprep/validate/valid",
-	                test_jabber_util_nodeprep_validate);
-	for (i = 0; test_jabber_util_nodeprep_validate_illegal_chars_data[i]; i++) {
-		test_name = g_strdup_printf(
-		        "/jabber/util/nodeprep/validate/illegal_chars/%d", i);
-		g_test_add_data_func(
-		        test_name,
-		        test_jabber_util_nodeprep_validate_illegal_chars_data[i],
-		        (GTestDataFunc)
-		                test_jabber_util_nodeprep_validate_illegal_chars);
-		g_free(test_name);
-	}
-	g_test_add_func("/jabber/util/nodeprep/validate/too_long",
-	                test_jabber_util_nodeprep_validate_too_long);
-
-	for (i = 0; test_jabber_util_jabber_id_new_valid_data[i]; i++) {
-		test_name = g_strdup_printf("/jabber/util/id_new/valid/%d", i);
-		g_test_add_data_func(
-		        test_name, test_jabber_util_jabber_id_new_valid_data[i],
-		        (GTestDataFunc)test_jabber_util_jabber_id_new_valid);
-		g_free(test_name);
-	}
-	for (i = 0; test_jabber_util_jabber_id_new_invalid_data[i]; i++) {
-		test_name = g_strdup_printf("/jabber/util/id_new/invalid/%d", i);
-		g_test_add_data_func(
-		        test_name, test_jabber_util_jabber_id_new_invalid_data[i],
-		        (GTestDataFunc)test_jabber_util_jabber_id_new_invalid);
-		g_free(test_name);
-	}
-	g_test_add_func("/jabber/util/id_new/jid_parts",
-	                test_jabber_util_jid_parts);
-
-	for (i = 0; test_jabber_util_jabber_normalize_data[i].input; i++) {
-		test_name = g_strdup_printf("/jabber/util/normalize/%d", i);
-		g_test_add_data_func(test_name,
-		                     &test_jabber_util_jabber_normalize_data[i],
-		                     (GTestDataFunc)test_jabber_util_jabber_normalize);
-		g_free(test_name);
-	}
-
-	return g_test_run();
-}
diff --git a/libpurple/protocols/jabber/tests/test_jabber_scram.c b/libpurple/protocols/jabber/tests/test_jabber_scram.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/tests/test_jabber_scram.c
+++ /dev/null
@@ -1,109 +0,0 @@
-#include <string.h>
-
-#include <purple.h>
-
-#include "protocols/jabber/auth_scram.h"
-#include "protocols/jabber/jutil.h"
-
-static JabberScramHash sha1_mech = { "-SHA-1", G_CHECKSUM_SHA1 };
-
-#define assert_pbkdf2_equal(password, salt, count, expected) { \
-	GString *p = g_string_new(password); \
-	GString *s = g_string_new(salt); \
-	guchar *result = jabber_scram_hi(&sha1_mech, p, s, count); \
-	g_assert_nonnull(result); \
-	g_assert_cmpmem(result, 20, expected, 20); \
-	g_string_free(s, TRUE); \
-	g_string_free(p, TRUE); \
-	g_free(result); \
-}
-
-static void
-test_jabber_scram_pbkdf2(void) {
-	assert_pbkdf2_equal("password", "salt", 1, "\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6");
-	assert_pbkdf2_equal("password", "salt", 2, "\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57");
-	assert_pbkdf2_equal("password", "salt", 4096, "\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1");
-	/* This test is insane and takes forever, so it's disabled */
-	/*
-	assert_pbkdf2_equal("password", "salt", 16777216, "\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94\x5b\x3d\x6b\xa2\x15\x8c\x26\x34\xe9\x84");
-	*/
-}
-
-static void
-test_jabber_scram_proofs(void) {
-	JabberScramData *data = g_new0(JabberScramData, 1);
-	gboolean ret;
-	GString *salt;
-	const char *client_proof;
-/*	const char *server_signature; */
-
-	data->hash = &sha1_mech;
-	data->password = g_strdup("password");
-	data->auth_message = g_string_new("n=username@jabber.org,r=8jLxB5515dhFxBil5A0xSXMH,"
-			"r=8jLxB5515dhFxBil5A0xSXMHabc,s=c2FsdA==,i=1,"
-			"c=biws,r=8jLxB5515dhFxBil5A0xSXMHabc");
-	client_proof = "\x48\x61\x30\xa5\x61\x0b\xae\xb9\xe4\x11\xa8\xfd\xa5\xcd\x34\x1d\x8a\x3c\x28\x17";
-
-	salt = g_string_new("salt");
-	ret = jabber_scram_calc_proofs(data, salt, 1);
-	g_assert_true(ret);
-
-	g_assert_cmpmem(client_proof, 20, data->client_proof->str, 20);
-	g_string_free(salt, TRUE);
-
-	jabber_scram_data_destroy(data);
-}
-
-#define assert_successful_exchange(pw, nonce, start_data, challenge1, response1, success) { \
-	JabberScramData *data = g_new0(JabberScramData, 1); \
-	gboolean ret; \
-	gchar *out; \
-	\
-	data->step = 1; \
-	data->hash = &sha1_mech; \
-	data->password = jabber_saslprep(pw); \
-	g_assert_nonnull(data->password); \
-	data->cnonce = g_strdup(nonce); \
-	data->auth_message = g_string_new(start_data); \
-	\
-	ret = jabber_scram_feed_parser(data, challenge1, &out); \
-	g_assert_true(ret); \
-	g_assert_cmpstr(response1, ==, out); \
-	g_free(out); \
-	\
-	data->step = 2; \
-	ret = jabber_scram_feed_parser(data, success, &out); \
-	g_assert_true(ret); \
-	g_assert_null(out); \
-	\
-	jabber_scram_data_destroy(data); \
-}
-
-static void
-test_jabber_scram_exchange(void) {
-	assert_successful_exchange("password", "H7yDYKAWBCrM2Fa5SxGa4iez",
-			"n=paul,r=H7yDYKAWBCrM2Fa5SxGa4iez",
-			"r=H7yDYKAWBCrM2Fa5SxGa4iezFPVDPpDUcGxPkH3RzP,s=3rXeErP/os7jUNqU,i=4096",
-			"c=biws,r=H7yDYKAWBCrM2Fa5SxGa4iezFPVDPpDUcGxPkH3RzP,p=pXkak78EuwwOEwk2/h/OzD7NkEI=",
-			"v=ldX4EBNnOgDnNTOCmbSfBHAUCOs=");
-
-	assert_successful_exchange("pass½word", "GNb2HsNI7VnTv8ABsE5AnY8W",
-			"n=paul,r=GNb2HsNI7VnTv8ABsE5AnY8W",
-			"r=GNb2HsNI7VnTv8ABsE5AnY8W/w/I3eRKM0I7jxFWOH,s=ysAriUjPzFqOXnMQ,i=4096",
-			"c=biws,r=GNb2HsNI7VnTv8ABsE5AnY8W/w/I3eRKM0I7jxFWOH,p=n/CtgdWjOYnLQ4m9Na+wPn9D2uY=",
-			"v=4TkZwKWy6JHNmrUbU2+IdAaXtos=");
-}
-
-gint
-main(gint argc, gchar **argv) {
-	g_test_init(&argc, &argv, NULL);
-
-	g_test_add_func("/jabber/scram/pbkdf2",
-	                test_jabber_scram_pbkdf2);
-	g_test_add_func("/jabber/scram/proofs",
-	                test_jabber_scram_proofs);
-	g_test_add_func("/jabber/scram/exchange",
-	                test_jabber_scram_exchange);
-
-	return g_test_run();
-}
diff --git a/libpurple/protocols/jabber/useravatar.h b/libpurple/protocols/jabber/useravatar.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/useravatar.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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_JABBER_USERAVATAR_H
-#define PURPLE_JABBER_USERAVATAR_H
-
-#include "jabber.h"
-
-#include <purple.h>
-
-/* Implementation of XEP-0084 */
-
-void jabber_avatar_init(void);
-void jabber_avatar_set(JabberStream *js, PurpleImage *img);
-
-void jabber_avatar_fetch_mine(JabberStream *js);
-
-#endif /* PURPLE_JABBER_USERAVATAR_H */
diff --git a/libpurple/protocols/jabber/useravatar.c b/libpurple/protocols/jabber/useravatar.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/useravatar.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <purpleconfig.h>
-
-#include <glib/gi18n-lib.h>
-
-#include <purple.h>
-#include "libpurple/glibcompat.h"
-
-#include <libsoup/soup.h>
-
-#include "useravatar.h"
-#include "pep.h"
-
-#define MAX_HTTP_BUDDYICON_BYTES (200 * 1024)
-
-static void update_buddy_metadata(JabberStream *js, const char *from, PurpleXmlNode *items);
-
-void jabber_avatar_init(void)
-{
-	jabber_add_feature(NS_AVATAR_1_1_METADATA,
-	                   jabber_pep_namespace_only_when_pep_enabled_cb);
-	jabber_add_feature(NS_AVATAR_1_1_DATA,
-	                   jabber_pep_namespace_only_when_pep_enabled_cb);
-
-	jabber_pep_register_handler(NS_AVATAR_1_1_METADATA,
-	                            update_buddy_metadata);
-}
-
-void jabber_avatar_set(JabberStream *js, PurpleImage *img)
-{
-	PurpleXmlNode *publish, *metadata, *item;
-
-	if (!js->pep)
-		return;
-
-	if (!img) {
-		publish = purple_xmlnode_new("publish");
-		purple_xmlnode_set_attrib(publish, "node", NS_AVATAR_1_1_METADATA);
-
-		item = purple_xmlnode_new_child(publish, "item");
-		metadata = purple_xmlnode_new_child(item, "metadata");
-		purple_xmlnode_set_namespace(metadata, NS_AVATAR_1_1_METADATA);
-
-		/* publish */
-		jabber_pep_publish(js, publish);
-	} else {
-		/*
-		 * TODO: This is pretty gross.  The Jabber protocol really shouldn't
-		 *       do voodoo to try to determine the image type, height
-		 *       and width.
-		 */
-		/* A PNG header, including the IHDR, but nothing else */
-		/* ATTN: this is in network byte order! */
-		const struct {
-			guchar signature[8]; /* must be hex 89 50 4E 47 0D 0A 1A 0A */
-			struct {
-				guint32 length; /* must be 0x0d */
-				guchar type[4]; /* must be 'I' 'H' 'D' 'R' */
-				guint32 width;
-				guint32 height;
-				guchar bitdepth;
-				guchar colortype;
-				guchar compression;
-				guchar filter;
-				guchar interlace;
-			} ihdr;
-		} *png = NULL;
-
-		if (purple_image_get_data_size(img) > sizeof(*png))
-			png = purple_image_get_data(img);
-
-		/* check if the data is a valid png file (well, at least to some extent) */
-		if(png && png->signature[0] == 0x89 &&
-		   png->signature[1] == 0x50 &&
-		   png->signature[2] == 0x4e &&
-		   png->signature[3] == 0x47 &&
-		   png->signature[4] == 0x0d &&
-		   png->signature[5] == 0x0a &&
-		   png->signature[6] == 0x1a &&
-		   png->signature[7] == 0x0a &&
-		   GUINT32_FROM_BE(png->ihdr.length) == 0x0d &&
-		   png->ihdr.type[0] == 'I' &&
-		   png->ihdr.type[1] == 'H' &&
-		   png->ihdr.type[2] == 'D' &&
-		   png->ihdr.type[3] == 'R') {
-			/* parse PNG header to get the size of the image (yes, this is required) */
-			guint32 width = GUINT32_FROM_BE(png->ihdr.width);
-			guint32 height = GUINT32_FROM_BE(png->ihdr.height);
-			PurpleXmlNode *data, *info;
-			char *lengthstring, *widthstring, *heightstring;
-
-			/* compute the sha1 hash */
-			char *hash = g_compute_checksum_for_data(
-				G_CHECKSUM_SHA1,
-				purple_image_get_data(img),
-				purple_image_get_data_size(img));
-			char *base64avatar = g_base64_encode(
-				purple_image_get_data(img),
-				purple_image_get_data_size(img));
-
-			publish = purple_xmlnode_new("publish");
-			purple_xmlnode_set_attrib(publish, "node", NS_AVATAR_1_1_DATA);
-
-			item = purple_xmlnode_new_child(publish, "item");
-			purple_xmlnode_set_attrib(item, "id", hash);
-
-			data = purple_xmlnode_new_child(item, "data");
-			purple_xmlnode_set_namespace(data, NS_AVATAR_1_1_DATA);
-
-			purple_xmlnode_insert_data(data, base64avatar, -1);
-			/* publish the avatar itself */
-			jabber_pep_publish(js, publish);
-
-			g_free(base64avatar);
-
-			lengthstring = g_strdup_printf("%" G_GSIZE_FORMAT,
-				purple_image_get_data_size(img));
-			widthstring = g_strdup_printf("%u", width);
-			heightstring = g_strdup_printf("%u", height);
-
-			/* publish the metadata */
-			publish = purple_xmlnode_new("publish");
-			purple_xmlnode_set_attrib(publish, "node", NS_AVATAR_1_1_METADATA);
-
-			item = purple_xmlnode_new_child(publish, "item");
-			purple_xmlnode_set_attrib(item, "id", hash);
-
-			metadata = purple_xmlnode_new_child(item, "metadata");
-			purple_xmlnode_set_namespace(metadata, NS_AVATAR_1_1_METADATA);
-
-			info = purple_xmlnode_new_child(metadata, "info");
-			purple_xmlnode_set_attrib(info, "id", hash);
-			purple_xmlnode_set_attrib(info, "type", "image/png");
-			purple_xmlnode_set_attrib(info, "bytes", lengthstring);
-			purple_xmlnode_set_attrib(info, "width", widthstring);
-			purple_xmlnode_set_attrib(info, "height", heightstring);
-
-			jabber_pep_publish(js, publish);
-
-			g_free(lengthstring);
-			g_free(widthstring);
-			g_free(heightstring);
-			g_free(hash);
-		} else {
-			purple_debug_error("jabber", "Cannot set PEP avatar to non-PNG data\n");
-		}
-	}
-}
-
-static void
-do_got_own_avatar_cb(JabberStream *js, G_GNUC_UNUSED const char *from,
-                     PurpleXmlNode *items)
-{
-	PurpleXmlNode *item = NULL, *metadata = NULL, *info = NULL;
-	PurpleAccount *account = purple_connection_get_account(js->gc);
-	const char *server_hash = NULL;
-
-	if (items && (item = purple_xmlnode_get_child(items, "item")) &&
-			(metadata = purple_xmlnode_get_child(item, "metadata")) &&
-			(info = purple_xmlnode_get_child(metadata, "info"))) {
-		server_hash = purple_xmlnode_get_attrib(info, "id");
-	}
-
-	/*
-	 * If we have an avatar and the server returned an error/malformed data,
-	 * push our avatar. If the server avatar doesn't match the local one, push
-	 * our avatar.
-	 */
-	if ((!items || !metadata) ||
-			!purple_strequal(server_hash, js->initial_avatar_hash)) {
-		PurpleImage *img = purple_buddy_icons_find_account_icon(account);
-		jabber_avatar_set(js, img);
-		if (img)
-			g_object_unref(img);
-	}
-}
-
-void jabber_avatar_fetch_mine(JabberStream *js)
-{
-	if (js->initial_avatar_hash) {
-		jabber_pep_request_item(js, NULL, NS_AVATAR_1_1_METADATA, NULL,
-		                        do_got_own_avatar_cb);
-	}
-}
-
-typedef struct {
-	JabberStream *js;
-	char *from;
-	char *id;
-	SoupMessage *msg;
-} JabberBuddyAvatarUpdateURLInfo;
-
-static void
-do_buddy_avatar_update_fromurl(GObject *source, GAsyncResult *result,
-                               gpointer data)
-{
-	JabberBuddyAvatarUpdateURLInfo *info = data;
-	GBytes *response_body = NULL;
-	gpointer icon_data = NULL;
-	gsize length = 0;
-	GError *error = NULL;
-	const gchar *error_message = NULL;
-
-	if(SOUP_STATUS_IS_SUCCESSFUL(soup_message_get_status(info->msg))) {
-		response_body = soup_session_send_and_read_finish(SOUP_SESSION(source),
-		                                                  result, &error);
-		error_message = error ? error->message : "unknown";
-	} else {
-		error_message = soup_message_get_reason_phrase(info->msg);
-	}
-	if(response_body == NULL) {
-		purple_debug_error("jabber",
-		                   "do_buddy_avatar_update_fromurl got error \"%s\"",
-		                   error_message);
-		goto out;
-	}
-
-	icon_data = g_bytes_unref_to_data(response_body, &length);
-	purple_buddy_icons_set_for_user(purple_connection_get_account(info->js->gc),
-	                                info->from, icon_data, length, info->id);
-
-out:
-	g_free(info->from);
-	g_free(info->id);
-	g_object_unref(info->msg);
-	g_free(info);
-	g_clear_error(&error);
-}
-
-static void
-do_buddy_avatar_update_data(JabberStream *js, const char *from, PurpleXmlNode *items)
-{
-	PurpleXmlNode *item, *data;
-	const char *checksum;
-	char *b64data;
-	void *img;
-	size_t size;
-	if(!items)
-		return;
-
-	item = purple_xmlnode_get_child(items, "item");
-	if(!item)
-		return;
-
-	data = purple_xmlnode_get_child(item, "data");
-	if(!data)
-		return;
-
-	checksum = purple_xmlnode_get_attrib(item,"id");
-	if(!checksum)
-		return;
-
-	b64data = purple_xmlnode_get_data(data);
-	if(!b64data)
-		return;
-
-	img = g_base64_decode(b64data, &size);
-	if(!img) {
-		g_free(b64data);
-		return;
-	}
-
-	purple_buddy_icons_set_for_user(purple_connection_get_account(js->gc), from, img, size, checksum);
-	g_free(b64data);
-}
-
-static void
-update_buddy_metadata(JabberStream *js, const char *from, PurpleXmlNode *items)
-{
-	PurpleBuddy *buddy = purple_blist_find_buddy(purple_connection_get_account(js->gc), from);
-	const char *checksum;
-	PurpleXmlNode *item, *metadata;
-	if(!buddy)
-		return;
-
-	if (!items)
-		return;
-
-	item = purple_xmlnode_get_child(items,"item");
-	if (!item)
-		return;
-
-	metadata = purple_xmlnode_get_child(item, "metadata");
-	if(!metadata)
-		return;
-
-	checksum = purple_buddy_icons_get_checksum_for_user(buddy);
-
-	/* <stop/> was the pre-v1.1 method of publishing an empty avatar */
-	if(purple_xmlnode_get_child(metadata, "stop")) {
-		purple_buddy_icons_set_for_user(purple_connection_get_account(js->gc), from, NULL, 0, NULL);
-	} else {
-		PurpleXmlNode *info, *goodinfo = NULL;
-		gboolean has_children = FALSE;
-
-		/* iterate over all info nodes to get one we can use */
-		for(info = metadata->child; info; info = info->next) {
-			if(info->type == PURPLE_XMLNODE_TYPE_TAG)
-				has_children = TRUE;
-			if(info->type == PURPLE_XMLNODE_TYPE_TAG && purple_strequal(info->name,"info")) {
-				const char *type = purple_xmlnode_get_attrib(info,"type");
-				const char *id = purple_xmlnode_get_attrib(info,"id");
-
-				if(checksum && id && purple_strequal(id, checksum)) {
-					/* we already have that avatar, so we don't have to do anything */
-					goodinfo = NULL;
-					break;
-				}
-				/* We'll only pick the png one for now. It's a very nice image format anyways. */
-				if(id && !goodinfo && purple_strequal(type, "image/png"))
-					goodinfo = info;
-			}
-		}
-		if(has_children == FALSE) {
-			purple_buddy_icons_set_for_user(purple_connection_get_account(js->gc), from, NULL, 0, NULL);
-		} else if(goodinfo) {
-			const char *url = purple_xmlnode_get_attrib(goodinfo, "url");
-			const char *id = purple_xmlnode_get_attrib(goodinfo,"id");
-
-			/* the avatar might either be stored in a pep node, or on a HTTP(S) URL */
-			if(!url) {
-				jabber_pep_request_item(js, from, NS_AVATAR_1_1_DATA, id,
-				                        do_buddy_avatar_update_data);
-			} else {
-				SoupMessage *msg;
-				JabberBuddyAvatarUpdateURLInfo *info = g_new0(JabberBuddyAvatarUpdateURLInfo, 1);
-				info->js = js;
-				info->from = g_strdup(from);
-				info->id = g_strdup(id);
-
-				info->msg = msg = soup_message_new("GET", url);
-				soup_session_send_and_read_async(js->http_conns, msg,
-				                                 G_PRIORITY_DEFAULT, NULL,
-				                                 do_buddy_avatar_update_fromurl,
-				                                 info);
-			}
-		}
-	}
-}
diff --git a/libpurple/protocols/jabber/usernick.h b/libpurple/protocols/jabber/usernick.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/usernick.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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_JABBER_USERNICK_H
-#define PURPLE_JABBER_USERNICK_H
-
-#include "jabber.h"
-
-/* Implementation of XEP-0172 */
-
-void jabber_nick_init(void);
-void jabber_nick_append_menu(GMenu *menu);
-void jabber_nick_add_action_entries(GSimpleActionGroup *group);
-
-#endif /* PURPLE_JABBER_USERNICK_H */
diff --git a/libpurple/protocols/jabber/usernick.c b/libpurple/protocols/jabber/usernick.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/usernick.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "usernick.h"
-#include "pep.h"
-#include <string.h>
-
-static void jabber_nick_cb(JabberStream *js, const char *from, PurpleXmlNode *items) {
-	/* it doesn't make sense to have more than one item here, so let's just pick the first one */
-	PurpleXmlNode *item = purple_xmlnode_get_child(items, "item");
-	JabberBuddy *buddy = jabber_buddy_find(js, from, FALSE);
-	PurpleXmlNode *nick;
-	char *nickname = NULL;
-
-	/* ignore the nick of people not on our buddy list */
-	if (!buddy || !item)
-		return;
-
-	nick = purple_xmlnode_get_child_with_namespace(item, "nick", "http://jabber.org/protocol/nick");
-	if (!nick)
-		return;
-	nickname = purple_xmlnode_get_data(nick);
-	purple_serv_got_alias(js->gc, from, nickname);
-	g_free(nickname);
-}
-
-static void do_nick_set(JabberStream *js, const char *nick) {
-	PurpleXmlNode *publish, *nicknode;
-
-	publish = purple_xmlnode_new("publish");
-	purple_xmlnode_set_attrib(publish,"node","http://jabber.org/protocol/nick");
-	nicknode = purple_xmlnode_new_child(purple_xmlnode_new_child(publish, "item"), "nick");
-	purple_xmlnode_set_namespace(nicknode, "http://jabber.org/protocol/nick");
-
-	if(nick && nick[0] != '\0')
-		purple_xmlnode_insert_data(nicknode, nick, -1);
-
-	jabber_pep_publish(js, publish);
-	/* publish is freed by jabber_pep_publish -> jabber_iq_send -> jabber_iq_free
-		(yay for well-defined memory management rules) */
-}
-
-static void
-do_nick_got_own_nick_cb(JabberStream *js, G_GNUC_UNUSED const char *from,
-                        PurpleXmlNode *items)
-{
-	char *oldnickname = NULL;
-	PurpleXmlNode *item = NULL;
-
-	if (items)
-		item = purple_xmlnode_get_child(items,"item");
-
-	if(item) {
-		PurpleXmlNode *nick = purple_xmlnode_get_child_with_namespace(item,"nick","http://jabber.org/protocol/nick");
-		if(nick)
-			oldnickname = purple_xmlnode_get_data(nick);
-	}
-
-	purple_request_input(js->gc, _("Set User Nickname"), _("Please specify a new nickname for you."),
-		_("This information is visible to all contacts on your contact list, so choose something appropriate."),
-		oldnickname, FALSE, FALSE, NULL, _("Set"), G_CALLBACK(do_nick_set), _("Cancel"), NULL,
-		purple_request_cpar_from_connection(js->gc), js);
-	g_free(oldnickname);
-}
-
-static void
-do_nick_set_nick(G_GNUC_UNUSED GSimpleAction *action, GVariant *parameter,
-                 G_GNUC_UNUSED gpointer data)
-{
-	const char *account_id = NULL;
-	PurpleAccountManager *manager = NULL;
-	PurpleAccount *account = NULL;
-	PurpleConnection *connection = NULL;
-	JabberStream *js = NULL;
-
-	if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) {
-		g_critical("XMPP Set Nickname action parameter is of incorrect type %s",
-		           g_variant_get_type_string(parameter));
-	}
-
-	account_id = g_variant_get_string(parameter, NULL);
-	manager = purple_account_manager_get_default();
-	account = purple_account_manager_find_by_id(manager, account_id);
-	connection = purple_account_get_connection(account);
-	g_clear_object(&account);
-	js = purple_connection_get_protocol_data(connection);
-
-	/* since the nickname might have been changed by another resource of this account, we always have to request the old one
-		from the server to present as the default for the new one */
-	jabber_pep_request_item(js, NULL, "http://jabber.org/protocol/nick", NULL, do_nick_got_own_nick_cb);
-}
-
-void jabber_nick_init(void) {
-	jabber_add_feature("http://jabber.org/protocol/nick", jabber_pep_namespace_only_when_pep_enabled_cb);
-	jabber_pep_register_handler("http://jabber.org/protocol/nick", jabber_nick_cb);
-}
-
-void
-jabber_nick_add_action_entries(GSimpleActionGroup *group) {
-	GActionEntry entries[] = {
-		{
-			.name = "set-nickname",
-			.activate = do_nick_set_nick,
-			.parameter_type = "s",
-		},
-	};
-	gsize nentries = G_N_ELEMENTS(entries);
-
-	g_action_map_add_action_entries(G_ACTION_MAP(group), entries, nentries,
-	                                NULL);
-}
-
-void
-jabber_nick_append_menu(GMenu *menu) {
-	GMenuItem *item = NULL;
-
-	item = g_menu_item_new(_("Set Nickname..."), "prpl-xmpp.set-nickname");
-	g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s",
-	                          "account");
-	g_menu_append_item(menu, item);
-	g_object_unref(item);
-}
diff --git a/libpurple/protocols/jabber/xdata.h b/libpurple/protocols/jabber/xdata.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/xdata.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * @file xdata.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 PURPLE_JABBER_XDATA_H
-#define PURPLE_JABBER_XDATA_H
-
-#include "jabber.h"
-
-#include <purple.h>
-
-typedef struct {
-	char *name;
-	char *handle;
-} JabberXDataAction;
-
-typedef void (*jabber_x_data_cb)(JabberStream *js, PurpleXmlNode *result, gpointer user_data);
-typedef void (*jabber_x_data_action_cb)(JabberStream *js, PurpleXmlNode *result, const char *actionhandle, gpointer user_data);
-void *jabber_x_data_request(JabberStream *js, PurpleXmlNode *packet, jabber_x_data_cb cb, gpointer user_data);
-void *jabber_x_data_request_with_actions(JabberStream *js, PurpleXmlNode *packet, GList *actions, int defaultaction, jabber_x_data_action_cb cb, gpointer user_data);
-
-/*
- * Return the form type (the CDATA of the value child of the FORM_TYPE
- * field entry.
- * E.g., for the following, "http://jabber.org/protocol/muc#roominfo".
- * <x xmlns='jabber:x:data' type='result'>
- *  <field var='FORM_TYPE' type='hidden'>
- *    <value>http://jabber.org/protocol/muc#roominfo</value>
- *  </field>
- * </x>
- *
- * @param form The PurpleXmlNode for the form (the 'x' element)
- * @returns The FORM_TYPE.  Must be freed by caller.
- */
-gchar *jabber_x_data_get_formtype(const PurpleXmlNode *form);
-
-#endif /* PURPLE_JABBER_XDATA_H */
diff --git a/libpurple/protocols/jabber/xdata.c b/libpurple/protocols/jabber/xdata.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/xdata.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * purple - Jabber Protocol Plugin
- *
- * 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 <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "xdata.h"
-
-typedef enum {
-	JABBER_X_DATA_IGNORE = 0,
-	JABBER_X_DATA_TEXT_SINGLE,
-	JABBER_X_DATA_TEXT_MULTI,
-	JABBER_X_DATA_LIST_SINGLE,
-	JABBER_X_DATA_LIST_MULTI,
-	JABBER_X_DATA_BOOLEAN,
-	JABBER_X_DATA_JID_SINGLE
-} jabber_x_data_field_type;
-
-struct jabber_x_data_data {
-	GHashTable *fields;
-	GSList *values;
-	GCallback cb;
-	gpointer user_data;
-	JabberStream *js;
-	GList *actions;
-	PurpleRequestGroup *actiongroup;
-};
-
-static void
-jabber_x_data_ok_cb(struct jabber_x_data_data *data, PurpleRequestPage *page) {
-	PurpleXmlNode *result = purple_xmlnode_new("x");
-	GCallback cb = data->cb;
-	gpointer user_data = data->user_data;
-	JabberStream *js = data->js;
-	char *actionhandle = NULL;
-	gboolean hasActions = (data->actions != NULL);
-	guint n_groups;
-
-	purple_xmlnode_set_namespace(result, "jabber:x:data");
-	purple_xmlnode_set_attrib(result, "type", "submit");
-
-	n_groups = g_list_model_get_n_items(G_LIST_MODEL(page));
-	for(guint group_index = 0; group_index < n_groups; group_index++) {
-		PurpleRequestGroup *group = NULL;
-		guint n_fields;
-
-		group = g_list_model_get_item(G_LIST_MODEL(page), group_index);
-		n_fields = g_list_model_get_n_items(G_LIST_MODEL(group));
-
-		if(group == data->actiongroup) {
-			for(guint field_index = 0; field_index < n_fields; field_index++) {
-				PurpleRequestField *field = NULL;
-				PurpleRequestFieldChoice *choice = NULL;
-				const char *id = NULL;
-				int handleindex;
-
-				field = g_list_model_get_item(G_LIST_MODEL(group), field_index);
-				choice = PURPLE_REQUEST_FIELD_CHOICE(field);
-				id = purple_request_field_get_id(field);
-
-				if(!purple_strequal(id, "libpurple:jabber:xdata:actions")) {
-					g_object_unref(field);
-					continue;
-				}
-
-				handleindex = GPOINTER_TO_INT(purple_request_field_choice_get_value(choice));
-				actionhandle = g_strdup(g_list_nth_data(data->actions, handleindex));
-				g_object_unref(field);
-				break;
-			}
-
-			g_object_unref(group);
-			continue;
-		}
-
-		for(guint field_index = 0; field_index < n_fields; field_index++) {
-			PurpleXmlNode *fieldnode, *valuenode;
-			PurpleRequestField *field = NULL;
-			const char *id = NULL;
-			jabber_x_data_field_type type;
-
-			field = g_list_model_get_item(G_LIST_MODEL(group), field_index);
-			id = purple_request_field_get_id(field);
-			type = GPOINTER_TO_INT(g_hash_table_lookup(data->fields, id));
-
-			switch(type) {
-				case JABBER_X_DATA_TEXT_SINGLE:
-				case JABBER_X_DATA_JID_SINGLE:
-					{
-					PurpleRequestFieldString *sfield = PURPLE_REQUEST_FIELD_STRING(field);
-					const char *value = purple_request_field_string_get_value(sfield);
-					if (value == NULL)
-						break;
-					fieldnode = purple_xmlnode_new_child(result, "field");
-					purple_xmlnode_set_attrib(fieldnode, "var", id);
-					valuenode = purple_xmlnode_new_child(fieldnode, "value");
-					purple_xmlnode_insert_data(valuenode, value, -1);
-					break;
-					}
-				case JABBER_X_DATA_TEXT_MULTI:
-					{
-					PurpleRequestFieldString *sfield = PURPLE_REQUEST_FIELD_STRING(field);
-					const char *value = purple_request_field_string_get_value(sfield);
-					char **pieces, **p;
-					if (value == NULL)
-						break;
-					fieldnode = purple_xmlnode_new_child(result, "field");
-					purple_xmlnode_set_attrib(fieldnode, "var", id);
-
-					pieces = g_strsplit(value, "\n", -1);
-					for(p = pieces; *p != NULL; p++) {
-						valuenode = purple_xmlnode_new_child(fieldnode, "value");
-						purple_xmlnode_insert_data(valuenode, *p, -1);
-					}
-					g_strfreev(pieces);
-					}
-					break;
-				case JABBER_X_DATA_LIST_SINGLE:
-				case JABBER_X_DATA_LIST_MULTI:
-					{
-					PurpleRequestFieldList *lfield = PURPLE_REQUEST_FIELD_LIST(field);
-					GList *selected = purple_request_field_list_get_selected(lfield);
-					char *value;
-					fieldnode = purple_xmlnode_new_child(result, "field");
-					purple_xmlnode_set_attrib(fieldnode, "var", id);
-
-					while(selected) {
-						value = purple_request_field_list_get_data(lfield, selected->data);
-						valuenode = purple_xmlnode_new_child(fieldnode, "value");
-						if(value)
-							purple_xmlnode_insert_data(valuenode, value, -1);
-						selected = selected->next;
-					}
-					}
-					break;
-				case JABBER_X_DATA_BOOLEAN:
-					{
-					PurpleRequestFieldBool *bfield = PURPLE_REQUEST_FIELD_BOOL(field);
-					fieldnode = purple_xmlnode_new_child(result, "field");
-					purple_xmlnode_set_attrib(fieldnode, "var", id);
-					valuenode = purple_xmlnode_new_child(fieldnode, "value");
-					if(purple_request_field_bool_get_value(bfield)) {
-						purple_xmlnode_insert_data(valuenode, "1", -1);
-					} else {
-						purple_xmlnode_insert_data(valuenode, "0", -1);
-					}
-					}
-					break;
-				case JABBER_X_DATA_IGNORE:
-					break;
-			}
-
-			g_object_unref(field);
-		}
-
-		g_object_unref(group);
-	}
-
-	g_hash_table_destroy(data->fields);
-	g_slist_free_full(data->values, g_free);
-	g_list_free_full(data->actions, g_free);
-	g_free(data);
-
-	if(hasActions) {
-		((jabber_x_data_action_cb)cb)(js, result, actionhandle, user_data);
-	} else {
-		((jabber_x_data_cb)cb)(js, result, user_data);
-	}
-
-	g_free(actionhandle);
-}
-
-static void
-jabber_x_data_cancel_cb(struct jabber_x_data_data *data,
-                        G_GNUC_UNUSED PurpleRequestPage *page)
-{
-	PurpleXmlNode *result = purple_xmlnode_new("x");
-	GCallback cb = data->cb;
-	gpointer user_data = data->user_data;
-	JabberStream *js = data->js;
-	gboolean hasActions = (data->actions != NULL);
-	g_hash_table_destroy(data->fields);
-	g_slist_free_full(data->values, g_free);
-	g_list_free_full(data->actions, g_free);
-	g_free(data);
-
-	purple_xmlnode_set_namespace(result, "jabber:x:data");
-	purple_xmlnode_set_attrib(result, "type", "cancel");
-
-	if(hasActions) {
-		((jabber_x_data_action_cb)cb)(js, result, NULL, user_data);
-	} else {
-		((jabber_x_data_cb)cb)(js, result, user_data);
-	}
-}
-
-void *jabber_x_data_request(JabberStream *js, PurpleXmlNode *packet, jabber_x_data_cb cb, gpointer user_data)
-{
-	return jabber_x_data_request_with_actions(js, packet, NULL, 0,
-	                                          (jabber_x_data_action_cb)(GCallback)cb,
-	                                          user_data);
-}
-
-void *jabber_x_data_request_with_actions(JabberStream *js, PurpleXmlNode *packet, GList *actions, int defaultaction, jabber_x_data_action_cb cb, gpointer user_data)
-{
-	void *handle;
-	PurpleXmlNode *fn, *x;
-	PurpleRequestPage *page;
-	PurpleRequestGroup *group;
-	PurpleRequestField *field = NULL;
-
-	char *title = NULL;
-	char *instructions = NULL;
-
-	struct jabber_x_data_data *data = g_new0(struct jabber_x_data_data, 1);
-
-	data->fields = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
-	data->user_data = user_data;
-	data->cb = G_CALLBACK(cb);
-	data->js = js;
-
-	page = purple_request_page_new();
-	group = purple_request_group_new(NULL);
-	purple_request_page_add_group(page, group);
-
-	for(fn = purple_xmlnode_get_child(packet, "field"); fn; fn = purple_xmlnode_get_next_twin(fn)) {
-		PurpleXmlNode *valuenode;
-		const char *type = purple_xmlnode_get_attrib(fn, "type");
-		const char *label = purple_xmlnode_get_attrib(fn, "label");
-		const char *var = purple_xmlnode_get_attrib(fn, "var");
-		char *value = NULL;
-
-		if(!type)
-			type = "text-single";
-
-		if(!var && !purple_strequal(type, "fixed"))
-			continue;
-		if(!label)
-			label = var;
-
-		if(purple_strequal(type, "text-private")) {
-			if((valuenode = purple_xmlnode_get_child(fn, "value")))
-				value = purple_xmlnode_get_data(valuenode);
-
-			field = purple_request_field_string_new(var, label,
-					value ? value : "", FALSE);
-			purple_request_field_string_set_masked(PURPLE_REQUEST_FIELD_STRING(field),
-			                                       TRUE);
-			purple_request_group_add_field(group, field);
-
-			g_hash_table_replace(data->fields, g_strdup(var), GINT_TO_POINTER(JABBER_X_DATA_TEXT_SINGLE));
-
-			g_free(value);
-		} else if(purple_strequal(type, "text-multi") || purple_strequal(type, "jid-multi")) {
-			GString *str = g_string_new("");
-
-			for(valuenode = purple_xmlnode_get_child(fn, "value"); valuenode;
-					valuenode = purple_xmlnode_get_next_twin(valuenode)) {
-
-				if(!(value = purple_xmlnode_get_data(valuenode)))
-					continue;
-
-				g_string_append_printf(str, "%s\n", value);
-				g_free(value);
-			}
-
-			field = purple_request_field_string_new(var, label,
-					str->str, TRUE);
-			purple_request_group_add_field(group, field);
-
-			g_hash_table_replace(data->fields, g_strdup(var), GINT_TO_POINTER(JABBER_X_DATA_TEXT_MULTI));
-
-			g_string_free(str, TRUE);
-		} else if(purple_strequal(type, "list-single") || purple_strequal(type, "list-multi")) {
-			PurpleRequestFieldList *list_field = NULL;
-			PurpleXmlNode *optnode;
-			GList *selected = NULL;
-
-			field = purple_request_field_list_new(var, label);
-			list_field = PURPLE_REQUEST_FIELD_LIST(field);
-
-			if(purple_strequal(type, "list-multi")) {
-				purple_request_field_list_set_multi_select(list_field, TRUE);
-				g_hash_table_replace(data->fields, g_strdup(var),
-						GINT_TO_POINTER(JABBER_X_DATA_LIST_MULTI));
-			} else {
-				g_hash_table_replace(data->fields, g_strdup(var),
-						GINT_TO_POINTER(JABBER_X_DATA_LIST_SINGLE));
-			}
-
-			for(valuenode = purple_xmlnode_get_child(fn, "value"); valuenode;
-					valuenode = purple_xmlnode_get_next_twin(valuenode)) {
-				char *data = purple_xmlnode_get_data(valuenode);
-				if (data != NULL) {
-					selected = g_list_prepend(selected, data);
-				}
-			}
-
-			for(optnode = purple_xmlnode_get_child(fn, "option"); optnode;
-					optnode = purple_xmlnode_get_next_twin(optnode)) {
-				const char *lbl;
-
-				if(!(valuenode = purple_xmlnode_get_child(optnode, "value")))
-					continue;
-
-				if(!(value = purple_xmlnode_get_data(valuenode)))
-					continue;
-
-				if(!(lbl = purple_xmlnode_get_attrib(optnode, "label")))
-					lbl = value;
-
-				data->values = g_slist_prepend(data->values, value);
-
-				purple_request_field_list_add_icon(list_field, lbl, NULL, value);
-				if(g_list_find_custom(selected, value, (GCompareFunc)strcmp)) {
-					purple_request_field_list_add_selected(list_field, lbl);
-				}
-			}
-			purple_request_group_add_field(group, field);
-
-			g_list_free_full(selected, g_free);
-		} else if(purple_strequal(type, "boolean")) {
-			gboolean def = FALSE;
-
-			if((valuenode = purple_xmlnode_get_child(fn, "value")))
-				value = purple_xmlnode_get_data(valuenode);
-
-			if(value && (!g_ascii_strcasecmp(value, "yes") ||
-						!g_ascii_strcasecmp(value, "true") || !g_ascii_strcasecmp(value, "1")))
-				def = TRUE;
-
-			field = purple_request_field_bool_new(var, label, def);
-			purple_request_group_add_field(group, field);
-
-			g_hash_table_replace(data->fields, g_strdup(var), GINT_TO_POINTER(JABBER_X_DATA_BOOLEAN));
-
-			g_free(value);
-		} else if(purple_strequal(type, "fixed")) {
-			if((valuenode = purple_xmlnode_get_child(fn, "value")))
-				value = purple_xmlnode_get_data(valuenode);
-
-			if(value != NULL) {
-				field = purple_request_field_label_new("", value);
-				purple_request_group_add_field(group, field);
-
-				g_free(value);
-			}
-		} else if(purple_strequal(type, "hidden")) {
-			if((valuenode = purple_xmlnode_get_child(fn, "value")))
-				value = purple_xmlnode_get_data(valuenode);
-
-			field = purple_request_field_string_new(var, "", value ? value : "",
-					FALSE);
-			purple_request_field_set_visible(field, FALSE);
-			purple_request_group_add_field(group, field);
-
-			g_hash_table_replace(data->fields, g_strdup(var), GINT_TO_POINTER(JABBER_X_DATA_TEXT_SINGLE));
-
-			g_free(value);
-		} else { /* text-single, jid-single, and the default */
-			if((valuenode = purple_xmlnode_get_child(fn, "value")))
-				value = purple_xmlnode_get_data(valuenode);
-
-			field = purple_request_field_string_new(var, label,
-					value ? value : "", FALSE);
-			purple_request_group_add_field(group, field);
-
-			if(purple_strequal(type, "jid-single")) {
-				purple_request_field_set_type_hint(field, "screenname");
-				g_hash_table_replace(data->fields, g_strdup(var), GINT_TO_POINTER(JABBER_X_DATA_JID_SINGLE));
-			} else {
-				g_hash_table_replace(data->fields, g_strdup(var), GINT_TO_POINTER(JABBER_X_DATA_TEXT_SINGLE));
-			}
-
-			g_free(value);
-		}
-
-		if(field && purple_xmlnode_get_child(fn, "required"))
-			purple_request_field_set_required(field,TRUE);
-	}
-
-	if(actions != NULL) {
-		PurpleRequestField *field = NULL;
-		PurpleRequestFieldChoice *choice = NULL;
-		GList *action;
-		int i;
-
-		data->actiongroup = group = purple_request_group_new(_("Actions"));
-		purple_request_page_add_group(page, group);
-		field = purple_request_field_choice_new("libpurple:jabber:xdata:actions",
-		                                        _("Select an action"),
-		                                        GINT_TO_POINTER(defaultaction));
-		choice = PURPLE_REQUEST_FIELD_CHOICE(field);
-
-		for(i = 0, action = actions; action; action = g_list_next(action), i++) {
-			JabberXDataAction *a = action->data;
-
-			purple_request_field_choice_add(choice, a->name, GINT_TO_POINTER(i));
-			data->actions = g_list_append(data->actions, g_strdup(a->handle));
-		}
-		purple_request_field_set_required(field, TRUE);
-		purple_request_group_add_field(group, field);
-	}
-
-	if((x = purple_xmlnode_get_child(packet, "title")))
-		title = purple_xmlnode_get_data(x);
-
-	if((x = purple_xmlnode_get_child(packet, "instructions")))
-		instructions = purple_xmlnode_get_data(x);
-
-	handle = purple_request_fields(js->gc, title, title, instructions, page,
-			_("OK"), G_CALLBACK(jabber_x_data_ok_cb),
-			_("Cancel"), G_CALLBACK(jabber_x_data_cancel_cb),
-			purple_request_cpar_from_connection(js->gc),
-			data);
-
-	g_free(title);
-	g_free(instructions);
-
-	return handle;
-}
-
-gchar *
-jabber_x_data_get_formtype(const PurpleXmlNode *form)
-{
-	PurpleXmlNode *field;
-
-	g_return_val_if_fail(form != NULL, NULL);
-
-	for (field = purple_xmlnode_get_child((PurpleXmlNode *)form, "field"); field;
-			field = purple_xmlnode_get_next_twin(field)) {
-		const char *var = purple_xmlnode_get_attrib(field, "var");
-		if (purple_strequal(var, "FORM_TYPE")) {
-			PurpleXmlNode *value = purple_xmlnode_get_child(field, "value");
-			if (value)
-				return purple_xmlnode_get_data(value);
-			else
-				/* An interesting corner case... Looking for a second
-				 * FORM_TYPE would be more considerate, but I'm in favor
-				 * of not helping broken clients.
-				 */
-				return NULL;
-		}
-	}
-
-	/* Erm, none found :( */
-	return NULL;
-}
-
diff --git a/libpurple/protocols/jabber/xmpp.h b/libpurple/protocols/jabber/xmpp.h
deleted file mode 100644
--- a/libpurple/protocols/jabber/xmpp.h
+++ /dev/null
@@ -1,47 +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_JABBER_XMPP_H
-#define PURPLE_JABBER_XMPP_H
-
-#include "jabber.h"
-
-#define XMPP_PROTOCOL_ID "prpl-jabber"
-
-#define XMPP_TYPE_PROTOCOL (xmpp_protocol_get_type())
-G_DECLARE_FINAL_TYPE(XMPPProtocol, xmpp_protocol, XMPP, PROTOCOL,
-                     JabberProtocol)
-
-/**
- * Registers the XMPPProtocol type in the type system.
- */
-G_GNUC_INTERNAL
-void xmpp_protocol_register(PurplePlugin *plugin);
-
-G_GNUC_INTERNAL
-PurpleProtocol *xmpp_protocol_new(void);
-
-/**
- * Returns the GType for the XMPPProtocol object.
- */
-
-#endif /* PURPLE_JABBER_XMPP_H */
diff --git a/libpurple/protocols/jabber/xmpp.c b/libpurple/protocols/jabber/xmpp.c
deleted file mode 100644
--- a/libpurple/protocols/jabber/xmpp.c
+++ /dev/null
@@ -1,147 +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 <purpleconfig.h>
-
-#include <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "xmpp.h"
-
-struct _XMPPProtocol {
-	JabberProtocol parent;
-};
-
-static GList *
-xmpp_protocol_get_account_options(G_GNUC_UNUSED PurpleProtocol *protocol) {
-	PurpleAccountOption *option;
-	PurpleKeyValuePair *kvp = NULL;
-	GList *opts = NULL, *encryption_values = NULL;
-
-	/* build the list of encryption types we support */
-	kvp = purple_key_value_pair_new(_("Require encryption"), "require_tls");
-	encryption_values = g_list_append(encryption_values, kvp);
-
-	kvp = purple_key_value_pair_new(_("Use encryption if available"),
-	                                "opportunistic_tls");
-	encryption_values = g_list_append(encryption_values, kvp);
-
-	kvp = purple_key_value_pair_new(_("Use old-style SSL"), "old_ssl");
-	encryption_values = g_list_append(encryption_values, kvp);
-
-	/* build all the options */
-	option = purple_account_option_list_new(_("Connection security"),
-	                                        "connection_security",
-	                                        encryption_values);
-	opts = g_list_append(opts, option);
-
-	option = purple_account_option_bool_new(_("Allow plaintext auth over "
-	                                          "unencrypted streams"),
-	                                        "auth_plain_in_clear", FALSE);
-	opts = g_list_append(opts, option);
-
-	option = purple_account_option_int_new(_("Connect port"), "port", 5222);
-	opts = g_list_append(opts, option);
-
-	option = purple_account_option_string_new(_("Connect server"),
-	                                          "connect_server", NULL);
-	opts = g_list_append(opts, option);
-
-	option = purple_account_option_string_new(_("File transfer proxies"),
-	                                          "ft_proxies", NULL);
-	opts = g_list_append(opts, option);
-
-	option = purple_account_option_string_new(_("BOSH URL"), "bosh_url", NULL);
-	opts = g_list_append(opts, option);
-
-	return opts;
-}
-
-static GList *
-xmpp_protocol_get_user_splits(G_GNUC_UNUSED PurpleProtocol *protocol) {
-	GList *splits = NULL;
-	PurpleAccountUserSplit *split;
-
-	/* Translators: 'domain' is used here in the context of Internet domains,
-	 * e.g. pidgin.im.
-	 */
-	split = purple_account_user_split_new(_("Domain"), NULL, '@');
-	purple_account_user_split_set_reverse(split, FALSE);
-	splits = g_list_append(splits, split);
-
-	split = purple_account_user_split_new(_("Resource"), "", '/');
-	purple_account_user_split_set_reverse(split, FALSE);
-	splits = g_list_append(splits, split);
-
-	return splits;
-}
-
-static void
-xmpp_protocol_init(G_GNUC_UNUSED XMPPProtocol *self) {
-	purple_prefs_remove("/plugins/prpl/jabber");
-}
-
-static void
-xmpp_protocol_class_init(XMPPProtocolClass *klass) {
-	PurpleProtocolClass *protocol_class = PURPLE_PROTOCOL_CLASS(klass);
-
-	protocol_class->get_account_options = xmpp_protocol_get_account_options;
-	protocol_class->get_user_splits = xmpp_protocol_get_user_splits;
-}
-
-static void
-xmpp_protocol_class_finalize(G_GNUC_UNUSED XMPPProtocolClass *klass)
-{
-}
-
-G_DEFINE_DYNAMIC_TYPE_EXTENDED(XMPPProtocol, xmpp_protocol,
-                               JABBER_TYPE_PROTOCOL, G_TYPE_FLAG_FINAL, {})
-
-/* This exists solely because the above macro makes xmpp_protocol_register_type
- * static. */
-void
-xmpp_protocol_register(PurplePlugin *plugin)
-{
-	xmpp_protocol_register_type(G_TYPE_MODULE(plugin));
-}
-
-PurpleProtocol *
-xmpp_protocol_new(void) {
-	PurpleProtocolOptions options;
-
-	options = OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME |
-	          OPT_PROTO_MAIL_CHECK | OPT_PROTO_SLASH_COMMANDS_NATIVE |
-	          OPT_PROTO_PASSWORD_OPTIONAL;
-
-	return g_object_new(
-		XMPP_TYPE_PROTOCOL,
-		"id", XMPP_PROTOCOL_ID,
-		"name", "XMPP (Deprecated)",
-		"description", _("Extensible Messaging and Presence Protocol for IM, "
-		                 "voice, and video."),
-		"icon-name", "im-jabber",
-		"icon-resource-path", "/im/pidgin/libpurple/xmpp/icons",
-		"options", options,
-		NULL
-	);
-}
diff --git a/libpurple/protocols/meson.build b/libpurple/protocols/meson.build
deleted file mode 100644
--- a/libpurple/protocols/meson.build
+++ /dev/null
@@ -1,1 +0,0 @@
-subdir('jabber')
diff --git a/meson.build b/meson.build
--- a/meson.build
+++ b/meson.build
@@ -266,7 +266,7 @@
 
 dependency('shoes', required : false)
 
-DEFAULT_PRPLS = ['demo', 'ircv3', 'jabber', 'xmpp']
+DEFAULT_PRPLS = ['demo', 'ircv3', 'xmpp']
 
 dynamic_list = get_option('dynamic-prpls').split(',')
 if dynamic_list == ['all']
@@ -285,7 +285,6 @@
 
 DYNAMIC_DEMO = DYNAMIC_PRPLS.contains('demo')
 DYNAMIC_IRCV3 = DYNAMIC_PRPLS.contains('ircv3')
-DYNAMIC_JABBER = DYNAMIC_PRPLS.contains('jabber')
 DYNAMIC_XMPP = DYNAMIC_PRPLS.contains('xmpp')
 
 add_project_arguments(
diff --git a/po/POTFILES.in b/po/POTFILES.in
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -62,45 +62,6 @@
 libpurple/plugins/wincred/wincred.c
 libpurple/prefs.c
 libpurple/protocols.c
-libpurple/protocols/jabber/adhoccommands.c
-libpurple/protocols/jabber/auth.c
-libpurple/protocols/jabber/auth_digest_md5.c
-libpurple/protocols/jabber/auth_plain.c
-libpurple/protocols/jabber/auth_scram.c
-libpurple/protocols/jabber/auth_webex.c
-libpurple/protocols/jabber/bosh.c
-libpurple/protocols/jabber/buddy.c
-libpurple/protocols/jabber/caps.c
-libpurple/protocols/jabber/chat.c
-libpurple/protocols/jabber/data.c
-libpurple/protocols/jabber/disco.c
-libpurple/protocols/jabber/ibb.c
-libpurple/protocols/jabber/iq.c
-libpurple/protocols/jabber/jabber.c
-libpurple/protocols/jabber/jingle/content.c
-libpurple/protocols/jabber/jingle/iceudp.c
-libpurple/protocols/jabber/jingle/jingle.c
-libpurple/protocols/jabber/jingle/rawudp.c
-libpurple/protocols/jabber/jingle/rtp.c
-libpurple/protocols/jabber/jingle/session.c
-libpurple/protocols/jabber/jingle/transport.c
-libpurple/protocols/jabber/jutil.c
-libpurple/protocols/jabber/message.c
-libpurple/protocols/jabber/oob.c
-libpurple/protocols/jabber/parser.c
-libpurple/protocols/jabber/pep.c
-libpurple/protocols/jabber/ping.c
-libpurple/protocols/jabber/presence.c
-libpurple/protocols/jabber/roster.c
-libpurple/protocols/jabber/si.c
-libpurple/protocols/jabber/tests/test_jabber_caps.c
-libpurple/protocols/jabber/tests/test_jabber_digest_md5.c
-libpurple/protocols/jabber/tests/test_jabber_jutil.c
-libpurple/protocols/jabber/tests/test_jabber_scram.c
-libpurple/protocols/jabber/useravatar.c
-libpurple/protocols/jabber/usernick.c
-libpurple/protocols/jabber/xdata.c
-libpurple/protocols/jabber/xmpp.c
 libpurple/proxy.c
 libpurple/purpleaccount.c
 libpurple/purpleaccountmanager.c
