summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/irc/CMakeLists.txt1
-rw-r--r--src/plugins/irc/Makefile.am2
-rw-r--r--src/plugins/irc/irc-channel.c2
-rw-r--r--src/plugins/irc/irc-debug.c3
-rw-r--r--src/plugins/irc/irc-raw.c43
-rw-r--r--src/plugins/irc/irc-raw.h21
-rw-r--r--src/plugins/irc/irc-redirect.c1272
-rw-r--r--src/plugins/irc/irc-redirect.h116
-rw-r--r--src/plugins/irc/irc-server.c129
-rw-r--r--src/plugins/irc/irc-server.h3
-rw-r--r--src/plugins/irc/irc-upgrade.c89
-rw-r--r--src/plugins/irc/irc-upgrade.h2
-rw-r--r--src/plugins/irc/irc.c9
13 files changed, 1643 insertions, 49 deletions
diff --git a/src/plugins/irc/CMakeLists.txt b/src/plugins/irc/CMakeLists.txt
index d751b90da..93ccf9cca 100644
--- a/src/plugins/irc/CMakeLists.txt
+++ b/src/plugins/irc/CMakeLists.txt
@@ -37,6 +37,7 @@ irc-msgbuffer.c irc-msgbuffer.h
irc-nick.c irc-nick.h
irc-protocol.c irc-protocol.h
irc-raw.c irc-raw.h
+irc-redirect.c irc-redirect.h
irc-sasl.c irc-sasl.h
irc-server.c irc-server.h
irc-upgrade.c irc-upgrade.h)
diff --git a/src/plugins/irc/Makefile.am b/src/plugins/irc/Makefile.am
index da7b374be..105c7eeb8 100644
--- a/src/plugins/irc/Makefile.am
+++ b/src/plugins/irc/Makefile.am
@@ -61,6 +61,8 @@ irc_la_SOURCES = irc.c \
irc-protocol.h \
irc-raw.c \
irc-raw.h \
+ irc-redirect.c \
+ irc-redirect.h \
irc-sasl.c \
irc-sasl.h \
irc-server.c \
diff --git a/src/plugins/irc/irc-channel.c b/src/plugins/irc/irc-channel.c
index 6271d59a6..6ffed14e0 100644
--- a/src/plugins/irc/irc-channel.c
+++ b/src/plugins/irc/irc-channel.c
@@ -920,7 +920,7 @@ irc_channel_print_log (struct t_irc_channel *channel)
struct t_irc_nick *ptr_nick;
weechat_log_printf ("");
- weechat_log_printf (" => channel %s (addr:0x%lx)]", channel->name, channel);
+ weechat_log_printf (" => channel %s (addr:0x%lx):", channel->name, channel);
weechat_log_printf (" type . . . . . . . . . . : %d", channel->type);
weechat_log_printf (" topic. . . . . . . . . . : '%s'", channel->topic);
weechat_log_printf (" modes. . . . . . . . . . : '%s'", channel->modes);
diff --git a/src/plugins/irc/irc-debug.c b/src/plugins/irc/irc-debug.c
index 3d8a1202c..c46d5a99d 100644
--- a/src/plugins/irc/irc-debug.c
+++ b/src/plugins/irc/irc-debug.c
@@ -27,6 +27,7 @@
#include "../weechat-plugin.h"
#include "irc.h"
#include "irc-debug.h"
+#include "irc-redirect.h"
#include "irc-server.h"
@@ -52,6 +53,8 @@ irc_debug_signal_debug_dump_cb (void *data, const char *signal,
irc_server_print_log ();
+ irc_redirect_pattern_print_log ();
+
weechat_log_printf ("");
weechat_log_printf ("***** End of \"%s\" plugin dump *****",
weechat_plugin->name);
diff --git a/src/plugins/irc/irc-raw.c b/src/plugins/irc/irc-raw.c
index d2e5764e4..ba7401d36 100644
--- a/src/plugins/irc/irc-raw.c
+++ b/src/plugins/irc/irc-raw.c
@@ -211,10 +211,10 @@ irc_raw_message_add_to_list (time_t date, const char *prefix,
*/
struct t_irc_raw_message *
-irc_raw_message_add (struct t_irc_server *server, int send, int modified,
+irc_raw_message_add (struct t_irc_server *server, int flags,
const char *message)
{
- char *buf, *buf2, prefix[256];
+ char *buf, *buf2, prefix[256], prefix_arrow[16];
const unsigned char *ptr_buf;
const char *hexa = "0123456789ABCDEF";
int pos_buf, pos_buf2, char_size, i;
@@ -247,16 +247,43 @@ irc_raw_message_add (struct t_irc_server *server, int send, int modified,
}
buf2[pos_buf2] = '\0';
}
+
+ /* build prefix with arrow */
+ prefix_arrow[0] = '\0';
+ switch (flags & (IRC_RAW_FLAG_RECV | IRC_RAW_FLAG_SEND
+ | IRC_RAW_FLAG_MODIFIED | IRC_RAW_FLAG_REDIRECT))
+ {
+ case IRC_RAW_FLAG_RECV:
+ strcpy (prefix_arrow, IRC_RAW_PREFIX_RECV);
+ break;
+ case IRC_RAW_FLAG_RECV | IRC_RAW_FLAG_MODIFIED:
+ strcpy (prefix_arrow, IRC_RAW_PREFIX_RECV_MODIFIED);
+ break;
+ case IRC_RAW_FLAG_RECV | IRC_RAW_FLAG_REDIRECT:
+ strcpy (prefix_arrow, IRC_RAW_PREFIX_RECV_REDIRECT);
+ break;
+ case IRC_RAW_FLAG_SEND:
+ strcpy (prefix_arrow, IRC_RAW_PREFIX_SEND);
+ break;
+ case IRC_RAW_FLAG_SEND | IRC_RAW_FLAG_MODIFIED:
+ strcpy (prefix_arrow, IRC_RAW_PREFIX_SEND_MODIFIED);
+ break;
+ default:
+ if (flags && IRC_RAW_FLAG_RECV)
+ strcpy (prefix_arrow, IRC_RAW_PREFIX_RECV);
+ else
+ strcpy (prefix_arrow, IRC_RAW_PREFIX_SEND);
+ break;
+ }
+
snprintf (prefix, sizeof (prefix), "%s%s%s%s%s",
(server) ? weechat_color ("chat_server") : "",
(server) ? server->name : "",
(server) ? " " : "",
- (send) ?
+ (flags & IRC_RAW_FLAG_SEND) ?
weechat_color ("chat_prefix_quit") :
weechat_color ("chat_prefix_join"),
- (send) ?
- ((modified) ? IRC_RAW_PREFIX_SEND_MOD : IRC_RAW_PREFIX_SEND) :
- ((modified) ? IRC_RAW_PREFIX_RECV_MOD : IRC_RAW_PREFIX_RECV));
+ prefix_arrow);
new_raw_message = irc_raw_message_add_to_list (time (NULL),
prefix,
@@ -275,7 +302,7 @@ irc_raw_message_add (struct t_irc_server *server, int send, int modified,
*/
void
-irc_raw_print (struct t_irc_server *server, int send, int modified,
+irc_raw_print (struct t_irc_server *server, int flags,
const char *message)
{
struct t_irc_raw_message *new_raw_message;
@@ -287,7 +314,7 @@ irc_raw_print (struct t_irc_server *server, int send, int modified,
if (!irc_raw_buffer && (weechat_irc_plugin->debug >= 1))
irc_raw_open (0);
- new_raw_message = irc_raw_message_add (server, send, modified, message);
+ new_raw_message = irc_raw_message_add (server, flags, message);
if (new_raw_message)
{
if (irc_raw_buffer)
diff --git a/src/plugins/irc/irc-raw.h b/src/plugins/irc/irc-raw.h
index 1a5cfd61c..bd913e3b0 100644
--- a/src/plugins/irc/irc-raw.h
+++ b/src/plugins/irc/irc-raw.h
@@ -20,11 +20,18 @@
#ifndef __WEECHAT_IRC_RAW_H
#define __WEECHAT_IRC_RAW_H 1
-#define IRC_RAW_BUFFER_NAME "irc_raw"
-#define IRC_RAW_PREFIX_RECV "-->"
-#define IRC_RAW_PREFIX_RECV_MOD "==>"
-#define IRC_RAW_PREFIX_SEND "<--"
-#define IRC_RAW_PREFIX_SEND_MOD "<=="
+#define IRC_RAW_BUFFER_NAME "irc_raw"
+
+#define IRC_RAW_PREFIX_RECV "-->"
+#define IRC_RAW_PREFIX_RECV_MODIFIED "==>"
+#define IRC_RAW_PREFIX_RECV_REDIRECT "R>>"
+#define IRC_RAW_PREFIX_SEND "<--"
+#define IRC_RAW_PREFIX_SEND_MODIFIED "<=="
+
+#define IRC_RAW_FLAG_RECV 1
+#define IRC_RAW_FLAG_SEND 2
+#define IRC_RAW_FLAG_MODIFIED 4
+#define IRC_RAW_FLAG_REDIRECT 8
struct t_irc_raw_message
{
@@ -45,8 +52,8 @@ extern void irc_raw_open (int switch_to_buffer);
extern struct t_irc_raw_message *irc_raw_message_add_to_list (time_t date,
const char *prefix,
const char *message);
-extern void irc_raw_print (struct t_irc_server *server, int send,
- int modified, const char *message);
+extern void irc_raw_print (struct t_irc_server *server, int flags,
+ const char *message);
extern void irc_raw_message_free_all ();
extern int irc_raw_add_to_infolist (struct t_infolist *infolist,
struct t_irc_raw_message *raw_message);
diff --git a/src/plugins/irc/irc-redirect.c b/src/plugins/irc/irc-redirect.c
new file mode 100644
index 000000000..d16bc89ab
--- /dev/null
+++ b/src/plugins/irc/irc-redirect.c
@@ -0,0 +1,1272 @@
+/*
+ * Copyright (C) 2010 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 <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:3,403:3,442:3,479:3",
+ "329:3",
+ 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:3",
+ "368:3,403:3,442:3,479:3",
+ 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:3",
+ "349:3,403:3,442:3,472,479:3,482:3",
+ 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:3",
+ "347:3,403:3,442:3,472,479:3,482:3",
+ 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:2,221:3,403:3,501,502",
+ NULL,
+ NULL, NULL,
+ },
+ { "names", 0, 0,
+ /*
+ * names: start: 353: list of nicks on channel
+ * stop: 366: end of /names list
+ * extra; -
+ */
+ "353:4",
+ "366:3",
+ 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:3,332:3,403:3",
+ "333:3",
+ NULL, NULL,
+ },
+ { "userhost", 0, 0,
+ /*
+ * userhost: start: 401: no such nick/channel
+ * stop: 302: userhost
+ * 461: not enough parameters
+ * extra: -
+ */
+ "401:3",
+ "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:3,354,401:3",
+ "315:3,403:3",
+ 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:3",
+ "318:3,401:3,402:3,431:3,461",
+ "318:3",
+ NULL, NULL,
+ },
+ { "whowas", 0, 0,
+ /*
+ * whowas: start: 314: whowas (user)
+ * 406: there was no such nickname
+ * stop: 369: end of whowas
+ * extra: -
+ */
+ "314:3,406:3",
+ "369:3",
+ 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);
+
+ irc_redirect_print_log (server);
+
+ 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,
+ char **message_argv, int message_argc,
+ const char *command,
+ 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 (*value >= message_argc)
+ return 0;
+
+ if (strcmp (message_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)
+{
+ /*
+ * 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);
+ redirect->output = realloc (redirect->output, redirect->output_size);
+ if (redirect->output)
+ 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)
+{
+ struct t_irc_redirect *ptr_redirect, *ptr_next_redirect;
+ int rc, match_stop, message_argc;
+ char **message_argv;
+
+ if (!server || !server->redirects || !message || !command)
+ return 0;
+
+ rc = 0;
+
+ message_argv = weechat_string_split (message, " ", 0, 0, &message_argc);
+
+ 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,
+ message_argv,
+ message_argc,
+ command,
+ 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,
+ message_argv,
+ message_argc,
+ command,
+ 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,
+ message_argv,
+ message_argc,
+ command,
+ 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,
+ message_argv,
+ message_argc,
+ command,
+ 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 (message_argv)
+ weechat_string_free_split (message_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_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 ();
+}
diff --git a/src/plugins/irc/irc-redirect.h b/src/plugins/irc/irc-redirect.h
new file mode 100644
index 000000000..77f54d8a0
--- /dev/null
+++ b/src/plugins/irc/irc-redirect.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2010 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/>.
+ */
+
+#ifndef __WEECHAT_IRC_REDIRECT_H
+#define __WEECHAT_IRC_REDIRECT_H 1
+
+#define IRC_REDIRECT_TIMEOUT_DEFAULT 60
+
+struct t_irc_server;
+
+/* template for redirections (IRC plugin creates some templates at startup) */
+
+struct t_irc_redirect_pattern
+{
+ char *name; /* name */
+ int temp_pattern; /* temporary pattern (created by */
+ /* external plugin/script) */
+ int timeout; /* default timeout (in seconds) */
+ char *cmd_start; /* command(s) starting redirection */
+ /* (can be NULL or empty) */
+ char *cmd_stop; /* command(s) stopping redirection */
+ /* (not NULL, at least one command) */
+ char *cmd_extra; /* extra command(s) after end commands */
+ struct t_irc_redirect_pattern *prev_redirect; /* link to previous redir. */
+ struct t_irc_redirect_pattern *next_redirect; /* link to next redir. */
+};
+
+/* command redirection (created when a command is redirected) */
+
+struct t_irc_redirect
+{
+ struct t_irc_server *server; /* server for this redirection */
+ char *pattern; /* name of pattern used for this redir. */
+ char *signal; /* name of signal sent after redirection */
+ int count; /* how many times redirect is executed */
+ int current_count; /* current count */
+ char *string; /* we search this string in messages */
+ int timeout; /* timeout (in seconds) */
+ char *command; /* command sent to server, which is */
+ /* redirected */
+ time_t start_time; /* time when command is sent to server */
+ /* (this is begining of this redirect) */
+ struct t_hashtable *cmd_start; /* command(s) starting redirection */
+ /* (can be NULL or empty) */
+ struct t_hashtable *cmd_stop; /* command(s) stopping redirection */
+ /* (not NULL, at least one command) */
+ struct t_hashtable *cmd_extra; /* extra command(s) after end command(s) */
+ int cmd_start_received; /* one of start commands received ? */
+ int cmd_stop_received; /* one of stop commands received ? */
+ struct t_hashtable *cmd_filter; /* command(s) to add to output */
+ /* (if NULL or empty, all cmds are sent) */
+ char *output; /* output of IRC command (gradually */
+ /* filled with IRC messages) */
+ int output_size; /* size (in bytes) of output string */
+ struct t_irc_redirect *prev_redirect; /* link to previous redirect */
+ struct t_irc_redirect *next_redirect; /* link to next redirect */
+};
+
+extern struct t_irc_redirect_pattern *irc_redirect_patterns;
+extern struct t_irc_redirect_pattern *last_irc_redirect_pattern;
+
+extern 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);
+extern 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);
+extern struct t_irc_redirect *irc_redirect_search_available (struct t_irc_server *server);
+extern void irc_redirect_init_command (struct t_irc_redirect *redirect,
+ const char *command);
+extern void irc_redirect_stop (struct t_irc_redirect *redirect,
+ const char *error);
+extern int irc_redirect_message (struct t_irc_server *server,
+ const char *message, const char *command);
+extern void irc_redirect_free (struct t_irc_redirect *redirect);
+extern void irc_redirect_free_all (struct t_irc_server *server);
+extern int irc_redirect_pattern_add_to_infolist (struct t_infolist *infolist,
+ struct t_irc_redirect_pattern *redirect_pattern);
+extern int irc_redirect_add_to_infolist (struct t_infolist *infolist,
+ struct t_irc_redirect *redirect);
+extern void irc_redirect_pattern_print_log ();
+extern void irc_redirect_print_log (struct t_irc_server *server);
+extern int irc_redirect_pattern_hsignal_cb (void *data, const char *signal,
+ struct t_hashtable *hashtable);
+extern int irc_redirect_command_hsignal_cb (void *data, const char *signal,
+ struct t_hashtable *hashtable);
+extern void irc_redirect_init ();
+extern void irc_redirect_end ();
+
+#endif /* __WEECHAT_IRC_REDIRECT_H */
diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c
index f26615784..6ffaeefd0 100644
--- a/src/plugins/irc/irc-server.c
+++ b/src/plugins/irc/irc-server.c
@@ -52,6 +52,7 @@
#include "irc-nick.h"
#include "irc-protocol.h"
#include "irc-raw.h"
+#include "irc-redirect.h"
#include "irc-sasl.h"
@@ -467,6 +468,8 @@ irc_server_alloc (const char *name)
new_server->outqueue[i] = NULL;
new_server->last_outqueue[i] = NULL;
}
+ new_server->redirects = NULL;
+ new_server->last_redirect = NULL;
new_server->buffer = NULL;
new_server->buffer_as_string = NULL;
new_server->channels = NULL;
@@ -768,7 +771,8 @@ irc_server_apply_command_line_options (struct t_irc_server *server,
void
irc_server_outqueue_add (struct t_irc_server *server, int priority,
const char *command, const char *msg1,
- const char *msg2, int modified, const char *tags)
+ const char *msg2, int modified, const char *tags,
+ struct t_irc_redirect *redirect)
{
struct t_irc_outqueue *new_outqueue;
@@ -780,6 +784,7 @@ irc_server_outqueue_add (struct t_irc_server *server, int priority,
new_outqueue->message_after_mod = (msg2) ? strdup (msg2) : NULL;
new_outqueue->modified = modified;
new_outqueue->tags = (tags) ? strdup (tags) : NULL;
+ new_outqueue->redirect = redirect;
new_outqueue->prev_outqueue = server->last_outqueue[priority];
new_outqueue->next_outqueue = NULL;
@@ -902,6 +907,7 @@ irc_server_free_data (struct t_irc_server *server)
{
irc_server_outqueue_free_all (server, i);
}
+ irc_redirect_free_all (server);
if (server->channels)
irc_channel_free_all (server);
if (server->buffer_as_string)
@@ -1267,7 +1273,7 @@ irc_server_outqueue_send (struct t_irc_server *server)
'\r');
if (pos)
pos[0] = '\0';
- irc_raw_print (server, 1, 0,
+ irc_raw_print (server, IRC_RAW_FLAG_SEND,
server->outqueue[priority]->message_before_mod);
if (pos)
pos[0] = '\r';
@@ -1278,7 +1284,8 @@ irc_server_outqueue_send (struct t_irc_server *server)
'\r');
if (pos)
pos[0] = '\0';
- irc_raw_print (server, 1, server->outqueue[priority]->modified,
+ irc_raw_print (server, IRC_RAW_FLAG_SEND |
+ ((server->outqueue[priority]->modified) ? IRC_RAW_FLAG_MODIFIED : 0),
server->outqueue[priority]->message_after_mod);
if (pos)
pos[0] = '\r';
@@ -1300,6 +1307,13 @@ irc_server_outqueue_send (struct t_irc_server *server)
irc_server_send (server, server->outqueue[priority]->message_after_mod,
strlen (server->outqueue[priority]->message_after_mod));
server->last_user_message = time_now;
+
+ /* start redirection if redirect is set */
+ if (server->outqueue[priority]->redirect)
+ {
+ irc_redirect_init_command (server->outqueue[priority]->redirect,
+ server->outqueue[priority]->message_after_mod);
+ }
}
irc_server_outqueue_free (server, priority,
server->outqueue[priority]);
@@ -1468,16 +1482,11 @@ irc_server_parse_message_to_hashtable (const char *message)
if (!hashtable)
return NULL;
- weechat_hashtable_set (hashtable, "nick",
- (nick) ? (void *)nick : (void *)empty_str);
- weechat_hashtable_set (hashtable, "host",
- (host) ? (void *)host : (void *)empty_str);
- weechat_hashtable_set (hashtable, "command",
- (command) ? (void *)command : (void *)empty_str);
- weechat_hashtable_set (hashtable, "channel",
- (channel) ? (void *)channel : (void *)empty_str);
- weechat_hashtable_set (hashtable, "arguments",
- (arguments) ? (void *)arguments : (void *)empty_str);
+ weechat_hashtable_set (hashtable, "nick", (nick) ? nick : empty_str);
+ weechat_hashtable_set (hashtable, "host", (host) ? host : empty_str);
+ weechat_hashtable_set (hashtable, "command", (command) ? command : empty_str);
+ weechat_hashtable_set (hashtable, "channel", (channel) ? channel : empty_str);
+ weechat_hashtable_set (hashtable, "arguments", (arguments) ? arguments : empty_str);
return hashtable;
}
@@ -1505,6 +1514,7 @@ irc_server_send_one_msg (struct t_irc_server *server, int flags,
char str_modifier[64], modifier_data[256];
int rc, queue_msg, add_to_queue, first_message, anti_flood;
time_t time_now;
+ struct t_irc_redirect *ptr_redirect;
rc = 1;
@@ -1596,6 +1606,8 @@ irc_server_send_one_msg (struct t_irc_server *server, int flags,
tags_to_send = irc_server_get_tags_to_send (tags);
+ ptr_redirect = irc_redirect_search_available (server);
+
if (add_to_queue > 0)
{
/* queue message (do not send anything now) */
@@ -1603,14 +1615,21 @@ irc_server_send_one_msg (struct t_irc_server *server, int flags,
(new_msg && first_message) ? message : NULL,
buffer,
(new_msg) ? 1 : 0,
- tags_to_send);
+ tags_to_send,
+ ptr_redirect);
}
else
{
if (first_message)
- irc_raw_print (server, 1, 0, message);
+ {
+ irc_raw_print (server, IRC_RAW_FLAG_SEND, message);
+ }
if (new_msg)
- irc_raw_print (server, 1, 1, ptr_msg);
+ {
+ irc_raw_print (server,
+ IRC_RAW_FLAG_SEND | IRC_RAW_FLAG_MODIFIED,
+ ptr_msg);
+ }
/* send signal with command that will be sent to server */
irc_server_send_signal (server, "irc_out",
@@ -1629,6 +1648,8 @@ irc_server_send_one_msg (struct t_irc_server *server, int flags,
if (queue_msg > 0)
server->last_user_message = time_now;
}
+ if (ptr_redirect)
+ irc_redirect_init_command (ptr_redirect, buffer);
}
if (tags_to_send)
@@ -1648,7 +1669,10 @@ irc_server_send_one_msg (struct t_irc_server *server, int flags,
free (msg_encoded);
}
else
- irc_raw_print (server, 1, 1, _("(message dropped)"));
+ {
+ irc_raw_print (server, IRC_RAW_FLAG_SEND | IRC_RAW_FLAG_MODIFIED,
+ _("(message dropped)"));
+ }
if (nick)
free (nick);
@@ -1849,7 +1873,8 @@ irc_server_msgq_flush ()
if (ptr_data[0])
{
- irc_raw_print (irc_recv_msgq->server, 0, 0, ptr_data);
+ irc_raw_print (irc_recv_msgq->server, IRC_RAW_FLAG_RECV,
+ ptr_data);
irc_server_parse_message (ptr_data, NULL, NULL, &command,
NULL, NULL);
@@ -1882,8 +1907,11 @@ irc_server_msgq_flush ()
pos[0] = '\0';
if (new_msg)
- irc_raw_print (irc_recv_msgq->server, 0, 1,
+ {
+ irc_raw_print (irc_recv_msgq->server,
+ IRC_RAW_FLAG_RECV | IRC_RAW_FLAG_MODIFIED,
ptr_msg);
+ }
irc_server_parse_message (ptr_msg, &nick, &host,
&command, &channel,
@@ -1926,11 +1954,22 @@ irc_server_msgq_flush ()
"?");
/* parse and execute command */
- irc_protocol_recv_command (irc_recv_msgq->server,
- (msg_decoded_without_color) ?
- msg_decoded_without_color : ((msg_decoded) ? msg_decoded : ptr_msg),
- command,
- channel);
+ if (irc_redirect_message (irc_recv_msgq->server,
+ (msg_decoded_without_color) ?
+ msg_decoded_without_color : ((msg_decoded) ? msg_decoded : ptr_msg),
+ command))
+ {
+ /* message redirected, we'll not display it! */
+ }
+ else
+ {
+ /* message not redirected, display it */
+ irc_protocol_recv_command (irc_recv_msgq->server,
+ (msg_decoded_without_color) ?
+ msg_decoded_without_color : ((msg_decoded) ? msg_decoded : ptr_msg),
+ command,
+ channel);
+ }
if (nick)
free (nick);
@@ -1956,7 +1995,8 @@ irc_server_msgq_flush ()
}
else
{
- irc_raw_print (irc_recv_msgq->server, 0, 1,
+ irc_raw_print (irc_recv_msgq->server,
+ IRC_RAW_FLAG_RECV | IRC_RAW_FLAG_MODIFIED,
_("(message dropped)"));
}
if (new_msg)
@@ -2125,7 +2165,8 @@ int
irc_server_timer_cb (void *data, int remaining_calls)
{
struct t_irc_server *ptr_server;
- time_t new_time;
+ struct t_irc_redirect *ptr_redirect, *ptr_next_redirect;
+ time_t current_time;
static struct timeval tv;
int away_check;
@@ -2133,7 +2174,7 @@ irc_server_timer_cb (void *data, int remaining_calls)
(void) data;
(void) remaining_calls;
- new_time = time (NULL);
+ current_time = time (NULL);
for (ptr_server = irc_servers; ptr_server;
ptr_server = ptr_server->next_server)
@@ -2141,7 +2182,7 @@ irc_server_timer_cb (void *data, int remaining_calls)
/* check if reconnection is pending */
if ((!ptr_server->is_connected)
&& (ptr_server->reconnect_start > 0)
- && (new_time >= (ptr_server->reconnect_start + ptr_server->reconnect_delay)))
+ && (current_time >= (ptr_server->reconnect_start + ptr_server->reconnect_delay)))
{
irc_server_reconnect (ptr_server);
}
@@ -2155,7 +2196,7 @@ irc_server_timer_cb (void *data, int remaining_calls)
/* check for lag */
if ((weechat_config_integer (irc_config_network_lag_check) > 0)
&& (ptr_server->lag_check_time.tv_sec == 0)
- && (new_time >= ptr_server->lag_next_check))
+ && (current_time >= ptr_server->lag_next_check))
{
irc_server_sendf (ptr_server, 0, NULL, "PING %s",
(ptr_server->current_address) ?
@@ -2171,7 +2212,7 @@ irc_server_timer_cb (void *data, int remaining_calls)
if (away_check > 0)
{
if ((ptr_server->last_away_check == 0)
- || (new_time >= ptr_server->last_away_check + (away_check * 60)))
+ || (current_time >= ptr_server->last_away_check + (away_check * 60)))
{
irc_server_check_away (ptr_server);
}
@@ -2180,7 +2221,7 @@ irc_server_timer_cb (void *data, int remaining_calls)
/* check if it's time to autojoin channels (after command delay) */
if ((ptr_server->command_time != 0)
- && (new_time >= ptr_server->command_time +
+ && (current_time >= ptr_server->command_time +
IRC_SERVER_OPTION_INTEGER(ptr_server, IRC_SERVER_OPTION_COMMAND_DELAY)))
{
irc_server_autojoin_channels (ptr_server);
@@ -2195,10 +2236,10 @@ irc_server_timer_cb (void *data, int remaining_calls)
&tv);
/* refresh lag item if needed */
if (((ptr_server->lag_last_refresh == 0)
- || (new_time >= ptr_server->lag_last_refresh + weechat_config_integer (irc_config_network_lag_refresh_interval)))
+ || (current_time >= ptr_server->lag_last_refresh + weechat_config_integer (irc_config_network_lag_refresh_interval)))
&& (ptr_server->lag >= weechat_config_integer (irc_config_network_lag_min_show)))
{
- ptr_server->lag_last_refresh = new_time;
+ ptr_server->lag_last_refresh = current_time;
weechat_bar_item_update ("lag");
}
/* lag timeout? => disconnect */
@@ -2212,6 +2253,21 @@ irc_server_timer_cb (void *data, int remaining_calls)
irc_server_disconnect (ptr_server, 0, 1);
}
}
+
+ /* remove redirects if timeout occurs */
+ ptr_redirect = ptr_server->redirects;
+ while (ptr_redirect)
+ {
+ ptr_next_redirect = ptr_redirect->next_redirect;
+
+ if ((ptr_redirect->start_time > 0)
+ && (ptr_redirect->start_time + ptr_redirect->timeout < current_time))
+ {
+ irc_redirect_stop (ptr_redirect, "timeout");
+ }
+
+ ptr_redirect = ptr_next_redirect;
+ }
}
}
}
@@ -2285,6 +2341,9 @@ irc_server_close_connection (struct t_irc_server *server)
irc_server_outqueue_free_all (server, i);
}
+ /* remove all redirects */
+ irc_redirect_free_all (server);
+
/* server is now disconnected */
server->is_connected = 0;
server->ssl_connected = 0;
@@ -4230,6 +4289,8 @@ irc_server_print_log ()
weechat_log_printf (" outqueue[%02d] . . . . : 0x%lx", i, ptr_server->outqueue[i]);
weechat_log_printf (" last_outqueue[%02d]. . : 0x%lx", i, ptr_server->last_outqueue[i]);
}
+ weechat_log_printf (" redirects. . . . . . : 0x%lx", ptr_server->redirects);
+ weechat_log_printf (" last_redirect. . . . : 0x%lx", ptr_server->last_redirect);
weechat_log_printf (" buffer . . . . . . . : 0x%lx", ptr_server->buffer);
weechat_log_printf (" buffer_as_string . . : 0x%lx", ptr_server->buffer_as_string);
weechat_log_printf (" channels . . . . . . : 0x%lx", ptr_server->channels);
@@ -4237,6 +4298,8 @@ irc_server_print_log ()
weechat_log_printf (" prev_server. . . . . : 0x%lx", ptr_server->prev_server);
weechat_log_printf (" next_server. . . . . : 0x%lx", ptr_server->next_server);
+ irc_redirect_print_log (ptr_server);
+
for (ptr_channel = ptr_server->channels; ptr_channel;
ptr_channel = ptr_channel->next_channel)
{
diff --git a/src/plugins/irc/irc-server.h b/src/plugins/irc/irc-server.h
index d841c761c..251afb337 100644
--- a/src/plugins/irc/irc-server.h
+++ b/src/plugins/irc/irc-server.h
@@ -108,6 +108,7 @@ struct t_irc_outqueue
char *message_after_mod; /* msg after modifier(s) */
int modified; /* msg was modified by modifier(s) */
char *tags; /* tags (used by Relay plugin) */
+ struct t_irc_redirect *redirect; /* command redirection */
struct t_irc_outqueue *next_outqueue; /* link to next msg in queue */
struct t_irc_outqueue *prev_outqueue; /* link to prev msg in queue */
};
@@ -169,6 +170,8 @@ struct t_irc_server
struct t_irc_outqueue *outqueue[2]; /* queue for outgoing messages */
/* with 2 priorities (high/low) */
struct t_irc_outqueue *last_outqueue[2]; /* last outgoing message */
+ struct t_irc_redirect *redirects; /* command redirections */
+ struct t_irc_redirect *last_redirect; /* last command redirection */
struct t_gui_buffer *buffer; /* GUI buffer allocated for server */
char *buffer_as_string; /* used to return buffer info */
struct t_irc_channel *channels; /* opened channels on server */
diff --git a/src/plugins/irc/irc-upgrade.c b/src/plugins/irc/irc-upgrade.c
index de5aa11d5..1e5d48c29 100644
--- a/src/plugins/irc/irc-upgrade.c
+++ b/src/plugins/irc/irc-upgrade.c
@@ -34,6 +34,7 @@
#include "irc-channel.h"
#include "irc-nick.h"
#include "irc-raw.h"
+#include "irc-redirect.h"
struct t_irc_server *irc_upgrade_current_server = NULL;
@@ -51,6 +52,8 @@ irc_upgrade_save_all_data (struct t_upgrade_file *upgrade_file)
struct t_irc_server *ptr_server;
struct t_irc_channel *ptr_channel;
struct t_irc_nick *ptr_nick;
+ struct t_irc_redirect *ptr_redirect;
+ struct t_irc_redirect_pattern *ptr_redirect_pattern;
struct t_irc_raw_message *ptr_raw_message;
int rc;
@@ -73,6 +76,7 @@ irc_upgrade_save_all_data (struct t_upgrade_file *upgrade_file)
if (!rc)
return 0;
+ /* save server channels and nicks */
for (ptr_channel = ptr_server->channels; ptr_channel;
ptr_channel = ptr_channel->next_channel)
{
@@ -112,6 +116,27 @@ irc_upgrade_save_all_data (struct t_upgrade_file *upgrade_file)
return 0;
}
}
+
+ /* save server redirects */
+ for (ptr_redirect = ptr_server->redirects; ptr_redirect;
+ ptr_redirect = ptr_redirect->next_redirect)
+ {
+ /* save channel */
+ infolist = weechat_infolist_new ();
+ if (!infolist)
+ return 0;
+ if (!irc_redirect_add_to_infolist (infolist, ptr_redirect))
+ {
+ weechat_infolist_free (infolist);
+ return 0;
+ }
+ rc = weechat_upgrade_write_object (upgrade_file,
+ IRC_UPGRADE_TYPE_REDIRECT,
+ infolist);
+ weechat_infolist_free (infolist);
+ if (!rc)
+ return 0;
+ }
}
/* save raw messages */
@@ -134,6 +159,30 @@ irc_upgrade_save_all_data (struct t_upgrade_file *upgrade_file)
return 0;
}
+ /* save redirect patterns */
+ for (ptr_redirect_pattern = irc_redirect_patterns; ptr_redirect_pattern;
+ ptr_redirect_pattern = ptr_redirect_pattern->next_redirect)
+ {
+ /* save only temporary patterns (created by other plugins/scripts) */
+ if (ptr_redirect_pattern->temp_pattern)
+ {
+ infolist = weechat_infolist_new ();
+ if (!infolist)
+ return 0;
+ if (!irc_redirect_pattern_add_to_infolist (infolist, ptr_redirect_pattern))
+ {
+ weechat_infolist_free (infolist);
+ return 0;
+ }
+ rc = weechat_upgrade_write_object (upgrade_file,
+ IRC_UPGRADE_TYPE_REDIRECT_PATTERN,
+ infolist);
+ weechat_infolist_free (infolist);
+ if (!rc)
+ return 0;
+ }
+ }
+
return 1;
}
@@ -204,6 +253,7 @@ irc_upgrade_read_cb (void *data,
char *buf, option_name[64];
const char *buffer_name, *str, *nick;
struct t_irc_nick *ptr_nick;
+ struct t_irc_redirect *ptr_redirect;
struct t_gui_buffer *ptr_buffer;
/* make C compiler happy */
@@ -382,6 +432,45 @@ irc_upgrade_read_cb (void *data,
}
}
break;
+ case IRC_UPGRADE_TYPE_REDIRECT:
+ if (irc_upgrade_current_server)
+ {
+ ptr_redirect = irc_redirect_new_with_commands (
+ irc_upgrade_current_server,
+ weechat_infolist_string (infolist, "pattern"),
+ weechat_infolist_string (infolist, "signal"),
+ weechat_infolist_integer (infolist, "count"),
+ weechat_infolist_string (infolist, "string"),
+ weechat_infolist_integer (infolist, "timeout"),
+ weechat_infolist_string (infolist, "cmd_start"),
+ weechat_infolist_string (infolist, "cmd_stop"),
+ weechat_infolist_string (infolist, "cmd_extra"),
+ weechat_infolist_string (infolist, "cmd_filter"));
+ if (ptr_redirect)
+ {
+ ptr_redirect->current_count = weechat_infolist_integer (infolist, "current_count");
+ str = weechat_infolist_string (infolist, "command");
+ if (str)
+ ptr_redirect->command = strdup (str);
+ ptr_redirect->start_time = weechat_infolist_time (infolist, "start_time");
+ ptr_redirect->cmd_start_received = weechat_infolist_integer (infolist, "cmd_start_received");
+ ptr_redirect->cmd_stop_received = weechat_infolist_integer (infolist, "cmd_stop_received");
+ str = weechat_infolist_string (infolist, "output");
+ if (str)
+ ptr_redirect->output = strdup (str);
+ ptr_redirect->output_size = weechat_infolist_integer (infolist, "output_size");
+ }
+ }
+ break;
+ case IRC_UPGRADE_TYPE_REDIRECT_PATTERN:
+ irc_redirect_pattern_new (
+ weechat_infolist_string (infolist, "name"),
+ weechat_infolist_integer (infolist, "temp_pattern"),
+ weechat_infolist_integer (infolist, "timeout"),
+ weechat_infolist_string (infolist, "cmd_start"),
+ weechat_infolist_string (infolist, "cmd_stop"),
+ weechat_infolist_string (infolist, "cmd_extra"));
+ break;
case IRC_UPGRADE_TYPE_RAW_MESSAGE:
irc_raw_message_add_to_list (weechat_infolist_time (infolist, "date"),
weechat_infolist_string (infolist, "prefix"),
diff --git a/src/plugins/irc/irc-upgrade.h b/src/plugins/irc/irc-upgrade.h
index 431c9d0bb..724fd15c9 100644
--- a/src/plugins/irc/irc-upgrade.h
+++ b/src/plugins/irc/irc-upgrade.h
@@ -30,6 +30,8 @@ enum t_irc_upgrade_type
IRC_UPGRADE_TYPE_CHANNEL,
IRC_UPGRADE_TYPE_NICK,
IRC_UPGRADE_TYPE_RAW_MESSAGE,
+ IRC_UPGRADE_TYPE_REDIRECT_PATTERN,
+ IRC_UPGRADE_TYPE_REDIRECT,
};
extern int irc_upgrade_save ();
diff --git a/src/plugins/irc/irc.c b/src/plugins/irc/irc.c
index 61737e64f..68e3abb3c 100644
--- a/src/plugins/irc/irc.c
+++ b/src/plugins/irc/irc.c
@@ -40,6 +40,7 @@
#include "irc-channel.h"
#include "irc-nick.h"
#include "irc-raw.h"
+#include "irc-redirect.h"
#include "irc-upgrade.h"
@@ -164,6 +165,8 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[])
irc_info_init ();
+ irc_redirect_init ();
+
/* hook some signals */
irc_debug_init ();
weechat_hook_signal ("quit", &irc_signal_quit_cb, NULL);
@@ -173,6 +176,10 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[])
weechat_hook_signal ("xfer_send_accept_resume", &irc_server_xfer_send_accept_resume_cb, NULL);
weechat_hook_signal ("irc_input_send", &irc_input_send_cb, NULL);
+ /* hook hsignals for redirection */
+ weechat_hook_hsignal ("irc_redirect_pattern", &irc_redirect_pattern_hsignal_cb, NULL);
+ weechat_hook_hsignal ("irc_redirect_command", &irc_redirect_command_hsignal_cb, NULL);
+
/* modifiers */
weechat_hook_modifier ("irc_color_decode", &irc_color_modifier_cb, NULL);
weechat_hook_modifier ("irc_color_encode", &irc_color_modifier_cb, NULL);
@@ -262,5 +269,7 @@ weechat_plugin_end (struct t_weechat_plugin *plugin)
irc_config_free ();
+ irc_redirect_end ();
+
return WEECHAT_RC_OK;
}