pidgin/pidgin

Remove the original irc protocol plugin

13 months ago, Gary Kramlich
637ba5491231
Parents 91d0671d4778
Children fc241db9162d
Remove the original irc protocol plugin

I was waiting to do this until IRCv3 was at feature parity, but now one is
using this right now anyways which means having to keep updating it for changes
is just a waste of effort.

Testing Done:
ran `ninja turtles` and opened the new account dialog without issue.

Reviewed at https://reviews.imfreedom.org/r/2392/
--- a/libpurple/protocols/irc/cmds.c Wed Mar 29 23:21:05 2023 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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);
- }
-}
--- a/libpurple/protocols/irc/dcc_send.c Wed Mar 29 23:21:05 2023 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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);
-}
--- a/libpurple/protocols/irc/irc.c Wed Mar 29 23:21:05 2023 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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)
--- a/libpurple/protocols/irc/irc.h Wed Mar 29 23:21:05 2023 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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 */
--- a/libpurple/protocols/irc/meson.build Wed Mar 29 23:21:05 2023 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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
--- a/libpurple/protocols/irc/msgs.c Wed Mar 29 23:21:05 2023 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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);
-}
--- a/libpurple/protocols/irc/parse.c Wed Mar 29 23:21:05 2023 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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);
-}
Binary file libpurple/protocols/irc/resources/icons/16x16/apps/im-irc.png has changed
--- a/libpurple/protocols/irc/resources/icons/16x16/apps/scalable/im-irc.svg Wed Mar 29 23:21:05 2023 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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>
Binary file libpurple/protocols/irc/resources/icons/22x22/apps/im-irc.png has changed
--- a/libpurple/protocols/irc/resources/icons/22x22/apps/scalable/im-irc.svg Wed Mar 29 23:21:05 2023 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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>
Binary file libpurple/protocols/irc/resources/icons/48x48/apps/im-irc.png has changed
--- a/libpurple/protocols/irc/resources/icons/scalable/apps/im-irc.svg Wed Mar 29 23:21:05 2023 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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>
--- a/libpurple/protocols/irc/resources/irc.gresource.xml Wed Mar 29 23:21:05 2023 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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>
--- a/libpurple/protocols/meson.build Wed Mar 29 23:21:05 2023 -0500
+++ b/libpurple/protocols/meson.build Wed Mar 29 23:21:45 2023 -0500
@@ -2,6 +2,5 @@
subdir('demo')
subdir('facebook')
subdir('gg')
-subdir('irc')
subdir('ircv3')
subdir('jabber')
--- a/po/POTFILES.in Wed Mar 29 23:21:05 2023 -0500
+++ b/po/POTFILES.in Wed Mar 29 23:21:45 2023 -0500
@@ -111,11 +111,6 @@
libpurple/protocols/gg/utils.c
libpurple/protocols/gg/validator.c
libpurple/protocols/gg/xml.c
-libpurple/protocols/irc/cmds.c
-libpurple/protocols/irc/dcc_send.c
-libpurple/protocols/irc/irc.c
-libpurple/protocols/irc/msgs.c
-libpurple/protocols/irc/parse.c
libpurple/protocols/jabber/adhoccommands.c
libpurple/protocols/jabber/auth.c
libpurple/protocols/jabber/auth_digest_md5.c