# HG changeset patch
# Node ID 9519814ad7e0
# Parent  69702e419730
diff --git a/libpurple/protocols/irc/cmds.c b/libpurple/protocols/irc/cmds.c
deleted file mode 100644
--- a/libpurple/protocols/irc/cmds.c
+++ /dev/null
@@ -1,792 +0,0 @@
-/**
- * purple
- *
- * Copyright (C) 2003, Ethan Blanton <eblanton@cs.purdue.edu>
- *
- * 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 "irc.h"
-
-
-static void irc_do_mode(struct irc_conn *irc, const char *target, const char *sign, char **ops);
-
-int
-irc_cmd_default(struct irc_conn *irc, const char *cmd, const char *target,
-                G_GNUC_UNUSED const char **args)
-{
-	PurpleConversation *convo;
-	PurpleConversationManager *manager;
-	char *buf;
-
-	manager = purple_conversation_manager_get_default();
-	convo = purple_conversation_manager_find(manager, irc->account, target);
-
-	if (!convo) {
-		return 1;
-	}
-
-	buf = g_strdup_printf(_("Unknown command: %s"), cmd);
-	purple_conversation_write_system_message(convo, buf, PURPLE_MESSAGE_NO_LOG);
-	g_free(buf);
-
-	return 1;
-}
-
-int
-irc_cmd_away(struct irc_conn *irc, const char *cmd,
-             G_GNUC_UNUSED const char *target, const char **args)
-{
-	char *buf, *message;
-
-	if (args[0] && !purple_strequal(cmd, "back")) {
-		message = purple_markup_strip_html(args[0]);
-		purple_util_chrreplace(message, '\n', ' ');
-		buf = irc_format(irc, "v:", "AWAY", message);
-		g_free(message);
-	} else {
-		buf = irc_format(irc, "v", "AWAY");
-	}
-	irc_send(irc, buf);
-	g_free(buf);
-
-	return 0;
-}
-
-int
-irc_cmd_ctcp(struct irc_conn *irc, G_GNUC_UNUSED const char *cmd,
-             G_GNUC_UNUSED const char *target, const char **args)
-{
-	/* we have defined args as args[0] is target and args[1] is ctcp command */
-	char *buf;
-	GString *string;
-
-	/* check if we have args */
-	if (!args || !args[0] || !args[1])
-		return 0;
-
-	/* TODO:strip newlines or send each line as separate ctcp or something
-	 * actually, this shouldn't be done here but somewhere else since irc should support escaping newlines */
-
-	string = g_string_new(args[1]);
-	g_string_prepend_c (string,'\001');
-	g_string_append_c (string,'\001');
-	buf = irc_format(irc, "vn:", "PRIVMSG", args[0], string->str);
-	g_string_free(string,TRUE);
-
-	irc_send(irc, buf);
-	g_free(buf);
-
-	return 1;
-}
-
-int irc_cmd_ctcp_action(struct irc_conn *irc, const char *cmd, const char *target, const char **args)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-	gchar *action, *escaped, *dst, **newargs;
-	const gchar *src, *me;
-	gchar *msg;
-	PurpleContactInfo *info = NULL;
-	PurpleConversation *convo;
-	PurpleConversationManager *manager;
-	PurpleMessage *pmsg;
-
-	if (!args || !args[0] || !gc) {
-		return 0;
-	}
-
-	info = PURPLE_CONTACT_INFO(irc->account);
-	me = purple_contact_info_get_name_for_display(info);
-
-	manager = purple_conversation_manager_get_default();
-	convo = purple_conversation_manager_find(manager, irc->account, target);
-
-	msg = g_strdup_printf("/me %s", args[0]);
-
-	/* XXX: we'd prefer to keep this in conversation.c */
-	if (PURPLE_IS_IM_CONVERSATION(convo)) {
-		const gchar *conv_name = purple_conversation_get_name(convo);
-		pmsg = purple_message_new_outgoing(irc->account, me, conv_name, msg,
-		                                   0);
-
-		purple_signal_emit(purple_conversations_get_handle(),
-			"sending-im-msg", irc->account, pmsg);
-	} else {
-		pmsg = purple_message_new_outgoing(irc->account, me, NULL, msg, 0);
-
-		purple_signal_emit(purple_conversations_get_handle(),
-			"sending-chat-msg", irc->account, pmsg,
-			purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(convo)));
-	}
-
-	/* We free the original message because it could have been changed by the
-	 * sending-*-msg signals above.
-	 */
-	g_free(msg);
-
-	/* if the message was eaten by a signal we bail */
-	if(purple_message_is_empty(pmsg)) {
-		g_object_unref(G_OBJECT(pmsg));
-
-		return 0;
-	}
-
-	/* create a copy of the updated message, which should not be null because
-	 * we just tested if it was empty in the above conditional.
-	 */
-	msg = g_strdup(purple_message_get_contents(pmsg));
-
-	if (strncmp(msg, "/me ", 4) != 0) {
-		newargs = g_new0(char *, 2);
-		newargs[0] = g_strdup(target);
-		newargs[1] = msg;
-
-		irc_cmd_privmsg(irc, cmd, target, (const char **)newargs);
-
-		g_free(newargs[0]);
-		g_free(newargs);
-	} else {
-		action = g_malloc(strlen(&msg[4]) + 10);
-
-		sprintf(action, "\001ACTION ");
-
-		src = &msg[4];
-		dst = action + 8;
-		while (*src) {
-			if (*src == '\n') {
-				if (*(src + 1) == '\0') {
-					break;
-				} else {
-					*dst++ = ' ';
-					src++;
-					continue;
-				}
-			}
-			*dst++ = *src++;
-		}
-		*dst++ = '\001';
-		*dst = '\0';
-
-		newargs = g_new0(char *, 2);
-		newargs[0] = g_strdup(target);
-		newargs[1] = action;
-		irc_cmd_privmsg(irc, cmd, target, (const char **)newargs);
-		g_free(newargs[0]);
-		g_free(newargs);
-		g_free(action);
-	}
-
-	/* XXX: we'd prefer to keep this in conversation.c */
-	if (PURPLE_IS_IM_CONVERSATION(convo)) {
-		purple_signal_emit(purple_conversations_get_handle(),
-			"sent-im-msg", irc->account, pmsg);
-	} else {
-		purple_signal_emit(purple_conversations_get_handle(),
-			"sent-chat-msg", irc->account, pmsg,
-			purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(convo)));
-	}
-
-	g_free(msg);
-
-	if (convo) {
-		escaped = g_markup_escape_text(args[0], -1);
-		action = g_strdup_printf("/me %s", escaped);
-		g_free(escaped);
-		if (action[strlen(action) - 1] == '\n') {
-			action[strlen(action) - 1] = '\0';
-		}
-		if (PURPLE_IS_CHAT_CONVERSATION(convo)) {
-			purple_serv_got_chat_in(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(convo)),
-			                 purple_connection_get_display_name(gc),
-			                 PURPLE_MESSAGE_SEND, action, time(NULL));
-		} else {
-			purple_message_set_recipient(pmsg,
-			                             purple_connection_get_display_name(gc));
-			purple_conversation_write_message(convo, pmsg);
-		}
-		g_free(action);
-	}
-
-	g_object_unref(G_OBJECT(pmsg));
-
-	return 1;
-}
-
-int
-irc_cmd_ctcp_version(struct irc_conn *irc, G_GNUC_UNUSED const char *cmd,
-                     G_GNUC_UNUSED const char *target, const char **args)
-{
-	char *buf;
-
-	if (!args || !args[0])
-		return 0;
-
-	buf = irc_format(irc, "vn:", "PRIVMSG", args[0], "\001VERSION\001");
-	irc_send(irc, buf);
-	g_free(buf);
-
-	return 0;
-}
-
-int
-irc_cmd_invite(struct irc_conn *irc, G_GNUC_UNUSED const char *cmd,
-               const char *target, const char **args)
-{
-	char *buf;
-
-	if (!args || !args[0] || !(args[1] || target))
-		return 0;
-
-	buf = irc_format(irc, "vnc", "INVITE", args[0], args[1] ? args[1] : target);
-	irc_send(irc, buf);
-	g_free(buf);
-
-	return 0;
-}
-
-int
-irc_cmd_join(struct irc_conn *irc, G_GNUC_UNUSED const char *cmd,
-             G_GNUC_UNUSED const char *target, const char **args)
-{
-	char *buf;
-
-	if (!args || !args[0])
-		return 0;
-
-	if (args[1])
-		buf = irc_format(irc, "vcv", "JOIN", args[0], args[1]);
-	else
-		buf = irc_format(irc, "vc", "JOIN", args[0]);
-	irc_send(irc, buf);
-	g_free(buf);
-
-	return 0;
-}
-
-int
-irc_cmd_kick(struct irc_conn *irc, G_GNUC_UNUSED const char *cmd,
-             const char *target, const char **args)
-{
-	PurpleConversationManager *manager;
-	char *buf;
-
-	if(!args || !args[0]) {
-		return 0;
-	}
-
-	manager = purple_conversation_manager_get_default();
-	if(!purple_conversation_manager_find_chat(manager, irc->account, target)) {
-		return 0;
-	}
-
-	if(args[1]) {
-		buf = irc_format(irc, "vcn:", "KICK", target, args[0], args[1]);
-	} else {
-		buf = irc_format(irc, "vcn", "KICK", target, args[0]);
-	}
-	irc_send(irc, buf);
-	g_free(buf);
-
-	return 0;
-}
-
-int
-irc_cmd_list(struct irc_conn *irc, G_GNUC_UNUSED const char *cmd,
-             G_GNUC_UNUSED const char *target, G_GNUC_UNUSED const char **args)
-{
-	purple_roomlist_show_with_account(irc->account);
-
-	return 0;
-}
-
-int irc_cmd_mode(struct irc_conn *irc, const char *cmd, const char *target, const char **args)
-{
-	PurpleConnection *gc;
-	char *buf;
-
-	if (!args)
-		return 0;
-
-	if (purple_strequal(cmd, "mode")) {
-		if (!args[0] && irc_ischannel(target))
-			buf = irc_format(irc, "vc", "MODE", target);
-		else if (args[0] && (*args[0] == '+' || *args[0] == '-'))
-			buf = irc_format(irc, "vcn", "MODE", target, args[0]);
-		else if (args[0])
-			buf = irc_format(irc, "vn", "MODE", args[0]);
-		else
-			return 0;
-	} else if (purple_strequal(cmd, "umode")) {
-		if (!args[0])
-			return 0;
-		gc = purple_account_get_connection(irc->account);
-		buf = irc_format(irc, "vnc", "MODE", purple_connection_get_display_name(gc), args[0]);
-	} else {
-		return 0;
-	}
-
-	irc_send(irc, buf);
-	g_free(buf);
-
-	return 0;
-}
-
-int
-irc_cmd_names(struct irc_conn *irc, G_GNUC_UNUSED const char *cmd,
-              const char *target, const char **args)
-{
-	char *buf;
-
-	if (!args || (!args[0] && !irc_ischannel(target)))
-		return 0;
-
-	buf = irc_format(irc, "vc", "NAMES", args[0] ? args[0] : target);
-	irc_send(irc, buf);
-	g_free(buf);
-
-	return 0;
-}
-
-int
-irc_cmd_nick(struct irc_conn *irc, G_GNUC_UNUSED const char *cmd,
-             G_GNUC_UNUSED const char *target, const char **args)
-{
-	char *buf;
-
-	if (!args || !args[0])
-		return 0;
-
-	buf = irc_format(irc, "v:", "NICK", args[0]);
-	g_free(irc->reqnick);
-	irc->reqnick = g_strdup(args[0]);
-	irc->nickused = FALSE;
-	irc_send(irc, buf);
-	g_free(buf);
-
-	return 0;
-}
-
-int irc_cmd_op(struct irc_conn *irc, const char *cmd, const char *target, const char **args)
-{
-	char **nicks, **ops, *sign, *mode;
-	int i = 0, used = 0;
-
-	if (!args || !args[0] || !*args[0])
-		return 0;
-
-	if (purple_strequal(cmd, "op")) {
-		sign = "+";
-		mode = "o";
-	} else if (purple_strequal(cmd, "deop")) {
-		sign = "-";
-		mode = "o";
-	} else if (purple_strequal(cmd, "voice")) {
-		sign = "+";
-		mode = "v";
-	} else if (purple_strequal(cmd, "devoice")) {
-		sign = "-";
-		mode = "v";
-	} else {
-		purple_debug_error("irc", "invalid 'op' command '%s'", cmd);
-		return 0;
-	}
-
-	nicks = g_strsplit(args[0], " ", -1);
-
-	for (i = 0; nicks[i]; i++)
-		/* nothing */;
-	ops = g_new0(char *, i * 2 + 1);
-
-	for (i = 0; nicks[i]; i++) {
-		if (*nicks[i]) {
-			ops[used++] = mode;
-			ops[used++] = nicks[i];
-		}
-	}
-
-	irc_do_mode(irc, target, sign, ops);
-	g_free(ops);
-	g_strfreev(nicks);
-
-	return 0;
-}
-
-int
-irc_cmd_part(struct irc_conn *irc, G_GNUC_UNUSED const char *cmd,
-             const char *target, const char **args)
-{
-	char *buf;
-
-	if (!args)
-		return 0;
-
-	if (args[1])
-		buf = irc_format(irc, "vc:", "PART", args[0] ? args[0] : target, args[1]);
-	else
-		buf = irc_format(irc, "vc", "PART", args[0] ? args[0] : target);
-	irc_send(irc, buf);
-	g_free(buf);
-
-	return 0;
-}
-
-int
-irc_cmd_ping(struct irc_conn *irc, G_GNUC_UNUSED const char *cmd,
-             const char *target, const char **args)
-{
-	char *stamp;
-	char *buf;
-
-	if (args && args[0]) {
-		if (irc_ischannel(args[0]))
-			return 0;
-		stamp = g_strdup_printf("\001PING %" G_GINT64_FORMAT "\001",
-		                        g_get_monotonic_time());
-		buf = irc_format(irc, "vn:", "PRIVMSG", args[0], stamp);
-		g_free(stamp);
-	} else if (target) {
-		stamp = g_strdup_printf("%s %" G_GINT64_FORMAT, target,
-		                        g_get_monotonic_time());
-		buf = irc_format(irc, "v:", "PING", stamp);
-		g_free(stamp);
-	} else {
-		stamp = g_strdup_printf("%" G_GUINT64_FORMAT, g_get_monotonic_time());
-		buf = irc_format(irc, "vv", "PING", stamp);
-		g_free(stamp);
-	}
-	irc_send(irc, buf);
-	g_free(buf);
-
-	return 0;
-}
-
-int
-irc_cmd_privmsg(struct irc_conn *irc, const char *cmd,
-                G_GNUC_UNUSED const char *target, const char **args)
-{
-	int max_privmsg_arg_len;
-	const char *cur, *end;
-	gchar *salvaged;
-	char *msg, *buf;
-
-	if (!args || !args[0] || !args[1])
-		return 0;
-
-	max_privmsg_arg_len = IRC_MAX_MSG_SIZE - strlen(args[0]) - 64;
-	salvaged = g_utf8_make_valid(args[1], -1);
-	cur = salvaged;
-	end = salvaged;
-	while (*end && *cur) {
-		end = strchr(cur, '\n');
-		if (!end)
-			end = cur + strlen(cur);
-		if (end - cur > max_privmsg_arg_len) {
-			/* this call is used to find the last valid character position in the first
-			 * max_privmsg_arg_len bytes of the utf-8 message
-			 */
-			g_utf8_validate(cur, max_privmsg_arg_len, &end);
-		}
-
-		msg = g_strndup(cur, end - cur);
-
-		if(purple_strequal(cmd, "notice"))
-			buf = irc_format(irc, "vt:", "NOTICE", args[0], msg);
-		else
-			buf = irc_format(irc, "vt:", "PRIVMSG", args[0], msg);
-
-		irc_send(irc, buf);
-		g_free(msg);
-		g_free(buf);
-		cur = end;
-		if(*cur == '\n') {
-			cur++;
-		}
-	}
-
-	g_free(salvaged);
-
-	return 0;
-}
-
-int
-irc_cmd_quit(struct irc_conn *irc, G_GNUC_UNUSED const char *cmd,
-             G_GNUC_UNUSED const char *target, const char **args)
-{
-	char *buf;
-
-	if (!irc->quitting) {
-		/*
-		 * Use purple_account_get_string(irc->account, "quitmsg", IRC_DEFAULT_QUIT)
-		 * and uncomment the appropriate account preference in irc.c if we
-		 * decide we want custom quit messages.
-		 */
-		buf = irc_format(irc, "v:", "QUIT", (args && args[0]) ? args[0] : IRC_DEFAULT_QUIT);
-		irc_send(irc, buf);
-		g_free(buf);
-
-		irc->quitting = TRUE;
-
-		if (!purple_account_is_disconnecting(irc->account))
-			purple_account_set_status(irc->account, "offline", TRUE, NULL);
-	}
-
-	return 0;
-}
-
-int
-irc_cmd_quote(struct irc_conn *irc, G_GNUC_UNUSED const char *cmd,
-              G_GNUC_UNUSED const char *target, const char **args)
-{
-	char *buf;
-
-	if (!args || !args[0])
-		return 0;
-
-	buf = irc_format(irc, "n", args[0]);
-	irc_send(irc, buf);
-	g_free(buf);
-
-	return 0;
-}
-
-int irc_cmd_query(struct irc_conn *irc, const char *cmd, const char *target, const char **args)
-{
-	PurpleConversation *im;
-	PurpleConnection *gc;
-
-	if (!args || !args[0])
-		return 0;
-
-	im = purple_im_conversation_new(irc->account, args[0]);
-	purple_conversation_present(im);
-
-	if (args[1]) {
-		PurpleMessage *message = NULL;
-		PurpleContactInfo *info = PURPLE_CONTACT_INFO(irc->account);
-		const gchar *me = NULL;
-		const gchar *recipient = NULL;
-
-		gc = purple_account_get_connection(irc->account);
-		irc_cmd_privmsg(irc, cmd, target, args);
-
-		me = purple_contact_info_get_name_for_display(info);
-		recipient = purple_connection_get_display_name(gc);
-		message = purple_message_new_outgoing(irc->account, me, recipient,
-		                                      args[1], 0);
-
-		purple_conversation_write_message(im, message);
-
-		g_object_unref(G_OBJECT(message));
-	}
-
-	return 0;
-}
-
-int
-irc_cmd_remove(struct irc_conn *irc, G_GNUC_UNUSED const char *cmd,
-               const char *target, const char **args)
-{
-	char *buf;
-
-	if (!args || !args[0])
-		return 0;
-
-	if (!irc_ischannel(target)) /* not a channel, punt */
-		return 0;
-
-	if (args[1])
-		buf = irc_format(irc, "vcn:", "REMOVE", target, args[0], args[1]);
-	else
-		buf = irc_format(irc, "vcn", "REMOVE", target, args[0]);
-	irc_send(irc, buf);
-	g_free(buf);
-
-	return 0;
-}
-
-int
-irc_cmd_service(struct irc_conn *irc, const char *cmd,
-                G_GNUC_UNUSED const char *target, const char **args)
-{
-	char *capital_cmd, *buf;
-
-	if (!args || !args[0])
-		return 0;
-
-	/* cmd will be one of nickserv, chanserv, memoserv or operserv */
-	capital_cmd = g_ascii_strup(cmd, -1);
-	buf = irc_format(irc, "v:", capital_cmd, args[0]);
-	irc_send(irc, buf);
-	g_free(capital_cmd);
-	g_free(buf);
-
-	return 0;
-}
-
-int
-irc_cmd_time(struct irc_conn *irc, G_GNUC_UNUSED const char *cmd,
-             G_GNUC_UNUSED const char *target, G_GNUC_UNUSED const char **args)
-{
-	char *buf;
-
-	buf = irc_format(irc, "v", "TIME");
-	irc_send(irc, buf);
-	g_free(buf);
-
-	return 0;
-}
-
-int
-irc_cmd_topic(struct irc_conn *irc, G_GNUC_UNUSED const char *cmd,
-              const char *target, const char **args)
-{
-	PurpleConversation *chat;
-	PurpleConversationManager *manager;
-	char *buf;
-	const char *topic;
-
-	if (!args) {
-		return 0;
-	}
-
-	manager = purple_conversation_manager_get_default();
-	chat = purple_conversation_manager_find_chat(manager, irc->account, target);
-	if (!chat) {
-		return 0;
-	}
-
-	if (!args[0]) {
-		topic = purple_chat_conversation_get_topic (PURPLE_CHAT_CONVERSATION(chat));
-
-		if (topic) {
-			char *tmp, *tmp2;
-			tmp = g_markup_escape_text(topic, -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(
-			chat, buf, PURPLE_MESSAGE_NO_LOG);
-		g_free(buf);
-
-		return 0;
-	}
-
-	buf = irc_format(irc, "vt:", "TOPIC", target, args[0]);
-	irc_send(irc, buf);
-	g_free(buf);
-
-	return 0;
-}
-
-int
-irc_cmd_wallops(struct irc_conn *irc, const char *cmd,
-                G_GNUC_UNUSED const char *target, const char **args)
-{
-	char *buf;
-
-	if (!args || !args[0])
-		return 0;
-
-	if (purple_strequal(cmd, "wallops"))
-		buf = irc_format(irc, "v:", "WALLOPS", args[0]);
-	else if (purple_strequal(cmd, "operwall"))
-		buf = irc_format(irc, "v:", "OPERWALL", args[0]);
-	else
-		return 0;
-
-	irc_send(irc, buf);
-	g_free(buf);
-
-	return 0;
-}
-
-int
-irc_cmd_whois(struct irc_conn *irc, G_GNUC_UNUSED const char *cmd,
-              G_GNUC_UNUSED const char *target, const char **args)
-{
-	char *buf;
-
-	if (!args || !args[0])
-		return 0;
-
-	if (args[1]) {
-		buf = irc_format(irc, "vvn", "WHOIS", args[0], args[1]);
-		irc->whois.nick = g_strdup(args[1]);
-	} else {
-		buf = irc_format(irc, "vn", "WHOIS", args[0]);
-		irc->whois.nick = g_strdup(args[0]);
-	}
-
-	irc_send(irc, buf);
-	g_free(buf);
-
-	return 0;
-}
-
-int
-irc_cmd_whowas(struct irc_conn *irc, G_GNUC_UNUSED const char *cmd,
-               G_GNUC_UNUSED const char *target, const char **args)
-{
-	char *buf;
-
-	if (!args || !args[0])
-		return 0;
-
-	buf = irc_format(irc, "vn", "WHOWAS", args[0]);
-
-	irc->whois.nick = g_strdup(args[0]);
-	irc_send(irc, buf);
-	g_free(buf);
-
-	return 0;
-}
-
-static void irc_do_mode(struct irc_conn *irc, const char *target, const char *sign, char **ops)
-{
-	char *buf, mode[5];
-	int i = 0;
-
-	if (!sign)
-		return;
-
-	while (ops[i]) {
-		if (ops[i + 2] && ops[i + 4]) {
-			g_snprintf(mode, sizeof(mode), "%s%s%s%s", sign,
-				   ops[i], ops[i + 2], ops[i + 4]);
-			buf = irc_format(irc, "vcvnnn", "MODE", target, mode,
-					 ops[i + 1], ops[i + 3], ops[i + 5]);
-			i += 6;
-		} else if (ops[i + 2]) {
-			g_snprintf(mode, sizeof(mode), "%s%s%s",
-				   sign, ops[i], ops[i + 2]);
-			buf = irc_format(irc, "vcvnn", "MODE", target, mode,
-					 ops[i + 1], ops[i + 3]);
-			i += 4;
-		} else {
-			g_snprintf(mode, sizeof(mode), "%s%s", sign, ops[i]);
-			buf = irc_format(irc, "vcvn", "MODE", target, mode, ops[i + 1]);
-			i += 2;
-		}
-		irc_send(irc, buf);
-		g_free(buf);
-	}
-}
diff --git a/libpurple/protocols/irc/dcc_send.c b/libpurple/protocols/irc/dcc_send.c
deleted file mode 100644
--- a/libpurple/protocols/irc/dcc_send.c
+++ /dev/null
@@ -1,413 +0,0 @@
-/**
- * purple
- *
- * Copyright (C) 2004, Timothy T Ringenbach <omarvo@hotmail.com>
- * Copyright (C) 2003, Robbert Haarman <purple@inglorion.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include <errno.h>
-
-#include <glib/gi18n-lib.h>
-
-#ifndef _WIN32
-# include <arpa/inet.h>
-#endif
-
-#include <purple.h>
-#include "libpurple/glibcompat.h"
-
-#include "irc.h"
-
-struct _IrcXfer {
-	PurpleXfer parent;
-
-	/* receive properties */
-	gchar *ip;
-	guint remote_port;
-
-	/* send properties */
-	GSocketService *service;
-	GSocketConnection *conn;
-	gint inpa;
-	guchar *rxqueue;
-	guint rxlen;
-};
-
-G_DEFINE_DYNAMIC_TYPE(IrcXfer, irc_xfer, PURPLE_TYPE_XFER);
-
-/***************************************************************************
- * Functions related to receiving files via DCC SEND
- ***************************************************************************/
-
-/*
- * This function is called whenever data is received.
- * It sends the acknowledgement (in the form of a total byte count as an
- * unsigned 4 byte integer in network byte order)
- */
-static void
-irc_dccsend_recv_ack(PurpleXfer *xfer, G_GNUC_UNUSED const guchar *data,
-                     G_GNUC_UNUSED size_t size)
-{
-	guint32 l;
-	gssize result;
-
-	if(purple_xfer_get_xfer_type(xfer) != PURPLE_XFER_TYPE_RECEIVE) {
-		return;
-	}
-
-	l = g_htonl(purple_xfer_get_bytes_sent(xfer));
-	result = purple_xfer_write(xfer, (guchar *)&l, sizeof(l));
-	if (result != sizeof(l)) {
-		purple_debug_error("irc", "unable to send acknowledgement: %s\n", g_strerror(errno));
-		/* TODO: We should probably close the connection here or something. */
-	}
-}
-
-static void irc_dccsend_recv_init(PurpleXfer *xfer) {
-	IrcXfer *xd = IRC_XFER(xfer);
-
-	purple_xfer_start(xfer, -1, xd->ip, xd->remote_port);
-}
-
-/* This function makes the necessary arrangements for receiving files */
-void irc_dccsend_recv(struct irc_conn *irc, const char *from, const char *msg) {
-	IrcXfer *xfer;
-	gchar **token;
-	GString *filename;
-	int i = 0;
-	guint32 nip;
-
-	token = g_strsplit(msg, " ", 0);
-	if (!token[0] || !token[1] || !token[2]) {
-		g_strfreev(token);
-		return;
-	}
-
-	filename = g_string_new("");
-	if (token[0][0] == '"') {
-		if (!strchr(&(token[0][1]), '"')) {
-			g_string_append(filename, &(token[0][1]));
-			for (i = 1; token[i]; i++)
-				if (!strchr(token[i], '"')) {
-					g_string_append_printf(filename, " %s", token[i]);
-				} else {
-					g_string_append_len(filename, token[i], strlen(token[i]) - 1);
-					break;
-				}
-		} else {
-			g_string_append_len(filename, &(token[0][1]), strlen(&(token[0][1])) - 1);
-		}
-	} else {
-		g_string_append(filename, token[0]);
-	}
-
-	if (!token[i] || !token[i+1] || !token[i+2]) {
-		g_strfreev(token);
-		g_string_free(filename, TRUE);
-		return;
-	}
-	i++;
-
-	xfer = g_object_new(
-		IRC_TYPE_XFER,
-		"account", irc->account,
-		"type", PURPLE_XFER_TYPE_RECEIVE,
-		"remote-user", from,
-		NULL
-	);
-
-	purple_xfer_set_filename(PURPLE_XFER(xfer), filename->str);
-
-	xfer->remote_port = atoi(token[i+1]);
-
-	nip = strtoul(token[i], NULL, 10);
-	if (nip) {
-		GInetAddress *addr = g_inet_address_new_from_bytes(
-		        (const guchar *)&nip, G_SOCKET_FAMILY_IPV4);
-		xfer->ip = g_inet_address_to_string(addr);
-		g_object_unref(addr);
-	} else {
-		xfer->ip = g_strdup(token[i]);
-	}
-
-	purple_debug_info("irc", "Receiving file (%s) from %s", filename->str, xfer->ip);
-	purple_xfer_set_size(PURPLE_XFER(xfer), token[i+2] ? atoi(token[i+2]) : 0);
-
-	purple_xfer_request(PURPLE_XFER(xfer));
-
-	g_strfreev(token);
-	g_string_free(filename, TRUE);
-}
-
-/*******************************************************************
- * Functions related to sending files via DCC SEND
- *******************************************************************/
-
-/* just in case you were wondering, this is why DCC is crappy */
-static void
-irc_dccsend_send_read(gpointer data, int source,
-                      G_GNUC_UNUSED PurpleInputCondition cond)
-{
-	PurpleXfer *xfer = PURPLE_XFER(data);
-	IrcXfer *xd = IRC_XFER(xfer);
-	char buffer[64];
-	int len;
-
-	len = read(source, buffer, sizeof(buffer));
-
-	if (len < 0 && errno == EAGAIN)
-		return;
-	else if (len <= 0) {
-		/* XXX: Shouldn't this be canceling the transfer? */
-		g_clear_handle_id(&xd->inpa, g_source_remove);
-		return;
-	}
-
-	xd->rxqueue = g_realloc(xd->rxqueue, len + xd->rxlen);
-	memcpy(xd->rxqueue + xd->rxlen, buffer, len);
-	xd->rxlen += len;
-
-	while (1) {
-		gint32 val;
-		size_t acked;
-
-		if (xd->rxlen < 4)
-			break;
-
-		memcpy(&val, xd->rxqueue, sizeof(val));
-		acked = g_ntohl(val);
-
-		xd->rxlen -= 4;
-		if (xd->rxlen) {
-			unsigned char *tmp = g_memdup2(xd->rxqueue + 4, xd->rxlen);
-			g_free(xd->rxqueue);
-			xd->rxqueue = tmp;
-		} else {
-			g_free(xd->rxqueue);
-			xd->rxqueue = NULL;
-		}
-
-		if ((goffset)acked >= purple_xfer_get_size(xfer)) {
-			g_clear_handle_id(&xd->inpa, g_source_remove);
-			purple_xfer_set_completed(xfer, TRUE);
-			purple_xfer_end(xfer);
-			return;
-		}
-	}
-}
-
-static gssize irc_dccsend_send_write(PurpleXfer *xfer, const guchar *buffer, size_t size)
-{
-	gssize s;
-	gssize ret;
-
-	s = MIN((gssize)purple_xfer_get_bytes_remaining(xfer), (gssize)size);
-	if (!s) {
-		return 0;
-	}
-
-	ret = PURPLE_XFER_CLASS(irc_xfer_parent_class)->write(xfer, buffer, s);
-
-	if (ret < 0 && errno == EAGAIN) {
-		ret = 0;
-	}
-
-	return ret;
-}
-
-static void
-irc_dccsend_send_connected(G_GNUC_UNUSED GSocketService *service,
-                           GSocketConnection *connection,
-                           GObject *source_object, G_GNUC_UNUSED gpointer data)
-{
-	PurpleXfer *xfer = PURPLE_XFER(source_object);
-	IrcXfer *xd = IRC_XFER(xfer);
-	GSocket *sock;
-	int fd = -1;
-
-	xd->conn = g_object_ref(connection);
-	g_socket_service_stop(xd->service);
-	g_clear_object(&xd->service);
-
-	sock = g_socket_connection_get_socket(connection);
-	fd = g_socket_get_fd(sock);
-	_purple_network_set_common_socket_flags(fd);
-
-	xd->inpa = purple_input_add(fd, PURPLE_INPUT_READ, irc_dccsend_send_read,
-	                            xfer);
-	/* Start the transfer */
-	purple_xfer_start(xfer, fd, NULL, 0);
-}
-
-/*
- * This function is called after the user has selected a file to send.
- */
-static void
-irc_dccsend_send_init(PurpleXfer *xfer)
-{
-	IrcXfer *xd = IRC_XFER(xfer);
-	PurpleConnection *gc =
-	        purple_account_get_connection(purple_xfer_get_account(xfer));
-	struct irc_conn *irc;
-	const char *arg[2];
-	char *tmp;
-	GInetAddress *addr = NULL;
-	const guint8 *bytes = NULL;
-	guint32 ip = 0;
-	guint16 port;
-	GError *error = NULL;
-
-	purple_xfer_set_filename(
-	        xfer, g_path_get_basename(purple_xfer_get_local_filename(xfer)));
-
-	/* Create a listening socket */
-	xd->service = g_socket_service_new();
-	if (xd->service == NULL) {
-		purple_notify_error(gc, NULL, _("File Transfer Failed"),
-		                    _("Unable to open a listening port."),
-		                    purple_request_cpar_from_connection(gc));
-		purple_xfer_cancel_local(xfer);
-		return;
-	}
-
-	/* Monitor the listening socket */
-	g_signal_connect(xd->service, "incoming",
-	                 G_CALLBACK(irc_dccsend_send_connected), NULL);
-
-	port = purple_socket_listener_add_any_inet_port(
-	        G_SOCKET_LISTENER(xd->service), G_OBJECT(xfer), &error);
-	if (port != 0) {
-		purple_xfer_set_local_port(xfer, port);
-	} else {
-		purple_notify_error(gc, NULL, _("File Transfer Failed"),
-			_("Unable to open a listening port."),
-			purple_request_cpar_from_connection(gc));
-		g_error_free(error);
-		g_clear_object(&xd->service);
-		purple_xfer_cancel_local(xfer);
-		return;
-	}
-
-	irc = purple_connection_get_protocol_data(gc);
-
-	purple_debug_misc("irc", "port is %hu\n", port);
-
-	/* Send the intended recipient the DCC request */
-	arg[0] = purple_xfer_get_remote_user(xfer);
-	tmp = purple_network_get_my_ip_from_gio(irc->conn);
-	addr = g_inet_address_new_from_string(tmp);
-	bytes = g_inet_address_to_bytes(addr);
-	ip = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3];
-	g_object_unref(addr);
-	g_free(tmp);
-	arg[1] = tmp = g_strdup_printf(
-	        "\001DCC SEND \"%s\" %u %hu %" G_GOFFSET_FORMAT "\001",
-	        purple_xfer_get_filename(xfer), ip, port,
-	        purple_xfer_get_size(xfer));
-
-	irc_cmd_privmsg(purple_connection_get_protocol_data(gc), "msg", NULL, arg);
-	g_free(tmp);
-}
-
-PurpleXfer *
-irc_dccsend_new_xfer(G_GNUC_UNUSED PurpleProtocolXfer *prplxfer,
-                     PurpleConnection *gc, const char *who)
-{
-	return g_object_new(
-		IRC_TYPE_XFER,
-		"account", purple_connection_get_account(gc),
-		"type", PURPLE_XFER_TYPE_SEND,
-		"remote-user", who,
-		NULL
-	);
-}
-
-/**
- * Purple calls this function when the user selects Send File from the
- * buddy menu
- * It sets up the PurpleXfer struct and tells Purple to go ahead
- */
-void irc_dccsend_send_file(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *who, const char *file) {
-	PurpleXfer *xfer = irc_dccsend_new_xfer(prplxfer, gc, who);
-
-	/* Perform the request */
-	if (file)
-		purple_xfer_request_accepted(xfer, file);
-	else
-		purple_xfer_request(xfer);
-}
-
-/******************************************************************************
- * PurpleXfer Implementation
- *****************************************************************************/
-static void
-irc_dccsend_init(PurpleXfer *xfer) {
-	PurpleXferType type = purple_xfer_get_xfer_type(xfer);
-
-	if(type == PURPLE_XFER_TYPE_SEND) {
-		irc_dccsend_send_init(xfer);
-	} else if(type == PURPLE_XFER_TYPE_RECEIVE) {
-		irc_dccsend_recv_init(xfer);
-	}
-}
-
-/******************************************************************************
- * GObject Implementation
- *****************************************************************************/
-static void
-irc_xfer_init(G_GNUC_UNUSED IrcXfer *xfer) {
-}
-
-static void
-irc_xfer_finalize(GObject *obj) {
-	IrcXfer *xfer = IRC_XFER(obj);
-
-	/* clean up the receiving proprties */
-	g_free(xfer->ip);
-	g_free(xfer->rxqueue);
-
-	/* clean up the sending properties */
-	if (xfer->service) {
-		g_socket_service_stop(xfer->service);
-	}
-	g_clear_object(&xfer->service);
-	g_clear_handle_id(&xfer->inpa, g_source_remove);
-	g_clear_object(&xfer->conn);
-
-	G_OBJECT_CLASS(irc_xfer_parent_class)->finalize(obj);
-}
-
-static void
-irc_xfer_class_finalize(G_GNUC_UNUSED IrcXferClass *klass) {
-}
-
-static void
-irc_xfer_class_init(IrcXferClass *klass) {
-	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
-	PurpleXferClass *xfer_class = PURPLE_XFER_CLASS(klass);
-
-	obj_class->finalize = irc_xfer_finalize;
-
-	xfer_class->init = irc_dccsend_init;
-	xfer_class->ack = irc_dccsend_recv_ack;
-	xfer_class->write = irc_dccsend_send_write;
-}
-
-void
-irc_xfer_register(GTypeModule *module) {
-	irc_xfer_register_type(module);
-}
diff --git a/libpurple/protocols/irc/irc.h b/libpurple/protocols/irc/irc.h
deleted file mode 100644
--- a/libpurple/protocols/irc/irc.h
+++ /dev/null
@@ -1,222 +0,0 @@
-/**
- * purple
- *
- * Copyright (C) 2003, 2012 Ethan Blanton <elb@pidgin.im>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#ifndef PURPLE_IRC_IRC_H
-#define PURPLE_IRC_IRC_H
-
-#include <glib.h>
-#include <gmodule.h>
-
-#include <config.h>
-
-#include <hasl.h>
-
-#include <purple.h>
-
-#define IRC_TYPE_PROTOCOL (irc_protocol_get_type())
-G_DECLARE_FINAL_TYPE(IRCProtocol, irc_protocol, IRC, PROTOCOL, PurpleProtocol)
-
-#define IRC_DEFAULT_SERVER "irc.libera.chat"
-#define IRC_DEFAULT_PORT 6667
-#define IRC_DEFAULT_SSL_PORT 994
-
-#define IRC_DEFAULT_CHARSET "UTF-8"
-#define IRC_DEFAULT_AUTODETECT FALSE
-#define IRC_DEFAULT_ALIAS "purple"
-
-#define IRC_DEFAULT_QUIT "Leaving."
-
-#define IRC_BUFSIZE_INCREMENT 1024
-#define IRC_MAX_BUFSIZE 16384
-
-#define IRC_MAX_MSG_SIZE 512
-
-#define IRC_NAMES_FLAG "irc-namelist"
-
-enum { IRC_USEROPT_SERVER, IRC_USEROPT_PORT, IRC_USEROPT_CHARSET };
-enum irc_state { IRC_STATE_NEW, IRC_STATE_ESTABLISHED };
-
-struct irc_conn {
-	PurpleAccount *account;
-	GHashTable *msgs;
-	GHashTable *cmds;
-	char *server;
-	GSocketConnection *conn;
-	GCancellable *cancellable;
-	guint timer;
-	GHashTable *buddies;
-
-	gboolean ison_outstanding;
-	GList *buddies_outstanding;
-
-	GDataInputStream *input;
-	PurpleQueuedOutputStream *output;
-
-	GString *motd;
-	GString *names;
-	struct _whois {
-		char *nick;
-		char *real;
-		char *login;
-		char *ident;
-		char *host;
-		char *away;
-		char *server;
-		char *serverinfo;
-		GString *channels;
-		int ircop;
-		int identified;
-		int idle;
-		time_t signon;
-	} whois;
-	PurpleRoomlist *roomlist;
-
-	gboolean quitting;
-
-	time_t recv_time;
-
-	char *mode_chars;
-	char *reqnick;
-	gboolean nickused;
-
-	HaslContext *hasl_ctx;
-};
-
-struct irc_buddy {
-	char *name;
-	gboolean online;
-	gboolean flag;
-	gboolean new_online_status;
-	int ref;
-};
-
-typedef int (*IRCCmdCallback) (struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-
-int irc_send(struct irc_conn *irc, const char *buf);
-int irc_send_len(struct irc_conn *irc, const char *buf, int len);
-gboolean irc_blist_timeout(struct irc_conn *irc);
-gboolean irc_who_channel_timeout(struct irc_conn *irc);
-void irc_buddy_query(struct irc_conn *irc);
-
-char *irc_escape_privmsg(const char *text, gssize length);
-
-char *irc_mirc2html(const char *string);
-char *irc_mirc2txt(const char *string);
-
-const char *irc_nick_skip_mode(struct irc_conn *irc, const char *string);
-
-gboolean irc_ischannel(const char *string);
-
-void irc_register_commands(void);
-void irc_unregister_commands(void);
-void irc_msg_table_build(struct irc_conn *irc);
-void irc_parse_msg(struct irc_conn *irc, char *input);
-char *irc_parse_ctcp(struct irc_conn *irc, const char *from, const char *to, const char *msg, int notice);
-char *irc_format(struct irc_conn *irc, const char *format, ...);
-
-void irc_msg_default(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_away(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_badmode(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_badnick(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_ban(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_banfull(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_banned(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_chanmode(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_endwhois(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_features(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_invite(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_inviteonly(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_ison(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_join(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_kick(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_list(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_luser(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_mode(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_motd(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_names(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_nick(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_nickused(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_nochan(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_nonick(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_nochangenick(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_nosend(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_notice(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_notinchan(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_notop(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_part(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_ping(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_pong(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_privmsg(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_quit(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_regonly(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_time(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_topic(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_topicinfo(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_unavailable(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_unknown(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_wallops(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_whois(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_who(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_cap(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_auth(struct irc_conn *irc, char *arg);
-void irc_msg_authenticate(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_authok(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_authtryagain(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_authfail(struct irc_conn *irc, const char *name, const char *from, char **args);
-
-void irc_cmd_table_build(struct irc_conn *irc);
-
-int irc_cmd_default(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_away(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_ctcp(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_ctcp_action(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_ctcp_version(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_invite(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_join(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_kick(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_list(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_mode(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_names(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_nick(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_op(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_privmsg(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_part(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_ping(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_quit(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_quote(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_query(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_remove(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_service(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_time(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_topic(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_wallops(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_whois(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-int irc_cmd_whowas(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
-
-#define IRC_TYPE_XFER (irc_xfer_get_type())
-G_DECLARE_FINAL_TYPE(IrcXfer, irc_xfer, IRC, XFER, PurpleXfer);
-
-void irc_xfer_register(GTypeModule *module);
-
-PurpleXfer *irc_dccsend_new_xfer(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *who);
-void irc_dccsend_send_file(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *who, const char *file);
-void irc_dccsend_recv(struct irc_conn *irc, const char *from, const char *msg);
-
-#endif /* PURPLE_IRC_IRC_H */
diff --git a/libpurple/protocols/irc/irc.c b/libpurple/protocols/irc/irc.c
deleted file mode 100644
--- a/libpurple/protocols/irc/irc.c
+++ /dev/null
@@ -1,1282 +0,0 @@
-/**
- * purple
- *
- * Copyright (C) 2003, Robbert Haarman <purple@inglorion.net>
- * Copyright (C) 2003, 2012 Ethan Blanton <elb@pidgin.im>
- * Copyright (C) 2000-2003, Rob Flynn <rob@tgflinux.com>
- * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include <errno.h>
-
-#include <glib/gi18n-lib.h>
-
-#include <gplugin.h>
-#include <gplugin-native.h>
-
-#include <purple.h>
-
-#include "irc.h"
-
-#define PING_TIMEOUT 60
-
-struct _IRCProtocol {
-	PurpleProtocol parent;
-};
-
-static void irc_ison_buddy_init(char *name, struct irc_buddy *ib, GList **list);
-
-static GList *irc_status_types(PurpleProtocol *protocol, PurpleAccount *account);
-/* static GList *irc_chat_info(PurpleConnection *gc); */
-static void irc_login(PurpleProtocol *protocol, PurpleAccount *account);
-static void irc_login_cb(GObject *source, GAsyncResult *res, gpointer user_data);
-static void irc_close(PurpleProtocol *protocol, PurpleConnection *gc);
-static int irc_im_send(PurpleProtocolIM *im, PurpleConnection *gc, PurpleMessage *msg);
-static int irc_chat_send(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id, PurpleMessage *msg);
-static void irc_chat_join(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, GHashTable *data);
-static void irc_read_input_cb(GObject *source, GAsyncResult *res, gpointer data);
-
-static guint irc_nick_hash(const char *nick);
-static gboolean irc_nick_equal(const char *nick1, const char *nick2);
-static void irc_buddy_free(struct irc_buddy *ib);
-
-PurpleProtocol *_irc_protocol = NULL;
-
-static gint
-irc_uri_handler_match_server(PurpleAccount *account, const gchar *match_server)
-{
-	const gchar *protocol_id;
-	const gchar *username;
-	gchar *server;
-
-	protocol_id = purple_account_get_protocol_id(account);
-
-	if (!purple_strequal(protocol_id, "prpl-irc") ||
-			!purple_account_is_connected(account)) {
-		return -1;
-	}
-
-	if (match_server == NULL || match_server[0] == '\0') {
-		/* No server specified, match any IRC account */
-		return 0;
-	}
-
-	username = purple_contact_info_get_username(PURPLE_CONTACT_INFO(account));
-	server = strchr(username, '@');
-
-	/* +1 to skip '@' */
-	if (server == NULL || !purple_strequal(match_server, server + 1)) {
-		return -1;
-	}
-
-	return 0;
-}
-
-static gboolean
-irc_uri_handler(const gchar *scheme, const gchar *uri, GHashTable *params)
-{
-	PurpleAccountManager *manager = NULL;
-	gchar *target;
-	gchar *server;
-	gchar **target_tokens;
-	PurpleAccount *account;
-	gchar **modifier;
-	gboolean isnick = FALSE;
-
-	g_return_val_if_fail(uri != NULL, FALSE);
-
-	if (!purple_strequal(scheme, "irc")) {
-		/* Not a scheme we handle here */
-		return FALSE;
-	}
-
-	if (g_str_has_prefix(uri, "//")) {
-		/* Skip initial '//' if it exists */
-		uri += 2;
-	}
-
-	/* Find the target (aka room or user) */
-	target = strchr(uri, '/');
-
-	/* [1] to skip the '/' */
-	if (target == NULL || target[1] == '\0') {
-		purple_debug_warning("irc",
-				"URI missing valid target: %s", uri);
-		return FALSE;
-	}
-
-	server = g_strndup(uri, target - uri);
-
-	/* Find account with correct server */
-	manager = purple_account_manager_get_default();
-	account = purple_account_manager_find_custom(manager,
-	                                             (GEqualFunc)irc_uri_handler_match_server,
-	                                             server);
-
-	if (account == NULL) {
-		purple_debug_warning("irc",
-				"No account online on '%s' for handling URI",
-				server);
-		g_free(server);
-		return FALSE;
-	}
-
-	/* Tokenize modifiers, +1 to skip the initial '/' */
-	target_tokens = g_strsplit(target + 1, ",", 0);
-	target = g_strdup_printf("#%s", target_tokens[0]);
-
-	/* Parse modifiers, start at 1 to skip the actual target */
-	for (modifier = target_tokens + 1; *modifier != NULL; ++modifier) {
-		if (purple_strequal(*modifier, "isnick")) {
-			isnick = TRUE;
-			break;
-		}
-	}
-
-	g_strfreev(target_tokens);
-
-	if (isnick) {
-		PurpleConversation *im;
-
-		/* 'server' isn't needed here. Free it immediately. */
-		g_free(server);
-
-		/* +1 to skip '#' target prefix */
-		im = purple_im_conversation_new(account, target + 1);
-		g_free(target);
-
-		purple_conversation_present(im);
-
-		if (params != NULL) {
-			const gchar *msg = g_hash_table_lookup(params, "msg");
-
-			if (msg != NULL) {
-				purple_conversation_send_confirm(im, msg);
-			}
-		}
-
-		return TRUE;
-	} else {
-		GHashTable *components;
-
-		components = g_hash_table_new_full(g_str_hash, g_str_equal,
-				NULL, g_free);
-
-		/* Transfer ownership of these to the hash table */
-		g_hash_table_insert(components, "server", server);
-		g_hash_table_insert(components, "channel", target);
-
-		if (params != NULL) {
-			const gchar *key = g_hash_table_lookup(params, "key");
-
-			if (key != NULL) {
-				g_hash_table_insert(components, "password",
-						g_strdup(key));
-			}
-		}
-
-		purple_serv_join_chat(purple_account_get_connection(account),
-				components);
-		g_hash_table_destroy(components);
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-static void
-irc_view_motd(G_GNUC_UNUSED GSimpleAction *action,
-              GVariant *parameter,
-              G_GNUC_UNUSED gpointer data)
-{
-	const gchar *account_id = NULL;
-	PurpleAccountManager *manager = NULL;
-	PurpleAccount *account = NULL;
-	PurpleConnection *gc = NULL;
-	struct irc_conn *irc;
-	char *title, *body;
-
-	if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) {
-		g_critical("IRC View MOTD 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);
-	gc = purple_account_get_connection(account);
-
-	if (gc == NULL || purple_connection_get_protocol_data(gc) == NULL) {
-		purple_debug_error("irc", "got MOTD request for NULL gc");
-		return;
-	}
-	irc = purple_connection_get_protocol_data(gc);
-	if (irc->motd == NULL) {
-		purple_notify_error(gc, _("Error displaying MOTD"),
-			_("No MOTD available"),
-			_("There is no MOTD associated with this connection."),
-			purple_request_cpar_from_connection(gc));
-		return;
-	}
-	title = g_strdup_printf(_("MOTD for %s"), irc->server);
-	body = g_strdup_printf("<span style=\"font-family: monospace;\">%s</span>", irc->motd->str);
-	purple_notify_formatted(gc, title, title, NULL, body, NULL, NULL);
-	g_free(title);
-	g_free(body);
-}
-
-static int
-irc_send_raw(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
-             PurpleConnection *gc, const gchar *buf, gint len)
-{
-	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
-	if (len == -1) {
-		len = strlen(buf);
-	}
-	irc_send_len(irc, buf, len);
-	return len;
-}
-
-static void
-irc_push_bytes_cb(GObject *source, GAsyncResult *res, gpointer data)
-{
-	PurpleQueuedOutputStream *stream = PURPLE_QUEUED_OUTPUT_STREAM(source);
-	PurpleConnection *gc = data;
-	gboolean result;
-	GError *error = NULL;
-
-	result = purple_queued_output_stream_push_bytes_finish(stream,
-			res, &error);
-
-	if (!result) {
-		purple_queued_output_stream_clear_queue(stream);
-
-		g_prefix_error(&error, "%s", _("Lost connection with server: "));
-		purple_connection_take_error(gc, error);
-		return;
-	}
-}
-
-int irc_send(struct irc_conn *irc, const char *buf)
-{
-    return irc_send_len(irc, buf, strlen(buf));
-}
-
-int
-irc_send_len(struct irc_conn *irc, const char *buf, G_GNUC_UNUSED int buflen) {
- 	char *tosend = g_strdup(buf);
-	int len;
-	GBytes *data;
-
-	purple_signal_emit(_irc_protocol, "irc-sending-text", purple_account_get_connection(irc->account), &tosend);
-
-	if (tosend == NULL)
-		return 0;
-
-	if (purple_debug_is_verbose()) {
-		gchar *clean = g_utf8_make_valid(tosend, -1);
-		clean = g_strstrip(clean);
-		purple_debug_misc("irc", "<< %s\n", clean);
-		g_free(clean);
-	}
-
-	len = strlen(tosend);
-	data = g_bytes_new_take(tosend, len);
-	purple_queued_output_stream_push_bytes_async(irc->output, data,
-			G_PRIORITY_DEFAULT, irc->cancellable, irc_push_bytes_cb,
-			purple_account_get_connection(irc->account));
-	g_bytes_unref(data);
-
-	return len;
-}
-
-/* XXX I don't like messing directly with these buddies */
-gboolean irc_blist_timeout(struct irc_conn *irc)
-{
-	if (irc->ison_outstanding) {
-		return TRUE;
-	}
-
-	g_hash_table_foreach(irc->buddies, (GHFunc)irc_ison_buddy_init,
-	                     (gpointer *)&irc->buddies_outstanding);
-
-	irc_buddy_query(irc);
-
-	return TRUE;
-}
-
-void irc_buddy_query(struct irc_conn *irc)
-{
-	GList *lp;
-	GString *string;
-	struct irc_buddy *ib;
-	char *buf;
-
-	string = g_string_sized_new(512);
-
-	while ((lp = g_list_first(irc->buddies_outstanding))) {
-		ib = (struct irc_buddy *)lp->data;
-		if (string->len + strlen(ib->name) + 1 > 450)
-			break;
-		g_string_append_printf(string, "%s ", ib->name);
-		ib->new_online_status = FALSE;
-		irc->buddies_outstanding = g_list_delete_link(irc->buddies_outstanding, lp);
-	}
-
-	if (string->len) {
-		buf = irc_format(irc, "vn", "ISON", string->str);
-		irc_send(irc, buf);
-		g_free(buf);
-		irc->ison_outstanding = TRUE;
-	} else
-		irc->ison_outstanding = FALSE;
-
-	g_string_free(string, TRUE);
-}
-
-static void
-irc_ison_buddy_init(G_GNUC_UNUSED char *name, struct irc_buddy *ib,
-                    GList **list)
-{
-	*list = g_list_append(*list, ib);
-}
-
-
-static void irc_ison_one(struct irc_conn *irc, struct irc_buddy *ib)
-{
-	char *buf;
-
-	if (irc->buddies_outstanding != NULL) {
-		irc->buddies_outstanding = g_list_append(irc->buddies_outstanding, ib);
-		return;
-	}
-
-	ib->new_online_status = FALSE;
-	buf = irc_format(irc, "vn", "ISON", ib->name);
-	irc_send(irc, buf);
-	g_free(buf);
-}
-
-static GList *
-irc_protocol_get_account_options(G_GNUC_UNUSED PurpleProtocol *protocol) {
-	PurpleAccountOption *option;
-	GList *opts = NULL;
-
-	option = purple_account_option_int_new(_("Port"), "port",
-	                                       IRC_DEFAULT_PORT);
-	opts = g_list_append(opts, option);
-
-	option = purple_account_option_string_new(_("Encodings"), "encoding",
-	                                          IRC_DEFAULT_CHARSET);
-	opts = g_list_append(opts, option);
-
-	option = purple_account_option_bool_new(_("Auto-detect incoming UTF-8"),
-	                                        "autodetect_utf8",
-	                                        IRC_DEFAULT_AUTODETECT);
-	opts = g_list_append(opts, option);
-
-	option = purple_account_option_string_new(_("Ident name"), "username", "");
-	opts = g_list_append(opts, option);
-
-	option = purple_account_option_string_new(_("Real name"), "realname", "");
-	opts = g_list_append(opts, option);
-
-	/*
-	option = purple_account_option_string_new(_("Quit message"), "quitmsg",
-	                                          IRC_DEFAULT_QUIT);
-	opts = g_list_append(opts, option);
-	*/
-
-	option = purple_account_option_bool_new(_("Use SSL"), "ssl", FALSE);
-	opts = g_list_append(opts, option);
-
-	option = purple_account_option_bool_new(_("Authenticate with SASL"),
-	                                        "sasl", FALSE);
-	opts = g_list_append(opts, option);
-
-	option = purple_account_option_bool_new(_("Allow plaintext SASL auth over "
-	                                          "unencrypted connection"),
-	                                        "auth_plain_in_clear", FALSE);
-	opts = g_list_append(opts, option);
-
-	return opts;
-}
-
-static GList *
-irc_protocol_get_user_splits(G_GNUC_UNUSED PurpleProtocol *protocol) {
-	PurpleAccountUserSplit *split;
-
-	split = purple_account_user_split_new(_("Server"), IRC_DEFAULT_SERVER,
-	                                      '@');
-
-	return g_list_append(NULL, split);
-}
-
-static GList *
-irc_status_types(G_GNUC_UNUSED PurpleProtocol *protocol,
-                 G_GNUC_UNUSED PurpleAccount *account)
-{
-	PurpleStatusType *type;
-	GList *types = NULL;
-
-	type = purple_status_type_new(PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE);
-	types = g_list_append(types, type);
-
-	type = purple_status_type_new_with_attrs(
-		PURPLE_STATUS_AWAY, NULL, NULL, TRUE, TRUE, FALSE,
-		"message", _("Message"), purple_value_new(G_TYPE_STRING),
-		NULL);
-	types = g_list_append(types, type);
-
-	type = purple_status_type_new(PURPLE_STATUS_OFFLINE, NULL, NULL, TRUE);
-	types = g_list_append(types, type);
-
-	return types;
-}
-
-static const gchar *
-irc_protocol_actions_get_prefix(G_GNUC_UNUSED PurpleProtocolActions *actions) {
-	return "prpl-irc";
-}
-
-static GActionGroup *
-irc_protocol_actions_get_action_group(G_GNUC_UNUSED PurpleProtocolActions *actions,
-                                      G_GNUC_UNUSED PurpleConnection *connection)
-{
-	GSimpleActionGroup *group = NULL;
-	GActionEntry entries[] = {
-		{
-			.name = "view-motd",
-			.activate = irc_view_motd,
-			.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);
-
-	return G_ACTION_GROUP(group);
-}
-
-static GMenu *
-irc_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(_("View MOTD"), "prpl-irc.view-motd");
-	g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s",
-	                          "account");
-	g_menu_append_item(menu, item);
-
-	g_object_unref(item);
-
-
-	return menu;
-}
-
-static GList *
-irc_chat_join_info(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
-                   G_GNUC_UNUSED PurpleConnection *gc)
-{
-	GList *m = NULL;
-	PurpleProtocolChatEntry *pce;
-
-	pce = g_new0(PurpleProtocolChatEntry, 1);
-	pce->label = _("_Channel");
-	pce->identifier = "channel";
-	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;
-}
-
-static GHashTable *
-irc_chat_info_defaults(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
-                       G_GNUC_UNUSED PurpleConnection *gc,
-                       const gchar *chat_name)
-{
-	GHashTable *defaults;
-
-	defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
-
-	if (chat_name != NULL)
-		g_hash_table_insert(defaults, "channel", g_strdup(chat_name));
-
-	return defaults;
-}
-
-static void
-irc_login(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleAccount *account) {
-	PurpleConnection *gc;
-	struct irc_conn *irc;
-	char **userparts;
-	const char *username = NULL;
-	GSocketClient *client;
-	GError *error = NULL;
-
-	username = purple_contact_info_get_username(PURPLE_CONTACT_INFO(account));
-
-	gc = purple_account_get_connection(account);
-	purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_NO_NEWLINES |
-		PURPLE_CONNECTION_FLAG_NO_IMAGES);
-
-	if (strpbrk(username, " \t\v\r\n") != NULL) {
-		purple_connection_take_error(gc, g_error_new_literal(
-			PURPLE_CONNECTION_ERROR,
-			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
-			_("IRC nick and server may not contain whitespace")));
-		return;
-	}
-
-	irc = g_new0(struct irc_conn, 1);
-	purple_connection_set_protocol_data(gc, irc);
-	irc->account = account;
-	irc->cancellable = g_cancellable_new();
-
-	userparts = g_strsplit(username, "@", 2);
-	purple_connection_set_display_name(gc, userparts[0]);
-	irc->server = g_strdup(userparts[1]);
-	g_strfreev(userparts);
-
-	irc->buddies = g_hash_table_new_full((GHashFunc)irc_nick_hash, (GEqualFunc)irc_nick_equal,
-					     NULL, (GDestroyNotify)irc_buddy_free);
-	irc->cmds = g_hash_table_new(g_str_hash, g_str_equal);
-	irc_cmd_table_build(irc);
-	irc->msgs = g_hash_table_new(g_str_hash, g_str_equal);
-	irc_msg_table_build(irc);
-
-	client = purple_gio_socket_client_new(account, &error);
-
-	if (client == NULL) {
-		purple_connection_take_error(gc, error);
-		return;
-	}
-
-	/* Optionally use TLS if it's set in the account settings */
-	g_socket_client_set_tls(client,
-			purple_account_get_bool(account, "ssl", FALSE));
-
-	g_socket_client_connect_to_host_async(client, irc->server,
-			purple_account_get_int(account, "port",
-					g_socket_client_get_tls(client) ?
-							IRC_DEFAULT_SSL_PORT :
-							IRC_DEFAULT_PORT),
-			irc->cancellable, irc_login_cb, gc);
-	g_object_unref(client);
-}
-
-static gboolean do_login(PurpleConnection *gc) {
-	char *buf = NULL;
-	char *server;
-	const char *nickname, *identname, *realname;
-	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
-	const char *pass = purple_connection_get_password(gc);
-	const gboolean use_sasl = purple_account_get_bool(irc->account, "sasl", FALSE);
-
-	if (pass && *pass) {
-		if (use_sasl)
-			buf = irc_format(irc, "vv:", "CAP", "REQ", "sasl");
-		else
-			buf = irc_format(irc, "v:", "PASS", pass);
-		if (irc_send(irc, buf) < 0) {
-			g_free(buf);
-			return FALSE;
-		}
-		g_free(buf);
-	}
-
-	nickname = purple_connection_get_display_name(gc);
-
-	realname = purple_account_get_string(irc->account, "realname", "");
-	if(realname == NULL || *realname == '\0') {
-		realname = IRC_DEFAULT_ALIAS;
-	}
-
-	identname = purple_account_get_string(irc->account, "username", "");
-	if(identname == NULL || *identname == '\0') {
-		identname = nickname;
-	}
-
-	if (*irc->server == ':') {
-		/* Same as hostname, above. */
-		server = g_strdup_printf("0%s", irc->server);
-	} else {
-		server = g_strdup(irc->server);
-	}
-
-	buf = irc_format(irc, "vvvv:", "USER", identname, "*", server, realname);
-	g_free(server);
-	if (irc_send(irc, buf) < 0) {
-		g_free(buf);
-		return FALSE;
-	}
-	g_free(buf);
-	buf = irc_format(irc, "vn", "NICK", nickname);
-	irc->reqnick = g_strdup(nickname);
-	irc->nickused = FALSE;
-	if (irc_send(irc, buf) < 0) {
-		g_free(buf);
-		return FALSE;
-	}
-	g_free(buf);
-
-	irc->recv_time = time(NULL);
-
-	return TRUE;
-}
-
-static void
-irc_login_cb(GObject *source, GAsyncResult *res, gpointer user_data)
-{
-	PurpleConnection *gc = user_data;
-	GSocketConnection *conn;
-	GError *error = NULL;
-	struct irc_conn *irc;
-
-	conn = g_socket_client_connect_to_host_finish(G_SOCKET_CLIENT(source),
-			res, &error);
-
-	if (conn == NULL) {
-		g_prefix_error(&error, "%s", _("Unable to connect: "));
-		purple_connection_take_error(gc, error);
-		return;
-	}
-
-	irc = purple_connection_get_protocol_data(gc);
-	irc->conn = conn;
-	irc->output = purple_queued_output_stream_new(
-			g_io_stream_get_output_stream(G_IO_STREAM(irc->conn)));
-
-	if (do_login(gc)) {
-		irc->input = g_data_input_stream_new(
-				g_io_stream_get_input_stream(
-						G_IO_STREAM(irc->conn)));
-		g_data_input_stream_read_line_async(irc->input,
-				G_PRIORITY_DEFAULT, irc->cancellable,
-				irc_read_input_cb, gc);
-	}
-}
-
-static void
-irc_close(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleConnection *gc) {
-	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
-
-	if (irc == NULL)
-		return;
-
-	if (irc->conn != NULL)
-		irc_cmd_quit(irc, "quit", NULL, NULL);
-
-	if (irc->cancellable != NULL) {
-		g_cancellable_cancel(irc->cancellable);
-		g_clear_object(&irc->cancellable);
-	}
-
-	if (irc->conn != NULL) {
-		purple_gio_graceful_close(G_IO_STREAM(irc->conn),
-				G_INPUT_STREAM(irc->input),
-				G_OUTPUT_STREAM(irc->output));
-	}
-
-	g_clear_object(&irc->input);
-	g_clear_object(&irc->output);
-	g_clear_object(&irc->conn);
-
-	g_clear_handle_id(&irc->timer, g_source_remove);
-	g_hash_table_destroy(irc->cmds);
-	g_hash_table_destroy(irc->msgs);
-	g_hash_table_destroy(irc->buddies);
-	if (irc->motd)
-		g_string_free(irc->motd, TRUE);
-	g_free(irc->server);
-
-	g_free(irc->mode_chars);
-	g_free(irc->reqnick);
-
-	g_clear_object(&irc->hasl_ctx);
-
-	g_free(irc);
-}
-
-static int
-irc_im_send(G_GNUC_UNUSED PurpleProtocolIM *im, PurpleConnection *gc,
-            PurpleMessage *msg)
-{
-	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
-	char *plain;
-	const char *args[2];
-
-	args[0] = irc_nick_skip_mode(irc, purple_message_get_recipient(msg));
-
-	purple_markup_html_to_xhtml(purple_message_get_contents(msg),
-		NULL, &plain);
-	args[1] = plain;
-
-	irc_cmd_privmsg(irc, "msg", NULL, args);
-	g_free(plain);
-	return 1;
-}
-
-static void
-irc_get_info(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
-             PurpleConnection *gc, const gchar *who)
-{
-	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
-	const char *args[2];
-	args[0] = who;
-	args[1] = NULL;
-	irc_cmd_whois(irc, "whois", NULL, args);
-}
-
-static void
-irc_set_status(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
-               PurpleAccount *account, PurpleStatus *status)
-{
-	PurpleConnection *gc = purple_account_get_connection(account);
-	struct irc_conn *irc;
-	const char *args[1];
-	const char *status_id = purple_status_get_id(status);
-
-	g_return_if_fail(gc != NULL);
-	irc = purple_connection_get_protocol_data(gc);
-
-	if (!purple_status_is_active(status))
-		return;
-
-	args[0] = NULL;
-
-	if (purple_strequal(status_id, "away")) {
-		args[0] = purple_status_get_attr_string(status, "message");
-		if ((args[0] == NULL) || (*args[0] == '\0'))
-			args[0] = _("Away");
-		irc_cmd_away(irc, "away", NULL, args);
-	} else if (purple_strequal(status_id, "available")) {
-		irc_cmd_away(irc, "back", NULL, args);
-	}
-}
-
-static void
-irc_add_buddy(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
-              PurpleConnection *gc, PurpleBuddy *buddy,
-              G_GNUC_UNUSED PurpleGroup *group,
-              G_GNUC_UNUSED const gchar *message)
-{
-	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
-	struct irc_buddy *ib;
-	const char *bname = purple_buddy_get_name(buddy);
-
-	ib = g_hash_table_lookup(irc->buddies, bname);
-	if (ib != NULL) {
-		ib->ref++;
-		purple_protocol_got_user_status(irc->account, bname,
-				ib->online ? "available" : "offline", NULL);
-	} else {
-		ib = g_new0(struct irc_buddy, 1);
-		ib->name = g_strdup(bname);
-		ib->ref = 1;
-		g_hash_table_replace(irc->buddies, ib->name, ib);
-	}
-
-	/* if the timer isn't set, this is during signon, so we don't want to flood
-	 * ourself off with ISON's, so we don't, but after that we want to know when
-	 * someone's online asap */
-	if (irc->timer)
-		irc_ison_one(irc, ib);
-}
-
-static void
-irc_remove_buddy(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
-                 PurpleConnection *gc, PurpleBuddy *buddy,
-                 G_GNUC_UNUSED PurpleGroup *group)
-{
-	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
-	struct irc_buddy *ib;
-
-	ib = g_hash_table_lookup(irc->buddies, purple_buddy_get_name(buddy));
-	if (ib && --ib->ref == 0) {
-		g_hash_table_remove(irc->buddies, purple_buddy_get_name(buddy));
-	}
-}
-
-static void
-irc_read_input_cb(GObject *source, GAsyncResult *res, gpointer data)
-{
-	PurpleConnection *gc = data;
-	struct irc_conn *irc;
-	gchar *line;
-	gsize len;
-	gsize start = 0;
-	GError *error = NULL;
-
-	line = g_data_input_stream_read_line_finish(
-			G_DATA_INPUT_STREAM(source), res, &len, &error);
-
-	if (line == NULL && error != NULL) {
-		g_prefix_error(&error, "%s", _("Lost connection with server: "));
-		purple_connection_take_error(gc, error);
-		return;
-	} else if (line == NULL) {
-		purple_connection_take_error(gc, g_error_new_literal(
-			PURPLE_CONNECTION_ERROR,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("Server closed the connection")));
-		return;
-	}
-
-	irc = purple_connection_get_protocol_data(gc);
-
-	purple_connection_update_last_received(gc);
-
-	if (len > 0 && line[len - 1] == '\r')
-		line[len - 1] = '\0';
-
-	/* This is a hack to work around the fact that marv gets messages
-	 * with null bytes in them while using some weird irc server at work
- 	 */
-	while (start < len && line[start] == '\0')
-		++start;
-
-	if (start < len) {
-		irc_parse_msg(irc, line + start);
-	}
-
-	g_free(line);
-
-	g_data_input_stream_read_line_async(irc->input,
-			G_PRIORITY_DEFAULT, irc->cancellable,
-			irc_read_input_cb, gc);
-}
-
-static void
-irc_chat_join(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
-              PurpleConnection *gc, GHashTable *data)
-{
-	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
-	const char *args[2];
-
-	args[0] = g_hash_table_lookup(data, "channel");
-	args[1] = g_hash_table_lookup(data, "password");
-	irc_cmd_join(irc, "join", NULL, args);
-}
-
-static gchar *
-irc_get_chat_name(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
-                  GHashTable *data)
-{
-	return g_strdup(g_hash_table_lookup(data, "channel"));
-}
-
-static void
-irc_chat_invite(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
-                PurpleConnection *gc, gint id,
-                G_GNUC_UNUSED const gchar *message, const gchar *name)
-{
-	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
-	PurpleConversation *convo;
-	PurpleConversationManager *manager;
-	const char *args[2];
-
-	manager = purple_conversation_manager_get_default();
-	convo = purple_conversation_manager_find_chat_by_id(manager,
-	                                                    purple_connection_get_account(gc),
-	                                                    id);
-	if (!convo) {
-		purple_debug_error("irc", "Got chat invite request for bogus chat");
-		return;
-	}
-	args[0] = name;
-	args[1] = purple_conversation_get_name(convo);
-	irc_cmd_invite(irc, "invite", purple_conversation_get_name(convo), args);
-}
-
-
-static void
-irc_chat_leave(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
-               PurpleConnection *gc, gint id)
-{
-	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
-	PurpleConversation *convo;
-	PurpleConversationManager *manager;
-	const char *args[2];
-
-	manager = purple_conversation_manager_get_default();
-	convo = purple_conversation_manager_find_chat_by_id(manager,
-	                                                    purple_connection_get_account(gc),
-	                                                    id);
-	if (!convo) {
-		return;
-	}
-
-	args[0] = purple_conversation_get_name(convo);
-	args[1] = NULL;
-	irc_cmd_part(irc, "part", purple_conversation_get_name(convo), args);
-	purple_serv_got_chat_left(gc, id);
-}
-
-static gint
-irc_chat_send(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
-              PurpleConnection *gc, gint id, PurpleMessage *msg)
-{
-	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
-	PurpleConversation *convo;
-	PurpleConversationManager *manager;
-	const char *args[2];
-	char *tmp;
-
-	manager = purple_conversation_manager_get_default();
-	convo = purple_conversation_manager_find_chat_by_id(manager,
-	                                                    purple_connection_get_account(gc),
-	                                                    id);
-
-	if (!convo) {
-		purple_debug_error("irc", "chat send on nonexistent chat");
-		return -EINVAL;
-	}
-	purple_markup_html_to_xhtml(purple_message_get_contents(msg), NULL, &tmp);
-	args[0] = purple_conversation_get_name(convo);
-	args[1] = tmp;
-
-	irc_cmd_privmsg(irc, "msg", NULL, args);
-
-	/* TODO: use msg */
-	purple_serv_got_chat_in(gc, id, purple_connection_get_display_name(gc),
-		purple_message_get_flags(msg),
-		purple_message_get_contents(msg), time(NULL));
-	g_free(tmp);
-	return 0;
-}
-
-static guint irc_nick_hash(const char *nick)
-{
-	char *lc;
-	guint bucket;
-
-	lc = g_utf8_strdown(nick, -1);
-	bucket = g_str_hash(lc);
-	g_free(lc);
-
-	return bucket;
-}
-
-static gboolean irc_nick_equal(const char *nick1, const char *nick2)
-{
-	return (purple_utf8_strcasecmp(nick1, nick2) == 0);
-}
-
-static void irc_buddy_free(struct irc_buddy *ib)
-{
-	g_free(ib->name);
-	g_free(ib);
-}
-
-static void
-irc_chat_set_topic(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
-                   PurpleConnection *gc, gint id, const gchar *topic)
-{
-	PurpleConversation *conv;
-	PurpleConversationManager *manager;
-	char *buf;
-	const char *name = NULL;
-	struct irc_conn *irc;
-
-	manager = purple_conversation_manager_get_default();
-	conv = purple_conversation_manager_find_chat_by_id(manager,
-	                                                   purple_connection_get_account(gc),
-	                                                   id);
-
-	irc = purple_connection_get_protocol_data(gc);
-	name = purple_conversation_get_name(conv);
-
-	if (name == NULL) {
-		return;
-	}
-
-	buf = irc_format(irc, "vt:", "TOPIC", name, topic);
-	irc_send(irc, buf);
-	g_free(buf);
-}
-
-static PurpleRoomlist *
-irc_roomlist_get_list(G_GNUC_UNUSED PurpleProtocolRoomlist *protocol_roomlist,
-                      PurpleConnection *gc)
-{
-	struct irc_conn *irc;
-	char *buf;
-
-	irc = purple_connection_get_protocol_data(gc);
-
-	if (irc->roomlist)
-		g_object_unref(irc->roomlist);
-
-	irc->roomlist = purple_roomlist_new(purple_connection_get_account(gc));
-
-	buf = irc_format(irc, "v", "LIST");
-	irc_send(irc, buf);
-	g_free(buf);
-
-	return irc->roomlist;
-}
-
-static void
-irc_roomlist_cancel(G_GNUC_UNUSED PurpleProtocolRoomlist *protocol_roomlist,
-                    PurpleRoomlist *list)
-{
-	PurpleAccount *account = purple_roomlist_get_account(list);
-	PurpleConnection *gc = purple_account_get_connection(account);
-	struct irc_conn *irc;
-
-	if (gc == NULL)
-		return;
-
-	irc = purple_connection_get_protocol_data(gc);
-
-	purple_roomlist_set_in_progress(list, FALSE);
-
-	if (irc->roomlist == list) {
-		irc->roomlist = NULL;
-		g_object_unref(list);
-	}
-}
-
-static void
-irc_keepalive(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
-              PurpleConnection *gc)
-{
-	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
-	if ((time(NULL) - irc->recv_time) > PING_TIMEOUT)
-		irc_cmd_ping(irc, NULL, NULL, NULL);
-}
-
-static const char *
-irc_normalize(G_GNUC_UNUSED PurpleProtocolClient *client,
-              G_GNUC_UNUSED PurpleAccount *account,
-              const char *who)
-{
-	return purple_normalize_nocase(who);
-}
-
-static gssize
-irc_get_max_message_size(G_GNUC_UNUSED PurpleProtocolClient *client,
-                         G_GNUC_UNUSED PurpleConversation *conv)
-{
-	/* TODO: this static value is got from pidgin-otr, but it depends on
-	 * some factors, for example IRC channel name. */
-	return 417;
-}
-
-static void
-irc_protocol_init(G_GNUC_UNUSED IRCProtocol *self) {
-}
-
-static void
-irc_protocol_class_init(IRCProtocolClass *klass)
-{
-	PurpleProtocolClass *protocol_class = PURPLE_PROTOCOL_CLASS(klass);
-
-	protocol_class->login = irc_login;
-	protocol_class->close = irc_close;
-	protocol_class->status_types = irc_status_types;
-
-	protocol_class->get_account_options = irc_protocol_get_account_options;
-	protocol_class->get_user_splits = irc_protocol_get_user_splits;
-}
-
-static void
-irc_protocol_class_finalize(G_GNUC_UNUSED IRCProtocolClass *klass)
-{
-}
-
-static void
-irc_protocol_actions_iface_init(PurpleProtocolActionsInterface *iface)
-{
-	iface->get_prefix = irc_protocol_actions_get_prefix;
-	iface->get_action_group = irc_protocol_actions_get_action_group;
-	iface->get_menu = irc_protocol_actions_get_menu;
-}
-
-static void
-irc_protocol_client_iface_init(PurpleProtocolClientInterface *client_iface)
-{
-	client_iface->normalize            = irc_normalize;
-	client_iface->get_max_message_size = irc_get_max_message_size;
-}
-
-static void
-irc_protocol_server_iface_init(PurpleProtocolServerInterface *server_iface)
-{
-	server_iface->set_status   = irc_set_status;
-	server_iface->get_info     = irc_get_info;
-	server_iface->add_buddy    = irc_add_buddy;
-	server_iface->remove_buddy = irc_remove_buddy;
-	server_iface->keepalive    = irc_keepalive;
-	server_iface->send_raw     = irc_send_raw;
-}
-
-static void
-irc_protocol_im_iface_init(PurpleProtocolIMInterface *im_iface)
-{
-	im_iface->send = irc_im_send;
-}
-
-static void
-irc_protocol_chat_iface_init(PurpleProtocolChatInterface *chat_iface)
-{
-	chat_iface->info          = irc_chat_join_info;
-	chat_iface->info_defaults = irc_chat_info_defaults;
-	chat_iface->join          = irc_chat_join;
-	chat_iface->get_name      = irc_get_chat_name;
-	chat_iface->invite        = irc_chat_invite;
-	chat_iface->leave         = irc_chat_leave;
-	chat_iface->send          = irc_chat_send;
-	chat_iface->set_topic     = irc_chat_set_topic;
-}
-
-static void
-irc_protocol_roomlist_iface_init(PurpleProtocolRoomlistInterface *roomlist_iface)
-{
-	roomlist_iface->get_list = irc_roomlist_get_list;
-	roomlist_iface->cancel   = irc_roomlist_cancel;
-}
-
-static void
-irc_protocol_xfer_iface_init(PurpleProtocolXferInterface *xfer_iface)
-{
-	xfer_iface->send_file = irc_dccsend_send_file;
-	xfer_iface->new_xfer  = irc_dccsend_new_xfer;
-}
-
-G_DEFINE_DYNAMIC_TYPE_EXTENDED(
-	IRCProtocol,
-	irc_protocol,
-	PURPLE_TYPE_PROTOCOL,
-	G_TYPE_FLAG_FINAL,
-	G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_ACTIONS,
-	                              irc_protocol_actions_iface_init)
-	G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_CLIENT,
-	                              irc_protocol_client_iface_init)
-	G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_SERVER,
-	                              irc_protocol_server_iface_init)
-	G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_IM,
-	                              irc_protocol_im_iface_init)
-	G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_CHAT,
-	                              irc_protocol_chat_iface_init)
-	G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_ROOMLIST,
-	                              irc_protocol_roomlist_iface_init)
-	G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_XFER,
-	                              irc_protocol_xfer_iface_init))
-
-static PurpleProtocol *
-irc_protocol_new(void) {
-	return PURPLE_PROTOCOL(g_object_new(
-		IRC_TYPE_PROTOCOL,
-		"id", "prpl-irc",
-		"name", "IRC",
-		"description", _("Internet Relay Chat (IRC) is a text-based chat "
-		                 "system."),
-		"icon-name", "im-irc",
-		"icon-resource-path", "/im/pidgin/libpurple/irc/icons",
-		"options", OPT_PROTO_CHAT_TOPIC | OPT_PROTO_PASSWORD_OPTIONAL |
-		           OPT_PROTO_SLASH_COMMANDS_NATIVE,
-		NULL));
-}
-
-static GPluginPluginInfo *
-irc_query(G_GNUC_UNUSED GError **error) {
-	return purple_plugin_info_new(
-		"id",           "prpl-irc",
-		"name",         "IRC Protocol",
-		"version",      DISPLAY_VERSION,
-		"category",     N_("Protocol"),
-		"summary",      N_("IRC Protocol Plugin"),
-		"description",  N_("The IRC Protocol Plugin that Sucks Less"),
-		"website",      PURPLE_WEBSITE,
-		"abi-version",  PURPLE_ABI_VERSION,
-		"flags",        PURPLE_PLUGIN_INFO_FLAGS_INTERNAL |
-		                PURPLE_PLUGIN_INFO_FLAGS_AUTO_LOAD,
-		NULL
-	);
-}
-
-static gboolean
-irc_load(GPluginPlugin *plugin, GError **error)
-{
-	PurpleProtocolManager *manager = purple_protocol_manager_get_default();
-
-	irc_protocol_register_type(G_TYPE_MODULE(plugin));
-
-	irc_xfer_register(G_TYPE_MODULE(plugin));
-
-	_irc_protocol = irc_protocol_new();
-	if(!purple_protocol_manager_register(manager, _irc_protocol, error)) {
-		g_clear_object(&_irc_protocol);
-
-		return FALSE;
-	}
-
-	purple_prefs_remove("/plugins/prpl/irc/quitmsg");
-	purple_prefs_remove("/plugins/prpl/irc");
-
-	irc_register_commands();
-
-	purple_signal_register(_irc_protocol, "irc-sending-text",
-			     purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
-			     PURPLE_TYPE_CONNECTION,
-			     G_TYPE_POINTER); /* pointer to a string */
-	purple_signal_register(_irc_protocol, "irc-receiving-text",
-			     purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
-			     PURPLE_TYPE_CONNECTION,
-			     G_TYPE_POINTER); /* pointer to a string */
-
-	purple_signal_connect(purple_get_core(), "uri-handler", plugin,
-			G_CALLBACK(irc_uri_handler), NULL);
-
-	return TRUE;
-}
-
-static gboolean
-irc_unload(GPluginPlugin *plugin, G_GNUC_UNUSED gboolean shutdown,
-           GError **error)
-{
-	PurpleProtocolManager *manager = purple_protocol_manager_get_default();
-
-	if(!purple_protocol_manager_unregister(manager, _irc_protocol, error)) {
-		return FALSE;
-	}
-
-	irc_unregister_commands();
-
-	purple_signal_disconnect(purple_get_core(), "uri-handler", plugin,
-			G_CALLBACK(irc_uri_handler));
-
-	g_clear_object(&_irc_protocol);
-
-	return TRUE;
-}
-
-GPLUGIN_NATIVE_PLUGIN_DECLARE(irc)
diff --git a/libpurple/protocols/irc/meson.build b/libpurple/protocols/irc/meson.build
deleted file mode 100644
--- a/libpurple/protocols/irc/meson.build
+++ /dev/null
@@ -1,23 +0,0 @@
-IRC_SOURCES = [
-	'cmds.c',
-	'dcc_send.c',
-	'irc.c',
-	'irc.h',
-	'msgs.c',
-	'parse.c'
-]
-
-if DYNAMIC_IRC
-	irc_resources = gnome.compile_resources('ircresource',
-		'resources/irc.gresource.xml',
-		source_dir : 'resources',
-		c_name : 'irc')
-	IRC_SOURCES += irc_resources
-
-	irc_prpl = shared_library('irc', IRC_SOURCES,
-	    c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="Purple-IRC"'],
-	    dependencies : [hasl, libpurple_dep, glib, gio, ws2_32],
-	    install : true, install_dir : PURPLE_PLUGINDIR)
-
-	devenv.append('PURPLE_PLUGIN_PATH', meson.current_build_dir())
-endif
diff --git a/libpurple/protocols/irc/msgs.c b/libpurple/protocols/irc/msgs.c
deleted file mode 100644
--- a/libpurple/protocols/irc/msgs.c
+++ /dev/null
@@ -1,1733 +0,0 @@
-/**
- * purple
- *
- * Copyright (C) 2003, 2012 Ethan Blanton <elb@pidgin.im>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-/*
- * Note: If you change any of these functions to use additional args you
- * MUST ensure the arg count is correct in parse.c. Otherwise it may be
- * possible for a malicious server or man-in-the-middle to trigger a crash.
- */
-
-#include <glib/gi18n-lib.h>
-
-#include <ctype.h>
-
-#include <purple.h>
-
-#include "irc.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <hasl.h>
-
-static char *irc_mask_nick(const char *mask);
-static char *irc_mask_userhost(const char *mask);
-static void irc_chat_remove_buddy(PurpleChatConversation *chat, char *data[2]);
-static void irc_buddy_status(char *name, struct irc_buddy *ib, struct irc_conn *irc);
-static void irc_connected(struct irc_conn *irc, const char *nick);
-
-static void irc_msg_handle_privmsg(struct irc_conn *irc, const char *name,
-                                   const char *from, const char *to,
-                                   const char *rawmsg, gboolean notice);
-
-static void irc_sasl_finish(struct irc_conn *irc);
-
-static char *irc_mask_nick(const char *mask)
-{
-	char *end, *buf;
-
-	end = strchr(mask, '!');
-	if (!end)
-		buf = g_strdup(mask);
-	else
-		buf = g_strndup(mask, end - mask);
-
-	return buf;
-}
-
-static char *irc_mask_userhost(const char *mask)
-{
-	return g_strdup(strchr(mask, '!') + 1);
-}
-
-static void irc_chat_remove_buddy(PurpleChatConversation *chat, char *data[2])
-{
-	char *message, *stripped;
-
-	stripped = data[1] ? irc_mirc2txt(data[1]) : NULL;
-	message = g_strdup_printf("quit: %s", stripped);
-	g_free(stripped);
-
-	if (purple_chat_conversation_has_user(chat, data[0]))
-		purple_chat_conversation_remove_user(chat, data[0], message);
-
-	g_free(message);
-}
-
-static void irc_connected(struct irc_conn *irc, const char *nick)
-{
-	PurpleConnection *gc;
-	PurpleStatus *status;
-	GSList *buddies;
-	PurpleAccount *account;
-
-	if ((gc = purple_account_get_connection(irc->account)) == NULL
-	    || PURPLE_CONNECTION_IS_CONNECTED(gc))
-		return;
-
-	purple_connection_set_display_name(gc, nick);
-	purple_connection_set_state(gc, PURPLE_CONNECTION_STATE_CONNECTED);
-	account = purple_connection_get_account(gc);
-
-	/* If we're away then set our away message */
-	status = purple_account_get_active_status(irc->account);
-	if (purple_status_type_get_primitive(purple_status_get_status_type(status)) != PURPLE_STATUS_AVAILABLE) {
-		PurpleProtocol *protocol = purple_connection_get_protocol(gc);
-		purple_protocol_server_set_status(PURPLE_PROTOCOL_SERVER(protocol), irc->account, status);
-	}
-
-	/* this used to be in the core, but it's not now */
-	for (buddies = purple_blist_find_buddies(account, NULL); buddies;
-			buddies = g_slist_delete_link(buddies, buddies))
-	{
-		PurpleBuddy *b = buddies->data;
-		struct irc_buddy *ib = g_new0(struct irc_buddy, 1);
-		ib->name = g_strdup(purple_buddy_get_name(b));
-		ib->ref = 1;
-		g_hash_table_replace(irc->buddies, ib->name, ib);
-	}
-
-	irc_blist_timeout(irc);
-	if (!irc->timer)
-		irc->timer = g_timeout_add_seconds(45, (GSourceFunc)irc_blist_timeout, (gpointer)irc);
-}
-
-/* This function is ugly, but it's really an error handler. */
-void
-irc_msg_default(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-                G_GNUC_UNUSED const char *from, char **args)
-{
-	int i;
-	const char *end, *cur, *numeric = NULL;
-	char *clean, *tmp, *convname;
-	PurpleConversation *convo;
-	PurpleConversationManager *manager;
-
-	for (cur = args[0], i = 0; i < 4; i++) {
-		end = strchr(cur, ' ');
-		if (end == NULL) {
-			goto undirected;
-		}
-		/* Check for 3-digit numeric in second position */
-		if (i == 1) {
-			if (end - cur != 3
-			    || !isdigit(cur[0]) || !isdigit(cur[1])
-			    || !isdigit(cur[2])) {
-				goto undirected;
-			}
-			/* Save the numeric for printing to the channel */
-			numeric = cur;
-		}
-		/* Don't advance cur if we're on the final iteration. */
-		if (i != 3) {
-			cur = end + 1;
-		}
-	}
-
-	/* At this point, cur is the beginning of the fourth position,
-	 * end is the following space, and there are remaining
-	 * arguments.  We'll check to see if this argument is a
-	 * currently active conversation (private message or channel,
-	 * either one), and print the numeric to that conversation if it
-	 * is. */
-
-	tmp = g_strndup(cur, end - cur);
-	convname = g_utf8_make_valid(tmp, -1);
-	g_free(tmp);
-
-	/* Check for an existing conversation */
-	manager = purple_conversation_manager_get_default();
-	convo = purple_conversation_manager_find(manager, irc->account, convname);
-	g_free(convname);
-
-	if (convo == NULL) {
-		goto undirected;
-	}
-
-	/* end + 1 is the first argument past the target.  The initial
-	 * arguments we've skipped are routing info, numeric, recipient
-	 * (this account's nick, most likely), and target (this
-	 * channel).  If end + 1 is an ASCII :, skip it, because it's
-	 * meaningless in this context.  This won't catch all
-	 * :-arguments, but it'll catch the easy case. */
-	if (*++end == ':') {
-		end++;
-	}
-
-	/* We then print "numeric: remainder". */
-	clean = g_utf8_make_valid(end, -1);
-	tmp = g_strdup_printf("%.3s: %s", numeric, clean);
-	g_free(clean);
-	purple_conversation_write_system_message(convo, tmp,
-		PURPLE_MESSAGE_NO_LOG | PURPLE_MESSAGE_RAW |
-		PURPLE_MESSAGE_NO_LINKIFY);
-	g_free(tmp);
-	return;
-
-  undirected:
-	/* This, too, should be escaped somehow (smarter) */
-	clean = g_utf8_make_valid(args[0], -1);
-	purple_debug_info("irc", "Unrecognized message: %s", clean);
-	g_free(clean);
-}
-
-void
-irc_msg_features(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-                 G_GNUC_UNUSED const char *from, char **args)
-{
-	gchar **features;
-	int i;
-
-	features = g_strsplit(args[1], " ", -1);
-	for (i = 0; features[i]; i++) {
-		char *val;
-		if (!strncmp(features[i], "PREFIX=", 7)) {
-			if ((val = strchr(features[i] + 7, ')')) != NULL)
-				irc->mode_chars = g_strdup(val + 1);
-		}
-	}
-
-	g_strfreev(features);
-}
-
-void
-irc_msg_luser(struct irc_conn *irc, const char *name,
-              G_GNUC_UNUSED const char *from, char **args)
-{
-	if (purple_strequal(name, "251")) {
-		/* 251 is required, so we pluck our nick from here and
-		 * finalize connection */
-		irc_connected(irc, args[0]);
-		/* Some IRC servers seem to not send a 255 numeric, so
-		 * I guess we can't require it; 251 will do. */
-	/* } else if (purple_strequal(name, "255")) { */
-	}
-}
-
-void irc_msg_away(struct irc_conn *irc, const char *name, const char *from, char **args)
-{
-	PurpleConnection *gc;
-	char *msg;
-
-	if (irc->whois.nick && !purple_utf8_strcasecmp(irc->whois.nick, args[1])) {
-		/* We're doing a whois, show this in the whois dialog */
-		irc_msg_whois(irc, name, from, args);
-		return;
-	}
-
-	gc = purple_account_get_connection(irc->account);
-	if (gc) {
-		msg = g_markup_escape_text(args[2], -1);
-		purple_serv_got_im(gc, args[1], msg, PURPLE_MESSAGE_AUTO_RESP, time(NULL));
-		g_free(msg);
-	}
-}
-
-void
-irc_msg_badmode(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-                G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-
-	g_return_if_fail(gc);
-
-	purple_notify_error(gc, NULL, _("Bad mode"), args[1],
-		purple_request_cpar_from_connection(gc));
-}
-
-void
-irc_msg_ban(struct irc_conn *irc, const char *name,
-            G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConversation *chat;
-	PurpleConversationManager *manager;
-
-	manager = purple_conversation_manager_get_default();
-	chat = purple_conversation_manager_find_chat(manager, irc->account,
-	                                             args[1]);
-
-	if (purple_strequal(name, "367")) {
-		char *msg = NULL;
-		/* Ban list entry */
-		if (args[3] && args[4]) {
-			/* This is an extended syntax, not in RFC 1459 */
-			int t1 = atoi(args[4]);
-			time_t t2 = time(NULL);
-			char *time = purple_str_seconds_to_string(t2 - t1);
-			msg = g_strdup_printf(_("Ban on %s by %s, set %s ago"),
-			                      args[2], args[3], time);
-			g_free(time);
-		} else {
-			msg = g_strdup_printf(_("Ban on %s"), args[2]);
-		}
-		if (chat) {
-			purple_conversation_write_system_message(
-				chat, msg, PURPLE_MESSAGE_NO_LOG);
-		} else {
-			purple_debug_info("irc", "%s\n", msg);
-		}
-		g_free(msg);
-	} else if (purple_strequal(name, "368")) {
-		if (!chat)
-			return;
-		/* End of ban list */
-		purple_conversation_write_system_message(chat,
-			_("End of ban list"), PURPLE_MESSAGE_NO_LOG);
-	}
-}
-
-void
-irc_msg_banned(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-               G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-	char *buf;
-
-	g_return_if_fail(gc);
-
-	buf = g_strdup_printf(_("You are banned from %s."), args[1]);
-	purple_notify_error(gc, _("Banned"), _("Banned"), buf,
-		purple_request_cpar_from_connection(gc));
-	g_free(buf);
-}
-
-void
-irc_msg_banfull(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-                G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConversation *chat;
-	PurpleConversationManager *manager;
-	char *buf, *nick;
-
-	manager = purple_conversation_manager_get_default();
-	chat = purple_conversation_manager_find_chat(manager, irc->account,
-	                                             args[1]);
-	if (!chat) {
-		return;
-	}
-
-	nick = g_markup_escape_text(args[2], -1);
-	buf = g_strdup_printf(_("Cannot ban %s: banlist is full"), nick);
-	g_free(nick);
-	purple_conversation_write_system_message(chat, buf, PURPLE_MESSAGE_NO_LOG);
-	g_free(buf);
-}
-
-void
-irc_msg_chanmode(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-                 G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConversation *chat;
-	PurpleConversationManager *manager;
-	char *buf, *escaped;
-
-	manager = purple_conversation_manager_get_default();
-	chat = purple_conversation_manager_find_chat(manager, irc->account,
-	                                             args[1]);
-	if (!chat) { /* XXX punt on channels we are not in for now */
-		return;
-	}
-
-	escaped = (args[3] != NULL) ? g_markup_escape_text(args[3], -1) : NULL;
-	buf = g_strdup_printf("mode for %s: %s %s", args[1], args[2], escaped ? escaped : "");
-	purple_conversation_write_system_message(chat, buf, 0);
-	g_free(escaped);
-	g_free(buf);
-}
-
-void
-irc_msg_whois(struct irc_conn *irc, const char *name,
-              G_GNUC_UNUSED const char *from, char **args)
-{
-	if (!irc->whois.nick) {
-		purple_debug_warning("irc", "Unexpected %s reply for %s",
-		                     purple_strequal(name, "314") ? "WHOWAS" : "WHOIS", args[1]);
-		return;
-	}
-
-	if (purple_utf8_strcasecmp(irc->whois.nick, args[1])) {
-		purple_debug_warning("irc", "Got %s reply for %s while waiting for %s",
-		                     purple_strequal(name, "314") ? "WHOWAS" : "WHOIS", args[1], irc->whois.nick);
-		return;
-	}
-
-	if (purple_strequal(name, "301")) {
-		irc->whois.away = g_strdup(args[2]);
-	} else if (purple_strequal(name, "311") || purple_strequal(name, "314")) {
-		irc->whois.ident = g_strdup(args[2]);
-		irc->whois.host = g_strdup(args[3]);
-		irc->whois.real = g_strdup(args[5]);
-	} else if (purple_strequal(name, "312")) {
-		irc->whois.server = g_strdup(args[2]);
-		irc->whois.serverinfo = g_strdup(args[3]);
-	} else if (purple_strequal(name, "313")) {
-		irc->whois.ircop = 1;
-	} else if (purple_strequal(name, "317")) {
-		irc->whois.idle = atoi(args[2]);
-		if (args[3])
-			irc->whois.signon = (time_t)atoi(args[3]);
-	} else if (purple_strequal(name, "319")) {
-		if (irc->whois.channels == NULL) {
-			irc->whois.channels = g_string_new(args[2]);
-		} else {
-			irc->whois.channels = g_string_append(irc->whois.channels, args[2]);
-		}
-	} else if (purple_strequal(name, "320")) {
-		irc->whois.identified = 1;
-	} else if (purple_strequal(name, "330")) {
-		purple_debug_info("irc", "330 %s: 1=[%s] 2=[%s] 3=[%s]",
-		                  name, args[1], args[2], args[3]);
-		if (purple_strequal(args[3], "is logged in as"))
-			irc->whois.login = g_strdup(args[2]);
-	}
-}
-
-void
-irc_msg_endwhois(struct irc_conn *irc, const char *name,
-                 G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConnection *gc;
-	char *tmp, *tmp2;
-	PurpleNotifyUserInfo *user_info;
-
-	if (!irc->whois.nick) {
-		purple_debug_warning("irc", "Unexpected End of %s for %s",
-		                     purple_strequal(name, "369") ? "WHOWAS" : "WHOIS", args[1]);
-		return;
-	}
-	if (purple_utf8_strcasecmp(irc->whois.nick, args[1])) {
-		purple_debug_warning("irc", "Received end of %s for %s, expecting %s",
-		                     purple_strequal(name, "369") ? "WHOWAS" : "WHOIS", args[1], irc->whois.nick);
-		return;
-	}
-
-	user_info = purple_notify_user_info_new();
-
-	tmp2 = g_markup_escape_text(args[1], -1);
-	tmp = g_strdup_printf("%s%s%s", tmp2,
-				(irc->whois.ircop ? _(" <i>(ircop)</i>") : ""),
-				(irc->whois.identified ? _(" <i>(identified)</i>") : ""));
-	purple_notify_user_info_add_pair_html(user_info, _("Nick"), tmp);
-	g_free(tmp2);
-	g_free(tmp);
-
-	if (irc->whois.away) {
-		purple_notify_user_info_add_pair_plaintext(user_info, _("Away"), irc->whois.away);
-		g_free(irc->whois.away);
-	}
-	if (irc->whois.real) {
-		purple_notify_user_info_add_pair_plaintext(user_info, _("Real name"), irc->whois.real);
-		g_free(irc->whois.real);
-	}
-	if (irc->whois.login) {
-		purple_notify_user_info_add_pair_plaintext(user_info, _("Login name"), irc->whois.login);
-		g_free(irc->whois.login);
-	}
-	if (irc->whois.ident) {
-		purple_notify_user_info_add_pair_plaintext(user_info, _("Ident name"), irc->whois.ident);
-		g_free(irc->whois.ident);
-	}
-	if (irc->whois.host) {
-		purple_notify_user_info_add_pair_plaintext(user_info, _("Host name"), irc->whois.host);
-		g_free(irc->whois.host);
-	}
-	if (irc->whois.server) {
-		tmp = g_strdup_printf("%s (%s)", irc->whois.server, irc->whois.serverinfo);
-		purple_notify_user_info_add_pair_plaintext(user_info, _("Server"), tmp);
-		g_free(tmp);
-		g_free(irc->whois.server);
-		g_free(irc->whois.serverinfo);
-	}
-	if (irc->whois.channels) {
-		purple_notify_user_info_add_pair_plaintext(user_info, _("Currently on"), irc->whois.channels->str);
-		g_string_free(irc->whois.channels, TRUE);
-	}
-	if (irc->whois.idle) {
-		GDateTime *signon = NULL;
-
-		tmp = purple_str_seconds_to_string(irc->whois.idle);
-		purple_notify_user_info_add_pair_plaintext(user_info, _("Idle for"),
-		                                           tmp);
-		g_free(tmp);
-
-		signon = g_date_time_new_from_unix_local(irc->whois.signon);
-		tmp = g_date_time_format(signon, "%c");
-		purple_notify_user_info_add_pair_plaintext(user_info,
-		                                           _("Online since"), tmp);
-		g_free(tmp);
-		g_date_time_unref(signon);
-	}
-	if (purple_strequal(irc->whois.nick, "elb")) {
-		purple_notify_user_info_add_pair_plaintext(user_info,
-																   _("<b>Defining adjective:</b>"), _("Glorious"));
-	}
-
-	gc = purple_account_get_connection(irc->account);
-
-	purple_notify_userinfo(gc, irc->whois.nick, user_info, NULL, NULL);
-	purple_notify_user_info_destroy(user_info);
-
-	g_free(irc->whois.nick);
-	memset(&irc->whois, 0, sizeof(irc->whois));
-}
-
-void
-irc_msg_who(struct irc_conn *irc, const char *name,
-            G_GNUC_UNUSED const char *from, char **args)
-{
-	if (purple_strequal(name, "352")) {
-		PurpleConversation *chat;
-		PurpleConversationManager *manager;
-		PurpleChatUser *cb;
-
-		char *cur, *userhost, *realname;
-
-		PurpleChatUserFlags flags;
-
-		manager = purple_conversation_manager_get_default();
-		chat = purple_conversation_manager_find_chat(manager, irc->account,
-		                                             args[1]);
-		if (!chat) {
-			purple_debug_error("irc", "Got a WHO response for %s, which doesn't exist", args[1]);
-			return;
-		}
-
-		cb = purple_chat_conversation_find_user(PURPLE_CHAT_CONVERSATION(chat), args[5]);
-		if (!cb) {
-			purple_debug_error("irc", "Got a WHO response for %s who isn't a buddy.", args[5]);
-			return;
-		}
-
-		userhost = g_strdup_printf("%s@%s", args[2], args[3]);
-
-		/* The final argument is a :-argument, but annoyingly
-		 * contains two "words", the hop count and real name. */
-		for (cur = args[7]; *cur; cur++) {
-			if (*cur == ' ') {
-				cur++;
-				break;
-			}
-		}
-		realname = g_strdup(cur);
-
-		g_object_set_data_full(G_OBJECT(cb), "userhost", userhost, g_free);
-		g_object_set_data_full(G_OBJECT(cb), "realname", realname, g_free);
-
-		flags = purple_chat_user_get_flags(cb);
-
-		/* FIXME: I'm not sure this is really a good idea, now
-		 * that we no longer do periodic WHO.  It seems to me
-		 * like it's more likely to be confusing than not.
-		 * Comments? */
-		if (args[6][0] == 'G' && !(flags & PURPLE_CHAT_USER_AWAY)) {
-			purple_chat_user_set_flags(cb, flags | PURPLE_CHAT_USER_AWAY);
-		} else if(args[6][0] == 'H' && (flags & PURPLE_CHAT_USER_AWAY)) {
-			purple_chat_user_set_flags(cb, flags & ~PURPLE_CHAT_USER_AWAY);
-		}
-	}
-}
-
-void
-irc_msg_list(struct irc_conn *irc, const char *name,
-             G_GNUC_UNUSED const char *from, char **args)
-{
-	if (!irc->roomlist)
-		return;
-
-	if (purple_strequal(name, "321")) {
-		purple_roomlist_set_in_progress(irc->roomlist, TRUE);
-		return;
-	}
-
-	if (purple_strequal(name, "323")) {
-		purple_roomlist_set_in_progress(irc->roomlist, FALSE);
-		g_object_unref(irc->roomlist);
-		irc->roomlist = NULL;
-		return;
-	}
-
-	if (purple_strequal(name, "322")) {
-		PurpleRoomlistRoom *room;
-		char *topic;
-
-		if (!purple_roomlist_get_in_progress(irc->roomlist)) {
-			purple_debug_warning("irc", "Buggy server didn't send RPL_LISTSTART.\n");
-			purple_roomlist_set_in_progress(irc->roomlist, TRUE);
-		}
-
-		topic = irc_mirc2txt(args[3]);
-		room = purple_roomlist_room_new(args[1], topic);
-		g_free(topic);
-
-		purple_roomlist_room_set_user_count(room, strtol(args[2], NULL, 10));
-		purple_roomlist_room_add_field(room, "channel", args[1]);
-		purple_roomlist_room_add(irc->roomlist, room);
-		g_object_unref(room);
-	}
-}
-
-void irc_msg_topic(struct irc_conn *irc, const char *name, const char *from, char **args)
-{
-	char *chan, *topic, *msg, *nick, *tmp, *tmp2;
-	PurpleConversation *chat;
-	PurpleConversationManager *manager;
-
-	if (purple_strequal(name, "topic")) {
-		chan = args[0];
-		topic = irc_mirc2txt (args[1]);
-	} else {
-		chan = args[1];
-		topic = irc_mirc2txt (args[2]);
-	}
-
-	manager = purple_conversation_manager_get_default();
-	chat = purple_conversation_manager_find_chat(manager, irc->account, chan);
-	if (!chat) {
-		purple_debug_error("irc", "Got a topic for %s, which doesn't exist", chan);
-		g_free(topic);
-		return;
-	}
-
-	/* If this is an interactive update, print it out */
-	tmp = g_markup_escape_text(topic, -1);
-	tmp2 = purple_markup_linkify(tmp);
-	g_free(tmp);
-	if (purple_strequal(name, "topic")) {
-		const char *current_topic = purple_chat_conversation_get_topic(PURPLE_CHAT_CONVERSATION(chat));
-		if (!(current_topic != NULL && purple_strequal(tmp2, current_topic)))
-		{
-			char *nick_esc;
-			nick = irc_mask_nick(from);
-			nick_esc = g_markup_escape_text(nick, -1);
-			purple_chat_conversation_set_topic(PURPLE_CHAT_CONVERSATION(chat), nick, topic);
-			if (*tmp2)
-				msg = g_strdup_printf(_("%s has changed the topic to: %s"), nick_esc, tmp2);
-			else
-				msg = g_strdup_printf(_("%s has cleared the topic."), nick_esc);
-			g_free(nick_esc);
-			g_free(nick);
-			purple_conversation_write_system_message(
-				chat, msg, 0);
-			g_free(msg);
-		}
-	} else {
-		char *chan_esc = g_markup_escape_text(chan, -1);
-		msg = g_strdup_printf(_("The topic for %s is: %s"), chan_esc, tmp2);
-		g_free(chan_esc);
-		purple_chat_conversation_set_topic(PURPLE_CHAT_CONVERSATION(chat), NULL, topic);
-		purple_conversation_write_system_message(chat, msg, 0);
-		g_free(msg);
-	}
-	g_free(tmp2);
-	g_free(topic);
-}
-
-void
-irc_msg_topicinfo(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-                  G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConversation *chat;
-	PurpleConversationManager *manager;
-	GDateTime *dt, *local;
-	gint64 mtime;
-	char *msg, *timestamp, *datestamp;
-
-	manager = purple_conversation_manager_get_default();
-	chat = purple_conversation_manager_find_chat(manager, irc->account,
-	                                             args[1]);
-	if (!chat) {
-		purple_debug_error("irc", "Got topic info for %s, which doesn't exist", args[1]);
-		return;
-	}
-
-	mtime = g_ascii_strtoll(args[3], NULL, 10);
-	if(mtime == 0 || mtime == G_MININT64 || mtime == G_MAXINT64) {
-		purple_debug_error("irc", "Got apparently nonsensical topic timestamp %s", args[3]);
-		return;
-	}
-
-	dt = g_date_time_new_from_unix_utc(mtime);
-	if(dt == NULL) {
-		purple_debug_error("irc", "Failed to turn %" G_GINT64_FORMAT " into a GDateTime", mtime);
-		return;
-	}
-
-	local = g_date_time_to_local(dt);
-	g_date_time_unref(dt);
-
-	timestamp = g_date_time_format(local, "%X");
-	datestamp = g_date_time_format(local, "%x");
-	msg = g_strdup_printf(_("Topic for %s set by %s at %s on %s"), args[1], args[2], timestamp, datestamp);
-	purple_conversation_write_system_message(chat,
-		msg, PURPLE_MESSAGE_NO_LINKIFY);
-	g_free(timestamp);
-	g_free(datestamp);
-	g_free(msg);
-	g_date_time_unref(local);
-}
-
-void
-irc_msg_unknown(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-                G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-	char *buf;
-
-	g_return_if_fail(gc);
-
-	buf = g_strdup_printf(_("Unknown message '%s'"), args[1]);
-	purple_notify_error(gc, _("Unknown message"), buf, _("The IRC server "
-		"received a message it did not understand."),
-		purple_request_cpar_from_connection(gc));
-	g_free(buf);
-}
-
-void
-irc_msg_names(struct irc_conn *irc, const char *name,
-              G_GNUC_UNUSED const char *from, char **args)
-{
-	char *names, *cur, *end, *tmp, *msg;
-
-	if (purple_strequal(name, "366")) {
-		PurpleConversation *convo;
-		PurpleConversationManager *manager;
-
-		manager = purple_conversation_manager_get_default();
-		convo = purple_conversation_manager_find(manager, irc->account,
-		                                         args[1]);
-		if (!convo) {
-			purple_debug_error("irc", "Got a NAMES list for %s, which doesn't exist", args[1]);
-			g_string_free(irc->names, TRUE);
-			irc->names = NULL;
-			return;
-		}
-
-		names = cur = g_string_free(irc->names, FALSE);
-		irc->names = NULL;
-		if (g_object_get_data(G_OBJECT(convo), IRC_NAMES_FLAG)) {
-			msg = g_strdup_printf(_("Users on %s: %s"), args[1], names ? names : "");
-			purple_conversation_write_system_message(convo, msg, PURPLE_MESSAGE_NO_LOG);
-			g_free(msg);
-		} else if (cur != NULL) {
-			GList *users = NULL;
-			GList *flags = NULL;
-
-			while (*cur) {
-				PurpleChatUserFlags f = PURPLE_CHAT_USER_NONE;
-				end = strchr(cur, ' ');
-				if (!end)
-					end = cur + strlen(cur);
-				if (*cur == '@') {
-					f = PURPLE_CHAT_USER_OP;
-					cur++;
-				} else if (*cur == '%') {
-					f = PURPLE_CHAT_USER_HALFOP;
-					cur++;
-				} else if(*cur == '+') {
-					f = PURPLE_CHAT_USER_VOICE;
-					cur++;
-				} else if(irc->mode_chars
-					  && strchr(irc->mode_chars, *cur)) {
-					if (*cur == '~')
-						f = PURPLE_CHAT_USER_FOUNDER;
-					cur++;
-				}
-				tmp = g_strndup(cur, end - cur);
-				users = g_list_prepend(users, tmp);
-				flags = g_list_prepend(flags, GINT_TO_POINTER(f));
-				cur = end;
-				if (*cur)
-					cur++;
-			}
-
-			if (users != NULL) {
-				purple_chat_conversation_add_users(PURPLE_CHAT_CONVERSATION(convo), users, NULL, flags, FALSE);
-
-				g_list_free_full(users, g_free);
-				g_list_free(flags);
-			}
-
-			g_object_set_data(G_OBJECT(convo), IRC_NAMES_FLAG,
-						   GINT_TO_POINTER(TRUE));
-		}
-		g_free(names);
-	} else {
-		if (!irc->names)
-			irc->names = g_string_new("");
-
-		if (irc->names->len && irc->names->str[irc->names->len - 1] != ' ')
-			irc->names = g_string_append_c(irc->names, ' ');
-		irc->names = g_string_append(irc->names, args[3]);
-	}
-}
-
-void
-irc_msg_motd(struct irc_conn *irc, const char *name,
-             G_GNUC_UNUSED const char *from, char **args)
-{
-	char *escaped;
-
-	if (purple_strequal(name, "375")) {
-		if (irc->motd) {
-			g_string_free(irc->motd, TRUE);
-			irc->motd = NULL;
-		}
-		irc->motd = g_string_new("");
-		return;
-	} else if (purple_strequal(name, "376")) {
-		/* dircproxy 1.0.5 does not send 251 on reconnection, so
-		 * finalize the connection here if it is not already done. */
-		irc_connected(irc, args[0]);
-		return;
-	} else if (purple_strequal(name, "422")) {
-		/* in case there is no 251, and no MOTD set, finalize the connection.
-		 * (and clear the motd for good measure). */
-
-		if (irc->motd) {
-			g_string_free(irc->motd, TRUE);
-			irc->motd = NULL;
-		}
-
-		irc_connected(irc, args[0]);
-		return;
-	}
-
-	if (!irc->motd) {
-		purple_debug_error("irc", "IRC server sent MOTD without STARTMOTD\n");
-		return;
-	}
-
-	if (!args[1])
-		return;
-
-	escaped = g_markup_escape_text(args[1], -1);
-	g_string_append_printf(irc->motd, "%s<br>", escaped);
-	g_free(escaped);
-}
-
-void
-irc_msg_time(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-             G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConnection *gc;
-
-	gc = purple_account_get_connection(irc->account);
-
-	g_return_if_fail(gc);
-
-	purple_notify_message(gc, PURPLE_NOTIFY_MSG_INFO, _("Time Response"),
-		_("The IRC server's local time is:"), args[2], NULL, NULL,
-		purple_request_cpar_from_connection(gc));
-}
-
-void
-irc_msg_nochan(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-               G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-
-	g_return_if_fail(gc);
-
-	purple_notify_error(gc, NULL, _("No such channel"), args[1],
-		purple_request_cpar_from_connection(gc));
-}
-
-void
-irc_msg_nonick(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-               G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConnection *gc;
-	PurpleConversation *convo;
-	PurpleConversationManager *manager;
-
-	manager = purple_conversation_manager_get_default();
-	convo = purple_conversation_manager_find(manager, irc->account, args[1]);
-	if (convo) {
-		purple_conversation_write_system_message(convo,
-			PURPLE_IS_IM_CONVERSATION(convo) ? _("User is not logged in") : _("no such channel"),
-			PURPLE_MESSAGE_NO_LOG);
-
-	} else {
-		if ((gc = purple_account_get_connection(irc->account)) == NULL)
-			return;
-		purple_notify_error(gc, NULL, _("No such nick or channel"),
-			args[1], purple_request_cpar_from_connection(gc));
-	}
-
-	if (irc->whois.nick && !purple_utf8_strcasecmp(irc->whois.nick, args[1])) {
-		g_free(irc->whois.nick);
-		irc->whois.nick = NULL;
-	}
-}
-
-void
-irc_msg_nosend(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-               G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConnection *gc;
-	PurpleConversation *chat;
-	PurpleConversationManager *manager;
-
-	manager = purple_conversation_manager_get_default();
-	chat = purple_conversation_manager_find_chat(manager, irc->account,
-	                                             args[1]);
-	if (chat) {
-		purple_conversation_write_system_message(chat, args[2],
-			PURPLE_MESSAGE_NO_LOG);
-	} else {
-		if ((gc = purple_account_get_connection(irc->account)) == NULL)
-			return;
-		purple_notify_error(gc, NULL, _("Could not send"), args[2],
-			purple_request_cpar_from_connection(gc));
-	}
-}
-
-void
-irc_msg_notinchan(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-                  G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConversation *chat;
-	PurpleConversationManager *manager;
-
-	manager = purple_conversation_manager_get_default();
-	chat = purple_conversation_manager_find_chat(manager, irc->account,
-	                                             args[1]);
-
-	purple_debug_info("irc", "We're apparently not in %s, but tried to use it", args[1]);
-	if (chat) {
-		/*g_slist_remove(irc->gc->buddy_chats, chat);
-		  purple_conversation_set_account(chat, NULL);*/
-		purple_conversation_write_system_message(chat,
-			args[2], PURPLE_MESSAGE_NO_LOG);
-	}
-}
-
-void
-irc_msg_notop(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-              G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConversation *chat;
-	PurpleConversationManager *manager;
-
-	manager = purple_conversation_manager_get_default();
-	chat = purple_conversation_manager_find_chat(manager, irc->account,
-	                                             args[1]);
-	if (!chat) {
-		return;
-	}
-
-	purple_conversation_write_system_message(chat, args[2], 0);
-}
-
-void
-irc_msg_invite(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-               const char *from, char **args)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-	GHashTable *components;
-	gchar *nick;
-
-	g_return_if_fail(gc);
-
-	components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-	nick = irc_mask_nick(from);
-
-	g_hash_table_insert(components, g_strdup("channel"), g_strdup(args[1]));
-
-	purple_serv_got_chat_invite(gc, args[1], nick, NULL, components);
-	g_free(nick);
-}
-
-void
-irc_msg_inviteonly(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-                   G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-	char *buf;
-
-	g_return_if_fail(gc);
-
-	buf = g_strdup_printf(_("Joining %s requires an invitation."), args[1]);
-	purple_notify_error(gc, _("Invitation only"), _("Invitation only"), buf,
-		purple_request_cpar_from_connection(gc));
-	g_free(buf);
-}
-
-void
-irc_msg_ison(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-             G_GNUC_UNUSED const char *from, char **args)
-{
-	char **nicks;
-	struct irc_buddy *ib;
-	int i;
-
-	nicks = g_strsplit(args[1], " ", -1);
-	for (i = 0; nicks[i]; i++) {
-		if ((ib = g_hash_table_lookup(irc->buddies, (gconstpointer)nicks[i])) == NULL) {
-			continue;
-		}
-		ib->new_online_status = TRUE;
-	}
-	g_strfreev(nicks);
-
-	if (irc->ison_outstanding)
-		irc_buddy_query(irc);
-
-	if (!irc->ison_outstanding)
-		g_hash_table_foreach(irc->buddies, (GHFunc)irc_buddy_status, (gpointer)irc);
-}
-
-static void irc_buddy_status(char *name, struct irc_buddy *ib, struct irc_conn *irc)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-	PurpleBuddy *buddy = purple_blist_find_buddy(irc->account, name);
-
-	if (!gc || !buddy)
-		return;
-
-	if (ib->online && !ib->new_online_status) {
-		purple_protocol_got_user_status(irc->account, name, "offline", NULL);
-		ib->online = FALSE;
-	} else if (!ib->online && ib->new_online_status) {
-		purple_protocol_got_user_status(irc->account, name, "available", NULL);
-		ib->online = TRUE;
-	}
-}
-
-void
-irc_msg_join(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-             const char *from, char **args)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-	PurpleConversation *chat;
-	PurpleConversationManager *manager;
-	PurpleChatUser *cb;
-
-	char *nick, *userhost, *buf;
-	struct irc_buddy *ib;
-	static int id = 1;
-
-	g_return_if_fail(gc);
-
-	nick = irc_mask_nick(from);
-
-	manager = purple_conversation_manager_get_default();
-
-	if (!purple_utf8_strcasecmp(nick, purple_connection_get_display_name(gc))) {
-		/* We are joining a channel for the first time */
-		purple_serv_got_joined_chat(gc, id++, args[0]);
-		g_free(nick);
-		chat = purple_conversation_manager_find_chat(manager, irc->account,
-		                                             args[0]);
-
-		if (chat == NULL) {
-			purple_debug_error("irc", "tried to join %s but couldn't\n", args[0]);
-			return;
-		}
-		g_object_set_data(G_OBJECT(chat), IRC_NAMES_FLAG,
-					   GINT_TO_POINTER(FALSE));
-
-		// Get the real name and user host for all participants.
-		buf = irc_format(irc, "vc", "WHO", args[0]);
-		irc_send(irc, buf);
-		g_free(buf);
-
-		/* Until purple_conversation_present does something that
-		 * one would expect in Pidgin, this call produces buggy
-		 * behavior both for the /join and auto-join cases. */
-		/* purple_conversation_present(chat); */
-		return;
-	}
-
-	chat = purple_conversation_manager_find_chat(manager, irc->account,
-	                                             args[0]);
-	if (chat == NULL) {
-		purple_debug_error("irc", "JOIN for %s failed", args[0]);
-		g_free(nick);
-		return;
-	}
-
-	userhost = irc_mask_userhost(from);
-
-	purple_chat_conversation_add_user(PURPLE_CHAT_CONVERSATION(chat), nick, userhost, PURPLE_CHAT_USER_NONE, TRUE);
-
-	cb = purple_chat_conversation_find_user(PURPLE_CHAT_CONVERSATION(chat), nick);
-
-	if (cb) {
-		g_object_set_data_full(G_OBJECT(cb), "userhost", userhost, g_free);
-	}
-
-	if ((ib = g_hash_table_lookup(irc->buddies, nick)) != NULL) {
-		ib->new_online_status = TRUE;
-		irc_buddy_status(nick, ib, irc);
-	}
-
-	g_free(nick);
-}
-
-void
-irc_msg_kick(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-             const char *from, char **args)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-	PurpleConversation *chat;
-	PurpleConversationManager *manager;
-	char *nick, *buf;
-
-	g_return_if_fail(gc);
-
-	manager = purple_conversation_manager_get_default();
-	chat = purple_conversation_manager_find_chat(manager, irc->account,
-	                                             args[0]);
-
-	nick = irc_mask_nick(from);
-
-	if (!chat) {
-		purple_debug_error("irc", "Received a KICK for unknown channel %s", args[0]);
-		g_free(nick);
-		return;
-	}
-
-	if (!purple_utf8_strcasecmp(purple_connection_get_display_name(gc), args[1])) {
-		buf = g_strdup_printf(_("You have been kicked by %s: (%s)"), nick, args[2]);
-		purple_conversation_write_system_message(PURPLE_CONVERSATION(chat), buf, 0);
-		g_free(buf);
-		purple_serv_got_chat_left(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(chat)));
-	} else {
-		buf = g_strdup_printf(_("Kicked by %s (%s)"), nick, args[2]);
-		purple_chat_conversation_remove_user(PURPLE_CHAT_CONVERSATION(chat), args[1], buf);
-		g_free(buf);
-	}
-
-	g_free(nick);
-}
-
-void
-irc_msg_mode(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-             const char *from, char **args)
-{
-	char *nick = irc_mask_nick(from), *buf;
-
-	if (*args[0] == '#' || *args[0] == '&') {	/* Channel	*/
-		PurpleConversation *chat;
-		PurpleConversationManager *manager;
-		char *escaped;
-
-		manager = purple_conversation_manager_get_default();
-		chat = purple_conversation_manager_find_chat(manager, irc->account,
-		                                             args[0]);
-		if (!chat) {
-			purple_debug_error("irc", "MODE received for %s, which we are not in", args[0]);
-			g_free(nick);
-			return;
-		}
-		escaped = (args[2] != NULL) ? g_markup_escape_text(args[2], -1) : NULL;
-		buf = g_strdup_printf(_("mode (%s %s) by %s"), args[1], escaped ? escaped : "", nick);
-		purple_conversation_write_system_message(chat, buf, 0);
-		g_free(escaped);
-		g_free(buf);
-		if(args[2]) {
-			PurpleChatUser *cb;
-			PurpleChatUserFlags newflag, flags;
-			char *mcur, *cur, *end, *user;
-			gboolean add = FALSE;
-			mcur = args[1];
-			cur = args[2];
-			while (*cur && *mcur) {
-				if ((*mcur == '+') || (*mcur == '-')) {
-					add = (*mcur == '+') ? TRUE : FALSE;
-					mcur++;
-					continue;
-				}
-				end = strchr(cur, ' ');
-				if (!end)
-					end = cur + strlen(cur);
-				user = g_strndup(cur, end - cur);
-				cb = purple_chat_conversation_find_user(PURPLE_CHAT_CONVERSATION(chat), user);
-				flags = purple_chat_user_get_flags(cb);
-				newflag = PURPLE_CHAT_USER_NONE;
-				if (*mcur == 'o')
-					newflag = PURPLE_CHAT_USER_OP;
-				else if (*mcur =='h')
-					newflag = PURPLE_CHAT_USER_HALFOP;
-				else if (*mcur == 'v')
-					newflag = PURPLE_CHAT_USER_VOICE;
-				else if(irc->mode_chars
-					  && strchr(irc->mode_chars, '~') && (*mcur == 'q'))
-					newflag = PURPLE_CHAT_USER_FOUNDER;
-				if (newflag) {
-					if (add)
-						flags |= newflag;
-					else
-						flags &= ~newflag;
-					purple_chat_user_set_flags(cb, flags);
-				}
-				g_free(user);
-				cur = end;
-				if (*cur)
-					cur++;
-				if (*mcur)
-					mcur++;
-			}
-		}
-	} else {					/* User		*/
-	}
-	g_free(nick);
-}
-
-void
-irc_msg_nick(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-             const char *from, char **args)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-	PurpleConversation *im;
-	PurpleConversationManager *manager;
-	GSList *chats;
-	char *nick = irc_mask_nick(from);
-
-	irc->nickused = FALSE;
-
-	if (!gc) {
-		g_free(nick);
-		return;
-	}
-	chats = purple_connection_get_active_chats(gc);
-
-	if (!purple_utf8_strcasecmp(nick, purple_connection_get_display_name(gc))) {
-		purple_connection_set_display_name(gc, args[0]);
-	}
-
-	while (chats) {
-		PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(chats->data);
-		/* This is ugly ... */
-		if (purple_chat_conversation_has_user(chat, nick))
-			purple_chat_conversation_rename_user(chat, nick, args[0]);
-		chats = chats->next;
-	}
-
-	manager = purple_conversation_manager_get_default();
-	im = purple_conversation_manager_find_im(manager, irc->account, nick);
-	if (im != NULL) {
-		purple_conversation_set_name(im, args[0]);
-	}
-
-	g_free(nick);
-}
-
-void
-irc_msg_badnick(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-                G_GNUC_UNUSED const char *from, G_GNUC_UNUSED char **args)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-	if (purple_connection_get_state(gc) == PURPLE_CONNECTION_STATE_CONNECTED) {
-		purple_notify_error(gc, _("Invalid nickname"), _("Invalid "
-			"nickname"), _("Your selected nickname was rejected by "
-			"the server.  It probably contains invalid characters."),
-			purple_request_cpar_from_connection(gc));
-
-	} else {
-		purple_connection_take_error(gc, g_error_new_literal(
-				PURPLE_CONNECTION_ERROR,
-				PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
-				_("Your selected account name was rejected by the server.  It probably contains invalid characters.")));
-	}
-}
-
-void
-irc_msg_nickused(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-                 G_GNUC_UNUSED const char *from, char **args)
-{
-	char *newnick, *buf, *end;
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-
-	if (gc && purple_connection_get_state(gc) == PURPLE_CONNECTION_STATE_CONNECTED) {
-		/* We only want to do the following dance if the connection
-		   has not been successfully completed.  If it has, just
-		   notify the user that their /nick command didn't go. */
-		buf = g_strdup_printf(_("The nickname \"%s\" is already being used."),
-				      irc->reqnick);
-		purple_notify_error(gc, _("Nickname in use"), _("Nickname in "
-			"use"), buf, purple_request_cpar_from_connection(gc));
-		g_free(buf);
-		g_free(irc->reqnick);
-		irc->reqnick = NULL;
-		return;
-	}
-
-	if (strlen(args[1]) < strlen(irc->reqnick) || irc->nickused)
-		newnick = g_strdup(args[1]);
-	else
-		newnick = g_strdup_printf("%s0", args[1]);
-	end = newnick + strlen(newnick) - 1;
-	/* try fallbacks */
-	if((*end < '9') && (*end >= '1')) {
-			*end = *end + 1;
-	} else *end = '1';
-
-	g_free(irc->reqnick);
-	irc->reqnick = newnick;
-	irc->nickused = TRUE;
-
-	purple_connection_set_display_name(
-		purple_account_get_connection(irc->account), newnick);
-
-	buf = irc_format(irc, "vn", "NICK", newnick);
-	irc_send(irc, buf);
-	g_free(buf);
-}
-
-void irc_msg_notice(struct irc_conn *irc, const char *name, const char *from, char **args)
-{
-	irc_msg_handle_privmsg(irc, name, from, args[0], args[1], TRUE);
-}
-
-void
-irc_msg_nochangenick(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-                     G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-
-	g_return_if_fail(gc);
-
-	purple_notify_error(gc, _("Cannot change nick"),
-		_("Could not change nick"), args[2],
-		purple_request_cpar_from_connection(gc));
-}
-
-void
-irc_msg_part(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-             const char *from, char **args)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-	PurpleConversation *chat;
-	PurpleConversationManager *manager;
-	char *nick, *msg, *channel;
-
-	g_return_if_fail(gc);
-
-	/* Undernet likes to :-quote the channel name, for no good reason
-	 * that I can see.  This catches that. */
-	channel = (args[0][0] == ':') ? &args[0][1] : args[0];
-
-	manager = purple_conversation_manager_get_default();
-	chat = purple_conversation_manager_find_chat(manager, irc->account,
-	                                             channel);
-	if (!chat) {
-		purple_debug_info("irc", "Got a PART on %s, which doesn't exist -- probably closed", channel);
-		return;
-	}
-
-	nick = irc_mask_nick(from);
-	if (!purple_utf8_strcasecmp(nick, purple_connection_get_display_name(gc))) {
-		char *escaped = args[1] ? g_markup_escape_text(args[1], -1) : NULL;
-		msg = g_strdup_printf(_("You have parted the channel%s%s"),
-		                      (args[1] && *args[1]) ? ": " : "",
-		                      (escaped && *escaped) ? escaped : "");
-		g_free(escaped);
-		purple_conversation_write_system_message(chat, msg, 0);
-		g_free(msg);
-		purple_serv_got_chat_left(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(chat)));
-	} else {
-		msg = args[1] ? irc_mirc2txt(args[1]) : NULL;
-		purple_chat_conversation_remove_user(PURPLE_CHAT_CONVERSATION(chat), nick, msg);
-		g_free(msg);
-	}
-	g_free(nick);
-}
-
-void
-irc_msg_ping(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-             G_GNUC_UNUSED const char *from, char **args)
-{
-	char *buf;
-
-	buf = irc_format(irc, "v:", "PONG", args[0]);
-	irc_send(irc, buf);
-	g_free(buf);
-}
-
-void
-irc_msg_pong(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-             G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConversation *convo;
-	PurpleConversationManager *manager;
-	PurpleConnection *gc;
-	char **parts, *msg;
-	gint64 oldstamp;
-
-	parts = g_strsplit(args[1], " ", 2);
-
-	if (!parts[0] || !parts[1]) {
-		g_strfreev(parts);
-		return;
-	}
-
-	if (sscanf(parts[1], "%" G_GINT64_FORMAT, &oldstamp) != 1) {
-		msg = g_strdup(_("Error: invalid PONG from server"));
-	} else {
-		msg = g_strdup_printf(_("PING reply -- Lag: %f seconds"),
-		                      (g_get_monotonic_time() - oldstamp) /
-		                              (gdouble)G_USEC_PER_SEC);
-	}
-
-	manager = purple_conversation_manager_get_default();
-	convo = purple_conversation_manager_find(manager, irc->account, parts[0]);
-	g_strfreev(parts);
-	if (convo) {
-		purple_conversation_write_system_message(convo, msg, PURPLE_MESSAGE_NO_LOG);
-	} else {
-		gc = purple_account_get_connection(irc->account);
-		if (!gc) {
-			g_free(msg);
-			return;
-		}
-		purple_notify_info(gc, NULL, "PONG", msg,
-			purple_request_cpar_from_connection(gc));
-	}
-	g_free(msg);
-}
-
-void irc_msg_privmsg(struct irc_conn *irc, const char *name, const char *from, char **args)
-{
-	irc_msg_handle_privmsg(irc, name, from, args[0], args[1], FALSE);
-}
-
-static void
-irc_msg_handle_privmsg(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-                       const char *from, const char *to, const char *rawmsg,
-                       gboolean notice)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-	PurpleConversation *chat;
-	char *tmp;
-	char *msg;
-	char *nick;
-
-	if (!gc)
-		return;
-
-	nick = irc_mask_nick(from);
-	tmp = irc_parse_ctcp(irc, nick, to, rawmsg, notice);
-	if (!tmp) {
-		g_free(nick);
-		return;
-	}
-
-	msg = irc_escape_privmsg(tmp, -1);
-	g_free(tmp);
-
-	tmp = irc_mirc2html(msg);
-	g_free(msg);
-	msg = tmp;
-	if (notice) {
-		tmp = g_strdup_printf("(notice) %s", msg);
-		g_free(msg);
-		msg = tmp;
-	}
-
-	if (!purple_utf8_strcasecmp(to, purple_connection_get_display_name(gc))) {
-		purple_serv_got_im(gc, nick, msg, 0, time(NULL));
-	} else {
-		PurpleConversationManager *manager;
-
-		manager = purple_conversation_manager_get_default();
-		chat = purple_conversation_manager_find_chat(manager, irc->account,
-		                                             irc_nick_skip_mode(irc, to));
-		if (chat) {
-			purple_serv_got_chat_in(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(chat)),
-				nick, PURPLE_MESSAGE_RECV, msg, time(NULL));
-		} else
-			purple_debug_info("irc", "Got a %s on %s, which does not exist\n",
-			                  notice ? "NOTICE" : "PRIVMSG", to);
-	}
-	g_free(msg);
-	g_free(nick);
-}
-
-void
-irc_msg_regonly(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-                G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-	PurpleConversationManager *manager;
-	char *msg;
-
-	g_return_if_fail(gc);
-
-	manager = purple_conversation_manager_get_default();
-
-	if(purple_conversation_manager_find_chat(manager, irc->account, args[1])) {
-		/* This is a channel we're already in; for some reason,
-		 * freenode feels the need to notify us that in some
-		 * hypothetical other situation this might not have
-		 * succeeded.  Suppress that. */
-		return;
-	}
-
-	msg = g_strdup_printf(_("Cannot join %s: Registration is required."), args[1]);
-	purple_notify_error(gc, _("Cannot join channel"), msg, args[2],
-		purple_request_cpar_from_connection(gc));
-	g_free(msg);
-}
-
-void
-irc_msg_quit(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-             const char *from, char **args)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-	struct irc_buddy *ib;
-	char *data[2];
-
-	g_return_if_fail(gc);
-
-	data[0] = irc_mask_nick(from);
-	data[1] = args[0];
-	/* XXX this should have an API, I shouldn't grab this directly */
-	g_slist_foreach(purple_connection_get_active_chats(gc),
-			(GFunc)irc_chat_remove_buddy, data);
-
-	if ((ib = g_hash_table_lookup(irc->buddies, data[0])) != NULL) {
-		ib->new_online_status = FALSE;
-		irc_buddy_status(data[0], ib, irc);
-	}
-	g_free(data[0]);
-}
-
-void
-irc_msg_unavailable(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-                    G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-
-	purple_notify_error(gc, NULL, _("Nick or channel is temporarily "
-		"unavailable."), args[1],
-		purple_request_cpar_from_connection(gc));
-}
-
-void
-irc_msg_wallops(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-                const char *from, char **args)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-	char *nick, *msg;
-
-	g_return_if_fail(gc);
-
-	nick = irc_mask_nick(from);
-	msg = g_strdup_printf (_("Wallops from %s"), nick);
-	g_free(nick);
-	purple_notify_info(gc, NULL, msg, args[0],
-		purple_request_cpar_from_connection(gc));
-	g_free(msg);
-}
-
-static void
-irc_auth_sasl_attempt(struct irc_conn *irc) {
-	PurpleAccount *account = irc->account;
-	PurpleConnection *gc = purple_account_get_connection(account);
-	char *buf;
-	const char *current_mechanism = NULL;
-	const char *next_mechanism = NULL;
-
-	current_mechanism = hasl_context_get_current_mechanism(irc->hasl_ctx);
-	if(current_mechanism != NULL) {
-		g_message("SASL '%s' mechanism failed", current_mechanism);
-	}
-
-	next_mechanism = hasl_context_next(irc->hasl_ctx);
-	if(next_mechanism == NULL) {
-		purple_connection_take_error(gc,
-		                             g_error_new_literal(
-		                             PURPLE_CONNECTION_ERROR,
-		                             PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
-		                             _("SASL authentication failed: No worthy authentication mechanisms found.")));
-		irc_sasl_finish(irc);
-
-		return;
-	}
-
-	g_message("Using SASL: %s", next_mechanism);
-	buf = irc_format(irc, "vv", "AUTHENTICATE", next_mechanism);
-	irc_send(irc, buf);
-	g_free(buf);
-}
-
-/* SASL authentication */
-void
-irc_msg_cap(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-            G_GNUC_UNUSED const char *from, char **args)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-	gboolean allow_clear_text = FALSE;
-
-	if (strncmp(g_strstrip(args[2]), "sasl", 5))
-		return;
-	if (strncmp(args[1], "ACK", 4)) {
-		purple_connection_take_error(gc, g_error_new_literal(
-			PURPLE_CONNECTION_ERROR,
-			PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
-			_("SASL authentication failed: Server does not support SASL authentication.")));
-
-		irc_sasl_finish(irc);
-		return;
-	}
-
-	irc->hasl_ctx = hasl_context_new();
-	hasl_context_set_allowed_mechanisms(irc->hasl_ctx, "PLAIN");
-
-	hasl_context_set_username(irc->hasl_ctx,
-	                          purple_connection_get_display_name(gc));
-	hasl_context_set_password(irc->hasl_ctx,
-	                          purple_connection_get_password(gc));
-	hasl_context_set_authzid(irc->hasl_ctx, "");
-	hasl_context_set_tls(irc->hasl_ctx, G_IS_TLS_CONNECTION(irc->conn));
-
-	allow_clear_text = purple_account_get_bool(irc->account,
-	                                           "auth_plain_in_clear",
-	                                           FALSE);
-	hasl_context_set_allow_clear_text(irc->hasl_ctx, allow_clear_text);
-
-	irc_auth_sasl_attempt(irc);
-}
-
-void
-irc_msg_auth(struct irc_conn *irc, char *arg)
-{
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-	HaslMechanismResult res;
-	GError *error = NULL;
-	char *buf, *authinfo;
-	char *serverin = NULL;
-	gsize serverinlen = 0;
-	guint8 *c_out;
-	gsize clen;
-
-	if(!arg) {
-		return;
-	}
-
-	if(arg[0] != '+') {
-		serverin = (char *)g_base64_decode(arg, &serverinlen);
-	}
-
-	res = hasl_context_step(irc->hasl_ctx, (guint8 *)serverin, serverinlen,
-	                        &c_out, &clen, &error);
-	g_free(serverin);
-
-	if(res == HASL_MECHANISM_RESULT_ERROR) {
-		const char *error_msg = "unknown error";
-
-		if(error != NULL && error->message != NULL) {
-			error_msg = error->message;
-		}
-
-		purple_connection_take_error(gc, g_error_new(
-			PURPLE_CONNECTION_ERROR,
-			PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
-			_("SASL authentication failed: %s"),
-			error_msg));
-
-		g_clear_error(&error);
-
-		irc_sasl_finish(irc);
-
-		return;
-	}
-
-	if(error != NULL) {
-			g_warning("hasl_context_step returned an error without an error "
-			          "status: %s", error->message);
-			g_clear_error(&error);
-	}
-
-	if(clen > 0) {
-		authinfo = g_base64_encode(c_out, clen);
-		g_free(c_out);
-	} else {
-		authinfo = g_strdup("+");
-	}
-
-	buf = irc_format(irc, "vv", "AUTHENTICATE", authinfo);
-	irc_send(irc, buf);
-	g_free(buf);
-	g_free(authinfo);
-	g_free(serverin);
-}
-
-void
-irc_msg_authenticate(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-                     G_GNUC_UNUSED const char *from, char **args)
-{
-	irc_msg_auth(irc, args[0]);
-}
-
-void
-irc_msg_authok(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-               G_GNUC_UNUSED const char *from, G_GNUC_UNUSED char **args)
-{
-	char *buf;
-
-	g_clear_object(&irc->hasl_ctx);
-	purple_debug_info("irc", "Successfully authenticated using SASL.\n");
-
-	/* Finish auth session */
-	buf = irc_format(irc, "vv", "CAP", "END");
-	irc_send(irc, buf);
-	g_free(buf);
-}
-
-void
-irc_msg_authtryagain(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-                     G_GNUC_UNUSED const char *from, G_GNUC_UNUSED char **args)
-{
-	irc_auth_sasl_attempt(irc);
-}
-
-void
-irc_msg_authfail(struct irc_conn *irc, G_GNUC_UNUSED const char *name,
-                 G_GNUC_UNUSED const char *from,
-                 G_GNUC_UNUSED char **args)
-{
-	irc_auth_sasl_attempt(irc);
-}
-
-static void
-irc_sasl_finish(struct irc_conn *irc)
-{
-	char *buf;
-
-	g_clear_object(&irc->hasl_ctx);
-
-	/* Auth failed, abort */
-	buf = irc_format(irc, "vv", "CAP", "END");
-	irc_send(irc, buf);
-	g_free(buf);
-}
diff --git a/libpurple/protocols/irc/parse.c b/libpurple/protocols/irc/parse.c
deleted file mode 100644
--- a/libpurple/protocols/irc/parse.c
+++ /dev/null
@@ -1,819 +0,0 @@
-/**
- * purple
- *
- * Copyright (C) 2003, Ethan Blanton <eblanton@cs.purdue.edu>
- *
- * 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 "irc.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-static GSList *cmds = NULL;
-
-static char *irc_send_convert(struct irc_conn *irc, const char *string);
-static char *irc_recv_convert(struct irc_conn *irc, const char *string);
-
-static void irc_parse_error_cb(struct irc_conn *irc, char *input);
-
-static char *irc_mirc_colors[16] = {
-	"white", "black", "blue", "dark green", "red", "brown", "purple",
-		"orange", "yellow", "green", "teal", "cyan", "light blue",
-		"pink", "grey", "light grey" };
-
-extern PurpleProtocol *_irc_protocol;
-
-/*typedef void (*IRCMsgCallback)(struct irc_conn *irc, char *from, char *name, char **args);*/
-static struct _irc_msg {
-	char *name;
-	char *format;
-
-	/** The required parameter count, based on values we use, not protocol
-	 *  specification. */
-	int req_cnt;
-
-	void (*cb)(struct irc_conn *irc, const char *name, const char *from, char **args);
-} _irc_msgs[] = {
-	{ "005", "n*", 2, irc_msg_features },		/* Feature list			*/
-	{ "251", "n:", 1, irc_msg_luser },		/* Client & Server count	*/
-	{ "255", "n:", 1, irc_msg_luser },		/* Client & Server count Mk. II	*/
-	{ "301", "nn:", 3, irc_msg_away },		/* User is away			*/
-	{ "303", "n:", 2, irc_msg_ison },		/* ISON reply			*/
-	{ "311", "nnvvv:", 6, irc_msg_whois },		/* Whois user			*/
-	{ "312", "nnv:", 4, irc_msg_whois },		/* Whois server			*/
-	{ "313", "nn:", 2, irc_msg_whois },		/* Whois ircop			*/
-	{ "314", "nnnvv:", 6, irc_msg_whois },		/* Whowas user			*/
-	{ "315", "nt:", 0, irc_msg_who },		/* end of WHO channel		*/
-	{ "317", "nnvv", 3, irc_msg_whois },		/* Whois idle			*/
-	{ "318", "nt:", 2, irc_msg_endwhois },		/* End of WHOIS			*/
-	{ "319", "nn:", 3, irc_msg_whois },		/* Whois channels		*/
-	{ "320", "nn:", 2, irc_msg_whois },		/* Whois (fn ident)		*/
-	{ "321", "*", 0, irc_msg_list },		/* Start of list		*/
-	{ "322", "ncv:", 4, irc_msg_list },		/* List.			*/
-	{ "323", ":", 0, irc_msg_list },		/* End of list.			*/
-	{ "324", "ncv:", 3, irc_msg_chanmode },		/* Channel modes		*/
-	{ "330", "nnv:", 4, irc_msg_whois },		/* Whois (fn login)		*/
-	{ "331", "nc:", 3, irc_msg_topic },		/* No channel topic		*/
-	{ "332", "nc:", 3, irc_msg_topic },		/* Channel topic		*/
-	{ "333", "ncvv", 4, irc_msg_topicinfo },	/* Topic setter stuff		*/
-	{ "352", "ncvvvnv:", 8, irc_msg_who },		/* Channel WHO			*/
-	{ "353", "nvc:", 4, irc_msg_names },		/* Names list			*/
-	{ "366", "nc:", 2, irc_msg_names },		/* End of names			*/
-	{ "367", "ncnnv", 3, irc_msg_ban },		/* Ban list			*/
-	{ "368", "nc:", 2, irc_msg_ban },		/* End of ban list		*/
-	{ "369", "nt:", 2, irc_msg_endwhois },		/* End of WHOWAS		*/
-	{ "372", "n:", 1, irc_msg_motd },		/* MOTD				*/
-	{ "375", "n:", 1, irc_msg_motd },		/* Start MOTD			*/
-	{ "376", "n:", 1, irc_msg_motd },		/* End of MOTD			*/
-	{ "391", "nv:", 3, irc_msg_time },		/* Time reply			*/
-	{ "401", "nt:", 2, irc_msg_nonick },		/* No such nick/chan		*/
-	{ "403", "nc:", 2, irc_msg_nochan },		/* No such channel		*/
-	{ "404", "nt:", 3, irc_msg_nosend },		/* Cannot send to chan		*/
-	{ "406", "nt:", 2, irc_msg_nonick },		/* No such nick for WHOWAS	*/
-	{ "421", "nv:", 2, irc_msg_unknown },		/* Unknown command		*/
-	{ "422", "n:", 1, irc_msg_motd },		/* MOTD file missing		*/
-	{ "432", "vn:", 0, irc_msg_badnick },		/* Erroneous nickname		*/
-	{ "433", "vn:", 2, irc_msg_nickused },		/* Nickname already in use	*/
-	{ "437", "nc:", 2, irc_msg_unavailable },	/* Nick/channel is unavailable	*/
-	{ "438", "nn:", 3, irc_msg_nochangenick },	/* Nick may not change		*/
-	{ "442", "nc:", 3, irc_msg_notinchan },		/* Not in channel		*/
-	{ "473", "nc:", 2, irc_msg_inviteonly },	/* Tried to join invite-only	*/
-	{ "474", "nc:", 2, irc_msg_banned },		/* Banned from channel		*/
-	{ "477", "nc:", 3, irc_msg_regonly },		/* Registration Required	*/
-	{ "478", "nct:", 3, irc_msg_banfull },		/* Banlist is full		*/
-	{ "482", "nc:", 3, irc_msg_notop },		/* Need to be op to do that	*/
-	{ "501", "n:", 2, irc_msg_badmode },		/* Unknown mode flag		*/
-	{ "506", "nc:", 3, irc_msg_nosend },		/* Must identify to send	*/
-	{ "515", "nc:", 3, irc_msg_regonly },		/* Registration required	*/
-	{ "903", "*", 0, irc_msg_authok},		/* SASL auth successful		*/
-	{ "904", "*", 0, irc_msg_authtryagain },	/* SASL auth failed, can recover*/
-	{ "905", "*", 0, irc_msg_authfail },		/* SASL auth failed		*/
-	{ "906", "*", 0, irc_msg_authfail },		/* SASL auth failed		*/
-	{ "907", "*", 0, irc_msg_authfail },		/* SASL auth failed		*/
-	{ "cap", "vv:", 3, irc_msg_cap },		/* SASL capable			*/
-	{ "authenticate", ":", 1, irc_msg_authenticate }, /* SASL authenticate		*/
-	{ "invite", "n:", 2, irc_msg_invite },		/* Invited			*/
-	{ "join", ":", 1, irc_msg_join },		/* Joined a channel		*/
-	{ "kick", "cn:", 3, irc_msg_kick },		/* KICK				*/
-	{ "mode", "tv:", 2, irc_msg_mode },		/* MODE for channel		*/
-	{ "nick", ":", 1, irc_msg_nick },		/* Nick change			*/
-	{ "notice", "t:", 2, irc_msg_notice },		/* NOTICE recv			*/
-	{ "part", "c:", 1, irc_msg_part },		/* Parted a channel		*/
-	{ "ping", ":", 1, irc_msg_ping },		/* Received PING from server	*/
-	{ "pong", "v:", 2, irc_msg_pong },		/* Received PONG from server	*/
-	{ "privmsg", "t:", 2, irc_msg_privmsg },	/* Received private message	*/
-	{ "topic", "c:", 2, irc_msg_topic },		/* TOPIC command		*/
-	{ "quit", ":", 1, irc_msg_quit },		/* QUIT notice			*/
-	{ "wallops", ":", 1, irc_msg_wallops },		/* WALLOPS command		*/
-	{ NULL, NULL, 0, NULL }
-};
-
-static struct _irc_user_cmd {
-	char *name;
-	char *format;
-	IRCCmdCallback cb;
-	char *help;
-} _irc_cmds[] = {
-	{ "action", ":", irc_cmd_ctcp_action, N_("action &lt;action to perform&gt;:  Perform an action.") },
-	{ "authserv", ":", irc_cmd_service, N_("authserv: Send a command to authserv") },
-	{ "away", ":", irc_cmd_away, N_("away [message]:  Set an away message, or use no message to return from being away.") },
-	{ "ctcp", "t:", irc_cmd_ctcp, N_("ctcp <nick> <msg>: sends ctcp msg to nick.") },
-	{ "chanserv", ":", irc_cmd_service, N_("chanserv: Send a command to chanserv") },
-	{ "deop", ":", irc_cmd_op, N_("deop &lt;nick1&gt; [nick2] ...:  Remove channel operator status from someone. You must be a channel operator to do this.") },
-	{ "devoice", ":", irc_cmd_op, N_("devoice &lt;nick1&gt; [nick2] ...:  Remove channel voice status from someone, preventing them from speaking if the channel is moderated (+m). You must be a channel operator to do this.") },
-	{ "invite", ":", irc_cmd_invite, N_("invite &lt;nick&gt; [room]:  Invite someone to join you in the specified channel, or the current channel.") },
-	{ "j", "cv", irc_cmd_join, N_("j &lt;room1&gt;[,room2][,...] [key1[,key2][,...]]:  Enter one or more channels, optionally providing a channel key for each if needed.") },
-	{ "join", "cv", irc_cmd_join, N_("join &lt;room1&gt;[,room2][,...] [key1[,key2][,...]]:  Enter one or more channels, optionally providing a channel key for each if needed.") },
-	{ "kick", "n:", irc_cmd_kick, N_("kick &lt;nick&gt; [message]:  Remove someone from a channel. You must be a channel operator to do this.") },
-	{ "list", ":", irc_cmd_list, N_("list:  Display a list of chat rooms on the network. <i>Warning, some servers may disconnect you upon doing this.</i>") },
-	{ "me", ":", irc_cmd_ctcp_action, N_("me &lt;action to perform&gt;:  Perform an action.") },
-	{ "memoserv", ":", irc_cmd_service, N_("memoserv: Send a command to memoserv") },
-	{ "mode", ":", irc_cmd_mode, N_("mode &lt;+|-&gt;&lt;A-Za-z&gt; &lt;nick|channel&gt;:  Set or unset a channel or user mode.") },
-	{ "msg", "t:", irc_cmd_privmsg, N_("msg &lt;nick&gt; &lt;message&gt;:  Send a private message to a user (as opposed to a channel).") },
-	{ "names", "c", irc_cmd_names, N_("names [channel]:  List the users currently in a channel.") },
-	{ "nick", "n", irc_cmd_nick, N_("nick &lt;new nickname&gt;:  Change your nickname.") },
-	{ "nickserv", ":", irc_cmd_service, N_("nickserv: Send a command to nickserv") },
-	{ "notice", "t:", irc_cmd_privmsg, N_("notice &lt;target&lt;:  Send a notice to a user or channel.") },
-	{ "op", ":", irc_cmd_op, N_("op &lt;nick1&gt; [nick2] ...:  Grant channel operator status to someone. You must be a channel operator to do this.") },
-	{ "operwall", ":", irc_cmd_wallops, N_("operwall &lt;message&gt;:  If you don't know what this is, you probably can't use it.") },
-	{ "operserv", ":", irc_cmd_service, N_("operserv: Send a command to operserv") },
-	{ "part", "c:", irc_cmd_part, N_("part [room] [message]:  Leave the current channel, or a specified channel, with an optional message.") },
-	{ "ping", "n", irc_cmd_ping, N_("ping [nick]:  Asks how much lag a user (or the server if no user specified) has.") },
-	{ "query", "n:", irc_cmd_query, N_("query &lt;nick&gt; &lt;message&gt;:  Send a private message to a user (as opposed to a channel).") },
-	{ "quit", ":", irc_cmd_quit, N_("quit [message]:  Disconnect from the server, with an optional message.") },
-	{ "quote", "*", irc_cmd_quote, N_("quote [...]:  Send a raw command to the server.") },
-	{ "remove", "n:", irc_cmd_remove, N_("remove &lt;nick&gt; [message]:  Remove someone from a room. You must be a channel operator to do this.") },
-	{ "time", "", irc_cmd_time, N_("time: Displays the current local time at the IRC server.") },
-	{ "topic", ":", irc_cmd_topic, N_("topic [new topic]:  View or change the channel topic.") },
-	{ "umode", ":", irc_cmd_mode, N_("umode &lt;+|-&gt;&lt;A-Za-z&gt;:  Set or unset a user mode.") },
-	{ "version", ":", irc_cmd_ctcp_version, N_("version [nick]: send CTCP VERSION request to a user") },
-	{ "voice", ":", irc_cmd_op, N_("voice &lt;nick1&gt; [nick2] ...:  Grant channel voice status to someone. You must be a channel operator to do this.") },
-	{ "wallops", ":", irc_cmd_wallops, N_("wallops &lt;message&gt;:  If you don't know what this is, you probably can't use it.") },
-	{ "whois", "tt", irc_cmd_whois, N_("whois [server] &lt;nick&gt;:  Get information on a user.") },
-	{ "whowas", "t", irc_cmd_whowas, N_("whowas &lt;nick&gt;: Get information on a user that has logged off.") },
-	{ NULL, NULL, NULL, NULL }
-};
-
-static PurpleCmdRet
-irc_parse_purple_cmd(PurpleConversation *conv, const gchar *cmd,
-                     gchar **args, G_GNUC_UNUSED gchar **error,
-                     G_GNUC_UNUSED gpointer data)
-{
-	PurpleConnection *gc;
-	struct irc_conn *irc;
-	struct _irc_user_cmd *cmdent;
-
-	gc = purple_conversation_get_connection(conv);
-	if (!gc)
-		return PURPLE_CMD_RET_FAILED;
-
-	irc = purple_connection_get_protocol_data(gc);
-
-	if ((cmdent = g_hash_table_lookup(irc->cmds, cmd)) == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	(cmdent->cb)(irc, cmd, purple_conversation_get_name(conv), (const char **)args);
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static void irc_register_command(struct _irc_user_cmd *c)
-{
-	PurpleCmdId id;
-	PurpleCmdFlag f;
-	char args[10];
-	char *format;
-	size_t i;
-
-	f = PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PROTOCOL_ONLY
-	    | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS;
-
-	format = c->format;
-
-	for (i = 0; (i < (sizeof(args) - 1)) && *format; i++, format++)
-		switch (*format) {
-		case 'v':
-		case 'n':
-		case 'c':
-		case 't':
-			args[i] = 'w';
-			break;
-		case ':':
-		case '*':
-			args[i] = 's';
-			break;
-		}
-
-	args[i] = '\0';
-
-	id = purple_cmd_register(c->name, args, PURPLE_CMD_P_PROTOCOL, f, "prpl-irc",
-	                  irc_parse_purple_cmd, _(c->help), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-}
-
-void irc_register_commands(void)
-{
-	struct _irc_user_cmd *c;
-
-	for (c = _irc_cmds; c && c->name; c++)
-		irc_register_command(c);
-}
-
-void irc_unregister_commands(void)
-{
-	g_clear_slist(&cmds, (GDestroyNotify)(gpointer)purple_cmd_unregister);
-}
-
-static char *irc_send_convert(struct irc_conn *irc, const char *string)
-{
-	char *utf8;
-	GError *err = NULL;
-	gchar **encodings;
-	const gchar *enclist;
-
-	enclist = purple_account_get_string(irc->account, "encoding", IRC_DEFAULT_CHARSET);
-	encodings = g_strsplit(enclist, ",", 2);
-
-	if (encodings[0] == NULL || !g_ascii_strcasecmp("UTF-8", encodings[0])) {
-		g_strfreev(encodings);
-		return NULL;
-	}
-
-	utf8 = g_convert(string, strlen(string), encodings[0], "UTF-8", NULL, NULL, &err);
-	if (err) {
-		purple_debug_error("irc", "Send conversion error: %s", err->message);
-		purple_debug_error("irc", "Sending as UTF-8 instead of %s", encodings[0]);
-		utf8 = g_strdup(string);
-		g_error_free(err);
-	}
-	g_strfreev(encodings);
-
-	return utf8;
-}
-
-static char *irc_recv_convert(struct irc_conn *irc, const char *string)
-{
-	char *utf8 = NULL;
-	const gchar *charset, *enclist;
-	gchar **encodings;
-	gboolean autodetect;
-	int i;
-
-	autodetect = purple_account_get_bool(irc->account, "autodetect_utf8", IRC_DEFAULT_AUTODETECT);
-
-	if (autodetect && g_utf8_validate(string, -1, NULL)) {
-		return g_strdup(string);
-	}
-
-	enclist = purple_account_get_string(irc->account, "encoding", IRC_DEFAULT_CHARSET);
-	encodings = g_strsplit(enclist, ",", -1);
-
-	if (encodings[0] == NULL) {
-		g_strfreev(encodings);
-		return g_utf8_make_valid(string, -1);
-	}
-
-	for (i = 0; encodings[i] != NULL; i++) {
-		charset = encodings[i];
-		while (*charset == ' ')
-			charset++;
-
-		if (!g_ascii_strcasecmp("UTF-8", charset)) {
-			if (g_utf8_validate(string, -1, NULL))
-				utf8 = g_strdup(string);
-		} else {
-			utf8 = g_convert(string, -1, "UTF-8", charset, NULL, NULL, NULL);
-		}
-
-		if (utf8) {
-			g_strfreev(encodings);
-			return utf8;
-		}
-	}
-	g_strfreev(encodings);
-
-	return g_utf8_make_valid(string, -1);
-}
-
-/* This function is shamelessly stolen from glib--it is an old version of the
- * private function append_escaped_text, used by g_markup_escape_text, whose
- * behavior changed in glib 2.12. */
-static void irc_append_escaped_text(GString *str, const char *text, gssize length)
-{
-	const char *p = text;
-	const char *end = text + length;
-	const char *next = NULL;
-
-	while(p != end) {
-		next = g_utf8_next_char(p);
-
-		switch(*p) {
-			case '&':
-				g_string_append(str, "&amp;");
-				break;
-			case '<':
-				g_string_append(str, "&lt;");
-				break;
-			case '>':
-				g_string_append(str, "&gt;");
-				break;
-			case '\'':
-				g_string_append(str, "&apos;");
-				break;
-			case '"':
-				g_string_append(str, "&quot;");
-				break;
-			default:
-				g_string_append_len(str, p, next - p);
-				break;
-		}
-
-		p = next;
-	}
-}
-
-/* This function is shamelessly stolen from glib--it is an old version of the
- * function g_markup_escape_text, whose behavior changed in glib 2.12. */
-char *irc_escape_privmsg(const char *text, gssize length)
-{
-	GString *str;
-
-	g_return_val_if_fail(text != NULL, NULL);
-
-	if(length < 0)
-		length = strlen(text);
-
-	str = g_string_sized_new(length);
-
-	irc_append_escaped_text(str, text, length);
-
-	return g_string_free(str, FALSE);
-}
-
-/* XXX tag closings are not necessarily correctly nested here!  If we
- *     get a ^O or reach the end of the string and there are open
- *     tags, they are closed in a fixed order ... this means, for
- *     example, you might see <FONT COLOR="blue">some text <B>with
- *     various attributes</FONT></B> (notice that B and FONT overlap
- *     and are not cleanly nested).  This is imminently fixable but
- *     I am not fixing it right now.
- */
-char *irc_mirc2html(const char *string)
-{
-	const char *cur, *end;
-	char fg[3] = "\0\0", bg[3] = "\0\0";
-	int fgnum, bgnum;
-	int font = 0, bold = 0, underline = 0, italic = 0;
-	GString *decoded;
-
-	if (string == NULL)
-		return NULL;
-
-	decoded = g_string_sized_new(strlen(string));
-
-	cur = string;
-	do {
-		end = strpbrk(cur, "\002\003\007\017\026\037");
-
-		decoded = g_string_append_len(decoded, cur, (end ? (gssize)(end - cur) : (gssize)strlen(cur)));
-		cur = end ? end : cur + strlen(cur);
-
-		switch (*cur) {
-		case '\002':
-			cur++;
-			if (!bold) {
-				decoded = g_string_append(decoded, "<B>");
-				bold = TRUE;
-			} else {
-				decoded = g_string_append(decoded, "</B>");
-				bold = FALSE;
-			}
-			break;
-		case '\003':
-			cur++;
-			fg[0] = fg[1] = bg[0] = bg[1] = '\0';
-			if (isdigit(*cur))
-				fg[0] = *cur++;
-			if (isdigit(*cur))
-				fg[1] = *cur++;
-			if (*cur == ',') {
-				cur++;
-				if (isdigit(*cur))
-					bg[0] = *cur++;
-				if (isdigit(*cur))
-					bg[1] = *cur++;
-			}
-			if (font) {
-				decoded = g_string_append(decoded, "</FONT>");
-				font = FALSE;
-			}
-
-			if (fg[0]) {
-				fgnum = atoi(fg);
-				if (fgnum < 0 || fgnum > 15)
-					continue;
-				font = TRUE;
-				g_string_append_printf(decoded, "<FONT COLOR=\"%s\"", irc_mirc_colors[fgnum]);
-				if (bg[0]) {
-					bgnum = atoi(bg);
-					if (bgnum >= 0 && bgnum < 16)
-						g_string_append_printf(decoded, " BACK=\"%s\"", irc_mirc_colors[bgnum]);
-				}
-				decoded = g_string_append_c(decoded, '>');
-			}
-			break;
-		case '\011':
-			cur++;
-			if (!italic) {
-				decoded = g_string_append(decoded, "<I>");
-				italic = TRUE;
-			} else {
-				decoded = g_string_append(decoded, "</I>");
-				italic = FALSE;
-			}
-			break;
-		case '\037':
-			cur++;
-			if (!underline) {
-				decoded = g_string_append(decoded, "<U>");
-				underline = TRUE;
-			} else {
-				decoded = g_string_append(decoded, "</U>");
-				underline = FALSE;
-			}
-			break;
-		case '\007':
-		case '\026':
-			cur++;
-			break;
-		case '\017':
-			cur++;
-			/* fallthrough */
-		case '\000':
-			if (bold)
-				decoded = g_string_append(decoded, "</B>");
-			if (italic)
-				decoded = g_string_append(decoded, "</I>");
-			if (underline)
-				decoded = g_string_append(decoded, "</U>");
-			if (font)
-				decoded = g_string_append(decoded, "</FONT>");
-			bold = italic = underline = font = FALSE;
-			break;
-		default:
-			purple_debug_error("irc", "Unexpected mIRC formatting character %d", *cur);
-		}
-	} while (*cur);
-
-	return g_string_free(decoded, FALSE);
-}
-
-char *irc_mirc2txt (const char *string)
-{
-	char *result;
-	int i, j;
-
-	if (string == NULL)
-		return NULL;
-
-	result = g_strdup (string);
-
-	for (i = 0, j = 0; result[i]; i++) {
-		switch (result[i]) {
-		case '\002':
-		case '\003':
-			/* Foreground color */
-			if (isdigit(result[i + 1]))
-				i++;
-			if (isdigit(result[i + 1]))
-				i++;
-			/* Optional comma and background color */
-			if (result[i + 1] == ',') {
-				i++;
-				if (isdigit(result[i + 1]))
-					i++;
-				if (isdigit(result[i + 1]))
-					i++;
-			}
-			/* Note that i still points to the last character
-			 * of the color selection string. */
-			continue;
-		case '\007':
-		case '\017':
-		case '\026':
-		case '\037':
-			continue;
-		default:
-			result[j++] = result[i];
-		}
-	}
-	result[j] = '\0';
-	return result;
-}
-
-const char *irc_nick_skip_mode(struct irc_conn *irc, const char *nick)
-{
-	static const char *default_modes = "@+%&";
-	const char *mode_chars;
-
-	mode_chars = irc->mode_chars ? irc->mode_chars : default_modes;
-
-	while (*nick && strchr(mode_chars, *nick) != NULL)
-		nick++;
-
-	return nick;
-}
-
-gboolean irc_ischannel(const char *string)
-{
-	return (string[0] == '#' || string[0] == '&');
-}
-
-char *irc_parse_ctcp(struct irc_conn *irc, const char *from, const char *to, const char *msg, int notice)
-{
-	PurpleConnection *gc;
-	const char *cur = msg + 1;
-	char *buf, *ctcp;
-
-	/* Note that this is NOT correct w.r.t. multiple CTCPs in one
-	 * message and low-level quoting ... but if you want that crap,
-	 * use a real IRC client. */
-
-	if (msg[0] != '\001' || msg[1] == '\0' || msg[strlen(msg) - 1] != '\001')
-		return g_strdup(msg);
-
-	if (!strncmp(cur, "ACTION ", 7)) {
-		cur += 7;
-		buf = g_strdup_printf("/me %s", cur);
-		buf[strlen(buf) - 1] = '\0';
-		return buf;
-	} else if (!strncmp(cur, "PING ", 5)) {
-		if (notice) { /* reply */
-			gint64 timestamp;
-			gc = purple_account_get_connection(irc->account);
-			if (!gc)
-				return NULL;
-			if (sscanf(cur, "PING %" G_GINT64_FORMAT, &timestamp) == 1) {
-				buf = g_strdup_printf(_("Reply time from %s: %f seconds"), from,
-				                      (g_get_monotonic_time() - timestamp) /
-				                              (gdouble)G_USEC_PER_SEC);
-				purple_notify_info(gc, _("PONG"),
-					_("CTCP PING reply"), buf,
-					purple_request_cpar_from_connection(gc));
-				g_free(buf);
-			} else {
-				purple_debug_error("irc", "Unable to parse PING timestamp");
-			}
-			return NULL;
-		} else {
-			buf = irc_format(irc, "vt:", "NOTICE", from, msg);
-			irc_send(irc, buf);
-			g_free(buf);
-		}
-	} else if (!strncmp(cur, "VERSION", 7) && !notice) {
-		buf = irc_format(irc, "vt:", "NOTICE", from, "\001VERSION Purple IRC\001");
-		irc_send(irc, buf);
-		g_free(buf);
-	} else if (!strncmp(cur, "DCC SEND ", 9)) {
-		irc_dccsend_recv(irc, from, msg + 10);
-		return NULL;
-	}
-
-	ctcp = g_strdup(msg + 1);
-	ctcp[strlen(ctcp) - 1] = '\0';
-	buf = g_strdup_printf("Received CTCP '%s' (to %s) from %s", ctcp, to, from);
-	g_free(ctcp);
-	return buf;
-}
-
-void irc_msg_table_build(struct irc_conn *irc)
-{
-	int i;
-
-	if (!irc || !irc->msgs) {
-		purple_debug_error("irc", "Attempt to build a message table on a bogus structure");
-		return;
-	}
-
-	for (i = 0; _irc_msgs[i].name; i++) {
-		g_hash_table_insert(irc->msgs, (gpointer)_irc_msgs[i].name, (gpointer)&_irc_msgs[i]);
-	}
-}
-
-void irc_cmd_table_build(struct irc_conn *irc)
-{
-	int i;
-
-	if (!irc || !irc->cmds) {
-		purple_debug_error("irc", "Attempt to build a command table on a bogus structure");
-		return;
-	}
-
-	for (i = 0; _irc_cmds[i].name ; i++) {
-		g_hash_table_insert(irc->cmds, (gpointer)_irc_cmds[i].name, (gpointer)&_irc_cmds[i]);
-	}
-}
-
-char *
-irc_format(G_GNUC_UNUSED struct irc_conn *irc, const char *format, ...)
-{
-	GString *string = g_string_new("");
-	char *tok, *tmp;
-	const char *cur;
-	va_list ap;
-
-	va_start(ap, format);
-	for (cur = format; *cur; cur++) {
-		if (cur != format)
-			g_string_append_c(string, ' ');
-
-		tok = va_arg(ap, char *);
-		switch (*cur) {
-		case 'v':
-			g_string_append(string, tok);
-			break;
-		case ':':
-			g_string_append_c(string, ':');
-			G_GNUC_FALLTHROUGH;
-		case 't':
-		case 'n':
-		case 'c':
-			tmp = irc_send_convert(irc, tok);
-			g_string_append(string, tmp ? tmp : tok);
-			g_free(tmp);
-			break;
-		default:
-			purple_debug_error("irc", "Invalid format character '%c'", *cur);
-			break;
-		}
-	}
-	va_end(ap);
-	g_string_append(string, "\r\n");
-	return (g_string_free(string, FALSE));
-}
-
-void irc_parse_msg(struct irc_conn *irc, char *input)
-{
-	struct _irc_msg *msgent;
-	char *cur, *end, *tmp, *from, *msgname, *fmt, **args, *msg;
-	guint i;
-	PurpleConnection *gc = purple_account_get_connection(irc->account);
-	gboolean fmt_valid;
-	int args_cnt;
-
-	irc->recv_time = time(NULL);
-
-	/*
-	 * The data passed to irc-receiving-text is the raw protocol data.
-	 * TODO: It should be passed as an array of bytes and a length
-	 * instead of a null terminated string.
-	 */
-	purple_signal_emit(_irc_protocol, "irc-receiving-text", gc, &input);
-
-	if (purple_debug_is_verbose()) {
-		char *clean = g_utf8_make_valid(input, -1);
-		clean = g_strstrip(clean);
-		purple_debug_misc("irc", ">> %s\n", clean);
-		g_free(clean);
-	}
-
-	if (!strncmp(input, "PING ", 5)) {
-		msg = irc_format(irc, "vv", "PONG", input + 5);
-		irc_send(irc, msg);
-		g_free(msg);
-		return;
-	} else if (!strncmp(input, "ERROR ", 6)) {
-		GError *error = NULL;
-		if (g_utf8_validate(input, -1, NULL)) {
-			error = g_error_new(
-				PURPLE_CONNECTION_ERROR,
-				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-				"%s\n%s", _("Disconnected."), input);
-		} else {
-			error = g_error_new_literal(
-				PURPLE_CONNECTION_ERROR,
-				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-				_("Disconnected."));
-		}
-		purple_connection_take_error(gc, error);
-		return;
-	} else if (!strncmp(input, "AUTHENTICATE ", 13)) {
-		irc_msg_auth(irc, input + 13);
-		return;
-	}
-
-	if (input[0] != ':' || (cur = strchr(input, ' ')) == NULL) {
-		irc_parse_error_cb(irc, input);
-		return;
-	}
-
-	from = g_strndup(&input[1], cur - &input[1]);
-	cur++;
-	end = strchr(cur, ' ');
-	if (!end)
-		end = cur + strlen(cur);
-
-	tmp = g_strndup(cur, end - cur);
-	msgname = g_ascii_strdown(tmp, -1);
-	g_free(tmp);
-
-	if ((msgent = g_hash_table_lookup(irc->msgs, msgname)) == NULL) {
-		irc_msg_default(irc, "", from, &input);
-		g_free(msgname);
-		g_free(from);
-		return;
-	}
-	g_free(msgname);
-
-	fmt_valid = TRUE;
-	args = g_new0(char *, strlen(msgent->format));
-	args_cnt = 0;
-	for (cur = end, fmt = msgent->format, i = 0; fmt[i] && *cur++; i++) {
-		switch (fmt[i]) {
-		case 'v':
-			if (!(end = strchr(cur, ' '))) end = cur + strlen(cur);
-			/* This is a string of unknown encoding which we do not
-			 * want to transcode, but it may or may not be valid
-			 * UTF-8, so we'll salvage it.  If a nick/channel/target
-			 * field has inadvertently been marked verbatim, this
-			 * could cause weirdness. */
-			tmp = g_strndup(cur, end - cur);
-			args[i] = g_utf8_make_valid(tmp, -1);
-			g_free(tmp);
-			cur += end - cur;
-			break;
-		case 't':
-		case 'n':
-		case 'c':
-			if (!(end = strchr(cur, ' '))) end = cur + strlen(cur);
-			tmp = g_strndup(cur, end - cur);
-			args[i] = irc_recv_convert(irc, tmp);
-			g_free(tmp);
-			cur += end - cur;
-			break;
-		case ':':
-			if (*cur == ':') cur++;
-			args[i] = irc_recv_convert(irc, cur);
-			cur = cur + strlen(cur);
-			break;
-		case '*':
-			/* Ditto 'v' above; we're going to salvage this in case
-			 * it leaks past the IRC protocol */
-			args[i] = g_utf8_make_valid(cur, -1);
-			cur = cur + strlen(cur);
-			break;
-		default:
-			purple_debug_error("irc", "invalid message format character '%c'", fmt[i]);
-			fmt_valid = FALSE;
-			break;
-		}
-		if (fmt_valid)
-			args_cnt = i + 1;
-	}
-	if (G_UNLIKELY(!fmt_valid)) {
-		purple_debug_error("irc", "message format was invalid");
-	} else if (G_LIKELY(args_cnt >= msgent->req_cnt)) {
-		tmp = irc_recv_convert(irc, from);
-		(msgent->cb)(irc, msgent->name, tmp, args);
-		g_free(tmp);
-	} else {
-		purple_debug_error("irc", "args count (%d) doesn't reach "
-			"expected value of %d for the '%s' command",
-			args_cnt, msgent->req_cnt, msgent->name);
-	}
-	for (i = 0; i < strlen(msgent->format); i++) {
-		g_free(args[i]);
-	}
-	g_free(args);
-	g_free(from);
-}
-
-static void
-irc_parse_error_cb(G_GNUC_UNUSED struct irc_conn *irc, char *input)
-{
-	char *clean;
-	/* This really should be escaped somehow that you can tell what
-	 * the junk was -- but as it is, it can crash glib. */
-	clean = g_utf8_make_valid(input, -1);
-	purple_debug_warning("irc", "Unrecognized string: %s", clean);
-	g_free(clean);
-}
diff --git a/libpurple/protocols/irc/resources/icons/16x16/apps/im-irc.png b/libpurple/protocols/irc/resources/icons/16x16/apps/im-irc.png
deleted file mode 100644
index 2d22c75a0412a3090ad9fc82600e1fdf07aa6bcf..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/libpurple/protocols/irc/resources/icons/16x16/apps/scalable/im-irc.svg b/libpurple/protocols/irc/resources/icons/16x16/apps/scalable/im-irc.svg
deleted file mode 100644
--- a/libpurple/protocols/irc/resources/icons/16x16/apps/scalable/im-irc.svg
+++ /dev/null
@@ -1,222 +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="svg4345"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   sodipodi:docbase="/home/hbons/Desktop"
-   sodipodi:docname="irc.svg"
-   inkscape:export-filename="/home/hbons/Bureaublad/irc.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90"
-   version="1.0"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
-  <defs
-     id="defs4347">
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient8648">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop8650" />
-      <stop
-         style="stop-color:#729fcf;stop-opacity:1"
-         offset="1"
-         id="stop8652" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient8632">
-      <stop
-         style="stop-color:#729fcf;stop-opacity:1"
-         offset="0"
-         id="stop8634" />
-      <stop
-         style="stop-color:#386ca5;stop-opacity:1"
-         offset="1"
-         id="stop8636" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient5235">
-      <stop
-         style="stop-color:#2e3436;stop-opacity:1;"
-         offset="0"
-         id="stop5237" />
-      <stop
-         style="stop-color:#2e3436;stop-opacity:0;"
-         offset="1"
-         id="stop5239" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3816">
-      <stop
-         style="stop-color:#000000;stop-opacity:1;"
-         offset="0"
-         id="stop3818" />
-      <stop
-         style="stop-color:#000000;stop-opacity:0;"
-         offset="1"
-         id="stop3820" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3816"
-       id="radialGradient4179"
-       gradientUnits="userSpaceOnUse"
-       cx="31.112698"
-       cy="19.008621"
-       fx="31.112698"
-       fy="19.008621"
-       r="8.6620579" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient5235"
-       id="radialGradient5241"
-       cx="23.234518"
-       cy="40.688972"
-       fx="23.234518"
-       fy="40.688972"
-       r="16.956987"
-       gradientTransform="matrix(1,0,0,0.133183,0,35.2699)"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient8632"
-       id="linearGradient8638"
-       x1="12.031081"
-       y1="3.9636562"
-       x2="14.700418"
-       y2="10.228306"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient8648"
-       id="linearGradient8654"
-       x1="11.198016"
-       y1="1.0312058"
-       x2="11.198016"
-       y2="14.496081"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient8648"
-       id="linearGradient8660"
-       gradientUnits="userSpaceOnUse"
-       x1="11.198016"
-       y1="1.1643296"
-       x2="11.198016"
-       y2="14.496081"
-       gradientTransform="matrix(-1,0,0,1,16.00001,5)" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient8632"
-       id="linearGradient8662"
-       gradientUnits="userSpaceOnUse"
-       x1="9.7651443"
-       y1="4.0303011"
-       x2="9.0022526"
-       y2="9.9950476"
-       gradientTransform="matrix(-1,0,0,1,16.00001,5)" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="15.004829"
-     inkscape:cx="21.840023"
-     inkscape:cy="16.645163"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     inkscape:grid-bbox="true"
-     inkscape:document-units="px"
-     inkscape:window-width="1440"
-     inkscape:window-height="847"
-     inkscape:window-x="0"
-     inkscape:window-y="0"
-     width="16px"
-     height="16px"
-     inkscape:snap-bbox="true"
-     inkscape:snap-nodes="false"
-     objecttolerance="10"
-     gridtolerance="10"
-     showguides="true"
-     inkscape:guide-bbox="true">
-    <inkscape:grid
-       type="xygrid"
-       id="grid7860"
-       visible="true"
-       enabled="true" />
-  </sodipodi:namedview>
-  <metadata
-     id="metadata4350">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     id="layer1"
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer">
-    <path
-       style="opacity:0.66000000000000003;fill:url(#linearGradient8654);fill-opacity:1;stroke:url(#linearGradient8638);stroke-width:0.99999928000000005;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 14.875001,0.49999963 C 15.217688,0.49999963 15.5,0.74481173 15.5,1.049489 L 15.5,3.7114598 L 15.5,4.7860168 L 15.5,7.9687565 C 15.5,8.2734337 15.217688,8.5182463 14.875001,8.5182459 L 13.523824,8.5182459 C 13.523824,8.5182459 13.500261,10.537057 13.500261,10.537057 C 12.189929,10.537057 10.901093,8.5069021 10.901093,8.5069021 L 6.1250097,8.5182459 C 5.7823233,8.5182459 5.5000104,8.2734333 5.5000104,7.9687565 L 5.5000104,4.7860168 L 5.5000104,3.7114598 L 5.5000104,1.049489 C 5.5000104,0.74481189 5.7823228,0.49999967 6.1250097,0.49999963 L 8.8380752,0.49999963 L 12.375003,0.49999963 L 14.875001,0.49999963 z"
-       id="path5540"
-       sodipodi:nodetypes="cccccccccccccccccc" />
-    <path
-       style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999892999999995;stroke-miterlimit:4;stroke-opacity:1;opacity:0.66"
-       d="M 14.326096,1.4999995 C 14.416734,1.4999995 14.500009,1.5636953 14.500009,1.6546223 L 14.500009,3.9018072 L 14.500009,4.8089277 L 14.500009,7.35505 C 14.500009,7.4459764 14.416733,7.5096728 14.326096,7.5096728 L 12.610239,7.5206242 C 12.405479,7.52273 12.449632,8.6309999 12.449632,8.6309999 L 11.44851,7.4434005 L 6.6739127,7.5096728 C 6.5832743,7.5096728 6.4999995,7.4459761 6.4999995,7.35505 L 6.4999995,4.8089277 L 6.4999995,3.9018072 L 6.4999995,1.6546223 C 6.4999995,1.5636954 6.5832739,1.4999995 6.6739127,1.4999995 L 9.0465863,1.4999995 L 12.139758,1.4999995 L 14.326096,1.4999995 z"
-       id="path5542"
-       sodipodi:nodetypes="cccccccccccccccccc" />
-    <path
-       sodipodi:type="arc"
-       style="opacity:0.52838428;fill:url(#radialGradient5241);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path4340"
-       sodipodi:cx="23.234518"
-       sodipodi:cy="40.688972"
-       sodipodi:rx="16.956987"
-       sodipodi:ry="2.2583797"
-       d="M 40.191505 40.688972 A 16.956987 2.2583797 0 1 1  6.2775307,40.688972 A 16.956987 2.2583797 0 1 1  40.191505 40.688972 z"
-       transform="matrix(1.208941,0,0,1.980928,-1.589159,5.924394)" />
-    <path
-       transform="matrix(2.539812,0,0,0.410815,-57.0204,65.80212)"
-       sodipodi:type="arc"
-       style="opacity:1;color:black;fill:url(#radialGradient4179);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       id="path4306"
-       sodipodi:cx="31.112698"
-       sodipodi:cy="19.008621"
-       sodipodi:rx="8.6620579"
-       sodipodi:ry="8.6620579"
-       d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1  22.45064,19.008621 A 8.6620579 8.6620579 0 1 1  39.774755 19.008621 z" />
-    <path
-       style="opacity:1;fill:url(#linearGradient8660);fill-opacity:1;stroke:url(#linearGradient8662);stroke-width:0.99999928000000005;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 1.125011,5.4999996 C 0.78232384,5.4999996 0.50001184,5.7448117 0.50001184,6.049489 L 0.50001184,8.7114598 L 0.50001184,9.7860168 L 0.50001184,12.968757 C 0.50001184,13.273434 0.78232384,13.518247 1.125011,13.518246 L 2.476188,13.518246 C 2.476188,13.518246 2.499751,15.631308 2.499751,15.631308 C 3.810083,15.631308 5.0989186,13.506902 5.0989186,13.506902 L 9.8750026,13.518246 C 10.217687,13.518246 10.5,13.273434 10.5,12.968757 L 10.5,9.7860168 L 10.5,8.7114598 L 10.5,6.049489 C 10.5,5.7448118 10.217688,5.4999996 9.8750026,5.4999996 L 7.1619366,5.4999996 L 3.625009,5.4999996 L 1.125011,5.4999996 z"
-       id="path8656"
-       sodipodi:nodetypes="cccccccccccccccccc" />
-    <path
-       style="opacity:0.375;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999893;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 1.673916,6.4999995 C 1.583278,6.4999995 1.500003,6.5636953 1.500003,6.6546223 L 1.500003,8.9018072 L 1.500003,9.8089277 L 1.500003,12.35505 C 1.500003,12.445977 1.583279,12.509673 1.673916,12.509673 L 3.389773,12.520625 C 3.594533,12.52273 3.5714046,13.578902 3.5032546,14.008003 L 4.551502,12.443401 L 9.3260996,12.509673 C 9.4167376,12.509673 9.5000126,12.445976 9.5000126,12.35505 L 9.5000126,9.8089277 L 9.5000126,8.9018072 L 9.5000126,6.6546223 C 9.5000126,6.5636954 9.4167376,6.4999995 9.3260996,6.4999995 L 6.9534256,6.4999995 L 3.860254,6.4999995 L 1.673916,6.4999995 z"
-       id="path8658"
-       sodipodi:nodetypes="cccccccccccccccccc" />
-  </g>
-</svg>
diff --git a/libpurple/protocols/irc/resources/icons/22x22/apps/im-irc.png b/libpurple/protocols/irc/resources/icons/22x22/apps/im-irc.png
deleted file mode 100644
index 4fa09abe9cd2942067b3989641393550d672e416..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/libpurple/protocols/irc/resources/icons/22x22/apps/scalable/im-irc.svg b/libpurple/protocols/irc/resources/icons/22x22/apps/scalable/im-irc.svg
deleted file mode 100644
--- a/libpurple/protocols/irc/resources/icons/22x22/apps/scalable/im-irc.svg
+++ /dev/null
@@ -1,237 +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="svg4345"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   sodipodi:docbase="/home/hbons/Desktop"
-   sodipodi:docname="irc.svg"
-   inkscape:export-filename="/home/hbons/Desktop/pidgin.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90"
-   version="1.0"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
-  <defs
-     id="defs4347">
-    <linearGradient
-       id="linearGradient2804">
-      <stop
-         style="stop-color:black;stop-opacity:0;"
-         offset="0"
-         id="stop2806" />
-      <stop
-         id="stop2812"
-         offset="0.5"
-         style="stop-color:black;stop-opacity:1;" />
-      <stop
-         style="stop-color:black;stop-opacity:0;"
-         offset="1"
-         id="stop2808" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2804"
-       id="linearGradient1516"
-       gradientUnits="userSpaceOnUse"
-       x1="21.875"
-       y1="48.000977"
-       x2="21.875"
-       y2="40" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2781"
-       id="radialGradient1514"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(2,0,0,0.8,36,8.8)"
-       cx="1"
-       cy="44"
-       fx="1"
-       fy="44"
-       r="5" />
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2781">
-      <stop
-         style="stop-color:black;stop-opacity:1;"
-         offset="0"
-         id="stop2783" />
-      <stop
-         style="stop-color:black;stop-opacity:0;"
-         offset="1"
-         id="stop2785" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2781"
-       id="radialGradient1512"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(2,0,0,0.8,-13,-79.2)"
-       cx="1"
-       cy="44"
-       fx="1"
-       fy="44"
-       r="5" />
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient5235">
-      <stop
-         style="stop-color:#2e3436;stop-opacity:1;"
-         offset="0"
-         id="stop5237" />
-      <stop
-         style="stop-color:#2e3436;stop-opacity:0;"
-         offset="1"
-         id="stop5239" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3816">
-      <stop
-         style="stop-color:#000000;stop-opacity:1;"
-         offset="0"
-         id="stop3818" />
-      <stop
-         style="stop-color:#000000;stop-opacity:0;"
-         offset="1"
-         id="stop3820" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3816"
-       id="radialGradient4179"
-       gradientUnits="userSpaceOnUse"
-       cx="31.112698"
-       cy="19.008621"
-       fx="31.112698"
-       fy="19.008621"
-       r="8.6620579" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient5235"
-       id="radialGradient5241"
-       cx="23.234518"
-       cy="40.688972"
-       fx="23.234518"
-       fy="40.688972"
-       r="16.956987"
-       gradientTransform="matrix(1,0,0,0.133183,0,35.2699)"
-       gradientUnits="userSpaceOnUse" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="28"
-     inkscape:cx="17.768242"
-     inkscape:cy="11.945133"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     inkscape:grid-bbox="true"
-     inkscape:document-units="px"
-     inkscape:window-width="1274"
-     inkscape:window-height="966"
-     inkscape:window-x="3"
-     inkscape:window-y="25"
-     width="24px"
-     height="24px" />
-  <metadata
-     id="metadata4350">
-    <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">
-    <g
-       id="g1504"
-       style="opacity:0.12663754"
-       transform="matrix(0.496192,0,0,0.581846,-0.128303,-4.772994)">
-      <rect
-         transform="scale(-1,-1)"
-         y="-48"
-         x="-11"
-         height="8"
-         width="10"
-         id="rect1506"
-         style="opacity:1;color:black;fill:url(#radialGradient1512);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         y="40"
-         x="38"
-         height="8"
-         width="10"
-         id="rect1508"
-         style="opacity:1;color:black;fill:url(#radialGradient1514);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         y="40"
-         x="11"
-         height="8"
-         width="27"
-         id="rect1510"
-         style="opacity:1;color:black;fill:url(#linearGradient1516);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-    </g>
-    <path
-       sodipodi:type="arc"
-       style="opacity:0.52838428;fill:url(#radialGradient5241);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path4340"
-       sodipodi:cx="23.234518"
-       sodipodi:cy="40.688972"
-       sodipodi:rx="16.956987"
-       sodipodi:ry="2.2583797"
-       d="M 40.191505 40.688972 A 16.956987 2.2583797 0 1 1  6.2775307,40.688972 A 16.956987 2.2583797 0 1 1  40.191505 40.688972 z"
-       transform="matrix(1.208941,0,0,1.980928,-0.589159,7.924396)" />
-    <path
-       style="opacity:1;fill:#efefef;fill-opacity:1;stroke:#787878;stroke-width:1.69608581;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 2.875,7.5 C 2.1210885,7.5 1.5,8.1265217 1.5,8.90625 L 1.5,15.71875 L 1.5,18.46875 L 1.5,26.613999 C 1.5,27.393727 2.1210885,28.02025 2.875,28.020249 L 4.9145119,28.020249 L 4.9145119,30.532781 L 8.1141033,27.991218 L 22.125,28.020249 C 22.878911,28.020249 23.5,27.393726 23.5,26.613999 L 23.5,18.46875 L 23.5,15.71875 L 23.5,8.90625 C 23.5,8.1265221 22.878912,7.5000001 22.125,7.5 L 16.15625,7.5 L 8.375,7.5 L 2.875,7.5 z "
-       id="path4334"
-       transform="matrix(-0.590909,0,0,0.588279,23.38636,-1.912091)"
-       sodipodi:nodetypes="cccccccccccccccccc" />
-    <path
-       transform="matrix(-0.546584,0,0,0.546584,22.8323,-1.111803)"
-       style="fill:none;fill-opacity:1;stroke:white;stroke-width:1.82954407;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 2.875,8.4375 C 2.6469872,8.4375 2.4375,8.6305983 2.4375,8.90625 L 2.4375,15.71875 L 2.4375,18.46875 L 2.4375,26.1875 C 2.4375,26.46315 2.6469898,26.65625 2.875,26.65625 L 5.0575572,26.65625 C 5.5726565,26.662634 5.9886729,27.078651 5.9950572,27.59375 L 7.0909095,26.8125 C 7.2621189,26.685027 8.9741324,26.618972 9.1875,26.625 L 22.125,26.65625 C 22.353012,26.65625 22.5625,26.463149 22.5625,26.1875 L 22.5625,18.46875 L 22.5625,15.71875 L 22.5625,8.90625 C 22.5625,8.6305986 22.353013,8.4375 22.125,8.4375 L 16.15625,8.4375 L 8.375,8.4375 L 2.875,8.4375 z "
-       id="path4336"
-       sodipodi:nodetypes="ccccccccccccccccccc" />
-    <path
-       transform="matrix(2.539812,0,0,0.410815,-56.0204,67.80212)"
-       sodipodi:type="arc"
-       style="opacity:1;color:black;fill:url(#radialGradient4179);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       id="path4306"
-       sodipodi:cx="31.112698"
-       sodipodi:cy="19.008621"
-       sodipodi:rx="8.6620579"
-       sodipodi:ry="8.6620579"
-       d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1  22.45064,19.008621 A 8.6620579 8.6620579 0 1 1  39.774755 19.008621 z" />
-    <path
-       style="opacity:1;fill:#efefef;fill-opacity:1;stroke:#787878;stroke-width:1.69608581;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 2.875,7.5 C 2.1210885,7.5 1.5,8.1265217 1.5,8.90625 L 1.5,15.71875 L 1.5,18.46875 L 1.5,26.613999 C 1.5,27.393727 2.1210885,28.02025 2.875,28.020249 L 4.9145119,28.020249 L 4.9145119,30.532781 L 8.1141033,27.991218 L 22.125,28.020249 C 22.878911,28.020249 23.5,27.393726 23.5,26.613999 L 23.5,18.46875 L 23.5,15.71875 L 23.5,8.90625 C 23.5,8.1265221 22.878912,7.5000001 22.125,7.5 L 16.15625,7.5 L 8.375,7.5 L 2.875,7.5 z "
-       id="path5534"
-       transform="matrix(0.590909,0,0,0.588279,0.613639,3.087907)"
-       sodipodi:nodetypes="cccccccccccccccccc" />
-    <path
-       transform="matrix(0.546584,0,0,0.546584,1.167699,3.888195)"
-       style="fill:none;fill-opacity:1;stroke:white;stroke-width:1.82954407;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 2.875,8.4375 C 2.6469872,8.4375 2.4375,8.6305983 2.4375,8.90625 L 2.4375,15.71875 L 2.4375,18.46875 L 2.4375,26.1875 C 2.4375,26.46315 2.6469898,26.65625 2.875,26.65625 L 5.0575572,26.65625 C 5.5726565,26.662634 5.9886729,27.078651 5.9950572,27.59375 L 7.0909095,26.8125 C 7.2621189,26.685027 8.9741324,26.618972 9.1875,26.625 L 22.125,26.65625 C 22.353012,26.65625 22.5625,26.463149 22.5625,26.1875 L 22.5625,18.46875 L 22.5625,15.71875 L 22.5625,8.90625 C 22.5625,8.6305986 22.353013,8.4375 22.125,8.4375 L 16.15625,8.4375 L 8.375,8.4375 L 2.875,8.4375 z "
-       id="path5536"
-       sodipodi:nodetypes="ccccccccccccccccccc" />
-  </g>
-</svg>
diff --git a/libpurple/protocols/irc/resources/icons/48x48/apps/im-irc.png b/libpurple/protocols/irc/resources/icons/48x48/apps/im-irc.png
deleted file mode 100644
index 606425fabb7aa1d5e9e490ad5d74bc55c4c94262..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/libpurple/protocols/irc/resources/icons/scalable/apps/im-irc.svg b/libpurple/protocols/irc/resources/icons/scalable/apps/im-irc.svg
deleted file mode 100644
--- a/libpurple/protocols/irc/resources/icons/scalable/apps/im-irc.svg
+++ /dev/null
@@ -1,238 +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="svg4345"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   sodipodi:docbase="/home/hbons/Desktop"
-   sodipodi:docname="irc.svg"
-   inkscape:export-filename="/home/hbons/Desktop/pidgin.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
-  <defs
-     id="defs4347">
-    <linearGradient
-       id="linearGradient2804">
-      <stop
-         style="stop-color:black;stop-opacity:0;"
-         offset="0"
-         id="stop2806" />
-      <stop
-         id="stop2812"
-         offset="0.5"
-         style="stop-color:black;stop-opacity:1;" />
-      <stop
-         style="stop-color:black;stop-opacity:0;"
-         offset="1"
-         id="stop2808" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2804"
-       id="linearGradient1516"
-       gradientUnits="userSpaceOnUse"
-       x1="21.875"
-       y1="48.000977"
-       x2="21.875"
-       y2="40" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2781"
-       id="radialGradient1514"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(2,0,0,0.8,36,8.8)"
-       cx="1"
-       cy="44"
-       fx="1"
-       fy="44"
-       r="5" />
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2781">
-      <stop
-         style="stop-color:black;stop-opacity:1;"
-         offset="0"
-         id="stop2783" />
-      <stop
-         style="stop-color:black;stop-opacity:0;"
-         offset="1"
-         id="stop2785" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2781"
-       id="radialGradient1512"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(2,0,0,0.8,-13,-79.2)"
-       cx="1"
-       cy="44"
-       fx="1"
-       fy="44"
-       r="5" />
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient5235">
-      <stop
-         style="stop-color:#2e3436;stop-opacity:1;"
-         offset="0"
-         id="stop5237" />
-      <stop
-         style="stop-color:#2e3436;stop-opacity:0;"
-         offset="1"
-         id="stop5239" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3816">
-      <stop
-         style="stop-color:#000000;stop-opacity:1;"
-         offset="0"
-         id="stop3818" />
-      <stop
-         style="stop-color:#000000;stop-opacity:0;"
-         offset="1"
-         id="stop3820" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3816"
-       id="radialGradient4179"
-       gradientUnits="userSpaceOnUse"
-       cx="31.112698"
-       cy="19.008621"
-       fx="31.112698"
-       fy="19.008621"
-       r="8.6620579" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient5235"
-       id="radialGradient5241"
-       cx="23.234518"
-       cy="40.688972"
-       fx="23.234518"
-       fy="40.688972"
-       r="16.956987"
-       gradientTransform="matrix(1,0,0,0.133183,0,35.2699)"
-       gradientUnits="userSpaceOnUse" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="13.062462"
-     inkscape:cx="40.814762"
-     inkscape:cy="25.717712"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     inkscape:grid-bbox="true"
-     inkscape:document-units="px"
-     inkscape:window-width="1274"
-     inkscape:window-height="966"
-     inkscape:window-x="3"
-     inkscape:window-y="25" />
-  <metadata
-     id="metadata4350">
-    <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">
-    <g
-       id="g1504"
-       style="opacity:0.12663754"
-       transform="matrix(0.851064,0,0,0.999995,3.148928,-3.9998)">
-      <rect
-         transform="scale(-1,-1)"
-         y="-48"
-         x="-11"
-         height="8"
-         width="10"
-         id="rect1506"
-         style="opacity:1;color:black;fill:url(#radialGradient1512);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         y="40"
-         x="38"
-         height="8"
-         width="10"
-         id="rect1508"
-         style="opacity:1;color:black;fill:url(#radialGradient1514);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         y="40"
-         x="11"
-         height="8"
-         width="27"
-         id="rect1510"
-         style="opacity:1;color:black;fill:url(#linearGradient1516);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-    </g>
-    <path
-       sodipodi:type="arc"
-       style="opacity:0.52838428;fill:url(#radialGradient5241);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path4340"
-       sodipodi:cx="23.234518"
-       sodipodi:cy="40.688972"
-       sodipodi:rx="16.956987"
-       sodipodi:ry="2.2583797"
-       d="M 40.191505 40.688972 A 16.956987 2.2583797 0 1 1  6.2775307,40.688972 A 16.956987 2.2583797 0 1 1  40.191505 40.688972 z"
-       transform="matrix(1.208941,0,0,1.980928,3.410841,15.87176)" />
-    <path
-       style="opacity:1;fill:#efefef;fill-opacity:1;stroke:#787878;stroke-width:0.95516169;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 2.875,7.5 C 2.1210885,7.5 1.5,8.1265217 1.5,8.90625 L 1.5,15.71875 L 1.5,18.46875 L 1.5,26.189031 C 1.5,26.968759 2.1210885,27.595282 2.875,27.595281 L 5.5,27.595281 L 5.5,30.532781 L 9.2020155,27.56625 L 22.125,27.595281 C 22.878911,27.595281 23.5,26.968758 23.5,26.189031 L 23.5,18.46875 L 23.5,15.71875 L 23.5,8.90625 C 23.5,8.1265221 22.878912,7.5000001 22.125,7.5 L 16.15625,7.5 L 8.375,7.5 L 2.875,7.5 z "
-       id="path4334"
-       transform="matrix(-1.045455,0,0,1.048433,44.0682,0.636752)"
-       sodipodi:nodetypes="cccccccccccccccccc" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.94924349"
-       inkscape:original="M 2.875 7.5 C 2.1210885 7.5 1.5 8.1265217 1.5 8.90625 L 1.5 15.71875 L 1.5 18.46875 L 1.5 26.1875 C 1.5 26.967227 2.1210885 27.593751 2.875 27.59375 L 5.5 27.59375 L 5.5 30.53125 L 9.1875 27.5625 L 22.125 27.59375 C 22.878911 27.593749 23.5 26.967227 23.5 26.1875 L 23.5 18.46875 L 23.5 15.71875 L 23.5 8.90625 C 23.5 8.1265221 22.878912 7.5000001 22.125 7.5 L 16.15625 7.5 L 8.375 7.5 L 2.875 7.5 z "
-       style="opacity:1;fill:none;fill-opacity:1;stroke:white;stroke-width:0.95516169;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path4336"
-       d="M 2.875,8.4375 C 2.6469872,8.4375 2.4375,8.6305983 2.4375,8.90625 L 2.4375,15.71875 L 2.4375,18.46875 L 2.4375,26.1875 C 2.4375,26.46315 2.6469898,26.65625 2.875,26.65625 L 5.5,26.65625 C 6.0150993,26.662634 6.4311157,27.078651 6.4375,27.59375 L 6.4375,28.5625 L 8.59375,26.8125 C 8.7649594,26.685027 8.9741324,26.618972 9.1875,26.625 L 22.125,26.65625 C 22.353012,26.65625 22.5625,26.463149 22.5625,26.1875 L 22.5625,18.46875 L 22.5625,15.71875 L 22.5625,8.90625 C 22.5625,8.6305986 22.353013,8.4375 22.125,8.4375 L 16.15625,8.4375 L 8.375,8.4375 L 2.875,8.4375 z "
-       transform="matrix(-1.045455,0,0,1.048433,44.0682,0.636752)" />
-    <path
-       transform="matrix(2.539812,0,0,0.410815,-52.0204,75.74948)"
-       sodipodi:type="arc"
-       style="opacity:1;color:black;fill:url(#radialGradient4179);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       id="path4306"
-       sodipodi:cx="31.112698"
-       sodipodi:cy="19.008621"
-       sodipodi:rx="8.6620579"
-       sodipodi:ry="8.6620579"
-       d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1  22.45064,19.008621 A 8.6620579 8.6620579 0 1 1  39.774755 19.008621 z" />
-    <path
-       style="opacity:1;fill:#efefef;fill-opacity:1;stroke:#787878;stroke-width:0.95516169;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 2.875,7.5 C 2.1210885,7.5 1.5,8.1265217 1.5,8.90625 L 1.5,15.71875 L 1.5,18.46875 L 1.5,26.189031 C 1.5,26.968759 2.1210885,27.595282 2.875,27.595281 L 5.5,27.595281 L 5.5,30.532781 L 9.2020155,27.56625 L 22.125,27.595281 C 22.878911,27.595281 23.5,26.968758 23.5,26.189031 L 23.5,18.46875 L 23.5,15.71875 L 23.5,8.90625 C 23.5,8.1265221 22.878912,7.5000001 22.125,7.5 L 16.15625,7.5 L 8.375,7.5 L 2.875,7.5 z "
-       id="rect1326"
-       transform="matrix(1.045455,0,0,1.048433,3.931818,8.785079)"
-       sodipodi:nodetypes="cccccccccccccccccc" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-0.94924349"
-       inkscape:original="M 2.875 7.5 C 2.1210885 7.5 1.5 8.1265217 1.5 8.90625 L 1.5 15.71875 L 1.5 18.46875 L 1.5 26.1875 C 1.5 26.967227 2.1210885 27.593751 2.875 27.59375 L 5.5 27.59375 L 5.5 30.53125 L 9.1875 27.5625 L 22.125 27.59375 C 22.878911 27.593749 23.5 26.967227 23.5 26.1875 L 23.5 18.46875 L 23.5 15.71875 L 23.5 8.90625 C 23.5 8.1265221 22.878912 7.5000001 22.125 7.5 L 16.15625 7.5 L 8.375 7.5 L 2.875 7.5 z "
-       style="opacity:1;fill:none;fill-opacity:1;stroke:white;stroke-width:0.95516169;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path5034"
-       d="M 2.875,8.4375 C 2.6469872,8.4375 2.4375,8.6305983 2.4375,8.90625 L 2.4375,15.71875 L 2.4375,18.46875 L 2.4375,26.1875 C 2.4375,26.46315 2.6469898,26.65625 2.875,26.65625 L 5.5,26.65625 C 6.0150993,26.662634 6.4311157,27.078651 6.4375,27.59375 L 6.4375,28.5625 L 8.59375,26.8125 C 8.7649594,26.685027 8.9741324,26.618972 9.1875,26.625 L 22.125,26.65625 C 22.353012,26.65625 22.5625,26.463149 22.5625,26.1875 L 22.5625,18.46875 L 22.5625,15.71875 L 22.5625,8.90625 C 22.5625,8.6305986 22.353013,8.4375 22.125,8.4375 L 16.15625,8.4375 L 8.375,8.4375 L 2.875,8.4375 z "
-       transform="matrix(1.045455,0,0,1.048433,3.931818,8.785079)" />
-  </g>
-</svg>
diff --git a/libpurple/protocols/irc/resources/irc.gresource.xml b/libpurple/protocols/irc/resources/irc.gresource.xml
deleted file mode 100644
--- a/libpurple/protocols/irc/resources/irc.gresource.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<gresources>
-  <gresource prefix="/im/pidgin/libpurple/irc">
-    <file>icons/16x16/apps/im-irc.png</file>
-    <file>icons/16x16/apps/scalable/im-irc.svg</file>
-    <file>icons/22x22/apps/im-irc.png</file>
-    <file>icons/22x22/apps/scalable/im-irc.svg</file>
-    <file>icons/48x48/apps/im-irc.png</file>
-    <file>icons/scalable/apps/im-irc.svg</file>
-  </gresource>
-</gresources>
diff --git a/libpurple/protocols/meson.build b/libpurple/protocols/meson.build
--- a/libpurple/protocols/meson.build
+++ b/libpurple/protocols/meson.build
@@ -2,6 +2,5 @@
 subdir('demo')
 subdir('facebook')
 subdir('gg')
-subdir('irc')
 subdir('ircv3')
 subdir('jabber')
diff --git a/po/POTFILES.in b/po/POTFILES.in
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -111,11 +111,6 @@
 libpurple/protocols/gg/utils.c
 libpurple/protocols/gg/validator.c
 libpurple/protocols/gg/xml.c
-libpurple/protocols/irc/cmds.c
-libpurple/protocols/irc/dcc_send.c
-libpurple/protocols/irc/irc.c
-libpurple/protocols/irc/msgs.c
-libpurple/protocols/irc/parse.c
 libpurple/protocols/jabber/adhoccommands.c
 libpurple/protocols/jabber/auth.c
 libpurple/protocols/jabber/auth_digest_md5.c
