diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ab862f..0241d68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,6 +68,7 @@ OPTION(DISABLE_FIFO "Disable FIFO plugin") OPTION(DISABLE_IRC "Disable IRC plugin") OPTION(DISABLE_LOGGER "Disable Logger plugin") OPTION(ENABLE_RELAY "Enable Relay plugin") +OPTION(DISABLE_RMODIFIER "Disable Rmodifier plugin") OPTION(DISABLE_SCRIPTS "Disable script plugins") OPTION(DISABLE_PERL "Disable Perl scripting language") OPTION(DISABLE_PYTHON "Disable Python scripting language") diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index e4f0a84..1655905 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -66,6 +66,10 @@ IF(ENABLE_RELAY) ADD_SUBDIRECTORY( relay ) ENDIF(ENABLE_RELAY) +IF(NOT DISABLE_RMODIFIER) + ADD_SUBDIRECTORY( rmodifier ) +ENDIF(NOT DISABLE_RMODIFIER) + IF(NOT DISABLE_SCRIPTS OR NOT DISABLE_PERL OR NOT DISABLE_PYTHON OR NOT DISABLE_RUBY OR NOT DISABLE_LUA OR NOT DISABLE_TCL) ADD_SUBDIRECTORY( scripts ) ENDIF(NOT DISABLE_SCRIPTS OR NOT DISABLE_PERL OR NOT DISABLE_PYTHON OR NOT DISABLE_RUBY OR NOT DISABLE_LUA OR NOT DISABLE_TCL) diff --git a/src/plugins/rmodifier/CMakeLists.txt b/src/plugins/rmodifier/CMakeLists.txt new file mode 100644 index 0000000..fcbc516 --- /dev/null +++ b/src/plugins/rmodifier/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright (c) 2003-2010 by FlashCode +# +# 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 . +# + +ADD_LIBRARY(rmodifier MODULE +rmodifier.c rmodifier.h +rmodifier-config.c rmodifier-config.h +rmodifier-info.c rmodifier-info.h) +SET_TARGET_PROPERTIES(rmodifier PROPERTIES PREFIX "") + +TARGET_LINK_LIBRARIES(rmodifier) + +INSTALL(TARGETS rmodifier LIBRARY DESTINATION ${LIBDIR}/plugins) diff --git a/src/plugins/rmodifier/rmodifier-config.c b/src/plugins/rmodifier/rmodifier-config.c new file mode 100644 index 0000000..f5e5773 --- /dev/null +++ b/src/plugins/rmodifier/rmodifier-config.c @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2003-2010 by FlashCode + * 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 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 . + */ + +/* + * rmodifier-config.c: rmodifier configuration options (file rmodifier.conf) + */ + + +#include +#include +#include +#include + +#include "../weechat-plugin.h" +#include "rmodifier.h" + + +struct t_config_file *rmodifier_config_file = NULL; +struct t_config_section *rmodifier_config_section_modifier = NULL; + +struct t_config_option *rmodifier_config_look_hide_char; + +char *rmodifier_default_list[][4] = +{ + { "set_pass", "history_add", + "^(/set +\\S*password\\S* +)(.*)", "1,2*" + }, + { "nickserv", "history_add", + "^(/(msg|quote) +nickserv +identify +)(.*)", "1,3*" + }, + { "oper", "history_add,input_text_display", + "^(/oper +\\S+ +)(.*)", "1,2*" + }, + { NULL, NULL, NULL, NULL }, +}; + + +/* + * rmodifier_config_reload: reload rmodifier configuration file + */ + +int +rmodifier_config_reload (void *data, struct t_config_file *config_file) +{ + /* make C compiler happy */ + (void) data; + + rmodifier_free_all (); + + return weechat_config_reload (config_file); +} + +/* + * rmodifier_config_modifier_change_cb: callback called when a rmodifier is + * modified in section "modifier" + */ + +void +rmodifier_config_modifier_change_cb (void *data, struct t_config_option *option) +{ + /* make C compiler happy */ + (void) data; + + rmodifier_new_with_string (weechat_config_option_get_pointer (option, "name"), + weechat_config_option_get_pointer (option, "value")); +} + +/* + * rmodifier_config_modifier_delete_cb: callback called when rmodifier option + * is deleted in section "modifier" + */ + +void +rmodifier_config_modifier_delete_cb (void *data, struct t_config_option *option) +{ + struct t_rmodifier *ptr_rmodifier; + + /* make C compiler happy */ + (void) data; + + ptr_rmodifier = rmodifier_search (weechat_config_option_get_pointer (option, + "name")); + if (ptr_rmodifier) + rmodifier_free (ptr_rmodifier); +} + +/* + * rmodifier_config_modifier_write_default_cb: write default rmodifiers in + * configuration file in section + * "modifier" + */ + +int +rmodifier_config_modifier_write_default_cb (void *data, + struct t_config_file *config_file, + const char *section_name) +{ + int i; + + /* make C compiler happy */ + (void) data; + + if (!weechat_config_write_line (config_file, section_name, NULL)) + return WEECHAT_CONFIG_WRITE_ERROR; + + for (i = 0; rmodifier_default_list[i][0]; i++) + { + if (!weechat_config_write_line (config_file, + rmodifier_default_list[i][0], + "\"%s;%s;%s\"", + rmodifier_default_list[i][1], + rmodifier_default_list[i][2], + rmodifier_default_list[i][3])) + return WEECHAT_CONFIG_WRITE_ERROR; + } + + return WEECHAT_CONFIG_WRITE_OK; +} + +/* + * rmodifier_config_modifier_new_option: create new option in section "modifier" + */ + +void +rmodifier_config_modifier_new_option (const char *name, const char *modifiers, + const char *regex, const char *groups) +{ + int length; + char *value; + + length = strlen (modifiers) + 1 + strlen (regex) + 1 + + ((groups) ? strlen (groups) : 0) + 1; + value = malloc (length); + if (value) + { + snprintf (value, length, "%s;%s;%s", + modifiers, regex, + (groups) ? groups : ""); + weechat_config_new_option (rmodifier_config_file, + rmodifier_config_section_modifier, + name, "string", NULL, + NULL, 0, 0, "", value, 0, + NULL, NULL, + &rmodifier_config_modifier_change_cb, NULL, + &rmodifier_config_modifier_delete_cb, NULL); + free (value); + } +} + +/* + * rmodifier_config_modifier_create_option_cb: callback to create option in + * "modifier" section + */ + +int +rmodifier_config_modifier_create_option_cb (void *data, + struct t_config_file *config_file, + struct t_config_section *section, + const char *option_name, + const char *value) +{ + struct t_rmodifier *ptr_rmodifier; + int rc; + + /* make C compiler happy */ + (void) data; + (void) config_file; + (void) section; + + rc = WEECHAT_CONFIG_OPTION_SET_ERROR; + + /* create rmodifier */ + ptr_rmodifier = rmodifier_search (option_name); + if (ptr_rmodifier) + rmodifier_free (ptr_rmodifier); + if (value && value[0]) + { + ptr_rmodifier = rmodifier_new_with_string (option_name, value); + if (ptr_rmodifier) + { + rc = WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; + /* create option */ + rmodifier_config_modifier_new_option (ptr_rmodifier->name, + ptr_rmodifier->modifiers, + ptr_rmodifier->str_regex, + ptr_rmodifier->groups); + } + else + rc = WEECHAT_CONFIG_OPTION_SET_ERROR; + } + else + rc = WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; + + if (rc == WEECHAT_CONFIG_OPTION_SET_ERROR) + { + weechat_printf (NULL, + _("%s%s: error creating rmodifier \"%s\" => \"%s\""), + weechat_prefix ("error"), RMODIFIER_PLUGIN_NAME, + option_name, value); + } + + return rc; +} + +/* + * rmodifier_config_init: init rmodifier configuration file + * return: 1 if ok, 0 if error + */ + +int +rmodifier_config_init () +{ + struct t_config_section *ptr_section; + + rmodifier_config_file = weechat_config_new (RMODIFIER_CONFIG_NAME, + &rmodifier_config_reload, NULL); + if (!rmodifier_config_file) + return 0; + + /* look */ + ptr_section = weechat_config_new_section (rmodifier_config_file, "look", + 0, 0, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL); + if (!ptr_section) + { + weechat_config_free (rmodifier_config_file); + return 0; + } + + rmodifier_config_look_hide_char = weechat_config_new_option ( + rmodifier_config_file, ptr_section, + "hide_char", "string", + N_("char used to hide part of a string"), + NULL, 0, 0, "*", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); + + /* modifier */ + ptr_section = weechat_config_new_section (rmodifier_config_file, "modifier", + 0, 0, + NULL, NULL, + NULL, NULL, + &rmodifier_config_modifier_write_default_cb, NULL, + &rmodifier_config_modifier_create_option_cb, NULL, + NULL, NULL); + if (!ptr_section) + { + weechat_config_free (rmodifier_config_file); + return 0; + } + rmodifier_config_section_modifier = ptr_section; + + return 1; +} + +/* + * rmodifier_config_read: read rmodifier configuration file + */ + +int +rmodifier_config_read () +{ + return weechat_config_read (rmodifier_config_file); +} + +/* + * rmodifier_config_write: write rmodifier configuration file + */ + +int +rmodifier_config_write () +{ + return weechat_config_write (rmodifier_config_file); +} diff --git a/src/plugins/rmodifier/rmodifier-config.h b/src/plugins/rmodifier/rmodifier-config.h new file mode 100644 index 0000000..8487ad1 --- /dev/null +++ b/src/plugins/rmodifier/rmodifier-config.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2003-2010 by FlashCode + * 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 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 . + */ + + +#ifndef __WEECHAT_RMODIFIER_CONFIG_H +#define __WEECHAT_RMODIFIER_CONFIG_H 1 + +extern struct t_config_file *rmodifier_config_file; +extern struct t_config_section *rmodifier_config_section_modifier; + +struct t_config_option *rmodifier_config_look_hide_char; + +extern void rmodifier_config_modifier_new_option (const char *name, + const char *modifiers, + const char *regex, + const char *groups); +extern int rmodifier_config_init (); +extern int rmodifier_config_read (); +extern int rmodifier_config_write (); + +#endif /* rmodifier-config.h */ diff --git a/src/plugins/rmodifier/rmodifier-info.c b/src/plugins/rmodifier/rmodifier-info.c new file mode 100644 index 0000000..780dc38 --- /dev/null +++ b/src/plugins/rmodifier/rmodifier-info.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2003-2010 by FlashCode + * 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 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 . + */ + +/* + * rmodifier-info.c: info and infolist hooks for rmodifier plugin + */ + + +#include + +#include "../weechat-plugin.h" +#include "rmodifier.h" + + +/* + * rmodifier_info_get_infolist_cb: callback called when rmodifier infolist is + * asked + */ + +struct t_infolist * +rmodifier_info_get_infolist_cb (void *data, const char *infolist_name, + void *pointer, const char *arguments) +{ + struct t_infolist *ptr_infolist; + struct t_rmodifier *ptr_rmodifier; + + /* make C compiler happy */ + (void) data; + (void) arguments; + + if (!infolist_name || !infolist_name[0]) + return NULL; + + if (weechat_strcasecmp (infolist_name, RMODIFIER_PLUGIN_NAME) == 0) + { + if (pointer && !rmodifier_valid (pointer)) + return NULL; + + ptr_infolist = weechat_infolist_new (); + if (ptr_infolist) + { + if (pointer) + { + /* build list with only one rmodifier */ + if (!rmodifier_add_to_infolist (ptr_infolist, pointer)) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + return ptr_infolist; + } + else + { + /* build list with all rmodifiers matching arguments */ + for (ptr_rmodifier = rmodifier_list; ptr_rmodifier; + ptr_rmodifier = ptr_rmodifier->next_rmodifier) + { + if (!arguments || !arguments[0] + || weechat_string_match (ptr_rmodifier->name, arguments, 0)) + { + if (!rmodifier_add_to_infolist (ptr_infolist, ptr_rmodifier)) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + } + } + return ptr_infolist; + } + } + } + + return NULL; +} + +/* + * rmodifier_info_init: initialize info and infolist hooks for rmodifier plugin + */ + +void +rmodifier_info_init () +{ + /* rmodifier infolist hooks */ + weechat_hook_infolist ("rmodifier", N_("list of rmodifiers"), + N_("rmodifier pointer (optional)"), + N_("rmodifier name (can start or end with \"*\" as joker) (optional)"), + &rmodifier_info_get_infolist_cb, NULL); +} diff --git a/src/plugins/rmodifier/rmodifier-info.h b/src/plugins/rmodifier/rmodifier-info.h new file mode 100644 index 0000000..dde71e9 --- /dev/null +++ b/src/plugins/rmodifier/rmodifier-info.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2003-2010 by FlashCode + * 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 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 . + */ + + +#ifndef __WEECHAT_RMODIFIER_INFO_H +#define __WEECHAT_RMODIFIER_INFO_H 1 + +extern void rmodifier_info_init (); + +#endif /* rmodifier-info.h */ diff --git a/src/plugins/rmodifier/rmodifier.c b/src/plugins/rmodifier/rmodifier.c new file mode 100644 index 0000000..0fd23c7 --- /dev/null +++ b/src/plugins/rmodifier/rmodifier.c @@ -0,0 +1,714 @@ +/* + * Copyright (c) 2003-2010 by FlashCode + * 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 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 . + */ + +/* + * rmodifier.c: hook and update modifier strings using regular expressions + * (useful for hiding passwords in input or command history) + */ + + +#include +#include +#include + +#include "../weechat-plugin.h" +#include "rmodifier.h" +#include "rmodifier-config.h" +#include "rmodifier-info.h" + + +WEECHAT_PLUGIN_NAME(RMODIFIER_PLUGIN_NAME); +WEECHAT_PLUGIN_DESCRIPTION("Rmodifier plugin for WeeChat"); +WEECHAT_PLUGIN_AUTHOR("FlashCode "); +WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); +WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); + +struct t_weechat_plugin *weechat_rmodifier_plugin = NULL; + +struct t_rmodifier *rmodifier_list = NULL; +struct t_rmodifier *last_rmodifier = NULL; +struct t_weelist *rmodifier_hook_list = NULL; + + +/* + * rmodifier_valid: check if a rmodifier pointer exists + * return 1 if rmodifier exists + * 0 if rmodifier is not found + */ + +int +rmodifier_valid (struct t_rmodifier *rmodifier) +{ + struct t_rmodifier *ptr_rmodifier; + + if (!rmodifier) + return 0; + + for (ptr_rmodifier = rmodifier_list; ptr_rmodifier; + ptr_rmodifier = ptr_rmodifier->next_rmodifier) + { + if (ptr_rmodifier == rmodifier) + return 1; + } + + /* rmodifier not found */ + return 0; +} + +/* + * rmodifier_search: search a rmodifier + */ + +struct t_rmodifier * +rmodifier_search (const char *name) +{ + struct t_rmodifier *ptr_rmodifier; + + for (ptr_rmodifier = rmodifier_list; ptr_rmodifier; + ptr_rmodifier = ptr_rmodifier->next_rmodifier) + { + if (strcmp (name, ptr_rmodifier->name) == 0) + return ptr_rmodifier; + } + return NULL; +} + +/* + * rmodifier_count: return number of rmodifiers + */ + +int +rmodifier_count () +{ + struct t_rmodifier *ptr_rmodifier; + int count; + + count = 0; + for (ptr_rmodifier = rmodifier_list; ptr_rmodifier; + ptr_rmodifier = ptr_rmodifier->next_rmodifier) + { + count++; + } + return count; +} + +/* + * rmodifier_hide_string: hide a string (using char defined in option + * "rmodifier.look.hide_char") + */ + +char * +rmodifier_hide_string (const char *string) +{ + int length, i; + char *result; + + if (!string || !string[0]) + return NULL; + + length = weechat_utf8_strlen (string); + result = malloc ((length * strlen (weechat_config_string (rmodifier_config_look_hide_char))) + 1); + if (!result) + return NULL; + + result[0] = '\0'; + for (i = 0; i < length; i++) + { + strcat (result, weechat_config_string (rmodifier_config_look_hide_char)); + } + + return result; +} + +/* + * rmodifier_replace_groups: replace groups in a string, using regex_match + * found by call to regexec() + */ + +char * +rmodifier_replace_groups (const char *string, regmatch_t regex_match[], + const char *groups) +{ + char *result, *str_group, *string_to_add; + const char *ptr_groups; + int length, num_group; + + length = 1; + result = malloc (length); + if (!result) + return NULL; + + result[0] = '\0'; + ptr_groups = groups; + while (ptr_groups && ptr_groups[0]) + { + if ((ptr_groups[0] >= '1') && (ptr_groups[0] <= '9')) + { + num_group = ptr_groups[0] - '0'; + if (regex_match[num_group].rm_so >= 0) + { + str_group = weechat_strndup (string + regex_match[num_group].rm_so, + regex_match[num_group].rm_eo -regex_match[num_group].rm_so); + //weechat_printf (NULL, "group %d == '%s'", num_group, str_group); + if (str_group) + { + string_to_add = NULL; + if (ptr_groups[1] == '*') + string_to_add = rmodifier_hide_string (str_group); + else + string_to_add = strdup (str_group); + + if (string_to_add) + { + length += strlen (string_to_add); + result = realloc (result, length); + if (!result) + return NULL; + strcat (result, string_to_add); + free (string_to_add); + } + free (str_group); + } + } + } + ptr_groups = weechat_utf8_next_char (ptr_groups); + } + + return result; +} + +/* + * rmodifier_modifier_cb: callback for a modifier + */ + +char * +rmodifier_modifier_cb (void *data, const char *modifier, + const char *modifier_data, const char *string) +{ + struct t_rmodifier *rmodifier; + regmatch_t regex_match[9]; + int i; + + /* make C compiler happy */ + (void) modifier; + (void) modifier_data; + + rmodifier = (struct t_rmodifier *)data; + + /* reset matching groups */ + for (i = 0; i < 9; i++) + { + regex_match[i].rm_so = -1; + } + + /* execute regex and return modified string if matching */ + //weechat_printf (NULL, "test with regex: %s", rmodifier->str_regex); + if (regexec (rmodifier->regex, string, 9, regex_match, 0) == 0) + { + return rmodifier_replace_groups (string, regex_match, + rmodifier->groups); + } + + /* regex not matching */ + return NULL; +} + +/* + * rmodifier_create_regex: create regex for a rmodifier + */ + +void +rmodifier_create_regex (struct t_rmodifier *rmodifier) +{ + if (rmodifier->regex) + { + regfree (rmodifier->regex); + free (rmodifier->regex); + } + + rmodifier->regex = malloc (sizeof (*rmodifier->regex)); + if (!rmodifier->regex) + return; + + if (regcomp (rmodifier->regex, rmodifier->str_regex, + REG_EXTENDED | REG_ICASE) != 0) + { + weechat_printf (NULL, + _("%s%s: error compiling regular expression \"%s\""), + weechat_prefix ("error"), RMODIFIER_PLUGIN_NAME, + rmodifier->str_regex); + free (rmodifier->regex); + return; + } +} + +/* + * rmodifier_hook_modifiers: hook modifiers for a rmodifier + */ + +void +rmodifier_hook_modifiers (struct t_rmodifier *rmodifier) +{ + char **argv; + int argc, i; + + argv = weechat_string_split (rmodifier->modifiers, ",", 0, 0, &argc); + + if (argv) + { + rmodifier->hooks = malloc (sizeof (*rmodifier->hooks) * argc); + if (rmodifier->hooks) + { + for (i = 0; i < argc; i++) + { + rmodifier->hooks[i] = weechat_hook_modifier (argv[i], + &rmodifier_modifier_cb, + rmodifier); + } + rmodifier->hooks_count = argc; + } + weechat_string_free_split (argv); + } +} + +/* + * rmodifier_new: create new rmodifier and add it to rmodifier list + */ + +struct t_rmodifier * +rmodifier_new (const char *name, const char *modifiers, const char *str_regex, + const char *groups) +{ + struct t_rmodifier *new_rmodifier, *ptr_rmodifier; + + if (!name || !name[0] || !modifiers || !modifiers[0] + || !str_regex || !str_regex[0]) + return NULL; + + ptr_rmodifier = rmodifier_search (name); + if (ptr_rmodifier) + rmodifier_free (ptr_rmodifier); + + new_rmodifier = malloc (sizeof (*new_rmodifier)); + if (new_rmodifier) + { + new_rmodifier->name = strdup (name); + new_rmodifier->hooks = NULL; + new_rmodifier->modifiers = strdup (modifiers); + new_rmodifier->str_regex = strdup (str_regex); + new_rmodifier->regex = NULL; + new_rmodifier->groups = strdup ((groups) ? groups : ""); + + /* create regex and modifiers */ + rmodifier_create_regex (new_rmodifier); + rmodifier_hook_modifiers (new_rmodifier); + + if (rmodifier_list) + { + /* add rmodifier to end of list */ + new_rmodifier->prev_rmodifier = last_rmodifier; + new_rmodifier->next_rmodifier = NULL; + last_rmodifier->next_rmodifier = new_rmodifier; + last_rmodifier = new_rmodifier; + } + else + { + new_rmodifier->prev_rmodifier = NULL; + new_rmodifier->next_rmodifier = NULL; + rmodifier_list = new_rmodifier; + last_rmodifier = new_rmodifier; + } + } + + return new_rmodifier; +} + +/* + * rmodifier_new_with_string: create a rmodifier with a single string, which + * contains: "modifiers;regex;groups" + */ + +struct t_rmodifier * +rmodifier_new_with_string (const char *name, const char *value) +{ + struct t_rmodifier *new_rmodifier; + char *pos1, *pos2, *modifiers, *str_regex; + + new_rmodifier = NULL; + + pos1 = strchr (value, ';'); + pos2 = rindex (value, ';'); + if (pos1 && pos2 && (pos2 > pos1)) + { + modifiers = weechat_strndup (value, pos1 - value); + str_regex = weechat_strndup (pos1 + 1, pos2 - (pos1 + 1)); + if (modifiers && str_regex) + { + new_rmodifier = rmodifier_new (name, + modifiers, str_regex, pos2 + 1); + } + if (modifiers) + free (modifiers); + if (str_regex) + free (str_regex); + } + + return new_rmodifier; +} + +/* + * rmodifier_free: free a rmodifier and remove it from list + */ + +void +rmodifier_free (struct t_rmodifier *rmodifier) +{ + struct t_rmodifier *new_rmodifier_list; + int i; + + /* remove rmodifier from list */ + if (last_rmodifier == rmodifier) + last_rmodifier = rmodifier->prev_rmodifier; + if (rmodifier->prev_rmodifier) + { + (rmodifier->prev_rmodifier)->next_rmodifier = rmodifier->next_rmodifier; + new_rmodifier_list = rmodifier_list; + } + else + new_rmodifier_list = rmodifier->next_rmodifier; + if (rmodifier->next_rmodifier) + (rmodifier->next_rmodifier)->prev_rmodifier = rmodifier->prev_rmodifier; + + /* free data */ + if (rmodifier->name) + free (rmodifier->name); + if (rmodifier->modifiers) + free (rmodifier->modifiers); + if (rmodifier->hooks) + { + for (i = 0; i < rmodifier->hooks_count; i++) + { + weechat_unhook (rmodifier->hooks[i]); + } + free (rmodifier->hooks); + } + if (rmodifier->str_regex) + free (rmodifier->str_regex); + if (rmodifier->regex) + { + regfree (rmodifier->regex); + free (rmodifier->regex); + } + if (rmodifier->groups) + free (rmodifier->groups); + free (rmodifier); + + rmodifier_list = new_rmodifier_list; +} + +/* + * rmodifier_free_all: free all rmodifier + */ + +void +rmodifier_free_all () +{ + while (rmodifier_list) + { + rmodifier_free (rmodifier_list); + } +} + +/* + * rmodifier_command_cb: manage rmodifiers + */ + +int +rmodifier_command_cb (void *data, struct t_gui_buffer *buffer, int argc, + char **argv, char **argv_eol) +{ + struct t_rmodifier *ptr_rmodifier; + struct t_config_option *ptr_option; + int i, count; + + /* make C compiler happy */ + (void) data; + (void) buffer; + + if ((argc == 1) + || ((argc == 2) && (weechat_strcasecmp (argv[1], "list") == 0))) + { + /* list all rmodifiers */ + if (rmodifier_list) + { + weechat_printf (NULL, ""); + weechat_printf (NULL, _("List of rmodifiers:")); + for (ptr_rmodifier = rmodifier_list; ptr_rmodifier; + ptr_rmodifier = ptr_rmodifier->next_rmodifier) + { + weechat_printf (NULL, + " %s[%s%s%s]%s %s%s: %s%s %s/%s %s", + weechat_color ("chat_delimiters"), + weechat_color ("chat"), + ptr_rmodifier->name, + weechat_color ("chat_delimiters"), + weechat_color ("chat"), + ptr_rmodifier->modifiers, + weechat_color ("chat_delimiters"), + weechat_color ("chat_host"), + ptr_rmodifier->str_regex, + weechat_color ("chat_delimiters"), + weechat_color ("chat"), + ptr_rmodifier->groups); + } + } + else + weechat_printf (NULL, _("No rmodifier defined")); + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[1], "add") == 0) + { + /* add a rmodifier */ + if (argc < 6) + { + weechat_printf (NULL, + _("%sError: missing arguments for \"%s\" " + "command"), + weechat_prefix ("error"), "rmodifier"); + return WEECHAT_RC_ERROR; + } + ptr_rmodifier = rmodifier_new (argv[2], argv[3], argv_eol[5], argv[4]); + if (!ptr_rmodifier) + { + weechat_printf (NULL, + _("%s%s: error creating rmodifier \"%s\""), + weechat_prefix ("error"), RMODIFIER_PLUGIN_NAME, + argv[2]); + return WEECHAT_RC_ERROR; + } + /* create config option */ + ptr_option = weechat_config_search_option (rmodifier_config_file, + rmodifier_config_section_modifier, + argv[2]); + if (ptr_option) + weechat_config_option_free (ptr_option); + rmodifier_config_modifier_new_option (ptr_rmodifier->name, + ptr_rmodifier->modifiers, + ptr_rmodifier->str_regex, + ptr_rmodifier->groups); + + /* display message */ + weechat_printf (NULL, _("Rmodifier \"%s\" created"), + ptr_rmodifier->name); + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[1], "del") == 0) + { + /* add a rmodifier */ + if (argc < 3) + { + weechat_printf (NULL, + _("%sError: missing arguments for \"%s\" " + "command"), + weechat_prefix ("error"), "rmodifier"); + return WEECHAT_RC_ERROR; + } + if (weechat_strcasecmp (argv[2], "-all") == 0) + { + count = rmodifier_count(); + rmodifier_free_all (); + weechat_config_section_free_options (rmodifier_config_section_modifier); + if (count > 0) + weechat_printf (NULL, _("%d rmodifiers removed"), count); + } + else + { + for (i = 2; i < argc; i++) + { + ptr_rmodifier = rmodifier_search (argv[i]); + if (ptr_rmodifier) + { + ptr_option = weechat_config_search_option (rmodifier_config_file, + rmodifier_config_section_modifier, + argv[i]); + if (ptr_option) + weechat_config_option_free (ptr_option); + rmodifier_free (ptr_rmodifier); + weechat_printf (NULL, _("Rmodifier \"%s\" removed"), + argv[i]); + } + else + { + weechat_printf (NULL, _("%sRmodifier \"%s\" not found"), + weechat_prefix ("error"), argv[i]); + } + } + } + return WEECHAT_RC_OK; + } + + return WEECHAT_RC_OK; +} + +/* + * rmodifier_completion_cb: callback for completion with list of rmodifiers + */ + +int +rmodifier_completion_cb (void *data, const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion) +{ + struct t_rmodifier *ptr_rmodifier; + + /* make C compiler happy */ + (void) data; + (void) completion_item; + (void) buffer; + + for (ptr_rmodifier = rmodifier_list; ptr_rmodifier; + ptr_rmodifier = ptr_rmodifier->next_rmodifier) + { + weechat_hook_completion_list_add (completion, ptr_rmodifier->name, + 0, WEECHAT_LIST_POS_SORT); + } + + return WEECHAT_RC_OK; +} + +/* + * rmodifier_add_to_infolist: add a rmodifier in an infolist + * return 1 if ok, 0 if error + */ + +int +rmodifier_add_to_infolist (struct t_infolist *infolist, + struct t_rmodifier *rmodifier) +{ + struct t_infolist_item *ptr_item; + char option_name[64]; + int i; + + if (!infolist || !rmodifier) + return 0; + + ptr_item = weechat_infolist_new_item (infolist); + if (!ptr_item) + return 0; + + if (!weechat_infolist_new_var_string (ptr_item, "name", rmodifier->name)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "modifiers", rmodifier->modifiers)) + return 0; + for (i = 0; i < rmodifier->hooks_count; i++) + { + snprintf (option_name, sizeof (option_name), "hook_%05d", i + 1); + if (!weechat_infolist_new_var_pointer (ptr_item, option_name, + rmodifier->hooks[i])) + return 0; + } + if (!weechat_infolist_new_var_integer (ptr_item, "hooks_count", rmodifier->hooks_count)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "str_regex", rmodifier->str_regex)) + return 0; + if (!weechat_infolist_new_var_pointer (ptr_item, "regex", rmodifier->regex)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "groups", rmodifier->groups)) + return 0; + + return 1; +} + +/* + * weechat_plugin_init: initialize rmodifier plugin + */ + +int +weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) +{ + /* make C compiler happy */ + (void) argc; + (void) argv; + + weechat_plugin = plugin; + + rmodifier_hook_list = weechat_list_new (); + + if (!rmodifier_config_init ()) + { + weechat_printf (NULL, + _("%s%s: error creating configuration file"), + weechat_prefix("error"), RMODIFIER_PLUGIN_NAME); + return WEECHAT_RC_ERROR; + } + rmodifier_config_read (); + + weechat_hook_command ("rmodifier", + N_("hook and update modifier strings using regular " + "expressions"), + N_("[list] | [add name modifiers groups regex] | " + "[del name|-all [name...]]"), + N_(" list: list all rmodifiers\n" + " add: add a rmodifier\n" + " name: name of rmodifier\n" + "modifiers: comma separated list of modifiers\n" + " groups: action on groups found: comma separated " + "list of groups (from 1 to 9) with optional \"*\" " + "after number to hide group\n" + " regex: regular expression\n" + " del: delete a rmodifier\n" + " -all: delete all rmodifiers\n\n" + "Examples:\n" + " hide everything typed after a command /password:\n" + " /rmodifier add password input_text_display 1,2* ^(/password +)(.*)\n" + " delete rmodifier \"password\":\n" + " /rmodifier del password\n" + " delete all rmodifiers:\n" + " /rmodifier del -all"), + "list" + " || add %(rmodifier)" + " || del %(rmodifier)|-all %(rmodifier)|%*", + &rmodifier_command_cb, NULL); + + weechat_hook_completion ("rmodifier", N_("list of rmodifiers"), + &rmodifier_completion_cb, NULL); + + rmodifier_info_init (); + + return WEECHAT_RC_OK; +} + +/* + * weechat_plugin_end: end rmodifier plugin + */ + +int +weechat_plugin_end (struct t_weechat_plugin *plugin) +{ + /* make C compiler happy */ + (void) plugin; + + rmodifier_config_write (); + rmodifier_free_all (); + weechat_list_free (rmodifier_hook_list); + weechat_config_free (rmodifier_config_file); + + return WEECHAT_RC_OK; +} diff --git a/src/plugins/rmodifier/rmodifier.h b/src/plugins/rmodifier/rmodifier.h new file mode 100644 index 0000000..d0fdea1 --- /dev/null +++ b/src/plugins/rmodifier/rmodifier.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2003-2010 by FlashCode + * 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 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 . + */ + + +#ifndef __WEECHAT_RMODIFIER_H +#define __WEECHAT_RMODIFIER_H 1 + +#include + +#define weechat_plugin weechat_rmodifier_plugin +#define RMODIFIER_PLUGIN_NAME "rmodifier" + +#define RMODIFIER_CONFIG_NAME "rmodifier" + +struct t_rmodifier +{ + char *name; /* name of rmodifier */ + char *modifiers; /* modifiers */ + struct t_hook **hooks; /* hooks for modifiers */ + int hooks_count; /* number of hooks */ + char *str_regex; /* string with regex */ + regex_t *regex; /* regex */ + char *groups; /* actions on groups in regex */ + /* (keep, delete, hide) */ + struct t_rmodifier *prev_rmodifier; /* link to previous rmodifier */ + struct t_rmodifier *next_rmodifier; /* link to next rmodifier */ +}; + +extern struct t_rmodifier *rmodifier_list; + +extern struct t_weechat_plugin *weechat_rmodifier_plugin; + +extern int rmodifier_valid (struct t_rmodifier *rmodifier); +extern struct t_rmodifier *rmodifier_search (const char *name); +extern struct t_rmodifier *rmodifier_new_with_string (const char *name, + const char *value); +extern void rmodifier_free (struct t_rmodifier *rmodifier); +extern void rmodifier_free_all (); +extern int rmodifier_add_to_infolist (struct t_infolist *infolist, + struct t_rmodifier *rmodifier); + +#endif /* rmodifier.h */