summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libpurple/protocols/irc/cmds.c792
-rw-r--r--libpurple/protocols/irc/dcc_send.c413
-rw-r--r--libpurple/protocols/irc/irc.c1282
-rw-r--r--libpurple/protocols/irc/irc.h222
-rw-r--r--libpurple/protocols/irc/meson.build23
-rw-r--r--libpurple/protocols/irc/msgs.c1733
-rw-r--r--libpurple/protocols/irc/parse.c819
-rw-r--r--libpurple/protocols/irc/resources/icons/16x16/apps/im-irc.pngbin618 -> 0 bytes
-rw-r--r--libpurple/protocols/irc/resources/icons/16x16/apps/scalable/im-irc.svg222
-rw-r--r--libpurple/protocols/irc/resources/icons/22x22/apps/im-irc.pngbin558 -> 0 bytes
-rw-r--r--libpurple/protocols/irc/resources/icons/22x22/apps/scalable/im-irc.svg237
-rw-r--r--libpurple/protocols/irc/resources/icons/48x48/apps/im-irc.pngbin1003 -> 0 bytes
-rw-r--r--libpurple/protocols/irc/resources/icons/scalable/apps/im-irc.svg238
-rw-r--r--libpurple/protocols/irc/resources/irc.gresource.xml11
-rw-r--r--libpurple/protocols/meson.build1
-rw-r--r--po/POTFILES.in5
16 files changed, 0 insertions, 5998 deletions
diff --git a/libpurple/protocols/irc/cmds.c b/libpurple/protocols/irc/cmds.c
deleted file mode 100644
index 2709247e46..0000000000
--- 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
index 35fc61518c..0000000000
--- 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.c b/libpurple/protocols/irc/irc.c
deleted file mode 100644
index 4304650b88..0000000000
--- 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/irc.h b/libpurple/protocols/irc/irc.h
deleted file mode 100644
index 3ca5e72cd2..0000000000
--- 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/meson.build b/libpurple/protocols/irc/meson.build
deleted file mode 100644
index 14bfefbdda..0000000000
--- 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
index af90fd9198..0000000000
--- 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
index 12d0136dd8..0000000000
--- 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 2d22c75a04..0000000000
--- a/libpurple/protocols/irc/resources/icons/16x16/apps/im-irc.png
+++ /dev/null
Binary files differ
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
index d218f8db53..0000000000
--- 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 4fa09abe9c..0000000000
--- a/libpurple/protocols/irc/resources/icons/22x22/apps/im-irc.png
+++ /dev/null
Binary files differ
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
index a4ab01eea2..0000000000
--- 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 606425fabb..0000000000
--- a/libpurple/protocols/irc/resources/icons/48x48/apps/im-irc.png
+++ /dev/null
Binary files differ
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
index 28e8cb6ee4..0000000000
--- 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
index 5e890b4aa3..0000000000
--- 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
index c62892598f..256aaf4868 100644
--- a/libpurple/protocols/meson.build
+++ b/libpurple/protocols/meson.build
@@ -2,6 +2,5 @@ subdir('bonjour')
subdir('demo')
subdir('facebook')
subdir('gg')
-subdir('irc')
subdir('ircv3')
subdir('jabber')
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f8b546f066..37a8f3610f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -111,11 +111,6 @@ libpurple/protocols/gg/tcpsocket.c
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