pidgin/purple-plugin-pack

Bump versions version for release
pp_2_8_0
2020-08-06, Gary Kramlich
1e6de767dd01
Bump versions version for release
/**
* @file irc-more.c A couple of additional IRC features.
*
* Copyright (C) 2007-2008 Sadrul Habib Chowdhury <sadrul@users.sourceforge.net>
* Copyright (C) 2007-2008 John Bailey <rekkanoryo@rekkanoryo.org>
*
* 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
*/
/* If you can't figure out what this line is for, DON'T TOUCH IT. */
#include "../common/pp_internal.h"
#include <accountopt.h>
#include <cmds.h>
#include <conversation.h>
#include <debug.h>
#include <plugin.h>
#include <prpl.h>
#include <string.h>
#define AUTOJOIN purple_account_get_string(account, "autojoin", NULL)
#define CTCP_REPLY purple_account_get_string(account, "ctcp-message", "Purple IRC")
#define PART_MESSAGE purple_account_get_string(account, "part-message", "Leaving.")
#define QUIT_MESSAGE purple_account_get_string(account, "quit-message", "Leaving.")
#define SET_UMODES purple_account_get_string(account, "setumodes", NULL)
#define UNSET_UMODES purple_account_get_string(account, "unsetumodes", NULL)
#define PLUGIN_ID "core-plugin_pack-irc-more"
#define MATCHES(string) !strncmp(*msg, string, sizeof(string) - 1)
static PurpleCmdId notice_cmd_id = 0;
static PurplePluginProtocolInfo *irc_info = NULL;
static gboolean
show_them(gpointer data)
{
/* So you think you can kick me? I'll show you! */
PurpleConversation *conv = data;
const char *conv_name = NULL;
char *command = NULL, *markup = NULL, *error = NULL;
if(conv)
conv_name = purple_conversation_get_name(conv);
if(conv_name) {
command = g_strdup_printf("join %s", conv_name);
markup = g_markup_escape_text(command, -1);
error = NULL;
purple_cmd_do_command(conv, command, markup, &error); /* Do anything with the return value? */
g_free(command);
g_free(markup);
g_free(error);
}
return FALSE;
}
static void
irc_receiving_text(PurpleConnection *gc, const char **incoming, gpointer null)
{
char **splits, *str;
PurpleAccount *account = NULL;
if (!incoming || !*incoming || !**incoming) /* oh the fun .. I can do this all day! */
return;
splits = g_strsplit(*incoming, " ", -1);
/* if there's not at least 5 elements in the string array, this isn't a kick; ignore */
if(g_strv_length(splits) < 5)
return;
account = purple_connection_get_account(gc);
str = g_ascii_strdown(splits[1], -1);
if (strcmp(str, "kick") == 0 && splits[2] && splits[3]) {
char *name = splits[2];
GList *chats = purple_get_chats();
while (chats) {
PurpleConversation *conv = chats->data;
chats = chats->next;
if (purple_conversation_get_account(conv) == account
&& strcmp(purple_conversation_get_name(conv), name) == 0) {
purple_timeout_add(100, show_them, conv);
break;
}
}
}
g_free(str);
g_strfreev(splits);
}
static gboolean
autojoin_cb(gpointer data)
{
PurpleAccount *account = data;
gchar *cmd = g_strdup_printf("join %s", AUTOJOIN), *error = NULL,
*esc = g_markup_escape_text(cmd, -1);
int result = 0;
#if !PURPLE_VERSION_CHECK(3,0,0)
/* this hack courtesy irchelper -- don't use purple_conversation_set_account
* because it will fire a signal that other plugins can use. Instead do
* this hack. This will break when struct hiding is complete and ABI breaks. */
PurpleConversation *conv = g_new0(PurpleConversation, 1);
conv->type = PURPLE_CONV_TYPE_IM;
conv->account = account;
#else
PurpleConversation *conv = purple_conversation_new(PURPLE_CONV_TYPE_IM,
account, "None");
#endif
purple_debug_info("irc-more", "Executing command: %s\n", cmd);
result = purple_cmd_do_command(conv, cmd, esc, &error);
purple_debug_info("irc-more", "Executed command. Result: %d. Error: %s\n",
result, error ? error : "(null)");
g_free(cmd);
g_free(conv);
g_free(esc);
return FALSE;
}
static void
signed_on_cb(PurpleConnection *gc)
{
/* should this be done on a timeout? */
PurpleAccount *account = NULL;
const gchar *nick = NULL, *setmodes = NULL, *unsetmodes = NULL, *autojoin = NULL;
gchar *msg = NULL, *msg2 = NULL;
account = purple_connection_get_account(gc);
/* hopefully prevent crashes related to non-IRC accounts signing on */
if(strcmp("prpl-irc", purple_account_get_protocol_id(account)))
return;
nick = purple_connection_get_display_name(gc);
setmodes = SET_UMODES;
unsetmodes = UNSET_UMODES;
autojoin = AUTOJOIN;
if(setmodes && *setmodes) {
msg = g_strdup_printf("MODE %s +%s\r\n", nick, setmodes);
purple_debug_info("irc-more", "Sending command: %s\n", msg);
irc_info->send_raw(gc, msg, strlen(msg));
g_free(msg);
}
if(unsetmodes && *unsetmodes) {
msg2 = g_strdup_printf("MODE %s -%s\r\n", nick, unsetmodes);
purple_debug_info("irc-more", "Sending command: %s\n", msg);
irc_info->send_raw(gc, msg2, strlen(msg2));
g_free(msg2);
}
if(autojoin && *autojoin)
purple_timeout_add_seconds(6, autojoin_cb, account);
return;
}
#if !PURPLE_VERSION_CHECK(2,4,0)
static PurpleCmdRet
notice_cmd_cb(PurpleConversation *conv, const gchar *cmd, gchar **args,
gchar **error, void *data)
{
gchar *tmp = NULL, *msg = NULL;
gint len = 0, arg0len = 0, arg1len = 0, maxlen = 0;
PurpleConnection *gc = NULL;
if(!args && !args[0] && !args[1])
return PURPLE_CMD_RET_FAILED;
gc = purple_conversation_get_connection(conv);
/* convenience to make the next comparison make more sense */
arg0len = strlen(args[0]);
arg1len = strlen(args[1]);
/* IRC messages are limited to 512 bytes. 2 are reserved for CRLF, 2 for
* the spaces needed after the command and target, 1 for the colon needed
* before the notice text starts, and 6 for NOTICE. Result is the length
* of the message needs to be limited to 501 bytes. We need to account
* for the length of the nick or channel name that is the target, too. */
maxlen = 501 - arg0len;
if(arg1len > maxlen)
tmp = g_strndup(args[1], maxlen);
/* if tmp is not NULL, the notice the user wants to send is too long so we
* truncated it. If tmp is NULL the notice is fine as-is. Either way,
* assign msg as appropriate. */
if(tmp)
msg = tmp;
else
msg = args[1];
msg = g_strdup_printf("NOTICE %s :%s\r\n", args[0], msg);
len = strlen(msg);
irc_info->send_raw(gc, msg, len);
/* avoid a possible double-free crash */
if(msg != tmp)
g_free(tmp);
g_free(msg);
return PURPLE_CMD_RET_OK;
}
#endif
static void
irc_sending_text(PurpleConnection *gc, char **msg, gpointer data)
{
PurpleAccount *account = purple_connection_get_account(gc);
char *old = *msg;
if (MATCHES("QUIT ")) {
char *message = strchr(*msg, ':');
if (!message || purple_strequal(message + 1, "Leaving.\r\n")) {
*msg = g_strdup_printf("QUIT :%s\r\n", QUIT_MESSAGE);
}
} else if (MATCHES("PART ")) {
char *message = strchr(*msg, ':');
if (message)
return; /* The user did give some part message. Do not use the default one. */
message = strchr(*msg, '\r');
*message = '\0';
*msg = g_strdup_printf("%s :%s\r\n", *msg, PART_MESSAGE);
} else if (MATCHES("NOTICE ")) {
char *version = strstr(*msg, ":\001VERSION ");
if (!version)
return;
*version = '\0';
*msg = g_strdup_printf("%s:\001VERSION %s\001\r\n", *msg, CTCP_REPLY);
}
if (*msg != old)
g_free(old);
}
static gboolean
plugin_load(PurplePlugin *plugin)
{
PurplePlugin *prpl = NULL;
PurpleAccountOption *option;
void *gc_handle = NULL;
#if !PURPLE_VERSION_CHECK(2,4,0)
gchar *notice_help = NULL;
#endif
prpl = purple_find_prpl("prpl-irc");
/* if we didn't find the prpl, bail */
if (!prpl)
return FALSE;
#if !PURPLE_VERSION_CHECK(2,4,0)
/* specify our help string and register our command */
notice_help = _("notice target message: Send a notice to the specified target.");
notice_cmd_id = purple_cmd_register("notice", "ws", PURPLE_CMD_P_PLUGIN,
PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
"prpl-irc", notice_cmd_cb, notice_help, NULL);
#endif
/* we need this handle for the signed-on signal */
gc_handle = purple_connections_get_handle();
/* list signals in alphabetical order for consistency */
purple_signal_connect(prpl, "irc-sending-text", plugin,
G_CALLBACK(irc_sending_text), NULL);
purple_signal_connect(prpl, "irc-receiving-text", plugin,
G_CALLBACK(irc_receiving_text), NULL);
purple_signal_connect(gc_handle, "signed-on", plugin,
G_CALLBACK(signed_on_cb), NULL);
irc_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
/* Alphabetize the option label strings */
option = purple_account_option_string_new(_("Auto-Join Channels"), "autojoin", "");
irc_info->protocol_options = g_list_append(irc_info->protocol_options, option);
option = purple_account_option_string_new(_("CTCP Version reply"), "ctcp-message", "Purple IRC");
irc_info->protocol_options = g_list_append(irc_info->protocol_options, option);
option = purple_account_option_string_new(_("Default Quit Message"), "quit-message", "Leaving.");
irc_info->protocol_options = g_list_append(irc_info->protocol_options, option);
option = purple_account_option_string_new(_("Default Part Message"), "part-message", "Leaving.");
irc_info->protocol_options = g_list_append(irc_info->protocol_options, option);
option = purple_account_option_string_new(_("Set User Modes On Connect"), "setumodes", "i");
irc_info->protocol_options = g_list_append(irc_info->protocol_options, option);
option = purple_account_option_string_new(_("Unset User Modes On Connect"), "unsetumodes", "");
irc_info->protocol_options = g_list_append(irc_info->protocol_options, option);
return TRUE;
}
static gboolean
plugin_unload(PurplePlugin *plugin)
{
purple_cmd_unregister(notice_cmd_id);
return TRUE;
}
static PurplePluginInfo info =
{
PURPLE_PLUGIN_MAGIC,
PURPLE_MAJOR_VERSION,
PURPLE_MINOR_VERSION,
PURPLE_PLUGIN_STANDARD,
NULL,
0,
NULL,
PURPLE_PRIORITY_DEFAULT,
PLUGIN_ID,
NULL,
PP_VERSION,
NULL,
NULL,
"Sadrul H Chowdhury <sadrul@users.sourceforge.net>\n"
"John Bailey <rekkanoryo@rekkanoryo.org>",
PP_WEBSITE,
plugin_load,
plugin_unload,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
static void
init_plugin(PurplePlugin *plugin)
{
#ifdef ENABLE_NLS
bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
#endif /* ENABLE_NLS */
info.name = _("IRC More");
info.summary = _("Adds additional IRC features.");
#if !PURPLE_VERSION_CHECK(2,4,0)
info.description = _("Adds additional IRC features, including a "
"customizable quit message, a customizable CTCP VERSION reply, "
"a rudimentary channel autojoin list, and the /notice command for "
"notices.");
#else
info.description = _("Adds additional IRC features, including a "
"customizable quit message, a customizable CTCP VERSION reply, "
"and a rudimentary channel autojoin list.");
#endif
}
PURPLE_INIT_PLUGIN(irc_more, init_plugin, info)