summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
authorSebastien Helleu <flashcode@flashtux.org>2007-10-31 18:30:21 +0100
committerSebastien Helleu <flashcode@flashtux.org>2007-10-31 18:30:21 +0100
commit90262cbcfea07e26236f15b46db02e73e8a43fc3 (patch)
tree696afac6bb8b7d8b8d395b98cab47c79c7d548b7 /src/plugins
parent2ab46db3adc2aed13572cc14074415e7751bb52a (diff)
downloadweechat-90262cbcfea07e26236f15b46db02e73e8a43fc3.zip
Added trigger plugin
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/trigger/CMakeLists.txt21
-rw-r--r--src/plugins/trigger/Makefile.am30
-rw-r--r--src/plugins/trigger/dump.c148
-rw-r--r--src/plugins/trigger/trigger-libc.c463
-rw-r--r--src/plugins/trigger/trigger-libc.h40
-rw-r--r--src/plugins/trigger/trigger-libirc.c333
-rw-r--r--src/plugins/trigger/trigger-libirc.h40
-rw-r--r--src/plugins/trigger/trigger.c927
-rw-r--r--src/plugins/trigger/trigger.h52
9 files changed, 2054 insertions, 0 deletions
diff --git a/src/plugins/trigger/CMakeLists.txt b/src/plugins/trigger/CMakeLists.txt
new file mode 100644
index 000000000..d06107be6
--- /dev/null
+++ b/src/plugins/trigger/CMakeLists.txt
@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2007 FlashCode <flashcode@flashtux.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+ADD_LIBRARY(trigger MODULE trigger.c trigger.h trigger-libc.c trigger-libc.h
+trigger-libirc.c trigger-libirc.h)
+SET_TARGET_PROPERTIES(trigger PROPERTIES PREFIX "")
+
+INSTALL(TARGETS trigger LIBRARY DESTINATION lib/${PROJECT_NAME}/plugins)
diff --git a/src/plugins/trigger/Makefile.am b/src/plugins/trigger/Makefile.am
new file mode 100644
index 000000000..81d92db5e
--- /dev/null
+++ b/src/plugins/trigger/Makefile.am
@@ -0,0 +1,30 @@
+# Copyright (c) 2003-2007 FlashCode <flashcode@flashtux.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+INCLUDES = -DLOCALEDIR=\"$(datadir)/locale\" $(TRIGGER_CFLAGS)
+
+libdir = ${weechat_libdir}/plugins
+
+lib_LTLIBRARIES = trigger.la
+
+trigger_la_SOURCES = trigger.c \
+ trigger.h \
+ trigger-libc.c \
+ trigger-libc.h \
+ trigger-libirc.c \
+ trigger-libirc.h
+trigger_la_LDFLAGS = -module
+trigger_la_LIBADD = $(TRIGGER_LFLAGS)
diff --git a/src/plugins/trigger/dump.c b/src/plugins/trigger/dump.c
new file mode 100644
index 000000000..7a92809a8
--- /dev/null
+++ b/src/plugins/trigger/dump.c
@@ -0,0 +1,148 @@
+int
+weechat_trigger_match (t_weechat_trigger *ptr_ign,
+ char *pattern, char *commands,
+ char *channels, char *servers)
+{
+ if (strcasecmp (ptr_ign->pattern, pattern) == 0
+ && strcasecmp (ptr_ign->commands, commands) == 0
+ && strcasecmp (ptr_ign->channels, channels) == 0
+ && strcasecmp (ptr_ign->servers, servers) == 0)
+ return 1;
+
+ return 0;
+}
+
+t_weechat_trigger *
+weechat_trigger_search (char *pattern, char *commands,
+ char *channels, char *servers)
+{
+ t_weechat_trigger *l;
+
+ l = weechat_trigger_list;
+ while (l)
+ {
+ if (weechat_trigger_match (l, pattern, commands, channels, servers))
+ return l;
+ l = l->next_trigger;
+ }
+
+ return NULL;
+}
+int
+weechat_trigger_add (t_weechat_plugin *plugin,
+ char *pattern, char *commands,
+ char *channels, char *servers)
+{
+ t_weechat_trigger *new;
+
+ if (!pattern)
+ return 0;
+ if (weechat_trigger_search (pattern, commands, channels, servers))
+ {
+ return 2;
+ }
+
+ new = weechat_trigger_alloc (pattern, commands, channels, servers);
+ if (new)
+ {
+ if (weechat_trigger_last)
+ {
+ weechat_trigger_last->next_trigger = new;
+ new->prev_trigger = weechat_trigger_last;
+ weechat_trigger_last = new;
+ }
+ else
+ {
+ weechat_trigger_list = new;
+ weechat_trigger_last = new;
+ }
+
+ return 1;
+ }
+ else
+ plugin->print_server (plugin, "Unable to add trigger, memory allocation failed.");
+
+ return 0;
+}
+
+int
+weechat_trigger_list_del (char *pattern, char *commands,
+ char *channels, char *servers)
+{
+ char *error;
+ int number;
+ t_weechat_trigger *p, *l;
+
+ if (!pattern || !weechat_trigger_list)
+ return 0;
+
+ error = NULL;
+ number = strtol (pattern, &error, 10);
+ p = NULL;
+
+ if (error && (error[0] == '\0') && number > 0)
+ {
+ l = weechat_trigger_list;
+ while (l && number >= 0)
+ {
+ number--;
+ if (number == 0)
+ p = l;
+ l = l->next_trigger;
+ }
+ }
+ else
+ p = weechat_trigger_search (pattern, commands, channels, servers);
+
+ if (p)
+ {
+ if (p->prev_trigger)
+ p->prev_trigger->next_trigger = p->next_trigger;
+
+ if (p->next_trigger)
+ p->next_trigger->prev_trigger = p->prev_trigger;
+
+ if (p == weechat_trigger_list)
+ weechat_trigger_list = p->next_trigger;
+
+ if (p == weechat_trigger_last)
+ weechat_trigger_last = p->prev_trigger;
+
+ weechat_trigger_free (p);
+ return 1;
+ }
+
+ return 0;
+}
+
+ /*
+ server = plugin->get_info (plugin, "server", NULL);
+ if (!server)
+ server = strdup ("*");
+
+ if (argc >= 4)
+ ret = weechat_trigger_add (plugin, argv[0], argv[1], argv[2], argv[3]);
+ else if (argc == 3)
+ ret = weechat_trigger_add (plugin, argv[0], argv[1], argv[2], server);
+ else if (argc == 2)
+ ret = weechat_trigger_add (plugin, argv[0], argv[1], "*", server);
+ else if (argc == 1)
+ ret = weechat_trigger_add (plugin, argv[0], "*", "*", server);
+ else
+ {
+ ret = weechat_trigger_list (plugin);
+ ret = 1;
+ }
+
+ if (server)
+ free (server);
+
+ if (argc > 0 && ret == 1)
+ plugin->print_server (plugin, "Trigger: new trigger: on %s/%s: trigger %s from %s",
+ weechat_trigger_last->servers, weechat_trigger_last->channels,
+ weechat_trigger_last->commands, weechat_trigger_last->pattern);
+ else if (ret == 2)
+ plugin->print_server (plugin, "Trigger: trigger already exists.");
+ else if (ret == 0)
+ plugin->print_server (plugin, "Trigger: error: unable to add trigger.");
+ */
diff --git a/src/plugins/trigger/trigger-libc.c b/src/plugins/trigger/trigger-libc.c
new file mode 100644
index 000000000..d8b278660
--- /dev/null
+++ b/src/plugins/trigger/trigger-libc.c
@@ -0,0 +1,463 @@
+/*
+ * Copyright (c) 2003-2006 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* weechat-trigger-libirc.c: Tiny libc */
+
+/*
+ * c_is_number: return 1 if string is an number
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <fnmatch.h>
+#undef FNM_CASEFOLD
+#define FNM_CASEFOLD (1 << 4)
+
+/*
+ * c_is_number : is a string a number (an integer)
+ * return : 1 if true else 0
+ */
+
+int
+c_is_number (char *s)
+{
+ int i, l, r;
+
+ if (!s)
+ return 0;
+
+ r = 1;
+ l = strlen (s);
+ for (i=0; i<l; i++)
+ {
+ if (!isdigit(s[i]))
+ {
+ r = 0;
+ break;
+ }
+ }
+ return r;
+}
+
+/*
+ * c_to_number : convert a string to a number (an integer)
+ * return the number
+ */
+
+int
+c_to_number (char *s)
+{
+ int number = 0;
+
+ if (c_is_number (s) == 1)
+ number = strtol (s, NULL, 10);
+
+ return number;
+}
+
+/*
+ * c_strndup: strndup function (not existing in FreeBSD and maybe other)
+ */
+
+char *
+c_strndup (char *string, int length)
+{
+ char *result;
+
+ if ((int)strlen (string) < length)
+ return strdup (string);
+
+ result = (char *)malloc (length + 1);
+ if (!result)
+ return NULL;
+
+ memcpy (result, string, length);
+ result[length] = '\0';
+
+ return result;
+}
+
+/*
+ * c_ascii_tolower: locale independant string conversion to lower case
+ */
+
+void
+c_ascii_tolower (char *string)
+{
+ while (string && string[0])
+ {
+ if ((string[0] >= 'A') && (string[0] <= 'Z'))
+ string[0] += ('a' - 'A');
+ string++;
+ }
+}
+
+/*
+ * c_ascii_toupper: locale independant string conversion to upper case
+ */
+
+void
+c_ascii_toupper (char *string)
+{
+ while (string && string[0])
+ {
+ if ((string[0] >= 'a') && (string[0] <= 'z'))
+ string[0] -= ('a' - 'A');
+ string++;
+ }
+}
+
+/*
+ * weechat_strreplace: replace a string by new one in a string
+ * note: returned value has to be free() after use
+ */
+
+char *
+c_weechat_strreplace (char *string, char *search, char *replace)
+{
+ char *pos, *new_string;
+ int length1, length2, length_new, count;
+
+ if (!string || !search || !replace)
+ return NULL;
+
+ length1 = strlen (search);
+ length2 = strlen (replace);
+
+ /* count number of strings to replace */
+ count = 0;
+ pos = string;
+ while (pos && pos[0] && (pos = strstr (pos, search)))
+ {
+ count++;
+ pos += length1;
+ }
+
+ /* easy: no string to replace! */
+ if (count == 0)
+ return strdup (string);
+
+ /* compute needed memory for new string */
+ length_new = strlen (string) - (count * length1) + (count * length2) + 1;
+
+ /* allocate new string */
+ new_string = (char *)malloc (length_new * sizeof (char));
+ if (!new_string)
+ return strdup (string);
+
+ /* replace all occurences */
+ new_string[0] = '\0';
+ while (string && string[0])
+ {
+ pos = strstr (string, search);
+ if (pos)
+ {
+ strncat (new_string, string, pos - string);
+ strcat (new_string, replace);
+ pos += length1;
+ }
+ else
+ strcat (new_string, string);
+ string = pos;
+ }
+ return new_string;
+}
+
+/*
+ * explode_string: explode a string according to separators
+ */
+
+char **
+c_explode_string (char *string, char *separators, int num_items_max,
+ int *num_items)
+{
+ int i, n_items;
+ char **array;
+ char *ptr, *ptr1, *ptr2;
+
+ if (num_items != NULL)
+ *num_items = 0;
+
+ n_items = num_items_max;
+
+ if (!string || !string[0])
+ return NULL;
+
+ if (num_items_max == 0)
+ {
+ /* calculate number of items */
+ ptr = string;
+ i = 1;
+ while ((ptr = strpbrk (ptr, separators)))
+ {
+ while (strchr (separators, ptr[0]) != NULL)
+ ptr++;
+ i++;
+ }
+ n_items = i;
+ }
+
+ array =
+ (char **) malloc ((num_items_max ? n_items : n_items + 1) *
+ sizeof (char *));
+
+ ptr1 = string;
+ ptr2 = string;
+
+ for (i = 0; i < n_items; i++)
+ {
+ while (strchr (separators, ptr1[0]) != NULL)
+ ptr1++;
+ if (i == (n_items - 1) || (ptr2 = strpbrk (ptr1, separators)) == NULL)
+ if ((ptr2 = strchr (ptr1, '\r')) == NULL)
+ if ((ptr2 = strchr (ptr1, '\n')) == NULL)
+ ptr2 = strchr (ptr1, '\0');
+
+ if ((ptr1 == NULL) || (ptr2 == NULL))
+ {
+ array[i] = NULL;
+ }
+ else
+ {
+ if (ptr2 - ptr1 > 0)
+ {
+ array[i] =
+ (char *) malloc ((ptr2 - ptr1 + 1) * sizeof (char));
+ array[i] = strncpy (array[i], ptr1, ptr2 - ptr1);
+ array[i][ptr2 - ptr1] = '\0';
+ ptr1 = ++ptr2;
+ }
+ else
+ {
+ array[i] = NULL;
+ }
+ }
+ }
+ if (num_items_max == 0)
+ {
+ array[i] = NULL;
+ if (num_items != NULL)
+ *num_items = i;
+ }
+ else
+ {
+ if (num_items != NULL)
+ *num_items = num_items_max;
+ }
+
+ return array;
+}
+
+/*
+ * c_free_exploded_string: free an exploded string
+ */
+
+void
+c_free_exploded_string (char **exploded_string)
+{
+ int i;
+
+ if (exploded_string)
+ {
+ for (i = 0; exploded_string[i]; i++)
+ free (exploded_string[i]);
+ free (exploded_string);
+ }
+}
+
+/*
+ * c_split_multi_command: split a list of commands separated by 'sep'
+ * and ecscaped with '\'
+ * - empty commands are removed
+ * - spaces on the left of each commands are stripped
+ * Result must be freed with free_multi_command
+ */
+
+char **
+c_split_multi_command (char *command, char sep)
+{
+ int nb_substr, arr_idx, str_idx, type;
+ char **array;
+ char *buffer, *ptr, *p;
+
+ if (command == NULL)
+ return NULL;
+
+ nb_substr = 1;
+ ptr = command;
+ while ( (p = strchr(ptr, sep)) != NULL)
+ {
+ nb_substr++;
+ ptr = ++p;
+ }
+
+ array = (char **) malloc ((nb_substr + 1) * sizeof(char *));
+ if (!array)
+ return NULL;
+
+ buffer = (char *) malloc ( (strlen(command) + 1) * sizeof (char));
+ if (!buffer)
+ {
+ free (array);
+ return NULL;
+ }
+
+ ptr = command;
+ str_idx = 0;
+ arr_idx = 0;
+ while(*ptr != '\0')
+ {
+ type = 0;
+ if (*ptr == ';')
+ {
+ if (ptr == command)
+ type = 1;
+ else if ( *(ptr-1) != '\\')
+ type = 1;
+ else if ( *(ptr-1) == '\\')
+ type = 2;
+ }
+ if (type == 1)
+ {
+ buffer[str_idx] = '\0';
+ str_idx = -1;
+ p = buffer;
+ /* strip white spaces a the begining of the line */
+ while (*p == ' ') p++;
+ if (p && p[0])
+ array[arr_idx++] = strdup (p);
+ }
+ else if (type == 2)
+ buffer[--str_idx] = *ptr;
+ else
+ buffer[str_idx] = *ptr;
+ str_idx++;
+ ptr++;
+ }
+
+ buffer[str_idx] = '\0';
+ p = buffer;
+ while (*p == ' ') p++;
+ if (p && p[0])
+ array[arr_idx++] = strdup (p);
+
+ array[arr_idx] = NULL;
+
+ free (buffer);
+
+ array = (char **) realloc (array, (arr_idx + 1) * sizeof(char *));
+
+ return array;
+}
+
+/*
+ * c_free_multi_command : free a list of commands splitted
+ * with split_multi_command
+ */
+
+void
+c_free_multi_command (char **commands)
+{
+ int i;
+
+ if (commands)
+ {
+ for (i = 0; commands[i]; i++)
+ free (commands[i]);
+ free (commands);
+ }
+}
+
+/*
+ * c_join_string : join a list of string with 'sep' as glue
+ * result must be freed with c_free_joined_string
+ */
+
+char *
+c_join_string(char **list, char *sep)
+{
+ int i, len;
+ char *str;
+
+ str = NULL;
+ if (list)
+ {
+ len = 0;
+ for (i = 0; list[i]; i++)
+ len += strlen (list[i]);
+
+ len += i*strlen (sep) + 1;
+ str = (char *) malloc (len * sizeof(char));
+ if (str)
+ {
+ for (i = 0; list[i]; i++)
+ {
+ if (i == 0)
+ strcpy (str, list[i]);
+ else
+ {
+ strcat (str, sep);
+ strcat (str, list[i]);
+ }
+ }
+ }
+ }
+
+ return str;
+}
+
+/*
+ * c_free_joined_string : free a string joined with c_join_string
+ */
+
+void
+c_free_joined_string (char *str)
+{
+ free (str);
+}
+
+/*
+ * c_match_string : case sensitive matching
+ * return 1 if it matches else 0
+ *
+ */
+int
+c_match_string (char *string, char *pattern)
+{
+ if (!string || !pattern)
+ return 0;
+ return fnmatch (pattern, string, 0) == 0 ? 1 : 0;
+}
+
+
+/*
+ * c_imatch_string : case insensitive matching
+ * return 1 if it matches else 0
+ *
+ */
+int
+c_imatch_string (char *string, char *pattern)
+{
+ if (!string || !pattern)
+ return 0;
+ return fnmatch (pattern, string, FNM_CASEFOLD) == 0 ? 1 : 0;
+}
diff --git a/src/plugins/trigger/trigger-libc.h b/src/plugins/trigger/trigger-libc.h
new file mode 100644
index 000000000..0a4f16804
--- /dev/null
+++ b/src/plugins/trigger/trigger-libc.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2003-2006 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* weechat-trigger-libirc.c: Tiny libc */
+
+#ifndef WEECHAT_TRIGGER_LIBC__H
+#define WEECHAT_TRIGGER_LIBC__H 1
+
+int c_is_number (char *);
+int c_to_number (char *);
+char *c_strndup (char *, int);
+void c_ascii_tolower (char *);
+void c_ascii_toupper (char *);
+char *c_weechat_strreplace (char *, char *, char *);
+char **c_explode_string (char *, char *, int, int *);
+void c_free_exploded_string (char **);
+char **c_split_multi_command (char *, char);
+void c_free_multi_command (char **);
+char *c_join_string(char **, char *);
+void c_free_joined_string (char *);
+int c_match_string (char *, char *);
+int c_imatch_string (char *, char *);
+
+#endif /* WEECHAT_TRIGGER_LIBC__H */
diff --git a/src/plugins/trigger/trigger-libirc.c b/src/plugins/trigger/trigger-libirc.c
new file mode 100644
index 000000000..92b829e0b
--- /dev/null
+++ b/src/plugins/trigger/trigger-libirc.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2003-2006 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* weechat-trigger-libirc.c: Tiny libirc for trigger plugin */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "weechat-trigger-libc.h"
+#include "weechat-trigger-libirc.h"
+
+typedef struct irc_msg_type
+{
+ char *command;
+ void (*parser) (irc_msg *, char *);
+} irc_msg_type;
+
+void irc_parse_common (irc_msg *, char *);
+void irc_parse_join (irc_msg *, char *);
+void irc_parse_kick (irc_msg *, char *);
+void irc_parse_mode (irc_msg *, char *);
+void irc_parse_nick (irc_msg *, char *);
+void irc_parse_privmsg (irc_msg *, char *);
+void irc_parse_quit (irc_msg *, char *);
+void irc_parse_wallops (irc_msg *, char *);
+
+irc_msg_type irc_msg_types[] =
+{
+ /* kill and error commands to add */
+ { "invite", irc_parse_common },
+ { "join", irc_parse_join },
+ { "kick", irc_parse_kick },
+ { "mode", irc_parse_mode },
+ { "nick", irc_parse_nick },
+ { "notice", irc_parse_common },
+ { "part", irc_parse_common },
+ { "ping", irc_parse_common },
+ { "pong", irc_parse_common },
+ { "privmsg", irc_parse_privmsg },
+ { "quit", irc_parse_quit },
+ { "topic", irc_parse_common },
+ { "wallops", irc_parse_wallops },
+ {NULL, NULL }
+};
+
+char *irc_ctcp_types[] =
+{
+ "action", "dcc", "sed", "finger", "version", "source",
+ "userinfo", "clientinfo","errmsg", "ping", "time",
+ NULL
+};
+
+void irc_parse_userhost (irc_msg *m)
+{
+ char *excl, *ar;
+
+ if (m && m->userhost)
+ {
+ excl = strchr (m->userhost, '!');
+ if (excl) {
+ m->nick = c_strndup (m->userhost, excl-m->userhost);
+ ar = strchr (excl, '@');
+ if (ar)
+ {
+ m->user = c_strndup (excl+1, ar-excl-1);
+ ar++;
+ m->host = strdup (ar);
+ }
+ }
+ else
+ m->host = strdup (m->userhost);
+ }
+}
+
+void irc_parse_common (irc_msg *m, char *p)
+{
+ char *spc;
+
+ p++;
+ if (p && *p)
+ {
+ spc = strchr (p, ' ');
+ if (spc)
+ {
+ m->channel = c_strndup (p, spc-p);
+ spc++;
+ if (spc && *spc && spc[0] == ':')
+ m->message = strdup (spc+1);
+ }
+ }
+}
+
+
+void irc_parse_snotice (irc_msg *m, char *p)
+{
+ char *c;
+
+ if (p)
+ {
+ c = strchr (p, ':');
+ c++;
+ if (c && *c)
+ {
+ m->message = strdup (c);
+ m->command = strdup ("notice");
+ }
+ }
+}
+
+void irc_parse_privmsg (irc_msg *m, char *p)
+{
+ char ctcp_buf[32];
+ char *c, *d;
+ char **it;
+
+ irc_parse_common (m, p);
+
+ c = m->message;
+ if (c)
+ {
+ if (*c == '\x01')
+ {
+ c++;
+ d = strchr(c, '\x01');
+ if (d)
+ {
+ for (it = irc_ctcp_types; *it; it++)
+ {
+ if (strncasecmp (c, *it, strlen(*it)) == 0)
+ {
+ snprintf (ctcp_buf, sizeof(ctcp_buf), "ctcp-%s", *it);
+ free (m->command);
+ m->command = strdup (ctcp_buf);
+ c += strlen(*it);
+ d = c_strndup (c+1, d-c+1);
+ free (m->message);
+ m->message = d;
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+void irc_parse_join (irc_msg *m, char *p)
+{
+ p++;
+ if (p && *p && p[0] == ':')
+ {
+ m->channel = strdup (p+1);
+ }
+}
+
+void irc_parse_nick (irc_msg *m, char *p)
+{
+ p++;
+ if (p && *p && p[0] == ':')
+ {
+ m->message = strdup (p+1);
+ }
+}
+
+void irc_parse_mode (irc_msg *m, char *p)
+{
+ char *spc;
+
+ p++;
+ if (p && *p)
+ {
+ spc = strchr (p, ' ');
+ if (spc)
+ {
+ m->channel = c_strndup (p, spc-p);
+ spc++;
+ if (spc && *spc)
+ m->message = strdup (spc);
+ }
+ }
+}
+
+void irc_parse_quit (irc_msg *m, char *p)
+{
+ p++;
+ if (p && *p && p[0] == ':')
+ {
+ m->message = strdup (p+1);
+ }
+}
+
+void irc_parse_kick (irc_msg *m, char *p)
+{
+ char *spc1, *spc2;
+
+ p++;
+ if (p && *p)
+ {
+ spc1 = strchr (p, ' ');
+ if (spc1)
+ {
+ m->channel = c_strndup (p, spc1-p);
+ spc1++;
+ if (spc1 && *spc1)
+ {
+ spc2 = strchr(spc1, ' ');
+ if (spc2)
+ {
+ m->data = c_strndup (spc1, spc2-spc1);
+ spc2++;
+ if (spc2 && *spc2 && spc2[0] == ':')
+ m->message = strdup (spc2+1);
+ }
+ }
+ }
+ }
+}
+
+void irc_parse_wallops (irc_msg *m, char *p)
+{
+ p++;
+ if (p && *p && p[0] == ':')
+ {
+ m->message = strdup (p+1);
+ }
+}
+
+void irc_parse_numeric (irc_msg *m, char *p)
+{
+ char *spc1, *spc2;
+
+ p++;
+ if (p && *p)
+ {
+ spc1 = strchr (p, ' ');
+ if (spc1)
+ {
+ spc2 = strchr (spc1, ' ');
+ spc2++;
+ if (spc2 && *spc2 && spc2[0] == ':')
+ m->message = strdup (spc2+1);
+ }
+ }
+}
+
+
+
+irc_msg *irc_parse_msg (char *msg)
+{
+ irc_msg *m;
+ char *spc1, *spc2;
+ irc_msg_type *it;
+
+ m = (irc_msg *) malloc(sizeof(irc_msg));
+
+ if (m)
+ {
+ m->userhost = NULL;
+ m->nick = NULL;
+ m->user = NULL;
+ m->host = NULL;
+ m->command = NULL;
+ m->channel = NULL;
+ m->message = NULL;
+ m->data = NULL;
+
+ if (msg && msg[0] == ':')
+ {
+ spc1 = strchr (msg, ' ');
+ if (spc1)
+ {
+ spc1++;
+ spc2 = strchr (spc1, ' ');
+ if (spc2)
+ {
+ m->command = c_strndup (spc1, spc2-spc1);
+ c_ascii_tolower (m->command);
+
+ m->userhost = c_strndup (msg+1, spc1-msg-2);
+ irc_parse_userhost (m);
+
+ if (c_is_number (m->command))
+ irc_parse_numeric (m, spc2);
+ else
+ for (it = irc_msg_types; it->command; it++)
+ {
+ if (strcmp (m->command, it->command) == 0)
+ {
+ it->parser (m, spc2);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (msg && strncasecmp("NOTICE ", msg, 7) == 0)
+ irc_parse_snotice (m, msg);
+ }
+ return m;
+}
+
+void irc_msg_free (irc_msg *m)
+{
+ if (m)
+ {
+ if (m->userhost) free (m->userhost);
+ if (m->nick) free (m->nick);
+ if (m->user) free (m->user);
+ if (m->host) free (m->host);
+ if (m->command) free (m->command);
+ if (m->channel) free (m->channel);
+ if (m->message) free (m->message);
+ if (m->data) free (m->data);
+ free (m);
+ }
+}
diff --git a/src/plugins/trigger/trigger-libirc.h b/src/plugins/trigger/trigger-libirc.h
new file mode 100644
index 000000000..1d48f4093
--- /dev/null
+++ b/src/plugins/trigger/trigger-libirc.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2003-2006 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* weechat-trigger-libirc.c: Tiny libirc for trigger plugin */
+
+#ifndef WEECHAT_TRIGGER_LIBIRC__H
+#define WEECHAT_TRIGGER_LIBIRC__H 1
+
+typedef struct irc_msg
+{
+ char *userhost;
+ char *nick;
+ char *user;
+ char *host;
+ char *command;
+ char *channel;
+ char *message;
+ char *data;
+} irc_msg;
+
+irc_msg *irc_parse_msg (char *);
+void irc_msg_free (irc_msg *);
+
+#endif /* WEECHAT_TRIGGER_LIBIRC__H */
diff --git a/src/plugins/trigger/trigger.c b/src/plugins/trigger/trigger.c
new file mode 100644
index 000000000..44b410af3
--- /dev/null
+++ b/src/plugins/trigger/trigger.c
@@ -0,0 +1,927 @@
+/*
+ * Copyright (c) 2003-2006 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* weechat-trigger.c: Trigger plugin for WeeChat */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../weechat-plugin.h"
+#include "weechat-trigger.h"
+#include "weechat-trigger-libirc.h"
+#include "weechat-trigger-libc.h"
+
+t_weechat_trigger *weechat_trigger_list = NULL;
+t_weechat_trigger *weechat_trigger_last = NULL;
+
+t_weechat_trigger *weechat_trigger_alloc (char *pattern, char *domain, char *commands,
+ char *channels, char *servers,
+ char *action, char *cmd)
+{
+ t_weechat_trigger *new;
+
+ new = (t_weechat_trigger *) malloc (sizeof (t_weechat_trigger));
+ if (new)
+ {
+ new->pattern = strdup (pattern);
+ new->domain = strdup (domain);
+
+ new->commands = c_explode_string (commands, ",", 0, NULL);
+ new->channels = c_explode_string (channels, ",", 0, NULL);
+ new->servers = c_explode_string (servers, ",", 0, NULL);
+ new->action = strdup (action);
+
+ if (cmd)
+ new->cmds = c_split_multi_command (cmd, ';');
+ else
+ new->cmds = NULL;
+
+ new->prev_trigger = NULL;
+ new->next_trigger = NULL;
+ }
+ return new;
+}
+
+void weechat_trigger_free (t_weechat_trigger *trig)
+{
+ if (trig)
+ {
+ if (trig->pattern)
+ free (trig->pattern);
+ if (trig->domain)
+ free (trig->domain);
+ if (trig->commands)
+ c_free_exploded_string (trig->commands);
+ if (trig->channels)
+ c_free_exploded_string (trig->channels);
+ if (trig->servers)
+ c_free_exploded_string (trig->servers);
+ if (trig->action)
+ free (trig->action);
+ if (trig->cmds)
+ c_free_multi_command (trig->cmds);
+ free (trig);
+ }
+}
+
+int
+weechat_trigger_action_exists (char *action)
+{
+ if (strcasecmp(action, "ignore") == 0
+ || strcasecmp(action, "display") == 0
+ || strcasecmp(action, "highlight") == 0
+ || strcasecmp(action, "run") == 0)
+ return 1;
+
+ return 0;
+}
+
+int
+weechat_trigger_domain_exists (char *action)
+{
+ if (strcasecmp(action, "*") == 0
+ || strcasecmp(action, "user") == 0
+ || strcasecmp(action, "nick") == 0
+ || strcasecmp(action, "userhost") == 0
+ || strcasecmp(action, "msg") == 0)
+ return 1;
+
+ return 0;
+}
+
+/*
+ * weechat_trigger_add : create and add a new trigger in triggers list
+ * return :
+ * 0 : adding was successfull
+ * 1 : memory error
+ * 2 : bad arguments
+ */
+
+int
+weechat_trigger_add (int argc, char **argv)
+{
+ int ret = 2;
+ char *rcmd;
+ t_weechat_trigger *trig = NULL;
+
+ if (argc == 6)
+ {
+ if (weechat_trigger_action_exists (argv[5])
+ && strcasecmp (argv[5], "run") != 0)
+ {
+ trig = weechat_trigger_alloc (
+ argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], NULL);
+ if (!trig)
+ ret = 1;
+ }
+ }
+ else if (argc > 6)
+ {
+ if (strcasecmp (argv[5], "run") == 0)
+ {
+ rcmd = c_join_string (&argv[6], " ");
+ if (rcmd)
+ {
+ trig = weechat_trigger_alloc (
+ argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], rcmd);
+ c_free_joined_string (rcmd);
+ if (!trig)
+ ret = 1;
+ }
+ }
+ }
+
+ if (trig)
+ {
+ if (weechat_trigger_last)
+ {
+ weechat_trigger_last->next_trigger = trig;
+ trig->prev_trigger = weechat_trigger_last;
+ weechat_trigger_last = trig;
+ }
+ else
+ {
+ weechat_trigger_list = trig;
+ weechat_trigger_last = trig;
+ }
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/*
+ *
+ */
+
+int
+weechat_trigger_move (int from, int to)
+{
+ t_weechat_trigger *l, *f, *t;
+ int ret, i;
+
+ if (from == to)
+ return 0;
+
+ ret = 1;
+ f = NULL;
+ t = NULL;
+ l = weechat_trigger_list;
+ i = 0;
+ while (l)
+ {
+ i++;
+ if (i == from)
+ f = l;
+ if (i == to)
+ t = l;
+ l = l->next_trigger;
+ }
+
+ if (f && t)
+ {
+ if (weechat_trigger_list == f)
+ weechat_trigger_list = f->next_trigger;
+
+ if (weechat_trigger_last == f)
+ weechat_trigger_last = f->prev_trigger;
+
+ if (f->prev_trigger)
+ f->prev_trigger->next_trigger = f->next_trigger;
+ if (f->next_trigger)
+ f->next_trigger->prev_trigger = f->prev_trigger;
+
+ if (to > from && !t->next_trigger)
+ {
+ t->next_trigger = f;
+ f->prev_trigger = t;
+ f->next_trigger = NULL;
+
+ weechat_trigger_last = f;
+ }
+ else
+ {
+ if (to > from && t->next_trigger)
+ t = t->next_trigger;
+
+ if (t->prev_trigger)
+ t->prev_trigger->next_trigger = f;
+ f->next_trigger = t;
+ f->prev_trigger = t->prev_trigger;
+ t->prev_trigger = f;
+
+ if (t == weechat_trigger_list)
+ weechat_trigger_list = f;
+ }
+
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/*
+ * weechat_trigger_move : remove a trigger trigger in triggers list
+ * by its number
+ * return : 0 = success ; 1 = failed
+ */
+
+int
+weechat_trigger_remove (int n)
+{
+ t_weechat_trigger *l, *p;
+ int ret;
+
+ ret = 1;
+ l = weechat_trigger_list;
+ p = NULL;
+ while (l && n >= 0)
+ {
+ n--;
+ if (n == 0) {
+ p = l;
+ break;
+ }
+ l = l->next_trigger;
+ }
+
+ if (p)
+ {
+ if (p->prev_trigger)
+ p->prev_trigger->next_trigger = p->next_trigger;
+
+ if (p->next_trigger)
+ p->next_trigger->prev_trigger = p->prev_trigger;
+
+ if (p == weechat_trigger_list)
+ weechat_trigger_list = p->next_trigger;
+
+ if (p == weechat_trigger_last)
+ weechat_trigger_last = p->prev_trigger;
+
+ weechat_trigger_free (p);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+void
+weechat_trigger_display (t_weechat_plugin *plugin)
+{
+ t_weechat_trigger *l;
+ int i;
+ char *commands, *channels, *servers, *cmds;
+
+ if (weechat_trigger_list)
+ {
+ plugin->print_server (plugin, "Trigger list:");
+ l = weechat_trigger_list;
+ i = 1;
+ while (l)
+ {
+ commands = c_join_string (l->commands, ",");
+ channels = c_join_string (l->channels, ",");
+ servers = c_join_string (l->servers, ",");
+ cmds = c_join_string (l->cmds, ";");
+
+ if (strcasecmp (l->action, "run") == 0)
+ plugin->print_server (plugin,
+ "[%d] pattern '%s/%s' for irc command(s) '%s'"
+ " for channel(s) '%s' on server(s) '%s'"
+ " do '%s' command(s) '%s'",
+ i, l->pattern, l->domain, commands, channels,
+ servers, l->action, cmds);
+ else
+ plugin->print_server (plugin,
+ "[%d] pattern '%s/%s' for irc command(s) '%s'"
+ " for channel(s) '%s' on server(s) '%s'"
+ " do '%s'",
+ i, l->pattern, l->domain, commands, channels,
+ servers, l->action);
+
+ if (commands) c_free_joined_string (commands);
+ if (channels) c_free_joined_string (channels);
+ if (servers) c_free_joined_string (servers);
+ if (cmds) c_free_joined_string (cmds);
+ l = l->next_trigger;
+ i++;
+ }
+ }
+ else
+ plugin->print_server (plugin, "Trigger list: no trigger defined.");
+}
+
+/*
+ * weechat_trigger_cmd: /trigger command
+ */
+
+int
+weechat_trigger_cmd (t_weechat_plugin *plugin,
+ int cmd_argc, char **cmd_argv,
+ char *handler_args, void *handler_pointer)
+{
+ int argc, ret, n1, n2;
+ char **argv;
+
+ /* make C compiler happy */
+ (void) cmd_argc;
+ (void) handler_args;
+ (void) handler_pointer;
+
+ ret = 0;
+
+ if (cmd_argv[2])
+ argv = c_explode_string (cmd_argv[2], " ", 0, &argc);
+ else
+ {
+ argv = NULL;
+ argc = 0;
+ }
+
+ if (argv)
+ {
+ if (strcasecmp (argv[0], "add") == 0)
+ {
+ if (argc >= 7)
+ {
+ switch (weechat_trigger_add (argc-1, &argv[1]))
+ {
+ case 0:
+ plugin->print_server (plugin, "Trigger: trigger successfully created");
+ break;
+ case 1:
+ plugin->print_server (plugin, "Trigger error: memory error while creating trigger");
+ break;
+ case 2:
+ plugin->print_server (plugin, "Trigger error: 'action' or 'domain' option seems misused");
+ break;
+ }
+ }
+ else
+ plugin->print_server (plugin, "Trigger error: missing arguments");
+ }
+ else if (strcasecmp (argv[0], "move") == 0)
+ {
+ if (argc == 3)
+ {
+ n1 = c_to_number (argv[1]);
+ n2 = c_to_number (argv[2]);
+ if (n1 > 0 && n2 > 0)
+ {
+ if (weechat_trigger_move (n1, n2) == 0)
+ plugin->print_server (plugin, "Trigger: trigger sucessfully moved from psotion %d to %d", n1, n2);
+ else
+ plugin->print_server (plugin, "Trigger error: fail to move from %d to %d, number(s) seems invalid", n1, n2);
+ }
+ else
+ plugin->print_server (plugin, "Trigger error: fail to move from %d to %d, number(s) seems invalid", n1, n2);
+ }
+ else
+ plugin->print_server (plugin, "Trigger error: fail to move, missing or too much arguments");
+
+ }
+ else if (strcasecmp (argv[0], "remove") == 0)
+ {
+ if (argc == 2)
+ {
+ n1 = c_to_number (argv[1]);
+ if (n1 > 0)
+ {
+ if (weechat_trigger_remove (n1) == 0)
+ plugin->print_server (plugin, "Trigger: trigger number %d sucessfully removed", n1);
+ else
+ plugin->print_server (plugin, "Trigger error: fail to remove trigger number %d, number out of bound", n1);
+ }
+ else
+ plugin->print_server (plugin, "Trigger error: fail to remove trigger number %d, number seems invalid", n1);
+ }
+ else
+ plugin->print_server (plugin, "Trigger error: fail to remove trigger, missing or too much arguments");
+ }
+ else
+ weechat_trigger_display (plugin);
+
+ c_free_exploded_string (argv);
+ }
+ else
+ weechat_trigger_display (plugin);
+
+ return PLUGIN_RC_OK;
+}
+
+/*
+ * weechat_trigger_match: find if a trigger match an irc message
+ * return : 0 if it does match
+ * 1 if it doesn't match
+ * 2 if irc message can't be parsed
+ */
+irc_msg *
+weechat_trigger_match(t_weechat_trigger *trigger, char *msg, char *server, int *ret)
+{
+ irc_msg *imsg;
+ int match_c, match_h, match_s;
+ char **pp;
+
+ imsg = irc_parse_msg (msg);
+ *ret = 1;
+ match_c = 0;
+ match_h = 0;
+ match_s = 0;
+
+ if (imsg)
+ {
+ /*
+ p->print_server(p,
+ "uh=[%s] n=[%s] u=[%s] h=[%s] com=[%s] chan=[%s] srv=[%s] msg=[%s]",
+ imsg->userhost, imsg->nick, imsg->user, imsg->host,
+ imsg->command, imsg->channel, server, imsg->message);
+ */
+
+
+ if (
+ (imsg->user
+ && ((strcasecmp(trigger->domain, "*") == 0)
+ || (strcasecmp(trigger->domain, "user") == 0))
+ && c_imatch_string (imsg->user, trigger->pattern))
+ ||
+ (imsg->nick
+ && ((strcasecmp(trigger->domain, "*") == 0)
+ || strcasecmp(trigger->domain, "nick") == 0)
+ && c_imatch_string (imsg->nick, trigger->pattern))
+ ||
+ (imsg->userhost
+ && ((strcasecmp(trigger->domain, "*") == 0)
+ || (strcasecmp(trigger->domain, "userhost") == 0))
+ && c_imatch_string (imsg->userhost, trigger->pattern))
+ ||
+ (imsg->message
+ && ((strcasecmp(trigger->domain, "*") == 0)
+ || (strcasecmp(trigger->domain, "msg") == 0))
+ && c_imatch_string (imsg->message, trigger->pattern))
+ )
+ {
+ if (!imsg->command)
+ match_c = 1;
+ else if (trigger->commands)
+ {
+ for (pp = trigger->commands; *pp; pp++)
+ {
+ if (c_imatch_string (imsg->command, *pp))
+ {
+ match_c = 1;
+ break;
+ }
+ }
+ }
+
+ if (match_c)
+ {
+ if (!imsg->channel)
+ match_h = 1;
+ else if (trigger->channels)
+ {
+ for(pp = trigger->channels; *pp; pp++)
+ {
+ if (c_imatch_string (imsg->channel, *pp))
+ {
+ match_h = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if (match_h)
+ {
+ if (!server)
+ match_s = 1;
+ else if (trigger->servers)
+ {
+ for(pp = trigger->servers; *pp; pp++)
+ {
+ if (c_imatch_string (server, *pp))
+ {
+ match_s = 1;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ *ret = ((match_c == 1) && (match_h == 1) && (match_s == 1)) ? 0 : 1;
+ }
+ else
+ *ret = 2;
+
+ return imsg;
+}
+
+/*
+ * weechat_trigger_msg: trigger handler
+ */
+
+int
+weechat_trigger_msg (t_weechat_plugin *plugin,
+ int argc, char **argv,
+ char *handler_args, void *handler_pointer)
+{
+ t_weechat_trigger *l;
+ int ret, i, j, match;
+ char *ccom, *tcom;
+ irc_msg *imsg;
+
+ /* make C compiler happy */
+ (void) argc;
+ (void) handler_args;
+ (void) handler_pointer;
+
+ ret = PLUGIN_RC_OK;
+ l = weechat_trigger_list;
+ i = 0;
+
+ while (l)
+ {
+ i++;
+ /* argv[0] = server name */
+ imsg = weechat_trigger_match (l, argv[2], argv[0], &match);
+
+ if (imsg && match == 2)
+ {
+ plugin->print_server (plugin, "Trigger error: error while parsing irc message : [%s]", argv[2]);
+ irc_msg_free (imsg);
+ }
+ else if (imsg && match == 0)
+ {
+ if (strcasecmp (l->action, "display") == 0)
+ plugin->print_server (plugin, "Trigger display: matching trigger number %d with message [%s]", i, argv[2]);
+ else if (strcasecmp (l->action, "ignore") == 0)
+ ret = PLUGIN_RC_OK_IGNORE_WEECHAT;
+ else if (strcasecmp (l->action, "highlight") == 0)
+ ret = PLUGIN_RC_OK_WITH_HIGHLIGHT;
+ else if (l->cmds && strcasecmp (l->action, "run") == 0)
+ {
+ for(j = 0; l->cmds[j]; j++)
+ {
+ /* formatting commands by replacing with defined values */
+ ccom = strdup (l->cmds[j]);
+ if (ccom)
+ {
+ tcom = c_weechat_strreplace (ccom, "%uh", imsg->userhost == NULL ? "" : imsg->userhost);
+ if (tcom)
+ {
+ if (ccom) free (ccom);
+ ccom = tcom;
+ }
+
+ tcom = c_weechat_strreplace (ccom, "%n", imsg->nick == NULL ? "" : imsg->nick);
+ if (tcom)
+ {
+ if (ccom) free (ccom);
+ ccom = tcom;
+ }
+
+ tcom = c_weechat_strreplace (ccom, "%u", imsg->user == NULL ? "" : imsg->user);
+ if (tcom)
+ {
+ if (ccom) free (ccom);
+ ccom = tcom;
+ }
+
+ tcom = c_weechat_strreplace (ccom, "%h", imsg->host == NULL ? "" : imsg->host);
+ if (tcom)
+ {
+ if (ccom) free (ccom);
+ ccom = tcom;
+ }
+
+ tcom = c_weechat_strreplace (ccom, "%c", imsg->command == NULL ? "" : imsg->command);
+ if (tcom)
+ {
+ if (ccom) free (ccom);
+ ccom = tcom;
+ }
+
+ tcom = c_weechat_strreplace (ccom, "%C", imsg->channel == NULL ? "" : imsg->channel);
+ if (tcom)
+ {
+ if (ccom) free (ccom);
+ ccom = tcom;
+ }
+
+ tcom = c_weechat_strreplace (ccom, "%S", argv[0] == NULL ? "" : argv[0]);
+ if (tcom)
+ {
+ if (ccom) free (ccom);
+ ccom = tcom;
+ }
+
+ tcom = c_weechat_strreplace (ccom, "%d", imsg->data == NULL ? "" : imsg->data);
+ if (tcom)
+ {
+ if (ccom) free (ccom);
+ ccom = tcom;
+ }
+
+ plugin->exec_command (plugin, NULL, NULL, ccom);
+ free (ccom);
+ }
+ else
+ plugin->exec_command (plugin, NULL, NULL, l->cmds[j]);
+ }
+ }
+ irc_msg_free (imsg);
+ }
+
+ l = l->next_trigger;
+ }
+
+ return ret;
+}
+
+/*
+ * weechat_trigger_tmsg: /tmsg command
+ */
+
+int
+weechat_trigger_tmsg (t_weechat_plugin *plugin,
+ int cmd_argc, char **cmd_argv,
+ char *handler_args, void *handler_pointer)
+{
+ int argc;
+ char **argv, *srv, *chan, *cmd;
+
+ /* make C compiler happy */
+ (void) cmd_argc;
+ (void) handler_args;
+ (void) handler_pointer;
+
+ if (cmd_argv[2])
+ argv = c_explode_string (cmd_argv[2], " ", 0, &argc);
+ else
+ {
+ argv = NULL;
+ argc = 0;
+ }
+
+ if (argv && argc>=3)
+ {
+ srv = (strcmp (argv[0], "*") == 0) ? NULL : argv[0];
+ chan = (strcmp (argv[1], "*") == 0) ? NULL : argv[1];
+
+ cmd = c_join_string (&argv[2], " ");
+ plugin->exec_command (plugin, srv, chan, (cmd == NULL) ? "" : cmd);
+ if (cmd)
+ c_free_joined_string (cmd);
+ }
+ else
+ plugin->print_server (plugin, "Trigger error: wrong argument count for command \"tmsg\"");
+
+ if (argv)
+ c_free_exploded_string (argv);
+
+ return PLUGIN_RC_OK;
+}
+
+
+
+/*
+ * weechat_trigger_edit: load/save triggers from/in a file
+ */
+int
+weechat_trigger_edit (t_weechat_plugin *plugin, int todo)
+{
+ t_weechat_trigger *l;
+ int len, ret, argc;
+ char **argv, *commands, *channels, *servers, *cmds;
+ char *weechat_dir, *triggerrc, line[1024], *p, *q;
+ FILE *f;
+
+ ret = 0;
+
+ if ((todo != CONF_LOAD) && (todo != CONF_SAVE))
+ return -1;
+
+ weechat_dir = plugin->get_info (plugin, "weechat_dir", NULL);
+ if (!weechat_dir)
+ return -1;
+
+ len = strlen (weechat_dir) + strlen(DIR_SEP) + strlen(CONF_FILE) + 1;
+ triggerrc = (char *) malloc (len * sizeof(char));
+ if (!triggerrc)
+ return -1;
+
+ snprintf (triggerrc, len, "%s%s%s", weechat_dir, DIR_SEP, CONF_FILE);
+
+ /* saving */
+ if (todo == CONF_SAVE)
+ {
+ f = fopen (triggerrc, "w");
+ if (!f) {
+ plugin->print_server (plugin, "Trigger plugin: error, unable to write file '%s'", triggerrc);
+ return -1;
+ }
+
+ fprintf (f, "#\n");
+ fprintf (f, "#WeeChat trigger plugin config file\n");
+ fprintf (f, "# BE CAREFUL - DO NOT EDIT BY HAND\n");
+ fprintf (f, "#\n\n");
+
+ l = weechat_trigger_list;
+ while (l)
+ {
+ commands = c_join_string (l->commands, ",");
+ channels = c_join_string (l->channels, ",");
+ servers = c_join_string (l->servers, ",");
+ cmds = c_join_string (l->cmds, ";");
+
+ if (strcasecmp (l->action, "run") == 0)
+ fprintf (f, "%s %s %s %s %s %s %s\n",
+ l->pattern, l->domain, commands,
+ channels, servers, l->action, cmds);
+ else
+ fprintf (f, "%s %s %s %s %s %s\n",
+ l->pattern, l->domain, commands,
+ channels, servers, l->action);
+
+ ret++;
+ l = l->next_trigger;
+ }
+ fclose(f);
+ }
+
+ /* loading */
+ if (todo == CONF_LOAD)
+ {
+ f = fopen (triggerrc, "r");
+ if (!f) {
+ plugin->print_server (plugin, "Trigger plugin: error, unable to read file '%s'", triggerrc);
+ return -1;
+ }
+
+ while (!feof (f))
+ {
+ p = fgets (line, sizeof (line), f);
+ if (p)
+ {
+ /* skip spaces ans tabs */
+ while(p[0] == ' ' || p[0] == '\t')
+ p++;
+ /* skip comments and empty lines */
+ if ((p[0] != '#') && (p[0] != '\r') && (p[0] != '\n'))
+ {
+ q = strrchr (p, '\n');
+ if (q)
+ *q = '\0';
+ argv = c_explode_string (p, " ", 0, &argc);
+ if (argv && argc >= 7)
+ {
+ if (weechat_trigger_add (argc, argv) == 0)
+ ret++;
+ else
+ plugin->print_server (plugin, "Trigger: failed to load trigger \"%s\"", p);
+ }
+ if (argv)
+ c_free_exploded_string (argv);
+ }
+ }
+ }
+ fclose(f);
+ }
+
+ return ret;
+}
+
+/*
+ * weechat_plugin_init: init trigger plugin
+ */
+
+int
+weechat_plugin_init (t_weechat_plugin *plugin)
+{
+ t_plugin_handler *cmd_handler_trigger, *cmd_handler_tmsg, *msg_handler;
+ int n;
+
+ weechat_trigger_list = NULL;
+ weechat_trigger_last = NULL;
+
+ /* loading saved triggers */
+ n = weechat_trigger_edit (plugin, CONF_LOAD);
+ switch (n)
+ {
+ case -1:
+ plugin->print_server (plugin, "Trigger plugin starting: error");
+ break;
+ case 0:
+ plugin->print_server (plugin, "Trigger plugin starting: no triggers found");
+ break;
+ default:
+ plugin->print_server (plugin, "Trigger plugin starting: %d triggers found and loaded", n);
+ }
+
+ /* add trigger command handler */
+ cmd_handler_trigger = plugin->cmd_handler_add (plugin, "trigger",
+ "Trigger actions on IRC messages by nicks/hosts, irc messages, commands, channels and servers",
+ " [ list ] | [ add pattern domain [type(s) | command(s)] channel(s) server(s) [action [cmd]] ] | [ move from_num to_num ] | [ remove num ]",
+ " 'list': list triggers\n"
+ " 'add': create a new trigger\n"
+ " pattern: pattern to match\n"
+ " domain: domain where the pattern is searched (user, nick, userhost, msg)\n"
+ " type(s): messages types to trigger (privmsg, ctcp-$type, dcc, join, part, quit, ...).\n"
+ " command(s): irc commands to trigger.\n"
+ " channel(s): channels to trigger.\n"
+ " server(s): servers to trigger.\n"
+ " action: action to perform if trigger match (ignore, display, highlight, run)\n"
+ " cmd: irc or WeeChat command(s) to run if action is 'run'\n"
+ " possible replacements in command(s) :\n"
+ " %uh : userhost mask\n"
+ " %n : nickname\n"
+ " %u : username\n"
+ " %h : hostname\n"
+ " %c : irc command\n"
+ " %C : channel name\n"
+ " %S : server name\n"
+ " %d : extra data\n"
+ " 'move': move trigger position in trigger's list\n"
+ " from_num: current trigger position\n"
+ " to_num: future trigger position\n"
+ "'remove': remove a trigger\n"
+ " num: position of the trigger to remove\n"
+ "\n"
+ "Multiples values separated by commas can be set for fields : type(s), command(s), channel(s) and server(s).\n"
+ "It's possible to use wildcards for fields : pattern, type(s), command(s), channel(s) and server(s) options.\n\n",
+ "list|add|move|remove *|%n *|user|nick|userhost|msg *|%I|ctcp-action|ctcp-dcc|ctcp-sed|ctcp-finger|ctcp-version|ctcp-source|ctcp-userinfo|ctcp-clientinfo|ctcp-errmsg|ctcp-ping|ctcp-time *|%c *|%s ignore|display|highlight|run",
+ &weechat_trigger_cmd,
+ NULL, NULL);
+
+ /* add messge modifier */
+ msg_handler = plugin->msg_handler_add (plugin, "*",
+ &weechat_trigger_msg,
+ NULL, NULL);
+
+
+ /* add tmsg command handler */
+ cmd_handler_tmsg = plugin->cmd_handler_add (plugin, "tmsg",
+ "Send a message to a channel",
+ " server receiver text",
+ "server: server ('*' = current server)\n"
+ "channel: channel ('*' = current channel)\n"
+ "text: text to send\n",
+ "*|%s *|%c",
+ &weechat_trigger_tmsg,
+ NULL, NULL);
+
+ return PLUGIN_RC_OK;
+}
+
+/*
+ * weechat_plugin_end: end trigger plugin
+ */
+
+void
+weechat_plugin_end (t_weechat_plugin *plugin)
+{
+ t_weechat_trigger *l;
+ int n;
+
+ /* make C compiler happy */
+ (void) plugin;
+
+ n = weechat_trigger_edit (plugin, CONF_SAVE);
+ switch (n)
+ {
+ case -1:
+ plugin->print_server (plugin, "Trigger plugin ending: error");
+ break;
+ case 0:
+ plugin->print_server (plugin, "Trigger plugin ending: no triggers to save");
+ break;
+ default:
+ plugin->print_server (plugin, "Trigger plugin ending: saving %d triggers", n);
+ }
+
+ while (weechat_trigger_list)
+ {
+ l = weechat_trigger_list;
+ weechat_trigger_list = weechat_trigger_list->next_trigger;
+ weechat_trigger_free (l);
+ }
+}
diff --git a/src/plugins/trigger/trigger.h b/src/plugins/trigger/trigger.h
new file mode 100644
index 000000000..fcaaaf94a
--- /dev/null
+++ b/src/plugins/trigger/trigger.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2003-2006 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* weechat-trigger.h: Trigger plugin support for WeeChat */
+
+#ifndef WEECHAT_TRIGGER__H
+#define WEECHAT_TRIGGER__H 1
+
+#define _PLUGIN_NAME "trigger"
+#define _PLUGIN_VERSION "0.1"
+#define _PLUGIN_DESC "Trigger plugin for WeeChat"
+
+char plugin_name[] = _PLUGIN_NAME;
+char plugin_version[] = _PLUGIN_VERSION;
+char plugin_description[] = _PLUGIN_DESC;
+
+typedef struct t_weechat_trigger
+{
+ char *pattern;
+ char *domain;
+ char **commands;
+ char **channels;
+ char **servers;
+ char *action;
+ char **cmds;
+
+ struct t_weechat_trigger *prev_trigger;
+ struct t_weechat_trigger *next_trigger;
+} t_weechat_trigger;
+
+#define CONF_FILE "trigger.rc"
+#define CONF_SAVE 1
+#define CONF_LOAD 2
+#define DIR_SEP "/"
+
+#endif /* WEECHAT_TRIGGER__H */