1
0
mirror of https://github.com/weechat/weechat.git synced 2026-06-24 20:06:38 +02:00
Files
weechat/src/plugins/irc/irc-redirect.c
T
2011-08-28 15:25:30 +02:00

1357 lines
46 KiB
C

/*
* Copyright (C) 2010-2011 Sebastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat 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 3 of the License, or
* (at your option) any later version.
*
* WeeChat 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 WeeChat. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* irc-redirect.c: redirection of IRC command output
*/
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "../weechat-plugin.h"
#include "irc.h"
#include "irc-redirect.h"
#include "irc-server.h"
struct t_irc_redirect_pattern *irc_redirect_patterns = NULL;
struct t_irc_redirect_pattern *last_irc_redirect_pattern = NULL;
/* default redirect patterns */
struct t_irc_redirect_pattern irc_redirect_patterns_default[] =
{
{ "ison", 0, 0,
/*
* ison: start: -
* stop: 303: ison
* extra: -
*/
NULL,
"303",
NULL,
NULL, NULL,
},
{ "list", 0, 0,
/*
* list: start: 321: /list start
* stop: 323: end of /list
* extra: -
*/
"321",
"323",
NULL,
NULL, NULL,
},
{ "mode_channel", 0, 0,
/*
* mode_channel: start: -
* stop: 324: mode
* 403: no such channel
* 442: not on channel
* 479: cannot join channel (illegal name)
* extra: 329: channel creation date
*/
NULL,
"324:1,403:1,442:1,479:1",
"329:1",
NULL, NULL,
},
{ "mode_channel_ban", 0, 0, /* mode #channel b */
/*
* mode_channel_ban: start: 367: ban
* stop: 368: end of channel ban list
* 403: no such channel
* 442: not on channel
* 479: cannot join channel (illegal name)
* extra: -
*/
"367:1",
"368:1,403:1,442:1,479:1",
NULL,
NULL, NULL,
},
{ "mode_channel_ban_exception", 0, 0, /* mode #channel e */
/*
* mode_channel_ban_exception: start: 348: ban exception
* stop: 349: end of ban exceptions
* 403: no such channel
* 442: not on channel
* 472: unknown mode char to me
* 479: cannot join channel (illegal name)
* 482: you're not channel operator
* extra: -
*/
"348:1",
"349:1,403:1,442:1,472,479:1,482:1",
NULL,
NULL, NULL,
},
{ "mode_channel_invite", 0, 0, /* mode #channel I */
/*
* mode_channel_invite: start: 346: invite
* stop: 347: end of invite list
* 403: no such channel
* 442: not on channel
* 472: unknown mode char to me
* 479: cannot join channel (illegal name)
* 482: you're not channel operator
* extra: -
*/
"346:1",
"347:1,403:1,442:1,472,479:1,482:1",
NULL,
NULL, NULL,
},
{ "mode_user", 0, 0,
/*
* mode_user: start: -
* stop: mode: mode
* 221: user mode string
* 403: no such channel
* 501: unknown mode flag
* 502: can't change mode for other users
* extra; -
*/
NULL,
"mode:0,221:0,403:1,501,502",
NULL,
NULL, NULL,
},
{ "names", 0, 0,
/*
* names: start: 353: list of nicks on channel
* stop: 366: end of /names list
* extra; -
*/
"353:2",
"366:1",
NULL,
NULL, NULL,
},
{ "ping", 0, 0,
/*
* ping: start: -
* stop: pong: pong
* 402: no such server
* extra: -
*/
NULL,
"pong,402",
NULL,
NULL, NULL,
},
{ "time", 0, 0,
/*
* time: start: -
* stop: 391: local time from server
* extra: -
*/
NULL,
"391",
NULL,
NULL, NULL,
},
{ "topic", 0, 0,
/*
* topic: start: -
* stop: 331: no topic is set
* 332: topic
* 403: no such channel
* extra: 333: infos about topic (nick and date changed)
*/
NULL,
"331:1,332:1,403:1",
"333:1",
NULL, NULL,
},
{ "userhost", 0, 0,
/*
* userhost: start: 401: no such nick/channel
* stop: 302: userhost
* 461: not enough parameters
* extra: -
*/
"401:1",
"302,461",
NULL,
NULL, NULL,
},
{ "who", 0, 0,
/*
* who: start: 352: who
* 354: whox
* 401: no such nick/channel
* stop: 315: end of /who list
* 403: no such channel
* extra: -
*/
"352:1,354,401:1",
"315:1,403:1",
NULL,
NULL, NULL,
},
{ "whois", 0, 0,
/*
* whois: start: 311: whois (user)
* stop: 318: whois (end)
* 401: no such nick/channel
* 402: no such server
* 431: no nickname given
* 461: not enough parameters
* extra: 318: whois (end)
*/
"311:1",
"318:1,401:1,402:1,431:1,461",
"318:1",
NULL, NULL,
},
{ "whowas", 0, 0,
/*
* whowas: start: 314: whowas (user)
* 406: there was no such nickname
* stop: 369: end of whowas
* extra: -
*/
"314:1,406:1",
"369:1",
NULL,
NULL, NULL,
},
{ NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
};
/*
* irc_redirect_pattern_search: search a redirect pattern in list of patterns
*/
struct t_irc_redirect_pattern *
irc_redirect_pattern_search (const char *name)
{
struct t_irc_redirect_pattern *ptr_redirect_pattern;
if (!name)
return NULL;
for (ptr_redirect_pattern = irc_redirect_patterns; ptr_redirect_pattern;
ptr_redirect_pattern = ptr_redirect_pattern->next_redirect)
{
if (strcmp (ptr_redirect_pattern->name, name) == 0)
return ptr_redirect_pattern;
}
/* redirect pattern not found */
return NULL;
}
/*
* irc_redirect_pattern_new: create a new redirect pattern
*/
struct t_irc_redirect_pattern *
irc_redirect_pattern_new (const char *name, int temp_pattern, int timeout,
const char *cmd_start, const char *cmd_stop,
const char *cmd_extra)
{
struct t_irc_redirect_pattern *ptr_redirect_pattern, *new_redirect_pattern;
if (!name)
return NULL;
if (!cmd_stop || !cmd_stop[0])
{
weechat_printf (NULL,
_("%s%s: missing argument \"%s\" for redirect pattern"),
weechat_prefix ("error"), IRC_PLUGIN_NAME,
"cmd_stop");
return NULL;
}
/* check if redirect pattern already exists */
ptr_redirect_pattern = irc_redirect_pattern_search (name);
if (ptr_redirect_pattern)
{
weechat_printf (NULL,
_("%s%s: redirect pattern \"%s\" already exists"),
weechat_prefix ("error"), IRC_PLUGIN_NAME,
name);
return NULL;
}
new_redirect_pattern = malloc (sizeof (*new_redirect_pattern));
if (!new_redirect_pattern)
return NULL;
/* initialize new redirect */
new_redirect_pattern->name = strdup (name);
new_redirect_pattern->temp_pattern = temp_pattern;
new_redirect_pattern->timeout = (timeout > 0) ? timeout : IRC_REDIRECT_TIMEOUT_DEFAULT;
new_redirect_pattern->cmd_start = (cmd_start) ? strdup (cmd_start) : NULL;
new_redirect_pattern->cmd_stop = strdup (cmd_stop);
new_redirect_pattern->cmd_extra = (cmd_extra) ? strdup (cmd_extra) : NULL;
/* add redirect pattern to end of list */
new_redirect_pattern->prev_redirect = last_irc_redirect_pattern;
if (irc_redirect_patterns)
last_irc_redirect_pattern->next_redirect = new_redirect_pattern;
else
irc_redirect_patterns = new_redirect_pattern;
last_irc_redirect_pattern = new_redirect_pattern;
new_redirect_pattern->next_redirect = NULL;
return new_redirect_pattern;
}
/*
* irc_redirect_pattern_free: free a redirect pattern and remove it from list
*/
void
irc_redirect_pattern_free (struct t_irc_redirect_pattern *redirect_pattern)
{
struct t_irc_redirect_pattern *new_redirect_patterns;
if (!redirect_pattern)
return;
/* remove redirect */
if (last_irc_redirect_pattern == redirect_pattern)
last_irc_redirect_pattern = redirect_pattern->prev_redirect;
if (redirect_pattern->prev_redirect)
{
(redirect_pattern->prev_redirect)->next_redirect = redirect_pattern->next_redirect;
new_redirect_patterns = irc_redirect_patterns;
}
else
new_redirect_patterns = redirect_pattern->next_redirect;
if (redirect_pattern->next_redirect)
(redirect_pattern->next_redirect)->prev_redirect = redirect_pattern->prev_redirect;
/* free data */
if (redirect_pattern->name)
free (redirect_pattern->name);
if (redirect_pattern->cmd_start)
free (redirect_pattern->cmd_start);
if (redirect_pattern->cmd_stop)
free (redirect_pattern->cmd_stop);
if (redirect_pattern->cmd_extra)
free (redirect_pattern->cmd_extra);
free (redirect_pattern);
irc_redirect_patterns = new_redirect_patterns;
}
/*
* irc_redirect_pattern_free_all: free all redirect patterns
*/
void
irc_redirect_pattern_free_all ()
{
while (irc_redirect_patterns)
{
irc_redirect_pattern_free (irc_redirect_patterns);
}
}
/*
* irc_redirect_new_with_commands: create a new redirect for a command on a
* server (with start/stop/extra commands in
* arguments)
*/
struct t_irc_redirect *
irc_redirect_new_with_commands (struct t_irc_server *server,
const char *pattern, const char *signal,
int count, const char *string, int timeout,
const char *cmd_start,
const char *cmd_stop,
const char *cmd_extra,
const char *cmd_filter)
{
struct t_irc_redirect *new_redirect;
char **items[4], *pos, *error;
int i, j, num_items[4];
long value;
struct t_hashtable *hash_cmd[4];
new_redirect = malloc (sizeof (*new_redirect));
if (!new_redirect)
return NULL;
/* create hashtables with commands */
for (i = 0; i < 4; i++)
{
hash_cmd[i] = NULL;
items[i] = NULL;
}
if (cmd_start)
items[0] = weechat_string_split (cmd_start, ",", 0, 0, &num_items[0]);
if (cmd_stop)
items[1] = weechat_string_split (cmd_stop, ",", 0, 0, &num_items[1]);
if (cmd_extra)
items[2] = weechat_string_split (cmd_extra, ",", 0, 0, &num_items[2]);
if (cmd_filter)
items[3] = weechat_string_split (cmd_filter, ",", 0, 0, &num_items[3]);
for (i = 0; i < 4; i++)
{
if (items[i])
{
hash_cmd[i] = weechat_hashtable_new (8,
WEECHAT_HASHTABLE_STRING,
WEECHAT_HASHTABLE_INTEGER,
NULL,
NULL);
for (j = 0; j < num_items[i]; j++)
{
if (i < 3)
{
value = -1;
pos = strchr (items[i][j], ':');
if (pos)
{
pos[0] = '\0';
value = strtol (pos + 1, &error, 10);
if (!error || error[0])
value = -1;
}
weechat_string_toupper (items[i][j]);
weechat_hashtable_set (hash_cmd[i], items[i][j], &value);
}
else
{
weechat_hashtable_set (hash_cmd[i], items[i][j], NULL);
}
}
weechat_string_free_split (items[i]);
}
}
/* initialize new redirect */
new_redirect->server = server;
new_redirect->pattern = strdup (pattern);
new_redirect->signal = strdup (signal);
new_redirect->count = (count >= 1) ? count : 1;
new_redirect->current_count = 1;
new_redirect->string = (string) ? strdup (string) : NULL;
new_redirect->timeout = timeout;
new_redirect->command = NULL;
new_redirect->start_time = 0;
new_redirect->cmd_start = hash_cmd[0];
new_redirect->cmd_stop = hash_cmd[1];
new_redirect->cmd_extra = hash_cmd[2];
new_redirect->cmd_start_received = 0;
new_redirect->cmd_stop_received = 0;
new_redirect->cmd_filter = hash_cmd[3];
new_redirect->output = NULL;
new_redirect->output_size = 0;
/* add redirect to end of list */
new_redirect->prev_redirect = server->last_redirect;
if (server->redirects)
(server->last_redirect)->next_redirect = new_redirect;
else
server->redirects = new_redirect;
server->last_redirect = new_redirect;
new_redirect->next_redirect = NULL;
return new_redirect;
}
/*
* irc_redirect_new: create a new redirect for a command on a server
*/
struct t_irc_redirect *
irc_redirect_new (struct t_irc_server *server,
const char *pattern, const char *signal,
int count, const char *string, int timeout,
const char *cmd_filter)
{
struct t_irc_redirect_pattern *ptr_redirect_pattern;
struct t_irc_redirect *new_redirect;
if (!server->is_connected)
{
weechat_printf (NULL,
_("%s%s: no connection to server \"%s\" for redirect"),
weechat_prefix ("error"), IRC_PLUGIN_NAME,
server->name);
return NULL;
}
if (!pattern || !pattern[0])
{
weechat_printf (NULL, _("%s%s: missing argument \"%s\" for redirect"),
weechat_prefix ("error"), IRC_PLUGIN_NAME, "pattern");
return NULL;
}
if (!signal || !signal[0])
{
weechat_printf (NULL, _("%s%s: missing argument \"%s\" for redirect"),
weechat_prefix ("error"), IRC_PLUGIN_NAME, "signal");
return NULL;
}
ptr_redirect_pattern = irc_redirect_pattern_search (pattern);
if (!ptr_redirect_pattern)
{
weechat_printf (NULL, _("%s%s: redirect pattern \"%s\" not found"),
weechat_prefix ("error"), IRC_PLUGIN_NAME,
pattern);
return NULL;
}
new_redirect = irc_redirect_new_with_commands (server, pattern, signal,
count, string,
(timeout > 0) ? timeout : ptr_redirect_pattern->timeout,
ptr_redirect_pattern->cmd_start,
ptr_redirect_pattern->cmd_stop,
ptr_redirect_pattern->cmd_extra,
cmd_filter);
/*
* remove redirect pattern if it is temporary (created by external
* plugin/script)
*/
if (new_redirect && ptr_redirect_pattern->temp_pattern)
irc_redirect_pattern_free (ptr_redirect_pattern);
return new_redirect;
}
/*
* irc_redirect_search_available: search first redirect available for server
*/
struct t_irc_redirect *
irc_redirect_search_available (struct t_irc_server *server)
{
struct t_irc_redirect *ptr_redirect;
if (!server)
return NULL;
for (ptr_redirect = server->redirects; ptr_redirect;
ptr_redirect = ptr_redirect->next_redirect)
{
if (ptr_redirect->start_time == 0)
return ptr_redirect;
}
/* no redirect available */
return NULL;
}
/*
* irc_redirect_init_command: initalize a redirect with IRC command sent to
* server
*/
void
irc_redirect_init_command (struct t_irc_redirect *redirect,
const char *command)
{
char *pos;
if (!redirect)
return;
if (command)
{
pos = strchr (command, '\r');
if (!pos)
pos = strchr (command, '\n');
if (pos)
redirect->command = weechat_strndup (command, pos - command);
else
redirect->command = strdup (command);
}
else
redirect->command = NULL;
redirect->start_time = time (NULL);
if (weechat_irc_plugin->debug >= 2)
{
weechat_printf (redirect->server->buffer,
_("%s: starting redirection for command \"%s\" "
"on server \"%s\" (redirect pattern: \"%s\")"),
IRC_PLUGIN_NAME,
redirect->command,
redirect->server->name,
redirect->pattern);
}
}
/*
* irc_redirect_message_match_hash: return 1 if a message matches hashtable
* with commands, 0 if it doesn't match
*/
int
irc_redirect_message_match_hash (struct t_irc_redirect *redirect,
const char *command,
char **arguments_argv, int arguments_argc,
struct t_hashtable *cmd_hash)
{
int *value;
value = weechat_hashtable_get (cmd_hash, command);
if (!value)
return 0;
/*
* if string is in redirect and that this command requires string to
* be in message, then search for this string
*/
if (redirect->string && redirect->string[0] && (*value >= 0))
{
if (!arguments_argv || (*value >= arguments_argc))
return 0;
if (weechat_strcasecmp (arguments_argv[*value], redirect->string) != 0)
return 0;
}
return 1;
}
/*
* irc_redirect_message_add: add a message to redirect output
*/
void
irc_redirect_message_add (struct t_irc_redirect *redirect, const char *message,
const char *command)
{
char *output2;
/*
* if command is not for output, then don't add message
* (it is silently ignored)
*/
if (redirect->cmd_filter
&& !weechat_hashtable_has_key (redirect->cmd_filter, command))
return;
/* add message to output */
if (redirect->output)
{
redirect->output_size += strlen("\n") + strlen (message);
output2 = realloc (redirect->output, redirect->output_size);
if (!output2)
{
free (redirect->output);
redirect->output = NULL;
redirect->output_size = 0;
return;
}
redirect->output = output2;
strcat (redirect->output, "\n");
}
else
{
redirect->output_size = strlen (message) + 1;
redirect->output = malloc (redirect->output_size);
if (redirect->output)
redirect->output[0] = '\0';
}
if (redirect->output)
strcat (redirect->output, message);
}
/*
* irc_redirect_stop: end of a redirection: send data to callback and free
* redirect (if count has been reached)
*/
void
irc_redirect_stop (struct t_irc_redirect *redirect, const char *error)
{
struct t_hashtable *hashtable;
char signal_name[1024], str_int[64];
redirect->current_count++;
if (error || (redirect->current_count > redirect->count))
{
/*
* error or max count reached, then we run callback and remove
* redirect
*/
hashtable = weechat_hashtable_new (8,
WEECHAT_HASHTABLE_STRING,
WEECHAT_HASHTABLE_STRING,
NULL,
NULL);
if (hashtable)
{
/* set error and output (main fields) */
weechat_hashtable_set (hashtable, "error",
(error) ? (char *)error : "");
weechat_hashtable_set (hashtable, "output",
(redirect->output) ? redirect->output : "");
snprintf (str_int, sizeof (str_int), "%d", redirect->output_size);
weechat_hashtable_set (hashtable, "output_size", str_int);
/* set some other fields with values from redirect */
weechat_hashtable_set (hashtable, "server", redirect->server->name);
weechat_hashtable_set (hashtable, "pattern", redirect->pattern);
weechat_hashtable_set (hashtable, "signal", redirect->signal);
weechat_hashtable_set (hashtable, "command", redirect->command);
}
snprintf (signal_name, sizeof (signal_name), "irc_redirection_%s_%s",
redirect->signal, redirect->pattern);
weechat_hook_hsignal_send (signal_name, hashtable);
if (hashtable)
weechat_hashtable_free (hashtable);
irc_redirect_free (redirect);
}
else
{
/*
* max count not yet reached, then we prepare redirect to continue
* redirection
*/
redirect->cmd_start_received = 0;
redirect->cmd_stop_received = 0;
}
}
/*
* irc_redirect_message: try to redirect a received message (from IRC server)
* to a redirect in server
* return: 1 if message has been redirected
* 0 if no matching redirect was found
* if message has been redirected, irc plugin will
* discard it (do not display anything)
*/
int
irc_redirect_message (struct t_irc_server *server, const char *message,
const char *command, const char *arguments)
{
struct t_irc_redirect *ptr_redirect, *ptr_next_redirect;
int rc, match_stop, arguments_argc;
char **arguments_argv;
if (!server || !server->redirects || !message || !command)
return 0;
rc = 0;
if (arguments && arguments[0])
{
arguments_argv = weechat_string_split (arguments, " ", 0, 0,
&arguments_argc);
}
else
{
arguments_argv = NULL;
arguments_argc = 0;
}
ptr_redirect = server->redirects;
while (ptr_redirect)
{
ptr_next_redirect = ptr_redirect->next_redirect;
if (ptr_redirect->start_time > 0)
{
if (ptr_redirect->cmd_stop_received)
{
if (ptr_redirect->cmd_extra
&& irc_redirect_message_match_hash (ptr_redirect,
command,
arguments_argv,
arguments_argc,
ptr_redirect->cmd_extra))
{
irc_redirect_message_add (ptr_redirect, message, command);
irc_redirect_stop (ptr_redirect, NULL);
rc = 1;
goto end;
}
irc_redirect_stop (ptr_redirect, NULL);
}
else
{
/* message matches a start command? */
if (ptr_redirect->cmd_start
&& !ptr_redirect->cmd_start_received
&& irc_redirect_message_match_hash (ptr_redirect,
command,
arguments_argv,
arguments_argc,
ptr_redirect->cmd_start))
{
/*
* message is a start command for redirection, then add
* message to output for redirection and mark start
* command as "received" for this redirect
*/
irc_redirect_message_add (ptr_redirect, message, command);
ptr_redirect->cmd_start_received = 1;
rc = 1;
goto end;
}
/*
* if matching stop command, or start command received, we are
* in redirection: add message to output and close redirection
* if matching stop command
*/
match_stop = irc_redirect_message_match_hash (ptr_redirect,
command,
arguments_argv,
arguments_argc,
ptr_redirect->cmd_stop);
if (match_stop || ptr_redirect->cmd_start_received)
{
/*
* add message to output if matching stop of if command
* is numeric
*/
irc_redirect_message_add (ptr_redirect, message, command);
if (match_stop)
{
ptr_redirect->cmd_stop_received = 1;
if (ptr_redirect->cmd_extra)
{
if (irc_redirect_message_match_hash (ptr_redirect,
command,
arguments_argv,
arguments_argc,
ptr_redirect->cmd_extra))
{
/*
* this command is a stop and extra command,
* then remove redirect
*/
irc_redirect_stop (ptr_redirect, NULL);
}
}
else
{
/*
* no extra command after stop, then remove
* redirect
*/
irc_redirect_stop (ptr_redirect, NULL);
}
}
rc = 1;
goto end;
}
}
}
ptr_redirect = ptr_next_redirect;
}
end:
if (arguments_argv)
weechat_string_free_split (arguments_argv);
return rc;
}
/*
* irc_redirect_free: free a redirect and remove it from list
*/
void
irc_redirect_free (struct t_irc_redirect *redirect)
{
struct t_irc_server *server;
struct t_irc_redirect *new_redirects;
int priority;
struct t_irc_outqueue *ptr_outqueue;
if (!redirect)
return;
server = redirect->server;
/* remove redirect */
if (server->last_redirect == redirect)
server->last_redirect = redirect->prev_redirect;
if (redirect->prev_redirect)
{
(redirect->prev_redirect)->next_redirect = redirect->next_redirect;
new_redirects = server->redirects;
}
else
new_redirects = redirect->next_redirect;
if (redirect->next_redirect)
(redirect->next_redirect)->prev_redirect = redirect->prev_redirect;
/* remove any pointer to this redirect */
for (priority = 0; priority < IRC_SERVER_NUM_OUTQUEUES_PRIO; priority++)
{
for (ptr_outqueue = server->outqueue[priority]; ptr_outqueue;
ptr_outqueue = ptr_outqueue->next_outqueue)
{
if (ptr_outqueue->redirect == redirect)
ptr_outqueue->redirect = NULL;
}
}
/* free data */
if (redirect->pattern)
free (redirect->pattern);
if (redirect->signal)
free (redirect->signal);
if (redirect->string)
free (redirect->string);
if (redirect->command)
free (redirect->command);
if (redirect->cmd_start)
weechat_hashtable_free (redirect->cmd_start);
if (redirect->cmd_stop)
weechat_hashtable_free (redirect->cmd_stop);
if (redirect->cmd_extra)
weechat_hashtable_free (redirect->cmd_extra);
if (redirect->cmd_filter)
weechat_hashtable_free (redirect->cmd_filter);
if (redirect->output)
free (redirect->output);
free (redirect);
server->redirects = new_redirects;
}
/*
* irc_redirect_free_all: free all redirects in list
*/
void
irc_redirect_free_all (struct t_irc_server *server)
{
while (server->redirects)
{
irc_redirect_free (server->redirects);
}
}
/*
* irc_redirect_hdata_redirect_pattern_cb: return hdata for redirect pattern
*/
struct t_hdata *
irc_redirect_hdata_redirect_pattern_cb (void *data, const char *hdata_name)
{
struct t_hdata *hdata;
/* make C compiler happy */
(void) data;
hdata = weechat_hdata_new (hdata_name, "prev_redirect", "next_redirect");
if (hdata)
{
WEECHAT_HDATA_VAR(struct t_irc_redirect_pattern, name, STRING, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect_pattern, temp_pattern, INTEGER, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect_pattern, timeout, INTEGER, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect_pattern, cmd_start, STRING, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect_pattern, cmd_stop, STRING, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect_pattern, cmd_extra, STRING, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect_pattern, prev_redirect, POINTER, hdata_name);
WEECHAT_HDATA_VAR(struct t_irc_redirect_pattern, next_redirect, POINTER, hdata_name);
WEECHAT_HDATA_LIST(irc_redirect_patterns);
WEECHAT_HDATA_LIST(last_irc_redirect_pattern);
}
return hdata;
}
/*
* irc_redirect_hdata_redirect_cb: return hdata for redirect
*/
struct t_hdata *
irc_redirect_hdata_redirect_cb (void *data, const char *hdata_name)
{
struct t_hdata *hdata;
/* make C compiler happy */
(void) data;
hdata = weechat_hdata_new (hdata_name, "prev_redirect", "next_redirect");
if (hdata)
{
WEECHAT_HDATA_VAR(struct t_irc_redirect, server, POINTER, "irc_server");
WEECHAT_HDATA_VAR(struct t_irc_redirect, pattern, STRING, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect, signal, STRING, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect, count, INTEGER, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect, current_count, INTEGER, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect, string, STRING, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect, timeout, INTEGER, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect, command, STRING, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect, start_time, TIME, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect, cmd_start, POINTER, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect, cmd_stop, POINTER, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect, cmd_extra, POINTER, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect, cmd_start_received, INTEGER, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect, cmd_stop_received, INTEGER, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect, cmd_filter, POINTER, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect, output, STRING, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect, output_size, INTEGER, NULL);
WEECHAT_HDATA_VAR(struct t_irc_redirect, prev_redirect, POINTER, hdata_name);
WEECHAT_HDATA_VAR(struct t_irc_redirect, next_redirect, POINTER, hdata_name);
}
return hdata;
}
/*
* irc_redirect_pattern_add_to_infolist: add a redirect pattern in an infolist
* return 1 if ok, 0 if error
*/
int
irc_redirect_pattern_add_to_infolist (struct t_infolist *infolist,
struct t_irc_redirect_pattern *redirect_pattern)
{
struct t_infolist_item *ptr_item;
if (!infolist || !redirect_pattern)
return 0;
ptr_item = weechat_infolist_new_item (infolist);
if (!ptr_item)
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "name", redirect_pattern->name))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "temp_pattern", redirect_pattern->temp_pattern))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "timeout", redirect_pattern->timeout))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "cmd_start", redirect_pattern->cmd_start))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "cmd_stop", redirect_pattern->cmd_stop))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "cmd_extra", redirect_pattern->cmd_extra))
return 0;
return 1;
}
/*
* irc_redirect_add_to_infolist: add a redirect in an infolist
* return 1 if ok, 0 if error
*/
int
irc_redirect_add_to_infolist (struct t_infolist *infolist,
struct t_irc_redirect *redirect)
{
struct t_infolist_item *ptr_item;
if (!infolist || !redirect)
return 0;
ptr_item = weechat_infolist_new_item (infolist);
if (!ptr_item)
return 0;
if (!weechat_infolist_new_var_pointer (ptr_item, "server", redirect->server))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "server_name", redirect->server->name))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "pattern", redirect->pattern))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "signal", redirect->signal))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "count", redirect->count))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "current_count", redirect->current_count))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "string", redirect->string))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "timeout", redirect->timeout))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "command", redirect->command))
return 0;
if (!weechat_infolist_new_var_time (ptr_item, "start_time", redirect->start_time))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "cmd_start", weechat_hashtable_get_string (redirect->cmd_start, "keys_values")))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "cmd_stop", weechat_hashtable_get_string (redirect->cmd_stop, "keys_values")))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "cmd_extra", weechat_hashtable_get_string (redirect->cmd_extra, "keys_values")))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "cmd_start_received", redirect->cmd_start_received))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "cmd_stop_received", redirect->cmd_stop_received))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "cmd_filter", weechat_hashtable_get_string (redirect->cmd_filter, "keys_values")))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "output", redirect->output))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "output_size", redirect->output_size))
return 0;
return 1;
}
/*
* irc_redirect_pattern_print_log: print redirect infos in log (usually for
* crash dump)
*/
void
irc_redirect_pattern_print_log ()
{
struct t_irc_redirect_pattern *ptr_redirect_pattern;
for (ptr_redirect_pattern = irc_redirect_patterns; ptr_redirect_pattern;
ptr_redirect_pattern = ptr_redirect_pattern->next_redirect)
{
weechat_log_printf ("");
weechat_log_printf ("[redirect_pattern (addr:0x%lx)]", ptr_redirect_pattern);
weechat_log_printf (" name . . . . . . . . : '%s'", ptr_redirect_pattern->name);
weechat_log_printf (" temp_pattern . . . . : %d", ptr_redirect_pattern->temp_pattern);
weechat_log_printf (" timeout. . . . . . . : %d", ptr_redirect_pattern->timeout);
weechat_log_printf (" cmd_start. . . . . . : '%s'", ptr_redirect_pattern->cmd_start);
weechat_log_printf (" cmd_stop . . . . . . : '%s'", ptr_redirect_pattern->cmd_stop);
weechat_log_printf (" cmd_extra. . . . . . : '%s'", ptr_redirect_pattern->cmd_extra);
weechat_log_printf (" prev_redirect. . . . : 0x%lx", ptr_redirect_pattern->prev_redirect);
weechat_log_printf (" next_redirect. . . . : 0x%lx", ptr_redirect_pattern->next_redirect);
}
}
/*
* irc_redirect_print_log: print redirect infos in log (usually for crash dump)
*/
void
irc_redirect_print_log (struct t_irc_server *server)
{
struct t_irc_redirect *ptr_redirect;
for (ptr_redirect = server->redirects; ptr_redirect;
ptr_redirect = ptr_redirect->next_redirect)
{
weechat_log_printf ("");
weechat_log_printf (" => redirect (addr:0x%lx):", ptr_redirect);
weechat_log_printf (" server. . . . . . . : 0x%lx ('%s')",
ptr_redirect->server, ptr_redirect->server->name);
weechat_log_printf (" pattern . . . . . . : '%s'", ptr_redirect->pattern);
weechat_log_printf (" signal. . . . . . . : '%s'", ptr_redirect->signal);
weechat_log_printf (" count . . . . . . . : %d", ptr_redirect->count);
weechat_log_printf (" current_count . . . : %d", ptr_redirect->current_count);
weechat_log_printf (" string. . . . . . . : '%s'", ptr_redirect->string);
weechat_log_printf (" timeout . . . . . . : %d", ptr_redirect->timeout);
weechat_log_printf (" command . . . . . . : '%s'", ptr_redirect->command);
weechat_log_printf (" start_time. . . . . : %ld", ptr_redirect->start_time);
weechat_log_printf (" cmd_start . . . . . : 0x%lx (hashtable: '%s')",
ptr_redirect->cmd_start,
weechat_hashtable_get_string (ptr_redirect->cmd_start, "keys_values"));
weechat_log_printf (" cmd_stop. . . . . . : 0x%lx (hashtable: '%s')",
ptr_redirect->cmd_stop,
weechat_hashtable_get_string (ptr_redirect->cmd_stop, "keys_values"));
weechat_log_printf (" cmd_extra . . . . . : 0x%lx (hashtable: '%s')",
ptr_redirect->cmd_extra,
weechat_hashtable_get_string (ptr_redirect->cmd_extra, "keys_values"));
weechat_log_printf (" cmd_start_received. : %d", ptr_redirect->cmd_start_received);
weechat_log_printf (" cmd_stop_received . : %d", ptr_redirect->cmd_stop_received);
weechat_log_printf (" cmd_filter. . . . . : 0x%lx (hashtable: '%s')",
ptr_redirect->cmd_filter,
weechat_hashtable_get_string (ptr_redirect->cmd_filter, "keys_values"));
weechat_log_printf (" output. . . . . . . : '%s'", ptr_redirect->output);
weechat_log_printf (" output_size . . . . : %d", ptr_redirect->output_size);
weechat_log_printf (" prev_redirect . . . : 0x%lx", ptr_redirect->prev_redirect);
weechat_log_printf (" next_redirect . . . : 0x%lx", ptr_redirect->next_redirect);
}
}
/*
* irc_redirect_pattern_hsignal_cb: callback for hsignal "irc_redirect_pattern"
* It is called when other plugins/scripts are
* creating a redirect pattern (irc plugin
* itself does not use this function)
*/
int
irc_redirect_pattern_hsignal_cb (void *data, const char *signal,
struct t_hashtable *hashtable)
{
const char *pattern, *str_timeout, *cmd_start, *cmd_stop, *cmd_extra;
char *error;
int number, timeout;
/* make C compiler happy */
(void) data;
(void) signal;
if (!hashtable)
return WEECHAT_RC_ERROR;
pattern = weechat_hashtable_get (hashtable, "pattern");
str_timeout = weechat_hashtable_get (hashtable, "timeout");
cmd_start = weechat_hashtable_get (hashtable, "cmd_start");
cmd_stop = weechat_hashtable_get (hashtable, "cmd_stop");
cmd_extra = weechat_hashtable_get (hashtable, "cmd_extra");
if (!pattern || !pattern[0])
{
weechat_printf (NULL,
_("%s%s: missing argument \"%s\" for redirect "
"pattern"),
weechat_prefix ("error"), IRC_PLUGIN_NAME, "pattern");
return WEECHAT_RC_ERROR;
}
if (!cmd_stop || !cmd_stop[0])
{
weechat_printf (NULL,
_("%s%s: missing argument \"%s\" for redirect "
"pattern"),
weechat_prefix ("error"), IRC_PLUGIN_NAME, "cmd_stop");
return WEECHAT_RC_ERROR;
}
timeout = 0;
if (str_timeout && str_timeout[0])
{
number = (int)strtol (str_timeout, &error, 10);
if (error && !error[0])
timeout = number;
}
/*
* create a temporary redirect pattern (it will be removed when a
* redirect will use it)
*/
irc_redirect_pattern_new (pattern, 1, timeout,
cmd_start, cmd_stop, cmd_extra);
return WEECHAT_RC_OK;
}
/*
* irc_redirect_command_hsignal_cb: callback for hsignal "irc_redirect_command"
* It is called when other plugins/scripts are
* redirecting an IRC command (irc plugin
* itself does not use this function)
*/
int
irc_redirect_command_hsignal_cb (void *data, const char *signal,
struct t_hashtable *hashtable)
{
const char *server, *pattern, *redirect_signal, *str_count, *string;
const char *str_timeout, *cmd_filter;
char *error;
struct t_irc_server *ptr_server;
int number, count, timeout;
/* make C compiler happy */
(void) data;
(void) signal;
if (!hashtable)
return WEECHAT_RC_ERROR;
server = weechat_hashtable_get (hashtable, "server");
pattern = weechat_hashtable_get (hashtable, "pattern");
redirect_signal = weechat_hashtable_get (hashtable, "signal");
str_count = weechat_hashtable_get (hashtable, "count");
string = weechat_hashtable_get (hashtable, "string");
str_timeout = weechat_hashtable_get (hashtable, "timeout");
cmd_filter = weechat_hashtable_get (hashtable, "cmd_filter");
if (!server || !server[0])
{
weechat_printf (NULL,
_("%s%s: missing argument \"%s\" for redirect"),
weechat_prefix ("error"), IRC_PLUGIN_NAME, "server");
return WEECHAT_RC_ERROR;
}
ptr_server = irc_server_search (server);
if (!ptr_server)
{
weechat_printf (NULL,
_("%s%s: server \"%s\" not found for redirect"),
weechat_prefix ("error"), IRC_PLUGIN_NAME, server);
return WEECHAT_RC_ERROR;
}
count = 1;
if (str_count && str_count[0])
{
number = (int)strtol (str_count, &error, 10);
if (error && !error[0])
count = number;
}
timeout = 0;
if (str_timeout && str_timeout[0])
{
number = (int)strtol (str_timeout, &error, 10);
if (error && !error[0])
timeout = number;
}
irc_redirect_new (ptr_server, pattern, redirect_signal,
count, string, timeout, cmd_filter);
return WEECHAT_RC_OK;
}
/*
* irc_redirect_init: create default redirect patterns
*/
void
irc_redirect_init ()
{
int i;
for (i = 0; irc_redirect_patterns_default[i].name; i++)
{
irc_redirect_pattern_new (irc_redirect_patterns_default[i].name,
0,
irc_redirect_patterns_default[i].timeout,
irc_redirect_patterns_default[i].cmd_start,
irc_redirect_patterns_default[i].cmd_stop,
irc_redirect_patterns_default[i].cmd_extra);
}
}
/*
* irc_redirect_end: free all redirect patterns
*/
void
irc_redirect_end ()
{
irc_redirect_pattern_free_all ();
}